1 /* 2 * Copyright 2014 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 "SkCommandLineFlags.h" 9 #include "SkPicture.h" 10 #include "SkPictureData.h" 11 #include "SkStream.h" 12 13 DEFINE_string2(input, i, "", "skp on which to report"); 14 DEFINE_bool2(version, v, true, "version"); 15 DEFINE_bool2(cullRect, c, true, "cullRect"); 16 DEFINE_bool2(flags, f, true, "flags"); 17 DEFINE_bool2(tags, t, true, "tags"); 18 DEFINE_bool2(quiet, q, false, "quiet"); 19 20 // This tool can print simple information about an SKP but its main use 21 // is just to check if an SKP has been truncated during the recording 22 // process. 23 // return codes: 24 static const int kSuccess = 0; 25 static const int kTruncatedFile = 1; 26 static const int kNotAnSKP = 2; 27 static const int kInvalidTag = 3; 28 static const int kMissingInput = 4; 29 static const int kIOError = 5; 30 31 int tool_main(int argc, char** argv); 32 int tool_main(int argc, char** argv) { 33 SkCommandLineFlags::SetUsage("Prints information about an skp file"); 34 SkCommandLineFlags::Parse(argc, argv); 35 36 if (FLAGS_input.count() != 1) { 37 if (!FLAGS_quiet) { 38 SkDebugf("Missing input file\n"); 39 } 40 return kMissingInput; 41 } 42 43 SkFILEStream stream(FLAGS_input[0]); 44 if (!stream.isValid()) { 45 if (!FLAGS_quiet) { 46 SkDebugf("Couldn't open file\n"); 47 } 48 return kIOError; 49 } 50 51 size_t totStreamSize = stream.getLength(); 52 53 SkPictInfo info; 54 if (!SkPicture::InternalOnly_StreamIsSKP(&stream, &info)) { 55 return kNotAnSKP; 56 } 57 58 if (FLAGS_version && !FLAGS_quiet) { 59 SkDebugf("Version: %d\n", info.fVersion); 60 } 61 if (FLAGS_cullRect && !FLAGS_quiet) { 62 SkDebugf("Cull Rect: %f,%f,%f,%f\n", 63 info.fCullRect.fLeft, info.fCullRect.fTop, 64 info.fCullRect.fRight, info.fCullRect.fBottom); 65 } 66 if (FLAGS_flags && !FLAGS_quiet) { 67 SkDebugf("Flags: 0x%x\n", info.fFlags); 68 } 69 70 if (!stream.readBool()) { 71 // If we read true there's a picture playback object flattened 72 // in the file; if false, there isn't a playback, so we're done 73 // reading the file. 74 return kSuccess; 75 } 76 77 for (;;) { 78 uint32_t tag = stream.readU32(); 79 if (SK_PICT_EOF_TAG == tag) { 80 break; 81 } 82 83 uint32_t chunkSize = stream.readU32(); 84 size_t curPos = stream.getPosition(); 85 86 // "move" doesn't error out when seeking beyond the end of file 87 // so we need a preemptive check here. 88 if (curPos+chunkSize > totStreamSize) { 89 if (!FLAGS_quiet) { 90 SkDebugf("truncated file\n"); 91 } 92 return kTruncatedFile; 93 } 94 95 // Not all the tags store the chunk size (in bytes). Three 96 // of them store tag-specific size information (e.g., number of 97 // fonts) instead. This forces us to early exit when those 98 // chunks are encountered. 99 switch (tag) { 100 case SK_PICT_READER_TAG: 101 if (FLAGS_tags && !FLAGS_quiet) { 102 SkDebugf("SK_PICT_READER_TAG %d\n", chunkSize); 103 } 104 break; 105 case SK_PICT_FACTORY_TAG: 106 if (FLAGS_tags && !FLAGS_quiet) { 107 SkDebugf("SK_PICT_FACTORY_TAG %d\n", chunkSize); 108 } 109 // Remove this code when v21 and below are no longer supported 110 #ifndef DISABLE_V21_COMPATIBILITY_CODE 111 if (info.fVersion < 22) { 112 if (!FLAGS_quiet) { 113 SkDebugf("Exiting early due to format limitations\n"); 114 } 115 return kSuccess; // TODO: need to store size in bytes 116 } 117 #endif 118 break; 119 case SK_PICT_TYPEFACE_TAG: 120 if (FLAGS_tags && !FLAGS_quiet) { 121 SkDebugf("SK_PICT_TYPEFACE_TAG %d\n", chunkSize); 122 SkDebugf("Exiting early due to format limitations\n"); 123 } 124 return kSuccess; // TODO: need to store size in bytes 125 break; 126 case SK_PICT_PICTURE_TAG: 127 if (FLAGS_tags && !FLAGS_quiet) { 128 SkDebugf("SK_PICT_PICTURE_TAG %d\n", chunkSize); 129 SkDebugf("Exiting early due to format limitations\n"); 130 } 131 return kSuccess; // TODO: need to store size in bytes 132 break; 133 case SK_PICT_BUFFER_SIZE_TAG: 134 if (FLAGS_tags && !FLAGS_quiet) { 135 SkDebugf("SK_PICT_BUFFER_SIZE_TAG %d\n", chunkSize); 136 } 137 break; 138 default: 139 if (!FLAGS_quiet) { 140 SkDebugf("Unknown tag %d\n", chunkSize); 141 } 142 return kInvalidTag; 143 } 144 145 if (!stream.move(chunkSize)) { 146 if (!FLAGS_quiet) { 147 SkDebugf("seek error\n"); 148 } 149 return kTruncatedFile; 150 } 151 } 152 153 return kSuccess; 154 } 155 156 #if !defined SK_BUILD_FOR_IOS 157 int main(int argc, char * const argv[]) { 158 return tool_main(argc, (char**) argv); 159 } 160 #endif 161