Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(337)

Unified Diff: examples/ui/pdf_viewer/pdf_viewer.cc

Issue 1559723002: Update the UI examples. (Closed) Base URL: git@github.com:domokit/mojo.git@moz-14
Patch Set: address feedback Created 4 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « examples/ui/pdf_viewer/README.md ('k') | examples/ui/png_viewer/BUILD.gn » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: examples/ui/pdf_viewer/pdf_viewer.cc
diff --git a/examples/ui/pdf_viewer/pdf_viewer.cc b/examples/ui/pdf_viewer/pdf_viewer.cc
new file mode 100644
index 0000000000000000000000000000000000000000..ee760ab71f7e459a04a58558de1fcead76e76c5a
--- /dev/null
+++ b/examples/ui/pdf_viewer/pdf_viewer.cc
@@ -0,0 +1,305 @@
+// Copyright 2014 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 <memory>
+#include <string>
+
+#include "base/bind.h"
+#include "base/macros.h"
+#include "base/memory/scoped_ptr.h"
+#include "mojo/application/application_runner_chromium.h"
+#include "mojo/data_pipe_utils/data_pipe_utils.h"
+#include "mojo/public/c/system/main.h"
+#include "mojo/ui/choreographer.h"
+#include "mojo/ui/content_viewer_app.h"
+#include "mojo/ui/ganesh_view.h"
+#include "mojo/ui/input_handler.h"
+#include "third_party/pdfium/fpdfsdk/include/fpdf_ext.h"
+#include "third_party/pdfium/fpdfsdk/include/fpdfview.h"
+#include "third_party/skia/include/core/SkCanvas.h"
+#include "third_party/skia/include/core/SkData.h"
+#include "third_party/skia/include/core/SkImage.h"
+#include "third_party/skia/include/core/SkImageInfo.h"
+#include "third_party/skia/include/core/SkSurface.h"
+#include "v8/include/v8.h"
+
+namespace examples {
+
+namespace {
+constexpr uint32_t kContentImageResourceId = 1;
+constexpr uint32_t kRootNodeId = mojo::gfx::composition::kSceneRootNodeId;
+} // namespace
+
+class PDFLibrary;
+
+class PDFDocument {
+ public:
+ PDFDocument(const std::shared_ptr<PDFLibrary>& pdf_library,
+ FPDF_DOCUMENT doc,
+ const std::string& data)
+ : pdf_library_(pdf_library),
+ doc_(doc),
+ data_(data),
+ page_count_(FPDF_GetPageCount(doc_)) {}
+
+ ~PDFDocument() { FPDF_CloseDocument(doc_); }
+
+ uint32_t page_count() { return page_count_; }
+
+ skia::RefPtr<SkImage> DrawPage(int page_index, const mojo::Size& size) {
+ FPDF_PAGE page = FPDF_LoadPage(doc_, page_index);
+
+ double width_pts = FPDF_GetPageWidth(page);
+ double height_pts = FPDF_GetPageHeight(page);
+
+ int width, height;
+ if (size.width * height_pts < size.height * width_pts) {
+ width = size.width;
+ height = height_pts * size.width / width_pts;
+ } else {
+ width = width_pts * size.height / height_pts;
+ height = size.height;
+ }
+
+ int stride = width * 4;
+ skia::RefPtr<SkData> pixels =
+ skia::AdoptRef(SkData::NewUninitialized(stride * height));
+ DCHECK(pixels);
+
+ FPDF_BITMAP bitmap = FPDFBitmap_CreateEx(width, height, FPDFBitmap_BGRA,
+ pixels->writable_data(), stride);
+ FPDFBitmap_FillRect(bitmap, 0, 0, width, height, 0xFFFFFFFF);
+ FPDF_RenderPageBitmap(bitmap, page, 0, 0, width, height, 0, 0);
+ FPDFBitmap_Destroy(bitmap);
+
+ FPDF_ClosePage(page);
+
+ SkImageInfo info = SkImageInfo::Make(width, height, kBGRA_8888_SkColorType,
+ kOpaque_SkAlphaType);
+ return skia::AdoptRef(SkImage::NewRasterData(info, pixels.get(), stride));
+ }
+
+ private:
+ std::shared_ptr<PDFLibrary> pdf_library_;
+ FPDF_DOCUMENT doc_;
+ std::string data_;
+ uint32_t page_count_;
+};
+
+class PDFLibrary : public std::enable_shared_from_this<PDFLibrary> {
+ public:
+ PDFLibrary() {
+ v8::V8::InitializeICU();
+ FPDF_InitLibrary();
+ }
+
+ ~PDFLibrary() { FPDF_DestroyLibrary(); }
+
+ std::shared_ptr<PDFDocument> Decode(mojo::URLResponsePtr response) {
+ std::string data;
+ mojo::common::BlockingCopyToString(response->body.Pass(), &data);
+ if (data.length() >= static_cast<size_t>(std::numeric_limits<int>::max()))
+ return nullptr;
+
+ FPDF_DOCUMENT doc = FPDF_LoadMemDocument(
+ data.data(), static_cast<int>(data.length()), nullptr);
+ if (!doc)
+ return nullptr;
+
+ return std::make_shared<PDFDocument>(shared_from_this(), doc, data);
+ }
+};
+
+class PDFDocumentView : public mojo::ui::GaneshView,
+ public mojo::ui::ChoreographerDelegate,
+ public mojo::ui::InputListener {
+ public:
+ PDFDocumentView(
+ mojo::ApplicationImpl* app_impl,
+ const std::shared_ptr<PDFDocument>& pdf_document,
+ const mojo::ui::ViewProvider::CreateViewCallback& create_view_callback)
+ : GaneshView(app_impl, "PDFDocumentViewer", create_view_callback),
+ pdf_document_(pdf_document),
+ choreographer_(scene(), this),
+ input_handler_(view_service_provider(), this) {
+ DCHECK(pdf_document_);
+ }
+
+ ~PDFDocumentView() override {}
+
+ private:
+ // |GaneshView|:
+ void OnLayout(mojo::ui::ViewLayoutParamsPtr layout_params,
+ mojo::Array<uint32_t> children_needing_layout,
+ const OnLayoutCallback& callback) override {
+ size_.width = layout_params->constraints->max_width;
+ size_.height = layout_params->constraints->max_height;
+
+ auto info = mojo::ui::ViewLayoutResult::New();
+ info->size = size_.Clone();
+ callback.Run(info.Pass());
+
+ Redraw();
+ }
+
+ // |InputListener|:
+ void OnEvent(mojo::EventPtr event, const OnEventCallback& callback) override {
+ if (event->key_data && (event->action != mojo::EventType::KEY_PRESSED ||
+ event->key_data->is_char)) {
+ callback.Run(false);
+ return;
+ }
+
+ if ((event->key_data &&
+ event->key_data->windows_key_code == mojo::KeyboardCode::DOWN) ||
+ (event->pointer_data && event->pointer_data->vertical_wheel < 0)) {
+ GotoNextPage();
+ callback.Run(true);
+ return;
+ }
+
+ if ((event->key_data &&
+ event->key_data->windows_key_code == mojo::KeyboardCode::UP) ||
+ (event->pointer_data && event->pointer_data->vertical_wheel > 0)) {
+ GotoPreviousPage();
+ callback.Run(true);
+ return;
+ }
+
+ callback.Run(false);
+ }
+
+ // |ChoreographerDelegate|:
+ void OnDraw(const mojo::gfx::composition::FrameInfo& frame_info,
+ const base::TimeDelta& time_delta) override {
+ mojo::Rect bounds;
+ bounds.width = size_.width;
+ bounds.height = size_.height;
+
+ auto update = mojo::gfx::composition::SceneUpdate::New();
+ mojo::gfx::composition::ResourcePtr content_resource =
+ ganesh_renderer()->DrawCanvas(
+ size_,
+ base::Bind(&PDFDocumentView::DrawContent, base::Unretained(this)));
+ DCHECK(content_resource);
+ update->resources.insert(kContentImageResourceId, content_resource.Pass());
+
+ auto root_node = mojo::gfx::composition::Node::New();
+ root_node->op = mojo::gfx::composition::NodeOp::New();
+ root_node->op->set_image(mojo::gfx::composition::ImageNodeOp::New());
+ root_node->op->get_image()->content_rect = bounds.Clone();
+ root_node->op->get_image()->image_resource_id = kContentImageResourceId;
+ update->nodes.insert(kRootNodeId, root_node.Pass());
+
+ scene()->Update(update.Pass());
+ scene()->Publish(nullptr);
+ }
+
+ void DrawContent(SkCanvas* canvas) {
+ if (!cached_image_) {
+ cached_image_ = pdf_document_->DrawPage(page_, size_);
+ }
+
+ if (cached_image_) {
+ canvas->clear(SK_ColorBLACK);
+ canvas->drawImageRect(
+ cached_image_.get(),
+ SkRect::MakeWH(cached_image_->width(), cached_image_->height()),
+ SkRect::MakeXYWH((size_.width - cached_image_->width()) / 2,
+ (size_.height - cached_image_->height()) / 2,
+ cached_image_->width(), cached_image_->height()),
+ nullptr);
+ } else {
+ canvas->clear(SK_ColorBLUE);
+ }
+ }
+
+ void GotoNextPage() {
+ if (page_ + 1 < pdf_document_->page_count()) {
+ page_++;
+ Redraw();
+ }
+ }
+
+ void GotoPreviousPage() {
+ if (page_ > 0) {
+ page_--;
+ Redraw();
+ }
+ }
+
+ void Redraw() {
+ cached_image_.clear();
+ choreographer_.ScheduleDraw();
+ }
+
+ std::shared_ptr<PDFDocument> pdf_document_;
+ uint32_t page_ = 0u;
+ skia::RefPtr<SkImage> cached_image_;
+
+ mojo::Size size_;
+ mojo::ui::Choreographer choreographer_;
+ mojo::ui::InputHandler input_handler_;
+
+ DISALLOW_COPY_AND_ASSIGN(PDFDocumentView);
+};
+
+class PDFContentViewProviderApp : public mojo::ui::ViewProviderApp {
+ public:
+ PDFContentViewProviderApp(const std::shared_ptr<PDFLibrary>& pdf_library,
+ const std::shared_ptr<PDFDocument>& pdf_document)
+ : pdf_library_(pdf_library), pdf_document_(pdf_document) {
+ DCHECK(pdf_library_);
+ DCHECK(pdf_document_);
+ }
+
+ ~PDFContentViewProviderApp() override {}
+
+ bool CreateView(
+ const std::string& connection_url,
+ mojo::InterfaceRequest<mojo::ServiceProvider> services,
+ mojo::ServiceProviderPtr exposed_services,
+ const mojo::ui::ViewProvider::CreateViewCallback& callback) override {
+ new PDFDocumentView(app_impl(), pdf_document_, callback);
+ return true;
+ }
+
+ private:
+ std::shared_ptr<PDFLibrary> pdf_library_;
+ std::shared_ptr<PDFDocument> pdf_document_;
+
+ DISALLOW_COPY_AND_ASSIGN(PDFContentViewProviderApp);
+};
+
+class PDFContentViewerApp : public mojo::ui::ContentViewerApp {
+ public:
+ PDFContentViewerApp() : pdf_library_(std::make_shared<PDFLibrary>()) {}
+
+ ~PDFContentViewerApp() override {}
+
+ mojo::ui::ViewProviderApp* LoadContent(
+ const std::string& content_handler_url,
+ mojo::URLResponsePtr response) override {
+ std::shared_ptr<PDFDocument> pdf_document =
+ pdf_library_->Decode(response.Pass());
+ if (!pdf_document) {
+ LOG(ERROR) << "Could not decode PDFDocument.";
+ return nullptr;
+ }
+
+ return new PDFContentViewProviderApp(pdf_library_, pdf_document);
+ }
+
+ private:
+ std::shared_ptr<PDFLibrary> pdf_library_;
+
+ DISALLOW_COPY_AND_ASSIGN(PDFContentViewerApp);
+};
+
+} // namespace examples
+
+MojoResult MojoMain(MojoHandle application_request) {
+ mojo::ApplicationRunnerChromium runner(new examples::PDFContentViewerApp());
+ return runner.Run(application_request);
+}
« no previous file with comments | « examples/ui/pdf_viewer/README.md ('k') | examples/ui/png_viewer/BUILD.gn » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698