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