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