From 9be5ff6f9871ef22740094e7c25dd67329a73d20 Mon Sep 17 00:00:00 2001 From: herb Date: Wed, 11 Nov 2015 11:30:11 -0800 Subject: [PATCH] Replace glyph find and position with common code for the gpu bitmap case. BUG=skia: Review URL: https://codereview.chromium.org/1424173005 --- src/core/SkDraw.cpp | 29 ++++----- src/core/SkFindAndPlaceGlyph.h | 74 ++++++++-------------- src/gpu/GrAtlasTextContext.cpp | 140 ++++------------------------------------- 3 files changed, 49 insertions(+), 194 deletions(-) diff --git a/src/core/SkDraw.cpp b/src/core/SkDraw.cpp index 0b650be..4be510c 100644 --- a/src/core/SkDraw.cpp +++ b/src/core/SkDraw.cpp @@ -1748,13 +1748,10 @@ void SkDraw::drawPosText(const char text[], size_t byteLength, return; } - SkDrawCacheProc glyphCacheProc = paint.getDrawCacheProc(); - SkAutoGlyphCache autoCache(paint, &fDevice->surfaceProps(), fMatrix); - SkGlyphCache* cache = autoCache.getCache(); - + // The Blitter Choose needs to be live while using the blitter below. + SkAutoBlitterChoose blitterChooser; SkAAClipBlitterWrapper wrapper; - SkAutoBlitterChoose blitterChooser; - SkBlitter* blitter = nullptr; + SkBlitter* blitter = nullptr; if (needsRasterTextBlit(*this)) { blitterChooser.choose(fDst, *fMatrix, paint); blitter = blitterChooser.get(); @@ -1764,23 +1761,21 @@ void SkDraw::drawPosText(const char text[], size_t byteLength, } } + SkAutoGlyphCache autoCache(paint, &fDevice->surfaceProps(), fMatrix); + SkGlyphCache* cache = autoCache.getCache(); SkDraw1Glyph d1g; SkDraw1Glyph::Proc proc = d1g.init(this, blitter, cache, paint); + SkPaint::Align textAlignment = paint.getTextAlign(); + SkDrawCacheProc glyphCacheProc = paint.getDrawCacheProc(); - auto processOneGlyph = + SkFindAndPlaceGlyph::ProcessPosText( + text, byteLength, offset, *fMatrix, pos, scalarsPerPosition, + textAlignment, glyphCacheProc, cache, [&](const SkGlyph& glyph, SkPoint position, SkPoint rounding) { position += rounding; proc(d1g, SkScalarToFixed(position.fX), SkScalarToFixed(position.fY), glyph); - }; - - SkPaint::Align textAlignment = paint.getTextAlign(); - if (!SkFindAndPlaceGlyph::SpecializedProcessPosText( - text, byteLength, offset, *fMatrix, pos, scalarsPerPosition, - textAlignment, glyphCacheProc, cache, processOneGlyph)) { - SkFindAndPlaceGlyph::ProcessPosText( - text, byteLength, offset, *fMatrix, pos, scalarsPerPosition, - textAlignment, glyphCacheProc, cache, processOneGlyph); - } + } + ); } #if defined _WIN32 && _MSC_VER >= 1300 diff --git a/src/core/SkFindAndPlaceGlyph.h b/src/core/SkFindAndPlaceGlyph.h index 320caf4..0280e90 100644 --- a/src/core/SkFindAndPlaceGlyph.h +++ b/src/core/SkFindAndPlaceGlyph.h @@ -53,21 +53,6 @@ public: SkPaint::Align textAlignment, SkDrawCacheProc& glyphCacheProc, SkGlyphCache* cache, ProcessOneGlyph&& processOneGlyph); - // SpecializedProcessPosText is a version of ProcessPosText that de-virtualizes the - // different components used. It returns true if it can handle the situation, otherwise it - // returns false. This allows greater inlining freedom to the compiler. Currently, there is - // only one specialized variant: sub-pixel position, left-aligned, x-axis-aligned, - // translation, and one scalar per position entry. - // * This is by far the most common type of text Blink draws. - template - static bool SpecializedProcessPosText(const char* const text, size_t byteLength, - const SkPoint& offset, const SkMatrix& matrix, - const SkScalar pos[], int scalarsPerPosition, - SkPaint::Align textAlignment, - SkDrawCacheProc& glyphCacheProc, - SkGlyphCache* cache, - ProcessOneGlyph&& processOneGlyph); - private: // UntaggedVariant is a pile of memory that can hold one of the Ts. It provides a way // to initialize that memory in a typesafe way. @@ -417,6 +402,32 @@ inline void SkFindAndPlaceGlyph::ProcessPosText( const SkScalar pos[], int scalarsPerPosition, SkPaint::Align textAlignment, SkDrawCacheProc& glyphCacheProc, SkGlyphCache* cache, ProcessOneGlyph&& processOneGlyph) { + SkAxisAlignment axisAlignment = SkComputeAxisAlignmentForHText(matrix); + uint32_t mtype = matrix.getType(); + + // Specialized code for handling the most common case for blink. The while loop is totally + // de-virtualized. + if (scalarsPerPosition == 1 + && textAlignment == SkPaint::kLeft_Align + && axisAlignment == kX_SkAxisAlignment + && cache->isSubpixel() + && mtype <= SkMatrix::kTranslate_Mask) { + typedef GlyphFindAndPlaceSubpixel< + ProcessOneGlyph, SkPaint::kLeft_Align, kX_SkAxisAlignment> Positioner; + HorizontalPositions positions{pos}; + TranslationMapper mapper{matrix, offset}; + Positioner positioner(cache, glyphCacheProc); + const char* cursor = text; + const char* stop = text + byteLength; + while (cursor < stop) { + SkPoint mappedPoint = mapper.TranslationMapper::map( + positions.HorizontalPositions::nextPoint()); + positioner.Positioner::findAndPositionGlyph( + &cursor, mappedPoint, skstd::forward(processOneGlyph)); + } + return; + } + PositionReader positionReader{ [&](PositionReader::Variants* to_init) { if (2 == scalarsPerPosition) { @@ -429,7 +440,6 @@ inline void SkFindAndPlaceGlyph::ProcessPosText( Mapper mapper{ [&](Mapper::Variants* to_init) { - uint32_t mtype = matrix.getType(); if (mtype & (SkMatrix::kAffine_Mask | SkMatrix::kPerspective_Mask) || scalarsPerPosition == 2) { to_init->initialize(matrix, offset); @@ -444,7 +454,6 @@ inline void SkFindAndPlaceGlyph::ProcessPosText( GlyphFindAndPlace findAndPosition{ [&](typename GlyphFindAndPlace::Variants* to_init) { if (cache->isSubpixel()) { - SkAxisAlignment axisAlignment = SkComputeAxisAlignmentForHText(matrix); switch (textAlignment) { case SkPaint::kLeft_Align: InitSubpixel( @@ -489,35 +498,4 @@ inline void SkFindAndPlaceGlyph::ProcessPosText( } } -template -inline bool SkFindAndPlaceGlyph::SpecializedProcessPosText( - const char* const text, size_t byteLength, const SkPoint& offset, const SkMatrix& matrix, - const SkScalar pos[], int scalarsPerPosition, SkPaint::Align textAlignment, - SkDrawCacheProc& glyphCacheProc, SkGlyphCache* cache, ProcessOneGlyph&& processOneGlyph) { - SkAxisAlignment axisAlignment = SkComputeAxisAlignmentForHText(matrix); - uint32_t mtype = matrix.getType(); - if (scalarsPerPosition == 1 - && textAlignment == SkPaint::kLeft_Align - && axisAlignment == kX_SkAxisAlignment - && cache->isSubpixel() - && mtype <= SkMatrix::kTranslate_Mask) { - typedef GlyphFindAndPlaceSubpixel< - ProcessOneGlyph, SkPaint::kLeft_Align, kX_SkAxisAlignment> Positioner; - HorizontalPositions positions{pos}; - TranslationMapper mapper{matrix, offset}; - Positioner positioner(cache, glyphCacheProc); - const char* cursor = text; - const char* stop = text + byteLength; - while (cursor < stop) { - SkPoint mappedPoint = mapper.TranslationMapper::map( - positions.HorizontalPositions::nextPoint()); - positioner.Positioner::findAndPositionGlyph( - &cursor, mappedPoint, skstd::forward(processOneGlyph)); - } - return true; - } - return false; -} - - #endif // SkFindAndPositionGlyph_DEFINED diff --git a/src/gpu/GrAtlasTextContext.cpp b/src/gpu/GrAtlasTextContext.cpp index 4d6a675..f800465 100644 --- a/src/gpu/GrAtlasTextContext.cpp +++ b/src/gpu/GrAtlasTextContext.cpp @@ -27,6 +27,7 @@ #include "SkDraw.h" #include "SkDrawFilter.h" #include "SkDrawProcs.h" +#include "SkFindAndPlaceGlyph.h" #include "SkGlyphCache.h" #include "SkGpuDevice.h" #include "SkGrPriv.h" @@ -915,138 +916,19 @@ void GrAtlasTextContext::internalDrawBMPPosText(GrAtlasTextBlob* blob, int runIn // Get GrFontScaler from cache GrFontScaler* fontScaler = GetGrFontScaler(cache); - const char* stop = text + byteLength; - SkTextAlignProc alignProc(skPaint.getTextAlign()); - SkTextMapStateProc tmsProc(viewMatrix, offset, scalarsPerPosition); - - if (cache->isSubpixel()) { - // maybe we should skip the rounding if linearText is set - SkAxisAlignment baseline = SkComputeAxisAlignmentForHText(viewMatrix); - - SkFixed fxMask = ~0; - SkFixed fyMask = ~0; - SkScalar halfSampleX = SkFixedToScalar(SkGlyph::kSubpixelRound); - SkScalar halfSampleY = SkFixedToScalar(SkGlyph::kSubpixelRound); - if (kX_SkAxisAlignment == baseline) { - fyMask = 0; - halfSampleY = SK_ScalarHalf; - } else if (kY_SkAxisAlignment == baseline) { - fxMask = 0; - halfSampleX = SK_ScalarHalf; + SkFindAndPlaceGlyph::ProcessPosText( + text, byteLength, offset, viewMatrix, pos, scalarsPerPosition, + skPaint.getTextAlign(), glyphCacheProc, cache, + [&](const SkGlyph& glyph, SkPoint position, SkPoint rounding) { + position += rounding; + this->bmpAppendGlyph( + blob, runIndex, glyph, + SkScalarFloorToInt(position.fX), SkScalarFloorToInt(position.fY), + color, fontScaler, clipRect); } - - if (SkPaint::kLeft_Align == skPaint.getTextAlign()) { - while (text < stop) { - SkPoint tmsLoc; - tmsProc(pos, &tmsLoc); - Sk48Dot16 fx = SkScalarTo48Dot16(tmsLoc.fX + halfSampleX); - Sk48Dot16 fy = SkScalarTo48Dot16(tmsLoc.fY + halfSampleY); - - const SkGlyph& glyph = glyphCacheProc(cache, &text, - fx & fxMask, fy & fyMask); - - if (glyph.fWidth) { - this->bmpAppendGlyph(blob, - runIndex, - glyph, - Sk48Dot16FloorToInt(fx), - Sk48Dot16FloorToInt(fy), - color, - fontScaler, - clipRect); - } - pos += scalarsPerPosition; - } - } else { - while (text < stop) { - const char* currentText = text; - const SkGlyph& metricGlyph = glyphCacheProc(cache, &text, 0, 0); - - if (metricGlyph.fWidth) { - SkDEBUGCODE(SkFixed prevAdvX = metricGlyph.fAdvanceX;) - SkDEBUGCODE(SkFixed prevAdvY = metricGlyph.fAdvanceY;) - SkPoint tmsLoc; - tmsProc(pos, &tmsLoc); - SkPoint alignLoc; - alignProc(tmsLoc, metricGlyph, &alignLoc); - - Sk48Dot16 fx = SkScalarTo48Dot16(alignLoc.fX + halfSampleX); - Sk48Dot16 fy = SkScalarTo48Dot16(alignLoc.fY + halfSampleY); - - // have to call again, now that we've been "aligned" - const SkGlyph& glyph = glyphCacheProc(cache, ¤tText, - fx & fxMask, fy & fyMask); - // the assumption is that the metrics haven't changed - SkASSERT(prevAdvX == glyph.fAdvanceX); - SkASSERT(prevAdvY == glyph.fAdvanceY); - SkASSERT(glyph.fWidth); - - this->bmpAppendGlyph(blob, - runIndex, - glyph, - Sk48Dot16FloorToInt(fx), - Sk48Dot16FloorToInt(fy), - color, - fontScaler, - clipRect); - } - pos += scalarsPerPosition; - } - } - } else { // not subpixel - - if (SkPaint::kLeft_Align == skPaint.getTextAlign()) { - while (text < stop) { - // the last 2 parameters are ignored - const SkGlyph& glyph = glyphCacheProc(cache, &text, 0, 0); - - if (glyph.fWidth) { - SkPoint tmsLoc; - tmsProc(pos, &tmsLoc); - - Sk48Dot16 fx = SkScalarTo48Dot16(tmsLoc.fX + SK_ScalarHalf); //halfSampleX; - Sk48Dot16 fy = SkScalarTo48Dot16(tmsLoc.fY + SK_ScalarHalf); //halfSampleY; - this->bmpAppendGlyph(blob, - runIndex, - glyph, - Sk48Dot16FloorToInt(fx), - Sk48Dot16FloorToInt(fy), - color, - fontScaler, - clipRect); - } - pos += scalarsPerPosition; - } - } else { - while (text < stop) { - // the last 2 parameters are ignored - const SkGlyph& glyph = glyphCacheProc(cache, &text, 0, 0); - - if (glyph.fWidth) { - SkPoint tmsLoc; - tmsProc(pos, &tmsLoc); - - SkPoint alignLoc; - alignProc(tmsLoc, glyph, &alignLoc); - - Sk48Dot16 fx = SkScalarTo48Dot16(alignLoc.fX + SK_ScalarHalf); //halfSampleX; - Sk48Dot16 fy = SkScalarTo48Dot16(alignLoc.fY + SK_ScalarHalf); //halfSampleY; - this->bmpAppendGlyph(blob, - runIndex, - glyph, - Sk48Dot16FloorToInt(fx), - Sk48Dot16FloorToInt(fy), - color, - fontScaler, - clipRect); - } - pos += scalarsPerPosition; - } - } - } + ); } - void GrAtlasTextContext::internalDrawDFText(GrAtlasTextBlob* blob, int runIndex, const SkPaint& skPaint, GrColor color, const SkMatrix& viewMatrix, -- 2.7.4