[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