SkARGB4444_Blitter::SkARGB4444_Blitter(const SkBitmap& device,
                                   const SkPaint& paint) : INHERITED(device) {
    // cache premultiplied versions in 4444
    SkPMColor c = SkPreMultiplyColor(paint.getColor());
    fPMColor16 = SkPixel32ToPixel4444(c);
    if (paint.isDither()) {
        fPMColor16Other = SkDitherPixel32To4444(c);
    } else {
        fPMColor16Other = fPMColor16;
    }

    // cache raw versions in 4444
    fRawColor16 = SkPackARGB4444(0xFF >> 4, SkColorGetR(c) >> 4,
                                 SkColorGetG(c) >> 4, SkColorGetB(c) >> 4);
    if (paint.isDither()) {
        fRawColor16Other = SkDitherARGB32To4444(0xFF, SkColorGetR(c),
                                                SkColorGetG(c), SkColorGetB(c));
    } else {
        fRawColor16Other = fRawColor16;
    }

    fScale16 = SkAlpha15To16(SkGetPackedA4444(fPMColor16Other));
    if (16 == fScale16) {
        // force the original to also be opaque
        fPMColor16 |= (0xF << SK_A4444_SHIFT);
    }
}
Example #2
0
SkARGB4444_Blitter::SkARGB4444_Blitter(const SkBitmap& device, const SkPaint& paint)
    : INHERITED(device)
{
    // cache premultiplied versions in 4444
    SkPMColor c = SkPreMultiplyColor(paint.getColor());
    fPMColor16 = SkPixel32ToPixel4444(c);
    if (paint.isDither()) {
        fPMColor16Other = SkDitherPixel32To4444(c);
    } else {
        fPMColor16Other = fPMColor16;
    }

    // cache raw versions in 4444
    fRawColor16 = SkPackARGB4444(0xFF >> 4, SkColorGetR(c) >> 4,
                                 SkColorGetG(c) >> 4, SkColorGetB(c) >> 4);
    if (paint.isDither()) {
        fRawColor16Other = SkDitherARGB32To4444(0xFF, SkColorGetR(c),
                                                SkColorGetG(c), SkColorGetB(c));
    } else {
        fRawColor16Other = fRawColor16;
    }
    
#if 0 /// don't think this assertion is true, but need it be?

    // our dithered color will be the same or more opaque than the original
    // so use dithered to compute our scale
    SkASSERT(SkGetPackedA4444(fPMColor16Other) >= SkGetPackedA4444(fPMColor16));
#endif

    fScale16 = SkAlpha15To16(SkGetPackedA4444(fPMColor16Other));
    if (16 == fScale16) {
        // force the original to also be opaque
        fPMColor16 |= (0xF << SK_A4444_SHIFT);
    }
}
Example #3
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);
    }
}
Example #4
0
        virtual void onDrawContent(SkCanvas* canvas)
            {
            canvas->translate(SkIntToScalar(10), SkIntToScalar(50));

            const SkScalar W = SkIntToScalar(fBitmaps[0].width() + 1);
            const SkScalar H = SkIntToScalar(fBitmaps[0].height() + 1);
            SkPaint paint;

            const SkScalar scale = SkFloatToScalar(0.897917f);
            canvas->scale(SK_Scalar1, scale);

            for (int k = 0; k < 2; k++)
                {
                paint.setFilterBitmap(k == 1);
                for (int j = 0; j < 2; j++)
                    {
                    paint.setDither(j == 1);
                    for (int i = 0; i < fBitmapCount; i++)
                        {
                        SkScalar x = (k * fBitmapCount + j) * W;
                        SkScalar y = i * H;
                        x = SkIntToScalar(SkScalarRound(x));
                        y = SkIntToScalar(SkScalarRound(y));
                        canvas->drawBitmap(fBitmaps[i], x, y, &paint);
                        if (i == 0)
                            {
                            SkPaint p;
                            p.setAntiAlias(true);
                            p.setTextAlign(SkPaint::kCenter_Align);
                            p.setTextSize(SkIntToScalar(18));
                            SkString s("dither=");
                            s.appendS32(paint.isDither());
                            s.append(" filter=");
                            s.appendS32(paint.isFilterBitmap());
                            canvas->drawText(s.c_str(), s.size(), x + W/2,
                                             y - p.getTextSize(), p);
                            }
                        if (k+j == 2)
                            {
                            SkPaint p;
                            p.setAntiAlias(true);
                            p.setTextSize(SkIntToScalar(18));
                            SkString s;
                            s.append(" depth=");
                            s.appendS32(fBitmaps[i].config() == SkBitmap::kRGB_565_Config ? 16 : 32);
                            canvas->drawText(s.c_str(), s.size(), x + W + SkIntToScalar(4),
                                             y + H/2, p);
                            }
                        }
                    }
                }
            }
