Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2009 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2009 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "ots.h" | 5 #include "ots.h" |
| 6 | 6 |
| 7 #include <sys/types.h> | 7 #include <sys/types.h> |
| 8 #include <zlib.h> | 8 #include <zlib.h> |
| 9 | 9 |
| 10 #include <algorithm> | 10 #include <algorithm> |
| (...skipping 16 matching lines...) Expand all Loading... | |
| 27 uint32_t length; | 27 uint32_t length; |
| 28 uint32_t uncompressed_length; | 28 uint32_t uncompressed_length; |
| 29 }; | 29 }; |
| 30 | 30 |
| 31 // Round a value up to the nearest multiple of 4. Note that this can overflow | 31 // Round a value up to the nearest multiple of 4. Note that this can overflow |
| 32 // and return zero. | 32 // and return zero. |
| 33 template<typename T> T Round4(T value) { | 33 template<typename T> T Round4(T value) { |
| 34 return (value + 3) & ~3; | 34 return (value + 3) & ~3; |
| 35 } | 35 } |
| 36 | 36 |
| 37 uint32_t Tag(const char *tag_str) { | |
| 38 uint32_t ret; | |
| 39 std::memcpy(&ret, tag_str, 4); | |
| 40 return ret; | |
| 41 } | |
| 42 | |
| 43 bool CheckTag(uint32_t tag_value) { | 37 bool CheckTag(uint32_t tag_value) { |
| 44 for (unsigned i = 0; i < 4; ++i) { | 38 for (unsigned i = 0; i < 4; ++i) { |
| 45 const uint32_t check = tag_value & 0xff; | 39 const uint32_t check = tag_value & 0xff; |
| 46 if (check < 32 || check > 126) { | 40 if (check < 32 || check > 126) { |
| 47 return false; // non-ASCII character found. | 41 return false; // non-ASCII character found. |
| 48 } | 42 } |
| 49 tag_value >>= 8; | 43 tag_value >>= 8; |
| 50 } | 44 } |
| 51 return true; | 45 return true; |
| 52 } | 46 } |
| (...skipping 23 matching lines...) Expand all Loading... | |
| 76 uint8_t* Allocate(size_t length) { | 70 uint8_t* Allocate(size_t length) { |
| 77 uint8_t* p = new uint8_t[length]; | 71 uint8_t* p = new uint8_t[length]; |
| 78 hunks_.push_back(p); | 72 hunks_.push_back(p); |
| 79 return p; | 73 return p; |
| 80 } | 74 } |
| 81 | 75 |
| 82 private: | 76 private: |
| 83 std::vector<uint8_t*> hunks_; | 77 std::vector<uint8_t*> hunks_; |
| 84 }; | 78 }; |
| 85 | 79 |
| 80 // Use a macro instead of a function because gcc 4.4.3 creates static | |
| 81 // initializers in that case. Note this macro assumes a little-endian system. | |
| 82 #define TAG(a, b, c, d) (a | (b << 8) | (c << 16) | (d << 24)) | |
| 83 | |
| 86 const struct { | 84 const struct { |
| 87 uint32_t tag; | 85 uint32_t tag; |
| 88 bool (*parse)(ots::OpenTypeFile *otf, const uint8_t *data, size_t length); | 86 bool (*parse)(ots::OpenTypeFile *otf, const uint8_t *data, size_t length); |
| 89 bool (*serialise)(ots::OTSStream *out, ots::OpenTypeFile *file); | 87 bool (*serialise)(ots::OTSStream *out, ots::OpenTypeFile *file); |
| 90 bool (*should_serialise)(ots::OpenTypeFile *file); | 88 bool (*should_serialise)(ots::OpenTypeFile *file); |
| 91 void (*free)(ots::OpenTypeFile *file); | 89 void (*free)(ots::OpenTypeFile *file); |
| 92 bool required; | 90 bool required; |
| 93 } table_parsers[] = { | 91 } table_parsers[] = { |
| 94 { Tag("maxp"), ots::ots_maxp_parse, ots::ots_maxp_serialise, | 92 { TAG('m', 'a', 'x', 'p'), ots::ots_maxp_parse, ots::ots_maxp_serialise, |
| 95 ots::ots_maxp_should_serialise, ots::ots_maxp_free, true }, | 93 ots::ots_maxp_should_serialise, ots::ots_maxp_free, true }, |
| 96 { Tag("head"), ots::ots_head_parse, ots::ots_head_serialise, | 94 { TAG('h', 'e', 'a', 'd'), ots::ots_head_parse, ots::ots_head_serialise, |
| 97 ots::ots_head_should_serialise, ots::ots_head_free, true }, | 95 ots::ots_head_should_serialise, ots::ots_head_free, true }, |
| 98 { Tag("OS/2"), ots::ots_os2_parse, ots::ots_os2_serialise, | 96 { TAG('O', 'S', '/', '2'), ots::ots_os2_parse, ots::ots_os2_serialise, |
| 99 ots::ots_os2_should_serialise, ots::ots_os2_free, true }, | 97 ots::ots_os2_should_serialise, ots::ots_os2_free, true }, |
| 100 { Tag("cmap"), ots::ots_cmap_parse, ots::ots_cmap_serialise, | 98 { TAG('c', 'm', 'a', 'p'), ots::ots_cmap_parse, ots::ots_cmap_serialise, |
| 101 ots::ots_cmap_should_serialise, ots::ots_cmap_free, true }, | 99 ots::ots_cmap_should_serialise, ots::ots_cmap_free, true }, |
| 102 { Tag("hhea"), ots::ots_hhea_parse, ots::ots_hhea_serialise, | 100 { TAG('h', 'h', 'e', 'a'), ots::ots_hhea_parse, ots::ots_hhea_serialise, |
| 103 ots::ots_hhea_should_serialise, ots::ots_hhea_free, true }, | 101 ots::ots_hhea_should_serialise, ots::ots_hhea_free, true }, |
| 104 { Tag("hmtx"), ots::ots_hmtx_parse, ots::ots_hmtx_serialise, | 102 { TAG('h', 'm', 't', 'x'), ots::ots_hmtx_parse, ots::ots_hmtx_serialise, |
| 105 ots::ots_hmtx_should_serialise, ots::ots_hmtx_free, true }, | 103 ots::ots_hmtx_should_serialise, ots::ots_hmtx_free, true }, |
| 106 { Tag("name"), ots::ots_name_parse, ots::ots_name_serialise, | 104 { TAG('n', 'a', 'm', 'e'), ots::ots_name_parse, ots::ots_name_serialise, |
| 107 ots::ots_name_should_serialise, ots::ots_name_free, true }, | 105 ots::ots_name_should_serialise, ots::ots_name_free, true }, |
| 108 { Tag("post"), ots::ots_post_parse, ots::ots_post_serialise, | 106 { TAG('p', 'o', 's', 't'), ots::ots_post_parse, ots::ots_post_serialise, |
| 109 ots::ots_post_should_serialise, ots::ots_post_free, true }, | 107 ots::ots_post_should_serialise, ots::ots_post_free, true }, |
| 110 { Tag("loca"), ots::ots_loca_parse, ots::ots_loca_serialise, | 108 { TAG('l', 'o', 'c', 'a'), ots::ots_loca_parse, ots::ots_loca_serialise, |
| 111 ots::ots_loca_should_serialise, ots::ots_loca_free, false }, | 109 ots::ots_loca_should_serialise, ots::ots_loca_free, false }, |
| 112 { Tag("glyf"), ots::ots_glyf_parse, ots::ots_glyf_serialise, | 110 { TAG('g', 'l', 'y', 'f'), ots::ots_glyf_parse, ots::ots_glyf_serialise, |
| 113 ots::ots_glyf_should_serialise, ots::ots_glyf_free, false }, | 111 ots::ots_glyf_should_serialise, ots::ots_glyf_free, false }, |
| 114 { Tag("CFF "), ots::ots_cff_parse, ots::ots_cff_serialise, | 112 { TAG('C', 'F', 'F', ' '), ots::ots_cff_parse, ots::ots_cff_serialise, |
| 115 ots::ots_cff_should_serialise, ots::ots_cff_free, false }, | 113 ots::ots_cff_should_serialise, ots::ots_cff_free, false }, |
| 116 { Tag("VDMX"), ots::ots_vdmx_parse, ots::ots_vdmx_serialise, | 114 { TAG('V', 'D', 'M', 'X'), ots::ots_vdmx_parse, ots::ots_vdmx_serialise, |
| 117 ots::ots_vdmx_should_serialise, ots::ots_vdmx_free, false }, | 115 ots::ots_vdmx_should_serialise, ots::ots_vdmx_free, false }, |
| 118 { Tag("hdmx"), ots::ots_hdmx_parse, ots::ots_hdmx_serialise, | 116 { TAG('h', 'd', 'm', 'x'), ots::ots_hdmx_parse, ots::ots_hdmx_serialise, |
| 119 ots::ots_hdmx_should_serialise, ots::ots_hdmx_free, false }, | 117 ots::ots_hdmx_should_serialise, ots::ots_hdmx_free, false }, |
| 120 { Tag("gasp"), ots::ots_gasp_parse, ots::ots_gasp_serialise, | 118 { TAG('g', 'a', 's', 'p'), ots::ots_gasp_parse, ots::ots_gasp_serialise, |
| 121 ots::ots_gasp_should_serialise, ots::ots_gasp_free, false }, | 119 ots::ots_gasp_should_serialise, ots::ots_gasp_free, false }, |
| 122 { Tag("cvt "), ots::ots_cvt_parse, ots::ots_cvt_serialise, | 120 { TAG('c', 'v', 't', ' '), ots::ots_cvt_parse, ots::ots_cvt_serialise, |
| 123 ots::ots_cvt_should_serialise, ots::ots_cvt_free, false }, | 121 ots::ots_cvt_should_serialise, ots::ots_cvt_free, false }, |
| 124 { Tag("fpgm"), ots::ots_fpgm_parse, ots::ots_fpgm_serialise, | 122 { TAG('f', 'p', 'g', 'm'), ots::ots_fpgm_parse, ots::ots_fpgm_serialise, |
| 125 ots::ots_fpgm_should_serialise, ots::ots_fpgm_free, false }, | 123 ots::ots_fpgm_should_serialise, ots::ots_fpgm_free, false }, |
| 126 { Tag("prep"), ots::ots_prep_parse, ots::ots_prep_serialise, | 124 { TAG('p', 'r', 'e', 'p'), ots::ots_prep_parse, ots::ots_prep_serialise, |
| 127 ots::ots_prep_should_serialise, ots::ots_prep_free, false }, | 125 ots::ots_prep_should_serialise, ots::ots_prep_free, false }, |
| 128 { Tag("LTSH"), ots::ots_ltsh_parse, ots::ots_ltsh_serialise, | 126 { TAG('L', 'T', 'S', 'H'), ots::ots_ltsh_parse, ots::ots_ltsh_serialise, |
| 129 ots::ots_ltsh_should_serialise, ots::ots_ltsh_free, false }, | 127 ots::ots_ltsh_should_serialise, ots::ots_ltsh_free, false }, |
| 130 { Tag("VORG"), ots::ots_vorg_parse, ots::ots_vorg_serialise, | 128 { TAG('V', 'O', 'R', 'G'), ots::ots_vorg_parse, ots::ots_vorg_serialise, |
| 131 ots::ots_vorg_should_serialise, ots::ots_vorg_free, false }, | 129 ots::ots_vorg_should_serialise, ots::ots_vorg_free, false }, |
| 132 { Tag("kern"), ots::ots_kern_parse, ots::ots_kern_serialise, | 130 { TAG('k', 'e', 'r', 'n'), ots::ots_kern_parse, ots::ots_kern_serialise, |
| 133 ots::ots_kern_should_serialise, ots::ots_kern_free, false }, | 131 ots::ots_kern_should_serialise, ots::ots_kern_free, false }, |
| 134 // We need to parse GDEF table in advance of parsing GSUB/GPOS tables | 132 // We need to parse GDEF table in advance of parsing GSUB/GPOS tables |
| 135 // because they could refer GDEF table. | 133 // because they could refer GDEF table. |
| 136 { Tag("GDEF"), ots::ots_gdef_parse, ots::ots_gdef_serialise, | 134 { TAG('G', 'D', 'E', 'F'), ots::ots_gdef_parse, ots::ots_gdef_serialise, |
| 137 ots::ots_gdef_should_serialise, ots::ots_gdef_free, false }, | 135 ots::ots_gdef_should_serialise, ots::ots_gdef_free, false }, |
| 138 { Tag("GPOS"), ots::ots_gpos_parse, ots::ots_gpos_serialise, | 136 { TAG('G', 'P', 'O', 'S'), ots::ots_gpos_parse, ots::ots_gpos_serialise, |
| 139 ots::ots_gpos_should_serialise, ots::ots_gpos_free, false }, | 137 ots::ots_gpos_should_serialise, ots::ots_gpos_free, false }, |
| 140 { Tag("GSUB"), ots::ots_gsub_parse, ots::ots_gsub_serialise, | 138 { TAG('G', 'S', 'U', 'B'), ots::ots_gsub_parse, ots::ots_gsub_serialise, |
| 141 ots::ots_gsub_should_serialise, ots::ots_gsub_free, false }, | 139 ots::ots_gsub_should_serialise, ots::ots_gsub_free, false }, |
| 142 { Tag("vhea"), ots::ots_vhea_parse, ots::ots_vhea_serialise, | 140 { TAG('v', 'h', 'e', 'a'), ots::ots_vhea_parse, ots::ots_vhea_serialise, |
| 143 ots::ots_vhea_should_serialise, ots::ots_vhea_free, false }, | 141 ots::ots_vhea_should_serialise, ots::ots_vhea_free, false }, |
| 144 { Tag("vmtx"), ots::ots_vmtx_parse, ots::ots_vmtx_serialise, | 142 { TAG('v', 'm', 't', 'x'), ots::ots_vmtx_parse, ots::ots_vmtx_serialise, |
| 145 ots::ots_vmtx_should_serialise, ots::ots_vmtx_free, false }, | 143 ots::ots_vmtx_should_serialise, ots::ots_vmtx_free, false }, |
| 146 // TODO(bashi): Support mort, base, and jstf tables. | 144 // TODO(bashi): Support mort, base, and jstf tables. |
| 147 { 0, NULL, NULL, NULL, NULL, false }, | 145 { 0, NULL, NULL, NULL, NULL, false }, |
| 148 }; | 146 }; |
| 149 | 147 |
| 150 bool IsValidVersionTag(uint32_t tag) { | 148 bool IsValidVersionTag(uint32_t tag) { |
| 151 return tag == Tag("\x00\x01\x00\x00") || | 149 return tag == TAG('\x00', '\x01', '\x00', '\x00') || |
|
Nico
2011/12/09 19:13:30
The function-local Tag() calls didn't matter, but
| |
| 152 // OpenType fonts with CFF data have 'OTTO' tag. | 150 // OpenType fonts with CFF data have 'OTTO' tag. |
| 153 tag == Tag("OTTO") || | 151 tag == TAG('O', 'T', 'T', 'O') || |
| 154 // Older Mac fonts might have 'true' or 'typ1' tag. | 152 // Older Mac fonts might have 'true' or 'typ1' tag. |
| 155 tag == Tag("true") || | 153 tag == TAG('t', 'r', 'u', 'e') || |
| 156 tag == Tag("typ1"); | 154 tag == TAG('t', 'y', 'p', '1'); |
| 157 } | 155 } |
| 158 | 156 |
| 159 bool ProcessGeneric(ots::OpenTypeFile *header, ots::OTSStream *output, | 157 bool ProcessGeneric(ots::OpenTypeFile *header, ots::OTSStream *output, |
| 160 const uint8_t *data, size_t length, | 158 const uint8_t *data, size_t length, |
| 161 const std::vector<OpenTypeTable>& tables, | 159 const std::vector<OpenTypeTable>& tables, |
| 162 ots::Buffer& file); | 160 ots::Buffer& file); |
| 163 | 161 |
| 164 bool ProcessTTF(ots::OpenTypeFile *header, | 162 bool ProcessTTF(ots::OpenTypeFile *header, |
| 165 ots::OTSStream *output, const uint8_t *data, size_t length) { | 163 ots::OTSStream *output, const uint8_t *data, size_t length) { |
| 166 ots::Buffer file(data, length); | 164 ots::Buffer file(data, length); |
| (...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 244 // we disallow all files > 1GB in size for sanity. | 242 // we disallow all files > 1GB in size for sanity. |
| 245 if (length > 1024 * 1024 * 1024) { | 243 if (length > 1024 * 1024 * 1024) { |
| 246 return OTS_FAILURE(); | 244 return OTS_FAILURE(); |
| 247 } | 245 } |
| 248 | 246 |
| 249 uint32_t woff_tag; | 247 uint32_t woff_tag; |
| 250 if (!file.ReadTag(&woff_tag)) { | 248 if (!file.ReadTag(&woff_tag)) { |
| 251 return OTS_FAILURE(); | 249 return OTS_FAILURE(); |
| 252 } | 250 } |
| 253 | 251 |
| 254 if (woff_tag != Tag("wOFF")) { | 252 if (woff_tag != TAG('w', 'O', 'F', 'F')) { |
| 255 return OTS_FAILURE(); | 253 return OTS_FAILURE(); |
| 256 } | 254 } |
| 257 | 255 |
| 258 if (!file.ReadTag(&header->version)) { | 256 if (!file.ReadTag(&header->version)) { |
| 259 return OTS_FAILURE(); | 257 return OTS_FAILURE(); |
| 260 } | 258 } |
| 261 if (!IsValidVersionTag(header->version)) { | 259 if (!IsValidVersionTag(header->version)) { |
| 262 return OTS_FAILURE(); | 260 return OTS_FAILURE(); |
| 263 } | 261 } |
| 264 | 262 |
| (...skipping 175 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 440 table_length = it->second.length; | 438 table_length = it->second.length; |
| 441 } | 439 } |
| 442 | 440 |
| 443 if (!table_parsers[i].parse(header, table_data, table_length)) { | 441 if (!table_parsers[i].parse(header, table_data, table_length)) { |
| 444 return OTS_FAILURE(); | 442 return OTS_FAILURE(); |
| 445 } | 443 } |
| 446 } | 444 } |
| 447 | 445 |
| 448 if (header->cff) { | 446 if (header->cff) { |
| 449 // font with PostScript glyph | 447 // font with PostScript glyph |
| 450 if (header->version != Tag("OTTO")) { | 448 if (header->version != TAG('O', 'T', 'T', 'O')) { |
| 451 return OTS_FAILURE(); | 449 return OTS_FAILURE(); |
| 452 } | 450 } |
| 453 if (header->glyf || header->loca) { | 451 if (header->glyf || header->loca) { |
| 454 // mixing outline formats is not recommended | 452 // mixing outline formats is not recommended |
| 455 return OTS_FAILURE(); | 453 return OTS_FAILURE(); |
| 456 } | 454 } |
| 457 } else { | 455 } else { |
| 458 if (!header->glyf || !header->loca) { | 456 if (!header->glyf || !header->loca) { |
| 459 // No TrueType glyph found. | 457 // No TrueType glyph found. |
| 460 // Note: bitmap-only fonts are not supported. | 458 // Note: bitmap-only fonts are not supported. |
| (...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 504 | 502 |
| 505 if (!table_parsers[i].should_serialise(header)) { | 503 if (!table_parsers[i].should_serialise(header)) { |
| 506 continue; | 504 continue; |
| 507 } | 505 } |
| 508 | 506 |
| 509 OutputTable out; | 507 OutputTable out; |
| 510 out.tag = table_parsers[i].tag; | 508 out.tag = table_parsers[i].tag; |
| 511 out.offset = output->Tell(); | 509 out.offset = output->Tell(); |
| 512 | 510 |
| 513 output->ResetChecksum(); | 511 output->ResetChecksum(); |
| 514 if (table_parsers[i].tag == Tag("head")) { | 512 if (table_parsers[i].tag == TAG('h', 'e', 'a', 'd')) { |
| 515 head_table_offset = out.offset; | 513 head_table_offset = out.offset; |
| 516 } | 514 } |
| 517 if (!table_parsers[i].serialise(output, header)) { | 515 if (!table_parsers[i].serialise(output, header)) { |
| 518 return OTS_FAILURE(); | 516 return OTS_FAILURE(); |
| 519 } | 517 } |
| 520 | 518 |
| 521 const size_t end_offset = output->Tell(); | 519 const size_t end_offset = output->Tell(); |
| 522 if (end_offset <= out.offset) { | 520 if (end_offset <= out.offset) { |
| 523 // paranoid check. |end_offset| is supposed to be greater than the offset, | 521 // paranoid check. |end_offset| is supposed to be greater than the offset, |
| 524 // as long as the Tell() interface is implemented correctly. | 522 // as long as the Tell() interface is implemented correctly. |
| (...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 622 va_start(va, format); | 620 va_start(va, format); |
| 623 std::vfprintf(stderr, format, va); | 621 std::vfprintf(stderr, format, va); |
| 624 va_end(va); | 622 va_end(va); |
| 625 std::fprintf(stderr, "\n"); | 623 std::fprintf(stderr, "\n"); |
| 626 std::fflush(stderr); | 624 std::fflush(stderr); |
| 627 } | 625 } |
| 628 } | 626 } |
| 629 #endif | 627 #endif |
| 630 | 628 |
| 631 } // namespace ots | 629 } // namespace ots |
| OLD | NEW |