static void copyToMask(const SkRasterClip& rc, SkMask* mask) { if (rc.isAA()) { rc.aaRgn().copyToMask(mask); } else { copyToMask(rc.bwRgn(), mask); } }
bool SkLayerRasterizer::onRasterize(const SkPath& path, const SkMatrix& matrix, const SkIRect* clipBounds, SkMask* mask, SkMask::CreateMode mode) const { SkASSERT(fLayers); if (fLayers->empty()) { return false; } if (SkMask::kJustRenderImage_CreateMode != mode) { if (!compute_bounds(*fLayers, path, matrix, clipBounds, &mask->fBounds)) return false; } if (SkMask::kComputeBoundsAndRenderImage_CreateMode == mode) { mask->fFormat = SkMask::kA8_Format; mask->fRowBytes = mask->fBounds.width(); size_t size = mask->computeImageSize(); if (0 == size) { return false; // too big to allocate, abort } mask->fImage = SkMask::AllocImage(size); memset(mask->fImage, 0, size); } if (SkMask::kJustComputeBounds_CreateMode != mode) { SkBitmap device; SkRasterClip rectClip; SkDraw draw; SkMatrix translatedMatrix; // this translates us to our local pixels SkMatrix drawMatrix; // this translates the path by each layer's offset rectClip.setRect(SkIRect::MakeWH(mask->fBounds.width(), mask->fBounds.height())); translatedMatrix = matrix; translatedMatrix.postTranslate(-SkIntToScalar(mask->fBounds.fLeft), -SkIntToScalar(mask->fBounds.fTop)); device.installMaskPixels(*mask); draw.fBitmap = &device; draw.fMatrix = &drawMatrix; draw.fRC = &rectClip; draw.fClip = &rectClip.bwRgn(); // we set the matrixproc in the loop, as the matrix changes each time (potentially) SkDeque::F2BIter iter(*fLayers); SkLayerRasterizer_Rec* rec; while ((rec = (SkLayerRasterizer_Rec*)iter.next()) != NULL) { drawMatrix = translatedMatrix; drawMatrix.preTranslate(rec->fOffset.fX, rec->fOffset.fY); draw.drawPath(path, rec->fPaint); } } return true; }
bool SkRasterClip::setPath(const SkPath& path, const SkRasterClip& clip, bool doAA) { if (clip.isBW()) { return this->setPath(path, clip.bwRgn(), doAA); } else { SkRegion tmp; tmp.setRect(clip.getBounds()); if (!this->setPath(path, clip, doAA)) { return false; } return this->op(clip, SkRegion::kIntersect_Op); } }
void SkScan::FillXRect(const SkXRect& xr, const SkRasterClip& clip, SkBlitter* blitter) { if (clip.isEmpty() || xr.isEmpty()) { return; } if (clip.isBW()) { FillXRect(xr, &clip.bwRgn(), blitter); return; } SkAAClipBlitterWrapper wrapper(clip, blitter); FillXRect(xr, &wrapper.getRgn(), wrapper.getBlitter()); }
bool SkRasterClip::op(const SkRasterClip& clip, SkRegion::Op op) { if (this->isBW() && clip.isBW()) { return fBW.op(clip.fBW, op); } else { SkAAClip tmp; const SkAAClip* other; if (this->isBW()) { this->convertToAA(); } if (clip.isBW()) { tmp.setRegion(clip.bwRgn()); other = &tmp; } else { other = &clip.aaRgn(); } return fAA.op(*other, op); } }
void SkScan::FillTriangle(const SkPoint pts[], const SkRasterClip& clip, SkBlitter* blitter) { if (clip.isEmpty()) { return; } SkRect r; r.set(pts, 3); // If r is too large (larger than can easily fit in SkFixed) then we need perform geometric // clipping. This is a bit of work, so we just call the general FillPath() to handle it. // Use FixedMax/2 as the limit so we can subtract two edges and still store that in Fixed. const SkScalar limit = SK_MaxS16 >> 1; if (!SkRect::MakeLTRB(-limit, -limit, limit, limit).contains(r)) { SkPath path; path.addPoly(pts, 3, false); FillPath(path, clip, blitter); return; } SkIRect ir = conservative_round_to_int(r); if (ir.isEmpty() || !SkIRect::Intersects(ir, clip.getBounds())) { return; } SkAAClipBlitterWrapper wrap; const SkRegion* clipRgn; if (clip.isBW()) { clipRgn = &clip.bwRgn(); } else { wrap.init(clip, blitter); clipRgn = &wrap.getRgn(); blitter = wrap.getBlitter(); } SkScanClipper clipper(blitter, clipRgn, ir); blitter = clipper.getBlitter(); if (blitter) { sk_fill_triangle(pts, clipper.getClipRect(), blitter, ir); } }
bool SkRasterClip::op(const SkRasterClip& clip, SkRegion::Op op) { AUTO_RASTERCLIP_VALIDATE(*this); clip.validate(); if (this->isBW() && clip.isBW()) { return fBW.op(clip.fBW, op); } else { SkAAClip tmp; const SkAAClip* other; if (this->isBW()) { this->convertToAA(); } if (clip.isBW()) { tmp.setRegion(clip.bwRgn()); other = &tmp; } else { other = &clip.aaRgn(); } return fAA.op(*other, op); } }
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) { 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)); paint.setAntiAlias(SkMask::kBW_Format != mask.fFormat); switch (mask.fFormat) { case SkMask::kBW_Format: dstRB = 0; // signals we need a copy break; case SkMask::kA8_Format: break; case SkMask::kLCD16_Format: // TODO: trigger off LCD orientation dstW = 4*dstW - 8; matrix.setTranslate(-SkIntToScalar(mask.fBounds.fLeft + 1), -SkIntToScalar(mask.fBounds.fTop)); matrix.postScale(SkIntToScalar(4), SK_Scalar1); dstRB = 0; // signals we need a copy break; default: SkDEBUGFAIL("unexpected mask format"); } SkRasterClip clip; clip.setRect(SkIRect::MakeWH(dstW, dstH)); const SkImageInfo info = SkImageInfo::MakeA8(dstW, dstH); SkAutoPixmapStorage dst; if (0 == dstRB) { if (!dst.tryAlloc(info)) { // can't allocate offscreen, so empty the mask and return sk_bzero(mask.fImage, mask.computeImageSize()); return; } } else { dst.reset(info, mask.fImage, dstRB); } sk_bzero(dst.writable_addr(), dst.getSafeSize()); SkDraw draw; draw.fDst = dst; draw.fRC = &clip; draw.fClip = &clip.bwRgn(); draw.fMatrix = &matrix; draw.drawPath(path, paint); switch (mask.fFormat) { case SkMask::kBW_Format: packA8ToA1(mask, dst.addr8(0, 0), dst.rowBytes()); break; case SkMask::kA8_Format: if (maskPreBlend.isApplicable()) { applyLUTToA8Mask(mask, maskPreBlend.fG); } break; case SkMask::kLCD16_Format: if (maskPreBlend.isApplicable()) { pack4xHToLCD16<true>(dst, mask, maskPreBlend); } else { pack4xHToLCD16<false>(dst, mask, maskPreBlend); } break; default: break; } }
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; } }