Index: Source/platform/fonts/Font.cpp |
diff --git a/Source/platform/fonts/Font.cpp b/Source/platform/fonts/Font.cpp |
index 4522a7f0389e092064c4132d33e79318e4d3a14c..84a96f1947f76af8719f768af3691b3cb07edb1c 100644 |
--- a/Source/platform/fonts/Font.cpp |
+++ b/Source/platform/fonts/Font.cpp |
@@ -339,9 +339,6 @@ CodePath Font::codePath(const TextRunPaintInfo& runInfo) const |
if (m_fontDescription.featureSettings() && m_fontDescription.featureSettings()->size() > 0 && m_fontDescription.letterSpacing() == 0) |
return ComplexPath; |
- if (m_fontDescription.orientation() == Vertical) |
- return ComplexPath; |
- |
if (m_fontDescription.widthVariant() != RegularWidth) |
return ComplexPath; |
@@ -716,7 +713,8 @@ void Font::drawGlyphs(GraphicsContext* gc, const SimpleFontData* font, |
{ |
ASSERT(glyphBuffer.size() >= from + numGlyphs); |
- if (!glyphBuffer.hasVerticalOffsets()) { |
+ bool drawVertically = font->platformData().orientation() == Vertical && font->verticalData(); |
+ if (!glyphBuffer.hasVerticalOffsets() && !drawVertically) { |
SkAutoSTMalloc<64, SkScalar> storage(numGlyphs); |
SkScalar* xpos = storage.get(); |
for (unsigned i = 0; i < numGlyphs; i++) |
@@ -727,24 +725,40 @@ void Font::drawGlyphs(GraphicsContext* gc, const SimpleFontData* font, |
return; |
} |
- bool drawVertically = font->platformData().orientation() == Vertical && font->verticalData(); |
- |
- GraphicsContextStateSaver stateSaver(*gc, false); |
+ GraphicsContextStateSaver stateSaver(*gc); |
if (drawVertically) { |
- stateSaver.save(); |
- gc->concatCTM(AffineTransform(0, -1, 1, 0, point.x(), point.y())); |
- gc->concatCTM(AffineTransform(1, 0, 0, 1, -point.x(), -point.y())); |
+ const float initialAdvance = glyphBuffer.hasVerticalOffsets() ? 0 : glyphBuffer.xOffsetAt(from); |
+ const FloatPoint adjustedPoint(point.x() + initialAdvance, point.y()); |
+ const float verticalBaselineXOffset = font->fontMetrics().floatAscent() - font->fontMetrics().floatAscent(IdeographicBaseline); |
+ const FloatPoint verticalOrigin(adjustedPoint.x() + verticalBaselineXOffset, adjustedPoint.y() - initialAdvance); |
+ |
+ // Multiple matrices are needed to convert between multiple coordinate systems, so they are pre-concatenated. |
+ // First, rotate back the rotated baseline in the rendering coordinates to the glyph baseline: |
+ // gc->concatCTM(AffineTransform(0, -1, 1, 0, adjustedPoint.x(), adjustedPoint.y())); |
+ // gc->concatCTM(AffineTransform(1, 0, 0, 1, -adjustedPoint.x(), -adjustedPoint.y())); |
+ // then move to the text origin to use the glyph coordinate system. |
+ // gc->concatCTM(AffineTransform(1, 0, 0, 1, verticalOrigin.x(), verticalOrigin.y())); |
+ gc->concatCTM(AffineTransform(0, -1, 1, 0, |
+ -adjustedPoint.y() + adjustedPoint.x() + verticalOrigin.y(), |
+ adjustedPoint.x() + adjustedPoint.y() - verticalOrigin.x())); |
+ } else { |
+ gc->concatCTM(AffineTransform::translation(point.x(), point.y())); |
} |
- const float verticalBaselineXOffset = drawVertically ? SkFloatToScalar(font->fontMetrics().floatAscent() - font->fontMetrics().floatAscent(IdeographicBaseline)) : 0; |
- |
- ASSERT(glyphBuffer.hasVerticalOffsets()); |
- SkAutoSTMalloc<32, SkPoint> storage(numGlyphs); |
+ SkAutoSTMalloc<64, SkPoint> storage(numGlyphs); |
SkPoint* pos = storage.get(); |
- for (unsigned i = 0; i < numGlyphs; i++) { |
- pos[i].set( |
- SkFloatToScalar(point.x() + verticalBaselineXOffset + glyphBuffer.xOffsetAt(from + i)), |
- SkFloatToScalar(point.y() + glyphBuffer.yOffsetAt(from + i))); |
+ |
+ if (!glyphBuffer.hasVerticalOffsets()) { // Simple path, vertical |
+ ASSERT(drawVertically); |
+ |
+ Vector<FloatPoint, 64> translations(numGlyphs); |
+ font->verticalData()->getVerticalTranslationsForGlyphs(font, glyphBuffer.glyphs(from), numGlyphs, reinterpret_cast<float*>(&translations[0])); |
+ |
+ for (unsigned i = 0; i < numGlyphs; ++i) |
+ pos[i].set(SkFloatToScalar(translations[i].x()), SkFloatToScalar(glyphBuffer.xOffsetAt(from + i) - translations[i].y())); |
+ } else { // Complex path, either horizontal or vertical |
+ for (unsigned i = 0; i < numGlyphs; i++) |
+ pos[i].set(SkFloatToScalar(glyphBuffer.xOffsetAt(from + i)), SkFloatToScalar(glyphBuffer.yOffsetAt(from + i))); |
} |
paintGlyphs(gc, font, glyphBuffer.glyphs(from), numGlyphs, pos, textRect); |