basegfx/source/curve/b2dcubicbezier.cxx | 24 +-- canvas/source/directx/dx_textlayout_drawhelper.cxx | 4 canvas/source/opengl/ogl_canvashelper.cxx | 2 canvas/source/tools/surface.cxx | 9 - canvas/source/vcl/canvasfont.cxx | 2 canvas/source/vcl/canvashelper.cxx | 4 canvas/source/vcl/canvashelper_texturefill.cxx | 36 ++--- canvas/source/vcl/impltools.cxx | 8 - chart2/source/controller/main/SelectionHelper.cxx | 2 cppcanvas/source/mtfrenderer/transparencygroupaction.cxx | 4 cui/source/dialogs/cuigrfflt.cxx | 8 - cui/source/tabpages/transfrm.cxx | 4 drawinglayer/source/drawinglayeruno/xprimitive2drenderer.cxx | 2 drawinglayer/source/primitive2d/textlayoutdevice.cxx | 67 +++++++--- drawinglayer/source/processor2d/helperwrongspellrenderer.cxx | 6 drawinglayer/source/processor2d/vclmetafileprocessor2d.cxx | 16 +- drawinglayer/source/processor2d/vclprocessor2d.cxx | 49 +++++-- drawinglayer/source/tools/converters.cxx | 2 drawinglayer/source/tools/emfphelperdata.cxx | 34 ++--- drawinglayer/source/tools/emfphelperdata.hxx | 10 + editeng/source/editeng/impedit3.cxx | 6 editeng/source/items/svxfont.cxx | 2 editeng/source/outliner/outliner.cxx | 4 emfio/qa/cppunit/emf/EmfImportTest.cxx | 4 emfio/source/reader/mtftools.cxx | 6 filter/source/msfilter/escherex.cxx | 2 filter/source/msfilter/eschesdo.cxx | 15 +- filter/source/svg/svgfilter.cxx | 2 filter/source/svg/svgwriter.cxx | 24 +-- hwpfilter/source/drawing.h | 1 include/basegfx/numeric/ftools.hxx | 20 +-- include/drawinglayer/primitive2d/textlayoutdevice.hxx | 2 include/svx/svdtrans.hxx | 12 - include/svx/transfrmhelper.hxx | 8 - include/tools/helpers.hxx | 8 - include/vcl/bitmap.hxx | 8 + include/vcl/outdev.hxx | 16 ++ include/vcl/vcllayout.hxx | 5 sc/qa/uitest/chart/chartLegend.py | 4 sc/source/core/data/drwlayer.cxx | 12 - sc/source/ui/miscdlgs/autofmt.cxx | 8 - sc/source/ui/view/drawview.cxx | 4 sd/qa/unit/layout-tests.cxx | 4 sd/qa/unit/tiledrendering/LOKitSearchTest.cxx | 6 sd/source/core/sdpage.cxx | 16 +- sd/source/filter/html/htmlex.cxx | 3 sd/source/ui/app/optsitem.cxx | 4 sd/source/ui/dlg/vectdlg.cxx | 6 sd/source/ui/func/fuoaprms.cxx | 3 sd/source/ui/view/drviews8.cxx | 4 sfx2/source/doc/objcont.cxx | 4 slideshow/source/engine/shapes/drawinglayeranimation.cxx | 6 slideshow/source/engine/slideview.cxx | 4 svgio/qa/cppunit/SvgImportTest.cxx | 9 + svgio/source/svgreader/svgcharacternode.cxx | 18 +- svx/qa/unit/customshapes.cxx | 10 - svx/source/customshapes/EnhancedCustomShape2d.cxx | 4 svx/source/customshapes/EnhancedCustomShape3d.cxx | 2 svx/source/dialog/_contdlg.cxx | 4 svx/source/dialog/frmsel.cxx | 12 - svx/source/engine3d/obj3d.cxx | 2 svx/source/engine3d/view3d.cxx | 6 svx/source/gallery2/galobj.cxx | 4 svx/source/svdraw/gradtrns.cxx | 24 +-- svx/source/svdraw/sdrpagewindow.cxx | 7 - svx/source/svdraw/svdcrtv.cxx | 4 svx/source/svdraw/svddrgmt.cxx | 16 +- svx/source/svdraw/svddrgv.cxx | 16 +- svx/source/svdraw/svdedtv1.cxx | 4 svx/source/svdraw/svdedxv.cxx | 8 - svx/source/svdraw/svdfmtf.cxx | 15 +- svx/source/svdraw/svdhdl.cxx | 12 + svx/source/svdraw/svdmrkv.cxx | 12 - svx/source/svdraw/svdoashp.cxx | 18 +- svx/source/svdraw/svdobj.cxx | 6 svx/source/svdraw/svdocapt.cxx | 6 svx/source/svdraw/svdocirc.cxx | 11 + svx/source/svdraw/svdoedge.cxx | 16 +- svx/source/svdraw/svdograf.cxx | 18 +- svx/source/svdraw/svdomeas.cxx | 22 +-- svx/source/svdraw/svdopath.cxx | 37 +++-- svx/source/svdraw/svdorect.cxx | 2 svx/source/svdraw/svdotext.cxx | 10 - svx/source/svdraw/svdotextdecomposition.cxx | 12 - svx/source/svdraw/svdpdf.cxx | 20 +-- svx/source/svdraw/svdpoev.cxx | 9 - svx/source/svdraw/svdtrans.cxx | 24 +-- svx/source/unodraw/UnoGraphicExporter.cxx | 8 - svx/source/unodraw/unoshape.cxx | 8 - svx/source/xoutdev/_xpoly.cxx | 7 - sw/qa/extras/layout/layout.cxx | 6 sw/qa/extras/ww8export/data/empty_group.docx |binary sw/qa/extras/ww8export/ww8export4.cxx | 24 +++ sw/source/core/draw/dflyobj.cxx | 32 ++-- sw/source/core/graphic/ndgrf.cxx | 3 sw/source/core/layout/fly.cxx | 2 sw/source/core/layout/wsfrm.cxx | 28 ++-- sw/source/ui/table/autoformatpreview.cxx | 15 +- toolkit/source/awt/vclxfont.cxx | 2 tools/CppunitTest_tools_test.mk | 1 tools/qa/cppunit/test_fround.cxx | 62 --------- tools/source/generic/color.cxx | 7 - tools/source/generic/line.cxx | 7 - tools/source/generic/poly.cxx | 37 +++-- vcl/inc/font/LogicalFontInstance.hxx | 5 vcl/inc/impfontcache.hxx | 8 - vcl/inc/impglyphitem.hxx | 6 vcl/inc/pdf/pdfbuildin_fonts.hxx | 2 vcl/inc/qt5/QtFont.hxx | 1 vcl/inc/quartz/salgdi.h | 2 vcl/inc/unx/freetype_glyphcache.hxx | 2 vcl/inc/unx/glyphcache.hxx | 1 vcl/inc/win/DWriteTextRenderer.hxx | 15 -- vcl/inc/win/winlayout.hxx | 4 vcl/osx/salframeview.mm | 3 vcl/qa/cppunit/cjktext.cxx | 2 vcl/qa/cppunit/complextext.cxx | 2 vcl/qa/cppunit/fontmocks.hxx | 3 vcl/qa/cppunit/logicalfontinstance.cxx | 67 ++++++++-- vcl/qt5/QtFont.cxx | 7 - vcl/quartz/ctfonts.cxx | 21 --- vcl/skia/gdiimpl.cxx | 17 +- vcl/skia/salbmp.cxx | 3 vcl/skia/win/gdiimpl.cxx | 33 ++--- vcl/skia/x11/textrender.cxx | 10 - vcl/source/animate/AnimationRenderer.cxx | 8 - vcl/source/bitmap/BitmapEmbossGreyFilter.cxx | 6 vcl/source/bitmap/BitmapEx.cxx | 2 vcl/source/bitmap/BitmapFastScaleFilter.cxx | 4 vcl/source/bitmap/BitmapInterpolateScaleFilter.cxx | 4 vcl/source/bitmap/BitmapScaleConvolutionFilter.cxx | 8 - vcl/source/bitmap/BitmapScaleSuperFilter.cxx | 4 vcl/source/bitmap/BitmapTools.cxx | 16 +- vcl/source/bitmap/bitmap.cxx | 52 ++++---- vcl/source/bitmap/impvect.cxx | 6 vcl/source/filter/eps/eps.cxx | 4 vcl/source/filter/wmf/emfwr.cxx | 8 - vcl/source/filter/wmf/wmfwr.cxx | 6 vcl/source/font/LogicalFontInstance.cxx | 36 ++++- vcl/source/font/fontcache.cxx | 4 vcl/source/gdi/CommonSalLayout.cxx | 6 vcl/source/gdi/gdimetafiletools.cxx | 8 - vcl/source/gdi/gdimtf.cxx | 28 ++-- vcl/source/gdi/impgraph.cxx | 6 vcl/source/gdi/metaact.cxx | 30 ++-- vcl/source/gdi/pdfbuildin_fonts.cxx | 5 vcl/source/gdi/pdfwriter_impl.cxx | 37 ++++- vcl/source/gdi/pdfwriter_impl2.cxx | 8 - vcl/source/gdi/print.cxx | 10 - vcl/source/gdi/regband.cxx | 7 - vcl/source/gdi/region.cxx | 4 vcl/source/gdi/regionband.cxx | 4 vcl/source/gdi/sallayout.cxx | 40 ++++-- vcl/source/gdi/textlayout.cxx | 2 vcl/source/graphic/GraphicObject.cxx | 24 +-- vcl/source/helper/canvastools.cxx | 4 vcl/source/outdev/bitmapex.cxx | 18 +- vcl/source/outdev/font.cxx | 6 vcl/source/outdev/hatch.cxx | 19 +- vcl/source/outdev/map.cxx | 37 +++++ vcl/source/outdev/rect.cxx | 16 +- vcl/source/outdev/text.cxx | 71 ++++++++--- vcl/source/outdev/textline.cxx | 4 vcl/source/outdev/transparent.cxx | 2 vcl/source/window/printdlg.cxx | 4 vcl/source/window/window2.cxx | 6 vcl/unx/generic/glyphs/freetype_glyphcache.cxx | 38 ----- vcl/unx/generic/glyphs/glyphcache.cxx | 8 - vcl/unx/gtk3/gtkinst.cxx | 3 vcl/win/gdi/DWriteTextRenderer.cxx | 39 ++++-- vcl/win/gdi/gdiimpl.cxx | 4 vcl/win/gdi/salfont.cxx | 53 -------- vcl/win/gdi/winlayout.cxx | 18 -- vcl/workben/listglyphs.cxx | 2 xmloff/source/draw/shapeexport.cxx | 17 +- 175 files changed, 1134 insertions(+), 1011 deletions(-)
New commits: commit 76342214ed36a02342dbc43a081fa0e64a0262c4 Author: Mike Kaganski <mike.kagan...@collabora.com> AuthorDate: Tue Apr 23 05:25:34 2024 +0500 Commit: Mike Kaganski <mike.kagan...@collabora.com> CommitDate: Mon Apr 29 10:02:52 2024 +0500 Fix a thinko in 8a97f1ba8d9ccb65b2c89106de20666311d90c30 Change-Id: I07bb67e9384470269d1fd3df087acee377cce729 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/166490 Tested-by: Jenkins Reviewed-by: Mike Kaganski <mike.kagan...@collabora.com> diff --git a/drawinglayer/source/primitive2d/textlayoutdevice.cxx b/drawinglayer/source/primitive2d/textlayoutdevice.cxx index 31120279a732..a9b78c599042 100644 --- a/drawinglayer/source/primitive2d/textlayoutdevice.cxx +++ b/drawinglayer/source/primitive2d/textlayoutdevice.cxx @@ -188,7 +188,7 @@ void TextLayouterDevice::setFontAttribute(const attribute::FontAttribute& rFontA } else { - mnFontScalingFixX = mnFontScalingFixY = 0; + mnFontScalingFixX = mnFontScalingFixY = 1.0; } } commit 44e8c255d6e072e12f3e178b5080ad0f6b87b173 Author: Mike Kaganski <mike.kagan...@collabora.com> AuthorDate: Mon Apr 22 14:45:37 2024 +0500 Commit: Mike Kaganski <mike.kagan...@collabora.com> CommitDate: Mon Apr 29 10:02:52 2024 +0500 tdf#160773: handle 0-size font height Regression from commit cc3663bbaed4f65d64154e5f9abb51a5f622f710 (tdf#160702: improve text positioning, 2024-04-20), where I didn't know yet that this was possible :-) Change-Id: I1316db48b8acbacd077eeb4a8989c3dbf7e4a7b5 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/166425 Tested-by: Jenkins Reviewed-by: Mike Kaganski <mike.kagan...@collabora.com> diff --git a/drawinglayer/source/primitive2d/textlayoutdevice.cxx b/drawinglayer/source/primitive2d/textlayoutdevice.cxx index 5bc82301b794..31120279a732 100644 --- a/drawinglayer/source/primitive2d/textlayoutdevice.cxx +++ b/drawinglayer/source/primitive2d/textlayoutdevice.cxx @@ -179,8 +179,17 @@ void TextLayouterDevice::setFontAttribute(const attribute::FontAttribute& rFontA = getVclFontFromFontAttribute(rFontAttribute, fFontScaleX, fFontScaleY, 0.0, rLocale); setFont(aFont); Size aFontSize = aFont.GetFontSize(); - mnFontScalingFixY = fFontScaleY / aFontSize.Height(); - mnFontScalingFixX = fFontScaleX / (aFontSize.Width() ? aFontSize.Width() : aFontSize.Height()); + if (aFontSize.Height()) + { + mnFontScalingFixY = fFontScaleY / aFontSize.Height(); + // aFontSize.Width() is 0 for uninformly scaled fonts: see getVclFontFromFontAttribute + mnFontScalingFixX + = fFontScaleX / (aFontSize.Width() ? aFontSize.Width() : aFontSize.Height()); + } + else + { + mnFontScalingFixX = mnFontScalingFixY = 0; + } } double TextLayouterDevice::getOverlineOffset() const commit 6e179e68bcfa6fadd503327699d907966f6fa3d8 Author: Mike Kaganski <mike.kagan...@collabora.com> AuthorDate: Tue Apr 16 10:48:06 2024 +0500 Commit: Mike Kaganski <mike.kagan...@collabora.com> CommitDate: Mon Apr 29 10:02:52 2024 +0500 tdf#160702: improve text positioning Opening an SVG with text in different elements (e.g., tspans) in the same text element performs calculations to position the parts properly (i.e., the next part will start where the previous part ended, unless the position in overridden explicitly). These calculations require to know the text widths. The first problem leas here: the text width was calculated for a typically small text size (numerically equal to the pixel size defined in the SVG), but these calculations aren't truly linear, because font rendering may change depending on font height. Additionally, the rounding gives much higher error in smaller sizes than in larger. There was already a workaround for a similar problem in ViewRedirector::createRedirectedPrimitive2DSequence, where a large font (with 100 times greater height) was used to increase correctness. This was also used here, with the same large height (50000) used as a reference. Then, at the time of wrawing the text at different zoom levels, the code in VclProcessor2D::RenderTextSimpleOrDecoratedPortionPrimitive2D creates a font of a calculated size, and uses it to output the text. But the font is always created with an integral height, which means, that for a wanted height of 2.5 (in a zoomed out view), the really used height will be 3, which is 20% larger; or for wanted height of 2.4, the actual height will be 2 (20% smaller). This resulted in odd jumps of the text widths, when the text may overlap the following part, or conversely, create a big gap before the next gap. To try to mitigate that, the function now takes the difference between the wanted and the actual font size into account, and adjusts the MapMode accordingly. This doesn't fix the jumping completely (e.g., because of the mentioned special handling of small font sizes in the fonts thenselves, like hinting), but still makes the calculations much more stable, decreasing the amount of jumping. Similar changes are made in TextLayouterDevice. Use of the functions that return text size as a double, not rounded value, should additionally help improving stability. Change-Id: I455845d8ca43ee9c06a0fc980947f35d8a25797a Reviewed-on: https://gerrit.libreoffice.org/c/core/+/166238 Tested-by: Jenkins Reviewed-by: Mike Kaganski <mike.kagan...@collabora.com> diff --git a/drawinglayer/source/primitive2d/textlayoutdevice.cxx b/drawinglayer/source/primitive2d/textlayoutdevice.cxx index e36abffe2e64..5bc82301b794 100644 --- a/drawinglayer/source/primitive2d/textlayoutdevice.cxx +++ b/drawinglayer/source/primitive2d/textlayoutdevice.cxx @@ -22,6 +22,8 @@ #include <algorithm> #include <com/sun/star/uno/XComponentContext.hpp> + +#include <basegfx/matrix/b2dhommatrixtools.hxx> #include <drawinglayer/attribute/fontattribute.hxx> #include <drawinglayer/primitive2d/textlayoutdevice.hxx> #include <comphelper/processfactory.hxx> @@ -162,56 +164,69 @@ TextLayouterDevice::TextLayouterDevice() TextLayouterDevice::~TextLayouterDevice() COVERITY_NOEXCEPT_FALSE { releaseGlobalVirtualDevice(); } -void TextLayouterDevice::setFont(const vcl::Font& rFont) { mrDevice.SetFont(rFont); } +void TextLayouterDevice::setFont(const vcl::Font& rFont) +{ + mrDevice.SetFont(rFont); + mnFontScalingFixX = 1.0; + mnFontScalingFixY = 1.0; +} void TextLayouterDevice::setFontAttribute(const attribute::FontAttribute& rFontAttribute, double fFontScaleX, double fFontScaleY, const css::lang::Locale& rLocale) { - setFont(getVclFontFromFontAttribute(rFontAttribute, fFontScaleX, fFontScaleY, 0.0, rLocale)); + vcl::Font aFont + = getVclFontFromFontAttribute(rFontAttribute, fFontScaleX, fFontScaleY, 0.0, rLocale); + setFont(aFont); + Size aFontSize = aFont.GetFontSize(); + mnFontScalingFixY = fFontScaleY / aFontSize.Height(); + mnFontScalingFixX = fFontScaleX / (aFontSize.Width() ? aFontSize.Width() : aFontSize.Height()); } double TextLayouterDevice::getOverlineOffset() const { const ::FontMetric& rMetric = mrDevice.GetFontMetric(); double fRet = (rMetric.GetInternalLeading() / 2.0) - rMetric.GetAscent(); - return fRet; + return fRet * mnFontScalingFixY; } double TextLayouterDevice::getUnderlineOffset() const { const ::FontMetric& rMetric = mrDevice.GetFontMetric(); double fRet = rMetric.GetDescent() / 2.0; - return fRet; + return fRet * mnFontScalingFixY; } double TextLayouterDevice::getStrikeoutOffset() const { const ::FontMetric& rMetric = mrDevice.GetFontMetric(); double fRet = (rMetric.GetAscent() - rMetric.GetInternalLeading()) / 3.0; - return fRet; + return fRet * mnFontScalingFixY; } double TextLayouterDevice::getOverlineHeight() const { const ::FontMetric& rMetric = mrDevice.GetFontMetric(); double fRet = rMetric.GetInternalLeading() / 2.5; - return fRet; + return fRet * mnFontScalingFixY; } double TextLayouterDevice::getUnderlineHeight() const { const ::FontMetric& rMetric = mrDevice.GetFontMetric(); double fRet = rMetric.GetDescent() / 4.0; - return fRet; + return fRet * mnFontScalingFixY; } -double TextLayouterDevice::getTextHeight() const { return mrDevice.GetTextHeight(); } +double TextLayouterDevice::getTextHeight() const +{ + return mrDevice.GetTextHeightDouble() * mnFontScalingFixY; +} double TextLayouterDevice::getTextWidth(const OUString& rText, sal_uInt32 nIndex, sal_uInt32 nLength) const { - return mrDevice.GetTextWidth(rText, nIndex, nLength); + return mrDevice.GetTextWidthDouble(rText, nIndex, nLength) * mnFontScalingFixX; } void TextLayouterDevice::getTextOutlines(basegfx::B2DPolyPolygonVector& rB2DPolyPolyVector, @@ -245,6 +260,13 @@ void TextLayouterDevice::getTextOutlines(basegfx::B2DPolyPolygonVector& rB2DPoly { mrDevice.GetTextOutlines(rB2DPolyPolyVector, rText, nIndex, nIndex, nLength); } + if (!rtl_math_approxEqual(mnFontScalingFixY, 1.0) + || !rtl_math_approxEqual(mnFontScalingFixX, 1.0)) + { + auto scale = basegfx::utils::createScaleB2DHomMatrix(mnFontScalingFixX, mnFontScalingFixY); + for (auto& poly : rB2DPolyPolyVector) + poly.transform(scale); + } } basegfx::B2DRange TextLayouterDevice::getTextBoundRect(const OUString& rText, sal_uInt32 nIndex, @@ -262,6 +284,12 @@ basegfx::B2DRange TextLayouterDevice::getTextBoundRect(const OUString& rText, sa { basegfx::B2DRange aRect; mrDevice.GetTextBoundRect(aRect, rText, nIndex, nIndex, nLength); + if (!rtl_math_approxEqual(mnFontScalingFixY, 1.0) + || !rtl_math_approxEqual(mnFontScalingFixX, 1.0)) + { + aRect.transform( + basegfx::utils::createScaleB2DHomMatrix(mnFontScalingFixX, mnFontScalingFixY)); + } return aRect; } @@ -271,13 +299,13 @@ basegfx::B2DRange TextLayouterDevice::getTextBoundRect(const OUString& rText, sa double TextLayouterDevice::getFontAscent() const { const ::FontMetric& rMetric = mrDevice.GetFontMetric(); - return rMetric.GetAscent(); + return rMetric.GetAscent() * mnFontScalingFixY; } double TextLayouterDevice::getFontDescent() const { const ::FontMetric& rMetric = mrDevice.GetFontMetric(); - return rMetric.GetDescent(); + return rMetric.GetDescent() * mnFontScalingFixY; } void TextLayouterDevice::addTextRectActions(const ::tools::Rectangle& rRectangle, @@ -305,7 +333,7 @@ std::vector<double> TextLayouterDevice::getTextArray(const OUString& rText, sal_ mrDevice.GetTextArray(rText, &aArray, nIndex, nTextLength); aRetval.reserve(aArray.size()); for (size_t i = 0, nEnd = aArray.size(); i < nEnd; ++i) - aRetval.push_back(aArray[i]); + aRetval.push_back(aArray[i] * mnFontScalingFixX); } return aRetval; diff --git a/drawinglayer/source/processor2d/vclprocessor2d.cxx b/drawinglayer/source/processor2d/vclprocessor2d.cxx index 6a1073fa9d5b..f8e5d0457583 100644 --- a/drawinglayer/source/processor2d/vclprocessor2d.cxx +++ b/drawinglayer/source/processor2d/vclprocessor2d.cxx @@ -180,7 +180,8 @@ void VclProcessor2D::RenderTextSimpleOrDecoratedPortionPrimitive2D( } // Don't draw fonts without height - if (aFont.GetFontHeight() <= 0) + Size aResultFontSize = aFont.GetFontSize(); + if (aResultFontSize.Height() <= 0) return; // set FillColor Attribute @@ -397,8 +398,31 @@ void VclProcessor2D::RenderTextSimpleOrDecoratedPortionPrimitive2D( else { const basegfx::B2DPoint aPoint(aLocalTransform * basegfx::B2DPoint(0.0, 0.0)); - aStartPoint = Point(basegfx::fround<tools::Long>(aPoint.getX()), - basegfx::fround<tools::Long>(aPoint.getY())); + double aPointX = aPoint.getX(), aPointY = aPoint.getY(); + + // aFont has an integer size; we must scale a bit for precision + double nFontScalingFixY = aFontScaling.getY() / aResultFontSize.Height(); + double nFontScalingFixX = aFontScaling.getX() + / (aResultFontSize.Width() ? aResultFontSize.Width() + : aResultFontSize.Height()); + + if (!rtl_math_approxEqual(nFontScalingFixY, 1.0) + || !rtl_math_approxEqual(nFontScalingFixX, 1.0)) + { + MapMode aMapMode = mpOutputDevice->GetMapMode(); + aMapMode.SetScaleX(aMapMode.GetScaleX() * nFontScalingFixX); + aMapMode.SetScaleY(aMapMode.GetScaleY() * nFontScalingFixY); + + mpOutputDevice->Push(vcl::PushFlags::MAPMODE); + mpOutputDevice->SetRelativeMapMode(aMapMode); + bChangeMapMode = true; + + aPointX /= nFontScalingFixX; + aPointY /= nFontScalingFixY; + } + + aStartPoint = Point(basegfx::fround<tools::Long>(aPointX), + basegfx::fround<tools::Long>(aPointY)); } // tdf#152990 set the font after the MapMode is (potentially) set so canvas uses the desired diff --git a/include/drawinglayer/primitive2d/textlayoutdevice.hxx b/include/drawinglayer/primitive2d/textlayoutdevice.hxx index 6348de0ddd25..a2e45f1bd8b5 100644 --- a/include/drawinglayer/primitive2d/textlayoutdevice.hxx +++ b/include/drawinglayer/primitive2d/textlayoutdevice.hxx @@ -63,6 +63,8 @@ class DRAWINGLAYER_DLLPUBLIC TextLayouterDevice /// internally used VirtualDevice SolarMutexGuard maSolarGuard; VirtualDevice& mrDevice; + double mnFontScalingFixX = 1.0; + double mnFontScalingFixY = 1.0; public: /// constructor/destructor diff --git a/svgio/source/svgreader/svgcharacternode.cxx b/svgio/source/svgreader/svgcharacternode.cxx index 4ffc46a483db..d83c8b645202 100644 --- a/svgio/source/svgreader/svgcharacternode.cxx +++ b/svgio/source/svgreader/svgcharacternode.cxx @@ -257,9 +257,12 @@ namespace svgio::svgreader // prepare locale css::lang::Locale aLocale; - // prepare TextLayouterDevice + // prepare TextLayouterDevice; use a larger font size for more linear size + // calculations. Similar to nTextSizeFactor in sd/source/ui/view/sdview.cxx + // (ViewRedirector::createRedirectedPrimitive2DSequence). + const double sizeFactor = fFontHeight < 50000 ? 50000 / fFontHeight : 1.0; TextLayouterDevice aTextLayouterDevice; - aTextLayouterDevice.setFontAttribute(aFontAttribute, fFontWidth, fFontHeight, aLocale); + aTextLayouterDevice.setFontAttribute(aFontAttribute, fFontWidth * sizeFactor, fFontHeight * sizeFactor, aLocale); // prepare TextArray ::std::vector< double > aTextArray(rSvgTextPosition.getX()); @@ -293,7 +296,7 @@ namespace svgio::svgreader // get current TextPosition and TextWidth in units basegfx::B2DPoint aPosition(rSvgTextPosition.getPosition()); - double fTextWidth(aTextLayouterDevice.getTextWidth(getText(), nIndex, nLength)); + double fTextWidth(aTextLayouterDevice.getTextWidth(getText(), nIndex, nLength) / sizeFactor); // check for user-given TextLength if(0.0 != rSvgTextPosition.getTextLength() @@ -306,7 +309,10 @@ namespace svgio::svgreader // spacing, need to create and expand TextArray if(aTextArray.empty()) { - aTextArray = aTextLayouterDevice.getTextArray(getText(), nIndex, nLength); + auto aExtendArray(aTextLayouterDevice.getTextArray(getText(), nIndex, nLength)); + aTextArray.reserve(aExtendArray.size()); + for (auto n : aExtendArray) + aTextArray.push_back(n / sizeFactor); } for(auto &a : aTextArray) @@ -384,12 +390,12 @@ namespace svgio::svgreader { case BaselineShift::Sub: { - aPosition.setY(aPosition.getY() + aTextLayouterDevice.getUnderlineOffset()); + aPosition.setY(aPosition.getY() + aTextLayouterDevice.getUnderlineOffset() / sizeFactor); break; } case BaselineShift::Super: { - aPosition.setY(aPosition.getY() + aTextLayouterDevice.getOverlineOffset()); + aPosition.setY(aPosition.getY() + aTextLayouterDevice.getOverlineOffset() / sizeFactor); break; } case BaselineShift::Percentage: commit c92e08d54033ffeb010c7460f1c25b31cb4c0f37 Author: Mike Kaganski <mike.kagan...@collabora.com> AuthorDate: Thu Apr 18 13:18:37 2024 +0500 Commit: Mike Kaganski <mike.kagan...@collabora.com> CommitDate: Mon Apr 29 10:02:52 2024 +0500 Return double from OutputDevice::GetTextArray And introduce GetTextWidth / GetTextHeight variants returning double. It allows to avoid premature rounding. At least in one case - testTdf145111_anchor_in_Fontwork - it allowed to make the test DPI-independent (at least in my testing on Windows, using 125, 150, and 175% UI scaling). Change-Id: I973d2c729ec6bb7114b4f99b9027f1ead7c1d061 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/166237 Tested-by: Jenkins Reviewed-by: Mike Kaganski <mike.kagan...@collabora.com> diff --git a/drawinglayer/source/processor2d/vclprocessor2d.cxx b/drawinglayer/source/processor2d/vclprocessor2d.cxx index 13025b27d8a2..6a1073fa9d5b 100644 --- a/drawinglayer/source/processor2d/vclprocessor2d.cxx +++ b/drawinglayer/source/processor2d/vclprocessor2d.cxx @@ -340,8 +340,8 @@ void VclProcessor2D::RenderTextSimpleOrDecoratedPortionPrimitive2D( { tools::Long nWidthToFill = rTextCandidate.getWidthToFill(); - tools::Long nWidth - = mpOutputDevice->GetTextArray(rTextCandidate.getText(), &aDXArray, 0, 1); + tools::Long nWidth = basegfx::fround<tools::Long>( + mpOutputDevice->GetTextArray(rTextCandidate.getText(), &aDXArray, 0, 1)); sal_Int32 nChars = 2; if (nWidth) nChars = nWidthToFill / nWidth; diff --git a/editeng/source/items/svxfont.cxx b/editeng/source/items/svxfont.cxx index b484a645a7f6..306b378fc133 100644 --- a/editeng/source/items/svxfont.cxx +++ b/editeng/source/items/svxfont.cxx @@ -37,7 +37,7 @@ static tools::Long GetTextArray( const OutputDevice* pOut, const OUString& rStr, { const SalLayoutGlyphs* layoutGlyphs = SalLayoutGlyphsCache::self()->GetLayoutGlyphs(pOut, rStr, nIndex, nLen); - return pOut->GetTextArray( rStr, pDXAry, nIndex, nLen, true, nullptr, layoutGlyphs); + return basegfx::fround<tools::Long>(pOut->GetTextArray( rStr, pDXAry, nIndex, nLen, true, nullptr, layoutGlyphs)); } SvxFont::SvxFont() diff --git a/emfio/qa/cppunit/emf/EmfImportTest.cxx b/emfio/qa/cppunit/emf/EmfImportTest.cxx index 1e03cc15dc20..627423117b37 100644 --- a/emfio/qa/cppunit/emf/EmfImportTest.cxx +++ b/emfio/qa/cppunit/emf/EmfImportTest.cxx @@ -1343,7 +1343,7 @@ void Test::TestExtTextOutOpaqueAndClipWMF() assertXPath(pDocument, aXPathPrefix + "mask/group[3]/mask/group/polypolygoncolor", "color", "#ff8000"); assertXPath(pDocument, aXPathPrefix + "mask/group[3]/mask/group/polypolygoncolor/polypolygon", - "path", "m1067 1067h1270v473h-1270z"); + "path", "m1067 1067h1317v473h-1317z"); assertXPath(pDocument, aXPathPrefix + "mask/group[3]/mask/group/textsimpleportion", "text", "OOOO"); assertXPath(pDocument, aXPathPrefix + "mask/group[3]/mask/group/textsimpleportion", "fontcolor", diff --git a/filter/source/svg/svgwriter.cxx b/filter/source/svg/svgwriter.cxx index ff444a6ce284..aa83250f53b6 100644 --- a/filter/source/svg/svgwriter.cxx +++ b/filter/source/svg/svgwriter.cxx @@ -2690,7 +2690,7 @@ void SVGActionWriter::ImplWriteText( const Point& rPos, const OUString& rText, } else { - aNormSize = Size( mpVDev->GetTextArray( rText, &aTmpArray ), 0 ); + aNormSize = Size(basegfx::fround<tools::Long>(mpVDev->GetTextArray(rText, &aTmpArray)), 0); } // if text is rotated, set transform matrix at new g element diff --git a/include/vcl/outdev.hxx b/include/vcl/outdev.hxx index 8bcf883c8fc9..098a5ccc5ef0 100644 --- a/include/vcl/outdev.hxx +++ b/include/vcl/outdev.hxx @@ -1033,12 +1033,16 @@ public: tools::Long GetTextWidth( const OUString& rStr, sal_Int32 nIndex = 0, sal_Int32 nLen = -1, vcl::text::TextLayoutCache const* = nullptr, SalLayoutGlyphs const*const pLayoutCache = nullptr) const; + double GetTextWidthDouble(const OUString& rStr, sal_Int32 nIndex = 0, sal_Int32 nLen = -1, + vcl::text::TextLayoutCache const* = nullptr, + SalLayoutGlyphs const* const pLayoutCache = nullptr) const; /** Height where any character of the current font fits; in logic coordinates. See also GetTextBoundRect() for more explanation + code examples. */ tools::Long GetTextHeight() const; + double GetTextHeightDouble() const; float approximate_digit_width() const; void DrawTextArray( const Point& rStartPt, const OUString& rStr, @@ -1048,7 +1052,7 @@ public: sal_Int32 nLen, SalLayoutFlags flags = SalLayoutFlags::NONE, const SalLayoutGlyphs* pLayoutCache = nullptr); - tools::Long GetTextArray( const OUString& rStr, KernArray* pDXAry, + double GetTextArray( const OUString& rStr, KernArray* pDXAry, sal_Int32 nIndex = 0, sal_Int32 nLen = -1, bool bCaret = false, vcl::text::TextLayoutCache const* = nullptr, SalLayoutGlyphs const*const pLayoutCache = nullptr) const; @@ -1841,6 +1845,9 @@ private: */ SAL_DLLPRIVATE tools::Long ImplLogicYToDevicePixel( tools::Long nY ) const; + SAL_DLLPRIVATE double ImplDevicePixelToLogicWidthDouble(double nWidth) const; + SAL_DLLPRIVATE double ImplDevicePixelToLogicHeightDouble(double nHeight) const; + /** @name Native Widget Rendering functions These all just call through to the private mpGraphics functions of the same name. diff --git a/sc/qa/uitest/chart/chartLegend.py b/sc/qa/uitest/chart/chartLegend.py index 45938e23017d..fe0525a0746d 100644 --- a/sc/qa/uitest/chart/chartLegend.py +++ b/sc/qa/uitest/chart/chartLegend.py @@ -88,7 +88,7 @@ class chartLegend(UITestCase): xLegends.executeAction("SELECT", tuple()) with self.ui_test.execute_dialog_through_action(xLegends, "COMMAND", mkPropertyValues({"COMMAND": "TransformDialog"})) as xDialog: - self.assertEqual("4.61", get_state_as_dict(xDialog.getChild("MTR_FLD_POS_X"))['Value']) + self.assertEqual("4.59", get_state_as_dict(xDialog.getChild("MTR_FLD_POS_X"))['Value']) self.assertEqual("1.54", get_state_as_dict(xDialog.getChild("MTR_FLD_POS_Y"))['Value']) xChartMain.executeAction("TYPE", mkPropertyValues({"KEYCODE": "UP"})) @@ -96,7 +96,7 @@ class chartLegend(UITestCase): # Check the position has changed after moving the label using the arrows keys with self.ui_test.execute_dialog_through_action(xLegends, "COMMAND", mkPropertyValues({"COMMAND": "TransformDialog"})) as xDialog: - self.assertEqual("4.51", get_state_as_dict(xDialog.getChild("MTR_FLD_POS_X"))['Value']) + self.assertEqual("4.49", get_state_as_dict(xDialog.getChild("MTR_FLD_POS_X"))['Value']) self.assertEqual("1.44", get_state_as_dict(xDialog.getChild("MTR_FLD_POS_Y"))['Value']) def test_Tdf147394(self): diff --git a/sd/qa/unit/layout-tests.cxx b/sd/qa/unit/layout-tests.cxx index 1c4429f62aec..681f137f4dbb 100644 --- a/sd/qa/unit/layout-tests.cxx +++ b/sd/qa/unit/layout-tests.cxx @@ -103,7 +103,7 @@ CPPUNIT_TEST_FIXTURE(SdLayoutTest, testTdf128212) xmlDocUniquePtr pXmlDoc = load("pptx/tdf128212.pptx"); // Without the fix in place, this test would have failed with - // - Expected: 7793 + // - Expected: 7795 // - Actual : 12068 assertXPath(pXmlDoc, "/metafile/push[1]/push[1]/textarray", "x", "4525"); assertXPath(pXmlDoc, "/metafile/push[1]/push[1]/textarray", "y", "7797"); @@ -310,7 +310,7 @@ CPPUNIT_TEST_FIXTURE(SdLayoutTest, testFitToFrameTextFitting) assertXPath(pXmlDoc, "/metafile/push[1]/push[1]/textarray[1]", "y", "406"); assertXPath(pXmlDoc, "/metafile/push[1]/push[1]/textarray[1]/dxarray", "first", "114"); #ifndef _WIN32 // Windows seems to differ in text layouting, so ignore for now - assertXPath(pXmlDoc, "/metafile/push[1]/push[1]/textarray[1]/dxarray", "last", "7010"); + assertXPath(pXmlDoc, "/metafile/push[1]/push[1]/textarray[1]/dxarray", "last", "6984"); #endif } diff --git a/sd/qa/unit/tiledrendering/LOKitSearchTest.cxx b/sd/qa/unit/tiledrendering/LOKitSearchTest.cxx index f3beb12b3ce1..1468f130cf11 100644 --- a/sd/qa/unit/tiledrendering/LOKitSearchTest.cxx +++ b/sd/qa/unit/tiledrendering/LOKitSearchTest.cxx @@ -655,8 +655,7 @@ void LOKitSearchTest::testSearchIn2MixedObjects() CPPUNIT_ASSERT_EQUAL(size_t(1), mpCallbackRecorder->m_aSearchResultSelection.size()); CPPUNIT_ASSERT_EQUAL(size_t(1), mpCallbackRecorder->m_aSearchResultPart.size()); - CPPUNIT_ASSERT_EQUAL(OString("3546, 3174, 738, 402"), - mpCallbackRecorder->m_aSearchResultSelection[0]); + CPPUNIT_ASSERT_EQUAL("3545, 3174, 740, 402", mpCallbackRecorder->m_aSearchResultSelection[0]); // Search next @@ -681,8 +680,7 @@ void LOKitSearchTest::testSearchIn2MixedObjects() CPPUNIT_ASSERT_EQUAL(size_t(1), mpCallbackRecorder->m_aSearchResultSelection.size()); CPPUNIT_ASSERT_EQUAL(size_t(1), mpCallbackRecorder->m_aSearchResultPart.size()); - CPPUNIT_ASSERT_EQUAL(OString("3546, 3174, 738, 402"), - mpCallbackRecorder->m_aSearchResultSelection[0]); + CPPUNIT_ASSERT_EQUAL("3545, 3174, 740, 402", mpCallbackRecorder->m_aSearchResultSelection[0]); } // Test searching in document with mixed objects. We have 6 objects. diff --git a/svx/qa/unit/customshapes.cxx b/svx/qa/unit/customshapes.cxx index efe322d54e76..86bae7d50447 100644 --- a/svx/qa/unit/customshapes.cxx +++ b/svx/qa/unit/customshapes.cxx @@ -406,10 +406,6 @@ CPPUNIT_TEST_FIXTURE(CustomshapesTest, testTdf145111_Fontwork_rendering_font_siz CPPUNIT_TEST_FIXTURE(CustomshapesTest, testTdf145111_anchor_in_Fontwork) { - // The tested positions depend on dpi. - if (!IsDefaultDPI()) - return; - // tdf#145004 In case ScaleX is true in property TextPath, SDRTEXTVERTADJUST is // evaluated and should shift the Fontwork text. That did not work for // 'Top-Left' and 'Bottom-Left'. @@ -423,8 +419,7 @@ CPPUNIT_TEST_FIXTURE(CustomshapesTest, testTdf145111_anchor_in_Fontwork) SdrObjCustomShape& rSdrCustomShape( static_cast<SdrObjCustomShape&>(*SdrObject::getSdrObjectFromXShape(xShape))); - // Without the fix in place top was 2295, but should be 2916 for 96dpi. - // Was 2184, should be 2886 for 120dpi. + // Without the fix in place top was 2295, but should be 2900. tools::Rectangle aBoundRect(rSdrCustomShape.GetCurrentBoundRect()); CPPUNIT_ASSERT_DOUBLES_EQUAL(tools::Long(2916), aBoundRect.Top(), 5); } @@ -434,8 +429,7 @@ CPPUNIT_TEST_FIXTURE(CustomshapesTest, testTdf145111_anchor_in_Fontwork) SdrObjCustomShape& rSdrCustomShape( static_cast<SdrObjCustomShape&>(*SdrObject::getSdrObjectFromXShape(xShape))); - // Without the fix in place top was 10294, but should be 9519 for 96dpi. - // Was 10184, should be 9481 for 120dpi. + // Without the fix in place top was 10294, but should be 9500. tools::Rectangle aBoundRect(rSdrCustomShape.GetCurrentBoundRect()); CPPUNIT_ASSERT_DOUBLES_EQUAL(tools::Long(9519), aBoundRect.Top(), 5); } diff --git a/sw/qa/extras/layout/layout.cxx b/sw/qa/extras/layout/layout.cxx index 0ffdb543fbd9..65b31c5909c6 100644 --- a/sw/qa/extras/layout/layout.cxx +++ b/sw/qa/extras/layout/layout.cxx @@ -3673,7 +3673,7 @@ CPPUNIT_TEST_FIXTURE(SwLayoutWriter, testTdf106234) "type", "PortionType::Margin"); // This was a justified line, without width assertXPath(pXmlDoc, "/root/page/body/txt[2]/SwParaPortion/SwLineLayout[1]/SwGluePortion", - "width", "7881"); + "width", "7882"); } CPPUNIT_TEST_FIXTURE(SwLayoutWriter, testTdf120287b) @@ -3686,7 +3686,7 @@ CPPUNIT_TEST_FIXTURE(SwLayoutWriter, testTdf120287b) assertXPath( pXmlDoc, "/root/page/body/txt[1]/SwParaPortion/SwLineLayout/child::*[@type='PortionType::TabRight']", - "width", "17"); + "width", "19"); } CPPUNIT_TEST_FIXTURE(SwLayoutWriter, testTdf120287c) @@ -3819,7 +3819,7 @@ CPPUNIT_TEST_FIXTURE(SwLayoutWriter, testTdf122607) assertXPath(pXmlDoc, "/root/page[1]/anchored/fly/txt[1]/anchored/fly/tab/row[2]/cell/txt[7]/anchored/" "fly/txt/SwParaPortion/SwLineLayout/child::*[1]", - "width", "428"); + "width", "427"); assertXPath(pXmlDoc, "/root/page[1]/anchored/fly/txt[1]/anchored/fly/tab/row[2]/cell/txt[7]/anchored/" "fly/txt/SwParaPortion/SwLineLayout/child::*[1]", diff --git a/toolkit/source/awt/vclxfont.cxx b/toolkit/source/awt/vclxfont.cxx index 866a362e710f..f7338e79cfd0 100644 --- a/toolkit/source/awt/vclxfont.cxx +++ b/toolkit/source/awt/vclxfont.cxx @@ -156,7 +156,7 @@ sal_Int32 VCLXFont::getStringWidthArray( const OUString& str, css::uno::Sequence vcl::Font aOldFont = pOutDev->GetFont(); pOutDev->SetFont( maFont ); KernArray aDXA; - nRet = pOutDev->GetTextArray( str, &aDXA ); + nRet = basegfx::fround(pOutDev->GetTextArray(str, &aDXA)); rDXArray.realloc(aDXA.size()); sal_Int32* pArray = rDXArray.getArray(); for (size_t i = 0, nLen = aDXA.size(); i < nLen; ++i) diff --git a/vcl/qa/cppunit/complextext.cxx b/vcl/qa/cppunit/complextext.cxx index daf70a1c589d..cfe5d2213d7d 100644 --- a/vcl/qa/cppunit/complextext.cxx +++ b/vcl/qa/cppunit/complextext.cxx @@ -79,7 +79,7 @@ void VclComplexTextTest::testArabic() std::vector<sal_Int32> aRefCharWidths {6, 9, 16, 16, 22, 22, 26, 29, 32, 32, 36, 40, 49, 53, 56, 63, 63, 66, 72, 72}; KernArray aCharWidths; - tools::Long nTextWidth = pOutDev->GetTextArray(aOneTwoThree, &aCharWidths); + tools::Long nTextWidth = basegfx::fround<tools::Long>(pOutDev->GetTextArray(aOneTwoThree, &aCharWidths)); CPPUNIT_ASSERT_EQUAL(aRefCharWidths, aCharWidths.get_subunit_array()); // this sporadically returns 75 or 74 on some of the windows tinderboxes eg. tb73 diff --git a/vcl/source/filter/wmf/emfwr.cxx b/vcl/source/filter/wmf/emfwr.cxx index 45a1a7ce4e27..dfdc3156f838 100644 --- a/vcl/source/filter/wmf/emfwr.cxx +++ b/vcl/source/filter/wmf/emfwr.cxx @@ -880,7 +880,7 @@ void EMFWriter::ImplWriteTextRecord( const Point& rPos, const OUString& rText, K } else { - nNormWidth = maVDev->GetTextArray( rText, &aOwnArray ); + nNormWidth = basegfx::fround<sal_uInt32>(maVDev->GetTextArray(rText, &aOwnArray)); pDX = aOwnArray; } diff --git a/vcl/source/filter/wmf/wmfwr.cxx b/vcl/source/filter/wmf/wmfwr.cxx index 335773728b60..c35d7236c9d9 100644 --- a/vcl/source/filter/wmf/wmfwr.cxx +++ b/vcl/source/filter/wmf/wmfwr.cxx @@ -1198,7 +1198,7 @@ void WMFWriter::WriteRecords( const GDIMetaFile & rMTF ) pVirDev->SetFont( aSrcFont ); const sal_Int32 nLen = aTemp.getLength(); KernArray aDXAry; - const sal_Int32 nNormSize = pVirDev->GetTextArray( aTemp, nLen ? &aDXAry : nullptr ); + const sal_Int32 nNormSize = basegfx::fround(pVirDev->GetTextArray( aTemp, nLen ? &aDXAry : nullptr )); if (nLen && nNormSize == 0) { OSL_FAIL("Impossible div by 0 action: MetaStretchTextAction!"); diff --git a/vcl/source/gdi/textlayout.cxx b/vcl/source/gdi/textlayout.cxx index 0ee1c9ba5faf..ce681a2e9eea 100644 --- a/vcl/source/gdi/textlayout.cxx +++ b/vcl/source/gdi/textlayout.cxx @@ -166,7 +166,7 @@ namespace vcl return 0; // retrieve the character widths from the reference device - tools::Long nTextWidth = m_rReferenceDevice.GetTextArray( _rText, _pDXAry, _nStartIndex, _nLength ); + tools::Long nTextWidth = basegfx::fround<tools::Long>(m_rReferenceDevice.GetTextArray( _rText, _pDXAry, _nStartIndex, _nLength )); #if OSL_DEBUG_LEVEL > 1 if ( _pDXAry ) { diff --git a/vcl/source/outdev/map.cxx b/vcl/source/outdev/map.cxx index d7ddaf3ccd86..3359cc70c210 100644 --- a/vcl/source/outdev/map.cxx +++ b/vcl/source/outdev/map.cxx @@ -272,6 +272,19 @@ static tools::Long ImplPixelToLogic(tools::Long n, tools::Long nDPI, tools::Long return n; } +static double ImplPixelToLogicDouble(double n, tools::Long nDPI, tools::Long nMapNum, + tools::Long nMapDenom) +{ + assert(nDPI > 0); + if (nMapNum == 0) + return 0; + + n *= nMapDenom; + n /= nDPI; + n /= nMapNum; + return n; +} + tools::Long OutputDevice::ImplLogicXToDevicePixel( tools::Long nX ) const { if ( !mbMap ) @@ -314,6 +327,14 @@ tools::Long OutputDevice::ImplDevicePixelToLogicWidth( tools::Long nWidth ) cons return ImplPixelToLogic(nWidth, mnDPIX, maMapRes.mnMapScNumX, maMapRes.mnMapScDenomX); } +SAL_DLLPRIVATE double OutputDevice::ImplDevicePixelToLogicWidthDouble(double nWidth) const +{ + if (!mbMap) + return nWidth; + + return ImplPixelToLogicDouble(nWidth, mnDPIX, maMapRes.mnMapScNumX, maMapRes.mnMapScDenomX); +} + tools::Long OutputDevice::ImplDevicePixelToLogicHeight( tools::Long nHeight ) const { if ( !mbMap ) @@ -322,6 +343,14 @@ tools::Long OutputDevice::ImplDevicePixelToLogicHeight( tools::Long nHeight ) co return ImplPixelToLogic(nHeight, mnDPIY, maMapRes.mnMapScNumY, maMapRes.mnMapScDenomY); } +double OutputDevice::ImplDevicePixelToLogicHeightDouble(double nHeight) const +{ + if (!mbMap) + return nHeight; + + return ImplPixelToLogicDouble(nHeight, mnDPIY, maMapRes.mnMapScNumY, maMapRes.mnMapScDenomY); +} + Point OutputDevice::ImplLogicToDevicePixel( const Point& rLogicPt ) const { if ( !mbMap ) diff --git a/vcl/source/outdev/text.cxx b/vcl/source/outdev/text.cxx index bbbb63f2326d..0ff3ac91f177 100644 --- a/vcl/source/outdev/text.cxx +++ b/vcl/source/outdev/text.cxx @@ -892,11 +892,15 @@ tools::Long OutputDevice::GetTextWidth( const OUString& rStr, sal_Int32 nIndex, vcl::text::TextLayoutCache const*const pLayoutCache, SalLayoutGlyphs const*const pSalLayoutCache) const { + double nWidth = GetTextWidthDouble(rStr, nIndex, nLen, pLayoutCache, pSalLayoutCache); + return basegfx::fround<tools::Long>(nWidth); +} - tools::Long nWidth = GetTextArray( rStr, nullptr, nIndex, - nLen, false, pLayoutCache, pSalLayoutCache ); - - return nWidth; +double OutputDevice::GetTextWidthDouble(const OUString& rStr, sal_Int32 nIndex, sal_Int32 nLen, + vcl::text::TextLayoutCache const* const pLayoutCache, + SalLayoutGlyphs const* const pSalLayoutCache) const +{ + return GetTextArray(rStr, nullptr, nIndex, nLen, false, pLayoutCache, pSalLayoutCache); } tools::Long OutputDevice::GetTextHeight() const @@ -912,6 +916,16 @@ tools::Long OutputDevice::GetTextHeight() const return nHeight; } +double OutputDevice::GetTextHeightDouble() const +{ + if (!InitFont()) + return 0; + + tools::Long nHeight = mpFontInstance->mnLineHeight + mnEmphasisAscent + mnEmphasisDescent; + + return ImplDevicePixelToLogicHeightDouble(nHeight); +} + float OutputDevice::approximate_char_width() const { //note pango uses "The quick brown fox jumps over the lazy dog." for english @@ -960,7 +974,7 @@ void OutputDevice::DrawTextArray( const Point& rStartPt, const OUString& rStr, mpAlphaVDev->DrawTextArray( rStartPt, rStr, pDXAry, pKashidaAry, nIndex, nLen, flags ); } -tools::Long OutputDevice::GetTextArray( const OUString& rStr, KernArray* pKernArray, +double OutputDevice::GetTextArray( const OUString& rStr, KernArray* pKernArray, sal_Int32 nIndex, sal_Int32 nLen, bool bCaret, vcl::text::TextLayoutCache const*const pLayoutCache, SalLayoutGlyphs const*const pSalLayoutCache) const @@ -1048,7 +1062,7 @@ tools::Long OutputDevice::GetTextArray( const OUString& rStr, KernArray* pKernAr if (mbMap) { for (int i = 0; i < nLen; ++i) - (*pDXAry)[i] = ImplDevicePixelToLogicWidth( (*pDXAry)[i] * nSubPixelFactor ); + (*pDXAry)[i] = ImplDevicePixelToLogicWidthDouble((*pDXAry)[i] * nSubPixelFactor); } else if (nSubPixelFactor) { @@ -1057,10 +1071,7 @@ tools::Long OutputDevice::GetTextArray( const OUString& rStr, KernArray* pKernAr } } - if (mbMap) - nWidth = ImplDevicePixelToLogicWidth( nWidth ); - - return basegfx::fround<tools::Long>(nWidth); + return ImplDevicePixelToLogicWidthDouble(nWidth); #endif /* VCL_FLOAT_DEVICE_PIXEL */ } commit 9059240ea11f8c16c3fb9d40a85650d187ad19db Author: Mike Kaganski <mike.kagan...@collabora.com> AuthorDate: Wed Apr 10 12:15:55 2024 +0500 Commit: Mike Kaganski <mike.kagan...@collabora.com> CommitDate: Mon Apr 29 10:02:52 2024 +0500 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.kagan...@collabora.com> diff --git a/drawinglayer/source/primitive2d/textlayoutdevice.cxx b/drawinglayer/source/primitive2d/textlayoutdevice.cxx index ea9fed02a20f..e36abffe2e64 100644 --- a/drawinglayer/source/primitive2d/textlayoutdevice.cxx +++ b/drawinglayer/source/primitive2d/textlayoutdevice.cxx @@ -260,15 +260,9 @@ basegfx::B2DRange TextLayouterDevice::getTextBoundRect(const OUString& rText, sa if (nTextLength) { - ::tools::Rectangle aRect; - + basegfx::B2DRange aRect; mrDevice.GetTextBoundRect(aRect, rText, nIndex, nIndex, nLength); - - // #i104432#, #i102556# take empty results into account - if (!aRect.IsEmpty()) - { - return vcl::unotools::b2DRectangleFromRectangle(aRect); - } + return aRect; } return basegfx::B2DRange(); diff --git a/include/vcl/outdev.hxx b/include/vcl/outdev.hxx index 6b864213a66d..8bcf883c8fc9 100644 --- a/include/vcl/outdev.hxx +++ b/include/vcl/outdev.hxx @@ -54,6 +54,7 @@ #include <vcl/settings.hxx> #include <vcl/vclreferencebase.hxx> +#include <basegfx/range/b2drectangle.hxx> #include <basegfx/numeric/ftools.hxx> #include <basegfx/vector/b2enums.hxx> #include <basegfx/polygon/b2dpolypolygon.hxx> @@ -960,6 +961,11 @@ public: sal_uLong nLayoutWidth = 0, KernArraySpan aDXArray = KernArraySpan(), o3tl::span<const sal_Bool> pKashidaArray = {}, const SalLayoutGlyphs* pGlyphs = nullptr ) const; + bool GetTextBoundRect( basegfx::B2DRectangle& rRect, + const OUString& rStr, sal_Int32 nBase = 0, sal_Int32 nIndex = 0, sal_Int32 nLen = -1, + sal_uLong nLayoutWidth = 0, KernArraySpan aDXArray = KernArraySpan(), + o3tl::span<const sal_Bool> pKashidaArray = {}, + const SalLayoutGlyphs* pGlyphs = nullptr ) const; tools::Rectangle ImplGetTextBoundRect( const SalLayout& ) const; @@ -1627,6 +1633,7 @@ public: SAL_WARN_UNUSED_RESULT tools::Polygon PixelToLogic(const tools::Polygon& rDevicePoly) const; SAL_WARN_UNUSED_RESULT tools::PolyPolygon PixelToLogic(const tools::PolyPolygon& rDevicePolyPoly) const; SAL_WARN_UNUSED_RESULT basegfx::B2DPolyPolygon PixelToLogic(const basegfx::B2DPolyPolygon& rDevicePolyPoly) const; + SAL_WARN_UNUSED_RESULT basegfx::B2DRectangle PixelToLogic(const basegfx::B2DRectangle& rDeviceRect) const; SAL_WARN_UNUSED_RESULT vcl::Region PixelToLogic(const vcl::Region& rDeviceRegion) const; SAL_WARN_UNUSED_RESULT Point PixelToLogic(const Point& rDevicePt, const MapMode& rMapMode) const; SAL_WARN_UNUSED_RESULT Size PixelToLogic(const Size& rDeviceSize, const MapMode& rMapMode) const; diff --git a/include/vcl/vcllayout.hxx b/include/vcl/vcllayout.hxx index 4705a44d9b92..887480ce3ee9 100644 --- a/include/vcl/vcllayout.hxx +++ b/include/vcl/vcllayout.hxx @@ -20,6 +20,7 @@ #pragma once #include <basegfx/polygon/b2dpolypolygon.hxx> +#include <basegfx/range/b2drectangle.hxx> #include <i18nlangtag/languagetag.hxx> #include <tools/gen.hxx> #include <tools/degree.hxx> @@ -103,7 +104,9 @@ public: virtual bool GetNextGlyph(const GlyphItem** pGlyph, DevicePoint& rPos, int& nStart, const LogicalFontInstance** ppGlyphFont = nullptr) const = 0; virtual bool GetOutline(basegfx::B2DPolyPolygonVector&) const; - bool GetBoundRect(tools::Rectangle&) const; + bool GetBoundRect(basegfx::B2DRectangle&) const; + + static tools::Rectangle BoundRect2Rectangle(basegfx::B2DRectangle&); virtual SalLayoutGlyphs GetGlyphs() const; diff --git a/svgio/qa/cppunit/SvgImportTest.cxx b/svgio/qa/cppunit/SvgImportTest.cxx index d61c5c761f79..7a8706556129 100644 --- a/svgio/qa/cppunit/SvgImportTest.cxx +++ b/svgio/qa/cppunit/SvgImportTest.cxx @@ -41,6 +41,8 @@ protected: void checkRectPrimitive(Primitive2DSequence const & rPrimitive); Primitive2DSequence parseSvg(std::u16string_view aSource); + void assertXPathDouble(const xmlDocUniquePtr& pXmlDoc, const OString& rXPath, + const OString& rAttribute, double nExpectedValue, double delta); }; Primitive2DSequence Test::parseSvg(std::u16string_view aSource) @@ -82,6 +84,13 @@ void Test::checkRectPrimitive(Primitive2DSequence const & rPrimitive) } +void Test::assertXPathDouble(const xmlDocUniquePtr& pXmlDoc, const OString& rXPath, + const OString& rAttribute, double nExpectedValue, double delta) +{ + auto sVal = getXPath(pXmlDoc, rXPath, rAttribute); + CPPUNIT_ASSERT_DOUBLES_EQUAL(nExpectedValue, sVal.toDouble(), delta); +} + bool arePrimitive2DSequencesEqual(const Primitive2DSequence& rA, const Primitive2DSequence& rB) { return std::equal(rA.begin(), rA.end(), rB.begin(), rB.end(), diff --git a/vcl/skia/gdiimpl.cxx b/vcl/skia/gdiimpl.cxx index 84b625115648..c40a010173a7 100644 --- a/vcl/skia/gdiimpl.cxx +++ b/vcl/skia/gdiimpl.cxx @@ -2131,7 +2131,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 c8c2d6ca1093..e801ac3057ca 100644 --- a/vcl/source/gdi/sallayout.cxx +++ b/vcl/source/gdi/sallayout.cxx @@ -221,11 +221,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; DevicePoint aPos; @@ -241,28 +240,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 67414cb2976c..d7ddaf3ccd86 100644 --- a/vcl/source/outdev/map.cxx +++ b/vcl/source/outdev/map.cxx @@ -1230,6 +1230,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 9e93a5775857..bbbb63f2326d 100644 --- a/vcl/source/outdev/text.cxx +++ b/vcl/source/outdev/text.cxx @@ -23,6 +23,7 @@ #include <rtl/ustrbuf.hxx> #include <sal/log.hxx> #include <basegfx/matrix/b2dhommatrix.hxx> +#include <basegfx/matrix/b2dhommatrixtools.hxx> #include <comphelper/processfactory.hxx> #include <tools/lineend.hxx> #include <tools/debug.hxx> @@ -233,7 +234,11 @@ bool OutputDevice::ImplDrawRotateText( SalLayout& rSalLayout ) tools::Rectangle aBoundRect; rSalLayout.DrawBase() = DevicePoint( 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 tools::Long nRight = rSalLayout.GetTextWidth(); @@ -2326,9 +2331,22 @@ bool OutputDevice::GetTextBoundRect( tools::Rectangle& rRect, sal_uLong nLayoutWidth, KernArraySpan pDXAry, o3tl::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, + o3tl::span<const sal_Bool> pKashidaAry, + const SalLayoutGlyphs* pGlyphs) const { bool bRet = false; - rRect.SetEmpty(); + rRect.reset(); std::unique_ptr<SalLayout> pSalLayout; const Point aPoint; @@ -2352,18 +2370,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 ); - DevicePoint aPos = pSalLayout->GetDrawPosition(DevicePoint(nXOffset, 0)); - aRotatedOfs -= Point(aPos.getX(), aPos.getY()); - aPixelRect += aRotatedOfs; + basegfx::B2DPoint aPos = pSalLayout->GetDrawPosition(basegfx::B2DPoint(nXOffset, 0)); + 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 321587db8137..fb96cfa68659 100644 --- a/vcl/win/gdi/DWriteTextRenderer.cxx +++ b/vcl/win/gdi/DWriteTextRenderer.cxx @@ -238,8 +238,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. commit ddd6d8bd2ed2b37492d7660df1769618cea17105 Author: Mike Kaganski <mike.kagan...@collabora.com> AuthorDate: Fri Apr 19 10:31:39 2024 +0500 Commit: Mike Kaganski <mike.kagan...@collabora.com> CommitDate: Mon Apr 29 10:02:52 2024 +0500 Add a unit test for commit 3f0220f18a66630e06e3c128980f21a5722f49ca (Handle empty range properly, 2024-04-18) Change-Id: Ifea60ace8ff864ef092e6a62177d5926ceb60de3 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/166278 Tested-by: Jenkins Reviewed-by: Mike Kaganski <mike.kagan...@collabora.com> diff --git a/sw/qa/extras/ww8export/data/empty_group.docx b/sw/qa/extras/ww8export/data/empty_group.docx new file mode 100644 index 000000000000..a3454746c5e0 Binary files /dev/null and b/sw/qa/extras/ww8export/data/empty_group.docx differ diff --git a/sw/qa/extras/ww8export/ww8export4.cxx b/sw/qa/extras/ww8export/ww8export4.cxx index efb198ebae00..b4116ff2bbac 100644 --- a/sw/qa/extras/ww8export/ww8export4.cxx +++ b/sw/qa/extras/ww8export/ww8export4.cxx @@ -19,8 +19,11 @@ #include <comphelper/sequenceashashmap.hxx> #include <o3tl/string_view.hxx> +#include <svx/svdpage.hxx> #include <docsh.hxx> +#include <drawdoc.hxx> +#include <IDocumentDrawModelAccess.hxx> #include <IDocumentSettingAccess.hxx> #include <unotxdoc.hxx> @@ -78,6 +81,27 @@ DECLARE_WW8EXPORT_TEST(testTdf104704_mangledFooter, "tdf104704_mangledFooter.odt CPPUNIT_ASSERT_EQUAL(2, getPages()); } +CPPUNIT_TEST_FIXTURE(Test, testEmptyGroup) +{ + // Given a document with an empty group + createSwDoc("empty_group.docx"); + + CPPUNIT_ASSERT_EQUAL(1, getPages()); + CPPUNIT_ASSERT_EQUAL(1, getShapes()); + SwXTextDocument* pTextDoc = dynamic_cast<SwXTextDocument*>(mxComponent.get()); + CPPUNIT_ASSERT(pTextDoc); + SwDoc* pDoc = pTextDoc->GetDocShell()->GetDoc(); + SdrPage* pPage = pDoc->getIDocumentDrawModelAccess().GetDrawModel()->GetPage(0); + SdrObject* pObject = pPage->GetObj(0); + + CPPUNIT_ASSERT_EQUAL(OUString("Empty group"), pObject->GetName()); + CPPUNIT_ASSERT(pObject->IsGroupObject()); + CPPUNIT_ASSERT_EQUAL(size_t(0), pObject->GetSubList()->GetObjCount()); + + // it must not assert/crash on save + saveAndReload(OUString::createFromAscii(mpFilter)); +} + CPPUNIT_PLUGIN_IMPLEMENT(); /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ commit b2509d82c0b63d001f0f7a946e0d4c926158f6e2 Author: Mike Kaganski <mike.kagan...@collabora.com> AuthorDate: Wed Apr 17 21:16:23 2024 +0100 Commit: Mike Kaganski <mike.kagan...@collabora.com> CommitDate: Mon Apr 29 10:02:52 2024 +0500 Handle empty range properly Since commit 690526f95e3ee4fd25bb2c987e093543e4bc435b (Generalize basegfx::fround for templated return type, 2024-04-14), an assertion could fail for certain case, like include/o3tl/unit_conversion.hxx:75: sal_Int64 o3tl::detail::MulDiv(I, sal_Int64, sal_Int64) [I = long]: Assertion `isBetween(n, (SAL_MIN_INT64 + d / 2) / m, (SAL_MAX_INT64 - d / 2) / m)' The problem was unchecked case of empty B2DRange. Change-Id: Ice9125ea557b73a7fabf64bc1ad9368f503ad525 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/166101 Tested-by: Jenkins Reviewed-by: Caolán McNamara <caolan.mcnam...@collabora.com> diff --git a/filter/source/msfilter/eschesdo.cxx b/filter/source/msfilter/eschesdo.cxx index ca0dc8a4a14d..2f8f84bb9dc4 100644 --- a/filter/source/msfilter/eschesdo.cxx +++ b/filter/source/msfilter/eschesdo.cxx @@ -1151,10 +1151,19 @@ void ImplEESdrObject::Init() { // if it's a group, the unrotated range is needed for that group const basegfx::B2DRange aUnrotatedRange(getUnrotatedGroupBoundRange(mXShape)); - const Point aNewP(basegfx::fround<tools::Long>(aUnrotatedRange.getMinX()), basegfx::fround<tools::Long>(aUnrotatedRange.getMinY())); - const Size aNewS(basegfx::fround<tools::Long>(aUnrotatedRange.getWidth()), basegfx::fround<tools::Long>(aUnrotatedRange.getHeight())); + if (aUnrotatedRange.isEmpty()) + { + SetRect(tools::Rectangle()); + } + else + { + const Point aNewP(basegfx::fround<tools::Long>(aUnrotatedRange.getMinX()), + basegfx::fround<tools::Long>(aUnrotatedRange.getMinY())); + const Size aNewS(basegfx::fround<tools::Long>(aUnrotatedRange.getWidth()), + basegfx::fround<tools::Long>(aUnrotatedRange.getHeight())); - SetRect(ImplEESdrWriter::ImplMapPoint(aNewP), ImplEESdrWriter::ImplMapSize(aNewS)); + SetRect(ImplEESdrWriter::ImplMapPoint(aNewP), ImplEESdrWriter::ImplMapSize(aNewS)); + } } else { commit 02f22e016e0e7bda4c2f3c910ce3026e6672a117 Author: Mike Kaganski <mike.kagan...@collabora.com> AuthorDate: Tue Apr 16 23:10:45 2024 +0500 Commit: Mike Kaganski <mike.kagan...@collabora.com> CommitDate: Mon Apr 29 10:02:51 2024 +0500 Drop FRound, and use generalized basegfx::fround Change-Id: I7447e649dc3ef4e51242f69c7486a3e84e103d2e Reviewed-on: https://gerrit.libreoffice.org/c/core/+/166159 Tested-by: Jenkins Reviewed-by: Mike Kaganski <mike.kagan...@collabora.com> diff --git a/cui/source/dialogs/cuigrfflt.cxx b/cui/source/dialogs/cuigrfflt.cxx index c67ee92d141c..0ffb50342936 100644 --- a/cui/source/dialogs/cuigrfflt.cxx +++ b/cui/source/dialogs/cuigrfflt.cxx @@ -192,8 +192,8 @@ Graphic GraphicFilterMosaic::GetFilteredGraphic( const Graphic& rGraphic, Graphic aRet; tools::Long nTileWidth = static_cast<tools::Long>(mxMtrWidth->get_value(FieldUnit::PIXEL)); tools::Long nTileHeight = static_cast<tools::Long>(mxMtrHeight->get_value(FieldUnit::PIXEL)); - const Size aSize( std::max( FRound( nTileWidth * fScaleX ), tools::Long(1) ), - std::max( FRound( nTileHeight * fScaleY ), tools::Long(1) ) ); + const Size aSize( std::max( basegfx::fround<tools::Long>( nTileWidth * fScaleX ), tools::Long(1) ), + std::max( basegfx::fround<tools::Long>( nTileHeight * fScaleY ), tools::Long(1) ) ); if( rGraphic.IsAnimated() ) { @@ -270,7 +270,7 @@ GraphicFilterSolarize::GraphicFilterSolarize(weld::Window* pParent, const Graphi , mxMtrThreshold(m_xBuilder->weld_metric_spin_button("value", FieldUnit::PERCENT)) , mxCbxInvert(m_xBuilder->weld_check_button("invert")) { - mxMtrThreshold->set_value(FRound(cGreyThreshold / 2.55), FieldUnit::PERCENT); + mxMtrThreshold->set_value(basegfx::fround(cGreyThreshold / 2.55), FieldUnit::PERCENT); mxMtrThreshold->connect_value_changed(LINK(this, GraphicFilterSolarize, EditModifyHdl)); mxCbxInvert->set_active(bInvert); @@ -290,7 +290,7 @@ IMPL_LINK_NOARG(GraphicFilterSolarize, EditModifyHdl, weld::MetricSpinButton&, v Graphic GraphicFilterSolarize::GetFilteredGraphic( const Graphic& rGraphic, double, double ) { Graphic aRet; - sal_uInt8 nGreyThreshold = static_cast<sal_uInt8>(FRound(mxMtrThreshold->get_value(FieldUnit::PERCENT) * 2.55)); + sal_uInt8 nGreyThreshold = basegfx::fround<sal_uInt8>(mxMtrThreshold->get_value(FieldUnit::PERCENT) * 2.55); if( rGraphic.IsAnimated() ) { diff --git a/filter/source/svg/svgwriter.cxx b/filter/source/svg/svgwriter.cxx index e4420dc27e71..ff444a6ce284 100644 --- a/filter/source/svg/svgwriter.cxx +++ b/filter/source/svg/svgwriter.cxx @@ -2184,7 +2184,7 @@ void SVGActionWriter::ImplWriteShape( const SVGShapeDescriptor& rShape ) for( size_t k = 0; k < rShape.maDashArray.size(); ++k ) { - const sal_Int32 nDash = ImplMap( FRound( rShape.maDashArray[ k ] ) ); + const sal_Int32 nDash = ImplMap(basegfx::fround(rShape.maDashArray[k])); if( k ) aDashArrayStr.append(","); @@ -2546,8 +2546,8 @@ void SVGActionWriter::ImplWriteMask(GDIMetaFile& rMtf, const Point& rDestPt, con if (fScaleX != 1.0 || fScaleY != 1.0) { rMtf.Scale(fScaleX, fScaleY); - aSrcPt.setX(FRound(aSrcPt.X() * fScaleX)); - aSrcPt.setY(FRound(aSrcPt.Y() * fScaleY)); + aSrcPt.setX(basegfx::fround<tools::Long>(aSrcPt.X() * fScaleX)); + aSrcPt.setY(basegfx::fround<tools::Long>(aSrcPt.Y() * fScaleY)); } nMoveX = rDestPt.X() - aSrcPt.X(); @@ -2747,7 +2747,7 @@ void SVGActionWriter::ImplWriteText( const Point& rPos, const OUString& rText, const double fFactor = static_cast<double>(nWidth) / aNormSize.Width(); for( i = 0; i < ( nLen - 1 ); i++ ) - aTmpArray.set(i, FRound(aTmpArray[i] * fFactor)); + aTmpArray.set(i, basegfx::fround(aTmpArray[i] * fFactor)); } else { @@ -2811,11 +2811,11 @@ void SVGActionWriter::ImplWriteText( const Point& rPos, const OUString& rText, return; tools::Polygon aPoly( 4 ); - const tools::Long nLineHeight = std::max<tools::Long>( FRound( aMetric.GetLineHeight() * 0.05 ), 1 ); + const tools::Long nLineHeight = std::max<tools::Long>( basegfx::fround<tools::Long>( aMetric.GetLineHeight() * 0.05 ), 1 ); if( rFont.GetStrikeout() ) { - const tools::Long nYLinePos = aBaseLinePos.Y() - FRound( aMetric.GetAscent() * 0.26 ); + const tools::Long nYLinePos = aBaseLinePos.Y() - basegfx::fround<tools::Long>( aMetric.GetAscent() * 0.26 ); aPoly[ 0 ].setX( aBaseLinePos.X() ); aPoly[ 0 ].setY( nYLinePos - ( nLineHeight >> 1 ) ); aPoly[ 1 ].setX( aBaseLinePos.X() + aNormSize.Width() - 1 ); aPoly[ 1 ].setY( aPoly[ 0 ].Y() ); @@ -3323,8 +3323,8 @@ void SVGActionWriter::ImplWriteActions( const GDIMetaFile& rMtf, // i.e. invisible line, because it makes it visible, // resulting an extra line behind the normal shape line if ( aNewLineColor.GetAlpha() > 0 ) - aNewLineColor.SetAlpha( 255 - sal::static_int_cast<sal_uInt8>( FRound( pA->GetTransparence() * 2.55 ) ) ); - aNewFillColor.SetAlpha( 255 - sal::static_int_cast<sal_uInt8>( FRound( pA->GetTransparence() * 2.55 ) ) ); + aNewLineColor.SetAlpha( 255 - basegfx::fround<sal_uInt8>( pA->GetTransparence() * 2.55 ) ); + aNewFillColor.SetAlpha( 255 - basegfx::fround<sal_uInt8>( pA->GetTransparence() * 2.55 ) ); maAttributeWriter.AddPaintAttr( aNewLineColor, aNewFillColor ); ImplWritePolyPolygon( rPolyPoly, false ); @@ -3435,7 +3435,7 @@ void SVGActionWriter::ImplWriteActions( const GDIMetaFile& rMtf, mapCurShape->maShapePolyPoly = aShapePolyPoly; mapCurShape->maShapeFillColor = aFill.getFillColor(); - mapCurShape->maShapeFillColor.SetAlpha( 255 - static_cast<sal_uInt8>(FRound( 255.0 * aFill.getTransparency() )) ); + mapCurShape->maShapeFillColor.SetAlpha( 255 - basegfx::fround<sal_uInt8>( 255.0 * aFill.getTransparency() ) ); if( bGradient ) { @@ -3525,8 +3525,8 @@ void SVGActionWriter::ImplWriteActions( const GDIMetaFile& rMtf, } mapCurShape->maShapeLineColor = mpVDev->GetLineColor(); - mapCurShape->maShapeLineColor.SetAlpha( 255 - static_cast<sal_uInt8>(FRound( aStroke.getTransparency() * 255.0 )) ); - mapCurShape->mnStrokeWidth = FRound( aStroke.getStrokeWidth() ); + mapCurShape->maShapeLineColor.SetAlpha( 255 - basegfx::fround<sal_uInt8>( aStroke.getTransparency() * 255.0 ) ); + mapCurShape->mnStrokeWidth = basegfx::fround(aStroke.getStrokeWidth()); aStroke.getDashArray( mapCurShape->maDashArray ); // added support for LineJoin diff --git a/include/basegfx/numeric/ftools.hxx b/include/basegfx/numeric/ftools.hxx index 28efe2770b74..b286c847968c 100644 --- a/include/basegfx/numeric/ftools.hxx +++ b/include/basegfx/numeric/ftools.hxx @@ -35,41 +35,25 @@ namespace basegfx @return the nearest integer */ - inline sal_Int32 fround32( double fVal ) + template <class Int = sal_Int32> + inline std::enable_if_t<std::is_integral_v<Int>, Int> fround(double fVal) { if (fVal >= 0.0) { - if (fVal >= std::numeric_limits<sal_Int32>::max() - .5) - return std::numeric_limits<sal_Int32>::max(); - return static_cast<sal_Int32>(fVal + .5); + if (fVal >= static_cast<double>(std::numeric_limits<Int>::max()) - 0.5) + return std::numeric_limits<Int>::max(); + return static_cast<Int>(fVal + .5); } - if (fVal <= std::numeric_limits<sal_Int32>::min() + .5) - return std::numeric_limits<sal_Int32>::min(); - return static_cast<sal_Int32>(fVal - .5); + if (fVal <= static_cast<double>(std::numeric_limits<Int>::min()) + 0.5) + return std::numeric_limits<Int>::min(); + return static_cast<Int>(fVal - .5); } /** Round double to nearest integer @return the nearest 64 bit integer */ - inline sal_Int64 fround64( double fVal ) - { - return fVal > 0.0 ? static_cast<sal_Int64>( fVal + .5 ) : -static_cast<sal_Int64>( -fVal + .5 ); - } - - /** Round double to nearest integer - - @return the nearest integer - */ - template <class Int = sal_Int32> - inline std::enable_if_t<std::is_integral_v<Int> && std::is_signed_v<Int>, Int> - fround(double fVal) - { - if constexpr (sizeof(Int) == sizeof(sal_Int64)) - return fround64(fVal); - else - return fround32(fVal); - } + inline sal_Int64 fround64(double fVal) { return fround<sal_Int64>(fVal); } /** Prune a small epsilon range around zero. diff --git a/include/svx/svdtrans.hxx b/include/svx/svdtrans.hxx index 0087f5407f81..88bbfc6fa1ed 100644 --- a/include/svx/svdtrans.hxx +++ b/include/svx/svdtrans.hxx @@ -94,27 +94,27 @@ inline void ResizePoint(Point& rPnt, const Point& rRef, const Fraction& xFract, { double nxFract = xFract.IsValid() ? static_cast<double>(xFract) : 1.0; double nyFract = yFract.IsValid() ? static_cast<double>(yFract) : 1.0; - rPnt.setX(rRef.X() + FRound( (rPnt.X() - rRef.X()) * nxFract )); - rPnt.setY(rRef.Y() + FRound( (rPnt.Y() - rRef.Y()) * nyFract )); + rPnt.setX(rRef.X() + basegfx::fround<tools::Long>((rPnt.X() - rRef.X()) * nxFract)); + rPnt.setY(rRef.Y() + basegfx::fround<tools::Long>((rPnt.Y() - rRef.Y()) * nyFract)); } inline void RotatePoint(Point& rPnt, const Point& rRef, double sn, double cs) { tools::Long dx=rPnt.X()-rRef.X(); tools::Long dy=rPnt.Y()-rRef.Y(); - rPnt.setX(FRound(rRef.X()+dx*cs+dy*sn)); - rPnt.setY(FRound(rRef.Y()+dy*cs-dx*sn)); + rPnt.setX(basegfx::fround<tools::Long>(rRef.X() + dx * cs + dy * sn)); + rPnt.setY(basegfx::fround<tools::Long>(rRef.Y() + dy * cs - dx * sn)); } inline void ShearPoint(Point& rPnt, const Point& rRef, double tn, bool bVShear) { if (!bVShear) { // Horizontal if (rPnt.Y()!=rRef.Y()) { // else not needed - rPnt.AdjustX(-FRound((rPnt.Y()-rRef.Y())*tn)); + rPnt.AdjustX(basegfx::fround<tools::Long>((rRef.Y() - rPnt.Y()) * tn)); } } else { // or else vertical if (rPnt.X()!=rRef.X()) { // else not needed - rPnt.AdjustY(-FRound((rPnt.X()-rRef.X())*tn)); + rPnt.AdjustY(basegfx::fround<tools::Long>((rRef.X() - rPnt.X()) * tn)); } } } diff --git a/include/tools/helpers.hxx b/include/tools/helpers.hxx index 5f61ba80836c..d0fb08f70e5b 100644 --- a/include/tools/helpers.hxx +++ b/include/tools/helpers.hxx @@ -71,14 +71,6 @@ inline sal_uInt32 AlignedWidth4Bytes(sal_uInt32 nWidthBits) return (nWidthBits >> 5) << 2; } -inline tools::Long FRound( double fVal ) -{ - return fVal > 0.0 - ? fVal == double(std::numeric_limits<tools::Long>::max()) - ? std::numeric_limits<tools::Long>::max() : static_cast<tools::Long>( fVal + 0.5 ) - : static_cast<tools::Long>( fVal - 0.5 ); -} - //valid range: (-180,180] template <typename T> [[nodiscard]] inline typename std::enable_if<std::is_signed<T>::value, T>::type diff --git a/include/vcl/bitmap.hxx b/include/vcl/bitmap.hxx index 123b48fcd752..19dc78bc5d76 100644 --- a/include/vcl/bitmap.hxx +++ b/include/vcl/bitmap.hxx @@ -20,6 +20,9 @@ #ifndef INCLUDED_VCL_BITMAP_HXX #define INCLUDED_VCL_BITMAP_HXX +#include <sal/config.h> + +#include <basegfx/numeric/ftools.hxx> #include <tools/degree.hxx> #include <vcl/checksum.hxx> #include <vcl/dllapi.h> @@ -32,7 +35,10 @@ #include <memory> -#define GAMMA( _def_cVal, _def_InvGamma ) (static_cast<sal_uInt8>(MinMax(FRound(pow( _def_cVal/255.0,_def_InvGamma)*255.0),0,255))) +inline sal_uInt8 GAMMA(double _def_cVal, double _def_InvGamma) +{ + return basegfx::fround<sal_uInt8>(pow(_def_cVal / 255.0, _def_InvGamma) * 255.0); +} class Color; diff --git a/sc/source/core/data/drwlayer.cxx b/sc/source/core/data/drwlayer.cxx index 20da0fcac2bf..c4bd1b2f90b1 100644 --- a/sc/source/core/data/drwlayer.cxx +++ b/sc/source/core/data/drwlayer.cxx @@ -963,10 +963,10 @@ void ScDrawLayer::InitializeCellAnchoredObj(SdrObject* pObj, ScDrawObjData& rDat static_cast<SdrPathObj*>(pObj)->GetPathPoly().getB2DPolygon(0)); const basegfx::B2DPoint aB2DPoint0(aPoly.getB2DPoint(0)); const basegfx::B2DPoint aB2DPoint1(aPoly.getB2DPoint(1)); - const Point aPointLT(FRound(std::min(aB2DPoint0.getX(), aB2DPoint1.getX())), - FRound(std::min(aB2DPoint0.getY(), aB2DPoint1.getY()))); - const Point aPointRB(FRound(std::max(aB2DPoint0.getX(), aB2DPoint1.getX())), - FRound(std::max(aB2DPoint0.getY(), aB2DPoint1.getY()))); + const Point aPointLT(basegfx::fround<tools::Long>(std::min(aB2DPoint0.getX(), aB2DPoint1.getX())), + basegfx::fround<tools::Long>(std::min(aB2DPoint0.getY(), aB2DPoint1.getY()))); + const Point aPointRB(basegfx::fround<tools::Long>(std::max(aB2DPoint0.getX(), aB2DPoint1.getX())), + basegfx::fround<tools::Long>(std::max(aB2DPoint0.getY(), aB2DPoint1.getY()))); const tools::Rectangle aObjRect(aPointLT, aPointRB); GetCellAnchorFromPosition(aObjRect, rNoRotatedAnchor, *pDoc, nTab1, false /*bHiddenAsZero*/); diff --git a/sd/source/filter/html/htmlex.cxx b/sd/source/filter/html/htmlex.cxx index aed0312bc812..7f41e2966a4d 100644 --- a/sd/source/filter/html/htmlex.cxx +++ b/sd/source/filter/html/htmlex.cxx @@ -2774,7 +2774,8 @@ OUString HtmlExport::CreateHTMLPolygonArea( const ::basegfx::B2DPolyPolygon& rPo for ( sal_uInt32 nPoint = 0; nPoint < nNoOfPoints; nPoint++ ) { const ::basegfx::B2DPoint aB2DPoint(aPolygon.getB2DPoint(nPoint)); - Point aPnt(FRound(aB2DPoint.getX()), FRound(aB2DPoint.getY())); + Point aPnt(basegfx::fround<tools::Long>(aB2DPoint.getX()), + basegfx::fround<tools::Long>(aB2DPoint.getY())); // coordinates are relative to the physical page origin, not the // origin of ordinates aPnt.Move(aShift.Width(), aShift.Height()); diff --git a/sd/source/ui/app/optsitem.cxx b/sd/source/ui/app/optsitem.cxx index fb9aac86d491..1736a20e0c6c 100644 --- a/sd/source/ui/app/optsitem.cxx +++ b/sd/source/ui/app/optsitem.cxx @@ -1042,13 +1042,13 @@ bool SdOptionsGrid::ReadData( const Any* pValues ) if( pValues[2].hasValue() ) { - const sal_uInt32 nDivX = FRound( *o3tl::doAccess<double>(pValues[ 2 ]) ); + const sal_uInt32 nDivX = basegfx::fround<sal_uInt32>(*o3tl::doAccess<double>(pValues[2])); SetFieldDivisionX( SvxOptionsGrid::GetFieldDrawX() / ( nDivX + 1 ) ); } if( pValues[3].hasValue() ) { - const sal_uInt32 nDivY = FRound( *o3tl::doAccess<double>(pValues[ 3 ]) ); + const sal_uInt32 nDivY = basegfx::fround<sal_uInt32>(*o3tl::doAccess<double>(pValues[3])); SetFieldDivisionY( SvxOptionsGrid::GetFieldDrawY() / ( nDivY + 1 ) ); } diff --git a/sd/source/ui/dlg/vectdlg.cxx b/sd/source/ui/dlg/vectdlg.cxx index 4069aa225f44..ee407b7eb8ca 100644 --- a/sd/source/ui/dlg/vectdlg.cxx +++ b/sd/source/ui/dlg/vectdlg.cxx @@ -221,9 +221,9 @@ void SdVectorizeDlg::AddTile( BitmapReadAccess const * pRAcc, GDIMetaFile& rMtf, } } - const Color aColor( static_cast<sal_uInt8>(FRound( nSumR * fMult )), - static_cast<sal_uInt8>(FRound( nSumG * fMult )), - static_cast<sal_uInt8>(FRound( nSumB * fMult )) ); + const Color aColor( basegfx::fround<sal_uInt8>( nSumR * fMult ), + basegfx::fround<sal_uInt8>( nSumG * fMult ), + basegfx::fround<sal_uInt8>( nSumB * fMult ) ); ::tools::Rectangle aRect( Point( nPosX, nPosY ), Size( nWidth + 1, nHeight + 1 ) ); const Size& rMaxSize = rMtf.GetPrefSize(); diff --git a/sd/source/ui/func/fuoaprms.cxx b/sd/source/ui/func/fuoaprms.cxx index 0feaabfb4736..893f833fcdf1 100644 --- a/sd/source/ui/func/fuoaprms.cxx +++ b/sd/source/ui/func/fuoaprms.cxx @@ -662,7 +662,8 @@ void FuObjectAnimationParameters::DoExecute( SfxRequest& rReq ) const ::basegfx::B2DPolygon& aPolygon(rPolyPolygon.getB2DPolygon(nNoOfPolygons - 1)); sal_uInt32 nPoints(aPolygon.count()); const ::basegfx::B2DPoint aNewB2DCenter(aPolygon.getB2DPoint(nPoints - 1)); - const Point aNewCenter(FRound(aNewB2DCenter.getX()), FRound(aNewB2DCenter.getY())); + const Point aNewCenter(basegfx::fround<::tools::Long>(aNewB2DCenter.getX()), + basegfx::fround<::tools::Long>(aNewB2DCenter.getY())); Size aDistance(aNewCenter.X() - aCurCenter.X(), aNewCenter.Y() - aCurCenter.Y()); pRunningObj->Move(aDistance); diff --git a/sd/source/ui/view/drviews8.cxx b/sd/source/ui/view/drviews8.cxx index 0f2907d424ba..15be1d1c95d0 100644 --- a/sd/source/ui/view/drviews8.cxx +++ b/sd/source/ui/view/drviews8.cxx @@ -74,13 +74,13 @@ void DrawViewShell::ScannerEvent() if( fGrfWH < fWinWH ) { - aBmpSize.setWidth( FRound( aPageSize.Height() * fGrfWH ) ); + aBmpSize.setWidth( basegfx::fround<::tools::Long>( aPageSize.Height() * fGrfWH ) ); aBmpSize.setHeight( aPageSize.Height() ); } else if( fGrfWH > 0.F ) { aBmpSize.setWidth( aPageSize.Width() ); - aBmpSize.setHeight( FRound( aPageSize.Width() / fGrfWH ) ); + aBmpSize.setHeight( basegfx::fround<::tools::Long>( aPageSize.Width() / fGrfWH ) ); } } diff --git a/sfx2/source/doc/objcont.cxx b/sfx2/source/doc/objcont.cxx index a3b5226917d3..847d44d00820 100644 --- a/sfx2/source/doc/objcont.cxx +++ b/sfx2/source/doc/objcont.cxx @@ -171,13 +171,13 @@ bool SfxObjectShell::CreatePreview_Impl( bool bFullContent, VirtualDevice* pDevi double fWH = static_cast< double >( aSizePix.Width() ) / aSizePix.Height(); if ( fWH <= 1.0 ) { - aSizePix.setWidth( FRound( nMaximumExtent * fWH ) ); + aSizePix.setWidth(basegfx::fround<tools::Long>(nMaximumExtent * fWH)); aSizePix.setHeight( nMaximumExtent ); } else { aSizePix.setWidth( nMaximumExtent ); - aSizePix.setHeight( FRound( nMaximumExtent / fWH ) ); + aSizePix.setHeight(basegfx::fround<tools::Long>(nMaximumExtent / fWH)); } } // do it 4x larger to be able to scale it down & get beautiful antialias diff --git a/slideshow/source/engine/shapes/drawinglayeranimation.cxx b/slideshow/source/engine/shapes/drawinglayeranimation.cxx index d0d3acb66369..ea765eea9649 100644 --- a/slideshow/source/engine/shapes/drawinglayeranimation.cxx +++ b/slideshow/source/engine/shapes/drawinglayeranimation.cxx @@ -422,7 +422,7 @@ void ActivityImpl::ImpForceScrollTextAnimNodes() const double fNumberSteps = (fRelativeDistance * fDistanceLogic) / GetStepWidthLogic(); - nLoopTime = FRound(fNumberSteps * mnFrequency); + nLoopTime = basegfx::fround<sal_uInt32>(fNumberSteps * mnFrequency); // init loop ScrollTextAnimNode aInitNode( @@ -451,7 +451,7 @@ void ActivityImpl::ImpForceScrollTextAnimNodes() const double fNumberSteps = (fRelativeDistance * fDistanceLogic) / GetStepWidthLogic(); - nLoopTime = FRound(fNumberSteps * mnFrequency); + nLoopTime = basegfx::fround<sal_uInt32>(fNumberSteps * mnFrequency); if(0 == mnRepeat) { @@ -501,7 +501,7 @@ void ActivityImpl::ImpForceScrollTextAnimNodes() const double fNumberSteps = (fRelativeDistance * fDistanceLogic) / GetStepWidthLogic(); - nLoopTime = FRound(fNumberSteps * mnFrequency); + nLoopTime = basegfx::fround<sal_uInt32>(fNumberSteps * mnFrequency); // exit loop ScrollTextAnimNode aExitNode( diff --git a/svx/source/customshapes/EnhancedCustomShape2d.cxx b/svx/source/customshapes/EnhancedCustomShape2d.cxx index d93dbee142a3..4c5214bf8674 100644 --- a/svx/source/customshapes/EnhancedCustomShape2d.cxx +++ b/svx/source/customshapes/EnhancedCustomShape2d.cxx @@ -1171,9 +1171,9 @@ bool EnhancedCustomShape2d::GetHandlePosition( const sal_uInt32 nIndex, Point& r double fY =-dx * sin( a ); rReturnPosition = Point( - FRound( fX + aReferencePoint.X() ), + basegfx::fround<tools::Long>( fX + aReferencePoint.X() ), basegfx::fTools::equalZero(fXScale) ? aReferencePoint.Y() : - FRound( ( fY * fYScale ) / fXScale + aReferencePoint.Y() ) ); + basegfx::fround<tools::Long>( ( fY * fYScale ) / fXScale + aReferencePoint.Y() ) ); } else { diff --git a/svx/source/dialog/_contdlg.cxx b/svx/source/dialog/_contdlg.cxx index 3ae8cba852e0..02608859b380 100644 --- a/svx/source/dialog/_contdlg.cxx +++ b/svx/source/dialog/_contdlg.cxx @@ -135,12 +135,12 @@ tools::PolyPolygon SvxContourDlg::CreateAutoContour( const Graphic& rGraphic, if( fWH <= 1.0 ) { aSizePix.setHeight(512); - aSizePix.setWidth( FRound( ( aSizePix.Height() ) * fWH ) ); + aSizePix.setWidth(basegfx::fround<tools::Long>(aSizePix.Height() * fWH)); } else { aSizePix.setWidth(512); - aSizePix.setHeight( FRound( ( aSizePix.Width() ) / fWH ) ); + aSizePix.setHeight(basegfx::fround<tools::Long>(aSizePix.Width() / fWH)); } } diff --git a/svx/source/gallery2/galobj.cxx b/svx/source/gallery2/galobj.cxx index 44362b9a78ec..80d49228e750 100644 --- a/svx/source/gallery2/galobj.cxx +++ b/svx/source/gallery2/galobj.cxx @@ -118,9 +118,9 @@ bool SgaObject::CreateThumb( const Graphic& rGraphic ) double fFactorPix = static_cast< double >( aBmpSize.Width() ) / aBmpSize.Height(); if( fFactorPix > fFactorLog ) - aBmpSize.setWidth( FRound( aBmpSize.Height() * fFactorLog ) ); + aBmpSize.setWidth( basegfx::fround<tools::Long>( aBmpSize.Height() * fFactorLog ) ); else - aBmpSize.setHeight( FRound( aBmpSize.Width() / fFactorLog ) ); + aBmpSize.setHeight( basegfx::fround<tools::Long>( aBmpSize.Width() / fFactorLog ) ); aBmpEx.Scale(aBmpSize, BmpScaleFlag::BestQuality); } diff --git a/svx/source/svdraw/gradtrns.cxx b/svx/source/svdraw/gradtrns.cxx index d665cd48ce16..34c547bba8ed 100644 --- a/svx/source/svdraw/gradtrns.cxx +++ b/svx/source/svdraw/gradtrns.cxx @@ -235,7 +235,7 @@ void GradTransformer::VecToGrad(GradTransVector const & rV, GradTransGradient& r } // to int and set - Degree10 nNewAngle( FRound(fNewFullAngle)); + Degree10 nNewAngle(basegfx::fround<sal_Int16>(fNewFullAngle)); if(nNewAngle != rGOld.aGradient.GetAngle()) { @@ -252,7 +252,7 @@ void GradTransformer::VecToGrad(GradTransVector const & rV, GradTransGradient& r const double fFullLen(aFullVec.getLength()); const double fOldLen(aOldVec.getLength()); const double fNewBorder((fFullLen * 100.0) / fOldLen); - sal_Int32 nNewBorder(100 - FRound(fNewBorder)); + sal_Int32 nNewBorder(100 - basegfx::fround(fNewBorder)); // clip if(nNewBorder < 0) @@ -283,7 +283,7 @@ void GradTransformer::VecToGrad(GradTransVector const & rV, GradTransGradient& r const double fFullLen(aFullVec.getLength()); const double fOldLen(aOldVec.getLength()); const double fNewBorder((fFullLen * 100.0) / fOldLen); - sal_Int32 nNewBorder = 100 - FRound(fNewBorder); + sal_Int32 nNewBorder = 100 - basegfx::fround(fNewBorder); // clip if(nNewBorder < 0) @@ -319,7 +319,7 @@ void GradTransformer::VecToGrad(GradTransVector const & rV, GradTransGradient& r } // to int and set - const Degree10 nNewAngle(FRound(fNewFullAngle)); + const Degree10 nNewAngle(basegfx::fround<sal_Int16>(fNewFullAngle)); if(nNewAngle != rGOld.aGradient.GetAngle()) { @@ -336,8 +336,8 @@ void GradTransformer::VecToGrad(GradTransVector const & rV, GradTransGradient& r { const basegfx::B2DPoint aTopLeft(aRange.getMinX(), aRange.getMinY()); const basegfx::B2DPoint aOffset(aEndPos - aTopLeft); - sal_Int32 nNewXOffset(FRound((aOffset.getX() * 100.0) / aRange.getWidth())); - sal_Int32 nNewYOffset(FRound((aOffset.getY() * 100.0) / aRange.getHeight())); + sal_Int32 nNewXOffset(basegfx::fround(aOffset.getX() * 100.0 / aRange.getWidth())); + sal_Int32 nNewYOffset(basegfx::fround(aOffset.getY() * 100.0 / aRange.getHeight())); // clip if(nNewXOffset < 0) @@ -376,7 +376,7 @@ void GradTransformer::VecToGrad(GradTransVector const & rV, GradTransGradient& r const double fFullLen(aFullVec.getLength()); const double fOldLen(aOldVec.getLength()); const double fNewBorder((fFullLen * 100.0) / fOldLen); - sal_Int32 nNewBorder(100 - FRound(fNewBorder)); + sal_Int32 nNewBorder(100 - basegfx::fround(fNewBorder)); // clip if(nNewBorder < 0) @@ -414,7 +414,7 @@ void GradTransformer::VecToGrad(GradTransVector const & rV, GradTransGradient& r } // to int and set - const Degree10 nNewAngle(FRound(fNewFullAngle)); + const Degree10 nNewAngle(basegfx::fround<sal_Int16>(fNewFullAngle)); if(nNewAngle != rGOld.aGradient.GetAngle()) { @@ -431,8 +431,8 @@ void GradTransformer::VecToGrad(GradTransVector const & rV, GradTransGradient& r { const basegfx::B2DPoint aTopLeft(aRange.getMinX(), aRange.getMinY()); const basegfx::B2DPoint aOffset(aEndPos - aTopLeft); - sal_Int32 nNewXOffset(FRound((aOffset.getX() * 100.0) / aRange.getWidth())); - sal_Int32 nNewYOffset(FRound((aOffset.getY() * 100.0) / aRange.getHeight())); + sal_Int32 nNewXOffset(basegfx::fround(aOffset.getX() * 100.0 / aRange.getWidth())); + sal_Int32 nNewYOffset(basegfx::fround(aOffset.getY() * 100.0 / aRange.getHeight())); // clip if(nNewXOffset < 0) @@ -471,7 +471,7 @@ void GradTransformer::VecToGrad(GradTransVector const & rV, GradTransGradient& r const double fFullLen(aFullVec.getLength()); const double fOldLen(aOldVec.getLength()); const double fNewBorder((fFullLen * 100.0) / fOldLen); - sal_Int32 nNewBorder(100 - FRound(fNewBorder)); + sal_Int32 nNewBorder(100 - basegfx::fround(fNewBorder)); // clip if(nNewBorder < 0) @@ -509,7 +509,7 @@ void GradTransformer::VecToGrad(GradTransVector const & rV, GradTransGradient& r } // to int and set - const Degree10 nNewAngle(FRound(fNewFullAngle)); + const Degree10 nNewAngle(basegfx::fround<sal_Int16>(fNewFullAngle)); if(nNewAngle != rGOld.aGradient.GetAngle()) { diff --git a/svx/source/svdraw/sdrpagewindow.cxx b/svx/source/svdraw/sdrpagewindow.cxx index 01be77135674..86fbe967ccbc 100644 --- a/svx/source/svdraw/sdrpagewindow.cxx +++ b/svx/source/svdraw/sdrpagewindow.cxx @@ -231,6 +231,7 @@ void SdrPageWindow::PrepareRedraw(const vcl::Region& rReg) // clip test #ifdef CLIPPER_TEST #include <svx/svdopath.hxx> +#include <basegfx/numeric/ftools.hxx> #include <basegfx/polygon/b2dpolygon.hxx> #include <tools/helpers.hxx> #include <basegfx/polygon/b2dpolygoncutandtouch.hxx> @@ -262,8 +263,10 @@ namespace { const basegfx::B2DPoint aBStart(aCandidate.getB2DPoint(a)); const basegfx::B2DPoint aBEnd(aCandidate.getB2DPoint((a + 1) % aCandidate.count())); - const Point aStart(FRound(aBStart.getX()), FRound(aBStart.getY())); - const Point aEnd(FRound(aBEnd.getX()), FRound(aBEnd.getY())); + const Point aStart(basegfx::fround<tools::Long>(aBStart.getX()), + basegfx::fround<tools::Long>(aBStart.getY())); + const Point aEnd(basegfx::fround<tools::Long>(aBEnd.getX()), + basegfx::fround<tools::Long>(aBEnd.getY())); rOutDev.DrawLine(aStart, aEnd); } } diff --git a/svx/source/svdraw/svdedtv1.cxx b/svx/source/svdraw/svdedtv1.cxx index 2e4d218a3aee..7d40c4f211f8 100644 --- a/svx/source/svdraw/svdedtv1.cxx +++ b/svx/source/svdraw/svdedtv1.cxx @@ -559,7 +559,7 @@ void SdrEditView::ImpCrookObj(SdrObject* pO, const Point& rRef, const Point& rRa aCtr1 -= aCtr0; if(bRotOk) - pO->Rotate(aCtr0, Degree100(FRound(basegfx::rad2deg<100>(nAngle))), nSin, nCos); + pO->Rotate(aCtr0, Degree100(basegfx::fround(basegfx::rad2deg<100>(nAngle))), nSin, nCos); pO->Move(Size(aCtr1.X(),aCtr1.Y())); } @@ -1675,7 +1675,7 @@ void SdrEditView::SetGeoAttrToMarked(const SfxItemSet& rAttr, bool addPageMargin double nNew = tan(toRadians(nNewShearAngle)); nNew-=nOld; nNew = basegfx::rad2deg<100>(atan(nNew)); - nShearAngle=Degree100(FRound(nNew)); + nShearAngle = Degree100(basegfx::fround(nNew)); } else { nShearAngle=nNewShearAngle-nOldShearAngle; } diff --git a/svx/source/svdraw/svdfmtf.cxx b/svx/source/svdraw/svdfmtf.cxx index f27413d4700c..54760e0f6e18 100644 --- a/svx/source/svdraw/svdfmtf.cxx +++ b/svx/source/svdraw/svdfmtf.cxx @@ -394,7 +394,7 @@ void ImpSdrGDIMetaFileImport::SetAttributes(SdrObject* pObj, bool bForceTextAttr if(bText && mbFntDirty) { vcl::Font aFnt(mpVD->GetFont()); - const sal_uInt32 nHeight(FRound(aFnt.GetFontSize().Height() * mfScaleY)); + const sal_uInt32 nHeight(basegfx::fround(aFnt.GetFontSize().Height() * mfScaleY)); mpTextAttr->Put( SvxFontItem( aFnt.GetFamilyType(), aFnt.GetFamilyName(), aFnt.GetStyleName(), aFnt.GetPitch(), aFnt.GetCharSet(), EE_CHAR_FONTINFO ) ); mpTextAttr->Put( SvxFontItem( aFnt.GetFamilyType(), aFnt.GetFamilyName(), aFnt.GetStyleName(), aFnt.GetPitch(), aFnt.GetCharSet(), EE_CHAR_FONTINFO_CJK ) ); @@ -1002,11 +1002,12 @@ void ImpSdrGDIMetaFileImport::ImportText( const Point& rPos, const OUString& rSt sal_Int32 nTextWidth = static_cast<sal_Int32>( mpVD->GetTextWidth( rStr ) * mfScaleX ); sal_Int32 nTextHeight = static_cast<sal_Int32>( mpVD->GetTextHeight() * mfScaleY ); - Point aPos( FRound(rPos.X() * mfScaleX + maOfs.X()), FRound(rPos.Y() * mfScaleY + maOfs.Y()) ); + Point aPos(basegfx::fround<tools::Long>(rPos.X() * mfScaleX + maOfs.X()), + basegfx::fround<tools::Long>(rPos.Y() * mfScaleY + maOfs.Y())); Size aSize( nTextWidth, nTextHeight ); if ( eAlg == ALIGN_BASELINE ) - aPos.AdjustY( -(FRound(aFontMetric.GetAscent() * mfScaleY)) ); + aPos.AdjustY(basegfx::fround<tools::Long>(aFontMetric.GetAscent() * -mfScaleY)); else if ( eAlg == ALIGN_BOTTOM ) aPos.AdjustY( -nTextHeight ); diff --git a/svx/source/svdraw/svdhdl.cxx b/svx/source/svdraw/svdhdl.cxx index 379b3ed3f73e..75d6ae0c873f 100644 --- a/svx/source/svdraw/svdhdl.cxx +++ b/svx/source/svdraw/svdhdl.cxx @@ -1420,16 +1420,20 @@ void SdrHdlGradient::FromIAOToItem(SdrObject* _pObj, bool bSetItemOnObject, bool // back transformation, set values on pIAOHandle GradTransformer::GradToVec(aGradTransGradient, aGradTransVector, _pObj); - SetPos(Point(FRound(aGradTransVector.maPositionA.getX()), FRound(aGradTransVector.maPositionA.getY()))); - Set2ndPos(Point(FRound(aGradTransVector.maPositionB.getX()), FRound(aGradTransVector.maPositionB.getY()))); + SetPos({ basegfx::fround<tools::Long>(aGradTransVector.maPositionA.getX()), + basegfx::fround<tools::Long>(aGradTransVector.maPositionA.getY()) }); + Set2ndPos({ basegfx::fround<tools::Long>(aGradTransVector.maPositionB.getX()), + basegfx::fround<tools::Long>(aGradTransVector.maPositionB.getY()) }); if(pColHdl1) { - pColHdl1->SetPos(Point(FRound(aGradTransVector.maPositionA.getX()), FRound(aGradTransVector.maPositionA.getY()))); + pColHdl1->SetPos({ basegfx::fround<tools::Long>(aGradTransVector.maPositionA.getX()), + basegfx::fround<tools::Long>(aGradTransVector.maPositionA.getY()) }); pColHdl1->SetColor(aGradTransVector.aCol1); } if(pColHdl2) { - pColHdl2->SetPos(Point(FRound(aGradTransVector.maPositionB.getX()), FRound(aGradTransVector.maPositionB.getY()))); + pColHdl2->SetPos({ basegfx::fround<tools::Long>(aGradTransVector.maPositionB.getX()), + basegfx::fround<tools::Long>(aGradTransVector.maPositionB.getY()) }); pColHdl2->SetColor(aGradTransVector.aCol2); } } diff --git a/svx/source/svdraw/svdoashp.cxx b/svx/source/svdraw/svdoashp.cxx index 44ecb8fefded..fd0c43f851f1 100644 --- a/svx/source/svdraw/svdoashp.cxx +++ b/svx/source/svdraw/svdoashp.cxx @@ -3033,7 +3033,8 @@ void SdrObjCustomShape::TRSetBaseGeometry(const basegfx::B2DHomMatrix& rMatrix, } // scale - Size aSize(FRound(fabs(aScale.getX())), FRound(fabs(aScale.getY()))); + Size aSize(basegfx::fround<tools::Long>(fabs(aScale.getX())), + basegfx::fround<tools::Long>(fabs(aScale.getY()))); // fdo#47434 We need a valid rectangle here if( !aSize.Height() ) aSize.setHeight( 1 ); if( !aSize.Width() ) aSize.setWidth( 1 ); @@ -3053,7 +3054,7 @@ void SdrObjCustomShape::TRSetBaseGeometry(const basegfx::B2DHomMatrix& rMatrix, // #i123181# The fix for #121932# here was wrong, the trunk version does not correct the // mirrored shear values, neither at the object level, nor on the API or XML level. Taking // back the mirroring of the shear angle - aGeoStat.nShearAngle = Degree100(FRound(basegfx::rad2deg<100>(atan(fShearX)))); + aGeoStat.nShearAngle = Degree100(basegfx::fround(basegfx::rad2deg<100>(atan(fShearX)))); aGeoStat.RecalcTan(); Shear(Point(), aGeoStat.nShearAngle, aGeoStat.mfTanShearAngle, false); } @@ -3066,7 +3067,7 @@ void SdrObjCustomShape::TRSetBaseGeometry(const basegfx::B2DHomMatrix& rMatrix, // #i78696# // fRotate is mathematically correct, but aGeoStat.nRotationAngle is // mirrored -> mirror value here - aGeoStat.nRotationAngle = NormAngle36000(Degree100(FRound(-basegfx::rad2deg<100>(fRotate)))); + aGeoStat.nRotationAngle = NormAngle36000(Degree100(basegfx::fround(-basegfx::rad2deg<100>(fRotate)))); aGeoStat.RecalcSinCos(); Rotate(Point(), aGeoStat.nRotationAngle, aGeoStat.mfSinRotationAngle, aGeoStat.mfCosRotationAngle); } @@ -3074,7 +3075,8 @@ void SdrObjCustomShape::TRSetBaseGeometry(const basegfx::B2DHomMatrix& rMatrix, // translate? if(!aTranslate.equalZero()) { - Move(Size(FRound(aTranslate.getX()), FRound(aTranslate.getY()))); + Move(Size(basegfx::fround<tools::Long>(aTranslate.getX()), + basegfx::fround<tools::Long>(aTranslate.getY()))); } // Apply flipping from enhanced geometry at center of the shape. @@ -3095,11 +3097,11 @@ void SdrObjCustomShape::TRSetBaseGeometry(const basegfx::B2DHomMatrix& rMatrix, double fCenterX = aCenter.getX(); double fCenterY = aCenter.getY(); if (bIsMirroredX) // vertical axis - Mirror(Point(FRound(fCenterX),FRound(fCenterY)), - Point(FRound(fCenterX), FRound(fCenterY + 1000.0))); + Mirror(Point(basegfx::fround<tools::Long>(fCenterX), basegfx::fround<tools::Long>(fCenterY)), + Point(basegfx::fround<tools::Long>(fCenterX), basegfx::fround<tools::Long>(fCenterY + 1000.0))); if (bIsMirroredY) // horizontal axis - Mirror(Point(FRound(fCenterX),FRound(fCenterY)), - Point(FRound(fCenterX + 1000.0), FRound(fCenterY))); + Mirror(Point(basegfx::fround<tools::Long>(fCenterX), basegfx::fround<tools::Long>(fCenterY)), + Point(basegfx::fround<tools::Long>(fCenterX + 1000.0), basegfx::fround<tools::Long>(fCenterY))); } // taking fObjectRotation instead of aGeo.nAngle diff --git a/svx/source/svdraw/svdobj.cxx b/svx/source/svdraw/svdobj.cxx index 4bcd7c386270..a817ad295a9b 100644 --- a/svx/source/svdraw/svdobj.cxx +++ b/svx/source/svdraw/svdobj.cxx @@ -3036,8 +3036,10 @@ void SdrObject::TRSetBaseGeometry(const basegfx::B2DHomMatrix& rMatrix, const ba } // build BaseRect - Point aPoint(FRound(aTranslate.getX()), FRound(aTranslate.getY())); - tools::Rectangle aBaseRect(aPoint, Size(FRound(aScale.getX()), FRound(aScale.getY()))); + Point aPoint(basegfx::fround<tools::Long>(aTranslate.getX()), + basegfx::fround<tools::Long>(aTranslate.getY())); + tools::Rectangle aBaseRect(aPoint, Size(basegfx::fround<tools::Long>(aScale.getX()), + basegfx::fround<tools::Long>(aScale.getY()))); // set BaseRect SetSnapRect(aBaseRect); diff --git a/svx/source/svdraw/svdocapt.cxx b/svx/source/svdraw/svdocapt.cxx index 6a886272bad1..0287b2391a5b 100644 --- a/svx/source/svdraw/svdocapt.cxx +++ b/svx/source/svdraw/svdocapt.cxx @@ -737,8 +737,10 @@ void SdrCaptionObj::TRSetBaseGeometry(const basegfx::B2DHomMatrix& rMatrix, cons } // build BaseRect - Point aPoint(FRound(aTranslate.getX()), FRound(aTranslate.getY())); - tools::Rectangle aBaseRect(aPoint, Size(FRound(aScale.getX()), FRound(aScale.getY()))); + Point aPoint(basegfx::fround<tools::Long>(aTranslate.getX()), + basegfx::fround<tools::Long>(aTranslate.getY())); + tools::Rectangle aBaseRect(aPoint, Size(basegfx::fround<tools::Long>(aScale.getX()), + basegfx::fround<tools::Long>(aScale.getY()))); // set BaseRect, but rescue TailPos over this call const Point aTailPoint = GetTailPos(); diff --git a/svx/source/svdraw/svdocirc.cxx b/svx/source/svdraw/svdocirc.cxx index 1207548114bf..270eda407493 100644 --- a/svx/source/svdraw/svdocirc.cxx +++ b/svx/source/svdraw/svdocirc.cxx @@ -57,7 +57,8 @@ static Point GetAnglePnt(const tools::Rectangle& rR, Degree100 nAngle) tools::Long nHgt=rR.Bottom()-rR.Top(); tools::Long nMaxRad=(std::max(nWdt,nHgt)+1) /2; double a = toRadians(nAngle); - Point aRetval(FRound(cos(a)*nMaxRad),-FRound(sin(a)*nMaxRad)); + Point aRetval(basegfx::fround<tools::Long>(cos(a) * nMaxRad), + basegfx::fround<tools::Long>(-sin(a) * nMaxRad)); if (nWdt==0) aRetval.setX(0 ); if (nHgt==0) aRetval.setY(0 ); if (nWdt!=nHgt) { @@ -886,13 +887,15 @@ void SdrCircObj::NbcMirror(const Point& rRef1, const Point& rRef2) tools::Long nMaxRad=(std::max(nWdt,nHgt)+1) /2; // starting point double a = toRadians(nStartAngle); - aTmpPt1=Point(FRound(cos(a)*nMaxRad),-FRound(sin(a)*nMaxRad)); + aTmpPt1 = Point(basegfx::fround<tools::Long>(cos(a) * nMaxRad), + basegfx::fround<tools::Long>(-sin(a) * nMaxRad)); if (nWdt==0) aTmpPt1.setX(0 ); if (nHgt==0) aTmpPt1.setY(0 ); aTmpPt1+=aCenter; // finishing point a = toRadians(nEndAngle); - aTmpPt2=Point(FRound(cos(a)*nMaxRad),-FRound(sin(a)*nMaxRad)); + aTmpPt2 = Point(basegfx::fround<tools::Long>(cos(a) * nMaxRad), + basegfx::fround<tools::Long>(-sin(a) * nMaxRad)); if (nWdt==0) aTmpPt2.setX(0 ); if (nHgt==0) aTmpPt2.setY(0 ); aTmpPt2+=aCenter; @@ -1011,7 +1014,7 @@ void SdrCircObj::TakeUnrotatedSnapRect(tools::Rectangle& rRect) const if (maGeo.nShearAngle==0_deg100) return; - tools::Long nDst = FRound((rRect.Bottom() - rRect.Top()) * maGeo.mfTanShearAngle); + tools::Long nDst = basegfx::fround<tools::Long>((rRect.Bottom() - rRect.Top()) * maGeo.mfTanShearAngle); if (maGeo.nShearAngle > 0_deg100) { Point aRef(rRect.TopLeft()); diff --git a/svx/source/svdraw/svdograf.cxx b/svx/source/svdraw/svdograf.cxx index a4b2060956dc..49fb0666af82 100644 --- a/svx/source/svdraw/svdograf.cxx +++ b/svx/source/svdraw/svdograf.cxx @@ -1051,7 +1051,7 @@ void SdrGrafObj::ImpSetAttrToGrafInfo() aGrafInfo.SetChannelG( rSet.Get( SDRATTR_GRAFGREEN ).GetValue() ); aGrafInfo.SetChannelB( rSet.Get( SDRATTR_GRAFBLUE ).GetValue() ); -e ... etc. - the rest is truncated