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:
parent
c622982a7a
commit
3a64e01a7e
@ -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 don’t 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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user