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