diff options
author | Tomaž Vajngerl <tomaz.vajngerl@collabora.co.uk> | 2019-11-04 18:36:51 +0100 |
---|---|---|
committer | Tomaž Vajngerl <quikee@gmail.com> | 2019-11-08 12:09:48 +0100 |
commit | 389c8239c93663fa5546b2f0227a118a3ad091bf (patch) | |
tree | 283ca215c088c682aeb1d492d6f5b7be21921965 | |
parent | 456300d4fbea0f27453973b50d148753d0315b80 (diff) |
widget theme: Gradient support when drawing widgets
Change-Id: I29239348e36e4963d9708a22ac649b2b1d68bf02
Reviewed-on: https://gerrit.libreoffice.org/82207
Tested-by: Jenkins
Reviewed-by: Tomaž Vajngerl <quikee@gmail.com>
-rw-r--r-- | include/basegfx/DrawCommands.hxx | 46 | ||||
-rw-r--r-- | svgio/source/svgreader/svgvisitor.cxx | 37 | ||||
-rw-r--r-- | vcl/headless/svpgdi.cxx | 34 | ||||
-rw-r--r-- | vcl/inc/SalGradient.hxx | 36 | ||||
-rw-r--r-- | vcl/inc/headless/svpgdi.hxx | 2 | ||||
-rw-r--r-- | vcl/inc/salgdi.hxx | 9 | ||||
-rw-r--r-- | vcl/source/gdi/FileDefinitionWidgetDraw.cxx | 46 | ||||
-rw-r--r-- | vcl/source/gdi/salgdilayout.cxx | 5 |
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, |