Add TextRun object to nvpr text
Adds a TextRun object that defines a resolution-independent, paint- indepent draw for a string of nvpr text. BUG=skia: Review URL: https://codereview.chromium.org/1375353004
This commit is contained in:
parent
cc7f305c69
commit
3bd909a44c
@ -25,9 +25,7 @@
|
||||
|
||||
GrStencilAndCoverTextContext::GrStencilAndCoverTextContext(GrContext* context,
|
||||
const SkSurfaceProps& surfaceProps)
|
||||
: INHERITED(context, surfaceProps)
|
||||
, fDraw(nullptr)
|
||||
, fStroke(SkStrokeRec::kFill_InitStyle) {
|
||||
: INHERITED(context, surfaceProps) {
|
||||
}
|
||||
|
||||
GrStencilAndCoverTextContext*
|
||||
@ -71,20 +69,103 @@ void GrStencilAndCoverTextContext::onDrawText(GrDrawContext* dc, GrRenderTarget*
|
||||
size_t byteLength,
|
||||
SkScalar x, SkScalar y,
|
||||
const SkIRect& regionClipBounds) {
|
||||
SkASSERT(byteLength == 0 || text != nullptr);
|
||||
TextRun run(skPaint);
|
||||
run.setText(text, byteLength, x, y, fContext, &fSurfaceProps);
|
||||
run.draw(dc, rt, clip, paint, viewMatrix, regionClipBounds, fFallbackTextContext, skPaint);
|
||||
}
|
||||
|
||||
if (text == nullptr || byteLength == 0 /*|| fRC->isEmpty()*/) {
|
||||
return;
|
||||
void GrStencilAndCoverTextContext::onDrawPosText(GrDrawContext* dc, GrRenderTarget* rt,
|
||||
const GrClip& clip,
|
||||
const GrPaint& paint,
|
||||
const SkPaint& skPaint,
|
||||
const SkMatrix& viewMatrix,
|
||||
const char text[],
|
||||
size_t byteLength,
|
||||
const SkScalar pos[],
|
||||
int scalarsPerPosition,
|
||||
const SkPoint& offset,
|
||||
const SkIRect& regionClipBounds) {
|
||||
TextRun run(skPaint);
|
||||
run.setPosText(text, byteLength, pos, scalarsPerPosition, offset, fContext, &fSurfaceProps);
|
||||
run.draw(dc, rt, clip, paint, viewMatrix, regionClipBounds, fFallbackTextContext, skPaint);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
GrStencilAndCoverTextContext::TextRun::TextRun(const SkPaint& fontAndStroke)
|
||||
: fStroke(fontAndStroke),
|
||||
fFont(fontAndStroke) {
|
||||
SkASSERT(!fStroke.isHairlineStyle()); // Hairlines are not supported.
|
||||
|
||||
// Setting to "fill" ensures that no strokes get baked into font outlines. (We use the GPU path
|
||||
// rendering API for stroking).
|
||||
fFont.setStyle(SkPaint::kFill_Style);
|
||||
|
||||
if (fFont.isFakeBoldText() && SkStrokeRec::kStroke_Style != fStroke.getStyle()) {
|
||||
// Instead of letting fake bold get baked into the glyph outlines, do it with GPU stroke.
|
||||
SkScalar fakeBoldScale = SkScalarInterpFunc(fFont.getTextSize(),
|
||||
kStdFakeBoldInterpKeys,
|
||||
kStdFakeBoldInterpValues,
|
||||
kStdFakeBoldInterpLength);
|
||||
SkScalar extra = SkScalarMul(fFont.getTextSize(), fakeBoldScale);
|
||||
fStroke.setStrokeStyle(fStroke.needToApply() ? fStroke.getWidth() + extra : extra,
|
||||
true /*strokeAndFill*/);
|
||||
|
||||
fFont.setFakeBoldText(false);
|
||||
}
|
||||
|
||||
this->init(rt, clip, paint, skPaint, byteLength, viewMatrix, regionClipBounds);
|
||||
if (!fFont.getPathEffect() && !fStroke.isDashed()) {
|
||||
// We can draw the glyphs from canonically sized paths.
|
||||
fTextRatio = fFont.getTextSize() / SkPaint::kCanonicalTextSizeForPaths;
|
||||
fTextInverseRatio = SkPaint::kCanonicalTextSizeForPaths / fFont.getTextSize();
|
||||
|
||||
SkDrawCacheProc glyphCacheProc = fSkPaint.getDrawCacheProc();
|
||||
// Compensate for the glyphs being scaled by fTextRatio.
|
||||
if (!fStroke.isFillStyle()) {
|
||||
fStroke.setStrokeStyle(fStroke.getWidth() / fTextRatio,
|
||||
SkStrokeRec::kStrokeAndFill_Style == fStroke.getStyle());
|
||||
}
|
||||
|
||||
fFont.setLinearText(true);
|
||||
fFont.setLCDRenderText(false);
|
||||
fFont.setAutohinted(false);
|
||||
fFont.setHinting(SkPaint::kNo_Hinting);
|
||||
fFont.setSubpixelText(true);
|
||||
fFont.setTextSize(SkIntToScalar(SkPaint::kCanonicalTextSizeForPaths));
|
||||
|
||||
fUsingRawGlyphPaths = SK_Scalar1 == fFont.getTextScaleX() &&
|
||||
0 == fFont.getTextSkewX() &&
|
||||
!fFont.isFakeBoldText() &&
|
||||
!fFont.isVerticalText();
|
||||
} else {
|
||||
fTextRatio = fTextInverseRatio = 1.0f;
|
||||
fUsingRawGlyphPaths = false;
|
||||
}
|
||||
|
||||
// When drawing from canonically sized paths, the actual local coords are fTextRatio * coords.
|
||||
fLocalMatrix.setScale(fTextRatio, fTextRatio);
|
||||
}
|
||||
|
||||
GrStencilAndCoverTextContext::TextRun::~TextRun() {
|
||||
}
|
||||
|
||||
void GrStencilAndCoverTextContext::TextRun::setText(const char text[], size_t byteLength,
|
||||
SkScalar x, SkScalar y, GrContext* ctx,
|
||||
const SkSurfaceProps* surfaceProps) {
|
||||
SkASSERT(byteLength == 0 || text != nullptr);
|
||||
|
||||
SkAutoGlyphCacheNoGamma autoGlyphCache(fFont, surfaceProps, nullptr);
|
||||
SkGlyphCache* glyphCache = autoGlyphCache.getCache();
|
||||
|
||||
fDraw.reset(GrPathRangeDraw::Create(this->createGlyphs(ctx, glyphCache),
|
||||
GrPathRendering::kTranslate_PathTransformType,
|
||||
fFont.countText(text, byteLength)));
|
||||
|
||||
SkDrawCacheProc glyphCacheProc = fFont.getDrawCacheProc();
|
||||
|
||||
const char* stop = text + byteLength;
|
||||
|
||||
// Measure first if needed.
|
||||
if (fSkPaint.getTextAlign() != SkPaint::kLeft_Align) {
|
||||
if (fFont.getTextAlign() != SkPaint::kLeft_Align) {
|
||||
SkFixed stopX = 0;
|
||||
SkFixed stopY = 0;
|
||||
|
||||
@ -92,7 +173,7 @@ void GrStencilAndCoverTextContext::onDrawText(GrDrawContext* dc, GrRenderTarget*
|
||||
while (textPtr < stop) {
|
||||
// We don't need x, y here, since all subpixel variants will have the
|
||||
// same advance.
|
||||
const SkGlyph& glyph = glyphCacheProc(fGlyphCache, &textPtr, 0, 0);
|
||||
const SkGlyph& glyph = glyphCacheProc(glyphCache, &textPtr, 0, 0);
|
||||
|
||||
stopX += glyph.fAdvanceX;
|
||||
stopY += glyph.fAdvanceY;
|
||||
@ -102,7 +183,7 @@ void GrStencilAndCoverTextContext::onDrawText(GrDrawContext* dc, GrRenderTarget*
|
||||
SkScalar alignX = SkFixedToScalar(stopX) * fTextRatio;
|
||||
SkScalar alignY = SkFixedToScalar(stopY) * fTextRatio;
|
||||
|
||||
if (fSkPaint.getTextAlign() == SkPaint::kCenter_Align) {
|
||||
if (fFont.getTextAlign() == SkPaint::kCenter_Align) {
|
||||
alignX = SkScalarHalf(alignX);
|
||||
alignY = SkScalarHalf(alignY);
|
||||
}
|
||||
@ -118,7 +199,7 @@ void GrStencilAndCoverTextContext::onDrawText(GrDrawContext* dc, GrRenderTarget*
|
||||
SkFixed fx = SkScalarToFixed(x);
|
||||
SkFixed fy = SkScalarToFixed(y);
|
||||
while (text < stop) {
|
||||
const SkGlyph& glyph = glyphCacheProc(fGlyphCache, &text, 0, 0);
|
||||
const SkGlyph& glyph = glyphCacheProc(glyphCache, &text, 0, 0);
|
||||
fx += SkFixedMul(autokern.adjust(glyph), fixedSizeRatio);
|
||||
if (glyph.fWidth) {
|
||||
this->appendGlyph(glyph, SkPoint::Make(SkFixedToScalar(fx), SkFixedToScalar(fy)));
|
||||
@ -127,39 +208,30 @@ void GrStencilAndCoverTextContext::onDrawText(GrDrawContext* dc, GrRenderTarget*
|
||||
fx += SkFixedMul(glyph.fAdvanceX, fixedSizeRatio);
|
||||
fy += SkFixedMul(glyph.fAdvanceY, fixedSizeRatio);
|
||||
}
|
||||
|
||||
this->finish(dc);
|
||||
}
|
||||
|
||||
void GrStencilAndCoverTextContext::onDrawPosText(GrDrawContext* dc, GrRenderTarget* rt,
|
||||
const GrClip& clip,
|
||||
const GrPaint& paint,
|
||||
const SkPaint& skPaint,
|
||||
const SkMatrix& viewMatrix,
|
||||
const char text[],
|
||||
size_t byteLength,
|
||||
const SkScalar pos[],
|
||||
int scalarsPerPosition,
|
||||
const SkPoint& offset,
|
||||
const SkIRect& regionClipBounds) {
|
||||
void GrStencilAndCoverTextContext::TextRun::setPosText(const char text[], size_t byteLength,
|
||||
const SkScalar pos[], int scalarsPerPosition,
|
||||
const SkPoint& offset, GrContext* ctx,
|
||||
const SkSurfaceProps* surfaceProps) {
|
||||
SkASSERT(byteLength == 0 || text != nullptr);
|
||||
SkASSERT(1 == scalarsPerPosition || 2 == scalarsPerPosition);
|
||||
|
||||
// nothing to draw
|
||||
if (text == nullptr || byteLength == 0/* || fRC->isEmpty()*/) {
|
||||
return;
|
||||
}
|
||||
SkAutoGlyphCacheNoGamma autoGlyphCache(fFont, surfaceProps, nullptr);
|
||||
SkGlyphCache* glyphCache = autoGlyphCache.getCache();
|
||||
|
||||
this->init(rt, clip, paint, skPaint, byteLength, viewMatrix, regionClipBounds);
|
||||
fDraw.reset(GrPathRangeDraw::Create(this->createGlyphs(ctx, glyphCache),
|
||||
GrPathRendering::kTranslate_PathTransformType,
|
||||
fFont.countText(text, byteLength)));
|
||||
|
||||
SkDrawCacheProc glyphCacheProc = fSkPaint.getDrawCacheProc();
|
||||
SkDrawCacheProc glyphCacheProc = fFont.getDrawCacheProc();
|
||||
|
||||
const char* stop = text + byteLength;
|
||||
|
||||
SkTextMapStateProc tmsProc(SkMatrix::I(), offset, scalarsPerPosition);
|
||||
SkTextAlignProc alignProc(fSkPaint.getTextAlign());
|
||||
SkTextAlignProc alignProc(fFont.getTextAlign());
|
||||
while (text < stop) {
|
||||
const SkGlyph& glyph = glyphCacheProc(fGlyphCache, &text, 0, 0);
|
||||
const SkGlyph& glyph = glyphCacheProc(glyphCache, &text, 0, 0);
|
||||
if (glyph.fWidth) {
|
||||
SkPoint tmsLoc;
|
||||
tmsProc(pos, &tmsLoc);
|
||||
@ -170,23 +242,22 @@ void GrStencilAndCoverTextContext::onDrawPosText(GrDrawContext* dc, GrRenderTarg
|
||||
}
|
||||
pos += scalarsPerPosition;
|
||||
}
|
||||
|
||||
this->finish(dc);
|
||||
}
|
||||
|
||||
static GrPathRange* get_gr_glyphs(GrContext* ctx,
|
||||
const SkTypeface* typeface,
|
||||
const SkDescriptor* desc,
|
||||
const GrStrokeInfo& stroke) {
|
||||
GrPathRange* GrStencilAndCoverTextContext::TextRun::createGlyphs(GrContext* ctx,
|
||||
SkGlyphCache* glyphCache) {
|
||||
SkTypeface* typeface = fUsingRawGlyphPaths ? fFont.getTypeface()
|
||||
: glyphCache->getScalerContext()->getTypeface();
|
||||
const SkDescriptor* desc = fUsingRawGlyphPaths ? nullptr : &glyphCache->getDescriptor();
|
||||
|
||||
static const GrUniqueKey::Domain kPathGlyphDomain = GrUniqueKey::GenerateDomain();
|
||||
int strokeDataCount = stroke.computeUniqueKeyFragmentData32Cnt();
|
||||
int strokeDataCount = fStroke.computeUniqueKeyFragmentData32Cnt();
|
||||
GrUniqueKey glyphKey;
|
||||
GrUniqueKey::Builder builder(&glyphKey, kPathGlyphDomain, 2 + strokeDataCount);
|
||||
reinterpret_cast<uint32_t&>(builder[0]) = desc ? desc->getChecksum() : 0;
|
||||
reinterpret_cast<uint32_t&>(builder[1]) = typeface ? typeface->uniqueID() : 0;
|
||||
if (strokeDataCount > 0) {
|
||||
stroke.asUniqueKeyFragment(&builder[2]);
|
||||
fStroke.asUniqueKeyFragment(&builder[2]);
|
||||
}
|
||||
builder.finish();
|
||||
|
||||
@ -194,7 +265,7 @@ static GrPathRange* get_gr_glyphs(GrContext* ctx,
|
||||
static_cast<GrPathRange*>(
|
||||
ctx->resourceProvider()->findAndRefResourceByUniqueKey(glyphKey)));
|
||||
if (nullptr == glyphs) {
|
||||
glyphs.reset(ctx->resourceProvider()->createGlyphs(typeface, desc, stroke));
|
||||
glyphs.reset(ctx->resourceProvider()->createGlyphs(typeface, desc, fStroke));
|
||||
ctx->resourceProvider()->assignUniqueKeyToResource(glyphKey, glyphs);
|
||||
} else {
|
||||
SkASSERT(nullptr == desc || glyphs->isEqualTo(*desc));
|
||||
@ -203,107 +274,32 @@ static GrPathRange* get_gr_glyphs(GrContext* ctx,
|
||||
return glyphs.detach();
|
||||
}
|
||||
|
||||
void GrStencilAndCoverTextContext::init(GrRenderTarget* rt,
|
||||
const GrClip& clip,
|
||||
const GrPaint& paint,
|
||||
const SkPaint& skPaint,
|
||||
size_t textByteLength,
|
||||
const SkMatrix& viewMatrix,
|
||||
const SkIRect& regionClipBounds) {
|
||||
fClip = clip;
|
||||
|
||||
fRenderTarget.reset(SkRef(rt));
|
||||
|
||||
fRegionClipBounds = regionClipBounds;
|
||||
fClip.getConservativeBounds(fRenderTarget->width(), fRenderTarget->height(), &fClipRect);
|
||||
|
||||
fPaint = paint;
|
||||
fSkPaint = skPaint;
|
||||
|
||||
// Don't bake strokes into the glyph outlines. We will stroke the glyphs using the GPU instead.
|
||||
fStroke = GrStrokeInfo(fSkPaint);
|
||||
fSkPaint.setStyle(SkPaint::kFill_Style);
|
||||
|
||||
SkASSERT(!fStroke.isHairlineStyle()); // Hairlines are not supported.
|
||||
|
||||
if (fSkPaint.isFakeBoldText() && SkStrokeRec::kStroke_Style != fStroke.getStyle()) {
|
||||
// Instead of baking fake bold into the glyph outlines, do it with the GPU stroke.
|
||||
SkScalar fakeBoldScale = SkScalarInterpFunc(fSkPaint.getTextSize(),
|
||||
kStdFakeBoldInterpKeys,
|
||||
kStdFakeBoldInterpValues,
|
||||
kStdFakeBoldInterpLength);
|
||||
SkScalar extra = SkScalarMul(fSkPaint.getTextSize(), fakeBoldScale);
|
||||
fStroke.setStrokeStyle(fStroke.needToApply() ? fStroke.getWidth() + extra : extra,
|
||||
true /*strokeAndFill*/);
|
||||
|
||||
fSkPaint.setFakeBoldText(false);
|
||||
}
|
||||
|
||||
bool canUseRawPaths;
|
||||
if (!fStroke.isDashed()) {
|
||||
// We can draw the glyphs from canonically sized paths.
|
||||
fTextRatio = fSkPaint.getTextSize() / SkPaint::kCanonicalTextSizeForPaths;
|
||||
fTextInverseRatio = SkPaint::kCanonicalTextSizeForPaths / fSkPaint.getTextSize();
|
||||
|
||||
// Compensate for the glyphs being scaled by fTextRatio.
|
||||
if (!fStroke.isFillStyle()) {
|
||||
fStroke.setStrokeStyle(fStroke.getWidth() / fTextRatio,
|
||||
SkStrokeRec::kStrokeAndFill_Style == fStroke.getStyle());
|
||||
}
|
||||
|
||||
fSkPaint.setLinearText(true);
|
||||
fSkPaint.setLCDRenderText(false);
|
||||
fSkPaint.setAutohinted(false);
|
||||
fSkPaint.setHinting(SkPaint::kNo_Hinting);
|
||||
fSkPaint.setSubpixelText(true);
|
||||
fSkPaint.setTextSize(SkIntToScalar(SkPaint::kCanonicalTextSizeForPaths));
|
||||
|
||||
canUseRawPaths = SK_Scalar1 == fSkPaint.getTextScaleX() &&
|
||||
0 == fSkPaint.getTextSkewX() &&
|
||||
!fSkPaint.isFakeBoldText() &&
|
||||
!fSkPaint.isVerticalText();
|
||||
} else {
|
||||
fTextRatio = fTextInverseRatio = 1.0f;
|
||||
canUseRawPaths = false;
|
||||
}
|
||||
|
||||
fViewMatrix = viewMatrix;
|
||||
fViewMatrix.preScale(fTextRatio, fTextRatio);
|
||||
fLocalMatrix.setScale(fTextRatio, fTextRatio);
|
||||
|
||||
fGlyphCache = fSkPaint.detachCache(&fSurfaceProps, nullptr, true /*ignoreGamma*/);
|
||||
fGlyphs = canUseRawPaths ?
|
||||
get_gr_glyphs(fContext, fSkPaint.getTypeface(), nullptr, fStroke) :
|
||||
get_gr_glyphs(fContext, fGlyphCache->getScalerContext()->getTypeface(),
|
||||
&fGlyphCache->getDescriptor(), fStroke);
|
||||
}
|
||||
|
||||
inline void GrStencilAndCoverTextContext::appendGlyph(const SkGlyph& glyph, const SkPoint& pos) {
|
||||
inline void GrStencilAndCoverTextContext::TextRun::appendGlyph(const SkGlyph& glyph,
|
||||
const SkPoint& pos) {
|
||||
// Stick the glyphs we can't draw into the fallback arrays.
|
||||
if (SkMask::kARGB32_Format == glyph.fMaskFormat) {
|
||||
fFallbackIndices.push_back(glyph.getGlyphID());
|
||||
fFallbackPositions.push_back(pos);
|
||||
} else {
|
||||
// TODO: infer the reserve count from the text length.
|
||||
if (!fDraw) {
|
||||
fDraw = GrPathRangeDraw::Create(fGlyphs,
|
||||
GrPathRendering::kTranslate_PathTransformType,
|
||||
64);
|
||||
}
|
||||
float translate[] = { fTextInverseRatio * pos.x(), fTextInverseRatio * pos.y() };
|
||||
fDraw->append(glyph.getGlyphID(), translate);
|
||||
}
|
||||
}
|
||||
|
||||
void GrStencilAndCoverTextContext::flush(GrDrawContext* dc) {
|
||||
if (fDraw) {
|
||||
SkASSERT(fDraw->count());
|
||||
void GrStencilAndCoverTextContext::TextRun::draw(GrDrawContext* dc,
|
||||
GrRenderTarget* rt,
|
||||
const GrClip& clip,
|
||||
const GrPaint& paint,
|
||||
const SkMatrix& viewMatrix,
|
||||
const SkIRect& regionClipBounds,
|
||||
GrTextContext* fallbackTextContext,
|
||||
const SkPaint& originalSkPaint) const {
|
||||
SkASSERT(fDraw);
|
||||
|
||||
// We should only be flushing about once every run. However, if this impacts performance
|
||||
// we could move the creation of the GrPipelineBuilder earlier.
|
||||
GrPipelineBuilder pipelineBuilder(fPaint, fRenderTarget, fClip);
|
||||
SkASSERT(fRenderTarget->isStencilBufferMultisampled() || !fPaint.isAntiAlias());
|
||||
pipelineBuilder.setState(GrPipelineBuilder::kHWAntialias_Flag, fPaint.isAntiAlias());
|
||||
if (fDraw->count()) {
|
||||
GrPipelineBuilder pipelineBuilder(paint, rt, clip);
|
||||
SkASSERT(rt->isStencilBufferMultisampled() || !paint.isAntiAlias());
|
||||
pipelineBuilder.setState(GrPipelineBuilder::kHWAntialias_Flag, paint.isAntiAlias());
|
||||
|
||||
GR_STATIC_CONST_SAME_STENCIL(kStencilPass,
|
||||
kZero_StencilOp,
|
||||
@ -315,50 +311,38 @@ void GrStencilAndCoverTextContext::flush(GrDrawContext* dc) {
|
||||
|
||||
*pipelineBuilder.stencil() = kStencilPass;
|
||||
|
||||
dc->drawPathsFromRange(&pipelineBuilder, fViewMatrix, fLocalMatrix, fPaint.getColor(),
|
||||
fDraw, GrPathRendering::kWinding_FillType);
|
||||
fDraw->unref();
|
||||
fDraw = nullptr;
|
||||
SkMatrix drawMatrix(viewMatrix);
|
||||
drawMatrix.preScale(fTextRatio, fTextRatio);
|
||||
|
||||
dc->drawPathsFromRange(&pipelineBuilder, drawMatrix, fLocalMatrix, paint.getColor(), fDraw,
|
||||
GrPathRendering::kWinding_FillType);
|
||||
}
|
||||
|
||||
if (fFallbackIndices.count()) {
|
||||
SkASSERT(fFallbackPositions.count() == fFallbackIndices.count());
|
||||
|
||||
SkPaint fallbackSkPaint(fSkPaint);
|
||||
enum { kPreservedFlags = SkPaint::kFakeBoldText_Flag | SkPaint::kLinearText_Flag |
|
||||
SkPaint::kLCDRenderText_Flag | SkPaint::kAutoHinting_Flag };
|
||||
|
||||
SkPaint fallbackSkPaint(originalSkPaint);
|
||||
fStroke.applyToPaint(&fallbackSkPaint);
|
||||
if (!fStroke.isFillStyle()) {
|
||||
fallbackSkPaint.setStrokeWidth(fStroke.getWidth() * fTextRatio);
|
||||
}
|
||||
fallbackSkPaint.setTextAlign(SkPaint::kLeft_Align); // Align has already been accounted for.
|
||||
fallbackSkPaint.setTextEncoding(SkPaint::kGlyphID_TextEncoding);
|
||||
fallbackSkPaint.setHinting(fFont.getHinting());
|
||||
fallbackSkPaint.setFlags((fFont.getFlags() & kPreservedFlags) |
|
||||
(originalSkPaint.getFlags() & ~kPreservedFlags));
|
||||
// No need for subpixel positioning with bitmap glyphs. TODO: revisit if non-bitmap color
|
||||
// glyphs show up and https://code.google.com/p/skia/issues/detail?id=4408 gets resolved.
|
||||
fallbackSkPaint.setSubpixelText(false);
|
||||
fallbackSkPaint.setTextSize(fSkPaint.getTextSize() * fTextRatio);
|
||||
fallbackSkPaint.setTextSize(fFont.getTextSize() * fTextRatio);
|
||||
|
||||
SkMatrix fallbackMatrix(fViewMatrix);
|
||||
fallbackMatrix.preScale(fTextInverseRatio, fTextInverseRatio);
|
||||
|
||||
fFallbackTextContext->drawPosText(dc, fRenderTarget, fClip, fPaint, fallbackSkPaint,
|
||||
fallbackMatrix, (char*)fFallbackIndices.begin(),
|
||||
sizeof(uint16_t) * fFallbackIndices.count(),
|
||||
fFallbackPositions[0].asScalars(), 2, SkPoint::Make(0, 0),
|
||||
fRegionClipBounds);
|
||||
fFallbackIndices.reset();
|
||||
fFallbackPositions.reset();
|
||||
fallbackTextContext->drawPosText(dc, rt, clip, paint, fallbackSkPaint, viewMatrix,
|
||||
(char*)fFallbackIndices.begin(),
|
||||
sizeof(uint16_t) * fFallbackIndices.count(),
|
||||
fFallbackPositions[0].asScalars(), 2, SkPoint::Make(0, 0),
|
||||
regionClipBounds);
|
||||
}
|
||||
}
|
||||
|
||||
void GrStencilAndCoverTextContext::finish(GrDrawContext* dc) {
|
||||
this->flush(dc);
|
||||
|
||||
SkASSERT(!fDraw);
|
||||
SkASSERT(!fFallbackIndices.count());
|
||||
SkASSERT(!fFallbackPositions.count());
|
||||
|
||||
fGlyphs->unref();
|
||||
fGlyphs = nullptr;
|
||||
|
||||
SkGlyphCache::AttachCache(fGlyphCache);
|
||||
fGlyphCache = nullptr;
|
||||
}
|
||||
|
@ -15,7 +15,6 @@
|
||||
class GrTextStrike;
|
||||
class GrPath;
|
||||
class GrPathRange;
|
||||
class GrPathRangeDraw;
|
||||
class SkSurfaceProps;
|
||||
|
||||
/*
|
||||
@ -30,25 +29,6 @@ public:
|
||||
virtual ~GrStencilAndCoverTextContext();
|
||||
|
||||
private:
|
||||
SkScalar fTextRatio;
|
||||
float fTextInverseRatio;
|
||||
SkGlyphCache* fGlyphCache;
|
||||
|
||||
GrPathRange* fGlyphs;
|
||||
GrPathRangeDraw* fDraw;
|
||||
GrStrokeInfo fStroke;
|
||||
SkSTArray<32, uint16_t, true> fFallbackIndices;
|
||||
SkSTArray<32, SkPoint, true> fFallbackPositions;
|
||||
|
||||
SkMatrix fViewMatrix;
|
||||
SkMatrix fLocalMatrix;
|
||||
SkAutoTUnref<GrRenderTarget> fRenderTarget;
|
||||
GrClip fClip;
|
||||
SkIRect fClipRect;
|
||||
SkIRect fRegionClipBounds;
|
||||
GrPaint fPaint;
|
||||
SkPaint fSkPaint;
|
||||
|
||||
GrStencilAndCoverTextContext(GrContext*, const SkSurfaceProps&);
|
||||
|
||||
bool canDraw(const GrRenderTarget*, const GrClip&, const GrPaint&,
|
||||
@ -65,11 +45,37 @@ private:
|
||||
const SkScalar pos[], int scalarsPerPosition,
|
||||
const SkPoint& offset, const SkIRect& regionClipBounds) override;
|
||||
|
||||
void init(GrRenderTarget*, const GrClip&, const GrPaint&, const SkPaint&, size_t textByteLength,
|
||||
const SkMatrix& viewMatrix, const SkIRect& regionClipBounds);
|
||||
void appendGlyph(const SkGlyph&, const SkPoint&);
|
||||
void flush(GrDrawContext* dc);
|
||||
void finish(GrDrawContext* dc);
|
||||
class TextRun {
|
||||
public:
|
||||
TextRun(const SkPaint& fontAndStroke);
|
||||
~TextRun();
|
||||
|
||||
void setText(const char text[], size_t byteLength, SkScalar x, SkScalar y,
|
||||
GrContext*, const SkSurfaceProps*);
|
||||
|
||||
void setPosText(const char text[], size_t byteLength,
|
||||
const SkScalar pos[], int scalarsPerPosition, const SkPoint& offset,
|
||||
GrContext*, const SkSurfaceProps*);
|
||||
|
||||
void draw(GrDrawContext*, GrRenderTarget*, const GrClip&, const GrPaint&, const SkMatrix&,
|
||||
const SkIRect& regionClipBounds, GrTextContext* fallbackTextContext,
|
||||
const SkPaint& originalSkPaint) const;
|
||||
|
||||
private:
|
||||
GrPathRange* createGlyphs(GrContext*, SkGlyphCache*);
|
||||
|
||||
void appendGlyph(const SkGlyph&, const SkPoint&);
|
||||
|
||||
GrStrokeInfo fStroke;
|
||||
SkPaint fFont;
|
||||
SkScalar fTextRatio;
|
||||
float fTextInverseRatio;
|
||||
SkMatrix fLocalMatrix;
|
||||
bool fUsingRawGlyphPaths;
|
||||
SkAutoTUnref<GrPathRangeDraw> fDraw;
|
||||
SkSTArray<32, uint16_t, true> fFallbackIndices;
|
||||
SkSTArray<32, SkPoint, true> fFallbackPositions;
|
||||
};
|
||||
|
||||
typedef GrTextContext INHERITED;
|
||||
};
|
||||
|
Loading…
Reference in New Issue
Block a user