michael@0: /* michael@0: * Copyright 2012 Google Inc. michael@0: * michael@0: * Use of this source code is governed by a BSD-style license that can be michael@0: * found in the LICENSE file. michael@0: */ michael@0: michael@0: #ifndef SkSurface_DEFINED michael@0: #define SkSurface_DEFINED michael@0: michael@0: #include "SkRefCnt.h" michael@0: #include "SkImage.h" michael@0: michael@0: class SkCanvas; michael@0: class SkPaint; michael@0: class GrContext; michael@0: class GrRenderTarget; michael@0: michael@0: /** michael@0: * SkSurface represents the backend/results of drawing to a canvas. For raster michael@0: * drawing, the surface will be pixels, but (for example) when drawing into michael@0: * a PDF or Picture canvas, the surface stores the recorded commands. michael@0: * michael@0: * To draw into a canvas, first create the appropriate type of Surface, and michael@0: * then request the canvas from the surface. michael@0: */ michael@0: class SK_API SkSurface : public SkRefCnt { michael@0: public: michael@0: SK_DECLARE_INST_COUNT(SkSurface) michael@0: michael@0: /** michael@0: * Create a new surface, using the specified pixels/rowbytes as its michael@0: * backend. michael@0: * michael@0: * If the requested surface cannot be created, or the request is not a michael@0: * supported configuration, NULL will be returned. michael@0: */ michael@0: static SkSurface* NewRasterDirect(const SkImageInfo&, void* pixels, size_t rowBytes); michael@0: michael@0: /** michael@0: * Return a new surface, with the memory for the pixels automatically michael@0: * allocated. michael@0: * michael@0: * If the requested surface cannot be created, or the request is not a michael@0: * supported configuration, NULL will be returned. michael@0: */ michael@0: static SkSurface* NewRaster(const SkImageInfo&); michael@0: michael@0: /** michael@0: * Helper version of NewRaster. It creates a SkImageInfo with the michael@0: * specified width and height, and populates the rest of info to match michael@0: * pixels in SkPMColor format. michael@0: */ michael@0: static SkSurface* NewRasterPMColor(int width, int height) { michael@0: return NewRaster(SkImageInfo::MakeN32Premul(width, height)); michael@0: } michael@0: michael@0: /** michael@0: * Return a new surface whose contents will be recorded into a picture. michael@0: * When this surface is drawn into another canvas, its contents will be michael@0: * "replayed" into that canvas. michael@0: */ michael@0: static SkSurface* NewPicture(int width, int height); michael@0: michael@0: /** michael@0: * Return a new surface using the specified render target. michael@0: */ michael@0: static SkSurface* NewRenderTargetDirect(GrRenderTarget*); michael@0: michael@0: /** michael@0: * Return a new surface whose contents will be drawn to an offscreen michael@0: * render target, allocated by the surface. michael@0: */ michael@0: static SkSurface* NewRenderTarget(GrContext*, const SkImageInfo&, int sampleCount = 0); michael@0: michael@0: int width() const { return fWidth; } michael@0: int height() const { return fHeight; } michael@0: michael@0: /** michael@0: * Returns a unique non-zero, unique value identifying the content of this michael@0: * surface. Each time the content is changed changed, either by drawing michael@0: * into this surface, or explicitly calling notifyContentChanged()) this michael@0: * method will return a new value. michael@0: * michael@0: * If this surface is empty (i.e. has a zero-dimention), this will return michael@0: * 0. michael@0: */ michael@0: uint32_t generationID(); michael@0: michael@0: /** michael@0: * Modes that can be passed to notifyContentWillChange michael@0: */ michael@0: enum ContentChangeMode { michael@0: /** michael@0: * Use this mode if it is known that the upcoming content changes will michael@0: * clear or overwrite prior contents, thus making them discardable. michael@0: */ michael@0: kDiscard_ContentChangeMode, michael@0: /** michael@0: * Use this mode if prior surface contents need to be preserved or michael@0: * if in doubt. michael@0: */ michael@0: kRetain_ContentChangeMode, michael@0: }; michael@0: michael@0: /** michael@0: * Call this if the contents are about to change. This will (lazily) force a new michael@0: * value to be returned from generationID() when it is called next. michael@0: */ michael@0: void notifyContentWillChange(ContentChangeMode mode); michael@0: michael@0: /** michael@0: * Return a canvas that will draw into this surface. This will always michael@0: * return the same canvas for a given surface, and is manged/owned by the michael@0: * surface. It should not be used when its parent surface has gone out of michael@0: * scope. michael@0: */ michael@0: SkCanvas* getCanvas(); michael@0: michael@0: /** michael@0: * Return a new surface that is "compatible" with this one, in that it will michael@0: * efficiently be able to be drawn into this surface. Typical calling michael@0: * pattern: michael@0: * michael@0: * SkSurface* A = SkSurface::New...(); michael@0: * SkCanvas* canvasA = surfaceA->newCanvas(); michael@0: * ... michael@0: * SkSurface* surfaceB = surfaceA->newSurface(...); michael@0: * SkCanvas* canvasB = surfaceB->newCanvas(); michael@0: * ... // draw using canvasB michael@0: * canvasA->drawSurface(surfaceB); // <--- this will always be optimal! michael@0: */ michael@0: SkSurface* newSurface(const SkImageInfo&); michael@0: michael@0: /** michael@0: * Returns an image of the current state of the surface pixels up to this michael@0: * point. Subsequent changes to the surface (by drawing into its canvas) michael@0: * will not be reflected in this image. michael@0: */ michael@0: SkImage* newImageSnapshot(); michael@0: michael@0: /** michael@0: * Thought the caller could get a snapshot image explicitly, and draw that, michael@0: * it seems that directly drawing a surface into another canvas might be michael@0: * a common pattern, and that we could possibly be more efficient, since michael@0: * we'd know that the "snapshot" need only live until we've handed it off michael@0: * to the canvas. michael@0: */ michael@0: void draw(SkCanvas*, SkScalar x, SkScalar y, const SkPaint*); michael@0: michael@0: /** michael@0: * If the surface has direct access to its pixels (i.e. they are in local michael@0: * RAM) return the const-address of those pixels, and if not null, return michael@0: * the ImageInfo and rowBytes. The returned address is only valid while michael@0: * the surface object is in scope, and no API call is made on the surface michael@0: * or its canvas. michael@0: * michael@0: * On failure, returns NULL and the info and rowBytes parameters are michael@0: * ignored. michael@0: */ michael@0: const void* peekPixels(SkImageInfo* info, size_t* rowBytes); michael@0: michael@0: protected: michael@0: SkSurface(int width, int height); michael@0: SkSurface(const SkImageInfo&); michael@0: michael@0: // called by subclass if their contents have changed michael@0: void dirtyGenerationID() { michael@0: fGenerationID = 0; michael@0: } michael@0: michael@0: private: michael@0: const int fWidth; michael@0: const int fHeight; michael@0: uint32_t fGenerationID; michael@0: michael@0: typedef SkRefCnt INHERITED; michael@0: }; michael@0: michael@0: #endif