Replace glyph find and position with common code for the gpu bitmap case.
BUG=skia:
Review URL: https://codereview.chromium.org/1424173005
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 @@
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 @@
}
}
+ 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 @@
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 @@
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 @@
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 @@
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 @@
}
}
-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
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 @@
// 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,