• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
SK_DEFINE_INST_COUNT(SkSurface)12 SK_DEFINE_INST_COUNT(SkSurface)
13 
14 ///////////////////////////////////////////////////////////////////////////////
15 
16 void SkSurface_Base::installIntoCanvasForDirtyNotification() {
17     if (fCachedCanvas) {
18         fCachedCanvas->setSurfaceBase(this);
19     }
20 }
21 
SkSurface_Base(int width,int height)22 SkSurface_Base::SkSurface_Base(int width, int height) : INHERITED(width, height) {
23     fCachedCanvas = NULL;
24     fCachedImage = NULL;
25 }
26 
~SkSurface_Base()27 SkSurface_Base::~SkSurface_Base() {
28     // in case the canvas outsurvives us, we null the callback
29     if (fCachedCanvas) {
30         fCachedCanvas->setSurfaceBase(NULL);
31     }
32 
33     SkSafeUnref(fCachedImage);
34     SkSafeUnref(fCachedCanvas);
35 }
36 
onDraw(SkCanvas * canvas,SkScalar x,SkScalar y,const SkPaint * paint)37 void SkSurface_Base::onDraw(SkCanvas* canvas, SkScalar x, SkScalar y,
38                             const SkPaint* paint) {
39     SkImage* image = this->newImageShapshot();
40     if (image) {
41         image->draw(canvas, x, y, paint);
42         image->unref();
43     }
44 }
45 
getCachedCanvas()46 SkCanvas* SkSurface_Base::getCachedCanvas() {
47     if (NULL == fCachedCanvas) {
48         fCachedCanvas = this->onNewCanvas();
49         this->installIntoCanvasForDirtyNotification();
50     }
51     return fCachedCanvas;
52 }
53 
getCachedImage()54 SkImage* SkSurface_Base::getCachedImage() {
55     if (NULL == fCachedImage) {
56         fCachedImage = this->onNewImageShapshot();
57         this->installIntoCanvasForDirtyNotification();
58     }
59     return fCachedImage;
60 }
61 
aboutToDraw(SkCanvas * canvas)62 void SkSurface_Base::aboutToDraw(SkCanvas* canvas) {
63     this->dirtyGenerationID();
64 
65     if (canvas) {
66         SkASSERT(canvas == fCachedCanvas);
67         SkASSERT(canvas->getSurfaceBase() == this);
68         canvas->setSurfaceBase(NULL);
69     }
70 
71     if (fCachedImage) {
72         // the surface may need to fork its backend, if its sharing it with
73         // the cached image. Note: we only call if there is an outstanding owner
74         // on the image (besides us).
75         if (fCachedImage->getRefCnt() > 1) {
76             this->onCopyOnWrite(fCachedImage, canvas);
77         }
78 
79         // regardless of copy-on-write, we must drop our cached image now, so
80         // that the next request will get our new contents.
81         fCachedImage->unref();
82         fCachedImage = NULL;
83     }
84 }
85 
newGenerationID()86 uint32_t SkSurface_Base::newGenerationID() {
87     this->installIntoCanvasForDirtyNotification();
88 
89     static int32_t gID;
90     return sk_atomic_inc(&gID) + 1;
91 }
92 
asSB(SkSurface * surface)93 static SkSurface_Base* asSB(SkSurface* surface) {
94     return static_cast<SkSurface_Base*>(surface);
95 }
96 
97 ///////////////////////////////////////////////////////////////////////////////
98 
SkSurface(int width,int height)99 SkSurface::SkSurface(int width, int height) : fWidth(width), fHeight(height) {
100     SkASSERT(width >= 0);
101     SkASSERT(height >= 0);
102     fGenerationID = 0;
103 }
104 
generationID()105 uint32_t SkSurface::generationID() {
106     if (0 == fGenerationID) {
107         fGenerationID = asSB(this)->newGenerationID();
108     }
109     return fGenerationID;
110 }
111 
notifyContentChanged()112 void SkSurface::notifyContentChanged() {
113     asSB(this)->aboutToDraw(NULL);
114 }
115 
getCanvas()116 SkCanvas* SkSurface::getCanvas() {
117     return asSB(this)->getCachedCanvas();
118 }
119 
newImageShapshot()120 SkImage* SkSurface::newImageShapshot() {
121     SkImage* image = asSB(this)->getCachedImage();
122     SkSafeRef(image);   // the caller will call unref() to balance this
123     return image;
124 }
125 
newSurface(const SkImage::Info & info)126 SkSurface* SkSurface::newSurface(const SkImage::Info& info) {
127     return asSB(this)->onNewSurface(info);
128 }
129 
draw(SkCanvas * canvas,SkScalar x,SkScalar y,const SkPaint * paint)130 void SkSurface::draw(SkCanvas* canvas, SkScalar x, SkScalar y,
131                      const SkPaint* paint) {
132     return asSB(this)->onDraw(canvas, x, y, paint);
133 }
134