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.
5 #include "pdf/progress_control.h"
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"
14 namespace chrome_pdf
{
16 const double ProgressControl::kCompleted
= 100.0;
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;
31 int ScaleInt(int val
, float scale
) {
32 return static_cast<int>(val
* scale
);
35 ProgressControl::ProgressControl()
40 ProgressControl::~ProgressControl() {
43 bool ProgressControl::CreateProgressControl(
46 Control::Owner
* delegate
,
49 const std::vector
<pp::ImageData
>& images
,
50 const pp::ImageData
& background
,
51 const std::string
& text
) {
54 bool res
= Control::Create(id
, pp::Rect(), visible
, delegate
);
56 Reconfigure(background
, images
, device_scale
);
60 void ProgressControl::Reconfigure(const pp::ImageData
& background
,
61 const std::vector
<pp::ImageData
>& images
,
63 DCHECK(images
.size() != 0);
65 background_
= background
;
66 device_scale_
= device_scale
;
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);
76 void ProgressControl::CalculateLayout(pp::Instance
* instance
,
77 const std::vector
<pp::ImageData
>& images
,
78 const pp::ImageData
& background
,
79 const std::string
& text
,
84 DCHECK(images
.size() != 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());
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
);
99 pp::FontDescription_Dev desc
;
100 PP_FontMetrics_Dev metrics
;
101 font
.Describe(&desc
, &metrics
);
102 int text_height
= metrics
.height
;
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
));
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());
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());
121 *image_rc
= pp::Rect(ScaleInt(kLeftPadding
, device_scale
) + offset_x
,
122 ScaleInt(kTopPadding
, device_scale
) + offset_y
,
127 ctrl_size
->width() - text_length
-
128 ScaleInt(kRightPadding
, device_scale
) - offset_x
,
129 (ctrl_size
->height() - text_height
) / 2,
134 size_t ProgressControl::GetImageIngex() const {
135 return static_cast<size_t>((progress_
/ 100.0) * images_
.size());
138 void ProgressControl::Paint(pp::ImageData
* image_data
, const pp::Rect
& rc
) {
142 pp::Rect draw_rc
= rect().Intersect(rc
);
143 if (draw_rc
.IsEmpty())
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);
151 size_t index
= GetImageIngex();
152 if (index
>= images_
.size())
153 index
= images_
.size() - 1;
155 AlphaBlend(images_
[index
],
156 pp::Rect(images_
[index
].size()),
161 pp::Rect
image_draw_rc(draw_rc
);
162 image_draw_rc
.Offset(-rect().x(), -rect().y());
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
);
178 if (visible() && old_index
!= new_index
)
179 owner()->Invalidate(id(), rect());
182 void ProgressControl::PrepareBackground() {
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
);
191 pp::FontDescription_Dev desc
;
192 PP_FontMetrics_Dev metrics
;
193 font
.Describe(&desc
, &metrics
);
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);
201 void ProgressControl::AdjustBackground() {
202 ctrl_background_
= pp::ImageData(owner()->GetInstance(),
203 PP_IMAGEDATAFORMAT_BGRA_PREMUL
,
207 if (rect().size() == background_
.size()) {
208 CopyImage(background_
, pp::Rect(background_
.size()),
209 &ctrl_background_
, pp::Rect(ctrl_background_
.size()), false);
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.
224 int slice_x
= background_
.size().width() / 3;
225 int slice_y
= background_
.size().height() / 3;
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);
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);
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);
245 CopyImage(background_
, src_rc
, &ctrl_background_
, dest_rc
, false);
249 slice_x
, 0, background_
.size().width() - 2 * slice_x
, slice_y
);
251 slice_x
, 0, ctrl_background_
.size().width() - 2 * slice_x
, slice_y
);
252 CopyImage(background_
, src_rc
, &ctrl_background_
, dest_rc
, true);
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);
261 0, slice_y
, slice_x
, background_
.size().height() - 2 * slice_y
);
263 0, slice_y
, slice_x
, ctrl_background_
.size().height() - 2 * slice_y
);
264 CopyImage(background_
, src_rc
, &ctrl_background_
, dest_rc
, true);
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);
272 src_rc
= pp::Rect(slice_x
,
274 background_
.size().width() - 2 * slice_x
,
275 background_
.size().height() - 2 * slice_y
);
276 dest_rc
= pp::Rect(slice_x
,
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);
283 } // namespace chrome_pdf