Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 /* | 1 /* |
| 2 * Copyright (C) 1999 Lars Knoll (knoll@kde.org) | 2 * Copyright (C) 1999 Lars Knoll (knoll@kde.org) |
| 3 * (C) 1999 Antti Koivisto (koivisto@kde.org) | 3 * (C) 1999 Antti Koivisto (koivisto@kde.org) |
| 4 * (C) 2000 Dirk Mueller (mueller@kde.org) | 4 * (C) 2000 Dirk Mueller (mueller@kde.org) |
| 5 * Copyright (C) 2003, 2006, 2010, 2011 Apple Inc. All rights reserved. | 5 * Copyright (C) 2003, 2006, 2010, 2011 Apple Inc. All rights reserved. |
| 6 * Copyright (c) 2007, 2008, 2010 Google Inc. All rights reserved. | 6 * Copyright (c) 2007, 2008, 2010 Google Inc. All rights reserved. |
| 7 * | 7 * |
| 8 * This library is free software; you can redistribute it and/or | 8 * This library is free software; you can redistribute it and/or |
| 9 * modify it under the terms of the GNU Library General Public | 9 * modify it under the terms of the GNU Library General Public |
| 10 * License as published by the Free Software Foundation; either | 10 * License as published by the Free Software Foundation; either |
| (...skipping 324 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 335 CodePath Font::codePath(const TextRunPaintInfo& runInfo) const | 335 CodePath Font::codePath(const TextRunPaintInfo& runInfo) const |
| 336 { | 336 { |
| 337 const TextRun& run = runInfo.run; | 337 const TextRun& run = runInfo.run; |
| 338 | 338 |
| 339 if (fontDescription().typesettingFeatures() && (runInfo.from || runInfo.to ! = run.length())) | 339 if (fontDescription().typesettingFeatures() && (runInfo.from || runInfo.to ! = run.length())) |
| 340 return ComplexPath; | 340 return ComplexPath; |
| 341 | 341 |
| 342 if (m_fontDescription.featureSettings() && m_fontDescription.featureSettings ()->size() > 0 && m_fontDescription.letterSpacing() == 0) | 342 if (m_fontDescription.featureSettings() && m_fontDescription.featureSettings ()->size() > 0 && m_fontDescription.letterSpacing() == 0) |
| 343 return ComplexPath; | 343 return ComplexPath; |
| 344 | 344 |
| 345 if (m_fontDescription.orientation() == Vertical) | |
| 346 return ComplexPath; | |
| 347 | |
| 345 if (m_fontDescription.widthVariant() != RegularWidth) | 348 if (m_fontDescription.widthVariant() != RegularWidth) |
| 346 return ComplexPath; | 349 return ComplexPath; |
| 347 | 350 |
| 348 if (run.length() > 1 && fontDescription().typesettingFeatures()) | 351 if (run.length() > 1 && fontDescription().typesettingFeatures()) |
| 349 return ComplexPath; | 352 return ComplexPath; |
| 350 | 353 |
| 351 // FIXME: This really shouldn't be needed but for some reason the | 354 // FIXME: This really shouldn't be needed but for some reason the |
| 352 // TextRendering setting doesn't propagate to typesettingFeatures in time | 355 // TextRendering setting doesn't propagate to typesettingFeatures in time |
| 353 // for the prefs width calculation. | 356 // for the prefs width calculation. |
| 354 if (fontDescription().textRendering() == OptimizeLegibility || fontDescripti on().textRendering() == GeometricPrecision) | 357 if (fontDescription().textRendering() == OptimizeLegibility || fontDescripti on().textRendering() == GeometricPrecision) |
| (...skipping 426 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 781 SkPaint paint = textFillPaint(gc, font); | 784 SkPaint paint = textFillPaint(gc, font); |
| 782 gc->drawPosTextH(glyphs, numGlyphs * sizeof(Glyph), xpos, constY, textRe ct, paint); | 785 gc->drawPosTextH(glyphs, numGlyphs * sizeof(Glyph), xpos, constY, textRe ct, paint); |
| 783 } | 786 } |
| 784 | 787 |
| 785 if ((textMode & TextModeStroke) && gc->hasStroke()) { | 788 if ((textMode & TextModeStroke) && gc->hasStroke()) { |
| 786 SkPaint paint = textStrokePaint(gc, font, textMode & TextModeFill); | 789 SkPaint paint = textStrokePaint(gc, font, textMode & TextModeFill); |
| 787 gc->drawPosTextH(glyphs, numGlyphs * sizeof(Glyph), xpos, constY, textRe ct, paint); | 790 gc->drawPosTextH(glyphs, numGlyphs * sizeof(Glyph), xpos, constY, textRe ct, paint); |
| 788 } | 791 } |
| 789 } | 792 } |
| 790 | 793 |
| 791 void Font::paintGlyphsVertical(GraphicsContext* gc, const SimpleFontData* font, | |
| 792 const GlyphBuffer& glyphBuffer, unsigned from, unsigned numGlyphs, const Flo atPoint& point, | |
| 793 const FloatRect& textRect) const | |
| 794 { | |
| 795 const OpenTypeVerticalData* verticalData = font->verticalData(); | |
| 796 | |
| 797 SkAutoSTMalloc<32, SkPoint> storage(numGlyphs); | |
| 798 SkPoint* pos = storage.get(); | |
| 799 | |
| 800 // Bend over backwards to preserve legacy rounding. | |
| 801 float initialAdvance = glyphBuffer.xOffsetAt(from); | |
| 802 FloatPoint adjustedPoint(point.x() + initialAdvance, point.y()); | |
| 803 | |
| 804 AffineTransform savedMatrix = gc->getCTM(); | |
| 805 gc->concatCTM(AffineTransform(0, -1, 1, 0, adjustedPoint.x(), adjustedPoint. y())); | |
| 806 gc->concatCTM(AffineTransform(1, 0, 0, 1, -adjustedPoint.x(), -adjustedPoint .y())); | |
| 807 | |
| 808 const unsigned kMaxBufferLength = 256; | |
| 809 Vector<FloatPoint, kMaxBufferLength> translations; | |
| 810 | |
| 811 const FontMetrics& metrics = font->fontMetrics(); | |
| 812 float verticalOriginX = adjustedPoint.x() + metrics.floatAscent() - metrics. floatAscent(IdeographicBaseline); | |
| 813 | |
| 814 unsigned glyphIndex = 0; | |
| 815 while (glyphIndex < numGlyphs) { | |
| 816 unsigned chunkLength = std::min(kMaxBufferLength, numGlyphs - glyphIndex ); | |
| 817 | |
| 818 const Glyph* glyphs = glyphBuffer.glyphs(from + glyphIndex); | |
| 819 | |
| 820 translations.resize(chunkLength); | |
| 821 verticalData->getVerticalTranslationsForGlyphs(font, glyphs, chunkLength , | |
| 822 reinterpret_cast<float*>(&translations[0])); | |
| 823 | |
| 824 for (unsigned i = 0; i < chunkLength; ++i, ++glyphIndex) { | |
| 825 SkScalar x = verticalOriginX + lroundf(translations[i].x()); | |
| 826 SkScalar y = adjustedPoint.y() - SkIntToScalar( | |
| 827 -lroundf(glyphBuffer.xOffsetAt(from + glyphIndex) - initialAdvan ce - translations[i].y())); | |
| 828 pos[i].set(x, y); | |
| 829 } | |
| 830 paintGlyphs(gc, font, glyphs, chunkLength, pos, textRect); | |
| 831 } | |
| 832 | |
| 833 gc->setCTM(savedMatrix); | |
| 834 } | |
| 835 | |
| 836 void Font::drawGlyphs(GraphicsContext* gc, const SimpleFontData* font, | 794 void Font::drawGlyphs(GraphicsContext* gc, const SimpleFontData* font, |
| 837 const GlyphBuffer& glyphBuffer, unsigned from, unsigned numGlyphs, | 795 const GlyphBuffer& glyphBuffer, unsigned from, unsigned numGlyphs, |
| 838 const FloatPoint& point, const FloatRect& textRect) const | 796 const FloatPoint& point, const FloatRect& textRect) const |
| 839 { | 797 { |
| 840 ASSERT(glyphBuffer.size() >= from + numGlyphs); | 798 ASSERT(glyphBuffer.size() >= from + numGlyphs); |
| 841 | 799 |
| 842 if (font->platformData().orientation() == Vertical && font->verticalData()) { | |
| 843 paintGlyphsVertical(gc, font, glyphBuffer, from, numGlyphs, point, textR ect); | |
| 844 return; | |
| 845 } | |
| 846 | |
| 847 if (!glyphBuffer.hasVerticalOffsets()) { | 800 if (!glyphBuffer.hasVerticalOffsets()) { |
| 848 SkAutoSTMalloc<64, SkScalar> storage(numGlyphs); | 801 SkAutoSTMalloc<64, SkScalar> storage(numGlyphs); |
| 849 SkScalar* xpos = storage.get(); | 802 SkScalar* xpos = storage.get(); |
| 850 for (unsigned i = 0; i < numGlyphs; i++) | 803 for (unsigned i = 0; i < numGlyphs; i++) |
| 851 xpos[i] = SkFloatToScalar(point.x() + glyphBuffer.xOffsetAt(from + i )); | 804 xpos[i] = SkFloatToScalar(point.x() + glyphBuffer.xOffsetAt(from + i )); |
| 852 | 805 |
| 853 paintGlyphsHorizontal(gc, font, glyphBuffer.glyphs(from), numGlyphs, xpo s, | 806 paintGlyphsHorizontal(gc, font, glyphBuffer.glyphs(from), numGlyphs, xpo s, |
| 854 SkFloatToScalar(point.y()), textRect); | 807 SkFloatToScalar(point.y()), textRect); |
| 855 return; | 808 return; |
| 856 } | 809 } |
| 857 | 810 |
| 811 bool drawVertically = font->platformData().orientation() == Vertical && font ->verticalData(); | |
| 812 | |
| 813 AffineTransform savedMatrix = gc->getCTM(); | |
|
fs
2014/12/03 09:40:39
In https://codereview.chromium.org/748863004/ this
| |
| 814 if (drawVertically) { | |
| 815 gc->concatCTM(AffineTransform(0, -1, 1, 0, point.x(), point.y())); | |
| 816 gc->concatCTM(AffineTransform(1, 0, 0, 1, -point.x(), -point.y())); | |
| 817 } | |
| 818 | |
| 819 const float verticalBaselineXOffset = drawVertically ? SkFloatToScalar(font- >fontMetrics().floatAscent() - font->fontMetrics().floatAscent(IdeographicBaseli ne)) : 0; | |
| 820 | |
| 858 ASSERT(glyphBuffer.hasVerticalOffsets()); | 821 ASSERT(glyphBuffer.hasVerticalOffsets()); |
| 859 SkAutoSTMalloc<32, SkPoint> storage(numGlyphs); | 822 SkAutoSTMalloc<32, SkPoint> storage(numGlyphs); |
| 860 SkPoint* pos = storage.get(); | 823 SkPoint* pos = storage.get(); |
| 861 for (unsigned i = 0; i < numGlyphs; i++) { | 824 for (unsigned i = 0; i < numGlyphs; i++) { |
| 862 pos[i].set( | 825 pos[i].set( |
| 863 SkFloatToScalar(point.x() + glyphBuffer.xOffsetAt(from + i)), | 826 SkFloatToScalar(point.x() + verticalBaselineXOffset + glyphBuffer.xO ffsetAt(from + i)), |
| 864 SkFloatToScalar(point.y() + glyphBuffer.yOffsetAt(from + i))); | 827 SkFloatToScalar(point.y() + glyphBuffer.yOffsetAt(from + i))); |
| 865 } | 828 } |
| 866 | 829 |
| 867 paintGlyphs(gc, font, glyphBuffer.glyphs(from), numGlyphs, pos, textRect); | 830 paintGlyphs(gc, font, glyphBuffer.glyphs(from), numGlyphs, pos, textRect); |
| 831 | |
| 832 if (drawVertically) { | |
| 833 gc->setCTM(savedMatrix); | |
| 834 } | |
| 868 } | 835 } |
| 869 | 836 |
| 870 void Font::drawTextBlob(GraphicsContext* gc, const SkTextBlob* blob, const SkPoi nt& origin) const | 837 void Font::drawTextBlob(GraphicsContext* gc, const SkTextBlob* blob, const SkPoi nt& origin) const |
| 871 { | 838 { |
| 872 ASSERT(RuntimeEnabledFeatures::textBlobEnabled()); | 839 ASSERT(RuntimeEnabledFeatures::textBlobEnabled()); |
| 873 | 840 |
| 874 TextDrawingModeFlags textMode = gc->textDrawingMode(); | 841 TextDrawingModeFlags textMode = gc->textDrawingMode(); |
| 875 if (textMode & TextModeFill) | 842 if (textMode & TextModeFill) |
| 876 gc->drawTextBlob(blob, origin, gc->fillPaint()); | 843 gc->drawTextBlob(blob, origin, gc->fillPaint()); |
| 877 | 844 |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 914 HarfBuzzShaper shaper(this, run); | 881 HarfBuzzShaper shaper(this, run); |
| 915 if (!shaper.shape()) | 882 if (!shaper.shape()) |
| 916 return FloatRect(); | 883 return FloatRect(); |
| 917 return shaper.selectionRect(point, height, from, to); | 884 return shaper.selectionRect(point, height, from, to); |
| 918 } | 885 } |
| 919 | 886 |
| 920 void Font::drawGlyphBuffer(GraphicsContext* context, | 887 void Font::drawGlyphBuffer(GraphicsContext* context, |
| 921 const TextRunPaintInfo& runInfo, const GlyphBuffer& glyphBuffer, | 888 const TextRunPaintInfo& runInfo, const GlyphBuffer& glyphBuffer, |
| 922 const FloatPoint& point) const | 889 const FloatPoint& point) const |
| 923 { | 890 { |
| 891 if (!glyphBuffer.size()) | |
| 892 return; | |
| 893 | |
| 924 // Draw each contiguous run of glyphs that use the same font data. | 894 // Draw each contiguous run of glyphs that use the same font data. |
| 925 const SimpleFontData* fontData = glyphBuffer.fontDataAt(0); | 895 const SimpleFontData* fontData = glyphBuffer.fontDataAt(0); |
| 926 unsigned lastFrom = 0; | 896 unsigned lastFrom = 0; |
| 927 unsigned nextGlyph; | 897 unsigned nextGlyph; |
| 928 | 898 |
| 929 for (nextGlyph = 0; nextGlyph < glyphBuffer.size(); ++nextGlyph) { | 899 for (nextGlyph = 0; nextGlyph < glyphBuffer.size(); ++nextGlyph) { |
| 930 const SimpleFontData* nextFontData = glyphBuffer.fontDataAt(nextGlyph); | 900 const SimpleFontData* nextFontData = glyphBuffer.fontDataAt(nextGlyph); |
| 931 | 901 |
| 932 if (nextFontData != fontData) { | 902 if (nextFontData != fontData) { |
| 933 drawGlyphs(context, fontData, glyphBuffer, lastFrom, nextGlyph - las tFrom, point, | 903 drawGlyphs(context, fontData, glyphBuffer, lastFrom, nextGlyph - las tFrom, point, |
| 934 runInfo.bounds); | 904 runInfo.bounds); |
| 935 | 905 |
| 936 lastFrom = nextGlyph; | 906 lastFrom = nextGlyph; |
| 937 fontData = nextFontData; | 907 fontData = nextFontData; |
| 938 } | 908 } |
| 939 } | 909 } |
| 940 | 910 |
| 941 drawGlyphs(context, fontData, glyphBuffer, lastFrom, nextGlyph - lastFrom, p oint, | 911 drawGlyphs(context, fontData, glyphBuffer, lastFrom, nextGlyph - lastFrom, p oint, |
| 942 runInfo.bounds); | 912 runInfo.bounds); |
| 943 } | 913 } |
| 944 | 914 |
| 945 inline static float offsetToMiddleOfGlyph(const SimpleFontData* fontData, Glyph glyph) | 915 inline static float offsetToMiddleOfGlyph(const SimpleFontData* fontData, Glyph glyph, FontOrientation orientation = Horizontal) |
| 946 { | 916 { |
| 947 if (fontData->platformData().orientation() == Horizontal) { | 917 FloatRect bounds = fontData->boundsForGlyph(glyph); |
| 948 FloatRect bounds = fontData->boundsForGlyph(glyph); | 918 if (orientation == Horizontal) |
| 949 return bounds.x() + bounds.width() / 2; | 919 return bounds.x() + bounds.width() / 2; |
| 950 } | 920 return bounds.y() + bounds.height() / 2; |
| 951 // FIXME: Use glyph bounds once they make sense for vertical fonts. | |
| 952 return fontData->widthForGlyph(glyph) / 2; | |
| 953 } | 921 } |
| 954 | 922 |
| 955 void Font::drawEmphasisMarks(GraphicsContext* context, const TextRunPaintInfo& r unInfo, const GlyphBuffer& glyphBuffer, const AtomicString& mark, const FloatPoi nt& point) const | 923 void Font::drawEmphasisMarks(GraphicsContext* context, const TextRunPaintInfo& r unInfo, const GlyphBuffer& glyphBuffer, const AtomicString& mark, const FloatPoi nt& point) const |
| 956 { | 924 { |
| 957 FontCachePurgePreventer purgePreventer; | 925 FontCachePurgePreventer purgePreventer; |
| 958 | 926 |
| 959 GlyphData markGlyphData; | 927 GlyphData markGlyphData; |
| 960 if (!getEmphasisMarkGlyphData(mark, markGlyphData)) | 928 if (!getEmphasisMarkGlyphData(mark, markGlyphData)) |
| 961 return; | 929 return; |
| 962 | 930 |
| 963 const SimpleFontData* markFontData = markGlyphData.fontData; | 931 const SimpleFontData* markFontData = markGlyphData.fontData; |
| 964 ASSERT(markFontData); | 932 ASSERT(markFontData); |
| 965 if (!markFontData) | 933 if (!markFontData) |
| 966 return; | 934 return; |
| 967 | 935 |
| 968 GlyphBuffer markBuffer; | 936 GlyphBuffer markBuffer; |
| 969 float midMarkOffset = offsetToMiddleOfGlyph(markFontData, markGlyphData.glyp h); | 937 bool drawVertically = markFontData->platformData().orientation() == Vertical && markFontData->verticalData(); |
| 970 for (unsigned i = 0; i < glyphBuffer.size(); ++i) { | 938 for (unsigned i = 0; i < glyphBuffer.size(); ++i) { |
| 971 // Skip marks for suppressed glyphs. | 939 // Skip marks for suppressed glyphs. |
| 972 if (!glyphBuffer.glyphAt(i)) | 940 if (!glyphBuffer.glyphAt(i)) |
| 973 continue; | 941 continue; |
| 974 | 942 |
| 975 // We want the middle of the emphasis mark aligned with the middle of th e glyph. | 943 // We want the middle of the emphasis mark aligned with the middle of th e glyph. |
| 976 // The input offsets are already adjusted to point to the middle of the glyph, so all | 944 // The input offsets are already adjusted to point to the middle of the glyph, so all |
| 977 // is left to do is adjust for 1/2 mark width. | 945 // is left to do is adjust for 1/2 mark width. |
| 978 // FIXME: we could avoid this by passing some additional info to the sha per, | 946 // FIXME: we could avoid this by passing some additional info to the sha per, |
| 979 // and perform all adjustments at buffer build time. | 947 // and perform all adjustments at buffer build time. |
| 980 markBuffer.add(markGlyphData.glyph, markFontData, glyphBuffer.xOffsetAt( i) - midMarkOffset); | 948 if (!drawVertically) { |
| 949 markBuffer.add(markGlyphData.glyph, markFontData, glyphBuffer.xOffse tAt(i) - offsetToMiddleOfGlyph(markFontData, markGlyphData.glyph)); | |
| 950 } else { | |
| 951 markBuffer.add(markGlyphData.glyph, markFontData, FloatPoint(- offse tToMiddleOfGlyph(markFontData, markGlyphData.glyph), | |
| 952 glyphBuffer.xOffsetAt(i) - offsetToMiddleOfGlyph(markFontData, m arkGlyphData.glyph, Vertical))); | |
| 953 } | |
| 981 } | 954 } |
| 982 | 955 |
| 983 drawGlyphBuffer(context, runInfo, markBuffer, point); | 956 drawGlyphBuffer(context, runInfo, markBuffer, point); |
| 984 } | 957 } |
| 985 | 958 |
| 986 float Font::floatWidthForSimpleText(const TextRun& run, HashSet<const SimpleFont Data*>* fallbackFonts, IntRectExtent* glyphBounds) const | 959 float Font::floatWidthForSimpleText(const TextRun& run, HashSet<const SimpleFont Data*>* fallbackFonts, IntRectExtent* glyphBounds) const |
| 987 { | 960 { |
| 988 SimpleShaper::GlyphBounds bounds; | 961 SimpleShaper::GlyphBounds bounds; |
| 989 SimpleShaper shaper(this, run, fallbackFonts, glyphBounds ? &bounds : 0); | 962 SimpleShaper shaper(this, run, fallbackFonts, glyphBounds ? &bounds : 0); |
| 990 shaper.advance(run.length()); | 963 shaper.advance(run.length()); |
| (...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1059 if (delta <= 0) | 1032 if (delta <= 0) |
| 1060 break; | 1033 break; |
| 1061 } | 1034 } |
| 1062 } | 1035 } |
| 1063 } | 1036 } |
| 1064 | 1037 |
| 1065 return offset; | 1038 return offset; |
| 1066 } | 1039 } |
| 1067 | 1040 |
| 1068 } // namespace blink | 1041 } // namespace blink |
| OLD | NEW |