diff options
author | Haibo Huang <hhb@google.com> | 2019-05-03 15:19:10 -0700 |
---|---|---|
committer | Haibo Huang <hhb@google.com> | 2019-05-03 22:40:58 +0000 |
commit | 29d542f77dfe291616322f469e777e43ecca88f9 (patch) | |
tree | afb7377913edde6f710eac5369d710595f7ae4b6 | |
parent | 7515f315c3f168e48946ef4b3e9f6d0b63747b59 (diff) | |
parent | 9620b607af5b796badefebcf16d7ce6e6786f205 (diff) | |
download | sfntly-29d542f77dfe291616322f469e777e43ecca88f9.tar.gz |
Merge remote-tracking branch 'aosp/upstream-master' into update
Bug: 129498355
Bug: 116114182
Test: build
Change-Id: I16095748d0ed921fbf1e4f473fa91f271648f673
86 files changed, 1137 insertions, 868 deletions
@@ -2,55 +2,10 @@ cc_library_static { name: "libsfntly", host_supported: true, srcs: [ - "cpp/src/sfntly/data/byte_array.cc", - "cpp/src/sfntly/data/font_data.cc", - "cpp/src/sfntly/data/font_input_stream.cc", - "cpp/src/sfntly/data/font_output_stream.cc", - "cpp/src/sfntly/data/growable_memory_byte_array.cc", - "cpp/src/sfntly/data/memory_byte_array.cc", - "cpp/src/sfntly/data/readable_font_data.cc", - "cpp/src/sfntly/data/writable_font_data.cc", - "cpp/src/sfntly/font.cc", - "cpp/src/sfntly/font_factory.cc", - "cpp/src/sfntly/port/file_input_stream.cc", - "cpp/src/sfntly/port/lock.cc", - "cpp/src/sfntly/port/memory_input_stream.cc", - "cpp/src/sfntly/port/memory_output_stream.cc", - "cpp/src/sfntly/table/bitmap/big_glyph_metrics.cc", - "cpp/src/sfntly/table/bitmap/bitmap_glyph.cc", - "cpp/src/sfntly/table/bitmap/bitmap_glyph_info.cc", - "cpp/src/sfntly/table/bitmap/bitmap_size_table.cc", - "cpp/src/sfntly/table/bitmap/composite_bitmap_glyph.cc", - "cpp/src/sfntly/table/bitmap/ebdt_table.cc", - "cpp/src/sfntly/table/bitmap/eblc_table.cc", - "cpp/src/sfntly/table/bitmap/ebsc_table.cc", - "cpp/src/sfntly/table/bitmap/glyph_metrics.cc", - "cpp/src/sfntly/table/bitmap/index_sub_table.cc", - "cpp/src/sfntly/table/bitmap/index_sub_table_format1.cc", - "cpp/src/sfntly/table/bitmap/index_sub_table_format2.cc", - "cpp/src/sfntly/table/bitmap/index_sub_table_format3.cc", - "cpp/src/sfntly/table/bitmap/index_sub_table_format4.cc", - "cpp/src/sfntly/table/bitmap/index_sub_table_format5.cc", - "cpp/src/sfntly/table/bitmap/simple_bitmap_glyph.cc", - "cpp/src/sfntly/table/bitmap/small_glyph_metrics.cc", - "cpp/src/sfntly/table/byte_array_table_builder.cc", - "cpp/src/sfntly/table/core/cmap_table.cc", - "cpp/src/sfntly/table/core/font_header_table.cc", - "cpp/src/sfntly/table/core/horizontal_device_metrics_table.cc", - "cpp/src/sfntly/table/core/horizontal_header_table.cc", - "cpp/src/sfntly/table/core/horizontal_metrics_table.cc", - "cpp/src/sfntly/table/core/maximum_profile_table.cc", - "cpp/src/sfntly/table/core/name_table.cc", - "cpp/src/sfntly/table/core/os2_table.cc", - "cpp/src/sfntly/table/font_data_table.cc", - "cpp/src/sfntly/table/generic_table_builder.cc", - "cpp/src/sfntly/table/header.cc", - "cpp/src/sfntly/table/subtable.cc", - "cpp/src/sfntly/table/table.cc", - "cpp/src/sfntly/table/table_based_table_builder.cc", - "cpp/src/sfntly/table/truetype/glyph_table.cc", - "cpp/src/sfntly/table/truetype/loca_table.cc", - "cpp/src/sfntly/tag.cc", + "cpp/src/sfntly/*.cc", + "cpp/src/sfntly/data/*.cc", + "cpp/src/sfntly/port/*.cc", + "cpp/src/sfntly/table/**/*.cc", "cpp/src/sample/chromium/font_subsetter.cc", "cpp/src/sample/chromium/subsetter_impl.cc", ], diff --git a/COPYING.android b/COPYING.android deleted file mode 100644 index 13bcce2..0000000 --- a/COPYING.android +++ /dev/null @@ -1,2 +0,0 @@ -See cpp/COPYING for license details. - @@ -0,0 +1 @@ +cpp/COPYING.txt
\ No newline at end of file @@ -5,10 +5,10 @@ third_party { type: GIT value: "https://github.com/googlefonts/sfntly.git" } - version: "64f78562d2003eb7cacaaa86a398cbd41881ba6f" + version: "9620b607af5b796badefebcf16d7ce6e6786f205" last_upgrade_date { - year: 2017 - month: 4 - day: 11 + year: 2019 + month: 5 + day: 3 } } @@ -1,203 +1 @@ - - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - - TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - - 1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - - 2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - - 3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - - 4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - - 5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - - 6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - - 7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - - 8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - - 9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - - END OF TERMS AND CONDITIONS - - APPENDIX: How to apply the Apache License to your work. - - To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "[]" - replaced with your own identifying information. (Don't include - the brackets!) The text should be enclosed in the appropriate - comment syntax for the file format. We also recommend that a - file or class name and description of purpose be included on the - same "printed page" as the copyright notice for easier - identification within third-party archives. - - Copyright 2011 Google Inc. All Rights Reserved. - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - +LICENSE
\ No newline at end of file @@ -1,17 +1,6 @@ -# What is sfntly? +# sfntly -sfntly is pronounced "esfontlee". +This project is not developed any further. +Only Bug fixes will be merged, but new features won't. -sfntly is a Java and C++ library for using, editing, and creating sfnt container based fonts (e.g. OpenType, TrueType). This library was initially created by Google's Font Team and the C++ port was done by the Chrome team. It has been made open source. - -The basic features of sfntly are the reading, editing, and writing of an sfnt container font. Fonts that use an sfnt container include OpenType, TrueType, AAT/GX, and Graphite. sfntly isn't itself a tool that is usable by an end user - it is a library that allows software developers to build tools that manipulate fonts in ways that haven't been easily accessible to most developers. The sfntly library is available in Java with a partial C++ port. However, we have included some font tools that are built on top of sfntly: a font subsetter, font dumper, a font linter, some compression utilities. - -The uses of sfntly are really anything that you can think of that involves reading and/or editing fonts. Right now, the Java version is the core library used to power Google's Web Fonts project. There it is used for all font manipulation - to read font data, to pull apart fonts, and to then reassemble them before they are streamed out to a user. Portions of the font that are not needed - specific glyph ranges or features - are stripped using sfntly to minimize the size of the streamed font. The C++ port is used somewhat similarly within Chrome to subset fonts for insertion into a PDF for viewing or printing. Though the features stripped in the font are different in Chrome than in Web Fonts because the end use is different. - -Using sfntly you can read and extract any of the tables in a font. The tables are the individual data structures within the font for each of the features and functionality: glyph outlines, character maps, kerning, meta data, etc. If you look over the OpenType and TrueType specs, you will see a number of categories of tables. sfntly currently supports all of the required tables, the TrueType outline tables, bitmap glyph tables, and a couple of the other miscellaneous tables. This level of support provides for many of the needs developers have related to the informational reading of font data. It also covers a lot of the editing needs. - -To get started with sfntly: clone the repository and follow the quickstart.txt guide in the Java directory - -have fun - -Stuart Gill - sfntly Architect and Lead Developer +An actively maintained fork with new features is available at <https://github.com/rillig/sfntly> diff --git a/cpp/CMakeLists.txt b/cpp/CMakeLists.txt index 85932bc..57bcabc 100644 --- a/cpp/CMakeLists.txt +++ b/cpp/CMakeLists.txt @@ -6,13 +6,15 @@ set(CMAKE_LEGACY_CYGWIN_WIN32 0) project(sfntly) +set(GCC_OR_CLANG ((CMAKE_CXX_COMPILER_ID MATCHES "Clang") OR CMAKE_COMPILER_IS_GNUCXX)) + # For gcc, make the default be debug build and valgrind friendly. -if(CMAKE_COMPILER_IS_GNUCXX) +if(GCC_OR_CLANG) if(NOT CMAKE_BUILD_TYPE) set(CMAKE_BUILD_TYPE Debug) add_definitions("-DDEBUG -D_DEBUG -g -fno-inline -fno-omit-frame-pointer -fno-builtin") endif(NOT CMAKE_BUILD_TYPE) -endif(CMAKE_COMPILER_IS_GNUCXX) +endif(GCC_OR_CLANG) set(LIBRARY_OUTPUT_PATH ${CMAKE_CURRENT_BINARY_DIR}/lib) set(EXECUTABLE_OUTPUT_PATH ${CMAKE_CURRENT_BINARY_DIR}/bin) @@ -21,9 +23,9 @@ endif(CMAKE_COMPILER_IS_GNUCXX) # The following simulates Chrome compilation flags add_definitions(-DSFNTLY_NO_EXCEPTION) -if(CMAKE_COMPILER_IS_GNUCXX) +if(GCC_OR_CLANG) add_definitions(-D__wur=__attribute__\(\(warn_unused_result\)\) -Wall -Werror -fno-exceptions) -endif(CMAKE_COMPILER_IS_GNUCXX) +endif(GCC_OR_CLANG) # Use STL for TinyXML library add_definitions(-DTIXML_USE_STL) @@ -69,9 +71,9 @@ endif(MSVC10 OR MSVC90) src/sfntly/tools/*.h src/sfntly/tools/*.cc) add_executable(subsetter ${SIMPLE_SUBSETTER}) target_link_libraries(subsetter sfntly icuuc) -if(CMAKE_COMPILER_IS_GNUCXX) +if(GCC_OR_CLANG) target_link_libraries(subsetter pthread) -endif(CMAKE_COMPILER_IS_GNUCXX) +endif(GCC_OR_CLANG) file(GLOB TINYXML src/test/tinyxml/*.cpp) add_library(tinyxml ${TINYXML}) @@ -86,9 +88,9 @@ endif(CMAKE_COMPILER_IS_GNUCXX) ext/gtest/src/gtest-all.cc ext/gtest/src/gtest_main.cc) target_link_libraries(unit_test sfntly icuuc tinyxml) -if(CMAKE_COMPILER_IS_GNUCXX) +if(GCC_OR_CLANG) target_link_libraries(unit_test pthread) -endif(CMAKE_COMPILER_IS_GNUCXX) +endif(GCC_OR_CLANG) # subtly targets file(GLOB SUBTLY_FILES src/sample/subtly/*.h src/sample/subtly/*.cc) file(GLOB SUBTLY_MAINS src/sample/subtly/*main.cc) @@ -98,26 +100,26 @@ endif(CMAKE_COMPILER_IS_GNUCXX) add_executable(subtly_subsetter src/sample/subtly/subsetter_main.cc) target_link_libraries(subtly_subsetter subtly sfntly icuuc) -if(CMAKE_COMPILER_IS_GNUCXX) +if(GCC_OR_CLANG) target_link_libraries(subtly_subsetter pthread) -endif(CMAKE_COMPILER_IS_GNUCXX) +endif(GCC_OR_CLANG) add_executable(subtly_merger src/sample/subtly/merger_main.cc) target_link_libraries(subtly_merger subtly sfntly icuuc) -if(CMAKE_COMPILER_IS_GNUCXX) +if(GCC_OR_CLANG) target_link_libraries(subtly_merger pthread) -endif(CMAKE_COMPILER_IS_GNUCXX) +endif(GCC_OR_CLANG) add_executable(subtly_debug src/sample/subtly/debug_main.cc) target_link_libraries(subtly_debug subtly sfntly icuuc) -if(CMAKE_COMPILER_IS_GNUCXX) +if(GCC_OR_CLANG) target_link_libraries(subtly_debug pthread) -endif(CMAKE_COMPILER_IS_GNUCXX) +endif(GCC_OR_CLANG) add_executable(chrome_subsetter ${CHROME_SUBSETTER_LIB} src/sample/chromium/chrome_subsetter.cc ) target_link_libraries(chrome_subsetter sfntly icuuc) - if(CMAKE_COMPILER_IS_GNUCXX) + if(GCC_OR_CLANG) target_link_libraries(chrome_subsetter pthread) - endif(CMAKE_COMPILER_IS_GNUCXX) + endif(GCC_OR_CLANG) diff --git a/cpp/README.txt b/cpp/README.txt deleted file mode 100644 index ac2b43a..0000000 --- a/cpp/README.txt +++ /dev/null @@ -1,3 +0,0 @@ -Please refer to http://code.google.com/p/sfntly/wiki/build_cpp regarding how to build sfntly. - -sfntly wiki contains other useful documents: http://code.google.com/p/sfntly/w/list
\ No newline at end of file diff --git a/cpp/src/sample/chromium/subsetter_impl.cc b/cpp/src/sample/chromium/subsetter_impl.cc index fc82ef1..d6c3216 100644 --- a/cpp/src/sample/chromium/subsetter_impl.cc +++ b/cpp/src/sample/chromium/subsetter_impl.cc @@ -20,11 +20,13 @@ #include <algorithm> #include <iterator> +#include <limits> #include <map> #include <set> #include <string> #include <unicode/ustring.h> +#include <unicode/uversion.h> #include "sfntly/table/bitmap/eblc_table.h" #include "sfntly/table/bitmap/ebdt_table.h" @@ -306,6 +308,10 @@ bool SetupGlyfBuilders(Font::Builder* font_builder, for (int32_t j = last_glyph_id + 1; j <= *i; ++j) { loca_list[j] = last_offset; } + + if (last_offset > std::numeric_limits<int32_t>::max() - length) + return false; + last_offset += length; loca_list[*i + 1] = last_offset; last_glyph_id = *i; @@ -320,14 +326,15 @@ bool SetupGlyfBuilders(Font::Builder* font_builder, bool HasOverlap(int32_t range_begin, int32_t range_end, const IntegerSet& glyph_ids) { - if (range_begin == range_end) { + if (range_begin == range_end) return glyph_ids.find(range_begin) != glyph_ids.end(); - } else if (range_end > range_begin) { - IntegerSet::const_iterator left = glyph_ids.lower_bound(range_begin); - IntegerSet::const_iterator right = glyph_ids.lower_bound(range_end); - return right != left; - } - return false; + + if (range_begin >= range_end) + return false; + + IntegerSet::const_iterator left = glyph_ids.lower_bound(range_begin); + IntegerSet::const_iterator right = glyph_ids.lower_bound(range_end); + return left != right; } // Initialize builder, returns false if glyph_id subset is not covered. @@ -415,14 +422,14 @@ bool InitializeBitmapBuilder(EbdtTable::Builder* ebdt, EblcTable::Builder* eblc, void CopyBigGlyphMetrics(BigGlyphMetrics::Builder* source, BigGlyphMetrics::Builder* target) { - target->SetHeight(static_cast<byte_t>(source->Height())); - target->SetWidth(static_cast<byte_t>(source->Width())); - target->SetHoriBearingX(static_cast<byte_t>(source->HoriBearingX())); - target->SetHoriBearingY(static_cast<byte_t>(source->HoriBearingY())); - target->SetHoriAdvance(static_cast<byte_t>(source->HoriAdvance())); - target->SetVertBearingX(static_cast<byte_t>(source->VertBearingX())); - target->SetVertBearingY(static_cast<byte_t>(source->VertBearingY())); - target->SetVertAdvance(static_cast<byte_t>(source->VertAdvance())); + target->SetHeight(static_cast<uint8_t>(source->Height())); + target->SetWidth(static_cast<uint8_t>(source->Width())); + target->SetHoriBearingX(static_cast<uint8_t>(source->HoriBearingX())); + target->SetHoriBearingY(static_cast<uint8_t>(source->HoriBearingY())); + target->SetHoriAdvance(static_cast<uint8_t>(source->HoriAdvance())); + target->SetVertBearingX(static_cast<uint8_t>(source->VertBearingX())); + target->SetVertBearingY(static_cast<uint8_t>(source->VertBearingY())); + target->SetVertAdvance(static_cast<uint8_t>(source->VertAdvance())); } CALLER_ATTACH IndexSubTable::Builder* @@ -685,11 +692,7 @@ bool SubsetterImpl::LoadFont(const char* font_name, FontArray font_array; factory_->LoadFonts(&mis, &font_array); font_ = FindFont(font_name, font_array); - if (font_ == NULL) { - return false; - } - - return true; + return font_ != NULL; } int SubsetterImpl::SubsetFont(const unsigned int* glyph_ids, @@ -723,12 +726,14 @@ int SubsetterImpl::SubsetFont(const unsigned int* glyph_ids, MemoryOutputStream output_stream; factory_->SerializeFont(new_font, &output_stream); - int length = static_cast<int>(output_stream.Size()); - if (length > 0) { - *output_buffer = new unsigned char[length]; - memcpy(*output_buffer, output_stream.Get(), length); + size_t length = output_stream.Size(); + if (length == 0 || + length > static_cast<size_t>(std::numeric_limits<int>::max())) { + return 0; } + *output_buffer = new unsigned char[length]; + memcpy(*output_buffer, output_stream.Get(), length); return length; } @@ -790,6 +795,8 @@ Font* SubsetterImpl::Subset(const IntegerSet& glyph_ids, GlyphTable* glyf, Tag::cmap, // Keep here for future tagged PDF development. Tag::name, // Keep here due to legal concerns: copyright info inside. }; + const size_t kTablesInSubSetSize = + sizeof(TABLES_IN_SUBSET) / sizeof(TABLES_IN_SUBSET[0]); // Setup font builders we need. FontBuilderPtr font_builder; @@ -817,9 +824,8 @@ Font* SubsetterImpl::Subset(const IntegerSet& glyph_ids, GlyphTable* glyf, } IntegerSet allowed_tags; - for (size_t i = 0; i < sizeof(TABLES_IN_SUBSET) / sizeof(int32_t); ++i) { + for (size_t i = 0; i < kTablesInSubSetSize; ++i) allowed_tags.insert(TABLES_IN_SUBSET[i]); - } IntegerSet result; std::set_difference(allowed_tags.begin(), allowed_tags.end(), @@ -828,12 +834,12 @@ Font* SubsetterImpl::Subset(const IntegerSet& glyph_ids, GlyphTable* glyf, allowed_tags = result; // Setup remaining builders. - for (IntegerSet::iterator i = allowed_tags.begin(), e = allowed_tags.end(); - i != e; ++i) { - Table* table = font_->GetTable(*i); - if (table) { - font_builder->NewTableBuilder(*i, table->ReadFontData()); - } + for (IntegerSet::const_iterator it = allowed_tags.begin(); + it != allowed_tags.end(); ++it) { + int32_t tag = *it; + Table* table = font_->GetTable(tag); + if (table) + font_builder->NewTableBuilder(tag, table->ReadFontData()); } return font_builder->Build(); diff --git a/cpp/src/sfntly/data/byte_array.cc b/cpp/src/sfntly/data/byte_array.cc index 57f9eed..f510881 100644 --- a/cpp/src/sfntly/data/byte_array.cc +++ b/cpp/src/sfntly/data/byte_array.cc @@ -26,9 +26,6 @@ const int32_t ByteArray::COPY_BUFFER_SIZE = 8192; ByteArray::~ByteArray() {} -int32_t ByteArray::Length() { return filled_length_; } -int32_t ByteArray::Size() { return storage_length_; } - int32_t ByteArray::SetFilledLength(int32_t filled_length) { filled_length_ = std::min<int32_t>(filled_length, storage_length_); return filled_length_; @@ -40,24 +37,27 @@ int32_t ByteArray::Get(int32_t index) { return InternalGet(index) & 0xff; } -int32_t ByteArray::Get(int32_t index, ByteVector* b) { +int32_t ByteArray::Get(int32_t index, std::vector<uint8_t>* b) { assert(b); return Get(index, &((*b)[0]), 0, b->size()); } int32_t ByteArray::Get(int32_t index, - byte_t* b, + uint8_t* b, int32_t offset, int32_t length) { assert(b); - if (index < 0 || index >= filled_length_) { + if (index < 0 || index >= filled_length_) return 0; - } + + if (length <= 0) + return 0; + int32_t actual_length = std::min<int32_t>(length, filled_length_ - index); return InternalGet(index, b, offset, actual_length); } -void ByteArray::Put(int32_t index, byte_t b) { +void ByteArray::Put(int32_t index, uint8_t b) { if (index < 0 || index >= Size()) { #if defined (SFNTLY_NO_EXCEPTION) return; @@ -70,13 +70,13 @@ void ByteArray::Put(int32_t index, byte_t b) { filled_length_ = std::max<int32_t>(filled_length_, index + 1); } -int32_t ByteArray::Put(int index, ByteVector* b) { +int32_t ByteArray::Put(int index, std::vector<uint8_t>* b) { assert(b); return Put(index, &((*b)[0]), 0, b->size()); } int32_t ByteArray::Put(int32_t index, - byte_t* b, + uint8_t* b, int32_t offset, int32_t length) { assert(b); @@ -109,7 +109,7 @@ int32_t ByteArray::CopyTo(int32_t dst_offset, ByteArray* array, return -1; } - ByteVector b(COPY_BUFFER_SIZE); + std::vector<uint8_t> b(COPY_BUFFER_SIZE); int32_t bytes_read = 0; int32_t index = 0; int32_t remaining_length = length; @@ -130,7 +130,7 @@ int32_t ByteArray::CopyTo(OutputStream* os) { } int32_t ByteArray::CopyTo(OutputStream* os, int32_t offset, int32_t length) { - ByteVector b(COPY_BUFFER_SIZE); + std::vector<uint8_t> b(COPY_BUFFER_SIZE); int32_t bytes_read = 0; int32_t index = 0; int32_t buffer_length = std::min<int32_t>(COPY_BUFFER_SIZE, length); @@ -143,7 +143,7 @@ int32_t ByteArray::CopyTo(OutputStream* os, int32_t offset, int32_t length) { } bool ByteArray::CopyFrom(InputStream* is, int32_t length) { - ByteVector b(COPY_BUFFER_SIZE); + std::vector<uint8_t> b(COPY_BUFFER_SIZE); int32_t bytes_read = 0; int32_t index = 0; int32_t buffer_length = std::min<int32_t>(COPY_BUFFER_SIZE, length); @@ -163,7 +163,7 @@ bool ByteArray::CopyFrom(InputStream* is, int32_t length) { } bool ByteArray::CopyFrom(InputStream* is) { - ByteVector b(COPY_BUFFER_SIZE); + std::vector<uint8_t> b(COPY_BUFFER_SIZE); int32_t bytes_read = 0; int32_t index = 0; int32_t buffer_length = COPY_BUFFER_SIZE; diff --git a/cpp/src/sfntly/data/byte_array.h b/cpp/src/sfntly/data/byte_array.h index 70dc92f..c5e3788 100644 --- a/cpp/src/sfntly/data/byte_array.h +++ b/cpp/src/sfntly/data/byte_array.h @@ -32,15 +32,15 @@ class ByteArray : virtual public RefCount { virtual ~ByteArray(); // Gets the current filled and readable length of the array. - int32_t Length(); + int32_t Length() const { return filled_length_; } // Gets the maximum size of the array. This is the maximum number of bytes that // the array can hold and all of it may not be filled with data or even fully // allocated yet. - int32_t Size(); + int32_t Size() const { return storage_length_; } // Determines whether or not this array is growable or of fixed size. - bool growable() { return growable_; } + bool growable() const { return growable_; } int32_t SetFilledLength(int32_t filled_length); @@ -55,7 +55,7 @@ class ByteArray : virtual public RefCount { // @param index the index into the byte array // @param b the buffer to put the bytes read into // @return the number of bytes read from the buffer - virtual int32_t Get(int32_t index, ByteVector* b); + virtual int32_t Get(int32_t index, std::vector<uint8_t>* b); // Gets the bytes from the given index and fill the buffer with them starting // at the offset given. As many bytes as the specified length are read unless @@ -66,18 +66,18 @@ class ByteArray : virtual public RefCount { // @param length the number of bytes to put into the buffer // @return the number of bytes read from the buffer virtual int32_t Get(int32_t index, - byte_t* b, + uint8_t* b, int32_t offset, int32_t length); // Puts the specified byte into the array at the given index unless that would // be beyond the length of the array and it isn't growable. - virtual void Put(int32_t index, byte_t b); + virtual void Put(int32_t index, uint8_t b); // Puts the specified bytes into the array at the given index. The entire // buffer is put into the array unless that would extend beyond the length and // the array isn't growable. - virtual int32_t Put(int32_t index, ByteVector* b); + virtual int32_t Put(int32_t index, std::vector<uint8_t>* b); // Puts the specified bytes into the array at the given index. All of the bytes // specified are put into the array unless that would extend beyond the length @@ -89,7 +89,7 @@ class ByteArray : virtual public RefCount { // @param length the number of bytes to copy into the array // @return the number of bytes actually written virtual int32_t Put(int32_t index, - byte_t* b, + uint8_t* b, int32_t offset, int32_t length); @@ -149,7 +149,7 @@ class ByteArray : virtual public RefCount { // Stores the byte at the index given. // @param index the location to store at // @param b the byte to store - virtual void InternalPut(int32_t index, byte_t b) = 0; + virtual void InternalPut(int32_t index, uint8_t b) = 0; // Stores the array of bytes at the given index. // @param index the location to store at @@ -158,14 +158,14 @@ class ByteArray : virtual public RefCount { // @param length the length of the byte array to store from the offset // @return the number of bytes actually stored virtual int32_t InternalPut(int32_t index, - byte_t* b, + uint8_t* b, int32_t offset, int32_t length) = 0; // Gets the byte at the index given. // @param index the location to get from // @return the byte stored at the index - virtual byte_t InternalGet(int32_t index) = 0; + virtual uint8_t InternalGet(int32_t index) = 0; // Gets the bytes at the index given of the given length. // @param index the location to start getting from @@ -174,7 +174,7 @@ class ByteArray : virtual public RefCount { // @param length the length of bytes to read // @return the number of bytes actually ready virtual int32_t InternalGet(int32_t index, - byte_t* b, + uint8_t* b, int32_t offset, int32_t length) = 0; @@ -182,7 +182,7 @@ class ByteArray : virtual public RefCount { virtual void Close() = 0; // C++ port only, raw pointer to the first element of storage. - virtual byte_t* Begin() = 0; + virtual uint8_t* Begin() = 0; // Java toString() not ported. diff --git a/cpp/src/sfntly/data/font_data.cc b/cpp/src/sfntly/data/font_data.cc index 95bee3e..8fa8610 100644 --- a/cpp/src/sfntly/data/font_data.cc +++ b/cpp/src/sfntly/data/font_data.cc @@ -81,11 +81,11 @@ void FontData::Init(ByteArray* ba) { bound_length_ = GROWABLE_SIZE; } -int32_t FontData::BoundOffset(int32_t offset) { +int32_t FontData::BoundOffset(int32_t offset) const { return offset + bound_offset_; } -int32_t FontData::BoundLength(int32_t offset, int32_t length) { +int32_t FontData::BoundLength(int32_t offset, int32_t length) const { return std::min<int32_t>(length, bound_length_ - offset); } diff --git a/cpp/src/sfntly/data/font_data.h b/cpp/src/sfntly/data/font_data.h index e0e7e79..20c7e37 100644 --- a/cpp/src/sfntly/data/font_data.h +++ b/cpp/src/sfntly/data/font_data.h @@ -99,14 +99,14 @@ class FontData : virtual public RefCount { // the data. // @param offset the offset to get the bound compensated offset for // @return the bound compensated offset - int32_t BoundOffset(int32_t offset); + int32_t BoundOffset(int32_t offset) const; // Gets the length in the underlying data taking into account any bounds on // the data. // @param offset the offset that the length is being used at // @param length the length to get the bound compensated length for // @return the bound compensated length - int32_t BoundLength(int32_t offset, int32_t length); + int32_t BoundLength(int32_t offset, int32_t length) const; static const int32_t GROWABLE_SIZE = INT_MAX; diff --git a/cpp/src/sfntly/data/font_input_stream.cc b/cpp/src/sfntly/data/font_input_stream.cc index dcf8be3..87a515b 100644 --- a/cpp/src/sfntly/data/font_input_stream.cc +++ b/cpp/src/sfntly/data/font_input_stream.cc @@ -32,10 +32,17 @@ FontInputStream::~FontInputStream() { // Do not close here, underlying InputStream will close themselves. } +int32_t FontInputStream::Length() { + if (bounded_) + return length_; + if (stream_) + return stream_->Length(); + return 0; +} + int32_t FontInputStream::Available() { - if (stream_) { + if (stream_) return stream_->Available(); - } return 0; } @@ -75,7 +82,7 @@ int32_t FontInputStream::Read() { return b; } -int32_t FontInputStream::Read(ByteVector* b, int32_t offset, int32_t length) { +int32_t FontInputStream::Read(std::vector<uint8_t>* b, int32_t offset, int32_t length) { if (!stream_ || offset < 0 || length < 0 || (bounded_ && position_ >= length_)) { return -1; @@ -88,7 +95,7 @@ int32_t FontInputStream::Read(ByteVector* b, int32_t offset, int32_t length) { return bytes_read; } -int32_t FontInputStream::Read(ByteVector* b) { +int32_t FontInputStream::Read(std::vector<uint8_t>* b) { return Read(b, 0, b->size()); } diff --git a/cpp/src/sfntly/data/font_input_stream.h b/cpp/src/sfntly/data/font_input_stream.h index 9992b07..c02848d 100644 --- a/cpp/src/sfntly/data/font_input_stream.h +++ b/cpp/src/sfntly/data/font_input_stream.h @@ -59,7 +59,7 @@ class FontInputStream : public InputStream { virtual ~FontInputStream(); - + virtual int32_t Length(); virtual int32_t Available(); virtual void Close(); virtual void Mark(int32_t readlimit); @@ -67,8 +67,8 @@ class FontInputStream : public InputStream { virtual void Reset(); virtual int32_t Read(); - virtual int32_t Read(ByteVector* buffer); - virtual int32_t Read(ByteVector* buffer, int32_t offset, int32_t length); + virtual int32_t Read(std::vector<uint8_t>* buffer); + virtual int32_t Read(std::vector<uint8_t>* buffer, int32_t offset, int32_t length); // Get the current position in the stream in bytes. // @return the current position in bytes diff --git a/cpp/src/sfntly/data/font_output_stream.cc b/cpp/src/sfntly/data/font_output_stream.cc index 3422a22..169b02f 100644 --- a/cpp/src/sfntly/data/font_output_stream.cc +++ b/cpp/src/sfntly/data/font_output_stream.cc @@ -29,21 +29,21 @@ FontOutputStream::~FontOutputStream() { // Do not close, underlying stream shall clean up themselves. } -void FontOutputStream::Write(byte_t b) { +void FontOutputStream::Write(uint8_t b) { if (stream_) { stream_->Write(b); position_++; } } -void FontOutputStream::Write(ByteVector* b) { +void FontOutputStream::Write(std::vector<uint8_t>* b) { if (b) { Write(b, 0, b->size()); position_ += b->size(); } } -void FontOutputStream::Write(ByteVector* b, int32_t off, int32_t len) { +void FontOutputStream::Write(std::vector<uint8_t>* b, int32_t off, int32_t len) { assert(b); assert(stream_); if (off < 0 || len < 0 || off + len < 0 || @@ -59,7 +59,7 @@ void FontOutputStream::Write(ByteVector* b, int32_t off, int32_t len) { position_ += len; } -void FontOutputStream::Write(byte_t* b, int32_t off, int32_t len) { +void FontOutputStream::Write(uint8_t* b, int32_t off, int32_t len) { assert(b); assert(stream_); if (off < 0 || len < 0 || off + len < 0) { @@ -74,13 +74,13 @@ void FontOutputStream::Write(byte_t* b, int32_t off, int32_t len) { position_ += len; } -void FontOutputStream::WriteChar(byte_t c) { +void FontOutputStream::WriteChar(uint8_t c) { Write(c); } void FontOutputStream::WriteUShort(int32_t us) { - Write((byte_t)((us >> 8) & 0xff)); - Write((byte_t)(us & 0xff)); + Write((uint8_t)((us >> 8) & 0xff)); + Write((uint8_t)(us & 0xff)); } void FontOutputStream::WriteShort(int32_t s) { @@ -88,16 +88,16 @@ void FontOutputStream::WriteShort(int32_t s) { } void FontOutputStream::WriteUInt24(int32_t ui) { - Write((byte_t)(ui >> 16) & 0xff); - Write((byte_t)(ui >> 8) & 0xff); - Write((byte_t)ui & 0xff); + Write((uint8_t)(ui >> 16) & 0xff); + Write((uint8_t)(ui >> 8) & 0xff); + Write((uint8_t)ui & 0xff); } void FontOutputStream::WriteULong(int64_t ul) { - Write((byte_t)((ul >> 24) & 0xff)); - Write((byte_t)((ul >> 16) & 0xff)); - Write((byte_t)((ul >> 8) & 0xff)); - Write((byte_t)(ul & 0xff)); + Write((uint8_t)((ul >> 24) & 0xff)); + Write((uint8_t)((ul >> 16) & 0xff)); + Write((uint8_t)((ul >> 8) & 0xff)); + Write((uint8_t)(ul & 0xff)); } void FontOutputStream::WriteLong(int64_t l) { diff --git a/cpp/src/sfntly/data/font_output_stream.h b/cpp/src/sfntly/data/font_output_stream.h index fcd48e8..fa4d346 100644 --- a/cpp/src/sfntly/data/font_output_stream.h +++ b/cpp/src/sfntly/data/font_output_stream.h @@ -48,13 +48,11 @@ class FontOutputStream : public OutputStream { explicit FontOutputStream(OutputStream* os); virtual ~FontOutputStream(); - virtual size_t position() { return position_; } - - virtual void Write(byte_t b); - virtual void Write(ByteVector* b); - virtual void Write(ByteVector* b, int32_t off, int32_t len); - virtual void Write(byte_t* b, int32_t off, int32_t len); - virtual void WriteChar(byte_t c); + virtual void Write(uint8_t b); + virtual void Write(std::vector<uint8_t>* b); + virtual void Write(std::vector<uint8_t>* b, int32_t off, int32_t len); + virtual void Write(uint8_t* b, int32_t off, int32_t len); + virtual void WriteChar(uint8_t c); virtual void WriteUShort(int32_t us); virtual void WriteShort(int32_t s); virtual void WriteUInt24(int32_t ui); diff --git a/cpp/src/sfntly/data/growable_memory_byte_array.cc b/cpp/src/sfntly/data/growable_memory_byte_array.cc index c335614..b7b10fc 100644 --- a/cpp/src/sfntly/data/growable_memory_byte_array.cc +++ b/cpp/src/sfntly/data/growable_memory_byte_array.cc @@ -39,7 +39,7 @@ int32_t GrowableMemoryByteArray::CopyTo(OutputStream* os, return length; } -void GrowableMemoryByteArray::InternalPut(int32_t index, byte_t b) { +void GrowableMemoryByteArray::InternalPut(int32_t index, uint8_t b) { if ((size_t)index >= b_.size()) { b_.resize((size_t)(index + 1)); } @@ -47,7 +47,7 @@ void GrowableMemoryByteArray::InternalPut(int32_t index, byte_t b) { } int32_t GrowableMemoryByteArray::InternalPut(int32_t index, - byte_t* b, + uint8_t* b, int32_t offset, int32_t length) { if ((size_t)index + length >= b_.size()) { @@ -59,12 +59,12 @@ int32_t GrowableMemoryByteArray::InternalPut(int32_t index, return length; } -byte_t GrowableMemoryByteArray::InternalGet(int32_t index) { +uint8_t GrowableMemoryByteArray::InternalGet(int32_t index) { return b_[index]; } int32_t GrowableMemoryByteArray::InternalGet(int32_t index, - byte_t* b, + uint8_t* b, int32_t offset, int32_t length) { memcpy(b + offset, &(b_[0]) + index, length); @@ -75,7 +75,7 @@ void GrowableMemoryByteArray::Close() { b_.clear(); } -byte_t* GrowableMemoryByteArray::Begin() { +uint8_t* GrowableMemoryByteArray::Begin() { return &(b_[0]); } diff --git a/cpp/src/sfntly/data/growable_memory_byte_array.h b/cpp/src/sfntly/data/growable_memory_byte_array.h index 8583a0d..370d2cb 100644 --- a/cpp/src/sfntly/data/growable_memory_byte_array.h +++ b/cpp/src/sfntly/data/growable_memory_byte_array.h @@ -44,21 +44,21 @@ class GrowableMemoryByteArray : public ByteArray, virtual int32_t CopyTo(OutputStream* os) { return ByteArray::CopyTo(os); } protected: - virtual void InternalPut(int32_t index, byte_t b); + virtual void InternalPut(int32_t index, uint8_t b); virtual int32_t InternalPut(int32_t index, - byte_t* b, + uint8_t* b, int32_t offset, int32_t length); - virtual byte_t InternalGet(int32_t index); + virtual uint8_t InternalGet(int32_t index); virtual int32_t InternalGet(int32_t index, - byte_t* b, + uint8_t* b, int32_t offset, int32_t length); virtual void Close(); - virtual byte_t* Begin(); + virtual uint8_t* Begin(); private: - ByteVector b_; + std::vector<uint8_t> b_; }; } // namespace sfntly diff --git a/cpp/src/sfntly/data/memory_byte_array.cc b/cpp/src/sfntly/data/memory_byte_array.cc index d6c9c48..9a81cf6 100644 --- a/cpp/src/sfntly/data/memory_byte_array.cc +++ b/cpp/src/sfntly/data/memory_byte_array.cc @@ -24,7 +24,7 @@ MemoryByteArray::MemoryByteArray(int32_t length) : ByteArray(0, length), b_(NULL), allocated_(true) { } -MemoryByteArray::MemoryByteArray(byte_t* b, int32_t filled_length) +MemoryByteArray::MemoryByteArray(uint8_t* b, int32_t filled_length) : ByteArray(filled_length, filled_length), b_(b), allocated_(false) { assert(b); } @@ -43,18 +43,18 @@ int32_t MemoryByteArray::CopyTo(OutputStream* os, void MemoryByteArray::Init() { if (allocated_ && b_ == NULL) { - b_ = new byte_t[Size()]; + b_ = new uint8_t[Size()]; memset(b_, 0, Size()); } } -void MemoryByteArray::InternalPut(int32_t index, byte_t b) { +void MemoryByteArray::InternalPut(int32_t index, uint8_t b) { Init(); b_[index] = b; } int32_t MemoryByteArray::InternalPut(int32_t index, - byte_t* b, + uint8_t* b, int32_t offset, int32_t length) { assert(b); @@ -63,13 +63,13 @@ int32_t MemoryByteArray::InternalPut(int32_t index, return length; } -byte_t MemoryByteArray::InternalGet(int32_t index) { +uint8_t MemoryByteArray::InternalGet(int32_t index) { Init(); return b_[index]; } int32_t MemoryByteArray::InternalGet(int32_t index, - byte_t* b, + uint8_t* b, int32_t offset, int32_t length) { assert(b); @@ -85,7 +85,7 @@ void MemoryByteArray::Close() { b_ = NULL; } -byte_t* MemoryByteArray::Begin() { +uint8_t* MemoryByteArray::Begin() { Init(); return b_; } diff --git a/cpp/src/sfntly/data/memory_byte_array.h b/cpp/src/sfntly/data/memory_byte_array.h index 838fd1a..b84cc5a 100644 --- a/cpp/src/sfntly/data/memory_byte_array.h +++ b/cpp/src/sfntly/data/memory_byte_array.h @@ -28,7 +28,7 @@ class MemoryByteArray : public ByteArray, public RefCounted<MemoryByteArray> { explicit MemoryByteArray(int32_t length); // Note: not implemented due to dangerous operations in constructor. - //explicit MemoryByteArray(ByteVector* b); + //explicit MemoryByteArray(std::vector<uint8_t>* b); // Construct a new MemoryByteArray using byte array. // @param b the byte array that provides the actual storage @@ -37,7 +37,7 @@ class MemoryByteArray : public ByteArray, public RefCounted<MemoryByteArray> { // ownership of b. Caller is responsible for handling the lifetime // of b. C++ port also assumes filled_length is buffer_length since // there is not a reliable way to identify the actual size of buffer. - MemoryByteArray(byte_t* b, int32_t filled_length); + MemoryByteArray(uint8_t* b, int32_t filled_length); virtual ~MemoryByteArray(); virtual int32_t CopyTo(OutputStream* os, int32_t offset, int32_t length); @@ -56,23 +56,23 @@ class MemoryByteArray : public ByteArray, public RefCounted<MemoryByteArray> { virtual int32_t CopyTo(OutputStream* os) { return ByteArray::CopyTo(os); } protected: - virtual void InternalPut(int32_t index, byte_t b); + virtual void InternalPut(int32_t index, uint8_t b); virtual int32_t InternalPut(int32_t index, - byte_t* b, + uint8_t* b, int32_t offset, int32_t length); - virtual byte_t InternalGet(int32_t index); + virtual uint8_t InternalGet(int32_t index); virtual int32_t InternalGet(int32_t index, - byte_t* b, + uint8_t* b, int32_t offset, int32_t length); virtual void Close(); - virtual byte_t* Begin(); + virtual uint8_t* Begin(); private: void Init(); // C++ port only, used to allocate memory outside constructor. - byte_t* b_; + uint8_t* b_; bool allocated_; }; diff --git a/cpp/src/sfntly/data/readable_font_data.cc b/cpp/src/sfntly/data/readable_font_data.cc index 07a0db6..b7c5332 100644 --- a/cpp/src/sfntly/data/readable_font_data.cc +++ b/cpp/src/sfntly/data/readable_font_data.cc @@ -38,7 +38,7 @@ ReadableFontData::~ReadableFontData() {} // not too useful without copying, but it's not performance // savvy to do copying. CALLER_ATTACH -ReadableFontData* ReadableFontData::CreateReadableFontData(ByteVector* b) { +ReadableFontData* ReadableFontData::CreateReadableFontData(std::vector<uint8_t>* b) { assert(b); ByteArrayPtr ba = new MemoryByteArray(b->size()); ba->Put(0, b); @@ -54,7 +54,7 @@ int64_t ReadableFontData::Checksum() { return checksum_; } -void ReadableFontData::SetCheckSumRanges(const IntegerList& ranges) { +void ReadableFontData::SetCheckSumRanges(const std::vector<int32_t>& ranges) { checksum_range_ = ranges; checksum_set_ = false; // UNIMPLEMENTED: atomicity } @@ -84,7 +84,7 @@ int32_t ReadableFontData::ReadByte(int32_t index) { } int32_t ReadableFontData::ReadBytes(int32_t index, - byte_t* b, + uint8_t* b, int32_t offset, int32_t length) { return array_->Get(BoundOffset(index), b, offset, BoundLength(index, length)); @@ -192,13 +192,13 @@ int32_t ReadableFontData::ReadFixed(int32_t index) { } int64_t ReadableFontData::ReadDateTimeAsLong(int32_t index) { - int32_t high = ReadULong(index); + int64_t high = ReadULong(index); if (high == kInvalidUnsigned) return kInvalidLongDateTime; - int32_t low = ReadULong(index + 4); + int64_t low = ReadULong(index + 4); if (low == kInvalidUnsigned) return kInvalidLongDateTime; - return (int64_t)high << 32 | low; + return high << 32 | low; } int32_t ReadableFontData::ReadFWord(int32_t index) { diff --git a/cpp/src/sfntly/data/readable_font_data.h b/cpp/src/sfntly/data/readable_font_data.h index 37a0918..db5e70c 100644 --- a/cpp/src/sfntly/data/readable_font_data.h +++ b/cpp/src/sfntly/data/readable_font_data.h @@ -57,7 +57,7 @@ class ReadableFontData : public FontData, static const int32_t kInvalidUnsigned = -1; static const int64_t kInvalidLongDateTime = -1; - static CALLER_ATTACH ReadableFontData* CreateReadableFontData(ByteVector* b); + static CALLER_ATTACH ReadableFontData* CreateReadableFontData(std::vector<uint8_t>* b); // Gets a computed checksum for the data. This checksum uses the OpenType spec // calculation. Every ULong value (32 bit unsigned) in the data is summed and @@ -72,7 +72,7 @@ class ReadableFontData : public FontData, // assumed to extend to the end of the data. The lengths of each range must be // a multiple of 4. // @param ranges the range bounds to use for the checksum - void SetCheckSumRanges(const IntegerList& ranges); + void SetCheckSumRanges(const std::vector<int32_t>& ranges); // Read the UBYTE at the given index. // @param index index into the font data @@ -94,7 +94,7 @@ class ReadableFontData : public FontData, // @return the number of bytes actually read; -1 if the index is outside the // bounds of the font data virtual int32_t ReadBytes(int32_t index, - byte_t* b, + uint8_t* b, int32_t offset, int32_t length); @@ -306,7 +306,7 @@ class ReadableFontData : public FontData, Lock checksum_lock_; bool checksum_set_; int64_t checksum_; - IntegerList checksum_range_; + std::vector<int32_t> checksum_range_; }; typedef Ptr<ReadableFontData> ReadableFontDataPtr; diff --git a/cpp/src/sfntly/data/writable_font_data.cc b/cpp/src/sfntly/data/writable_font_data.cc index 073e9df..40c778e 100644 --- a/cpp/src/sfntly/data/writable_font_data.cc +++ b/cpp/src/sfntly/data/writable_font_data.cc @@ -47,20 +47,20 @@ WritableFontData* WritableFontData::CreateWritableFontData(int32_t length) { // not too useful without copying, but it's not performance // savvy to do copying. CALLER_ATTACH -WritableFontData* WritableFontData::CreateWritableFontData(ByteVector* b) { +WritableFontData* WritableFontData::CreateWritableFontData(std::vector<uint8_t>* b) { ByteArrayPtr ba = new GrowableMemoryByteArray(); ba->Put(0, b); WritableFontDataPtr wfd = new WritableFontData(ba); return wfd.Detach(); } -int32_t WritableFontData::WriteByte(int32_t index, byte_t b) { +int32_t WritableFontData::WriteByte(int32_t index, uint8_t b) { array_->Put(BoundOffset(index), b); return 1; } int32_t WritableFontData::WriteBytes(int32_t index, - byte_t* b, + uint8_t* b, int32_t offset, int32_t length) { return array_->Put(BoundOffset(index), @@ -69,16 +69,16 @@ int32_t WritableFontData::WriteBytes(int32_t index, BoundLength(index, length)); } -int32_t WritableFontData::WriteBytes(int32_t index, ByteVector* b) { +int32_t WritableFontData::WriteBytes(int32_t index, std::vector<uint8_t>* b) { assert(b); return WriteBytes(index, &((*b)[0]), 0, b->size()); } int32_t WritableFontData::WriteBytesPad(int32_t index, - ByteVector* b, + std::vector<uint8_t>* b, int32_t offset, int32_t length, - byte_t pad) { + uint8_t pad) { int32_t written = array_->Put(BoundOffset(index), &((*b)[0]), @@ -90,30 +90,30 @@ int32_t WritableFontData::WriteBytesPad(int32_t index, } int32_t WritableFontData::WritePadding(int32_t index, int32_t count) { - return WritePadding(index, count, (byte_t)0); + return WritePadding(index, count, (uint8_t)0); } int32_t WritableFontData::WritePadding(int32_t index, int32_t count, - byte_t pad) { + uint8_t pad) { for (int32_t i = 0; i < count; ++i) { array_->Put(index + i, pad); } return count; } -int32_t WritableFontData::WriteChar(int32_t index, byte_t c) { +int32_t WritableFontData::WriteChar(int32_t index, uint8_t c) { return WriteByte(index, c); } int32_t WritableFontData::WriteUShort(int32_t index, int32_t us) { - WriteByte(index, (byte_t)((us >> 8) & 0xff)); - WriteByte(index + 1, (byte_t)(us & 0xff)); + WriteByte(index, (uint8_t)((us >> 8) & 0xff)); + WriteByte(index + 1, (uint8_t)(us & 0xff)); return 2; } int32_t WritableFontData::WriteUShortLE(int32_t index, int32_t us) { - WriteByte(index, (byte_t)(us & 0xff)); - WriteByte(index + 1, (byte_t)((us >> 8) & 0xff)); + WriteByte(index, (uint8_t)(us & 0xff)); + WriteByte(index + 1, (uint8_t)((us >> 8) & 0xff)); return 2; } @@ -122,25 +122,25 @@ int32_t WritableFontData::WriteShort(int32_t index, int32_t s) { } int32_t WritableFontData::WriteUInt24(int32_t index, int32_t ui) { - WriteByte(index, (byte_t)((ui >> 16) & 0xff)); - WriteByte(index + 1, (byte_t)((ui >> 8) & 0xff)); - WriteByte(index + 2, (byte_t)(ui & 0xff)); + WriteByte(index, (uint8_t)((ui >> 16) & 0xff)); + WriteByte(index + 1, (uint8_t)((ui >> 8) & 0xff)); + WriteByte(index + 2, (uint8_t)(ui & 0xff)); return 3; } int32_t WritableFontData::WriteULong(int32_t index, int64_t ul) { - WriteByte(index, (byte_t)((ul >> 24) & 0xff)); - WriteByte(index + 1, (byte_t)((ul >> 16) & 0xff)); - WriteByte(index + 2, (byte_t)((ul >> 8) & 0xff)); - WriteByte(index + 3, (byte_t)(ul & 0xff)); + WriteByte(index, (uint8_t)((ul >> 24) & 0xff)); + WriteByte(index + 1, (uint8_t)((ul >> 16) & 0xff)); + WriteByte(index + 2, (uint8_t)((ul >> 8) & 0xff)); + WriteByte(index + 3, (uint8_t)(ul & 0xff)); return 4; } int32_t WritableFontData::WriteULongLE(int32_t index, int64_t ul) { - WriteByte(index, (byte_t)(ul & 0xff)); - WriteByte(index + 1, (byte_t)((ul >> 8) & 0xff)); - WriteByte(index + 2, (byte_t)((ul >> 16) & 0xff)); - WriteByte(index + 3, (byte_t)((ul >> 24) & 0xff)); + WriteByte(index, (uint8_t)(ul & 0xff)); + WriteByte(index + 1, (uint8_t)((ul >> 8) & 0xff)); + WriteByte(index + 2, (uint8_t)((ul >> 16) & 0xff)); + WriteByte(index + 3, (uint8_t)((ul >> 24) & 0xff)); return 4; } diff --git a/cpp/src/sfntly/data/writable_font_data.h b/cpp/src/sfntly/data/writable_font_data.h index d2a049e..61fc6a9 100644 --- a/cpp/src/sfntly/data/writable_font_data.h +++ b/cpp/src/sfntly/data/writable_font_data.h @@ -42,13 +42,13 @@ class WritableFontData : public ReadableFontData { // bytes. // @param b the byte vector to wrap // @return a new writable font data - static CALLER_ATTACH WritableFontData* CreateWritableFontData(ByteVector* b); + static CALLER_ATTACH WritableFontData* CreateWritableFontData(std::vector<uint8_t>* b); // Write a byte at the given index. // @param index index into the font data // @param b the byte to write // @return the number of bytes written - virtual int32_t WriteByte(int32_t index, byte_t b); + virtual int32_t WriteByte(int32_t index, uint8_t b); // Write the bytes from the array. // @param index index into the font data @@ -58,7 +58,7 @@ class WritableFontData : public ReadableFontData { // @return the number of bytes actually written; -1 if the index is outside // the FontData's range virtual int32_t WriteBytes(int32_t index, - byte_t* b, + uint8_t* b, int32_t offset, int32_t length); @@ -67,7 +67,7 @@ class WritableFontData : public ReadableFontData { // @param b the source for the bytes to be written // @return the number of bytes actually written; -1 if the index is outside // the FontData's range - virtual int32_t WriteBytes(int32_t index, ByteVector* b); + virtual int32_t WriteBytes(int32_t index, std::vector<uint8_t>* b); // Write the bytes from the array and pad if necessary. // Write to the length given using the byte array provided and if there are @@ -80,10 +80,10 @@ class WritableFontData : public ReadableFontData { // @param pad the padding byte to be used if necessary // @return the number of bytes actually written virtual int32_t WriteBytesPad(int32_t index, - ByteVector* b, + std::vector<uint8_t>* b, int32_t offset, int32_t length, - byte_t pad); + uint8_t pad); // Writes padding to the FontData. The padding byte written is 0x00. // @param index index into the font data @@ -96,14 +96,14 @@ class WritableFontData : public ReadableFontData { // @param count the number of pad bytes to write // @param pad the byte value to use as padding // @return the number of pad bytes written - virtual int32_t WritePadding(int32_t index, int32_t count, byte_t pad); + virtual int32_t WritePadding(int32_t index, int32_t count, uint8_t pad); // Write the CHAR at the given index. // @param index index into the font data // @param c the CHAR // @return the number of bytes actually written // @throws IndexOutOfBoundsException if index is outside the FontData's range - virtual int32_t WriteChar(int32_t index, byte_t c); + virtual int32_t WriteChar(int32_t index, uint8_t c); // Write the USHORT at the given index. // @param index index into the font data diff --git a/cpp/src/sfntly/font.cc b/cpp/src/sfntly/font.cc index ca35048..eec7bec 100644 --- a/cpp/src/sfntly/font.cc +++ b/cpp/src/sfntly/font.cc @@ -18,12 +18,13 @@ #include <stdio.h> -#include <functional> #include <algorithm> +#include <functional> +#include <iterator> +#include <limits> #include <map> #include <string> #include <typeinfo> -#include <iterator> #include "sfntly/data/font_input_stream.h" #include "sfntly/font_factory.h" @@ -47,6 +48,12 @@ const int32_t kSFNTVersionMinor = 0; const int32_t kMaxTableSize = 200 * 1024 * 1024; +bool IsValidHeaderRegion(int32_t data_length, int32_t offset, int32_t length) { + return offset >= 0 && length >= 0 && + offset <= std::numeric_limits<int32_t>::max() - length && + offset + length <= data_length; +} + } // namespace /****************************************************************************** @@ -68,9 +75,9 @@ const TableMap* Font::GetTableMap() { return &tables_; } -void Font::Serialize(OutputStream* os, IntegerList* table_ordering) { +void Font::Serialize(OutputStream* os, std::vector<int32_t>* table_ordering) { assert(table_ordering); - IntegerList final_table_ordering; + std::vector<int32_t> final_table_ordering; GenerateTableOrdering(table_ordering, &final_table_ordering); TableHeaderList table_records; BuildTableHeadersForSerialization(&final_table_ordering, &table_records); @@ -80,36 +87,32 @@ void Font::Serialize(OutputStream* os, IntegerList* table_ordering) { SerializeTables(&fos, &table_records); } -Font::Font(int32_t sfnt_version, ByteVector* digest) +Font::Font(int32_t sfnt_version, std::vector<uint8_t>* digest) : sfnt_version_(sfnt_version) { // non-trivial assignments that makes debugging hard if placed in // initialization list digest_ = *digest; } -void Font::BuildTableHeadersForSerialization(IntegerList* table_ordering, +void Font::BuildTableHeadersForSerialization(std::vector<int32_t>* table_ordering, TableHeaderList* table_headers) { assert(table_headers); assert(table_ordering); - IntegerList final_table_ordering; + std::vector<int32_t> final_table_ordering; GenerateTableOrdering(table_ordering, &final_table_ordering); int32_t table_offset = Offset::kTableRecordBegin + num_tables() * Offset::kTableRecordSize; - for (IntegerList::iterator tag = final_table_ordering.begin(), - tag_end = final_table_ordering.end(); - tag != tag_end; ++tag) { - if (tables_.find(*tag) == tables_.end()) { + for (size_t i = 0; i < final_table_ordering.size(); ++i) { + int32_t tag = final_table_ordering[i]; + TablePtr table = GetTable(tag); + if (table == NULL) continue; - } - TablePtr table = tables_[*tag]; - if (table != NULL) { - HeaderPtr header = - new Header(*tag, table->CalculatedChecksum(), table_offset, - table->header()->length()); - table_headers->push_back(header); - table_offset += (table->DataLength() + 3) & ~3; - } + + HeaderPtr header = new Header(tag, table->CalculatedChecksum(), + table_offset, table->header()->length()); + table_headers->push_back(header); + table_offset += (table->DataLength() + 3) & ~3; } } @@ -142,10 +145,9 @@ void Font::SerializeTables(FontOutputStream* fos, TableHeaderList* table_headers) { assert(fos); assert(table_headers); - for (TableHeaderList::iterator record = table_headers->begin(), - end_of_headers = table_headers->end(); - record != end_of_headers; ++record) { - TablePtr target_table = GetTable((*record)->tag()); + for (size_t i = 0; i < table_headers->size(); ++i) { + const HeaderPtr& record = (*table_headers)[i]; + TablePtr target_table = GetTable(record->tag()); if (target_table == NULL) { #if !defined (SFNTLY_NO_EXCEPTION) throw IOException("Table out of sync with font header."); @@ -153,18 +155,17 @@ void Font::SerializeTables(FontOutputStream* fos, return; } int32_t table_size = target_table->Serialize(fos); - if (table_size != (*record)->length()) { - assert(false); - } + assert(table_size == record->length()); + int32_t filler_size = ((table_size + 3) & ~3) - table_size; for (int32_t i = 0; i < filler_size; ++i) { - fos->Write(static_cast<byte_t>(0)); + fos->Write(static_cast<uint8_t>(0)); } } } -void Font::GenerateTableOrdering(IntegerList* default_table_ordering, - IntegerList* table_ordering) { +void Font::GenerateTableOrdering(std::vector<int32_t>* default_table_ordering, + std::vector<int32_t>* table_ordering) { assert(default_table_ordering); assert(table_ordering); table_ordering->clear(); @@ -179,7 +180,7 @@ void Font::GenerateTableOrdering(IntegerList* default_table_ordering, table != table_end; ++table) { tables_in_font.insert(Int2BoolEntry(table->first, false)); } - for (IntegerList::iterator tag = default_table_ordering->begin(), + for (std::vector<int32_t>::iterator tag = default_table_ordering->begin(), tag_end = default_table_ordering->end(); tag != tag_end; ++tag) { if (HasTable(*tag)) { @@ -195,7 +196,7 @@ void Font::GenerateTableOrdering(IntegerList* default_table_ordering, } } -void Font::DefaultTableOrdering(IntegerList* default_table_ordering) { +void Font::DefaultTableOrdering(std::vector<int32_t>* default_table_ordering) { assert(default_table_ordering); default_table_ordering->clear(); if (HasTable(Tag::CFF)) { @@ -268,7 +269,7 @@ CALLER_ATTACH Font* Font::Builder::Build() { return font.Detach(); } -void Font::Builder::SetDigest(ByteVector* digest) { +void Font::Builder::SetDigest(std::vector<uint8_t>* digest) { digest_.clear(); digest_ = *digest; } @@ -440,7 +441,7 @@ void Font::Builder::InterRelateBuilders(TableBuilderMap* builder_map) { loca_table_builder = down_cast<LocaTable::Builder*>(raw_loca_builder); } - Table::Builder* raw_hmtx_builder = GetBuilder(builder_map, Tag::hmtx); + Table::Builder* raw_hmtx_builder = GetReadBuilder(builder_map, Tag::hmtx); HorizontalMetricsTableBuilderPtr horizontal_metrics_builder; if (raw_hmtx_builder != NULL) { horizontal_metrics_builder = @@ -459,18 +460,22 @@ void Font::Builder::InterRelateBuilders(TableBuilderMap* builder_map) { // set the inter table data required to build certain tables if (horizontal_metrics_builder != NULL) { if (max_profile_builder != NULL) { - horizontal_metrics_builder->SetNumGlyphs( - max_profile_builder->NumGlyphs()); + int32_t num_glyphs = max_profile_builder->NumGlyphs(); + if (num_glyphs >= 0) + horizontal_metrics_builder->SetNumGlyphs(num_glyphs); } if (horizontal_header_builder != NULL) { - horizontal_metrics_builder->SetNumberOfHMetrics( - horizontal_header_builder->NumberOfHMetrics()); + int32_t num_hmetrics = horizontal_header_builder->NumberOfHMetrics(); + if (num_hmetrics >= 0) + horizontal_metrics_builder->SetNumberOfHMetrics(num_hmetrics); } } if (loca_table_builder != NULL) { if (max_profile_builder != NULL) { - loca_table_builder->SetNumGlyphs(max_profile_builder->NumGlyphs()); + int32_t num_glyphs = max_profile_builder->NumGlyphs(); + if (num_glyphs >= 0) + loca_table_builder->SetNumGlyphs(num_glyphs); } if (header_table_builder != NULL) { loca_table_builder->set_format_version( @@ -502,6 +507,9 @@ void Font::Builder::ReadHeader(FontInputStream* is, int64_t checksum = is->ReadULong(); int32_t offset = is->ReadULongAsInt(); int32_t length = is->ReadULongAsInt(); + if (!IsValidHeaderRegion(is->Length(), offset, length)) + continue; + HeaderPtr table = new Header(tag, checksum, offset, length); records->insert(table); } @@ -517,6 +525,9 @@ void Font::Builder::ReadHeader(ReadableFontData* fd, entry_selector_ = fd->ReadUShort(offset + Offset::kEntrySelector); range_shift_ = fd->ReadUShort(offset + Offset::kRangeShift); + if (num_tables_ > fd->Size() / Offset::kTableRecordSize) + return; + int32_t table_offset = offset + Offset::kTableRecordBegin; for (int32_t table_number = 0; table_number < num_tables_; @@ -525,6 +536,9 @@ void Font::Builder::ReadHeader(ReadableFontData* fd, int64_t checksum = fd->ReadULong(table_offset + Offset::kTableCheckSum); int32_t offset = fd->ReadULongAsInt(table_offset + Offset::kTableOffset); int32_t length = fd->ReadULongAsInt(table_offset + Offset::kTableLength); + if (!IsValidHeaderRegion(fd->Size(), offset, length)) + continue; + HeaderPtr table = new Header(tag, checksum, offset, length); records->insert(table); } diff --git a/cpp/src/sfntly/font.h b/cpp/src/sfntly/font.h index 2220adb..3187c11 100644 --- a/cpp/src/sfntly/font.h +++ b/cpp/src/sfntly/font.h @@ -149,7 +149,7 @@ class Font : public RefCounted<Font> { CALLER_ATTACH Font* Build(); // Set a unique fingerprint for the font object. - void SetDigest(ByteVector* digest); + void SetDigest(std::vector<uint8_t>* digest); // Clear all table builders. void ClearTableBuilders(); @@ -226,7 +226,7 @@ class Font : public RefCounted<Font> { int32_t entry_selector_; int32_t range_shift_; DataBlockMap data_blocks_; - ByteVector digest_; + std::vector<uint8_t> digest_; }; virtual ~Font(); @@ -236,7 +236,7 @@ class Font : public RefCounted<Font> { // Gets a copy of the fonts digest that was created when the font was read. If // no digest was set at creation time then the return result will be null. - ByteVector* digest() { return &digest_; } + std::vector<uint8_t>* digest() { return &digest_; } // Get the checksum for this font. int64_t checksum() { return checksum_; } @@ -265,7 +265,7 @@ class Font : public RefCounted<Font> { // Serialize the font to the output stream. // @param os the destination for the font serialization // @param tableOrdering the table ordering to apply - void Serialize(OutputStream* os, IntegerList* table_ordering); + void Serialize(OutputStream* os, std::vector<int32_t>* table_ordering); private: // Offsets to specific elements in the underlying data. These offsets are @@ -300,7 +300,7 @@ class Font : public RefCounted<Font> { // @param digest the computed digest for the font; null if digest was not // computed // Note: Current C++ port does not support SHA digest validation. - Font(int32_t sfnt_version, ByteVector* digest); + Font(int32_t sfnt_version, std::vector<uint8_t>* digest); // Build the table headers to be used for serialization. These headers will be // filled out with the data required for serialization. The headers will be @@ -309,7 +309,7 @@ class Font : public RefCounted<Font> { // @param tableOrdering the tables to generate headers for and the order to // sort them // @return a list of table headers ready for serialization - void BuildTableHeadersForSerialization(IntegerList* table_ordering, + void BuildTableHeadersForSerialization(std::vector<int32_t>* table_ordering, TableHeaderList* table_headers); // Searialize the headers. @@ -330,15 +330,15 @@ class Font : public RefCounted<Font> { // @param defaultTableOrdering the partial ordering to be used as a seed for // the full ordering // @param (out) table_ordering the full ordering for serialization - void GenerateTableOrdering(IntegerList* default_table_ordering, - IntegerList* table_ordering); + void GenerateTableOrdering(std::vector<int32_t>* default_table_ordering, + std::vector<int32_t>* table_ordering); // Get the default table ordering based on the type of the font. // @param (out) default_table_ordering the default table ordering - void DefaultTableOrdering(IntegerList* default_table_ordering); + void DefaultTableOrdering(std::vector<int32_t>* default_table_ordering); int32_t sfnt_version_; - ByteVector digest_; + std::vector<uint8_t> digest_; int64_t checksum_; TableMap tables_; }; diff --git a/cpp/src/sfntly/font_factory.cc b/cpp/src/sfntly/font_factory.cc index c162a77..bb1986f 100644 --- a/cpp/src/sfntly/font_factory.cc +++ b/cpp/src/sfntly/font_factory.cc @@ -52,7 +52,7 @@ void FontFactory::LoadFonts(InputStream* is, FontArray* output) { } } -void FontFactory::LoadFonts(ByteVector* b, FontArray* output) { +void FontFactory::LoadFonts(std::vector<uint8_t>* b, FontArray* output) { WritableFontDataPtr wfd; wfd.Attach(WritableFontData::CreateWritableFontData(b)); if (IsCollection(wfd)) { @@ -80,7 +80,7 @@ void FontFactory::LoadFontsForBuilding(InputStream* is, } } -void FontFactory::LoadFontsForBuilding(ByteVector* b, +void FontFactory::LoadFontsForBuilding(std::vector<uint8_t>* b, FontBuilderArray* output) { WritableFontDataPtr wfd; wfd.Attach(WritableFontData::CreateWritableFontData(b)); @@ -96,12 +96,8 @@ void FontFactory::LoadFontsForBuilding(ByteVector* b, } void FontFactory::SerializeFont(Font* font, OutputStream* os) { - font->Serialize(os, &table_ordering_); -} - -void FontFactory::SetSerializationTableOrdering( - const IntegerList& table_ordering) { - table_ordering_ = table_ordering; + std::vector<int32_t> table_ordering; + font->Serialize(os, &table_ordering); } CALLER_ATTACH Font::Builder* FontFactory::NewFontBuilder() { @@ -180,6 +176,10 @@ void FontFactory::LoadCollectionForBuilding(WritableFontData* wfd, int32_t version = wfd->ReadFixed(Offset::kVersion); UNREFERENCED_PARAMETER(version); int32_t num_fonts = wfd->ReadULongAsInt(Offset::kNumFonts); + if (num_fonts < 0) + return; + if (num_fonts > wfd->Length() / 4) + return; builders->reserve(num_fonts); int32_t offset_table_offset = Offset::kOffsetTable; @@ -187,6 +187,9 @@ void FontFactory::LoadCollectionForBuilding(WritableFontData* wfd, font_number < num_fonts; font_number++, offset_table_offset += DataSize::kULONG) { int32_t offset = wfd->ReadULongAsInt(offset_table_offset); + if (offset < 0 || offset >= wfd->Length()) + continue; + FontBuilderPtr builder; builder.Attach(LoadSingleOTFForBuilding(wfd, offset)); builders->push_back(builder); @@ -194,14 +197,14 @@ void FontFactory::LoadCollectionForBuilding(WritableFontData* wfd, } bool FontFactory::IsCollection(PushbackInputStream* pbis) { - ByteVector tag(4); + std::vector<uint8_t> tag(4); pbis->Read(&tag); pbis->Unread(&tag); return Tag::ttcf == GenerateTag(tag[0], tag[1], tag[2], tag[3]); } bool FontFactory::IsCollection(ReadableFontData* rfd) { - ByteVector tag(4); + std::vector<uint8_t> tag(4); rfd->ReadBytes(0, &(tag[0]), 0, tag.size()); return Tag::ttcf == GenerateTag(tag[0], tag[1], tag[2], tag[3]); diff --git a/cpp/src/sfntly/font_factory.h b/cpp/src/sfntly/font_factory.h index 63deff4..12e54a5 100644 --- a/cpp/src/sfntly/font_factory.h +++ b/cpp/src/sfntly/font_factory.h @@ -56,7 +56,7 @@ class FontFactory : public RefCounted<FontFactory> { // than one font and in this case multiple font objects will be returned. If // the data in the stream cannot be parsed or is invalid an array of size zero // will be returned. - void LoadFonts(ByteVector* b, FontArray* output); + void LoadFonts(std::vector<uint8_t>* b, FontArray* output); // Load the font(s) from the input stream into font builders. The current // settings on the factory are used during the loading process. One or more @@ -72,7 +72,7 @@ class FontFactory : public RefCounted<FontFactory> { // font container formats may have more than one font and in this case // multiple font builder objects will be returned. If the data in the stream // cannot be parsed or is invalid an array of size zero will be returned. - void LoadFontsForBuilding(ByteVector* b, FontBuilderArray* output); + void LoadFontsForBuilding(std::vector<uint8_t>* b, FontBuilderArray* output); // Font serialization // Serialize the font to the output stream. @@ -81,12 +81,6 @@ class FontFactory : public RefCounted<FontFactory> { // Byte buffer it is. void SerializeFont(Font* font, OutputStream* os); - // Set the table ordering to be used in serializing a font. The table ordering - // is an ordered list of table ids and tables will be serialized in the order - // given. Any tables whose id is not listed in the ordering will be placed in - // an unspecified order following those listed. - void SetSerializationTableOrdering(const IntegerList& table_ordering); - // Get an empty font builder for creating a new font from scratch. CALLER_ATTACH Font::Builder* NewFontBuilder(); @@ -131,7 +125,6 @@ class FontFactory : public RefCounted<FontFactory> { static bool IsCollection(ReadableFontData* wfd); bool fingerprint_; - IntegerList table_ordering_; }; typedef Ptr<FontFactory> FontFactoryPtr; diff --git a/cpp/src/sfntly/port/file_input_stream.cc b/cpp/src/sfntly/port/file_input_stream.cc index dfe9a7b..12c1e12 100644 --- a/cpp/src/sfntly/port/file_input_stream.cc +++ b/cpp/src/sfntly/port/file_input_stream.cc @@ -35,6 +35,10 @@ FileInputStream::~FileInputStream() { Close(); } +int32_t FileInputStream::Length() { + return length_; +} + int32_t FileInputStream::Available() { return length_ - position_; } @@ -70,17 +74,17 @@ int32_t FileInputStream::Read() { #endif return 0; } - byte_t value; + uint8_t value; size_t length = fread(&value, 1, 1, file_); position_ += length; return value; } -int32_t FileInputStream::Read(ByteVector* b) { +int32_t FileInputStream::Read(std::vector<uint8_t>* b) { return Read(b, 0, b->size()); } -int32_t FileInputStream::Read(ByteVector* b, int32_t offset, int32_t length) { +int32_t FileInputStream::Read(std::vector<uint8_t>* b, int32_t offset, int32_t length) { assert(b); if (!file_) { #if !defined (SFNTLY_NO_EXCEPTION) @@ -127,11 +131,11 @@ int64_t FileInputStream::Skip(int64_t n) { return skip_count; } -void FileInputStream::Unread(ByteVector* b) { +void FileInputStream::Unread(std::vector<uint8_t>* b) { Unread(b, 0, b->size()); } -void FileInputStream::Unread(ByteVector* b, int32_t offset, int32_t length) { +void FileInputStream::Unread(std::vector<uint8_t>* b, int32_t offset, int32_t length) { assert(b); assert(b->size() >= size_t(offset + length)); if (!file_) { diff --git a/cpp/src/sfntly/port/file_input_stream.h b/cpp/src/sfntly/port/file_input_stream.h index cbca25f..1128444 100644 --- a/cpp/src/sfntly/port/file_input_stream.h +++ b/cpp/src/sfntly/port/file_input_stream.h @@ -29,19 +29,20 @@ class FileInputStream : public PushbackInputStream { virtual ~FileInputStream(); // InputStream methods + virtual int32_t Length(); virtual int32_t Available(); virtual void Close(); virtual void Mark(int32_t readlimit); virtual bool MarkSupported(); virtual int32_t Read(); - virtual int32_t Read(ByteVector* b); - virtual int32_t Read(ByteVector* b, int32_t offset, int32_t length); + virtual int32_t Read(std::vector<uint8_t>* b); + virtual int32_t Read(std::vector<uint8_t>* b, int32_t offset, int32_t length); virtual void Reset(); virtual int64_t Skip(int64_t n); // PushbackInputStream methods - virtual void Unread(ByteVector* b); - virtual void Unread(ByteVector* b, int32_t offset, int32_t length); + virtual void Unread(std::vector<uint8_t>* b); + virtual void Unread(std::vector<uint8_t>* b, int32_t offset, int32_t length); // Own methods virtual bool Open(const char* file_path); diff --git a/cpp/src/sfntly/port/input_stream.h b/cpp/src/sfntly/port/input_stream.h index 5d24036..a403c11 100644 --- a/cpp/src/sfntly/port/input_stream.h +++ b/cpp/src/sfntly/port/input_stream.h @@ -24,24 +24,25 @@ namespace sfntly { // C++ equivalent to Java's OutputStream class class InputStream { public: - // Make gcc -Wnon-virtual-dtor happy. - virtual ~InputStream() {} - + virtual int32_t Length() = 0; virtual int32_t Available() = 0; virtual void Close() = 0; virtual void Mark(int32_t readlimit) = 0; virtual bool MarkSupported() = 0; virtual int32_t Read() = 0; - virtual int32_t Read(ByteVector* b) = 0; - virtual int32_t Read(ByteVector* b, int32_t offset, int32_t length) = 0; + virtual int32_t Read(std::vector<uint8_t>* b) = 0; + virtual int32_t Read(std::vector<uint8_t>* b, int32_t offset, int32_t length) = 0; virtual void Reset() = 0; virtual int64_t Skip(int64_t n) = 0; + + protected: + virtual ~InputStream() {} }; class PushbackInputStream : public InputStream { public: - virtual void Unread(ByteVector* b) = 0; - virtual void Unread(ByteVector* b, int32_t offset, int32_t length) = 0; + virtual void Unread(std::vector<uint8_t>* b) = 0; + virtual void Unread(std::vector<uint8_t>* b, int32_t offset, int32_t length) = 0; }; } // namespace sfntly diff --git a/cpp/src/sfntly/port/memory_input_stream.cc b/cpp/src/sfntly/port/memory_input_stream.cc index f6f2b9b..73f03f5 100755 --- a/cpp/src/sfntly/port/memory_input_stream.cc +++ b/cpp/src/sfntly/port/memory_input_stream.cc @@ -37,6 +37,10 @@ MemoryInputStream::~MemoryInputStream() { Close(); } +int32_t MemoryInputStream::Length() { + return length_; +} + int32_t MemoryInputStream::Available() { return length_ - position_; } @@ -66,15 +70,15 @@ int32_t MemoryInputStream::Read() { #endif return 0; } - byte_t value = buffer_[position_++]; + uint8_t value = buffer_[position_++]; return value; } -int32_t MemoryInputStream::Read(ByteVector* b) { +int32_t MemoryInputStream::Read(std::vector<uint8_t>* b) { return Read(b, 0, b->size()); } -int32_t MemoryInputStream::Read(ByteVector* b, int32_t offset, int32_t length) { +int32_t MemoryInputStream::Read(std::vector<uint8_t>* b, int32_t offset, int32_t length) { assert(b); if (!buffer_) { #if !defined (SFNTLY_NO_EXCEPTION) @@ -119,11 +123,11 @@ int64_t MemoryInputStream::Skip(int64_t n) { return skip_count; } -void MemoryInputStream::Unread(ByteVector* b) { +void MemoryInputStream::Unread(std::vector<uint8_t>* b) { Unread(b, 0, b->size()); } -void MemoryInputStream::Unread(ByteVector* b, int32_t offset, int32_t length) { +void MemoryInputStream::Unread(std::vector<uint8_t>* b, int32_t offset, int32_t length) { assert(b); assert(b->size() >= size_t(offset + length)); if (!buffer_) { @@ -138,7 +142,7 @@ void MemoryInputStream::Unread(ByteVector* b, int32_t offset, int32_t length) { position_ -= unread_count; } -bool MemoryInputStream::Attach(const byte_t* buffer, size_t length) { +bool MemoryInputStream::Attach(const uint8_t* buffer, size_t length) { assert(buffer); assert(length); buffer_ = buffer; diff --git a/cpp/src/sfntly/port/memory_input_stream.h b/cpp/src/sfntly/port/memory_input_stream.h index bc861c3..2478893 100755 --- a/cpp/src/sfntly/port/memory_input_stream.h +++ b/cpp/src/sfntly/port/memory_input_stream.h @@ -29,25 +29,26 @@ class MemoryInputStream : public PushbackInputStream { virtual ~MemoryInputStream(); // InputStream methods + virtual int32_t Length(); virtual int32_t Available(); virtual void Close(); virtual void Mark(int32_t readlimit); virtual bool MarkSupported(); virtual int32_t Read(); - virtual int32_t Read(ByteVector* b); - virtual int32_t Read(ByteVector* b, int32_t offset, int32_t length); + virtual int32_t Read(std::vector<uint8_t>* b); + virtual int32_t Read(std::vector<uint8_t>* b, int32_t offset, int32_t length); virtual void Reset(); virtual int64_t Skip(int64_t n); // PushbackInputStream methods - virtual void Unread(ByteVector* b); - virtual void Unread(ByteVector* b, int32_t offset, int32_t length); + virtual void Unread(std::vector<uint8_t>* b); + virtual void Unread(std::vector<uint8_t>* b, int32_t offset, int32_t length); // Own methods - virtual bool Attach(const byte_t* buffer, size_t length); + virtual bool Attach(const uint8_t* buffer, size_t length); private: - const byte_t* buffer_; + const uint8_t* buffer_; size_t position_; size_t length_; }; diff --git a/cpp/src/sfntly/port/memory_output_stream.cc b/cpp/src/sfntly/port/memory_output_stream.cc index f2ff2e3..f071c97 100644 --- a/cpp/src/sfntly/port/memory_output_stream.cc +++ b/cpp/src/sfntly/port/memory_output_stream.cc @@ -24,11 +24,11 @@ MemoryOutputStream::MemoryOutputStream() { MemoryOutputStream::~MemoryOutputStream() { } -void MemoryOutputStream::Write(ByteVector* buffer) { +void MemoryOutputStream::Write(std::vector<uint8_t>* buffer) { store_.insert(store_.end(), buffer->begin(), buffer->end()); } -void MemoryOutputStream::Write(ByteVector* buffer, +void MemoryOutputStream::Write(std::vector<uint8_t>* buffer, int32_t offset, int32_t length) { assert(buffer); @@ -43,7 +43,7 @@ void MemoryOutputStream::Write(ByteVector* buffer, } } -void MemoryOutputStream::Write(byte_t* buffer, int32_t offset, int32_t length) { +void MemoryOutputStream::Write(uint8_t* buffer, int32_t offset, int32_t length) { assert(buffer); if (offset >= 0 && length > 0) { store_.insert(store_.end(), buffer + offset, buffer + offset + length); @@ -54,11 +54,11 @@ void MemoryOutputStream::Write(byte_t* buffer, int32_t offset, int32_t length) { } } -void MemoryOutputStream::Write(byte_t b) { +void MemoryOutputStream::Write(uint8_t b) { store_.push_back(b); } -byte_t* MemoryOutputStream::Get() { +uint8_t* MemoryOutputStream::Get() { if (store_.empty()) { return NULL; } diff --git a/cpp/src/sfntly/port/memory_output_stream.h b/cpp/src/sfntly/port/memory_output_stream.h index d1eda7f..586c9d9 100644 --- a/cpp/src/sfntly/port/memory_output_stream.h +++ b/cpp/src/sfntly/port/memory_output_stream.h @@ -34,16 +34,16 @@ class MemoryOutputStream : public OutputStream { virtual void Close() {} // no-op virtual void Flush() {} // no-op - virtual void Write(ByteVector* buffer); - virtual void Write(ByteVector* buffer, int32_t offset, int32_t length); - virtual void Write(byte_t* buffer, int32_t offset, int32_t length); - virtual void Write(byte_t b); + virtual void Write(std::vector<uint8_t>* buffer); + virtual void Write(std::vector<uint8_t>* buffer, int32_t offset, int32_t length); + virtual void Write(uint8_t* buffer, int32_t offset, int32_t length); + virtual void Write(uint8_t b); - byte_t* Get(); + uint8_t* Get(); size_t Size(); private: - std::vector<byte_t> store_; + std::vector<uint8_t> store_; }; } // namespace sfntly diff --git a/cpp/src/sfntly/port/output_stream.h b/cpp/src/sfntly/port/output_stream.h index 64a6024..8dd2e5c 100644 --- a/cpp/src/sfntly/port/output_stream.h +++ b/cpp/src/sfntly/port/output_stream.h @@ -29,16 +29,16 @@ class OutputStream { virtual void Close() = 0; virtual void Flush() = 0; - virtual void Write(ByteVector* buffer) = 0; - virtual void Write(byte_t b) = 0; + virtual void Write(std::vector<uint8_t>* buffer) = 0; + virtual void Write(uint8_t b) = 0; // Note: C++ port offered both versions of Write() here. The first one is // better because it does check bounds. The second one is there for // performance concerns. - virtual void Write(ByteVector* buffer, int32_t offset, int32_t length) = 0; + virtual void Write(std::vector<uint8_t>* buffer, int32_t offset, int32_t length) = 0; // Note: Caller is responsible for the boundary of buffer. - virtual void Write(byte_t* buffer, int32_t offset, int32_t length) = 0; + virtual void Write(uint8_t* buffer, int32_t offset, int32_t length) = 0; }; } // namespace sfntly diff --git a/cpp/src/sfntly/port/refcount.h b/cpp/src/sfntly/port/refcount.h index 6353b08..d083c73 100644 --- a/cpp/src/sfntly/port/refcount.h +++ b/cpp/src/sfntly/port/refcount.h @@ -97,6 +97,8 @@ #pragma warning(disable:4250) #endif +bool TestSmartPointer(); + namespace sfntly { template <typename T> @@ -157,6 +159,7 @@ class RefCounted : virtual public RefCount { } mutable size_t ref_count_; // reference count of current object + friend bool ::TestSmartPointer(); #if defined (ENABLE_OBJECT_COUNTER) static size_t object_counter_; static size_t next_id_; diff --git a/cpp/src/sfntly/port/type.h b/cpp/src/sfntly/port/type.h index 9f82a5a..cb8c1ea 100644 --- a/cpp/src/sfntly/port/type.h +++ b/cpp/src/sfntly/port/type.h @@ -17,42 +17,21 @@ #ifndef SFNTLY_CPP_SRC_SFNTLY_PORT_TYPE_H_ #define SFNTLY_CPP_SRC_SFNTLY_PORT_TYPE_H_ -#include <assert.h> +#include <stdint.h> -#if defined (_MSC_VER) && (_MSC_VER < 1600) - typedef unsigned char uint8_t; - typedef signed char int8_t; - typedef unsigned __int16 uint16_t; - typedef signed __int16 int16_t; - typedef unsigned __int32 uint32_t; - typedef signed __int32 int32_t; - typedef unsigned __int64 uint64_t; - typedef signed __int64 int64_t; - // Definitions to avoid ICU redefinition issue - #define U_HAVE_INT8_T 1 - #define U_HAVE_UINT8_T 1 - #define U_HAVE_INT16_T 1 - #define U_HAVE_UINT16_T 1 - #define U_HAVE_INT32_T 1 - #define U_HAVE_UINT32_T 1 - #define U_HAVE_INT64_T 1 - #define U_HAVE_UINT64_T 1 -#else - #include <stdint.h> -#endif - -#include <stddef.h> -#include <vector> +#include <cassert> +#include <cstddef> #include <set> +#include <vector> namespace sfntly { +// deprecated typedef uint8_t byte_t; typedef uint16_t word_t; typedef uint32_t dword_t; typedef uint64_t qword_t; - -typedef std::vector<byte_t> ByteVector; +typedef std::vector<uint8_t> ByteVector; typedef std::vector<int32_t> IntegerList; typedef std::set<int32_t> IntegerSet; diff --git a/cpp/src/sfntly/table/bitmap/big_glyph_metrics.cc b/cpp/src/sfntly/table/bitmap/big_glyph_metrics.cc index d853212..041366f 100644 --- a/cpp/src/sfntly/table/bitmap/big_glyph_metrics.cc +++ b/cpp/src/sfntly/table/bitmap/big_glyph_metrics.cc @@ -77,7 +77,7 @@ int32_t BigGlyphMetrics::Builder::Height() { return InternalReadData()->ReadByte(Offset::kHeight); } -void BigGlyphMetrics::Builder::SetHeight(byte_t height) { +void BigGlyphMetrics::Builder::SetHeight(uint8_t height) { InternalWriteData()->WriteByte(Offset::kHeight, height); } @@ -85,7 +85,7 @@ int32_t BigGlyphMetrics::Builder::Width() { return InternalReadData()->ReadByte(Offset::kWidth); } -void BigGlyphMetrics::Builder::SetWidth(byte_t width) { +void BigGlyphMetrics::Builder::SetWidth(uint8_t width) { InternalWriteData()->WriteByte(Offset::kWidth, width); } @@ -93,7 +93,7 @@ int32_t BigGlyphMetrics::Builder::HoriBearingX() { return InternalReadData()->ReadByte(Offset::kHoriBearingX); } -void BigGlyphMetrics::Builder::SetHoriBearingX(byte_t bearing) { +void BigGlyphMetrics::Builder::SetHoriBearingX(uint8_t bearing) { InternalWriteData()->WriteByte(Offset::kHoriBearingX, bearing); } @@ -101,7 +101,7 @@ int32_t BigGlyphMetrics::Builder::HoriBearingY() { return InternalReadData()->ReadByte(Offset::kHoriBearingY); } -void BigGlyphMetrics::Builder::SetHoriBearingY(byte_t bearing) { +void BigGlyphMetrics::Builder::SetHoriBearingY(uint8_t bearing) { InternalWriteData()->WriteByte(Offset::kHoriBearingY, bearing); } @@ -109,7 +109,7 @@ int32_t BigGlyphMetrics::Builder::HoriAdvance() { return InternalReadData()->ReadByte(Offset::kHoriAdvance); } -void BigGlyphMetrics::Builder::SetHoriAdvance(byte_t advance) { +void BigGlyphMetrics::Builder::SetHoriAdvance(uint8_t advance) { InternalWriteData()->WriteByte(Offset::kHoriAdvance, advance); } @@ -117,7 +117,7 @@ int32_t BigGlyphMetrics::Builder::VertBearingX() { return InternalReadData()->ReadByte(Offset::kVertBearingX); } -void BigGlyphMetrics::Builder::SetVertBearingX(byte_t bearing) { +void BigGlyphMetrics::Builder::SetVertBearingX(uint8_t bearing) { InternalWriteData()->WriteByte(Offset::kVertBearingX, bearing); } @@ -125,7 +125,7 @@ int32_t BigGlyphMetrics::Builder::VertBearingY() { return InternalReadData()->ReadByte(Offset::kVertBearingY); } -void BigGlyphMetrics::Builder::SetVertBearingY(byte_t bearing) { +void BigGlyphMetrics::Builder::SetVertBearingY(uint8_t bearing) { InternalWriteData()->WriteByte(Offset::kVertBearingY, bearing); } @@ -133,7 +133,7 @@ int32_t BigGlyphMetrics::Builder::VertAdvance() { return InternalReadData()->ReadByte(Offset::kVertAdvance); } -void BigGlyphMetrics::Builder::SetVertAdvance(byte_t advance) { +void BigGlyphMetrics::Builder::SetVertAdvance(uint8_t advance) { InternalWriteData()->WriteByte(Offset::kVertAdvance, advance); } diff --git a/cpp/src/sfntly/table/bitmap/big_glyph_metrics.h b/cpp/src/sfntly/table/bitmap/big_glyph_metrics.h index a91601c..84783c2 100644 --- a/cpp/src/sfntly/table/bitmap/big_glyph_metrics.h +++ b/cpp/src/sfntly/table/bitmap/big_glyph_metrics.h @@ -50,21 +50,21 @@ class BigGlyphMetrics : public GlyphMetrics, virtual ~Builder(); int32_t Height(); - void SetHeight(byte_t height); + void SetHeight(uint8_t height); int32_t Width(); - void SetWidth(byte_t width); + void SetWidth(uint8_t width); int32_t HoriBearingX(); - void SetHoriBearingX(byte_t bearing); + void SetHoriBearingX(uint8_t bearing); int32_t HoriBearingY(); - void SetHoriBearingY(byte_t bearing); + void SetHoriBearingY(uint8_t bearing); int32_t HoriAdvance(); - void SetHoriAdvance(byte_t advance); + void SetHoriAdvance(uint8_t advance); int32_t VertBearingX(); - void SetVertBearingX(byte_t bearing); + void SetVertBearingX(uint8_t bearing); int32_t VertBearingY(); - void SetVertBearingY(byte_t bearing); + void SetVertBearingY(uint8_t bearing); int32_t VertAdvance(); - void SetVertAdvance(byte_t advance); + void SetVertAdvance(uint8_t advance); virtual CALLER_ATTACH FontDataTable* SubBuildTable(ReadableFontData* data); virtual void SubDataSet(); diff --git a/cpp/src/sfntly/table/bitmap/eblc_table.cc b/cpp/src/sfntly/table/bitmap/eblc_table.cc index 0ad2764..d0700d9 100644 --- a/cpp/src/sfntly/table/bitmap/eblc_table.cc +++ b/cpp/src/sfntly/table/bitmap/eblc_table.cc @@ -294,19 +294,23 @@ BitmapSizeTableBuilderList* EblcTable::Builder::GetSizeList() { void EblcTable::Builder::Initialize(ReadableFontData* data, BitmapSizeTableBuilderList* output) { assert(output); - if (data) { - int32_t num_sizes = data->ReadULongAsInt(Offset::kNumSizes); - for (int32_t i = 0; i < num_sizes; ++i) { - ReadableFontDataPtr new_data; - new_data.Attach(down_cast<ReadableFontData*>( - data->Slice(Offset::kBitmapSizeTableArrayStart + - i * Offset::kBitmapSizeTableLength, - Offset::kBitmapSizeTableLength))); - BitmapSizeTableBuilderPtr size_builder; - size_builder.Attach(BitmapSizeTable::Builder::CreateBuilder( - new_data, data)); - output->push_back(size_builder); - } + if (!data) + return; + + int32_t num_sizes = data->ReadULongAsInt(Offset::kNumSizes); + if (num_sizes > data->Size() / Offset::kBitmapSizeTableLength) + return; + + for (int32_t i = 0; i < num_sizes; ++i) { + ReadableFontDataPtr new_data; + new_data.Attach(down_cast<ReadableFontData*>( + data->Slice(Offset::kBitmapSizeTableArrayStart + + i * Offset::kBitmapSizeTableLength, + Offset::kBitmapSizeTableLength))); + BitmapSizeTableBuilderPtr size_builder; + size_builder.Attach(BitmapSizeTable::Builder::CreateBuilder( + new_data, data)); + output->push_back(size_builder); } } diff --git a/cpp/src/sfntly/table/bitmap/index_sub_table_format1.cc b/cpp/src/sfntly/table/bitmap/index_sub_table_format1.cc index 5199e18..42d21ab 100644 --- a/cpp/src/sfntly/table/bitmap/index_sub_table_format1.cc +++ b/cpp/src/sfntly/table/bitmap/index_sub_table_format1.cc @@ -82,7 +82,7 @@ int32_t IndexSubTableFormat1::Builder::GlyphLength(int32_t glyph_id) { if (loca == -1) { return 0; } - IntegerList* offset_array = GetOffsetArray(); + std::vector<int32_t>* offset_array = GetOffsetArray(); return offset_array->at(loca + 1) - offset_array->at(loca); } @@ -193,7 +193,7 @@ int32_t IndexSubTableFormat1::Builder::SubSerialize( EblcTable::Offset::kIndexSubTable1_offsetArray))); size += source->CopyTo(target); } else { - for (IntegerList::iterator b = GetOffsetArray()->begin(), + for (std::vector<int32_t>::iterator b = GetOffsetArray()->begin(), e = GetOffsetArray()->end(); b != e; b++) { size += new_data->WriteLong(size, *b); } @@ -201,12 +201,12 @@ int32_t IndexSubTableFormat1::Builder::SubSerialize( return size; } -IntegerList* IndexSubTableFormat1::Builder::OffsetArray() { +std::vector<int32_t>* IndexSubTableFormat1::Builder::OffsetArray() { return GetOffsetArray(); } void IndexSubTableFormat1::Builder::SetOffsetArray( - const IntegerList& offset_array) { + const std::vector<int32_t>& offset_array) { offset_array_.clear(); offset_array_ = offset_array; set_model_changed(); @@ -234,7 +234,7 @@ IndexSubTableFormat1::Builder::Builder(ReadableFontData* data, : IndexSubTable::Builder(data, first_glyph_index, last_glyph_index) { } -IntegerList* IndexSubTableFormat1::Builder::GetOffsetArray() { +std::vector<int32_t>* IndexSubTableFormat1::Builder::GetOffsetArray() { if (offset_array_.empty()) { Initialize(InternalReadData()); set_model_changed(); diff --git a/cpp/src/sfntly/table/bitmap/index_sub_table_format1.h b/cpp/src/sfntly/table/bitmap/index_sub_table_format1.h index 33171c1..58a6ce7 100644 --- a/cpp/src/sfntly/table/bitmap/index_sub_table_format1.h +++ b/cpp/src/sfntly/table/bitmap/index_sub_table_format1.h @@ -53,8 +53,8 @@ class IndexSubTableFormat1 : public IndexSubTable, virtual bool SubReadyToSerialize(); virtual int32_t SubSerialize(WritableFontData* new_data); - IntegerList* OffsetArray(); - void SetOffsetArray(const IntegerList& offset_array); + std::vector<int32_t>* OffsetArray(); + void SetOffsetArray(const std::vector<int32_t>& offset_array); CALLER_ATTACH BitmapGlyphInfoIter* Iterator(); static CALLER_ATTACH Builder* CreateBuilder(); @@ -78,7 +78,7 @@ class IndexSubTableFormat1 : public IndexSubTable, Builder(ReadableFontData* data, int32_t first_glyph_index, int32_t last_glyph_index); - IntegerList* GetOffsetArray(); + std::vector<int32_t>* GetOffsetArray(); void Initialize(ReadableFontData* data); static int32_t DataLength(ReadableFontData* data, @@ -86,7 +86,7 @@ class IndexSubTableFormat1 : public IndexSubTable, int32_t first_glyph_index, int32_t last_glyph_index); - IntegerList offset_array_; + std::vector<int32_t> offset_array_; }; virtual ~IndexSubTableFormat1(); diff --git a/cpp/src/sfntly/table/bitmap/index_sub_table_format3.cc b/cpp/src/sfntly/table/bitmap/index_sub_table_format3.cc index e2679b7..abd5517 100644 --- a/cpp/src/sfntly/table/bitmap/index_sub_table_format3.cc +++ b/cpp/src/sfntly/table/bitmap/index_sub_table_format3.cc @@ -91,7 +91,7 @@ int32_t IndexSubTableFormat3::Builder::GlyphLength(int32_t glyph_id) { if (loca == -1) { return 0; } - IntegerList* offset_array = GetOffsetArray(); + std::vector<int32_t>* offset_array = GetOffsetArray(); return offset_array->at(loca + 1) - offset_array->at(loca); } @@ -108,7 +108,7 @@ void IndexSubTableFormat3::Builder::Revert() { } void IndexSubTableFormat3::Builder::SetOffsetArray( - const IntegerList& offset_array) { + const std::vector<int32_t>& offset_array) { offset_array_.clear(); offset_array_ = offset_array; set_model_changed(); @@ -205,7 +205,7 @@ int32_t IndexSubTableFormat3::Builder::SubSerialize( EblcTable::Offset::kIndexSubTable3_offsetArray))); size += source->CopyTo(target); } else { - for (IntegerList::iterator b = GetOffsetArray()->begin(), + for (std::vector<int32_t>::iterator b = GetOffsetArray()->begin(), e = GetOffsetArray()->end(); b != e; b++) { size += new_data->WriteUShort(size, *b); } @@ -230,7 +230,7 @@ IndexSubTableFormat3::Builder::Builder(ReadableFontData* data, : IndexSubTable::Builder(data, first_glyph_index, last_glyph_index) { } -IntegerList* IndexSubTableFormat3::Builder::GetOffsetArray() { +std::vector<int32_t>* IndexSubTableFormat3::Builder::GetOffsetArray() { if (offset_array_.empty()) { Initialize(InternalReadData()); set_model_changed(); diff --git a/cpp/src/sfntly/table/bitmap/index_sub_table_format3.h b/cpp/src/sfntly/table/bitmap/index_sub_table_format3.h index d71f857..1f2f0aa 100644 --- a/cpp/src/sfntly/table/bitmap/index_sub_table_format3.h +++ b/cpp/src/sfntly/table/bitmap/index_sub_table_format3.h @@ -52,7 +52,7 @@ class IndexSubTableFormat3 : public IndexSubTable, virtual bool SubReadyToSerialize(); virtual int32_t SubSerialize(WritableFontData* new_data); - void SetOffsetArray(const IntegerList& offset_array); + void SetOffsetArray(const std::vector<int32_t>& offset_array); static CALLER_ATTACH Builder* CreateBuilder(); static CALLER_ATTACH Builder* CreateBuilder(ReadableFontData* data, @@ -75,7 +75,7 @@ class IndexSubTableFormat3 : public IndexSubTable, Builder(ReadableFontData* data, int32_t first_glyph_index, int32_t last_glyph_index); - IntegerList* GetOffsetArray(); + std::vector<int32_t>* GetOffsetArray(); void Initialize(ReadableFontData* data); static int32_t DataLength(ReadableFontData* data, @@ -83,7 +83,7 @@ class IndexSubTableFormat3 : public IndexSubTable, int32_t first_glyph_index, int32_t last_glyph_index); - IntegerList offset_array_; + std::vector<int32_t> offset_array_; }; virtual ~IndexSubTableFormat3(); diff --git a/cpp/src/sfntly/table/bitmap/index_sub_table_format5.cc b/cpp/src/sfntly/table/bitmap/index_sub_table_format5.cc index 0ca21fe..b1f773a 100644 --- a/cpp/src/sfntly/table/bitmap/index_sub_table_format5.cc +++ b/cpp/src/sfntly/table/bitmap/index_sub_table_format5.cc @@ -104,8 +104,8 @@ int32_t IndexSubTableFormat5::Builder::GlyphStartOffset(int32_t glyph_id) { if (check == -1) { return -1; } - IntegerList* glyph_array = GetGlyphArray(); - IntegerList::iterator it = std::find(glyph_array->begin(), + std::vector<int32_t>* glyph_array = GetGlyphArray(); + std::vector<int32_t>::iterator it = std::find(glyph_array->begin(), glyph_array->end(), glyph_id); if (it == glyph_array->end()) { @@ -215,7 +215,7 @@ int32_t IndexSubTableFormat5::Builder::SubSerialize( slice.Attach(down_cast<WritableFontData*>(new_data->Slice(size))); size += BigMetrics()->SubSerialize(slice); size += new_data->WriteULong(size, glyph_array_.size()); - for (IntegerList::iterator b = glyph_array_.begin(), e = glyph_array_.end(); + for (std::vector<int32_t>::iterator b = glyph_array_.begin(), e = glyph_array_.end(); b != e; b++) { size += new_data->WriteUShort(size, *b); } @@ -245,11 +245,11 @@ BigGlyphMetrics::Builder* IndexSubTableFormat5::Builder::BigMetrics() { return metrics_; } -IntegerList* IndexSubTableFormat5::Builder::GlyphArray() { +std::vector<int32_t>* IndexSubTableFormat5::Builder::GlyphArray() { return GetGlyphArray(); } -void IndexSubTableFormat5::Builder::SetGlyphArray(const IntegerList& v) { +void IndexSubTableFormat5::Builder::SetGlyphArray(const std::vector<int32_t>& v) { glyph_array_.clear(); glyph_array_ = v; set_model_changed(); @@ -277,7 +277,7 @@ IndexSubTableFormat5::Builder::Builder(ReadableFontData* data, : IndexSubTable::Builder(data, first_glyph_index, last_glyph_index) { } -IntegerList* IndexSubTableFormat5::Builder::GetGlyphArray() { +std::vector<int32_t>* IndexSubTableFormat5::Builder::GetGlyphArray() { if (glyph_array_.empty()) { Initialize(InternalReadData()); set_model_changed(); diff --git a/cpp/src/sfntly/table/bitmap/index_sub_table_format5.h b/cpp/src/sfntly/table/bitmap/index_sub_table_format5.h index a39e88c..b6534e7 100644 --- a/cpp/src/sfntly/table/bitmap/index_sub_table_format5.h +++ b/cpp/src/sfntly/table/bitmap/index_sub_table_format5.h @@ -55,8 +55,8 @@ class IndexSubTableFormat5 : public IndexSubTable, int32_t ImageSize(); void SetImageSize(int32_t image_size); BigGlyphMetrics::Builder* BigMetrics(); - IntegerList* GlyphArray(); - void SetGlyphArray(const IntegerList& v); + std::vector<int32_t>* GlyphArray(); + void SetGlyphArray(const std::vector<int32_t>& v); static CALLER_ATTACH Builder* CreateBuilder(); static CALLER_ATTACH Builder* CreateBuilder(ReadableFontData* data, @@ -79,7 +79,7 @@ class IndexSubTableFormat5 : public IndexSubTable, int32_t first_glyph_index, int32_t last_glyph_index); - IntegerList* GetGlyphArray(); + std::vector<int32_t>* GetGlyphArray(); void Initialize(ReadableFontData* data); static int32_t DataLength(ReadableFontData* data, @@ -87,7 +87,7 @@ class IndexSubTableFormat5 : public IndexSubTable, int32_t first_glyph_index, int32_t last_glyph_index); - IntegerList glyph_array_; + std::vector<int32_t> glyph_array_; BigGlyphMetricsBuilderPtr metrics_; }; virtual ~IndexSubTableFormat5(); diff --git a/cpp/src/sfntly/table/bitmap/small_glyph_metrics.cc b/cpp/src/sfntly/table/bitmap/small_glyph_metrics.cc index 0f3c1e9..24ff624 100644 --- a/cpp/src/sfntly/table/bitmap/small_glyph_metrics.cc +++ b/cpp/src/sfntly/table/bitmap/small_glyph_metrics.cc @@ -65,7 +65,7 @@ int32_t SmallGlyphMetrics::Builder::Height() { return InternalReadData()->ReadByte(Offset::kHeight); } -void SmallGlyphMetrics::Builder::SetHeight(byte_t height) { +void SmallGlyphMetrics::Builder::SetHeight(uint8_t height) { InternalWriteData()->WriteByte(Offset::kHeight, height); } @@ -73,7 +73,7 @@ int32_t SmallGlyphMetrics::Builder::Width() { return InternalReadData()->ReadByte(Offset::kWidth); } -void SmallGlyphMetrics::Builder::SetWidth(byte_t width) { +void SmallGlyphMetrics::Builder::SetWidth(uint8_t width) { InternalWriteData()->WriteByte(Offset::kWidth, width); } @@ -81,7 +81,7 @@ int32_t SmallGlyphMetrics::Builder::BearingX() { return InternalReadData()->ReadByte(Offset::kBearingX); } -void SmallGlyphMetrics::Builder::SetBearingX(byte_t bearing) { +void SmallGlyphMetrics::Builder::SetBearingX(uint8_t bearing) { InternalWriteData()->WriteByte(Offset::kBearingX, bearing); } @@ -89,7 +89,7 @@ int32_t SmallGlyphMetrics::Builder::BearingY() { return InternalReadData()->ReadByte(Offset::kBearingY); } -void SmallGlyphMetrics::Builder::SetBearingY(byte_t bearing) { +void SmallGlyphMetrics::Builder::SetBearingY(uint8_t bearing) { InternalWriteData()->WriteByte(Offset::kBearingY, bearing); } @@ -97,7 +97,7 @@ int32_t SmallGlyphMetrics::Builder::Advance() { return InternalReadData()->ReadByte(Offset::kAdvance); } -void SmallGlyphMetrics::Builder::SetAdvance(byte_t advance) { +void SmallGlyphMetrics::Builder::SetAdvance(uint8_t advance) { InternalWriteData()->WriteByte(Offset::kAdvance, advance); } diff --git a/cpp/src/sfntly/table/bitmap/small_glyph_metrics.h b/cpp/src/sfntly/table/bitmap/small_glyph_metrics.h index ea13720..57cc06e 100644 --- a/cpp/src/sfntly/table/bitmap/small_glyph_metrics.h +++ b/cpp/src/sfntly/table/bitmap/small_glyph_metrics.h @@ -46,15 +46,15 @@ class SmallGlyphMetrics : public GlyphMetrics, virtual ~Builder(); int32_t Height(); - void SetHeight(byte_t height); + void SetHeight(uint8_t height); int32_t Width(); - void SetWidth(byte_t width); + void SetWidth(uint8_t width); int32_t BearingX(); - void SetBearingX(byte_t bearing); + void SetBearingX(uint8_t bearing); int32_t BearingY(); - void SetBearingY(byte_t bearing); + void SetBearingY(uint8_t bearing); int32_t Advance(); - void SetAdvance(byte_t advance); + void SetAdvance(uint8_t advance); virtual CALLER_ATTACH FontDataTable* SubBuildTable(ReadableFontData* data); virtual void SubDataSet(); diff --git a/cpp/src/sfntly/table/byte_array_table_builder.cc b/cpp/src/sfntly/table/byte_array_table_builder.cc index 631a05f..2fc982f 100644 --- a/cpp/src/sfntly/table/byte_array_table_builder.cc +++ b/cpp/src/sfntly/table/byte_array_table_builder.cc @@ -31,7 +31,7 @@ int32_t ByteArrayTableBuilder::ByteValue(int32_t index) { return data->ReadByte(index); } -void ByteArrayTableBuilder::SetByteValue(int32_t index, byte_t b) { +void ByteArrayTableBuilder::SetByteValue(int32_t index, uint8_t b) { WritableFontDataPtr data = InternalWriteData(); if (data == NULL) { #if !defined (SFNTLY_NO_EXCEPTION) diff --git a/cpp/src/sfntly/table/byte_array_table_builder.h b/cpp/src/sfntly/table/byte_array_table_builder.h index 42d27a8..a3df0f8 100644 --- a/cpp/src/sfntly/table/byte_array_table_builder.h +++ b/cpp/src/sfntly/table/byte_array_table_builder.h @@ -36,7 +36,7 @@ class ByteArrayTableBuilder : public TableBasedTableBuilder { // start of the table. // @param index index relative to the start of the table // @param b byte value to set - virtual void SetByteValue(int32_t index, byte_t b); + virtual void SetByteValue(int32_t index, uint8_t b); // Get the number of bytes set for this table. It may include padding bytes at // the end. diff --git a/cpp/src/sfntly/table/core/cmap_table.cc b/cpp/src/sfntly/table/core/cmap_table.cc index 1c83d2e..1f1668e 100644 --- a/cpp/src/sfntly/table/core/cmap_table.cc +++ b/cpp/src/sfntly/table/core/cmap_table.cc @@ -469,8 +469,8 @@ int32_t CMapTable::CMapFormat2::GlyphId(int32_t character) { } uint32_t c = ToBE32(character); - byte_t high_byte = (c >> 8) & 0xff; - byte_t low_byte = c & 0xff; + uint8_t high_byte = (c >> 8) & 0xff; + uint8_t low_byte = c & 0xff; int32_t offset = SubHeaderOffset(high_byte); if (offset == 0) { @@ -956,7 +956,7 @@ CMapTable::CMapFormat4::Builder::Builder(WritableFontData* data, int32_t offset, } CMapTable::CMapFormat4::Builder::Builder(SegmentList* segments, - IntegerList* glyph_id_array, + std::vector<int32_t>* glyph_id_array, const CMapId& cmap_id) : CMap::Builder(reinterpret_cast<ReadableFontData*>(NULL), CMapFormat::kFormat4, cmap_id), @@ -1016,7 +1016,7 @@ void CMapTable::CMapFormat4::Builder::set_segments(SegmentList* segments) { set_model_changed(); } -IntegerList* CMapTable::CMapFormat4::Builder::glyph_id_array() { +std::vector<int32_t>* CMapTable::CMapFormat4::Builder::glyph_id_array() { if (glyph_id_array_.empty()) { Initialize(InternalReadData()); set_model_changed(); @@ -1025,7 +1025,7 @@ IntegerList* CMapTable::CMapFormat4::Builder::glyph_id_array() { } void CMapTable::CMapFormat4::Builder:: -set_glyph_id_array(IntegerList* glyph_id_array) { +set_glyph_id_array(std::vector<int32_t>* glyph_id_array) { glyph_id_array_.assign(glyph_id_array->begin(), glyph_id_array->end()); set_model_changed(); } diff --git a/cpp/src/sfntly/table/core/cmap_table.h b/cpp/src/sfntly/table/core/cmap_table.h index b264b07..81f0a5d 100644 --- a/cpp/src/sfntly/table/core/cmap_table.h +++ b/cpp/src/sfntly/table/core/cmap_table.h @@ -374,13 +374,13 @@ public: virtual ~Builder(); SegmentList* segments(); void set_segments(SegmentList* segments); - IntegerList* glyph_id_array(); - void set_glyph_id_array(IntegerList* glyph_id_array); + std::vector<int32_t>* glyph_id_array(); + void set_glyph_id_array(std::vector<int32_t>* glyph_id_array); protected: Builder(WritableFontData* data, int32_t offset, const CMapId& cmap_id); Builder(ReadableFontData* data, int32_t offset, const CMapId& cmap_id); - Builder(SegmentList* segments, IntegerList* glyph_id_array, + Builder(SegmentList* segments, std::vector<int32_t>* glyph_id_array, const CMapId& cmap_id); explicit Builder(const CMapId& cmap_id); @@ -395,7 +395,7 @@ public: void Initialize(ReadableFontData* data); SegmentList segments_; - IntegerList glyph_id_array_; + std::vector<int32_t> glyph_id_array_; }; CMap::CharacterIterator* Iterator(); diff --git a/cpp/src/sfntly/table/core/font_header_table.cc b/cpp/src/sfntly/table/core/font_header_table.cc index a848afd..e089c7e 100644 --- a/cpp/src/sfntly/table/core/font_header_table.cc +++ b/cpp/src/sfntly/table/core/font_header_table.cc @@ -92,7 +92,7 @@ int32_t FontHeaderTable::GlyphDataFormat() { FontHeaderTable::FontHeaderTable(Header* header, ReadableFontData* data) : Table(header, data) { - IntegerList checksum_ranges; + std::vector<int32_t> checksum_ranges; checksum_ranges.push_back(0); checksum_ranges.push_back(Offset::kCheckSumAdjustment); checksum_ranges.push_back(Offset::kMagicNumber); diff --git a/cpp/src/sfntly/table/core/name_table.cc b/cpp/src/sfntly/table/core/name_table.cc index 4eb54ad..0e1fff9 100644 --- a/cpp/src/sfntly/table/core/name_table.cc +++ b/cpp/src/sfntly/table/core/name_table.cc @@ -78,7 +78,7 @@ NameTable::NameEntry::NameEntry() { } NameTable::NameEntry::NameEntry(const NameEntryId& name_entry_id, - const ByteVector& name_bytes) { + const std::vector<uint8_t>& name_bytes) { Init(name_entry_id.platform_id(), name_entry_id.encoding_id(), name_entry_id.language_id(), @@ -90,13 +90,13 @@ NameTable::NameEntry::NameEntry(int32_t platform_id, int32_t encoding_id, int32_t language_id, int32_t name_id, - const ByteVector& name_bytes) { + const std::vector<uint8_t>& name_bytes) { Init(platform_id, encoding_id, language_id, name_id, &name_bytes); } NameTable::NameEntry::~NameEntry() {} -ByteVector* NameTable::NameEntry::NameAsBytes() { +std::vector<uint8_t>* NameTable::NameEntry::NameAsBytes() { return &name_bytes_; } @@ -119,7 +119,7 @@ void NameTable::NameEntry::Init(int32_t platform_id, int32_t encoding_id, int32_t language_id, int32_t name_id, - const ByteVector* name_bytes) { + const std::vector<uint8_t>* name_bytes) { name_entry_id_ = NameEntryId(platform_id, encoding_id, language_id, name_id); if (name_bytes) { name_bytes_ = *name_bytes; @@ -136,7 +136,7 @@ NameTable::NameEntryBuilder::NameEntryBuilder() { } NameTable::NameEntryBuilder::NameEntryBuilder(const NameEntryId& name_entry_id, - const ByteVector& name_bytes) { + const std::vector<uint8_t>& name_bytes) { Init(name_entry_id.platform_id(), name_entry_id.encoding_id(), name_entry_id.language_id(), @@ -174,14 +174,14 @@ void NameTable::NameEntryBuilder::SetName(const UChar* name) { &name_entry_->name_bytes_); } -void NameTable::NameEntryBuilder::SetName(const ByteVector& name_bytes) { +void NameTable::NameEntryBuilder::SetName(const std::vector<uint8_t>& name_bytes) { name_entry_->name_bytes_.clear(); std::copy(name_bytes.begin(), name_bytes.end(), name_entry_->name_bytes_.begin()); } -void NameTable::NameEntryBuilder::SetName(const ByteVector& name_bytes, +void NameTable::NameEntryBuilder::SetName(const std::vector<uint8_t>& name_bytes, int32_t offset, int32_t length) { name_entry_->name_bytes_.clear(); @@ -194,7 +194,7 @@ void NameTable::NameEntryBuilder::Init(int32_t platform_id, int32_t encoding_id, int32_t language_id, int32_t name_id, - const ByteVector* name_bytes) { + const std::vector<uint8_t>* name_bytes) { name_entry_ = new NameEntry(); name_entry_->Init(platform_id, encoding_id, language_id, name_id, name_bytes); } @@ -465,7 +465,7 @@ int32_t NameTable::NameId(int32_t index) { OffsetForNameRecord(index)); } -void NameTable::NameAsBytes(int32_t index, ByteVector* b) { +void NameTable::NameAsBytes(int32_t index, std::vector<uint8_t>* b) { assert(b); b->clear(); @@ -473,26 +473,30 @@ void NameTable::NameAsBytes(int32_t index, ByteVector* b) { if (length <= 0) return; + int32_t offset = NameOffset(index); + if (offset < 0) + return; + b->resize(length); - data_->ReadBytes(NameOffset(index), &((*b)[0]), 0, length); + data_->ReadBytes(offset, &((*b)[0]), 0, length); } void NameTable::NameAsBytes(int32_t platform_id, int32_t encoding_id, int32_t language_id, int32_t name_id, - ByteVector* b) { + std::vector<uint8_t>* b) { assert(b); NameEntryPtr entry; entry.Attach(GetNameEntry(platform_id, encoding_id, language_id, name_id)); if (entry) { - ByteVector* name = entry->NameAsBytes(); + std::vector<uint8_t>* name = entry->NameAsBytes(); std::copy(name->begin(), name->end(), b->begin()); } } UChar* NameTable::Name(int32_t index) { - ByteVector b; + std::vector<uint8_t> b; NameAsBytes(index, &b); return ConvertFromNameBytes(&b, PlatformId(index), EncodingId(index)); } @@ -510,7 +514,7 @@ UChar* NameTable::Name(int32_t platform_id, } CALLER_ATTACH NameTable::NameEntry* NameTable::GetNameEntry(int32_t index) { - ByteVector b; + std::vector<uint8_t> b; NameAsBytes(index, &b); NameEntryPtr instance = new NameEntry(PlatformId(index), EncodingId(index), @@ -646,7 +650,7 @@ UConverter* NameTable::GetCharset(int32_t platform_id, int32_t encoding_id) { void NameTable::ConvertToNameBytes(const UChar* name, int32_t platform_id, int32_t encoding_id, - ByteVector* b) { + std::vector<uint8_t>* b) { assert(b); assert(name); b->clear(); @@ -673,7 +677,7 @@ void NameTable::ConvertToNameBytes(const UChar* name, ucnv_close(cs); } -UChar* NameTable::ConvertFromNameBytes(ByteVector* name_bytes, +UChar* NameTable::ConvertFromNameBytes(std::vector<uint8_t>* name_bytes, int32_t platform_id, int32_t encoding_id) { if (name_bytes == NULL || name_bytes->size() == 0) { diff --git a/cpp/src/sfntly/table/core/name_table.h b/cpp/src/sfntly/table/core/name_table.h index 4eaafbb..ac109df 100644 --- a/cpp/src/sfntly/table/core/name_table.h +++ b/cpp/src/sfntly/table/core/name_table.h @@ -446,12 +446,12 @@ class NameTable : public SubTableContainerTable, public RefCounted<NameTable> { class NameEntry : public RefCounted<NameEntry> { public: NameEntry(); - NameEntry(const NameEntryId& name_entry_id, const ByteVector& name_bytes); + NameEntry(const NameEntryId& name_entry_id, const std::vector<uint8_t>& name_bytes); NameEntry(int32_t platform_id, int32_t encoding_id, int32_t language_id, int32_t name_id, - const ByteVector& name_bytes); + const std::vector<uint8_t>& name_bytes); virtual ~NameEntry(); NameEntryId& name_entry_id() { return name_entry_id_; } @@ -462,7 +462,7 @@ class NameTable : public SubTableContainerTable, public RefCounted<NameTable> { // Get the bytes for name. Returned pointer is the address of private // member of this class, do not attempt to delete. - ByteVector* NameAsBytes(); + std::vector<uint8_t>* NameAsBytes(); // C++ port only: get the length of NameAsBytes. int32_t NameBytesLength(); @@ -477,10 +477,10 @@ class NameTable : public SubTableContainerTable, public RefCounted<NameTable> { private: void Init(int32_t platform_id, int32_t encoding_id, int32_t language_id, - int32_t name_id, const ByteVector* name_bytes); + int32_t name_id, const std::vector<uint8_t>* name_bytes); NameEntryId name_entry_id_; - ByteVector name_bytes_; + std::vector<uint8_t> name_bytes_; friend class NameEntryBuilder; }; @@ -492,14 +492,14 @@ class NameTable : public SubTableContainerTable, public RefCounted<NameTable> { public: NameEntryBuilder(); NameEntryBuilder(const NameEntryId& name_entry_id, - const ByteVector& name_bytes); + const std::vector<uint8_t>& name_bytes); explicit NameEntryBuilder(const NameEntryId& name_entry_id); explicit NameEntryBuilder(NameEntry* entry); virtual ~NameEntryBuilder(); virtual void SetName(const UChar* name); - virtual void SetName(const ByteVector& name_bytes); - virtual void SetName(const ByteVector& name_bytes, + virtual void SetName(const std::vector<uint8_t>& name_bytes); + virtual void SetName(const std::vector<uint8_t>& name_bytes, int32_t offset, int32_t length); @@ -510,7 +510,7 @@ class NameTable : public SubTableContainerTable, public RefCounted<NameTable> { private: void Init(int32_t platform_id, int32_t encoding_id, int32_t language_id, - int32_t name_id, const ByteVector* name_bytes); + int32_t name_id, const std::vector<uint8_t>* name_bytes); Ptr<NameEntry> name_entry_; }; @@ -647,10 +647,10 @@ class NameTable : public SubTableContainerTable, public RefCounted<NameTable> { // Get the name as bytes for the specified name. If there is no entry for the // requested name, then empty vector is returned. - virtual void NameAsBytes(int32_t index, ByteVector* b); + virtual void NameAsBytes(int32_t index, std::vector<uint8_t>* b); virtual void NameAsBytes(int32_t platform_id, int32_t encoding_id, int32_t language_id, int32_t name_id, - ByteVector* b); + std::vector<uint8_t>* b); // Get the name as a UChar* for the given name record. If there is no // encoding conversion available for the name record then a best attempt @@ -724,13 +724,13 @@ class NameTable : public SubTableContainerTable, public RefCounted<NameTable> { // Note: ICU UConverter* convention requires caller to ucnv_close() it. static UConverter* GetCharset(int32_t platform_id, int32_t encoding_id); - // Note: Output will be stored in ByteVector* b. Original data in b will be + // Note: Output will be stored in std::vector<uint8_t>* b. Original data in b will be // erased and replaced with converted name bytes. static void ConvertToNameBytes(const UChar* name, int32_t platform_id, - int32_t encoding_id, ByteVector* b); + int32_t encoding_id, std::vector<uint8_t>* b); // Note: ICU UChar* convention requires caller to delete[] it. - static UChar* ConvertFromNameBytes(ByteVector* name_bytes, + static UChar* ConvertFromNameBytes(std::vector<uint8_t>* name_bytes, int32_t platform_id, int32_t encoding_id); }; // class NameTable typedef Ptr<NameTable> NameTablePtr; diff --git a/cpp/src/sfntly/table/core/os2_table.cc b/cpp/src/sfntly/table/core/os2_table.cc index 1fef309..0d37db1 100644 --- a/cpp/src/sfntly/table/core/os2_table.cc +++ b/cpp/src/sfntly/table/core/os2_table.cc @@ -166,7 +166,7 @@ int32_t OS2Table::SFamilyClass() { return data_->ReadShort(Offset::kSFamilyClass); } -void OS2Table::Panose(ByteVector* value) { +void OS2Table::Panose(std::vector<uint8_t>* value) { assert(value); value->clear(); value->resize(10); @@ -189,7 +189,7 @@ int64_t OS2Table::UlUnicodeRange4() { return data_->ReadULong(Offset::kUlUnicodeRange4); } -void OS2Table::AchVendId(ByteVector* b) { +void OS2Table::AchVendId(std::vector<uint8_t>* b) { assert(b); b->clear(); b->resize(4); @@ -415,7 +415,7 @@ void OS2Table::Builder::SetSFamilyClass(int32_t family) { InternalWriteData()->WriteShort(Offset::kSFamilyClass, family); } -void OS2Table::Builder::Panose(ByteVector* value) { +void OS2Table::Builder::Panose(std::vector<uint8_t>* value) { assert(value); value->clear(); value->resize(Offset::kPanoseLength); @@ -425,7 +425,7 @@ void OS2Table::Builder::Panose(ByteVector* value) { Offset::kPanoseLength); } -void OS2Table::Builder::SetPanose(ByteVector* panose) { +void OS2Table::Builder::SetPanose(std::vector<uint8_t>* panose) { assert(panose); if (panose->size() != Offset::kPanoseLength) { #if !defined (SFNTLY_NO_EXCEPTION) @@ -468,14 +468,14 @@ void OS2Table::Builder::SetUlUnicodeRange4(int64_t range) { InternalWriteData()->WriteULong(Offset::kUlUnicodeRange4, range); } -void OS2Table::Builder::AchVendId(ByteVector* b) { +void OS2Table::Builder::AchVendId(std::vector<uint8_t>* b) { assert(b); b->clear(); b->resize(4); InternalReadData()->ReadBytes(Offset::kAchVendId, &((*b)[0]), 0, 4); } -void OS2Table::Builder::SetAchVendId(ByteVector* b) { +void OS2Table::Builder::SetAchVendId(std::vector<uint8_t>* b) { assert(b); assert(b->size()); InternalWriteData()->WriteBytesPad(Offset::kAchVendId, @@ -484,7 +484,7 @@ void OS2Table::Builder::SetAchVendId(ByteVector* b) { std::min<size_t>( (size_t)Offset::kAchVendIdLength, b->size()), - static_cast<byte_t>(' ')); + static_cast<uint8_t>(' ')); } int32_t OS2Table::Builder::FsSelection() { diff --git a/cpp/src/sfntly/table/core/os2_table.h b/cpp/src/sfntly/table/core/os2_table.h index 00d26d2..6057412 100644 --- a/cpp/src/sfntly/table/core/os2_table.h +++ b/cpp/src/sfntly/table/core/os2_table.h @@ -357,8 +357,8 @@ class OS2Table : public Table, public RefCounted<OS2Table> { void SetYStrikeoutPosition(int32_t position); int32_t SFamilyClass(); void SetSFamilyClass(int32_t family); - void Panose(ByteVector* value); - void SetPanose(ByteVector* panose); + void Panose(std::vector<uint8_t>* value); + void SetPanose(std::vector<uint8_t>* panose); int64_t UlUnicodeRange1(); void SetUlUnicodeRange1(int64_t range); int64_t UlUnicodeRange2(); @@ -369,12 +369,12 @@ class OS2Table : public Table, public RefCounted<OS2Table> { void SetUlUnicodeRange4(int64_t range); // UNIMPLEMENTED: EnumSet<UnicodeRange> UlUnicodeRange() // setUlUnicodeRange(EnumSet<UnicodeRange> rangeSet) - void AchVendId(ByteVector* b); + void AchVendId(std::vector<uint8_t>* b); // This field is 4 bytes in length and only the first 4 bytes of the byte // array will be written. If the byte array is less than 4 bytes it will be // padded out with space characters (0x20). // @param b ach Vendor Id - void SetAchVendId(ByteVector* b); + void SetAchVendId(std::vector<uint8_t>* b); // UNIMPLEMENTED: public EnumSet<FsSelection> fsSelection() int32_t FsSelection(); void SetFsSelection(int32_t fs_selection); @@ -429,13 +429,13 @@ class OS2Table : public Table, public RefCounted<OS2Table> { int32_t YStrikeoutSize(); int32_t YStrikeoutPosition(); int32_t SFamilyClass(); - void Panose(ByteVector* value); + void Panose(std::vector<uint8_t>* value); int64_t UlUnicodeRange1(); int64_t UlUnicodeRange2(); int64_t UlUnicodeRange3(); int64_t UlUnicodeRange4(); // UNIMPLEMENTED: public EnumSet<UnicodeRange> UlUnicodeRange() - void AchVendId(ByteVector* b); + void AchVendId(std::vector<uint8_t>* b); // UNIMPLEMENTED: public EnumSet<FsSelection> fsSelection() int32_t FsSelection(); int32_t UsFirstCharIndex(); diff --git a/cpp/src/sfntly/table/header.h b/cpp/src/sfntly/table/header.h index 7744a21..1a4cba1 100644 --- a/cpp/src/sfntly/table/header.h +++ b/cpp/src/sfntly/table/header.h @@ -34,51 +34,51 @@ class Header : public RefCounted<Header> { virtual ~Header(); // Get the table tag. - int32_t tag() { return tag_; } + int32_t tag() const { return tag_; } // Get the table offset. The offset is from the start of the font file. This // offset value is what was read from the font file during construction of the // font. It may not be meaningful if the font was maninpulated through the // builders. - int32_t offset() { return offset_; } + int32_t offset() const { return offset_; } // Is the offset in the header valid. The offset will not be valid if the // table was constructed during building and has no physical location in a // font file. - bool offset_valid() { return offset_valid_; } + bool offset_valid() const { return offset_valid_; } // Get the length of the table as recorded in the table record header. During // building the header length will reflect the length that was initially read // from the font file. This may not be consistent with the current state of // the data. - int32_t length() { return length_; } + int32_t length() const { return length_; } // Is the length in the header valid. The length will not be valid if the // table was constructed during building and has no physical location in a // font file until the table is built from the builder. - bool length_valid() { return length_valid_; } + bool length_valid() const { return length_valid_; } // Get the checksum for the table as recorded in the table record header. - int64_t checksum() { return checksum_; } + int64_t checksum() const { return checksum_; } // Is the checksum valid. The checksum will not be valid if the table was // constructed during building and has no physical location in a font file. // Note that this does *NOT* check the validity of the checksum against // the calculated checksum for the table data. - bool checksum_valid() { return checksum_valid_; } + bool checksum_valid() const { return checksum_valid_; } // UNIMPLEMENTED: boolean equals(Object obj) // int hashCode() // string toString() private: - int32_t tag_; - int32_t offset_; - bool offset_valid_; - int32_t length_; - bool length_valid_; - int64_t checksum_; - bool checksum_valid_; + const int32_t tag_; + const int32_t offset_; + const bool offset_valid_; + const int32_t length_; + const bool length_valid_; + const int64_t checksum_; + const bool checksum_valid_; friend class HeaderComparatorByOffset; friend class HeaderComparatorByTag; diff --git a/cpp/src/sfntly/table/truetype/glyph_table.cc b/cpp/src/sfntly/table/truetype/glyph_table.cc index 0c1e841..32b76b6 100644 --- a/cpp/src/sfntly/table/truetype/glyph_table.cc +++ b/cpp/src/sfntly/table/truetype/glyph_table.cc @@ -69,13 +69,13 @@ GlyphTable::Builder::Builder(Header* header, ReadableFontData* data) GlyphTable::Builder::~Builder() { } -void GlyphTable::Builder::SetLoca(const IntegerList& loca) { +void GlyphTable::Builder::SetLoca(const std::vector<int32_t>& loca) { loca_ = loca; set_model_changed(false); glyph_builders_.clear(); } -void GlyphTable::Builder::GenerateLocaList(IntegerList* locas) { +void GlyphTable::Builder::GenerateLocaList(std::vector<int32_t>* locas) { assert(locas); GlyphBuilderList* glyph_builders = GetGlyphBuilders(); locas->push_back(0); @@ -158,7 +158,7 @@ int32_t GlyphTable::Builder::SubSerialize(WritableFontData* new_data) { } void GlyphTable::Builder::Initialize(ReadableFontData* data, - const IntegerList& loca) { + const std::vector<int32_t>& loca) { if (data != NULL) { if (loca_.empty()) { return; @@ -181,7 +181,7 @@ void GlyphTable::Builder::Initialize(ReadableFontData* data, GlyphTable::GlyphBuilderList* GlyphTable::Builder::GetGlyphBuilders() { if (glyph_builders_.empty()) { - if (InternalReadData() && !loca_.empty()) { + if (InternalReadData() && loca_.empty()) { #if !defined (SFNTLY_NO_EXCEPTION) throw IllegalStateException( "Loca values not set - unable to parse glyph data."); @@ -354,29 +354,6 @@ CALLER_ATTACH ReadableFontData* GlyphTable::SimpleGlyph::Instructions() { data_->Slice(instructions_offset_, InstructionSize())); } -int32_t GlyphTable::SimpleGlyph::NumberOfPoints(int32_t contour) { - Initialize(); - if (contour >= NumberOfContours()) { - return 0; - } - return contour_index_[contour + 1] - contour_index_[contour]; -} - -int32_t GlyphTable::SimpleGlyph::XCoordinate(int32_t contour, int32_t point) { - Initialize(); - return x_coordinates_[contour_index_[contour] + point]; -} - -int32_t GlyphTable::SimpleGlyph::YCoordinate(int32_t contour, int32_t point) { - Initialize(); - return y_coordinates_[contour_index_[contour] + point]; -} - -bool GlyphTable::SimpleGlyph::OnCurve(int32_t contour, int32_t point) { - Initialize(); - return on_curve_[contour_index_[contour] + point]; -} - void GlyphTable::SimpleGlyph::Initialize() { AutoLock lock(initialization_lock_); if (initialized_) { @@ -545,6 +522,8 @@ GlyphTable::CompositeGlyph::~CompositeGlyph() { } int32_t GlyphTable::CompositeGlyph::Flags(int32_t contour) { + if (contour < 0 || static_cast<size_t>(contour) >= contour_index_.size()) + return ReadableFontData::kInvalidUnsigned; return data_->ReadUShort(contour_index_[contour]); } @@ -553,58 +532,11 @@ int32_t GlyphTable::CompositeGlyph::NumGlyphs() { } int32_t GlyphTable::CompositeGlyph::GlyphIndex(int32_t contour) { + if (contour < 0 || static_cast<size_t>(contour) >= contour_index_.size()) + return ReadableFontData::kInvalidUnsigned; return data_->ReadUShort(DataSize::kUSHORT + contour_index_[contour]); } -int32_t GlyphTable::CompositeGlyph::Argument1(int32_t contour) { - int32_t index = 2 * DataSize::kUSHORT + contour_index_[contour]; - int32_t contour_flags = Flags(contour); - if ((contour_flags & kFLAG_ARG_1_AND_2_ARE_WORDS) == - kFLAG_ARG_1_AND_2_ARE_WORDS) { - return data_->ReadUShort(index); - } - return data_->ReadByte(index); -} - -int32_t GlyphTable::CompositeGlyph::Argument2(int32_t contour) { - int32_t index = 2 * DataSize::kUSHORT + contour_index_[contour]; - int32_t contour_flags = Flags(contour); - if ((contour_flags & kFLAG_ARG_1_AND_2_ARE_WORDS) == - kFLAG_ARG_1_AND_2_ARE_WORDS) { - return data_->ReadUShort(index + DataSize::kUSHORT); - } - return data_->ReadByte(index + DataSize::kUSHORT); -} - -int32_t GlyphTable::CompositeGlyph::TransformationSize(int32_t contour) { - int32_t contour_flags = Flags(contour); - if ((contour_flags & kFLAG_WE_HAVE_A_SCALE) == kFLAG_WE_HAVE_A_SCALE) { - return DataSize::kF2DOT14; - } else if ((contour_flags & kFLAG_WE_HAVE_AN_X_AND_Y_SCALE) == - kFLAG_WE_HAVE_AN_X_AND_Y_SCALE) { - return 2 * DataSize::kF2DOT14; - } else if ((contour_flags & kFLAG_WE_HAVE_A_TWO_BY_TWO) == - kFLAG_WE_HAVE_A_TWO_BY_TWO) { - return 4 * DataSize::kF2DOT14; - } - return 0; -} - -void GlyphTable::CompositeGlyph::Transformation(int32_t contour, - ByteVector* transformation) { - int32_t contour_flags = Flags(contour); - int32_t index = contour_index_[contour] + 2 * DataSize::kUSHORT; - if ((contour_flags & kFLAG_ARG_1_AND_2_ARE_WORDS) == - kFLAG_ARG_1_AND_2_ARE_WORDS) { - index += 2 * DataSize::kSHORT; - } else { - index += 2 * DataSize::kBYTE; - } - int32_t tsize = TransformationSize(contour); - transformation->resize(tsize); - data_->ReadBytes(index, &((*transformation)[0]), 0, tsize); -} - int32_t GlyphTable::CompositeGlyph::InstructionSize() { return instruction_size_; } @@ -626,6 +558,9 @@ void GlyphTable::CompositeGlyph::Initialize() { while ((flags & kFLAG_MORE_COMPONENTS) == kFLAG_MORE_COMPONENTS) { contour_index_.push_back(index); flags = data_->ReadUShort(index); + if (flags == ReadableFontData::kInvalidUnsigned) + break; + index += 2 * DataSize::kUSHORT; // flags and glyphIndex if ((flags & kFLAG_ARG_1_AND_2_ARE_WORDS) == kFLAG_ARG_1_AND_2_ARE_WORDS) { index += 2 * DataSize::kSHORT; diff --git a/cpp/src/sfntly/table/truetype/glyph_table.h b/cpp/src/sfntly/table/truetype/glyph_table.h index 4ffddda..e16c8c8 100644 --- a/cpp/src/sfntly/table/truetype/glyph_table.h +++ b/cpp/src/sfntly/table/truetype/glyph_table.h @@ -115,8 +115,8 @@ class GlyphTable : public SubTableContainerTable, Builder(Header* header, ReadableFontData* data); virtual ~Builder(); - virtual void SetLoca(const IntegerList& loca); - virtual void GenerateLocaList(IntegerList* locas); + virtual void SetLoca(const std::vector<int32_t>& loca); + virtual void GenerateLocaList(std::vector<int32_t>* locas); static CALLER_ATTACH Builder* CreateBuilder(Header* header, WritableFontData* data); @@ -150,12 +150,12 @@ class GlyphTable : public SubTableContainerTable, virtual int32_t SubSerialize(WritableFontData* new_data); private: - void Initialize(ReadableFontData* data, const IntegerList& loca); + void Initialize(ReadableFontData* data, const std::vector<int32_t>& loca); GlyphBuilderList* GetGlyphBuilders(); void Revert(); GlyphBuilderList glyph_builders_; - IntegerList loca_; + std::vector<int32_t> loca_; }; class SimpleGlyph : public Glyph, public RefCounted<SimpleGlyph> { @@ -199,11 +199,6 @@ class GlyphTable : public SubTableContainerTable, virtual CALLER_ATTACH ReadableFontData* Instructions(); virtual void Initialize(); - int32_t NumberOfPoints(int32_t contour); - int32_t XCoordinate(int32_t contour, int32_t point); - int32_t YCoordinate(int32_t contour, int32_t point); - bool OnCurve(int32_t contour, int32_t point); - private: void ParseData(bool fill_arrays); int32_t FlagAsInt(int32_t index); @@ -224,10 +219,10 @@ class GlyphTable : public SubTableContainerTable, int32_t x_byte_count_; int32_t y_byte_count_; - IntegerList x_coordinates_; - IntegerList y_coordinates_; + std::vector<int32_t> x_coordinates_; + std::vector<int32_t> y_coordinates_; std::vector<bool> on_curve_; - IntegerList contour_index_; + std::vector<int32_t> contour_index_; }; class CompositeGlyph : public Glyph, public RefCounted<CompositeGlyph> { @@ -272,10 +267,6 @@ class GlyphTable : public SubTableContainerTable, int32_t Flags(int32_t contour); int32_t NumGlyphs(); int32_t GlyphIndex(int32_t contour); - int32_t Argument1(int32_t contour); - int32_t Argument2(int32_t contour); - int32_t TransformationSize(int32_t contour); - void Transformation(int32_t contour, ByteVector* transformation); virtual int32_t InstructionSize(); virtual CALLER_ATTACH ReadableFontData* Instructions(); @@ -283,7 +274,7 @@ class GlyphTable : public SubTableContainerTable, virtual void Initialize(); private: - IntegerList contour_index_; + std::vector<int32_t> contour_index_; int32_t instruction_size_; int32_t instructions_offset_; bool initialized_; diff --git a/cpp/src/sfntly/table/truetype/loca_table.cc b/cpp/src/sfntly/table/truetype/loca_table.cc index c692155..a1e82a4 100644 --- a/cpp/src/sfntly/table/truetype/loca_table.cc +++ b/cpp/src/sfntly/table/truetype/loca_table.cc @@ -40,7 +40,11 @@ int32_t LocaTable::GlyphLength(int32_t glyph_id) { #endif return 0; } - return Loca(glyph_id + 1) - Loca(glyph_id); + int32_t glyph_val = Loca(glyph_id); + int32_t glyph_next_val = Loca(glyph_id + 1); + if (glyph_val < 0 || glyph_next_val < 0 || glyph_next_val <= glyph_val) + return 0; + return glyph_next_val - glyph_val; } int32_t LocaTable::NumLocas() { @@ -109,11 +113,11 @@ LocaTable::Builder* LocaTable::Builder::CreateBuilder(Header* header, return builder.Detach(); } -IntegerList* LocaTable::Builder::LocaList() { +std::vector<int32_t>* LocaTable::Builder::LocaList() { return GetLocaList(); } -void LocaTable::Builder::SetLocaList(IntegerList* list) { +void LocaTable::Builder::SetLocaList(std::vector<int32_t>* list) { loca_.clear(); if (list) { loca_ = *list; @@ -136,6 +140,7 @@ int32_t LocaTable::Builder::GlyphLength(int32_t glyph_id) { } void LocaTable::Builder::SetNumGlyphs(int32_t num_glyphs) { + assert(num_glyphs >= 0); num_glyphs_ = num_glyphs; } @@ -183,7 +188,7 @@ bool LocaTable::Builder::SubReadyToSerialize() { int32_t LocaTable::Builder::SubSerialize(WritableFontData* new_data) { int32_t size = 0; - for (IntegerList::iterator l = loca_.begin(), end = loca_.end(); + for (std::vector<int32_t>::iterator l = loca_.begin(), end = loca_.end(); l != end; ++l) { if (format_version_ == IndexToLocFormat::kLongOffset) { size += new_data->WriteULong(size, *l); @@ -228,7 +233,7 @@ int32_t LocaTable::Builder::LastGlyphIndex() { return !loca_.empty() ? loca_.size() - 2 : num_glyphs_ - 1; } -IntegerList* LocaTable::Builder::GetLocaList() { +std::vector<int32_t>* LocaTable::Builder::GetLocaList() { if (loca_.empty()) { Initialize(InternalReadData()); set_model_changed(); diff --git a/cpp/src/sfntly/table/truetype/loca_table.h b/cpp/src/sfntly/table/truetype/loca_table.h index 67c5749..fe1dd4a 100644 --- a/cpp/src/sfntly/table/truetype/loca_table.h +++ b/cpp/src/sfntly/table/truetype/loca_table.h @@ -60,12 +60,12 @@ class LocaTable : public Table, public RefCounted<LocaTable> { // SetLocaList(List) method. // If there is no current data for the loca table builder or the loca list // have not been previously set then this will return an empty List. - IntegerList* LocaList(); + std::vector<int32_t>* LocaList(); // Set the list of locas to be used for building this table. If any existing // list was already retrieved with the LocaList() method then the // connection of that previous list to this builder will be broken. - void SetLocaList(IntegerList* list); + void SetLocaList(std::vector<int32_t>* list); // Return the offset for the given glyph id. Valid glyph ids are from 0 to // one less than the number of glyphs. The zero entry is the special entry @@ -129,13 +129,13 @@ class LocaTable : public Table, public RefCounted<LocaTable> { // Internal method to get the loca list if already generated and if not to // initialize the state of the builder. // @return the loca list - IntegerList* GetLocaList(); + std::vector<int32_t>* GetLocaList(); void ClearLoca(bool nullify); int32_t format_version_; // Note: IndexToLocFormat int32_t num_glyphs_; - IntegerList loca_; + std::vector<int32_t> loca_; }; virtual ~LocaTable(); diff --git a/cpp/src/sfntly/tools/subsetter/glyph_table_subsetter.cc b/cpp/src/sfntly/tools/subsetter/glyph_table_subsetter.cc index b3d6b07..02cc149 100644 --- a/cpp/src/sfntly/tools/subsetter/glyph_table_subsetter.cc +++ b/cpp/src/sfntly/tools/subsetter/glyph_table_subsetter.cc @@ -39,7 +39,7 @@ bool GlyphTableSubsetter::Subset(Subsetter* subsetter, assert(subsetter); assert(font_builder); - IntegerList* permutation_table = subsetter->GlyphPermutationTable(); + std::vector<int32_t>* permutation_table = subsetter->GlyphPermutationTable(); if (!permutation_table || permutation_table->empty()) return false; @@ -66,7 +66,7 @@ bool GlyphTableSubsetter::Subset(Subsetter* subsetter, } GlyphTable::GlyphBuilderList* glyph_builders = glyph_table_builder->GlyphBuilders(); - for (IntegerList::iterator old_glyph_id = permutation_table->begin(), + for (std::vector<int32_t>::iterator old_glyph_id = permutation_table->begin(), old_glyph_id_end = permutation_table->end(); old_glyph_id != old_glyph_id_end; ++old_glyph_id) { int old_offset = loca_table->GlyphOffset(*old_glyph_id); @@ -81,7 +81,7 @@ bool GlyphTableSubsetter::Subset(Subsetter* subsetter, glyph_builder.Attach(glyph_table_builder->GlyphBuilder(copy_data)); glyph_builders->push_back(glyph_builder); } - IntegerList loca_list; + std::vector<int32_t> loca_list; glyph_table_builder->GenerateLocaList(&loca_list); loca_table_builder->SetLocaList(&loca_list); return true; diff --git a/cpp/src/sfntly/tools/subsetter/subsetter.cc b/cpp/src/sfntly/tools/subsetter/subsetter.cc index 7d98779..3019cad 100644 --- a/cpp/src/sfntly/tools/subsetter/subsetter.cc +++ b/cpp/src/sfntly/tools/subsetter/subsetter.cc @@ -37,7 +37,7 @@ Subsetter::~Subsetter() { table_subsetters_.clear(); } -void Subsetter::SetGlyphs(IntegerList* glyphs) { +void Subsetter::SetGlyphs(std::vector<int32_t>* glyphs) { new_to_old_glyphs_ = *glyphs; } @@ -47,7 +47,7 @@ void Subsetter::SetCMaps(CMapIdList* cmap_ids, int32_t number) { // TODO(arthurhsu): IMPLEMENT } -void Subsetter::SetRemoveTables(IntegerSet* remove_tables) { +void Subsetter::SetRemoveTables(std::set<int32_t>* remove_tables) { remove_tables_ = *remove_tables; } @@ -55,13 +55,13 @@ CALLER_ATTACH Font::Builder* Subsetter::Subset() { FontBuilderPtr font_builder; font_builder.Attach(font_factory_->NewFontBuilder()); - IntegerSet table_tags; + std::set<int32_t> table_tags; for (TableMap::const_iterator i = font_->GetTableMap()->begin(), e = font_->GetTableMap()->end(); i != e; ++i) { table_tags.insert(i->first); } if (!remove_tables_.empty()) { - IntegerSet result; + std::set<int32_t> result; std::set_difference(table_tags.begin(), table_tags.end(), remove_tables_.begin(), remove_tables_.end(), std::inserter(result, result.end())); @@ -73,15 +73,15 @@ CALLER_ATTACH Font::Builder* Subsetter::Subset() { table_subsetter != table_subsetter_end; ++table_subsetter) { bool handled = (*table_subsetter)->Subset(this, font_, font_builder); if (handled) { - IntegerSet* handled_tags = (*table_subsetter)->TagsHandled(); - IntegerSet result; + std::set<int32_t>* handled_tags = (*table_subsetter)->TagsHandled(); + std::set<int32_t> result; std::set_difference(table_tags.begin(), table_tags.end(), handled_tags->begin(), handled_tags->end(), std::inserter(result, result.end())); table_tags = result; } } - for (IntegerSet::iterator tag = table_tags.begin(), + for (std::set<int32_t>::iterator tag = table_tags.begin(), tag_end = table_tags.end(); tag != tag_end; ++tag) { Table* table = font_->GetTable(*tag); if (table) { @@ -91,7 +91,7 @@ CALLER_ATTACH Font::Builder* Subsetter::Subset() { return font_builder.Detach(); } -IntegerList* Subsetter::GlyphPermutationTable() { +std::vector<int32_t>* Subsetter::GlyphPermutationTable() { return &new_to_old_glyphs_; } diff --git a/cpp/src/sfntly/tools/subsetter/subsetter.h b/cpp/src/sfntly/tools/subsetter/subsetter.h index 85940a7..d0a2607 100644 --- a/cpp/src/sfntly/tools/subsetter/subsetter.h +++ b/cpp/src/sfntly/tools/subsetter/subsetter.h @@ -31,7 +31,7 @@ class Subsetter : public RefCounted<Subsetter> { Subsetter(Font* font, FontFactory* font_factory); virtual ~Subsetter(); - virtual void SetGlyphs(IntegerList* glyphs); + virtual void SetGlyphs(std::vector<int32_t>* glyphs); // Set the cmaps to be used in the subsetted font. The cmaps are listed in // order of priority and the number parameter gives a count of how many of the @@ -51,9 +51,9 @@ class Subsetter : public RefCounted<Subsetter> { // @param number the maximum number of cmaps to place in the subsetted font virtual void SetCMaps(CMapIdList* cmap_ids, int32_t number); - virtual void SetRemoveTables(IntegerSet* remove_tables); + virtual void SetRemoveTables(std::set<int32_t>* remove_tables); virtual CALLER_ATTACH Font::Builder* Subset(); - virtual IntegerList* GlyphPermutationTable(); + virtual std::vector<int32_t>* GlyphPermutationTable(); virtual CMapIdList* CMapId(); private: @@ -62,8 +62,8 @@ class Subsetter : public RefCounted<Subsetter> { TableSubsetterList table_subsetters_; // Settings from user - IntegerSet remove_tables_; - IntegerList new_to_old_glyphs_; + std::set<int32_t> remove_tables_; + std::vector<int32_t> new_to_old_glyphs_; CMapIdList cmap_ids_; }; diff --git a/cpp/src/sfntly/tools/subsetter/table_subsetter.h b/cpp/src/sfntly/tools/subsetter/table_subsetter.h index 1336615..6a39f73 100644 --- a/cpp/src/sfntly/tools/subsetter/table_subsetter.h +++ b/cpp/src/sfntly/tools/subsetter/table_subsetter.h @@ -26,7 +26,7 @@ namespace sfntly { class Subsetter; class TableSubsetter : virtual public RefCount { public: - virtual IntegerSet* TagsHandled() = 0; + virtual std::set<int32_t>* TagsHandled() = 0; virtual bool TagHandled(int32_t tag) = 0; virtual bool Subset(Subsetter* subsetter, Font* font, Font::Builder* font_builder) = 0; diff --git a/cpp/src/sfntly/tools/subsetter/table_subsetter_impl.cc b/cpp/src/sfntly/tools/subsetter/table_subsetter_impl.cc index f239c78..d2085a1 100644 --- a/cpp/src/sfntly/tools/subsetter/table_subsetter_impl.cc +++ b/cpp/src/sfntly/tools/subsetter/table_subsetter_impl.cc @@ -31,7 +31,7 @@ bool TableSubsetterImpl::TagHandled(int32_t tag) { return tags_.find(tag) != tags_.end(); } -IntegerSet* TableSubsetterImpl::TagsHandled() { +std::set<int32_t>* TableSubsetterImpl::TagsHandled() { return &tags_; } diff --git a/cpp/src/sfntly/tools/subsetter/table_subsetter_impl.h b/cpp/src/sfntly/tools/subsetter/table_subsetter_impl.h index de0d9a9..14c770a 100644 --- a/cpp/src/sfntly/tools/subsetter/table_subsetter_impl.h +++ b/cpp/src/sfntly/tools/subsetter/table_subsetter_impl.h @@ -26,10 +26,10 @@ class TableSubsetterImpl : public TableSubsetter { TableSubsetterImpl(const int32_t* tags, size_t tags_length); virtual ~TableSubsetterImpl(); virtual bool TagHandled(int32_t tag); - virtual IntegerSet* TagsHandled(); + virtual std::set<int32_t>* TagsHandled(); protected: - IntegerSet tags_; + std::set<int32_t> tags_; }; } // namespace sfntly diff --git a/cpp/src/test/bitmap_table_test.cc b/cpp/src/test/bitmap_table_test.cc index df3ffc0..e9eacc7 100644 --- a/cpp/src/test/bitmap_table_test.cc +++ b/cpp/src/test/bitmap_table_test.cc @@ -58,11 +58,18 @@ bool CommonReadingTest(Font* raw_font) { EXPECT_FALSE(bitmap_loca == NULL); EXPECT_FALSE(bitmap_table == NULL); + if (!bitmap_loca) { + return false; + } + EXPECT_EQ(bitmap_loca->NumSizes(), NUM_STRIKES); // Strike 1 BitmapSizeTablePtr strike1 = bitmap_loca->GetBitmapSizeTable(0); EXPECT_FALSE(strike1 == NULL); + if (!strike1) { + return false; + } EXPECT_EQ(strike1->IndexSubTableArrayOffset(), STRIKE1_ARRAY_OFFSET); EXPECT_EQ(strike1->NumberOfIndexSubTables(), STRIKE1_NUM_INDEX_TABLES); EXPECT_EQ(strike1->ColorRef(), STRIKE1_COLOR_REF); diff --git a/cpp/src/test/byte_array_test.cc b/cpp/src/test/byte_array_test.cc index 40a6489..de50089 100644 --- a/cpp/src/test/byte_array_test.cc +++ b/cpp/src/test/byte_array_test.cc @@ -28,7 +28,7 @@ const int32_t BYTE_ARRAY_SIZES[] = void FillTestByteArray(ByteArray* ba, int32_t size) { for (int32_t i = 0; i < size; ++i) { - ba->Put(i, (byte_t)(i % 256)); + ba->Put(i, (uint8_t)(i % 256)); } } diff --git a/cpp/src/test/endian_test.cc b/cpp/src/test/endian_test.cc index 0d9da09..80cce68 100644 --- a/cpp/src/test/endian_test.cc +++ b/cpp/src/test/endian_test.cc @@ -25,7 +25,7 @@ namespace sfntly { bool TestEndian() { - byte_t test_data[] = { + uint8_t test_data[] = { 0x68, 0x65, 0x61, 0x64, // 0: head 0xca, 0xca, 0xca, 0xca, // 4: ubyte, byte, char 0x00, 0x18, 0x80, 0x18, // 8: ushort, short diff --git a/cpp/src/test/font_data_test.cc b/cpp/src/test/font_data_test.cc index 4b0db64..5ed041c 100644 --- a/cpp/src/test/font_data_test.cc +++ b/cpp/src/test/font_data_test.cc @@ -136,14 +136,14 @@ bool TestReadableFontDataSearching() { void FillTestByteArray(ByteArray* ba, int32_t size) { for (int32_t i = 0; i < size; ++i) { - ba->Put(i, (byte_t)(i % 256)); + ba->Put(i, (uint8_t)(i % 256)); } } void ReadFontDataWithSingleByte(ReadableFontData* rfd, ByteVector* buffer) { buffer->resize(rfd->Length()); for (int32_t index = 0; index < rfd->Length(); ++index) { - (*buffer)[index] = (byte_t)(rfd->ReadByte(index)); + (*buffer)[index] = (uint8_t)(rfd->ReadByte(index)); } } @@ -178,7 +178,7 @@ void ReadFontDataWithSlidingWindow(ReadableFontData* rfd, int32_t window_size, void WriteFontDataWithSingleByte(ReadableFontData* rfd, WritableFontData* wfd) { for (int32_t index = 0; index < rfd->Length(); ++index) { - byte_t b = (byte_t)(rfd->ReadByte(index)); + uint8_t b = (uint8_t)(rfd->ReadByte(index)); wfd->WriteByte(index, b); } } diff --git a/cpp/src/test/open_type_data_test.cc b/cpp/src/test/open_type_data_test.cc index 0917aab..5d73e84 100644 --- a/cpp/src/test/open_type_data_test.cc +++ b/cpp/src/test/open_type_data_test.cc @@ -20,12 +20,12 @@ namespace sfntly { -const byte_t TEST_OTF_DATA[] = +const uint8_t TEST_OTF_DATA[] = {0xff, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01}; bool TestOTFRead() { ByteVector bytes; - for (size_t i = 0; i < sizeof(TEST_OTF_DATA) / sizeof(byte_t); ++i) { + for (size_t i = 0; i < sizeof(TEST_OTF_DATA) / sizeof(uint8_t); ++i) { bytes.push_back(TEST_OTF_DATA[i]); } ByteArrayPtr array = new MemoryByteArray(&(bytes[0]), bytes.size()); @@ -45,7 +45,7 @@ bool TestOTFRead() { bool TestOTFCopy() { ByteVector source_bytes(1024); for (size_t i = 0; i < source_bytes.size(); ++i) { - source_bytes[i] = (byte_t)(i & 0xff); + source_bytes[i] = (uint8_t)(i & 0xff); } ByteArrayPtr source_array = new MemoryByteArray(&(source_bytes[0]), 1024); ReadableFontDataPtr source = new ReadableFontData(source_array); diff --git a/cpp/src/test/otf_basic_editing_test.cc b/cpp/src/test/otf_basic_editing_test.cc index 7388fac..04c8778 100644 --- a/cpp/src/test/otf_basic_editing_test.cc +++ b/cpp/src/test/otf_basic_editing_test.cc @@ -33,30 +33,41 @@ bool TestOTFBasicEditing() { factory.Attach(FontFactory::GetInstance()); FontBuilderArray font_builder_array; BuilderForFontFile(SAMPLE_TTF_FILE, factory, &font_builder_array); + if (font_builder_array.size() != 1) { + EXPECT_TRUE(false); + return false; + } FontBuilderPtr font_builder = font_builder_array[0]; // ensure the builder is not bogus - EXPECT_TRUE(font_builder != NULL); + if (!font_builder) { + EXPECT_TRUE(false); + return false; + } TableBuilderMap* builder_map = font_builder->table_builders(); - EXPECT_TRUE(builder_map != NULL); + if (!builder_map) { + EXPECT_TRUE(false); + return false; + } IntegerSet builder_tags; for (TableBuilderMap::iterator i = builder_map->begin(), e = builder_map->end(); i != e; ++i) { - EXPECT_TRUE(i->second != NULL); - if (i->second == NULL) { + if (!i->second) { + EXPECT_TRUE(false); char tag[5] = {0}; int32_t value = ToBE32(i->first); memcpy(tag, &value, 4); fprintf(stderr, "tag %s does not have valid builder\n", tag); - } else { - builder_tags.insert(i->first); + continue; } + builder_tags.insert(i->first); } FontHeaderTableBuilderPtr header_builder = down_cast<FontHeaderTable::Builder*>( font_builder->GetTableBuilder(Tag::head)); int64_t mod_date = header_builder->Modified(); + EXPECT_EQ(3397043097, mod_date); header_builder->SetModified(mod_date + 1); FontPtr font; font.Attach(font_builder->Build()); @@ -65,10 +76,10 @@ bool TestOTFBasicEditing() { const TableMap* table_map = font->GetTableMap(); for (TableMap::const_iterator i = table_map->begin(), e = table_map->end(); i != e; ++i) { - TablePtr table = (*i).second; + TablePtr table = i->second; HeaderPtr header = table->header(); - EXPECT_TRUE(builder_tags.find(header->tag()) != builder_tags.end()); - builder_tags.erase(header->tag()); + size_t erased = builder_tags.erase(header->tag()); + EXPECT_EQ(1U, erased); } EXPECT_TRUE(builder_tags.empty()); @@ -79,7 +90,7 @@ bool TestOTFBasicEditing() { // Checksum correctness of builder. TablePtr post = font->GetTable(Tag::post); - EXPECT_EQ(post->CalculatedChecksum(), TTF_CHECKSUM[SAMPLE_TTF_POST]); + EXPECT_EQ(TTF_CHECKSUM[SAMPLE_TTF_POST], post->CalculatedChecksum()); return true; } diff --git a/cpp/src/test/test_utils_test.cc b/cpp/src/test/test_utils_test.cc index 9afc03c..fbd5ed1 100644 --- a/cpp/src/test/test_utils_test.cc +++ b/cpp/src/test/test_utils_test.cc @@ -40,7 +40,7 @@ bool TestEncoding() { for (i = 0; i < 7; ++i) { int32_t encoded = TestUtils::EncodeOneChar(conv, (int16_t)from[i]); for (; encoded; encoded <<= 8) { - byte_t b = (encoded & 0xff000000) >> 24; + uint8_t b = (encoded & 0xff000000) >> 24; if (!b) continue; EXPECT_EQ(want[j], b); diff --git a/cpp/src/test/verify_hhea.cc b/cpp/src/test/verify_hhea.cc index 81ddb58..1e1001c 100644 --- a/cpp/src/test/verify_hhea.cc +++ b/cpp/src/test/verify_hhea.cc @@ -24,7 +24,7 @@ namespace sfntly { const int32_t HHEA_ASCENDER = 2023; const int32_t HHEA_DESCENDER = -648; -const int32_t HHEA_LINE_GAP = 93; +// const int32_t HHEA_LINE_GAP = 93; const int32_t HHEA_ADVANCE_WIDTH_MAX = 2753; const int32_t HHEA_MIN_LSB = -968; const int32_t HHEA_MIN_RSB = -411; diff --git a/cpp/src/test/verify_maxp.cc b/cpp/src/test/verify_maxp.cc index dcd776e..074042a 100644 --- a/cpp/src/test/verify_maxp.cc +++ b/cpp/src/test/verify_maxp.cc @@ -31,7 +31,7 @@ const int32_t MAXP_MAX_ZONES = 2; const int32_t MAXP_MAX_TWILIGHT_POINTS = 0; const int32_t MAXP_MAX_STORAGE = 1; const int32_t MAXP_MAX_FUNCTION_DEFS = 1; -const int32_t MAXP_MAX_INSTR_DEFS = 0; +// const int32_t MAXP_MAX_INSTR_DEFS = 0; const int32_t MAXP_MAX_STACK_ELEMENTS = 64; const int32_t MAXP_MAX_INSTR_SIZE = 46; const int32_t MAXP_MAX_COMPONENT_ELEMENTS = 4; diff --git a/cpp/src/test/verify_os2.cc b/cpp/src/test/verify_os2.cc index 4897e87..c80c58a 100644 --- a/cpp/src/test/verify_os2.cc +++ b/cpp/src/test/verify_os2.cc @@ -37,12 +37,12 @@ const int32_t OS2_YSUPS_YOFFSET = 1; const int32_t OS2_YSTRIKEOUT_SIZE = 12312; const int32_t OS2_YSTRIKEOUT_POS = -16224; const int32_t OS2_SFAMILY_CLASS = 0; -const byte_t OS2_PANOSE[] = { 2, 11, 6, 3, 6, 1, 0, 0, 0, 0 }; +const uint8_t OS2_PANOSE[] = { 2, 11, 6, 3, 6, 1, 0, 0, 0, 0 }; const int64_t OS2_UL_UNICODE_RANGE1 = 0xE00002FFL; const int64_t OS2_UL_UNICODE_RANGE2 = 0x520020FBL; const int64_t OS2_UL_UNICODE_RANGE3 = 0L; const int64_t OS2_UL_UNICODE_RANGE4 = 0L; -const byte_t OS2_ACH_VEND_ID[] = { 'P', 'f', 'E', 'd' }; +const uint8_t OS2_ACH_VEND_ID[] = { 'P', 'f', 'E', 'd' }; const int32_t OS2_FS_SELECTION = 0x0040; const int32_t OS2_US_FIRST_CHAR_IDX = 0x0020; const int32_t OS2_US_LAST_CHAR_IDX = 0xFFFF; diff --git a/doc/MicroTypeExpress.md b/doc/MicroTypeExpress.md new file mode 100644 index 0000000..97f55d0 --- /dev/null +++ b/doc/MicroTypeExpress.md @@ -0,0 +1,42 @@ +# MicroType Express in sfntly + +This page describes sfntly’s implementation of MicroType Express +compression. + +The MicroType Express format is [documented](http://www.w3.org/Submission/MTX/), +and is recently available under license terms we believe are friendly to +open source (as well as proprietary) implementation. The most popular +implementation of a decoder is Internet Explorer, as a compression +option in its Embedded OpenType (EOT) format. Since MicroType Express +gives an approximate 15% gain in compression over gzip, a web font +service striving for maximum performance can benefit from implementing +EOT compression. + +The current codebase in sfntly is for compression only (this is by far +the most useful for web serving). The easiest way to get started is with +the command line tool, sfnttool: + +``` +sfnttool -e -x source.ttf source.eot +``` + +The code has been tested extensively against IE, and is currently in +production in Google Web Fonts, both for full fonts and for subsetting +(using the text= parameter). This serving path also uses sfntly to +compute the subsets, and is essentially the same as the -s parameter to +sfnttool. + +If you’re interested in the code and details of the compression +algorithm, here’s a bit of a guide: + +The top-level MicroType Express compression code is in MtxWriter.java +(in the tools/conversion/eot directory). This code implements almost all +of the MicroType Express format, including the hdmx tables, push +sequences, and jump coding. The main feature missing is the VDMX table +(vertical device metrics), which is very rarely used in web fonts. + +Patches are welcome -- possible areas include: implementing the VDMX +table, speeding up the LZCOMP entropy coder (the match finding code is a +straightforward adaptation of the algorithm in the format document), +implementing a decoder in addition to an encoder, and porting the Java +implementation to C++. diff --git a/doc/SfntlyCPlusPlusNotes.md b/doc/SfntlyCPlusPlusNotes.md new file mode 100644 index 0000000..0a55f85 --- /dev/null +++ b/doc/SfntlyCPlusPlusNotes.md @@ -0,0 +1,164 @@ +Introduction +=============================================================== + +This document will as the C++ port matures serve as a log to how +different parts of the library work. As of today, there is some general +info but mostly CMap specific details. + +------------------------------------------------------------------------ + +Font Data Tables +=========================================================================== + +One of the important goals in `sfntly` is thread safety which is why +tables can only be created with their nested `Builder` class and are +immutable after creation. + +`CMapTable` +-------------------------------------------------------- + +*CMap* = character map; it converts *code points* in a *code page* to +*glyph IDs*. + +The CMapTable is a table of CMaps (CMaps are also tables; one for every +encoding supported by the font). Representing an encoding-dependent +character map is in one of 14 formats, out of which formats 0 and 4 are +the most used; sfntly/C++ will initially only support formats 0, 2, 4 +and 12. + +### `CMapFormat0` Byte encoding table + +Format 0 is a basic table where a character’s glyph ID is looked up in a +glyphIdArray256. As it only supports 256 characters it can only encode +ASCII and ISO 8859-x (alphabet-based languages). + +### `CMapFormat2` High-byte mapping through table + +Chinese, Japanese and Korean (CJK) need special 2 byte encodings for +each code point like Shift-JIS. + +### `CMapFormat4` Segment mapping to delta values + +This is the preferred format for Unicode Basic Multilingual Plane (BMP) +encodings according to the Microsoft spec. Format 4 defines segments +(contiguous ranges of characters; variable length). Finding a +character’s glyph id first means finding the segment it is part of using +a binary search (the segments are sorted). A segment has a +**`startCode`**, an **`endCode`** (the minimum and maximum code points +in the segment), an **`idDelta`** (delta for all code points in the +segment) and an **`idRangeOffset`** (offset into glyphIdArray or 0). + +`idDelta` and `idRangeOffset` seem to be the same thing, offsets. In +fact, `idRangeOffset` uses the glyph array to get the index by relying +on the fact that the array is immediately after the `idRangeOffset` +table in the font file. So, the segment’s offset is `idRangeOffset[i]` +but since the `idRangeOffset` table contains words and not bytes, the +value is divided by 2. + +``` {.prettyprint} +glyphIndex = *(&idRangeOffset[i] + idRangeOffset[i] / 2 + (c - startCode[i])) +``` + +`idDelta[i]` is another kind of segment offset used when +`idRangeOffset[i] = 0`, in which case it is added directly to the +character code. + +``` {.prettyprint} +glyphIndex = idDelta[i] + c +``` + +### Class Hierarchy + +`CMapTable` is the main class and the container for all other CMap +related classes. + +#### Utility classes + +- `CMapTable::CMapId` describes a pair of IDs, platform ID and + encoding ID that form the CMaps ID. The ID a CMap has is usually a + good indicator as to what kind of format the CMap uses (Unicode + CMaps are usually either format 4 or format 12). +- `CMapTable::CMapIdComparator` +- `CMapTable::CMapIterator` iteration through the CMapTable is + supported through a Java-style iterator. +- `CMapTable::CMapFilter` Java-style filter; CMapIterator supports + filtering CMaps. By default, it accepts everything CMap. +- `CMapTable::CMapIdFilter` extends CMapFilter; only accepts one type + of CMap. Used in conjunction with CMapIterator, this is how the CMap + getters are implemented. +- **`CMapTable::Builder`** is the only way to create a CMapTable. + +#### CMaps + +- **`CMapTable::CMap`** is the abstract base class that all + `CMapFormat*` derive. It defines basic functions and the abstract + `CMapTable::CMap::CharacterIterator` class to iterate through the + characters in the map. The basic implementation just loops through + every character between a start and an end. This is overridden so + that format specific iteration is performed. +- `CMapFormat0` (mostly done?) +- `CMapFormat2` (needs builders) +- ... coming soon + +`[todo: will add images soon; need to upload to svn]` + +------------------------------------------------------------------------ + +# Table Building Pipeline + +Building a data table in sfntly is done by the +`FontDataTable::Builder::build` method which defines the general +pipeline and leaves the details to each implementing subclass +(`CMapTable::Builder` for example). Note: **`sub*`** methods are table +specific + +**`ReadableFontDataPtr data = internalReadData()`** +> There are 2 private fields in the `FontDataTable::Builder` class: +> `rData` and `wData` for `ReadableFontData` and `WritableFontData`. +> This function returns `rData` if there is any or `wData` (it is cast +> to readable font data) if `rData` is null. *They hold the same data!* + +**`if (model_changed_)`** +> A font is essentially a binary blob when loaded inside a `FontData` +> object. A *model* is the Java/C++ collection of objects that represent +> the same data in a manipulable format. If you ask for the model (even +> if you dont write to it), it will count as changed and the underlying +> raw data will get updated. + +**`if (!subReadyToSerialize())`** +**`return NULL`** +`else` +1. **`size = subDataToSerialize()`** +2. **`WritableDataPtr new_data = container_->getNewData(size)`** +3. **`subSerialize(new_data)`** +4. **`data = new_data`** + +**`FontDataTablePtr table = subBuildTable(data)`** +> The table is actually built, where `subBuildTable` is overridden by +> every class of table but a table header is always added. + +Subtable Builders +------------------------------------------------------------------------------ + +Subtables are lazily built + +When creating the object view of the font and dealing with lots of +tables, it would be wasteful to create builders for every subtable there +is since most users only do fairly high level manipulation of the font. +Instead, **only the tables at font level are fully built**. + +All other subtables have builders that contain valid FontData but the +object view is not created by default. For the `CMapTable`, this means +that if you don’t go through the `getCMapBuilders()` method, the CMap +builders are not initialized. So, the builder map would seem to be empty +when calling its `size()` method but there are CMaps in the font when +calling `numCMaps(internalReadFont())`. + +------------------------------------------------------------------------ + +Character encoders +--------------------------------------------------------------------------------- + +Sfntly/Java uses a native ICU-based API for encoding characters. +Sfntly/C++ uses ICU directly. In unit tests we assume text is encoded in +UTF16. Public APIs will use ICU classes like `UnicodeString`. diff --git a/doc/Useful_links.md b/doc/Useful_links.md new file mode 100644 index 0000000..2caa409 --- /dev/null +++ b/doc/Useful_links.md @@ -0,0 +1,25 @@ +Wiki + +- TrueType + [http://en.wikipedia.org/wiki/TrueType](http://en.wikipedia.org/wiki/TrueType) +- OpenType + [http://en.wikipedia.org/wiki/OpenType](http://en.wikipedia.org/wiki/OpenType) + +Microsoft Typography +[http://www.microsoft.com/typography/default.mspx](http://www.microsoft.com/typography/default.mspx) + +- Font specifications + [http://www.microsoft.com/typography/SpecificationsOverview.mspx](http://www.microsoft.com/typography/SpecificationsOverview.mspx), + including OpenType and TrueType. +- Font Tools + [http://www.microsoft.com/typography/tools/tools.aspx](http://www.microsoft.com/typography/tools/tools.aspx) + +Apple + +- TrueType reference manual + [http://developer.apple.com/fonts/TTRefMan](http://developer.apple.com/fonts/TTRefMan) + +Adobe + +- OpenType + [http://www.adobe.com/type/opentype/](http://www.adobe.com/type/opentype/) diff --git a/doc/build_cpp.md b/doc/build_cpp.md new file mode 100644 index 0000000..5e3d344 --- /dev/null +++ b/doc/build_cpp.md @@ -0,0 +1,150 @@ +# How to build sfntly C++ port + +## Build Environment Requirements + +* cmake 2.6 or above +* C++ compiler requirement + * Windows: Visual C++ 2008, Visual C++ 2010 + * Linux: g++ 4.3 or above. + g++ must support built-in atomic ops and has companion libstd++. + * Mac: Apple XCode 3.2.5 or above. + +## External Dependencies + +sfntly is dependent on several external packages. + +* [Google C++ Testing Framework](https://github.com/google/googletest) + + You can download the package yourself or extract the one from `ext/redist`. + The package needs to be extracted to ext and rename/symbolic link to `gtest`. + + sfntly C++ port had been tested with gTest 1.6.0. + +* ICU + + For Linux, default ICU headers in system will be used. + Linux users please make sure you have dev packages for ICU. + For example, you can run `sudo apt-get install libicu-dev` in Ubuntu and see if the required library is installed. + + For Windows, download from http://site.icu-project.org/download or extract the one from `ext/redist`. + You can also provide your own ICU package. + However, you need to alter the include path, library path, and provide `icudt.dll`. + + Tested with ICU 4.6.1 binary release. + + For Mac users, please download ICU source tarball from http://site.icu-project.org/download + and install according to ICU documents. + +## Getting the Source + +Clone the Git repository from https://github.com/googlei18n/sfntly. + +## Building on Windows + +Let's assume your folder for sfntly is `d:\src\sfntly`. + +1. If you don't have cmake installed, extract the cmake-XXX.zip + into `d:\src\sfntly\cpp\ext\cmake` removing the "-XXX" part. + The extracted binary should be in `d:\src\sfntly\cpp\ext\cmake\bin\cmake.exe`. +2. Extract gtest-XXX.zip into `d:\src\sfntly\cpp\ext\gtest` + removing the "-XXX" part. +3. Extract icu4c-XXX.zip into `d:\src\sfntly\cpp\ext\icu` + removing the "-XXX" part. +4. Run the following commands to create the Visual Studio solution files: + + ``` + d: + cd d:\src\sfntly\cpp + md build + cd build + ..\ext\cmake\bin\cmake .. + ``` + +You should see `sfntly.sln` in `d:\src\sfntly\cpp\build`. + +5. Until the test is modified to access the fonts in the `ext\data` directory: + copy the test fonts from `d:\src\sfntly\cpp\data\ext\` to `d:\src\sfntly\cpp\build\bin\Debug`. +6. Open sfntly.sln. + Since sfntly use STL extensively, please patch your Visual Studio for any STL-related hotfixes/service packs. +7. Build the solution (if the icuuc dll is not found, + you may need to add `d:\src\sfntly\cpp\ext\icu\bin` to the system path). + +### Building on Windows via Command Line + +Visual Studio 2008 and 2010 support command line building, +therefore you dont need the IDE to build the project. + +For Visual Studio 2008 (assume its installed at `c:\vs08`) + + cd d:\src\sfntly\cpp\build + ..\ext\cmake\bin\cmake .. -G "Visual Studio 9 2008" + c:\vs08\common7\tools\vsvars32.bat + vcbuild sfntly.sln + +We invoke the cmake with `-G` to make sure +Visual Studio 2008 solution/project files are generated. +You can also use `devenv sfntly.sln /build` +to build the solution instead of using `vcbuild`. + +There are subtle differences between `devenv` and `vcbuild`. +Please refer to your Visual Studio manual for more details. + +For Visual Studio 2010 (assume its installed at `c:\vs10`) + + + cd d:\src\sfntly\cpp\build + ..\ext\cmake\bin\cmake .. -G "Visual Studio 10" + c:\vs10\common7\tools\vsvars32.bat + msbuild sfntly.sln + +If you install both Visual Studio 2008 and 2010 on your system, +you cant run the scripts above in the same Command Prompt window. +`vsvars32.bat` assumes that it is run from a clean Command Prompt. + +## Building on Linux/Mac + +### Recommended Out-of-Source Building + +1. `cd` *<sfntly dir>* +2. `mkdir build` +3. `cd build` +4. `cmake ..` +5. `make` + +### Default In-Source Building + +> This is not recommended. +> Please use out-of-source whenever possible. + +1. `cd` *<sfntly dir>* +2. `cmake .` +3. `make` + +### Using clang Instead + +Change the `cmake` command line to + + CC=clang CXX=clang++ cmake .. + +The generated Makefile will use clang. +Please note that sfntly uses a lot of advanced C++ semantics that +might not be understood or compiled correctly by earlier versions +of clang (2.8 and before). + +sfntly is tested to compile and run correctly on clang 3.0 (trunk 135314). +clang 2.9 might work but unfortunately we dont have the resource to test it. + +### Debug and Release Builds + +Currently Debug builds are set as default. +To build Release builds, you can either modify the `CMakeList.txt`, +or set environment variable `CMAKE_BUILD_TYPE` to `Release` +before invoking `cmake`. + +Windows users can just switch the configuration in Visual Studio. + +## Running Unit Test + +A program named `unit_test` will be generated after a full compilation. +It expects fonts in `data/ext` to be in the same directory it resides to execute the unit tests. +Windows users also needs to copy `icudt.dll` and `icuuc.dll` to that directory. diff --git a/doc/smart_pointer_usage.md b/doc/smart_pointer_usage.md new file mode 100644 index 0000000..5f77013 --- /dev/null +++ b/doc/smart_pointer_usage.md @@ -0,0 +1,145 @@ +Usage of smart pointers in sfntly C++ port +========================================================================================================================================================= + +In sfntly C++ port, an object ref-counting and smart pointer mechanism +is implemented. The implementation works very much like COM. + +Ref-countable object type inherits from RefCounted<>, which have +addRef() and release() just like IUnknown in COM (but no +QueryInterface). Ptr<> is a smart pointer class like +CComPtr<> which is used to hold the ref-countable objects so that +the object ref count is handled correctly. + +Lets take a look at the example: + +``` {.prettyprint} +class Foo : public RefCounted<Foo> { + public: + static Foo* CreateInstance() { + Ptr<Foo> obj = new Foo(); // ref count = 1 + return obj.detach(); // Giving away the control of this instance. + } +}; +typedef Ptr<Foo> FooPtr; // Common short-hand notation. + +FooPtr obj; +obj.attach(Foo::CreateInstance()); // ref count = 1 + // Take over control but not bumping + // ref count. +{ + FooPtr obj2 = obj; // ref count = 2 + // Assignment bumps up ref count. +} // ref count = 1 + // obj2 out of scope, decrements ref count + +obj.release(); // ref count = 0, object destroyed +``` + +Notes on usage +--------------------------------------------------------------------- + +- Virtual inherit from RefCount interface in base class if smart + pointers are going to be defined. + +<!-- --> + +- All RefCounted objects must be instantiated on the heap. Allocating + the object on stack will cause crash. + +<!-- --> + +- Be careful when you have complex inheritance. For example, + +> In this case the smart pointer is pretty dumb and dont count on it to +> nicely destroy your objects as designed. Try refactor your code like +> +> ``` {.prettyprint} +> class I; // the common interface and implementations +> class A : public I, public RefCounted<A>; // A specific implementation +> class B : public I, public RefCounted<B>; // B specific implementation +> ``` + +- Smart pointers here are very bad candidates for function parameters + and return values. Use dumb pointers when passing over the stack. + +<!-- --> + +- When down\_cast is performed on a dangling pointer due to bugs in + code, VC++ will generate SEH which is not handled well in VC++ + debugger. One can use WinDBG to run it and get the faulting stack. + +<!-- --> + +- Idioms for heap object as return value + +> If you are not passing that object back, you are the end of scope. + +> Be very careful when using the assignment operator as opposed to +> attaching. This can easily cause memory leaks. Have a look at [The +> difference between assignment and attachment with ATL smart +> pointers](http://blogs.msdn.com/b/oldnewthing/archive/2009/11/20/9925918.aspx). +> Since were using essentially the same model, it applies in pretty much +> the same way. The easiest way of knowing when to Attach and when to +> assign is to check the declaration of the function you are using. +> +> ``` {.prettyprint} +> // Attach to the pointer returned by GetInstance +> static CALLER_ATTACH FontFactory* GetInstance(); +> +> // Assign pointer returned by NewCMapBuilder +> CMap::Builder* NewCMapBuilder(const CMapId& cmap_id, +> ReadableFontData* data); +> ``` + +Detecting Memory Leak +------------------------------------------------------------------------------------------ + +> The implementation of COM-like ref-counting and smart pointer remedies +> the lack of garbage collector in C++ to certain extent, however, it +> also introduces other problems. The most common one is memory leakage. +> How do we know that our code leak memory or not? + +- For Linux/Mac, valgrind + [http://valgrind.org](http://valgrind.org/) + is very useful. +- For Windows, the easiest is to use Visual C++ built-in CRT debugging + [http://msdn.microsoft.com/en-us/library/x98tx3cf(v=vs.80).aspx](http://msdn.microsoft.com/en-us/library/x98tx3cf(v=vs.80).aspx) + +Useful Tips for Debugging Ref-Couting Issue +------------------------------------------------------------------------------------------------------------------------------------------------------------ + +- Define `ENABLE_OBJECT_COUNTER` and `REF_COUNT_DEBUGGING`. All + ref-count related activity will be ouput to stderr. + +<!-- --> + +- The logs will look like (under VC2010) + +> Use your favorite editor to transform them into SQL statements, e.g. +> Regex pattern +> +> ``` {.prettyprint} +> ^([ACDR]) class RefCounted<class sfntly::([A-Za-z0-9:]+)>[ *const]+:oc=([-0-9]+),oid=([0-9]+),rc=([-0-9]+) +> ``` + +> Replace to +> +> ``` {.prettyprint} +> insert into log values(\1, \2, \3, \4, \5); +> ``` + +- Add one line to the beginning of log + +<!-- --> + +- Run sqlite shell, use .read to input the SQL file. + +<!-- --> + +- Run following commands to get the leaking object class and object + id: + +<!-- --> + +- Once you know which object is leaking, its much easier to setup + conditional breakpoints to identify the real culprit. diff --git a/doc/unit_tests.md b/doc/unit_tests.md new file mode 100644 index 0000000..0426979 --- /dev/null +++ b/doc/unit_tests.md @@ -0,0 +1,32 @@ +[]{#Unit_Test}Unit Test[](#Unit_Test){.section_anchor} +====================================================== + +sfntly C++ port uses Google testing framework for unit testing. + +All test cases are under src/test. + +To run the unit test, you need to compile sfntly first, then copy +Tuffy.ttf from data/ext to the folder that unit\_test(.exe) is located. +Run the unit\_test. + +If you are only interested in one test case, for example, you are +working on name table and only wants name editing test, you can use the +gtest\_filter flag in command line. + +``` {.prettyprint} +unit_test --gtest_filter=NameEditing.* +``` + +For more info regarding running a subset of gtest, please see [GTest +Advanced +Guide](http://code.google.com/p/googletest/wiki/V1_6_AdvancedGuide). + +Its strongly suggested to run unit\_tests with valgrind. The following +example shows a typical test command + +``` {.prettyprint} +valgrind --leak-check=full -v ./unit_test --gtest_filter=*.*-FontData.* +``` + +FontData tests are the longest and you may want to bypass them during +development. They shall be run in bots, however. |