[Libreoffice-commits] core.git: Branch 'feature/commonsallayout' - 13 commits - config_host.mk.in configure.ac external/harfbuzz RepositoryExternal.mk vcl/CppunitTest_vcl_wmf_test.mk vcl/inc vcl/Library_vcl.mk vcl/source

Khaled Hosny khaledhosny at eglug.org
Sun Oct 9 23:02:18 UTC 2016


Rebased ref, commits from common ancestor:
commit c74ddf0d07c34dc5b20853be752508bce7a67578
Author: Khaled Hosny <khaledhosny at eglug.org>
Date:   Mon Oct 10 00:54:00 2016 +0200

    Validate Kashida positions in CommonSalLayout
    
    Currently checks only for ligatures, but that is a big improvement over
    al code that didn’t do any validation except on Windows.
    
    Change-Id: I035248f4ccc23134ea27b40c2dd6197130749f14

diff --git a/vcl/inc/CommonSalLayout.hxx b/vcl/inc/CommonSalLayout.hxx
index e9116ba..8ee1255 100644
--- a/vcl/inc/CommonSalLayout.hxx
+++ b/vcl/inc/CommonSalLayout.hxx
@@ -68,4 +68,6 @@ public:
 
     virtual bool            GetCharWidths(DeviceCoordinate* pCharWidths) const override;
     virtual void            ApplyDXArray(ImplLayoutArgs&) override;
+
+    virtual bool            IsKashidaPosValid(int nCharPos) const override;
 };
diff --git a/vcl/source/gdi/CommonSalLayout.cxx b/vcl/source/gdi/CommonSalLayout.cxx
index e338261..0bbab99 100644
--- a/vcl/source/gdi/CommonSalLayout.cxx
+++ b/vcl/source/gdi/CommonSalLayout.cxx
@@ -612,3 +612,30 @@ void CommonSalLayout::ApplyDXArray(ImplLayoutArgs& rArgs)
         }
     }
 }
+
+bool CommonSalLayout::IsKashidaPosValid(int nCharPos) const
+{
+    for (auto pIter = m_GlyphItems.begin(); pIter != m_GlyphItems.end(); ++pIter)
+    {
+        if (pIter->mnCharPos == nCharPos)
+        {
+            // Search backwards for previous glyph belonging to a different
+            // character. We are looking backwards because we are dealing with
+            // RTL glyphs, which will be in visual order.
+            for (auto pPrev = pIter - 1; pPrev != m_GlyphItems.begin(); --pPrev)
+            {
+                if (pPrev->mnCharPos != nCharPos)
+                {
+                    // Check if the found glyph belongs to the next character,
+                    // otherwise the current glyph will be a ligature which is
+                    // invalid kashida position.
+                    if (pPrev->mnCharPos == (nCharPos + 1))
+                        return true;
+                    break;
+                }
+            }
+        }
+    }
+
+    return false;
+}
commit 7b36271ca9095c60c01a3810df2e42334e02a8de
Author: Khaled Hosny <khaledhosny at eglug.org>
Date:   Sun Oct 9 23:23:45 2016 +0200

    Re-enable Kashida insertion in CommonSalLayout
    
    We now do Kashida insertion in ApplyDXArray(), no need for a separate
    step. This simplifies the code greatly (old code is in
    GenericSalLayout::KashidaJustify()).
    
    Change-Id: Ie31c8969e26f1f293820f1e90f963a5ba1fc9eb1

diff --git a/vcl/source/gdi/CommonSalLayout.cxx b/vcl/source/gdi/CommonSalLayout.cxx
index 433fbee..e338261 100644
--- a/vcl/source/gdi/CommonSalLayout.cxx
+++ b/vcl/source/gdi/CommonSalLayout.cxx
@@ -283,27 +283,18 @@ void CommonSalLayout::SetNeedFallback(ImplLayoutArgs& rArgs, sal_Int32 nCharPos,
 
 void CommonSalLayout::AdjustLayout(ImplLayoutArgs& rArgs)
 {
-    GenericSalLayout::AdjustLayout(rArgs);
+    SalLayout::AdjustLayout(rArgs);
+
+    if (rArgs.mpDXArray)
+        ApplyDXArray(rArgs);
+    else if (rArgs.mnLayoutWidth)
+        Justify(rArgs.mnLayoutWidth);
 
     // apply asian kerning if the glyphs are not already formatted
     if( (rArgs.mnFlags & SalLayoutFlags::KerningAsian)
     && !(rArgs.mnFlags & SalLayoutFlags::Vertical) )
         if( (rArgs.mpDXArray != nullptr) || (rArgs.mnLayoutWidth != 0) )
             ApplyAsianKerning(rArgs.mrStr);
-
-    if((rArgs.mnFlags & SalLayoutFlags::KashidaJustification) && rArgs.mpDXArray)
-    {
-        hb_codepoint_t nKashidaCodePoint = 0x0640;
-        hb_codepoint_t nKashidaGlyphIndex;
-
-        if(hb_font_get_glyph(mpHbFont, nKashidaCodePoint, 0, &nKashidaGlyphIndex))
-        {
-            if(nKashidaGlyphIndex)
-            {
-                KashidaJustify(nKashidaGlyphIndex, hb_font_get_glyph_h_advance(mpHbFont, nKashidaGlyphIndex) >> 6);
-            }
-        }
-    }
 }
 
 void CommonSalLayout::DrawText( SalGraphics& rSalGraphics ) const
@@ -546,6 +537,16 @@ void CommonSalLayout::ApplyDXArray(ImplLayoutArgs& rArgs)
             pNewCharWidths[i] = rArgs.mpDXArray[i] - rArgs.mpDXArray[i - 1];
     }
 
+    DeviceCoordinate nKashidaWidth = 0;
+    hb_codepoint_t nKashidaIndex;
+    if (rArgs.mnFlags & SalLayoutFlags::KashidaJustification)
+    {
+        if (hb_font_get_glyph(mpHbFont, 0x0640, 0, &nKashidaIndex))
+            nKashidaWidth = hb_font_get_glyph_h_advance(mpHbFont, nKashidaIndex) / 64;
+    }
+
+    std::map<size_t, DeviceCoordinate> pKashidas;
+
     DeviceCoordinate nDelta = 0;
     size_t i = 0;
     while (i < m_GlyphItems.size())
