Convert drawText to using the find and place code.
BUG=skia: Review URL: https://codereview.chromium.org/1448453002
This commit is contained in:
parent
5520dede29
commit
e59124ed1a
@ -34,7 +34,6 @@
|
||||
#include "SkUtils.h"
|
||||
#include "SkVertState.h"
|
||||
|
||||
#include "SkAutoKern.h"
|
||||
#include "SkBitmapProcShader.h"
|
||||
#include "SkDrawProcs.h"
|
||||
#include "SkMatrixUtils.h"
|
||||
@ -53,7 +52,7 @@ public:
|
||||
const SkPaint& paint, bool drawCoverage = false) {
|
||||
fBlitter = SkBlitter::Choose(dst, matrix, paint, &fAllocator, drawCoverage);
|
||||
}
|
||||
|
||||
|
||||
SkBlitter* operator->() { return fBlitter; }
|
||||
SkBlitter* get() const { return fBlitter; }
|
||||
|
||||
@ -1374,26 +1373,6 @@ void SkDraw::drawSprite(const SkBitmap& bitmap, int x, int y, const SkPaint& ori
|
||||
#include "SkTextToPathIter.h"
|
||||
#include "SkUtils.h"
|
||||
|
||||
static void measure_text(SkGlyphCache* cache, SkDrawCacheProc glyphCacheProc,
|
||||
const char text[], size_t byteLength, SkVector* stopVector) {
|
||||
SkFixed x = 0, y = 0;
|
||||
const char* stop = text + byteLength;
|
||||
|
||||
SkAutoKern autokern;
|
||||
|
||||
while (text < stop) {
|
||||
// don't need x, y here, since all subpixel variants will have the
|
||||
// same advance
|
||||
const SkGlyph& glyph = glyphCacheProc(cache, &text, 0, 0);
|
||||
|
||||
x += autokern.adjust(glyph) + glyph.fAdvanceX;
|
||||
y += glyph.fAdvanceY;
|
||||
}
|
||||
stopVector->set(SkFixedToScalar(x), SkFixedToScalar(y));
|
||||
|
||||
SkASSERT(text == stop);
|
||||
}
|
||||
|
||||
bool SkDraw::ShouldDrawTextAsPaths(const SkPaint& paint, const SkMatrix& ctm) {
|
||||
// hairline glyphs are fast enough so we don't need to cache them
|
||||
if (SkPaint::kStroke_Style == paint.getStyle() && 0 == paint.getStrokeWidth()) {
|
||||
@ -1601,38 +1580,10 @@ void SkDraw::drawText(const char text[], size_t byteLength,
|
||||
return;
|
||||
}
|
||||
|
||||
SkDrawCacheProc glyphCacheProc = paint.getDrawCacheProc();
|
||||
|
||||
SkDrawCacheProc glyphCacheProc = paint.getDrawCacheProc();
|
||||
SkAutoGlyphCache autoCache(paint, &fDevice->surfaceProps(), fMatrix);
|
||||
SkGlyphCache* cache = autoCache.getCache();
|
||||
|
||||
// transform our starting point
|
||||
{
|
||||
SkPoint loc;
|
||||
fMatrix->mapXY(x, y, &loc);
|
||||
x = loc.fX;
|
||||
y = loc.fY;
|
||||
}
|
||||
|
||||
// need to measure first
|
||||
if (paint.getTextAlign() != SkPaint::kLeft_Align) {
|
||||
SkVector stop;
|
||||
|
||||
measure_text(cache, glyphCacheProc, text, byteLength, &stop);
|
||||
|
||||
SkScalar stopX = stop.fX;
|
||||
SkScalar stopY = stop.fY;
|
||||
|
||||
if (paint.getTextAlign() == SkPaint::kCenter_Align) {
|
||||
stopX = SkScalarHalf(stopX);
|
||||
stopY = SkScalarHalf(stopY);
|
||||
}
|
||||
x -= stopX;
|
||||
y -= stopY;
|
||||
}
|
||||
|
||||
const char* stop = text + byteLength;
|
||||
|
||||
SkAAClipBlitter aaBlitter;
|
||||
SkAutoBlitterChoose blitterChooser;
|
||||
SkBlitter* blitter = nullptr;
|
||||
@ -1645,38 +1596,16 @@ void SkDraw::drawText(const char text[], size_t byteLength,
|
||||
}
|
||||
}
|
||||
|
||||
SkAutoKern autokern;
|
||||
SkDraw1Glyph d1g;
|
||||
SkDraw1Glyph::Proc proc = d1g.init(this, blitter, cache, paint);
|
||||
|
||||
SkFixed fxMask = ~0;
|
||||
SkFixed fyMask = ~0;
|
||||
if (cache->isSubpixel()) {
|
||||
SkAxisAlignment baseline = SkComputeAxisAlignmentForHText(*fMatrix);
|
||||
if (kX_SkAxisAlignment == baseline) {
|
||||
fyMask = 0;
|
||||
d1g.fHalfSampleY = SK_ScalarHalf;
|
||||
} else if (kY_SkAxisAlignment == baseline) {
|
||||
fxMask = 0;
|
||||
d1g.fHalfSampleX = SK_ScalarHalf;
|
||||
SkFindAndPlaceGlyph::ProcessText(
|
||||
text, byteLength, {x, y}, *fMatrix, paint.getTextAlign(), glyphCacheProc, cache,
|
||||
[&](const SkGlyph& glyph, SkPoint position, SkPoint rounding) {
|
||||
position += rounding;
|
||||
proc(d1g, SkScalarTo48Dot16(position.fX), SkScalarTo48Dot16(position.fY), glyph);
|
||||
}
|
||||
}
|
||||
|
||||
Sk48Dot16 fx = SkScalarTo48Dot16(x + d1g.fHalfSampleX);
|
||||
Sk48Dot16 fy = SkScalarTo48Dot16(y + d1g.fHalfSampleY);
|
||||
|
||||
while (text < stop) {
|
||||
const SkGlyph& glyph = glyphCacheProc(cache, &text, fx & fxMask, fy & fyMask);
|
||||
|
||||
fx += autokern.adjust(glyph);
|
||||
|
||||
if (glyph.fWidth) {
|
||||
proc(d1g, fx, fy, glyph);
|
||||
}
|
||||
|
||||
fx += glyph.fAdvanceX;
|
||||
fy += glyph.fAdvanceY;
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
@ -1773,7 +1702,7 @@ void SkDraw::drawPosText(const char text[], size_t byteLength,
|
||||
textAlignment, glyphCacheProc, cache,
|
||||
[&](const SkGlyph& glyph, SkPoint position, SkPoint rounding) {
|
||||
position += rounding;
|
||||
proc(d1g, SkScalarToFixed(position.fX), SkScalarToFixed(position.fY), glyph);
|
||||
proc(d1g, SkScalarTo48Dot16(position.fX), SkScalarTo48Dot16(position.fY), glyph);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
@ -8,6 +8,7 @@
|
||||
#ifndef SkFindAndPositionGlyph_DEFINED
|
||||
#define SkFindAndPositionGlyph_DEFINED
|
||||
|
||||
#include "SkAutoKern.h"
|
||||
#include "SkGlyph.h"
|
||||
#include "SkGlyphCache.h"
|
||||
#include "SkPaint.h"
|
||||
@ -30,6 +31,10 @@ struct SkMaxSizeOf<H, Ts...> {
|
||||
|
||||
class SkFindAndPlaceGlyph {
|
||||
public:
|
||||
template<typename ProcessOneGlyph>
|
||||
static void ProcessText(const char text[], size_t byteLength, SkPoint offset, const
|
||||
SkMatrix& matrix, SkPaint::Align textAlignment, SkDrawCacheProc& glyphCacheProc,
|
||||
SkGlyphCache* cache, ProcessOneGlyph&& processOneGlyph);
|
||||
// ProcessPosText handles all cases for finding and positioning glyphs. It has a very large
|
||||
// multiplicity. It figures out the glyph, position and rounding and pass those parameters to
|
||||
// processOneGlyph.
|
||||
@ -48,7 +53,7 @@ public:
|
||||
// This routine handles all of them using inline polymorphic variable (no heap allocation).
|
||||
template<typename ProcessOneGlyph>
|
||||
static void ProcessPosText(const char text[], size_t byteLength,
|
||||
const SkPoint& offset, const SkMatrix& matrix,
|
||||
SkPoint offset, const SkMatrix& matrix,
|
||||
const SkScalar pos[], int scalarsPerPosition,
|
||||
SkPaint::Align textAlignment, SkDrawCacheProc& glyphCacheProc,
|
||||
SkGlyphCache* cache, ProcessOneGlyph&& processOneGlyph);
|
||||
@ -142,7 +147,8 @@ private:
|
||||
typedef PolymorphicVariant<PositionReaderInterface, HorizontalPositions, ArbitraryPositions>
|
||||
PositionReader;
|
||||
|
||||
// MapperInterface given a point map it through the matrix. There are several shortcut variants.
|
||||
// MapperInterface given a point map it through the matrix. There are several shortcut
|
||||
// variants.
|
||||
// * TranslationMapper - assumes a translation only matrix.
|
||||
// * XScaleMapper - assumes an X scaling and a translation.
|
||||
// * GeneralMapper - Does all other matricies.
|
||||
@ -201,7 +207,7 @@ private:
|
||||
typedef PolymorphicVariant<
|
||||
MapperInterface, TranslationMapper, XScaleMapper, GeneralMapper> Mapper;
|
||||
|
||||
// Text alignment handles shifting the glyph based on its width.
|
||||
// TextAlignmentAdjustment handles shifting the glyph based on its width.
|
||||
static SkPoint TextAlignmentAdjustment(SkPaint::Align textAlignment, const SkGlyph& glyph) {
|
||||
switch (textAlignment) {
|
||||
case SkPaint::kLeft_Align:
|
||||
@ -222,8 +228,7 @@ private:
|
||||
// Needs to be a macro because you can't have a const float unless you make it constexpr.
|
||||
#define kSubpixelRounding (SkFixedToScalar(SkGlyph::kSubpixelRound))
|
||||
|
||||
// Functions for handling sub-pixel aligned positions.
|
||||
// The subpixel_position_rounding function returns a point suitable for rounding a sub-pixel
|
||||
// The SubpixelPositionRounding function returns a point suitable for rounding a sub-pixel
|
||||
// positioned glyph.
|
||||
static SkPoint SubpixelPositionRounding(SkAxisAlignment axisAlignment) {
|
||||
switch (axisAlignment) {
|
||||
@ -238,7 +243,7 @@ private:
|
||||
return {0.0f, 0.0f};
|
||||
}
|
||||
|
||||
// The subpixel_position_alignment function produces a suitable position for the glyph cache to
|
||||
// The SubpixelAlignment function produces a suitable position for the glyph cache to
|
||||
// produce the correct sub-pixel alignment. If a position is aligned with an axis a shortcut
|
||||
// of 0 is used for the sub-pixel position.
|
||||
static SkIPoint SubpixelAlignment(SkAxisAlignment axisAlignment, SkPoint position) {
|
||||
@ -266,36 +271,47 @@ private:
|
||||
public:
|
||||
virtual ~GlyphFindAndPlaceInterface() { };
|
||||
|
||||
// findAndPositionGlyph calculates the position of the glyph, finds the glyph, and
|
||||
// returns the position of where the next glyph will be using the glyph's advance and
|
||||
// possibly kerning. The returned position is used by drawText, but ignored by drawPosText.
|
||||
// The compiler should prune all this calculation if the return value is not used.
|
||||
//
|
||||
// This should be a pure virtual, but some versions of GCC <= 4.8 have a bug that causes a
|
||||
// compile error.
|
||||
// See GCC bug: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=60277
|
||||
virtual void findAndPositionGlyph(const char** text, SkPoint position,
|
||||
ProcessOneGlyph&& processOneGlyph) { };
|
||||
virtual SkPoint findAndPositionGlyph(
|
||||
const char** text, SkPoint position, ProcessOneGlyph&& processOneGlyph) {
|
||||
SkFAIL("Should never get here.");
|
||||
return {0.0f, 0.0f};
|
||||
};
|
||||
};
|
||||
|
||||
// GlyphFindAndPlaceSubpixel handles finding and placing glyphs when sub-pixel positioning is
|
||||
// requested. After it has found and placed the glyph it calls the templated function
|
||||
// ProcessOneGlyph in order to actually perform an action.
|
||||
template<typename ProcessOneGlyph, SkPaint::Align kTextAlignment, SkAxisAlignment kAxisAlignment>
|
||||
template<typename ProcessOneGlyph, SkPaint::Align kTextAlignment,
|
||||
SkAxisAlignment kAxisAlignment>
|
||||
class GlyphFindAndPlaceSubpixel final : public GlyphFindAndPlaceInterface<ProcessOneGlyph> {
|
||||
public:
|
||||
GlyphFindAndPlaceSubpixel(SkGlyphCache* cache, SkDrawCacheProc glyphCacheProc)
|
||||
: fCache(cache), fGlyphCacheProc(glyphCacheProc) {
|
||||
}
|
||||
: fCache(cache)
|
||||
, fGlyphCacheProc(glyphCacheProc) { }
|
||||
|
||||
void findAndPositionGlyph(const char** text, SkPoint position,
|
||||
ProcessOneGlyph&& processOneGlyph) override {
|
||||
SkPoint findAndPositionGlyph(
|
||||
const char** text, SkPoint position, ProcessOneGlyph&& processOneGlyph) override {
|
||||
SkPoint finalPosition = position;
|
||||
if (kTextAlignment != SkPaint::kLeft_Align) {
|
||||
// Get the width of an un-sub-pixel positioned glyph for calculating the alignment.
|
||||
// This is not needed for kLeftAlign because its adjustment is always {0, 0}.
|
||||
// Get the width of an un-sub-pixel positioned glyph for calculating the
|
||||
// alignment. This is not needed for kLeftAlign because its adjustment is
|
||||
// always {0, 0}.
|
||||
const char* tempText = *text;
|
||||
const SkGlyph &metricGlyph = fGlyphCacheProc(fCache, &tempText, 0, 0);
|
||||
|
||||
if (metricGlyph.fWidth <= 0) {
|
||||
// Exiting early, be sure to update text pointer.
|
||||
*text = tempText;
|
||||
return;
|
||||
return finalPosition + SkPoint{SkFixedToScalar(metricGlyph.fAdvanceX),
|
||||
SkFixedToScalar(metricGlyph.fAdvanceY)};
|
||||
}
|
||||
|
||||
// Adjust the final position by the alignment adjustment.
|
||||
@ -304,14 +320,16 @@ private:
|
||||
|
||||
// Find the glyph.
|
||||
SkIPoint lookupPosition = SubpixelAlignment(kAxisAlignment, finalPosition);
|
||||
const SkGlyph& renderGlyph = fGlyphCacheProc(
|
||||
fCache, text, lookupPosition.fX, lookupPosition.fY);
|
||||
const SkGlyph& renderGlyph =
|
||||
fGlyphCacheProc(fCache, text, lookupPosition.fX, lookupPosition.fY);
|
||||
|
||||
// If the glyph has no width (no pixels) then don't bother processing it.
|
||||
if (renderGlyph.fWidth > 0) {
|
||||
processOneGlyph(renderGlyph, finalPosition,
|
||||
SubpixelPositionRounding(kAxisAlignment));
|
||||
}
|
||||
return finalPosition + SkPoint{SkFixedToScalar(renderGlyph.fAdvanceX),
|
||||
SkFixedToScalar(renderGlyph.fAdvanceY)};
|
||||
}
|
||||
|
||||
private:
|
||||
@ -319,28 +337,43 @@ private:
|
||||
SkDrawCacheProc fGlyphCacheProc;
|
||||
};
|
||||
|
||||
enum SelectKerning {
|
||||
kNoKerning = false,
|
||||
kUseKerning = true
|
||||
};
|
||||
|
||||
// GlyphFindAndPlaceFullPixel handles finding and placing glyphs when no sub-pixel
|
||||
// positioning is requested.
|
||||
template<typename ProcessOneGlyph, SkPaint::Align kTextAlignment>
|
||||
// positioning is requested. The kUseKerning argument should be true for drawText, and false
|
||||
// for drawPosText.
|
||||
template<typename ProcessOneGlyph, SkPaint::Align kTextAlignment, SelectKerning kUseKerning>
|
||||
class GlyphFindAndPlaceFullPixel final : public GlyphFindAndPlaceInterface<ProcessOneGlyph> {
|
||||
public:
|
||||
GlyphFindAndPlaceFullPixel(SkGlyphCache* cache, SkDrawCacheProc glyphCacheProc)
|
||||
: fCache(cache), fGlyphCacheProc(glyphCacheProc) { }
|
||||
: fCache(cache), fGlyphCacheProc(glyphCacheProc) {
|
||||
// Kerning can only be used with SkPaint::kLeft_Align
|
||||
static_assert(!kUseKerning || SkPaint::kLeft_Align == kTextAlignment,
|
||||
"Kerning can only be used with left aligned text.");
|
||||
}
|
||||
|
||||
void findAndPositionGlyph(const char** text, SkPoint position,
|
||||
ProcessOneGlyph&& processOneGlyph) override {
|
||||
SkPoint findAndPositionGlyph(
|
||||
const char** text, SkPoint position, ProcessOneGlyph&& processOneGlyph) override {
|
||||
SkPoint finalPosition = position;
|
||||
const SkGlyph& glyph = fGlyphCacheProc(fCache, text, 0, 0);
|
||||
if (glyph.fWidth <= 0) {
|
||||
return;
|
||||
if (kUseKerning) {
|
||||
finalPosition += {SkFixedToScalar(fAutoKern.adjust(glyph)), 0.0f};
|
||||
}
|
||||
finalPosition -= TextAlignmentAdjustment(kTextAlignment, glyph);
|
||||
processOneGlyph(glyph, finalPosition, {SK_ScalarHalf, SK_ScalarHalf});
|
||||
if (glyph.fWidth > 0) {
|
||||
finalPosition -= TextAlignmentAdjustment(kTextAlignment, glyph);
|
||||
processOneGlyph(glyph, finalPosition, {SK_ScalarHalf, SK_ScalarHalf});
|
||||
}
|
||||
return finalPosition + SkPoint{SkFixedToScalar(glyph.fAdvanceX),
|
||||
SkFixedToScalar(glyph.fAdvanceY)};
|
||||
}
|
||||
|
||||
private:
|
||||
SkGlyphCache* const fCache;
|
||||
SkDrawCacheProc fGlyphCacheProc;
|
||||
SkAutoKern fAutoKern;
|
||||
};
|
||||
|
||||
// GlyphFindAndPlace is a large variant that encapsulates the multiple types of finding and
|
||||
@ -365,9 +398,9 @@ private:
|
||||
GlyphFindAndPlaceSubpixel<ProcessOneGlyph, SkPaint::kRight_Align, kX_SkAxisAlignment >,
|
||||
GlyphFindAndPlaceSubpixel<ProcessOneGlyph, SkPaint::kRight_Align, kY_SkAxisAlignment >,
|
||||
// Full pixel
|
||||
GlyphFindAndPlaceFullPixel<ProcessOneGlyph, SkPaint::kLeft_Align >,
|
||||
GlyphFindAndPlaceFullPixel<ProcessOneGlyph, SkPaint::kCenter_Align>,
|
||||
GlyphFindAndPlaceFullPixel<ProcessOneGlyph, SkPaint::kRight_Align >
|
||||
GlyphFindAndPlaceFullPixel<ProcessOneGlyph, SkPaint::kLeft_Align, kNoKerning>,
|
||||
GlyphFindAndPlaceFullPixel<ProcessOneGlyph, SkPaint::kCenter_Align, kNoKerning>,
|
||||
GlyphFindAndPlaceFullPixel<ProcessOneGlyph, SkPaint::kRight_Align, kNoKerning>
|
||||
>;
|
||||
|
||||
// InitSubpixel is a helper function for initializing all the variants of
|
||||
@ -396,11 +429,30 @@ private:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static SkPoint MeasureText(SkGlyphCache* cache, SkDrawCacheProc glyphCacheProc,
|
||||
const char text[], size_t byteLength) {
|
||||
SkFixed x = 0, y = 0;
|
||||
const char* stop = text + byteLength;
|
||||
|
||||
SkAutoKern autokern;
|
||||
|
||||
while (text < stop) {
|
||||
// don't need x, y here, since all subpixel variants will have the
|
||||
// same advance
|
||||
const SkGlyph& glyph = glyphCacheProc(cache, &text, 0, 0);
|
||||
|
||||
x += autokern.adjust(glyph) + glyph.fAdvanceX;
|
||||
y += glyph.fAdvanceY;
|
||||
}
|
||||
SkASSERT(text == stop);
|
||||
return {SkFixedToScalar(x), SkFixedToScalar(y)};
|
||||
}
|
||||
};
|
||||
|
||||
template<typename ProcessOneGlyph>
|
||||
inline void SkFindAndPlaceGlyph::ProcessPosText(
|
||||
const char text[], size_t byteLength, const SkPoint& offset, const SkMatrix& matrix,
|
||||
const char text[], size_t byteLength, SkPoint offset, const SkMatrix& matrix,
|
||||
const SkScalar pos[], int scalarsPerPosition, SkPaint::Align textAlignment,
|
||||
SkDrawCacheProc& glyphCacheProc, SkGlyphCache* cache, ProcessOneGlyph&& processOneGlyph) {
|
||||
|
||||
@ -475,17 +527,17 @@ inline void SkFindAndPlaceGlyph::ProcessPosText(
|
||||
case SkPaint::kLeft_Align:
|
||||
to_init->template initialize<
|
||||
GlyphFindAndPlaceFullPixel<ProcessOneGlyph,
|
||||
SkPaint::kLeft_Align>>(cache, glyphCacheProc);
|
||||
SkPaint::kLeft_Align, kNoKerning>>(cache, glyphCacheProc);
|
||||
break;
|
||||
case SkPaint::kCenter_Align:
|
||||
to_init->template initialize<
|
||||
GlyphFindAndPlaceFullPixel<ProcessOneGlyph,
|
||||
SkPaint::kCenter_Align>>(cache, glyphCacheProc);
|
||||
SkPaint::kCenter_Align, kNoKerning>>(cache, glyphCacheProc);
|
||||
break;
|
||||
case SkPaint::kRight_Align:
|
||||
to_init->template initialize<
|
||||
GlyphFindAndPlaceFullPixel<ProcessOneGlyph,
|
||||
SkPaint::kRight_Align>>(cache, glyphCacheProc);
|
||||
SkPaint::kRight_Align, kNoKerning>>(cache, glyphCacheProc);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -500,4 +552,48 @@ inline void SkFindAndPlaceGlyph::ProcessPosText(
|
||||
}
|
||||
}
|
||||
|
||||
template<typename ProcessOneGlyph>
|
||||
inline void SkFindAndPlaceGlyph::ProcessText(
|
||||
const char text[], size_t byteLength, SkPoint offset, const SkMatrix& matrix,
|
||||
SkPaint::Align textAlignment, SkDrawCacheProc& glyphCacheProc, SkGlyphCache* cache,
|
||||
ProcessOneGlyph&& processOneGlyph) {
|
||||
|
||||
// transform the starting point
|
||||
matrix.mapPoints(&offset, 1);
|
||||
|
||||
// need to measure first
|
||||
if (textAlignment != SkPaint::kLeft_Align) {
|
||||
SkVector stop = MeasureText(cache, glyphCacheProc, text, byteLength);
|
||||
|
||||
if (textAlignment == SkPaint::kCenter_Align) {
|
||||
stop *= SK_ScalarHalf;
|
||||
}
|
||||
offset -= stop;
|
||||
}
|
||||
|
||||
GlyphFindAndPlace<ProcessOneGlyph> findAndPosition{
|
||||
[&](typename GlyphFindAndPlace<ProcessOneGlyph>::Variants* to_init) {
|
||||
if (cache->isSubpixel()) {
|
||||
SkAxisAlignment axisAlignment = SkComputeAxisAlignmentForHText(matrix);
|
||||
InitSubpixel<ProcessOneGlyph, SkPaint::kLeft_Align>(
|
||||
to_init, axisAlignment, cache, glyphCacheProc);
|
||||
} else {
|
||||
to_init->template initialize<
|
||||
GlyphFindAndPlaceFullPixel<
|
||||
ProcessOneGlyph, SkPaint::kLeft_Align, kUseKerning>>(
|
||||
cache, glyphCacheProc);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const char* stop = text + byteLength;
|
||||
SkPoint current = offset;
|
||||
while (text < stop) {
|
||||
current =
|
||||
findAndPosition->findAndPositionGlyph(
|
||||
&text, current, skstd::forward<ProcessOneGlyph>(processOneGlyph));
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
#endif // SkFindAndPositionGlyph_DEFINED
|
||||
|
@ -487,7 +487,7 @@ void GrAtlasTextContext::regenerateTextBlob(GrAtlasTextBlob* cacheBlob,
|
||||
const SkTextBlob* blob, SkScalar x, SkScalar y,
|
||||
SkDrawFilter* drawFilter, const SkIRect& clipRect,
|
||||
GrRenderTarget* rt, const GrClip& clip) {
|
||||
// The color here is the GrPaint color, and it is used to determine whether we
|
||||
// The color here is the GrPaint color, and it is used to determine whether we
|
||||
// have to regenerate LCD text blobs.
|
||||
// We use this color vs the SkPaint color because it has the colorfilter applied.
|
||||
cacheBlob->fPaintColor = color;
|
||||
@ -686,8 +686,8 @@ inline void GrAtlasTextContext::fallbackDrawPosText(GrAtlasTextBlob* blob,
|
||||
}
|
||||
|
||||
inline GrAtlasTextBlob*
|
||||
GrAtlasTextContext::setupDFBlob(int glyphCount, const SkPaint& origPaint,
|
||||
const SkMatrix& viewMatrix, SkPaint* dfPaint,
|
||||
GrAtlasTextContext::setupDFBlob(int glyphCount, const SkPaint& origPaint,
|
||||
const SkMatrix& viewMatrix, SkPaint* dfPaint,
|
||||
SkScalar* textRatio) {
|
||||
GrAtlasTextBlob* blob = fCache->createBlob(glyphCount, 1, kGrayTextVASize);
|
||||
|
||||
@ -725,7 +725,7 @@ GrAtlasTextContext::createDrawTextBlob(GrRenderTarget* rt, const GrClip& clip,
|
||||
byteLength, x, y, clipRect, textRatio, &fallbackTxt, &fallbackPos,
|
||||
&offset, skPaint);
|
||||
if (fallbackTxt.count()) {
|
||||
this->fallbackDrawPosText(blob, 0, rt, clip, paint.getColor(), skPaint, viewMatrix,
|
||||
this->fallbackDrawPosText(blob, 0, rt, clip, paint.getColor(), skPaint, viewMatrix,
|
||||
fallbackTxt, fallbackPos, 2, offset, clipRect);
|
||||
}
|
||||
} else {
|
||||
@ -764,8 +764,8 @@ GrAtlasTextContext::createDrawPosTextBlob(GrRenderTarget* rt, const GrClip& clip
|
||||
byteLength, pos, scalarsPerPosition, offset, clipRect,
|
||||
textRatio, &fallbackTxt, &fallbackPos);
|
||||
if (fallbackTxt.count()) {
|
||||
this->fallbackDrawPosText(blob, 0, rt, clip, paint.getColor(), skPaint, viewMatrix,
|
||||
fallbackTxt, fallbackPos, scalarsPerPosition, offset,
|
||||
this->fallbackDrawPosText(blob, 0, rt, clip, paint.getColor(), skPaint, viewMatrix,
|
||||
fallbackTxt, fallbackPos, scalarsPerPosition, offset,
|
||||
clipRect);
|
||||
}
|
||||
} else {
|
||||
@ -780,7 +780,7 @@ GrAtlasTextContext::createDrawPosTextBlob(GrRenderTarget* rt, const GrClip& clip
|
||||
}
|
||||
|
||||
void GrAtlasTextContext::onDrawText(GrDrawContext* dc, GrRenderTarget* rt,
|
||||
const GrClip& clip,
|
||||
const GrClip& clip,
|
||||
const GrPaint& paint, const SkPaint& skPaint,
|
||||
const SkMatrix& viewMatrix,
|
||||
const char text[], size_t byteLength,
|
||||
@ -826,73 +826,16 @@ void GrAtlasTextContext::internalDrawBMPText(GrAtlasTextBlob* blob, int runIndex
|
||||
// Get GrFontScaler from cache
|
||||
GrFontScaler* fontScaler = GetGrFontScaler(cache);
|
||||
|
||||
// transform our starting point
|
||||
{
|
||||
SkPoint loc;
|
||||
viewMatrix.mapXY(x, y, &loc);
|
||||
x = loc.fX;
|
||||
y = loc.fY;
|
||||
}
|
||||
|
||||
// need to measure first
|
||||
if (skPaint.getTextAlign() != SkPaint::kLeft_Align) {
|
||||
SkVector stopVector;
|
||||
MeasureText(cache, glyphCacheProc, text, byteLength, &stopVector);
|
||||
|
||||
SkScalar stopX = stopVector.fX;
|
||||
SkScalar stopY = stopVector.fY;
|
||||
|
||||
if (skPaint.getTextAlign() == SkPaint::kCenter_Align) {
|
||||
stopX = SkScalarHalf(stopX);
|
||||
stopY = SkScalarHalf(stopY);
|
||||
SkFindAndPlaceGlyph::ProcessText(
|
||||
text, byteLength, {x, y}, viewMatrix, 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);
|
||||
}
|
||||
x -= stopX;
|
||||
y -= stopY;
|
||||
}
|
||||
|
||||
const char* stop = text + byteLength;
|
||||
|
||||
SkAutoKern autokern;
|
||||
|
||||
SkFixed fxMask = ~0;
|
||||
SkFixed fyMask = ~0;
|
||||
SkScalar halfSampleX, halfSampleY;
|
||||
if (cache->isSubpixel()) {
|
||||
halfSampleX = halfSampleY = SkFixedToScalar(SkGlyph::kSubpixelRound);
|
||||
SkAxisAlignment baseline = SkComputeAxisAlignmentForHText(viewMatrix);
|
||||
if (kX_SkAxisAlignment == baseline) {
|
||||
fyMask = 0;
|
||||
halfSampleY = SK_ScalarHalf;
|
||||
} else if (kY_SkAxisAlignment == baseline) {
|
||||
fxMask = 0;
|
||||
halfSampleX = SK_ScalarHalf;
|
||||
}
|
||||
} else {
|
||||
halfSampleX = halfSampleY = SK_ScalarHalf;
|
||||
}
|
||||
|
||||
Sk48Dot16 fx = SkScalarTo48Dot16(x + halfSampleX);
|
||||
Sk48Dot16 fy = SkScalarTo48Dot16(y + halfSampleY);
|
||||
|
||||
while (text < stop) {
|
||||
const SkGlyph& glyph = glyphCacheProc(cache, &text, fx & fxMask, fy & fyMask);
|
||||
|
||||
fx += autokern.adjust(glyph);
|
||||
|
||||
if (glyph.fWidth) {
|
||||
this->bmpAppendGlyph(blob,
|
||||
runIndex,
|
||||
glyph,
|
||||
Sk48Dot16FloorToInt(fx),
|
||||
Sk48Dot16FloorToInt(fy),
|
||||
color,
|
||||
fontScaler,
|
||||
clipRect);
|
||||
}
|
||||
|
||||
fx += glyph.fAdvanceX;
|
||||
fy += glyph.fAdvanceY;
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
void GrAtlasTextContext::internalDrawBMPPosText(GrAtlasTextBlob* blob, int runIndex,
|
||||
@ -949,7 +892,7 @@ void GrAtlasTextContext::internalDrawDFText(GrAtlasTextBlob* blob, int runIndex,
|
||||
SkDrawCacheProc glyphCacheProc = origPaint.getDrawCacheProc();
|
||||
SkAutoDescriptor desc;
|
||||
origPaint.getScalerContextDescriptor(&desc, fSurfaceProps, nullptr, true);
|
||||
SkGlyphCache* origPaintCache = SkGlyphCache::DetachCache(origPaint.getTypeface(),
|
||||
SkGlyphCache* origPaintCache = SkGlyphCache::DetachCache(origPaint.getTypeface(),
|
||||
desc.getDesc());
|
||||
|
||||
SkTArray<SkScalar> positions;
|
||||
@ -1932,7 +1875,7 @@ private:
|
||||
};
|
||||
|
||||
void GrAtlasTextContext::flushRunAsPaths(GrDrawContext* dc, GrRenderTarget* rt,
|
||||
const SkTextBlobRunIterator& it,
|
||||
const SkTextBlobRunIterator& it,
|
||||
const GrClip& clip, const SkPaint& skPaint,
|
||||
SkDrawFilter* drawFilter, const SkMatrix& viewMatrix,
|
||||
const SkIRect& clipBounds, SkScalar x, SkScalar y) {
|
||||
@ -2029,7 +1972,7 @@ inline void GrAtlasTextContext::flushRun(GrDrawContext* dc, GrPipelineBuilder* p
|
||||
}
|
||||
}
|
||||
|
||||
inline void GrAtlasTextContext::flushBigGlyphs(GrAtlasTextBlob* cacheBlob,
|
||||
inline void GrAtlasTextContext::flushBigGlyphs(GrAtlasTextBlob* cacheBlob,
|
||||
GrDrawContext* dc, GrRenderTarget* rt,
|
||||
const GrClip& clip, const SkPaint& skPaint,
|
||||
SkScalar transX, SkScalar transY,
|
||||
@ -2056,7 +1999,7 @@ inline void GrAtlasTextContext::flushBigGlyphs(GrAtlasTextBlob* cacheBlob,
|
||||
|
||||
void GrAtlasTextContext::flush(const SkTextBlob* blob,
|
||||
GrAtlasTextBlob* cacheBlob,
|
||||
GrDrawContext* dc,
|
||||
GrDrawContext* dc,
|
||||
GrRenderTarget* rt,
|
||||
const SkPaint& skPaint,
|
||||
const GrPaint& grPaint,
|
||||
|
Loading…
Reference in New Issue
Block a user