[Libreoffice-commits] core.git: vcl/inc vcl/opengl vcl/skia vcl/unx vcl/win

Luboš Luňák (via logerrit) logerrit at kemper.freedesktop.org
Fri Sep 25 10:06:35 UTC 2020


 vcl/inc/opengl/gdiimpl.hxx      |    1 
 vcl/inc/salgdiimpl.hxx          |    2 
 vcl/inc/skia/gdiimpl.hxx        |    2 
 vcl/inc/unx/salgdi.h            |    2 
 vcl/inc/win/salgdi.h            |    3 -
 vcl/opengl/gdiimpl.cxx          |    6 ++
 vcl/skia/gdiimpl.cxx            |  106 +++++++++++++++++++++++++++++++++++++++-
 vcl/unx/generic/gdi/gdiimpl.cxx |    5 +
 vcl/unx/generic/gdi/gdiimpl.hxx |    1 
 vcl/unx/generic/gdi/salgdi.cxx  |    5 +
 vcl/win/gdi/gdiimpl.cxx         |    6 ++
 vcl/win/gdi/gdiimpl.hxx         |    2 
 vcl/win/gdi/salgdi.cxx          |   10 +++
 13 files changed, 149 insertions(+), 2 deletions(-)

New commits:
commit eb2753560d9238f60131ff9f64aaf1eb4ae2d764
Author:     Luboš Luňák <l.lunak at collabora.com>
AuthorDate: Wed Sep 23 23:21:42 2020 +0200
Commit:     Tomaž Vajngerl <quikee at gmail.com>
CommitDate: Fri Sep 25 12:05:59 2020 +0200

    draw linear and radial gradients directly with Skia
    
    Change-Id: I592fd5d823d70c6ca01e90e96a30fb6925f63545
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/103282
    Tested-by: Jenkins
    Reviewed-by: Tomaž Vajngerl <quikee at gmail.com>

diff --git a/vcl/inc/opengl/gdiimpl.hxx b/vcl/inc/opengl/gdiimpl.hxx
index a6de106a6018..da6ce6713998 100644
--- a/vcl/inc/opengl/gdiimpl.hxx
+++ b/vcl/inc/opengl/gdiimpl.hxx
@@ -379,6 +379,7 @@ public:
                     sal_uInt8 nTransparency ) override;
 
     virtual bool drawGradient(const tools::PolyPolygon& rPolygon, const Gradient& rGradient) override;
+    virtual bool implDrawGradient(basegfx::B2DPolyPolygon const & rPolyPolygon, SalGradient const & rGradient) override;
 
     virtual bool supportsOperation(OutDevSupportType eType) const override;
 
diff --git a/vcl/inc/salgdiimpl.hxx b/vcl/inc/salgdiimpl.hxx
index 0e62669d654e..1af6e68bc2b0 100644
--- a/vcl/inc/salgdiimpl.hxx
+++ b/vcl/inc/salgdiimpl.hxx
@@ -37,6 +37,7 @@ class SalFrame;
 class Gradient;
 class OpenGLContext;
 class SalVirtualDevice;
+struct SalGradient;
 
 class VCL_PLUGIN_PUBLIC SalGraphicsImpl
 {
@@ -202,6 +203,7 @@ public:
                     sal_uInt8 nTransparency ) = 0;
 
     virtual bool drawGradient(const tools::PolyPolygon& rPolygon, const Gradient& rGradient) = 0;
+    virtual bool implDrawGradient(basegfx::B2DPolyPolygon const & rPolyPolygon, SalGradient const & rGradient) = 0;
 
     virtual bool supportsOperation(OutDevSupportType eType) const = 0;
 };
diff --git a/vcl/inc/skia/gdiimpl.hxx b/vcl/inc/skia/gdiimpl.hxx
index 2d8086639a08..df0bef608a00 100644
--- a/vcl/inc/skia/gdiimpl.hxx
+++ b/vcl/inc/skia/gdiimpl.hxx
@@ -192,6 +192,8 @@ public:
 
     virtual bool drawGradient(const tools::PolyPolygon& rPolygon,
                               const Gradient& rGradient) override;
