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

Side by Side 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 unified diff | 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 »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include <memory>
6 #include <string>
7
8 #include "base/bind.h"
9 #include "base/macros.h"
10 #include "base/memory/scoped_ptr.h"
11 #include "mojo/application/application_runner_chromium.h"
12 #include "mojo/data_pipe_utils/data_pipe_utils.h"
13 #include "mojo/public/c/system/main.h"
14 #include "mojo/ui/choreographer.h"
15 #include "mojo/ui/content_viewer_app.h"
16 #include "mojo/ui/ganesh_view.h"
17 #include "mojo/ui/input_handler.h"
18 #include "third_party/pdfium/fpdfsdk/include/fpdf_ext.h"
19 #include "third_party/pdfium/fpdfsdk/include/fpdfview.h"
20 #include "third_party/skia/include/core/SkCanvas.h"
21 #include "third_party/skia/include/core/SkData.h"
22 #include "third_party/skia/include/core/SkImage.h"
23 #include "third_party/skia/include/core/SkImageInfo.h"
24 #include "third_party/skia/include/core/SkSurface.h"
25 #include "v8/include/v8.h"
26
27 namespace examples {
28
29 namespace {
30 constexpr uint32_t kContentImageResourceId = 1;
31 constexpr uint32_t kRootNodeId = mojo::gfx::composition::kSceneRootNodeId;
32 } // namespace
33
34 class PDFLibrary;
35
36 class PDFDocument {
37 public:
38 PDFDocument(const std::shared_ptr<PDFLibrary>& pdf_library,
39 FPDF_DOCUMENT doc,
40 const std::string& data)
41 : pdf_library_(pdf_library),
42 doc_(doc),
43 data_(data),
44 page_count_(FPDF_GetPageCount(doc_)) {}
45
46 ~PDFDocument() { FPDF_CloseDocument(doc_); }
47
48 uint32_t page_count() { return page_count_; }
49
50 skia::RefPtr<SkImage> DrawPage(int page_index, const mojo::Size& size) {
51 FPDF_PAGE page = FPDF_LoadPage(doc_, page_index);
52
53 double width_pts = FPDF_GetPageWidth(page);
54 double height_pts = FPDF_GetPageHeight(page);
55
56 int width, height;
57 if (size.width * height_pts < size.height * width_pts) {
58 width = size.width;
59 height = height_pts * size.width / width_pts;
60 } else {
61 width = width_pts * size.height / height_pts;
62 height = size.height;
63 }
64
65 int stride = width * 4;
66 skia::RefPtr<SkData> pixels =
67 skia::AdoptRef(SkData::NewUninitialized(stride * height));
68 DCHECK(pixels);
69
70 FPDF_BITMAP bitmap = FPDFBitmap_CreateEx(width, height, FPDFBitmap_BGRA,
71 pixels->writable_data(), stride);
72 FPDFBitmap_FillRect(bitmap, 0, 0, width, height, 0xFFFFFFFF);
73 FPDF_RenderPageBitmap(bitmap, page, 0, 0, width, height, 0, 0);
74 FPDFBitmap_Destroy(bitmap);
75
76 FPDF_ClosePage(page);
77
78 SkImageInfo info = SkImageInfo::Make(width, height, kBGRA_8888_SkColorType,
79 kOpaque_SkAlphaType);
80 return skia::AdoptRef(SkImage::NewRasterData(info, pixels.get(), stride));
81 }
82
83 private:
84 std::shared_ptr<PDFLibrary> pdf_library_;
85 FPDF_DOCUMENT doc_;
86 std::string data_;
87 uint32_t page_count_;
88 };
89
90 class PDFLibrary : public std::enable_shared_from_this<PDFLibrary> {
91 public:
92 PDFLibrary() {
93 v8::V8::InitializeICU();
94 FPDF_InitLibrary();
95 }
96
97 ~PDFLibrary() { FPDF_DestroyLibrary(); }
98
99 std::shared_ptr<PDFDocument> Decode(mojo::URLResponsePtr response) {
100 std::string data;
101 mojo::common::BlockingCopyToString(response->body.Pass(), &data);
102 if (data.length() >= static_cast<size_t>(std::numeric_limits<int>::max()))
103 return nullptr;
104
105 FPDF_DOCUMENT doc = FPDF_LoadMemDocument(
106 data.data(), static_cast<int>(data.length()), nullptr);
107 if (!doc)
108 return nullptr;
109
110 return std::make_shared<PDFDocument>(shared_from_this(), doc, data);
111 }
112 };
113
114 class PDFDocumentView : public mojo::ui::GaneshView,
115 public mojo::ui::ChoreographerDelegate,
116 public mojo::ui::InputListener {
117 public:
118 PDFDocumentView(
119 mojo::ApplicationImpl* app_impl,
120 const std::shared_ptr<PDFDocument>& pdf_document,
121 const mojo::ui::ViewProvider::CreateViewCallback& create_view_callback)
122 : GaneshView(app_impl, "PDFDocumentViewer", create_view_callback),
123 pdf_document_(pdf_document),
124 choreographer_(scene(), this),
125 input_handler_(view_service_provider(), this) {
126 DCHECK(pdf_document_);
127 }
128
129 ~PDFDocumentView() override {}
130
131 private:
132 // |GaneshView|:
133 void OnLayout(mojo::ui::ViewLayoutParamsPtr layout_params,
134 mojo::Array<uint32_t> children_needing_layout,
135 const OnLayoutCallback& callback) override {
136 size_.width = layout_params->constraints->max_width;
137 size_.height = layout_params->constraints->max_height;
138
139 auto info = mojo::ui::ViewLayoutResult::New();
140 info->size = size_.Clone();
141 callback.Run(info.Pass());
142
143 Redraw();
144 }
145
146 // |InputListener|:
147 void OnEvent(mojo::EventPtr event, const OnEventCallback& callback) override {
148 if (event->key_data && (event->action != mojo::EventType::KEY_PRESSED ||
149 event->key_data->is_char)) {
150 callback.Run(false);
151 return;
152 }
153
154 if ((event->key_data &&
155 event->key_data->windows_key_code == mojo::KeyboardCode::DOWN) ||
156 (event->pointer_data && event->pointer_data->vertical_wheel < 0)) {
157 GotoNextPage();
158 callback.Run(true);
159 return;
160 }
161
162 if ((event->key_data &&
163 event->key_data->windows_key_code == mojo::KeyboardCode::UP) ||
164 (event->pointer_data && event->pointer_data->vertical_wheel > 0)) {
165 GotoPreviousPage();
166 callback.Run(true);
167 return;
168 }
169
170 callback.Run(false);
171 }
172
173 // |ChoreographerDelegate|:
174 void OnDraw(const mojo::gfx::composition::FrameInfo& frame_info,
175 const base::TimeDelta& time_delta) override {
176 mojo::Rect bounds;
177 bounds.width = size_.width;
178 bounds.height = size_.height;
179
180 auto update = mojo::gfx::composition::SceneUpdate::New();
181 mojo::gfx::composition::ResourcePtr content_resource =
182 ganesh_renderer()->DrawCanvas(
183 size_,
184 base::Bind(&PDFDocumentView::DrawContent, base::Unretained(this)));
185 DCHECK(content_resource);
186 update->resources.insert(kContentImageResourceId, content_resource.Pass());
187
188 auto root_node = mojo::gfx::composition::Node::New();
189 root_node->op = mojo::gfx::composition::NodeOp::New();
190 root_node->op->set_image(mojo::gfx::composition::ImageNodeOp::New());
191 root_node->op->get_image()->content_rect = bounds.Clone();
192 root_node->op->get_image()->image_resource_id = kContentImageResourceId;
193 update->nodes.insert(kRootNodeId, root_node.Pass());
194
195 scene()->Update(update.Pass());
196 scene()->Publish(nullptr);
197 }
198
199 void DrawContent(SkCanvas* canvas) {
200 if (!cached_image_) {
201 cached_image_ = pdf_document_->DrawPage(page_, size_);
202 }
203
204 if (cached_image_) {
205 canvas->clear(SK_ColorBLACK);
206 canvas->drawImageRect(
207 cached_image_.get(),
208 SkRect::MakeWH(cached_image_->width(), cached_image_->height()),
209 SkRect::MakeXYWH((size_.width - cached_image_->width()) / 2,
210 (size_.height - cached_image_->height()) / 2,
211 cached_image_->width(), cached_image_->height()),
212 nullptr);
213 } else {
214 canvas->clear(SK_ColorBLUE);
215 }
216 }
217
218 void GotoNextPage() {
219 if (page_ + 1 < pdf_document_->page_count()) {
220 page_++;
221 Redraw();
222 }
223 }
224
225 void GotoPreviousPage() {
226 if (page_ > 0) {
227 page_--;
228 Redraw();
229 }
230 }
231
232 void Redraw() {
233 cached_image_.clear();
234 choreographer_.ScheduleDraw();
235 }
236
237 std::shared_ptr<PDFDocument> pdf_document_;
238 uint32_t page_ = 0u;
239 skia::RefPtr<SkImage> cached_image_;
240
241 mojo::Size size_;
242 mojo::ui::Choreographer choreographer_;
243 mojo::ui::InputHandler input_handler_;
244
245 DISALLOW_COPY_AND_ASSIGN(PDFDocumentView);
246 };
247
248 class PDFContentViewProviderApp : public mojo::ui::ViewProviderApp {
249 public:
250 PDFContentViewProviderApp(const std::shared_ptr<PDFLibrary>& pdf_library,
251 const std::shared_ptr<PDFDocument>& pdf_document)
252 : pdf_library_(pdf_library), pdf_document_(pdf_document) {
253 DCHECK(pdf_library_);
254 DCHECK(pdf_document_);
255 }
256
257 ~PDFContentViewProviderApp() override {}
258
259 bool CreateView(
260 const std::string& connection_url,
261 mojo::InterfaceRequest<mojo::ServiceProvider> services,
262 mojo::ServiceProviderPtr exposed_services,
263 const mojo::ui::ViewProvider::CreateViewCallback& callback) override {
264 new PDFDocumentView(app_impl(), pdf_document_, callback);
265 return true;
266 }
267
268 private:
269 std::shared_ptr<PDFLibrary> pdf_library_;
270 std::shared_ptr<PDFDocument> pdf_document_;
271
272 DISALLOW_COPY_AND_ASSIGN(PDFContentViewProviderApp);
273 };
274
275 class PDFContentViewerApp : public mojo::ui::ContentViewerApp {
276 public:
277 PDFContentViewerApp() : pdf_library_(std::make_shared<PDFLibrary>()) {}
278
279 ~PDFContentViewerApp() override {}
280
281 mojo::ui::ViewProviderApp* LoadContent(
282 const std::string& content_handler_url,
283 mojo::URLResponsePtr response) override {
284 std::shared_ptr<PDFDocument> pdf_document =
285 pdf_library_->Decode(response.Pass());
286 if (!pdf_document) {
287 LOG(ERROR) << "Could not decode PDFDocument.";
288 return nullptr;
289 }
290
291 return new PDFContentViewProviderApp(pdf_library_, pdf_document);
292 }
293
294 private:
295 std::shared_ptr<PDFLibrary> pdf_library_;
296
297 DISALLOW_COPY_AND_ASSIGN(PDFContentViewerApp);
298 };
299
300 } // namespace examples
301
302 MojoResult MojoMain(MojoHandle application_request) {
303 mojo::ApplicationRunnerChromium runner(new examples::PDFContentViewerApp());
304 return runner.Run(application_request);
305 }
OLDNEW
« 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