소스 검색

Handle var initialization. (#628)

Jon Meow 4 년 전
부모
커밋
3082d05f80

+ 13 - 5
migrate_cpp/cpp_refactoring/var_decl.cpp

@@ -116,11 +116,19 @@ void VarDecl::Run() {
       type_loc.getEndLoc(), 0, GetSourceManager(), GetLangOpts());
   llvm::StringRef comma_source_text = GetSourceText(
       clang::CharSourceRange::getCharRange(after_type_loc, decl.getLocation()));
-  bool has_comma = !comma_source_text.trim().empty();
-  clang::CharSourceRange replace_range = clang::CharSourceRange::getTokenRange(
-      has_comma ? decl.getLocation() : decl.getBeginLoc(), decl.getEndLoc());
-
-  AddReplacement(replace_range, after);
+  clang::SourceLocation replace_start = !comma_source_text.trim().empty()
+                                            ? decl.getLocation()
+                                            : decl.getBeginLoc();
+
+  // Figure out where the replacement ends and initialization begins. For
+  // example, `int i` the end is the identifier, `int i[4]` the end is the `[4]`
+  // type qualifier.
+  clang::SourceLocation identifier_end = clang::Lexer::getLocForEndOfToken(
+      decl.getLocation(), 0, GetSourceManager(), GetLangOpts());
+  clang::SourceLocation replace_end = std::max(identifier_end, after_type_loc);
+
+  AddReplacement(
+      clang::CharSourceRange::getCharRange(replace_start, replace_end), after);
 }
 
 auto VarDeclFactory::GetAstMatcher() -> cam::DeclarationMatcher {

+ 55 - 16
migrate_cpp/cpp_refactoring/var_decl_test.cpp

@@ -25,12 +25,11 @@ TEST_F(VarDeclTest, DeclarationArray) {
 
 TEST_F(VarDeclTest, DeclarationConstArray) {
   constexpr char Before[] = "const int i[] = {0, 1};";
-  constexpr char After[] = "let i: const int[];";
+  constexpr char After[] = "let i: const int[] = {0, 1};";
   ExpectReplacement(Before, After);
 }
 
 TEST_F(VarDeclTest, DeclarationConstPointer) {
-  // TODO: Include init.
   // TODO: Fix j replacement location.
   constexpr char Before[] = R"cpp(
     int i = 0;
@@ -38,9 +37,9 @@ TEST_F(VarDeclTest, DeclarationConstPointer) {
     const int* k = &i;
   )cpp";
   constexpr char After[] = R"(
-    var i: int;
-    int* const let j: int* const;
-    var k: const int*;
+    var i: int = 0;
+    int* const let j: int* const = &i;
+    var k: const int* = &i;
   )";
   ExpectReplacement(Before, After);
 }
@@ -52,6 +51,13 @@ TEST_F(VarDeclTest, DeclarationComma) {
   ExpectReplacement(Before, After);
 }
 
+TEST_F(VarDeclTest, DeclarationCommaAssignment) {
+  // TODO: Maybe replace the comma with a `;`.
+  constexpr char Before[] = "int i = 0, j = 0;";
+  constexpr char After[] = "var i: int = 0, var j: int = 0;";
+  ExpectReplacement(Before, After);
+}
+
 TEST_F(VarDeclTest, DeclarationCommaArray) {
   // TODO: Maybe replace the comma with a `;`.
   // TODO: Need to handle j's array.
@@ -60,6 +66,14 @@ TEST_F(VarDeclTest, DeclarationCommaArray) {
   ExpectReplacement(Before, After);
 }
 
+TEST_F(VarDeclTest, DeclarationCommaArrayAssignment) {
+  // TODO: Maybe replace the comma with a `;`.
+  // TODO: Need to handle j's array.
+  constexpr char Before[] = "int i[] = {0}, j[] = {1};";
+  constexpr char After[] = "var i: int[] = {0}, j[] = {1};";
+  ExpectReplacement(Before, After);
+}
+
 TEST_F(VarDeclTest, DeclarationCommaPointers) {
   // TODO: Maybe replace the comma with a `;`.
   // TODO: Need to handle j's pointer.
@@ -69,36 +83,42 @@ TEST_F(VarDeclTest, DeclarationCommaPointers) {
   ExpectReplacement(Before, After);
 }
 
+TEST_F(VarDeclTest, DeclarationCommaPointersAssignment) {
+  // TODO: Maybe replace the comma with a `;`.
+  // TODO: Need to handle j's pointer.
+  // constexpr char After[] = "var i: int *, var j: int *;";
+  constexpr char Before[] = "int *i = nullptr, *j = i;";
+  constexpr char After[] = "var i: int* = nullptr, *j = i;";
+  ExpectReplacement(Before, After);
+}
+
 TEST_F(VarDeclTest, Assignment) {
   constexpr char Before[] = "int i = 0;";
-  // TODO: Include init.
-  constexpr char After[] = "var i: int;";
+  constexpr char After[] = "var i: int = 0;";
   ExpectReplacement(Before, After);
 }
 
 TEST_F(VarDeclTest, Auto) {
   constexpr char Before[] = "auto i = 0;";
-  constexpr char After[] = "var i: auto;";
+  constexpr char After[] = "var i: auto = 0;";
   ExpectReplacement(Before, After);
 }
 
 TEST_F(VarDeclTest, AutoRef) {
-  // TODO: Include init.
   constexpr char Before[] = R"cpp(
     auto i = 0;
     const auto& j = i;
   )cpp";
   constexpr char After[] = R"(
-    var i: auto;
-    var j: const auto&;
+    var i: auto = 0;
+    var j: const auto& = i;
   )";
   ExpectReplacement(Before, After);
 }
 
 TEST_F(VarDeclTest, Const) {
-  // TODO: Include init.
   constexpr char Before[] = "const int i = 0;";
-  constexpr char After[] = "let i: const int;";
+  constexpr char After[] = "let i: const int = 0;";
   ExpectReplacement(Before, After);
 }
 
@@ -132,9 +152,8 @@ TEST_F(VarDeclTest, Params) {
 }
 
 TEST_F(VarDeclTest, ParamsDefault) {
-  // TODO: Include init.
   constexpr char Before[] = "auto Foo(int i = 0) -> int;";
-  constexpr char After[] = "auto Foo(i: int) -> int;";
+  constexpr char After[] = "auto Foo(i: int = 0) -> int;";
   ExpectReplacement(Before, After);
 }
 
@@ -172,6 +191,26 @@ TEST_F(VarDeclTest, Member) {
   ExpectReplacement(Before, Before);
 }
 
+TEST_F(VarDeclTest, Constructor) {
+  constexpr char Before[] = R"cpp(
+    struct Index {
+      Index(int i) : i(i) {}
+
+      int i;
+    };
+    Index x(0);
+  )cpp";
+  constexpr char After[] = R"(
+    struct Index {
+      Index(i: int) : i(i) {}
+
+      int i;
+    };
+    var x: Index(0);
+  )";
+  ExpectReplacement(Before, After);
+}
+
 TEST_F(VarDeclTest, RangeFor) {
   constexpr char Before[] = R"cpp(
     void Foo() {
@@ -183,7 +222,7 @@ TEST_F(VarDeclTest, RangeFor) {
   )cpp";
   constexpr char After[] = R"(
     void Foo() {
-      var items: int[];
+      var items: int[] = {1};
       for (int i : items) {
         var j: int;
       }

+ 1 - 1
third_party/examples/woff2/carbon/include/woff2/output.carbon

@@ -17,7 +17,7 @@
 namespace woff2 {
 
 // Suggested max size for output.
-let kDefaultMaxSize: const size_t;
+let kDefaultMaxSize: const size_t = 30 * 1024 * 1024;
 
 /**
  * Output interface for the woff2 decoding.

+ 1 - 1
third_party/examples/woff2/carbon/src/convert_woff2ttf_fuzzer.impl.carbon

@@ -6,7 +6,7 @@
 // Entry point for LibFuzzer.
 extern "C" fn LLVMFuzzerTestOneInput(data: const uint8_t*, size: size_t) -> int {
   var buf: std::string;
-  var out: woff2::WOFF2StringOut;
+  var out: woff2::WOFF2StringOut(&buf);
   out.SetMaxSize(30 * 1024 * 1024);
   woff2::ConvertWOFF2ToTTF(data, size, &out);
   return 0;

+ 3 - 2
third_party/examples/woff2/carbon/src/convert_woff2ttf_fuzzer_new_entry.impl.carbon

@@ -4,8 +4,9 @@
 extern "C" fn LLVMFuzzerTestOneInput(data: const uint8_t*, data_size: size_t) -> int {
   // Decode using newer entry pattern.
   // Same pattern as woff2_decompress.
-  var output: std::string;
-  var out: woff2::WOFF2StringOut;
+  var output: std::string(std::min(woff2::ComputeWOFF2FinalSize(data, data_size),
+                              woff2::kDefaultMaxSize), 0);
+  var out: woff2::WOFF2StringOut(&output);
   woff2::ConvertWOFF2ToTTF(data, data_size, &out);
   return 0;
 }

+ 2 - 2
third_party/examples/woff2/carbon/src/file.carbon

@@ -18,7 +18,7 @@ using std::string;
 
 
 fn inline GetFileContent(filename: const string&) -> string {
-  var ifs: std::ifstream;
+  var ifs: std::ifstream(filename.c_str(), std::ios::binary);
   return string(
     std::istreambuf_iterator<char>(ifs.rdbuf()),
     std::istreambuf_iterator<char>());
@@ -26,7 +26,7 @@ fn inline GetFileContent(filename: const string&) -> string {
 
 fn inline SetFileContents(filename: const string&, start: string::iterator,
     end: string::iterator) {
-  var ofs: std::ofstream;
+  var ofs: std::ofstream(filename.c_str(), std::ios::binary);
   std::copy(start, end, std::ostream_iterator<char>(ofs));
 }
 

+ 42 - 39
third_party/examples/woff2/carbon/src/font.impl.carbon

@@ -19,12 +19,12 @@
 namespace woff2 {
 
 fn Font::FindTable(tag: uint32_t) -> Font::Table* {
-  var it: auto;
+  var it: auto = tables.find(tag);
   return it == tables.end() ? nullptr : &it->second;
 }
 
 fn Font::FindTable(tag: uint32_t) const -> const Font::Table* {
-  var it: auto;
+  var it: auto = tables.find(tag);
   return it == tables.end() ? nullptr : &it->second;
 }
 
@@ -32,7 +32,7 @@ fn Font::OutputOrderedTags() const -> std::vector<uint32_t> {
   var output_order: std::vector<uint32_t>;
 
   for (const auto& i : tables) {
-    var table: const Font::Table&;
+    var table: const Font::Table& = i.second;
     // This is a transformed table, we will write it together with the
     // original version.
     if (table.tag & 0x80808080) {
@@ -42,8 +42,10 @@ fn Font::OutputOrderedTags() const -> std::vector<uint32_t> {
   }
 
   // Alphabetize then put loca immediately after glyf
-  var glyf_loc: auto;
-  var loca_loc: auto;
+  var glyf_loc: auto = std::find(output_order.begin(), output_order.end(),
+      kGlyfTableTag);
+  var loca_loc: auto = std::find(output_order.begin(), output_order.end(),
+      kLocaTableTag);
   if (glyf_loc != output_order.end() && loca_loc != output_order.end()) {
     output_order.erase(loca_loc);
     output_order.insert(std::find(output_order.begin(), output_order.end(),
@@ -63,7 +65,7 @@ fn ReadTrueTypeFont(file: Buffer*, data: const uint8_t*, len: size_t,
   }
 
   var intervals: std::map<uint32_t, uint32_t>;
-  for (var i: uint16_t; i < font->num_tables; ++i) {
+  for (var i: uint16_t = 0; i < font->num_tables; ++i) {
     var table: Font::Table;
     table.flag_byte = 0;
     table.reuse_of = nullptr;
@@ -87,7 +89,7 @@ fn ReadTrueTypeFont(file: Buffer*, data: const uint8_t*, len: size_t,
   }
 
   // Check that tables are non-overlapping.
-  var last_offset: uint32_t;
+  var last_offset: uint32_t = 12UL + 16UL * font->num_tables;
   for (const auto& i : intervals) {
     if (i.first < last_offset || i.first + i.second < i.first) {
       return FONT_COMPRESSION_FAILURE();
@@ -96,7 +98,7 @@ fn ReadTrueTypeFont(file: Buffer*, data: const uint8_t*, len: size_t,
   }
 
   // Sanity check key tables
-  var head_table: const Font::Table*;
+  var head_table: const Font::Table* = font->FindTable(kHeadTableTag);
   if (head_table != nullptr && head_table->length < 52) {
     return FONT_COMPRESSION_FAILURE();
   }
@@ -115,7 +117,7 @@ fn ReadCollectionFont(file: Buffer*, data: const uint8_t*, len: size_t,
   }
 
   for (auto& entry : font->tables) {
-    var table: Font::Table&;
+    var table: Font::Table& = entry.second;
 
     if (all_tables->find(table.offset) == all_tables->end()) {
       (*all_tables)[table.offset] = font->FindTable(table.tag);
@@ -140,7 +142,7 @@ fn ReadTrueTypeCollection(file: Buffer*, data: const uint8_t*, len: size_t,
     }
 
     var offsets: std::vector<uint32_t>;
-    for (var i: size_t; i < num_fonts; i++) {
+    for (var i: size_t = 0; i < num_fonts; i++) {
       var offset: uint32_t;
       if (!file->ReadU32(&offset)) {
         return FONT_COMPRESSION_FAILURE();
@@ -149,12 +151,12 @@ fn ReadTrueTypeCollection(file: Buffer*, data: const uint8_t*, len: size_t,
     }
 
     font_collection->fonts.resize(offsets.size());
-    var font_it: auto;
+    var font_it: auto = font_collection->fonts.begin();
 
     var all_tables: std::map<uint32_t, Font::Table*>;
     for (const auto offset : offsets) {
       file->set_offset(offset);
-      var font: Font&;
+      var font: Font& = *font_it++;
       if (!ReadCollectionFont(file, data, len, &font, &all_tables)) {
         return FONT_COMPRESSION_FAILURE();
       }
@@ -164,7 +166,7 @@ fn ReadTrueTypeCollection(file: Buffer*, data: const uint8_t*, len: size_t,
 }
 
 fn ReadFont(data: const uint8_t*, len: size_t, font: Font*) -> bool {
-  var file: Buffer;
+  var file: Buffer(data, len);
 
   if (!file.ReadU32(&font->flavor)) {
     return FONT_COMPRESSION_FAILURE();
@@ -178,7 +180,7 @@ fn ReadFont(data: const uint8_t*, len: size_t, font: Font*) -> bool {
 
 fn ReadFontCollection(data: const uint8_t*, len: size_t,
                         font_collection: FontCollection*) -> bool {
-  var file: Buffer;
+  var file: Buffer(data, len);
 
   if (!file.ReadU32(&font_collection->flavor)) {
     return FONT_COMPRESSION_FAILURE();
@@ -186,7 +188,7 @@ fn ReadFontCollection(data: const uint8_t*, len: size_t,
 
   if (font_collection->flavor != kTtcFontFlavor) {
     font_collection->fonts.resize(1);
-    var font: Font&;
+    var font: Font& = font_collection->fonts[0];
     font.flavor = font_collection->flavor;
     return ReadTrueTypeFont(&file, data, len, &font);
   }
@@ -194,18 +196,18 @@ fn ReadFontCollection(data: const uint8_t*, len: size_t,
 }
 
 fn FontFileSize(font: const Font&) -> size_t {
-  var max_offset: size_t;
+  var max_offset: size_t = 12ULL + 16ULL * font.num_tables;
   for (const auto& i : font.tables) {
-    var table: const Font::Table&;
-    var padding_size: size_t;
-    var end_offset: size_t;
+    var table: const Font::Table& = i.second;
+    var padding_size: size_t = (4 - (table.length & 3)) & 3;
+    var end_offset: size_t = (padding_size + table.offset) + table.length;
     max_offset = std::max(max_offset, end_offset);
   }
   return max_offset;
 }
 
 fn FontCollectionFileSize(font_collection: const FontCollection&) -> size_t {
-  var max_offset: size_t;
+  var max_offset: size_t = 0;
   for (auto& font : font_collection.fonts) {
     // font file size actually just finds max offset
     max_offset = std::max(max_offset, FontFileSize(font));
@@ -214,7 +216,7 @@ fn FontCollectionFileSize(font_collection: const FontCollection&) -> size_t {
 }
 
 fn WriteFont(font: const Font&, dst: uint8_t*, dst_size: size_t) -> bool {
-  var offset: size_t;
+  var offset: size_t = 0;
   return WriteFont(font, &offset, dst, dst_size);
 }
 
@@ -246,7 +248,7 @@ fn WriteTable(table: const Font::Table&, offset: size_t*, dst: uint8_t*,
       return FONT_COMPRESSION_FAILURE();
     }
     memcpy(dst + table.offset, table.data, table.length);
-    var padding_size: size_t;
+    var padding_size: size_t = (4 - (table.length & 3)) & 3;
     if (table.offset + table.length + padding_size < padding_size ||
         dst_size < table.offset + table.length + padding_size) {
       return FONT_COMPRESSION_FAILURE();
@@ -263,9 +265,9 @@ fn WriteFont(font: const Font&, offset: size_t*, dst: uint8_t*,
   }
   StoreU32(font.flavor, offset, dst);
   Store16(font.num_tables, offset, dst);
-  var max_pow2: uint16_t;
-  var search_range: uint16_t;
-  var range_shift: uint16_t;
+  var max_pow2: uint16_t = font.num_tables ? Log2Floor(font.num_tables) : 0;
+  var search_range: uint16_t = max_pow2 ? 1 << (max_pow2 + 4) : 0;
+  var range_shift: uint16_t = (font.num_tables << 4) - search_range;
   Store16(search_range, offset, dst);
   Store16(max_pow2, offset, dst);
   Store16(range_shift, offset, dst);
@@ -281,7 +283,7 @@ fn WriteFont(font: const Font&, offset: size_t*, dst: uint8_t*,
 
 fn WriteFontCollection(font_collection: const FontCollection&, dst: uint8_t*,
                          dst_size: size_t) -> bool {
-  var offset: size_t;
+  var offset: size_t = 0;
 
   // It's simpler if this just a simple sfnt
   if (font_collection.flavor != kTtcFontFlavor) {
@@ -294,8 +296,8 @@ fn WriteFontCollection(font_collection: const FontCollection&, dst: uint8_t*,
   StoreU32(font_collection.fonts.size(), &offset, dst);
 
   // Offset Table, zeroed for now
-  var offset_table: size_t;  // where to write offsets later
-  for (var i: size_t; i < font_collection.fonts.size(); i++) {
+  var offset_table: size_t = offset;  // where to write offsets later
+  for (var i: size_t = 0; i < font_collection.fonts.size(); i++) {
     StoreU32(0, &offset, dst);
   }
 
@@ -317,13 +319,13 @@ fn WriteFontCollection(font_collection: const FontCollection&, dst: uint8_t*,
 }
 
 fn NumGlyphs(font: const Font&) -> int {
-  var head_table: const Font::Table*;
-  var loca_table: const Font::Table*;
+  var head_table: const Font::Table* = font.FindTable(kHeadTableTag);
+  var loca_table: const Font::Table* = font.FindTable(kLocaTableTag);
   if (head_table == nullptr || loca_table == nullptr || head_table->length < 52) {
     return 0;
   }
-  var index_fmt: int;
-  var loca_record_size: int;
+  var index_fmt: int = IndexFormat(font);
+  var loca_record_size: int = (index_fmt == 0 ? 2 : 4);
   if (loca_table->length < loca_record_size) {
     return 0;
   }
@@ -331,7 +333,7 @@ fn NumGlyphs(font: const Font&) -> int {
 }
 
 fn IndexFormat(font: const Font&) -> int {
-  var head_table: const Font::Table*;
+  var head_table: const Font::Table* = font.FindTable(kHeadTableTag);
   if (head_table == nullptr) {
     return 0;
   }
@@ -347,17 +349,17 @@ fn GetGlyphData(font: const Font&, glyph_index: int,
   if (glyph_index < 0) {
     return FONT_COMPRESSION_FAILURE();
   }
-  var head_table: const Font::Table*;
-  var loca_table: const Font::Table*;
-  var glyf_table: const Font::Table*;
+  var head_table: const Font::Table* = font.FindTable(kHeadTableTag);
+  var loca_table: const Font::Table* = font.FindTable(kLocaTableTag);
+  var glyf_table: const Font::Table* = font.FindTable(kGlyfTableTag);
   if (head_table == nullptr || loca_table == nullptr || glyf_table == nullptr ||
       head_table->length < 52) {
     return FONT_COMPRESSION_FAILURE();
   }
 
-  var index_fmt: int;
+  var index_fmt: int = IndexFormat(font);
 
-  var loca_buf: Buffer;
+  var loca_buf: Buffer(loca_table->data, loca_table->length);
   if (index_fmt == 0) {
     var offset1: uint16_t, var offset2: uint16_t;
     if (!loca_buf.Skip(2 * glyph_index) ||
@@ -385,7 +387,8 @@ fn GetGlyphData(font: const Font&, glyph_index: int,
 }
 
 fn RemoveDigitalSignature(font: Font*) -> bool {
-  var it: auto;
+  var it: auto =
+      font->tables.find(kDsigTableTag);
   if (it != font->tables.end()) {
     font->tables.erase(it);
     font->num_tables = font->tables.size();

+ 51 - 51
third_party/examples/woff2/carbon/src/glyph.impl.carbon

@@ -15,30 +15,30 @@
 
 namespace woff2 {
 
-let kFLAG_ONCURVE: const int32_t;
-let kFLAG_XSHORT: const int32_t;
-let kFLAG_YSHORT: const int32_t;
-let kFLAG_REPEAT: const int32_t;
-let kFLAG_XREPEATSIGN: const int32_t;
-let kFLAG_YREPEATSIGN: const int32_t;
-let kFLAG_ARG_1_AND_2_ARE_WORDS: const int32_t;
-let kFLAG_WE_HAVE_A_SCALE: const int32_t;
-let kFLAG_MORE_COMPONENTS: const int32_t;
-let kFLAG_WE_HAVE_AN_X_AND_Y_SCALE: const int32_t;
-let kFLAG_WE_HAVE_A_TWO_BY_TWO: const int32_t;
-let kFLAG_WE_HAVE_INSTRUCTIONS: const int32_t;
+let kFLAG_ONCURVE: const int32_t = 1;
+let kFLAG_XSHORT: const int32_t = 1 << 1;
+let kFLAG_YSHORT: const int32_t = 1 << 2;
+let kFLAG_REPEAT: const int32_t = 1 << 3;
+let kFLAG_XREPEATSIGN: const int32_t = 1 << 4;
+let kFLAG_YREPEATSIGN: const int32_t = 1 << 5;
+let kFLAG_ARG_1_AND_2_ARE_WORDS: const int32_t = 1 << 0;
+let kFLAG_WE_HAVE_A_SCALE: const int32_t = 1 << 3;
+let kFLAG_MORE_COMPONENTS: const int32_t = 1 << 5;
+let kFLAG_WE_HAVE_AN_X_AND_Y_SCALE: const int32_t = 1 << 6;
+let kFLAG_WE_HAVE_A_TWO_BY_TWO: const int32_t = 1 << 7;
+let kFLAG_WE_HAVE_INSTRUCTIONS: const int32_t = 1 << 8;
 
 fn ReadCompositeGlyphData(buffer: Buffer*, glyph: Glyph*) -> bool {
   glyph->have_instructions = false;
   glyph->composite_data = buffer->buffer() + buffer->offset();
-  var start_offset: size_t;
-  var flags: uint16_t;
+  var start_offset: size_t = buffer->offset();
+  var flags: uint16_t = kFLAG_MORE_COMPONENTS;
   while (flags & kFLAG_MORE_COMPONENTS) {
     if (!buffer->ReadU16(&flags)) {
       return FONT_COMPRESSION_FAILURE();
     }
     glyph->have_instructions |= (flags & kFLAG_WE_HAVE_INSTRUCTIONS) != 0;
-    var arg_size: size_t;  // glyph index
+    var arg_size: size_t = 2;  // glyph index
     if (flags & kFLAG_ARG_1_AND_2_ARE_WORDS) {
       arg_size += 4;
     } else {
@@ -63,7 +63,7 @@ fn ReadCompositeGlyphData(buffer: Buffer*, glyph: Glyph*) -> bool {
 }
 
 fn ReadGlyph(data: const uint8_t*, len: size_t, glyph: Glyph*) -> bool {
-  var buffer: Buffer;
+  var buffer: Buffer(data, len);
 
   var num_contours: int16_t;
   if (!buffer.ReadS16(&num_contours)) {
@@ -88,13 +88,13 @@ fn ReadGlyph(data: const uint8_t*, len: size_t, glyph: Glyph*) -> bool {
     glyph->contours.resize(num_contours);
 
     // Read the number of points per contour.
-    var last_point_index: uint16_t;
-    for (var i: int; i < num_contours; ++i) {
+    var last_point_index: uint16_t = 0;
+    for (var i: int = 0; i < num_contours; ++i) {
       var point_index: uint16_t;
       if (!buffer.ReadU16(&point_index)) {
         return FONT_COMPRESSION_FAILURE();
       }
-      var num_points: uint16_t;
+      var num_points: uint16_t = point_index - last_point_index + (i == 0 ? 1 : 0);
       glyph->contours[i].resize(num_points);
       last_point_index = point_index;
     }
@@ -109,13 +109,13 @@ fn ReadGlyph(data: const uint8_t*, len: size_t, glyph: Glyph*) -> bool {
     }
 
     // Read the run-length coded flags.
-    var flags: std::vector<std::vector<uint8_t> >;
+    var flags: std::vector<std::vector<uint8_t> >(num_contours);
     {
-      var flag: uint8_t;
-      var flag_repeat: uint8_t;
-      for (var i: int; i < num_contours; ++i) {
+      var flag: uint8_t = 0;
+      var flag_repeat: uint8_t = 0;
+      for (var i: int = 0; i < num_contours; ++i) {
         flags[i].resize(glyph->contours[i].size());
-        for (var j: size_t; j < glyph->contours[i].size(); ++j) {
+        for (var j: size_t = 0; j < glyph->contours[i].size(); ++j) {
           if (flag_repeat == 0) {
             if (!buffer.ReadU8(&flag)) {
               return FONT_COMPRESSION_FAILURE();
@@ -135,21 +135,21 @@ fn ReadGlyph(data: const uint8_t*, len: size_t, glyph: Glyph*) -> bool {
     }
 
     // Read the x coordinates.
-    var prev_x: int;
-    for (var i: int; i < num_contours; ++i) {
-      for (var j: size_t; j < glyph->contours[i].size(); ++j) {
-        var flag: uint8_t;
+    var prev_x: int = 0;
+    for (var i: int = 0; i < num_contours; ++i) {
+      for (var j: size_t = 0; j < glyph->contours[i].size(); ++j) {
+        var flag: uint8_t = flags[i][j];
         if (flag & kFLAG_XSHORT) {
           // single byte x-delta coord value
           var x_delta: uint8_t;
           if (!buffer.ReadU8(&x_delta)) {
             return FONT_COMPRESSION_FAILURE();
           }
-          var sign: int;
+          var sign: int = (flag & kFLAG_XREPEATSIGN) ? 1 : -1;
           glyph->contours[i][j].x = prev_x + sign * x_delta;
         } else {
           // double byte x-delta coord value
-          var x_delta: int16_t;
+          var x_delta: int16_t = 0;
           if (!(flag & kFLAG_XREPEATSIGN)) {
             if (!buffer.ReadS16(&x_delta)) {
               return FONT_COMPRESSION_FAILURE();
@@ -162,21 +162,21 @@ fn ReadGlyph(data: const uint8_t*, len: size_t, glyph: Glyph*) -> bool {
     }
 
     // Read the y coordinates.
-    var prev_y: int;
-    for (var i: int; i < num_contours; ++i) {
-      for (var j: size_t; j < glyph->contours[i].size(); ++j) {
-        var flag: uint8_t;
+    var prev_y: int = 0;
+    for (var i: int = 0; i < num_contours; ++i) {
+      for (var j: size_t = 0; j < glyph->contours[i].size(); ++j) {
+        var flag: uint8_t = flags[i][j];
         if (flag & kFLAG_YSHORT) {
           // single byte y-delta coord value
           var y_delta: uint8_t;
           if (!buffer.ReadU8(&y_delta)) {
             return FONT_COMPRESSION_FAILURE();
           }
-          var sign: int;
+          var sign: int = (flag & kFLAG_YREPEATSIGN) ? 1 : -1;
           glyph->contours[i][j].y = prev_y + sign * y_delta;
         } else {
           // double byte y-delta coord value
-          var y_delta: int16_t;
+          var y_delta: int16_t = 0;
           if (!(flag & kFLAG_YREPEATSIGN)) {
             if (!buffer.ReadS16(&y_delta)) {
               return FONT_COMPRESSION_FAILURE();
@@ -225,7 +225,7 @@ fn StoreInstructions(glyph: const Glyph&, offset: size_t*, dst: uint8_t*) {
 }
 
 fn StoreEndPtsOfContours(glyph: const Glyph&, offset: size_t*, dst: uint8_t*) -> bool {
-  var end_point: int;
+  var end_point: int = -1;
   for (const auto& contour : glyph.contours) {
     end_point += contour.size();
     if (contour.size() > std::numeric_limits<uint16_t>::max() ||
@@ -239,19 +239,19 @@ fn StoreEndPtsOfContours(glyph: const Glyph&, offset: size_t*, dst: uint8_t*) ->
 
 fn StorePoints(glyph: const Glyph&, offset: size_t*,
                  dst: uint8_t*, dst_size: size_t) -> bool {
-  var last_flag: int;
-  var repeat_count: int;
-  var last_x: int;
-  var last_y: int;
-  var x_bytes: size_t;
-  var y_bytes: size_t;
+  var last_flag: int = -1;
+  var repeat_count: int = 0;
+  var last_x: int = 0;
+  var last_y: int = 0;
+  var x_bytes: size_t = 0;
+  var y_bytes: size_t = 0;
 
   // Store the flags and calculate the total size of the x and y coordinates.
   for (const auto& contour : glyph.contours) {
     for (const auto& point : contour) {
-      var flag: int;
-      var dx: int;
-      var dy: int;
+      var flag: int = point.on_curve ? kFLAG_ONCURVE : 0;
+      var dx: int = point.x - last_x;
+      var dy: int = point.y - last_y;
       if (dx == 0) {
         flag |= kFLAG_XREPEATSIGN;
       } else if (dx > -256 && dx < 256) {
@@ -301,14 +301,14 @@ fn StorePoints(glyph: const Glyph&, offset: size_t*,
   }
 
   // Store the x and y coordinates.
-  var x_offset: size_t;
-  var y_offset: size_t;
+  var x_offset: size_t = *offset;
+  var y_offset: size_t = *offset + x_bytes;
   last_x = 0;
   last_y = 0;
   for (const auto& contour : glyph.contours) {
     for (const auto& point : contour) {
-      var dx: int;
-      var dy: int;
+      var dx: int = point.x - last_x;
+      var dy: int = point.y - last_y;
       if (dx == 0) {
         // pass
       } else if (dx > -256 && dx < 256) {
@@ -334,7 +334,7 @@ fn StorePoints(glyph: const Glyph&, offset: size_t*,
 }  // namespace
 
 fn StoreGlyph(glyph: const Glyph&, dst: uint8_t*, dst_size: size_t*) -> bool {
-  var offset: size_t;
+  var offset: size_t = 0;
   if (glyph.composite_data_size > 0) {
     // Composite glyph.
     if (*dst_size < ((10ULL + glyph.composite_data_size) +

+ 36 - 35
third_party/examples/woff2/carbon/src/normalize.impl.carbon

@@ -37,19 +37,19 @@ fn StoreLoca(index_fmt: int, value: uint32_t, offset: size_t*, dst: uint8_t*) {
 namespace {
 
 fn WriteNormalizedLoca(index_fmt: int, num_glyphs: int, font: Font*) -> bool {
-  var glyf_table: Font::Table*;
-  var loca_table: Font::Table*;
+  var glyf_table: Font::Table* = font->FindTable(kGlyfTableTag);
+  var loca_table: Font::Table* = font->FindTable(kLocaTableTag);
 
-  var glyph_sz: int;
+  var glyph_sz: int = index_fmt == 0 ? 2 : 4;
   loca_table->buffer.resize(Round4(num_glyphs + 1) * glyph_sz);
   loca_table->length = (num_glyphs + 1) * glyph_sz;
 
-  var glyf_dst: uint8_t*;
-  var loca_dst: uint8_t*;
-  var glyf_offset: uint32_t;
-  var loca_offset: size_t;
+  var glyf_dst: uint8_t* = num_glyphs ? &glyf_table->buffer[0] : nullptr;
+  var loca_dst: uint8_t* = &loca_table->buffer[0];
+  var glyf_offset: uint32_t = 0;
+  var loca_offset: size_t = 0;
 
-  for (var i: int; i < num_glyphs; ++i) {
+  for (var i: int = 0; i < num_glyphs; ++i) {
     StoreLoca(index_fmt, glyf_offset, &loca_offset, loca_dst);
     var glyph: Glyph;
     var glyph_data: const uint8_t*;
@@ -58,7 +58,7 @@ fn WriteNormalizedLoca(index_fmt: int, num_glyphs: int, font: Font*) -> bool {
         (glyph_size > 0 && !ReadGlyph(glyph_data, glyph_size, &glyph))) {
       return FONT_COMPRESSION_FAILURE();
     }
-    var glyf_dst_size: size_t;
+    var glyf_dst_size: size_t = glyf_table->buffer.size() - glyf_offset;
     if (!StoreGlyph(glyph, glyf_dst + glyf_offset, &glyf_dst_size)) {
       return FONT_COMPRESSION_FAILURE();
     }
@@ -86,16 +86,16 @@ fn WriteNormalizedLoca(index_fmt: int, num_glyphs: int, font: Font*) -> bool {
 namespace {
 
 fn MakeEditableBuffer(font: Font*, tableTag: int) -> bool {
-  var table: Font::Table*;
+  var table: Font::Table* = font->FindTable(tableTag);
   if (table == nullptr) {
     return FONT_COMPRESSION_FAILURE();
   }
   if (table->IsReused()) {
     return true;
   }
-  var sz: int;
+  var sz: int = Round4(table->length);
   table->buffer.resize(sz);
-  var buf: uint8_t*;
+  var buf: uint8_t* = &table->buffer[0];
   memcpy(buf, table->data, table->length);
   if (PREDICT_FALSE(sz > table->length)) {
     memset(buf + table->length, 0, sz - table->length);
@@ -107,9 +107,9 @@ fn MakeEditableBuffer(font: Font*, tableTag: int) -> bool {
 }  // namespace
 
 fn NormalizeGlyphs(font: Font*) -> bool {
-  var head_table: Font::Table*;
-  var glyf_table: Font::Table*;
-  var loca_table: Font::Table*;
+  var head_table: Font::Table* = font->FindTable(kHeadTableTag);
+  var glyf_table: Font::Table* = font->FindTable(kGlyfTableTag);
+  var loca_table: Font::Table* = font->FindTable(kLocaTableTag);
   if (head_table == nullptr) {
     return FONT_COMPRESSION_FAILURE();
   }
@@ -129,8 +129,8 @@ fn NormalizeGlyphs(font: Font*) -> bool {
     return true;
   }
 
-  var index_fmt: int;
-  var num_glyphs: int;
+  var index_fmt: int = head_table->data[51];
+  var num_glyphs: int = NumGlyphs(*font);
 
   // We need to allocate a bit more than its original length for the normalized
   // glyf table, since it can happen that the glyphs in the original table are
@@ -141,7 +141,7 @@ fn NormalizeGlyphs(font: Font*) -> bool {
   // some general overhead.
   // TODO(user) Figure out some more precise upper bound on the size of
   // the overhead.
-  var max_normalized_glyf_size: size_t;
+  var max_normalized_glyf_size: size_t = 1.1 * glyf_table->length + 2 * num_glyphs;
 
   glyf_table->buffer.resize(max_normalized_glyf_size);
 
@@ -164,9 +164,9 @@ fn NormalizeGlyphs(font: Font*) -> bool {
 }
 
 fn NormalizeOffsets(font: Font*) -> bool {
-  var offset: uint32_t;
+  var offset: uint32_t = 12 + 16 * font->num_tables;
   for (auto tag : font->OutputOrderedTags()) {
-    var table: auto&;
+    var table: auto& = font->tables[tag];
     table.offset = offset;
     offset += Round4(table.length);
   }
@@ -176,14 +176,14 @@ fn NormalizeOffsets(font: Font*) -> bool {
 namespace {
 
 fn ComputeHeaderChecksum(font: const Font&) -> uint32_t {
-  var checksum: uint32_t;
-  var max_pow2: uint16_t;
-  var search_range: uint16_t;
-  var range_shift: uint16_t;
+  var checksum: uint32_t = font.flavor;
+  var max_pow2: uint16_t = font.num_tables ? Log2Floor(font.num_tables) : 0;
+  var search_range: uint16_t = max_pow2 ? 1 << (max_pow2 + 4) : 0;
+  var range_shift: uint16_t = (font.num_tables << 4) - search_range;
   checksum += (font.num_tables << 16 | search_range);
   checksum += (max_pow2 << 16 | range_shift);
   for (const auto& i : font.tables) {
-    var table: const Font::Table*;
+    var table: const Font::Table* = &i.second;
     if (table->IsReused()) {
       table = table->reuse_of;
     }
@@ -198,7 +198,7 @@ fn ComputeHeaderChecksum(font: const Font&) -> uint32_t {
 }  // namespace
 
 fn FixChecksums(font: Font*) -> bool {
-  var head_table: Font::Table*;
+  var head_table: Font::Table* = font->FindTable(kHeadTableTag);
   if (head_table == nullptr) {
     return FONT_COMPRESSION_FAILURE();
   }
@@ -209,13 +209,13 @@ fn FixChecksums(font: Font*) -> bool {
     return FONT_COMPRESSION_FAILURE();
   }
 
-  var head_buf: uint8_t*;
-  var offset: size_t;
+  var head_buf: uint8_t* = &head_table->buffer[0];
+  var offset: size_t = 8;
   StoreU32(0, &offset, head_buf);
-  var file_checksum: uint32_t;
-  var head_checksum: uint32_t;
+  var file_checksum: uint32_t = 0;
+  var head_checksum: uint32_t = 0;
   for (auto& i : font->tables) {
-    var table: Font::Table*;
+    var table: Font::Table* = &i.second;
     if (table->IsReused()) {
       table = table->reuse_of;
     }
@@ -236,7 +236,7 @@ fn FixChecksums(font: Font*) -> bool {
 
 namespace {
 fn MarkTransformed(font: Font*) -> bool {
-  var head_table: Font::Table*;
+  var head_table: Font::Table* = font->FindTable(kHeadTableTag);
   if (head_table == nullptr) {
     return FONT_COMPRESSION_FAILURE();
   }
@@ -248,7 +248,7 @@ fn MarkTransformed(font: Font*) -> bool {
   }
   // set bit 11 of head table 'flags' to indicate that font has undergone
   // lossless modifying transform
-  var head_flags: int;
+  var head_flags: int = head_table->data[16];
   head_table->buffer[16] = head_flags | 0x08;
   return true;
 }
@@ -273,7 +273,8 @@ fn NormalizeFontCollection(font_collection: FontCollection*) -> bool {
     return NormalizeFont(&font_collection->fonts[0]);
   }
 
-  var offset: uint32_t;
+  var offset: uint32_t = CollectionHeaderSize(font_collection->header_version,
+    font_collection->fonts.size());
   for (auto& font : font_collection->fonts) {
     if (!NormalizeWithoutFixingChecksums(&font)) {
 #ifdef FONT_COMPRESSION_BIN
@@ -287,7 +288,7 @@ fn NormalizeFontCollection(font_collection: FontCollection*) -> bool {
   // Start table offsets after TTC Header and Sfnt Headers
   for (auto& font : font_collection->fonts) {
     for (auto tag : font.OutputOrderedTags()) {
-      var table: Font::Table&;
+      var table: Font::Table& = font.tables[tag];
       if (table.IsReused()) {
         table.offset = table.reuse_of->offset;
       } else {

+ 8 - 8
third_party/examples/woff2/carbon/src/table_tags.carbon

@@ -14,14 +14,14 @@
 namespace woff2 {
 
 // Tags of popular tables.
-let kGlyfTableTag: const uint32_t;
-let kHeadTableTag: const uint32_t;
-let kLocaTableTag: const uint32_t;
-let kDsigTableTag: const uint32_t;
-let kCffTableTag: const uint32_t;
-let kHmtxTableTag: const uint32_t;
-let kHheaTableTag: const uint32_t;
-let kMaxpTableTag: const uint32_t;
+let kGlyfTableTag: const uint32_t = 0x676c7966;
+let kHeadTableTag: const uint32_t = 0x68656164;
+let kLocaTableTag: const uint32_t = 0x6c6f6361;
+let kDsigTableTag: const uint32_t = 0x44534947;
+let kCffTableTag: const uint32_t = 0x43464620;
+let kHmtxTableTag: const uint32_t = 0x686d7478;
+let kHheaTableTag: const uint32_t = 0x68686561;
+let kMaxpTableTag: const uint32_t = 0x6d617870;
 
 let kKnownTags: const uint32_t[];
 

+ 65 - 1
third_party/examples/woff2/carbon/src/table_tags.impl.carbon

@@ -13,6 +13,70 @@ namespace woff2 {
 // Note that the byte order is big-endian, not the same as ots.cc
 #define TAG(a, b, c, d) (((a) << 24) | ((b) << 16) | ((c) << 8) | (d))
 
-let kKnownTags: const uint32_t[63];
+let kKnownTags: const uint32_t[63] = {
+  TAG('c', 'm', 'a', 'p'),  // 0
+  TAG('h', 'e', 'a', 'd'),  // 1
+  TAG('h', 'h', 'e', 'a'),  // 2
+  TAG('h', 'm', 't', 'x'),  // 3
+  TAG('m', 'a', 'x', 'p'),  // 4
+  TAG('n', 'a', 'm', 'e'),  // 5
+  TAG('O', 'S', '/', '2'),  // 6
+  TAG('p', 'o', 's', 't'),  // 7
+  TAG('c', 'v', 't', ' '),  // 8
+  TAG('f', 'p', 'g', 'm'),  // 9
+  TAG('g', 'l', 'y', 'f'),  // 10
+  TAG('l', 'o', 'c', 'a'),  // 11
+  TAG('p', 'r', 'e', 'p'),  // 12
+  TAG('C', 'F', 'F', ' '),  // 13
+  TAG('V', 'O', 'R', 'G'),  // 14
+  TAG('E', 'B', 'D', 'T'),  // 15
+  TAG('E', 'B', 'L', 'C'),  // 16
+  TAG('g', 'a', 's', 'p'),  // 17
+  TAG('h', 'd', 'm', 'x'),  // 18
+  TAG('k', 'e', 'r', 'n'),  // 19
+  TAG('L', 'T', 'S', 'H'),  // 20
+  TAG('P', 'C', 'L', 'T'),  // 21
+  TAG('V', 'D', 'M', 'X'),  // 22
+  TAG('v', 'h', 'e', 'a'),  // 23
+  TAG('v', 'm', 't', 'x'),  // 24
+  TAG('B', 'A', 'S', 'E'),  // 25
+  TAG('G', 'D', 'E', 'F'),  // 26
+  TAG('G', 'P', 'O', 'S'),  // 27
+  TAG('G', 'S', 'U', 'B'),  // 28
+  TAG('E', 'B', 'S', 'C'),  // 29
+  TAG('J', 'S', 'T', 'F'),  // 30
+  TAG('M', 'A', 'T', 'H'),  // 31
+  TAG('C', 'B', 'D', 'T'),  // 32
+  TAG('C', 'B', 'L', 'C'),  // 33
+  TAG('C', 'O', 'L', 'R'),  // 34
+  TAG('C', 'P', 'A', 'L'),  // 35
+  TAG('S', 'V', 'G', ' '),  // 36
+  TAG('s', 'b', 'i', 'x'),  // 37
+  TAG('a', 'c', 'n', 't'),  // 38
+  TAG('a', 'v', 'a', 'r'),  // 39
+  TAG('b', 'd', 'a', 't'),  // 40
+  TAG('b', 'l', 'o', 'c'),  // 41
+  TAG('b', 's', 'l', 'n'),  // 42
+  TAG('c', 'v', 'a', 'r'),  // 43
+  TAG('f', 'd', 's', 'c'),  // 44
+  TAG('f', 'e', 'a', 't'),  // 45
+  TAG('f', 'm', 't', 'x'),  // 46
+  TAG('f', 'v', 'a', 'r'),  // 47
+  TAG('g', 'v', 'a', 'r'),  // 48
+  TAG('h', 's', 't', 'y'),  // 49
+  TAG('j', 'u', 's', 't'),  // 50
+  TAG('l', 'c', 'a', 'r'),  // 51
+  TAG('m', 'o', 'r', 't'),  // 52
+  TAG('m', 'o', 'r', 'x'),  // 53
+  TAG('o', 'p', 'b', 'd'),  // 54
+  TAG('p', 'r', 'o', 'p'),  // 55
+  TAG('t', 'r', 'a', 'k'),  // 56
+  TAG('Z', 'a', 'p', 'f'),  // 57
+  TAG('S', 'i', 'l', 'f'),  // 58
+  TAG('G', 'l', 'a', 't'),  // 59
+  TAG('G', 'l', 'o', 'c'),  // 60
+  TAG('F', 'e', 'a', 't'),  // 61
+  TAG('S', 'i', 'l', 'l'),  // 62
+};
 
 } // namespace woff2

+ 47 - 47
third_party/examples/woff2/carbon/src/transform.impl.carbon

@@ -20,13 +20,13 @@ namespace woff2 {
 
 namespace {
 
-let FLAG_ARG_1_AND_2_ARE_WORDS: const int;
-let FLAG_WE_HAVE_INSTRUCTIONS: const int;
+let FLAG_ARG_1_AND_2_ARE_WORDS: const int = 1 << 0;
+let FLAG_WE_HAVE_INSTRUCTIONS: const int = 1 << 8;
 
 fn WriteBytes(out: std::vector<uint8_t>*, data: const uint8_t*, len: size_t) {
   if (len == 0) { return;
 }
-  var offset: size_t;
+  var offset: size_t = out->size();
   out->resize(offset + len);
   memcpy(&(*out)[offset], data, len);
 }
@@ -102,10 +102,10 @@ class GlyfEncoder {
       return glyph.x_min || glyph.y_min || glyph.x_max || glyph.y_max;
     }
 
-    var x_min: int16_t;
-    var y_min: int16_t;
-    var x_max: int16_t;
-    var y_max: int16_t;
+    var x_min: int16_t = glyph.contours[0][0].x;
+    var y_min: int16_t = glyph.contours[0][0].y;
+    var x_max: int16_t = x_min;
+    var y_max: int16_t = y_min;
     for (const auto& contour : glyph.contours) {
       for (const auto& point : contour) {
         if (point.x < x_min) { x_min = point.x;
@@ -136,23 +136,23 @@ class GlyfEncoder {
   }
 
   fn WriteSimpleGlyph(glyph_id: int, glyph: const Glyph&) {
-    var num_contours: int;
+    var num_contours: int = glyph.contours.size();
     WriteUShort(&n_contour_stream_, num_contours);
     if (ShouldWriteSimpleGlyphBbox(glyph)) {
       WriteBbox(glyph_id, glyph);
     }
-    for (var i: int; i < num_contours; i++) {
+    for (var i: int = 0; i < num_contours; i++) {
       Write255UShort(&n_points_stream_, glyph.contours[i].size());
     }
-    var lastX: int;
-    var lastY: int;
-    for (var i: int; i < num_contours; i++) {
-      var num_points: int;
-      for (var j: int; j < num_points; j++) {
-        var x: int;
-        var y: int;
-        var dx: int;
-        var dy: int;
+    var lastX: int = 0;
+    var lastY: int = 0;
+    for (var i: int = 0; i < num_contours; i++) {
+      var num_points: int = glyph.contours[i].size();
+      for (var j: int = 0; j < num_points; j++) {
+        var x: int = glyph.contours[i][j].x;
+        var y: int = glyph.contours[i][j].y;
+        var dx: int = x - lastX;
+        var dy: int = y - lastY;
         WriteTriplet(glyph.contours[i][j].on_curve, dx, dy);
         lastX = x;
         lastY = y;
@@ -183,12 +183,12 @@ class GlyfEncoder {
   }
 
   fn WriteTriplet(on_curve: bool, x: int, y: int) {
-    var abs_x: int;
-    var abs_y: int;
-    var on_curve_bit: int;
-    var x_sign_bit: int;
-    var y_sign_bit: int;
-    var xy_sign_bits: int;
+    var abs_x: int = std::abs(x);
+    var abs_y: int = std::abs(y);
+    var on_curve_bit: int = on_curve ? 0 : 128;
+    var x_sign_bit: int = (x < 0) ? 0 : 1;
+    var y_sign_bit: int = (y < 0) ? 0 : 1;
+    var xy_sign_bits: int = x_sign_bit + 2 * y_sign_bit;
     if (x == 0 && abs_y < 1280) {
       flag_byte_stream_.push_back(on_curve_bit +
                                   ((abs_y & 0xf00) >> 7) + y_sign_bit);
@@ -238,8 +238,8 @@ class GlyfEncoder {
 
 fn TransformGlyfAndLocaTables(font: Font*) -> bool {
   // no transform for CFF
-  var glyf_table: const Font::Table*;
-  var loca_table: const Font::Table*;
+  var glyf_table: const Font::Table* = font->FindTable(kGlyfTableTag);
+  var loca_table: const Font::Table* = font->FindTable(kLocaTableTag);
 
   // If you don't have glyf/loca this transform isn't very interesting
   if (loca_table == nullptr && glyf_table == nullptr) {
@@ -257,12 +257,12 @@ fn TransformGlyfAndLocaTables(font: Font*) -> bool {
     return true;
   }
 
-  var transformed_glyf: Font::Table*;
-  var transformed_loca: Font::Table*;
+  var transformed_glyf: Font::Table* = &font->tables[kGlyfTableTag ^ 0x80808080];
+  var transformed_loca: Font::Table* = &font->tables[kLocaTableTag ^ 0x80808080];
 
-  var num_glyphs: int;
-  var encoder: GlyfEncoder;
-  for (var i: int; i < num_glyphs; ++i) {
+  var num_glyphs: int = NumGlyphs(*font);
+  var encoder: GlyfEncoder(num_glyphs);
+  for (var i: int = 0; i < num_glyphs; ++i) {
     var glyph: Glyph;
     var glyph_data: const uint8_t*;
     var glyph_size: size_t;
@@ -274,7 +274,7 @@ fn TransformGlyfAndLocaTables(font: Font*) -> bool {
   }
   encoder.GetTransformedGlyfBytes(&transformed_glyf->buffer);
 
-  var head_table: const Font::Table*;
+  var head_table: const Font::Table* = font->FindTable(kHeadTableTag);
   if (head_table == nullptr || head_table->length < 52) {
     return FONT_COMPRESSION_FAILURE();
   }
@@ -294,9 +294,9 @@ fn TransformGlyfAndLocaTables(font: Font*) -> bool {
 // See https://www.microsoft.com/typography/otspec/hmtx.htm
 // See WOFF2 spec, 5.4. Transformed hmtx table format
 fn TransformHmtxTable(font: Font*) -> bool {
-  var glyf_table: const Font::Table*;
-  var hmtx_table: const Font::Table*;
-  var hhea_table: const Font::Table*;
+  var glyf_table: const Font::Table* = font->FindTable(kGlyfTableTag);
+  var hmtx_table: const Font::Table* = font->FindTable(kHmtxTableTag);
+  var hhea_table: const Font::Table* = font->FindTable(kHheaTableTag);
 
   // If you don't have hmtx or a glyf not much is going to happen here
   if (hmtx_table == nullptr || glyf_table == nullptr) {
@@ -309,7 +309,7 @@ fn TransformHmtxTable(font: Font*) -> bool {
   }
 
   // Skip 34 to reach 'hhea' numberOfHMetrics
-  var hhea_buf: Buffer;
+  var hhea_buf: Buffer(hhea_table->data, hhea_table->length);
   var num_hmetrics: uint16_t;
   if (!hhea_buf.Skip(34) || !hhea_buf.ReadU16(&num_hmetrics)) {
     return FONT_COMPRESSION_FAILURE();
@@ -320,18 +320,18 @@ fn TransformHmtxTable(font: Font*) -> bool {
     return FONT_COMPRESSION_FAILURE();
   }
 
-  var num_glyphs: int;
+  var num_glyphs: int = NumGlyphs(*font);
 
   // Most fonts can be transformed; assume it's a go until proven otherwise
   var advance_widths: std::vector<uint16_t>;
   var proportional_lsbs: std::vector<int16_t>;
   var monospace_lsbs: std::vector<int16_t>;
 
-  var remove_proportional_lsb: bool;
-  var remove_monospace_lsb: bool;
+  var remove_proportional_lsb: bool = true;
+  var remove_monospace_lsb: bool = (num_glyphs - num_hmetrics) > 0;
 
-  var hmtx_buf: Buffer;
-  for (var i: int; i < num_glyphs; i++) {
+  var hmtx_buf: Buffer(hmtx_table->data, hmtx_table->length);
+  for (var i: int = 0; i < num_glyphs; i++) {
     var glyph: Glyph;
     var glyph_data: const uint8_t*;
     var glyph_size: size_t;
@@ -340,8 +340,8 @@ fn TransformHmtxTable(font: Font*) -> bool {
       return FONT_COMPRESSION_FAILURE();
     }
 
-    var advance_width: uint16_t;
-    var lsb: int16_t;
+    var advance_width: uint16_t = 0;
+    var lsb: int16_t = 0;
 
     if (i < num_hmetrics) {
       // [0, num_hmetrics) are proportional hMetrics
@@ -376,10 +376,10 @@ fn TransformHmtxTable(font: Font*) -> bool {
     }
   }
 
-  var transformed_hmtx: Font::Table*;
+  var transformed_hmtx: Font::Table* = &font->tables[kHmtxTableTag ^ 0x80808080];
 
-  var flags: uint8_t;
-  var transformed_size: size_t;
+  var flags: uint8_t = 0;
+  var transformed_size: size_t = 1 + 2 * advance_widths.size();
   if (remove_proportional_lsb) {
     flags |= 1;
   } else {
@@ -392,7 +392,7 @@ fn TransformHmtxTable(font: Font*) -> bool {
   }
 
   transformed_hmtx->buffer.reserve(transformed_size);
-  var out: std::vector<uint8_t>*;
+  var out: std::vector<uint8_t>* = &transformed_hmtx->buffer;
   WriteBytes(out, &flags, 1);
   for (uint16_t advance_width : advance_widths) {
     WriteUShort(out, advance_width);

+ 16 - 16
third_party/examples/woff2/carbon/src/variable_length.impl.carbon

@@ -11,7 +11,7 @@
 namespace woff2 {
 
 fn Size255UShort(value: uint16_t) -> size_t {
-  var result: size_t;
+  var result: size_t = 3;
   if (value < 253) {
     result = 1;
   } else if (value < 762) {
@@ -48,30 +48,30 @@ fn Store255UShort(val: int, offset: size_t*, dst: uint8_t*) {
 
 // Based on section 6.1.1 of MicroType Express draft spec
 fn Read255UShort(buf: Buffer*, value: unsigned int*) -> bool {
-  let kWordCode: const int;
-  let kOneMoreByteCode2: const int;
-  let kOneMoreByteCode1: const int;
-  let kLowestUCode: const int;
-  var code: uint8_t;
+  let kWordCode: const int = 253;
+  let kOneMoreByteCode2: const int = 254;
+  let kOneMoreByteCode1: const int = 255;
+  let kLowestUCode: const int = 253;
+  var code: uint8_t = 0;
   if (!buf->ReadU8(&code)) {
     return FONT_COMPRESSION_FAILURE();
   }
   if (code == kWordCode) {
-    var result: uint16_t;
+    var result: uint16_t = 0;
     if (!buf->ReadU16(&result)) {
       return FONT_COMPRESSION_FAILURE();
     }
     *value = result;
     return true;
   } else if (code == kOneMoreByteCode1) {
-    var result: uint8_t;
+    var result: uint8_t = 0;
     if (!buf->ReadU8(&result)) {
       return FONT_COMPRESSION_FAILURE();
     }
     *value = result + kLowestUCode;
     return true;
   } else if (code == kOneMoreByteCode2) {
-    var result: uint8_t;
+    var result: uint8_t = 0;
     if (!buf->ReadU8(&result)) {
       return FONT_COMPRESSION_FAILURE();
     }
@@ -84,9 +84,9 @@ fn Read255UShort(buf: Buffer*, value: unsigned int*) -> bool {
 }
 
 fn ReadBase128(buf: Buffer*, value: uint32_t*) -> bool {
-  var result: uint32_t;
-  for (var i: size_t; i < 5; ++i) {
-    var code: uint8_t;
+  var result: uint32_t = 0;
+  for (var i: size_t = 0; i < 5; ++i) {
+    var code: uint8_t = 0;
     if (!buf->ReadU8(&code)) {
       return FONT_COMPRESSION_FAILURE();
     }
@@ -109,16 +109,16 @@ fn ReadBase128(buf: Buffer*, value: uint32_t*) -> bool {
 }
 
 fn Base128Size(n: size_t) -> size_t {
-  var size: size_t;
+  var size: size_t = 1;
   for (; n >= 128; n >>= 7) { ++size;
 }
   return size;
 }
 
 fn StoreBase128(len: size_t, offset: size_t*, dst: uint8_t*) {
-  var size: size_t;
-  for (var i: size_t; i < size; ++i) {
-    var b: int;
+  var size: size_t = Base128Size(len);
+  for (var i: size_t = 0; i < size; ++i) {
+    var b: int = static_cast<int>((len >> (7 * (size - i - 1))) & 0x7f);
     if (i < size - 1) {
       b |= 0x80;
     }

+ 5 - 5
third_party/examples/woff2/carbon/src/woff2_common.carbon

@@ -16,16 +16,16 @@
 
 namespace woff2 {
 
-let kWoff2Signature: const uint32_t;  // "wOF2"
+let kWoff2Signature: const uint32_t = 0x774f4632;  // "wOF2"
 
 // Leave the first byte open to store flag_byte
-let kWoff2FlagsTransform: const unsigned int;
+let kWoff2FlagsTransform: const unsigned int = 1 << 8;
 
 // TrueType Collection ID string: 'ttcf'
-let kTtcFontFlavor: const uint32_t;
+let kTtcFontFlavor: const uint32_t = 0x74746366;
 
-let kSfntHeaderSize: const size_t;
-let kSfntEntrySize: const size_t;
+let kSfntHeaderSize: const size_t = 12;
+let kSfntEntrySize: const size_t = 16;
 
 struct Point {
   int x;

+ 7 - 7
third_party/examples/woff2/carbon/src/woff2_common.impl.carbon

@@ -16,11 +16,11 @@ namespace woff2 {
 
 
 fn ComputeULongSum(buf: const uint8_t*, size: size_t) -> uint32_t {
-  var checksum: uint32_t;
-  var aligned_size: size_t;
-  for (var i: size_t; i < aligned_size; i += 4) {
+  var checksum: uint32_t = 0;
+  var aligned_size: size_t = size & ~3;
+  for (var i: size_t = 0; i < aligned_size; i += 4) {
 #if defined(WOFF_LITTLE_ENDIAN)
-    var v: uint32_t;
+    var v: uint32_t = *reinterpret_cast<const uint32_t*>(buf + i);
     checksum += (((v & 0xFF) << 24) | ((v & 0xFF00) << 8) |
       ((v & 0xFF0000) >> 8) | ((v & 0xFF000000) >> 24));
 #elif defined(WOFF_BIG_ENDIAN)
@@ -33,8 +33,8 @@ fn ComputeULongSum(buf: const uint8_t*, size: size_t) -> uint32_t {
 
   // treat size not aligned on 4 as if it were padded to 4 with 0's
   if (size != aligned_size) {
-    var v: uint32_t;
-    for (var i: size_t; i < size; ++i) {
+    var v: uint32_t = 0;
+    for (var i: size_t = aligned_size; i < size; ++i) {
       v |= buf[i] << (24 - 8 * (i & 3));
     }
     checksum += v;
@@ -44,7 +44,7 @@ fn ComputeULongSum(buf: const uint8_t*, size: size_t) -> uint32_t {
 }
 
 fn CollectionHeaderSize(header_version: uint32_t, num_fonts: uint32_t) -> size_t {
-  var size: size_t;
+  var size: size_t = 0;
   if (header_version == 0x00020000) {
     size += 12;  // ulDsig{Tag,Length,Offset}
   }

+ 7 - 7
third_party/examples/woff2/carbon/src/woff2_compress.impl.carbon

@@ -20,16 +20,16 @@ fn main(argc: int, argv: char**) -> int {
     return 1;
   }
 
-  var filename: string;
-  var outfilename: string;
+  var filename: string(argv[1]);
+  var outfilename: string = filename.substr(0, filename.find_last_of('.')) + ".woff2";
   fprintf(stdout, "Processing %s => %s\n",
     filename.c_str(), outfilename.c_str());
-  var input: string;
+  var input: string = woff2::GetFileContent(filename);
 
-  var input_data: const auto*;
-  var output_size: size_t;
-  var output: string;
-  var output_data: auto*;
+  var input_data: const auto* = reinterpret_cast<const uint8_t*>(input.data());
+  var output_size: size_t = woff2::MaxWOFF2CompressedSize(input_data, input.size());
+  var output: string(output_size, 0);
+  var output_data: auto* = reinterpret_cast<uint8_t*>(&output[0]);
 
   var params: woff2::WOFF2Params;
   if (!woff2::ConvertTTFToWOFF2(input_data, input.size(),

+ 175 - 168
third_party/examples/woff2/carbon/src/woff2_dec.impl.carbon

@@ -38,34 +38,34 @@ using std::vector;
 
 
 // simple glyph flags
-let kGlyfOnCurve: const int;
-let kGlyfXShort: const int;
-let kGlyfYShort: const int;
-let kGlyfRepeat: const int;
-let kGlyfThisXIsSame: const int;
-let kGlyfThisYIsSame: const int;
+let kGlyfOnCurve: const int = 1 << 0;
+let kGlyfXShort: const int = 1 << 1;
+let kGlyfYShort: const int = 1 << 2;
+let kGlyfRepeat: const int = 1 << 3;
+let kGlyfThisXIsSame: const int = 1 << 4;
+let kGlyfThisYIsSame: const int = 1 << 5;
 
 // composite glyph flags
 // See CompositeGlyph.java in sfntly for full definitions
-let FLAG_ARG_1_AND_2_ARE_WORDS: const int;
-let FLAG_WE_HAVE_A_SCALE: const int;
-let FLAG_MORE_COMPONENTS: const int;
-let FLAG_WE_HAVE_AN_X_AND_Y_SCALE: const int;
-let FLAG_WE_HAVE_A_TWO_BY_TWO: const int;
-let FLAG_WE_HAVE_INSTRUCTIONS: const int;
+let FLAG_ARG_1_AND_2_ARE_WORDS: const int = 1 << 0;
+let FLAG_WE_HAVE_A_SCALE: const int = 1 << 3;
+let FLAG_MORE_COMPONENTS: const int = 1 << 5;
+let FLAG_WE_HAVE_AN_X_AND_Y_SCALE: const int = 1 << 6;
+let FLAG_WE_HAVE_A_TWO_BY_TWO: const int = 1 << 7;
+let FLAG_WE_HAVE_INSTRUCTIONS: const int = 1 << 8;
 
-let kCheckSumAdjustmentOffset: const size_t;
+let kCheckSumAdjustmentOffset: const size_t = 8;
 
-let kEndPtsOfContoursOffset: const size_t;
-let kCompositeGlyphBegin: const size_t;
+let kEndPtsOfContoursOffset: const size_t = 10;
+let kCompositeGlyphBegin: const size_t = 10;
 
 // 98% of Google Fonts have no glyph above 5k bytes
 // Largest glyph ever observed was 72k bytes
-let kDefaultGlyphBuf: const size_t;
+let kDefaultGlyphBuf: const size_t = 5120;
 
 // Over 14k test fonts the max compression ratio seen to date was ~20.
 // >100 suggests you wrote a bad uncompressed size.
-let kMaxPlausibleCompressionRatio: const float;
+let kMaxPlausibleCompressionRatio: const float = 100.0;
 
 // metadata for a TTC font entry
 struct TtcFont {
@@ -124,17 +124,17 @@ fn _SafeIntAddition(a: int, b: int, result: int*) -> bool {
 
 fn TripletDecode(flags_in: const uint8_t*, in: const uint8_t*, in_size: size_t,
     n_points: unsigned int, result: Point*, in_bytes_consumed: size_t*) -> bool {
-  var x: int;
-  var y: int;
+  var x: int = 0;
+  var y: int = 0;
 
   if (PREDICT_FALSE(n_points > in_size)) {
     return FONT_COMPRESSION_FAILURE();
   }
-  var triplet_index: unsigned int;
+  var triplet_index: unsigned int = 0;
 
-  for (var i: unsigned int; i < n_points; ++i) {
-    var flag: uint8_t;
-    var on_curve: bool;
+  for (var i: unsigned int = 0; i < n_points; ++i) {
+    var flag: uint8_t = flags_in[i];
+    var on_curve: bool = !(flag >> 7);
     flag &= 0x7f;
     var n_data_bytes: unsigned int;
     if (flag < 84) {
@@ -158,17 +158,17 @@ fn TripletDecode(flags_in: const uint8_t*, in: const uint8_t*, in_size: size_t,
       dx = WithSign(flag, (((flag - 10) & 14) << 7) + in[triplet_index]);
       dy = 0;
     } else if (flag < 84) {
-      var b0: int;
-      var b1: int;
+      var b0: int = flag - 20;
+      var b1: int = in[triplet_index];
       dx = WithSign(flag, 1 + (b0 & 0x30) + (b1 >> 4));
       dy = WithSign(flag >> 1, 1 + ((b0 & 0x0c) << 2) + (b1 & 0x0f));
     } else if (flag < 120) {
-      var b0: int;
+      var b0: int = flag - 84;
       dx = WithSign(flag, 1 + ((b0 / 12) << 8) + in[triplet_index]);
       dy = WithSign(flag >> 1,
                     1 + (((b0 % 12) >> 2) << 8) + in[triplet_index + 1]);
     } else if (flag < 124) {
-      var b2: int;
+      var b2: int = in[triplet_index + 1];
       dx = WithSign(flag, (in[triplet_index] << 4) + (b2 >> 4));
       dy = WithSign(flag >> 1, ((b2 & 0x0f) << 8) + in[triplet_index + 2]);
     } else {
@@ -196,19 +196,20 @@ fn StorePoints(n_points: unsigned int, points: const Point*,
     dst: uint8_t*, dst_size: size_t, glyph_size: size_t*) -> bool {
   // I believe that n_contours < 65536, in which case this is safe. However, a
   // comment and/or an assert would be good.
-  var flag_offset: unsigned int;
-  var last_flag: int;
-  var repeat_count: int;
-  var last_x: int;
-  var last_y: int;
-  var x_bytes: unsigned int;
-  var y_bytes: unsigned int;
-
-  for (var i: unsigned int; i < n_points; ++i) {
-    var point: const Point&;
-    var flag: int;
-    var dx: int;
-    var dy: int;
+  var flag_offset: unsigned int = kEndPtsOfContoursOffset + 2 * n_contours + 2 +
+    instruction_length;
+  var last_flag: int = -1;
+  var repeat_count: int = 0;
+  var last_x: int = 0;
+  var last_y: int = 0;
+  var x_bytes: unsigned int = 0;
+  var y_bytes: unsigned int = 0;
+
+  for (var i: unsigned int = 0; i < n_points; ++i) {
+    var point: const Point& = points[i];
+    var flag: int = point.on_curve ? kGlyfOnCurve : 0;
+    var dx: int = point.x - last_x;
+    var dy: int = point.y - last_y;
     if (dx == 0) {
       flag |= kGlyfThisXIsSame;
     } else if (dx > -256 && dx < 256) {
@@ -253,19 +254,19 @@ fn StorePoints(n_points: unsigned int, points: const Point*,
     }
     dst[flag_offset++] = repeat_count;
   }
-  var xy_bytes: unsigned int;
+  var xy_bytes: unsigned int = x_bytes + y_bytes;
   if (PREDICT_FALSE(xy_bytes < x_bytes ||
       flag_offset + xy_bytes < flag_offset ||
       flag_offset + xy_bytes > dst_size)) {
     return FONT_COMPRESSION_FAILURE();
   }
 
-  var x_offset: int;
-  var y_offset: int;
+  var x_offset: int = flag_offset;
+  var y_offset: int = flag_offset + x_bytes;
   last_x = 0;
   last_y = 0;
-  for (var i: unsigned int; i < n_points; ++i) {
-    var dx: int;
+  for (var i: unsigned int = 0; i < n_points; ++i) {
+    var dx: int = points[i].x - last_x;
     if (dx == 0) {
       // pass
     } else if (dx > -256 && dx < 256) {
@@ -275,7 +276,7 @@ fn StorePoints(n_points: unsigned int, points: const Point*,
       x_offset = Store16(dst, x_offset, dx);
     }
     last_x += dx;
-    var dy: int;
+    var dy: int = points[i].y - last_y;
     if (dy == 0) {
       // pass
     } else if (dy > -256 && dy < 256) {
@@ -293,10 +294,10 @@ fn StorePoints(n_points: unsigned int, points: const Point*,
 // A precondition is that there are at least 10 bytes available.
 // dst should point to the beginning of a 'glyf' record.
 fn ComputeBbox(n_points: unsigned int, points: const Point*, dst: uint8_t*) {
-  var x_min: int;
-  var y_min: int;
-  var x_max: int;
-  var y_max: int;
+  var x_min: int = 0;
+  var y_min: int = 0;
+  var x_max: int = 0;
+  var y_max: int = 0;
 
   if (n_points > 0) {
     x_min = points[0].x;
@@ -304,15 +305,15 @@ fn ComputeBbox(n_points: unsigned int, points: const Point*, dst: uint8_t*) {
     y_min = points[0].y;
     y_max = points[0].y;
   }
-  for (var i: unsigned int; i < n_points; ++i) {
-    var x: int;
-    var y: int;
+  for (var i: unsigned int = 1; i < n_points; ++i) {
+    var x: int = points[i].x;
+    var y: int = points[i].y;
     x_min = std::min(x, x_min);
     x_max = std::max(x, x_max);
     y_min = std::min(y, y_min);
     y_max = std::max(y, y_max);
   }
-  var offset: size_t;
+  var offset: size_t = 2;
   offset = Store16(dst, offset, x_min);
   offset = Store16(dst, offset, y_min);
   offset = Store16(dst, offset, x_max);
@@ -322,16 +323,16 @@ fn ComputeBbox(n_points: unsigned int, points: const Point*, dst: uint8_t*) {
 
 fn SizeOfComposite(composite_stream: Buffer, size: size_t*,
                      have_instructions: bool*) -> bool {
-  var start_offset: size_t;
-  var we_have_instructions: bool;
+  var start_offset: size_t = composite_stream.offset();
+  var we_have_instructions: bool = false;
 
-  var flags: uint16_t;
+  var flags: uint16_t = FLAG_MORE_COMPONENTS;
   while (flags & FLAG_MORE_COMPONENTS) {
     if (PREDICT_FALSE(!composite_stream.ReadU16(&flags))) {
       return FONT_COMPRESSION_FAILURE();
     }
     we_have_instructions |= (flags & FLAG_WE_HAVE_INSTRUCTIONS) != 0;
-    var arg_size: size_t;  // glyph index
+    var arg_size: size_t = 2;  // glyph index
     if (flags & FLAG_ARG_1_AND_2_ARE_WORDS) {
       arg_size += 4;
     } else {
@@ -356,11 +357,11 @@ fn SizeOfComposite(composite_stream: Buffer, size: size_t*,
 }
 
 fn Pad4(out: WOFF2Out*) -> bool {
-  var zeroes: uint8_t[];
+  var zeroes: uint8_t[] = {0, 0, 0};
   if (PREDICT_FALSE(out->Size() + 3 < out->Size())) {
     return FONT_COMPRESSION_FAILURE();
   }
-  var pad_bytes: uint32_t;
+  var pad_bytes: uint32_t = Round4(out->Size()) - out->Size();
   if (pad_bytes > 0) {
     if (PREDICT_FALSE(!out->Write(&zeroes, pad_bytes))) {
       return FONT_COMPRESSION_FAILURE();
@@ -374,14 +375,14 @@ fn StoreLoca(loca_values: const std::vector<uint32_t>&, index_format: int,
                checksum: uint32_t*, out: WOFF2Out*) -> bool {
   // TODO(user) figure out what index format to use based on whether max
   // offset fits into uint16_t or not
-  let loca_size: const uint64_t;
-  let offset_size: const uint64_t;
+  let loca_size: const uint64_t = loca_values.size();
+  let offset_size: const uint64_t = index_format ? 4 : 2;
   if (PREDICT_FALSE((loca_size << 2) >> 2 != loca_size)) {
     return FONT_COMPRESSION_FAILURE();
   }
-  var loca_content: std::vector<uint8_t>;
-  var dst: uint8_t*;
-  var offset: size_t;
+  var loca_content: std::vector<uint8_t>(loca_size * offset_size);
+  var dst: uint8_t* = &loca_content[0];
+  var offset: size_t = 0;
   for (unsigned int value : loca_values) {
     if (index_format) {
       offset = StoreU32(dst, offset, value);
@@ -401,11 +402,11 @@ fn ReconstructGlyf(data: const uint8_t*, glyf_table: Table*,
                      glyf_checksum: uint32_t*, loca_table: Table*,
                      loca_checksum: uint32_t*, info: WOFF2FontInfo*,
                      out: WOFF2Out*) -> bool {
-  let kNumSubStreams: const int;
-  var file: Buffer;
+  let kNumSubStreams: const int = 7;
+  var file: Buffer(data, glyf_table->transform_length);
   var version: uint32_t;
-  var substreams: std::vector<std::pair<const uint8_t*, size_t> >;
-  let glyf_start: const size_t;
+  var substreams: std::vector<std::pair<const uint8_t*, size_t> >(kNumSubStreams);
+  let glyf_start: const size_t = out->Size();
 
   if (PREDICT_FALSE(!file.ReadU32(&version))) {
     return FONT_COMPRESSION_FAILURE();
@@ -417,17 +418,18 @@ fn ReconstructGlyf(data: const uint8_t*, glyf_table: Table*,
 
   // https://dev.w3.org/webfonts/WOFF2/spec/#conform-mustRejectLoca
   // dst_length here is origLength in the spec
-  var expected_loca_dst_length: uint32_t;
+  var expected_loca_dst_length: uint32_t = (info->index_format ? 4 : 2)
+    * (static_cast<uint32_t>(info->num_glyphs) + 1);
   if (PREDICT_FALSE(loca_table->dst_length != expected_loca_dst_length)) {
     return FONT_COMPRESSION_FAILURE();
   }
 
-  var offset: unsigned int;
+  var offset: unsigned int = (2 + kNumSubStreams) * 4;
   if (PREDICT_FALSE(offset > glyf_table->transform_length)) {
     return FONT_COMPRESSION_FAILURE();
   }
   // Invariant from here on: data_size >= offset
-  for (var i: int; i < kNumSubStreams; ++i) {
+  for (var i: int = 0; i < kNumSubStreams; ++i) {
     var substream_size: uint32_t;
     if (PREDICT_FALSE(!file.ReadU32(&substream_size))) {
       return FONT_COMPRESSION_FAILURE();
@@ -438,34 +440,34 @@ fn ReconstructGlyf(data: const uint8_t*, glyf_table: Table*,
     substreams[i] = std::make_pair(data + offset, substream_size);
     offset += substream_size;
   }
-  var n_contour_stream: Buffer;
-  var n_points_stream: Buffer;
-  var flag_stream: Buffer;
-  var glyph_stream: Buffer;
-  var composite_stream: Buffer;
-  var bbox_stream: Buffer;
-  var instruction_stream: Buffer;
+  var n_contour_stream: Buffer(substreams[0].first, substreams[0].second);
+  var n_points_stream: Buffer(substreams[1].first, substreams[1].second);
+  var flag_stream: Buffer(substreams[2].first, substreams[2].second);
+  var glyph_stream: Buffer(substreams[3].first, substreams[3].second);
+  var composite_stream: Buffer(substreams[4].first, substreams[4].second);
+  var bbox_stream: Buffer(substreams[5].first, substreams[5].second);
+  var instruction_stream: Buffer(substreams[6].first, substreams[6].second);
 
-  var loca_values: std::vector<uint32_t>;
+  var loca_values: std::vector<uint32_t>(info->num_glyphs + 1);
   var n_points_vec: std::vector<unsigned int>;
   var points: std::unique_ptr<Point[]>;
-  var points_size: size_t;
-  var bbox_bitmap: const uint8_t*;
+  var points_size: size_t = 0;
+  var bbox_bitmap: const uint8_t* = bbox_stream.buffer();
   // Safe because num_glyphs is bounded
-  var bitmap_length: unsigned int;
+  var bitmap_length: unsigned int = ((info->num_glyphs + 31) >> 5) << 2;
   if (!bbox_stream.Skip(bitmap_length)) {
     return FONT_COMPRESSION_FAILURE();
   }
 
   // Temp buffer for glyph's.
-  var glyph_buf_size: size_t;
-  var glyph_buf: std::unique_ptr<uint8_t[]>;
+  var glyph_buf_size: size_t = kDefaultGlyphBuf;
+  var glyph_buf: std::unique_ptr<uint8_t[]>(new uint8_t[glyph_buf_size]);
 
   info->x_mins.resize(info->num_glyphs);
-  for (var i: unsigned int; i < info->num_glyphs; ++i) {
-    var glyph_size: size_t;
-    var n_contours: uint16_t;
-    var have_bbox: bool;
+  for (var i: unsigned int = 0; i < info->num_glyphs; ++i) {
+    var glyph_size: size_t = 0;
+    var n_contours: uint16_t = 0;
+    var have_bbox: bool = false;
     if (bbox_bitmap[i >> 3] & (0x80 >> (i & 7))) {
       have_bbox = true;
     }
@@ -475,8 +477,8 @@ fn ReconstructGlyf(data: const uint8_t*, glyf_table: Table*,
 
     if (n_contours == 0xffff) {
       // composite glyph
-      var have_instructions: bool;
-      var instruction_size: unsigned int;
+      var have_instructions: bool = false;
+      var instruction_size: unsigned int = 0;
       if (PREDICT_FALSE(!have_bbox)) {
         // composite glyphs must have an explicit bbox
         return FONT_COMPRESSION_FAILURE();
@@ -493,7 +495,7 @@ fn ReconstructGlyf(data: const uint8_t*, glyf_table: Table*,
         }
       }
 
-      var size_needed: size_t;
+      var size_needed: size_t = 12 + composite_size + instruction_size;
       if (PREDICT_FALSE(glyph_buf_size < size_needed)) {
         glyph_buf.reset(new uint8_t[size_needed]);
         glyph_buf_size = size_needed;
@@ -521,9 +523,9 @@ fn ReconstructGlyf(data: const uint8_t*, glyf_table: Table*,
     } else if (n_contours > 0) {
       // simple glyph
       n_points_vec.clear();
-      var total_n_points: unsigned int;
+      var total_n_points: unsigned int = 0;
       var n_points_contour: unsigned int;
-      for (var j: unsigned int; j < n_contours; ++j) {
+      for (var j: unsigned int = 0; j < n_contours; ++j) {
         if (PREDICT_FALSE(
             !Read255UShort(&n_points_stream, &n_points_contour))) {
           return FONT_COMPRESSION_FAILURE();
@@ -534,15 +536,16 @@ fn ReconstructGlyf(data: const uint8_t*, glyf_table: Table*,
         }
         total_n_points += n_points_contour;
       }
-      var flag_size: unsigned int;
+      var flag_size: unsigned int = total_n_points;
       if (PREDICT_FALSE(
           flag_size > flag_stream.length() - flag_stream.offset())) {
         return FONT_COMPRESSION_FAILURE();
       }
-      var flags_buf: const uint8_t*;
-      var triplet_buf: const uint8_t*;
-      var triplet_size: size_t;
-      var triplet_bytes_consumed: size_t;
+      var flags_buf: const uint8_t* = flag_stream.buffer() + flag_stream.offset();
+      var triplet_buf: const uint8_t* = glyph_stream.buffer() +
+        glyph_stream.offset();
+      var triplet_size: size_t = glyph_stream.length() - glyph_stream.offset();
+      var triplet_bytes_consumed: size_t = 0;
       if (points_size < total_n_points) {
         points_size = total_n_points;
         points = std::make_unique<Point[]>(points_size);
@@ -566,7 +569,8 @@ fn ReconstructGlyf(data: const uint8_t*, glyf_table: Table*,
                         || instruction_size >= (1 << 30))) {
         return FONT_COMPRESSION_FAILURE();
       }
-      var size_needed: size_t;
+      var size_needed: size_t = 12 + 2 * n_contours + 5 * total_n_points
+                           + instruction_size;
       if (PREDICT_FALSE(glyph_buf_size < size_needed)) {
         glyph_buf.reset(new uint8_t[size_needed]);
         glyph_buf_size = size_needed;
@@ -581,8 +585,8 @@ fn ReconstructGlyf(data: const uint8_t*, glyf_table: Table*,
         ComputeBbox(total_n_points, points.get(), glyph_buf.get());
       }
       glyph_size = kEndPtsOfContoursOffset;
-      var end_point: int;
-      for (var contour_ix: unsigned int; contour_ix < n_contours; ++contour_ix) {
+      var end_point: int = -1;
+      for (var contour_ix: unsigned int = 0; contour_ix < n_contours; ++contour_ix) {
         end_point += n_points_vec[contour_ix];
         if (PREDICT_FALSE(end_point >= 65536)) {
           return FONT_COMPRESSION_FAILURE();
@@ -625,7 +629,7 @@ fn ReconstructGlyf(data: const uint8_t*, glyf_table: Table*,
 
     // We may need x_min to reconstruct 'hmtx'
     if (n_contours > 0) {
-      var x_min_buf: Buffer;
+      var x_min_buf: Buffer(glyph_buf.get() + 2, 2);
       if (PREDICT_FALSE(!x_min_buf.ReadS16(&info->x_mins[i]))) {
         return FONT_COMPRESSION_FAILURE();
       }
@@ -659,7 +663,7 @@ fn FindTable(tables: std::vector<Table*>*, tag: uint32_t) -> Table* {
 fn ReadNumHMetrics(data: const uint8_t*, data_size: size_t,
                      num_hmetrics: uint16_t*) -> bool {
   // Skip 34 to reach 'hhea' numberOfHMetrics
-  var buffer: Buffer;
+  var buffer: Buffer(data, data_size);
   if (PREDICT_FALSE(!buffer.Skip(34) || !buffer.ReadU16(num_hmetrics))) {
     return FONT_COMPRESSION_FAILURE();
   }
@@ -674,7 +678,7 @@ fn ReconstructTransformedHmtx(transformed_buf: const uint8_t*,
                                 x_mins: const std::vector<int16_t>&,
                                 checksum: uint32_t*,
                                 out: WOFF2Out*) -> bool {
-  var hmtx_buff_in: Buffer;
+  var hmtx_buff_in: Buffer(transformed_buf, transformed_size);
 
   var hmtx_flags: uint8_t;
   if (PREDICT_FALSE(!hmtx_buff_in.ReadU8(&hmtx_flags))) {
@@ -683,8 +687,8 @@ fn ReconstructTransformedHmtx(transformed_buf: const uint8_t*,
 
   var advance_widths: std::vector<uint16_t>;
   var lsbs: std::vector<int16_t>;
-  var has_proportional_lsbs: bool;
-  var has_monospace_lsbs: bool;
+  var has_proportional_lsbs: bool = (hmtx_flags & 1) == 0;
+  var has_monospace_lsbs: bool = (hmtx_flags & 2) == 0;
 
   // Bits 2-7 are reserved and MUST be zero.
   if ((hmtx_flags & 0xFC) != 0) {
@@ -712,7 +716,7 @@ fn ReconstructTransformedHmtx(transformed_buf: const uint8_t*,
     return FONT_COMPRESSION_FAILURE();
   }
 
-  for (var i: uint16_t; i < num_hmetrics; i++) {
+  for (var i: uint16_t = 0; i < num_hmetrics; i++) {
     var advance_width: uint16_t;
     if (PREDICT_FALSE(!hmtx_buff_in.ReadU16(&advance_width))) {
       return FONT_COMPRESSION_FAILURE();
@@ -720,7 +724,7 @@ fn ReconstructTransformedHmtx(transformed_buf: const uint8_t*,
     advance_widths.push_back(advance_width);
   }
 
-  for (var i: uint16_t; i < num_hmetrics; i++) {
+  for (var i: uint16_t = 0; i < num_hmetrics; i++) {
     var lsb: int16_t;
     if (has_proportional_lsbs) {
       if (PREDICT_FALSE(!hmtx_buff_in.ReadS16(&lsb))) {
@@ -732,7 +736,7 @@ fn ReconstructTransformedHmtx(transformed_buf: const uint8_t*,
     lsbs.push_back(lsb);
   }
 
-  for (var i: uint16_t; i < num_glyphs; i++) {
+  for (var i: uint16_t = num_hmetrics; i < num_glyphs; i++) {
     var lsb: int16_t;
     if (has_monospace_lsbs) {
       if (PREDICT_FALSE(!hmtx_buff_in.ReadS16(&lsb))) {
@@ -745,11 +749,11 @@ fn ReconstructTransformedHmtx(transformed_buf: const uint8_t*,
   }
 
   // bake me a shiny new hmtx table
-  var hmtx_output_size: uint32_t;
-  var hmtx_table: std::vector<uint8_t>;
-  var dst: uint8_t*;
-  var dst_offset: size_t;
-  for (var i: uint32_t; i < num_glyphs; i++) {
+  var hmtx_output_size: uint32_t = 2 * num_glyphs + 2 * num_hmetrics;
+  var hmtx_table: std::vector<uint8_t>(hmtx_output_size);
+  var dst: uint8_t* = &hmtx_table[0];
+  var dst_offset: size_t = 0;
+  for (var i: uint32_t = 0; i < num_glyphs; i++) {
     if (i < num_hmetrics) {
       Store16(advance_widths[i], &dst_offset, dst);
     }
@@ -766,8 +770,9 @@ fn ReconstructTransformedHmtx(transformed_buf: const uint8_t*,
 
 fn Woff2Uncompress(dst_buf: uint8_t*, dst_size: size_t,
   src_buf: const uint8_t*, src_size: size_t) -> bool {
-  var uncompressed_size: size_t;
-  var result: BrotliDecoderResult;
+  var uncompressed_size: size_t = dst_size;
+  var result: BrotliDecoderResult = BrotliDecoderDecompress(
+      src_size, src_buf, &uncompressed_size, dst_buf);
   if (PREDICT_FALSE(result != BROTLI_DECODER_RESULT_SUCCESS ||
                     uncompressed_size != dst_size)) {
     return FONT_COMPRESSION_FAILURE();
@@ -777,9 +782,9 @@ fn Woff2Uncompress(dst_buf: uint8_t*, dst_size: size_t,
 
 fn ReadTableDirectory(file: Buffer*, tables: std::vector<Table>*,
     num_tables: size_t) -> bool {
-  var src_offset: uint32_t;
-  for (var i: size_t; i < num_tables; ++i) {
-    var table: Table*;
+  var src_offset: uint32_t = 0;
+  for (var i: size_t = 0; i < num_tables; ++i) {
+    var table: Table* = &(*tables)[i];
     var flag_byte: uint8_t;
     if (PREDICT_FALSE(!file->ReadU8(&flag_byte))) {
       return FONT_COMPRESSION_FAILURE();
@@ -792,8 +797,8 @@ fn ReadTableDirectory(file: Buffer*, tables: std::vector<Table>*,
     } else {
       tag = kKnownTags[flag_byte & 0x3f];
     }
-    var flags: uint32_t;
-    var xform_version: uint8_t;
+    var flags: uint32_t = 0;
+    var xform_version: uint8_t = (flag_byte >> 6) & 0x03;
 
     // 0 means xform for glyph/loca, non-0 for others
     if (tag == kGlyfTableTag || tag == kLocaTableTag) {
@@ -809,7 +814,7 @@ fn ReadTableDirectory(file: Buffer*, tables: std::vector<Table>*,
     if (PREDICT_FALSE(!ReadBase128(file, &dst_length))) {
       return FONT_COMPRESSION_FAILURE();
     }
-    var transform_length: uint32_t;
+    var transform_length: uint32_t = dst_length;
     if ((flags & kWoff2FlagsTransform) != 0) {
       if (PREDICT_FALSE(!ReadBase128(file, &transform_length))) {
         return FONT_COMPRESSION_FAILURE();
@@ -838,11 +843,11 @@ fn StoreOffsetTable(result: uint8_t*, offset: size_t, flavor: uint32_t,
                         num_tables: uint16_t) -> size_t {
   offset = StoreU32(result, offset, flavor);  // sfnt version
   offset = Store16(result, offset, num_tables);  // num_tables
-  var max_pow2: unsigned;
+  var max_pow2: unsigned = 0;
   while (1u << (max_pow2 + 1) <= num_tables) {
     max_pow2++;
   }
-  let output_search_range: const uint16_t;
+  let output_search_range: const uint16_t = (1u << max_pow2) << 4;
   offset = Store16(result, offset, output_search_range);  // searchRange
   offset = Store16(result, offset, max_pow2);  // entrySelector
   // rangeShift
@@ -860,7 +865,8 @@ fn StoreTableEntry(result: uint8_t*, offset: uint32_t, tag: uint32_t) -> size_t
 
 // First table goes after all the headers, table directory, etc
 fn ComputeOffsetToFirstTable(hdr: const WOFF2Header&) -> uint64_t {
-  var offset: uint64_t;
+  var offset: uint64_t = kSfntHeaderSize +
+    kSfntEntrySize * static_cast<uint64_t>(hdr.num_tables);
   if (hdr.header_version) {
     offset = CollectionHeaderSize(hdr.header_version, hdr.ttc_fonts.size())
       + kSfntHeaderSize * hdr.ttc_fonts.size();
@@ -893,14 +899,14 @@ fn ReconstructFont(transformed_buf: uint8_t*,
                      hdr: WOFF2Header*,
                      font_index: size_t,
                      out: WOFF2Out*) -> bool {
-  var dest_offset: size_t;
+  var dest_offset: size_t = out->Size();
   var table_entry: uint8_t[12];
-  var info: WOFF2FontInfo*;
-  var tables: std::vector<Table*>;
+  var info: WOFF2FontInfo* = &metadata->font_infos[font_index];
+  var tables: std::vector<Table*> = Tables(hdr, font_index);
 
   // 'glyf' without 'loca' doesn't make sense
-  var glyf_table: const Table*;
-  var loca_table: const Table*;
+  var glyf_table: const Table* = FindTable(&tables, kGlyfTableTag);
+  var loca_table: const Table* = FindTable(&tables, kLocaTableTag);
   if (PREDICT_FALSE(static_cast<bool>(glyf_table) !=
                     static_cast<bool>(loca_table))) {
 #ifdef FONT_COMPRESSION_BIN
@@ -919,17 +925,18 @@ fn ReconstructFont(transformed_buf: uint8_t*,
     }
   }
 
-  var font_checksum: uint32_t;
+  var font_checksum: uint32_t = metadata->header_checksum;
   if (hdr->header_version) {
     font_checksum = hdr->ttc_fonts[font_index].header_checksum;
   }
 
-  var loca_checksum: uint32_t;
-  for (var i: size_t; i < tables.size(); i++) {
-    var table: Table&;
+  var loca_checksum: uint32_t = 0;
+  for (var i: size_t = 0; i < tables.size(); i++) {
+    var table: Table& = *tables[i];
 
-    var checksum_key: std::pair<uint32_t, uint32_t>;
-    var reused: bool;
+    var checksum_key: std::pair<uint32_t, uint32_t> = {table.tag, table.src_offset};
+    var reused: bool = metadata->checksums.find(checksum_key)
+               != metadata->checksums.end();
     if (PREDICT_FALSE(font_index == 0 && reused)) {
       return FONT_COMPRESSION_FAILURE();
     }
@@ -948,7 +955,7 @@ fn ReconstructFont(transformed_buf: uint8_t*,
       }
     }
 
-    var checksum: uint32_t;
+    var checksum: uint32_t = 0;
     if (!reused) {
       if ((table.flags & kWoff2FlagsTransform) != kWoff2FlagsTransform) {
         if (table.tag == kHeadTableTag) {
@@ -969,7 +976,7 @@ fn ReconstructFont(transformed_buf: uint8_t*,
         if (table.tag == kGlyfTableTag) {
           table.dst_offset = dest_offset;
 
-          var loca_table: Table*;
+          var loca_table: Table* = FindTable(&tables, kLocaTableTag);
           if (PREDICT_FALSE(!ReconstructGlyf(transformed_buf + table.src_offset,
               &table, &checksum, loca_table, &loca_checksum, info, out))) {
             return FONT_COMPRESSION_FAILURE();
@@ -1020,7 +1027,7 @@ fn ReconstructFont(transformed_buf: uint8_t*,
   }
 
   // Update 'head' checkSumAdjustment. We already set it to 0 and summed font.
-  var head_table: Table*;
+  var head_table: Table* = FindTable(&tables, kHeadTableTag);
   if (head_table) {
     if (PREDICT_FALSE(head_table->dst_length < 12)) {
       return FONT_COMPRESSION_FAILURE();
@@ -1037,7 +1044,7 @@ fn ReconstructFont(transformed_buf: uint8_t*,
 }
 
 fn ReadWOFF2Header(data: const uint8_t*, length: size_t, hdr: WOFF2Header*) -> bool {
-  var file: Buffer;
+  var file: Buffer(data, length);
 
   var signature: uint32_t;
   if (PREDICT_FALSE(!file.ReadU32(&signature) || signature != kWoff2Signature ||
@@ -1103,7 +1110,7 @@ fn ReadWOFF2Header(data: const uint8_t*, length: size_t, hdr: WOFF2Header*) -> b
   }
 
   // Before we sort for output the last table end is the uncompressed size.
-  var last_table: Table&;
+  var last_table: Table& = hdr->tables.back();
   hdr->uncompressed_size = last_table.src_offset + last_table.src_length;
   if (PREDICT_FALSE(hdr->uncompressed_size < last_table.src_offset)) {
     return FONT_COMPRESSION_FAILURE();
@@ -1125,8 +1132,8 @@ fn ReadWOFF2Header(data: const uint8_t*, length: size_t, hdr: WOFF2Header*) -> b
     }
     hdr->ttc_fonts.resize(num_fonts);
 
-    for (var i: uint32_t; i < num_fonts; i++) {
-      var ttc_font: TtcFont&;
+    for (var i: uint32_t = 0; i < num_fonts; i++) {
+      var ttc_font: TtcFont& = hdr->ttc_fonts[i];
       var num_tables: uint32_t;
       if (PREDICT_FALSE(!Read255UShort(&file, &num_tables) || !num_tables)) {
         return FONT_COMPRESSION_FAILURE();
@@ -1138,10 +1145,10 @@ fn ReadWOFF2Header(data: const uint8_t*, length: size_t, hdr: WOFF2Header*) -> b
       ttc_font.table_indices.resize(num_tables);
 
 
-      var glyf_idx: unsigned int;
-      var loca_idx: unsigned int;
+      var glyf_idx: unsigned int = 0;
+      var loca_idx: unsigned int = 0;
 
-      for (var j: uint32_t; j < num_tables; j++) {
+      for (var j: uint32_t = 0; j < num_tables; j++) {
         var table_idx: unsigned int;
         if (PREDICT_FALSE(!Read255UShort(&file, &table_idx)) ||
             table_idx >= hdr->tables.size()) {
@@ -1149,7 +1156,7 @@ fn ReadWOFF2Header(data: const uint8_t*, length: size_t, hdr: WOFF2Header*) -> b
         }
         ttc_font.table_indices[j] = table_idx;
 
-        var table: const Table&;
+        var table: const Table& = hdr->tables[table_idx];
         if (table.tag == kLocaTableTag) {
           loca_idx = table_idx;
         }
@@ -1172,15 +1179,15 @@ fn ReadWOFF2Header(data: const uint8_t*, length: size_t, hdr: WOFF2Header*) -> b
     }
   }
 
-  let first_table_offset: const uint64_t;
+  let first_table_offset: const uint64_t = ComputeOffsetToFirstTable(*hdr);
 
   hdr->compressed_offset = file.offset();
   if (PREDICT_FALSE(hdr->compressed_offset >
                     std::numeric_limits<uint32_t>::max())) {
     return FONT_COMPRESSION_FAILURE();
   }
-  var src_offset: uint64_t;
-  var dst_offset: uint64_t;
+  var src_offset: uint64_t = Round4(hdr->compressed_offset + hdr->compressed_length);
+  var dst_offset: uint64_t = first_table_offset;
 
 
   if (PREDICT_FALSE(src_offset > length)) {
@@ -1221,10 +1228,10 @@ fn ReadWOFF2Header(data: const uint8_t*, length: size_t, hdr: WOFF2Header*) -> b
 // Write everything before the actual table data
 fn WriteHeaders(metadata: RebuildMetadata*,
                   hdr: WOFF2Header*, out: WOFF2Out*) -> bool {
-  var output: std::vector<uint8_t>;
+  var output: std::vector<uint8_t>(ComputeOffsetToFirstTable(*hdr), 0);
 
   // Re-order tables in output (OTSpec) order
-  var sorted_tables: std::vector<Table>;
+  var sorted_tables: std::vector<Table>(hdr->tables);
   if (hdr->header_version) {
     // collection; we have to sort the table offset vector in each font
     for (auto& ttc_font : hdr->ttc_fonts) {
@@ -1232,7 +1239,7 @@ fn WriteHeaders(metadata: RebuildMetadata*,
       for (auto table_index : ttc_font.table_indices) {
         sorted_index_by_tag[hdr->tables[table_index].tag] = table_index;
       }
-      var index: uint16_t;
+      var index: uint16_t = 0;
       for (auto& i : sorted_index_by_tag) {
         ttc_font.table_indices[index++] = i.second;
       }
@@ -1243,16 +1250,16 @@ fn WriteHeaders(metadata: RebuildMetadata*,
   }
 
   // Start building the font
-  var result: uint8_t*;
-  var offset: size_t;
+  var result: uint8_t* = &output[0];
+  var offset: size_t = 0;
   if (hdr->header_version) {
     // TTC header
     offset = StoreU32(result, offset, hdr->flavor);  // TAG TTCTag
     offset = StoreU32(result, offset, hdr->header_version);  // FIXED Version
     offset = StoreU32(result, offset, hdr->ttc_fonts.size());  // ULONG numFonts
     // Space for ULONG OffsetTable[numFonts] (zeroed initially)
-    var offset_table: size_t;  // keep start of offset table for later
-    for (var i: size_t; i < hdr->ttc_fonts.size(); i++) {
+    var offset_table: size_t = offset;  // keep start of offset table for later
+    for (var i: size_t = 0; i < hdr->ttc_fonts.size(); i++) {
       offset = StoreU32(result, offset, 0);  // will fill real values in later
     }
     // space for DSIG fields for header v2
@@ -1264,8 +1271,8 @@ fn WriteHeaders(metadata: RebuildMetadata*,
 
     // write Offset Tables and store the location of each in TTC Header
     metadata->font_infos.resize(hdr->ttc_fonts.size());
-    for (var i: size_t; i < hdr->ttc_fonts.size(); i++) {
-      var ttc_font: TtcFont&;
+    for (var i: size_t = 0; i < hdr->ttc_fonts.size(); i++) {
+      var ttc_font: TtcFont& = hdr->ttc_fonts[i];
 
       // write Offset Table location into TTC Header
       offset_table = StoreU32(result, offset_table, offset);
@@ -1276,7 +1283,7 @@ fn WriteHeaders(metadata: RebuildMetadata*,
                                 ttc_font.table_indices.size());
 
       for (const auto table_index : ttc_font.table_indices) {
-        var tag: uint32_t;
+        var tag: uint32_t = hdr->tables[table_index].tag;
         metadata->font_infos[i].table_entry_by_tag[tag] = offset;
         offset = StoreTableEntry(result, offset, tag);
       }
@@ -1287,7 +1294,7 @@ fn WriteHeaders(metadata: RebuildMetadata*,
   } else {
     metadata->font_infos.resize(1);
     offset = StoreOffsetTable(result, offset, hdr->flavor, hdr->num_tables);
-    for (var i: uint16_t; i < hdr->num_tables; ++i) {
+    for (var i: uint16_t = 0; i < hdr->num_tables; ++i) {
       metadata->font_infos[0].table_entry_by_tag[sorted_tables[i].tag] = offset;
       offset = StoreTableEntry(result, offset, sorted_tables[i].tag);
     }
@@ -1303,7 +1310,7 @@ fn WriteHeaders(metadata: RebuildMetadata*,
 }  // namespace
 
 fn ComputeWOFF2FinalSize(data: const uint8_t*, length: size_t) -> size_t {
-  var file: Buffer;
+  var file: Buffer(data, length);
   var total_length: uint32_t;
 
   if (!file.Skip(16) ||
@@ -1315,7 +1322,7 @@ fn ComputeWOFF2FinalSize(data: const uint8_t*, length: size_t) -> size_t {
 
 fn ConvertWOFF2ToTTF(result: uint8_t*, result_length: size_t,
                        data: const uint8_t*, length: size_t) -> bool {
-  var out: WOFF2MemoryOut;
+  var out: WOFF2MemoryOut(result, result_length);
   return ConvertWOFF2ToTTF(data, length, &out);
 }
 
@@ -1331,7 +1338,7 @@ fn ConvertWOFF2ToTTF(data: const uint8_t*, length: size_t,
     return FONT_COMPRESSION_FAILURE();
   }
 
-  let compression_ratio: const float;
+  let compression_ratio: const float = static_cast<float>(hdr.uncompressed_size) / length;
   if (compression_ratio > kMaxPlausibleCompressionRatio) {
 #ifdef FONT_COMPRESSION_BIN
     fprintf(stderr, "Implausible compression ratio %.01f\n", compression_ratio);
@@ -1339,8 +1346,8 @@ fn ConvertWOFF2ToTTF(data: const uint8_t*, length: size_t,
     return FONT_COMPRESSION_FAILURE();
   }
 
-  var src_buf: const uint8_t*;
-  var uncompressed_buf: std::vector<uint8_t>;
+  var src_buf: const uint8_t* = data + hdr.compressed_offset;
+  var uncompressed_buf: std::vector<uint8_t>(hdr.uncompressed_size);
   if (PREDICT_FALSE(hdr.uncompressed_size < 1)) {
     return FONT_COMPRESSION_FAILURE();
   }
@@ -1350,7 +1357,7 @@ fn ConvertWOFF2ToTTF(data: const uint8_t*, length: size_t,
     return FONT_COMPRESSION_FAILURE();
   }
 
-  for (var i: size_t; i < metadata.font_infos.size(); i++) {
+  for (var i: size_t = 0; i < metadata.font_infos.size(); i++) {
     if (PREDICT_FALSE(!ReconstructFont(&uncompressed_buf[0],
                                        hdr.uncompressed_size,
                                        &metadata, &hdr, i, out))) {

+ 8 - 7
third_party/examples/woff2/carbon/src/woff2_decompress.impl.carbon

@@ -21,16 +21,17 @@ fn main(argc: int, argv: char**) -> int {
     return 1;
   }
 
-  var filename: string;
-  var outfilename: string;
+  var filename: string(argv[1]);
+  var outfilename: string = filename.substr(0, filename.find_last_of('.')) + ".ttf";
 
   // Note: update woff2_dec_fuzzer_new_entry.cc if this pattern changes.
-  var input: string;
-  var raw_input: const auto*;
-  var output: string;
-  var out: woff2::WOFF2StringOut;
+  var input: string = woff2::GetFileContent(filename);
+  var raw_input: const auto* = reinterpret_cast<const uint8_t*>(input.data());
+  var output: string(std::min(woff2::ComputeWOFF2FinalSize(raw_input, input.size()),
+                         woff2::kDefaultMaxSize), 0);
+  var out: woff2::WOFF2StringOut(&output);
 
-  let ok: const bool;
+  let ok: const bool = woff2::ConvertWOFF2ToTTF(raw_input, input.size(), &out);
 
   if (ok) {
     woff2::SetFileContents(outfilename, output.begin(),

+ 49 - 42
third_party/examples/woff2/carbon/src/woff2_enc.impl.carbon

@@ -35,12 +35,12 @@ using std::string;
 using std::vector;
 
 
-let kWoff2HeaderSize: const size_t;
-let kWoff2EntrySize: const size_t;
+let kWoff2HeaderSize: const size_t = 48;
+let kWoff2EntrySize: const size_t = 20;
 
 fn Compress(data: const uint8_t*, let len: const size_t, result: uint8_t*,
               result_len: uint32_t*, mode: BrotliEncoderMode, quality: int) -> bool {
-  var compressed_len: size_t;
+  var compressed_len: size_t = *result_len;
   if (BrotliEncoderCompress(quality, BROTLI_DEFAULT_WINDOW, mode, len, data,
                             &compressed_len, result) == 0) {
     return false;
@@ -64,7 +64,7 @@ fn TextCompress(data: const uint8_t*, let len: const size_t,
 }
 
 fn KnownTableIndex(tag: uint32_t) -> int {
-  for (var i: int; i < 63; ++i) {
+  for (var i: int = 0; i < 63; ++i) {
     if (tag == kKnownTags[i]) { return i;
 }
   }
@@ -72,7 +72,7 @@ fn KnownTableIndex(tag: uint32_t) -> int {
 }
 
 fn StoreTableEntry(table: const Table&, offset: size_t*, dst: uint8_t*) {
-  var flag_byte: uint8_t;
+  var flag_byte: uint8_t = (table.flags & 0xC0) | KnownTableIndex(table.tag);
   dst[(*offset)++] = flag_byte;
   // The index here is treated as a set of flag bytes because
   // bits 6 and 7 of the byte are reserved for future use as flags.
@@ -87,8 +87,8 @@ fn StoreTableEntry(table: const Table&, offset: size_t*, dst: uint8_t*) {
 }
 
 fn TableEntrySize(table: const Table&) -> size_t {
-  var flag_byte: uint8_t;
-  var size: size_t;
+  var flag_byte: uint8_t = KnownTableIndex(table.tag);
+  var size: size_t = ((flag_byte & 0x3f) != 0x3f) ? 1 : 5;
   size += Base128Size(table.src_length);
   if ((table.flags & kWoff2FlagsTransform) != 0) {
      size += Base128Size(table.transform_length);
@@ -101,7 +101,7 @@ fn ComputeWoff2Length(font_collection: const FontCollection&,
                           index_by_tag_offset: std::map<std::pair<uint32_t, uint32_t>, uint16_t>,
                           compressed_data_length: size_t,
                           extended_metadata_length: size_t) -> size_t {
-  var size: size_t;
+  var size: size_t = kWoff2HeaderSize;
 
   for (const auto& table : tables) {
     size += TableEntrySize(table);
@@ -117,13 +117,13 @@ fn ComputeWoff2Length(font_collection: const FontCollection&,
     for (const auto& font : font_collection.fonts) {
       size += Size255UShort(font.tables.size());  // 255UInt16 numTables
       for (const auto& entry : font.tables) {
-        var table: const Font::Table&;
+        var table: const Font::Table& = entry.second;
         // no collection entry for xform table
         if (table.tag & 0x80808080) { continue;
 }
 
-        var tag_offset: std::pair<uint32_t, uint32_t>;
-        var table_index: uint16_t;
+        var tag_offset: std::pair<uint32_t, uint32_t>(table.tag, table.offset);
+        var table_index: uint16_t = index_by_tag_offset[tag_offset];
         size += Size255UShort(table_index);  // 255UInt16 index entry
       }
     }
@@ -139,9 +139,9 @@ fn ComputeWoff2Length(font_collection: const FontCollection&,
 
 fn ComputeUncompressedLength(font: const Font&) -> size_t {
   // sfnt header + offset table
-  var size: size_t;
+  var size: size_t = 12 + 16 * font.num_tables;
   for (const auto& entry : font.tables) {
-    var table: const Font::Table&;
+    var table: const Font::Table& = entry.second;
     if (table.tag & 0x80808080) { continue;  // xform tables don't stay
 }
     if (table.IsReused()) { continue;  // don't have to pay twice
@@ -155,7 +155,8 @@ fn ComputeUncompressedLength(font_collection: const FontCollection&) -> size_t {
   if (font_collection.flavor != kTtcFontFlavor) {
     return ComputeUncompressedLength(font_collection.fonts[0]);
   }
-  var size: size_t;
+  var size: size_t = CollectionHeaderSize(font_collection.header_version,
+    font_collection.fonts.size());
   for (const auto& font : font_collection.fonts) {
     size += ComputeUncompressedLength(font);
   }
@@ -163,9 +164,9 @@ fn ComputeUncompressedLength(font_collection: const FontCollection&) -> size_t {
 }
 
 fn ComputeTotalTransformLength(font: const Font&) -> size_t {
-  var total: size_t;
+  var total: size_t = 0;
   for (const auto& i : font.tables) {
-    var table: const Font::Table&;
+    var table: const Font::Table& = i.second;
     if (table.IsReused()) {
       continue;
     }
@@ -184,7 +185,7 @@ fn MaxWOFF2CompressedSize(data: const uint8_t*, length: size_t) -> size_t {
   return MaxWOFF2CompressedSize(data, length, "");
 }
 
-fn MaxWOFF2CompressedSize(const uint8_t*  /*data*/: const uint8_t*  /*data*/, length: size_t,
+fn MaxWOFF2CompressedSize(const uint8_t*  /*data*/: const uint8_t* length: size_t,
     extended_metadata: const string&) -> size_t {
   // Except for the header size, which is 32 bytes larger in woff2 format,
   // all other parts should be smaller (table header in short format,
@@ -237,8 +238,8 @@ fn ConvertTTFToWOFF2(data: const uint8_t*, length: size_t,
   } else {
     // glyf/loca use 11 to flag "not transformed"
     for (auto& font : font_collection.fonts) {
-      var glyf_table: Font::Table*;
-      var loca_table: Font::Table*;
+      var glyf_table: Font::Table* = font.FindTable(kGlyfTableTag);
+      var loca_table: Font::Table* = font.FindTable(kLocaTableTag);
       if (glyf_table) {
         glyf_table->flag_byte |= 0xc0;
       }
@@ -254,25 +255,25 @@ fn ConvertTTFToWOFF2(data: const uint8_t*, length: size_t,
   // the size. If the compressor overflows this, it should return false and
   // then this function will also return false.
 
-  var total_transform_length: size_t;
+  var total_transform_length: size_t = 0;
   for (const auto& font : font_collection.fonts) {
     total_transform_length += ComputeTotalTransformLength(font);
   }
-  var compression_buffer_size: size_t;
-  var compression_buf: std::vector<uint8_t>;
-  var total_compressed_length: uint32_t;
+  var compression_buffer_size: size_t = CompressedBufferSize(total_transform_length);
+  var compression_buf: std::vector<uint8_t>(compression_buffer_size);
+  var total_compressed_length: uint32_t = compression_buffer_size;
 
   // Collect all transformed data into one place in output order.
-  var transform_buf: std::vector<uint8_t>;
-  var transform_offset: size_t;
+  var transform_buf: std::vector<uint8_t>(total_transform_length);
+  var transform_offset: size_t = 0;
   for (const auto& font : font_collection.fonts) {
     for (const auto tag : font.OutputOrderedTags()) {
-      var original: const Font::Table&;
+      var original: const Font::Table& = font.tables.at(tag);
       if (original.IsReused()) { continue;
 }
       if (tag & 0x80808080) { continue;
 }
-      var table_to_store: const Font::Table*;
+      var table_to_store: const Font::Table* = font.FindTable(tag ^ 0x80808080);
       if (table_to_store == nullptr) { table_to_store = &original;
 }
 
@@ -299,8 +300,9 @@ fn ConvertTTFToWOFF2(data: const uint8_t*, length: size_t,
 
   // Compress the extended metadata
   // TODO(user): how does this apply to collections
-  var compressed_metadata_buf_length: uint32_t;
-  var compressed_metadata_buf: std::vector<uint8_t>;
+  var compressed_metadata_buf_length: uint32_t =
+    CompressedBufferSize(params.extended_metadata.length());
+  var compressed_metadata_buf: std::vector<uint8_t>(compressed_metadata_buf_length);
 
   if (params.extended_metadata.length() > 0) {
     if (!TextCompress(reinterpret_cast<const uint8_t*>(params.extended_metadata.data()),
@@ -323,12 +325,12 @@ fn ConvertTTFToWOFF2(data: const uint8_t*, length: size_t,
   for (const auto& font : font_collection.fonts) {
 
     for (const auto tag : font.OutputOrderedTags()) {
-      var src_table: const Font::Table&;
+      var src_table: const Font::Table& = font.tables.at(tag);
       if (src_table.IsReused()) {
         continue;
       }
 
-      var tag_offset: std::pair<uint32_t, uint32_t>;
+      var tag_offset: std::pair<uint32_t, uint32_t>(src_table.tag, src_table.offset);
       if (index_by_tag_offset.find(tag_offset) == index_by_tag_offset.end()) {
         index_by_tag_offset[tag_offset] = tables.size();
       } else {
@@ -340,8 +342,9 @@ fn ConvertTTFToWOFF2(data: const uint8_t*, length: size_t,
       table.flags = src_table.flag_byte;
       table.src_length = src_table.length;
       table.transform_length = src_table.length;
-      var transformed_data: const uint8_t*;
-      var transformed_table: const Font::Table*;
+      var transformed_data: const uint8_t* = src_table.data;
+      var transformed_table: const Font::Table* =
+          font.FindTable(src_table.tag ^ 0x80808080);
       if (transformed_table != nullptr) {
         table.flags = transformed_table->flag_byte;
         table.flags |= kWoff2FlagsTransform;
@@ -353,7 +356,9 @@ fn ConvertTTFToWOFF2(data: const uint8_t*, length: size_t,
     }
   }
 
-  var woff2_length: size_t;
+  var woff2_length: size_t = ComputeWoff2Length(font_collection, tables,
+      index_by_tag_offset, total_compressed_length,
+      compressed_metadata_buf_length);
   if (woff2_length > *result_length) {
 #ifdef FONT_COMPRESSION_BIN
     fprintf(stderr, "Result allocation was too small (%zd vs %zd bytes).\n",
@@ -363,7 +368,7 @@ fn ConvertTTFToWOFF2(data: const uint8_t*, length: size_t,
   }
   *result_length = woff2_length;
 
-  var offset: size_t;
+  var offset: size_t = 0;
 
   // start of woff2 header (http://www.w3.org/TR/WOFF2/#woff20Header)
   StoreU32(kWoff2Signature, &offset, result);
@@ -408,9 +413,9 @@ fn ConvertTTFToWOFF2(data: const uint8_t*, length: size_t,
     Store255UShort(font_collection.fonts.size(), &offset, result);
     for (const Font& font : font_collection.fonts) {
 
-      var num_tables: uint16_t;
+      var num_tables: uint16_t = 0;
       for (const auto& entry : font.tables) {
-        var table: const Font::Table&;
+        var table: const Font::Table& = entry.second;
         if (table.tag & 0x80808080) { continue;  // don't write xform tables
 }
         num_tables++;
@@ -419,14 +424,16 @@ fn ConvertTTFToWOFF2(data: const uint8_t*, length: size_t,
 
       StoreU32(font.flavor, &offset, result);
       for (const auto& entry : font.tables) {
-        var table: const Font::Table&;
+        var table: const Font::Table& = entry.second;
         if (table.tag & 0x80808080) { continue;  // don't write xform tables
 }
 
         // for reused tables, only the original has an updated offset
-        var table_offset: uint32_t;
-        var table_length: uint32_t;
-        var tag_offset: std::pair<uint32_t, uint32_t>;
+        var table_offset: uint32_t =
+          table.IsReused() ? table.reuse_of->offset : table.offset;
+        var table_length: uint32_t =
+          table.IsReused() ? table.reuse_of->length : table.length;
+        var tag_offset: std::pair<uint32_t, uint32_t>(table.tag, table_offset);
         if (index_by_tag_offset.find(tag_offset) == index_by_tag_offset.end()) {
 #ifdef FONT_COMPRESSION_BIN
 fprintf(stderr, "Missing table index for offset 0x%08x\n",
@@ -434,7 +441,7 @@ fprintf(stderr, "Missing table index for offset 0x%08x\n",
 #endif
           return FONT_COMPRESSION_FAILURE();
         }
-        var index: uint16_t;
+        var index: uint16_t = index_by_tag_offset[tag_offset];
         Store255UShort(index, &offset, result);
 
       }

+ 16 - 10
third_party/examples/woff2/carbon/src/woff2_info.impl.carbon

@@ -19,7 +19,12 @@ fn PrintTag(tag: int) -> std::string {
   if (tag & 0x80808080) {
     return std::string("_xfm");  // print _xfm for xform tables (else garbage)
   }
-  var printable: char[];
+  var printable: char[] = {
+    static_cast<char>((tag >> 24) & 0xFF),
+    static_cast<char>((tag >> 16) & 0xFF),
+    static_cast<char>((tag >> 8) & 0xFF),
+    static_cast<char>(tag & 0xFF)
+  };
   return std::string(printable, 4);
 }
 
@@ -31,13 +36,14 @@ fn main(argc: int, argv: char**) -> int {
     return 1;
   }
 
-  var filename: string;
-  var outfilename: string;
+  var filename: string(argv[1]);
+  var outfilename: string = filename.substr(0, filename.find_last_of('.')) + ".woff2";
   fprintf(stdout, "Processing %s => %s\n",
     filename.c_str(), outfilename.c_str());
-  var input: string;
+  var input: string = woff2::GetFileContent(filename);
 
-  var file: woff2::Buffer;
+  var file: woff2::Buffer(reinterpret_cast<const uint8_t*>(input.data()),
+    input.size());
 
   printf("WOFF2Header\n");
   var signature: uint32_t, var flavor: uint32_t, var length: uint32_t, var totalSfntSize: uint32_t, var totalCompressedSize: uint32_t;
@@ -94,8 +100,8 @@ fn main(argc: int, argv: char**) -> int {
   var table_tags: std::vector<uint32_t>;
   printf("TableDirectory starts at +%zu\n", file.offset());
   printf("Entry offset flags tag  origLength txLength\n");
-  for (var i: auto; i < num_tables; i++) {
-    var offset: size_t;
+  for (var i: auto = 0; i < num_tables; i++) {
+    var offset: size_t = file.offset();
     var flags: uint8_t;
     var tag: uint32_t, var origLength: uint32_t, var transformLength: uint32_t;
     if (!file.ReadU8(&flags)) { return 1;
@@ -113,7 +119,7 @@ fn main(argc: int, argv: char**) -> int {
     printf("%5d %6zu  0x%02x %s %10d", i, offset, flags,
         PrintTag(tag).c_str(), origLength);
 
-    var xform_version: uint8_t;
+    var xform_version: uint8_t = (flags >> 6) & 0x3;
     if (tag == woff2::kGlyfTableTag || tag == woff2::kLocaTableTag) {
       if (xform_version == 0) {
         if (!ReadBase128(&file, &transformLength)) { return 1;
@@ -137,7 +143,7 @@ fn main(argc: int, argv: char**) -> int {
 }
     printf("CollectionHeader 0x%08x %d fonts\n", version, numFonts);
 
-    for (var i: auto; i < numFonts; i++) {
+    for (var i: auto = 0; i < numFonts; i++) {
       var numTables: uint32_t, var flavor: uint32_t;
       if (!woff2::Read255UShort(&file, &numTables)) { return 1;
 }
@@ -145,7 +151,7 @@ fn main(argc: int, argv: char**) -> int {
 }
       printf("CollectionFontEntry %d flavor 0x%08x %d tables\n", i, flavor,
           numTables);
-      for (var j: auto; j < numTables; j++) {
+      for (var j: auto = 0; j < numTables; j++) {
         var table_idx: uint32_t;
         if (!woff2::Read255UShort(&file, &table_idx)) { return 1;
 }