diff options
author | Tor Lillqvist <tml@collabora.com> | 2016-03-15 10:18:15 +0200 |
---|---|---|
committer | Miklos Vajna <vmiklos@collabora.co.uk> | 2016-03-17 07:55:38 +0000 |
commit | c54310c6b0f14a649ab3d290c012fff2fab86d85 (patch) | |
tree | 47185f877aa9de8dc6ee544236518fdb1a441e2e | |
parent | 99ab65e9139d60542344041a96ab8d3a4dc39bdb (diff) |
tdf#97319: Give up on attempting to cache non-BMP glyphs for SimpleWinLayout
Add code to handle surrogate pairs in glyph caching, but I can't
figure out why successive non-BMP glyphs in the bugdoc get drawn on
top of each others. So bail out...
Change-Id: Id1907cb766b9285d32e484049bec1b99159c5768
Reviewed-on: https://gerrit.libreoffice.org/23292
Tested-by: Jenkins <ci@libreoffice.org>
Reviewed-by: Miklos Vajna <vmiklos@collabora.co.uk>
-rw-r--r-- | vcl/win/source/gdi/winlayout.cxx | 56 |
1 files changed, 44 insertions, 12 deletions
diff --git a/vcl/win/source/gdi/winlayout.cxx b/vcl/win/source/gdi/winlayout.cxx index 2e83894a1ed1..3b1f081e03b8 100644 --- a/vcl/win/source/gdi/winlayout.cxx +++ b/vcl/win/source/gdi/winlayout.cxx @@ -76,7 +76,7 @@ const int GLYPH_OFFSET_RATIO = GLYPH_SPACE_RATIO * 2; struct OpenGLGlyphCacheChunk { - WORD mnFirstGlyph; + int mnFirstGlyph; // Must be int to handle non-BMP code points when mbRealGlyphIndices is false int mnGlyphCount; std::vector<Rectangle> maLocation; std::vector<int> maLeftOverhangs; @@ -383,9 +383,9 @@ bool ImplWinFontEntry::AddChunkOfGlyphs(bool bRealGlyphIndices, int nGlyphIndex, aChunk.mnGlyphCount = nCount; aChunk.mbRealGlyphIndices = bRealGlyphIndices; - std::vector<WORD> aGlyphIndices(nCount); + std::vector<uint32_t> aCodePointsOrGlyphIndices(nCount); for (int i = 0; i < nCount; i++) - aGlyphIndices[i] = nGlyphIndex + i; + aCodePointsOrGlyphIndices[i] = nGlyphIndex + i; HDC hDC = CreateCompatibleDC(rLayout.mhDC); if (hDC == NULL) @@ -424,18 +424,21 @@ bool ImplWinFontEntry::AddChunkOfGlyphs(bool bRealGlyphIndices, int nGlyphIndex, return false; } } + std::vector<WORD> aGlyphIndices(nCount); // Fetch the ink boxes and calculate the size of the atlas. if (!bRealGlyphIndices) { - // FIXME First convert from UTF16 to utf32 - std::vector<uint32_t> aCodePoints(aGlyphIndices.begin(), aGlyphIndices.end()); - aGlyphIndices.resize(aCodePoints.size()); - if (!SUCCEEDED(pTxt->GetFontFace()->GetGlyphIndices(aCodePoints.data(), aCodePoints.size(), aGlyphIndices.data()))) + if (!SUCCEEDED(pTxt->GetFontFace()->GetGlyphIndices(aCodePointsOrGlyphIndices.data(), aCodePointsOrGlyphIndices.size(), aGlyphIndices.data()))) { pTxt->ReleaseFont(); return false; } } + else + { + for (int i = 0; i < nCount; i++) + aGlyphIndices[i] = aCodePointsOrGlyphIndices[i]; + } Rectangle bounds(0, 0, 0, 0); auto aInkBoxes = pTxt->GetGlyphInkBoxes(aGlyphIndices.data(), aGlyphIndices.data() + nCount); for (auto &box : aInkBoxes) @@ -712,7 +715,10 @@ bool SimpleWinLayout::LayoutText( ImplLayoutArgs& rArgs ) if( bSurrogate ) nCharCode = 0x10000 + ((pCodes[0] - 0xD800) << 10) + (pCodes[1] - 0xDC00); else // or fall back to a replacement character + { + // FIXME: Surely this is an error situation that should not happen? nCharCode = '?'; + } } // get the advance width for the current UTF-32 code point @@ -1492,10 +1498,25 @@ bool SimpleWinLayout::CacheGlyphs(SalGraphics& rGraphics) const for (int i = 0; i < mnGlyphCount; i++) { - if (mrWinFontEntry.GlyphIsCached(mpOutGlyphs[i])) + int nCodePoint; + if (i < mnGlyphCount-1 && rtl::isHighSurrogate(mpOutGlyphs[i]) && rtl::isLowSurrogate(mpOutGlyphs[i+1])) + { +#if 1 + return false; +#else + nCodePoint = rtl::combineSurrogates(mpOutGlyphs[i], mpOutGlyphs[i+1]); + i++; +#endif + } + else + { + nCodePoint = mpOutGlyphs[i]; + } + + if (mrWinFontEntry.GlyphIsCached(nCodePoint)) continue; - if (!mrWinFontEntry.AddChunkOfGlyphs(false, mpOutGlyphs[i], *this, rGraphics)) + if (!mrWinFontEntry.AddChunkOfGlyphs(false, nCodePoint, *this, rGraphics)) return false; } @@ -1529,10 +1550,21 @@ bool SimpleWinLayout::DrawCachedGlyphs(SalGraphics& rGraphics) const if (mpOutGlyphs[i] == DROPPED_OUTGLYPH) continue; - assert(mrWinFontEntry.GlyphIsCached(mpOutGlyphs[i])); + int nCodePoint; + if (i < mnGlyphCount-1 && rtl::isHighSurrogate(mpOutGlyphs[i]) && rtl::isLowSurrogate(mpOutGlyphs[i+1])) + { + nCodePoint = rtl::combineSurrogates(mpOutGlyphs[i], mpOutGlyphs[i+1]); + i++; + } + else + { + nCodePoint = mpOutGlyphs[i]; + } + + assert(mrWinFontEntry.GlyphIsCached(nCodePoint)); - const OpenGLGlyphCacheChunk& rChunk = mrWinFontEntry.GetCachedGlyphChunkFor(mpOutGlyphs[i]); - const int n = mpOutGlyphs[i] - rChunk.mnFirstGlyph; + const OpenGLGlyphCacheChunk& rChunk = mrWinFontEntry.GetCachedGlyphChunkFor(nCodePoint); + const int n = nCodePoint - rChunk.mnFirstGlyph; SalTwoRect a2Rects(rChunk.maLocation[n].Left(), rChunk.maLocation[n].Top(), rChunk.maLocation[n].getWidth(), rChunk.maLocation[n].getHeight(), |