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 |