1 :
2 : /*
3 : * Copyright 2011 Google Inc.
4 : *
5 : * Use of this source code is governed by a BSD-style license that can be
6 : * found in the LICENSE file.
7 : */
8 : #include "SkDevice.h"
9 : #include "SkDraw.h"
10 : #include "SkImageFilter.h"
11 : #include "SkMetaData.h"
12 : #include "SkRect.h"
13 :
14 : ///////////////////////////////////////////////////////////////////////////////
15 :
16 0 : SkDevice::SkDevice(const SkBitmap& bitmap) : fBitmap(bitmap) {
17 0 : fOrigin.setZero();
18 0 : fMetaData = NULL;
19 0 : }
20 :
21 0 : SkDevice::SkDevice(SkBitmap::Config config, int width, int height, bool isOpaque) {
22 0 : fOrigin.setZero();
23 0 : fMetaData = NULL;
24 :
25 0 : fBitmap.setConfig(config, width, height);
26 0 : fBitmap.allocPixels();
27 0 : fBitmap.setIsOpaque(isOpaque);
28 0 : if (!isOpaque) {
29 0 : fBitmap.eraseColor(0);
30 : }
31 0 : }
32 :
33 0 : SkDevice::~SkDevice() {
34 0 : delete fMetaData;
35 0 : }
36 :
37 0 : SkDevice* SkDevice::createCompatibleDevice(SkBitmap::Config config,
38 : int width, int height,
39 : bool isOpaque) {
40 : return this->onCreateCompatibleDevice(config, width, height,
41 0 : isOpaque, kGeneral_Usage);
42 : }
43 :
44 0 : SkDevice* SkDevice::createCompatibleDeviceForSaveLayer(SkBitmap::Config config,
45 : int width, int height,
46 : bool isOpaque) {
47 : return this->onCreateCompatibleDevice(config, width, height,
48 0 : isOpaque, kSaveLayer_Usage);
49 : }
50 :
51 0 : SkDevice* SkDevice::onCreateCompatibleDevice(SkBitmap::Config config,
52 : int width, int height,
53 : bool isOpaque,
54 : Usage usage) {
55 0 : return SkNEW_ARGS(SkDevice,(config, width, height, isOpaque));
56 : }
57 :
58 0 : SkMetaData& SkDevice::getMetaData() {
59 : // metadata users are rare, so we lazily allocate it. If that changes we
60 : // can decide to just make it a field in the device (rather than a ptr)
61 0 : if (NULL == fMetaData) {
62 0 : fMetaData = new SkMetaData;
63 : }
64 0 : return *fMetaData;
65 : }
66 :
67 0 : void SkDevice::lockPixels() {
68 0 : if (fBitmap.lockPixelsAreWritable()) {
69 0 : fBitmap.lockPixels();
70 : }
71 0 : }
72 :
73 0 : void SkDevice::unlockPixels() {
74 0 : if (fBitmap.lockPixelsAreWritable()) {
75 0 : fBitmap.unlockPixels();
76 : }
77 0 : }
78 :
79 0 : const SkBitmap& SkDevice::accessBitmap(bool changePixels) {
80 0 : this->onAccessBitmap(&fBitmap);
81 0 : if (changePixels) {
82 0 : fBitmap.notifyPixelsChanged();
83 : }
84 0 : return fBitmap;
85 : }
86 :
87 0 : void SkDevice::getGlobalBounds(SkIRect* bounds) const {
88 0 : if (bounds) {
89 : bounds->setXYWH(fOrigin.x(), fOrigin.y(),
90 0 : fBitmap.width(), fBitmap.height());
91 : }
92 0 : }
93 :
94 0 : void SkDevice::clear(SkColor color) {
95 0 : fBitmap.eraseColor(color);
96 0 : }
97 :
98 0 : void SkDevice::onAccessBitmap(SkBitmap* bitmap) {}
99 :
100 0 : void SkDevice::setMatrixClip(const SkMatrix& matrix, const SkRegion& region,
101 : const SkClipStack& clipStack) {
102 0 : }
103 :
104 0 : bool SkDevice::filterImage(SkImageFilter*, const SkBitmap& src,
105 : const SkMatrix& ctm,
106 : SkBitmap* result, SkIPoint* offset) {
107 0 : return false;
108 : }
109 :
110 : ///////////////////////////////////////////////////////////////////////////////
111 :
112 0 : bool SkDevice::readPixels(SkBitmap* bitmap, int x, int y,
113 : SkCanvas::Config8888 config8888) {
114 0 : if (SkBitmap::kARGB_8888_Config != bitmap->config() ||
115 0 : NULL != bitmap->getTexture()) {
116 0 : return false;
117 : }
118 :
119 0 : const SkBitmap& src = this->accessBitmap(false);
120 :
121 : SkIRect srcRect = SkIRect::MakeXYWH(x, y, bitmap->width(),
122 0 : bitmap->height());
123 0 : SkIRect devbounds = SkIRect::MakeWH(src.width(), src.height());
124 0 : if (!srcRect.intersect(devbounds)) {
125 0 : return false;
126 : }
127 :
128 0 : SkBitmap tmp;
129 : SkBitmap* bmp;
130 0 : if (bitmap->isNull()) {
131 : tmp.setConfig(SkBitmap::kARGB_8888_Config, bitmap->width(),
132 0 : bitmap->height());
133 0 : if (!tmp.allocPixels()) {
134 0 : return false;
135 : }
136 0 : bmp = &tmp;
137 : } else {
138 0 : bmp = bitmap;
139 : }
140 :
141 0 : SkIRect subrect = srcRect;
142 0 : subrect.offset(-x, -y);
143 0 : SkBitmap bmpSubset;
144 0 : bmp->extractSubset(&bmpSubset, subrect);
145 :
146 : bool result = this->onReadPixels(bmpSubset,
147 : srcRect.fLeft,
148 : srcRect.fTop,
149 0 : config8888);
150 0 : if (result && bmp == &tmp) {
151 0 : tmp.swap(*bitmap);
152 : }
153 0 : return result;
154 : }
155 :
156 : #ifdef SK_CPU_LENDIAN
157 : #if 24 == SK_A32_SHIFT && 16 == SK_R32_SHIFT && \
158 : 8 == SK_G32_SHIFT && 0 == SK_B32_SHIFT
159 : const SkCanvas::Config8888 SkDevice::kPMColorAlias =
160 : SkCanvas::kBGRA_Premul_Config8888;
161 : #elif 24 == SK_A32_SHIFT && 0 == SK_R32_SHIFT && \
162 : 8 == SK_G32_SHIFT && 16 == SK_B32_SHIFT
163 : const SkCanvas::Config8888 SkDevice::kPMColorAlias =
164 : SkCanvas::kRGBA_Premul_Config8888;
165 : #else
166 : const SkCanvas::Config8888 SkDevice::kPMColorAlias =
167 : (SkCanvas::Config8888) -1;
168 : #endif
169 : #else
170 : #if 0 == SK_A32_SHIFT && 8 == SK_R32_SHIFT && \
171 : 16 == SK_G32_SHIFT && 24 == SK_B32_SHIFT
172 : const SkCanvas::Config8888 SkDevice::kPMColorAlias =
173 : SkCanvas::kBGRA_Premul_Config8888;
174 : #elif 0 == SK_A32_SHIFT && 24 == SK_R32_SHIFT && \
175 : 16 == SK_G32_SHIFT && 8 == SK_B32_SHIFT
176 : const SkCanvas::Config8888 SkDevice::kPMColorAlias =
177 : SkCanvas::kRGBA_Premul_Config8888;
178 : #else
179 : const SkCanvas::Config8888 SkDevice::kPMColorAlias =
180 : (SkCanvas::Config8888) -1;
181 : #endif
182 : #endif
183 :
184 : #include <SkConfig8888.h>
185 :
186 0 : bool SkDevice::onReadPixels(const SkBitmap& bitmap,
187 : int x, int y,
188 : SkCanvas::Config8888 config8888) {
189 0 : SkASSERT(SkBitmap::kARGB_8888_Config == bitmap.config());
190 0 : SkASSERT(!bitmap.isNull());
191 0 : SkASSERT(SkIRect::MakeWH(this->width(), this->height()).contains(SkIRect::MakeXYWH(x, y, bitmap.width(), bitmap.height())));
192 :
193 : SkIRect srcRect = SkIRect::MakeXYWH(x, y, bitmap.width(),
194 0 : bitmap.height());
195 0 : const SkBitmap& src = this->accessBitmap(false);
196 :
197 0 : SkBitmap subset;
198 0 : if (!src.extractSubset(&subset, srcRect)) {
199 0 : return false;
200 : }
201 0 : if (SkBitmap::kARGB_8888_Config != subset.config()) {
202 : // It'd be preferable to do this directly to bitmap.
203 0 : subset.copyTo(&subset, SkBitmap::kARGB_8888_Config);
204 : }
205 0 : SkAutoLockPixels alp(bitmap);
206 0 : uint32_t* bmpPixels = reinterpret_cast<uint32_t*>(bitmap.getPixels());
207 0 : if ((SkCanvas::kNative_Premul_Config8888 == config8888 ||
208 : kPMColorAlias == config8888)) {
209 0 : SkCopyARGB8888BitmapTo(bmpPixels, bitmap.rowBytes(), subset);
210 : } else {
211 : SkCopyBitmapToConfig8888(bmpPixels,
212 0 : bitmap.rowBytes(),
213 : config8888,
214 0 : subset);
215 : }
216 0 : return true;
217 : }
218 :
219 0 : void SkDevice::writePixels(const SkBitmap& bitmap,
220 : int x, int y,
221 : SkCanvas::Config8888 config8888) {
222 0 : if (bitmap.isNull() || bitmap.getTexture()) {
223 0 : return;
224 : }
225 0 : const SkBitmap* sprite = &bitmap;
226 : // check whether we have to handle a config8888 that doesn't match SkPMColor
227 0 : if (SkBitmap::kARGB_8888_Config == bitmap.config() &&
228 : SkCanvas::kNative_Premul_Config8888 != config8888 &&
229 : kPMColorAlias != config8888) {
230 :
231 : // We're going to have to convert from a config8888 to the native config
232 : // First we clip to the device bounds.
233 0 : SkBitmap dstBmp = this->accessBitmap(true);
234 : SkIRect spriteRect = SkIRect::MakeXYWH(x, y,
235 0 : bitmap.width(), bitmap.height());
236 0 : SkIRect devRect = SkIRect::MakeWH(dstBmp.width(), dstBmp.height());
237 0 : if (!spriteRect.intersect(devRect)) {
238 : return;
239 : }
240 :
241 : // write directly to the device if it has pixels and is SkPMColor
242 : bool drawSprite;
243 0 : if (SkBitmap::kARGB_8888_Config == dstBmp.config() && !dstBmp.isNull()) {
244 : // we can write directly to the dst when doing the conversion
245 0 : dstBmp.extractSubset(&dstBmp, spriteRect);
246 0 : drawSprite = false;
247 : } else {
248 : // we convert to a temporary bitmap and draw that as a sprite
249 : dstBmp.setConfig(SkBitmap::kARGB_8888_Config,
250 : spriteRect.width(),
251 0 : spriteRect.height());
252 0 : if (!dstBmp.allocPixels()) {
253 : return;
254 : }
255 0 : drawSprite = true;
256 : }
257 :
258 : // copy pixels to dstBmp and convert from config8888 to native config.
259 0 : SkAutoLockPixels alp(bitmap);
260 : uint32_t* srcPixels = bitmap.getAddr32(spriteRect.fLeft - x,
261 0 : spriteRect.fTop - y);
262 : SkCopyConfig8888ToBitmap(dstBmp,
263 : srcPixels,
264 0 : bitmap.rowBytes(),
265 0 : config8888);
266 :
267 0 : if (drawSprite) {
268 : // we've clipped the sprite when we made a copy
269 0 : x = spriteRect.fLeft;
270 0 : y = spriteRect.fTop;
271 0 : sprite = &dstBmp;
272 : } else {
273 : return;
274 : }
275 : }
276 :
277 0 : SkPaint paint;
278 0 : paint.setXfermodeMode(SkXfermode::kSrc_Mode);
279 0 : SkCanvas canvas(this);
280 0 : canvas.drawSprite(*sprite, x, y, &paint);
281 : }
282 :
283 : ///////////////////////////////////////////////////////////////////////////////
284 :
285 0 : void SkDevice::drawPaint(const SkDraw& draw, const SkPaint& paint) {
286 0 : draw.drawPaint(paint);
287 0 : }
288 :
289 0 : void SkDevice::drawPoints(const SkDraw& draw, SkCanvas::PointMode mode, size_t count,
290 : const SkPoint pts[], const SkPaint& paint) {
291 0 : draw.drawPoints(mode, count, pts, paint);
292 0 : }
293 :
294 0 : void SkDevice::drawRect(const SkDraw& draw, const SkRect& r,
295 : const SkPaint& paint) {
296 0 : draw.drawRect(r, paint);
297 0 : }
298 :
299 0 : void SkDevice::drawPath(const SkDraw& draw, const SkPath& path,
300 : const SkPaint& paint, const SkMatrix* prePathMatrix,
301 : bool pathIsMutable) {
302 0 : draw.drawPath(path, paint, prePathMatrix, pathIsMutable);
303 0 : }
304 :
305 0 : void SkDevice::drawBitmap(const SkDraw& draw, const SkBitmap& bitmap,
306 : const SkIRect* srcRect,
307 : const SkMatrix& matrix, const SkPaint& paint) {
308 0 : SkBitmap tmp; // storage if we need a subset of bitmap
309 0 : const SkBitmap* bitmapPtr = &bitmap;
310 :
311 0 : if (srcRect) {
312 0 : if (!bitmap.extractSubset(&tmp, *srcRect)) {
313 : return; // extraction failed
314 : }
315 0 : bitmapPtr = &tmp;
316 : }
317 0 : draw.drawBitmap(*bitmapPtr, matrix, paint);
318 : }
319 :
320 0 : void SkDevice::drawSprite(const SkDraw& draw, const SkBitmap& bitmap,
321 : int x, int y, const SkPaint& paint) {
322 0 : draw.drawSprite(bitmap, x, y, paint);
323 0 : }
324 :
325 0 : void SkDevice::drawText(const SkDraw& draw, const void* text, size_t len,
326 : SkScalar x, SkScalar y, const SkPaint& paint) {
327 0 : draw.drawText((const char*)text, len, x, y, paint);
328 0 : }
329 :
330 0 : void SkDevice::drawPosText(const SkDraw& draw, const void* text, size_t len,
331 : const SkScalar xpos[], SkScalar y,
332 : int scalarsPerPos, const SkPaint& paint) {
333 0 : draw.drawPosText((const char*)text, len, xpos, y, scalarsPerPos, paint);
334 0 : }
335 :
336 0 : void SkDevice::drawTextOnPath(const SkDraw& draw, const void* text,
337 : size_t len, const SkPath& path,
338 : const SkMatrix* matrix,
339 : const SkPaint& paint) {
340 0 : draw.drawTextOnPath((const char*)text, len, path, matrix, paint);
341 0 : }
342 :
343 : #ifdef SK_BUILD_FOR_ANDROID
344 : void SkDevice::drawPosTextOnPath(const SkDraw& draw, const void* text, size_t len,
345 : const SkPoint pos[], const SkPaint& paint,
346 : const SkPath& path, const SkMatrix* matrix) {
347 : draw.drawPosTextOnPath((const char*)text, len, pos, paint, path, matrix);
348 : }
349 : #endif
350 :
351 0 : void SkDevice::drawVertices(const SkDraw& draw, SkCanvas::VertexMode vmode,
352 : int vertexCount,
353 : const SkPoint verts[], const SkPoint textures[],
354 : const SkColor colors[], SkXfermode* xmode,
355 : const uint16_t indices[], int indexCount,
356 : const SkPaint& paint) {
357 : draw.drawVertices(vmode, vertexCount, verts, textures, colors, xmode,
358 0 : indices, indexCount, paint);
359 0 : }
360 :
361 0 : void SkDevice::drawDevice(const SkDraw& draw, SkDevice* device,
362 : int x, int y, const SkPaint& paint) {
363 0 : const SkBitmap& src = device->accessBitmap(false);
364 0 : draw.drawSprite(src, x, y, paint);
365 0 : }
366 :
367 : ///////////////////////////////////////////////////////////////////////////////
368 :
369 0 : bool SkDevice::filterTextFlags(const SkPaint& paint, TextFlags* flags) {
370 0 : if (!paint.isLCDRenderText() || !paint.isAntiAlias()) {
371 : // we're cool with the paint as is
372 0 : return false;
373 : }
374 :
375 0 : if (SkBitmap::kARGB_8888_Config != fBitmap.config() ||
376 0 : paint.getRasterizer() ||
377 0 : paint.getPathEffect() ||
378 0 : paint.isFakeBoldText() ||
379 0 : paint.getStyle() != SkPaint::kFill_Style ||
380 0 : !SkXfermode::IsMode(paint.getXfermode(), SkXfermode::kSrcOver_Mode)) {
381 : // turn off lcd
382 0 : flags->fFlags = paint.getFlags() & ~SkPaint::kLCDRenderText_Flag;
383 0 : flags->fHinting = paint.getHinting();
384 0 : return true;
385 : }
386 : // we're cool with the paint as is
387 0 : return false;
388 : }
389 :
|