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 <khaledho...@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 <khaledho...@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; + } + } + } }
_______________________________________________ Libreoffice-commits mailing list libreoffice-comm...@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/libreoffice-commits