• Home
  • History
  • Annotate
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2013 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 "SkBitmapDevice.h"
9 #include "SkConfig8888.h"
10 #include "SkDraw.h"
11 #include "SkRasterClip.h"
12 #include "SkShader.h"
13 #include "SkSurface.h"
14 
15 #define CHECK_FOR_ANNOTATION(paint) \
16     do { if (paint.getAnnotation()) { return; } } while (0)
17 
valid_for_bitmap_device(const SkImageInfo & info,SkAlphaType * newAlphaType)18 static bool valid_for_bitmap_device(const SkImageInfo& info,
19                                     SkAlphaType* newAlphaType) {
20     if (info.width() < 0 || info.height() < 0) {
21         return false;
22     }
23 
24     // TODO: can we stop supporting kUnknown in SkBitmkapDevice?
25     if (kUnknown_SkColorType == info.colorType()) {
26         if (newAlphaType) {
27             *newAlphaType = kIgnore_SkAlphaType;
28         }
29         return true;
30     }
31 
32     switch (info.alphaType()) {
33         case kPremul_SkAlphaType:
34         case kOpaque_SkAlphaType:
35             break;
36         default:
37             return false;
38     }
39 
40     SkAlphaType canonicalAlphaType = info.alphaType();
41 
42     switch (info.colorType()) {
43         case kAlpha_8_SkColorType:
44             break;
45         case kRGB_565_SkColorType:
46             canonicalAlphaType = kOpaque_SkAlphaType;
47             break;
48         case kN32_SkColorType:
49             break;
50         default:
51             return false;
52     }
53 
54     if (newAlphaType) {
55         *newAlphaType = canonicalAlphaType;
56     }
57     return true;
58 }
59 
SkBitmapDevice(const SkBitmap & bitmap)60 SkBitmapDevice::SkBitmapDevice(const SkBitmap& bitmap) : fBitmap(bitmap) {
61     SkASSERT(valid_for_bitmap_device(bitmap.info(), NULL));
62 }
63 
64 #if 0
65 SkBitmapDevice::SkBitmapDevice(const SkBitmap& bitmap, const SkDeviceProperties& deviceProperties)
66     : SkBaseDevice(deviceProperties)
67     , fBitmap(bitmap)
68 {
69     SkASSERT(valid_for_bitmap_device(bitmap.info(), NULL));
70 }
71 #endif
72 
Create(const SkImageInfo & origInfo,const SkDeviceProperties * props)73 SkBitmapDevice* SkBitmapDevice::Create(const SkImageInfo& origInfo,
74                                        const SkDeviceProperties* props) {
75     SkAlphaType newAT = origInfo.alphaType();
76     if (!valid_for_bitmap_device(origInfo, &newAT)) {
77         return NULL;
78     }
79 
80     const SkImageInfo info = origInfo.makeAlphaType(newAT);
81     SkBitmap bitmap;
82 
83     if (kUnknown_SkColorType == info.colorType()) {
84         if (!bitmap.setInfo(info)) {
85             return NULL;
86         }
87     } else {
88         if (!bitmap.tryAllocPixels(info)) {
89             return NULL;
90         }
91         if (!bitmap.info().isOpaque()) {
92             bitmap.eraseColor(SK_ColorTRANSPARENT);
93         }
94     }
95 
96     if (props && false) {
97 //        return SkNEW_ARGS(SkBitmapDevice, (bitmap, *props));
98     } else {
99         return SkNEW_ARGS(SkBitmapDevice, (bitmap));
100     }
101 }
102 
imageInfo() const103 SkImageInfo SkBitmapDevice::imageInfo() const {
104     return fBitmap.info();
105 }
106 
replaceBitmapBackendForRasterSurface(const SkBitmap & bm)107 void SkBitmapDevice::replaceBitmapBackendForRasterSurface(const SkBitmap& bm) {
108     SkASSERT(bm.width() == fBitmap.width());
109     SkASSERT(bm.height() == fBitmap.height());
110     fBitmap = bm;   // intent is to use bm's pixelRef (and rowbytes/config)
111     fBitmap.lockPixels();
112 }
113 
onCreateDevice(const SkImageInfo & info,Usage usage)114 SkBaseDevice* SkBitmapDevice::onCreateDevice(const SkImageInfo& info, Usage usage) {
115     return SkBitmapDevice::Create(info);// &this->getDeviceProperties());
116 }
117 
lockPixels()118 void SkBitmapDevice::lockPixels() {
119     if (fBitmap.lockPixelsAreWritable()) {
120         fBitmap.lockPixels();
121     }
122 }
123 
unlockPixels()124 void SkBitmapDevice::unlockPixels() {
125     if (fBitmap.lockPixelsAreWritable()) {
126         fBitmap.unlockPixels();
127     }
128 }
129 
clear(SkColor color)130 void SkBitmapDevice::clear(SkColor color) {
131     fBitmap.eraseColor(color);
132 }
133 
onAccessBitmap()134 const SkBitmap& SkBitmapDevice::onAccessBitmap() {
135     return fBitmap;
136 }
137 
onAccessPixels(SkImageInfo * info,size_t * rowBytes)138 void* SkBitmapDevice::onAccessPixels(SkImageInfo* info, size_t* rowBytes) {
139     if (fBitmap.getPixels()) {
140         *info = fBitmap.info();
141         *rowBytes = fBitmap.rowBytes();
142         return fBitmap.getPixels();
143     }
144     return NULL;
145 }
146 
147 #include "SkConfig8888.h"
148 #include "SkPixelRef.h"
149 
onWritePixels(const SkImageInfo & srcInfo,const void * srcPixels,size_t srcRowBytes,int x,int y)150 bool SkBitmapDevice::onWritePixels(const SkImageInfo& srcInfo, const void* srcPixels,
151                                    size_t srcRowBytes, int x, int y) {
152     // since we don't stop creating un-pixeled devices yet, check for no pixels here
153     if (NULL == fBitmap.getPixels()) {
154         return false;
155     }
156 
157     const SkImageInfo dstInfo = fBitmap.info().makeWH(srcInfo.width(), srcInfo.height());
158 
159     void* dstPixels = fBitmap.getAddr(x, y);
160     size_t dstRowBytes = fBitmap.rowBytes();
161 
162     if (SkPixelInfo::CopyPixels(dstInfo, dstPixels, dstRowBytes, srcInfo, srcPixels, srcRowBytes)) {
163         fBitmap.notifyPixelsChanged();
164         return true;
165     }
166     return false;
167 }
168 
onReadPixels(const SkImageInfo & dstInfo,void * dstPixels,size_t dstRowBytes,int x,int y)169 bool SkBitmapDevice::onReadPixels(const SkImageInfo& dstInfo, void* dstPixels, size_t dstRowBytes,
170                                   int x, int y) {
171     return fBitmap.readPixels(dstInfo, dstPixels, dstRowBytes, x, y);
172 }
173 
174 ///////////////////////////////////////////////////////////////////////////////
175 
drawPaint(const SkDraw & draw,const SkPaint & paint)176 void SkBitmapDevice::drawPaint(const SkDraw& draw, const SkPaint& paint) {
177     draw.drawPaint(paint);
178 }
179 
drawPoints(const SkDraw & draw,SkCanvas::PointMode mode,size_t count,const SkPoint pts[],const SkPaint & paint)180 void SkBitmapDevice::drawPoints(const SkDraw& draw, SkCanvas::PointMode mode, size_t count,
181                                 const SkPoint pts[], const SkPaint& paint) {
182     CHECK_FOR_ANNOTATION(paint);
183     draw.drawPoints(mode, count, pts, paint);
184 }
185 
drawRect(const SkDraw & draw,const SkRect & r,const SkPaint & paint)186 void SkBitmapDevice::drawRect(const SkDraw& draw, const SkRect& r, const SkPaint& paint) {
187     CHECK_FOR_ANNOTATION(paint);
188     draw.drawRect(r, paint);
189 }
190 
drawOval(const SkDraw & draw,const SkRect & oval,const SkPaint & paint)191 void SkBitmapDevice::drawOval(const SkDraw& draw, const SkRect& oval, const SkPaint& paint) {
192     CHECK_FOR_ANNOTATION(paint);
193 
194     SkPath path;
195     path.addOval(oval);
196     // call the VIRTUAL version, so any subclasses who do handle drawPath aren't
197     // required to override drawOval.
198     this->drawPath(draw, path, paint, NULL, true);
199 }
200 
drawRRect(const SkDraw & draw,const SkRRect & rrect,const SkPaint & paint)201 void SkBitmapDevice::drawRRect(const SkDraw& draw, const SkRRect& rrect, const SkPaint& paint) {
202     CHECK_FOR_ANNOTATION(paint);
203 
204 #ifdef SK_IGNORE_BLURRED_RRECT_OPT
205     SkPath  path;
206 
207     path.addRRect(rrect);
208     // call the VIRTUAL version, so any subclasses who do handle drawPath aren't
209     // required to override drawRRect.
210     this->drawPath(draw, path, paint, NULL, true);
211 #else
212     draw.drawRRect(rrect, paint);
213 #endif
214 }
215 
drawPath(const SkDraw & draw,const SkPath & path,const SkPaint & paint,const SkMatrix * prePathMatrix,bool pathIsMutable)216 void SkBitmapDevice::drawPath(const SkDraw& draw, const SkPath& path,
217                               const SkPaint& paint, const SkMatrix* prePathMatrix,
218                               bool pathIsMutable) {
219     CHECK_FOR_ANNOTATION(paint);
220     draw.drawPath(path, paint, prePathMatrix, pathIsMutable);
221 }
222 
drawBitmap(const SkDraw & draw,const SkBitmap & bitmap,const SkMatrix & matrix,const SkPaint & paint)223 void SkBitmapDevice::drawBitmap(const SkDraw& draw, const SkBitmap& bitmap,
224                                 const SkMatrix& matrix, const SkPaint& paint) {
225     draw.drawBitmap(bitmap, matrix, paint);
226 }
227 
drawBitmapRect(const SkDraw & draw,const SkBitmap & bitmap,const SkRect * src,const SkRect & dst,const SkPaint & paint,SkCanvas::DrawBitmapRectFlags flags)228 void SkBitmapDevice::drawBitmapRect(const SkDraw& draw, const SkBitmap& bitmap,
229                                     const SkRect* src, const SkRect& dst,
230                                     const SkPaint& paint,
231                                     SkCanvas::DrawBitmapRectFlags flags) {
232     SkMatrix    matrix;
233     SkRect      bitmapBounds, tmpSrc, tmpDst;
234     SkBitmap    tmpBitmap;
235 
236     bitmapBounds.isetWH(bitmap.width(), bitmap.height());
237 
238     // Compute matrix from the two rectangles
239     if (src) {
240         tmpSrc = *src;
241     } else {
242         tmpSrc = bitmapBounds;
243     }
244     matrix.setRectToRect(tmpSrc, dst, SkMatrix::kFill_ScaleToFit);
245 
246     const SkRect* dstPtr = &dst;
247     const SkBitmap* bitmapPtr = &bitmap;
248 
249     // clip the tmpSrc to the bounds of the bitmap, and recompute dstRect if
250     // needed (if the src was clipped). No check needed if src==null.
251     if (src) {
252         if (!bitmapBounds.contains(*src)) {
253             if (!tmpSrc.intersect(bitmapBounds)) {
254                 return; // nothing to draw
255             }
256             // recompute dst, based on the smaller tmpSrc
257             matrix.mapRect(&tmpDst, tmpSrc);
258             dstPtr = &tmpDst;
259         }
260 
261         // since we may need to clamp to the borders of the src rect within
262         // the bitmap, we extract a subset.
263         SkIRect srcIR;
264         tmpSrc.roundOut(&srcIR);
265         if(bitmap.pixelRef()->getTexture()) {
266             // Accelerated source canvas, don't use extractSubset but readPixels to get the subset.
267             // This way, the pixels are copied in CPU memory instead of GPU memory.
268             bitmap.pixelRef()->readPixels(&tmpBitmap, &srcIR);
269         } else {
270             if (!bitmap.extractSubset(&tmpBitmap, srcIR)) {
271                 return;
272             }
273         }
274         bitmapPtr = &tmpBitmap;
275 
276         // Since we did an extract, we need to adjust the matrix accordingly
277         SkScalar dx = 0, dy = 0;
278         if (srcIR.fLeft > 0) {
279             dx = SkIntToScalar(srcIR.fLeft);
280         }
281         if (srcIR.fTop > 0) {
282             dy = SkIntToScalar(srcIR.fTop);
283         }
284         if (dx || dy) {
285             matrix.preTranslate(dx, dy);
286         }
287 
288         SkRect extractedBitmapBounds;
289         extractedBitmapBounds.isetWH(bitmapPtr->width(), bitmapPtr->height());
290         if (extractedBitmapBounds == tmpSrc) {
291             // no fractional part in src, we can just call drawBitmap
292             goto USE_DRAWBITMAP;
293         }
294     } else {
295         USE_DRAWBITMAP:
296         // We can go faster by just calling drawBitmap, which will concat the
297         // matrix with the CTM, and try to call drawSprite if it can. If not,
298         // it will make a shader and call drawRect, as we do below.
299         this->drawBitmap(draw, *bitmapPtr, matrix, paint);
300         return;
301     }
302 
303     // construct a shader, so we can call drawRect with the dst
304     SkShader* s = SkShader::CreateBitmapShader(*bitmapPtr,
305                                                SkShader::kClamp_TileMode,
306                                                SkShader::kClamp_TileMode,
307                                                &matrix);
308     if (NULL == s) {
309         return;
310     }
311 
312     SkPaint paintWithShader(paint);
313     paintWithShader.setStyle(SkPaint::kFill_Style);
314     paintWithShader.setShader(s)->unref();
315 
316     // Call ourself, in case the subclass wanted to share this setup code
317     // but handle the drawRect code themselves.
318     this->drawRect(draw, *dstPtr, paintWithShader);
319 }
320 
drawSprite(const SkDraw & draw,const SkBitmap & bitmap,int x,int y,const SkPaint & paint)321 void SkBitmapDevice::drawSprite(const SkDraw& draw, const SkBitmap& bitmap,
322                                 int x, int y, const SkPaint& paint) {
323     draw.drawSprite(bitmap, x, y, paint);
324 }
325 
drawText(const SkDraw & draw,const void * text,size_t len,SkScalar x,SkScalar y,const SkPaint & paint)326 void SkBitmapDevice::drawText(const SkDraw& draw, const void* text, size_t len,
327                               SkScalar x, SkScalar y, const SkPaint& paint) {
328     draw.drawText((const char*)text, len, x, y, paint);
329 }
330 
drawPosText(const SkDraw & draw,const void * text,size_t len,const SkScalar xpos[],SkScalar y,int scalarsPerPos,const SkPaint & paint)331 void SkBitmapDevice::drawPosText(const SkDraw& draw, const void* text, size_t len,
332                                  const SkScalar xpos[], SkScalar y,
333                                  int scalarsPerPos, const SkPaint& paint) {
334     draw.drawPosText((const char*)text, len, xpos, y, scalarsPerPos, paint);
335 }
336 
drawTextOnPath(const SkDraw & draw,const void * text,size_t len,const SkPath & path,const SkMatrix * matrix,const SkPaint & paint)337 void SkBitmapDevice::drawTextOnPath(const SkDraw& draw, const void* text,
338                                     size_t len, const SkPath& path,
339                                     const SkMatrix* matrix,
340                                     const SkPaint& paint) {
341     draw.drawTextOnPath((const char*)text, len, path, matrix, paint);
342 }
343 
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)344 void SkBitmapDevice::drawVertices(const SkDraw& draw, SkCanvas::VertexMode vmode,
345                                   int vertexCount,
346                                   const SkPoint verts[], const SkPoint textures[],
347                                   const SkColor colors[], SkXfermode* xmode,
348                                   const uint16_t indices[], int indexCount,
349                                   const SkPaint& paint) {
350     draw.drawVertices(vmode, vertexCount, verts, textures, colors, xmode,
351                       indices, indexCount, paint);
352 }
353 
drawDevice(const SkDraw & draw,SkBaseDevice * device,int x,int y,const SkPaint & paint)354 void SkBitmapDevice::drawDevice(const SkDraw& draw, SkBaseDevice* device,
355                                 int x, int y, const SkPaint& paint) {
356     const SkBitmap& src = device->accessBitmap(false);
357     draw.drawSprite(src, x, y, paint);
358 }
359 
newSurface(const SkImageInfo & info,const SkSurfaceProps & props)360 SkSurface* SkBitmapDevice::newSurface(const SkImageInfo& info, const SkSurfaceProps& props) {
361     return SkSurface::NewRaster(info, &props);
362 }
363 
peekPixels(SkImageInfo * info,size_t * rowBytes)364 const void* SkBitmapDevice::peekPixels(SkImageInfo* info, size_t* rowBytes) {
365     const SkImageInfo bmInfo = fBitmap.info();
366     if (fBitmap.getPixels() && (kUnknown_SkColorType != bmInfo.colorType())) {
367         if (info) {
368             *info = bmInfo;
369         }
370         if (rowBytes) {
371             *rowBytes = fBitmap.rowBytes();
372         }
373         return fBitmap.getPixels();
374     }
375     return NULL;
376 }
377 
getImageFilterCache()378 SkImageFilter::Cache* SkBitmapDevice::getImageFilterCache() {
379     SkImageFilter::Cache* cache = SkImageFilter::Cache::Get();
380     cache->ref();
381     return cache;
382 }
383 
384 ///////////////////////////////////////////////////////////////////////////////
385 
filterTextFlags(const SkPaint & paint,TextFlags * flags)386 bool SkBitmapDevice::filterTextFlags(const SkPaint& paint, TextFlags* flags) {
387     if (!paint.isLCDRenderText() || !paint.isAntiAlias()) {
388         // we're cool with the paint as is
389         return false;
390     }
391 
392     if (kN32_SkColorType != fBitmap.colorType() ||
393         paint.getRasterizer() ||
394         paint.getPathEffect() ||
395         paint.isFakeBoldText() ||
396         paint.getStyle() != SkPaint::kFill_Style ||
397         !SkXfermode::IsMode(paint.getXfermode(), SkXfermode::kSrcOver_Mode)) {
398         // turn off lcd, but turn on kGenA8
399         flags->fFlags = paint.getFlags() & ~SkPaint::kLCDRenderText_Flag;
400         flags->fFlags |= SkPaint::kGenA8FromLCD_Flag;
401         return true;
402     }
403     // we're cool with the paint as is
404     return false;
405 }
406