summaryrefslogtreecommitdiff
path: root/xfa_test/pdf/progress_control.cc
diff options
context:
space:
mode:
authorBo Xu <bo_xu@foxitsoftware.com>2014-10-28 23:03:33 -0700
committerBo Xu <bo_xu@foxitsoftware.com>2014-11-03 11:10:11 -0800
commitfdc00a7042d912aafaabddae4d9c84199921ef23 (patch)
tree32ab8ac91cc68d2cd15b9168782a71b3f3f5e7b9 /xfa_test/pdf/progress_control.cc
parente9b38fa38de2c95d8260be31c57d9272c4d127ed (diff)
downloadpdfium-fdc00a7042d912aafaabddae4d9c84199921ef23.tar.xz
Merge XFA to PDFium master at 4dc95e7 on 10/28/2014
Diffstat (limited to 'xfa_test/pdf/progress_control.cc')
-rw-r--r--xfa_test/pdf/progress_control.cc283
1 files changed, 283 insertions, 0 deletions
diff --git a/xfa_test/pdf/progress_control.cc b/xfa_test/pdf/progress_control.cc
new file mode 100644
index 0000000000..2c2bca4e42
--- /dev/null
+++ b/xfa_test/pdf/progress_control.cc
@@ -0,0 +1,283 @@
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "pdf/progress_control.h"
+
+#include <algorithm>
+
+#include "base/logging.h"
+#include "pdf/draw_utils.h"
+#include "pdf/resource_consts.h"
+#include "ppapi/cpp/dev/font_dev.h"
+
+namespace chrome_pdf {
+
+const double ProgressControl::kCompleted = 100.0;
+
+// There is a bug outputting text with alpha 0xFF (opaque) to an intermediate
+// image. It outputs alpha channgel of the text pixels to 0xFF (transparent).
+// And it breaks next alpha blending.
+// For now, let's use alpha 0xFE to work around this bug.
+// TODO(gene): investigate this bug.
+const uint32 kProgressTextColor = 0xFEDDE6FC;
+const uint32 kProgressTextSize = 16;
+const uint32 kImageTextSpacing = 8;
+const uint32 kTopPadding = 8;
+const uint32 kBottomPadding = 12;
+const uint32 kLeftPadding = 10;
+const uint32 kRightPadding = 10;
+
+int ScaleInt(int val, float scale) {
+ return static_cast<int>(val * scale);
+}
+
+ProgressControl::ProgressControl()
+ : progress_(0.0),
+ device_scale_(1.0) {
+}
+
+ProgressControl::~ProgressControl() {
+}
+
+bool ProgressControl::CreateProgressControl(
+ uint32 id,
+ bool visible,
+ Control::Owner* delegate,
+ double progress,
+ float device_scale,
+ const std::vector<pp::ImageData>& images,
+ const pp::ImageData& background,
+ const std::string& text) {
+ progress_ = progress;
+ text_ = text;
+ bool res = Control::Create(id, pp::Rect(), visible, delegate);
+ if (res)
+ Reconfigure(background, images, device_scale);
+ return res;
+}
+
+void ProgressControl::Reconfigure(const pp::ImageData& background,
+ const std::vector<pp::ImageData>& images,
+ float device_scale) {
+ DCHECK(images.size() != 0);
+ images_ = images;
+ background_ = background;
+ device_scale_ = device_scale;
+ pp::Size ctrl_size;
+ CalculateLayout(owner()->GetInstance(), images_, background_, text_,
+ device_scale_, &ctrl_size, &image_rc_, &text_rc_);
+ pp::Rect rc(pp::Point(), ctrl_size);
+ Control::SetRect(rc, false);
+ PrepareBackground();
+}
+
+// static
+void ProgressControl::CalculateLayout(pp::Instance* instance,
+ const std::vector<pp::ImageData>& images,
+ const pp::ImageData& background,
+ const std::string& text,
+ float device_scale,
+ pp::Size* ctrl_size,
+ pp::Rect* image_rc,
+ pp::Rect* text_rc) {
+ DCHECK(images.size() != 0);
+ int image_width = 0;
+ int image_height = 0;
+ for (size_t i = 0; i < images.size(); i++) {
+ image_width = std::max(image_width, images[i].size().width());
+ image_height = std::max(image_height, images[i].size().height());
+ }
+
+ pp::FontDescription_Dev description;
+ description.set_family(PP_FONTFAMILY_SANSSERIF);
+ description.set_size(ScaleInt(kProgressTextSize, device_scale));
+ description.set_weight(PP_FONTWEIGHT_BOLD);
+ pp::Font_Dev font(instance, description);
+ int text_length = font.MeasureSimpleText(text);
+
+ pp::FontDescription_Dev desc;
+ PP_FontMetrics_Dev metrics;
+ font.Describe(&desc, &metrics);
+ int text_height = metrics.height;
+
+ *ctrl_size = pp::Size(
+ image_width + text_length +
+ ScaleInt(kImageTextSpacing + kLeftPadding + kRightPadding, device_scale),
+ std::max(image_height, text_height) +
+ ScaleInt(kTopPadding + kBottomPadding, device_scale));
+
+ int offset_x = 0;
+ int offset_y = 0;
+ if (ctrl_size->width() < background.size().width()) {
+ offset_x += (background.size().width() - ctrl_size->width()) / 2;
+ ctrl_size->set_width(background.size().width());
+ }
+ if (ctrl_size->height() < background.size().height()) {
+ offset_y += (background.size().height() - ctrl_size->height()) / 2;
+ ctrl_size->set_height(background.size().height());
+ }
+
+ *image_rc = pp::Rect(ScaleInt(kLeftPadding, device_scale) + offset_x,
+ ScaleInt(kTopPadding, device_scale) + offset_y,
+ image_width,
+ image_height);
+
+ *text_rc = pp::Rect(
+ ctrl_size->width() - text_length -
+ ScaleInt(kRightPadding, device_scale) - offset_x,
+ (ctrl_size->height() - text_height) / 2,
+ text_length,
+ text_height);
+}
+
+size_t ProgressControl::GetImageIngex() const {
+ return static_cast<size_t>((progress_ / 100.0) * images_.size());
+}
+
+void ProgressControl::Paint(pp::ImageData* image_data, const pp::Rect& rc) {
+ if (!visible())
+ return;
+
+ pp::Rect draw_rc = rect().Intersect(rc);
+ if (draw_rc.IsEmpty())
+ return;
+
+ pp::ImageData buffer(owner()->GetInstance(), ctrl_background_.format(),
+ ctrl_background_.size(), false);
+ CopyImage(ctrl_background_, pp::Rect(ctrl_background_.size()),
+ &buffer, pp::Rect(ctrl_background_.size()), false);
+
+ size_t index = GetImageIngex();
+ if (index >= images_.size())
+ index = images_.size() - 1;
+
+ AlphaBlend(images_[index],
+ pp::Rect(images_[index].size()),
+ &buffer,
+ image_rc_.point(),
+ kOpaqueAlpha);
+
+ pp::Rect image_draw_rc(draw_rc);
+ image_draw_rc.Offset(-rect().x(), -rect().y());
+ AlphaBlend(buffer,
+ image_draw_rc,
+ image_data,
+ draw_rc.point(),
+ transparency());
+}
+
+void ProgressControl::SetProgress(double progress) {
+ size_t old_index = GetImageIngex();
+ progress_ = progress;
+ size_t new_index = GetImageIngex();
+ if (progress_ >= kCompleted) {
+ progress_ = kCompleted;
+ owner()->OnEvent(id(), EVENT_ID_PROGRESS_COMPLETED, NULL);
+ }
+ if (visible() && old_index != new_index)
+ owner()->Invalidate(id(), rect());
+}
+
+void ProgressControl::PrepareBackground() {
+ AdjustBackground();
+
+ pp::FontDescription_Dev description;
+ description.set_family(PP_FONTFAMILY_SANSSERIF);
+ description.set_size(ScaleInt(kProgressTextSize, device_scale_));
+ description.set_weight(PP_FONTWEIGHT_BOLD);
+ pp::Font_Dev font(owner()->GetInstance(), description);
+
+ pp::FontDescription_Dev desc;
+ PP_FontMetrics_Dev metrics;
+ font.Describe(&desc, &metrics);
+
+ pp::Point text_origin = pp::Point(text_rc_.x(),
+ (text_rc_.y() + text_rc_.bottom() + metrics.x_height) / 2);
+ font.DrawTextAt(&ctrl_background_, pp::TextRun_Dev(text_), text_origin,
+ kProgressTextColor, pp::Rect(ctrl_background_.size()), false);
+}
+
+void ProgressControl::AdjustBackground() {
+ ctrl_background_ = pp::ImageData(owner()->GetInstance(),
+ PP_IMAGEDATAFORMAT_BGRA_PREMUL,
+ rect().size(),
+ false);
+
+ if (rect().size() == background_.size()) {
+ CopyImage(background_, pp::Rect(background_.size()),
+ &ctrl_background_, pp::Rect(ctrl_background_.size()), false);
+ return;
+ }
+
+ // We need to stretch background to new dimentions. To do so, we split
+ // background into 9 different parts. We copy corner rects (1,3,7,9) as is,
+ // stretch rectangles between corners (2,4,6,8) in 1 dimention, and
+ // stretch center rect (5) in 2 dimentions.
+ // |---|---|---|
+ // | 1 | 2 | 3 |
+ // |---|---|---|
+ // | 4 | 5 | 6 |
+ // |---|---|---|
+ // | 7 | 8 | 9 |
+ // |---|---|---|
+ int slice_x = background_.size().width() / 3;
+ int slice_y = background_.size().height() / 3;
+
+ // Copy rect 1
+ pp::Rect src_rc(0, 0, slice_x, slice_y);
+ pp::Rect dest_rc(0, 0, slice_x, slice_y);
+ CopyImage(background_, src_rc, &ctrl_background_, dest_rc, false);
+
+ // Copy rect 3
+ src_rc.set_x(background_.size().width() - slice_x);
+ dest_rc.set_x(ctrl_background_.size().width() - slice_x);
+ CopyImage(background_, src_rc, &ctrl_background_, dest_rc, false);
+
+ // Copy rect 9
+ src_rc.set_y(background_.size().height() - slice_y);
+ dest_rc.set_y(ctrl_background_.size().height() - slice_y);
+ CopyImage(background_, src_rc, &ctrl_background_, dest_rc, false);
+
+ // Copy rect 7
+ src_rc.set_x(0);
+ dest_rc.set_x(0);
+ CopyImage(background_, src_rc, &ctrl_background_, dest_rc, false);
+
+ // Stretch rect 2
+ src_rc = pp::Rect(
+ slice_x, 0, background_.size().width() - 2 * slice_x, slice_y);
+ dest_rc = pp::Rect(
+ slice_x, 0, ctrl_background_.size().width() - 2 * slice_x, slice_y);
+ CopyImage(background_, src_rc, &ctrl_background_, dest_rc, true);
+
+ // Copy rect 8
+ src_rc.set_y(background_.size().height() - slice_y);
+ dest_rc.set_y(ctrl_background_.size().height() - slice_y);
+ CopyImage(background_, src_rc, &ctrl_background_, dest_rc, true);
+
+ // Stretch rect 4
+ src_rc = pp::Rect(
+ 0, slice_y, slice_x, background_.size().height() - 2 * slice_y);
+ dest_rc = pp::Rect(
+ 0, slice_y, slice_x, ctrl_background_.size().height() - 2 * slice_y);
+ CopyImage(background_, src_rc, &ctrl_background_, dest_rc, true);
+
+ // Copy rect 6
+ src_rc.set_x(background_.size().width() - slice_x);
+ dest_rc.set_x(ctrl_background_.size().width() - slice_x);
+ CopyImage(background_, src_rc, &ctrl_background_, dest_rc, true);
+
+ // Stretch rect 5
+ src_rc = pp::Rect(slice_x,
+ slice_y,
+ background_.size().width() - 2 * slice_x,
+ background_.size().height() - 2 * slice_y);
+ dest_rc = pp::Rect(slice_x,
+ slice_y,
+ ctrl_background_.size().width() - 2 * slice_x,
+ ctrl_background_.size().height() - 2 * slice_y);
+ CopyImage(background_, src_rc, &ctrl_background_, dest_rc, true);
+}
+
+} // namespace chrome_pdf