Replace glyph find and position with common code for the gpu bitmap case.
authorherb <herb@google.com>
Wed, 11 Nov 2015 19:30:11 +0000 (11:30 -0800)
committerCommit bot <commit-bot@chromium.org>
Wed, 11 Nov 2015 19:30:11 +0000 (11:30 -0800)
BUG=skia:

Review URL: https://codereview.chromium.org/1424173005

src/core/SkDraw.cpp
src/core/SkFindAndPlaceGlyph.h
src/gpu/GrAtlasTextContext.cpp

index 0b650be..4be510c 100644 (file)
@@ -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
index 320caf4..0280e90 100644 (file)
@@ -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<typename ProcessOneGlyph>
-    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>(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<GeneralMapper>(matrix, offset);
@@ -444,7 +454,6 @@ inline void SkFindAndPlaceGlyph::ProcessPosText(
     GlyphFindAndPlace<ProcessOneGlyph> findAndPosition{
         [&](typename GlyphFindAndPlace<ProcessOneGlyph>::Variants* to_init) {
             if (cache->isSubpixel()) {
-                SkAxisAlignment axisAlignment = SkComputeAxisAlignmentForHText(matrix);
                 switch (textAlignment) {
                     case SkPaint::kLeft_Align:
                         InitSubpixel<ProcessOneGlyph, SkPaint::kLeft_Align>(
@@ -489,35 +498,4 @@ inline void SkFindAndPlaceGlyph::ProcessPosText(
     }
 }
 
-template<typename ProcessOneGlyph>
-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>(processOneGlyph));
-        }
-        return true;
-    }
-    return false;
-}
-
-
 #endif  // SkFindAndPositionGlyph_DEFINED
index 4d6a675..f800465 100644 (file)
@@ -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, &currentText,
-                                                          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,