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#ifndef SkSurface_Base_DEFINED
9#define SkSurface_Base_DEFINED
10
11#include "SkCanvas.h"
12#include "SkSurface.h"
13#include "SkSurfacePriv.h"
14
15class SkSurface_Base : public SkSurface {
16public:
17    SkSurface_Base(int width, int height, const SkSurfaceProps*);
18    SkSurface_Base(const SkImageInfo&, const SkSurfaceProps*);
19    virtual ~SkSurface_Base();
20
21    /**
22     *  Allocate a canvas that will draw into this surface. We will cache this
23     *  canvas, to return the same object to the caller multiple times. We
24     *  take ownership, and will call unref() on the canvas when we go out of
25     *  scope.
26     */
27    virtual SkCanvas* onNewCanvas() = 0;
28
29    virtual SkSurface* onNewSurface(const SkImageInfo&) = 0;
30
31    /**
32     *  Allocate an SkImage that represents the current contents of the surface.
33     *  This needs to be able to outlive the surface itself (if need be), and
34     *  must faithfully represent the current contents, even if the surface
35     *  is changed after this called (e.g. it is drawn to via its canvas).
36     */
37    virtual SkImage* onNewImageSnapshot(Budgeted) = 0;
38
39    /**
40     *  Default implementation:
41     *
42     *  image = this->newImageSnapshot();
43     *  if (image) {
44     *      image->draw(canvas, ...);
45     *      image->unref();
46     *  }
47     */
48    virtual void onDraw(SkCanvas*, SkScalar x, SkScalar y, const SkPaint*);
49
50    /**
51     * Called as a performance hint when the Surface is allowed to make it's contents
52     * undefined.
53     */
54    virtual void onDiscard() {}
55
56    /**
57     *  If the surface is about to change, we call this so that our subclass
58     *  can optionally fork their backend (copy-on-write) in case it was
59     *  being shared with the cachedImage.
60     */
61    virtual void onCopyOnWrite(ContentChangeMode) = 0;
62
63    inline SkCanvas* getCachedCanvas();
64    inline SkImage* getCachedImage(Budgeted);
65
66    // called by SkSurface to compute a new genID
67    uint32_t newGenerationID();
68
69private:
70    SkCanvas*   fCachedCanvas;
71    SkImage*    fCachedImage;
72
73    void aboutToDraw(ContentChangeMode mode);
74    friend class SkCanvas;
75    friend class SkSurface;
76
77    typedef SkSurface INHERITED;
78};
79
80SkCanvas* SkSurface_Base::getCachedCanvas() {
81    if (NULL == fCachedCanvas) {
82        fCachedCanvas = this->onNewCanvas();
83        if (fCachedCanvas) {
84            fCachedCanvas->setSurfaceBase(this);
85        }
86    }
87    return fCachedCanvas;
88}
89
90SkImage* SkSurface_Base::getCachedImage(Budgeted budgeted) {
91    if (NULL == fCachedImage) {
92        fCachedImage = this->onNewImageSnapshot(budgeted);
93        SkASSERT(!fCachedCanvas || fCachedCanvas->getSurfaceBase() == this);
94    }
95    return fCachedImage;
96}
97
98#endif
99