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 |