|
1 /* |
|
2 * Copyright 2011 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 "SkDevice.h" |
|
9 #include "SkMetaData.h" |
|
10 |
|
11 #if SK_PMCOLOR_BYTE_ORDER(B,G,R,A) |
|
12 const SkCanvas::Config8888 SkBaseDevice::kPMColorAlias = SkCanvas::kBGRA_Premul_Config8888; |
|
13 #elif SK_PMCOLOR_BYTE_ORDER(R,G,B,A) |
|
14 const SkCanvas::Config8888 SkBaseDevice::kPMColorAlias = SkCanvas::kRGBA_Premul_Config8888; |
|
15 #else |
|
16 const SkCanvas::Config8888 SkBaseDevice::kPMColorAlias = (SkCanvas::Config8888) -1; |
|
17 #endif |
|
18 |
|
19 /////////////////////////////////////////////////////////////////////////////// |
|
20 |
|
21 SkBaseDevice::SkBaseDevice() |
|
22 : fLeakyProperties(SkDeviceProperties::MakeDefault()) |
|
23 #ifdef SK_DEBUG |
|
24 , fAttachedToCanvas(false) |
|
25 #endif |
|
26 { |
|
27 fOrigin.setZero(); |
|
28 fMetaData = NULL; |
|
29 } |
|
30 |
|
31 SkBaseDevice::SkBaseDevice(const SkDeviceProperties& deviceProperties) |
|
32 : fLeakyProperties(deviceProperties) |
|
33 #ifdef SK_DEBUG |
|
34 , fAttachedToCanvas(false) |
|
35 #endif |
|
36 { |
|
37 fOrigin.setZero(); |
|
38 fMetaData = NULL; |
|
39 } |
|
40 |
|
41 SkBaseDevice::~SkBaseDevice() { |
|
42 delete fMetaData; |
|
43 } |
|
44 |
|
45 SkBaseDevice* SkBaseDevice::createCompatibleDevice(const SkImageInfo& info) { |
|
46 #ifdef SK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG |
|
47 // We call the old method to support older subclasses. |
|
48 // If they have, we return their device, else we use the new impl. |
|
49 SkBitmap::Config config = SkColorTypeToBitmapConfig(info.colorType()); |
|
50 SkBaseDevice* dev = this->onCreateCompatibleDevice(config, |
|
51 info.width(), |
|
52 info.height(), |
|
53 info.isOpaque(), |
|
54 kGeneral_Usage); |
|
55 if (dev) { |
|
56 return dev; |
|
57 } |
|
58 // fall through to new impl |
|
59 #endif |
|
60 return this->onCreateDevice(info, kGeneral_Usage); |
|
61 } |
|
62 |
|
63 SkBaseDevice* SkBaseDevice::createCompatibleDeviceForSaveLayer(const SkImageInfo& info) { |
|
64 #ifdef SK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG |
|
65 // We call the old method to support older subclasses. |
|
66 // If they have, we return their device, else we use the new impl. |
|
67 SkBitmap::Config config = SkColorTypeToBitmapConfig(info.colorType()); |
|
68 SkBaseDevice* dev = this->onCreateCompatibleDevice(config, |
|
69 info.width(), |
|
70 info.height(), |
|
71 info.isOpaque(), |
|
72 kSaveLayer_Usage); |
|
73 if (dev) { |
|
74 return dev; |
|
75 } |
|
76 // fall through to new impl |
|
77 #endif |
|
78 return this->onCreateDevice(info, kSaveLayer_Usage); |
|
79 } |
|
80 |
|
81 #ifdef SK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG |
|
82 SkBaseDevice* SkBaseDevice::createCompatibleDevice(SkBitmap::Config config, |
|
83 int width, int height, |
|
84 bool isOpaque) { |
|
85 SkImageInfo info = SkImageInfo::Make(width, height, |
|
86 SkBitmapConfigToColorType(config), |
|
87 isOpaque ? kOpaque_SkAlphaType |
|
88 : kPremul_SkAlphaType); |
|
89 return this->createCompatibleDevice(info); |
|
90 } |
|
91 #endif |
|
92 |
|
93 SkMetaData& SkBaseDevice::getMetaData() { |
|
94 // metadata users are rare, so we lazily allocate it. If that changes we |
|
95 // can decide to just make it a field in the device (rather than a ptr) |
|
96 if (NULL == fMetaData) { |
|
97 fMetaData = new SkMetaData; |
|
98 } |
|
99 return *fMetaData; |
|
100 } |
|
101 |
|
102 // TODO: should make this guy pure-virtual. |
|
103 SkImageInfo SkBaseDevice::imageInfo() const { |
|
104 return SkImageInfo::MakeUnknown(this->width(), this->height()); |
|
105 } |
|
106 |
|
107 const SkBitmap& SkBaseDevice::accessBitmap(bool changePixels) { |
|
108 const SkBitmap& bitmap = this->onAccessBitmap(); |
|
109 if (changePixels) { |
|
110 bitmap.notifyPixelsChanged(); |
|
111 } |
|
112 return bitmap; |
|
113 } |
|
114 |
|
115 bool SkBaseDevice::readPixels(SkBitmap* bitmap, int x, int y, |
|
116 SkCanvas::Config8888 config8888) { |
|
117 if (SkBitmap::kARGB_8888_Config != bitmap->config() || |
|
118 NULL != bitmap->getTexture()) { |
|
119 return false; |
|
120 } |
|
121 |
|
122 const SkBitmap& src = this->accessBitmap(false); |
|
123 |
|
124 SkIRect srcRect = SkIRect::MakeXYWH(x, y, bitmap->width(), |
|
125 bitmap->height()); |
|
126 SkIRect devbounds = SkIRect::MakeWH(src.width(), src.height()); |
|
127 if (!srcRect.intersect(devbounds)) { |
|
128 return false; |
|
129 } |
|
130 |
|
131 SkBitmap tmp; |
|
132 SkBitmap* bmp; |
|
133 if (bitmap->isNull()) { |
|
134 if (!tmp.allocPixels(SkImageInfo::MakeN32Premul(bitmap->width(), |
|
135 bitmap->height()))) { |
|
136 return false; |
|
137 } |
|
138 bmp = &tmp; |
|
139 } else { |
|
140 bmp = bitmap; |
|
141 } |
|
142 |
|
143 SkIRect subrect = srcRect; |
|
144 subrect.offset(-x, -y); |
|
145 SkBitmap bmpSubset; |
|
146 bmp->extractSubset(&bmpSubset, subrect); |
|
147 |
|
148 bool result = this->onReadPixels(bmpSubset, |
|
149 srcRect.fLeft, |
|
150 srcRect.fTop, |
|
151 config8888); |
|
152 if (result && bmp == &tmp) { |
|
153 tmp.swap(*bitmap); |
|
154 } |
|
155 return result; |
|
156 } |
|
157 |
|
158 SkSurface* SkBaseDevice::newSurface(const SkImageInfo&) { return NULL; } |
|
159 |
|
160 const void* SkBaseDevice::peekPixels(SkImageInfo*, size_t*) { return NULL; } |
|
161 |
|
162 void SkBaseDevice::drawDRRect(const SkDraw& draw, const SkRRect& outer, |
|
163 const SkRRect& inner, const SkPaint& paint) { |
|
164 SkPath path; |
|
165 path.addRRect(outer); |
|
166 path.addRRect(inner); |
|
167 path.setFillType(SkPath::kEvenOdd_FillType); |
|
168 |
|
169 const SkMatrix* preMatrix = NULL; |
|
170 const bool pathIsMutable = true; |
|
171 this->drawPath(draw, path, paint, preMatrix, pathIsMutable); |
|
172 } |
|
173 |
|
174 bool SkBaseDevice::writePixelsDirect(const SkImageInfo& info, const void* pixels, size_t rowBytes, |
|
175 int x, int y) { |
|
176 #ifdef SK_DEBUG |
|
177 SkASSERT(info.width() > 0 && info.height() > 0); |
|
178 SkASSERT(pixels); |
|
179 SkASSERT(rowBytes >= info.minRowBytes()); |
|
180 SkASSERT(x >= 0 && y >= 0); |
|
181 |
|
182 const SkImageInfo& dstInfo = this->imageInfo(); |
|
183 SkASSERT(x + info.width() <= dstInfo.width()); |
|
184 SkASSERT(y + info.height() <= dstInfo.height()); |
|
185 #endif |
|
186 return this->onWritePixels(info, pixels, rowBytes, x, y); |
|
187 } |
|
188 |
|
189 bool SkBaseDevice::onWritePixels(const SkImageInfo&, const void*, size_t, int, int) { |
|
190 return false; |
|
191 } |
|
192 |
|
193 bool SkBaseDevice::onReadPixels(const SkBitmap&, int x, int y, SkCanvas::Config8888) { |
|
194 return false; |
|
195 } |
|
196 |
|
197 void* SkBaseDevice::accessPixels(SkImageInfo* info, size_t* rowBytes) { |
|
198 SkImageInfo tmpInfo; |
|
199 size_t tmpRowBytes; |
|
200 if (NULL == info) { |
|
201 info = &tmpInfo; |
|
202 } |
|
203 if (NULL == rowBytes) { |
|
204 rowBytes = &tmpRowBytes; |
|
205 } |
|
206 return this->onAccessPixels(info, rowBytes); |
|
207 } |
|
208 |
|
209 void* SkBaseDevice::onAccessPixels(SkImageInfo* info, size_t* rowBytes) { |
|
210 return NULL; |
|
211 } |
|
212 |
|
213 #ifdef SK_SUPPORT_LEGACY_WRITEPIXELSCONFIG |
|
214 void SkBaseDevice::writePixels(const SkBitmap&, int x, int y, SkCanvas::Config8888) {} |
|
215 #endif |
|
216 |
|
217 void SkBaseDevice::EXPERIMENTAL_optimize(SkPicture* picture) { |
|
218 // The base class doesn't perform any analysis but derived classes may |
|
219 } |
|
220 |
|
221 bool SkBaseDevice::EXPERIMENTAL_drawPicture(const SkPicture& picture) { |
|
222 // The base class doesn't perform any accelerated picture rendering |
|
223 return false; |
|
224 } |