diff options
author | Khaled Hosny <khaledhosny@eglug.org> | 2013-04-28 15:56:26 +0200 |
---|---|---|
committer | Khaled Hosny <khaledhosny@eglug.org> | 2013-04-29 12:45:41 +0200 |
commit | c559b13b80ab4c8ca4e6ca713bce388ea650e02c (patch) | |
tree | 4e0599d1ca6b493668613f8f438972a709e2c05b /vcl | |
parent | ca0b580e2a21999d75bcd39ae5b6f81e9e42897b (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.cxx | 80 | ||||
-rw-r--r-- | vcl/inc/sallayout.hxx | 3 |
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 |