summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/basegfx/DrawCommands.hxx46
-rw-r--r--svgio/source/svgreader/svgvisitor.cxx37
-rw-r--r--vcl/headless/svpgdi.cxx34
-rw-r--r--vcl/inc/SalGradient.hxx36
-rw-r--r--vcl/inc/headless/svpgdi.hxx2
-rw-r--r--vcl/inc/salgdi.hxx9
-rw-r--r--vcl/source/gdi/FileDefinitionWidgetDraw.cxx46
-rw-r--r--vcl/source/gdi/salgdilayout.cxx5
8 files changed, 215 insertions, 0 deletions
diff --git a/include/basegfx/DrawCommands.hxx b/include/basegfx/DrawCommands.hxx
index f72d17011c0b..30e7cfbf4a05 100644
--- a/include/basegfx/DrawCommands.hxx
+++ b/include/basegfx/DrawCommands.hxx
@@ -16,6 +16,8 @@
#include <basegfx/color/bcolor.hxx>
#include <basegfx/polygon/b2dpolypolygon.hxx>
#include <basegfx/range/b2drange.hxx>
+#include <basegfx/matrix/b2dhommatrix.hxx>
+#include <basegfx/color/bcolor.hxx>
namespace gfx
{
@@ -34,6 +36,48 @@ enum class DrawCommandType
Path
};
+enum class GradientType
+{
+ Linear
+};
+
+class GradientStop
+{
+public:
+ float mfOffset;
+ basegfx::BColor maColor;
+ float mfOpacity;
+};
+
+class GradientInfo
+{
+public:
+ GradientType meType;
+
+ std::vector<GradientStop> maGradientStops;
+
+ GradientInfo(GradientType eType)
+ : meType(eType)
+ {
+ }
+};
+
+class LinearGradientInfo : public GradientInfo
+{
+public:
+ LinearGradientInfo()
+ : GradientInfo(GradientType::Linear)
+ {
+ }
+
+ double x1;
+ double y1;
+ double x2;
+ double y2;
+
+ basegfx::B2DHomMatrix maMatrix;
+};
+
class DrawBase : public DrawCommand
{
private:
@@ -70,6 +114,7 @@ public:
double mnOpacity;
std::shared_ptr<basegfx::BColor> mpFillColor;
std::shared_ptr<basegfx::BColor> mpStrokeColor;
+ std::shared_ptr<GradientInfo> mpFillGradient;
DrawRectangle(basegfx::B2DRange const& rRectangle)
: DrawBase(DrawCommandType::Rectangle)
@@ -91,6 +136,7 @@ public:
double mnOpacity;
std::shared_ptr<basegfx::BColor> mpFillColor;
std::shared_ptr<basegfx::BColor> mpStrokeColor;
+ std::shared_ptr<GradientInfo> mpFillGradient;
DrawPath(basegfx::B2DPolyPolygon const& rPolyPolygon)
: DrawBase(DrawCommandType::Path)
diff --git a/svgio/source/svgreader/svgvisitor.cxx b/svgio/source/svgreader/svgvisitor.cxx
index 011ce5492fa3..52247be8dd43 100644
--- a/svgio/source/svgreader/svgvisitor.cxx
+++ b/svgio/source/svgreader/svgvisitor.cxx
@@ -16,6 +16,7 @@
#include <svgsvgnode.hxx>
#include <svggnode.hxx>
#include <svgpathnode.hxx>
+#include <svggradientnode.hxx>
#include <svgvisitor.hxx>
#include <tools/color.hxx>
@@ -77,8 +78,44 @@ void SvgDrawVisitor::visit(svgio::svgreader::SvgNode const& rNode)
pRectangle->mnOpacity = rRectNode.getSvgStyleAttributes()->getOpacity().getNumber();
const basegfx::BColor* pFillColor = rRectNode.getSvgStyleAttributes()->getFill();
+ const SvgGradientNode* pFillGradient
+ = rRectNode.getSvgStyleAttributes()->getSvgGradientNodeFill();
if (pFillColor)
+ {
pRectangle->mpFillColor = std::make_shared<basegfx::BColor>(*pFillColor);
+ }
+ else if (pFillGradient)
+ {
+ drawinglayer::primitive2d::SvgGradientEntryVector aSvgGradientEntryVector;
+ pFillGradient->collectGradientEntries(aSvgGradientEntryVector);
+ if (!aSvgGradientEntryVector.empty())
+ {
+ auto aGradientInfo = std::make_shared<gfx::LinearGradientInfo>();
+
+ aGradientInfo->x1 = pFillGradient->getX1().getNumber();
+ aGradientInfo->y1 = pFillGradient->getY1().getNumber();
+ aGradientInfo->x2 = pFillGradient->getX2().getNumber();
+ aGradientInfo->y2 = pFillGradient->getY2().getNumber();
+
+ const basegfx::B2DHomMatrix* pGradientTransform
+ = pFillGradient->getGradientTransform();
+ if (pGradientTransform)
+ {
+ aGradientInfo->maMatrix = *pGradientTransform;
+ }
+
+ pRectangle->mpFillGradient = aGradientInfo;
+
+ for (auto const& rEntry : aSvgGradientEntryVector)
+ {
+ gfx::GradientStop aStop;
+ aStop.maColor = rEntry.getColor();
+ aStop.mfOffset = rEntry.getOffset();
+ aStop.mfOpacity = rEntry.getOpacity();
+ pRectangle->mpFillGradient->maGradientStops.push_back(aStop);
+ }
+ }
+ }
const basegfx::BColor* pStrokeColor = rRectNode.getSvgStyleAttributes()->getStroke();
if (pStrokeColor)
diff --git a/vcl/headless/svpgdi.cxx b/vcl/headless/svpgdi.cxx
index 5c1f0daab194..57f66d4fabf6 100644
--- a/vcl/headless/svpgdi.cxx
+++ b/vcl/headless/svpgdi.cxx
@@ -32,6 +32,7 @@
#include <o3tl/safeint.hxx>
#include <vcl/BitmapTools.hxx>
#include <vcl/sysdata.hxx>
+#include <vcl/gradient.hxx>
#include <config_cairo_canvas.h>
#include <basegfx/numeric/ftools.hxx>
#include <basegfx/range/b2drange.hxx>
@@ -1494,6 +1495,39 @@ bool SvpSalGraphics::drawPolyPolygon(
return true;
}
+bool SvpSalGraphics::implDrawGradient(basegfx::B2DPolyPolygon const & rPolyPolygon, SalGradient const & rGradient)
+{
+ cairo_t* cr = getCairoContext(true);
+ clipRegion(cr);
+
+ basegfx::B2DHomMatrix rObjectToDevice;
+
+ for (auto const & rPolygon : rPolyPolygon)
+ AddPolygonToPath(cr, rPolygon, rObjectToDevice, !getAntiAliasB2DDraw(), false);
+
+ cairo_pattern_t* pattern;
+ pattern = cairo_pattern_create_linear(rGradient.maPoint1.getX(), rGradient.maPoint1.getY(), rGradient.maPoint2.getX(), rGradient.maPoint2.getY());
+
+ for (SalGradientStop const & rStop : rGradient.maStops)
+ {
+ double r = rStop.maColor.GetRed() / 255.0;
+ double g = rStop.maColor.GetGreen() / 255.0;
+ double b = rStop.maColor.GetBlue() / 255.0;
+ double a = (0xFF - rStop.maColor.GetTransparency()) / 255.0;
+ double offset = rStop.mfOffset;
+
+ cairo_pattern_add_color_stop_rgba(pattern, offset, r, g, b, a);
+ }
+ cairo_set_source(cr, pattern);
+
+ basegfx::B2DRange extents = getClippedFillDamage(cr);
+ cairo_fill_preserve(cr);
+
+ releaseCairoContext(cr, true, extents);
+
+ return true;
+}
+
void SvpSalGraphics::applyColor(cairo_t *cr, Color aColor, double fTransparency)
{
if (cairo_surface_get_content(m_pSurface) == CAIRO_CONTENT_COLOR_ALPHA)
diff --git a/vcl/inc/SalGradient.hxx b/vcl/inc/SalGradient.hxx
new file mode 100644
index 000000000000..1b4a47f9a6ff
--- /dev/null
+++ b/vcl/inc/SalGradient.hxx
@@ -0,0 +1,36 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#ifndef INCLUDED_VCL_INC_SALGRADIENT_HXX
+#define INCLUDED_VCL_INC_SALGRADIENT_HXX
+
+#include <basegfx/point/b2dpoint.hxx>
+
+struct SalGradientStop
+{
+ Color maColor;
+ float mfOffset;
+
+ SalGradientStop(Color const& rColor, float fOffset)
+ : maColor(rColor)
+ , mfOffset(fOffset)
+ {
+ }
+};
+
+struct SalGradient
+{
+ basegfx::B2DPoint maPoint1;
+ basegfx::B2DPoint maPoint2;
+ std::vector<SalGradientStop> maStops;
+};
+
+#endif // INCLUDED_VCL_INC_SALGRADIENT_HXX
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/inc/headless/svpgdi.hxx b/vcl/inc/headless/svpgdi.hxx
index b0e4aac4adad..d06c138a0284 100644
--- a/vcl/inc/headless/svpgdi.hxx
+++ b/vcl/inc/headless/svpgdi.hxx
@@ -232,6 +232,8 @@ public:
const PolyFlags* const* pFlgAry ) override;
virtual bool drawGradient( const tools::PolyPolygon&, const Gradient& ) override { return false; };
+ virtual bool implDrawGradient(basegfx::B2DPolyPolygon const & rPolyPolygon, SalGradient const & rGradient) override;
+
virtual void copyArea( long nDestX,
long nDestY,
long nSrcX,
diff --git a/vcl/inc/salgdi.hxx b/vcl/inc/salgdi.hxx
index d61c00cd9654..6b5899a4ce10 100644
--- a/vcl/inc/salgdi.hxx
+++ b/vcl/inc/salgdi.hxx
@@ -25,6 +25,7 @@
#include "impfontmetricdata.hxx"
#include "salgdiimpl.hxx"
#include "sallayout.hxx"
+#include "SalGradient.hxx"
#include <basegfx/matrix/b2dhommatrix.hxx>
#include "WidgetDrawInterface.hxx"
@@ -275,6 +276,8 @@ public:
const tools::PolyPolygon& rPolyPoly,
const Gradient& rGradient );
+ bool DrawGradient(basegfx::B2DPolyPolygon const & rPolyPolygon,
+ SalGradient const & rGradient);
// CopyArea --> No RasterOp, but ClipRegion
void CopyArea(
@@ -486,6 +489,12 @@ protected:
const tools::PolyPolygon& rPolyPoly,
const Gradient& rGradient ) = 0;
+ virtual bool implDrawGradient(basegfx::B2DPolyPolygon const & /*rPolyPolygon*/,
+ SalGradient const & /*rGradient*/)
+ {
+ return false;
+ }
+
// CopyArea --> No RasterOp, but ClipRegion
virtual void copyArea(
long nDestX, long nDestY,
diff --git a/vcl/source/gdi/FileDefinitionWidgetDraw.cxx b/vcl/source/gdi/FileDefinitionWidgetDraw.cxx
index 653a369a1e3d..40d443bb0edf 100644
--- a/vcl/source/gdi/FileDefinitionWidgetDraw.cxx
+++ b/vcl/source/gdi/FileDefinitionWidgetDraw.cxx
@@ -19,11 +19,13 @@
#include <basegfx/range/b2drectangle.hxx>
#include <basegfx/polygon/b2dpolygontools.hxx>
+#include <basegfx/tuple/b2dtuple.hxx>
#include <basegfx/matrix/b2dhommatrixtools.hxx>
#include <tools/stream.hxx>
#include <vcl/bitmapex.hxx>
#include <vcl/BitmapTools.hxx>
+#include <vcl/gradient.hxx>
#include <comphelper/seqstream.hxx>
#include <comphelper/processfactory.hxx>
@@ -221,6 +223,50 @@ void drawFromDrawCommands(gfx::DrawRoot const& rDrawRoot, SalGraphics& rGraphics
basegfx::B2DPolyPolygon(aB2DPolygon),
1.0 - rRectangle.mnOpacity, nullptr);
}
+ else if (rRectangle.mpFillGradient)
+ {
+ rGraphics.SetLineColor();
+ rGraphics.SetFillColor();
+ if (rRectangle.mpFillGradient->meType == gfx::GradientType::Linear)
+ {
+ auto* pLinearGradient = static_cast<gfx::LinearGradientInfo*>(
+ rRectangle.mpFillGradient.get());
+ SalGradient aGradient;
+ double x, y;
+
+ x = pLinearGradient->x1;
+ y = pLinearGradient->y1;
+
+ if (x > aSVGRect.getCenterX())
+ x = x + fDeltaX;
+ if (y > aSVGRect.getCenterY())
+ y = y + fDeltaY;
+
+ aGradient.maPoint1 = basegfx::B2DPoint(x, y);
+ aGradient.maPoint1 *= basegfx::utils::createTranslateB2DHomMatrix(
+ aTargetSurface.getMinX() - 0.5, aTargetSurface.getMinY() - 0.5);
+
+ x = pLinearGradient->x2;
+ y = pLinearGradient->y2;
+
+ if (x > aSVGRect.getCenterX())
+ x = x + fDeltaX;
+ if (y > aSVGRect.getCenterY())
+ y = y + fDeltaY;
+
+ aGradient.maPoint2 = basegfx::B2DPoint(x, y);
+ aGradient.maPoint2 *= basegfx::utils::createTranslateB2DHomMatrix(
+ aTargetSurface.getMinX() - 0.5, aTargetSurface.getMinY() - 0.5);
+
+ for (gfx::GradientStop const& rStop : pLinearGradient->maGradientStops)
+ {
+ Color aColor(rStop.maColor);
+ aColor.SetTransparency(rStop.mfOpacity * (1.0f - rRectangle.mnOpacity));
+ aGradient.maStops.emplace_back(aColor, rStop.mfOffset);
+ }
+ rGraphics.DrawGradient(basegfx::B2DPolyPolygon(aB2DPolygon), aGradient);
+ }
+ }
if (rRectangle.mpStrokeColor)
{
rGraphics.SetLineColor(Color(*rRectangle.mpStrokeColor));
diff --git a/vcl/source/gdi/salgdilayout.cxx b/vcl/source/gdi/salgdilayout.cxx
index c3c3c306d19e..b0fefa665bd5 100644
--- a/vcl/source/gdi/salgdilayout.cxx
+++ b/vcl/source/gdi/salgdilayout.cxx
@@ -652,6 +652,11 @@ bool SalGraphics::DrawGradient( const tools::PolyPolygon& rPolyPoly, const Gradi
return drawGradient( rPolyPoly, rGradient );
}
+bool SalGraphics::DrawGradient(basegfx::B2DPolyPolygon const & rPolyPolygon, SalGradient const & rSalGradient)
+{
+ return implDrawGradient(rPolyPolygon, rSalGradient);
+}
+
void SalGraphics::CopyArea( long nDestX, long nDestY,
long nSrcX, long nSrcY,
long nSrcWidth, long nSrcHeight,