Пример #1
0
    void onDraw(SkCanvas* canvas) override {
        canvas->drawARGB(255, 0, 0, 0);

        SkRect r = SkRect::MakeXYWH(16.5f, 16.5f, 96.0f, 96.0f);

        SkPaint p0;
        p0.setColor(SK_ColorWHITE);
        p0.setAntiAlias(true);

        canvas->drawRect(r, p0);

        r = SkRect::MakeXYWH(3.5f, 3.5f, 59.0f, 59.0f);

        // UL corner: replace white with green with a tight tolerance
        SkPaint p1;
        p1.setColor(SK_ColorGREEN);
        p1.setAntiAlias(true);
        p1.setXfermode(SkAvoidXfermode::Create(SK_ColorWHITE,
                                               5,
                                               SkAvoidXfermode::kTargetColor_Mode))->unref();

        canvas->drawRect(r, p1);

        r.offsetTo(65.5f, 3.5f);

        // UR corner: draw red everywhere except white with a tight tolerance
        SkPaint p2;
        p2.setColor(SK_ColorRED);
        p2.setAntiAlias(true);
        p2.setXfermode(SkAvoidXfermode::Create(SK_ColorWHITE,
                                               250,
                                               SkAvoidXfermode::kAvoidColor_Mode))->unref();

        canvas->drawRect(r, p2);

        r.offsetTo(3.5f, 65.5f);

        // LL corner: replace white with blue with a loose tolerance
        SkPaint p3;
        p3.setColor(SK_ColorBLUE);
        p3.setAntiAlias(true);
        p3.setXfermode(SkAvoidXfermode::Create(SK_ColorWHITE,
                                               250,
                                               SkAvoidXfermode::kTargetColor_Mode))->unref();

        canvas->drawRect(r, p3);

        r.offsetTo(65.5f, 65.5f);

        // LR corner: draw yellow everywhere except white with a loose tolerance
        SkPaint p4;
        p4.setColor(SK_ColorYELLOW);
        p4.setAntiAlias(true);
        p4.setXfermode(SkAvoidXfermode::Create(SK_ColorWHITE,
                                               5,
                                               SkAvoidXfermode::kAvoidColor_Mode))->unref();

        canvas->drawRect(r, p4);
    }
Пример #2
0
    void onDraw(SkCanvas* canvas) override {
        canvas->drawBitmap(fBM, 0, 0);

        SkRect r = SkRect::MakeIWH(64, 64);

        // UL corner: replace white with black with a tight tolerance
        SkPaint p1;
        p1.setColor(SK_ColorBLACK);
        p1.setXfermode(SkAvoidXfermode::Create(SK_ColorWHITE,
                                               5,
                                               SkAvoidXfermode::kTargetColor_Mode))->unref();

        canvas->drawRect(r, p1);

        r.offsetTo(64, 0.0f);

        // UR corner: draw black everywhere except white with a tight tolerance
        SkPaint p2;
        p2.setColor(SK_ColorBLACK);
        p2.setXfermode(SkAvoidXfermode::Create(SK_ColorWHITE,
                                               250,
                                               SkAvoidXfermode::kAvoidColor_Mode))->unref();

        canvas->drawRect(r, p2);

        r.offsetTo(0.0f, 64);

        // LL corner: replace red with blue with a loose tolerance
        SkPaint p3;
        p3.setColor(SK_ColorBLUE);
        p3.setXfermode(SkAvoidXfermode::Create(SK_ColorRED,
                                               250,
                                               SkAvoidXfermode::kTargetColor_Mode))->unref();

        canvas->drawRect(r, p3);

        r.offsetTo(64, 64);

        // LR corner: draw black everywhere except red with a loose tolerance
        SkPaint p4;
        p4.setColor(SK_ColorBLACK);
        p4.setXfermode(SkAvoidXfermode::Create(SK_ColorRED,
                                               5,
                                               SkAvoidXfermode::kAvoidColor_Mode))->unref();

        canvas->drawRect(r, p4);
    }
