| Index: sky/engine/platform/fonts/Font.cpp
|
| diff --git a/sky/engine/platform/fonts/Font.cpp b/sky/engine/platform/fonts/Font.cpp
|
| index 31678343207d6ee3cb96422aa131ad9abdbb44ef..b0c297562489bd3ece28620c4fe00b8d9db0cea2 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 @@ void Font::update(PassRefPtr<FontSelector> fontSelector) const
|
| 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 @@ void Font::drawEmphasisMarks(GraphicsContext* context, const TextRunPaintInfo& r
|
| 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 @@ int Font::emphasisMarkHeight(const AtomicString& mark) const
|
| 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 offsetToMiddleOfGlyph(const SimpleFontData* fontData, Glyph
|
|
|
| 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 @@ void Font::drawEmphasisMarks(GraphicsContext* context, const TextRunPaintInfo& r
|
| 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;
|
| }
|
|
|