From c090eb518394345dd6a8db9dea583263686c0083 Mon Sep 17 00:00:00 2001 From: Greger Stolt Nilsen Date: Sun, 9 Jun 2024 14:51:42 +0200 Subject: [PATCH] Add SVG and PDF output. --- .vscode/settings.json | 7 ++++++- include/pyro/graphics.h | 15 ++++++++++++--- include/pyro/graphics_cairo.h | 4 +++- include/pyro/pyro.h | 4 ++-- src/graphics.cpp | 18 +++++++++++++----- src/graphics_cairo.cpp | 25 ++++++++++++++++++++----- src/image.cpp | 2 +- tests/test-graphics.cpp | 22 ++++++++++++++++++++++ 8 files changed, 79 insertions(+), 18 deletions(-) diff --git a/.vscode/settings.json b/.vscode/settings.json index 97f92e3..f094999 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -117,7 +117,12 @@ "variant": "cpp", "vector": "cpp", "nonlinearoptimization": "cpp", - "ios": "cpp" + "ios": "cpp", + "charconv": "cpp", + "numbers": "cpp", + "__locale": "cpp", + "__verbose_abort": "cpp", + "execution": "cpp" }, "mesonbuild.buildFolder": "build", "terminal.integrated.env.linux": { diff --git a/include/pyro/graphics.h b/include/pyro/graphics.h index 916ffe9..0e2a5c9 100644 --- a/include/pyro/graphics.h +++ b/include/pyro/graphics.h @@ -8,16 +8,22 @@ #include "font.h" #include "transformer.h" +#include + namespace Pyro { enum GraphicsMode { - CAIRO + CAIRO, + PDF, + SVG, }; class Graphics : public Image { protected: + GraphicsMode mode; + std::filesystem::path filename{""}; bool stroke_enable{true}; bool fill_enable{true}; @@ -35,7 +41,7 @@ namespace Pyro Transformer2D transformer; public: - Graphics(unsigned int width, unsigned int height, unsigned int channels, unsigned int dpi, Unit unit = Unit::PX); + Graphics(unsigned int width, unsigned int height, std::filesystem::path filename = ""); virtual ~Graphics() override; virtual void init() override; @@ -194,7 +200,10 @@ namespace Pyro * @param width The width of the canvas * @param height The height of the canvas */ - Graphics *creategraphics(unsigned int width, unsigned int height, GraphicsMode mode = GraphicsMode::CAIRO); + Graphics *creategraphics(unsigned int width, + unsigned int height, + GraphicsMode mode = GraphicsMode::CAIRO, + std::filesystem::path filename = ""); }; diff --git a/include/pyro/graphics_cairo.h b/include/pyro/graphics_cairo.h index daa3b20..4a2e765 100644 --- a/include/pyro/graphics_cairo.h +++ b/include/pyro/graphics_cairo.h @@ -17,7 +17,9 @@ namespace Pyro cairo_font_face_t *font{nullptr}; public: - GraphicsCairo(unsigned int width, unsigned int height, unsigned int channels, unsigned int dpi, Unit unit); + GraphicsCairo(unsigned int width, unsigned int height, + GraphicsMode mode = GraphicsMode::CAIRO, + std::filesystem::path filename = ""); ~GraphicsCairo() override; void init() override; diff --git a/include/pyro/pyro.h b/include/pyro/pyro.h index 3b620b1..fdd5c66 100644 --- a/include/pyro/pyro.h +++ b/include/pyro/pyro.h @@ -33,7 +33,7 @@ namespace Pyro // Drawing functions // **** COLOR **** - inline void background(Color c) { pg->background(c); }; + inline void background(const Color &c) { pg->background(c); }; inline void background(int c, int a = 255) { pg->background(c / 255.0f, c / 255.0f, c / 255.0f, a / 255.0); }; inline void background(int r, int g, int b, int a = 255) { pg->background(r / 255.0f, g / 255.0f, b / 255.0f, a / 255.0f); }; @@ -44,7 +44,7 @@ namespace Pyro // TODO: clear // TODO: colormode - inline void fill(Color c) { pg->fill(c); }; + inline void fill(const Color &c) { pg->fill(c); }; inline void fill(float c, float a = 1.0) { pg->fill(c, c, c, a); }; inline void fill(float r, float g, float b, float a = 1.0) { pg->fill(r, g, b, a); }; inline void fill(int c, int a = 255) { pg->fill(c, a); }; diff --git a/src/graphics.cpp b/src/graphics.cpp index 022a3f0..5856377 100644 --- a/src/graphics.cpp +++ b/src/graphics.cpp @@ -10,8 +10,9 @@ namespace Pyro { - Graphics::Graphics(unsigned int width, unsigned int height, unsigned int format, unsigned int dpi, Unit unit) : Image(width, height, format, 1, dpi, unit) + Graphics::Graphics(unsigned int width, unsigned int height, std::filesystem::path filename) : Image(width, height, ARGB) { + this->filename = filename; } Graphics::~Graphics() @@ -29,17 +30,24 @@ namespace Pyro this->background(192); } - Graphics *creategraphics(unsigned int width, unsigned int height, GraphicsMode mode) + Graphics *creategraphics(unsigned int width, unsigned int height, GraphicsMode mode, std::filesystem::path filename) { + Graphics *g = nullptr; switch (mode) { + case GraphicsMode::SVG: + case GraphicsMode::PDF: + assert(filename != ""); + g = new GraphicsCairo(width, height, mode, filename); + break; case GraphicsMode::CAIRO: default: - Graphics *g = new GraphicsCairo(width, height, ARGB, 72, Unit::PX); - g->init(); - return g; + g = new GraphicsCairo(width, height); } + assert(g != nullptr); + g->init(); + return g; } void Graphics::point(float x, float y, Unit unit) diff --git a/src/graphics_cairo.cpp b/src/graphics_cairo.cpp index 9edffa6..927a1d2 100644 --- a/src/graphics_cairo.cpp +++ b/src/graphics_cairo.cpp @@ -1,19 +1,34 @@ #include "pyro/graphics_cairo.h" #include "pyro/font_impl.h" #include "pyro/utils.h" +#include +#include + namespace Pyro { - GraphicsCairo::GraphicsCairo(unsigned int width, unsigned int height, unsigned int format, unsigned int dpi, Unit unit) : Graphics(width, height, format, dpi, unit) + GraphicsCairo::GraphicsCairo(unsigned int width, unsigned int height, GraphicsMode mode, std::filesystem::path filename) : Graphics(width, height, filename) { + this->mode = mode; } void GraphicsCairo::init() { Image::init(); - this->surface = cairo_image_surface_create_for_data(this->load_bytes(), - CAIRO_FORMAT_ARGB32, - this->_pixelwidth, this->_pixelheight, - this->_pixelwidth * 4); + switch (this->mode) + { + case SVG: + this->surface = cairo_svg_surface_create(filename.c_str(), _width, _height); + break; + case PDF: + this->surface = cairo_pdf_surface_create(filename.c_str(), _width, _height); + break; + default: + this->surface = cairo_image_surface_create_for_data(this->load_bytes(), + CAIRO_FORMAT_ARGB32, + this->_pixelwidth, this->_pixelheight, + this->_pixelwidth * 4); + break; + } this->cr = cairo_create(this->surface); Graphics::init(); } diff --git a/src/image.cpp b/src/image.cpp index 48af2be..d1767e6 100644 --- a/src/image.cpp +++ b/src/image.cpp @@ -1575,7 +1575,7 @@ namespace Pyro // Utility functions Image *createimage(unsigned int width, unsigned int height, int format) { - Image *img = new Image(width, height, format, 1, 72, Unit::PX); + Image *img = new Image(width, height, format); img->init(); return img; } diff --git a/tests/test-graphics.cpp b/tests/test-graphics.cpp index 450a674..28a03cb 100644 --- a/tests/test-graphics.cpp +++ b/tests/test-graphics.cpp @@ -243,3 +243,25 @@ TEST_CASE("Save and load images", "[graphics]") remove(filename); } } + +TEST_CASE("Use different modes", "[graphics]") +{ + SECTION("SVG") + { + Pyro::Graphics *svg = Pyro::creategraphics(640, 480, Pyro::GraphicsMode::SVG, "test-file.svg"); + svg->rect(10, 10, 20, 20); + REQUIRE(svg); + delete svg; + std::remove("test-file.svg"); + } + + SECTION("PDF") + { + + Pyro::Graphics *pdf = Pyro::creategraphics(640, 480, Pyro::GraphicsMode::PDF, "test-file.pdf"); + pdf->rect(10, 10, 20, 20); + REQUIRE(pdf); + delete pdf; + std::remove("test-file.pdf"); + } +}