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