@@ -553,16 +554,61 @@ void CommonSalLayout::ApplyDXArray(ImplLayoutArgs& rArgs)
         int nCharPos = m_GlyphItems[i].mnCharPos - mnMinCharPos;
         DeviceCoordinate nDiff = pNewCharWidths[nCharPos] - pOldCharWidths[nCharPos];
 
-        m_GlyphItems[i].maLinearPos.X() += nDelta;
+        if (nKashidaWidth && nDiff)
+            pKashidas[i] = nDiff;
+
         size_t j = i;
-        while (++j < m_GlyphItems.size())
+        while (j < m_GlyphItems.size())
         {
             if (m_GlyphItems[j].mnCharPos != m_GlyphItems[i].mnCharPos)
                 break;
             m_GlyphItems[j].maLinearPos.X() += nDelta;
+            // For RTL, put all justification space to the left of the glyph.
+            if (m_GlyphItems[i].IsRTLGlyph())
+                m_GlyphItems[j].maLinearPos.X() += nDiff;
+            ++j;
         }
 
         nDelta += nDiff;
         i = j;
     }
+
+    if (!pKashidas.empty())
+    {
+        size_t nInserted = 0;
+        for (auto const& pKashida : pKashidas)
+        {
+            auto pGlyphIter = m_GlyphItems.begin() + nInserted + pKashida.first;
+
+            if (!pGlyphIter->IsRTLGlyph())
+                continue;
+
+            sal_Int32 indexUtf16 = pGlyphIter->mnCharPos;
+            sal_UCS4 aChar = rArgs.mrStr.iterateCodePoints(&indexUtf16, 0);
+            static hb_unicode_funcs_t* pHbUnicodeFuncs = getUnicodeFuncs();
+            if (hb_unicode_general_category (pHbUnicodeFuncs, aChar) == HB_UNICODE_GENERAL_CATEGORY_SPACE_SEPARATOR)
+                continue;
+
+            DeviceCoordinate nGapWidth = pKashida.second;
+            int nKashidaCount = ceil(nGapWidth / nKashidaWidth);
+            DeviceCoordinate nInsertedKashidaWidth;
+            if (nGapWidth < nKashidaWidth)
+                nInsertedKashidaWidth = nGapWidth;
+            else
+                nInsertedKashidaWidth = nGapWidth / nKashidaCount;
+
+            Point aPos(pGlyphIter->maLinearPos.X() - nGapWidth, 0);
+            int nCharPos = pGlyphIter->mnCharPos;
+            int nFlags = GlyphItem::IS_IN_CLUSTER | GlyphItem::IS_RTL_GLYPH;
+            while (nKashidaCount)
+            {
+                GlyphItem aKashida(nCharPos, nKashidaIndex, aPos, nFlags, nInsertedKashidaWidth);
+                pGlyphIter = m_GlyphItems.insert(pGlyphIter, aKashida);
+                aPos.X() += nInsertedKashidaWidth;
+                ++pGlyphIter;
+                ++nInserted;
+                --nKashidaCount;
+            }
+        }
+    }
 }
commit 13d388b2468572c67d9d8b96536b07eadc28e70c
Author: Khaled Hosny <khaledhosny at eglug.org>
Date:   Sun Oct 9 19:08:18 2016 +0200

    Revert "Use HarfBuzz shape plan for a bit more control"
    
    This reverts commit 8b32ead0b988b142cd9878f126d985d946fd4ccc.

