| 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 79 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 90 // being reasonably safe (because inherited fonts in the render tree pick up
the new | 90 // being reasonably safe (because inherited fonts in the render tree pick up
the new |
| 91 // style anyway. Other copies are transient, e.g., the state in the Graphics
Context, and | 91 // style anyway. Other copies are transient, e.g., the state in the Graphics
Context, and |
| 92 // won't stick around long enough to get you in trouble). Still, this is pre
tty disgusting, | 92 // won't stick around long enough to get you in trouble). Still, this is pre
tty disgusting, |
| 93 // and could eventually be rectified by using RefPtrs for Fonts themselves. | 93 // and could eventually be rectified by using RefPtrs for Fonts themselves. |
| 94 if (!m_fontFallbackList) | 94 if (!m_fontFallbackList) |
| 95 m_fontFallbackList = FontFallbackList::create(); | 95 m_fontFallbackList = FontFallbackList::create(); |
| 96 m_fontFallbackList->invalidate(fontSelector); | 96 m_fontFallbackList->invalidate(fontSelector); |
| 97 } | 97 } |
| 98 | 98 |
| 99 float Font::buildGlyphBuffer(const TextRunPaintInfo& runInfo, GlyphBuffer& glyph
Buffer, | 99 float Font::buildGlyphBuffer(const TextRunPaintInfo& runInfo, GlyphBuffer& glyph
Buffer, |
| 100 ForTextEmphasisOrNot forTextEmphasis) const | 100 const GlyphData* emphasisData) const |
| 101 { | 101 { |
| 102 if (codePath(runInfo) == ComplexPath) { | 102 if (codePath(runInfo) == ComplexPath) { |
| 103 HarfBuzzShaper shaper(this, runInfo.run, (forTextEmphasis == ForTextEmph
asis) | 103 HarfBuzzShaper shaper(this, runInfo.run, emphasisData); |
| 104 ? HarfBuzzShaper::ForTextEmphasis : HarfBuzzShaper::NotForTextEmphas
is); | |
| 105 shaper.setDrawRange(runInfo.from, runInfo.to); | 104 shaper.setDrawRange(runInfo.from, runInfo.to); |
| 106 shaper.shape(&glyphBuffer); | 105 shaper.shape(&glyphBuffer); |
| 107 return shaper.totalWidth(); | 106 return shaper.totalWidth(); |
| 108 } | 107 } |
| 109 | 108 |
| 110 SimpleShaper shaper(this, runInfo.run, nullptr /* fallbackFonts */, | 109 SimpleShaper shaper(this, runInfo.run, emphasisData, nullptr /* fallbackFont
s */, nullptr); |
| 111 nullptr, forTextEmphasis); | |
| 112 shaper.advance(runInfo.from); | 110 shaper.advance(runInfo.from); |
| 113 shaper.advance(runInfo.to, &glyphBuffer); | 111 shaper.advance(runInfo.to, &glyphBuffer); |
| 114 float width = shaper.runWidthSoFar(); | 112 float width = shaper.runWidthSoFar(); |
| 115 | 113 |
| 116 if (runInfo.run.rtl()) { | 114 if (runInfo.run.rtl()) { |
| 117 // Glyphs are shaped & stored in RTL advance order - reverse them for LT
R drawing. | 115 // Glyphs are shaped & stored in RTL advance order - reverse them for LT
R drawing. |
| 118 shaper.advance(runInfo.run.length()); | 116 shaper.advance(runInfo.run.length()); |
| 119 glyphBuffer.reverseForSimpleRTL(width, shaper.runWidthSoFar()); | 117 glyphBuffer.reverseForSimpleRTL(width, shaper.runWidthSoFar()); |
| 120 } | 118 } |
| 121 | 119 |
| (...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 183 drawGlyphBuffer(context, runInfo, glyphBuffer, point); | 181 drawGlyphBuffer(context, runInfo, glyphBuffer, point); |
| 184 | 182 |
| 185 return totalAdvance; | 183 return totalAdvance; |
| 186 } | 184 } |
| 187 | 185 |
| 188 void Font::drawEmphasisMarks(GraphicsContext* context, const TextRunPaintInfo& r
unInfo, const AtomicString& mark, const FloatPoint& point) const | 186 void Font::drawEmphasisMarks(GraphicsContext* context, const TextRunPaintInfo& r
unInfo, const AtomicString& mark, const FloatPoint& point) const |
| 189 { | 187 { |
| 190 if (shouldSkipDrawing()) | 188 if (shouldSkipDrawing()) |
| 191 return; | 189 return; |
| 192 | 190 |
| 191 FontCachePurgePreventer purgePreventer; |
| 192 |
| 193 GlyphData emphasisGlyphData; |
| 194 if (!getEmphasisMarkGlyphData(mark, emphasisGlyphData)) |
| 195 return; |
| 196 |
| 197 ASSERT(emphasisGlyphData.fontData); |
| 198 if (!emphasisGlyphData.fontData) |
| 199 return; |
| 200 |
| 193 GlyphBuffer glyphBuffer; | 201 GlyphBuffer glyphBuffer; |
| 194 buildGlyphBuffer(runInfo, glyphBuffer, ForTextEmphasis); | 202 buildGlyphBuffer(runInfo, glyphBuffer, &emphasisGlyphData); |
| 195 | 203 |
| 196 if (glyphBuffer.isEmpty()) | 204 if (glyphBuffer.isEmpty()) |
| 197 return; | 205 return; |
| 198 | 206 |
| 199 drawEmphasisMarks(context, runInfo, glyphBuffer, mark, point); | 207 drawGlyphBuffer(context, runInfo, glyphBuffer, point); |
| 200 } | 208 } |
| 201 | 209 |
| 202 static inline void updateGlyphOverflowFromBounds(const IntRectOutsets& glyphBoun
ds, | 210 static inline void updateGlyphOverflowFromBounds(const IntRectOutsets& glyphBoun
ds, |
| 203 const FontMetrics& fontMetrics, GlyphOverflow* glyphOverflow) | 211 const FontMetrics& fontMetrics, GlyphOverflow* glyphOverflow) |
| 204 { | 212 { |
| 205 glyphOverflow->top = std::max<int>(glyphOverflow->top, | 213 glyphOverflow->top = std::max<int>(glyphOverflow->top, |
| 206 glyphBounds.top() - (glyphOverflow->computeBounds ? 0 : fontMetrics.asce
nt())); | 214 glyphBounds.top() - (glyphOverflow->computeBounds ? 0 : fontMetrics.asce
nt())); |
| 207 glyphOverflow->bottom = std::max<int>(glyphOverflow->bottom, | 215 glyphOverflow->bottom = std::max<int>(glyphOverflow->bottom, |
| 208 glyphBounds.bottom() - (glyphOverflow->computeBounds ? 0 : fontMetrics.d
escent())); | 216 glyphBounds.bottom() - (glyphOverflow->computeBounds ? 0 : fontMetrics.d
escent())); |
| 209 glyphOverflow->left = glyphBounds.left(); | 217 glyphOverflow->left = glyphBounds.left(); |
| (...skipping 550 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 760 SkPaint paint = gc->strokePaint(); | 768 SkPaint paint = gc->strokePaint(); |
| 761 if (textMode & TextModeFill) | 769 if (textMode & TextModeFill) |
| 762 paint.setLooper(0); | 770 paint.setLooper(0); |
| 763 gc->drawTextBlob(blob, origin, paint); | 771 gc->drawTextBlob(blob, origin, paint); |
| 764 } | 772 } |
| 765 } | 773 } |
| 766 | 774 |
| 767 float Font::floatWidthForComplexText(const TextRun& run, HashSet<const SimpleFon
tData*>* fallbackFonts, IntRectOutsets* glyphBounds) const | 775 float Font::floatWidthForComplexText(const TextRun& run, HashSet<const SimpleFon
tData*>* fallbackFonts, IntRectOutsets* glyphBounds) const |
| 768 { | 776 { |
| 769 FloatRect bounds; | 777 FloatRect bounds; |
| 770 HarfBuzzShaper shaper(this, run, HarfBuzzShaper::NotForTextEmphasis, fallbac
kFonts, glyphBounds ? &bounds : 0); | 778 HarfBuzzShaper shaper(this, run, nullptr, fallbackFonts, glyphBounds ? &boun
ds : 0); |
| 771 if (!shaper.shape()) | 779 if (!shaper.shape()) |
| 772 return 0; | 780 return 0; |
| 773 | 781 |
| 774 glyphBounds->setTop(ceilf(-bounds.y())); | 782 glyphBounds->setTop(ceilf(-bounds.y())); |
| 775 glyphBounds->setBottom(ceilf(bounds.maxY())); | 783 glyphBounds->setBottom(ceilf(bounds.maxY())); |
| 776 glyphBounds->setLeft(std::max<int>(0, ceilf(-bounds.x()))); | 784 glyphBounds->setLeft(std::max<int>(0, ceilf(-bounds.x()))); |
| 777 glyphBounds->setRight(std::max<int>(0, ceilf(bounds.maxX() - shaper.totalWid
th()))); | 785 glyphBounds->setRight(std::max<int>(0, ceilf(bounds.maxX() - shaper.totalWid
th()))); |
| 778 | 786 |
| 779 return shaper.totalWidth(); | 787 return shaper.totalWidth(); |
| 780 } | 788 } |
| (...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 820 | 828 |
| 821 lastFrom = nextGlyph; | 829 lastFrom = nextGlyph; |
| 822 fontData = nextFontData; | 830 fontData = nextFontData; |
| 823 } | 831 } |
| 824 } | 832 } |
| 825 | 833 |
| 826 drawGlyphs(context, fontData, glyphBuffer, lastFrom, nextGlyph - lastFrom, p
oint, | 834 drawGlyphs(context, fontData, glyphBuffer, lastFrom, nextGlyph - lastFrom, p
oint, |
| 827 runInfo.bounds); | 835 runInfo.bounds); |
| 828 } | 836 } |
| 829 | 837 |
| 830 inline static float offsetToMiddleOfGlyph(const SimpleFontData* fontData, Glyph
glyph, FontOrientation orientation = Horizontal) | |
| 831 { | |
| 832 FloatRect bounds = fontData->boundsForGlyph(glyph); | |
| 833 if (orientation == Horizontal) | |
| 834 return bounds.x() + bounds.width() / 2; | |
| 835 return bounds.y() + bounds.height() / 2; | |
| 836 } | |
| 837 | |
| 838 void Font::drawEmphasisMarks(GraphicsContext* context, const TextRunPaintInfo& r
unInfo, const GlyphBuffer& glyphBuffer, const AtomicString& mark, const FloatPoi
nt& point) const | |
| 839 { | |
| 840 FontCachePurgePreventer purgePreventer; | |
| 841 | |
| 842 GlyphData markGlyphData; | |
| 843 if (!getEmphasisMarkGlyphData(mark, markGlyphData)) | |
| 844 return; | |
| 845 | |
| 846 const SimpleFontData* markFontData = markGlyphData.fontData; | |
| 847 ASSERT(markFontData); | |
| 848 if (!markFontData) | |
| 849 return; | |
| 850 | |
| 851 GlyphBuffer markBuffer; | |
| 852 bool drawVertically = markFontData->platformData().orientation() == Vertical
&& markFontData->verticalData(); | |
| 853 for (unsigned i = 0; i < glyphBuffer.size(); ++i) { | |
| 854 // Skip marks for suppressed glyphs. | |
| 855 if (!glyphBuffer.glyphAt(i)) | |
| 856 continue; | |
| 857 | |
| 858 // We want the middle of the emphasis mark aligned with the middle of th
e glyph. | |
| 859 // The input offsets are already adjusted to point to the middle of the
glyph, so all | |
| 860 // is left to do is adjust for 1/2 mark width. | |
| 861 // FIXME: we could avoid this by passing some additional info to the sha
per, | |
| 862 // and perform all adjustments at buffer build time. | |
| 863 if (!drawVertically) { | |
| 864 markBuffer.add(markGlyphData.glyph, markFontData, glyphBuffer.xOffse
tAt(i) - offsetToMiddleOfGlyph(markFontData, markGlyphData.glyph)); | |
| 865 } else { | |
| 866 markBuffer.add(markGlyphData.glyph, markFontData, FloatPoint(- offse
tToMiddleOfGlyph(markFontData, markGlyphData.glyph), | |
| 867 glyphBuffer.xOffsetAt(i) - offsetToMiddleOfGlyph(markFontData, m
arkGlyphData.glyph, Vertical))); | |
| 868 } | |
| 869 } | |
| 870 | |
| 871 drawGlyphBuffer(context, runInfo, markBuffer, point); | |
| 872 } | |
| 873 | |
| 874 float Font::floatWidthForSimpleText(const TextRun& run, HashSet<const SimpleFont
Data*>* fallbackFonts, IntRectOutsets* glyphBounds) const | 838 float Font::floatWidthForSimpleText(const TextRun& run, HashSet<const SimpleFont
Data*>* fallbackFonts, IntRectOutsets* glyphBounds) const |
| 875 { | 839 { |
| 876 FloatRect bounds; | 840 FloatRect bounds; |
| 877 SimpleShaper shaper(this, run, fallbackFonts, glyphBounds ? &bounds : 0); | 841 SimpleShaper shaper(this, run, nullptr, fallbackFonts, glyphBounds ? &bounds
: 0); |
| 878 shaper.advance(run.length()); | 842 shaper.advance(run.length()); |
| 879 float runWidth = shaper.runWidthSoFar(); | 843 float runWidth = shaper.runWidthSoFar(); |
| 880 | 844 |
| 881 if (glyphBounds) { | 845 if (glyphBounds) { |
| 882 glyphBounds->setTop(ceilf(-bounds.y())); | 846 glyphBounds->setTop(ceilf(-bounds.y())); |
| 883 glyphBounds->setBottom(ceilf(bounds.maxY())); | 847 glyphBounds->setBottom(ceilf(bounds.maxY())); |
| 884 glyphBounds->setLeft(std::max<int>(0, ceilf(-bounds.x()))); | 848 glyphBounds->setLeft(std::max<int>(0, ceilf(-bounds.x()))); |
| 885 glyphBounds->setRight(std::max<int>(0, ceilf(bounds.maxX() - runWidth)))
; | 849 glyphBounds->setRight(std::max<int>(0, ceilf(bounds.maxX() - runWidth)))
; |
| 886 } | 850 } |
| 887 return runWidth; | 851 return runWidth; |
| 888 } | 852 } |
| 889 | 853 |
| 890 FloatRect Font::selectionRectForSimpleText(const TextRun& run, const FloatPoint&
point, int h, int from, int to, bool accountForGlyphBounds) const | 854 FloatRect Font::selectionRectForSimpleText(const TextRun& run, const FloatPoint&
point, int h, int from, int to, bool accountForGlyphBounds) const |
| 891 { | 855 { |
| 892 FloatRect bounds; | 856 FloatRect bounds; |
| 893 SimpleShaper shaper(this, run, 0, accountForGlyphBounds ? &bounds : 0); | 857 SimpleShaper shaper(this, run, nullptr, nullptr, accountForGlyphBounds ? &bo
unds : nullptr); |
| 894 shaper.advance(from); | 858 shaper.advance(from); |
| 895 float fromX = shaper.runWidthSoFar(); | 859 float fromX = shaper.runWidthSoFar(); |
| 896 shaper.advance(to); | 860 shaper.advance(to); |
| 897 float toX = shaper.runWidthSoFar(); | 861 float toX = shaper.runWidthSoFar(); |
| 898 | 862 |
| 899 if (run.rtl()) { | 863 if (run.rtl()) { |
| 900 shaper.advance(run.length()); | 864 shaper.advance(run.length()); |
| 901 float totalWidth = shaper.runWidthSoFar(); | 865 float totalWidth = shaper.runWidthSoFar(); |
| 902 float beforeWidth = fromX; | 866 float beforeWidth = fromX; |
| 903 float afterWidth = toX; | 867 float afterWidth = toX; |
| (...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 947 if (delta <= 0) | 911 if (delta <= 0) |
| 948 break; | 912 break; |
| 949 } | 913 } |
| 950 } | 914 } |
| 951 } | 915 } |
| 952 | 916 |
| 953 return offset; | 917 return offset; |
| 954 } | 918 } |
| 955 | 919 |
| 956 } // namespace blink | 920 } // namespace blink |
| OLD | NEW |