• 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 #include "SkDevice.h"
12 #include "SkMallocPixelRef.h"
13 
14 static const size_t kIgnoreRowBytesValue = (size_t)~0;
15 
16 class SkSurface_Raster : public SkSurface_Base {
17 public:
18     static bool Valid(const SkImageInfo&, size_t rb = kIgnoreRowBytesValue);
19 
20     SkSurface_Raster(const SkImageInfo&, void*, size_t rb);
21     SkSurface_Raster(const SkImageInfo&, SkPixelRef*, size_t rb);
22 
23     virtual SkCanvas* onNewCanvas() SK_OVERRIDE;
24     virtual SkSurface* onNewSurface(const SkImageInfo&) SK_OVERRIDE;
25     virtual SkImage* onNewImageSnapshot() SK_OVERRIDE;
26     virtual void onDraw(SkCanvas*, SkScalar x, SkScalar y,
27                         const SkPaint*) SK_OVERRIDE;
28     virtual void onCopyOnWrite(ContentChangeMode) SK_OVERRIDE;
29 
30 private:
31     SkBitmap    fBitmap;
32     bool        fWeOwnThePixels;
33 
34     typedef SkSurface_Base INHERITED;
35 };
36 
37 ///////////////////////////////////////////////////////////////////////////////
38 
Valid(const SkImageInfo & info,size_t rowBytes)39 bool SkSurface_Raster::Valid(const SkImageInfo& info, size_t rowBytes) {
40     static const size_t kMaxTotalSize = SK_MaxS32;
41 
42     SkBitmap::Config config = SkImageInfoToBitmapConfig(info);
43 
44     int shift = 0;
45     switch (config) {
46         case SkBitmap::kA8_Config:
47             shift = 0;
48             break;
49         case SkBitmap::kRGB_565_Config:
50             shift = 1;
51             break;
52         case SkBitmap::kARGB_8888_Config:
53             shift = 2;
54             break;
55         default:
56             return false;
57     }
58 
59     // TODO: examine colorspace
60 
61     if (kIgnoreRowBytesValue == rowBytes) {
62         return true;
63     }
64 
65     uint64_t minRB = (uint64_t)info.fWidth << shift;
66     if (minRB > rowBytes) {
67         return false;
68     }
69 
70     size_t alignedRowBytes = rowBytes >> shift << shift;
71     if (alignedRowBytes != rowBytes) {
72         return false;
73     }
74 
75     uint64_t size = (uint64_t)info.fHeight * rowBytes;
76     if (size > kMaxTotalSize) {
77         return false;
78     }
79 
80     return true;
81 }
82 
SkSurface_Raster(const SkImageInfo & info,void * pixels,size_t rb)83 SkSurface_Raster::SkSurface_Raster(const SkImageInfo& info, void* pixels, size_t rb)
84         : INHERITED(info.fWidth, info.fHeight) {
85     SkBitmap::Config config = SkImageInfoToBitmapConfig(info);
86     fBitmap.setConfig(config, info.fWidth, info.fHeight, rb, info.fAlphaType);
87     fBitmap.setPixels(pixels);
88     fWeOwnThePixels = false;    // We are "Direct"
89 }
90 
SkSurface_Raster(const SkImageInfo & info,SkPixelRef * pr,size_t rb)91 SkSurface_Raster::SkSurface_Raster(const SkImageInfo& info, SkPixelRef* pr, size_t rb)
92         : INHERITED(info.fWidth, info.fHeight) {
93     SkBitmap::Config config = SkImageInfoToBitmapConfig(info);
94     fBitmap.setConfig(config, info.fWidth, info.fHeight, rb, info.fAlphaType);
95     fBitmap.setPixelRef(pr);
96     fWeOwnThePixels = true;
97 
98     if (!SkAlphaTypeIsOpaque(info.fAlphaType)) {
99         fBitmap.eraseColor(SK_ColorTRANSPARENT);
100     }
101 }
102 
onNewCanvas()103 SkCanvas* SkSurface_Raster::onNewCanvas() {
104     return SkNEW_ARGS(SkCanvas, (fBitmap));
105 }
106 
onNewSurface(const SkImageInfo & info)107 SkSurface* SkSurface_Raster::onNewSurface(const SkImageInfo& info) {
108     return SkSurface::NewRaster(info);
109 }
110 
onDraw(SkCanvas * canvas,SkScalar x,SkScalar y,const SkPaint * paint)111 void SkSurface_Raster::onDraw(SkCanvas* canvas, SkScalar x, SkScalar y,
112                               const SkPaint* paint) {
113     canvas->drawBitmap(fBitmap, x, y, paint);
114 }
115 
onNewImageSnapshot()116 SkImage* SkSurface_Raster::onNewImageSnapshot() {
117     return SkNewImageFromBitmap(fBitmap, fWeOwnThePixels);
118 }
119 
onCopyOnWrite(ContentChangeMode mode)120 void SkSurface_Raster::onCopyOnWrite(ContentChangeMode mode) {
121     // are we sharing pixelrefs with the image?
122     SkASSERT(NULL != this->getCachedImage());
123     if (SkBitmapImageGetPixelRef(this->getCachedImage()) == fBitmap.pixelRef()) {
124         SkASSERT(fWeOwnThePixels);
125         if (kDiscard_ContentChangeMode == mode) {
126             fBitmap.setPixelRef(NULL, 0);
127             fBitmap.allocPixels();
128         } else {
129             SkBitmap prev(fBitmap);
130             prev.deepCopyTo(&fBitmap, prev.config());
131         }
132         // Now fBitmap is a deep copy of itself (and therefore different from
133         // what is being used by the image. Next we update the canvas to use
134         // this as its backend, so we can't modify the image's pixels anymore.
135         SkASSERT(NULL != this->getCachedCanvas());
136         this->getCachedCanvas()->getDevice()->replaceBitmapBackendForRasterSurface(fBitmap);
137     }
138 }
139 
140 ///////////////////////////////////////////////////////////////////////////////
141 
NewRasterDirect(const SkImageInfo & info,void * pixels,size_t rowBytes)142 SkSurface* SkSurface::NewRasterDirect(const SkImageInfo& info, void* pixels, size_t rowBytes) {
143     if (!SkSurface_Raster::Valid(info, rowBytes)) {
144         return NULL;
145     }
146     if (NULL == pixels) {
147         return NULL;
148     }
149 
150     return SkNEW_ARGS(SkSurface_Raster, (info, pixels, rowBytes));
151 }
152 
NewRaster(const SkImageInfo & info)153 SkSurface* SkSurface::NewRaster(const SkImageInfo& info) {
154     if (!SkSurface_Raster::Valid(info)) {
155         return NULL;
156     }
157 
158     SkAutoTUnref<SkPixelRef> pr(SkMallocPixelRef::NewAllocate(info, 0, NULL));
159     if (NULL == pr.get()) {
160         return NULL;
161     }
162     return SkNEW_ARGS(SkSurface_Raster, (info, pr, info.minRowBytes()));
163 }
164