include/vcl/outdev.hxx             |    1 
 vcl/inc/ImplLayoutArgs.hxx         |    4 ++-
 vcl/inc/sallayout.hxx              |    3 +-
 vcl/source/gdi/CommonSalLayout.cxx |   14 ++++++-----
 vcl/source/outdev/map.cxx          |    8 ++++++
 vcl/source/outdev/text.cxx         |   47 ++++++++++++++++++++++++++-----------
 vcl/source/text/ImplLayoutArgs.cxx |    6 ++++
 7 files changed, 62 insertions(+), 21 deletions(-)

New commits:
commit bb830461f0c22f7efe10de799a6a39b56cc5b4a5
Author:     Caolán McNamara <caol...@redhat.com>
AuthorDate: Thu Jan 13 12:12:51 2022 +0000
Commit:     Caolán McNamara <caol...@redhat.com>
CommitDate: Thu Jan 13 18:32:28 2022 +0100

    keep scaled ResolutionIndependentLayout glyph positions as floating point
    
    When rendering in ResolutionIndependentLayout mode keep the scaled
    glyph positions as floating point all the way down to the renderer
    
    Change-Id: I02415f18c26737a886751972f472b499a25c776b
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/128379
    Tested-by: Jenkins
    Reviewed-by: Caolán McNamara <caol...@redhat.com>

diff --git a/include/vcl/outdev.hxx b/include/vcl/outdev.hxx
index ddeafe9f8599..0282ea8458b5 100644
--- a/include/vcl/outdev.hxx
+++ b/include/vcl/outdev.hxx
@@ -1699,6 +1699,7 @@ public:
     SAL_DLLPRIVATE tools::Long         ImplLogicWidthToDevicePixel( 
tools::Long nWidth ) const;
 
     SAL_DLLPRIVATE DeviceCoordinate LogicWidthToDeviceCoordinate( tools::Long 
nWidth ) const;
+    SAL_DLLPRIVATE double LogicWidthToDeviceFontCoordinate( tools::Long nWidth 
) const;
 
     /** Convert a logical X coordinate to a device pixel's X coordinate.
 
diff --git a/vcl/inc/ImplLayoutArgs.hxx b/vcl/inc/ImplLayoutArgs.hxx
index 865470b7897a..fa5e8005ba00 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,6 +49,7 @@ public:
 
     void SetLayoutWidth(DeviceCoordinate nWidth);
     void SetDXArray(const DeviceCoordinate* pDXArray);
+    void SetAltNaturalDXArray(const double* pDXArray);
     void SetOrientation(Degree10 nOrientation);
 
     void ResetPos();
diff --git a/vcl/inc/sallayout.hxx b/vcl/inc/sallayout.hxx
index acd49edfda30..f5ffd0f2e587 100644
--- a/vcl/inc/sallayout.hxx
+++ b/vcl/inc/sallayout.hxx
@@ -136,7 +136,8 @@ private:
                     GenericSalLayout( const GenericSalLayout& ) = delete;
                     GenericSalLayout& operator=( const GenericSalLayout& ) = 
delete;
 
-    void            ApplyDXArray(const DeviceCoordinate*, SalLayoutFlags 
nLayoutFlags);
+    template<typename DC>
+    void            ApplyDXArray(const DC*, SalLayoutFlags nLayoutFlags);
     void            Justify(DeviceCoordinate nNewWidth);
     void            ApplyAsianKerning(const OUString& rStr);
 
diff --git a/vcl/source/gdi/CommonSalLayout.cxx 
b/vcl/source/gdi/CommonSalLayout.cxx
index f1cbb149dd33..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);
@@ -635,12 +637,12 @@ void 
GenericSalLayout::GetCharWidths(std::vector<DeviceCoordinate>& 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<typename DC>
+void GenericSalLayout::ApplyDXArray(const DC* pDXArray, SalLayoutFlags 
nLayoutFlags)
 {
     int nCharCount = mnEndCharPos - mnMinCharPos;
     std::vector<DeviceCoordinate> aOldCharWidths;
-    std::unique_ptr<DeviceCoordinate[]> const pNewCharWidths(new 
DeviceCoordinate[nCharCount]);
+    std::unique_ptr<DC[]> 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<size_t, DeviceCoordinate> 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];
 
diff --git a/vcl/source/outdev/map.cxx b/vcl/source/outdev/map.cxx
index 73badc74bcfc..f98ff3057b6f 100644
--- a/vcl/source/outdev/map.cxx
+++ b/vcl/source/outdev/map.cxx
@@ -1830,4 +1830,12 @@ DeviceCoordinate 
OutputDevice::LogicWidthToDeviceCoordinate( tools::Long nWidth
 #endif
 }
 
+double OutputDevice::LogicWidthToDeviceFontCoordinate(tools::Long nWidth) const
+{
+    if (!mbMap)
+        return nWidth;
+
+    return ImplLogicToPixel(static_cast<double>(nWidth), mnDPIX, 
maMapRes.mnMapScNumX, maMapRes.mnMapScDenomX);
+}
+
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/source/outdev/text.cxx b/vcl/source/outdev/text.cxx
index 916bff7cab2d..de196499a81f 100644
--- a/vcl/source/outdev/text.cxx
+++ b/vcl/source/outdev/text.cxx
@@ -1341,21 +1341,41 @@ std::unique_ptr<SalLayout> 
OutputDevice::ImplLayout(const OUString& rOrigStr,
     vcl::text::ImplLayoutArgs aLayoutArgs = ImplPrepareLayoutArgs( aStr, 
nMinIndex, nLen,
             nPixelWidth, flags, pLayoutCache);
 
+    DeviceCoordinate nEndGlyphCoord(0);
     std::unique_ptr<DeviceCoordinate[]> xDXPixelArray;
-    DeviceCoordinate* pDXPixelArray(nullptr);
+    std::unique_ptr<double[]> 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;
+                // 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] = 
LogicWidthToDeviceFontCoordinate(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
         {
@@ -1369,11 +1389,12 @@ std::unique_ptr<SalLayout> 
OutputDevice::ImplLayout(const OUString& rOrigStr,
 #else /* !VCL_FLOAT_DEVICE_PIXEL */
             pDXPixelArray = const_cast<DeviceCoordinate*>(pDXArray.data());
 #endif /* !VCL_FLOAT_DEVICE_PIXEL */
+
+            aLayoutArgs.SetDXArray(pDXPixelArray);
+            nEndGlyphCoord = pDXPixelArray[nLen - 1];
         }
     }
 
-    aLayoutArgs.SetDXArray(pDXPixelArray);
-
     // get matching layout object for base font
     std::unique_ptr<SalLayout> pSalLayout = mpGraphics->GetTextLayout(0);
 
@@ -1403,8 +1424,8 @@ std::unique_ptr<SalLayout> OutputDevice::ImplLayout(const 
OUString& rOrigStr,
     if( aLayoutArgs.mnFlags & SalLayoutFlags::RightAlign )
     {
         DeviceCoordinate nRTLOffset;
-        if( pDXPixelArray )
-            nRTLOffset = pDXPixelArray[ nLen - 1 ];
+        if (!pDXArray.empty())
+            nRTLOffset = nEndGlyphCoord;
         else if( nPixelWidth )
             nRTLOffset = nPixelWidth;
         else
diff --git a/vcl/source/text/ImplLayoutArgs.cxx 
b/vcl/source/text/ImplLayoutArgs.cxx
index 7957d1ace824..a5b0ebb0a39f 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(); }

Reply via email to