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(SkPixelRef*);
     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     int shift = 0;
     43     switch (info.fColorType) {
     44         case kAlpha_8_SkColorType:
     45             shift = 0;
     46             break;
     47         case kRGB_565_SkColorType:
     48             shift = 1;
     49             break;
     50         case kN32_SkColorType:
     51             shift = 2;
     52             break;
     53         default:
     54             return false;
     55     }
     56 
     57     if (kIgnoreRowBytesValue == rowBytes) {
     58         return true;
     59     }
     60 
     61     uint64_t minRB = (uint64_t)info.fWidth << shift;
     62     if (minRB > rowBytes) {
     63         return false;
     64     }
     65 
     66     size_t alignedRowBytes = rowBytes >> shift << shift;
     67     if (alignedRowBytes != rowBytes) {
     68         return false;
     69     }
     70 
     71     uint64_t size = sk_64_mul(info.fHeight, rowBytes);
     72     if (size > kMaxTotalSize) {
     73         return false;
     74     }
     75 
     76     return true;
     77 }
     78 
     79 SkSurface_Raster::SkSurface_Raster(const SkImageInfo& info, void* pixels, size_t rb)
     80     : INHERITED(info)
     81 {
     82     fBitmap.installPixels(info, pixels, rb);
     83     fWeOwnThePixels = false;    // We are "Direct"
     84 }
     85 
     86 SkSurface_Raster::SkSurface_Raster(SkPixelRef* pr)
     87     : INHERITED(pr->info().fWidth, pr->info().fHeight)
     88 {
     89     const SkImageInfo& info = pr->info();
     90 
     91     fBitmap.setInfo(info, info.minRowBytes());
     92     fBitmap.setPixelRef(pr);
     93     fWeOwnThePixels = true;
     94 
     95     if (!info.isOpaque()) {
     96         fBitmap.eraseColor(SK_ColorTRANSPARENT);
     97     }
     98 }
     99 
    100 SkCanvas* SkSurface_Raster::onNewCanvas() {
    101     return SkNEW_ARGS(SkCanvas, (fBitmap));
    102 }
    103 
    104 SkSurface* SkSurface_Raster::onNewSurface(const SkImageInfo& info) {
    105     return SkSurface::NewRaster(info);
    106 }
    107 
    108 void SkSurface_Raster::onDraw(SkCanvas* canvas, SkScalar x, SkScalar y,
    109                               const SkPaint* paint) {
    110     canvas->drawBitmap(fBitmap, x, y, paint);
    111 }
    112 
    113 SkImage* SkSurface_Raster::onNewImageSnapshot() {
    114     return SkNewImageFromBitmap(fBitmap, fWeOwnThePixels);
    115 }
    116 
    117 void SkSurface_Raster::onCopyOnWrite(ContentChangeMode mode) {
    118     // are we sharing pixelrefs with the image?
    119     SkASSERT(NULL != this->getCachedImage());
    120     if (SkBitmapImageGetPixelRef(this->getCachedImage()) == fBitmap.pixelRef()) {
    121         SkASSERT(fWeOwnThePixels);
    122         if (kDiscard_ContentChangeMode == mode) {
    123             fBitmap.setPixelRef(NULL);
    124             fBitmap.allocPixels();
    125         } else {
    126             SkBitmap prev(fBitmap);
    127             prev.deepCopyTo(&fBitmap);
    128         }
    129         // Now fBitmap is a deep copy of itself (and therefore different from
    130         // what is being used by the image. Next we update the canvas to use
    131         // this as its backend, so we can't modify the image's pixels anymore.
    132         SkASSERT(NULL != this->getCachedCanvas());
    133         this->getCachedCanvas()->getDevice()->replaceBitmapBackendForRasterSurface(fBitmap);
    134     }
    135 }
    136 
    137 ///////////////////////////////////////////////////////////////////////////////
    138 
    139 SkSurface* SkSurface::NewRasterDirect(const SkImageInfo& info, void* pixels, size_t rowBytes) {
    140     if (!SkSurface_Raster::Valid(info, rowBytes)) {
    141         return NULL;
    142     }
    143     if (NULL == pixels) {
    144         return NULL;
    145     }
    146 
    147     return SkNEW_ARGS(SkSurface_Raster, (info, pixels, rowBytes));
    148 }
    149 
    150 SkSurface* SkSurface::NewRaster(const SkImageInfo& info) {
    151     if (!SkSurface_Raster::Valid(info)) {
    152         return NULL;
    153     }
    154 
    155     SkAutoTUnref<SkPixelRef> pr(SkMallocPixelRef::NewAllocate(info, 0, NULL));
    156     if (NULL == pr.get()) {
    157         return NULL;
    158     }
    159     return SkNEW_ARGS(SkSurface_Raster, (pr));
    160 }
    161