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