Upstream version 7.36.149.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     SkASSERT(!fCachedCanvas || fCachedCanvas->getSurfaceBase() == this);
47
48     if (NULL != fCachedImage) {
49         // the surface may need to fork its backend, if its sharing it with
50         // the cached image. Note: we only call if there is an outstanding owner
51         // on the image (besides us).
52         if (!fCachedImage->unique()) {
53             this->onCopyOnWrite(mode);
54         }
55
56         // regardless of copy-on-write, we must drop our cached image now, so
57         // that the next request will get our new contents.
58         fCachedImage->unref();
59         fCachedImage = NULL;
60     } else if (kDiscard_ContentChangeMode == mode) {
61         this->onDiscard();
62     }
63 }
64
65 uint32_t SkSurface_Base::newGenerationID() {
66     SkASSERT(!fCachedCanvas || fCachedCanvas->getSurfaceBase() == this);
67     static int32_t gID;
68     return sk_atomic_inc(&gID) + 1;
69 }
70
71 static SkSurface_Base* asSB(SkSurface* surface) {
72     return static_cast<SkSurface_Base*>(surface);
73 }
74
75 ///////////////////////////////////////////////////////////////////////////////
76
77 SkSurface::SkSurface(int width, int height) : fWidth(width), fHeight(height) {
78     SkASSERT(fWidth >= 0);
79     SkASSERT(fHeight >= 0);
80     fGenerationID = 0;
81 }
82
83 SkSurface::SkSurface(const SkImageInfo& info)
84     : fWidth(info.fWidth)
85     , fHeight(info.fHeight)
86 {
87     SkASSERT(fWidth >= 0);
88     SkASSERT(fHeight >= 0);
89     fGenerationID = 0;
90 }
91
92 uint32_t SkSurface::generationID() {
93     if (0 == fGenerationID) {
94         fGenerationID = asSB(this)->newGenerationID();
95     }
96     return fGenerationID;
97 }
98
99 void SkSurface::notifyContentWillChange(ContentChangeMode mode) {
100     asSB(this)->aboutToDraw(mode);
101 }
102
103 SkCanvas* SkSurface::getCanvas() {
104     return asSB(this)->getCachedCanvas();
105 }
106
107 SkImage* SkSurface::newImageSnapshot() {
108     SkImage* image = asSB(this)->getCachedImage();
109     SkSafeRef(image);   // the caller will call unref() to balance this
110     return image;
111 }
112
113 SkSurface* SkSurface::newSurface(const SkImageInfo& info) {
114     return asSB(this)->onNewSurface(info);
115 }
116
117 void SkSurface::draw(SkCanvas* canvas, SkScalar x, SkScalar y,
118                      const SkPaint* paint) {
119     return asSB(this)->onDraw(canvas, x, y, paint);
120 }
121
122 const void* SkSurface::peekPixels(SkImageInfo* info, size_t* rowBytes) {
123     return this->getCanvas()->peekPixels(info, rowBytes);
124 }