Skip to content

Commit b4cb1fa

Browse files
author
Watson
committed
Add native PNG backend and fallback-first example rendering path
1 parent 3d15f21 commit b4cb1fa

File tree

10 files changed

+499
-36
lines changed

10 files changed

+499
-36
lines changed

CMakeLists.txt

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ add_library(gnuplotpp
2323
src/gnuplot_backend.cpp
2424
src/presets.cpp
2525
src/svg_backend.cpp
26+
src/png_backend.cpp
2627
)
2728

2829
add_library(gnuplotpp::gnuplotpp ALIAS gnuplotpp)
@@ -79,4 +80,8 @@ if(BUILD_TESTING)
7980
add_executable(gnuplotpp_svg_backend_test tests/svg_backend_test.cpp)
8081
target_link_libraries(gnuplotpp_svg_backend_test PRIVATE gnuplotpp::gnuplotpp)
8182
add_test(NAME gnuplotpp_svg_backend_test COMMAND gnuplotpp_svg_backend_test)
83+
84+
add_executable(gnuplotpp_png_backend_test tests/png_backend_test.cpp)
85+
target_link_libraries(gnuplotpp_png_backend_test PRIVATE gnuplotpp::gnuplotpp)
86+
add_test(NAME gnuplotpp_png_backend_test COMMAND gnuplotpp_png_backend_test)
8287
endif()

README.md

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,10 +18,12 @@ flowchart LR
1818
B --> C[IPlotBackend]
1919
C --> D[GnuplotBackend]
2020
C --> E[SvgBackend]
21+
C --> J[PngBackend]
2122
D --> F[tmp/*.dat]
2223
D --> G[tmp/figure.gp]
2324
D --> H[figure.pdf|svg|eps|png]
2425
E --> I[figure.svg]
26+
J --> K[figure.png]
2527
```
2628

2729
## Render Flow
@@ -74,7 +76,8 @@ If network/package resolution fails, configuration now degrades with warnings an
7476
You run only the C++ executable.
7577

7678
- If `gnuplot` exists, examples render publication outputs (`pdf/svg/png`) via `GnuplotBackend`.
77-
- If `gnuplot` is missing, examples automatically fall back to native `SvgBackend` and still generate `figure.svg`.
79+
- If `gnuplot` is missing, examples automatically fall back to native `PngBackend` and generate `figure.png`.
80+
- If PNG fallback fails, examples try native `SvgBackend` as a secondary fallback.
7881

7982
## Example Plots
8083

@@ -85,4 +88,4 @@ You run only the C++ executable.
8588

8689
Generated outputs include at least:
8790

88-
- `out/<name>/figures/figure.svg`
91+
- `out/<name>/figures/figure.png`

examples/layout_2x2_example.cpp

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
#include "gnuplotpp/gnuplot_backend.hpp"
2+
#include "gnuplotpp/png_backend.hpp"
23
#include "gnuplotpp/plot.hpp"
34
#include "gnuplotpp/presets.hpp"
45
#include "gnuplotpp/svg_backend.hpp"
@@ -72,16 +73,24 @@ int main(int argc, char** argv) {
7273
fig.axes(2).add_series(SeriesSpec{.type = SeriesType::Line, .label = "SRIF"}, t, ez);
7374
fig.axes(3).add_series(SeriesSpec{.type = SeriesType::Line, .label = "SRIF"}, t, ev);
7475

76+
RenderResult result;
7577
if (gnuplot_available()) {
7678
fig.set_backend(make_gnuplot_backend());
79+
result = fig.save(out_dir / "figures");
7780
} else {
78-
fig.set_backend(make_svg_backend());
81+
fig.set_backend(make_png_backend());
82+
result = fig.save(out_dir / "figures");
83+
if (!result.ok) {
84+
fig.set_backend(make_svg_backend());
85+
result = fig.save(out_dir / "figures");
86+
}
7987
}
8088

81-
const auto result = fig.save(out_dir / "figures");
8289
if (!result.ok) {
8390
std::cerr << "plot render incomplete: " << result.message << "\n";
84-
std::cerr << "script: " << result.script_path << "\n";
91+
if (!result.script_path.empty()) {
92+
std::cerr << "script: " << result.script_path << "\n";
93+
}
8594
return 1;
8695
}
8796

examples/two_window_example.cpp

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
#include "gnuplotpp/gnuplot_backend.hpp"
2+
#include "gnuplotpp/png_backend.hpp"
23
#include "gnuplotpp/plot.hpp"
34
#include "gnuplotpp/presets.hpp"
45
#include "gnuplotpp/svg_backend.hpp"
@@ -64,15 +65,24 @@ int main(int argc, char** argv) {
6465
fig.axes(0, 0).add_series(SeriesSpec{.type = SeriesType::Line, .label = "SRIF"}, t, ep);
6566
fig.axes(0, 1).add_series(SeriesSpec{.type = SeriesType::Line, .label = "SRIF"}, t, ev);
6667

68+
RenderResult result;
6769
if (gnuplot_available()) {
6870
fig.set_backend(make_gnuplot_backend());
69-
} else { fig.set_backend(make_svg_backend());
71+
result = fig.save(out_dir / "figures");
72+
} else {
73+
fig.set_backend(make_png_backend());
74+
result = fig.save(out_dir / "figures");
75+
if (!result.ok) {
76+
fig.set_backend(make_svg_backend());
77+
result = fig.save(out_dir / "figures");
78+
}
7079
}
7180

72-
const auto result = fig.save(out_dir / "figures");
7381
if (!result.ok) {
7482
std::cerr << "plot render incomplete: " << result.message << "\n";
75-
std::cerr << "script: " << result.script_path << "\n";
83+
if (!result.script_path.empty()) {
84+
std::cerr << "script: " << result.script_path << "\n";
85+
}
7686
return 1;
7787
}
7888

include/gnuplotpp/png_backend.hpp

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
#pragma once
2+
3+
#include "gnuplotpp/plot.hpp"
4+
5+
#include <memory>
6+
7+
namespace gnuplotpp {
8+
9+
/**
10+
* @brief Native C++ PNG renderer backend.
11+
*/
12+
class PngBackend final : public IPlotBackend {
13+
public:
14+
/**
15+
* @brief Render figure content directly to PNG output.
16+
* @param fig Figure to render.
17+
* @param out_dir Output directory.
18+
* @return Render status and generated paths.
19+
*/
20+
RenderResult render(const Figure& fig,
21+
const std::filesystem::path& out_dir) override;
22+
};
23+
24+
/** @brief Factory helper for native PNG backend. */
25+
std::shared_ptr<IPlotBackend> make_png_backend();
26+
27+
} // namespace gnuplotpp

include/gnuplotpp/svg_backend.hpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
namespace gnuplotpp {
88

99
/**
10-
* @brief Native C++ SVG renderer backend (no external plotting command).
10+
* @brief Native C++ SVG renderer backend.
1111
*/
1212
class SvgBackend final : public IPlotBackend {
1313
public:

0 commit comments

Comments
 (0)