diff options
author | Caolán McNamara <caolanm@redhat.com> | 2023-01-03 19:47:32 +0000 |
---|---|---|
committer | Caolán McNamara <caolanm@redhat.com> | 2023-01-05 10:49:01 +0000 |
commit | fa0ecf2a61c24c6485693d81ff820693f21a5ec8 (patch) | |
tree | d22273c6017eca60c7f774b9a00daa3f40807d2c /vcl/headless | |
parent | 8549d6e26f5116b1fcf5e066252cc987a3f2574f (diff) |
move drawGradient into CairoCommon and reuse from X11CairoSalGraphicsImpl
Change-Id: I249afbc4cf6318fd9ed42fef0a2aa71d1a76d9ce
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/145024
Tested-by: Jenkins
Reviewed-by: Caolán McNamara <caolanm@redhat.com>
Diffstat (limited to 'vcl/headless')
-rw-r--r-- | vcl/headless/CairoCommon.cxx | 78 | ||||
-rw-r--r-- | vcl/headless/SvpGraphicsBackend.cxx | 75 |
2 files changed, 82 insertions, 71 deletions
diff --git a/vcl/headless/CairoCommon.cxx b/vcl/headless/CairoCommon.cxx index cfd463da41e3..14932adc6470 100644 --- a/vcl/headless/CairoCommon.cxx +++ b/vcl/headless/CairoCommon.cxx @@ -888,6 +888,84 @@ bool CairoCommon::drawPolyLine(cairo_t* cr, basegfx::B2DRange* pExtents, const C return true; } +bool CairoCommon::drawGradient(cairo_t* cr, basegfx::B2DRange* pExtents, bool bAntiAlias, + 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 cairo how many colors to use in the gradient. + + tools::Rectangle aInputRect(rPolyPolygon.GetBoundRect()); + if (rPolyPolygon.IsRect()) + { + // Rect->Polygon conversion loses the right and bottom edge, fix that. + aInputRect.AdjustRight(1); + aInputRect.AdjustBottom(1); + basegfx::B2DHomMatrix rObjectToDevice; + AddPolygonToPath(cr, tools::Polygon(aInputRect).getB2DPolygon(), rObjectToDevice, + !bAntiAlias, false); + } + else + { + basegfx::B2DPolyPolygon aB2DPolyPolygon(rPolyPolygon.getB2DPolyPolygon()); + for (auto const& rPolygon : std::as_const(aB2DPolyPolygon)) + { + basegfx::B2DHomMatrix rObjectToDevice; + AddPolygonToPath(cr, rPolygon, rObjectToDevice, !bAntiAlias, false); + } + } + + Gradient aGradient(rGradient); + + tools::Rectangle aBoundRect; + Point aCenter; + + aGradient.SetAngle(aGradient.GetAngle() + 2700_deg10); + aGradient.GetBoundRect(aInputRect, aBoundRect, aCenter); + Color aStartColor = aGradient.GetStartColor(); + Color aEndColor = aGradient.GetEndColor(); + + cairo_pattern_t* pattern; + if (rGradient.GetStyle() == GradientStyle::Linear) + { + tools::Polygon aPoly(aBoundRect); + aPoly.Rotate(aCenter, aGradient.GetAngle() % 3600_deg10); + pattern + = cairo_pattern_create_linear(aPoly[0].X(), aPoly[0].Y(), aPoly[1].X(), aPoly[1].Y()); + } + else + { + double radius = std::max(aBoundRect.GetWidth() / 2.0, aBoundRect.GetHeight() / 2.0); + // Move the center a bit to the top-left (the default VCL algorithm is a bit off-center that way, + // cairo is the opposite way). + pattern = cairo_pattern_create_radial(aCenter.X() - 0.5, aCenter.Y() - 0.5, 0, + aCenter.X() - 0.5, aCenter.Y() - 0.5, radius); + std::swap(aStartColor, aEndColor); + } + + cairo_pattern_add_color_stop_rgba( + pattern, aGradient.GetBorder() / 100.0, + aStartColor.GetRed() * aGradient.GetStartIntensity() / 25500.0, + aStartColor.GetGreen() * aGradient.GetStartIntensity() / 25500.0, + aStartColor.GetBlue() * aGradient.GetStartIntensity() / 25500.0, 1.0); + + cairo_pattern_add_color_stop_rgba( + pattern, 1.0, aEndColor.GetRed() * aGradient.GetEndIntensity() / 25500.0, + aEndColor.GetGreen() * aGradient.GetEndIntensity() / 25500.0, + aEndColor.GetBlue() * aGradient.GetEndIntensity() / 25500.0, 1.0); + + cairo_set_source(cr, pattern); + cairo_pattern_destroy(pattern); + + if (pExtents) + *pExtents = getClippedFillDamage(cr); + cairo_fill_preserve(cr); + + return true; +} + bool CairoCommon::implDrawGradient(cairo_t* cr, basegfx::B2DRange* pExtents, bool bAntiAlias, basegfx::B2DPolyPolygon const& rPolyPolygon, SalGradient const& rGradient) diff --git a/vcl/headless/SvpGraphicsBackend.cxx b/vcl/headless/SvpGraphicsBackend.cxx index 6f527f350760..cedf105a2e94 100644 --- a/vcl/headless/SvpGraphicsBackend.cxx +++ b/vcl/headless/SvpGraphicsBackend.cxx @@ -876,83 +876,16 @@ bool SvpGraphicsBackend::drawAlphaRect(tools::Long nX, tools::Long nY, tools::Lo bool SvpGraphicsBackend::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 cairo how many colors to use in the gradient. - cairo_t* cr = m_rCairoCommon.getCairoContext(true, getAntiAlias()); + basegfx::B2DRange extents; m_rCairoCommon.clipRegion(cr); - tools::Rectangle aInputRect(rPolyPolygon.GetBoundRect()); - if (rPolyPolygon.IsRect()) - { - // Rect->Polygon conversion loses the right and bottom edge, fix that. - aInputRect.AdjustRight(1); - aInputRect.AdjustBottom(1); - basegfx::B2DHomMatrix rObjectToDevice; - AddPolygonToPath(cr, tools::Polygon(aInputRect).getB2DPolygon(), rObjectToDevice, - !getAntiAlias(), false); - } - else - { - basegfx::B2DPolyPolygon aB2DPolyPolygon(rPolyPolygon.getB2DPolyPolygon()); - for (auto const& rPolygon : std::as_const(aB2DPolyPolygon)) - { - basegfx::B2DHomMatrix rObjectToDevice; - AddPolygonToPath(cr, rPolygon, rObjectToDevice, !getAntiAlias(), false); - } - } - - Gradient aGradient(rGradient); - - tools::Rectangle aBoundRect; - Point aCenter; - - aGradient.SetAngle(aGradient.GetAngle() + 2700_deg10); - aGradient.GetBoundRect(aInputRect, aBoundRect, aCenter); - Color aStartColor = aGradient.GetStartColor(); - Color aEndColor = aGradient.GetEndColor(); - - cairo_pattern_t* pattern; - if (rGradient.GetStyle() == GradientStyle::Linear) - { - tools::Polygon aPoly(aBoundRect); - aPoly.Rotate(aCenter, aGradient.GetAngle() % 3600_deg10); - pattern - = cairo_pattern_create_linear(aPoly[0].X(), aPoly[0].Y(), aPoly[1].X(), aPoly[1].Y()); - } - else - { - double radius = std::max(aBoundRect.GetWidth() / 2.0, aBoundRect.GetHeight() / 2.0); - // Move the center a bit to the top-left (the default VCL algorithm is a bit off-center that way, - // cairo is the opposite way). - pattern = cairo_pattern_create_radial(aCenter.X() - 0.5, aCenter.Y() - 0.5, 0, - aCenter.X() - 0.5, aCenter.Y() - 0.5, radius); - std::swap(aStartColor, aEndColor); - } - - cairo_pattern_add_color_stop_rgba( - pattern, aGradient.GetBorder() / 100.0, - aStartColor.GetRed() * aGradient.GetStartIntensity() / 25500.0, - aStartColor.GetGreen() * aGradient.GetStartIntensity() / 25500.0, - aStartColor.GetBlue() * aGradient.GetStartIntensity() / 25500.0, 1.0); - - cairo_pattern_add_color_stop_rgba( - pattern, 1.0, aEndColor.GetRed() * aGradient.GetEndIntensity() / 25500.0, - aEndColor.GetGreen() * aGradient.GetEndIntensity() / 25500.0, - aEndColor.GetBlue() * aGradient.GetEndIntensity() / 25500.0, 1.0); - - cairo_set_source(cr, pattern); - cairo_pattern_destroy(pattern); - - basegfx::B2DRange extents = getClippedFillDamage(cr); - cairo_fill_preserve(cr); + const bool bRetval( + CairoCommon::drawGradient(cr, &extents, getAntiAlias(), rPolyPolygon, rGradient)); m_rCairoCommon.releaseCairoContext(cr, true, extents); - return true; + return bRetval; } bool SvpGraphicsBackend::implDrawGradient(basegfx::B2DPolyPolygon const& rPolyPolygon, |