예제 #1
0
void SkGL::SetPaint(const SkPaint& paint, bool isPremul, bool justAlpha) {
    if (justAlpha) {
        SkGL::SetAlpha(paint.getAlpha());
    } else {
        SkGL::SetColor(paint.getColor());
    }

    GLenum sm = GL_ONE;
    GLenum dm = GL_ONE_MINUS_SRC_ALPHA;

    SkXfermode* mode = paint.getXfermode();
    SkXfermode::Coeff sc, dc;
    if (mode && mode->asCoeff(&sc, &dc)) {
        sm = gXfermodeCoeff2Blend[sc];
        dm = gXfermodeCoeff2Blend[dc];
    }

    // hack for text, which is not-premul (afaik)
    if (!isPremul) {
        if (GL_ONE == sm) {
            sm = GL_SRC_ALPHA;
        }
    }

    glEnable(GL_BLEND);
    glBlendFunc(sm, dm);

    if (paint.isDither()) {
        glEnable(GL_DITHER);
    } else {
        glDisable(GL_DITHER);
    }
}
    virtual void blitRect(int x, int y, int width, int height) {
        SkASSERT(width > 0 && height > 0);
        SK_RESTRICT SkPMColor* dst = fDevice->getAddr32(x, y);
        const SK_RESTRICT SkPMColor16* src = fSource->getAddr16(x - fLeft,
                                                                y - fTop);
        unsigned dstRB = fDevice->rowBytes();
        unsigned srcRB = fSource->rowBytes();
        SK_RESTRICT SkPMColor* buffer = fBuffer;
        SkColorFilter* colorFilter = fColorFilter;
        SkXfermode* xfermode = fXfermode;

        do {
            fillbuffer(buffer, src, width);

            if (NULL != colorFilter) {
                colorFilter->filterSpan(buffer, width, buffer);
            }
            if (NULL != xfermode) {
                xfermode->xfer32(dst, buffer, width, NULL);
            } else {
                fProc32(dst, buffer, width, fAlpha);
            }

            dst = (SK_RESTRICT SkPMColor*)((char*)dst + dstRB);
            src = (const SK_RESTRICT SkPMColor16*)((const char*)src + srcRB);
        } while (--height != 0);
    }
예제 #3
0
// Returns true if the xfermode will keep the dst opaque, assuming the dst is already opaque.
static inline bool xfermodePreservesOpaque(const SkPaint& paint, bool srcIsOpaque)
{
    SkXfermode* xfermode = paint.getXfermode();
    if (!xfermode)
        return true; // default to kSrcOver_Mode
    SkXfermode::Mode mode;
    if (!xfermode->asMode(&mode))
        return false;

    switch (mode) {
    case SkXfermode::kDst_Mode: // dest
    case SkXfermode::kSrcOver_Mode: // source + dest - source*dest
    case SkXfermode::kDstOver_Mode: // source + dest - source*dest
    case SkXfermode::kSrcATop_Mode: // dest
    case SkXfermode::kPlus_Mode: // source+dest
    default: // the rest are all source + dest - source*dest
        return true;
    case SkXfermode::kClear_Mode: // 0
    case SkXfermode::kSrcOut_Mode: // source * (1-dest)
    case SkXfermode::kDstOut_Mode: // dest * (1-source)
    case SkXfermode::kXor_Mode: // source + dest - 2*(source*dest)
        return false;
    case SkXfermode::kSrc_Mode: // source
    case SkXfermode::kSrcIn_Mode: // source * dest
    case SkXfermode::kDstIn_Mode: // dest * source
    case SkXfermode::kDstATop_Mode: // source
        return srcIsOpaque;
    }
}
예제 #4
0
	ShaderView()
    {
        SkImageDecoder::DecodeFile("/cover.png", &fBitmap);

        SkPoint pts[2];
        SkColor colors[2];
        
        pts[0].set(0, 0);
        pts[1].set(SkIntToScalar(100), 0);
        colors[0] = SK_ColorRED;
        colors[1] = SK_ColorBLUE;
        SkShader* shaderA = SkGradientShader::CreateLinear(pts, colors, NULL, 2, SkShader::kClamp_TileMode);
        
        pts[0].set(0, 0);
        pts[1].set(0, SkIntToScalar(100));
        colors[0] = SK_ColorBLACK;
        colors[1] = SkColorSetARGB(0x80, 0, 0, 0);
        SkShader* shaderB = SkGradientShader::CreateLinear(pts, colors, NULL, 2, SkShader::kClamp_TileMode);
        
        SkXfermode* mode = SkPorterDuff::CreateXfermode(SkPorterDuff::kDstIn_Mode);

        fShader = new SkComposeShader(shaderA, shaderB, mode);
        shaderA->unref();
        shaderB->unref();
        mode->unref();
    }
