build iOS with 'make all'
[platform/upstream/libSkiaSharp.git] / tools / render_pictures_main.cpp
1 /*
2  * Copyright 2012 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 "SkBitmap.h"
9 #include "SkCanvas.h"
10 #include "SkDevice.h"
11 #include "SkGraphics.h"
12 #include "SkMath.h"
13 #include "SkOSFile.h"
14 #include "SkPicture.h"
15 #include "SkStream.h"
16 #include "SkString.h"
17 #include "SkTArray.h"
18 #include "PictureRenderer.h"
19 #include "picture_utils.h"
20
21 static void usage(const char* argv0) {
22     SkDebugf("SkPicture rendering tool\n");
23     SkDebugf("\n"
24 "Usage: \n"
25 "     %s <input>... <outputDir> \n"
26 "     [--mode pipe | pow2tile minWidth height[%] | simple\n"
27 "         | tile width[%] height[%]]\n"
28 "     [--device bitmap"
29 #if SK_SUPPORT_GPU
30 " | gpu"
31 #endif
32 "]"
33 , argv0);
34     SkDebugf("\n\n");
35     SkDebugf(
36 "     input:     A list of directories and files to use as input. Files are\n"
37 "                expected to have the .skp extension.\n\n");
38     SkDebugf(
39 "     outputDir: directory to write the rendered images.\n\n");
40     SkDebugf(
41 "     --mode pipe | pow2tile minWidth height[%] | simple\n"
42 "          | tile width[%] height[%]: Run in the corresponding mode.\n"
43 "                                     Default is simple.\n");
44     SkDebugf(
45 "                     pipe, Render using a SkGPipe.\n");
46     SkDebugf(
47 "                     pow2tile minWidth height[%], Creates tiles with widths\n"
48 "                                                  that are all a power of two\n"
49 "                                                  such that they minimize the\n"
50 "                                                  amount of wasted tile space.\n"
51 "                                                  minWidth is the minimum width\n"
52 "                                                  of these tiles and must be a\n"
53 "                                                  power of two. A simple render\n"
54 "                                                  is done with these tiles.\n");
55     SkDebugf(
56 "                     simple, Render using the default rendering method.\n");
57     SkDebugf(
58 "                     tile width[%] height[%], Do a simple render using tiles\n"
59 "                                              with the given dimensions.\n");
60     SkDebugf("\n");
61     SkDebugf(
62 "     --device bitmap"
63 #if SK_SUPPORT_GPU
64 " | gpu"
65 #endif
66 ": Use the corresponding device. Default is bitmap.\n");
67     SkDebugf(
68 "                     bitmap, Render to a bitmap.\n");
69 #if SK_SUPPORT_GPU
70     SkDebugf(
71 "                     gpu, Render to the GPU.\n");
72 #endif
73 }
74
75 static void make_output_filepath(SkString* path, const SkString& dir,
76                                  const SkString& name) {
77     sk_tools::make_filepath(path, dir, name);
78     // Remove ".skp"
79     path->remove(path->size() - 4, 4);
80 }
81
82 static bool render_picture(const SkString& inputPath, const SkString& outputDir,
83                            sk_tools::PictureRenderer& renderer) {
84     SkString inputFilename;
85     sk_tools::get_basename(&inputFilename, inputPath);
86
87     SkFILEStream inputStream;
88     inputStream.setPath(inputPath.c_str());
89     if (!inputStream.isValid()) {
90         SkDebugf("Could not open file %s\n", inputPath.c_str());
91         return false;
92     }
93
94     bool success = false;
95     SkPicture picture(&inputStream, &success);
96     if (!success) {
97         SkDebugf("Could not read an SkPicture from %s\n", inputPath.c_str());
98         return false;
99     }
100
101     SkDebugf("drawing... [%i %i] %s\n", picture.width(), picture.height(),
102              inputPath.c_str());
103
104     renderer.init(&picture);
105     renderer.setup();
106
107     SkString outputPath;
108     make_output_filepath(&outputPath, outputDir, inputFilename);
109
110     success = renderer.render(&outputPath);
111     if (!success) {
112         SkDebugf("Could not write to file %s\n", outputPath.c_str());
113     }
114
115     renderer.resetState();
116
117     renderer.end();
118     return success;
119 }
120
121 static int process_input(const SkString& input, const SkString& outputDir,
122                           sk_tools::PictureRenderer& renderer) {
123     SkOSFile::Iter iter(input.c_str(), "skp");
124     SkString inputFilename;
125     int failures = 0;
126     if (iter.next(&inputFilename)) {
127         do {
128             SkString inputPath;
129             sk_tools::make_filepath(&inputPath, input, inputFilename);
130             if (!render_picture(inputPath, outputDir, renderer)) {
131                 ++failures;
132             }
133         } while(iter.next(&inputFilename));
134     } else if (SkStrEndsWith(input.c_str(), ".skp")) {
135         SkString inputPath(input);
136         if (!render_picture(inputPath, outputDir, renderer)) {
137             ++failures;
138         }
139     } else {
140         SkString warning;
141         warning.printf("Warning: skipping %s\n", input.c_str());
142         SkDebugf(warning.c_str());
143     }
144     return failures;
145 }
146
147 static void parse_commandline(int argc, char* const argv[], SkTArray<SkString>* inputs,
148                               sk_tools::PictureRenderer*& renderer){
149     const char* argv0 = argv[0];
150     char* const* stop = argv + argc;
151
152     sk_tools::PictureRenderer::SkDeviceTypes deviceType =
153         sk_tools::PictureRenderer::kBitmap_DeviceType;
154
155     for (++argv; argv < stop; ++argv) {
156         if (0 == strcmp(*argv, "--mode")) {
157             SkDELETE(renderer);
158
159             ++argv;
160             if (argv >= stop) {
161                 SkDebugf("Missing mode for --mode\n");
162                 usage(argv0);
163                 exit(-1);
164             }
165
166             if (0 == strcmp(*argv, "pipe")) {
167                 renderer = SkNEW(sk_tools::PipePictureRenderer);
168             } else if (0 == strcmp(*argv, "simple")) {
169                 renderer = SkNEW(sk_tools::SimplePictureRenderer);
170             } else if ((0 == strcmp(*argv, "tile")) || (0 == strcmp(*argv, "pow2tile"))) {
171                 char* mode = *argv;
172                 bool isPowerOf2Mode = false;
173
174                 if (0 == strcmp(*argv, "pow2tile")) {
175                     isPowerOf2Mode = true;
176                 }
177
178                 sk_tools::TiledPictureRenderer* tileRenderer =
179                     SkNEW(sk_tools::TiledPictureRenderer);
180                 ++argv;
181                 if (argv >= stop) {
182                     SkDELETE(tileRenderer);
183                     SkDebugf("Missing width for --mode %s\n", mode);
184                     usage(argv0);
185                     exit(-1);
186                 }
187
188                 if (isPowerOf2Mode) {
189                     int minWidth = atoi(*argv);
190
191                     if (!SkIsPow2(minWidth) || minWidth <= 0) {
192                         SkDELETE(tileRenderer);
193                         SkDebugf("--mode %s must be given a width"
194                                  " value that is a power of two\n", mode);
195                         exit(-1);
196                     }
197
198                     tileRenderer->setTileMinPowerOf2Width(minWidth);
199                 } else if (sk_tools::is_percentage(*argv)) {
200                     tileRenderer->setTileWidthPercentage(atof(*argv));
201                     if (!(tileRenderer->getTileWidthPercentage() > 0)) {
202                         SkDELETE(tileRenderer);
203                         SkDebugf("--mode %s must be given a width percentage > 0\n", mode);
204                         exit(-1);
205                     }
206                 } else {
207                     tileRenderer->setTileWidth(atoi(*argv));
208                     if (!(tileRenderer->getTileWidth() > 0)) {
209                         SkDELETE(tileRenderer);
210                         SkDebugf("--mode %s must be given a width > 0\n", mode);
211                         exit(-1);
212                     }
213                 }
214
215                 ++argv;
216                 if (argv >= stop) {
217                     SkDELETE(tileRenderer);
218                     SkDebugf("Missing height for --mode %s\n", mode);
219                     usage(argv0);
220                     exit(-1);
221                 }
222
223                 if (sk_tools::is_percentage(*argv)) {
224                     tileRenderer->setTileHeightPercentage(atof(*argv));
225                     if (!(tileRenderer->getTileHeightPercentage() > 0)) {
226                         SkDELETE(tileRenderer);
227                         SkDebugf(
228                             "--mode %s must be given a height percentage > 0\n", mode);
229                         exit(-1);
230                     }
231                 } else {
232                     tileRenderer->setTileHeight(atoi(*argv));
233                     if (!(tileRenderer->getTileHeight() > 0)) {
234                         SkDELETE(tileRenderer);
235                         SkDebugf("--mode %s must be given a height > 0\n", mode);
236                         exit(-1);
237                     }
238                 }
239
240                 renderer = tileRenderer;
241             } else {
242                 SkDebugf("%s is not a valid mode for --mode\n", *argv);
243                 usage(argv0);
244                 exit(-1);
245             }
246         } else if (0 == strcmp(*argv, "--device")) {
247             ++argv;
248             if (argv >= stop) {
249                 SkDebugf("Missing mode for --deivce\n");
250                 usage(argv0);
251                 exit(-1);
252             }
253
254             if (0 == strcmp(*argv, "bitmap")) {
255                 deviceType = sk_tools::PictureRenderer::kBitmap_DeviceType;
256             }
257 #if SK_SUPPORT_GPU
258             else if (0 == strcmp(*argv, "gpu")) {
259                 deviceType = sk_tools::PictureRenderer::kGPU_DeviceType;
260             }
261 #endif
262             else {
263                 SkDebugf("%s is not a valid mode for --device\n", *argv);
264                 usage(argv0);
265                 exit(-1);
266             }
267
268         } else if ((0 == strcmp(*argv, "-h")) || (0 == strcmp(*argv, "--help"))) {
269             SkDELETE(renderer);
270             usage(argv0);
271             exit(-1);
272         } else {
273             inputs->push_back(SkString(*argv));
274         }
275     }
276
277     if (inputs->count() < 2) {
278         SkDELETE(renderer);
279         usage(argv0);
280         exit(-1);
281     }
282
283     if (NULL == renderer) {
284         renderer = SkNEW(sk_tools::SimplePictureRenderer);
285     }
286
287     renderer->setDeviceType(deviceType);
288 }
289
290 int tool_main(int argc, char** argv);
291 int tool_main(int argc, char** argv) {
292     SkAutoGraphics ag;
293     SkTArray<SkString> inputs;
294     sk_tools::PictureRenderer* renderer = NULL;
295
296     parse_commandline(argc, argv, &inputs, renderer);
297     SkString outputDir = inputs[inputs.count() - 1];
298     SkASSERT(renderer);
299
300     int failures = 0;
301     for (int i = 0; i < inputs.count() - 1; i ++) {
302         failures += process_input(inputs[i], outputDir, *renderer);
303     }
304     if (failures != 0) {
305         SkDebugf("Failed to render %i pictures.\n", failures);
306         return 1;
307     }
308 #if SK_SUPPORT_GPU
309 #if GR_CACHE_STATS
310     if (renderer->isUsingGpuDevice()) {
311         GrContext* ctx = renderer->getGrContext();
312
313         ctx->printCacheStats();
314     }
315 #endif
316 #endif
317
318     SkDELETE(renderer);
319 }
320
321 #if !defined SK_BUILD_FOR_IOS
322 int main(int argc, char * const argv[]) {
323     return tool_main(argc, (char**) argv);
324 }
325 #endif