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