OLD | NEW |
| (Empty) |
1 // Copyright (c) 2011 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 #include "pdf/progress_control.h" | |
6 | |
7 #include <algorithm> | |
8 | |
9 #include "base/logging.h" | |
10 #include "pdf/draw_utils.h" | |
11 #include "pdf/resource_consts.h" | |
12 #include "ppapi/cpp/dev/font_dev.h" | |
13 | |
14 namespace chrome_pdf { | |
15 | |
16 const double ProgressControl::kCompleted = 100.0; | |
17 | |
18 // There is a bug outputting text with alpha 0xFF (opaque) to an intermediate | |
19 // image. It outputs alpha channgel of the text pixels to 0xFF (transparent). | |
20 // And it breaks next alpha blending. | |
21 // For now, let's use alpha 0xFE to work around this bug. | |
22 // TODO(gene): investigate this bug. | |
23 const uint32 kProgressTextColor = 0xFEDDE6FC; | |
24 const uint32 kProgressTextSize = 16; | |
25 const uint32 kImageTextSpacing = 8; | |
26 const uint32 kTopPadding = 8; | |
27 const uint32 kBottomPadding = 12; | |
28 const uint32 kLeftPadding = 10; | |
29 const uint32 kRightPadding = 10; | |
30 | |
31 int ScaleInt(int val, float scale) { | |
32 return static_cast<int>(val * scale); | |
33 } | |
34 | |
35 ProgressControl::ProgressControl() | |
36 : progress_(0.0), | |
37 device_scale_(1.0) { | |
38 } | |
39 | |
40 ProgressControl::~ProgressControl() { | |
41 } | |
42 | |
43 bool ProgressControl::CreateProgressControl( | |
44 uint32 id, | |
45 bool visible, | |
46 Control::Owner* delegate, | |
47 double progress, | |
48 float device_scale, | |
49 const std::vector<pp::ImageData>& images, | |
50 const pp::ImageData& background, | |
51 const std::string& text) { | |
52 progress_ = progress; | |
53 text_ = text; | |
54 bool res = Control::Create(id, pp::Rect(), visible, delegate); | |
55 if (res) | |
56 Reconfigure(background, images, device_scale); | |
57 return res; | |
58 } | |
59 | |
60 void ProgressControl::Reconfigure(const pp::ImageData& background, | |
61 const std::vector<pp::ImageData>& images, | |
62 float device_scale) { | |
63 DCHECK(images.size() != 0); | |
64 images_ = images; | |
65 background_ = background; | |
66 device_scale_ = device_scale; | |
67 pp::Size ctrl_size; | |
68 CalculateLayout(owner()->GetInstance(), images_, background_, text_, | |
69 device_scale_, &ctrl_size, &image_rc_, &text_rc_); | |
70 pp::Rect rc(pp::Point(), ctrl_size); | |
71 Control::SetRect(rc, false); | |
72 PrepareBackground(); | |
73 } | |
74 | |
75 // static | |
76 void ProgressControl::CalculateLayout(pp::Instance* instance, | |
77 const std::vector<pp::ImageData>& images, | |
78 const pp::ImageData& background, | |
79 const std::string& text, | |
80 float device_scale, | |
81 pp::Size* ctrl_size, | |
82 pp::Rect* image_rc, | |
83 pp::Rect* text_rc) { | |
84 DCHECK(images.size() != 0); | |
85 int image_width = 0; | |
86 int image_height = 0; | |
87 for (size_t i = 0; i < images.size(); i++) { | |
88 image_width = std::max(image_width, images[i].size().width()); | |
89 image_height = std::max(image_height, images[i].size().height()); | |
90 } | |
91 | |
92 pp::FontDescription_Dev description; | |
93 description.set_family(PP_FONTFAMILY_SANSSERIF); | |
94 description.set_size(ScaleInt(kProgressTextSize, device_scale)); | |
95 description.set_weight(PP_FONTWEIGHT_BOLD); | |
96 pp::Font_Dev font(instance, description); | |
97 int text_length = font.MeasureSimpleText(text); | |
98 | |
99 pp::FontDescription_Dev desc; | |
100 PP_FontMetrics_Dev metrics; | |
101 font.Describe(&desc, &metrics); | |
102 int text_height = metrics.height; | |
103 | |
104 *ctrl_size = pp::Size( | |
105 image_width + text_length + | |
106 ScaleInt(kImageTextSpacing + kLeftPadding + kRightPadding, device_scale), | |
107 std::max(image_height, text_height) + | |
108 ScaleInt(kTopPadding + kBottomPadding, device_scale)); | |
109 | |
110 int offset_x = 0; | |
111 int offset_y = 0; | |
112 if (ctrl_size->width() < background.size().width()) { | |
113 offset_x += (background.size().width() - ctrl_size->width()) / 2; | |
114 ctrl_size->set_width(background.size().width()); | |
115 } | |
116 if (ctrl_size->height() < background.size().height()) { | |
117 offset_y += (background.size().height() - ctrl_size->height()) / 2; | |
118 ctrl_size->set_height(background.size().height()); | |
119 } | |
120 | |
121 *image_rc = pp::Rect(ScaleInt(kLeftPadding, device_scale) + offset_x, | |
122 ScaleInt(kTopPadding, device_scale) + offset_y, | |
123 image_width, | |
124 image_height); | |
125 | |
126 *text_rc = pp::Rect( | |
127 ctrl_size->width() - text_length - | |
128 ScaleInt(kRightPadding, device_scale) - offset_x, | |
129 (ctrl_size->height() - text_height) / 2, | |
130 text_length, | |
131 text_height); | |
132 } | |
133 | |
134 size_t ProgressControl::GetImageIngex() const { | |
135 return static_cast<size_t>((progress_ / 100.0) * images_.size()); | |
136 } | |
137 | |
138 void ProgressControl::Paint(pp::ImageData* image_data, const pp::Rect& rc) { | |
139 if (!visible()) | |
140 return; | |
141 | |
142 pp::Rect draw_rc = rect().Intersect(rc); | |
143 if (draw_rc.IsEmpty()) | |
144 return; | |
145 | |
146 pp::ImageData buffer(owner()->GetInstance(), ctrl_background_.format(), | |
147 ctrl_background_.size(), false); | |
148 CopyImage(ctrl_background_, pp::Rect(ctrl_background_.size()), | |
149 &buffer, pp::Rect(ctrl_background_.size()), false); | |
150 | |
151 size_t index = GetImageIngex(); | |
152 if (index >= images_.size()) | |
153 index = images_.size() - 1; | |
154 | |
155 AlphaBlend(images_[index], | |
156 pp::Rect(images_[index].size()), | |
157 &buffer, | |
158 image_rc_.point(), | |
159 kOpaqueAlpha); | |
160 | |
161 pp::Rect image_draw_rc(draw_rc); | |
162 image_draw_rc.Offset(-rect().x(), -rect().y()); | |
163 AlphaBlend(buffer, | |
164 image_draw_rc, | |
165 image_data, | |
166 draw_rc.point(), | |
167 transparency()); | |
168 } | |
169 | |
170 void ProgressControl::SetProgress(double progress) { | |
171 size_t old_index = GetImageIngex(); | |
172 progress_ = progress; | |
173 size_t new_index = GetImageIngex(); | |
174 if (progress_ >= kCompleted) { | |
175 progress_ = kCompleted; | |
176 owner()->OnEvent(id(), EVENT_ID_PROGRESS_COMPLETED, NULL); | |
177 } | |
178 if (visible() && old_index != new_index) | |
179 owner()->Invalidate(id(), rect()); | |
180 } | |
181 | |
182 void ProgressControl::PrepareBackground() { | |
183 AdjustBackground(); | |
184 | |
185 pp::FontDescription_Dev description; | |
186 description.set_family(PP_FONTFAMILY_SANSSERIF); | |
187 description.set_size(ScaleInt(kProgressTextSize, device_scale_)); | |
188 description.set_weight(PP_FONTWEIGHT_BOLD); | |
189 pp::Font_Dev font(owner()->GetInstance(), description); | |
190 | |
191 pp::FontDescription_Dev desc; | |
192 PP_FontMetrics_Dev metrics; | |
193 font.Describe(&desc, &metrics); | |
194 | |
195 pp::Point text_origin = pp::Point(text_rc_.x(), | |
196 (text_rc_.y() + text_rc_.bottom() + metrics.x_height) / 2); | |
197 font.DrawTextAt(&ctrl_background_, pp::TextRun_Dev(text_), text_origin, | |
198 kProgressTextColor, pp::Rect(ctrl_background_.size()), false); | |
199 } | |
200 | |
201 void ProgressControl::AdjustBackground() { | |
202 ctrl_background_ = pp::ImageData(owner()->GetInstance(), | |
203 PP_IMAGEDATAFORMAT_BGRA_PREMUL, | |
204 rect().size(), | |
205 false); | |
206 | |
207 if (rect().size() == background_.size()) { | |
208 CopyImage(background_, pp::Rect(background_.size()), | |
209 &ctrl_background_, pp::Rect(ctrl_background_.size()), false); | |
210 return; | |
211 } | |
212 | |
213 // We need to stretch background to new dimentions. To do so, we split | |
214 // background into 9 different parts. We copy corner rects (1,3,7,9) as is, | |
215 // stretch rectangles between corners (2,4,6,8) in 1 dimention, and | |
216 // stretch center rect (5) in 2 dimentions. | |
217 // |---|---|---| | |
218 // | 1 | 2 | 3 | | |
219 // |---|---|---| | |
220 // | 4 | 5 | 6 | | |
221 // |---|---|---| | |
222 // | 7 | 8 | 9 | | |
223 // |---|---|---| | |
224 int slice_x = background_.size().width() / 3; | |
225 int slice_y = background_.size().height() / 3; | |
226 | |
227 // Copy rect 1 | |
228 pp::Rect src_rc(0, 0, slice_x, slice_y); | |
229 pp::Rect dest_rc(0, 0, slice_x, slice_y); | |
230 CopyImage(background_, src_rc, &ctrl_background_, dest_rc, false); | |
231 | |
232 // Copy rect 3 | |
233 src_rc.set_x(background_.size().width() - slice_x); | |
234 dest_rc.set_x(ctrl_background_.size().width() - slice_x); | |
235 CopyImage(background_, src_rc, &ctrl_background_, dest_rc, false); | |
236 | |
237 // Copy rect 9 | |
238 src_rc.set_y(background_.size().height() - slice_y); | |
239 dest_rc.set_y(ctrl_background_.size().height() - slice_y); | |
240 CopyImage(background_, src_rc, &ctrl_background_, dest_rc, false); | |
241 | |
242 // Copy rect 7 | |
243 src_rc.set_x(0); | |
244 dest_rc.set_x(0); | |
245 CopyImage(background_, src_rc, &ctrl_background_, dest_rc, false); | |
246 | |
247 // Stretch rect 2 | |
248 src_rc = pp::Rect( | |
249 slice_x, 0, background_.size().width() - 2 * slice_x, slice_y); | |
250 dest_rc = pp::Rect( | |
251 slice_x, 0, ctrl_background_.size().width() - 2 * slice_x, slice_y); | |
252 CopyImage(background_, src_rc, &ctrl_background_, dest_rc, true); | |
253 | |
254 // Copy rect 8 | |
255 src_rc.set_y(background_.size().height() - slice_y); | |
256 dest_rc.set_y(ctrl_background_.size().height() - slice_y); | |
257 CopyImage(background_, src_rc, &ctrl_background_, dest_rc, true); | |
258 | |
259 // Stretch rect 4 | |
260 src_rc = pp::Rect( | |
261 0, slice_y, slice_x, background_.size().height() - 2 * slice_y); | |
262 dest_rc = pp::Rect( | |
263 0, slice_y, slice_x, ctrl_background_.size().height() - 2 * slice_y); | |
264 CopyImage(background_, src_rc, &ctrl_background_, dest_rc, true); | |
265 | |
266 // Copy rect 6 | |
267 src_rc.set_x(background_.size().width() - slice_x); | |
268 dest_rc.set_x(ctrl_background_.size().width() - slice_x); | |
269 CopyImage(background_, src_rc, &ctrl_background_, dest_rc, true); | |
270 | |
271 // Stretch rect 5 | |
272 src_rc = pp::Rect(slice_x, | |
273 slice_y, | |
274 background_.size().width() - 2 * slice_x, | |
275 background_.size().height() - 2 * slice_y); | |
276 dest_rc = pp::Rect(slice_x, | |
277 slice_y, | |
278 ctrl_background_.size().width() - 2 * slice_x, | |
279 ctrl_background_.size().height() - 2 * slice_y); | |
280 CopyImage(background_, src_rc, &ctrl_background_, dest_rc, true); | |
281 } | |
282 | |
283 } // namespace chrome_pdf | |
OLD | NEW |