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 | */ |
junov@chromium.org | 96447be | 2013-04-18 13:28:19 +0000 | [diff] [blame^] | 27 | class SK_API SkSurface : public SkRefCnt { |
reed@google.com | 889b09e | 2012-07-27 21:10:42 +0000 | [diff] [blame] | 28 | public: |
reed@google.com | fd875e8 | 2012-08-28 12:43:54 +0000 | [diff] [blame] | 29 | SK_DECLARE_INST_COUNT(SkSurface) |
robertphillips@google.com | a22e211 | 2012-08-16 14:58:06 +0000 | [diff] [blame] | 30 | |
reed@google.com | 889b09e | 2012-07-27 21:10:42 +0000 | [diff] [blame] | 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 | */ |
mike@reedtribe.org | b947625 | 2012-11-15 02:37:45 +0000 | [diff] [blame] | 38 | static SkSurface* NewRasterDirect(const SkImage::Info&, void* pixels, size_t rowBytes); |
reed@google.com | 889b09e | 2012-07-27 21:10:42 +0000 | [diff] [blame] | 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 | */ |
mike@reedtribe.org | b947625 | 2012-11-15 02:37:45 +0000 | [diff] [blame] | 47 | static SkSurface* NewRaster(const SkImage::Info&); |
reed@google.com | 889b09e | 2012-07-27 21:10:42 +0000 | [diff] [blame] | 48 | |
| 49 | /** |
| 50 | * Return a new surface whose contents will be recorded into a picture. |
| 51 | * When this surface is drawn into another canvas, its contents will be |
| 52 | * "replayed" into that canvas. |
| 53 | */ |
| 54 | static SkSurface* NewPicture(int width, int height); |
| 55 | |
reed@google.com | 5d4ba88 | 2012-07-31 15:45:27 +0000 | [diff] [blame] | 56 | /** |
| 57 | * Return a new surface using the specified render target. |
| 58 | */ |
| 59 | static SkSurface* NewRenderTargetDirect(GrContext*, GrRenderTarget*); |
| 60 | |
| 61 | /** |
| 62 | * Return a new surface whose contents will be drawn to an offscreen |
| 63 | * render target, allocated by the surface. |
| 64 | */ |
mike@reedtribe.org | b947625 | 2012-11-15 02:37:45 +0000 | [diff] [blame] | 65 | static SkSurface* NewRenderTarget(GrContext*, const SkImage::Info&, int sampleCount = 0); |
reed@google.com | 5d4ba88 | 2012-07-31 15:45:27 +0000 | [diff] [blame] | 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 | */ |
reed@google.com | 97af1a6 | 2012-08-28 12:19:02 +0000 | [diff] [blame] | 79 | uint32_t generationID(); |
rmistry@google.com | fbfcd56 | 2012-08-23 18:09:54 +0000 | [diff] [blame] | 80 | |
reed@google.com | 889b09e | 2012-07-27 21:10:42 +0000 | [diff] [blame] | 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(); |
rmistry@google.com | fbfcd56 | 2012-08-23 18:09:54 +0000 | [diff] [blame] | 86 | |
reed@google.com | 889b09e | 2012-07-27 21:10:42 +0000 | [diff] [blame] | 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 | */ |
mike@reedtribe.org | b947625 | 2012-11-15 02:37:45 +0000 | [diff] [blame] | 108 | SkSurface* newSurface(const SkImage::Info&); |
reed@google.com | 889b09e | 2012-07-27 21:10:42 +0000 | [diff] [blame] | 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 | */ |
junov@chromium.org | 5ee449a | 2013-04-12 20:20:50 +0000 | [diff] [blame] | 115 | SkImage* newImageSnapshot(); |
reed@google.com | 889b09e | 2012-07-27 21:10:42 +0000 | [diff] [blame] | 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 | |
reed@google.com | 97af1a6 | 2012-08-28 12:19:02 +0000 | [diff] [blame] | 129 | // called by subclass if their contents have changed |
| 130 | void dirtyGenerationID() { |
| 131 | fGenerationID = 0; |
| 132 | } |
| 133 | |
reed@google.com | 889b09e | 2012-07-27 21:10:42 +0000 | [diff] [blame] | 134 | private: |
reed@google.com | 97af1a6 | 2012-08-28 12:19:02 +0000 | [diff] [blame] | 135 | const int fWidth; |
| 136 | const int fHeight; |
| 137 | uint32_t fGenerationID; |
skia.committer@gmail.com | a27096b | 2012-08-30 14:38:00 +0000 | [diff] [blame] | 138 | |
reed@google.com | 7edfb49 | 2012-08-28 12:48:35 +0000 | [diff] [blame] | 139 | typedef SkRefCnt INHERITED; |
reed@google.com | 889b09e | 2012-07-27 21:10:42 +0000 | [diff] [blame] | 140 | }; |
| 141 | |
| 142 | #endif |