bool SkPaintPriv::ShouldDither(const SkPaint& p, SkColorType dstCT) {
    // The paint dither flag can veto.
    if (!p.isDither()) {
        return false;
    }

    // We always dither 565 or 4444 when requested.
    if (dstCT == kRGB_565_SkColorType || dstCT == kARGB_4444_SkColorType) {
        return true;
    }

    // Otherwise, dither is only needed for non-const paints.
    return p.getImageFilter() || p.getMaskFilter()
        || !p.getShader() || !as_SB(p.getShader())->isConstant();
}
Example #6
0
bool SkLinearGradient::setContext(const SkBitmap& device, const SkPaint& paint,
                                 const SkMatrix& matrix) {
    if (!this->INHERITED::setContext(device, paint, matrix)) {
        return false;
    }

    unsigned mask = SkMatrix::kTranslate_Mask | SkMatrix::kScale_Mask;
    if ((fDstToIndex.getType() & ~mask) == 0) {
        fFlags |= SkShader::kConstInY32_Flag;
        if ((fFlags & SkShader::kHasSpan16_Flag) && !paint.isDither()) {
            // only claim this if we do have a 16bit mode (i.e. none of our
            // colors have alpha), and if we are not dithering (which obviously
            // is not const in Y).
            fFlags |= SkShader::kConstInY16_Flag;
        }
    }
    return true;
}
String LoggingCanvas::stringForSkPaintFlags(const SkPaint& paint)
{
    if (!paint.getFlags())
        return "none";
    String flagsString = "";
    appendFlagToString(&flagsString, paint.isAntiAlias(), "AntiAlias");
    appendFlagToString(&flagsString, paint.isDither(), "Dither");
    appendFlagToString(&flagsString, paint.isUnderlineText(), "UnderlinText");
    appendFlagToString(&flagsString, paint.isStrikeThruText(), "StrikeThruText");
    appendFlagToString(&flagsString, paint.isFakeBoldText(), "FakeBoldText");
    appendFlagToString(&flagsString, paint.isLinearText(), "LinearText");
    appendFlagToString(&flagsString, paint.isSubpixelText(), "SubpixelText");
    appendFlagToString(&flagsString, paint.isDevKernText(), "DevKernText");
    appendFlagToString(&flagsString, paint.isLCDRenderText(), "LCDRenderText");
    appendFlagToString(&flagsString, paint.isEmbeddedBitmapText(), "EmbeddedBitmapText");
    appendFlagToString(&flagsString, paint.isAutohinted(), "Autohinted");
    appendFlagToString(&flagsString, paint.isVerticalText(), "VerticalText");
    appendFlagToString(&flagsString, paint.getFlags() & SkPaint::kGenA8FromLCD_Flag, "GenA8FromLCD");
    return flagsString;
}
bool SkColorShader::setContext(const SkBitmap& device, const SkPaint& paint,
                               const SkMatrix& matrix) {
    if (!this->INHERITED::setContext(device, paint, matrix)) {
        return false;
    }

    SkColor c;
    unsigned a;
    
    if (fInheritColor) {
        c = paint.getColor();
        a = SkColorGetA(c);
    } else {
        c = fColor;
        a = SkAlphaMul(SkColorGetA(c), SkAlpha255To256(paint.getAlpha()));
    }

    unsigned r = SkColorGetR(c);
    unsigned g = SkColorGetG(c);
    unsigned b = SkColorGetB(c);

    // we want this before we apply any alpha
    fColor16 = SkPack888ToRGB16(r, g, b);

    if (a != 255) {
        r = SkMulDiv255Round(r, a);
        g = SkMulDiv255Round(g, a);
        b = SkMulDiv255Round(b, a);
    }
    fPMColor = SkPackARGB32(a, r, g, b);

    fFlags = kConstInY32_Flag;
    if (255 == a) {
        fFlags |= kOpaqueAlpha_Flag;
        if (paint.isDither() == false) {
            fFlags |= kHasSpan16_Flag;
        }
    }

    return true;
}
Example #9
0
bool SkBitmapProcShader::setContext(const SkBitmap& device,
                                    const SkPaint& paint,
                                    const SkMatrix& matrix) {
    if (!fRawBitmap.getTexture() && !valid_for_drawing(fRawBitmap)) {
        return false;
    }

    // do this first, so we have a correct inverse matrix
    if (!this->INHERITED::setContext(device, paint, matrix)) {
        return false;
    }

    fState.fOrigBitmap = fRawBitmap;
    if (!fState.chooseProcs(this->getTotalInverse(), paint)) {
        this->INHERITED::endContext();
        return false;
    }

    const SkBitmap& bitmap = *fState.fBitmap;
    bool bitmapIsOpaque = bitmap.isOpaque();

    // update fFlags
    uint32_t flags = 0;
    if (bitmapIsOpaque && (255 == this->getPaintAlpha())) {
        flags |= kOpaqueAlpha_Flag;
    }

    switch (bitmap.config()) {
        case SkBitmap::kRGB_565_Config:
            flags |= (kHasSpan16_Flag | kIntrinsicly16_Flag);
            break;
        case SkBitmap::kIndex8_Config:
        case SkBitmap::kARGB_8888_Config:
            if (bitmapIsOpaque) {
                flags |= kHasSpan16_Flag;
            }
            break;
        case SkBitmap::kA8_Config:
            break;  // never set kHasSpan16_Flag
        default:
            break;
    }

    if (paint.isDither() && bitmap.config() != SkBitmap::kRGB_565_Config) {
        // gradients can auto-dither in their 16bit sampler, but we don't so
        // we clear the flag here.
        flags &= ~kHasSpan16_Flag;
    }

    // if we're only 1-pixel high, and we don't rotate, then we can claim this
    if (1 == bitmap.height() &&
            only_scale_and_translate(this->getTotalInverse())) {
        flags |= kConstInY32_Flag;
        if (flags & kHasSpan16_Flag) {
            flags |= kConstInY16_Flag;
        }
    }

    fFlags = flags;
    return true;
}
Example #10
0
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;
            }
        }
    }

    SkXfermode* mode = skPaint.getXfermode();
    GrXPFactory* xpFactory = nullptr;
    if (!SkXfermode::AsXPFactory(mode, &xpFactory)) {
        // Fall back to src-over
        // return false here?
        xpFactory = GrPorterDuffXPFactory::Create(SkXfermode::kSrcOver_Mode);
    }
    SkASSERT(xpFactory);
    grPaint->setXPFactory(xpFactory)->unref();

