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