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_DEFINED
9#define SkSurface_DEFINED
10
11#include "SkRefCnt.h"
12#include "SkImage.h"
13
14class SkCanvas;
15class SkPaint;
16class GrContext;
17class GrRenderTarget;
18
19/**
20 *  SkSurface represents the backend/results of drawing to a canvas. For raster
21 *  drawing, the surface will be pixels, but (for example) when drawing into
22 *  a PDF or Picture canvas, the surface stores the recorded commands.
23 *
24 *  To draw into a canvas, first create the appropriate type of Surface, and
25 *  then request the canvas from the surface.
26 */
27class SK_API SkSurface : public SkRefCnt {
28public:
29    SK_DECLARE_INST_COUNT(SkSurface)
30
31    /**
32     *  Create a new surface, using the specified pixels/rowbytes as its
33     *  backend.
34     *
35     *  If the requested surface cannot be created, or the request is not a
36     *  supported configuration, NULL will be returned.
37     */
38    static SkSurface* NewRasterDirect(const SkImageInfo&, void* pixels, size_t rowBytes);
39
40    /**
41     *  Return a new surface, with the memory for the pixels automatically
42     *  allocated.
43     *
44     *  If the requested surface cannot be created, or the request is not a
45     *  supported configuration, NULL will be returned.
46     */
47    static SkSurface* NewRaster(const SkImageInfo&);
48
49    /**
50     *  Helper version of NewRaster. It creates a SkImageInfo with the
51     *  specified width and height, and populates the rest of info to match
52     *  pixels in SkPMColor format.
53     */
54    static SkSurface* NewRasterPMColor(int width, int height) {
55        SkImageInfo info = {
56            width, height, kPMColor_SkColorType, kPremul_SkAlphaType
57        };
58        return NewRaster(info);
59    }
60
61    /**
62     *  Return a new surface whose contents will be recorded into a picture.
63     *  When this surface is drawn into another canvas, its contents will be
64     *  "replayed" into that canvas.
65     */
66    static SkSurface* NewPicture(int width, int height);
67
68    /**
69     *  Return a new surface using the specified render target.
70     */
71    static SkSurface* NewRenderTargetDirect(GrContext*, GrRenderTarget*);
72
73    /**
74     *  Return a new surface whose contents will be drawn to an offscreen
75     *  render target, allocated by the surface.
76     */
77    static SkSurface* NewRenderTarget(GrContext*, const SkImageInfo&, int sampleCount = 0);
78
79    int width() const { return fWidth; }
80    int height() const { return fHeight; }
81
82    /**
83     *  Returns a unique non-zero, unique value identifying the content of this
84     *  surface. Each time the content is changed changed, either by drawing
85     *  into this surface, or explicitly calling notifyContentChanged()) this
86     *  method will return a new value.
87     *
88     *  If this surface is empty (i.e. has a zero-dimention), this will return
89     *  0.
90     */
91    uint32_t generationID();
92
93    /**
94     *  Modes that can be passed to notifyContentWillChange
95     */
96    enum ContentChangeMode {
97        /**
98         *  Use this mode if it is known that the upcoming content changes will
99         *  clear or overwrite prior contents, thus making them discardable.
100         */
101        kDiscard_ContentChangeMode,
102        /**
103         *  Use this mode if prior surface contents need to be preserved or
104         *  if in doubt.
105         */
106        kRetain_ContentChangeMode,
107    };
108
109    /**
110     *  Call this if the contents are about to change. This will (lazily) force a new
111     *  value to be returned from generationID() when it is called next.
112     */
113    void notifyContentWillChange(ContentChangeMode mode);
114
115    /**
116     *  Return a canvas that will draw into this surface. This will always
117     *  return the same canvas for a given surface, and is manged/owned by the
118     *  surface. It should not be used when its parent surface has gone out of
119     *  scope.
120     */
121    SkCanvas* getCanvas();
122
123    /**
124     *  Return a new surface that is "compatible" with this one, in that it will
125     *  efficiently be able to be drawn into this surface. Typical calling
126     *  pattern:
127     *
128     *  SkSurface* A = SkSurface::New...();
129     *  SkCanvas* canvasA = surfaceA->newCanvas();
130     *  ...
131     *  SkSurface* surfaceB = surfaceA->newSurface(...);
132     *  SkCanvas* canvasB = surfaceB->newCanvas();
133     *  ... // draw using canvasB
134     *  canvasA->drawSurface(surfaceB); // <--- this will always be optimal!
135     */
136    SkSurface* newSurface(const SkImageInfo&);
137
138    /**
139     *  Returns an image of the current state of the surface pixels up to this
140     *  point. Subsequent changes to the surface (by drawing into its canvas)
141     *  will not be reflected in this image.
142     */
143    SkImage* newImageSnapshot();
144
145    /**
146     *  Thought the caller could get a snapshot image explicitly, and draw that,
147     *  it seems that directly drawing a surface into another canvas might be
148     *  a common pattern, and that we could possibly be more efficient, since
149     *  we'd know that the "snapshot" need only live until we've handed it off
150     *  to the canvas.
151     */
152    void draw(SkCanvas*, SkScalar x, SkScalar y, const SkPaint*);
153
154protected:
155    SkSurface(int width, int height);
156
157    // called by subclass if their contents have changed
158    void dirtyGenerationID() {
159        fGenerationID = 0;
160    }
161
162private:
163    const int   fWidth;
164    const int   fHeight;
165    uint32_t    fGenerationID;
166
167    typedef SkRefCnt INHERITED;
168};
169
170#endif
171