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