1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/gfx/skia/trunk/src/core/SkBitmapDevice.cpp Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,589 @@ 1.4 +/* 1.5 + * Copyright 2013 Google Inc. 1.6 + * 1.7 + * Use of this source code is governed by a BSD-style license that can be 1.8 + * found in the LICENSE file. 1.9 + */ 1.10 + 1.11 +#include "SkBitmapDevice.h" 1.12 +#include "SkConfig8888.h" 1.13 +#include "SkDraw.h" 1.14 +#include "SkRasterClip.h" 1.15 +#include "SkShader.h" 1.16 +#include "SkSurface.h" 1.17 + 1.18 +#define CHECK_FOR_ANNOTATION(paint) \ 1.19 + do { if (paint.getAnnotation()) { return; } } while (0) 1.20 + 1.21 +static bool valid_for_bitmap_device(const SkImageInfo& info, 1.22 + SkAlphaType* newAlphaType) { 1.23 + if (info.width() < 0 || info.height() < 0) { 1.24 + return false; 1.25 + } 1.26 + 1.27 + // TODO: can we stop supporting kUnknown in SkBitmkapDevice? 1.28 + if (kUnknown_SkColorType == info.colorType()) { 1.29 + if (newAlphaType) { 1.30 + *newAlphaType = kIgnore_SkAlphaType; 1.31 + } 1.32 + return true; 1.33 + } 1.34 + 1.35 + switch (info.alphaType()) { 1.36 + case kPremul_SkAlphaType: 1.37 + case kOpaque_SkAlphaType: 1.38 + break; 1.39 + default: 1.40 + return false; 1.41 + } 1.42 + 1.43 + SkAlphaType canonicalAlphaType = info.alphaType(); 1.44 + 1.45 + switch (info.colorType()) { 1.46 + case kAlpha_8_SkColorType: 1.47 + break; 1.48 + case kRGB_565_SkColorType: 1.49 + canonicalAlphaType = kOpaque_SkAlphaType; 1.50 + break; 1.51 + case kPMColor_SkColorType: 1.52 + break; 1.53 + default: 1.54 + return false; 1.55 + } 1.56 + 1.57 + if (newAlphaType) { 1.58 + *newAlphaType = canonicalAlphaType; 1.59 + } 1.60 + return true; 1.61 +} 1.62 + 1.63 +SkBitmapDevice::SkBitmapDevice(const SkBitmap& bitmap) : fBitmap(bitmap) { 1.64 + SkASSERT(valid_for_bitmap_device(bitmap.info(), NULL)); 1.65 +} 1.66 + 1.67 +SkBitmapDevice::SkBitmapDevice(const SkBitmap& bitmap, const SkDeviceProperties& deviceProperties) 1.68 + : SkBaseDevice(deviceProperties) 1.69 + , fBitmap(bitmap) 1.70 +{ 1.71 + SkASSERT(valid_for_bitmap_device(bitmap.info(), NULL)); 1.72 +} 1.73 + 1.74 +#ifdef SK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG 1.75 +void SkBitmapDevice::init(SkBitmap::Config config, int width, int height, bool isOpaque) { 1.76 + fBitmap.setConfig(config, width, height, 0, isOpaque ? 1.77 + kOpaque_SkAlphaType : kPremul_SkAlphaType); 1.78 + 1.79 + if (SkBitmap::kNo_Config != config) { 1.80 + if (!fBitmap.allocPixels()) { 1.81 + // indicate failure by zeroing our bitmap 1.82 + fBitmap.setConfig(config, 0, 0, 0, isOpaque ? 1.83 + kOpaque_SkAlphaType : kPremul_SkAlphaType); 1.84 + } else if (!isOpaque) { 1.85 + fBitmap.eraseColor(SK_ColorTRANSPARENT); 1.86 + } 1.87 + } 1.88 +} 1.89 + 1.90 +SkBitmapDevice::SkBitmapDevice(SkBitmap::Config config, int width, int height, bool isOpaque) { 1.91 + this->init(config, width, height, isOpaque); 1.92 +} 1.93 + 1.94 +SkBitmapDevice::SkBitmapDevice(SkBitmap::Config config, int width, int height, bool isOpaque, 1.95 + const SkDeviceProperties& deviceProperties) 1.96 + : SkBaseDevice(deviceProperties) 1.97 +{ 1.98 + this->init(config, width, height, isOpaque); 1.99 +} 1.100 +#endif 1.101 +SkBitmapDevice* SkBitmapDevice::Create(const SkImageInfo& origInfo, 1.102 + const SkDeviceProperties* props) { 1.103 + SkImageInfo info = origInfo; 1.104 + if (!valid_for_bitmap_device(info, &info.fAlphaType)) { 1.105 + return NULL; 1.106 + } 1.107 + 1.108 + SkBitmap bitmap; 1.109 + 1.110 + if (kUnknown_SkColorType == info.colorType()) { 1.111 + if (!bitmap.setConfig(info)) { 1.112 + return NULL; 1.113 + } 1.114 + } else { 1.115 + if (!bitmap.allocPixels(info)) { 1.116 + return NULL; 1.117 + } 1.118 + if (!bitmap.info().isOpaque()) { 1.119 + bitmap.eraseColor(SK_ColorTRANSPARENT); 1.120 + } 1.121 + } 1.122 + 1.123 + if (props) { 1.124 + return SkNEW_ARGS(SkBitmapDevice, (bitmap, *props)); 1.125 + } else { 1.126 + return SkNEW_ARGS(SkBitmapDevice, (bitmap)); 1.127 + } 1.128 +} 1.129 + 1.130 +SkImageInfo SkBitmapDevice::imageInfo() const { 1.131 + return fBitmap.info(); 1.132 +} 1.133 + 1.134 +void SkBitmapDevice::replaceBitmapBackendForRasterSurface(const SkBitmap& bm) { 1.135 + SkASSERT(bm.width() == fBitmap.width()); 1.136 + SkASSERT(bm.height() == fBitmap.height()); 1.137 + fBitmap = bm; // intent is to use bm's pixelRef (and rowbytes/config) 1.138 + fBitmap.lockPixels(); 1.139 +} 1.140 + 1.141 +SkBaseDevice* SkBitmapDevice::onCreateDevice(const SkImageInfo& info, Usage usage) { 1.142 + return SkBitmapDevice::Create(info, &this->getDeviceProperties()); 1.143 +} 1.144 + 1.145 +void SkBitmapDevice::lockPixels() { 1.146 + if (fBitmap.lockPixelsAreWritable()) { 1.147 + fBitmap.lockPixels(); 1.148 + } 1.149 +} 1.150 + 1.151 +void SkBitmapDevice::unlockPixels() { 1.152 + if (fBitmap.lockPixelsAreWritable()) { 1.153 + fBitmap.unlockPixels(); 1.154 + } 1.155 +} 1.156 + 1.157 +void SkBitmapDevice::clear(SkColor color) { 1.158 + fBitmap.eraseColor(color); 1.159 +} 1.160 + 1.161 +const SkBitmap& SkBitmapDevice::onAccessBitmap() { 1.162 + return fBitmap; 1.163 +} 1.164 + 1.165 +bool SkBitmapDevice::canHandleImageFilter(const SkImageFilter*) { 1.166 + return false; 1.167 +} 1.168 + 1.169 +bool SkBitmapDevice::filterImage(const SkImageFilter* filter, const SkBitmap& src, 1.170 + const SkImageFilter::Context& ctx, SkBitmap* result, 1.171 + SkIPoint* offset) { 1.172 + return false; 1.173 +} 1.174 + 1.175 +bool SkBitmapDevice::allowImageFilter(const SkImageFilter*) { 1.176 + return true; 1.177 +} 1.178 + 1.179 +bool SkBitmapDevice::onReadPixels(const SkBitmap& bitmap, 1.180 + int x, int y, 1.181 + SkCanvas::Config8888 config8888) { 1.182 + SkASSERT(SkBitmap::kARGB_8888_Config == bitmap.config()); 1.183 + SkASSERT(!bitmap.isNull()); 1.184 + SkASSERT(SkIRect::MakeWH(this->width(), this->height()).contains(SkIRect::MakeXYWH(x, y, 1.185 + bitmap.width(), 1.186 + bitmap.height()))); 1.187 + 1.188 + SkIRect srcRect = SkIRect::MakeXYWH(x, y, bitmap.width(), bitmap.height()); 1.189 + const SkBitmap& src = this->accessBitmap(false); 1.190 + 1.191 + SkBitmap subset; 1.192 + if (!src.extractSubset(&subset, srcRect)) { 1.193 + return false; 1.194 + } 1.195 + if (kPMColor_SkColorType != subset.colorType()) { 1.196 + // It'd be preferable to do this directly to bitmap. 1.197 + subset.copyTo(&subset, kPMColor_SkColorType); 1.198 + } 1.199 + SkAutoLockPixels alp(bitmap); 1.200 + uint32_t* bmpPixels = reinterpret_cast<uint32_t*>(bitmap.getPixels()); 1.201 + SkCopyBitmapToConfig8888(bmpPixels, bitmap.rowBytes(), config8888, subset); 1.202 + return true; 1.203 +} 1.204 + 1.205 +#ifdef SK_SUPPORT_LEGACY_WRITEPIXELSCONFIG 1.206 +void SkBitmapDevice::writePixels(const SkBitmap& bitmap, 1.207 + int x, int y, 1.208 + SkCanvas::Config8888 config8888) { 1.209 + if (bitmap.isNull() || bitmap.getTexture()) { 1.210 + return; 1.211 + } 1.212 + const SkBitmap* sprite = &bitmap; 1.213 + // check whether we have to handle a config8888 that doesn't match SkPMColor 1.214 + if (SkBitmap::kARGB_8888_Config == bitmap.config() && 1.215 + SkCanvas::kNative_Premul_Config8888 != config8888 && 1.216 + kPMColorAlias != config8888) { 1.217 + 1.218 + // We're going to have to convert from a config8888 to the native config 1.219 + // First we clip to the device bounds. 1.220 + SkBitmap dstBmp = this->accessBitmap(true); 1.221 + SkIRect spriteRect = SkIRect::MakeXYWH(x, y, 1.222 + bitmap.width(), bitmap.height()); 1.223 + SkIRect devRect = SkIRect::MakeWH(dstBmp.width(), dstBmp.height()); 1.224 + if (!spriteRect.intersect(devRect)) { 1.225 + return; 1.226 + } 1.227 + 1.228 + // write directly to the device if it has pixels and is SkPMColor 1.229 + bool drawSprite; 1.230 + if (SkBitmap::kARGB_8888_Config == dstBmp.config() && !dstBmp.isNull()) { 1.231 + // we can write directly to the dst when doing the conversion 1.232 + dstBmp.extractSubset(&dstBmp, spriteRect); 1.233 + drawSprite = false; 1.234 + } else { 1.235 + // we convert to a temporary bitmap and draw that as a sprite 1.236 + if (!dstBmp.allocPixels(SkImageInfo::MakeN32Premul(spriteRect.width(), 1.237 + spriteRect.height()))) { 1.238 + return; 1.239 + } 1.240 + drawSprite = true; 1.241 + } 1.242 + 1.243 + // copy pixels to dstBmp and convert from config8888 to native config. 1.244 + SkAutoLockPixels alp(bitmap); 1.245 + uint32_t* srcPixels = bitmap.getAddr32(spriteRect.fLeft - x, 1.246 + spriteRect.fTop - y); 1.247 + SkCopyConfig8888ToBitmap(dstBmp, 1.248 + srcPixels, 1.249 + bitmap.rowBytes(), 1.250 + config8888); 1.251 + 1.252 + if (drawSprite) { 1.253 + // we've clipped the sprite when we made a copy 1.254 + x = spriteRect.fLeft; 1.255 + y = spriteRect.fTop; 1.256 + sprite = &dstBmp; 1.257 + } else { 1.258 + return; 1.259 + } 1.260 + } 1.261 + 1.262 + SkPaint paint; 1.263 + paint.setXfermodeMode(SkXfermode::kSrc_Mode); 1.264 + SkRasterClip clip(SkIRect::MakeWH(fBitmap.width(), fBitmap.height())); 1.265 + SkDraw draw; 1.266 + draw.fRC = &clip; 1.267 + draw.fClip = &clip.bwRgn(); 1.268 + draw.fBitmap = &fBitmap; // canvas should have already called accessBitmap 1.269 + draw.fMatrix = &SkMatrix::I(); 1.270 + this->drawSprite(draw, *sprite, x, y, paint); 1.271 +} 1.272 +#endif 1.273 + 1.274 +void* SkBitmapDevice::onAccessPixels(SkImageInfo* info, size_t* rowBytes) { 1.275 + if (fBitmap.getPixels()) { 1.276 + *info = fBitmap.info(); 1.277 + *rowBytes = fBitmap.rowBytes(); 1.278 + return fBitmap.getPixels(); 1.279 + } 1.280 + return NULL; 1.281 +} 1.282 + 1.283 +static void rect_memcpy(void* dst, size_t dstRB, const void* src, size_t srcRB, size_t bytesPerRow, 1.284 + int rowCount) { 1.285 + SkASSERT(bytesPerRow <= srcRB); 1.286 + SkASSERT(bytesPerRow <= dstRB); 1.287 + for (int i = 0; i < rowCount; ++i) { 1.288 + memcpy(dst, src, bytesPerRow); 1.289 + dst = (char*)dst + dstRB; 1.290 + src = (const char*)src + srcRB; 1.291 + } 1.292 +} 1.293 + 1.294 +static bool info2config8888(const SkImageInfo& info, SkCanvas::Config8888* config) { 1.295 + bool pre; 1.296 + switch (info.alphaType()) { 1.297 + case kPremul_SkAlphaType: 1.298 + case kOpaque_SkAlphaType: 1.299 + pre = true; 1.300 + break; 1.301 + case kUnpremul_SkAlphaType: 1.302 + pre = false; 1.303 + break; 1.304 + default: 1.305 + return false; 1.306 + } 1.307 + switch (info.colorType()) { 1.308 + case kRGBA_8888_SkColorType: 1.309 + *config = pre ? SkCanvas::kRGBA_Premul_Config8888 : SkCanvas::kRGBA_Unpremul_Config8888; 1.310 + return true; 1.311 + case kBGRA_8888_SkColorType: 1.312 + *config = pre ? SkCanvas::kBGRA_Premul_Config8888 : SkCanvas::kBGRA_Unpremul_Config8888; 1.313 + return true; 1.314 + default: 1.315 + return false; 1.316 + } 1.317 +} 1.318 + 1.319 +// TODO: make this guy real, and not rely on legacy config8888 utility 1.320 +#include "SkConfig8888.h" 1.321 +static bool write_pixels(const SkImageInfo& dstInfo, void* dstPixels, size_t dstRowBytes, 1.322 + const SkImageInfo& srcInfo, const void* srcPixels, size_t srcRowBytes) { 1.323 + if (srcInfo.dimensions() != dstInfo.dimensions()) { 1.324 + return false; 1.325 + } 1.326 + if (4 == srcInfo.bytesPerPixel() && 4 == dstInfo.bytesPerPixel()) { 1.327 + SkCanvas::Config8888 srcConfig, dstConfig; 1.328 + if (!info2config8888(srcInfo, &srcConfig) || !info2config8888(dstInfo, &dstConfig)) { 1.329 + return false; 1.330 + } 1.331 + SkConvertConfig8888Pixels((uint32_t*)dstPixels, dstRowBytes, dstConfig, 1.332 + (const uint32_t*)srcPixels, srcRowBytes, srcConfig, 1.333 + srcInfo.width(), srcInfo.height()); 1.334 + return true; 1.335 + } 1.336 + if (srcInfo.colorType() == dstInfo.colorType()) { 1.337 + switch (srcInfo.colorType()) { 1.338 + case kRGB_565_SkColorType: 1.339 + case kAlpha_8_SkColorType: 1.340 + break; 1.341 + case kARGB_4444_SkColorType: 1.342 + if (srcInfo.alphaType() != dstInfo.alphaType()) { 1.343 + return false; 1.344 + } 1.345 + break; 1.346 + default: 1.347 + return false; 1.348 + } 1.349 + rect_memcpy(dstPixels, dstRowBytes, srcPixels, srcRowBytes, 1.350 + srcInfo.width() * srcInfo.bytesPerPixel(), srcInfo.height()); 1.351 + } 1.352 + // TODO: add support for more conversions as needed 1.353 + return false; 1.354 +} 1.355 + 1.356 +bool SkBitmapDevice::onWritePixels(const SkImageInfo& srcInfo, const void* srcPixels, 1.357 + size_t srcRowBytes, int x, int y) { 1.358 + // since we don't stop creating un-pixeled devices yet, check for no pixels here 1.359 + if (NULL == fBitmap.getPixels()) { 1.360 + return false; 1.361 + } 1.362 + 1.363 + SkImageInfo dstInfo = fBitmap.info(); 1.364 + dstInfo.fWidth = srcInfo.width(); 1.365 + dstInfo.fHeight = srcInfo.height(); 1.366 + 1.367 + void* dstPixels = fBitmap.getAddr(x, y); 1.368 + size_t dstRowBytes = fBitmap.rowBytes(); 1.369 + 1.370 + if (write_pixels(dstInfo, dstPixels, dstRowBytes, srcInfo, srcPixels, srcRowBytes)) { 1.371 + fBitmap.notifyPixelsChanged(); 1.372 + return true; 1.373 + } 1.374 + return false; 1.375 +} 1.376 + 1.377 +/////////////////////////////////////////////////////////////////////////////// 1.378 + 1.379 +void SkBitmapDevice::drawPaint(const SkDraw& draw, const SkPaint& paint) { 1.380 + draw.drawPaint(paint); 1.381 +} 1.382 + 1.383 +void SkBitmapDevice::drawPoints(const SkDraw& draw, SkCanvas::PointMode mode, size_t count, 1.384 + const SkPoint pts[], const SkPaint& paint) { 1.385 + CHECK_FOR_ANNOTATION(paint); 1.386 + draw.drawPoints(mode, count, pts, paint); 1.387 +} 1.388 + 1.389 +void SkBitmapDevice::drawRect(const SkDraw& draw, const SkRect& r, const SkPaint& paint) { 1.390 + CHECK_FOR_ANNOTATION(paint); 1.391 + draw.drawRect(r, paint); 1.392 +} 1.393 + 1.394 +void SkBitmapDevice::drawOval(const SkDraw& draw, const SkRect& oval, const SkPaint& paint) { 1.395 + CHECK_FOR_ANNOTATION(paint); 1.396 + 1.397 + SkPath path; 1.398 + path.addOval(oval); 1.399 + // call the VIRTUAL version, so any subclasses who do handle drawPath aren't 1.400 + // required to override drawOval. 1.401 + this->drawPath(draw, path, paint, NULL, true); 1.402 +} 1.403 + 1.404 +void SkBitmapDevice::drawRRect(const SkDraw& draw, const SkRRect& rrect, const SkPaint& paint) { 1.405 + CHECK_FOR_ANNOTATION(paint); 1.406 + 1.407 +#ifdef SK_IGNORE_BLURRED_RRECT_OPT 1.408 + SkPath path; 1.409 + 1.410 + path.addRRect(rrect); 1.411 + // call the VIRTUAL version, so any subclasses who do handle drawPath aren't 1.412 + // required to override drawRRect. 1.413 + this->drawPath(draw, path, paint, NULL, true); 1.414 +#else 1.415 + draw.drawRRect(rrect, paint); 1.416 +#endif 1.417 +} 1.418 + 1.419 +void SkBitmapDevice::drawPath(const SkDraw& draw, const SkPath& path, 1.420 + const SkPaint& paint, const SkMatrix* prePathMatrix, 1.421 + bool pathIsMutable) { 1.422 + CHECK_FOR_ANNOTATION(paint); 1.423 + draw.drawPath(path, paint, prePathMatrix, pathIsMutable); 1.424 +} 1.425 + 1.426 +void SkBitmapDevice::drawBitmap(const SkDraw& draw, const SkBitmap& bitmap, 1.427 + const SkMatrix& matrix, const SkPaint& paint) { 1.428 + draw.drawBitmap(bitmap, matrix, paint); 1.429 +} 1.430 + 1.431 +void SkBitmapDevice::drawBitmapRect(const SkDraw& draw, const SkBitmap& bitmap, 1.432 + const SkRect* src, const SkRect& dst, 1.433 + const SkPaint& paint, 1.434 + SkCanvas::DrawBitmapRectFlags flags) { 1.435 + SkMatrix matrix; 1.436 + SkRect bitmapBounds, tmpSrc, tmpDst; 1.437 + SkBitmap tmpBitmap; 1.438 + 1.439 + bitmapBounds.isetWH(bitmap.width(), bitmap.height()); 1.440 + 1.441 + // Compute matrix from the two rectangles 1.442 + if (src) { 1.443 + tmpSrc = *src; 1.444 + } else { 1.445 + tmpSrc = bitmapBounds; 1.446 + } 1.447 + matrix.setRectToRect(tmpSrc, dst, SkMatrix::kFill_ScaleToFit); 1.448 + 1.449 + const SkRect* dstPtr = &dst; 1.450 + const SkBitmap* bitmapPtr = &bitmap; 1.451 + 1.452 + // clip the tmpSrc to the bounds of the bitmap, and recompute dstRect if 1.453 + // needed (if the src was clipped). No check needed if src==null. 1.454 + if (src) { 1.455 + if (!bitmapBounds.contains(*src)) { 1.456 + if (!tmpSrc.intersect(bitmapBounds)) { 1.457 + return; // nothing to draw 1.458 + } 1.459 + // recompute dst, based on the smaller tmpSrc 1.460 + matrix.mapRect(&tmpDst, tmpSrc); 1.461 + dstPtr = &tmpDst; 1.462 + } 1.463 + 1.464 + // since we may need to clamp to the borders of the src rect within 1.465 + // the bitmap, we extract a subset. 1.466 + SkIRect srcIR; 1.467 + tmpSrc.roundOut(&srcIR); 1.468 + if (!bitmap.extractSubset(&tmpBitmap, srcIR)) { 1.469 + return; 1.470 + } 1.471 + bitmapPtr = &tmpBitmap; 1.472 + 1.473 + // Since we did an extract, we need to adjust the matrix accordingly 1.474 + SkScalar dx = 0, dy = 0; 1.475 + if (srcIR.fLeft > 0) { 1.476 + dx = SkIntToScalar(srcIR.fLeft); 1.477 + } 1.478 + if (srcIR.fTop > 0) { 1.479 + dy = SkIntToScalar(srcIR.fTop); 1.480 + } 1.481 + if (dx || dy) { 1.482 + matrix.preTranslate(dx, dy); 1.483 + } 1.484 + 1.485 + SkRect extractedBitmapBounds; 1.486 + extractedBitmapBounds.isetWH(bitmapPtr->width(), bitmapPtr->height()); 1.487 + if (extractedBitmapBounds == tmpSrc) { 1.488 + // no fractional part in src, we can just call drawBitmap 1.489 + goto USE_DRAWBITMAP; 1.490 + } 1.491 + } else { 1.492 + USE_DRAWBITMAP: 1.493 + // We can go faster by just calling drawBitmap, which will concat the 1.494 + // matrix with the CTM, and try to call drawSprite if it can. If not, 1.495 + // it will make a shader and call drawRect, as we do below. 1.496 + this->drawBitmap(draw, *bitmapPtr, matrix, paint); 1.497 + return; 1.498 + } 1.499 + 1.500 + // construct a shader, so we can call drawRect with the dst 1.501 + SkShader* s = SkShader::CreateBitmapShader(*bitmapPtr, 1.502 + SkShader::kClamp_TileMode, 1.503 + SkShader::kClamp_TileMode); 1.504 + if (NULL == s) { 1.505 + return; 1.506 + } 1.507 + s->setLocalMatrix(matrix); 1.508 + 1.509 + SkPaint paintWithShader(paint); 1.510 + paintWithShader.setStyle(SkPaint::kFill_Style); 1.511 + paintWithShader.setShader(s)->unref(); 1.512 + 1.513 + // Call ourself, in case the subclass wanted to share this setup code 1.514 + // but handle the drawRect code themselves. 1.515 + this->drawRect(draw, *dstPtr, paintWithShader); 1.516 +} 1.517 + 1.518 +void SkBitmapDevice::drawSprite(const SkDraw& draw, const SkBitmap& bitmap, 1.519 + int x, int y, const SkPaint& paint) { 1.520 + draw.drawSprite(bitmap, x, y, paint); 1.521 +} 1.522 + 1.523 +void SkBitmapDevice::drawText(const SkDraw& draw, const void* text, size_t len, 1.524 + SkScalar x, SkScalar y, const SkPaint& paint) { 1.525 + draw.drawText((const char*)text, len, x, y, paint); 1.526 +} 1.527 + 1.528 +void SkBitmapDevice::drawPosText(const SkDraw& draw, const void* text, size_t len, 1.529 + const SkScalar xpos[], SkScalar y, 1.530 + int scalarsPerPos, const SkPaint& paint) { 1.531 + draw.drawPosText((const char*)text, len, xpos, y, scalarsPerPos, paint); 1.532 +} 1.533 + 1.534 +void SkBitmapDevice::drawTextOnPath(const SkDraw& draw, const void* text, 1.535 + size_t len, const SkPath& path, 1.536 + const SkMatrix* matrix, 1.537 + const SkPaint& paint) { 1.538 + draw.drawTextOnPath((const char*)text, len, path, matrix, paint); 1.539 +} 1.540 + 1.541 +void SkBitmapDevice::drawVertices(const SkDraw& draw, SkCanvas::VertexMode vmode, 1.542 + int vertexCount, 1.543 + const SkPoint verts[], const SkPoint textures[], 1.544 + const SkColor colors[], SkXfermode* xmode, 1.545 + const uint16_t indices[], int indexCount, 1.546 + const SkPaint& paint) { 1.547 + draw.drawVertices(vmode, vertexCount, verts, textures, colors, xmode, 1.548 + indices, indexCount, paint); 1.549 +} 1.550 + 1.551 +void SkBitmapDevice::drawDevice(const SkDraw& draw, SkBaseDevice* device, 1.552 + int x, int y, const SkPaint& paint) { 1.553 + const SkBitmap& src = device->accessBitmap(false); 1.554 + draw.drawSprite(src, x, y, paint); 1.555 +} 1.556 + 1.557 +SkSurface* SkBitmapDevice::newSurface(const SkImageInfo& info) { 1.558 + return SkSurface::NewRaster(info); 1.559 +} 1.560 + 1.561 +const void* SkBitmapDevice::peekPixels(SkImageInfo* info, size_t* rowBytes) { 1.562 + if (fBitmap.getPixels() && fBitmap.asImageInfo(info)) { 1.563 + if (rowBytes) { 1.564 + *rowBytes = fBitmap.rowBytes(); 1.565 + } 1.566 + return fBitmap.getPixels(); 1.567 + } 1.568 + return NULL; 1.569 +} 1.570 + 1.571 +/////////////////////////////////////////////////////////////////////////////// 1.572 + 1.573 +bool SkBitmapDevice::filterTextFlags(const SkPaint& paint, TextFlags* flags) { 1.574 + if (!paint.isLCDRenderText() || !paint.isAntiAlias()) { 1.575 + // we're cool with the paint as is 1.576 + return false; 1.577 + } 1.578 + 1.579 + if (SkBitmap::kARGB_8888_Config != fBitmap.config() || 1.580 + paint.getRasterizer() || 1.581 + paint.getPathEffect() || 1.582 + paint.isFakeBoldText() || 1.583 + paint.getStyle() != SkPaint::kFill_Style || 1.584 + !SkXfermode::IsMode(paint.getXfermode(), SkXfermode::kSrcOver_Mode)) { 1.585 + // turn off lcd 1.586 + flags->fFlags = paint.getFlags() & ~SkPaint::kLCDRenderText_Flag; 1.587 + flags->fHinting = paint.getHinting(); 1.588 + return true; 1.589 + } 1.590 + // we're cool with the paint as is 1.591 + return false; 1.592 +}