diff --git a/vcl/source/gdi/CommonSalLayout.cxx b/vcl/source/gdi/CommonSalLayout.cxx
index bd1b029..433fbee 100644
--- a/vcl/source/gdi/CommonSalLayout.cxx
+++ b/vcl/source/gdi/CommonSalLayout.cxx
@@ -314,7 +314,6 @@ void CommonSalLayout::DrawText( SalGraphics& rSalGraphics ) const
 
 bool CommonSalLayout::LayoutText(ImplLayoutArgs& rArgs)
 {
-    hb_face_t* pHbFace = hb_font_get_face(mpHbFont);
     hb_script_t aHbScript = HB_SCRIPT_INVALID;
 
     int nGlyphCapacity = 2 * (rArgs.mnEndCharPos - rArgs.mnMinCharPos);
@@ -416,13 +415,7 @@ bool CommonSalLayout::LayoutText(ImplLayoutArgs& rArgs)
 #if HB_VERSION_ATLEAST(0, 9, 42)
             hb_buffer_set_cluster_level(pHbBuffer, HB_BUFFER_CLUSTER_LEVEL_MONOTONE_CHARACTERS);
 #endif
-            const char *pHbShapers[5] = { "coretext_aat", "graphite2", "ot", "fallback", nullptr };
-            hb_segment_properties_t aHbProps;
-            hb_buffer_get_segment_properties(pHbBuffer, &aHbProps);
-            hb_shape_plan_t *pHbPlan = hb_shape_plan_create_cached(pHbFace, &aHbProps, nullptr, 0, pHbShapers);
-            assert(hb_shape_plan_execute(pHbPlan, mpHbFont, pHbBuffer, nullptr, 0));
-            hb_buffer_set_content_type(pHbBuffer, HB_BUFFER_CONTENT_TYPE_GLYPHS);
-            SAL_INFO("vcl.harfbuzz", hb_shape_plan_get_shaper(pHbPlan) << " shaper used for " << rArgs);
+            hb_shape(mpHbFont, pHbBuffer, nullptr, 0);
 
             int nRunGlyphCount = hb_buffer_get_length(pHbBuffer);
             hb_glyph_info_t *pHbGlyphInfos = hb_buffer_get_glyph_infos(pHbBuffer, nullptr);
@@ -455,6 +448,7 @@ bool CommonSalLayout::LayoutText(ImplLayoutArgs& rArgs)
                     nGlyphFlags |= GlyphItem::IS_IN_CLUSTER;
 
                 bool bDiacritic = false;
+                hb_face_t* pHbFace = hb_font_get_face(mpHbFont);
                 if (hb_ot_layout_has_glyph_classes(pHbFace))
                 {
                     // the font has GDEF table
commit 793771e9c0bc6fcd34633375f0bd920c0f20ad22
Author: Khaled Hosny <khaledhosny at eglug.org>
Date:   Thu Oct 6 04:15:41 2016 +0200

    Use HarfBuzz shape plan for a bit more control
    
    This way we control exactly what shapers we use in what order, and as an
    extra we can now tell which shaper HarfBuzz ends up using.
    
    Change-Id: Idd303b2a557e16ac86ada0c2006d3e2a052ac489

diff --git a/vcl/source/gdi/CommonSalLayout.cxx b/vcl/source/gdi/CommonSalLayout.cxx
index 433fbee..bd1b029 100644
--- a/vcl/source/gdi/CommonSalLayout.cxx
+++ b/vcl/source/gdi/CommonSalLayout.cxx
@@ -314,6 +314,7 @@ void CommonSalLayout::DrawText( SalGraphics& rSalGraphics ) const
 
 bool CommonSalLayout::LayoutText(ImplLayoutArgs& rArgs)
 {
+    hb_face_t* pHbFace = hb_font_get_face(mpHbFont);
     hb_script_t aHbScript = HB_SCRIPT_INVALID;
 
     int nGlyphCapacity = 2 * (rArgs.mnEndCharPos - rArgs.mnMinCharPos);
@@ -415,7 +416,13 @@ bool CommonSalLayout::LayoutText(ImplLayoutArgs& rArgs)
 #if HB_VERSION_ATLEAST(0, 9, 42)
             hb_buffer_set_cluster_level(pHbBuffer, HB_BUFFER_CLUSTER_LEVEL_MONOTONE_CHARACTERS);
 #endif
-            hb_shape(mpHbFont, pHbBuffer, nullptr, 0);
+            const char *pHbShapers[5] = { "coretext_aat", "graphite2", "ot", "fallback", nullptr };
+            hb_segment_properties_t aHbProps;
+            hb_buffer_get_segment_properties(pHbBuffer, &aHbProps);
+            hb_shape_plan_t *pHbPlan = hb_shape_plan_create_cached(pHbFace, &aHbProps, nullptr, 0, pHbShapers);
+            assert(hb_shape_plan_execute(pHbPlan, mpHbFont, pHbBuffer, nullptr, 0));
+            hb_buffer_set_content_type(pHbBuffer, HB_BUFFER_CONTENT_TYPE_GLYPHS);
+            SAL_INFO("vcl.harfbuzz", hb_shape_plan_get_shaper(pHbPlan) << " shaper used for " << rArgs);
 
             int nRunGlyphCount = hb_buffer_get_length(pHbBuffer);
             hb_glyph_info_t *pHbGlyphInfos = hb_buffer_get_glyph_infos(pHbBuffer, nullptr);
@@ -448,7 +455,6 @@ bool CommonSalLayout::LayoutText(ImplLayoutArgs& rArgs)
                     nGlyphFlags |= GlyphItem::IS_IN_CLUSTER;
 
                 bool bDiacritic = false;
-                hb_face_t* pHbFace = hb_font_get_face(mpHbFont);
                 if (hb_ot_layout_has_glyph_classes(pHbFace))
                 {
                     // the font has GDEF table
commit 3298e627e15a9773829623f524c65e2709edf3b1
Author: Khaled Hosny <khaledhosny at eglug.org>
Date:   Mon Sep 26 19:09:52 2016 +0200

    First try on vertical text in CommonSalLayout
    
    Does not work quite right yet.
    
    Change-Id: I52a71c9c21ad75c7cb9c8574e5e7e3b7c1c0c0c3

diff --git a/vcl/source/gdi/CommonSalLayout.cxx b/vcl/source/gdi/CommonSalLayout.cxx
index 20310b6..433fbee 100644
--- a/vcl/source/gdi/CommonSalLayout.cxx
+++ b/vcl/source/gdi/CommonSalLayout.cxx
@@ -381,6 +381,16 @@ bool CommonSalLayout::LayoutText(ImplLayoutArgs& rArgs)
             LanguageTag &rTag = rArgs.maLanguageTag;
             OString sLanguage = OUStringToOString(rTag.getBcp47(), RTL_TEXTENCODING_ASCII_US);
 
+            bool bVertical = false;
+            if ((rArgs.mnFlags & SalLayoutFlags::Vertical) &&
+                (aHbScript == HB_SCRIPT_HAN ||
+                 aHbScript == HB_SCRIPT_HANGUL ||
+                 aHbScript == HB_SCRIPT_HIRAGANA ||
+                 aHbScript == HB_SCRIPT_KATAKANA))
+            {
+                bVertical = true;
+            }
+
             int nHbFlags = HB_BUFFER_FLAGS_DEFAULT;
             if (nMinRunPos == 0)
                 nHbFlags |= HB_BUFFER_FLAG_BOT; /* Beginning-of-text */
@@ -392,7 +402,10 @@ bool CommonSalLayout::LayoutText(ImplLayoutArgs& rArgs)
 #if !HB_VERSION_ATLEAST(1, 1, 0)
             hb_buffer_set_unicode_funcs(pHbBuffer, pHbUnicodeFuncs);
 #endif
-            hb_buffer_set_direction(pHbBuffer, bRightToLeft ? HB_DIRECTION_RTL: HB_DIRECTION_LTR);
+            if (SAL_UNLIKELY(bVertical))
+              hb_buffer_set_direction(pHbBuffer, HB_DIRECTION_TTB);
+            else
+              hb_buffer_set_direction(pHbBuffer, bRightToLeft ? HB_DIRECTION_RTL: HB_DIRECTION_LTR);
             hb_buffer_set_script(pHbBuffer, aHbScript);
             hb_buffer_set_language(pHbBuffer, hb_language_from_string(sLanguage.getStr(), -1));
             hb_buffer_set_flags(pHbBuffer, (hb_buffer_flags_t) nHbFlags);
@@ -457,17 +470,31 @@ bool CommonSalLayout::LayoutText(ImplLayoutArgs& rArgs)
                 if (bDiacritic)
                     nGlyphFlags |= GlyphItem::IS_DIACRITIC;
 
-                int32_t nXOffset =  pHbPositions[i].x_offset >> 6;
-                int32_t nYOffset =  pHbPositions[i].y_offset >> 6;
-                int32_t nXAdvance = pHbPositions[i].x_advance >> 6;
-                int32_t nYAdvance = pHbPositions[i].y_advance >> 6;
+                int32_t nXOffset;
+                int32_t nYOffset;
+                int32_t nXAdvance;
+                Point aNewPos;
+
+                if (SAL_UNLIKELY(bVertical))
+                {
+                    nXOffset =  pHbPositions[i].y_offset >> 6;
+                    nYOffset =  pHbPositions[i].x_offset >> 6;
+                    nXAdvance = pHbPositions[i].y_advance >> 6;
+                    nGlyphIndex |= GF_ROTL;
+                    aNewPos = Point(-(aCurrPos.X() + nXOffset), aCurrPos.Y() + nYOffset);
+                }
+                else
+                {
+                    nXOffset =  pHbPositions[i].x_offset >> 6;
+                    nYOffset =  pHbPositions[i].y_offset >> 6;
+                    nXAdvance = pHbPositions[i].x_advance >> 6;
+                    aNewPos = Point(aCurrPos.X() + nXOffset, -(aCurrPos.Y() + nYOffset));
+                }
 
-                Point aNewPos = Point(aCurrPos.X() + nXOffset, -(aCurrPos.Y() + nYOffset));
                 const GlyphItem aGI(nCharPos, nGlyphIndex, aNewPos, nGlyphFlags, nXAdvance, nXOffset);
                 AppendGlyph(aGI);
 
                 aCurrPos.X() += nXAdvance;
-                aCurrPos.Y() += nYAdvance;
             }
 
             hb_buffer_destroy(pHbBuffer);
commit 5447455d02b749bd217dac06a9c690fb7b0115bf
Author: Khaled Hosny <khaledhosny at eglug.org>
Date:   Sat Sep 24 23:13:47 2016 +0200

    Use range loop
    
    Change-Id: I5ce49e57ed57378b4b9e16c8bb020048644252a9

diff --git a/vcl/source/gdi/CommonSalLayout.cxx b/vcl/source/gdi/CommonSalLayout.cxx
index 05b136d..20310b6 100644
--- a/vcl/source/gdi/CommonSalLayout.cxx
+++ b/vcl/source/gdi/CommonSalLayout.cxx
@@ -371,12 +371,12 @@ bool CommonSalLayout::LayoutText(ImplLayoutArgs& rArgs)
         if (bRightToLeft)
             std::reverse(aScriptSubRuns.begin(), aScriptSubRuns.end());
 
-        for (HbScriptRuns::iterator it = aScriptSubRuns.begin(); it != aScriptSubRuns.end(); ++it)
+        for (const auto& aScriptRun : aScriptSubRuns)
         {
-            int nMinRunPos = it->mnMin;
-            int nEndRunPos = it->mnEnd;
+            int nMinRunPos = aScriptRun.mnMin;
+            int nEndRunPos = aScriptRun.mnEnd;
             int nRunLen = nEndRunPos - nMinRunPos;
-            aHbScript = it->maScript;
+            aHbScript = aScriptRun.maScript;
             // hb_language_from_string() accept ISO639-3 language tag except for Chinese.
             LanguageTag &rTag = rArgs.maLanguageTag;
             OString sLanguage = OUStringToOString(rTag.getBcp47(), RTL_TEXTENCODING_ASCII_US);
commit eec9fb46f330e402a026c71e693823f3a8eb951e
Author: Khaled Hosny <khaledhosny at eglug.org>
Date:   Sat Sep 24 23:04:39 2016 +0200

    Use const reference
    
    Change-Id: I0f632f3a8b480f785608aa081add1b1d2fefd312

diff --git a/vcl/inc/CommonSalLayout.hxx b/vcl/inc/CommonSalLayout.hxx
index 89214d4..e9116ba 100644
--- a/vcl/inc/CommonSalLayout.hxx
+++ b/vcl/inc/CommonSalLayout.hxx
@@ -36,7 +36,7 @@
 class CommonSalLayout : public GenericSalLayout
 {
     hb_font_t* mpHbFont;
-    FontSelectPattern maFontSelData;
+    const FontSelectPattern& mrFontSelData;
     css::uno::Reference<css::i18n::XBreakIterator> mxBreak;
 #ifdef _WIN32
     HDC   mhDC;
diff --git a/vcl/source/gdi/CommonSalLayout.cxx b/vcl/source/gdi/CommonSalLayout.cxx
index 7698bab..05b136d 100644
--- a/vcl/source/gdi/CommonSalLayout.cxx
+++ b/vcl/source/gdi/CommonSalLayout.cxx
@@ -129,7 +129,7 @@ static hb_unicode_funcs_t* getUnicodeFuncs()
 CommonSalLayout::CommonSalLayout(WinSalGraphics* WSL, WinFontInstance& rWinFontInstance, const WinFontFace& rWinFontFace)
 :   mhFont((HFONT)GetCurrentObject(WSL->getHDC(), OBJ_FONT)),
     mhDC(WSL->getHDC()),
-    maFontSelData(rWinFontInstance.maFontSelData),
+    mrFontSelData(rWinFontInstance.maFontSelData),
     mpD2DRenderer(nullptr)
 {
     mpHbFont = rWinFontFace.GetHbFont();
@@ -153,7 +153,7 @@ CommonSalLayout::CommonSalLayout(WinSalGraphics* WSL, WinFontInstance& rWinFontI
         hb_face_destroy(pHbFace);
     }
 
-    scaleHbFont(mpHbFont, maFontSelData);
+    scaleHbFont(mpHbFont, mrFontSelData);
 }
 
 void CommonSalLayout::InitFont() const
@@ -163,7 +163,7 @@ void CommonSalLayout::InitFont() const
 
 #elif defined(MACOSX) || defined(IOS)
 CommonSalLayout::CommonSalLayout(const CoreTextStyle& rCoreTextStyle)
-:   maFontSelData(rCoreTextStyle.maFontSelData),
+:   mrFontSelData(rCoreTextStyle.maFontSelData),
     mrCoreTextStyle(rCoreTextStyle)
 {
     mpHbFont = rCoreTextStyle.GetHbFont();
@@ -184,12 +184,12 @@ CommonSalLayout::CommonSalLayout(const CoreTextStyle& rCoreTextStyle)
         hb_face_destroy(pHbFace);
     }
 
-    scaleHbFont(mpHbFont, maFontSelData);
+    scaleHbFont(mpHbFont, mrFontSelData);
 }
 
 #else
 CommonSalLayout::CommonSalLayout(ServerFont& rServerFont)
-:   maFontSelData(rServerFont.GetFontSelData()),
+:   mrFontSelData(rServerFont.GetFontSelData()),
     mrServerFont(rServerFont)
 {
     mpHbFont = rServerFont.GetHbFont();
@@ -203,7 +203,7 @@ CommonSalLayout::CommonSalLayout(ServerFont& rServerFont)
         hb_face_destroy(pHbFace);
     }
 
-    scaleHbFont(mpHbFont, maFontSelData);
+    scaleHbFont(mpHbFont, mrFontSelData);
 }
 #endif
 
commit 44d8b051018dab82648bb65b4de401b8860aab0d
Author: Khaled Hosny <khaledhosny at eglug.org>
Date:   Fri Sep 23 18:34:09 2016 +0200

    Make sure HarfBuzz module depends on Graphite
    
    Change-Id: I9c1cc9c679ceebeb4e5cd898876aaa7b61c18f17

diff --git a/RepositoryExternal.mk b/RepositoryExternal.mk
index 64eeacf..c818136 100644
--- a/RepositoryExternal.mk
+++ b/RepositoryExternal.mk
@@ -1368,6 +1368,8 @@ $(call gb_LinkTarget_add_libs,$(1),$(GRAPHITE_LIBS))
 
 endef
 
+gb_ExternalProject__use_graphite:=
+
 else # !SYSTEM_GRAPHITE
 
 define gb_LinkTarget__use_graphite
@@ -1382,6 +1384,10 @@ $(call gb_LinkTarget_use_static_libraries,$(1),\
 
 endef
 
+define gb_ExternalProject__use_graphite
+$(call gb_ExternalProject_use_external_project,$(1),graphite)
+
+endef
 endif # SYSTEM_GRAPHITE
 
 ifneq ($(SYSTEM_ICU),)
diff --git a/external/harfbuzz/ExternalProject_harfbuzz.mk b/external/harfbuzz/ExternalProject_harfbuzz.mk
index 1be5c6f..57cfc44 100644
--- a/external/harfbuzz/ExternalProject_harfbuzz.mk
+++ b/external/harfbuzz/ExternalProject_harfbuzz.mk
@@ -17,6 +17,7 @@ $(eval $(call gb_ExternalProject_register_targets,harfbuzz,\
 
 $(eval $(call gb_ExternalProject_use_externals,harfbuzz,\
 	icu \
+	graphite \
 ))
 
 $(call gb_ExternalProject_get_state_target,harfbuzz,build) :
commit ad594e7c82aa4cc40f95d4308dcb8bb1f01786eb
Author: Khaled Hosny <khaledhosny at eglug.org>
Date:   Thu Sep 22 07:57:04 2016 -0700

    Build HarfBuzz with Core Text on Mac
    
    To enable support for AAT fonts.
    
    Change-Id: Ifcc7d1672e98f8c067482400b7e45226bed4dbf1

diff --git a/external/harfbuzz/ExternalProject_harfbuzz.mk b/external/harfbuzz/ExternalProject_harfbuzz.mk
index 4412815..1be5c6f 100644
--- a/external/harfbuzz/ExternalProject_harfbuzz.mk
+++ b/external/harfbuzz/ExternalProject_harfbuzz.mk
@@ -36,6 +36,7 @@ $(call gb_ExternalProject_get_state_target,harfbuzz,build) :
 			--with-cairo=no \
 			--with-glib=no \
 			--with-graphite2=yes \
+			$(if $(filter MACOSX,$(OS)),--with-coretext=yes) \
 			$(if $(verbose),--disable-silent-rules,--enable-silent-rules) \
 			$(if $(CROSS_COMPILING),--build=$(BUILD_PLATFORM) --host=$(HOST_PLATFORM)) \
 			$(if $(filter LINUX,$(OS)),CXXFLAGS="$(CXXFLAGS) -fvisibility=hidden") \
commit 6d9bf14e3c0f458dc024f08035675e78f51f30e4
Author: Khaled Hosny <khaledhosny at eglug.org>
Date:   Thu Sep 22 19:48:10 2016 +0200

    Always pass BCP 47 tags to HarfBuzz
    
    This is what it is expecting anyway, no need to special case it for
    Chinese.
    
    Change-Id: I6732412375d19816b599005d78abd796f67599ee

diff --git a/vcl/source/gdi/CommonSalLayout.cxx b/vcl/source/gdi/CommonSalLayout.cxx
index a5e3bf6..7698bab 100644
--- a/vcl/source/gdi/CommonSalLayout.cxx
+++ b/vcl/source/gdi/CommonSalLayout.cxx
@@ -379,7 +379,7 @@ bool CommonSalLayout::LayoutText(ImplLayoutArgs& rArgs)
             aHbScript = it->maScript;
             // hb_language_from_string() accept ISO639-3 language tag except for Chinese.
             LanguageTag &rTag = rArgs.maLanguageTag;
-            OString sLanguage = OUStringToOString( MsLangId::isChinese(rTag.getLanguageType()) ? rTag.getBcp47():rTag.getLanguage() , RTL_TEXTENCODING_UTF8 );
+            OString sLanguage = OUStringToOString(rTag.getBcp47(), RTL_TEXTENCODING_ASCII_US);
 
             int nHbFlags = HB_BUFFER_FLAGS_DEFAULT;
             if (nMinRunPos == 0)
commit 63c7b0eaf502bd184757917212caab1c424f52ce
Author: Khaled Hosny <khaledhosny at eglug.org>
Date:   Thu Sep 22 19:45:23 2016 +0200

    Always build Graphite everywhere
    
    It is no longer an optional feature on any platform. The
    --enable-graphite stuff is kept as it controls the old Graphite
    integration code and it should be removed without.
    
    Change-Id: Ib4d76bba782a1439f02f93411b22d237a1987ea5

diff --git a/RepositoryExternal.mk b/RepositoryExternal.mk
index e0f1337..64eeacf 100644
--- a/RepositoryExternal.mk
+++ b/RepositoryExternal.mk
@@ -1357,8 +1357,6 @@ endef
 
 endif # SYSTEM_FONTCONFIG
 
-ifeq ($(ENABLE_GRAPHITE),TRUE)
-
 ifneq ($(SYSTEM_GRAPHITE),)
 
 define gb_LinkTarget__use_graphite
@@ -1386,12 +1384,6 @@ endef
 
 endif # SYSTEM_GRAPHITE
 
-else # !ENABLE_GRAPHITE
-
-gb_LinkTarget__use_graphite :=
-
-endif # ENABLE_GRAPHITE
-
 ifneq ($(SYSTEM_ICU),)
 
 gb_LinkTarget__use_icu_headers:=
diff --git a/configure.ac b/configure.ac
index d67054b..1419367 100644
--- a/configure.ac
+++ b/configure.ac
@@ -9240,19 +9240,20 @@ AC_SUBST(ICU_LIBS)
 dnl ===================================================================
 dnl Graphite
 dnl ===================================================================
+libo_CHECK_SYSTEM_MODULE([graphite],[GRAPHITE],[graphite2 >= 0.9.3],["-I${WORKDIR}/UnpackedTarball/graphite/include"],["-L${WORKDIR}/LinkTarget/StaticLibrary -lgraphite"])
+if test "$with_system_graphite" = "yes"; then
+    libo_MINGW_CHECK_DLL([libgraphite2])
+fi
+if test "$COM" = "MSC"; then # override the above
+    GRAPHITE_LIBS="${WORKDIR}/LinkTarget/StaticLibrary/graphite.lib"
+fi
 
+# This is the old Graphite support that will eventually be removed
 AC_MSG_CHECKING([whether to enable graphite support])
 if test $_os != Darwin -a $_os != Android -a $_os != iOS -a \( -z "$enable_graphite" -o "$enable_graphite" != no \); then
     AC_MSG_RESULT([yes])
     ENABLE_GRAPHITE="TRUE"
     AC_DEFINE(ENABLE_GRAPHITE)
-    libo_CHECK_SYSTEM_MODULE([graphite],[GRAPHITE],[graphite2 >= 0.9.3],["-I${WORKDIR}/UnpackedTarball/graphite/include"],["-L${WORKDIR}/LinkTarget/StaticLibrary -lgraphite"])
-    if test "$with_system_graphite" = "yes"; then
-        libo_MINGW_CHECK_DLL([libgraphite2])
-    fi
-    if test "$COM" = "MSC"; then # override the above
-        GRAPHITE_LIBS="${WORKDIR}/LinkTarget/StaticLibrary/graphite.lib"
-    fi
 
 else
     AC_MSG_RESULT([no])
@@ -9339,6 +9340,9 @@ if test "$COM" = "MSC"; then # override the above
     HARFBUZZ_LIBS="${WORKDIR}/UnpackedTarball/harfbuzz/src/.libs/libharfbuzz.lib"
 fi
 if test "$with_system_harfbuzz" = "yes"; then
+    if test "$with_system_graphite" = "no"; then
+        AC_MSG_ERROR([--with-system-graphite must be used when --with-system-harfbuzz is used])
+    fi
     AC_MSG_CHECKING([whether system Harfbuzz is built with Graphite support])
     _save_libs="$LIBS"
     _save_cflags="$CFLAGS"
@@ -9347,6 +9351,10 @@ if test "$with_system_harfbuzz" = "yes"; then
     AC_CHECK_FUNC(hb_graphite2_face_get_gr_face,,[AC_MSG_ERROR([Harfbuzz needs to be built with Graphite support.])])
     LIBS="$_save_libs"
     CFLAGS="$_save_cflags"
+else
+    if test "$with_system_graphite" = "yes"; then
+        AC_MSG_ERROR([--without-system-graphite must be used when --without-system-harfbuzz is used])
+    fi
 fi
 
 AC_MSG_CHECKING([whether to use X11])
diff --git a/vcl/CppunitTest_vcl_wmf_test.mk b/vcl/CppunitTest_vcl_wmf_test.mk
index 51e9126..1de86d8 100644
--- a/vcl/CppunitTest_vcl_wmf_test.mk
+++ b/vcl/CppunitTest_vcl_wmf_test.mk
@@ -80,6 +80,7 @@ endif
 
 $(eval $(call gb_CppunitTest_use_externals,vcl_wmf_test,\
     gio \
+    graphite \
     harfbuzz \
     icuuc \
     lcms2 \
@@ -90,10 +91,6 @@ $(eval $(call gb_CppunitTest_use_externals,vcl_wmf_test,\
  ))
 endif
 
-ifeq ($(ENABLE_GRAPHITE),TRUE)
-$(eval $(call gb_CppunitTest_use_external,vcl_wmf_test,graphite))
-endif
-
 ifeq ($(OS),MACOSX)
 $(eval $(call gb_CppunitTest_use_system_darwin_frameworks,vcl_wmf_test,\
     ApplicationServices \
diff --git a/vcl/Library_vcl.mk b/vcl/Library_vcl.mk
index 67bcbe5..2b0874a 100644
--- a/vcl/Library_vcl.mk
+++ b/vcl/Library_vcl.mk
@@ -116,6 +116,7 @@ $(eval $(call gb_Library_use_externals,vcl,\
 	boost_headers \
 	gio \
 	glm_headers \
+	graphite \
 	harfbuzz \
 	icu_headers \
 	icuuc \
@@ -434,8 +435,6 @@ $(eval $(call gb_Library_add_exception_objects,vcl,\
 ))
 endif
 
-$(eval $(call gb_Library_use_external,vcl,graphite))
-
 endif
 
 vcl_quartz_code= \
commit 424d47ade5bf3081bb01a4a93aebcf72c590fe2f
Author: Khaled Hosny <khaledhosny at eglug.org>
Date:   Thu Sep 22 19:29:04 2016 +0200

    Always build HarfBuzz everywhere
    
    It is no longer an optional feature on any platform.
    
    Change-Id: I70cdcd2c0df69d961ecc5f36b4e8d035d251ef16

diff --git a/RepositoryExternal.mk b/RepositoryExternal.mk
index 95241ab..e0f1337 100644
--- a/RepositoryExternal.mk
+++ b/RepositoryExternal.mk
@@ -1490,7 +1490,6 @@ endef
 
 endif # SYSTEM_ICU
 
-ifeq ($(ENABLE_HARFBUZZ),TRUE)
 ifneq ($(SYSTEM_HARFBUZZ),)
 
 define gb_LinkTarget__use_harfbuzz
@@ -1515,11 +1514,6 @@ $(call gb_LinkTarget_use_external_project,$(1),harfbuzz)
 endef
 
 endif # SYSTEM_HARFBUZZ
-else # ENABLE_HARFBUZZ != YES
-
-gb_LinkTarget__use_harfbuzz :=
-
-endif # ENABLE_HARFBUZZ
 
 ifeq ($(DISABLE_OPENSSL),TRUE)
 
diff --git a/config_host.mk.in b/config_host.mk.in
index 2e6d007..90c25a6 100644
--- a/config_host.mk.in
+++ b/config_host.mk.in
@@ -133,7 +133,6 @@ export ENABLE_FIREBIRD_SDBC=@ENABLE_FIREBIRD_SDBC@
 export ENABLE_GIO=@ENABLE_GIO@
 export ENABLE_GRAPHITE=@ENABLE_GRAPHITE@
 export ENABLE_ORCUS=@ENABLE_ORCUS@
-export ENABLE_HARFBUZZ=@ENABLE_HARFBUZZ@
 export ENABLE_GLTF=@ENABLE_GLTF@
 export SYSTEM_LIBGLTF=@SYSTEM_LIBGLTF@
 export LIBGLTF_CFLAGS=@LIBGLTF_CFLAGS@
diff --git a/configure.ac b/configure.ac
index 6dd2d10..d67054b 100644
--- a/configure.ac
+++ b/configure.ac
@@ -2135,12 +2135,6 @@ AC_ARG_WITH(iwyu,
          Use only if you are hacking on it.]),
 ,)
 
-AC_ARG_WITH(harfbuzz,
-    AS_HELP_STRING([--with-harfbuzz],
-        [Enable HarfBuzz support regardless of the platform.
-         Experimental only. Use only if working on it.]),
-,)
-
 dnl ===================================================================
 dnl Branding
 dnl ===================================================================
@@ -9340,32 +9334,20 @@ AC_SUBST(ENABLE_ORCUS)
 dnl ===================================================================
 dnl HarfBuzz
 dnl ===================================================================
-AC_MSG_CHECKING([whether to enable HarfBuzz support])
-if test "$with_harfbuzz" = "yes" -o \( $_os != WINNT -a $_os != Darwin -a $_os != iOS \); then
-    AC_MSG_RESULT([yes])
-    ENABLE_HARFBUZZ="TRUE"
-    if $PKG_CONFIG --atleast-version 0.9.18 harfbuzz; then
-        libo_CHECK_SYSTEM_MODULE([harfbuzz],[HARFBUZZ],[harfbuzz-icu >= 0.9.18],["-I${WORKDIR}/UnpackedTarball/harfbuzz/src"],["-L${WORKDIR}/UnpackedTarball/harfbuzz/src/.libs -lharfbuzz"])
-    else
-        libo_CHECK_SYSTEM_MODULE([harfbuzz],[HARFBUZZ],[harfbuzz >= 0.9.10],[-I${WORKDIR}/UnpackedTarball/harfbuzz/src],["-L${WORKDIR}/UnpackedTarball/harfbuzz/src/.libs -lharfbuzz"])
-    fi
-    if test "$COM" = "MSC"; then # override the above
-        HARFBUZZ_LIBS="${WORKDIR}/UnpackedTarball/harfbuzz/src/.libs/libharfbuzz.lib"
-    fi
-    if test "$with_system_harfbuzz" = "yes"; then
-        AC_MSG_CHECKING([whether system Harfbuzz is built with Graphite support])
-        _save_libs="$LIBS"
-        _save_cflags="$CFLAGS"
-        LIBS="$LIBS $HARFBUZZ_LIBS"
-        CFLAGS="$CFLAGS $HARFBUZZ_CFLAGS"
-        AC_CHECK_FUNC(hb_graphite2_face_get_gr_face,,[AC_MSG_ERROR([Harfbuzz needs to be built with Graphite support.])])
-        LIBS="$_save_libs"
-        CFLAGS="$_save_cflags"
-    fi
-else
-    AC_MSG_RESULT([no])
+libo_CHECK_SYSTEM_MODULE([harfbuzz],[HARFBUZZ],[harfbuzz-icu >= 0.9.18],["-I${WORKDIR}/UnpackedTarball/harfbuzz/src"],["-L${WORKDIR}/UnpackedTarball/harfbuzz/src/.libs -lharfbuzz"])
+if test "$COM" = "MSC"; then # override the above
+    HARFBUZZ_LIBS="${WORKDIR}/UnpackedTarball/harfbuzz/src/.libs/libharfbuzz.lib"
+fi
+if test "$with_system_harfbuzz" = "yes"; then
+    AC_MSG_CHECKING([whether system Harfbuzz is built with Graphite support])
+    _save_libs="$LIBS"
+    _save_cflags="$CFLAGS"
+    LIBS="$LIBS $HARFBUZZ_LIBS"
+    CFLAGS="$CFLAGS $HARFBUZZ_CFLAGS"
+    AC_CHECK_FUNC(hb_graphite2_face_get_gr_face,,[AC_MSG_ERROR([Harfbuzz needs to be built with Graphite support.])])
+    LIBS="$_save_libs"
+    CFLAGS="$_save_cflags"
 fi
-AC_SUBST(ENABLE_HARFBUZZ)
 
 AC_MSG_CHECKING([whether to use X11])
 dnl ***************************************
commit 63fc67caa13e6dfe7f3f1930751deab78a5c5878
Author: Khaled Hosny <khaledhosny at eglug.org>
Date:   Sun Sep 11 10:25:46 2016 +0200

    Override GetCharWidths and ApplyDXArray in CSL
    
    A much simpler and saner implementation. This also unbreaks Awami
    Nastaliq.
    
    Break kashida justification, will need to rewrite that one as well.
    
    Change-Id: I843679e937f2881e77df61f5cbd9516b6df1b3b6

diff --git a/vcl/inc/CommonSalLayout.hxx b/vcl/inc/CommonSalLayout.hxx
index 83de5c1..89214d4 100644
--- a/vcl/inc/CommonSalLayout.hxx
+++ b/vcl/inc/CommonSalLayout.hxx
@@ -65,4 +65,7 @@ public:
     virtual bool            LayoutText(ImplLayoutArgs&) override;
     virtual void            DrawText( SalGraphics& ) const override;
     std::shared_ptr<vcl::TextLayoutCache> CreateTextLayoutCache(OUString const&) const override;
+
+    virtual bool            GetCharWidths(DeviceCoordinate* pCharWidths) const override;
+    virtual void            ApplyDXArray(ImplLayoutArgs&) override;
 };
diff --git a/vcl/inc/sallayout.hxx b/vcl/inc/sallayout.hxx
index cfb2930..1050943 100644
--- a/vcl/inc/sallayout.hxx
+++ b/vcl/inc/sallayout.hxx
@@ -326,7 +326,7 @@ public:
     void            AppendGlyph( const GlyphItem& );
     void            Reserve(int size) { m_GlyphItems.reserve(size + 1); }
     virtual void    AdjustLayout( ImplLayoutArgs& ) override;
-    void    ApplyDXArray( ImplLayoutArgs& );
+    virtual void    ApplyDXArray( ImplLayoutArgs& );
     void    Justify( DeviceCoordinate nNewWidth );
     void            KashidaJustify( long nIndex, int nWidth );
     void            ApplyAsianKerning(const OUString& rStr);
@@ -352,7 +352,7 @@ protected:
     virtual void    DropGlyph( int nStart ) override;
     virtual void    Simplify( bool bIsBase ) override;
 
-    bool            GetCharWidths( DeviceCoordinate* pCharWidths ) const;
+    virtual bool    GetCharWidths( DeviceCoordinate* pCharWidths ) const;
 
     std::vector<GlyphItem>     m_GlyphItems;
 
diff --git a/vcl/source/gdi/CommonSalLayout.cxx b/vcl/source/gdi/CommonSalLayout.cxx
index 9c68bdb..a5e3bf6 100644
--- a/vcl/source/gdi/CommonSalLayout.cxx
+++ b/vcl/source/gdi/CommonSalLayout.cxx
@@ -486,3 +486,56 @@ bool CommonSalLayout::LayoutText(ImplLayoutArgs& rArgs)
 
     return true;
 }
+
+bool CommonSalLayout::GetCharWidths(DeviceCoordinate* pCharWidths) const
+{
+    int nCharCount = mnEndCharPos - mnMinCharPos;
+
+    for (int i = 0; i < nCharCount; ++i)
+        pCharWidths[i] = 0;
+
+    for (auto const& aGlyphItem : m_GlyphItems)
+        pCharWidths[aGlyphItem.mnCharPos - mnMinCharPos] += aGlyphItem.mnNewWidth;
+
+    return true;
+}
+
+void CommonSalLayout::ApplyDXArray(ImplLayoutArgs& rArgs)
+{
+    if (rArgs.mpDXArray == nullptr)
+        return;
+
+    int nCharCount = mnEndCharPos - mnMinCharPos;
+    std::unique_ptr<DeviceCoordinate[]> const pOldCharWidths(new DeviceCoordinate[nCharCount]);
+    std::unique_ptr<DeviceCoordinate[]> const pNewCharWidths(new DeviceCoordinate[nCharCount]);
+
+    GetCharWidths(pOldCharWidths.get());
+
+    for (int i = 0; i < nCharCount; ++i)
+    {
+        if (i == 0)
+            pNewCharWidths[i] = rArgs.mpDXArray[i];
+        else
+            pNewCharWidths[i] = rArgs.mpDXArray[i] - rArgs.mpDXArray[i - 1];
+    }
+
+    DeviceCoordinate nDelta = 0;
+    size_t i = 0;
+    while (i < m_GlyphItems.size())
+    {
+        int nCharPos = m_GlyphItems[i].mnCharPos - mnMinCharPos;
+        DeviceCoordinate nDiff = pNewCharWidths[nCharPos] - pOldCharWidths[nCharPos];
+
+        m_GlyphItems[i].maLinearPos.X() += nDelta;
+        size_t j = i;
+        while (++j < m_GlyphItems.size())
+        {
+            if (m_GlyphItems[j].mnCharPos != m_GlyphItems[i].mnCharPos)
+                break;
+            m_GlyphItems[j].maLinearPos.X() += nDelta;
+        }
+
+        nDelta += nDiff;
+        i = j;
+    }
+}


More information about the Libreoffice-commits mailing list