vcl/inc/ImplLayoutArgs.hxx         |    8 ++----
 vcl/inc/sallayout.hxx              |   10 +++-----
 vcl/source/gdi/CommonSalLayout.cxx |   15 ++++--------
 vcl/source/gdi/sallayout.cxx       |   20 ++++++++--------
 vcl/source/outdev/text.cxx         |   46 ++++++++++---------------------------
 vcl/source/text/ImplLayoutArgs.cxx |   22 ++++-------------
 6 files changed, 41 insertions(+), 80 deletions(-)

New commits:
commit 9cabb7ca71dfc426b9925300c4214f05399bfd12
Author:     Caolán McNamara <caol...@redhat.com>
AuthorDate: Fri Aug 19 20:54:14 2022 +0100
Commit:     Caolán McNamara <caol...@redhat.com>
CommitDate: Sat Aug 20 13:06:09 2022 +0200

    always transport the text dxarray as doubles when rendering
    
    continue to do rounding to integer, just transported as double,
    unless the opt-in TextRenderModeForResolutionIndependentLayout is set,
    so this is not intended to create visible changes
    
    though
    nRunAdvance = static_cast<tools::Long>(nRunAdvance*fUnitMul + 0.5);
    becomes
    nRunAdvance = nRunAdvance * fUnitMul;
    in MultiSalLayout::ImplAdjustMultiLayout which might create a
    difference, but it is in the glyph fallback case where things are a last
    ditch effort already
    
    Change-Id: Iebd4ff9a602d0fa29a5253d73e6372d274d0c8c9
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/138565
    Tested-by: Jenkins
    Reviewed-by: Caolán McNamara <caol...@redhat.com>

diff --git a/vcl/inc/ImplLayoutArgs.hxx b/vcl/inc/ImplLayoutArgs.hxx
index 105a4e2d8961..381d09185563 100644
--- a/vcl/inc/ImplLayoutArgs.hxx
+++ b/vcl/inc/ImplLayoutArgs.hxx
@@ -35,8 +35,7 @@ public:
     vcl::text::TextLayoutCache const* m_pTextLayoutCache;
 
     // positioning related inputs
-    const DeviceCoordinate* mpDXArray; // in integer pixel units
-    const double* mpAltNaturalDXArray; // in floating point pixel units
+    const double* mpNaturalDXArray; // in floating point pixel units
     const sal_Bool* mpKashidaArray;
     DeviceCoordinate mnLayoutWidth; // in pixel units
     Degree10 mnOrientation; // in 0-3600 system
@@ -49,8 +48,7 @@ public:
                    LanguageTag aLanguageTag, vcl::text::TextLayoutCache const* 
pLayoutCache);
 
     void SetLayoutWidth(DeviceCoordinate nWidth);
-    void SetDXArray(const DeviceCoordinate* pDXArray);
-    void SetAltNaturalDXArray(const double* pDXArray);
+    void SetNaturalDXArray(const double* pDXArray);
     void SetKashidaArray(const sal_Bool* pKashidaArray);
     void SetOrientation(Degree10 nOrientation);
 
@@ -58,7 +56,7 @@ public:
     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; }
+    bool HasDXArray() const { return mpNaturalDXArray; }
 
     // methods used by BiDi and glyph fallback
     bool HasFallbackRun() const;
diff --git a/vcl/inc/sallayout.hxx b/vcl/inc/sallayout.hxx
index b49c1c663ee4..165a6170bbc2 100644
--- a/vcl/inc/sallayout.hxx
+++ b/vcl/inc/sallayout.hxx
@@ -82,10 +82,9 @@ public:
 
     void SetIncomplete(bool bIncomplete);
 
-    template<typename DC>
     void            ImplAdjustMultiLayout(vcl::text::ImplLayoutArgs& rArgs,
                                           vcl::text::ImplLayoutArgs& 
rMultiArgs,
-                                          const DC* pMultiDXArray);
+                                          const double* pMultiDXArray);
 
     virtual         ~MultiSalLayout() override;
 
