| 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 325 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 336 CodePath Font::codePath(const TextRunPaintInfo& runInfo) const | 336 CodePath Font::codePath(const TextRunPaintInfo& runInfo) const |
| 337 { | 337 { |
| 338 const TextRun& run = runInfo.run; | 338 const TextRun& run = runInfo.run; |
| 339 | 339 |
| 340 if (fontDescription().typesettingFeatures() && (runInfo.from || runInfo.to !
= run.length())) | 340 if (fontDescription().typesettingFeatures() && (runInfo.from || runInfo.to !
= run.length())) |
| 341 return ComplexPath; | 341 return ComplexPath; |
| 342 | 342 |
| 343 if (m_fontDescription.featureSettings() && m_fontDescription.featureSettings
()->size() > 0 && m_fontDescription.letterSpacing() == 0) | 343 if (m_fontDescription.featureSettings() && m_fontDescription.featureSettings
()->size() > 0 && m_fontDescription.letterSpacing() == 0) |
| 344 return ComplexPath; | 344 return ComplexPath; |
| 345 | 345 |
| 346 if (m_fontDescription.orientation() == Vertical) |
| 347 return ComplexPath; |
| 348 |
| 346 if (m_fontDescription.widthVariant() != RegularWidth) | 349 if (m_fontDescription.widthVariant() != RegularWidth) |
| 347 return ComplexPath; | 350 return ComplexPath; |
| 348 | 351 |
| 349 if (run.length() > 1 && fontDescription().typesettingFeatures()) | 352 if (run.length() > 1 && fontDescription().typesettingFeatures()) |
| 350 return ComplexPath; | 353 return ComplexPath; |
| 351 | 354 |
| 352 // FIXME: This really shouldn't be needed but for some reason the | 355 // FIXME: This really shouldn't be needed but for some reason the |
| 353 // TextRendering setting doesn't propagate to typesettingFeatures in time | 356 // TextRendering setting doesn't propagate to typesettingFeatures in time |
| 354 // for the prefs width calculation. | 357 // for the prefs width calculation. |
| 355 if (fontDescription().textRendering() == OptimizeLegibility || fontDescripti
on().textRendering() == GeometricPrecision) | 358 if (fontDescription().textRendering() == OptimizeLegibility || fontDescripti
on().textRendering() == GeometricPrecision) |
| (...skipping 342 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 698 SkPaint paint = textFillPaint(gc, font); | 701 SkPaint paint = textFillPaint(gc, font); |
| 699 gc->drawPosTextH(glyphs, numGlyphs * sizeof(Glyph), xpos, constY, textRe
ct, paint); | 702 gc->drawPosTextH(glyphs, numGlyphs * sizeof(Glyph), xpos, constY, textRe
ct, paint); |
| 700 } | 703 } |
| 701 | 704 |
| 702 if ((textMode & TextModeStroke) && gc->hasStroke()) { | 705 if ((textMode & TextModeStroke) && gc->hasStroke()) { |
| 703 SkPaint paint = textStrokePaint(gc, font, textMode & TextModeFill); | 706 SkPaint paint = textStrokePaint(gc, font, textMode & TextModeFill); |
| 704 gc->drawPosTextH(glyphs, numGlyphs * sizeof(Glyph), xpos, constY, textRe
ct, paint); | 707 gc->drawPosTextH(glyphs, numGlyphs * sizeof(Glyph), xpos, constY, textRe
ct, paint); |
| 705 } | 708 } |
| 706 } | 709 } |
| 707 | 710 |
| 708 void Font::paintGlyphsVertical(GraphicsContext* gc, const SimpleFontData* font, | |
| 709 const GlyphBuffer& glyphBuffer, unsigned from, unsigned numGlyphs, const Flo
atPoint& point, | |
| 710 const FloatRect& textRect) const | |
| 711 { | |
| 712 const OpenTypeVerticalData* verticalData = font->verticalData(); | |
| 713 | |
| 714 SkAutoSTMalloc<32, SkPoint> storage(numGlyphs); | |
| 715 SkPoint* pos = storage.get(); | |
| 716 | |
| 717 // Bend over backwards to preserve legacy rounding. | |
| 718 float initialAdvance = glyphBuffer.xOffsetAt(from); | |
| 719 FloatPoint adjustedPoint(point.x() + initialAdvance, point.y()); | |
| 720 | |
| 721 GraphicsContextStateSaver stateSaver(*gc); | |
| 722 gc->concatCTM(AffineTransform(0, -1, 1, 0, adjustedPoint.x(), adjustedPoint.
y())); | |
| 723 gc->concatCTM(AffineTransform(1, 0, 0, 1, -adjustedPoint.x(), -adjustedPoint
.y())); | |
| 724 | |
| 725 const unsigned kMaxBufferLength = 256; | |
| 726 Vector<FloatPoint, kMaxBufferLength> translations; | |
| 727 | |
| 728 const FontMetrics& metrics = font->fontMetrics(); | |
| 729 float verticalOriginX = adjustedPoint.x() + metrics.floatAscent() - metrics.
floatAscent(IdeographicBaseline); | |
| 730 | |
| 731 unsigned glyphIndex = 0; | |
| 732 while (glyphIndex < numGlyphs) { | |
| 733 unsigned chunkLength = std::min(kMaxBufferLength, numGlyphs - glyphIndex
); | |
| 734 | |
| 735 const Glyph* glyphs = glyphBuffer.glyphs(from + glyphIndex); | |
| 736 | |
| 737 translations.resize(chunkLength); | |
| 738 verticalData->getVerticalTranslationsForGlyphs(font, glyphs, chunkLength
, | |
| 739 reinterpret_cast<float*>(&translations[0])); | |
| 740 | |
| 741 for (unsigned i = 0; i < chunkLength; ++i, ++glyphIndex) { | |
| 742 SkScalar x = verticalOriginX + lroundf(translations[i].x()); | |
| 743 SkScalar y = adjustedPoint.y() - SkIntToScalar( | |
| 744 -lroundf(glyphBuffer.xOffsetAt(from + glyphIndex) - initialAdvan
ce - translations[i].y())); | |
| 745 pos[i].set(x, y); | |
| 746 } | |
| 747 paintGlyphs(gc, font, glyphs, chunkLength, pos, textRect); | |
| 748 } | |
| 749 } | |
| 750 | |
| 751 void Font::drawGlyphs(GraphicsContext* gc, const SimpleFontData* font, | 711 void Font::drawGlyphs(GraphicsContext* gc, const SimpleFontData* font, |
| 752 const GlyphBuffer& glyphBuffer, unsigned from, unsigned numGlyphs, | 712 const GlyphBuffer& glyphBuffer, unsigned from, unsigned numGlyphs, |
| 753 const FloatPoint& point, const FloatRect& textRect) const | 713 const FloatPoint& point, const FloatRect& textRect) const |
| 754 { | 714 { |
| 755 ASSERT(glyphBuffer.size() >= from + numGlyphs); | 715 ASSERT(glyphBuffer.size() >= from + numGlyphs); |
| 756 | 716 |
| 757 if (font->platformData().orientation() == Vertical && font->verticalData())
{ | |
| 758 paintGlyphsVertical(gc, font, glyphBuffer, from, numGlyphs, point, textR
ect); | |
| 759 return; | |
| 760 } | |
| 761 | |
| 762 if (!glyphBuffer.hasVerticalOffsets()) { | 717 if (!glyphBuffer.hasVerticalOffsets()) { |
| 763 SkAutoSTMalloc<64, SkScalar> storage(numGlyphs); | 718 SkAutoSTMalloc<64, SkScalar> storage(numGlyphs); |
| 764 SkScalar* xpos = storage.get(); | 719 SkScalar* xpos = storage.get(); |
| 765 for (unsigned i = 0; i < numGlyphs; i++) | 720 for (unsigned i = 0; i < numGlyphs; i++) |
| 766 xpos[i] = SkFloatToScalar(point.x() + glyphBuffer.xOffsetAt(from + i
)); | 721 xpos[i] = SkFloatToScalar(point.x() + glyphBuffer.xOffsetAt(from + i
)); |
| 767 | 722 |
| 768 paintGlyphsHorizontal(gc, font, glyphBuffer.glyphs(from), numGlyphs, xpo
s, | 723 paintGlyphsHorizontal(gc, font, glyphBuffer.glyphs(from), numGlyphs, xpo
s, |
| 769 SkFloatToScalar(point.y()), textRect); | 724 SkFloatToScalar(point.y()), textRect); |
| 770 return; | 725 return; |
| 771 } | 726 } |
| 772 | 727 |
| 728 bool drawVertically = font->platformData().orientation() == Vertical && font
->verticalData(); |
| 729 |
| 730 GraphicsContextStateSaver stateSaver(*gc, false); |
| 731 if (drawVertically) { |
| 732 stateSaver.save(); |
| 733 gc->concatCTM(AffineTransform(0, -1, 1, 0, point.x(), point.y())); |
| 734 gc->concatCTM(AffineTransform(1, 0, 0, 1, -point.x(), -point.y())); |
| 735 } |
| 736 |
| 737 const float verticalBaselineXOffset = drawVertically ? SkFloatToScalar(font-
>fontMetrics().floatAscent() - font->fontMetrics().floatAscent(IdeographicBaseli
ne)) : 0; |
| 738 |
| 773 ASSERT(glyphBuffer.hasVerticalOffsets()); | 739 ASSERT(glyphBuffer.hasVerticalOffsets()); |
| 774 SkAutoSTMalloc<32, SkPoint> storage(numGlyphs); | 740 SkAutoSTMalloc<32, SkPoint> storage(numGlyphs); |
| 775 SkPoint* pos = storage.get(); | 741 SkPoint* pos = storage.get(); |
| 776 for (unsigned i = 0; i < numGlyphs; i++) { | 742 for (unsigned i = 0; i < numGlyphs; i++) { |
| 777 pos[i].set( | 743 pos[i].set( |
| 778 SkFloatToScalar(point.x() + glyphBuffer.xOffsetAt(from + i)), | 744 SkFloatToScalar(point.x() + verticalBaselineXOffset + glyphBuffer.xO
ffsetAt(from + i)), |
| 779 SkFloatToScalar(point.y() + glyphBuffer.yOffsetAt(from + i))); | 745 SkFloatToScalar(point.y() + glyphBuffer.yOffsetAt(from + i))); |
| 780 } | 746 } |
| 781 | 747 |
| 782 paintGlyphs(gc, font, glyphBuffer.glyphs(from), numGlyphs, pos, textRect); | 748 paintGlyphs(gc, font, glyphBuffer.glyphs(from), numGlyphs, pos, textRect); |
| 783 } | 749 } |
| 784 | 750 |
| 785 void Font::drawTextBlob(GraphicsContext* gc, const SkTextBlob* blob, const SkPoi
nt& origin) const | 751 void Font::drawTextBlob(GraphicsContext* gc, const SkTextBlob* blob, const SkPoi
nt& origin) const |
| 786 { | 752 { |
| 787 ASSERT(RuntimeEnabledFeatures::textBlobEnabled()); | 753 ASSERT(RuntimeEnabledFeatures::textBlobEnabled()); |
| 788 | 754 |
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 829 HarfBuzzShaper shaper(this, run); | 795 HarfBuzzShaper shaper(this, run); |
| 830 if (!shaper.shape()) | 796 if (!shaper.shape()) |
| 831 return FloatRect(); | 797 return FloatRect(); |
| 832 return shaper.selectionRect(point, height, from, to); | 798 return shaper.selectionRect(point, height, from, to); |
| 833 } | 799 } |
| 834 | 800 |
| 835 void Font::drawGlyphBuffer(GraphicsContext* context, | 801 void Font::drawGlyphBuffer(GraphicsContext* context, |
| 836 const TextRunPaintInfo& runInfo, const GlyphBuffer& glyphBuffer, | 802 const TextRunPaintInfo& runInfo, const GlyphBuffer& glyphBuffer, |
| 837 const FloatPoint& point) const | 803 const FloatPoint& point) const |
| 838 { | 804 { |
| 805 if (!glyphBuffer.size()) |
| 806 return; |
| 807 |
| 839 // Draw each contiguous run of glyphs that use the same font data. | 808 // Draw each contiguous run of glyphs that use the same font data. |
| 840 const SimpleFontData* fontData = glyphBuffer.fontDataAt(0); | 809 const SimpleFontData* fontData = glyphBuffer.fontDataAt(0); |
| 841 unsigned lastFrom = 0; | 810 unsigned lastFrom = 0; |
| 842 unsigned nextGlyph; | 811 unsigned nextGlyph; |
| 843 | 812 |
| 844 for (nextGlyph = 0; nextGlyph < glyphBuffer.size(); ++nextGlyph) { | 813 for (nextGlyph = 0; nextGlyph < glyphBuffer.size(); ++nextGlyph) { |
| 845 const SimpleFontData* nextFontData = glyphBuffer.fontDataAt(nextGlyph); | 814 const SimpleFontData* nextFontData = glyphBuffer.fontDataAt(nextGlyph); |
| 846 | 815 |
| 847 if (nextFontData != fontData) { | 816 if (nextFontData != fontData) { |
| 848 drawGlyphs(context, fontData, glyphBuffer, lastFrom, nextGlyph - las
tFrom, point, | 817 drawGlyphs(context, fontData, glyphBuffer, lastFrom, nextGlyph - las
tFrom, point, |
| 849 runInfo.bounds); | 818 runInfo.bounds); |
| 850 | 819 |
| 851 lastFrom = nextGlyph; | 820 lastFrom = nextGlyph; |
| 852 fontData = nextFontData; | 821 fontData = nextFontData; |
| 853 } | 822 } |
| 854 } | 823 } |
| 855 | 824 |
| 856 drawGlyphs(context, fontData, glyphBuffer, lastFrom, nextGlyph - lastFrom, p
oint, | 825 drawGlyphs(context, fontData, glyphBuffer, lastFrom, nextGlyph - lastFrom, p
oint, |
| 857 runInfo.bounds); | 826 runInfo.bounds); |
| 858 } | 827 } |
| 859 | 828 |
| 860 inline static float offsetToMiddleOfGlyph(const SimpleFontData* fontData, Glyph
glyph) | 829 inline static float offsetToMiddleOfGlyph(const SimpleFontData* fontData, Glyph
glyph, FontOrientation orientation = Horizontal) |
| 861 { | 830 { |
| 862 if (fontData->platformData().orientation() == Horizontal) { | 831 FloatRect bounds = fontData->boundsForGlyph(glyph); |
| 863 FloatRect bounds = fontData->boundsForGlyph(glyph); | 832 if (orientation == Horizontal) |
| 864 return bounds.x() + bounds.width() / 2; | 833 return bounds.x() + bounds.width() / 2; |
| 865 } | 834 return bounds.y() + bounds.height() / 2; |
| 866 // FIXME: Use glyph bounds once they make sense for vertical fonts. | |
| 867 return fontData->widthForGlyph(glyph) / 2; | |
| 868 } | 835 } |
| 869 | 836 |
| 870 void Font::drawEmphasisMarks(GraphicsContext* context, const TextRunPaintInfo& r
unInfo, const GlyphBuffer& glyphBuffer, const AtomicString& mark, const FloatPoi
nt& point) const | 837 void Font::drawEmphasisMarks(GraphicsContext* context, const TextRunPaintInfo& r
unInfo, const GlyphBuffer& glyphBuffer, const AtomicString& mark, const FloatPoi
nt& point) const |
| 871 { | 838 { |
| 872 FontCachePurgePreventer purgePreventer; | 839 FontCachePurgePreventer purgePreventer; |
| 873 | 840 |
| 874 GlyphData markGlyphData; | 841 GlyphData markGlyphData; |
| 875 if (!getEmphasisMarkGlyphData(mark, markGlyphData)) | 842 if (!getEmphasisMarkGlyphData(mark, markGlyphData)) |
| 876 return; | 843 return; |
| 877 | 844 |
| 878 const SimpleFontData* markFontData = markGlyphData.fontData; | 845 const SimpleFontData* markFontData = markGlyphData.fontData; |
| 879 ASSERT(markFontData); | 846 ASSERT(markFontData); |
| 880 if (!markFontData) | 847 if (!markFontData) |
| 881 return; | 848 return; |
| 882 | 849 |
| 883 GlyphBuffer markBuffer; | 850 GlyphBuffer markBuffer; |
| 884 float midMarkOffset = offsetToMiddleOfGlyph(markFontData, markGlyphData.glyp
h); | 851 bool drawVertically = markFontData->platformData().orientation() == Vertical
&& markFontData->verticalData(); |
| 885 for (unsigned i = 0; i < glyphBuffer.size(); ++i) { | 852 for (unsigned i = 0; i < glyphBuffer.size(); ++i) { |
| 886 // Skip marks for suppressed glyphs. | 853 // Skip marks for suppressed glyphs. |
| 887 if (!glyphBuffer.glyphAt(i)) | 854 if (!glyphBuffer.glyphAt(i)) |
| 888 continue; | 855 continue; |
| 889 | 856 |
| 890 // We want the middle of the emphasis mark aligned with the middle of th
e glyph. | 857 // We want the middle of the emphasis mark aligned with the middle of th
e glyph. |
| 891 // The input offsets are already adjusted to point to the middle of the
glyph, so all | 858 // The input offsets are already adjusted to point to the middle of the
glyph, so all |
| 892 // is left to do is adjust for 1/2 mark width. | 859 // is left to do is adjust for 1/2 mark width. |
| 893 // FIXME: we could avoid this by passing some additional info to the sha
per, | 860 // FIXME: we could avoid this by passing some additional info to the sha
per, |
| 894 // and perform all adjustments at buffer build time. | 861 // and perform all adjustments at buffer build time. |
| 895 markBuffer.add(markGlyphData.glyph, markFontData, glyphBuffer.xOffsetAt(
i) - midMarkOffset); | 862 if (!drawVertically) { |
| 863 markBuffer.add(markGlyphData.glyph, markFontData, glyphBuffer.xOffse
tAt(i) - offsetToMiddleOfGlyph(markFontData, markGlyphData.glyph)); |
| 864 } else { |
| 865 markBuffer.add(markGlyphData.glyph, markFontData, FloatPoint(- offse
tToMiddleOfGlyph(markFontData, markGlyphData.glyph), |
| 866 glyphBuffer.xOffsetAt(i) - offsetToMiddleOfGlyph(markFontData, m
arkGlyphData.glyph, Vertical))); |
| 867 } |
| 896 } | 868 } |
| 897 | 869 |
| 898 drawGlyphBuffer(context, runInfo, markBuffer, point); | 870 drawGlyphBuffer(context, runInfo, markBuffer, point); |
| 899 } | 871 } |
| 900 | 872 |
| 901 float Font::floatWidthForSimpleText(const TextRun& run, HashSet<const SimpleFont
Data*>* fallbackFonts, IntRectExtent* glyphBounds) const | 873 float Font::floatWidthForSimpleText(const TextRun& run, HashSet<const SimpleFont
Data*>* fallbackFonts, IntRectExtent* glyphBounds) const |
| 902 { | 874 { |
| 903 SimpleShaper::GlyphBounds bounds; | 875 SimpleShaper::GlyphBounds bounds; |
| 904 SimpleShaper shaper(this, run, fallbackFonts, glyphBounds ? &bounds : 0); | 876 SimpleShaper shaper(this, run, fallbackFonts, glyphBounds ? &bounds : 0); |
| 905 shaper.advance(run.length()); | 877 shaper.advance(run.length()); |
| (...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 974 if (delta <= 0) | 946 if (delta <= 0) |
| 975 break; | 947 break; |
| 976 } | 948 } |
| 977 } | 949 } |
| 978 } | 950 } |
| 979 | 951 |
| 980 return offset; | 952 return offset; |
| 981 } | 953 } |
| 982 | 954 |
| 983 } // namespace blink | 955 } // namespace blink |
| OLD | NEW |