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