include/vcl/outdev.hxx          |    4 +++
 vcl/source/gdi/impglyphitem.cxx |   27 ++++++++++++++++++--
 vcl/source/outdev/text.cxx      |   53 +++++++++++++++++++++++-----------------
 3 files changed, 59 insertions(+), 25 deletions(-)

New commits:
commit 3a407fc49490a348a8147a59dae242aa21708c31
Author:     Luboš Luňák <[email protected]>
AuthorDate: Wed Apr 27 12:27:52 2022 +0200
Commit:     Luboš Luňák <[email protected]>
CommitDate: Wed Apr 27 22:45:52 2022 +0200

    make SalLayoutFlags match after makeGlyphsSubset()
    
    SalLayoutFlags::BiDiStrong would be set by ImplLayout() if the entire
    subset had no RTL, but the entire string may not be that, so when
    creating a subset make sure to also set this flag. Similarly
    SalLayoutFlags::KashidaJustification should be set only if any
    glyph in the range has GlyphItemFlags::ALLOW_KASHIDA.
    
    Change-Id: I0aa2526f2fdd0c6a6b905ad0cb4040ee556529a8
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/133502
    Tested-by: Jenkins
    Reviewed-by: Luboš Luňák <[email protected]>

diff --git a/include/vcl/outdev.hxx b/include/vcl/outdev.hxx
index 7dacb68d55ad..bf4985622fad 100644
--- a/include/vcl/outdev.hxx
+++ b/include/vcl/outdev.hxx
@@ -1078,6 +1078,10 @@ public:
                                               const SalLayoutGlyphs* pGlyphs = 
nullptr) const;
     static std::shared_ptr<const vcl::text::TextLayoutCache> 
CreateTextLayoutCache(OUString const&);
 
+    SAL_DLLPRIVATE SalLayoutFlags GetBiDiLayoutFlags( std::u16string_view rStr,
+                                                      const sal_Int32 
nMinIndex,
+                                                      const sal_Int32 
nEndIndex ) const;
+
 protected:
     SAL_DLLPRIVATE void         ImplInitTextLineSize();
     SAL_DLLPRIVATE void         ImplInitAboveTextLineSize();
diff --git a/vcl/source/gdi/impglyphitem.cxx b/vcl/source/gdi/impglyphitem.cxx
index 83c044ce176c..5c4acbc6859c 100644
--- a/vcl/source/gdi/impglyphitem.cxx
+++ b/vcl/source/gdi/impglyphitem.cxx
@@ -164,8 +164,9 @@ SalLayoutGlyphsCache* SalLayoutGlyphsCache::self()
     return cache.get();
 }
 
