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

Side by Side Diff: experimental/PdfViewer/pdf_viewer_main.cpp

Issue 1266093003: Remove experimental/PdfViewer (Closed) Base URL: https://skia.googlesource.com/skia.git@master
Patch Set: 2015-08-03 (Monday) 10:43:56 EDT Created 5 years, 4 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
OLDNEW
(Empty)
1 /*
2 * Copyright 2013 Google Inc.
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
7
8 #include "SkCanvas.h"
9 #include "SkCommandLineFlags.h"
10 #include "SkDevice.h"
11 #include "SkGraphics.h"
12 #include "SkImageDecoder.h"
13 #include "SkImageEncoder.h"
14 #include "SkOSFile.h"
15 #include "SkPdfConfig.h"
16 #include "SkPdfRenderer.h"
17 #include "SkPicture.h"
18 #include "SkStream.h"
19 #include "SkTypeface.h"
20 #include "SkTArray.h"
21 #include "SkNulCanvas.h"
22
23 DEFINE_string2(readPath, r, "", "pdf files or directories of pdf files to proces s.");
24 DEFINE_string2(writePath, w, "", "Directory to write the rendered pages.");
25 DEFINE_bool2(noExtensionForOnePagePdf, n, false, "No page extension if only one page.");
26 DEFINE_bool2(showMemoryUsage, m, false, "Show Memory usage.");
27 DEFINE_string2(pages, p, "all", "What pages to render and how:\n"
28 "\tall - all pages\n"
29 "\treverse - all pages, in reverse order\n"
30 "\tfirst - first page\n"
31 "\tlast - last page\n"
32 "\tnumber - a specific page number\n"
33 );
34 DEFINE_double(DPI, 72, "DPI to be used for rendering (scale).");
35 DEFINE_int32(benchLoad, 0, "Load the pdf file minimally N times, without any ren dering and \n"
36 "\tminimal parsing to ensure correctness. Default 0 (disabled).");
37 DEFINE_int32(benchRender, 0, "Render the pdf content N times. Default 0 (disable d)");
38 DEFINE_string2(config, c, "8888", "Canvas to render:\n"
39 "\t8888 - argb\n"
40 "\tnul - render in null canvas, any draw will just return.\n"
41 );
42 DEFINE_bool2(transparentBackground, t, false, "Make background transparent inste ad of white.");
43
44 /**
45 * Given list of directories and files to use as input, expects to find .pdf
46 * files and it will convert them to .png files writing them in the same directo ry
47 * one file for each page.
48 *
49 * Returns zero exit code if all .pdf files were converted successfully,
50 * otherwise returns error code 1.
51 */
52
53 static const char PDF_FILE_EXTENSION[] = "pdf";
54 static const char PNG_FILE_EXTENSION[] = "png";
55
56 /** Replaces the extension of a file.
57 * @param path File name whose extension will be changed.
58 * @param old_extension The old extension.
59 * @param new_extension The new extension.
60 * @returns false if the file did not has the expected extension.
61 * if false is returned, contents of path are undefined.
62 */
63 static bool add_page_and_replace_filename_extension(SkString* path, int page,
64 const char old_extension[],
65 const char new_extension[]) {
66 if (path->endsWith(old_extension)) {
67 path->remove(path->size() - strlen(old_extension),
68 strlen(old_extension));
69 if (!path->endsWith(".")) {
70 return false;
71 }
72 if (page >= 0) {
73 path->appendf("%i.", page);
74 }
75 path->append(new_extension);
76 return true;
77 }
78 return false;
79 }
80
81 /** Builds the output filename. path = dir/name, and it replaces expected
82 * .skp extension with .pdf extention.
83 * @param path Output filename.
84 * @param name The name of the file.
85 * @returns false if the file did not has the expected extension.
86 * if false is returned, contents of path are undefined.
87 */
88 static bool make_output_filepath(SkString* path, const SkString& dir,
89 const SkString& name,
90 int page) {
91 *path = SkOSPath::Join(dir.c_str(), name.c_str());
92 return add_page_and_replace_filename_extension(path, page,
93 PDF_FILE_EXTENSION,
94 PNG_FILE_EXTENSION);
95 }
96
97 static void setup_bitmap(SkBitmap* bitmap, int width, int height, SkColor color) {
98 bitmap->allocN32Pixels(width, height);
99 bitmap->eraseColor(color);
100 }
101
102 /** Write the output of pdf renderer to a file.
103 * @param outputDir Output dir.
104 * @param inputFilename The skp file that was read.
105 * @param renderer The object responsible to write the pdf file.
106 * @param page -1 means there is only one page (0), and render in a file without page extension
107 */
108
109 #ifdef PDF_TRACE_DIFF_IN_PNG
110 extern "C" SkBitmap* gDumpBitmap;
111 extern "C" SkCanvas* gDumpCanvas;
112 #endif
113
114 static bool render_page(const SkString& outputDir,
115 const SkString& inputFilename,
116 const SkPdfRenderer& renderer,
117 int page) {
118 SkRect rect = renderer.MediaBox(page < 0 ? 0 :page);
119
120 // Exercise all pdf codepaths as in normal rendering, but no actual bits are changed.
121 if (!FLAGS_config.isEmpty() && strcmp(FLAGS_config[0], "nul") == 0) {
122 SkBitmap bitmap;
123 SkNulCanvas canvas(bitmap);
124 renderer.renderPage(page < 0 ? 0 : page, &canvas, rect);
125 } else {
126 // 8888
127 SkRect rect = renderer.MediaBox(page < 0 ? 0 :page);
128
129 SkBitmap bitmap;
130 SkScalar width = SkScalarMul(rect.width(), SkDoubleToScalar(FLAGS_DPI / 72.0));
131 SkScalar height = SkScalarMul(rect.height(), SkDoubleToScalar(FLAGS_DPI / 72.0));
132
133 rect = SkRect::MakeWH(width, height);
134
135 SkColor background = FLAGS_transparentBackground ? SK_ColorTRANSPARENT : SK_ColorWHITE;
136
137 #ifdef PDF_DEBUG_3X
138 setup_bitmap(&bitmap, 3 * (int)SkScalarToDouble(width), 3 * (int)SkScala rToDouble(height),
139 background);
140 #else
141 setup_bitmap(&bitmap, (int)SkScalarToDouble(width), (int)SkScalarToDoubl e(height),
142 background);
143 #endif
144 if (strcmp(FLAGS_config[0], "8888") != 0) {
145 SkDebugf("unknown --config: %s\n", FLAGS_config[0]);
146 return false;
147 }
148 SkCanvas canvas(bitmap);
149
150 #ifdef PDF_TRACE_DIFF_IN_PNG
151 gDumpBitmap = &bitmap;
152 gDumpCanvas = &canvas;
153 #endif
154 renderer.renderPage(page < 0 ? 0 : page, &canvas, rect);
155
156 SkString outputPath;
157 if (!make_output_filepath(&outputPath, outputDir, inputFilename, page)) {
158 return false;
159 }
160 SkImageEncoder::EncodeFile(outputPath.c_str(), bitmap, SkImageEncoder::k PNG_Type, 100);
161
162 if (FLAGS_showMemoryUsage) {
163 SkDebugf("Memory usage after page %i rendered: %u\n",
164 page < 0 ? 0 : page, (unsigned int)renderer.bytesUsed());
165 }
166 }
167 return true;
168 }
169
170 /** Reads an skp file, renders it to pdf and writes the output to a pdf file
171 * @param inputPath The skp file to be read.
172 * @param outputDir Output dir.
173 */
174 static bool process_pdf(const SkString& inputPath, const SkString& outputDir) {
175 SkDebugf("Loading PDF: %s\n", inputPath.c_str());
176
177 SkString inputFilename = SkOSPath::Basename(inputPath.c_str());
178
179 SkAutoTDelete<SkPdfRenderer> renderer(SkPdfRenderer::CreateFromFile(inputPat h.c_str()));
180 if (NULL == renderer.get()) {
181 SkDebugf("Failure loading file %s\n", inputPath.c_str());
182 return false;
183 }
184
185 if (FLAGS_showMemoryUsage) {
186 SkDebugf("Memory usage after load: %u\n", (unsigned int) renderer->bytes Used());
187 }
188
189 // TODO(edisonn): bench timers
190 if (FLAGS_benchLoad > 0) {
191 for (int i = 0 ; i < FLAGS_benchLoad; i++) {
192 SkAutoTDelete<SkPdfRenderer> benchRenderer(
193 SkPdfRenderer::CreateFromFile(inputPath.c_str()));
194 if (NULL == benchRenderer.get()) {
195 SkDebugf("Failed to load on %ith attempt\n", i);
196 } else if (FLAGS_showMemoryUsage) {
197 SkDebugf("Memory usage after load %i number : %u\n", i,
198 (unsigned int) benchRenderer->bytesUsed());
199 }
200 }
201 }
202
203 if (!renderer->pages()) {
204 // This should never happen, since CreateFromFile will return NULL if th ere are no pages.
205 SkASSERT(false);
206 SkDebugf("ERROR: Empty PDF Document %s\n", inputPath.c_str());
207 return false;
208 }
209
210 bool success = true;
211 for (int i = 0; i < FLAGS_benchRender + 1; i++) {
212 // TODO(edisonn) if (i == 1) start timer
213 if (strcmp(FLAGS_pages[0], "all") == 0) {
214 for (int pn = 0; pn < renderer->pages(); ++pn) {
215 success &= render_page(outputDir, inputFilename, *renderer,
216 FLAGS_noExtensionForOnePagePdf && renderer->pages() == 1 ? -1 : pn);
217 }
218 } else if (strcmp(FLAGS_pages[0], "reverse") == 0) {
219 for (int pn = renderer->pages() - 1; pn >= 0; --pn) {
220 success &= render_page(outputDir, inputFilename, *renderer,
221 FLAGS_noExtensionForOnePagePdf && renderer->pages() == 1 ? -1 : pn);
222 }
223 } else if (strcmp(FLAGS_pages[0], "first") == 0) {
224 success &= render_page(outputDir, inputFilename, *renderer,
225 FLAGS_noExtensionForOnePagePdf && renderer->pages() == 1 ? - 1 : 0);
226 } else if (strcmp(FLAGS_pages[0], "last") == 0) {
227 success &= render_page(outputDir, inputFilename, *renderer,
228 FLAGS_noExtensionForOnePagePdf && renderer->pages() == 1 ? - 1
229 : renderer->pages() - 1);
230 } else {
231 int pn = atoi(FLAGS_pages[0]);
232 success &= render_page(outputDir, inputFilename, *renderer,
233 FLAGS_noExtensionForOnePagePdf && renderer->pages() == 1 ? - 1 : pn);
234 }
235 }
236
237 if (!success) {
238 SkDebugf("Failures for file %s\n", inputPath.c_str());
239 }
240
241 return success;
242 }
243
244 /** For each file in the directory or for the file passed in input, call
245 * parse_pdf.
246 * @param input A directory or an pdf file.
247 * @param outputDir Output dir.
248 */
249 static int process_input(const char* input, const SkString& outputDir) {
250 int failures = 0;
251 if (sk_isdir(input)) {
252 SkOSFile::Iter iter(input, PDF_FILE_EXTENSION);
253 SkString inputFilename;
254 while (iter.next(&inputFilename)) {
255 SkString inputPath = SkOSPath::Join(input, inputFilename.c_str());
256 if (!process_pdf(inputPath, outputDir)) {
257 ++failures;
258 }
259 }
260 } else {
261 SkString inputPath(input);
262 if (!process_pdf(inputPath, outputDir)) {
263 ++failures;
264 }
265 }
266 return failures;
267 }
268
269 int tool_main(int argc, char** argv);
270 int tool_main(int argc, char** argv) {
271 SkCommandLineFlags::SetUsage("Parse and Render .pdf files (pdf viewer).");
272 SkCommandLineFlags::Parse(argc, argv);
273
274 if (FLAGS_readPath.isEmpty()) {
275 SkDebugf(".pdf files or directories are required.\n");
276 exit(-1);
277 }
278
279 SkString outputDir;
280 if (FLAGS_writePath.count() == 1) {
281 outputDir.set(FLAGS_writePath[0]);
282 }
283
284 int failures = 0;
285 for (int i = 0; i < FLAGS_readPath.count(); i ++) {
286 failures += process_input(FLAGS_readPath[i], outputDir);
287 }
288
289 reportPdfRenderStats();
290
291 if (failures != 0) {
292 SkDebugf("Failed to render %i PDFs.\n", failures);
293 return 1;
294 }
295
296 return 0;
297 }
298
299 #if !defined SK_BUILD_FOR_IOS
300 int main(int argc, char * const argv[]) {
301 return tool_main(argc, (char**) argv);
302 }
303 #endif
OLDNEW
« no previous file with comments | « experimental/PdfViewer/inc/SkPdfTokenLooper.h ('k') | experimental/PdfViewer/pdfparser/SkPdfNYI.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698