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 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
93 // FIXME: It is pretty crazy that we are willing to just poke into a RefPtr,
but it ends up | 93 // FIXME: It is pretty crazy that we are willing to just poke into a RefPtr,
but it ends up |
94 // being reasonably safe (because inherited fonts in the render tree pick up
the new | 94 // being reasonably safe (because inherited fonts in the render tree pick up
the new |
95 // style anyway. Other copies are transient, e.g., the state in the Graphics
Context, and | 95 // style anyway. Other copies are transient, e.g., the state in the Graphics
Context, and |
96 // won't stick around long enough to get you in trouble). Still, this is pre
tty disgusting, | 96 // won't stick around long enough to get you in trouble). Still, this is pre
tty disgusting, |
97 // and could eventually be rectified by using RefPtrs for Fonts themselves. | 97 // and could eventually be rectified by using RefPtrs for Fonts themselves. |
98 if (!m_fontFallbackList) | 98 if (!m_fontFallbackList) |
99 m_fontFallbackList = FontFallbackList::create(); | 99 m_fontFallbackList = FontFallbackList::create(); |
100 m_fontFallbackList->invalidate(fontSelector); | 100 m_fontFallbackList->invalidate(fontSelector); |
101 } | 101 } |
102 | 102 |
103 float Font::drawText(GraphicsContext* context, const TextRunPaintInfo& runInfo,
const FloatPoint& point, CustomFontNotReadyAction customFontNotReadyAction) cons
t | 103 float Font::buildGlyphBuffer(const TextRunPaintInfo& runInfo, GlyphBuffer& glyph
Buffer, |
| 104 ForTextEmphasisOrNot forTextEmphasis) const |
| 105 { |
| 106 if (codePath(runInfo) == ComplexPath) { |
| 107 HarfBuzzShaper shaper(this, runInfo.run, (forTextEmphasis == ForTextEmph
asis) |
| 108 ? HarfBuzzShaper::ForTextEmphasis : HarfBuzzShaper::NotForTextEmphas
is); |
| 109 shaper.setDrawRange(runInfo.from, runInfo.to); |
| 110 shaper.shape(&glyphBuffer); |
| 111 |
| 112 return 0; |
| 113 } |
| 114 |
| 115 SimpleShaper shaper(this, runInfo.run, nullptr /* fallbackFonts */, |
| 116 nullptr /* GlyphBounds */, forTextEmphasis); |
| 117 shaper.advance(runInfo.from); |
| 118 float beforeWidth = shaper.runWidthSoFar(); |
| 119 shaper.advance(runInfo.to, &glyphBuffer); |
| 120 |
| 121 if (runInfo.run.ltr()) |
| 122 return beforeWidth; |
| 123 |
| 124 // RTL |
| 125 float afterWidth = shaper.runWidthSoFar(); |
| 126 shaper.advance(runInfo.run.length()); |
| 127 glyphBuffer.reverse(); |
| 128 |
| 129 return shaper.runWidthSoFar() - afterWidth; |
| 130 } |
| 131 |
| 132 void Font::drawText(GraphicsContext* context, const TextRunPaintInfo& runInfo, |
| 133 const FloatPoint& point) const |
| 134 { |
| 135 // Don't draw anything while we are using custom fonts that are in the proce
ss of loading. |
| 136 if (shouldSkipDrawing()) |
| 137 return; |
| 138 |
| 139 TextDrawingModeFlags textMode = context->textDrawingMode(); |
| 140 if (!(textMode & TextModeFill) && !((textMode & TextModeStroke) && context->
hasStroke())) |
| 141 return; |
| 142 |
| 143 if (runInfo.cachedTextBlob && runInfo.cachedTextBlob->get()) { |
| 144 ASSERT(RuntimeEnabledFeatures::textBlobEnabled()); |
| 145 // we have a pre-cached blob -- happy joy! |
| 146 drawTextBlob(context, runInfo.cachedTextBlob->get(), point.data()); |
| 147 return; |
| 148 } |
| 149 |
| 150 GlyphBuffer glyphBuffer; |
| 151 float initialAdvance = buildGlyphBuffer(runInfo, glyphBuffer); |
| 152 |
| 153 if (glyphBuffer.isEmpty()) |
| 154 return; |
| 155 |
| 156 if (RuntimeEnabledFeatures::textBlobEnabled()) { |
| 157 // Enabling text-blobs forces the blob rendering path even for uncacheab
le blobs. |
| 158 TextBlobPtr uncacheableTextBlob; |
| 159 TextBlobPtr& textBlob = runInfo.cachedTextBlob ? *runInfo.cachedTextBlob
: uncacheableTextBlob; |
| 160 FloatRect blobBounds = runInfo.bounds; |
| 161 blobBounds.moveBy(-point); |
| 162 |
| 163 textBlob = buildTextBlob(glyphBuffer, initialAdvance, blobBounds, contex
t->couldUseLCDRenderedText()); |
| 164 if (textBlob) { |
| 165 drawTextBlob(context, textBlob.get(), point.data()); |
| 166 return; |
| 167 } |
| 168 } |
| 169 |
| 170 drawGlyphBuffer(context, runInfo, glyphBuffer, FloatPoint(point.x() + initia
lAdvance, point.y())); |
| 171 } |
| 172 |
| 173 float Font::drawUncachedText(GraphicsContext* context, const TextRunPaintInfo& r
unInfo, |
| 174 const FloatPoint& point, CustomFontNotReadyAction customFontNotReadyAction)
const |
104 { | 175 { |
105 // Don't draw anything while we are using custom fonts that are in the proce
ss of loading, | 176 // Don't draw anything while we are using custom fonts that are in the proce
ss of loading, |
106 // except if the 'force' argument is set to true (in which case it will use
a fallback | 177 // except if the 'force' argument is set to true (in which case it will use
a fallback |
107 // font). | 178 // font). |
108 if (shouldSkipDrawing() && customFontNotReadyAction == DoNotPaintIfFontNotRe
ady) | 179 if (shouldSkipDrawing() && customFontNotReadyAction == DoNotPaintIfFontNotRe
ady) |
109 return 0; | 180 return 0; |
110 | 181 |
111 if (codePath(runInfo) != ComplexPath) | 182 TextDrawingModeFlags textMode = context->textDrawingMode(); |
112 return drawSimpleText(context, runInfo, point); | 183 if (!(textMode & TextModeFill) && !((textMode & TextModeStroke) && context->
hasStroke())) |
| 184 return 0; |
113 | 185 |
114 return drawComplexText(context, runInfo, point); | 186 GlyphBuffer glyphBuffer; |
| 187 float initialAdvance = buildGlyphBuffer(runInfo, glyphBuffer); |
| 188 |
| 189 if (glyphBuffer.isEmpty()) |
| 190 return 0; |
| 191 |
| 192 return drawGlyphBuffer(context, runInfo, glyphBuffer, FloatPoint(point.x() +
initialAdvance, point.y())); |
115 } | 193 } |
116 | 194 |
117 void Font::drawEmphasisMarks(GraphicsContext* context, const TextRunPaintInfo& r
unInfo, const AtomicString& mark, const FloatPoint& point) const | 195 void Font::drawEmphasisMarks(GraphicsContext* context, const TextRunPaintInfo& r
unInfo, const AtomicString& mark, const FloatPoint& point) const |
118 { | 196 { |
119 if (shouldSkipDrawing()) | 197 if (shouldSkipDrawing()) |
120 return; | 198 return; |
121 | 199 |
122 if (codePath(runInfo) != ComplexPath) | 200 GlyphBuffer glyphBuffer; |
123 drawEmphasisMarksForSimpleText(context, runInfo, mark, point); | 201 float initialAdvance = buildGlyphBuffer(runInfo, glyphBuffer, ForTextEmphasi
s); |
124 else | 202 |
125 drawEmphasisMarksForComplexText(context, runInfo, mark, point); | 203 if (glyphBuffer.isEmpty()) |
| 204 return; |
| 205 |
| 206 drawEmphasisMarks(context, runInfo, glyphBuffer, mark, FloatPoint(point.x()
+ initialAdvance, point.y())); |
126 } | 207 } |
127 | 208 |
128 static inline void updateGlyphOverflowFromBounds(const IntRectExtent& glyphBound
s, | 209 static inline void updateGlyphOverflowFromBounds(const IntRectExtent& glyphBound
s, |
129 const FontMetrics& fontMetrics, GlyphOverflow* glyphOverflow) | 210 const FontMetrics& fontMetrics, GlyphOverflow* glyphOverflow) |
130 { | 211 { |
131 glyphOverflow->top = std::max<int>(glyphOverflow->top, | 212 glyphOverflow->top = std::max<int>(glyphOverflow->top, |
132 glyphBounds.top() - (glyphOverflow->computeBounds ? 0 : fontMetrics.asce
nt())); | 213 glyphBounds.top() - (glyphOverflow->computeBounds ? 0 : fontMetrics.asce
nt())); |
133 glyphOverflow->bottom = std::max<int>(glyphOverflow->bottom, | 214 glyphOverflow->bottom = std::max<int>(glyphOverflow->bottom, |
134 glyphBounds.bottom() - (glyphOverflow->computeBounds ? 0 : fontMetrics.d
escent())); | 215 glyphBounds.bottom() - (glyphOverflow->computeBounds ? 0 : fontMetrics.d
escent())); |
135 glyphOverflow->left = glyphBounds.left(); | 216 glyphOverflow->left = glyphBounds.left(); |
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
183 #if ENABLE(SVG_FONTS) | 264 #if ENABLE(SVG_FONTS) |
184 if (TextRun::RenderingContext* renderingContext = run.renderingContext()) | 265 if (TextRun::RenderingContext* renderingContext = run.renderingContext()) |
185 return renderingContext->floatWidthUsingSVGFont(*this, run, charsConsume
d, glyphId); | 266 return renderingContext->floatWidthUsingSVGFont(*this, run, charsConsume
d, glyphId); |
186 #endif | 267 #endif |
187 | 268 |
188 charsConsumed = run.length(); | 269 charsConsumed = run.length(); |
189 glyphId = 0; | 270 glyphId = 0; |
190 return width(run); | 271 return width(run); |
191 } | 272 } |
192 | 273 |
193 PassTextBlobPtr Font::buildTextBlob(const TextRunPaintInfo& runInfo, const Float
Point& textOrigin, bool couldUseLCDRenderedText, CustomFontNotReadyAction custom
FontNotReadyAction) const | 274 PassTextBlobPtr Font::buildTextBlob(const GlyphBuffer& glyphBuffer, float initia
lAdvance, |
| 275 const FloatRect& bounds, bool couldUseLCD) const |
194 { | 276 { |
195 ASSERT(RuntimeEnabledFeatures::textBlobEnabled()); | 277 ASSERT(RuntimeEnabledFeatures::textBlobEnabled()); |
196 | 278 |
197 // FIXME: Some logic in common with Font::drawText. Would be nice to | 279 // FIXME: Implement the more general full-positioning path for complex text
support. |
198 // deduplicate. | 280 if (glyphBuffer.hasOffsets()) |
199 if (shouldSkipDrawing() && customFontNotReadyAction == DoNotPaintIfFontNotRe
ady) | |
200 return nullptr; | 281 return nullptr; |
201 | 282 |
202 if (codePath(runInfo) != ComplexPath) | |
203 return buildTextBlobForSimpleText(runInfo, textOrigin, couldUseLCDRender
edText); | |
204 | |
205 return nullptr; | |
206 } | |
207 | |
208 PassTextBlobPtr Font::buildTextBlobForSimpleText(const TextRunPaintInfo& runInfo
, const FloatPoint& textOrigin, bool couldUseLCDRenderedText) const | |
209 { | |
210 GlyphBuffer glyphBuffer; | |
211 float initialAdvance = getGlyphsAndAdvancesForSimpleText(runInfo, glyphBuffe
r); | |
212 | |
213 if (glyphBuffer.isEmpty()) | |
214 return nullptr; | |
215 | |
216 FloatRect blobBounds = runInfo.bounds; | |
217 blobBounds.moveBy(-textOrigin); | |
218 | |
219 float ignoredWidth; | |
220 return buildTextBlob(glyphBuffer, initialAdvance, blobBounds, ignoredWidth,
couldUseLCDRenderedText); | |
221 } | |
222 | |
223 PassTextBlobPtr Font::buildTextBlob(const GlyphBuffer& glyphBuffer, float initia
lAdvance, | |
224 const FloatRect& bounds, float& advance, bool couldUseLCD) const | |
225 { | |
226 ASSERT(RuntimeEnabledFeatures::textBlobEnabled()); | |
227 | |
228 // FIXME: Implement the more general full-positioning path. | |
229 ASSERT(!glyphBuffer.hasOffsets()); | |
230 | |
231 SkTextBlobBuilder builder; | 283 SkTextBlobBuilder builder; |
232 SkScalar x = SkFloatToScalar(initialAdvance); | 284 SkScalar x = SkFloatToScalar(initialAdvance); |
233 SkRect skBounds = bounds; | 285 SkRect skBounds = bounds; |
234 | 286 |
235 unsigned i = 0; | 287 unsigned i = 0; |
236 while (i < glyphBuffer.size()) { | 288 while (i < glyphBuffer.size()) { |
237 const SimpleFontData* fontData = glyphBuffer.fontDataAt(i); | 289 const SimpleFontData* fontData = glyphBuffer.fontDataAt(i); |
238 | 290 |
239 // FIXME: Handle vertical text. | 291 // FIXME: Handle vertical text. |
240 if (fontData->platformData().orientation() == Vertical) | 292 if (fontData->platformData().orientation() == Vertical) |
(...skipping 23 matching lines...) Expand all Loading... |
264 const uint16_t* glyphs = glyphBuffer.glyphs(start); | 316 const uint16_t* glyphs = glyphBuffer.glyphs(start); |
265 std::copy(glyphs, glyphs + count, buffer.glyphs); | 317 std::copy(glyphs, glyphs + count, buffer.glyphs); |
266 | 318 |
267 const float* advances = glyphBuffer.advances(start); | 319 const float* advances = glyphBuffer.advances(start); |
268 for (unsigned j = 0; j < count; j++) { | 320 for (unsigned j = 0; j < count; j++) { |
269 buffer.pos[j] = x; | 321 buffer.pos[j] = x; |
270 x += SkFloatToScalar(advances[j]); | 322 x += SkFloatToScalar(advances[j]); |
271 } | 323 } |
272 } | 324 } |
273 | 325 |
274 advance = x; | |
275 return adoptRef(builder.build()); | 326 return adoptRef(builder.build()); |
276 } | 327 } |
277 | 328 |
278 | 329 |
279 FloatRect Font::selectionRectForText(const TextRun& run, const FloatPoint& point
, int h, int from, int to, bool accountForGlyphBounds) const | 330 FloatRect Font::selectionRectForText(const TextRun& run, const FloatPoint& point
, int h, int from, int to, bool accountForGlyphBounds) const |
280 { | 331 { |
281 to = (to == -1 ? run.length() : to); | 332 to = (to == -1 ? run.length() : to); |
282 | 333 |
283 TextRunPaintInfo runInfo(run); | 334 TextRunPaintInfo runInfo(run); |
284 runInfo.from = from; | 335 runInfo.from = from; |
(...skipping 402 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
687 return 0; | 738 return 0; |
688 | 739 |
689 const SimpleFontData* markFontData = markGlyphData.fontData; | 740 const SimpleFontData* markFontData = markGlyphData.fontData; |
690 ASSERT(markFontData); | 741 ASSERT(markFontData); |
691 if (!markFontData) | 742 if (!markFontData) |
692 return 0; | 743 return 0; |
693 | 744 |
694 return markFontData->fontMetrics().height(); | 745 return markFontData->fontMetrics().height(); |
695 } | 746 } |
696 | 747 |
697 float Font::getGlyphsAndAdvancesForSimpleText(const TextRunPaintInfo& runInfo, | |
698 GlyphBuffer& glyphBuffer, ForTextEmphasisOrNot forTextEmphasis) const | |
699 { | |
700 float initialAdvance; | |
701 | |
702 SimpleShaper shaper(this, runInfo.run, 0 /* fallbackFonts */, | |
703 0 /* GlyphBounds */, forTextEmphasis); | |
704 shaper.advance(runInfo.from); | |
705 float beforeWidth = shaper.runWidthSoFar(); | |
706 shaper.advance(runInfo.to, &glyphBuffer); | |
707 | |
708 if (glyphBuffer.isEmpty()) | |
709 return 0; | |
710 | |
711 float afterWidth = shaper.runWidthSoFar(); | |
712 | |
713 if (runInfo.run.rtl()) { | |
714 shaper.advance(runInfo.run.length()); | |
715 initialAdvance = shaper.runWidthSoFar() - afterWidth; | |
716 glyphBuffer.reverse(); | |
717 } else { | |
718 initialAdvance = beforeWidth; | |
719 } | |
720 | |
721 return initialAdvance; | |
722 } | |
723 | |
724 float Font::drawSimpleText(GraphicsContext* context, const TextRunPaintInfo& run
Info, const FloatPoint& point) const | |
725 { | |
726 // This glyph buffer holds our glyphs+advances+font data for each glyph. | |
727 GlyphBuffer glyphBuffer; | |
728 float initialAdvance = getGlyphsAndAdvancesForSimpleText(runInfo, glyphBuffe
r); | |
729 | |
730 if (glyphBuffer.isEmpty()) | |
731 return 0; | |
732 | |
733 FloatPoint startPoint(point.x() + initialAdvance, point.y()); | |
734 return drawGlyphBuffer(context, runInfo, glyphBuffer, startPoint); | |
735 } | |
736 | |
737 void Font::drawEmphasisMarksForSimpleText(GraphicsContext* context, const TextRu
nPaintInfo& runInfo, const AtomicString& mark, const FloatPoint& point) const | |
738 { | |
739 GlyphBuffer glyphBuffer; | |
740 float initialAdvance = getGlyphsAndAdvancesForSimpleText(runInfo, glyphBuffe
r, ForTextEmphasis); | |
741 | |
742 if (glyphBuffer.isEmpty()) | |
743 return; | |
744 | |
745 drawEmphasisMarks(context, runInfo, glyphBuffer, mark, FloatPoint(point.x()
+ initialAdvance, point.y())); | |
746 } | |
747 | |
748 static SkPaint textFillPaint(GraphicsContext* gc, const SimpleFontData* font) | 748 static SkPaint textFillPaint(GraphicsContext* gc, const SimpleFontData* font) |
749 { | 749 { |
750 SkPaint paint = gc->fillPaint(); | 750 SkPaint paint = gc->fillPaint(); |
751 font->platformData().setupPaint(&paint, gc); | 751 font->platformData().setupPaint(&paint, gc); |
752 gc->adjustTextRenderMode(&paint); | 752 gc->adjustTextRenderMode(&paint); |
753 paint.setTextEncoding(SkPaint::kGlyphID_TextEncoding); | 753 paint.setTextEncoding(SkPaint::kGlyphID_TextEncoding); |
754 return paint; | 754 return paint; |
755 } | 755 } |
756 | 756 |
757 static SkPaint textStrokePaint(GraphicsContext* gc, const SimpleFontData* font,
bool isFilling) | 757 static SkPaint textStrokePaint(GraphicsContext* gc, const SimpleFontData* font,
bool isFilling) |
(...skipping 108 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
866 for (unsigned i = 0; i < numGlyphs; i++) { | 866 for (unsigned i = 0; i < numGlyphs; i++) { |
867 xpos[i] = x; | 867 xpos[i] = x; |
868 x += SkFloatToScalar(adv[i]); | 868 x += SkFloatToScalar(adv[i]); |
869 } | 869 } |
870 const Glyph* glyphs = glyphBuffer.glyphs(from); | 870 const Glyph* glyphs = glyphBuffer.glyphs(from); |
871 paintGlyphsHorizontal(gc, font, glyphs, numGlyphs, xpos, SkFloatToScalar
(y), textRect); | 871 paintGlyphsHorizontal(gc, font, glyphs, numGlyphs, xpos, SkFloatToScalar
(y), textRect); |
872 return; | 872 return; |
873 } | 873 } |
874 | 874 |
875 ASSERT(glyphBuffer.hasOffsets()); | 875 ASSERT(glyphBuffer.hasOffsets()); |
876 const GlyphBufferWithOffsets& glyphBufferWithOffsets = | |
877 static_cast<const GlyphBufferWithOffsets&>(glyphBuffer); | |
878 SkAutoSTMalloc<32, SkPoint> storage(numGlyphs); | 876 SkAutoSTMalloc<32, SkPoint> storage(numGlyphs); |
879 SkPoint* pos = storage.get(); | 877 SkPoint* pos = storage.get(); |
880 const FloatSize* offsets = glyphBufferWithOffsets.offsets(from); | 878 const FloatSize* offsets = glyphBuffer.offsets(from); |
881 const float* advances = glyphBufferWithOffsets.advances(from); | 879 const float* advances = glyphBuffer.advances(from); |
882 SkScalar advanceSoFar = SkFloatToScalar(0); | 880 SkScalar advanceSoFar = SkFloatToScalar(0); |
883 for (unsigned i = 0; i < numGlyphs; i++) { | 881 for (unsigned i = 0; i < numGlyphs; i++) { |
884 pos[i].set( | 882 pos[i].set( |
885 x + SkFloatToScalar(offsets[i].width()) + advanceSoFar, | 883 x + SkFloatToScalar(offsets[i].width()) + advanceSoFar, |
886 y + SkFloatToScalar(offsets[i].height())); | 884 y + SkFloatToScalar(offsets[i].height())); |
887 advanceSoFar += SkFloatToScalar(advances[i]); | 885 advanceSoFar += SkFloatToScalar(advances[i]); |
888 } | 886 } |
889 | 887 |
890 const Glyph* glyphs = glyphBufferWithOffsets.glyphs(from); | 888 const Glyph* glyphs = glyphBuffer.glyphs(from); |
891 paintGlyphs(gc, font, glyphs, numGlyphs, pos, textRect); | 889 paintGlyphs(gc, font, glyphs, numGlyphs, pos, textRect); |
892 } | 890 } |
893 | 891 |
894 void Font::drawTextBlob(GraphicsContext* gc, const SkTextBlob* blob, const SkPoi
nt& origin) const | 892 void Font::drawTextBlob(GraphicsContext* gc, const SkTextBlob* blob, const SkPoi
nt& origin) const |
895 { | 893 { |
896 ASSERT(RuntimeEnabledFeatures::textBlobEnabled()); | 894 ASSERT(RuntimeEnabledFeatures::textBlobEnabled()); |
897 | 895 |
898 TextDrawingModeFlags textMode = gc->textDrawingMode(); | 896 TextDrawingModeFlags textMode = gc->textDrawingMode(); |
899 if (textMode & TextModeFill) | 897 if (textMode & TextModeFill) |
900 gc->drawTextBlob(blob, origin, gc->fillPaint()); | 898 gc->drawTextBlob(blob, origin, gc->fillPaint()); |
901 | 899 |
902 if ((textMode & TextModeStroke) && gc->hasStroke()) { | 900 if ((textMode & TextModeStroke) && gc->hasStroke()) { |
903 SkPaint paint = gc->strokePaint(); | 901 SkPaint paint = gc->strokePaint(); |
904 if (textMode & TextModeFill) | 902 if (textMode & TextModeFill) |
905 paint.setLooper(0); | 903 paint.setLooper(0); |
906 gc->drawTextBlob(blob, origin, paint); | 904 gc->drawTextBlob(blob, origin, paint); |
907 } | 905 } |
908 } | 906 } |
909 | 907 |
910 float Font::drawComplexText(GraphicsContext* gc, const TextRunPaintInfo& runInfo
, const FloatPoint& point) const | |
911 { | |
912 if (!runInfo.run.length()) | |
913 return 0; | |
914 | |
915 TextDrawingModeFlags textMode = gc->textDrawingMode(); | |
916 bool fill = textMode & TextModeFill; | |
917 bool stroke = (textMode & TextModeStroke) && gc->hasStroke(); | |
918 | |
919 if (!fill && !stroke) | |
920 return 0; | |
921 | |
922 GlyphBufferWithOffsets glyphBuffer; | |
923 HarfBuzzShaper shaper(this, runInfo.run); | |
924 shaper.setDrawRange(runInfo.from, runInfo.to); | |
925 if (!shaper.shape(&glyphBuffer) || glyphBuffer.isEmpty()) | |
926 return 0; | |
927 return drawGlyphBuffer(gc, runInfo, glyphBuffer, point); | |
928 } | |
929 | |
930 void Font::drawEmphasisMarksForComplexText(GraphicsContext* context, const TextR
unPaintInfo& runInfo, const AtomicString& mark, const FloatPoint& point) const | |
931 { | |
932 GlyphBuffer glyphBuffer; | |
933 | |
934 float initialAdvance = getGlyphsAndAdvancesForComplexText(runInfo, glyphBuff
er, ForTextEmphasis); | |
935 | |
936 if (glyphBuffer.isEmpty()) | |
937 return; | |
938 | |
939 drawEmphasisMarks(context, runInfo, glyphBuffer, mark, FloatPoint(point.x()
+ initialAdvance, point.y())); | |
940 } | |
941 | |
942 float Font::getGlyphsAndAdvancesForComplexText(const TextRunPaintInfo& runInfo,
GlyphBuffer& glyphBuffer, ForTextEmphasisOrNot forTextEmphasis) const | |
943 { | |
944 HarfBuzzShaper shaper(this, runInfo.run, HarfBuzzShaper::ForTextEmphasis); | |
945 shaper.setDrawRange(runInfo.from, runInfo.to); | |
946 shaper.shape(&glyphBuffer); | |
947 return 0; | |
948 } | |
949 | |
950 float Font::floatWidthForComplexText(const TextRun& run, HashSet<const SimpleFon
tData*>* fallbackFonts, IntRectExtent* glyphBounds) const | 908 float Font::floatWidthForComplexText(const TextRun& run, HashSet<const SimpleFon
tData*>* fallbackFonts, IntRectExtent* glyphBounds) const |
951 { | 909 { |
952 HarfBuzzShaper shaper(this, run, HarfBuzzShaper::NotForTextEmphasis, fallbac
kFonts); | 910 HarfBuzzShaper shaper(this, run, HarfBuzzShaper::NotForTextEmphasis, fallbac
kFonts); |
953 if (!shaper.shape()) | 911 if (!shaper.shape()) |
954 return 0; | 912 return 0; |
955 | 913 |
956 glyphBounds->setTop(floorf(-shaper.glyphBoundingBox().top())); | 914 glyphBounds->setTop(floorf(-shaper.glyphBoundingBox().top())); |
957 glyphBounds->setBottom(ceilf(shaper.glyphBoundingBox().bottom())); | 915 glyphBounds->setBottom(ceilf(shaper.glyphBoundingBox().bottom())); |
958 glyphBounds->setLeft(std::max<int>(0, floorf(-shaper.glyphBoundingBox().left
()))); | 916 glyphBounds->setLeft(std::max<int>(0, floorf(-shaper.glyphBoundingBox().left
()))); |
959 glyphBounds->setRight(std::max<int>(0, ceilf(shaper.glyphBoundingBox().right
() - shaper.totalWidth()))); | 917 glyphBounds->setRight(std::max<int>(0, ceilf(shaper.glyphBoundingBox().right
() - shaper.totalWidth()))); |
(...skipping 195 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1155 if (delta <= 0) | 1113 if (delta <= 0) |
1156 break; | 1114 break; |
1157 } | 1115 } |
1158 } | 1116 } |
1159 } | 1117 } |
1160 | 1118 |
1161 return offset; | 1119 return offset; |
1162 } | 1120 } |
1163 | 1121 |
1164 } // namespace blink | 1122 } // namespace blink |
OLD | NEW |