diff options
author | Mike Kaganski <mike.kaganski@collabora.com> | 2024-04-10 12:15:55 +0500 |
---|---|---|
committer | Aron Budea <aron.budea@collabora.com> | 2024-05-08 08:11:16 +0200 |
commit | 8c8704d346bc8f30e60f446afb5ee9cdc2dc9a80 (patch) | |
tree | 83e2a656b1ea1f8b9083db9244655a268dbfc9a6 /vcl | |
parent | 8f95a0806d7cf1f5ec97c2d2ecdd4964e6dc8504 (diff) |
tdf#160622: Let SalLayout::GetBoundRect return basegfx::B2DRectangle
This avoids premature rounding in TextLayouterDevice::getTextBoundRect.
The box in D2DWriteTextOutRenderer::performRender needs to be expanded
to allow room for the line width (which now will be guaranteed on all
sides; previously, the rounding could happen to give no room on some
side, even prior to commit 8962141a12c966b2d891829925e6203bf8d51852).
Fixes some lines partially cut off in smaller text (or zoomed out).
Change-Id: I07335136021f894cf045363b4d736bfab06c64d4
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/166236
Tested-by: Jenkins
Reviewed-by: Mike Kaganski <mike.kaganski@collabora.com>
Signed-off-by: Xisco Fauli <xiscofauli@libreoffice.org>
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/167014
(cherry picked from commit aa2df54f37926cf95261eefade1b87da3229cfd7)
Diffstat (limited to 'vcl')
-rw-r--r-- | vcl/skia/gdiimpl.cxx | 2 | ||||
-rw-r--r-- | vcl/source/gdi/sallayout.cxx | 33 | ||||
-rw-r--r-- | vcl/source/outdev/map.cxx | 8 | ||||
-rw-r--r-- | vcl/source/outdev/text.cxx | 38 | ||||
-rw-r--r-- | vcl/win/gdi/DWriteTextRenderer.cxx | 11 |
5 files changed, 64 insertions, 28 deletions
diff --git a/vcl/skia/gdiimpl.cxx b/vcl/skia/gdiimpl.cxx index d7028b959842..f4ad57f715b0 100644 --- a/vcl/skia/gdiimpl.cxx +++ b/vcl/skia/gdiimpl.cxx @@ -2154,7 +2154,7 @@ void SkiaSalGraphicsImpl::drawGenericLayout(const GenericSalLayout& layout, Colo preDraw(); auto getBoundRect = [&layout]() { - tools::Rectangle rect; + basegfx::B2DRectangle rect; layout.GetBoundRect(rect); return rect; }; diff --git a/vcl/source/gdi/sallayout.cxx b/vcl/source/gdi/sallayout.cxx index 28138c3f61fd..3b1279dd1f66 100644 --- a/vcl/source/gdi/sallayout.cxx +++ b/vcl/source/gdi/sallayout.cxx @@ -220,11 +220,10 @@ static double trimInsignificant(double n) return std::abs(n) >= 0x1p53 ? n : std::round(n * 1e5) / 1e5; } -bool SalLayout::GetBoundRect(tools::Rectangle& rRect) const +bool SalLayout::GetBoundRect(basegfx::B2DRectangle& rRect) const { bool bRet = false; - - basegfx::B2DRectangle aUnion; + rRect.reset(); basegfx::B2DRectangle aRectangle; basegfx::B2DPoint aPos; @@ -240,28 +239,28 @@ bool SalLayout::GetBoundRect(tools::Rectangle& rRect) const { aRectangle.transform(basegfx::utils::createTranslateB2DHomMatrix(aPos)); // merge rectangle - aUnion.expand(aRectangle); + rRect.expand(aRectangle); } bRet = true; } } - if (aUnion.isEmpty()) - { - rRect = {}; - } - else - { - double l = rtl::math::approxFloor(trimInsignificant(aUnion.getMinX())), - t = rtl::math::approxFloor(trimInsignificant(aUnion.getMinY())), - r = rtl::math::approxCeil(trimInsignificant(aUnion.getMaxX())), - b = rtl::math::approxCeil(trimInsignificant(aUnion.getMaxY())); - assert(std::isfinite(l) && std::isfinite(t) && std::isfinite(r) && std::isfinite(b)); - rRect = tools::Rectangle(l, t, r, b); - } return bRet; } +tools::Rectangle SalLayout::BoundRect2Rectangle(basegfx::B2DRectangle& rRect) +{ + if (rRect.isEmpty()) + return {}; + + double l = rtl::math::approxFloor(trimInsignificant(rRect.getMinX())), + t = rtl::math::approxFloor(trimInsignificant(rRect.getMinY())), + r = rtl::math::approxCeil(trimInsignificant(rRect.getMaxX())), + b = rtl::math::approxCeil(trimInsignificant(rRect.getMaxY())); + assert(std::isfinite(l) && std::isfinite(t) && std::isfinite(r) && std::isfinite(b)); + return tools::Rectangle(l, t, r, b); +} + SalLayoutGlyphs SalLayout::GetGlyphs() const { return SalLayoutGlyphs(); // invalid diff --git a/vcl/source/outdev/map.cxx b/vcl/source/outdev/map.cxx index 23c68a238551..8707805eb1c2 100644 --- a/vcl/source/outdev/map.cxx +++ b/vcl/source/outdev/map.cxx @@ -1217,6 +1217,14 @@ basegfx::B2DPolyPolygon OutputDevice::PixelToLogic( const basegfx::B2DPolyPolygo return aTransformedPoly; } +basegfx::B2DRectangle OutputDevice::PixelToLogic(const basegfx::B2DRectangle& rDeviceRect) const +{ + basegfx::B2DRectangle aTransformedRect = rDeviceRect; + const basegfx::B2DHomMatrix& rTransformationMatrix = GetInverseViewTransformation(); + aTransformedRect.transform(rTransformationMatrix); + return aTransformedRect; +} + vcl::Region OutputDevice::PixelToLogic( const vcl::Region& rDeviceRegion ) const { diff --git a/vcl/source/outdev/text.cxx b/vcl/source/outdev/text.cxx index 1b40a1b2de28..16fdf7b073d0 100644 --- a/vcl/source/outdev/text.cxx +++ b/vcl/source/outdev/text.cxx @@ -21,6 +21,7 @@ #include <sal/log.hxx> #include <basegfx/matrix/b2dhommatrix.hxx> +#include <basegfx/matrix/b2dhommatrixtools.hxx> #include <tools/lineend.hxx> #include <tools/debug.hxx> #include <unotools/configmgr.hxx> @@ -214,7 +215,11 @@ bool OutputDevice::ImplDrawRotateText( SalLayout& rSalLayout ) tools::Rectangle aBoundRect; rSalLayout.DrawBase() = basegfx::B2DPoint( 0, 0 ); rSalLayout.DrawOffset() = Point( 0, 0 ); - if (!rSalLayout.GetBoundRect(aBoundRect)) + if (basegfx::B2DRectangle r; rSalLayout.GetBoundRect(r)) + { + aBoundRect = SalLayout::BoundRect2Rectangle(r); + } + else { // guess vertical text extents if GetBoundRect failed double nRight = rSalLayout.GetTextWidth(); @@ -1922,8 +1927,21 @@ bool OutputDevice::GetTextBoundRect( tools::Rectangle& rRect, std::span<const sal_Bool> pKashidaAry, const SalLayoutGlyphs* pGlyphs ) const { + basegfx::B2DRectangle aRect; + bool bRet = GetTextBoundRect(aRect, rStr, nBase, nIndex, nLen, nLayoutWidth, pDXAry, + pKashidaAry, pGlyphs); + rRect = SalLayout::BoundRect2Rectangle(aRect); + return bRet; +} + +bool OutputDevice::GetTextBoundRect(basegfx::B2DRectangle& rRect, const OUString& rStr, + sal_Int32 nBase, sal_Int32 nIndex, sal_Int32 nLen, + sal_uLong nLayoutWidth, KernArraySpan pDXAry, + std::span<const sal_Bool> pKashidaAry, + const SalLayoutGlyphs* pGlyphs) const +{ bool bRet = false; - rRect.SetEmpty(); + rRect.reset(); std::unique_ptr<SalLayout> pSalLayout; const Point aPoint; @@ -1947,18 +1965,22 @@ bool OutputDevice::GetTextBoundRect( tools::Rectangle& rRect, nullptr, pGlyphs); if( pSalLayout ) { - tools::Rectangle aPixelRect; + basegfx::B2DRectangle aPixelRect; bRet = pSalLayout->GetBoundRect(aPixelRect); if( bRet ) { - Point aRotatedOfs( mnTextOffX, mnTextOffY ); basegfx::B2DPoint aPos = pSalLayout->GetDrawPosition(basegfx::B2DPoint(nXOffset, 0)); - aRotatedOfs -= Point(aPos.getX(), aPos.getY()); - aPixelRect += aRotatedOfs; + auto m = basegfx::utils::createTranslateB2DHomMatrix(mnTextOffX - aPos.getX(), + mnTextOffY - aPos.getY()); + aPixelRect.transform(m); rRect = PixelToLogic( aPixelRect ); - if( mbMap ) - rRect += Point( maMapRes.mnMapOfsX, maMapRes.mnMapOfsY ); + if (mbMap) + { + m = basegfx::utils::createTranslateB2DHomMatrix(maMapRes.mnMapOfsX, + maMapRes.mnMapOfsY); + rRect.transform(m); + } } } diff --git a/vcl/win/gdi/DWriteTextRenderer.cxx b/vcl/win/gdi/DWriteTextRenderer.cxx index 3d3dac83c6dd..82508061b62a 100644 --- a/vcl/win/gdi/DWriteTextRenderer.cxx +++ b/vcl/win/gdi/DWriteTextRenderer.cxx @@ -225,8 +225,15 @@ bool D2DWriteTextOutRenderer::performRender(GenericSalLayout const & rLayout, Sa if (!pFontFace) return false; - tools::Rectangle bounds; - bool succeeded = rLayout.GetBoundRect(bounds); + auto [succeeded, bounds] = [&rLayout]() + { + basegfx::B2DRectangle r; + bool result = rLayout.GetBoundRect(r); + if (result) + r.grow(1); // plus 1 pixel to the tight range + return std::make_pair(result, SalLayout::BoundRect2Rectangle(r)); + }(); + if (succeeded) { hr = BindDC(hDC, bounds); // Update the bounding rect. |