예제 #5
0
void SkComposeShader::ComposeShaderContext::shadeSpan(int x, int y, SkPMColor result[], int count) {
    SkShader::Context* shaderContextA = fShaderContextA;
    SkShader::Context* shaderContextB = fShaderContextB;
    SkBlendMode        mode = static_cast<const SkComposeShader&>(fShader).fMode;
    unsigned           scale = SkAlpha255To256(this->getPaintAlpha());

    SkPMColor   tmp[TMP_COLOR_COUNT];

    SkXfermode* xfer = SkXfermode::Peek(mode);
    if (nullptr == xfer) {   // implied SRC_OVER
        // TODO: when we have a good test-case, should use SkBlitRow::Proc32
        // for these loops
        do {
            int n = count;
            if (n > TMP_COLOR_COUNT) {
                n = TMP_COLOR_COUNT;
            }

            shaderContextA->shadeSpan(x, y, result, n);
            shaderContextB->shadeSpan(x, y, tmp, n);

            if (256 == scale) {
                for (int i = 0; i < n; i++) {
                    result[i] = SkPMSrcOver(tmp[i], result[i]);
                }
            } else {
                for (int i = 0; i < n; i++) {
                    result[i] = SkAlphaMulQ(SkPMSrcOver(tmp[i], result[i]),
                                            scale);
                }
            }

            result += n;
            x += n;
            count -= n;
        } while (count > 0);
    } else {    // use mode for the composition
        do {
            int n = count;
            if (n > TMP_COLOR_COUNT) {
                n = TMP_COLOR_COUNT;
            }

            shaderContextA->shadeSpan(x, y, result, n);
            shaderContextB->shadeSpan(x, y, tmp, n);
            xfer->xfer32(result, tmp, n, nullptr);

            if (256 != scale) {
                for (int i = 0; i < n; i++) {
                    result[i] = SkAlphaMulQ(result[i], scale);
                }
            }

            result += n;
            x += n;
            count -= n;
        } while (count > 0);
    }
}
SkXfermode::Mode CanvasRenderingContext2DState::globalComposite() const
{
    SkXfermode* xferMode = m_strokePaint.getXfermode();
    SkXfermode::Mode mode;
    if (!xferMode || !xferMode->asMode(&mode))
        return SkXfermode::kSrcOver_Mode;
    return mode;
}
예제 #7
0
void SkComposeShader::shadeSpan(int x, int y, SkPMColor result[], int count) {
    SkShader*   shaderA = fShaderA;
    SkShader*   shaderB = fShaderB;
    SkXfermode* mode = fMode;
    unsigned    scale = SkAlpha255To256(this->getPaintAlpha());

    SkPMColor   tmp[TMP_COLOR_COUNT];

    if (NULL == mode) {   // implied SRC_OVER
        // TODO: when we have a good test-case, should use SkBlitRow::Proc32
        // for these loops
        do {
            int n = count;
            if (n > TMP_COLOR_COUNT) {
                n = TMP_COLOR_COUNT;
            }

            shaderA->shadeSpan(x, y, result, n);
            shaderB->shadeSpan(x, y, tmp, n);

            if (256 == scale) {
                for (int i = 0; i < n; i++) {
                    result[i] = SkPMSrcOver(tmp[i], result[i]);
                }
            } else {
                for (int i = 0; i < n; i++) {
                    result[i] = SkAlphaMulQ(SkPMSrcOver(tmp[i], result[i]),
                                            scale);
                }
            }

            result += n;
            x += n;
            count -= n;
        } while (count > 0);
    } else {    // use mode for the composition
        do {
            int n = count;
            if (n > TMP_COLOR_COUNT) {
                n = TMP_COLOR_COUNT;
            }

            shaderA->shadeSpan(x, y, result, n);
            shaderB->shadeSpan(x, y, tmp, n);
            mode->xfer32(result, tmp, n, NULL);

            if (256 == scale) {
                for (int i = 0; i < n; i++) {
                    result[i] = SkAlphaMulQ(result[i], scale);
                }
            }

            result += n;
            x += n;
            count -= n;
        } while (count > 0);
    }
}
예제 #8
0
void SkARGB32_Shader_Blitter::blitMask(const SkMask& mask, const SkIRect& clip) {
    // we only handle kA8 with an xfermode
    if (fXfermode && (SkMask::kA8_Format != mask.fFormat)) {
        this->INHERITED::blitMask(mask, clip);
        return;
    }

    SkASSERT(mask.fBounds.contains(clip));

    SkBlitMask::RowProc proc = NULL;
    if (!fXfermode) {
        unsigned flags = 0;
        if (fShader->getFlags() & SkShader::kOpaqueAlpha_Flag) {
            flags |= SkBlitMask::kSrcIsOpaque_RowFlag;
        }
        proc = SkBlitMask::RowFactory(SkBitmap::kARGB_8888_Config, mask.fFormat,
                                      (SkBlitMask::RowFlags)flags);
        if (NULL == proc) {
            this->INHERITED::blitMask(mask, clip);
            return;
        }
    }

    const int x = clip.fLeft;
    const int width = clip.width();
    int y = clip.fTop;
    int height = clip.height();

    char* dstRow = (char*)fDevice.getAddr32(x, y);
    const size_t dstRB = fDevice.rowBytes();
    const uint8_t* maskRow = (const uint8_t*)mask.getAddr(x, y);
    const size_t maskRB = mask.fRowBytes;

    SkShader* shader = fShader;
    SkPMColor* span = fBuffer;

    if (fXfermode) {
        SkASSERT(SkMask::kA8_Format == mask.fFormat);
        SkXfermode* xfer = fXfermode;
        do {
            shader->shadeSpan(x, y, span, width);
            xfer->xfer32((SkPMColor*)dstRow, span, width, maskRow);
            dstRow += dstRB;
            maskRow += maskRB;
            y += 1;
        } while (--height > 0);
    } else {
        do {
            shader->shadeSpan(x, y, span, width);
            proc(dstRow, maskRow, span, width);
            dstRow += dstRB;
            maskRow += maskRB;
            y += 1;
        } while (--height > 0);
    }
}
예제 #9
0
void mbe_copy_source(mbe_t *src, mbe_t *dst) {
    SkPaint *paint = dst->paint;
    const SkBitmap *bmap;
    SkXfermode *mode;

    /* _prepare_paint(dst, SkPaint::kFill_Style); */
    mode = SkXfermode::Create(SkXfermode::kSrc_Mode);
    paint->setXfermode(mode);
    bmap = &src->canvas->getDevice()->accessBitmap(false);

    dst->canvas->drawBitmap(*bmap, 0, 0, paint);

    paint->reset();
    mode->unref();
    /* _finish_paint(dst); */
}
예제 #10
0
파일: vertices.cpp 프로젝트: webbjiang/skia
    void onDraw(SkCanvas* canvas) override {
        // start with the center of a 3x3 grid
        static const uint16_t fan[] = {
            4,
            0, 1, 2, 5, 8, 7, 6, 3, 0
        };

        const struct {
            const SkColor*  fColors;
            const SkPoint*  fTexs;
        } rec[] = {
            { fColors,  NULL },
            { NULL,     fTexs },
            { fColors,  fTexs },
        };

        const SkXfermode::Mode modes[] = {
            SkXfermode::kSrc_Mode,
            SkXfermode::kDst_Mode,
            SkXfermode::kModulate_Mode,
        };

        SkPaint paint;
        paint.setShader(fShader);
        paint.setAlpha(fAlpha);

        canvas->translate(20, 20);
        for (size_t j = 0; j < SK_ARRAY_COUNT(modes); ++j) {
            SkXfermode* xfer = SkXfermode::Create(modes[j]);
            canvas->save();
            for (size_t i = 0; i < SK_ARRAY_COUNT(rec); ++i) {
                canvas->drawVertices(SkCanvas::kTriangleFan_VertexMode,
                                     SK_ARRAY_COUNT(fPts), fPts,
                                     rec[i].fTexs, rec[i].fColors,
                                     xfer, fan, SK_ARRAY_COUNT(fan), paint);
                canvas->translate(200, 0);
            }
            canvas->restore();
            canvas->translate(0, 200);
            xfer->unref();
        }
    }
