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* 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 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::onNewImageSnapshot() {
    124     return SkNewImageFromBitmap(fBitmap, fWeOwnThePixels);
    125 }
    126 
    127 void SkSurface_Raster::onCopyOnWrite(ContentChangeMode mode) {
    128     // are we sharing pixelrefs with the image?
    129     SkASSERT(NULL != this->getCachedImage());
    130     if (SkBitmapImageGetPixelRef(this->getCachedImage()) == fBitmap.pixelRef()) {
    131         SkASSERT(fWeOwnThePixels);
    132         if (kDiscard_ContentChangeMode == mode) {
    133             fBitmap.setPixelRef(NULL, 0);
    134             fBitmap.allocPixels();
    135         } else {
    136             SkBitmap prev(fBitmap);
    137             prev.deepCopyTo(&fBitmap, prev.config());
    138         }
    139         // Now fBitmap is a deep copy of itself (and therefore different from
    140         // what is being used by the image. Next we update the canvas to use
    141         // this as its backend, so we can't modify the image's pixels anymore.
    142         SkASSERT(NULL != this->getCachedCanvas());
    143         this->getCachedCanvas()->getDevice()->replaceBitmapBackendForRasterSurface(fBitmap);
    144     }
    145 }
    146 
    147 ///////////////////////////////////////////////////////////////////////////////
    148 
    149 SkSurface* SkSurface::NewRasterDirect(const SkImage::Info& info, void* pixels, size_t rowBytes) {
    150     if (!SkSurface_Raster::Valid(info, rowBytes)) {
    151         return NULL;
    152     }
    153     if (NULL == pixels) {
    154         return NULL;
    155     }
    156 
    157     return SkNEW_ARGS(SkSurface_Raster, (info, pixels, rowBytes));
    158 }
    159 
    160 SkSurface* SkSurface::NewRaster(const SkImage::Info& info) {
    161     if (!SkSurface_Raster::Valid(info)) {
    162         return NULL;
    163     }
    164 
    165     static const size_t kMaxTotalSize = SK_MaxS32;
    166     size_t rowBytes = SkImageMinRowBytes(info);
    167     uint64_t size64 = (uint64_t)info.fHeight * rowBytes;
    168     if (size64 > kMaxTotalSize) {
    169         return NULL;
    170     }
    171 
    172     size_t size = (size_t)size64;
    173     void* pixels = sk_malloc_throw(size);
    174     if (NULL == pixels) {
    175         return NULL;
    176     }
    177 
    178     SkAutoTUnref<SkPixelRef> pr(SkNEW_ARGS(SkMallocPixelRef, (pixels, size, NULL, true)));
    179     return SkNEW_ARGS(SkSurface_Raster, (info, pr, rowBytes));
    180 }
    181