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

changeset 0
6474c204b198
     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 +}

mercurial