1
2 /*
3 * Copyright 2008 The Android Open Source Project
4 *
5 * Use of this source code is governed by a BSD-style license that can be
6 * found in the LICENSE file.
7 */
8
9
10 #include "SkCanvas.h"
11 #include "SkBounder.h"
12 #include "SkDevice.h"
13 #include "SkDeviceImageFilterProxy.h"
14 #include "SkDraw.h"
15 #include "SkDrawFilter.h"
16 #include "SkDrawLooper.h"
17 #include "SkMetaData.h"
18 #include "SkPicture.h"
19 #include "SkRasterClip.h"
20 #include "SkRRect.h"
21 #include "SkScalarCompare.h"
22 #include "SkSurface_Base.h"
23 #include "SkTemplates.h"
24 #include "SkTextFormatParams.h"
25 #include "SkTLazy.h"
26 #include "SkUtils.h"
27
28 SK_DEFINE_INST_COUNT(SkBounder)
29 SK_DEFINE_INST_COUNT(SkCanvas)
30 SK_DEFINE_INST_COUNT(SkDrawFilter)
31
32 // experimental for faster tiled drawing...
33 //#define SK_ENABLE_CLIP_QUICKREJECT
34
35 //#define SK_TRACE_SAVERESTORE
36
37 #ifdef SK_TRACE_SAVERESTORE
38 static int gLayerCounter;
inc_layer()39 static void inc_layer() { ++gLayerCounter; printf("----- inc layer %d\n", gLayerCounter); }
dec_layer()40 static void dec_layer() { --gLayerCounter; printf("----- dec layer %d\n", gLayerCounter); }
41
42 static int gRecCounter;
inc_rec()43 static void inc_rec() { ++gRecCounter; printf("----- inc rec %d\n", gRecCounter); }
dec_rec()44 static void dec_rec() { --gRecCounter; printf("----- dec rec %d\n", gRecCounter); }
45
46 static int gCanvasCounter;
inc_canvas()47 static void inc_canvas() { ++gCanvasCounter; printf("----- inc canvas %d\n", gCanvasCounter); }
dec_canvas()48 static void dec_canvas() { --gCanvasCounter; printf("----- dec canvas %d\n", gCanvasCounter); }
49 #else
50 #define inc_layer()
51 #define dec_layer()
52 #define inc_rec()
53 #define dec_rec()
54 #define inc_canvas()
55 #define dec_canvas()
56 #endif
57
58 #ifdef SK_DEBUG
59 #include "SkPixelRef.h"
60
61 /*
62 * Some pixelref subclasses can support being "locked" from another thread
63 * during the lock-scope of skia calling them. In these instances, this balance
64 * check will fail, but may not be indicative of a problem, so we allow a build
65 * flag to disable this check.
66 *
67 * Potentially another fix would be to have a (debug-only) virtual or flag on
68 * pixelref, which could tell us at runtime if this check is valid. That would
69 * eliminate the need for this heavy-handed build check.
70 */
71 #ifdef SK_DISABLE_PIXELREF_LOCKCOUNT_BALANCE_CHECK
72 class AutoCheckLockCountBalance {
73 public:
AutoCheckLockCountBalance(const SkBitmap &)74 AutoCheckLockCountBalance(const SkBitmap&) { /* do nothing */ }
75 };
76 #else
77 class AutoCheckLockCountBalance {
78 public:
AutoCheckLockCountBalance(const SkBitmap & bm)79 AutoCheckLockCountBalance(const SkBitmap& bm) : fPixelRef(bm.pixelRef()) {
80 fLockCount = fPixelRef ? fPixelRef->getLockCount() : 0;
81 }
~AutoCheckLockCountBalance()82 ~AutoCheckLockCountBalance() {
83 const int count = fPixelRef ? fPixelRef->getLockCount() : 0;
84 SkASSERT(count == fLockCount);
85 }
86
87 private:
88 const SkPixelRef* fPixelRef;
89 int fLockCount;
90 };
91 #endif
92
93 class AutoCheckNoSetContext {
94 public:
AutoCheckNoSetContext(const SkPaint & paint)95 AutoCheckNoSetContext(const SkPaint& paint) : fPaint(paint) {
96 this->assertNoSetContext(fPaint);
97 }
~AutoCheckNoSetContext()98 ~AutoCheckNoSetContext() {
99 this->assertNoSetContext(fPaint);
100 }
101
102 private:
103 const SkPaint& fPaint;
104
assertNoSetContext(const SkPaint & paint)105 void assertNoSetContext(const SkPaint& paint) {
106 SkShader* s = paint.getShader();
107 if (s) {
108 SkASSERT(!s->setContextHasBeenCalled());
109 }
110 }
111 };
112
113 #define CHECK_LOCKCOUNT_BALANCE(bitmap) AutoCheckLockCountBalance clcb(bitmap)
114 #define CHECK_SHADER_NOSETCONTEXT(paint) AutoCheckNoSetContext cshsc(paint)
115
116 #else
117 #define CHECK_LOCKCOUNT_BALANCE(bitmap)
118 #define CHECK_SHADER_NOSETCONTEXT(paint)
119 #endif
120
121 typedef SkTLazy<SkPaint> SkLazyPaint;
122
predrawNotify()123 void SkCanvas::predrawNotify() {
124 if (fSurfaceBase) {
125 fSurfaceBase->aboutToDraw(this);
126 }
127 }
128
129 ///////////////////////////////////////////////////////////////////////////////
130
131 /* This is the record we keep for each SkDevice that the user installs.
132 The clip/matrix/proc are fields that reflect the top of the save/restore
133 stack. Whenever the canvas changes, it marks a dirty flag, and then before
134 these are used (assuming we're not on a layer) we rebuild these cache
135 values: they reflect the top of the save stack, but translated and clipped
136 by the device's XY offset and bitmap-bounds.
137 */
138 struct DeviceCM {
139 DeviceCM* fNext;
140 SkDevice* fDevice;
141 SkRasterClip fClip;
142 const SkMatrix* fMatrix;
143 SkPaint* fPaint; // may be null (in the future)
144
DeviceCMDeviceCM145 DeviceCM(SkDevice* device, int x, int y, const SkPaint* paint, SkCanvas* canvas)
146 : fNext(NULL) {
147 if (NULL != device) {
148 device->ref();
149 device->onAttachToCanvas(canvas);
150 }
151 fDevice = device;
152 fPaint = paint ? SkNEW_ARGS(SkPaint, (*paint)) : NULL;
153 }
154
~DeviceCMDeviceCM155 ~DeviceCM() {
156 if (NULL != fDevice) {
157 fDevice->onDetachFromCanvas();
158 fDevice->unref();
159 }
160 SkDELETE(fPaint);
161 }
162
updateMCDeviceCM163 void updateMC(const SkMatrix& totalMatrix, const SkRasterClip& totalClip,
164 const SkClipStack& clipStack, SkRasterClip* updateClip) {
165 int x = fDevice->getOrigin().x();
166 int y = fDevice->getOrigin().y();
167 int width = fDevice->width();
168 int height = fDevice->height();
169
170 if ((x | y) == 0) {
171 fMatrix = &totalMatrix;
172 fClip = totalClip;
173 } else {
174 fMatrixStorage = totalMatrix;
175 fMatrixStorage.postTranslate(SkIntToScalar(-x),
176 SkIntToScalar(-y));
177 fMatrix = &fMatrixStorage;
178
179 totalClip.translate(-x, -y, &fClip);
180 }
181
182 fClip.op(SkIRect::MakeWH(width, height), SkRegion::kIntersect_Op);
183
184 // intersect clip, but don't translate it (yet)
185
186 if (updateClip) {
187 updateClip->op(SkIRect::MakeXYWH(x, y, width, height),
188 SkRegion::kDifference_Op);
189 }
190
191 fDevice->setMatrixClip(*fMatrix, fClip.forceGetBW(), clipStack);
192
193 #ifdef SK_DEBUG
194 if (!fClip.isEmpty()) {
195 SkIRect deviceR;
196 deviceR.set(0, 0, width, height);
197 SkASSERT(deviceR.contains(fClip.getBounds()));
198 }
199 #endif
200 }
201
202 private:
203 SkMatrix fMatrixStorage;
204 };
205
206 /* This is the record we keep for each save/restore level in the stack.
207 Since a level optionally copies the matrix and/or stack, we have pointers
208 for these fields. If the value is copied for this level, the copy is
209 stored in the ...Storage field, and the pointer points to that. If the
210 value is not copied for this level, we ignore ...Storage, and just point
211 at the corresponding value in the previous level in the stack.
212 */
213 class SkCanvas::MCRec {
214 public:
215 MCRec* fNext;
216 SkMatrix* fMatrix; // points to either fMatrixStorage or prev MCRec
217 SkRasterClip* fRasterClip; // points to either fRegionStorage or prev MCRec
218 SkDrawFilter* fFilter; // the current filter (or null)
219
220 DeviceCM* fLayer;
221 /* If there are any layers in the stack, this points to the top-most
222 one that is at or below this level in the stack (so we know what
223 bitmap/device to draw into from this level. This value is NOT
224 reference counted, since the real owner is either our fLayer field,
225 or a previous one in a lower level.)
226 */
227 DeviceCM* fTopLayer;
228
MCRec(const MCRec * prev,int flags)229 MCRec(const MCRec* prev, int flags) {
230 if (NULL != prev) {
231 if (flags & SkCanvas::kMatrix_SaveFlag) {
232 fMatrixStorage = *prev->fMatrix;
233 fMatrix = &fMatrixStorage;
234 } else {
235 fMatrix = prev->fMatrix;
236 }
237
238 if (flags & SkCanvas::kClip_SaveFlag) {
239 fRasterClipStorage = *prev->fRasterClip;
240 fRasterClip = &fRasterClipStorage;
241 } else {
242 fRasterClip = prev->fRasterClip;
243 }
244
245 fFilter = prev->fFilter;
246 SkSafeRef(fFilter);
247
248 fTopLayer = prev->fTopLayer;
249 } else { // no prev
250 fMatrixStorage.reset();
251
252 fMatrix = &fMatrixStorage;
253 fRasterClip = &fRasterClipStorage;
254 fFilter = NULL;
255 fTopLayer = NULL;
256 }
257 fLayer = NULL;
258
259 // don't bother initializing fNext
260 inc_rec();
261 }
~MCRec()262 ~MCRec() {
263 SkSafeUnref(fFilter);
264 SkDELETE(fLayer);
265 dec_rec();
266 }
267
268 private:
269 SkMatrix fMatrixStorage;
270 SkRasterClip fRasterClipStorage;
271 };
272
273 class SkDrawIter : public SkDraw {
274 public:
SkDrawIter(SkCanvas * canvas,bool skipEmptyClips=true)275 SkDrawIter(SkCanvas* canvas, bool skipEmptyClips = true) {
276 canvas = canvas->canvasForDrawIter();
277 fCanvas = canvas;
278 canvas->updateDeviceCMCache();
279
280 fClipStack = &canvas->fClipStack;
281 fBounder = canvas->getBounder();
282 fCurrLayer = canvas->fMCRec->fTopLayer;
283 fSkipEmptyClips = skipEmptyClips;
284 }
285
next()286 bool next() {
287 // skip over recs with empty clips
288 if (fSkipEmptyClips) {
289 while (fCurrLayer && fCurrLayer->fClip.isEmpty()) {
290 fCurrLayer = fCurrLayer->fNext;
291 }
292 }
293
294 const DeviceCM* rec = fCurrLayer;
295 if (rec && rec->fDevice) {
296
297 fMatrix = rec->fMatrix;
298 fClip = &((SkRasterClip*)&rec->fClip)->forceGetBW();
299 fRC = &rec->fClip;
300 fDevice = rec->fDevice;
301 fBitmap = &fDevice->accessBitmap(true);
302 fPaint = rec->fPaint;
303 SkDEBUGCODE(this->validate();)
304
305 fCurrLayer = rec->fNext;
306 if (fBounder) {
307 fBounder->setClip(fClip);
308 }
309 // fCurrLayer may be NULL now
310
311 return true;
312 }
313 return false;
314 }
315
getDevice() const316 SkDevice* getDevice() const { return fDevice; }
getX() const317 int getX() const { return fDevice->getOrigin().x(); }
getY() const318 int getY() const { return fDevice->getOrigin().y(); }
getMatrix() const319 const SkMatrix& getMatrix() const { return *fMatrix; }
getClip() const320 const SkRegion& getClip() const { return *fClip; }
getPaint() const321 const SkPaint* getPaint() const { return fPaint; }
322
323 private:
324 SkCanvas* fCanvas;
325 const DeviceCM* fCurrLayer;
326 const SkPaint* fPaint; // May be null.
327 SkBool8 fSkipEmptyClips;
328
329 typedef SkDraw INHERITED;
330 };
331
332 /////////////////////////////////////////////////////////////////////////////
333
334 class AutoDrawLooper {
335 public:
AutoDrawLooper(SkCanvas * canvas,const SkPaint & paint,bool skipLayerForImageFilter=false)336 AutoDrawLooper(SkCanvas* canvas, const SkPaint& paint,
337 bool skipLayerForImageFilter = false) : fOrigPaint(paint) {
338 fCanvas = canvas;
339 fLooper = paint.getLooper();
340 fFilter = canvas->getDrawFilter();
341 fPaint = NULL;
342 fSaveCount = canvas->getSaveCount();
343 fDoClearImageFilter = false;
344 fDone = false;
345
346 if (!skipLayerForImageFilter && fOrigPaint.getImageFilter()) {
347 SkPaint tmp;
348 tmp.setImageFilter(fOrigPaint.getImageFilter());
349 // it would be nice if we had a guess at the bounds, instead of null
350 (void)canvas->internalSaveLayer(NULL, &tmp,
351 SkCanvas::kARGB_ClipLayer_SaveFlag, true);
352 // we'll clear the imageFilter for the actual draws in next(), so
353 // it will only be applied during the restore().
354 fDoClearImageFilter = true;
355 }
356
357 if (fLooper) {
358 fLooper->init(canvas);
359 fIsSimple = false;
360 } else {
361 // can we be marked as simple?
362 fIsSimple = !fFilter && !fDoClearImageFilter;
363 }
364 }
365
~AutoDrawLooper()366 ~AutoDrawLooper() {
367 if (fDoClearImageFilter) {
368 fCanvas->internalRestore();
369 }
370 SkASSERT(fCanvas->getSaveCount() == fSaveCount);
371 }
372
paint() const373 const SkPaint& paint() const {
374 SkASSERT(fPaint);
375 return *fPaint;
376 }
377
next(SkDrawFilter::Type drawType)378 bool next(SkDrawFilter::Type drawType) {
379 if (fDone) {
380 return false;
381 } else if (fIsSimple) {
382 fDone = true;
383 fPaint = &fOrigPaint;
384 return !fPaint->nothingToDraw();
385 } else {
386 return this->doNext(drawType);
387 }
388 }
389
390 private:
391 SkLazyPaint fLazyPaint;
392 SkCanvas* fCanvas;
393 const SkPaint& fOrigPaint;
394 SkDrawLooper* fLooper;
395 SkDrawFilter* fFilter;
396 const SkPaint* fPaint;
397 int fSaveCount;
398 bool fDoClearImageFilter;
399 bool fDone;
400 bool fIsSimple;
401
402 bool doNext(SkDrawFilter::Type drawType);
403 };
404
doNext(SkDrawFilter::Type drawType)405 bool AutoDrawLooper::doNext(SkDrawFilter::Type drawType) {
406 fPaint = NULL;
407 SkASSERT(!fIsSimple);
408 SkASSERT(fLooper || fFilter || fDoClearImageFilter);
409
410 SkPaint* paint = fLazyPaint.set(fOrigPaint);
411
412 if (fDoClearImageFilter) {
413 paint->setImageFilter(NULL);
414 }
415
416 if (fLooper && !fLooper->next(fCanvas, paint)) {
417 fDone = true;
418 return false;
419 }
420 if (fFilter) {
421 if (!fFilter->filter(paint, drawType)) {
422 fDone = true;
423 return false;
424 }
425 if (NULL == fLooper) {
426 // no looper means we only draw once
427 fDone = true;
428 }
429 }
430 fPaint = paint;
431
432 // if we only came in here for the imagefilter, mark us as done
433 if (!fLooper && !fFilter) {
434 fDone = true;
435 }
436
437 // call this after any possible paint modifiers
438 if (fPaint->nothingToDraw()) {
439 fPaint = NULL;
440 return false;
441 }
442 return true;
443 }
444
445 /* Stack helper for managing a SkBounder. In the destructor, if we were
446 given a bounder, we call its commit() method, signifying that we are
447 done accumulating bounds for that draw.
448 */
449 class SkAutoBounderCommit {
450 public:
SkAutoBounderCommit(SkBounder * bounder)451 SkAutoBounderCommit(SkBounder* bounder) : fBounder(bounder) {}
~SkAutoBounderCommit()452 ~SkAutoBounderCommit() {
453 if (NULL != fBounder) {
454 fBounder->commit();
455 }
456 }
457 private:
458 SkBounder* fBounder;
459 };
460
461 #include "SkColorPriv.h"
462
463 class AutoValidator {
464 public:
AutoValidator(SkDevice * device)465 AutoValidator(SkDevice* device) : fDevice(device) {}
~AutoValidator()466 ~AutoValidator() {
467 #ifdef SK_DEBUG
468 const SkBitmap& bm = fDevice->accessBitmap(false);
469 if (bm.config() == SkBitmap::kARGB_4444_Config) {
470 for (int y = 0; y < bm.height(); y++) {
471 const SkPMColor16* p = bm.getAddr16(0, y);
472 for (int x = 0; x < bm.width(); x++) {
473 SkPMColor16 c = p[x];
474 SkPMColor16Assert(c);
475 }
476 }
477 }
478 #endif
479 }
480 private:
481 SkDevice* fDevice;
482 };
483
484 ////////// macros to place around the internal draw calls //////////////////
485
486 #define LOOPER_BEGIN_DRAWDEVICE(paint, type) \
487 /* AutoValidator validator(fMCRec->fTopLayer->fDevice); */ \
488 this->predrawNotify(); \
489 AutoDrawLooper looper(this, paint, true); \
490 while (looper.next(type)) { \
491 SkAutoBounderCommit ac(fBounder); \
492 SkDrawIter iter(this);
493
494 #define LOOPER_BEGIN(paint, type) \
495 /* AutoValidator validator(fMCRec->fTopLayer->fDevice); */ \
496 this->predrawNotify(); \
497 AutoDrawLooper looper(this, paint); \
498 while (looper.next(type)) { \
499 SkAutoBounderCommit ac(fBounder); \
500 SkDrawIter iter(this);
501
502 #define LOOPER_END }
503
504 ////////////////////////////////////////////////////////////////////////////
505
init(SkDevice * device)506 SkDevice* SkCanvas::init(SkDevice* device) {
507 fBounder = NULL;
508 fLocalBoundsCompareType.setEmpty();
509 fLocalBoundsCompareTypeDirty = true;
510 fAllowSoftClip = true;
511 fDeviceCMDirty = false;
512 fSaveLayerCount = 0;
513 fMetaData = NULL;
514
515 fMCRec = (MCRec*)fMCStack.push_back();
516 new (fMCRec) MCRec(NULL, 0);
517
518 fMCRec->fLayer = SkNEW_ARGS(DeviceCM, (NULL, 0, 0, NULL, NULL));
519 fMCRec->fTopLayer = fMCRec->fLayer;
520 fMCRec->fNext = NULL;
521
522 fSurfaceBase = NULL;
523
524 return this->setDevice(device);
525 }
526
SkCanvas()527 SkCanvas::SkCanvas()
528 : fMCStack(sizeof(MCRec), fMCRecStorage, sizeof(fMCRecStorage)) {
529 inc_canvas();
530
531 this->init(NULL);
532 }
533
SkCanvas(SkDevice * device)534 SkCanvas::SkCanvas(SkDevice* device)
535 : fMCStack(sizeof(MCRec), fMCRecStorage, sizeof(fMCRecStorage)) {
536 inc_canvas();
537
538 this->init(device);
539 }
540
SkCanvas(const SkBitmap & bitmap)541 SkCanvas::SkCanvas(const SkBitmap& bitmap)
542 : fMCStack(sizeof(MCRec), fMCRecStorage, sizeof(fMCRecStorage)) {
543 inc_canvas();
544
545 this->init(SkNEW_ARGS(SkDevice, (bitmap)))->unref();
546 }
547
~SkCanvas()548 SkCanvas::~SkCanvas() {
549 // free up the contents of our deque
550 this->restoreToCount(1); // restore everything but the last
551 SkASSERT(0 == fSaveLayerCount);
552
553 this->internalRestore(); // restore the last, since we're going away
554
555 SkSafeUnref(fBounder);
556 SkDELETE(fMetaData);
557
558 dec_canvas();
559 }
560
setBounder(SkBounder * bounder)561 SkBounder* SkCanvas::setBounder(SkBounder* bounder) {
562 SkRefCnt_SafeAssign(fBounder, bounder);
563 return bounder;
564 }
565
getDrawFilter() const566 SkDrawFilter* SkCanvas::getDrawFilter() const {
567 return fMCRec->fFilter;
568 }
569
setDrawFilter(SkDrawFilter * filter)570 SkDrawFilter* SkCanvas::setDrawFilter(SkDrawFilter* filter) {
571 SkRefCnt_SafeAssign(fMCRec->fFilter, filter);
572 return filter;
573 }
574
getMetaData()575 SkMetaData& SkCanvas::getMetaData() {
576 // metadata users are rare, so we lazily allocate it. If that changes we
577 // can decide to just make it a field in the device (rather than a ptr)
578 if (NULL == fMetaData) {
579 fMetaData = new SkMetaData;
580 }
581 return *fMetaData;
582 }
583
584 ///////////////////////////////////////////////////////////////////////////////
585
flush()586 void SkCanvas::flush() {
587 SkDevice* device = this->getDevice();
588 if (device) {
589 device->flush();
590 }
591 }
592
getDeviceSize() const593 SkISize SkCanvas::getDeviceSize() const {
594 SkDevice* d = this->getDevice();
595 return d ? SkISize::Make(d->width(), d->height()) : SkISize::Make(0, 0);
596 }
597
getDevice() const598 SkDevice* SkCanvas::getDevice() const {
599 // return root device
600 MCRec* rec = (MCRec*) fMCStack.front();
601 SkASSERT(rec && rec->fLayer);
602 return rec->fLayer->fDevice;
603 }
604
getTopDevice(bool updateMatrixClip) const605 SkDevice* SkCanvas::getTopDevice(bool updateMatrixClip) const {
606 if (updateMatrixClip) {
607 const_cast<SkCanvas*>(this)->updateDeviceCMCache();
608 }
609 return fMCRec->fTopLayer->fDevice;
610 }
611
setDevice(SkDevice * device)612 SkDevice* SkCanvas::setDevice(SkDevice* device) {
613 // return root device
614 SkDeque::F2BIter iter(fMCStack);
615 MCRec* rec = (MCRec*)iter.next();
616 SkASSERT(rec && rec->fLayer);
617 SkDevice* rootDevice = rec->fLayer->fDevice;
618
619 if (rootDevice == device) {
620 return device;
621 }
622
623 if (device) {
624 device->onAttachToCanvas(this);
625 }
626 if (rootDevice) {
627 rootDevice->onDetachFromCanvas();
628 }
629
630 SkRefCnt_SafeAssign(rec->fLayer->fDevice, device);
631 rootDevice = device;
632
633 fDeviceCMDirty = true;
634
635 /* Now we update our initial region to have the bounds of the new device,
636 and then intersect all of the clips in our stack with these bounds,
637 to ensure that we can't draw outside of the device's bounds (and trash
638 memory).
639
640 NOTE: this is only a partial-fix, since if the new device is larger than
641 the previous one, we don't know how to "enlarge" the clips in our stack,
642 so drawing may be artificially restricted. Without keeping a history of
643 all calls to canvas->clipRect() and canvas->clipPath(), we can't exactly
644 reconstruct the correct clips, so this approximation will have to do.
645 The caller really needs to restore() back to the base if they want to
646 accurately take advantage of the new device bounds.
647 */
648
649 SkIRect bounds;
650 if (device) {
651 bounds.set(0, 0, device->width(), device->height());
652 } else {
653 bounds.setEmpty();
654 }
655 // now jam our 1st clip to be bounds, and intersect the rest with that
656 rec->fRasterClip->setRect(bounds);
657 while ((rec = (MCRec*)iter.next()) != NULL) {
658 (void)rec->fRasterClip->op(bounds, SkRegion::kIntersect_Op);
659 }
660
661 return device;
662 }
663
readPixels(SkBitmap * bitmap,int x,int y,Config8888 config8888)664 bool SkCanvas::readPixels(SkBitmap* bitmap,
665 int x, int y,
666 Config8888 config8888) {
667 SkDevice* device = this->getDevice();
668 if (!device) {
669 return false;
670 }
671 return device->readPixels(bitmap, x, y, config8888);
672 }
673
readPixels(const SkIRect & srcRect,SkBitmap * bitmap)674 bool SkCanvas::readPixels(const SkIRect& srcRect, SkBitmap* bitmap) {
675 SkDevice* device = this->getDevice();
676 if (!device) {
677 return false;
678 }
679
680 SkIRect bounds;
681 bounds.set(0, 0, device->width(), device->height());
682 if (!bounds.intersect(srcRect)) {
683 return false;
684 }
685
686 SkBitmap tmp;
687 tmp.setConfig(SkBitmap::kARGB_8888_Config, bounds.width(),
688 bounds.height());
689 if (this->readPixels(&tmp, bounds.fLeft, bounds.fTop)) {
690 bitmap->swap(tmp);
691 return true;
692 } else {
693 return false;
694 }
695 }
696
writePixels(const SkBitmap & bitmap,int x,int y,Config8888 config8888)697 void SkCanvas::writePixels(const SkBitmap& bitmap, int x, int y,
698 Config8888 config8888) {
699 SkDevice* device = this->getDevice();
700 if (device) {
701 if (SkIRect::Intersects(SkIRect::MakeSize(this->getDeviceSize()),
702 SkIRect::MakeXYWH(x, y, bitmap.width(), bitmap.height()))) {
703 device->accessBitmap(true);
704 device->writePixels(bitmap, x, y, config8888);
705 }
706 }
707 }
708
canvasForDrawIter()709 SkCanvas* SkCanvas::canvasForDrawIter() {
710 return this;
711 }
712
713 //////////////////////////////////////////////////////////////////////////////
714
updateDeviceCMCache()715 void SkCanvas::updateDeviceCMCache() {
716 if (fDeviceCMDirty) {
717 const SkMatrix& totalMatrix = this->getTotalMatrix();
718 const SkRasterClip& totalClip = *fMCRec->fRasterClip;
719 DeviceCM* layer = fMCRec->fTopLayer;
720
721 if (NULL == layer->fNext) { // only one layer
722 layer->updateMC(totalMatrix, totalClip, fClipStack, NULL);
723 } else {
724 SkRasterClip clip(totalClip);
725 do {
726 layer->updateMC(totalMatrix, clip, fClipStack, &clip);
727 } while ((layer = layer->fNext) != NULL);
728 }
729 fDeviceCMDirty = false;
730 }
731 }
732
733 ///////////////////////////////////////////////////////////////////////////////
734
internalSave(SaveFlags flags)735 int SkCanvas::internalSave(SaveFlags flags) {
736 int saveCount = this->getSaveCount(); // record this before the actual save
737
738 MCRec* newTop = (MCRec*)fMCStack.push_back();
739 new (newTop) MCRec(fMCRec, flags); // balanced in restore()
740
741 newTop->fNext = fMCRec;
742 fMCRec = newTop;
743
744 fClipStack.save();
745 SkASSERT(fClipStack.getSaveCount() == this->getSaveCount() - 1);
746
747 return saveCount;
748 }
749
save(SaveFlags flags)750 int SkCanvas::save(SaveFlags flags) {
751 // call shared impl
752 return this->internalSave(flags);
753 }
754
755 #define C32MASK (1 << SkBitmap::kARGB_8888_Config)
756 #define C16MASK (1 << SkBitmap::kRGB_565_Config)
757 #define C8MASK (1 << SkBitmap::kA8_Config)
758
resolve_config(SkCanvas * canvas,const SkIRect & bounds,SkCanvas::SaveFlags flags,bool * isOpaque)759 static SkBitmap::Config resolve_config(SkCanvas* canvas,
760 const SkIRect& bounds,
761 SkCanvas::SaveFlags flags,
762 bool* isOpaque) {
763 *isOpaque = (flags & SkCanvas::kHasAlphaLayer_SaveFlag) == 0;
764
765 #if 0
766 // loop through and union all the configs we may draw into
767 uint32_t configMask = 0;
768 for (int i = canvas->countLayerDevices() - 1; i >= 0; --i)
769 {
770 SkDevice* device = canvas->getLayerDevice(i);
771 if (device->intersects(bounds))
772 configMask |= 1 << device->config();
773 }
774
775 // if the caller wants alpha or fullcolor, we can't return 565
776 if (flags & (SkCanvas::kFullColorLayer_SaveFlag |
777 SkCanvas::kHasAlphaLayer_SaveFlag))
778 configMask &= ~C16MASK;
779
780 switch (configMask) {
781 case C8MASK: // if we only have A8, return that
782 return SkBitmap::kA8_Config;
783
784 case C16MASK: // if we only have 565, return that
785 return SkBitmap::kRGB_565_Config;
786
787 default:
788 return SkBitmap::kARGB_8888_Config; // default answer
789 }
790 #else
791 return SkBitmap::kARGB_8888_Config; // default answer
792 #endif
793 }
794
bounds_affects_clip(SkCanvas::SaveFlags flags)795 static bool bounds_affects_clip(SkCanvas::SaveFlags flags) {
796 return (flags & SkCanvas::kClipToLayer_SaveFlag) != 0;
797 }
798
clipRectBounds(const SkRect * bounds,SaveFlags flags,SkIRect * intersection)799 bool SkCanvas::clipRectBounds(const SkRect* bounds, SaveFlags flags,
800 SkIRect* intersection) {
801 SkIRect clipBounds;
802 if (!this->getClipDeviceBounds(&clipBounds)) {
803 return false;
804 }
805 SkIRect ir;
806 if (NULL != bounds) {
807 SkRect r;
808
809 this->getTotalMatrix().mapRect(&r, *bounds);
810 r.roundOut(&ir);
811 // early exit if the layer's bounds are clipped out
812 if (!ir.intersect(clipBounds)) {
813 if (bounds_affects_clip(flags)) {
814 fMCRec->fRasterClip->setEmpty();
815 }
816 return false;
817 }
818 } else { // no user bounds, so just use the clip
819 ir = clipBounds;
820 }
821
822 fClipStack.clipDevRect(ir, SkRegion::kIntersect_Op);
823
824 // early exit if the clip is now empty
825 if (bounds_affects_clip(flags) &&
826 !fMCRec->fRasterClip->op(ir, SkRegion::kIntersect_Op)) {
827 return false;
828 }
829
830 if (intersection) {
831 *intersection = ir;
832 }
833 return true;
834 }
835
saveLayer(const SkRect * bounds,const SkPaint * paint,SaveFlags flags)836 int SkCanvas::saveLayer(const SkRect* bounds, const SkPaint* paint,
837 SaveFlags flags) {
838 return this->internalSaveLayer(bounds, paint, flags, false);
839 }
840
internalSaveLayer(const SkRect * bounds,const SkPaint * paint,SaveFlags flags,bool justForImageFilter)841 int SkCanvas::internalSaveLayer(const SkRect* bounds, const SkPaint* paint,
842 SaveFlags flags, bool justForImageFilter) {
843 // do this before we create the layer. We don't call the public save() since
844 // that would invoke a possibly overridden virtual
845 int count = this->internalSave(flags);
846
847 fDeviceCMDirty = true;
848
849 SkIRect ir;
850 if (!this->clipRectBounds(bounds, flags, &ir)) {
851 return count;
852 }
853
854 // Kill the imagefilter if our device doesn't allow it
855 SkLazyPaint lazyP;
856 if (paint && paint->getImageFilter()) {
857 if (!this->getTopDevice()->allowImageFilter(paint->getImageFilter())) {
858 if (justForImageFilter) {
859 // early exit if the layer was just for the imageFilter
860 return count;
861 }
862 SkPaint* p = lazyP.set(*paint);
863 p->setImageFilter(NULL);
864 paint = p;
865 }
866 }
867
868 bool isOpaque;
869 SkBitmap::Config config = resolve_config(this, ir, flags, &isOpaque);
870
871 SkDevice* device;
872 if (paint && paint->getImageFilter()) {
873 device = this->createCompatibleDevice(config, ir.width(), ir.height(),
874 isOpaque);
875 } else {
876 device = this->createLayerDevice(config, ir.width(), ir.height(),
877 isOpaque);
878 }
879 if (NULL == device) {
880 SkDebugf("Unable to create device for layer.");
881 return count;
882 }
883
884 device->setOrigin(ir.fLeft, ir.fTop);
885 DeviceCM* layer = SkNEW_ARGS(DeviceCM, (device, ir.fLeft, ir.fTop, paint, this));
886 device->unref();
887
888 layer->fNext = fMCRec->fTopLayer;
889 fMCRec->fLayer = layer;
890 fMCRec->fTopLayer = layer; // this field is NOT an owner of layer
891
892 fSaveLayerCount += 1;
893 return count;
894 }
895
saveLayerAlpha(const SkRect * bounds,U8CPU alpha,SaveFlags flags)896 int SkCanvas::saveLayerAlpha(const SkRect* bounds, U8CPU alpha,
897 SaveFlags flags) {
898 if (0xFF == alpha) {
899 return this->saveLayer(bounds, NULL, flags);
900 } else {
901 SkPaint tmpPaint;
902 tmpPaint.setAlpha(alpha);
903 return this->saveLayer(bounds, &tmpPaint, flags);
904 }
905 }
906
restore()907 void SkCanvas::restore() {
908 // check for underflow
909 if (fMCStack.count() > 1) {
910 this->internalRestore();
911 }
912 }
913
internalRestore()914 void SkCanvas::internalRestore() {
915 SkASSERT(fMCStack.count() != 0);
916
917 fDeviceCMDirty = true;
918 fLocalBoundsCompareTypeDirty = true;
919
920 fClipStack.restore();
921 // reserve our layer (if any)
922 DeviceCM* layer = fMCRec->fLayer; // may be null
923 // now detach it from fMCRec so we can pop(). Gets freed after its drawn
924 fMCRec->fLayer = NULL;
925
926 // now do the normal restore()
927 fMCRec->~MCRec(); // balanced in save()
928 fMCStack.pop_back();
929 fMCRec = (MCRec*)fMCStack.back();
930
931 /* Time to draw the layer's offscreen. We can't call the public drawSprite,
932 since if we're being recorded, we don't want to record this (the
933 recorder will have already recorded the restore).
934 */
935 if (NULL != layer) {
936 if (layer->fNext) {
937 const SkIPoint& origin = layer->fDevice->getOrigin();
938 this->internalDrawDevice(layer->fDevice, origin.x(), origin.y(),
939 layer->fPaint);
940 // reset this, since internalDrawDevice will have set it to true
941 fDeviceCMDirty = true;
942
943 SkASSERT(fSaveLayerCount > 0);
944 fSaveLayerCount -= 1;
945 }
946 SkDELETE(layer);
947 }
948
949 SkASSERT(fClipStack.getSaveCount() == this->getSaveCount() - 1);
950 }
951
getSaveCount() const952 int SkCanvas::getSaveCount() const {
953 return fMCStack.count();
954 }
955
restoreToCount(int count)956 void SkCanvas::restoreToCount(int count) {
957 // sanity check
958 if (count < 1) {
959 count = 1;
960 }
961
962 int n = this->getSaveCount() - count;
963 for (int i = 0; i < n; ++i) {
964 this->restore();
965 }
966 }
967
isDrawingToLayer() const968 bool SkCanvas::isDrawingToLayer() const {
969 return fSaveLayerCount > 0;
970 }
971
972 /////////////////////////////////////////////////////////////////////////////
973
974 // can't draw it if its empty, or its too big for a fixed-point width or height
reject_bitmap(const SkBitmap & bitmap)975 static bool reject_bitmap(const SkBitmap& bitmap) {
976 return bitmap.width() <= 0 || bitmap.height() <= 0
977 #ifndef SK_ALLOW_OVER_32K_BITMAPS
978 || bitmap.width() > 32767 || bitmap.height() > 32767
979 #endif
980 ;
981 }
982
internalDrawBitmap(const SkBitmap & bitmap,const SkIRect * srcRect,const SkMatrix & matrix,const SkPaint * paint)983 void SkCanvas::internalDrawBitmap(const SkBitmap& bitmap, const SkIRect* srcRect,
984 const SkMatrix& matrix, const SkPaint* paint) {
985 if (reject_bitmap(bitmap)) {
986 return;
987 }
988
989 SkLazyPaint lazy;
990 if (NULL == paint) {
991 paint = lazy.init();
992 }
993 this->commonDrawBitmap(bitmap, srcRect, matrix, *paint);
994 }
995
internalDrawDevice(SkDevice * srcDev,int x,int y,const SkPaint * paint)996 void SkCanvas::internalDrawDevice(SkDevice* srcDev, int x, int y,
997 const SkPaint* paint) {
998 SkPaint tmp;
999 if (NULL == paint) {
1000 tmp.setDither(true);
1001 paint = &tmp;
1002 }
1003
1004 LOOPER_BEGIN_DRAWDEVICE(*paint, SkDrawFilter::kBitmap_Type)
1005 while (iter.next()) {
1006 SkDevice* dstDev = iter.fDevice;
1007 paint = &looper.paint();
1008 SkImageFilter* filter = paint->getImageFilter();
1009 SkIPoint pos = { x - iter.getX(), y - iter.getY() };
1010 if (filter && !dstDev->canHandleImageFilter(filter)) {
1011 SkDeviceImageFilterProxy proxy(dstDev);
1012 SkBitmap dst;
1013 const SkBitmap& src = srcDev->accessBitmap(false);
1014 if (filter->filterImage(&proxy, src, *iter.fMatrix, &dst, &pos)) {
1015 SkPaint tmpUnfiltered(*paint);
1016 tmpUnfiltered.setImageFilter(NULL);
1017 dstDev->drawSprite(iter, dst, pos.x(), pos.y(), tmpUnfiltered);
1018 }
1019 } else {
1020 dstDev->drawDevice(iter, srcDev, pos.x(), pos.y(), *paint);
1021 }
1022 }
1023 LOOPER_END
1024 }
1025
drawSprite(const SkBitmap & bitmap,int x,int y,const SkPaint * paint)1026 void SkCanvas::drawSprite(const SkBitmap& bitmap, int x, int y,
1027 const SkPaint* paint) {
1028 SkDEBUGCODE(bitmap.validate();)
1029 CHECK_LOCKCOUNT_BALANCE(bitmap);
1030
1031 if (reject_bitmap(bitmap)) {
1032 return;
1033 }
1034
1035 SkPaint tmp;
1036 if (NULL == paint) {
1037 paint = &tmp;
1038 }
1039
1040 LOOPER_BEGIN_DRAWDEVICE(*paint, SkDrawFilter::kBitmap_Type)
1041
1042 while (iter.next()) {
1043 paint = &looper.paint();
1044 SkImageFilter* filter = paint->getImageFilter();
1045 SkIPoint pos = { x - iter.getX(), y - iter.getY() };
1046 if (filter && !iter.fDevice->canHandleImageFilter(filter)) {
1047 SkDeviceImageFilterProxy proxy(iter.fDevice);
1048 SkBitmap dst;
1049 if (filter->filterImage(&proxy, bitmap, *iter.fMatrix,
1050 &dst, &pos)) {
1051 SkPaint tmpUnfiltered(*paint);
1052 tmpUnfiltered.setImageFilter(NULL);
1053 iter.fDevice->drawSprite(iter, dst, pos.x(), pos.y(),
1054 tmpUnfiltered);
1055 }
1056 } else {
1057 iter.fDevice->drawSprite(iter, bitmap, pos.x(), pos.y(), *paint);
1058 }
1059 }
1060 LOOPER_END
1061 }
1062
1063 /////////////////////////////////////////////////////////////////////////////
1064
translate(SkScalar dx,SkScalar dy)1065 bool SkCanvas::translate(SkScalar dx, SkScalar dy) {
1066 fDeviceCMDirty = true;
1067 fLocalBoundsCompareTypeDirty = true;
1068 return fMCRec->fMatrix->preTranslate(dx, dy);
1069 }
1070
scale(SkScalar sx,SkScalar sy)1071 bool SkCanvas::scale(SkScalar sx, SkScalar sy) {
1072 fDeviceCMDirty = true;
1073 fLocalBoundsCompareTypeDirty = true;
1074 return fMCRec->fMatrix->preScale(sx, sy);
1075 }
1076
rotate(SkScalar degrees)1077 bool SkCanvas::rotate(SkScalar degrees) {
1078 fDeviceCMDirty = true;
1079 fLocalBoundsCompareTypeDirty = true;
1080 return fMCRec->fMatrix->preRotate(degrees);
1081 }
1082
skew(SkScalar sx,SkScalar sy)1083 bool SkCanvas::skew(SkScalar sx, SkScalar sy) {
1084 fDeviceCMDirty = true;
1085 fLocalBoundsCompareTypeDirty = true;
1086 return fMCRec->fMatrix->preSkew(sx, sy);
1087 }
1088
concat(const SkMatrix & matrix)1089 bool SkCanvas::concat(const SkMatrix& matrix) {
1090 fDeviceCMDirty = true;
1091 fLocalBoundsCompareTypeDirty = true;
1092 return fMCRec->fMatrix->preConcat(matrix);
1093 }
1094
setMatrix(const SkMatrix & matrix)1095 void SkCanvas::setMatrix(const SkMatrix& matrix) {
1096 fDeviceCMDirty = true;
1097 fLocalBoundsCompareTypeDirty = true;
1098 *fMCRec->fMatrix = matrix;
1099 }
1100
1101 // this is not virtual, so it must call a virtual method so that subclasses
1102 // will see its action
resetMatrix()1103 void SkCanvas::resetMatrix() {
1104 SkMatrix matrix;
1105
1106 matrix.reset();
1107 this->setMatrix(matrix);
1108 }
1109
1110 //////////////////////////////////////////////////////////////////////////////
1111
clipRect(const SkRect & rect,SkRegion::Op op,bool doAA)1112 bool SkCanvas::clipRect(const SkRect& rect, SkRegion::Op op, bool doAA) {
1113 #ifdef SK_ENABLE_CLIP_QUICKREJECT
1114 if (SkRegion::kIntersect_Op == op) {
1115 if (fMCRec->fRasterClip->isEmpty()) {
1116 return false;
1117 }
1118
1119 if (this->quickReject(rect)) {
1120 fDeviceCMDirty = true;
1121 fLocalBoundsCompareTypeDirty = true;
1122
1123 fClipStack.clipEmpty();
1124 return fMCRec->fRasterClip->setEmpty();
1125 }
1126 }
1127 #endif
1128
1129 AutoValidateClip avc(this);
1130
1131 fDeviceCMDirty = true;
1132 fLocalBoundsCompareTypeDirty = true;
1133 doAA &= fAllowSoftClip;
1134
1135 if (fMCRec->fMatrix->rectStaysRect()) {
1136 // for these simpler matrices, we can stay a rect ever after applying
1137 // the matrix. This means we don't have to a) make a path, and b) tell
1138 // the region code to scan-convert the path, only to discover that it
1139 // is really just a rect.
1140 SkRect r;
1141
1142 fMCRec->fMatrix->mapRect(&r, rect);
1143 fClipStack.clipDevRect(r, op, doAA);
1144 return fMCRec->fRasterClip->op(r, op, doAA);
1145 } else {
1146 // since we're rotate or some such thing, we convert the rect to a path
1147 // and clip against that, since it can handle any matrix. However, to
1148 // avoid recursion in the case where we are subclassed (e.g. Pictures)
1149 // we explicitly call "our" version of clipPath.
1150 SkPath path;
1151
1152 path.addRect(rect);
1153 return this->SkCanvas::clipPath(path, op, doAA);
1154 }
1155 }
1156
clipPathHelper(const SkCanvas * canvas,SkRasterClip * currClip,const SkPath & devPath,SkRegion::Op op,bool doAA)1157 static bool clipPathHelper(const SkCanvas* canvas, SkRasterClip* currClip,
1158 const SkPath& devPath, SkRegion::Op op, bool doAA) {
1159 // base is used to limit the size (and therefore memory allocation) of the
1160 // region that results from scan converting devPath.
1161 SkRegion base;
1162
1163 if (SkRegion::kIntersect_Op == op) {
1164 // since we are intersect, we can do better (tighter) with currRgn's
1165 // bounds, than just using the device. However, if currRgn is complex,
1166 // our region blitter may hork, so we do that case in two steps.
1167 if (currClip->isRect()) {
1168 return currClip->setPath(devPath, *currClip, doAA);
1169 } else {
1170 base.setRect(currClip->getBounds());
1171 SkRasterClip clip;
1172 clip.setPath(devPath, base, doAA);
1173 return currClip->op(clip, op);
1174 }
1175 } else {
1176 const SkDevice* device = canvas->getDevice();
1177 if (!device) {
1178 return currClip->setEmpty();
1179 }
1180
1181 base.setRect(0, 0, device->width(), device->height());
1182
1183 if (SkRegion::kReplace_Op == op) {
1184 return currClip->setPath(devPath, base, doAA);
1185 } else {
1186 SkRasterClip clip;
1187 clip.setPath(devPath, base, doAA);
1188 return currClip->op(clip, op);
1189 }
1190 }
1191 }
1192
clipRRect(const SkRRect & rrect,SkRegion::Op op,bool doAA)1193 bool SkCanvas::clipRRect(const SkRRect& rrect, SkRegion::Op op, bool doAA) {
1194 if (rrect.isRect()) {
1195 // call the non-virtual version
1196 return this->SkCanvas::clipRect(rrect.getBounds(), op, doAA);
1197 } else {
1198 SkPath path;
1199 path.addRRect(rrect);
1200 // call the non-virtual version
1201 return this->SkCanvas::clipPath(path, op, doAA);
1202 }
1203 }
1204
clipPath(const SkPath & path,SkRegion::Op op,bool doAA)1205 bool SkCanvas::clipPath(const SkPath& path, SkRegion::Op op, bool doAA) {
1206 #ifdef SK_ENABLE_CLIP_QUICKREJECT
1207 if (SkRegion::kIntersect_Op == op && !path.isInverseFillType()) {
1208 if (fMCRec->fRasterClip->isEmpty()) {
1209 return false;
1210 }
1211
1212 if (this->quickReject(path.getBounds())) {
1213 fDeviceCMDirty = true;
1214 fLocalBoundsCompareTypeDirty = true;
1215
1216 fClipStack.clipEmpty();
1217 return fMCRec->fRasterClip->setEmpty();
1218 }
1219 }
1220 #endif
1221
1222 AutoValidateClip avc(this);
1223
1224 fDeviceCMDirty = true;
1225 fLocalBoundsCompareTypeDirty = true;
1226 doAA &= fAllowSoftClip;
1227
1228 SkPath devPath;
1229 path.transform(*fMCRec->fMatrix, &devPath);
1230
1231 // Check if the transfomation, or the original path itself
1232 // made us empty. Note this can also happen if we contained NaN
1233 // values. computing the bounds detects this, and will set our
1234 // bounds to empty if that is the case. (see SkRect::set(pts, count))
1235 if (devPath.getBounds().isEmpty()) {
1236 // resetting the path will remove any NaN or other wanky values
1237 // that might upset our scan converter.
1238 devPath.reset();
1239 }
1240
1241 // if we called path.swap() we could avoid a deep copy of this path
1242 fClipStack.clipDevPath(devPath, op, doAA);
1243
1244 return clipPathHelper(this, fMCRec->fRasterClip, devPath, op, doAA);
1245 }
1246
clipRegion(const SkRegion & rgn,SkRegion::Op op)1247 bool SkCanvas::clipRegion(const SkRegion& rgn, SkRegion::Op op) {
1248 AutoValidateClip avc(this);
1249
1250 fDeviceCMDirty = true;
1251 fLocalBoundsCompareTypeDirty = true;
1252
1253 // todo: signal fClipStack that we have a region, and therefore (I guess)
1254 // we have to ignore it, and use the region directly?
1255 fClipStack.clipDevRect(rgn.getBounds(), op);
1256
1257 return fMCRec->fRasterClip->op(rgn, op);
1258 }
1259
1260 #ifdef SK_DEBUG
validateClip() const1261 void SkCanvas::validateClip() const {
1262 // construct clipRgn from the clipstack
1263 const SkDevice* device = this->getDevice();
1264 if (!device) {
1265 SkASSERT(this->getTotalClip().isEmpty());
1266 return;
1267 }
1268
1269 SkIRect ir;
1270 ir.set(0, 0, device->width(), device->height());
1271 SkRasterClip tmpClip(ir);
1272
1273 SkClipStack::B2TIter iter(fClipStack);
1274 const SkClipStack::Element* element;
1275 while ((element = iter.next()) != NULL) {
1276 switch (element->getType()) {
1277 case SkClipStack::Element::kPath_Type:
1278 clipPathHelper(this,
1279 &tmpClip,
1280 element->getPath(),
1281 element->getOp(),
1282 element->isAA());
1283 break;
1284 case SkClipStack::Element::kRect_Type:
1285 element->getRect().round(&ir);
1286 tmpClip.op(ir, element->getOp());
1287 break;
1288 case SkClipStack::Element::kEmpty_Type:
1289 tmpClip.setEmpty();
1290 break;
1291 }
1292 }
1293
1294 #if 0 // enable this locally for testing
1295 // now compare against the current rgn
1296 const SkRegion& rgn = this->getTotalClip();
1297 SkASSERT(rgn == tmpClip);
1298 #endif
1299 }
1300 #endif
1301
replayClips(ClipVisitor * visitor) const1302 void SkCanvas::replayClips(ClipVisitor* visitor) const {
1303 SkClipStack::B2TIter iter(fClipStack);
1304 const SkClipStack::Element* element;
1305
1306 static const SkRect kEmpty = { 0, 0, 0, 0 };
1307 while ((element = iter.next()) != NULL) {
1308 switch (element->getType()) {
1309 case SkClipStack::Element::kPath_Type:
1310 visitor->clipPath(element->getPath(), element->getOp(), element->isAA());
1311 break;
1312 case SkClipStack::Element::kRect_Type:
1313 visitor->clipRect(element->getRect(), element->getOp(), element->isAA());
1314 break;
1315 case SkClipStack::Element::kEmpty_Type:
1316 visitor->clipRect(kEmpty, SkRegion::kIntersect_Op, false);
1317 break;
1318 }
1319 }
1320 }
1321
1322 ///////////////////////////////////////////////////////////////////////////////
1323
computeLocalClipBoundsCompareType() const1324 void SkCanvas::computeLocalClipBoundsCompareType() const {
1325 SkRect r;
1326
1327 if (!this->getClipBounds(&r)) {
1328 fLocalBoundsCompareType.setEmpty();
1329 } else {
1330 fLocalBoundsCompareType.set(SkScalarToCompareType(r.fLeft),
1331 SkScalarToCompareType(r.fTop),
1332 SkScalarToCompareType(r.fRight),
1333 SkScalarToCompareType(r.fBottom));
1334 }
1335 }
1336
quickReject(const SkRect & rect) const1337 bool SkCanvas::quickReject(const SkRect& rect) const {
1338
1339 if (!rect.isFinite())
1340 return true;
1341
1342 if (fMCRec->fRasterClip->isEmpty()) {
1343 return true;
1344 }
1345
1346 if (fMCRec->fMatrix->hasPerspective()) {
1347 SkRect dst;
1348 fMCRec->fMatrix->mapRect(&dst, rect);
1349 SkIRect idst;
1350 dst.roundOut(&idst);
1351 return !SkIRect::Intersects(idst, fMCRec->fRasterClip->getBounds());
1352 } else {
1353 const SkRectCompareType& clipR = this->getLocalClipBoundsCompareType();
1354
1355 // for speed, do the most likely reject compares first
1356 SkScalarCompareType userT = SkScalarToCompareType(rect.fTop);
1357 SkScalarCompareType userB = SkScalarToCompareType(rect.fBottom);
1358 if (userT >= clipR.fBottom || userB <= clipR.fTop) {
1359 return true;
1360 }
1361 SkScalarCompareType userL = SkScalarToCompareType(rect.fLeft);
1362 SkScalarCompareType userR = SkScalarToCompareType(rect.fRight);
1363 if (userL >= clipR.fRight || userR <= clipR.fLeft) {
1364 return true;
1365 }
1366 return false;
1367 }
1368 }
1369
quickReject(const SkPath & path) const1370 bool SkCanvas::quickReject(const SkPath& path) const {
1371 return path.isEmpty() || this->quickReject(path.getBounds());
1372 }
1373
pinIntForScalar(int x)1374 static inline int pinIntForScalar(int x) {
1375 #ifdef SK_SCALAR_IS_FIXED
1376 if (x < SK_MinS16) {
1377 x = SK_MinS16;
1378 } else if (x > SK_MaxS16) {
1379 x = SK_MaxS16;
1380 }
1381 #endif
1382 return x;
1383 }
1384
getClipBounds(SkRect * bounds) const1385 bool SkCanvas::getClipBounds(SkRect* bounds) const {
1386 SkIRect ibounds;
1387 if (!getClipDeviceBounds(&ibounds)) {
1388 return false;
1389 }
1390
1391 SkMatrix inverse;
1392 // if we can't invert the CTM, we can't return local clip bounds
1393 if (!fMCRec->fMatrix->invert(&inverse)) {
1394 if (bounds) {
1395 bounds->setEmpty();
1396 }
1397 return false;
1398 }
1399
1400 if (NULL != bounds) {
1401 SkRect r;
1402 // adjust it outwards in case we are antialiasing
1403 const int inset = 1;
1404
1405 // SkRect::iset() will correctly assert if we pass a value out of range
1406 // (when SkScalar==fixed), so we pin to legal values. This does not
1407 // really returnt the correct answer, but its the best we can do given
1408 // that we've promised to return SkRect (even though we support devices
1409 // that can be larger than 32K in width or height).
1410 r.iset(pinIntForScalar(ibounds.fLeft - inset),
1411 pinIntForScalar(ibounds.fTop - inset),
1412 pinIntForScalar(ibounds.fRight + inset),
1413 pinIntForScalar(ibounds.fBottom + inset));
1414 inverse.mapRect(bounds, r);
1415 }
1416 return true;
1417 }
1418
getClipDeviceBounds(SkIRect * bounds) const1419 bool SkCanvas::getClipDeviceBounds(SkIRect* bounds) const {
1420 const SkRasterClip& clip = *fMCRec->fRasterClip;
1421 if (clip.isEmpty()) {
1422 if (bounds) {
1423 bounds->setEmpty();
1424 }
1425 return false;
1426 }
1427
1428 if (NULL != bounds) {
1429 *bounds = clip.getBounds();
1430 }
1431 return true;
1432 }
1433
getTotalMatrix() const1434 const SkMatrix& SkCanvas::getTotalMatrix() const {
1435 return *fMCRec->fMatrix;
1436 }
1437
getClipType() const1438 SkCanvas::ClipType SkCanvas::getClipType() const {
1439 if (fMCRec->fRasterClip->isEmpty()) return kEmpty_ClipType;
1440 if (fMCRec->fRasterClip->isRect()) return kRect_ClipType;
1441 return kComplex_ClipType;
1442 }
1443
getTotalClip() const1444 const SkRegion& SkCanvas::getTotalClip() const {
1445 return fMCRec->fRasterClip->forceGetBW();
1446 }
1447
createLayerDevice(SkBitmap::Config config,int width,int height,bool isOpaque)1448 SkDevice* SkCanvas::createLayerDevice(SkBitmap::Config config,
1449 int width, int height,
1450 bool isOpaque) {
1451 SkDevice* device = this->getTopDevice();
1452 if (device) {
1453 return device->createCompatibleDeviceForSaveLayer(config, width, height,
1454 isOpaque);
1455 } else {
1456 return NULL;
1457 }
1458 }
1459
createCompatibleDevice(SkBitmap::Config config,int width,int height,bool isOpaque)1460 SkDevice* SkCanvas::createCompatibleDevice(SkBitmap::Config config,
1461 int width, int height,
1462 bool isOpaque) {
1463 SkDevice* device = this->getDevice();
1464 if (device) {
1465 return device->createCompatibleDevice(config, width, height, isOpaque);
1466 } else {
1467 return NULL;
1468 }
1469 }
1470
1471
1472 //////////////////////////////////////////////////////////////////////////////
1473 // These are the virtual drawing methods
1474 //////////////////////////////////////////////////////////////////////////////
1475
clear(SkColor color)1476 void SkCanvas::clear(SkColor color) {
1477 SkDrawIter iter(this);
1478
1479 while (iter.next()) {
1480 iter.fDevice->clear(color);
1481 }
1482 }
1483
drawPaint(const SkPaint & paint)1484 void SkCanvas::drawPaint(const SkPaint& paint) {
1485 this->internalDrawPaint(paint);
1486 }
1487
internalDrawPaint(const SkPaint & paint)1488 void SkCanvas::internalDrawPaint(const SkPaint& paint) {
1489 CHECK_SHADER_NOSETCONTEXT(paint);
1490
1491 LOOPER_BEGIN(paint, SkDrawFilter::kPaint_Type)
1492
1493 while (iter.next()) {
1494 iter.fDevice->drawPaint(iter, looper.paint());
1495 }
1496
1497 LOOPER_END
1498 }
1499
drawPoints(PointMode mode,size_t count,const SkPoint pts[],const SkPaint & paint)1500 void SkCanvas::drawPoints(PointMode mode, size_t count, const SkPoint pts[],
1501 const SkPaint& paint) {
1502 if ((long)count <= 0) {
1503 return;
1504 }
1505
1506 CHECK_SHADER_NOSETCONTEXT(paint);
1507
1508 if (paint.canComputeFastBounds()) {
1509 SkRect r;
1510 // special-case 2 points (common for drawing a single line)
1511 if (2 == count) {
1512 r.set(pts[0], pts[1]);
1513 } else {
1514 r.set(pts, count);
1515 }
1516 SkRect storage;
1517 if (this->quickReject(paint.computeFastStrokeBounds(r, &storage))) {
1518 return;
1519 }
1520 }
1521
1522 SkASSERT(pts != NULL);
1523
1524 LOOPER_BEGIN(paint, SkDrawFilter::kPoint_Type)
1525
1526 while (iter.next()) {
1527 iter.fDevice->drawPoints(iter, mode, count, pts, looper.paint());
1528 }
1529
1530 LOOPER_END
1531 }
1532
drawRect(const SkRect & r,const SkPaint & paint)1533 void SkCanvas::drawRect(const SkRect& r, const SkPaint& paint) {
1534 CHECK_SHADER_NOSETCONTEXT(paint);
1535
1536 if (paint.canComputeFastBounds()) {
1537 SkRect storage;
1538 if (this->quickReject(paint.computeFastBounds(r, &storage))) {
1539 return;
1540 }
1541 }
1542
1543 LOOPER_BEGIN(paint, SkDrawFilter::kRect_Type)
1544
1545 while (iter.next()) {
1546 iter.fDevice->drawRect(iter, r, looper.paint());
1547 }
1548
1549 LOOPER_END
1550 }
1551
drawOval(const SkRect & oval,const SkPaint & paint)1552 void SkCanvas::drawOval(const SkRect& oval, const SkPaint& paint) {
1553 CHECK_SHADER_NOSETCONTEXT(paint);
1554
1555 if (paint.canComputeFastBounds()) {
1556 SkRect storage;
1557 if (this->quickReject(paint.computeFastBounds(oval, &storage))) {
1558 return;
1559 }
1560 }
1561
1562 LOOPER_BEGIN(paint, SkDrawFilter::kOval_Type)
1563
1564 while (iter.next()) {
1565 iter.fDevice->drawOval(iter, oval, looper.paint());
1566 }
1567
1568 LOOPER_END
1569 }
1570
drawRRect(const SkRRect & rrect,const SkPaint & paint)1571 void SkCanvas::drawRRect(const SkRRect& rrect, const SkPaint& paint) {
1572 CHECK_SHADER_NOSETCONTEXT(paint);
1573
1574 if (paint.canComputeFastBounds()) {
1575 SkRect storage;
1576 if (this->quickReject(paint.computeFastBounds(rrect.getBounds(), &storage))) {
1577 return;
1578 }
1579 }
1580
1581 if (rrect.isRect()) {
1582 // call the non-virtual version
1583 this->SkCanvas::drawRect(rrect.getBounds(), paint);
1584 } else {
1585 SkPath path;
1586 path.addRRect(rrect);
1587 // call the non-virtual version
1588 this->SkCanvas::drawPath(path, paint);
1589 }
1590 }
1591
1592
drawPath(const SkPath & path,const SkPaint & paint)1593 void SkCanvas::drawPath(const SkPath& path, const SkPaint& paint) {
1594 CHECK_SHADER_NOSETCONTEXT(paint);
1595
1596 if (!path.isFinite()) {
1597 return;
1598 }
1599
1600 if (!path.isInverseFillType() && paint.canComputeFastBounds()) {
1601 SkRect storage;
1602 const SkRect& bounds = path.getBounds();
1603 if (this->quickReject(paint.computeFastBounds(bounds, &storage))) {
1604 return;
1605 }
1606 }
1607 if (path.isEmpty()) {
1608 if (path.isInverseFillType()) {
1609 this->internalDrawPaint(paint);
1610 }
1611 return;
1612 }
1613
1614 LOOPER_BEGIN(paint, SkDrawFilter::kPath_Type)
1615
1616 while (iter.next()) {
1617 iter.fDevice->drawPath(iter, path, looper.paint());
1618 }
1619
1620 LOOPER_END
1621 }
1622
drawBitmap(const SkBitmap & bitmap,SkScalar x,SkScalar y,const SkPaint * paint)1623 void SkCanvas::drawBitmap(const SkBitmap& bitmap, SkScalar x, SkScalar y,
1624 const SkPaint* paint) {
1625 SkDEBUGCODE(bitmap.validate();)
1626
1627 if (NULL == paint || paint->canComputeFastBounds()) {
1628 SkRect bounds = {
1629 x, y,
1630 x + SkIntToScalar(bitmap.width()),
1631 y + SkIntToScalar(bitmap.height())
1632 };
1633 if (paint) {
1634 (void)paint->computeFastBounds(bounds, &bounds);
1635 }
1636 if (this->quickReject(bounds)) {
1637 return;
1638 }
1639 }
1640
1641 SkMatrix matrix;
1642 matrix.setTranslate(x, y);
1643 this->internalDrawBitmap(bitmap, NULL, matrix, paint);
1644 }
1645
1646 // this one is non-virtual, so it can be called safely by other canvas apis
internalDrawBitmapRect(const SkBitmap & bitmap,const SkRect * src,const SkRect & dst,const SkPaint * paint)1647 void SkCanvas::internalDrawBitmapRect(const SkBitmap& bitmap, const SkRect* src,
1648 const SkRect& dst, const SkPaint* paint) {
1649 if (bitmap.width() == 0 || bitmap.height() == 0 || dst.isEmpty()) {
1650 return;
1651 }
1652
1653 CHECK_LOCKCOUNT_BALANCE(bitmap);
1654
1655 if (NULL == paint || paint->canComputeFastBounds()) {
1656 SkRect storage;
1657 const SkRect* bounds = &dst;
1658 if (paint) {
1659 bounds = &paint->computeFastBounds(dst, &storage);
1660 }
1661 if (this->quickReject(*bounds)) {
1662 return;
1663 }
1664 }
1665
1666 SkLazyPaint lazy;
1667 if (NULL == paint) {
1668 paint = lazy.init();
1669 }
1670
1671 LOOPER_BEGIN(*paint, SkDrawFilter::kBitmap_Type)
1672
1673 while (iter.next()) {
1674 iter.fDevice->drawBitmapRect(iter, bitmap, src, dst, looper.paint());
1675 }
1676
1677 LOOPER_END
1678 }
1679
drawBitmapRectToRect(const SkBitmap & bitmap,const SkRect * src,const SkRect & dst,const SkPaint * paint)1680 void SkCanvas::drawBitmapRectToRect(const SkBitmap& bitmap, const SkRect* src,
1681 const SkRect& dst, const SkPaint* paint) {
1682 SkDEBUGCODE(bitmap.validate();)
1683 this->internalDrawBitmapRect(bitmap, src, dst, paint);
1684 }
1685
drawBitmapMatrix(const SkBitmap & bitmap,const SkMatrix & matrix,const SkPaint * paint)1686 void SkCanvas::drawBitmapMatrix(const SkBitmap& bitmap, const SkMatrix& matrix,
1687 const SkPaint* paint) {
1688 SkDEBUGCODE(bitmap.validate();)
1689 this->internalDrawBitmap(bitmap, NULL, matrix, paint);
1690 }
1691
commonDrawBitmap(const SkBitmap & bitmap,const SkIRect * srcRect,const SkMatrix & matrix,const SkPaint & paint)1692 void SkCanvas::commonDrawBitmap(const SkBitmap& bitmap, const SkIRect* srcRect,
1693 const SkMatrix& matrix, const SkPaint& paint) {
1694 SkDEBUGCODE(bitmap.validate();)
1695 CHECK_LOCKCOUNT_BALANCE(bitmap);
1696
1697 LOOPER_BEGIN(paint, SkDrawFilter::kBitmap_Type)
1698
1699 while (iter.next()) {
1700 iter.fDevice->drawBitmap(iter, bitmap, srcRect, matrix, looper.paint());
1701 }
1702
1703 LOOPER_END
1704 }
1705
internalDrawBitmapNine(const SkBitmap & bitmap,const SkIRect & center,const SkRect & dst,const SkPaint * paint)1706 void SkCanvas::internalDrawBitmapNine(const SkBitmap& bitmap,
1707 const SkIRect& center, const SkRect& dst,
1708 const SkPaint* paint) {
1709 if (NULL == paint || paint->canComputeFastBounds()) {
1710 SkRect storage;
1711 const SkRect* bounds = &dst;
1712 if (paint) {
1713 bounds = &paint->computeFastBounds(dst, &storage);
1714 }
1715 if (this->quickReject(*bounds)) {
1716 return;
1717 }
1718 }
1719
1720 const int32_t w = bitmap.width();
1721 const int32_t h = bitmap.height();
1722
1723 SkIRect c = center;
1724 // pin center to the bounds of the bitmap
1725 c.fLeft = SkMax32(0, center.fLeft);
1726 c.fTop = SkMax32(0, center.fTop);
1727 c.fRight = SkPin32(center.fRight, c.fLeft, w);
1728 c.fBottom = SkPin32(center.fBottom, c.fTop, h);
1729
1730 const SkScalar srcX[4] = {
1731 0, SkIntToScalar(c.fLeft), SkIntToScalar(c.fRight), SkIntToScalar(w)
1732 };
1733 const SkScalar srcY[4] = {
1734 0, SkIntToScalar(c.fTop), SkIntToScalar(c.fBottom), SkIntToScalar(h)
1735 };
1736 SkScalar dstX[4] = {
1737 dst.fLeft, dst.fLeft + SkIntToScalar(c.fLeft),
1738 dst.fRight - SkIntToScalar(w - c.fRight), dst.fRight
1739 };
1740 SkScalar dstY[4] = {
1741 dst.fTop, dst.fTop + SkIntToScalar(c.fTop),
1742 dst.fBottom - SkIntToScalar(h - c.fBottom), dst.fBottom
1743 };
1744
1745 if (dstX[1] > dstX[2]) {
1746 dstX[1] = dstX[0] + (dstX[3] - dstX[0]) * c.fLeft / (w - c.width());
1747 dstX[2] = dstX[1];
1748 }
1749
1750 if (dstY[1] > dstY[2]) {
1751 dstY[1] = dstY[0] + (dstY[3] - dstY[0]) * c.fTop / (h - c.height());
1752 dstY[2] = dstY[1];
1753 }
1754
1755 for (int y = 0; y < 3; y++) {
1756 SkRect s, d;
1757
1758 s.fTop = srcY[y];
1759 s.fBottom = srcY[y+1];
1760 d.fTop = dstY[y];
1761 d.fBottom = dstY[y+1];
1762 for (int x = 0; x < 3; x++) {
1763 s.fLeft = srcX[x];
1764 s.fRight = srcX[x+1];
1765 d.fLeft = dstX[x];
1766 d.fRight = dstX[x+1];
1767 this->internalDrawBitmapRect(bitmap, &s, d, paint);
1768 }
1769 }
1770 }
1771
drawBitmapNine(const SkBitmap & bitmap,const SkIRect & center,const SkRect & dst,const SkPaint * paint)1772 void SkCanvas::drawBitmapNine(const SkBitmap& bitmap, const SkIRect& center,
1773 const SkRect& dst, const SkPaint* paint) {
1774 SkDEBUGCODE(bitmap.validate();)
1775
1776 // Need a device entry-point, so gpu can use a mesh
1777 this->internalDrawBitmapNine(bitmap, center, dst, paint);
1778 }
1779
1780 class SkDeviceFilteredPaint {
1781 public:
SkDeviceFilteredPaint(SkDevice * device,const SkPaint & paint)1782 SkDeviceFilteredPaint(SkDevice* device, const SkPaint& paint) {
1783 SkDevice::TextFlags flags;
1784 if (device->filterTextFlags(paint, &flags)) {
1785 SkPaint* newPaint = fLazy.set(paint);
1786 newPaint->setFlags(flags.fFlags);
1787 newPaint->setHinting(flags.fHinting);
1788 fPaint = newPaint;
1789 } else {
1790 fPaint = &paint;
1791 }
1792 }
1793
paint() const1794 const SkPaint& paint() const { return *fPaint; }
1795
1796 private:
1797 const SkPaint* fPaint;
1798 SkLazyPaint fLazy;
1799 };
1800
DrawRect(const SkDraw & draw,const SkPaint & paint,const SkRect & r,SkScalar textSize)1801 void SkCanvas::DrawRect(const SkDraw& draw, const SkPaint& paint,
1802 const SkRect& r, SkScalar textSize) {
1803 if (paint.getStyle() == SkPaint::kFill_Style) {
1804 draw.fDevice->drawRect(draw, r, paint);
1805 } else {
1806 SkPaint p(paint);
1807 p.setStrokeWidth(SkScalarMul(textSize, paint.getStrokeWidth()));
1808 draw.fDevice->drawRect(draw, r, p);
1809 }
1810 }
1811
DrawTextDecorations(const SkDraw & draw,const SkPaint & paint,const char text[],size_t byteLength,SkScalar x,SkScalar y)1812 void SkCanvas::DrawTextDecorations(const SkDraw& draw, const SkPaint& paint,
1813 const char text[], size_t byteLength,
1814 SkScalar x, SkScalar y) {
1815 SkASSERT(byteLength == 0 || text != NULL);
1816
1817 // nothing to draw
1818 if (text == NULL || byteLength == 0 ||
1819 draw.fClip->isEmpty() ||
1820 (paint.getAlpha() == 0 && paint.getXfermode() == NULL)) {
1821 return;
1822 }
1823
1824 SkScalar width = 0;
1825 SkPoint start;
1826
1827 start.set(0, 0); // to avoid warning
1828 if (paint.getFlags() & (SkPaint::kUnderlineText_Flag |
1829 SkPaint::kStrikeThruText_Flag)) {
1830 width = paint.measureText(text, byteLength);
1831
1832 SkScalar offsetX = 0;
1833 if (paint.getTextAlign() == SkPaint::kCenter_Align) {
1834 offsetX = SkScalarHalf(width);
1835 } else if (paint.getTextAlign() == SkPaint::kRight_Align) {
1836 offsetX = width;
1837 }
1838 start.set(x - offsetX, y);
1839 }
1840
1841 if (0 == width) {
1842 return;
1843 }
1844
1845 uint32_t flags = paint.getFlags();
1846
1847 if (flags & (SkPaint::kUnderlineText_Flag |
1848 SkPaint::kStrikeThruText_Flag)) {
1849 SkScalar textSize = paint.getTextSize();
1850 SkScalar height = SkScalarMul(textSize, kStdUnderline_Thickness);
1851 SkRect r;
1852
1853 r.fLeft = start.fX;
1854 r.fRight = start.fX + width;
1855
1856 if (flags & SkPaint::kUnderlineText_Flag) {
1857 SkScalar offset = SkScalarMulAdd(textSize, kStdUnderline_Offset,
1858 start.fY);
1859 r.fTop = offset;
1860 r.fBottom = offset + height;
1861 DrawRect(draw, paint, r, textSize);
1862 }
1863 if (flags & SkPaint::kStrikeThruText_Flag) {
1864 SkScalar offset = SkScalarMulAdd(textSize, kStdStrikeThru_Offset,
1865 start.fY);
1866 r.fTop = offset;
1867 r.fBottom = offset + height;
1868 DrawRect(draw, paint, r, textSize);
1869 }
1870 }
1871 }
1872
drawText(const void * text,size_t byteLength,SkScalar x,SkScalar y,const SkPaint & paint)1873 void SkCanvas::drawText(const void* text, size_t byteLength,
1874 SkScalar x, SkScalar y, const SkPaint& paint) {
1875 CHECK_SHADER_NOSETCONTEXT(paint);
1876
1877 LOOPER_BEGIN(paint, SkDrawFilter::kText_Type)
1878
1879 while (iter.next()) {
1880 SkDeviceFilteredPaint dfp(iter.fDevice, looper.paint());
1881 iter.fDevice->drawText(iter, text, byteLength, x, y, dfp.paint());
1882 DrawTextDecorations(iter, dfp.paint(),
1883 static_cast<const char*>(text), byteLength, x, y);
1884 }
1885
1886 LOOPER_END
1887 }
1888
drawPosText(const void * text,size_t byteLength,const SkPoint pos[],const SkPaint & paint)1889 void SkCanvas::drawPosText(const void* text, size_t byteLength,
1890 const SkPoint pos[], const SkPaint& paint) {
1891 CHECK_SHADER_NOSETCONTEXT(paint);
1892
1893 LOOPER_BEGIN(paint, SkDrawFilter::kText_Type)
1894
1895 while (iter.next()) {
1896 SkDeviceFilteredPaint dfp(iter.fDevice, looper.paint());
1897 iter.fDevice->drawPosText(iter, text, byteLength, &pos->fX, 0, 2,
1898 dfp.paint());
1899 }
1900
1901 LOOPER_END
1902 }
1903
drawPosTextH(const void * text,size_t byteLength,const SkScalar xpos[],SkScalar constY,const SkPaint & paint)1904 void SkCanvas::drawPosTextH(const void* text, size_t byteLength,
1905 const SkScalar xpos[], SkScalar constY,
1906 const SkPaint& paint) {
1907 CHECK_SHADER_NOSETCONTEXT(paint);
1908
1909 LOOPER_BEGIN(paint, SkDrawFilter::kText_Type)
1910
1911 while (iter.next()) {
1912 SkDeviceFilteredPaint dfp(iter.fDevice, looper.paint());
1913 iter.fDevice->drawPosText(iter, text, byteLength, xpos, constY, 1,
1914 dfp.paint());
1915 }
1916
1917 LOOPER_END
1918 }
1919
drawTextOnPath(const void * text,size_t byteLength,const SkPath & path,const SkMatrix * matrix,const SkPaint & paint)1920 void SkCanvas::drawTextOnPath(const void* text, size_t byteLength,
1921 const SkPath& path, const SkMatrix* matrix,
1922 const SkPaint& paint) {
1923 CHECK_SHADER_NOSETCONTEXT(paint);
1924
1925 LOOPER_BEGIN(paint, SkDrawFilter::kText_Type)
1926
1927 while (iter.next()) {
1928 iter.fDevice->drawTextOnPath(iter, text, byteLength, path,
1929 matrix, looper.paint());
1930 }
1931
1932 LOOPER_END
1933 }
1934
1935 #ifdef SK_BUILD_FOR_ANDROID
drawPosTextOnPath(const void * text,size_t byteLength,const SkPoint pos[],const SkPaint & paint,const SkPath & path,const SkMatrix * matrix)1936 void SkCanvas::drawPosTextOnPath(const void* text, size_t byteLength,
1937 const SkPoint pos[], const SkPaint& paint,
1938 const SkPath& path, const SkMatrix* matrix) {
1939 CHECK_SHADER_NOSETCONTEXT(paint);
1940
1941 LOOPER_BEGIN(paint, SkDrawFilter::kText_Type)
1942
1943 while (iter.next()) {
1944 iter.fDevice->drawPosTextOnPath(iter, text, byteLength, pos,
1945 looper.paint(), path, matrix);
1946 }
1947
1948 LOOPER_END
1949 }
1950 #endif
1951
drawVertices(VertexMode vmode,int vertexCount,const SkPoint verts[],const SkPoint texs[],const SkColor colors[],SkXfermode * xmode,const uint16_t indices[],int indexCount,const SkPaint & paint)1952 void SkCanvas::drawVertices(VertexMode vmode, int vertexCount,
1953 const SkPoint verts[], const SkPoint texs[],
1954 const SkColor colors[], SkXfermode* xmode,
1955 const uint16_t indices[], int indexCount,
1956 const SkPaint& paint) {
1957 CHECK_SHADER_NOSETCONTEXT(paint);
1958
1959 LOOPER_BEGIN(paint, SkDrawFilter::kPath_Type)
1960
1961 while (iter.next()) {
1962 iter.fDevice->drawVertices(iter, vmode, vertexCount, verts, texs,
1963 colors, xmode, indices, indexCount,
1964 looper.paint());
1965 }
1966
1967 LOOPER_END
1968 }
1969
drawData(const void * data,size_t length)1970 void SkCanvas::drawData(const void* data, size_t length) {
1971 // do nothing. Subclasses may do something with the data
1972 }
1973
1974 //////////////////////////////////////////////////////////////////////////////
1975 // These methods are NOT virtual, and therefore must call back into virtual
1976 // methods, rather than actually drawing themselves.
1977 //////////////////////////////////////////////////////////////////////////////
1978
drawARGB(U8CPU a,U8CPU r,U8CPU g,U8CPU b,SkXfermode::Mode mode)1979 void SkCanvas::drawARGB(U8CPU a, U8CPU r, U8CPU g, U8CPU b,
1980 SkXfermode::Mode mode) {
1981 SkPaint paint;
1982
1983 paint.setARGB(a, r, g, b);
1984 if (SkXfermode::kSrcOver_Mode != mode) {
1985 paint.setXfermodeMode(mode);
1986 }
1987 this->drawPaint(paint);
1988 }
1989
drawColor(SkColor c,SkXfermode::Mode mode)1990 void SkCanvas::drawColor(SkColor c, SkXfermode::Mode mode) {
1991 SkPaint paint;
1992
1993 paint.setColor(c);
1994 if (SkXfermode::kSrcOver_Mode != mode) {
1995 paint.setXfermodeMode(mode);
1996 }
1997 this->drawPaint(paint);
1998 }
1999
drawPoint(SkScalar x,SkScalar y,const SkPaint & paint)2000 void SkCanvas::drawPoint(SkScalar x, SkScalar y, const SkPaint& paint) {
2001 SkPoint pt;
2002
2003 pt.set(x, y);
2004 this->drawPoints(kPoints_PointMode, 1, &pt, paint);
2005 }
2006
drawPoint(SkScalar x,SkScalar y,SkColor color)2007 void SkCanvas::drawPoint(SkScalar x, SkScalar y, SkColor color) {
2008 SkPoint pt;
2009 SkPaint paint;
2010
2011 pt.set(x, y);
2012 paint.setColor(color);
2013 this->drawPoints(kPoints_PointMode, 1, &pt, paint);
2014 }
2015
drawLine(SkScalar x0,SkScalar y0,SkScalar x1,SkScalar y1,const SkPaint & paint)2016 void SkCanvas::drawLine(SkScalar x0, SkScalar y0, SkScalar x1, SkScalar y1,
2017 const SkPaint& paint) {
2018 SkPoint pts[2];
2019
2020 pts[0].set(x0, y0);
2021 pts[1].set(x1, y1);
2022 this->drawPoints(kLines_PointMode, 2, pts, paint);
2023 }
2024
drawRectCoords(SkScalar left,SkScalar top,SkScalar right,SkScalar bottom,const SkPaint & paint)2025 void SkCanvas::drawRectCoords(SkScalar left, SkScalar top,
2026 SkScalar right, SkScalar bottom,
2027 const SkPaint& paint) {
2028 SkRect r;
2029
2030 r.set(left, top, right, bottom);
2031 this->drawRect(r, paint);
2032 }
2033
drawCircle(SkScalar cx,SkScalar cy,SkScalar radius,const SkPaint & paint)2034 void SkCanvas::drawCircle(SkScalar cx, SkScalar cy, SkScalar radius,
2035 const SkPaint& paint) {
2036 if (radius < 0) {
2037 radius = 0;
2038 }
2039
2040 SkRect r;
2041 r.set(cx - radius, cy - radius, cx + radius, cy + radius);
2042 this->drawOval(r, paint);
2043 }
2044
drawRoundRect(const SkRect & r,SkScalar rx,SkScalar ry,const SkPaint & paint)2045 void SkCanvas::drawRoundRect(const SkRect& r, SkScalar rx, SkScalar ry,
2046 const SkPaint& paint) {
2047 if (rx > 0 && ry > 0) {
2048 if (paint.canComputeFastBounds()) {
2049 SkRect storage;
2050 if (this->quickReject(paint.computeFastBounds(r, &storage))) {
2051 return;
2052 }
2053 }
2054 SkRRect rrect;
2055 rrect.setRectXY(r, rx, ry);
2056 this->drawRRect(rrect, paint);
2057 } else {
2058 this->drawRect(r, paint);
2059 }
2060 }
2061
drawArc(const SkRect & oval,SkScalar startAngle,SkScalar sweepAngle,bool useCenter,const SkPaint & paint)2062 void SkCanvas::drawArc(const SkRect& oval, SkScalar startAngle,
2063 SkScalar sweepAngle, bool useCenter,
2064 const SkPaint& paint) {
2065 if (SkScalarAbs(sweepAngle) >= SkIntToScalar(360)) {
2066 this->drawOval(oval, paint);
2067 } else {
2068 SkPath path;
2069 if (useCenter) {
2070 path.moveTo(oval.centerX(), oval.centerY());
2071 }
2072 path.arcTo(oval, startAngle, sweepAngle, !useCenter);
2073 if (useCenter) {
2074 path.close();
2075 }
2076 this->drawPath(path, paint);
2077 }
2078 }
2079
drawTextOnPathHV(const void * text,size_t byteLength,const SkPath & path,SkScalar hOffset,SkScalar vOffset,const SkPaint & paint)2080 void SkCanvas::drawTextOnPathHV(const void* text, size_t byteLength,
2081 const SkPath& path, SkScalar hOffset,
2082 SkScalar vOffset, const SkPaint& paint) {
2083 SkMatrix matrix;
2084
2085 matrix.setTranslate(hOffset, vOffset);
2086 this->drawTextOnPath(text, byteLength, path, &matrix, paint);
2087 }
2088
2089 ///////////////////////////////////////////////////////////////////////////////
2090
drawPicture(SkPicture & picture)2091 void SkCanvas::drawPicture(SkPicture& picture) {
2092 picture.draw(this);
2093 }
2094
2095 ///////////////////////////////////////////////////////////////////////////////
2096 ///////////////////////////////////////////////////////////////////////////////
2097
LayerIter(SkCanvas * canvas,bool skipEmptyClips)2098 SkCanvas::LayerIter::LayerIter(SkCanvas* canvas, bool skipEmptyClips) {
2099 SK_COMPILE_ASSERT(sizeof(fStorage) >= sizeof(SkDrawIter), fStorage_too_small);
2100
2101 SkASSERT(canvas);
2102
2103 fImpl = new (fStorage) SkDrawIter(canvas, skipEmptyClips);
2104 fDone = !fImpl->next();
2105 }
2106
~LayerIter()2107 SkCanvas::LayerIter::~LayerIter() {
2108 fImpl->~SkDrawIter();
2109 }
2110
next()2111 void SkCanvas::LayerIter::next() {
2112 fDone = !fImpl->next();
2113 }
2114
device() const2115 SkDevice* SkCanvas::LayerIter::device() const {
2116 return fImpl->getDevice();
2117 }
2118
matrix() const2119 const SkMatrix& SkCanvas::LayerIter::matrix() const {
2120 return fImpl->getMatrix();
2121 }
2122
paint() const2123 const SkPaint& SkCanvas::LayerIter::paint() const {
2124 const SkPaint* paint = fImpl->getPaint();
2125 if (NULL == paint) {
2126 paint = &fDefaultPaint;
2127 }
2128 return *paint;
2129 }
2130
clip() const2131 const SkRegion& SkCanvas::LayerIter::clip() const { return fImpl->getClip(); }
x() const2132 int SkCanvas::LayerIter::x() const { return fImpl->getX(); }
y() const2133 int SkCanvas::LayerIter::y() const { return fImpl->getY(); }
2134
2135 ///////////////////////////////////////////////////////////////////////////////
2136
~ClipVisitor()2137 SkCanvas::ClipVisitor::~ClipVisitor() { }
2138