summaryrefslogtreecommitdiff
path: root/xfa_test/pdf/thumbnail_control.cc
diff options
context:
space:
mode:
Diffstat (limited to 'xfa_test/pdf/thumbnail_control.cc')
-rw-r--r--xfa_test/pdf/thumbnail_control.cc301
1 files changed, 301 insertions, 0 deletions
diff --git a/xfa_test/pdf/thumbnail_control.cc b/xfa_test/pdf/thumbnail_control.cc
new file mode 100644
index 0000000000..9a779b2912
--- /dev/null
+++ b/xfa_test/pdf/thumbnail_control.cc
@@ -0,0 +1,301 @@
+// Copyright (c) 2012 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/thumbnail_control.h"
+
+#include <algorithm>
+
+#include "base/logging.h"
+#include "base/strings/string_util.h"
+#include "pdf/draw_utils.h"
+#include "pdf/number_image_generator.h"
+
+namespace chrome_pdf {
+
+const int kLeftBorderSize = 52;
+const int kBorderSize = 12;
+const int kHighlightBorderSize = 2;
+
+const uint32 kLeftColor = 0x003F537B;
+const uint32 kRightColor = 0x990D1626;
+
+const uint32 kTopHighlightColor = 0xFF426DC9;
+const uint32 kBottomHighlightColor = 0xFF6391DE;
+const uint32 kThumbnailBackgroundColor = 0xFF000000;
+
+const uint32 kSlidingTimeoutMs = 50;
+const int32 kSlidingShift = 50;
+
+const double kNonSelectedThumbnailAlpha = 0.91;
+
+ThumbnailControl::ThumbnailControl()
+ : engine_(NULL), sliding_width_(0), sliding_shift_(kSlidingShift),
+ sliding_timeout_(kSlidingTimeoutMs), sliding_timer_id_(0) {
+}
+
+ThumbnailControl::~ThumbnailControl() {
+ ClearCache();
+}
+
+bool ThumbnailControl::CreateThumbnailControl(
+ uint32 id, const pp::Rect& rc,
+ bool visible, Owner* owner, PDFEngine* engine,
+ NumberImageGenerator* number_image_generator) {
+ engine_ = engine;
+ number_image_generator_ = number_image_generator;
+ sliding_width_ = rc.width();
+
+ return Control::Create(id, rc, visible, owner);
+}
+
+void ThumbnailControl::SetPosition(int position, int total, bool invalidate) {
+ visible_rect_ = pp::Rect();
+ visible_pages_.clear();
+
+ if (rect().width() < kLeftBorderSize + kBorderSize) {
+ return; // control is too narrow to show thumbnails.
+ }
+
+ int num_pages = engine_->GetNumberOfPages();
+
+ int max_doc_width = 0, total_doc_height = 0;
+ std::vector<pp::Rect> page_sizes(num_pages);
+ for (int i = 0; i < num_pages; ++i) {
+ page_sizes[i] = engine_->GetPageRect(i);
+ max_doc_width = std::max(max_doc_width, page_sizes[i].width());
+ total_doc_height += page_sizes[i].height();
+ }
+
+ if (!max_doc_width)
+ return;
+
+ int max_thumbnail_width = rect().width() - kLeftBorderSize - kBorderSize;
+ double thumbnail_ratio =
+ max_thumbnail_width / static_cast<double>(max_doc_width);
+
+ int total_thumbnail_height = 0;
+ for (int i = 0; i < num_pages; ++i) {
+ total_thumbnail_height += kBorderSize;
+ int thumbnail_width =
+ static_cast<int>(page_sizes[i].width() * thumbnail_ratio);
+ int thumbnail_height =
+ static_cast<int>(page_sizes[i].height() * thumbnail_ratio);
+ int x = (max_thumbnail_width - thumbnail_width) / 2;
+ page_sizes[i] =
+ pp::Rect(x, total_thumbnail_height, thumbnail_width, thumbnail_height);
+ total_thumbnail_height += thumbnail_height;
+ }
+ total_thumbnail_height += kBorderSize;
+
+ int visible_y = 0;
+ if (total > 0) {
+ double range = total_thumbnail_height - rect().height();
+ if (range < 0)
+ range = 0;
+ visible_y = static_cast<int>(range * position / total);
+ }
+ visible_rect_ = pp::Rect(0, visible_y, max_thumbnail_width, rect().height());
+
+ for (int i = 0; i < num_pages; ++i) {
+ if (page_sizes[i].Intersects(visible_rect_)) {
+ PageInfo page_info;
+ page_info.index = i;
+ page_info.rect = page_sizes[i];
+ page_info.rect.Offset(kLeftBorderSize, -visible_rect_.y());
+ visible_pages_.push_back(page_info);
+ }
+ }
+
+ if (invalidate)
+ owner()->Invalidate(id(), rect());
+}
+
+void ThumbnailControl::Show(bool visible, bool invalidate) {
+ if (!visible || invalidate)
+ ClearCache();
+ sliding_width_ = rect().width();
+ Control::Show(visible, invalidate);
+}
+
+void ThumbnailControl::SlideIn() {
+ if (visible())
+ return;
+
+ Show(true, false);
+ sliding_width_ = 0;
+ sliding_shift_ = kSlidingShift;
+
+ sliding_timer_id_ = owner()->ScheduleTimer(id(), sliding_timeout_);
+ owner()->Invalidate(id(), rect());
+}
+
+void ThumbnailControl::SlideOut() {
+ if (!visible())
+ return;
+ sliding_shift_ = -kSlidingShift;
+ sliding_timer_id_ = owner()->ScheduleTimer(id(), sliding_timeout_);
+}
+
+void ThumbnailControl::Paint(pp::ImageData* image_data, const pp::Rect& rc) {
+ if (!visible())
+ return;
+
+ pp::Rect control_rc(rect());
+ control_rc.Offset(control_rc.width() - sliding_width_, 0);
+ control_rc.set_width(sliding_width_);
+
+ pp::Rect draw_rc = rc.Intersect(control_rc);
+ if (draw_rc.IsEmpty())
+ return;
+
+ pp::Rect gradient_rc(control_rc.x(), draw_rc.y(),
+ control_rc.width(), draw_rc.height());
+ GradientFill(owner()->GetInstance(),
+ image_data,
+ draw_rc,
+ gradient_rc,
+ kLeftColor,
+ kRightColor,
+ true,
+ transparency());
+
+ int selected_page = engine_->GetMostVisiblePage();
+ for (size_t i = 0; i < visible_pages_.size(); ++i) {
+ pp::Rect page_rc = visible_pages_[i].rect;
+ page_rc.Offset(control_rc.point());
+
+ if (visible_pages_[i].index == selected_page) {
+ pp::Rect highlight_rc = page_rc;
+ highlight_rc.Inset(-kHighlightBorderSize, -kHighlightBorderSize);
+ GradientFill(owner()->GetInstance(),
+ image_data,
+ draw_rc,
+ highlight_rc,
+ kTopHighlightColor,
+ kBottomHighlightColor,
+ false,
+ transparency());
+ }
+
+ pp::Rect draw_page_rc = page_rc.Intersect(draw_rc);
+ if (draw_page_rc.IsEmpty())
+ continue;
+
+ // First search page image in the cache.
+ pp::ImageData* thumbnail = NULL;
+ std::map<int, pp::ImageData*>::iterator it =
+ image_cache_.find(visible_pages_[i].index);
+ if (it != image_cache_.end()) {
+ if (it->second->size() == page_rc.size())
+ thumbnail = image_cache_[visible_pages_[i].index];
+ else
+ image_cache_.erase(it);
+ }
+
+ // If page is not found in the cache, create new one.
+ if (thumbnail == NULL) {
+ thumbnail = new pp::ImageData(owner()->GetInstance(),
+ PP_IMAGEDATAFORMAT_BGRA_PREMUL,
+ page_rc.size(),
+ false);
+ engine_->PaintThumbnail(thumbnail, visible_pages_[i].index);
+
+ pp::ImageData page_number;
+ number_image_generator_->GenerateImage(
+ visible_pages_[i].index + 1, &page_number);
+ pp::Point origin(
+ (thumbnail->size().width() - page_number.size().width()) / 2,
+ (thumbnail->size().height() - page_number.size().height()) / 2);
+
+ if (origin.x() > 0 && origin.y() > 0) {
+ AlphaBlend(page_number, pp::Rect(pp::Point(), page_number.size()),
+ thumbnail, origin, kOpaqueAlpha);
+ }
+
+ image_cache_[visible_pages_[i].index] = thumbnail;
+ }
+
+ uint8 alpha = transparency();
+ if (visible_pages_[i].index != selected_page)
+ alpha = static_cast<uint8>(alpha * kNonSelectedThumbnailAlpha);
+ FillRect(image_data, draw_page_rc, kThumbnailBackgroundColor);
+ draw_page_rc.Offset(-page_rc.x(), -page_rc.y());
+ AlphaBlend(*thumbnail, draw_page_rc, image_data,
+ draw_page_rc.point() + page_rc.point(), alpha);
+ }
+}
+
+bool ThumbnailControl::HandleEvent(const pp::InputEvent& event) {
+ if (!visible())
+ return false;
+
+ pp::MouseInputEvent mouse_event(event);
+ if (mouse_event.is_null())
+ return false;
+ pp::Point pt = mouse_event.GetPosition();
+ if (!rect().Contains(pt))
+ return false;
+
+ int over_page = -1;
+ for (size_t i = 0; i < visible_pages_.size(); ++i) {
+ pp::Rect page_rc = visible_pages_[i].rect;
+ page_rc.Offset(rect().point());
+ if (page_rc.Contains(pt)) {
+ over_page = i;
+ break;
+ }
+ }
+
+ bool handled = false;
+ switch (event.GetType()) {
+ case PP_INPUTEVENT_TYPE_MOUSEMOVE:
+ owner()->SetCursor(id(),
+ over_page == -1 ? PP_CURSORTYPE_POINTER : PP_CURSORTYPE_HAND);
+ break;
+ case PP_INPUTEVENT_TYPE_MOUSEDOWN:
+ if (over_page != -1) {
+ owner()->Invalidate(id(), rect());
+ owner()->OnEvent(id(), EVENT_ID_THUMBNAIL_SELECTED,
+ &visible_pages_[over_page].index);
+ }
+ handled = true;
+ break;
+ default:
+ break;
+ }
+
+ return handled;
+}
+
+void ThumbnailControl::OnTimerFired(uint32 timer_id) {
+ if (timer_id == sliding_timer_id_) {
+ sliding_width_ += sliding_shift_;
+ if (sliding_width_ <= 0) {
+ // We completely slided out. Make control invisible now.
+ Show(false, false);
+ } else if (sliding_width_ >= rect().width()) {
+ // We completely slided in. Make sliding width to full control width.
+ sliding_width_ = rect().width();
+ } else {
+ // We have not completed sliding yet. Keep sliding.
+ sliding_timer_id_ = owner()->ScheduleTimer(id(), sliding_timeout_);
+ }
+ owner()->Invalidate(id(), rect());
+ }
+}
+
+void ThumbnailControl::ResetEngine(PDFEngine* engine) {
+ engine_ = engine;
+ ClearCache();
+}
+
+void ThumbnailControl::ClearCache() {
+ std::map<int, pp::ImageData*>::iterator it;
+ for (it = image_cache_.begin(); it != image_cache_.end(); ++it) {
+ delete it->second;
+ }
+ image_cache_.clear();
+}
+
+} // namespace chrome_pdf