diff options
author | Bo Xu <bo_xu@foxitsoftware.com> | 2014-10-28 23:03:33 -0700 |
---|---|---|
committer | Bo Xu <bo_xu@foxitsoftware.com> | 2014-11-03 11:10:11 -0800 |
commit | fdc00a7042d912aafaabddae4d9c84199921ef23 (patch) | |
tree | 32ab8ac91cc68d2cd15b9168782a71b3f3f5e7b9 /xfa_test/pdf/paint_manager.h | |
parent | e9b38fa38de2c95d8260be31c57d9272c4d127ed (diff) | |
download | pdfium-fdc00a7042d912aafaabddae4d9c84199921ef23.tar.xz |
Merge XFA to PDFium master at 4dc95e7 on 10/28/2014
Diffstat (limited to 'xfa_test/pdf/paint_manager.h')
-rw-r--r-- | xfa_test/pdf/paint_manager.h | 205 |
1 files changed, 205 insertions, 0 deletions
diff --git a/xfa_test/pdf/paint_manager.h b/xfa_test/pdf/paint_manager.h new file mode 100644 index 0000000000..7755eb6829 --- /dev/null +++ b/xfa_test/pdf/paint_manager.h @@ -0,0 +1,205 @@ +// Copyright (c) 2010 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 PDF_PAINT_MANAGER_H_ +#define PDF_PAINT_MANAGER_H_ + +#include <vector> + +#include "pdf/paint_aggregator.h" +#include "ppapi/cpp/graphics_2d.h" +#include "ppapi/utility/completion_callback_factory.h" + +namespace pp { +class Graphics2D; +class Instance; +class Point; +class Rect; +}; + +// Custom PaintManager for the PDF plugin. This is branched from the Pepper +// version. The difference is that this supports progressive rendering of dirty +// rects, where multiple calls to the rendering engine are needed. It also +// supports having higher-priority rects flushing right away, i.e. the +// scrollbars. +// +// The client's OnPaint +class PaintManager { + public: + // Like PaintAggregator's version, but allows the plugin to tell us whether + // it should be flushed to the screen immediately or when the rest of the + // plugin viewport is ready. + struct ReadyRect { + pp::Point offset; + pp::Rect rect; + pp::ImageData image_data; + bool flush_now; + + ReadyRect(const pp::Rect& r, const pp::ImageData& i, bool f) + : rect(r), image_data(i), flush_now(f) {} + + operator PaintAggregator::ReadyRect() const { + PaintAggregator::ReadyRect rv; + rv.offset = offset; + rv.rect = rect; + rv.image_data = image_data; + return rv; + } + }; + class Client { + public: + // Paints the given invalid area of the plugin to the given graphics + // device. Returns true if anything was painted. + // + // You are given the list of rects to paint in |paint_rects|. You can + // combine painting into less rectangles if it's more efficient. When a + // rect is painted, information about that paint should be inserted into + // |ready|. Otherwise if a paint needs more work, add the rect to + // |pending|. If |pending| is not empty, your OnPaint function will get + // called again. Once OnPaint is called and it returns no pending rects, + // all the previously ready rects will be flushed on screen. The exception + // is for ready rects that have |flush_now| set to true. These will be + // flushed right away. + // + // Do not call Flush() on the graphics device, this will be done + // automatically if you return true from this function since the + // PaintManager needs to handle the callback. + // + // Calling Invalidate/Scroll is not allowed while inside an OnPaint + virtual void OnPaint(const std::vector<pp::Rect>& paint_rects, + std::vector<ReadyRect>* ready, + std::vector<pp::Rect>* pending) = 0; + protected: + // You shouldn't be doing deleting through this interface. + virtual ~Client() {} + }; + + // The instance is the plugin instance using this paint manager to do its + // painting. Painting will automatically go to this instance and you don't + // have to manually bind any device context (this is all handled by the + // paint manager). + // + // The Client is a non-owning pointer and must remain valid (normally the + // object implementing the Client interface will own the paint manager). + // + // The is_always_opaque flag will be passed to the device contexts that this + // class creates. Set this to true if your plugin always draws an opaque + // image to the device. This is used as a hint to the browser that it does + // not need to do alpha blending, which speeds up painting. If you generate + // non-opqaue pixels or aren't sure, set this to false for more general + // blending. + // + // If you set is_always_opaque, your alpha channel should always be set to + // 0xFF or there may be painting artifacts. Being opaque will allow the + // browser to do a memcpy rather than a blend to paint the plugin, and this + // means your alpha values will get set on the page backing store. If these + // values are incorrect, it could mess up future blending. If you aren't + // sure, it is always correct to specify that it it not opaque. + // + // You will need to call SetSize before this class will do anything. Normally + // you do this from the ViewChanged method of your plugin instance. + PaintManager(pp::Instance* instance, Client* client, bool is_always_opaque); + + ~PaintManager(); + + // Returns the size of the graphics context to allocate for a given plugin + // size. We may allocated a slightly larger buffer than required so that we + // don't have to resize the context when scrollbars appear/dissapear due to + // zooming (which can result in flickering). + static pp::Size GetNewContextSize(const pp::Size& current_context_size, + const pp::Size& plugin_size); + + // You must call this function before using if you use the 0-arg constructor. + // See the constructor for what these arguments mean. + void Initialize(pp::Instance* instance, Client* client, + bool is_always_opaque); + + // Sets the size of the plugin. If the size is the same as the previous call, + // this will be a NOP. If the size has changed, a new device will be + // allocated to the given size and a paint to that device will be scheduled. + // + // This is intended to be called from ViewChanged with the size of the + // plugin. Since it tracks the old size and only allocates when the size + // changes, you can always call this function without worrying about whether + // the size changed or ViewChanged is called for another reason (like the + // position changed). + void SetSize(const pp::Size& new_size, float new_device_scale); + + // Invalidate the entire plugin. + void Invalidate(); + + // Invalidate the given rect. + void InvalidateRect(const pp::Rect& rect); + + // The given rect should be scrolled by the given amounts. + void ScrollRect(const pp::Rect& clip_rect, const pp::Point& amount); + + // Returns the size of the graphics context for the next paint operation. + // This is the pending size if a resize is pending (the plugin has called + // SetSize but we haven't actually painted it yet), or the current size of + // no resize is pending. + pp::Size GetEffectiveSize() const; + float GetEffectiveDeviceScale() const; + + private: + // Disallow copy and assign (these are unimplemented). + PaintManager(const PaintManager&); + PaintManager& operator=(const PaintManager&); + + // Makes sure there is a callback that will trigger a paint at a later time. + // This will be either a Flush callback telling us we're allowed to generate + // more data, or, if there's no flush callback pending, a manual call back + // to the message loop via ExecuteOnMainThread. + void EnsureCallbackPending(); + + // Does the client paint and executes a Flush if necessary. + void DoPaint(); + + // Callback for asynchronous completion of Flush. + void OnFlushComplete(int32_t); + + // Callback for manual scheduling of paints when there is no flush callback + // pending. + void OnManualCallbackComplete(int32_t); + + pp::Instance* instance_; + + // Non-owning pointer. See the constructor. + Client* client_; + + bool is_always_opaque_; + + pp::CompletionCallbackFactory<PaintManager> callback_factory_; + + // This graphics device will be is_null() if no graphics has been manually + // set yet. + pp::Graphics2D graphics_; + + PaintAggregator aggregator_; + + // See comment for EnsureCallbackPending for more on how these work. + bool manual_callback_pending_; + bool flush_pending_; + + // When we get a resize, we don't bind right away (see SetSize). The + // has_pending_resize_ tells us that we need to do a resize for the next + // paint operation. When true, the new size is in pending_size_. + bool has_pending_resize_; + bool graphics_need_to_be_bound_; + pp::Size pending_size_; + pp::Size plugin_size_; + float pending_device_scale_; + float device_scale_; + + // True iff we're in the middle of a paint. + bool in_paint_; + + // True if we haven't painted the plugin viewport yet. + bool first_paint_; + + // True when the view size just changed and we're waiting for a paint. + bool view_size_changed_waiting_for_paint_; +}; + +#endif // PDF_PAINT_MANAGER_H_ |