reed@google.com | 889b09e | 2012-07-27 21:10:42 +0000 | [diff] [blame] | 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 | |
| 14 | class SkCanvas; |
| 15 | class SkPaint; |
reed@google.com | 5d4ba88 | 2012-07-31 15:45:27 +0000 | [diff] [blame^] | 16 | class GrContext; |
| 17 | class GrRenderTarget; |
reed@google.com | 889b09e | 2012-07-27 21:10:42 +0000 | [diff] [blame] | 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 | */ |
| 27 | class SkSurface : public SkRefCnt { |
| 28 | public: |
| 29 | /** |
| 30 | * Create a new surface, using the specified pixels/rowbytes as its |
| 31 | * backend. |
| 32 | * |
| 33 | * If the requested surface cannot be created, or the request is not a |
| 34 | * supported configuration, NULL will be returned. |
| 35 | */ |
| 36 | static SkSurface* NewRasterDirect(const SkImage::Info&, SkColorSpace*, |
| 37 | void* pixels, size_t rowBytes); |
| 38 | |
| 39 | /** |
| 40 | * Return a new surface, with the memory for the pixels automatically |
| 41 | * allocated. |
| 42 | * |
| 43 | * If the requested surface cannot be created, or the request is not a |
| 44 | * supported configuration, NULL will be returned. |
| 45 | */ |
| 46 | static SkSurface* NewRaster(const SkImage::Info&, SkColorSpace*); |
| 47 | |
| 48 | /** |
| 49 | * Return a new surface whose contents will be recorded into a picture. |
| 50 | * When this surface is drawn into another canvas, its contents will be |
| 51 | * "replayed" into that canvas. |
| 52 | */ |
| 53 | static SkSurface* NewPicture(int width, int height); |
| 54 | |
reed@google.com | 5d4ba88 | 2012-07-31 15:45:27 +0000 | [diff] [blame^] | 55 | /** |
| 56 | * Return a new surface using the specified render target. |
| 57 | */ |
| 58 | static SkSurface* NewRenderTargetDirect(GrContext*, GrRenderTarget*); |
| 59 | |
| 60 | /** |
| 61 | * Return a new surface whose contents will be drawn to an offscreen |
| 62 | * render target, allocated by the surface. |
| 63 | */ |
| 64 | static SkSurface* NewRenderTarget(GrContext*, const SkImage::Info&, |
| 65 | SkColorSpace*, int sampleCount = 0); |
| 66 | |
reed@google.com | 889b09e | 2012-07-27 21:10:42 +0000 | [diff] [blame] | 67 | int width() const { return fWidth; } |
| 68 | int height() const { return fHeight; } |
| 69 | |
| 70 | /** |
| 71 | * Returns a unique non-zero, unique value identifying the content of this |
| 72 | * surface. Each time the content is changed changed, either by drawing |
| 73 | * into this surface, or explicitly calling notifyContentChanged()) this |
| 74 | * method will return a new value. |
| 75 | * |
| 76 | * If this surface is empty (i.e. has a zero-dimention), this will return |
| 77 | * 0. |
| 78 | */ |
| 79 | uint32_t generationID() const; |
| 80 | |
| 81 | /** |
| 82 | * Call this if the contents have changed. This will (lazily) force a new |
| 83 | * value to be returned from generationID() when it is called next. |
| 84 | */ |
| 85 | void notifyContentChanged(); |
| 86 | |
| 87 | /** |
reed@google.com | 9ea5a3b | 2012-07-30 21:03:46 +0000 | [diff] [blame] | 88 | * Return a canvas that will draw into this surface. This will always |
| 89 | * return the same canvas for a given surface, and is manged/owned by the |
| 90 | * surface. It should not be used when its parent surface has gone out of |
| 91 | * scope. |
reed@google.com | 889b09e | 2012-07-27 21:10:42 +0000 | [diff] [blame] | 92 | */ |
reed@google.com | 9ea5a3b | 2012-07-30 21:03:46 +0000 | [diff] [blame] | 93 | SkCanvas* getCanvas(); |
reed@google.com | 889b09e | 2012-07-27 21:10:42 +0000 | [diff] [blame] | 94 | |
| 95 | /** |
| 96 | * Return a new surface that is "compatible" with this one, in that it will |
| 97 | * efficiently be able to be drawn into this surface. Typical calling |
| 98 | * pattern: |
| 99 | * |
| 100 | * SkSurface* A = SkSurface::New...(); |
| 101 | * SkCanvas* canvasA = surfaceA->newCanvas(); |
| 102 | * ... |
| 103 | * SkSurface* surfaceB = surfaceA->newSurface(...); |
| 104 | * SkCanvas* canvasB = surfaceB->newCanvas(); |
| 105 | * ... // draw using canvasB |
| 106 | * canvasA->drawSurface(surfaceB); // <--- this will always be optimal! |
| 107 | */ |
| 108 | SkSurface* newSurface(const SkImage::Info&, SkColorSpace*); |
| 109 | |
| 110 | /** |
| 111 | * Returns an image of the current state of the surface pixels up to this |
| 112 | * point. Subsequent changes to the surface (by drawing into its canvas) |
| 113 | * will not be reflected in this image. |
| 114 | */ |
| 115 | SkImage* newImageShapshot(); |
| 116 | |
| 117 | /** |
| 118 | * Thought the caller could get a snapshot image explicitly, and draw that, |
| 119 | * it seems that directly drawing a surface into another canvas might be |
| 120 | * a common pattern, and that we could possibly be more efficient, since |
| 121 | * we'd know that the "snapshot" need only live until we've handed it off |
| 122 | * to the canvas. |
| 123 | */ |
| 124 | void draw(SkCanvas*, SkScalar x, SkScalar y, const SkPaint*); |
| 125 | |
| 126 | protected: |
| 127 | SkSurface(int width, int height); |
| 128 | |
| 129 | private: |
| 130 | const int fWidth; |
| 131 | const int fHeight; |
| 132 | mutable uint32_t fGenerationID; |
| 133 | }; |
| 134 | |
| 135 | #endif |