Android bitmap erase(透過)
graphics/java/android/graphics/Bitmap.java
public void eraseColor(int c)
↓
graphics/java/android/graphics/Bitmap.java
nativeErase(mNativeBitmap, c)
↓
android/platform_frameworks_base/core/jni/android/graphics/Bitmap.cpp
nativeErase=>Bitmap_erase =>bitmap->eraseColor(color)
↓
android/platform_external_skia/include/core/SkBitmap.h
eraseColor()
void eraseColor(SkColor c) const {
this->eraseARGB(SkColorGetA(c), SkColorGetR(c), SkColorGetG(c),
SkColorGetB(c));
}
android/platform_external_skia/src/core/SkBitmap.cpp
void SkBitmap::eraseARGB(U8CPU a, U8CPU r, U8CPU g, U8CPU b) const { SkDEBUGCODE(this->validate();) if (0 == fWidth || 0 == fHeight || kNo_Config == fConfig || kIndex8_Config == fConfig) { return; } SkAutoLockPixels alp(*this); // perform this check after the lock call if (!this->readyToDraw()) { return; } int height = fHeight; const int width = fWidth; const int rowBytes = fRowBytes; // make rgb premultiplied if (255 != a) { r = SkAlphaMul(r, a); g = SkAlphaMul(g, a); b = SkAlphaMul(b, a); } switch (fConfig) { (略) case kARGB_8888_Config: { uint32_t* p = (uint32_t*)fPixels; uint32_t v = SkPackARGB32(a, r, g, b); while (--height >= 0) { sk_memset32(p, v, width); p = (uint32_t*)((char*)p + rowBytes); } break; } } this->notifyPixelsChanged(); }
android/platform_external_skia/src/core/SkCanvas.cpp
void SkCanvas::drawBitmap(const SkBitmap& bitmap, SkScalar x, SkScalar y, const SkPaint* paint) { SkDEBUGCODE(bitmap.validate();) if (NULL == paint || (paint->getMaskFilter() == NULL)) { SkRect fastBounds; fastBounds.set(x, y, x + SkIntToScalar(bitmap.width()), y + SkIntToScalar(bitmap.height())); if (this->quickReject(fastBounds, paint2EdgeType(paint))) { return; } } SkMatrix matrix; matrix.setTranslate(x, y); this->internalDrawBitmap(bitmap, NULL, matrix, paint); } void SkCanvas::internalDrawBitmap(const SkBitmap& bitmap, const SkIRect* srcRect, const SkMatrix& matrix, const SkPaint* paint) { if (reject_bitmap(bitmap)) { return; } SkLazyPaint lazy; if (NULL == paint) { paint = lazy.init(); } this->commonDrawBitmap(bitmap, srcRect, matrix, *paint); } void SkCanvas::commonDrawBitmap(const SkBitmap& bitmap, const SkIRect* srcRect, const SkMatrix& matrix, const SkPaint& paint) { SkDEBUGCODE(bitmap.validate();) LOOPER_BEGIN(paint, SkDrawFilter::kBitmap_Type) while (iter.next()) { iter.fDevice->drawBitmap(iter, bitmap, srcRect, matrix, looper.paint()); } LOOPER_END }
android/platform_external_skia/src/core/SkDevice.cpp
void SkDevice::drawBitmap(const SkDraw& draw, const SkBitmap& bitmap, const SkIRect* srcRect, const SkMatrix& matrix, const SkPaint& paint) { SkBitmap tmp; // storage if we need a subset of bitmap const SkBitmap* bitmapPtr = &bitmap; if (srcRect) { if (!bitmap.extractSubset(&tmp, *srcRect)) { return; // extraction failed } bitmapPtr = &tmp; } draw.drawBitmap(*bitmapPtr, matrix, paint); }
android/platform_external_skia/src/core/SkDraw.cpp
void SkDraw::drawBitmap(const SkBitmap& bitmap, const SkMatrix& prematrix, const SkPaint& paint) const { SkDEBUGCODE(this->validate();) // nothing to draw if (fClip->isEmpty() || bitmap.width() == 0 || bitmap.height() == 0 || bitmap.getConfig() == SkBitmap::kNo_Config || (paint.getAlpha() == 0 && paint.getXfermode() == NULL)) { return; } #ifndef SK_ALLOW_OVER_32K_BITMAPS // run away on too-big bitmaps for now (exceed 16.16) if (bitmap.width() > 32767 || bitmap.height() > 32767) { return; } #endif SkAutoPaintStyleRestore restore(paint, SkPaint::kFill_Style); SkMatrix matrix; if (!matrix.setConcat(*fMatrix, prematrix)) { return; } if (clipped_out(matrix, *fClip, bitmap.width(), bitmap.height())) { return; } if (fBounder && just_translate(matrix, bitmap)) { SkIRect ir; int32_t ix = SkScalarRound(matrix.getTranslateX()); int32_t iy = SkScalarRound(matrix.getTranslateY()); ir.set(ix, iy, ix + bitmap.width(), iy + bitmap.height()); if (!fBounder->doIRect(ir)) { return; } } // only lock the pixels if we passed the clip and bounder tests SkAutoLockPixels alp(bitmap); // after the lock, check if we are valid if (!bitmap.readyToDraw()) { return; } if (bitmap.getConfig() != SkBitmap::kA8_Config && just_translate(matrix, bitmap)) { int ix = SkScalarRound(matrix.getTranslateX()); int iy = SkScalarRound(matrix.getTranslateY()); uint32_t storage[kBlitterStorageLongCount]; SkBlitter* blitter = SkBlitter::ChooseSprite(*fBitmap, paint, bitmap, ix, iy, storage, sizeof(storage)); if (blitter) { SkAutoTPlacementDelete<SkBlitter> ad(blitter, storage); SkIRect ir; ir.set(ix, iy, ix + bitmap.width(), iy + bitmap.height()); SkRegion::Cliperator iter(*fClip, ir); const SkIRect& cr = iter.rect(); for (; !iter.done(); iter.next()) { SkASSERT(!cr.isEmpty()); blitter->blitRect(cr.fLeft, cr.fTop, cr.width(), cr.height()); } return; } #if 0 SkDebugf("---- MISSING sprite case: config=%d [%d %d], device=%d, xfer=%p, alpha=0x%X colorFilter=%p\n", bitmap.config(), bitmap.width(), bitmap.height(), fBitmap->config(), paint.getXfermode(), paint.getAlpha(), paint.getColorFilter()); #endif } // now make a temp draw on the stack, and use it // SkDraw draw(*this); draw.fMatrix = &matrix; if (bitmap.getConfig() == SkBitmap::kA8_Config) { draw.drawBitmapAsMask(bitmap, paint); } else { SkAutoBitmapShaderInstall install(bitmap, &paint); SkRect r; r.set(0, 0, SkIntToScalar(bitmap.width()), SkIntToScalar(bitmap.height())); // is this ok if paint has a rasterizer? draw.drawRect(r, paint); } }