Пример #3
0
    void onDraw(SkCanvas* canvas) override {
        canvas->drawBitmap(fBM, 0, 0);

        SkRect r = SkRect::MakeIWH(256, 256);

        // Negate the red channel of the dst (via the ancillary color) but leave
        // the green & blue channels alone
        SkPaint p1;
        p1.setColor(SK_ColorBLACK); // noop
        p1.setXfermode(SkPixelXorXfermode::Create(0x7FFF0000))->unref();

        canvas->drawRect(r, p1);

        r.offsetTo(256.0f, 0.0f);

        // Negate the dst color via the src color
        SkPaint p2;
        p2.setColor(SK_ColorWHITE);
        p2.setXfermode(SkPixelXorXfermode::Create(SK_ColorBLACK))->unref(); // noop

        canvas->drawRect(r, p2);

        r.offsetTo(0.0f, 256.0f);

        // Just return the original color
        SkPaint p3;
        p3.setColor(SK_ColorBLACK); // noop
        p3.setXfermode(SkPixelXorXfermode::Create(SK_ColorBLACK))->unref(); // noop

        canvas->drawRect(r, p3);

        r.offsetTo(256.0f, 256.0f);

        // Negate the red & green channels (via the ancillary color) but leave
        // the blue channel alone
        SkPaint p4;
        p4.setColor(SK_ColorBLACK); // noop
        p4.setXfermode(SkPixelXorXfermode::Create(SK_ColorYELLOW))->unref();

        canvas->drawRect(r, p4);
    }
