Home | History | Annotate | Download | only in image
      1 /*
      2  * Copyright 2012 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 "SkBitmap.h"
      9 #include "SkCanvas.h"
     10 #include "SkImagePriv.h"
     11 #include "SkImage_Base.h"
     12 
     13 static SkImage_Base* as_IB(SkImage* image) {
     14     return static_cast<SkImage_Base*>(image);
     15 }
     16 
     17 static const SkImage_Base* as_IB(const SkImage* image) {
     18     return static_cast<const SkImage_Base*>(image);
     19 }
     20 
     21 uint32_t SkImage::NextUniqueID() {
     22     static int32_t gUniqueID;
     23 
     24     // never return 0;
     25     uint32_t id;
     26     do {
     27         id = sk_atomic_inc(&gUniqueID) + 1;
     28     } while (0 == id);
     29     return id;
     30 }
     31 
     32 void SkImage::draw(SkCanvas* canvas, SkScalar x, SkScalar y, const SkPaint* paint) const {
     33     as_IB(this)->onDraw(canvas, x, y, paint);
     34 }
     35 
     36 void SkImage::draw(SkCanvas* canvas, const SkRect* src, const SkRect& dst,
     37                    const SkPaint* paint) const {
     38     as_IB(this)->onDrawRectToRect(canvas, src, dst, paint);
     39 }
     40 
     41 const void* SkImage::peekPixels(SkImageInfo* info, size_t* rowBytes) const {
     42     SkImageInfo infoStorage;
     43     size_t rowBytesStorage;
     44     if (NULL == info) {
     45         info = &infoStorage;
     46     }
     47     if (NULL == rowBytes) {
     48         rowBytes = &rowBytesStorage;
     49     }
     50     return as_IB(this)->onPeekPixels(info, rowBytes);
     51 }
     52 
     53 bool SkImage::readPixels(SkBitmap* bitmap, const SkIRect* subset) const {
     54     if (NULL == bitmap) {
     55         return false;
     56     }
     57 
     58     SkIRect bounds = SkIRect::MakeWH(this->width(), this->height());
     59 
     60     // trim against the bitmap, if its already been allocated
     61     if (bitmap->pixelRef()) {
     62         bounds.fRight = SkMin32(bounds.fRight, bitmap->width());
     63         bounds.fBottom = SkMin32(bounds.fBottom, bitmap->height());
     64         if (bounds.isEmpty()) {
     65             return false;
     66         }
     67     }
     68 
     69     if (subset && !bounds.intersect(*subset)) {
     70         // perhaps we could return true + empty-bitmap?
     71         return false;
     72     }
     73     return as_IB(this)->onReadPixels(bitmap, bounds);
     74 }
     75 
     76 GrTexture* SkImage::getTexture() {
     77     return as_IB(this)->onGetTexture();
     78 }
     79 
     80 SkShader* SkImage::newShader(SkShader::TileMode tileX,
     81                              SkShader::TileMode tileY,
     82                              const SkMatrix* localMatrix) const {
     83     return as_IB(this)->onNewShader(tileX, tileY, localMatrix);
     84 }
     85 
     86 SkData* SkImage::encode(SkImageEncoder::Type type, int quality) const {
     87     SkBitmap bm;
     88     if (as_IB(this)->getROPixels(&bm)) {
     89         return SkImageEncoder::EncodeData(bm, type, quality);
     90     }
     91     return NULL;
     92 }
     93 
     94 ///////////////////////////////////////////////////////////////////////////////
     95 
     96 static bool raster_canvas_supports(const SkImageInfo& info) {
     97     switch (info.colorType()) {
     98         case kN32_SkColorType:
     99             return kUnpremul_SkAlphaType != info.alphaType();
    100         case kRGB_565_SkColorType:
    101             return true;
    102         case kAlpha_8_SkColorType:
    103             return true;
    104         default:
    105             break;
    106     }
    107     return false;
    108 }
    109 
    110 bool SkImage_Base::onReadPixels(SkBitmap* bitmap, const SkIRect& subset) const {
    111     if (bitmap->pixelRef()) {
    112         const SkImageInfo info = bitmap->info();
    113         if (kUnknown_SkColorType == info.colorType()) {
    114             return false;
    115         }
    116         if (!raster_canvas_supports(info)) {
    117             return false;
    118         }
    119     } else {
    120         SkBitmap tmp;
    121         if (!tmp.tryAllocN32Pixels(subset.width(), subset.height())) {
    122             return false;
    123         }
    124         *bitmap = tmp;
    125     }
    126 
    127     SkRect srcR, dstR;
    128     srcR.set(subset);
    129     dstR = srcR;
    130     dstR.offset(-dstR.left(), -dstR.top());
    131 
    132     SkCanvas canvas(*bitmap);
    133 
    134     SkPaint paint;
    135     paint.setXfermodeMode(SkXfermode::kClear_Mode);
    136     canvas.drawRect(dstR, paint);
    137 
    138     const_cast<SkImage_Base*>(this)->onDrawRectToRect(&canvas, &srcR, dstR, NULL);
    139     return true;
    140 }
    141