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 "SkSurface_Base.h"
      9 #include "SkImagePriv.h"
     10 #include "SkCanvas.h"
     11 #include "SkDevice.h"
     12 #include "SkMallocPixelRef.h"
     13 
     14 static const size_t kIgnoreRowBytesValue = (size_t)~0;
     15 
     16 class SkSurface_Raster : public SkSurface_Base {
     17 public:
     18     static bool Valid(const SkImageInfo&, size_t rb = kIgnoreRowBytesValue);
     19 
     20     SkSurface_Raster(const SkImageInfo&, void*, size_t rb);
     21     SkSurface_Raster(const SkImageInfo&, SkPixelRef*, size_t rb);
     22 
     23     virtual SkCanvas* onNewCanvas() SK_OVERRIDE;
     24     virtual SkSurface* onNewSurface(const SkImageInfo&) SK_OVERRIDE;
     25     virtual SkImage* onNewImageSnapshot() SK_OVERRIDE;
     26     virtual void onDraw(SkCanvas*, SkScalar x, SkScalar y,
     27                         const SkPaint*) SK_OVERRIDE;
     28     virtual void onCopyOnWrite(ContentChangeMode) SK_OVERRIDE;
     29 
     30 private:
     31     SkBitmap    fBitmap;
     32     bool        fWeOwnThePixels;
     33 
     34     typedef SkSurface_Base INHERITED;
     35 };
     36 
     37 ///////////////////////////////////////////////////////////////////////////////
     38 
     39 bool SkSurface_Raster::Valid(const SkImageInfo& info, size_t rowBytes) {
     40     static const size_t kMaxTotalSize = SK_MaxS32;
     41 
     42     SkBitmap::Config config = SkImageInfoToBitmapConfig(info);
     43 
     44     int shift = 0;
     45     switch (config) {
     46         case SkBitmap::kA8_Config:
     47             shift = 0;
     48             break;
     49         case SkBitmap::kRGB_565_Config:
     50             shift = 1;
     51             break;
     52         case SkBitmap::kARGB_8888_Config:
     53             shift = 2;
     54             break;
     55         default:
     56             return false;
     57     }
     58 
     59     // TODO: examine colorspace
     60 
     61     if (kIgnoreRowBytesValue == rowBytes) {
     62         return true;
     63     }
     64 
     65     uint64_t minRB = (uint64_t)info.fWidth << shift;
     66     if (minRB > rowBytes) {
     67         return false;
     68     }
     69 
     70     size_t alignedRowBytes = rowBytes >> shift << shift;
     71     if (alignedRowBytes != rowBytes) {
     72         return false;
     73     }
     74 
     75     uint64_t size = (uint64_t)info.fHeight * rowBytes;
     76     if (size > kMaxTotalSize) {
     77         return false;
     78     }
     79 
     80     return true;
     81 }
     82 
     83 SkSurface_Raster::SkSurface_Raster(const SkImageInfo& info, void* pixels, size_t rb)
     84         : INHERITED(info.fWidth, info.fHeight) {
     85     SkBitmap::Config config = SkImageInfoToBitmapConfig(info);
     86     fBitmap.setConfig(config, info.fWidth, info.fHeight, rb, info.fAlphaType);
     87     fBitmap.setPixels(pixels);
     88     fWeOwnThePixels = false;    // We are "Direct"
     89 }
     90 
     91 SkSurface_Raster::SkSurface_Raster(const SkImageInfo& info, SkPixelRef* pr, size_t rb)
     92         : INHERITED(info.fWidth, info.fHeight) {
     93     SkBitmap::Config config = SkImageInfoToBitmapConfig(info);
     94     fBitmap.setConfig(config, info.fWidth, info.fHeight, rb, info.fAlphaType);
     95     fBitmap.setPixelRef(pr);
     96     fWeOwnThePixels = true;
     97 
     98     if (!SkAlphaTypeIsOpaque(info.fAlphaType)) {
     99         fBitmap.eraseColor(SK_ColorTRANSPARENT);
    100     }
    101 }
    102 
    103 SkCanvas* SkSurface_Raster::onNewCanvas() {
    104     return SkNEW_ARGS(SkCanvas, (fBitmap));
    105 }
    106 
    107 SkSurface* SkSurface_Raster::onNewSurface(const SkImageInfo& info) {
    108     return SkSurface::NewRaster(info);
    109 }
    110 
    111 void SkSurface_Raster::onDraw(SkCanvas* canvas, SkScalar x, SkScalar y,
    112                               const SkPaint* paint) {
    113     canvas->drawBitmap(fBitmap, x, y, paint);
    114 }
    115 
    116 SkImage* SkSurface_Raster::onNewImageSnapshot() {
    117     return SkNewImageFromBitmap(fBitmap, fWeOwnThePixels);
    118 }
    119 
    120 void SkSurface_Raster::onCopyOnWrite(ContentChangeMode mode) {
    121     // are we sharing pixelrefs with the image?
    122     SkASSERT(NULL != this->getCachedImage());
    123     if (SkBitmapImageGetPixelRef(this->getCachedImage()) == fBitmap.pixelRef()) {
    124         SkASSERT(fWeOwnThePixels);
    125         if (kDiscard_ContentChangeMode == mode) {
    126             fBitmap.setPixelRef(NULL, 0);
    127             fBitmap.allocPixels();
    128         } else {
    129             SkBitmap prev(fBitmap);
    130             prev.deepCopyTo(&fBitmap, prev.config());
    131         }
    132         // Now fBitmap is a deep copy of itself (and therefore different from
    133         // what is being used by the image. Next we update the canvas to use
    134         // this as its backend, so we can't modify the image's pixels anymore.
    135         SkASSERT(NULL != this->getCachedCanvas());
    136         this->getCachedCanvas()->getDevice()->replaceBitmapBackendForRasterSurface(fBitmap);
    137     }
    138 }
    139 
    140 ///////////////////////////////////////////////////////////////////////////////
    141 
    142 SkSurface* SkSurface::NewRasterDirect(const SkImageInfo& info, void* pixels, size_t rowBytes) {
    143     if (!SkSurface_Raster::Valid(info, rowBytes)) {
    144         return NULL;
    145     }
    146     if (NULL == pixels) {
    147         return NULL;
    148     }
    149 
    150     return SkNEW_ARGS(SkSurface_Raster, (info, pixels, rowBytes));
    151 }
    152 
    153 SkSurface* SkSurface::NewRaster(const SkImageInfo& info) {
    154     if (!SkSurface_Raster::Valid(info)) {
    155         return NULL;
    156     }
    157 
    158     SkAutoTUnref<SkPixelRef> pr(SkMallocPixelRef::NewAllocate(info, 0, NULL));
    159     if (NULL == pr.get()) {
    160         return NULL;
    161     }
    162     return SkNEW_ARGS(SkSurface_Raster, (info, pr, info.minRowBytes()));
    163 }
    164