[Libreoffice-commits] core.git: vcl/inc vcl/source

Khaled Hosny khaledhosny at eglug.org
Mon Nov 28 05:40:55 UTC 2016


 vcl/inc/sallayout.hxx              |    1 
 vcl/source/gdi/CommonSalLayout.cxx |   76 +++++++++++++++----------------------
 vcl/source/gdi/sallayout.cxx       |   35 -----------------
 3 files changed, 32 insertions(+), 80 deletions(-)

New commits:
commit f246542d1f61b5253189676688f59e5f952267a1
Author: Khaled Hosny <khaledhosny at eglug.org>
Date:   Mon Nov 28 06:43:29 2016 +0200

    Simplify things a bit
    
    * Drop SortGlyphItems() and update the Kashida insertion code not depend
      on that sorting.
    * IS_DIACRITIC flag can now be based solely on the General Category
      property, since it now is used for non-spacing marks not any OpenType
      mark glyph. Pending complete removal.
    * Check whether a glyph can take Kashida or not in one place. We need to
      stop second-guessing here and pass explicit Kashida insertion points
      from upper layers.
    
    Change-Id: I39caa126a07d08c5725505615acc0c8f7a14e169
    Reviewed-on: https://gerrit.libreoffice.org/31300
    Tested-by: Jenkins <ci at libreoffice.org>
    Reviewed-by: Khaled Hosny <khaledhosny at eglug.org>

diff --git a/vcl/inc/sallayout.hxx b/vcl/inc/sallayout.hxx
index c20a582..effb646 100644
--- a/vcl/inc/sallayout.hxx
+++ b/vcl/inc/sallayout.hxx
@@ -333,7 +333,6 @@ public:
     virtual void    ApplyDXArray(ImplLayoutArgs&) = 0;
     void            Justify(DeviceCoordinate nNewWidth);
     void            ApplyAsianKerning(const OUString& rStr);
-    void            SortGlyphItems();
 
     // used by upper layers
     virtual DeviceCoordinate GetTextWidth() const override;
diff --git a/vcl/source/gdi/CommonSalLayout.cxx b/vcl/source/gdi/CommonSalLayout.cxx
index 59a5d80..c61e540 100644
--- a/vcl/source/gdi/CommonSalLayout.cxx
+++ b/vcl/source/gdi/CommonSalLayout.cxx
@@ -598,29 +598,15 @@ bool CommonSalLayout::LayoutText(ImplLayoutArgs& rArgs)
                 sal_Int32 indexUtf16 = nCharPos;
                 sal_UCS4 aChar = rArgs.mrStr.iterateCodePoints(&indexUtf16, 0);
 
-                bool bDiacritic = false;
-                if (hb_ot_layout_has_glyph_classes(pHbFace))
-                {
-                    // the font has GDEF table
-                    if (pHbPositions[i].x_advance == 0)
-                        bDiacritic = hb_ot_layout_get_glyph_class(pHbFace, nGlyphIndex) == HB_OT_LAYOUT_GLYPH_CLASS_MARK;
-                }
-                else
-                {
 #if HB_VERSION_ATLEAST(0, 9, 42)
-                    if (u_getIntPropertyValue(aChar, UCHAR_GENERAL_CATEGORY) == U_NON_SPACING_MARK)
-                        bDiacritic = true;
-#else
-                    // the font lacks GDEF table
-                    if (pHbPositions[i].x_advance == 0)
-                        bDiacritic = true;
-#endif
-                }
-
-                if (bDiacritic)
+                if (u_getIntPropertyValue(aChar, UCHAR_GENERAL_CATEGORY) == U_NON_SPACING_MARK)
                     nGlyphFlags |= GlyphItem::IS_DIACRITIC;
+#endif
 
-                if ((aSubRun.maScript == HB_SCRIPT_ARABIC) || (aSubRun.maScript == HB_SCRIPT_SYRIAC))
+                if ((aSubRun.maScript == HB_SCRIPT_ARABIC ||
+                     aSubRun.maScript == HB_SCRIPT_SYRIAC) &&
+                    HB_DIRECTION_IS_BACKWARD(aSubRun.maDirection) &&
+                    !u_isUWhiteSpace(aChar))
                 {
                     nGlyphFlags |= GlyphItem::ALLOW_KASHIDA;
                     rArgs.mnFlags |= SalLayoutFlags::KashidaJustification;
@@ -664,11 +650,6 @@ bool CommonSalLayout::LayoutText(ImplLayoutArgs& rArgs)
 
     hb_buffer_destroy(pHbBuffer);
 
-    // sort glyphs in visual order
-    // and then in logical order (e.g. diacritics after cluster start)
-    // XXX: why?
-    SortGlyphItems();
-
     return true;
 }
 
@@ -753,14 +734,10 @@ void CommonSalLayout::ApplyDXArray(ImplLayoutArgs& rArgs)
         int nCharPos = m_GlyphItems[i].mnCharPos - mnMinCharPos;
         DeviceCoordinate nDiff = pNewCharWidths[nCharPos] - pOldCharWidths[nCharPos];
 
