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