예제 #11
0
// We're only interested in some fields of the SkPaint, so we have a custom
// operator== function.
bool SkPDFGraphicState::GSCanonicalEntry::operator==(
        const SkPDFGraphicState::GSCanonicalEntry& gs) const {
    const SkPaint* a = fPaint;
    const SkPaint* b = gs.fPaint;
    SkASSERT(a != NULL);
    SkASSERT(b != NULL);

    if (SkColorGetA(a->getColor()) != SkColorGetA(b->getColor()) ||
           a->getStrokeCap() != b->getStrokeCap() ||
           a->getStrokeJoin() != b->getStrokeJoin() ||
           a->getStrokeWidth() != b->getStrokeWidth() ||
           a->getStrokeMiter() != b->getStrokeMiter()) {
        return false;
    }

    SkXfermode::Mode aXfermodeName = SkXfermode::kSrcOver_Mode;
    SkXfermode* aXfermode = a->getXfermode();
    if (aXfermode) {
        aXfermode->asMode(&aXfermodeName);
    }
    if (aXfermodeName < 0 || aXfermodeName > SkXfermode::kLastMode ||
            blend_mode_from_xfermode(aXfermodeName) == NULL) {
        aXfermodeName = SkXfermode::kSrcOver_Mode;
    }
    const char* aXfermodeString = blend_mode_from_xfermode(aXfermodeName);
    SkASSERT(aXfermodeString != NULL);

    SkXfermode::Mode bXfermodeName = SkXfermode::kSrcOver_Mode;
    SkXfermode* bXfermode = b->getXfermode();
    if (bXfermode) {
        bXfermode->asMode(&bXfermodeName);
    }
    if (bXfermodeName < 0 || bXfermodeName > SkXfermode::kLastMode ||
            blend_mode_from_xfermode(bXfermodeName) == NULL) {
        bXfermodeName = SkXfermode::kSrcOver_Mode;
    }
    const char* bXfermodeString = blend_mode_from_xfermode(bXfermodeName);
    SkASSERT(bXfermodeString != NULL);

    return strcmp(aXfermodeString, bXfermodeString) == 0;
}
예제 #12
0
static void test_asMode(skiatest::Reporter* reporter) {
    for (int mode = 0; mode <= SkXfermode::kLastMode; mode++) {
        SkXfermode* xfer = SkXfermode::Create((SkXfermode::Mode) mode);

        SkXfermode::Mode reportedMode = ILLEGAL_MODE;
        REPORTER_ASSERT(reporter, reportedMode != mode);

        // test IsMode
        REPORTER_ASSERT(reporter, SkXfermode::AsMode(xfer, &reportedMode));
        REPORTER_ASSERT(reporter, reportedMode == mode);

        // repeat that test, but with asMode instead
        if (xfer) {
            reportedMode = (SkXfermode::Mode) -1;
            REPORTER_ASSERT(reporter, xfer->asMode(&reportedMode));
            REPORTER_ASSERT(reporter, reportedMode == mode);
            xfer->unref();
        } else {
            REPORTER_ASSERT(reporter, SkXfermode::kSrcOver_Mode == mode);
        }
    }

    SkXfermode* bogusXfer = new SkProcXfermode(bogusXfermodeProc);
    SkXfermode::Mode reportedMode = ILLEGAL_MODE;
    REPORTER_ASSERT(reporter, !bogusXfer->asMode(&reportedMode));
    REPORTER_ASSERT(reporter, reportedMode == ILLEGAL_MODE);
    REPORTER_ASSERT(reporter, !SkXfermode::AsMode(bogusXfer, &reportedMode));
    REPORTER_ASSERT(reporter, reportedMode == ILLEGAL_MODE);
    bogusXfer->unref();
}
예제 #13
0
    static bool PaintMayAffectTransparentBlack(const SkPaint* paint) {
        if (paint) {
            // FIXME: this is very conservative
            if (paint->getImageFilter() || paint->getColorFilter()) {
                return true;
            }

            // Unusual Xfermodes require us to process a saved layer
            // even with operations outisde the clip.
            // For example, DstIn is used by masking layers.
            // https://code.google.com/p/skia/issues/detail?id=1291
            // https://crbug.com/401593
            SkXfermode* xfermode = paint->getXfermode();
            SkXfermode::Mode mode;
            // SrcOver is ok, and is also the common case with a NULL xfermode.
            // So we should make that the fast path and bypass the mode extraction
            // and test.
            if (xfermode && xfermode->asMode(&mode)) {
                switch (mode) {
                    // For each of the following transfer modes, if the source
                    // alpha is zero (our transparent black), the resulting
                    // blended alpha is not necessarily equal to the original
                    // destination alpha.
                    case SkXfermode::kClear_Mode:
                    case SkXfermode::kSrc_Mode:
                    case SkXfermode::kSrcIn_Mode:
                    case SkXfermode::kDstIn_Mode:
                    case SkXfermode::kSrcOut_Mode:
                    case SkXfermode::kDstATop_Mode:
                    case SkXfermode::kModulate_Mode:
                        return true;
                        break;
                    default:
                        break;
                }
            }
        }
        return false;
    }
