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 
     12 ///////////////////////////////////////////////////////////////////////////////
     13 
     14 SkSurface_Base::SkSurface_Base(int width, int height) : INHERITED(width, height) {
     15     fCachedCanvas = NULL;
     16     fCachedImage = NULL;
     17 }
     18 
     19 SkSurface_Base::SkSurface_Base(const SkImageInfo& info) : INHERITED(info) {
     20     fCachedCanvas = NULL;
     21     fCachedImage = NULL;
     22 }
     23 
     24 SkSurface_Base::~SkSurface_Base() {
     25     // in case the canvas outsurvives us, we null the callback
     26     if (fCachedCanvas) {
     27         fCachedCanvas->setSurfaceBase(NULL);
     28     }
     29 
     30     SkSafeUnref(fCachedImage);
     31     SkSafeUnref(fCachedCanvas);
     32 }
     33 
     34 void SkSurface_Base::onDraw(SkCanvas* canvas, SkScalar x, SkScalar y,
     35                             const SkPaint* paint) {
     36     SkImage* image = this->newImageSnapshot();
     37     if (image) {
     38         image->draw(canvas, x, y, paint);
     39         image->unref();
     40     }
     41 }
     42 
     43 void SkSurface_Base::aboutToDraw(ContentChangeMode mode) {
     44     this->dirtyGenerationID();
     45 
     46     SkASSERT(!fCachedCanvas || fCachedCanvas->getSurfaceBase() == this);
     47 
     48     if (NULL != fCachedImage) {
     49         // the surface may need to fork its backend, if its sharing it with
     50         // the cached image. Note: we only call if there is an outstanding owner
     51         // on the image (besides us).
     52         if (!fCachedImage->unique()) {
     53             this->onCopyOnWrite(mode);
     54         }
     55 
     56         // regardless of copy-on-write, we must drop our cached image now, so
     57         // that the next request will get our new contents.
     58         fCachedImage->unref();
     59         fCachedImage = NULL;
     60     } else if (kDiscard_ContentChangeMode == mode) {
     61         this->onDiscard();
     62     }
     63 }
     64 
     65 uint32_t SkSurface_Base::newGenerationID() {
     66     SkASSERT(!fCachedCanvas || fCachedCanvas->getSurfaceBase() == this);
     67     static int32_t gID;
     68     return sk_atomic_inc(&gID) + 1;
     69 }
     70 
     71 static SkSurface_Base* asSB(SkSurface* surface) {
     72     return static_cast<SkSurface_Base*>(surface);
     73 }
     74 
     75 ///////////////////////////////////////////////////////////////////////////////
     76 
     77 SkSurface::SkSurface(int width, int height) : fWidth(width), fHeight(height) {
     78     SkASSERT(fWidth >= 0);
     79     SkASSERT(fHeight >= 0);
     80     fGenerationID = 0;
     81 }
     82 
     83 SkSurface::SkSurface(const SkImageInfo& info)
     84     : fWidth(info.fWidth)
     85     , fHeight(info.fHeight)
     86 {
     87     SkASSERT(fWidth >= 0);
     88     SkASSERT(fHeight >= 0);
     89     fGenerationID = 0;
     90 }
     91 
     92 uint32_t SkSurface::generationID() {
     93     if (0 == fGenerationID) {
     94         fGenerationID = asSB(this)->newGenerationID();
     95     }
     96     return fGenerationID;
     97 }
     98 
     99 void SkSurface::notifyContentWillChange(ContentChangeMode mode) {
    100     asSB(this)->aboutToDraw(mode);
    101 }
    102 
    103 SkCanvas* SkSurface::getCanvas() {
    104     return asSB(this)->getCachedCanvas();
    105 }
    106 
    107 SkImage* SkSurface::newImageSnapshot() {
    108     SkImage* image = asSB(this)->getCachedImage();
    109     SkSafeRef(image);   // the caller will call unref() to balance this
    110     return image;
    111 }
    112 
    113 SkSurface* SkSurface::newSurface(const SkImageInfo& info) {
    114     return asSB(this)->onNewSurface(info);
    115 }
    116 
    117 void SkSurface::draw(SkCanvas* canvas, SkScalar x, SkScalar y,
    118                      const SkPaint* paint) {
    119     return asSB(this)->onDraw(canvas, x, y, paint);
    120 }
    121 
    122 const void* SkSurface::peekPixels(SkImageInfo* info, size_t* rowBytes) {
    123     return this->getCanvas()->peekPixels(info, rowBytes);
    124 }
    125