-        // nDiff > 1 to ignore rounding errors.
-        if (bKashidaJustify && m_GlyphItems[i].AllowKashida() && nDiff > 1)
-            pKashidas[i] = nDiff;
-
-        // Adjust the width of the first glyph belonging to current character.
+        // Adjust the width of the first glyph in the cluster.
         m_GlyphItems[i].mnNewWidth += nDiff;
 
-        // Apply the X position of all glyphs belonging to current character.
+        // Apply the X position of all glyphs in the cluster.
         size_t j = i;
         while (j < m_GlyphItems.size())
         {
@@ -773,10 +750,31 @@ void CommonSalLayout::ApplyDXArray(ImplLayoutArgs& rArgs)
             ++j;
         }
 
+        // Id this glyph is Kashida-justifiable, then mark this as a Kashida
+        // position. Since this must be a RTL glyph, we mark the last glyph in
+        // the cluster not the fisrt as this would be the base glyph.
+        // nDiff > 1 to ignore rounding errors.
+        if (bKashidaJustify && m_GlyphItems[i].AllowKashida() && nDiff > 1)
+        {
+            pKashidas[j - 1] = nDiff;
+            // Move any non-spacing marks attached to this cluster as well.
+            // Looping backward because this is RTL glyph.
+            if (i > 0)
+            {
+                auto pGlyph = m_GlyphItems.begin() + i - 1;
+                while (pGlyph != m_GlyphItems.begin() && pGlyph->IsDiacritic())
+                {
+                    pGlyph->maLinearPos.X() += nDiff;
+                    --pGlyph;
+                }
+            }
+        }
+
+
         // Increment the delta, the loop above makes sure we do so only once
-        // for every character not for every glyph (otherwise we would apply it
-        // multiple times for each glyphs belonging to the same character which
-        // is wrong since DX adjustments are character based).
+        // for every character (cluster) not for every glyph (otherwise we
+        // would apply it multiple times for each glyphs belonging to the same
+        // character which is wrong since DX adjustments are character based).
         nDelta += nDiff;
         i = j;
     }
@@ -789,16 +787,6 @@ void CommonSalLayout::ApplyDXArray(ImplLayoutArgs& rArgs)
         {
             auto pGlyphIter = m_GlyphItems.begin() + nInserted + pKashida.first;
 
-            // Don’t insert Kashida after LTR glyphs.
-            if (!pGlyphIter->IsRTLGlyph())
-                continue;
-
-            // Don’t insert Kashida after space.
-            sal_Int32 indexUtf16 = pGlyphIter->mnCharPos;
-            sal_UCS4 aChar = rArgs.mrStr.iterateCodePoints(&indexUtf16, 0);
-            if (u_isUWhiteSpace(aChar))
-                continue;
-
             // The total Kashida width.
             DeviceCoordinate nTotalWidth = pKashida.second;
 
diff --git a/vcl/source/gdi/sallayout.cxx b/vcl/source/gdi/sallayout.cxx
index ebae19b..9c10cde 100644
--- a/vcl/source/gdi/sallayout.cxx
+++ b/vcl/source/gdi/sallayout.cxx
@@ -1129,41 +1129,6 @@ void GenericSalLayout::Simplify( bool bIsBase )
     m_GlyphItems.erase(m_GlyphItems.begin() + j, m_GlyphItems.end());
 }
 
-// make sure GlyphItems are sorted left to right
-void GenericSalLayout::SortGlyphItems()
-{
-    // move cluster components behind their cluster start (especially for RTL)
-    // using insertion sort because the glyph items are "almost sorted"
-
-    for( std::vector<GlyphItem>::iterator pGlyphIter = m_GlyphItems.begin(), pGlyphIterEnd = m_GlyphItems.end(); pGlyphIter != pGlyphIterEnd; ++pGlyphIter )
-    {
-        // find a cluster starting with a diacritic
-        if( !pGlyphIter->IsDiacritic() )
-            continue;
-        if( !pGlyphIter->IsClusterStart() )
-            continue;
-        for( std::vector<GlyphItem>::iterator pBaseGlyph = pGlyphIter; ++pBaseGlyph != pGlyphIterEnd; )
-        {
-            // find the base glyph matching to the misplaced diacritic
-            if( pBaseGlyph->IsClusterStart() )
-                break;
-            if( pBaseGlyph->IsDiacritic() )
-                continue;
-
-            // found the matching base glyph
-            // => this base glyph becomes the new cluster start
-            iter_swap(pGlyphIter, pBaseGlyph);
-
-            // update glyph flags of swapped glyphitems
-            pGlyphIter->mnFlags &= ~GlyphItem::IS_IN_CLUSTER;
-            pBaseGlyph->mnFlags |= GlyphItem::IS_IN_CLUSTER;
-            // prepare for checking next cluster
-            pGlyphIter = pBaseGlyph;
-            break;
-        }
-    }
-}
-
 MultiSalLayout::MultiSalLayout( SalLayout& rBaseLayout )
 :   SalLayout()
 ,   mnLevel( 1 )


More information about the Libreoffice-commits mailing list