Example #1
0
void GrContext::drawFontCache(const SkRect& rect, GrMaskFormat format, const SkPaint& paint,
                              GrRenderTarget* target) {
    GrBatchFontCache* cache = this->getBatchFontCache();

    GrTexture* atlas = cache->getTexture(format);

    SkAutoTUnref<GrDrawContext> drawContext(this->drawContext(target));
    // TODO: add drawContext method to encapsulate this.

    GrPaint grPaint;
    SkMatrix mat;
    mat.reset();
    if (!SkPaintToGrPaint(this, paint, mat, &grPaint)) {
        return;
    }
    SkMatrix textureMat;
    textureMat.reset();
    // TODO: use setScaleTranslate()
    textureMat[SkMatrix::kMScaleX] = 1.0f/rect.width();
    textureMat[SkMatrix::kMScaleY] = 1.0f/rect.height();
    textureMat[SkMatrix::kMTransX] = -rect.fLeft/rect.width();
    textureMat[SkMatrix::kMTransY] = -rect.fTop/rect.height();

    grPaint.addColorTextureProcessor(atlas, textureMat);

    GrClip clip;
    drawContext->drawRect(clip, grPaint, mat, rect);
}
void GrStencilAndCoverTextContext::uncachedDrawTextBlob(GrContext* context,
                                                        GrDrawContext* dc,
                                                        const GrClip& clip,
                                                        const SkPaint& skPaint,
                                                        const SkMatrix& viewMatrix,
                                                        const SkSurfaceProps& props,
                                                        const SkTextBlob* blob,
                                                        SkScalar x, SkScalar y,
                                                        SkDrawFilter* drawFilter,
                                                        const SkIRect& clipBounds) {
    SkPaint runPaint = skPaint;

    SkTextBlobRunIterator it(blob);
    for (;!it.done(); it.next()) {
        size_t textLen = it.glyphCount() * sizeof(uint16_t);
        const SkPoint& offset = it.offset();

        // applyFontToPaint() always overwrites the exact same attributes,
        // so it is safe to not re-seed the paint for this reason.
        it.applyFontToPaint(&runPaint);

        if (drawFilter && !drawFilter->filter(&runPaint, SkDrawFilter::kText_Type)) {
            // A false return from filter() means we should abort the current draw.
            runPaint = skPaint;
            continue;
        }

        runPaint.setFlags(GrTextUtils::FilterTextFlags(props, runPaint));

        GrPaint grPaint;
        if (!SkPaintToGrPaint(context, dc, runPaint, viewMatrix, &grPaint)) {
            return;
        }

        switch (it.positioning()) {
            case SkTextBlob::kDefault_Positioning:
                this->drawText(context, dc, clip, grPaint, runPaint, viewMatrix, props,
                               (const char *)it.glyphs(),
                               textLen, x + offset.x(), y + offset.y(), clipBounds);
                break;
            case SkTextBlob::kHorizontal_Positioning:
                this->drawPosText(context, dc, clip, grPaint, runPaint, viewMatrix, props,
                                  (const char*)it.glyphs(),
                                  textLen, it.pos(), 1, SkPoint::Make(x, y + offset.y()),
                                  clipBounds);
                break;
            case SkTextBlob::kFull_Positioning:
                this->drawPosText(context, dc, clip, grPaint, runPaint, viewMatrix, props,
                                  (const char*)it.glyphs(),
                                  textLen, it.pos(), 2, SkPoint::Make(x, y), clipBounds);
                break;
        }

        if (drawFilter) {
            // A draw filter may change the paint arbitrarily, so we must re-seed in this case.
            runPaint = skPaint;
        }
    }
}
Example #3
0
void SkGpuDevice::drawTexture(GrTexture* tex, const SkRect& dst, const SkPaint& paint) {
    GrPaint grPaint;
    SkMatrix mat;
    mat.reset();
    if (!SkPaintToGrPaint(this->context(), paint, mat,
                          this->surfaceProps().isGammaCorrect(), &grPaint)) {
        return;
    }
    SkMatrix textureMat;
    textureMat.reset();
    textureMat[SkMatrix::kMScaleX] = 1.0f/dst.width();
    textureMat[SkMatrix::kMScaleY] = 1.0f/dst.height();
    textureMat[SkMatrix::kMTransX] = -dst.fLeft/dst.width();
    textureMat[SkMatrix::kMTransY] = -dst.fTop/dst.height();

    grPaint.addColorTextureProcessor(tex, textureMat);

    fDrawContext->drawRect(GrNoClip(), grPaint, mat, dst);
}
void GrStencilAndCoverTextContext::drawTextBlob(GrContext* context, GrDrawContext* dc,
                                                const GrClip& clip, const SkPaint& skPaint,
                                                const SkMatrix& viewMatrix,
                                                const SkSurfaceProps& props,
                                                const SkTextBlob* skBlob, SkScalar x, SkScalar y,
                                                SkDrawFilter* drawFilter,
                                                const SkIRect& clipBounds) {
    if (context->abandoned()) {
        return;
    }

    if (!this->internalCanDraw(skPaint)) {
        fFallbackTextContext->drawTextBlob(context, dc, clip, skPaint, viewMatrix, props, skBlob,
                                           x, y, drawFilter, clipBounds);
        return;
    }

    if (drawFilter || skPaint.getPathEffect()) {
        // This draw can't be cached.
        this->uncachedDrawTextBlob(context, dc, clip, skPaint, viewMatrix, props, skBlob, x, y,
                                   drawFilter, clipBounds);
        return;
    }

    GrPaint paint;
    if (!SkPaintToGrPaint(context, dc, skPaint, viewMatrix, &paint)) {
        return;
    }

    const TextBlob& blob = this->findOrCreateTextBlob(skBlob, skPaint);

    TextBlob::Iter iter(blob);
    for (TextRun* run = iter.get(); run; run = iter.next()) {
        // The run's "font" overrides the anti-aliasing of the passed in paint!
        paint.setAntiAlias(run->isAntiAlias());
        run->draw(context, dc, paint, clip, viewMatrix, props,  x, y,
                  clipBounds, fFallbackTextContext, skPaint);
        run->releaseGlyphCache();
    }
}
void GrStencilAndCoverTextContext::drawTextBlob(GrContext* context, GrDrawContext* dc,
        const GrClip& clip, const SkPaint& skPaint,
        const SkMatrix& viewMatrix,
        const SkSurfaceProps& props,
        const SkTextBlob* skBlob, SkScalar x, SkScalar y,
        SkDrawFilter* drawFilter,
        const SkIRect& clipBounds) {
    if (context->abandoned()) {
        return;
    }

    if (!this->internalCanDraw(skPaint)) {
        fFallbackTextContext->drawTextBlob(context, dc, clip, skPaint, viewMatrix, props, skBlob,
                                           x, y, drawFilter, clipBounds);
        return;
    }

    if (drawFilter || skPaint.getPathEffect()) {
        // This draw can't be cached.
        this->uncachedDrawTextBlob(context, dc, clip, skPaint, viewMatrix, props, skBlob, x, y,
                                   drawFilter, clipBounds);
        return;
    }

    GrPaint paint;
    if (!SkPaintToGrPaint(context, skPaint, viewMatrix, &paint)) {
        return;
    }

    const TextBlob& blob = this->findOrCreateTextBlob(skBlob, skPaint);
    GrPipelineBuilder pipelineBuilder(paint, dc->accessRenderTarget(), clip);

    TextBlob::Iter iter(blob);
    for (TextRun* run = iter.get(); run; run = iter.next()) {
        run->draw(context, dc, &pipelineBuilder, paint.getColor(), viewMatrix, props,  x, y,
                  clipBounds, fFallbackTextContext, skPaint);
        run->releaseGlyphCache();
    }
}
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);
    }
}