diff options
author | Tomaž Vajngerl <tomaz.vajngerl@collabora.co.uk> | 2020-09-22 15:20:57 +0200 |
---|---|---|
committer | Luboš Luňák <l.lunak@collabora.com> | 2020-09-25 19:35:35 +0200 |
commit | 20c09d351ee060bdde13d92d2bf86dd998cdb0cb (patch) | |
tree | 20be340a0da3f306fbd1312fcc431f93f21d35c6 | |
parent | f3ca55e78799934c19ae66a822397d98b7997fa9 (diff) |
use vcl lin. gradient drawing in drawinglayer + cairo impl.
This adds a divert for drawing of linear gradients drawing, which
can be implemented natively with a much higher quality and speed.
This also adds a implementation of drawing linear gradients with
cairo.
Change-Id: I8c39915c3579e6eb88cdce8ae4ac9694ffdb4957
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/103374
Tested-by: Jenkins
Reviewed-by: Luboš Luňák <l.lunak@collabora.com>
-rw-r--r-- | drawinglayer/source/processor2d/vclpixelprocessor2d.cxx | 71 | ||||
-rw-r--r-- | drawinglayer/source/processor2d/vclpixelprocessor2d.hxx | 2 | ||||
-rw-r--r-- | vcl/headless/svpgdi.cxx | 49 | ||||
-rw-r--r-- | vcl/inc/headless/svpgdi.hxx | 3 |
4 files changed, 124 insertions, 1 deletions
diff --git a/drawinglayer/source/processor2d/vclpixelprocessor2d.cxx b/drawinglayer/source/processor2d/vclpixelprocessor2d.cxx index 716c23028ba6..4314c656c389 100644 --- a/drawinglayer/source/processor2d/vclpixelprocessor2d.cxx +++ b/drawinglayer/source/processor2d/vclpixelprocessor2d.cxx @@ -53,6 +53,7 @@ #include <drawinglayer/primitive2d/wrongspellprimitive2d.hxx> #include <drawinglayer/primitive2d/controlprimitive2d.hxx> #include <drawinglayer/primitive2d/borderlineprimitive2d.hxx> +#include <drawinglayer/primitive2d/fillgradientprimitive2d.hxx> #include <drawinglayer/primitive2d/unifiedtransparenceprimitive2d.hxx> #include <drawinglayer/primitive2d/pagepreviewprimitive2d.hxx> #include <drawinglayer/primitive2d/backgroundcolorprimitive2d.hxx> @@ -66,6 +67,13 @@ #include <com/sun/star/awt/XWindow2.hpp> #include <com/sun/star/awt/XControl.hpp> +#include <vcl/window.hxx> +#include <vcl/gradient.hxx> +#include <svtools/borderhelper.hxx> +#include <editeng/borderline.hxx> + +#include <com/sun/star/table/BorderLineStyle.hpp> + using namespace com::sun::star; namespace drawinglayer::processor2d @@ -198,6 +206,30 @@ bool VclPixelProcessor2D::tryDrawPolygonStrokePrimitive2DDirect( /* false bBypassAACheck, default*/); } +namespace +{ +GradientStyle convertGradientStyle(drawinglayer::attribute::GradientStyle eGradientStyle) +{ + switch (eGradientStyle) + { + case drawinglayer::attribute::GradientStyle::Axial: + return GradientStyle::Axial; + case drawinglayer::attribute::GradientStyle::Radial: + return GradientStyle::Radial; + case drawinglayer::attribute::GradientStyle::Elliptical: + return GradientStyle::Elliptical; + case drawinglayer::attribute::GradientStyle::Square: + return GradientStyle::Square; + case drawinglayer::attribute::GradientStyle::Rect: + return GradientStyle::Rect; + case drawinglayer::attribute::GradientStyle::Linear: + default: + return GradientStyle::Linear; + } +} + +} // end anonymous namespace + void VclPixelProcessor2D::processBasePrimitive2D(const primitive2d::BasePrimitive2D& rCandidate) { switch (rCandidate.getPrimitive2DID()) @@ -400,6 +432,12 @@ void VclPixelProcessor2D::processBasePrimitive2D(const primitive2d::BasePrimitiv static_cast<const drawinglayer::primitive2d::ShadowPrimitive2D&>(rCandidate)); break; } + case PRIMITIVE2D_ID_FILLGRADIENTPRIMITIVE2D: + { + processFillGradientPrimitive2D( + static_cast<const drawinglayer::primitive2d::FillGradientPrimitive2D&>(rCandidate)); + break; + } default: { SAL_INFO("drawinglayer", "default case for " << drawinglayer::primitive2d::idToString( @@ -1141,6 +1179,39 @@ void VclPixelProcessor2D::processShadowPrimitive2D(const primitive2d::ShadowPrim SAL_WARN("drawinglayer", "Temporary buffered virtual device is not visible"); } +void VclPixelProcessor2D::processFillGradientPrimitive2D( + const primitive2d::FillGradientPrimitive2D& rPrimitive) +{ + const attribute::FillGradientAttribute& rFillGradient = rPrimitive.getFillGradient(); + + if (rFillGradient.getSteps() > 0 + || rFillGradient.getStyle() != drawinglayer::attribute::GradientStyle::Linear) + { + process(rPrimitive); + return; + } + + GradientStyle eGradientStyle = convertGradientStyle(rFillGradient.getStyle()); + + basegfx::B2DRange aRange(rPrimitive.getOutputRange()); + aRange.transform(maCurrentTransformation); + + const tools::Rectangle aRectangle( + sal_Int32(std::floor(aRange.getMinX())), sal_Int32(std::floor(aRange.getMinY())), + sal_Int32(std::ceil(aRange.getMaxX())), sal_Int32(std::ceil(aRange.getMaxY()))); + + Gradient aGradient(eGradientStyle, Color(rFillGradient.getStartColor()), + Color(rFillGradient.getEndColor())); + + aGradient.SetAngle(rFillGradient.getAngle() / F_PI1800); + aGradient.SetBorder(rFillGradient.getBorder() * 100); + aGradient.SetOfsX(rFillGradient.getOffsetX() * 100.0); + aGradient.SetOfsY(rFillGradient.getOffsetY() * 100.0); + aGradient.SetSteps(rFillGradient.getSteps()); + + mpOutputDevice->DrawGradient(aRectangle, aGradient); +} + } // end of namespace /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/drawinglayer/source/processor2d/vclpixelprocessor2d.hxx b/drawinglayer/source/processor2d/vclpixelprocessor2d.hxx index c3bd19141669..480fdcaa6e18 100644 --- a/drawinglayer/source/processor2d/vclpixelprocessor2d.hxx +++ b/drawinglayer/source/processor2d/vclpixelprocessor2d.hxx @@ -42,6 +42,7 @@ class BorderLinePrimitive2D; class GlowPrimitive2D; class ShadowPrimitive2D; class SoftEdgePrimitive2D; +class FillGradientPrimitive2D; } namespace drawinglayer::processor2d @@ -99,6 +100,7 @@ class VclPixelProcessor2D final : public VclProcessor2D void processGlowPrimitive2D(const primitive2d::GlowPrimitive2D& rCandidate); void processSoftEdgePrimitive2D(const primitive2d::SoftEdgePrimitive2D& rCandidate); void processShadowPrimitive2D(const primitive2d::ShadowPrimitive2D& rCandidate); + void processFillGradientPrimitive2D(const primitive2d::FillGradientPrimitive2D& rPrimitive); public: /// constructor/destructor diff --git a/vcl/headless/svpgdi.cxx b/vcl/headless/svpgdi.cxx index 458ac9cb565a..e769474c3dd5 100644 --- a/vcl/headless/svpgdi.cxx +++ b/vcl/headless/svpgdi.cxx @@ -1910,6 +1910,55 @@ bool SvpSalGraphics::drawPolyPolygon( return true; } +bool SvpSalGraphics::drawGradient(const tools::PolyPolygon& rPolyPolygon, const Gradient& rGradient) +{ + cairo_t* cr = getCairoContext(true); + clipRegion(cr); + + basegfx::B2DPolyPolygon aB2DPolyPolygon(rPolyPolygon.getB2DPolyPolygon()); + + for (auto const & rPolygon : aB2DPolyPolygon) + { + basegfx::B2DHomMatrix rObjectToDevice; + AddPolygonToPath(cr, rPolygon, rObjectToDevice, !getAntiAliasB2DDraw(), false); + } + + Gradient aGradient(rGradient); + + tools::Rectangle aInputRect(rPolyPolygon.GetBoundRect()); + tools::Rectangle aBoundRect; + Point aCenter; + + aGradient.SetAngle(aGradient.GetAngle() + 2700); + aGradient.GetBoundRect(aInputRect, aBoundRect, aCenter); + + tools::Polygon aPoly(aBoundRect); + aPoly.Rotate(aCenter, aGradient.GetAngle() % 3600); + + cairo_pattern_t* pattern; + pattern = cairo_pattern_create_linear(aPoly[0].X(), aPoly[0].Y(), aPoly[1].X(), aPoly[1].Y()); + + cairo_pattern_add_color_stop_rgba(pattern, aGradient.GetBorder() / 100.0, + aGradient.GetStartColor().GetRed() / 255.0, + aGradient.GetStartColor().GetGreen() / 255.0, + aGradient.GetStartColor().GetBlue() / 255.0, + 1.0); + + cairo_pattern_add_color_stop_rgba(pattern, 1.0, + aGradient.GetEndColor().GetRed() / 255.0, + aGradient.GetEndColor().GetGreen() / 255.0, + aGradient.GetEndColor().GetBlue() / 255.0, + 1.0); + cairo_set_source(cr, pattern); + + basegfx::B2DRange extents = getClippedFillDamage(cr); + cairo_fill_preserve(cr); + + releaseCairoContext(cr, true, extents); + + return true; +} + bool SvpSalGraphics::implDrawGradient(basegfx::B2DPolyPolygon const & rPolyPolygon, SalGradient const & rGradient) { cairo_t* cr = getCairoContext(true); diff --git a/vcl/inc/headless/svpgdi.hxx b/vcl/inc/headless/svpgdi.hxx index 3cffdcd2a1c0..8ffe104627c4 100644 --- a/vcl/inc/headless/svpgdi.hxx +++ b/vcl/inc/headless/svpgdi.hxx @@ -232,7 +232,8 @@ public: const sal_uInt32* pPoints, const SalPoint* const* pPtAry, const PolyFlags* const* pFlgAry ) override; - virtual bool drawGradient( const tools::PolyPolygon&, const Gradient& ) override { return false; }; + + virtual bool drawGradient(tools::PolyPolygon const & rPolyPolygon, Gradient const & rGradient) override; virtual bool implDrawGradient(basegfx::B2DPolyPolygon const & rPolyPolygon, SalGradient const & rGradient) override; |