Add the pdf plugin's source in src\pdf.
I've updated gypi files to not use internal_pdf variable anymore, which was brought in from pdf repo's supplemental.gypi. R=thestig@chromium.org TBR=darin Review URL: https://codereview.chromium.org/294793003 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@271531 0039d316-1c4b-4281-b951-d872f2087c98
This commit is contained in:
build
chrome
pdf
DEPSInfo.plistOWNERSbutton.ccbutton.hchunk_stream.ccchunk_stream.hcontrol.cccontrol.hdocument_loader.ccdocument_loader.hdraw_utils.ccdraw_utils.hfading_control.ccfading_control.hfading_controls.ccfading_controls.hinstance.ccinstance.hlibpdf.mapnumber_image_generator.ccnumber_image_generator.hout_of_process_instance.ccout_of_process_instance.hpage_indicator.ccpage_indicator.hpaint_aggregator.ccpaint_aggregator.hpaint_manager.ccpaint_manager.hpdf.ccpdf.defpdf.gyppdf.hpdf.rcpdf_engine.h
pdfium
pdfium_assert_matching_enums.ccpdfium_engine.ccpdfium_engine.hpdfium_mem_buffer_file_read.ccpdfium_mem_buffer_file_read.hpdfium_mem_buffer_file_write.ccpdfium_mem_buffer_file_write.hpdfium_page.ccpdfium_page.hpdfium_range.ccpdfium_range.hpdfium_test.cc
preview_mode_client.ccpreview_mode_client.hprogress_control.ccprogress_control.hresource.hresource_consts.hthumbnail_control.ccthumbnail_control.h@ -1103,6 +1103,7 @@
|
||||
'../ipc/ipc.gyp:ipc_tests',
|
||||
'../media/media.gyp:media_unittests',
|
||||
'../net/net.gyp:net_unittests_run',
|
||||
'../pdf/pdf.gyp:pdf',
|
||||
'../printing/printing.gyp:printing_unittests',
|
||||
'../remoting/remoting.gyp:remoting_webapp',
|
||||
'../sql/sql.gyp:sql_unittests',
|
||||
@ -1114,11 +1115,6 @@
|
||||
'../url/url.gyp:url_unittests',
|
||||
],
|
||||
'conditions': [
|
||||
['internal_pdf', {
|
||||
'dependencies': [
|
||||
'../pdf/pdf.gyp:pdf',
|
||||
],
|
||||
}], # internal_pdf
|
||||
['target_arch=="ia32"', {
|
||||
'dependencies': [
|
||||
'../chrome/chrome.gyp:crash_service_win64',
|
||||
|
@ -1275,9 +1275,6 @@
|
||||
# Build libpeerconnection as a static library by default.
|
||||
'libpeer_target_type%': 'static_library',
|
||||
|
||||
# Set to 1 to compile with the built in pdf viewer.
|
||||
'internal_pdf%': 0,
|
||||
|
||||
# Set to 1 to compile with the OpenGL ES 2.0 conformance tests.
|
||||
'internal_gles2_conform_tests%': 0,
|
||||
|
||||
|
@ -282,6 +282,9 @@
|
||||
'app/chrome_main_mac.mm',
|
||||
'app/chrome_main_mac.h',
|
||||
],
|
||||
'dependencies': [
|
||||
'../pdf/pdf.gyp:pdf',
|
||||
],
|
||||
'include_dirs': [
|
||||
'<(grit_out_dir)',
|
||||
],
|
||||
@ -319,11 +322,6 @@
|
||||
'../components/components.gyp:breakpad_stubs',
|
||||
],
|
||||
}], # mac_breakpad_compiled_in
|
||||
['internal_pdf', {
|
||||
'dependencies': [
|
||||
'../pdf/pdf.gyp:pdf',
|
||||
],
|
||||
}],
|
||||
], # conditions
|
||||
}], # OS=="mac"
|
||||
], # conditions
|
||||
|
@ -76,6 +76,7 @@
|
||||
# Bring in pdfsqueeze and run it on all pdfs
|
||||
'../build/temp_gyp/pdfsqueeze.gyp:pdfsqueeze',
|
||||
'../crypto/crypto.gyp:crypto',
|
||||
'../pdf/pdf.gyp:pdf',
|
||||
# On Mac, Flash gets put into the framework, so we need this
|
||||
# dependency here. flash_player.gyp will copy the Flash bundle
|
||||
# into PRODUCT_DIR.
|
||||
@ -146,13 +147,10 @@
|
||||
},
|
||||
{
|
||||
'destination': '<(PRODUCT_DIR)/$(CONTENTS_FOLDER_PATH)/Internet Plug-Ins',
|
||||
'files': [],
|
||||
'files': [
|
||||
'<(PRODUCT_DIR)/PDF.plugin',
|
||||
],
|
||||
'conditions': [
|
||||
['internal_pdf', {
|
||||
'files': [
|
||||
'<(PRODUCT_DIR)/PDF.plugin',
|
||||
],
|
||||
}],
|
||||
['disable_nacl!=1', {
|
||||
'files': [
|
||||
'<(PRODUCT_DIR)/ppGoogleNaClPluginChrome.plugin',
|
||||
@ -278,11 +276,6 @@
|
||||
},
|
||||
],
|
||||
}], # mac_keystone
|
||||
['internal_pdf', {
|
||||
'dependencies': [
|
||||
'../pdf/pdf.gyp:pdf',
|
||||
],
|
||||
}],
|
||||
['debug_devtools==1', {
|
||||
'postbuilds': [{
|
||||
'postbuild_name': 'Copy inspector files',
|
||||
|
@ -368,7 +368,7 @@
|
||||
'--breakpad=0',
|
||||
'--keystone=<(mac_keystone)',
|
||||
'--scm=1',
|
||||
'--pdf=<(internal_pdf)',
|
||||
'--pdf=1',
|
||||
'--bundle_id=<(mac_bundle_id)'],
|
||||
},
|
||||
{
|
||||
@ -430,23 +430,17 @@
|
||||
# chrome/app/theme/google_chrome/BRANDING have the short name
|
||||
# "chrome" etc.; should we try to extract from there instead?
|
||||
|
||||
# On Mac, this is done in chrome_dll.gypi.
|
||||
['internal_pdf', {
|
||||
# CrOS does this in a separate build step.
|
||||
['OS=="linux" and chromeos==0 and linux_dump_symbols==1', {
|
||||
'dependencies': [
|
||||
'../pdf/pdf.gyp:pdf',
|
||||
'../pdf/pdf.gyp:pdf_linux_symbols',
|
||||
],
|
||||
'conditions': [
|
||||
# CrOS does this in a separate build step.
|
||||
['OS=="linux" and chromeos==0 and linux_dump_symbols==1', {
|
||||
'dependencies': [
|
||||
'../pdf/pdf.gyp:pdf_linux_symbols',
|
||||
],
|
||||
}], # OS=="linux" and chromeos==0 and linux_dump_symbols==1
|
||||
],
|
||||
}], # internal_pdf
|
||||
}], # OS=="linux" and chromeos==0 and linux_dump_symbols==1
|
||||
],
|
||||
'dependencies': [
|
||||
'../components/components.gyp:startup_metric_utils',
|
||||
# On Mac, this is done in chrome_dll.gypi.
|
||||
'../pdf/pdf.gyp:pdf',
|
||||
'chrome_resources.gyp:packed_extra_resources',
|
||||
'chrome_resources.gyp:packed_resources',
|
||||
# Copy Flash Player files to PRODUCT_DIR if applicable. Let the .gyp
|
||||
|
@ -495,6 +495,7 @@
|
||||
'<(PRODUCT_DIR)/chrome',
|
||||
'<(PRODUCT_DIR)/chrome_sandbox',
|
||||
'<(PRODUCT_DIR)/libffmpegsumo.so',
|
||||
'<(PRODUCT_DIR)/libpdf.so',
|
||||
'<(PRODUCT_DIR)/libppGoogleNaClPluginChrome.so',
|
||||
'<(PRODUCT_DIR)/xdg-mime',
|
||||
'<(PRODUCT_DIR)/xdg-settings',
|
||||
@ -541,11 +542,6 @@
|
||||
'deb_arch': 'arm',
|
||||
'rpm_arch': 'arm',
|
||||
}],
|
||||
['internal_pdf', {
|
||||
'packaging_files_binaries': [
|
||||
'<(PRODUCT_DIR)/libpdf.so',
|
||||
],
|
||||
}],
|
||||
['libpeer_target_type!="static_library"', {
|
||||
'packaging_files_binaries': [
|
||||
'<(PRODUCT_DIR)/lib/libpeerconnection.so',
|
||||
|
@ -1770,11 +1770,6 @@
|
||||
['exclude', '^browser/captive_portal/'],
|
||||
],
|
||||
}],
|
||||
['internal_pdf', {
|
||||
'dependencies': [
|
||||
'../pdf/pdf.gyp:pdf',
|
||||
],
|
||||
}],
|
||||
['enable_webrtc==0', {
|
||||
'sources!': [
|
||||
'browser/extensions/api/webrtc_audio_private/webrtc_audio_private_browsertest.cc',
|
||||
|
5
pdf/DEPS
Normal file
5
pdf/DEPS
Normal file
@ -0,0 +1,5 @@
|
||||
include_rules = [
|
||||
"+net",
|
||||
"+ppapi",
|
||||
"+third_party/pdfium/fpdfsdk/include",
|
||||
]
|
44
pdf/Info.plist
Normal file
44
pdf/Info.plist
Normal file
@ -0,0 +1,44 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>CFBundleDevelopmentRegion</key>
|
||||
<string>English</string>
|
||||
<key>CFBundleExecutable</key>
|
||||
<string>${EXECUTABLE_NAME}</string>
|
||||
<key>CFBundleIdentifier</key>
|
||||
<string>org.chromium.pdf_plugin</string>
|
||||
<key>CFBundleInfoDictionaryVersion</key>
|
||||
<string>6.0</string>
|
||||
<key>CFBundleName</key>
|
||||
<string>${PRODUCT_NAME}</string>
|
||||
<key>CFBundlePackageType</key>
|
||||
<string>BRPL</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string>1.0</string>
|
||||
<key>CFBundleSignature</key>
|
||||
<string>????</string>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>1.0</string>
|
||||
<key>CFPlugInDynamicRegisterFunction</key>
|
||||
<string></string>
|
||||
<key>CFPlugInDynamicRegistration</key>
|
||||
<string>NO</string>
|
||||
<key>WebPluginDescription</key>
|
||||
<string>Chrome PDF Viewer</string>
|
||||
<key>WebPluginMIMETypes</key>
|
||||
<dict>
|
||||
<key>application/pdf</key>
|
||||
<dict>
|
||||
<key>WebPluginExtensions</key>
|
||||
<array>
|
||||
<string>pdf</string>
|
||||
</array>
|
||||
<key>WebPluginTypeDescription</key>
|
||||
<string>Acrobat Portable Document Format</string>
|
||||
</dict>
|
||||
</dict>
|
||||
<key>WebPluginName</key>
|
||||
<string>Chrome PDF Viewer</string>
|
||||
</dict>
|
||||
</plist>
|
5
pdf/OWNERS
Normal file
5
pdf/OWNERS
Normal file
@ -0,0 +1,5 @@
|
||||
cevans@chromium.org
|
||||
gene@chromium.org
|
||||
jam@chromium.org
|
||||
raymes@chromium.org
|
||||
thestig@chromium.org
|
179
pdf/button.cc
Normal file
179
pdf/button.cc
Normal file
@ -0,0 +1,179 @@
|
||||
// Copyright (c) 2010 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/button.h"
|
||||
|
||||
#include "base/logging.h"
|
||||
#include "pdf/draw_utils.h"
|
||||
#include "ppapi/cpp/input_event.h"
|
||||
|
||||
namespace chrome_pdf {
|
||||
|
||||
Button::Button()
|
||||
: style_(BUTTON_CLICKABLE), state_(BUTTON_NORMAL), is_pressed_(false) {
|
||||
}
|
||||
|
||||
Button::~Button() {
|
||||
}
|
||||
|
||||
bool Button::CreateButton(uint32 id,
|
||||
const pp::Point& origin,
|
||||
bool visible,
|
||||
Control::Owner* owner,
|
||||
ButtonStyle style,
|
||||
const pp::ImageData& face_normal,
|
||||
const pp::ImageData& face_highlighted,
|
||||
const pp::ImageData& face_pressed) {
|
||||
DCHECK(face_normal.size().GetArea());
|
||||
DCHECK(face_normal.size() == face_highlighted.size());
|
||||
DCHECK(face_normal.size() == face_pressed.size());
|
||||
|
||||
pp::Rect rc(origin, face_normal.size());
|
||||
if (!Control::Create(id, rc, visible, owner))
|
||||
return false;
|
||||
|
||||
style_ = style;
|
||||
|
||||
normal_ = face_normal;
|
||||
highlighted_ = face_highlighted;
|
||||
pressed_ = face_pressed;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
void Button::Paint(pp::ImageData* image_data, const pp::Rect& rc) {
|
||||
if (!visible())
|
||||
return;
|
||||
|
||||
pp::Rect draw_rc = rc.Intersect(rect());
|
||||
if (draw_rc.IsEmpty())
|
||||
return;
|
||||
|
||||
pp::Point origin = draw_rc.point();
|
||||
draw_rc.Offset(-rect().x(), -rect().y());
|
||||
|
||||
AlphaBlend(GetCurrentImage(), draw_rc, image_data, origin, transparency());
|
||||
}
|
||||
|
||||
bool Button::HandleEvent(const pp::InputEvent& event) {
|
||||
if (!visible())
|
||||
return false;
|
||||
|
||||
// Button handles mouse events only.
|
||||
pp::MouseInputEvent mouse_event(event);
|
||||
if (mouse_event.is_null())
|
||||
return false;
|
||||
|
||||
pp::Point pt = mouse_event.GetPosition();
|
||||
if (!rect().Contains(pt) ||
|
||||
event.GetType() == PP_INPUTEVENT_TYPE_MOUSELEAVE) {
|
||||
ChangeState(BUTTON_NORMAL, false);
|
||||
owner()->SetEventCapture(id(), false);
|
||||
return false;
|
||||
}
|
||||
|
||||
owner()->SetCursor(id(), PP_CURSORTYPE_POINTER);
|
||||
owner()->SetEventCapture(id(), true);
|
||||
|
||||
bool handled = true;
|
||||
switch (event.GetType()) {
|
||||
case PP_INPUTEVENT_TYPE_MOUSEMOVE:
|
||||
if (state_ == BUTTON_NORMAL)
|
||||
ChangeState(BUTTON_HIGHLIGHTED, false);
|
||||
break;
|
||||
case PP_INPUTEVENT_TYPE_MOUSEDOWN:
|
||||
if (mouse_event.GetButton() == PP_INPUTEVENT_MOUSEBUTTON_LEFT) {
|
||||
ChangeState(BUTTON_PRESSED, false);
|
||||
is_pressed_ = true;
|
||||
}
|
||||
break;
|
||||
case PP_INPUTEVENT_TYPE_MOUSEUP:
|
||||
if (mouse_event.GetButton() == PP_INPUTEVENT_MOUSEBUTTON_LEFT &&
|
||||
is_pressed_) {
|
||||
OnButtonClicked();
|
||||
is_pressed_ = false;
|
||||
} else {
|
||||
// Since button has not been pressed, return false to allow other
|
||||
// controls (scrollbar) to process mouse button up.
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
handled = false;
|
||||
break;
|
||||
}
|
||||
|
||||
return handled;
|
||||
}
|
||||
|
||||
void Button::OnEventCaptureReleased() {
|
||||
ChangeState(BUTTON_NORMAL, false);
|
||||
}
|
||||
|
||||
void Button::Show(bool visible, bool invalidate) {
|
||||
// If button become invisible, remove pressed flag.
|
||||
if (!visible)
|
||||
is_pressed_ = false;
|
||||
Control::Show(visible, invalidate);
|
||||
}
|
||||
|
||||
void Button::AdjustTransparency(uint8 transparency, bool invalidate) {
|
||||
// If button become invisible, remove pressed flag.
|
||||
if (transparency == kTransparentAlpha)
|
||||
is_pressed_ = false;
|
||||
Control::AdjustTransparency(transparency, invalidate);
|
||||
}
|
||||
|
||||
void Button::SetPressedState(bool pressed) {
|
||||
if (style_ == BUTTON_STATE) {
|
||||
if (IsPressed() != pressed)
|
||||
ChangeState(pressed ? BUTTON_PRESSED_STICKY : BUTTON_NORMAL, true);
|
||||
}
|
||||
}
|
||||
|
||||
const pp::ImageData& Button::GetCurrentImage() {
|
||||
switch (state_) {
|
||||
case BUTTON_NORMAL: return normal_;
|
||||
case BUTTON_HIGHLIGHTED: return highlighted_;
|
||||
case BUTTON_PRESSED:
|
||||
case BUTTON_PRESSED_STICKY: return pressed_;
|
||||
}
|
||||
NOTREACHED();
|
||||
return normal_;
|
||||
}
|
||||
|
||||
void Button::ChangeState(ButtonState new_state, bool force) {
|
||||
if (style_ == BUTTON_STATE && !force) {
|
||||
// If button is a state button and pressed state is sticky,
|
||||
// user have to click on this button again to unpress it.
|
||||
if ((state_ == BUTTON_PRESSED_STICKY && new_state != BUTTON_PRESSED_STICKY)
|
||||
||
|
||||
(state_ != BUTTON_PRESSED_STICKY && new_state == BUTTON_PRESSED_STICKY))
|
||||
return;
|
||||
}
|
||||
|
||||
if (state_ != new_state) {
|
||||
state_ = new_state;
|
||||
owner()->Invalidate(id(), rect());
|
||||
}
|
||||
}
|
||||
|
||||
void Button::OnButtonClicked() {
|
||||
switch (style_) {
|
||||
case BUTTON_CLICKABLE:
|
||||
ChangeState(BUTTON_HIGHLIGHTED, true);
|
||||
owner()->OnEvent(id(), EVENT_ID_BUTTON_CLICKED, NULL);
|
||||
break;
|
||||
case BUTTON_STATE:
|
||||
SetPressedState(!IsPressed());
|
||||
owner()->OnEvent(id(), EVENT_ID_BUTTON_STATE_CHANGED, NULL);
|
||||
break;
|
||||
default:
|
||||
NOTREACHED();
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace chrome_pdf
|
||||
|
71
pdf/button.h
Normal file
71
pdf/button.h
Normal file
@ -0,0 +1,71 @@
|
||||
// Copyright (c) 2010 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.
|
||||
|
||||
#ifndef PDF_BUTTON_H_
|
||||
#define PDF_BUTTON_H_
|
||||
|
||||
#include "pdf/control.h"
|
||||
#include "ppapi/cpp/image_data.h"
|
||||
#include "ppapi/cpp/rect.h"
|
||||
|
||||
namespace chrome_pdf {
|
||||
|
||||
class Button : public Control {
|
||||
public:
|
||||
enum ButtonEventIds {
|
||||
EVENT_ID_BUTTON_CLICKED,
|
||||
EVENT_ID_BUTTON_STATE_CHANGED,
|
||||
};
|
||||
|
||||
enum ButtonStyle {
|
||||
BUTTON_CLICKABLE,
|
||||
BUTTON_STATE
|
||||
};
|
||||
|
||||
enum ButtonState {
|
||||
BUTTON_NORMAL,
|
||||
BUTTON_HIGHLIGHTED,
|
||||
BUTTON_PRESSED,
|
||||
BUTTON_PRESSED_STICKY,
|
||||
};
|
||||
|
||||
Button();
|
||||
virtual ~Button();
|
||||
virtual bool CreateButton(uint32 id,
|
||||
const pp::Point& origin,
|
||||
bool visible,
|
||||
Control::Owner* delegate,
|
||||
ButtonStyle style,
|
||||
const pp::ImageData& face_normal,
|
||||
const pp::ImageData& face_highlighted,
|
||||
const pp::ImageData& face_pressed);
|
||||
|
||||
virtual void Paint(pp::ImageData* image_data, const pp::Rect& rc);
|
||||
virtual bool HandleEvent(const pp::InputEvent& event);
|
||||
virtual void OnEventCaptureReleased();
|
||||
virtual void Show(bool visible, bool invalidate);
|
||||
virtual void AdjustTransparency(uint8 transparency, bool invalidate);
|
||||
|
||||
ButtonState state() const { return state_; }
|
||||
bool IsPressed() const { return state() == BUTTON_PRESSED_STICKY; }
|
||||
void SetPressedState(bool pressed);
|
||||
|
||||
private:
|
||||
void OnButtonClicked();
|
||||
|
||||
const pp::ImageData& GetCurrentImage();
|
||||
void ChangeState(ButtonState new_state, bool force);
|
||||
|
||||
ButtonStyle style_;
|
||||
ButtonState state_;
|
||||
bool is_pressed_;
|
||||
|
||||
pp::ImageData normal_;
|
||||
pp::ImageData highlighted_;
|
||||
pp::ImageData pressed_;
|
||||
};
|
||||
|
||||
} // namespace chrome_pdf
|
||||
|
||||
#endif // PDF_BUTTON_H_
|
172
pdf/chunk_stream.cc
Normal file
172
pdf/chunk_stream.cc
Normal file
@ -0,0 +1,172 @@
|
||||
// Copyright (c) 2010 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/chunk_stream.h"
|
||||
|
||||
#define __STDC_LIMIT_MACROS
|
||||
#ifdef _WIN32
|
||||
#include <limits.h>
|
||||
#else
|
||||
#include <stdint.h>
|
||||
#endif
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
#include "base/basictypes.h"
|
||||
|
||||
namespace chrome_pdf {
|
||||
|
||||
ChunkStream::ChunkStream() {
|
||||
}
|
||||
|
||||
ChunkStream::~ChunkStream() {
|
||||
}
|
||||
|
||||
void ChunkStream::Clear() {
|
||||
chunks_.clear();
|
||||
data_.clear();
|
||||
}
|
||||
|
||||
void ChunkStream::Preallocate(size_t stream_size) {
|
||||
data_.reserve(stream_size);
|
||||
}
|
||||
|
||||
size_t ChunkStream::GetSize() {
|
||||
return data_.size();
|
||||
}
|
||||
|
||||
bool ChunkStream::WriteData(size_t offset, void* buffer, size_t size) {
|
||||
if (SIZE_MAX - size < offset)
|
||||
return false;
|
||||
|
||||
if (data_.size() < offset + size)
|
||||
data_.resize(offset + size);
|
||||
|
||||
memcpy(&data_[offset], buffer, size);
|
||||
|
||||
if (chunks_.empty()) {
|
||||
chunks_[offset] = size;
|
||||
return true;
|
||||
}
|
||||
|
||||
std::map<size_t, size_t>::iterator start = chunks_.upper_bound(offset);
|
||||
if (start != chunks_.begin())
|
||||
--start; // start now points to the key equal or lower than offset.
|
||||
if (start->first + start->second < offset)
|
||||
++start; // start element is entirely before current chunk, skip it.
|
||||
|
||||
std::map<size_t, size_t>::iterator end = chunks_.upper_bound(offset + size);
|
||||
if (start == end) { // No chunks to merge.
|
||||
chunks_[offset] = size;
|
||||
return true;
|
||||
}
|
||||
|
||||
--end;
|
||||
|
||||
size_t new_offset = std::min<size_t>(start->first, offset);
|
||||
size_t new_size =
|
||||
std::max<size_t>(end->first + end->second, offset + size) - new_offset;
|
||||
|
||||
chunks_.erase(start, ++end);
|
||||
|
||||
chunks_[new_offset] = new_size;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ChunkStream::ReadData(size_t offset, size_t size, void* buffer) const {
|
||||
if (!IsRangeAvailable(offset, size))
|
||||
return false;
|
||||
|
||||
memcpy(buffer, &data_[offset], size);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ChunkStream::GetMissedRanges(
|
||||
size_t offset, size_t size,
|
||||
std::vector<std::pair<size_t, size_t> >* ranges) const {
|
||||
if (IsRangeAvailable(offset, size))
|
||||
return false;
|
||||
|
||||
ranges->clear();
|
||||
if (chunks_.empty()) {
|
||||
ranges->push_back(std::pair<size_t, size_t>(offset, size));
|
||||
return true;
|
||||
}
|
||||
|
||||
std::map<size_t, size_t>::const_iterator start = chunks_.upper_bound(offset);
|
||||
if (start != chunks_.begin())
|
||||
--start; // start now points to the key equal or lower than offset.
|
||||
if (start->first + start->second < offset)
|
||||
++start; // start element is entirely before current chunk, skip it.
|
||||
|
||||
std::map<size_t, size_t>::const_iterator end =
|
||||
chunks_.upper_bound(offset + size);
|
||||
if (start == end) { // No data in the current range available.
|
||||
ranges->push_back(std::pair<size_t, size_t>(offset, size));
|
||||
return true;
|
||||
}
|
||||
|
||||
size_t cur_offset = offset;
|
||||
std::map<size_t, size_t>::const_iterator it;
|
||||
for (it = start; it != end; ++it) {
|
||||
if (cur_offset < it->first) {
|
||||
size_t new_size = it->first - cur_offset;
|
||||
ranges->push_back(std::pair<size_t, size_t>(cur_offset, new_size));
|
||||
cur_offset = it->first + it->second;
|
||||
} else if (cur_offset < it->first + it->second) {
|
||||
cur_offset = it->first + it->second;
|
||||
}
|
||||
}
|
||||
|
||||
// Add last chunk.
|
||||
if (cur_offset < offset + size)
|
||||
ranges->push_back(std::pair<size_t, size_t>(cur_offset,
|
||||
offset + size - cur_offset));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ChunkStream::IsRangeAvailable(size_t offset, size_t size) const {
|
||||
if (chunks_.empty())
|
||||
return false;
|
||||
|
||||
if (SIZE_MAX - size < offset)
|
||||
return false;
|
||||
|
||||
std::map<size_t, size_t>::const_iterator it = chunks_.upper_bound(offset);
|
||||
if (it == chunks_.begin())
|
||||
return false; // No chunks includes offset byte.
|
||||
|
||||
--it; // Now it starts equal or before offset.
|
||||
return (it->first + it->second) >= (offset + size);
|
||||
}
|
||||
|
||||
size_t ChunkStream::GetFirstMissingByte() const {
|
||||
if (chunks_.empty())
|
||||
return 0;
|
||||
std::map<size_t, size_t>::const_iterator begin = chunks_.begin();
|
||||
return begin->first > 0 ? 0 : begin->second;
|
||||
}
|
||||
|
||||
size_t ChunkStream::GetLastByteBefore(size_t offset) const {
|
||||
if (chunks_.empty())
|
||||
return 0;
|
||||
std::map<size_t, size_t>::const_iterator it = chunks_.upper_bound(offset);
|
||||
if (it == chunks_.begin())
|
||||
return 0;
|
||||
--it;
|
||||
return it->first + it->second;
|
||||
}
|
||||
|
||||
size_t ChunkStream::GetFirstByteAfter(size_t offset) const {
|
||||
if (chunks_.empty())
|
||||
return 0;
|
||||
std::map<size_t, size_t>::const_iterator it = chunks_.upper_bound(offset);
|
||||
if (it == chunks_.end())
|
||||
return data_.size();
|
||||
return it->first;
|
||||
}
|
||||
|
||||
} // namespace chrome_pdf
|
48
pdf/chunk_stream.h
Normal file
48
pdf/chunk_stream.h
Normal file
@ -0,0 +1,48 @@
|
||||
// Copyright (c) 2010 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.
|
||||
|
||||
#ifndef PDF_CHUNK_STREAM_H_
|
||||
#define PDF_CHUNK_STREAM_H_
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
#include <map>
|
||||
#include <vector>
|
||||
|
||||
namespace chrome_pdf {
|
||||
|
||||
// This class collects a chunks of data into one data stream. Client can check
|
||||
// if data in certain range is available, and get missing chunks of data.
|
||||
class ChunkStream {
|
||||
public:
|
||||
ChunkStream();
|
||||
~ChunkStream();
|
||||
|
||||
void Clear();
|
||||
|
||||
void Preallocate(size_t stream_size);
|
||||
size_t GetSize();
|
||||
|
||||
bool WriteData(size_t offset, void* buffer, size_t size);
|
||||
bool ReadData(size_t offset, size_t size, void* buffer) const;
|
||||
|
||||
// Returns vector of pairs where first is an offset, second is a size.
|
||||
bool GetMissedRanges(size_t offset, size_t size,
|
||||
std::vector<std::pair<size_t, size_t> >* ranges) const;
|
||||
bool IsRangeAvailable(size_t offset, size_t size) const;
|
||||
size_t GetFirstMissingByte() const;
|
||||
|
||||
size_t GetLastByteBefore(size_t offset) const;
|
||||
size_t GetFirstByteAfter(size_t offset) const;
|
||||
|
||||
private:
|
||||
std::vector<unsigned char> data_;
|
||||
|
||||
// Pair, first - begining of the chunk, second - size of the chunk.
|
||||
std::map<size_t, size_t> chunks_;
|
||||
};
|
||||
|
||||
}; // namespace chrome_pdf
|
||||
|
||||
#endif
|
114
pdf/control.cc
Normal file
114
pdf/control.cc
Normal file
@ -0,0 +1,114 @@
|
||||
// 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/control.h"
|
||||
|
||||
#include "base/logging.h"
|
||||
#include "pdf/draw_utils.h"
|
||||
|
||||
namespace chrome_pdf {
|
||||
|
||||
Control::Control()
|
||||
: id_(kInvalidControlId),
|
||||
visible_(false),
|
||||
owner_(NULL),
|
||||
transparency_(kOpaqueAlpha) {
|
||||
}
|
||||
|
||||
Control::~Control() {
|
||||
}
|
||||
|
||||
bool Control::Create(uint32 id, const pp::Rect& rc,
|
||||
bool visible, Owner* owner) {
|
||||
DCHECK(owner);
|
||||
if (owner_ || id == kInvalidControlId)
|
||||
return false; // Already created or id is invalid.
|
||||
id_ = id;
|
||||
rc_ = rc;
|
||||
visible_ = visible;
|
||||
owner_ = owner;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Control::HandleEvent(const pp::InputEvent& event) {
|
||||
return false;
|
||||
}
|
||||
|
||||
void Control::PaintMultipleRects(pp::ImageData* image_data,
|
||||
const std::list<pp::Rect>& rects) {
|
||||
DCHECK(rects.size() > 0);
|
||||
if (rects.size() == 1) {
|
||||
Paint(image_data, rects.front());
|
||||
return;
|
||||
}
|
||||
|
||||
// Some rects in the input list may overlap. To prevent double
|
||||
// paining (causes problems with semi-transparent controls) we'll
|
||||
// paint control into buffer image data only once and copy requested
|
||||
// rectangles.
|
||||
pp::ImageData buffer(owner()->GetInstance(), image_data->format(),
|
||||
rect().size(), false);
|
||||
pp::Rect draw_rc = pp::Rect(image_data->size()).Intersect(rect());
|
||||
pp::Rect ctrl_rc = pp::Rect(rect().point() - draw_rc.point(), draw_rc.size());
|
||||
CopyImage(*image_data, draw_rc, &buffer, ctrl_rc, false);
|
||||
|
||||
// Temporary move control to origin (0,0) and draw it into temp buffer.
|
||||
// Move to the original position afterward. Since this is going on temp
|
||||
// buffer, we don't need to invalidate here.
|
||||
pp::Rect temp = rect();
|
||||
MoveTo(pp::Point(0, 0), false);
|
||||
Paint(&buffer, ctrl_rc);
|
||||
MoveTo(temp.point(), false);
|
||||
|
||||
std::list<pp::Rect>::const_iterator iter;
|
||||
for (iter = rects.begin(); iter != rects.end(); ++iter) {
|
||||
pp::Rect draw_rc = rect().Intersect(*iter);
|
||||
if (!draw_rc.IsEmpty()) {
|
||||
// Copy requested rect from the buffer image.
|
||||
pp::Rect src_rc = draw_rc;
|
||||
src_rc.Offset(-rect().x(), -rect().y());
|
||||
CopyImage(buffer, src_rc, image_data, draw_rc, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Control::Show(bool visible, bool invalidate) {
|
||||
if (visible_ != visible) {
|
||||
visible_ = visible;
|
||||
if (invalidate)
|
||||
owner_->Invalidate(id_, rc_);
|
||||
}
|
||||
}
|
||||
|
||||
void Control::AdjustTransparency(uint8 transparency, bool invalidate) {
|
||||
if (transparency_ != transparency) {
|
||||
transparency_ = transparency;
|
||||
if (invalidate && visible_)
|
||||
owner_->Invalidate(id_, rc_);
|
||||
}
|
||||
}
|
||||
|
||||
void Control::MoveBy(const pp::Point& offset, bool invalidate) {
|
||||
pp::Rect old_rc = rc_;
|
||||
rc_.Offset(offset);
|
||||
if (invalidate && visible_) {
|
||||
owner()->Invalidate(id(), old_rc);
|
||||
owner()->Invalidate(id(), rect());
|
||||
}
|
||||
}
|
||||
|
||||
void Control::SetRect(const pp::Rect& rc, bool invalidate) {
|
||||
pp::Rect old_rc = rc_;
|
||||
rc_ = rc;
|
||||
if (invalidate && visible_) {
|
||||
owner()->Invalidate(id(), old_rc);
|
||||
owner()->Invalidate(id(), rect());
|
||||
}
|
||||
}
|
||||
|
||||
void Control::MoveTo(const pp::Point& origin, bool invalidate) {
|
||||
MoveBy(origin - rc_.point(), invalidate);
|
||||
}
|
||||
|
||||
} // namespace chrome_pdf
|
77
pdf/control.h
Normal file
77
pdf/control.h
Normal file
@ -0,0 +1,77 @@
|
||||
// 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.
|
||||
|
||||
#ifndef PDF_CONTROL_H_
|
||||
#define PDF_CONTROL_H_
|
||||
|
||||
#include <list>
|
||||
|
||||
#include "base/basictypes.h"
|
||||
#include "ppapi/c/dev/pp_cursor_type_dev.h"
|
||||
#include "ppapi/cpp/rect.h"
|
||||
|
||||
namespace pp {
|
||||
class ImageData;
|
||||
class InputEvent;
|
||||
class Instance;
|
||||
}
|
||||
|
||||
namespace chrome_pdf {
|
||||
|
||||
const uint32 kInvalidControlId = 0;
|
||||
|
||||
class Control {
|
||||
public:
|
||||
class Owner {
|
||||
public:
|
||||
virtual ~Owner() {}
|
||||
virtual void OnEvent(uint32 control_id, uint32 event_id, void* data) = 0;
|
||||
virtual void Invalidate(uint32 control_id, const pp::Rect& rc) = 0;
|
||||
virtual uint32 ScheduleTimer(uint32 control_id, uint32 timeout_ms) = 0;
|
||||
virtual void SetEventCapture(uint32 control_id, bool set_capture) = 0;
|
||||
virtual void SetCursor(uint32 control_id,
|
||||
PP_CursorType_Dev cursor_type) = 0;
|
||||
virtual pp::Instance* GetInstance() = 0;
|
||||
};
|
||||
|
||||
Control();
|
||||
virtual ~Control();
|
||||
virtual bool Create(uint32 id, const pp::Rect& rc,
|
||||
bool visible, Owner* owner);
|
||||
|
||||
virtual void Paint(pp::ImageData* image_data, const pp::Rect& rc) {}
|
||||
virtual bool HandleEvent(const pp::InputEvent& event);
|
||||
virtual void OnTimerFired(uint32 timer_id) {}
|
||||
virtual void EventCaptureReleased() {}
|
||||
|
||||
// Paint control into multiple destination rects.
|
||||
virtual void PaintMultipleRects(pp::ImageData* image_data,
|
||||
const std::list<pp::Rect>& rects);
|
||||
|
||||
virtual void Show(bool visible, bool invalidate);
|
||||
virtual void AdjustTransparency(uint8 transparency, bool invalidate);
|
||||
virtual void MoveBy(const pp::Point& offset, bool invalidate);
|
||||
virtual void SetRect(const pp::Rect& rc, bool invalidate);
|
||||
|
||||
void MoveTo(const pp::Point& origin, bool invalidate);
|
||||
|
||||
uint32 id() const { return id_; }
|
||||
const pp::Rect& rect() const { return rc_; }
|
||||
bool visible() const { return visible_; }
|
||||
Owner* owner() { return owner_; }
|
||||
uint8 transparency() const { return transparency_; }
|
||||
|
||||
private:
|
||||
uint32 id_;
|
||||
pp::Rect rc_;
|
||||
bool visible_;
|
||||
Owner* owner_;
|
||||
uint8 transparency_;
|
||||
};
|
||||
|
||||
typedef Control::Owner ControlOwner;
|
||||
|
||||
} // namespace chrome_pdf
|
||||
|
||||
#endif // PDF_CONTROL_H_
|
515
pdf/document_loader.cc
Normal file
515
pdf/document_loader.cc
Normal file
@ -0,0 +1,515 @@
|
||||
// Copyright (c) 2010 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/document_loader.h"
|
||||
|
||||
#include "base/logging.h"
|
||||
#include "base/strings/string_util.h"
|
||||
#include "net/http/http_util.h"
|
||||
#include "ppapi/c/pp_errors.h"
|
||||
#include "ppapi/cpp/url_loader.h"
|
||||
#include "ppapi/cpp/url_request_info.h"
|
||||
#include "ppapi/cpp/url_response_info.h"
|
||||
|
||||
namespace chrome_pdf {
|
||||
|
||||
// Document below size will be downloaded in one chunk.
|
||||
const uint32 kMinFileSize = 64*1024;
|
||||
|
||||
DocumentLoader::DocumentLoader(Client* client)
|
||||
: client_(client), partial_document_(false), request_pending_(false),
|
||||
current_pos_(0), current_chunk_size_(0), current_chunk_read_(0),
|
||||
document_size_(0), header_request_(true), is_multipart_(false) {
|
||||
loader_factory_.Initialize(this);
|
||||
}
|
||||
|
||||
DocumentLoader::~DocumentLoader() {
|
||||
}
|
||||
|
||||
bool DocumentLoader::Init(const pp::URLLoader& loader,
|
||||
const std::string& url,
|
||||
const std::string& headers) {
|
||||
DCHECK(url_.empty());
|
||||
url_ = url;
|
||||
loader_ = loader;
|
||||
|
||||
std::string response_headers;
|
||||
if (!headers.empty()) {
|
||||
response_headers = headers;
|
||||
} else {
|
||||
pp::URLResponseInfo response = loader_.GetResponseInfo();
|
||||
pp::Var headers_var = response.GetHeaders();
|
||||
|
||||
if (headers_var.is_string()) {
|
||||
response_headers = headers_var.AsString();
|
||||
}
|
||||
}
|
||||
|
||||
bool accept_ranges_bytes = false;
|
||||
bool content_encoded = false;
|
||||
uint32 content_length = 0;
|
||||
std::string type;
|
||||
std::string disposition;
|
||||
if (!response_headers.empty()) {
|
||||
net::HttpUtil::HeadersIterator it(response_headers.begin(),
|
||||
response_headers.end(), "\n");
|
||||
while (it.GetNext()) {
|
||||
if (LowerCaseEqualsASCII(it.name(), "content-length")) {
|
||||
content_length = atoi(it.values().c_str());
|
||||
} else if (LowerCaseEqualsASCII(it.name(), "accept-ranges")) {
|
||||
accept_ranges_bytes = LowerCaseEqualsASCII(it.values(), "bytes");
|
||||
} else if (LowerCaseEqualsASCII(it.name(), "content-encoding")) {
|
||||
content_encoded = true;
|
||||
} else if (LowerCaseEqualsASCII(it.name(), "content-type")) {
|
||||
type = it.values();
|
||||
size_t semi_colon_pos = type.find(';');
|
||||
if (semi_colon_pos != std::string::npos) {
|
||||
type = type.substr(0, semi_colon_pos);
|
||||
}
|
||||
TrimWhitespace(type, base::TRIM_ALL, &type);
|
||||
} else if (LowerCaseEqualsASCII(it.name(), "content-disposition")) {
|
||||
disposition = it.values();
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!type.empty() &&
|
||||
!EndsWith(type, "/pdf", false) &&
|
||||
!EndsWith(type, ".pdf", false) &&
|
||||
!EndsWith(type, "/x-pdf", false) &&
|
||||
!EndsWith(type, "/*", false) &&
|
||||
!EndsWith(type, "/acrobat", false) &&
|
||||
!EndsWith(type, "/unknown", false) &&
|
||||
!StartsWithASCII(url, "blob:", false)) {
|
||||
return false;
|
||||
}
|
||||
if (StartsWithASCII(disposition, "attachment", false)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (content_length > 0)
|
||||
chunk_stream_.Preallocate(content_length);
|
||||
|
||||
document_size_ = content_length;
|
||||
requests_count_ = 0;
|
||||
|
||||
// Document loading strategy.
|
||||
// Following table shows the growth on the minimal request size depending
|
||||
// on the number requests that has been made already.
|
||||
chunk_size_table_[10] = 32*1024;
|
||||
chunk_size_table_[20] = 64*1024;
|
||||
chunk_size_table_[30] = 128*1024;
|
||||
chunk_size_table_[40] = 256*1024;
|
||||
chunk_size_table_[50] = 512*1024;
|
||||
chunk_size_table_[60] = 1024*1024;
|
||||
chunk_size_table_[70] = 2048*1024;
|
||||
|
||||
// Enable partial loading only if file size is above the threshold.
|
||||
// It will allow avoiding latency for multiple requests.
|
||||
if (content_length > kMinFileSize &&
|
||||
accept_ranges_bytes &&
|
||||
!content_encoded) {
|
||||
LoadPartialDocument();
|
||||
} else {
|
||||
LoadFullDocument();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void DocumentLoader::LoadPartialDocument() {
|
||||
partial_document_ = true;
|
||||
// Force the main request to be cancelled, since if we're a full-frame plugin
|
||||
// there could be other references to the loader.
|
||||
loader_.Close();
|
||||
loader_ = pp::URLLoader();
|
||||
// Download file header.
|
||||
header_request_ = true;
|
||||
RequestData(0, std::min(GetRequestSize(), document_size_));
|
||||
}
|
||||
|
||||
void DocumentLoader::LoadFullDocument() {
|
||||
partial_document_ = false;
|
||||
chunk_buffer_.clear();
|
||||
ReadMore();
|
||||
}
|
||||
|
||||
bool DocumentLoader::IsDocumentComplete() const {
|
||||
if (document_size_ == 0) // Document size unknown.
|
||||
return false;
|
||||
return IsDataAvailable(0, document_size_);
|
||||
}
|
||||
|
||||
uint32 DocumentLoader::GetAvailableData() const {
|
||||
if (document_size_ == 0) { // If document size is unknown.
|
||||
return current_pos_;
|
||||
}
|
||||
|
||||
std::vector<std::pair<size_t, size_t> > ranges;
|
||||
chunk_stream_.GetMissedRanges(0, document_size_, &ranges);
|
||||
uint32 available = document_size_;
|
||||
std::vector<std::pair<size_t, size_t> >::iterator it;
|
||||
for (it = ranges.begin(); it != ranges.end(); ++it) {
|
||||
available -= it->second;
|
||||
}
|
||||
return available;
|
||||
}
|
||||
|
||||
void DocumentLoader::ClearPendingRequests() {
|
||||
// The first item in the queue is pending (need to keep it in the queue).
|
||||
if (pending_requests_.size() > 1) {
|
||||
// Remove all elements except the first one.
|
||||
pending_requests_.erase(++pending_requests_.begin(),
|
||||
pending_requests_.end());
|
||||
}
|
||||
}
|
||||
|
||||
bool DocumentLoader::GetBlock(uint32 position, uint32 size, void* buf) const {
|
||||
return chunk_stream_.ReadData(position, size, buf);
|
||||
}
|
||||
|
||||
bool DocumentLoader::IsDataAvailable(uint32 position, uint32 size) const {
|
||||
return chunk_stream_.IsRangeAvailable(position, size);
|
||||
}
|
||||
|
||||
void DocumentLoader::RequestData(uint32 position, uint32 size) {
|
||||
DCHECK(partial_document_);
|
||||
|
||||
// We have some artefact request from
|
||||
// PDFiumEngine::OnDocumentComplete() -> FPDFAvail_IsPageAvail after
|
||||
// document is complete.
|
||||
// We need this fix in PDFIum. Adding this as a work around.
|
||||
// Bug: http://code.google.com/p/chromium/issues/detail?id=79996
|
||||
// Test url:
|
||||
// http://www.icann.org/en/correspondence/holtzman-to-jeffrey-02mar11-en.pdf
|
||||
if (IsDocumentComplete())
|
||||
return;
|
||||
|
||||
pending_requests_.push_back(std::pair<size_t, size_t>(position, size));
|
||||
DownloadPendingRequests();
|
||||
}
|
||||
|
||||
void DocumentLoader::DownloadPendingRequests() {
|
||||
if (request_pending_ || pending_requests_.empty())
|
||||
return;
|
||||
|
||||
// Remove already completed requests.
|
||||
// By design DownloadPendingRequests() should have at least 1 request in the
|
||||
// queue. ReadComplete() will remove the last pending comment from the queue.
|
||||
while (pending_requests_.size() > 1) {
|
||||
if (IsDataAvailable(pending_requests_.front().first,
|
||||
pending_requests_.front().second)) {
|
||||
pending_requests_.pop_front();
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
uint32 pos = pending_requests_.front().first;
|
||||
uint32 size = pending_requests_.front().second;
|
||||
if (IsDataAvailable(pos, size)) {
|
||||
ReadComplete();
|
||||
return;
|
||||
}
|
||||
|
||||
// If current request has been partially downloaded already, split it into
|
||||
// a few smaller requests.
|
||||
std::vector<std::pair<size_t, size_t> > ranges;
|
||||
chunk_stream_.GetMissedRanges(pos, size, &ranges);
|
||||
if (ranges.size() > 0) {
|
||||
pending_requests_.pop_front();
|
||||
pending_requests_.insert(pending_requests_.begin(),
|
||||
ranges.begin(), ranges.end());
|
||||
pos = pending_requests_.front().first;
|
||||
size = pending_requests_.front().second;
|
||||
}
|
||||
|
||||
uint32 cur_request_size = GetRequestSize();
|
||||
// If size is less than default request, try to expand download range for
|
||||
// more optimal download.
|
||||
if (size < cur_request_size && partial_document_) {
|
||||
// First, try to expand block towards the end of the file.
|
||||
uint32 new_pos = pos;
|
||||
uint32 new_size = cur_request_size;
|
||||
if (pos + new_size > document_size_)
|
||||
new_size = document_size_ - pos;
|
||||
|
||||
std::vector<std::pair<size_t, size_t> > ranges;
|
||||
if (chunk_stream_.GetMissedRanges(new_pos, new_size, &ranges)) {
|
||||
new_pos = ranges[0].first;
|
||||
new_size = ranges[0].second;
|
||||
}
|
||||
|
||||
// Second, try to expand block towards the beginning of the file.
|
||||
if (new_size < cur_request_size) {
|
||||
uint32 block_end = new_pos + new_size;
|
||||
if (block_end > cur_request_size) {
|
||||
new_pos = block_end - cur_request_size;
|
||||
} else {
|
||||
new_pos = 0;
|
||||
}
|
||||
new_size = block_end - new_pos;
|
||||
|
||||
if (chunk_stream_.GetMissedRanges(new_pos, new_size, &ranges)) {
|
||||
new_pos = ranges.back().first;
|
||||
new_size = ranges.back().second;
|
||||
}
|
||||
}
|
||||
pos = new_pos;
|
||||
size = new_size;
|
||||
}
|
||||
|
||||
size_t last_byte_before = chunk_stream_.GetLastByteBefore(pos);
|
||||
size_t first_byte_after = chunk_stream_.GetFirstByteAfter(pos + size - 1);
|
||||
if (pos - last_byte_before < cur_request_size) {
|
||||
size = pos + size - last_byte_before;
|
||||
pos = last_byte_before;
|
||||
}
|
||||
|
||||
if ((pos + size < first_byte_after) &&
|
||||
(pos + size + cur_request_size >= first_byte_after))
|
||||
size = first_byte_after - pos;
|
||||
|
||||
request_pending_ = true;
|
||||
|
||||
// Start downloading first pending request.
|
||||
loader_.Close();
|
||||
loader_ = client_->CreateURLLoader();
|
||||
pp::CompletionCallback callback =
|
||||
loader_factory_.NewCallback(&DocumentLoader::DidOpen);
|
||||
pp::URLRequestInfo request = GetRequest(pos, size);
|
||||
requests_count_++;
|
||||
int rv = loader_.Open(request, callback);
|
||||
if (rv != PP_OK_COMPLETIONPENDING)
|
||||
callback.Run(rv);
|
||||
}
|
||||
|
||||
pp::URLRequestInfo DocumentLoader::GetRequest(uint32 position,
|
||||
uint32 size) const {
|
||||
pp::URLRequestInfo request(client_->GetPluginInstance());
|
||||
request.SetURL(url_.c_str());
|
||||
request.SetMethod("GET");
|
||||
request.SetFollowRedirects(true);
|
||||
|
||||
const size_t kBufSize = 100;
|
||||
char buf[kBufSize];
|
||||
// According to rfc2616, byte range specifies position of the first and last
|
||||
// bytes in the requested range inclusively. Therefore we should subtract 1
|
||||
// from the position + size, to get index of the last byte that needs to be
|
||||
// downloaded.
|
||||
base::snprintf(buf, kBufSize, "Range: bytes=%d-%d", position,
|
||||
position + size - 1);
|
||||
pp::Var header(buf);
|
||||
request.SetHeaders(header);
|
||||
|
||||
return request;
|
||||
}
|
||||
|
||||
void DocumentLoader::DidOpen(int32_t result) {
|
||||
if (result != PP_OK) {
|
||||
NOTREACHED();
|
||||
return;
|
||||
}
|
||||
|
||||
is_multipart_ = false;
|
||||
current_chunk_size_ = 0;
|
||||
current_chunk_read_ = 0;
|
||||
|
||||
pp::Var headers_var = loader_.GetResponseInfo().GetHeaders();
|
||||
std::string headers;
|
||||
if (headers_var.is_string())
|
||||
headers = headers_var.AsString();
|
||||
|
||||
std::string boundary = GetMultiPartBoundary(headers);
|
||||
if (boundary.size()) {
|
||||
// Leave position untouched for now, when we read the data we'll get it.
|
||||
is_multipart_ = true;
|
||||
multipart_boundary_ = boundary;
|
||||
} else {
|
||||
// Need to make sure that the server returned a byte-range, since it's
|
||||
// possible for a server to just ignore our bye-range request and just
|
||||
// return the entire document even if it supports byte-range requests.
|
||||
// i.e. sniff response to
|
||||
// http://www.act.org/compass/sample/pdf/geometry.pdf
|
||||
current_pos_ = 0;
|
||||
uint32 start_pos, end_pos;
|
||||
if (GetByteRange(headers, &start_pos, &end_pos)) {
|
||||
current_pos_ = start_pos;
|
||||
if (end_pos && end_pos > start_pos)
|
||||
current_chunk_size_ = end_pos - start_pos + 1;
|
||||
}
|
||||
}
|
||||
|
||||
ReadMore();
|
||||
}
|
||||
|
||||
bool DocumentLoader::GetByteRange(const std::string& headers, uint32* start,
|
||||
uint32* end) {
|
||||
net::HttpUtil::HeadersIterator it(headers.begin(), headers.end(), "\n");
|
||||
while (it.GetNext()) {
|
||||
if (LowerCaseEqualsASCII(it.name(), "content-range")) {
|
||||
std::string range = it.values().c_str();
|
||||
if (StartsWithASCII(range, "bytes", false)) {
|
||||
range = range.substr(strlen("bytes"));
|
||||
std::string::size_type pos = range.find('-');
|
||||
std::string range_end;
|
||||
if (pos != std::string::npos)
|
||||
range_end = range.substr(pos + 1);
|
||||
TrimWhitespaceASCII(range, base::TRIM_LEADING, &range);
|
||||
TrimWhitespaceASCII(range_end, base::TRIM_LEADING, &range_end);
|
||||
*start = atoi(range.c_str());
|
||||
*end = atoi(range_end.c_str());
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
std::string DocumentLoader::GetMultiPartBoundary(const std::string& headers) {
|
||||
net::HttpUtil::HeadersIterator it(headers.begin(), headers.end(), "\n");
|
||||
while (it.GetNext()) {
|
||||
if (LowerCaseEqualsASCII(it.name(), "content-type")) {
|
||||
std::string type = StringToLowerASCII(it.values());
|
||||
if (StartsWithASCII(type, "multipart/", true)) {
|
||||
const char* boundary = strstr(type.c_str(), "boundary=");
|
||||
if (!boundary) {
|
||||
NOTREACHED();
|
||||
break;
|
||||
}
|
||||
|
||||
return std::string(boundary + 9);
|
||||
}
|
||||
}
|
||||
}
|
||||
return std::string();
|
||||
}
|
||||
|
||||
void DocumentLoader::ReadMore() {
|
||||
pp::CompletionCallback callback =
|
||||
loader_factory_.NewCallback(&DocumentLoader::DidRead);
|
||||
int rv = loader_.ReadResponseBody(buffer_, sizeof(buffer_), callback);
|
||||
if (rv != PP_OK_COMPLETIONPENDING)
|
||||
callback.Run(rv);
|
||||
}
|
||||
|
||||
void DocumentLoader::DidRead(int32_t result) {
|
||||
if (result > 0) {
|
||||
char* start = buffer_;
|
||||
size_t length = result;
|
||||
if (is_multipart_ && result > 2) {
|
||||
for (int i = 2; i < result; ++i) {
|
||||
if ((buffer_[i - 1] == '\n' && buffer_[i - 2] == '\n') ||
|
||||
(i >= 4 &&
|
||||
buffer_[i - 1] == '\n' && buffer_[i - 2] == '\r' &&
|
||||
buffer_[i - 3] == '\n' && buffer_[i - 4] == '\r')) {
|
||||
uint32 start_pos, end_pos;
|
||||
if (GetByteRange(std::string(buffer_, i), &start_pos, &end_pos)) {
|
||||
current_pos_ = start_pos;
|
||||
start += i;
|
||||
length -= i;
|
||||
if (end_pos && end_pos > start_pos)
|
||||
current_chunk_size_ = end_pos - start_pos + 1;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Reset this flag so we don't look inside the buffer in future calls of
|
||||
// DidRead for this response. Note that this code DOES NOT handle multi-
|
||||
// part responses with more than one part (we don't issue them at the
|
||||
// moment, so they shouldn't arrive).
|
||||
is_multipart_ = false;
|
||||
}
|
||||
|
||||
if (current_chunk_size_ &&
|
||||
current_chunk_read_ + length > current_chunk_size_)
|
||||
length = current_chunk_size_ - current_chunk_read_;
|
||||
|
||||
if (length) {
|
||||
if (document_size_ > 0) {
|
||||
chunk_stream_.WriteData(current_pos_, start, length);
|
||||
} else {
|
||||
// If we did not get content-length in the response, we can't
|
||||
// preallocate buffer for the entire document. Resizing array causing
|
||||
// memory fragmentation issues on the large files and OOM exceptions.
|
||||
// To fix this, we collect all chunks of the file to the list and
|
||||
// concatenate them together after request is complete.
|
||||
chunk_buffer_.push_back(std::vector<unsigned char>());
|
||||
chunk_buffer_.back().resize(length);
|
||||
memcpy(&(chunk_buffer_.back()[0]), start, length);
|
||||
}
|
||||
current_pos_ += length;
|
||||
current_chunk_read_ += length;
|
||||
client_->OnNewDataAvailable();
|
||||
}
|
||||
ReadMore();
|
||||
} else if (result == PP_OK) {
|
||||
ReadComplete();
|
||||
} else {
|
||||
NOTREACHED();
|
||||
}
|
||||
}
|
||||
|
||||
void DocumentLoader::ReadComplete() {
|
||||
if (!partial_document_) {
|
||||
if (document_size_ == 0) {
|
||||
// For the document with no 'content-length" specified we've collected all
|
||||
// the chunks already. Let's allocate final document buffer and copy them
|
||||
// over.
|
||||
chunk_stream_.Preallocate(current_pos_);
|
||||
uint32 pos = 0;
|
||||
std::list<std::vector<unsigned char> >::iterator it;
|
||||
for (it = chunk_buffer_.begin(); it != chunk_buffer_.end(); ++it) {
|
||||
chunk_stream_.WriteData(pos, &((*it)[0]), it->size());
|
||||
pos += it->size();
|
||||
}
|
||||
chunk_buffer_.clear();
|
||||
}
|
||||
document_size_ = current_pos_;
|
||||
client_->OnDocumentComplete();
|
||||
return;
|
||||
}
|
||||
|
||||
request_pending_ = false;
|
||||
pending_requests_.pop_front();
|
||||
|
||||
// If there are more pending request - continue downloading.
|
||||
if (!pending_requests_.empty()) {
|
||||
DownloadPendingRequests();
|
||||
return;
|
||||
}
|
||||
|
||||
if (IsDocumentComplete()) {
|
||||
client_->OnDocumentComplete();
|
||||
return;
|
||||
}
|
||||
|
||||
if (header_request_)
|
||||
client_->OnPartialDocumentLoaded();
|
||||
else
|
||||
client_->OnPendingRequestComplete();
|
||||
header_request_ = false;
|
||||
|
||||
// The OnPendingRequestComplete could have added more requests.
|
||||
if (!pending_requests_.empty()) {
|
||||
DownloadPendingRequests();
|
||||
} else {
|
||||
// Document is not complete and we have no outstanding requests.
|
||||
// Let's keep downloading PDF file in small chunks.
|
||||
uint32 pos = chunk_stream_.GetFirstMissingByte();
|
||||
std::vector<std::pair<size_t, size_t> > ranges;
|
||||
chunk_stream_.GetMissedRanges(pos, GetRequestSize(), &ranges);
|
||||
DCHECK(ranges.size() > 0);
|
||||
RequestData(ranges[0].first, ranges[0].second);
|
||||
}
|
||||
}
|
||||
|
||||
uint32 DocumentLoader::GetRequestSize() const {
|
||||
std::map<uint32, uint32>::const_iterator iter =
|
||||
chunk_size_table_.lower_bound(requests_count_);
|
||||
if (iter == chunk_size_table_.end())
|
||||
iter--;
|
||||
return iter->second;
|
||||
}
|
||||
|
||||
} // namespace chrome_pdf
|
126
pdf/document_loader.h
Normal file
126
pdf/document_loader.h
Normal file
@ -0,0 +1,126 @@
|
||||
// Copyright (c) 2010 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.
|
||||
|
||||
#ifndef PDF_DOCUMENT_LOADER_H_
|
||||
#define PDF_DOCUMENT_LOADER_H_
|
||||
|
||||
#include <list>
|
||||
#include <map>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "base/basictypes.h"
|
||||
#include "pdf/chunk_stream.h"
|
||||
#include "ppapi/cpp/url_loader.h"
|
||||
#include "ppapi/utility/completion_callback_factory.h"
|
||||
|
||||
#define kDefaultRequestSize 32768u
|
||||
|
||||
namespace chrome_pdf {
|
||||
|
||||
class DocumentLoader {
|
||||
public:
|
||||
class Client {
|
||||
public:
|
||||
// Gets the pp::Instance object.
|
||||
virtual pp::Instance* GetPluginInstance() = 0;
|
||||
// Creates new URLLoader based on client settings.
|
||||
virtual pp::URLLoader CreateURLLoader() = 0;
|
||||
// Notification called when partial information about document is available.
|
||||
// Only called for urls that returns full content size and supports byte
|
||||
// range requests.
|
||||
virtual void OnPartialDocumentLoaded() = 0;
|
||||
// Notification called when all outstanding pending requests are complete.
|
||||
virtual void OnPendingRequestComplete() = 0;
|
||||
// Notification called when new data is available.
|
||||
virtual void OnNewDataAvailable() = 0;
|
||||
// Notification called when document is fully loaded.
|
||||
virtual void OnDocumentComplete() = 0;
|
||||
};
|
||||
|
||||
explicit DocumentLoader(Client* client);
|
||||
virtual ~DocumentLoader();
|
||||
|
||||
bool Init(const pp::URLLoader& loader,
|
||||
const std::string& url,
|
||||
const std::string& headers);
|
||||
|
||||
// Data access interface. Return true is sucessful.
|
||||
bool GetBlock(uint32 position, uint32 size, void* buf) const;
|
||||
|
||||
// Data availability interface. Return true data avaialble.
|
||||
bool IsDataAvailable(uint32 position, uint32 size) const;
|
||||
|
||||
// Data availability interface. Return true data avaialble.
|
||||
void RequestData(uint32 position, uint32 size);
|
||||
|
||||
bool IsDocumentComplete() const;
|
||||
uint32 document_size() const { return document_size_; }
|
||||
|
||||
// Return number of bytes available.
|
||||
uint32 GetAvailableData() const;
|
||||
|
||||
// Clear pending requests from the queue.
|
||||
void ClearPendingRequests();
|
||||
|
||||
bool is_partial_document() { return partial_document_; }
|
||||
|
||||
private:
|
||||
// Called by the completion callback of the document's URLLoader.
|
||||
void DidOpen(int32_t result);
|
||||
// Call to read data from the document's URLLoader.
|
||||
void ReadMore();
|
||||
// Called by the completion callback of the document's URLLoader.
|
||||
void DidRead(int32_t result);
|
||||
|
||||
// If the headers have a byte-range response, writes the start and end
|
||||
// positions and returns true if at least the start position was parsed.
|
||||
// The end position will be set to 0 if it was not found or parsed from the
|
||||
// response.
|
||||
// Returns false if not even a start position could be parsed.
|
||||
static bool GetByteRange(const std::string& headers, uint32* start,
|
||||
uint32* end);
|
||||
|
||||
// If the headers have a multi-part response, returns the boundary name.
|
||||
// Otherwise returns an empty string.
|
||||
static std::string GetMultiPartBoundary(const std::string& headers);
|
||||
|
||||
// Called when we detect that partial document load is possible.
|
||||
void LoadPartialDocument();
|
||||
// Called when we have to load full document.
|
||||
void LoadFullDocument();
|
||||
// Download pending requests.
|
||||
void DownloadPendingRequests();
|
||||
// Called when we complete server request and read all data from it.
|
||||
void ReadComplete();
|
||||
// Creates request to download size byte of data data starting from position.
|
||||
pp::URLRequestInfo GetRequest(uint32 position, uint32 size) const;
|
||||
// Returns current request size in bytes.
|
||||
uint32 GetRequestSize() const;
|
||||
|
||||
Client* client_;
|
||||
std::string url_;
|
||||
pp::URLLoader loader_;
|
||||
pp::CompletionCallbackFactory<DocumentLoader> loader_factory_;
|
||||
ChunkStream chunk_stream_;
|
||||
bool partial_document_;
|
||||
bool request_pending_;
|
||||
typedef std::list<std::pair<size_t, size_t> > PendingRequests;
|
||||
PendingRequests pending_requests_;
|
||||
char buffer_[kDefaultRequestSize];
|
||||
uint32 current_pos_;
|
||||
uint32 current_chunk_size_;
|
||||
uint32 current_chunk_read_;
|
||||
uint32 document_size_;
|
||||
bool header_request_;
|
||||
bool is_multipart_;
|
||||
std::string multipart_boundary_;
|
||||
uint32 requests_count_;
|
||||
std::map<uint32, uint32> chunk_size_table_;
|
||||
std::list<std::vector<unsigned char> > chunk_buffer_;
|
||||
};
|
||||
|
||||
} // namespace chrome_pdf
|
||||
|
||||
#endif // PDF_DOCUMENT_LOADER_H_
|
324
pdf/draw_utils.cc
Normal file
324
pdf/draw_utils.cc
Normal file
@ -0,0 +1,324 @@
|
||||
// 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/draw_utils.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <math.h>
|
||||
#include <vector>
|
||||
|
||||
#include "base/logging.h"
|
||||
|
||||
namespace chrome_pdf {
|
||||
|
||||
inline uint8 GetBlue(const uint32& pixel) {
|
||||
return static_cast<uint8>(pixel & 0xFF);
|
||||
}
|
||||
|
||||
inline uint8 GetGreen(const uint32& pixel) {
|
||||
return static_cast<uint8>((pixel >> 8) & 0xFF);
|
||||
}
|
||||
|
||||
inline uint8 GetRed(const uint32& pixel) {
|
||||
return static_cast<uint8>((pixel >> 16) & 0xFF);
|
||||
}
|
||||
|
||||
inline uint8 GetAlpha(const uint32& pixel) {
|
||||
return static_cast<uint8>((pixel >> 24) & 0xFF);
|
||||
}
|
||||
|
||||
inline uint32_t MakePixel(uint8 red, uint8 green, uint8 blue, uint8 alpha) {
|
||||
return (static_cast<uint32_t>(alpha) << 24) |
|
||||
(static_cast<uint32_t>(red) << 16) |
|
||||
(static_cast<uint32_t>(green) << 8) |
|
||||
static_cast<uint32_t>(blue);
|
||||
}
|
||||
|
||||
inline uint8 GradientChannel(uint8 start, uint8 end, double ratio) {
|
||||
double new_channel = start - (static_cast<double>(start) - end) * ratio;
|
||||
if (new_channel < 0)
|
||||
return 0;
|
||||
if (new_channel > 255)
|
||||
return 255;
|
||||
return static_cast<uint8>(new_channel + 0.5);
|
||||
}
|
||||
|
||||
inline uint8 ProcessColor(uint8 src_color, uint8 dest_color, uint8 alpha) {
|
||||
uint32 processed = static_cast<uint32>(src_color) * alpha +
|
||||
static_cast<uint32>(dest_color) * (0xFF - alpha);
|
||||
return static_cast<uint8>((processed / 0xFF) & 0xFF);
|
||||
}
|
||||
|
||||
bool AlphaBlend(const pp::ImageData& src, const pp::Rect& src_rc,
|
||||
pp::ImageData* dest, const pp::Point& dest_origin,
|
||||
uint8 alpha_adjustment) {
|
||||
const uint32_t* src_origin_pixel = src.GetAddr32(src_rc.point());
|
||||
uint32_t* dest_origin_pixel = dest->GetAddr32(dest_origin);
|
||||
|
||||
int height = src_rc.height();
|
||||
int width = src_rc.width();
|
||||
for (int y = 0; y < height; y++) {
|
||||
const uint32_t* src_pixel = src_origin_pixel;
|
||||
uint32_t* dest_pixel = dest_origin_pixel;
|
||||
for (int x = 0; x < width; x++) {
|
||||
uint8 alpha = static_cast<uint8>(static_cast<uint32_t>(alpha_adjustment) *
|
||||
GetAlpha(*src_pixel) / 0xFF);
|
||||
uint8 red = ProcessColor(GetRed(*src_pixel), GetRed(*dest_pixel), alpha);
|
||||
uint8 green = ProcessColor(GetGreen(*src_pixel),
|
||||
GetGreen(*dest_pixel), alpha);
|
||||
uint8 blue = ProcessColor(GetBlue(*src_pixel),
|
||||
GetBlue(*dest_pixel), alpha);
|
||||
*dest_pixel = MakePixel(red, green, blue, GetAlpha(*dest_pixel));
|
||||
|
||||
src_pixel++;
|
||||
dest_pixel++;
|
||||
}
|
||||
src_origin_pixel = reinterpret_cast<const uint32_t*>(
|
||||
reinterpret_cast<const char*>(src_origin_pixel) + src.stride());
|
||||
dest_origin_pixel = reinterpret_cast<uint32_t*>(
|
||||
reinterpret_cast<char*>(dest_origin_pixel) + dest->stride());
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void GradientFill(pp::ImageData* image, const pp::Rect& rc,
|
||||
uint32 start_color, uint32 end_color, bool horizontal) {
|
||||
std::vector<uint32> colors;
|
||||
colors.resize(horizontal ? rc.width() : rc.height());
|
||||
for (size_t i = 0; i < colors.size(); ++i) {
|
||||
double ratio = static_cast<double>(i) / colors.size();
|
||||
colors[i] = MakePixel(
|
||||
GradientChannel(GetRed(start_color), GetRed(end_color), ratio),
|
||||
GradientChannel(GetGreen(start_color), GetGreen(end_color), ratio),
|
||||
GradientChannel(GetBlue(start_color), GetBlue(end_color), ratio),
|
||||
GradientChannel(GetAlpha(start_color), GetAlpha(end_color), ratio));
|
||||
}
|
||||
|
||||
if (horizontal) {
|
||||
const void* data = &(colors[0]);
|
||||
size_t size = colors.size() * 4;
|
||||
uint32_t* origin_pixel = image->GetAddr32(rc.point());
|
||||
for (int y = 0; y < rc.height(); y++) {
|
||||
memcpy(origin_pixel, data, size);
|
||||
origin_pixel = reinterpret_cast<uint32_t*>(
|
||||
reinterpret_cast<char*>(origin_pixel) + image->stride());
|
||||
}
|
||||
} else {
|
||||
uint32_t* origin_pixel = image->GetAddr32(rc.point());
|
||||
for (int y = 0; y < rc.height(); y++) {
|
||||
uint32_t* pixel = origin_pixel;
|
||||
for (int x = 0; x < rc.width(); x++) {
|
||||
*pixel = colors[y];
|
||||
pixel++;
|
||||
}
|
||||
origin_pixel = reinterpret_cast<uint32_t*>(
|
||||
reinterpret_cast<char*>(origin_pixel) + image->stride());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void GradientFill(pp::Instance* instance,
|
||||
pp::ImageData* image,
|
||||
const pp::Rect& dirty_rc,
|
||||
const pp::Rect& gradient_rc,
|
||||
uint32 start_color,
|
||||
uint32 end_color,
|
||||
bool horizontal,
|
||||
uint8 transparency) {
|
||||
pp::Rect draw_rc = gradient_rc.Intersect(dirty_rc);
|
||||
if (draw_rc.IsEmpty())
|
||||
return;
|
||||
|
||||
pp::ImageData gradient(instance, PP_IMAGEDATAFORMAT_BGRA_PREMUL,
|
||||
gradient_rc.size(), false);
|
||||
|
||||
GradientFill(&gradient, pp::Rect(pp::Point(), gradient_rc.size()),
|
||||
start_color, end_color, horizontal);
|
||||
|
||||
pp::Rect copy_rc(draw_rc);
|
||||
copy_rc.Offset(-gradient_rc.x(), -gradient_rc.y());
|
||||
AlphaBlend(gradient, copy_rc, image, draw_rc.point(), transparency);
|
||||
}
|
||||
|
||||
void CopyImage(const pp::ImageData& src, const pp::Rect& src_rc,
|
||||
pp::ImageData* dest, const pp::Rect& dest_rc,
|
||||
bool stretch) {
|
||||
DCHECK(src_rc.width() <= dest_rc.width() &&
|
||||
src_rc.height() <= dest_rc.height());
|
||||
|
||||
const uint32_t* src_origin_pixel = src.GetAddr32(src_rc.point());
|
||||
uint32_t* dest_origin_pixel = dest->GetAddr32(dest_rc.point());
|
||||
if (stretch) {
|
||||
double x_ratio = static_cast<double>(src_rc.width()) / dest_rc.width();
|
||||
double y_ratio = static_cast<double>(src_rc.height()) / dest_rc.height();
|
||||
int height = dest_rc.height();
|
||||
int width = dest_rc.width();
|
||||
for (int y = 0; y < height; y++) {
|
||||
uint32_t* dest_pixel = dest_origin_pixel;
|
||||
for (int x = 0; x < width; x++) {
|
||||
uint32 src_x = static_cast<uint32>(x * x_ratio);
|
||||
uint32 src_y = static_cast<uint32>(y * y_ratio);
|
||||
const uint32_t* src_pixel = src.GetAddr32(
|
||||
pp::Point(src_rc.x() + src_x, src_rc.y() + src_y));
|
||||
*dest_pixel = *src_pixel;
|
||||
dest_pixel++;
|
||||
}
|
||||
dest_origin_pixel = reinterpret_cast<uint32_t*>(
|
||||
reinterpret_cast<char*>(dest_origin_pixel) + dest->stride());
|
||||
}
|
||||
} else {
|
||||
int height = src_rc.height();
|
||||
int width_bytes = src_rc.width() * 4;
|
||||
for (int y = 0; y < height; y++) {
|
||||
memcpy(dest_origin_pixel, src_origin_pixel, width_bytes);
|
||||
src_origin_pixel = reinterpret_cast<const uint32_t*>(
|
||||
reinterpret_cast<const char*>(src_origin_pixel) + src.stride());
|
||||
dest_origin_pixel = reinterpret_cast<uint32_t*>(
|
||||
reinterpret_cast<char*>(dest_origin_pixel) + dest->stride());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void FillRect(pp::ImageData* image, const pp::Rect& rc, uint32 color) {
|
||||
int height = rc.height();
|
||||
if (height == 0)
|
||||
return;
|
||||
|
||||
// Fill in first row.
|
||||
uint32_t* top_line = image->GetAddr32(rc.point());
|
||||
int width = rc.width();
|
||||
for (int x = 0; x < width; x++)
|
||||
top_line[x] = color;
|
||||
|
||||
// Fill in the rest of the rectangle.
|
||||
int byte_width = width * 4;
|
||||
uint32_t* cur_line = reinterpret_cast<uint32_t*>(
|
||||
reinterpret_cast<char*>(top_line) + image->stride());
|
||||
for (int y = 1; y < height; y++) {
|
||||
memcpy(cur_line, top_line, byte_width);
|
||||
cur_line = reinterpret_cast<uint32_t*>(
|
||||
reinterpret_cast<char*>(cur_line) + image->stride());
|
||||
}
|
||||
}
|
||||
|
||||
ShadowMatrix::ShadowMatrix(uint32 depth, double factor, uint32 background)
|
||||
: depth_(depth), factor_(factor), background_(background) {
|
||||
DCHECK(depth_ > 0);
|
||||
matrix_.resize(depth_ * depth_);
|
||||
|
||||
// pv - is a rounding power factor for smoothing corners.
|
||||
// pv = 2.0 will make corners completely round.
|
||||
const double pv = 4.0;
|
||||
// pow_pv - cache to avoid recalculating pow(x, pv) every time.
|
||||
std::vector<double> pow_pv(depth_, 0.0);
|
||||
|
||||
double r = static_cast<double>(depth_);
|
||||
double coef = 256.0 / pow(r, factor);
|
||||
|
||||
for (uint32 y = 0; y < depth_; y++) {
|
||||
// Since matrix is symmetrical, we can reduce the number of calculations
|
||||
// by mirroring results.
|
||||
for (uint32 x = 0; x <= y; x++) {
|
||||
// Fill cache if needed.
|
||||
if (pow_pv[x] == 0.0)
|
||||
pow_pv[x] = pow(x, pv);
|
||||
if (pow_pv[y] == 0.0)
|
||||
pow_pv[y] = pow(y, pv);
|
||||
|
||||
// v - is a value for the smoothing function.
|
||||
// If x == 0 simplify calculations.
|
||||
double v = (x == 0) ? y : pow(pow_pv[x] + pow_pv[y], 1 / pv);
|
||||
|
||||
// Smoothing function.
|
||||
// If factor == 1, smoothing will be linear from 0 to the end,
|
||||
// if 0 < factor < 1, smoothing will drop faster near 0.
|
||||
// if factor > 1, smoothing will drop faster near the end (depth).
|
||||
double f = 256.0 - coef * pow(v, factor);
|
||||
|
||||
uint8 alpha = 0;
|
||||
if (f > kOpaqueAlpha)
|
||||
alpha = kOpaqueAlpha;
|
||||
else if (f < kTransparentAlpha)
|
||||
alpha = kTransparentAlpha;
|
||||
else
|
||||
alpha = static_cast<uint8>(f);
|
||||
|
||||
uint8 red = ProcessColor(0, GetRed(background), alpha);
|
||||
uint8 green = ProcessColor(0, GetGreen(background), alpha);
|
||||
uint8 blue = ProcessColor(0, GetBlue(background), alpha);
|
||||
uint32 pixel = MakePixel(red, green, blue, GetAlpha(background));
|
||||
|
||||
// Mirror matrix.
|
||||
matrix_[y * depth_ + x] = pixel;
|
||||
matrix_[x * depth_ + y] = pixel;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ShadowMatrix::~ShadowMatrix() {
|
||||
}
|
||||
|
||||
void PaintShadow(pp::ImageData* image,
|
||||
const pp::Rect& clip_rc,
|
||||
const pp::Rect& shadow_rc,
|
||||
const ShadowMatrix& matrix) {
|
||||
pp::Rect draw_rc = shadow_rc.Intersect(clip_rc);
|
||||
if (draw_rc.IsEmpty())
|
||||
return;
|
||||
|
||||
int32 depth = static_cast<int32>(matrix.depth());
|
||||
for (int32_t y = draw_rc.y(); y < draw_rc.bottom(); y++) {
|
||||
for (int32_t x = draw_rc.x(); x < draw_rc.right(); x++) {
|
||||
int32_t matrix_x = std::max(depth + shadow_rc.x() - x - 1,
|
||||
depth - shadow_rc.right() + x);
|
||||
int32_t matrix_y = std::max(depth + shadow_rc.y() - y - 1,
|
||||
depth - shadow_rc.bottom() + y);
|
||||
uint32_t* pixel = image->GetAddr32(pp::Point(x, y));
|
||||
|
||||
if (matrix_x < 0)
|
||||
matrix_x = 0;
|
||||
else if (matrix_x >= static_cast<int32>(depth))
|
||||
matrix_x = depth - 1;
|
||||
|
||||
if (matrix_y < 0)
|
||||
matrix_y = 0;
|
||||
else if (matrix_y >= static_cast<int32>(depth))
|
||||
matrix_y = depth - 1;
|
||||
|
||||
*pixel = matrix.GetValue(matrix_x, matrix_y);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void DrawShadow(pp::ImageData* image,
|
||||
const pp::Rect& shadow_rc,
|
||||
const pp::Rect& object_rc,
|
||||
const pp::Rect& clip_rc,
|
||||
const ShadowMatrix& matrix) {
|
||||
if (shadow_rc == object_rc)
|
||||
return; // Nothing to paint.
|
||||
|
||||
// Fill top part.
|
||||
pp::Rect rc(shadow_rc.point(),
|
||||
pp::Size(shadow_rc.width(), object_rc.y() - shadow_rc.y()));
|
||||
PaintShadow(image, rc.Intersect(clip_rc), shadow_rc, matrix);
|
||||
|
||||
// Fill bottom part.
|
||||
rc = pp::Rect(shadow_rc.x(), object_rc.bottom(),
|
||||
shadow_rc.width(), shadow_rc.bottom() - object_rc.bottom());
|
||||
PaintShadow(image, rc.Intersect(clip_rc), shadow_rc, matrix);
|
||||
|
||||
// Fill left part.
|
||||
rc = pp::Rect(shadow_rc.x(), object_rc.y(),
|
||||
object_rc.x() - shadow_rc.x(), object_rc.height());
|
||||
PaintShadow(image, rc.Intersect(clip_rc), shadow_rc, matrix);
|
||||
|
||||
// Fill right part.
|
||||
rc = pp::Rect(object_rc.right(), object_rc.y(),
|
||||
shadow_rc.right() - object_rc.right(), object_rc.height());
|
||||
PaintShadow(image, rc.Intersect(clip_rc), shadow_rc, matrix);
|
||||
}
|
||||
|
||||
} // namespace chrome_pdf
|
||||
|
94
pdf/draw_utils.h
Normal file
94
pdf/draw_utils.h
Normal file
@ -0,0 +1,94 @@
|
||||
// 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.
|
||||
|
||||
#ifndef PDF_DRAW_UTILS_H_
|
||||
#define PDF_DRAW_UTILS_H_
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include "base/basictypes.h"
|
||||
#include "ppapi/cpp/image_data.h"
|
||||
#include "ppapi/cpp/rect.h"
|
||||
|
||||
namespace chrome_pdf {
|
||||
|
||||
const uint8 kOpaqueAlpha = 0xFF;
|
||||
const uint8 kTransparentAlpha = 0x00;
|
||||
|
||||
bool AlphaBlend(const pp::ImageData& src, const pp::Rect& src_rc,
|
||||
pp::ImageData* dest, const pp::Point& dest_origin,
|
||||
uint8 alpha_adjustment);
|
||||
|
||||
// Fill rectangle with gradient horizontally or vertically. Start is a color of
|
||||
// top-left point of the rectangle, end color is a color of
|
||||
// top-right (horizontal==true) or bottom-left (horizontal==false) point.
|
||||
void GradientFill(pp::ImageData* image,
|
||||
const pp::Rect& rc,
|
||||
uint32 start_color,
|
||||
uint32 end_color,
|
||||
bool horizontal);
|
||||
|
||||
// Fill dirty rectangle with gradient, where gradient color set for corners of
|
||||
// gradient rectangle. Parts of the dirty rect outside of gradient rect will
|
||||
// be unchanged.
|
||||
void GradientFill(pp::Instance* instance,
|
||||
pp::ImageData* image,
|
||||
const pp::Rect& dirty_rc,
|
||||
const pp::Rect& gradient_rc,
|
||||
uint32 start_color,
|
||||
uint32 end_color,
|
||||
bool horizontal,
|
||||
uint8 transparency);
|
||||
|
||||
// Copy one image into another. If stretch is true, the result occupy the entire
|
||||
// dest_rc. If stretch is false, dest_rc.point will be used as an origin of the
|
||||
// result image. Copy will ignore all pixels with transparent alpha from the
|
||||
// source image.
|
||||
void CopyImage(const pp::ImageData& src, const pp::Rect& src_rc,
|
||||
pp::ImageData* dest, const pp::Rect& dest_rc,
|
||||
bool stretch);
|
||||
|
||||
// Fill in rectangle with specified color.
|
||||
void FillRect(pp::ImageData* image, const pp::Rect& rc, uint32 color);
|
||||
|
||||
// Shadow Matrix contains matrix for shadow rendering. To reduce amount of
|
||||
// calculations user may choose to cache matrix and reuse it if nothing changed.
|
||||
class ShadowMatrix {
|
||||
public:
|
||||
// Matrix parameters.
|
||||
// depth - how big matrix should be. Shadow will go smoothly across the
|
||||
// entire matrix from black to background color.
|
||||
// If factor == 1, smoothing will be linear from 0 to the end (depth),
|
||||
// if 0 < factor < 1, smoothing will drop faster near 0.
|
||||
// if factor > 1, smoothing will drop faster near the end (depth).
|
||||
ShadowMatrix(uint32 depth, double factor, uint32 background);
|
||||
|
||||
~ShadowMatrix();
|
||||
|
||||
uint32 GetValue(int32 x, int32 y) const { return matrix_[y * depth_ + x]; }
|
||||
|
||||
uint32 depth() const { return depth_; }
|
||||
double factor() const { return factor_; }
|
||||
uint32 background() const { return background_; }
|
||||
|
||||
private:
|
||||
uint32 depth_;
|
||||
double factor_;
|
||||
uint32 background_;
|
||||
std::vector<uint32> matrix_;
|
||||
};
|
||||
|
||||
// Draw shadow on the image using provided ShadowMatrix.
|
||||
// shadow_rc - rectangle occupied by shadow
|
||||
// object_rc - rectangle that drops the shadow
|
||||
// clip_rc - clipping region
|
||||
void DrawShadow(pp::ImageData* image,
|
||||
const pp::Rect& shadow_rc,
|
||||
const pp::Rect& object_rc,
|
||||
const pp::Rect& clip_rc,
|
||||
const ShadowMatrix& matrix);
|
||||
|
||||
} // namespace chrome_pdf
|
||||
|
||||
#endif // PDF_DRAW_UTILS_H_
|
75
pdf/fading_control.cc
Normal file
75
pdf/fading_control.cc
Normal file
@ -0,0 +1,75 @@
|
||||
// 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/fading_control.h"
|
||||
|
||||
#include <math.h>
|
||||
|
||||
#include "base/logging.h"
|
||||
#include "pdf/draw_utils.h"
|
||||
#include "pdf/resource_consts.h"
|
||||
|
||||
namespace chrome_pdf {
|
||||
|
||||
FadingControl::FadingControl()
|
||||
: alpha_shift_(0), timer_id_(0) {
|
||||
}
|
||||
|
||||
FadingControl::~FadingControl() {
|
||||
}
|
||||
|
||||
void FadingControl::OnTimerFired(uint32 timer_id) {
|
||||
if (timer_id == timer_id_) {
|
||||
int32 new_alpha = transparency() + alpha_shift_;
|
||||
if (new_alpha <= kTransparentAlpha) {
|
||||
Show(false, true);
|
||||
OnFadeOutComplete();
|
||||
return;
|
||||
}
|
||||
if (new_alpha >= kOpaqueAlpha) {
|
||||
AdjustTransparency(kOpaqueAlpha, true);
|
||||
OnFadeInComplete();
|
||||
return;
|
||||
}
|
||||
|
||||
AdjustTransparency(static_cast<uint8>(new_alpha), true);
|
||||
timer_id_ = owner()->ScheduleTimer(id(), kFadingTimeoutMs);
|
||||
}
|
||||
}
|
||||
|
||||
// Fade In/Out control depending on visible flag over the time of time_ms.
|
||||
void FadingControl::Fade(bool show, uint32 time_ms) {
|
||||
DCHECK(time_ms != 0);
|
||||
// Check if we already in the same state.
|
||||
if (!visible() && !show)
|
||||
return;
|
||||
if (!visible() && show) {
|
||||
Show(show, false);
|
||||
AdjustTransparency(kTransparentAlpha, false);
|
||||
OnFadeOutComplete();
|
||||
}
|
||||
if (transparency() == kOpaqueAlpha && show) {
|
||||
OnFadeInComplete();
|
||||
return;
|
||||
}
|
||||
|
||||
int delta = show ? kOpaqueAlpha - transparency() : transparency();
|
||||
double shift =
|
||||
static_cast<double>(delta) * kFadingTimeoutMs / time_ms;
|
||||
if (shift > delta)
|
||||
alpha_shift_ = delta;
|
||||
else
|
||||
alpha_shift_ = static_cast<int>(ceil(shift));
|
||||
|
||||
if (alpha_shift_ == 0)
|
||||
alpha_shift_ = 1;
|
||||
|
||||
// If disabling, make alpha shift negative.
|
||||
if (!show)
|
||||
alpha_shift_ = -alpha_shift_;
|
||||
|
||||
timer_id_ = owner()->ScheduleTimer(id(), kFadingTimeoutMs);
|
||||
}
|
||||
|
||||
} // namespace chrome_pdf
|
32
pdf/fading_control.h
Normal file
32
pdf/fading_control.h
Normal file
@ -0,0 +1,32 @@
|
||||
// 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.
|
||||
|
||||
#ifndef PDF_FADING_CONTROL_H_
|
||||
#define PDF_FADING_CONTROL_H_
|
||||
|
||||
#include "pdf/control.h"
|
||||
|
||||
namespace chrome_pdf {
|
||||
|
||||
class FadingControl : public Control {
|
||||
public:
|
||||
FadingControl();
|
||||
virtual ~FadingControl();
|
||||
|
||||
virtual void OnTimerFired(uint32 timer_id);
|
||||
|
||||
// Fade In/Out control depending on visible flag over the time of time_ms.
|
||||
virtual void Fade(bool visible, uint32 time_ms);
|
||||
|
||||
virtual void OnFadeInComplete() {}
|
||||
virtual void OnFadeOutComplete() {}
|
||||
|
||||
private:
|
||||
int alpha_shift_;
|
||||
uint32 timer_id_;
|
||||
};
|
||||
|
||||
} // namespace chrome_pdf
|
||||
|
||||
#endif // PDF_FADING_CONTROL_H_
|
316
pdf/fading_controls.cc
Normal file
316
pdf/fading_controls.cc
Normal file
@ -0,0 +1,316 @@
|
||||
// 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/fading_controls.h"
|
||||
|
||||
#include "base/logging.h"
|
||||
#include "base/stl_util.h"
|
||||
#include "pdf/draw_utils.h"
|
||||
#include "pdf/resource_consts.h"
|
||||
#include "ppapi/cpp/input_event.h"
|
||||
|
||||
namespace chrome_pdf {
|
||||
|
||||
const uint32 kFadingAlphaShift = 64;
|
||||
const uint32 kSplashFadingAlphaShift = 16;
|
||||
|
||||
FadingControls::FadingControls()
|
||||
: state_(NONE), current_transparency_(kOpaqueAlpha), fading_timer_id_(0),
|
||||
current_capture_control_(kInvalidControlId),
|
||||
fading_timeout_(kFadingTimeoutMs), alpha_shift_(kFadingAlphaShift),
|
||||
splash_(false), splash_timeout_(0) {
|
||||
}
|
||||
|
||||
FadingControls::~FadingControls() {
|
||||
STLDeleteElements(&controls_);
|
||||
}
|
||||
|
||||
bool FadingControls::CreateFadingControls(
|
||||
uint32 id, const pp::Rect& rc, bool visible,
|
||||
Control::Owner* owner, uint8 transparency) {
|
||||
current_transparency_ = transparency;
|
||||
return Control::Create(id, rc, visible, owner);
|
||||
}
|
||||
|
||||
void FadingControls::Paint(pp::ImageData* image_data, const pp::Rect& rc) {
|
||||
// When this control is set to invisible the individual controls are not.
|
||||
// So we need to check for visible() here.
|
||||
if (!visible())
|
||||
return;
|
||||
|
||||
std::list<Control*>::iterator iter;
|
||||
for (iter = controls_.begin(); iter != controls_.end(); ++iter) {
|
||||
(*iter)->Paint(image_data, rc);
|
||||
}
|
||||
}
|
||||
|
||||
bool FadingControls::HandleEvent(const pp::InputEvent& event) {
|
||||
if (!visible())
|
||||
return false;
|
||||
|
||||
pp::MouseInputEvent mouse_event(event);
|
||||
if (mouse_event.is_null())
|
||||
return NotifyControls(event);
|
||||
|
||||
pp::Point pt = mouse_event.GetPosition();
|
||||
|
||||
bool is_mouse_click =
|
||||
mouse_event.GetType() == PP_INPUTEVENT_TYPE_MOUSEDOWN ||
|
||||
mouse_event.GetType() == PP_INPUTEVENT_TYPE_MOUSEUP;
|
||||
|
||||
if (rect().Contains(pt)) {
|
||||
CancelSplashMode();
|
||||
FadeIn();
|
||||
|
||||
// Eat mouse click if are invisible or just fading in.
|
||||
// That prevents accidental clicks on the controls for touch devices.
|
||||
bool eat_mouse_click =
|
||||
(state_ == FADING_IN || current_transparency_ == kTransparentAlpha);
|
||||
if (eat_mouse_click && is_mouse_click &&
|
||||
mouse_event.GetButton() == PP_INPUTEVENT_MOUSEBUTTON_LEFT)
|
||||
return true; // Eat this event here.
|
||||
}
|
||||
|
||||
if ((!rect().Contains(pt)) ||
|
||||
event.GetType() == PP_INPUTEVENT_TYPE_MOUSELEAVE) {
|
||||
if (!splash_)
|
||||
FadeOut();
|
||||
pp::MouseInputEvent event_leave(pp::MouseInputEvent(
|
||||
owner()->GetInstance(),
|
||||
PP_INPUTEVENT_TYPE_MOUSELEAVE,
|
||||
event.GetTimeStamp(),
|
||||
event.GetModifiers(),
|
||||
mouse_event.GetButton(),
|
||||
mouse_event.GetPosition(),
|
||||
mouse_event.GetClickCount(),
|
||||
mouse_event.GetMovement()));
|
||||
return NotifyControls(event_leave);
|
||||
}
|
||||
|
||||
return NotifyControls(event);
|
||||
}
|
||||
|
||||
void FadingControls::OnTimerFired(uint32 timer_id) {
|
||||
if (timer_id == fading_timer_id_) {
|
||||
int32 current_alpha = static_cast<int32>(current_transparency_);
|
||||
if (state_ == FADING_IN)
|
||||
current_alpha += alpha_shift_;
|
||||
else if (state_ == FADING_OUT)
|
||||
current_alpha -= alpha_shift_;
|
||||
|
||||
if (current_alpha >= kOpaqueAlpha) {
|
||||
state_ = NONE;
|
||||
current_alpha = kOpaqueAlpha;
|
||||
} else if (current_alpha <= kTransparentAlpha) {
|
||||
state_ = NONE;
|
||||
current_alpha = kTransparentAlpha;
|
||||
}
|
||||
current_transparency_ = static_cast<uint8>(current_alpha);
|
||||
|
||||
// Invalidate controls with new alpha transparency.
|
||||
std::list<Control*>::iterator iter;
|
||||
for (iter = controls_.begin(); iter != controls_.end(); ++iter) {
|
||||
// We are going to invalidate the whole FadingControls area, to
|
||||
// allow simultaneous drawing.
|
||||
(*iter)->AdjustTransparency(current_transparency_, false);
|
||||
}
|
||||
owner()->Invalidate(id(), GetControlsRect());
|
||||
|
||||
if (state_ != NONE) // Fading still in progress.
|
||||
fading_timer_id_ = owner()->ScheduleTimer(id(), fading_timeout_);
|
||||
else
|
||||
OnFadingComplete();
|
||||
} else {
|
||||
// Dispatch timer to controls.
|
||||
std::list<Control*>::iterator iter;
|
||||
for (iter = controls_.begin(); iter != controls_.end(); ++iter) {
|
||||
(*iter)->OnTimerFired(timer_id);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void FadingControls::EventCaptureReleased() {
|
||||
if (current_capture_control_ != kInvalidControlId) {
|
||||
// Remove previous catpure.
|
||||
Control* ctrl = GetControl(current_capture_control_);
|
||||
if (ctrl)
|
||||
ctrl->EventCaptureReleased();
|
||||
}
|
||||
}
|
||||
|
||||
void FadingControls::MoveBy(const pp::Point& offset, bool invalidate) {
|
||||
std::list<Control*>::iterator iter;
|
||||
for (iter = controls_.begin(); iter != controls_.end(); ++iter) {
|
||||
// We invalidate entire FadingControl later if needed.
|
||||
(*iter)->MoveBy(offset, false);
|
||||
}
|
||||
Control::MoveBy(offset, invalidate);
|
||||
}
|
||||
|
||||
void FadingControls::OnEvent(uint32 control_id, uint32 event_id, void* data) {
|
||||
owner()->OnEvent(control_id, event_id, data);
|
||||
}
|
||||
|
||||
void FadingControls::Invalidate(uint32 control_id, const pp::Rect& rc) {
|
||||
owner()->Invalidate(control_id, rc);
|
||||
}
|
||||
|
||||
uint32 FadingControls::ScheduleTimer(uint32 control_id, uint32 timeout_ms) {
|
||||
// TODO(gene): implement timer routine properly.
|
||||
NOTIMPLEMENTED();
|
||||
//owner()->ScheduleTimer(control_id);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void FadingControls::SetEventCapture(uint32 control_id, bool set_capture) {
|
||||
if (control_id == current_capture_control_) {
|
||||
if (!set_capture) // Remove event capture.
|
||||
current_capture_control_ = kInvalidControlId;
|
||||
} else {
|
||||
EventCaptureReleased();
|
||||
current_capture_control_ = control_id;
|
||||
}
|
||||
}
|
||||
|
||||
void FadingControls::SetCursor(uint32 control_id,
|
||||
PP_CursorType_Dev cursor_type) {
|
||||
owner()->SetCursor(control_id, cursor_type);
|
||||
}
|
||||
|
||||
pp::Instance* FadingControls::GetInstance() {
|
||||
return owner()->GetInstance();
|
||||
}
|
||||
|
||||
bool FadingControls::AddControl(Control* control) {
|
||||
DCHECK(control);
|
||||
if (control->owner() != this)
|
||||
return false;
|
||||
if (!rect().Contains(control->rect()))
|
||||
return false;
|
||||
|
||||
control->AdjustTransparency(current_transparency_, false);
|
||||
controls_.push_back(control);
|
||||
return true;
|
||||
}
|
||||
|
||||
void FadingControls::RemoveControl(uint32 control_id) {
|
||||
if (current_capture_control_ == control_id) {
|
||||
current_capture_control_ = kInvalidControlId;
|
||||
}
|
||||
std::list<Control*>::iterator iter;
|
||||
for (iter = controls_.begin(); iter != controls_.end(); ++iter) {
|
||||
if ((*iter)->id() == control_id) {
|
||||
delete (*iter);
|
||||
controls_.erase(iter);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Control* FadingControls::GetControl(uint32 id) {
|
||||
std::list<Control*>::iterator iter;
|
||||
for (iter = controls_.begin(); iter != controls_.end(); ++iter) {
|
||||
if ((*iter)->id() == id)
|
||||
return *iter;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
pp::Rect FadingControls::GetControlsRect() {
|
||||
pp::Rect rc;
|
||||
std::list<Control*>::iterator iter;
|
||||
for (iter = controls_.begin(); iter != controls_.end(); ++iter) {
|
||||
rc = rc.Union((*iter)->rect());
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
bool FadingControls::ExpandLeft(int offset) {
|
||||
pp::Rect rc = rect();
|
||||
rc.set_width(rc.width() + offset);
|
||||
rc.set_x(rc.x() - offset);
|
||||
if (!rc.Contains(GetControlsRect()))
|
||||
return false;
|
||||
// No need to invalidate since we are expanding triggering area only.
|
||||
SetRect(rc, false);
|
||||
return true;
|
||||
}
|
||||
|
||||
void FadingControls::Splash(uint32 time_ms) {
|
||||
splash_ = true;
|
||||
splash_timeout_ = time_ms;
|
||||
alpha_shift_ = kSplashFadingAlphaShift;
|
||||
FadeIn();
|
||||
}
|
||||
|
||||
bool FadingControls::NotifyControls(const pp::InputEvent& event) {
|
||||
// First pass event to a control that current capture is set to.
|
||||
Control* ctrl = GetControl(current_capture_control_);
|
||||
if (ctrl) {
|
||||
if (ctrl->HandleEvent(event))
|
||||
return true;
|
||||
}
|
||||
|
||||
std::list<Control*>::iterator iter;
|
||||
for (iter = controls_.begin(); iter != controls_.end(); ++iter) {
|
||||
// Now pass event to all control except control with capture,
|
||||
// since we already passed to it above.
|
||||
if ((*iter) != ctrl && (*iter)->HandleEvent(event))
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void FadingControls::FadeIn() {
|
||||
bool already_visible =
|
||||
(state_ == NONE && current_transparency_ == kOpaqueAlpha);
|
||||
if (state_ != FADING_IN && !already_visible) {
|
||||
state_ = FADING_IN;
|
||||
fading_timer_id_ = owner()->ScheduleTimer(id(), fading_timeout_);
|
||||
}
|
||||
if (already_visible)
|
||||
OnFadingComplete();
|
||||
}
|
||||
|
||||
void FadingControls::FadeOut() {
|
||||
bool already_invisible =
|
||||
(state_ == NONE && current_transparency_ == kTransparentAlpha);
|
||||
if (state_ != FADING_OUT && !already_invisible) {
|
||||
state_ = FADING_OUT;
|
||||
fading_timer_id_ = owner()->ScheduleTimer(id(), fading_timeout_);
|
||||
}
|
||||
if (already_invisible)
|
||||
OnFadingComplete();
|
||||
}
|
||||
|
||||
void FadingControls::OnFadingComplete() {
|
||||
DCHECK(current_transparency_ == kOpaqueAlpha ||
|
||||
current_transparency_ == kTransparentAlpha);
|
||||
// In the splash mode following states are possible:
|
||||
// Fade-in complete: splash_==true, splash_timeout_ != 0
|
||||
// We need to schedule timer for splash_timeout_.
|
||||
// Splash timeout complete: splash_==true, splash_timeout_ == 0
|
||||
// We need to fade out still using splash settings.
|
||||
// Fade-out complete: current_transparency_ == kTransparentAlpha
|
||||
// We need to cancel splash mode and go back to normal settings.
|
||||
if (splash_) {
|
||||
if (current_transparency_ == kOpaqueAlpha) {
|
||||
if (splash_timeout_) {
|
||||
fading_timer_id_ = owner()->ScheduleTimer(id(), splash_timeout_);
|
||||
splash_timeout_ = 0;
|
||||
} else {
|
||||
FadeOut();
|
||||
}
|
||||
} else {
|
||||
CancelSplashMode();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void FadingControls::CancelSplashMode() {
|
||||
splash_ = false;
|
||||
alpha_shift_ = kFadingAlphaShift;
|
||||
}
|
||||
|
||||
} // namespace chrome_pdf
|
84
pdf/fading_controls.h
Normal file
84
pdf/fading_controls.h
Normal file
@ -0,0 +1,84 @@
|
||||
// Copyright (c) 2010 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.
|
||||
|
||||
#ifndef PDF_FADING_CONTROLS_H_
|
||||
#define PDF_FADING_CONTROLS_H_
|
||||
|
||||
#include <list>
|
||||
|
||||
#include "pdf/control.h"
|
||||
|
||||
namespace chrome_pdf {
|
||||
|
||||
class FadingControls : public Control,
|
||||
public ControlOwner {
|
||||
public:
|
||||
enum FadingState {
|
||||
NONE,
|
||||
FADING_IN,
|
||||
FADING_OUT
|
||||
};
|
||||
|
||||
FadingControls();
|
||||
virtual ~FadingControls();
|
||||
virtual bool CreateFadingControls(
|
||||
uint32 id, const pp::Rect& rc, bool visible,
|
||||
Control::Owner* delegate, uint8 transparency);
|
||||
|
||||
// Control interface.
|
||||
virtual void Paint(pp::ImageData* image_data, const pp::Rect& rc);
|
||||
virtual bool HandleEvent(const pp::InputEvent& event);
|
||||
virtual void OnTimerFired(uint32 timer_id);
|
||||
virtual void EventCaptureReleased();
|
||||
virtual void MoveBy(const pp::Point& offset, bool invalidate);
|
||||
|
||||
// ControlOwner interface.
|
||||
virtual void OnEvent(uint32 control_id, uint32 event_id, void* data);
|
||||
virtual void Invalidate(uint32 control_id, const pp::Rect& rc);
|
||||
virtual uint32 ScheduleTimer(uint32 control_id, uint32 timeout_ms);
|
||||
virtual void SetEventCapture(uint32 control_id, bool set_capture);
|
||||
virtual void SetCursor(uint32 control_id, PP_CursorType_Dev cursor_type);
|
||||
virtual pp::Instance* GetInstance();
|
||||
|
||||
// FadingControls interface
|
||||
// This function takes ownership of the control, and will destoy it
|
||||
// when control is destroyed.
|
||||
// Input control MUST be located inside FadingControls boundaries, and has
|
||||
// this instance of FadingControls as a delegate.
|
||||
virtual bool AddControl(Control* control);
|
||||
virtual void RemoveControl(uint32 control_id);
|
||||
virtual Control* GetControl(uint32 id);
|
||||
virtual pp::Rect GetControlsRect();
|
||||
|
||||
// Expand/Shrink area which triggers inner control appearance to the left.
|
||||
virtual bool ExpandLeft(int offset);
|
||||
|
||||
// Fade-in, then show controls for time_ms, and then fade-out. Any mouse
|
||||
// event in this control area will interrupt splash mode.
|
||||
virtual void Splash(uint32 time_ms);
|
||||
|
||||
uint8 current_transparency() const { return current_transparency_; }
|
||||
|
||||
private:
|
||||
bool NotifyControls(const pp::InputEvent& event);
|
||||
void FadeIn();
|
||||
void FadeOut();
|
||||
void OnFadingComplete();
|
||||
void CancelSplashMode();
|
||||
|
||||
std::list<Control*> controls_;
|
||||
FadingState state_;
|
||||
uint8 current_transparency_;
|
||||
uint32 fading_timer_id_;
|
||||
uint32 current_capture_control_;
|
||||
uint32 fading_timeout_;
|
||||
uint32 alpha_shift_;
|
||||
bool splash_;
|
||||
uint32 splash_timeout_;
|
||||
};
|
||||
|
||||
} // namespace chrome_pdf
|
||||
|
||||
#endif // PDF_FADING_CONTROLS_H_
|
||||
|
2719
pdf/instance.cc
Normal file
2719
pdf/instance.cc
Normal file
File diff suppressed because it is too large
Load Diff
526
pdf/instance.h
Normal file
526
pdf/instance.h
Normal file
@ -0,0 +1,526 @@
|
||||
// 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.
|
||||
|
||||
#ifndef PDF_INSTANCE_H_
|
||||
#define PDF_INSTANCE_H_
|
||||
|
||||
#include <queue>
|
||||
#include <set>
|
||||
#include <string>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
#include "base/memory/scoped_ptr.h"
|
||||
#include "pdf/button.h"
|
||||
#include "pdf/fading_controls.h"
|
||||
#include "pdf/page_indicator.h"
|
||||
#include "pdf/paint_manager.h"
|
||||
#include "pdf/pdf_engine.h"
|
||||
#include "pdf/preview_mode_client.h"
|
||||
#include "pdf/progress_control.h"
|
||||
#include "pdf/thumbnail_control.h"
|
||||
|
||||
#include "ppapi/c/private/ppb_pdf.h"
|
||||
#include "ppapi/cpp/dev/printing_dev.h"
|
||||
#include "ppapi/cpp/dev/scriptable_object_deprecated.h"
|
||||
#include "ppapi/cpp/dev/scrollbar_dev.h"
|
||||
#include "ppapi/cpp/dev/selection_dev.h"
|
||||
#include "ppapi/cpp/dev/widget_client_dev.h"
|
||||
#include "ppapi/cpp/dev/zoom_dev.h"
|
||||
#include "ppapi/cpp/graphics_2d.h"
|
||||
#include "ppapi/cpp/image_data.h"
|
||||
#include "ppapi/cpp/input_event.h"
|
||||
#include "ppapi/cpp/private/find_private.h"
|
||||
#include "ppapi/cpp/private/instance_private.h"
|
||||
#include "ppapi/cpp/private/var_private.h"
|
||||
#include "ppapi/cpp/url_loader.h"
|
||||
#include "ppapi/utility/completion_callback_factory.h"
|
||||
|
||||
namespace pp {
|
||||
class TextInput_Dev;
|
||||
}
|
||||
|
||||
namespace chrome_pdf {
|
||||
|
||||
struct ToolbarButtonInfo;
|
||||
|
||||
class Instance : public pp::InstancePrivate,
|
||||
public pp::Find_Private,
|
||||
public pp::Printing_Dev,
|
||||
public pp::Selection_Dev,
|
||||
public pp::WidgetClient_Dev,
|
||||
public pp::Zoom_Dev,
|
||||
public PaintManager::Client,
|
||||
public PDFEngine::Client,
|
||||
public PreviewModeClient::Client,
|
||||
public ControlOwner {
|
||||
public:
|
||||
explicit Instance(PP_Instance instance);
|
||||
virtual ~Instance();
|
||||
|
||||
// pp::Instance implementation.
|
||||
virtual bool Init(uint32_t argc,
|
||||
const char* argn[],
|
||||
const char* argv[]) OVERRIDE;
|
||||
virtual bool HandleDocumentLoad(const pp::URLLoader& loader) OVERRIDE;
|
||||
virtual bool HandleInputEvent(const pp::InputEvent& event) OVERRIDE;
|
||||
virtual void DidChangeView(const pp::View& view) OVERRIDE;
|
||||
virtual pp::Var GetInstanceObject() OVERRIDE;
|
||||
|
||||
// pp::Find_Private implementation.
|
||||
virtual bool StartFind(const std::string& text, bool case_sensitive) OVERRIDE;
|
||||
virtual void SelectFindResult(bool forward) OVERRIDE;
|
||||
virtual void StopFind() OVERRIDE;
|
||||
|
||||
// pp::PaintManager::Client implementation.
|
||||
virtual void OnPaint(const std::vector<pp::Rect>& paint_rects,
|
||||
std::vector<PaintManager::ReadyRect>* ready,
|
||||
std::vector<pp::Rect>* pending) OVERRIDE;
|
||||
|
||||
// pp::Printing_Dev implementation.
|
||||
virtual uint32_t QuerySupportedPrintOutputFormats() OVERRIDE;
|
||||
virtual int32_t PrintBegin(
|
||||
const PP_PrintSettings_Dev& print_settings) OVERRIDE;
|
||||
virtual pp::Resource PrintPages(
|
||||
const PP_PrintPageNumberRange_Dev* page_ranges,
|
||||
uint32_t page_range_count) OVERRIDE;
|
||||
virtual void PrintEnd() OVERRIDE;
|
||||
virtual bool IsPrintScalingDisabled() OVERRIDE;
|
||||
|
||||
// pp::Private implementation.
|
||||
virtual pp::Var GetLinkAtPosition(const pp::Point& point);
|
||||
|
||||
// PPP_Selection_Dev implementation.
|
||||
virtual pp::Var GetSelectedText(bool html) OVERRIDE;
|
||||
|
||||
// WidgetClient_Dev implementation.
|
||||
virtual void InvalidateWidget(pp::Widget_Dev widget,
|
||||
const pp::Rect& dirty_rect) OVERRIDE;
|
||||
virtual void ScrollbarValueChanged(pp::Scrollbar_Dev scrollbar,
|
||||
uint32_t value) OVERRIDE;
|
||||
virtual void ScrollbarOverlayChanged(pp::Scrollbar_Dev scrollbar,
|
||||
bool overlay) OVERRIDE;
|
||||
|
||||
// pp::Zoom_Dev implementation.
|
||||
virtual void Zoom(double scale, bool text_only) OVERRIDE;
|
||||
void ZoomChanged(double factor); // Override.
|
||||
|
||||
void FlushCallback(int32_t result);
|
||||
void DidOpen(int32_t result);
|
||||
void DidOpenPreview(int32_t result);
|
||||
// If the given widget intersects the rectangle, paints it and adds the
|
||||
// rect to ready.
|
||||
void PaintIfWidgetIntersects(pp::Widget_Dev* widget,
|
||||
const pp::Rect& rect,
|
||||
std::vector<PaintManager::ReadyRect>* ready,
|
||||
std::vector<pp::Rect>* pending);
|
||||
|
||||
// Called when the timer is fired.
|
||||
void OnTimerFired(int32_t);
|
||||
void OnClientTimerFired(int32_t id);
|
||||
|
||||
// Called when the control timer is fired.
|
||||
void OnControlTimerFired(int32_t,
|
||||
const uint32& control_id,
|
||||
const uint32& timer_id);
|
||||
|
||||
// Called to print without re-entrancy issues.
|
||||
void OnPrint(int32_t);
|
||||
|
||||
// PDFEngine::Client implementation.
|
||||
virtual void DocumentSizeUpdated(const pp::Size& size);
|
||||
virtual void Invalidate(const pp::Rect& rect);
|
||||
virtual void Scroll(const pp::Point& point);
|
||||
virtual void ScrollToX(int position);
|
||||
virtual void ScrollToY(int position);
|
||||
virtual void ScrollToPage(int page);
|
||||
virtual void NavigateTo(const std::string& url, bool open_in_new_tab);
|
||||
virtual void UpdateCursor(PP_CursorType_Dev cursor);
|
||||
virtual void UpdateTickMarks(const std::vector<pp::Rect>& tickmarks);
|
||||
virtual void NotifyNumberOfFindResultsChanged(int total, bool final_result);
|
||||
virtual void NotifySelectedFindResultChanged(int current_find_index);
|
||||
virtual void GetDocumentPassword(
|
||||
pp::CompletionCallbackWithOutput<pp::Var> callback);
|
||||
virtual void Alert(const std::string& message);
|
||||
virtual bool Confirm(const std::string& message);
|
||||
virtual std::string Prompt(const std::string& question,
|
||||
const std::string& default_answer);
|
||||
virtual std::string GetURL();
|
||||
virtual void Email(const std::string& to,
|
||||
const std::string& cc,
|
||||
const std::string& bcc,
|
||||
const std::string& subject,
|
||||
const std::string& body);
|
||||
virtual void Print();
|
||||
virtual void SubmitForm(const std::string& url,
|
||||
const void* data,
|
||||
int length);
|
||||
virtual std::string ShowFileSelectionDialog();
|
||||
virtual pp::URLLoader CreateURLLoader();
|
||||
virtual void ScheduleCallback(int id, int delay_in_ms);
|
||||
virtual void SearchString(const base::char16* string,
|
||||
const base::char16* term,
|
||||
bool case_sensitive,
|
||||
std::vector<SearchStringResult>* results);
|
||||
virtual void DocumentPaintOccurred();
|
||||
virtual void DocumentLoadComplete(int page_count);
|
||||
virtual void DocumentLoadFailed();
|
||||
virtual pp::Instance* GetPluginInstance();
|
||||
virtual void DocumentHasUnsupportedFeature(const std::string& feature);
|
||||
virtual void DocumentLoadProgress(uint32 available, uint32 doc_size);
|
||||
virtual void FormTextFieldFocusChange(bool in_focus);
|
||||
virtual bool IsPrintPreview();
|
||||
|
||||
// ControlOwner implementation.
|
||||
virtual void OnEvent(uint32 control_id, uint32 event_id, void* data);
|
||||
virtual void Invalidate(uint32 control_id, const pp::Rect& rc);
|
||||
virtual uint32 ScheduleTimer(uint32 control_id, uint32 timeout_ms);
|
||||
virtual void SetEventCapture(uint32 control_id, bool set_capture);
|
||||
virtual void SetCursor(uint32 control_id, PP_CursorType_Dev cursor_type);
|
||||
virtual pp::Instance* GetInstance();
|
||||
|
||||
bool dont_paint() const { return dont_paint_; }
|
||||
void set_dont_paint(bool dont_paint) { dont_paint_ = dont_paint; }
|
||||
|
||||
// Called by PDFScriptableObject.
|
||||
bool HasScriptableMethod(const pp::Var& method, pp::Var* exception);
|
||||
pp::Var CallScriptableMethod(const pp::Var& method,
|
||||
const std::vector<pp::Var>& args,
|
||||
pp::Var* exception);
|
||||
|
||||
// PreviewModeClient::Client implementation.
|
||||
virtual void PreviewDocumentLoadComplete() OVERRIDE;
|
||||
virtual void PreviewDocumentLoadFailed() OVERRIDE;
|
||||
|
||||
// Helper functions for implementing PPP_PDF.
|
||||
void RotateClockwise();
|
||||
void RotateCounterclockwise();
|
||||
|
||||
private:
|
||||
// Called whenever the plugin geometry changes to update the location of the
|
||||
// scrollbars, background parts, and notifies the pdf engine.
|
||||
void OnGeometryChanged(double old_zoom, float old_device_scale);
|
||||
|
||||
void CreateHorizontalScrollbar();
|
||||
void CreateVerticalScrollbar();
|
||||
void DestroyHorizontalScrollbar();
|
||||
void DestroyVerticalScrollbar();
|
||||
|
||||
// Returns the thickness of a scrollbar. This returns the thickness when it's
|
||||
// shown, so for overlay scrollbars it'll still be non-zero.
|
||||
int GetScrollbarThickness();
|
||||
|
||||
// Returns the space we need to reserve for the scrollbar in the plugin area.
|
||||
// If overlay scrollbars are used, this will be 0.
|
||||
int GetScrollbarReservedThickness();
|
||||
|
||||
// Returns true if overlay scrollbars are in use.
|
||||
bool IsOverlayScrollbar();
|
||||
|
||||
// Figures out the location of any background rectangles (i.e. those that
|
||||
// aren't painted by the PDF engine).
|
||||
void CalculateBackgroundParts();
|
||||
|
||||
// Computes document width/height in device pixels, based on current zoom and
|
||||
// device scale
|
||||
int GetDocumentPixelWidth() const;
|
||||
int GetDocumentPixelHeight() const;
|
||||
|
||||
// Draws a rectangle with the specified dimensions and color in our buffer.
|
||||
void FillRect(const pp::Rect& rect, unsigned int color);
|
||||
|
||||
std::vector<pp::ImageData> GetThumbnailResources();
|
||||
std::vector<pp::ImageData> GetProgressBarResources(pp::ImageData* background);
|
||||
|
||||
void CreateToolbar(const ToolbarButtonInfo* tb_info, size_t size);
|
||||
int GetToolbarRightOffset();
|
||||
int GetToolbarBottomOffset();
|
||||
void CreateProgressBar();
|
||||
void ConfigureProgressBar();
|
||||
void CreateThumbnails();
|
||||
void CreatePageIndicator(bool always_visible);
|
||||
void ConfigurePageIndicator();
|
||||
|
||||
void PaintOverlayControl(Control* ctrl,
|
||||
pp::ImageData* image_data,
|
||||
std::vector<PaintManager::ReadyRect>* ready);
|
||||
|
||||
void LoadUrl(const std::string& url);
|
||||
void LoadPreviewUrl(const std::string& url);
|
||||
void LoadUrlInternal(const std::string& url, pp::URLLoader* loader,
|
||||
void (Instance::* method)(int32_t));
|
||||
|
||||
// Creates a URL loader and allows it to access all urls, i.e. not just the
|
||||
// frame's origin.
|
||||
pp::URLLoader CreateURLLoaderInternal();
|
||||
|
||||
// Figure out the initial page to display based on #page=N and #nameddest=foo
|
||||
// in the |url_|.
|
||||
// Returns -1 if there is no valid fragment. The returned value is 0-based,
|
||||
// whereas page=N is 1-based.
|
||||
int GetInitialPage(const std::string& url);
|
||||
|
||||
void UpdateToolbarPosition(bool invalidate);
|
||||
void UpdateProgressBarPosition(bool invalidate);
|
||||
void UpdatePageIndicatorPosition(bool invalidate);
|
||||
|
||||
void FormDidOpen(int32_t result);
|
||||
|
||||
std::string GetLocalizedString(PP_ResourceString id);
|
||||
|
||||
void UserMetricsRecordAction(const std::string& action);
|
||||
|
||||
void SaveAs();
|
||||
|
||||
enum ZoomMode {
|
||||
ZOOM_SCALE, // Standard zooming mode, resize will not affect it.
|
||||
ZOOM_FIT_TO_WIDTH, // Maintain fit to width on resize.
|
||||
ZOOM_FIT_TO_PAGE, // Maintain fit to page on resize.
|
||||
ZOOM_AUTO // Maintain the default auto fitting mode on resize.
|
||||
};
|
||||
|
||||
enum DocumentLoadState {
|
||||
LOAD_STATE_LOADING,
|
||||
LOAD_STATE_COMPLETE,
|
||||
LOAD_STATE_FAILED,
|
||||
};
|
||||
|
||||
// Set new zoom mode and scale. Scale will be ignored if mode != ZOOM_SCALE.
|
||||
void SetZoom(ZoomMode zoom_mode, double scale);
|
||||
|
||||
// Updates internal zoom scale based on the plugin/document geometry and
|
||||
// current mode.
|
||||
void UpdateZoomScale();
|
||||
|
||||
// Simulates how Chrome "snaps" zooming up/down to the next nearest zoom level
|
||||
// when the previous zoom level wasn't an integer. We do this so that
|
||||
// pressing the zoom buttons has the same effect as the menu buttons, even if
|
||||
// we start from a non-standard zoom level because of fit-width or fit-height.
|
||||
double CalculateZoom(uint32 control_id) const;
|
||||
|
||||
pp::ImageData CreateResourceImage(PP_ResourceImage image_id);
|
||||
|
||||
void DrawText(const pp::Point& top_center, PP_ResourceString id);
|
||||
|
||||
// Set print preview mode, where the current PDF document is reduced to
|
||||
// only one page, and then extended to |page_count| pages with
|
||||
// |page_count| - 1 blank pages.
|
||||
void SetPrintPreviewMode(int page_count);
|
||||
|
||||
// Returns the page number to be displayed in the page indicator. If the
|
||||
// plugin is running within print preview, the displayed number might be
|
||||
// different from the index of the displayed page.
|
||||
int GetPageNumberToDisplay();
|
||||
|
||||
// Process the preview page data information. |src_url| specifies the preview
|
||||
// page data location. The |src_url| is in the format:
|
||||
// chrome://print/id/page_number/print.pdf
|
||||
// |dst_page_index| specifies the blank page index that needs to be replaced
|
||||
// with the new page data.
|
||||
void ProcessPreviewPageInfo(const std::string& src_url, int dst_page_index);
|
||||
// Load the next available preview page into the blank page.
|
||||
void LoadAvailablePreviewPage();
|
||||
|
||||
// Enables autoscroll using origin as a neutral (center) point.
|
||||
void EnableAutoscroll(const pp::Point& origin);
|
||||
// Disables autoscroll and returns to normal functionality.
|
||||
void DisableAutoscroll();
|
||||
// Calculate autoscroll info and return proper mouse pointer and scroll
|
||||
// andjustments.
|
||||
PP_CursorType_Dev CalculateAutoscroll(const pp::Point& mouse_pos);
|
||||
|
||||
void ConfigureNumberImageGenerator();
|
||||
|
||||
NumberImageGenerator* number_image_generator();
|
||||
|
||||
int GetScaled(int x) const;
|
||||
|
||||
pp::ImageData image_data_;
|
||||
// Used when the plugin is embedded in a page and we have to create the loader
|
||||
// ourself.
|
||||
pp::CompletionCallbackFactory<Instance> loader_factory_;
|
||||
pp::URLLoader embed_loader_;
|
||||
pp::URLLoader embed_preview_loader_;
|
||||
|
||||
scoped_ptr<pp::Scrollbar_Dev> h_scrollbar_;
|
||||
scoped_ptr<pp::Scrollbar_Dev> v_scrollbar_;
|
||||
int32 valid_v_range_;
|
||||
|
||||
PP_CursorType_Dev cursor_; // The current cursor.
|
||||
|
||||
// Used when selecting and dragging beyond the visible portion, in which case
|
||||
// we want to scroll the document.
|
||||
bool timer_pending_;
|
||||
pp::MouseInputEvent last_mouse_event_;
|
||||
pp::CompletionCallbackFactory<Instance> timer_factory_;
|
||||
uint32 current_timer_id_;
|
||||
|
||||
// Size, in pixels, of plugin rectangle.
|
||||
pp::Size plugin_size_;
|
||||
// Size, in DIPs, of plugin rectangle.
|
||||
pp::Size plugin_dip_size_;
|
||||
// Remaining area, in pixels, to render the pdf in after accounting for
|
||||
// scrollbars/toolbars and horizontal centering.
|
||||
pp::Rect available_area_;
|
||||
// Size of entire document in pixels (i.e. if each page is 800 pixels high and
|
||||
// there are 10 pages, the height will be 8000).
|
||||
pp::Size document_size_;
|
||||
|
||||
double zoom_; // Current zoom factor.
|
||||
|
||||
float device_scale_; // Current device scale factor.
|
||||
bool printing_enabled_;
|
||||
bool hidpi_enabled_;
|
||||
// True if the plugin is full-page.
|
||||
bool full_;
|
||||
// Zooming mode (none, fit to width, fit to height)
|
||||
ZoomMode zoom_mode_;
|
||||
|
||||
// If true, this means we told the RenderView that we're starting a network
|
||||
// request so that it can start the throbber. We will tell it again once the
|
||||
// document finishes loading.
|
||||
bool did_call_start_loading_;
|
||||
|
||||
// Hold off on painting invalidated requests while this flag is true.
|
||||
bool dont_paint_;
|
||||
|
||||
// Indicates if plugin is in autoscroll mode.
|
||||
bool is_autoscroll_;
|
||||
// Rect for autoscroll anchor.
|
||||
pp::Rect autoscroll_rect_;
|
||||
// Image of the autoscroll anchor and its background.
|
||||
pp::ImageData autoscroll_anchor_;
|
||||
// Autoscrolling deltas in pixels.
|
||||
int autoscroll_x_;
|
||||
int autoscroll_y_;
|
||||
|
||||
// Thickness of a scrollbar.
|
||||
int scrollbar_thickness_;
|
||||
|
||||
// Reserved thickness of a scrollbar. This is how much space the scrollbar
|
||||
// takes from the available area. 0 for overlay.
|
||||
int scrollbar_reserved_thickness_;
|
||||
|
||||
// Used to remember which toolbar is in use
|
||||
const ToolbarButtonInfo* current_tb_info_;
|
||||
size_t current_tb_info_size_;
|
||||
|
||||
PaintManager paint_manager_;
|
||||
|
||||
struct BackgroundPart {
|
||||
pp::Rect location;
|
||||
unsigned int color;
|
||||
};
|
||||
std::vector<BackgroundPart> background_parts_;
|
||||
|
||||
struct PrintSettings {
|
||||
PrintSettings() {
|
||||
Clear();
|
||||
}
|
||||
void Clear() {
|
||||
is_printing = false;
|
||||
print_pages_called_ = false;
|
||||
memset(&pepper_print_settings, 0, sizeof(pepper_print_settings));
|
||||
}
|
||||
// This is set to true when PrintBegin is called and false when PrintEnd is
|
||||
// called.
|
||||
bool is_printing;
|
||||
// To know whether this was an actual print operation, so we don't double
|
||||
// count UMA logging.
|
||||
bool print_pages_called_;
|
||||
PP_PrintSettings_Dev pepper_print_settings;
|
||||
};
|
||||
|
||||
PrintSettings print_settings_;
|
||||
|
||||
scoped_ptr<PDFEngine> engine_;
|
||||
|
||||
// This engine is used to render the individual preview page data. This is
|
||||
// used only in print preview mode. This will use |PreviewModeClient|
|
||||
// interface which has very limited access to the pp::Instance.
|
||||
scoped_ptr<PDFEngine> preview_engine_;
|
||||
|
||||
std::string url_;
|
||||
|
||||
scoped_ptr<FadingControls> toolbar_;
|
||||
ThumbnailControl thumbnails_;
|
||||
ProgressControl progress_bar_;
|
||||
uint32 delayed_progress_timer_id_;
|
||||
PageIndicator page_indicator_;
|
||||
|
||||
// Used for creating images from numbers.
|
||||
scoped_ptr<NumberImageGenerator> number_image_generator_;
|
||||
|
||||
// Used for submitting forms.
|
||||
pp::CompletionCallbackFactory<Instance> form_factory_;
|
||||
pp::URLLoader form_loader_;
|
||||
|
||||
// Used for printing without re-entrancy issues.
|
||||
pp::CompletionCallbackFactory<Instance> print_callback_factory_;
|
||||
|
||||
// True if we haven't painted the plugin viewport yet.
|
||||
bool first_paint_;
|
||||
|
||||
// True when we've painted at least one page from the document.
|
||||
bool painted_first_page_;
|
||||
|
||||
// True if we should display page indicator, false otherwise
|
||||
bool show_page_indicator_;
|
||||
|
||||
// Callback when the document load completes.
|
||||
pp::Var on_load_callback_;
|
||||
pp::Var on_scroll_callback_;
|
||||
pp::Var on_plugin_size_changed_callback_;
|
||||
|
||||
DocumentLoadState document_load_state_;
|
||||
DocumentLoadState preview_document_load_state_;
|
||||
|
||||
// JavaScript interface to control this instance.
|
||||
// This wraps a PDFScriptableObject in a pp::Var.
|
||||
pp::VarPrivate instance_object_;
|
||||
|
||||
// Used so that we only tell the browser once about an unsupported feature, to
|
||||
// avoid the infobar going up more than once.
|
||||
bool told_browser_about_unsupported_feature_;
|
||||
|
||||
// Keeps track of which unsupported features we reported, so we avoid spamming
|
||||
// the stats if a feature shows up many times per document.
|
||||
std::set<std::string> unsupported_features_reported_;
|
||||
|
||||
// Number of pages in print preview mode, 0 if not in print preview mode.
|
||||
int print_preview_page_count_;
|
||||
std::vector<int> print_preview_page_numbers_;
|
||||
|
||||
// Used to manage loaded print preview page information. A |PreviewPageInfo|
|
||||
// consists of data source url string and the page index in the destination
|
||||
// document.
|
||||
typedef std::pair<std::string, int> PreviewPageInfo;
|
||||
std::queue<PreviewPageInfo> preview_pages_info_;
|
||||
|
||||
// Used to signal the browser about focus changes to trigger the OSK.
|
||||
// TODO(abodenha@chromium.org) Implement full IME support in the plugin.
|
||||
// http://crbug.com/132565
|
||||
scoped_ptr<pp::TextInput_Dev> text_input_;
|
||||
};
|
||||
|
||||
// This implements the JavaScript class entrypoint for the plugin instance.
|
||||
// This class is just a thin wrapper. It delegates relevant methods to Instance.
|
||||
class PDFScriptableObject : public pp::deprecated::ScriptableObject {
|
||||
public:
|
||||
explicit PDFScriptableObject(Instance* instance);
|
||||
virtual ~PDFScriptableObject();
|
||||
|
||||
// pp::deprecated::ScriptableObject implementation.
|
||||
virtual bool HasMethod(const pp::Var& method, pp::Var* exception);
|
||||
virtual pp::Var Call(const pp::Var& method,
|
||||
const std::vector<pp::Var>& args,
|
||||
pp::Var* exception);
|
||||
|
||||
private:
|
||||
Instance* instance_;
|
||||
};
|
||||
|
||||
} // namespace chrome_pdf
|
||||
|
||||
#endif // PDF_INSTANCE_H_
|
10
pdf/libpdf.map
Normal file
10
pdf/libpdf.map
Normal file
@ -0,0 +1,10 @@
|
||||
{
|
||||
global:
|
||||
GetPDFDocInfo;
|
||||
PPP_GetInterface;
|
||||
PPP_InitializeModule;
|
||||
PPP_ShutdownModule;
|
||||
RenderPDFPageToBitmap;
|
||||
local:
|
||||
*;
|
||||
};
|
81
pdf/number_image_generator.cc
Normal file
81
pdf/number_image_generator.cc
Normal file
@ -0,0 +1,81 @@
|
||||
// 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/number_image_generator.h"
|
||||
|
||||
#include "base/logging.h"
|
||||
#include "base/strings/string_util.h"
|
||||
#include "pdf/draw_utils.h"
|
||||
#include "pdf/instance.h"
|
||||
|
||||
namespace chrome_pdf {
|
||||
|
||||
const int kPageNumberSeparator = 0;
|
||||
const int kPageNumberOriginX = 8;
|
||||
const int kPageNumberOriginY = 4;
|
||||
|
||||
NumberImageGenerator::NumberImageGenerator(Instance* instance)
|
||||
: instance_(instance),
|
||||
device_scale_(1.0f) {
|
||||
}
|
||||
|
||||
NumberImageGenerator::~NumberImageGenerator() {
|
||||
}
|
||||
|
||||
void NumberImageGenerator::Configure(const pp::ImageData& number_background,
|
||||
const std::vector<pp::ImageData>& number_images, float device_scale) {
|
||||
number_background_ = number_background;
|
||||
number_images_ = number_images;
|
||||
device_scale_ = device_scale;
|
||||
}
|
||||
|
||||
void NumberImageGenerator::GenerateImage(
|
||||
int page_number, pp::ImageData* image) {
|
||||
char buffer[12];
|
||||
base::snprintf(buffer, sizeof(buffer), "%u", page_number);
|
||||
int extra_width = 0;
|
||||
DCHECK(number_images_.size() >= 10);
|
||||
DCHECK(!number_background_.is_null());
|
||||
for (size_t i = 1; i < strlen(buffer); ++i) {
|
||||
int index = buffer[i] - '0';
|
||||
extra_width += number_images_[index].size().width();
|
||||
extra_width += static_cast<int>(kPageNumberSeparator * device_scale_);
|
||||
}
|
||||
|
||||
*image = pp::ImageData(
|
||||
instance_,
|
||||
PP_IMAGEDATAFORMAT_BGRA_PREMUL,
|
||||
pp::Size(number_background_.size().width() + extra_width,
|
||||
number_background_.size().height()),
|
||||
false);
|
||||
|
||||
int stretch_point = number_background_.size().width() / 2;
|
||||
|
||||
pp::Rect src_rc(0, 0, stretch_point, number_background_.size().height());
|
||||
pp::Rect dest_rc(src_rc);
|
||||
CopyImage(number_background_, src_rc, image, dest_rc, false);
|
||||
src_rc.Offset(number_background_.size().width() - stretch_point, 0);
|
||||
dest_rc.Offset(image->size().width() - stretch_point, 0);
|
||||
CopyImage(number_background_, src_rc, image, dest_rc, false);
|
||||
src_rc = pp::Rect(stretch_point, 0, 1, number_background_.size().height());
|
||||
dest_rc = src_rc;
|
||||
dest_rc.set_width(extra_width + 1);
|
||||
CopyImage(number_background_, src_rc, image, dest_rc, true);
|
||||
|
||||
pp::Point origin(static_cast<int>(kPageNumberOriginX * device_scale_),
|
||||
static_cast<int>(kPageNumberOriginY * device_scale_));
|
||||
for (size_t i = 0; i < strlen(buffer); ++i) {
|
||||
int index = buffer[i] - '0';
|
||||
CopyImage(
|
||||
number_images_[index],
|
||||
pp::Rect(pp::Point(), number_images_[index].size()),
|
||||
image, pp::Rect(origin, number_images_[index].size()), false);
|
||||
origin += pp::Point(
|
||||
number_images_[index].size().width() +
|
||||
static_cast<int>(kPageNumberSeparator * device_scale_), 0);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace chrome_pdf
|
||||
|
37
pdf/number_image_generator.h
Normal file
37
pdf/number_image_generator.h
Normal file
@ -0,0 +1,37 @@
|
||||
// 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.
|
||||
|
||||
#ifndef PDF_NUMBER_IMAGE_GENERATOR_H
|
||||
#define PDF_NUMBER_IMAGE_GENERATOR_H
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include "ppapi/cpp/image_data.h"
|
||||
|
||||
namespace chrome_pdf {
|
||||
|
||||
class Instance;
|
||||
|
||||
class NumberImageGenerator {
|
||||
public:
|
||||
explicit NumberImageGenerator(Instance* instance);
|
||||
virtual ~NumberImageGenerator();
|
||||
|
||||
void Configure(const pp::ImageData& number_background,
|
||||
const std::vector<pp::ImageData>& number_images,
|
||||
float device_scale);
|
||||
|
||||
void GenerateImage(int page_number, pp::ImageData* image);
|
||||
|
||||
private:
|
||||
Instance* instance_;
|
||||
pp::ImageData number_background_;
|
||||
std::vector<pp::ImageData> number_images_;
|
||||
float device_scale_;
|
||||
};
|
||||
|
||||
} // namespace chrome_pdf
|
||||
|
||||
#endif // PDF_NUMBER_IMAGE_GENERATOR_H
|
||||
|
1362
pdf/out_of_process_instance.cc
Normal file
1362
pdf/out_of_process_instance.cc
Normal file
File diff suppressed because it is too large
Load Diff
338
pdf/out_of_process_instance.h
Normal file
338
pdf/out_of_process_instance.h
Normal file
@ -0,0 +1,338 @@
|
||||
// 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.
|
||||
|
||||
#ifndef PDF_OUT_OF_PROCESS_INSTANCE_H_
|
||||
#define PDF_OUT_OF_PROCESS_INSTANCE_H_
|
||||
|
||||
#include <queue>
|
||||
#include <set>
|
||||
#include <string>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
#include "base/memory/scoped_ptr.h"
|
||||
#include "pdf/paint_manager.h"
|
||||
#include "pdf/pdf_engine.h"
|
||||
#include "pdf/preview_mode_client.h"
|
||||
|
||||
#include "ppapi/c/private/ppb_pdf.h"
|
||||
#include "ppapi/cpp/dev/printing_dev.h"
|
||||
#include "ppapi/cpp/dev/scriptable_object_deprecated.h"
|
||||
#include "ppapi/cpp/dev/selection_dev.h"
|
||||
#include "ppapi/cpp/graphics_2d.h"
|
||||
#include "ppapi/cpp/image_data.h"
|
||||
#include "ppapi/cpp/input_event.h"
|
||||
#include "ppapi/cpp/private/find_private.h"
|
||||
#include "ppapi/cpp/private/instance_private.h"
|
||||
#include "ppapi/cpp/private/uma_private.h"
|
||||
#include "ppapi/cpp/private/var_private.h"
|
||||
#include "ppapi/cpp/url_loader.h"
|
||||
#include "ppapi/utility/completion_callback_factory.h"
|
||||
|
||||
namespace pp {
|
||||
class TextInput_Dev;
|
||||
}
|
||||
|
||||
namespace chrome_pdf {
|
||||
|
||||
class OutOfProcessInstance : public pp::InstancePrivate,
|
||||
public pp::Find_Private,
|
||||
public pp::Printing_Dev,
|
||||
public pp::Selection_Dev,
|
||||
public PaintManager::Client,
|
||||
public PDFEngine::Client,
|
||||
public PreviewModeClient::Client {
|
||||
public:
|
||||
explicit OutOfProcessInstance(PP_Instance instance);
|
||||
virtual ~OutOfProcessInstance();
|
||||
|
||||
// pp::Instance implementation.
|
||||
virtual bool Init(uint32_t argc,
|
||||
const char* argn[],
|
||||
const char* argv[]) OVERRIDE;
|
||||
virtual void HandleMessage(const pp::Var& message) OVERRIDE;
|
||||
virtual bool HandleInputEvent(const pp::InputEvent& event) OVERRIDE;
|
||||
virtual void DidChangeView(const pp::View& view) OVERRIDE;
|
||||
virtual pp::Var GetInstanceObject() OVERRIDE;
|
||||
|
||||
// pp::Find_Private implementation.
|
||||
virtual bool StartFind(const std::string& text, bool case_sensitive) OVERRIDE;
|
||||
virtual void SelectFindResult(bool forward) OVERRIDE;
|
||||
virtual void StopFind() OVERRIDE;
|
||||
|
||||
// pp::PaintManager::Client implementation.
|
||||
virtual void OnPaint(const std::vector<pp::Rect>& paint_rects,
|
||||
std::vector<PaintManager::ReadyRect>* ready,
|
||||
std::vector<pp::Rect>* pending) OVERRIDE;
|
||||
|
||||
// pp::Printing_Dev implementation.
|
||||
virtual uint32_t QuerySupportedPrintOutputFormats() OVERRIDE;
|
||||
virtual int32_t PrintBegin(
|
||||
const PP_PrintSettings_Dev& print_settings) OVERRIDE;
|
||||
virtual pp::Resource PrintPages(
|
||||
const PP_PrintPageNumberRange_Dev* page_ranges,
|
||||
uint32_t page_range_count) OVERRIDE;
|
||||
virtual void PrintEnd() OVERRIDE;
|
||||
virtual bool IsPrintScalingDisabled() OVERRIDE;
|
||||
|
||||
// pp::Private implementation.
|
||||
virtual pp::Var GetLinkAtPosition(const pp::Point& point);
|
||||
|
||||
// PPP_Selection_Dev implementation.
|
||||
virtual pp::Var GetSelectedText(bool html) OVERRIDE;
|
||||
|
||||
void FlushCallback(int32_t result);
|
||||
void DidOpen(int32_t result);
|
||||
void DidOpenPreview(int32_t result);
|
||||
|
||||
// Called when the timer is fired.
|
||||
void OnClientTimerFired(int32_t id);
|
||||
|
||||
// Called to print without re-entrancy issues.
|
||||
void OnPrint(int32_t);
|
||||
|
||||
// PDFEngine::Client implementation.
|
||||
virtual void DocumentSizeUpdated(const pp::Size& size);
|
||||
virtual void Invalidate(const pp::Rect& rect);
|
||||
virtual void Scroll(const pp::Point& point);
|
||||
virtual void ScrollToX(int position);
|
||||
virtual void ScrollToY(int position);
|
||||
virtual void ScrollToPage(int page);
|
||||
virtual void NavigateTo(const std::string& url, bool open_in_new_tab);
|
||||
virtual void UpdateCursor(PP_CursorType_Dev cursor);
|
||||
virtual void UpdateTickMarks(const std::vector<pp::Rect>& tickmarks);
|
||||
virtual void NotifyNumberOfFindResultsChanged(int total, bool final_result);
|
||||
virtual void NotifySelectedFindResultChanged(int current_find_index);
|
||||
virtual void GetDocumentPassword(
|
||||
pp::CompletionCallbackWithOutput<pp::Var> callback);
|
||||
virtual void Alert(const std::string& message);
|
||||
virtual bool Confirm(const std::string& message);
|
||||
virtual std::string Prompt(const std::string& question,
|
||||
const std::string& default_answer);
|
||||
virtual std::string GetURL();
|
||||
virtual void Email(const std::string& to,
|
||||
const std::string& cc,
|
||||
const std::string& bcc,
|
||||
const std::string& subject,
|
||||
const std::string& body);
|
||||
virtual void Print();
|
||||
virtual void SubmitForm(const std::string& url,
|
||||
const void* data,
|
||||
int length);
|
||||
virtual std::string ShowFileSelectionDialog();
|
||||
virtual pp::URLLoader CreateURLLoader();
|
||||
virtual void ScheduleCallback(int id, int delay_in_ms);
|
||||
virtual void SearchString(const base::char16* string,
|
||||
const base::char16* term,
|
||||
bool case_sensitive,
|
||||
std::vector<SearchStringResult>* results);
|
||||
virtual void DocumentPaintOccurred();
|
||||
virtual void DocumentLoadComplete(int page_count);
|
||||
virtual void DocumentLoadFailed();
|
||||
virtual pp::Instance* GetPluginInstance();
|
||||
virtual void DocumentHasUnsupportedFeature(const std::string& feature);
|
||||
virtual void DocumentLoadProgress(uint32 available, uint32 doc_size);
|
||||
virtual void FormTextFieldFocusChange(bool in_focus);
|
||||
virtual bool IsPrintPreview();
|
||||
|
||||
// PreviewModeClient::Client implementation.
|
||||
virtual void PreviewDocumentLoadComplete() OVERRIDE;
|
||||
virtual void PreviewDocumentLoadFailed() OVERRIDE;
|
||||
|
||||
// Helper functions for implementing PPP_PDF.
|
||||
void RotateClockwise();
|
||||
void RotateCounterclockwise();
|
||||
|
||||
private:
|
||||
void ResetRecentlySentFindUpdate(int32_t);
|
||||
|
||||
// Called whenever the plugin geometry changes to update the location of the
|
||||
// background parts, and notifies the pdf engine.
|
||||
void OnGeometryChanged(double old_zoom, float old_device_scale);
|
||||
|
||||
// Figures out the location of any background rectangles (i.e. those that
|
||||
// aren't painted by the PDF engine).
|
||||
void CalculateBackgroundParts();
|
||||
|
||||
// Computes document width/height in device pixels, based on current zoom and
|
||||
// device scale
|
||||
int GetDocumentPixelWidth() const;
|
||||
int GetDocumentPixelHeight() const;
|
||||
|
||||
// Draws a rectangle with the specified dimensions and color in our buffer.
|
||||
void FillRect(const pp::Rect& rect, unsigned int color);
|
||||
|
||||
void LoadUrl(const std::string& url);
|
||||
void LoadPreviewUrl(const std::string& url);
|
||||
void LoadUrlInternal(const std::string& url, pp::URLLoader* loader,
|
||||
void (OutOfProcessInstance::* method)(int32_t));
|
||||
|
||||
// Creates a URL loader and allows it to access all urls, i.e. not just the
|
||||
// frame's origin.
|
||||
pp::URLLoader CreateURLLoaderInternal();
|
||||
|
||||
// Figure out the initial page to display based on #page=N and #nameddest=foo
|
||||
// in the |url_|.
|
||||
// Returns -1 if there is no valid fragment. The returned value is 0-based,
|
||||
// whereas page=N is 1-based.
|
||||
int GetInitialPage(const std::string& url);
|
||||
|
||||
void FormDidOpen(int32_t result);
|
||||
|
||||
std::string GetLocalizedString(PP_ResourceString id);
|
||||
|
||||
void UserMetricsRecordAction(const std::string& action);
|
||||
|
||||
enum DocumentLoadState {
|
||||
LOAD_STATE_LOADING,
|
||||
LOAD_STATE_COMPLETE,
|
||||
LOAD_STATE_FAILED,
|
||||
};
|
||||
|
||||
// Set new zoom scale.
|
||||
void SetZoom(double scale);
|
||||
|
||||
// Reduces the document to 1 page and appends |print_preview_page_count_|
|
||||
// blank pages to the document for print preview.
|
||||
void AppendBlankPrintPreviewPages();
|
||||
|
||||
// Process the preview page data information. |src_url| specifies the preview
|
||||
// page data location. The |src_url| is in the format:
|
||||
// chrome://print/id/page_number/print.pdf
|
||||
// |dst_page_index| specifies the blank page index that needs to be replaced
|
||||
// with the new page data.
|
||||
void ProcessPreviewPageInfo(const std::string& src_url, int dst_page_index);
|
||||
// Load the next available preview page into the blank page.
|
||||
void LoadAvailablePreviewPage();
|
||||
|
||||
pp::ImageData image_data_;
|
||||
// Used when the plugin is embedded in a page and we have to create the loader
|
||||
// ourself.
|
||||
pp::CompletionCallbackFactory<OutOfProcessInstance> loader_factory_;
|
||||
pp::URLLoader embed_loader_;
|
||||
pp::URLLoader embed_preview_loader_;
|
||||
|
||||
PP_CursorType_Dev cursor_; // The current cursor.
|
||||
|
||||
pp::CompletionCallbackFactory<OutOfProcessInstance> timer_factory_;
|
||||
|
||||
// Size, in pixels, of plugin rectangle.
|
||||
pp::Size plugin_size_;
|
||||
// Size, in DIPs, of plugin rectangle.
|
||||
pp::Size plugin_dip_size_;
|
||||
// Remaining area, in pixels, to render the pdf in after accounting for
|
||||
// horizontal centering.
|
||||
pp::Rect available_area_;
|
||||
// Size of entire document in pixels (i.e. if each page is 800 pixels high and
|
||||
// there are 10 pages, the height will be 8000).
|
||||
pp::Size document_size_;
|
||||
|
||||
double zoom_; // Current zoom factor.
|
||||
|
||||
float device_scale_; // Current device scale factor.
|
||||
bool printing_enabled_;
|
||||
// True if the plugin is full-page.
|
||||
bool full_;
|
||||
|
||||
PaintManager paint_manager_;
|
||||
|
||||
struct BackgroundPart {
|
||||
pp::Rect location;
|
||||
unsigned int color;
|
||||
};
|
||||
std::vector<BackgroundPart> background_parts_;
|
||||
|
||||
struct PrintSettings {
|
||||
PrintSettings() {
|
||||
Clear();
|
||||
}
|
||||
void Clear() {
|
||||
is_printing = false;
|
||||
print_pages_called_ = false;
|
||||
memset(&pepper_print_settings, 0, sizeof(pepper_print_settings));
|
||||
}
|
||||
// This is set to true when PrintBegin is called and false when PrintEnd is
|
||||
// called.
|
||||
bool is_printing;
|
||||
// To know whether this was an actual print operation, so we don't double
|
||||
// count UMA logging.
|
||||
bool print_pages_called_;
|
||||
PP_PrintSettings_Dev pepper_print_settings;
|
||||
};
|
||||
|
||||
PrintSettings print_settings_;
|
||||
|
||||
scoped_ptr<PDFEngine> engine_;
|
||||
|
||||
// This engine is used to render the individual preview page data. This is
|
||||
// used only in print preview mode. This will use |PreviewModeClient|
|
||||
// interface which has very limited access to the pp::Instance.
|
||||
scoped_ptr<PDFEngine> preview_engine_;
|
||||
|
||||
std::string url_;
|
||||
|
||||
// Used for submitting forms.
|
||||
pp::CompletionCallbackFactory<OutOfProcessInstance> form_factory_;
|
||||
pp::URLLoader form_loader_;
|
||||
|
||||
// Used for printing without re-entrancy issues.
|
||||
pp::CompletionCallbackFactory<OutOfProcessInstance> print_callback_factory_;
|
||||
|
||||
// True if we haven't painted the plugin viewport yet.
|
||||
bool first_paint_;
|
||||
|
||||
DocumentLoadState document_load_state_;
|
||||
DocumentLoadState preview_document_load_state_;
|
||||
|
||||
// JavaScript interface to control this instance.
|
||||
// This wraps a PDFScriptableObject in a pp::Var.
|
||||
pp::VarPrivate instance_object_;
|
||||
|
||||
// A UMA resource for histogram reporting.
|
||||
pp::UMAPrivate uma_;
|
||||
|
||||
// Used so that we only tell the browser once about an unsupported feature, to
|
||||
// avoid the infobar going up more than once.
|
||||
bool told_browser_about_unsupported_feature_;
|
||||
|
||||
// Keeps track of which unsupported features we reported, so we avoid spamming
|
||||
// the stats if a feature shows up many times per document.
|
||||
std::set<std::string> unsupported_features_reported_;
|
||||
|
||||
// Number of pages in print preview mode, 0 if not in print preview mode.
|
||||
int print_preview_page_count_;
|
||||
std::vector<int> print_preview_page_numbers_;
|
||||
|
||||
// Used to manage loaded print preview page information. A |PreviewPageInfo|
|
||||
// consists of data source url string and the page index in the destination
|
||||
// document.
|
||||
typedef std::pair<std::string, int> PreviewPageInfo;
|
||||
std::queue<PreviewPageInfo> preview_pages_info_;
|
||||
|
||||
// Used to signal the browser about focus changes to trigger the OSK.
|
||||
// TODO(abodenha@chromium.org) Implement full IME support in the plugin.
|
||||
// http://crbug.com/132565
|
||||
scoped_ptr<pp::TextInput_Dev> text_input_;
|
||||
|
||||
// The last document load progress value sent to the web page.
|
||||
double last_progress_sent_;
|
||||
|
||||
// Whether an update to the number of find results found was sent less than
|
||||
// |kFindResultCooldownMs| milliseconds ago.
|
||||
bool recently_sent_find_update_;
|
||||
|
||||
// The tickmarks.
|
||||
std::vector<pp::Rect> tickmarks_;
|
||||
|
||||
// Whether the plugin has received a viewport changed message. Nothing should
|
||||
// be painted until this is received.
|
||||
bool received_viewport_message_;
|
||||
|
||||
// The callback for receiving the password from the page.
|
||||
scoped_ptr<pp::CompletionCallbackWithOutput<pp::Var> > password_callback_;
|
||||
};
|
||||
|
||||
} // namespace chrome_pdf
|
||||
|
||||
#endif // PDF_OUT_OF_PROCESS_INSTANCE_H_
|
126
pdf/page_indicator.cc
Normal file
126
pdf/page_indicator.cc
Normal file
@ -0,0 +1,126 @@
|
||||
// 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/page_indicator.h"
|
||||
|
||||
#include "base/logging.h"
|
||||
#include "base/strings/string_util.h"
|
||||
#include "pdf/draw_utils.h"
|
||||
#include "pdf/number_image_generator.h"
|
||||
#include "pdf/resource_consts.h"
|
||||
|
||||
namespace chrome_pdf {
|
||||
|
||||
|
||||
PageIndicator::PageIndicator()
|
||||
: current_page_(0),
|
||||
splash_timeout_(kPageIndicatorSplashTimeoutMs),
|
||||
fade_timeout_(kPageIndicatorScrollFadeTimeoutMs),
|
||||
always_visible_(false) {
|
||||
}
|
||||
|
||||
PageIndicator::~PageIndicator() {
|
||||
}
|
||||
|
||||
bool PageIndicator::CreatePageIndicator(
|
||||
uint32 id,
|
||||
bool visible,
|
||||
Control::Owner* delegate,
|
||||
NumberImageGenerator* number_image_generator,
|
||||
bool always_visible) {
|
||||
number_image_generator_ = number_image_generator;
|
||||
always_visible_ = always_visible;
|
||||
|
||||
pp::Rect rc;
|
||||
bool res = Control::Create(id, rc, visible, delegate);
|
||||
return res;
|
||||
}
|
||||
|
||||
void PageIndicator::Configure(const pp::Point& origin,
|
||||
const pp::ImageData& background) {
|
||||
background_ = background;
|
||||
pp::Rect rc(origin, background_.size());
|
||||
Control::SetRect(rc, false);
|
||||
}
|
||||
|
||||
void PageIndicator::set_current_page(int current_page) {
|
||||
if (current_page_ < 0)
|
||||
return;
|
||||
|
||||
current_page_ = current_page;
|
||||
}
|
||||
|
||||
void PageIndicator::Paint(pp::ImageData* image_data, const pp::Rect& rc) {
|
||||
if (!visible())
|
||||
return;
|
||||
|
||||
pp::Rect draw_rc = rc.Intersect(rect());
|
||||
if (draw_rc.IsEmpty())
|
||||
return;
|
||||
|
||||
// Copying the background image to a temporary buffer.
|
||||
pp::ImageData buffer(owner()->GetInstance(), background_.format(),
|
||||
background_.size(), false);
|
||||
CopyImage(background_, pp::Rect(background_.size()),
|
||||
&buffer, pp::Rect(background_.size()), false);
|
||||
|
||||
// Creating the page number image.
|
||||
pp::ImageData page_number_image;
|
||||
number_image_generator_->GenerateImage(current_page_, &page_number_image);
|
||||
|
||||
pp::Point origin2(
|
||||
(buffer.size().width() - page_number_image.size().width()) / 2.5,
|
||||
(buffer.size().height() - page_number_image.size().height()) / 2);
|
||||
|
||||
// Drawing page number image on the buffer.
|
||||
if (origin2.x() > 0 && origin2.y() > 0) {
|
||||
CopyImage(page_number_image,
|
||||
pp::Rect(pp::Point(), page_number_image.size()),
|
||||
&buffer,
|
||||
pp::Rect(origin2, page_number_image.size()),
|
||||
false);
|
||||
}
|
||||
|
||||
// Drawing the buffer.
|
||||
pp::Point origin = draw_rc.point();
|
||||
draw_rc.Offset(-rect().x(), -rect().y());
|
||||
AlphaBlend(buffer, draw_rc, image_data, origin, transparency());
|
||||
}
|
||||
|
||||
void PageIndicator::OnTimerFired(uint32 timer_id) {
|
||||
FadingControl::OnTimerFired(timer_id);
|
||||
if (timer_id == fade_out_timer_id_) {
|
||||
Fade(false, fade_timeout_);
|
||||
}
|
||||
}
|
||||
|
||||
void PageIndicator::ResetFadeOutTimer() {
|
||||
fade_out_timer_id_ =
|
||||
owner()->ScheduleTimer(id(), splash_timeout_);
|
||||
}
|
||||
|
||||
void PageIndicator::OnFadeInComplete() {
|
||||
if (!always_visible_)
|
||||
ResetFadeOutTimer();
|
||||
}
|
||||
|
||||
void PageIndicator::Splash() {
|
||||
Splash(kPageIndicatorSplashTimeoutMs, kPageIndicatorScrollFadeTimeoutMs);
|
||||
}
|
||||
|
||||
void PageIndicator::Splash(uint32 splash_timeout, uint32 fade_timeout) {
|
||||
splash_timeout_ = splash_timeout;
|
||||
fade_timeout_ = fade_timeout;
|
||||
if (!always_visible_)
|
||||
fade_out_timer_id_ = 0;
|
||||
Fade(true, fade_timeout_);
|
||||
}
|
||||
|
||||
int PageIndicator::GetYPosition(
|
||||
int vertical_scrollbar_y, int document_height, int plugin_height) {
|
||||
double percent = static_cast<double>(vertical_scrollbar_y) / document_height;
|
||||
return (plugin_height - rect().height()) * percent;
|
||||
}
|
||||
|
||||
} // namespace chrome_pdf
|
72
pdf/page_indicator.h
Normal file
72
pdf/page_indicator.h
Normal file
@ -0,0 +1,72 @@
|
||||
// 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.
|
||||
|
||||
#ifndef PDF_PAGE_INDICATOR_H_
|
||||
#define PDF_PAGE_INDICATOR_H_
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "pdf/control.h"
|
||||
#include "pdf/fading_control.h"
|
||||
#include "ppapi/cpp/image_data.h"
|
||||
#include "ppapi/cpp/point.h"
|
||||
#include "ppapi/cpp/rect.h"
|
||||
|
||||
namespace chrome_pdf {
|
||||
|
||||
class NumberImageGenerator;
|
||||
|
||||
const uint32 kPageIndicatorScrollFadeTimeoutMs = 240;
|
||||
const uint32 kPageIndicatorInitialFadeTimeoutMs = 960;
|
||||
const uint32 kPageIndicatorSplashTimeoutMs = 2000;
|
||||
|
||||
class PageIndicator : public FadingControl {
|
||||
public:
|
||||
PageIndicator();
|
||||
virtual ~PageIndicator();
|
||||
virtual bool CreatePageIndicator(
|
||||
uint32 id,
|
||||
bool visible,
|
||||
Control::Owner* delegate,
|
||||
NumberImageGenerator* number_image_generator,
|
||||
bool always_visible);
|
||||
|
||||
void Configure(const pp::Point& origin, const pp::ImageData& background);
|
||||
|
||||
int current_page() const { return current_page_; }
|
||||
void set_current_page(int current_page);
|
||||
|
||||
virtual void Splash();
|
||||
void Splash(uint32 splash_timeout, uint32 page_timeout);
|
||||
|
||||
// Returns the y position where the page indicator should be drawn given the
|
||||
// position of the scrollbar and the total document height and the plugin
|
||||
// height.
|
||||
int GetYPosition(
|
||||
int vertical_scrollbar_y, int document_height, int plugin_height);
|
||||
|
||||
// Control interface.
|
||||
virtual void Paint(pp::ImageData* image_data, const pp::Rect& rc);
|
||||
virtual void OnTimerFired(uint32 timer_id);
|
||||
|
||||
// FadingControl interface.
|
||||
virtual void OnFadeInComplete();
|
||||
|
||||
private:
|
||||
void ResetFadeOutTimer();
|
||||
|
||||
int current_page_;
|
||||
pp::ImageData background_;
|
||||
NumberImageGenerator* number_image_generator_;
|
||||
uint32 fade_out_timer_id_;
|
||||
uint32 splash_timeout_;
|
||||
uint32 fade_timeout_;
|
||||
|
||||
bool always_visible_;
|
||||
};
|
||||
|
||||
} // namespace chrome_pdf
|
||||
|
||||
#endif // PDF_PAGE_INDICATOR_H_
|
263
pdf/paint_aggregator.cc
Normal file
263
pdf/paint_aggregator.cc
Normal file
@ -0,0 +1,263 @@
|
||||
// Copyright (c) 2010 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/paint_aggregator.h"
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
#include "base/logging.h"
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// ALGORITHM NOTES
|
||||
//
|
||||
// We attempt to maintain a scroll rect in the presence of invalidations that
|
||||
// are contained within the scroll rect. If an invalidation crosses a scroll
|
||||
// rect, then we just treat the scroll rect as an invalidation rect.
|
||||
//
|
||||
// For invalidations performed prior to scrolling and contained within the
|
||||
// scroll rect, we offset the invalidation rects to account for the fact that
|
||||
// the consumer will perform scrolling before painting.
|
||||
//
|
||||
// We only support scrolling along one axis at a time. A diagonal scroll will
|
||||
// therefore be treated as an invalidation.
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
PaintAggregator::PaintUpdate::PaintUpdate() {
|
||||
}
|
||||
|
||||
PaintAggregator::PaintUpdate::~PaintUpdate() {
|
||||
}
|
||||
|
||||
PaintAggregator::InternalPaintUpdate::InternalPaintUpdate() :
|
||||
synthesized_scroll_damage_rect_(false) {
|
||||
}
|
||||
|
||||
PaintAggregator::InternalPaintUpdate::~InternalPaintUpdate() {
|
||||
}
|
||||
|
||||
pp::Rect PaintAggregator::InternalPaintUpdate::GetScrollDamage() const {
|
||||
// Should only be scrolling in one direction at a time.
|
||||
DCHECK(!(scroll_delta.x() && scroll_delta.y()));
|
||||
|
||||
pp::Rect damaged_rect;
|
||||
|
||||
// Compute the region we will expose by scrolling, and paint that into a
|
||||
// shared memory section.
|
||||
if (scroll_delta.x()) {
|
||||
int32_t dx = scroll_delta.x();
|
||||
damaged_rect.set_y(scroll_rect.y());
|
||||
damaged_rect.set_height(scroll_rect.height());
|
||||
if (dx > 0) {
|
||||
damaged_rect.set_x(scroll_rect.x());
|
||||
damaged_rect.set_width(dx);
|
||||
} else {
|
||||
damaged_rect.set_x(scroll_rect.right() + dx);
|
||||
damaged_rect.set_width(-dx);
|
||||
}
|
||||
} else {
|
||||
int32_t dy = scroll_delta.y();
|
||||
damaged_rect.set_x(scroll_rect.x());
|
||||
damaged_rect.set_width(scroll_rect.width());
|
||||
if (dy > 0) {
|
||||
damaged_rect.set_y(scroll_rect.y());
|
||||
damaged_rect.set_height(dy);
|
||||
} else {
|
||||
damaged_rect.set_y(scroll_rect.bottom() + dy);
|
||||
damaged_rect.set_height(-dy);
|
||||
}
|
||||
}
|
||||
|
||||
// In case the scroll offset exceeds the width/height of the scroll rect
|
||||
return scroll_rect.Intersect(damaged_rect);
|
||||
}
|
||||
|
||||
PaintAggregator::PaintAggregator() {
|
||||
}
|
||||
|
||||
bool PaintAggregator::HasPendingUpdate() const {
|
||||
return !update_.scroll_rect.IsEmpty() || !update_.paint_rects.empty();
|
||||
}
|
||||
|
||||
void PaintAggregator::ClearPendingUpdate() {
|
||||
update_ = InternalPaintUpdate();
|
||||
}
|
||||
|
||||
PaintAggregator::PaintUpdate PaintAggregator::GetPendingUpdate() {
|
||||
// Convert the internal paint update to the external one, which includes a
|
||||
// bit more precomputed info for the caller.
|
||||
PaintUpdate ret;
|
||||
ret.scroll_delta = update_.scroll_delta;
|
||||
ret.scroll_rect = update_.scroll_rect;
|
||||
ret.has_scroll = ret.scroll_delta.x() != 0 || ret.scroll_delta.y() != 0;
|
||||
|
||||
// Include the scroll damage (if any) in the paint rects.
|
||||
// Code invalidates damaged rect here, it pick it up from the list of paint
|
||||
// rects in the next block.
|
||||
if (ret.has_scroll && !update_.synthesized_scroll_damage_rect_) {
|
||||
update_.synthesized_scroll_damage_rect_ = true;
|
||||
pp::Rect scroll_damage = update_.GetScrollDamage();
|
||||
InvalidateRectInternal(scroll_damage, false);
|
||||
}
|
||||
|
||||
ret.paint_rects.reserve(update_.paint_rects.size() + 1);
|
||||
for (size_t i = 0; i < update_.paint_rects.size(); i++)
|
||||
ret.paint_rects.push_back(update_.paint_rects[i]);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void PaintAggregator::SetIntermediateResults(
|
||||
const std::vector<ReadyRect>& ready,
|
||||
const std::vector<pp::Rect>& pending) {
|
||||
update_.ready_rects.insert(
|
||||
update_.ready_rects.end(), ready.begin(), ready.end());
|
||||
update_.paint_rects = pending;
|
||||
}
|
||||
|
||||
std::vector<PaintAggregator::ReadyRect> PaintAggregator::GetReadyRects() const {
|
||||
return update_.ready_rects;
|
||||
}
|
||||
|
||||
void PaintAggregator::InvalidateRect(const pp::Rect& rect) {
|
||||
InvalidateRectInternal(rect, true);
|
||||
}
|
||||
|
||||
void PaintAggregator::ScrollRect(const pp::Rect& clip_rect,
|
||||
const pp::Point& amount) {
|
||||
// We only support scrolling along one axis at a time.
|
||||
if (amount.x() != 0 && amount.y() != 0) {
|
||||
InvalidateRect(clip_rect);
|
||||
return;
|
||||
}
|
||||
|
||||
// We can only scroll one rect at a time.
|
||||
if (!update_.scroll_rect.IsEmpty() && update_.scroll_rect != clip_rect) {
|
||||
InvalidateRect(clip_rect);
|
||||
return;
|
||||
}
|
||||
|
||||
// Again, we only support scrolling along one axis at a time. Make sure this
|
||||
// update doesn't scroll on a different axis than any existing one.
|
||||
if ((amount.x() && update_.scroll_delta.y()) ||
|
||||
(amount.y() && update_.scroll_delta.x())) {
|
||||
InvalidateRect(clip_rect);
|
||||
return;
|
||||
}
|
||||
|
||||
// The scroll rect is new or isn't changing (though the scroll amount may
|
||||
// be changing).
|
||||
update_.scroll_rect = clip_rect;
|
||||
update_.scroll_delta += amount;
|
||||
|
||||
// We might have just wiped out a pre-existing scroll.
|
||||
if (update_.scroll_delta == pp::Point()) {
|
||||
update_.scroll_rect = pp::Rect();
|
||||
return;
|
||||
}
|
||||
|
||||
// Adjust any paint rects that intersect the scroll. For the portion of the
|
||||
// paint that is inside the scroll area, move it by the scroll amount and
|
||||
// replace the existing paint with it. For the portion (if any) that is
|
||||
// outside the scroll, just invalidate it.
|
||||
std::vector<pp::Rect> leftover_rects;
|
||||
for (size_t i = 0; i < update_.paint_rects.size(); ++i) {
|
||||
if (!update_.scroll_rect.Intersects(update_.paint_rects[i]))
|
||||
continue;
|
||||
|
||||
pp::Rect intersection =
|
||||
update_.paint_rects[i].Intersect(update_.scroll_rect);
|
||||
pp::Rect rect = update_.paint_rects[i];
|
||||
while (!rect.IsEmpty()) {
|
||||
pp::Rect leftover = rect.Subtract(intersection);
|
||||
if (leftover.IsEmpty())
|
||||
break;
|
||||
// Don't want to call InvalidateRectInternal now since it'll modify
|
||||
// update_.paint_rects, so keep track of this and do it below.
|
||||
leftover_rects.push_back(leftover);
|
||||
rect = rect.Subtract(leftover);
|
||||
}
|
||||
|
||||
update_.paint_rects[i] = ScrollPaintRect(intersection, amount);
|
||||
|
||||
// The rect may have been scrolled out of view.
|
||||
if (update_.paint_rects[i].IsEmpty()) {
|
||||
update_.paint_rects.erase(update_.paint_rects.begin() + i);
|
||||
i--;
|
||||
}
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < leftover_rects.size(); ++i)
|
||||
InvalidateRectInternal(leftover_rects[i], false);
|
||||
|
||||
for (size_t i = 0; i < update_.ready_rects.size(); ++i) {
|
||||
if (update_.scroll_rect.Contains(update_.ready_rects[i].rect)) {
|
||||
update_.ready_rects[i].rect =
|
||||
ScrollPaintRect(update_.ready_rects[i].rect, amount);
|
||||
}
|
||||
}
|
||||
|
||||
if (update_.synthesized_scroll_damage_rect_) {
|
||||
pp::Rect damage = update_.GetScrollDamage();
|
||||
InvalidateRect(damage);
|
||||
}
|
||||
}
|
||||
|
||||
pp::Rect PaintAggregator::ScrollPaintRect(const pp::Rect& paint_rect,
|
||||
const pp::Point& amount) const {
|
||||
pp::Rect result = paint_rect;
|
||||
result.Offset(amount);
|
||||
result = update_.scroll_rect.Intersect(result);
|
||||
return result;
|
||||
}
|
||||
|
||||
void PaintAggregator::InvalidateScrollRect() {
|
||||
pp::Rect scroll_rect = update_.scroll_rect;
|
||||
update_.scroll_rect = pp::Rect();
|
||||
update_.scroll_delta = pp::Point();
|
||||
InvalidateRect(scroll_rect);
|
||||
}
|
||||
|
||||
void PaintAggregator::InvalidateRectInternal(const pp::Rect& rect_old,
|
||||
bool check_scroll) {
|
||||
pp::Rect rect = rect_old;
|
||||
// Check if any rects that are ready to be painted overlap.
|
||||
for (size_t i = 0; i < update_.ready_rects.size(); ++i) {
|
||||
const pp::Rect& existing_rect = update_.ready_rects[i].rect;
|
||||
if (rect.Intersects(existing_rect)) {
|
||||
// Re-invalidate in case the union intersects other paint rects.
|
||||
rect = existing_rect.Union(rect);
|
||||
update_.ready_rects.erase(update_.ready_rects.begin() + i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
bool add_paint = true;
|
||||
|
||||
// Combine overlapping paints using smallest bounding box.
|
||||
for (size_t i = 0; i < update_.paint_rects.size(); ++i) {
|
||||
const pp::Rect& existing_rect = update_.paint_rects[i];
|
||||
if (existing_rect.Contains(rect)) // Optimize out redundancy.
|
||||
add_paint = false;
|
||||
if (rect.Intersects(existing_rect) || rect.SharesEdgeWith(existing_rect)) {
|
||||
// Re-invalidate in case the union intersects other paint rects.
|
||||
pp::Rect combined_rect = existing_rect.Union(rect);
|
||||
update_.paint_rects.erase(update_.paint_rects.begin() + i);
|
||||
InvalidateRectInternal(combined_rect, check_scroll);
|
||||
add_paint = false;
|
||||
}
|
||||
}
|
||||
|
||||
if (add_paint) {
|
||||
// Add a non-overlapping paint.
|
||||
update_.paint_rects.push_back(rect);
|
||||
}
|
||||
|
||||
// If the new paint overlaps with a scroll, then also invalidate the rect in
|
||||
// its new position.
|
||||
if (check_scroll &&
|
||||
!update_.scroll_rect.IsEmpty() &&
|
||||
update_.scroll_rect.Intersects(rect)) {
|
||||
InvalidateRectInternal(ScrollPaintRect(rect, update_.scroll_delta), false);
|
||||
}
|
||||
}
|
130
pdf/paint_aggregator.h
Normal file
130
pdf/paint_aggregator.h
Normal file
@ -0,0 +1,130 @@
|
||||
// Copyright (c) 2010 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.
|
||||
|
||||
#ifndef PDF_PAINT_AGGREGATOR_H_
|
||||
#define PDF_PAINT_AGGREGATOR_H_
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include "ppapi/cpp/image_data.h"
|
||||
#include "ppapi/cpp/rect.h"
|
||||
#include "ppapi/cpp/rect.h"
|
||||
|
||||
// This class is responsible for aggregating multiple invalidation and scroll
|
||||
// commands to produce a scroll and repaint sequence. You can use this manually
|
||||
// to track your updates, but most applications will use the PaintManager to
|
||||
// additionally handle the necessary callbacks on top of the PaintAggregator
|
||||
// functionality.
|
||||
//
|
||||
// See http://code.google.com/p/ppapi/wiki/2DPaintingModel
|
||||
class PaintAggregator {
|
||||
public:
|
||||
// Stores information about a rectangle that has finished painting. The
|
||||
// PaintManager will paint it only when everything else on the screen is also
|
||||
// ready.
|
||||
struct ReadyRect {
|
||||
pp::Point offset;
|
||||
pp::Rect rect;
|
||||
pp::ImageData image_data;
|
||||
};
|
||||
|
||||
struct PaintUpdate {
|
||||
PaintUpdate();
|
||||
~PaintUpdate();
|
||||
|
||||
// True if there is a scroll applied. This indicates that the scroll delta
|
||||
// and scroll_rect are nonzero (just as a convenience).
|
||||
bool has_scroll;
|
||||
|
||||
// The amount to scroll by. Either the X or Y may be nonzero to indicate a
|
||||
// scroll in that direction, but there will never be a scroll in both
|
||||
// directions at the same time (this will be converted to a paint of the
|
||||
// region instead).
|
||||
//
|
||||
// If there is no scroll, this will be (0, 0).
|
||||
pp::Point scroll_delta;
|
||||
|
||||
// The rectangle that should be scrolled by the scroll_delta. If there is no
|
||||
// scroll, this will be (0, 0, 0, 0). We only track one scroll command at
|
||||
// once. If there are multiple ones, they will be converted to invalidates.
|
||||
pp::Rect scroll_rect;
|
||||
|
||||
// A list of all the individual dirty rectangles. This is an aggregated list
|
||||
// of all invalidate calls. Different rectangles may be unified to produce a
|
||||
// minimal list with no overlap that is more efficient to paint. This list
|
||||
// also contains the region exposed by any scroll command.
|
||||
std::vector<pp::Rect> paint_rects;
|
||||
};
|
||||
|
||||
PaintAggregator();
|
||||
|
||||
// There is a PendingUpdate if InvalidateRect or ScrollRect were called and
|
||||
// ClearPendingUpdate was not called.
|
||||
bool HasPendingUpdate() const;
|
||||
void ClearPendingUpdate();
|
||||
|
||||
PaintUpdate GetPendingUpdate();
|
||||
|
||||
// Sets the result of a call to the plugin to paint. This includes rects that
|
||||
// are finished painting (ready), and ones that are still in-progress
|
||||
// (pending).
|
||||
void SetIntermediateResults(const std::vector<ReadyRect>& ready,
|
||||
const std::vector<pp::Rect>& pending);
|
||||
|
||||
// Returns the rectangles that are ready to be painted.
|
||||
std::vector<ReadyRect> GetReadyRects() const;
|
||||
|
||||
// The given rect should be repainted.
|
||||
void InvalidateRect(const pp::Rect& rect);
|
||||
|
||||
// The given rect should be scrolled by the given amounts.
|
||||
void ScrollRect(const pp::Rect& clip_rect, const pp::Point& amount);
|
||||
|
||||
private:
|
||||
// This structure is an internal version of PaintUpdate. It's different in
|
||||
// two respects:
|
||||
//
|
||||
// - The scroll damange (area exposed by the scroll operation, if any) is
|
||||
// maintained separately from the dirty rects generated by calling
|
||||
// InvalidateRect. We need to know this distinction for some operations.
|
||||
//
|
||||
// - The paint bounds union is computed on the fly so we don't have to keep
|
||||
// a rectangle up-to-date as we do different operations.
|
||||
class InternalPaintUpdate {
|
||||
public:
|
||||
InternalPaintUpdate();
|
||||
~InternalPaintUpdate();
|
||||
|
||||
// Computes the rect damaged by scrolling within |scroll_rect| by
|
||||
// |scroll_delta|. This rect must be repainted. It is not included in
|
||||
// paint_rects.
|
||||
pp::Rect GetScrollDamage() const;
|
||||
|
||||
pp::Point scroll_delta;
|
||||
pp::Rect scroll_rect;
|
||||
|
||||
// Does not include the scroll damage rect unless
|
||||
// synthesized_scroll_damage_rect_ is set.
|
||||
std::vector<pp::Rect> paint_rects;
|
||||
|
||||
// Rectangles that are finished painting.
|
||||
std::vector<ReadyRect> ready_rects;
|
||||
|
||||
// Whether we have added the scroll damage rect to paint_rects yet or not.
|
||||
bool synthesized_scroll_damage_rect_;
|
||||
};
|
||||
|
||||
pp::Rect ScrollPaintRect(const pp::Rect& paint_rect,
|
||||
const pp::Point& amount) const;
|
||||
void InvalidateScrollRect();
|
||||
|
||||
// Internal method used by InvalidateRect. If |check_scroll| is true, then the
|
||||
// method checks if there's a pending scroll and if so also invalidates |rect|
|
||||
// in the new scroll position.
|
||||
void InvalidateRectInternal(const pp::Rect& rect, bool check_scroll);
|
||||
|
||||
InternalPaintUpdate update_;
|
||||
};
|
||||
|
||||
#endif // PDF_PAINT_AGGREGATOR_H_
|
296
pdf/paint_manager.cc
Normal file
296
pdf/paint_manager.cc
Normal file
@ -0,0 +1,296 @@
|
||||
// Copyright (c) 2010 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/paint_manager.h"
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
#include "base/logging.h"
|
||||
#include "ppapi/c/pp_errors.h"
|
||||
#include "ppapi/cpp/instance.h"
|
||||
#include "ppapi/cpp/module.h"
|
||||
|
||||
PaintManager::PaintManager(pp::Instance* instance,
|
||||
Client* client,
|
||||
bool is_always_opaque)
|
||||
: instance_(instance),
|
||||
client_(client),
|
||||
is_always_opaque_(is_always_opaque),
|
||||
callback_factory_(NULL),
|
||||
manual_callback_pending_(false),
|
||||
flush_pending_(false),
|
||||
has_pending_resize_(false),
|
||||
graphics_need_to_be_bound_(false),
|
||||
pending_device_scale_(1.0),
|
||||
device_scale_(1.0),
|
||||
in_paint_(false),
|
||||
first_paint_(true),
|
||||
view_size_changed_waiting_for_paint_(false) {
|
||||
// Set the callback object outside of the initializer list to avoid a
|
||||
// compiler warning about using "this" in an initializer list.
|
||||
callback_factory_.Initialize(this);
|
||||
|
||||
// You can not use a NULL client pointer.
|
||||
DCHECK(client);
|
||||
}
|
||||
|
||||
PaintManager::~PaintManager() {
|
||||
}
|
||||
|
||||
// static
|
||||
pp::Size PaintManager::GetNewContextSize(const pp::Size& current_context_size,
|
||||
const pp::Size& plugin_size) {
|
||||
// The number of additional space in pixels to allocate to the right/bottom
|
||||
// of the context.
|
||||
const int kBufferSize = 100;
|
||||
|
||||
// Default to returning the same size.
|
||||
pp::Size result = current_context_size;
|
||||
|
||||
pp::Size min_size(std::max(current_context_size.width() - kBufferSize, 0),
|
||||
std::max(current_context_size.height() - kBufferSize, 0));
|
||||
// If the plugin size is bigger than the current context size, we need to
|
||||
// resize the context. If the plugin size is smaller than the current
|
||||
// context size by a given threshhold then resize the context so that we
|
||||
// aren't wasting too much memory.
|
||||
if (plugin_size.width() > current_context_size.width() ||
|
||||
plugin_size.height() > current_context_size.height() ||
|
||||
plugin_size.width() < min_size.width() ||
|
||||
plugin_size.height() < min_size.height()) {
|
||||
// Create a larger context than needed so that if we only resize by a
|
||||
// small margin, we don't need a new context.
|
||||
result = pp::Size(plugin_size.width() + kBufferSize,
|
||||
plugin_size.height() + kBufferSize);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void PaintManager::Initialize(pp::Instance* instance,
|
||||
Client* client,
|
||||
bool is_always_opaque) {
|
||||
DCHECK(!instance_ && !client_); // Can't initialize twice.
|
||||
instance_ = instance;
|
||||
client_ = client;
|
||||
is_always_opaque_ = is_always_opaque;
|
||||
}
|
||||
|
||||
void PaintManager::SetSize(const pp::Size& new_size, float device_scale) {
|
||||
if (GetEffectiveSize() == new_size &&
|
||||
GetEffectiveDeviceScale() == device_scale)
|
||||
return;
|
||||
|
||||
has_pending_resize_ = true;
|
||||
pending_size_ = new_size;
|
||||
pending_device_scale_ = device_scale;
|
||||
|
||||
view_size_changed_waiting_for_paint_ = true;
|
||||
|
||||
Invalidate();
|
||||
}
|
||||
|
||||
void PaintManager::Invalidate() {
|
||||
// You must call SetSize before using.
|
||||
DCHECK(!graphics_.is_null() || has_pending_resize_);
|
||||
|
||||
EnsureCallbackPending();
|
||||
aggregator_.InvalidateRect(pp::Rect(GetEffectiveSize()));
|
||||
}
|
||||
|
||||
void PaintManager::InvalidateRect(const pp::Rect& rect) {
|
||||
DCHECK(!in_paint_);
|
||||
|
||||
// You must call SetSize before using.
|
||||
DCHECK(!graphics_.is_null() || has_pending_resize_);
|
||||
|
||||
// Clip the rect to the device area.
|
||||
pp::Rect clipped_rect = rect.Intersect(pp::Rect(GetEffectiveSize()));
|
||||
if (clipped_rect.IsEmpty())
|
||||
return; // Nothing to do.
|
||||
|
||||
EnsureCallbackPending();
|
||||
aggregator_.InvalidateRect(clipped_rect);
|
||||
}
|
||||
|
||||
void PaintManager::ScrollRect(const pp::Rect& clip_rect,
|
||||
const pp::Point& amount) {
|
||||
DCHECK(!in_paint_);
|
||||
|
||||
// You must call SetSize before using.
|
||||
DCHECK(!graphics_.is_null() || has_pending_resize_);
|
||||
|
||||
EnsureCallbackPending();
|
||||
|
||||
aggregator_.ScrollRect(clip_rect, amount);
|
||||
}
|
||||
|
||||
pp::Size PaintManager::GetEffectiveSize() const {
|
||||
return has_pending_resize_ ? pending_size_ : plugin_size_;
|
||||
}
|
||||
|
||||
float PaintManager::GetEffectiveDeviceScale() const {
|
||||
return has_pending_resize_ ? pending_device_scale_ : device_scale_;
|
||||
}
|
||||
|
||||
void PaintManager::EnsureCallbackPending() {
|
||||
// The best way for us to do the next update is to get a notification that
|
||||
// a previous one has completed. So if we're already waiting for one, we
|
||||
// don't have to do anything differently now.
|
||||
if (flush_pending_)
|
||||
return;
|
||||
|
||||
// If no flush is pending, we need to do a manual call to get back to the
|
||||
// main thread. We may have one already pending, or we may need to schedule.
|
||||
if (manual_callback_pending_)
|
||||
return;
|
||||
|
||||
pp::Module::Get()->core()->CallOnMainThread(
|
||||
0,
|
||||
callback_factory_.NewCallback(&PaintManager::OnManualCallbackComplete),
|
||||
0);
|
||||
manual_callback_pending_ = true;
|
||||
}
|
||||
|
||||
void PaintManager::DoPaint() {
|
||||
in_paint_ = true;
|
||||
|
||||
std::vector<ReadyRect> ready;
|
||||
std::vector<pp::Rect> pending;
|
||||
|
||||
DCHECK(aggregator_.HasPendingUpdate());
|
||||
|
||||
// Apply any pending resize. Setting the graphics to this class must happen
|
||||
// before asking the plugin to paint in case it requests invalides or resizes.
|
||||
// However, the bind must not happen until afterward since we don't want to
|
||||
// have an unpainted device bound. The needs_binding flag tells us whether to
|
||||
// do this later.
|
||||
if (has_pending_resize_) {
|
||||
plugin_size_ = pending_size_;
|
||||
// Only create a new graphics context if the current context isn't big
|
||||
// enough or if it is far too big. This avoids creating a new context if
|
||||
// we only resize by a small amount.
|
||||
pp::Size new_size = GetNewContextSize(graphics_.size(), pending_size_);
|
||||
if (graphics_.size() != new_size) {
|
||||
graphics_ = pp::Graphics2D(instance_, new_size, is_always_opaque_);
|
||||
graphics_need_to_be_bound_ = true;
|
||||
|
||||
// Since we're binding a new one, all of the callbacks have been canceled.
|
||||
manual_callback_pending_ = false;
|
||||
flush_pending_ = false;
|
||||
callback_factory_.CancelAll();
|
||||
}
|
||||
|
||||
if (pending_device_scale_ != 1.0)
|
||||
graphics_.SetScale(1.0 / pending_device_scale_);
|
||||
device_scale_ = pending_device_scale_;
|
||||
|
||||
// This must be cleared before calling into the plugin since it may do
|
||||
// additional invalidation or sizing operations.
|
||||
has_pending_resize_ = false;
|
||||
pending_size_ = pp::Size();
|
||||
}
|
||||
|
||||
PaintAggregator::PaintUpdate update = aggregator_.GetPendingUpdate();
|
||||
client_->OnPaint(update.paint_rects, &ready, &pending);
|
||||
|
||||
if (ready.empty() && pending.empty()) {
|
||||
in_paint_ = false;
|
||||
return; // Nothing was painted, don't schedule a flush.
|
||||
}
|
||||
|
||||
std::vector<PaintAggregator::ReadyRect> ready_now;
|
||||
if (pending.empty()) {
|
||||
std::vector<PaintAggregator::ReadyRect> temp_ready;
|
||||
for (size_t i = 0; i < ready.size(); ++i)
|
||||
temp_ready.push_back(ready[i]);
|
||||
aggregator_.SetIntermediateResults(temp_ready, pending);
|
||||
ready_now = aggregator_.GetReadyRects();
|
||||
aggregator_.ClearPendingUpdate();
|
||||
|
||||
// Apply any scroll first.
|
||||
if (update.has_scroll)
|
||||
graphics_.Scroll(update.scroll_rect, update.scroll_delta);
|
||||
|
||||
view_size_changed_waiting_for_paint_ = false;
|
||||
} else {
|
||||
std::vector<PaintAggregator::ReadyRect> ready_later;
|
||||
for (size_t i = 0; i < ready.size(); ++i) {
|
||||
// Don't flush any part (i.e. scrollbars) if we're resizing the browser,
|
||||
// as that'll lead to flashes. Until we flush, the browser will use the
|
||||
// previous image, but if we flush, it'll revert to using the blank image.
|
||||
// We make an exception for the first paint since we want to show the
|
||||
// default background color instead of the pepper default of black.
|
||||
if (ready[i].flush_now &&
|
||||
(!view_size_changed_waiting_for_paint_ || first_paint_)) {
|
||||
ready_now.push_back(ready[i]);
|
||||
} else {
|
||||
ready_later.push_back(ready[i]);
|
||||
}
|
||||
}
|
||||
// Take the rectangles, except the ones that need to be flushed right away,
|
||||
// and save them so that everything is flushed at once.
|
||||
aggregator_.SetIntermediateResults(ready_later, pending);
|
||||
|
||||
if (ready_now.empty()) {
|
||||
in_paint_ = false;
|
||||
EnsureCallbackPending();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < ready_now.size(); ++i) {
|
||||
graphics_.PaintImageData(
|
||||
ready_now[i].image_data, ready_now[i].offset, ready_now[i].rect);
|
||||
}
|
||||
|
||||
int32_t result = graphics_.Flush(
|
||||
callback_factory_.NewCallback(&PaintManager::OnFlushComplete));
|
||||
|
||||
// If you trigger this assertion, then your plugin has called Flush()
|
||||
// manually. When using the PaintManager, you should not call Flush, it will
|
||||
// handle that for you because it needs to know when it can do the next paint
|
||||
// by implementing the flush callback.
|
||||
//
|
||||
// Another possible cause of this assertion is re-using devices. If you
|
||||
// use one device, swap it with another, then swap it back, we won't know
|
||||
// that we've already scheduled a Flush on the first device. It's best to not
|
||||
// re-use devices in this way.
|
||||
DCHECK(result != PP_ERROR_INPROGRESS);
|
||||
|
||||
if (result == PP_OK_COMPLETIONPENDING) {
|
||||
flush_pending_ = true;
|
||||
} else {
|
||||
DCHECK(result == PP_OK); // Catch all other errors in debug mode.
|
||||
}
|
||||
|
||||
in_paint_ = false;
|
||||
first_paint_ = false;
|
||||
|
||||
if (graphics_need_to_be_bound_) {
|
||||
instance_->BindGraphics(graphics_);
|
||||
graphics_need_to_be_bound_ = false;
|
||||
}
|
||||
}
|
||||
|
||||
void PaintManager::OnFlushComplete(int32_t) {
|
||||
DCHECK(flush_pending_);
|
||||
flush_pending_ = false;
|
||||
|
||||
// If more paints were enqueued while we were waiting for the flush to
|
||||
// complete, execute them now.
|
||||
if (aggregator_.HasPendingUpdate())
|
||||
DoPaint();
|
||||
}
|
||||
|
||||
void PaintManager::OnManualCallbackComplete(int32_t) {
|
||||
DCHECK(manual_callback_pending_);
|
||||
manual_callback_pending_ = false;
|
||||
|
||||
// Just because we have a manual callback doesn't mean there are actually any
|
||||
// invalid regions. Even though we only schedule this callback when something
|
||||
// is pending, a Flush callback could have come in before this callback was
|
||||
// executed and that could have cleared the queue.
|
||||
if (aggregator_.HasPendingUpdate())
|
||||
DoPaint();
|
||||
}
|
205
pdf/paint_manager.h
Normal file
205
pdf/paint_manager.h
Normal file
@ -0,0 +1,205 @@
|
||||
// Copyright (c) 2010 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.
|
||||
|
||||
#ifndef PDF_PAINT_MANAGER_H_
|
||||
#define PDF_PAINT_MANAGER_H_
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include "pdf/paint_aggregator.h"
|
||||
#include "ppapi/cpp/graphics_2d.h"
|
||||
#include "ppapi/utility/completion_callback_factory.h"
|
||||
|
||||
namespace pp {
|
||||
class Graphics2D;
|
||||
class Instance;
|
||||
class Point;
|
||||
class Rect;
|
||||
};
|
||||
|
||||
// Custom PaintManager for the PDF plugin. This is branched from the Pepper
|
||||
// version. The difference is that this supports progressive rendering of dirty
|
||||
// rects, where multiple calls to the rendering engine are needed. It also
|
||||
// supports having higher-priority rects flushing right away, i.e. the
|
||||
// scrollbars.
|
||||
//
|
||||
// The client's OnPaint
|
||||
class PaintManager {
|
||||
public:
|
||||
// Like PaintAggregator's version, but allows the plugin to tell us whether
|
||||
// it should be flushed to the screen immediately or when the rest of the
|
||||
// plugin viewport is ready.
|
||||
struct ReadyRect {
|
||||
pp::Point offset;
|
||||
pp::Rect rect;
|
||||
pp::ImageData image_data;
|
||||
bool flush_now;
|
||||
|
||||
ReadyRect(const pp::Rect& r, const pp::ImageData& i, bool f)
|
||||
: rect(r), image_data(i), flush_now(f) {}
|
||||
|
||||
operator PaintAggregator::ReadyRect() const {
|
||||
PaintAggregator::ReadyRect rv;
|
||||
rv.offset = offset;
|
||||
rv.rect = rect;
|
||||
rv.image_data = image_data;
|
||||
return rv;
|
||||
}
|
||||
};
|
||||
class Client {
|
||||
public:
|
||||
// Paints the given invalid area of the plugin to the given graphics
|
||||
// device. Returns true if anything was painted.
|
||||
//
|
||||
// You are given the list of rects to paint in |paint_rects|. You can
|
||||
// combine painting into less rectangles if it's more efficient. When a
|
||||
// rect is painted, information about that paint should be inserted into
|
||||
// |ready|. Otherwise if a paint needs more work, add the rect to
|
||||
// |pending|. If |pending| is not empty, your OnPaint function will get
|
||||
// called again. Once OnPaint is called and it returns no pending rects,
|
||||
// all the previously ready rects will be flushed on screen. The exception
|
||||
// is for ready rects that have |flush_now| set to true. These will be
|
||||
// flushed right away.
|
||||
//
|
||||
// Do not call Flush() on the graphics device, this will be done
|
||||
// automatically if you return true from this function since the
|
||||
// PaintManager needs to handle the callback.
|
||||
//
|
||||
// Calling Invalidate/Scroll is not allowed while inside an OnPaint
|
||||
virtual void OnPaint(const std::vector<pp::Rect>& paint_rects,
|
||||
std::vector<ReadyRect>* ready,
|
||||
std::vector<pp::Rect>* pending) = 0;
|
||||
protected:
|
||||
// You shouldn't be doing deleting through this interface.
|
||||
virtual ~Client() {}
|
||||
};
|
||||
|
||||
// The instance is the plugin instance using this paint manager to do its
|
||||
// painting. Painting will automatically go to this instance and you don't
|
||||
// have to manually bind any device context (this is all handled by the
|
||||
// paint manager).
|
||||
//
|
||||
// The Client is a non-owning pointer and must remain valid (normally the
|
||||
// object implementing the Client interface will own the paint manager).
|
||||
//
|
||||
// The is_always_opaque flag will be passed to the device contexts that this
|
||||
// class creates. Set this to true if your plugin always draws an opaque
|
||||
// image to the device. This is used as a hint to the browser that it does
|
||||
// not need to do alpha blending, which speeds up painting. If you generate
|
||||
// non-opqaue pixels or aren't sure, set this to false for more general
|
||||
// blending.
|
||||
//
|
||||
// If you set is_always_opaque, your alpha channel should always be set to
|
||||
// 0xFF or there may be painting artifacts. Being opaque will allow the
|
||||
// browser to do a memcpy rather than a blend to paint the plugin, and this
|
||||
// means your alpha values will get set on the page backing store. If these
|
||||
// values are incorrect, it could mess up future blending. If you aren't
|
||||
// sure, it is always correct to specify that it it not opaque.
|
||||
//
|
||||
// You will need to call SetSize before this class will do anything. Normally
|
||||
// you do this from the ViewChanged method of your plugin instance.
|
||||
PaintManager(pp::Instance* instance, Client* client, bool is_always_opaque);
|
||||
|
||||
~PaintManager();
|
||||
|
||||
// Returns the size of the graphics context to allocate for a given plugin
|
||||
// size. We may allocated a slightly larger buffer than required so that we
|
||||
// don't have to resize the context when scrollbars appear/dissapear due to
|
||||
// zooming (which can result in flickering).
|
||||
static pp::Size GetNewContextSize(const pp::Size& current_context_size,
|
||||
const pp::Size& plugin_size);
|
||||
|
||||
// You must call this function before using if you use the 0-arg constructor.
|
||||
// See the constructor for what these arguments mean.
|
||||
void Initialize(pp::Instance* instance, Client* client,
|
||||
bool is_always_opaque);
|
||||
|
||||
// Sets the size of the plugin. If the size is the same as the previous call,
|
||||
// this will be a NOP. If the size has changed, a new device will be
|
||||
// allocated to the given size and a paint to that device will be scheduled.
|
||||
//
|
||||
// This is intended to be called from ViewChanged with the size of the
|
||||
// plugin. Since it tracks the old size and only allocates when the size
|
||||
// changes, you can always call this function without worrying about whether
|
||||
// the size changed or ViewChanged is called for another reason (like the
|
||||
// position changed).
|
||||
void SetSize(const pp::Size& new_size, float new_device_scale);
|
||||
|
||||
// Invalidate the entire plugin.
|
||||
void Invalidate();
|
||||
|
||||
// Invalidate the given rect.
|
||||
void InvalidateRect(const pp::Rect& rect);
|
||||
|
||||
// The given rect should be scrolled by the given amounts.
|
||||
void ScrollRect(const pp::Rect& clip_rect, const pp::Point& amount);
|
||||
|
||||
// Returns the size of the graphics context for the next paint operation.
|
||||
// This is the pending size if a resize is pending (the plugin has called
|
||||
// SetSize but we haven't actually painted it yet), or the current size of
|
||||
// no resize is pending.
|
||||
pp::Size GetEffectiveSize() const;
|
||||
float GetEffectiveDeviceScale() const;
|
||||
|
||||
private:
|
||||
// Disallow copy and assign (these are unimplemented).
|
||||
PaintManager(const PaintManager&);
|
||||
PaintManager& operator=(const PaintManager&);
|
||||
|
||||
// Makes sure there is a callback that will trigger a paint at a later time.
|
||||
// This will be either a Flush callback telling us we're allowed to generate
|
||||
// more data, or, if there's no flush callback pending, a manual call back
|
||||
// to the message loop via ExecuteOnMainThread.
|
||||
void EnsureCallbackPending();
|
||||
|
||||
// Does the client paint and executes a Flush if necessary.
|
||||
void DoPaint();
|
||||
|
||||
// Callback for asynchronous completion of Flush.
|
||||
void OnFlushComplete(int32_t);
|
||||
|
||||
// Callback for manual scheduling of paints when there is no flush callback
|
||||
// pending.
|
||||
void OnManualCallbackComplete(int32_t);
|
||||
|
||||
pp::Instance* instance_;
|
||||
|
||||
// Non-owning pointer. See the constructor.
|
||||
Client* client_;
|
||||
|
||||
bool is_always_opaque_;
|
||||
|
||||
pp::CompletionCallbackFactory<PaintManager> callback_factory_;
|
||||
|
||||
// This graphics device will be is_null() if no graphics has been manually
|
||||
// set yet.
|
||||
pp::Graphics2D graphics_;
|
||||
|
||||
PaintAggregator aggregator_;
|
||||
|
||||
// See comment for EnsureCallbackPending for more on how these work.
|
||||
bool manual_callback_pending_;
|
||||
bool flush_pending_;
|
||||
|
||||
// When we get a resize, we don't bind right away (see SetSize). The
|
||||
// has_pending_resize_ tells us that we need to do a resize for the next
|
||||
// paint operation. When true, the new size is in pending_size_.
|
||||
bool has_pending_resize_;
|
||||
bool graphics_need_to_be_bound_;
|
||||
pp::Size pending_size_;
|
||||
pp::Size plugin_size_;
|
||||
float pending_device_scale_;
|
||||
float device_scale_;
|
||||
|
||||
// True iff we're in the middle of a paint.
|
||||
bool in_paint_;
|
||||
|
||||
// True if we haven't painted the plugin viewport yet.
|
||||
bool first_paint_;
|
||||
|
||||
// True when the view size just changed and we're waiting for a paint.
|
||||
bool view_size_changed_waiting_for_paint_;
|
||||
};
|
||||
|
||||
#endif // PDF_PAINT_MANAGER_H_
|
244
pdf/pdf.cc
Normal file
244
pdf/pdf.cc
Normal file
@ -0,0 +1,244 @@
|
||||
// Copyright (c) 2010 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/pdf.h"
|
||||
|
||||
#if defined(OS_WIN)
|
||||
#include <windows.h>
|
||||
#endif
|
||||
|
||||
#include "base/command_line.h"
|
||||
#include "base/logging.h"
|
||||
#include "pdf/instance.h"
|
||||
#include "pdf/out_of_process_instance.h"
|
||||
#include "ppapi/c/ppp.h"
|
||||
#include "ppapi/cpp/private/pdf.h"
|
||||
|
||||
bool g_sdk_initialized_via_pepper = false;
|
||||
|
||||
// The Mac release builds discard CreateModule and the entire PDFModule
|
||||
// definition because they are not referenced here. This causes the Pepper
|
||||
// exports (PPP_GetInterface etc) to not be exported. So we force the linker
|
||||
// to include this code by using __attribute__((used)).
|
||||
#if __GNUC__ >= 4
|
||||
#define PDF_USED __attribute__((used))
|
||||
#else
|
||||
#define PDF_USED
|
||||
#endif
|
||||
|
||||
#if defined(OS_WIN)
|
||||
HMODULE g_hmodule;
|
||||
|
||||
void HandleInvalidParameter(const wchar_t* expression,
|
||||
const wchar_t* function,
|
||||
const wchar_t* file,
|
||||
unsigned int line,
|
||||
uintptr_t reserved) {
|
||||
// Do the same as Chrome's CHECK(false) which is undefined.
|
||||
::base::debug::BreakDebugger();
|
||||
return;
|
||||
}
|
||||
|
||||
void HandlePureVirtualCall() {
|
||||
// Do the same as Chrome's CHECK(false) which is undefined.
|
||||
::base::debug::BreakDebugger();
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
BOOL APIENTRY DllMain(HMODULE module, DWORD reason_for_call, LPVOID reserved) {
|
||||
g_hmodule = module;
|
||||
if (reason_for_call == DLL_PROCESS_ATTACH) {
|
||||
// On windows following handlers work only inside module. So breakpad in
|
||||
// chrome.dll does not catch that. To avoid linking related code or
|
||||
// duplication breakpad_win.cc::InitCrashReporter() just catch errors here
|
||||
// and crash in a way interceptable by breakpad of parent module.
|
||||
_set_invalid_parameter_handler(HandleInvalidParameter);
|
||||
_set_purecall_handler(HandlePureVirtualCall);
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
namespace pp {
|
||||
|
||||
PDF_USED Module* CreateModule() {
|
||||
return new chrome_pdf::PDFModule();
|
||||
}
|
||||
|
||||
} // namespace pp
|
||||
|
||||
namespace chrome_pdf {
|
||||
|
||||
PDFModule::PDFModule() {
|
||||
}
|
||||
|
||||
PDFModule::~PDFModule() {
|
||||
if (g_sdk_initialized_via_pepper) {
|
||||
chrome_pdf::ShutdownSDK();
|
||||
g_sdk_initialized_via_pepper = false;
|
||||
}
|
||||
}
|
||||
|
||||
bool PDFModule::Init() {
|
||||
return true;
|
||||
}
|
||||
|
||||
pp::Instance* PDFModule::CreateInstance(PP_Instance instance) {
|
||||
if (!g_sdk_initialized_via_pepper) {
|
||||
void* data = NULL;
|
||||
#if defined(OS_WIN)
|
||||
data = g_hmodule;
|
||||
#endif
|
||||
if (!chrome_pdf::InitializeSDK(data))
|
||||
return NULL;
|
||||
g_sdk_initialized_via_pepper = true;
|
||||
}
|
||||
|
||||
if (pp::PDF::IsOutOfProcess(pp::InstanceHandle(instance)))
|
||||
return new OutOfProcessInstance(instance);
|
||||
return new Instance(instance);
|
||||
}
|
||||
|
||||
} // namespace chrome_pdf
|
||||
|
||||
extern "C" {
|
||||
|
||||
// TODO(sanjeevr): It might make sense to provide more stateful wrappers over
|
||||
// the internal PDF SDK (such as LoadDocument, LoadPage etc). Determine if we
|
||||
// need to provide this.
|
||||
// Wrapper exports over the PDF engine that can be used by an external module
|
||||
// such as Chrome (since Chrome cannot directly pull in PDFium sources).
|
||||
#if defined(OS_WIN)
|
||||
// |pdf_buffer| is the buffer that contains the entire PDF document to be
|
||||
// rendered.
|
||||
// |buffer_size| is the size of pdf_buffer in bytes.
|
||||
// |page_number| is the 0-based index of the page to be rendered.
|
||||
// |dc| is the device context to render into.
|
||||
// |dpi_x| and |dpi_y| are the x and y resolutions respectively. If either value
|
||||
// is -1, the dpi from the DC will be used.
|
||||
// |bounds_origin_x|, |bounds_origin_y|, |bounds_width| and |bounds_height|
|
||||
// specify a bounds rectangle within the DC in which to render the PDF page.
|
||||
// |fit_to_bounds| specifies whether the output should be shrunk to fit the
|
||||
// supplied bounds if the page size is larger than the bounds in any
|
||||
// dimension. If this is false, parts of the PDF page that lie outside the
|
||||
// bounds will be clipped.
|
||||
// |stretch_to_bounds| specifies whether the output should be stretched to fit
|
||||
// the supplied bounds if the page size is smaller than the bounds in any
|
||||
// dimension.
|
||||
// If both |fit_to_bounds| and |stretch_to_bounds| are true, then
|
||||
// |fit_to_bounds| is honored first.
|
||||
// |keep_aspect_ratio| If any scaling is to be done is true, this flag specifies
|
||||
// whether the original aspect ratio of the page should be preserved while
|
||||
// scaling.
|
||||
// |center_in_bounds| specifies whether the final image (after any scaling is
|
||||
// done) should be centered within the given bounds.
|
||||
// |autorotate| specifies whether the final image should be rotated to match
|
||||
// the output bound.
|
||||
// Returns false if the document or the page number are not valid.
|
||||
PP_EXPORT bool RenderPDFPageToDC(const void* pdf_buffer,
|
||||
int buffer_size,
|
||||
int page_number,
|
||||
HDC dc,
|
||||
int dpi_x,
|
||||
int dpi_y,
|
||||
int bounds_origin_x,
|
||||
int bounds_origin_y,
|
||||
int bounds_width,
|
||||
int bounds_height,
|
||||
bool fit_to_bounds,
|
||||
bool stretch_to_bounds,
|
||||
bool keep_aspect_ratio,
|
||||
bool center_in_bounds,
|
||||
bool autorotate) {
|
||||
if (!g_sdk_initialized_via_pepper) {
|
||||
if (!chrome_pdf::InitializeSDK(g_hmodule)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
scoped_ptr<chrome_pdf::PDFEngineExports> engine_exports(
|
||||
chrome_pdf::PDFEngineExports::Create());
|
||||
chrome_pdf::PDFEngineExports::RenderingSettings settings(
|
||||
dpi_x, dpi_y, pp::Rect(bounds_origin_x, bounds_origin_y, bounds_width,
|
||||
bounds_height),
|
||||
fit_to_bounds, stretch_to_bounds, keep_aspect_ratio, center_in_bounds,
|
||||
autorotate);
|
||||
bool ret = engine_exports->RenderPDFPageToDC(pdf_buffer, buffer_size,
|
||||
page_number, settings, dc);
|
||||
if (!g_sdk_initialized_via_pepper) {
|
||||
chrome_pdf::ShutdownSDK();
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
#endif // OS_WIN
|
||||
|
||||
// |page_count| and |max_page_width| are optional and can be NULL.
|
||||
// Returns false if the document is not valid.
|
||||
PDF_USED PP_EXPORT
|
||||
bool GetPDFDocInfo(const void* pdf_buffer,
|
||||
int buffer_size, int* page_count,
|
||||
double* max_page_width) {
|
||||
if (!g_sdk_initialized_via_pepper) {
|
||||
void* data = NULL;
|
||||
#if defined(OS_WIN)
|
||||
data = g_hmodule;
|
||||
#endif
|
||||
if (!chrome_pdf::InitializeSDK(data))
|
||||
return false;
|
||||
}
|
||||
scoped_ptr<chrome_pdf::PDFEngineExports> engine_exports(
|
||||
chrome_pdf::PDFEngineExports::Create());
|
||||
bool ret = engine_exports->GetPDFDocInfo(
|
||||
pdf_buffer, buffer_size, page_count, max_page_width);
|
||||
if (!g_sdk_initialized_via_pepper) {
|
||||
chrome_pdf::ShutdownSDK();
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
// Renders PDF page into 4-byte per pixel BGRA color bitmap.
|
||||
// |pdf_buffer| is the buffer that contains the entire PDF document to be
|
||||
// rendered.
|
||||
// |pdf_buffer_size| is the size of pdf_buffer in bytes.
|
||||
// |page_number| is the 0-based index of the page to be rendered.
|
||||
// |bitmap_buffer| is the output buffer for bitmap.
|
||||
// |bitmap_width| is the width of the output bitmap.
|
||||
// |bitmap_height| is the height of the output bitmap.
|
||||
// |dpi| is the resolutions.
|
||||
// |autorotate| specifies whether the final image should be rotated to match
|
||||
// the output bound.
|
||||
// Returns false if the document or the page number are not valid.
|
||||
PDF_USED PP_EXPORT
|
||||
bool RenderPDFPageToBitmap(const void* pdf_buffer,
|
||||
int pdf_buffer_size,
|
||||
int page_number,
|
||||
void* bitmap_buffer,
|
||||
int bitmap_width,
|
||||
int bitmap_height,
|
||||
int dpi,
|
||||
bool autorotate) {
|
||||
if (!g_sdk_initialized_via_pepper) {
|
||||
void* data = NULL;
|
||||
#if defined(OS_WIN)
|
||||
data = g_hmodule;
|
||||
#endif
|
||||
if (!chrome_pdf::InitializeSDK(data))
|
||||
return false;
|
||||
}
|
||||
scoped_ptr<chrome_pdf::PDFEngineExports> engine_exports(
|
||||
chrome_pdf::PDFEngineExports::Create());
|
||||
chrome_pdf::PDFEngineExports::RenderingSettings settings(
|
||||
dpi, dpi, pp::Rect(bitmap_width, bitmap_height), true, false, true, true,
|
||||
autorotate);
|
||||
bool ret = engine_exports->RenderPDFPageToBitmap(
|
||||
pdf_buffer, pdf_buffer_size, page_number, settings, bitmap_buffer);
|
||||
if (!g_sdk_initialized_via_pepper) {
|
||||
chrome_pdf::ShutdownSDK();
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
} // extern "C"
|
7
pdf/pdf.def
Normal file
7
pdf/pdf.def
Normal file
@ -0,0 +1,7 @@
|
||||
LIBRARY pdf
|
||||
|
||||
EXPORTS
|
||||
NP_GetEntryPoints @1
|
||||
NP_Initialize @2
|
||||
NP_Shutdown @3
|
||||
|
181
pdf/pdf.gyp
Normal file
181
pdf/pdf.gyp
Normal file
@ -0,0 +1,181 @@
|
||||
{
|
||||
'variables': {
|
||||
'chromium_code': 1,
|
||||
'pdf_engine%': 0, # 0 PDFium
|
||||
},
|
||||
'target_defaults': {
|
||||
'cflags': [
|
||||
'-fPIC',
|
||||
],
|
||||
},
|
||||
'targets': [
|
||||
{
|
||||
'target_name': 'pdf',
|
||||
'type': 'loadable_module',
|
||||
'msvs_guid': '647863C0-C7A3-469A-B1ED-AD7283C34BED',
|
||||
'dependencies': [
|
||||
'../base/base.gyp:base',
|
||||
'../net/net.gyp:net',
|
||||
'../ppapi/ppapi.gyp:ppapi_cpp',
|
||||
'../third_party/pdfium/pdfium.gyp:fpdfsdk',
|
||||
],
|
||||
'xcode_settings': {
|
||||
'INFOPLIST_FILE': 'Info.plist',
|
||||
},
|
||||
'mac_framework_dirs': [
|
||||
'$(SDKROOT)/System/Library/Frameworks/ApplicationServices.framework/Frameworks',
|
||||
],
|
||||
'ldflags': [ '-L<(PRODUCT_DIR)',],
|
||||
'sources': [
|
||||
'button.h',
|
||||
'button.cc',
|
||||
'chunk_stream.h',
|
||||
'chunk_stream.cc',
|
||||
'control.h',
|
||||
'control.cc',
|
||||
'document_loader.h',
|
||||
'document_loader.cc',
|
||||
'draw_utils.cc',
|
||||
'draw_utils.h',
|
||||
'fading_control.cc',
|
||||
'fading_control.h',
|
||||
'fading_controls.cc',
|
||||
'fading_controls.h',
|
||||
'instance.cc',
|
||||
'instance.h',
|
||||
'number_image_generator.cc',
|
||||
'number_image_generator.h',
|
||||
'out_of_process_instance.cc',
|
||||
'out_of_process_instance.h',
|
||||
'page_indicator.cc',
|
||||
'page_indicator.h',
|
||||
'paint_aggregator.cc',
|
||||
'paint_aggregator.h',
|
||||
'paint_manager.cc',
|
||||
'paint_manager.h',
|
||||
'pdf.cc',
|
||||
'pdf.h',
|
||||
'pdf.rc',
|
||||
'progress_control.cc',
|
||||
'progress_control.h',
|
||||
'pdf_engine.h',
|
||||
'preview_mode_client.cc',
|
||||
'preview_mode_client.h',
|
||||
'resource.h',
|
||||
'resource_consts.h',
|
||||
'thumbnail_control.cc',
|
||||
'thumbnail_control.h',
|
||||
'../chrome/browser/chrome_page_zoom_constants.cc',
|
||||
'../content/common/page_zoom.cc',
|
||||
],
|
||||
'conditions': [
|
||||
['pdf_engine==0', {
|
||||
'sources': [
|
||||
'pdfium/pdfium_assert_matching_enums.cc',
|
||||
'pdfium/pdfium_engine.cc',
|
||||
'pdfium/pdfium_engine.h',
|
||||
'pdfium/pdfium_mem_buffer_file_read.cc',
|
||||
'pdfium/pdfium_mem_buffer_file_read.h',
|
||||
'pdfium/pdfium_mem_buffer_file_write.cc',
|
||||
'pdfium/pdfium_mem_buffer_file_write.h',
|
||||
'pdfium/pdfium_page.cc',
|
||||
'pdfium/pdfium_page.h',
|
||||
'pdfium/pdfium_range.cc',
|
||||
'pdfium/pdfium_range.h',
|
||||
],
|
||||
}],
|
||||
['OS!="win"', {
|
||||
'sources!': [
|
||||
'pdf.rc',
|
||||
],
|
||||
}],
|
||||
['OS=="mac"', {
|
||||
'mac_bundle': 1,
|
||||
'product_name': 'PDF',
|
||||
'product_extension': 'plugin',
|
||||
# Strip the shipping binary of symbols so "Foxit" doesn't appear in
|
||||
# the binary. Symbols are stored in a separate .dSYM.
|
||||
'variables': {
|
||||
'mac_real_dsym': 1,
|
||||
},
|
||||
'sources+': [
|
||||
'Info.plist'
|
||||
],
|
||||
}],
|
||||
['OS=="win"', {
|
||||
'defines': [
|
||||
'COMPILE_CONTENT_STATICALLY',
|
||||
],
|
||||
# TODO(jschuh): crbug.com/167187 fix size_t to int truncations.
|
||||
'msvs_disabled_warnings': [ 4267, ],
|
||||
}],
|
||||
['OS=="linux"', {
|
||||
'configurations': {
|
||||
'Release_Base': {
|
||||
#'cflags': [ '-fno-weak',], # get rid of symbols that strip doesn't remove.
|
||||
# Don't do this for now since official builder will take care of it. That
|
||||
# way symbols can still be uploaded to the crash server.
|
||||
#'ldflags': [ '-s',], # strip local symbols from binary.
|
||||
},
|
||||
},
|
||||
# Use a custom version script to prevent leaking the vendor name in
|
||||
# visible symbols.
|
||||
'ldflags': [
|
||||
'-Wl,--version-script=<!(cd <(DEPTH) && pwd -P)/pdf/libpdf.map'
|
||||
],
|
||||
}],
|
||||
],
|
||||
},
|
||||
{
|
||||
'target_name': 'pdfium_test',
|
||||
'type': 'executable',
|
||||
'dependencies': [
|
||||
'../base/base.gyp:base',
|
||||
'../base/base.gyp:base_i18n',
|
||||
'../third_party/pdfium/pdfium.gyp:fpdfsdk',
|
||||
],
|
||||
'sources': [
|
||||
'pdfium/pdfium_test.cc',
|
||||
],
|
||||
}
|
||||
],
|
||||
'conditions': [
|
||||
# CrOS has a separate step to do this.
|
||||
['OS=="linux" and chromeos==0',
|
||||
{ 'targets': [
|
||||
{
|
||||
'target_name': 'pdf_linux_symbols',
|
||||
'type': 'none',
|
||||
'conditions': [
|
||||
['linux_dump_symbols==1', {
|
||||
'actions': [
|
||||
{
|
||||
'action_name': 'dump_symbols',
|
||||
'inputs': [
|
||||
'<(DEPTH)/build/linux/dump_app_syms',
|
||||
'<(PRODUCT_DIR)/dump_syms',
|
||||
'<(PRODUCT_DIR)/libpdf.so',
|
||||
],
|
||||
'outputs': [
|
||||
'<(PRODUCT_DIR)/libpdf.so.breakpad.<(target_arch)',
|
||||
],
|
||||
'action': ['<(DEPTH)/build/linux/dump_app_syms',
|
||||
'<(PRODUCT_DIR)/dump_syms',
|
||||
'<(linux_strip_binary)',
|
||||
'<(PRODUCT_DIR)/libpdf.so',
|
||||
'<@(_outputs)'],
|
||||
'message': 'Dumping breakpad symbols to <(_outputs)',
|
||||
'process_outputs_as_sources': 1,
|
||||
},
|
||||
],
|
||||
'dependencies': [
|
||||
'pdf',
|
||||
'../breakpad/breakpad.gyp:dump_syms',
|
||||
],
|
||||
}],
|
||||
],
|
||||
},
|
||||
],
|
||||
},], # OS=="linux" and chromeos==0
|
||||
],
|
||||
}
|
24
pdf/pdf.h
Normal file
24
pdf/pdf.h
Normal file
@ -0,0 +1,24 @@
|
||||
// Copyright (c) 2010 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.
|
||||
|
||||
#ifndef PDF_PDF_H_
|
||||
#define PDF_PDF_H_
|
||||
|
||||
#include "ppapi/cpp/module.h"
|
||||
|
||||
namespace chrome_pdf {
|
||||
|
||||
class PDFModule : public pp::Module {
|
||||
public:
|
||||
PDFModule();
|
||||
virtual ~PDFModule();
|
||||
|
||||
// pp::Module implementation.
|
||||
virtual bool Init();
|
||||
virtual pp::Instance* CreateInstance(PP_Instance instance);
|
||||
};
|
||||
|
||||
} // namespace chrome_pdf
|
||||
|
||||
#endif // PDF_PDF_H_
|
104
pdf/pdf.rc
Normal file
104
pdf/pdf.rc
Normal file
@ -0,0 +1,104 @@
|
||||
// Microsoft Visual C++ generated resource script.
|
||||
//
|
||||
#include "resource.h"
|
||||
|
||||
#define APSTUDIO_READONLY_SYMBOLS
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Generated from the TEXTINCLUDE 2 resource.
|
||||
//
|
||||
#include "afxres.h"
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
#undef APSTUDIO_READONLY_SYMBOLS
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// English (U.S.) resources
|
||||
|
||||
#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
|
||||
#ifdef _WIN32
|
||||
LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
|
||||
#pragma code_page(1252)
|
||||
#endif //_WIN32
|
||||
|
||||
#ifdef APSTUDIO_INVOKED
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// TEXTINCLUDE
|
||||
//
|
||||
|
||||
1 TEXTINCLUDE
|
||||
BEGIN
|
||||
"resource.h\0"
|
||||
END
|
||||
|
||||
2 TEXTINCLUDE
|
||||
BEGIN
|
||||
"#include ""afxres.h""\r\n"
|
||||
"\0"
|
||||
END
|
||||
|
||||
3 TEXTINCLUDE
|
||||
BEGIN
|
||||
"\r\n"
|
||||
"\0"
|
||||
END
|
||||
|
||||
#endif // APSTUDIO_INVOKED
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Version
|
||||
//
|
||||
|
||||
VS_VERSION_INFO VERSIONINFO
|
||||
FILEVERSION 1,0,0,1
|
||||
PRODUCTVERSION 1,0,0,1
|
||||
FILEFLAGSMASK 0x17L
|
||||
#ifdef _DEBUG
|
||||
FILEFLAGS 0x1L
|
||||
#else
|
||||
FILEFLAGS 0x0L
|
||||
#endif
|
||||
FILEOS 0x4L
|
||||
FILETYPE 0x2L
|
||||
FILESUBTYPE 0x0L
|
||||
BEGIN
|
||||
BLOCK "StringFileInfo"
|
||||
BEGIN
|
||||
BLOCK "040904e4"
|
||||
BEGIN
|
||||
VALUE "FileDescription", "Chrome PDF Viewer"
|
||||
VALUE "FileVersion", "1, 0, 0, 1"
|
||||
VALUE "InternalName", "pdf"
|
||||
VALUE "LegalCopyright", "Copyright (C) 2010"
|
||||
VALUE "MIMEType", "application/pdf"
|
||||
VALUE "FileExtents", "pdf"
|
||||
VALUE "FileOpenName", "Acrobat Portable Document Format"
|
||||
VALUE "OriginalFilename", "pdf.dll"
|
||||
VALUE "ProductName", "Chrome PDF Viewer"
|
||||
VALUE "ProductVersion", "1, 0, 0, 1"
|
||||
END
|
||||
END
|
||||
BLOCK "VarFileInfo"
|
||||
BEGIN
|
||||
VALUE "Translation", 0x409, 1252
|
||||
END
|
||||
END
|
||||
|
||||
#endif // English (U.S.) resources
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
|
||||
#ifndef APSTUDIO_INVOKED
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Generated from the TEXTINCLUDE 3 resource.
|
||||
//
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
#endif // not APSTUDIO_INVOKED
|
||||
|
319
pdf/pdf_engine.h
Normal file
319
pdf/pdf_engine.h
Normal file
@ -0,0 +1,319 @@
|
||||
// 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.
|
||||
|
||||
#ifndef PDF_PDF_ENGINE_H_
|
||||
#define PDF_PDF_ENGINE_H_
|
||||
|
||||
#include "build/build_config.h"
|
||||
|
||||
#if defined(OS_WIN)
|
||||
#include <windows.h>
|
||||
#endif
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "base/strings/string16.h"
|
||||
|
||||
#include "ppapi/c/dev/pp_cursor_type_dev.h"
|
||||
#include "ppapi/c/dev/ppp_printing_dev.h"
|
||||
#include "ppapi/c/ppb_input_event.h"
|
||||
#include "ppapi/cpp/completion_callback.h"
|
||||
#include "ppapi/cpp/image_data.h"
|
||||
#include "ppapi/cpp/rect.h"
|
||||
#include "ppapi/cpp/size.h"
|
||||
#include "ppapi/cpp/url_loader.h"
|
||||
|
||||
namespace pp {
|
||||
class InputEvent;
|
||||
}
|
||||
|
||||
#define kBackgroundColorR 204
|
||||
#define kBackgroundColorG 204
|
||||
#define kBackgroundColorB 204
|
||||
#define kBackgroundColorA 255
|
||||
|
||||
namespace chrome_pdf {
|
||||
|
||||
class Stream;
|
||||
|
||||
#if defined(OS_MACOSX)
|
||||
const uint32 kDefaultKeyModifier = PP_INPUTEVENT_MODIFIER_METAKEY;
|
||||
#else // !OS_MACOSX
|
||||
const uint32 kDefaultKeyModifier = PP_INPUTEVENT_MODIFIER_CONTROLKEY;
|
||||
#endif // OS_MACOSX
|
||||
|
||||
// Do one time initialization of the SDK. data is platform specific, on Windows
|
||||
// it's the instance of the DLL and it's unused on other platforms.
|
||||
bool InitializeSDK(void* data);
|
||||
// Tells the SDK that we're shutting down.
|
||||
void ShutdownSDK();
|
||||
|
||||
// This class encapsulates a PDF rendering engine.
|
||||
class PDFEngine {
|
||||
public:
|
||||
|
||||
enum DocumentPermission {
|
||||
PERMISSION_COPY,
|
||||
PERMISSION_COPY_ACCESSIBLE,
|
||||
PERMISSION_PRINT_LOW_QUALITY,
|
||||
PERMISSION_PRINT_HIGH_QUALITY,
|
||||
};
|
||||
|
||||
// The interface that's provided to the rendering engine.
|
||||
class Client {
|
||||
public:
|
||||
// Informs the client about the document's size in pixels.
|
||||
virtual void DocumentSizeUpdated(const pp::Size& size) = 0;
|
||||
|
||||
// Informs the client that the given rect needs to be repainted.
|
||||
virtual void Invalidate(const pp::Rect& rect) = 0;
|
||||
|
||||
// Informs the client to scroll the plugin area by the given offset.
|
||||
virtual void Scroll(const pp::Point& point) = 0;
|
||||
|
||||
// Scroll the horizontal/vertical scrollbars to a given position.
|
||||
virtual void ScrollToX(int position) = 0;
|
||||
virtual void ScrollToY(int position) = 0;
|
||||
|
||||
// Scroll to the specified page.
|
||||
virtual void ScrollToPage(int page) = 0;
|
||||
|
||||
// Navigate to the given url.
|
||||
virtual void NavigateTo(const std::string& url, bool open_in_new_tab) = 0;
|
||||
|
||||
// Updates the cursor.
|
||||
virtual void UpdateCursor(PP_CursorType_Dev cursor) = 0;
|
||||
|
||||
// Updates the tick marks in the vertical scrollbar.
|
||||
virtual void UpdateTickMarks(const std::vector<pp::Rect>& tickmarks) = 0;
|
||||
|
||||
// Updates the number of find results for the current search term. If
|
||||
// there are no matches 0 should be passed in. Only when the plugin has
|
||||
// finished searching should it pass in the final count with final_result
|
||||
// set to true.
|
||||
virtual void NotifyNumberOfFindResultsChanged(int total,
|
||||
bool final_result) = 0;
|
||||
|
||||
// Updates the index of the currently selected search item.
|
||||
virtual void NotifySelectedFindResultChanged(int current_find_index) = 0;
|
||||
|
||||
// Prompts the user for a password to open this document. The callback is
|
||||
// called when the password is retrieved.
|
||||
virtual void GetDocumentPassword(
|
||||
pp::CompletionCallbackWithOutput<pp::Var> callback) = 0;
|
||||
|
||||
// Puts up an alert with the given message.
|
||||
virtual void Alert(const std::string& message) = 0;
|
||||
|
||||
// Puts up a confirm with the given message, and returns true if the user
|
||||
// presses OK, or false if they press cancel.
|
||||
virtual bool Confirm(const std::string& message) = 0;
|
||||
|
||||
// Puts up a prompt with the given message and default answer and returns
|
||||
// the answer.
|
||||
virtual std::string Prompt(const std::string& question,
|
||||
const std::string& default_answer) = 0;
|
||||
|
||||
// Returns the url of the pdf.
|
||||
virtual std::string GetURL() = 0;
|
||||
|
||||
// Send an email.
|
||||
virtual void Email(const std::string& to,
|
||||
const std::string& cc,
|
||||
const std::string& bcc,
|
||||
const std::string& subject,
|
||||
const std::string& body) = 0;
|
||||
|
||||
// Put up the print dialog.
|
||||
virtual void Print() = 0;
|
||||
|
||||
// Submit the data using HTTP POST.
|
||||
virtual void SubmitForm(const std::string& url,
|
||||
const void* data,
|
||||
int length) = 0;
|
||||
|
||||
// Pops up a file selection dialog and returns the result.
|
||||
virtual std::string ShowFileSelectionDialog() = 0;
|
||||
|
||||
// Creates and returns new URL loader for partial document requests.
|
||||
virtual pp::URLLoader CreateURLLoader() = 0;
|
||||
|
||||
// Calls the client's OnCallback() function in delay_in_ms with the given
|
||||
// id.
|
||||
virtual void ScheduleCallback(int id, int delay_in_ms) = 0;
|
||||
|
||||
// Searches the given string for "term" and returns the results. Unicode-
|
||||
// aware.
|
||||
struct SearchStringResult {
|
||||
int start_index;
|
||||
int length;
|
||||
};
|
||||
virtual void SearchString(const base::char16* string,
|
||||
const base::char16* term,
|
||||
bool case_sensitive,
|
||||
std::vector<SearchStringResult>* results) = 0;
|
||||
|
||||
// Notifies the client that the engine has painted a page from the document.
|
||||
virtual void DocumentPaintOccurred() = 0;
|
||||
|
||||
// Notifies the client that the document has finished loading.
|
||||
virtual void DocumentLoadComplete(int page_count) = 0;
|
||||
|
||||
// Notifies the client that the document has failed to load.
|
||||
virtual void DocumentLoadFailed() = 0;
|
||||
|
||||
virtual pp::Instance* GetPluginInstance() = 0;
|
||||
|
||||
// Notifies that an unsupported feature in the PDF was encountered.
|
||||
virtual void DocumentHasUnsupportedFeature(const std::string& feature) = 0;
|
||||
|
||||
// Notifies the client about document load progress.
|
||||
virtual void DocumentLoadProgress(uint32 available, uint32 doc_size) = 0;
|
||||
|
||||
// Notifies the client about focus changes for form text fields.
|
||||
virtual void FormTextFieldFocusChange(bool in_focus) = 0;
|
||||
|
||||
// Returns true if the plugin has been opened within print preview.
|
||||
virtual bool IsPrintPreview() = 0;
|
||||
};
|
||||
|
||||
// Factory method to create an instance of the PDF Engine.
|
||||
static PDFEngine* Create(Client* client);
|
||||
|
||||
virtual ~PDFEngine() {}
|
||||
// Most of these functions are similar to the Pepper functions of the same
|
||||
// name, so not repeating the description here unless it's different.
|
||||
virtual bool New(const char* url) = 0;
|
||||
virtual bool New(const char* url,
|
||||
const char* headers) = 0;
|
||||
virtual void PageOffsetUpdated(const pp::Point& page_offset) = 0;
|
||||
virtual void PluginSizeUpdated(const pp::Size& size) = 0;
|
||||
virtual void ScrolledToXPosition(int position) = 0;
|
||||
virtual void ScrolledToYPosition(int position) = 0;
|
||||
// Paint is called a series of times. Before these n calls are made, PrePaint
|
||||
// is called once. After Paint is called n times, PostPaint is called once.
|
||||
virtual void PrePaint() = 0;
|
||||
virtual void Paint(const pp::Rect& rect,
|
||||
pp::ImageData* image_data,
|
||||
std::vector<pp::Rect>* ready,
|
||||
std::vector<pp::Rect>* pending) = 0;
|
||||
virtual void PostPaint() = 0;
|
||||
virtual bool HandleDocumentLoad(const pp::URLLoader& loader) = 0;
|
||||
virtual bool HandleEvent(const pp::InputEvent& event) = 0;
|
||||
virtual uint32_t QuerySupportedPrintOutputFormats() = 0;
|
||||
virtual void PrintBegin() = 0;
|
||||
virtual pp::Resource PrintPages(
|
||||
const PP_PrintPageNumberRange_Dev* page_ranges,
|
||||
uint32_t page_range_count,
|
||||
const PP_PrintSettings_Dev& print_settings) = 0;
|
||||
virtual void PrintEnd() = 0;
|
||||
virtual void StartFind(const char* text, bool case_sensitive) = 0;
|
||||
virtual bool SelectFindResult(bool forward) = 0;
|
||||
virtual void StopFind() = 0;
|
||||
virtual void ZoomUpdated(double new_zoom_level) = 0;
|
||||
virtual void RotateClockwise() = 0;
|
||||
virtual void RotateCounterclockwise() = 0;
|
||||
virtual std::string GetSelectedText() = 0;
|
||||
virtual std::string GetLinkAtPosition(const pp::Point& point) = 0;
|
||||
virtual bool IsSelecting() = 0;
|
||||
// Checks the permissions associated with this document.
|
||||
virtual bool HasPermission(DocumentPermission permission) const = 0;
|
||||
virtual void SelectAll() = 0;
|
||||
// Gets the number of pages in the document.
|
||||
virtual int GetNumberOfPages() = 0;
|
||||
// Gets the 0-based page number of |destination|, or -1 if it does not exist.
|
||||
virtual int GetNamedDestinationPage(const std::string& destination) = 0;
|
||||
// Gets the index of the first visible page, or -1 if none are visible.
|
||||
virtual int GetFirstVisiblePage() = 0;
|
||||
// Gets the index of the most visible page, or -1 if none are visible.
|
||||
virtual int GetMostVisiblePage() = 0;
|
||||
// Gets the rectangle of the page including shadow.
|
||||
virtual pp::Rect GetPageRect(int index) = 0;
|
||||
// Gets the rectangle of the page excluding any additional areas.
|
||||
virtual pp::Rect GetPageContentsRect(int index) = 0;
|
||||
// Gets the offset of the vertical scrollbar from the top in document
|
||||
// coordinates.
|
||||
virtual int GetVerticalScrollbarYPosition() = 0;
|
||||
// Paints page thumbnail to the ImageData.
|
||||
virtual void PaintThumbnail(pp::ImageData* image_data, int index) = 0;
|
||||
// Set color / grayscale rendering modes.
|
||||
virtual void SetGrayscale(bool grayscale) = 0;
|
||||
// Callback for timer that's set with ScheduleCallback().
|
||||
virtual void OnCallback(int id) = 0;
|
||||
// Gets the JSON representation of the PDF file
|
||||
virtual std::string GetPageAsJSON(int index) = 0;
|
||||
// Gets the PDF document's print scaling preference. True if the document can
|
||||
// be scaled to fit.
|
||||
virtual bool GetPrintScaling() = 0;
|
||||
|
||||
// Append blank pages to make a 1-page document to a |num_pages| document.
|
||||
// Always retain the first page data.
|
||||
virtual void AppendBlankPages(int num_pages) = 0;
|
||||
// Append the first page of the document loaded with the |engine| to this
|
||||
// document at page |index|.
|
||||
virtual void AppendPage(PDFEngine* engine, int index) = 0;
|
||||
|
||||
// Allow client to query and reset scroll positions in document coordinates.
|
||||
// Note that this is meant for cases where the device scale factor changes,
|
||||
// and not for general scrolling - the engine will not repaint due to this.
|
||||
virtual pp::Point GetScrollPosition() = 0;
|
||||
virtual void SetScrollPosition(const pp::Point& position) = 0;
|
||||
|
||||
virtual bool IsProgressiveLoad() = 0;
|
||||
};
|
||||
|
||||
// Interface for exports that wrap the PDF engine.
|
||||
class PDFEngineExports {
|
||||
public:
|
||||
struct RenderingSettings {
|
||||
RenderingSettings(int dpi_x,
|
||||
int dpi_y,
|
||||
const pp::Rect& bounds,
|
||||
bool fit_to_bounds,
|
||||
bool stretch_to_bounds,
|
||||
bool keep_aspect_ratio,
|
||||
bool center_in_bounds,
|
||||
bool autorotate)
|
||||
: dpi_x(dpi_x), dpi_y(dpi_y), bounds(bounds),
|
||||
fit_to_bounds(fit_to_bounds), stretch_to_bounds(stretch_to_bounds),
|
||||
keep_aspect_ratio(keep_aspect_ratio),
|
||||
center_in_bounds(center_in_bounds), autorotate(autorotate) {
|
||||
}
|
||||
int dpi_x;
|
||||
int dpi_y;
|
||||
pp::Rect bounds;
|
||||
bool fit_to_bounds;
|
||||
bool stretch_to_bounds;
|
||||
bool keep_aspect_ratio;
|
||||
bool center_in_bounds;
|
||||
bool autorotate;
|
||||
};
|
||||
|
||||
PDFEngineExports() {}
|
||||
virtual ~PDFEngineExports() {}
|
||||
static PDFEngineExports* Create();
|
||||
#if defined(OS_WIN)
|
||||
// See the definition of RenderPDFPageToDC in pdf.cc for details.
|
||||
virtual bool RenderPDFPageToDC(const void* pdf_buffer,
|
||||
int buffer_size,
|
||||
int page_number,
|
||||
const RenderingSettings& settings,
|
||||
HDC dc) = 0;
|
||||
#endif // OS_WIN
|
||||
// See the definition of RenderPDFPageToBitmap in pdf.cc for details.
|
||||
virtual bool RenderPDFPageToBitmap(const void* pdf_buffer,
|
||||
int pdf_buffer_size,
|
||||
int page_number,
|
||||
const RenderingSettings& settings,
|
||||
void* bitmap_buffer) = 0;
|
||||
virtual bool GetPDFDocInfo(const void* pdf_buffer,
|
||||
int buffer_size,
|
||||
int* page_count,
|
||||
double* max_page_width) = 0;
|
||||
};
|
||||
|
||||
} // namespace chrome_pdf
|
||||
|
||||
#endif // PDF_PDF_ENGINE_H_
|
207
pdf/pdfium/pdfium_assert_matching_enums.cc
Normal file
207
pdf/pdfium/pdfium_assert_matching_enums.cc
Normal file
@ -0,0 +1,207 @@
|
||||
// Copyright (c) 2010 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 "base/basictypes.h"
|
||||
#include "ppapi/c/pp_input_event.h"
|
||||
#include "ppapi/c/private/ppb_pdf.h"
|
||||
#include "third_party/pdfium/fpdfsdk/include/fpdf_fwlevent.h"
|
||||
#include "third_party/pdfium/fpdfsdk/include/fpdf_sysfontinfo.h"
|
||||
#include "ui/events/keycodes/keyboard_codes.h"
|
||||
|
||||
#define COMPILE_ASSERT_MATCH(np_name, pdfium_name) \
|
||||
COMPILE_ASSERT(int(np_name) == int(pdfium_name), mismatching_enums)
|
||||
|
||||
COMPILE_ASSERT_MATCH(PP_INPUTEVENT_MODIFIER_SHIFTKEY, FWL_EVENTFLAG_ShiftKey);
|
||||
COMPILE_ASSERT_MATCH(PP_INPUTEVENT_MODIFIER_CONTROLKEY,
|
||||
FWL_EVENTFLAG_ControlKey);
|
||||
COMPILE_ASSERT_MATCH(PP_INPUTEVENT_MODIFIER_ALTKEY, FWL_EVENTFLAG_AltKey);
|
||||
COMPILE_ASSERT_MATCH(PP_INPUTEVENT_MODIFIER_METAKEY, FWL_EVENTFLAG_MetaKey);
|
||||
COMPILE_ASSERT_MATCH(PP_INPUTEVENT_MODIFIER_ISKEYPAD, FWL_EVENTFLAG_KeyPad);
|
||||
COMPILE_ASSERT_MATCH(PP_INPUTEVENT_MODIFIER_ISAUTOREPEAT,
|
||||
FWL_EVENTFLAG_AutoRepeat);
|
||||
COMPILE_ASSERT_MATCH(PP_INPUTEVENT_MODIFIER_LEFTBUTTONDOWN,
|
||||
FWL_EVENTFLAG_LeftButtonDown);
|
||||
COMPILE_ASSERT_MATCH(PP_INPUTEVENT_MODIFIER_MIDDLEBUTTONDOWN,
|
||||
FWL_EVENTFLAG_MiddleButtonDown);
|
||||
COMPILE_ASSERT_MATCH(PP_INPUTEVENT_MODIFIER_RIGHTBUTTONDOWN,
|
||||
FWL_EVENTFLAG_RightButtonDown);
|
||||
|
||||
COMPILE_ASSERT_MATCH(ui::VKEY_BACK, FWL_VKEY_Back);
|
||||
COMPILE_ASSERT_MATCH(ui::VKEY_TAB, FWL_VKEY_Tab);
|
||||
COMPILE_ASSERT_MATCH(ui::VKEY_CLEAR, FWL_VKEY_Clear);
|
||||
COMPILE_ASSERT_MATCH(ui::VKEY_RETURN, FWL_VKEY_Return);
|
||||
COMPILE_ASSERT_MATCH(ui::VKEY_SHIFT, FWL_VKEY_Shift);
|
||||
COMPILE_ASSERT_MATCH(ui::VKEY_CONTROL, FWL_VKEY_Control);
|
||||
COMPILE_ASSERT_MATCH(ui::VKEY_MENU, FWL_VKEY_Menu);
|
||||
COMPILE_ASSERT_MATCH(ui::VKEY_PAUSE, FWL_VKEY_Pause);
|
||||
COMPILE_ASSERT_MATCH(ui::VKEY_CAPITAL, FWL_VKEY_Capital);
|
||||
COMPILE_ASSERT_MATCH(ui::VKEY_KANA, FWL_VKEY_Kana);
|
||||
COMPILE_ASSERT_MATCH(ui::VKEY_HANGUL, FWL_VKEY_Hangul);
|
||||
COMPILE_ASSERT_MATCH(ui::VKEY_JUNJA, FWL_VKEY_Junja);
|
||||
COMPILE_ASSERT_MATCH(ui::VKEY_FINAL, FWL_VKEY_Final);
|
||||
COMPILE_ASSERT_MATCH(ui::VKEY_HANJA, FWL_VKEY_Hanja);
|
||||
COMPILE_ASSERT_MATCH(ui::VKEY_KANJI, FWL_VKEY_Kanji);
|
||||
COMPILE_ASSERT_MATCH(ui::VKEY_ESCAPE, FWL_VKEY_Escape);
|
||||
COMPILE_ASSERT_MATCH(ui::VKEY_CONVERT, FWL_VKEY_Convert);
|
||||
COMPILE_ASSERT_MATCH(ui::VKEY_NONCONVERT, FWL_VKEY_NonConvert);
|
||||
COMPILE_ASSERT_MATCH(ui::VKEY_ACCEPT, FWL_VKEY_Accept);
|
||||
COMPILE_ASSERT_MATCH(ui::VKEY_MODECHANGE, FWL_VKEY_ModeChange);
|
||||
COMPILE_ASSERT_MATCH(ui::VKEY_SPACE, FWL_VKEY_Space);
|
||||
COMPILE_ASSERT_MATCH(ui::VKEY_PRIOR, FWL_VKEY_Prior);
|
||||
COMPILE_ASSERT_MATCH(ui::VKEY_NEXT, FWL_VKEY_Next);
|
||||
COMPILE_ASSERT_MATCH(ui::VKEY_END, FWL_VKEY_End);
|
||||
COMPILE_ASSERT_MATCH(ui::VKEY_HOME, FWL_VKEY_Home);
|
||||
COMPILE_ASSERT_MATCH(ui::VKEY_LEFT, FWL_VKEY_Left);
|
||||
COMPILE_ASSERT_MATCH(ui::VKEY_UP, FWL_VKEY_Up);
|
||||
COMPILE_ASSERT_MATCH(ui::VKEY_RIGHT, FWL_VKEY_Right);
|
||||
COMPILE_ASSERT_MATCH(ui::VKEY_DOWN, FWL_VKEY_Down);
|
||||
COMPILE_ASSERT_MATCH(ui::VKEY_SELECT, FWL_VKEY_Select);
|
||||
COMPILE_ASSERT_MATCH(ui::VKEY_PRINT, FWL_VKEY_Print);
|
||||
COMPILE_ASSERT_MATCH(ui::VKEY_EXECUTE, FWL_VKEY_Execute);
|
||||
COMPILE_ASSERT_MATCH(ui::VKEY_SNAPSHOT, FWL_VKEY_Snapshot);
|
||||
COMPILE_ASSERT_MATCH(ui::VKEY_INSERT, FWL_VKEY_Insert);
|
||||
COMPILE_ASSERT_MATCH(ui::VKEY_DELETE, FWL_VKEY_Delete);
|
||||
COMPILE_ASSERT_MATCH(ui::VKEY_HELP, FWL_VKEY_Help);
|
||||
COMPILE_ASSERT_MATCH(ui::VKEY_0, FWL_VKEY_0);
|
||||
COMPILE_ASSERT_MATCH(ui::VKEY_1, FWL_VKEY_1);
|
||||
COMPILE_ASSERT_MATCH(ui::VKEY_2, FWL_VKEY_2);
|
||||
COMPILE_ASSERT_MATCH(ui::VKEY_3, FWL_VKEY_3);
|
||||
COMPILE_ASSERT_MATCH(ui::VKEY_4, FWL_VKEY_4);
|
||||
COMPILE_ASSERT_MATCH(ui::VKEY_5, FWL_VKEY_5);
|
||||
COMPILE_ASSERT_MATCH(ui::VKEY_6, FWL_VKEY_6);
|
||||
COMPILE_ASSERT_MATCH(ui::VKEY_7, FWL_VKEY_7);
|
||||
COMPILE_ASSERT_MATCH(ui::VKEY_8, FWL_VKEY_8);
|
||||
COMPILE_ASSERT_MATCH(ui::VKEY_9, FWL_VKEY_9);
|
||||
COMPILE_ASSERT_MATCH(ui::VKEY_A, FWL_VKEY_A);
|
||||
COMPILE_ASSERT_MATCH(ui::VKEY_B, FWL_VKEY_B);
|
||||
COMPILE_ASSERT_MATCH(ui::VKEY_C, FWL_VKEY_C);
|
||||
COMPILE_ASSERT_MATCH(ui::VKEY_D, FWL_VKEY_D);
|
||||
COMPILE_ASSERT_MATCH(ui::VKEY_E, FWL_VKEY_E);
|
||||
COMPILE_ASSERT_MATCH(ui::VKEY_F, FWL_VKEY_F);
|
||||
COMPILE_ASSERT_MATCH(ui::VKEY_G, FWL_VKEY_G);
|
||||
COMPILE_ASSERT_MATCH(ui::VKEY_H, FWL_VKEY_H);
|
||||
COMPILE_ASSERT_MATCH(ui::VKEY_I, FWL_VKEY_I);
|
||||
COMPILE_ASSERT_MATCH(ui::VKEY_J, FWL_VKEY_J);
|
||||
COMPILE_ASSERT_MATCH(ui::VKEY_K, FWL_VKEY_K);
|
||||
COMPILE_ASSERT_MATCH(ui::VKEY_L, FWL_VKEY_L);
|
||||
COMPILE_ASSERT_MATCH(ui::VKEY_M, FWL_VKEY_M);
|
||||
COMPILE_ASSERT_MATCH(ui::VKEY_N, FWL_VKEY_N);
|
||||
COMPILE_ASSERT_MATCH(ui::VKEY_O, FWL_VKEY_O);
|
||||
COMPILE_ASSERT_MATCH(ui::VKEY_P, FWL_VKEY_P);
|
||||
COMPILE_ASSERT_MATCH(ui::VKEY_Q, FWL_VKEY_Q);
|
||||
COMPILE_ASSERT_MATCH(ui::VKEY_R, FWL_VKEY_R);
|
||||
COMPILE_ASSERT_MATCH(ui::VKEY_S, FWL_VKEY_S);
|
||||
COMPILE_ASSERT_MATCH(ui::VKEY_T, FWL_VKEY_T);
|
||||
COMPILE_ASSERT_MATCH(ui::VKEY_U, FWL_VKEY_U);
|
||||
COMPILE_ASSERT_MATCH(ui::VKEY_V, FWL_VKEY_V);
|
||||
COMPILE_ASSERT_MATCH(ui::VKEY_W, FWL_VKEY_W);
|
||||
COMPILE_ASSERT_MATCH(ui::VKEY_X, FWL_VKEY_X);
|
||||
COMPILE_ASSERT_MATCH(ui::VKEY_Y, FWL_VKEY_Y);
|
||||
COMPILE_ASSERT_MATCH(ui::VKEY_Z, FWL_VKEY_Z);
|
||||
COMPILE_ASSERT_MATCH(ui::VKEY_LWIN, FWL_VKEY_LWin);
|
||||
COMPILE_ASSERT_MATCH(ui::VKEY_COMMAND, FWL_VKEY_Command);
|
||||
COMPILE_ASSERT_MATCH(ui::VKEY_RWIN, FWL_VKEY_RWin);
|
||||
COMPILE_ASSERT_MATCH(ui::VKEY_APPS, FWL_VKEY_Apps);
|
||||
COMPILE_ASSERT_MATCH(ui::VKEY_SLEEP, FWL_VKEY_Sleep);
|
||||
COMPILE_ASSERT_MATCH(ui::VKEY_NUMPAD0, FWL_VKEY_NumPad0);
|
||||
COMPILE_ASSERT_MATCH(ui::VKEY_NUMPAD1, FWL_VKEY_NumPad1);
|
||||
COMPILE_ASSERT_MATCH(ui::VKEY_NUMPAD2, FWL_VKEY_NumPad2);
|
||||
COMPILE_ASSERT_MATCH(ui::VKEY_NUMPAD3, FWL_VKEY_NumPad3);
|
||||
COMPILE_ASSERT_MATCH(ui::VKEY_NUMPAD4, FWL_VKEY_NumPad4);
|
||||
COMPILE_ASSERT_MATCH(ui::VKEY_NUMPAD5, FWL_VKEY_NumPad5);
|
||||
COMPILE_ASSERT_MATCH(ui::VKEY_NUMPAD6, FWL_VKEY_NumPad6);
|
||||
COMPILE_ASSERT_MATCH(ui::VKEY_NUMPAD7, FWL_VKEY_NumPad7);
|
||||
COMPILE_ASSERT_MATCH(ui::VKEY_NUMPAD8, FWL_VKEY_NumPad8);
|
||||
COMPILE_ASSERT_MATCH(ui::VKEY_NUMPAD9, FWL_VKEY_NumPad9);
|
||||
COMPILE_ASSERT_MATCH(ui::VKEY_MULTIPLY, FWL_VKEY_Multiply);
|
||||
COMPILE_ASSERT_MATCH(ui::VKEY_ADD, FWL_VKEY_Add);
|
||||
COMPILE_ASSERT_MATCH(ui::VKEY_SEPARATOR, FWL_VKEY_Separator);
|
||||
COMPILE_ASSERT_MATCH(ui::VKEY_SUBTRACT, FWL_VKEY_Subtract);
|
||||
COMPILE_ASSERT_MATCH(ui::VKEY_DECIMAL, FWL_VKEY_Decimal);
|
||||
COMPILE_ASSERT_MATCH(ui::VKEY_DIVIDE, FWL_VKEY_Divide);
|
||||
COMPILE_ASSERT_MATCH(ui::VKEY_F1, FWL_VKEY_F1);
|
||||
COMPILE_ASSERT_MATCH(ui::VKEY_F2, FWL_VKEY_F2);
|
||||
COMPILE_ASSERT_MATCH(ui::VKEY_F3, FWL_VKEY_F3);
|
||||
COMPILE_ASSERT_MATCH(ui::VKEY_F4, FWL_VKEY_F4);
|
||||
COMPILE_ASSERT_MATCH(ui::VKEY_F5, FWL_VKEY_F5);
|
||||
COMPILE_ASSERT_MATCH(ui::VKEY_F6, FWL_VKEY_F6);
|
||||
COMPILE_ASSERT_MATCH(ui::VKEY_F7, FWL_VKEY_F7);
|
||||
COMPILE_ASSERT_MATCH(ui::VKEY_F8, FWL_VKEY_F8);
|
||||
COMPILE_ASSERT_MATCH(ui::VKEY_F9, FWL_VKEY_F9);
|
||||
COMPILE_ASSERT_MATCH(ui::VKEY_F10, FWL_VKEY_F10);
|
||||
COMPILE_ASSERT_MATCH(ui::VKEY_F11, FWL_VKEY_F11);
|
||||
COMPILE_ASSERT_MATCH(ui::VKEY_F12, FWL_VKEY_F12);
|
||||
COMPILE_ASSERT_MATCH(ui::VKEY_F13, FWL_VKEY_F13);
|
||||
COMPILE_ASSERT_MATCH(ui::VKEY_F14, FWL_VKEY_F14);
|
||||
COMPILE_ASSERT_MATCH(ui::VKEY_F15, FWL_VKEY_F15);
|
||||
COMPILE_ASSERT_MATCH(ui::VKEY_F16, FWL_VKEY_F16);
|
||||
COMPILE_ASSERT_MATCH(ui::VKEY_F17, FWL_VKEY_F17);
|
||||
COMPILE_ASSERT_MATCH(ui::VKEY_F18, FWL_VKEY_F18);
|
||||
COMPILE_ASSERT_MATCH(ui::VKEY_F19, FWL_VKEY_F19);
|
||||
COMPILE_ASSERT_MATCH(ui::VKEY_F20, FWL_VKEY_F20);
|
||||
COMPILE_ASSERT_MATCH(ui::VKEY_F21, FWL_VKEY_F21);
|
||||
COMPILE_ASSERT_MATCH(ui::VKEY_F22, FWL_VKEY_F22);
|
||||
COMPILE_ASSERT_MATCH(ui::VKEY_F23, FWL_VKEY_F23);
|
||||
COMPILE_ASSERT_MATCH(ui::VKEY_F24, FWL_VKEY_F24);
|
||||
COMPILE_ASSERT_MATCH(ui::VKEY_NUMLOCK, FWL_VKEY_NunLock);
|
||||
COMPILE_ASSERT_MATCH(ui::VKEY_SCROLL, FWL_VKEY_Scroll);
|
||||
COMPILE_ASSERT_MATCH(ui::VKEY_LSHIFT, FWL_VKEY_LShift);
|
||||
COMPILE_ASSERT_MATCH(ui::VKEY_RSHIFT, FWL_VKEY_RShift);
|
||||
COMPILE_ASSERT_MATCH(ui::VKEY_LCONTROL, FWL_VKEY_LControl);
|
||||
COMPILE_ASSERT_MATCH(ui::VKEY_RCONTROL, FWL_VKEY_RControl);
|
||||
COMPILE_ASSERT_MATCH(ui::VKEY_LMENU, FWL_VKEY_LMenu);
|
||||
COMPILE_ASSERT_MATCH(ui::VKEY_RMENU, FWL_VKEY_RMenu);
|
||||
COMPILE_ASSERT_MATCH(ui::VKEY_BROWSER_BACK, FWL_VKEY_BROWSER_Back);
|
||||
COMPILE_ASSERT_MATCH(ui::VKEY_BROWSER_FORWARD, FWL_VKEY_BROWSER_Forward);
|
||||
COMPILE_ASSERT_MATCH(ui::VKEY_BROWSER_REFRESH, FWL_VKEY_BROWSER_Refresh);
|
||||
COMPILE_ASSERT_MATCH(ui::VKEY_BROWSER_STOP, FWL_VKEY_BROWSER_Stop);
|
||||
COMPILE_ASSERT_MATCH(ui::VKEY_BROWSER_SEARCH, FWL_VKEY_BROWSER_Search);
|
||||
COMPILE_ASSERT_MATCH(ui::VKEY_BROWSER_FAVORITES, FWL_VKEY_BROWSER_Favorites);
|
||||
COMPILE_ASSERT_MATCH(ui::VKEY_BROWSER_HOME, FWL_VKEY_BROWSER_Home);
|
||||
COMPILE_ASSERT_MATCH(ui::VKEY_VOLUME_MUTE, FWL_VKEY_VOLUME_Mute);
|
||||
COMPILE_ASSERT_MATCH(ui::VKEY_VOLUME_DOWN, FWL_VKEY_VOLUME_Down);
|
||||
COMPILE_ASSERT_MATCH(ui::VKEY_VOLUME_UP, FWL_VKEY_VOLUME_Up);
|
||||
COMPILE_ASSERT_MATCH(ui::VKEY_MEDIA_NEXT_TRACK, FWL_VKEY_MEDIA_NEXT_Track);
|
||||
COMPILE_ASSERT_MATCH(ui::VKEY_MEDIA_PREV_TRACK, FWL_VKEY_MEDIA_PREV_Track);
|
||||
COMPILE_ASSERT_MATCH(ui::VKEY_MEDIA_STOP, FWL_VKEY_MEDIA_Stop);
|
||||
COMPILE_ASSERT_MATCH(ui::VKEY_MEDIA_PLAY_PAUSE, FWL_VKEY_MEDIA_PLAY_Pause);
|
||||
COMPILE_ASSERT_MATCH(ui::VKEY_MEDIA_LAUNCH_MAIL, FWL_VKEY_MEDIA_LAUNCH_Mail);
|
||||
COMPILE_ASSERT_MATCH(ui::VKEY_MEDIA_LAUNCH_MEDIA_SELECT,
|
||||
FWL_VKEY_MEDIA_LAUNCH_MEDIA_Select);
|
||||
COMPILE_ASSERT_MATCH(ui::VKEY_MEDIA_LAUNCH_APP1, FWL_VKEY_MEDIA_LAUNCH_APP1);
|
||||
COMPILE_ASSERT_MATCH(ui::VKEY_MEDIA_LAUNCH_APP2, FWL_VKEY_MEDIA_LAUNCH_APP2);
|
||||
COMPILE_ASSERT_MATCH(ui::VKEY_OEM_1, FWL_VKEY_OEM_1);
|
||||
COMPILE_ASSERT_MATCH(ui::VKEY_OEM_PLUS, FWL_VKEY_OEM_Plus);
|
||||
COMPILE_ASSERT_MATCH(ui::VKEY_OEM_COMMA, FWL_VKEY_OEM_Comma);
|
||||
COMPILE_ASSERT_MATCH(ui::VKEY_OEM_MINUS, FWL_VKEY_OEM_Minus);
|
||||
COMPILE_ASSERT_MATCH(ui::VKEY_OEM_PERIOD, FWL_VKEY_OEM_Period);
|
||||
COMPILE_ASSERT_MATCH(ui::VKEY_OEM_2, FWL_VKEY_OEM_2);
|
||||
COMPILE_ASSERT_MATCH(ui::VKEY_OEM_3, FWL_VKEY_OEM_3);
|
||||
COMPILE_ASSERT_MATCH(ui::VKEY_OEM_4, FWL_VKEY_OEM_4);
|
||||
COMPILE_ASSERT_MATCH(ui::VKEY_OEM_5, FWL_VKEY_OEM_5);
|
||||
COMPILE_ASSERT_MATCH(ui::VKEY_OEM_6, FWL_VKEY_OEM_6);
|
||||
COMPILE_ASSERT_MATCH(ui::VKEY_OEM_7, FWL_VKEY_OEM_7);
|
||||
COMPILE_ASSERT_MATCH(ui::VKEY_OEM_8, FWL_VKEY_OEM_8);
|
||||
COMPILE_ASSERT_MATCH(ui::VKEY_OEM_102, FWL_VKEY_OEM_102);
|
||||
COMPILE_ASSERT_MATCH(ui::VKEY_PROCESSKEY, FWL_VKEY_ProcessKey);
|
||||
COMPILE_ASSERT_MATCH(ui::VKEY_PACKET, FWL_VKEY_Packet);
|
||||
COMPILE_ASSERT_MATCH(ui::VKEY_ATTN, FWL_VKEY_Attn);
|
||||
COMPILE_ASSERT_MATCH(ui::VKEY_CRSEL, FWL_VKEY_Crsel);
|
||||
COMPILE_ASSERT_MATCH(ui::VKEY_EXSEL, FWL_VKEY_Exsel);
|
||||
COMPILE_ASSERT_MATCH(ui::VKEY_EREOF, FWL_VKEY_Ereof);
|
||||
COMPILE_ASSERT_MATCH(ui::VKEY_PLAY, FWL_VKEY_Play);
|
||||
COMPILE_ASSERT_MATCH(ui::VKEY_ZOOM, FWL_VKEY_Zoom);
|
||||
COMPILE_ASSERT_MATCH(ui::VKEY_NONAME, FWL_VKEY_NoName);
|
||||
COMPILE_ASSERT_MATCH(ui::VKEY_PA1, FWL_VKEY_PA1);
|
||||
COMPILE_ASSERT_MATCH(ui::VKEY_OEM_CLEAR, FWL_VKEY_OEM_Clear);
|
||||
COMPILE_ASSERT_MATCH(ui::VKEY_UNKNOWN, FWL_VKEY_Unknown);
|
||||
|
||||
COMPILE_ASSERT_MATCH(PP_PRIVATEFONTCHARSET_ANSI, FXFONT_ANSI_CHARSET);
|
||||
COMPILE_ASSERT_MATCH(PP_PRIVATEFONTCHARSET_DEFAULT, FXFONT_DEFAULT_CHARSET);
|
||||
COMPILE_ASSERT_MATCH(PP_PRIVATEFONTCHARSET_SYMBOL, FXFONT_SYMBOL_CHARSET);
|
||||
COMPILE_ASSERT_MATCH(PP_PRIVATEFONTCHARSET_SHIFTJIS, FXFONT_SHIFTJIS_CHARSET);
|
||||
COMPILE_ASSERT_MATCH(PP_PRIVATEFONTCHARSET_HANGUL, FXFONT_HANGEUL_CHARSET);
|
||||
COMPILE_ASSERT_MATCH(PP_PRIVATEFONTCHARSET_GB2312, FXFONT_GB2312_CHARSET);
|
||||
COMPILE_ASSERT_MATCH(PP_PRIVATEFONTCHARSET_CHINESEBIG5,
|
||||
FXFONT_CHINESEBIG5_CHARSET);
|
3389
pdf/pdfium/pdfium_engine.cc
Normal file
3389
pdf/pdfium/pdfium_engine.cc
Normal file
File diff suppressed because it is too large
Load Diff
621
pdf/pdfium/pdfium_engine.h
Normal file
621
pdf/pdfium/pdfium_engine.h
Normal file
@ -0,0 +1,621 @@
|
||||
// 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.
|
||||
|
||||
#ifndef PDF_PDFIUM_PDFIUM_ENGINE_H_
|
||||
#define PDF_PDFIUM_PDFIUM_ENGINE_H_
|
||||
|
||||
#include <map>
|
||||
#include <string>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
#include "base/memory/scoped_ptr.h"
|
||||
#include "base/time/time.h"
|
||||
#include "pdf/document_loader.h"
|
||||
#include "pdf/pdf_engine.h"
|
||||
#include "pdf/pdfium/pdfium_page.h"
|
||||
#include "pdf/pdfium/pdfium_range.h"
|
||||
#include "ppapi/cpp/completion_callback.h"
|
||||
#include "ppapi/cpp/dev/buffer_dev.h"
|
||||
#include "ppapi/cpp/image_data.h"
|
||||
#include "ppapi/cpp/point.h"
|
||||
#include "third_party/pdfium/fpdfsdk/include/fpdf_dataavail.h"
|
||||
#include "third_party/pdfium/fpdfsdk/include/fpdf_progressive.h"
|
||||
#include "third_party/pdfium/fpdfsdk/include/fpdfformfill.h"
|
||||
#include "third_party/pdfium/fpdfsdk/include/fpdfview.h"
|
||||
|
||||
namespace pp {
|
||||
class KeyboardInputEvent;
|
||||
class MouseInputEvent;
|
||||
}
|
||||
|
||||
namespace chrome_pdf {
|
||||
|
||||
class ShadowMatrix;
|
||||
|
||||
class PDFiumEngine : public PDFEngine,
|
||||
public DocumentLoader::Client,
|
||||
public FPDF_FORMFILLINFO,
|
||||
public IPDF_JSPLATFORM,
|
||||
public IFSDK_PAUSE {
|
||||
public:
|
||||
explicit PDFiumEngine(PDFEngine::Client* client);
|
||||
virtual ~PDFiumEngine();
|
||||
|
||||
// PDFEngine implementation.
|
||||
virtual bool New(const char* url);
|
||||
virtual bool New(const char* url,
|
||||
const char* headers);
|
||||
virtual void PageOffsetUpdated(const pp::Point& page_offset);
|
||||
virtual void PluginSizeUpdated(const pp::Size& size);
|
||||
virtual void ScrolledToXPosition(int position);
|
||||
virtual void ScrolledToYPosition(int position);
|
||||
virtual void PrePaint();
|
||||
virtual void Paint(const pp::Rect& rect,
|
||||
pp::ImageData* image_data,
|
||||
std::vector<pp::Rect>* ready,
|
||||
std::vector<pp::Rect>* pending);
|
||||
virtual void PostPaint();
|
||||
virtual bool HandleDocumentLoad(const pp::URLLoader& loader);
|
||||
virtual bool HandleEvent(const pp::InputEvent& event);
|
||||
virtual uint32_t QuerySupportedPrintOutputFormats();
|
||||
virtual void PrintBegin();
|
||||
virtual pp::Resource PrintPages(
|
||||
const PP_PrintPageNumberRange_Dev* page_ranges,
|
||||
uint32_t page_range_count,
|
||||
const PP_PrintSettings_Dev& print_settings);
|
||||
virtual void PrintEnd();
|
||||
virtual void StartFind(const char* text, bool case_sensitive);
|
||||
virtual bool SelectFindResult(bool forward);
|
||||
virtual void StopFind();
|
||||
virtual void ZoomUpdated(double new_zoom_level);
|
||||
virtual void RotateClockwise();
|
||||
virtual void RotateCounterclockwise();
|
||||
virtual std::string GetSelectedText();
|
||||
virtual std::string GetLinkAtPosition(const pp::Point& point);
|
||||
virtual bool IsSelecting();
|
||||
virtual bool HasPermission(DocumentPermission permission) const;
|
||||
virtual void SelectAll();
|
||||
virtual int GetNumberOfPages();
|
||||
virtual int GetNamedDestinationPage(const std::string& destination);
|
||||
virtual int GetFirstVisiblePage();
|
||||
virtual int GetMostVisiblePage();
|
||||
virtual pp::Rect GetPageRect(int index);
|
||||
virtual pp::Rect GetPageContentsRect(int index);
|
||||
virtual int GetVerticalScrollbarYPosition() { return position_.y(); }
|
||||
virtual void PaintThumbnail(pp::ImageData* image_data, int index);
|
||||
virtual void SetGrayscale(bool grayscale);
|
||||
virtual void OnCallback(int id);
|
||||
virtual std::string GetPageAsJSON(int index);
|
||||
virtual bool GetPrintScaling();
|
||||
virtual void AppendBlankPages(int num_pages);
|
||||
virtual void AppendPage(PDFEngine* engine, int index);
|
||||
virtual pp::Point GetScrollPosition();
|
||||
virtual void SetScrollPosition(const pp::Point& position);
|
||||
virtual bool IsProgressiveLoad();
|
||||
|
||||
// DocumentLoader::Client implementation.
|
||||
virtual pp::Instance* GetPluginInstance();
|
||||
virtual pp::URLLoader CreateURLLoader();
|
||||
virtual void OnPartialDocumentLoaded();
|
||||
virtual void OnPendingRequestComplete();
|
||||
virtual void OnNewDataAvailable();
|
||||
virtual void OnDocumentComplete();
|
||||
|
||||
void UnsupportedFeature(int type);
|
||||
|
||||
std::string current_find_text() const { return current_find_text_; }
|
||||
|
||||
FPDF_DOCUMENT doc() { return doc_; }
|
||||
FPDF_FORMHANDLE form() { return form_; }
|
||||
|
||||
private:
|
||||
// This helper class is used to detect the difference in selection between
|
||||
// construction and destruction. At destruction, it invalidates all the
|
||||
// parts that are newly selected, along with all the parts that used to be
|
||||
// selected but are not anymore.
|
||||
class SelectionChangeInvalidator {
|
||||
public:
|
||||
explicit SelectionChangeInvalidator(PDFiumEngine* engine);
|
||||
~SelectionChangeInvalidator();
|
||||
private:
|
||||
// Sets the given container to the all the currently visible selection
|
||||
// rectangles, in screen coordinates.
|
||||
void GetVisibleSelectionsScreenRects(std::vector<pp::Rect>* rects);
|
||||
|
||||
PDFiumEngine* engine_;
|
||||
// Screen rectangles that were selected on construction.
|
||||
std::vector<pp::Rect> old_selections_;
|
||||
// The origin at the time this object was constructed.
|
||||
pp::Point previous_origin_;
|
||||
};
|
||||
|
||||
friend class SelectionChangeInvalidator;
|
||||
|
||||
struct FileAvail : public FX_FILEAVAIL {
|
||||
DocumentLoader* loader;
|
||||
};
|
||||
|
||||
struct DownloadHints : public FX_DOWNLOADHINTS {
|
||||
DocumentLoader* loader;
|
||||
};
|
||||
|
||||
// PDFium interface to get block of data.
|
||||
static int GetBlock(void* param, unsigned long position,
|
||||
unsigned char* buffer, unsigned long size);
|
||||
|
||||
// PDFium interface to check is block of data is available.
|
||||
static bool IsDataAvail(FX_FILEAVAIL* param,
|
||||
size_t offset, size_t size);
|
||||
|
||||
// PDFium interface to request download of the block of data.
|
||||
static void AddSegment(FX_DOWNLOADHINTS* param,
|
||||
size_t offset, size_t size);
|
||||
|
||||
// We finished getting the pdf file, so load it. This will complete
|
||||
// asynchronously (due to password fetching) and may be run multiple times.
|
||||
void LoadDocument();
|
||||
|
||||
// Try loading the document. Returns true if the document is successfully
|
||||
// loaded or is already loaded otherwise it will return false. If
|
||||
// |with_password| is set to true, the document will be loaded with
|
||||
// |password|. If the document could not be loaded and needs a password,
|
||||
// |needs_password| will be set to true.
|
||||
bool TryLoadingDoc(bool with_password,
|
||||
const std::string& password,
|
||||
bool* needs_password);
|
||||
|
||||
// Ask the user for the document password and then continue loading the
|
||||
// document.
|
||||
void GetPasswordAndLoad();
|
||||
|
||||
// Called when the password has been retrieved.
|
||||
void OnGetPasswordComplete(int32_t result,
|
||||
const pp::Var& password);
|
||||
|
||||
// Continues loading the document when the password has been retrieved, or if
|
||||
// there is no password.
|
||||
void ContinueLoadingDocument(bool has_password,
|
||||
const std::string& password);
|
||||
|
||||
// Finish loading the document and notify the client that the document has
|
||||
// been loaded. This should only be run after |doc_| has been loaded and the
|
||||
// document is fully downloaded. If this has been run once, it will result in
|
||||
// a no-op.
|
||||
void FinishLoadingDocument();
|
||||
|
||||
// Loads information about the pages in the document and calculate the
|
||||
// document size.
|
||||
void LoadPageInfo(bool reload);
|
||||
|
||||
// Calculate which pages should be displayed right now.
|
||||
void CalculateVisiblePages();
|
||||
|
||||
// Returns true iff the given page index is visible. CalculateVisiblePages
|
||||
// must have been called first.
|
||||
bool IsPageVisible(int index) const;
|
||||
|
||||
// Checks if a page is now available, and if so marks it as such and returns
|
||||
// true. Otherwise, it will return false and will add the index to the given
|
||||
// array if it's not already there.
|
||||
bool CheckPageAvailable(int index, std::vector<int>* pending);
|
||||
|
||||
// Helper function to get a given page's size in pixels. This is not part of
|
||||
// PDFiumPage because we might not have that structure when we need this.
|
||||
pp::Size GetPageSize(int index);
|
||||
|
||||
void UpdateTickMarks();
|
||||
|
||||
// Called to continue searching so we don't block the main thread.
|
||||
void ContinueFind(int32_t result);
|
||||
|
||||
// Inserts a find result into find_results_, which is sorted.
|
||||
void AddFindResult(const PDFiumRange& result);
|
||||
|
||||
// Search a page using PDFium's methods. Doesn't work with unicode. This
|
||||
// function is just kept arount in case PDFium code is fixed.
|
||||
void SearchUsingPDFium(const base::string16& term,
|
||||
bool case_sensitive,
|
||||
bool first_search,
|
||||
int character_to_start_searching_from,
|
||||
int current_page);
|
||||
|
||||
// Search a page ourself using ICU.
|
||||
void SearchUsingICU(const base::string16& term,
|
||||
bool case_sensitive,
|
||||
bool first_search,
|
||||
int character_to_start_searching_from,
|
||||
int current_page);
|
||||
|
||||
// Input event handlers.
|
||||
bool OnMouseDown(const pp::MouseInputEvent& event);
|
||||
bool OnMouseUp(const pp::MouseInputEvent& event);
|
||||
bool OnMouseMove(const pp::MouseInputEvent& event);
|
||||
bool OnKeyDown(const pp::KeyboardInputEvent& event);
|
||||
bool OnKeyUp(const pp::KeyboardInputEvent& event);
|
||||
bool OnChar(const pp::KeyboardInputEvent& event);
|
||||
|
||||
pp::Buffer_Dev PrintPagesAsRasterPDF(
|
||||
const PP_PrintPageNumberRange_Dev* page_ranges,
|
||||
uint32_t page_range_count,
|
||||
const PP_PrintSettings_Dev& print_settings);
|
||||
pp::Buffer_Dev PrintPagesAsPDF(const PP_PrintPageNumberRange_Dev* page_ranges,
|
||||
uint32_t page_range_count,
|
||||
const PP_PrintSettings_Dev& print_settings);
|
||||
pp::Buffer_Dev GetFlattenedPrintData(const FPDF_DOCUMENT& doc);
|
||||
void FitContentsToPrintableAreaIfRequired(
|
||||
const FPDF_DOCUMENT& doc,
|
||||
const PP_PrintSettings_Dev& print_settings);
|
||||
void SaveSelectedFormForPrint();
|
||||
|
||||
// Given a mouse event, returns which page and character location it's closest
|
||||
// to.
|
||||
PDFiumPage::Area GetCharIndex(const pp::MouseInputEvent& event,
|
||||
int* page_index,
|
||||
int* char_index,
|
||||
PDFiumPage::LinkTarget* target);
|
||||
PDFiumPage::Area GetCharIndex(const pp::Point& point,
|
||||
int* page_index,
|
||||
int* char_index,
|
||||
PDFiumPage::LinkTarget* target);
|
||||
|
||||
void OnSingleClick(int page_index, int char_index);
|
||||
void OnMultipleClick(int click_count, int page_index, int char_index);
|
||||
|
||||
// Starts a progressive paint operation given a rectangle in screen
|
||||
// coordinates. Returns the index in progressive_rects_.
|
||||
int StartPaint(int page_index, const pp::Rect& dirty);
|
||||
|
||||
// Continues a paint operation that was started earlier. Returns true if the
|
||||
// paint is done, or false if it needs to be continued.
|
||||
bool ContinuePaint(int progressive_index, pp::ImageData* image_data);
|
||||
|
||||
// Called once PDFium is finished rendering a page so that we draw our
|
||||
// borders, highlighting etc.
|
||||
void FinishPaint(int progressive_index, pp::ImageData* image_data);
|
||||
|
||||
// Stops any paints that are in progress.
|
||||
void CancelPaints();
|
||||
|
||||
// Invalidates all pages. Use this when some global parameter, such as page
|
||||
// orientation, has changed.
|
||||
void InvalidateAllPages();
|
||||
|
||||
// If the page is narrower than the document size, paint the extra space
|
||||
// with the page background.
|
||||
void FillPageSides(int progressive_index);
|
||||
|
||||
void PaintPageShadow(int progressive_index, pp::ImageData* image_data);
|
||||
|
||||
// Highlight visible find results and selections.
|
||||
void DrawSelections(int progressive_index, pp::ImageData* image_data);
|
||||
|
||||
// Paints an page that hasn't finished downloading.
|
||||
void PaintUnavailablePage(int page_index,
|
||||
const pp::Rect& dirty,
|
||||
pp::ImageData* image_data);
|
||||
|
||||
// Given a page index, returns the corresponding index in progressive_rects_,
|
||||
// or -1 if it doesn't exist.
|
||||
int GetProgressiveIndex(int page_index) const;
|
||||
|
||||
// Creates a FPDF_BITMAP from a rectangle in screen coordinates.
|
||||
FPDF_BITMAP CreateBitmap(const pp::Rect& rect,
|
||||
pp::ImageData* image_data) const;
|
||||
|
||||
// Given a rectangle in screen coordinates, returns the coordinates in the
|
||||
// units that PDFium rendering functions expect.
|
||||
void GetPDFiumRect(int page_index, const pp::Rect& rect, int* start_x,
|
||||
int* start_y, int* size_x, int* size_y) const;
|
||||
|
||||
// Returns the rendering flags to pass to PDFium.
|
||||
int GetRenderingFlags() const;
|
||||
|
||||
// Returns the currently visible rectangle in document coordinates.
|
||||
pp::Rect GetVisibleRect() const;
|
||||
|
||||
// Returns a page's rect in screen coordinates, as well as its surrounding
|
||||
// border areas and bottom separator.
|
||||
pp::Rect GetPageScreenRect(int page_index) const;
|
||||
|
||||
// Given a rectangle in document coordinates, returns the rectange into screen
|
||||
// coordinates (i.e. 0,0 is top left corner of plugin area). If it's not
|
||||
// visible, an empty rectangle is returned.
|
||||
pp::Rect GetScreenRect(const pp::Rect& rect) const;
|
||||
|
||||
// Highlights the given rectangle.
|
||||
void Highlight(void* buffer,
|
||||
int stride,
|
||||
const pp::Rect& rect,
|
||||
std::vector<pp::Rect>* highlighted_rects);
|
||||
|
||||
// Helper function to convert a device to page coordinates. If the page is
|
||||
// not yet loaded, page_x and page_y will be set to 0.
|
||||
void DeviceToPage(int page_index,
|
||||
float device_x,
|
||||
float device_y,
|
||||
double* page_x,
|
||||
double* page_y);
|
||||
|
||||
// Helper function to get the index of a given FPDF_PAGE. Returns -1 if not
|
||||
// found.
|
||||
int GetVisiblePageIndex(FPDF_PAGE page);
|
||||
|
||||
// Helper function to change the current page, running page open/close
|
||||
// triggers as necessary.
|
||||
void SetCurrentPage(int index);
|
||||
|
||||
// Transform |page| contents to fit in the selected printer paper size.
|
||||
void TransformPDFPageForPrinting(FPDF_PAGE page,
|
||||
const PP_PrintSettings_Dev& print_settings);
|
||||
|
||||
void DrawPageShadow(const pp::Rect& page_rect,
|
||||
const pp::Rect& shadow_rect,
|
||||
const pp::Rect& clip_rect,
|
||||
pp::ImageData* image_data);
|
||||
|
||||
void GetRegion(const pp::Point& location,
|
||||
pp::ImageData* image_data,
|
||||
void** region,
|
||||
int* stride) const;
|
||||
|
||||
// Called when the selection changes.
|
||||
void OnSelectionChanged();
|
||||
|
||||
// FPDF_FORMFILLINFO callbacks.
|
||||
static void Form_Invalidate(FPDF_FORMFILLINFO* param,
|
||||
FPDF_PAGE page,
|
||||
double left,
|
||||
double top,
|
||||
double right,
|
||||
double bottom);
|
||||
static void Form_OutputSelectedRect(FPDF_FORMFILLINFO* param,
|
||||
FPDF_PAGE page,
|
||||
double left,
|
||||
double top,
|
||||
double right,
|
||||
double bottom);
|
||||
static void Form_SetCursor(FPDF_FORMFILLINFO* param, int cursor_type);
|
||||
static int Form_SetTimer(FPDF_FORMFILLINFO* param,
|
||||
int elapse,
|
||||
TimerCallback timer_func);
|
||||
static void Form_KillTimer(FPDF_FORMFILLINFO* param, int timer_id);
|
||||
static FPDF_SYSTEMTIME Form_GetLocalTime(FPDF_FORMFILLINFO* param);
|
||||
static void Form_OnChange(FPDF_FORMFILLINFO* param);
|
||||
static FPDF_PAGE Form_GetPage(FPDF_FORMFILLINFO* param,
|
||||
FPDF_DOCUMENT document,
|
||||
int page_index);
|
||||
static FPDF_PAGE Form_GetCurrentPage(FPDF_FORMFILLINFO* param,
|
||||
FPDF_DOCUMENT document);
|
||||
static int Form_GetRotation(FPDF_FORMFILLINFO* param, FPDF_PAGE page);
|
||||
static void Form_ExecuteNamedAction(FPDF_FORMFILLINFO* param,
|
||||
FPDF_BYTESTRING named_action);
|
||||
static void Form_SetTextFieldFocus(FPDF_FORMFILLINFO* param,
|
||||
FPDF_WIDESTRING value,
|
||||
FPDF_DWORD valueLen,
|
||||
FPDF_BOOL is_focus);
|
||||
static void Form_DoURIAction(FPDF_FORMFILLINFO* param, FPDF_BYTESTRING uri);
|
||||
static void Form_DoGoToAction(FPDF_FORMFILLINFO* param,
|
||||
int page_index,
|
||||
int zoom_mode,
|
||||
float* position_array,
|
||||
int size_of_array);
|
||||
|
||||
// IPDF_JSPLATFORM callbacks.
|
||||
static int Form_Alert(IPDF_JSPLATFORM* param,
|
||||
FPDF_WIDESTRING message,
|
||||
FPDF_WIDESTRING title,
|
||||
int type,
|
||||
int icon);
|
||||
static void Form_Beep(IPDF_JSPLATFORM* param, int type);
|
||||
static int Form_Response(IPDF_JSPLATFORM* param,
|
||||
FPDF_WIDESTRING question,
|
||||
FPDF_WIDESTRING title,
|
||||
FPDF_WIDESTRING default_response,
|
||||
FPDF_WIDESTRING label,
|
||||
FPDF_BOOL password,
|
||||
void* response,
|
||||
int length);
|
||||
static int Form_GetFilePath(IPDF_JSPLATFORM* param,
|
||||
void* file_path,
|
||||
int length);
|
||||
static void Form_Mail(IPDF_JSPLATFORM* param,
|
||||
void* mail_data,
|
||||
int length,
|
||||
FPDF_BOOL ui,
|
||||
FPDF_WIDESTRING to,
|
||||
FPDF_WIDESTRING subject,
|
||||
FPDF_WIDESTRING cc,
|
||||
FPDF_WIDESTRING bcc,
|
||||
FPDF_WIDESTRING message);
|
||||
static void Form_Print(IPDF_JSPLATFORM* param,
|
||||
FPDF_BOOL ui,
|
||||
int start,
|
||||
int end,
|
||||
FPDF_BOOL silent,
|
||||
FPDF_BOOL shrink_to_fit,
|
||||
FPDF_BOOL print_as_image,
|
||||
FPDF_BOOL reverse,
|
||||
FPDF_BOOL annotations);
|
||||
static void Form_SubmitForm(IPDF_JSPLATFORM* param,
|
||||
void* form_data,
|
||||
int length,
|
||||
FPDF_WIDESTRING url);
|
||||
static void Form_GotoPage(IPDF_JSPLATFORM* param, int page_number);
|
||||
static int Form_Browse(IPDF_JSPLATFORM* param, void* file_path, int length);
|
||||
|
||||
// IFSDK_PAUSE callbacks
|
||||
static FPDF_BOOL Pause_NeedToPauseNow(IFSDK_PAUSE* param);
|
||||
|
||||
PDFEngine::Client* client_;
|
||||
pp::Size document_size_; // Size of document in pixels.
|
||||
|
||||
// The scroll position in screen coordinates.
|
||||
pp::Point position_;
|
||||
// The offset of the page into the viewport.
|
||||
pp::Point page_offset_;
|
||||
// The plugin size in screen coordinates.
|
||||
pp::Size plugin_size_;
|
||||
double current_zoom_;
|
||||
unsigned int current_rotation_;
|
||||
|
||||
DocumentLoader doc_loader_; // Main document's loader.
|
||||
std::string url_;
|
||||
std::string headers_;
|
||||
pp::CompletionCallbackFactory<PDFiumEngine> find_factory_;
|
||||
|
||||
pp::CompletionCallbackFactory<PDFiumEngine> password_factory_;
|
||||
int32_t password_tries_remaining_;
|
||||
|
||||
// The current text used for searching.
|
||||
std::string current_find_text_;
|
||||
|
||||
// The PDFium wrapper object for the document.
|
||||
FPDF_DOCUMENT doc_;
|
||||
|
||||
// The PDFium wrapper for form data. Used even if there are no form controls
|
||||
// on the page.
|
||||
FPDF_FORMHANDLE form_;
|
||||
|
||||
// The page(s) of the document. Store a vector of pointers so that when the
|
||||
// vector is resized we don't close the pages that are used in pending
|
||||
// paints.
|
||||
std::vector<PDFiumPage*> pages_;
|
||||
|
||||
// The indexes of the pages currently visible.
|
||||
std::vector<int> visible_pages_;
|
||||
|
||||
// The indexes of the pages pending download.
|
||||
std::vector<int> pending_pages_;
|
||||
|
||||
// During handling of input events we don't want to unload any pages in
|
||||
// callbacks to us from PDFium, since the current page can change while PDFium
|
||||
// code still has a pointer to it.
|
||||
bool defer_page_unload_;
|
||||
std::vector<int> deferred_page_unloads_;
|
||||
|
||||
// Used for selection. There could be more than one range if selection spans
|
||||
// more than one page.
|
||||
std::vector<PDFiumRange> selection_;
|
||||
// True if we're in the middle of selection.
|
||||
bool selecting_;
|
||||
|
||||
// Used for searching.
|
||||
typedef std::vector<PDFiumRange> FindResults;
|
||||
FindResults find_results_;
|
||||
// Which page to search next.
|
||||
int next_page_to_search_;
|
||||
// Where to stop searching.
|
||||
int last_page_to_search_;
|
||||
int last_character_index_to_search_; // -1 if search until end of page.
|
||||
// Which result the user has currently selected.
|
||||
int current_find_index_;
|
||||
|
||||
// Permissions bitfield.
|
||||
unsigned long permissions_;
|
||||
|
||||
// Interface structure to provide access to document stream.
|
||||
FPDF_FILEACCESS file_access_;
|
||||
// Interface structure to check data availability in the document stream.
|
||||
FileAvail file_availability_;
|
||||
// Interface structure to request data chunks from the document stream.
|
||||
DownloadHints download_hints_;
|
||||
// Pointer to the document availability interface.
|
||||
FPDF_AVAIL fpdf_availability_;
|
||||
|
||||
pp::Size default_page_size_;
|
||||
|
||||
// Used to manage timers that form fill API needs. The pair holds the timer
|
||||
// period, in ms, and the callback function.
|
||||
std::map<int, std::pair<int, TimerCallback> > timers_;
|
||||
int next_timer_id_;
|
||||
|
||||
// Holds the page index of the last page that the mouse clicked on.
|
||||
int last_page_mouse_down_;
|
||||
|
||||
// Holds the page index of the first visible page; refreshed by calling
|
||||
// CalculateVisiblePages()
|
||||
int first_visible_page_;
|
||||
|
||||
// Holds the page index of the most visible page; refreshed by calling
|
||||
// CalculateVisiblePages()
|
||||
int most_visible_page_;
|
||||
|
||||
// Set to true after FORM_DoDocumentJSAction/FORM_DoDocumentOpenAction have
|
||||
// been called. Only after that can we call FORM_DoPageAAction.
|
||||
bool called_do_document_action_;
|
||||
|
||||
// Records parts of form fields that need to be highlighted at next paint, in
|
||||
// screen coordinates.
|
||||
std::vector<pp::Rect> form_highlights_;
|
||||
|
||||
// Whether to render in grayscale or in color.
|
||||
bool render_grayscale_;
|
||||
|
||||
// The link currently under the cursor.
|
||||
std::string link_under_cursor_;
|
||||
|
||||
// Pending progressive paints.
|
||||
struct ProgressivePaint {
|
||||
pp::Rect rect; // In screen coordinates.
|
||||
FPDF_BITMAP bitmap;
|
||||
int page_index;
|
||||
// Temporary used to figure out if in a series of Paint() calls whether this
|
||||
// pending paint was updated or not.
|
||||
int painted_;
|
||||
};
|
||||
std::vector<ProgressivePaint> progressive_paints_;
|
||||
|
||||
// Keeps track of when we started the last progressive paint, so that in our
|
||||
// callback we can determine if we need to pause.
|
||||
base::Time last_progressive_start_time_;
|
||||
|
||||
// The timeout to use for the current progressive paint.
|
||||
int progressive_paint_timeout_;
|
||||
|
||||
// Shadow matrix for generating the page shadow bitmap.
|
||||
scoped_ptr<ShadowMatrix> page_shadow_;
|
||||
|
||||
// Set to true if the user is being prompted for their password. Will be set
|
||||
// to false after the user finishes getting their password.
|
||||
bool getting_password_;
|
||||
};
|
||||
|
||||
// Create a local variable of this when calling PDFium functions which can call
|
||||
// our global callback when an unsupported feature is reached.
|
||||
class ScopedUnsupportedFeature {
|
||||
public:
|
||||
explicit ScopedUnsupportedFeature(PDFiumEngine* engine);
|
||||
~ScopedUnsupportedFeature();
|
||||
private:
|
||||
PDFiumEngine* engine_;
|
||||
PDFiumEngine* old_engine_;
|
||||
};
|
||||
|
||||
class PDFiumEngineExports : public PDFEngineExports {
|
||||
public:
|
||||
PDFiumEngineExports() {}
|
||||
#if defined(OS_WIN)
|
||||
// See the definition of RenderPDFPageToDC in pdf.cc for details.
|
||||
virtual bool RenderPDFPageToDC(const void* pdf_buffer,
|
||||
int buffer_size,
|
||||
int page_number,
|
||||
const RenderingSettings& settings,
|
||||
HDC dc);
|
||||
#endif // OS_WIN
|
||||
virtual bool RenderPDFPageToBitmap(const void* pdf_buffer,
|
||||
int pdf_buffer_size,
|
||||
int page_number,
|
||||
const RenderingSettings& settings,
|
||||
void* bitmap_buffer);
|
||||
|
||||
virtual bool GetPDFDocInfo(const void* pdf_buffer,
|
||||
int buffer_size,
|
||||
int* page_count,
|
||||
double* max_page_width);
|
||||
};
|
||||
|
||||
} // namespace chrome_pdf
|
||||
|
||||
#endif // PDF_PDFIUM_PDFIUM_ENGINE_H_
|
34
pdf/pdfium/pdfium_mem_buffer_file_read.cc
Normal file
34
pdf/pdfium/pdfium_mem_buffer_file_read.cc
Normal file
@ -0,0 +1,34 @@
|
||||
// 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/pdfium/pdfium_mem_buffer_file_read.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
namespace chrome_pdf {
|
||||
|
||||
PDFiumMemBufferFileRead::PDFiumMemBufferFileRead(const void* data,
|
||||
size_t size) {
|
||||
m_FileLen = size;
|
||||
m_Param = this;
|
||||
m_GetBlock = &GetBlock;
|
||||
data_ = reinterpret_cast<const unsigned char*>(data);
|
||||
}
|
||||
|
||||
PDFiumMemBufferFileRead::~PDFiumMemBufferFileRead() {
|
||||
}
|
||||
|
||||
int PDFiumMemBufferFileRead::GetBlock(void* param,
|
||||
unsigned long position,
|
||||
unsigned char* buf,
|
||||
unsigned long size) {
|
||||
const PDFiumMemBufferFileRead* data =
|
||||
reinterpret_cast<const PDFiumMemBufferFileRead*>(param);
|
||||
if (!data || position + size > data->m_FileLen)
|
||||
return 0;
|
||||
memcpy(buf, data->data_ + position, size);
|
||||
return 1;
|
||||
}
|
||||
|
||||
} // namespace chrome_pdf
|
30
pdf/pdfium/pdfium_mem_buffer_file_read.h
Normal file
30
pdf/pdfium/pdfium_mem_buffer_file_read.h
Normal file
@ -0,0 +1,30 @@
|
||||
// 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.
|
||||
|
||||
#ifndef PDF_PDFIUM_PDFIUM_MEM_BUFFER_FILE_READ_H_
|
||||
#define PDF_PDFIUM_PDFIUM_MEM_BUFFER_FILE_READ_H_
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "third_party/pdfium/fpdfsdk/include/fpdfview.h"
|
||||
|
||||
namespace chrome_pdf {
|
||||
|
||||
// Implementation of FPDF_FILEACCESS from a memory buffer.
|
||||
class PDFiumMemBufferFileRead : public FPDF_FILEACCESS {
|
||||
public:
|
||||
PDFiumMemBufferFileRead(const void* data, size_t size);
|
||||
~PDFiumMemBufferFileRead();
|
||||
|
||||
private:
|
||||
static int GetBlock(void* param,
|
||||
unsigned long position,
|
||||
unsigned char* buf,
|
||||
unsigned long size);
|
||||
const unsigned char* data_;
|
||||
};
|
||||
|
||||
} // namespace chrome_pdf
|
||||
|
||||
#endif // PDF_PDFIUM_PDFIUM_MEM_BUFFER_FILE_READ_H_
|
33
pdf/pdfium/pdfium_mem_buffer_file_write.cc
Normal file
33
pdf/pdfium/pdfium_mem_buffer_file_write.cc
Normal file
@ -0,0 +1,33 @@
|
||||
// Copyright (c) 2010 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/pdfium/pdfium_mem_buffer_file_write.h"
|
||||
|
||||
namespace chrome_pdf {
|
||||
|
||||
PDFiumMemBufferFileWrite::PDFiumMemBufferFileWrite() {
|
||||
version = 1;
|
||||
WriteBlock = &WriteBlockImpl;
|
||||
}
|
||||
|
||||
PDFiumMemBufferFileWrite::~PDFiumMemBufferFileWrite() {
|
||||
}
|
||||
|
||||
int PDFiumMemBufferFileWrite::WriteBlockImpl(FPDF_FILEWRITE* this_file_write,
|
||||
const void* data,
|
||||
unsigned long size) {
|
||||
PDFiumMemBufferFileWrite* mem_buffer_file_write =
|
||||
static_cast<PDFiumMemBufferFileWrite*>(this_file_write);
|
||||
return mem_buffer_file_write->DoWriteBlock(data, size);
|
||||
}
|
||||
|
||||
int PDFiumMemBufferFileWrite::DoWriteBlock(const void* data,
|
||||
unsigned long size) {
|
||||
buffer_.append(static_cast<const unsigned char*>(data), size);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
} // namespace chrome_pdf
|
||||
|
34
pdf/pdfium/pdfium_mem_buffer_file_write.h
Normal file
34
pdf/pdfium/pdfium_mem_buffer_file_write.h
Normal file
@ -0,0 +1,34 @@
|
||||
// Copyright (c) 2010 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.
|
||||
|
||||
#ifndef PDF_PDFIUM_PDFIUM_MEM_BUFFER_FILE_WRITE_
|
||||
#define PDF_PDFIUM_PDFIUM_MEM_BUFFER_FILE_WRITE_
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "third_party/pdfium/fpdfsdk/include/fpdfsave.h"
|
||||
|
||||
namespace chrome_pdf {
|
||||
|
||||
// Implementation of FPDF_FILEWRITE into a memory buffer.
|
||||
class PDFiumMemBufferFileWrite : public FPDF_FILEWRITE {
|
||||
public:
|
||||
PDFiumMemBufferFileWrite();
|
||||
~PDFiumMemBufferFileWrite();
|
||||
|
||||
const std::basic_string<unsigned char>& buffer() { return buffer_; }
|
||||
size_t size() { return buffer_.size(); }
|
||||
|
||||
private:
|
||||
int DoWriteBlock(const void* data, unsigned long size);
|
||||
static int WriteBlockImpl(FPDF_FILEWRITE* this_file_write, const void* data,
|
||||
unsigned long size);
|
||||
|
||||
std::basic_string<unsigned char> buffer_;
|
||||
};
|
||||
|
||||
} // namespace chrome_pdf
|
||||
|
||||
#endif // PDF_PDFIUM_PDFIUM_MEM_BUFFER_FILE_WRITE_
|
||||
|
478
pdf/pdfium/pdfium_page.cc
Normal file
478
pdf/pdfium/pdfium_page.cc
Normal file
@ -0,0 +1,478 @@
|
||||
// Copyright (c) 2010 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/pdfium/pdfium_page.h"
|
||||
|
||||
#include <math.h>
|
||||
|
||||
#include "base/logging.h"
|
||||
#include "base/strings/string_number_conversions.h"
|
||||
#include "base/strings/string_util.h"
|
||||
#include "base/strings/utf_string_conversions.h"
|
||||
#include "base/values.h"
|
||||
#include "pdf/pdfium/pdfium_engine.h"
|
||||
|
||||
// Used when doing hit detection.
|
||||
#define kTolerance 20.0
|
||||
|
||||
// Dictionary Value key names for returning the accessible page content as JSON.
|
||||
const char kPageWidth[] = "width";
|
||||
const char kPageHeight[] = "height";
|
||||
const char kPageTextBox[] = "textBox";
|
||||
const char kTextBoxLeft[] = "left";
|
||||
const char kTextBoxTop[] = "top";
|
||||
const char kTextBoxWidth[] = "width";
|
||||
const char kTextBoxHeight[] = "height";
|
||||
const char kTextBoxFontSize[] = "fontSize";
|
||||
const char kTextBoxNodes[] = "textNodes";
|
||||
const char kTextNodeType[] = "type";
|
||||
const char kTextNodeText[] = "text";
|
||||
const char kTextNodeURL[] = "url";
|
||||
const char kTextNodeTypeText[] = "text";
|
||||
const char kTextNodeTypeURL[] = "url";
|
||||
const char kDocLinkURLPrefix[] = "#page";
|
||||
|
||||
namespace chrome_pdf {
|
||||
|
||||
PDFiumPage::PDFiumPage(PDFiumEngine* engine,
|
||||
int i,
|
||||
const pp::Rect& r,
|
||||
bool available)
|
||||
: engine_(engine),
|
||||
page_(NULL),
|
||||
text_page_(NULL),
|
||||
index_(i),
|
||||
rect_(r),
|
||||
calculated_links_(false),
|
||||
available_(available) {
|
||||
}
|
||||
|
||||
PDFiumPage::~PDFiumPage() {
|
||||
Unload();
|
||||
}
|
||||
|
||||
void PDFiumPage::Unload() {
|
||||
if (text_page_) {
|
||||
FPDFText_ClosePage(text_page_);
|
||||
text_page_ = NULL;
|
||||
}
|
||||
|
||||
if (page_) {
|
||||
if (engine_->form()) {
|
||||
FORM_OnBeforeClosePage(page_, engine_->form());
|
||||
}
|
||||
FPDF_ClosePage(page_);
|
||||
page_ = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
FPDF_PAGE PDFiumPage::GetPage() {
|
||||
ScopedUnsupportedFeature scoped_unsupported_feature(engine_);
|
||||
if (!available_)
|
||||
return NULL;
|
||||
if (!page_) {
|
||||
page_ = FPDF_LoadPage(engine_->doc(), index_);
|
||||
if (page_ && engine_->form()) {
|
||||
FORM_OnAfterLoadPage(page_, engine_->form());
|
||||
}
|
||||
}
|
||||
return page_;
|
||||
}
|
||||
|
||||
FPDF_PAGE PDFiumPage::GetPrintPage() {
|
||||
ScopedUnsupportedFeature scoped_unsupported_feature(engine_);
|
||||
if (!available_)
|
||||
return NULL;
|
||||
if (!page_)
|
||||
page_ = FPDF_LoadPage(engine_->doc(), index_);
|
||||
return page_;
|
||||
}
|
||||
|
||||
void PDFiumPage::ClosePrintPage() {
|
||||
if (page_) {
|
||||
FPDF_ClosePage(page_);
|
||||
page_ = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
FPDF_TEXTPAGE PDFiumPage::GetTextPage() {
|
||||
if (!available_)
|
||||
return NULL;
|
||||
if (!text_page_)
|
||||
text_page_ = FPDFText_LoadPage(GetPage());
|
||||
return text_page_;
|
||||
}
|
||||
|
||||
base::Value* PDFiumPage::GetAccessibleContentAsValue(int rotation) {
|
||||
base::DictionaryValue* node = new base::DictionaryValue();
|
||||
|
||||
if (!available_)
|
||||
return node;
|
||||
|
||||
double width = FPDF_GetPageWidth(GetPage());
|
||||
double height = FPDF_GetPageHeight(GetPage());
|
||||
|
||||
base::ListValue* text = new base::ListValue();
|
||||
int box_count = FPDFText_CountRects(GetTextPage(), 0, GetCharCount());
|
||||
for (int i = 0; i < box_count; i++) {
|
||||
double left, top, right, bottom;
|
||||
FPDFText_GetRect(GetTextPage(), i, &left, &top, &right, &bottom);
|
||||
text->Append(
|
||||
GetTextBoxAsValue(height, left, top, right, bottom, rotation));
|
||||
}
|
||||
|
||||
node->SetDouble(kPageWidth, width);
|
||||
node->SetDouble(kPageHeight, height);
|
||||
node->Set(kPageTextBox, text); // Takes ownership of |text|
|
||||
|
||||
return node;
|
||||
}
|
||||
|
||||
base::Value* PDFiumPage::GetTextBoxAsValue(double page_height,
|
||||
double left, double top,
|
||||
double right, double bottom,
|
||||
int rotation) {
|
||||
base::string16 text_utf16;
|
||||
int char_count =
|
||||
FPDFText_GetBoundedText(GetTextPage(), left, top, right, bottom, NULL, 0);
|
||||
if (char_count > 0) {
|
||||
unsigned short* data = reinterpret_cast<unsigned short*>(
|
||||
WriteInto(&text_utf16, char_count + 1));
|
||||
FPDFText_GetBoundedText(GetTextPage(),
|
||||
left, top, right, bottom,
|
||||
data, char_count);
|
||||
}
|
||||
std::string text_utf8 = base::UTF16ToUTF8(text_utf16);
|
||||
|
||||
FPDF_LINK link = FPDFLink_GetLinkAtPoint(GetPage(), left, top);
|
||||
Area area;
|
||||
std::vector<LinkTarget> targets;
|
||||
if (link) {
|
||||
targets.push_back(LinkTarget());
|
||||
area = GetLinkTarget(link, &targets[0]);
|
||||
} else {
|
||||
pp::Rect rect(
|
||||
PageToScreen(pp::Point(), 1.0, left, top, right, bottom, rotation));
|
||||
GetLinks(rect, &targets);
|
||||
area = targets.size() == 0 ? TEXT_AREA : WEBLINK_AREA;
|
||||
}
|
||||
|
||||
int char_index = FPDFText_GetCharIndexAtPos(GetTextPage(), left, top,
|
||||
kTolerance, kTolerance);
|
||||
double font_size = FPDFText_GetFontSize(GetTextPage(), char_index);
|
||||
|
||||
base::DictionaryValue* node = new base::DictionaryValue();
|
||||
node->SetDouble(kTextBoxLeft, left);
|
||||
node->SetDouble(kTextBoxTop, page_height - top);
|
||||
node->SetDouble(kTextBoxWidth, right - left);
|
||||
node->SetDouble(kTextBoxHeight, top - bottom);
|
||||
node->SetDouble(kTextBoxFontSize, font_size);
|
||||
|
||||
base::ListValue* text_nodes = new base::ListValue();
|
||||
|
||||
if (area == DOCLINK_AREA) {
|
||||
std::string url = kDocLinkURLPrefix + base::IntToString(targets[0].page);
|
||||
text_nodes->Append(CreateURLNode(text_utf8, url));
|
||||
} else if (area == WEBLINK_AREA && link) {
|
||||
text_nodes->Append(CreateURLNode(text_utf8, targets[0].url));
|
||||
} else if (area == WEBLINK_AREA && !link) {
|
||||
size_t start = 0;
|
||||
for (size_t i = 0; i < targets.size(); ++i) {
|
||||
// Remove the extra NULL character at end.
|
||||
// Otherwise, find() will not return any matches.
|
||||
if (targets[i].url.size() > 0 &&
|
||||
targets[i].url[targets[i].url.size() - 1] == '\0') {
|
||||
targets[i].url.resize(targets[i].url.size() - 1);
|
||||
}
|
||||
// There should only ever be one NULL character
|
||||
DCHECK(targets[i].url[targets[i].url.size() - 1] != '\0');
|
||||
|
||||
// PDFium may change the case of generated links.
|
||||
std::string lowerCaseURL = StringToLowerASCII(targets[i].url);
|
||||
std::string lowerCaseText = StringToLowerASCII(text_utf8);
|
||||
size_t pos = lowerCaseText.find(lowerCaseURL, start);
|
||||
size_t length = targets[i].url.size();
|
||||
if (pos == std::string::npos) {
|
||||
// Check if the link is a "mailto:" URL
|
||||
if (lowerCaseURL.compare(0, 7, "mailto:") == 0) {
|
||||
pos = lowerCaseText.find(lowerCaseURL.substr(7), start);
|
||||
length -= 7;
|
||||
}
|
||||
|
||||
if (pos == std::string::npos) {
|
||||
// No match has been found. This should never happen.
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
std::string before_text = text_utf8.substr(start, pos - start);
|
||||
if (before_text.size() > 0)
|
||||
text_nodes->Append(CreateTextNode(before_text));
|
||||
std::string link_text = text_utf8.substr(pos, length);
|
||||
text_nodes->Append(CreateURLNode(link_text, targets[i].url));
|
||||
|
||||
start = pos + length;
|
||||
}
|
||||
std::string before_text = text_utf8.substr(start);
|
||||
if (before_text.size() > 0)
|
||||
text_nodes->Append(CreateTextNode(before_text));
|
||||
} else {
|
||||
text_nodes->Append(CreateTextNode(text_utf8));
|
||||
}
|
||||
|
||||
node->Set(kTextBoxNodes, text_nodes); // Takes ownership of |text_nodes|.
|
||||
return node;
|
||||
}
|
||||
|
||||
base::Value* PDFiumPage::CreateTextNode(std::string text) {
|
||||
base::DictionaryValue* node = new base::DictionaryValue();
|
||||
node->SetString(kTextNodeType, kTextNodeTypeText);
|
||||
node->SetString(kTextNodeText, text);
|
||||
return node;
|
||||
}
|
||||
|
||||
base::Value* PDFiumPage::CreateURLNode(std::string text, std::string url) {
|
||||
base::DictionaryValue* node = new base::DictionaryValue();
|
||||
node->SetString(kTextNodeType, kTextNodeTypeURL);
|
||||
node->SetString(kTextNodeText, text);
|
||||
node->SetString(kTextNodeURL, url);
|
||||
return node;
|
||||
}
|
||||
|
||||
PDFiumPage::Area PDFiumPage::GetCharIndex(const pp::Point& point,
|
||||
int rotation,
|
||||
int* char_index,
|
||||
LinkTarget* target) {
|
||||
if (!available_)
|
||||
return NONSELECTABLE_AREA;
|
||||
pp::Point point2 = point - rect_.point();
|
||||
double new_x, new_y;
|
||||
FPDF_DeviceToPage(GetPage(), 0, 0, rect_.width(), rect_.height(),
|
||||
rotation, point2.x(), point2.y(), &new_x, &new_y);
|
||||
|
||||
int rv = FPDFText_GetCharIndexAtPos(
|
||||
GetTextPage(), new_x, new_y, kTolerance, kTolerance);
|
||||
*char_index = rv;
|
||||
|
||||
FPDF_LINK link = FPDFLink_GetLinkAtPoint(GetPage(), new_x, new_y);
|
||||
if (link) {
|
||||
// We don't handle all possible link types of the PDF. For example,
|
||||
// launch actions, cross-document links, etc.
|
||||
// In that case, GetLinkTarget() will return NONSELECTABLE_AREA
|
||||
// and we should proceed with area detection.
|
||||
PDFiumPage::Area area = GetLinkTarget(link, target);
|
||||
if (area != PDFiumPage::NONSELECTABLE_AREA)
|
||||
return area;
|
||||
}
|
||||
|
||||
if (rv < 0)
|
||||
return NONSELECTABLE_AREA;
|
||||
|
||||
return GetLink(*char_index, target) != -1 ? WEBLINK_AREA : TEXT_AREA;
|
||||
}
|
||||
|
||||
base::char16 PDFiumPage::GetCharAtIndex(int index) {
|
||||
if (!available_)
|
||||
return L'\0';
|
||||
return static_cast<base::char16>(FPDFText_GetUnicode(GetTextPage(), index));
|
||||
}
|
||||
|
||||
int PDFiumPage::GetCharCount() {
|
||||
if (!available_)
|
||||
return 0;
|
||||
return FPDFText_CountChars(GetTextPage());
|
||||
}
|
||||
|
||||
PDFiumPage::Area PDFiumPage::GetLinkTarget(
|
||||
FPDF_LINK link, PDFiumPage::LinkTarget* target) {
|
||||
FPDF_DEST dest = FPDFLink_GetDest(engine_->doc(), link);
|
||||
if (dest != NULL)
|
||||
return GetDestinationTarget(dest, target);
|
||||
|
||||
FPDF_ACTION action = FPDFLink_GetAction(link);
|
||||
if (action) {
|
||||
switch (FPDFAction_GetType(action)) {
|
||||
case PDFACTION_GOTO: {
|
||||
FPDF_DEST dest = FPDFAction_GetDest(engine_->doc(), action);
|
||||
if (dest)
|
||||
return GetDestinationTarget(dest, target);
|
||||
// TODO(gene): We don't fully support all types of the in-document
|
||||
// links. Need to implement that. There is a bug to track that:
|
||||
// http://code.google.com/p/chromium/issues/detail?id=55776
|
||||
} break;
|
||||
case PDFACTION_URI: {
|
||||
if (target) {
|
||||
size_t buffer_size =
|
||||
FPDFAction_GetURIPath(engine_->doc(), action, NULL, 0);
|
||||
if (buffer_size > 1) {
|
||||
void* data = WriteInto(&target->url, buffer_size);
|
||||
FPDFAction_GetURIPath(engine_->doc(), action, data, buffer_size);
|
||||
}
|
||||
}
|
||||
return WEBLINK_AREA;
|
||||
} break;
|
||||
// TODO(gene): We don't support PDFACTION_REMOTEGOTO and PDFACTION_LAUNCH
|
||||
// at the moment.
|
||||
}
|
||||
}
|
||||
|
||||
return NONSELECTABLE_AREA;
|
||||
}
|
||||
|
||||
PDFiumPage::Area PDFiumPage::GetDestinationTarget(
|
||||
FPDF_DEST destination, PDFiumPage::LinkTarget* target) {
|
||||
int page_index = FPDFDest_GetPageIndex(engine_->doc(), destination);
|
||||
if (target) {
|
||||
target->page = page_index;
|
||||
}
|
||||
return DOCLINK_AREA;
|
||||
}
|
||||
|
||||
int PDFiumPage::GetLink(int char_index, PDFiumPage::LinkTarget* target) {
|
||||
if (!available_)
|
||||
return -1;
|
||||
|
||||
CalculateLinks();
|
||||
|
||||
// Get the bounding box of the rect again, since it might have moved because
|
||||
// of the tolerance above.
|
||||
double left, right, bottom, top;
|
||||
FPDFText_GetCharBox(GetTextPage(), char_index, &left, &right, &bottom, &top);
|
||||
|
||||
pp::Point origin(
|
||||
PageToScreen(pp::Point(), 1.0, left, top, right, bottom, 0).point());
|
||||
for (size_t i = 0; i < links_.size(); ++i) {
|
||||
for (size_t j = 0; j < links_[i].rects.size(); ++j) {
|
||||
if (links_[i].rects[j].Contains(origin)) {
|
||||
if (target)
|
||||
target->url = links_[i].url;
|
||||
return i;
|
||||
}
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
std::vector<int> PDFiumPage::GetLinks(pp::Rect text_area,
|
||||
std::vector<LinkTarget>* targets) {
|
||||
if (!available_)
|
||||
return std::vector<int>();
|
||||
|
||||
CalculateLinks();
|
||||
|
||||
std::vector<int> links;
|
||||
|
||||
for (size_t i = 0; i < links_.size(); ++i) {
|
||||
for (size_t j = 0; j < links_[i].rects.size(); ++j) {
|
||||
if (links_[i].rects[j].Intersects(text_area)) {
|
||||
if (targets) {
|
||||
LinkTarget target;
|
||||
target.url = links_[i].url;
|
||||
targets->push_back(target);
|
||||
}
|
||||
links.push_back(i);
|
||||
}
|
||||
}
|
||||
}
|
||||
return links;
|
||||
}
|
||||
|
||||
void PDFiumPage::CalculateLinks() {
|
||||
if (calculated_links_)
|
||||
return;
|
||||
|
||||
calculated_links_ = true;
|
||||
FPDF_PAGELINK links = FPDFLink_LoadWebLinks(GetTextPage());
|
||||
int count = FPDFLink_CountWebLinks(links);
|
||||
for (int i = 0; i < count; ++i) {
|
||||
base::string16 url;
|
||||
int url_length = FPDFLink_GetURL(links, i, NULL, 0);
|
||||
if (url_length > 0) {
|
||||
unsigned short* data =
|
||||
reinterpret_cast<unsigned short*>(WriteInto(&url, url_length + 1));
|
||||
FPDFLink_GetURL(links, i, data, url_length);
|
||||
}
|
||||
Link link;
|
||||
link.url = base::UTF16ToUTF8(url);
|
||||
|
||||
// If the link cannot be converted to a pp::Var, then it is not possible to
|
||||
// pass it to JS. In this case, ignore the link like other PDF viewers.
|
||||
// See http://crbug.com/312882 for an example.
|
||||
pp::Var link_var(link.url);
|
||||
if (!link_var.is_string())
|
||||
continue;
|
||||
|
||||
// Make sure all the characters in the URL are valid per RFC 1738.
|
||||
// http://crbug.com/340326 has a sample bad PDF.
|
||||
// GURL does not work correctly, e.g. it just strips \t \r \n.
|
||||
bool is_invalid_url = false;
|
||||
for (size_t j = 0; j < link.url.length(); ++j) {
|
||||
// Control characters are not allowed.
|
||||
// 0x7F is also a control character.
|
||||
// 0x80 and above are not in US-ASCII.
|
||||
if (link.url[j] < ' ' || link.url[j] >= '\x7F') {
|
||||
is_invalid_url = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (is_invalid_url)
|
||||
continue;
|
||||
|
||||
int rect_count = FPDFLink_CountRects(links, i);
|
||||
for (int j = 0; j < rect_count; ++j) {
|
||||
double left, top, right, bottom;
|
||||
FPDFLink_GetRect(links, i, j, &left, &top, &right, &bottom);
|
||||
link.rects.push_back(
|
||||
PageToScreen(pp::Point(), 1.0, left, top, right, bottom, 0));
|
||||
}
|
||||
links_.push_back(link);
|
||||
}
|
||||
FPDFLink_CloseWebLinks(links);
|
||||
}
|
||||
|
||||
pp::Rect PDFiumPage::PageToScreen(const pp::Point& offset,
|
||||
double zoom,
|
||||
double left,
|
||||
double top,
|
||||
double right,
|
||||
double bottom,
|
||||
int rotation) {
|
||||
if (!available_)
|
||||
return pp::Rect();
|
||||
|
||||
int new_left, new_top, new_right, new_bottom;
|
||||
FPDF_PageToDevice(
|
||||
page_,
|
||||
static_cast<int>((rect_.x() - offset.x()) * zoom),
|
||||
static_cast<int>((rect_.y() - offset.y()) * zoom),
|
||||
static_cast<int>(ceil(rect_.width() * zoom)),
|
||||
static_cast<int>(ceil(rect_.height() * zoom)),
|
||||
rotation, left, top, &new_left, &new_top);
|
||||
FPDF_PageToDevice(
|
||||
page_,
|
||||
static_cast<int>((rect_.x() - offset.x()) * zoom),
|
||||
static_cast<int>((rect_.y() - offset.y()) * zoom),
|
||||
static_cast<int>(ceil(rect_.width() * zoom)),
|
||||
static_cast<int>(ceil(rect_.height() * zoom)),
|
||||
rotation, right, bottom, &new_right, &new_bottom);
|
||||
|
||||
// If the PDF is rotated, the horizontal/vertical coordinates could be
|
||||
// flipped. See
|
||||
// http://www.netl.doe.gov/publications/proceedings/03/ubc/presentations/Goeckner-pres.pdf
|
||||
if (new_right < new_left)
|
||||
std::swap(new_right, new_left);
|
||||
if (new_bottom < new_top)
|
||||
std::swap(new_bottom, new_top);
|
||||
|
||||
return pp::Rect(
|
||||
new_left, new_top, new_right - new_left + 1, new_bottom - new_top + 1);
|
||||
}
|
||||
|
||||
PDFiumPage::Link::Link() {
|
||||
}
|
||||
|
||||
PDFiumPage::Link::~Link() {
|
||||
}
|
||||
|
||||
} // namespace chrome_pdf
|
136
pdf/pdfium/pdfium_page.h
Normal file
136
pdf/pdfium/pdfium_page.h
Normal file
@ -0,0 +1,136 @@
|
||||
// Copyright (c) 2010 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.
|
||||
|
||||
#ifndef PDF_PDFIUM_PDFIUM_PAGE_H_
|
||||
#define PDF_PDFIUM_PDFIUM_PAGE_H_
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "base/strings/string16.h"
|
||||
#include "ppapi/cpp/rect.h"
|
||||
#include "third_party/pdfium/fpdfsdk/include/fpdfdoc.h"
|
||||
#include "third_party/pdfium/fpdfsdk/include/fpdfformfill.h"
|
||||
#include "third_party/pdfium/fpdfsdk/include/fpdftext.h"
|
||||
|
||||
namespace base {
|
||||
class Value;
|
||||
}
|
||||
|
||||
namespace chrome_pdf {
|
||||
|
||||
class PDFiumEngine;
|
||||
|
||||
// Wrapper around a page from the document.
|
||||
class PDFiumPage {
|
||||
public:
|
||||
PDFiumPage(PDFiumEngine* engine,
|
||||
int i,
|
||||
const pp::Rect& r,
|
||||
bool available);
|
||||
~PDFiumPage();
|
||||
// Unloads the PDFium data for this page from memory.
|
||||
void Unload();
|
||||
// Gets the FPDF_PAGE for this page, loading and parsing it if necessary.
|
||||
FPDF_PAGE GetPage();
|
||||
//Get the FPDF_PAGE for printing.
|
||||
FPDF_PAGE GetPrintPage();
|
||||
//Close the printing page.
|
||||
void ClosePrintPage();
|
||||
|
||||
// Returns FPDF_TEXTPAGE for the page, loading and parsing it if necessary.
|
||||
FPDF_TEXTPAGE GetTextPage();
|
||||
|
||||
// Returns a DictionaryValue version of the page.
|
||||
base::Value* GetAccessibleContentAsValue(int rotation);
|
||||
|
||||
enum Area {
|
||||
NONSELECTABLE_AREA,
|
||||
TEXT_AREA,
|
||||
WEBLINK_AREA, // Area is a hyperlink.
|
||||
DOCLINK_AREA, // Area is a link to a different part of the same document.
|
||||
};
|
||||
|
||||
struct LinkTarget {
|
||||
// We are using std::string here which have a copy contructor.
|
||||
// That prevents us from using union here.
|
||||
std::string url; // Valid for WEBLINK_AREA only.
|
||||
int page; // Valid for DOCLINK_AREA only.
|
||||
};
|
||||
|
||||
// Given a point in the document that's in this page, returns its character
|
||||
// index if it's near a character, and also the type of text.
|
||||
// Target is optional. It will be filled in for WEBLINK_AREA or
|
||||
// DOCLINK_AREA only.
|
||||
Area GetCharIndex(const pp::Point& point, int rotation, int* char_index,
|
||||
LinkTarget* target);
|
||||
|
||||
// Gets the character at the given index.
|
||||
base::char16 GetCharAtIndex(int index);
|
||||
|
||||
// Gets the number of characters in the page.
|
||||
int GetCharCount();
|
||||
|
||||
// Converts from page coordinates to screen coordinates.
|
||||
pp::Rect PageToScreen(const pp::Point& offset,
|
||||
double zoom,
|
||||
double left,
|
||||
double top,
|
||||
double right,
|
||||
double bottom,
|
||||
int rotation);
|
||||
|
||||
int index() const { return index_; }
|
||||
pp::Rect rect() const { return rect_; }
|
||||
void set_rect(const pp::Rect& r) { rect_ = r; }
|
||||
bool available() const { return available_; }
|
||||
void set_available(bool available) { available_ = available; }
|
||||
void set_calculated_links(bool calculated_links) {
|
||||
calculated_links_ = calculated_links;
|
||||
}
|
||||
|
||||
private:
|
||||
// Returns a link index if the given character index is over a link, or -1
|
||||
// otherwise.
|
||||
int GetLink(int char_index, LinkTarget* target);
|
||||
// Returns the link indices if the given rect intersects a link rect, or an
|
||||
// empty vector otherwise.
|
||||
std::vector<int> GetLinks(pp::Rect text_area,
|
||||
std::vector<LinkTarget>* targets);
|
||||
// Calculate the locations of any links on the page.
|
||||
void CalculateLinks();
|
||||
// Returns link type and target associated with a link. Returns
|
||||
// NONSELECTABLE_AREA if link detection failed.
|
||||
Area GetLinkTarget(FPDF_LINK link, LinkTarget* target);
|
||||
// Returns target associated with a destination.
|
||||
Area GetDestinationTarget(FPDF_DEST destination, LinkTarget* target);
|
||||
// Returns the text in the supplied box as a Value Node
|
||||
base::Value* GetTextBoxAsValue(double page_height, double left, double top,
|
||||
double right, double bottom, int rotation);
|
||||
// Helper functions for JSON generation
|
||||
base::Value* CreateTextNode(std::string text);
|
||||
base::Value* CreateURLNode(std::string text, std::string url);
|
||||
|
||||
struct Link {
|
||||
Link();
|
||||
~Link();
|
||||
|
||||
std::string url;
|
||||
// Bounding rectangles of characters.
|
||||
std::vector<pp::Rect> rects;
|
||||
};
|
||||
|
||||
PDFiumEngine* engine_;
|
||||
FPDF_PAGE page_;
|
||||
FPDF_TEXTPAGE text_page_;
|
||||
int index_;
|
||||
pp::Rect rect_;
|
||||
bool calculated_links_;
|
||||
std::vector<Link> links_;
|
||||
bool available_;
|
||||
};
|
||||
|
||||
} // namespace chrome_pdf
|
||||
|
||||
#endif // PDF_PDFIUM_PDFIUM_PAGE_H_
|
79
pdf/pdfium/pdfium_range.cc
Normal file
79
pdf/pdfium/pdfium_range.cc
Normal file
@ -0,0 +1,79 @@
|
||||
// Copyright (c) 2010 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/pdfium/pdfium_range.h"
|
||||
|
||||
#include "base/logging.h"
|
||||
#include "base/strings/string_util.h"
|
||||
|
||||
namespace chrome_pdf {
|
||||
|
||||
PDFiumRange::PDFiumRange(PDFiumPage* page, int char_index, int char_count)
|
||||
: page_(page),
|
||||
char_index_(char_index),
|
||||
char_count_(char_count),
|
||||
cached_screen_rects_zoom_(0) {
|
||||
}
|
||||
|
||||
PDFiumRange::~PDFiumRange() {
|
||||
}
|
||||
|
||||
void PDFiumRange::SetCharCount(int char_count) {
|
||||
char_count_ = char_count;
|
||||
|
||||
cached_screen_rects_offset_ = pp::Point();
|
||||
cached_screen_rects_zoom_ = 0;
|
||||
}
|
||||
|
||||
std::vector<pp::Rect> PDFiumRange::GetScreenRects(const pp::Point& offset,
|
||||
double zoom,
|
||||
int rotation) {
|
||||
if (offset == cached_screen_rects_offset_ &&
|
||||
zoom == cached_screen_rects_zoom_) {
|
||||
return cached_screen_rects_;
|
||||
}
|
||||
|
||||
cached_screen_rects_.clear();
|
||||
cached_screen_rects_offset_ = offset;
|
||||
cached_screen_rects_zoom_ = zoom;
|
||||
|
||||
int char_index = char_index_;
|
||||
int char_count = char_count_;
|
||||
if (char_count < 0) {
|
||||
char_count *= -1;
|
||||
char_index -= char_count - 1;
|
||||
}
|
||||
|
||||
int count = FPDFText_CountRects(page_->GetTextPage(), char_index, char_count);
|
||||
for (int i = 0; i < count; ++i) {
|
||||
double left, top, right, bottom;
|
||||
FPDFText_GetRect(page_->GetTextPage(), i, &left, &top, &right, &bottom);
|
||||
cached_screen_rects_.push_back(
|
||||
page_->PageToScreen(offset, zoom, left, top, right, bottom, rotation));
|
||||
}
|
||||
|
||||
return cached_screen_rects_;
|
||||
}
|
||||
|
||||
base::string16 PDFiumRange::GetText() {
|
||||
int index = char_index_;
|
||||
int count = char_count_;
|
||||
if (!count)
|
||||
return base::string16();
|
||||
if (count < 0) {
|
||||
count *= -1;
|
||||
index -= count - 1;
|
||||
}
|
||||
|
||||
base::string16 rv;
|
||||
unsigned short* data =
|
||||
reinterpret_cast<unsigned short*>(WriteInto(&rv, count + 1));
|
||||
if (data) {
|
||||
int written = FPDFText_GetText(page_->GetTextPage(), index, count, data);
|
||||
rv.reserve(written);
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
|
||||
} // namespace chrome_pdf
|
54
pdf/pdfium/pdfium_range.h
Normal file
54
pdf/pdfium/pdfium_range.h
Normal file
@ -0,0 +1,54 @@
|
||||
// Copyright (c) 2010 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.
|
||||
|
||||
#ifndef PDF_PDFIUM_PDFIUM_RANGE_H_
|
||||
#define PDF_PDFIUM_PDFIUM_RANGE_H_
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "base/strings/string16.h"
|
||||
#include "pdf/pdfium/pdfium_page.h"
|
||||
#include "ppapi/cpp/rect.h"
|
||||
|
||||
namespace chrome_pdf {
|
||||
|
||||
// Describes location of a string of characters.
|
||||
class PDFiumRange {
|
||||
public:
|
||||
PDFiumRange(PDFiumPage* page, int char_index, int char_count);
|
||||
~PDFiumRange();
|
||||
|
||||
// Update how many characters are in the selection. Could be negative if
|
||||
// backwards.
|
||||
void SetCharCount(int char_count);
|
||||
|
||||
int page_index() const { return page_->index(); }
|
||||
int char_index() const { return char_index_; }
|
||||
int char_count() const { return char_count_; }
|
||||
|
||||
// Gets bounding rectangles of range in screen coordinates.
|
||||
std::vector<pp::Rect> GetScreenRects(const pp::Point& offset,
|
||||
double zoom,
|
||||
int rotation);
|
||||
|
||||
// Gets the string of characters in this range.
|
||||
base::string16 GetText();
|
||||
|
||||
private:
|
||||
PDFiumPage* page_;
|
||||
// Index of first character.
|
||||
int char_index_;
|
||||
// How many characters are part of this range (negative if backwards).
|
||||
int char_count_;
|
||||
|
||||
// Cache of ScreenRect, and the associated variables used when caching it.
|
||||
std::vector<pp::Rect> cached_screen_rects_;
|
||||
pp::Point cached_screen_rects_offset_;
|
||||
double cached_screen_rects_zoom_;
|
||||
};
|
||||
|
||||
} // namespace chrome_pdf
|
||||
|
||||
#endif // PDF_PDFIUM_PDFIUM_RANGE_H_
|
312
pdf/pdfium/pdfium_test.cc
Normal file
312
pdf/pdfium/pdfium_test.cc
Normal file
@ -0,0 +1,312 @@
|
||||
// Copyright (c) 2010 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 <limits.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <list>
|
||||
#include <string>
|
||||
#include <utility>
|
||||
|
||||
#include "base/at_exit.h"
|
||||
#include "base/i18n/icu_util.h"
|
||||
#include "third_party/pdfium/fpdfsdk/include/fpdf_dataavail.h"
|
||||
#include "third_party/pdfium/fpdfsdk/include/fpdf_ext.h"
|
||||
#include "third_party/pdfium/fpdfsdk/include/fpdfformfill.h"
|
||||
#include "third_party/pdfium/fpdfsdk/include/fpdftext.h"
|
||||
#include "third_party/pdfium/fpdfsdk/include/fpdfview.h"
|
||||
|
||||
#ifdef _WIN32
|
||||
#define snprintf _snprintf
|
||||
/* in Windows, rb for open and read binary file */
|
||||
#define FOPEN_READ "rb"
|
||||
#else
|
||||
#define FOPEN_READ "r"
|
||||
#endif
|
||||
|
||||
static void write_file(const char* pdf_name, int num,
|
||||
const char* buffer, int stride, int width, int height) {
|
||||
if (stride < 0 || width < 0 || height < 0)
|
||||
return;
|
||||
if (height > 0 && width > INT_MAX / height)
|
||||
return;
|
||||
int out_len = width * height;
|
||||
if (out_len > INT_MAX / 3)
|
||||
return;
|
||||
out_len *= 3;
|
||||
|
||||
char filename[256];
|
||||
snprintf(filename, sizeof(filename), "%s.%d.ppm", pdf_name, num);
|
||||
FILE* fp = fopen(filename, "w");
|
||||
if (!fp)
|
||||
return;
|
||||
fprintf(fp, "P6\n# PDF test render\n%d %d\n255\n", width, height);
|
||||
// Source data is B, G, R, unused.
|
||||
// Dest data is R, G, B.
|
||||
char* result = new char[out_len];
|
||||
if (result) {
|
||||
int h, w;
|
||||
for (h = 0; h < height; ++h) {
|
||||
const char* src_line = buffer + (stride * h);
|
||||
char* dest_line = result + (width * h * 3);
|
||||
for (w = 0; w < width; ++w) {
|
||||
// R
|
||||
dest_line[w * 3] = src_line[(w * 4) + 2];
|
||||
// G
|
||||
dest_line[(w * 3) + 1] = src_line[(w * 4) + 1];
|
||||
// B
|
||||
dest_line[(w * 3) + 2] = src_line[w * 4];
|
||||
}
|
||||
}
|
||||
fwrite(result, out_len, 1, fp);
|
||||
delete [] result;
|
||||
}
|
||||
fclose(fp);
|
||||
}
|
||||
|
||||
int Form_Alert(IPDF_JSPLATFORM*, FPDF_WIDESTRING, FPDF_WIDESTRING, int, int) {
|
||||
printf("Form_Alert called.\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
void Unsupported_Handler(UNSUPPORT_INFO*, int type) {
|
||||
std::string feature = "Unknown";
|
||||
switch (type) {
|
||||
case FPDF_UNSP_DOC_XFAFORM:
|
||||
feature = "XFA";
|
||||
break;
|
||||
case FPDF_UNSP_DOC_PORTABLECOLLECTION:
|
||||
feature = "Portfolios_Packages";
|
||||
break;
|
||||
case FPDF_UNSP_DOC_ATTACHMENT:
|
||||
case FPDF_UNSP_ANNOT_ATTACHMENT:
|
||||
feature = "Attachment";
|
||||
break;
|
||||
case FPDF_UNSP_DOC_SECURITY:
|
||||
feature = "Rights_Management";
|
||||
break;
|
||||
case FPDF_UNSP_DOC_SHAREDREVIEW:
|
||||
feature = "Shared_Review";
|
||||
break;
|
||||
case FPDF_UNSP_DOC_SHAREDFORM_ACROBAT:
|
||||
case FPDF_UNSP_DOC_SHAREDFORM_FILESYSTEM:
|
||||
case FPDF_UNSP_DOC_SHAREDFORM_EMAIL:
|
||||
feature = "Shared_Form";
|
||||
break;
|
||||
case FPDF_UNSP_ANNOT_3DANNOT:
|
||||
feature = "3D";
|
||||
break;
|
||||
case FPDF_UNSP_ANNOT_MOVIE:
|
||||
feature = "Movie";
|
||||
break;
|
||||
case FPDF_UNSP_ANNOT_SOUND:
|
||||
feature = "Sound";
|
||||
break;
|
||||
case FPDF_UNSP_ANNOT_SCREEN_MEDIA:
|
||||
case FPDF_UNSP_ANNOT_SCREEN_RICHMEDIA:
|
||||
feature = "Screen";
|
||||
break;
|
||||
case FPDF_UNSP_ANNOT_SIG:
|
||||
feature = "Digital_Signature";
|
||||
break;
|
||||
}
|
||||
printf("Unsupported feature: %s.\n", feature.c_str());
|
||||
}
|
||||
|
||||
bool ParseCommandLine(int argc, const char* argv[], bool* write_images,
|
||||
std::list<const char*>* files) {
|
||||
*write_images = false;
|
||||
files->clear();
|
||||
|
||||
int cur_arg = 1;
|
||||
if (cur_arg < argc &&
|
||||
strcmp(argv[cur_arg], "--write_images") == 0) {
|
||||
*write_images = true;
|
||||
cur_arg++;
|
||||
}
|
||||
|
||||
if (cur_arg >= argc)
|
||||
return false;
|
||||
|
||||
for (int i = cur_arg; i < argc; i++)
|
||||
files->push_back(argv[i]);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
class TestLoader {
|
||||
public:
|
||||
TestLoader(const char* pBuf, size_t len);
|
||||
|
||||
const char* m_pBuf;
|
||||
size_t m_Len;
|
||||
};
|
||||
|
||||
TestLoader::TestLoader(const char* pBuf, size_t len)
|
||||
: m_pBuf(pBuf), m_Len(len) {
|
||||
}
|
||||
|
||||
int Get_Block(void* param, unsigned long pos, unsigned char* pBuf,
|
||||
unsigned long size) {
|
||||
TestLoader* pLoader = (TestLoader*) param;
|
||||
if (pos + size < pos || pos + size > pLoader->m_Len) return 0;
|
||||
memcpy(pBuf, pLoader->m_pBuf + pos, size);
|
||||
return 1;
|
||||
}
|
||||
|
||||
bool Is_Data_Avail(FX_FILEAVAIL* pThis, size_t offset, size_t size) {
|
||||
return true;
|
||||
}
|
||||
|
||||
void Add_Segment(FX_DOWNLOADHINTS* pThis, size_t offset, size_t size) {
|
||||
}
|
||||
|
||||
void RenderPdf(const char* name, const char* pBuf, size_t len,
|
||||
bool write_images) {
|
||||
printf("Rendering PDF file %s.\n", name);
|
||||
|
||||
IPDF_JSPLATFORM platform_callbacks;
|
||||
memset(&platform_callbacks, '\0', sizeof(platform_callbacks));
|
||||
platform_callbacks.version = 1;
|
||||
platform_callbacks.app_alert = Form_Alert;
|
||||
|
||||
FPDF_FORMFILLINFO form_callbacks;
|
||||
memset(&form_callbacks, '\0', sizeof(form_callbacks));
|
||||
form_callbacks.version = 1;
|
||||
form_callbacks.m_pJsPlatform = &platform_callbacks;
|
||||
|
||||
TestLoader loader(pBuf, len);
|
||||
|
||||
FPDF_FILEACCESS file_access;
|
||||
memset(&file_access, '\0', sizeof(file_access));
|
||||
file_access.m_FileLen = len;
|
||||
file_access.m_GetBlock = Get_Block;
|
||||
file_access.m_Param = &loader;
|
||||
|
||||
FX_FILEAVAIL file_avail;
|
||||
memset(&file_avail, '\0', sizeof(file_avail));
|
||||
file_avail.version = 1;
|
||||
file_avail.IsDataAvail = Is_Data_Avail;
|
||||
|
||||
FX_DOWNLOADHINTS hints;
|
||||
memset(&hints, '\0', sizeof(hints));
|
||||
hints.version = 1;
|
||||
hints.AddSegment = Add_Segment;
|
||||
|
||||
FPDF_DOCUMENT doc;
|
||||
FPDF_AVAIL pdf_avail = FPDFAvail_Create(&file_avail, &file_access);
|
||||
|
||||
(void) FPDFAvail_IsDocAvail(pdf_avail, &hints);
|
||||
|
||||
if (!FPDFAvail_IsLinearized(pdf_avail)) {
|
||||
printf("Non-linearized path...\n");
|
||||
doc = FPDF_LoadCustomDocument(&file_access, NULL);
|
||||
} else {
|
||||
printf("Linearized path...\n");
|
||||
doc = FPDFAvail_GetDocument(pdf_avail, NULL);
|
||||
}
|
||||
|
||||
(void) FPDF_GetDocPermissions(doc);
|
||||
(void) FPDFAvail_IsFormAvail(pdf_avail, &hints);
|
||||
|
||||
FPDF_FORMHANDLE form = FPDFDOC_InitFormFillEnviroument(doc, &form_callbacks);
|
||||
FPDF_SetFormFieldHighlightColor(form, 0, 0xFFE4DD);
|
||||
FPDF_SetFormFieldHighlightAlpha(form, 100);
|
||||
|
||||
int first_page = FPDFAvail_GetFirstPageNum(doc);
|
||||
(void) FPDFAvail_IsPageAvail(pdf_avail, first_page, &hints);
|
||||
|
||||
int page_count = FPDF_GetPageCount(doc);
|
||||
for (int i = 0; i < page_count; ++i) {
|
||||
(void) FPDFAvail_IsPageAvail(pdf_avail, i, &hints);
|
||||
}
|
||||
|
||||
FORM_DoDocumentJSAction(form);
|
||||
FORM_DoDocumentOpenAction(form);
|
||||
|
||||
for (int i = 0; i < page_count; ++i) {
|
||||
FPDF_PAGE page = FPDF_LoadPage(doc, i);
|
||||
FPDF_TEXTPAGE text_page = FPDFText_LoadPage(page);
|
||||
FORM_OnAfterLoadPage(page, form);
|
||||
FORM_DoPageAAction(page, form, FPDFPAGE_AACTION_OPEN);
|
||||
|
||||
int width = static_cast<int>(FPDF_GetPageWidth(page));
|
||||
int height = static_cast<int>(FPDF_GetPageHeight(page));
|
||||
FPDF_BITMAP bitmap = FPDFBitmap_Create(width, height, 0);
|
||||
FPDFBitmap_FillRect(bitmap, 0, 0, width, height, 255, 255, 255, 255);
|
||||
|
||||
FPDF_RenderPageBitmap(bitmap, page, 0, 0, width, height, 0, 0);
|
||||
FPDF_FFLDraw(form, bitmap, page, 0, 0, width, height, 0, 0);
|
||||
if (write_images) {
|
||||
const char* buffer = reinterpret_cast<const char*>(
|
||||
FPDFBitmap_GetBuffer(bitmap));
|
||||
int stride = FPDFBitmap_GetStride(bitmap);
|
||||
write_file(name, i, buffer, stride, width, height);
|
||||
}
|
||||
|
||||
FPDFBitmap_Destroy(bitmap);
|
||||
|
||||
FORM_DoPageAAction(page, form, FPDFPAGE_AACTION_CLOSE);
|
||||
FORM_OnBeforeClosePage(page, form);
|
||||
FPDFText_ClosePage(text_page);
|
||||
FPDF_ClosePage(page);
|
||||
}
|
||||
|
||||
FORM_DoDocumentAAction(form, FPDFDOC_AACTION_WC);
|
||||
FPDFDOC_ExitFormFillEnviroument(form);
|
||||
FPDF_CloseDocument(doc);
|
||||
FPDFAvail_Destroy(pdf_avail);
|
||||
|
||||
printf("Loaded, parsed and rendered %d pages.\n", page_count);
|
||||
}
|
||||
|
||||
int main(int argc, const char* argv[]) {
|
||||
base::AtExitManager exit_manager;
|
||||
base::i18n::InitializeICU();
|
||||
bool write_images = false;
|
||||
std::list<const char*> files;
|
||||
if (!ParseCommandLine(argc, argv, &write_images, &files)) {
|
||||
printf("Usage is: test [--write_images] /path/to/pdf\n");
|
||||
printf("--write_images - to write page images <pdf-name>.<page-number>.ppm\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
FPDF_InitLibrary(NULL);
|
||||
|
||||
UNSUPPORT_INFO unsuppored_info;
|
||||
memset(&unsuppored_info, '\0', sizeof(unsuppored_info));
|
||||
unsuppored_info.version = 1;
|
||||
unsuppored_info.FSDK_UnSupport_Handler = Unsupported_Handler;
|
||||
|
||||
FSDK_SetUnSpObjProcessHandler(&unsuppored_info);
|
||||
|
||||
while (!files.empty()) {
|
||||
const char* filename = files.front();
|
||||
files.pop_front();
|
||||
FILE* file = fopen(filename, FOPEN_READ);
|
||||
if (!file) {
|
||||
fprintf(stderr, "Failed to open: %s\n", filename);
|
||||
continue;
|
||||
}
|
||||
(void) fseek(file, 0, SEEK_END);
|
||||
size_t len = ftell(file);
|
||||
(void) fseek(file, 0, SEEK_SET);
|
||||
char* pBuf = (char*) malloc(len);
|
||||
size_t ret = fread(pBuf, 1, len, file);
|
||||
(void) fclose(file);
|
||||
if (ret != len) {
|
||||
fprintf(stderr, "Failed to read: %s\n", filename);
|
||||
} else {
|
||||
RenderPdf(filename, pBuf, len, write_images);
|
||||
}
|
||||
free(pBuf);
|
||||
}
|
||||
|
||||
FPDF_DestroyLibrary();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
162
pdf/preview_mode_client.cc
Normal file
162
pdf/preview_mode_client.cc
Normal file
@ -0,0 +1,162 @@
|
||||
// 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/preview_mode_client.h"
|
||||
|
||||
#include "base/logging.h"
|
||||
#include "pdf/instance.h"
|
||||
|
||||
namespace chrome_pdf {
|
||||
|
||||
PreviewModeClient::PreviewModeClient(Client* client)
|
||||
: client_(client) {
|
||||
}
|
||||
|
||||
void PreviewModeClient::DocumentSizeUpdated(const pp::Size& size) {
|
||||
}
|
||||
|
||||
void PreviewModeClient::Invalidate(const pp::Rect& rect) {
|
||||
NOTREACHED();
|
||||
}
|
||||
|
||||
void PreviewModeClient::Scroll(const pp::Point& point) {
|
||||
NOTREACHED();
|
||||
}
|
||||
|
||||
void PreviewModeClient::ScrollToX(int position) {
|
||||
NOTREACHED();
|
||||
}
|
||||
|
||||
void PreviewModeClient::ScrollToY(int position) {
|
||||
NOTREACHED();
|
||||
}
|
||||
|
||||
void PreviewModeClient::ScrollToPage(int page) {
|
||||
NOTREACHED();
|
||||
}
|
||||
|
||||
void PreviewModeClient::NavigateTo(const std::string& url,
|
||||
bool open_in_new_tab) {
|
||||
NOTREACHED();
|
||||
}
|
||||
|
||||
void PreviewModeClient::UpdateCursor(PP_CursorType_Dev cursor) {
|
||||
NOTREACHED();
|
||||
}
|
||||
|
||||
void PreviewModeClient::UpdateTickMarks(
|
||||
const std::vector<pp::Rect>& tickmarks) {
|
||||
NOTREACHED();
|
||||
}
|
||||
|
||||
void PreviewModeClient::NotifyNumberOfFindResultsChanged(int total,
|
||||
bool final_result) {
|
||||
NOTREACHED();
|
||||
}
|
||||
|
||||
void PreviewModeClient::NotifySelectedFindResultChanged(
|
||||
int current_find_index) {
|
||||
NOTREACHED();
|
||||
}
|
||||
|
||||
void PreviewModeClient::GetDocumentPassword(
|
||||
pp::CompletionCallbackWithOutput<pp::Var> callback) {
|
||||
callback.Run(PP_ERROR_FAILED);
|
||||
}
|
||||
|
||||
void PreviewModeClient::Alert(const std::string& message) {
|
||||
NOTREACHED();
|
||||
}
|
||||
|
||||
bool PreviewModeClient::Confirm(const std::string& message) {
|
||||
NOTREACHED();
|
||||
return false;
|
||||
}
|
||||
|
||||
std::string PreviewModeClient::Prompt(const std::string& question,
|
||||
const std::string& default_answer) {
|
||||
NOTREACHED();
|
||||
return std::string();
|
||||
}
|
||||
|
||||
std::string PreviewModeClient::GetURL() {
|
||||
NOTREACHED();
|
||||
return std::string();
|
||||
}
|
||||
|
||||
void PreviewModeClient::Email(const std::string& to,
|
||||
const std::string& cc,
|
||||
const std::string& bcc,
|
||||
const std::string& subject,
|
||||
const std::string& body) {
|
||||
NOTREACHED();
|
||||
}
|
||||
|
||||
void PreviewModeClient::Print() {
|
||||
NOTREACHED();
|
||||
}
|
||||
|
||||
void PreviewModeClient::SubmitForm(const std::string& url,
|
||||
const void* data,
|
||||
int length) {
|
||||
NOTREACHED();
|
||||
}
|
||||
|
||||
std::string PreviewModeClient::ShowFileSelectionDialog() {
|
||||
NOTREACHED();
|
||||
return std::string();
|
||||
}
|
||||
|
||||
pp::URLLoader PreviewModeClient::CreateURLLoader() {
|
||||
NOTREACHED();
|
||||
return pp::URLLoader();
|
||||
}
|
||||
|
||||
void PreviewModeClient::ScheduleCallback(int id, int delay_in_ms) {
|
||||
NOTREACHED();
|
||||
}
|
||||
|
||||
void PreviewModeClient::SearchString(const base::char16* string,
|
||||
const base::char16* term,
|
||||
bool case_sensitive,
|
||||
std::vector<SearchStringResult>* results) {
|
||||
NOTREACHED();
|
||||
}
|
||||
|
||||
void PreviewModeClient::DocumentPaintOccurred() {
|
||||
NOTREACHED();
|
||||
}
|
||||
|
||||
void PreviewModeClient::DocumentLoadComplete(int page_count) {
|
||||
client_->PreviewDocumentLoadComplete();
|
||||
}
|
||||
|
||||
void PreviewModeClient::DocumentLoadFailed() {
|
||||
client_->PreviewDocumentLoadFailed();
|
||||
}
|
||||
|
||||
pp::Instance* PreviewModeClient::GetPluginInstance() {
|
||||
NOTREACHED();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void PreviewModeClient::DocumentHasUnsupportedFeature(
|
||||
const std::string& feature) {
|
||||
NOTREACHED();
|
||||
}
|
||||
|
||||
void PreviewModeClient::DocumentLoadProgress(uint32 available,
|
||||
uint32 doc_size) {
|
||||
}
|
||||
|
||||
void PreviewModeClient::FormTextFieldFocusChange(bool in_focus) {
|
||||
NOTREACHED();
|
||||
}
|
||||
|
||||
bool PreviewModeClient::IsPrintPreview() {
|
||||
NOTREACHED();
|
||||
return false;
|
||||
}
|
||||
|
||||
} // namespace chrome_pdf
|
77
pdf/preview_mode_client.h
Normal file
77
pdf/preview_mode_client.h
Normal file
@ -0,0 +1,77 @@
|
||||
// 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.
|
||||
|
||||
#ifndef PDF_PREVIEW_MODE_CLIENT_H_
|
||||
#define PDF_PREVIEW_MODE_CLIENT_H_
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "pdf/pdf_engine.h"
|
||||
|
||||
namespace chrome_pdf {
|
||||
|
||||
// The interface that's provided to the print preview rendering engine.
|
||||
class PreviewModeClient : public PDFEngine::Client {
|
||||
public:
|
||||
class Client {
|
||||
public:
|
||||
virtual void PreviewDocumentLoadFailed() = 0;
|
||||
virtual void PreviewDocumentLoadComplete() = 0;
|
||||
};
|
||||
explicit PreviewModeClient(Client* client);
|
||||
virtual ~PreviewModeClient() {}
|
||||
|
||||
// PDFEngine::Client implementation.
|
||||
virtual void DocumentSizeUpdated(const pp::Size& size);
|
||||
virtual void Invalidate(const pp::Rect& rect);
|
||||
virtual void Scroll(const pp::Point& point);
|
||||
virtual void ScrollToX(int position);
|
||||
virtual void ScrollToY(int position);
|
||||
virtual void ScrollToPage(int page);
|
||||
virtual void NavigateTo(const std::string& url, bool open_in_new_tab);
|
||||
virtual void UpdateCursor(PP_CursorType_Dev cursor);
|
||||
virtual void UpdateTickMarks(const std::vector<pp::Rect>& tickmarks);
|
||||
virtual void NotifyNumberOfFindResultsChanged(int total,
|
||||
bool final_result);
|
||||
virtual void NotifySelectedFindResultChanged(int current_find_index);
|
||||
virtual void GetDocumentPassword(
|
||||
pp::CompletionCallbackWithOutput<pp::Var> callback);
|
||||
virtual void Alert(const std::string& message);
|
||||
virtual bool Confirm(const std::string& message);
|
||||
virtual std::string Prompt(const std::string& question,
|
||||
const std::string& default_answer);
|
||||
virtual std::string GetURL();
|
||||
virtual void Email(const std::string& to,
|
||||
const std::string& cc,
|
||||
const std::string& bcc,
|
||||
const std::string& subject,
|
||||
const std::string& body);
|
||||
virtual void Print();
|
||||
virtual void SubmitForm(const std::string& url,
|
||||
const void* data,
|
||||
int length);
|
||||
virtual std::string ShowFileSelectionDialog();
|
||||
virtual pp::URLLoader CreateURLLoader();
|
||||
virtual void ScheduleCallback(int id, int delay_in_ms);
|
||||
virtual void SearchString(const base::char16* string,
|
||||
const base::char16* term,
|
||||
bool case_sensitive,
|
||||
std::vector<SearchStringResult>* results);
|
||||
virtual void DocumentPaintOccurred();
|
||||
virtual void DocumentLoadComplete(int page_count);
|
||||
virtual void DocumentLoadFailed();
|
||||
virtual pp::Instance* GetPluginInstance();
|
||||
virtual void DocumentHasUnsupportedFeature(const std::string& feature);
|
||||
virtual void DocumentLoadProgress(uint32 available, uint32 doc_size);
|
||||
virtual void FormTextFieldFocusChange(bool in_focus);
|
||||
virtual bool IsPrintPreview();
|
||||
|
||||
private:
|
||||
Client* client_;
|
||||
};
|
||||
|
||||
} // namespace chrome_pdf
|
||||
|
||||
#endif // PDF_PREVIEW_MODE_CLIENT_H_
|
283
pdf/progress_control.cc
Normal file
283
pdf/progress_control.cc
Normal file
@ -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
|
72
pdf/progress_control.h
Normal file
72
pdf/progress_control.h
Normal file
@ -0,0 +1,72 @@
|
||||
// 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.
|
||||
|
||||
#ifndef PDF_PROGRESS_CONTROL_H_
|
||||
#define PDF_PROGRESS_CONTROL_H_
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "pdf/control.h"
|
||||
#include "pdf/fading_control.h"
|
||||
#include "ppapi/cpp/image_data.h"
|
||||
|
||||
namespace chrome_pdf {
|
||||
|
||||
class ProgressControl : public FadingControl {
|
||||
public:
|
||||
static const double kCompleted;
|
||||
|
||||
enum ProgressEventIds {
|
||||
EVENT_ID_PROGRESS_COMPLETED,
|
||||
};
|
||||
|
||||
ProgressControl();
|
||||
virtual ~ProgressControl();
|
||||
virtual bool 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);
|
||||
void Reconfigure(const pp::ImageData& background,
|
||||
const std::vector<pp::ImageData>& images,
|
||||
float device_scale);
|
||||
|
||||
static void 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);
|
||||
|
||||
// Control interface.
|
||||
virtual void Paint(pp::ImageData* image_data, const pp::Rect& rc);
|
||||
|
||||
// ProgressControl interface
|
||||
// Set progress indicator in percents from 0% to 100%.
|
||||
virtual void SetProgress(double progress);
|
||||
|
||||
private:
|
||||
void PrepareBackground();
|
||||
void AdjustBackground();
|
||||
size_t GetImageIngex() const;
|
||||
|
||||
double progress_;
|
||||
float device_scale_;
|
||||
std::vector<pp::ImageData> images_;
|
||||
pp::ImageData background_;
|
||||
pp::ImageData ctrl_background_;
|
||||
std::string text_;
|
||||
pp::Rect image_rc_;
|
||||
pp::Rect text_rc_;
|
||||
};
|
||||
|
||||
} // namespace chrome_pdf
|
||||
|
||||
#endif // PDF_PROGRESS_CONTROL_H_
|
14
pdf/resource.h
Normal file
14
pdf/resource.h
Normal file
@ -0,0 +1,14 @@
|
||||
//{{NO_DEPENDENCIES}}
|
||||
// Microsoft Visual C++ generated include file.
|
||||
// Used by pdf.rc
|
||||
|
||||
// Next default values for new objects
|
||||
//
|
||||
#ifdef APSTUDIO_INVOKED
|
||||
#ifndef APSTUDIO_READONLY_SYMBOLS
|
||||
#define _APS_NEXT_RESOURCE_VALUE 101
|
||||
#define _APS_NEXT_COMMAND_VALUE 40001
|
||||
#define _APS_NEXT_CONTROL_VALUE 1001
|
||||
#define _APS_NEXT_SYMED_VALUE 101
|
||||
#endif
|
||||
#endif
|
49
pdf/resource_consts.h
Normal file
49
pdf/resource_consts.h
Normal file
@ -0,0 +1,49 @@
|
||||
// Copyright (c) 2010 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.
|
||||
|
||||
#ifndef PDF_RESOURCE_RESOURCE_CONSTS_H_
|
||||
#define PDF_RESOURCE_RESOURCE_CONSTS_H_
|
||||
|
||||
#include "base/basictypes.h"
|
||||
|
||||
namespace chrome_pdf {
|
||||
|
||||
const int kDragTimerMs = 50;
|
||||
const double kMinZoom = 0.1;
|
||||
const double kMaxZoom = 10.0;
|
||||
const double kZoomStep = 1.2;
|
||||
|
||||
const uint32 kFadingTimeoutMs = 50;
|
||||
|
||||
const uint32 kToolbarId = 10;
|
||||
const uint32 kThumbnailsId = 11;
|
||||
const uint32 kProgressBarId = 12;
|
||||
const uint32 kPageIndicatorId = 13;
|
||||
const uint32 kFitToPageButtonId = 100;
|
||||
const uint32 kFitToWidthButtonId = 101;
|
||||
const uint32 kZoomOutButtonId = 102;
|
||||
const uint32 kZoomInButtonId = 103;
|
||||
const uint32 kSaveButtonId = 104;
|
||||
const uint32 kPrintButtonId = 105;
|
||||
|
||||
const uint32 kAutoScrollId = 200;
|
||||
|
||||
// fading_rect.left = button_rect.left - kToolbarFadingOffsetLeft
|
||||
const int32 kToolbarFadingOffsetLeft = 40;
|
||||
// fading_rect.top = button_rect.top - kToolbarFadingOffsetTop
|
||||
const int32 kToolbarFadingOffsetTop = 40;
|
||||
// fading_rect.right = button_rect.right + kToolbarFadingOffsetRight
|
||||
const int32 kToolbarFadingOffsetRight = 10;
|
||||
// fading_rect.bottom = button_rect.bottom + kToolbarFadingOffsetBottom
|
||||
const int32 kToolbarFadingOffsetBottom = 8;
|
||||
|
||||
const int32 kProgressOffsetLeft = 8;
|
||||
const int32 kProgressOffsetBottom = 8;
|
||||
|
||||
// Width of the thumbnails control.
|
||||
const int32 kThumbnailsWidth = 196;
|
||||
|
||||
} // namespace chrome_pdf
|
||||
|
||||
#endif // PDF_RESOURCE_RESOURCE_CONSTS_H_
|
301
pdf/thumbnail_control.cc
Normal file
301
pdf/thumbnail_control.cc
Normal file
@ -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
|
67
pdf/thumbnail_control.h
Normal file
67
pdf/thumbnail_control.h
Normal file
@ -0,0 +1,67 @@
|
||||
// Copyright (c) 2010 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.
|
||||
|
||||
#ifndef PDF_THUMBNAIL_CONTROL_H_
|
||||
#define PDF_THUMBNAIL_CONTROL_H_
|
||||
|
||||
#include <map>
|
||||
#include <vector>
|
||||
|
||||
#include "pdf/control.h"
|
||||
#include "pdf/pdf_engine.h"
|
||||
#include "ppapi/cpp/input_event.h"
|
||||
|
||||
namespace chrome_pdf {
|
||||
|
||||
class NumberImageGenerator;
|
||||
|
||||
class ThumbnailControl : public Control {
|
||||
public:
|
||||
enum ThumbnailEventIds {
|
||||
EVENT_ID_THUMBNAIL_SELECTED = 100,
|
||||
};
|
||||
|
||||
explicit ThumbnailControl();
|
||||
virtual ~ThumbnailControl();
|
||||
|
||||
// Sets current position of the thumnail control.
|
||||
void SetPosition(int position, int total, bool invalidate);
|
||||
void SlideIn();
|
||||
void SlideOut();
|
||||
|
||||
virtual bool CreateThumbnailControl(
|
||||
uint32 id, const pp::Rect& rc,
|
||||
bool visible, Owner* owner, PDFEngine* engine,
|
||||
NumberImageGenerator* number_image_generator);
|
||||
|
||||
// Control interface.
|
||||
virtual void Show(bool visible, bool invalidate);
|
||||
virtual void Paint(pp::ImageData* image_data, const pp::Rect& rc);
|
||||
virtual bool HandleEvent(const pp::InputEvent& event);
|
||||
virtual void OnTimerFired(uint32 timer_id);
|
||||
|
||||
virtual void ResetEngine(PDFEngine* engine);
|
||||
|
||||
private:
|
||||
void ClearCache();
|
||||
|
||||
struct PageInfo {
|
||||
int index;
|
||||
pp::Rect rect;
|
||||
};
|
||||
|
||||
PDFEngine* engine_;
|
||||
pp::Rect visible_rect_;
|
||||
std::vector<PageInfo> visible_pages_;
|
||||
std::map<int, pp::ImageData*> image_cache_;
|
||||
int sliding_width_;
|
||||
int sliding_shift_;
|
||||
int sliding_timeout_;
|
||||
uint32 sliding_timer_id_;
|
||||
NumberImageGenerator* number_image_generator_;
|
||||
};
|
||||
|
||||
} // namespace chrome_pdf
|
||||
|
||||
#endif // PDF_THUMBNAIL_CONTROL_H_
|
Reference in New Issue
Block a user