+    virtual bool implDrawGradient(const basegfx::B2DPolyPolygon& rPolyPolygon,
+                                  const SalGradient& rGradient) override;
 
     virtual bool supportsOperation(OutDevSupportType eType) const override;
 
diff --git a/vcl/inc/unx/salgdi.h b/vcl/inc/unx/salgdi.h
index 027d0aa6f061..eac9dad95bb8 100644
--- a/vcl/inc/unx/salgdi.h
+++ b/vcl/inc/unx/salgdi.h
@@ -178,6 +178,8 @@ public:
                                         bool bPixelSnapHairline) override;
 
     virtual bool                    drawGradient( const tools::PolyPolygon&, const Gradient& ) override;
+    virtual bool                    implDrawGradient(basegfx::B2DPolyPolygon const & rPolyPolygon,
+                                        SalGradient const & rGradient) override;
 
 #if 1 // TODO: remove these obsolete methods
     virtual bool                    drawPolyLineBezier(
diff --git a/vcl/inc/win/salgdi.h b/vcl/inc/win/salgdi.h
index bf89853e1a8e..f2560f3ade59 100644
--- a/vcl/inc/win/salgdi.h
+++ b/vcl/inc/win/salgdi.h
@@ -250,7 +250,8 @@ protected:
     virtual bool        drawPolyLineBezier( sal_uInt32 nPoints, const SalPoint* pPtAry, const PolyFlags* pFlgAry ) override;
     virtual bool        drawPolygonBezier( sal_uInt32 nPoints, const SalPoint* pPtAry, const PolyFlags* pFlgAry ) override;
     virtual bool        drawPolyPolygonBezier( sal_uInt32 nPoly, 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( const tools::PolyPolygon&, const Gradient& ) override;
+    virtual bool        implDrawGradient(basegfx::B2DPolyPolygon const & rPolyPolygon, SalGradient const & rGradient) override;
 
     // CopyArea --> No RasterOp, but ClipRegion
     virtual void        copyArea( long nDestX, long nDestY, long nSrcX, long nSrcY, long nSrcWidth,
diff --git a/vcl/opengl/gdiimpl.cxx b/vcl/opengl/gdiimpl.cxx
index 3125642aa44e..d656d5fdf789 100644
--- a/vcl/opengl/gdiimpl.cxx
+++ b/vcl/opengl/gdiimpl.cxx
@@ -2188,6 +2188,12 @@ bool OpenGLSalGraphicsImpl::drawGradient(const tools::PolyPolygon& rPolyPoly,
     return true;
 }
 
+bool OpenGLSalGraphicsImpl::implDrawGradient(basegfx::B2DPolyPolygon const & /*rPolyPolygon*/,
+    SalGradient const & /*rGradient*/)
+{
+    return false;
+}
+
 void OpenGLSalGraphicsImpl::flush()
 {
     FlushDeferredDrawing();
diff --git a/vcl/skia/gdiimpl.cxx b/vcl/skia/gdiimpl.cxx
index 7722a8018619..8daf50e87160 100644
--- a/vcl/skia/gdiimpl.cxx
+++ b/vcl/skia/gdiimpl.cxx
@@ -24,11 +24,13 @@
 #include <vcl/idle.hxx>
 #include <vcl/svapp.hxx>
 #include <vcl/lazydelete.hxx>
+#include <vcl/gradient.hxx>
 #include <vcl/skia/SkiaHelper.hxx>
 #include <skia/utils.hxx>
 #include <skia/zone.hxx>
 
 #include <SkCanvas.h>
+#include <SkGradientShader.h>
 #include <SkPath.h>
 #include <SkRegion.h>
 #include <SkDashPathEffect.h>
@@ -192,6 +194,12 @@ SkColor toSkColorWithTransparency(Color aColor, double fTransparency)
     return SkColorSetA(toSkColor(aColor), 255 * (1.0 - fTransparency));
 }
 
+SkColor toSkColorWithIntensity(Color color, int intensity)
+{
+    return SkColorSetARGB(255 - color.GetTransparency(), color.GetRed() * intensity / 100,
+                          color.GetGreen() * intensity / 100, color.GetBlue() * intensity / 100);
+}
+
 Color fromSkColor(SkColor color)
 {
     return Color(255 - SkColorGetA(color), SkColorGetR(color), SkColorGetG(color),
@@ -1758,7 +1766,103 @@ bool SkiaSalGraphicsImpl::drawAlphaRect(long nX, long nY, long nWidth, long nHei
     return true;
 }
 
-bool SkiaSalGraphicsImpl::drawGradient(const tools::PolyPolygon&, const Gradient&) { return false; }
+bool SkiaSalGraphicsImpl::drawGradient(const tools::PolyPolygon& rPolyPolygon,
+                                       const Gradient& rGradient)
+{
+    if (rGradient.GetStyle() != GradientStyle::Linear
+        && rGradient.GetStyle() != GradientStyle::Radial)
+        return false; // unsupported
+    if (rGradient.GetSteps() != 0)
+        return false; // We can't tell Skia how many colors to use in the gradient.
+    preDraw();
+    SAL_INFO("vcl.skia.trace", "drawgradient(" << this << "): " << rPolyPolygon.getB2DPolyPolygon()
+                                               << ":" << static_cast<int>(rGradient.GetStyle()));
+    tools::Rectangle boundRect(rPolyPolygon.GetBoundRect());
+    if (boundRect.IsEmpty())
+        return true;
+    SkPath path;
+    if (rPolyPolygon.IsRect())
+    {
+        // Rect->Polygon conversion loses the right and bottom edge, fix that.
+        path.addRect(SkRect::MakeXYWH(boundRect.getX(), boundRect.getY(), boundRect.GetWidth(),
+                                      boundRect.GetHeight()));
+        boundRect.AdjustRight(1);
+        boundRect.AdjustBottom(1);
+    }
+    else
+        addPolyPolygonToPath(rPolyPolygon.getB2DPolyPolygon(), path);
+    path.setFillType(SkPathFillType::kEvenOdd);
+    addXorRegion(path.getBounds());
+
+    Gradient aGradient(rGradient);
+    tools::Rectangle aBoundRect;
+    Point aCenter;
+    aGradient.SetAngle(aGradient.GetAngle() + 2700);
+    aGradient.GetBoundRect(boundRect, aBoundRect, aCenter);
+    tools::Polygon aPoly(aBoundRect);
+    aPoly.Rotate(aCenter, aGradient.GetAngle() % 3600);
+
+    SkColor startColor
+        = toSkColorWithIntensity(rGradient.GetStartColor(), rGradient.GetStartIntensity());
+    SkColor endColor = toSkColorWithIntensity(rGradient.GetEndColor(), rGradient.GetEndIntensity());
+
+    sk_sp<SkShader> shader;
+    if (rGradient.GetStyle() == GradientStyle::Linear)
+    {
+        SkPoint points[2] = { SkPoint::Make(toSkX(aPoly[0].X()), toSkY(aPoly[0].Y())),
+                              SkPoint::Make(toSkX(aPoly[1].X()), toSkY(aPoly[1].Y())) };
+        SkColor colors[2] = { startColor, endColor };
+        SkScalar pos[2] = { SkDoubleToScalar(aGradient.GetBorder() / 100.0), 1.0 };
+        shader = SkGradientShader::MakeLinear(points, colors, pos, 2, SkTileMode::kClamp);
+    }
+    else
+    {
+        // Move the center by (-1,-1) (the default VCL algorithm is a bit off-center that way).
+        SkPoint center = SkPoint::Make(toSkX(aCenter.X()) - 1, toSkY(aCenter.Y()) - 1);
+        SkScalar radius = std::max(aBoundRect.GetWidth() / 2, aBoundRect.GetHeight() / 2);
+        SkColor colors[2] = { endColor, startColor };
+        SkScalar pos[2] = { SkDoubleToScalar(aGradient.GetBorder() / 100.0), 1.0 };
+        shader = SkGradientShader::MakeRadial(center, radius, colors, pos, 2, SkTileMode::kClamp);
+    }
+
+    SkPaint paint;
+    paint.setShader(shader);
+    getDrawCanvas()->drawPath(path, paint);
+    postDraw();
+    return true;
+}
+
+bool SkiaSalGraphicsImpl::implDrawGradient(const basegfx::B2DPolyPolygon& rPolyPolygon,
+                                           const SalGradient& rGradient)
+{
+    preDraw();
+    SAL_INFO("vcl.skia.trace",
+             "impldrawgradient(" << this << "): " << rPolyPolygon << ":" << rGradient.maPoint1
+                                 << "->" << rGradient.maPoint2 << ":" << rGradient.maStops.size());
+
+    SkPath path;
+    addPolyPolygonToPath(rPolyPolygon, path);
+    path.setFillType(SkPathFillType::kEvenOdd);
+
+    SkPoint points[2]
+        = { SkPoint::Make(toSkX(rGradient.maPoint1.getX()), toSkY(rGradient.maPoint1.getY())),
+            SkPoint::Make(toSkX(rGradient.maPoint2.getX()), toSkY(rGradient.maPoint2.getY())) };
+    std::vector<SkColor> colors;
+    std::vector<SkScalar> pos;
+    for (const SalGradientStop& stop : rGradient.maStops)
+    {
+        colors.emplace_back(toSkColor(stop.maColor));
+        pos.emplace_back(stop.mfOffset);
+    }
+    sk_sp<SkShader> shader = SkGradientShader::MakeLinear(points, colors.data(), pos.data(),
+                                                          colors.size(), SkTileMode::kDecal);
+    SkPaint paint;
+    paint.setShader(shader);
+    getDrawCanvas()->drawPath(path, paint);
+    addXorRegion(path.getBounds());
+    postDraw();
+    return true;
+}
 
 static double toRadian(int degree10th) { return (3600 - degree10th) * M_PI / 1800.0; }
 static double toCos(int degree10th) { return SkScalarCos(toRadian(degree10th)); }
diff --git a/vcl/unx/generic/gdi/gdiimpl.cxx b/vcl/unx/generic/gdi/gdiimpl.cxx
index a348b752dc89..5dede8f9dda6 100644
--- a/vcl/unx/generic/gdi/gdiimpl.cxx
+++ b/vcl/unx/generic/gdi/gdiimpl.cxx
@@ -1972,6 +1972,11 @@ bool X11SalGraphicsImpl::drawGradient(const tools::PolyPolygon& /*rPolygon*/, co
     return false;
 }
 
+bool X11SalGraphicsImpl::implDrawGradient(basegfx::B2DPolyPolygon const & /*rPolyPolygon*/, SalGradient const & /*rGradient*/)
+{
+    return false;
+}
+
 bool X11SalGraphicsImpl::supportsOperation(OutDevSupportType eType) const
 {
     bool bRet = false;
diff --git a/vcl/unx/generic/gdi/gdiimpl.hxx b/vcl/unx/generic/gdi/gdiimpl.hxx
index 061993bb80df..6a9201cf9c6c 100644
--- a/vcl/unx/generic/gdi/gdiimpl.hxx
+++ b/vcl/unx/generic/gdi/gdiimpl.hxx
@@ -284,6 +284,7 @@ public:
                     sal_uInt8 nTransparency ) override;
 
     virtual bool drawGradient(const tools::PolyPolygon& rPolygon, const Gradient& rGradient) override;
+    virtual bool implDrawGradient(basegfx::B2DPolyPolygon const & rPolyPolygon, SalGradient const & rGradient) override;
 
     virtual bool supportsOperation(OutDevSupportType eType) const override;
 
diff --git a/vcl/unx/generic/gdi/salgdi.cxx b/vcl/unx/generic/gdi/salgdi.cxx
index 79037c1b3a2a..719b07ef8f63 100644
--- a/vcl/unx/generic/gdi/salgdi.cxx
+++ b/vcl/unx/generic/gdi/salgdi.cxx
@@ -773,6 +773,11 @@ bool X11SalGraphics::drawGradient(const tools::PolyPolygon& rPoly, const Gradien
     return mxImpl->drawGradient(rPoly, rGradient);
 }
 
+bool X11SalGraphics::implDrawGradient(basegfx::B2DPolyPolygon const & rPolyPolygon, SalGradient const & rGradient)
+{
+    return mxImpl->implDrawGradient(rPolyPolygon, rGradient);
+}
+
 SalGeometryProvider *X11SalGraphics::GetGeometryProvider() const
 {
     if (m_pFrame)
diff --git a/vcl/win/gdi/gdiimpl.cxx b/vcl/win/gdi/gdiimpl.cxx
index e748fee84126..7c52bf36e879 100644
--- a/vcl/win/gdi/gdiimpl.cxx
+++ b/vcl/win/gdi/gdiimpl.cxx
@@ -2688,6 +2688,12 @@ bool WinSalGraphicsImpl::drawGradient(const tools::PolyPolygon& /*rPolygon*/,
     return false;
 }
 
+bool WinSalGraphicsImpl::implDrawGradient(basegfx::B2DPolyPolygon const & /*rPolyPolygon*/,
+    SalGradient const & /*rGradient*/)
+{
+    return false;
+}
+
 bool WinSalGraphicsImpl::supportsOperation(OutDevSupportType eType) const
 {
     static bool bAllowForTest(true);
diff --git a/vcl/win/gdi/gdiimpl.hxx b/vcl/win/gdi/gdiimpl.hxx
index 748afbcf04d4..92ef89e3f221 100644
--- a/vcl/win/gdi/gdiimpl.hxx
+++ b/vcl/win/gdi/gdiimpl.hxx
@@ -241,6 +241,8 @@ public:
 
     virtual bool drawGradient(const tools::PolyPolygon& rPolygon,
             const Gradient& rGradient) override;
+    virtual bool implDrawGradient(basegfx::B2DPolyPolygon const & rPolyPolygon,
+                SalGradient const & rGradient) override;
 
     virtual bool supportsOperation(OutDevSupportType eType) const override;
 };
diff --git a/vcl/win/gdi/salgdi.cxx b/vcl/win/gdi/salgdi.cxx
index 4b47b10b8f22..db4ea113b290 100644
--- a/vcl/win/gdi/salgdi.cxx
+++ b/vcl/win/gdi/salgdi.cxx
@@ -816,6 +816,16 @@ bool WinSalGraphics::drawPolyPolygonBezier( sal_uInt32 nPoly, const sal_uInt32*
     return mpImpl->drawPolyPolygonBezier( nPoly, pPoints, pPtAry, pFlgAry );
 }
 
+bool WinSalGraphics::drawGradient(const tools::PolyPolygon& rPoly, const Gradient& rGradient)
+{
+    return mpImpl->drawGradient(rPoly, rGradient);
+}
+
+bool WinSalGraphics::implDrawGradient(basegfx::B2DPolyPolygon const & rPolyPolygon, SalGradient const & rGradient)
+{
+    return mpImpl->implDrawGradient(rPolyPolygon, rGradient);
+}
+
 static BYTE* ImplSearchEntry( BYTE* pSource, BYTE const * pDest, sal_uLong nComp, sal_uLong nSize )
 {
     while ( nComp-- >= nSize )


More information about the Libreoffice-commits mailing list