// Copyright (c) 2011 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #ifndef PPAPI_CPP_GRAPHICS_2D_H_ #define PPAPI_CPP_GRAPHICS_2D_H_ #include "ppapi/c/pp_stdint.h" #include "ppapi/cpp/resource.h" #include "ppapi/cpp/size.h" /// @file /// This file defines the API to create a 2D graphics context in the browser. namespace pp { class CompletionCallback; class ImageData; class Instance; class Point; class Rect; class Graphics2D : public Resource { public: /// Default constructor for creating an is_null() Graphics2D /// object. Graphics2D(); /// The copy constructor for Graphics2D. The underlying 2D context is not /// copied; this constructor creates another reference to the original 2D /// context. /// /// @param[in] other A pointer to a Graphics2D context. Graphics2D(const Graphics2D& other); /// A constructor allocating a new 2D graphics context with the given size /// in the browser, resulting object will be is_null() if the allocation /// failed. /// /// @param[in] instance The module instance. /// @param[in] size The size of the 2D graphics context in the browser, /// measured in device pixels. /// @param[in] is_always_opaque Set the is_always_opaque flag /// to true if you know that you will be painting only opaque data to this /// context. This option will disable blending when compositing the module /// with the web page, which might give higher performance on some computers. /// /// If you set is_always_opaque, your alpha channel should /// always be set to 0xFF or there may be painting artifacts. The alpha values /// overwrite the destination alpha values without blending when /// is_always_opaque is true. Graphics2D(Instance* instance, const Size& size, bool is_always_opaque); /// A destructor that decrements the reference count of a /// Graphics2D object made using the previous copy constructor. /// It is possible that the destructor does not toally destroy the underlying /// 2D context if there are outstanding references to it. virtual ~Graphics2D(); /// This function assigns one 2D graphics context to this 2D graphics /// context. This function increases the reference count of the 2D resource /// of the other 2D graphics context while decrementing the reference counter /// of this 2D graphics context. /// /// @param[in] other An other 2D graphics context. /// /// @return A new Graphics2D context. Graphics2D& operator=(const Graphics2D& other); /// Getter function for returning size of the 2D graphics context. /// /// @return The size of the 2D graphics context measured in device pixels. const Size& size() const { return size_; } /// PaintImageData() enqueues a paint command of the given image into /// the context. This command has no effect until you call Flush(). As a /// result, what counts is the contents of the bitmap when you call Flush, /// not when you call this function. /// /// The provided image will be placed at top_left from the top /// left of the context's internal backing store. This version of /// PaintImageData paints the entire image. Refer to the other version of /// this function to paint only part of the area. /// /// The painted area of the source bitmap must fall entirely within the /// context. Attempting to paint outside of the context will result in an /// error. /// /// There are two methods most modules will use for painting. The first /// method is to generate a new ImageData and then paint it. /// In this case, you'll set the location of your painting to /// top_left and set src_rect to NULL. /// The second is that you're generating small invalid regions out of a larger /// bitmap representing your entire module's image. /// /// @param[in] image The ImageData to be painted. /// @param[in] top_left A Point representing the /// top_left location where the ImageData will be /// painted. void PaintImageData(const ImageData& image, const Point& top_left); /// PaintImageData() enqueues a paint command of the given image into /// the context. This command has no effect until you call Flush(). As a /// result, what counts is the contents of the bitmap when you call Flush(), /// not when you call this function. /// /// The provided image will be placed at top_left from the top /// left of the context's internal backing store. Then the pixels contained /// in src_rect will be copied into the backing store. This /// means that the rectangle being painted will be at src_rect /// offset by top_left. /// /// The src_rect is specified in the coordinate system of the /// image being painted, not the context. For the common case of copying the /// entire image, you may specify an empty src_rect. /// /// The painted area of the source bitmap must fall entirely within the /// context. Attempting to paint outside of the context will result in an /// error. However, the source bitmap may fall outside the context, as long /// as the src_rect subset of it falls entirely within the /// context. /// /// There are two methods most modules will use for painting. The first /// method is to generate a new ImageData and then paint it. In /// this case, you'll set the location of your painting to /// top_left and set src_rect to NULL. /// The second is that you're generating small invalid regions out of a larger /// bitmap representing your entire module. In this case, you would set the /// location of your image to (0,0) and then set src_rect to the /// pixels you changed. /// /// @param[in] image The ImageData to be painted. /// @param[in] top_left A Point representing the /// top_left location where the ImageData will be /// painted. /// @param[in] src_rect The rectangular area where the ImageData /// will be painted. void PaintImageData(const ImageData& image, const Point& top_left, const Rect& src_rect); /// Scroll() enqueues a scroll of the context's backing store. This /// function has no effect until you call Flush(). The data within the /// provided clipping rectangle will be shifted by (dx, dy) pixels. /// /// This function will result in some exposed region which will have /// undefined contents. The module should call PaintImageData() on /// these exposed regions to give the correct contents. /// /// The scroll can be larger than the area of the clipping rectangle, which /// means the current image will be scrolled out of the rectangle. This /// scenario is not an error but will result in a no-op. /// /// @param[in] clip The clipping rectangle. /// @param[in] amount The amount the area in the clipping rectangle will /// shifted. void Scroll(const Rect& clip, const Point& amount); /// ReplaceContents() provides a slightly more efficient way to paint the /// entire module's image. Normally, calling PaintImageData() requires that /// the browser copy the pixels out of the image and into the graphics /// context's backing store. This function replaces the graphics context's /// backing store with the given image, avoiding the copy. /// /// The new image must be the exact same size as this graphics context. If /// the new image uses a different image format than the browser's native /// bitmap format (use ImageData::GetNativeImageDataFormat() to retrieve the /// format), then a conversion will be done inside the browser which may slow /// the performance a little bit. /// /// Note: The new image will not be painted until you call /// Flush(). /// /// After this call, you should take care to release your references to the /// image. If you paint to the image after ReplaceContents(), there is the /// possibility of significant painting artifacts because the page might use /// partially-rendered data when copying out of the backing store. /// /// In the case of an animation, you will want to allocate a new image for /// the next frame. It is best if you wait until the flush callback has /// executed before allocating this bitmap. This gives the browser the option /// of caching the previous backing store and handing it back to you /// (assuming the sizes match). In the optimal case, this means no bitmaps are /// allocated during the animation, and the backing store and "front buffer" /// (which the module is painting into) are just being swapped back and forth. /// /// @param[in] image The ImageData to be painted. void ReplaceContents(ImageData* image); /// Flush() flushes any enqueued paint, scroll, and replace commands /// to the backing store. This actually executes the updates, and causes a /// repaint of the webpage, assuming this graphics context is bound to a /// module instance. /// /// Flush() runs in asynchronous mode. Specify a callback function and /// the argument for that callback function. The callback function will be /// executed on the calling thread when the image has been painted to the /// screen. While you are waiting for a Flush callback, /// additional calls to Flush() will fail. /// /// Because the callback is executed (or thread unblocked) only when the /// module's image is actually on the screen, this function provides /// a way to rate limit animations. By waiting until the image is on the /// screen before painting the next frame, you can ensure you're not /// flushing 2D graphics faster than the screen can be updated. /// /// Unbound contexts /// If the context is not bound to a module instance, you will /// still get a callback. The callback will execute after Flush() returns /// to avoid reentrancy. The callback will not wait until anything is /// painted to the screen because there will be nothing on the screen. The /// timing of this callback is not guaranteed and may be deprioritized by /// the browser because it is not affecting the user experience. /// /// Off-screen instances /// If the context is bound to an instance that is /// currently not visible (for example, scrolled out of view) it will /// behave like the "unbound context" case. /// /// Detaching a context /// If you detach a context from a module instance, any /// pending flush callbacks will be converted into the "unbound context" /// case. /// /// Released contexts /// A callback may or may not still get called even if you have released all /// of your references to the context. This can occur if there are internal /// references to the context that means it has not been internally /// destroyed (for example, if it is still bound to an instance) or due to /// other implementation details. As a result, you should be careful to /// check that flush callbacks are for the context you expect and that /// you're capable of handling callbacks for context that you may have /// released your reference to. /// /// Shutdown /// If a module instance is removed when a Flush is pending, the /// callback will not be executed. /// /// @param[in] cc A CompletionCallback to be called when the /// image has been painted on the screen. /// /// @return Returns PP_OK on success or /// PP_Error_BadResource if the graphics context is invalid, /// PP_Error_BadArgument if the callback is null and /// flush is being called from the main thread of the module, or /// PP_Error_InProgress if a flush is already pending that has /// not issued its callback yet. In the failure case, nothing will be /// updated and no callback will be scheduled. // TODO(darin): We should ensure that the completion callback always runs, so // that it is easier for consumers to manage memory referenced by a callback. // TODO(): Add back in the synchronous mode description once we have support // for it. int32_t Flush(const CompletionCallback& cc); private: Size size_; }; } // namespace pp #endif // PPAPI_CPP_GRAPHICS_2D_H_