| 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 81 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 92 // being reasonably safe (because inherited fonts in the render tree pick up
the new | 92 // being reasonably safe (because inherited fonts in the render tree pick up
the new |
| 93 // style anyway. Other copies are transient, e.g., the state in the Graphics
Context, and | 93 // style anyway. Other copies are transient, e.g., the state in the Graphics
Context, and |
| 94 // won't stick around long enough to get you in trouble). Still, this is pre
tty disgusting, | 94 // won't stick around long enough to get you in trouble). Still, this is pre
tty disgusting, |
| 95 // and could eventually be rectified by using RefPtrs for Fonts themselves. | 95 // and could eventually be rectified by using RefPtrs for Fonts themselves. |
| 96 if (!m_fontFallbackList) | 96 if (!m_fontFallbackList) |
| 97 m_fontFallbackList = FontFallbackList::create(); | 97 m_fontFallbackList = FontFallbackList::create(); |
| 98 m_fontFallbackList->invalidate(fontSelector); | 98 m_fontFallbackList->invalidate(fontSelector); |
| 99 } | 99 } |
| 100 | 100 |
| 101 float Font::buildGlyphBuffer(const TextRunPaintInfo& runInfo, GlyphBuffer& glyph
Buffer, | 101 float Font::buildGlyphBuffer(const TextRunPaintInfo& runInfo, GlyphBuffer& glyph
Buffer, |
| 102 ForTextEmphasisOrNot forTextEmphasis) const | 102 const GlyphData* emphasisData) const |
| 103 { | 103 { |
| 104 if (codePath(runInfo) == ComplexPath) { | 104 if (codePath(runInfo) == ComplexPath) { |
| 105 HarfBuzzShaper shaper(this, runInfo.run, (forTextEmphasis == ForTextEmph
asis) | 105 HarfBuzzShaper shaper(this, runInfo.run, emphasisData); |
| 106 ? HarfBuzzShaper::ForTextEmphasis : HarfBuzzShaper::NotForTextEmphas
is); | |
| 107 shaper.setDrawRange(runInfo.from, runInfo.to); | 106 shaper.setDrawRange(runInfo.from, runInfo.to); |
| 108 shaper.shape(&glyphBuffer); | 107 shaper.shape(&glyphBuffer); |
| 109 return shaper.totalWidth(); | 108 return shaper.totalWidth(); |
| 110 } | 109 } |
| 111 | 110 |
| 112 SimpleShaper shaper(this, runInfo.run, nullptr /* fallbackFonts */, | 111 SimpleShaper shaper(this, runInfo.run, emphasisData, nullptr /* fallbackFont
s */, nullptr); |
| 113 nullptr, forTextEmphasis); | |
| 114 shaper.advance(runInfo.from); | 112 shaper.advance(runInfo.from); |
| 115 shaper.advance(runInfo.to, &glyphBuffer); | 113 shaper.advance(runInfo.to, &glyphBuffer); |
| 116 float width = shaper.runWidthSoFar(); | 114 float width = shaper.runWidthSoFar(); |
| 117 | 115 |
| 118 if (runInfo.run.rtl()) { | 116 if (runInfo.run.rtl()) { |
| 119 // Glyphs are shaped & stored in RTL advance order - reverse them for LT
R drawing. | 117 // Glyphs are shaped & stored in RTL advance order - reverse them for LT
R drawing. |
| 120 shaper.advance(runInfo.run.length()); | 118 shaper.advance(runInfo.run.length()); |
| 121 glyphBuffer.reverseForSimpleRTL(width, shaper.runWidthSoFar()); | 119 glyphBuffer.reverseForSimpleRTL(width, shaper.runWidthSoFar()); |
| 122 } | 120 } |
| 123 | 121 |
| (...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 197 } | 195 } |
| 198 | 196 |
| 199 bidiRuns.deleteRuns(); | 197 bidiRuns.deleteRuns(); |
| 200 } | 198 } |
| 201 | 199 |
| 202 void Font::drawEmphasisMarks(GraphicsContext* context, const TextRunPaintInfo& r
unInfo, const AtomicString& mark, const FloatPoint& point) const | 200 void Font::drawEmphasisMarks(GraphicsContext* context, const TextRunPaintInfo& r
unInfo, const AtomicString& mark, const FloatPoint& point) const |
| 203 { | 201 { |
| 204 if (shouldSkipDrawing()) | 202 if (shouldSkipDrawing()) |
| 205 return; | 203 return; |
| 206 | 204 |
| 205 FontCachePurgePreventer purgePreventer; |
| 206 |
| 207 GlyphData emphasisGlyphData; |
| 208 if (!getEmphasisMarkGlyphData(mark, emphasisGlyphData)) |
| 209 return; |
| 210 |
| 211 ASSERT(emphasisGlyphData.fontData); |
| 212 if (!emphasisGlyphData.fontData) |
| 213 return; |
| 214 |
| 207 GlyphBuffer glyphBuffer; | 215 GlyphBuffer glyphBuffer; |
| 208 buildGlyphBuffer(runInfo, glyphBuffer, ForTextEmphasis); | 216 buildGlyphBuffer(runInfo, glyphBuffer, &emphasisGlyphData); |
| 209 | 217 |
| 210 if (glyphBuffer.isEmpty()) | 218 if (glyphBuffer.isEmpty()) |
| 211 return; | 219 return; |
| 212 | 220 |
| 213 drawEmphasisMarks(context, runInfo, glyphBuffer, mark, point); | 221 drawGlyphBuffer(context, runInfo, glyphBuffer, point); |
| 214 } | 222 } |
| 215 | 223 |
| 216 static inline void updateGlyphOverflowFromBounds(const IntRectOutsets& glyphBoun
ds, | 224 static inline void updateGlyphOverflowFromBounds(const IntRectOutsets& glyphBoun
ds, |
| 217 const FontMetrics& fontMetrics, GlyphOverflow* glyphOverflow) | 225 const FontMetrics& fontMetrics, GlyphOverflow* glyphOverflow) |
| 218 { | 226 { |
| 219 glyphOverflow->top = std::max<int>(glyphOverflow->top, | 227 glyphOverflow->top = std::max<int>(glyphOverflow->top, |
| 220 glyphBounds.top() - (glyphOverflow->computeBounds ? 0 : fontMetrics.asce
nt())); | 228 glyphBounds.top() - (glyphOverflow->computeBounds ? 0 : fontMetrics.asce
nt())); |
| 221 glyphOverflow->bottom = std::max<int>(glyphOverflow->bottom, | 229 glyphOverflow->bottom = std::max<int>(glyphOverflow->bottom, |
| 222 glyphBounds.bottom() - (glyphOverflow->computeBounds ? 0 : fontMetrics.d
escent())); | 230 glyphBounds.bottom() - (glyphOverflow->computeBounds ? 0 : fontMetrics.d
escent())); |
| 223 glyphOverflow->left = glyphBounds.left(); | 231 glyphOverflow->left = glyphBounds.left(); |
| (...skipping 550 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 774 SkPaint paint = gc->strokePaint(); | 782 SkPaint paint = gc->strokePaint(); |
| 775 if (textMode & TextModeFill) | 783 if (textMode & TextModeFill) |
| 776 paint.setLooper(0); | 784 paint.setLooper(0); |
| 777 gc->drawTextBlob(blob, origin, paint); | 785 gc->drawTextBlob(blob, origin, paint); |
| 778 } | 786 } |
| 779 } | 787 } |
| 780 | 788 |
| 781 float Font::floatWidthForComplexText(const TextRun& run, HashSet<const SimpleFon
tData*>* fallbackFonts, IntRectOutsets* glyphBounds) const | 789 float Font::floatWidthForComplexText(const TextRun& run, HashSet<const SimpleFon
tData*>* fallbackFonts, IntRectOutsets* glyphBounds) const |
| 782 { | 790 { |
| 783 FloatRect bounds; | 791 FloatRect bounds; |
| 784 HarfBuzzShaper shaper(this, run, HarfBuzzShaper::NotForTextEmphasis, fallbac
kFonts, glyphBounds ? &bounds : 0); | 792 HarfBuzzShaper shaper(this, run, nullptr, fallbackFonts, glyphBounds ? &boun
ds : 0); |
| 785 if (!shaper.shape()) | 793 if (!shaper.shape()) |
| 786 return 0; | 794 return 0; |
| 787 | 795 |
| 788 glyphBounds->setTop(ceilf(-bounds.y())); | 796 glyphBounds->setTop(ceilf(-bounds.y())); |
| 789 glyphBounds->setBottom(ceilf(bounds.maxY())); | 797 glyphBounds->setBottom(ceilf(bounds.maxY())); |
| 790 glyphBounds->setLeft(std::max<int>(0, ceilf(-bounds.x()))); | 798 glyphBounds->setLeft(std::max<int>(0, ceilf(-bounds.x()))); |
| 791 glyphBounds->setRight(std::max<int>(0, ceilf(bounds.maxX() - shaper.totalWid
th()))); | 799 glyphBounds->setRight(std::max<int>(0, ceilf(bounds.maxX() - shaper.totalWid
th()))); |
| 792 | 800 |
| 793 return shaper.totalWidth(); | 801 return shaper.totalWidth(); |
| 794 } | 802 } |
| (...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 846 | 854 |
| 847 lastFrom = nextGlyph; | 855 lastFrom = nextGlyph; |
| 848 fontData = nextFontData; | 856 fontData = nextFontData; |
| 849 } | 857 } |
| 850 } | 858 } |
| 851 | 859 |
| 852 drawGlyphs(context, fontData, glyphBuffer, lastFrom, nextGlyph - lastFrom, p
oint, | 860 drawGlyphs(context, fontData, glyphBuffer, lastFrom, nextGlyph - lastFrom, p
oint, |
| 853 runInfo.bounds); | 861 runInfo.bounds); |
| 854 } | 862 } |
| 855 | 863 |
| 856 inline static float offsetToMiddleOfGlyph(const SimpleFontData* fontData, Glyph
glyph, FontOrientation orientation = Horizontal) | |
| 857 { | |
| 858 FloatRect bounds = fontData->boundsForGlyph(glyph); | |
| 859 if (orientation == Horizontal) | |
| 860 return bounds.x() + bounds.width() / 2; | |
| 861 return bounds.y() + bounds.height() / 2; | |
| 862 } | |
| 863 | |
| 864 void Font::drawEmphasisMarks(GraphicsContext* context, const TextRunPaintInfo& r
unInfo, const GlyphBuffer& glyphBuffer, const AtomicString& mark, const FloatPoi
nt& point) const | |
| 865 { | |
| 866 FontCachePurgePreventer purgePreventer; | |
| 867 | |
| 868 GlyphData markGlyphData; | |
| 869 if (!getEmphasisMarkGlyphData(mark, markGlyphData)) | |
| 870 return; | |
| 871 | |
| 872 const SimpleFontData* markFontData = markGlyphData.fontData; | |
| 873 ASSERT(markFontData); | |
| 874 if (!markFontData) | |
| 875 return; | |
| 876 | |
| 877 GlyphBuffer markBuffer; | |
| 878 bool drawVertically = markFontData->platformData().orientation() == Vertical
&& markFontData->verticalData(); | |
| 879 for (unsigned i = 0; i < glyphBuffer.size(); ++i) { | |
| 880 // Skip marks for suppressed glyphs. | |
| 881 if (!glyphBuffer.glyphAt(i)) | |
| 882 continue; | |
| 883 | |
| 884 // We want the middle of the emphasis mark aligned with the middle of th
e glyph. | |
| 885 // The input offsets are already adjusted to point to the middle of the
glyph, so all | |
| 886 // is left to do is adjust for 1/2 mark width. | |
| 887 // FIXME: we could avoid this by passing some additional info to the sha
per, | |
| 888 // and perform all adjustments at buffer build time. | |
| 889 if (!drawVertically) { | |
| 890 markBuffer.add(markGlyphData.glyph, markFontData, glyphBuffer.xOffse
tAt(i) - offsetToMiddleOfGlyph(markFontData, markGlyphData.glyph)); | |
| 891 } else { | |
| 892 markBuffer.add(markGlyphData.glyph, markFontData, FloatPoint(- offse
tToMiddleOfGlyph(markFontData, markGlyphData.glyph), | |
| 893 glyphBuffer.xOffsetAt(i) - offsetToMiddleOfGlyph(markFontData, m
arkGlyphData.glyph, Vertical))); | |
| 894 } | |
| 895 } | |
| 896 | |
| 897 drawGlyphBuffer(context, runInfo, markBuffer, point); | |
| 898 } | |
| 899 | |
| 900 float Font::floatWidthForSimpleText(const TextRun& run, HashSet<const SimpleFont
Data*>* fallbackFonts, IntRectOutsets* glyphBounds) const | 864 float Font::floatWidthForSimpleText(const TextRun& run, HashSet<const SimpleFont
Data*>* fallbackFonts, IntRectOutsets* glyphBounds) const |
| 901 { | 865 { |
| 902 FloatRect bounds; | 866 FloatRect bounds; |
| 903 SimpleShaper shaper(this, run, fallbackFonts, glyphBounds ? &bounds : 0); | 867 SimpleShaper shaper(this, run, nullptr, fallbackFonts, glyphBounds ? &bounds
: 0); |
| 904 shaper.advance(run.length()); | 868 shaper.advance(run.length()); |
| 905 float runWidth = shaper.runWidthSoFar(); | 869 float runWidth = shaper.runWidthSoFar(); |
| 906 | 870 |
| 907 if (glyphBounds) { | 871 if (glyphBounds) { |
| 908 glyphBounds->setTop(ceilf(-bounds.y())); | 872 glyphBounds->setTop(ceilf(-bounds.y())); |
| 909 glyphBounds->setBottom(ceilf(bounds.maxY())); | 873 glyphBounds->setBottom(ceilf(bounds.maxY())); |
| 910 glyphBounds->setLeft(std::max<int>(0, ceilf(-bounds.x()))); | 874 glyphBounds->setLeft(std::max<int>(0, ceilf(-bounds.x()))); |
| 911 glyphBounds->setRight(std::max<int>(0, ceilf(bounds.maxX() - runWidth)))
; | 875 glyphBounds->setRight(std::max<int>(0, ceilf(bounds.maxX() - runWidth)))
; |
| 912 } | 876 } |
| 913 return runWidth; | 877 return runWidth; |
| 914 } | 878 } |
| 915 | 879 |
| 916 FloatRect Font::selectionRectForSimpleText(const TextRun& run, const FloatPoint&
point, int h, int from, int to, bool accountForGlyphBounds) const | 880 FloatRect Font::selectionRectForSimpleText(const TextRun& run, const FloatPoint&
point, int h, int from, int to, bool accountForGlyphBounds) const |
| 917 { | 881 { |
| 918 FloatRect bounds; | 882 FloatRect bounds; |
| 919 SimpleShaper shaper(this, run, 0, accountForGlyphBounds ? &bounds : 0); | 883 SimpleShaper shaper(this, run, nullptr, nullptr, accountForGlyphBounds ? &bo
unds : nullptr); |
| 920 shaper.advance(from); | 884 shaper.advance(from); |
| 921 float fromX = shaper.runWidthSoFar(); | 885 float fromX = shaper.runWidthSoFar(); |
| 922 shaper.advance(to); | 886 shaper.advance(to); |
| 923 float toX = shaper.runWidthSoFar(); | 887 float toX = shaper.runWidthSoFar(); |
| 924 | 888 |
| 925 if (run.rtl()) { | 889 if (run.rtl()) { |
| 926 shaper.advance(run.length()); | 890 shaper.advance(run.length()); |
| 927 float totalWidth = shaper.runWidthSoFar(); | 891 float totalWidth = shaper.runWidthSoFar(); |
| 928 float beforeWidth = fromX; | 892 float beforeWidth = fromX; |
| 929 float afterWidth = toX; | 893 float afterWidth = toX; |
| (...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 973 if (delta <= 0) | 937 if (delta <= 0) |
| 974 break; | 938 break; |
| 975 } | 939 } |
| 976 } | 940 } |
| 977 } | 941 } |
| 978 | 942 |
| 979 return offset; | 943 return offset; |
| 980 } | 944 } |
| 981 | 945 |
| 982 } // namespace blink | 946 } // namespace blink |
| OLD | NEW |