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