summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKhaled Hosny <khaledhosny@eglug.org>2016-11-28 06:43:29 +0200
committerKhaled Hosny <khaledhosny@eglug.org>2016-11-28 05:40:30 +0000
commitf246542d1f61b5253189676688f59e5f952267a1 (patch)
tree0e0f3bada0178a1a2ccf669ac3931b0fb28aeb15
parent2db42ab241d0852d89a470b18727c22d0fc06745 (diff)
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@libreoffice.org> Reviewed-by: Khaled Hosny <khaledhosny@eglug.org>
-rw-r--r--vcl/inc/sallayout.hxx1
-rw-r--r--vcl/source/gdi/CommonSalLayout.cxx76
-rw-r--r--vcl/source/gdi/sallayout.cxx35
3 files changed, 32 insertions, 80 deletions
diff --git a/vcl/inc/sallayout.hxx b/vcl/inc/sallayout.hxx
index c20a58259cc0..effb6463d0cb 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 59a5d807d69e..c61e540c0be9 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 ebae19b0a968..9c10cde15005 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 )