1 /*
2 * Copyright 2012 Google Inc.
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
7
8 #include "SkSurface_Base.h"
9 #include "SkImagePriv.h"
10 #include "SkCanvas.h"
11
12 ///////////////////////////////////////////////////////////////////////////////
13
SkSurface_Base(int width,int height)14 SkSurface_Base::SkSurface_Base(int width, int height) : INHERITED(width, height) {
15 fCachedCanvas = NULL;
16 fCachedImage = NULL;
17 }
18
~SkSurface_Base()19 SkSurface_Base::~SkSurface_Base() {
20 // in case the canvas outsurvives us, we null the callback
21 if (fCachedCanvas) {
22 fCachedCanvas->setSurfaceBase(NULL);
23 }
24
25 SkSafeUnref(fCachedImage);
26 SkSafeUnref(fCachedCanvas);
27 }
28
onDraw(SkCanvas * canvas,SkScalar x,SkScalar y,const SkPaint * paint)29 void SkSurface_Base::onDraw(SkCanvas* canvas, SkScalar x, SkScalar y,
30 const SkPaint* paint) {
31 SkImage* image = this->newImageSnapshot();
32 if (image) {
33 image->draw(canvas, x, y, paint);
34 image->unref();
35 }
36 }
37
aboutToDraw(ContentChangeMode mode)38 void SkSurface_Base::aboutToDraw(ContentChangeMode mode) {
39 this->dirtyGenerationID();
40
41 if (NULL != fCachedCanvas) {
42 SkASSERT(fCachedCanvas->getSurfaceBase() == this || \
43 NULL == fCachedCanvas->getSurfaceBase());
44 fCachedCanvas->setSurfaceBase(NULL);
45 }
46
47 if (NULL != fCachedImage) {
48 // the surface may need to fork its backend, if its sharing it with
49 // the cached image. Note: we only call if there is an outstanding owner
50 // on the image (besides us).
51 if (!fCachedImage->unique()) {
52 this->onCopyOnWrite(mode);
53 }
54
55 // regardless of copy-on-write, we must drop our cached image now, so
56 // that the next request will get our new contents.
57 fCachedImage->unref();
58 fCachedImage = NULL;
59 }
60 }
61
newGenerationID()62 uint32_t SkSurface_Base::newGenerationID() {
63 this->installIntoCanvasForDirtyNotification();
64
65 static int32_t gID;
66 return sk_atomic_inc(&gID) + 1;
67 }
68
asSB(SkSurface * surface)69 static SkSurface_Base* asSB(SkSurface* surface) {
70 return static_cast<SkSurface_Base*>(surface);
71 }
72
73 ///////////////////////////////////////////////////////////////////////////////
74
SkSurface(int width,int height)75 SkSurface::SkSurface(int width, int height) : fWidth(width), fHeight(height) {
76 SkASSERT(width >= 0);
77 SkASSERT(height >= 0);
78 fGenerationID = 0;
79 }
80
generationID()81 uint32_t SkSurface::generationID() {
82 if (0 == fGenerationID) {
83 fGenerationID = asSB(this)->newGenerationID();
84 }
85 return fGenerationID;
86 }
87
notifyContentWillChange(ContentChangeMode mode)88 void SkSurface::notifyContentWillChange(ContentChangeMode mode) {
89 asSB(this)->aboutToDraw(mode);
90 }
91
getCanvas()92 SkCanvas* SkSurface::getCanvas() {
93 return asSB(this)->getCachedCanvas();
94 }
95
newImageSnapshot()96 SkImage* SkSurface::newImageSnapshot() {
97 SkImage* image = asSB(this)->getCachedImage();
98 SkSafeRef(image); // the caller will call unref() to balance this
99 return image;
100 }
101
newSurface(const SkImageInfo & info)102 SkSurface* SkSurface::newSurface(const SkImageInfo& info) {
103 return asSB(this)->onNewSurface(info);
104 }
105
draw(SkCanvas * canvas,SkScalar x,SkScalar y,const SkPaint * paint)106 void SkSurface::draw(SkCanvas* canvas, SkScalar x, SkScalar y,
107 const SkPaint* paint) {
108 return asSB(this)->onDraw(canvas, x, y, paint);
109 }
110