1 /* Copyright 2014 Google Inc. All Rights Reserved.
2 
3    Distributed under MIT license.
4    See file LICENSE for detail or copy at https://opensource.org/licenses/MIT
5 */
6 
7 /* A commandline tool for dumping info about a woff2 file. */
8 
9 #include <string>
10 
11 #include "file.h"
12 #include "./woff2_common.h"
13 #include "./buffer.h"
14 #include "./font.h"
15 #include "./table_tags.h"
16 #include "./variable_length.h"
17 
PrintTag(int tag)18 std::string PrintTag(int tag) {
19   if (tag & 0x80808080) {
20     return std::string("_xfm");  // print _xfm for xform tables (else garbage)
21   }
22   char printable[] = {
23     static_cast<char>((tag >> 24) & 0xFF),
24     static_cast<char>((tag >> 16) & 0xFF),
25     static_cast<char>((tag >> 8) & 0xFF),
26     static_cast<char>(tag & 0xFF)
27   };
28   return std::string(printable, 4);
29 }
30 
main(int argc,char ** argv)31 int main(int argc, char **argv) {
32   using std::string;
33 
34   if (argc != 2) {
35     fprintf(stderr, "One argument, the input filename, must be provided.\n");
36     return 1;
37   }
38 
39   string filename(argv[1]);
40   string outfilename = filename.substr(0, filename.find_last_of(".")) + ".woff2";
41   fprintf(stdout, "Processing %s => %s\n",
42     filename.c_str(), outfilename.c_str());
43   string input = woff2::GetFileContent(filename);
44 
45   woff2::Buffer file(reinterpret_cast<const uint8_t*>(input.data()),
46     input.size());
47 
48   printf("WOFF2Header\n");
49   uint32_t signature, flavor, length, totalSfntSize, totalCompressedSize;
50   uint32_t metaOffset, metaLength, metaOrigLength, privOffset, privLength;
51   uint16_t num_tables, reserved, major, minor;
52   if (!file.ReadU32(&signature)) return 1;
53   if (!file.ReadU32(&flavor)) return 1;
54   if (!file.ReadU32(&length)) return 1;
55   if (!file.ReadU16(&num_tables)) return 1;
56   if (!file.ReadU16(&reserved)) return 1;
57   if (!file.ReadU32(&totalSfntSize)) return 1;
58   if (!file.ReadU32(&totalCompressedSize)) return 1;
59   if (!file.ReadU16(&major)) return 1;
60   if (!file.ReadU16(&minor)) return 1;
61   if (!file.ReadU32(&metaOffset)) return 1;
62   if (!file.ReadU32(&metaLength)) return 1;
63   if (!file.ReadU32(&metaOrigLength)) return 1;
64   if (!file.ReadU32(&privOffset)) return 1;
65   if (!file.ReadU32(&privLength)) return 1;
66 
67   if (signature != 0x774F4632) {
68     printf("Invalid signature: %08x\n", signature);
69     return 1;
70   }
71   printf("signature           0x%08x\n", signature);
72   printf("flavor              0x%08x\n", flavor);
73   printf("length              %d\n", length);
74   printf("numTables           %d\n", num_tables);
75   printf("reserved            %d\n", reserved);
76   printf("totalSfntSize       %d\n", totalSfntSize);
77   printf("totalCompressedSize %d\n", totalCompressedSize);
78   printf("majorVersion        %d\n", major);
79   printf("minorVersion        %d\n", minor);
80   printf("metaOffset          %d\n", metaOffset);
81   printf("metaLength          %d\n", metaLength);
82   printf("metaOrigLength      %d\n", metaOrigLength);
83   printf("privOffset          %d\n", privOffset);
84   printf("privLength          %d\n", privLength);
85 
86   std::vector<uint32_t> table_tags;
87   printf("TableDirectory starts at +%zu\n", file.offset());
88   printf("Entry offset flags tag  origLength txLength\n");
89   for (auto i = 0; i < num_tables; i++) {
90     size_t offset = file.offset();
91     uint8_t flags;
92     uint32_t tag, origLength, transformLength;
93     if (!file.ReadU8(&flags)) return 1;
94     if ((flags & 0x3f) == 0x3f) {
95       if (!file.ReadU32(&tag)) return 1;
96     } else {
97       tag = woff2::kKnownTags[flags & 0x3f];
98     }
99     table_tags.push_back(tag);
100     if (!ReadBase128(&file, &origLength)) return 1;
101 
102     printf("%5d %6zu  0x%02x %s %10d", i, offset, flags,
103         PrintTag(tag).c_str(), origLength);
104 
105     uint8_t xform_version = (flags >> 6) & 0x3;
106     if (tag == woff2::kGlyfTableTag || tag == woff2::kLocaTableTag) {
107       if (xform_version == 0) {
108         if (!ReadBase128(&file, &transformLength)) return 1;
109         printf(" %8d", transformLength);
110       }
111     } else if (xform_version > 0) {
112       if (!ReadBase128(&file, &transformLength)) return 1;
113       printf(" %8d", transformLength);
114     }
115     printf("\n");
116   }
117 
118   // Collection header
119   if (flavor == woff2::kTtcFontFlavor) {
120     uint32_t version, numFonts;
121     if (!file.ReadU32(&version)) return 1;
122     if (!woff2::Read255UShort(&file, &numFonts)) return 1;
123     printf("CollectionHeader 0x%08x %d fonts\n", version, numFonts);
124 
125     for (auto i = 0; i < numFonts; i++) {
126       uint32_t numTables, flavor;
127       if (!woff2::Read255UShort(&file, &numTables)) return 1;
128       if (!file.ReadU32(&flavor)) return 1;
129       printf("CollectionFontEntry %d flavor 0x%08x %d tables\n", i, flavor,
130           numTables);
131       for (auto j = 0; j < numTables; j++) {
132         uint32_t table_idx;
133         if (!woff2::Read255UShort(&file, &table_idx)) return 1;
134         if (table_idx >= table_tags.size()) return 1;
135         printf("  %d %s (idx %d)\n", j,
136             PrintTag(table_tags[table_idx]).c_str(), table_idx);
137       }
138     }
139   }
140 
141   printf("TableDirectory ends at +%zu\n", file.offset());
142 
143   return 0;
144 }
145