summaryrefslogtreecommitdiffstats
path: root/src/display/drawing-paintserver.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/display/drawing-paintserver.h')
-rw-r--r--src/display/drawing-paintserver.h186
1 files changed, 186 insertions, 0 deletions
diff --git a/src/display/drawing-paintserver.h b/src/display/drawing-paintserver.h
new file mode 100644
index 0000000..eb68f6b
--- /dev/null
+++ b/src/display/drawing-paintserver.h
@@ -0,0 +1,186 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+#ifndef INKSCAPE_DISPLAY_DRAWING_PAINT_SERVER_H
+#define INKSCAPE_DISPLAY_DRAWING_PAINT_SERVER_H
+/**
+ * @file
+ * Representation of paint servers used when rendering.
+ */
+/*
+ * Author: PBS <pbs3141@gmail.com>
+ * Copyright (C) 2022 Authors
+ * Released under GNU GPL v2+, read the file 'COPYING' for more information.
+ */
+
+#include <array>
+#include <vector>
+#include <cairo.h>
+#include <2geom/rect.h>
+#include <2geom/affine.h>
+#include "object/sp-gradient-spread.h"
+#include "object/sp-gradient-units.h"
+#include "object/sp-gradient-vector.h"
+
+class SPGradient;
+
+namespace Inkscape {
+
+/**
+ * A DrawingPaintServer is a lightweight copy of the resources needed to paint using a paint server.
+ *
+ * It is built by an SPPaintServer, stored in the DrawingItem tree, and used when rendering.
+ *
+ * The pattern information is stored in a rendering-backend agnostic way, and the object remains
+ * valid even after the original SPPaintServer is modified or destroyed.
+ */
+class DrawingPaintServer
+{
+public:
+ virtual ~DrawingPaintServer() = 0;
+
+ /// Produce a pattern that can be used for painting with Cairo.
+ virtual cairo_pattern_t *create_pattern(cairo_t *ct, Geom::OptRect const &bbox, double opacity) const = 0;
+
+ /// Return whether this paint server could benefit from dithering.
+ virtual bool ditherable() const { return false; }
+
+ /// Return whether create_pattern() uses its cairo_t argument. Such pattern cannot be cached, but recreated each time.
+ /// Fixme: The only reson this exists is to work around https://gitlab.freedesktop.org/cairo/cairo/-/issues/146.
+ virtual bool uses_cairo_ctx() const { return false; }
+};
+
+// Todo: Remove, merging with existing implementation for solid colours.
+/**
+ * A simple solid color, storing an RGB color and an opacity.
+ */
+class DrawingSolidColor final
+ : public DrawingPaintServer
+{
+public:
+ DrawingSolidColor(float *c, double alpha)
+ : c({c[0], c[1], c[2]})
+ , alpha(alpha) {}
+
+ cairo_pattern_t *create_pattern(cairo_t *, Geom::OptRect const &, double opacity) const override;
+
+private:
+ std::array<float, 3> c; ///< RGB color components.
+ double alpha;
+};
+
+/**
+ * The base class for all gradients.
+ */
+class DrawingGradient
+ : public DrawingPaintServer
+{
+protected:
+ DrawingGradient(SPGradientSpread spread, SPGradientUnits units, Geom::Affine const &transform)
+ : spread(spread)
+ , units(units)
+ , transform(transform) {}
+
+ bool ditherable() const override { return true; }
+
+ /// Perform some common initialization steps on the given Cairo pattern.
+ void common_setup(cairo_pattern_t *pat, Geom::OptRect const &bbox, double opacity) const;
+
+ SPGradientSpread spread;
+ SPGradientUnits units;
+ Geom::Affine transform;
+};
+
+/**
+ * A linear gradient.
+ */
+class DrawingLinearGradient final
+ : public DrawingGradient
+{
+public:
+ DrawingLinearGradient(SPGradientSpread spread, SPGradientUnits units, Geom::Affine const &transform,
+ float x1, float y1, float x2, float y2, std::vector<SPGradientStop> stops)
+ : DrawingGradient(spread, units, transform)
+ , x1(x1)
+ , y1(y1)
+ , x2(x2)
+ , y2(y2)
+ , stops(std::move(stops)) {}
+
+ cairo_pattern_t *create_pattern(cairo_t*, Geom::OptRect const &bbox, double opacity) const override;
+
+private:
+ float x1, y1, x2, y2;
+ std::vector<SPGradientStop> stops;
+};
+
+/**
+ * A radial gradient.
+ */
+class DrawingRadialGradient final
+ : public DrawingGradient
+{
+public:
+ DrawingRadialGradient(SPGradientSpread spread, SPGradientUnits units, Geom::Affine const &transform,
+ float fx, float fy, float cx, float cy, float r, float fr, std::vector<SPGradientStop> stops)
+ : DrawingGradient(spread, units, transform)
+ , fx(fx)
+ , fy(fy)
+ , cx(cx)
+ , cy(cy)
+ , r(r)
+ , fr(fr)
+ , stops(std::move(stops)) {}
+
+ cairo_pattern_t *create_pattern(cairo_t *ct, Geom::OptRect const &bbox, double opacity) const override;
+
+ bool uses_cairo_ctx() const override { return true; }
+
+private:
+ float fx, fy, cx, cy, r, fr;
+ std::vector<SPGradientStop> stops;
+};
+
+/**
+ * A mesh gradient.
+ */
+class DrawingMeshGradient final
+ : public DrawingGradient
+{
+public:
+ struct PatchData
+ {
+ Geom::Point points[4][4];
+ char pathtype[4];
+ bool tensorIsSet[4];
+ Geom::Point tensorpoints[4];
+ std::array<float, 3> color[4];
+ double opacity[4];
+ };
+
+ DrawingMeshGradient(SPGradientSpread spread, SPGradientUnits units, Geom::Affine const &transform,
+ int rows, int cols, std::vector<std::vector<PatchData>> patchdata)
+ : DrawingGradient(spread, units, transform)
+ , rows(rows)
+ , cols(cols)
+ , patchdata(std::move(patchdata)) {}
+
+ cairo_pattern_t *create_pattern(cairo_t*, Geom::OptRect const &bbox, double opacity) const override;
+
+private:
+ int rows;
+ int cols;
+ std::vector<std::vector<PatchData>> patchdata;
+};
+
+} // namespace Inkscape
+
+#endif // INKSCAPE_DISPLAY_DRAWING_PAINT_SERVER_H
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :