Chromium Code Reviews| 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 * | 6 * |
| 7 * This library is free software; you can redistribute it and/or | 7 * This library is free software; you can redistribute it and/or |
| 8 * modify it under the terms of the GNU Library General Public | 8 * modify it under the terms of the GNU Library General Public |
| 9 * License as published by the Free Software Foundation; either | 9 * License as published by the Free Software Foundation; either |
| 10 * version 2 of the License, or (at your option) any later version. | 10 * version 2 of the License, or (at your option) any later version. |
| (...skipping 16 matching lines...) Expand all Loading... | |
| 27 #include "gen/sky/platform/RuntimeEnabledFeatures.h" | 27 #include "gen/sky/platform/RuntimeEnabledFeatures.h" |
| 28 #include "sky/engine/platform/LayoutUnit.h" | 28 #include "sky/engine/platform/LayoutUnit.h" |
| 29 #include "sky/engine/platform/fonts/Character.h" | 29 #include "sky/engine/platform/fonts/Character.h" |
| 30 #include "sky/engine/platform/fonts/FontCache.h" | 30 #include "sky/engine/platform/fonts/FontCache.h" |
| 31 #include "sky/engine/platform/fonts/FontFallbackList.h" | 31 #include "sky/engine/platform/fonts/FontFallbackList.h" |
| 32 #include "sky/engine/platform/fonts/FontPlatformFeatures.h" | 32 #include "sky/engine/platform/fonts/FontPlatformFeatures.h" |
| 33 #include "sky/engine/platform/fonts/GlyphBuffer.h" | 33 #include "sky/engine/platform/fonts/GlyphBuffer.h" |
| 34 #include "sky/engine/platform/fonts/GlyphPageTreeNode.h" | 34 #include "sky/engine/platform/fonts/GlyphPageTreeNode.h" |
| 35 #include "sky/engine/platform/fonts/SimpleFontData.h" | 35 #include "sky/engine/platform/fonts/SimpleFontData.h" |
| 36 #include "sky/engine/platform/fonts/WidthIterator.h" | 36 #include "sky/engine/platform/fonts/WidthIterator.h" |
| 37 #include "sky/engine/platform/fonts/harfbuzz/HarfBuzzShaper.h" | |
| 37 #include "sky/engine/platform/geometry/FloatRect.h" | 38 #include "sky/engine/platform/geometry/FloatRect.h" |
| 38 #include "sky/engine/platform/graphics/GraphicsContext.h" | 39 #include "sky/engine/platform/graphics/GraphicsContext.h" |
| 39 #include "sky/engine/platform/text/TextRun.h" | 40 #include "sky/engine/platform/text/TextRun.h" |
| 40 #include "sky/engine/wtf/MainThread.h" | 41 #include "sky/engine/wtf/MainThread.h" |
| 41 #include "sky/engine/wtf/StdLibExtras.h" | 42 #include "sky/engine/wtf/StdLibExtras.h" |
| 42 #include "sky/engine/wtf/unicode/CharacterNames.h" | 43 #include "sky/engine/wtf/unicode/CharacterNames.h" |
| 43 #include "sky/engine/wtf/unicode/Unicode.h" | 44 #include "sky/engine/wtf/unicode/Unicode.h" |
| 44 | 45 |
| 45 using namespace WTF; | 46 using namespace WTF; |
| 46 using namespace Unicode; | 47 using namespace Unicode; |
| (...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 96 // FIXME: It is pretty crazy that we are willing to just poke into a RefPtr, but it ends up | 97 // FIXME: It is pretty crazy that we are willing to just poke into a RefPtr, but it ends up |
| 97 // being reasonably safe (because inherited fonts in the render tree pick up the new | 98 // being reasonably safe (because inherited fonts in the render tree pick up the new |
| 98 // style anyway. Other copies are transient, e.g., the state in the Graphics Context, and | 99 // style anyway. Other copies are transient, e.g., the state in the Graphics Context, and |
| 99 // won't stick around long enough to get you in trouble). Still, this is pre tty disgusting, | 100 // won't stick around long enough to get you in trouble). Still, this is pre tty disgusting, |
| 100 // and could eventually be rectified by using RefPtrs for Fonts themselves. | 101 // and could eventually be rectified by using RefPtrs for Fonts themselves. |
| 101 if (!m_fontFallbackList) | 102 if (!m_fontFallbackList) |
| 102 m_fontFallbackList = FontFallbackList::create(); | 103 m_fontFallbackList = FontFallbackList::create(); |
| 103 m_fontFallbackList->invalidate(fontSelector); | 104 m_fontFallbackList->invalidate(fontSelector); |
| 104 } | 105 } |
| 105 | 106 |
| 106 void Font::drawText(GraphicsContext* context, const TextRunPaintInfo& runInfo, c onst FloatPoint& point, CustomFontNotReadyAction customFontNotReadyAction) const | 107 float Font::buildGlyphBuffer(const TextRunPaintInfo& runInfo, GlyphBuffer& glyph Buffer, |
| 108 ForTextEmphasisOrNot forTextEmphasis) const | |
| 109 { | |
| 110 if (codePath(runInfo.run) == ComplexPath) { | |
| 111 HarfBuzzShaper shaper(this, runInfo.run, (forTextEmphasis == ForTextEmph asis) | |
| 112 ? HarfBuzzShaper::ForTextEmphasis : HarfBuzzShaper::NotForTextEmphas is); | |
| 113 shaper.setDrawRange(runInfo.from, runInfo.to); | |
| 114 shaper.shape(&glyphBuffer); | |
| 115 | |
| 116 return 0; | |
|
esprehn
2015/01/21 09:58:57
I wonder why it's always zero for the complex text
| |
| 117 } | |
| 118 | |
| 119 WidthIterator it(this, runInfo.run, nullptr, false, forTextEmphasis); | |
| 120 it.advance(runInfo.from); | |
| 121 float beforeWidth = it.runWidthSoFar(); | |
| 122 it.advance(runInfo.to, &glyphBuffer); | |
| 123 | |
| 124 if (runInfo.run.ltr()) | |
| 125 return beforeWidth; | |
| 126 | |
| 127 // RTL | |
| 128 float afterWidth = it.runWidthSoFar(); | |
| 129 it.advance(runInfo.run.length()); | |
| 130 glyphBuffer.reverse(); | |
| 131 | |
| 132 return it.runWidthSoFar() - afterWidth; | |
| 133 } | |
| 134 | |
| 135 void Font::drawText(GraphicsContext* context, const TextRunPaintInfo& runInfo, | |
| 136 const FloatPoint& point) const | |
| 137 { | |
| 138 // Don't draw anything while we are using custom fonts that are in the proce ss of loading. | |
| 139 if (shouldSkipDrawing()) | |
| 140 return; | |
| 141 | |
| 142 TextDrawingModeFlags textMode = context->textDrawingMode(); | |
| 143 if (!(textMode & TextModeFill) && !((textMode & TextModeStroke) && context-> hasStroke())) | |
| 144 return; | |
| 145 | |
| 146 if (runInfo.cachedTextBlob && runInfo.cachedTextBlob->get()) { | |
| 147 ASSERT(RuntimeEnabledFeatures::textBlobEnabled()); | |
| 148 // we have a pre-cached blob -- happy joy! | |
| 149 drawTextBlob(context, runInfo.cachedTextBlob->get(), point.data()); | |
| 150 return; | |
| 151 } | |
| 152 | |
| 153 GlyphBuffer glyphBuffer; | |
| 154 float initialAdvance = buildGlyphBuffer(runInfo, glyphBuffer); | |
| 155 | |
| 156 if (glyphBuffer.isEmpty()) | |
| 157 return; | |
| 158 | |
| 159 if (RuntimeEnabledFeatures::textBlobEnabled()) { | |
| 160 // Enabling text-blobs forces the blob rendering path even for uncacheab le blobs. | |
| 161 TextBlobPtr uncacheableTextBlob; | |
| 162 TextBlobPtr& textBlob = runInfo.cachedTextBlob ? *runInfo.cachedTextBlob : uncacheableTextBlob; | |
| 163 FloatRect blobBounds = runInfo.bounds; | |
| 164 blobBounds.moveBy(-point); | |
| 165 | |
| 166 textBlob = buildTextBlob(glyphBuffer, initialAdvance, blobBounds); | |
| 167 if (textBlob) { | |
| 168 drawTextBlob(context, textBlob.get(), point.data()); | |
| 169 return; | |
| 170 } | |
| 171 } | |
| 172 | |
| 173 drawGlyphBuffer(context, runInfo, glyphBuffer, FloatPoint(point.x() + initia lAdvance, point.y())); | |
| 174 } | |
| 175 | |
| 176 float Font::drawUncachedText(GraphicsContext* context, const TextRunPaintInfo& r unInfo, | |
| 177 const FloatPoint& point, CustomFontNotReadyAction customFontNotReadyAction) const | |
| 107 { | 178 { |
| 108 // Don't draw anything while we are using custom fonts that are in the proce ss of loading, | 179 // Don't draw anything while we are using custom fonts that are in the proce ss of loading, |
| 109 // except if the 'force' argument is set to true (in which case it will use a fallback | 180 // except if the 'force' argument is set to true (in which case it will use a fallback |
| 110 // font). | 181 // font). |
| 111 if (shouldSkipDrawing() && customFontNotReadyAction == DoNotPaintIfFontNotRe ady) | 182 if (shouldSkipDrawing() && customFontNotReadyAction == DoNotPaintIfFontNotRe ady) |
| 112 return; | 183 return 0; |
| 113 | 184 |
| 114 CodePath codePathToUse = codePath(runInfo.run); | 185 TextDrawingModeFlags textMode = context->textDrawingMode(); |
| 115 // FIXME: Use the fast code path once it handles partial runs with kerning a nd ligatures. See http://webkit.org/b/100050 | 186 if (!(textMode & TextModeFill) && !((textMode & TextModeStroke) && context-> hasStroke())) |
| 116 if (codePathToUse != ComplexPath && fontDescription().typesettingFeatures() && (runInfo.from || runInfo.to != runInfo.run.length())) | 187 return 0; |
| 117 codePathToUse = ComplexPath; | |
| 118 | 188 |
| 119 if (codePathToUse != ComplexPath) { | 189 GlyphBuffer glyphBuffer; |
| 120 drawSimpleText(context, runInfo, point); | 190 float initialAdvance = buildGlyphBuffer(runInfo, glyphBuffer); |
| 121 } else { | 191 |
| 122 drawComplexText(context, runInfo, point); | 192 if (glyphBuffer.isEmpty()) |
| 123 } | 193 return 0; |
| 194 | |
| 195 return drawGlyphBuffer(context, runInfo, glyphBuffer, FloatPoint(point.x() + initialAdvance, point.y())); | |
| 124 } | 196 } |
| 125 | 197 |
| 126 void Font::drawEmphasisMarks(GraphicsContext* context, const TextRunPaintInfo& r unInfo, const AtomicString& mark, const FloatPoint& point) const | 198 void Font::drawEmphasisMarks(GraphicsContext* context, const TextRunPaintInfo& r unInfo, const AtomicString& mark, const FloatPoint& point) const |
| 127 { | 199 { |
| 128 if (shouldSkipDrawing()) | 200 if (shouldSkipDrawing()) |
| 129 return; | 201 return; |
| 130 | 202 |
| 131 CodePath codePathToUse = codePath(runInfo.run); | 203 GlyphBuffer glyphBuffer; |
| 132 // FIXME: Use the fast code path once it handles partial runs with kerning a nd ligatures. See http://webkit.org/b/100050 | 204 float initialAdvance = buildGlyphBuffer(runInfo, glyphBuffer, ForTextEmphasi s); |
| 133 if (codePathToUse != ComplexPath && fontDescription().typesettingFeatures() && (runInfo.from || runInfo.to != runInfo.run.length())) | |
| 134 codePathToUse = ComplexPath; | |
| 135 | 205 |
| 136 if (codePathToUse != ComplexPath) | 206 if (glyphBuffer.isEmpty()) |
| 137 drawEmphasisMarksForSimpleText(context, runInfo, mark, point); | 207 return; |
| 138 else | 208 |
| 139 drawEmphasisMarksForComplexText(context, runInfo, mark, point); | 209 drawEmphasisMarks(context, runInfo, glyphBuffer, mark, FloatPoint(point.x() + initialAdvance, point.y())); |
| 140 } | 210 } |
| 141 | 211 |
| 142 static inline void updateGlyphOverflowFromBounds(const IntRectExtent& glyphBound s, | 212 static inline void updateGlyphOverflowFromBounds(const IntRectExtent& glyphBound s, |
| 143 const FontMetrics& fontMetrics, GlyphOverflow* glyphOverflow) | 213 const FontMetrics& fontMetrics, GlyphOverflow* glyphOverflow) |
| 144 { | 214 { |
| 145 glyphOverflow->top = std::max<int>(glyphOverflow->top, | 215 glyphOverflow->top = std::max<int>(glyphOverflow->top, |
| 146 glyphBounds.top() - (glyphOverflow->computeBounds ? 0 : fontMetrics.asce nt())); | 216 glyphBounds.top() - (glyphOverflow->computeBounds ? 0 : fontMetrics.asce nt())); |
| 147 glyphOverflow->bottom = std::max<int>(glyphOverflow->bottom, | 217 glyphOverflow->bottom = std::max<int>(glyphOverflow->bottom, |
| 148 glyphBounds.bottom() - (glyphOverflow->computeBounds ? 0 : fontMetrics.d escent())); | 218 glyphBounds.bottom() - (glyphOverflow->computeBounds ? 0 : fontMetrics.d escent())); |
| 149 glyphOverflow->left = glyphBounds.left(); | 219 glyphOverflow->left = glyphBounds.left(); |
| (...skipping 452 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 602 return 0; | 672 return 0; |
| 603 | 673 |
| 604 const SimpleFontData* markFontData = markGlyphData.fontData; | 674 const SimpleFontData* markFontData = markGlyphData.fontData; |
| 605 ASSERT(markFontData); | 675 ASSERT(markFontData); |
| 606 if (!markFontData) | 676 if (!markFontData) |
| 607 return 0; | 677 return 0; |
| 608 | 678 |
| 609 return markFontData->fontMetrics().height(); | 679 return markFontData->fontMetrics().height(); |
| 610 } | 680 } |
| 611 | 681 |
| 612 float Font::getGlyphsAndAdvancesForSimpleText(const TextRunPaintInfo& runInfo, G lyphBuffer& glyphBuffer, ForTextEmphasisOrNot forTextEmphasis) const | 682 float Font::drawGlyphBuffer(GraphicsContext* context, const TextRunPaintInfo& ru nInfo, const GlyphBuffer& glyphBuffer, const FloatPoint& point) const |
| 613 { | |
| 614 float initialAdvance; | |
| 615 | |
| 616 WidthIterator it(this, runInfo.run, 0, false, forTextEmphasis); | |
| 617 it.advance(runInfo.from); | |
| 618 float beforeWidth = it.m_runWidthSoFar; | |
| 619 it.advance(runInfo.to, &glyphBuffer); | |
| 620 | |
| 621 if (glyphBuffer.isEmpty()) | |
| 622 return 0; | |
| 623 | |
| 624 float afterWidth = it.m_runWidthSoFar; | |
| 625 | |
| 626 if (runInfo.run.rtl()) { | |
| 627 it.advance(runInfo.run.length()); | |
| 628 initialAdvance = it.m_runWidthSoFar - afterWidth; | |
| 629 glyphBuffer.reverse(); | |
| 630 } else { | |
| 631 initialAdvance = beforeWidth; | |
| 632 } | |
| 633 | |
| 634 return initialAdvance; | |
| 635 } | |
| 636 | |
| 637 void Font::drawSimpleText(GraphicsContext* context, const TextRunPaintInfo& runI nfo, const FloatPoint& point) const | |
| 638 { | |
| 639 // This glyph buffer holds our glyphs+advances+font data for each glyph. | |
| 640 GlyphBuffer glyphBuffer; | |
| 641 float initialAdvance = getGlyphsAndAdvancesForSimpleText(runInfo, glyphBuffe r); | |
| 642 ASSERT(!glyphBuffer.hasVerticalAdvances()); | |
| 643 | |
| 644 if (glyphBuffer.isEmpty()) | |
| 645 return; | |
| 646 | |
| 647 TextBlobPtr textBlob; | |
| 648 if (RuntimeEnabledFeatures::textBlobEnabled()) { | |
| 649 // Using text blob causes a small difference in how gradients and | |
| 650 // patterns are rendered. | |
| 651 // FIXME: Fix this, most likely in Skia. | |
| 652 if (!context->strokeGradient() && !context->strokePattern() && !context- >fillGradient() && !context->fillPattern()) { | |
| 653 FloatRect blobBounds = runInfo.bounds; | |
| 654 blobBounds.moveBy(-point); | |
| 655 textBlob = buildTextBlob(glyphBuffer, initialAdvance, blobBounds); | |
| 656 } | |
| 657 } | |
| 658 | |
| 659 if (textBlob) { | |
| 660 drawTextBlob(context, textBlob.get(), point.data()); | |
| 661 } else { | |
| 662 FloatPoint startPoint(point.x() + initialAdvance, point.y()); | |
| 663 drawGlyphBuffer(context, runInfo, glyphBuffer, startPoint); | |
| 664 } | |
| 665 } | |
| 666 | |
| 667 void Font::drawEmphasisMarksForSimpleText(GraphicsContext* context, const TextRu nPaintInfo& runInfo, const AtomicString& mark, const FloatPoint& point) const | |
| 668 { | |
| 669 GlyphBuffer glyphBuffer; | |
| 670 float initialAdvance = getGlyphsAndAdvancesForSimpleText(runInfo, glyphBuffe r, ForTextEmphasis); | |
| 671 | |
| 672 if (glyphBuffer.isEmpty()) | |
| 673 return; | |
| 674 | |
| 675 drawEmphasisMarks(context, runInfo, glyphBuffer, mark, FloatPoint(point.x() + initialAdvance, point.y())); | |
| 676 } | |
| 677 | |
| 678 void Font::drawGlyphBuffer(GraphicsContext* context, const TextRunPaintInfo& run Info, const GlyphBuffer& glyphBuffer, const FloatPoint& point) const | |
| 679 { | 683 { |
| 680 // Draw each contiguous run of glyphs that use the same font data. | 684 // Draw each contiguous run of glyphs that use the same font data. |
| 681 const SimpleFontData* fontData = glyphBuffer.fontDataAt(0); | 685 const SimpleFontData* fontData = glyphBuffer.fontDataAt(0); |
| 682 FloatPoint startPoint(point); | 686 FloatPoint startPoint(point); |
| 683 FloatPoint nextPoint = startPoint + glyphBuffer.advanceAt(0); | 687 float advanceSoFar = 0; |
| 684 unsigned lastFrom = 0; | 688 unsigned lastFrom = 0; |
| 685 unsigned nextGlyph = 1; | 689 unsigned nextGlyph = 0; |
| 686 while (nextGlyph < glyphBuffer.size()) { | 690 while (nextGlyph < glyphBuffer.size()) { |
| 687 const SimpleFontData* nextFontData = glyphBuffer.fontDataAt(nextGlyph); | 691 const SimpleFontData* nextFontData = glyphBuffer.fontDataAt(nextGlyph); |
| 688 | |
| 689 if (nextFontData != fontData) { | 692 if (nextFontData != fontData) { |
| 690 drawGlyphs(context, fontData, glyphBuffer, lastFrom, nextGlyph - las tFrom, startPoint, runInfo.bounds); | 693 drawGlyphs(context, fontData, glyphBuffer, lastFrom, nextGlyph - las tFrom, startPoint, runInfo.bounds); |
| 691 | |
| 692 lastFrom = nextGlyph; | 694 lastFrom = nextGlyph; |
| 693 fontData = nextFontData; | 695 fontData = nextFontData; |
| 694 startPoint = nextPoint; | 696 startPoint += FloatSize(advanceSoFar, 0); |
| 697 advanceSoFar = 0; | |
| 695 } | 698 } |
| 696 nextPoint += glyphBuffer.advanceAt(nextGlyph); | 699 advanceSoFar += glyphBuffer.advanceAt(nextGlyph); |
| 697 nextGlyph++; | 700 nextGlyph++; |
| 698 } | 701 } |
| 702 drawGlyphs(context, fontData, glyphBuffer, lastFrom, nextGlyph - lastFrom, s tartPoint, runInfo.bounds); | |
| 703 startPoint += FloatSize(advanceSoFar, 0); | |
| 704 return startPoint.x() - point.x(); | |
| 705 } | |
| 699 | 706 |
| 700 drawGlyphs(context, fontData, glyphBuffer, lastFrom, nextGlyph - lastFrom, s tartPoint, runInfo.bounds); | |
| 701 } | |
| 702 | 707 |
| 703 inline static float offsetToMiddleOfGlyph(const SimpleFontData* fontData, Glyph glyph) | 708 inline static float offsetToMiddleOfGlyph(const SimpleFontData* fontData, Glyph glyph) |
| 704 { | 709 { |
| 705 if (fontData->platformData().orientation() == Horizontal) { | 710 if (fontData->platformData().orientation() == Horizontal) { |
| 706 FloatRect bounds = fontData->boundsForGlyph(glyph); | 711 FloatRect bounds = fontData->boundsForGlyph(glyph); |
| 707 return bounds.x() + bounds.width() / 2; | 712 return bounds.x() + bounds.width() / 2; |
| 708 } | 713 } |
| 709 // FIXME: Use glyph bounds once they make sense for vertical fonts. | 714 // FIXME: Use glyph bounds once they make sense for vertical fonts. |
| 710 return fontData->widthForGlyph(glyph) / 2; | 715 return fontData->widthForGlyph(glyph) / 2; |
| 711 } | 716 } |
| 712 | 717 |
| 713 inline static float offsetToMiddleOfAdvanceAtIndex(const GlyphBuffer& glyphBuffe r, size_t i) | 718 inline static float offsetToMiddleOfAdvanceAtIndex(const GlyphBuffer& glyphBuffe r, size_t i) |
| 714 { | 719 { |
| 715 return glyphBuffer.advanceAt(i).width() / 2; | 720 return glyphBuffer.advanceAt(i) / 2; |
| 716 } | 721 } |
| 717 | 722 |
| 718 void Font::drawEmphasisMarks(GraphicsContext* context, const TextRunPaintInfo& r unInfo, const GlyphBuffer& glyphBuffer, const AtomicString& mark, const FloatPoi nt& point) const | 723 void Font::drawEmphasisMarks(GraphicsContext* context, const TextRunPaintInfo& r unInfo, const GlyphBuffer& glyphBuffer, const AtomicString& mark, const FloatPoi nt& point) const |
| 719 { | 724 { |
| 720 FontCachePurgePreventer purgePreventer; | 725 FontCachePurgePreventer purgePreventer; |
| 721 | 726 |
| 722 GlyphData markGlyphData; | 727 GlyphData markGlyphData; |
| 723 if (!getEmphasisMarkGlyphData(mark, markGlyphData)) | 728 if (!getEmphasisMarkGlyphData(mark, markGlyphData)) |
| 724 return; | 729 return; |
| 725 | 730 |
| 726 const SimpleFontData* markFontData = markGlyphData.fontData; | 731 const SimpleFontData* markFontData = markGlyphData.fontData; |
| 727 ASSERT(markFontData); | 732 ASSERT(markFontData); |
| 728 if (!markFontData) | 733 if (!markFontData) |
| 729 return; | 734 return; |
| 730 | 735 |
| 731 Glyph markGlyph = markGlyphData.glyph; | 736 Glyph markGlyph = markGlyphData.glyph; |
| 732 Glyph spaceGlyph = markFontData->spaceGlyph(); | 737 Glyph spaceGlyph = markFontData->spaceGlyph(); |
| 733 | 738 |
| 734 float middleOfLastGlyph = offsetToMiddleOfAdvanceAtIndex(glyphBuffer, 0); | 739 float middleOfLastGlyph = offsetToMiddleOfAdvanceAtIndex(glyphBuffer, 0); |
| 735 FloatPoint startPoint(point.x() + middleOfLastGlyph - offsetToMiddleOfGlyph( markFontData, markGlyph), point.y()); | 740 FloatPoint startPoint(point.x() + middleOfLastGlyph - offsetToMiddleOfGlyph( markFontData, markGlyph), point.y()); |
| 736 | 741 |
| 737 GlyphBuffer markBuffer; | 742 GlyphBuffer markBuffer; |
| 738 for (unsigned i = 0; i + 1 < glyphBuffer.size(); ++i) { | 743 for (unsigned i = 0; i + 1 < glyphBuffer.size(); ++i) { |
| 739 float middleOfNextGlyph = offsetToMiddleOfAdvanceAtIndex(glyphBuffer, i + 1); | 744 float middleOfNextGlyph = offsetToMiddleOfAdvanceAtIndex(glyphBuffer, i + 1); |
| 740 float advance = glyphBuffer.advanceAt(i).width() - middleOfLastGlyph + m iddleOfNextGlyph; | 745 float advance = glyphBuffer.advanceAt(i) - middleOfLastGlyph + middleOfN extGlyph; |
| 741 markBuffer.add(glyphBuffer.glyphAt(i) ? markGlyph : spaceGlyph, markFont Data, advance); | 746 markBuffer.add(glyphBuffer.glyphAt(i) ? markGlyph : spaceGlyph, markFont Data, advance); |
| 742 middleOfLastGlyph = middleOfNextGlyph; | 747 middleOfLastGlyph = middleOfNextGlyph; |
| 743 } | 748 } |
| 744 markBuffer.add(glyphBuffer.glyphAt(glyphBuffer.size() - 1) ? markGlyph : spa ceGlyph, markFontData, 0); | 749 markBuffer.add(glyphBuffer.glyphAt(glyphBuffer.size() - 1) ? markGlyph : spa ceGlyph, markFontData, 0); |
| 745 | 750 |
| 746 drawGlyphBuffer(context, runInfo, markBuffer, startPoint); | 751 drawGlyphBuffer(context, runInfo, markBuffer, startPoint); |
| 747 } | 752 } |
| 748 | 753 |
| 749 float Font::floatWidthForSimpleText(const TextRun& run, HashSet<const SimpleFont Data*>* fallbackFonts, IntRectExtent* glyphBounds) const | 754 float Font::floatWidthForSimpleText(const TextRun& run, HashSet<const SimpleFont Data*>* fallbackFonts, IntRectExtent* glyphBounds) const |
| 750 { | 755 { |
| (...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 827 if (delta <= 0) | 832 if (delta <= 0) |
| 828 break; | 833 break; |
| 829 } | 834 } |
| 830 } | 835 } |
| 831 } | 836 } |
| 832 | 837 |
| 833 return offset; | 838 return offset; |
| 834 } | 839 } |
| 835 | 840 |
| 836 } // namespace blink | 841 } // namespace blink |
| OLD | NEW |