18a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com/* 2ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * Copyright 2014 Google Inc. 38a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com * 4ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * Use of this source code is governed by a BSD-style license that can be 5ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * found in the LICENSE file. 68a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com */ 78a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 88a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkCommandLineFlags.h" 98a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkPicture.h" 108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkPictureData.h" 118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkPictureCommon.h" 128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkStream.h" 138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkFontDescriptor.h" 14fab44db294846ff05d837b9cf0bf97a073891da7bungeman@google.com 15ef3fcd877aa78c1d0ac802043cd8785180304c12bsalomonDEFINE_string2(input, i, "", "skp on which to report"); 168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comDEFINE_bool2(version, v, true, "version"); 1795cc012ccaea20f372893ae277ea0a8a6339d094mtkleinDEFINE_bool2(cullRect, c, true, "cullRect"); 1895cc012ccaea20f372893ae277ea0a8a6339d094mtkleinDEFINE_bool2(flags, f, true, "flags"); 1995cc012ccaea20f372893ae277ea0a8a6339d094mtkleinDEFINE_bool2(tags, t, true, "tags"); 2095cc012ccaea20f372893ae277ea0a8a6339d094mtkleinDEFINE_bool2(quiet, q, false, "quiet"); 2195cc012ccaea20f372893ae277ea0a8a6339d094mtklein 2295cc012ccaea20f372893ae277ea0a8a6339d094mtklein// This tool can print simple information about an SKP but its main use 238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com// is just to check if an SKP has been truncated during the recording 248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com// process. 258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com// return codes: 269aa8b32233702b19b97bebdc2c702e0c53407d45reed@android.comstatic const int kSuccess = 0; 279aa8b32233702b19b97bebdc2c702e0c53407d45reed@android.comstatic const int kTruncatedFile = 1; 289aa8b32233702b19b97bebdc2c702e0c53407d45reed@android.comstatic const int kNotAnSKP = 2; 299aa8b32233702b19b97bebdc2c702e0c53407d45reed@android.comstatic const int kInvalidTag = 3; 309aa8b32233702b19b97bebdc2c702e0c53407d45reed@android.comstatic const int kMissingInput = 4; 319aa8b32233702b19b97bebdc2c702e0c53407d45reed@android.comstatic const int kIOError = 5; 328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comint main(int argc, char** argv) { 348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkCommandLineFlags::SetUsage("Prints information about an skp file"); 358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkCommandLineFlags::Parse(argc, argv); 368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (FLAGS_input.count() != 1) { 388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (!FLAGS_quiet) { 39de916c8ac866378cee9af2bf161c79f528d9ccd5reed@google.com SkDebugf("Missing input file\n"); 408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return kMissingInput; 428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 44de916c8ac866378cee9af2bf161c79f528d9ccd5reed@google.com SkFILEStream stream(FLAGS_input[0]); 458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (!stream.isValid()) { 468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (!FLAGS_quiet) { 478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkDebugf("Couldn't open file\n"); 488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return kIOError; 508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 52519f9677a41239808f41a7c13ef1f6e05eb1ed50mtklein@google.com size_t totStreamSize = stream.getLength(); 538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkPictInfo info; 557ffb1b21abcc7bbed5a0fc711f6dd7b9dbb4f577ctguil@chromium.org if (!SkPicture_StreamIsSKP(&stream, &info)) { 568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return kNotAnSKP; 578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 58de916c8ac866378cee9af2bf161c79f528d9ccd5reed@google.com 598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (FLAGS_version && !FLAGS_quiet) { 608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkDebugf("Version: %d\n", info.getVersion()); 618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 62de916c8ac866378cee9af2bf161c79f528d9ccd5reed@google.com if (FLAGS_cullRect && !FLAGS_quiet) { 638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkDebugf("Cull Rect: %f,%f,%f,%f\n", 648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com info.fCullRect.fLeft, info.fCullRect.fTop, 65de916c8ac866378cee9af2bf161c79f528d9ccd5reed@google.com info.fCullRect.fRight, info.fCullRect.fBottom); 668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 67519f9677a41239808f41a7c13ef1f6e05eb1ed50mtklein@google.com 68519f9677a41239808f41a7c13ef1f6e05eb1ed50mtklein@google.com if (!stream.readBool()) { 69519f9677a41239808f41a7c13ef1f6e05eb1ed50mtklein@google.com // If we read true there's a picture playback object flattened 70519f9677a41239808f41a7c13ef1f6e05eb1ed50mtklein@google.com // in the file; if false, there isn't a playback, so we're done 71519f9677a41239808f41a7c13ef1f6e05eb1ed50mtklein@google.com // reading the file. 72519f9677a41239808f41a7c13ef1f6e05eb1ed50mtklein@google.com return kSuccess; 73519f9677a41239808f41a7c13ef1f6e05eb1ed50mtklein@google.com } 74519f9677a41239808f41a7c13ef1f6e05eb1ed50mtklein@google.com 754516f4786f5dda1b86a8f825b9e8e910d9c2363creed@android.com for (;;) { 764516f4786f5dda1b86a8f825b9e8e910d9c2363creed@android.com uint32_t tag = stream.readU32(); 774516f4786f5dda1b86a8f825b9e8e910d9c2363creed@android.com if (SK_PICT_EOF_TAG == tag) { 784516f4786f5dda1b86a8f825b9e8e910d9c2363creed@android.com break; 794516f4786f5dda1b86a8f825b9e8e910d9c2363creed@android.com } 80bdf736133b513bb13f7c66e01c8c37ac526ce8d4reed@google.com 81bdf736133b513bb13f7c66e01c8c37ac526ce8d4reed@google.com uint32_t chunkSize = stream.readU32(); 8236352bf5e38f45a70ee4f4fc132a38048d38206dmtklein size_t curPos = stream.getPosition(); 83bdf736133b513bb13f7c66e01c8c37ac526ce8d4reed@google.com 84bdf736133b513bb13f7c66e01c8c37ac526ce8d4reed@google.com // "move" doesn't error out when seeking beyond the end of file 85bdf736133b513bb13f7c66e01c8c37ac526ce8d4reed@google.com // so we need a preemptive check here. 86bdf736133b513bb13f7c66e01c8c37ac526ce8d4reed@google.com if (curPos+chunkSize > totStreamSize) { 87bdf736133b513bb13f7c66e01c8c37ac526ce8d4reed@google.com if (!FLAGS_quiet) { 88bdf736133b513bb13f7c66e01c8c37ac526ce8d4reed@google.com SkDebugf("truncated file\n"); 89bdf736133b513bb13f7c66e01c8c37ac526ce8d4reed@google.com } 90bdf736133b513bb13f7c66e01c8c37ac526ce8d4reed@google.com return kTruncatedFile; 91bdf736133b513bb13f7c66e01c8c37ac526ce8d4reed@google.com } 92bdf736133b513bb13f7c66e01c8c37ac526ce8d4reed@google.com 93bdf736133b513bb13f7c66e01c8c37ac526ce8d4reed@google.com // Not all the tags store the chunk size (in bytes). Three 94bdf736133b513bb13f7c66e01c8c37ac526ce8d4reed@google.com // of them store tag-specific size information (e.g., number of 958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // fonts) instead. This forces us to early exit when those 968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // chunks are encountered. 978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com switch (tag) { 988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com case SK_PICT_READER_TAG: 99c4ade57cd4ce5083e0fac19111a6ee6e32e18df4george if (FLAGS_tags && !FLAGS_quiet) { 1008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkDebugf("SK_PICT_READER_TAG %d\n", chunkSize); 1018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 1028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com break; 10345d1d1d9a71253e0ed28ba87f5f946b5845f1d6dcommit-bot@chromium.org case SK_PICT_FACTORY_TAG: 1040c00f21fee3f5cfa3aa7e5d46ff94cb8cf340451tomhudson@google.com if (FLAGS_tags && !FLAGS_quiet) { 1058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkDebugf("SK_PICT_FACTORY_TAG %d\n", chunkSize); 1068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 1078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com break; 1088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com case SK_PICT_TYPEFACE_TAG: { 1098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (FLAGS_tags && !FLAGS_quiet) { 1108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkDebugf("SK_PICT_TYPEFACE_TAG %d\n", chunkSize); 1118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 1128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1130c00f21fee3f5cfa3aa7e5d46ff94cb8cf340451tomhudson@google.com const int count = SkToInt(chunkSize); 1148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com for (int i = 0; i < count; i++) { 1158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkFontDescriptor desc; 1168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (!SkFontDescriptor::Deserialize(&stream, &desc)) { 1178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (!FLAGS_quiet) { 1188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkDebugf("File corruption in SkFontDescriptor\n"); 1198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 1208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return kInvalidTag; 1218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 1228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 12345d1d1d9a71253e0ed28ba87f5f946b5845f1d6dcommit-bot@chromium.org 12488cb22b6b4816c7a9ca6c5b795965b4606f9eb7bcommit-bot@chromium.org // clear this since we've consumed all the typefaces 125b59161f0000eb4aca3dcef29f27ffd0fb5a568e5mtklein chunkSize = 0; 126b59161f0000eb4aca3dcef29f27ffd0fb5a568e5mtklein break; 127b59161f0000eb4aca3dcef29f27ffd0fb5a568e5mtklein } 128b59161f0000eb4aca3dcef29f27ffd0fb5a568e5mtklein case SK_PICT_PICTURE_TAG: 129b59161f0000eb4aca3dcef29f27ffd0fb5a568e5mtklein if (FLAGS_tags && !FLAGS_quiet) { 13076f9e938df0b5826fd4c80b854ceafaf385cfbe1robertphillips@google.com SkDebugf("SK_PICT_PICTURE_TAG %d\n", chunkSize); 13176f9e938df0b5826fd4c80b854ceafaf385cfbe1robertphillips@google.com SkDebugf("Exiting early due to format limitations\n"); 13276f9e938df0b5826fd4c80b854ceafaf385cfbe1robertphillips@google.com } 13376f9e938df0b5826fd4c80b854ceafaf385cfbe1robertphillips@google.com return kSuccess; // TODO: need to store size in bytes 1340f10f7bf1fb43ca6346dc220a076773b1f19a367commit-bot@chromium.org break; 1350f10f7bf1fb43ca6346dc220a076773b1f19a367commit-bot@chromium.org case SK_PICT_BUFFER_SIZE_TAG: 1360f10f7bf1fb43ca6346dc220a076773b1f19a367commit-bot@chromium.org if (FLAGS_tags && !FLAGS_quiet) { 137bc3d92a7d84b56eb235d6c2d9b7de00625200713skia.committer@gmail.com SkDebugf("SK_PICT_BUFFER_SIZE_TAG %d\n", chunkSize); 138bc3d92a7d84b56eb235d6c2d9b7de00625200713skia.committer@gmail.com } 1390f10f7bf1fb43ca6346dc220a076773b1f19a367commit-bot@chromium.org break; 1400f10f7bf1fb43ca6346dc220a076773b1f19a367commit-bot@chromium.org default: 1410f10f7bf1fb43ca6346dc220a076773b1f19a367commit-bot@chromium.org if (!FLAGS_quiet) { 1420f10f7bf1fb43ca6346dc220a076773b1f19a367commit-bot@chromium.org SkDebugf("Unknown tag %d\n", chunkSize); 1430f10f7bf1fb43ca6346dc220a076773b1f19a367commit-bot@chromium.org } 1440f10f7bf1fb43ca6346dc220a076773b1f19a367commit-bot@chromium.org return kInvalidTag; 1450f10f7bf1fb43ca6346dc220a076773b1f19a367commit-bot@chromium.org } 1460f10f7bf1fb43ca6346dc220a076773b1f19a367commit-bot@chromium.org 14736352bf5e38f45a70ee4f4fc132a38048d38206dmtklein if (!stream.move(chunkSize)) { 14876f9e938df0b5826fd4c80b854ceafaf385cfbe1robertphillips@google.com if (!FLAGS_quiet) { 14976f9e938df0b5826fd4c80b854ceafaf385cfbe1robertphillips@google.com SkDebugf("seek error\n"); 15028be72b63e457c680c192a34fb9f58e1c693363fvandebo@chromium.org } 15128be72b63e457c680c192a34fb9f58e1c693363fvandebo@chromium.org return kTruncatedFile; 15228be72b63e457c680c192a34fb9f58e1c693363fvandebo@chromium.org } 15328be72b63e457c680c192a34fb9f58e1c693363fvandebo@chromium.org } 154562b2e67a29f24db4c258aa2fa59cd7b4ee15174bungeman@google.com 155562b2e67a29f24db4c258aa2fa59cd7b4ee15174bungeman@google.com return kSuccess; 1569c28fa5579734129f1bad026b8b6aea3bf76da5fbungeman@google.com} 1579c28fa5579734129f1bad026b8b6aea3bf76da5fbungeman@google.com