summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTor Lillqvist <tml@collabora.com>2016-03-15 10:18:15 +0200
committerTor Lillqvist <tml@collabora.com>2016-03-15 10:21:43 +0200
commit73443fd278811837650160482c34c15e8830f0d3 (patch)
treeef34799cf09f0a1255385aaa313443d012a84731
parente2e3d75364ec7906954383c4fa6c883e416a37cc (diff)
tdf#97319: Handle surrogate pairs in glyph caching for SimpleWinLayout
(For UniscribeLayout we use glyph indices.) Change-Id: Id1907cb766b9285d32e484049bec1b99159c5768
-rw-r--r--vcl/win/gdi/winlayout.cxx49
1 files changed, 37 insertions, 12 deletions
diff --git a/vcl/win/gdi/winlayout.cxx b/vcl/win/gdi/winlayout.cxx
index 56df8947c2f8..9aa23acd41e5 100644
--- a/vcl/win/gdi/winlayout.cxx
+++ b/vcl/win/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 WinFontInstance::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 WinFontInstance::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)
@@ -1491,10 +1494,21 @@ 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]))
+ {
+ nCodePoint = rtl::combineSurrogates(mpOutGlyphs[i], mpOutGlyphs[i+1]);
+ i++;
+ }
+ 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;
}
@@ -1528,10 +1542,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(),