| 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 |