summaryrefslogtreecommitdiff
path: root/vcl/quartz
diff options
context:
space:
mode:
authorKhaled Hosny <khaledhosny@eglug.org>2016-10-15 06:11:26 -0700
committerKhaled Hosny <khaledhosny@eglug.org>2016-10-18 20:41:34 +0200
commit3a304a4e75d21fff5ba4775d9cb93b17f998e7ef (patch)
treec4b4546c8c3aa39d5c53da0687528a577a7208da /vcl/quartz
parent8f054454bf0703e154bb5964134c6f84f891a5b8 (diff)
Rewrite AquaSalGraphics::DrawSalLayout()
Slightly cleaner code and now handles glyph rotation for vertical text. Change-Id: I98cc8fd7df5e73068294e4d7dd6b38a71dcbdcc7
Diffstat (limited to 'vcl/quartz')
-rw-r--r--vcl/quartz/salgdi.cxx89
1 files changed, 67 insertions, 22 deletions
diff --git a/vcl/quartz/salgdi.cxx b/vcl/quartz/salgdi.cxx
index 787ddbff16e3..12dc1f114192 100644
--- a/vcl/quartz/salgdi.cxx
+++ b/vcl/quartz/salgdi.cxx
@@ -485,37 +485,82 @@ bool AquaSalGraphics::GetGlyphBoundRect( sal_GlyphId aGlyphId, Rectangle& rRect
void AquaSalGraphics::DrawSalLayout(const CommonSalLayout& rLayout)
{
- CGContextRef context = mrContext;
- SAL_INFO("vcl.ct", "CGContextSaveGState(" << context << ")");
- CGContextSaveGState(context);
- SAL_INFO("vcl.ct", "CGContextScaleCTM(" << context << ",1.0,-1.0)");
- const CoreTextStyle& rCTStyle = rLayout.getFontData();
-
- CTFontRef pFont = static_cast<CTFontRef>(CFDictionaryGetValue(rCTStyle.GetStyleDict(), kCTFontAttributeName));
- CGContextScaleCTM(context, 1.0, -1.0);
- CGContextSetShouldAntialias(context, !mbNonAntialiasedText);
- // rotate the matrix
- const CGFloat fRadians = rCTStyle.mfFontRotation;
- CGContextRotateCTM(context, +fRadians);
- const CGAffineTransform aInvMatrix = CGAffineTransformMakeRotation(-fRadians);
- CGContextSetFillColor(context, maTextColor.AsArray());
-
- // draw the text
+ const CoreTextStyle& rStyle = rLayout.getFontData();
+ const FontSelectPattern& rFontSelect = rStyle.maFontSelData;
+ if (rFontSelect.mnHeight == 0)
+ return;
+
+ CTFontRef pFont = static_cast<CTFontRef>(CFDictionaryGetValue(rStyle.GetStyleDict(), kCTFontAttributeName));
+
Point aPos;
sal_GlyphId aGlyphId;
std::vector<CGGlyph> aGlyphIds;
std::vector<CGPoint> aGlyphPos;
+ std::vector<bool> aGlyphRotation;
int nStart = 0;
- for (; rLayout.GetNextGlyphs(1, &aGlyphId, aPos, nStart); )
+ while (rLayout.GetNextGlyphs(1, &aGlyphId, aPos, nStart))
{
+ // Transform the position of non-vertical glyphs.
+ CGAffineTransform aMatrix = CGAffineTransformMakeRotation(-rStyle.mfFontRotation);
+
+ // Transform the position of vertical glyphs.
+ // We don’t handle GF_ROTR as it is not used in CommonSalLayout.
+ bool nGlyphRotation = false;
+ if ((aGlyphId & GF_ROTMASK) == GF_ROTL)
+ {
+ nGlyphRotation = true;
+ double nYdiff = CTFontGetAscent(pFont) - CTFontGetDescent(pFont);
+ aMatrix = CGAffineTransformTranslate(aMatrix, 0, -nYdiff);
+ }
+
aGlyphIds.push_back(aGlyphId & GF_IDXMASK);
- aGlyphPos.push_back(CGPointApplyAffineTransform(CGPointMake(aPos.X(), -1*aPos.Y()), aInvMatrix));
+ aGlyphPos.push_back(CGPointApplyAffineTransform(CGPointMake(aPos.X(), -aPos.Y()), aMatrix));
+ aGlyphRotation.push_back(nGlyphRotation);
+ }
+
+ if (aGlyphIds.empty())
+ return;
+
+ CGContextSaveGState(mrContext);
+
+ // Create a transformed font for drawing vertical glyphs.
+ 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);
+ CGContextRotateCTM(mrContext, rStyle.mfFontRotation);
+ CGContextSetShouldAntialias(mrContext, !mbNonAntialiasedText);
+ CGContextSetFillColor(mrContext, maTextColor.AsArray());
+
+ auto aIt = aGlyphRotation.cbegin();
+ while (aIt != aGlyphRotation.cend())
+ {
+ bool nGlyphRotation = *aIt;
+ // Find the boundary of the run of glyphs with the same rotation, to be
+ // drawn together.
+ auto aNext = std::find(aIt, aGlyphRotation.cend(), !nGlyphRotation);
+ size_t nStartIndex = std::distance(aGlyphRotation.cbegin(), aIt);
+ size_t nLen = std::distance(aIt, aNext);
+
+ if (nGlyphRotation && pRotatedFont)
+ CTFontDrawGlyphs(pRotatedFont, &aGlyphIds[nStartIndex], &aGlyphPos[nStartIndex], nLen, mrContext);
+ else
+ CTFontDrawGlyphs(pFont, &aGlyphIds[nStartIndex], &aGlyphPos[nStartIndex], nLen, mrContext);
+
+ aIt = aNext;
}
- CTFontDrawGlyphs(pFont, aGlyphIds.data(), aGlyphPos.data(), nStart, context);
- // restore the original graphic context transformations
- SAL_INFO("vcl.ct", "CGContextRestoreGState(" << context << ")");
- CGContextRestoreGState(context);
+ if (pRotatedFont)
+ CFRelease(pRotatedFont);
+ CGContextRestoreGState(mrContext);
}
void AquaSalGraphics::SetFont(FontSelectPattern* pReqFont, int nFallbackLevel)