summaryrefslogtreecommitdiff
path: root/vcl
diff options
context:
space:
mode:
authorKhaled Hosny <khaledhosny@eglug.org>2013-04-28 15:56:26 +0200
committerKhaled Hosny <khaledhosny@eglug.org>2013-04-29 12:45:41 +0200
commitc559b13b80ab4c8ca4e6ca713bce388ea650e02c (patch)
tree4e0599d1ca6b493668613f8f438972a709e2c05b /vcl
parentca0b580e2a21999d75bcd39ae5b6f81e9e42897b (diff)
[harfbuzz] Re-enable text justification
It turned out that ApplyDXArray() is need to apply advance width adjustments after justification, so we can't just bypass it. So I just copied GenericSalLayout::ApplyDXArray() and stripped it of ICUism so it does not break with HarfBuzz, but I had to make m_GlyphItems non-private, so I'm not sure this is the right approach. Change-Id: I66d647c3590fdf912c39d0cf23ac72bcc7ca72c9
Diffstat (limited to 'vcl')
-rw-r--r--vcl/generic/glyphs/gcach_layout.cxx80
-rw-r--r--vcl/inc/sallayout.hxx3
2 files changed, 78 insertions, 5 deletions
diff --git a/vcl/generic/glyphs/gcach_layout.cxx b/vcl/generic/glyphs/gcach_layout.cxx
index f147ab24ca4a..abd1ab81b67a 100644
--- a/vcl/generic/glyphs/gcach_layout.cxx
+++ b/vcl/generic/glyphs/gcach_layout.cxx
@@ -106,13 +106,85 @@ void ServerFontLayout::AdjustLayout( ImplLayoutArgs& rArgs )
}
}
+// apply adjustments to glyph advances, e.g. as a result of justification.
void ServerFontLayout::ApplyDXArray(ImplLayoutArgs& rArgs)
{
- // No idea what issue ApplyDXArray() was supposed to fix, but whatever
- // GenericSalLayout::ApplyDXArray() does it just breaks our perfectly
- // positioned text.
- if (!bUseHarfBuzz)
+ if (bUseHarfBuzz)
+ {
+ if (m_GlyphItems.empty())
+ return;
+
+ // determine cluster boundaries and x base offset
+ const int nCharCount = rArgs.mnEndCharPos - rArgs.mnMinCharPos;
+ int* pLogCluster = (int*)alloca(nCharCount * sizeof(int));
+ size_t i;
+ int n,p;
+ long nBasePointX = -1;
+ if (mnLayoutFlags & SAL_LAYOUT_FOR_FALLBACK)
+ nBasePointX = 0;
+ for (p = 0; p < nCharCount; ++p)
+ pLogCluster[p] = -1;
+
+ for (i = 0; i < m_GlyphItems.size(); ++i)
+ {
+ n = m_GlyphItems[i].mnCharPos - rArgs.mnMinCharPos;
+ if ((n < 0) || (nCharCount <= n))
+ continue;
+ if (pLogCluster[n] < 0)
+ pLogCluster[n] = i;
+ if (nBasePointX < 0)
+ nBasePointX = m_GlyphItems[i].maLinearPos.X();
+ }
+ // retarget unresolved pLogCluster[n] to a glyph inside the cluster
+ // TODO: better do it while the deleted-glyph markers are still there
+ for (n = 0; n < nCharCount; ++n)
+ if ((p = pLogCluster[0]) >= 0)
+ break;
+ if (n >= nCharCount)
+ return;
+ for (n = 0; n < nCharCount; ++n)
+ {
+ if (pLogCluster[n] < 0)
+ pLogCluster[n] = p;
+ else
+ p = pLogCluster[n];
+ }
+
+ // calculate adjusted cluster widths
+ sal_Int32* pNewGlyphWidths = (sal_Int32*)alloca(m_GlyphItems.size() * sizeof(sal_Int32));
+ for (i = 0; i < m_GlyphItems.size(); ++i)
+ pNewGlyphWidths[i] = 0;
+
+ bool bRTL;
+ for (int nCharPos = p = -1; rArgs.GetNextPos(&nCharPos, &bRTL); )
+ {
+ n = nCharPos - rArgs.mnMinCharPos;
+ if ((n < 0) || (nCharCount <= n)) continue;
+
+ if (pLogCluster[n] >= 0)
+ p = pLogCluster[n];
+ if (p >= 0)
+ {
+ long nDelta = rArgs.mpDXArray[n];
+ if(n > 0)
+ nDelta -= rArgs.mpDXArray[n - 1];
+ pNewGlyphWidths[p] += nDelta * mnUnitsPerPixel;
+ }
+ }
+
+ // move cluster positions using the adjusted widths
+ long nDelta = 0;
+ for (i = 0; i < m_GlyphItems.size(); ++i)
+ {
+ nDelta += pNewGlyphWidths[i] - m_GlyphItems[i].mnNewWidth;
+ m_GlyphItems[i].mnNewWidth = pNewGlyphWidths[i];
+ m_GlyphItems[i].maLinearPos.X() += nDelta;
+ }
+ }
+ else
+ {
GenericSalLayout::ApplyDXArray(rArgs);
+ }
}
// =======================================================================
diff --git a/vcl/inc/sallayout.hxx b/vcl/inc/sallayout.hxx
index ad6cd9479ab5..5d99acb768df 100644
--- a/vcl/inc/sallayout.hxx
+++ b/vcl/inc/sallayout.hxx
@@ -367,8 +367,9 @@ protected:
bool GetCharWidths( sal_Int32* pCharWidths ) const;
-private:
GlyphVector m_GlyphItems;
+
+private:
mutable Point maBasePoint;
// enforce proper copy semantic