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