diff options
Diffstat (limited to 'src/display/drawing-paintserver.h')
-rw-r--r-- | src/display/drawing-paintserver.h | 186 |
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 : |