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 14namespace pp { 15class Graphics2D; 16class Instance; 17class Point; 18class 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 28class 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_ 206