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 SkImage::Info&, size_t rb = kIgnoreRowBytesValue);
     19 
     20     SkSurface_Raster(const SkImage::Info&, void*, size_t rb);
     21     SkSurface_Raster(const SkImage::Info&, SkPixelRef*, size_t rb);
     22 
     23     virtual SkCanvas* onNewCanvas() SK_OVERRIDE;
     24     virtual SkSurface* onNewSurface(const SkImage::Info&) SK_OVERRIDE;
     25     virtual SkImage* onNewImageShapshot() SK_OVERRIDE;
     26     virtual void onDraw(SkCanvas*, SkScalar x, SkScalar y,
     27                         const SkPaint*) SK_OVERRIDE;
     28     virtual void onCopyOnWrite(SkImage*, SkCanvas*) 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 SkImage::Info& info, size_t rowBytes) {
     40     static const size_t kMaxTotalSize = SK_MaxS32;
     41 
     42     bool isOpaque;
     43     SkBitmap::Config config = SkImageInfoToBitmapConfig(info, &isOpaque);
     44 
     45     int shift = 0;
     46     switch (config) {
     47         case SkBitmap::kA8_Config:
     48             shift = 0;
     49             break;
     50         case SkBitmap::kRGB_565_Config:
     51             shift = 1;
     52             break;
     53         case SkBitmap::kARGB_8888_Config:
     54             shift = 2;
     55             break;
     56         default:
     57             return false;
     58     }
     59 
     60     // TODO: examine colorspace
     61 
     62     if (kIgnoreRowBytesValue == rowBytes) {
     63         return true;
     64     }
     65 
     66     uint64_t minRB = (uint64_t)info.fWidth << shift;
     67     if (minRB > rowBytes) {
     68         return false;
     69     }
     70 
     71     size_t alignedRowBytes = rowBytes >> shift << shift;
     72     if (alignedRowBytes != rowBytes) {
     73         return false;
     74     }
     75 
     76     uint64_t size = (uint64_t)info.fHeight * rowBytes;
     77     if (size > kMaxTotalSize) {
     78         return false;
     79     }
     80 
     81     return true;
     82 }
     83 
     84 SkSurface_Raster::SkSurface_Raster(const SkImage::Info& info, void* pixels, size_t rb)
     85         : INHERITED(info.fWidth, info.fHeight) {
     86     bool isOpaque;
     87     SkBitmap::Config config = SkImageInfoToBitmapConfig(info, &isOpaque);
     88 
     89     fBitmap.setConfig(config, info.fWidth, info.fHeight, rb);
     90     fBitmap.setPixels(pixels);
     91     fBitmap.setIsOpaque(isOpaque);
     92     fWeOwnThePixels = false;    // We are "Direct"
     93 }
     94 
     95 SkSurface_Raster::SkSurface_Raster(const SkImage::Info& info, SkPixelRef* pr, size_t rb)
     96         : INHERITED(info.fWidth, info.fHeight) {
     97     bool isOpaque;
     98     SkBitmap::Config config = SkImageInfoToBitmapConfig(info, &isOpaque);
     99 
    100     fBitmap.setConfig(config, info.fWidth, info.fHeight, rb);
    101     fBitmap.setPixelRef(pr);
    102     fBitmap.setIsOpaque(isOpaque);
    103     fWeOwnThePixels = true;
    104 
    105     if (!isOpaque) {
    106         fBitmap.eraseColor(SK_ColorTRANSPARENT);
    107     }
    108 }
    109 
    110 SkCanvas* SkSurface_Raster::onNewCanvas() {
    111     return SkNEW_ARGS(SkCanvas, (fBitmap));
    112 }
    113 
    114 SkSurface* SkSurface_Raster::onNewSurface(const SkImage::Info& info) {
    115     return SkSurface::NewRaster(info);
    116 }
    117 
    118 void SkSurface_Raster::onDraw(SkCanvas* canvas, SkScalar x, SkScalar y,
    119                               const SkPaint* paint) {
    120     canvas->drawBitmap(fBitmap, x, y, paint);
    121 }
    122 
    123 SkImage* SkSurface_Raster::onNewImageShapshot() {
    124     return SkNewImageFromBitmap(fBitmap, fWeOwnThePixels);
    125 }
    126 
    127 void SkSurface_Raster::onCopyOnWrite(SkImage* image, SkCanvas* canvas) {
    128     // are we sharing pixelrefs with the image?
    129     if (SkBitmapImageGetPixelRef(image) == fBitmap.pixelRef()) {
    130         SkASSERT(fWeOwnThePixels);
    131         SkBitmap prev(fBitmap);
    132         prev.deepCopyTo(&fBitmap, prev.config());
    133         // Now fBitmap is a deep copy of itself (and therefore different from
    134         // what is being used by the image. Next we update the canvas to use
    135         // this as its backend, so we can't modify the image's pixels anymore.
    136         canvas->getDevice()->replaceBitmapBackendForRasterSurface(fBitmap);
    137     }
    138 }
    139 
    140 ///////////////////////////////////////////////////////////////////////////////
    141 
    142 SkSurface* SkSurface::NewRasterDirect(const SkImage::Info& 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 SkImage::Info& info) {
    154     if (!SkSurface_Raster::Valid(info)) {
    155         return NULL;
    156     }
    157 
    158     static const size_t kMaxTotalSize = SK_MaxS32;
    159     size_t rowBytes = SkImageMinRowBytes(info);
    160     uint64_t size64 = (uint64_t)info.fHeight * rowBytes;
    161     if (size64 > kMaxTotalSize) {
    162         return NULL;
    163     }
    164 
    165     size_t size = (size_t)size64;
    166     void* pixels = sk_malloc_throw(size);
    167     if (NULL == pixels) {
    168         return NULL;
    169     }
    170 
    171     SkAutoTUnref<SkPixelRef> pr(SkNEW_ARGS(SkMallocPixelRef, (pixels, size, NULL, true)));
    172     return SkNEW_ARGS(SkSurface_Raster, (info, pr, rowBytes));
    173 }
    174