/* Copyright 2014 Google Inc. All Rights Reserved. Distributed under MIT license. See file LICENSE for detail or copy at https://opensource.org/licenses/MIT */ /* A commandline tool for dumping info about a woff2 file. */ #include #include "file.h" #include "./woff2_common.h" #include "./buffer.h" #include "./font.h" #include "./table_tags.h" #include "./variable_length.h" std::string PrintTag(int tag) { if (tag & 0x80808080) { return std::string("_xfm"); // print _xfm for xform tables (else garbage) } char printable[] = { static_cast((tag >> 24) & 0xFF), static_cast((tag >> 16) & 0xFF), static_cast((tag >> 8) & 0xFF), static_cast(tag & 0xFF) }; return std::string(printable, 4); } int main(int argc, char **argv) { if (argc != 2) { fprintf(stderr, "One argument, the input filename, must be provided.\n"); return 1; } std::string filename(argv[1]); std::string outfilename = filename.substr(0, filename.find_last_of(".")) + ".woff2"; fprintf(stdout, "Processing %s => %s\n", filename.c_str(), outfilename.c_str()); std::string input = woff2::GetFileContent(filename); woff2::Buffer file(reinterpret_cast(input.data()), input.size()); printf("WOFF2Header\n"); uint32_t signature, flavor, length, totalSfntSize, totalCompressedSize; uint32_t metaOffset, metaLength, metaOrigLength, privOffset, privLength; uint16_t num_tables, reserved, major, minor; if (!file.ReadU32(&signature)) return 1; if (!file.ReadU32(&flavor)) return 1; if (!file.ReadU32(&length)) return 1; if (!file.ReadU16(&num_tables)) return 1; if (!file.ReadU16(&reserved)) return 1; if (!file.ReadU32(&totalSfntSize)) return 1; if (!file.ReadU32(&totalCompressedSize)) return 1; if (!file.ReadU16(&major)) return 1; if (!file.ReadU16(&minor)) return 1; if (!file.ReadU32(&metaOffset)) return 1; if (!file.ReadU32(&metaLength)) return 1; if (!file.ReadU32(&metaOrigLength)) return 1; if (!file.ReadU32(&privOffset)) return 1; if (!file.ReadU32(&privLength)) return 1; if (signature != 0x774F4632) { printf("Invalid signature: %08x\n", signature); return 1; } printf("signature 0x%08x\n", signature); printf("flavor 0x%08x\n", flavor); printf("length %d\n", length); printf("numTables %d\n", num_tables); printf("reserved %d\n", reserved); printf("totalSfntSize %d\n", totalSfntSize); printf("totalCompressedSize %d\n", totalCompressedSize); printf("majorVersion %d\n", major); printf("minorVersion %d\n", minor); printf("metaOffset %d\n", metaOffset); printf("metaLength %d\n", metaLength); printf("metaOrigLength %d\n", metaOrigLength); printf("privOffset %d\n", privOffset); printf("privLength %d\n", privLength); std::vector table_tags; printf("TableDirectory starts at +%zu\n", file.offset()); printf("Entry offset flags tag origLength txLength\n"); for (auto i = 0; i < num_tables; i++) { size_t offset = file.offset(); uint8_t flags; uint32_t tag, origLength, transformLength; if (!file.ReadU8(&flags)) return 1; if ((flags & 0x3f) == 0x3f) { if (!file.ReadU32(&tag)) return 1; } else { tag = woff2::kKnownTags[flags & 0x3f]; } table_tags.push_back(tag); if (!ReadBase128(&file, &origLength)) return 1; printf("%5d %6zu 0x%02x %s %10d", i, offset, flags, PrintTag(tag).c_str(), origLength); uint8_t xform_version = (flags >> 6) & 0x3; if (tag == woff2::kGlyfTableTag || tag == woff2::kLocaTableTag) { if (xform_version == 0) { if (!ReadBase128(&file, &transformLength)) return 1; printf(" %8d", transformLength); } } else if (xform_version > 0) { if (!ReadBase128(&file, &transformLength)) return 1; printf(" %8d", transformLength); } printf("\n"); } // Collection header if (flavor == woff2::kTtcFontFlavor) { uint32_t version, numFonts; if (!file.ReadU32(&version)) return 1; if (!woff2::Read255UShort(&file, &numFonts)) return 1; printf("CollectionHeader 0x%08x %d fonts\n", version, numFonts); for (auto i = 0; i < numFonts; i++) { uint32_t numTables, flavor; if (!woff2::Read255UShort(&file, &numTables)) return 1; if (!file.ReadU32(&flavor)) return 1; printf("CollectionFontEntry %d flavor 0x%08x %d tables\n", i, flavor, numTables); for (auto j = 0; j < numTables; j++) { uint32_t table_idx; if (!woff2::Read255UShort(&file, &table_idx)) return 1; if (table_idx >= table_tags.size()) return 1; printf(" %d %s (idx %d)\n", j, PrintTag(table_tags[table_idx]).c_str(), table_idx); } } } printf("TableDirectory ends at +%zu\n", file.offset()); return 0; }