| 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 |