gfx/skia/trunk/src/core/SkBitmapDevice.cpp

Sat, 03 Jan 2015 20:18:00 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Sat, 03 Jan 2015 20:18:00 +0100
branch
TOR_BUG_3246
changeset 7
129ffea94266
permissions
-rw-r--r--

Conditionally enable double key logic according to:
private browsing mode or privacy.thirdparty.isolate preference and
implement in GetCookieStringCommon and FindCookie where it counts...
With some reservations of how to convince FindCookie users to test
condition and pass a nullptr when disabling double key logic.

michael@0 1 /*
michael@0 2 * Copyright 2013 Google Inc.
michael@0 3 *
michael@0 4 * Use of this source code is governed by a BSD-style license that can be
michael@0 5 * found in the LICENSE file.
michael@0 6 */
michael@0 7
michael@0 8 #include "SkBitmapDevice.h"
michael@0 9 #include "SkConfig8888.h"
michael@0 10 #include "SkDraw.h"
michael@0 11 #include "SkRasterClip.h"
michael@0 12 #include "SkShader.h"
michael@0 13 #include "SkSurface.h"
michael@0 14
michael@0 15 #define CHECK_FOR_ANNOTATION(paint) \
michael@0 16 do { if (paint.getAnnotation()) { return; } } while (0)
michael@0 17
michael@0 18 static bool valid_for_bitmap_device(const SkImageInfo& info,
michael@0 19 SkAlphaType* newAlphaType) {
michael@0 20 if (info.width() < 0 || info.height() < 0) {
michael@0 21 return false;
michael@0 22 }
michael@0 23
michael@0 24 // TODO: can we stop supporting kUnknown in SkBitmkapDevice?
michael@0 25 if (kUnknown_SkColorType == info.colorType()) {
michael@0 26 if (newAlphaType) {
michael@0 27 *newAlphaType = kIgnore_SkAlphaType;
michael@0 28 }
michael@0 29 return true;
michael@0 30 }
michael@0 31
michael@0 32 switch (info.alphaType()) {
michael@0 33 case kPremul_SkAlphaType:
michael@0 34 case kOpaque_SkAlphaType:
michael@0 35 break;
michael@0 36 default:
michael@0 37 return false;
michael@0 38 }
michael@0 39
michael@0 40 SkAlphaType canonicalAlphaType = info.alphaType();
michael@0 41
michael@0 42 switch (info.colorType()) {
michael@0 43 case kAlpha_8_SkColorType:
michael@0 44 break;
michael@0 45 case kRGB_565_SkColorType:
michael@0 46 canonicalAlphaType = kOpaque_SkAlphaType;
michael@0 47 break;
michael@0 48 case kPMColor_SkColorType:
michael@0 49 break;
michael@0 50 default:
michael@0 51 return false;
michael@0 52 }
michael@0 53
michael@0 54 if (newAlphaType) {
michael@0 55 *newAlphaType = canonicalAlphaType;
michael@0 56 }
michael@0 57 return true;
michael@0 58 }
michael@0 59
michael@0 60 SkBitmapDevice::SkBitmapDevice(const SkBitmap& bitmap) : fBitmap(bitmap) {
michael@0 61 SkASSERT(valid_for_bitmap_device(bitmap.info(), NULL));
michael@0 62 }
michael@0 63
michael@0 64 SkBitmapDevice::SkBitmapDevice(const SkBitmap& bitmap, const SkDeviceProperties& deviceProperties)
michael@0 65 : SkBaseDevice(deviceProperties)
michael@0 66 , fBitmap(bitmap)
michael@0 67 {
michael@0 68 SkASSERT(valid_for_bitmap_device(bitmap.info(), NULL));
michael@0 69 }
michael@0 70
michael@0 71 #ifdef SK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG
michael@0 72 void SkBitmapDevice::init(SkBitmap::Config config, int width, int height, bool isOpaque) {
michael@0 73 fBitmap.setConfig(config, width, height, 0, isOpaque ?
michael@0 74 kOpaque_SkAlphaType : kPremul_SkAlphaType);
michael@0 75
michael@0 76 if (SkBitmap::kNo_Config != config) {
michael@0 77 if (!fBitmap.allocPixels()) {
michael@0 78 // indicate failure by zeroing our bitmap
michael@0 79 fBitmap.setConfig(config, 0, 0, 0, isOpaque ?
michael@0 80 kOpaque_SkAlphaType : kPremul_SkAlphaType);
michael@0 81 } else if (!isOpaque) {
michael@0 82 fBitmap.eraseColor(SK_ColorTRANSPARENT);
michael@0 83 }
michael@0 84 }
michael@0 85 }
michael@0 86
michael@0 87 SkBitmapDevice::SkBitmapDevice(SkBitmap::Config config, int width, int height, bool isOpaque) {
michael@0 88 this->init(config, width, height, isOpaque);
michael@0 89 }
michael@0 90
michael@0 91 SkBitmapDevice::SkBitmapDevice(SkBitmap::Config config, int width, int height, bool isOpaque,
michael@0 92 const SkDeviceProperties& deviceProperties)
michael@0 93 : SkBaseDevice(deviceProperties)
michael@0 94 {
michael@0 95 this->init(config, width, height, isOpaque);
michael@0 96 }
michael@0 97 #endif
michael@0 98 SkBitmapDevice* SkBitmapDevice::Create(const SkImageInfo& origInfo,
michael@0 99 const SkDeviceProperties* props) {
michael@0 100 SkImageInfo info = origInfo;
michael@0 101 if (!valid_for_bitmap_device(info, &info.fAlphaType)) {
michael@0 102 return NULL;
michael@0 103 }
michael@0 104
michael@0 105 SkBitmap bitmap;
michael@0 106
michael@0 107 if (kUnknown_SkColorType == info.colorType()) {
michael@0 108 if (!bitmap.setConfig(info)) {
michael@0 109 return NULL;
michael@0 110 }
michael@0 111 } else {
michael@0 112 if (!bitmap.allocPixels(info)) {
michael@0 113 return NULL;
michael@0 114 }
michael@0 115 if (!bitmap.info().isOpaque()) {
michael@0 116 bitmap.eraseColor(SK_ColorTRANSPARENT);
michael@0 117 }
michael@0 118 }
michael@0 119
michael@0 120 if (props) {
michael@0 121 return SkNEW_ARGS(SkBitmapDevice, (bitmap, *props));
michael@0 122 } else {
michael@0 123 return SkNEW_ARGS(SkBitmapDevice, (bitmap));
michael@0 124 }
michael@0 125 }
michael@0 126
michael@0 127 SkImageInfo SkBitmapDevice::imageInfo() const {
michael@0 128 return fBitmap.info();
michael@0 129 }
michael@0 130
michael@0 131 void SkBitmapDevice::replaceBitmapBackendForRasterSurface(const SkBitmap& bm) {
michael@0 132 SkASSERT(bm.width() == fBitmap.width());
michael@0 133 SkASSERT(bm.height() == fBitmap.height());
michael@0 134 fBitmap = bm; // intent is to use bm's pixelRef (and rowbytes/config)
michael@0 135 fBitmap.lockPixels();
michael@0 136 }
michael@0 137
michael@0 138 SkBaseDevice* SkBitmapDevice::onCreateDevice(const SkImageInfo& info, Usage usage) {
michael@0 139 return SkBitmapDevice::Create(info, &this->getDeviceProperties());
michael@0 140 }
michael@0 141
michael@0 142 void SkBitmapDevice::lockPixels() {
michael@0 143 if (fBitmap.lockPixelsAreWritable()) {
michael@0 144 fBitmap.lockPixels();
michael@0 145 }
michael@0 146 }
michael@0 147
michael@0 148 void SkBitmapDevice::unlockPixels() {
michael@0 149 if (fBitmap.lockPixelsAreWritable()) {
michael@0 150 fBitmap.unlockPixels();
michael@0 151 }
michael@0 152 }
michael@0 153
michael@0 154 void SkBitmapDevice::clear(SkColor color) {
michael@0 155 fBitmap.eraseColor(color);
michael@0 156 }
michael@0 157
michael@0 158 const SkBitmap& SkBitmapDevice::onAccessBitmap() {
michael@0 159 return fBitmap;
michael@0 160 }
michael@0 161
michael@0 162 bool SkBitmapDevice::canHandleImageFilter(const SkImageFilter*) {
michael@0 163 return false;
michael@0 164 }
michael@0 165
michael@0 166 bool SkBitmapDevice::filterImage(const SkImageFilter* filter, const SkBitmap& src,
michael@0 167 const SkImageFilter::Context& ctx, SkBitmap* result,
michael@0 168 SkIPoint* offset) {
michael@0 169 return false;
michael@0 170 }
michael@0 171
michael@0 172 bool SkBitmapDevice::allowImageFilter(const SkImageFilter*) {
michael@0 173 return true;
michael@0 174 }
michael@0 175
michael@0 176 bool SkBitmapDevice::onReadPixels(const SkBitmap& bitmap,
michael@0 177 int x, int y,
michael@0 178 SkCanvas::Config8888 config8888) {
michael@0 179 SkASSERT(SkBitmap::kARGB_8888_Config == bitmap.config());
michael@0 180 SkASSERT(!bitmap.isNull());
michael@0 181 SkASSERT(SkIRect::MakeWH(this->width(), this->height()).contains(SkIRect::MakeXYWH(x, y,
michael@0 182 bitmap.width(),
michael@0 183 bitmap.height())));
michael@0 184
michael@0 185 SkIRect srcRect = SkIRect::MakeXYWH(x, y, bitmap.width(), bitmap.height());
michael@0 186 const SkBitmap& src = this->accessBitmap(false);
michael@0 187
michael@0 188 SkBitmap subset;
michael@0 189 if (!src.extractSubset(&subset, srcRect)) {
michael@0 190 return false;
michael@0 191 }
michael@0 192 if (kPMColor_SkColorType != subset.colorType()) {
michael@0 193 // It'd be preferable to do this directly to bitmap.
michael@0 194 subset.copyTo(&subset, kPMColor_SkColorType);
michael@0 195 }
michael@0 196 SkAutoLockPixels alp(bitmap);
michael@0 197 uint32_t* bmpPixels = reinterpret_cast<uint32_t*>(bitmap.getPixels());
michael@0 198 SkCopyBitmapToConfig8888(bmpPixels, bitmap.rowBytes(), config8888, subset);
michael@0 199 return true;
michael@0 200 }
michael@0 201
michael@0 202 #ifdef SK_SUPPORT_LEGACY_WRITEPIXELSCONFIG
michael@0 203 void SkBitmapDevice::writePixels(const SkBitmap& bitmap,
michael@0 204 int x, int y,
michael@0 205 SkCanvas::Config8888 config8888) {
michael@0 206 if (bitmap.isNull() || bitmap.getTexture()) {
michael@0 207 return;
michael@0 208 }
michael@0 209 const SkBitmap* sprite = &bitmap;
michael@0 210 // check whether we have to handle a config8888 that doesn't match SkPMColor
michael@0 211 if (SkBitmap::kARGB_8888_Config == bitmap.config() &&
michael@0 212 SkCanvas::kNative_Premul_Config8888 != config8888 &&
michael@0 213 kPMColorAlias != config8888) {
michael@0 214
michael@0 215 // We're going to have to convert from a config8888 to the native config
michael@0 216 // First we clip to the device bounds.
michael@0 217 SkBitmap dstBmp = this->accessBitmap(true);
michael@0 218 SkIRect spriteRect = SkIRect::MakeXYWH(x, y,
michael@0 219 bitmap.width(), bitmap.height());
michael@0 220 SkIRect devRect = SkIRect::MakeWH(dstBmp.width(), dstBmp.height());
michael@0 221 if (!spriteRect.intersect(devRect)) {
michael@0 222 return;
michael@0 223 }
michael@0 224
michael@0 225 // write directly to the device if it has pixels and is SkPMColor
michael@0 226 bool drawSprite;
michael@0 227 if (SkBitmap::kARGB_8888_Config == dstBmp.config() && !dstBmp.isNull()) {
michael@0 228 // we can write directly to the dst when doing the conversion
michael@0 229 dstBmp.extractSubset(&dstBmp, spriteRect);
michael@0 230 drawSprite = false;
michael@0 231 } else {
michael@0 232 // we convert to a temporary bitmap and draw that as a sprite
michael@0 233 if (!dstBmp.allocPixels(SkImageInfo::MakeN32Premul(spriteRect.width(),
michael@0 234 spriteRect.height()))) {
michael@0 235 return;
michael@0 236 }
michael@0 237 drawSprite = true;
michael@0 238 }
michael@0 239
michael@0 240 // copy pixels to dstBmp and convert from config8888 to native config.
michael@0 241 SkAutoLockPixels alp(bitmap);
michael@0 242 uint32_t* srcPixels = bitmap.getAddr32(spriteRect.fLeft - x,
michael@0 243 spriteRect.fTop - y);
michael@0 244 SkCopyConfig8888ToBitmap(dstBmp,
michael@0 245 srcPixels,
michael@0 246 bitmap.rowBytes(),
michael@0 247 config8888);
michael@0 248
michael@0 249 if (drawSprite) {
michael@0 250 // we've clipped the sprite when we made a copy
michael@0 251 x = spriteRect.fLeft;
michael@0 252 y = spriteRect.fTop;
michael@0 253 sprite = &dstBmp;
michael@0 254 } else {
michael@0 255 return;
michael@0 256 }
michael@0 257 }
michael@0 258
michael@0 259 SkPaint paint;
michael@0 260 paint.setXfermodeMode(SkXfermode::kSrc_Mode);
michael@0 261 SkRasterClip clip(SkIRect::MakeWH(fBitmap.width(), fBitmap.height()));
michael@0 262 SkDraw draw;
michael@0 263 draw.fRC = &clip;
michael@0 264 draw.fClip = &clip.bwRgn();
michael@0 265 draw.fBitmap = &fBitmap; // canvas should have already called accessBitmap
michael@0 266 draw.fMatrix = &SkMatrix::I();
michael@0 267 this->drawSprite(draw, *sprite, x, y, paint);
michael@0 268 }
michael@0 269 #endif
michael@0 270
michael@0 271 void* SkBitmapDevice::onAccessPixels(SkImageInfo* info, size_t* rowBytes) {
michael@0 272 if (fBitmap.getPixels()) {
michael@0 273 *info = fBitmap.info();
michael@0 274 *rowBytes = fBitmap.rowBytes();
michael@0 275 return fBitmap.getPixels();
michael@0 276 }
michael@0 277 return NULL;
michael@0 278 }
michael@0 279
michael@0 280 static void rect_memcpy(void* dst, size_t dstRB, const void* src, size_t srcRB, size_t bytesPerRow,
michael@0 281 int rowCount) {
michael@0 282 SkASSERT(bytesPerRow <= srcRB);
michael@0 283 SkASSERT(bytesPerRow <= dstRB);
michael@0 284 for (int i = 0; i < rowCount; ++i) {
michael@0 285 memcpy(dst, src, bytesPerRow);
michael@0 286 dst = (char*)dst + dstRB;
michael@0 287 src = (const char*)src + srcRB;
michael@0 288 }
michael@0 289 }
michael@0 290
michael@0 291 static bool info2config8888(const SkImageInfo& info, SkCanvas::Config8888* config) {
michael@0 292 bool pre;
michael@0 293 switch (info.alphaType()) {
michael@0 294 case kPremul_SkAlphaType:
michael@0 295 case kOpaque_SkAlphaType:
michael@0 296 pre = true;
michael@0 297 break;
michael@0 298 case kUnpremul_SkAlphaType:
michael@0 299 pre = false;
michael@0 300 break;
michael@0 301 default:
michael@0 302 return false;
michael@0 303 }
michael@0 304 switch (info.colorType()) {
michael@0 305 case kRGBA_8888_SkColorType:
michael@0 306 *config = pre ? SkCanvas::kRGBA_Premul_Config8888 : SkCanvas::kRGBA_Unpremul_Config8888;
michael@0 307 return true;
michael@0 308 case kBGRA_8888_SkColorType:
michael@0 309 *config = pre ? SkCanvas::kBGRA_Premul_Config8888 : SkCanvas::kBGRA_Unpremul_Config8888;
michael@0 310 return true;
michael@0 311 default:
michael@0 312 return false;
michael@0 313 }
michael@0 314 }
michael@0 315
michael@0 316 // TODO: make this guy real, and not rely on legacy config8888 utility
michael@0 317 #include "SkConfig8888.h"
michael@0 318 static bool write_pixels(const SkImageInfo& dstInfo, void* dstPixels, size_t dstRowBytes,
michael@0 319 const SkImageInfo& srcInfo, const void* srcPixels, size_t srcRowBytes) {
michael@0 320 if (srcInfo.dimensions() != dstInfo.dimensions()) {
michael@0 321 return false;
michael@0 322 }
michael@0 323 if (4 == srcInfo.bytesPerPixel() && 4 == dstInfo.bytesPerPixel()) {
michael@0 324 SkCanvas::Config8888 srcConfig, dstConfig;
michael@0 325 if (!info2config8888(srcInfo, &srcConfig) || !info2config8888(dstInfo, &dstConfig)) {
michael@0 326 return false;
michael@0 327 }
michael@0 328 SkConvertConfig8888Pixels((uint32_t*)dstPixels, dstRowBytes, dstConfig,
michael@0 329 (const uint32_t*)srcPixels, srcRowBytes, srcConfig,
michael@0 330 srcInfo.width(), srcInfo.height());
michael@0 331 return true;
michael@0 332 }
michael@0 333 if (srcInfo.colorType() == dstInfo.colorType()) {
michael@0 334 switch (srcInfo.colorType()) {
michael@0 335 case kRGB_565_SkColorType:
michael@0 336 case kAlpha_8_SkColorType:
michael@0 337 break;
michael@0 338 case kARGB_4444_SkColorType:
michael@0 339 if (srcInfo.alphaType() != dstInfo.alphaType()) {
michael@0 340 return false;
michael@0 341 }
michael@0 342 break;
michael@0 343 default:
michael@0 344 return false;
michael@0 345 }
michael@0 346 rect_memcpy(dstPixels, dstRowBytes, srcPixels, srcRowBytes,
michael@0 347 srcInfo.width() * srcInfo.bytesPerPixel(), srcInfo.height());
michael@0 348 }
michael@0 349 // TODO: add support for more conversions as needed
michael@0 350 return false;
michael@0 351 }
michael@0 352
michael@0 353 bool SkBitmapDevice::onWritePixels(const SkImageInfo& srcInfo, const void* srcPixels,
michael@0 354 size_t srcRowBytes, int x, int y) {
michael@0 355 // since we don't stop creating un-pixeled devices yet, check for no pixels here
michael@0 356 if (NULL == fBitmap.getPixels()) {
michael@0 357 return false;
michael@0 358 }
michael@0 359
michael@0 360 SkImageInfo dstInfo = fBitmap.info();
michael@0 361 dstInfo.fWidth = srcInfo.width();
michael@0 362 dstInfo.fHeight = srcInfo.height();
michael@0 363
michael@0 364 void* dstPixels = fBitmap.getAddr(x, y);
michael@0 365 size_t dstRowBytes = fBitmap.rowBytes();
michael@0 366
michael@0 367 if (write_pixels(dstInfo, dstPixels, dstRowBytes, srcInfo, srcPixels, srcRowBytes)) {
michael@0 368 fBitmap.notifyPixelsChanged();
michael@0 369 return true;
michael@0 370 }
michael@0 371 return false;
michael@0 372 }
michael@0 373
michael@0 374 ///////////////////////////////////////////////////////////////////////////////
michael@0 375
michael@0 376 void SkBitmapDevice::drawPaint(const SkDraw& draw, const SkPaint& paint) {
michael@0 377 draw.drawPaint(paint);
michael@0 378 }
michael@0 379
michael@0 380 void SkBitmapDevice::drawPoints(const SkDraw& draw, SkCanvas::PointMode mode, size_t count,
michael@0 381 const SkPoint pts[], const SkPaint& paint) {
michael@0 382 CHECK_FOR_ANNOTATION(paint);
michael@0 383 draw.drawPoints(mode, count, pts, paint);
michael@0 384 }
michael@0 385
michael@0 386 void SkBitmapDevice::drawRect(const SkDraw& draw, const SkRect& r, const SkPaint& paint) {
michael@0 387 CHECK_FOR_ANNOTATION(paint);
michael@0 388 draw.drawRect(r, paint);
michael@0 389 }
michael@0 390
michael@0 391 void SkBitmapDevice::drawOval(const SkDraw& draw, const SkRect& oval, const SkPaint& paint) {
michael@0 392 CHECK_FOR_ANNOTATION(paint);
michael@0 393
michael@0 394 SkPath path;
michael@0 395 path.addOval(oval);
michael@0 396 // call the VIRTUAL version, so any subclasses who do handle drawPath aren't
michael@0 397 // required to override drawOval.
michael@0 398 this->drawPath(draw, path, paint, NULL, true);
michael@0 399 }
michael@0 400
michael@0 401 void SkBitmapDevice::drawRRect(const SkDraw& draw, const SkRRect& rrect, const SkPaint& paint) {
michael@0 402 CHECK_FOR_ANNOTATION(paint);
michael@0 403
michael@0 404 #ifdef SK_IGNORE_BLURRED_RRECT_OPT
michael@0 405 SkPath path;
michael@0 406
michael@0 407 path.addRRect(rrect);
michael@0 408 // call the VIRTUAL version, so any subclasses who do handle drawPath aren't
michael@0 409 // required to override drawRRect.
michael@0 410 this->drawPath(draw, path, paint, NULL, true);
michael@0 411 #else
michael@0 412 draw.drawRRect(rrect, paint);
michael@0 413 #endif
michael@0 414 }
michael@0 415
michael@0 416 void SkBitmapDevice::drawPath(const SkDraw& draw, const SkPath& path,
michael@0 417 const SkPaint& paint, const SkMatrix* prePathMatrix,
michael@0 418 bool pathIsMutable) {
michael@0 419 CHECK_FOR_ANNOTATION(paint);
michael@0 420 draw.drawPath(path, paint, prePathMatrix, pathIsMutable);
michael@0 421 }
michael@0 422
michael@0 423 void SkBitmapDevice::drawBitmap(const SkDraw& draw, const SkBitmap& bitmap,
michael@0 424 const SkMatrix& matrix, const SkPaint& paint) {
michael@0 425 draw.drawBitmap(bitmap, matrix, paint);
michael@0 426 }
michael@0 427
michael@0 428 void SkBitmapDevice::drawBitmapRect(const SkDraw& draw, const SkBitmap& bitmap,
michael@0 429 const SkRect* src, const SkRect& dst,
michael@0 430 const SkPaint& paint,
michael@0 431 SkCanvas::DrawBitmapRectFlags flags) {
michael@0 432 SkMatrix matrix;
michael@0 433 SkRect bitmapBounds, tmpSrc, tmpDst;
michael@0 434 SkBitmap tmpBitmap;
michael@0 435
michael@0 436 bitmapBounds.isetWH(bitmap.width(), bitmap.height());
michael@0 437
michael@0 438 // Compute matrix from the two rectangles
michael@0 439 if (src) {
michael@0 440 tmpSrc = *src;
michael@0 441 } else {
michael@0 442 tmpSrc = bitmapBounds;
michael@0 443 }
michael@0 444 matrix.setRectToRect(tmpSrc, dst, SkMatrix::kFill_ScaleToFit);
michael@0 445
michael@0 446 const SkRect* dstPtr = &dst;
michael@0 447 const SkBitmap* bitmapPtr = &bitmap;
michael@0 448
michael@0 449 // clip the tmpSrc to the bounds of the bitmap, and recompute dstRect if
michael@0 450 // needed (if the src was clipped). No check needed if src==null.
michael@0 451 if (src) {
michael@0 452 if (!bitmapBounds.contains(*src)) {
michael@0 453 if (!tmpSrc.intersect(bitmapBounds)) {
michael@0 454 return; // nothing to draw
michael@0 455 }
michael@0 456 // recompute dst, based on the smaller tmpSrc
michael@0 457 matrix.mapRect(&tmpDst, tmpSrc);
michael@0 458 dstPtr = &tmpDst;
michael@0 459 }
michael@0 460
michael@0 461 // since we may need to clamp to the borders of the src rect within
michael@0 462 // the bitmap, we extract a subset.
michael@0 463 SkIRect srcIR;
michael@0 464 tmpSrc.roundOut(&srcIR);
michael@0 465 if (!bitmap.extractSubset(&tmpBitmap, srcIR)) {
michael@0 466 return;
michael@0 467 }
michael@0 468 bitmapPtr = &tmpBitmap;
michael@0 469
michael@0 470 // Since we did an extract, we need to adjust the matrix accordingly
michael@0 471 SkScalar dx = 0, dy = 0;
michael@0 472 if (srcIR.fLeft > 0) {
michael@0 473 dx = SkIntToScalar(srcIR.fLeft);
michael@0 474 }
michael@0 475 if (srcIR.fTop > 0) {
michael@0 476 dy = SkIntToScalar(srcIR.fTop);
michael@0 477 }
michael@0 478 if (dx || dy) {
michael@0 479 matrix.preTranslate(dx, dy);
michael@0 480 }
michael@0 481
michael@0 482 SkRect extractedBitmapBounds;
michael@0 483 extractedBitmapBounds.isetWH(bitmapPtr->width(), bitmapPtr->height());
michael@0 484 if (extractedBitmapBounds == tmpSrc) {
michael@0 485 // no fractional part in src, we can just call drawBitmap
michael@0 486 goto USE_DRAWBITMAP;
michael@0 487 }
michael@0 488 } else {
michael@0 489 USE_DRAWBITMAP:
michael@0 490 // We can go faster by just calling drawBitmap, which will concat the
michael@0 491 // matrix with the CTM, and try to call drawSprite if it can. If not,
michael@0 492 // it will make a shader and call drawRect, as we do below.
michael@0 493 this->drawBitmap(draw, *bitmapPtr, matrix, paint);
michael@0 494 return;
michael@0 495 }
michael@0 496
michael@0 497 // construct a shader, so we can call drawRect with the dst
michael@0 498 SkShader* s = SkShader::CreateBitmapShader(*bitmapPtr,
michael@0 499 SkShader::kClamp_TileMode,
michael@0 500 SkShader::kClamp_TileMode);
michael@0 501 if (NULL == s) {
michael@0 502 return;
michael@0 503 }
michael@0 504 s->setLocalMatrix(matrix);
michael@0 505
michael@0 506 SkPaint paintWithShader(paint);
michael@0 507 paintWithShader.setStyle(SkPaint::kFill_Style);
michael@0 508 paintWithShader.setShader(s)->unref();
michael@0 509
michael@0 510 // Call ourself, in case the subclass wanted to share this setup code
michael@0 511 // but handle the drawRect code themselves.
michael@0 512 this->drawRect(draw, *dstPtr, paintWithShader);
michael@0 513 }
michael@0 514
michael@0 515 void SkBitmapDevice::drawSprite(const SkDraw& draw, const SkBitmap& bitmap,
michael@0 516 int x, int y, const SkPaint& paint) {
michael@0 517 draw.drawSprite(bitmap, x, y, paint);
michael@0 518 }
michael@0 519
michael@0 520 void SkBitmapDevice::drawText(const SkDraw& draw, const void* text, size_t len,
michael@0 521 SkScalar x, SkScalar y, const SkPaint& paint) {
michael@0 522 draw.drawText((const char*)text, len, x, y, paint);
michael@0 523 }
michael@0 524
michael@0 525 void SkBitmapDevice::drawPosText(const SkDraw& draw, const void* text, size_t len,
michael@0 526 const SkScalar xpos[], SkScalar y,
michael@0 527 int scalarsPerPos, const SkPaint& paint) {
michael@0 528 draw.drawPosText((const char*)text, len, xpos, y, scalarsPerPos, paint);
michael@0 529 }
michael@0 530
michael@0 531 void SkBitmapDevice::drawTextOnPath(const SkDraw& draw, const void* text,
michael@0 532 size_t len, const SkPath& path,
michael@0 533 const SkMatrix* matrix,
michael@0 534 const SkPaint& paint) {
michael@0 535 draw.drawTextOnPath((const char*)text, len, path, matrix, paint);
michael@0 536 }
michael@0 537
michael@0 538 void SkBitmapDevice::drawVertices(const SkDraw& draw, SkCanvas::VertexMode vmode,
michael@0 539 int vertexCount,
michael@0 540 const SkPoint verts[], const SkPoint textures[],
michael@0 541 const SkColor colors[], SkXfermode* xmode,
michael@0 542 const uint16_t indices[], int indexCount,
michael@0 543 const SkPaint& paint) {
michael@0 544 draw.drawVertices(vmode, vertexCount, verts, textures, colors, xmode,
michael@0 545 indices, indexCount, paint);
michael@0 546 }
michael@0 547
michael@0 548 void SkBitmapDevice::drawDevice(const SkDraw& draw, SkBaseDevice* device,
michael@0 549 int x, int y, const SkPaint& paint) {
michael@0 550 const SkBitmap& src = device->accessBitmap(false);
michael@0 551 draw.drawSprite(src, x, y, paint);
michael@0 552 }
michael@0 553
michael@0 554 SkSurface* SkBitmapDevice::newSurface(const SkImageInfo& info) {
michael@0 555 return SkSurface::NewRaster(info);
michael@0 556 }
michael@0 557
michael@0 558 const void* SkBitmapDevice::peekPixels(SkImageInfo* info, size_t* rowBytes) {
michael@0 559 if (fBitmap.getPixels() && fBitmap.asImageInfo(info)) {
michael@0 560 if (rowBytes) {
michael@0 561 *rowBytes = fBitmap.rowBytes();
michael@0 562 }
michael@0 563 return fBitmap.getPixels();
michael@0 564 }
michael@0 565 return NULL;
michael@0 566 }
michael@0 567
michael@0 568 ///////////////////////////////////////////////////////////////////////////////
michael@0 569
michael@0 570 bool SkBitmapDevice::filterTextFlags(const SkPaint& paint, TextFlags* flags) {
michael@0 571 if (!paint.isLCDRenderText() || !paint.isAntiAlias()) {
michael@0 572 // we're cool with the paint as is
michael@0 573 return false;
michael@0 574 }
michael@0 575
michael@0 576 if (SkBitmap::kARGB_8888_Config != fBitmap.config() ||
michael@0 577 paint.getRasterizer() ||
michael@0 578 paint.getPathEffect() ||
michael@0 579 paint.isFakeBoldText() ||
michael@0 580 paint.getStyle() != SkPaint::kFill_Style ||
michael@0 581 !SkXfermode::IsMode(paint.getXfermode(), SkXfermode::kSrcOver_Mode)) {
michael@0 582 // turn off lcd
michael@0 583 flags->fFlags = paint.getFlags() & ~SkPaint::kLCDRenderText_Flag;
michael@0 584 flags->fHinting = paint.getHinting();
michael@0 585 return true;
michael@0 586 }
michael@0 587 // we're cool with the paint as is
michael@0 588 return false;
michael@0 589 }

mercurial