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