| 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 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 42 for (unsigned i = 0; i < 4; ++i) { | 42 for (unsigned i = 0; i < 4; ++i) { |
| 43 const uint32_t check = tag_value & 0xff; | 43 const uint32_t check = tag_value & 0xff; |
| 44 if (check < 32 || check > 126) { | 44 if (check < 32 || check > 126) { |
| 45 return false; // non-ASCII character found. | 45 return false; // non-ASCII character found. |
| 46 } | 46 } |
| 47 tag_value >>= 8; | 47 tag_value >>= 8; |
| 48 } | 48 } |
| 49 return true; | 49 return true; |
| 50 } | 50 } |
| 51 | 51 |
| 52 uint32_t Tag(const char *tag_str) { |
| 53 uint32_t ret; |
| 54 std::memcpy(&ret, tag_str, 4); |
| 55 return ret; |
| 56 } |
| 57 |
| 52 struct OutputTable { | 58 struct OutputTable { |
| 53 uint32_t tag; | 59 uint32_t tag; |
| 54 size_t offset; | 60 size_t offset; |
| 55 size_t length; | 61 size_t length; |
| 56 uint32_t chksum; | 62 uint32_t chksum; |
| 57 | 63 |
| 58 static bool SortByTag(const OutputTable& a, const OutputTable& b) { | 64 static bool SortByTag(const OutputTable& a, const OutputTable& b) { |
| 59 const uint32_t atag = ntohl(a.tag); | 65 const uint32_t atag = ntohl(a.tag); |
| 60 const uint32_t btag = ntohl(b.tag); | 66 const uint32_t btag = ntohl(b.tag); |
| 61 return atag < btag; | 67 return atag < btag; |
| (...skipping 12 matching lines...) Expand all Loading... |
| 74 uint8_t* Allocate(size_t length) { | 80 uint8_t* Allocate(size_t length) { |
| 75 uint8_t* p = new uint8_t[length]; | 81 uint8_t* p = new uint8_t[length]; |
| 76 hunks_.push_back(p); | 82 hunks_.push_back(p); |
| 77 return p; | 83 return p; |
| 78 } | 84 } |
| 79 | 85 |
| 80 private: | 86 private: |
| 81 std::vector<uint8_t*> hunks_; | 87 std::vector<uint8_t*> hunks_; |
| 82 }; | 88 }; |
| 83 | 89 |
| 84 // Use a macro instead of a function because gcc 4.4.3 creates static | |
| 85 // initializers in that case. | |
| 86 #if defined(__BIG_ENDIAN__) || defined(_BIG_ENDIAN) | |
| 87 #define TAG(d, c, b, a) (a | (b << 8) | (c << 16) | (d << 24)) | |
| 88 #else | |
| 89 #define TAG(a, b, c, d) (a | (b << 8) | (c << 16) | (d << 24)) | |
| 90 #endif | |
| 91 | |
| 92 const struct { | 90 const struct { |
| 93 uint32_t tag; | 91 const char* tag; |
| 94 bool (*parse)(ots::OpenTypeFile *otf, const uint8_t *data, size_t length); | 92 bool (*parse)(ots::OpenTypeFile *otf, const uint8_t *data, size_t length); |
| 95 bool (*serialise)(ots::OTSStream *out, ots::OpenTypeFile *file); | 93 bool (*serialise)(ots::OTSStream *out, ots::OpenTypeFile *file); |
| 96 bool (*should_serialise)(ots::OpenTypeFile *file); | 94 bool (*should_serialise)(ots::OpenTypeFile *file); |
| 97 void (*free)(ots::OpenTypeFile *file); | 95 void (*free)(ots::OpenTypeFile *file); |
| 98 bool required; | 96 bool required; |
| 99 } table_parsers[] = { | 97 } table_parsers[] = { |
| 100 { TAG('m', 'a', 'x', 'p'), ots::ots_maxp_parse, ots::ots_maxp_serialise, | 98 { "maxp", ots::ots_maxp_parse, ots::ots_maxp_serialise, |
| 101 ots::ots_maxp_should_serialise, ots::ots_maxp_free, true }, | 99 ots::ots_maxp_should_serialise, ots::ots_maxp_free, true }, |
| 102 { TAG('h', 'e', 'a', 'd'), ots::ots_head_parse, ots::ots_head_serialise, | 100 { "head", ots::ots_head_parse, ots::ots_head_serialise, |
| 103 ots::ots_head_should_serialise, ots::ots_head_free, true }, | 101 ots::ots_head_should_serialise, ots::ots_head_free, true }, |
| 104 { TAG('O', 'S', '/', '2'), ots::ots_os2_parse, ots::ots_os2_serialise, | 102 { "OS/2", ots::ots_os2_parse, ots::ots_os2_serialise, |
| 105 ots::ots_os2_should_serialise, ots::ots_os2_free, true }, | 103 ots::ots_os2_should_serialise, ots::ots_os2_free, true }, |
| 106 { TAG('c', 'm', 'a', 'p'), ots::ots_cmap_parse, ots::ots_cmap_serialise, | 104 { "cmap", ots::ots_cmap_parse, ots::ots_cmap_serialise, |
| 107 ots::ots_cmap_should_serialise, ots::ots_cmap_free, true }, | 105 ots::ots_cmap_should_serialise, ots::ots_cmap_free, true }, |
| 108 { TAG('h', 'h', 'e', 'a'), ots::ots_hhea_parse, ots::ots_hhea_serialise, | 106 { "hhea", ots::ots_hhea_parse, ots::ots_hhea_serialise, |
| 109 ots::ots_hhea_should_serialise, ots::ots_hhea_free, true }, | 107 ots::ots_hhea_should_serialise, ots::ots_hhea_free, true }, |
| 110 { TAG('h', 'm', 't', 'x'), ots::ots_hmtx_parse, ots::ots_hmtx_serialise, | 108 { "hmtx", ots::ots_hmtx_parse, ots::ots_hmtx_serialise, |
| 111 ots::ots_hmtx_should_serialise, ots::ots_hmtx_free, true }, | 109 ots::ots_hmtx_should_serialise, ots::ots_hmtx_free, true }, |
| 112 { TAG('n', 'a', 'm', 'e'), ots::ots_name_parse, ots::ots_name_serialise, | 110 { "name", ots::ots_name_parse, ots::ots_name_serialise, |
| 113 ots::ots_name_should_serialise, ots::ots_name_free, true }, | 111 ots::ots_name_should_serialise, ots::ots_name_free, true }, |
| 114 { TAG('p', 'o', 's', 't'), ots::ots_post_parse, ots::ots_post_serialise, | 112 { "post", ots::ots_post_parse, ots::ots_post_serialise, |
| 115 ots::ots_post_should_serialise, ots::ots_post_free, true }, | 113 ots::ots_post_should_serialise, ots::ots_post_free, true }, |
| 116 { TAG('l', 'o', 'c', 'a'), ots::ots_loca_parse, ots::ots_loca_serialise, | 114 { "loca", ots::ots_loca_parse, ots::ots_loca_serialise, |
| 117 ots::ots_loca_should_serialise, ots::ots_loca_free, false }, | 115 ots::ots_loca_should_serialise, ots::ots_loca_free, false }, |
| 118 { TAG('g', 'l', 'y', 'f'), ots::ots_glyf_parse, ots::ots_glyf_serialise, | 116 { "glyf", ots::ots_glyf_parse, ots::ots_glyf_serialise, |
| 119 ots::ots_glyf_should_serialise, ots::ots_glyf_free, false }, | 117 ots::ots_glyf_should_serialise, ots::ots_glyf_free, false }, |
| 120 { TAG('C', 'F', 'F', ' '), ots::ots_cff_parse, ots::ots_cff_serialise, | 118 { "CFF ", ots::ots_cff_parse, ots::ots_cff_serialise, |
| 121 ots::ots_cff_should_serialise, ots::ots_cff_free, false }, | 119 ots::ots_cff_should_serialise, ots::ots_cff_free, false }, |
| 122 { TAG('V', 'D', 'M', 'X'), ots::ots_vdmx_parse, ots::ots_vdmx_serialise, | 120 { "VDMX", ots::ots_vdmx_parse, ots::ots_vdmx_serialise, |
| 123 ots::ots_vdmx_should_serialise, ots::ots_vdmx_free, false }, | 121 ots::ots_vdmx_should_serialise, ots::ots_vdmx_free, false }, |
| 124 { TAG('h', 'd', 'm', 'x'), ots::ots_hdmx_parse, ots::ots_hdmx_serialise, | 122 { "hdmx", ots::ots_hdmx_parse, ots::ots_hdmx_serialise, |
| 125 ots::ots_hdmx_should_serialise, ots::ots_hdmx_free, false }, | 123 ots::ots_hdmx_should_serialise, ots::ots_hdmx_free, false }, |
| 126 { TAG('g', 'a', 's', 'p'), ots::ots_gasp_parse, ots::ots_gasp_serialise, | 124 { "gasp", ots::ots_gasp_parse, ots::ots_gasp_serialise, |
| 127 ots::ots_gasp_should_serialise, ots::ots_gasp_free, false }, | 125 ots::ots_gasp_should_serialise, ots::ots_gasp_free, false }, |
| 128 { TAG('c', 'v', 't', ' '), ots::ots_cvt_parse, ots::ots_cvt_serialise, | 126 { "cvt ", ots::ots_cvt_parse, ots::ots_cvt_serialise, |
| 129 ots::ots_cvt_should_serialise, ots::ots_cvt_free, false }, | 127 ots::ots_cvt_should_serialise, ots::ots_cvt_free, false }, |
| 130 { TAG('f', 'p', 'g', 'm'), ots::ots_fpgm_parse, ots::ots_fpgm_serialise, | 128 { "fpgm", ots::ots_fpgm_parse, ots::ots_fpgm_serialise, |
| 131 ots::ots_fpgm_should_serialise, ots::ots_fpgm_free, false }, | 129 ots::ots_fpgm_should_serialise, ots::ots_fpgm_free, false }, |
| 132 { TAG('p', 'r', 'e', 'p'), ots::ots_prep_parse, ots::ots_prep_serialise, | 130 { "prep", ots::ots_prep_parse, ots::ots_prep_serialise, |
| 133 ots::ots_prep_should_serialise, ots::ots_prep_free, false }, | 131 ots::ots_prep_should_serialise, ots::ots_prep_free, false }, |
| 134 { TAG('L', 'T', 'S', 'H'), ots::ots_ltsh_parse, ots::ots_ltsh_serialise, | 132 { "LTSH", ots::ots_ltsh_parse, ots::ots_ltsh_serialise, |
| 135 ots::ots_ltsh_should_serialise, ots::ots_ltsh_free, false }, | 133 ots::ots_ltsh_should_serialise, ots::ots_ltsh_free, false }, |
| 136 { TAG('V', 'O', 'R', 'G'), ots::ots_vorg_parse, ots::ots_vorg_serialise, | 134 { "VORG", ots::ots_vorg_parse, ots::ots_vorg_serialise, |
| 137 ots::ots_vorg_should_serialise, ots::ots_vorg_free, false }, | 135 ots::ots_vorg_should_serialise, ots::ots_vorg_free, false }, |
| 138 { TAG('k', 'e', 'r', 'n'), ots::ots_kern_parse, ots::ots_kern_serialise, | 136 { "kern", ots::ots_kern_parse, ots::ots_kern_serialise, |
| 139 ots::ots_kern_should_serialise, ots::ots_kern_free, false }, | 137 ots::ots_kern_should_serialise, ots::ots_kern_free, false }, |
| 140 // We need to parse GDEF table in advance of parsing GSUB/GPOS tables | 138 // We need to parse GDEF table in advance of parsing GSUB/GPOS tables |
| 141 // because they could refer GDEF table. | 139 // because they could refer GDEF table. |
| 142 { TAG('G', 'D', 'E', 'F'), ots::ots_gdef_parse, ots::ots_gdef_serialise, | 140 { "GDEF", ots::ots_gdef_parse, ots::ots_gdef_serialise, |
| 143 ots::ots_gdef_should_serialise, ots::ots_gdef_free, false }, | 141 ots::ots_gdef_should_serialise, ots::ots_gdef_free, false }, |
| 144 { TAG('G', 'P', 'O', 'S'), ots::ots_gpos_parse, ots::ots_gpos_serialise, | 142 { "GPOS", ots::ots_gpos_parse, ots::ots_gpos_serialise, |
| 145 ots::ots_gpos_should_serialise, ots::ots_gpos_free, false }, | 143 ots::ots_gpos_should_serialise, ots::ots_gpos_free, false }, |
| 146 { TAG('G', 'S', 'U', 'B'), ots::ots_gsub_parse, ots::ots_gsub_serialise, | 144 { "GSUB", ots::ots_gsub_parse, ots::ots_gsub_serialise, |
| 147 ots::ots_gsub_should_serialise, ots::ots_gsub_free, false }, | 145 ots::ots_gsub_should_serialise, ots::ots_gsub_free, false }, |
| 148 { TAG('v', 'h', 'e', 'a'), ots::ots_vhea_parse, ots::ots_vhea_serialise, | 146 { "vhea", ots::ots_vhea_parse, ots::ots_vhea_serialise, |
| 149 ots::ots_vhea_should_serialise, ots::ots_vhea_free, false }, | 147 ots::ots_vhea_should_serialise, ots::ots_vhea_free, false }, |
| 150 { TAG('v', 'm', 't', 'x'), ots::ots_vmtx_parse, ots::ots_vmtx_serialise, | 148 { "vmtx", ots::ots_vmtx_parse, ots::ots_vmtx_serialise, |
| 151 ots::ots_vmtx_should_serialise, ots::ots_vmtx_free, false }, | 149 ots::ots_vmtx_should_serialise, ots::ots_vmtx_free, false }, |
| 152 // TODO(bashi): Support mort, base, and jstf tables. | 150 // TODO(bashi): Support mort, base, and jstf tables. |
| 153 { 0, NULL, NULL, NULL, NULL, false }, | 151 { 0, NULL, NULL, NULL, NULL, false }, |
| 154 }; | 152 }; |
| 155 | 153 |
| 156 bool IsValidVersionTag(uint32_t tag) { | 154 bool IsValidVersionTag(uint32_t tag) { |
| 157 return tag == TAG('\x00', '\x01', '\x00', '\x00') || | 155 return tag == Tag("\x00\x01\x00\x00") || |
| 158 // OpenType fonts with CFF data have 'OTTO' tag. | 156 // OpenType fonts with CFF data have 'OTTO' tag. |
| 159 tag == TAG('O', 'T', 'T', 'O') || | 157 tag == Tag("OTTO") || |
| 160 // Older Mac fonts might have 'true' or 'typ1' tag. | 158 // Older Mac fonts might have 'true' or 'typ1' tag. |
| 161 tag == TAG('t', 'r', 'u', 'e') || | 159 tag == Tag("true") || |
| 162 tag == TAG('t', 'y', 'p', '1'); | 160 tag == Tag("typ1"); |
| 163 } | 161 } |
| 164 | 162 |
| 165 bool ProcessGeneric(ots::OpenTypeFile *header, ots::OTSStream *output, | 163 bool ProcessGeneric(ots::OpenTypeFile *header, ots::OTSStream *output, |
| 166 const uint8_t *data, size_t length, | 164 const uint8_t *data, size_t length, |
| 167 const std::vector<OpenTypeTable>& tables, | 165 const std::vector<OpenTypeTable>& tables, |
| 168 ots::Buffer& file); | 166 ots::Buffer& file); |
| 169 | 167 |
| 170 bool ProcessTTF(ots::OpenTypeFile *header, | 168 bool ProcessTTF(ots::OpenTypeFile *header, |
| 171 ots::OTSStream *output, const uint8_t *data, size_t length) { | 169 ots::OTSStream *output, const uint8_t *data, size_t length) { |
| 172 ots::Buffer file(data, length); | 170 ots::Buffer file(data, length); |
| (...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 250 // we disallow all files > 1GB in size for sanity. | 248 // we disallow all files > 1GB in size for sanity. |
| 251 if (length > 1024 * 1024 * 1024) { | 249 if (length > 1024 * 1024 * 1024) { |
| 252 return OTS_FAILURE(); | 250 return OTS_FAILURE(); |
| 253 } | 251 } |
| 254 | 252 |
| 255 uint32_t woff_tag; | 253 uint32_t woff_tag; |
| 256 if (!file.ReadTag(&woff_tag)) { | 254 if (!file.ReadTag(&woff_tag)) { |
| 257 return OTS_FAILURE(); | 255 return OTS_FAILURE(); |
| 258 } | 256 } |
| 259 | 257 |
| 260 if (woff_tag != TAG('w', 'O', 'F', 'F')) { | 258 if (woff_tag != Tag("wOFF")) { |
| 261 return OTS_FAILURE(); | 259 return OTS_FAILURE(); |
| 262 } | 260 } |
| 263 | 261 |
| 264 if (!file.ReadTag(&header->version)) { | 262 if (!file.ReadTag(&header->version)) { |
| 265 return OTS_FAILURE(); | 263 return OTS_FAILURE(); |
| 266 } | 264 } |
| 267 if (!IsValidVersionTag(header->version)) { | 265 if (!IsValidVersionTag(header->version)) { |
| 268 return OTS_FAILURE(); | 266 return OTS_FAILURE(); |
| 269 } | 267 } |
| 270 | 268 |
| (...skipping 227 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 498 return OTS_FAILURE(); | 496 return OTS_FAILURE(); |
| 499 } | 497 } |
| 500 } | 498 } |
| 501 | 499 |
| 502 Arena arena; | 500 Arena arena; |
| 503 | 501 |
| 504 for (unsigned i = 0; ; ++i) { | 502 for (unsigned i = 0; ; ++i) { |
| 505 if (table_parsers[i].parse == NULL) break; | 503 if (table_parsers[i].parse == NULL) break; |
| 506 | 504 |
| 507 const std::map<uint32_t, OpenTypeTable>::const_iterator it | 505 const std::map<uint32_t, OpenTypeTable>::const_iterator it |
| 508 = table_map.find(table_parsers[i].tag); | 506 = table_map.find(Tag(table_parsers[i].tag)); |
| 509 | 507 |
| 510 if (it == table_map.end()) { | 508 if (it == table_map.end()) { |
| 511 if (table_parsers[i].required) { | 509 if (table_parsers[i].required) { |
| 512 return OTS_FAILURE(); | 510 return OTS_FAILURE(); |
| 513 } | 511 } |
| 514 continue; | 512 continue; |
| 515 } | 513 } |
| 516 | 514 |
| 517 const uint8_t* table_data; | 515 const uint8_t* table_data; |
| 518 size_t table_length; | 516 size_t table_length; |
| (...skipping 14 matching lines...) Expand all Loading... |
| 533 table_length = it->second.length; | 531 table_length = it->second.length; |
| 534 } | 532 } |
| 535 | 533 |
| 536 if (!table_parsers[i].parse(header, table_data, table_length)) { | 534 if (!table_parsers[i].parse(header, table_data, table_length)) { |
| 537 return OTS_FAILURE(); | 535 return OTS_FAILURE(); |
| 538 } | 536 } |
| 539 } | 537 } |
| 540 | 538 |
| 541 if (header->cff) { | 539 if (header->cff) { |
| 542 // font with PostScript glyph | 540 // font with PostScript glyph |
| 543 if (header->version != TAG('O', 'T', 'T', 'O')) { | 541 if (header->version != Tag("OTTO")) { |
| 544 return OTS_FAILURE(); | 542 return OTS_FAILURE(); |
| 545 } | 543 } |
| 546 if (header->glyf || header->loca) { | 544 if (header->glyf || header->loca) { |
| 547 // mixing outline formats is not recommended | 545 // mixing outline formats is not recommended |
| 548 return OTS_FAILURE(); | 546 return OTS_FAILURE(); |
| 549 } | 547 } |
| 550 } else { | 548 } else { |
| 551 if (!header->glyf || !header->loca) { | 549 if (!header->glyf || !header->loca) { |
| 552 // No TrueType glyph found. | 550 // No TrueType glyph found. |
| 553 // Note: bitmap-only fonts are not supported. | 551 // Note: bitmap-only fonts are not supported. |
| (...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 593 for (unsigned i = 0; ; ++i) { | 591 for (unsigned i = 0; ; ++i) { |
| 594 if (table_parsers[i].parse == NULL) { | 592 if (table_parsers[i].parse == NULL) { |
| 595 break; | 593 break; |
| 596 } | 594 } |
| 597 | 595 |
| 598 if (!table_parsers[i].should_serialise(header)) { | 596 if (!table_parsers[i].should_serialise(header)) { |
| 599 continue; | 597 continue; |
| 600 } | 598 } |
| 601 | 599 |
| 602 OutputTable out; | 600 OutputTable out; |
| 603 out.tag = table_parsers[i].tag; | 601 uint32_t tag = Tag(table_parsers[i].tag); |
| 602 out.tag = tag; |
| 604 out.offset = output->Tell(); | 603 out.offset = output->Tell(); |
| 605 | 604 |
| 606 output->ResetChecksum(); | 605 output->ResetChecksum(); |
| 607 if (table_parsers[i].tag == TAG('h', 'e', 'a', 'd')) { | 606 if (tag == Tag("head")) { |
| 608 head_table_offset = out.offset; | 607 head_table_offset = out.offset; |
| 609 } | 608 } |
| 610 if (!table_parsers[i].serialise(output, header)) { | 609 if (!table_parsers[i].serialise(output, header)) { |
| 611 return OTS_FAILURE(); | 610 return OTS_FAILURE(); |
| 612 } | 611 } |
| 613 | 612 |
| 614 const size_t end_offset = output->Tell(); | 613 const size_t end_offset = output->Tell(); |
| 615 if (end_offset <= out.offset) { | 614 if (end_offset <= out.offset) { |
| 616 // paranoid check. |end_offset| is supposed to be greater than the offset, | 615 // paranoid check. |end_offset| is supposed to be greater than the offset, |
| 617 // as long as the Tell() interface is implemented correctly. | 616 // as long as the Tell() interface is implemented correctly. |
| (...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 715 va_start(va, format); | 714 va_start(va, format); |
| 716 std::vfprintf(stderr, format, va); | 715 std::vfprintf(stderr, format, va); |
| 717 va_end(va); | 716 va_end(va); |
| 718 std::fprintf(stderr, "\n"); | 717 std::fprintf(stderr, "\n"); |
| 719 std::fflush(stderr); | 718 std::fflush(stderr); |
| 720 } | 719 } |
| 721 } | 720 } |
| 722 #endif | 721 #endif |
| 723 | 722 |
| 724 } // namespace ots | 723 } // namespace ots |
| OLD | NEW |