* found in the LICENSE file.
*/
-
#include "SkCanvas.h"
#include "SkCanvasPriv.h"
#include "SkBitmapDevice.h"
#include "SkDraw.h"
#include "SkDrawFilter.h"
#include "SkDrawLooper.h"
+#include "SkImage.h"
#include "SkMetaData.h"
#include "SkPathOps.h"
#include "SkPatchUtils.h"
#include "SkSmallAllocator.h"
#include "SkSurface_Base.h"
#include "SkTemplates.h"
+#include "SkTextBlob.h"
#include "SkTextFormatParams.h"
#include "SkTLazy.h"
#include "SkUtils.h"
///////////////////////////////////////////////////////////////////////////////
+static uint32_t filter_paint_flags(const SkSurfaceProps& props, uint32_t flags) {
+ const uint32_t propFlags = props.flags();
+ if (propFlags & SkSurfaceProps::kDisallowDither_Flag) {
+ flags &= ~SkPaint::kDither_Flag;
+ }
+ if (propFlags & SkSurfaceProps::kDisallowAntiAlias_Flag) {
+ flags &= ~SkPaint::kAntiAlias_Flag;
+ }
+ return flags;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
/* This is the record we keep for each SkBaseDevice that the user installs.
The clip/matrix/proc are fields that reflect the top of the save/restore
stack. Whenever the canvas changes, it marks a dirty flag, and then before
const SkMatrix* fMatrix;
SkPaint* fPaint; // may be null (in the future)
- DeviceCM(SkBaseDevice* device, int x, int y, const SkPaint* paint, SkCanvas* canvas)
- : fNext(NULL) {
+ DeviceCM(SkBaseDevice* device, int x, int y, const SkPaint* paint, SkCanvas* canvas,
+ bool conservativeRasterClip)
+ : fNext(NULL)
+ , fClip(conservativeRasterClip)
+ {
if (NULL != device) {
device->ref();
device->onAttachToCanvas(canvas);
}
~DeviceCM() {
- if (NULL != fDevice) {
+ if (fDevice) {
fDevice->onDetachFromCanvas();
fDevice->unref();
}
*/
class SkCanvas::MCRec {
public:
- SkMatrix fMatrix;
SkRasterClip fRasterClip;
+ SkMatrix fMatrix;
SkDrawFilter* fFilter; // the current filter (or null)
-
- DeviceCM* fLayer;
+ DeviceCM* fLayer;
/* If there are any layers in the stack, this points to the top-most
one that is at or below this level in the stack (so we know what
bitmap/device to draw into from this level. This value is NOT
*/
DeviceCM* fTopLayer;
- MCRec(const MCRec* prev) {
- if (NULL != prev) {
- fMatrix = prev->fMatrix;
- fRasterClip = prev->fRasterClip;
+ MCRec(bool conservativeRasterClip) : fRasterClip(conservativeRasterClip) {
+ fMatrix.reset();
+ fFilter = NULL;
+ fLayer = NULL;
+ fTopLayer = NULL;
- fFilter = prev->fFilter;
- SkSafeRef(fFilter);
-
- fTopLayer = prev->fTopLayer;
- } else { // no prev
- fMatrix.reset();
- fFilter = NULL;
- fTopLayer = NULL;
- }
+ // don't bother initializing fNext
+ inc_rec();
+ }
+ MCRec(const MCRec& prev) : fRasterClip(prev.fRasterClip) {
+ fMatrix = prev.fMatrix;
+ fFilter = SkSafeRef(prev.fFilter);
fLayer = NULL;
+ fTopLayer = prev.fTopLayer;
// don't bother initializing fNext
inc_rec();
class AutoDrawLooper {
public:
- AutoDrawLooper(SkCanvas* canvas, const SkPaint& paint,
+ AutoDrawLooper(SkCanvas* canvas, const SkSurfaceProps& props, const SkPaint& paint,
bool skipLayerForImageFilter = false,
const SkRect* bounds = NULL) : fOrigPaint(paint) {
fCanvas = canvas;
fFilter = canvas->getDrawFilter();
- fPaint = NULL;
+ fPaint = &fOrigPaint;
fSaveCount = canvas->getSaveCount();
fDoClearImageFilter = false;
fDone = false;
// can we be marked as simple?
fIsSimple = !fFilter && !fDoClearImageFilter;
}
+
+ uint32_t oldFlags = paint.getFlags();
+ fNewPaintFlags = filter_paint_flags(props, oldFlags);
+ if (fIsSimple && (fNewPaintFlags != oldFlags)) {
+ SkPaint* paint = fLazyPaint.set(fOrigPaint);
+ paint->setFlags(fNewPaintFlags);
+ fPaint = paint;
+ // if we're not simple, doNext() will take care of calling setFlags()
+ }
}
~AutoDrawLooper() {
return false;
} else if (fIsSimple) {
fDone = true;
- fPaint = &fOrigPaint;
return !fPaint->nothingToDraw();
} else {
return this->doNext(drawType);
SkDrawFilter* fFilter;
const SkPaint* fPaint;
int fSaveCount;
+ uint32_t fNewPaintFlags;
bool fDoClearImageFilter;
bool fDone;
bool fIsSimple;
SkASSERT(fLooperContext || fFilter || fDoClearImageFilter);
SkPaint* paint = fLazyPaint.set(fOrigPaint);
+ paint->setFlags(fNewPaintFlags);
if (fDoClearImageFilter) {
paint->setImageFilter(NULL);
return true;
}
-#include "SkColorPriv.h"
-
////////// macros to place around the internal draw calls //////////////////
#define LOOPER_BEGIN_DRAWDEVICE(paint, type) \
this->predrawNotify(); \
- AutoDrawLooper looper(this, paint, true); \
+ AutoDrawLooper looper(this, fProps, paint, true); \
while (looper.next(type)) { \
SkDrawIter iter(this);
#define LOOPER_BEGIN(paint, type, bounds) \
this->predrawNotify(); \
- AutoDrawLooper looper(this, paint, false, bounds); \
+ AutoDrawLooper looper(this, fProps, paint, false, bounds); \
while (looper.next(type)) { \
SkDrawIter iter(this);
////////////////////////////////////////////////////////////////////////////
-SkBaseDevice* SkCanvas::init(SkBaseDevice* device) {
+void SkCanvas::setupDevice(SkBaseDevice* device) {
+ device->setPixelGeometry(fProps.pixelGeometry());
+}
+
+SkBaseDevice* SkCanvas::init(SkBaseDevice* device, InitFlags flags) {
+ fConservativeRasterClip = SkToBool(flags & kConservativeRasterClip_InitFlag);
fCachedLocalClipBounds.setEmpty();
fCachedLocalClipBoundsDirty = true;
fAllowSoftClip = true;
fAllowSimplifyClip = false;
- fDeviceCMDirty = false;
+ fDeviceCMDirty = true;
fSaveLayerCount = 0;
fCullCount = 0;
fMetaData = NULL;
fMCRec = (MCRec*)fMCStack.push_back();
- new (fMCRec) MCRec(NULL);
+ new (fMCRec) MCRec(fConservativeRasterClip);
- fMCRec->fLayer = SkNEW_ARGS(DeviceCM, (NULL, 0, 0, NULL, NULL));
+ fMCRec->fLayer = SkNEW_ARGS(DeviceCM, (NULL, 0, 0, NULL, NULL, fConservativeRasterClip));
fMCRec->fTopLayer = fMCRec->fLayer;
fSurfaceBase = NULL;
- return this->setRootDevice(device);
+ if (device) {
+ this->setupDevice(device);
+ if (device->forceConservativeRasterClip()) {
+ fConservativeRasterClip = true;
+ }
+ device->onAttachToCanvas(this);
+ fMCRec->fLayer->fDevice = SkRef(device);
+ fMCRec->fRasterClip.setRect(SkIRect::MakeWH(device->width(), device->height()));
+ }
+ return device;
}
SkCanvas::SkCanvas()
: fMCStack(sizeof(MCRec), fMCRecStorage, sizeof(fMCRecStorage))
+ , fProps(SkSurfaceProps::kLegacyFontHost_InitType)
{
inc_canvas();
- this->init(NULL);
+ this->init(NULL, kDefault_InitFlags);
}
+static SkBitmap make_nopixels(int width, int height) {
+ SkBitmap bitmap;
+ bitmap.setInfo(SkImageInfo::MakeUnknown(width, height));
+ return bitmap;
+}
+
+class SkNoPixelsBitmapDevice : public SkBitmapDevice {
+public:
+ SkNoPixelsBitmapDevice(int width, int height) : INHERITED(make_nopixels(width, height)) {}
+
+private:
+
+ typedef SkBitmapDevice INHERITED;
+};
+
SkCanvas::SkCanvas(int width, int height)
: fMCStack(sizeof(MCRec), fMCRecStorage, sizeof(fMCRecStorage))
+ , fProps(SkSurfaceProps::kLegacyFontHost_InitType)
{
inc_canvas();
- SkBitmap bitmap;
- bitmap.setInfo(SkImageInfo::MakeUnknown(width, height));
- this->init(SkNEW_ARGS(SkBitmapDevice, (bitmap)))->unref();
+ this->init(SkNEW_ARGS(SkNoPixelsBitmapDevice, (width, height)), kDefault_InitFlags)->unref();
+}
+
+SkCanvas::SkCanvas(int width, int height, InitFlags flags)
+ : fMCStack(sizeof(MCRec), fMCRecStorage, sizeof(fMCRecStorage))
+ , fProps(SkSurfaceProps::kLegacyFontHost_InitType)
+{
+ inc_canvas();
+
+ this->init(SkNEW_ARGS(SkNoPixelsBitmapDevice, (width, height)), flags)->unref();
+}
+
+SkCanvas::SkCanvas(SkBaseDevice* device, const SkSurfaceProps* props, InitFlags flags)
+ : fMCStack(sizeof(MCRec), fMCRecStorage, sizeof(fMCRecStorage))
+ , fProps(SkSurfacePropsCopyOrDefault(props))
+{
+ inc_canvas();
+
+ this->init(device, flags);
}
SkCanvas::SkCanvas(SkBaseDevice* device)
: fMCStack(sizeof(MCRec), fMCRecStorage, sizeof(fMCRecStorage))
+ , fProps(SkSurfaceProps::kLegacyFontHost_InitType)
+{
+ inc_canvas();
+
+ this->init(device, kDefault_InitFlags);
+}
+
+SkCanvas::SkCanvas(const SkBitmap& bitmap, const SkSurfaceProps& props)
+ : fMCStack(sizeof(MCRec), fMCRecStorage, sizeof(fMCRecStorage))
+ , fProps(props)
{
inc_canvas();
- this->init(device);
+ SkAutoTUnref<SkBaseDevice> device(SkNEW_ARGS(SkBitmapDevice, (bitmap)));
+ this->init(device, kDefault_InitFlags);
}
SkCanvas::SkCanvas(const SkBitmap& bitmap)
: fMCStack(sizeof(MCRec), fMCRecStorage, sizeof(fMCRecStorage))
+ , fProps(SkSurfaceProps::kLegacyFontHost_InitType)
{
inc_canvas();
- this->init(SkNEW_ARGS(SkBitmapDevice, (bitmap)))->unref();
+ SkAutoTUnref<SkBaseDevice> device(SkNEW_ARGS(SkBitmapDevice, (bitmap)));
+ this->init(device, kDefault_InitFlags);
}
SkCanvas::~SkCanvas() {
SkRefCnt_SafeAssign(rec->fLayer->fDevice, device);
rootDevice = device;
+ this->setupDevice(device);
fDeviceCMDirty = true;
bool weAllocated = false;
if (NULL == bitmap->pixelRef()) {
- if (!bitmap->allocPixels()) {
+ if (!bitmap->tryAllocPixels()) {
return false;
}
weAllocated = true;
return false;
}
- if (!bitmap->allocN32Pixels(r.width(), r.height())) {
+ if (!bitmap->tryAllocN32Pixels(r.width(), r.height())) {
// bitmap will already be reset.
return false;
}
return false;
}
- SkImageInfo info = origInfo;
// the intersect may have shrunk info's logical size
- info.fWidth = srcR.width();
- info.fHeight = srcR.height();
+ const SkImageInfo info = origInfo.makeWH(srcR.width(), srcR.height());
// if x or y are negative, then we have to adjust pixels
if (x > 0) {
return false;
}
- SkImageInfo info = origInfo;
// the intersect may have shrunk info's logical size
- info.fWidth = target.width();
- info.fHeight = target.height();
+ const SkImageInfo info = origInfo.makeWH(target.width(), target.height());
// if x or y are negative, then we have to adjust pixels
if (x > 0) {
int saveCount = this->getSaveCount(); // record this before the actual save
MCRec* newTop = (MCRec*)fMCStack.push_back();
- new (newTop) MCRec(fMCRec); // balanced in restore()
+ new (newTop) MCRec(*fMCRec); // balanced in restore()
fMCRec = newTop;
fClipStack.save();
op = SkRegion::kReplace_Op;
}
SkIRect ir;
- if (NULL != bounds) {
+ if (bounds) {
SkRect r;
this->getTotalMatrix().mapRect(&r, *bounds);
SkDebugf("Unable to create device for layer.");
return count;
}
+ this->setupDevice(device);
device->setOrigin(ir.fLeft, ir.fTop);
- DeviceCM* layer = SkNEW_ARGS(DeviceCM, (device, ir.fLeft, ir.fTop, paint, this));
+ DeviceCM* layer = SkNEW_ARGS(DeviceCM,
+ (device, ir.fLeft, ir.fTop, paint, this, fConservativeRasterClip));
device->unref();
layer->fNext = fMCRec->fTopLayer;
since if we're being recorded, we don't want to record this (the
recorder will have already recorded the restore).
*/
- if (NULL != layer) {
+ if (layer) {
if (layer->fNext) {
const SkIPoint& origin = layer->fDevice->getOrigin();
this->internalDrawDevice(layer->fDevice, origin.x(), origin.y(),
return fSaveLayerCount > 0;
}
-SkSurface* SkCanvas::newSurface(const SkImageInfo& info) {
- return this->onNewSurface(info);
+SkSurface* SkCanvas::newSurface(const SkImageInfo& info, const SkSurfaceProps* props) {
+ if (NULL == props) {
+ props = &fProps;
+ }
+ return this->onNewSurface(info, *props);
}
-SkSurface* SkCanvas::onNewSurface(const SkImageInfo& info) {
+SkSurface* SkCanvas::onNewSurface(const SkImageInfo& info, const SkSurfaceProps& props) {
SkBaseDevice* dev = this->getDevice();
- return dev ? dev->newSurface(info) : NULL;
+ return dev ? dev->newSurface(info, props) : NULL;
}
SkImageInfo SkCanvas::imageInfo() const {
fAddr = canvas->peekPixels(&fInfo, &fRowBytes);
if (NULL == fAddr) {
fInfo = canvas->imageInfo();
- if (kUnknown_SkColorType == fInfo.colorType() || !fBitmap.allocPixels(fInfo)) {
+ if (kUnknown_SkColorType == fInfo.colorType() || !fBitmap.tryAllocPixels(fInfo)) {
return; // failure, fAddr is NULL
}
if (!canvas->readPixels(&fBitmap, 0, 0)) {
fMCRec->fMatrix.mapRect(&r, rect);
fClipStack.clipDevRect(r, op, kSoft_ClipEdgeStyle == edgeStyle);
- fMCRec->fRasterClip.op(r, op, kSoft_ClipEdgeStyle == edgeStyle);
+ fMCRec->fRasterClip.op(r, this->getBaseLayerSize(), op, kSoft_ClipEdgeStyle == edgeStyle);
} else {
// since we're rotated or some such thing, we convert the rect to a path
// and clip against that, since it can handle any matrix. However, to
}
}
-static void clip_path_helper(const SkCanvas* canvas, SkRasterClip* currClip,
- const SkPath& devPath, SkRegion::Op op, bool doAA) {
- // base is used to limit the size (and therefore memory allocation) of the
- // region that results from scan converting devPath.
- SkRegion base;
-
- if (SkRegion::kIntersect_Op == op) {
- // since we are intersect, we can do better (tighter) with currRgn's
- // bounds, than just using the device. However, if currRgn is complex,
- // our region blitter may hork, so we do that case in two steps.
- if (currClip->isRect()) {
- // FIXME: we should also be able to do this when currClip->isBW(),
- // but relaxing the test above triggers GM asserts in
- // SkRgnBuilder::blitH(). We need to investigate what's going on.
- currClip->setPath(devPath, currClip->bwRgn(), doAA);
- } else {
- base.setRect(currClip->getBounds());
- SkRasterClip clip;
- clip.setPath(devPath, base, doAA);
- currClip->op(clip, op);
- }
- } else {
- const SkISize size = canvas->getBaseLayerSize();
- base.setRect(0, 0, size.width(), size.height());
-
- if (SkRegion::kReplace_Op == op) {
- currClip->setPath(devPath, base, doAA);
- } else {
- SkRasterClip clip;
- clip.setPath(devPath, base, doAA);
- currClip->op(clip, op);
- }
- }
+static void rasterclip_path(SkRasterClip* rc, const SkCanvas* canvas, const SkPath& devPath,
+ SkRegion::Op op, bool doAA) {
+ rc->op(devPath, canvas->getBaseLayerSize(), op, doAA);
}
void SkCanvas::clipRRect(const SkRRect& rrect, SkRegion::Op op, bool doAA) {
SkPath devPath;
devPath.addRRect(transformedRRect);
- clip_path_helper(this, &fMCRec->fRasterClip, devPath, op, kSoft_ClipEdgeStyle == edgeStyle);
+ rasterclip_path(&fMCRec->fRasterClip, this, devPath, op, kSoft_ClipEdgeStyle == edgeStyle);
return;
}
op = SkRegion::kReplace_Op;
}
- clip_path_helper(this, &fMCRec->fRasterClip, devPath, op, edgeStyle);
-}
-
-void SkCanvas::updateClipConservativelyUsingBounds(const SkRect& bounds, SkRegion::Op op,
- bool inverseFilled) {
- // This is for updating the clip conservatively using only bounds
- // information.
- // Contract:
- // The current clip must contain the true clip. The true
- // clip is the clip that would have normally been computed
- // by calls to clipPath and clipRRect
- // Objective:
- // Keep the current clip as small as possible without
- // breaking the contract, using only clip bounding rectangles
- // (for performance).
-
- // N.B.: This *never* calls back through a virtual on canvas, so subclasses
- // don't have to worry about getting caught in a loop. Thus anywhere
- // we call a virtual method, we explicitly prefix it with
- // SkCanvas:: to be sure to call the base-class.
-
- if (inverseFilled) {
- switch (op) {
- case SkRegion::kIntersect_Op:
- case SkRegion::kDifference_Op:
- // These ops can only shrink the current clip. So leaving
- // the clip unchanged conservatively respects the contract.
- break;
- case SkRegion::kUnion_Op:
- case SkRegion::kReplace_Op:
- case SkRegion::kReverseDifference_Op:
- case SkRegion::kXOR_Op: {
- // These ops can grow the current clip up to the extents of
- // the input clip, which is inverse filled, so we just set
- // the current clip to the device bounds.
- SkRect deviceBounds;
- SkIRect deviceIBounds;
- this->getDevice()->getGlobalBounds(&deviceIBounds);
- deviceBounds = SkRect::Make(deviceIBounds);
-
- // set the clip in device space
- SkMatrix savedMatrix = this->getTotalMatrix();
- this->SkCanvas::setMatrix(SkMatrix::I());
- this->SkCanvas::onClipRect(deviceBounds, SkRegion::kReplace_Op,
- kHard_ClipEdgeStyle);
- this->setMatrix(savedMatrix);
- break;
- }
- default:
- SkASSERT(0); // unhandled op?
- }
- } else {
- // Not inverse filled
- switch (op) {
- case SkRegion::kIntersect_Op:
- case SkRegion::kUnion_Op:
- case SkRegion::kReplace_Op:
- this->SkCanvas::onClipRect(bounds, op, kHard_ClipEdgeStyle);
- break;
- case SkRegion::kDifference_Op:
- // Difference can only shrink the current clip.
- // Leaving clip unchanged conservatively fullfills the contract.
- break;
- case SkRegion::kReverseDifference_Op:
- // To reverse, we swap in the bounds with a replace op.
- // As with difference, leave it unchanged.
- this->SkCanvas::onClipRect(bounds, SkRegion::kReplace_Op, kHard_ClipEdgeStyle);
- break;
- case SkRegion::kXOR_Op:
- // Be conservative, based on (A XOR B) always included in (A union B),
- // which is always included in (bounds(A) union bounds(B))
- this->SkCanvas::onClipRect(bounds, SkRegion::kUnion_Op, kHard_ClipEdgeStyle);
- break;
- default:
- SkASSERT(0); // unhandled op?
- }
- }
+ rasterclip_path(&fMCRec->fRasterClip, this, devPath, op, edgeStyle);
}
void SkCanvas::clipRegion(const SkRegion& rgn, SkRegion::Op op) {
SkIRect ir;
ir.set(0, 0, device->width(), device->height());
- SkRasterClip tmpClip(ir);
+ SkRasterClip tmpClip(ir, fConservativeRasterClip);
SkClipStack::B2TIter iter(fClipStack);
const SkClipStack::Element* element;
default: {
SkPath path;
element->asPath(&path);
- clip_path_helper(this, &tmpClip, path, element->getOp(), element->isAA());
+ rasterclip_path(&tmpClip, this, path, element->getOp(), element->isAA());
break;
}
}
}
bool SkCanvas::quickReject(const SkRect& rect) const {
-
if (!rect.isFinite())
return true;
return false;
}
- if (NULL != bounds) {
+ if (bounds) {
SkRect r;
// adjust it outwards in case we are antialiasing
const int inset = 1;
return false;
}
- if (NULL != bounds) {
+ if (bounds) {
*bounds = clip.getBounds();
}
return true;
return fMCRec->fMatrix;
}
-#ifdef SK_SUPPORT_LEGACY_GETCLIPTYPE
-SkCanvas::ClipType SkCanvas::getClipType() const {
- if (fMCRec->fRasterClip.isEmpty()) {
- return kEmpty_ClipType;
- }
- if (fMCRec->fRasterClip.isRect()) {
- return kRect_ClipType;
- }
- return kComplex_ClipType;
-}
-#endif
-
const SkRegion& SkCanvas::internal_private_getTotalClip() const {
return fMCRec->fRasterClip.forceGetBW();
}
-void SkCanvas::internal_private_getTotalClipAsPath(SkPath* path) const {
- path->reset();
-
- const SkRegion& rgn = fMCRec->fRasterClip.forceGetBW();
- if (rgn.isEmpty()) {
- return;
- }
- (void)rgn.getBoundaryPath(path);
-}
-
GrRenderTarget* SkCanvas::internal_private_accessTopLayerRenderTarget() {
SkBaseDevice* dev = this->getTopDevice();
return dev ? dev->accessRenderTarget() : NULL;
GrContext* SkCanvas::getGrContext() {
#if SK_SUPPORT_GPU
SkBaseDevice* device = this->getTopDevice();
- if (NULL != device) {
+ if (device) {
GrRenderTarget* renderTarget = device->accessRenderTarget();
- if (NULL != renderTarget) {
+ if (renderTarget) {
return renderTarget->getContext();
}
}
}
void SkCanvas::onDiscard() {
- if (NULL != fSurfaceBase) {
+ if (fSurfaceBase) {
fSurfaceBase->aboutToDraw(SkSurface::kDiscard_ContentChangeMode);
}
}
LOOPER_END
}
+void SkCanvas::drawImage(const SkImage* image, SkScalar left, SkScalar top,
+ const SkPaint* paint) {
+ image->draw(this, left, top, paint);
+}
+
+void SkCanvas::drawImageRect(const SkImage* image, const SkRect* src,
+ const SkRect& dst,
+ const SkPaint* paint) {
+ image->draw(this, src, dst, paint);
+}
+
void SkCanvas::drawBitmap(const SkBitmap& bitmap, SkScalar x, SkScalar y,
const SkPaint* paint) {
SkDEBUGCODE(bitmap.validate();)
if (device->filterTextFlags(paint, &flags)) {
SkPaint* newPaint = fLazy.set(paint);
newPaint->setFlags(flags.fFlags);
- newPaint->setHinting(flags.fHinting);
fPaint = newPaint;
} else {
fPaint = &paint;
LOOPER_END
}
+void SkCanvas::onDrawTextBlob(const SkTextBlob* blob, SkScalar x, SkScalar y,
+ const SkPaint& paint) {
+
+ // FIXME: temporarily disable quickreject for empty bounds,
+ // pending implicit blob bounds implementation.
+ if (!blob->bounds().isEmpty() && paint.canComputeFastBounds()) {
+ SkRect storage;
+
+ if (this->quickReject(paint.computeFastBounds(blob->bounds().makeOffset(x, y), &storage))) {
+ return;
+ }
+ }
+
+ LOOPER_BEGIN(paint, SkDrawFilter::kText_Type, NULL)
+
+ while (iter.next()) {
+ SkDeviceFilteredPaint dfp(iter.fDevice, looper.paint());
+ iter.fDevice->drawTextBlob(iter, blob, x, y, dfp.paint());
+ }
+
+ LOOPER_END
+}
+
// These will become non-virtual, so they always call the (virtual) onDraw... method
void SkCanvas::drawText(const void* text, size_t byteLength, SkScalar x, SkScalar y,
const SkPaint& paint) {
const SkMatrix* matrix, const SkPaint& paint) {
this->onDrawTextOnPath(text, byteLength, path, matrix, paint);
}
+void SkCanvas::drawTextBlob(const SkTextBlob* blob, SkScalar x, SkScalar y,
+ const SkPaint& paint) {
+ if (blob) {
+ this->onDrawTextBlob(blob, x, y, paint);
+ }
+}
void SkCanvas::drawVertices(VertexMode vmode, int vertexCount,
const SkPoint verts[], const SkPoint texs[],
///////////////////////////////////////////////////////////////////////////////
void SkCanvas::EXPERIMENTAL_optimize(const SkPicture* picture) {
SkBaseDevice* device = this->getDevice();
- if (NULL != device) {
+ if (device) {
device->EXPERIMENTAL_optimize(picture);
}
}
void SkCanvas::drawPicture(const SkPicture* picture) {
- if (NULL != picture) {
+ if (picture) {
this->onDrawPicture(picture, NULL, NULL);
}
}
void SkCanvas::drawPicture(const SkPicture* picture, const SkMatrix* matrix, const SkPaint* paint) {
- if (NULL != picture) {
+ if (picture) {
if (matrix && matrix->isIdentity()) {
matrix = NULL;
}
void SkCanvas::onDrawPicture(const SkPicture* picture, const SkMatrix* matrix,
const SkPaint* paint) {
SkBaseDevice* device = this->getTopDevice();
- if (NULL != device) {
+ if (device) {
// Canvas has to first give the device the opportunity to render
// the picture itself.
if (device->EXPERIMENTAL_drawPicture(this, picture, matrix, paint)) {
}
}
- SkAutoCanvasMatrixPaint acmp(this, matrix, paint, picture->width(), picture->height());
+ SkAutoCanvasMatrixPaint acmp(this, matrix, paint, picture->cullRect());
- picture->draw(this);
+ picture->playback(this);
}
///////////////////////////////////////////////////////////////////////////////
}
SkBitmap bitmap;
- if (!bitmap.allocPixels(info)) {
+ if (!bitmap.tryAllocPixels(info)) {
return NULL;
}
///////////////////////////////////////////////////////////////////////////////
SkAutoCanvasMatrixPaint::SkAutoCanvasMatrixPaint(SkCanvas* canvas, const SkMatrix* matrix,
- const SkPaint* paint, int width, int height)
+ const SkPaint* paint, const SkRect& bounds)
: fCanvas(canvas)
, fSaveCount(canvas->getSaveCount())
{
- if (NULL != paint) {
- SkRect bounds = SkRect::MakeWH(SkIntToScalar(width), SkIntToScalar(height));
+ if (paint) {
+ SkRect newBounds = bounds;
if (matrix) {
- matrix->mapRect(&bounds);
+ matrix->mapRect(&newBounds);
}
- canvas->saveLayer(&bounds, paint);
- } else if (NULL != matrix) {
+ canvas->saveLayer(&newBounds, paint);
+ } else if (matrix) {
canvas->save();
}
- if (NULL != matrix) {
+ if (matrix) {
canvas->concat(*matrix);
}
}