blob: ac75707c4fc43f09d5ada655e73faa5f8b56e891 [file] [log] [blame]
junov@chromium.org777442d2012-06-12 14:56:36 +00001/*
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
junov@chromium.org777442d2012-06-12 14:56:36 +00008#include "SkBitmap.h"
9#include "SkCanvas.h"
keyar@chromium.org472b3792012-07-20 22:34:27 +000010#include "SkDevice.h"
borenet@google.com10ef79e2012-09-10 17:19:06 +000011#include "SkGraphics.h"
keyar@chromium.orgf4959ab2012-08-23 20:53:25 +000012#include "SkMath.h"
junov@chromium.org777442d2012-06-12 14:56:36 +000013#include "SkOSFile.h"
14#include "SkPicture.h"
15#include "SkStream.h"
16#include "SkString.h"
senorblanco@chromium.org3cbbb542012-07-13 18:55:53 +000017#include "SkTArray.h"
keyar@chromium.org451bb9f2012-07-26 17:27:57 +000018#include "PictureRenderer.h"
twiz@google.coma31b8bb2012-06-22 18:24:56 +000019#include "picture_utils.h"
junov@chromium.org777442d2012-06-12 14:56:36 +000020
junov@chromium.org777442d2012-06-12 14:56:36 +000021static void usage(const char* argv0) {
22 SkDebugf("SkPicture rendering tool\n");
23 SkDebugf("\n"
24"Usage: \n"
keyar@chromium.org472b3792012-07-20 22:34:27 +000025" %s <input>... <outputDir> \n"
keyar@chromium.orgf4959ab2012-08-23 20:53:25 +000026" [--mode pipe | pow2tile minWidth height[%] | simple\n"
27" | tile width[%] height[%]]\n"
keyar@chromium.orgc81686c2012-08-20 15:04:04 +000028" [--device bitmap"
29#if SK_SUPPORT_GPU
30" | gpu"
31#endif
32"]"
junov@chromium.org777442d2012-06-12 14:56:36 +000033, argv0);
keyar@chromium.org472b3792012-07-20 22:34:27 +000034 SkDebugf("\n\n");
junov@chromium.org777442d2012-06-12 14:56:36 +000035 SkDebugf(
keyar@chromium.org795cd472012-08-02 18:57:53 +000036" input: A list of directories and files to use as input. Files are\n"
37" expected to have the .skp extension.\n\n");
junov@chromium.org777442d2012-06-12 14:56:36 +000038 SkDebugf(
keyar@chromium.org795cd472012-08-02 18:57:53 +000039" outputDir: directory to write the rendered images.\n\n");
keyar@chromium.org472b3792012-07-20 22:34:27 +000040 SkDebugf(
keyar@chromium.orgf4959ab2012-08-23 20:53:25 +000041" --mode pipe | pow2tile minWidth height[%] | simple\n"
42" | tile width[%] height[%]: Run in the corresponding mode.\n"
43" Default is simple.\n");
keyar@chromium.org472b3792012-07-20 22:34:27 +000044 SkDebugf(
keyar@chromium.org795cd472012-08-02 18:57:53 +000045" pipe, Render using a SkGPipe.\n");
46 SkDebugf(
keyar@chromium.orgf4959ab2012-08-23 20:53:25 +000047" 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(
keyar@chromium.org795cd472012-08-02 18:57:53 +000056" 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");
keyar@chromium.orgc81686c2012-08-20 15:04:04 +000060 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");
keyar@chromium.orgc81686c2012-08-20 15:04:04 +000069#if SK_SUPPORT_GPU
keyar@chromium.orga40c20d2012-08-20 15:04:12 +000070 SkDebugf(
keyar@chromium.orgc81686c2012-08-20 15:04:04 +000071" gpu, Render to the GPU.\n");
72#endif
junov@chromium.org777442d2012-06-12 14:56:36 +000073}
74
keyar@chromium.org1cbd47c2012-07-13 18:22:59 +000075static void make_output_filepath(SkString* path, const SkString& dir,
junov@chromium.org777442d2012-06-12 14:56:36 +000076 const SkString& name) {
twiz@google.coma31b8bb2012-06-22 18:24:56 +000077 sk_tools::make_filepath(path, dir, name);
junov@chromium.org777442d2012-06-12 14:56:36 +000078 path->remove(path->size() - 3, 3);
79 path->append("png");
80}
81
keyar@chromium.org1cbd47c2012-07-13 18:22:59 +000082static void write_output(const SkString& outputDir, const SkString& inputFilename,
keyar@chromium.org9299ede2012-08-21 19:05:08 +000083 const sk_tools::PictureRenderer& renderer) {
junov@chromium.org777442d2012-06-12 14:56:36 +000084 SkString outputPath;
85 make_output_filepath(&outputPath, outputDir, inputFilename);
keyar@chromium.org9299ede2012-08-21 19:05:08 +000086 bool isWritten = renderer.write(outputPath);
junov@chromium.org777442d2012-06-12 14:56:36 +000087 if (!isWritten) {
88 SkDebugf("Could not write to file %s\n", outputPath.c_str());
89 }
90}
91
keyar@chromium.org1cbd47c2012-07-13 18:22:59 +000092static void render_picture(const SkString& inputPath, const SkString& outputDir,
keyar@chromium.org451bb9f2012-07-26 17:27:57 +000093 sk_tools::PictureRenderer& renderer) {
keyar@chromium.orgd1dc9202012-07-09 18:32:08 +000094 SkString inputFilename;
95 sk_tools::get_basename(&inputFilename, inputPath);
twiz@google.coma31b8bb2012-06-22 18:24:56 +000096
keyar@chromium.orgd1dc9202012-07-09 18:32:08 +000097 SkFILEStream inputStream;
twiz@google.coma31b8bb2012-06-22 18:24:56 +000098 inputStream.setPath(inputPath.c_str());
99 if (!inputStream.isValid()) {
100 SkDebugf("Could not open file %s\n", inputPath.c_str());
101 return;
102 }
103
junov@chromium.org777442d2012-06-12 14:56:36 +0000104 SkPicture picture(&inputStream);
keyar@chromium.org451bb9f2012-07-26 17:27:57 +0000105
keyar@chromium.org9d696c02012-08-07 17:11:33 +0000106 renderer.init(&picture);
107
scroggo@google.com9a412522012-09-07 15:21:18 +0000108 renderer.render(true);
109
110 renderer.resetState();
keyar@chromium.org9d696c02012-08-07 17:11:33 +0000111
keyar@chromium.org9299ede2012-08-21 19:05:08 +0000112 write_output(outputDir, inputFilename, renderer);
keyar@chromium.org9d696c02012-08-07 17:11:33 +0000113
114 renderer.end();
junov@chromium.org777442d2012-06-12 14:56:36 +0000115}
116
keyar@chromium.org1cbd47c2012-07-13 18:22:59 +0000117static void process_input(const SkString& input, const SkString& outputDir,
keyar@chromium.org451bb9f2012-07-26 17:27:57 +0000118 sk_tools::PictureRenderer& renderer) {
keyar@chromium.org1cbd47c2012-07-13 18:22:59 +0000119 SkOSFile::Iter iter(input.c_str(), "skp");
junov@chromium.org777442d2012-06-12 14:56:36 +0000120 SkString inputFilename;
121
keyar@chromium.orgd1dc9202012-07-09 18:32:08 +0000122 if (iter.next(&inputFilename)) {
123 do {
124 SkString inputPath;
125 sk_tools::make_filepath(&inputPath, input, inputFilename);
keyar@chromium.org451bb9f2012-07-26 17:27:57 +0000126 render_picture(inputPath, outputDir, renderer);
keyar@chromium.orgd1dc9202012-07-09 18:32:08 +0000127 } while(iter.next(&inputFilename));
128 } else {
129 SkString inputPath(input);
keyar@chromium.org451bb9f2012-07-26 17:27:57 +0000130 render_picture(inputPath, outputDir, renderer);
keyar@chromium.org1cbd47c2012-07-13 18:22:59 +0000131 }
132}
133
134static void parse_commandline(int argc, char* const argv[], SkTArray<SkString>* inputs,
keyar@chromium.org451bb9f2012-07-26 17:27:57 +0000135 sk_tools::PictureRenderer*& renderer){
keyar@chromium.org1cbd47c2012-07-13 18:22:59 +0000136 const char* argv0 = argv[0];
137 char* const* stop = argv + argc;
138
keyar@chromium.orgc81686c2012-08-20 15:04:04 +0000139 sk_tools::PictureRenderer::SkDeviceTypes deviceType =
140 sk_tools::PictureRenderer::kBitmap_DeviceType;
141
keyar@chromium.org1cbd47c2012-07-13 18:22:59 +0000142 for (++argv; argv < stop; ++argv) {
keyar@chromium.org795cd472012-08-02 18:57:53 +0000143 if (0 == strcmp(*argv, "--mode")) {
144 SkDELETE(renderer);
145
keyar@chromium.orgcc6e5ef2012-07-27 20:09:26 +0000146 ++argv;
keyar@chromium.org795cd472012-08-02 18:57:53 +0000147 if (argv >= stop) {
148 SkDebugf("Missing mode for --mode\n");
149 usage(argv0);
150 exit(-1);
151 }
152
153 if (0 == strcmp(*argv, "pipe")) {
154 renderer = SkNEW(sk_tools::PipePictureRenderer);
155 } else if (0 == strcmp(*argv, "simple")) {
156 renderer = SkNEW(sk_tools::SimplePictureRenderer);
keyar@chromium.orgf4959ab2012-08-23 20:53:25 +0000157 } else if ((0 == strcmp(*argv, "tile")) || (0 == strcmp(*argv, "pow2tile"))) {
158 char* mode = *argv;
159 bool isPowerOf2Mode = false;
160
161 if (0 == strcmp(*argv, "pow2tile")) {
162 isPowerOf2Mode = true;
163 }
164
keyar@chromium.org795cd472012-08-02 18:57:53 +0000165 sk_tools::TiledPictureRenderer* tileRenderer =
166 SkNEW(sk_tools::TiledPictureRenderer);
167 ++argv;
168 if (argv >= stop) {
169 SkDELETE(tileRenderer);
keyar@chromium.orgf4959ab2012-08-23 20:53:25 +0000170 SkDebugf("Missing width for --mode %s\n", mode);
keyar@chromium.org795cd472012-08-02 18:57:53 +0000171 usage(argv0);
172 exit(-1);
173 }
174
keyar@chromium.orgf4959ab2012-08-23 20:53:25 +0000175 if (isPowerOf2Mode) {
176 int minWidth = atoi(*argv);
177
178 if (!SkIsPow2(minWidth) || minWidth <= 0) {
179 SkDELETE(tileRenderer);
180 SkDebugf("--mode %s must be given a width"
181 " value that is a power of two\n", mode);
182 exit(-1);
183 }
184
185 tileRenderer->setTileMinPowerOf2Width(minWidth);
186 } else if (sk_tools::is_percentage(*argv)) {
keyar@chromium.orgcc6e5ef2012-07-27 20:09:26 +0000187 tileRenderer->setTileWidthPercentage(atof(*argv));
188 if (!(tileRenderer->getTileWidthPercentage() > 0)) {
189 SkDELETE(tileRenderer);
keyar@chromium.orgf4959ab2012-08-23 20:53:25 +0000190 SkDebugf("--mode %s must be given a width percentage > 0\n", mode);
keyar@chromium.orgcc6e5ef2012-07-27 20:09:26 +0000191 exit(-1);
192 }
193 } else {
194 tileRenderer->setTileWidth(atoi(*argv));
195 if (!(tileRenderer->getTileWidth() > 0)) {
196 SkDELETE(tileRenderer);
keyar@chromium.orgf4959ab2012-08-23 20:53:25 +0000197 SkDebugf("--mode %s must be given a width > 0\n", mode);
keyar@chromium.orgcc6e5ef2012-07-27 20:09:26 +0000198 exit(-1);
199 }
200 }
keyar@chromium.org795cd472012-08-02 18:57:53 +0000201
202 ++argv;
203 if (argv >= stop) {
204 SkDELETE(tileRenderer);
keyar@chromium.orgf4959ab2012-08-23 20:53:25 +0000205 SkDebugf("Missing height for --mode %s\n", mode);
keyar@chromium.org795cd472012-08-02 18:57:53 +0000206 usage(argv0);
207 exit(-1);
208 }
209
keyar@chromium.org163b5672012-08-01 17:53:29 +0000210 if (sk_tools::is_percentage(*argv)) {
keyar@chromium.orgcc6e5ef2012-07-27 20:09:26 +0000211 tileRenderer->setTileHeightPercentage(atof(*argv));
212 if (!(tileRenderer->getTileHeightPercentage() > 0)) {
213 SkDELETE(tileRenderer);
214 SkDebugf(
keyar@chromium.orgf4959ab2012-08-23 20:53:25 +0000215 "--mode %s must be given a height percentage > 0\n", mode);
keyar@chromium.orgcc6e5ef2012-07-27 20:09:26 +0000216 exit(-1);
217 }
218 } else {
219 tileRenderer->setTileHeight(atoi(*argv));
220 if (!(tileRenderer->getTileHeight() > 0)) {
221 SkDELETE(tileRenderer);
keyar@chromium.orgf4959ab2012-08-23 20:53:25 +0000222 SkDebugf("--mode %s must be given a height > 0\n", mode);
keyar@chromium.orgcc6e5ef2012-07-27 20:09:26 +0000223 exit(-1);
224 }
225 }
keyar@chromium.org795cd472012-08-02 18:57:53 +0000226
227 renderer = tileRenderer;
keyar@chromium.orgcc6e5ef2012-07-27 20:09:26 +0000228 } else {
keyar@chromium.org795cd472012-08-02 18:57:53 +0000229 SkDebugf("%s is not a valid mode for --mode\n", *argv);
keyar@chromium.orgcc6e5ef2012-07-27 20:09:26 +0000230 usage(argv0);
231 exit(-1);
232 }
keyar@chromium.orgc81686c2012-08-20 15:04:04 +0000233 } else if (0 == strcmp(*argv, "--device")) {
234 ++argv;
235 if (argv >= stop) {
236 SkDebugf("Missing mode for --deivce\n");
237 usage(argv0);
238 exit(-1);
239 }
240
241 if (0 == strcmp(*argv, "bitmap")) {
242 deviceType = sk_tools::PictureRenderer::kBitmap_DeviceType;
243 }
244#if SK_SUPPORT_GPU
245 else if (0 == strcmp(*argv, "gpu")) {
246 deviceType = sk_tools::PictureRenderer::kGPU_DeviceType;
247 }
248#endif
249 else {
250 SkDebugf("%s is not a valid mode for --device\n", *argv);
251 usage(argv0);
252 exit(-1);
253 }
254
keyar@chromium.org472b3792012-07-20 22:34:27 +0000255 } else if ((0 == strcmp(*argv, "-h")) || (0 == strcmp(*argv, "--help"))) {
keyar@chromium.org451bb9f2012-07-26 17:27:57 +0000256 SkDELETE(renderer);
keyar@chromium.org472b3792012-07-20 22:34:27 +0000257 usage(argv0);
258 exit(-1);
keyar@chromium.orga2333d92012-07-16 17:29:16 +0000259 } else {
260 inputs->push_back(SkString(*argv));
261 }
keyar@chromium.orgd1dc9202012-07-09 18:32:08 +0000262 }
keyar@chromium.org472b3792012-07-20 22:34:27 +0000263
264 if (inputs->count() < 2) {
keyar@chromium.org451bb9f2012-07-26 17:27:57 +0000265 SkDELETE(renderer);
keyar@chromium.org472b3792012-07-20 22:34:27 +0000266 usage(argv0);
267 exit(-1);
268 }
keyar@chromium.org451bb9f2012-07-26 17:27:57 +0000269
270 if (NULL == renderer) {
271 renderer = SkNEW(sk_tools::SimplePictureRenderer);
272 }
keyar@chromium.org4ea96c52012-08-20 15:03:29 +0000273
keyar@chromium.orgc81686c2012-08-20 15:04:04 +0000274 renderer->setDeviceType(deviceType);
keyar@chromium.orgd1dc9202012-07-09 18:32:08 +0000275}
276
277int main(int argc, char* const argv[]) {
borenet@google.com10ef79e2012-09-10 17:19:06 +0000278 SkGraphics::Init();
keyar@chromium.org1cbd47c2012-07-13 18:22:59 +0000279 SkTArray<SkString> inputs;
keyar@chromium.org451bb9f2012-07-26 17:27:57 +0000280 sk_tools::PictureRenderer* renderer = NULL;
keyar@chromium.org472b3792012-07-20 22:34:27 +0000281
keyar@chromium.org451bb9f2012-07-26 17:27:57 +0000282 parse_commandline(argc, argv, &inputs, renderer);
keyar@chromium.org1cbd47c2012-07-13 18:22:59 +0000283 SkString outputDir = inputs[inputs.count() - 1];
keyar@chromium.org451bb9f2012-07-26 17:27:57 +0000284 SkASSERT(renderer);
keyar@chromium.orgd1dc9202012-07-09 18:32:08 +0000285
keyar@chromium.org1cbd47c2012-07-13 18:22:59 +0000286 for (int i = 0; i < inputs.count() - 1; i ++) {
keyar@chromium.org451bb9f2012-07-26 17:27:57 +0000287 process_input(inputs[i], outputDir, *renderer);
junov@chromium.org777442d2012-06-12 14:56:36 +0000288 }
keyar@chromium.org451bb9f2012-07-26 17:27:57 +0000289
290 SkDELETE(renderer);
borenet@google.com10ef79e2012-09-10 17:19:06 +0000291 SkGraphics::Term();
junov@chromium.org777442d2012-06-12 14:56:36 +0000292}