Пример #4
0
GrTexture* GaussianBlur(GrContext* context,
                        GrTexture* srcTexture,
                        bool canClobberSrc,
                        const SkRect& dstBounds,
                        const SkRect* srcBounds,
                        float sigmaX,
                        float sigmaY,
                        GrTextureProvider::SizeConstraint constraint) {
    SkASSERT(context);
    SkIRect clearRect;
    int scaleFactorX, radiusX;
    int scaleFactorY, radiusY;
    int maxTextureSize = context->caps()->maxTextureSize();
    sigmaX = adjust_sigma(sigmaX, maxTextureSize, &scaleFactorX, &radiusX);
    sigmaY = adjust_sigma(sigmaY, maxTextureSize, &scaleFactorY, &radiusY);

    SkPoint srcOffset = SkPoint::Make(-dstBounds.x(), -dstBounds.y());
    SkRect localDstBounds = SkRect::MakeWH(dstBounds.width(), dstBounds.height());
    SkRect localSrcBounds;
    SkRect srcRect;
    if (srcBounds) {
        srcRect = localSrcBounds = *srcBounds;
        srcRect.offset(srcOffset);
        srcBounds = &localSrcBounds;
    } else {
        srcRect = localDstBounds;
    }

    scale_rect(&srcRect, 1.0f / scaleFactorX, 1.0f / scaleFactorY);
    srcRect.roundOut(&srcRect);
    scale_rect(&srcRect, static_cast<float>(scaleFactorX),
                         static_cast<float>(scaleFactorY));

    // setup new clip
    GrClip clip(localDstBounds);

    SkASSERT(kBGRA_8888_GrPixelConfig == srcTexture->config() ||
             kRGBA_8888_GrPixelConfig == srcTexture->config() ||
             kAlpha_8_GrPixelConfig == srcTexture->config());

    GrSurfaceDesc desc;
    desc.fFlags = kRenderTarget_GrSurfaceFlag;
    desc.fWidth = SkScalarFloorToInt(dstBounds.width());
    desc.fHeight = SkScalarFloorToInt(dstBounds.height());
    desc.fConfig = srcTexture->config();

    GrTexture* dstTexture;
    GrTexture* tempTexture;
    SkAutoTUnref<GrTexture> temp1, temp2;

    temp1.reset(context->textureProvider()->createTexture(desc, constraint));
    dstTexture = temp1.get();
    if (canClobberSrc) {
        tempTexture = srcTexture;
    } else {
        temp2.reset(context->textureProvider()->createTexture(desc, constraint));
        tempTexture = temp2.get();
    }

    if (nullptr == dstTexture || nullptr == tempTexture) {
        return nullptr;
    }

    SkAutoTUnref<GrDrawContext> srcDrawContext;

    for (int i = 1; i < scaleFactorX || i < scaleFactorY; i *= 2) {
        GrPaint paint;
        SkMatrix matrix;
        matrix.setIDiv(srcTexture->width(), srcTexture->height());
        SkRect dstRect(srcRect);
        if (srcBounds && i == 1) {
            SkRect domain;
            matrix.mapRect(&domain, *srcBounds);
            domain.inset((i < scaleFactorX) ? SK_ScalarHalf / srcTexture->width() : 0.0f,
                         (i < scaleFactorY) ? SK_ScalarHalf / srcTexture->height() : 0.0f);
            SkAutoTUnref<const GrFragmentProcessor> fp(GrTextureDomainEffect::Create(
                srcTexture,
                matrix,
                domain,
                GrTextureDomain::kDecal_Mode,
                GrTextureParams::kBilerp_FilterMode));
            paint.addColorFragmentProcessor(fp);
            srcRect.offset(-srcOffset);
            srcOffset.set(0, 0);
        } else {
            GrTextureParams params(SkShader::kClamp_TileMode, GrTextureParams::kBilerp_FilterMode);
            paint.addColorTextureProcessor(srcTexture, matrix, params);
        }
        paint.setPorterDuffXPFactory(SkXfermode::kSrc_Mode);
        scale_rect(&dstRect, i < scaleFactorX ? 0.5f : 1.0f,
                             i < scaleFactorY ? 0.5f : 1.0f);

        SkAutoTUnref<GrDrawContext> dstDrawContext(
                                             context->drawContext(dstTexture->asRenderTarget()));
        if (!dstDrawContext) {
            return nullptr;
        }
        dstDrawContext->fillRectToRect(clip, paint, SkMatrix::I(), dstRect, srcRect);

        srcDrawContext.swap(dstDrawContext);
        srcRect = dstRect;
        srcTexture = dstTexture;
        SkTSwap(dstTexture, tempTexture);
        localSrcBounds = srcRect;
    }

    // For really small blurs (certainly no wider than 5x5 on desktop gpus) it is faster to just
    // launch a single non separable kernel vs two launches
    srcRect = localDstBounds;
    if (sigmaX > 0.0f && sigmaY > 0.0f &&
            (2 * radiusX + 1) * (2 * radiusY + 1) <= MAX_KERNEL_SIZE) {
        // We shouldn't be scaling because this is a small size blur
        SkASSERT((1 == scaleFactorX) && (1 == scaleFactorY));

        SkAutoTUnref<GrDrawContext> dstDrawContext(
                                             context->drawContext(dstTexture->asRenderTarget()));
        if (!dstDrawContext) {
            return nullptr;
        }
        convolve_gaussian_2d(dstDrawContext, clip, srcRect, srcOffset,
                             srcTexture, radiusX, radiusY, sigmaX, sigmaY, srcBounds);

        srcDrawContext.swap(dstDrawContext);
        srcRect.offsetTo(0, 0);
        srcTexture = dstTexture;
        SkTSwap(dstTexture, tempTexture);

    } else {
        scale_rect(&srcRect, 1.0f / scaleFactorX, 1.0f / scaleFactorY);
        srcRect.roundOut(&srcRect);
        const SkIRect srcIRect = srcRect.roundOut();
        if (sigmaX > 0.0f) {
            if (scaleFactorX > 1) {
                // TODO: if we pass in the source draw context we don't need this here
                if (!srcDrawContext) {
                    srcDrawContext.reset(context->drawContext(srcTexture->asRenderTarget()));
                    if (!srcDrawContext) {
                        return nullptr;
                    }        
                }

                // Clear out a radius to the right of the srcRect to prevent the
                // X convolution from reading garbage.
                clearRect = SkIRect::MakeXYWH(srcIRect.fRight, srcIRect.fTop,
                                              radiusX, srcIRect.height());
                srcDrawContext->clear(&clearRect, 0x0, false);
            }

            SkAutoTUnref<GrDrawContext> dstDrawContext(
                                             context->drawContext(dstTexture->asRenderTarget()));
            if (!dstDrawContext) {
                return nullptr;
            }
            convolve_gaussian(dstDrawContext, clip, srcRect,
                              srcTexture, Gr1DKernelEffect::kX_Direction, radiusX, sigmaX,
                              srcBounds, srcOffset);
            srcDrawContext.swap(dstDrawContext);
            srcTexture = dstTexture;
            srcRect.offsetTo(0, 0);
            SkTSwap(dstTexture, tempTexture);
            localSrcBounds = srcRect;
            srcOffset.set(0, 0);
        }

        if (sigmaY > 0.0f) {
            if (scaleFactorY > 1 || sigmaX > 0.0f) {
                // TODO: if we pass in the source draw context we don't need this here
                if (!srcDrawContext) {
                    srcDrawContext.reset(context->drawContext(srcTexture->asRenderTarget()));
                    if (!srcDrawContext) {
                        return nullptr;
                    }        
                }

                // Clear out a radius below the srcRect to prevent the Y
                // convolution from reading garbage.
                clearRect = SkIRect::MakeXYWH(srcIRect.fLeft, srcIRect.fBottom,
                                              srcIRect.width(), radiusY);
                srcDrawContext->clear(&clearRect, 0x0, false);
            }

            SkAutoTUnref<GrDrawContext> dstDrawContext(
                                               context->drawContext(dstTexture->asRenderTarget()));
            if (!dstDrawContext) {
                return nullptr;
            }
            convolve_gaussian(dstDrawContext, clip, srcRect,
                              srcTexture, Gr1DKernelEffect::kY_Direction, radiusY, sigmaY,
                              srcBounds, srcOffset);

            srcDrawContext.swap(dstDrawContext);
            srcTexture = dstTexture;
            srcRect.offsetTo(0, 0);
            SkTSwap(dstTexture, tempTexture);
        }
    }
    const SkIRect srcIRect = srcRect.roundOut();

    if (scaleFactorX > 1 || scaleFactorY > 1) {
        SkASSERT(srcDrawContext);

        // Clear one pixel to the right and below, to accommodate bilinear
        // upsampling.
        clearRect = SkIRect::MakeXYWH(srcIRect.fLeft, srcIRect.fBottom,
                                      srcIRect.width() + 1, 1);
        srcDrawContext->clear(&clearRect, 0x0, false);
        clearRect = SkIRect::MakeXYWH(srcIRect.fRight, srcIRect.fTop,
                                      1, srcIRect.height());
        srcDrawContext->clear(&clearRect, 0x0, false);
        SkMatrix matrix;
        matrix.setIDiv(srcTexture->width(), srcTexture->height());

        GrPaint paint;
        // FIXME:  this should be mitchell, not bilinear.
        GrTextureParams params(SkShader::kClamp_TileMode, GrTextureParams::kBilerp_FilterMode);
        paint.addColorTextureProcessor(srcTexture, matrix, params);
        paint.setPorterDuffXPFactory(SkXfermode::kSrc_Mode);

        SkRect dstRect(srcRect);
        scale_rect(&dstRect, (float) scaleFactorX, (float) scaleFactorY);

        SkAutoTUnref<GrDrawContext> dstDrawContext(
                                context->drawContext(dstTexture->asRenderTarget()));
        if (!dstDrawContext) {
            return nullptr;
        }
        dstDrawContext->fillRectToRect(clip, paint, SkMatrix::I(), dstRect, srcRect);

        srcDrawContext.swap(dstDrawContext);
        srcRect = dstRect;
        srcTexture = dstTexture;
        SkTSwap(dstTexture, tempTexture);
    }

    return SkRef(srcTexture);
}