Merge XFA to PDFium master at 4dc95e7 on 10/28/2014
[pdfium.git] / xfa_test / pdf / paint_manager.h
1 // Copyright (c) 2010 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #ifndef PDF_PAINT_MANAGER_H_
6 #define PDF_PAINT_MANAGER_H_
7
8 #include <vector>
9
10 #include "pdf/paint_aggregator.h"
11 #include "ppapi/cpp/graphics_2d.h"
12 #include "ppapi/utility/completion_callback_factory.h"
13
14 namespace pp {
15 class Graphics2D;
16 class Instance;
17 class Point;
18 class Rect;
19 };
20
21 // Custom PaintManager for the PDF plugin.  This is branched from the Pepper
22 // version.  The difference is that this supports progressive rendering of dirty
23 // rects, where multiple calls to the rendering engine are needed.  It also
24 // supports having higher-priority rects flushing right away, i.e. the
25 // scrollbars.
26 //
27 // The client's OnPaint
28 class PaintManager {
29  public:
30   // Like PaintAggregator's version, but allows the plugin to tell us whether
31   // it should be flushed to the screen immediately or when the rest of the
32   // plugin viewport is ready.
33   struct ReadyRect {
34     pp::Point offset;
35     pp::Rect rect;
36     pp::ImageData image_data;
37     bool flush_now;
38
39     ReadyRect(const pp::Rect& r, const pp::ImageData& i, bool f)
40         : rect(r), image_data(i), flush_now(f) {}
41
42     operator PaintAggregator::ReadyRect() const {
43       PaintAggregator::ReadyRect rv;
44       rv.offset = offset;
45       rv.rect = rect;
46       rv.image_data = image_data;
47       return rv;
48     }
49   };
50   class Client {
51    public:
52     // Paints the given invalid area of the plugin to the given graphics
53     // device. Returns true if anything was painted.
54     //
55     // You are given the list of rects to paint in |paint_rects|.  You can
56     // combine painting into less rectangles if it's more efficient.  When a
57     // rect is painted, information about that paint should be inserted into
58     // |ready|.  Otherwise if a paint needs more work, add the rect to
59     // |pending|.  If |pending| is not empty, your OnPaint function will get
60     // called again.  Once OnPaint is called and it returns no pending rects,
61     // all the previously ready rects will be flushed on screen.  The exception
62     // is for ready rects that have |flush_now| set to true.  These will be
63     // flushed right away.
64     //
65     // Do not call Flush() on the graphics device, this will be done
66     // automatically if you return true from this function since the
67     // PaintManager needs to handle the callback.
68     //
69     // Calling Invalidate/Scroll is not allowed while inside an OnPaint
70     virtual void OnPaint(const std::vector<pp::Rect>& paint_rects,
71                          std::vector<ReadyRect>* ready,
72                          std::vector<pp::Rect>* pending) = 0;
73    protected:
74     // You shouldn't be doing deleting through this interface.
75     virtual ~Client() {}
76   };
77
78   // The instance is the plugin instance using this paint manager to do its
79   // painting. Painting will automatically go to this instance and you don't
80   // have to manually bind any device context (this is all handled by the
81   // paint manager).
82   //
83   // The Client is a non-owning pointer and must remain valid (normally the
84   // object implementing the Client interface will own the paint manager).
85   //
86   // The is_always_opaque flag will be passed to the device contexts that this
87   // class creates. Set this to true if your plugin always draws an opaque
88   // image to the device. This is used as a hint to the browser that it does
89   // not need to do alpha blending, which speeds up painting. If you generate
90   // non-opqaue pixels or aren't sure, set this to false for more general
91   // blending.
92   //
93   // If you set is_always_opaque, your alpha channel should always be set to
94   // 0xFF or there may be painting artifacts. Being opaque will allow the
95   // browser to do a memcpy rather than a blend to paint the plugin, and this
96   // means your alpha values will get set on the page backing store. If these
97   // values are incorrect, it could mess up future blending. If you aren't
98   // sure, it is always correct to specify that it it not opaque.
99   //
100   // You will need to call SetSize before this class will do anything. Normally
101   // you do this from the ViewChanged method of your plugin instance.
102   PaintManager(pp::Instance* instance, Client* client, bool is_always_opaque);
103
104   ~PaintManager();
105
106   // Returns the size of the graphics context to allocate for a given plugin
107   // size. We may allocated a slightly larger buffer than required so that we
108   // don't have to resize the context when scrollbars appear/dissapear due to
109   // zooming (which can result in flickering).
110   static pp::Size GetNewContextSize(const pp::Size& current_context_size,
111                                     const pp::Size& plugin_size);
112
113   // You must call this function before using if you use the 0-arg constructor.
114   // See the constructor for what these arguments mean.
115   void Initialize(pp::Instance* instance, Client* client,
116                   bool is_always_opaque);
117
118   // Sets the size of the plugin. If the size is the same as the previous call,
119   // this will be a NOP. If the size has changed, a new device will be
120   // allocated to the given size and a paint to that device will be scheduled.
121   //
122   // This is intended to be called from ViewChanged with the size of the
123   // plugin. Since it tracks the old size and only allocates when the size
124   // changes, you can always call this function without worrying about whether
125   // the size changed or ViewChanged is called for another reason (like the
126   // position changed).
127   void SetSize(const pp::Size& new_size, float new_device_scale);
128
129   // Invalidate the entire plugin.
130   void Invalidate();
131
132   // Invalidate the given rect.
133   void InvalidateRect(const pp::Rect& rect);
134
135   // The given rect should be scrolled by the given amounts.
136   void ScrollRect(const pp::Rect& clip_rect, const pp::Point& amount);
137
138   // Returns the size of the graphics context for the next paint operation.
139   // This is the pending size if a resize is pending (the plugin has called
140   // SetSize but we haven't actually painted it yet), or the current size of
141   // no resize is pending.
142   pp::Size GetEffectiveSize() const;
143   float GetEffectiveDeviceScale() const;
144
145  private:
146   // Disallow copy and assign (these are unimplemented).
147   PaintManager(const PaintManager&);
148   PaintManager& operator=(const PaintManager&);
149
150   // Makes sure there is a callback that will trigger a paint at a later time.
151   // This will be either a Flush callback telling us we're allowed to generate
152   // more data, or, if there's no flush callback pending, a manual call back
153   // to the message loop via ExecuteOnMainThread.
154   void EnsureCallbackPending();
155
156   // Does the client paint and executes a Flush if necessary.
157   void DoPaint();
158
159   // Callback for asynchronous completion of Flush.
160   void OnFlushComplete(int32_t);
161
162   // Callback for manual scheduling of paints when there is no flush callback
163   // pending.
164   void OnManualCallbackComplete(int32_t);
165
166   pp::Instance* instance_;
167
168   // Non-owning pointer. See the constructor.
169   Client* client_;
170
171   bool is_always_opaque_;
172
173   pp::CompletionCallbackFactory<PaintManager> callback_factory_;
174
175   // This graphics device will be is_null() if no graphics has been manually
176   // set yet.
177   pp::Graphics2D graphics_;
178
179   PaintAggregator aggregator_;
180
181   // See comment for EnsureCallbackPending for more on how these work.
182   bool manual_callback_pending_;
183   bool flush_pending_;
184
185   // When we get a resize, we don't bind right away (see SetSize). The
186   // has_pending_resize_ tells us that we need to do a resize for the next
187   // paint operation. When true, the new size is in pending_size_.
188   bool has_pending_resize_;
189   bool graphics_need_to_be_bound_;
190   pp::Size pending_size_;
191   pp::Size plugin_size_;
192   float pending_device_scale_;
193   float device_scale_;
194
195   // True iff we're in the middle of a paint.
196   bool in_paint_;
197
198   // True if we haven't painted the plugin viewport yet.
199   bool first_paint_;
200
201   // True when the view size just changed and we're waiting for a paint.
202   bool view_size_changed_waiting_for_paint_;
203 };
204
205 #endif  // PDF_PAINT_MANAGER_H_