static bool rgbPictureImport(const unsigned char* pixels, bool premultiplied, WebPImporter importRGBX, WebPImporter importRGB, WebPPicture* picture)
{
    if (premultiplied)
        return importRGBX(picture, pixels, picture->width * 4);

    // Write the RGB pixels to an rgb data buffer, alpha premultiplied, then import the rgb data.

    Vector<unsigned char> rgb;
    size_t pixelCount = picture->height * picture->width;
    rgb.reserveInitialCapacity(pixelCount * 3);

    for (unsigned char* data = rgb.data(); pixelCount-- > 0; pixels += 4) {
        unsigned char alpha = pixels[3];
        if (alpha != 255) {
            *data++ = SkMulDiv255Round(pixels[0], alpha);
            *data++ = SkMulDiv255Round(pixels[1], alpha);
            *data++ = SkMulDiv255Round(pixels[2], alpha);
        } else {
            *data++ = pixels[0];
            *data++ = pixels[1];
            *data++ = pixels[2];
        }
    }

    return importRGB(picture, rgb.data(), picture->width * 3);
}
Example #2
0
SkColorShader::ColorShaderContext::ColorShaderContext(const SkColorShader& shader,
                                                      const ContextRec& rec)
    : INHERITED(shader, rec)
{
    SkColor color = shader.fColor;
    unsigned a = SkAlphaMul(SkColorGetA(color), SkAlpha255To256(rec.fPaint->getAlpha()));

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

    // 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 (rec.fPaint->isDither() == false) {
            fFlags |= kHasSpan16_Flag;
        }
    }
}
Example #3
0
SkColorShader::ColorShaderContext::ColorShaderContext(const SkColorShader& shader,
                                                      const ContextRec& rec)
    : INHERITED(shader, rec)
{
    SkColor color = shader.fColor;
    unsigned a = SkAlphaMul(SkColorGetA(color), SkAlpha255To256(rec.fPaint->getAlpha()));

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

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

    SkColor4f c4 = SkColor4f::FromColor(shader.fColor);
    c4.fA *= rec.fPaint->getAlpha() / 255.0f;
    fPM4f = c4.premul();

    fFlags = kConstInY32_Flag;
    if (255 == a) {
        fFlags |= kOpaqueAlpha_Flag;
    }
}
Example #4
0
/*
 * Convert a row of CMYK samples to RGBX in place.
 * Note that this method moves the row pointer.
 * @param width the number of pixels in the row that is being converted
 *              CMYK is stored as four bytes per pixel
 */
