OLD | NEW |
1 /* | 1 /* |
2 * Copyright 2012 Google Inc. | 2 * Copyright 2012 Google Inc. |
3 * | 3 * |
4 * Use of this source code is governed by a BSD-style license that can be | 4 * Use of this source code is governed by a BSD-style license that can be |
5 * found in the LICENSE file. | 5 * found in the LICENSE file. |
6 */ | 6 */ |
7 | 7 |
8 #include "LazyDecodeBitmap.h" | 8 #include "LazyDecodeBitmap.h" |
9 #include "CopyTilesRenderer.h" | 9 #include "CopyTilesRenderer.h" |
10 #include "SkBitmap.h" | 10 #include "SkBitmap.h" |
(...skipping 14 matching lines...) Expand all Loading... |
25 // Flags used by this file, alphabetically: | 25 // Flags used by this file, alphabetically: |
26 DEFINE_int32(clone, 0, "Clone the picture n times before rendering."); | 26 DEFINE_int32(clone, 0, "Clone the picture n times before rendering."); |
27 DECLARE_bool(deferImageDecoding); | 27 DECLARE_bool(deferImageDecoding); |
28 DEFINE_int32(maxComponentDiff, 256, "Maximum diff on a component, 0 - 256. Compo
nents that differ " | 28 DEFINE_int32(maxComponentDiff, 256, "Maximum diff on a component, 0 - 256. Compo
nents that differ " |
29 "by more than this amount are considered errors, though all diffs a
re reported. " | 29 "by more than this amount are considered errors, though all diffs a
re reported. " |
30 "Requires --validate."); | 30 "Requires --validate."); |
31 DECLARE_string(readPath); | 31 DECLARE_string(readPath); |
32 DEFINE_bool(writeEncodedImages, false, "Any time the skp contains an encoded ima
ge, write it to a " | 32 DEFINE_bool(writeEncodedImages, false, "Any time the skp contains an encoded ima
ge, write it to a " |
33 "file rather than decoding it. Requires writePath to be set. Skips d
rawing the full " | 33 "file rather than decoding it. Requires writePath to be set. Skips d
rawing the full " |
34 "skp to a file. Not compatible with deferImageDecoding."); | 34 "skp to a file. Not compatible with deferImageDecoding."); |
| 35 DEFINE_string(writeJsonSummaryPath, "", "File to write a JSON summary of image r
esults to. " |
| 36 "TODO(epoger): Currently, this only works if --writePath is also s
pecified."); |
35 DEFINE_string2(writePath, w, "", "Directory to write the rendered images."); | 37 DEFINE_string2(writePath, w, "", "Directory to write the rendered images."); |
36 DEFINE_bool(writeWholeImage, false, "In tile mode, write the entire rendered ima
ge to a " | 38 DEFINE_bool(writeWholeImage, false, "In tile mode, write the entire rendered ima
ge to a " |
37 "file, instead of an image for each tile."); | 39 "file, instead of an image for each tile."); |
38 DEFINE_bool(validate, false, "Verify that the rendered image contains the same p
ixels as " | 40 DEFINE_bool(validate, false, "Verify that the rendered image contains the same p
ixels as " |
39 "the picture rendered in simple mode. When used in conjunction with
--bbh, results " | 41 "the picture rendered in simple mode. When used in conjunction with
--bbh, results " |
40 "are validated against the picture rendered in the same mode, but wi
thout the bbh."); | 42 "are validated against the picture rendered in the same mode, but wi
thout the bbh."); |
41 | 43 |
42 DEFINE_bool(bench_record, false, "If true, drop into an infinite loop of recordi
ng the picture."); | 44 DEFINE_bool(bench_record, false, "If true, drop into an infinite loop of recordi
ng the picture."); |
43 | 45 |
44 static void make_output_filepath(SkString* path, const SkString& dir, | 46 static void make_output_filepath(SkString* path, const SkString& dir, |
(...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
125 if (!(fileStream.isValid() && fileStream.write(buffer, size))) { | 127 if (!(fileStream.isValid() && fileStream.write(buffer, size))) { |
126 SkDebugf("Failed to write encoded data to \"%s\"\n", outPath.c_str()); | 128 SkDebugf("Failed to write encoded data to \"%s\"\n", outPath.c_str()); |
127 } | 129 } |
128 // Put in a dummy bitmap. | 130 // Put in a dummy bitmap. |
129 return SkImageDecoder::DecodeStream(&memStream, bitmap, SkBitmap::kNo_Config
, | 131 return SkImageDecoder::DecodeStream(&memStream, bitmap, SkBitmap::kNo_Config
, |
130 SkImageDecoder::kDecodeBounds_Mode); | 132 SkImageDecoder::kDecodeBounds_Mode); |
131 } | 133 } |
132 | 134 |
133 ////////////////////////////////////////////////////////////////////////////////
//////////////////// | 135 ////////////////////////////////////////////////////////////////////////////////
//////////////////// |
134 | 136 |
135 static bool render_picture(const SkString& inputPath, const SkString* outputDir, | 137 /** |
136 sk_tools::PictureRenderer& renderer, | 138 * Called only by render_picture(). |
137 SkBitmap** out) { | 139 */ |
| 140 static bool render_picture_internal(const SkString& inputPath, const SkString* o
utputDir, |
| 141 sk_tools::PictureRenderer& renderer, |
| 142 SkBitmap** out) { |
138 SkString inputFilename; | 143 SkString inputFilename; |
139 sk_tools::get_basename(&inputFilename, inputPath); | 144 sk_tools::get_basename(&inputFilename, inputPath); |
140 | 145 |
141 SkFILEStream inputStream; | 146 SkFILEStream inputStream; |
142 inputStream.setPath(inputPath.c_str()); | 147 inputStream.setPath(inputPath.c_str()); |
143 if (!inputStream.isValid()) { | 148 if (!inputStream.isValid()) { |
144 SkDebugf("Could not open file %s\n", inputPath.c_str()); | 149 SkDebugf("Could not open file %s\n", inputPath.c_str()); |
145 return false; | 150 return false; |
146 } | 151 } |
147 | 152 |
(...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
234 fRenderer->setBBoxHierarchyType(fSavedBbhType); | 239 fRenderer->setBBoxHierarchyType(fSavedBbhType); |
235 } | 240 } |
236 } | 241 } |
237 | 242 |
238 private: | 243 private: |
239 sk_tools::PictureRenderer* fRenderer; | 244 sk_tools::PictureRenderer* fRenderer; |
240 sk_tools::PictureRenderer::BBoxHierarchyType fSavedBbhType; | 245 sk_tools::PictureRenderer::BBoxHierarchyType fSavedBbhType; |
241 }; | 246 }; |
242 } | 247 } |
243 | 248 |
| 249 /** |
| 250 * Render the SKP file(s) within inputPath, writing their bitmap images into out
putDir. |
| 251 * |
| 252 * @param inputPath path to an individual SKP file, or a directory of SKP files |
| 253 * @param outputDir if not NULL, write the image(s) generated into this director
y |
| 254 * @param renderer PictureRenderer to use to render the SKPs |
| 255 * @param jsonSummaryPtr if not NULL, add the image(s) generated to this summary |
| 256 */ |
244 static bool render_picture(const SkString& inputPath, const SkString* outputDir, | 257 static bool render_picture(const SkString& inputPath, const SkString* outputDir, |
245 sk_tools::PictureRenderer& renderer) { | 258 sk_tools::PictureRenderer& renderer, |
| 259 sk_tools::ImageResultsSummary *jsonSummaryPtr) { |
246 int diffs[256] = {0}; | 260 int diffs[256] = {0}; |
247 SkBitmap* bitmap = NULL; | 261 SkBitmap* bitmap = NULL; |
248 bool success = render_picture(inputPath, | 262 renderer.setJsonSummaryPtr(jsonSummaryPtr); |
| 263 bool success = render_picture_internal(inputPath, |
249 FLAGS_writeWholeImage ? NULL : outputDir, | 264 FLAGS_writeWholeImage ? NULL : outputDir, |
250 renderer, | 265 renderer, |
251 FLAGS_validate || FLAGS_writeWholeImage ? &bitmap : NULL); | 266 FLAGS_validate || FLAGS_writeWholeImage ? &bitmap : NULL); |
252 | 267 |
253 if (!success || ((FLAGS_validate || FLAGS_writeWholeImage) && bitmap == NULL
)) { | 268 if (!success || ((FLAGS_validate || FLAGS_writeWholeImage) && bitmap == NULL
)) { |
254 SkDebugf("Failed to draw the picture.\n"); | 269 SkDebugf("Failed to draw the picture.\n"); |
255 SkDELETE(bitmap); | 270 SkDELETE(bitmap); |
256 return false; | 271 return false; |
257 } | 272 } |
258 | 273 |
259 if (FLAGS_validate) { | 274 if (FLAGS_validate) { |
260 SkBitmap* referenceBitmap = NULL; | 275 SkBitmap* referenceBitmap = NULL; |
261 sk_tools::PictureRenderer* referenceRenderer; | 276 sk_tools::PictureRenderer* referenceRenderer; |
262 // If the renderer uses a BBoxHierarchy, then the reference renderer | 277 // If the renderer uses a BBoxHierarchy, then the reference renderer |
263 // will be the same renderer, without the bbh. | 278 // will be the same renderer, without the bbh. |
264 AutoRestoreBbhType arbbh; | 279 AutoRestoreBbhType arbbh; |
265 if (sk_tools::PictureRenderer::kNone_BBoxHierarchyType != | 280 if (sk_tools::PictureRenderer::kNone_BBoxHierarchyType != |
266 renderer.getBBoxHierarchyType()) { | 281 renderer.getBBoxHierarchyType()) { |
267 referenceRenderer = &renderer; | 282 referenceRenderer = &renderer; |
268 referenceRenderer->ref(); // to match auto unref below | 283 referenceRenderer->ref(); // to match auto unref below |
269 arbbh.set(referenceRenderer, sk_tools::PictureRenderer::kNone_BBoxHi
erarchyType); | 284 arbbh.set(referenceRenderer, sk_tools::PictureRenderer::kNone_BBoxHi
erarchyType); |
270 } else { | 285 } else { |
271 referenceRenderer = SkNEW(sk_tools::SimplePictureRenderer); | 286 referenceRenderer = SkNEW(sk_tools::SimplePictureRenderer); |
272 } | 287 } |
273 SkAutoTUnref<sk_tools::PictureRenderer> aurReferenceRenderer(referenceRe
nderer); | 288 SkAutoTUnref<sk_tools::PictureRenderer> aurReferenceRenderer(referenceRe
nderer); |
274 | 289 |
275 success = render_picture(inputPath, NULL, *referenceRenderer, | 290 success = render_picture_internal(inputPath, NULL, *referenceRenderer, |
276 &referenceBitmap); | 291 &referenceBitmap); |
277 | 292 |
278 if (!success || NULL == referenceBitmap || NULL == referenceBitmap->getP
ixels()) { | 293 if (!success || NULL == referenceBitmap || NULL == referenceBitmap->getP
ixels()) { |
279 SkDebugf("Failed to draw the reference picture.\n"); | 294 SkDebugf("Failed to draw the reference picture.\n"); |
280 SkDELETE(bitmap); | 295 SkDELETE(bitmap); |
281 SkDELETE(referenceBitmap); | 296 SkDELETE(referenceBitmap); |
282 return false; | 297 return false; |
283 } | 298 } |
284 | 299 |
285 if (success && (bitmap->width() != referenceBitmap->width())) { | 300 if (success && (bitmap->width() != referenceBitmap->width())) { |
286 SkDebugf("Expected image width: %i, actual image width %i.\n", | 301 SkDebugf("Expected image width: %i, actual image width %i.\n", |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
320 | 335 |
321 for (int i = 1; i <= 255; ++i) { | 336 for (int i = 1; i <= 255; ++i) { |
322 if(diffs[i] > 0) { | 337 if(diffs[i] > 0) { |
323 SkDebugf("Number of pixels with max diff of %i is %i\n", i, diff
s[i]); | 338 SkDebugf("Number of pixels with max diff of %i is %i\n", i, diff
s[i]); |
324 } | 339 } |
325 } | 340 } |
326 } | 341 } |
327 | 342 |
328 if (FLAGS_writeWholeImage) { | 343 if (FLAGS_writeWholeImage) { |
329 sk_tools::force_all_opaque(*bitmap); | 344 sk_tools::force_all_opaque(*bitmap); |
330 if (NULL != outputDir && FLAGS_writeWholeImage) { | 345 |
| 346 if (NULL != jsonSummaryPtr) { |
| 347 // EPOGER: This is a hacky way of constructing the filename associat
ed with the |
| 348 // image checksum; we basically are repeating the logic of make_outp
ut_filepath() |
| 349 // and code below here, within here. |
| 350 // It would be better for the filename (without outputDir) to be pas
sed in here, |
| 351 // and used both for the checksum file and writing into outputDir. |
| 352 // |
| 353 // EPOGER: what about including the config type within hashFilename?
That way, |
| 354 // we could combine results of different config types without confli
cting filenames. |
| 355 SkString hashFilename; |
| 356 sk_tools::get_basename(&hashFilename, inputPath); |
| 357 hashFilename.remove(hashFilename.size() - 4, 4); // Remove ".skp" |
| 358 hashFilename.append(".png"); |
| 359 jsonSummaryPtr->add(hashFilename.c_str(), *bitmap); |
| 360 } |
| 361 |
| 362 if (NULL != outputDir) { |
331 SkString inputFilename; | 363 SkString inputFilename; |
332 sk_tools::get_basename(&inputFilename, inputPath); | 364 sk_tools::get_basename(&inputFilename, inputPath); |
333 SkString outputPath; | 365 SkString outputPath; |
334 make_output_filepath(&outputPath, *outputDir, inputFilename); | 366 make_output_filepath(&outputPath, *outputDir, inputFilename); |
335 outputPath.append(".png"); | 367 outputPath.append(".png"); |
336 if (!SkImageEncoder::EncodeFile(outputPath.c_str(), *bitmap, | 368 if (!SkImageEncoder::EncodeFile(outputPath.c_str(), *bitmap, |
337 SkImageEncoder::kPNG_Type, 100)) { | 369 SkImageEncoder::kPNG_Type, 100)) { |
338 SkDebugf("Failed to draw the picture.\n"); | 370 SkDebugf("Failed to draw the picture.\n"); |
339 success = false; | 371 success = false; |
340 } | 372 } |
341 } | 373 } |
342 } | 374 } |
343 SkDELETE(bitmap); | 375 SkDELETE(bitmap); |
344 | 376 |
345 return success; | 377 return success; |
346 } | 378 } |
347 | 379 |
348 | 380 |
349 static int process_input(const char* input, const SkString* outputDir, | 381 static int process_input(const char* input, const SkString* outputDir, |
350 sk_tools::PictureRenderer& renderer) { | 382 sk_tools::PictureRenderer& renderer, |
| 383 sk_tools::ImageResultsSummary *jsonSummaryPtr) { |
351 SkOSFile::Iter iter(input, "skp"); | 384 SkOSFile::Iter iter(input, "skp"); |
352 SkString inputFilename; | 385 SkString inputFilename; |
353 int failures = 0; | 386 int failures = 0; |
354 SkDebugf("process_input, %s\n", input); | 387 SkDebugf("process_input, %s\n", input); |
355 if (iter.next(&inputFilename)) { | 388 if (iter.next(&inputFilename)) { |
356 do { | 389 do { |
357 SkString inputPath; | 390 SkString inputPath; |
358 SkString inputAsSkString(input); | 391 SkString inputAsSkString(input); |
359 sk_tools::make_filepath(&inputPath, inputAsSkString, inputFilename); | 392 sk_tools::make_filepath(&inputPath, inputAsSkString, inputFilename); |
360 if (!render_picture(inputPath, outputDir, renderer)) { | 393 if (!render_picture(inputPath, outputDir, renderer, jsonSummaryPtr))
{ |
361 ++failures; | 394 ++failures; |
362 } | 395 } |
363 } while(iter.next(&inputFilename)); | 396 } while(iter.next(&inputFilename)); |
364 } else if (SkStrEndsWith(input, ".skp")) { | 397 } else if (SkStrEndsWith(input, ".skp")) { |
365 SkString inputPath(input); | 398 SkString inputPath(input); |
366 if (!render_picture(inputPath, outputDir, renderer)) { | 399 if (!render_picture(inputPath, outputDir, renderer, jsonSummaryPtr)) { |
367 ++failures; | 400 ++failures; |
368 } | 401 } |
369 } else { | 402 } else { |
370 SkString warning; | 403 SkString warning; |
371 warning.printf("Warning: skipping %s\n", input); | 404 warning.printf("Warning: skipping %s\n", input); |
372 SkDebugf(warning.c_str()); | 405 SkDebugf(warning.c_str()); |
373 } | 406 } |
374 return failures; | 407 return failures; |
375 } | 408 } |
376 | 409 |
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
420 if (renderer.get() == NULL) { | 453 if (renderer.get() == NULL) { |
421 exit(-1); | 454 exit(-1); |
422 } | 455 } |
423 | 456 |
424 SkAutoGraphics ag; | 457 SkAutoGraphics ag; |
425 | 458 |
426 SkString outputDir; | 459 SkString outputDir; |
427 if (FLAGS_writePath.count() == 1) { | 460 if (FLAGS_writePath.count() == 1) { |
428 outputDir.set(FLAGS_writePath[0]); | 461 outputDir.set(FLAGS_writePath[0]); |
429 } | 462 } |
| 463 sk_tools::ImageResultsSummary jsonSummary; |
| 464 sk_tools::ImageResultsSummary* jsonSummaryPtr = NULL; |
| 465 if (FLAGS_writeJsonSummaryPath.count() == 1) { |
| 466 jsonSummaryPtr = &jsonSummary; |
| 467 } |
430 | 468 |
431 int failures = 0; | 469 int failures = 0; |
432 for (int i = 0; i < FLAGS_readPath.count(); i ++) { | 470 for (int i = 0; i < FLAGS_readPath.count(); i ++) { |
433 failures += process_input(FLAGS_readPath[i], &outputDir, *renderer.get()
); | 471 failures += process_input(FLAGS_readPath[i], &outputDir, *renderer.get()
, jsonSummaryPtr); |
434 } | 472 } |
435 if (failures != 0) { | 473 if (failures != 0) { |
436 SkDebugf("Failed to render %i pictures.\n", failures); | 474 SkDebugf("Failed to render %i pictures.\n", failures); |
437 return 1; | 475 return 1; |
438 } | 476 } |
439 #if SK_SUPPORT_GPU | 477 #if SK_SUPPORT_GPU |
440 #if GR_CACHE_STATS | 478 #if GR_CACHE_STATS |
441 if (renderer->isUsingGpuDevice()) { | 479 if (renderer->isUsingGpuDevice()) { |
442 GrContext* ctx = renderer->getGrContext(); | 480 GrContext* ctx = renderer->getGrContext(); |
443 ctx->printCacheStats(); | 481 ctx->printCacheStats(); |
444 #ifdef SK_DEVELOPER | 482 #ifdef SK_DEVELOPER |
445 ctx->dumpFontCache(); | 483 ctx->dumpFontCache(); |
446 #endif | 484 #endif |
447 } | 485 } |
448 #endif | 486 #endif |
449 #endif | 487 #endif |
| 488 if (FLAGS_writeJsonSummaryPath.count() == 1) { |
| 489 jsonSummary.writeToFile(FLAGS_writeJsonSummaryPath[0]); |
| 490 } |
450 return 0; | 491 return 0; |
451 } | 492 } |
452 | 493 |
453 #if !defined SK_BUILD_FOR_IOS | 494 #if !defined SK_BUILD_FOR_IOS |
454 int main(int argc, char * const argv[]) { | 495 int main(int argc, char * const argv[]) { |
455 return tool_main(argc, (char**) argv); | 496 return tool_main(argc, (char**) argv); |
456 } | 497 } |
457 #endif | 498 #endif |
OLD | NEW |