-static SalLayoutGlyphs makeGlyphsSubset(const SalLayoutGlyphs& source, 
sal_Int32 index,
-                                        sal_Int32 len)
+static SalLayoutGlyphs makeGlyphsSubset(const SalLayoutGlyphs& source,
+                                        const OutputDevice* outputDevice, 
std::u16string_view text,
+                                        sal_Int32 index, sal_Int32 len)
 {
     SalLayoutGlyphs ret;
     for (int level = 0;; ++level)
@@ -177,6 +178,25 @@ static SalLayoutGlyphs makeGlyphsSubset(const 
SalLayoutGlyphs& source, sal_Int32
         // If the glyphs range cannot be cloned, bail out.
         if (cloned == nullptr)
             return SalLayoutGlyphs();
+        // If the entire string is mixed LTR/RTL but the subset is only LTR,
+        // then make sure the flags match that, otherwise checkGlyphsEqual()
+        // would assert on flags being different.
+        cloned->SetFlags(cloned->GetFlags()
+                         | outputDevice->GetBiDiLayoutFlags(text, index, index 
+ len));
+        // SalLayoutFlags::KashidaJustification is set only if any glyph
+        // in the range has GlyphItemFlags::ALLOW_KASHIDA (otherwise unset it).
+        bool hasKashida = false;
+        for (const GlyphItem& item : *cloned)
+        {
+            if (item.AllowKashida())
+            {
+                assert(cloned->GetFlags() & 
SalLayoutFlags::KashidaJustification);
+                hasKashida = true;
+                break;
+            }
+        }
+        if (!hasKashida)
+            cloned->SetFlags(cloned->GetFlags() & 
~SalLayoutFlags::KashidaJustification);
         ret.AppendImpl(cloned);
     }
     return ret;
@@ -236,7 +256,8 @@ SalLayoutGlyphsCache::GetLayoutGlyphs(VclPtr<const 
OutputDevice> outputDevice, c
         GlyphsCache::const_iterator itWhole = mCachedGlyphs.find(keyWhole);
         if (itWhole != mCachedGlyphs.end() && itWhole->second.IsValid())
         {
-            mLastTemporaryGlyphs = makeGlyphsSubset(itWhole->second, nIndex, 
nLen);
+            mLastTemporaryGlyphs
+                = makeGlyphsSubset(itWhole->second, outputDevice, text, 
nIndex, nLen);
             if (mLastTemporaryGlyphs.IsValid())
             {
                 mLastTemporaryKey = std::move(key);
diff --git a/vcl/source/outdev/text.cxx b/vcl/source/outdev/text.cxx
index 840341502beb..7d3662d0604d 100644
--- a/vcl/source/outdev/text.cxx
+++ b/vcl/source/outdev/text.cxx
@@ -1170,28 +1170,7 @@ vcl::text::ImplLayoutArgs 
OutputDevice::ImplPrepareLayoutArgs( OUString& rStr,
     if( nEndIndex < nMinIndex )
         nEndIndex = nMinIndex;
 
-    if( mnTextLayoutMode & vcl::text::ComplexTextLayoutFlags::BiDiRtl )
-        nLayoutFlags |= SalLayoutFlags::BiDiRtl;
-    if( mnTextLayoutMode & vcl::text::ComplexTextLayoutFlags::BiDiStrong )
-        nLayoutFlags |= SalLayoutFlags::BiDiStrong;
-    else if( !(mnTextLayoutMode & vcl::text::ComplexTextLayoutFlags::BiDiRtl) )
-    {
-        // Disable Bidi if no RTL hint and only known LTR codes used.
-        bool bAllLtr = true;
-        for (sal_Int32 i = nMinIndex; i < nEndIndex; i++)
-        {
-            // [0x0000, 0x052F] are Latin, Greek and Cyrillic.
-            // [0x0370, 0x03FF] has a few holes as if Unicode 10.0.0, but
-            //                  hopefully no RTL character will be encoded 
there.
-            if (rStr[i] > 0x052F)
-            {
-                bAllLtr = false;
-                break;
-            }
-        }
-        if (bAllLtr)
-            nLayoutFlags |= SalLayoutFlags::BiDiStrong;
-    }
+    nLayoutFlags |= GetBiDiLayoutFlags( rStr, nMinIndex, nEndIndex );
 
     if( !maFont.IsKerning() )
         nLayoutFlags |= SalLayoutFlags::DisableKerning;
@@ -1251,6 +1230,36 @@ vcl::text::ImplLayoutArgs 
OutputDevice::ImplPrepareLayoutArgs( OUString& rStr,
     return aLayoutArgs;
 }
 
+SalLayoutFlags OutputDevice::GetBiDiLayoutFlags( std::u16string_view rStr,
+                                                 const sal_Int32 nMinIndex,
+                                                 const sal_Int32 nEndIndex ) 
const
+{
+    SalLayoutFlags nLayoutFlags = SalLayoutFlags::NONE;
+    if( mnTextLayoutMode & vcl::text::ComplexTextLayoutFlags::BiDiRtl )
+        nLayoutFlags |= SalLayoutFlags::BiDiRtl;
+    if( mnTextLayoutMode & vcl::text::ComplexTextLayoutFlags::BiDiStrong )
+        nLayoutFlags |= SalLayoutFlags::BiDiStrong;
+    else if( !(mnTextLayoutMode & vcl::text::ComplexTextLayoutFlags::BiDiRtl) )
+    {
+        // Disable Bidi if no RTL hint and only known LTR codes used.
+        bool bAllLtr = true;
+        for (sal_Int32 i = nMinIndex; i < nEndIndex; i++)
+        {
+            // [0x0000, 0x052F] are Latin, Greek and Cyrillic.
+            // [0x0370, 0x03FF] has a few holes as if Unicode 10.0.0, but
+            //                  hopefully no RTL character will be encoded 
there.
+            if (rStr[i] > 0x052F)
+            {
+                bAllLtr = false;
+                break;
+            }
+        }
+        if (bAllLtr)
+            nLayoutFlags |= SalLayoutFlags::BiDiStrong;
+    }
+    return nLayoutFlags;
+}
+
 static OutputDevice::FontMappingUseData* fontMappingUseData = nullptr;
 
 static inline bool IsTrackingFontMappingUse()

Reply via email to