예제 #14
0
static SkShader* make_bitmapfade(const SkBitmap& bm)
{
    SkPoint pts[2];
    SkColor colors[2];

    pts[0].set(0, 0);
    pts[1].set(0, SkIntToScalar(bm.height()));
    colors[0] = SK_ColorBLACK;
    colors[1] = SkColorSetARGB(0, 0, 0, 0);
    SkShader* shaderA = SkGradientShader::CreateLinear(pts, colors, NULL, 2, SkShader::kClamp_TileMode);

    SkShader* shaderB = SkShader::CreateBitmapShader(bm,
                        SkShader::kClamp_TileMode, SkShader::kClamp_TileMode);

    SkXfermode* mode = SkPorterDuff::CreateXfermode(SkPorterDuff::kDstIn_Mode);

    SkShader* shader = new SkComposeShader(shaderB, shaderA, mode);
    shaderA->unref();
    shaderB->unref();
    mode->unref();
    
    return shader;
}
예제 #15
0
static void test_asMode(skiatest::Reporter* reporter) {
    for (int mode = 0; mode <= SkXfermode::kLastMode; mode++) {
        SkXfermode* xfer = SkXfermode::Create((SkXfermode::Mode) mode);
        SkXfermode::Mode reportedMode = (SkXfermode::Mode) -1;
        REPORTER_ASSERT(reporter,
                        xfer != NULL || mode == SkXfermode::kSrcOver_Mode);
        if (xfer) {
          REPORTER_ASSERT(reporter, xfer->asMode(&reportedMode));
          REPORTER_ASSERT(reporter, reportedMode == mode);
          xfer->unref();
        }
    }

    SkXfermode* bogusXfer = new SkProcXfermode(bogusXfermodeProc);
    SkXfermode::Mode reportedMode = (SkXfermode::Mode) -1;
    REPORTER_ASSERT(reporter, !bogusXfer->asMode(&reportedMode));
    REPORTER_ASSERT(reporter, reportedMode == -1);
    bogusXfer->unref();
}
예제 #16
0
파일: SkGr.cpp 프로젝트: jfzhang2/skia
static inline bool skpaint_to_grpaint_impl(GrContext* context,
                                           const SkPaint& skPaint,
                                           const SkMatrix& viewM,
                                           const GrFragmentProcessor** shaderProcessor,
                                           SkXfermode::Mode* primColorMode,
                                           bool primitiveIsSrc,
                                           GrPaint* grPaint) {
    grPaint->setAntiAlias(skPaint.isAntiAlias());

    // Setup the initial color considering the shader, the SkPaint color, and the presence or not
    // of per-vertex colors.
    SkAutoTUnref<const GrFragmentProcessor> aufp;
    const GrFragmentProcessor* shaderFP = nullptr;
    if (!primColorMode || blend_requires_shader(*primColorMode, primitiveIsSrc)) {
        if (shaderProcessor) {
            shaderFP = *shaderProcessor;
        } else if (const SkShader* shader = skPaint.getShader()) {
            aufp.reset(shader->asFragmentProcessor(context, viewM, nullptr,
                                                   skPaint.getFilterQuality()));
            shaderFP = aufp;
            if (!shaderFP) {
                return false;
            }
        }
    }

    // Set this in below cases if the output of the shader/paint-color/paint-alpha/primXfermode is
    // a known constant value. In that case we can simply apply a color filter during this
    // conversion without converting the color filter to a GrFragmentProcessor.
    bool applyColorFilterToPaintColor = false;
    if (shaderFP) {
        if (primColorMode) {
            // There is a blend between the primitive color and the shader color. The shader sees
            // the opaque paint color. The shader's output is blended using the provided mode by
            // the primitive color. The blended color is then modulated by the paint's alpha.

            // The geometry processor will insert the primitive color to start the color chain, so
            // the GrPaint color will be ignored.

            GrColor shaderInput = SkColorToOpaqueGrColor(skPaint.getColor());

            shaderFP = GrFragmentProcessor::OverrideInput(shaderFP, shaderInput);
            aufp.reset(shaderFP);

            if (primitiveIsSrc) {
                shaderFP = GrXfermodeFragmentProcessor::CreateFromDstProcessor(shaderFP,
                                                                               *primColorMode);
            } else {
                shaderFP = GrXfermodeFragmentProcessor::CreateFromSrcProcessor(shaderFP,
                                                                               *primColorMode);
            }
            aufp.reset(shaderFP);
            // The above may return null if compose results in a pass through of the prim color.
            if (shaderFP) {
                grPaint->addColorFragmentProcessor(shaderFP);
            }

            GrColor paintAlpha = SkColorAlphaToGrColor(skPaint.getColor());
            if (GrColor_WHITE != paintAlpha) {
                grPaint->addColorFragmentProcessor(GrConstColorProcessor::Create(
                    paintAlpha, GrConstColorProcessor::kModulateRGBA_InputMode))->unref();
            }
        } else {
            // The shader's FP sees the paint unpremul color
            grPaint->setColor(SkColorToUnpremulGrColor(skPaint.getColor()));
            grPaint->addColorFragmentProcessor(shaderFP);
        }
    } else {
        if (primColorMode) {
            // There is a blend between the primitive color and the paint color. The blend considers
            // the opaque paint color. The paint's alpha is applied to the post-blended color.
            SkAutoTUnref<const GrFragmentProcessor> processor(
                GrConstColorProcessor::Create(SkColorToOpaqueGrColor(skPaint.getColor()),
                                              GrConstColorProcessor::kIgnore_InputMode));
            if (primitiveIsSrc) {
                processor.reset(GrXfermodeFragmentProcessor::CreateFromDstProcessor(processor,
                                                                                *primColorMode));
            } else {
                processor.reset(GrXfermodeFragmentProcessor::CreateFromSrcProcessor(processor,
                                                                                *primColorMode));

            }
            if (processor) {
                grPaint->addColorFragmentProcessor(processor);
            }

            grPaint->setColor(SkColorToOpaqueGrColor(skPaint.getColor()));

            GrColor paintAlpha = SkColorAlphaToGrColor(skPaint.getColor());
            if (GrColor_WHITE != paintAlpha) {
                grPaint->addColorFragmentProcessor(GrConstColorProcessor::Create(
                    paintAlpha, GrConstColorProcessor::kModulateRGBA_InputMode))->unref();
            }
        } else {
            // No shader, no primitive color.
            grPaint->setColor(SkColorToPremulGrColor(skPaint.getColor()));
            applyColorFilterToPaintColor = true;
        }
    }

    SkColorFilter* colorFilter = skPaint.getColorFilter();
    if (colorFilter) {
        if (applyColorFilterToPaintColor) {
            grPaint->setColor(SkColorToPremulGrColor(colorFilter->filterColor(skPaint.getColor())));
        } else {
            SkAutoTUnref<const GrFragmentProcessor> cfFP(
                colorFilter->asFragmentProcessor(context));
            if (cfFP) {
                grPaint->addColorFragmentProcessor(cfFP);
            } else {
                return false;
            }
        }
    }

    // When the xfermode is null on the SkPaint (meaning kSrcOver) we need the XPFactory field on
    // the GrPaint to also be null (also kSrcOver).
    SkASSERT(!grPaint->getXPFactory());
    SkXfermode* xfermode = skPaint.getXfermode();
    if (xfermode) {
        // SafeUnref in case a new xfermode is added that returns null. 
        // In such cases we will fall back to kSrcOver_Mode.
        SkSafeUnref(grPaint->setXPFactory(xfermode->asXPFactory()));
    }

#ifndef SK_IGNORE_GPU_DITHER
    if (skPaint.isDither() && grPaint->numColorFragmentProcessors() > 0) {
        grPaint->addColorFragmentProcessor(GrDitherEffect::Create())->unref();
    }
#endif
    return true;
}
예제 #17
0
void SkComposeShader::ComposeShaderContext::shadeSpan(int x, int y, SkPMColor result[], int count) {
    SkShader::Context* shaderContextA = fShaderContextA;
    SkShader::Context* shaderContextB = fShaderContextB;
    SkXfermode*        mode = static_cast<const SkComposeShader&>(fShader).fMode;
    unsigned           scale = SkAlpha255To256(this->getPaintAlpha());

#ifdef SK_BUILD_FOR_ANDROID
    scale = 256;    // ugh -- maintain old bug/behavior for now
#endif

    SkPMColor   tmp[TMP_COLOR_COUNT];

    if (NULL == mode) {   // implied SRC_OVER
        // TODO: when we have a good test-case, should use SkBlitRow::Proc32
        // for these loops
        do {
            int n = count;
            if (n > TMP_COLOR_COUNT) {
                n = TMP_COLOR_COUNT;
            }

            shaderContextA->shadeSpan(x, y, result, n);
            shaderContextB->shadeSpan(x, y, tmp, n);

            if (256 == scale) {
                for (int i = 0; i < n; i++) {
                    result[i] = SkPMSrcOver(tmp[i], result[i]);
                }
            } else {
                for (int i = 0; i < n; i++) {
                    result[i] = SkAlphaMulQ(SkPMSrcOver(tmp[i], result[i]),
                                            scale);
                }
            }

            result += n;
            x += n;
            count -= n;
        } while (count > 0);
    } else {    // use mode for the composition
        do {
            int n = count;
            if (n > TMP_COLOR_COUNT) {
                n = TMP_COLOR_COUNT;
            }

            shaderContextA->shadeSpan(x, y, result, n);
            shaderContextB->shadeSpan(x, y, tmp, n);
            mode->xfer32(result, tmp, n, NULL);

            if (256 != scale) {
                for (int i = 0; i < n; i++) {
                    result[i] = SkAlphaMulQ(result[i], scale);
                }
            }

            result += n;
            x += n;
            count -= n;
        } while (count > 0);
    }
}
예제 #18
0
void SkARGB32_Shader_Blitter::blitAntiH(int x, int y, const SkAlpha antialias[],
                                        const int16_t runs[]) {
    SkPMColor*  span = fBuffer;
    uint32_t*   device = fDevice.getAddr32(x, y);
    SkShader*   shader = fShader;

    if (fXfermode) {
        for (;;) {
            SkXfermode* xfer = fXfermode;

            int count = *runs;
            if (count <= 0)
                break;
            int aa = *antialias;
            if (aa) {
                shader->shadeSpan(x, y, span, count);
                if (aa == 255) {
                    xfer->xfer32(device, span, count, NULL);
                } else {
                    // count is almost always 1
                    for (int i = count - 1; i >= 0; --i) {
                        xfer->xfer32(&device[i], &span[i], 1, antialias);
                    }
                }
            }
            device += count;
            runs += count;
            antialias += count;
            x += count;
        }
    } else if (fShader->getFlags() & SkShader::kOpaqueAlpha_Flag) {
        for (;;) {
            int count = *runs;
            if (count <= 0) {
                break;
            }
            int aa = *antialias;
            if (aa) {
                if (aa == 255) {
                    // cool, have the shader draw right into the device
                    shader->shadeSpan(x, y, device, count);
                } else {
                    shader->shadeSpan(x, y, span, count);
                    fProc32Blend(device, span, count, aa);
                }
            }
            device += count;
            runs += count;
            antialias += count;
            x += count;
        }
    } else {    // no xfermode but the shader not opaque
        for (;;) {
            int count = *runs;
            if (count <= 0) {
                break;
            }
            int aa = *antialias;
            if (aa) {
                fShader->shadeSpan(x, y, span, count);
                if (aa == 255) {
                    fProc32(device, span, count, 255);
                } else {
                    fProc32Blend(device, span, count, aa);
                }
            }
            device += count;
            runs += count;
            antialias += count;
            x += count;
        }
    }
}