@@ -101,10 +100,10 @@ private:
 
 class VCL_DLLPUBLIC GenericSalLayout : public SalLayout
 {
-    template<typename DC> friend void MultiSalLayout::ImplAdjustMultiLayout(
+    friend void MultiSalLayout::ImplAdjustMultiLayout(
             vcl::text::ImplLayoutArgs& rArgs,
             vcl::text::ImplLayoutArgs& rMultiArgs,
-            const DC* pMultiDXArray);
+            const double* pMultiDXArray);
 
 public:
                     GenericSalLayout(LogicalFontInstance&);
@@ -142,8 +141,7 @@ private:
                     GenericSalLayout( const GenericSalLayout& ) = delete;
                     GenericSalLayout& operator=( const GenericSalLayout& ) = 
delete;
 
-    template<typename DC>
-    void            ApplyDXArray(const DC*, const sal_Bool*);
+    void            ApplyDXArray(const double*, const sal_Bool*);
     void            Justify(DeviceCoordinate nNewWidth);
     void            ApplyAsianKerning(const OUString& rStr);
 
diff --git a/vcl/source/gdi/CommonSalLayout.cxx 
b/vcl/source/gdi/CommonSalLayout.cxx
index eff9dab9acbb..4072a47d7109 100644
--- a/vcl/source/gdi/CommonSalLayout.cxx
+++ b/vcl/source/gdi/CommonSalLayout.cxx
@@ -196,10 +196,8 @@ void 
GenericSalLayout::AdjustLayout(vcl::text::ImplLayoutArgs& rArgs)
 {
     SalLayout::AdjustLayout(rArgs);
 
-    if (rArgs.mpAltNaturalDXArray) // Used when 
"TextRenderModeForResolutionIndependentLayout" is set
-        ApplyDXArray(rArgs.mpAltNaturalDXArray, rArgs.mpKashidaArray);
-    else if (rArgs.mpDXArray)   // Normal case
-        ApplyDXArray(rArgs.mpDXArray, rArgs.mpKashidaArray);
+    if (rArgs.mpNaturalDXArray)
+        ApplyDXArray(rArgs.mpNaturalDXArray, rArgs.mpKashidaArray);
     else if (rArgs.mnLayoutWidth)
         Justify(rArgs.mnLayoutWidth);
     // apply asian kerning if the glyphs are not already formatted
@@ -653,12 +651,11 @@ void 
GenericSalLayout::GetCharWidths(std::vector<DeviceCoordinate>& rCharWidths)
 //   justification).
 // - pKashidaArray: is the places where kashidas are inserted (for Arabic
 //   justification). The number of kashidas is calculated from the pDXArray.
-template<typename DC>
-void GenericSalLayout::ApplyDXArray(const DC* pDXArray, const sal_Bool* 
pKashidaArray)
+void GenericSalLayout::ApplyDXArray(const double* pDXArray, const sal_Bool* 
pKashidaArray)
 {
     int nCharCount = mnEndCharPos - mnMinCharPos;
     std::vector<DeviceCoordinate> aOldCharWidths;
-    std::unique_ptr<DC[]> const pNewCharWidths(new DC[nCharCount]);
+    std::unique_ptr<double[]> const pNewCharWidths(new double[nCharCount]);
 
     // Get the natural character widths (i.e. before applying DX adjustments).
     GetCharWidths(aOldCharWidths);
@@ -677,7 +674,7 @@ void GenericSalLayout::ApplyDXArray(const DC* pDXArray, 
const sal_Bool* pKashida
     std::map<size_t, DeviceCoordinate> pKashidas;
 
     // The accumulated difference in X position.
-    DC nDelta = 0;
+    double nDelta = 0;
 
     // Apply the DX adjustments to glyph positions and widths.
     size_t i = 0;
@@ -686,7 +683,7 @@ void GenericSalLayout::ApplyDXArray(const DC* pDXArray, 
const sal_Bool* pKashida
         // Accumulate the width difference for all characters corresponding to
         // this glyph.
         int nCharPos = m_GlyphItems[i].charPos() - mnMinCharPos;
-        DC nDiff = 0;
+        double nDiff = 0;
         for (int j = 0; j < m_GlyphItems[i].charCount(); j++)
             nDiff += pNewCharWidths[nCharPos + j] - aOldCharWidths[nCharPos + 
j];
 
diff --git a/vcl/source/gdi/sallayout.cxx b/vcl/source/gdi/sallayout.cxx
index cf74b3efdb8f..eca07148ed53 100644
--- a/vcl/source/gdi/sallayout.cxx
+++ b/vcl/source/gdi/sallayout.cxx
@@ -660,6 +660,7 @@ void MultiSalLayout::AdjustLayout( 
vcl::text::ImplLayoutArgs& rArgs )
     SalLayout::AdjustLayout( rArgs );
     vcl::text::ImplLayoutArgs aMultiArgs = rArgs;
     std::vector<DeviceCoordinate> aJustificationArray;
+    std::vector<double> aNaturalJustificationArray;
 
     if( !rArgs.HasDXArray() && rArgs.mnLayoutWidth )
     {
@@ -721,21 +722,20 @@ void MultiSalLayout::AdjustLayout( 
vcl::text::ImplLayoutArgs& rArgs )
                 }
             }
 
-            // change the mpDXArray temporarily (just for the justification)
-            aMultiArgs.mpDXArray = aJustificationArray.data();
+            aNaturalJustificationArray.reserve(aJustificationArray.size());
+            for (DeviceCoordinate a : aJustificationArray)
+                aNaturalJustificationArray.push_back(a);
+            // change the DXArray temporarily (just for the justification)
+            aMultiArgs.mpNaturalDXArray = aNaturalJustificationArray.data();
         }
     }
 
-    if (aMultiArgs.mpAltNaturalDXArray)
-        ImplAdjustMultiLayout(rArgs, aMultiArgs, 
aMultiArgs.mpAltNaturalDXArray);
-    else
-        ImplAdjustMultiLayout(rArgs, aMultiArgs, aMultiArgs.mpDXArray);
+    ImplAdjustMultiLayout(rArgs, aMultiArgs, aMultiArgs.mpNaturalDXArray);
 }
 
-template<typename DC>
 void MultiSalLayout::ImplAdjustMultiLayout(vcl::text::ImplLayoutArgs& rArgs,
                                            vcl::text::ImplLayoutArgs& 
rMultiArgs,
-                                           const DC* pMultiDXArray)
+                                           const double* pMultiDXArray)
 {
     // Compute rtl flags, since in some scripts glyphs/char order can be
     // reversed for a few character sequences e.g. Myanmar
@@ -865,7 +865,7 @@ void 
MultiSalLayout::ImplAdjustMultiLayout(vcl::text::ImplLayoutArgs& rArgs,
         }
 
         // skip to end of layout run and calculate its advance width
-        DC nRunAdvance = 0;
+        double nRunAdvance = 0;
         bool bKeepNotDef = (nFBLevel >= nLevel);
         for(;;)
         {
@@ -976,7 +976,7 @@ void 
MultiSalLayout::ImplAdjustMultiLayout(vcl::text::ImplLayoutArgs& rArgs,
             // the measured width is still in fallback font units
             // => convert it to base level font units
             if( n > 0 ) // optimization: because (fUnitMul==1.0) for (n==0)
-                nRunAdvance = static_cast<tools::Long>(nRunAdvance*fUnitMul + 
0.5);
+                nRunAdvance = nRunAdvance * fUnitMul;
         }
 
         // calculate new x position (in base level units)
diff --git a/vcl/source/outdev/text.cxx b/vcl/source/outdev/text.cxx
index 06f43fa2d3ea..d2c8855a2543 100644
--- a/vcl/source/outdev/text.cxx
+++ b/vcl/source/outdev/text.cxx
@@ -1356,7 +1356,6 @@ std::unique_ptr<SalLayout> OutputDevice::ImplLayout(const 
OUString& rOrigStr,
 
     OUString aStr = rOrigStr;
 
-    // convert from logical units to physical units
     // recode string if needed
     if( mpFontInstance->mpConversion ) {
         mpFontInstance->mpConversion->RecodeString( aStr, 0, aStr.getLength() 
);
@@ -1367,6 +1366,7 @@ std::unique_ptr<SalLayout> OutputDevice::ImplLayout(const 
OUString& rOrigStr,
     DeviceCoordinate nPixelWidth = 
static_cast<DeviceCoordinate>(nLogicalWidth);
     if( nLogicalWidth && mbMap )
     {
+        // convert from logical units to physical units
         nPixelWidth = LogicWidthToDeviceCoordinate( nLogicalWidth );
     }
 
@@ -1375,59 +1375,39 @@ std::unique_ptr<SalLayout> 
OutputDevice::ImplLayout(const OUString& rOrigStr,
 
     bool bTextRenderModeForResolutionIndependentLayout(false);
     DeviceCoordinate nEndGlyphCoord(0);
-    std::unique_ptr<DeviceCoordinate[]> xDXPixelArray;
     std::unique_ptr<double[]> xNaturalDXPixelArray;
     if( !pDXArray.empty() )
     {
-        DeviceCoordinate* pDXPixelArray(nullptr);
+        xNaturalDXPixelArray.reset(new double[nLen]);
+
         if (mbMap)
         {
+            // convert from logical units to font units
             if (GetTextRenderModeForResolutionIndependentLayout())
             {
+                // without rounding, keeping accuracy for lower levels
                 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();
+                // with rounding
                 // 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];
+                for (int i = 0; i < nLen; ++i)
+                    xNaturalDXPixelArray[i] = 
(LogicWidthToDeviceCoordinate((rLogicalPos.X() + pDXArray[i]) * 2) - 
nPixelXOfs2) / 2;
             }
-
         }
         else
         {
-#if VCL_FLOAT_DEVICE_PIXEL
-            xDXPixelArray.reset(new DeviceCoordinate[nLen]);
-            pDXPixelArray = xDXPixelArray.get();
-            for( int i = 0; i < nLen; ++i )
-            {
-                pDXPixelArray[i] = pDXArray[i];
-            }
-#else /* !VCL_FLOAT_DEVICE_PIXEL */
-            pDXPixelArray = const_cast<DeviceCoordinate*>(pDXArray.data());
-#endif /* !VCL_FLOAT_DEVICE_PIXEL */
-
-            aLayoutArgs.SetDXArray(pDXPixelArray);
-            nEndGlyphCoord = pDXPixelArray[nLen - 1];
+            for(int i = 0; i < nLen; ++i)
+                xNaturalDXPixelArray[i] = pDXArray[i];
         }
+
+        aLayoutArgs.SetNaturalDXArray(xNaturalDXPixelArray.get());
+        nEndGlyphCoord = std::lround(xNaturalDXPixelArray[nLen - 1]);
     }
 
     if (!pKashidaArray.empty())
diff --git a/vcl/source/text/ImplLayoutArgs.cxx 
b/vcl/source/text/ImplLayoutArgs.cxx
index 45b951a9845d..943de7d2eb75 100644
--- a/vcl/source/text/ImplLayoutArgs.cxx
+++ b/vcl/source/text/ImplLayoutArgs.cxx
@@ -37,8 +37,7 @@ ImplLayoutArgs::ImplLayoutArgs(const OUString& rStr, int 
nMinCharPos, int nEndCh
     , mnMinCharPos(nMinCharPos)
     , mnEndCharPos(nEndCharPos)
     , m_pTextLayoutCache(pLayoutCache)
-    , mpDXArray(nullptr)
-    , mpAltNaturalDXArray(nullptr)
+    , mpNaturalDXArray(nullptr)
     , mpKashidaArray(nullptr)
     , mnLayoutWidth(0)
     , mnOrientation(0)
@@ -91,12 +90,7 @@ ImplLayoutArgs::ImplLayoutArgs(const OUString& rStr, int 
nMinCharPos, int nEndCh
 
 void ImplLayoutArgs::SetLayoutWidth(DeviceCoordinate nWidth) { mnLayoutWidth = 
nWidth; }
 
-void ImplLayoutArgs::SetDXArray(DeviceCoordinate const* pDXArray) { mpDXArray 
= pDXArray; }
-
-void ImplLayoutArgs::SetAltNaturalDXArray(double const* pDXArray)
-{
-    mpAltNaturalDXArray = pDXArray;
-}
+void ImplLayoutArgs::SetNaturalDXArray(double const* pDXArray) { 
mpNaturalDXArray = pDXArray; }
 
 void ImplLayoutArgs::SetKashidaArray(sal_Bool const* pKashidaArray)
 {
@@ -308,7 +302,7 @@ std::ostream& operator<<(std::ostream& s, 
vcl::text::ImplLayoutArgs const& rArgs
     s << "\"";
 
     s << ",DXArray=";
-    if (rArgs.mpDXArray || rArgs.mpAltNaturalDXArray)
+    if (rArgs.mpNaturalDXArray)
     {
         s << "[";
         int count = rArgs.mnEndCharPos - rArgs.mnMinCharPos;
@@ -317,10 +311,7 @@ std::ostream& operator<<(std::ostream& s, 
vcl::text::ImplLayoutArgs const& rArgs
             lim = 7;
         for (int i = 0; i < lim; i++)
         {
-            if (rArgs.mpDXArray)
-                s << rArgs.mpDXArray[i];
-            else
-                s << rArgs.mpAltNaturalDXArray[i];
+            s << rArgs.mpNaturalDXArray[i];
             if (i < lim - 1)
                 s << ",";
         }
@@ -328,10 +319,7 @@ std::ostream& operator<<(std::ostream& s, 
vcl::text::ImplLayoutArgs const& rArgs
         {
             if (count > lim + 1)
                 s << "...";
-            if (rArgs.mpDXArray)
-                s << rArgs.mpDXArray[count - 1];
-            else
-                s << rArgs.mpAltNaturalDXArray[count - 1];
+            s << rArgs.mpNaturalDXArray[count - 1];
         }
         s << "]";
     }

Reply via email to