diff --git a/.gitignore b/.gitignore index d920b13..85ec8bc 100644 --- a/.gitignore +++ b/.gitignore @@ -5,9 +5,9 @@ /libreoffice-multiliblauncher.sh /dtoa-20180411.tgz /libcuckoo-93217f8d391718380c508a722ab9acd5e9081233.tar.gz -/libreoffice-7.3.5.2.tar.xz -/libreoffice-7.3.5.2.tar.xz.asc -/libreoffice-help-7.3.5.2.tar.xz -/libreoffice-help-7.3.5.2.tar.xz.asc -/libreoffice-translations-7.3.5.2.tar.xz -/libreoffice-translations-7.3.5.2.tar.xz.asc +/libreoffice-7.4.0.2.tar.xz +/libreoffice-7.4.0.2.tar.xz.asc +/libreoffice-help-7.4.0.2.tar.xz +/libreoffice-help-7.4.0.2.tar.xz.asc +/libreoffice-translations-7.4.0.2.tar.xz +/libreoffice-translations-7.4.0.2.tar.xz.asc diff --git a/0001-don-t-suppress-crashes.patch b/0001-don-t-suppress-crashes.patch index 4a35f3d..596534d 100644 --- a/0001-don-t-suppress-crashes.patch +++ b/0001-don-t-suppress-crashes.patch @@ -14,7 +14,7 @@ diff --git a/desktop/source/app/app.cxx b/desktop/source/app/app.cxx index c54aea9dd4f7..a613fe12cef2 100644 --- a/desktop/source/app/app.cxx +++ b/desktop/source/app/app.cxx -@@ -1147,14 +1147,12 @@ void Desktop::Exception(ExceptionCategory nCategory) +@@ -1165,8 +1165,6 @@ if( bRestart ) { RequestHandler::Disable(); @@ -22,8 +22,10 @@ index c54aea9dd4f7..a613fe12cef2 100644 - osl_removeSignalHandler( pSignalHandler ); restartOnMac(false); - if ( m_rSplashScreen.is() ) + #if !ENABLE_WASM_STRIP_SPLASH +@@ -1174,7 +1172,7 @@ m_rSplashScreen->reset(); + #endif - _exit( EXITHELPER_CRASH_WITH_RESTART ); + return; diff --git a/0001-rhbz-2104545-Only-call-utl-IsYounger-when-its-result.patch b/0001-rhbz-2104545-Only-call-utl-IsYounger-when-its-result.patch deleted file mode 100644 index 145f18e..0000000 --- a/0001-rhbz-2104545-Only-call-utl-IsYounger-when-its-result.patch +++ /dev/null @@ -1,70 +0,0 @@ -From c3afc3ba94500f726475adc895de6c92814ae8bb Mon Sep 17 00:00:00 2001 -From: Stephan Bergmann -Date: Fri, 8 Jul 2022 16:47:01 +0200 -Subject: [PATCH] rhbz#2104545: Only call utl::IsYounger when its result is - actually used - -...as it may be expensive, or even throw (uncaught) exceptions (as apparently -happened at rhbz#2104545, throwing some css::uno::RuntimeException while aMedObj -was an sftp URL). - -The two branches in the if statement's condition that will now potentially call -physObjIsOlder are disjoint (one for aMedObj being a file URL, the other for -aMedObj being any WebDAV-related URL), so there is no chance that this change -accidentally causes utl::IsYounger to be called more often than it used to be -called. - -Reviewed-on: https://gerrit.libreoffice.org/c/core/+/136904 -Tested-by: Jenkins -Reviewed-by: Stephan Bergmann -(cherry picked from commit 27ffdcf096a7e9863489599dd80528b088d1e9b8) -Conflicts: - sfx2/source/view/viewfrm.cxx - -Change-Id: I29a5f18a12a8b83ec603366db26451175b5622c9 -Reviewed-on: https://gerrit.libreoffice.org/c/core/+/136909 -Tested-by: Jenkins -Reviewed-by: Michael Stahl ---- - sfx2/source/view/viewfrm.cxx | 11 +++++++---- - 1 file changed, 7 insertions(+), 4 deletions(-) - -diff --git a/sfx2/source/view/viewfrm.cxx b/sfx2/source/view/viewfrm.cxx -index ecae96b5d945..7f3bf1a6bcc2 100644 ---- a/sfx2/source/view/viewfrm.cxx -+++ b/sfx2/source/view/viewfrm.cxx -@@ -270,6 +270,11 @@ bool AskPasswordToModify_Impl( const uno::Reference< task::XInteractionHandler > - - return bResult; - } -+ -+bool physObjIsOlder(INetURLObject const & aMedObj, INetURLObject const & aPhysObj) { -+ return ::utl::UCBContentHelper::IsYounger(aMedObj.GetMainURL( INetURLObject::DecodeMechanism::NONE), -+ aPhysObj.GetMainURL( INetURLObject::DecodeMechanism::NONE ) ); -+} - } - - void SfxViewFrame::ExecReload_Impl( SfxRequest& rReq ) -@@ -438,8 +443,6 @@ void SfxViewFrame::ExecReload_Impl( SfxRequest& rReq ) - // etag tells that the cache representation (e.g. in LO) is different from the one on the server, - // but tells nothing about the age - // Details at this link: http://tools.ietf.org/html/rfc4918#section-15, section 15.7 -- bool bPhysObjIsYounger = ::utl::UCBContentHelper::IsYounger( aMedObj.GetMainURL( INetURLObject::DecodeMechanism::NONE ), -- aPhysObj.GetMainURL( INetURLObject::DecodeMechanism::NONE ) ); - bool bIsWebDAV = aMedObj.isAnyKnownWebDAVScheme(); - - // tdf#118938 Reload the document when the user enters the editing password, -@@ -447,8 +450,8 @@ void SfxViewFrame::ExecReload_Impl( SfxRequest& rReq ) - if ( ( !bNeedsReload && ( ( aMedObj.GetProtocol() == INetProtocol::File && - ( aMedObj.getFSysPath( FSysStyle::Detect ) != aPhysObj.getFSysPath( FSysStyle::Detect ) - || bPasswordEntered ) && -- !bPhysObjIsYounger ) -- || ( bIsWebDAV && !bPhysObjIsYounger ) -+ !physObjIsOlder(aMedObj, aPhysObj) ) -+ || ( bIsWebDAV && !physObjIsOlder(aMedObj, aPhysObj) ) - || ( pMed->IsRemote() && !bIsWebDAV ) ) ) - || pVersionItem ) - // <- tdf#82744 --- -2.36.1 - diff --git a/0001-s390x-canvas-test-fails.patch b/0001-s390x-canvas-test-fails.patch deleted file mode 100644 index e811429..0000000 --- a/0001-s390x-canvas-test-fails.patch +++ /dev/null @@ -1,26 +0,0 @@ -From d0805b6732c0fe3168d144928cec1c59c2711211 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Caol=C3=A1n=20McNamara?= -Date: Sun, 6 Mar 2022 23:19:08 +0000 -Subject: [PATCH] s390x canvas test fails - -Change-Id: I7ac059aa19dd348f4e9c567445aff8f066c867b4 ---- - canvas/Module_canvas.mk | 4 ---- - 1 file changed, 4 deletions(-) - -diff --git a/canvas/Module_canvas.mk b/canvas/Module_canvas.mk -index 0ca3c4c9bfe0..f62d7ef46299 100644 ---- a/canvas/Module_canvas.mk -+++ b/canvas/Module_canvas.mk -@@ -49,8 +49,4 @@ $(eval $(call gb_Module_add_targets,canvas,\ - )) - endif - --$(eval $(call gb_Module_add_check_targets,canvas,\ -- CppunitTest_canvas_test \ --)) -- - # vim: set noet sw=4 ts=4: --- -2.35.1 - diff --git a/0001-tdf-144862-use-resolution-independent-positions-for-.patch b/0001-tdf-144862-use-resolution-independent-positions-for-.patch deleted file mode 100644 index 60c191c..0000000 --- a/0001-tdf-144862-use-resolution-independent-positions-for-.patch +++ /dev/null @@ -1,2868 +0,0 @@ -From abaae9bf594e183f16a20305e86330977fbf8758 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Caol=C3=A1n=20McNamara?= -Date: Mon, 20 Dec 2021 11:38:47 +0000 -Subject: [PATCH] tdf#144862 use resolution independent positions for writer's - screen-rendering -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -in favor of pushing it down to the text renderers and leave -it to them to optimized as best they can the the rendering -to make it look as well as possible. - -Change-Id: Ic0849c091a36e1a90453771b1c91b8ff706b679e -Reviewed-on: https://gerrit.libreoffice.org/c/core/+/128418 -Tested-by: Caolán McNamara -Reviewed-by: Caolán McNamara -(cherry picked from commit 4ed26badfd6fd9190cb6e54078b41eb38cb37dca) ---- - include/basegfx/tuple/Tuple2D.hxx | 6 + - include/vcl/devicecoordinate.hxx | 11 +- - include/vcl/outdev.hxx | 10 +- - include/vcl/vcllayout.hxx | 17 +- - sw/qa/extras/layout/layout.cxx | 2 +- - sw/source/core/inc/fntcache.hxx | 8 +- - sw/source/core/inc/scriptinfo.hxx | 10 +- - sw/source/core/text/itradj.cxx | 6 +- - sw/source/core/text/porlay.cxx | 10 +- - sw/source/core/text/portxt.cxx | 4 +- - sw/source/core/txtnode/fntcache.cxx | 201 ++++++++--------------- - sw/source/uibase/config/usrpref.cxx | 2 +- - vcl/inc/ImplLayoutArgs.hxx | 6 +- - vcl/inc/impglyphitem.hxx | 4 +- - vcl/inc/quartz/salgdi.h | 4 +- - vcl/inc/salgdi.hxx | 11 ++ - vcl/inc/sallayout.hxx | 18 +- - vcl/inc/skia/osx/gdiimpl.hxx | 3 +- - vcl/inc/skia/win/gdiimpl.hxx | 4 + - vcl/inc/win/DWriteTextRenderer.hxx | 17 +- - vcl/inc/win/salgdi.h | 2 +- - vcl/inc/win/winlayout.hxx | 8 +- - vcl/qt5/QtGraphics_Text.cxx | 21 ++- - vcl/quartz/salgdi.cxx | 16 +- - vcl/skia/gdiimpl.cxx | 4 +- - vcl/skia/osx/gdiimpl.cxx | 11 +- - vcl/skia/win/gdiimpl.cxx | 78 ++++++++- - vcl/skia/x11/textrender.cxx | 18 +- - vcl/source/gdi/CommonSalLayout.cxx | 35 ++-- - vcl/source/gdi/pdfwriter_impl.cxx | 28 ++-- - vcl/source/gdi/salgdilayout.cxx | 3 +- - vcl/source/gdi/sallayout.cxx | 102 +++++++----- - vcl/source/gdi/virdev.cxx | 2 + - vcl/source/outdev/font.cxx | 10 +- - vcl/source/outdev/map.cxx | 25 ++- - vcl/source/outdev/outdev.cxx | 19 ++- - vcl/source/outdev/text.cxx | 150 ++++++++++------- - vcl/source/outdev/textline.cxx | 18 +- - vcl/source/text/ImplLayoutArgs.cxx | 18 +- - vcl/unx/generic/gdi/cairotextrender.cxx | 23 ++- - vcl/unx/generic/print/genpspgraphics.cxx | 4 +- - vcl/win/gdi/DWriteTextRenderer.cxx | 42 +++-- - vcl/win/gdi/winlayout.cxx | 31 ++-- - 43 files changed, 618 insertions(+), 404 deletions(-) - -diff --git a/include/basegfx/tuple/Tuple2D.hxx b/include/basegfx/tuple/Tuple2D.hxx -index 2007732543b6..b173ad3033c1 100644 ---- a/include/basegfx/tuple/Tuple2D.hxx -+++ b/include/basegfx/tuple/Tuple2D.hxx -@@ -73,6 +73,12 @@ public: - /// Set Y-Coordinate of 2D Tuple - void setY(TYPE fY) { mnY = fY; } - -+ /// Adjust X-Coordinate of 2D Tuple -+ void adjustX(TYPE fX) { mnX += fX; } -+ -+ /// Adjust Y-Coordinate of 2D Tuple -+ void adjustY(TYPE fY) { mnY += fY; } -+ - // comparators with tolerance - - template , int> = 0> -diff --git a/include/vcl/devicecoordinate.hxx b/include/vcl/devicecoordinate.hxx -index acece32cc204..bd0bf1ee7963 100644 ---- a/include/vcl/devicecoordinate.hxx -+++ b/include/vcl/devicecoordinate.hxx -@@ -7,23 +7,22 @@ - * file, You can obtain one at http://mozilla.org/MPL/2.0/. - */ - --#ifndef INCLUDED_VCL_DEVICE_COORDINATE_HXX --#define INCLUDED_VCL_DEVICE_COORDINATE_HXX -+#pragma once - - #include - #include - --#if VCL_FLOAT_DEVICE_PIXEL - #include -+typedef basegfx::B2DPoint DevicePoint; -+ -+#if VCL_FLOAT_DEVICE_PIXEL -+ - typedef double DeviceCoordinate; - - #else /* !VCL_FLOAT_DEVICE_PIXEL */ - --#include - typedef sal_Int32 DeviceCoordinate; - - #endif /* ! Carpet Cushion */ - --#endif /* NDef INCLUDED_VCL_DEVICE_COORDINATE_HXX */ -- - /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ -diff --git a/include/vcl/outdev.hxx b/include/vcl/outdev.hxx -index e8011412955c..85670e44dec3 100644 ---- a/include/vcl/outdev.hxx -+++ b/include/vcl/outdev.hxx -@@ -242,6 +242,7 @@ private: - Point maRefPoint; - AntialiasingFlags mnAntialiasing; - LanguageType meTextLanguage; -+ bool mbTextRenderModeForResolutionIndependentLayout; - - mutable bool mbMap : 1; - mutable bool mbClipRegion : 1; -@@ -489,6 +490,10 @@ public: - void SetAntialiasing( AntialiasingFlags nMode ); - AntialiasingFlags GetAntialiasing() const { return mnAntialiasing; } - -+ // Render glyphs with a mode suitable for rendering of resolution-independent layout positions. -+ void SetTextRenderModeForResolutionIndependentLayout(bool bMode); -+ bool GetTextRenderModeForResolutionIndependentLayout() const { return mbTextRenderModeForResolutionIndependentLayout; } -+ - void SetDrawMode( DrawModeFlags nDrawMode ); - DrawModeFlags GetDrawMode() const { return mnDrawMode; } - -@@ -1244,8 +1249,9 @@ public: - o3tl::span pLogicDXArray={}, SalLayoutFlags flags = SalLayoutFlags::NONE, - vcl::text::TextLayoutCache const* = nullptr, - const SalLayoutGlyphs* pGlyphs = nullptr) const; -+ - SAL_DLLPRIVATE vcl::text::ImplLayoutArgs ImplPrepareLayoutArgs( OUString&, const sal_Int32 nIndex, const sal_Int32 nLen, -- DeviceCoordinate nPixelWidth, const DeviceCoordinate* pPixelDXArray, -+ DeviceCoordinate nPixelWidth, - SalLayoutFlags flags = SalLayoutFlags::NONE, - vcl::text::TextLayoutCache const* = nullptr) const; - SAL_DLLPRIVATE std::unique_ptr -@@ -1693,6 +1699,7 @@ public: - @returns Physical point on the device. - */ - SAL_DLLPRIVATE Point ImplLogicToDevicePixel( const Point& rLogicPt ) const; -+ SAL_DLLPRIVATE DevicePoint ImplLogicToDeviceFontCoordinate(const Point& rLogicPt) const; - - /** Convert a logical width to a width in units of device pixels. - -@@ -1705,6 +1712,7 @@ public: - @returns Width in units of device pixels. - */ - SAL_DLLPRIVATE tools::Long ImplLogicWidthToDevicePixel( tools::Long nWidth ) const; -+ SAL_DLLPRIVATE double ImplLogicWidthToDeviceFontWidth(tools::Long nWidth) const; - - SAL_DLLPRIVATE DeviceCoordinate LogicWidthToDeviceCoordinate( tools::Long nWidth ) const; - -diff --git a/include/vcl/vcllayout.hxx b/include/vcl/vcllayout.hxx -index 6ea9bc61bfbb..18d4da907375 100644 ---- a/include/vcl/vcllayout.hxx -+++ b/include/vcl/vcllayout.hxx -@@ -70,11 +70,11 @@ class VCL_DLLPUBLIC SalLayout - public: - virtual ~SalLayout(); - // used by upper layers -- Point& DrawBase() { return maDrawBase; } -- const Point& DrawBase() const { return maDrawBase; } -+ DevicePoint& DrawBase() { return maDrawBase; } -+ const DevicePoint& DrawBase() const { return maDrawBase; } - Point& DrawOffset() { return maDrawOffset; } - const Point& DrawOffset() const { return maDrawOffset; } -- Point GetDrawPosition( const Point& rRelative = Point(0,0) ) const; -+ DevicePoint GetDrawPosition( const DevicePoint& rRelative = DevicePoint(0,0) ) const; - - virtual bool LayoutText( vcl::text::ImplLayoutArgs&, const SalLayoutGlyphsImpl* ) = 0; // first step of layouting - virtual void AdjustLayout( vcl::text::ImplLayoutArgs& ); // adjusting after fallback etc. -@@ -84,6 +84,11 @@ public: - int GetUnitsPerPixel() const { return mnUnitsPerPixel; } - Degree10 GetOrientation() const { return mnOrientation; } - -+ void SetTextRenderModeForResolutionIndependentLayout(bool bTextRenderModeForResolutionIndependentLayout) -+ { -+ mbTextRenderModeForResolutionIndependentLayout = bTextRenderModeForResolutionIndependentLayout; -+ } -+ - // methods using string indexing - virtual sal_Int32 GetTextBreak(DeviceCoordinate nMaxWidth, DeviceCoordinate nCharExtra, int nFactor) const = 0; - virtual DeviceCoordinate FillDXArray( std::vector* pDXArray ) const = 0; -@@ -92,7 +97,7 @@ public: - virtual bool IsKashidaPosValid ( int /*nCharPos*/ ) const { return true; } // i60594 - - // methods using glyph indexing -- virtual bool GetNextGlyph(const GlyphItem** pGlyph, Point& rPos, int& nStart, -+ virtual bool GetNextGlyph(const GlyphItem** pGlyph, DevicePoint& rPos, int& nStart, - const LogicalFontInstance** ppGlyphFont = nullptr, - const vcl::font::PhysicalFontFace** pFallbackFont = nullptr) const = 0; - virtual bool GetOutline(basegfx::B2DPolyPolygonVector&) const; -@@ -116,7 +121,9 @@ protected: - Degree10 mnOrientation; - - mutable Point maDrawOffset; -- Point maDrawBase; -+ DevicePoint maDrawBase; -+ -+ bool mbTextRenderModeForResolutionIndependentLayout; - }; - - /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ -diff --git a/sw/qa/extras/layout/layout.cxx b/sw/qa/extras/layout/layout.cxx -index 94edf650a359..267c20770bef 100644 ---- a/sw/qa/extras/layout/layout.cxx -+++ b/sw/qa/extras/layout/layout.cxx -@@ -2823,7 +2823,7 @@ CPPUNIT_TEST_FIXTURE(SwLayoutWriter, testBtlrCell) - // Without the accompanying fix in place, this test would have failed with 'Expected: 1979; - // Actual : 2129', i.e. the gray background of the "AAA2." text was too close to the right edge - // of the text portion. Now it's exactly behind the text portion. -- assertXPath(pXmlDoc, "//rect[@top='2159']", "left", "1979"); -+ assertXPath(pXmlDoc, "(//rect)[2]", "left", "1979"); - - // Without the accompanying fix in place, this test would have failed with 'Expected: 269; - // Actual : 0', i.e. the AAA2 frame was not visible due to 0 width. -diff --git a/sw/source/core/inc/fntcache.hxx b/sw/source/core/inc/fntcache.hxx -index 0bdc4757d9b3..4285165a3336 100644 ---- a/sw/source/core/inc/fntcache.hxx -+++ b/sw/source/core/inc/fntcache.hxx -@@ -66,13 +66,13 @@ extern SwFntObj *pLastFont; - */ - struct SwTextGlyphsKey - { -- VclPtr m_pOutputDevice; -+ VclPtr m_pOutputDevice; - OUString m_aText; - sal_Int32 m_nIndex; - sal_Int32 m_nLength; - size_t mnHashCode; - -- SwTextGlyphsKey(VclPtr const& pOutputDevice, const OUString & sText, sal_Int32 nIndex, sal_Int32 nLength); -+ SwTextGlyphsKey(const OutputDevice* pOutputDevice, const OUString & sText, sal_Int32 nIndex, sal_Int32 nLength); - bool operator==(SwTextGlyphsKey const & rhs) const; - }; - struct SwTextGlyphsKeyHash -@@ -113,6 +113,10 @@ class SwFntObj final : public SwCacheObj - /// Cache of already calculated layout glyphs and text widths. - SwTextGlyphsMap m_aTextGlyphs; - -+ void GetTextArray(const OutputDevice& rOutputDevice, const OUString& rStr, -+ std::vector& rDXAry, sal_Int32 nIndex, sal_Int32 nLen, -+ bool bCaching); -+ - static tools::Long s_nPixWidth; - static MapMode *s_pPixMap; - -diff --git a/sw/source/core/inc/scriptinfo.hxx b/sw/source/core/inc/scriptinfo.hxx -index cd479034ed06..cfe9ef3e55fb 100644 ---- a/sw/source/core/inc/scriptinfo.hxx -+++ b/sw/source/core/inc/scriptinfo.hxx -@@ -281,8 +281,6 @@ public: - positions in the kerning array. - @param pKernArray - The printers kerning array. Optional. -- @param pScrArray -- The screen kerning array. Optional. - @param nStt - Start referring to the paragraph. - @param nLen -@@ -291,7 +289,7 @@ public: - The value which has to be added to a kashida opportunity. - @return The number of kashida opportunities in the given range - */ -- sal_Int32 KashidaJustify( sal_Int32* pKernArray, sal_Int32* pScrArray, -+ sal_Int32 KashidaJustify( sal_Int32* pKernArray, - TextFrameIndex nStt, TextFrameIndex nLen, tools::Long nSpaceAdd = 0) const; - - /** Clears array of kashidas marked as invalid -@@ -354,8 +352,6 @@ public: - The String - @param pKernArray - The printers kerning array. Optional. -- @param pScrArray -- The screen kerning array. Optional. - @param nIdx - Start referring to the paragraph. - @param nLen -@@ -365,7 +361,7 @@ public: - @return The number of extra spaces in the given range - */ - static TextFrameIndex ThaiJustify( const OUString& rText, sal_Int32* pKernArray, -- sal_Int32* pScrArray, TextFrameIndex nIdx, -+ TextFrameIndex nIdx, - TextFrameIndex nLen, - TextFrameIndex nNumberOfBlanks = TextFrameIndex(0), - tools::Long nSpaceAdd = 0 ); -@@ -374,7 +370,7 @@ public: - TextFrameIndex nPos, TextFrameIndex nEnd, LanguageType aLang); - - static void CJKJustify( const OUString& rText, sal_Int32* pKernArray, -- sal_Int32* pScrArray, TextFrameIndex nStt, -+ TextFrameIndex nStt, - TextFrameIndex nLen, LanguageType aLang, - tools::Long nSpaceAdd, bool bIsSpaceStop ); - -diff --git a/sw/source/core/text/itradj.cxx b/sw/source/core/text/itradj.cxx -index d664602bf3ce..a952ce7649c2 100644 ---- a/sw/source/core/text/itradj.cxx -+++ b/sw/source/core/text/itradj.cxx -@@ -122,7 +122,7 @@ static bool lcl_CheckKashidaPositions( SwScriptInfo& rSI, SwTextSizeInfo& rInf, - // total number of kashida positions, or the number of kashida positions after some positions - // have been dropped. - // Here we want the clean total, which is OK: We have called ClearKashidaInvalid() before. -- rKashidas = rSI.KashidaJustify ( nullptr, nullptr, rItr.GetStart(), rItr.GetLength() ); -+ rKashidas = rSI.KashidaJustify(nullptr, rItr.GetStart(), rItr.GetLength()); - - if (rKashidas <= 0) // nothing to do - return true; -@@ -147,7 +147,7 @@ static bool lcl_CheckKashidaPositions( SwScriptInfo& rSI, SwTextSizeInfo& rInf, - - if (nNext == TextFrameIndex(COMPLETE_STRING) || nNext > nEnd) - nNext = nEnd; -- sal_Int32 nKashidasInAttr = rSI.KashidaJustify ( nullptr, nullptr, nIdx, nNext - nIdx ); -+ sal_Int32 nKashidasInAttr = rSI.KashidaJustify(nullptr, nIdx, nNext - nIdx); - if (nKashidasInAttr > 0) - { - // Kashida glyph looks suspicious, skip Kashida justification -@@ -212,7 +212,7 @@ static bool lcl_CheckKashidaWidth ( SwScriptInfo& rSI, SwTextSizeInfo& rInf, SwT - - if (nNext == TextFrameIndex(COMPLETE_STRING) || nNext > nEnd) - nNext = nEnd; -- sal_Int32 nKashidasInAttr = rSI.KashidaJustify ( nullptr, nullptr, nIdx, nNext - nIdx ); -+ sal_Int32 nKashidasInAttr = rSI.KashidaJustify(nullptr, nIdx, nNext - nIdx); - - tools::Long nFontMinKashida = rInf.GetOut()->GetMinKashida(); - if ( nFontMinKashida && nKashidasInAttr > 0 && SwScriptInfo::IsArabicText( rInf.GetText(), nIdx, nNext - nIdx ) ) -diff --git a/sw/source/core/text/porlay.cxx b/sw/source/core/text/porlay.cxx -index 3db5d2ab0ac3..bd9d6a0e143c 100644 ---- a/sw/source/core/text/porlay.cxx -+++ b/sw/source/core/text/porlay.cxx -@@ -2183,7 +2183,6 @@ tools::Long SwScriptInfo::Compress(sal_Int32* pKernArray, TextFrameIndex nIdx, T - // have been dropped, depending on the state of the m_KashidaInvalid set. - - sal_Int32 SwScriptInfo::KashidaJustify( sal_Int32* pKernArray, -- sal_Int32* pScrArray, - TextFrameIndex const nStt, - TextFrameIndex const nLen, - tools::Long nSpaceAdd ) const -@@ -2253,8 +2252,6 @@ sal_Int32 SwScriptInfo::KashidaJustify( sal_Int32* pKernArray, - while ( nArrayPos < nArrayEnd ) - { - pKernArray[ sal_Int32(nArrayPos) ] += nKashAdd; -- if ( pScrArray ) -- pScrArray[ sal_Int32(nArrayPos) ] += nKashAdd; - ++nArrayPos; - } - nKashAdd += nSpaceAdd; -@@ -2442,7 +2439,7 @@ void SwScriptInfo::MarkKashidasInvalid(sal_Int32 const nCnt, - } - - TextFrameIndex SwScriptInfo::ThaiJustify( const OUString& rText, sal_Int32* pKernArray, -- sal_Int32* pScrArray, TextFrameIndex const nStt, -+ TextFrameIndex const nStt, - TextFrameIndex const nLen, - TextFrameIndex nNumberOfBlanks, - tools::Long nSpaceAdd ) -@@ -2474,7 +2471,6 @@ TextFrameIndex SwScriptInfo::ThaiJustify( const OUString& rText, sal_Int32* pKer - } - - if ( pKernArray ) pKernArray[ nI ] += nSpaceSum; -- if ( pScrArray ) pScrArray[ nI ] += nSpaceSum; - } - - return nCnt; -@@ -2775,7 +2771,7 @@ TextFrameIndex SwScriptInfo::CountCJKCharacters(const OUString &rText, - } - - void SwScriptInfo::CJKJustify( const OUString& rText, sal_Int32* pKernArray, -- sal_Int32* pScrArray, TextFrameIndex const nStt, -+ TextFrameIndex const nStt, - TextFrameIndex const nLen, LanguageType aLang, - tools::Long nSpaceAdd, bool bIsSpaceStop ) - { -@@ -2798,8 +2794,6 @@ void SwScriptInfo::CJKJustify( const OUString& rText, sal_Int32* pKernArray, - nSpaceSum += nSpaceAdd; - } - pKernArray[ nI ] += nSpaceSum; -- if ( pScrArray ) -- pScrArray[ nI ] += nSpaceSum; - } - } - /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ -diff --git a/sw/source/core/text/portxt.cxx b/sw/source/core/text/portxt.cxx -index 7def7badcc7a..219036aa834d 100644 ---- a/sw/source/core/text/portxt.cxx -+++ b/sw/source/core/text/portxt.cxx -@@ -113,7 +113,7 @@ static TextFrameIndex lcl_AddSpace(const SwTextSizeInfo &rInf, - { - if ( SwScriptInfo::IsArabicText( *pStr, nPos, nEnd - nPos ) && pSI->CountKashida() ) - { -- const sal_Int32 nKashRes = pSI->KashidaJustify( nullptr, nullptr, nPos, nEnd - nPos ); -+ const sal_Int32 nKashRes = pSI->KashidaJustify(nullptr, nPos, nEnd - nPos); - // i60591: need to check result of KashidaJustify - // determine if kashida justification is applicable - if (nKashRes != -1) -@@ -129,7 +129,7 @@ static TextFrameIndex lcl_AddSpace(const SwTextSizeInfo &rInf, - - if ( LANGUAGE_THAI == aLang ) - { -- nCnt = SwScriptInfo::ThaiJustify( *pStr, nullptr, nullptr, nPos, nEnd - nPos ); -+ nCnt = SwScriptInfo::ThaiJustify(*pStr, nullptr, nPos, nEnd - nPos); - - const SwLinePortion* pPor = rPor.GetNextPortion(); - if ( pPor && ( pPor->IsKernPortion() || -diff --git a/sw/source/core/txtnode/fntcache.cxx b/sw/source/core/txtnode/fntcache.cxx -index 93e83c2013e9..6ceaeaf99206 100644 ---- a/sw/source/core/txtnode/fntcache.cxx -+++ b/sw/source/core/txtnode/fntcache.cxx -@@ -77,11 +77,11 @@ static vcl::DeleteOnDeinit< VclPtr > s_pFntObjPixOut {}; - * Defines a substring on a given output device, to be used as an std::unordered_map<> - * key. - */ --SwTextGlyphsKey::SwTextGlyphsKey(VclPtr const& pOutputDevice, const OUString & sText, sal_Int32 nIndex, sal_Int32 nLength) -+SwTextGlyphsKey::SwTextGlyphsKey(const OutputDevice* pOutputDevice, const OUString & sText, sal_Int32 nIndex, sal_Int32 nLength) - : m_pOutputDevice(pOutputDevice), m_aText(sText), m_nIndex(nIndex), m_nLength(nLength) - { - mnHashCode = 0; -- o3tl::hash_combine(mnHashCode, pOutputDevice.get()); -+ o3tl::hash_combine(mnHashCode, pOutputDevice); - o3tl::hash_combine(mnHashCode, m_nIndex); - o3tl::hash_combine(mnHashCode, m_nLength); - if(m_nLength >= 0 && m_nIndex >= 0 && m_nIndex + m_nLength <= m_aText.getLength()) -@@ -855,6 +855,18 @@ static void lcl_DrawLineForWrongListData( - rInf.GetOut().Pop(); - } - -+void SwFntObj::GetTextArray(const OutputDevice& rDevice, const OUString& rStr, std::vector& rDXAry, -+ sal_Int32 nIndex, sal_Int32 nLen, bool bCaching) -+{ -+ SalLayoutGlyphs* pLayoutCache = nullptr; -+ if (bCaching) -+ { -+ SwTextGlyphsKey aGlyphsKey{&rDevice, rStr, nIndex, nLen}; -+ pLayoutCache = GetCachedSalLayoutGlyphs(aGlyphsKey); -+ } -+ rDevice.GetTextArray(rStr, &rDXAry, nIndex, nLen, nullptr, pLayoutCache); -+} -+ - void SwFntObj::DrawText( SwDrawTextInfo &rInf ) - { - OSL_ENSURE( rInf.GetShell(), "SwFntObj::DrawText without shell" ); -@@ -1031,11 +1043,11 @@ void SwFntObj::DrawText( SwDrawTextInfo &rInf ) - std::vector aKernArray; - - if ( m_pPrinter ) -- m_pPrinter->GetTextArray( rInf.GetText(), &aKernArray, -- sal_Int32(rInf.GetIdx()), sal_Int32(rInf.GetLen())); -+ GetTextArray(*m_pPrinter, rInf.GetText(), aKernArray, -+ sal_Int32(rInf.GetIdx()), sal_Int32(rInf.GetLen()), false); - else -- rInf.GetOut().GetTextArray( rInf.GetText(), &aKernArray, -- sal_Int32(rInf.GetIdx()), sal_Int32(rInf.GetLen())); -+ GetTextArray(rInf.GetOut(), rInf.GetText(), aKernArray, -+ sal_Int32(rInf.GetIdx()), sal_Int32(rInf.GetLen()), false); - - // Change the average width per character to an appropriate grid width - // basically get the ratio of the avg width to the grid unit width, then -@@ -1138,11 +1150,11 @@ void SwFntObj::DrawText( SwDrawTextInfo &rInf ) - std::vector aKernArray; - - if ( m_pPrinter ) -- m_pPrinter->GetTextArray( rInf.GetText(), &aKernArray, -- sal_Int32(rInf.GetIdx()), sal_Int32(rInf.GetLen())); -+ GetTextArray(*m_pPrinter, rInf.GetText(), aKernArray, -+ sal_Int32(rInf.GetIdx()), sal_Int32(rInf.GetLen()), false); - else -- rInf.GetOut().GetTextArray( rInf.GetText(), &aKernArray, -- sal_Int32(rInf.GetIdx()), sal_Int32(rInf.GetLen())); -+ GetTextArray(rInf.GetOut(), rInf.GetText(), aKernArray, -+ sal_Int32(rInf.GetIdx()), sal_Int32(rInf.GetLen()), false); - if ( bSwitchH2V ) - rInf.GetFrame()->SwitchHorizontalToVertical( aTextOriginPos ); - if ( rInf.GetSpace() || rInf.GetKanaComp()) -@@ -1278,8 +1290,8 @@ void SwFntObj::DrawText( SwDrawTextInfo &rInf ) - if( rInf.GetSpace() || rInf.GetKanaComp() ) - { - std::vector aKernArray; -- rInf.GetOut().GetTextArray( rInf.GetText(), &aKernArray, -- sal_Int32(rInf.GetIdx()), sal_Int32(rInf.GetLen())); -+ GetTextArray(rInf.GetOut(), rInf.GetText(), aKernArray, -+ sal_Int32(rInf.GetIdx()), sal_Int32(rInf.GetLen()), false); - - if( bStretch ) - { -@@ -1337,7 +1349,7 @@ void SwFntObj::DrawText( SwDrawTextInfo &rInf ) - - if (!MsLangId::isKorean(aLang)) - { -- SwScriptInfo::CJKJustify( rInf.GetText(), aKernArray.data(), nullptr, -+ SwScriptInfo::CJKJustify( rInf.GetText(), aKernArray.data(), - rInf.GetIdx(), rInf.GetLen(), aLang, nSpaceAdd, rInf.IsSpaceStop() ); - - bSpecialJust = true; -@@ -1351,7 +1363,7 @@ void SwFntObj::DrawText( SwDrawTextInfo &rInf ) - if ( SwScriptInfo::IsArabicText( rInf.GetText(), rInf.GetIdx(), rInf.GetLen() ) ) - { - if ( pSI && pSI->CountKashida() && -- pSI->KashidaJustify( aKernArray.data(), nullptr, rInf.GetIdx(), -+ pSI->KashidaJustify( aKernArray.data(), rInf.GetIdx(), - rInf.GetLen(), nSpaceAdd ) != -1 ) - { - bSpecialJust = true; -@@ -1369,7 +1381,7 @@ void SwFntObj::DrawText( SwDrawTextInfo &rInf ) - { - // Use rInf.GetSpace() because it has more precision than - // nSpaceAdd: -- SwScriptInfo::ThaiJustify( rInf.GetText(), aKernArray.data(), nullptr, -+ SwScriptInfo::ThaiJustify( rInf.GetText(), aKernArray.data(), - rInf.GetIdx(), rInf.GetLen(), - rInf.GetNumberOfBlanks(), - rInf.GetSpace() ); -@@ -1478,6 +1490,10 @@ void SwFntObj::DrawText( SwDrawTextInfo &rInf ) - - else - { -+ const bool bOrigTextRenderModeForResolutionIndependentLayout(rInf.GetOut().GetTextRenderModeForResolutionIndependentLayout()); -+ // set text render mode to suit use of resolution independent text layout -+ rInf.GetOut().SetTextRenderModeForResolutionIndependentLayout(true); -+ - const OUString* pStr = &rInf.GetText(); - - OUString aStr; -@@ -1487,14 +1503,6 @@ void SwFntObj::DrawText( SwDrawTextInfo &rInf ) - bBullet = false; - std::vector aKernArray; - CreateScrFont( *rInf.GetShell(), rInf.GetOut() ); -- tools::Long nScrPos; -- -- // get screen array -- std::vector aScrArray; -- SwTextGlyphsKey aGlyphsKey{ &rInf.GetOut(), rInf.GetText(), sal_Int32(rInf.GetIdx()), sal_Int32(rInf.GetLen()) }; -- SalLayoutGlyphs* pGlyphs = GetCachedSalLayoutGlyphs(aGlyphsKey); -- rInf.GetOut().GetTextArray( rInf.GetText(), &aScrArray, -- sal_Int32(rInf.GetIdx()), sal_Int32(rInf.GetLen()), nullptr, pGlyphs); - - // OLE: no printer available - // OSL_ENSURE( pPrinter, "DrawText needs pPrinter" ) -@@ -1506,15 +1514,13 @@ void SwFntObj::DrawText( SwDrawTextInfo &rInf ) - if( !m_pPrtFont->IsSameInstance( m_pPrinter->GetFont() ) ) - m_pPrinter->SetFont( *m_pPrtFont ); - } -- aGlyphsKey = SwTextGlyphsKey{ m_pPrinter, rInf.GetText(), sal_Int32(rInf.GetIdx()), sal_Int32(rInf.GetLen()) }; -- pGlyphs = GetCachedSalLayoutGlyphs(aGlyphsKey); -- m_pPrinter->GetTextArray(rInf.GetText(), &aKernArray, -- sal_Int32(rInf.GetIdx()), sal_Int32(rInf.GetLen()), nullptr, pGlyphs); -+ GetTextArray(*m_pPrinter, rInf.GetText(), aKernArray, -+ sal_Int32(rInf.GetIdx()), sal_Int32(rInf.GetLen()), true); - } - else - { -- rInf.GetOut().GetTextArray( rInf.GetText(), &aKernArray, -- sal_Int32(rInf.GetIdx()), sal_Int32(rInf.GetLen())); -+ GetTextArray(rInf.GetOut(), rInf.GetText(), aKernArray, -+ sal_Int32(rInf.GetIdx()), sal_Int32(rInf.GetLen()), true); - } - - // Modify Printer and ScreenArrays for special justifications -@@ -1532,10 +1538,6 @@ void SwFntObj::DrawText( SwDrawTextInfo &rInf ) - pSI && pSI->CountCompChg() && - lcl_IsMonoSpaceFont( rInf.GetOut() ) ) - { -- Point aTmpPos( aTextOriginPos ); -- pSI->Compress( aScrArray.data(), rInf.GetIdx(), rInf.GetLen(), -- rInf.GetKanaComp(), -- o3tl::narrowing(m_aFont.GetFontSize().Height()), lcl_IsFullstopCentered( rInf.GetOut() ), &aTmpPos ); - pSI->Compress( aKernArray.data(), rInf.GetIdx(), rInf.GetLen(), - rInf.GetKanaComp(), - o3tl::narrowing(m_aFont.GetFontSize().Height()), lcl_IsFullstopCentered( rInf.GetOut() ), &aTextOriginPos ); -@@ -1548,7 +1550,7 @@ void SwFntObj::DrawText( SwDrawTextInfo &rInf ) - - if (!MsLangId::isKorean(aLang)) - { -- SwScriptInfo::CJKJustify( rInf.GetText(), aKernArray.data(), aScrArray.data(), -+ SwScriptInfo::CJKJustify( rInf.GetText(), aKernArray.data(), - rInf.GetIdx(), rInf.GetLen(), aLang, nSpaceAdd, rInf.IsSpaceStop() ); - - nSpaceAdd = 0; -@@ -1561,7 +1563,7 @@ void SwFntObj::DrawText( SwDrawTextInfo &rInf ) - if ( SwScriptInfo::IsArabicText( rInf.GetText(), rInf.GetIdx(), rInf.GetLen() ) ) - { - if ( pSI && pSI->CountKashida() && -- pSI->KashidaJustify( aKernArray.data(), aScrArray.data(), rInf.GetIdx(), -+ pSI->KashidaJustify( aKernArray.data(), rInf.GetIdx(), - rInf.GetLen(), nSpaceAdd ) != -1 ) - nSpaceAdd = 0; - else -@@ -1577,7 +1579,7 @@ void SwFntObj::DrawText( SwDrawTextInfo &rInf ) - if ( LANGUAGE_THAI == aLang ) - { - SwScriptInfo::ThaiJustify( rInf.GetText(), aKernArray.data(), -- aScrArray.data(), rInf.GetIdx(), -+ rInf.GetIdx(), - rInf.GetLen(), - rInf.GetNumberOfBlanks(), - rInf.GetSpace() ); -@@ -1588,8 +1590,6 @@ void SwFntObj::DrawText( SwDrawTextInfo &rInf ) - } - } - -- nScrPos = aScrArray[ 0 ]; -- - if( bBullet ) - { - // !!! HACK !!! -@@ -1661,13 +1661,6 @@ void SwFntObj::DrawText( SwDrawTextInfo &rInf ) - } - else - { -- sal_Unicode nCh; -- -- // In case of Pair Kerning the printer influence on the positioning -- // grows -- const int nMul = m_pPrtFont->GetKerning() != FontKerning::NONE ? 1 : 3; -- const int nDiv = nMul+1; -- - // nSpaceSum contains the sum of the intermediate space distributed - // among Spaces by the Justification. - // The Spaces themselves will be positioned in the middle of the -@@ -1686,43 +1679,25 @@ void SwFntObj::DrawText( SwDrawTextInfo &rInf ) - nSpaceSum = nHalfSpace; - for (sal_Int32 i = 1; i < sal_Int32(nCnt); ++i, nKernSum += rInf.GetKern()) - { -- nCh = rInf.GetText()[sal_Int32(rInf.GetIdx()) + i]; -- -- tools::Long nScr = aScrArray[ i ] - aScrArray[ i - 1 ]; -+ sal_Unicode nCh = rInf.GetText()[sal_Int32(rInf.GetIdx()) + i]; - -- // If there is an (ex-)Space before us, position optimally, -- // i.e., our right margin to the 100% printer position; -- // if we _are_ an ex-Space, position us left-aligned to the -- // printer position. -- if ( nCh == CH_BLANK ) -+ // Apply SpaceSum -+ if (cChPrev == CH_BLANK) - { -- nScrPos = aKernArray[i-1] + nScr; -+ // no Pixel is lost: -+ nSpaceSum += nOtherHalf; -+ } - -- if ( cChPrev == CH_BLANK ) -- nSpaceSum += nOtherHalf; -+ if (nCh == CH_BLANK) -+ { - if (i + 1 == sal_Int32(nCnt)) - nSpaceSum += nSpaceAdd; - else - nSpaceSum += nHalfSpace; - } -- else -- { -- if ( cChPrev == CH_BLANK ) -- { -- nScrPos = aKernArray[i-1] + nScr; -- // no Pixel is lost: -- nSpaceSum += nOtherHalf; -- } -- else if ( cChPrev == '-' ) -- nScrPos = aKernArray[i-1] + nScr; -- else -- { -- nScrPos += nScr; -- nScrPos = ( nMul * nScrPos + aKernArray[i] ) / nDiv; -- } -- } -+ - cChPrev = nCh; -- aKernArray[i-1] = nScrPos - nScr + nKernSum + nSpaceSum; -+ aKernArray[i-1] += nKernSum + nSpaceSum; - // In word line mode and for Arabic, we disabled the half space trick. If a portion - // ends with a blank, the full nSpaceAdd value has been added to the character in - // front of the blank. This leads to painting artifacts, therefore we remove the -@@ -1843,8 +1818,8 @@ void SwFntObj::DrawText( SwDrawTextInfo &rInf ) - sal_Int32 nTmpIdx = bBullet - ? (rInf.GetIdx() ? 1 : 0) - : sal_Int32(rInf.GetIdx()); -- aGlyphsKey = SwTextGlyphsKey{ &rInf.GetOut(), *pStr, nTmpIdx, nLen }; -- pGlyphs = GetCachedSalLayoutGlyphs(aGlyphsKey); -+ SwTextGlyphsKey aGlyphsKey{ &rInf.GetOut(), *pStr, nTmpIdx, nLen }; -+ SalLayoutGlyphs* pGlyphs = GetCachedSalLayoutGlyphs(aGlyphsKey); - rInf.GetOut().DrawTextArray( aTextOriginPos, *pStr, aKernArray, - nTmpIdx , nLen, SalLayoutFlags::NONE, pGlyphs ); - if (bBullet) -@@ -1894,6 +1869,8 @@ void SwFntObj::DrawText( SwDrawTextInfo &rInf ) - } - } - } -+ -+ rInf.GetOut().SetTextRenderModeForResolutionIndependentLayout(bOrigTextRenderModeForResolutionIndependentLayout); - } - } - -@@ -1997,17 +1974,14 @@ Size SwFntObj::GetTextSize( SwDrawTextInfo& rInf ) - { - if( !m_pPrtFont->IsSameInstance( m_pPrinter->GetFont() ) ) - m_pPrinter->SetFont(*m_pPrtFont); -- aTextSize.setWidth( m_pPrinter->GetTextWidth( rInf.GetText(), -- sal_Int32(rInf.GetIdx()), sal_Int32(nLn))); - aTextSize.setHeight( m_pPrinter->GetTextHeight() ); - std::vector aKernArray; - CreateScrFont( *rInf.GetShell(), rInf.GetOut() ); - if( !GetScrFont()->IsSameInstance( rInf.GetOut().GetFont() ) ) - rInf.GetOut().SetFont( *m_pScrFont ); -- tools::Long nScrPos; - -- m_pPrinter->GetTextArray(rInf.GetText(), &aKernArray, -- sal_Int32(rInf.GetIdx()), sal_Int32(nLn)); -+ GetTextArray(*m_pPrinter, rInf.GetText(), aKernArray, -+ sal_Int32(rInf.GetIdx()), sal_Int32(nLn), false); - if( bCompress ) - rInf.SetKanaDiff( rInf.GetScriptInfo()->Compress( aKernArray.data(), - rInf.GetIdx(), nLn, rInf.GetKanaComp(), -@@ -2015,50 +1989,7 @@ Size SwFntObj::GetTextSize( SwDrawTextInfo& rInf ) - else - rInf.SetKanaDiff( 0 ); - -- if ( rInf.GetKanaDiff() ) -- nScrPos = aKernArray[ sal_Int32(nLn) - 1 ]; -- else -- { -- std::vector aScrArray; -- rInf.GetOut().GetTextArray( rInf.GetText(), &aScrArray, -- sal_Int32(rInf.GetIdx()), sal_Int32(rInf.GetLen())); -- nScrPos = aScrArray[ 0 ]; -- TextFrameIndex nCnt(rInf.GetText().getLength()); -- if ( nCnt < rInf.GetIdx() ) -- nCnt = TextFrameIndex(0); // assert??? -- else -- nCnt = nCnt - rInf.GetIdx(); -- nCnt = std::min(nCnt, nLn); -- sal_Unicode nChPrev = rInf.GetText()[ sal_Int32(rInf.GetIdx()) ]; -- -- sal_Unicode nCh; -- -- // In case of Pair Kerning the printer influence on the positioning -- // grows -- const int nMul = m_pPrtFont->GetKerning() != FontKerning::NONE ? 1 : 3; -- const int nDiv = nMul+1; -- for (sal_Int32 i = 1; i < sal_Int32(nCnt); i++) -- { -- nCh = rInf.GetText()[ sal_Int32(rInf.GetIdx()) + i ]; -- tools::Long nScr = aScrArray[ i ] - aScrArray[ i - 1 ]; -- if ( nCh == CH_BLANK ) -- nScrPos = aKernArray[i-1]+nScr; -- else -- { -- if ( nChPrev == CH_BLANK || nChPrev == '-' ) -- nScrPos = aKernArray[i-1]+nScr; -- else -- { -- nScrPos += nScr; -- nScrPos = ( nMul * nScrPos + aKernArray[i] ) / nDiv; -- } -- } -- nChPrev = nCh; -- aKernArray[i-1] = nScrPos - nScr; -- } -- } -- -- aTextSize.setWidth( nScrPos ); -+ aTextSize.setWidth(aKernArray[sal_Int32(nLn) - 1]); - } - else - { -@@ -2067,8 +1998,8 @@ Size SwFntObj::GetTextSize( SwDrawTextInfo& rInf ) - if( bCompress ) - { - std::vector aKernArray; -- rInf.GetOut().GetTextArray( rInf.GetText(), &aKernArray, -- sal_Int32(rInf.GetIdx()), sal_Int32(nLn)); -+ GetTextArray(rInf.GetOut(), rInf.GetText(), aKernArray, -+ sal_Int32(rInf.GetIdx()), sal_Int32(nLn), false); - rInf.SetKanaDiff( rInf.GetScriptInfo()->Compress( aKernArray.data(), - rInf.GetIdx(), nLn, rInf.GetKanaComp(), - o3tl::narrowing(m_aFont.GetFontSize().Height()) ,lcl_IsFullstopCentered( rInf.GetOut() ) ) ); -@@ -2110,14 +2041,14 @@ TextFrameIndex SwFntObj::GetModelPositionForViewPoint(SwDrawTextInfo &rInf) - { - m_pPrinter->SetLayoutMode( rInf.GetOut().GetLayoutMode() ); - m_pPrinter->SetDigitLanguage( rInf.GetOut().GetDigitLanguage() ); -- SwTextGlyphsKey aGlyphsKey{ m_pPrinter, rInf.GetText(), sal_Int32(rInf.GetIdx()), sal_Int32(rInf.GetLen()) }; -- SalLayoutGlyphs* pGlyphs = GetCachedSalLayoutGlyphs(aGlyphsKey); -- m_pPrinter->GetTextArray( rInf.GetText(), &aKernArray, -- sal_Int32(rInf.GetIdx()), sal_Int32(rInf.GetLen()), nullptr, pGlyphs); -+ GetTextArray(*m_pPrinter, rInf.GetText(), aKernArray, -+ sal_Int32(rInf.GetIdx()), sal_Int32(rInf.GetLen()), true); - } - else -- rInf.GetOut().GetTextArray( rInf.GetText(), &aKernArray, -- sal_Int32(rInf.GetIdx()), sal_Int32(rInf.GetLen())); -+ { -+ GetTextArray(rInf.GetOut(), rInf.GetText(), aKernArray, -+ sal_Int32(rInf.GetIdx()), sal_Int32(rInf.GetLen()), false); -+ } - - const SwScriptInfo* pSI = rInf.GetScriptInfo(); - if ( rInf.GetFont() && rInf.GetLen() ) -@@ -2142,7 +2073,7 @@ TextFrameIndex SwFntObj::GetModelPositionForViewPoint(SwDrawTextInfo &rInf) - - if (!MsLangId::isKorean(aLang)) - { -- SwScriptInfo::CJKJustify( rInf.GetText(), aKernArray.data(), nullptr, -+ SwScriptInfo::CJKJustify( rInf.GetText(), aKernArray.data(), - rInf.GetIdx(), rInf.GetLen(), aLang, nSpaceAdd, rInf.IsSpaceStop() ); - - nSpaceAdd = 0; -@@ -2156,7 +2087,7 @@ TextFrameIndex SwFntObj::GetModelPositionForViewPoint(SwDrawTextInfo &rInf) - if ( SwScriptInfo::IsArabicText( rInf.GetText(), rInf.GetIdx(), rInf.GetLen() ) ) - { - if ( pSI && pSI->CountKashida() && -- pSI->KashidaJustify( aKernArray.data(), nullptr, rInf.GetIdx(), rInf.GetLen(), -+ pSI->KashidaJustify( aKernArray.data(), rInf.GetIdx(), rInf.GetLen(), - nSpaceAdd ) != -1 ) - nSpaceAdd = 0; - } -@@ -2169,7 +2100,7 @@ TextFrameIndex SwFntObj::GetModelPositionForViewPoint(SwDrawTextInfo &rInf) - - if ( LANGUAGE_THAI == aLang ) - { -- SwScriptInfo::ThaiJustify( rInf.GetText(), aKernArray.data(), nullptr, -+ SwScriptInfo::ThaiJustify( rInf.GetText(), aKernArray.data(), - rInf.GetIdx(), rInf.GetLen(), - rInf.GetNumberOfBlanks(), - rInf.GetSpace() ); -diff --git a/sw/source/uibase/config/usrpref.cxx b/sw/source/uibase/config/usrpref.cxx -index 0c759a78cf94..e7b43df54c34 100644 ---- a/sw/source/uibase/config/usrpref.cxx -+++ b/sw/source/uibase/config/usrpref.cxx -@@ -388,7 +388,7 @@ void SwLayoutViewConfig::Load() - case 16: m_rParent.SetViewLayoutBookMode(bSet); break;// "ViewLayout/BookMode", - case 17: m_rParent.SetDefaultPageMode(bSet,true); break;// "Other/IsSquaredPageMode", - case 18: m_rParent.SetApplyCharUnit(bSet, true); break;// "Other/ApplyUserChar" -- case 19: m_rParent.SetShowScrollBarTips(bSet); break;// "Window/ShowScrollBarTips", -+ case 29: m_rParent.SetShowScrollBarTips(bSet); break;// "Window/ShowScrollBarTips", - } - } - } -diff --git a/vcl/inc/ImplLayoutArgs.hxx b/vcl/inc/ImplLayoutArgs.hxx -index 865470b7897a..fa94562ca86c 100644 ---- a/vcl/inc/ImplLayoutArgs.hxx -+++ b/vcl/inc/ImplLayoutArgs.hxx -@@ -35,7 +35,8 @@ public: - vcl::text::TextLayoutCache const* m_pTextLayoutCache; - - // positioning related inputs -- const DeviceCoordinate* mpDXArray; // in pixel units -+ const DeviceCoordinate* mpDXArray; // in integer pixel units -+ const double* mpAltNaturalDXArray; // in floating point pixel units - DeviceCoordinate mnLayoutWidth; // in pixel units - Degree10 mnOrientation; // in 0-3600 system - -@@ -48,12 +49,15 @@ public: - - void SetLayoutWidth(DeviceCoordinate nWidth); - void SetDXArray(const DeviceCoordinate* pDXArray); -+ void SetAltNaturalDXArray(const double* pDXArray); - void SetOrientation(Degree10 nOrientation); - - void ResetPos(); - bool GetNextPos(int* nCharPos, bool* bRTL); - bool GetNextRun(int* nMinRunPos, int* nEndRunPos, bool* bRTL); - void AddFallbackRun(int nMinRunPos, int nEndRunPos, bool bRTL); -+ bool HasDXArray() const { return mpDXArray || mpAltNaturalDXArray; } -+ - // methods used by BiDi and glyph fallback - bool HasFallbackRun() const; - bool PrepareFallback(const SalLayoutGlyphsImpl* pGlyphsImpl); -diff --git a/vcl/inc/impglyphitem.hxx b/vcl/inc/impglyphitem.hxx -index ca9f7cf5c052..4fc48f1ca2a2 100644 ---- a/vcl/inc/impglyphitem.hxx -+++ b/vcl/inc/impglyphitem.hxx -@@ -58,10 +58,10 @@ class VCL_DLLPUBLIC GlyphItem - GlyphItemFlags m_nFlags; - - public: -- Point m_aLinearPos; // absolute position of non rotated string -+ DevicePoint m_aLinearPos; // absolute position of non rotated string - sal_Int32 m_nNewWidth; // width after adjustments - -- GlyphItem(int nCharPos, int nCharCount, sal_GlyphId aGlyphId, const Point& rLinearPos, -+ GlyphItem(int nCharPos, int nCharCount, sal_GlyphId aGlyphId, const DevicePoint& rLinearPos, - GlyphItemFlags nFlags, int nOrigWidth, int nXOffset) - : m_nOrigWidth(nOrigWidth) - , m_nCharPos(nCharPos) -diff --git a/vcl/inc/quartz/salgdi.h b/vcl/inc/quartz/salgdi.h -index f0aa925c6083..569a14a6d3fc 100644 ---- a/vcl/inc/quartz/salgdi.h -+++ b/vcl/inc/quartz/salgdi.h -@@ -297,7 +297,7 @@ public: - const tools::Rectangle &rControlRegion, - ControlState nState, - const ImplControlValue &aValue) = 0; -- virtual void drawTextLayout(const GenericSalLayout& layout) = 0; -+ virtual void drawTextLayout(const GenericSalLayout& layout, bool bTextRenderModeForResolutionIndependentLayout) = 0; - virtual void Flush() {} - virtual void Flush( const tools::Rectangle& ) {} - protected: -@@ -446,7 +446,7 @@ public: - ControlState nState, - const ImplControlValue &aValue) override; - -- virtual void drawTextLayout(const GenericSalLayout& layout) override; -+ virtual void drawTextLayout(const GenericSalLayout& layout, bool bTextRenderModeForResolutionIndependentLayout) override; - - bool supportsOperation(OutDevSupportType eType) const override; - }; -diff --git a/vcl/inc/salgdi.hxx b/vcl/inc/salgdi.hxx -index 716c9aa934a6..6f9ee67f69a4 100644 ---- a/vcl/inc/salgdi.hxx -+++ b/vcl/inc/salgdi.hxx -@@ -96,6 +96,16 @@ public: - return m_bAntiAlias; - } - -+ void setTextRenderModeForResolutionIndependentLayout(bool bNew) -+ { -+ m_bTextRenderModeForResolutionIndependentLayout = bNew; -+ } -+ -+ bool getTextRenderModeForResolutionIndependentLayoutEnabled() const -+ { -+ return m_bTextRenderModeForResolutionIndependentLayout; -+ } -+ - // public SalGraphics methods, the interface to the independent vcl part - - // get device resolution -@@ -631,6 +641,7 @@ private: - protected: - /// flags which hold the SetAntialiasing() value from OutputDevice - bool m_bAntiAlias : 1; -+ bool m_bTextRenderModeForResolutionIndependentLayout : 1; - - inline tools::Long GetDeviceWidth(const OutputDevice& rOutDev) const; - -diff --git a/vcl/inc/sallayout.hxx b/vcl/inc/sallayout.hxx -index ab29a2022985..847c22ace091 100644 ---- a/vcl/inc/sallayout.hxx -+++ b/vcl/inc/sallayout.hxx -@@ -64,7 +64,7 @@ public: - sal_Int32 GetTextBreak(DeviceCoordinate nMaxWidth, DeviceCoordinate nCharExtra, int nFactor) const override; - DeviceCoordinate FillDXArray(std::vector* pDXArray) const override; - void GetCaretPositions(int nArraySize, sal_Int32* pCaretXArray) const override; -- bool GetNextGlyph(const GlyphItem** pGlyph, Point& rPos, int& nStart, -+ bool GetNextGlyph(const GlyphItem** pGlyph, DevicePoint& rPos, int& nStart, - const LogicalFontInstance** ppGlyphFont = nullptr, - const vcl::font::PhysicalFontFace** pFallbackFont = nullptr) const override; - bool GetOutline(basegfx::B2DPolyPolygonVector&) const override; -@@ -82,7 +82,11 @@ public: - - void SetIncomplete(bool bIncomplete); - --public: -+ template -+ void ImplAdjustMultiLayout(vcl::text::ImplLayoutArgs& rArgs, -+ vcl::text::ImplLayoutArgs& rMultiArgs, -+ const DC* pMultiDXArray); -+ - virtual ~MultiSalLayout() override; - - private: -@@ -97,7 +101,10 @@ private: - - class VCL_DLLPUBLIC GenericSalLayout : public SalLayout - { -- friend void MultiSalLayout::AdjustLayout(vcl::text::ImplLayoutArgs&); -+ template friend void MultiSalLayout::ImplAdjustMultiLayout( -+ vcl::text::ImplLayoutArgs& rArgs, -+ vcl::text::ImplLayoutArgs& rMultiArgs, -+ const DC* pMultiDXArray); - - public: - GenericSalLayout(LogicalFontInstance&); -@@ -121,7 +128,7 @@ public: - LogicalFontInstance& GetFont() const - { return *m_GlyphItems.GetFont(); } - -- bool GetNextGlyph(const GlyphItem** pGlyph, Point& rPos, int& nStart, -+ bool GetNextGlyph(const GlyphItem** pGlyph, DevicePoint& rPos, int& nStart, - const LogicalFontInstance** ppGlyphFont = nullptr, - const vcl::font::PhysicalFontFace** pFallbackFont = nullptr) const override; - -@@ -136,7 +143,8 @@ private: - GenericSalLayout( const GenericSalLayout& ) = delete; - GenericSalLayout& operator=( const GenericSalLayout& ) = delete; - -- void ApplyDXArray(const DeviceCoordinate*, SalLayoutFlags nLayoutFlags); -+ template -+ void ApplyDXArray(const DC*, SalLayoutFlags nLayoutFlags); - void Justify(DeviceCoordinate nNewWidth); - void ApplyAsianKerning(const OUString& rStr); - -diff --git a/vcl/inc/skia/osx/gdiimpl.hxx b/vcl/inc/skia/osx/gdiimpl.hxx -index e59aa60f56df..71baf24625fc 100644 ---- a/vcl/inc/skia/osx/gdiimpl.hxx -+++ b/vcl/inc/skia/osx/gdiimpl.hxx -@@ -38,7 +38,8 @@ public: - const tools::Rectangle& rControlRegion, ControlState nState, - const ImplControlValue& aValue) override; - -- virtual void drawTextLayout(const GenericSalLayout& layout) override; -+ virtual void drawTextLayout(const GenericSalLayout& layout, -+ bool bTextRenderModeForResolutionIndependentLayout) override; - - virtual void Flush() override; - virtual void Flush(const tools::Rectangle&) override; -diff --git a/vcl/inc/skia/win/gdiimpl.hxx b/vcl/inc/skia/win/gdiimpl.hxx -index 58043e5f6a83..a8897d0d7c20 100644 ---- a/vcl/inc/skia/win/gdiimpl.hxx -+++ b/vcl/inc/skia/win/gdiimpl.hxx -@@ -25,6 +25,8 @@ - #include - #include - -+#include -+ - class SkTypeface; - class ControlCacheKey; - -@@ -64,6 +66,8 @@ protected: - static void initFontInfo(); - inline static sal::systools::COMReference dwriteFactory; - inline static sal::systools::COMReference dwriteGdiInterop; -+ inline static sal::systools::COMReference dwriteFontSetBuilder; -+ inline static sal::systools::COMReference dwritePrivateCollection; - inline static sk_sp dwriteFontMgr; - inline static bool dwriteDone = false; - static SkFont::Edging fontEdging; -diff --git a/vcl/inc/win/DWriteTextRenderer.hxx b/vcl/inc/win/DWriteTextRenderer.hxx -index 6e097546d1e2..b64cc48a1c6a 100644 ---- a/vcl/inc/win/DWriteTextRenderer.hxx -+++ b/vcl/inc/win/DWriteTextRenderer.hxx -@@ -37,12 +37,13 @@ enum class D2DTextAntiAliasMode - class D2DWriteTextOutRenderer : public TextOutRenderer - { - public: -- explicit D2DWriteTextOutRenderer(); -+ explicit D2DWriteTextOutRenderer(bool bRenderingModeNatural); - virtual ~D2DWriteTextOutRenderer() override; - -- bool operator ()(GenericSalLayout const &rLayout, -+ bool operator()(GenericSalLayout const &rLayout, - SalGraphics &rGraphics, -- HDC hDC) override; -+ HDC hDC, -+ bool bRenderingModeNatural) override; - - HRESULT BindDC(HDC hDC, tools::Rectangle const & rRect = tools::Rectangle(0, 0, 1, 1)); - -@@ -54,12 +55,13 @@ public: - IDWriteFontFace * GetFontFace() const { return mpFontFace; } - float GetEmHeight() const { return mlfEmHeight; } - -- HRESULT CreateRenderTarget(); -+ HRESULT CreateRenderTarget(bool bRenderingModeNatural); - - bool Ready() const; - -- void applyTextAntiAliasMode(); -- void changeTextAntiAliasMode(D2DTextAntiAliasMode eMode); -+ void applyTextAntiAliasMode(bool bRenderingModeNatural); -+ -+ bool GetRenderingModeNatural() const { return mbRenderingModeNatural; } - - private: - // This is a singleton object disable copy ctor and assignment operator -@@ -67,7 +69,7 @@ private: - D2DWriteTextOutRenderer & operator = (const D2DWriteTextOutRenderer &) = delete; - - bool GetDWriteFaceFromHDC(HDC hDC, IDWriteFontFace ** ppFontFace, float * lfSize) const; -- bool performRender(GenericSalLayout const &rLayout, SalGraphics &rGraphics, HDC hDC, bool& bRetry); -+ bool performRender(GenericSalLayout const &rLayout, SalGraphics &rGraphics, HDC hDC, bool& bRetry, bool bRenderingModeNatural); - - ID2D1Factory * mpD2DFactory; - IDWriteFactory * mpDWriteFactory; -@@ -78,6 +80,7 @@ private: - IDWriteFontFace * mpFontFace; - float mlfEmHeight; - HDC mhDC; -+ bool mbRenderingModeNatural; - D2DTextAntiAliasMode meTextAntiAliasMode; - }; - -diff --git a/vcl/inc/win/salgdi.h b/vcl/inc/win/salgdi.h -index b472ece0a256..7833f988bd18 100644 ---- a/vcl/inc/win/salgdi.h -+++ b/vcl/inc/win/salgdi.h -@@ -316,7 +316,7 @@ public: - private: - // local helpers - -- void DrawTextLayout(const GenericSalLayout&, HDC, bool bUseDWrite); -+ void DrawTextLayout(const GenericSalLayout&, HDC, bool bUseDWrite, bool bRenderingModeNatural); - - public: - // public SalGraphics methods, the interface to the independent vcl part -diff --git a/vcl/inc/win/winlayout.hxx b/vcl/inc/win/winlayout.hxx -index 0b43ef4eeca1..5f56fe6b0c5e 100644 ---- a/vcl/inc/win/winlayout.hxx -+++ b/vcl/inc/win/winlayout.hxx -@@ -75,13 +75,14 @@ protected: - TextOutRenderer & operator = (const TextOutRenderer &) = delete; - - public: -- static TextOutRenderer & get(bool bUseDWrite); -+ static TextOutRenderer & get(bool bUseDWrite, bool bRenderingModeNatural); - - virtual ~TextOutRenderer() = default; - - virtual bool operator ()(GenericSalLayout const &rLayout, - SalGraphics &rGraphics, -- HDC hDC) = 0; -+ HDC hDC, -+ bool bRenderingModeNatural) = 0; - }; - - class ExTextOutRenderer : public TextOutRenderer -@@ -94,7 +95,8 @@ public: - - bool operator ()(GenericSalLayout const &rLayout, - SalGraphics &rGraphics, -- HDC hDC) override; -+ HDC hDC, -+ bool bRenderingModeNatural) override; - }; - - /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ -diff --git a/vcl/qt5/QtGraphics_Text.cxx b/vcl/qt5/QtGraphics_Text.cxx -index b509c2a946bd..02158fca29db 100644 ---- a/vcl/qt5/QtGraphics_Text.cxx -+++ b/vcl/qt5/QtGraphics_Text.cxx -@@ -294,11 +294,26 @@ std::unique_ptr QtGraphics::GetTextLayout(int nFallbackLevel) - return std::make_unique(*m_pTextStyle[nFallbackLevel]); - } - -+static QRawFont GetRawFont(const QFont& rFont, bool bWithoutHintingInTextDirection) -+{ -+ QFont::HintingPreference eHinting = rFont.hintingPreference(); -+ bool bAllowedHintStyle -+ = !bWithoutHintingInTextDirection -+ || (eHinting == QFont::PreferNoHinting || eHinting == QFont::PreferVerticalHinting); -+ if (bWithoutHintingInTextDirection && !bAllowedHintStyle) -+ { -+ QFont aFont(rFont); -+ aFont.setHintingPreference(QFont::PreferVerticalHinting); -+ return QRawFont::fromFont(aFont); -+ } -+ return QRawFont::fromFont(rFont); -+} -+ - void QtGraphics::DrawTextLayout(const GenericSalLayout& rLayout) - { - const QtFont* pFont = static_cast(&rLayout.GetFont()); - assert(pFont); -- QRawFont aRawFont(QRawFont::fromFont(*pFont)); -+ QRawFont aRawFont(GetRawFont(*pFont, getTextRenderModeForResolutionIndependentLayoutEnabled())); - - QVector glyphIndexes; - QVector positions; -@@ -311,13 +326,13 @@ void QtGraphics::DrawTextLayout(const GenericSalLayout& rLayout) - if (nOrientation) - pQtLayout->SetOrientation(0_deg10); - -- Point aPos; -+ DevicePoint aPos; - const GlyphItem* pGlyph; - int nStart = 0; - while (rLayout.GetNextGlyph(&pGlyph, aPos, nStart)) - { - glyphIndexes.push_back(pGlyph->glyphId()); -- positions.push_back(QPointF(aPos.X(), aPos.Y())); -+ positions.push_back(QPointF(aPos.getX(), aPos.getY())); - } - - // seems to be common to try to layout an empty string... -diff --git a/vcl/quartz/salgdi.cxx b/vcl/quartz/salgdi.cxx -index 9928cc4df3a2..b8a3ac375655 100644 ---- a/vcl/quartz/salgdi.cxx -+++ b/vcl/quartz/salgdi.cxx -@@ -363,10 +363,10 @@ bool AquaSalGraphics::AddTempDevFont(vcl::font::PhysicalFontCollection*, - - void AquaSalGraphics::DrawTextLayout(const GenericSalLayout& rLayout) - { -- mpBackend->drawTextLayout(rLayout); -+ mpBackend->drawTextLayout(rLayout, getTextRenderModeForResolutionIndependentLayoutEnabled()); - } - --void AquaGraphicsBackend::drawTextLayout(const GenericSalLayout& rLayout) -+void AquaGraphicsBackend::drawTextLayout(const GenericSalLayout& rLayout, bool bTextRenderModeForResolutionIndependentLayout) - { - #ifdef IOS - if (!mrShared.checkContext()) -@@ -387,7 +387,7 @@ void AquaGraphicsBackend::drawTextLayout(const GenericSalLayout& rLayout) - CTFontRef pFont = static_cast(CFDictionaryGetValue(rStyle.GetStyleDict(), kCTFontAttributeName)); - CGAffineTransform aRotMatrix = CGAffineTransformMakeRotation(-rStyle.mfFontRotation); - -- Point aPos; -+ DevicePoint aPos; - const GlyphItem* pGlyph; - std::vector aGlyphIds; - std::vector aGlyphPos; -@@ -395,7 +395,7 @@ void AquaGraphicsBackend::drawTextLayout(const GenericSalLayout& rLayout) - int nStart = 0; - while (rLayout.GetNextGlyph(&pGlyph, aPos, nStart)) - { -- CGPoint aGCPos = CGPointMake(aPos.X(), -aPos.Y()); -+ CGPoint aGCPos = CGPointMake(aPos.getX(), -aPos.getY()); - - // Whether the glyph should be upright in vertical mode or not - bool bUprightGlyph = false; -@@ -460,6 +460,14 @@ void AquaGraphicsBackend::drawTextLayout(const GenericSalLayout& rLayout) - CGContextSetTextDrawingMode(mrShared.maContextHolder.get(), kCGTextFillStroke); - } - -+ if (bTextRenderModeForResolutionIndependentLayout) -+ { -+ CGContextSetAllowsFontSubpixelQuantization(mrShared.maContextHolder.get(), false); -+ CGContextSetShouldSubpixelQuantizeFonts(mrShared.maContextHolder.get(), false); -+ CGContextSetAllowsFontSubpixelPositioning(mrShared.maContextHolder.get(), true); -+ CGContextSetShouldSubpixelPositionFonts(mrShared.maContextHolder.get(), true); -+ } -+ - auto aIt = aGlyphOrientation.cbegin(); - while (aIt != aGlyphOrientation.cend()) - { -diff --git a/vcl/skia/gdiimpl.cxx b/vcl/skia/gdiimpl.cxx -index 55fed5b84e72..6d027a6f860a 100644 ---- a/vcl/skia/gdiimpl.cxx -+++ b/vcl/skia/gdiimpl.cxx -@@ -2206,7 +2206,7 @@ void SkiaSalGraphicsImpl::drawGenericLayout(const GenericSalLayout& layout, Colo - glyphIds.reserve(256); - glyphForms.reserve(256); - verticals.reserve(256); -- Point aPos; -+ DevicePoint aPos; - const GlyphItem* pGlyph; - int nStart = 0; - while (layout.GetNextGlyph(&pGlyph, aPos, nStart)) -@@ -2215,7 +2215,7 @@ void SkiaSalGraphicsImpl::drawGenericLayout(const GenericSalLayout& layout, Colo - Degree10 angle = layout.GetOrientation(); - if (pGlyph->IsVertical()) - angle += 900_deg10; -- SkRSXform form = SkRSXform::Make(toCos(angle), toSin(angle), aPos.X(), aPos.Y()); -+ SkRSXform form = SkRSXform::Make(toCos(angle), toSin(angle), aPos.getX(), aPos.getY()); - glyphForms.emplace_back(std::move(form)); - verticals.emplace_back(pGlyph->IsVertical()); - } -diff --git a/vcl/skia/osx/gdiimpl.cxx b/vcl/skia/osx/gdiimpl.cxx -index 126f43bb6ac3..4c9ae86dbadf 100644 ---- a/vcl/skia/osx/gdiimpl.cxx -+++ b/vcl/skia/osx/gdiimpl.cxx -@@ -261,7 +261,8 @@ bool AquaSkiaSalGraphicsImpl::drawNativeControl(ControlType nType, ControlPart n - return bOK; - } - --void AquaSkiaSalGraphicsImpl::drawTextLayout(const GenericSalLayout& rLayout) -+void AquaSkiaSalGraphicsImpl::drawTextLayout(const GenericSalLayout& rLayout, -+ bool bSubpixelPositioning) - { - const CoreTextStyle& rStyle = *static_cast(&rLayout.GetFont()); - const vcl::font::FontSelectPattern& rFontSelect = rStyle.GetFontSelectPattern(); -@@ -295,8 +296,12 @@ void AquaSkiaSalGraphicsImpl::drawTextLayout(const GenericSalLayout& rLayout) - // font.setScaleX(rStyle.mfFontStretch); TODO - if (rStyle.mbFauxBold) - font.setEmbolden(true); -- font.setEdging(!mrShared.mbNonAntialiasedText ? SkFont::Edging::kAntiAlias -- : SkFont::Edging::kAlias); -+ -+ SkFont::Edging ePreferredAliasing -+ = bSubpixelPositioning ? SkFont::Edging::kSubpixelAntiAlias : SkFont::Edging::kAntiAlias; -+ if (bSubpixelPositioning) -+ font.setSubpixel(true); -+ font.setEdging(mrShared.mbNonAntialiasedText ? SkFont::Edging::kAlias : ePreferredAliasing); - - // Vertical font, use width as "height". - SkFont verticalFont(font); -diff --git a/vcl/skia/win/gdiimpl.cxx b/vcl/skia/win/gdiimpl.cxx -index a10351888eac..e9074340e66e 100644 ---- a/vcl/skia/win/gdiimpl.cxx -+++ b/vcl/skia/win/gdiimpl.cxx -@@ -163,11 +163,7 @@ sk_sp WinSkiaSalGraphicsImpl::createDirectWriteTypeface(HDC hdc, HFO - // different version of the same font installed system-wide). - // For that CreateFromFaceFromHdc() is necessary. The simpler - // CreateFontFromLOGFONT() seems to search for the best matching font, -- // which may not be the exact font. Our private fonts are installed -- // using AddFontResourceExW( FR_PRIVATE ) and that apparently does -- // not make them available to DirectWrite (at least, they are not -- // included the DWrite system font collection). For such cases, we'll -- // need to fall back to Skia's GDI-based font rendering. -+ // which may not be the exact font. - HFONT oldFont = SelectFont(hdc, hfont); - sal::systools::COMReference fontFace; - if (FAILED(CHECKHR(dwriteGdiInterop->CreateFontFaceFromHdc(hdc, &fontFace)))) -@@ -175,6 +171,7 @@ sk_sp WinSkiaSalGraphicsImpl::createDirectWriteTypeface(HDC hdc, HFO - SelectFont(hdc, oldFont); - return nullptr; - } -+ - SelectFont(hdc, oldFont); - sal::systools::COMReference collection; - if (FAILED(CHECKHR(dwriteFactory->GetSystemFontCollection(&collection)))) -@@ -182,7 +179,66 @@ sk_sp WinSkiaSalGraphicsImpl::createDirectWriteTypeface(HDC hdc, HFO - sal::systools::COMReference font; - // Do not use CHECKHR() here, as said above, this fails for our fonts. - if (FAILED(collection->GetFontFromFontFace(fontFace.get(), &font))) -- return nullptr; -+ { -+ // If not found in system collection, try our private font collection. -+ // If that's not possible we'll fall back to Skia's GDI-based font rendering. -+ if (!dwritePrivateCollection -+ || FAILED(dwritePrivateCollection->GetFontFromFontFace(fontFace.get(), &font))) -+ { -+ // Our private fonts are installed using AddFontResourceExW( FR_PRIVATE ) -+ // and that does not make them available to the DWrite system font -+ // collection. For such cases attempt to update a collection of -+ // private fonts with this newly used font. -+ -+ sal::systools::COMReference dwriteFactory3; -+ if (FAILED(dwriteFactory->QueryInterface(&dwriteFactory3))) -+ return nullptr; -+ -+ if (!dwriteFontSetBuilder -+ && FAILED(dwriteFactory3->CreateFontSetBuilder(&dwriteFontSetBuilder))) -+ return nullptr; -+ -+ UINT32 numberOfFiles; -+ if (FAILED(fontFace->GetFiles(&numberOfFiles, nullptr)) || numberOfFiles != 1) -+ return nullptr; -+ -+ sal::systools::COMReference fontFile; -+ if (FAILED(fontFace->GetFiles(&numberOfFiles, &fontFile))) -+ return nullptr; -+ -+ BOOL isSupported; -+ DWRITE_FONT_FILE_TYPE fileType; -+ UINT32 numberOfFonts; -+ if (FAILED(fontFile->Analyze(&isSupported, &fileType, nullptr, &numberOfFonts)) -+ || !isSupported) -+ return nullptr; -+ -+ // For each font within the font file, get a font face reference and add to the builder. -+ for (UINT32 fontIndex = 0; fontIndex < numberOfFonts; ++fontIndex) -+ { -+ sal::systools::COMReference fontFaceReference; -+ if (FAILED(dwriteFactory3->CreateFontFaceReference(fontFile.get(), fontIndex, -+ DWRITE_FONT_SIMULATIONS_NONE, -+ &fontFaceReference))) -+ continue; -+ -+ // Leave it to DirectWrite to read properties directly out of the font files -+ dwriteFontSetBuilder->AddFontFaceReference(fontFaceReference.get()); -+ } -+ -+ dwritePrivateCollection.clear(); -+ sal::systools::COMReference fontSet; -+ if (SUCCEEDED(CHECKHR(dwriteFontSetBuilder->CreateFontSet(&fontSet)))) -+ dwriteFactory3->CreateFontCollectionFromFontSet(fontSet.get(), -+ &dwritePrivateCollection); -+ } -+ -+ if (!dwritePrivateCollection) -+ return nullptr; -+ // CHECKHR because we expect to succeed here -+ if (FAILED(CHECKHR(dwritePrivateCollection->GetFontFromFontFace(fontFace.get(), &font)))) -+ return nullptr; -+ } - sal::systools::COMReference fontFamily; - if (FAILED(CHECKHR(font->GetFontFamily(&fontFamily)))) - return nullptr; -@@ -231,8 +287,14 @@ bool WinSkiaSalGraphicsImpl::DrawTextLayout(const GenericSalLayout& rLayout) - } - - SkFont font(typeface); -+ -+ bool bSubpixelPositioning = mWinParent.getTextRenderModeForResolutionIndependentLayoutEnabled(); -+ SkFont::Edging ePreferredAliasing -+ = bSubpixelPositioning ? SkFont::Edging::kSubpixelAntiAlias : fontEdging; -+ if (bSubpixelPositioning) -+ font.setSubpixel(true); - font.setEdging(logFont.lfQuality == NONANTIALIASED_QUALITY ? SkFont::Edging::kAlias -- : fontEdging); -+ : ePreferredAliasing); - - const vcl::font::FontSelectPattern& rFSD = pWinFont->GetFontSelectPattern(); - int nHeight = rFSD.mnHeight; -@@ -296,6 +358,8 @@ void WinSkiaSalGraphicsImpl::initFontInfo() - void WinSkiaSalGraphicsImpl::ClearDevFontCache() - { - dwriteFontMgr.reset(); -+ dwriteFontSetBuilder.clear(); -+ dwritePrivateCollection.clear(); - dwriteFactory.clear(); - dwriteGdiInterop.clear(); - dwriteDone = false; -diff --git a/vcl/skia/x11/textrender.cxx b/vcl/skia/x11/textrender.cxx -index a2d0dcbb36f6..9fda8ba6601c 100644 ---- a/vcl/skia/x11/textrender.cxx -+++ b/vcl/skia/x11/textrender.cxx -@@ -57,8 +57,22 @@ void SkiaTextRender::DrawTextLayout(const GenericSalLayout& rLayout, const SalGr - font.setSkewX(1.0 * -0x4000L / 0x10000L); - if (rFont.NeedsArtificialBold()) - font.setEmbolden(true); -- font.setEdging(rFont.GetAntialiasAdvice() ? SkFont::Edging::kAntiAlias -- : SkFont::Edging::kAlias); -+ -+ bool bSubpixelPositioning = rGraphics.getTextRenderModeForResolutionIndependentLayoutEnabled(); -+ SkFont::Edging ePreferredAliasing -+ = bSubpixelPositioning ? SkFont::Edging::kSubpixelAntiAlias : SkFont::Edging::kAntiAlias; -+ if (bSubpixelPositioning) -+ { -+ font.setSubpixel(true); -+ -+ SkFontHinting eHinting = font.getHinting(); -+ bool bAllowedHintStyle -+ = eHinting == SkFontHinting::kNone || eHinting == SkFontHinting::kSlight; -+ if (!bAllowedHintStyle) -+ font.setHinting(SkFontHinting::kSlight); -+ } -+ -+ font.setEdging(rFont.GetAntialiasAdvice() ? ePreferredAliasing : SkFont::Edging::kAlias); - - // Vertical font, use width as "height". - SkFont verticalFont(font); -diff --git a/vcl/source/gdi/CommonSalLayout.cxx b/vcl/source/gdi/CommonSalLayout.cxx -index 13bc53ebbdab..811849309d67 100644 ---- a/vcl/source/gdi/CommonSalLayout.cxx -+++ b/vcl/source/gdi/CommonSalLayout.cxx -@@ -197,7 +197,9 @@ void GenericSalLayout::AdjustLayout(vcl::text::ImplLayoutArgs& rArgs) - { - SalLayout::AdjustLayout(rArgs); - -- if (rArgs.mpDXArray) -+ if (rArgs.mpAltNaturalDXArray) // Used when "TextRenderModeForResolutionIndependentLayout" is set -+ ApplyDXArray(rArgs.mpAltNaturalDXArray, rArgs.mnFlags); -+ else if (rArgs.mpDXArray) // Normal case - ApplyDXArray(rArgs.mpDXArray, rArgs.mnFlags); - else if (rArgs.mnLayoutWidth) - Justify(rArgs.mnLayoutWidth); -@@ -331,7 +333,7 @@ bool GenericSalLayout::LayoutText(vcl::text::ImplLayoutArgs& rArgs, const SalLay - double nYScale = 0; - GetFont().GetScale(&nXScale, &nYScale); - -- Point aCurrPos(0, 0); -+ DevicePoint aCurrPos(0, 0); - while (true) - { - int nBidiMinRunPos, nBidiEndRunPos; -@@ -584,12 +586,12 @@ bool GenericSalLayout::LayoutText(vcl::text::ImplLayoutArgs& rArgs, const SalLay - nXOffset = std::lround(nXOffset * nXScale); - nYOffset = std::lround(nYOffset * nYScale); - -- Point aNewPos(aCurrPos.X() + nXOffset, aCurrPos.Y() + nYOffset); -+ DevicePoint aNewPos(aCurrPos.getX() + nXOffset, aCurrPos.getY() + nYOffset); - const GlyphItem aGI(nCharPos, nCharCount, nGlyphIndex, aNewPos, nGlyphFlags, - nAdvance, nXOffset); - m_GlyphItems.push_back(aGI); - -- aCurrPos.AdjustX(nAdvance ); -+ aCurrPos.adjustX(nAdvance); - } - } - } -@@ -635,12 +637,12 @@ void GenericSalLayout::GetCharWidths(std::vector& rCharWidths) - // * Check the above flag to decide whether to insert Kashidas or not. - // * For any RTL glyph that has DX adjustment, insert enough Kashidas to - // fill in the added space. -- --void GenericSalLayout::ApplyDXArray(const DeviceCoordinate* pDXArray, SalLayoutFlags nLayoutFlags) -+template -+void GenericSalLayout::ApplyDXArray(const DC* pDXArray, SalLayoutFlags nLayoutFlags) - { - int nCharCount = mnEndCharPos - mnMinCharPos; - std::vector aOldCharWidths; -- std::unique_ptr const pNewCharWidths(new DeviceCoordinate[nCharCount]); -+ std::unique_ptr const pNewCharWidths(new DC[nCharCount]); - - // Get the natural character widths (i.e. before applying DX adjustments). - GetCharWidths(aOldCharWidths); -@@ -671,7 +673,7 @@ void GenericSalLayout::ApplyDXArray(const DeviceCoordinate* pDXArray, SalLayoutF - std::map pKashidas; - - // The accumulated difference in X position. -- DeviceCoordinate nDelta = 0; -+ DC nDelta = 0; - - // Apply the DX adjustments to glyph positions and widths. - size_t i = 0; -@@ -680,7 +682,7 @@ void GenericSalLayout::ApplyDXArray(const DeviceCoordinate* pDXArray, SalLayoutF - // Accumulate the width difference for all characters corresponding to - // this glyph. - int nCharPos = m_GlyphItems[i].charPos() - mnMinCharPos; -- DeviceCoordinate nDiff = 0; -+ DC nDiff = 0; - for (int j = 0; j < m_GlyphItems[i].charCount(); j++) - nDiff += pNewCharWidths[nCharPos + j] - aOldCharWidths[nCharPos + j]; - -@@ -689,14 +691,14 @@ void GenericSalLayout::ApplyDXArray(const DeviceCoordinate* pDXArray, SalLayoutF - // Adjust the width and position of the first (leftmost) glyph in - // the cluster. - m_GlyphItems[i].m_nNewWidth += nDiff; -- m_GlyphItems[i].m_aLinearPos.AdjustX(nDelta); -+ m_GlyphItems[i].m_aLinearPos.adjustX(nDelta); - - // Adjust the position of the rest of the glyphs in the cluster. - while (++i < m_GlyphItems.size()) - { - if (!m_GlyphItems[i].IsInCluster()) - break; -- m_GlyphItems[i].m_aLinearPos.AdjustX(nDelta); -+ m_GlyphItems[i].m_aLinearPos.adjustX(nDelta); - } - } - else if (m_GlyphItems[i].IsInCluster()) -@@ -711,7 +713,7 @@ void GenericSalLayout::ApplyDXArray(const DeviceCoordinate* pDXArray, SalLayoutF - // the cluster. - // For RTL, we put all the adjustment to the left of the glyph. - m_GlyphItems[i].m_nNewWidth += nDiff; -- m_GlyphItems[i].m_aLinearPos.AdjustX(nDelta + nDiff); -+ m_GlyphItems[i].m_aLinearPos.adjustX(nDelta + nDiff); - - // Adjust the X position of all glyphs in the cluster. - size_t j = i; -@@ -720,7 +722,7 @@ void GenericSalLayout::ApplyDXArray(const DeviceCoordinate* pDXArray, SalLayoutF - --j; - if (!m_GlyphItems[j].IsInCluster()) - break; -- m_GlyphItems[j].m_aLinearPos.AdjustX(nDelta + nDiff); -+ m_GlyphItems[j].m_aLinearPos.adjustX(nDelta + nDiff); - } - - // If this glyph is Kashida-justifiable, then mark this as a -@@ -737,7 +739,7 @@ void GenericSalLayout::ApplyDXArray(const DeviceCoordinate* pDXArray, SalLayoutF - { - if (!m_GlyphItems[j].IsDiacritic()) - break; -- m_GlyphItems[j--].m_aLinearPos.AdjustX(nDiff); -+ m_GlyphItems[j--].m_aLinearPos.adjustX(nDiff); - } - } - i++; -@@ -779,15 +781,14 @@ void GenericSalLayout::ApplyDXArray(const DeviceCoordinate* pDXArray, SalLayoutF - nOverlap = nExcess / (nCopies - 1); - } - -- Point aPos(pGlyphIter->m_aLinearPos.getX() - nTotalWidth, 0); -+ DevicePoint aPos(pGlyphIter->m_aLinearPos.getX() - nTotalWidth, 0); - int nCharPos = pGlyphIter->charPos(); - GlyphItemFlags const nFlags = GlyphItemFlags::IS_IN_CLUSTER | GlyphItemFlags::IS_RTL_GLYPH; - while (nCopies--) - { - GlyphItem aKashida(nCharPos, 0, nKashidaIndex, aPos, nFlags, nKashidaWidth, 0); - pGlyphIter = m_GlyphItems.insert(pGlyphIter, aKashida); -- aPos.AdjustX(nKashidaWidth ); -- aPos.AdjustX( -nOverlap ); -+ aPos.adjustX(nKashidaWidth - nOverlap); - ++pGlyphIter; - ++nInserted; - } -diff --git a/vcl/source/gdi/pdfwriter_impl.cxx b/vcl/source/gdi/pdfwriter_impl.cxx -index 0a971622d5bc..a3ad137230fd 100644 ---- a/vcl/source/gdi/pdfwriter_impl.cxx -+++ b/vcl/source/gdi/pdfwriter_impl.cxx -@@ -3899,7 +3899,7 @@ void PDFWriterImpl::createDefaultCheckBoxAppearance( PDFWidget& rBox, const PDFW - // make sure OpenSymbol is embedded, and includes our checkmark - const sal_Unicode cMark=0x2713; - const GlyphItem aItem(0, 0, pMap->GetGlyphIndex(cMark), -- Point(), GlyphItemFlags::NONE, 0, 0); -+ DevicePoint(), GlyphItemFlags::NONE, 0, 0); - const std::vector aCodeUnits={ cMark }; - sal_uInt8 nMappedGlyph; - sal_Int32 nMappedFontObject; -@@ -5808,9 +5808,9 @@ void PDFWriterImpl::drawShadow( SalLayout& rLayout, const OUString& rText, bool - tools::Long nOff = 1 + ((GetFontInstance()->mnLineHeight-24)/24); - if( rFont.IsOutline() ) - nOff++; -- rLayout.DrawBase() += Point( nOff, nOff ); -+ rLayout.DrawBase() += DevicePoint(nOff, nOff); - drawLayout( rLayout, rText, bTextLines ); -- rLayout.DrawBase() -= Point( nOff, nOff ); -+ rLayout.DrawBase() -= DevicePoint(nOff, nOff); - - setFont( aSaveFont ); - setTextLineColor( aSaveTextLineColor ); -@@ -6133,7 +6133,7 @@ void PDFWriterImpl::drawLayout( SalLayout& rLayout, const OUString& rText, bool - std::vector< PDFGlyph > aGlyphs; - aGlyphs.reserve( nMaxGlyphs ); - // first get all the glyphs and register them; coordinates still in Pixel -- Point aPos; -+ DevicePoint aPos; - while (rLayout.GetNextGlyph(&pGlyph, aPos, nIndex, nullptr, &pFallbackFont)) - { - const auto* pFont = pFallbackFont ? pFallbackFont : pDevFont; -@@ -6206,7 +6206,7 @@ void PDFWriterImpl::drawLayout( SalLayout& rLayout, const OUString& rText, bool - if (bUseActualText || pGlyph->IsInCluster()) - nCharPos = pGlyph->charPos(); - -- aGlyphs.emplace_back(aPos, -+ aGlyphs.emplace_back(Point(aPos.getX(), aPos.getY()), - pGlyph, - nGlyphWidth, - nMappedFontObject, -@@ -6229,7 +6229,8 @@ void PDFWriterImpl::drawLayout( SalLayout& rLayout, const OUString& rText, bool - // The rectangle is the bounding box of the text, but also includes - // ascent / descent to match the on-screen rendering. - // This is the top left of the text without ascent / descent. -- tools::Rectangle aRectangle(PixelToLogic(rLayout.GetDrawPosition()), -+ DevicePoint aDrawPosition(rLayout.GetDrawPosition()); -+ tools::Rectangle aRectangle(PixelToLogic(Point(aDrawPosition.getX(), aDrawPosition.getY())), - Size(ImplDevicePixelToLogicWidth(rLayout.GetTextWidth()), 0)); - aRectangle.AdjustTop(-aRefDevFontMetric.GetAscent()); - // This includes ascent / descent. -@@ -6240,7 +6241,7 @@ void PDFWriterImpl::drawLayout( SalLayout& rLayout, const OUString& rText, bool - { - // Adapt rectangle for rotated text. - tools::Polygon aPolygon(aRectangle); -- aPolygon.Rotate(PixelToLogic(rLayout.GetDrawPosition()), pFontInstance->mnOrientation); -+ aPolygon.Rotate(PixelToLogic(Point(aDrawPosition.getX(), aDrawPosition.getY())), pFontInstance->mnOrientation); - drawPolygon(aPolygon); - } - else -@@ -6337,7 +6338,7 @@ void PDFWriterImpl::drawLayout( SalLayout& rLayout, const OUString& rText, bool - if (!pGlyph->IsSpacing()) - { - if( !nWidth ) -- aStartPt = aPos; -+ aStartPt = Point(aPos.getX(), aPos.getY()); - - nWidth += pGlyph->m_nNewWidth; - } -@@ -6359,9 +6360,9 @@ void PDFWriterImpl::drawLayout( SalLayout& rLayout, const OUString& rText, bool - } - else - { -- Point aStartPt = rLayout.GetDrawPosition(); -+ DevicePoint aStartPt = rLayout.GetDrawPosition(); - int nWidth = rLayout.GetTextWidth() / rLayout.GetUnitsPerPixel(); -- drawTextLine( PixelToLogic( aStartPt ), -+ drawTextLine( PixelToLogic(Point(aStartPt.getX(), aStartPt.getY()) ), - ImplDevicePixelToLogicWidth( nWidth ), - eStrikeout, eUnderline, eOverline, bUnderlineAbove ); - } -@@ -6437,9 +6438,10 @@ void PDFWriterImpl::drawLayout( SalLayout& rLayout, const OUString& rText, bool - - aAdjOffset -= Point( nEmphWidth2, nEmphHeight2 ); - -- aPos += aAdjOffset; -- aPos = PixelToLogic( aPos ); -- drawEmphasisMark( aPos.X(), aPos.Y(), -+ Point aMarkPos(aPos.getX(), aPos.getY()); -+ aMarkPos += aAdjOffset; -+ aMarkPos = PixelToLogic(aMarkPos); -+ drawEmphasisMark( aMarkPos.X(), aMarkPos.Y(), - aEmphPoly, bEmphPolyLine, - aEmphRect1, aEmphRect2 ); - } -diff --git a/vcl/source/gdi/salgdilayout.cxx b/vcl/source/gdi/salgdilayout.cxx -index aafa8f157e70..b22d4594cafe 100644 ---- a/vcl/source/gdi/salgdilayout.cxx -+++ b/vcl/source/gdi/salgdilayout.cxx -@@ -54,7 +54,8 @@ SalGraphics::SalGraphics() - m_aLastMirrorW(0), - m_nLastMirrorDeviceLTRButBiDiRtlTranslate(0), - m_bLastMirrorDeviceLTRButBiDiRtlSet(false), -- m_bAntiAlias(false) -+ m_bAntiAlias(false), -+ m_bTextRenderModeForResolutionIndependentLayout(false) - { - // read global RTL settings - if( AllSettings::GetLayoutRTL() ) -diff --git a/vcl/source/gdi/sallayout.cxx b/vcl/source/gdi/sallayout.cxx -index ebf10bf8e17c..abad66427491 100644 ---- a/vcl/source/gdi/sallayout.cxx -+++ b/vcl/source/gdi/sallayout.cxx -@@ -135,7 +135,8 @@ SalLayout::SalLayout() - mnEndCharPos( -1 ), - mnUnitsPerPixel( 1 ), - mnOrientation( 0 ), -- maDrawOffset( 0, 0 ) -+ maDrawOffset( 0, 0 ), -+ mbTextRenderModeForResolutionIndependentLayout(false) - {} - - SalLayout::~SalLayout() -@@ -148,10 +149,11 @@ void SalLayout::AdjustLayout( vcl::text::ImplLayoutArgs& rArgs ) - mnOrientation = rArgs.mnOrientation; - } - --Point SalLayout::GetDrawPosition( const Point& rRelative ) const -+DevicePoint SalLayout::GetDrawPosition(const DevicePoint& rRelative) const - { -- Point aPos = maDrawBase; -- Point aOfs = rRelative + maDrawOffset; -+ DevicePoint aPos(maDrawBase); -+ DevicePoint aOfs(rRelative.getX() + maDrawOffset.X(), -+ rRelative.getY() + maDrawOffset.Y()); - - if( mnOrientation == 0_deg10 ) - aPos += aOfs; -@@ -168,11 +170,20 @@ Point SalLayout::GetDrawPosition( const Point& rRelative ) const - fSin = sin( fRad ); - } - -- double fX = aOfs.X(); -- double fY = aOfs.Y(); -- tools::Long nX = static_cast( +fCos * fX + fSin * fY ); -- tools::Long nY = static_cast( +fCos * fY - fSin * fX ); -- aPos += Point( nX, nY ); -+ double fX = aOfs.getX(); -+ double fY = aOfs.getY(); -+ if (mbTextRenderModeForResolutionIndependentLayout) -+ { -+ double nX = +fCos * fX + fSin * fY; -+ double nY = +fCos * fY - fSin * fX; -+ aPos += DevicePoint(nX, nY); -+ } -+ else -+ { -+ tools::Long nX = static_cast( +fCos * fX + fSin * fY ); -+ tools::Long nY = static_cast( +fCos * fY - fSin * fX ); -+ aPos += DevicePoint(nX, nY); -+ } - } - - return aPos; -@@ -185,7 +196,7 @@ bool SalLayout::GetOutline(basegfx::B2DPolyPolygonVector& rVector) const - - basegfx::B2DPolyPolygon aGlyphOutline; - -- Point aPos; -+ DevicePoint aPos; - const GlyphItem* pGlyph; - int nStart = 0; - const LogicalFontInstance* pGlyphFont; -@@ -198,9 +209,9 @@ bool SalLayout::GetOutline(basegfx::B2DPolyPolygonVector& rVector) const - // only add non-empty outlines - if( bSuccess && (aGlyphOutline.count() > 0) ) - { -- if( aPos.X() || aPos.Y() ) -+ if( aPos.getX() || aPos.getY() ) - { -- aGlyphOutline.transform(basegfx::utils::createTranslateB2DHomMatrix(aPos.X(), aPos.Y())); -+ aGlyphOutline.transform(basegfx::utils::createTranslateB2DHomMatrix(aPos.getX(), aPos.getY())); - } - - // insert outline at correct position -@@ -218,7 +229,7 @@ bool SalLayout::GetBoundRect(tools::Rectangle& rRect) const - - tools::Rectangle aRectangle; - -- Point aPos; -+ DevicePoint aPos; - const GlyphItem* pGlyph; - int nStart = 0; - const LogicalFontInstance* pGlyphFont; -@@ -228,7 +239,7 @@ bool SalLayout::GetBoundRect(tools::Rectangle& rRect) const - if (pGlyph->GetGlyphBoundRect(pGlyphFont, aRectangle)) - { - // merge rectangle -- aRectangle += aPos; -+ aRectangle += Point(aPos.getX(), aPos.getY()); - if (rRect.IsEmpty()) - rRect = aRectangle; - else -@@ -322,7 +333,7 @@ void GenericSalLayout::Justify( DeviceCoordinate nNewWidth ) - for( pGlyphIter = m_GlyphItems.begin(); pGlyphIter != pGlyphIterRight; ++pGlyphIter ) - { - // move glyph to justified position -- pGlyphIter->m_aLinearPos.AdjustX(nDeltaSum ); -+ pGlyphIter->m_aLinearPos.adjustX(nDeltaSum); - - // do not stretch non-stretchable glyphs - if( pGlyphIter->IsDiacritic() || (nStretchable <= 0) ) -@@ -438,7 +449,7 @@ void GenericSalLayout::ApplyAsianKerning(const OUString& rStr) - - // adjust the glyph positions to the new glyph widths - if( pGlyphIter+1 != pGlyphIterEnd ) -- pGlyphIter->m_aLinearPos.AdjustX(nOffset); -+ pGlyphIter->m_aLinearPos.adjustX(nOffset); - } - } - -@@ -491,7 +502,7 @@ sal_Int32 GenericSalLayout::GetTextBreak( DeviceCoordinate nMaxWidth, DeviceCoor - } - - bool GenericSalLayout::GetNextGlyph(const GlyphItem** pGlyph, -- Point& rPos, int& nStart, -+ DevicePoint& rPos, int& nStart, - const LogicalFontInstance** ppGlyphFont, - const vcl::font::PhysicalFontFace**) const - { -@@ -521,10 +532,10 @@ bool GenericSalLayout::GetNextGlyph(const GlyphItem** pGlyph, - *ppGlyphFont = m_GlyphItems.GetFont().get(); - - // calculate absolute position in pixel units -- Point aRelativePos = pGlyphIter->m_aLinearPos; -+ DevicePoint aRelativePos = pGlyphIter->m_aLinearPos; - -- aRelativePos.setX( aRelativePos.X() / mnUnitsPerPixel ); -- aRelativePos.setY( aRelativePos.Y() / mnUnitsPerPixel ); -+ aRelativePos.setX( aRelativePos.getX() / mnUnitsPerPixel ); -+ aRelativePos.setY( aRelativePos.getY() / mnUnitsPerPixel ); - rPos = GetDrawPosition( aRelativePos ); - - return true; -@@ -550,7 +561,7 @@ void GenericSalLayout::MoveGlyph( int nStart, tools::Long nNewXPos ) - { - for( std::vector::iterator pGlyphIterEnd = m_GlyphItems.end(); pGlyphIter != pGlyphIterEnd; ++pGlyphIter ) - { -- pGlyphIter->m_aLinearPos.AdjustX(nXDelta ); -+ pGlyphIter->m_aLinearPos.adjustX(nXDelta); - } - } - } -@@ -637,7 +648,7 @@ void MultiSalLayout::AdjustLayout( vcl::text::ImplLayoutArgs& rArgs ) - vcl::text::ImplLayoutArgs aMultiArgs = rArgs; - std::vector aJustificationArray; - -- if( !rArgs.mpDXArray && rArgs.mnLayoutWidth ) -+ if( !rArgs.HasDXArray() && rArgs.mnLayoutWidth ) - { - // for stretched text in a MultiSalLayout the target width needs to be - // distributed by individually adjusting its virtual character widths -@@ -702,6 +713,17 @@ void MultiSalLayout::AdjustLayout( vcl::text::ImplLayoutArgs& rArgs ) - } - } - -+ if (aMultiArgs.mpAltNaturalDXArray) -+ ImplAdjustMultiLayout(rArgs, aMultiArgs, aMultiArgs.mpAltNaturalDXArray); -+ else -+ ImplAdjustMultiLayout(rArgs, aMultiArgs, aMultiArgs.mpDXArray); -+} -+ -+template -+void MultiSalLayout::ImplAdjustMultiLayout(vcl::text::ImplLayoutArgs& rArgs, -+ vcl::text::ImplLayoutArgs& rMultiArgs, -+ const DC* pMultiDXArray) -+{ - // Compute rtl flags, since in some scripts glyphs/char order can be - // reversed for a few character sequences e.g. Myanmar - std::vector vRtl(rArgs.mnEndCharPos - rArgs.mnMinCharPos, false); -@@ -721,17 +743,17 @@ void MultiSalLayout::AdjustLayout( vcl::text::ImplLayoutArgs& rArgs ) - const GlyphItem* pGlyphs[MAX_FALLBACK]; - bool bValid[MAX_FALLBACK] = { false }; - -- Point aPos; -+ DevicePoint aPos; - int nLevel = 0, n; - for( n = 0; n < mnLevel; ++n ) - { - // now adjust the individual components - if( n > 0 ) - { -- aMultiArgs.maRuns = maFallbackRuns[ n-1 ]; -- aMultiArgs.mnFlags |= SalLayoutFlags::ForFallback; -+ rMultiArgs.maRuns = maFallbackRuns[ n-1 ]; -+ rMultiArgs.mnFlags |= SalLayoutFlags::ForFallback; - } -- mpLayouts[n]->AdjustLayout( aMultiArgs ); -+ mpLayouts[n]->AdjustLayout( rMultiArgs ); - - // remove unused parts of component - if( n > 0 ) -@@ -830,7 +852,7 @@ void MultiSalLayout::AdjustLayout( vcl::text::ImplLayoutArgs& rArgs ) - } - - // skip to end of layout run and calculate its advance width -- DeviceCoordinate nRunAdvance = 0; -+ DC nRunAdvance = 0; - bool bKeepNotDef = (nFBLevel >= nLevel); - for(;;) - { -@@ -886,7 +908,7 @@ void MultiSalLayout::AdjustLayout( vcl::text::ImplLayoutArgs& rArgs ) - bKeepNotDef = bNeedFallback; - } - // check for reordered glyphs -- if (aMultiArgs.mpDXArray && -+ if (pMultiDXArray && - nRunVisibleEndChar < mnEndCharPos && - nRunVisibleEndChar >= mnMinCharPos && - pGlyphs[n]->charPos() < mnEndCharPos && -@@ -894,14 +916,14 @@ void MultiSalLayout::AdjustLayout( vcl::text::ImplLayoutArgs& rArgs ) - { - if (vRtl[nActiveCharPos - mnMinCharPos]) - { -- if (aMultiArgs.mpDXArray[nRunVisibleEndChar-mnMinCharPos] -- >= aMultiArgs.mpDXArray[pGlyphs[n]->charPos() - mnMinCharPos]) -+ if (pMultiDXArray[nRunVisibleEndChar-mnMinCharPos] -+ >= pMultiDXArray[pGlyphs[n]->charPos() - mnMinCharPos]) - { - nRunVisibleEndChar = pGlyphs[n]->charPos(); - } - } -- else if (aMultiArgs.mpDXArray[nRunVisibleEndChar-mnMinCharPos] -- <= aMultiArgs.mpDXArray[pGlyphs[n]->charPos() - mnMinCharPos]) -+ else if (pMultiDXArray[nRunVisibleEndChar-mnMinCharPos] -+ <= pMultiDXArray[pGlyphs[n]->charPos() - mnMinCharPos]) - { - nRunVisibleEndChar = pGlyphs[n]->charPos(); - } -@@ -910,7 +932,7 @@ void MultiSalLayout::AdjustLayout( vcl::text::ImplLayoutArgs& rArgs ) - - // if a justification array is available - // => use it directly to calculate the corresponding run width -- if( aMultiArgs.mpDXArray ) -+ if (pMultiDXArray) - { - // the run advance is the width from the first char - // in the run to the first char in the next run -@@ -919,16 +941,16 @@ void MultiSalLayout::AdjustLayout( vcl::text::ImplLayoutArgs& rArgs ) - if (nActiveCharIndex >= 0 && vRtl[nActiveCharIndex]) - { - if (nRunVisibleEndChar > mnMinCharPos && nRunVisibleEndChar <= mnEndCharPos) -- nRunAdvance -= aMultiArgs.mpDXArray[nRunVisibleEndChar - 1 - mnMinCharPos]; -+ nRunAdvance -= pMultiDXArray[nRunVisibleEndChar - 1 - mnMinCharPos]; - if (nLastRunEndChar > mnMinCharPos && nLastRunEndChar <= mnEndCharPos) -- nRunAdvance += aMultiArgs.mpDXArray[nLastRunEndChar - 1 - mnMinCharPos]; -+ nRunAdvance += pMultiDXArray[nLastRunEndChar - 1 - mnMinCharPos]; - } - else - { - if (nRunVisibleEndChar >= mnMinCharPos) -- nRunAdvance += aMultiArgs.mpDXArray[nRunVisibleEndChar - mnMinCharPos]; -+ nRunAdvance += pMultiDXArray[nRunVisibleEndChar - mnMinCharPos]; - if (nLastRunEndChar >= mnMinCharPos) -- nRunAdvance -= aMultiArgs.mpDXArray[nLastRunEndChar - mnMinCharPos]; -+ nRunAdvance -= pMultiDXArray[nLastRunEndChar - mnMinCharPos]; - } - nLastRunEndChar = nRunVisibleEndChar; - nRunVisibleEndChar = pGlyphs[nFirstValid]->charPos(); -@@ -1105,7 +1127,7 @@ void MultiSalLayout::GetCaretPositions( int nMaxIndex, sal_Int32* pCaretXArray ) - } - - bool MultiSalLayout::GetNextGlyph(const GlyphItem** pGlyph, -- Point& rPos, int& nStart, -+ DevicePoint& rPos, int& nStart, - const LogicalFontInstance** ppGlyphFont, - const vcl::font::PhysicalFontFace** pFallbackFont) const - { -@@ -1123,8 +1145,8 @@ bool MultiSalLayout::GetNextGlyph(const GlyphItem** pGlyph, - nStart |= nFontTag; - if (pFallbackFont) - *pFallbackFont = pFontFace; -- rPos += maDrawBase; -- rPos += maDrawOffset; -+ rPos.adjustX(maDrawBase.getX() + maDrawOffset.X()); -+ rPos.adjustY(maDrawBase.getY() + maDrawOffset.Y()); - return true; - } - } -diff --git a/vcl/source/gdi/virdev.cxx b/vcl/source/gdi/virdev.cxx -index 6a44cc1cd136..87721c683d77 100644 ---- a/vcl/source/gdi/virdev.cxx -+++ b/vcl/source/gdi/virdev.cxx -@@ -379,6 +379,8 @@ bool VirtualDevice::ImplSetOutputSizePixel( const Size& rNewSize, bool bErase, - mpAlphaVDev->SetMapMode( GetMapMode() ); - - mpAlphaVDev->SetAntialiasing( GetAntialiasing() ); -+ -+ mpAlphaVDev->SetTextRenderModeForResolutionIndependentLayout(GetTextRenderModeForResolutionIndependentLayout()); - } - - return true; -diff --git a/vcl/source/outdev/font.cxx b/vcl/source/outdev/font.cxx -index 5139f1fc03a4..71e4091e754e 100644 ---- a/vcl/source/outdev/font.cxx -+++ b/vcl/source/outdev/font.cxx -@@ -1117,7 +1117,7 @@ void OutputDevice::ImplDrawEmphasisMarks( SalLayout& rSalLayout ) - tools::Long nEmphasisHeight2 = nEmphasisHeight / 2; - aOffset += Point( nEmphasisWidth2, nEmphasisHeight2 ); - -- Point aOutPoint; -+ DevicePoint aOutPoint; - tools::Rectangle aRectangle; - const GlyphItem* pGlyph; - const LogicalFontInstance* pGlyphFont; -@@ -1136,10 +1136,10 @@ void OutputDevice::ImplDrawEmphasisMarks( SalLayout& rSalLayout ) - Point aOriginPt(0, 0); - aOriginPt.RotateAround( aAdjPoint, mpFontInstance->mnOrientation ); - } -- aOutPoint += aAdjPoint; -- aOutPoint -= Point( nEmphasisWidth2, nEmphasisHeight2 ); -- ImplDrawEmphasisMark( rSalLayout.DrawBase().X(), -- aOutPoint.X(), aOutPoint.Y(), -+ aOutPoint.adjustX(aAdjPoint.X() - nEmphasisWidth2); -+ aOutPoint.adjustY(aAdjPoint.Y() - nEmphasisHeight2); -+ ImplDrawEmphasisMark( rSalLayout.DrawBase().getX(), -+ aOutPoint.getX(), aOutPoint.getY(), - aPolyPoly, bPolyLine, aRect1, aRect2 ); - } - } -diff --git a/vcl/source/outdev/map.cxx b/vcl/source/outdev/map.cxx -index 227905f075a8..bb4683f37a19 100644 ---- a/vcl/source/outdev/map.cxx -+++ b/vcl/source/outdev/map.cxx -@@ -1879,11 +1879,32 @@ DeviceCoordinate OutputDevice::LogicWidthToDeviceCoordinate( tools::Long nWidth - return static_cast(nWidth); - - #if VCL_FLOAT_DEVICE_PIXEL -- return (double)nWidth * maMapRes.mfScaleX * mnDPIX; -+ return ImplLogicToPixel(static_cast(nWidth), mnDPIX, maMapRes.mnMapScNumX, maMapRes.mnMapScDenomX); - #else -- - return ImplLogicToPixel(nWidth, mnDPIX, maMapRes.mnMapScNumX, maMapRes.mnMapScDenomX); - #endif - } - -+double OutputDevice::ImplLogicWidthToDeviceFontWidth(tools::Long nWidth) const -+{ -+ if (!mbMap) -+ return nWidth; -+ -+ return ImplLogicToPixel(static_cast(nWidth), mnDPIX, -+ maMapRes.mnMapScNumX, maMapRes.mnMapScDenomX); -+} -+ -+DevicePoint OutputDevice::ImplLogicToDeviceFontCoordinate(const Point& rPoint) const -+{ -+ if (!mbMap) -+ return DevicePoint(rPoint.X() + mnOutOffX, rPoint.Y() + mnOutOffY); -+ -+ return DevicePoint(ImplLogicToPixel(static_cast(rPoint.X() + maMapRes.mnMapOfsX), mnDPIX, -+ maMapRes.mnMapScNumX, maMapRes.mnMapScDenomX) -+ + mnOutOffX + mnOutOffOrigX, -+ ImplLogicToPixel(static_cast(rPoint.Y() + maMapRes.mnMapOfsY), mnDPIY, -+ maMapRes.mnMapScNumY, maMapRes.mnMapScDenomY) -+ + mnOutOffY + mnOutOffOrigY); -+} -+ - /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ -diff --git a/vcl/source/outdev/outdev.cxx b/vcl/source/outdev/outdev.cxx -index 9231f7779a6b..1ad7a2e71dd0 100644 ---- a/vcl/source/outdev/outdev.cxx -+++ b/vcl/source/outdev/outdev.cxx -@@ -105,6 +105,7 @@ OutputDevice::OutputDevice(OutDevType eOutDevType) : - meRasterOp = RasterOp::OverPaint; - mnAntialiasing = AntialiasingFlags::NONE; - meTextLanguage = LANGUAGE_SYSTEM; // TODO: get default from configuration? -+ mbTextRenderModeForResolutionIndependentLayout = false; - mbLineColor = true; - mbFillColor = true; - mbInitLineColor = true; -@@ -354,16 +355,28 @@ void OutputDevice::SetAntialiasing( AntialiasingFlags nMode ) - mnAntialiasing = nMode; - mbInitFont = true; - -- if(mpGraphics) -- { -+ if (mpGraphics) - mpGraphics->setAntiAlias(bool(mnAntialiasing & AntialiasingFlags::Enable)); -- } - } - - if( mpAlphaVDev ) - mpAlphaVDev->SetAntialiasing( nMode ); - } - -+void OutputDevice::SetTextRenderModeForResolutionIndependentLayout(bool bMode) -+{ -+ if (mbTextRenderModeForResolutionIndependentLayout!= bMode) -+ { -+ mbTextRenderModeForResolutionIndependentLayout = bMode; -+ -+ if (mpGraphics) -+ mpGraphics->setTextRenderModeForResolutionIndependentLayout(bMode); -+ } -+ -+ if (mpAlphaVDev) -+ mpAlphaVDev->SetTextRenderModeForResolutionIndependentLayout(bMode); -+} -+ - void OutputDevice::SetDrawMode(DrawModeFlags nDrawMode) - { - mnDrawMode = nDrawMode; -diff --git a/vcl/source/outdev/text.cxx b/vcl/source/outdev/text.cxx -index a28dc49e5ebd..3d773e56d488 100644 ---- a/vcl/source/outdev/text.cxx -+++ b/vcl/source/outdev/text.cxx -@@ -168,9 +168,9 @@ void OutputDevice::ImplDrawTextRect( tools::Long nBaseX, tools::Long nBaseY, - void OutputDevice::ImplDrawTextBackground( const SalLayout& rSalLayout ) - { - const tools::Long nWidth = rSalLayout.GetTextWidth() / rSalLayout.GetUnitsPerPixel(); -- const Point aBase = rSalLayout.DrawBase(); -- const tools::Long nX = aBase.X(); -- const tools::Long nY = aBase.Y(); -+ const DevicePoint aBase = rSalLayout.DrawBase(); -+ const tools::Long nX = aBase.getX(); -+ const tools::Long nY = aBase.getY(); - - if ( mbLineColor || mbInitLineColor ) - { -@@ -187,9 +187,9 @@ void OutputDevice::ImplDrawTextBackground( const SalLayout& rSalLayout ) - - tools::Rectangle OutputDevice::ImplGetTextBoundRect( const SalLayout& rSalLayout ) const - { -- Point aPoint = rSalLayout.GetDrawPosition(); -- tools::Long nX = aPoint.X(); -- tools::Long nY = aPoint.Y(); -+ DevicePoint aPoint = rSalLayout.GetDrawPosition(); -+ tools::Long nX = aPoint.getX(); -+ tools::Long nY = aPoint.getY(); - - tools::Long nWidth = rSalLayout.GetTextWidth(); - tools::Long nHeight = mpFontInstance->mnLineHeight + mnEmphasisAscent + mnEmphasisDescent; -@@ -225,11 +225,11 @@ tools::Rectangle OutputDevice::ImplGetTextBoundRect( const SalLayout& rSalLayout - - bool OutputDevice::ImplDrawRotateText( SalLayout& rSalLayout ) - { -- tools::Long nX = rSalLayout.DrawBase().X(); -- tools::Long nY = rSalLayout.DrawBase().Y(); -+ tools::Long nX = rSalLayout.DrawBase().getX(); -+ tools::Long nY = rSalLayout.DrawBase().getY(); - - tools::Rectangle aBoundRect; -- rSalLayout.DrawBase() = Point( 0, 0 ); -+ rSalLayout.DrawBase() = DevicePoint( 0, 0 ); - rSalLayout.DrawOffset() = Point( 0, 0 ); - if (!rSalLayout.GetBoundRect(aBoundRect)) - { -@@ -261,7 +261,8 @@ bool OutputDevice::ImplDrawRotateText( SalLayout& rSalLayout ) - pVDev->ImplInitTextColor(); - - // draw text into upper left corner -- rSalLayout.DrawBase() -= aBoundRect.TopLeft(); -+ rSalLayout.DrawBase().adjustX(-aBoundRect.Left()); -+ rSalLayout.DrawBase().adjustY(-aBoundRect.Top()); - rSalLayout.DrawText( *pVDev->mpGraphics ); - - Bitmap aBmp = pVDev->GetBitmap( Point(), aBoundRect.GetSize() ); -@@ -302,18 +303,18 @@ void OutputDevice::ImplDrawTextDirect( SalLayout& rSalLayout, - if( ImplDrawRotateText( rSalLayout ) ) - return; - -- tools::Long nOldX = rSalLayout.DrawBase().X(); -+ auto nOldX = rSalLayout.DrawBase().getX(); - if( HasMirroredGraphics() ) - { - tools::Long w = IsVirtual() ? mnOutWidth : mpGraphics->GetGraphicsWidth(); -- tools::Long x = rSalLayout.DrawBase().X(); -+ auto x = rSalLayout.DrawBase().getX(); - rSalLayout.DrawBase().setX( w - 1 - x ); - if( !IsRTLEnabled() ) - { - OutputDevice *pOutDevRef = this; - // mirror this window back - tools::Long devX = w-pOutDevRef->mnOutWidth-pOutDevRef->mnOutOffX; // re-mirrored mnOutOffX -- rSalLayout.DrawBase().setX( devX + ( pOutDevRef->mnOutWidth - 1 - (rSalLayout.DrawBase().X() - devX) ) ) ; -+ rSalLayout.DrawBase().setX( devX + ( pOutDevRef->mnOutWidth - 1 - (rSalLayout.DrawBase().getX() - devX) ) ) ; - } - } - else if( IsRTLEnabled() ) -@@ -322,7 +323,7 @@ void OutputDevice::ImplDrawTextDirect( SalLayout& rSalLayout, - - // mirror this window back - tools::Long devX = pOutDevRef->mnOutOffX; // re-mirrored mnOutOffX -- rSalLayout.DrawBase().setX( pOutDevRef->mnOutWidth - 1 - (rSalLayout.DrawBase().X() - devX) + devX ); -+ rSalLayout.DrawBase().setX( pOutDevRef->mnOutWidth - 1 - (rSalLayout.DrawBase().getX() - devX) + devX ); - } - - rSalLayout.DrawText( *mpGraphics ); -@@ -345,7 +346,7 @@ void OutputDevice::ImplDrawSpecialText( SalLayout& rSalLayout ) - Color aOldOverlineColor = GetOverlineColor(); - FontRelief eRelief = maFont.GetRelief(); - -- Point aOrigPos = rSalLayout.DrawBase(); -+ DevicePoint aOrigPos = rSalLayout.DrawBase(); - if ( eRelief != FontRelief::NONE ) - { - Color aReliefColor( COL_LIGHTGRAY ); -@@ -413,9 +414,9 @@ void OutputDevice::ImplDrawSpecialText( SalLayout& rSalLayout ) - else - SetTextColor( COL_BLACK ); - ImplInitTextColor(); -- rSalLayout.DrawBase() += Point( nOff, nOff ); -+ rSalLayout.DrawBase() += DevicePoint( nOff, nOff ); - ImplDrawTextDirect( rSalLayout, mbTextLines ); -- rSalLayout.DrawBase() -= Point( nOff, nOff ); -+ rSalLayout.DrawBase() -= DevicePoint( nOff, nOff ); - SetTextColor( aOldColor ); - SetTextLineColor( aOldTextLineColor ); - SetOverlineColor( aOldOverlineColor ); -@@ -427,21 +428,21 @@ void OutputDevice::ImplDrawSpecialText( SalLayout& rSalLayout ) - - if ( maFont.IsOutline() ) - { -- rSalLayout.DrawBase() = aOrigPos + Point(-1,-1); -+ rSalLayout.DrawBase() = aOrigPos + DevicePoint(-1,-1); - ImplDrawTextDirect( rSalLayout, mbTextLines ); -- rSalLayout.DrawBase() = aOrigPos + Point(+1,+1); -+ rSalLayout.DrawBase() = aOrigPos + DevicePoint(+1,+1); - ImplDrawTextDirect( rSalLayout, mbTextLines ); -- rSalLayout.DrawBase() = aOrigPos + Point(-1,+0); -+ rSalLayout.DrawBase() = aOrigPos + DevicePoint(-1,+0); - ImplDrawTextDirect( rSalLayout, mbTextLines ); -- rSalLayout.DrawBase() = aOrigPos + Point(-1,+1); -+ rSalLayout.DrawBase() = aOrigPos + DevicePoint(-1,+1); - ImplDrawTextDirect( rSalLayout, mbTextLines ); -- rSalLayout.DrawBase() = aOrigPos + Point(+0,+1); -+ rSalLayout.DrawBase() = aOrigPos + DevicePoint(+0,+1); - ImplDrawTextDirect( rSalLayout, mbTextLines ); -- rSalLayout.DrawBase() = aOrigPos + Point(+0,-1); -+ rSalLayout.DrawBase() = aOrigPos + DevicePoint(+0,-1); - ImplDrawTextDirect( rSalLayout, mbTextLines ); -- rSalLayout.DrawBase() = aOrigPos + Point(+1,-1); -+ rSalLayout.DrawBase() = aOrigPos + DevicePoint(+1,-1); - ImplDrawTextDirect( rSalLayout, mbTextLines ); -- rSalLayout.DrawBase() = aOrigPos + Point(+1,+0); -+ rSalLayout.DrawBase() = aOrigPos + DevicePoint(+1,+0); - ImplDrawTextDirect( rSalLayout, mbTextLines ); - rSalLayout.DrawBase() = aOrigPos; - -@@ -468,7 +469,7 @@ void OutputDevice::ImplDrawText( SalLayout& rSalLayout ) - if( mbInitTextColor ) - ImplInitTextColor(); - -- rSalLayout.DrawBase() += Point( mnTextOffX, mnTextOffY ); -+ rSalLayout.DrawBase() += DevicePoint(mnTextOffX, mnTextOffY); - - if( IsTextFillColor() ) - ImplDrawTextBackground( rSalLayout ); -@@ -986,12 +987,13 @@ tools::Long OutputDevice::GetTextArray( const OUString& rStr, std::vector pDXPixelArray; -+ std::unique_ptr> xDXPixelArray; - if(pDXAry) - { -- pDXPixelArray.reset(new DeviceCoordinate[nLen]); -+ xDXPixelArray.reset(new std::vector(nLen)); - } -- DeviceCoordinate nWidth = pSalLayout->FillDXArray( pDXPixelArray.get() ); -+ std::vector* pDXPixelArray = xDXPixelArray.get(); -+ DeviceCoordinate nWidth = pSalLayout->FillDXArray(pDXPixelArray); - int nWidthFactor = pSalLayout->GetUnitsPerPixel(); - - // convert virtual char widths to virtual absolute positions -@@ -999,7 +1001,7 @@ tools::Long OutputDevice::GetTextArray( const OUString& rStr, std::vectorresize(nLen); - for( int i = 0; i < nLen; ++i ) - { -- (*pDXAry)[i] = basegfx::fround(pDXPixelArray[i]); -+ (*pDXAry)[i] = basegfx::fround((*pDXPixelArray)[i]); - } - } - return basegfx::fround(nWidth); -@@ -1148,7 +1150,7 @@ void OutputDevice::DrawStretchText( const Point& rStartPt, sal_uLong nWidth, - - vcl::text::ImplLayoutArgs OutputDevice::ImplPrepareLayoutArgs( OUString& rStr, - const sal_Int32 nMinIndex, const sal_Int32 nLen, -- DeviceCoordinate nPixelWidth, const DeviceCoordinate* pDXArray, -+ DeviceCoordinate nPixelWidth, - SalLayoutFlags nLayoutFlags, - vcl::text::TextLayoutCache const*const pLayoutCache) const - { -@@ -1241,7 +1243,6 @@ vcl::text::ImplLayoutArgs OutputDevice::ImplPrepareLayoutArgs( OUString& rStr, - aLayoutArgs.SetOrientation( nOrientation ); - - aLayoutArgs.SetLayoutWidth( nPixelWidth ); -- aLayoutArgs.SetDXArray( pDXArray ); - - return aLayoutArgs; - } -@@ -1338,21 +1339,47 @@ std::unique_ptr OutputDevice::ImplLayout(const OUString& rOrigStr, - nPixelWidth = LogicWidthToDeviceCoordinate( nLogicalWidth ); - } - -+ vcl::text::ImplLayoutArgs aLayoutArgs = ImplPrepareLayoutArgs( aStr, nMinIndex, nLen, -+ nPixelWidth, flags, pLayoutCache); -+ -+ bool bTextRenderModeForResolutionIndependentLayout(false); -+ DeviceCoordinate nEndGlyphCoord(0); - std::unique_ptr xDXPixelArray; -- DeviceCoordinate* pDXPixelArray(nullptr); -+ std::unique_ptr xNaturalDXPixelArray; - if( !pDXArray.empty() ) - { -- if(mbMap) -+ DeviceCoordinate* pDXPixelArray(nullptr); -+ if (mbMap) - { -- // convert from logical units to font units using a temporary array -- xDXPixelArray.reset(new DeviceCoordinate[nLen]); -- pDXPixelArray = xDXPixelArray.get(); -- // using base position for better rounding a.k.a. "dancing characters" -- DeviceCoordinate nPixelXOfs2 = LogicWidthToDeviceCoordinate(rLogicalPos.X() * 2); -- for( int i = 0; i < nLen; ++i ) -+ if (GetTextRenderModeForResolutionIndependentLayout()) - { -- pDXPixelArray[i] = (LogicWidthToDeviceCoordinate((rLogicalPos.X() + pDXArray[i]) * 2) - nPixelXOfs2) / 2; -+ bTextRenderModeForResolutionIndependentLayout = true; -+ -+ // convert from logical units to font units using a temporary array -+ xNaturalDXPixelArray.reset(new double[nLen]); -+ -+ for (int i = 0; i < nLen; ++i) -+ xNaturalDXPixelArray[i] = ImplLogicWidthToDeviceFontWidth(pDXArray[i]); -+ -+ aLayoutArgs.SetAltNaturalDXArray(xNaturalDXPixelArray.get()); -+ nEndGlyphCoord = std::lround(xNaturalDXPixelArray[nLen - 1]); - } -+ else -+ { -+ // convert from logical units to font units using a temporary array -+ xDXPixelArray.reset(new DeviceCoordinate[nLen]); -+ pDXPixelArray = xDXPixelArray.get(); -+ // using base position for better rounding a.k.a. "dancing characters" -+ DeviceCoordinate nPixelXOfs2 = LogicWidthToDeviceCoordinate(rLogicalPos.X() * 2); -+ for( int i = 0; i < nLen; ++i ) -+ { -+ pDXPixelArray[i] = (LogicWidthToDeviceCoordinate((rLogicalPos.X() + pDXArray[i]) * 2) - nPixelXOfs2) / 2; -+ } -+ -+ aLayoutArgs.SetDXArray(pDXPixelArray); -+ nEndGlyphCoord = pDXPixelArray[nLen - 1]; -+ } -+ - } - else - { -@@ -1361,17 +1388,17 @@ std::unique_ptr OutputDevice::ImplLayout(const OUString& rOrigStr, - pDXPixelArray = xDXPixelArray.get(); - for( int i = 0; i < nLen; ++i ) - { -- pDXPixelArray[i] = (*pDXArray)[i]; -+ pDXPixelArray[i] = pDXArray[i]; - } - #else /* !VCL_FLOAT_DEVICE_PIXEL */ - pDXPixelArray = const_cast(pDXArray.data()); - #endif /* !VCL_FLOAT_DEVICE_PIXEL */ -+ -+ aLayoutArgs.SetDXArray(pDXPixelArray); -+ nEndGlyphCoord = pDXPixelArray[nLen - 1]; - } - } - -- vcl::text::ImplLayoutArgs aLayoutArgs = ImplPrepareLayoutArgs( aStr, nMinIndex, nLen, -- nPixelWidth, pDXPixelArray, flags, pLayoutCache); -- - // get matching layout object for base font - std::unique_ptr pSalLayout = mpGraphics->GetTextLayout(0); - -@@ -1384,6 +1411,8 @@ std::unique_ptr OutputDevice::ImplLayout(const OUString& rOrigStr, - if( !pSalLayout ) - return nullptr; - -+ pSalLayout->SetTextRenderModeForResolutionIndependentLayout(bTextRenderModeForResolutionIndependentLayout); -+ - // do glyph fallback if needed - // #105768# avoid fallback for very small font sizes - if (aLayoutArgs.HasFallbackRun() && mpFontInstance->GetFontSelectPattern().mnHeight >= 3) -@@ -1396,13 +1425,21 @@ std::unique_ptr OutputDevice::ImplLayout(const OUString& rOrigStr, - - // position, justify, etc. the layout - pSalLayout->AdjustLayout( aLayoutArgs ); -- pSalLayout->DrawBase() = ImplLogicToDevicePixel( rLogicalPos ); -+ -+ if (bTextRenderModeForResolutionIndependentLayout) -+ pSalLayout->DrawBase() = ImplLogicToDeviceFontCoordinate(rLogicalPos); -+ else -+ { -+ Point aDevicePos = ImplLogicToDevicePixel(rLogicalPos); -+ pSalLayout->DrawBase() = DevicePoint(aDevicePos.X(), aDevicePos.Y()); -+ } -+ - // adjust to right alignment if necessary - if( aLayoutArgs.mnFlags & SalLayoutFlags::RightAlign ) - { - DeviceCoordinate nRTLOffset; -- if( pDXPixelArray ) -- nRTLOffset = pDXPixelArray[ nLen - 1 ]; -+ if (!pDXArray.empty()) -+ nRTLOffset = nEndGlyphCoord; - else if( nPixelWidth ) - nRTLOffset = nPixelWidth; - else -@@ -1425,7 +1462,7 @@ std::shared_ptr OutputDevice::CreateTextLayoutCache( - bool OutputDevice::GetTextIsRTL( const OUString& rString, sal_Int32 nIndex, sal_Int32 nLen ) const - { - OUString aStr( rString ); -- vcl::text::ImplLayoutArgs aArgs = ImplPrepareLayoutArgs( aStr, nIndex, nLen, 0, nullptr ); -+ vcl::text::ImplLayoutArgs aArgs = ImplPrepareLayoutArgs(aStr, nIndex, nLen, 0); - bool bRTL = false; - int nCharPos = -1; - if (!aArgs.GetNextPos(&nCharPos, &bRTL)) -@@ -2365,7 +2402,8 @@ bool OutputDevice::GetTextBoundRect( tools::Rectangle& rRect, - } - - Point aRotatedOfs( mnTextOffX, mnTextOffY ); -- aRotatedOfs -= pSalLayout->GetDrawPosition( Point( nXOffset, 0 ) ); -+ DevicePoint aPos = pSalLayout->GetDrawPosition(DevicePoint(nXOffset, 0)); -+ aRotatedOfs -= Point(aPos.getX(), aPos.getY()); - aPixelRect += aRotatedOfs; - rRect = PixelToLogic( aPixelRect ); - if( mbMap ) -@@ -2432,9 +2470,9 @@ bool OutputDevice::GetTextOutlines( basegfx::B2DPolyPolygonVector& rVector, - int nWidthFactor = pSalLayout->GetUnitsPerPixel(); - if( nXOffset | mnTextOffX | mnTextOffY ) - { -- Point aRotatedOfs( mnTextOffX*nWidthFactor, mnTextOffY*nWidthFactor ); -- aRotatedOfs -= pSalLayout->GetDrawPosition( Point( nXOffset, 0 ) ); -- aMatrix.translate( aRotatedOfs.X(), aRotatedOfs.Y() ); -+ DevicePoint aRotatedOfs( mnTextOffX*nWidthFactor, mnTextOffY*nWidthFactor ); -+ aRotatedOfs -= pSalLayout->GetDrawPosition(DevicePoint(nXOffset, 0)); -+ aMatrix.translate( aRotatedOfs.getX(), aRotatedOfs.getY() ); - } - - if( nWidthFactor > 1 ) -diff --git a/vcl/source/outdev/textline.cxx b/vcl/source/outdev/textline.cxx -index c4fcb33bf5d0..7c8af3db9220 100644 ---- a/vcl/source/outdev/textline.cxx -+++ b/vcl/source/outdev/textline.cxx -@@ -710,7 +710,7 @@ void OutputDevice::ImplDrawStrikeoutChar( tools::Long nBaseX, tools::Long nBaseY - SetTextColor( aColor ); - ImplInitTextColor(); - -- pLayout->DrawBase() = Point( nBaseX+mnTextOffX, nBaseY+mnTextOffY ); -+ pLayout->DrawBase() = DevicePoint(nBaseX + mnTextOffX, nBaseY + mnTextOffY); - - tools::Rectangle aPixelRect; - aPixelRect.SetLeft( nBaseX+mnTextOffX ); -@@ -811,10 +811,10 @@ void OutputDevice::ImplDrawTextLines( SalLayout& rSalLayout, FontStrikeout eStri - if( bWordLine ) - { - // draw everything relative to the layout base point -- const Point aStartPt = rSalLayout.DrawBase(); -+ const DevicePoint aStartPt = rSalLayout.DrawBase(); - - // calculate distance of each word from the base point -- Point aPos; -+ DevicePoint aPos; - DeviceCoordinate nDist = 0; - DeviceCoordinate nWidth = 0; - const GlyphItem* pGlyph; -@@ -827,10 +827,10 @@ void OutputDevice::ImplDrawTextLines( SalLayout& rSalLayout, FontStrikeout eStri - if( !nWidth ) - { - // get the distance to the base point (as projected to baseline) -- nDist = aPos.X() - aStartPt.X(); -+ nDist = aPos.getX() - aStartPt.getX(); - if( mpFontInstance->mnOrientation ) - { -- const tools::Long nDY = aPos.Y() - aStartPt.Y(); -+ const DeviceCoordinate nDY = aPos.getY() - aStartPt.getY(); - const double fRad = toRadians(mpFontInstance->mnOrientation); - nDist = FRound( nDist*cos(fRad) - nDY*sin(fRad) ); - } -@@ -842,7 +842,7 @@ void OutputDevice::ImplDrawTextLines( SalLayout& rSalLayout, FontStrikeout eStri - else if( nWidth > 0 ) - { - // draw the textline for each word -- ImplDrawTextLine( aStartPt.X(), aStartPt.Y(), nDist, nWidth, -+ ImplDrawTextLine( aStartPt.getX(), aStartPt.getY(), nDist, nWidth, - eStrikeout, eUnderline, eOverline, bUnderlineAbove ); - nWidth = 0; - } -@@ -851,14 +851,14 @@ void OutputDevice::ImplDrawTextLines( SalLayout& rSalLayout, FontStrikeout eStri - // draw textline for the last word - if( nWidth > 0 ) - { -- ImplDrawTextLine( aStartPt.X(), aStartPt.Y(), nDist, nWidth, -+ ImplDrawTextLine( aStartPt.getX(), aStartPt.getY(), nDist, nWidth, - eStrikeout, eUnderline, eOverline, bUnderlineAbove ); - } - } - else - { -- Point aStartPt = rSalLayout.GetDrawPosition(); -- ImplDrawTextLine( aStartPt.X(), aStartPt.Y(), 0, -+ DevicePoint aStartPt = rSalLayout.GetDrawPosition(); -+ ImplDrawTextLine( aStartPt.getX(), aStartPt.getY(), 0, - rSalLayout.GetTextWidth() / rSalLayout.GetUnitsPerPixel(), - eStrikeout, eUnderline, eOverline, bUnderlineAbove ); - } -diff --git a/vcl/source/text/ImplLayoutArgs.cxx b/vcl/source/text/ImplLayoutArgs.cxx -index 7957d1ace824..55e01d2737b8 100644 ---- a/vcl/source/text/ImplLayoutArgs.cxx -+++ b/vcl/source/text/ImplLayoutArgs.cxx -@@ -37,6 +37,7 @@ ImplLayoutArgs::ImplLayoutArgs(const OUString& rStr, int nMinCharPos, int nEndCh - , mnEndCharPos(nEndCharPos) - , m_pTextLayoutCache(pLayoutCache) - , mpDXArray(nullptr) -+ , mpAltNaturalDXArray(nullptr) - , mnLayoutWidth(0) - , mnOrientation(0) - { -@@ -101,6 +102,11 @@ void ImplLayoutArgs::SetLayoutWidth(DeviceCoordinate nWidth) { mnLayoutWidth = n - - void ImplLayoutArgs::SetDXArray(DeviceCoordinate const* pDXArray) { mpDXArray = pDXArray; } - -+void ImplLayoutArgs::SetAltNaturalDXArray(double const* pDXArray) -+{ -+ mpAltNaturalDXArray = pDXArray; -+} -+ - void ImplLayoutArgs::SetOrientation(Degree10 nOrientation) { mnOrientation = nOrientation; } - - void ImplLayoutArgs::ResetPos() { maRuns.ResetPos(); } -@@ -304,7 +310,7 @@ std::ostream& operator<<(std::ostream& s, vcl::text::ImplLayoutArgs const& rArgs - s << "\""; - - s << ",DXArray="; -- if (rArgs.mpDXArray) -+ if (rArgs.mpDXArray || rArgs.mpAltNaturalDXArray) - { - s << "["; - int count = rArgs.mnEndCharPos - rArgs.mnMinCharPos; -@@ -313,7 +319,10 @@ std::ostream& operator<<(std::ostream& s, vcl::text::ImplLayoutArgs const& rArgs - lim = 7; - for (int i = 0; i < lim; i++) - { -- s << rArgs.mpDXArray[i]; -+ if (rArgs.mpDXArray) -+ s << rArgs.mpDXArray[i]; -+ else -+ s << rArgs.mpAltNaturalDXArray[i]; - if (i < lim - 1) - s << ","; - } -@@ -321,7 +330,10 @@ std::ostream& operator<<(std::ostream& s, vcl::text::ImplLayoutArgs const& rArgs - { - if (count > lim + 1) - s << "..."; -- s << rArgs.mpDXArray[count - 1]; -+ if (rArgs.mpDXArray) -+ s << rArgs.mpDXArray[count - 1]; -+ else -+ s << rArgs.mpAltNaturalDXArray[count - 1]; - } - s << "]"; - } -diff --git a/vcl/unx/generic/gdi/cairotextrender.cxx b/vcl/unx/generic/gdi/cairotextrender.cxx -index b14c018652a4..c403c2f3246b 100644 ---- a/vcl/unx/generic/gdi/cairotextrender.cxx -+++ b/vcl/unx/generic/gdi/cairotextrender.cxx -@@ -125,15 +125,15 @@ void CairoTextRender::DrawTextLayout(const GenericSalLayout& rLayout, const SalG - std::vector glyph_extrarotation; - cairo_glyphs.reserve( 256 ); - -- Point aPos; -+ DevicePoint aPos; - const GlyphItem* pGlyph; - int nStart = 0; - while (rLayout.GetNextGlyph(&pGlyph, aPos, nStart)) - { - cairo_glyph_t aGlyph; - aGlyph.index = pGlyph->glyphId(); -- aGlyph.x = aPos.X(); -- aGlyph.y = aPos.Y(); -+ aGlyph.x = aPos.getX(); -+ aGlyph.y = aPos.getY(); - cairo_glyphs.push_back(aGlyph); - - if (pGlyph->IsVertical()) -@@ -172,12 +172,25 @@ void CairoTextRender::DrawTextLayout(const GenericSalLayout& rLayout, const SalG - if (const cairo_font_options_t* pFontOptions = pSVData->mpDefInst->GetCairoFontOptions()) - { - const StyleSettings& rStyleSettings = Application::GetSettings().GetStyleSettings(); -- if (!rStyleSettings.GetUseFontAAFromSystem() && !rGraphics.getAntiAlias()) -+ bool bDisableAA = !rStyleSettings.GetUseFontAAFromSystem() && !rGraphics.getAntiAlias(); -+ -+ const bool bResolutionIndependentLayoutEnabled = rGraphics.getTextRenderModeForResolutionIndependentLayoutEnabled(); -+ cairo_hint_style_t eHintStyle = cairo_font_options_get_hint_style(pFontOptions); -+ cairo_hint_metrics_t eHintMetricsStyle = cairo_font_options_get_hint_metrics(pFontOptions); -+ bool bAllowedHintStyle = !bResolutionIndependentLayoutEnabled || (eHintStyle == CAIRO_HINT_STYLE_NONE || eHintStyle == CAIRO_HINT_STYLE_SLIGHT); -+ bool bAllowedHintMetricStyle = !bResolutionIndependentLayoutEnabled || (eHintMetricsStyle == CAIRO_HINT_METRICS_OFF); -+ -+ if (bDisableAA || !bAllowedHintStyle || !bAllowedHintMetricStyle) - { - // Disable font AA in case global AA setting is supposed to affect - // font rendering (not the default) and AA is disabled. - cairo_font_options_t* pOptions = cairo_font_options_copy(pFontOptions); -- cairo_font_options_set_antialias(pOptions, CAIRO_ANTIALIAS_NONE); -+ if (bDisableAA) -+ cairo_font_options_set_antialias(pOptions, CAIRO_ANTIALIAS_NONE); -+ if (!bAllowedHintStyle) -+ cairo_font_options_set_hint_style(pOptions, CAIRO_HINT_STYLE_SLIGHT); -+ if (!bAllowedHintMetricStyle) -+ cairo_font_options_set_hint_metrics(pOptions, CAIRO_HINT_METRICS_OFF); - cairo_set_font_options(cr, pOptions); - cairo_font_options_destroy(pOptions); - } -diff --git a/vcl/unx/generic/print/genpspgraphics.cxx b/vcl/unx/generic/print/genpspgraphics.cxx -index 359c33026cfd..da0a406dea0b 100644 ---- a/vcl/unx/generic/print/genpspgraphics.cxx -+++ b/vcl/unx/generic/print/genpspgraphics.cxx -@@ -149,10 +149,10 @@ void PspSalLayout::InitFont() const - void GenPspGraphics::DrawTextLayout(const GenericSalLayout& rLayout) - { - const GlyphItem* pGlyph; -- Point aPos; -+ DevicePoint aPos; - int nStart = 0; - while (rLayout.GetNextGlyph(&pGlyph, aPos, nStart)) -- m_pPrinterGfx->DrawGlyph(aPos, *pGlyph); -+ m_pPrinterGfx->DrawGlyph(Point(aPos.getX(), aPos.getY()), *pGlyph); - } - - FontCharMapRef GenPspGraphics::GetFontCharMap() const -diff --git a/vcl/win/gdi/DWriteTextRenderer.cxx b/vcl/win/gdi/DWriteTextRenderer.cxx -index edd0b700bdf6..1ec441b00592 100644 ---- a/vcl/win/gdi/DWriteTextRenderer.cxx -+++ b/vcl/win/gdi/DWriteTextRenderer.cxx -@@ -99,7 +99,7 @@ HRESULT checkResult(HRESULT hr, const char* file, size_t line) - - } // end anonymous namespace - --D2DWriteTextOutRenderer::D2DWriteTextOutRenderer() -+D2DWriteTextOutRenderer::D2DWriteTextOutRenderer(bool bRenderingModeNatural) - : mpD2DFactory(nullptr), - mpDWriteFactory(nullptr), - mpGdiInterop(nullptr), -@@ -110,6 +110,7 @@ D2DWriteTextOutRenderer::D2DWriteTextOutRenderer() - mpFontFace(nullptr), - mlfEmHeight(0.0f), - mhDC(nullptr), -+ mbRenderingModeNatural(bRenderingModeNatural), - meTextAntiAliasMode(D2DTextAntiAliasMode::Default) - { - HRESULT hr = S_OK; -@@ -118,7 +119,7 @@ D2DWriteTextOutRenderer::D2DWriteTextOutRenderer() - if (SUCCEEDED(hr)) - { - hr = mpDWriteFactory->GetGdiInterop(&mpGdiInterop); -- hr = CreateRenderTarget(); -+ hr = CreateRenderTarget(bRenderingModeNatural); - } - meTextAntiAliasMode = lclGetSystemTextAntiAliasMode(); - } -@@ -135,7 +136,7 @@ D2DWriteTextOutRenderer::~D2DWriteTextOutRenderer() - mpD2DFactory->Release(); - } - --void D2DWriteTextOutRenderer::applyTextAntiAliasMode() -+void D2DWriteTextOutRenderer::applyTextAntiAliasMode(bool bRenderingModeNatural) - { - D2D1_TEXT_ANTIALIAS_MODE eTextAAMode = D2D1_TEXT_ANTIALIAS_MODE_DEFAULT; - DWRITE_RENDERING_MODE eRenderingMode = DWRITE_RENDERING_MODE_DEFAULT; -@@ -160,11 +161,15 @@ void D2DWriteTextOutRenderer::applyTextAntiAliasMode() - default: - break; - } -+ -+ if (bRenderingModeNatural) -+ eRenderingMode = DWRITE_RENDERING_MODE_CLEARTYPE_NATURAL; -+ - mpRT->SetTextRenderingParams(lclSetRenderingMode(mpDWriteFactory, eRenderingMode)); - mpRT->SetTextAntialiasMode(eTextAAMode); - } - --HRESULT D2DWriteTextOutRenderer::CreateRenderTarget() -+HRESULT D2DWriteTextOutRenderer::CreateRenderTarget(bool bRenderingModeNatural) - { - if (mpRT) - { -@@ -173,19 +178,10 @@ HRESULT D2DWriteTextOutRenderer::CreateRenderTarget() - } - HRESULT hr = CHECKHR(mpD2DFactory->CreateDCRenderTarget(&mRTProps, &mpRT)); - if (SUCCEEDED(hr)) -- applyTextAntiAliasMode(); -+ applyTextAntiAliasMode(bRenderingModeNatural); - return hr; - } - --void D2DWriteTextOutRenderer::changeTextAntiAliasMode(D2DTextAntiAliasMode eMode) --{ -- if (meTextAntiAliasMode != eMode) -- { -- meTextAntiAliasMode = eMode; -- applyTextAntiAliasMode(); -- } --} -- - bool D2DWriteTextOutRenderer::Ready() const - { - return mpGdiInterop && mpRT; -@@ -199,7 +195,7 @@ HRESULT D2DWriteTextOutRenderer::BindDC(HDC hDC, tools::Rectangle const & rRect) - return CHECKHR(mpRT->BindDC(hDC, &rc)); - } - --bool D2DWriteTextOutRenderer::operator ()(GenericSalLayout const & rLayout, SalGraphics& rGraphics, HDC hDC) -+bool D2DWriteTextOutRenderer::operator()(GenericSalLayout const & rLayout, SalGraphics& rGraphics, HDC hDC, bool bRenderingModeNatural) - { - bool bRetry = false; - bool bResult = false; -@@ -207,13 +203,13 @@ bool D2DWriteTextOutRenderer::operator ()(GenericSalLayout const & rLayout, SalG - do - { - bRetry = false; -- bResult = performRender(rLayout, rGraphics, hDC, bRetry); -+ bResult = performRender(rLayout, rGraphics, hDC, bRetry, bRenderingModeNatural); - nCount++; - } while (bRetry && nCount < 3); - return bResult; - } - --bool D2DWriteTextOutRenderer::performRender(GenericSalLayout const & rLayout, SalGraphics& rGraphics, HDC hDC, bool& bRetry) -+bool D2DWriteTextOutRenderer::performRender(GenericSalLayout const & rLayout, SalGraphics& rGraphics, HDC hDC, bool& bRetry, bool bRenderingModeNatural) - { - if (!Ready()) - return false; -@@ -223,14 +219,14 @@ bool D2DWriteTextOutRenderer::performRender(GenericSalLayout const & rLayout, Sa - - if (hr == D2DERR_RECREATE_TARGET) - { -- CreateRenderTarget(); -+ CreateRenderTarget(bRenderingModeNatural); - bRetry = true; - return false; - } - if (FAILED(hr)) - { - // If for any reason we can't bind fallback to legacy APIs. -- return ExTextOutRenderer()(rLayout, rGraphics, hDC); -+ return ExTextOutRenderer()(rLayout, rGraphics, hDC, bRenderingModeNatural); - } - - mlfEmHeight = 0; -@@ -261,15 +257,15 @@ bool D2DWriteTextOutRenderer::performRender(GenericSalLayout const & rLayout, Sa - mpRT->BeginDraw(); - - int nStart = 0; -- Point aPos(0, 0); -+ DevicePoint aPos; - const GlyphItem* pGlyph; - while (rLayout.GetNextGlyph(&pGlyph, aPos, nStart)) - { - UINT16 glyphIndices[] = { pGlyph->glyphId() }; - FLOAT glyphAdvances[] = { static_cast(pGlyph->m_nNewWidth) / fHScale }; - DWRITE_GLYPH_OFFSET glyphOffsets[] = { { 0.0f, 0.0f }, }; -- D2D1_POINT_2F baseline = { static_cast(aPos.X() - bounds.Left()) / fHScale, -- static_cast(aPos.Y() - bounds.Top()) }; -+ D2D1_POINT_2F baseline = { static_cast(aPos.getX() - bounds.Left()) / fHScale, -+ static_cast(aPos.getY() - bounds.Top()) }; - WinFontTransformGuard aTransformGuard(mpRT, fHScale, rLayout, baseline, pGlyph->IsVertical()); - DWRITE_GLYPH_RUN glyphs = { - mpFontFace, -@@ -295,7 +291,7 @@ bool D2DWriteTextOutRenderer::performRender(GenericSalLayout const & rLayout, Sa - - if (hr == D2DERR_RECREATE_TARGET) - { -- CreateRenderTarget(); -+ CreateRenderTarget(bRenderingModeNatural); - bRetry = true; - } - -diff --git a/vcl/win/gdi/winlayout.cxx b/vcl/win/gdi/winlayout.cxx -index 83033e9f6be8..c55dbbf978e5 100644 ---- a/vcl/win/gdi/winlayout.cxx -+++ b/vcl/win/gdi/winlayout.cxx -@@ -52,7 +52,7 @@ - #include - #include - --TextOutRenderer& TextOutRenderer::get(bool bUseDWrite) -+TextOutRenderer& TextOutRenderer::get(bool bUseDWrite, bool bRenderingModeNatural) - { - SalData* const pSalData = GetSalData(); - -@@ -64,9 +64,13 @@ TextOutRenderer& TextOutRenderer::get(bool bUseDWrite) - - if (bUseDWrite) - { -- if (!pSalData->m_pD2DWriteTextOutRenderer) -+ if (!pSalData->m_pD2DWriteTextOutRenderer -+ || static_cast(pSalData->m_pD2DWriteTextOutRenderer.get()) -+ ->GetRenderingModeNatural() -+ != bRenderingModeNatural) - { -- pSalData->m_pD2DWriteTextOutRenderer.reset(new D2DWriteTextOutRenderer()); -+ pSalData->m_pD2DWriteTextOutRenderer.reset( -+ new D2DWriteTextOutRenderer(bRenderingModeNatural)); - } - return *pSalData->m_pD2DWriteTextOutRenderer; - } -@@ -78,10 +82,10 @@ TextOutRenderer& TextOutRenderer::get(bool bUseDWrite) - } - - bool ExTextOutRenderer::operator()(GenericSalLayout const& rLayout, SalGraphics& /*rGraphics*/, -- HDC hDC) -+ HDC hDC, bool /*bRenderingModeNatural*/) - { - int nStart = 0; -- Point aPos(0, 0); -+ DevicePoint aPos; - const GlyphItem* pGlyph; - const WinFontInstance* pWinFont = static_cast(&rLayout.GetFont()); - UINT nTextAlign = GetTextAlign(hDC); -@@ -106,8 +110,8 @@ bool ExTextOutRenderer::operator()(GenericSalLayout const& rLayout, SalGraphics& - if (nCurTextAlign != nNewTextAlign) - SetTextAlign(hDC, nNewTextAlign); - -- ExtTextOutW(hDC, aPos.X(), aPos.Y() + nYOffset, ETO_GLYPH_INDEX, nullptr, &glyphWStr, 1, -- nullptr); -+ ExtTextOutW(hDC, aPos.getX(), aPos.getY() + nYOffset, ETO_GLYPH_INDEX, nullptr, &glyphWStr, -+ 1, nullptr); - - nCurTextAlign = nNewTextAlign; - } -@@ -294,10 +298,11 @@ void WinFontInstance::SetGraphics(WinSalGraphics* pGraphics) - SelectObject(hDC, hOrigFont); - } - --void WinSalGraphics::DrawTextLayout(const GenericSalLayout& rLayout, HDC hDC, bool bUseDWrite) -+void WinSalGraphics::DrawTextLayout(const GenericSalLayout& rLayout, HDC hDC, bool bUseDWrite, -+ bool bRenderingModeNatural) - { -- TextOutRenderer& render = TextOutRenderer::get(bUseDWrite); -- render(rLayout, *this, hDC); -+ TextOutRenderer& render = TextOutRenderer::get(bUseDWrite, bRenderingModeNatural); -+ render(rLayout, *this, hDC, bRenderingModeNatural); - } - - void WinSalGraphics::DrawTextLayout(const GenericSalLayout& rLayout) -@@ -313,7 +318,11 @@ void WinSalGraphics::DrawTextLayout(const GenericSalLayout& rLayout) - const HFONT hOrigFont = ::SelectFont(hDC, hLayoutFont); - - // DWrite text renderer performs vertical writing better except printing. -- DrawTextLayout(rLayout, hDC, !mbPrinter && rLayout.GetFont().GetFontSelectPattern().mbVertical); -+ const bool bVerticalScreenText -+ = !mbPrinter && rLayout.GetFont().GetFontSelectPattern().mbVertical; -+ const bool bRenderingModeNatural = getTextRenderModeForResolutionIndependentLayoutEnabled(); -+ const bool bUseDWrite = bVerticalScreenText || bRenderingModeNatural; -+ DrawTextLayout(rLayout, hDC, bUseDWrite, bRenderingModeNatural); - - ::SelectFont(hDC, hOrigFont); - } --- -2.35.1 - diff --git a/0001-workaround-x86-ICE-with-gcc-12.patch b/0001-workaround-x86-ICE-with-gcc-12.patch deleted file mode 100644 index 8f59ef8..0000000 --- a/0001-workaround-x86-ICE-with-gcc-12.patch +++ /dev/null @@ -1,35 +0,0 @@ -From 9fcb36d5ebb53f398c48024a1babcc36fc9625f3 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Caol=C3=A1n=20McNamara?= -Date: Sat, 5 Mar 2022 21:42:33 +0000 -Subject: [PATCH] workaround x86 ICE with gcc 12 - -Change-Id: I5c31cf31bf676fde4440e46e532595237cc41bab ---- - sc/source/core/tool/interpr2.cxx | 4 ++++ - 1 file changed, 4 insertions(+) - -diff --git a/sc/source/core/tool/interpr2.cxx b/sc/source/core/tool/interpr2.cxx -index 6525f2a6784b..fd3aba045487 100644 ---- a/sc/source/core/tool/interpr2.cxx -+++ b/sc/source/core/tool/interpr2.cxx -@@ -3421,6 +3421,9 @@ void lclAppendBlock( OStringBuffer& rText, sal_Int32 nValue ) - - } // namespace - -+#if defined(X86) -+void ScInterpreter::ScBahtText() {} -+#else - void ScInterpreter::ScBahtText() - { - sal_uInt8 nParamCount = GetByte(); -@@ -3487,6 +3490,7 @@ void ScInterpreter::ScBahtText() - - PushString( OStringToOUString(aText.makeStringAndClear(), RTL_TEXTENCODING_UTF8) ); - } -+#endif - - void ScInterpreter::ScGetPivotData() - { --- -2.35.1 - diff --git a/libreoffice.spec b/libreoffice.spec index 8013689..d2b8009 100644 --- a/libreoffice.spec +++ b/libreoffice.spec @@ -1,5 +1,5 @@ # download path contains version without the last (fourth) digit -%global libo_version 7.3.5 +%global libo_version 7.4.0 # Should contain .alphaX / .betaX, if this is pre-release (actually # pre-RC) version. The pre-release string is part of tarball file names, # so we need a way to define it easily at one place. @@ -151,6 +151,7 @@ BuildRequires: pkgconfig(gobject-introspection-1.0) BuildRequires: pkgconfig(gstreamer-1.0) BuildRequires: pkgconfig(gstreamer-plugins-base-1.0) BuildRequires: pkgconfig(gtk+-3.0) +BuildRequires: pkgconfig(gtk+-4.0) BuildRequires: pkgconfig(hunspell) BuildRequires: pkgconfig(ice) BuildRequires: pkgconfig(icu-i18n) @@ -252,11 +253,6 @@ Patch1: 0001-disble-tip-of-the-day-dialog-by-default.patch Patch2: 0001-Resolves-rhbz-1432468-disable-opencl-by-default.patch # backported Patch3: 0001-Revert-tdf-101630-gdrive-support-w-oAuth-and-Drive-A.patch -# ICE -Patch4: 0001-workaround-x86-ICE-with-gcc-12.patch -Patch5: 0001-s390x-canvas-test-fails.patch -Patch6: 0001-tdf-144862-use-resolution-independent-positions-for-.patch -Patch7: 0001-rhbz-2104545-Only-call-utl-IsYounger-when-its-result.patch # not upstreamed Patch500: 0001-disable-libe-book-support.patch @@ -611,6 +607,15 @@ Supplements: (%{name}-core%{?_isa} and gtk3%{?_isa}) %description gtk3 A plug-in for LibreOffice that enables integration into GTK+ 3 environment. +%package gtk4 +Summary: LibreOffice GTK+ 4 experimental integration plug-in +Requires: %{name}-core%{?_isa} = %{epoch}:%{version}-%{release} +Requires: %{name}-ure%{?_isa} = %{epoch}:%{version}-%{release} +Supplements: (%{name}-core%{?_isa} and gtk4%{?_isa}) + +%description gtk4 +An experimental plug-in for LibreOffice that enables integration into GTK+ 4 environment. + %if 0%{?fedora} %package kf5 @@ -1089,6 +1094,7 @@ touch autogen.lastrun --enable-python=system \ --with-idlc-cpp=cpp \ --disable-scripting-beanshell --disable-scripting-javascript \ + --enable-gtk4 \ %{javaoptions} \ %{distrooptions} \ %{?bundling_options} \ @@ -1370,7 +1376,7 @@ install -m 0644 -p mime/packages/libreoffice$PRODUCTVERSION.xml %{buildroot}%{_d %if 0%{?fedora} # restrict abipkgdiff to shared objects that actually have a stable ABI -for pkg in core base officebean ogltrans pdfimport calc writer impress graphicfilter postgresql ure pyuno x11 gtk3 kf5 libreofficekit; do +for pkg in core base officebean ogltrans pdfimport calc writer impress graphicfilter postgresql ure pyuno x11 gtk3 gtk4 kf5 libreofficekit; do cat > %{buildroot}%{baseinstdir}/program/${pkg}.abignore << _EOF [suppress_file] file_name_not_regexp=.*\.so\.[0-9]+ @@ -1501,9 +1507,7 @@ rm -f %{buildroot}%{baseinstdir}/program/officebean.abignore %endif %check -%ifnarch s390x make unitcheck slowcheck -%endif # we don't need this anymore rm -f %{buildroot}%{baseinstdir}/program/classes/smoketest.jar @@ -2224,6 +2228,12 @@ gtk-update-icon-cache -q %{_datadir}/icons/hicolor &>/dev/null || : %endif %{baseinstdir}/program/libvclplug_gtk3lo.so +%files gtk4 +%if 0%{?fedora} +%{baseinstdir}/program/gtk4.abignore +%endif +%{baseinstdir}/program/libvclplug_gtk4lo.so + %if 0%{?fedora} %files kf5 @@ -2247,6 +2257,9 @@ gtk-update-icon-cache -q %{_datadir}/icons/hicolor &>/dev/null || : %{_includedir}/LibreOfficeKit %changelog +* Tue Aug 09 2022 Caolán McNamara - 1:7.4.0.2-1 +- 7.4 version + * Wed Aug 03 2022 Caolán McNamara - 1:7.3.5.2-3 - Rebuilt for poppler 22.08.0 diff --git a/sources b/sources index 4288036..3f3482d 100644 --- a/sources +++ b/sources @@ -5,9 +5,9 @@ SHA512 (f543e6e2d7275557a839a164941c0a86e5f2c3f2a0042bfc434c88c6dde9e140-opens__ SHA512 (libreoffice-multiliblauncher.sh) = db532afdf5000bc66f9e02c7d0ab586468466f63f8f0bdb204832581e8277c5c59f688fa096548d642411cb8c46e8de4a744676b4e624c075262cfd6945138cd SHA512 (dtoa-20180411.tgz) = 722aa814c33a34bfffe6c0201b0035cc3b65854a0ba9ae2f51620a89d68019353e2c306651b35bca337186b22b2e9865ef3c5e3df8e9328006f882e4577f8c85 SHA512 (libcuckoo-93217f8d391718380c508a722ab9acd5e9081233.tar.gz) = 4159dfb4d08e359feb23127e12db590260913e70774161ac9513abb5183ad6ed6d2bdfbe56fc8aa68e2fc57ee29eae67aa0180e1a7d955016884ecba2ca60ff8 -SHA512 (libreoffice-7.3.5.2.tar.xz) = 00d381e97c0bc6f97d4e770b7037f08fc659e58e792d47b539ecd0b3fb4e3e9b570769e9b3eb26522d951fa14926f71bef8567756b8b8b8c4777a00e48ee030c -SHA512 (libreoffice-7.3.5.2.tar.xz.asc) = 9680c5f12a1c6e51d7000e7af1d2b176d353e850ade9d8298668d866cbbfd1ba93f1375d9003089bfaa83b5dd438d49080f3d7843cf6fb7d80ca07617022c935 -SHA512 (libreoffice-help-7.3.5.2.tar.xz) = 9e8c782fa20bef6806d96965c469be2423d5be6e6b3e78f690c553294cfe83877cd96fc2234caa247cf063264c1bea4909047771298946e33ae83e04597104c6 -SHA512 (libreoffice-help-7.3.5.2.tar.xz.asc) = 3cedc500e4f7d6d8a284bf9323ef475f8453ea2979df586980b174d7fc3105075eeb4bd590a5d834bbfde60b4985e5e0d36a308e827bda11dcb5c11b91b31f2a -SHA512 (libreoffice-translations-7.3.5.2.tar.xz) = fc928a77f804b886d6d494307c0d028d42c6322c211911eb2aaeb68d4b3d1992f5d43b22668464d8fffbbf1bcddfcc19a810192b10d4d37e51039aa639b2bbce -SHA512 (libreoffice-translations-7.3.5.2.tar.xz.asc) = 76f14f67bf26e3225661da4042d9defb0980d3fd556e63661bf85b0e11fdf3801cdd5f5a1b442296c5410906e6ff492ce103d781241448fd4a90fae491ecf824 +SHA512 (libreoffice-7.4.0.2.tar.xz) = f7b6493bf43f4396e108fc75387a0ed9ca7a9c9f743dda779dcc084ba174ebf3ce35cb207c8ee9544ef12a7d5084ff6f221d8b63f1a3a2ab4cce7c16bb340fec +SHA512 (libreoffice-7.4.0.2.tar.xz.asc) = 25f8f6976a519b8359eb02373484cd7ff5dbedaab98f61f930f73b7b73d4d0e28a2f2118c727146038c4b96629b19ac199934350a7f33b979ca16709a0edacb3 +SHA512 (libreoffice-help-7.4.0.2.tar.xz) = ac742a502a7f14a0b46cc490452bf621d2841cb83f3538f50853b694be15bcd39f57cf2ad17f07d59be13a4db0634b1a0e4d06a572c60e102c9d913a274ddeea +SHA512 (libreoffice-help-7.4.0.2.tar.xz.asc) = 2c87fa17a7935b44c65d9af02d6d0e86557d45ff9c99901d8d460be84c7c920d3589cdeb4f80b3f55d8103454a16b705c4622391c75b815d6b8e67e3813296d7 +SHA512 (libreoffice-translations-7.4.0.2.tar.xz) = a4492cc407af1759927414de30eebc4e3bc8398f23898224a3155e3f4c22c98ff4aae1283532c7a5e29b49625d5b2e973c26513c15101c30d795498651af74ce +SHA512 (libreoffice-translations-7.4.0.2.tar.xz.asc) = d63eee1a44584bbb406898de319af2db757fab6611b67c845f42e4d319e57eeefa4bafda9fc134cda9b87799bbfb9ba9b409fee03b5e77dd3c6b1d024c0fe235