Simplify vertical text drawing on macOS

Rotate only the rotated glyphs instead of rotating everything, then
unrotating the upright glyphs. No need for a rotated font either,
rotating the graphics is fine.

Change-Id: I1fce2c9c6a29abb1353a5fc8485a9c0d34edfbf1
This commit is contained in:
Khaled Hosny 2016-11-13 16:00:34 +02:00
parent c622982a7a
commit 3a64e01a7e

View File

@ -430,31 +430,39 @@ void AquaSalGraphics::DrawSalLayout(const CommonSalLayout& rLayout)
return; return;
CTFontRef pFont = static_cast<CTFontRef>(CFDictionaryGetValue(rStyle.GetStyleDict(), kCTFontAttributeName)); CTFontRef pFont = static_cast<CTFontRef>(CFDictionaryGetValue(rStyle.GetStyleDict(), kCTFontAttributeName));
CGAffineTransform aRotMatrix = CGAffineTransformMakeRotation(-rStyle.mfFontRotation);
Point aPos; Point aPos;
sal_GlyphId aGlyphId; sal_GlyphId aGlyphId;
std::vector<CGGlyph> aGlyphIds; std::vector<CGGlyph> aGlyphIds;
std::vector<CGPoint> aGlyphPos; std::vector<CGPoint> aGlyphPos;
std::vector<bool> aGlyphRotation; std::vector<bool> aGlyphOrientation;
int nStart = 0; int nStart = 0;
while (rLayout.GetNextGlyphs(1, &aGlyphId, aPos, nStart)) while (rLayout.GetNextGlyphs(1, &aGlyphId, aPos, nStart))
{ {
// Transform the position of non-vertical glyphs. CGPoint aGCPos = CGPointMake(aPos.X(), -aPos.Y());
CGAffineTransform aMatrix = CGAffineTransformMakeRotation(-rStyle.mfFontRotation);
// Transform the position of vertical glyphs. // Whether the glyph should be upright in vertical mode or not
// We dont handle GF_ROTR as it is not used in CommonSalLayout. bool bUprightGlyph = false;
bool nGlyphRotation = false;
if (rStyle.mfFontRotation)
{
if ((aGlyphId & GF_ROTMASK) == GF_ROTL) if ((aGlyphId & GF_ROTMASK) == GF_ROTL)
{ {
nGlyphRotation = true; bUprightGlyph = true;
double nYdiff = CTFontGetAscent(pFont) - CTFontGetDescent(pFont); // Adjust the position of upright (vertical) glyphs.
aMatrix = CGAffineTransformTranslate(aMatrix, 0, -nYdiff); aGCPos.y -= CTFontGetAscent(pFont) - CTFontGetDescent(pFont);
}
else
{
// Transform the position of rotated glyphs.
aGCPos = CGPointApplyAffineTransform(aGCPos, aRotMatrix);
}
} }
aGlyphIds.push_back(aGlyphId & GF_IDXMASK); aGlyphIds.push_back(aGlyphId & GF_IDXMASK);
aGlyphPos.push_back(CGPointApplyAffineTransform(CGPointMake(aPos.X(), -aPos.Y()), aMatrix)); aGlyphPos.push_back(aGCPos);
aGlyphRotation.push_back(nGlyphRotation); aGlyphOrientation.push_back(bUprightGlyph);
} }
if (aGlyphIds.empty()) if (aGlyphIds.empty())
@ -462,43 +470,30 @@ void AquaSalGraphics::DrawSalLayout(const CommonSalLayout& rLayout)
CGContextSaveGState(mrContext); CGContextSaveGState(mrContext);
// Create a transformed font for drawing vertical glyphs. // The view is vertically flipped (no idea why), flip it back.
CTFontRef pRotatedFont = nullptr;
if (rStyle.mfFontRotation)
{
CTFontDescriptorRef pDesc = CTFontCopyFontDescriptor(pFont);
CGFloat nSize = CTFontGetSize(pFont);
CGAffineTransform aMatrix = CTFontGetMatrix(pFont);
aMatrix = CGAffineTransformRotate(aMatrix, -rStyle.mfFontRotation);
pRotatedFont = CTFontCreateWithFontDescriptor(pDesc, nSize, &aMatrix);
CFRelease(pDesc);
}
CGContextScaleCTM(mrContext, 1.0, -1.0); CGContextScaleCTM(mrContext, 1.0, -1.0);
CGContextRotateCTM(mrContext, rStyle.mfFontRotation);
CGContextSetShouldAntialias(mrContext, !mbNonAntialiasedText); CGContextSetShouldAntialias(mrContext, !mbNonAntialiasedText);
CGContextSetFillColor(mrContext, maTextColor.AsArray()); CGContextSetFillColor(mrContext, maTextColor.AsArray());
auto aIt = aGlyphRotation.cbegin(); auto aIt = aGlyphOrientation.cbegin();
while (aIt != aGlyphRotation.cend()) while (aIt != aGlyphOrientation.cend())
{ {
bool nGlyphRotation = *aIt; bool bUprightGlyph = *aIt;
// Find the boundary of the run of glyphs with the same rotation, to be // Find the boundary of the run of glyphs with the same rotation, to be
// drawn together. // drawn together.
auto aNext = std::find(aIt, aGlyphRotation.cend(), !nGlyphRotation); auto aNext = std::find(aIt, aGlyphOrientation.cend(), !bUprightGlyph);
size_t nStartIndex = std::distance(aGlyphRotation.cbegin(), aIt); size_t nStartIndex = std::distance(aGlyphOrientation.cbegin(), aIt);
size_t nLen = std::distance(aIt, aNext); size_t nLen = std::distance(aIt, aNext);
if (nGlyphRotation && pRotatedFont) CGContextSaveGState(mrContext);
CTFontDrawGlyphs(pRotatedFont, &aGlyphIds[nStartIndex], &aGlyphPos[nStartIndex], nLen, mrContext); if (rStyle.mfFontRotation && !bUprightGlyph)
else CGContextRotateCTM(mrContext, rStyle.mfFontRotation);
CTFontDrawGlyphs(pFont, &aGlyphIds[nStartIndex], &aGlyphPos[nStartIndex], nLen, mrContext); CTFontDrawGlyphs(pFont, &aGlyphIds[nStartIndex], &aGlyphPos[nStartIndex], nLen, mrContext);
CGContextRestoreGState(mrContext);
aIt = aNext; aIt = aNext;
} }
if (pRotatedFont)
CFRelease(pRotatedFont);
CGContextRestoreGState(mrContext); CGContextRestoreGState(mrContext);
} }