Index: examples/pdf_viewer/pdf_viewer.cc |
diff --git a/examples/png_viewer/png_viewer.cc b/examples/pdf_viewer/pdf_viewer.cc |
similarity index 63% |
copy from examples/png_viewer/png_viewer.cc |
copy to examples/pdf_viewer/pdf_viewer.cc |
index 0db5884f812a796b8cf71d28c56e32c640ee124b..c4f0c04c52c2f6c8a40fc1380a94c7f77cc463ac 100644 |
--- a/examples/png_viewer/png_viewer.cc |
+++ b/examples/pdf_viewer/pdf_viewer.cc |
@@ -2,14 +2,8 @@ |
// Use of this source code is governed by a BSD-style license that can be |
// found in the LICENSE file. |
-#include <algorithm> |
- |
-#include "base/macros.h" |
-#include "base/memory/scoped_ptr.h" |
-#include "base/message_loop/message_loop.h" |
#include "base/strings/string_tokenizer.h" |
#include "examples/bitmap_uploader/bitmap_uploader.h" |
-#include "examples/media_viewer/media_viewer.mojom.h" |
#include "mojo/application/application_runner_chromium.h" |
#include "mojo/public/c/system/main.h" |
#include "mojo/public/cpp/application/application_connection.h" |
@@ -24,48 +18,51 @@ |
#include "mojo/services/public/cpp/view_manager/view_manager_delegate.h" |
#include "mojo/services/public/cpp/view_manager/view_observer.h" |
#include "mojo/services/public/interfaces/content_handler/content_handler.mojom.h" |
-#include "third_party/skia/include/core/SkColor.h" |
-#include "ui/gfx/codec/png_codec.h" |
+#include "mojo/services/public/interfaces/input_events/input_events.mojom.h" |
+#include "mojo/services/public/interfaces/input_events/input_key_codes.mojom.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" |
+#include "v8/include/v8.h" |
+ |
+#define BACKGROUND_COLOR 0xFF888888 |
namespace mojo { |
namespace examples { |
-class PNGViewer; |
+class PDFViewer; |
-// TODO(aa): Hook up ZoomableMedia interface again. |
-class PNGView : public ViewManagerDelegate, public ViewObserver { |
+class PDFView : public ViewManagerDelegate, public ViewObserver { |
public: |
static void Spawn(URLResponsePtr response, |
ServiceProviderImpl* exported_services, |
scoped_ptr<ServiceProvider> imported_services, |
Shell* shell) { |
- // PNGView deletes itself when its View is destroyed. |
- new PNGView( |
+ // PDFView deletes itself when its View is destroyed. |
+ new PDFView( |
response.Pass(), exported_services, imported_services.Pass(), shell); |
} |
private: |
- static const uint16_t kMaxZoomPercentage = 400; |
- static const uint16_t kMinZoomPercentage = 20; |
- static const uint16_t kDefaultZoomPercentage = 100; |
- static const uint16_t kZoomStep = 20; |
- |
- PNGView(URLResponsePtr response, |
+ PDFView(URLResponsePtr response, |
ServiceProviderImpl* exported_services, |
scoped_ptr<ServiceProvider> imported_services, |
Shell* shell) |
- : width_(0), |
- height_(0), |
+ : current_page_(0), |
+ page_count_(0), |
+ doc_(NULL), |
imported_services_(imported_services.Pass()), |
shell_(shell), |
root_(nullptr), |
- view_manager_client_factory_(shell, this), |
- zoom_percentage_(kDefaultZoomPercentage) { |
+ view_manager_client_factory_(shell, this) { |
exported_services->AddService(&view_manager_client_factory_); |
- DecodePNG(response.Pass()); |
+ FetchPDF(response.Pass()); |
} |
- virtual ~PNGView() { |
+ virtual ~PDFView() { |
+ if (doc_) |
+ FPDF_CloseDocument(doc_); |
if (root_) |
root_->RemoveObserver(this); |
} |
@@ -79,13 +76,11 @@ class PNGView : public ViewManagerDelegate, public ViewObserver { |
root_->AddObserver(this); |
bitmap_uploader_.reset(new BitmapUploader(root_)); |
bitmap_uploader_->Init(shell_); |
- bitmap_uploader_->SetColor(SK_ColorGRAY); |
- if (bitmap_.get()) |
- DrawBitmap(); |
+ bitmap_uploader_->SetColor(BACKGROUND_COLOR); |
+ DrawBitmap(); |
} |
virtual void OnViewManagerDisconnected(ViewManager* view_manager) override { |
- // TODO(aa): Need to figure out how shutdown works. |
} |
// Overridden from ViewObserver: |
@@ -96,15 +91,65 @@ class PNGView : public ViewManagerDelegate, public ViewObserver { |
DrawBitmap(); |
} |
+ virtual void OnViewInputEvent(View* view, const EventPtr& event) override { |
+ if (event->key_data && |
+ (event->action != EVENT_TYPE_KEY_PRESSED || |
+ event->key_data->is_char)) { |
+ return; |
+ } |
+ if ((event->key_data && |
+ event->key_data->windows_key_code == KEYBOARD_CODE_DOWN) || |
+ (event->wheel_data && event->wheel_data->y_offset < 0)) { |
+ if (current_page_ < (page_count_ - 1)) { |
+ current_page_++; |
+ DrawBitmap(); |
+ } |
+ } else if ((event->key_data && |
+ event->key_data->windows_key_code == KEYBOARD_CODE_UP) || |
+ (event->wheel_data && event->wheel_data->y_offset > 0)) { |
+ if (current_page_ > 0) { |
+ current_page_--; |
+ DrawBitmap(); |
+ } |
+ } |
+ } |
+ |
virtual void OnViewDestroyed(View* view) override { |
DCHECK_EQ(view, root_); |
delete this; |
} |
- void DecodePNG(URLResponsePtr response) { |
+ void DrawBitmap() { |
+ if (!root_ || !doc_) |
+ return; |
+ |
+ FPDF_PAGE page = FPDF_LoadPage(doc_, current_page_); |
+ FPDF_TEXTPAGE text_page = FPDFText_LoadPage(page); |
+ int width = static_cast<int>(FPDF_GetPageWidth(page)); |
+ int height = static_cast<int>(FPDF_GetPageHeight(page)); |
+ |
+ scoped_ptr<std::vector<unsigned char>> bitmap; |
+ bitmap.reset(new std::vector<unsigned char>); |
+ bitmap->resize(width * height * 4); |
+ |
+ FPDF_BITMAP f_bitmap = FPDFBitmap_CreateEx( |
+ width, height, FPDFBitmap_BGRA, &(*bitmap)[0], width * 4); |
+ FPDFBitmap_FillRect(f_bitmap, 0, 0, width, height, 0xFFFFFFFF); |
+ FPDF_RenderPageBitmap(f_bitmap, page, 0, 0, width, height, 0, 0); |
+ FPDFBitmap_Destroy(f_bitmap); |
+ |
+ FPDFText_ClosePage(text_page); |
+ FPDF_ClosePage(page); |
+ |
+ bitmap_uploader_->SetBitmap(width, height, bitmap.Pass(), |
+ BitmapUploader::BGRA); |
+ } |
+ |
+ void FetchPDF(URLResponsePtr response) { |
int content_length = GetContentLength(response->headers); |
- scoped_ptr<unsigned char[]> data(new unsigned char[content_length]); |
- unsigned char* buf = data.get(); |
+ scoped_ptr<unsigned char[]> data; |
+ data_.reset(new unsigned char[content_length]); |
+ unsigned char* buf = data_.get(); |
uint32_t bytes_remaining = content_length; |
uint32_t num_bytes = bytes_remaining; |
while (bytes_remaining > 0) { |
@@ -122,43 +167,8 @@ class PNGView : public ViewManagerDelegate, public ViewObserver { |
} |
} |
- bitmap_.reset(new std::vector<unsigned char>); |
- gfx::PNGCodec::Decode(static_cast<const unsigned char*>(data.get()), |
- content_length, |
- gfx::PNGCodec::FORMAT_BGRA, |
- bitmap_.get(), |
- &width_, |
- &height_); |
- } |
- |
- void DrawBitmap() { |
- if (!root_) |
- return; |
- |
- |
- bitmap_uploader_->SetBitmap(width_, height_, bitmap_.Pass(), |
- BitmapUploader::BGRA); |
- } |
- |
- void ZoomIn() { |
- if (zoom_percentage_ >= kMaxZoomPercentage) |
- return; |
- zoom_percentage_ += kZoomStep; |
- DrawBitmap(); |
- } |
- |
- void ZoomOut() { |
- if (zoom_percentage_ <= kMinZoomPercentage) |
- return; |
- zoom_percentage_ -= kZoomStep; |
- DrawBitmap(); |
- } |
- |
- void ZoomToActualSize() { |
- if (zoom_percentage_ == kDefaultZoomPercentage) |
- return; |
- zoom_percentage_ = kDefaultZoomPercentage; |
- DrawBitmap(); |
+ doc_ = FPDF_LoadMemDocument(data_.get(), content_length, NULL); |
+ page_count_ = FPDF_GetPageCount(doc_); |
} |
int GetContentLength(const Array<String>& headers) { |
@@ -176,17 +186,17 @@ class PNGView : public ViewManagerDelegate, public ViewObserver { |
return 0; |
} |
- int width_; |
- int height_; |
- scoped_ptr<std::vector<unsigned char>> bitmap_; |
+ scoped_ptr<unsigned char[]> data_; |
+ int current_page_; |
+ int page_count_; |
+ FPDF_DOCUMENT doc_; |
scoped_ptr<ServiceProvider> imported_services_; |
Shell* shell_; |
View* root_; |
ViewManagerClientFactory view_manager_client_factory_; |
- uint16_t zoom_percentage_; |
scoped_ptr<BitmapUploader> bitmap_uploader_; |
- DISALLOW_COPY_AND_ASSIGN(PNGView); |
+ DISALLOW_COPY_AND_ASSIGN(PDFView); |
}; |
class ContentHandlerImpl : public InterfaceImpl<ContentHandler> { |
@@ -204,7 +214,7 @@ class ContentHandlerImpl : public InterfaceImpl<ContentHandler> { |
BindToRequest(exported_services, &service_provider); |
scoped_ptr<ServiceProvider> remote( |
exported_services->CreateRemoteServiceProvider()); |
- PNGView::Spawn(response.Pass(), exported_services, remote.Pass(), shell_); |
+ PDFView::Spawn(response.Pass(), exported_services, remote.Pass(), shell_); |
} |
Shell* shell_; |
@@ -212,15 +222,21 @@ class ContentHandlerImpl : public InterfaceImpl<ContentHandler> { |
DISALLOW_COPY_AND_ASSIGN(ContentHandlerImpl); |
}; |
-class PNGViewer : public ApplicationDelegate { |
+class PDFViewer : public ApplicationDelegate { |
public: |
- PNGViewer() {} |
+ PDFViewer() {} |
+ virtual ~PDFViewer() { |
+ FPDF_DestroyLibrary(); |
+ } |
private: |
// Overridden from ApplicationDelegate: |
virtual void Initialize(ApplicationImpl* app) override { |
content_handler_factory_.reset( |
new InterfaceFactoryImplWithContext<ContentHandlerImpl, Shell>( |
app->shell())); |
+ |
+ v8::V8::InitializeICU(); |
+ FPDF_InitLibrary(NULL); |
} |
// Overridden from ApplicationDelegate: |
@@ -233,13 +249,13 @@ class PNGViewer : public ApplicationDelegate { |
scoped_ptr<InterfaceFactoryImplWithContext<ContentHandlerImpl, Shell> > |
content_handler_factory_; |
- DISALLOW_COPY_AND_ASSIGN(PNGViewer); |
+ DISALLOW_COPY_AND_ASSIGN(PDFViewer); |
}; |
} // namespace examples |
} // namespace mojo |
MojoResult MojoMain(MojoHandle shell_handle) { |
- mojo::ApplicationRunnerChromium runner(new mojo::examples::PNGViewer); |
+ mojo::ApplicationRunnerChromium runner(new mojo::examples::PDFViewer); |
return runner.Run(shell_handle); |
} |