diff --git a/builtins/libmathtext/CMakeLists.txt b/builtins/libmathtext/CMakeLists.txt index dbe4627d4e68a..be96507ecacbf 100644 --- a/builtins/libmathtext/CMakeLists.txt +++ b/builtins/libmathtext/CMakeLists.txt @@ -6,7 +6,9 @@ add_library(mathtext STATIC fontembed.cc + fontembedpdf.cc fontembedps.cc + geometry.cc mathrender.cc mathrenderstyle.cc mathrendertoken.cc @@ -15,7 +17,7 @@ add_library(mathtext STATIC mathtextparse.cc mathtextview.cc ) -target_include_directories(mathtext PUBLIC ./) # for mathtext/fontembed.h mathtext/mathrender.h mathtext/mathtext.h +target_include_directories(mathtext PUBLIC ./) # for mathtext/fontembed.h mathtext/mathrender.h mathtext/mathtext.h mathtext/geometry.h check_cxx_compiler_flag(-Wbidi-chars=none GCC_HAS_BIDI_CHARS_FLAG) if(GCC_HAS_BIDI_CHARS_FLAG) diff --git a/builtins/libmathtext/fontembed.cc b/builtins/libmathtext/fontembed.cc index a4a134a5127ca..9ca1fc9cdff03 100644 --- a/builtins/libmathtext/fontembed.cc +++ b/builtins/libmathtext/fontembed.cc @@ -1,5 +1,5 @@ // mathtext - A TeX/LaTeX compatible rendering library. Copyright (C) -// 2008-2012 Yue Shi Lai +// 2008-2016 Yue Shi Lai // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public License @@ -16,10 +16,11 @@ // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA // 02110-1301 USA -#include "mathtext/fontembed.h" +#include #include #include #include +#include #ifdef WIN32 #define snprintf _snprintf #endif @@ -44,32 +45,60 @@ // Microsoft Corp., TrueType 1.0 font files: technical specification // (1995), version 1.66 +#define ERROR_ACCESS(t) \ + (fprintf(stderr, "%s:%d: error: access out of bound in %s\n", \ + __FILE__, __LINE__, t)); +#define ERROR_UNSUPPORTED(t) \ + (fprintf(stderr, "%s:%d: error: %s is not supported\n", \ + __FILE__, __LINE__, t)); + namespace mathtext { typedef int32_t fixed_t; + void font_embed_t::protected_memcpy( + void *destination, + std::vector::const_iterator source, + std::vector::const_iterator source_end, + size_t length, const char *location) + { + if (source + length > source_end) { + ERROR_ACCESS(location); + } + memcpy(destination, &source[0], length); + } + void font_embed_t::parse_ttf_encoding_subtable_format4( std::map &cid_map, - const std::vector &font_data, const size_t offset, - const uint16_t length) + const std::vector &font_data, const size_t offset) { + static const char *location = + "TrueType encoding table format 4"; + cid_map.clear(); size_t offset_current = offset; struct ttf_encoding_subtable_format4_s { + uint16_t format; + uint16_t length; + uint16_t language; uint16_t seg_count_x2; uint16_t search_range; uint16_t entry_selector; uint16_t range_shift; } encoding_subtable_format4; - memcpy(&encoding_subtable_format4, - &font_data[offset_current], - sizeof(struct ttf_encoding_subtable_format4_s)); + protected_memcpy(&encoding_subtable_format4, + font_data.begin() + offset_current, + font_data.end(), + sizeof(struct ttf_encoding_subtable_format4_s), + location); offset_current += sizeof(struct ttf_encoding_subtable_format4_s); #ifdef LITTLE_ENDIAN + encoding_subtable_format4.length = + bswap_16(encoding_subtable_format4.length); encoding_subtable_format4.seg_count_x2 = bswap_16(encoding_subtable_format4.seg_count_x2); #endif // LITTLE_ENDIAN @@ -78,8 +107,11 @@ namespace mathtext { encoding_subtable_format4.seg_count_x2 >> 1; uint16_t *end_code = new uint16_t[seg_count]; - memcpy(end_code, &font_data[offset_current], - seg_count * sizeof(uint16_t)); + protected_memcpy(end_code, + font_data.begin() + offset_current, + font_data.end(), + seg_count * sizeof(uint16_t), + location); offset_current += seg_count * sizeof(uint16_t); #ifdef LITTLE_ENDIAN for (uint16_t segment = 0; segment < seg_count; segment++) { @@ -89,14 +121,18 @@ namespace mathtext { uint16_t reserved_pad; - memcpy(&reserved_pad, &font_data[offset_current], - sizeof(uint16_t)); + protected_memcpy(&reserved_pad, + font_data.begin() + offset_current, + font_data.end(), sizeof(uint16_t), + location); offset_current += sizeof(uint16_t); uint16_t *start_code = new uint16_t[seg_count]; - memcpy(start_code, &font_data[offset_current], - seg_count * sizeof(uint16_t)); + protected_memcpy(start_code, + font_data.begin() + offset_current, + font_data.end(), + seg_count * sizeof(uint16_t), location); offset_current += seg_count * sizeof(uint16_t); #ifdef LITTLE_ENDIAN for (uint16_t segment = 0; segment < seg_count; segment++) { @@ -106,8 +142,10 @@ namespace mathtext { uint16_t *id_delta = new uint16_t[seg_count]; - memcpy(id_delta, &font_data[offset_current], - seg_count * sizeof(uint16_t)); + protected_memcpy(id_delta, + font_data.begin() + offset_current, + font_data.end(), + seg_count * sizeof(uint16_t), location); offset_current += seg_count * sizeof(uint16_t); #ifdef LITTLE_ENDIAN for (uint16_t segment = 0; segment < seg_count; segment++) { @@ -116,12 +154,16 @@ namespace mathtext { #endif // LITTLE_ENDIAN const uint16_t variable = - (length >> 1) - (seg_count << 2) - 8; + (encoding_subtable_format4.length >> 1) - + (seg_count << 2) - 8; uint16_t *id_range_offset = new uint16_t[seg_count + variable]; - memcpy(id_range_offset, &font_data[offset_current], - (seg_count + variable) * sizeof(uint16_t)); + protected_memcpy(id_range_offset, + font_data.begin() + offset_current, + font_data.end(), + (seg_count + variable) * sizeof(uint16_t), + location); offset_current += (seg_count + variable) * sizeof(uint16_t); #ifdef LITTLE_ENDIAN for (uint16_t j = 0; j < seg_count + variable; j++) { @@ -135,13 +177,13 @@ namespace mathtext { const uint16_t inner_offset = segment + (id_range_offset[segment] >> 1) + (code - start_code[segment]); - const uint16_t glyph_index = + const uint16_t glyph_id = id_range_offset[segment] == 0 ? id_delta[segment] + code : inner_offset >= seg_count + variable ? 0 : id_range_offset[inner_offset]; - cid_map[static_cast(code)] = glyph_index; + cid_map[static_cast(code)] = glyph_id; } } @@ -149,6 +191,72 @@ namespace mathtext { delete [] start_code; delete [] id_delta; delete [] id_range_offset; + } + + void font_embed_t::parse_ttf_encoding_subtable_format12( + std::map &cid_map, + const std::vector &font_data, const size_t offset) + { + static const char *location = + "TrueType encoding table format 12"; + + cid_map.clear(); + + size_t offset_current = offset; + + struct ttf_encoding_subtable_format12_s { + uint16_t format; + uint16_t reserved; + uint32_t length; + uint32_t language; + uint32_t ngroups; + } encoding_subtable_format12; + + protected_memcpy(&encoding_subtable_format12, + font_data.begin() + offset_current, + font_data.end(), + sizeof(struct ttf_encoding_subtable_format12_s), + location); + offset_current += + sizeof(struct ttf_encoding_subtable_format12_s); +#ifdef LITTLE_ENDIAN + encoding_subtable_format12.ngroups = + bswap_32(encoding_subtable_format12.ngroups); +#endif // LITTLE_ENDIAN + + struct ttf_encoding_subtable_format12_group_s { + uint32_t start_char_code; + uint32_t end_char_code; + uint32_t start_glyph_id; + } encoding_subtable_format12_group; + + for (uint32_t group = 0; + group < encoding_subtable_format12.ngroups; group++) { + protected_memcpy( + &encoding_subtable_format12_group, + font_data.begin() + offset_current, + font_data.end(), + sizeof(struct ttf_encoding_subtable_format12_group_s), + location); + offset_current += + sizeof(struct ttf_encoding_subtable_format12_group_s); +#ifdef LITTLE_ENDIAN + encoding_subtable_format12_group.start_char_code = + bswap_32(encoding_subtable_format12_group.start_char_code); + encoding_subtable_format12_group.end_char_code = + bswap_32(encoding_subtable_format12_group.end_char_code); + encoding_subtable_format12_group.start_glyph_id = + bswap_32(encoding_subtable_format12_group.start_glyph_id); +#endif // LITTLE_ENDIAN + for (uint32_t code = + encoding_subtable_format12_group.start_char_code, + glyph_id = + encoding_subtable_format12_group.start_glyph_id; + code <= encoding_subtable_format12_group.end_char_code; + code++, glyph_id++) { + cid_map[static_cast(code)] = glyph_id; + } + } } ///////////////////////////////////////////////////////////////////// @@ -264,7 +372,7 @@ namespace mathtext { const uint8_t *input_data_data = input_data_offset + off_size * (count + 1); - data = std::vector(input_data_data, input_data_data + data = std::vector(input_data_data, input_data_data); } ~cff_index_t(void) { @@ -276,7 +384,147 @@ namespace mathtext { std::map glyph_usage) { } + + std::vector font_embed_t::subset_otf( + const std::vector &font_data, + const std::map &glyph_usage) + { + std::vector retval; + struct otf_offset_table_s { + char sfnt_version[4]; + uint16_t num_tables; + uint16_t search_range; + uint16_t entry_selector; + uint16_t range_shift; + } offset_table; + + memcpy(&offset_table, &font_data[0], + sizeof(struct otf_offset_table_s)); + if (strncmp(offset_table.sfnt_version, "OTTO", 4) != 0 || + strncmp(offset_table.sfnt_version, "\0\1\0\0", 4) != 0) { + // Neither a OpenType, nor TrueType font +#if 0 + fprintf(stderr, "%s:%d: error: unknown sfnt_version = " + "0x%02x%02x%02x%02x\n", __FILE__, __LINE__, + offset_table.sfnt_version[0], + offset_table.sfnt_version[1], + offset_table.sfnt_version[2], + offset_table.sfnt_version[3]); #endif + return retval; + } +#ifdef LITTLE_ENDIAN + offset_table.num_tables = bswap_16(offset_table.num_tables); +#endif // LITTLE_ENDIAN + + struct otf_table_directory_s { + char tag[4]; + uint32_t check_sum; + uint32_t offset; + uint32_t length; + }; + struct table_data_s *table_data = + new struct table_data_s[offset_table.num_tables]; + + for (uint16_t i = 0; i < offset_table.num_tables; i++) { + struct otf_table_directory_s table_directory; + + protected_memcpy( + &table_directory, + font_data.begin() + + sizeof(struct otf_offset_table_s) + i * + sizeof(struct otf_table_directory_s), + font_data.end(), + sizeof(struct otf_table_directory_s), + location); +#ifdef LITTLE_ENDIAN + table_directory.offset = + bswap_32(table_directory.offset); + table_directory.length = + bswap_32(table_directory.length); +#endif // LITTLE_ENDIAN +#if 0 + fprintf(stderr, "%s:%d: tag = %c%c%c%c, offset = %u, " + "length = %u\n", __FILE__, __LINE__, + table_directory.tag[0], table_directory.tag[1], + table_directory.tag[2], table_directory.tag[3], + table_directory.offset, table_directory.length); +#endif + memcpy(table_data[i].tag, table_directory.tag, + 4 * sizeof(char)); + table_data[i].data.resize(table_directory.length); + memcpy(&(table_data[i].data[0]), + &font_data[table_directory.offset], + table_directory.length); + } + + size_t size_count; + + size_count = sizeof(struct otf_offset_table_s) + + offset_table.num_tables * + sizeof(struct otf_table_directory_s); + for (size_t i = 0; i < offset_table.num_tables; i++) { + size_count += table_data[i].data.size(); + } + + size_t offset_current = sizeof(struct otf_offset_table_s); + size_t offset_check_sum_adjustment = 0; + bool head_table_exists = false; + + retval.resize(size_count); + memcpy(&retval[0], &font_data[0], + sizeof(struct otf_offset_table_s)); + for (size_t i = 0; i < offset_table.num_tables; i++) { + struct otf_table_directory_s table_directory; + const bool head_table = + strncmp(table_directory.tag, "head", 4) == 0; + + memcpy(table_directory.tag, table_data[i].tag, + 4 * sizeof(char)); + if (head_table) { + // Reset checkSumAdjustment in order to calculate the + // check sum of the head table + offset_check_sum_adjustment = 2 * sizeof(fixed_t); + *reinterpret_cast(&(table_data[i].data[ + offset_check_sum_adjustment])) = 0U; + // Change the offset for checkSumAdjustment to the + // global indexing + offset_check_sum_adjustment += offset_current; + head_table_exists = true; + } + table_directory.check_sum = + otf_check_sum(table_data[i].data); + table_directory.offset = size_count; + table_directory.length = table_data[i].data.size(); + + memcpy(&retval[offset_current], &table_directory, + sizeof(struct otf_table_directory_s)); + size_count += table_data[i].data.size(); + offset_current += sizeof(struct otf_table_directory_s); + } + + for (size_t i = 0; i < offset_table.num_tables; i++) { + memcpy(&retval[offset_current], &(table_data[i].data[0]), + table_data[i].data.size()); + offset_current += table_data[i].data.size(); + + const size_t padding_size = + (4U - table_data[i].data.size()) & 3U; + + memset(&retval[offset_current], '\0', padding_size); + offset_current += padding_size; + } + + if (head_table_exists) { + // Set checkSumAdjustment in the head table + *reinterpret_cast(&(retval[ + offset_check_sum_adjustment])) = + 0xb1b0afbaU - otf_check_sum(retval); + } + + return retval; + } +#endif ////////////////////////////////////////////////////////////// uint32_t font_embed_t::otf_check_sum( const std::vector &table_data) @@ -308,12 +556,11 @@ namespace mathtext { return sum; } - std::vector font_embed_t::read_font_data( - FILE *fp) + std::vector font_embed_t::read_font_data(FILE *fp) { std::vector font_data; - if (fp == nullptr) { + if (fp == nullptr) { return font_data; } if (fseek(fp, 0L, SEEK_SET) == -1) { @@ -354,7 +601,7 @@ namespace mathtext { FILE *fp = fopen(filename.c_str(), "r"); std::vector font_data; - if (fp == nullptr) { + if (fp == nullptr) { perror("fopen"); return font_data; } @@ -364,239 +611,324 @@ namespace mathtext { return font_data; } - bool font_embed_t::parse_otf_cff_header( - std::string &font_name, unsigned short &cid_encoding_id, - unsigned int &cff_offset, unsigned int &cff_length, - const std::vector &font_data) + std::map > + font_embed_t::parse_ttf_offset_table( + const std::vector &font_data, + size_t offset_table_size, uint16_t num_tables) { - // OpenType file structure - struct otf_offset_table_s { - char sfnt_version[4]; - uint16_t num_tables; - uint16_t search_range; - uint16_t entry_selector; - uint16_t range_shift; - } offset_table; - - memcpy(&offset_table, &font_data[0], - sizeof(struct otf_offset_table_s)); - if (strncmp(offset_table.sfnt_version, "OTTO", 4) != 0) { - // Not a OpenType CFF/Type 2 font - return false; - } -#ifdef LITTLE_ENDIAN - offset_table.num_tables = bswap_16(offset_table.num_tables); -#endif // LITTLE_ENDIAN + std::map > table; - bool name_table_exists = false; - bool cff_table_exists = false; - uint32_t name_offset = 0; - - for (uint16_t i = 0; i < offset_table.num_tables; i++) { - struct otf_table_directory_s { + for (uint16_t i = 0; i < num_tables; i++) { + struct ttf_table_directory_s { char tag[4]; uint32_t check_sum; uint32_t offset; uint32_t length; } table_directory; + if (!(offset_table_size + (i + 1) * + sizeof(struct ttf_table_directory_s) <= + font_data.size())) { + ERROR_ACCESS("table directory"); + break; + } memcpy(&table_directory, - &font_data[sizeof(struct otf_offset_table_s) + i * - sizeof(struct otf_table_directory_s)], - sizeof(struct otf_table_directory_s)); + &font_data[offset_table_size + i * + sizeof(struct ttf_table_directory_s)], + sizeof(struct ttf_table_directory_s)); #ifdef LITTLE_ENDIAN table_directory.offset = bswap_32(table_directory.offset); table_directory.length = bswap_32(table_directory.length); #endif // LITTLE_ENDIAN - if (strncmp(table_directory.tag, "name", 4) == 0) { - name_offset = table_directory.offset; - name_table_exists = true; + if (!(table_directory.offset + table_directory.length <= + font_data.size())) { + ERROR_ACCESS("table directory"); + break; } - else if (strncmp(table_directory.tag, "CFF ", 4) == 0) { - cff_offset = table_directory.offset; - cff_length = table_directory.length; - cff_table_exists = true; + table[std::string(table_directory.tag, + table_directory.tag + 4)] = + std::pair( + table_directory.offset, + table_directory.length); } - } - if (!(name_table_exists && cff_table_exists)) { - return false; + return table; } - // name + void font_embed_t::parse_ttf_cmap( + std::map &cid_map, + const std::vector &font_data, + uint32_t cmap_offset) + { + if (cmap_offset == 0) { + return; + } - struct otf_naming_table_header_s { - uint16_t format; - uint16_t count; - uint16_t string_offset; - } naming_table_header; + struct ttf_mapping_table_s { + uint16_t version; + uint16_t num_encoding_tables; + } mapping_table; - memcpy(&naming_table_header, &font_data[name_offset], - sizeof(struct otf_naming_table_header_s)); + memcpy(&mapping_table, &font_data[cmap_offset], + sizeof(struct ttf_mapping_table_s)); #ifdef LITTLE_ENDIAN - naming_table_header.format = - bswap_16(naming_table_header.format); - naming_table_header.count = - bswap_16(naming_table_header.count); - naming_table_header.string_offset = - bswap_16(naming_table_header.string_offset); + mapping_table.num_encoding_tables = + bswap_16(mapping_table.num_encoding_tables); #endif // LITTLE_ENDIAN - cid_encoding_id = 0xffffU; + uint32_t *subtable_offset = + new uint32_t[mapping_table.num_encoding_tables]; - for (uint16_t i = 0; i < naming_table_header.count; i++) { - struct otf_name_record_s { + for (uint16_t i = 0; + i < mapping_table.num_encoding_tables; i++) { + struct ttf_encoding_table_s { uint16_t platform_id; uint16_t encoding_id; - uint16_t language_id; - uint16_t name_id; - uint16_t length; - uint16_t offset; - } name_record; - const size_t base_offset = name_offset + - sizeof(struct otf_naming_table_header_s); - - memcpy(&name_record, - &font_data[base_offset + i * - sizeof(struct otf_name_record_s)], - sizeof(struct otf_name_record_s)); + uint32_t offset; + } encoding_table; + + memcpy( + &encoding_table, + &font_data[cmap_offset + + sizeof(struct ttf_mapping_table_s) + + i * sizeof(struct ttf_encoding_table_s)], + sizeof(struct ttf_encoding_table_s)); #ifdef LITTLE_ENDIAN - name_record.platform_id = - bswap_16(name_record.platform_id); - name_record.encoding_id = - bswap_16(name_record.encoding_id); - name_record.name_id = bswap_16(name_record.name_id); + encoding_table.platform_id = + bswap_16(encoding_table.platform_id); + encoding_table.encoding_id = + bswap_16(encoding_table.encoding_id); + encoding_table.offset = bswap_32(encoding_table.offset); #endif // LITTLE_ENDIAN - if (name_record.platform_id == 1 && - name_record.encoding_id == 0 && - name_record.name_id == 6) { - // Postscript name in Mac OS Roman - // - // The font name in Mac OS Roman encoding is - // sufficient to obtain an ASCII PostScript name (and - // is required by OpenType specification), while the - // Windows platform uses a UCS-2 string that would - // require conversion. + subtable_offset[i] = cmap_offset + encoding_table.offset; + } + + int priority_max = 0; + + for (uint16_t i = 0; + i < mapping_table.num_encoding_tables; i++) { + struct ttf_encoding_subtable_common_s { + uint16_t format; + uint16_t length; + uint16_t language; + } encoding_subtable_common; + + memcpy(&encoding_subtable_common, + &font_data[subtable_offset[i]], + sizeof(struct ttf_encoding_subtable_common_s)); #ifdef LITTLE_ENDIAN - name_record.length = bswap_16(name_record.length); - name_record.offset = bswap_16(name_record.offset); + encoding_subtable_common.format = + bswap_16(encoding_subtable_common.format); + encoding_subtable_common.length = + bswap_16(encoding_subtable_common.length); + encoding_subtable_common.language = + bswap_16(encoding_subtable_common.language); #endif // LITTLE_ENDIAN - char *buffer = new char[name_record.length + 1]; - - memcpy(buffer, - &font_data[name_offset + - naming_table_header.string_offset + - name_record.offset], - name_record.length); - buffer[name_record.length] = '\0'; - font_name = buffer; + size_t offset_current = subtable_offset[i]; +#if 0 + fprintf(stderr, "%s:%d: encoding_subtable_common.format " + "= %hu\n", __FILE__, __LINE__, + encoding_subtable_common.format); + fprintf(stderr, "%s:%d: encoding_subtable_common.length " + "= %hu\n", __FILE__, __LINE__, + encoding_subtable_common.length); + fprintf(stderr, "%s:%d: encoding_subtable_common.language " + "= %hu\n", __FILE__, __LINE__, + encoding_subtable_common.language); +#endif - delete [] buffer; + int priority; + + switch(encoding_subtable_common.format) { + ///////////////////////////////////////////////////// + // 8 and 16 bit mappings + // Priority range 1, 3..5 (2 reserved for format 13) + case 0: + priority = 1; + // Byte encoding table + break; + case 2: + // High-byte mapping through table + priority = 3; + break; + case 4: + // Segment mapping to delta values + priority = 5; +#if 0 + fprintf(stderr, "%s:%d: priority = %d, priority_max " + "= %d\n", __FILE__, __LINE__, priority, + priority_max); +#endif + if (priority_max <= priority) { + parse_ttf_encoding_subtable_format4( + cid_map, font_data, offset_current); + priority_max = priority; } - if (name_record.platform_id == 1 && - name_record.name_id == 20) { - // PostScript CID findfont name - // - // encoding_id Macintosh CMap - // --------------------------- - // 1 83pv-RKSJ-H - // 2 B5pc-H - // 3 KSCpc-EUC-H - // 25 GBpc-EUC-H - cid_encoding_id = name_record.encoding_id; - // The actual Macintosh encoding CMap name is of no - // further use. Note that Adobe currently only - // actively maintains the Unicode based CMaps. + break; + case 6: + // Trimmed table mapping + priority = 5; + break; + ///////////////////////////////////////////////////// + // 32-bit mappings + // Priority range 6..9 (2 reserved for format 13) + case 8: + // Mixed 16-bit and 32-bit coverage + priority = 6; + break; + case 10: + // Trimmed array + priority = 6; + break; + case 12: + // Segmented coverage + priority = 6; + if (priority_max <= priority) { + parse_ttf_encoding_subtable_format12( + cid_map, font_data, offset_current); + priority_max = priority; + } + break; + case 13: + // Last resort font + priority = 2; + break; + case 14: + // Unicode variation sequences + priority = 9; + break; + default: + delete [] subtable_offset; + return; } } - return true; + delete [] subtable_offset; } - bool font_embed_t::parse_ttf_header( - std::string &font_name, double *font_bbox, - std::map &cid_map, - std::vector &char_strings, - const std::vector &font_data) + void font_embed_t::parse_ttf_head( + double *font_bbox, uint16_t &units_per_em, + const std::vector &font_data, + uint32_t head_offset) { - cid_map.clear(); - char_strings.clear(); - - struct ttf_offset_table_s { - fixed_t sfnt_version; - uint16_t num_tables; - uint16_t search_range; - uint16_t entry_selector; - uint16_t range_shift; - } offset_table; - - memcpy(&offset_table, &font_data[0], - sizeof(struct ttf_offset_table_s)); + if (head_offset == 0) { + return; + } + + struct ttf_head_table_s { + fixed_t version; + fixed_t font_revision; + uint32_t check_sum_adjustment; + uint32_t magic_number; + uint16_t flags; + uint16_t units_per_em; + char created[8]; + char modified[8]; + int16_t x_min; + int16_t y_min; + int16_t x_max; + int16_t y_max; + uint16_t mac_style; + uint16_t lowest_rec_ppem; + int16_t font_direction_hint; + int16_t index_to_loc_format; + int16_t glyph_data_format; + } head_table; + + if (!(head_offset + sizeof(struct ttf_head_table_s) <= + font_data.size())) { + ERROR_ACCESS("head table"); + return; + } + memcpy(&head_table, &font_data[head_offset], + sizeof(struct ttf_head_table_s)); #ifdef LITTLE_ENDIAN - offset_table.sfnt_version = - bswap_32(offset_table.sfnt_version); - offset_table.num_tables = bswap_16(offset_table.num_tables); + head_table.units_per_em = bswap_16(head_table.units_per_em); + head_table.x_min = bswap_16(head_table.x_min); + head_table.y_min = bswap_16(head_table.y_min); + head_table.x_max = bswap_16(head_table.x_max); + head_table.y_max = bswap_16(head_table.y_max); #endif // LITTLE_ENDIAN - if (offset_table.sfnt_version != 0x00010000) { - return false; + + units_per_em = head_table.units_per_em; + font_bbox[0] = head_table.x_min * 1000.0 / units_per_em; + font_bbox[1] = head_table.y_min * 1000.0 / units_per_em; + font_bbox[2] = head_table.x_max * 1000.0 / units_per_em; + font_bbox[3] = head_table.y_max * 1000.0 / units_per_em; } - size_t name_offset = 0; - //size_t name_length = 0; - size_t head_offset = 0; - //size_t head_length = 0; - size_t cmap_offset = 0; - //size_t cmap_length = 0; - size_t post_offset = 0; - //size_t post_length = 0; - - for (uint16_t i = 0; i < offset_table.num_tables; i++) { - struct ttf_table_directory_s { - char tag[4]; - uint32_t check_sum; - uint32_t offset; - uint32_t length; - } table_directory; + uint16_t font_embed_t::parse_ttf_hhea( + const std::vector &font_data, + uint32_t hhea_offset) + { + if (!(hhea_offset + 36 <= font_data.size())) { + ERROR_ACCESS("hhea table"); + } - memcpy(&table_directory, - &font_data[sizeof(struct ttf_offset_table_s) + i * - sizeof(struct ttf_table_directory_s)], - sizeof(struct ttf_table_directory_s)); + // We don't care about anything other than numberOfHMetrics, which + // sits at a common position for both versions 0.5 (OTF CFF) + // and 1.0 (TTF). + + uint16_t number_of_h_metrics; + + memcpy(&number_of_h_metrics, &font_data[hhea_offset + 34], 2); #ifdef LITTLE_ENDIAN - table_directory.offset = - bswap_32(table_directory.offset); - table_directory.length = - bswap_32(table_directory.length); + number_of_h_metrics = bswap_16(number_of_h_metrics); #endif // LITTLE_ENDIAN -#if 0 - fprintf(stderr, "%s:%d: tag = %c%c%c%c, offset = %u, " - "length = %u\n", __FILE__, __LINE__, - table_directory.tag[0], table_directory.tag[1], - table_directory.tag[2], table_directory.tag[3], - table_directory.offset, table_directory.length); -#endif - if (strncmp(table_directory.tag, "name", 4) == 0) { - name_offset = table_directory.offset; - //name_length = table_directory.length; + + return number_of_h_metrics; } - else if (strncmp(table_directory.tag, "head", 4) == 0) { - head_offset = table_directory.offset; - //head_length = table_directory.length; + + std::vector font_embed_t::parse_ttf_hmtx( + const std::vector &font_data, + uint32_t hmtx_offset, uint16_t number_of_h_metrics) + { + std::vector advance_width; + + advance_width.resize(number_of_h_metrics); + for (size_t i = 0; i < number_of_h_metrics; i++) { + memcpy(&advance_width[i], &font_data[hmtx_offset + 4 * i], 2); +#ifdef LITTLE_ENDIAN + advance_width[i] = bswap_16(advance_width[i]); +#endif // LITTLE_ENDIAN } - else if (strncmp(table_directory.tag, "cmap", 4) == 0) { - cmap_offset = table_directory.offset; - //cmap_length = table_directory.length; + + return advance_width; } - else if (strncmp(table_directory.tag, "post", 4) == 0) { - post_offset = table_directory.offset; - //post_length = table_directory.length; + + uint16_t font_embed_t::parse_ttf_maxp( + const std::vector &font_data, + uint32_t maxp_offset) + { + if (!(maxp_offset + 6 <= font_data.size())) { + ERROR_ACCESS("maxp table"); } + + // We don't care about anything other than numGlyphs, which + // sits at a common position for both versions 0.5 (OTF CFF) + // and 1.0 (TTF). + + uint16_t num_glyphs; + + memcpy(&num_glyphs, &font_data[maxp_offset + 4], 2); +#ifdef LITTLE_ENDIAN + num_glyphs = bswap_16(num_glyphs); +#endif // LITTLE_ENDIAN + + return num_glyphs; } - // name + void font_embed_t::parse_ttf_name( + std::string &font_name, uint16_t &cid_encoding_id, + const std::vector &font_data, + uint32_t name_offset) + { + if (name_offset == 0) { + return; + } struct ttf_naming_table_header_s { uint16_t format; @@ -604,8 +936,14 @@ namespace mathtext { uint16_t string_offset; } naming_table_header; - memcpy(&naming_table_header, - &font_data[name_offset], + if (!(name_offset + + sizeof(struct ttf_naming_table_header_s) <= + font_data.size())) { + ERROR_ACCESS("name table"); + return; + } + + memcpy(&naming_table_header, &font_data[name_offset], sizeof(struct ttf_naming_table_header_s)); #ifdef LITTLE_ENDIAN naming_table_header.format = @@ -616,6 +954,8 @@ namespace mathtext { bswap_16(naming_table_header.string_offset); #endif // LITTLE_ENDIAN + cid_encoding_id = 0xffffU; + for (uint16_t i = 0; i < naming_table_header.count; i++) { struct ttf_name_record_s { uint16_t platform_id; @@ -625,12 +965,18 @@ namespace mathtext { uint16_t length; uint16_t offset; } name_record; - - memcpy( - &name_record, - &font_data[name_offset + - sizeof(struct ttf_naming_table_header_s) + - i * sizeof(struct ttf_name_record_s)], + const size_t base_offset = name_offset + + sizeof(struct ttf_naming_table_header_s); + + if (!(base_offset + (i + 1) * + sizeof(struct ttf_name_record_s) <= + font_data.size())) { + ERROR_ACCESS("name table"); + continue; + } + memcpy(&name_record, + &font_data[base_offset + i * + sizeof(struct ttf_name_record_s)], sizeof(struct ttf_name_record_s)); #ifdef LITTLE_ENDIAN name_record.platform_id = @@ -639,29 +985,34 @@ namespace mathtext { bswap_16(name_record.encoding_id); name_record.name_id = bswap_16(name_record.name_id); #endif // LITTLE_ENDIAN - // the font name in mac os roman encoding is good enough - // to obtain an ASCII post_script name, while the windows - // platform uses a utF-16 string that would require - // conversion. if (name_record.platform_id == 1 && name_record.encoding_id == 0 && name_record.name_id == 6) { + // Postscript name in Mac OS Roman + // + // The font name in Mac OS Roman encoding is + // sufficient to obtain an ASCII PostScript name (and + // is required by OpenType specification), while the + // Windows platform uses a UCS-2 string that would + // require conversion. #ifdef LITTLE_ENDIAN name_record.length = bswap_16(name_record.length); name_record.offset = bswap_16(name_record.offset); #endif // LITTLE_ENDIAN - - char *buffer = new char[name_record.length + 1]; - - memcpy(buffer, + if (!(name_offset + + naming_table_header.string_offset + + name_record.offset + name_record.length < + font_data.size())) { + ERROR_ACCESS("name table"); + continue; + } + + const char *p = reinterpret_cast( &font_data[name_offset + naming_table_header.string_offset + - name_record.offset], - name_record.length * sizeof(char)); - buffer[name_record.length] = '\0'; - font_name = buffer; + name_record.offset]); - delete [] buffer; + font_name = std::string(p, p + name_record.length); } else if (name_record.platform_id == 3 && name_record.encoding_id == 1 && @@ -670,68 +1021,175 @@ namespace mathtext { name_record.length = bswap_16(name_record.length); name_record.offset = bswap_16(name_record.offset); #endif // LITTLE_ENDIAN - + if (!(name_offset + + naming_table_header.string_offset + + name_record.offset + name_record.length < + font_data.size())) { + ERROR_ACCESS("name table"); + continue; + } // Very ugly UCS-2 to ASCII conversion, but should // work for most font names - char *buffer = - new char[(name_record.length >> 1) + 1]; + font_name.resize(name_record.length >> 1); for (uint16_t j = 0; j < (name_record.length >> 1); j++) { - buffer[j] = + font_name[j] = font_data[name_offset + naming_table_header.string_offset + name_record.offset + j * 2 + 1]; } - buffer[name_record.length >> 1] = '\0'; - font_name = buffer; - - delete [] buffer; + } + if (name_record.platform_id == 1 && + name_record.name_id == 20) { + // PostScript CID findfont name + // + // encoding_id Macintosh CMap + // --------------------------- + // 1 83pv-RKSJ-H + // 2 B5pc-H + // 3 KSCpc-EUC-H + // 25 GBpc-EUC-H + cid_encoding_id = name_record.encoding_id; + // The actual Macintosh encoding CMap name is of no + // further use. Note that Adobe currently only + // actively maintains the Unicode based CMaps. + } } } - // head - - struct ttf_head_table_s { - fixed_t version; - fixed_t font_revision; - uint32_t check_sum_adjustment; - uint32_t magic_number; - uint16_t flags; - uint16_t units_per_em; - char created[8]; - char modified[8]; - int16_t x_min; - int16_t y_min; - int16_t x_max; - int16_t y_max; - uint16_t mac_style; - uint16_t lowest_rec_ppem; - int16_t font_direction_hint; - int16_t index_to_loc_format; - int16_t glyph_data_format; - } head_table; - - memcpy(&head_table, &font_data[head_offset], - sizeof(struct ttf_head_table_s)); + void font_embed_t::parse_ttf_os_2( + uint32_t &font_descriptor_flag, double &ascent, + double &descent, double &leading, double &cap_height, + double &x_height, double &stem_v, double &avg_width, + const std::vector &font_data, + uint32_t os_2_offset, uint16_t units_per_em) + { + if (os_2_offset == 0) { + return; + } + + struct ttf_os_2_table_s { + uint16_t version; + int16_t x_avg_char_width; + uint16_t us_weight_class; + uint16_t us_width_class; + uint16_t fs_type; + int16_t y_subscript_x_size; + int16_t y_subscript_y_size; + int16_t y_subscript_x_offset; + int16_t y_subscript_y_offset; + int16_t y_superscript_x_size; + int16_t y_superscript_y_size; + int16_t y_superscript_x_offset; + int16_t y_superscript_y_offset; + int16_t y_strikeout_size; + int16_t y_strikeout_position; + int16_t s_family_class; + uint8_t panose[10]; + uint32_t ul_unicode_range1; + uint32_t ul_unicode_range2; + uint32_t ul_unicode_range3; + uint32_t ul_unicode_range4; + char ach_vend_id[4]; + uint16_t fs_selection; + uint16_t us_first_char_index; + uint16_t us_last_char_index; + int16_t s_typo_ascender; + int16_t s_typo_descender; + int16_t s_typo_line_gap; + uint16_t us_win_ascent; + uint16_t us_win_descent; + uint32_t ul_code_page_range1; + uint32_t ul_code_page_range2; + int16_t s_x_height; + int16_t s_cap_height; + uint16_t us_default_char; + uint16_t us_break_char; + uint16_t us_max_context; + uint16_t us_lower_optical_point_size; + uint16_t us_upper_optical_point_size; + } os_2_table; + + if (!(os_2_offset + sizeof(struct ttf_os_2_table_s) <= + font_data.size())) { + ERROR_ACCESS("OS/2 table"); + return; + } + memcpy(&os_2_table, &font_data[os_2_offset], + sizeof(struct ttf_os_2_table_s)); #ifdef LITTLE_ENDIAN - head_table.units_per_em = bswap_16(head_table.units_per_em); - head_table.x_min = bswap_16(head_table.x_min); - head_table.y_min = bswap_16(head_table.y_min); - head_table.x_max = bswap_16(head_table.x_max); - head_table.y_max = bswap_16(head_table.y_max); + os_2_table.x_avg_char_width = + bswap_16(os_2_table.x_avg_char_width); + os_2_table.s_family_class = + bswap_16(os_2_table.s_family_class); + os_2_table.s_typo_ascender = + bswap_16(os_2_table.s_typo_ascender); + os_2_table.s_typo_descender = + bswap_16(os_2_table.s_typo_descender); + os_2_table.s_typo_line_gap = + bswap_16(os_2_table.s_typo_line_gap); + os_2_table.s_x_height = bswap_16(os_2_table.s_x_height); + os_2_table.s_cap_height = bswap_16(os_2_table.s_cap_height); #endif // LITTLE_ENDIAN - font_bbox[0] = - (double)head_table.x_min / head_table.units_per_em; - font_bbox[1] = - (double)head_table.y_min / head_table.units_per_em; - font_bbox[2] = - (double)head_table.x_max / head_table.units_per_em; - font_bbox[3] = - (double)head_table.y_max / head_table.units_per_em; - - // post + switch (os_2_table.s_family_class >> 8) { + case 1: + case 2: + case 3: + case 4: + case 5: + case 7: + // Serif + font_descriptor_flag |= (1U << 1); + break; + case 8: + // Sans serif + font_descriptor_flag &= ~(1U << 1); + break; + case 10: + // Script + font_descriptor_flag |= (1U << 3); + break; + case 12: + // Symbolic + font_descriptor_flag |= (1U << 2); + // Nonsymbolic + font_descriptor_flag &= ~(1U << 2); + break; + } + if (os_2_table.fs_selection & (1U << 0) || + os_2_table.fs_selection & (1U << 9)) { + // Italic (or oblique) + font_descriptor_flag |= (1U << 6); + } + ascent = os_2_table.s_typo_ascender * 1000.0 / units_per_em; + descent = os_2_table.s_typo_descender * 1000.0 / units_per_em; + leading = os_2_table.s_typo_line_gap * 1000.0 / units_per_em; + cap_height = os_2_table.s_cap_height * 1000.0 / units_per_em; + x_height = os_2_table.s_x_height * 1000.0 / units_per_em; + + // The PDFLib values + static const uint16_t weight_class_stem_v[] = { + 50, 71, 109, 125, 135, 165, 201, 241 + }; + + stem_v = weight_class_stem_v[ + std::max(0, std::min(7, + os_2_table.us_weight_class / 100)) - 3]; + avg_width = os_2_table.x_avg_char_width * 1000.0 / + units_per_em; + } + + void font_embed_t::parse_ttf_post( + std::vector &charset, + double &italic_angle, uint32_t &font_descriptor_flags, + const std::vector &font_data, + uint32_t post_offset) + { + if (post_offset == 0) { + return; + } struct ttf_post_script_table_s { fixed_t format_type; @@ -745,6 +1203,13 @@ namespace mathtext { uint32_t max_mem_type1; } post_script_table; + if (!(post_offset + + sizeof(struct ttf_post_script_table_s) <= + font_data.size())) { + ERROR_ACCESS("post table"); + return; + } + memcpy(&post_script_table, &font_data[post_offset], sizeof(struct ttf_post_script_table_s)); @@ -752,12 +1217,25 @@ namespace mathtext { #ifdef LITTLE_ENDIAN post_script_table.format_type = bswap_32(post_script_table.format_type); + post_script_table.italic_angle = + bswap_32(post_script_table.italic_angle); + post_script_table.is_fixed_pitch = + bswap_32(post_script_table.is_fixed_pitch); post_script_table.min_mem_type42 = bswap_32(post_script_table.min_mem_type42); post_script_table.max_mem_type42 = bswap_32(post_script_table.max_mem_type42); #endif // LITTLE_ENDIAN + italic_angle = post_script_table.italic_angle * + (1.0 / (1U << 16)); + if (post_script_table.italic_angle != 0) { + font_descriptor_flags |= (1U << 6); + } + if (post_script_table.is_fixed_pitch != 0) { + font_descriptor_flags |= (1U << 0); + } + size_t offset_current = post_offset; #if 0 @@ -827,10 +1305,10 @@ namespace mathtext { delete [] buffer; } - char_strings.resize(num_glyphs); + charset.resize(num_glyphs); #include "table/macintoshordering.h" for (uint16_t glyph = 0; glyph < num_glyphs; glyph++) { - char_strings[glyph] = glyph_name_index[glyph] >= 258 ? + charset[glyph] = glyph_name_index[glyph] >= 258 ? glyph_name[glyph_name_index[glyph] - 258].c_str() : macintosh_ordering[glyph_name_index[glyph]]; } @@ -850,7 +1328,7 @@ namespace mathtext { "0x%08x\n", __FILE__, __LINE__, post_script_table.format_type); - return false; + return; } #if 0 if (post_script_table.format_type == 0x00025000) { @@ -858,167 +1336,450 @@ namespace mathtext { // glyph set. Deprecated as of OpenType Specification v1.3 // // numberOfGlyphs, offset[numGlyphs] - return false; + return; } #endif - - // cmap - - struct ttf_mapping_table_s { - uint16_t version; - uint16_t num_encoding_tables; - } mapping_table; - - memcpy(&mapping_table, &font_data[cmap_offset], - sizeof(struct ttf_mapping_table_s)); + } + + std::vector > + font_embed_t::parse_cff_index( + const std::vector &font_data, + uint32_t ¤t_offset, uint32_t *skip) + { + struct cff_index_s { + uint16_t count; + uint8_t off_size; + std::vector offset; + std::vector > data; + } cff_index; + + memcpy(&cff_index.count, &font_data[current_offset], 2); #ifdef LITTLE_ENDIAN - mapping_table.num_encoding_tables = - bswap_16(mapping_table.num_encoding_tables); + cff_index.count = bswap_16(cff_index.count); #endif // LITTLE_ENDIAN - - uint32_t *subtable_offset = - new uint32_t[mapping_table.num_encoding_tables]; - - for (uint16_t i = 0; - i < mapping_table.num_encoding_tables; i++) { - struct ttf_encoding_table_s { - uint16_t platform_id; - uint16_t encoding_id; - uint32_t offset; - } encoding_table; - - memcpy( - &encoding_table, - &font_data[cmap_offset + - sizeof(struct ttf_mapping_table_s) + - i * sizeof(struct ttf_encoding_table_s)], - sizeof(struct ttf_encoding_table_s)); + current_offset += 2; + if (!(cff_index.count > 0)) { + return cff_index.data; + } + + cff_index.off_size = font_data[current_offset]; + current_offset++; + + for (size_t i = 0; i < cff_index.count + 1U; i++) { + cff_index.offset.push_back(font_data[current_offset]); + current_offset++; + for (size_t j = 1; j < cff_index.off_size; j++) { + cff_index.offset.back() <<= 8; + cff_index.offset.back() |= font_data[current_offset]; + current_offset++; + } + } + if (skip == NULL) { + for (size_t i = 0; i < cff_index.count; i++) { + cff_index.data.push_back(std::vector( + &font_data[current_offset + + cff_index.offset[i] - 1], + &font_data[current_offset + + cff_index.offset[i + 1] - 1])); + } + } + else { + *skip = cff_index.count; + } + current_offset += cff_index.offset.back() - 1; + + return cff_index.data; + } + + double font_embed_t::parse_cff_dict_number( + std::vector::const_iterator &data, + std::vector::const_iterator end) + { + const char *nibble_chr[16] = { + "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", + ".", "E", "E-", "", "-", "" + }; + std::string nibble_str; + uint8_t nibble = 0; + bool nibble_high = true; + double ret = NAN; + int16_t ret_int16; + int32_t ret_int32; + + if (!(data < end)) { + ERROR_ACCESS("CFF DICT number"); + return NAN; + } + switch (data[0]) { + case 0x1e: + // Floating point value + while (!(nibble_high && nibble == 0xf) && data < end) { + nibble = nibble_high ? (data[0] >> 4) : + data[0] & 0xf; + nibble_str += nibble_chr[nibble]; + nibble_high = !nibble_high; + if (nibble_high) { + data++; + if (!(data < end)) { + ERROR_ACCESS("CFF DICT floating-point " + "number"); + return NAN; + } + } + }; + sscanf(nibble_str.c_str(), "%lf", &ret); + break; + case 28: + if (!(data + 3 <= end)) { + ERROR_ACCESS("CFF DICT 3 byte integer number"); + return NAN; + } + ret_int16 = (data[1] << 8) | data[2]; + ret = ret_int16; + data += 3; + break; + case 29: + if (!(data + 5 <= end)) { + ERROR_ACCESS("CFF DICT 5 byte integer number"); + return NAN; + } + ret_int32 = + (data[1] << 24) | + (data[2] << 16) | + (data[3] << 8) | + data[4]; + ret = ret_int32; + data += 5; + break; + default: + if (data[0] >= 32 && data[0] <= 246) { + ret = data[0] - 139; + data++; + } + else if (data[0] >= 247 && data[0] <= 250) { + if (!(data + 2 <= end)) { + ERROR_ACCESS("CFF DICT 2 byte positive integer " + "number"); + return NAN; + } + ret = (data[0] - 247) * 256 + + data[1] + 108; + data += 2; + } + else if (data[0] >= 251 && data[0] <= 254) { + if (!(data + 2 <= end)) { + ERROR_ACCESS("CFF DICT 2 byte negative integer " + "number"); + return NAN; + } + ret = -(data[0] - 251) * 256 - + data[1] - 108; + data += 2; + } + else { + fprintf(stderr, "%s:%d: Illegal CFF DICT number, " + "b0 = %d, 0x%02x\n", + __FILE__, __LINE__, data[0], data[0]); + } + } + + return ret; + } + + double font_embed_t::search_cff_top_dict_number( + const std::vector &top_dict, + uint8_t operator_value_1, uint8_t operator_value_2) + { + if (!(operator_value_1 <= 21)) { + fprintf(stderr, "%s:%d: Illegal CFF operator %d, " + "0x%02x requested\n", __FILE__, __LINE__, + operator_value_1, operator_value_1); + return NAN; + } + + double last = NAN; + + for (std::vector::const_iterator iterator = + top_dict.begin(); + iterator != top_dict.end();) { + if (operator_value_1 == 12 ? + iterator[0] == 12 && iterator[1] == operator_value_2 : + iterator[0] == operator_value_1) { + return last; + } + else if (iterator[0] <= 21) { + // Some other operators + last = NAN; + iterator += iterator[0] == 12 ? 2 : 1; + } + else if ((iterator[0] >= 28 && iterator[0] <= 30) || + (iterator[0] >= 32 && iterator[0] <= 254)) { + last = parse_cff_dict_number(iterator, top_dict.end()); + } + else { + fprintf(stderr, "%s:%d: error: unexpected byte %d, " + "0x%02x in CFF DICT (attempt to skip...)\n", + __FILE__, __LINE__, iterator[0], iterator[0]); + iterator++; + } + } + + return NAN; + } + + std::string font_embed_t::cff_sid_to_string( + uint16_t sid, + const std::vector > &string_index) + { +#include "table/cffstdstr.h" + if (!(sid < ncff_standard_string + string_index.size())) { + ERROR_ACCESS("CFF SID"); + } + + return sid < ncff_standard_string ? + cff_standard_string[sid] : + sid - ncff_standard_string < string_index.size() ? + std::string( + string_index[sid - ncff_standard_string].begin(), + string_index[sid - ncff_standard_string].end()) : + ""; + } + + std::vector font_embed_t::parse_cff_charset( + const std::vector &data, + uint32_t charset_offset, uint32_t nglyph, + const std::vector > &string_index) + { + if (!(charset_offset < data.size())) { + ERROR_ACCESS("CFF Charset"); + } + + const uint8_t format = data[charset_offset]; + std::vector charset; + + switch (format) { + case 0: + charset.push_back(".notdef"); + for (size_t i = 0; i < nglyph - 1; i++) { + uint16_t sid; + + if (!(charset_offset + 2 * i + 3 <= data.size())) { + ERROR_ACCESS("CFF Charset"); + } + memcpy(&sid, &data[charset_offset + 2 * i + 1], 2); #ifdef LITTLE_ENDIAN - encoding_table.platform_id = - bswap_16(encoding_table.platform_id); - encoding_table.encoding_id = - bswap_16(encoding_table.encoding_id); - encoding_table.offset = bswap_32(encoding_table.offset); + sid = bswap_16(sid); #endif // LITTLE_ENDIAN - subtable_offset[i] = cmap_offset + encoding_table.offset; + charset.push_back(cff_sid_to_string(sid, string_index)); + } + break; + default: + fprintf(stderr, "%s:%d: error: unsupported Charset " + "format %d\n", __FILE__, __LINE__, format); + break; } - int priority_max = 0; - - for (uint16_t i = 0; - i < mapping_table.num_encoding_tables; i++) { - struct ttf_encoding_subtable_common_s { - uint16_t format; - uint16_t length; - uint16_t language; - } encoding_subtable_common; - - memcpy(&encoding_subtable_common, - &font_data[subtable_offset[i]], - sizeof(struct ttf_encoding_subtable_common_s)); + return charset; + } + + void font_embed_t::parse_cff( + std::vector &charset, + const std::vector &font_data, + uint32_t cff_offset) + { + struct cff_header_s { + uint8_t major; + uint8_t minor; + uint8_t hdr_size; + uint8_t off_size; + } cff_header; + + uint32_t current_offset = cff_offset; + + if (!(current_offset + sizeof(struct cff_header_s) <= + font_data.size())) { + ERROR_ACCESS("CFF header"); + } + + memcpy(&cff_header, &font_data[current_offset], + sizeof(struct cff_header_s)); + current_offset += sizeof(struct cff_header_s); + + const std::vector > cff_name_index = + parse_cff_index(font_data, current_offset); + const std::vector > cff_top_dict_index = + parse_cff_index(font_data, current_offset); + + if (cff_top_dict_index.size() != 1) { + fprintf(stderr, "%s:%d: error: CFF FontSet is not " + "supported\n", __FILE__, __LINE__); + return; + } + + const uint32_t charset_offset = cff_offset + + search_cff_top_dict_number(cff_top_dict_index[0], 15); + uint32_t charstrings_offset = cff_offset + + search_cff_top_dict_number(cff_top_dict_index[0], 17); + uint32_t cff_nglyph = 0; + + parse_cff_index(font_data, charstrings_offset, &cff_nglyph); + + const std::vector > string_index = + parse_cff_index(font_data, current_offset); + + charset = parse_cff_charset(font_data, charset_offset, + cff_nglyph, string_index); + } + + bool font_embed_t::parse_otf_cff_header( + std::string &font_name, unsigned short &cid_encoding_id, + uint32_t font_descriptor_flags, double *font_bbox, + double &italic_angle, double &ascent, double &descent, + double &leading, double &cap_height, double &x_height, + double &stem_v,double &avg_width, + std::map &cid_map, + std::vector &charset, + std::vector &advance_width, + unsigned int &cff_offset, unsigned int &cff_length, + const std::vector &font_data) + { + // OpenType file structure + struct otf_offset_table_s { + char sfnt_version[4]; + uint16_t num_tables; + uint16_t search_range; + uint16_t entry_selector; + uint16_t range_shift; + } offset_table; + + if (!(sizeof(struct otf_offset_table_s) <= + font_data.size())) { + ERROR_ACCESS("OTF offset table"); + } + memcpy(&offset_table, &font_data[0], + sizeof(struct otf_offset_table_s)); + if (strncmp(offset_table.sfnt_version, "OTTO", 4) != 0) { + // Not a OpenType CFF/Type 2 font + return false; + } #ifdef LITTLE_ENDIAN - encoding_subtable_common.format = - bswap_16(encoding_subtable_common.format); - encoding_subtable_common.length = - bswap_16(encoding_subtable_common.length); - encoding_subtable_common.language = - bswap_16(encoding_subtable_common.language); + offset_table.num_tables = bswap_16(offset_table.num_tables); #endif // LITTLE_ENDIAN - offset_current = subtable_offset[i] + - sizeof(struct ttf_encoding_subtable_common_s); -#if 0 - fprintf(stderr, "%s:%d: encoding_subtable_common.format " - "= %hu\n", __FILE__, __LINE__, - encoding_subtable_common.format); - fprintf(stderr, "%s:%d: encoding_subtable_common.length " - "= %hu\n", __FILE__, __LINE__, - encoding_subtable_common.length); - fprintf(stderr, "%s:%d: encoding_subtable_common.language " - "= %hu\n", __FILE__, __LINE__, - encoding_subtable_common.language); -#endif - - int priority; - - switch(encoding_subtable_common.format) { - ///////////////////////////////////////////////////// - // 8 and 16 bit mappings - // Priority range 1, 3..5 (2 reserved for format 13) - case 0: - priority = 1; - // Byte encoding table - break; - case 2: - // High-byte mapping through table - priority = 3; - break; - case 4: - // Segment mapping to delta values - priority = 5; -#if 0 - fprintf(stderr, "%s:%d: priority = %d, priority_max " - "= %d\n", __FILE__, __LINE__, priority, - priority_max); -#endif - if (priority_max <= priority) { - parse_ttf_encoding_subtable_format4( - cid_map, font_data, offset_current, - encoding_subtable_common.length); - priority_max = priority; + std::map > table = + parse_ttf_offset_table( + font_data, sizeof(struct otf_offset_table_s), + offset_table.num_tables); + + const uint32_t cmap_offset = table["cmap"].first; + const uint32_t head_offset = table["head"].first; + const uint32_t hhea_offset = table["hhea"].first; + const uint32_t hmtx_offset = table["hmtx"].first; + const uint32_t maxp_offset = table["maxp"].first; + const uint32_t name_offset = table["name"].first; + const uint32_t os_2_offset = table["OS/2"].first; + const uint32_t post_offset = table["post"].first; + + cff_offset = table["CFF "].first; + cff_length = table["CFF "].second; + + if (!(cmap_offset != 0 && head_offset != 0 && + hhea_offset != 0 && hmtx_offset != 0 && + maxp_offset != 0 && name_offset != 0 && + os_2_offset != 0 && cff_offset != 0)) { + fprintf(stderr, "%s:%d: error: OTF CFF font is " + "missing required tables\n", __FILE__, __LINE__); + return false; } - break; - case 6: - // Trimmed table mapping - priority = 5; - break; - ///////////////////////////////////////////////////// - // 32-bit mappings - // Priority range 6..9 (2 reserved for format 13) - case 8: - // Mixed 16-bit and 32-bit coverage - priority = 6; - break; - case 10: - // Trimmed array - priority = 6; - break; - case 12: - // Segmented coverage - priority = 6; - break; - case 13: - // Last resort font - priority = 2; - break; - case 14: - // Unicode variation sequences - priority = 9; - break; - default: - delete [] subtable_offset; + + parse_ttf_name(font_name, cid_encoding_id, font_data, + name_offset); + + uint16_t units_per_em; + + parse_ttf_head(font_bbox, units_per_em, font_data, + head_offset); + font_descriptor_flags = 0; + parse_ttf_post(charset, italic_angle, font_descriptor_flags, + font_data, post_offset); + parse_ttf_cmap(cid_map, font_data, cmap_offset); + parse_ttf_os_2(font_descriptor_flags, ascent, descent, + leading, cap_height, x_height, stem_v, + avg_width, font_data, os_2_offset, + units_per_em); + + const uint16_t num_glyphs = + parse_ttf_maxp(font_data, maxp_offset); + advance_width = + parse_ttf_hmtx(font_data, hmtx_offset, + parse_ttf_hhea(font_data, hhea_offset)); + + if (advance_width.empty()) { + fprintf(stderr, "%s:%d: error: hMetrics in hmtx is " + "empty\n", __FILE__, __LINE__); return false; } - } + advance_width.resize(num_glyphs, advance_width.back()); - delete [] subtable_offset; + if (charset.empty()) { + parse_cff(charset, font_data, cff_offset); + } + cid_map.erase(L'\uffff'); + + return true; + } + + bool font_embed_t::parse_otf_cff_header( + std::string &font_name, unsigned short &cid_encoding_id, + unsigned int &cff_offset, unsigned int &cff_length, + const std::vector &font_data) + { + uint32_t font_descriptor_flags = 0; + double font_bbox[4]; + double italic_angle; + double ascent; + double descent; + double leading; + double cap_height; + double x_height; + double stem_v; + double avg_width; + std::map cid_map; + std::vector charset; + std::vector advance_width; + + return parse_otf_cff_header( + font_name, cid_encoding_id, font_descriptor_flags, + font_bbox, italic_angle, ascent, descent, leading, + cap_height, x_height, stem_v, avg_width, cid_map, + charset, advance_width, cff_offset, cff_length, + font_data); + } + + std::vector + font_embed_t::charset_from_adobe_glyph_list( + std::map &cid_map) + { // Regenerate cid_map from the Adobe glyph list - if (char_strings.empty() && !cid_map.empty()) { - char_strings.resize(cid_map.size()); - for (std::map::const_iterator iterator = cid_map.begin(); - iterator != cid_map.end(); ++iterator) { - if (iterator->second < char_strings.size()) { + std::vector charset; + + if (cid_map.empty()) { + return std::vector(1, ".notdef"); + } + charset.resize(cid_map.size()); + for (std::map::const_iterator iterator = + cid_map.begin(); + iterator != cid_map.end(); iterator++) { + if (iterator->second < charset.size()) { #include "table/adobeglyphlist.h" - const wchar_t *lower = - std::lower_bound( - adobe_glyph_ucs, - adobe_glyph_ucs + nadobe_glyph, + const wchar_t *lower = std::lower_bound( + adobe_glyph_ucs, adobe_glyph_ucs + nadobe_glyph, iterator->first); - // The longest Adobe glyph name is 20 characters - // long (0x03b0 = upsilondieresistonos) + // The longest Adobe glyph name is 20 characters long + // (0x03b0 = upsilondieresistonos) char buf[21]; if (iterator->first == L'\uffff') { @@ -1034,150 +1795,134 @@ namespace mathtext { else { snprintf(buf, 21, "uni%04X", iterator->first); } - char_strings[iterator->second] = buf; - } + charset[iterator->second] = buf; } } - return true; + return charset; } -#if 0 - std::vector font_embed_t::subset_otf( - const std::vector &font_data, - const std::map &glyph_usage) + bool font_embed_t::parse_ttf_header( + std::string &font_name, unsigned short &cid_encoding_id, + uint32_t font_descriptor_flags, double *font_bbox, + double &italic_angle, double &ascent, double &descent, + double &leading, double &cap_height, double &x_height, + double &stem_v,double &avg_width, + std::map &cid_map, + std::vector &charset, + std::vector &advance_width, + const std::vector &font_data) { - std::vector retval; - struct otf_offset_table_s { - char sfnt_version[4]; + cid_map.clear(); + charset.clear(); + + struct ttf_offset_table_s { + fixed_t sfnt_version; uint16_t num_tables; uint16_t search_range; uint16_t entry_selector; uint16_t range_shift; } offset_table; + if (!(sizeof(struct ttf_offset_table_s) <= + font_data.size())) { + ERROR_ACCESS("TTF offset table"); + } memcpy(&offset_table, &font_data[0], - sizeof(struct otf_offset_table_s)); - if (strncmp(offset_table.sfnt_version, "OTTO", 4) != 0 || - strncmp(offset_table.sfnt_version, "\0\1\0\0", 4) != 0) { - // Neither a OpenType, nor TrueType font -#if 0 - fprintf(stderr, "%s:%d: error: unknown sfnt_version = " - "0x%02x%02x%02x%02x\n", __FILE__, __LINE__, - offset_table.sfnt_version[0], - offset_table.sfnt_version[1], - offset_table.sfnt_version[2], - offset_table.sfnt_version[3]); -#endif - return retval; - } + sizeof(struct ttf_offset_table_s)); #ifdef LITTLE_ENDIAN + offset_table.sfnt_version = + bswap_32(offset_table.sfnt_version); offset_table.num_tables = bswap_16(offset_table.num_tables); #endif // LITTLE_ENDIAN - - struct otf_table_directory_s { - char tag[4]; - uint32_t check_sum; - uint32_t offset; - uint32_t length; - }; - struct table_data_s *table_data = - new struct table_data_s[offset_table.num_tables]; - - for (uint16_t i = 0; i < offset_table.num_tables; i++) { - struct otf_table_directory_s table_directory; - - memcpy(&table_directory, - &font_data[sizeof(struct otf_offset_table_s) + i * - sizeof(struct otf_table_directory_s)], - sizeof(struct otf_table_directory_s)); -#ifdef LITTLE_ENDIAN - table_directory.offset = - bswap_32(table_directory.offset); - table_directory.length = - bswap_32(table_directory.length); -#endif // LITTLE_ENDIAN -#if 0 - fprintf(stderr, "%s:%d: tag = %c%c%c%c, offset = %u, " - "length = %u\n", __FILE__, __LINE__, - table_directory.tag[0], table_directory.tag[1], - table_directory.tag[2], table_directory.tag[3], - table_directory.offset, table_directory.length); -#endif - memcpy(table_data[i].tag, table_directory.tag, - 4 * sizeof(char)); - table_data[i].data.resize(table_directory.length); - memcpy(&(table_data[i].data[0]), - &font_data[table_directory.offset], - table_directory.length); - } - - size_t size_count; - - size_count = sizeof(struct otf_offset_table_s) + - offset_table.num_tables * - sizeof(struct otf_table_directory_s); - for (size_t i = 0; i < offset_table.num_tables; i++) { - size_count += table_data[i].data.size(); + if (offset_table.sfnt_version != 0x00010000) { + return false; + } + + std::map > table = + parse_ttf_offset_table( + font_data, sizeof(struct ttf_offset_table_s), + offset_table.num_tables); + + const uint32_t cmap_offset = table["cmap"].first; + const uint32_t head_offset = table["head"].first; + const uint32_t hhea_offset = table["hhea"].first; + const uint32_t hmtx_offset = table["hmtx"].first; + const uint32_t maxp_offset = table["maxp"].first; + const uint32_t name_offset = table["name"].first; + const uint32_t os_2_offset = table["OS/2"].first; + const uint32_t post_offset = table["post"].first; + + if (!(cmap_offset != 0 && head_offset != 0 && + hhea_offset != 0 && hmtx_offset != 0 && + maxp_offset != 0 && name_offset != 0 && + os_2_offset != 0)) { + fprintf(stderr, "%s:%d: error: TTF font is missing " + "required tables\n", __FILE__, __LINE__); + return false; } - size_t offset_current = sizeof(struct otf_offset_table_s); - size_t offset_check_sum_adjustment = 0; - bool head_table_exists = false; - - retval.resize(size_count); - memcpy(&retval[0], &font_data[0], - sizeof(struct otf_offset_table_s)); - for (size_t i = 0; i < offset_table.num_tables; i++) { - struct otf_table_directory_s table_directory; - const bool head_table = - strncmp(table_directory.tag, "head", 4) == 0; - - memcpy(table_directory.tag, table_data[i].tag, - 4 * sizeof(char)); - if (head_table) { - // Reset checkSumAdjustment in order to calculate the - // check sum of the head table - offset_check_sum_adjustment = 2 * sizeof(fixed_t); - *reinterpret_cast(&(table_data[i].data[ - offset_check_sum_adjustment])) = 0U; - // Change the offset for checkSumAdjustment to the - // global indexing - offset_check_sum_adjustment += offset_current; - head_table_exists = true; + parse_ttf_name(font_name, cid_encoding_id, font_data, + name_offset); + + uint16_t units_per_em; + + parse_ttf_head(font_bbox, units_per_em, font_data, + head_offset); + font_descriptor_flags = 0; + parse_ttf_post(charset, italic_angle, font_descriptor_flags, + font_data, post_offset); + parse_ttf_cmap(cid_map, font_data, cmap_offset); + parse_ttf_os_2(font_descriptor_flags, ascent, descent, + leading, cap_height, x_height, stem_v, + avg_width, font_data, os_2_offset, + units_per_em); + + const uint16_t num_glyphs = + parse_ttf_maxp(font_data, maxp_offset); + advance_width = + parse_ttf_hmtx(font_data, hmtx_offset, + parse_ttf_hhea(font_data, hhea_offset)); + + if (advance_width.empty()) { + fprintf(stderr, "%s:%d: error: hMetrics in hmtx is " + "empty\n", __FILE__, __LINE__); + return false; } - table_directory.check_sum = - otf_check_sum(table_data[i].data); - table_directory.offset = size_count; - table_directory.length = table_data[i].data.size(); - - memcpy(&retval[offset_current], &table_directory, - sizeof(struct otf_table_directory_s)); - size_count += table_data[i].data.size(); - offset_current += sizeof(struct otf_table_directory_s); - } - - for (size_t i = 0; i < offset_table.num_tables; i++) { - memcpy(&retval[offset_current], &(table_data[i].data[0]), - table_data[i].data.size()); - offset_current += table_data[i].data.size(); - - const size_t padding_size = - (4U - table_data[i].data.size()) & 3U; + advance_width.resize(num_glyphs, advance_width.back()); - memset(&retval[offset_current], '\0', padding_size); - offset_current += padding_size; + if (charset.empty()) { + charset = charset_from_adobe_glyph_list(cid_map); } - if (head_table_exists) { - // Set checkSumAdjustment in the head table - *reinterpret_cast(&(retval[ - offset_check_sum_adjustment])) = - 0xb1b0afbaU - otf_check_sum(retval); + cid_map.erase(L'\uffff'); + + return true; } - return retval; + bool font_embed_t::parse_ttf_header( + std::string &font_name, double *font_bbox, + std::map &cid_map, + std::vector &charset, + const std::vector &font_data) + { + uint16_t cid_encoding_id; + uint32_t font_descriptor_flags = 0; + double italic_angle; + double ascent; + double descent; + double leading; + double cap_height; + double x_height; + double stem_v; + double avg_width; + std::vector advance_width; + + return parse_ttf_header( + font_name, cid_encoding_id, font_descriptor_flags, + font_bbox, italic_angle, ascent, descent, leading, + cap_height, x_height, stem_v, avg_width, cid_map, + charset, advance_width, font_data); } -#endif } diff --git a/builtins/libmathtext/fontembedpdf.cc b/builtins/libmathtext/fontembedpdf.cc new file mode 100644 index 0000000000000..2878c4c7c3250 --- /dev/null +++ b/builtins/libmathtext/fontembedpdf.cc @@ -0,0 +1,534 @@ +// mathtext - A TeX/LaTeX compatible rendering library. Copyright (C) +// 2008-2016 Yue Shi Lai +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public License +// as published by the Free Software Foundation; either version 2.1 of +// the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +// 02110-1301 USA + +#include +#include +#include +#include + +// References: +// +// Adobe Systems, Inc., PostScript language Document Structuring +// Convention specification (Adobe Systems, Inc., San Jose, CA, 1992), +// version 3.0, section 5.1. +// +// Adobe Systems, Inc., PostScript language reference manual +// (Addison-Wesley, Reading, MA, 1999), 3rd edition, section 5.8.1. +// +// Adobe Systems, Inc., Adobe Type 1 Font Format (Addison-Wesley, +// Reading, MA, 1993), version 1.1 +// +// Adobe Systems, Inc., The Compact Font Format specification, Adobe +// Technical Note 5176 (Adobe, Mountain View, CA, 2003), 4 December +// 2003 document +// +// Adobe Systems, Inc., Type 2 charstring format, Adobe Technical Note +// 5177 (Adobe, San Jose, CA, 2000), 16 March 2000 document + +namespace mathtext { + + uint16_t font_embed_pdf_t::utf16_high_surrogate(uint32_t code) + { + return ((code - 0x10000) >> 10) + 0xd800; + } + + uint16_t font_embed_pdf_t::utf16_low_surrogate(uint32_t code) + { + return ((code - 0x10000) & ((1U << 10) - 1U)) + 0xdc00; + } + + std::string font_embed_pdf_t::utf16be_str(uint32_t code) + { + char buffer[9]; + + if (code < 0x10000) { + snprintf(buffer, 5, "%04x", code); + } + else if (code < 0x110000) { + snprintf(buffer, 9, "%04x%04x", + utf16_high_surrogate(code), + utf16_low_surrogate(code)); + } + else { + snprintf(buffer, 5, "????"); + } + buffer[8] = '\0'; + + return buffer; + } + + std::string font_embed_pdf_t::uint16_str(uint16_t cid) + { + char buffer[6]; + + snprintf(buffer, 6, "%u", cid); + buffer[5] = '\0'; + + return buffer; + } + + void font_embed_pdf_t::add_cidfont_w_token( + std::string &s, const std::string &t) + { + while (!s.empty() && + (s.rbegin()[0] == ' ' || s.rbegin()[0] == '\n')) { + s.resize(s.size() - 1); + } + + if (!((s.rbegin()[0] == '[' && + t.begin()[0] >= '0' && s.begin()[0] <= '9') || + (s.rbegin()[0] >= '0' && s.rbegin()[0] <= '9' && + t.begin()[0] == ']'))) { + s += " "; + } + s += t; + + static const size_t pdf_line_width = 79; + const size_t last_break = s.rfind('\n'); + + if (last_break != std::string::npos && + s.size() - last_break - 1 <= pdf_line_width) { + return; + } + + const size_t new_break = + s.rfind(' ', + last_break == std::string::npos ? s.size() : + last_break + pdf_line_width + 1); + + if (new_break != std::string::npos) { + s[new_break] = '\n'; + } + } + + std::string font_embed_pdf_t::cidfont_w( + const std::vector &advance_width) + { + // Format 1 and 2 are the two formats on PDF 1.4 Reference, p. + // 340: + // + // c [w1 w2 ... wn] <-- "format 1" + // cfirst clast w <-- "format 2" + bool in_format_1 = false; + std::string str; + + str = "/W ["; + for (size_t cid = 1, cid_next = 2; + cid < advance_width.size(); cid = cid_next) { + while (cid_next < advance_width.size() && + advance_width[cid_next] == advance_width[cid]) { + cid_next++; + } + + if (cid_next == cid + 1) { + if (!in_format_1) { + add_cidfont_w_token(str, uint16_str(cid)); + add_cidfont_w_token(str, "["); + } + in_format_1 = true; + } + else { + if (in_format_1) { + add_cidfont_w_token(str, "]"); + } + add_cidfont_w_token(str, uint16_str(cid)); + add_cidfont_w_token(str, uint16_str(cid_next - 1)); + in_format_1 = false; + } + add_cidfont_w_token(str, uint16_str(advance_width[cid])); + } + if (in_format_1) { + add_cidfont_w_token(str, "]"); + } + add_cidfont_w_token(str, "]\n"); + + return str; + } + + std::map + font_embed_pdf_t::font_embed_cid( + std::string &font_name, + const std::vector &font_data, + unsigned int type) + { + unsigned short cid_encoding_id; + uint32_t font_descriptor_flags = 0; + double font_bbox[4]; + double italic_angle; + double ascent; + double descent; + double leading; + double cap_height; + double x_height; + double stem_v; + double avg_width; + std::map cid_map; + std::vector charset; + std::vector advance_width; + unsigned int cff_offset = 0; + unsigned int cff_length = 0; + + std::map pdf_object; + + if (!(type == 0 ? + parse_otf_cff_header( + font_name, cid_encoding_id, font_descriptor_flags, + font_bbox, italic_angle, ascent, descent, leading, + cap_height, x_height, stem_v, avg_width, cid_map, + charset, advance_width, cff_offset, cff_length, + font_data) : + parse_ttf_header( + font_name, cid_encoding_id, font_descriptor_flags, + font_bbox, italic_angle, ascent, descent, leading, + cap_height, x_height, stem_v, avg_width, cid_map, + charset, advance_width, font_data))) { + return pdf_object; + } + + // Layout of a embedded CID Type 0/2 font + // + // /Font (/Subtype /Type0/2) + // | /Encoding + // +-- /CMap + // | /DescendantFonts + // +-- /Font (/Subtype /CIDFontType0/2) + // | /FontDescriptor + // +-- /FontDescriptor + // | /FontFile3/2 + // +-- stream (plain or /SubType /CIDFontType0C) + + const uint16_t max_width = + *std::max_element(advance_width.begin(), + advance_width.end()); + + std::string font_file32 = + "<<\n"; + + if (type == 0) { + font_file32 += "/Subtype /CIDFontType0C\n"; + } + + char buffer[4096]; + + snprintf(buffer, 4096, + "/Length %u\n" + ">>\n" + "stream\n", + type == 0 ? cff_length : + static_cast(font_data.size())); + font_file32 += buffer; + + if (type == 0) { + font_file32.insert( + font_file32.end(), font_data.begin() + cff_offset, + font_data.begin() + cff_offset + cff_length); + } + else { + font_file32.insert( + font_file32.end(), font_data.begin(), + font_data.end()); + } + font_file32 += "\nendstream\n"; + + pdf_object["/FontFile32"] = font_file32; + + std::string font_descriptor = + "<<\n" + "/Type /FontDescriptor\n"; + + snprintf(buffer, 4096, + "/FontName /%s\n" + "/Flags %u\n" + "/FontBBox [%g %g %g %g]\n" + "/ItalicAngle %g\n" + "/Ascent %g\n" + "/Descent %g\n" + "/Leading %g\n" + "/CapHeight %g\n" + "/XHeight %g\n" + "/StemV %g\n" + "/StemH %g\n" + "/AvgWidth %g\n" + "/MaxWidth %hu\n", + font_name.c_str(), font_descriptor_flags, + font_bbox[0], font_bbox[1], font_bbox[2], + font_bbox[3], italic_angle, ascent, descent, + leading, cap_height, x_height, stem_v, 0.0, + avg_width, max_width); + font_descriptor += buffer; + font_descriptor += "/FontFile" + + std::string(type == 0 ? "3" : "2") + " %u %u R\n"; + font_descriptor += ">>\n"; + + pdf_object["/FontDescriptor"] = font_descriptor; + + const std::string registry = "Adobe"; + const std::string ordering = "Identity"; + const std::string supplement = "0"; + + pdf_object["/CIDFont"] = + "<<\n" + "/Type /Font\n" + "/Subtype /CIDFontType" + + std::string(type == 0 ? "0" : "2") + "\n" + "/BaseFont /" + font_name + "\n" + "/CIDSystemInfo\n" + "<<\n" + "/Registry (" + registry + ")\n" + "/Ordering (" + ordering + ")\n" + "/Supplement " + supplement + "\n" + ">>\n" + "/FontDescriptor %u %u R\n" + + cidfont_w(advance_width) + + ">>\n"; + + const std::string cmap_name = "UniMT-UTF16-H"; + std::string cmap_stream; + + cmap_stream = + "%!PS-Adobe-3.0 Resource-CMap\n" + "%%DocumentNeededResources: ProcSet (CIDInit)\n" + "%%IncludeResource: ProcSet (CIDInit)\n" + "%%BeginResource: CMap (" + cmap_name + ")\n" + "%%Title: (" + cmap_name + " " + registry + " " + + ordering + " " + supplement + ")\n" + "%%Version: 1.000\n" + "%%EndComments\n" + "\n" + "/CIDInit /ProcSet findresource begin\n" + "\n" + "12 dict begin\n" + "\n" + "begincmap\n" + "\n" + "/CIDSystemInfo 3 dict dup begin\n" + " /Registry (" + registry + ") def\n" + " /Ordering (" + ordering + ") def\n" + " /Supplement " + supplement + " def\n" + "end def\n" + "\n" + "/CMapName /" + cmap_name + " def\n" + "/CMapVersion 1.000 def\n" + "/CMapType 1 def\n" + "\n" + "/XUID [1000000 10] def\n" + "\n" + "/WMode 0 def\n" + "\n"; + + // UTF-16BE + + cmap_stream += + "3 begincodespacerange\n" + " <0000> \n" + " \n" + " \n" + "endcodespacerange\n" + "\n" + "1 beginnotdefrange\n" + "<0000> <001f> 1\n" + "endnotdefrange\n" + "\n"; + + // Split into begin/endcidchar and begin/endcidrange + + std::vector cid_char; + std::vector cid_range; + + { + std::map::const_iterator iterator = + cid_map.begin(); + const struct cid_range_s r0 = { + static_cast(iterator->first), + static_cast(iterator->first), + iterator->second + }; + + cid_range.push_back(r0); + iterator++; + for (; iterator != cid_map.end(); iterator++) { + const unsigned int code = iterator->first; + if (code == cid_range.back().code_last + 1U && + iterator->second == + iterator->first - cid_range.back().code_first + + cid_range.back().cid && + // Split around UTF-16BE byte overflow (<..ff> to + // <..00>) + (code & ((1U << 8) - 1U)) != 0U && + (code < 0x10000 ? true : + ((code >> 10) & ((1U << 8) - 1U)) != 0U)) { + cid_range.back().code_last++; + } + else { + if (cid_range.back().code_first == + cid_range.back().code_last) { + const struct cid_char_s c = { + cid_range.back().code_first, + cid_range.back().cid + }; + + cid_char.push_back(c); + cid_range.pop_back(); + } + + const struct cid_range_s r = { + static_cast(iterator->first), + static_cast(iterator->first), + iterator->second + }; + + cid_range.push_back(r); + } + } + } + if (cid_range.back().code_first == + cid_range.back().code_last) { + const struct cid_char_s c = { + cid_range.back().code_first, + cid_range.back().cid + }; + + cid_char.push_back(c); + cid_range.pop_back(); + } + + for (std::vector::const_iterator + iterator = cid_char.begin(); + iterator != cid_char.end(); iterator++) { + if ((iterator - cid_char.begin()) % 100U == 0U) { + if (iterator != cid_char.begin()) { + cmap_stream += + "endcidchar\n" + "\n"; + } + + const unsigned int chunk = + std::min(100U, static_cast + (cid_char.end() - iterator) / 2); + + snprintf(buffer, 4096, "%u begincidchar\n", + chunk); + cmap_stream += buffer; + } + + cmap_stream += "<" + utf16be_str(iterator->code) + "> " + + uint16_str(iterator->cid) + "\n"; + } + if (!cid_char.empty()) { + cmap_stream += + "endcidchar\n" + "\n"; + } + + for (std::vector::const_iterator + iterator = cid_range.begin(); + iterator != cid_range.end(); iterator++) { + if ((iterator - cid_range.begin()) % 100U == 0U) { + if (iterator != cid_range.begin()) { + cmap_stream += + "endcidrange\n" + "\n"; + } + + const unsigned int chunk = + std::min(100U, static_cast + (cid_range.end() - iterator) / 3); + + snprintf(buffer, 4096, "%u begincidrange\n", + chunk); + cmap_stream += buffer; + } + cmap_stream += "<" + utf16be_str(iterator->code_first) + + "> <" + utf16be_str(iterator->code_last) + "> " + + uint16_str(iterator->cid) + "\n"; + } + if (!cid_range.empty()) { + cmap_stream += + "endcidrange\n" + "\n"; + } + + cmap_stream += + "endcmap\n" + "CMapName currentdict /CMap defineresource pop\n" + "end\n" + "end\n" + "\n" + "%%EndResource\n" + "%%EOF"; + + std::string cmap; + + snprintf(buffer, 4096, + "<<\n" + "/CMapName /%s\n", + cmap_name.c_str()); + cmap = buffer; + cmap += + "/Type /CMap\n" + "/CIDSystemInfo\n" + "<<\n" + "/Registry (" + registry + ")\n" + "/Ordering (" + ordering + ")\n" + "/Supplement " + supplement + "\n" + ">>\n" + "/WMode 0\n"; + pdf_object["/CMap.dict_part"] = cmap; + snprintf(buffer, 4096, + "/Length %u\n" + ">>\n" + "stream\n", + static_cast(cmap_stream.size())); + cmap += buffer; + pdf_object["/CMap.stream"] = cmap_stream; + cmap += cmap_stream; + cmap += "\nendstream\n"; + + pdf_object["/CMap"] = cmap; + + // PDF 1.4 Reference, p. 353, Table 5.17 + + pdf_object["/Font"] = + "<<\n" + "/Type /Font\n" + "/Subtype /Type0\n" + "/BaseFont /" + font_name + "\n" + "/Encoding %u %u R\n" + "/DescendantFonts [%u %u R]\n" + ">>\n"; + + return pdf_object; + } + + std::map + font_embed_pdf_t::font_embed_type_2( + std::string &font_name, + const std::vector &font_data) + { + return font_embed_cid(font_name, font_data, 0); + } + + std::map + font_embed_pdf_t::font_embed_type_42( + std::string &font_name, + const std::vector &font_data) + { + return font_embed_cid(font_name, font_data, 2); + } + +} diff --git a/builtins/libmathtext/fontembedps.cc b/builtins/libmathtext/fontembedps.cc index 9e98e500a3539..f399b34f3352f 100644 --- a/builtins/libmathtext/fontembedps.cc +++ b/builtins/libmathtext/fontembedps.cc @@ -16,10 +16,10 @@ // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA // 02110-1301 USA -#include "mathtext/fontembed.h" +#include +#include #include #include -#include #ifdef WIN32 #define snprintf _snprintf #endif @@ -405,7 +405,7 @@ namespace mathtext { unsigned int glyph_index = cid_map[code_point]; if (char_strings[glyph_index] != ".notdef" && - !char_strings[glyph_index].empty()) { + char_strings[glyph_index] != "") { snprintf(linebuf, BUFSIZ, "dup %u /%s put\n", code_point, char_strings[glyph_index].c_str()); @@ -438,8 +438,9 @@ namespace mathtext { unsigned int char_strings_count = 0; - for (std::vector::const_iterator iterator = char_strings.begin(); iterator < char_strings.end(); - ++iterator) { + for (std::vector::const_iterator iterator = + char_strings.begin(); + iterator < char_strings.end(); iterator++) { if (!iterator->empty()) { char_strings_count++; } diff --git a/builtins/libmathtext/geometry.cc b/builtins/libmathtext/geometry.cc new file mode 100644 index 0000000000000..2138b854b37fb --- /dev/null +++ b/builtins/libmathtext/geometry.cc @@ -0,0 +1,78 @@ +// mathtext - A TeX/LaTeX compatible rendering library. Copyright (C) +// 2008-2012 Yue Shi Lai +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public License +// as published by the Free Software Foundation; either version 2.1 of +// the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +// 02110-1301 USA + +#include +#include +#include + +namespace mathtext { + + point_t::operator std::string(void) const + { + std::stringstream stream; + + stream << '(' << _x[0] << ", " << _x[1] << ')'; + + return stream.str(); + } + + const affine_transform_t affine_transform_t::identity = + affine_transform_t(1.0F, 0.0F, 0.0F, 1.0F, 0.0F, 0.0F); + + affine_transform_t affine_transform_t:: + translate(const float tx, const float ty) + { + return affine_transform_t(1.0F, 0.0F, 0.0F, 1.0F, tx, ty); + } + + affine_transform_t affine_transform_t:: + scale(const float sx, const float sy) + { + return affine_transform_t(sx, 0.0F, 0.0F, sy, 0.0F, 0.0F); + } + + affine_transform_t affine_transform_t::rotate(const float angle) + { + float sin_angle; + float cos_angle; + +#if defined(__APPLE__) + __sincosf(angle, &sin_angle, &cos_angle); +#elif defined(_WIN32) + sin_angle = std::sin(angle); + cos_angle = std::cos(angle); +#else + sincosf(angle, &sin_angle, &cos_angle); +#endif + + return affine_transform_t(cos_angle, sin_angle, + -sin_angle, cos_angle, 0, 0); + } + + affine_transform_t::operator std::string(void) const + { + std::stringstream stream; + + stream << '(' << _a[0] << ", " << _a[1] << ", 0)" << std::endl; + stream << '(' << _a[2] << ", " << _a[3] << ", 0)" << std::endl; + stream << '(' << _a[4] << ", " << _a[5] << ", 1)"; + + return stream.str(); + } + +} diff --git a/builtins/libmathtext/mathrender.cc b/builtins/libmathtext/mathrender.cc index c8d83055dac0e..7082a414b345a 100644 --- a/builtins/libmathtext/mathrender.cc +++ b/builtins/libmathtext/mathrender.cc @@ -1,118 +1,40 @@ -//////////////////////////////////////////////////////////////////////////////// -/// mathtext - A TeX/LaTeX compatible rendering library. Copyright (C) -/// 2008-2012 Yue Shi Lai -/// -/// This library is free software; you can redistribute it and/or -/// modify it under the terms of the GNU Lesser General Public License -/// as published by the Free Software Foundation; either version 2.1 of -/// the License, or (at your option) any later version. -/// -/// This library is distributed in the hope that it will be useful, but -/// WITHOUT ANY WARRANTY; without even the implied warranty of -/// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -/// Lesser General Public License for more details. -/// -/// You should have received a copy of the GNU Lesser General Public -/// License along with this library; if not, write to the Free Software -/// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA -/// 02110-1301 USA - -#ifdef WIN32 -// On Windows, Disable the warning: -// "characters beyond first in wide-character constant ignored" -#pragma warning( push ) -#pragma warning( disable : 4066) -#endif +// mathtext - A TeX/LaTeX compatible rendering library. Copyright (C) +// 2008-2012 Yue Shi Lai +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public License +// as published by the Free Software Foundation; either version 2.1 of +// the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +// 02110-1301 USA #include #include #include -#include "mathtext/mathrender.h" +#include -//////////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////// namespace mathtext { - -//////////////////////////////////////////////////////////////////////////////// - - point_t::operator std::string(void) const - { - std::stringstream stream; - - stream << '(' << _x[0] << ", " << _x[1] << ')'; - - return stream.str(); - } - - const affine_transform_t affine_transform_t::identity = - affine_transform_t(1.0F, 0.0F, 0.0F, 1.0F, 0.0F, 0.0F); - const affine_transform_t affine_transform_t::flip_y = - affine_transform_t(1.0F, 0.0F, 0.0F, -1.0F, 0.0F, 0.0F); - - -//////////////////////////////////////////////////////////////////////////////// - - affine_transform_t affine_transform_t:: - translate(const float tx, const float ty) - { - return affine_transform_t(1.0F, 0.0F, 0.0F, 1.0F, tx, ty); - } - - -//////////////////////////////////////////////////////////////////////////////// - - affine_transform_t affine_transform_t:: - scale(const float sx, const float sy) - { - return affine_transform_t(sx, 0.0F, 0.0F, sy, 0.0F, 0.0F); - } - - -//////////////////////////////////////////////////////////////////////////////// - - affine_transform_t affine_transform_t::rotate(const float angle) - { - float sin_angle; - float cos_angle; - - sin_angle = sin(angle); - cos_angle = cos(angle); - - return affine_transform_t(cos_angle, sin_angle, - -sin_angle, cos_angle, 0, 0); - } - - -//////////////////////////////////////////////////////////////////////////////// - - affine_transform_t::operator std::string(void) const - { - std::stringstream stream; - - stream << '(' << _a[0] << ", " << _a[1] << ", 0)" << std::endl; - stream << '(' << _a[2] << ", " << _a[3] << ", 0)" << std::endl; - stream << '(' << _a[4] << ", " << _a[5] << ", 1)"; - - return stream.str(); - } - #ifdef __INTEL_COMPILER #pragma warning(push) #pragma warning(disable: 869) #endif // __INTEL_COMPILER - -//////////////////////////////////////////////////////////////////////////////// - bool math_text_renderer_t::is_cyrillic(const wchar_t c) { return c >= L'\u0400' && c <= L'\u052f'; } - -//////////////////////////////////////////////////////////////////////////////// - bool math_text_renderer_t::is_cjk(const wchar_t c) { return @@ -141,21 +63,15 @@ namespace mathtext { (c >= L'\U0002f800' && c <= L'\U0002fa1f')); } - #if 0 -//////////////////////////////////////////////////////////////////////////////// - bool math_text_renderer_t::is_wgl_4(const wchar_t c) { return true; } #endif - -//////////////////////////////////////////////////////////////////////////////// -/// @see http://www.w3.org/International/questions/qa-scripts -/// @see http://www.unicode.org/reports/tr9/tr9-21.html - + // @see http://www.w3.org/International/questions/qa-scripts + // @see http://www.unicode.org/reports/tr9/tr9-21.html bool math_text_renderer_t::is_right_to_left(const wchar_t c) { return @@ -170,27 +86,18 @@ namespace mathtext { (c >= L'\ufb1d' && c <= L'\ufb4f')); } - #if 0 -//////////////////////////////////////////////////////////////////////////////// - bool math_text_renderer_t::is_cjk_punctuation_open(const wchar_t c) { return false; } - -//////////////////////////////////////////////////////////////////////////////// - bool math_text_renderer_t::is_cjk_punctuation_closed(const wchar_t c) { return false; } #endif - -//////////////////////////////////////////////////////////////////////////////// - bounding_box_t math_text_renderer_t:: math_bounding_box(const math_text_t::box_t &box, const unsigned int style) @@ -205,9 +112,6 @@ namespace mathtext { return box_bounding_box; } - -//////////////////////////////////////////////////////////////////////////////// - void math_text_renderer_t:: math_text(const point_t origin, const math_text_t::box_t &box, @@ -225,9 +129,6 @@ namespace mathtext { #pragma warning(pop) #endif // __INTEL_COMPILER - -//////////////////////////////////////////////////////////////////////////////// - bounding_box_t math_text_renderer_t:: math_bounding_box(const wchar_t &glyph, const unsigned int family, const float size) @@ -243,9 +144,6 @@ namespace mathtext { return math_symbol_bounding_box; } - -//////////////////////////////////////////////////////////////////////////////// - void math_text_renderer_t:: math_text(const point_t origin, const wchar_t &glyph, const unsigned int family, const float size, @@ -265,9 +163,6 @@ namespace mathtext { reset_font_size(family); } - -//////////////////////////////////////////////////////////////////////////////// - bounding_box_t math_text_renderer_t:: math_bounding_box(const math_text_t::math_symbol_t &math_symbol, const unsigned int style) @@ -278,9 +173,6 @@ namespace mathtext { return math_bounding_box(math_symbol._glyph, family, size); } - -//////////////////////////////////////////////////////////////////////////////// - void math_text_renderer_t:: math_text(const point_t origin, const math_text_t::math_symbol_t &math_symbol, @@ -294,9 +186,6 @@ namespace mathtext { render_structure); } - -//////////////////////////////////////////////////////////////////////////////// - bounding_box_t math_text_renderer_t:: math_bounding_box(const math_text_t::math_symbol_t &math_symbol, const unsigned int style, const float height) @@ -312,16 +201,13 @@ namespace mathtext { bounding_box_t ret = iterator->_offset + iterator->_bounding_box; - for (; iterator != token.end(); ++iterator) + for (; iterator != token.end(); iterator++) ret = ret.merge(iterator->_offset + iterator->_bounding_box); return ret; } - -//////////////////////////////////////////////////////////////////////////////// - void math_text_renderer_t:: math_text(const point_t origin, const math_text_t::math_symbol_t &math_symbol, @@ -331,7 +217,9 @@ namespace mathtext { std::vector token = math_tokenize(math_symbol, style, height); - for (std::vector::const_iterator iterator = token.begin(); iterator != token.end(); ++iterator) + for (std::vector::const_iterator iterator = + token.begin(); + iterator != token.end(); iterator++) math_text(origin + transform_pixel_to_logical().linear() * iterator->_offset, @@ -340,10 +228,9 @@ namespace mathtext { iterator->_extensible._size, render_structure); } + ///////////////////////////////////////////////////////////////// -//////////////////////////////////////////////////////////////////////////////// -/// A field can be a math symbol or a math list - + // A field can be a math symbol or a math list bounding_box_t math_text_renderer_t:: math_bounding_box(const std::vector:: const_iterator &math_list_begin, @@ -362,16 +249,13 @@ namespace mathtext { bounding_box_t ret = iterator->_offset + iterator->_bounding_box; - for (; iterator != token.end(); ++iterator) + for (; iterator != token.end(); iterator++) ret = ret.merge(iterator->_offset + iterator->_bounding_box); return ret; } - -//////////////////////////////////////////////////////////////////////////////// - void math_text_renderer_t:: math_text(const point_t origin, const std::vector:: @@ -398,8 +282,8 @@ namespace mathtext { math_text_t::item_t::TYPE_BOUNDARY && (math_list_end - 1)->_type == math_text_t::item_t::TYPE_BOUNDARY) { - ++math_list_begin_interior; - --math_list_end_interior; + math_list_begin_interior++; + math_list_end_interior--; delimiter = true; } @@ -415,7 +299,7 @@ namespace mathtext { math_list_begin->_atom._nucleus._math_symbol, style, token_iterator->_delimiter_height, render_structure); - ++token_iterator; + token_iterator++; } static const math_text_t::item_t fraction_item = @@ -435,14 +319,14 @@ namespace mathtext { fraction_iterator + 1, math_list_end_interior, token_iterator->_style, render_structure); - ++token_iterator; + token_iterator++; if(thickness > 0) { filled_rectangle( origin + transform_pixel_to_logical().linear() * (token_iterator->_offset + token_iterator->_bounding_box)); - ++token_iterator; + token_iterator++; } math_text(origin + transform_pixel_to_logical().linear() * @@ -450,12 +334,13 @@ namespace mathtext { math_list_begin_interior, fraction_iterator, token_iterator->_style, render_structure); - ++token_iterator; + token_iterator++; } else // Incrementally process a math list - for (std::vector::const_iterator iterator = math_list_begin_interior; - iterator != math_list_end_interior; ++iterator) { + for (std::vector::const_iterator + iterator = math_list_begin_interior; + iterator != math_list_end_interior; iterator++) { switch(iterator->_type) { case math_text_t::item_t::TYPE_ATOM: if(render_structure) @@ -469,7 +354,7 @@ namespace mathtext { iterator->_atom, token_iterator->_style, render_structure); - ++token_iterator; + token_iterator++; break; } // math_text_t::item_t::TYPE_KERN can be ignored @@ -486,9 +371,6 @@ namespace mathtext { render_structure); } - -//////////////////////////////////////////////////////////////////////////////// - bounding_box_t math_text_renderer_t:: math_bounding_box(const math_text_t::field_t &field, const unsigned int style) @@ -509,9 +391,6 @@ namespace mathtext { } } - -//////////////////////////////////////////////////////////////////////////////// - void math_text_renderer_t:: math_text(const point_t origin, const math_text_t::field_t &field, @@ -533,12 +412,9 @@ namespace mathtext { } } - -//////////////////////////////////////////////////////////////////////////////// -/// TeX algorithm for (three-way) atoms: -/// -/// See Knuth, The TeXbook (1986), pp. 445f. - + // TeX algorithm for (three-way) atoms: + // + // See Knuth, The TeXbook (1986), pp. 445f. bounding_box_t math_text_renderer_t:: math_bounding_box(const math_text_t::atom_t &atom, const unsigned int style) @@ -554,16 +430,13 @@ namespace mathtext { bounding_box_t ret = iterator->_offset + iterator->_bounding_box; - for (; iterator != token.end(); ++iterator) + for (; iterator != token.end(); iterator++) ret = ret.merge(iterator->_offset + iterator->_bounding_box); return ret; } - -//////////////////////////////////////////////////////////////////////////////// - void math_text_renderer_t:: math_text(const point_t origin, const math_text_t::atom_t &atom, @@ -594,7 +467,7 @@ namespace mathtext { token_iterator->_offset, atom._index, token_iterator->_style, render_structure); - ++token_iterator; + token_iterator++; } const math_text_t::math_symbol_t @@ -607,7 +480,7 @@ namespace mathtext { symbol_surd, token_iterator->_style, token_iterator->_delimiter_height, render_structure); - ++token_iterator; + token_iterator++; // Rule with clearance filled_rectangle( origin + transform_pixel_to_logical().linear() * @@ -637,7 +510,7 @@ namespace mathtext { if(atom._superscript.empty() && atom._subscript.empty()) return; - ++token_iterator; + token_iterator++; if(atom._superscript.empty()) { math_text(origin + @@ -659,55 +532,46 @@ namespace mathtext { token_iterator->_offset, atom._superscript, token_iterator->_style, render_structure); - ++token_iterator; + token_iterator++; math_text(origin + transform_pixel_to_logical().linear() * token_iterator->_offset, atom._subscript, token_iterator->_style, render_structure); } - -//////////////////////////////////////////////////////////////////////////////// - bounding_box_t math_text_renderer_t:: - bounding_box(const math_text_t &textbb, const bool display_style) + bounding_box(const math_text_t &text, const bool display_style) { - if(!textbb.well_formed()) - bounding_box(L"*** invalid: " + textbb.code()); + if (!text.well_formed()) + bounding_box(L"*** invalid: " + text.code()); const unsigned int initial_style = display_style ? math_text_t::item_t::STYLE_DISPLAY : math_text_t::item_t::STYLE_TEXT; - return math_bounding_box(textbb._math_list._math_list, + return math_bounding_box(text._math_list._math_list, initial_style); } - -//////////////////////////////////////////////////////////////////////////////// - void math_text_renderer_t:: - text(const float x, const float y, const math_text_t &texti, + text(const float x, const float y, const math_text_t &text, const bool display_style) { - if(!texti.well_formed()) { - text_raw(x, y, L"*** invalid: " + texti.code()); + if (!text.well_formed()) { + text_raw(x, y, L"*** invalid: " + text.code()); } const unsigned int initial_style = display_style ? math_text_t::item_t::STYLE_DISPLAY : math_text_t::item_t::STYLE_TEXT; - if(texti._render_structure) { + if (text._render_structure) { point(x, y); rectangle(point_t(x, y) + math_bounding_box( - texti._math_list._math_list, initial_style)); + text._math_list._math_list, initial_style)); } - math_text(point_t(x, y), texti._math_list._math_list, - initial_style, texti._render_structure); + math_text(point_t(x, y), text._math_list._math_list, + initial_style, text._render_structure); } } -#ifdef WIN32 -#pragma warning( pop ) -#endif diff --git a/builtins/libmathtext/mathrenderstyle.cc b/builtins/libmathtext/mathrenderstyle.cc index 85955bd86ad48..aeb4d5e6933f4 100644 --- a/builtins/libmathtext/mathrenderstyle.cc +++ b/builtins/libmathtext/mathrenderstyle.cc @@ -17,7 +17,8 @@ // 02110-1301 USA #include -#include "mathtext/mathrender.h" +#include +#include ///////////////////////////////////////////////////////////////////// @@ -251,11 +252,19 @@ namespace mathtext { unsigned int style) const { const unsigned int left_type_modified = - left_type <= (unsigned int) math_text_t::atom_t::TYPE_INNER ? - left_type : (unsigned int) math_text_t::atom_t::TYPE_ORD; + left_type <= + static_cast( + math_text_t::atom_t::TYPE_INNER) ? + left_type : + static_cast( + math_text_t::atom_t::TYPE_ORD); const unsigned int right_type_modified = - right_type <= (unsigned int) math_text_t::atom_t::TYPE_INNER ? - right_type : (unsigned int) math_text_t::atom_t::TYPE_ORD; + right_type <= + static_cast( + math_text_t::atom_t::TYPE_INNER) ? + right_type : + static_cast( + math_text_t::atom_t::TYPE_ORD); const unsigned int space = math_text_t::atom_t:: spacing(left_type_modified, right_type_modified, is_script_style(style)); @@ -454,13 +463,11 @@ namespace mathtext { size); const float remaining_height = height - bounding_box_sum.height(); - unsigned long repeat_ratio = 0; - if (bounding_box_repeatable.height() !=0) { - repeat_ratio = + const unsigned long repeat_ratio = (unsigned long)ceil( remaining_height / bounding_box_repeatable.height()); - } + nrepeat = glyph[GLYPH_MIDDLE] == L'\0' ? repeat_ratio : ((repeat_ratio + 1UL) >> 1); } diff --git a/builtins/libmathtext/mathrendertoken.cc b/builtins/libmathtext/mathrendertoken.cc index b2ef96417bd38..2e1fd1201c838 100644 --- a/builtins/libmathtext/mathrendertoken.cc +++ b/builtins/libmathtext/mathrendertoken.cc @@ -16,8 +16,9 @@ // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA // 02110-1301 USA +#include #include -#include "mathtext/mathrender.h" +#include ///////////////////////////////////////////////////////////////////// @@ -183,7 +184,7 @@ namespace mathtext { const bool generalized_fraction = fraction_iterator != math_list_end_interior; bool delimiter = false; - float delimiter_height = 0.f; + float delimiter_height = 0.f; bounding_box_t bounding_box_delimiter_left(0, 0, 0, 0, 0, 0); bounding_box_t bounding_box_delimiter_right(0, 0, 0, 0, 0, 0); @@ -191,8 +192,8 @@ namespace mathtext { math_text_t::item_t::TYPE_BOUNDARY && (math_list_end - 1)->_type == math_text_t::item_t::TYPE_BOUNDARY) { - ++math_list_begin_interior; - --math_list_end_interior; + math_list_begin_interior++; + math_list_end_interior--; delimiter = true; const bounding_box_t bounding_box_interior = @@ -381,8 +382,9 @@ namespace mathtext { } else // Incrementally process a math list - for (std::vector::const_iterator iterator = math_list_begin_interior; - iterator != math_list_end_interior; ++iterator) { + for (std::vector::const_iterator + iterator = math_list_begin_interior; + iterator != math_list_end_interior; iterator++) { unsigned int atom_type; bounding_box_t item_bounding_box; unsigned int current_style = has_accent ? diff --git a/builtins/libmathtext/mathtext.cc b/builtins/libmathtext/mathtext.cc index 0eef08902c4d9..3801fc983b3bc 100644 --- a/builtins/libmathtext/mathtext.cc +++ b/builtins/libmathtext/mathtext.cc @@ -16,8 +16,10 @@ // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA // 02110-1301 USA -#include "mathtext/mathtext.h" -#include +#include +#include +#include +#include ///////////////////////////////////////////////////////////////////// @@ -148,8 +150,9 @@ namespace mathtext { bool math_text_t::field_t::generalized_fraction(void) const { if(_type == TYPE_MATH_LIST) - for (std::vector::const_iterator iterator = _math_list.begin(); iterator != _math_list.end(); - ++iterator) + for (std::vector::const_iterator iterator = + _math_list.begin(); + iterator != _math_list.end(); iterator++) if(iterator->_type == item_t::TYPE_GENERALIZED_FRACTION) return true; @@ -221,7 +224,8 @@ namespace mathtext { { std::wstring wstring; - for (std::string::const_iterator iterator = string.begin(); iterator != string.end(); ++iterator) { + for (std::string::const_iterator iterator = string.begin(); + iterator != string.end(); iterator++) { wstring.push_back(*iterator); } @@ -237,63 +241,63 @@ namespace mathtext { wchar_t c; // Skip over byte ordering marks - if((unsigned char)(*iterator) == 0xef) { - ++iterator; - if((unsigned char)(*iterator) == 0xbb) { - ++iterator; - if((unsigned char)(*iterator) == 0xbf) { - ++iterator; + if ((*iterator & 0xff) == 0xef) { + iterator++; + if ((*iterator & 0xff) == 0xbb) { + iterator++; + if ((*iterator & 0xff) == 0xbf) { + iterator++; } } } if((*iterator & 0xf0) == 0xf0) { c = (*iterator & 0x7) << 18; - ++iterator; + iterator++; if((*iterator & 0xc0) != 0x80) { continue; } c |= (*iterator & 0x3f) << 12; - ++iterator; + iterator++; if((*iterator & 0xc0) != 0x80) { continue; } c |= (*iterator & 0x3f) << 6; - ++iterator; + iterator++; if((*iterator & 0xc0) != 0x80) { continue; } c |= (*iterator & 0x3f); - ++iterator; + iterator++; } else if((*iterator & 0xe0) == 0xe0) { c = (*iterator & 0xf) << 12; - ++iterator; + iterator++; if((*iterator & 0xc0) != 0x80) { continue; } c |= (*iterator & 0x3f) << 6; - ++iterator; + iterator++; if((*iterator & 0xc0) != 0x80) { continue; } c |= (*iterator & 0x3f); - ++iterator; + iterator++; } else if((*iterator & 0xc0) == 0xc0) { c = (*iterator & 0x1f) << 6; - ++iterator; + iterator++; if((*iterator & 0xc0) != 0x80) { continue; } c |= (*iterator & 0x3f); - ++iterator; + iterator++; } else if((*iterator & 0x80) == 0x0) { c = (*iterator & 0x7f); - ++iterator; + iterator++; } else { - ++iterator; + iterator++; continue; } wstring.push_back(c); @@ -333,7 +337,6 @@ namespace mathtext { return true; } -#if 0 std::string tex_form(const double x) { std::string retval; @@ -343,6 +346,5 @@ namespace mathtext { return retval; } } -#endif } diff --git a/builtins/libmathtext/mathtext/fontembed.h b/builtins/libmathtext/mathtext/fontembed.h index 6bd5147aeaee1..f0c90c54c306e 100644 --- a/builtins/libmathtext/mathtext/fontembed.h +++ b/builtins/libmathtext/mathtext/fontembed.h @@ -1,5 +1,5 @@ // mathtext - A TeX/LaTeX compatible rendering library. Copyright (C) -// 2008-2012 Yue Shi Lai +// 2008-2016 Yue Shi Lai // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public License @@ -16,32 +16,25 @@ // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA // 02110-1301 USA -#if defined(_MSC_VER) && (_MSC_VER < 1800) -// Visual C++ 2008 doesn't have stdint.h -typedef __int8 int8_t; -typedef __int16 int16_t; -typedef __int32 int32_t; -typedef __int64 int64_t; -typedef unsigned __int8 uint8_t; -typedef unsigned __int16 uint16_t; -typedef unsigned __int32 uint32_t; -typedef unsigned __int64 uint64_t; -#else -#include -#endif -#include #include #include #include +#include +#include namespace mathtext { class font_embed_t { - private: + protected: struct table_data_s { char tag[4]; std::vector data; }; + static void protected_memcpy( + void *destination, + std::vector::const_iterator source, + std::vector::const_iterator source_end, + size_t length, const char *location); static void subset_rename_otf_name_table( struct table_data_s &table_data, uint8_t *glyph_usage); static void subset_ttf_glyf_table( @@ -55,22 +48,110 @@ namespace mathtext { static void parse_ttf_encoding_subtable_format4( std::map &cid_map, const std::vector &font_data, - const size_t offset, const uint16_t length); + const size_t offset); + static void parse_ttf_encoding_subtable_format12( + std::map &cid_map, + const std::vector &font_data, + const size_t offset); static unsigned int otf_check_sum( const std::vector &table_data); public: // I/O static std::vector read_font_data(FILE *); - static std::vector read_font_data(const std::string &filename); + static std::vector read_font_data( + const std::string &filename); // Font parsing + // OTF/TTF tables + static std::map > + parse_ttf_offset_table( + const std::vector &font_data, + size_t offset_table_size, uint16_t num_tables); + static void parse_ttf_cmap( + std::map &cid_map, + const std::vector &font_data, + uint32_t cmap_offset); + static void parse_ttf_head( + double *font_bbox, uint16_t &units_per_em, + const std::vector &font_data, + uint32_t head_offset); + static uint16_t parse_ttf_hhea( + const std::vector &font_data, + uint32_t hhea_offset); + static std::vector parse_ttf_hmtx( + const std::vector &font_data, + uint32_t hmtx_offset, uint16_t number_of_h_metrics); + static uint16_t parse_ttf_maxp( + const std::vector &font_data, + uint32_t maxp_offset); + static void parse_ttf_name( + std::string &font_name, uint16_t &cid_encoding_id, + const std::vector &font_data, + uint32_t name_offset); + static void parse_ttf_os_2( + uint32_t &font_descriptor_flag, double &ascent, + double &descent, double &leading, double &cap_height, + double &x_height, double &stem_v, double &avg_width, + const std::vector &font_data, + uint32_t os_2_offset, uint16_t units_per_em); + static void parse_ttf_post( + std::vector &charset, + double &italic_angle, uint32_t &font_descriptor_flags, + const std::vector &font_data, + uint32_t name_offset); + // CFF parsing + static std::vector > parse_cff_index( + const std::vector &font_data, + uint32_t ¤t_offset, uint32_t *skip_psize = NULL); + static double parse_cff_dict_number( + std::vector::const_iterator &data, + std::vector::const_iterator end); + static double search_cff_top_dict_number( + const std::vector &top_dict, + uint8_t operator_value_1, uint8_t operator_value_2 = 255); + static std::string cff_sid_to_string( + uint16_t sid, + const std::vector > &string_index); + static std::vector parse_cff_charset( + const std::vector &data, + uint32_t charset_offset, uint32_t cff_nglyph, + const std::vector > &string_index); + static void parse_cff( + std::vector &charset, + const std::vector &font_data, + uint32_t cff_offset); + // OTF CFF parsing interface + static bool parse_otf_cff_header( + std::string &font_name, unsigned short &cid_encoding_id, + uint32_t font_descriptor_flags, double *font_bbox, + double &italic_angle, double &ascent, double &descent, + double &leading, double &cap_height, double &x_height, + double &stem_v,double &avg_width, + std::map &cid_map, + std::vector &charset, + std::vector &advance_width, + unsigned int &cff_offset, unsigned int &cff_length, + const std::vector &font_data); static bool parse_otf_cff_header( std::string &font_name, unsigned short &cid_encoding_id, unsigned int &cff_offset, unsigned int &cff_length, const std::vector &font_data); + static std::vector + charset_from_adobe_glyph_list( + std::map &cid_map); + static bool parse_ttf_header( + std::string &font_name, unsigned short &cid_encoding_id, + uint32_t font_descriptor_flags, double *font_bbox, + double &italic_angle, double &ascent, double &descent, + double &leading, double &cap_height, double &x_height, + double &stem_v,double &avg_width, + std::map &cid_map, + std::vector &charset, + std::vector &advance_width, + const std::vector &font_data); static bool parse_ttf_header( std::string &font_name, double *font_bbox, std::map &cid_map, - std::vector &char_strings, + std::vector &charset, const std::vector &font_data); // Font subsetting static std::vector subset_otf( @@ -101,14 +182,39 @@ namespace mathtext { }; class font_embed_pdf_t : public font_embed_t { + protected: + struct cid_char_s { + uint32_t code; + uint16_t cid; + }; + struct cid_range_s { + uint32_t code_first; + uint32_t code_last; + uint16_t cid; + }; + static uint16_t utf16_high_surrogate(uint32_t code); + static uint16_t utf16_low_surrogate(uint32_t code); + static std::string utf16be_str(uint32_t code); + static std::string uint16_str(uint16_t code); + static void add_cidfont_w_token(std::string &s, const std::string &t); + static std::string cidfont_w( + const std::vector &advance_width); + static std::string pdf_vector_differences( + const std::string &key, + const std::map &cid_map, + const std::vector &charset); + static std::map + font_embed_cid( + std::string &font_name, + const std::vector &font_data, + unsigned int type); public: - static std::string font_embed_type_1( + static std::map + font_embed_type_2( std::string &font_name, const std::vector &font_data); - static std::string font_embed_type_2( - std::string &font_name, - const std::vector &font_data); - static std::string font_embed_type_42( + static std::map + font_embed_type_42( std::string &font_name, const std::vector &font_data); }; diff --git a/builtins/libmathtext/mathtext/geometry.h b/builtins/libmathtext/mathtext/geometry.h new file mode 100644 index 0000000000000..b457a8bbd3438 --- /dev/null +++ b/builtins/libmathtext/mathtext/geometry.h @@ -0,0 +1,468 @@ +// -*- mode: c++; -*- + +// mathtext - A TeX/LaTeX compatible rendering library. Copyright (C) +// 2008-2012 Yue Shi Lai +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public License +// as published by the Free Software Foundation; either version 2.1 of +// the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +// 02110-1301 USA + +#ifndef MATHTEXT_GEOMETRY_H_ +#define MATHTEXT_GEOMETRY_H_ + +#include +#include +#include + +namespace mathtext { + + /** + * 2D point (and vector) + */ + class point_t { + private: + float _x[2]{}; + public: + inline point_t(void) + { + } + inline point_t(const float x0, const float y0) + { + _x[0] = x0; + _x[1] = y0; + } + inline const float *x(void) const + { + return _x; + } + inline float *x(void) + { + return _x; + } + inline float operator[](const int n) const + { + return _x[n]; + } + inline float &operator[](const int n) + { + return _x[n]; + } + inline point_t operator+(const point_t &point) const + { + return point_t(_x[0] + point._x[0], + _x[1] + point._x[1]); + } + inline point_t operator-(const point_t &point) const + { + return point_t(_x[0] - point._x[0], + _x[1] - point._x[1]); + } + inline point_t& operator+=(const point_t &point) + { + _x[0] += point._x[0]; + _x[1] += point._x[1]; + + return *this; + } + inline point_t& operator-=(const point_t &point) + { + _x[0] -= point._x[0]; + _x[1] -= point._x[1]; + + return *this; + } + inline point_t operator*(const float scale) const + { + return point_t(_x[0] * scale, _x[1] * scale); + } + inline point_t operator/(const float scale) const + { + return point_t(_x[0] / scale, _x[1] / scale); + } + inline point_t& operator*=(const float scale) + { + _x[0] *= scale; + _x[1] *= scale; + + return *this; + } + inline float dot(const point_t &point) const + { + return _x[0] * point._x[0] + _x[1] * point._x[1]; + } + inline float cross(const point_t &point) const + { + return _x[0] * point._x[1] - _x[1] * point._x[0]; + } + inline float norm_square(void) const + { + return _x[0] * _x[0] + _x[1] * _x[1]; + } + inline float norm(void) const + { + return sqrtf(norm_square()); + } + inline point_t unit_vector(void) const + { + return *this / norm(); + } + inline point_t rotate_cw(void) const + { + return point_t(_x[1], -_x[0]); + } + inline point_t rotate_ccw(void) const + { + return point_t(-_x[1], _x[0]); + } + inline bool operator==(const point_t &point) const + { + return _x[0] == point._x[0] && _x[1] == point._x[1]; + } + inline bool operator!=(const point_t &point) const + { + return _x[0] != point._x[0] || _x[1] != point._x[1]; + } + friend point_t operator*(const float scale, + const point_t &point); + operator std::string(void) const; + }; + + inline point_t operator*(const float scale, const point_t &point) + { + return point_t(scale * point._x[0], scale * point._x[1]); + } + + /** + * General 2D affine transform of the Adobe Imaging Model + * + * @see Adobe Systems, Inc., PostScript Language Reference Manual + * (Addison-Wesley, Reading, MA, 1999), section 4.3.3, pp. + * 187-189. + * @see Adobe Systems, Inc., PDF Reference, 6th Edition, Version + * 1.7 (Adobe Systems, Inc., San Jose, CA, 2006), section + * 4.2.2-4.2.3, pp. 204-209. + */ + class affine_transform_t { + private: + float _a[6]; + public: + static const affine_transform_t identity; + static const affine_transform_t flip_y; + static affine_transform_t + translate(const float tx, const float ty); + static affine_transform_t + scale(const float sx, const float sy); + static affine_transform_t rotate(const float angle); + inline affine_transform_t(const float a, const float b, + const float c, const float d, + const float tx, const float ty) + { + _a[0] = a; + _a[1] = b; + _a[2] = c; + _a[3] = d; + _a[4] = tx; + _a[5] = ty; + } + inline const float *a(void) const + { + return _a; + } + inline float *a(void) + { + return _a; + } + inline float operator[](const int n) const + { + return _a[n]; + } + inline float &operator[](const int n) + { + return _a[n]; + } + inline affine_transform_t linear(void) const + { + return affine_transform_t(_a[0], _a[1], _a[2], _a[3], + 0.0F, 0.0F); + } + inline affine_transform_t translate(void) const + { + return affine_transform_t(1.0F, 0.0F, 0.0F, 1.0F, + _a[4], _a[5]); + } + inline affine_transform_t operator*(const float s) const + { + return affine_transform_t(_a[0] * s, _a[1] * s, + _a[2] * s, _a[3] * s, + _a[4] * s, _a[5] * s); + } + inline affine_transform_t operator/(const float s) const + { + return affine_transform_t(_a[0] / s, _a[1] / s, + _a[2] / s, _a[3] / s, + _a[4] / s, _a[5] / s); + } + inline point_t operator*(const point_t x) const + { + return point_t(_a[0] * x[0] + _a[2] * x[1] + _a[4], + _a[1] * x[0] + _a[3] * x[1] + _a[5]); + } + inline affine_transform_t + operator*(const affine_transform_t b) const + { + return affine_transform_t( + _a[0] * b._a[0] + _a[1] * b._a[2], + _a[0] * b._a[1] + _a[1] * b._a[3], + _a[2] * b._a[0] + _a[3] * b._a[2], + _a[2] * b._a[1] + _a[3] * b._a[3], + _a[4] * b._a[0] + _a[5] * b._a[2] + b._a[4], + _a[4] * b._a[1] + _a[5] * b._a[3] + b._a[5]); + } + inline float determinant(void) const + { + return _a[0] * _a[3] - _a[1] * _a[2]; + } + inline affine_transform_t inverse(void) const + { + return affine_transform_t( + _a[3], -_a[1], -_a[2], _a[0], + _a[2] * _a[5] - _a[3] * _a[4], + _a[1] * _a[4] - _a[0] * _a[5]) * + (1.0F / determinant()); + } + operator std::string(void) const; + }; + + class bounding_box_t { + private: + point_t _lower_left; + point_t _upper_right; + float _advance{0.}; + float _italic_correction{0.}; + public: + inline bounding_box_t(void) + { + } + inline bounding_box_t(const point_t lower_left, + const point_t upper_right, + const float advance, + const float italic_correction) + : _lower_left(lower_left), _upper_right(upper_right), + _advance(advance), _italic_correction(italic_correction) + { + } + inline bounding_box_t(const float left, const float bottom, + const float right, const float top, + const float advance, + const float italic_correction) + : _advance(advance), _italic_correction(italic_correction) + { + _lower_left[0] = left; + _lower_left[1] = bottom; + _upper_right[0] = right; + _upper_right[1] = top; + } + inline point_t lower_left(void) const + { + return _lower_left; + } + inline point_t &lower_left(void) + { + return _lower_left; + } + inline point_t upper_right(void) const + { + return _upper_right; + } + inline point_t &upper_right(void) + { + return _upper_right; + } + inline float left(void) const + { + return _lower_left[0]; + } + inline float &left(void) + { + return _lower_left[0]; + } + inline float top(void) const + { + return _upper_right[1]; + } + inline float &top(void) + { + return _upper_right[1]; + } + inline float right(void) const + { + return _upper_right[0]; + } + inline float &right(void) + { + return _upper_right[0]; + } + inline float bottom(void) const + { + return _lower_left[1]; + } + inline float &bottom(void) + { + return _lower_left[1]; + } + inline float advance(void) const + { + return _advance; + } + inline float &advance(void) + { + return _advance; + } + inline float italic_correction(void) const + { + return _italic_correction; + } + inline float &italic_correction(void) + { + return _italic_correction; + } + inline float width(void) const + { + return _upper_right[0] - _lower_left[0]; + } + inline float height(void) const + { + return _upper_right[1] - _lower_left[1]; + } + inline float horizontal_center(void) const + { + return 0.5F * (_lower_left[0] + _upper_right[0]); + } + inline float vertical_center(void) const + { + return 0.5F * (_lower_left[1] + _upper_right[1]); + } + inline float ascent(void) const + { + return _upper_right[1]; + } + inline float descent(void) const + { + return -_lower_left[1]; + } + inline bounding_box_t + merge(const bounding_box_t &bounding_box) const + { + bounding_box_t ret; + + ret._lower_left[0] = + std::min(_lower_left[0], + bounding_box._lower_left[0]); + ret._lower_left[1] = + std::min(_lower_left[1], + bounding_box._lower_left[1]); + if (bounding_box._upper_right[0] > _upper_right[0]) { + ret._upper_right[0] = bounding_box._upper_right[0]; + ret._italic_correction = + bounding_box._italic_correction; + } + else { + ret._upper_right[0] = _upper_right[0]; + ret._italic_correction = _italic_correction; + } + ret._upper_right[1] = + std::max(_upper_right[1], + bounding_box._upper_right[1]); + ret._advance = + std::max(_upper_right[0] + _advance, + bounding_box._upper_right[0] + + bounding_box._advance) - + ret._upper_right[0]; + + return ret; + } + inline bounding_box_t operator+(const point_t &point) const + { + return bounding_box_t(_lower_left + point, + _upper_right + point, + _advance + point[0], + _italic_correction); + } + inline bounding_box_t operator-(const point_t &point) const + { + return bounding_box_t(_lower_left - point, + _upper_right - point, + _advance - point[0], + _italic_correction); + } + inline bounding_box_t operator+=(const point_t &point) + { + _lower_left += point; + _upper_right += point; + _advance += point[0]; + + return *this; + } + inline bounding_box_t operator-=(const point_t &point) + { + _lower_left -= point; + _upper_right -= point; + _advance -= point[0]; + + return *this; + } + friend bounding_box_t + operator+(const point_t &, const bounding_box_t &); + friend bounding_box_t + operator-(const point_t &, const bounding_box_t &); + friend bounding_box_t + operator*(const affine_transform_t &, + const bounding_box_t &); + }; + + inline bounding_box_t + operator+(const point_t &point, + const bounding_box_t &bounding_box) + { + return bounding_box_t(point + bounding_box._lower_left, + point + bounding_box._upper_right, + point[0] + bounding_box._advance, + bounding_box._italic_correction); + } + + inline bounding_box_t + operator-(const point_t &point, + const bounding_box_t &bounding_box) + { + return bounding_box_t(point - bounding_box._lower_left, + point - bounding_box._upper_right, + point[0] + bounding_box._advance, + bounding_box._italic_correction); + } + + inline bounding_box_t + operator*(const affine_transform_t &transform, + const bounding_box_t &bounding_box) + { + return bounding_box_t( + transform * bounding_box._lower_left, + transform * bounding_box._upper_right, + (transform * point_t(bounding_box._advance, 0))[0], + (transform * point_t( + bounding_box._italic_correction, 0))[0]); + } + +} + +#endif // MATHTEXT_GEOMETRY_H_ diff --git a/builtins/libmathtext/mathtext/mathrender.h b/builtins/libmathtext/mathtext/mathrender.h index 4f020b5a763bd..4d84f801c298e 100644 --- a/builtins/libmathtext/mathtext/mathrender.h +++ b/builtins/libmathtext/mathtext/mathrender.h @@ -1,3 +1,5 @@ +// -*- mode: c++; -*- + // mathtext - A TeX/LaTeX compatible rendering library. Copyright (C) // 2008-2012 Yue Shi Lai // @@ -19,523 +21,14 @@ #ifndef MATHRENDER_H_ #define MATHRENDER_H_ -#if defined(_MSC_VER) && (_MSC_VER < 1800) -// Visual C++ 2008 doesn't have stdint.h -typedef __int8 int8_t; -typedef __int16 int16_t; -typedef __int32 int32_t; -typedef __int64 int64_t; -typedef unsigned __int8 uint8_t; -typedef unsigned __int16 uint16_t; -typedef unsigned __int32 uint32_t; -typedef unsigned __int64 uint64_t; -#else -#include -#endif -#include #include #include -#include -#include "mathtext.h" +#include +#include +#include namespace mathtext { - /** - * 2D point (and vector) - */ - class point_t { - private: - float _x[2]; - public: - inline point_t(void) : _x() - { - } - inline point_t(const point_t &point) - { - _x[0] = point._x[0]; - _x[1] = point._x[1]; - } - inline point_t(const float x0, const float y0) - { - _x[0] = x0; - _x[1] = y0; - } - inline point_t& operator=(const point_t &point) - { - _x[0] = point._x[0]; - _x[1] = point._x[1]; - return *this; - } - inline const float *x(void) const - { - return _x; - } - inline float *x(void) - { - return _x; - } - inline float operator[](const int n) const - { - return _x[n]; - } - inline float &operator[](const int n) - { - return _x[n]; - } - inline point_t operator+(const point_t &point) const - { - return point_t(_x[0] + point._x[0], - _x[1] + point._x[1]); - } - inline point_t operator-(const point_t &point) const - { - return point_t(_x[0] - point._x[0], - _x[1] - point._x[1]); - } - inline point_t operator+=(const point_t &point) - { - _x[0] += point._x[0]; - _x[1] += point._x[1]; - - return *this; - } - inline point_t operator-=(const point_t &point) - { - _x[0] -= point._x[0]; - _x[1] -= point._x[1]; - - return *this; - } - inline point_t operator*(const float scale) const - { - return point_t(_x[0] * scale, _x[1] * scale); - } - inline point_t operator/(const float scale) const - { - return point_t(_x[0] / scale, _x[1] / scale); - } - inline point_t operator*=(const float scale) - { - _x[0] *= scale; - _x[1] *= scale; - - return *this; - } - inline float dot(const point_t &point) const - { - return _x[0] * point._x[0] + _x[1] * point._x[1]; - } - inline float cross(const point_t &point) const - { - return _x[0] * point._x[1] - _x[1] * point._x[0]; - } - inline float norm_square(void) const - { - return _x[0] * _x[0] + _x[1] * _x[1]; - } - inline float norm(void) const - { - return sqrtf(norm_square()); - } - inline point_t unit_vector(void) const - { - return *this / norm(); - } - inline point_t rotate_cw(void) const - { - return point_t(_x[1], -_x[0]); - } - inline point_t rotate_ccw(void) const - { - return point_t(-_x[1], _x[0]); - } - inline bool operator==(const point_t &point) const - { - return _x[0] == point._x[0] && _x[1] == point._x[1]; - } - inline bool operator!=(const point_t &point) const - { - return _x[0] != point._x[0] || _x[1] != point._x[1]; - } - friend point_t operator*(const float scale, - const point_t &point); - operator std::string(void) const; - }; - - inline point_t operator*(const float scale, const point_t &point) - { - return point_t(scale * point._x[0], scale * point._x[1]); - } - - /** - * General 2D affine transform of the Adobe Imaging Model - * - * The n-D affine transform is generally represented by - * - * ( xt ) ( a0 a1 a2 ) ( x ) - * ( yt ) = ( a3 a4 a5 ) ( y ) - * ( 1 ) ( 0 0 1 ) ( 1 ) - * - * with (a0, a1, a3, a4) representing the linear component of the - * transform, i.e. rotation and scaling, while (a2, a5) is the - * translation vector - * - * @see Adobe Systems, Inc., PostScript Language Reference Manual - * (Addison-Wesley, Reading, MA, 1999), section 4.3.3, pp. - * 187-189. - * @see Adobe Systems, Inc., PDF Reference, 6th Edition, Version - * 1.7 (Adobe Systems, Inc., San Jose, CA, 2006), section - * 4.2.2-4.2.3, pp. 204-209. - */ - class affine_transform_t { - private: - float _a[6]; - public: - static const affine_transform_t identity; - static const affine_transform_t flip_y; - static affine_transform_t - translate(const float tx, const float ty); - static affine_transform_t - scale(const float sx, const float sy); - static affine_transform_t rotate(const float angle); - inline affine_transform_t( - const float a0, const float b, const float c, - const float d, const float tx, const float ty) - { - _a[0] = a0; - _a[1] = b; - _a[2] = c; - _a[3] = d; - _a[4] = tx; - _a[5] = ty; - } - inline const float *a(void) const - { - return _a; - } - inline float *a(void) - { - return _a; - } - inline float operator[](const int n) const - { - return _a[n]; - } - inline float &operator[](const int n) - { - return _a[n]; - } - inline affine_transform_t linear(void) const - { - return affine_transform_t( - _a[0], _a[1], _a[2], _a[3], 0.0F, 0.0F); - } - inline affine_transform_t translate(void) const - { - return affine_transform_t( - 1.0F, 0.0F, 0.0F, 1.0F, _a[4], _a[5]); - } - inline affine_transform_t operator*(const float s) const - { - return affine_transform_t( - _a[0] * s, _a[1] * s, _a[2] * s, _a[3] * s, - _a[4] * s, _a[5] * s); - } - inline affine_transform_t operator/(const float s) const - { - return affine_transform_t( - _a[0] / s, _a[1] / s, _a[2] / s, _a[3] / s, - _a[4] / s, _a[5] / s); - } - inline point_t operator*(const point_t x) const - { - return point_t( - _a[0] * x[0] + _a[2] * x[1] + _a[4], - _a[1] * x[0] + _a[3] * x[1] + _a[5]); - } - /** - * Returns the affine transform of b, i.e. the matrix-vector - * product (*this) (b^T, 1)^T, of the vector b - * - * @returns the affine transform of the vector b - */ - inline affine_transform_t - operator*(const affine_transform_t b) const - { - return affine_transform_t( - _a[0] * b._a[0] + _a[1] * b._a[2], - _a[0] * b._a[1] + _a[1] * b._a[3], - _a[2] * b._a[0] + _a[3] * b._a[2], - _a[2] * b._a[1] + _a[3] * b._a[3], - _a[4] * b._a[0] + _a[5] * b._a[2] + b._a[4], - _a[4] * b._a[1] + _a[5] * b._a[3] + b._a[5]); - } - /** - * Returns the determinant det(*this) of the affine transform - * - * @returns the determinant det(*this) of the affine transform - */ - inline float determinant(void) const - { - return _a[0] * _a[3] - _a[1] * _a[2]; - } - /** - * Returns the determinant (*this)^(-1) of the affine - * transform - * - * @returns the determinant (*this)^(-1) of the affine - * transform - */ - inline affine_transform_t inverse(void) const - { - return affine_transform_t( - _a[3], -_a[1], -_a[2], _a[0], - _a[2] * _a[5] - _a[3] * _a[4], - _a[1] * _a[4] - _a[0] * _a[5]) * - (1.0F / determinant()); - } - operator std::string(void) const; - }; - - /** - * General TeX bounding box - */ - // FIXME: The skewchar mechanism is missing - class bounding_box_t { - private: - point_t _lower_left; - point_t _upper_right; - float _advance; - float _italic_correction; - public: - inline bounding_box_t(void) : _lower_left(), _upper_right(), _advance(), _italic_correction() - { - } - inline bounding_box_t( - const point_t lower_left_0, const point_t upper_right_0, - const float advance_0, const float italic_correction_0) - : _lower_left(lower_left_0), _upper_right(upper_right_0), - _advance(advance_0), - _italic_correction(italic_correction_0) - { - } - inline bounding_box_t( - const float left_0, const float bottom_0, const float right_0, - const float top_0, const float advance_0, - const float italic_correction_0) - : _advance(advance_0), - _italic_correction(italic_correction_0) - { - _lower_left[0] = left_0; - _lower_left[1] = bottom_0; - _upper_right[0] = right_0; - _upper_right[1] = top_0; - } - inline point_t lower_left(void) const - { - return _lower_left; - } - inline point_t &lower_left(void) - { - return _lower_left; - } - inline point_t upper_right(void) const - { - return _upper_right; - } - inline point_t &upper_right(void) - { - return _upper_right; - } - inline float left(void) const - { - return _lower_left[0]; - } - inline float &left(void) - { - return _lower_left[0]; - } - inline float top(void) const - { - return _upper_right[1]; - } - inline float &top(void) - { - return _upper_right[1]; - } - inline float right(void) const - { - return _upper_right[0]; - } - inline float &right(void) - { - return _upper_right[0]; - } - inline float bottom(void) const - { - return _lower_left[1]; - } - inline float &bottom(void) - { - return _lower_left[1]; - } - inline float advance(void) const - { - return _advance; - } - inline float &advance(void) - { - return _advance; - } - inline float italic_correction(void) const - { - return _italic_correction; - } - inline float &italic_correction(void) - { - return _italic_correction; - } - inline float width(void) const - { - return _upper_right[0] - _lower_left[0]; - } - inline float height(void) const - { - return _upper_right[1] - _lower_left[1]; - } - inline float horizontal_center(void) const - { - return 0.5F * (_lower_left[0] + _upper_right[0]); - } - inline float vertical_center(void) const - { - return 0.5F * (_lower_left[1] + _upper_right[1]); - } - inline float ascent(void) const - { - return _upper_right[1]; - } - inline float descent(void) const - { - return -_lower_left[1]; - } - inline bounding_box_t - merge(const bounding_box_t &bounding_box) const - { - bounding_box_t ret; - - ret._lower_left[0] = - std::min(_lower_left[0], - bounding_box._lower_left[0]); - ret._lower_left[1] = - std::min(_lower_left[1], - bounding_box._lower_left[1]); - if(bounding_box._upper_right[0] > _upper_right[0]) { - ret._upper_right[0] = bounding_box._upper_right[0]; - ret._italic_correction = - bounding_box._italic_correction; - } - else { - ret._upper_right[0] = _upper_right[0]; - ret._italic_correction = _italic_correction; - } - ret._upper_right[1] = - std::max(_upper_right[1], - bounding_box._upper_right[1]); - ret._advance = - std::max(_upper_right[0] + _advance, - bounding_box._upper_right[0] + - bounding_box._advance) - - ret._upper_right[0]; - - return ret; - } - inline bounding_box_t operator+(const point_t &point) const - { - return bounding_box_t( - _lower_left + point, _upper_right + point, - _advance + point[0], _italic_correction); - } - inline bounding_box_t operator-(const point_t &point) const - { - return bounding_box_t( - _lower_left - point, _upper_right - point, - _advance - point[0], _italic_correction); - } - inline bounding_box_t operator+=(const point_t &point) - { - _lower_left += point; - _upper_right += point; - _advance += point[0]; - - return *this; - } - inline bounding_box_t operator-=(const point_t &point) - { - _lower_left -= point; - _upper_right -= point; - _advance -= point[0]; - - return *this; - } - inline bounding_box_t operator*(const float scale) const - { - return bounding_box_t( - _lower_left * scale, _upper_right * scale, - _advance * scale, _italic_correction * scale); - } - inline bounding_box_t operator*=(const float scale) - { - _lower_left *= scale; - _upper_right *= scale; - _advance *= scale; - _italic_correction *= scale; - - return *this; - } - friend bounding_box_t - operator+(const point_t &, const bounding_box_t &); - friend bounding_box_t - operator-(const point_t &, const bounding_box_t &); - friend bounding_box_t - operator*(const affine_transform_t &, - const bounding_box_t &); - }; - - inline bounding_box_t - operator+(const point_t &point, - const bounding_box_t &bounding_box) - { - return bounding_box_t( - point + bounding_box._lower_left, - point + bounding_box._upper_right, - point[0] + bounding_box._advance, - bounding_box._italic_correction); - } - - inline bounding_box_t - operator-(const point_t &point, - const bounding_box_t &bounding_box) - { - return bounding_box_t( - point - bounding_box._lower_left, - point - bounding_box._upper_right, - point[0] + bounding_box._advance, - bounding_box._italic_correction); - } - - inline bounding_box_t - operator*(const affine_transform_t &transform, - const bounding_box_t &bounding_box) - { - return bounding_box_t( - transform * bounding_box._lower_left, - transform * bounding_box._upper_right, - (transform * point_t(bounding_box._advance, 0))[0], - (transform * point_t( - bounding_box._italic_correction, 0))[0]); - } - #ifdef __INTEL_COMPILER #pragma warning(push) #pragma warning(disable: 869) @@ -638,16 +131,15 @@ namespace mathtext { public: point_t _offset; bounding_box_t _bounding_box; - struct extension_t { + union { + unsigned int _style; + struct { wchar_t _glyph; unsigned int _family; float _size; + } _extensible; }; - union { - unsigned int _style; - extension_t _extensible; - }; - float _delimiter_height; + float _delimiter_height{0.f}; inline math_token_t( const bounding_box_t bounding_box, const unsigned int style, @@ -741,7 +233,7 @@ namespace mathtext { unsigned int left_type, unsigned int right_type, unsigned int style) const; protected: - inline virtual affine_transform_t + virtual affine_transform_t transform_logical_to_pixel(void) const = 0; virtual affine_transform_t transform_pixel_to_logical(void) const = 0; @@ -851,7 +343,7 @@ namespace mathtext { const unsigned int family = FAMILY_PLAIN) const = 0; virtual void set_font_size( const float size, const unsigned int family) = 0; - inline virtual void set_font_size(const float size) = 0; + virtual void set_font_size(const float size) = 0; virtual void reset_font_size( const unsigned int family) = 0; virtual void point(const float x, const float y) = 0; @@ -879,8 +371,9 @@ namespace mathtext { const bool display_style = false); ///////////////////////////////////////////////////////////// inline float default_axis_height( - const bool /*display_style = false*/) const + const bool display_style = false) const { + (void)display_style; return axis_height * style_size( math_text_t::item_t::STYLE_TEXT); } diff --git a/builtins/libmathtext/mathtext/mathtext.h b/builtins/libmathtext/mathtext/mathtext.h index 4908cf58b5e02..f14bafb909973 100644 --- a/builtins/libmathtext/mathtext/mathtext.h +++ b/builtins/libmathtext/mathtext/mathtext.h @@ -20,8 +20,6 @@ #define MATHTEXT_H_ #include -#include -#include namespace mathtext { @@ -43,8 +41,8 @@ namespace mathtext { * - Illegal TeX syntax may result in not well defined behaviors. * Most notably, `a^b^c' or `a_b_c' result in `a^c' and `a_c', * i.e. the overwriting of the previous superscripts and - * subscripts, and `a \\atop b \\atop c' or `a \\over b \\over c' - * result in `a \\atop {b \\atop c}' and `a \\over {b \\over c}', i.e. + * subscripts, and `a \atop b \atop c' or `a \over b \over c' + * result in `a \atop {b \atop c}' and `a \over {b \over c}', i.e. * a right associative interpretation. * * @see ISO/IEC JTC1/SC2/WG2, ISO/IEC 10646:2003/Amd.2:2006 (ISO, @@ -153,8 +151,7 @@ namespace mathtext { wchar_t _glyph; unsigned int _type; inline math_symbol_t(void) - : _family(FAMILY_PLAIN), _glyph(L'\0'), - _type(atom_t::TYPE_UNKNOWN) + : _family(FAMILY_PLAIN), _type(atom_t::TYPE_UNKNOWN) { } inline math_symbol_t(std::string code, wchar_t glyph, @@ -192,7 +189,6 @@ namespace mathtext { bool _vertical; std::wstring _string; box_t(void) - : _vertical(false), _string(L"") { } box_t(std::wstring string) @@ -314,8 +310,7 @@ namespace mathtext { field_t _index; inline atom_t(const unsigned int type, const field_t &nucleus) - : _type(type), _nucleus(nucleus), - _limits(LIMITS_UNKNOWN) + : _type(type), _nucleus(nucleus) { } inline atom_t(const unsigned int type, @@ -325,7 +320,7 @@ namespace mathtext { { } inline atom_t(const field_t &nucleus) - : _nucleus(nucleus), _limits(false) + : _nucleus(nucleus) { classify(); } @@ -333,7 +328,7 @@ namespace mathtext { const field_t &superscript, const field_t &subscript) : _nucleus(nucleus), _superscript(superscript), - _subscript(subscript), _limits(LIMITS_UNKNOWN) + _subscript(subscript) { classify(); } @@ -355,19 +350,18 @@ namespace mathtext { * Returns the interelement spacing between the given left * and right atom types, and whether the present style is * script or scriptscript, with 0, 1, 2, and 3 - * representing no space, \\thinkmuskip, \\medmuskip, and - * \\thickmuskip, respectively. + * representing no space, \thinkmuskip, \medmuskip, and + * \thickmuskip, respectively. * - * TeX defaults to \\thinkmuskip to 3 mu, \\medmuskip to 4 - * mu, and \\thickmuskip to 5 mu, with 1 mu being 1/18 + * TeX defaults to \thinkmuskip to 3 mu, \medmuskip to 4 + * mu, and \thickmuskip to 5 mu, with 1 mu being 1/18 * quad. * * @param[in] left_type left (enum) atom type * @param[in] right_type right (enum) atom type - * @param[in] script boolean * @return interelement spacing, with 0, 1, 2, and 3 - * representing no space, \\thinkmuskip, \\medmuskip, and - * \\thickmuskip, respectively + * representing no space, \thinkmuskip, \medmuskip, and + * \thickmuskip, respectively */ static unsigned int spacing(const unsigned int left_type, @@ -422,22 +416,16 @@ namespace mathtext { unsigned int _boundary; inline item_t(const unsigned int type, const float length = 0) - : _type(type), _atom(field_t()), _length(length), - _style_change(STYLE_UNKNOWN), - _boundary(BOUNDARY_UNKNOWN) + : _type(type), _atom(field_t()), _length(length) { } inline item_t(const atom_t &atom) - : _type(TYPE_ATOM), _atom(atom), _length(0), - _style_change(STYLE_UNKNOWN), - _boundary(BOUNDARY_UNKNOWN) + : _type(TYPE_ATOM), _atom(atom) { } inline item_t(const unsigned int type, const atom_t &atom) - : _type(type), _atom(atom), _length(0), - _style_change(STYLE_UNKNOWN), - _boundary(BOUNDARY_UNKNOWN) + : _type(type), _atom(atom) { } bool operator==(const item_t &item) const; @@ -507,6 +495,7 @@ namespace mathtext { inline void tree_view(void) const { std::vector branch; + tree_view(_math_list, branch, true); } friend class math_text_renderer_t; diff --git a/builtins/libmathtext/mathtextencode.cc b/builtins/libmathtext/mathtextencode.cc index 0640458dc23da..02b06ca8ccbba 100644 --- a/builtins/libmathtext/mathtextencode.cc +++ b/builtins/libmathtext/mathtextencode.cc @@ -16,17 +16,10 @@ // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA // 02110-1301 USA -#ifdef WIN32 -// On Windows, Disable the warning: -// "characters beyond first in wide-character constant ignored" -#pragma warning( push ) -#pragma warning( disable : 4066) -#endif - +#include #include #include -#include -#include "mathtext/mathtext.h" +#include ///////////////////////////////////////////////////////////////////// @@ -432,6 +425,3 @@ namespace mathtext { } } -#ifdef WIN32 -#pragma warning( pop ) -#endif diff --git a/builtins/libmathtext/mathtextparse.cc b/builtins/libmathtext/mathtextparse.cc index e72770ac42ea1..456a43b2bb7d6 100644 --- a/builtins/libmathtext/mathtextparse.cc +++ b/builtins/libmathtext/mathtextparse.cc @@ -19,8 +19,7 @@ #include #include #include -#include -#include "mathtext/mathtext.h" +#include ///////////////////////////////////////////////////////////////////// @@ -61,8 +60,9 @@ namespace mathtext { std::vector radical_index; bool horizontal_box = false; - for (std::vector::const_iterator iterator = str_split.begin(); iterator != str_split.end(); - ++iterator) { + for (std::vector::const_iterator iterator = + str_split.begin(); + iterator != str_split.end(); iterator++) { // ONLY LEVEL 0 superscript and subscript are interpreted, // and they are ignored afterwards. if(level == 0 && delimiter_level == 0) { @@ -343,7 +343,8 @@ namespace mathtext { { std::string code = raw_code; - for (std::string::iterator iterator = code.begin(); iterator != code.end(); ++iterator) { + for (std::string::iterator iterator = code.begin(); + iterator != code.end(); iterator++) { if(*iterator == escape_character) { *iterator = '\\'; } @@ -351,7 +352,7 @@ namespace mathtext { std::vector ret; - if(code.empty()) { + if (code.size() <= 0) { return ret; } diff --git a/builtins/libmathtext/mathtextview.cc b/builtins/libmathtext/mathtextview.cc index 3e32d3cf14668..1b9fe9f75231a 100644 --- a/builtins/libmathtext/mathtextview.cc +++ b/builtins/libmathtext/mathtextview.cc @@ -16,9 +16,9 @@ // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA // 02110-1301 USA +#include #include -#include -#include "mathtext/mathtext.h" +#include ///////////////////////////////////////////////////////////////////// @@ -30,9 +30,11 @@ namespace mathtext { tree_view_prefix(const std::vector &branch, const bool final) const { - if(!branch.empty()) { + if (branch.size() > 0) { std::cerr << ' '; - for (std::vector::const_iterator iterator = branch.begin(); iterator != branch.end(); ++iterator) { + for (std::vector::const_iterator iterator = + branch.begin(); + iterator != branch.end(); iterator++) { if(*iterator) { if(iterator + 1 == branch.end()) { if(final) @@ -81,8 +83,9 @@ namespace mathtext { std::vector branch_copy = branch; branch_copy.back() = !final; - for (std::vector::const_iterator iterator = field._math_list.begin(); - iterator != field._math_list.end(); ++iterator) { + for (std::vector::const_iterator iterator = + field._math_list.begin(); + iterator != field._math_list.end(); iterator++) { branch_copy.back() = !final; branch_copy.push_back(true); tree_view(*iterator, branch_copy, diff --git a/builtins/libmathtext/table/cffstdstr.h b/builtins/libmathtext/table/cffstdstr.h new file mode 100644 index 0000000000000..c4eaff6d4c5fb --- /dev/null +++ b/builtins/libmathtext/table/cffstdstr.h @@ -0,0 +1,79 @@ +static const size_t ncff_standard_string = 391; +static const char *cff_standard_string[ncff_standard_string] = { + ".notdef", "space", "exclam", "quotedbl", "numbersign", "dollar", + "percent", "ampersand", "quoteright", "parenleft", "parenright", + "asterisk", "plus", "comma", "hyphen", "period", "slash", "zero", + "one", "two", "three", "four", "five", "six", "seven", "eight", + "nine", "colon", "semicolon", "less", "equal", "greater", + "question", "at", "A", "B", "C", "D", "E", "F", "G", "H", "I", + "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", + "W", "X", "Y", "Z", "bracketleft", "backslash", "bracketright", + "asciicircum", "underscore", "quoteleft", "a", "b", "c", "d", "e", + "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", + "s", "t", "u", "v", "w", "x", "y", "z", "braceleft", "bar", + "braceright", "asciitilde", "exclamdown", "cent", "sterling", + "fraction", "yen", "florin", "section", "currency", "quotesingle", + "quotedblleft", "guillemotleft", "guilsinglleft", + "guilsinglright", "fi", "fl", "endash", "dagger", "daggerdbl", + "periodcentered", "paragraph", "bullet", "quotesinglbase", + "quotedblbase", "quotedblright", "guillemotright", "ellipsis", + "perthousand", "questiondown", "grave", "acute", "circumflex", + "tilde", "macron", "breve", "dotaccent", "dieresis", "ring", + "cedilla", "hungarumlaut", "ogonek", "caron", "emdash", "AE", + "ordfeminine", "Lslash", "Oslash", "OE", "ordmasculine", "ae", + "dotlessi", "lslash", "oslash", "oe", "germandbls", "onesuperior", + "logicalnot", "mu", "trademark", "Eth", "onehalf", "plusminus", + "Thorn", "onequarter", "divide", "brokenbar", "degree", "thorn", + "threequarters", "twosuperior", "registered", "minus", "eth", + "multiply", "threesuperior", "copyright", "Aacute", "Acircumflex", + "Adieresis", "Agrave", "Aring", "Atilde", "Ccedilla", "Eacute", + "Ecircumflex", "Edieresis", "Egrave", "Iacute", "Icircumflex", + "Idieresis", "Igrave", "Ntilde", "Oacute", "Ocircumflex", + "Odieresis", "Ograve", "Otilde", "Scaron", "Uacute", + "Ucircumflex", "Udieresis", "Ugrave", "Yacute", "Ydieresis", + "Zcaron", "aacute", "acircumflex", "adieresis", "agrave", "aring", + "atilde", "ccedilla", "eacute", "ecircumflex", "edieresis", + "egrave", "iacute", "icircumflex", "idieresis", "igrave", + "ntilde", "oacute", "ocircumflex", "odieresis", "ograve", + "otilde", "scaron", "uacute", "ucircumflex", "udieresis", + "ugrave", "yacute", "ydieresis", "zcaron", "exclamsmall", + "Hungarumlautsmall", "dollaroldstyle", "dollarsuperior", + "ampersandsmall", "Acutesmall", "parenleftsuperior", + "parenrightsuperior", "twodotenleader", "onedotenleader", + "zerooldstyle", "oneoldstyle", "twooldstyle", "threeoldstyle", + "fouroldstyle", "fiveoldstyle", "sixoldstyle", "sevenoldstyle", + "eightoldstyle", "nineoldstyle", "commasuperior", + "threequartersemdash", "periodsuperior", "questionsmall", + "asuperior", "bsuperior", "centsuperior", "dsuperior", + "esuperior", "isuperior", "lsuperior", "msuperior", "nsuperior", + "osuperior", "rsuperior", "ssuperior", "tsuperior", "ff", "ffi", + "ffl", "parenleftinferior", "parenrightinferior", + "Circumflexsmall", "hyphensuperior", "Gravesmall", "Asmall", + "Bsmall", "Csmall", "Dsmall", "Esmall", "Fsmall", "Gsmall", + "Hsmall", "Ismall", "Jsmall", "Ksmall", "Lsmall", "Msmall", + "Nsmall", "Osmall", "Psmall", "Qsmall", "Rsmall", "Ssmall", + "Tsmall", "Usmall", "Vsmall", "Wsmall", "Xsmall", "Ysmall", + "Zsmall", "colonmonetary", "onefitted", "rupiah", "Tildesmall", + "exclamdownsmall", "centoldstyle", "Lslashsmall", "Scaronsmall", + "Zcaronsmall", "Dieresissmall", "Brevesmall", "Caronsmall", + "Dotaccentsmall", "Macronsmall", "figuredash", "hypheninferior", + "Ogoneksmall", "Ringsmall", "Cedillasmall", "questiondownsmall", + "oneeighth", "threeeighths", "fiveeighths", "seveneighths", + "onethird", "twothirds", "zerosuperior", "foursuperior", + "fivesuperior", "sixsuperior", "sevensuperior", "eightsuperior", + "ninesuperior", "zeroinferior", "oneinferior", "twoinferior", + "threeinferior", "fourinferior", "fiveinferior", "sixinferior", + "seveninferior", "eightinferior", "nineinferior", "centinferior", + "dollarinferior", "periodinferior", "commainferior", + "Agravesmall", "Aacutesmall", "Acircumflexsmall", "Atildesmall", + "Adieresissmall", "Aringsmall", "AEsmall", "Ccedillasmall", + "Egravesmall", "Eacutesmall", "Ecircumflexsmall", + "Edieresissmall", "Igravesmall", "Iacutesmall", + "Icircumflexsmall", "Idieresissmall", "Ethsmall", "Ntildesmall", + "Ogravesmall", "Oacutesmall", "Ocircumflexsmall", "Otildesmall", + "Odieresissmall", "OEsmall", "Oslashsmall", "Ugravesmall", + "Uacutesmall", "Ucircumflexsmall", "Udieresissmall", + "Yacutesmall", "Thornsmall", "Ydieresissmall", "001.000", + "001.001", "001.002", "001.003", "Black", "Bold", "Book", "Light", + "Medium", "Regular", "Roman", "Semibold" +}; diff --git a/builtins/libmathtext/table/mathfontparam.h b/builtins/libmathtext/table/mathfontparam.h index de3cf46244784..32ca9794b9888 100644 --- a/builtins/libmathtext/table/mathfontparam.h +++ b/builtins/libmathtext/table/mathfontparam.h @@ -68,7 +68,8 @@ const float math_text_renderer_t::big_op_spacing_5 = 0.111111F; ///////////////////////////////////////////////////////////////////// // Implicit TFM Font Parameters const float math_text_renderer_t::radical_rule_thickness = 0.054F; -const float math_text_renderer_t::large_operator_display_scale = 1.4F; +const float math_text_renderer_t::large_operator_display_scale = + 1.4F; ///////////////////////////////////////////////////////////////////// // Text Mode Parameters diff --git a/graf2d/graf/src/TMathText.cxx b/graf2d/graf/src/TMathText.cxx index 63c12e422bcc6..a53390deb4418 100644 --- a/graf2d/graf/src/TMathText.cxx +++ b/graf2d/graf/src/TMathText.cxx @@ -246,10 +246,8 @@ class TMathTextRenderer : public TText, public TAttFill, upper_right_x <= advance ? 0.0F : std::max(0.0F, upper_right_x + margin - advance); const mathtext::bounding_box_t ret = - mathtext::bounding_box_t( - lower_left_x, lower_left_y, - upper_right_x, upper_right_y, - advance, italic_correction) * scale; + mathtext::bounding_box_t(lower_left_x * scale, lower_left_y * scale, upper_right_x * scale, + upper_right_y * scale, advance * scale, italic_correction * scale); current_x += ret.advance();