static void convert_CMYK_to_RGB(uint8_t* row, uint32_t width) {
    // We will implement a crude conversion from CMYK -> RGB using formulas
    // from easyrgb.com.
    //
    // CMYK -> CMY
    // C = C * (1 - K) + K
    // M = M * (1 - K) + K
    // Y = Y * (1 - K) + K
    //
    // libjpeg actually gives us inverted CMYK, so we must subtract the
    // original terms from 1.
    // CMYK -> CMY
    // C = (1 - C) * (1 - (1 - K)) + (1 - K)
    // M = (1 - M) * (1 - (1 - K)) + (1 - K)
    // Y = (1 - Y) * (1 - (1 - K)) + (1 - K)
    //
    // Simplifying the above expression.
    // CMYK -> CMY
    // C = 1 - CK
    // M = 1 - MK
    // Y = 1 - YK
    //
    // CMY -> RGB
    // R = (1 - C) * 255
    // G = (1 - M) * 255
    // B = (1 - Y) * 255
    //
    // Therefore the full conversion is below.  This can be verified at
    // www.rapidtables.com (assuming inverted CMYK).
    // CMYK -> RGB
    // R = C * K * 255
    // G = M * K * 255
    // B = Y * K * 255
    //
    // As a final note, we have treated the CMYK values as if they were on
    // a scale from 0-1, when in fact they are 8-bit ints scaling from 0-255.
    // We must divide each CMYK component by 255 to obtain the true conversion
    // we should perform.
    // CMYK -> RGB
    // R = C * K / 255
    // G = M * K / 255
    // B = Y * K / 255
    for (uint32_t x = 0; x < width; x++, row += 4) {
        row[0] = SkMulDiv255Round(row[0], row[3]);
        row[1] = SkMulDiv255Round(row[1], row[3]);
        row[2] = SkMulDiv255Round(row[2], row[3]);
        row[3] = 0xFF;
    }
}
Example #5
0
SkPMColor SkPreMultiplyARGB(U8CPU a, U8CPU r, U8CPU g, U8CPU b) {
    if (a != 255) {
#if 0
        unsigned scale = SkAlpha255To256(a);
        r = SkAlphaMul(r, scale);
        g = SkAlphaMul(g, scale);
        b = SkAlphaMul(b, scale);
#else
        r = SkMulDiv255Round(r, a);
        g = SkMulDiv255Round(g, a);
        b = SkMulDiv255Round(b, a);
#endif
    }
    return SkPackARGB32(a, r, g, b);
}
static void clamp_with_orig(uint8_t dst[], int dstRowBytes,
                            const uint8_t src[], int srcRowBytes,
                            int sw, int sh,
                            SkBlurMask::Style style) {
    int x;
    while (--sh >= 0) {
        switch (style) {
        case SkBlurMask::kSolid_Style:
            for (x = sw - 1; x >= 0; --x) {
                int s = *src;
                int d = *dst;
                *dst = SkToU8(s + d - SkMulDiv255Round(s, d));
                dst += 1;
                src += 1;
            }
            break;
        case SkBlurMask::kOuter_Style:
            for (x = sw - 1; x >= 0; --x) {
                if (*src) {
                    *dst = SkToU8(SkAlphaMul(*dst, SkAlpha255To256(255 - *src)));
                }
                dst += 1;
                src += 1;
            }
            break;
        default:
            SkDEBUGFAIL("Unexpected blur style here");
            break;
        }
        dst += dstRowBytes - sw;
        src += srcRowBytes - sw;
    }
}
// Fold the saveLayer's alpha into the drawBitmapRect and remove the saveLayer
// and restore
static void apply_0(SkDebugCanvas* canvas, int curCommand) {
    SkSaveLayerCommand* saveLayer =
        (SkSaveLayerCommand*) canvas->getDrawCommandAt(curCommand);
    const SkPaint* saveLayerPaint = saveLayer->paint();

    // if (NULL == saveLayerPaint) the dbmr's paint doesn't need to be changed
    if (NULL != saveLayerPaint) {
        SkDrawBitmapRectCommand* dbmr =
            (SkDrawBitmapRectCommand*) canvas->getDrawCommandAt(curCommand+1);
        SkPaint* dbmrPaint = dbmr->paint();

        if (NULL == dbmrPaint) {
            // if the DBMR doesn't have a paint just use the saveLayer's
            dbmr->setPaint(*saveLayerPaint);
        } else if (NULL != saveLayerPaint) {
            // Both paints are present so their alphas need to be combined
            SkColor color = saveLayerPaint->getColor();
            int a0 = SkColorGetA(color);

            color = dbmrPaint->getColor();
            int a1 = SkColorGetA(color);

            int newA = SkMulDiv255Round(a0, a1);
            SkASSERT(newA <= 0xFF);

            SkColor newColor = SkColorSetA(color, newA);
            dbmrPaint->setColor(newColor);
        }
    }

    canvas->deleteDrawCommandAt(curCommand+2);  // restore
    canvas->deleteDrawCommandAt(curCommand);    // saveLayer
}
Example #8
0
static void RGBAtoRGB(const unsigned char* pixels, unsigned int pixelCount, unsigned char* output)
{
    for (; pixelCount-- > 0; pixels += 4) {
        // Do source-over composition on black.
        unsigned char alpha = pixels[3];
        if (alpha != 255) {
            *output++ = SkMulDiv255Round(pixels[0], alpha);
            *output++ = SkMulDiv255Round(pixels[1], alpha);
            *output++ = SkMulDiv255Round(pixels[2], alpha);
        } else {
            *output++ = pixels[0];
            *output++ = pixels[1];
            *output++ = pixels[2];
        }
    }
}
static void RGBAtoRGB(const unsigned char* pixels, unsigned pixelCount, unsigned char* output)
{
    // Per <canvas> spec, composite the input image pixels source-over on black.

    for (; pixelCount-- > 0; pixels += 4) {
        unsigned char alpha = pixels[3];
        if (alpha != 255) {
            *output++ = SkMulDiv255Round(pixels[0], alpha);
            *output++ = SkMulDiv255Round(pixels[1], alpha);
            *output++ = SkMulDiv255Round(pixels[2], alpha);
        } else {
            *output++ = pixels[0];
            *output++ = pixels[1];
            *output++ = pixels[2];
        }
    }
}
Example #10
0
bool SkColorShader::asNewEffect(GrContext* context, const SkPaint& paint,
                                const SkMatrix* localMatrix, GrColor* grColor,
                                GrEffectRef** grEffect) const {
    *grEffect = NULL;
    SkColor skColor = fColor;
    U8CPU newA = SkMulDiv255Round(SkColorGetA(fColor), paint.getAlpha());
    *grColor = SkColor2GrColor(SkColorSetA(skColor, newA));
    return true;
}
// Convert a scanline of CMYK samples to RGBX in place. Note that this
// method moves the "scanline" pointer in its processing
static void convert_CMYK_to_RGB(uint8_t* scanline, unsigned int width) {
    // At this point we've received CMYK pixels from libjpeg. We
    // perform a crude conversion to RGB (based on the formulae 
    // from easyrgb.com):
    //  CMYK -> CMY
    //    C = ( C * (1 - K) + K )      // for each CMY component
    //  CMY -> RGB
    //    R = ( 1 - C ) * 255          // for each RGB component
    // Unfortunately we are seeing inverted CMYK so all the original terms
    // are 1-. This yields:
    //  CMYK -> CMY
    //    C = ( (1-C) * (1 - (1-K) + (1-K) ) -> C = 1 - C*K
    // The conversion from CMY->RGB remains the same
    for (unsigned int x = 0; x < width; ++x, scanline += 4) {
        scanline[0] = SkMulDiv255Round(scanline[0], scanline[3]);
        scanline[1] = SkMulDiv255Round(scanline[1], scanline[3]);
        scanline[2] = SkMulDiv255Round(scanline[2], scanline[3]);
        scanline[3] = 255;
    }
}
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;
}
static inline bool S32A_D565_Blend_1(SkPMColor sc, uint16_t dc, U8CPU alpha) {
    unsigned dst_scale = 255 - SkMulDiv255Round(SkGetPackedA32(sc), alpha);
    unsigned dr = (SkMulS16(SkGetPackedR32(sc), alpha) >> 3) + SkMulS16(SkGetPackedR16(dc), dst_scale);
    unsigned dg = (SkMulS16(SkGetPackedG32(sc), alpha) >> 2) + SkMulS16(SkGetPackedG16(dc), dst_scale);

    unsigned rr = SkDiv255Round(dr);
    unsigned rg = SkDiv255Round(dg);

    if (rr <= 31 && rg <= 63) {
        return true;
    }
    return false;
}
static inline bool S32A_D565_Blend_02(SkPMColor sc, uint16_t dc, U8CPU alpha) {
    unsigned dst_scale = 255 - SkMulDiv255Round(SkGetPackedA32(sc), alpha);
    unsigned dr = SkMulS16(SkGetPackedR32(sc), alpha) + SkMulS16(GetPackedR16As32(dc), dst_scale);
    unsigned dg = SkMulS16(SkGetPackedG32(sc), alpha) + SkMulS16(GetPackedG16As32(dc), dst_scale);
    unsigned db = SkMulS16(SkGetPackedB32(sc), alpha) + SkMulS16(GetPackedB16As32(dc), dst_scale);
    int rc = SkPack888ToRGB16(SkDiv255Round(dr),
                              SkDiv255Round(dg),
                              SkDiv255Round(db));

    unsigned rr = SkGetPackedR16(rc);
    unsigned rg = SkGetPackedG16(rc);

    if (rr <= 31 && rg <= 63) {
        return true;
    }
    return false;
}
Example #15
0
void SkGradientShaderBase::GradientShaderCache::Build32bitCache(
        SkPMColor cache[], SkColor c0, SkColor c1,
        int count, U8CPU paintAlpha, uint32_t gradFlags) {
    SkASSERT(count > 1);

    // need to apply paintAlpha to our two endpoints
    uint32_t a0 = SkMulDiv255Round(SkColorGetA(c0), paintAlpha);
    uint32_t a1 = SkMulDiv255Round(SkColorGetA(c1), paintAlpha);


    const bool interpInPremul = SkToBool(gradFlags &
                           SkGradientShader::kInterpolateColorsInPremul_Flag);

    uint32_t r0 = SkColorGetR(c0);
    uint32_t g0 = SkColorGetG(c0);
    uint32_t b0 = SkColorGetB(c0);

    uint32_t r1 = SkColorGetR(c1);
    uint32_t g1 = SkColorGetG(c1);
    uint32_t b1 = SkColorGetB(c1);

    if (interpInPremul) {
        r0 = SkMulDiv255Round(r0, a0);
        g0 = SkMulDiv255Round(g0, a0);
        b0 = SkMulDiv255Round(b0, a0);

        r1 = SkMulDiv255Round(r1, a1);
        g1 = SkMulDiv255Round(g1, a1);
        b1 = SkMulDiv255Round(b1, a1);
    }

    SkFixed da = SkIntToFixed(a1 - a0) / (count - 1);
    SkFixed dr = SkIntToFixed(r1 - r0) / (count - 1);
    SkFixed dg = SkIntToFixed(g1 - g0) / (count - 1);
    SkFixed db = SkIntToFixed(b1 - b0) / (count - 1);

    /*  We pre-add 1/8 to avoid having to add this to our [0] value each time
        in the loop. Without this, the bias for each would be
            0x2000  0xA000  0xE000  0x6000
        With this trick, we can add 0 for the first (no-op) and just adjust the
        others.
     */
    SkUFixed a = SkIntToFixed(a0) + 0x2000;
    SkUFixed r = SkIntToFixed(r0) + 0x2000;
    SkUFixed g = SkIntToFixed(g0) + 0x2000;
    SkUFixed b = SkIntToFixed(b0) + 0x2000;

    /*
     *  Our dither-cell (spatially) is
     *      0 2
     *      3 1
     *  Where
     *      [0] -> [-1/8 ... 1/8 ) values near 0
     *      [1] -> [ 1/8 ... 3/8 ) values near 1/4
     *      [2] -> [ 3/8 ... 5/8 ) values near 1/2
     *      [3] -> [ 5/8 ... 7/8 ) values near 3/4
     */

    if (0xFF == a0 && 0 == da) {
        do {
            cache[kCache32Count*0] = SkPackARGB32(0xFF, (r + 0     ) >> 16,
                                                        (g + 0     ) >> 16,
                                                        (b + 0     ) >> 16);
            cache[kCache32Count*1] = SkPackARGB32(0xFF, (r + 0x8000) >> 16,
                                                        (g + 0x8000) >> 16,
                                                        (b + 0x8000) >> 16);
            cache[kCache32Count*2] = SkPackARGB32(0xFF, (r + 0xC000) >> 16,
                                                        (g + 0xC000) >> 16,
                                                        (b + 0xC000) >> 16);
            cache[kCache32Count*3] = SkPackARGB32(0xFF, (r + 0x4000) >> 16,
                                                        (g + 0x4000) >> 16,
                                                        (b + 0x4000) >> 16);
            cache += 1;
            r += dr;
            g += dg;
            b += db;
        } while (--count != 0);
    } else if (interpInPremul) {
bool SkBlurMask::BlurRect(SkMask *dst, const SkRect &src,
                          SkScalar provided_radius, Style style,
                          SkIPoint *margin, SkMask::CreateMode createMode) {
    int profile_size;

    float radius = SkScalarToFloat(SkScalarMul(provided_radius, kBlurRadiusFudgeFactor));

    // adjust blur radius to match interpretation from boxfilter code
    radius = (radius + .5f) * 2.f;

    profile_size = compute_profile_size(radius);

    int pad = profile_size/2;
    if (margin) {
        margin->set( pad, pad );
    }

    dst->fBounds.set(SkScalarRoundToInt(src.fLeft - pad),
                     SkScalarRoundToInt(src.fTop - pad),
                     SkScalarRoundToInt(src.fRight + pad),
                     SkScalarRoundToInt(src.fBottom + pad));

    dst->fRowBytes = dst->fBounds.width();
    dst->fFormat = SkMask::kA8_Format;
    dst->fImage = NULL;

    int             sw = SkScalarFloorToInt(src.width());
    int             sh = SkScalarFloorToInt(src.height());

    if (createMode == SkMask::kJustComputeBounds_CreateMode) {
        if (style == kInner_Style) {
            dst->fBounds.set(SkScalarRoundToInt(src.fLeft),
                             SkScalarRoundToInt(src.fTop),
                             SkScalarRoundToInt(src.fRight),
                             SkScalarRoundToInt(src.fBottom)); // restore trimmed bounds
            dst->fRowBytes = sw;
        }
        return true;
    }
    unsigned int *profile = NULL;

    compute_profile(radius, &profile);
    SkAutoTDeleteArray<unsigned int> ada(profile);

    size_t dstSize = dst->computeImageSize();
    if (0 == dstSize) {
        return false;   // too big to allocate, abort
    }

    uint8_t*        dp = SkMask::AllocImage(dstSize);

    dst->fImage = dp;

    int dstHeight = dst->fBounds.height();
    int dstWidth = dst->fBounds.width();

    // nearest odd number less than the profile size represents the center
    // of the (2x scaled) profile
    int center = ( profile_size & ~1 ) - 1;

    int w = sw - center;
    int h = sh - center;

    uint8_t *outptr = dp;

    SkAutoTMalloc<uint8_t> horizontalScanline(dstWidth);

    for (int x = 0 ; x < dstWidth ; ++x) {
        if (profile_size <= sw) {
            horizontalScanline[x] = profile_lookup(profile, x, dstWidth, w);
        } else {
            float span = float(sw)/radius;
            float giX = 1.5f - (x+.5f)/radius;
            horizontalScanline[x] = (uint8_t) (255 * (gaussianIntegral(giX) - gaussianIntegral(giX + span)));
        }
    }

    for (int y = 0 ; y < dstHeight ; ++y) {
        unsigned int profile_y;
        if (profile_size <= sh) {
            profile_y = profile_lookup(profile, y, dstHeight, h);
        } else {
            float span = float(sh)/radius;
            float giY = 1.5f - (y+.5f)/radius;
            profile_y = (uint8_t) (255 * (gaussianIntegral(giY) - gaussianIntegral(giY + span)));
        }

        for (int x = 0 ; x < dstWidth ; x++) {
            unsigned int maskval = SkMulDiv255Round(horizontalScanline[x], profile_y);
            *(outptr++) = maskval;
        }
    }

    if (style == kInner_Style) {
        // now we allocate the "real" dst, mirror the size of src
        size_t srcSize = (size_t)(src.width() * src.height());
        if (0 == srcSize) {
            return false;   // too big to allocate, abort
        }
        dst->fImage = SkMask::AllocImage(srcSize);
        for (int y = 0 ; y < sh ; y++) {
            uint8_t *blur_scanline = dp + (y+pad)*dstWidth + pad;
            uint8_t *inner_scanline = dst->fImage + y*sw;
            memcpy(inner_scanline, blur_scanline, sw);
        }
        SkMask::FreeImage(dp);

        dst->fBounds.set(SkScalarRoundToInt(src.fLeft),
                         SkScalarRoundToInt(src.fTop),
                         SkScalarRoundToInt(src.fRight),
                         SkScalarRoundToInt(src.fBottom)); // restore trimmed bounds
        dst->fRowBytes = sw;

    } else if (style == kOuter_Style) {
        for (int y = pad ; y < dstHeight-pad ; y++) {
            uint8_t *dst_scanline = dp + y*dstWidth + pad;
            memset(dst_scanline, 0, sw);
        }
    } else if (style == kSolid_Style) {
        for (int y = pad ; y < dstHeight-pad ; y++) {
            uint8_t *dst_scanline = dp + y*dstWidth + pad;
            memset(dst_scanline, 0xff, sw);
        }
    }
    // normal and solid styles are the same for analytic rect blurs, so don't
    // need to handle solid specially.

    return true;
}
void SkGradientShaderBase::Build32bitCache(SkPMColor cache[], SkColor c0, SkColor c1,
                                      int count, U8CPU paintAlpha) {
    SkASSERT(count > 1);

    // need to apply paintAlpha to our two endpoints
    SkFixed a = SkMulDiv255Round(SkColorGetA(c0), paintAlpha);
    SkFixed da;
    {
        int tmp = SkMulDiv255Round(SkColorGetA(c1), paintAlpha);
        da = SkIntToFixed(tmp - a) / (count - 1);
    }

    /*
     *  r,g,b used to be SkFixed, but on gcc (4.2.1 mac and 4.6.3 goobuntu) in
     *  release builds, we saw a compiler error where the 0xFF parameter in
     *  SkPackARGB32() was being totally ignored whenever it was called with
     *  a non-zero add (e.g. 0x8000).
     *
     *  We found two work-arounds:
     *      1. change r,g,b to unsigned (or just one of them)
     *      2. change SkPackARGB32 to + its (a << SK_A32_SHIFT) value instead
     *         of using |
     *
     *  We chose #1 just because it was more localized.
     *  See http://code.google.com/p/skia/issues/detail?id=1113
     */
    uint32_t r = SkColorGetR(c0);
    uint32_t g = SkColorGetG(c0);
    uint32_t b = SkColorGetB(c0);

    SkFixed dr = SkIntToFixed(SkColorGetR(c1) - r) / (count - 1);
    SkFixed dg = SkIntToFixed(SkColorGetG(c1) - g) / (count - 1);
    SkFixed db = SkIntToFixed(SkColorGetB(c1) - b) / (count - 1);

    /*  We pre-add 1/8 to avoid having to add this to our [0] value each time
        in the loop. Without this, the bias for each would be
            0x2000  0xA000  0xE000  0x6000
        With this trick, we can add 0 for the first (no-op) and just adjust the
        others.
     */
    r = SkIntToFixed(r) + 0x2000;
    g = SkIntToFixed(g) + 0x2000;
    b = SkIntToFixed(b) + 0x2000;

    /*
     *  Our dither-cell (spatially) is
     *      0 2
     *      3 1
     *  Where
     *      [0] -> [-1/8 ... 1/8 ) values near 0
     *      [1] -> [ 1/8 ... 3/8 ) values near 1/4
     *      [2] -> [ 3/8 ... 5/8 ) values near 1/2
     *      [3] -> [ 5/8 ... 7/8 ) values near 3/4
     */

    if (0xFF == a && 0 == da) {
        do {
            cache[kCache32Count*0] = SkPackARGB32(0xFF, (r + 0     ) >> 16,
                                                        (g + 0     ) >> 16,
                                                        (b + 0     ) >> 16);
            cache[kCache32Count*1] = SkPackARGB32(0xFF, (r + 0x8000) >> 16,
                                                        (g + 0x8000) >> 16,
                                                        (b + 0x8000) >> 16);
            cache[kCache32Count*2] = SkPackARGB32(0xFF, (r + 0xC000) >> 16,
                                                        (g + 0xC000) >> 16,
                                                        (b + 0xC000) >> 16);
            cache[kCache32Count*3] = SkPackARGB32(0xFF, (r + 0x4000) >> 16,
                                                        (g + 0x4000) >> 16,
                                                        (b + 0x4000) >> 16);
            cache += 1;
            r += dr;
            g += dg;
            b += db;
        } while (--count != 0);
    } else {
Example #18
0
bool SkPixmap::erase(SkColor color, const SkIRect& inArea) const {
    if (nullptr == fPixels) {
        return false;
    }
    SkIRect area;
    if (!area.intersect(this->bounds(), inArea)) {
        return false;
    }

    U8CPU a = SkColorGetA(color);
    U8CPU r = SkColorGetR(color);
    U8CPU g = SkColorGetG(color);
    U8CPU b = SkColorGetB(color);

    int height = area.height();
    const int width = area.width();
    const int rowBytes = this->rowBytes();
    
    switch (this->colorType()) {
        case kGray_8_SkColorType: {
            if (255 != a) {
                r = SkMulDiv255Round(r, a);
                g = SkMulDiv255Round(g, a);
                b = SkMulDiv255Round(b, a);
            }
            int gray = SkComputeLuminance(r, g, b);
            uint8_t* p = this->writable_addr8(area.fLeft, area.fTop);
            while (--height >= 0) {
                memset(p, gray, width);
                p += rowBytes;
            }
            break;
        }
        case kAlpha_8_SkColorType: {
            uint8_t* p = this->writable_addr8(area.fLeft, area.fTop);
            while (--height >= 0) {
                memset(p, a, width);
                p += rowBytes;
            }
            break;
        }
        case kARGB_4444_SkColorType:
        case kRGB_565_SkColorType: {
            uint16_t* p = this->writable_addr16(area.fLeft, area.fTop);
            uint16_t v;
            
            // make rgb premultiplied
            if (255 != a) {
                r = SkMulDiv255Round(r, a);
                g = SkMulDiv255Round(g, a);
                b = SkMulDiv255Round(b, a);
            }
            
            if (kARGB_4444_SkColorType == this->colorType()) {
                v = pack_8888_to_4444(a, r, g, b);
            } else {
                v = SkPackRGB16(r >> (8 - SK_R16_BITS),
                                g >> (8 - SK_G16_BITS),
                                b >> (8 - SK_B16_BITS));
            }
            while (--height >= 0) {
                sk_memset16(p, v, width);
                p = (uint16_t*)((char*)p + rowBytes);
            }
            break;
        }
        case kBGRA_8888_SkColorType:
        case kRGBA_8888_SkColorType: {
            uint32_t* p = this->writable_addr32(area.fLeft, area.fTop);
            
            if (255 != a && kPremul_SkAlphaType == this->alphaType()) {
                r = SkMulDiv255Round(r, a);
                g = SkMulDiv255Round(g, a);
                b = SkMulDiv255Round(b, a);
            }
            uint32_t v = kRGBA_8888_SkColorType == this->colorType()
                             ? SkPackARGB_as_RGBA(a, r, g, b)
                             : SkPackARGB_as_BGRA(a, r, g, b);

            while (--height >= 0) {
                sk_memset32(p, v, width);
                p = (uint32_t*)((char*)p + rowBytes);
            }
            break;
        }
        default:
            return false; // no change, so don't call notifyPixelsChanged()
    }
    return true;
}
Example #19
0
// slower "correct"
static int test_srcover2(unsigned dst, unsigned alpha) {
    return alpha + SkMulDiv255Round(dst, 255 - alpha);
}
// Reduce to a single drawBitmapRectToRect call by folding the clipRect's into
// the src and dst Rects and the saveLayer paints into the drawBitmapRectToRect's
// paint.
static void apply_7(SkDebugCanvas* canvas, int curCommand) {
    SkSaveLayerCommand* saveLayer0 =
        (SkSaveLayerCommand*) canvas->getDrawCommandAt(curCommand+2);
    SkSaveLayerCommand* saveLayer1 =
        (SkSaveLayerCommand*) canvas->getDrawCommandAt(curCommand+5);
    SkClipRectCommand* clip2 =
        (SkClipRectCommand*) canvas->getDrawCommandAt(curCommand+7);
    SkDrawBitmapRectCommand* dbmr =
        (SkDrawBitmapRectCommand*) canvas->getDrawCommandAt(curCommand+8);

    SkScalar newSrcLeft = dbmr->srcRect()->fLeft + clip2->rect().fLeft - dbmr->dstRect().fLeft;
    SkScalar newSrcTop = dbmr->srcRect()->fTop + clip2->rect().fTop - dbmr->dstRect().fTop;

    SkRect newSrc = SkRect::MakeXYWH(newSrcLeft, newSrcTop,
                                     clip2->rect().width(), clip2->rect().height());

    dbmr->setSrcRect(newSrc);
    dbmr->setDstRect(clip2->rect());

    SkColor color = 0xFF000000;
    int a0, a1;

    const SkPaint* saveLayerPaint0 = saveLayer0->paint();
    if (NULL != saveLayerPaint0) {
        color = saveLayerPaint0->getColor();
        a0 = SkColorGetA(color);
    } else {
        a0 = 0xFF;
    }

    const SkPaint* saveLayerPaint1 = saveLayer1->paint();
    if (NULL != saveLayerPaint1) {
        color = saveLayerPaint1->getColor();
        a1 = SkColorGetA(color);
    } else {
        a1 = 0xFF;
    }

    int newA = SkMulDiv255Round(a0, a1);
    SkASSERT(newA <= 0xFF);

    SkPaint* dbmrPaint = dbmr->paint();

    if (NULL != dbmrPaint) {
        SkColor newColor = SkColorSetA(dbmrPaint->getColor(), newA);
        dbmrPaint->setColor(newColor);
    } else {
        SkColor newColor = SkColorSetA(color, newA);

        SkPaint newPaint;
        newPaint.setColor(newColor);
        dbmr->setPaint(newPaint);
    }

    // remove everything except the drawbitmaprect
    canvas->deleteDrawCommandAt(curCommand+13);   // restore
    canvas->deleteDrawCommandAt(curCommand+12);   // restore
    canvas->deleteDrawCommandAt(curCommand+11);   // restore
    canvas->deleteDrawCommandAt(curCommand+10);   // restore
    canvas->deleteDrawCommandAt(curCommand+9);    // restore
    canvas->deleteDrawCommandAt(curCommand+7);    // clipRect
    canvas->deleteDrawCommandAt(curCommand+6);    // save
    canvas->deleteDrawCommandAt(curCommand+5);    // saveLayer
    canvas->deleteDrawCommandAt(curCommand+4);    // clipRect
    canvas->deleteDrawCommandAt(curCommand+3);    // save
    canvas->deleteDrawCommandAt(curCommand+2);    // saveLayer
    canvas->deleteDrawCommandAt(curCommand+1);    // clipRect
    canvas->deleteDrawCommandAt(curCommand);      // save
}
Example #21
0
bool SkBlurMask::BlurRect(SkScalar sigma, SkMask *dst,
                          const SkRect &src, SkBlurStyle style,
                          SkIPoint *margin, SkMask::CreateMode createMode) {
    int profile_size = SkScalarCeilToInt(6*sigma);

    int pad = profile_size/2;
    if (margin) {
        margin->set( pad, pad );
    }

    dst->fBounds.set(SkScalarRoundToInt(src.fLeft - pad),
                     SkScalarRoundToInt(src.fTop - pad),
                     SkScalarRoundToInt(src.fRight + pad),
                     SkScalarRoundToInt(src.fBottom + pad));

    dst->fRowBytes = dst->fBounds.width();
    dst->fFormat = SkMask::kA8_Format;
    dst->fImage = nullptr;

    int             sw = SkScalarFloorToInt(src.width());
    int             sh = SkScalarFloorToInt(src.height());

    if (createMode == SkMask::kJustComputeBounds_CreateMode) {
        if (style == kInner_SkBlurStyle) {
            dst->fBounds.set(SkScalarRoundToInt(src.fLeft),
                             SkScalarRoundToInt(src.fTop),
                             SkScalarRoundToInt(src.fRight),
                             SkScalarRoundToInt(src.fBottom)); // restore trimmed bounds
            dst->fRowBytes = sw;
        }
        return true;
    }

    std::unique_ptr<uint8_t[]> profile(ComputeBlurProfile(sigma));

    size_t dstSize = dst->computeImageSize();
    if (0 == dstSize) {
        return false;   // too big to allocate, abort
    }

    uint8_t*        dp = SkMask::AllocImage(dstSize);

    dst->fImage = dp;

    int dstHeight = dst->fBounds.height();
    int dstWidth = dst->fBounds.width();

    uint8_t *outptr = dp;

    SkAutoTMalloc<uint8_t> horizontalScanline(dstWidth);
    SkAutoTMalloc<uint8_t> verticalScanline(dstHeight);

    ComputeBlurredScanline(horizontalScanline, profile.get(), dstWidth, sigma);
    ComputeBlurredScanline(verticalScanline, profile.get(), dstHeight, sigma);

    for (int y = 0 ; y < dstHeight ; ++y) {
        for (int x = 0 ; x < dstWidth ; x++) {
            unsigned int maskval = SkMulDiv255Round(horizontalScanline[x], verticalScanline[y]);
            *(outptr++) = maskval;
        }
    }

    if (style == kInner_SkBlurStyle) {
        // now we allocate the "real" dst, mirror the size of src
        size_t srcSize = (size_t)(src.width() * src.height());
        if (0 == srcSize) {
            return false;   // too big to allocate, abort
        }
        dst->fImage = SkMask::AllocImage(srcSize);
        for (int y = 0 ; y < sh ; y++) {
            uint8_t *blur_scanline = dp + (y+pad)*dstWidth + pad;
            uint8_t *inner_scanline = dst->fImage + y*sw;
            memcpy(inner_scanline, blur_scanline, sw);
        }
        SkMask::FreeImage(dp);

        dst->fBounds.set(SkScalarRoundToInt(src.fLeft),
                         SkScalarRoundToInt(src.fTop),
                         SkScalarRoundToInt(src.fRight),
                         SkScalarRoundToInt(src.fBottom)); // restore trimmed bounds
        dst->fRowBytes = sw;

    } else if (style == kOuter_SkBlurStyle) {
        for (int y = pad ; y < dstHeight-pad ; y++) {
            uint8_t *dst_scanline = dp + y*dstWidth + pad;
            memset(dst_scanline, 0, sw);
        }
    } else if (style == kSolid_SkBlurStyle) {
        for (int y = pad ; y < dstHeight-pad ; y++) {
            uint8_t *dst_scanline = dp + y*dstWidth + pad;
            memset(dst_scanline, 0xff, sw);
        }
    }
    // normal and solid styles are the same for analytic rect blurs, so don't
    // need to handle solid specially.

    return true;
}