[Libreoffice-commits] core.git: Branch 'feature/commonsallayout' - 2 commits - vcl/inc vcl/source
Khaled Hosny
khaledhosny at eglug.org
Sun Oct 9 22:58:12 UTC 2016
vcl/inc/CommonSalLayout.hxx | 2
vcl/source/gdi/CommonSalLayout.cxx | 107 +++++++++++++++++++++++++++++++------
2 files changed, 92 insertions(+), 17 deletions(-)
New commits:
commit 7a897b1d181ad23c3d2249c05c9047ced4ace11b
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 188472e..ea64d05 100644
--- a/vcl/source/gdi/CommonSalLayout.cxx
+++ b/vcl/source/gdi/CommonSalLayout.cxx
@@ -609,3 +609,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 da53eeb58bb6b510daf51c7e1edc20a5c1ef8b9a
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 7bcbf1d..188472e 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
@@ -543,6 +534,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())
@@ -550,16 +551,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;
+ }
+ }
+ }
}
More information about the Libreoffice-commits
mailing list