Merge Blink code to cache SkTextBlob This CL merges the following CLs from Blink to implement SkTextBlobs: https://codereview.chromium.org/554613004 https://codereview.chromium.org/645363003 https://codereview.chromium.org/667573008 https://codereview.chromium.org/672713002 https://codereview.chromium.org/778233002 https://codereview.chromium.org/820093005 https://codereview.chromium.org/856613002 R=esprehn@chromium.org Review URL: https://codereview.chromium.org/859203002
diff --git a/sky/engine/core/rendering/InlineTextBox.cpp b/sky/engine/core/rendering/InlineTextBox.cpp index cb54daf..a026235 100644 --- a/sky/engine/core/rendering/InlineTextBox.cpp +++ b/sky/engine/core/rendering/InlineTextBox.cpp
@@ -56,7 +56,7 @@ struct SameSizeAsInlineTextBox : public InlineBox { unsigned variables[1]; unsigned short variables2[2]; - void* pointers[2]; + void* pointers[3]; }; COMPILE_ASSERT(sizeof(InlineTextBox) == sizeof(SameSizeAsInlineTextBox), InlineTextBox_should_stay_small); @@ -416,13 +416,16 @@ const Font& font, const TextRun& textRun, const AtomicString& emphasisMark, int emphasisMarkOffset, int startOffset, int endOffset, int truncationPoint, - const FloatPoint& textOrigin, const FloatRect& boxRect) + const FloatPoint& textOrigin, const FloatRect& boxRect, + TextBlobPtr* cachedTextBlob = 0) { TextRunPaintInfo textRunPaintInfo(textRun); textRunPaintInfo.bounds = boxRect; if (startOffset <= endOffset) { textRunPaintInfo.from = startOffset; textRunPaintInfo.to = endOffset; + // FIXME: We should be able to use cachedTextBlob in more cases. + textRunPaintInfo.cachedTextBlob = cachedTextBlob; if (emphasisMark.isEmpty()) context->drawText(font, textRunPaintInfo, textOrigin); else @@ -460,11 +463,11 @@ void paintTextWithEmphasisMark( GraphicsContext* context, const Font& font, const TextPaintingStyle& textStyle, const TextRun& textRun, const AtomicString& emphasisMark, int emphasisMarkOffset, int startOffset, int endOffset, int length, - const FloatPoint& textOrigin, const FloatRect& boxRect) + const FloatPoint& textOrigin, const FloatRect& boxRect, TextBlobPtr* cachedTextBlob = 0) { GraphicsContextStateSaver stateSaver(*context, false); updateGraphicsContext(context, textStyle, stateSaver); - paintText(context, font, textRun, nullAtom, 0, startOffset, endOffset, length, textOrigin, boxRect); + paintText(context, font, textRun, nullAtom, 0, startOffset, endOffset, length, textOrigin, boxRect, cachedTextBlob); if (!emphasisMark.isEmpty()) { if (textStyle.emphasisMarkColor != textStyle.fillColor) @@ -603,12 +606,19 @@ startOffset = ePos; endOffset = sPos; } - paintTextWithEmphasisMark(context, font, textStyle, textRun, emphasisMark, emphasisMarkOffset, startOffset, endOffset, length, textOrigin, boxRect); + // FIXME: This cache should probably ultimately be held somewhere else. + // A hashmap is convenient to avoid a memory hit when the + // RuntimeEnabledFeature is off. + bool textBlobIsCacheable = RuntimeEnabledFeatures::textBlobEnabled() && startOffset == 0 && endOffset == length; + TextBlobPtr* cachedTextBlob = textBlobIsCacheable ? &m_cachedTextBlob : nullptr; + paintTextWithEmphasisMark(context, font, textStyle, textRun, emphasisMark, emphasisMarkOffset, startOffset, endOffset, length, textOrigin, boxRect, cachedTextBlob); } if ((paintSelectedTextOnly || paintSelectedTextSeparately) && sPos < ePos) { // paint only the text that is selected - paintTextWithEmphasisMark(context, font, selectionStyle, textRun, emphasisMark, emphasisMarkOffset, sPos, ePos, length, textOrigin, boxRect); + bool textBlobIsCacheable = RuntimeEnabledFeatures::textBlobEnabled() && sPos == 0 && ePos == length; + TextBlobPtr* cachedTextBlob = textBlobIsCacheable ? &m_cachedTextBlob : nullptr; + paintTextWithEmphasisMark(context, font, selectionStyle, textRun, emphasisMark, emphasisMarkOffset, sPos, ePos, length, textOrigin, boxRect, cachedTextBlob); } // Paint decorations
diff --git a/sky/engine/core/rendering/InlineTextBox.h b/sky/engine/core/rendering/InlineTextBox.h index ab67eee..76696f9 100644 --- a/sky/engine/core/rendering/InlineTextBox.h +++ b/sky/engine/core/rendering/InlineTextBox.h
@@ -161,6 +161,7 @@ private: InlineTextBox* m_prevTextBox; // The previous box that also uses our RenderObject InlineTextBox* m_nextTextBox; // The next box that also uses our RenderObject + TextBlobPtr m_cachedTextBlob; int m_start; unsigned short m_len;
diff --git a/sky/engine/platform/BUILD.gn b/sky/engine/platform/BUILD.gn index 63bf93c..20e644b 100644 --- a/sky/engine/platform/BUILD.gn +++ b/sky/engine/platform/BUILD.gn
@@ -699,7 +699,6 @@ "fonts/FontCacheTest.cpp", "fonts/FontDescriptionTest.cpp", "fonts/FontTest.cpp", - "fonts/GlyphBufferTest.cpp", "fonts/GlyphPageTreeNodeTest.cpp", "fonts/android/FontCacheAndroidTest.cpp", "geometry/FloatBoxTest.cpp",
diff --git a/sky/engine/platform/fonts/Font.cpp b/sky/engine/platform/fonts/Font.cpp index 3167834..b0c2975 100644 --- a/sky/engine/platform/fonts/Font.cpp +++ b/sky/engine/platform/fonts/Font.cpp
@@ -34,6 +34,7 @@ #include "sky/engine/platform/fonts/GlyphPageTreeNode.h" #include "sky/engine/platform/fonts/SimpleFontData.h" #include "sky/engine/platform/fonts/WidthIterator.h" +#include "sky/engine/platform/fonts/harfbuzz/HarfBuzzShaper.h" #include "sky/engine/platform/geometry/FloatRect.h" #include "sky/engine/platform/graphics/GraphicsContext.h" #include "sky/engine/platform/text/TextRun.h" @@ -103,24 +104,95 @@ m_fontFallbackList->invalidate(fontSelector); } -void Font::drawText(GraphicsContext* context, const TextRunPaintInfo& runInfo, const FloatPoint& point, CustomFontNotReadyAction customFontNotReadyAction) const +float Font::buildGlyphBuffer(const TextRunPaintInfo& runInfo, GlyphBuffer& glyphBuffer, + ForTextEmphasisOrNot forTextEmphasis) const +{ + if (codePath(runInfo.run) == ComplexPath) { + HarfBuzzShaper shaper(this, runInfo.run, (forTextEmphasis == ForTextEmphasis) + ? HarfBuzzShaper::ForTextEmphasis : HarfBuzzShaper::NotForTextEmphasis); + shaper.setDrawRange(runInfo.from, runInfo.to); + shaper.shape(&glyphBuffer); + + return 0; + } + + WidthIterator it(this, runInfo.run, nullptr, false, forTextEmphasis); + it.advance(runInfo.from); + float beforeWidth = it.runWidthSoFar(); + it.advance(runInfo.to, &glyphBuffer); + + if (runInfo.run.ltr()) + return beforeWidth; + + // RTL + float afterWidth = it.runWidthSoFar(); + it.advance(runInfo.run.length()); + glyphBuffer.reverse(); + + return it.runWidthSoFar() - afterWidth; +} + +void Font::drawText(GraphicsContext* context, const TextRunPaintInfo& runInfo, + const FloatPoint& point) const +{ + // Don't draw anything while we are using custom fonts that are in the process of loading. + if (shouldSkipDrawing()) + return; + + TextDrawingModeFlags textMode = context->textDrawingMode(); + if (!(textMode & TextModeFill) && !((textMode & TextModeStroke) && context->hasStroke())) + return; + + if (runInfo.cachedTextBlob && runInfo.cachedTextBlob->get()) { + ASSERT(RuntimeEnabledFeatures::textBlobEnabled()); + // we have a pre-cached blob -- happy joy! + drawTextBlob(context, runInfo.cachedTextBlob->get(), point.data()); + return; + } + + GlyphBuffer glyphBuffer; + float initialAdvance = buildGlyphBuffer(runInfo, glyphBuffer); + + if (glyphBuffer.isEmpty()) + return; + + if (RuntimeEnabledFeatures::textBlobEnabled()) { + // Enabling text-blobs forces the blob rendering path even for uncacheable blobs. + TextBlobPtr uncacheableTextBlob; + TextBlobPtr& textBlob = runInfo.cachedTextBlob ? *runInfo.cachedTextBlob : uncacheableTextBlob; + FloatRect blobBounds = runInfo.bounds; + blobBounds.moveBy(-point); + + textBlob = buildTextBlob(glyphBuffer, initialAdvance, blobBounds); + if (textBlob) { + drawTextBlob(context, textBlob.get(), point.data()); + return; + } + } + + drawGlyphBuffer(context, runInfo, glyphBuffer, FloatPoint(point.x() + initialAdvance, point.y())); +} + +float Font::drawUncachedText(GraphicsContext* context, const TextRunPaintInfo& runInfo, + const FloatPoint& point, CustomFontNotReadyAction customFontNotReadyAction) const { // Don't draw anything while we are using custom fonts that are in the process of loading, // except if the 'force' argument is set to true (in which case it will use a fallback // font). if (shouldSkipDrawing() && customFontNotReadyAction == DoNotPaintIfFontNotReady) - return; + return 0; - CodePath codePathToUse = codePath(runInfo.run); - // FIXME: Use the fast code path once it handles partial runs with kerning and ligatures. See http://webkit.org/b/100050 - if (codePathToUse != ComplexPath && fontDescription().typesettingFeatures() && (runInfo.from || runInfo.to != runInfo.run.length())) - codePathToUse = ComplexPath; + TextDrawingModeFlags textMode = context->textDrawingMode(); + if (!(textMode & TextModeFill) && !((textMode & TextModeStroke) && context->hasStroke())) + return 0; - if (codePathToUse != ComplexPath) { - drawSimpleText(context, runInfo, point); - } else { - drawComplexText(context, runInfo, point); - } + GlyphBuffer glyphBuffer; + float initialAdvance = buildGlyphBuffer(runInfo, glyphBuffer); + + if (glyphBuffer.isEmpty()) + return 0; + + return drawGlyphBuffer(context, runInfo, glyphBuffer, FloatPoint(point.x() + initialAdvance, point.y())); } void Font::drawEmphasisMarks(GraphicsContext* context, const TextRunPaintInfo& runInfo, const AtomicString& mark, const FloatPoint& point) const @@ -128,15 +200,13 @@ if (shouldSkipDrawing()) return; - CodePath codePathToUse = codePath(runInfo.run); - // FIXME: Use the fast code path once it handles partial runs with kerning and ligatures. See http://webkit.org/b/100050 - if (codePathToUse != ComplexPath && fontDescription().typesettingFeatures() && (runInfo.from || runInfo.to != runInfo.run.length())) - codePathToUse = ComplexPath; + GlyphBuffer glyphBuffer; + float initialAdvance = buildGlyphBuffer(runInfo, glyphBuffer, ForTextEmphasis); - if (codePathToUse != ComplexPath) - drawEmphasisMarksForSimpleText(context, runInfo, mark, point); - else - drawEmphasisMarksForComplexText(context, runInfo, mark, point); + if (glyphBuffer.isEmpty()) + return; + + drawEmphasisMarks(context, runInfo, glyphBuffer, mark, FloatPoint(point.x() + initialAdvance, point.y())); } static inline void updateGlyphOverflowFromBounds(const IntRectExtent& glyphBounds, @@ -609,97 +679,32 @@ return markFontData->fontMetrics().height(); } -float Font::getGlyphsAndAdvancesForSimpleText(const TextRunPaintInfo& runInfo, GlyphBuffer& glyphBuffer, ForTextEmphasisOrNot forTextEmphasis) const -{ - float initialAdvance; - - WidthIterator it(this, runInfo.run, 0, false, forTextEmphasis); - it.advance(runInfo.from); - float beforeWidth = it.m_runWidthSoFar; - it.advance(runInfo.to, &glyphBuffer); - - if (glyphBuffer.isEmpty()) - return 0; - - float afterWidth = it.m_runWidthSoFar; - - if (runInfo.run.rtl()) { - it.advance(runInfo.run.length()); - initialAdvance = it.m_runWidthSoFar - afterWidth; - glyphBuffer.reverse(); - } else { - initialAdvance = beforeWidth; - } - - return initialAdvance; -} - -void Font::drawSimpleText(GraphicsContext* context, const TextRunPaintInfo& runInfo, const FloatPoint& point) const -{ - // This glyph buffer holds our glyphs+advances+font data for each glyph. - GlyphBuffer glyphBuffer; - float initialAdvance = getGlyphsAndAdvancesForSimpleText(runInfo, glyphBuffer); - ASSERT(!glyphBuffer.hasVerticalAdvances()); - - if (glyphBuffer.isEmpty()) - return; - - TextBlobPtr textBlob; - if (RuntimeEnabledFeatures::textBlobEnabled()) { - // Using text blob causes a small difference in how gradients and - // patterns are rendered. - // FIXME: Fix this, most likely in Skia. - if (!context->strokeGradient() && !context->strokePattern() && !context->fillGradient() && !context->fillPattern()) { - FloatRect blobBounds = runInfo.bounds; - blobBounds.moveBy(-point); - textBlob = buildTextBlob(glyphBuffer, initialAdvance, blobBounds); - } - } - - if (textBlob) { - drawTextBlob(context, textBlob.get(), point.data()); - } else { - FloatPoint startPoint(point.x() + initialAdvance, point.y()); - drawGlyphBuffer(context, runInfo, glyphBuffer, startPoint); - } -} - -void Font::drawEmphasisMarksForSimpleText(GraphicsContext* context, const TextRunPaintInfo& runInfo, const AtomicString& mark, const FloatPoint& point) const -{ - GlyphBuffer glyphBuffer; - float initialAdvance = getGlyphsAndAdvancesForSimpleText(runInfo, glyphBuffer, ForTextEmphasis); - - if (glyphBuffer.isEmpty()) - return; - - drawEmphasisMarks(context, runInfo, glyphBuffer, mark, FloatPoint(point.x() + initialAdvance, point.y())); -} - -void Font::drawGlyphBuffer(GraphicsContext* context, const TextRunPaintInfo& runInfo, const GlyphBuffer& glyphBuffer, const FloatPoint& point) const +float Font::drawGlyphBuffer(GraphicsContext* context, const TextRunPaintInfo& runInfo, const GlyphBuffer& glyphBuffer, const FloatPoint& point) const { // Draw each contiguous run of glyphs that use the same font data. const SimpleFontData* fontData = glyphBuffer.fontDataAt(0); FloatPoint startPoint(point); - FloatPoint nextPoint = startPoint + glyphBuffer.advanceAt(0); + float advanceSoFar = 0; unsigned lastFrom = 0; - unsigned nextGlyph = 1; + unsigned nextGlyph = 0; while (nextGlyph < glyphBuffer.size()) { const SimpleFontData* nextFontData = glyphBuffer.fontDataAt(nextGlyph); - if (nextFontData != fontData) { drawGlyphs(context, fontData, glyphBuffer, lastFrom, nextGlyph - lastFrom, startPoint, runInfo.bounds); - lastFrom = nextGlyph; fontData = nextFontData; - startPoint = nextPoint; + startPoint += FloatSize(advanceSoFar, 0); + advanceSoFar = 0; } - nextPoint += glyphBuffer.advanceAt(nextGlyph); + advanceSoFar += glyphBuffer.advanceAt(nextGlyph); nextGlyph++; } - drawGlyphs(context, fontData, glyphBuffer, lastFrom, nextGlyph - lastFrom, startPoint, runInfo.bounds); + startPoint += FloatSize(advanceSoFar, 0); + return startPoint.x() - point.x(); } + inline static float offsetToMiddleOfGlyph(const SimpleFontData* fontData, Glyph glyph) { if (fontData->platformData().orientation() == Horizontal) { @@ -712,7 +717,7 @@ inline static float offsetToMiddleOfAdvanceAtIndex(const GlyphBuffer& glyphBuffer, size_t i) { - return glyphBuffer.advanceAt(i).width() / 2; + return glyphBuffer.advanceAt(i) / 2; } void Font::drawEmphasisMarks(GraphicsContext* context, const TextRunPaintInfo& runInfo, const GlyphBuffer& glyphBuffer, const AtomicString& mark, const FloatPoint& point) const @@ -737,7 +742,7 @@ GlyphBuffer markBuffer; for (unsigned i = 0; i + 1 < glyphBuffer.size(); ++i) { float middleOfNextGlyph = offsetToMiddleOfAdvanceAtIndex(glyphBuffer, i + 1); - float advance = glyphBuffer.advanceAt(i).width() - middleOfLastGlyph + middleOfNextGlyph; + float advance = glyphBuffer.advanceAt(i) - middleOfLastGlyph + middleOfNextGlyph; markBuffer.add(glyphBuffer.glyphAt(i) ? markGlyph : spaceGlyph, markFontData, advance); middleOfLastGlyph = middleOfNextGlyph; }
diff --git a/sky/engine/platform/fonts/Font.h b/sky/engine/platform/fonts/Font.h index 213915f..f57afd0 100644 --- a/sky/engine/platform/fonts/Font.h +++ b/sky/engine/platform/fonts/Font.h
@@ -100,7 +100,8 @@ void update(PassRefPtr<FontSelector>) const; enum CustomFontNotReadyAction { DoNotPaintIfFontNotReady, UseFallbackIfFontNotReady }; - void drawText(GraphicsContext*, const TextRunPaintInfo&, const FloatPoint&, CustomFontNotReadyAction = DoNotPaintIfFontNotReady) const; + void drawText(GraphicsContext*, const TextRunPaintInfo&, const FloatPoint&) const; + float drawUncachedText(GraphicsContext*, const TextRunPaintInfo&, const FloatPoint&, CustomFontNotReadyAction) const; void drawEmphasisMarks(GraphicsContext*, const TextRunPaintInfo&, const AtomicString& mark, const FloatPoint&) const; float width(const TextRun&, HashSet<const SimpleFontData*>* fallbackFonts = 0, GlyphOverflow* = 0) const; @@ -136,12 +137,11 @@ enum ForTextEmphasisOrNot { NotForTextEmphasis, ForTextEmphasis }; // Returns the initial in-stream advance. - float getGlyphsAndAdvancesForSimpleText(const TextRunPaintInfo&, GlyphBuffer&, ForTextEmphasisOrNot = NotForTextEmphasis) const; - void drawSimpleText(GraphicsContext*, const TextRunPaintInfo&, const FloatPoint&) const; - void drawEmphasisMarksForSimpleText(GraphicsContext*, const TextRunPaintInfo&, const AtomicString& mark, const FloatPoint&) const; + float buildGlyphBuffer(const TextRunPaintInfo&, GlyphBuffer&, ForTextEmphasisOrNot = NotForTextEmphasis) const; + PassTextBlobPtr buildTextBlob(const GlyphBuffer&, float initialAdvance, const FloatRect& bounds) const; void drawGlyphs(GraphicsContext*, const SimpleFontData*, const GlyphBuffer&, unsigned from, unsigned numGlyphs, const FloatPoint&, const FloatRect& textRect) const; - void drawGlyphBuffer(GraphicsContext*, const TextRunPaintInfo&, const GlyphBuffer&, const FloatPoint&) const; void drawTextBlob(GraphicsContext*, const SkTextBlob*, const SkPoint& origin) const; + float drawGlyphBuffer(GraphicsContext*, const TextRunPaintInfo&, const GlyphBuffer&, const FloatPoint&) const; void drawEmphasisMarks(GraphicsContext*, const TextRunPaintInfo&, const GlyphBuffer&, const AtomicString&, const FloatPoint&) const; float floatWidthForSimpleText(const TextRun&, HashSet<const SimpleFontData*>* fallbackFonts = 0, IntRectExtent* glyphBounds = 0) const; int offsetForPositionForSimpleText(const TextRun&, float position, bool includePartialGlyphs) const; @@ -149,10 +149,6 @@ bool getEmphasisMarkGlyphData(const AtomicString&, GlyphData&) const; - // Returns the initial in-stream advance. - float getGlyphsAndAdvancesForComplexText(const TextRunPaintInfo&, GlyphBuffer&, ForTextEmphasisOrNot = NotForTextEmphasis) const; - void drawComplexText(GraphicsContext*, const TextRunPaintInfo&, const FloatPoint&) const; - void drawEmphasisMarksForComplexText(GraphicsContext*, const TextRunPaintInfo&, const AtomicString& mark, const FloatPoint&) const; float floatWidthForComplexText(const TextRun&, HashSet<const SimpleFontData*>* fallbackFonts, IntRectExtent* glyphBounds) const; int offsetForPositionForComplexText(const TextRun&, float position, bool includePartialGlyphs) const; FloatRect selectionRectForComplexText(const TextRun&, const FloatPoint&, int h, int from, int to) const; @@ -183,8 +179,6 @@ return m_fontFallbackList && m_fontFallbackList->shouldSkipDrawing(); } - PassTextBlobPtr buildTextBlob(const GlyphBuffer&, float initialAdvance, const FloatRect& bounds) const; - FontDescription m_fontDescription; mutable RefPtr<FontFallbackList> m_fontFallbackList; };
diff --git a/sky/engine/platform/fonts/GlyphBuffer.h b/sky/engine/platform/fonts/GlyphBuffer.h index 7249213..c9e8a42 100644 --- a/sky/engine/platform/fonts/GlyphBuffer.h +++ b/sky/engine/platform/fonts/GlyphBuffer.h
@@ -40,22 +40,23 @@ class GlyphBuffer { public: - GlyphBuffer() : m_hasVerticalAdvances(false) { } + GlyphBuffer() { } bool isEmpty() const { return m_fontData.isEmpty(); } + bool hasOffsets() const { return !m_offsets.isEmpty(); } unsigned size() const { return m_fontData.size(); } - bool hasVerticalAdvances() const { return m_hasVerticalAdvances; } void clear() { m_fontData.clear(); m_glyphs.clear(); m_advances.clear(); - m_hasVerticalAdvances = false; + m_offsets.clear(); } const Glyph* glyphs(unsigned from) const { return m_glyphs.data() + from; } - const FloatSize* advances(unsigned from) const { return m_advances.data() + from; } + const float* advances(unsigned from) const { return m_advances.data() + from; } + const FloatSize* offsets(unsigned from) const { return m_offsets.data() + from; } const SimpleFontData* fontDataAt(unsigned index) const { return m_fontData[index]; } @@ -64,25 +65,30 @@ return m_glyphs[index]; } - FloatSize advanceAt(unsigned index) const + float advanceAt(unsigned index) const { return m_advances[index]; } void add(Glyph glyph, const SimpleFontData* font, float width) { + // should not mix offset/advance-only glyphs + ASSERT(!hasOffsets()); + m_fontData.append(font); m_glyphs.append(glyph); - m_advances.append(FloatSize(width, 0)); + m_advances.append(width); } - void add(Glyph glyph, const SimpleFontData* font, const FloatSize& advance) + void add(Glyph glyph, const SimpleFontData* font, const FloatSize& offset, float advance) { + // should not mix offset/advance-only glyphs + ASSERT(size() == m_offsets.size()); + m_fontData.append(font); m_glyphs.append(glyph); + m_offsets.append(offset); m_advances.append(advance); - if (advance.height()) - m_hasVerticalAdvances = true; } void reverse() @@ -92,23 +98,18 @@ m_advances.reverse(); } - void setAdvanceWidth(unsigned index, float newWidth) - { - m_advances[index].setWidth(newWidth); - } - void expandLastAdvance(float width) { ASSERT(!isEmpty()); - FloatSize& lastAdvance = m_advances.last(); - lastAdvance.setWidth(lastAdvance.width() + width); + float& lastAdvance = m_advances.last(); + lastAdvance += width; } private: Vector<const SimpleFontData*, 2048> m_fontData; Vector<Glyph, 2048> m_glyphs; - Vector<FloatSize, 2048> m_advances; - bool m_hasVerticalAdvances; + Vector<float, 2048> m_advances; + Vector<FloatSize, 1024> m_offsets; }; } // namespace blink
diff --git a/sky/engine/platform/fonts/GlyphBufferTest.cpp b/sky/engine/platform/fonts/GlyphBufferTest.cpp deleted file mode 100644 index 37d3d45..0000000 --- a/sky/engine/platform/fonts/GlyphBufferTest.cpp +++ /dev/null
@@ -1,237 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "sky/engine/config.h" -#include "sky/engine/platform/fonts/GlyphBuffer.h" - -#include <gtest/gtest.h> -#include "sky/engine/platform/fonts/SimpleFontData.h" -#include "sky/engine/wtf/PassRefPtr.h" -#include "sky/engine/wtf/RefPtr.h" - -using namespace blink; - -namespace { - -// Minimal TestSimpleFontData implementation. -// Font has no glyphs, but that's okay. -class TestSimpleFontData : public SimpleFontData { -public: - static PassRefPtr<TestSimpleFontData> create() - { - return adoptRef(new TestSimpleFontData); - } - -private: - TestSimpleFontData() : SimpleFontData(nullptr, 10, false, false) { } - - bool fillGlyphPage(GlyphPage* pageToFill, unsigned offset, unsigned length, UChar* buffer, unsigned bufferLength) const override - { - return false; - } -}; - -TEST(GlyphBufferTest, StartsEmpty) -{ - GlyphBuffer glyphBuffer; - EXPECT_TRUE(glyphBuffer.isEmpty()); - EXPECT_EQ(0u, glyphBuffer.size()); -} - -TEST(GlyphBufferTest, StoresGlyphs) -{ - RefPtr<SimpleFontData> font1 = TestSimpleFontData::create(); - RefPtr<SimpleFontData> font2 = TestSimpleFontData::create(); - - GlyphBuffer glyphBuffer; - glyphBuffer.add(42, font1.get(), 10); - glyphBuffer.add(43, font1.get(), 15); - glyphBuffer.add(44, font2.get(), FloatSize(12, 2)); - - EXPECT_FALSE(glyphBuffer.isEmpty()); - EXPECT_EQ(3u, glyphBuffer.size()); - - EXPECT_EQ(42, glyphBuffer.glyphAt(0)); - EXPECT_EQ(43, glyphBuffer.glyphAt(1)); - EXPECT_EQ(44, glyphBuffer.glyphAt(2)); - - const Glyph* glyphs = glyphBuffer.glyphs(0); - EXPECT_EQ(42, glyphs[0]); - EXPECT_EQ(43, glyphs[1]); - EXPECT_EQ(44, glyphs[2]); -} - -TEST(GlyphBufferTest, StoresAdvances) -{ - RefPtr<SimpleFontData> font1 = TestSimpleFontData::create(); - RefPtr<SimpleFontData> font2 = TestSimpleFontData::create(); - - GlyphBuffer glyphBuffer; - glyphBuffer.add(42, font1.get(), 10); - glyphBuffer.add(43, font1.get(), 15); - glyphBuffer.add(44, font2.get(), FloatSize(12, 2)); - - EXPECT_FALSE(glyphBuffer.isEmpty()); - EXPECT_EQ(3u, glyphBuffer.size()); - - EXPECT_EQ(FloatSize(10, 0), glyphBuffer.advanceAt(0)); - EXPECT_EQ(FloatSize(15, 0), glyphBuffer.advanceAt(1)); - EXPECT_EQ(FloatSize(12, 2), glyphBuffer.advanceAt(2)); - - const FloatSize* advances = glyphBuffer.advances(0); - EXPECT_EQ(FloatSize(10, 0), advances[0]); - EXPECT_EQ(FloatSize(15, 0), advances[1]); - EXPECT_EQ(FloatSize(12, 2), advances[2]); -} - -TEST(GlyphBufferTest, StoresSimpleFontData) -{ - RefPtr<SimpleFontData> font1 = TestSimpleFontData::create(); - RefPtr<SimpleFontData> font2 = TestSimpleFontData::create(); - - GlyphBuffer glyphBuffer; - glyphBuffer.add(42, font1.get(), 10); - glyphBuffer.add(43, font1.get(), 15); - glyphBuffer.add(44, font2.get(), FloatSize(12, 2)); - - EXPECT_FALSE(glyphBuffer.isEmpty()); - EXPECT_EQ(3u, glyphBuffer.size()); - - EXPECT_EQ(font1.get(), glyphBuffer.fontDataAt(0)); - EXPECT_EQ(font1.get(), glyphBuffer.fontDataAt(1)); - EXPECT_EQ(font2.get(), glyphBuffer.fontDataAt(2)); -} - -TEST(GlyphBufferTest, GlyphArrayWithOffset) -{ - RefPtr<SimpleFontData> font1 = TestSimpleFontData::create(); - RefPtr<SimpleFontData> font2 = TestSimpleFontData::create(); - - GlyphBuffer glyphBuffer; - glyphBuffer.add(42, font1.get(), 10); - glyphBuffer.add(43, font1.get(), 15); - glyphBuffer.add(44, font2.get(), FloatSize(12, 2)); - - EXPECT_FALSE(glyphBuffer.isEmpty()); - EXPECT_EQ(3u, glyphBuffer.size()); - - const Glyph* glyphs = glyphBuffer.glyphs(1); - EXPECT_EQ(43, glyphs[0]); - EXPECT_EQ(44, glyphs[1]); -} - -TEST(GlyphBufferTest, AdvanceArrayWithOffset) -{ - RefPtr<SimpleFontData> font1 = TestSimpleFontData::create(); - RefPtr<SimpleFontData> font2 = TestSimpleFontData::create(); - - GlyphBuffer glyphBuffer; - glyphBuffer.add(42, font1.get(), 10); - glyphBuffer.add(43, font1.get(), 15); - glyphBuffer.add(44, font2.get(), FloatSize(12, 2)); - - EXPECT_FALSE(glyphBuffer.isEmpty()); - EXPECT_EQ(3u, glyphBuffer.size()); - - const FloatSize* advances = glyphBuffer.advances(1); - EXPECT_EQ(FloatSize(15, 0), advances[0]); - EXPECT_EQ(FloatSize(12, 2), advances[1]); -} - -TEST(GlyphBufferTest, Clear) -{ - RefPtr<SimpleFontData> font1 = TestSimpleFontData::create(); - RefPtr<SimpleFontData> font2 = TestSimpleFontData::create(); - - GlyphBuffer glyphBuffer; - glyphBuffer.add(42, font1.get(), 10); - glyphBuffer.add(43, font1.get(), 15); - glyphBuffer.add(44, font2.get(), FloatSize(12, 2)); - - EXPECT_FALSE(glyphBuffer.isEmpty()); - EXPECT_EQ(3u, glyphBuffer.size()); - - glyphBuffer.clear(); - - EXPECT_TRUE(glyphBuffer.isEmpty()); - EXPECT_EQ(0u, glyphBuffer.size()); -} - -TEST(GlyphBufferTest, TracksVerticalAdvances) -{ - RefPtr<SimpleFontData> font = TestSimpleFontData::create(); - GlyphBuffer glyphBuffer; - EXPECT_FALSE(glyphBuffer.hasVerticalAdvances()); - glyphBuffer.add(42, font.get(), 10); - EXPECT_FALSE(glyphBuffer.hasVerticalAdvances()); - glyphBuffer.add(43, font.get(), FloatSize(15, 0)); - EXPECT_FALSE(glyphBuffer.hasVerticalAdvances()); - glyphBuffer.add(44, font.get(), FloatSize(10, 5)); - EXPECT_TRUE(glyphBuffer.hasVerticalAdvances()); - glyphBuffer.clear(); - EXPECT_FALSE(glyphBuffer.hasVerticalAdvances()); -} - -TEST(GlyphBufferTest, Reverse) -{ - RefPtr<SimpleFontData> font1 = TestSimpleFontData::create(); - RefPtr<SimpleFontData> font2 = TestSimpleFontData::create(); - - GlyphBuffer glyphBuffer; - glyphBuffer.add(42, font1.get(), 10); - glyphBuffer.add(43, font1.get(), 15); - glyphBuffer.add(44, font2.get(), FloatSize(12, 2)); - - EXPECT_FALSE(glyphBuffer.isEmpty()); - EXPECT_EQ(3u, glyphBuffer.size()); - EXPECT_TRUE(glyphBuffer.hasVerticalAdvances()); - - glyphBuffer.reverse(); - - EXPECT_FALSE(glyphBuffer.isEmpty()); - EXPECT_EQ(3u, glyphBuffer.size()); - EXPECT_TRUE(glyphBuffer.hasVerticalAdvances()); - EXPECT_EQ(44, glyphBuffer.glyphAt(0)); - EXPECT_EQ(43, glyphBuffer.glyphAt(1)); - EXPECT_EQ(42, glyphBuffer.glyphAt(2)); - EXPECT_EQ(FloatSize(12, 2), glyphBuffer.advanceAt(0)); - EXPECT_EQ(FloatSize(15, 0), glyphBuffer.advanceAt(1)); - EXPECT_EQ(FloatSize(10, 0), glyphBuffer.advanceAt(2)); - EXPECT_EQ(font2.get(), glyphBuffer.fontDataAt(0)); - EXPECT_EQ(font1.get(), glyphBuffer.fontDataAt(1)); - EXPECT_EQ(font1.get(), glyphBuffer.fontDataAt(2)); -} - -TEST(GlyphBufferTest, SetAdvanceWidth) -{ - RefPtr<SimpleFontData> font1 = TestSimpleFontData::create(); - RefPtr<SimpleFontData> font2 = TestSimpleFontData::create(); - - GlyphBuffer glyphBuffer; - glyphBuffer.add(42, font1.get(), 10); - glyphBuffer.add(43, font1.get(), 15); - glyphBuffer.add(44, font2.get(), FloatSize(12, 2)); - - glyphBuffer.setAdvanceWidth(1, 20); - EXPECT_EQ(FloatSize(20, 0), glyphBuffer.advanceAt(1)); - - glyphBuffer.setAdvanceWidth(2, 10); - EXPECT_EQ(FloatSize(10, 2), glyphBuffer.advanceAt(2)); -} - -TEST(GlyphBufferTest, ExpandLastAdvance) -{ - RefPtr<SimpleFontData> font1 = TestSimpleFontData::create(); - RefPtr<SimpleFontData> font2 = TestSimpleFontData::create(); - - GlyphBuffer glyphBuffer; - glyphBuffer.add(42, font1.get(), 10); - glyphBuffer.add(43, font1.get(), 15); - glyphBuffer.add(44, font2.get(), FloatSize(12, 2)); - - glyphBuffer.expandLastAdvance(20); - EXPECT_EQ(FloatSize(32, 2), glyphBuffer.advanceAt(2)); -} - -} // namespace
diff --git a/sky/engine/platform/fonts/harfbuzz/FontHarfBuzz.cpp b/sky/engine/platform/fonts/harfbuzz/FontHarfBuzz.cpp index 998b38b..af34cba 100644 --- a/sky/engine/platform/fonts/harfbuzz/FontHarfBuzz.cpp +++ b/sky/engine/platform/fonts/harfbuzz/FontHarfBuzz.cpp
@@ -31,7 +31,7 @@ #include "sky/engine/config.h" #include "sky/engine/platform/fonts/Font.h" -#include "sky/engine/platform/NotImplemented.h" +#include "gen/sky/platform/RuntimeEnabledFeatures.h" #include "sky/engine/platform/fonts/FontPlatformFeatures.h" #include "sky/engine/platform/fonts/GlyphBuffer.h" #include "sky/engine/platform/fonts/SimpleFontData.h" @@ -157,7 +157,7 @@ pos[i].set( x + SkIntToScalar(lroundf(translations[i].x())), y + -SkIntToScalar(-lroundf(currentWidth - translations[i].y()))); - currentWidth += glyphBuffer.advanceAt(from + glyphIndex).width(); + currentWidth += glyphBuffer.advanceAt(from + glyphIndex); } horizontalOffset += currentWidth; paintGlyphs(gc, font, glyphs, chunkLength, pos, textRect); @@ -167,13 +167,13 @@ return; } - if (!glyphBuffer.hasVerticalAdvances()) { + if (!glyphBuffer.hasOffsets()) { SkAutoSTMalloc<64, SkScalar> storage(numGlyphs); SkScalar* xpos = storage.get(); - const FloatSize* adv = glyphBuffer.advances(from); + const float* adv = glyphBuffer.advances(from); for (unsigned i = 0; i < numGlyphs; i++) { xpos[i] = x; - x += SkFloatToScalar(adv[i].width()); + x += SkFloatToScalar(adv[i]); } const Glyph* glyphs = glyphBuffer.glyphs(from); paintGlyphsHorizontal(gc, font, glyphs, numGlyphs, xpos, SkFloatToScalar(y), textRect); @@ -188,11 +188,14 @@ // here. SkAutoSTMalloc<32, SkPoint> storage(numGlyphs); SkPoint* pos = storage.get(); - const FloatSize* adv = glyphBuffer.advances(from); + const FloatSize* offsets = glyphBuffer.offsets(from); + const float* advances = glyphBuffer.advances(from); + SkScalar advanceSoFar = SkFloatToScalar(0); for (unsigned i = 0; i < numGlyphs; i++) { - pos[i].set(x, y); - x += SkFloatToScalar(adv[i].width()); - y += SkFloatToScalar(adv[i].height()); + pos[i].set( + x + SkFloatToScalar(offsets[i].width()) + advanceSoFar, + y + SkFloatToScalar(offsets[i].height())); + advanceSoFar += SkFloatToScalar(advances[i]); } const Glyph* glyphs = glyphBuffer.glyphs(from); @@ -201,69 +204,24 @@ void Font::drawTextBlob(GraphicsContext* gc, const SkTextBlob* blob, const SkPoint& origin) const { + ASSERT(RuntimeEnabledFeatures::textBlobEnabled()); + // FIXME: It would be good to move this to Font.cpp, if we're sure that none // of the things in FontMac's setupPaint need to apply here. // See also paintGlyphs. TextDrawingModeFlags textMode = gc->textDrawingMode(); - if (textMode & TextModeFill) { - SkPaint paint = gc->fillPaint(); - gc->adjustTextRenderMode(&paint); - paint.setTextEncoding(SkPaint::kGlyphID_TextEncoding); - gc->drawTextBlob(blob, origin, paint); - } + if (textMode & TextModeFill) + gc->drawTextBlob(blob, origin, gc->fillPaint()); if ((textMode & TextModeStroke) && gc->hasStroke()) { SkPaint paint = gc->strokePaint(); - gc->adjustTextRenderMode(&paint); - paint.setTextEncoding(SkPaint::kGlyphID_TextEncoding); if (textMode & TextModeFill) paint.setLooper(0); gc->drawTextBlob(blob, origin, paint); } } -void Font::drawComplexText(GraphicsContext* gc, const TextRunPaintInfo& runInfo, const FloatPoint& point) const -{ - if (!runInfo.run.length()) - return; - - TextDrawingModeFlags textMode = gc->textDrawingMode(); - bool fill = textMode & TextModeFill; - bool stroke = (textMode & TextModeStroke) && gc->hasStroke(); - - if (!fill && !stroke) - return; - - GlyphBuffer glyphBuffer; - HarfBuzzShaper shaper(this, runInfo.run); - shaper.setDrawRange(runInfo.from, runInfo.to); - if (!shaper.shape(&glyphBuffer) || glyphBuffer.isEmpty()) - return; - FloatPoint adjustedPoint = shaper.adjustStartPoint(point); - drawGlyphBuffer(gc, runInfo, glyphBuffer, adjustedPoint); -} - -void Font::drawEmphasisMarksForComplexText(GraphicsContext* context, const TextRunPaintInfo& runInfo, const AtomicString& mark, const FloatPoint& point) const -{ - GlyphBuffer glyphBuffer; - - float initialAdvance = getGlyphsAndAdvancesForComplexText(runInfo, glyphBuffer, ForTextEmphasis); - - if (glyphBuffer.isEmpty()) - return; - - drawEmphasisMarks(context, runInfo, glyphBuffer, mark, FloatPoint(point.x() + initialAdvance, point.y())); -} - -float Font::getGlyphsAndAdvancesForComplexText(const TextRunPaintInfo& runInfo, GlyphBuffer& glyphBuffer, ForTextEmphasisOrNot forTextEmphasis) const -{ - HarfBuzzShaper shaper(this, runInfo.run, HarfBuzzShaper::ForTextEmphasis); - shaper.setDrawRange(runInfo.from, runInfo.to); - shaper.shape(&glyphBuffer); - return 0; -} - float Font::floatWidthForComplexText(const TextRun& run, HashSet<const SimpleFontData*>* fallbackFonts, IntRectExtent* glyphBounds) const { HarfBuzzShaper shaper(this, run, HarfBuzzShaper::NotForTextEmphasis, fallbackFonts); @@ -299,27 +257,23 @@ return shaper.selectionRect(point, height, from, to); } -PassTextBlobPtr Font::buildTextBlob(const GlyphBuffer& glyphBuffer, float initialAdvance, const FloatRect& bounds) const +namespace { + +template <bool hasOffsets> +bool buildTextBlobInternal(const GlyphBuffer& glyphBuffer, SkScalar initialAdvance, SkTextBlobBuilder& builder) { - // FIXME: Except for setupPaint, this is not specific to FontHarfBuzz. - // FIXME: Also implement the more general full-positioning path. - ASSERT(!glyphBuffer.hasVerticalAdvances()); - - SkTextBlobBuilder builder; - SkScalar x = SkFloatToScalar(initialAdvance); - SkRect skBounds = bounds; - + SkScalar x = initialAdvance; unsigned i = 0; while (i < glyphBuffer.size()) { const SimpleFontData* fontData = glyphBuffer.fontDataAt(i); // FIXME: Handle vertical text. if (fontData->platformData().orientation() == Vertical) - return nullptr; + return false; // FIXME: Handle SVG fonts. if (fontData->isSVGFont()) - return nullptr; + return false; // FIXME: FontPlatformData makes some decisions on the device scale // factor, which is found via the GraphicsContext. This should be fixed @@ -333,19 +287,43 @@ i++; unsigned count = i - start; - const SkTextBlobBuilder::RunBuffer& buffer = builder.allocRunPosH(paint, count, 0, &skBounds); + const SkTextBlobBuilder::RunBuffer& buffer = hasOffsets ? + builder.allocRunPos(paint, count) : + builder.allocRunPosH(paint, count, 0); const uint16_t* glyphs = glyphBuffer.glyphs(start); std::copy(glyphs, glyphs + count, buffer.glyphs); - const FloatSize* advances = glyphBuffer.advances(start); + const float* advances = glyphBuffer.advances(start); + const FloatSize* offsets = glyphBuffer.offsets(start); for (unsigned j = 0; j < count; j++) { - buffer.pos[j] = x; - x += SkFloatToScalar(advances[j].width()); + if (hasOffsets) { + const FloatSize& offset = offsets[j]; + buffer.pos[2 * j] = x + offset.width(); + buffer.pos[2 * j + 1] = offset.height(); + } else { + buffer.pos[j] = x; + } + x += SkFloatToScalar(advances[j]); } } - - return adoptRef(builder.build()); + return true; } +} // namespace + +PassTextBlobPtr Font::buildTextBlob(const GlyphBuffer& glyphBuffer, float initialAdvance, const FloatRect& bounds) const +{ + ASSERT(RuntimeEnabledFeatures::textBlobEnabled()); + + SkTextBlobBuilder builder; + SkScalar advance = SkFloatToScalar(initialAdvance); + + bool success = glyphBuffer.hasOffsets() ? + buildTextBlobInternal<true>(glyphBuffer, advance, builder) : + buildTextBlobInternal<false>(glyphBuffer, advance, builder); + return success ? adoptRef(builder.build()) : nullptr; +} + + } // namespace blink
diff --git a/sky/engine/platform/fonts/harfbuzz/HarfBuzzShaper.cpp b/sky/engine/platform/fonts/harfbuzz/HarfBuzzShaper.cpp index 34fc737..1a3da20 100644 --- a/sky/engine/platform/fonts/harfbuzz/HarfBuzzShaper.cpp +++ b/sky/engine/platform/fonts/harfbuzz/HarfBuzzShaper.cpp
@@ -278,7 +278,7 @@ { m_glyphs[index] = glyphId; m_advances[index] = advance; - m_offsets[index] = FloatPoint(offsetX, offsetY); + m_offsets[index] = FloatSize(offsetX, offsetY); } int HarfBuzzShaper::HarfBuzzRun::characterIndexForXPosition(float targetX) @@ -571,11 +571,6 @@ return true; } -FloatPoint HarfBuzzShaper::adjustStartPoint(const FloatPoint& point) -{ - return point + m_startOffset; -} - static inline int handleMultipleUChar( UChar32 character, unsigned clusterLength, @@ -950,29 +945,35 @@ m_totalWidth += currentRun->width(); } -void HarfBuzzShaper::fillGlyphBufferFromHarfBuzzRun(GlyphBuffer* glyphBuffer, HarfBuzzRun* currentRun, FloatPoint& firstOffsetOfNextRun) +void HarfBuzzShaper::fillGlyphBufferFromHarfBuzzRun(GlyphBuffer* glyphBuffer, HarfBuzzRun* currentRun, float& carryAdvance) { - FloatPoint* offsets = currentRun->offsets(); + FloatSize* offsets = currentRun->offsets(); uint16_t* glyphs = currentRun->glyphs(); float* advances = currentRun->advances(); unsigned numGlyphs = currentRun->numGlyphs(); uint16_t* glyphToCharacterIndexes = currentRun->glyphToCharacterIndexes(); - for (unsigned i = 0; i < numGlyphs; ++i) { - uint16_t currentCharacterIndex = currentRun->startIndex() + glyphToCharacterIndexes[i]; - FloatPoint& currentOffset = offsets[i]; - FloatPoint& nextOffset = (i == numGlyphs - 1) ? firstOffsetOfNextRun : offsets[i + 1]; - float glyphAdvanceX = advances[i] + nextOffset.x() - currentOffset.x(); - float glyphAdvanceY = nextOffset.y() - currentOffset.y(); - if (m_run.rtl()) { - if (currentCharacterIndex >= m_toIndex) - m_startOffset.move(glyphAdvanceX, glyphAdvanceY); - else if (currentCharacterIndex >= m_fromIndex) - glyphBuffer->add(glyphs[i], currentRun->fontData(), FloatSize(glyphAdvanceX, glyphAdvanceY)); - } else { - if (currentCharacterIndex < m_fromIndex) - m_startOffset.move(glyphAdvanceX, glyphAdvanceY); - else if (currentCharacterIndex < m_toIndex) - glyphBuffer->add(glyphs[i], currentRun->fontData(), FloatSize(glyphAdvanceX, glyphAdvanceY)); + FloatSize runStartOffset = FloatSize(); + if (m_run.rtl()) { + for (unsigned i = 0; i < numGlyphs; ++i) { + uint16_t currentCharacterIndex = currentRun->startIndex() + glyphToCharacterIndexes[i]; + if (currentCharacterIndex >= m_toIndex) { + carryAdvance += advances[i]; + } else if (currentCharacterIndex >= m_fromIndex) { + runStartOffset = HB_DIRECTION_IS_HORIZONTAL(currentRun->direction()) ? FloatSize(carryAdvance, 0) : FloatSize(0, carryAdvance); + glyphBuffer->add(glyphs[i], currentRun->fontData(), runStartOffset + offsets[i], carryAdvance + advances[i]); + carryAdvance = 0; + } + } + } else { + for (unsigned i = 0; i < numGlyphs; ++i) { + uint16_t currentCharacterIndex = currentRun->startIndex() + glyphToCharacterIndexes[i]; + if (currentCharacterIndex < m_fromIndex) { + carryAdvance += advances[i]; + } else if (currentCharacterIndex < m_toIndex) { + runStartOffset = HB_DIRECTION_IS_HORIZONTAL(currentRun->direction()) ? FloatSize(carryAdvance, 0) : FloatSize(0, carryAdvance); + glyphBuffer->add(glyphs[i], currentRun->fontData(), runStartOffset + offsets[i], carryAdvance + advances[i]); + carryAdvance = 0; + } } } } @@ -1034,33 +1035,30 @@ bool HarfBuzzShaper::fillGlyphBuffer(GlyphBuffer* glyphBuffer) { unsigned numRuns = m_harfBuzzRuns.size(); + float carryAdvance = 0; if (m_run.rtl()) { - m_startOffset = m_harfBuzzRuns.last()->offsets()[0]; for (int runIndex = numRuns - 1; runIndex >= 0; --runIndex) { HarfBuzzRun* currentRun = m_harfBuzzRuns[runIndex].get(); if (!currentRun->hasGlyphToCharacterIndexes()) { // FIXME: bug 337886, 359664 continue; } - FloatPoint firstOffsetOfNextRun = !runIndex ? FloatPoint() : m_harfBuzzRuns[runIndex - 1]->offsets()[0]; if (m_forTextEmphasis == ForTextEmphasis) fillGlyphBufferForTextEmphasis(glyphBuffer, currentRun); else - fillGlyphBufferFromHarfBuzzRun(glyphBuffer, currentRun, firstOffsetOfNextRun); + fillGlyphBufferFromHarfBuzzRun(glyphBuffer, currentRun, carryAdvance); } } else { - m_startOffset = m_harfBuzzRuns.first()->offsets()[0]; for (unsigned runIndex = 0; runIndex < numRuns; ++runIndex) { HarfBuzzRun* currentRun = m_harfBuzzRuns[runIndex].get(); if (!currentRun->hasGlyphToCharacterIndexes()) { // FIXME: bug 337886, 359664 continue; } - FloatPoint firstOffsetOfNextRun = runIndex == numRuns - 1 ? FloatPoint() : m_harfBuzzRuns[runIndex + 1]->offsets()[0]; if (m_forTextEmphasis == ForTextEmphasis) fillGlyphBufferForTextEmphasis(glyphBuffer, currentRun); else - fillGlyphBufferFromHarfBuzzRun(glyphBuffer, currentRun, firstOffsetOfNextRun); + fillGlyphBufferFromHarfBuzzRun(glyphBuffer, currentRun, carryAdvance); } } return glyphBuffer->size();
diff --git a/sky/engine/platform/fonts/harfbuzz/HarfBuzzShaper.h b/sky/engine/platform/fonts/harfbuzz/HarfBuzzShaper.h index 8e968a6..581737c 100644 --- a/sky/engine/platform/fonts/harfbuzz/HarfBuzzShaper.h +++ b/sky/engine/platform/fonts/harfbuzz/HarfBuzzShaper.h
@@ -60,7 +60,6 @@ void setDrawRange(int from, int to); bool shape(GlyphBuffer* = 0); - FloatPoint adjustStartPoint(const FloatPoint&); float totalWidth() { return m_totalWidth; } int offsetForPosition(float targetX); FloatRect selectionRect(const FloatPoint&, int height, int from, int to); @@ -90,7 +89,7 @@ unsigned numGlyphs() const { return m_numGlyphs; } uint16_t* glyphs() { return &m_glyphs[0]; } float* advances() { return &m_advances[0]; } - FloatPoint* offsets() { return &m_offsets[0]; } + FloatSize* offsets() { return &m_offsets[0]; } bool hasGlyphToCharacterIndexes() const { return m_glyphToCharacterIndexes.size() > 0; @@ -116,7 +115,7 @@ Vector<uint16_t, 256> m_glyphs; Vector<float, 256> m_advances; Vector<uint16_t, 256> m_glyphToCharacterIndexes; - Vector<FloatPoint, 256> m_offsets; + Vector<FloatSize, 256> m_offsets; float m_width; }; @@ -130,7 +129,7 @@ bool createHarfBuzzRuns(); bool shapeHarfBuzzRuns(); bool fillGlyphBuffer(GlyphBuffer*); - void fillGlyphBufferFromHarfBuzzRun(GlyphBuffer*, HarfBuzzRun*, FloatPoint& firstOffsetOfNextRun); + void fillGlyphBufferFromHarfBuzzRun(GlyphBuffer*, HarfBuzzRun*, float& carryAdvance); void fillGlyphBufferForTextEmphasis(GlyphBuffer*, HarfBuzzRun* currentRun); void setGlyphPositionsForHarfBuzzRun(HarfBuzzRun*, hb_buffer_t*); void addHarfBuzzRun(unsigned startCharacter, unsigned endCharacter, const SimpleFontData*, UScriptCode); @@ -149,8 +148,6 @@ Vector<hb_feature_t, 4> m_features; Vector<OwnPtr<HarfBuzzRun>, 16> m_harfBuzzRuns; - FloatPoint m_startOffset; - int m_fromIndex; int m_toIndex;
diff --git a/sky/engine/platform/graphics/GraphicsContext.cpp b/sky/engine/platform/graphics/GraphicsContext.cpp index a0a8870..8323246 100644 --- a/sky/engine/platform/graphics/GraphicsContext.cpp +++ b/sky/engine/platform/graphics/GraphicsContext.cpp
@@ -918,12 +918,10 @@ TextRunPaintInfo subrunInfo(subrun); subrunInfo.bounds = runInfo.bounds; - font.drawText(this, subrunInfo, currPoint, customFontNotReadyAction); + float runWidth = font.drawUncachedText(this, subrunInfo, currPoint, customFontNotReadyAction); bidiRun = bidiRun->next(); - // FIXME: Have Font::drawText return the width of what it drew so that we don't have to re-measure here. - if (bidiRun) - currPoint.move(font.width(subrun), 0); + currPoint.move(runWidth, 0); } bidiRuns.deleteRuns();
diff --git a/sky/engine/platform/text/TextRun.h b/sky/engine/platform/text/TextRun.h index f6329ad..285ba5b 100644 --- a/sky/engine/platform/text/TextRun.h +++ b/sky/engine/platform/text/TextRun.h
@@ -32,6 +32,8 @@ #include "sky/engine/wtf/RefCounted.h" #include "sky/engine/wtf/text/WTFString.h" +class SkTextBlob; + namespace blink { class FloatPoint; @@ -245,6 +247,7 @@ : run(r) , from(0) , to(r.length()) + , cachedTextBlob(nullptr) { } @@ -252,6 +255,7 @@ int from; int to; FloatRect bounds; + RefPtr<const SkTextBlob>* cachedTextBlob; }; }