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