void SkSurface_Raster::onCopyOnWrite(ContentChangeMode mode) { // are we sharing pixelrefs with the image? sk_sp<SkImage> cached(this->refCachedImage(SkBudgeted::kNo, kNo_ForceUnique)); SkASSERT(cached); if (SkBitmapImageGetPixelRef(cached.get()) == fBitmap.pixelRef()) { SkASSERT(fWeOwnThePixels); if (kDiscard_ContentChangeMode == mode) { fBitmap.allocPixels(); } else { SkBitmap prev(fBitmap); fBitmap.allocPixels(); prev.lockPixels(); SkASSERT(prev.info() == fBitmap.info()); SkASSERT(prev.rowBytes() == fBitmap.rowBytes()); memcpy(fBitmap.getPixels(), prev.getPixels(), fBitmap.getSafeSize()); } SkASSERT(fBitmap.rowBytes() == fRowBytes); // be sure we always use the same value // Now fBitmap is a deep copy of itself (and therefore different from // what is being used by the image. Next we update the canvas to use // this as its backend, so we can't modify the image's pixels anymore. SkASSERT(this->getCachedCanvas()); this->getCachedCanvas()->getDevice()->replaceBitmapBackendForRasterSurface(fBitmap); } }
static void generateMask(const SkMask& mask, const SkPath& path) { SkBitmap::Config config; SkPaint paint; int srcW = mask.fBounds.width(); int srcH = mask.fBounds.height(); int dstW = srcW; int dstH = srcH; int dstRB = mask.fRowBytes; SkMatrix matrix; matrix.setTranslate(-SkIntToScalar(mask.fBounds.fLeft), -SkIntToScalar(mask.fBounds.fTop)); if (SkMask::kBW_Format == mask.fFormat) { config = SkBitmap::kA1_Config; paint.setAntiAlias(false); } else { config = SkBitmap::kA8_Config; paint.setAntiAlias(true); switch (mask.fFormat) { case SkMask::kA8_Format: break; case SkMask::kLCD16_Format: case SkMask::kLCD32_Format: // TODO: trigger off LCD orientation dstW *= 3; matrix.postScale(SkIntToScalar(3), SK_Scalar1); dstRB = 0; // signals we need a copy break; default: SkDEBUGFAIL("unexpected mask format"); } } SkRasterClip clip; clip.setRect(SkIRect::MakeWH(dstW, dstH)); SkBitmap bm; bm.setConfig(config, dstW, dstH, dstRB); if (0 == dstRB) { bm.allocPixels(); bm.lockPixels(); } else { bm.setPixels(mask.fImage); } sk_bzero(bm.getPixels(), bm.getSafeSize()); SkDraw draw; sk_bzero(&draw, sizeof(draw)); draw.fRC = &clip; draw.fClip = &clip.bwRgn(); draw.fMatrix = &matrix; draw.fBitmap = &bm; draw.drawPath(path, paint); if (0 == dstRB) { switch (mask.fFormat) { case SkMask::kLCD16_Format: pack3xHToLCD16(bm, mask); break; case SkMask::kLCD32_Format: pack3xHToLCD32(bm, mask); break; default: SkDEBUGFAIL("bad format for copyback"); } } }
static void generateMask(const SkMask& mask, const SkPath& path, const SkMaskGamma::PreBlend& maskPreBlend) { SkBitmap::Config config; SkPaint paint; int srcW = mask.fBounds.width(); int srcH = mask.fBounds.height(); int dstW = srcW; int dstH = srcH; int dstRB = mask.fRowBytes; SkMatrix matrix; matrix.setTranslate(-SkIntToScalar(mask.fBounds.fLeft), -SkIntToScalar(mask.fBounds.fTop)); if (SkMask::kBW_Format == mask.fFormat) { config = SkBitmap::kA1_Config; paint.setAntiAlias(false); } else { config = SkBitmap::kA8_Config; paint.setAntiAlias(true); switch (mask.fFormat) { case SkMask::kA8_Format: break; case SkMask::kLCD16_Format: case SkMask::kLCD32_Format: // TODO: trigger off LCD orientation dstW *= 3; matrix.postScale(SkIntToScalar(3), SK_Scalar1); dstRB = 0; // signals we need a copy break; default: SkDEBUGFAIL("unexpected mask format"); } } SkRasterClip clip; clip.setRect(SkIRect::MakeWH(dstW, dstH)); SkBitmap bm; bm.setConfig(config, dstW, dstH, dstRB); if (0 == dstRB) { if (!bm.allocPixels()) { // can't allocate offscreen, so empty the mask and return sk_bzero(mask.fImage, mask.computeImageSize()); return; } bm.lockPixels(); } else { bm.setPixels(mask.fImage); } sk_bzero(bm.getPixels(), bm.getSafeSize()); SkDraw draw; draw.fRC = &clip; draw.fClip = &clip.bwRgn(); draw.fMatrix = &matrix; draw.fBitmap = &bm; draw.drawPath(path, paint); switch (mask.fFormat) { case SkMask::kA8_Format: if (maskPreBlend.isApplicable()) { applyLUTToA8Mask(mask, maskPreBlend.fG); } break; case SkMask::kLCD16_Format: if (maskPreBlend.isApplicable()) { pack3xHToLCD16<true>(bm, mask, maskPreBlend); } else { pack3xHToLCD16<false>(bm, mask, maskPreBlend); } break; case SkMask::kLCD32_Format: if (maskPreBlend.isApplicable()) { pack3xHToLCD32<true>(bm, mask, maskPreBlend); } else { pack3xHToLCD32<false>(bm, mask, maskPreBlend); } break; default: break; } }