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 |