#ifndef SK_IGNORE_GPU_DITHER
    if (skPaint.isDither() && grPaint->numColorFragmentProcessors() > 0) {
        grPaint->addColorFragmentProcessor(GrDitherEffect::Create())->unref();
    }
#endif
    return true;
}
Example #11
0
bool SkPaint2GrPaintNoShader(GrContext* context, GrRenderTarget* rt, const SkPaint& skPaint,
                             GrColor paintColor, bool constantColor, GrPaint* grPaint) {

    grPaint->setDither(skPaint.isDither());
    grPaint->setAntiAlias(skPaint.isAntiAlias());

    SkXfermode* mode = skPaint.getXfermode();
    GrXPFactory* xpFactory = NULL;
    if (!SkXfermode::AsXPFactory(mode, &xpFactory)) {
        // Fall back to src-over
        // return false here?
        xpFactory = GrPorterDuffXPFactory::Create(SkXfermode::kSrcOver_Mode);
    }
    SkASSERT(xpFactory);
    grPaint->setXPFactory(xpFactory)->unref();

    //set the color of the paint to the one of the parameter
    grPaint->setColor(paintColor);

    SkColorFilter* colorFilter = skPaint.getColorFilter();
    if (colorFilter) {
        // if the source color is a constant then apply the filter here once rather than per pixel
        // in a shader.
        if (constantColor) {
            SkColor filtered = colorFilter->filterColor(skPaint.getColor());
            grPaint->setColor(SkColor2GrColor(filtered));
        } else {
            SkTDArray<GrFragmentProcessor*> array;
            // return false if failed?
            if (colorFilter->asFragmentProcessors(context, grPaint->getProcessorDataManager(),
                                                  &array)) {
                for (int i = 0; i < array.count(); ++i) {
                    grPaint->addColorProcessor(array[i]);
                    array[i]->unref();
                }
            }
        }
    }

#ifndef SK_IGNORE_GPU_DITHER
    // If the dither flag is set, then we need to see if the underlying context
    // supports it. If not, then install a dither effect.
    if (skPaint.isDither() && grPaint->numColorStages() > 0) {
        // What are we rendering into?
        SkASSERT(rt);

        // Suspect the dithering flag has no effect on these configs, otherwise
        // fall back on setting the appropriate state.
        if (GrPixelConfigIs8888(rt->config()) ||
            GrPixelConfigIs8888(rt->config())) {
            // The dither flag is set and the target is likely
            // not going to be dithered by the GPU.
            SkAutoTUnref<GrFragmentProcessor> fp(GrDitherEffect::Create());
            if (fp.get()) {
                grPaint->addColorProcessor(fp);
                grPaint->setDither(false);
            }
        }
    }
#endif
    return true;
}