virtual void filterSpan(const SkPMColor shader[], int count, SkPMColor result[]) { unsigned addR = SkColorGetR(fAdd); unsigned addG = SkColorGetG(fAdd); unsigned addB = SkColorGetB(fAdd); for (int i = 0; i < count; i++) { SkPMColor c = shader[i]; if (c) { unsigned a = SkGetPackedA32(c); unsigned scaleA = SkAlpha255To256(a); unsigned r = pin(SkGetPackedR32(c) + SkAlphaMul(addR, scaleA), a); unsigned g = pin(SkGetPackedG32(c) + SkAlphaMul(addG, scaleA), a); unsigned b = pin(SkGetPackedB32(c) + SkAlphaMul(addB, scaleA), a); c = SkPackARGB32(a, r, g, b); } result[i] = c; } }
inline uint32_t blendSrcOverDstNonPremultiplied(uint32_t src, uint32_t dst) { uint8_t srcA = SkGetPackedA32(src); if (srcA == 0) return dst; uint8_t dstA = SkGetPackedA32(dst); uint8_t dstFactorA = (dstA * SkAlpha255To256(255 - srcA)) >> 8; ASSERT(srcA + dstFactorA < (1U << 8)); uint8_t blendA = srcA + dstFactorA; unsigned scale = (1UL << 24) / blendA; uint8_t blendR = blendChannel(SkGetPackedR32(src), srcA, SkGetPackedR32(dst), dstFactorA, scale); uint8_t blendG = blendChannel(SkGetPackedG32(src), srcA, SkGetPackedG32(dst), dstFactorA, scale); uint8_t blendB = blendChannel(SkGetPackedB32(src), srcA, SkGetPackedB32(dst), dstFactorA, scale); return SkPackARGB32NoCheck(blendA, blendR, blendG, blendB); }
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; }
void SkLumaMaskXfermode::xfer32(SkPMColor dst[], const SkPMColor src[], int count, const SkAlpha aa[]) const { const SkPMColor* a = lumaOpA<SkPMColor>(fMode, src, dst); const SkPMColor* b = lumaOpB<SkPMColor>(fMode, src, dst); if (aa) { for (int i = 0; i < count; ++i) { unsigned cov = aa[i]; if (cov) { unsigned resC = luma_proc(a[i], b[i]); if (cov < 255) { resC = SkFastFourByteInterp256(resC, dst[i], SkAlpha255To256(cov)); } dst[i] = resC; } } } else { for (int i = 0; i < count; ++i) { dst[i] = luma_proc(a[i], b[i]); } } }
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); fFlags = kConstInY32_Flag; if (255 == a) { fFlags |= kOpaqueAlpha_Flag; } }
void SkARGB32_Black_Blitter::blitMask(const SkMask& mask, const SkIRect& clip) { SkASSERT(mask.fBounds.contains(clip)); if (mask.fFormat == SkMask::kBW_Format) { SkPMColor black = (SkPMColor)(SK_A32_MASK << SK_A32_SHIFT); SkARGB32_BlitBW(fDevice, mask, clip, black); } else if (SkMask::kARGB32_Format == mask.fFormat) { SkARGB32_Blit32(fDevice, mask, clip, fPMColor); } else if (SkMask::kLCD16_Format == mask.fFormat) { blitmask_lcd16(fDevice, mask, clip, fPMColor); } else if (SkMask::kLCD32_Format == mask.fFormat) { blitmask_lcd32(fDevice, mask, clip, fPMColor); } else { unsigned width = clip.width(); unsigned height = clip.height(); SkASSERT((int)height > 0); SkASSERT((int)width > 0); uint32_t* device = fDevice.getAddr32(clip.fLeft, clip.fTop); unsigned maskRB = mask.fRowBytes - width; unsigned deviceRB = fDevice.rowBytes() - (width << 2); const uint8_t* alpha = mask.getAddr(clip.fLeft, clip.fTop); do { unsigned w = width; do { unsigned aa = *alpha++; *device = (aa << SK_A32_SHIFT) + SkAlphaMulQ(*device, SkAlpha255To256(255 - aa)); device += 1; } while (--w != 0); device = (uint32_t*)((char*)device + deviceRB); alpha += maskRB; } while (--height != 0); } }
// kDstOut_Mode, //!< [Da * (1 - Sa), Dc * (1 - Sa)] static SkPMColor dstout_modeproc(SkPMColor src, SkPMColor dst) { return SkAlphaMulQ(dst, SkAlpha255To256(255 - SkGetPackedA32(src))); }
// kSrcIn_Mode, //!< [Sa * Da, Sc * Da] static SkPMColor srcin_modeproc(SkPMColor src, SkPMColor dst) { return SkAlphaMulQ(src, SkAlpha255To256(SkGetPackedA32(dst))); }
SkScalar scale = SkFixedToScalar(SK_Fixed1 >> shift); fUnitInvMatrix.postScale(scale, scale); // now point here instead of fOrigBitmap fBitmap = &fMipBitmap; } } fInvMatrix = m; fInvProc = m->getMapXYProc(); fInvType = m->getType(); fInvSx = SkScalarToFixed(m->getScaleX()); fInvKy = SkScalarToFixed(m->getSkewY()); fAlphaScale = SkAlpha255To256(paint.getAlpha()); // pick-up filtering from the paint, but only if the matrix is // more complex than identity/translate (i.e. no need to pay the cost // of filtering if we're not scaled etc.). // note: we explicitly check inv, since m might be scaled due to unitinv // trickery, but we don't want to see that for this test fDoFilter = paint.isFilterBitmap() && (inv.getType() > SkMatrix::kTranslate_Mask && valid_for_filtering(fBitmap->width() | fBitmap->height())); fShaderProc32 = NULL; fShaderProc16 = NULL; fSampleProc32 = NULL; fSampleProc16 = NULL;
bool SkBitmapProcState::chooseProcs(const SkMatrix& inv, const SkPaint& paint) { SkASSERT(fOrigBitmap.width() && fOrigBitmap.height()); fBitmap = NULL; fInvMatrix = inv; fFilterLevel = paint.getFilterLevel(); // possiblyScaleImage will look to see if it can rescale the image as a // preprocess; either by scaling up to the target size, or by selecting // a nearby mipmap level. If it does, it will adjust the working // matrix as well as the working bitmap. It may also adjust the filter // quality to avoid re-filtering an already perfectly scaled image. if (!this->possiblyScaleImage()) { if (!this->lockBaseBitmap()) { return false; } } // The above logic should have always assigned fBitmap, but in case it // didn't, we check for that now... // TODO(dominikg): Ask humper@ if we can just use an SkASSERT(fBitmap)? if (NULL == fBitmap) { return false; } // If we are "still" kMedium_FilterLevel, then the request was not fulfilled by possiblyScale, // so we downgrade to kLow (so the rest of the sniffing code can assume that) if (SkPaint::kMedium_FilterLevel == fFilterLevel) { fFilterLevel = SkPaint::kLow_FilterLevel; } bool trivialMatrix = (fInvMatrix.getType() & ~SkMatrix::kTranslate_Mask) == 0; bool clampClamp = SkShader::kClamp_TileMode == fTileModeX && SkShader::kClamp_TileMode == fTileModeY; if (!(fAdjustedMatrix || clampClamp || trivialMatrix)) { fInvMatrix.postIDiv(fOrigBitmap.width(), fOrigBitmap.height()); } // Now that all possible changes to the matrix have taken place, check // to see if we're really close to a no-scale matrix. If so, explicitly // set it to be so. Subsequent code may inspect this matrix to choose // a faster path in this case. // This code will only execute if the matrix has some scale component; // if it's already pure translate then we won't do this inversion. if (matrix_only_scale_translate(fInvMatrix)) { SkMatrix forward; if (fInvMatrix.invert(&forward)) { if (clampClamp ? just_trans_clamp(forward, *fBitmap) : just_trans_general(forward)) { SkScalar tx = -SkScalarRoundToScalar(forward.getTranslateX()); SkScalar ty = -SkScalarRoundToScalar(forward.getTranslateY()); fInvMatrix.setTranslate(tx, ty); } } } fInvProc = fInvMatrix.getMapXYProc(); fInvType = fInvMatrix.getType(); fInvSx = SkScalarToFixed(fInvMatrix.getScaleX()); fInvSxFractionalInt = SkScalarToFractionalInt(fInvMatrix.getScaleX()); fInvKy = SkScalarToFixed(fInvMatrix.getSkewY()); fInvKyFractionalInt = SkScalarToFractionalInt(fInvMatrix.getSkewY()); fAlphaScale = SkAlpha255To256(paint.getAlpha()); fShaderProc32 = NULL; fShaderProc16 = NULL; fSampleProc32 = NULL; fSampleProc16 = NULL; // recompute the triviality of the matrix here because we may have // changed it! trivialMatrix = (fInvMatrix.getType() & ~SkMatrix::kTranslate_Mask) == 0; if (SkPaint::kHigh_FilterLevel == fFilterLevel) { // If this is still set, that means we wanted HQ sampling // but couldn't do it as a preprocess. Let's try to install // the scanline version of the HQ sampler. If that process fails, // downgrade to bilerp. // NOTE: Might need to be careful here in the future when we want // to have the platform proc have a shot at this; it's possible that // the chooseBitmapFilterProc will fail to install a shader but a // platform-specific one might succeed, so it might be premature here // to fall back to bilerp. This needs thought. if (!this->setBitmapFilterProcs()) { fFilterLevel = SkPaint::kLow_FilterLevel; } } if (SkPaint::kLow_FilterLevel == fFilterLevel) { // Only try bilerp if the matrix is "interesting" and // the image has a suitable size. if (fInvType <= SkMatrix::kTranslate_Mask || !valid_for_filtering(fBitmap->width() | fBitmap->height())) { fFilterLevel = SkPaint::kNone_FilterLevel; } } // At this point, we know exactly what kind of sampling the per-scanline // shader will perform. fMatrixProc = this->chooseMatrixProc(trivialMatrix); // TODO(dominikg): SkASSERT(fMatrixProc) instead? chooseMatrixProc never returns NULL. if (NULL == fMatrixProc) { return false; } /////////////////////////////////////////////////////////////////////// const SkAlphaType at = fBitmap->alphaType(); // No need to do this if we're doing HQ sampling; if filter quality is // still set to HQ by the time we get here, then we must have installed // the shader procs above and can skip all this. if (fFilterLevel < SkPaint::kHigh_FilterLevel) { int index = 0; if (fAlphaScale < 256) { // note: this distinction is not used for D16 index |= 1; } if (fInvType <= (SkMatrix::kTranslate_Mask | SkMatrix::kScale_Mask)) { index |= 2; } if (fFilterLevel > SkPaint::kNone_FilterLevel) { index |= 4; } // bits 3,4,5 encoding the source bitmap format switch (fBitmap->colorType()) { case kN32_SkColorType: if (kPremul_SkAlphaType != at && kOpaque_SkAlphaType != at) { return false; } index |= 0; break; case kRGB_565_SkColorType: index |= 8; break; case kIndex_8_SkColorType: if (kPremul_SkAlphaType != at && kOpaque_SkAlphaType != at) { return false; } index |= 16; break; case kARGB_4444_SkColorType: if (kPremul_SkAlphaType != at && kOpaque_SkAlphaType != at) { return false; } index |= 24; break; case kAlpha_8_SkColorType: index |= 32; fPaintPMColor = SkPreMultiplyColor(paint.getColor()); break; default: // TODO(dominikg): Should we ever get here? SkASSERT(false) instead? return false; } #if !SK_ARM_NEON_IS_ALWAYS static const SampleProc32 gSkBitmapProcStateSample32[] = { S32_opaque_D32_nofilter_DXDY, S32_alpha_D32_nofilter_DXDY, S32_opaque_D32_nofilter_DX, S32_alpha_D32_nofilter_DX, S32_opaque_D32_filter_DXDY, S32_alpha_D32_filter_DXDY, S32_opaque_D32_filter_DX, S32_alpha_D32_filter_DX, S16_opaque_D32_nofilter_DXDY, S16_alpha_D32_nofilter_DXDY, S16_opaque_D32_nofilter_DX, S16_alpha_D32_nofilter_DX, S16_opaque_D32_filter_DXDY, S16_alpha_D32_filter_DXDY, S16_opaque_D32_filter_DX, S16_alpha_D32_filter_DX, SI8_opaque_D32_nofilter_DXDY, SI8_alpha_D32_nofilter_DXDY, SI8_opaque_D32_nofilter_DX, SI8_alpha_D32_nofilter_DX, SI8_opaque_D32_filter_DXDY, SI8_alpha_D32_filter_DXDY, SI8_opaque_D32_filter_DX, SI8_alpha_D32_filter_DX, S4444_opaque_D32_nofilter_DXDY, S4444_alpha_D32_nofilter_DXDY, S4444_opaque_D32_nofilter_DX, S4444_alpha_D32_nofilter_DX, S4444_opaque_D32_filter_DXDY, S4444_alpha_D32_filter_DXDY, S4444_opaque_D32_filter_DX, S4444_alpha_D32_filter_DX, // A8 treats alpha/opaque the same (equally efficient) SA8_alpha_D32_nofilter_DXDY, SA8_alpha_D32_nofilter_DXDY, SA8_alpha_D32_nofilter_DX, SA8_alpha_D32_nofilter_DX, SA8_alpha_D32_filter_DXDY, SA8_alpha_D32_filter_DXDY, SA8_alpha_D32_filter_DX, SA8_alpha_D32_filter_DX }; static const SampleProc16 gSkBitmapProcStateSample16[] = { S32_D16_nofilter_DXDY, S32_D16_nofilter_DX, S32_D16_filter_DXDY, S32_D16_filter_DX, S16_D16_nofilter_DXDY, S16_D16_nofilter_DX, S16_D16_filter_DXDY, S16_D16_filter_DX, SI8_D16_nofilter_DXDY, SI8_D16_nofilter_DX, SI8_D16_filter_DXDY, SI8_D16_filter_DX, // Don't support 4444 -> 565 NULL, NULL, NULL, NULL, // Don't support A8 -> 565 NULL, NULL, NULL, NULL }; #endif fSampleProc32 = SK_ARM_NEON_WRAP(gSkBitmapProcStateSample32)[index]; index >>= 1; // shift away any opaque/alpha distinction fSampleProc16 = SK_ARM_NEON_WRAP(gSkBitmapProcStateSample16)[index]; // our special-case shaderprocs if (SK_ARM_NEON_WRAP(S16_D16_filter_DX) == fSampleProc16) { if (clampClamp) { fShaderProc16 = SK_ARM_NEON_WRAP(Clamp_S16_D16_filter_DX_shaderproc); } else if (SkShader::kRepeat_TileMode == fTileModeX && SkShader::kRepeat_TileMode == fTileModeY) { fShaderProc16 = SK_ARM_NEON_WRAP(Repeat_S16_D16_filter_DX_shaderproc); } } else if (SK_ARM_NEON_WRAP(SI8_opaque_D32_filter_DX) == fSampleProc32 && clampClamp) { fShaderProc32 = SK_ARM_NEON_WRAP(Clamp_SI8_opaque_D32_filter_DX_shaderproc); } if (NULL == fShaderProc32) { fShaderProc32 = this->chooseShaderProc32(); } }
void SkTransparentShader::shadeSpan(int x, int y, SkPMColor span[], int count) { unsigned scale = SkAlpha255To256(fAlpha); switch (fDevice->getConfig()) { case SkBitmap::kARGB_8888_Config: if (scale == 256) { SkPMColor* src = fDevice->getAddr32(x, y); if (src != span) { memcpy(span, src, count * sizeof(SkPMColor)); } } else { const SkPMColor* src = fDevice->getAddr32(x, y); for (int i = count - 1; i >= 0; --i) { span[i] = SkAlphaMulQ(src[i], scale); } } break; case SkBitmap::kRGB_565_Config: { const uint16_t* src = fDevice->getAddr16(x, y); if (scale == 256) { for (int i = count - 1; i >= 0; --i) { span[i] = SkPixel16ToPixel32(src[i]); } } else { unsigned alpha = fAlpha; for (int i = count - 1; i >= 0; --i) { uint16_t c = src[i]; unsigned r = SkPacked16ToR32(c); unsigned g = SkPacked16ToG32(c); unsigned b = SkPacked16ToB32(c); span[i] = SkPackARGB32( alpha, SkAlphaMul(r, scale), SkAlphaMul(g, scale), SkAlphaMul(b, scale)); } } break; } case SkBitmap::kARGB_4444_Config: { const uint16_t* src = fDevice->getAddr16(x, y); if (scale == 256) { for (int i = count - 1; i >= 0; --i) { span[i] = SkPixel4444ToPixel32(src[i]); } } else { unsigned scale16 = scale >> 4; for (int i = count - 1; i >= 0; --i) { uint32_t c = SkExpand_4444(src[i]) * scale16; span[i] = SkCompact_8888(c); } } break; } case SkBitmap::kIndex8_Config: SkDEBUGFAIL("index8 not supported as a destination device"); break; case SkBitmap::kA8_Config: { const uint8_t* src = fDevice->getAddr8(x, y); if (scale == 256) { for (int i = count - 1; i >= 0; --i) { span[i] = SkPackARGB32(src[i], 0, 0, 0); } } else { for (int i = count - 1; i >= 0; --i) { span[i] = SkPackARGB32(SkAlphaMul(src[i], scale), 0, 0, 0); } } break; } case SkBitmap::kA1_Config: SkDEBUGFAIL("kA1_Config umimplemented at this time"); break; default: // to avoid warnings break; } }
// our std SkAlpha255To256 static int test_srcover0(unsigned dst, unsigned alpha) { return alpha + SkAlphaMul(dst, SkAlpha255To256(255 - alpha)); }
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); } }
/* * Analyze filter-quality and matrix, and decide how to implement that. * * In general, we cascade down the request level [ High ... None ] * - for a given level, if we can fulfill it, fine, else * - else we downgrade to the next lower level and try again. * We can always fulfill requests for Low and None * - sometimes we will "ignore" Low and give None, but this is likely a legacy perf hack * and may be removed. */ bool SkBitmapProcState::chooseProcs(const SkMatrix& inv, const SkPaint& paint) { fPixmap.reset(); fInvMatrix = inv; fFilterLevel = paint.getFilterQuality(); const int origW = fProvider.info().width(); const int origH = fProvider.info().height(); bool allow_ignore_fractional_translate = true; // historical default if (kMedium_SkFilterQuality == fFilterLevel) { allow_ignore_fractional_translate = false; } SkDefaultBitmapController controller; fBMState = controller.requestBitmap(fProvider, inv, paint.getFilterQuality(), fBMStateStorage.get(), fBMStateStorage.size()); // Note : we allow the controller to return an empty (zero-dimension) result. Should we? if (nullptr == fBMState || fBMState->pixmap().info().isEmpty()) { return false; } fPixmap = fBMState->pixmap(); fInvMatrix = fBMState->invMatrix(); fFilterLevel = fBMState->quality(); SkASSERT(fPixmap.addr()); bool trivialMatrix = (fInvMatrix.getType() & ~SkMatrix::kTranslate_Mask) == 0; bool clampClamp = SkShader::kClamp_TileMode == fTileModeX && SkShader::kClamp_TileMode == fTileModeY; // Most of the scanline procs deal with "unit" texture coordinates, as this // makes it easy to perform tiling modes (repeat = (x & 0xFFFF)). To generate // those, we divide the matrix by its dimensions here. // // We don't do this if we're either trivial (can ignore the matrix) or clamping // in both X and Y since clamping to width,height is just as easy as to 0xFFFF. if (!(clampClamp || trivialMatrix)) { fInvMatrix.postIDiv(fPixmap.width(), fPixmap.height()); } // Now that all possible changes to the matrix have taken place, check // to see if we're really close to a no-scale matrix. If so, explicitly // set it to be so. Subsequent code may inspect this matrix to choose // a faster path in this case. // This code will only execute if the matrix has some scale component; // if it's already pure translate then we won't do this inversion. if (matrix_only_scale_translate(fInvMatrix)) { SkMatrix forward; if (fInvMatrix.invert(&forward)) { if ((clampClamp && allow_ignore_fractional_translate) ? just_trans_clamp(forward, fPixmap) : just_trans_general(forward)) { fInvMatrix.setTranslate(-forward.getTranslateX(), -forward.getTranslateY()); } } } fInvProc = fInvMatrix.getMapXYProc(); fInvType = fInvMatrix.getType(); fInvSx = SkScalarToFixed(fInvMatrix.getScaleX()); fInvSxFractionalInt = SkScalarToFractionalInt(fInvMatrix.getScaleX()); fInvKy = SkScalarToFixed(fInvMatrix.getSkewY()); fInvKyFractionalInt = SkScalarToFractionalInt(fInvMatrix.getSkewY()); fAlphaScale = SkAlpha255To256(paint.getAlpha()); fShaderProc32 = nullptr; fShaderProc16 = nullptr; fSampleProc32 = nullptr; // recompute the triviality of the matrix here because we may have // changed it! trivialMatrix = (fInvMatrix.getType() & ~SkMatrix::kTranslate_Mask) == 0; // If our target pixmap is the same as the original, then we revert back to legacy behavior // and allow the code to ignore fractional translate. // // The width/height check allows allow_ignore_fractional_translate to stay false if we // previously set it that way (e.g. we started in kMedium). // if (fPixmap.width() == origW && fPixmap.height() == origH) { allow_ignore_fractional_translate = true; } if (kLow_SkFilterQuality == fFilterLevel && allow_ignore_fractional_translate) { // Only try bilerp if the matrix is "interesting" and // the image has a suitable size. if (fInvType <= SkMatrix::kTranslate_Mask || !valid_for_filtering(fPixmap.width() | fPixmap.height())) { fFilterLevel = kNone_SkFilterQuality; } } return this->chooseScanlineProcs(trivialMatrix, clampClamp, paint); }
} } runs += count; antialias += count; device += count; } } /////////////////////////////////////////////////////////////////////////////// // Special version of SkBlitRow::Factory32 that knows we're in kSrc_Mode, // instead of kSrcOver_Mode static void blend_srcmode(SkPMColor* SK_RESTRICT device, const SkPMColor* SK_RESTRICT span, int count, U8CPU aa) { int aa256 = SkAlpha255To256(aa); for (int i = 0; i < count; ++i) { device[i] = SkFourByteInterp256(span[i], device[i], aa256); } } SkARGB32_Shader_Blitter::SkARGB32_Shader_Blitter(const SkBitmap& device, const SkPaint& paint) : INHERITED(device, paint) { fBuffer = (SkPMColor*)sk_malloc_throw(device.width() * (sizeof(SkPMColor))); fXfermode = paint.getXfermode(); SkSafeRef(fXfermode); int flags = 0; if (!(fShader->getFlags() & SkShader::kOpaqueAlpha_Flag)) { flags |= SkBlitRow::kSrcPixelAlpha_Flag32;
static inline SkPMColor luma_proc(const SkPMColor a, const SkPMColor b) { unsigned luma = SkComputeLuminance(SkGetPackedR32(b), SkGetPackedG32(b), SkGetPackedB32(b)); return SkAlphaMulQ(a, SkAlpha255To256(luma)); }