void GrStencilAndCoverTextContext::TextRun::draw(GrContext* ctx, GrDrawContext* dc, GrPipelineBuilder* pipelineBuilder, GrColor color, const SkMatrix& viewMatrix, SkScalar x, SkScalar y, const SkIRect& clipBounds, GrTextContext* fallbackTextContext, const SkPaint& originalSkPaint) const { SkASSERT(fDraw); SkASSERT(pipelineBuilder->getRenderTarget()->isStencilBufferMultisampled() || !fFont.isAntiAlias()); if (fDraw->count()) { pipelineBuilder->setState(GrPipelineBuilder::kHWAntialias_Flag, fFont.isAntiAlias()); GR_STATIC_CONST_SAME_STENCIL(kStencilPass, kZero_StencilOp, kKeep_StencilOp, kNotEqual_StencilFunc, 0xffff, 0x0000, 0xffff); *pipelineBuilder->stencil() = kStencilPass; SkAutoTUnref<GrPathRange> glyphs(this->createGlyphs(ctx)); if (fLastDrawnGlyphsID != glyphs->getUniqueID()) { // Either this is the first draw or the glyphs object was purged since last draw. glyphs->loadPathsIfNeeded(fDraw->indices(), fDraw->count()); fLastDrawnGlyphsID = glyphs->getUniqueID(); } SkMatrix drawMatrix(viewMatrix); drawMatrix.preTranslate(x, y); drawMatrix.preScale(fTextRatio, fTextRatio); SkMatrix& localMatrix = fLocalMatrixTemplate; localMatrix.setTranslateX(x); localMatrix.setTranslateY(y); dc->drawPathsFromRange(pipelineBuilder, drawMatrix, localMatrix, color, glyphs, fDraw, GrPathRendering::kWinding_FillType); } if (fFallbackTextBlob) { SkPaint fallbackSkPaint(originalSkPaint); fStroke.applyToPaint(&fallbackSkPaint); if (!fStroke.isFillStyle()) { fallbackSkPaint.setStrokeWidth(fStroke.getWidth() * fTextRatio); } fallbackTextContext->drawTextBlob(dc, pipelineBuilder->getRenderTarget(), pipelineBuilder->clip(), fallbackSkPaint, viewMatrix, fFallbackTextBlob, x, y, nullptr, clipBounds); } }
void GrStencilAndCoverTextContext::TextRun::draw(GrContext* ctx, GrRenderTargetContext* renderTargetContext, const GrClip& clip, const SkMatrix& viewMatrix, const SkSurfaceProps& props, SkScalar x, SkScalar y, const SkIRect& clipBounds, GrAtlasTextContext* fallbackTextContext, const SkPaint& originalSkPaint) const { SkASSERT(fInstanceData); if (fInstanceData->count()) { static constexpr GrUserStencilSettings kCoverPass( GrUserStencilSettings::StaticInit< 0x0000, GrUserStencilTest::kNotEqual, // Stencil pass accounts for clip. 0xffff, GrUserStencilOp::kZero, GrUserStencilOp::kKeep, 0xffff>() ); sk_sp<GrPathRange> glyphs(this->createGlyphs(ctx->resourceProvider())); if (fLastDrawnGlyphsID != glyphs->uniqueID()) { // Either this is the first draw or the glyphs object was purged since last draw. glyphs->loadPathsIfNeeded(fInstanceData->indices(), fInstanceData->count()); fLastDrawnGlyphsID = glyphs->uniqueID(); } GrPaint grPaint; if (!SkPaintToGrPaint(ctx, renderTargetContext, originalSkPaint, viewMatrix, &grPaint)) { return; } // Don't compute a bounding box. For dst copy texture, we'll opt instead for it to just copy // the entire dst. Realistically this is a moot point, because any context that supports // NV_path_rendering will also support NV_blend_equation_advanced. // For clipping we'll just skip any optimizations based on the bounds. This does, however, // hurt GrOp combining. const SkRect bounds = SkRect::MakeIWH(renderTargetContext->width(), renderTargetContext->height()); // The run's "font" overrides the anti-aliasing of the passed in SkPaint! GrAAType aaType; if (this->aa() == GrAA::kYes) { SkASSERT(renderTargetContext->isStencilBufferMultisampled()); aaType = renderTargetContext->isUnifiedMultisampled() ? GrAAType::kMSAA : GrAAType::kMixedSamples; } else { aaType = GrAAType::kNone; } std::unique_ptr<GrDrawOp> op = GrDrawPathRangeOp::Make( viewMatrix, fTextRatio, fTextInverseRatio * x, fTextInverseRatio * y, std::move(grPaint), GrPathRendering::kWinding_FillType, aaType, glyphs.get(), fInstanceData.get(), bounds); renderTargetContext->addDrawOp(clip, std::move(op)); } if (fFallbackTextBlob) { SkPaint fallbackSkPaint(originalSkPaint); fStyle.strokeRec().applyToPaint(&fallbackSkPaint); if (!fStyle.isSimpleFill()) { fallbackSkPaint.setStrokeWidth(fStyle.strokeRec().getWidth() * fTextRatio); } fallbackTextContext->drawTextBlob(ctx, renderTargetContext, clip, fallbackSkPaint, viewMatrix, props, fFallbackTextBlob.get(), x, y, nullptr, clipBounds); } }
void GrStencilAndCoverTextContext::TextRun::draw(GrContext* ctx, GrDrawContext* dc, GrPipelineBuilder* pipelineBuilder, GrColor color, const SkMatrix& viewMatrix, const SkSurfaceProps& props, SkScalar x, SkScalar y, const SkIRect& clipBounds, GrTextContext* fallbackTextContext, const SkPaint& originalSkPaint) const { SkASSERT(fInstanceData); SkASSERT(dc->accessRenderTarget()->isStencilBufferMultisampled() || !fFont.isAntiAlias()); if (fInstanceData->count()) { pipelineBuilder->setState(GrPipelineBuilder::kHWAntialias_Flag, fFont.isAntiAlias()); GR_STATIC_CONST_SAME_STENCIL(kStencilPass, kZero_StencilOp, kKeep_StencilOp, kNotEqual_StencilFunc, 0xffff, 0x0000, 0xffff); *pipelineBuilder->stencil() = kStencilPass; SkAutoTUnref<GrPathRange> glyphs(this->createGlyphs(ctx)); if (fLastDrawnGlyphsID != glyphs->getUniqueID()) { // Either this is the first draw or the glyphs object was purged since last draw. glyphs->loadPathsIfNeeded(fInstanceData->indices(), fInstanceData->count()); fLastDrawnGlyphsID = glyphs->getUniqueID(); } // Don't compute a bounding box. For dst copy texture, we'll opt instead for it to just copy // the entire dst. Realistically this is a moot point, because any context that supports // NV_path_rendering will also support NV_blend_equation_advanced. // For clipping we'll just skip any optimizations based on the bounds. This does, however, // hurt batching. SkRect bounds = SkRect::MakeIWH(pipelineBuilder->getRenderTarget()->width(), pipelineBuilder->getRenderTarget()->height()); SkAutoTUnref<GrDrawPathBatchBase> batch( GrDrawPathRangeBatch::Create(viewMatrix, fTextRatio, fTextInverseRatio * x, fTextInverseRatio * y, color, GrPathRendering::kWinding_FillType, glyphs, fInstanceData, bounds)); dc->drawPathBatch(*pipelineBuilder, batch); } if (fFallbackTextBlob) { SkPaint fallbackSkPaint(originalSkPaint); fStroke.applyToPaint(&fallbackSkPaint); if (!fStroke.isFillStyle()) { fallbackSkPaint.setStrokeWidth(fStroke.getWidth() * fTextRatio); } fallbackTextContext->drawTextBlob(ctx, dc, pipelineBuilder->clip(), fallbackSkPaint, viewMatrix, props, fFallbackTextBlob, x, y, nullptr, clipBounds); } }
void GrStencilAndCoverTextContext::TextRun::draw(GrContext* ctx, GrDrawContext* drawContext, const GrPaint& grPaint, const GrClip& clip, const SkMatrix& viewMatrix, const SkSurfaceProps& props, SkScalar x, SkScalar y, const SkIRect& clipBounds, GrAtlasTextContext* fallbackTextContext, const SkPaint& originalSkPaint) const { SkASSERT(fInstanceData); SkASSERT(drawContext->isStencilBufferMultisampled() || !grPaint.isAntiAlias()); if (fInstanceData->count()) { static constexpr GrUserStencilSettings kCoverPass( GrUserStencilSettings::StaticInit< 0x0000, GrUserStencilTest::kNotEqual, // Stencil pass accounts for clip. 0xffff, GrUserStencilOp::kZero, GrUserStencilOp::kKeep, 0xffff>() ); SkAutoTUnref<GrPathRange> glyphs(this->createGlyphs(ctx)); if (fLastDrawnGlyphsID != glyphs->uniqueID()) { // Either this is the first draw or the glyphs object was purged since last draw. glyphs->loadPathsIfNeeded(fInstanceData->indices(), fInstanceData->count()); fLastDrawnGlyphsID = glyphs->uniqueID(); } // Don't compute a bounding box. For dst copy texture, we'll opt instead for it to just copy // the entire dst. Realistically this is a moot point, because any context that supports // NV_path_rendering will also support NV_blend_equation_advanced. // For clipping we'll just skip any optimizations based on the bounds. This does, however, // hurt batching. const SkRect bounds = SkRect::MakeIWH(drawContext->width(), drawContext->height()); SkAutoTUnref<GrDrawBatch> batch( GrDrawPathRangeBatch::Create(viewMatrix, fTextRatio, fTextInverseRatio * x, fTextInverseRatio * y, grPaint.getColor(), GrPathRendering::kWinding_FillType, glyphs, fInstanceData, bounds)); GrPipelineBuilder pipelineBuilder(grPaint); pipelineBuilder.setState(GrPipelineBuilder::kHWAntialias_Flag, grPaint.isAntiAlias()); pipelineBuilder.setUserStencil(&kCoverPass); drawContext->drawBatch(pipelineBuilder, clip, batch); } if (fFallbackTextBlob) { SkPaint fallbackSkPaint(originalSkPaint); fStyle.strokeRec().applyToPaint(&fallbackSkPaint); if (!fStyle.isSimpleFill()) { fallbackSkPaint.setStrokeWidth(fStyle.strokeRec().getWidth() * fTextRatio); } fallbackTextContext->drawTextBlob(ctx, drawContext, clip, fallbackSkPaint, viewMatrix, props, fFallbackTextBlob.get(), x, y, nullptr, clipBounds); } }