diff options
Diffstat (limited to 'xfa_test/pdf/thumbnail_control.cc')
-rw-r--r-- | xfa_test/pdf/thumbnail_control.cc | 301 |
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 |