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 |