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,
     33                    const SkPaint* paint) {
     34     as_IB(this)->onDraw(canvas, x, y, paint);
     35 }
     36 
     37 void SkImage::draw(SkCanvas* canvas, const SkRect* src, const SkRect& dst,
     38                    const SkPaint* paint) {
     39     as_IB(this)->onDrawRectToRect(canvas, src, dst, paint);
     40 }
     41 
     42 const void* SkImage::peekPixels(SkImageInfo* info, size_t* rowBytes) const {
     43     SkImageInfo infoStorage;
     44     size_t rowBytesStorage;
     45     if (NULL == info) {
     46         info = &infoStorage;
     47     }
     48     if (NULL == rowBytes) {
     49         rowBytes = &rowBytesStorage;
     50     }
     51     return as_IB(this)->onPeekPixels(info, rowBytes);
     52 }
     53 
     54 bool SkImage::readPixels(SkBitmap* bitmap, const SkIRect* subset) const {
     55     if (NULL == bitmap) {
     56         return false;
     57     }
     58 
     59     SkIRect bounds = SkIRect::MakeWH(this->width(), this->height());
     60 
     61     // trim against the bitmap, if its already been allocated
     62     if (bitmap->pixelRef()) {
     63         bounds.fRight = SkMin32(bounds.fRight, bitmap->width());
     64         bounds.fBottom = SkMin32(bounds.fBottom, bitmap->height());
     65         if (bounds.isEmpty()) {
     66             return false;
     67         }
     68     }
     69 
     70     if (subset && !bounds.intersect(*subset)) {
     71         // perhaps we could return true + empty-bitmap?
     72         return false;
     73     }
     74     return as_IB(this)->onReadPixels(bitmap, bounds);
     75 }
     76 
     77 GrTexture* SkImage::getTexture() {
     78     return as_IB(this)->onGetTexture();
     79 }
     80 
     81 SkData* SkImage::encode(SkImageEncoder::Type type, int quality) const {
     82     SkBitmap bm;
     83     if (as_IB(this)->getROPixels(&bm)) {
     84         return SkImageEncoder::EncodeData(bm, type, quality);
     85     }
     86     return NULL;
     87 }
     88 
     89 ///////////////////////////////////////////////////////////////////////////////
     90 
     91 static bool raster_canvas_supports(const SkImageInfo& info) {
     92     switch (info.fColorType) {
     93         case kN32_SkColorType:
     94             return kUnpremul_SkAlphaType != info.fAlphaType;
     95         case kRGB_565_SkColorType:
     96             return true;
     97         case kAlpha_8_SkColorType:
     98             return true;
     99         default:
    100             break;
    101     }
    102     return false;
    103 }
    104 
    105 bool SkImage_Base::onReadPixels(SkBitmap* bitmap, const SkIRect& subset) const {
    106     if (bitmap->pixelRef()) {
    107         const SkImageInfo info = bitmap->info();
    108         if (kUnknown_SkColorType == info.colorType()) {
    109             return false;
    110         }
    111         if (!raster_canvas_supports(info)) {
    112             return false;
    113         }
    114     } else {
    115         const SkImageInfo info = SkImageInfo::MakeN32Premul(subset.width(), subset.height());
    116         SkBitmap tmp;
    117         if (!tmp.allocPixels(info)) {
    118             return false;
    119         }
    120         *bitmap = tmp;
    121     }
    122 
    123     SkRect srcR, dstR;
    124     srcR.set(subset);
    125     dstR = srcR;
    126     dstR.offset(-dstR.left(), -dstR.top());
    127 
    128     SkCanvas canvas(*bitmap);
    129 
    130     SkPaint paint;
    131     paint.setXfermodeMode(SkXfermode::kClear_Mode);
    132     canvas.drawRect(dstR, paint);
    133 
    134     const_cast<SkImage_Base*>(this)->onDrawRectToRect(&canvas, &srcR, dstR, NULL);
    135     return true;
    136 }
    137