From 1156e2f0d3197f66ee93d1db399aebbabce797cf Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Tue, 30 Oct 2012 11:04:06 +0530 Subject: [PATCH] Import sfntly into the calibre source tree --- src/sfntly/COPYING.txt | 203 +++ src/sfntly/src/sfntly/data/byte_array.cc | 199 +++ src/sfntly/src/sfntly/data/byte_array.h | 201 +++ src/sfntly/src/sfntly/data/font_data.cc | 82 ++ src/sfntly/src/sfntly/data/font_data.h | 135 ++ .../src/sfntly/data/font_input_stream.cc | 141 ++ .../src/sfntly/data/font_input_stream.h | 97 ++ .../src/sfntly/data/font_output_stream.cc | 130 ++ .../src/sfntly/data/font_output_stream.h | 79 + .../sfntly/data/growable_memory_byte_array.cc | 82 ++ .../sfntly/data/growable_memory_byte_array.h | 66 + .../src/sfntly/data/memory_byte_array.cc | 93 ++ .../src/sfntly/data/memory_byte_array.h | 81 ++ .../src/sfntly/data/readable_font_data.cc | 336 +++++ .../src/sfntly/data/readable_font_data.h | 308 ++++ .../src/sfntly/data/writable_font_data.cc | 201 +++ .../src/sfntly/data/writable_font_data.h | 211 +++ src/sfntly/src/sfntly/font.cc | 557 +++++++ src/sfntly/src/sfntly/font.h | 352 +++++ src/sfntly/src/sfntly/font_factory.cc | 214 +++ src/sfntly/src/sfntly/font_factory.h | 140 ++ src/sfntly/src/sfntly/math/fixed1616.h | 41 + src/sfntly/src/sfntly/math/font_math.h | 49 + src/sfntly/src/sfntly/port/atomic.h | 71 + src/sfntly/src/sfntly/port/config.h | 28 + src/sfntly/src/sfntly/port/endian.h | 77 + src/sfntly/src/sfntly/port/exception_type.h | 125 ++ .../src/sfntly/port/file_input_stream.cc | 169 +++ .../src/sfntly/port/file_input_stream.h | 57 + src/sfntly/src/sfntly/port/input_stream.h | 49 + src/sfntly/src/sfntly/port/java_iterator.h | 94 ++ src/sfntly/src/sfntly/port/lock.cc | 72 + src/sfntly/src/sfntly/port/lock.h | 76 + .../src/sfntly/port/memory_input_stream.cc | 147 ++ .../src/sfntly/port/memory_input_stream.h | 57 + .../src/sfntly/port/memory_output_stream.cc | 72 + .../src/sfntly/port/memory_output_stream.h | 51 + src/sfntly/src/sfntly/port/output_stream.h | 46 + src/sfntly/src/sfntly/port/refcount.h | 277 ++++ src/sfntly/src/sfntly/port/type.h | 102 ++ .../sfntly/table/bitmap/big_glyph_metrics.cc | 171 +++ .../sfntly/table/bitmap/big_glyph_metrics.h | 96 ++ .../src/sfntly/table/bitmap/bitmap_glyph.cc | 101 ++ .../src/sfntly/table/bitmap/bitmap_glyph.h | 119 ++ .../sfntly/table/bitmap/bitmap_glyph_info.cc | 68 + .../sfntly/table/bitmap/bitmap_glyph_info.h | 85 ++ .../sfntly/table/bitmap/bitmap_size_table.cc | 604 ++++++++ .../sfntly/table/bitmap/bitmap_size_table.h | 173 +++ .../table/bitmap/composite_bitmap_glyph.cc | 109 ++ .../table/bitmap/composite_bitmap_glyph.h | 75 + .../src/sfntly/table/bitmap/ebdt_table.cc | 236 +++ .../src/sfntly/table/bitmap/ebdt_table.h | 108 ++ .../src/sfntly/table/bitmap/eblc_table.cc | 313 ++++ .../src/sfntly/table/bitmap/eblc_table.h | 194 +++ .../src/sfntly/table/bitmap/ebsc_table.cc | 107 ++ .../src/sfntly/table/bitmap/ebsc_table.h | 101 ++ .../src/sfntly/table/bitmap/glyph_metrics.cc | 39 + .../src/sfntly/table/bitmap/glyph_metrics.h | 43 + .../sfntly/table/bitmap/index_sub_table.cc | 278 ++++ .../src/sfntly/table/bitmap/index_sub_table.h | 178 +++ .../table/bitmap/index_sub_table_format1.cc | 299 ++++ .../table/bitmap/index_sub_table_format1.h | 116 ++ .../table/bitmap/index_sub_table_format2.cc | 272 ++++ .../table/bitmap/index_sub_table_format2.h | 106 ++ .../table/bitmap/index_sub_table_format3.cc | 295 ++++ .../table/bitmap/index_sub_table_format3.h | 113 ++ .../table/bitmap/index_sub_table_format4.cc | 381 +++++ .../table/bitmap/index_sub_table_format4.h | 135 ++ .../table/bitmap/index_sub_table_format5.cc | 344 +++++ .../table/bitmap/index_sub_table_format5.h | 118 ++ .../table/bitmap/simple_bitmap_glyph.cc | 45 + .../sfntly/table/bitmap/simple_bitmap_glyph.h | 44 + .../table/bitmap/small_glyph_metrics.cc | 126 ++ .../sfntly/table/bitmap/small_glyph_metrics.h | 79 + .../sfntly/table/byte_array_table_builder.cc | 70 + .../sfntly/table/byte_array_table_builder.h | 53 + .../src/sfntly/table/core/cmap_table.cc | 1288 +++++++++++++++++ src/sfntly/src/sfntly/table/core/cmap_table.h | 711 +++++++++ .../sfntly/table/core/font_header_table.cc | 265 ++++ .../src/sfntly/table/core/font_header_table.h | 168 +++ .../core/horizontal_device_metrics_table.cc | 124 ++ .../core/horizontal_device_metrics_table.h | 82 ++ .../table/core/horizontal_header_table.cc | 213 +++ .../table/core/horizontal_header_table.h | 111 ++ .../table/core/horizontal_metrics_table.cc | 138 ++ .../table/core/horizontal_metrics_table.h | 87 ++ .../table/core/maximum_profile_table.cc | 240 +++ .../sfntly/table/core/maximum_profile_table.h | 120 ++ .../src/sfntly/table/core/name_table.cc | 721 +++++++++ src/sfntly/src/sfntly/table/core/name_table.h | 744 ++++++++++ src/sfntly/src/sfntly/table/core/os2_table.cc | 608 ++++++++ src/sfntly/src/sfntly/table/core/os2_table.h | 508 +++++++ .../src/sfntly/table/font_data_table.cc | 193 +++ src/sfntly/src/sfntly/table/font_data_table.h | 123 ++ .../src/sfntly/table/generic_table_builder.cc | 49 + .../src/sfntly/table/generic_table_builder.h | 42 + src/sfntly/src/sfntly/table/header.cc | 66 + src/sfntly/src/sfntly/table/header.h | 114 ++ src/sfntly/src/sfntly/table/subtable.cc | 64 + src/sfntly/src/sfntly/table/subtable.h | 73 + .../sfntly/table/subtable_container_table.h | 48 + src/sfntly/src/sfntly/table/table.cc | 162 +++ src/sfntly/src/sfntly/table/table.h | 119 ++ .../sfntly/table/table_based_table_builder.cc | 69 + .../sfntly/table/table_based_table_builder.h | 48 + .../src/sfntly/table/truetype/glyph_table.cc | 679 +++++++++ .../src/sfntly/table/truetype/glyph_table.h | 335 +++++ .../src/sfntly/table/truetype/loca_table.cc | 246 ++++ .../src/sfntly/table/truetype/loca_table.h | 183 +++ src/sfntly/src/sfntly/tag.cc | 110 ++ src/sfntly/src/sfntly/tag.h | 123 ++ .../tools/subsetter/glyph_table_subsetter.cc | 90 ++ .../tools/subsetter/glyph_table_subsetter.h | 37 + .../src/sfntly/tools/subsetter/subsetter.cc | 102 ++ .../src/sfntly/tools/subsetter/subsetter.h | 72 + .../sfntly/tools/subsetter/table_subsetter.h | 39 + .../tools/subsetter/table_subsetter_impl.cc | 38 + .../tools/subsetter/table_subsetter_impl.h | 37 + 118 files changed, 20751 insertions(+) create mode 100644 src/sfntly/COPYING.txt create mode 100644 src/sfntly/src/sfntly/data/byte_array.cc create mode 100644 src/sfntly/src/sfntly/data/byte_array.h create mode 100644 src/sfntly/src/sfntly/data/font_data.cc create mode 100644 src/sfntly/src/sfntly/data/font_data.h create mode 100644 src/sfntly/src/sfntly/data/font_input_stream.cc create mode 100644 src/sfntly/src/sfntly/data/font_input_stream.h create mode 100644 src/sfntly/src/sfntly/data/font_output_stream.cc create mode 100644 src/sfntly/src/sfntly/data/font_output_stream.h create mode 100644 src/sfntly/src/sfntly/data/growable_memory_byte_array.cc create mode 100644 src/sfntly/src/sfntly/data/growable_memory_byte_array.h create mode 100644 src/sfntly/src/sfntly/data/memory_byte_array.cc create mode 100644 src/sfntly/src/sfntly/data/memory_byte_array.h create mode 100644 src/sfntly/src/sfntly/data/readable_font_data.cc create mode 100644 src/sfntly/src/sfntly/data/readable_font_data.h create mode 100644 src/sfntly/src/sfntly/data/writable_font_data.cc create mode 100644 src/sfntly/src/sfntly/data/writable_font_data.h create mode 100644 src/sfntly/src/sfntly/font.cc create mode 100644 src/sfntly/src/sfntly/font.h create mode 100644 src/sfntly/src/sfntly/font_factory.cc create mode 100644 src/sfntly/src/sfntly/font_factory.h create mode 100644 src/sfntly/src/sfntly/math/fixed1616.h create mode 100644 src/sfntly/src/sfntly/math/font_math.h create mode 100644 src/sfntly/src/sfntly/port/atomic.h create mode 100644 src/sfntly/src/sfntly/port/config.h create mode 100644 src/sfntly/src/sfntly/port/endian.h create mode 100644 src/sfntly/src/sfntly/port/exception_type.h create mode 100644 src/sfntly/src/sfntly/port/file_input_stream.cc create mode 100644 src/sfntly/src/sfntly/port/file_input_stream.h create mode 100644 src/sfntly/src/sfntly/port/input_stream.h create mode 100644 src/sfntly/src/sfntly/port/java_iterator.h create mode 100644 src/sfntly/src/sfntly/port/lock.cc create mode 100644 src/sfntly/src/sfntly/port/lock.h create mode 100755 src/sfntly/src/sfntly/port/memory_input_stream.cc create mode 100755 src/sfntly/src/sfntly/port/memory_input_stream.h create mode 100644 src/sfntly/src/sfntly/port/memory_output_stream.cc create mode 100644 src/sfntly/src/sfntly/port/memory_output_stream.h create mode 100644 src/sfntly/src/sfntly/port/output_stream.h create mode 100644 src/sfntly/src/sfntly/port/refcount.h create mode 100644 src/sfntly/src/sfntly/port/type.h create mode 100644 src/sfntly/src/sfntly/table/bitmap/big_glyph_metrics.cc create mode 100644 src/sfntly/src/sfntly/table/bitmap/big_glyph_metrics.h create mode 100644 src/sfntly/src/sfntly/table/bitmap/bitmap_glyph.cc create mode 100644 src/sfntly/src/sfntly/table/bitmap/bitmap_glyph.h create mode 100644 src/sfntly/src/sfntly/table/bitmap/bitmap_glyph_info.cc create mode 100644 src/sfntly/src/sfntly/table/bitmap/bitmap_glyph_info.h create mode 100644 src/sfntly/src/sfntly/table/bitmap/bitmap_size_table.cc create mode 100644 src/sfntly/src/sfntly/table/bitmap/bitmap_size_table.h create mode 100644 src/sfntly/src/sfntly/table/bitmap/composite_bitmap_glyph.cc create mode 100644 src/sfntly/src/sfntly/table/bitmap/composite_bitmap_glyph.h create mode 100644 src/sfntly/src/sfntly/table/bitmap/ebdt_table.cc create mode 100644 src/sfntly/src/sfntly/table/bitmap/ebdt_table.h create mode 100644 src/sfntly/src/sfntly/table/bitmap/eblc_table.cc create mode 100644 src/sfntly/src/sfntly/table/bitmap/eblc_table.h create mode 100644 src/sfntly/src/sfntly/table/bitmap/ebsc_table.cc create mode 100644 src/sfntly/src/sfntly/table/bitmap/ebsc_table.h create mode 100644 src/sfntly/src/sfntly/table/bitmap/glyph_metrics.cc create mode 100644 src/sfntly/src/sfntly/table/bitmap/glyph_metrics.h create mode 100644 src/sfntly/src/sfntly/table/bitmap/index_sub_table.cc create mode 100644 src/sfntly/src/sfntly/table/bitmap/index_sub_table.h create mode 100644 src/sfntly/src/sfntly/table/bitmap/index_sub_table_format1.cc create mode 100644 src/sfntly/src/sfntly/table/bitmap/index_sub_table_format1.h create mode 100644 src/sfntly/src/sfntly/table/bitmap/index_sub_table_format2.cc create mode 100644 src/sfntly/src/sfntly/table/bitmap/index_sub_table_format2.h create mode 100644 src/sfntly/src/sfntly/table/bitmap/index_sub_table_format3.cc create mode 100644 src/sfntly/src/sfntly/table/bitmap/index_sub_table_format3.h create mode 100644 src/sfntly/src/sfntly/table/bitmap/index_sub_table_format4.cc create mode 100644 src/sfntly/src/sfntly/table/bitmap/index_sub_table_format4.h create mode 100644 src/sfntly/src/sfntly/table/bitmap/index_sub_table_format5.cc create mode 100644 src/sfntly/src/sfntly/table/bitmap/index_sub_table_format5.h create mode 100644 src/sfntly/src/sfntly/table/bitmap/simple_bitmap_glyph.cc create mode 100644 src/sfntly/src/sfntly/table/bitmap/simple_bitmap_glyph.h create mode 100644 src/sfntly/src/sfntly/table/bitmap/small_glyph_metrics.cc create mode 100644 src/sfntly/src/sfntly/table/bitmap/small_glyph_metrics.h create mode 100644 src/sfntly/src/sfntly/table/byte_array_table_builder.cc create mode 100644 src/sfntly/src/sfntly/table/byte_array_table_builder.h create mode 100644 src/sfntly/src/sfntly/table/core/cmap_table.cc create mode 100644 src/sfntly/src/sfntly/table/core/cmap_table.h create mode 100644 src/sfntly/src/sfntly/table/core/font_header_table.cc create mode 100644 src/sfntly/src/sfntly/table/core/font_header_table.h create mode 100644 src/sfntly/src/sfntly/table/core/horizontal_device_metrics_table.cc create mode 100644 src/sfntly/src/sfntly/table/core/horizontal_device_metrics_table.h create mode 100644 src/sfntly/src/sfntly/table/core/horizontal_header_table.cc create mode 100644 src/sfntly/src/sfntly/table/core/horizontal_header_table.h create mode 100644 src/sfntly/src/sfntly/table/core/horizontal_metrics_table.cc create mode 100644 src/sfntly/src/sfntly/table/core/horizontal_metrics_table.h create mode 100644 src/sfntly/src/sfntly/table/core/maximum_profile_table.cc create mode 100644 src/sfntly/src/sfntly/table/core/maximum_profile_table.h create mode 100644 src/sfntly/src/sfntly/table/core/name_table.cc create mode 100644 src/sfntly/src/sfntly/table/core/name_table.h create mode 100644 src/sfntly/src/sfntly/table/core/os2_table.cc create mode 100644 src/sfntly/src/sfntly/table/core/os2_table.h create mode 100644 src/sfntly/src/sfntly/table/font_data_table.cc create mode 100644 src/sfntly/src/sfntly/table/font_data_table.h create mode 100644 src/sfntly/src/sfntly/table/generic_table_builder.cc create mode 100644 src/sfntly/src/sfntly/table/generic_table_builder.h create mode 100644 src/sfntly/src/sfntly/table/header.cc create mode 100644 src/sfntly/src/sfntly/table/header.h create mode 100644 src/sfntly/src/sfntly/table/subtable.cc create mode 100644 src/sfntly/src/sfntly/table/subtable.h create mode 100644 src/sfntly/src/sfntly/table/subtable_container_table.h create mode 100644 src/sfntly/src/sfntly/table/table.cc create mode 100644 src/sfntly/src/sfntly/table/table.h create mode 100644 src/sfntly/src/sfntly/table/table_based_table_builder.cc create mode 100644 src/sfntly/src/sfntly/table/table_based_table_builder.h create mode 100644 src/sfntly/src/sfntly/table/truetype/glyph_table.cc create mode 100644 src/sfntly/src/sfntly/table/truetype/glyph_table.h create mode 100644 src/sfntly/src/sfntly/table/truetype/loca_table.cc create mode 100644 src/sfntly/src/sfntly/table/truetype/loca_table.h create mode 100644 src/sfntly/src/sfntly/tag.cc create mode 100644 src/sfntly/src/sfntly/tag.h create mode 100644 src/sfntly/src/sfntly/tools/subsetter/glyph_table_subsetter.cc create mode 100644 src/sfntly/src/sfntly/tools/subsetter/glyph_table_subsetter.h create mode 100644 src/sfntly/src/sfntly/tools/subsetter/subsetter.cc create mode 100644 src/sfntly/src/sfntly/tools/subsetter/subsetter.h create mode 100644 src/sfntly/src/sfntly/tools/subsetter/table_subsetter.h create mode 100644 src/sfntly/src/sfntly/tools/subsetter/table_subsetter_impl.cc create mode 100644 src/sfntly/src/sfntly/tools/subsetter/table_subsetter_impl.h diff --git a/src/sfntly/COPYING.txt b/src/sfntly/COPYING.txt new file mode 100644 index 000000000000..c61423cfed52 --- /dev/null +++ b/src/sfntly/COPYING.txt @@ -0,0 +1,203 @@ + + 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. + diff --git a/src/sfntly/src/sfntly/data/byte_array.cc b/src/sfntly/src/sfntly/data/byte_array.cc new file mode 100644 index 000000000000..915a40c03571 --- /dev/null +++ b/src/sfntly/src/sfntly/data/byte_array.cc @@ -0,0 +1,199 @@ +/* + * 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. + */ + +#include "sfntly/data/byte_array.h" + +#include + +#include "sfntly/port/exception_type.h" + +namespace sfntly { + +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(filled_length, storage_length_); + return filled_length_; +} + +int32_t ByteArray::Get(int32_t index) { + return InternalGet(index) & 0xff; +} + +int32_t ByteArray::Get(int32_t index, ByteVector* b) { + assert(b); + return Get(index, &((*b)[0]), 0, b->size()); +} + +int32_t ByteArray::Get(int32_t index, + byte_t* b, + int32_t offset, + int32_t length) { + assert(b); + if (index < 0 || index >= filled_length_) { + return 0; + } + int32_t actual_length = std::min(length, filled_length_ - index); + return InternalGet(index, b, offset, actual_length); +} + +void ByteArray::Put(int32_t index, byte_t b) { + if (index < 0 || index >= Size()) { +#if defined (SFNTLY_NO_EXCEPTION) + return; +#else + throw IndexOutOfBoundException( + "Attempt to write outside the bounds of the data"); +#endif + } + InternalPut(index, b); + filled_length_ = std::max(filled_length_, index + 1); +} + +int32_t ByteArray::Put(int index, ByteVector* b) { + assert(b); + return Put(index, &((*b)[0]), 0, b->size()); +} + +int32_t ByteArray::Put(int32_t index, + byte_t* b, + int32_t offset, + int32_t length) { + assert(b); + if (index < 0 || index >= Size()) { +#if defined (SFNTLY_NO_EXCEPTION) + return 0; +#else + throw IndexOutOfBoundException( + "Attempt to write outside the bounds of the data"); +#endif + } + int32_t actual_length = std::min(length, Size() - index); + int32_t bytes_written = InternalPut(index, b, offset, actual_length); + filled_length_ = std::max(filled_length_, index + bytes_written); + return bytes_written; +} + +int32_t ByteArray::CopyTo(ByteArray* array) { + return CopyTo(array, 0, Length()); +} + +int32_t ByteArray::CopyTo(ByteArray* array, int32_t offset, int32_t length) { + return CopyTo(0, array, offset, length); +} + +int32_t ByteArray::CopyTo(int32_t dst_offset, ByteArray* array, + int32_t src_offset, int32_t length) { + assert(array); + if (array->Size() < dst_offset + length) { // insufficient space + return -1; + } + + ByteVector b(COPY_BUFFER_SIZE); + int32_t bytes_read = 0; + int32_t index = 0; + int32_t remaining_length = length; + int32_t buffer_length = std::min(COPY_BUFFER_SIZE, length); + while ((bytes_read = + Get(index + src_offset, &(b[0]), 0, buffer_length)) > 0) { + int bytes_written = array->Put(index + dst_offset, &(b[0]), 0, bytes_read); + UNREFERENCED_PARAMETER(bytes_written); + index += bytes_read; + remaining_length -= bytes_read; + buffer_length = std::min(b.size(), remaining_length); + } + return index; +} + +int32_t ByteArray::CopyTo(OutputStream* os) { + return CopyTo(os, 0, Length()); +} + +int32_t ByteArray::CopyTo(OutputStream* os, int32_t offset, int32_t length) { + ByteVector b(COPY_BUFFER_SIZE); + int32_t bytes_read = 0; + int32_t index = 0; + int32_t buffer_length = std::min(COPY_BUFFER_SIZE, length); + while ((bytes_read = Get(index + offset, &(b[0]), 0, buffer_length)) > 0) { + os->Write(&b, 0, bytes_read); + index += bytes_read; + buffer_length = std::min(b.size(), length - index); + } + return index; +} + +bool ByteArray::CopyFrom(InputStream* is, int32_t length) { + ByteVector b(COPY_BUFFER_SIZE); + int32_t bytes_read = 0; + int32_t index = 0; + int32_t buffer_length = std::min(COPY_BUFFER_SIZE, length); + while ((bytes_read = is->Read(&b, 0, buffer_length)) > 0) { + if (Put(index, &(b[0]), 0, bytes_read) != bytes_read) { +#if defined (SFNTLY_NO_EXCEPTION) + return 0; +#else + throw IOException("Error writing bytes."); +#endif + } + index += bytes_read; + length -= bytes_read; + buffer_length = std::min(b.size(), length); + } + return true; +} + +bool ByteArray::CopyFrom(InputStream* is) { + ByteVector b(COPY_BUFFER_SIZE); + int32_t bytes_read = 0; + int32_t index = 0; + int32_t buffer_length = COPY_BUFFER_SIZE; + while ((bytes_read = is->Read(&b, 0, buffer_length)) > 0) { + if (Put(index, &b[0], 0, bytes_read) != bytes_read) { +#if defined (SFNTLY_NO_EXCEPTION) + return 0; +#else + throw IOException("Error writing bytes."); +#endif + } + index += bytes_read; + } + return true; +} + +ByteArray::ByteArray(int32_t filled_length, + int32_t storage_length, + bool growable) { + Init(filled_length, storage_length, growable); +} + +ByteArray::ByteArray(int32_t filled_length, int32_t storage_length) { + Init(filled_length, storage_length, false); +} + +void ByteArray::Init(int32_t filled_length, + int32_t storage_length, + bool growable) { + storage_length_ = storage_length; + growable_ = growable; + SetFilledLength(filled_length); +} + +} // namespace sfntly diff --git a/src/sfntly/src/sfntly/data/byte_array.h b/src/sfntly/src/sfntly/data/byte_array.h new file mode 100644 index 000000000000..70dc92f51a87 --- /dev/null +++ b/src/sfntly/src/sfntly/data/byte_array.h @@ -0,0 +1,201 @@ +/* + * Copyright (C) 2011 The sfntly Open Source Project + * + * 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. + */ + +#ifndef SFNTLY_CPP_SRC_SFNTLY_DATA_BYTE_ARRAY_H_ +#define SFNTLY_CPP_SRC_SFNTLY_DATA_BYTE_ARRAY_H_ + +#include "sfntly/port/refcount.h" +#include "sfntly/port/type.h" +#include "sfntly/port/input_stream.h" +#include "sfntly/port/output_stream.h" + +namespace sfntly { + +// An abstraction to a contiguous array of bytes. +// C++ port of this class assumes that the data are stored in a linear region +// like std::vector. +class ByteArray : virtual public RefCount { + public: + virtual ~ByteArray(); + + // Gets the current filled and readable length of the array. + int32_t 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(); + + // Determines whether or not this array is growable or of fixed size. + bool growable() { return growable_; } + + int32_t SetFilledLength(int32_t filled_length); + + // Gets the byte from the given index. + // @param index the index into the byte array + // @return the byte or -1 if reading beyond the bounds of the data + virtual int32_t Get(int32_t index); + + // Gets the bytes from the given index and fill the buffer with them. As many + // bytes as will fit into the buffer are read unless that would go past the + // end of the array. + // @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); + + // 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 + // that would go past the end of the array. + // @param index the index into the byte array + // @param b the buffer to put the bytes read into + // @param offset the location in the buffer to start putting the bytes + // @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, + 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); + + // 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); + + // 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 + // and the array isn't growable. The bytes to be put into the array are those + // in the buffer from the given offset and for the given length. + // @param index the index into the ByteArray + // @param b the bytes to put into the array + // @param offset the offset in the bytes to start copying from + // @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, + int32_t offset, + int32_t length); + + // Fully copies this ByteArray to another ByteArray to the extent that the + // destination array has storage for the data copied. + virtual int32_t CopyTo(ByteArray* array); + + // Copies a segment of this ByteArray to another ByteArray. + // @param array the destination + // @param offset the offset in this ByteArray to start copying from + // @param length the maximum length in bytes to copy + // @return the number of bytes copied + virtual int32_t CopyTo(ByteArray* array, int32_t offset, int32_t length); + + // Copies this ByteArray to another ByteArray. + // @param dstOffset the offset in the destination array to start copying to + // @param array the destination + // @param srcOffset the offset in this ByteArray to start copying from + // @param length the maximum length in bytes to copy + // @return the number of bytes copied + virtual int32_t CopyTo(int32_t dst_offset, + ByteArray* array, + int32_t src_offset, + int32_t length); + + // Copies this ByteArray to an OutputStream. + // @param os the destination + // @return the number of bytes copied + virtual int32_t CopyTo(OutputStream* os); + + // Copies this ByteArray to an OutputStream. + // @param os the destination + // @param offset + // @param length + // @return the number of bytes copied + virtual int32_t CopyTo(OutputStream* os, int32_t offset, int32_t length); + + // Copies from the InputStream into this ByteArray. + // @param is the source + // @param length the number of bytes to copy + virtual bool CopyFrom(InputStream* is, int32_t length); + + // Copies everything from the InputStream into this ByteArray. + // @param is the source + virtual bool CopyFrom(InputStream* is); + + protected: + // filledLength the length that is "filled" and readable counting from offset. + // storageLength the maximum storage size of the underlying data. + // growable is the storage growable - storageLength is the max growable size. + ByteArray(int32_t filled_length, int32_t storage_length, bool growable); + ByteArray(int32_t filled_length, int32_t storage_length); + void Init(int32_t filled_length, int32_t storage_length, bool growable); + + // Internal subclass API + + // 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; + + // Stores the array of bytes at the given index. + // @param index the location to store at + // @param b the bytes to store + // @param offset the offset to start from in the byte array + // @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, + 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; + + // Gets the bytes at the index given of the given length. + // @param index the location to start getting from + // @param b the array to put the bytes into + // @param offset the offset in the array to put the bytes into + // @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, + int32_t offset, + int32_t length) = 0; + + // Close this instance of the ByteArray. + virtual void Close() = 0; + + // C++ port only, raw pointer to the first element of storage. + virtual byte_t* Begin() = 0; + + // Java toString() not ported. + + static const int32_t COPY_BUFFER_SIZE; + + private: + //bool bound_; // unused, comment out + int32_t filled_length_; + int32_t storage_length_; + bool growable_; +}; +typedef Ptr ByteArrayPtr; + +} // namespace sfntly + +#endif // SFNTLY_CPP_SRC_SFNTLY_DATA_BYTE_ARRAY_H_ diff --git a/src/sfntly/src/sfntly/data/font_data.cc b/src/sfntly/src/sfntly/data/font_data.cc new file mode 100644 index 000000000000..d2b95eac1b84 --- /dev/null +++ b/src/sfntly/src/sfntly/data/font_data.cc @@ -0,0 +1,82 @@ +/* + * 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. + */ + +#include +#include +#include + +#include "sfntly/data/font_data.h" + +namespace sfntly { + +int32_t FontData::Size() const { + return std::min(array_->Size() - bound_offset_, bound_length_); +} + +bool FontData::Bound(int32_t offset, int32_t length) { + if (offset + length > Size() || offset < 0 || length < 0) + return false; + + bound_offset_ += offset; + bound_length_ = length; + return true; +} + +bool FontData::Bound(int32_t offset) { +if (offset > Size() || offset < 0) + return false; + + bound_offset_ += offset; + return true; +} + +int32_t FontData::Length() const { + return std::min(array_->Length() - bound_offset_, bound_length_); +} + +FontData::FontData(ByteArray* ba) { + Init(ba); +} + +FontData::FontData(FontData* data, int32_t offset, int32_t length) { + Init(data->array_); + Bound(data->bound_offset_ + offset, length); +} + +FontData::FontData(FontData* data, int32_t offset) { + Init(data->array_); + Bound(data->bound_offset_ + offset, + (data->bound_length_ == GROWABLE_SIZE) + ? GROWABLE_SIZE : data->bound_length_ - offset); +} + +FontData::~FontData() {} + +void FontData::Init(ByteArray* ba) { + array_ = ba; + bound_offset_ = 0; + bound_length_ = GROWABLE_SIZE; +} + +int32_t FontData::BoundOffset(int32_t offset) { + return offset + bound_offset_; +} + +int32_t FontData::BoundLength(int32_t offset, int32_t length) { + return std::min(length, bound_length_ - offset); +} + +} // namespace sfntly diff --git a/src/sfntly/src/sfntly/data/font_data.h b/src/sfntly/src/sfntly/data/font_data.h new file mode 100644 index 000000000000..d02e8b75db2b --- /dev/null +++ b/src/sfntly/src/sfntly/data/font_data.h @@ -0,0 +1,135 @@ +/* + * 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. + */ + +#ifndef SFNTLY_CPP_SRC_SFNTLY_DATA_FONT_DATA_H_ +#define SFNTLY_CPP_SRC_SFNTLY_DATA_FONT_DATA_H_ + +#include + +#include + +#include "sfntly/port/type.h" +#include "sfntly/data/byte_array.h" +#include "sfntly/port/refcount.h" + +namespace sfntly { + +struct DataSize { + enum { + kBYTE = 1, + kCHAR = 1, + kUSHORT = 2, + kSHORT = 2, + kUINT24 = 3, + kULONG = 4, + kLONG = 4, + kFixed = 4, + kFUNIT = 4, + kFWORD = 2, + kUFWORD = 2, + kF2DOT14 = 2, + kLONGDATETIME = 8, + kTag = 4, + kGlyphID = 2, + kOffset = 2 + }; +}; + +class FontData : virtual public RefCount { + public: + // Gets the maximum size of the FontData. This is the maximum number of bytes + // that the font data can hold and all of it may not be filled with data or + // even fully allocated yet. + // @return the maximum size of this font data + virtual int32_t Size() const; + + // Sets limits on the size of the FontData. The FontData is then only + // visible within the bounds set. + // @param offset the start of the new bounds + // @param length the number of bytes in the bounded array + // @return true if the bounding range was successful; false otherwise + virtual bool Bound(int32_t offset, int32_t length); + + // Sets limits on the size of the FontData. This is a offset bound only so if + // the FontData is writable and growable then there is no limit to that growth + // from the bounding operation. + // @param offset the start of the new bounds which must be within the current + // size of the FontData + // @return true if the bounding range was successful; false otherwise + virtual bool Bound(int32_t offset); + + // Makes a slice of this FontData. The returned slice will share the data with + // the original FontData. + // @param offset the start of the slice + // @param length the number of bytes in the slice + // @return a slice of the original FontData + virtual CALLER_ATTACH FontData* Slice(int32_t offset, int32_t length) = 0; + + // Makes a bottom bound only slice of this array. The returned slice will + // share the data with the original FontData. + // @param offset the start of the slice + // @return a slice of the original FontData + virtual CALLER_ATTACH FontData* Slice(int32_t offset) = 0; + + // Gets the length of the data. + virtual int32_t Length() const; + + protected: + // Constructor. + // @param ba the byte array to use for the backing data + explicit FontData(ByteArray* ba); + + // Constructor. + // @param data the data to wrap + // @param offset the offset to start the wrap from + // @param length the length of the data wrapped + FontData(FontData* data, int32_t offset, int32_t length); + + // Constructor. + // @param data the data to wrap + // @param offset the offset to start the wrap from + FontData(FontData* data, int32_t offset); + virtual ~FontData(); + + void Init(ByteArray* ba); + + // Gets the offset in the underlying data taking into account any bounds on + // the data. + // @param offset the offset to get the bound compensated offset for + // @return the bound compensated offset + int32_t BoundOffset(int32_t offset); + + // 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); + + static const int32_t GROWABLE_SIZE = INT_MAX; + + // TODO(arthurhsu): style guide violation: refactor this protected member + ByteArrayPtr array_; + + private: + int32_t bound_offset_; + int32_t bound_length_; +}; +typedef Ptr FontDataPtr; + +} // namespace sfntly + +#endif // SFNTLY_CPP_SRC_SFNTLY_DATA_FONT_DATA_H_ diff --git a/src/sfntly/src/sfntly/data/font_input_stream.cc b/src/sfntly/src/sfntly/data/font_input_stream.cc new file mode 100644 index 000000000000..dcf8be35f9ae --- /dev/null +++ b/src/sfntly/src/sfntly/data/font_input_stream.cc @@ -0,0 +1,141 @@ +/* + * 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. + */ + +#include "sfntly/data/font_input_stream.h" + +#include + +namespace sfntly { + +FontInputStream::FontInputStream(InputStream* is) + : stream_(is), position_(0), length_(0), bounded_(false) { +} + +FontInputStream::FontInputStream(InputStream* is, size_t length) + : stream_(is), position_(0), length_(length), bounded_(true) { +} + +FontInputStream::~FontInputStream() { + // Do not close here, underlying InputStream will close themselves. +} + +int32_t FontInputStream::Available() { + if (stream_) { + return stream_->Available(); + } + return 0; +} + +void FontInputStream::Close() { + if (stream_) { + stream_->Close(); + } +} + +void FontInputStream::Mark(int32_t readlimit) { + if (stream_) { + stream_->Mark(readlimit); + } +} + +bool FontInputStream::MarkSupported() { + if (stream_) { + return stream_->MarkSupported(); + } + return false; +} + +void FontInputStream::Reset() { + if (stream_) { + stream_->Reset(); + } +} + +int32_t FontInputStream::Read() { + if (!stream_ || (bounded_ && position_ >= length_)) { + return -1; + } + int32_t b = stream_->Read(); + if (b >= 0) { + position_++; + } + return b; +} + +int32_t FontInputStream::Read(ByteVector* b, int32_t offset, int32_t length) { + if (!stream_ || offset < 0 || length < 0 || + (bounded_ && position_ >= length_)) { + return -1; + } + int32_t bytes_to_read = + bounded_ ? std::min(length, (int32_t)(length_ - position_)) : + length; + int32_t bytes_read = stream_->Read(b, offset, bytes_to_read); + position_ += bytes_read; + return bytes_read; +} + +int32_t FontInputStream::Read(ByteVector* b) { + return Read(b, 0, b->size()); +} + +int32_t FontInputStream::ReadChar() { + return Read(); +} + +int32_t FontInputStream::ReadUShort() { + return 0xffff & (Read() << 8 | Read()); +} + +int32_t FontInputStream::ReadShort() { + return ((Read() << 8 | Read()) << 16) >> 16; +} + +int32_t FontInputStream::ReadUInt24() { + return 0xffffff & (Read() << 16 | Read() << 8 | Read()); +} + +int64_t FontInputStream::ReadULong() { + return 0xffffffffL & ReadLong(); +} + +int32_t FontInputStream::ReadULongAsInt() { + int64_t ulong = ReadULong(); + return ((int32_t)ulong) & ~0x80000000; +} + +int32_t FontInputStream::ReadLong() { + return Read() << 24 | Read() << 16 | Read() << 8 | Read(); +} + +int32_t FontInputStream::ReadFixed() { + return ReadLong(); +} + +int64_t FontInputStream::ReadDateTimeAsLong() { + return (int64_t)ReadULong() << 32 | ReadULong(); +} + +int64_t FontInputStream::Skip(int64_t n) { + if (stream_) { + int64_t skipped = stream_->Skip(n); + position_ += skipped; + return skipped; + } + return 0; +} + +} // namespace sfntly diff --git a/src/sfntly/src/sfntly/data/font_input_stream.h b/src/sfntly/src/sfntly/data/font_input_stream.h new file mode 100644 index 000000000000..9992b0753f69 --- /dev/null +++ b/src/sfntly/src/sfntly/data/font_input_stream.h @@ -0,0 +1,97 @@ +/* + * 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. + */ + +#ifndef SFNTLY_CPP_SRC_SFNTLY_DATA_FONT_INPUT_STREAM_H_ +#define SFNTLY_CPP_SRC_SFNTLY_DATA_FONT_INPUT_STREAM_H_ + +#include "sfntly/port/type.h" +#include "sfntly/port/input_stream.h" + +namespace sfntly { + +// An input stream for reading font data. +// The data types used are as listed: +// BYTE 8-bit unsigned integer. +// CHAR 8-bit signed integer. +// USHORT 16-bit unsigned integer. +// SHORT 16-bit signed integer. +// UINT24 24-bit unsigned integer. +// ULONG 32-bit unsigned integer. +// LONG 32-bit signed integer. +// Fixed 32-bit signed fixed-point number (16.16) +// FUNIT Smallest measurable distance in the em space. +// FWORD 16-bit signed integer (SHORT) that describes a quantity in FUnits. +// UFWORD 16-bit unsigned integer (USHORT) that describes a quantity in +// FUnits. +// F2DOT14 16-bit signed fixed number with the low 14 bits of fraction (2.14) +// LONGDATETIME Date represented in number of seconds since 12:00 midnight, +// January 1, 1904. The value is represented as a signed 64-bit +// integer. + +// Note: Original class inherits from Java's FilterOutputStream, which wraps +// an InputStream within. In C++, we directly do the wrapping without +// defining another layer of abstraction. The wrapped output stream is +// *NOT* reference counted (because it's meaningless to ref-count an I/O +// stream). +class FontInputStream : public InputStream { + public: + // Constructor. + // @param is input stream to wrap + explicit FontInputStream(InputStream* is); + + // Constructor for a bounded font input stream. + // @param is input stream to wrap + // @param length the maximum length of bytes to read + FontInputStream(InputStream* is, size_t length); + + virtual ~FontInputStream(); + + + virtual int32_t Available(); + virtual void Close(); + virtual void Mark(int32_t readlimit); + virtual bool MarkSupported(); + 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); + + // Get the current position in the stream in bytes. + // @return the current position in bytes + virtual int64_t position() { return position_; } + + virtual int32_t ReadChar(); + virtual int32_t ReadUShort(); + virtual int32_t ReadShort(); + virtual int32_t ReadUInt24(); + virtual int64_t ReadULong(); + virtual int32_t ReadULongAsInt(); + virtual int32_t ReadLong(); + virtual int32_t ReadFixed(); + virtual int64_t ReadDateTimeAsLong(); + virtual int64_t Skip(int64_t n); // n can be negative. + + private: + InputStream* stream_; + int64_t position_; + int64_t length_; // Bound on length of data to read. + bool bounded_; +}; + +} // namespace sfntly + +#endif // SFNTLY_CPP_SRC_SFNTLY_DATA_FONT_INPUT_STREAM_H_ diff --git a/src/sfntly/src/sfntly/data/font_output_stream.cc b/src/sfntly/src/sfntly/data/font_output_stream.cc new file mode 100644 index 000000000000..3422a22827c0 --- /dev/null +++ b/src/sfntly/src/sfntly/data/font_output_stream.cc @@ -0,0 +1,130 @@ +/* + * 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. + */ + +#include "sfntly/data/font_output_stream.h" + +#include + +namespace sfntly { + +FontOutputStream::FontOutputStream(OutputStream* os) + : stream_(os), + position_(0) { +} + +FontOutputStream::~FontOutputStream() { + // Do not close, underlying stream shall clean up themselves. +} + +void FontOutputStream::Write(byte_t b) { + if (stream_) { + stream_->Write(b); + position_++; + } +} + +void FontOutputStream::Write(ByteVector* b) { + if (b) { + Write(b, 0, b->size()); + position_ += b->size(); + } +} + +void FontOutputStream::Write(ByteVector* b, int32_t off, int32_t len) { + assert(b); + assert(stream_); + if (off < 0 || len < 0 || off + len < 0 || + static_cast(off + len) > b->size()) { +#if !defined (SFNTLY_NO_EXCEPTION) + throw IndexOutOfBoundException(); +#else + return; +#endif + } + + stream_->Write(b, off, len); + position_ += len; +} + +void FontOutputStream::Write(byte_t* b, int32_t off, int32_t len) { + assert(b); + assert(stream_); + if (off < 0 || len < 0 || off + len < 0) { +#if !defined (SFNTLY_NO_EXCEPTION) + throw IndexOutOfBoundException(); +#else + return; +#endif + } + + stream_->Write(b, off, len); + position_ += len; +} + +void FontOutputStream::WriteChar(byte_t c) { + Write(c); +} + +void FontOutputStream::WriteUShort(int32_t us) { + Write((byte_t)((us >> 8) & 0xff)); + Write((byte_t)(us & 0xff)); +} + +void FontOutputStream::WriteShort(int32_t s) { + WriteUShort(s); +} + +void FontOutputStream::WriteUInt24(int32_t ui) { + Write((byte_t)(ui >> 16) & 0xff); + Write((byte_t)(ui >> 8) & 0xff); + Write((byte_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)); +} + +void FontOutputStream::WriteLong(int64_t l) { + WriteULong(l); +} + +void FontOutputStream::WriteFixed(int32_t f) { + WriteULong(f); +} + +void FontOutputStream::WriteDateTime(int64_t date) { + WriteULong((date >> 32) & 0xffffffff); + WriteULong(date & 0xffffffff); +} + +void FontOutputStream::Flush() { + if (stream_) { + stream_->Flush(); + } +} + +void FontOutputStream::Close() { + if (stream_) { + stream_->Flush(); + stream_->Close(); + position_ = 0; + } +} + +} // namespace sfntly diff --git a/src/sfntly/src/sfntly/data/font_output_stream.h b/src/sfntly/src/sfntly/data/font_output_stream.h new file mode 100644 index 000000000000..fcd48e8aaa88 --- /dev/null +++ b/src/sfntly/src/sfntly/data/font_output_stream.h @@ -0,0 +1,79 @@ +/* + * 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. + */ + +#ifndef SFNTLY_CPP_SRC_SFNTLY_DATA_FONT_OUTPUT_STREAM_H_ +#define SFNTLY_CPP_SRC_SFNTLY_DATA_FONT_OUTPUT_STREAM_H_ + +#include "sfntly/port/type.h" +#include "sfntly/port/output_stream.h" + +namespace sfntly { + +// An output stream for writing font data. +// The data types used are as listed: +// BYTE 8-bit unsigned integer. +// CHAR 8-bit signed integer. +// USHORT 16-bit unsigned integer. +// SHORT 16-bit signed integer. +// UINT24 24-bit unsigned integer. +// ULONG 32-bit unsigned integer. +// LONG 32-bit signed integer. +// Fixed 32-bit signed fixed-point number (16.16) +// FUNIT Smallest measurable distance in the em space. +// FWORD 16-bit signed integer (SHORT) that describes a quantity in FUnits. +// UFWORD 16-bit unsigned integer (USHORT) that describes a quantity in +// FUnits. +// F2DOT14 16-bit signed fixed number with the low 14 bits of fraction (2.14) +// LONGDATETIME Date represented in number of seconds since 12:00 midnight, +// January 1, 1904. The value is represented as a signed 64-bit +// integer. + +// Note: The wrapped output stream is *NOT* reference counted (because it's +// meaningless to ref-count an I/O stream). +class FontOutputStream : public OutputStream { + public: + 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 WriteUShort(int32_t us); + virtual void WriteShort(int32_t s); + virtual void WriteUInt24(int32_t ui); + virtual void WriteULong(int64_t ul); + virtual void WriteLong(int64_t l); + virtual void WriteFixed(int32_t l); + virtual void WriteDateTime(int64_t date); + + // Note: C++ port only. + virtual void Flush(); + virtual void Close(); + + private: + // Note: we do not use the variable name out as in Java because it has + // special meaning in VC++ and will be very confusing. + OutputStream* stream_; + size_t position_; +}; + +} // namespace sfntly + +#endif // SFNTLY_CPP_SRC_SFNTLY_DATA_FONT_OUTPUT_STREAM_H_ diff --git a/src/sfntly/src/sfntly/data/growable_memory_byte_array.cc b/src/sfntly/src/sfntly/data/growable_memory_byte_array.cc new file mode 100644 index 000000000000..c335614d4de3 --- /dev/null +++ b/src/sfntly/src/sfntly/data/growable_memory_byte_array.cc @@ -0,0 +1,82 @@ +/* + * 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. + */ + +#include "sfntly/data/growable_memory_byte_array.h" + +#include +#include + +#include + +namespace sfntly { + +GrowableMemoryByteArray::GrowableMemoryByteArray() + : ByteArray(0, INT_MAX, true) { + // Note: We did not set an initial size of array like Java because STL + // implementation will determine the best strategy. +} + +GrowableMemoryByteArray::~GrowableMemoryByteArray() {} + +int32_t GrowableMemoryByteArray::CopyTo(OutputStream* os, + int32_t offset, + int32_t length) { + assert(os); + os->Write(&b_, offset, length); + return length; +} + +void GrowableMemoryByteArray::InternalPut(int32_t index, byte_t b) { + if ((size_t)index >= b_.size()) { + b_.resize((size_t)(index + 1)); + } + b_[index] = b; +} + +int32_t GrowableMemoryByteArray::InternalPut(int32_t index, + byte_t* b, + int32_t offset, + int32_t length) { + if ((size_t)index + length >= b_.size()) { + // Note: We grow one byte more than Java version. VC debuggers shows + // data better this way. + b_.resize((size_t)(index + length + 1)); + } + std::copy(b + offset, b + offset + length, b_.begin() + index); + return length; +} + +byte_t GrowableMemoryByteArray::InternalGet(int32_t index) { + return b_[index]; +} + +int32_t GrowableMemoryByteArray::InternalGet(int32_t index, + byte_t* b, + int32_t offset, + int32_t length) { + memcpy(b + offset, &(b_[0]) + index, length); + return length; +} + +void GrowableMemoryByteArray::Close() { + b_.clear(); +} + +byte_t* GrowableMemoryByteArray::Begin() { + return &(b_[0]); +} + +} // namespace sfntly diff --git a/src/sfntly/src/sfntly/data/growable_memory_byte_array.h b/src/sfntly/src/sfntly/data/growable_memory_byte_array.h new file mode 100644 index 000000000000..8583a0d645f4 --- /dev/null +++ b/src/sfntly/src/sfntly/data/growable_memory_byte_array.h @@ -0,0 +1,66 @@ +/* + * 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. + */ + +#ifndef SFNTLY_CPP_SRC_SFNTLY_DATA_GROWABLE_MEMORY_BYTE_ARRAY_H_ +#define SFNTLY_CPP_SRC_SFNTLY_DATA_GROWABLE_MEMORY_BYTE_ARRAY_H_ + +#include "sfntly/data/byte_array.h" + +namespace sfntly { + +// Note: This is not really a port of Java version. Instead, this wraps a +// std::vector inside and let it grow by calling resize(). +class GrowableMemoryByteArray : public ByteArray, + public RefCounted { + public: + GrowableMemoryByteArray(); + virtual ~GrowableMemoryByteArray(); + virtual int32_t CopyTo(OutputStream* os, int32_t offset, int32_t length); + + // Make gcc -Woverloaded-virtual happy. + virtual int32_t CopyTo(ByteArray* array) { return ByteArray::CopyTo(array); } + virtual int32_t CopyTo(ByteArray* array, int32_t offset, int32_t length) { + return ByteArray::CopyTo(array, offset, length); + } + virtual int32_t CopyTo(int32_t dst_offset, + ByteArray* array, + int32_t src_offset, + int32_t length) { + return ByteArray::CopyTo(dst_offset, array, src_offset, length); + } + virtual int32_t CopyTo(OutputStream* os) { return ByteArray::CopyTo(os); } + + protected: + virtual void InternalPut(int32_t index, byte_t b); + virtual int32_t InternalPut(int32_t index, + byte_t* b, + int32_t offset, + int32_t length); + virtual byte_t InternalGet(int32_t index); + virtual int32_t InternalGet(int32_t index, + byte_t* b, + int32_t offset, + int32_t length); + virtual void Close(); + virtual byte_t* Begin(); + + private: + ByteVector b_; +}; + +} // namespace sfntly + +#endif // SFNTLY_CPP_SRC_SFNTLY_DATA_GROWABLE_MEMORY_BYTE_ARRAY_H_ diff --git a/src/sfntly/src/sfntly/data/memory_byte_array.cc b/src/sfntly/src/sfntly/data/memory_byte_array.cc new file mode 100644 index 000000000000..d6c9c4828d32 --- /dev/null +++ b/src/sfntly/src/sfntly/data/memory_byte_array.cc @@ -0,0 +1,93 @@ +/* + * 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. + */ + +#include "sfntly/data/memory_byte_array.h" + +#include + +namespace sfntly { + +MemoryByteArray::MemoryByteArray(int32_t length) + : ByteArray(0, length), b_(NULL), allocated_(true) { +} + +MemoryByteArray::MemoryByteArray(byte_t* b, int32_t filled_length) + : ByteArray(filled_length, filled_length), b_(b), allocated_(false) { + assert(b); +} + +MemoryByteArray::~MemoryByteArray() { + Close(); +} + +int32_t MemoryByteArray::CopyTo(OutputStream* os, + int32_t offset, + int32_t length) { + assert(os); + os->Write(b_, offset, length); + return length; +} + +void MemoryByteArray::Init() { + if (allocated_ && b_ == NULL) { + b_ = new byte_t[Size()]; + memset(b_, 0, Size()); + } +} + +void MemoryByteArray::InternalPut(int32_t index, byte_t b) { + Init(); + b_[index] = b; +} + +int32_t MemoryByteArray::InternalPut(int32_t index, + byte_t* b, + int32_t offset, + int32_t length) { + assert(b); + Init(); + memcpy(b_ + index, b + offset, length); + return length; +} + +byte_t MemoryByteArray::InternalGet(int32_t index) { + Init(); + return b_[index]; +} + +int32_t MemoryByteArray::InternalGet(int32_t index, + byte_t* b, + int32_t offset, + int32_t length) { + assert(b); + Init(); + memcpy(b + offset, b_ + index, length); + return length; +} + +void MemoryByteArray::Close() { + if (allocated_ && b_) { + delete[] b_; + } + b_ = NULL; +} + +byte_t* MemoryByteArray::Begin() { + Init(); + return b_; +} + +} // namespace sfntly diff --git a/src/sfntly/src/sfntly/data/memory_byte_array.h b/src/sfntly/src/sfntly/data/memory_byte_array.h new file mode 100644 index 000000000000..838fd1aca510 --- /dev/null +++ b/src/sfntly/src/sfntly/data/memory_byte_array.h @@ -0,0 +1,81 @@ +/* + * 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. + */ + +#ifndef SFNTLY_CPP_SRC_SFNTLY_DATA_MEMORY_BYTE_ARRAY_H_ +#define SFNTLY_CPP_SRC_SFNTLY_DATA_MEMORY_BYTE_ARRAY_H_ + +#include "sfntly/data/byte_array.h" + +namespace sfntly { + +class MemoryByteArray : public ByteArray, public RefCounted { + public: + // Construct a new MemoryByteArray with a new array of the size given. It is + // assumed that none of the array is filled and readable. + explicit MemoryByteArray(int32_t length); + + // Note: not implemented due to dangerous operations in constructor. + //explicit MemoryByteArray(ByteVector* b); + + // Construct a new MemoryByteArray using byte array. + // @param b the byte array that provides the actual storage + // @param filled_length the index of the last byte in the array has data + // Note: This is different from Java version, it does not take over the + // 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); + + virtual ~MemoryByteArray(); + virtual int32_t CopyTo(OutputStream* os, int32_t offset, int32_t length); + + // Make gcc -Woverloaded-virtual happy. + virtual int32_t CopyTo(ByteArray* array) { return ByteArray::CopyTo(array); } + virtual int32_t CopyTo(ByteArray* array, int32_t offset, int32_t length) { + return ByteArray::CopyTo(array, offset, length); + } + virtual int32_t CopyTo(int32_t dst_offset, + ByteArray* array, + int32_t src_offset, + int32_t length) { + return ByteArray::CopyTo(dst_offset, array, src_offset, length); + } + virtual int32_t CopyTo(OutputStream* os) { return ByteArray::CopyTo(os); } + + protected: + virtual void InternalPut(int32_t index, byte_t b); + virtual int32_t InternalPut(int32_t index, + byte_t* b, + int32_t offset, + int32_t length); + virtual byte_t InternalGet(int32_t index); + virtual int32_t InternalGet(int32_t index, + byte_t* b, + int32_t offset, + int32_t length); + virtual void Close(); + virtual byte_t* Begin(); + + private: + void Init(); // C++ port only, used to allocate memory outside constructor. + + byte_t* b_; + bool allocated_; +}; + +} // namespace sfntly + +#endif // SFNTLY_CPP_SRC_SFNTLY_DATA_MEMORY_BYTE_ARRAY_H_ diff --git a/src/sfntly/src/sfntly/data/readable_font_data.cc b/src/sfntly/src/sfntly/data/readable_font_data.cc new file mode 100644 index 000000000000..06d783f2e331 --- /dev/null +++ b/src/sfntly/src/sfntly/data/readable_font_data.cc @@ -0,0 +1,336 @@ +/* + * 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. + */ + +#include "sfntly/data/readable_font_data.h" + +#include + +#include "sfntly/data/memory_byte_array.h" +#include "sfntly/data/writable_font_data.h" +#include "sfntly/port/exception_type.h" + +namespace sfntly { + +ReadableFontData::ReadableFontData(ByteArray* array) + : FontData(array), + checksum_set_(false), + checksum_(0) { +} + +ReadableFontData::~ReadableFontData() {} + +// TODO(arthurhsu): re-investigate the memory model of this function. It's +// not too useful without copying, but it's not performance +// savvy to do copying. +CALLER_ATTACH +ReadableFontData* ReadableFontData::CreateReadableFontData(ByteVector* b) { + assert(b); + ByteArrayPtr ba = new MemoryByteArray(b->size()); + ba->Put(0, b); + ReadableFontDataPtr wfd = new ReadableFontData(ba); + return wfd.Detach(); +} + +int64_t ReadableFontData::Checksum() { + AutoLock lock(checksum_lock_); + if (!checksum_set_) { + ComputeChecksum(); + } + return checksum_; +} + +void ReadableFontData::SetCheckSumRanges(const IntegerList& ranges) { + checksum_range_ = ranges; + checksum_set_ = false; // UNIMPLEMENTED: atomicity +} + +int32_t ReadableFontData::ReadUByte(int32_t index) { + int32_t b = array_->Get(BoundOffset(index)); +#if !defined (SFNTLY_NO_EXCEPTION) + if (b < 0) { + throw IndexOutOfBoundException( + "Index attempted to be read from is out of bounds", index); + } +#endif + return b; +} + +int32_t ReadableFontData::ReadByte(int32_t index) { + int32_t b = array_->Get(BoundOffset(index)); +#if !defined (SFNTLY_NO_EXCEPTION) + if (b < 0) { + throw IndexOutOfBoundException( + "Index attempted to be read from is out of bounds", index); + } +#endif + return (b << 24) >> 24; +} + +int32_t ReadableFontData::ReadBytes(int32_t index, + byte_t* b, + int32_t offset, + int32_t length) { + return array_->Get(BoundOffset(index), b, offset, BoundLength(index, length)); +} + +int32_t ReadableFontData::ReadChar(int32_t index) { + return ReadUByte(index); +} + +int32_t ReadableFontData::ReadUShort(int32_t index) { + return 0xffff & (ReadUByte(index) << 8 | ReadUByte(index + 1)); +} + +int32_t ReadableFontData::ReadShort(int32_t index) { + return ((ReadByte(index) << 8 | ReadUByte(index + 1)) << 16) >> 16; +} + +int32_t ReadableFontData::ReadUInt24(int32_t index) { + return 0xffffff & (ReadUByte(index) << 16 | + ReadUByte(index + 1) << 8 | + ReadUByte(index + 2)); +} + +int64_t ReadableFontData::ReadULong(int32_t index) { + return 0xffffffffL & (ReadUByte(index) << 24 | + ReadUByte(index + 1) << 16 | + ReadUByte(index + 2) << 8 | + ReadUByte(index + 3)); +} + +int32_t ReadableFontData::ReadULongAsInt(int32_t index) { + int64_t ulong = ReadULong(index); +#if !defined (SFNTLY_NO_EXCEPTION) + if ((ulong & 0x80000000) == 0x80000000) { + throw ArithmeticException("Long value too large to fit into an integer."); + } +#endif + return static_cast(ulong); +} + +int64_t ReadableFontData::ReadULongLE(int32_t index) { + return 0xffffffffL & (ReadUByte(index) | + ReadUByte(index + 1) << 8 | + ReadUByte(index + 2) << 16 | + ReadUByte(index + 3) << 24); +} + +int32_t ReadableFontData::ReadLong(int32_t index) { + return ReadByte(index) << 24 | + ReadUByte(index + 1) << 16 | + ReadUByte(index + 2) << 8 | + ReadUByte(index + 3); +} + +int32_t ReadableFontData::ReadFixed(int32_t index) { + return ReadLong(index); +} + +int64_t ReadableFontData::ReadDateTimeAsLong(int32_t index) { + return (int64_t)ReadULong(index) << 32 | ReadULong(index + 4); +} + +int32_t ReadableFontData::ReadFWord(int32_t index) { + return ReadShort(index); +} + +int32_t ReadableFontData::ReadFUFWord(int32_t index) { + return ReadUShort(index); +} + +int32_t ReadableFontData::CopyTo(OutputStream* os) { + return array_->CopyTo(os, BoundOffset(0), Length()); +} + +int32_t ReadableFontData::CopyTo(WritableFontData* wfd) { + return array_->CopyTo(wfd->BoundOffset(0), + wfd->array_, + BoundOffset(0), + Length()); +} + +int32_t ReadableFontData::CopyTo(ByteArray* ba) { + return array_->CopyTo(ba, BoundOffset(0), Length()); +} + +int32_t ReadableFontData::SearchUShort(int32_t start_index, + int32_t start_offset, + int32_t end_index, + int32_t end_offset, + int32_t length, + int32_t key) { + int32_t location = 0; + int32_t bottom = 0; + int32_t top = length; + while (top != bottom) { + location = (top + bottom) / 2; + int32_t location_start = ReadUShort(start_index + location * start_offset); + if (key < location_start) { + // location is below current location + top = location; + } else { + // is key below the upper bound? + int32_t location_end = ReadUShort(end_index + location * end_offset); +#if defined (SFNTLY_DEBUG_FONTDATA) + fprintf(stderr, "**start: %d; end: %d\n", location_start, location_end); +#endif + if (key <= location_end) { + return location; + } else { + // location is above the current location + bottom = location + 1; + } + } + } + return -1; +} + +int32_t ReadableFontData::SearchUShort(int32_t start_index, + int32_t start_offset, + int32_t length, + int32_t key) { + int32_t location = 0; + int32_t bottom = 0; + int32_t top = length; + while (top != bottom) { + location = (top + bottom) / 2; + int32_t location_start = ReadUShort(start_index + location * start_offset); + if (key < location_start) { + // location is below current location + top = location; + } else if (key > location_start) { + // location is above current location + bottom = location + 1; + } else { + return location; + } + } + return -1; +} + +int32_t ReadableFontData::SearchULong(int32_t start_index, + int32_t start_offset, + int32_t end_index, + int32_t end_offset, + int32_t length, + int32_t key) { + int32_t location = 0; + int32_t bottom = 0; + int32_t top = length; + while (top != bottom) { + location = (top + bottom) / 2; + int32_t location_start = ReadULongAsInt(start_index + + location * start_offset); + if (key < location_start) { + // location is below current location + top = location; + } else { + // is key below the upper bound? + int32_t location_end = ReadULongAsInt(end_index + location * end_offset); +#if defined (SFNTLY_DEBUG_FONTDATA) + fprintf(stderr, "**start: %d; end: %d\n", location_start, location_end); +#endif + if (key <= location_end) { + return location; + } else { + // location is above the current location + bottom = location + 1; + } + } + } + return -1; +} + +CALLER_ATTACH FontData* ReadableFontData::Slice(int32_t offset, + int32_t length) { + if (offset < 0 || offset + length > Size()) { +#if !defined (SFNTLY_NO_EXCEPTION) + throw IndexOutOfBoundsException( + "Attempt to bind data outside of its limits"); +#endif + return NULL; + } + FontDataPtr slice = new ReadableFontData(this, offset, length); + return slice.Detach(); +} + +CALLER_ATTACH FontData* ReadableFontData::Slice(int32_t offset) { + if (offset < 0 || offset > Size()) { +#if !defined (SFNTLY_NO_EXCEPTION) + throw IndexOutOfBoundsException( + "Attempt to bind data outside of its limits"); +#endif + return NULL; + } + FontDataPtr slice = new ReadableFontData(this, offset); + return slice.Detach(); +} + +ReadableFontData::ReadableFontData(ReadableFontData* data, int32_t offset) + : FontData(data, offset), + checksum_set_(false), + checksum_(0) { +} + +ReadableFontData::ReadableFontData(ReadableFontData* data, + int32_t offset, + int32_t length) + : FontData(data, offset, length), + checksum_set_(false), + checksum_(0) { +} + +void ReadableFontData::ComputeChecksum() { + // TODO(arthurhsu): IMPLEMENT: synchronization/atomicity + int64_t sum = 0; + if (checksum_range_.empty()) { + sum = ComputeCheckSum(0, Length()); + } else { + for (uint32_t low_bound_index = 0; low_bound_index < checksum_range_.size(); + low_bound_index += 2) { + int32_t low_bound = checksum_range_[low_bound_index]; + int32_t high_bound = (low_bound_index == checksum_range_.size() - 1) ? + Length() : + checksum_range_[low_bound_index + 1]; + sum += ComputeCheckSum(low_bound, high_bound); + } + } + + checksum_ = sum & 0xffffffffL; + checksum_set_ = true; +} + +int64_t ReadableFontData::ComputeCheckSum(int32_t low_bound, + int32_t high_bound) { + int64_t sum = 0; + // Checksum all whole 4-byte chunks. + for (int32_t i = low_bound; i <= high_bound - 4; i += 4) { + sum += ReadULong(i); + } + + // Add last fragment if not 4-byte multiple + int32_t off = high_bound & -4; + if (off < high_bound) { + int32_t b3 = ReadUByte(off); + int32_t b2 = (off + 1 < high_bound) ? ReadUByte(off + 1) : 0; + int32_t b1 = (off + 2 < high_bound) ? ReadUByte(off + 2) : 0; + int32_t b0 = 0; + sum += (b3 << 24) | (b2 << 16) | (b1 << 8) | b0; + } + return sum; +} + +} // namespace sfntly diff --git a/src/sfntly/src/sfntly/data/readable_font_data.h b/src/sfntly/src/sfntly/data/readable_font_data.h new file mode 100644 index 000000000000..b43c62604156 --- /dev/null +++ b/src/sfntly/src/sfntly/data/readable_font_data.h @@ -0,0 +1,308 @@ +/* + * 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. + */ + +#ifndef SFNTLY_CPP_SRC_SFNTLY_DATA_READABLE_FONT_DATA_H_ +#define SFNTLY_CPP_SRC_SFNTLY_DATA_READABLE_FONT_DATA_H_ + +#include "sfntly/data/font_data.h" +#include "sfntly/port/lock.h" + +namespace sfntly { + +class WritableFontData; +class OutputStream; + +// Writable font data wrapper. Supports reading of data primitives in the +// TrueType / OpenType spec. +// The data types used are as listed: +// BYTE 8-bit unsigned integer. +// CHAR 8-bit signed integer. +// USHORT 16-bit unsigned integer. +// SHORT 16-bit signed integer. +// UINT24 24-bit unsigned integer. +// ULONG 32-bit unsigned integer. +// LONG 32-bit signed integer. +// Fixed 32-bit signed fixed-point number (16.16) +// FUNIT Smallest measurable distance in the em space. +// FWORD 16-bit signed integer (SHORT) that describes a quantity in FUnits. +// UFWORD 16-bit unsigned integer (USHORT) that describes a quantity in +// FUnits. +// F2DOT14 16-bit signed fixed number with the low 14 bits of fraction (2.14) +// LONGDATETIME Date represented in number of seconds since 12:00 midnight, +// January 1, 1904. The value is represented as a signed 64-bit +// integer. + +class ReadableFontData : public FontData, + public RefCounted { + public: + explicit ReadableFontData(ByteArray* array); + virtual ~ReadableFontData(); + + static CALLER_ATTACH ReadableFontData* CreateReadableFontData(ByteVector* 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 + // the resulting value is truncated to 32 bits. If the data length in bytes is + // not an integral multiple of 4 then any remaining bytes are treated as the + // start of a 4 byte sequence whose remaining bytes are zero. + // @return the checksum + int64_t Checksum(); + + // Sets the bounds to use for computing the checksum. These bounds are in + // begin and end pairs. If an odd number is given then the final range is + // 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); + + // Read the UBYTE at the given index. + // @param index index into the font data + // @return the UBYTE; -1 if outside the bounds of the font data + // @throws IndexOutOfBoundsException if index is outside the FontData's range + virtual int32_t ReadUByte(int32_t index); + + // Read the BYTE at the given index. + // @param index index into the font data + // @return the BYTE + // @throws IndexOutOfBoundsException if index is outside the FontData's range + virtual int32_t ReadByte(int32_t index); + + // Read the bytes at the given index into the array. + // @param index index into the font data + // @param b the destination for the bytes read + // @param offset offset in the byte array to place the bytes + // @param length the length of bytes to read + // @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, + int32_t offset, + int32_t length); + + // Read the CHAR at the given index. + // @param index index into the font data + // @return the CHAR + // @throws IndexOutOfBoundsException if index is outside the FontData's range + virtual int32_t ReadChar(int32_t index); + + // Read the USHORT at the given index. + // @param index index into the font data + // @return the USHORT + // @throws IndexOutOfBoundsException if index is outside the FontData's range + virtual int32_t ReadUShort(int32_t index); + + // Read the SHORT at the given index. + // @param index index into the font data + // @return the SHORT + // @throws IndexOutOfBoundsException if index is outside the FontData's range + virtual int32_t ReadShort(int32_t index); + + // Read the UINT24 at the given index. + // @param index index into the font data + // @return the UINT24 + // @throws IndexOutOfBoundsException if index is outside the FontData's range + virtual int32_t ReadUInt24(int32_t index); + + // Read the ULONG at the given index. + // @param index index into the font data + // @return the ULONG + // @throws IndexOutOfBoundsException if index is outside the FontData's range + virtual int64_t ReadULong(int32_t index); + + // Read the ULONG at the given index as int32_t. + // @param index index into the font data + // @return the ULONG + // @throws IndexOutOfBoundsException if index is outside the FontData's range + virtual int32_t ReadULongAsInt(int32_t index); + + // Read the ULONG at the given index, little-endian variant + // @param index index into the font data + // @return the ULONG + // @throws IndexOutOfBoundsException if index is outside the FontData's range + virtual int64_t ReadULongLE(int32_t index); + + // Read the LONG at the given index. + // @param index index into the font data + // @return the LONG + // @throws IndexOutOfBoundsException if index is outside the FontData's range + virtual int32_t ReadLong(int32_t index); + + // Read the Fixed at the given index. + // @param index index into the font data + // @return the Fixed + // @throws IndexOutOfBoundsException if index is outside the FontData's range + virtual int32_t ReadFixed(int32_t index); + + // Read the LONGDATETIME at the given index. + // @param index index into the font data + // @return the LONGDATETIME + // @throws IndexOutOfBoundsException if index is outside the FontData's range + virtual int64_t ReadDateTimeAsLong(int32_t index); + + // Read the FWORD at the given index. + // @param index index into the font data + // @return the FWORD + // @throws IndexOutOfBoundsException if index is outside the FontData's range + virtual int32_t ReadFWord(int32_t index); + + // Read the UFWORD at the given index. + // @param index index into the font data + // @return the UFWORD + // @throws IndexOutOfBoundsException if index is outside the FontData's range + virtual int32_t ReadFUFWord(int32_t index); + + // Note: Not ported because they just throw UnsupportedOperationException() + // in Java. + /* + virtual int32_t ReadFUnit(int32_t index); + virtual int64_t ReadF2Dot14(int32_t index); + */ + + // Copy the FontData to an OutputStream. + // @param os the destination + // @return number of bytes copied + // @throws IOException + virtual int32_t CopyTo(OutputStream* os); + + // Copy the FontData to a WritableFontData. + // @param wfd the destination + // @return number of bytes copied + // @throws IOException + virtual int32_t CopyTo(WritableFontData* wfd); + + // Make gcc -Woverloaded-virtual happy. + virtual int32_t CopyTo(ByteArray* ba); + + // Search for the key value in the range tables provided. + // The search looks through the start-end pairs looking for the key value. It + // is assumed that the start-end pairs are both represented by UShort values, + // ranges do not overlap, and are monotonically increasing. + // @param startIndex the position to read the first start value from + // @param startOffset the offset between subsequent start values + // @param endIndex the position to read the first end value from + // @param endOffset the offset between subsequent end values + // @param length the number of start-end pairs + // @param key the value to search for + // @return the index of the start-end pairs in which the key was found; -1 + // otherwise + int32_t SearchUShort(int32_t start_index, + int32_t start_offset, + int32_t end_index, + int32_t end_offset, + int32_t length, + int32_t key); + + // Search for the key value in the table provided. + // The search looks through the values looking for the key value. It is + // assumed that the are represented by UShort values and are monotonically + // increasing. + // @param startIndex the position to read the first start value from + // @param startOffset the offset between subsequent start values + // @param length the number of start-end pairs + // @param key the value to search for + // @return the index of the start-end pairs in which the key was found; -1 + // otherwise + int32_t SearchUShort(int32_t start_index, + int32_t start_offset, + int32_t length, + int32_t key); + + // Search for the key value in the range tables provided. + // The search looks through the start-end pairs looking for the key value. It + // is assumed that the start-end pairs are both represented by ULong values + // that can be represented within 31 bits, ranges do not overlap, and are + // monotonically increasing. + // @param startIndex the position to read the first start value from + // @param startOffset the offset between subsequent start values + // @param endIndex the position to read the first end value from + // @param endOffset the offset between subsequent end values + // @param length the number of start-end pairs + // @param key the value to search for + // @return the index of the start-end pairs in which the key was found; -1 + // otherwise + int32_t SearchULong(int32_t start_index, + int32_t start_offset, + int32_t end_index, + int32_t end_offset, + int32_t length, + int32_t key); + + + // TODO(arthurhsu): IMPLEMENT + /* + virtual int32_t ReadFUnit(int32_t index); + virtual int64_t ReadF2Dot14(int32_t index); + virtual int64_t ReadLongDateTime(int32_t index); + */ + + // Makes a slice of this FontData. The returned slice will share the data with + // the original FontData. + // @param offset the start of the slice + // @param length the number of bytes in the slice + // @return a slice of the original FontData + // Note: C++ polymorphism requires return type to be consistent + virtual CALLER_ATTACH FontData* Slice(int32_t offset, int32_t length); + + // Makes a bottom bound only slice of this array. The returned slice will + // share the data with the original FontData. + // @param offset the start of the slice + // @return a slice of the original FontData + // Note: C++ polymorphism requires return type to be consistent + virtual CALLER_ATTACH FontData* Slice(int32_t offset); + + // Not Ported: toString() + + protected: + // Constructor. Creates a bounded wrapper of another ReadableFontData from the + // given offset until the end of the original ReadableFontData. + // @param data data to wrap + // @param offset the start of this data's view of the original data + ReadableFontData(ReadableFontData* data, int32_t offset); + + // Constructor. Creates a bounded wrapper of another ReadableFontData from the + // given offset until the end of the original ReadableFontData. + // @param data data to wrap + // @param offset the start of this data's view of the original data + // @param length the length of the other FontData to use + ReadableFontData(ReadableFontData* data, int32_t offset, int32_t length); + + private: + // Compute the checksum for the font data using any ranges set for the + // calculation. + void ComputeChecksum(); + + // Do the actual computation of the checksum for a range using the + // TrueType/OpenType checksum algorithm. The range used is from the low bound + // to the high bound in steps of four bytes. If any of the bytes within that 4 + // byte segment are not readable then it will considered a zero for + // calculation. + // Only called from within a synchronized method so it does not need to be + // synchronized itself. + // @param lowBound first position to start a 4 byte segment on + // @param highBound last possible position to start a 4 byte segment on + // @return the checksum for the total range + int64_t ComputeCheckSum(int32_t low_bound, int32_t high_bound); + + Lock checksum_lock_; + bool checksum_set_; + int64_t checksum_; + IntegerList checksum_range_; +}; +typedef Ptr ReadableFontDataPtr; + +} // namespace sfntly + +#endif // SFNTLY_CPP_SRC_SFNTLY_DATA_READABLE_FONT_DATA_H_ diff --git a/src/sfntly/src/sfntly/data/writable_font_data.cc b/src/sfntly/src/sfntly/data/writable_font_data.cc new file mode 100644 index 000000000000..7f6f72f533eb --- /dev/null +++ b/src/sfntly/src/sfntly/data/writable_font_data.cc @@ -0,0 +1,201 @@ +/* + * 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. + */ + +#include "sfntly/data/writable_font_data.h" + +#include "sfntly/data/memory_byte_array.h" +#include "sfntly/data/growable_memory_byte_array.h" + +namespace sfntly { + +WritableFontData::WritableFontData(ByteArray* ba) : ReadableFontData(ba) { +} + +WritableFontData::~WritableFontData() {} + +// static +CALLER_ATTACH +WritableFontData* WritableFontData::CreateWritableFontData(int32_t length) { + ByteArrayPtr ba; + if (length > 0) { + ba = new MemoryByteArray(length); + ba->SetFilledLength(length); + } else { + ba = new GrowableMemoryByteArray(); + } + WritableFontDataPtr wfd = new WritableFontData(ba); + return wfd.Detach(); +} + +// TODO(arthurhsu): re-investigate the memory model of this function. It's +// not too useful without copying, but it's not performance +// savvy to do copying. +CALLER_ATTACH +WritableFontData* WritableFontData::CreateWritableFontData(ByteVector* 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) { + array_->Put(BoundOffset(index), b); + return 1; +} + +int32_t WritableFontData::WriteBytes(int32_t index, + byte_t* b, + int32_t offset, + int32_t length) { + return array_->Put(BoundOffset(index), + b, + offset, + BoundLength(index, length)); +} + +int32_t WritableFontData::WriteBytes(int32_t index, ByteVector* b) { + assert(b); + return WriteBytes(index, &((*b)[0]), 0, b->size()); +} + +int32_t WritableFontData::WriteBytesPad(int32_t index, + ByteVector* b, + int32_t offset, + int32_t length, + byte_t pad) { + int32_t written = + array_->Put(BoundOffset(index), + &((*b)[0]), + offset, + BoundLength(index, + std::min(length, b->size() - offset))); + written += WritePadding(written + index, length - written, pad); + return written; +} + +int32_t WritableFontData::WritePadding(int32_t index, int32_t count) { + return WritePadding(index, count, (byte_t)0); +} + +int32_t WritableFontData::WritePadding(int32_t index, int32_t count, + byte_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) { + 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)); + 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)); + return 2; +} + +int32_t WritableFontData::WriteShort(int32_t index, int32_t s) { + return WriteUShort(index, 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)); + 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)); + 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)); + return 4; +} + +int32_t WritableFontData::WriteLong(int32_t index, int64_t l) { + return WriteULong(index, l); +} + +int32_t WritableFontData::WriteFixed(int32_t index, int32_t f) { + return WriteLong(index, f); +} + +int32_t WritableFontData::WriteDateTime(int32_t index, int64_t date) { + WriteULong(index, (date >> 32) & 0xffffffff); + WriteULong(index + 4, date & 0xffffffff); + return 8; +} + +void WritableFontData::CopyFrom(InputStream* is, int32_t length) { + array_->CopyFrom(is, length); +} + +void WritableFontData::CopyFrom(InputStream* is) { + array_->CopyFrom(is); +} + +CALLER_ATTACH FontData* WritableFontData::Slice(int32_t offset, + int32_t length) { + if (offset < 0 || offset + length > Size()) { +#if !defined (SFNTLY_NO_EXCEPTION) + throw IndexOutOfBoundsException( + "Attempt to bind data outside of its limits"); +#endif + return NULL; + } + FontDataPtr slice = new WritableFontData(this, offset, length); + return slice.Detach(); +} + +CALLER_ATTACH FontData* WritableFontData::Slice(int32_t offset) { + if (offset > Size()) { +#if !defined (SFNTLY_NO_EXCEPTION) + throw IndexOutOfBoundsException( + "Attempt to bind data outside of its limits"); +#endif + return NULL; + } + FontDataPtr slice = new WritableFontData(this, offset); + return slice.Detach(); +} + +WritableFontData::WritableFontData(WritableFontData* data, int32_t offset) + : ReadableFontData(data, offset) { +} + +WritableFontData::WritableFontData(WritableFontData* data, + int32_t offset, + int32_t length) + : ReadableFontData(data, offset, length) { +} + +} // namespace sfntly diff --git a/src/sfntly/src/sfntly/data/writable_font_data.h b/src/sfntly/src/sfntly/data/writable_font_data.h new file mode 100644 index 000000000000..d2a049eb55ae --- /dev/null +++ b/src/sfntly/src/sfntly/data/writable_font_data.h @@ -0,0 +1,211 @@ +/* + * 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. + */ + +#ifndef SFNTLY_CPP_SRC_SFNTLY_DATA_WRITABLE_FONT_DATA_H_ +#define SFNTLY_CPP_SRC_SFNTLY_DATA_WRITABLE_FONT_DATA_H_ + +#include "sfntly/data/readable_font_data.h" + +namespace sfntly { + +// Writable font data wrapper. Supports writing of data primitives in the +// TrueType / OpenType spec. +class WritableFontData : public ReadableFontData { + public: + explicit WritableFontData(ByteArray* ba); + virtual ~WritableFontData(); + + // Constructs a writable font data object. If the length is specified as + // positive then a fixed size font data object will be created. If the length + // is zero or less then a growable font data object will be created and the + // size will be used as an estimate to help in allocating the original space. + // @param length if length > 0 create a fixed length font data; otherwise + // create a growable font data + // @return a new writable font data + static CALLER_ATTACH WritableFontData* CreateWritableFontData(int32_t length); + + // Constructs a writable font data object. The new font data object will wrap + // the bytes passed in to the factory and it will take make a copy of those + // bytes. + // @param b the byte vector to wrap + // @return a new writable font data + static CALLER_ATTACH WritableFontData* CreateWritableFontData(ByteVector* 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); + + // Write the bytes from the array. + // @param index index into the font data + // @param b the source for the bytes to be written + // @param offset offset in the byte array + // @param length the length of 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, + byte_t* b, + int32_t offset, + int32_t length); + + // Write the bytes from the array. + // @param index index into the font data + // @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); + + // Write the bytes from the array and pad if necessary. + // Write to the length given using the byte array provided and if there are + // not enough bytes in the array then pad to the requested length using the + // pad byte specified. + // @param index index into the font data + // @param b the source for the bytes to be written + // @param offset offset in the byte array + // @param length the length of the bytes to be written + // @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, + int32_t offset, + int32_t length, + byte_t pad); + + // Writes padding to the FontData. The padding byte written is 0x00. + // @param index index into the font data + // @param count the number of pad bytes to write + // @return the number of pad bytes written + virtual int32_t WritePadding(int32_t index, int32_t count); + + // Writes padding to the FontData. + // @param index index into the font data + // @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); + + // 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); + + // Write the USHORT at the given index. + // @param index index into the font data + // @param us the USHORT + // @return the number of bytes actually written + // @throws IndexOutOfBoundsException if index is outside the FontData's range + virtual int32_t WriteUShort(int32_t index, int32_t us); + + // Write the USHORT at the given index in little endian format. + // @param index index into the font data + // @param us the USHORT + // @return the number of bytes actually written + // @throws IndexOutOfBoundsException if index is outside the FontData's range + virtual int32_t WriteUShortLE(int32_t index, int32_t us); + + // Write the SHORT at the given index. + // @param index index into the font data + // @param s the SHORT + // @return the number of bytes actually written + // @throws IndexOutOfBoundsException if index is outside the FontData's range + virtual int32_t WriteShort(int32_t index, int32_t s); + + // Write the UINT24 at the given index. + // @param index index into the font data + // @param ui the UINT24 + // @return the number of bytes actually written + // @throws IndexOutOfBoundsException if index is outside the FontData's range + virtual int32_t WriteUInt24(int32_t index, int32_t ui); + + // Write the ULONG at the given index. + // @param index index into the font data + // @param ul the ULONG + // @return the number of bytes actually written + // @throws IndexOutOfBoundsException if index is outside the FontData's range + virtual int32_t WriteULong(int32_t index, int64_t ul); + + // Write the ULONG at the given index in little endian format. + // @param index index into the font data + // @param ul the ULONG + // @return the number of bytes actually written + // @throws IndexOutOfBoundsException if index is outside the FontData's range + virtual int32_t WriteULongLE(int32_t index, int64_t ul); + + // Write the LONG at the given index. + // @param index index into the font data + // @param l the LONG + // @return the number of bytes actually written + // @throws IndexOutOfBoundsException if index is outside the FontData's range + virtual int32_t WriteLong(int32_t index, int64_t l); + + // Write the Fixed at the given index. + // @param index index into the font data + // @param f the Fixed + // @return the number of bytes actually written + // @throws IndexOutOfBoundsException if index is outside the FontData's range + virtual int32_t WriteFixed(int32_t index, int32_t f); + + // Write the LONGDATETIME at the given index. + // @param index index into the font data + // @param date the LONGDATETIME + // @return the number of bytes actually written + // @throws IndexOutOfBoundsException if index is outside the FontData's range + virtual int32_t WriteDateTime(int32_t index, int64_t date); + + // Copy from the InputStream into this FontData. + // @param is the source + // @param length the number of bytes to copy + // @throws IOException + virtual void CopyFrom(InputStream* is, int32_t length); + + // Copy everything from the InputStream into this FontData. + // @param is the source + // @throws IOException + virtual void CopyFrom(InputStream* is); + + // Makes a slice of this FontData. The returned slice will share the data with + // the original FontData. + // @param offset the start of the slice + // @param length the number of bytes in the slice + // @return a slice of the original FontData + virtual CALLER_ATTACH FontData* Slice(int32_t offset, int32_t length); + + // Makes a bottom bound only slice of this array. The returned slice will + // share the data with the original FontData. + // @param offset the start of the slice + // @return a slice of the original FontData + virtual CALLER_ATTACH FontData* Slice(int32_t offset); + + private: + // Constructor with a lower bound. + // @param data other WritableFontData object to share data with + // @param offset offset from the other WritableFontData's data + WritableFontData(WritableFontData* data, int32_t offset); + + // Constructor with lower bound and a length bound. + // @param data other WritableFontData object to share data with + // @param offset offset from the other WritableFontData's data + // @param length length of other WritableFontData's data to use + WritableFontData(WritableFontData* data, int32_t offset, int32_t length); +}; +typedef Ptr WritableFontDataPtr; + +} // namespace sfntly + +#endif // SFNTLY_CPP_SRC_SFNTLY_DATA_WRITABLE_FONT_DATA_H_ diff --git a/src/sfntly/src/sfntly/font.cc b/src/sfntly/src/sfntly/font.cc new file mode 100644 index 000000000000..347e0c13e972 --- /dev/null +++ b/src/sfntly/src/sfntly/font.cc @@ -0,0 +1,557 @@ +/* + * 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. + */ + +#include "sfntly/font.h" + +#include + +#include +#include +#include +#include +#include +#include + +#include "sfntly/data/font_input_stream.h" +#include "sfntly/font_factory.h" +#include "sfntly/math/fixed1616.h" +#include "sfntly/math/font_math.h" +#include "sfntly/port/exception_type.h" +#include "sfntly/table/core/font_header_table.h" +#include "sfntly/table/core/horizontal_device_metrics_table.h" +#include "sfntly/table/core/horizontal_header_table.h" +#include "sfntly/table/core/horizontal_metrics_table.h" +#include "sfntly/table/core/maximum_profile_table.h" +#include "sfntly/table/truetype/loca_table.h" +#include "sfntly/tag.h" + +namespace sfntly { + +const int32_t SFNTVERSION_MAJOR = 1; +const int32_t SFNTVERSION_MINOR = 0; + +/****************************************************************************** + * Font class + ******************************************************************************/ +Font::~Font() {} + +bool Font::HasTable(int32_t tag) { + TableMap::const_iterator result = tables_.find(tag); + TableMap::const_iterator end = tables_.end(); + return (result != end); +} + +Table* Font::GetTable(int32_t tag) { + if (!HasTable(tag)) { + return NULL; + } + return tables_[tag]; +} + +const TableMap* Font::GetTableMap() { + return &tables_; +} + +void Font::Serialize(OutputStream* os, IntegerList* table_ordering) { + assert(table_ordering); + IntegerList final_table_ordering; + GenerateTableOrdering(table_ordering, &final_table_ordering); + TableHeaderList table_records; + BuildTableHeadersForSerialization(&final_table_ordering, &table_records); + + FontOutputStream fos(os); + SerializeHeader(&fos, &table_records); + SerializeTables(&fos, &table_records); +} + +Font::Font(int32_t sfnt_version, ByteVector* 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, + TableHeaderList* table_headers) { + assert(table_headers); + assert(table_ordering); + + IntegerList 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()) { + 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; + } + } +} + +void Font::SerializeHeader(FontOutputStream* fos, + TableHeaderList* table_headers) { + fos->WriteFixed(sfnt_version_); + fos->WriteUShort(table_headers->size()); + int32_t log2_of_max_power_of_2 = FontMath::Log2(table_headers->size()); + int32_t search_range = 2 << (log2_of_max_power_of_2 - 1 + 4); + fos->WriteUShort(search_range); + fos->WriteUShort(log2_of_max_power_of_2); + fos->WriteUShort((table_headers->size() * 16) - search_range); + + HeaderTagSortedSet sorted_headers; + std::copy(table_headers->begin(), + table_headers->end(), + std::inserter(sorted_headers, sorted_headers.end())); + + for (HeaderTagSortedSet::iterator record = sorted_headers.begin(), + record_end = sorted_headers.end(); + record != record_end; ++record) { + fos->WriteULong((*record)->tag()); + fos->WriteULong((int32_t)((*record)->checksum())); + fos->WriteULong((*record)->offset()); + fos->WriteULong((*record)->length()); + } +} + +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()); + if (target_table == NULL) { +#if !defined (SFNTLY_NO_EXCEPTION) + throw IOException("Table out of sync with font header."); +#endif + return; + } + int32_t table_size = target_table->Serialize(fos); + if (table_size != (*record)->length()) { + assert(false); + } + int32_t filler_size = ((table_size + 3) & ~3) - table_size; + for (int32_t i = 0; i < filler_size; ++i) { + fos->Write(static_cast(0)); + } + } +} + +void Font::GenerateTableOrdering(IntegerList* default_table_ordering, + IntegerList* table_ordering) { + assert(default_table_ordering); + assert(table_ordering); + table_ordering->clear(); + if (default_table_ordering->empty()) { + DefaultTableOrdering(default_table_ordering); + } + + typedef std::map Int2Bool; + typedef std::pair Int2BoolEntry; + Int2Bool tables_in_font; + for (TableMap::iterator table = tables_.begin(), table_end = tables_.end(); + table != table_end; ++table) { + tables_in_font.insert(Int2BoolEntry(table->first, false)); + } + for (IntegerList::iterator tag = default_table_ordering->begin(), + tag_end = default_table_ordering->end(); + tag != tag_end; ++tag) { + if (HasTable(*tag)) { + table_ordering->push_back(*tag); + tables_in_font[*tag] = true; + } + } + for (Int2Bool::iterator table = tables_in_font.begin(), + table_end = tables_in_font.end(); + table != table_end; ++table) { + if (table->second == false) + table_ordering->push_back(table->first); + } +} + +void Font::DefaultTableOrdering(IntegerList* default_table_ordering) { + assert(default_table_ordering); + default_table_ordering->clear(); + if (HasTable(Tag::CFF)) { + default_table_ordering->resize(CFF_TABLE_ORDERING_SIZE); + std::copy(CFF_TABLE_ORDERING, CFF_TABLE_ORDERING + CFF_TABLE_ORDERING_SIZE, + default_table_ordering->begin()); + return; + } + default_table_ordering->resize(TRUE_TYPE_TABLE_ORDERING_SIZE); + std::copy(TRUE_TYPE_TABLE_ORDERING, + TRUE_TYPE_TABLE_ORDERING + TRUE_TYPE_TABLE_ORDERING_SIZE, + default_table_ordering->begin()); +} + +/****************************************************************************** + * Font::Builder class + ******************************************************************************/ +Font::Builder::~Builder() {} + +CALLER_ATTACH Font::Builder* Font::Builder::GetOTFBuilder(FontFactory* factory, + InputStream* is) { + FontBuilderPtr builder = new Builder(factory); + builder->LoadFont(is); + return builder.Detach(); +} + +CALLER_ATTACH Font::Builder* Font::Builder::GetOTFBuilder( + FontFactory* factory, + WritableFontData* wfd, + int32_t offset_to_offset_table) { + FontBuilderPtr builder = new Builder(factory); + builder->LoadFont(wfd, offset_to_offset_table); + return builder.Detach(); +} + +CALLER_ATTACH Font::Builder* Font::Builder::GetOTFBuilder( + FontFactory* factory) { + FontBuilderPtr builder = new Builder(factory); + return builder.Detach(); +} + +bool Font::Builder::ReadyToBuild() { + // just read in data with no manipulation + if (table_builders_.empty() && !data_blocks_.empty()) { + return true; + } + + // TODO(stuartg): font level checks - required tables etc? + for (TableBuilderMap::iterator table_builder = table_builders_.begin(), + table_builder_end = table_builders_.end(); + table_builder != table_builder_end; + ++table_builder) { + if (!table_builder->second->ReadyToBuild()) + return false; + } + return true; +} + +CALLER_ATTACH Font* Font::Builder::Build() { + FontPtr font = new Font(sfnt_version_, &digest_); + + if (!table_builders_.empty()) { + // Note: Different from Java. Directly use font->tables_ here to avoid + // STL container copying. + BuildTablesFromBuilders(font, &table_builders_, &font->tables_); + } + + table_builders_.clear(); + data_blocks_.clear(); + return font.Detach(); +} + +void Font::Builder::SetDigest(ByteVector* digest) { + digest_.clear(); + digest_ = *digest; +} + +void Font::Builder::ClearTableBuilders() { + table_builders_.clear(); +} + +bool Font::Builder::HasTableBuilder(int32_t tag) { + return (table_builders_.find(tag) != table_builders_.end()); +} + +Table::Builder* Font::Builder::GetTableBuilder(int32_t tag) { + if (HasTableBuilder(tag)) + return table_builders_[tag]; + return NULL; +} + +Table::Builder* Font::Builder::NewTableBuilder(int32_t tag) { + HeaderPtr header = new Header(tag); + TableBuilderPtr builder; + builder.Attach(Table::Builder::GetBuilder(header, NULL)); + table_builders_.insert(TableBuilderEntry(header->tag(), builder)); + return builder; +} + +Table::Builder* Font::Builder::NewTableBuilder(int32_t tag, + ReadableFontData* src_data) { + assert(src_data); + WritableFontDataPtr data; + data.Attach(WritableFontData::CreateWritableFontData(src_data->Length())); + // TODO(stuarg): take over original data instead? + src_data->CopyTo(data); + + HeaderPtr header = new Header(tag, data->Length()); + TableBuilderPtr builder; + builder.Attach(Table::Builder::GetBuilder(header, data)); + table_builders_.insert(TableBuilderEntry(tag, builder)); + return builder; +} + +void Font::Builder::RemoveTableBuilder(int32_t tag) { + TableBuilderMap::iterator target = table_builders_.find(tag); + if (target != table_builders_.end()) { + table_builders_.erase(target); + } +} + +Font::Builder::Builder(FontFactory* factory) + : factory_(factory), + sfnt_version_(Fixed1616::Fixed(SFNTVERSION_MAJOR, SFNTVERSION_MINOR)) { +} + +void Font::Builder::LoadFont(InputStream* is) { + // Note: we do not throw exception here for is. This is more of an assertion. + assert(is); + FontInputStream font_is(is); + HeaderOffsetSortedSet records; + ReadHeader(&font_is, &records); + LoadTableData(&records, &font_is, &data_blocks_); + BuildAllTableBuilders(&data_blocks_, &table_builders_); + font_is.Close(); +} + +void Font::Builder::LoadFont(WritableFontData* wfd, + int32_t offset_to_offset_table) { + // Note: we do not throw exception here for is. This is more of an assertion. + assert(wfd); + HeaderOffsetSortedSet records; + ReadHeader(wfd, offset_to_offset_table, &records); + LoadTableData(&records, wfd, &data_blocks_); + BuildAllTableBuilders(&data_blocks_, &table_builders_); +} + +int32_t Font::Builder::SfntWrapperSize() { + return Offset::kSfntHeaderSize + + (Offset::kTableRecordSize * table_builders_.size()); +} + +void Font::Builder::BuildAllTableBuilders(DataBlockMap* table_data, + TableBuilderMap* builder_map) { + for (DataBlockMap::iterator record = table_data->begin(), + record_end = table_data->end(); + record != record_end; ++record) { + TableBuilderPtr builder; + builder.Attach(GetTableBuilder(record->first.p_, record->second.p_)); + builder_map->insert(TableBuilderEntry(record->first->tag(), builder)); + } + InterRelateBuilders(&table_builders_); +} + +CALLER_ATTACH +Table::Builder* Font::Builder::GetTableBuilder(Header* header, + WritableFontData* data) { + return Table::Builder::GetBuilder(header, data); +} + +void Font::Builder::BuildTablesFromBuilders(Font* font, + TableBuilderMap* builder_map, + TableMap* table_map) { + UNREFERENCED_PARAMETER(font); + InterRelateBuilders(builder_map); + + // Now build all the tables. + for (TableBuilderMap::iterator builder = builder_map->begin(), + builder_end = builder_map->end(); + builder != builder_end; ++builder) { + TablePtr table; + if (builder->second && builder->second->ReadyToBuild()) { + table.Attach(down_cast(builder->second->Build())); + } + if (table == NULL) { + table_map->clear(); +#if !defined (SFNTLY_NO_EXCEPTION) + std::string builder_string = "Unable to build table - "; + char* table_name = TagToString(builder->first); + builder_string += table_name; + delete[] table_name; + throw RuntimeException(builder_string.c_str()); +#endif + return; + } + table_map->insert(TableMapEntry(table->header()->tag(), table)); + } +} + +static Table::Builder* GetBuilder(TableBuilderMap* builder_map, int32_t tag) { + if (builder_map) { + TableBuilderMap::iterator target = builder_map->find(tag); + if (target != builder_map->end()) { + return target->second.p_; + } + } + + return NULL; +} + +void Font::Builder::InterRelateBuilders(TableBuilderMap* builder_map) { + Table::Builder* raw_head_builder = GetBuilder(builder_map, Tag::head); + FontHeaderTableBuilderPtr header_table_builder; + if (raw_head_builder != NULL) { + header_table_builder = + down_cast(raw_head_builder); + } + + Table::Builder* raw_hhea_builder = GetBuilder(builder_map, Tag::hhea); + HorizontalHeaderTableBuilderPtr horizontal_header_builder; + if (raw_head_builder != NULL) { + horizontal_header_builder = + down_cast(raw_hhea_builder); + } + + Table::Builder* raw_maxp_builder = GetBuilder(builder_map, Tag::maxp); + MaximumProfileTableBuilderPtr max_profile_builder; + if (raw_maxp_builder != NULL) { + max_profile_builder = + down_cast(raw_maxp_builder); + } + + Table::Builder* raw_loca_builder = GetBuilder(builder_map, Tag::loca); + LocaTableBuilderPtr loca_table_builder; + if (raw_loca_builder != NULL) { + loca_table_builder = down_cast(raw_loca_builder); + } + + Table::Builder* raw_hmtx_builder = GetBuilder(builder_map, Tag::hmtx); + HorizontalMetricsTableBuilderPtr horizontal_metrics_builder; + if (raw_hmtx_builder != NULL) { + horizontal_metrics_builder = + down_cast(raw_hmtx_builder); + } + +#if defined (SFNTLY_EXPERIMENTAL) + Table::Builder* raw_hdmx_builder = GetBuilder(builder_map, Tag::hdmx); + HorizontalDeviceMetricsTableBuilderPtr hdmx_table_builder; + if (raw_hdmx_builder != NULL) { + hdmx_table_builder = + down_cast(raw_hdmx_builder); + } +#endif + + // 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()); + } + if (horizontal_header_builder != NULL) { + horizontal_metrics_builder->SetNumberOfHMetrics( + horizontal_header_builder->NumberOfHMetrics()); + } + } + + if (loca_table_builder != NULL) { + if (max_profile_builder != NULL) { + loca_table_builder->SetNumGlyphs(max_profile_builder->NumGlyphs()); + } + if (header_table_builder != NULL) { + loca_table_builder->set_format_version( + header_table_builder->IndexToLocFormat()); + } + } + +#if defined (SFNTLY_EXPERIMENTAL) + // Note: In C++, hdmx_table_builder can be NULL in a subsetter. + if (max_profile_builder != NULL && hdmx_table_builder != NULL) { + hdmx_table_builder->SetNumGlyphs(max_profile_builder->NumGlyphs()); + } +#endif +} + +void Font::Builder::ReadHeader(FontInputStream* is, + HeaderOffsetSortedSet* records) { + assert(records); + sfnt_version_ = is->ReadFixed(); + num_tables_ = is->ReadUShort(); + search_range_ = is->ReadUShort(); + entry_selector_ = is->ReadUShort(); + range_shift_ = is->ReadUShort(); + + for (int32_t table_number = 0; table_number < num_tables_; ++table_number) { + // Need to use temporary vars here. C++ evaluates function parameters from + // right to left and thus breaks the order of input stream. + int32_t tag = is->ReadULongAsInt(); + int64_t checksum = is->ReadULong(); + int32_t offset = is->ReadULongAsInt(); + int32_t length = is->ReadULongAsInt(); + HeaderPtr table = new Header(tag, checksum, offset, length); + records->insert(table); + } +} + +void Font::Builder::ReadHeader(ReadableFontData* fd, + int32_t offset, + HeaderOffsetSortedSet* records) { + assert(records); + sfnt_version_ = fd->ReadFixed(offset + Offset::kSfntVersion); + num_tables_ = fd->ReadUShort(offset + Offset::kNumTables); + search_range_ = fd->ReadUShort(offset + Offset::kSearchRange); + entry_selector_ = fd->ReadUShort(offset + Offset::kEntrySelector); + range_shift_ = fd->ReadUShort(offset + Offset::kRangeShift); + + int32_t table_offset = offset + Offset::kTableRecordBegin; + for (int32_t table_number = 0; + table_number < num_tables_; + table_number++, table_offset += Offset::kTableRecordSize) { + int32_t tag = fd->ReadULongAsInt(table_offset + Offset::kTableTag); + 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); + HeaderPtr table = new Header(tag, checksum, offset, length); + records->insert(table); + } +} + +void Font::Builder::LoadTableData(HeaderOffsetSortedSet* headers, + FontInputStream* is, + DataBlockMap* table_data) { + assert(table_data); + for (HeaderOffsetSortedSet::iterator table_header = headers->begin(), + table_end = headers->end(); + table_header != table_end; + ++table_header) { + is->Skip((*table_header)->offset() - is->position()); + FontInputStream table_is(is, (*table_header)->length()); + WritableFontDataPtr data; + data.Attach( + WritableFontData::CreateWritableFontData((*table_header)->length())); + data->CopyFrom(&table_is, (*table_header)->length()); + table_data->insert(DataBlockEntry(*table_header, data)); + } +} + +void Font::Builder::LoadTableData(HeaderOffsetSortedSet* headers, + WritableFontData* fd, + DataBlockMap* table_data) { + for (HeaderOffsetSortedSet::iterator table_header = headers->begin(), + table_end = headers->end(); + table_header != table_end; + ++table_header) { + FontDataPtr sliced_data; + sliced_data.Attach( + fd->Slice((*table_header)->offset(), (*table_header)->length())); + WritableFontDataPtr data = down_cast(sliced_data.p_); + table_data->insert(DataBlockEntry(*table_header, data)); + } +} + +} // namespace sfntly diff --git a/src/sfntly/src/sfntly/font.h b/src/sfntly/src/sfntly/font.h new file mode 100644 index 000000000000..975e8cc52c93 --- /dev/null +++ b/src/sfntly/src/sfntly/font.h @@ -0,0 +1,352 @@ +/* + * 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. + */ + +#ifndef SFNTLY_CPP_SRC_SFNTLY_FONT_H_ +#define SFNTLY_CPP_SRC_SFNTLY_FONT_H_ + +#include + +#include "sfntly/port/refcount.h" +#include "sfntly/port/type.h" +#include "sfntly/port/endian.h" +#include "sfntly/data/font_input_stream.h" +#include "sfntly/data/font_output_stream.h" +#include "sfntly/data/writable_font_data.h" +#include "sfntly/table/table.h" + +namespace sfntly { + +// Note: following constants are embedded in Font class in Java. They are +// extracted out for easier reference from other classes. Offset is the +// one that is kept within class. +// Platform ids. These are used in a number of places within the font whenever +// the platform needs to be specified. +struct PlatformId { + enum { + kUnknown = -1, + kUnicode = 0, + kMacintosh = 1, + kISO = 2, + kWindows = 3, + kCustom = 4 + }; +}; + +// Unicode encoding ids. These are used in a number of places within the font +// whenever character encodings need to be specified. +struct UnicodeEncodingId { + enum { + kUnknown = -1, + kUnicode1_0 = 0, + kUnicode1_1 = 1, + kISO10646 = 2, + kUnicode2_0_BMP = 3, + kUnicode2_0 = 4, + kUnicodeVariationSequences = 5 + }; +}; + +// Windows encoding ids. These are used in a number of places within the font +// whenever character encodings need to be specified. +struct WindowsEncodingId { + enum { + kUnknown = 0xffffffff, + kSymbol = 0, + kUnicodeUCS2 = 1, + kShiftJIS = 2, + kPRC = 3, + kBig5 = 4, + kWansung = 5, + kJohab = 6, + kUnicodeUCS4 = 10 + }; +}; + +// Macintosh encoding ids. These are used in a number of places within the +// font whenever character encodings need to be specified. +struct MacintoshEncodingId { + // Macintosh Platform Encodings + enum { + kUnknown = -1, + kRoman = 0, + kJapanese = 1, + kChineseTraditional = 2, + kKorean = 3, + kArabic = 4, + kHebrew = 5, + kGreek = 6, + kRussian = 7, + kRSymbol = 8, + kDevanagari = 9, + kGurmukhi = 10, + kGujarati = 11, + kOriya = 12, + kBengali = 13, + kTamil = 14, + kTelugu = 15, + kKannada = 16, + kMalayalam = 17, + kSinhalese = 18, + kBurmese = 19, + kKhmer = 20, + kThai = 21, + kLaotian = 22, + kGeorgian = 23, + kArmenian = 24, + kChineseSimplified = 25, + kTibetan = 26, + kMongolian = 27, + kGeez = 28, + kSlavic = 29, + kVietnamese = 30, + kSindhi = 31, + kUninterpreted = 32 + }; +}; + +class FontFactory; + +// An sfnt container font object. This object is immutable and thread safe. To +// construct one use an instance of Font::Builder. +class Font : public RefCounted { + public: + // A builder for a font object. The builder allows the for the creation of + // immutable Font objects. The builder is a one use non-thread safe object and + // once the Font object has been created it is no longer usable. To create a + // further Font object new builder will be required. + class Builder : public RefCounted { + public: + virtual ~Builder(); + + static CALLER_ATTACH Builder* + GetOTFBuilder(FontFactory* factory, InputStream* is); + static CALLER_ATTACH Builder* + GetOTFBuilder(FontFactory* factory, + WritableFontData* ba, + int32_t offset_to_offset_table); + static CALLER_ATTACH Builder* GetOTFBuilder(FontFactory* factory); + + // Get the font factory that created this font builder. + FontFactory* GetFontFactory() { return factory_; } + + // Is the font ready to build? + bool ReadyToBuild(); + + // Build the Font. After this call this builder will no longer be usable. + CALLER_ATTACH Font* Build(); + + // Set a unique fingerprint for the font object. + void SetDigest(ByteVector* digest); + + // Clear all table builders. + void ClearTableBuilders(); + + // Does this font builder have the specified table builder. + bool HasTableBuilder(int32_t tag); + + // Get the table builder for the given tag. If there is no builder for that + // tag then return a null. + Table::Builder* GetTableBuilder(int32_t tag); + + // Creates a new table builder for the table type given by the table id tag. + // This new table has been added to the font and will replace any existing + // builder for that table. + // @return new empty table of the type specified by tag; if tag is not known + // then a generic OpenTypeTable is returned + virtual Table::Builder* NewTableBuilder(int32_t tag); + + // Creates a new table builder for the table type given by the table id tag. + // It makes a copy of the data provided and uses that copy for the table. + // This new table has been added to the font and will replace any existing + // builder for that table. + virtual Table::Builder* NewTableBuilder(int32_t tag, + ReadableFontData* src_data); + + // Get a map of the table builders in this font builder accessed by table + // tag. + virtual TableBuilderMap* table_builders() { return &table_builders_; } + + // Remove the specified table builder from the font builder. + // Note: different from Java: we don't return object in removeTableBuilder + virtual void RemoveTableBuilder(int32_t tag); + + // Get the number of table builders in the font builder. + virtual int32_t number_of_table_builders() { + return (int32_t)table_builders_.size(); + } + + private: + explicit Builder(FontFactory* factory); + virtual void LoadFont(InputStream* is); + virtual void LoadFont(WritableFontData* wfd, + int32_t offset_to_offset_table); + int32_t SfntWrapperSize(); + void BuildAllTableBuilders(DataBlockMap* table_data, + TableBuilderMap* builder_map); + CALLER_ATTACH Table::Builder* + GetTableBuilder(Header* header, WritableFontData* data); + void BuildTablesFromBuilders(Font* font, + TableBuilderMap* builder_map, + TableMap* tables); + static void InterRelateBuilders(TableBuilderMap* builder_map); + + void ReadHeader(FontInputStream* is, + HeaderOffsetSortedSet* records); + + void ReadHeader(ReadableFontData* fd, + int32_t offset, + HeaderOffsetSortedSet* records); + + void LoadTableData(HeaderOffsetSortedSet* headers, + FontInputStream* is, + DataBlockMap* table_data); + + void LoadTableData(HeaderOffsetSortedSet* headers, + WritableFontData* fd, + DataBlockMap* table_data); + + TableBuilderMap table_builders_; + FontFactory* factory_; // dumb pointer, avoid circular refcounting + int32_t sfnt_version_; + int32_t num_tables_; + int32_t search_range_; + int32_t entry_selector_; + int32_t range_shift_; + DataBlockMap data_blocks_; + ByteVector digest_; + }; + + virtual ~Font(); + + // Gets the sfnt version set in the sfnt wrapper of the font. + int32_t sfnt_version() { return sfnt_version_; } + + // 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_; } + + // Get the checksum for this font. + int64_t checksum() { return checksum_; } + + // Get the number of tables in this font. + int32_t num_tables() { return (int32_t)tables_.size(); } + + // Whether the font has a particular table. + bool HasTable(int32_t tag); + + // UNIMPLEMENTED: public Iterator iterator + + // Get the table in this font with the specified id. + // @param tag the identifier of the table + // @return the table specified if it exists; null otherwise + // C++ port: rename table() to GetTable() + Table* GetTable(int32_t tag); + + // Get a map of the tables in this font accessed by table tag. + // @return an unmodifiable view of the tables in this font + // Note: renamed tableMap() to GetTableMap() + const TableMap* GetTableMap(); + + // UNIMPLEMENTED: toString() + + // 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); + + private: + // Offsets to specific elements in the underlying data. These offsets are + // relative to the start of the table or the start of sub-blocks within the + // table. + struct Offset { + enum { + // Offsets within the main directory + kSfntVersion = 0, + kNumTables = 4, + kSearchRange = 6, + kEntrySelector = 8, + kRangeShift = 10, + kTableRecordBegin = 12, + kSfntHeaderSize = 12, + + // Offsets within a specific table record + kTableTag = 0, + kTableCheckSum = 4, + kTableOffset = 8, + kTableLength = 12, + kTableRecordSize = 16 + }; + }; + + // Note: the two constants are moved to tag.h to avoid VC++ bug. +// static const int32_t CFF_TABLE_ORDERING[]; +// static const int32_t TRUE_TYPE_TABLE_ORDERING[]; + + // Constructor. + // @param sfntVersion the sfnt version + // @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); + + // 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 + // sorted in the order specified and only those specified will have headers + // generated. + // @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, + TableHeaderList* table_headers); + + // Searialize the headers. + // @param fos the destination stream for the headers + // @param tableHeaders the headers to serialize + // @throws IOException + void SerializeHeader(FontOutputStream* fos, TableHeaderList* table_headers); + + // Serialize the tables. + // @param fos the destination stream for the headers + // @param tableHeaders the headers for the tables to serialize + // @throws IOException + void SerializeTables(FontOutputStream* fos, TableHeaderList* table_headers); + + // Generate the full table ordering to used for serialization. The full + // ordering uses the partial ordering as a seed and then adds all remaining + // tables in the font in an undefined order. + // @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); + + // 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); + + int32_t sfnt_version_; + ByteVector digest_; + int64_t checksum_; + TableMap tables_; +}; +typedef Ptr FontPtr; +typedef std::vector FontArray; +typedef Ptr FontBuilderPtr; +typedef std::vector FontBuilderArray; + +} // namespace sfntly + +#endif // SFNTLY_CPP_SRC_SFNTLY_FONT_H_ diff --git a/src/sfntly/src/sfntly/font_factory.cc b/src/sfntly/src/sfntly/font_factory.cc new file mode 100644 index 000000000000..c162a77af34d --- /dev/null +++ b/src/sfntly/src/sfntly/font_factory.cc @@ -0,0 +1,214 @@ +/* + * 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. + */ + +#include "sfntly/font_factory.h" + +#include + +#include "sfntly/tag.h" + +namespace sfntly { + +FontFactory::~FontFactory() { +} + +CALLER_ATTACH FontFactory* FontFactory::GetInstance() { + FontFactoryPtr instance = new FontFactory(); + return instance.Detach(); +} + +void FontFactory::FingerprintFont(bool fingerprint) { + fingerprint_ = fingerprint; +} + +bool FontFactory::FingerprintFont() { + return fingerprint_; +} + +void FontFactory::LoadFonts(InputStream* is, FontArray* output) { + assert(output); + PushbackInputStream* pbis = down_cast(is); + if (IsCollection(pbis)) { + LoadCollection(pbis, output); + return; + } + FontPtr font; + font.Attach(LoadSingleOTF(pbis)); + if (font) { + output->push_back(font); + } +} + +void FontFactory::LoadFonts(ByteVector* b, FontArray* output) { + WritableFontDataPtr wfd; + wfd.Attach(WritableFontData::CreateWritableFontData(b)); + if (IsCollection(wfd)) { + LoadCollection(wfd, output); + return; + } + FontPtr font; + font.Attach(LoadSingleOTF(wfd)); + if (font) { + output->push_back(font); + } +} + +void FontFactory::LoadFontsForBuilding(InputStream* is, + FontBuilderArray* output) { + PushbackInputStream* pbis = down_cast(is); + if (IsCollection(pbis)) { + LoadCollectionForBuilding(pbis, output); + return; + } + FontBuilderPtr builder; + builder.Attach(LoadSingleOTFForBuilding(pbis)); + if (builder) { + output->push_back(builder); + } +} + +void FontFactory::LoadFontsForBuilding(ByteVector* b, + FontBuilderArray* output) { + WritableFontDataPtr wfd; + wfd.Attach(WritableFontData::CreateWritableFontData(b)); + if (IsCollection(wfd)) { + LoadCollectionForBuilding(wfd, output); + return; + } + FontBuilderPtr builder; + builder.Attach(LoadSingleOTFForBuilding(wfd, 0)); + if (builder) { + output->push_back(builder); + } +} + +void FontFactory::SerializeFont(Font* font, OutputStream* os) { + font->Serialize(os, &table_ordering_); +} + +void FontFactory::SetSerializationTableOrdering( + const IntegerList& table_ordering) { + table_ordering_ = table_ordering; +} + +CALLER_ATTACH Font::Builder* FontFactory::NewFontBuilder() { + return Font::Builder::GetOTFBuilder(this); +} + +CALLER_ATTACH Font* FontFactory::LoadSingleOTF(InputStream* is) { + FontBuilderPtr builder; + builder.Attach(LoadSingleOTFForBuilding(is)); + return builder->Build(); +} + +CALLER_ATTACH Font* FontFactory::LoadSingleOTF(WritableFontData* wfd) { + FontBuilderPtr builder; + builder.Attach(LoadSingleOTFForBuilding(wfd, 0)); + return builder->Build(); +} + +void FontFactory::LoadCollection(InputStream* is, FontArray* output) { + FontBuilderArray ba; + LoadCollectionForBuilding(is, &ba); + output->reserve(ba.size()); + for (FontBuilderArray::iterator builder = ba.begin(), builders_end = ba.end(); + builder != builders_end; ++builder) { + FontPtr font; + font.Attach((*builder)->Build()); + output->push_back(font); + } +} + +void FontFactory::LoadCollection(WritableFontData* wfd, FontArray* output) { + FontBuilderArray builders; + LoadCollectionForBuilding(wfd, &builders); + output->reserve(builders.size()); + for (FontBuilderArray::iterator builder = builders.begin(), + builders_end = builders.end(); + builder != builders_end; ++builder) { + FontPtr font; + font.Attach((*builder)->Build()); + output->push_back(font); + } +} + +CALLER_ATTACH +Font::Builder* FontFactory::LoadSingleOTFForBuilding(InputStream* is) { + // UNIMPLEMENTED: SHA-1 hash checking via Java DigestStream + Font::Builder* builder = Font::Builder::GetOTFBuilder(this, is); + // UNIMPLEMENTED: setDigest + return builder; +} + +CALLER_ATTACH Font::Builder* + FontFactory::LoadSingleOTFForBuilding(WritableFontData* wfd, + int32_t offset_to_offset_table) { + // UNIMPLEMENTED: SHA-1 hash checking via Java DigestStream + Font::Builder* builder = + Font::Builder::GetOTFBuilder(this, wfd, offset_to_offset_table); + // UNIMPLEMENTED: setDigest + return builder; +} + +void FontFactory::LoadCollectionForBuilding(InputStream* is, + FontBuilderArray* builders) { + assert(is); + assert(builders); + WritableFontDataPtr wfd; + wfd.Attach(WritableFontData::CreateWritableFontData(is->Available())); + wfd->CopyFrom(is); + LoadCollectionForBuilding(wfd, builders); +} + +void FontFactory::LoadCollectionForBuilding(WritableFontData* wfd, + FontBuilderArray* builders) { + int32_t ttc_tag = wfd->ReadULongAsInt(Offset::kTTCTag); + UNREFERENCED_PARAMETER(ttc_tag); + int32_t version = wfd->ReadFixed(Offset::kVersion); + UNREFERENCED_PARAMETER(version); + int32_t num_fonts = wfd->ReadULongAsInt(Offset::kNumFonts); + + builders->reserve(num_fonts); + int32_t offset_table_offset = Offset::kOffsetTable; + for (int32_t font_number = 0; + font_number < num_fonts; + font_number++, offset_table_offset += DataSize::kULONG) { + int32_t offset = wfd->ReadULongAsInt(offset_table_offset); + FontBuilderPtr builder; + builder.Attach(LoadSingleOTFForBuilding(wfd, offset)); + builders->push_back(builder); + } +} + +bool FontFactory::IsCollection(PushbackInputStream* pbis) { + ByteVector 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); + rfd->ReadBytes(0, &(tag[0]), 0, tag.size()); + return Tag::ttcf == + GenerateTag(tag[0], tag[1], tag[2], tag[3]); +} + +FontFactory::FontFactory() + : fingerprint_(false) { +} + +} // namespace sfntly diff --git a/src/sfntly/src/sfntly/font_factory.h b/src/sfntly/src/sfntly/font_factory.h new file mode 100644 index 000000000000..63deff4abfea --- /dev/null +++ b/src/sfntly/src/sfntly/font_factory.h @@ -0,0 +1,140 @@ +/* + * 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. + */ + +#ifndef SFNTLY_CPP_SRC_SFNTLY_FONT_FACTORY_H_ +#define SFNTLY_CPP_SRC_SFNTLY_FONT_FACTORY_H_ + +#include + +#include "sfntly/port/refcount.h" +#include "sfntly/port/type.h" +#include "sfntly/font.h" + +namespace sfntly { + +class FontFactory : public RefCounted { + public: + virtual ~FontFactory(); + + // Factory method for the construction of a font factory. + static CALLER_ATTACH FontFactory* GetInstance(); + + // Toggle whether fonts that are loaded are fingerprinted with a SHA-1 hash. + // If a font is fingerprinted then a SHA-1 hash is generated at load time and + // stored in the font. This is useful for uniquely identifying fonts. By + // default this is turned on. + // @param fingerprint whether fingerprinting should be turned on or off + // TODO(arthurhsu): IMPLEMENT: C++ port currently don't do any SHA-1 + void FingerprintFont(bool fingerprint); + bool FingerprintFont(); + + // Load the font(s) from the input stream. The current settings on the factory + // are used during the loading process. One or more fonts are returned if the + // stream contains valid font data. Some font container formats may have more + // 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(InputStream* is, FontArray* output); + + // ByteArray font loading + // Load the font(s) from the byte array. The current settings on the factory + // are used during the loading process. One or more fonts are returned if the + // stream contains valid font data. Some font container formats may have more + // 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); + + // 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 + // font builders are returned if the stream contains valid font data. Some + // 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(InputStream* is, FontBuilderArray* output); + + // Load the font(s) from the byte array into font builders. The current + // settings on the factory are used during the loading process. One or more + // font builders are returned if the stream contains valid font data. Some + // 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); + + // Font serialization + // Serialize the font to the output stream. + // NOTE: in this port we attempted not to implement I/O stream because dealing + // with cross-platform I/O stream itself is big enough as a project. + // 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(); + + private: + // Offsets to specific elements in the underlying data. These offsets are + // relative to the start of the table or the start of sub-blocks within the + // table. + struct Offset { + enum { + // Offsets within the main directory. + kTTCTag = 0, + kVersion = 4, + kNumFonts = 8, + kOffsetTable = 12, + + // TTC Version 2.0 extensions. + // Offsets from end of OffsetTable. + kulDsigTag = 0, + kulDsigLength = 4, + kulDsigOffset = 8 + }; + }; + + FontFactory(); + + CALLER_ATTACH Font* LoadSingleOTF(InputStream* is); + CALLER_ATTACH Font* LoadSingleOTF(WritableFontData* wfd); + + void LoadCollection(InputStream* is, FontArray* output); + void LoadCollection(WritableFontData* wfd, FontArray* output); + + CALLER_ATTACH Font::Builder* LoadSingleOTFForBuilding(InputStream* is); + CALLER_ATTACH Font::Builder* + LoadSingleOTFForBuilding(WritableFontData* wfd, + int32_t offset_to_offset_table); + + void LoadCollectionForBuilding(InputStream* is, FontBuilderArray* builders); + void LoadCollectionForBuilding(WritableFontData* ba, + FontBuilderArray* builders); + + static bool IsCollection(PushbackInputStream* pbis); + static bool IsCollection(ReadableFontData* wfd); + + bool fingerprint_; + IntegerList table_ordering_; +}; +typedef Ptr FontFactoryPtr; + +} // namespace sfntly + +#endif // SFNTLY_CPP_SRC_SFNTLY_FONT_FACTORY_H_ diff --git a/src/sfntly/src/sfntly/math/fixed1616.h b/src/sfntly/src/sfntly/math/fixed1616.h new file mode 100644 index 000000000000..4abbe1809822 --- /dev/null +++ b/src/sfntly/src/sfntly/math/fixed1616.h @@ -0,0 +1,41 @@ +/* + * 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. + */ + +#ifndef SFNTLY_CPP_SRC_SFNTLY_MATH_FIXED1616_H_ +#define SFNTLY_CPP_SRC_SFNTLY_MATH_FIXED1616_H_ + +#include "sfntly/port/type.h" + +namespace sfntly { + +class Fixed1616 { + public: + static inline int32_t Integral(int32_t fixed) { + return (fixed >> 16); + } + + static inline int32_t Fractional(int32_t fixed) { + return (fixed & 0xffff); + } + + static inline int32_t Fixed(int32_t integral, int32_t fractional) { + return ((integral & 0xffff) << 16) | (fractional & 0xffff); + } +}; + +} // namespace sfntly + +#endif // SFNTLY_CPP_SRC_SFNTLY_MATH_FIXED1616_H_ diff --git a/src/sfntly/src/sfntly/math/font_math.h b/src/sfntly/src/sfntly/math/font_math.h new file mode 100644 index 000000000000..f1cd2d2a6f0b --- /dev/null +++ b/src/sfntly/src/sfntly/math/font_math.h @@ -0,0 +1,49 @@ +/* + * 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. + */ + +#ifndef SFNTLY_CPP_SRC_SFNTLY_MATH_FONT_MATH_H_ +#define SFNTLY_CPP_SRC_SFNTLY_MATH_FONT_MATH_H_ + +#include "sfntly/port/type.h" + +namespace sfntly { + +class FontMath { + public: + static int32_t Log2(int32_t a) { + int r = 0; // r will be lg(a) + while (a != 0) { + a >>= 1; + r++; + } + return r - 1; + } + + // Calculates the amount of padding needed. The values provided need to be in + // the same units. So, if the size is given as the number of bytes then the + // alignment size must also be specified as byte size to align to. + // @param size the size of the data that may need padding + // @param alignmentSize the number of units to align to + // @return the number of units needing to be added for alignment + static int32_t PaddingRequired(int32_t size, int32_t alignment_size) { + int32_t padding = alignment_size - (size % alignment_size); + return padding == alignment_size ? 0 : padding; + } +}; + +} // namespace sfntly + +#endif // SFNTLY_CPP_SRC_SFNTLY_MATH_FONT_MATH_H_ diff --git a/src/sfntly/src/sfntly/port/atomic.h b/src/sfntly/src/sfntly/port/atomic.h new file mode 100644 index 000000000000..b381a52af737 --- /dev/null +++ b/src/sfntly/src/sfntly/port/atomic.h @@ -0,0 +1,71 @@ +/* + * 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. + */ + +#ifndef SFNTLY_CPP_SRC_SFNTLY_PORT_ATOMIC_H_ +#define SFNTLY_CPP_SRC_SFNTLY_PORT_ATOMIC_H_ + +#if defined (WIN32) + +#include + +static inline size_t AtomicIncrement(size_t* address) { +#if defined (_WIN64) + return InterlockedIncrement64(reinterpret_cast(address)); +#else + return InterlockedIncrement(reinterpret_cast(address)); +#endif +} + +static inline size_t AtomicDecrement(size_t* address) { +#if defined (_WIN64) + return InterlockedDecrement64(reinterpret_cast(address)); +#else + return InterlockedDecrement(reinterpret_cast(address)); +#endif +} + +#elif defined (__APPLE__) + +#include + +static inline size_t AtomicIncrement(size_t* address) { + return OSAtomicIncrement32Barrier(reinterpret_cast(address)); +} + +static inline size_t AtomicDecrement(size_t* address) { + return OSAtomicDecrement32Barrier(reinterpret_cast(address)); +} + +// Originally we check __GCC_HAVE_SYNC_COMPARE_AND_SWAP_4, however, there are +// issues that clang not carring over this definition. Therefore we boldly +// assume it's gcc or gcc-compatible here. Compilation shall still fail since +// the intrinsics used are GCC-specific. + +#else + +#include + +static inline size_t AtomicIncrement(size_t* address) { + return __sync_add_and_fetch(address, 1); +} + +static inline size_t AtomicDecrement(size_t* address) { + return __sync_sub_and_fetch(address, 1); +} + +#endif // WIN32 + +#endif // SFNTLY_CPP_SRC_SFNTLY_PORT_ATOMIC_H_ diff --git a/src/sfntly/src/sfntly/port/config.h b/src/sfntly/src/sfntly/port/config.h new file mode 100644 index 000000000000..0fcdffe72465 --- /dev/null +++ b/src/sfntly/src/sfntly/port/config.h @@ -0,0 +1,28 @@ +/* + * 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. + */ + +#ifndef SFNTLY_CPP_SRC_SFNTLY_PORT_CONFIG_H_ +#define SFNTLY_CPP_SRC_SFNTLY_PORT_CONFIG_H_ + +#if !defined(SFNTLY_BIG_ENDIAN) && !defined(SFNTLY_LITTLE_ENDIAN) + #if defined (__ppc__) || defined (__ppc64__) + #define SFNTLY_BIG_ENDIAN + #else + #define SFNTLY_LITTLE_ENDIAN + #endif +#endif + +#endif // SFNTLY_CPP_SRC_SFNTLY_PORT_CONFIG_H_ diff --git a/src/sfntly/src/sfntly/port/endian.h b/src/sfntly/src/sfntly/port/endian.h new file mode 100644 index 000000000000..db58f0a307a3 --- /dev/null +++ b/src/sfntly/src/sfntly/port/endian.h @@ -0,0 +1,77 @@ +/* + * 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. + */ + +#ifndef SFNTLY_CPP_SRC_SFNTLY_PORT_ENDIAN_H_ +#define SFNTLY_CPP_SRC_SFNTLY_PORT_ENDIAN_H_ + +#include "sfntly/port/config.h" +#include "sfntly/port/type.h" + +namespace sfntly { + +static inline uint16_t EndianSwap16(uint16_t value) { + return (uint16_t)((value >> 8) | (value << 8)); +} + +static inline int32_t EndianSwap32(int32_t value) { + return (((value & 0x000000ff) << 24) | + ((value & 0x0000ff00) << 8) | + ((value & 0x00ff0000) >> 8) | + ((value & 0xff000000) >> 24)); +} + +static inline uint64_t EndianSwap64(uint64_t value) { + return (((value & 0x00000000000000ffLL) << 56) | + ((value & 0x000000000000ff00LL) << 40) | + ((value & 0x0000000000ff0000LL) << 24) | + ((value & 0x00000000ff000000LL) << 8) | + ((value & 0x000000ff00000000LL) >> 8) | + ((value & 0x0000ff0000000000LL) >> 24) | + ((value & 0x00ff000000000000LL) >> 40) | + ((value & 0xff00000000000000LL) >> 56)); +} + +#ifdef SFNTLY_LITTLE_ENDIAN + #define ToBE16(n) EndianSwap16(n) + #define ToBE32(n) EndianSwap32(n) + #define ToBE64(n) EndianSwap64(n) + #define ToLE16(n) (n) + #define ToLE32(n) (n) + #define ToLE64(n) (n) + #define FromBE16(n) EndianSwap16(n) + #define FromBE32(n) EndianSwap32(n) + #define FromBE64(n) EndianSwap64(n) + #define FromLE16(n) (n) + #define FromLE32(n) (n) + #define FromLE64(n) (n) +#else // SFNTLY_BIG_ENDIAN + #define ToBE16(n) (n) + #define ToBE32(n) (n) + #define ToBE64(n) (n) + #define ToLE16(n) EndianSwap16(n) + #define ToLE32(n) EndianSwap32(n) + #define ToLE64(n) EndianSwap64(n) + #define FromBE16(n) (n) + #define FromBE32(n) (n) + #define FromBE64(n) (n) + #define FromLE16(n) EndianSwap16(n) + #define FromLE32(n) EndianSwap32(n) + #define FromLE64(n) EndianSwap64(n) +#endif + +} // namespace sfntly + +#endif // SFNTLY_CPP_SRC_SFNTLY_PORT_ENDIAN_H_ diff --git a/src/sfntly/src/sfntly/port/exception_type.h b/src/sfntly/src/sfntly/port/exception_type.h new file mode 100644 index 000000000000..b96efcb6c567 --- /dev/null +++ b/src/sfntly/src/sfntly/port/exception_type.h @@ -0,0 +1,125 @@ +/* + * 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. + */ + +// Exceptions used in sfntly + +#ifndef SFNTLY_CPP_SRC_SFNTLY_PORT_EXCEPTION_TYPE_H_ +#define SFNTLY_CPP_SRC_SFNTLY_PORT_EXCEPTION_TYPE_H_ + +#if !defined (SFNTLY_NO_EXCEPTION) + +#include +#include +#include + +namespace sfntly { + +class Exception : public std::exception { + public: + Exception() : what_("Unknown exception") {} + explicit Exception(const char* message) throw() { SetMessage(message); } + virtual ~Exception() throw() {} + virtual const char* what() const throw() { return what_.c_str(); } + + protected: + void SetMessage(const char* message) throw() { + try { + what_ = message; + } catch (...) {} + } + + private: + std::string what_; +}; + +class IndexOutOfBoundException : public Exception { + public: + IndexOutOfBoundException() throw() : Exception("Index out of bound") {} + explicit IndexOutOfBoundException(const char* message) throw() + : Exception(message) {} + IndexOutOfBoundException(const char* message, int32_t index) throw() { + try { + std::ostringstream msg; + msg << message; + msg << ":"; + msg << index; + SetMessage(msg.str().c_str()); + } catch (...) {} + } + virtual ~IndexOutOfBoundException() throw() {} +}; + +class IOException : public Exception { + public: + IOException() throw() : Exception("I/O exception") {} + explicit IOException(const char* message) throw() : Exception(message) {} + virtual ~IOException() throw() {} +}; + +class ArithmeticException : public Exception { + public: + ArithmeticException() throw() : Exception("Arithmetic exception") {} + explicit ArithmeticException(const char* message) throw() + : Exception(message) {} + virtual ~ArithmeticException() throw() {} +}; + +class UnsupportedOperationException : public Exception { + public: + UnsupportedOperationException() throw() : + Exception("Operation not supported") {} + explicit UnsupportedOperationException(const char* message) throw() + : Exception(message) {} + virtual ~UnsupportedOperationException() throw() {} +}; + +class RuntimeException : public Exception { + public: + RuntimeException() throw() : Exception("Runtime exception") {} + explicit RuntimeException(const char* message) throw() + : Exception(message) {} + virtual ~RuntimeException() throw() {} +}; + +class NoSuchElementException : public Exception { + public: + NoSuchElementException() throw() : Exception("No such element") {} + explicit NoSuchElementException(const char* message) throw() + : Exception(message) {} + virtual ~NoSuchElementException() throw() {} +}; + +class IllegalArgumentException : public Exception { + public: + IllegalArgumentException() throw() : Exception("Illegal argument") {} + explicit IllegalArgumentException(const char* message) throw() + : Exception(message) {} + virtual ~IllegalArgumentException() throw() {} +}; + +class IllegalStateException : public Exception { + public: + IllegalStateException() throw() : Exception("Illegal state") {} + explicit IllegalStateException(const char* message) throw() + : Exception(message) {} + virtual ~IllegalStateException() throw() {} +}; + +} // namespace sfntly + +#endif // #if !defined (SFNTLY_NO_EXCEPTION) + +#endif // SFNTLY_CPP_SRC_SFNTLY_PORT_EXCEPTION_TYPE_H_ diff --git a/src/sfntly/src/sfntly/port/file_input_stream.cc b/src/sfntly/src/sfntly/port/file_input_stream.cc new file mode 100644 index 000000000000..5bcb434af05a --- /dev/null +++ b/src/sfntly/src/sfntly/port/file_input_stream.cc @@ -0,0 +1,169 @@ +/* + * 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. + */ + +#if defined (WIN32) +#include +#endif + +#include "sfntly/port/file_input_stream.h" +#include "sfntly/port/exception_type.h" + +namespace sfntly { + +FileInputStream::FileInputStream() + : file_(NULL), + position_(0), + length_(0) { +} + +FileInputStream::~FileInputStream() { + Close(); +} + +int32_t FileInputStream::Available() { + return length_ - position_; +} + +void FileInputStream::Close() { + if (file_) { + fclose(file_); + length_ = 0; + position_ = 0; + file_ = NULL; + } +} + +void FileInputStream::Mark(int32_t readlimit) { + // NOP + UNREFERENCED_PARAMETER(readlimit); +} + +bool FileInputStream::MarkSupported() { + return false; +} + +int32_t FileInputStream::Read() { + if (!file_) { +#if !defined (SFNTLY_NO_EXCEPTION) + throw IOException("no opened file"); +#endif + return 0; + } + if (feof(file_)) { +#if !defined (SFNTLY_NO_EXCEPTION) + throw IOException("eof reached"); +#endif + return 0; + } + byte_t value; + size_t length = fread(&value, 1, 1, file_); + position_ += length; + return value; +} + +int32_t FileInputStream::Read(ByteVector* b) { + return Read(b, 0, b->size()); +} + +int32_t FileInputStream::Read(ByteVector* b, int32_t offset, int32_t length) { + assert(b); + if (!file_) { +#if !defined (SFNTLY_NO_EXCEPTION) + throw IOException("no opened file"); +#endif + return 0; + } + if (feof(file_)) { +#if !defined (SFNTLY_NO_EXCEPTION) + throw IOException("eof reached"); +#endif + return 0; + } + size_t read_count = std::min(length_ - position_, length); + if (b->size() < (size_t)(offset + read_count)) { + b->resize((size_t)(offset + read_count)); + } + int32_t actual_read = fread(&((*b)[offset]), 1, read_count, file_); + position_ += actual_read; + return actual_read; +} + +void FileInputStream::Reset() { + // NOP +} + +int64_t FileInputStream::Skip(int64_t n) { + if (!file_) { +#if !defined (SFNTLY_NO_EXCEPTION) + throw IOException("no opened file"); +#endif + return 0; + } + int64_t skip_count = 0; + if (n < 0) { // move backwards + skip_count = std::max(0 - (int64_t)position_, n); + position_ -= (size_t)(0 - skip_count); + fseek(file_, position_, SEEK_SET); + } else { + skip_count = std::min(length_ - position_, (size_t)n); + position_ += (size_t)skip_count; + fseek(file_, (size_t)skip_count, SEEK_CUR); + } + return skip_count; +} + +void FileInputStream::Unread(ByteVector* b) { + Unread(b, 0, b->size()); +} + +void FileInputStream::Unread(ByteVector* b, int32_t offset, int32_t length) { + assert(b); + assert(b->size() >= size_t(offset + length)); + if (!file_) { +#if !defined (SFNTLY_NO_EXCEPTION) + throw IOException("no opened file"); +#endif + return; + } + size_t unread_count = std::min(position_, length); + fseek(file_, position_ - unread_count, SEEK_SET); + position_ -= unread_count; + Read(b, offset, length); + fseek(file_, position_ - unread_count, SEEK_SET); + position_ -= unread_count; +} + +bool FileInputStream::Open(const char* file_path) { + assert(file_path); + if (file_) { + Close(); + } +#if defined (WIN32) + fopen_s(&file_, file_path, "rb"); +#else + file_ = fopen(file_path, "rb"); +#endif + if (file_ == NULL) { + return false; + } + + fseek(file_, 0, SEEK_END); + length_ = ftell(file_); + fseek(file_, 0, SEEK_SET); + return true; +} + +} // namespace sfntly diff --git a/src/sfntly/src/sfntly/port/file_input_stream.h b/src/sfntly/src/sfntly/port/file_input_stream.h new file mode 100644 index 000000000000..cbca25f7e40c --- /dev/null +++ b/src/sfntly/src/sfntly/port/file_input_stream.h @@ -0,0 +1,57 @@ +/* + * 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. + */ + +#ifndef SFNTLY_CPP_SRC_SFNTLY_PORT_FILE_INPUT_STREAM_H_ +#define SFNTLY_CPP_SRC_SFNTLY_PORT_FILE_INPUT_STREAM_H_ + +#include + +#include "sfntly/port/input_stream.h" + +namespace sfntly { + +class FileInputStream : public PushbackInputStream { + public: + FileInputStream(); + virtual ~FileInputStream(); + + // InputStream methods + 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 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); + + // Own methods + virtual bool Open(const char* file_path); + + private: + FILE* file_; + size_t position_; + size_t length_; +}; + +} // namespace sfntly + +#endif // SFNTLY_CPP_SRC_SFNTLY_PORT_FILE_INPUT_STREAM_H_ diff --git a/src/sfntly/src/sfntly/port/input_stream.h b/src/sfntly/src/sfntly/port/input_stream.h new file mode 100644 index 000000000000..5d24036ea733 --- /dev/null +++ b/src/sfntly/src/sfntly/port/input_stream.h @@ -0,0 +1,49 @@ +/* + * 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. + */ + +#ifndef SFNTLY_CPP_SRC_SFNTLY_PORT_INPUT_STREAM_H_ +#define SFNTLY_CPP_SRC_SFNTLY_PORT_INPUT_STREAM_H_ + +#include "sfntly/port/type.h" + +namespace sfntly { + +// C++ equivalent to Java's OutputStream class +class InputStream { + public: + // Make gcc -Wnon-virtual-dtor happy. + virtual ~InputStream() {} + + 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 void Reset() = 0; + virtual int64_t Skip(int64_t n) = 0; +}; + +class PushbackInputStream : public InputStream { + public: + virtual void Unread(ByteVector* b) = 0; + virtual void Unread(ByteVector* b, int32_t offset, int32_t length) = 0; +}; + +} // namespace sfntly + +#endif // SFNTLY_CPP_SRC_SFNTLY_PORT_INPUT_STREAM_H_ diff --git a/src/sfntly/src/sfntly/port/java_iterator.h b/src/sfntly/src/sfntly/port/java_iterator.h new file mode 100644 index 000000000000..0a99bca1d04e --- /dev/null +++ b/src/sfntly/src/sfntly/port/java_iterator.h @@ -0,0 +1,94 @@ +/* + * 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. + */ + +#ifndef SFNTLY_CPP_SRC_SFNTLY_PORT_JAVA_ITERATOR_H_ +#define SFNTLY_CPP_SRC_SFNTLY_PORT_JAVA_ITERATOR_H_ + +#include "sfntly/port/refcount.h" + +// Interface of Java iterator. +// This is a forward read-only iterator that represents java.util.Iterator + +namespace sfntly { + +template +class Iterator : public virtual RefCount { + public: + virtual ~Iterator() {} + virtual ContainerBase* container_base() = 0; + + protected: + Iterator() {} + NO_COPY_AND_ASSIGN(Iterator); +}; + +template +class PODIterator : public Iterator, + public RefCounted< PODIterator > { + public: + explicit PODIterator(Container* container) : container_(container) {} + virtual ~PODIterator() {} + virtual ContainerBase* container_base() { + return static_cast(container_); + } + + virtual bool HasNext() = 0; + virtual ReturnType Next() = 0; + virtual void Remove() { +#if !defined (SFNTLY_NO_EXCEPTION) + // Default to no support. + throw UnsupportedOperationException(); +#endif + } + + protected: + Container* container() { return container_; } + + private: + Container* container_; // Dumb pointer is used to avoid circular ref-counting +}; + +template +class RefIterator : public Iterator, + public RefCounted< RefIterator > { + public: + explicit RefIterator(Container* container) : container_(container) {} + virtual ~RefIterator() {} + virtual ContainerBase* container_base() { + return static_cast(container_); + } + + virtual bool HasNext() = 0; + CALLER_ATTACH virtual ReturnType* Next() = 0; + virtual void Remove() { +#if !defined (SFNTLY_NO_EXCEPTION) + // Default to no support. + throw UnsupportedOperationException(); +#endif + } + + protected: + Container* container() { return container_; } + + private: + Container* container_; // Dumb pointer is used to avoid circular ref-counting +}; + +} // namespace sfntly + +#endif // SFNTLY_CPP_SRC_SFNTLY_PORT_JAVA_ITERATOR_H_ diff --git a/src/sfntly/src/sfntly/port/lock.cc b/src/sfntly/src/sfntly/port/lock.cc new file mode 100644 index 000000000000..6c0c309a9437 --- /dev/null +++ b/src/sfntly/src/sfntly/port/lock.cc @@ -0,0 +1,72 @@ +/* + * 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. + */ + +#include "sfntly/port/lock.h" + +namespace sfntly { + +#if defined (WIN32) + +Lock::Lock() { + // The second parameter is the spin count, for short-held locks it avoid the + // contending thread from going to sleep which helps performance greatly. + ::InitializeCriticalSectionAndSpinCount(&os_lock_, 2000); +} + +Lock::~Lock() { + ::DeleteCriticalSection(&os_lock_); +} + +bool Lock::Try() { + if (::TryEnterCriticalSection(&os_lock_) != FALSE) { + return true; + } + return false; +} + +void Lock::Acquire() { + ::EnterCriticalSection(&os_lock_); +} + +void Lock::Unlock() { + ::LeaveCriticalSection(&os_lock_); +} + +#else // We assume it's pthread + +Lock::Lock() { + pthread_mutex_init(&os_lock_, NULL); +} + +Lock::~Lock() { + pthread_mutex_destroy(&os_lock_); +} + +bool Lock::Try() { + return (pthread_mutex_trylock(&os_lock_) == 0); +} + +void Lock::Acquire() { + pthread_mutex_lock(&os_lock_); +} + +void Lock::Unlock() { + pthread_mutex_unlock(&os_lock_); +} + +#endif + +} // namespace sfntly diff --git a/src/sfntly/src/sfntly/port/lock.h b/src/sfntly/src/sfntly/port/lock.h new file mode 100644 index 000000000000..b2e29bf64fa2 --- /dev/null +++ b/src/sfntly/src/sfntly/port/lock.h @@ -0,0 +1,76 @@ +/* + * 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. + */ + +#ifndef SFNTLY_CPP_SRC_SFNTLY_PORT_LOCK_H_ +#define SFNTLY_CPP_SRC_SFNTLY_PORT_LOCK_H_ + +#if defined (WIN32) +#include +#else // Assume pthread. +#include +#include +#endif + +#include "sfntly/port/type.h" + +namespace sfntly { + +#if defined (WIN32) + typedef CRITICAL_SECTION OSLockType; +#else // Assume pthread. + typedef pthread_mutex_t OSLockType; +#endif + +class Lock { + public: + Lock(); + ~Lock(); + + // If the lock is not held, take it and return true. If the lock is already + // held by something else, immediately return false. + bool Try(); + + // Take the lock, blocking until it is available if necessary. + void Acquire(); + + // Release the lock. This must only be called by the lock's holder: after + // a successful call to Try, or a call to Lock. + void Unlock(); + + private: + OSLockType os_lock_; + NO_COPY_AND_ASSIGN(Lock); +}; + +// A helper class that acquires the given Lock while the AutoLock is in scope. +class AutoLock { + public: + explicit AutoLock(Lock& lock) : lock_(lock) { + lock_.Acquire(); + } + + ~AutoLock() { + lock_.Unlock(); + } + + private: + Lock& lock_; + NO_COPY_AND_ASSIGN(AutoLock); +}; + +} // namespace sfntly + +#endif // SFNTLY_CPP_SRC_SFNTLY_PORT_LOCK_H_ diff --git a/src/sfntly/src/sfntly/port/memory_input_stream.cc b/src/sfntly/src/sfntly/port/memory_input_stream.cc new file mode 100755 index 000000000000..56ee81e5dd90 --- /dev/null +++ b/src/sfntly/src/sfntly/port/memory_input_stream.cc @@ -0,0 +1,147 @@ +/* + * 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. + */ + +#if defined (WIN32) +#include +#endif + +#include + +#include "sfntly/port/memory_input_stream.h" +#include "sfntly/port/exception_type.h" + +namespace sfntly { + +MemoryInputStream::MemoryInputStream() + : buffer_(NULL), + position_(0), + length_(0) { +} + +MemoryInputStream::~MemoryInputStream() { + Close(); +} + +int32_t MemoryInputStream::Available() { + return length_ - position_; +} + +void MemoryInputStream::Close() { +} + +void MemoryInputStream::Mark(int32_t readlimit) { + // NOP + UNREFERENCED_PARAMETER(readlimit); +} + +bool MemoryInputStream::MarkSupported() { + return false; +} + +int32_t MemoryInputStream::Read() { + if (!buffer_) { +#if !defined (SFNTLY_NO_EXCEPTION) + throw IOException("no memory attached"); +#endif + return 0; + } + if (position_ >= length_) { +#if !defined (SFNTLY_NO_EXCEPTION) + throw IOException("eof reached"); +#endif + return 0; + } + byte_t value = buffer_[position_++]; + return value; +} + +int32_t MemoryInputStream::Read(ByteVector* b) { + return Read(b, 0, b->size()); +} + +int32_t MemoryInputStream::Read(ByteVector* b, int32_t offset, int32_t length) { + assert(b); + if (!buffer_) { +#if !defined (SFNTLY_NO_EXCEPTION) + throw IOException("no memory attached"); +#endif + return 0; + } + if (position_ >= length_) { +#if !defined (SFNTLY_NO_EXCEPTION) + throw IOException("eof reached"); +#endif + return 0; + } + size_t read_count = std::min(length_ - position_, length); + if (b->size() < (size_t)(offset + read_count)) { + b->resize((size_t)(offset + read_count)); + } + memcpy(&((*b)[offset]), buffer_ + position_, read_count); + position_ += read_count; + return read_count; +} + +void MemoryInputStream::Reset() { + // NOP +} + +int64_t MemoryInputStream::Skip(int64_t n) { + if (!buffer_) { +#if !defined (SFNTLY_NO_EXCEPTION) + throw IOException("no memory attached"); +#endif + return 0; + } + int64_t skip_count = 0; + if (n < 0) { // move backwards + skip_count = std::max(0 - (int64_t)position_, n); + position_ -= (size_t)(0 - skip_count); + } else { + skip_count = std::min(length_ - position_, (size_t)n); + position_ += (size_t)skip_count; + } + return skip_count; +} + +void MemoryInputStream::Unread(ByteVector* b) { + Unread(b, 0, b->size()); +} + +void MemoryInputStream::Unread(ByteVector* b, int32_t offset, int32_t length) { + assert(b); + assert(b->size() >= size_t(offset + length)); + if (!buffer_) { +#if !defined (SFNTLY_NO_EXCEPTION) + throw IOException("no memory attached"); +#endif + return; + } + size_t unread_count = std::min(position_, length); + position_ -= unread_count; + Read(b, offset, length); + position_ -= unread_count; +} + +bool MemoryInputStream::Attach(const byte_t* buffer, size_t length) { + assert(buffer); + assert(length); + buffer_ = buffer; + length_ = length; + return true; +} + +} // namespace sfntly diff --git a/src/sfntly/src/sfntly/port/memory_input_stream.h b/src/sfntly/src/sfntly/port/memory_input_stream.h new file mode 100755 index 000000000000..bc861c3f132c --- /dev/null +++ b/src/sfntly/src/sfntly/port/memory_input_stream.h @@ -0,0 +1,57 @@ +/* + * 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. + */ + +#ifndef SFNTLY_CPP_SRC_SFNTLY_PORT_MEMORY_INPUT_STREAM_H_ +#define SFNTLY_CPP_SRC_SFNTLY_PORT_MEMORY_INPUT_STREAM_H_ + +#include + +#include "sfntly/port/input_stream.h" + +namespace sfntly { + +class MemoryInputStream : public PushbackInputStream { + public: + MemoryInputStream(); + virtual ~MemoryInputStream(); + + // InputStream methods + 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 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); + + // Own methods + virtual bool Attach(const byte_t* buffer, size_t length); + + private: + const byte_t* buffer_; + size_t position_; + size_t length_; +}; + +} // namespace sfntly + +#endif // SFNTLY_CPP_SRC_SFNTLY_PORT_MEMORY_INPUT_STREAM_H_ diff --git a/src/sfntly/src/sfntly/port/memory_output_stream.cc b/src/sfntly/src/sfntly/port/memory_output_stream.cc new file mode 100644 index 000000000000..f2ff2e302e9d --- /dev/null +++ b/src/sfntly/src/sfntly/port/memory_output_stream.cc @@ -0,0 +1,72 @@ +/* + * 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. + */ + +#include "sfntly/port/memory_output_stream.h" + +namespace sfntly { + +MemoryOutputStream::MemoryOutputStream() { +} + +MemoryOutputStream::~MemoryOutputStream() { +} + +void MemoryOutputStream::Write(ByteVector* buffer) { + store_.insert(store_.end(), buffer->begin(), buffer->end()); +} + +void MemoryOutputStream::Write(ByteVector* buffer, + int32_t offset, + int32_t length) { + assert(buffer); + if (offset >= 0 && length > 0) { + store_.insert(store_.end(), + buffer->begin() + offset, + buffer->begin() + offset + length); + } else { +#if !defined(SFNTLY_NO_EXCEPTION) + throw IndexOutOfBoundException(); +#endif + } +} + +void MemoryOutputStream::Write(byte_t* buffer, int32_t offset, int32_t length) { + assert(buffer); + if (offset >= 0 && length > 0) { + store_.insert(store_.end(), buffer + offset, buffer + offset + length); + } else { +#if !defined(SFNTLY_NO_EXCEPTION) + throw IndexOutOfBoundException(); +#endif + } +} + +void MemoryOutputStream::Write(byte_t b) { + store_.push_back(b); +} + +byte_t* MemoryOutputStream::Get() { + if (store_.empty()) { + return NULL; + } + return &(store_[0]); +} + +size_t MemoryOutputStream::Size() { + return store_.size(); +} + +} // namespace sfntly diff --git a/src/sfntly/src/sfntly/port/memory_output_stream.h b/src/sfntly/src/sfntly/port/memory_output_stream.h new file mode 100644 index 000000000000..d1eda7faf879 --- /dev/null +++ b/src/sfntly/src/sfntly/port/memory_output_stream.h @@ -0,0 +1,51 @@ +/* + * 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. + */ + +#ifndef SFNTLY_CPP_SRC_SFNTLY_PORT_MEMORY_OUTPUT_STREAM_H_ +#define SFNTLY_CPP_SRC_SFNTLY_PORT_MEMORY_OUTPUT_STREAM_H_ + +#include +#include + +#include "sfntly/port/type.h" +#include "sfntly/port/output_stream.h" + +namespace sfntly { + +// OutputStream backed by STL vector + +class MemoryOutputStream : public OutputStream { + public: + MemoryOutputStream(); + virtual ~MemoryOutputStream(); + + 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); + + byte_t* Get(); + size_t Size(); + + private: + std::vector store_; +}; + +} // namespace sfntly + +#endif // SFNTLY_CPP_SRC_SFNTLY_PORT_MEMORY_OUTPUT_STREAM_H_ diff --git a/src/sfntly/src/sfntly/port/output_stream.h b/src/sfntly/src/sfntly/port/output_stream.h new file mode 100644 index 000000000000..64a602471d59 --- /dev/null +++ b/src/sfntly/src/sfntly/port/output_stream.h @@ -0,0 +1,46 @@ +/* + * 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. + */ + +#ifndef SFNTLY_CPP_SRC_SFNTLY_PORT_OUTPUT_STREAM_H_ +#define SFNTLY_CPP_SRC_SFNTLY_PORT_OUTPUT_STREAM_H_ + +#include "sfntly/port/type.h" + +namespace sfntly { + +// C++ equivalent to Java's OutputStream class +class OutputStream { + public: + // Make gcc -Wnon-virtual-dtor happy. + virtual ~OutputStream() {} + + virtual void Close() = 0; + virtual void Flush() = 0; + virtual void Write(ByteVector* buffer) = 0; + virtual void Write(byte_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; + + // Note: Caller is responsible for the boundary of buffer. + virtual void Write(byte_t* buffer, int32_t offset, int32_t length) = 0; +}; + +} // namespace sfntly + +#endif // SFNTLY_CPP_SRC_SFNTLY_PORT_OUTPUT_STREAM_H_ diff --git a/src/sfntly/src/sfntly/port/refcount.h b/src/sfntly/src/sfntly/port/refcount.h new file mode 100644 index 000000000000..eed51622d7f7 --- /dev/null +++ b/src/sfntly/src/sfntly/port/refcount.h @@ -0,0 +1,277 @@ +/* + * 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. + */ + +// Object reference count and smart pointer implementation. + +// Smart pointer usage in sfntly: +// +// sfntly carries a smart pointer implementation like COM. Ref-countable object +// type inherits from RefCounted<>, which have AddRef and Release just like +// IUnknown (but no QueryInterface). Use a Ptr<> based smart pointer to hold +// the object so that the object ref count is handled correctly. +// +// class Foo : public RefCounted { +// public: +// static Foo* CreateInstance() { +// Ptr obj = new Foo(); // ref count = 1 +// return obj.Detach(); +// } +// }; +// typedef Ptr FooPtr; // common short-hand notation +// FooPtr obj; +// obj.Attach(Foo::CreatedInstance()); // ref count = 1 +// { +// FooPtr obj2 = obj; // ref count = 2 +// } // ref count = 1, obj2 out of scope +// obj.Release(); // ref count = 0, object destroyed + +// Notes on usage: +// 1. Virtual inherit from RefCount interface in base class if smart pointers +// are going to be defined. +// 2. All RefCounted objects must be instantiated on the heap. Allocating the +// object on stack will cause crash. +// 3. Be careful when you have complex inheritance. For example, +// class A : public RefCounted; +// class B : public A, public RefCounted; +// In this case the smart pointer is pretty dumb and don't count on it to +// nicely destroy your objects as designed. Try refactor your code like +// class I; // the common interface and implementations +// class A : public I, public RefCounted; // A specific implementation +// class B : public I, public RefCounted; // B specific implementation +// 4. Smart pointers here are very bad candidates for function parameters. Use +// dumb pointers in function parameter list. +// 5. 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. +// 6. Idioms for heap object as return value +// Foo* createFoo() { FooPtr obj = new Foo(); return obj.Detach(); } +// Foo* passthru() { FooPtr obj = createFoo(), return obj; } +// FooPtr end_scope_pointer; +// end_scope_pointer.Attach(passThrough); +// If you are not passing that object back, you are the end of scope. + +#ifndef SFNTLY_CPP_SRC_SFNTLY_PORT_REFCOUNT_H_ +#define SFNTLY_CPP_SRC_SFNTLY_PORT_REFCOUNT_H_ + +#if !defined (NDEBUG) + #define ENABLE_OBJECT_COUNTER +// #define REF_COUNT_DEBUGGING +#endif + +#if defined (REF_COUNT_DEBUGGING) + #include + #include +#endif + +#include "sfntly/port/atomic.h" +#include "sfntly/port/type.h" + +// Special tag for functions that requires caller to attach instead of using +// assignment operators. +#define CALLER_ATTACH + +#if defined (REF_COUNT_DEBUGGING) + #define DEBUG_OUTPUT(a) \ + fprintf(stderr, "%s%s:oc=%d,oid=%d,rc=%d\n", a, \ + typeid(this).name(), object_counter_, object_id_, ref_count_) +#else + #define DEBUG_OUTPUT(a) +#endif + +#if defined (_MSC_VER) + // VC 2008/2010 incorrectly gives this warning for pure virtual functions + // in virtual inheritance. The only way to get around it is to disable it. + #pragma warning(disable:4250) +#endif + +namespace sfntly { + +class RefCount { + public: + // Make gcc -Wnon-virtual-dtor happy. + virtual ~RefCount() {} + + virtual size_t AddRef() const = 0; + virtual size_t Release() const = 0; +}; + +template +class NoAddRefRelease : public T { + public: + NoAddRefRelease(); + ~NoAddRefRelease(); + + private: + virtual size_t AddRef() const = 0; + virtual size_t Release() const = 0; +}; + +template +class RefCounted : virtual public RefCount { + public: + RefCounted() : ref_count_(0) { +#if defined (ENABLE_OBJECT_COUNTER) + object_id_ = AtomicIncrement(&next_id_); + AtomicIncrement(&object_counter_); + DEBUG_OUTPUT("C "); +#endif + } + RefCounted(const RefCounted&) : ref_count_(0) {} + virtual ~RefCounted() { +#if defined (ENABLE_OBJECT_COUNTER) + AtomicDecrement(&object_counter_); + DEBUG_OUTPUT("D "); +#endif + } + + RefCounted& operator=(const RefCounted&) { + // Each object maintains own ref count, don't propagate. + return *this; + } + + virtual size_t AddRef() const { + size_t new_count = AtomicIncrement(&ref_count_); + DEBUG_OUTPUT("A "); + return new_count; + } + + virtual size_t Release() const { + size_t new_ref_count = AtomicDecrement(&ref_count_); + DEBUG_OUTPUT("R "); + if (new_ref_count == 0) { + // A C-style is used to cast away const-ness and to derived. + // lint does not like this but this is how it works. + delete (TDerived*)(this); + } + return new_ref_count; + } + + mutable size_t ref_count_; // reference count of current object +#if defined (ENABLE_OBJECT_COUNTER) + static size_t object_counter_; + static size_t next_id_; + mutable size_t object_id_; +#endif +}; + +#if defined (ENABLE_OBJECT_COUNTER) +template size_t RefCounted::object_counter_ = 0; +template size_t RefCounted::next_id_ = 0; +#endif + +// semi-smart pointer for RefCount derived objects, similar to CComPtr +template +class Ptr { + public: + Ptr() : p_(NULL) { + } + + // This constructor shall not be explicit. + // lint does not like this but this is how it works. + Ptr(T* pT) : p_(NULL) { + *this = pT; + } + + Ptr(const Ptr& p) : p_(NULL) { + *this = p; + } + + ~Ptr() { + Release(); + } + + T* operator=(T* pT) { + if (p_ == pT) { + return p_; + } + if (pT) { + RefCount* p = static_cast(pT); + if (p == NULL) { + return NULL; + } + p->AddRef(); // always AddRef() before Release() + } + Release(); + p_ = pT; + return p_; + } + + T* operator=(const Ptr& p) { + if (p_ == p.p_) { + return p_; + } + return operator=(p.p_); + } + + operator T*&() { + return p_; + } + + T& operator*() const { + return *p_; // It can throw! + } + + NoAddRefRelease* operator->() const { + return (NoAddRefRelease*)p_; // It can throw! + } + + bool operator!() const { + return (p_ == NULL); + } + + bool operator<(const Ptr& p) const { + return (p_ < p.p_); + } + + bool operator!=(T* pT) const { + return !operator==(pT); + } + + bool operator==(T* pT) const { + return (p_ == pT); + } + + size_t Release() const { + size_t ref_count = 0; + if (p_) { + RefCount* p = static_cast(p_); + if (p) { + ref_count = p->Release(); + } + p_ = NULL; + } + return ref_count; + } + + void Attach(T* pT) { + if (p_ != pT) { + Release(); + p_ = pT; + } + } + + T* Detach() { + T* pT = p_; + p_ = NULL; + return pT; + } + + mutable T* p_; +}; + +} // namespace sfntly + +#endif // SFNTLY_CPP_SRC_SFNTLY_PORT_REFCOUNT_H_ diff --git a/src/sfntly/src/sfntly/port/type.h b/src/sfntly/src/sfntly/port/type.h new file mode 100644 index 000000000000..20a5ba8a8924 --- /dev/null +++ b/src/sfntly/src/sfntly/port/type.h @@ -0,0 +1,102 @@ +/* + * 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. + */ + +#ifndef SFNTLY_CPP_SRC_SFNTLY_PORT_TYPE_H_ +#define SFNTLY_CPP_SRC_SFNTLY_PORT_TYPE_H_ + +#include + +#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 +#endif + +#include +#include +#include + +namespace sfntly { + +typedef uint8_t byte_t; +typedef uint16_t word_t; +typedef uint32_t dword_t; +typedef uint64_t qword_t; + +typedef std::vector ByteVector; +typedef std::vector IntegerList; +typedef std::set IntegerSet; + +// A macro to disallow the copy constructor and operator= functions. +// This should be used in the private: declarations for a class. +#define NO_COPY_AND_ASSIGN(TypeName) \ + TypeName(const TypeName&); \ + void operator=(const TypeName&) + +} // namespace sfntly + +// Make google3 happy since it prohibits RTTI. +template +inline To implicit_cast(From const &f) { + return f; +} + +template // use like this: down_cast(foo); +inline To down_cast(From* f) { // so we only accept pointers + // Ensures that To is a sub-type of From *. This test is here only + // for compile-time type checking, and has no overhead in an + // optimized build at run-time, as it will be optimized away + // completely. +#if defined (_MSC_VER) + #pragma warning(push) + #pragma warning(disable:4127) // disable "conditional expression is constant" +#endif + if (false) { + implicit_cast(0); + } +#if defined (_MSC_VER) + #pragma warning(pop) +#endif + +// The following code is the only place for RTTI. It is done so to allow +// additional type checking when SFNTLY_TYPE_VERIFICATION is defined. +#if defined (SFNTLY_TYPE_VERIFICATION) + assert(f == NULL || dynamic_cast(f) != NULL); +#endif + return static_cast(f); +} + +#if !defined(WIN32) + #define UNREFERENCED_PARAMETER(p) do { (void)p; } while (0) +#endif + +#endif // SFNTLY_CPP_SRC_SFNTLY_PORT_TYPE_H_ diff --git a/src/sfntly/src/sfntly/table/bitmap/big_glyph_metrics.cc b/src/sfntly/src/sfntly/table/bitmap/big_glyph_metrics.cc new file mode 100644 index 000000000000..d853212bbeb1 --- /dev/null +++ b/src/sfntly/src/sfntly/table/bitmap/big_glyph_metrics.cc @@ -0,0 +1,171 @@ +/* + * 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. + */ + +#include "sfntly/table/bitmap/big_glyph_metrics.h" + +namespace sfntly { +/****************************************************************************** + * BigGlyphMetrics class + ******************************************************************************/ +BigGlyphMetrics::BigGlyphMetrics(ReadableFontData* data) + : GlyphMetrics(data) { +} + +BigGlyphMetrics::~BigGlyphMetrics() { +} + +int32_t BigGlyphMetrics::Height() { + return data_->ReadByte(Offset::kHeight); +} + +int32_t BigGlyphMetrics::Width() { + return data_->ReadByte(Offset::kWidth); +} + +int32_t BigGlyphMetrics::HoriBearingX() { + return data_->ReadByte(Offset::kHoriBearingX); +} + +int32_t BigGlyphMetrics::HoriBearingY() { + return data_->ReadByte(Offset::kHoriBearingY); +} + +int32_t BigGlyphMetrics::HoriAdvance() { + return data_->ReadByte(Offset::kHoriAdvance); +} + +int32_t BigGlyphMetrics::VertBearingX() { + return data_->ReadByte(Offset::kVertBearingX); +} + +int32_t BigGlyphMetrics::VertBearingY() { + return data_->ReadByte(Offset::kVertBearingY); +} + +int32_t BigGlyphMetrics::VertAdvance() { + return data_->ReadByte(Offset::kVertAdvance); +} + +/****************************************************************************** + * BigGlyphMetrics::Builder class + ******************************************************************************/ +BigGlyphMetrics::Builder::Builder(WritableFontData* data) + : GlyphMetrics::Builder(data) { +} + +BigGlyphMetrics::Builder::Builder(ReadableFontData* data) + : GlyphMetrics::Builder(data) { +} + +BigGlyphMetrics::Builder::~Builder() { +} + +int32_t BigGlyphMetrics::Builder::Height() { + return InternalReadData()->ReadByte(Offset::kHeight); +} + +void BigGlyphMetrics::Builder::SetHeight(byte_t height) { + InternalWriteData()->WriteByte(Offset::kHeight, height); +} + +int32_t BigGlyphMetrics::Builder::Width() { + return InternalReadData()->ReadByte(Offset::kWidth); +} + +void BigGlyphMetrics::Builder::SetWidth(byte_t width) { + InternalWriteData()->WriteByte(Offset::kWidth, width); +} + +int32_t BigGlyphMetrics::Builder::HoriBearingX() { + return InternalReadData()->ReadByte(Offset::kHoriBearingX); +} + +void BigGlyphMetrics::Builder::SetHoriBearingX(byte_t bearing) { + InternalWriteData()->WriteByte(Offset::kHoriBearingX, bearing); +} + +int32_t BigGlyphMetrics::Builder::HoriBearingY() { + return InternalReadData()->ReadByte(Offset::kHoriBearingY); +} + +void BigGlyphMetrics::Builder::SetHoriBearingY(byte_t bearing) { + InternalWriteData()->WriteByte(Offset::kHoriBearingY, bearing); +} + +int32_t BigGlyphMetrics::Builder::HoriAdvance() { + return InternalReadData()->ReadByte(Offset::kHoriAdvance); +} + +void BigGlyphMetrics::Builder::SetHoriAdvance(byte_t advance) { + InternalWriteData()->WriteByte(Offset::kHoriAdvance, advance); +} + +int32_t BigGlyphMetrics::Builder::VertBearingX() { + return InternalReadData()->ReadByte(Offset::kVertBearingX); +} + +void BigGlyphMetrics::Builder::SetVertBearingX(byte_t bearing) { + InternalWriteData()->WriteByte(Offset::kVertBearingX, bearing); +} + +int32_t BigGlyphMetrics::Builder::VertBearingY() { + return InternalReadData()->ReadByte(Offset::kVertBearingY); +} + +void BigGlyphMetrics::Builder::SetVertBearingY(byte_t bearing) { + InternalWriteData()->WriteByte(Offset::kVertBearingY, bearing); +} + +int32_t BigGlyphMetrics::Builder::VertAdvance() { + return InternalReadData()->ReadByte(Offset::kVertAdvance); +} + +void BigGlyphMetrics::Builder::SetVertAdvance(byte_t advance) { + InternalWriteData()->WriteByte(Offset::kVertAdvance, advance); +} + +CALLER_ATTACH FontDataTable* + BigGlyphMetrics::Builder::SubBuildTable(ReadableFontData* data) { + BigGlyphMetricsPtr output = new BigGlyphMetrics(data); + return output.Detach(); +} + +void BigGlyphMetrics::Builder::SubDataSet() { + // NOP. +} + +int32_t BigGlyphMetrics::Builder::SubDataSizeToSerialize() { + return 0; +} + +bool BigGlyphMetrics::Builder::SubReadyToSerialize() { + return false; +} + +int32_t BigGlyphMetrics::Builder::SubSerialize(WritableFontData* new_data) { + return Data()->CopyTo(new_data); +} + +// static +CALLER_ATTACH +BigGlyphMetrics::Builder* BigGlyphMetrics::Builder::CreateBuilder() { + WritableFontDataPtr data; + data.Attach(WritableFontData::CreateWritableFontData(Offset::kMetricsLength)); + BigGlyphMetricsBuilderPtr output = new BigGlyphMetrics::Builder(data); + return output.Detach(); +} + +} // namespace sfntly diff --git a/src/sfntly/src/sfntly/table/bitmap/big_glyph_metrics.h b/src/sfntly/src/sfntly/table/bitmap/big_glyph_metrics.h new file mode 100644 index 000000000000..a91601c211be --- /dev/null +++ b/src/sfntly/src/sfntly/table/bitmap/big_glyph_metrics.h @@ -0,0 +1,96 @@ +/* + * 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. + */ + +#ifndef SFNTLY_CPP_SRC_SFNTLY_TABLE_BITMAP_BIG_GLYPH_METRICS_H_ +#define SFNTLY_CPP_SRC_SFNTLY_TABLE_BITMAP_BIG_GLYPH_METRICS_H_ + +#include "sfntly/table/bitmap/glyph_metrics.h" + +namespace sfntly { + +class BigGlyphMetrics : public GlyphMetrics, + public RefCounted { + public: + struct Offset { + enum { + kMetricsLength = 8, + + kHeight = 0, + kWidth = 1, + kHoriBearingX = 2, + kHoriBearingY = 3, + kHoriAdvance = 4, + kVertBearingX = 5, + kVertBearingY = 6, + kVertAdvance = 7, + }; + }; + + class Builder : public GlyphMetrics::Builder, + public RefCounted { + public: + // Constructor scope altered to public because C++ does not allow base + // class to instantiate derived class with protected constructors. + explicit Builder(WritableFontData* data); + explicit Builder(ReadableFontData* data); + + virtual ~Builder(); + + int32_t Height(); + void SetHeight(byte_t height); + int32_t Width(); + void SetWidth(byte_t width); + int32_t HoriBearingX(); + void SetHoriBearingX(byte_t bearing); + int32_t HoriBearingY(); + void SetHoriBearingY(byte_t bearing); + int32_t HoriAdvance(); + void SetHoriAdvance(byte_t advance); + int32_t VertBearingX(); + void SetVertBearingX(byte_t bearing); + int32_t VertBearingY(); + void SetVertBearingY(byte_t bearing); + int32_t VertAdvance(); + void SetVertAdvance(byte_t advance); + + virtual CALLER_ATTACH FontDataTable* SubBuildTable(ReadableFontData* data); + virtual void SubDataSet(); + virtual int32_t SubDataSizeToSerialize(); + virtual bool SubReadyToSerialize(); + virtual int32_t SubSerialize(WritableFontData* new_data); + + // Static instantiation function. + static CALLER_ATTACH Builder* CreateBuilder(); + }; + + explicit BigGlyphMetrics(ReadableFontData* data); + virtual ~BigGlyphMetrics(); + + int32_t Height(); + int32_t Width(); + int32_t HoriBearingX(); + int32_t HoriBearingY(); + int32_t HoriAdvance(); + int32_t VertBearingX(); + int32_t VertBearingY(); + int32_t VertAdvance(); +}; +typedef Ptr BigGlyphMetricsPtr; +typedef Ptr BigGlyphMetricsBuilderPtr; + +} // namespace sfntly + +#endif // SFNTLY_CPP_SRC_SFNTLY_TABLE_BITMAP_BIG_GLYPH_METRICS_H_ diff --git a/src/sfntly/src/sfntly/table/bitmap/bitmap_glyph.cc b/src/sfntly/src/sfntly/table/bitmap/bitmap_glyph.cc new file mode 100644 index 000000000000..334a0c07fb49 --- /dev/null +++ b/src/sfntly/src/sfntly/table/bitmap/bitmap_glyph.cc @@ -0,0 +1,101 @@ +/* + * 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. + */ + +#include "sfntly/table/bitmap/bitmap_glyph.h" +#include "sfntly/table/bitmap/simple_bitmap_glyph.h" +#include "sfntly/table/bitmap/composite_bitmap_glyph.h" + +namespace sfntly { +/****************************************************************************** + * BitmapGlyph class + ******************************************************************************/ +BitmapGlyph::~BitmapGlyph() { +} + +CALLER_ATTACH BitmapGlyph* BitmapGlyph::CreateGlyph(ReadableFontData* data, + int32_t format) { + BitmapGlyphPtr glyph; + BitmapGlyphBuilderPtr builder; + builder.Attach(Builder::CreateGlyphBuilder(data, format)); + if (builder) { + glyph.Attach(down_cast(builder->Build())); + } + return glyph; +} + +BitmapGlyph::BitmapGlyph(ReadableFontData* data, int32_t format) + : SubTable(data), format_(format) { +} + +/****************************************************************************** + * BitmapGlyph::Builder class + ******************************************************************************/ +BitmapGlyph::Builder::~Builder() { +} + +CALLER_ATTACH BitmapGlyph::Builder* +BitmapGlyph::Builder::CreateGlyphBuilder(ReadableFontData* data, + int32_t format) { + BitmapGlyphBuilderPtr builder; + switch (format) { + case 1: + case 2: + case 3: + case 4: + case 5: + case 6: + case 7: + builder = new SimpleBitmapGlyph::Builder(data, format); + break; + case 8: + case 9: + builder = new CompositeBitmapGlyph::Builder(data, format); + break; + } + return builder.Detach(); +} + +BitmapGlyph::Builder::Builder(WritableFontData* data, int32_t format) + : SubTable::Builder(data), format_(format) { +} + +BitmapGlyph::Builder::Builder(ReadableFontData* data, int32_t format) + : SubTable::Builder(data), format_(format) { +} + +CALLER_ATTACH +FontDataTable* BitmapGlyph::Builder::SubBuildTable(ReadableFontData* data) { + UNREFERENCED_PARAMETER(data); + return NULL; +} + +void BitmapGlyph::Builder::SubDataSet() { + // NOP +} + +int32_t BitmapGlyph::Builder::SubDataSizeToSerialize() { + return InternalReadData()->Length(); +} + +bool BitmapGlyph::Builder::SubReadyToSerialize() { + return true; +} + +int32_t BitmapGlyph::Builder::SubSerialize(WritableFontData* new_data) { + return InternalReadData()->CopyTo(new_data); +} + +} // namespace sfntly diff --git a/src/sfntly/src/sfntly/table/bitmap/bitmap_glyph.h b/src/sfntly/src/sfntly/table/bitmap/bitmap_glyph.h new file mode 100644 index 000000000000..2dd4c3a130ce --- /dev/null +++ b/src/sfntly/src/sfntly/table/bitmap/bitmap_glyph.h @@ -0,0 +1,119 @@ +/* + * 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. + */ + +#ifndef SFNTLY_CPP_SRC_SFNTLY_TABLE_BITMAP_BITMAP_GLYPH_H_ +#define SFNTLY_CPP_SRC_SFNTLY_TABLE_BITMAP_BITMAP_GLYPH_H_ + +#include +#include + +#include "sfntly/table/subtable.h" + +namespace sfntly { + +class BitmapGlyph : public SubTable { + public: + struct Offset { + enum { + // header + kVersion = 0, + + kSmallGlyphMetricsLength = 5, + kBigGlyphMetricsLength = 8, + // format 1 + kGlyphFormat1_imageData = kSmallGlyphMetricsLength, + + // format 2 + kGlyphFormat2_imageData = kSmallGlyphMetricsLength, + + // format 3 + + // format 4 + + // format 5 + kGlyphFormat5_imageData = 0, + + // format 6 + kGlyphFormat6_imageData = kBigGlyphMetricsLength, + + // format 7 + kGlyphFormat7_imageData = kBigGlyphMetricsLength, + + // format 8 + kGlyphFormat8_numComponents = kSmallGlyphMetricsLength + 1, + kGlyphFormat8_componentArray = kGlyphFormat8_numComponents + + DataSize::kUSHORT, + + // format 9 + kGlyphFormat9_numComponents = kBigGlyphMetricsLength, + kGlyphFormat9_componentArray = kGlyphFormat9_numComponents + + DataSize::kUSHORT, + + // ebdtComponent + kEbdtComponentLength = DataSize::kUSHORT + 2 * DataSize::kCHAR, + kEbdtComponent_glyphCode = 0, + kEbdtComponent_xOffset = 2, + kEbdtComponent_yOffset = 3, + }; + }; + + // TODO(stuartg): builder is not functional at all + // - need to add subclasses for each type of bitmap glyph + class Builder : public SubTable::Builder { + public: + virtual ~Builder(); + + virtual CALLER_ATTACH FontDataTable* SubBuildTable(ReadableFontData* data); + virtual void SubDataSet(); + virtual int32_t SubDataSizeToSerialize(); + virtual bool SubReadyToSerialize(); + virtual int32_t SubSerialize(WritableFontData* new_data); + + int32_t format() { return format_; } + + static CALLER_ATTACH Builder* CreateGlyphBuilder(ReadableFontData* data, + int32_t format); + + protected: + Builder(WritableFontData* data, int32_t format); + Builder(ReadableFontData* data, int32_t format); + + private: + int32_t format_; + }; + + virtual ~BitmapGlyph(); + + static CALLER_ATTACH BitmapGlyph* CreateGlyph(ReadableFontData* data, + int32_t format); + int32_t format() { return format_; } + + // UNIMPLEMENTED: toString() + + protected: + BitmapGlyph(ReadableFontData* data, int32_t format); + + private: + int32_t format_; +}; +typedef Ptr BitmapGlyphPtr; +typedef Ptr BitmapGlyphBuilderPtr; +typedef std::map BitmapGlyphBuilderMap; +typedef std::vector BitmapGlyphBuilderList; + +} // namespace sfntly + +#endif // SFNTLY_CPP_SRC_SFNTLY_TABLE_BITMAP_BITMAP_GLYPH_H_ diff --git a/src/sfntly/src/sfntly/table/bitmap/bitmap_glyph_info.cc b/src/sfntly/src/sfntly/table/bitmap/bitmap_glyph_info.cc new file mode 100644 index 000000000000..ab9953bc7704 --- /dev/null +++ b/src/sfntly/src/sfntly/table/bitmap/bitmap_glyph_info.cc @@ -0,0 +1,68 @@ +/* + * 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. + */ + +#include "sfntly/table/bitmap/bitmap_glyph_info.h" + +namespace sfntly { + +BitmapGlyphInfo::BitmapGlyphInfo(int32_t glyph_id, + int32_t block_offset, + int32_t start_offset, + int32_t length, + int32_t format) + : glyph_id_(glyph_id), + relative_(true), + block_offset_(block_offset), + start_offset_(start_offset), + length_(length), + format_(format) { +} + +BitmapGlyphInfo::BitmapGlyphInfo(int32_t glyph_id, + int32_t start_offset, + int32_t length, + int32_t format) + : glyph_id_(glyph_id), + relative_(false), + block_offset_(0), + start_offset_(start_offset), + length_(length), + format_(format) { +} + +bool BitmapGlyphInfo::operator==(const BitmapGlyphInfo& rhs) const { + return (format_ == rhs.format_ && + glyph_id_ == rhs.glyph_id_ && + length_ == rhs.length_ && + offset() == rhs.offset()); +} + +bool BitmapGlyphInfo::operator==(BitmapGlyphInfo* rhs) { + if (rhs == NULL) { + return this == NULL; + } + return (format_ == rhs->format() && + glyph_id_ == rhs->glyph_id() && + length_ == rhs->length() && + offset() == rhs->offset()); +} + +bool StartOffsetComparator::operator()(BitmapGlyphInfo* lhs, + BitmapGlyphInfo* rhs) { + return lhs->start_offset() > rhs->start_offset(); +} + +} // namespace sfntly diff --git a/src/sfntly/src/sfntly/table/bitmap/bitmap_glyph_info.h b/src/sfntly/src/sfntly/table/bitmap/bitmap_glyph_info.h new file mode 100644 index 000000000000..9921d0d526a4 --- /dev/null +++ b/src/sfntly/src/sfntly/table/bitmap/bitmap_glyph_info.h @@ -0,0 +1,85 @@ +/* + * 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. + */ + +#ifndef SFNTLY_CPP_SRC_SFNTLY_TABLE_BITMAP_GLYPH_INFO_H_ +#define SFNTLY_CPP_SRC_SFNTLY_TABLE_BITMAP_GLYPH_INFO_H_ + +#include +#include + +#include "sfntly/table/subtable.h" + +namespace sfntly { + +// An immutable class holding bitmap glyph information. +class BitmapGlyphInfo : public RefCounted { + public: + // Constructor for a relative located glyph. The glyph's position in the EBDT + // table is a combination of it's block offset and it's own start offset. + // @param glyphId the glyph id + // @param blockOffset the offset of the block to which the glyph belongs + // @param startOffset the offset of the glyph within the block + // @param length the byte length + // @param format the glyph image format + BitmapGlyphInfo(int32_t glyph_id, + int32_t block_offset, + int32_t start_offset, + int32_t length, + int32_t format); + + // Constructor for an absolute located glyph. The glyph's position in the EBDT + // table is only given by it's own start offset. + // @param glyphId the glyph id + // @param startOffset the offset of the glyph within the block + // @param length the byte length + // @param format the glyph image format + BitmapGlyphInfo(int32_t glyph_id, + int32_t start_offset, + int32_t length, + int32_t format); + + int32_t glyph_id() const { return glyph_id_; } + bool relative() const { return relative_; } + int32_t block_offset() const { return block_offset_; } + int32_t offset() const { return block_offset() + start_offset(); } + int32_t start_offset() const { return start_offset_; } + int32_t length() const { return length_; } + int32_t format() const { return format_; } + + // UNIMPLEMENTED: hashCode() + bool operator==(const BitmapGlyphInfo& rhs) const; + bool operator==(BitmapGlyphInfo* rhs); + + private: + int32_t glyph_id_; + bool relative_; + int32_t block_offset_; + int32_t start_offset_; + int32_t length_; + int32_t format_; +}; +typedef Ptr BitmapGlyphInfoPtr; +typedef std::map BitmapGlyphInfoMap; +typedef std::vector BitmapLocaList; + +class StartOffsetComparator { + public: + bool operator()(BitmapGlyphInfo* lhs, BitmapGlyphInfo* rhs); +}; + +} // namespace sfntly + +#endif // SFNTLY_CPP_SRC_SFNTLY_TABLE_BITMAP_GLYPH_INFO_H_ diff --git a/src/sfntly/src/sfntly/table/bitmap/bitmap_size_table.cc b/src/sfntly/src/sfntly/table/bitmap/bitmap_size_table.cc new file mode 100644 index 000000000000..6c7d7315a453 --- /dev/null +++ b/src/sfntly/src/sfntly/table/bitmap/bitmap_size_table.cc @@ -0,0 +1,604 @@ +/* + * 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. + */ + +#include "sfntly/table/bitmap/bitmap_size_table.h" + +#include +#include + +#include "sfntly/math/font_math.h" +#include "sfntly/table/bitmap/eblc_table.h" +#include "sfntly/table/bitmap/index_sub_table_format1.h" +#include "sfntly/table/bitmap/index_sub_table_format2.h" +#include "sfntly/table/bitmap/index_sub_table_format3.h" +#include "sfntly/table/bitmap/index_sub_table_format4.h" +#include "sfntly/table/bitmap/index_sub_table_format5.h" + +namespace sfntly { +/****************************************************************************** + * BitmapSizeTable class + ******************************************************************************/ +BitmapSizeTable::~BitmapSizeTable() { +} + +int32_t BitmapSizeTable::IndexSubTableArrayOffset() { + return data_->ReadULongAsInt( + EblcTable::Offset::kBitmapSizeTable_indexSubTableArrayOffset); +} + +int32_t BitmapSizeTable::IndexTableSize() { + return data_->ReadULongAsInt( + EblcTable::Offset::kBitmapSizeTable_indexTableSize); +} + +int32_t BitmapSizeTable::NumberOfIndexSubTables() { + return NumberOfIndexSubTables(data_, 0); +} + +int32_t BitmapSizeTable::ColorRef() { + return data_->ReadULongAsInt(EblcTable::Offset::kBitmapSizeTable_colorRef); +} + +int32_t BitmapSizeTable::StartGlyphIndex() { + return data_->ReadUShort(EblcTable::Offset::kBitmapSizeTable_startGlyphIndex); +} + +int32_t BitmapSizeTable::EndGlyphIndex() { + return data_->ReadUShort(EblcTable::Offset::kBitmapSizeTable_endGlyphIndex); +} + +int32_t BitmapSizeTable::PpemX() { + return data_->ReadByte(EblcTable::Offset::kBitmapSizeTable_ppemX); +} + +int32_t BitmapSizeTable::PpemY() { + return data_->ReadByte(EblcTable::Offset::kBitmapSizeTable_ppemY); +} + +int32_t BitmapSizeTable::BitDepth() { + return data_->ReadByte(EblcTable::Offset::kBitmapSizeTable_bitDepth); +} + +int32_t BitmapSizeTable::FlagsAsInt() { + return data_->ReadChar(EblcTable::Offset::kBitmapSizeTable_flags); +} + +IndexSubTable* BitmapSizeTable::GetIndexSubTable(int32_t index) { + IndexSubTableList* subtable_list = GetIndexSubTableList(); + if (index >= 0 && (size_t)index < subtable_list->size()) { + return (*subtable_list)[index]; + } + return NULL; +} + +int32_t BitmapSizeTable::GlyphOffset(int32_t glyph_id) { + IndexSubTable* subtable = SearchIndexSubTables(glyph_id); + if (subtable == NULL) { + return -1; + } + return subtable->GlyphOffset(glyph_id); +} + +int32_t BitmapSizeTable::GlyphLength(int32_t glyph_id) { + IndexSubTable* subtable = SearchIndexSubTables(glyph_id); + if (subtable == NULL) { + return -1; + } + return subtable->GlyphLength(glyph_id); +} + +CALLER_ATTACH BitmapGlyphInfo* BitmapSizeTable::GlyphInfo(int32_t glyph_id) { + IndexSubTable* sub_table = SearchIndexSubTables(glyph_id); + if (sub_table == NULL) { + return NULL; + } + return sub_table->GlyphInfo(glyph_id); +} + +int32_t BitmapSizeTable::GlyphFormat(int32_t glyph_id) { + IndexSubTable* subtable = SearchIndexSubTables(glyph_id); + if (subtable == NULL) { + return -1; + } + return subtable->image_format(); +} + +BitmapSizeTable::BitmapSizeTable(ReadableFontData* data, + ReadableFontData* master_data) + : SubTable(data, master_data) { +} + +// static +int32_t BitmapSizeTable::NumberOfIndexSubTables(ReadableFontData* data, + int32_t table_offset) { + return data->ReadULongAsInt(table_offset + + EblcTable::Offset::kBitmapSizeTable_numberOfIndexSubTables); +} + +IndexSubTable* BitmapSizeTable::SearchIndexSubTables(int32_t glyph_id) { + // would be faster to binary search but too many size tables don't have + // sorted subtables +#if (SFNTLY_BITMAPSIZE_USE_BINARY_SEARCH) + return BinarySearchIndexSubTables(glyph_id); +#else + return LinearSearchIndexSubTables(glyph_id); +#endif +} + +IndexSubTable* BitmapSizeTable::LinearSearchIndexSubTables(int32_t glyph_id) { + IndexSubTableList* subtable_list = GetIndexSubTableList(); + for (IndexSubTableList::iterator b = subtable_list->begin(), + e = subtable_list->end(); b != e; b++) { + if ((*b)->first_glyph_index() <= glyph_id && + (*b)->last_glyph_index() >= glyph_id) { + return *b; + } + } + return NULL; +} + +IndexSubTable* BitmapSizeTable::BinarySearchIndexSubTables(int32_t glyph_id) { + IndexSubTableList* subtable_list = GetIndexSubTableList(); + int32_t index = 0; + int32_t bottom = 0; + int32_t top = subtable_list->size(); + while (top != bottom) { + index = (top + bottom) / 2; + IndexSubTable* subtable = (*subtable_list)[index]; + if (glyph_id < subtable->first_glyph_index()) { + // Location beow current location + top = index; + } else { + if (glyph_id <= subtable->last_glyph_index()) { + return subtable; + } else { + bottom = index + 1; + } + } + } + return NULL; +} + +CALLER_ATTACH +IndexSubTable* BitmapSizeTable::CreateIndexSubTable(int32_t index) { + return IndexSubTable::CreateIndexSubTable(master_read_data(), + IndexSubTableArrayOffset(), + index); +} + +IndexSubTableList* BitmapSizeTable::GetIndexSubTableList() { + AutoLock lock(index_subtables_lock_); + if (index_subtables_.empty()) { + for (int32_t i = 0; i < NumberOfIndexSubTables(); ++i) { + IndexSubTablePtr table; + table.Attach(CreateIndexSubTable(i)); + index_subtables_.push_back(table); + } + } + return &index_subtables_; +} + +/****************************************************************************** + * BitmapSizeTable::Builder class + ******************************************************************************/ +BitmapSizeTable::Builder::~Builder() { +} + +CALLER_ATTACH +FontDataTable* BitmapSizeTable::Builder::SubBuildTable(ReadableFontData* data) { + BitmapSizeTablePtr output = new BitmapSizeTable(data, master_read_data()); + return output.Detach(); +} + +void BitmapSizeTable::Builder::SubDataSet() { + Revert(); +} + +int32_t BitmapSizeTable::Builder::SubDataSizeToSerialize() { + IndexSubTableBuilderList* builders = IndexSubTableBuilders(); + if (builders->empty()) { + return 0; + } + int32_t size = EblcTable::Offset::kBitmapSizeTableLength; + bool variable = false; + for (IndexSubTableBuilderList::iterator b = builders->begin(), + e = builders->end(); b != e; b++) { + size += EblcTable::Offset::kIndexSubTableEntryLength; + int32_t sub_table_size = (*b)->SubDataSizeToSerialize(); + int32_t padding = FontMath::PaddingRequired(abs(sub_table_size), + DataSize::kULONG); +#if defined (SFNTLY_DEBUG_BITMAP) + fprintf(stderr, "subtable size=%d\n", sub_table_size); +#endif + variable = (sub_table_size > 0) ? variable : true; + size += abs(sub_table_size) + padding; + } +#if defined (SFNTLY_DEBUG_BITMAP) + fprintf(stderr, "bitmap table size=%d\n", variable ? -size : size); +#endif + return variable ? -size : size; +} + +bool BitmapSizeTable::Builder::SubReadyToSerialize() { + if (IndexSubTableBuilders()->empty()) { + return false; + } + return true; +} + +int32_t BitmapSizeTable::Builder::SubSerialize(WritableFontData* new_data) { + SetNumberOfIndexSubTables(IndexSubTableBuilders()->size()); + int32_t size = InternalReadData()->CopyTo(new_data); + return size; +} + +CALLER_ATTACH BitmapSizeTable::Builder* +BitmapSizeTable::Builder::CreateBuilder(WritableFontData* data, + ReadableFontData* master_data) { + BitmapSizeTableBuilderPtr output = + new BitmapSizeTable::Builder(data, master_data); + return output.Detach(); +} + +CALLER_ATTACH BitmapSizeTable::Builder* +BitmapSizeTable::Builder::CreateBuilder(ReadableFontData* data, + ReadableFontData* master_data) { + BitmapSizeTableBuilderPtr output = + new BitmapSizeTable::Builder(data, master_data); + return output.Detach(); +} + +int32_t BitmapSizeTable::Builder::IndexSubTableArrayOffset() { + return InternalReadData()->ReadULongAsInt( + EblcTable::Offset::kBitmapSizeTable_indexSubTableArrayOffset); +} + +void BitmapSizeTable::Builder::SetIndexSubTableArrayOffset(int32_t offset) { + InternalWriteData()->WriteULong( + EblcTable::Offset::kBitmapSizeTable_indexSubTableArrayOffset, offset); +} + +int32_t BitmapSizeTable::Builder::IndexTableSize() { + return InternalReadData()->ReadULongAsInt( + EblcTable::Offset::kBitmapSizeTable_indexTableSize); +} + +void BitmapSizeTable::Builder::SetIndexTableSize(int32_t size) { + InternalWriteData()->WriteULong( + EblcTable::Offset::kBitmapSizeTable_indexTableSize, size); +} + +int32_t BitmapSizeTable::Builder::NumberOfIndexSubTables() { + return GetIndexSubTableBuilders()->size(); +} + +int32_t BitmapSizeTable::Builder::ColorRef() { + return InternalReadData()->ReadULongAsInt( + EblcTable::Offset::kBitmapSizeTable_colorRef); +} + +int32_t BitmapSizeTable::Builder::StartGlyphIndex() { + return InternalReadData()->ReadUShort( + EblcTable::Offset::kBitmapSizeTable_startGlyphIndex); +} + +int32_t BitmapSizeTable::Builder::EndGlyphIndex() { + return InternalReadData()->ReadUShort( + EblcTable::Offset::kBitmapSizeTable_endGlyphIndex); +} + +int32_t BitmapSizeTable::Builder::PpemX() { + return InternalReadData()->ReadByte( + EblcTable::Offset::kBitmapSizeTable_ppemX); +} + +int32_t BitmapSizeTable::Builder::PpemY() { + return InternalReadData()->ReadByte( + EblcTable::Offset::kBitmapSizeTable_ppemY); +} + +int32_t BitmapSizeTable::Builder::BitDepth() { + return InternalReadData()->ReadByte( + EblcTable::Offset::kBitmapSizeTable_bitDepth); +} + +int32_t BitmapSizeTable::Builder::FlagsAsInt() { + return InternalReadData()->ReadChar( + EblcTable::Offset::kBitmapSizeTable_flags); +} + +IndexSubTable::Builder* BitmapSizeTable::Builder::IndexSubTableBuilder( + int32_t index) { + IndexSubTableBuilderList* sub_table_list = GetIndexSubTableBuilders(); + return sub_table_list->at(index); +} + +CALLER_ATTACH BitmapGlyphInfo* BitmapSizeTable::Builder::GlyphInfo( + int32_t glyph_id) { + IndexSubTable::Builder* sub_table = SearchIndexSubTables(glyph_id); + if (sub_table == NULL) { + return NULL; + } + return sub_table->GlyphInfo(glyph_id); +} + +int32_t BitmapSizeTable::Builder::GlyphOffset(int32_t glyph_id) { + IndexSubTable::Builder* subtable = SearchIndexSubTables(glyph_id); + if (subtable == NULL) { + return -1; + } + return subtable->GlyphOffset(glyph_id); +} + +int32_t BitmapSizeTable::Builder::GlyphLength(int32_t glyph_id) { + IndexSubTable::Builder* subtable = SearchIndexSubTables(glyph_id); + if (subtable == NULL) { + return -1; + } + return subtable->GlyphLength(glyph_id); +} + +int32_t BitmapSizeTable::Builder::GlyphFormat(int32_t glyph_id) { + IndexSubTable::Builder* subtable = SearchIndexSubTables(glyph_id); + if (subtable == NULL) { + return -1; + } + return subtable->image_format(); +} + +IndexSubTableBuilderList* BitmapSizeTable::Builder::IndexSubTableBuilders() { + return GetIndexSubTableBuilders(); +} + +CALLER_ATTACH BitmapSizeTable::Builder::BitmapGlyphInfoIterator* +BitmapSizeTable::Builder::GetIterator() { + Ptr output = + new BitmapSizeTable::Builder::BitmapGlyphInfoIterator(this); + return output.Detach(); +} + +void BitmapSizeTable::Builder::GenerateLocaMap(BitmapGlyphInfoMap* output) { + assert(output); + Ptr it; + it.Attach(GetIterator()); + while (it->HasNext()) { + BitmapGlyphInfoPtr info; + info.Attach(it->Next()); + (*output)[info->glyph_id()] = info; + } +} + +void BitmapSizeTable::Builder::Revert() { + index_sub_tables_.clear(); + set_model_changed(false); +} + +BitmapSizeTable::Builder::Builder(WritableFontData* data, + ReadableFontData* master_data) + : SubTable::Builder(data, master_data) { +} + +BitmapSizeTable::Builder::Builder(ReadableFontData* data, + ReadableFontData* master_data) + : SubTable::Builder(data, master_data) { +} + +void BitmapSizeTable::Builder::SetNumberOfIndexSubTables(int32_t count) { + InternalWriteData()->WriteULong( + EblcTable::Offset::kBitmapSizeTable_numberOfIndexSubTables, count); +} + +IndexSubTable::Builder* BitmapSizeTable::Builder::SearchIndexSubTables( + int32_t glyph_id) { + // would be faster to binary search but too many size tables don't have + // sorted subtables +#if (SFNTLY_BITMAPSIZE_USE_BINARY_SEARCH) + return BinarySearchIndexSubTables(glyph_id); +#else + return LinearSearchIndexSubTables(glyph_id); +#endif +} + +IndexSubTable::Builder* BitmapSizeTable::Builder::LinearSearchIndexSubTables( + int32_t glyph_id) { + IndexSubTableBuilderList* subtable_list = GetIndexSubTableBuilders(); + for (IndexSubTableBuilderList::iterator b = subtable_list->begin(), + e = subtable_list->end(); + b != e; b++) { + if ((*b)->first_glyph_index() <= glyph_id && + (*b)->last_glyph_index() >= glyph_id) { + return *b; + } + } + return NULL; +} + +IndexSubTable::Builder* BitmapSizeTable::Builder::BinarySearchIndexSubTables( + int32_t glyph_id) { + IndexSubTableBuilderList* subtable_list = GetIndexSubTableBuilders(); + int32_t index = 0; + int32_t bottom = 0; + int32_t top = subtable_list->size(); + while (top != bottom) { + index = (top + bottom) / 2; + IndexSubTable::Builder* subtable = subtable_list->at(index); + if (glyph_id < subtable->first_glyph_index()) { + // Location beow current location + top = index; + } else { + if (glyph_id <= subtable->last_glyph_index()) { + return subtable; + } else { + bottom = index + 1; + } + } + } + return NULL; +} + +IndexSubTableBuilderList* BitmapSizeTable::Builder::GetIndexSubTableBuilders() { + if (index_sub_tables_.empty()) { + Initialize(InternalReadData()); + set_model_changed(); + } + return &index_sub_tables_; +} + +void BitmapSizeTable::Builder::Initialize(ReadableFontData* data) { + index_sub_tables_.clear(); + if (data) { + int32_t number_of_index_subtables = + BitmapSizeTable::NumberOfIndexSubTables(data, 0); + index_sub_tables_.resize(number_of_index_subtables); + for (int32_t i = 0; i < number_of_index_subtables; ++i) { + index_sub_tables_[i].Attach(CreateIndexSubTableBuilder(i)); + } + } +} + +CALLER_ATTACH IndexSubTable::Builder* +BitmapSizeTable::Builder::CreateIndexSubTableBuilder(int32_t index) { + return IndexSubTable::Builder::CreateBuilder(master_read_data(), + IndexSubTableArrayOffset(), + index); +} + +/****************************************************************************** + * BitmapSizeTable::Builder::BitmapGlyphInfoIterator class + ******************************************************************************/ +BitmapSizeTable::Builder::BitmapGlyphInfoIterator::BitmapGlyphInfoIterator( + BitmapSizeTable::Builder* container) + : RefIterator(container) { + sub_table_iter_ = container->IndexSubTableBuilders()->begin(); + sub_table_glyph_info_iter_.Attach((*sub_table_iter_)->GetIterator()); +} + +bool BitmapSizeTable::Builder::BitmapGlyphInfoIterator::HasNext() { + if (sub_table_glyph_info_iter_ && HasNext(sub_table_glyph_info_iter_)) { + return true; + } + while (++sub_table_iter_ != container()->IndexSubTableBuilders()->end()) { + sub_table_glyph_info_iter_.Attach((*sub_table_iter_)->GetIterator()); + if (HasNext(sub_table_glyph_info_iter_)) { + return true; + } + } + return false; +} + +CALLER_ATTACH +BitmapGlyphInfo* BitmapSizeTable::Builder::BitmapGlyphInfoIterator::Next() { + if (!HasNext()) { + // Note: In C++, we do not throw exception when there's no element. + return NULL; + } + return Next(sub_table_glyph_info_iter_); +} + +bool BitmapSizeTable::Builder::BitmapGlyphInfoIterator::HasNext( + BitmapGlyphInfoIter* iterator_base) { + if (iterator_base) { + switch (iterator_base->container_base()->index_format()) { + case 1: { + IndexSubTableFormat1::Builder::BitmapGlyphInfoIterator* it = + down_cast( + iterator_base); + return it->HasNext(); + } + + case 2: { + IndexSubTableFormat2::Builder::BitmapGlyphInfoIterator* it = + down_cast( + iterator_base); + return it->HasNext(); + } + + case 3: { + IndexSubTableFormat3::Builder::BitmapGlyphInfoIterator* it = + down_cast( + iterator_base); + return it->HasNext(); + } + + case 4: { + IndexSubTableFormat4::Builder::BitmapGlyphInfoIterator* it = + down_cast( + iterator_base); + return it->HasNext(); + } + + case 5: { + IndexSubTableFormat5::Builder::BitmapGlyphInfoIterator* it = + down_cast( + iterator_base); + return it->HasNext(); + } + + default: + break; + } + } + return false; +} + +CALLER_ATTACH +BitmapGlyphInfo* BitmapSizeTable::Builder::BitmapGlyphInfoIterator::Next( + BitmapGlyphInfoIter* iterator_base) { + if (iterator_base) { + switch (iterator_base->container_base()->index_format()) { + case 1: { + IndexSubTableFormat1::Builder::BitmapGlyphInfoIterator* it = + down_cast( + iterator_base); + return it->Next(); + } + + case 2: { + IndexSubTableFormat2::Builder::BitmapGlyphInfoIterator* it = + down_cast( + iterator_base); + return it->Next(); + } + + case 3: { + IndexSubTableFormat3::Builder::BitmapGlyphInfoIterator* it = + down_cast( + iterator_base); + return it->Next(); + } + + case 4: { + IndexSubTableFormat4::Builder::BitmapGlyphInfoIterator* it = + down_cast( + iterator_base); + return it->Next(); + } + + case 5: { + IndexSubTableFormat5::Builder::BitmapGlyphInfoIterator* it = + down_cast( + iterator_base); + return it->Next(); + } + + default: + break; + } + } + return NULL; +} + +} // namespace sfntly diff --git a/src/sfntly/src/sfntly/table/bitmap/bitmap_size_table.h b/src/sfntly/src/sfntly/table/bitmap/bitmap_size_table.h new file mode 100644 index 000000000000..6733e2030420 --- /dev/null +++ b/src/sfntly/src/sfntly/table/bitmap/bitmap_size_table.h @@ -0,0 +1,173 @@ +/* + * 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. + */ + +#ifndef SFNTLY_CPP_SRC_SFNTLY_TABLE_BITMAP_BITMAP_SIZE_TABLE_H_ +#define SFNTLY_CPP_SRC_SFNTLY_TABLE_BITMAP_BITMAP_SIZE_TABLE_H_ + +#include "sfntly/port/lock.h" +#include "sfntly/table/bitmap/bitmap_glyph_info.h" +#include "sfntly/table/bitmap/index_sub_table.h" + +namespace sfntly { +// Binary search would be faster but many fonts have index subtables that +// aren't sorted. +// Note: preprocessor define is used to avoid const expression warnings in C++ +// code. +#define SFNTLY_BITMAPSIZE_USE_BINARY_SEARCH 0 + +class BitmapSizeTable : public SubTable, + public RefCounted { + public: + class Builder : public SubTable::Builder, + public RefCounted { + public: + class BitmapGlyphInfoIterator : + public RefIterator { + public: + explicit BitmapGlyphInfoIterator(Builder* container); + virtual ~BitmapGlyphInfoIterator() {} + + virtual bool HasNext(); + CALLER_ATTACH virtual BitmapGlyphInfo* Next(); + + private: + bool HasNext(BitmapGlyphInfoIter* iterator_base); + CALLER_ATTACH BitmapGlyphInfo* Next(BitmapGlyphInfoIter* iterator_base); + + IndexSubTableBuilderList::iterator sub_table_iter_; + BitmapGlyphInfoIterPtr sub_table_glyph_info_iter_; + }; + + virtual ~Builder(); + + virtual CALLER_ATTACH FontDataTable* SubBuildTable(ReadableFontData* data); + virtual void SubDataSet(); + virtual int32_t SubDataSizeToSerialize(); + virtual bool SubReadyToSerialize(); + virtual int32_t SubSerialize(WritableFontData* new_data); + + static CALLER_ATTACH Builder* CreateBuilder(WritableFontData* data, + ReadableFontData* master_data); + static CALLER_ATTACH Builder* CreateBuilder(ReadableFontData* data, + ReadableFontData* master_data); + // Gets the subtable array offset as set in the original table as read from + // the font file. This value cannot be explicitly set and will be generated + // during table building. + // @return the subtable array offset + int32_t IndexSubTableArrayOffset(); + + // Sets the subtable array offset. This is used only during the building + // process when the objects are being serialized. + // @param offset the offset to the index subtable array + void SetIndexSubTableArrayOffset(int32_t offset); + + // Gets the subtable array size as set in the original table as read from + // the font file. This value cannot be explicitly set and will be generated + // during table building. + // @return the subtable array size + int32_t IndexTableSize(); + + // Sets the subtable size. This is used only during the building process + // when the objects are being serialized. + // @param size the offset to the index subtable array + void SetIndexTableSize(int32_t size); + + int32_t NumberOfIndexSubTables(); + int32_t ColorRef(); + // TODO(stuartg): SBitLineMetrics hori(); + // TODO(stuartg): SBitLineMetrics vert(); + int32_t StartGlyphIndex(); + int32_t EndGlyphIndex(); + int32_t PpemX(); + int32_t PpemY(); + int32_t BitDepth(); + int32_t FlagsAsInt(); + + IndexSubTable::Builder* IndexSubTableBuilder(int32_t index); + CALLER_ATTACH BitmapGlyphInfo* GlyphInfo(int32_t glyph_id); + int32_t GlyphOffset(int32_t glyph_id); + int32_t GlyphLength(int32_t glyph_id); + int32_t GlyphFormat(int32_t glyph_id); + IndexSubTableBuilderList* IndexSubTableBuilders(); + // Note: renamed from iterator(), type is the derived type. + CALLER_ATTACH BitmapGlyphInfoIterator* GetIterator(); + void GenerateLocaMap(BitmapGlyphInfoMap* output); + + protected: + void Revert(); + + private: + Builder(WritableFontData* data, ReadableFontData* master_data); + Builder(ReadableFontData* data, ReadableFontData* master_data); + + void SetNumberOfIndexSubTables(int32_t count); + IndexSubTable::Builder* SearchIndexSubTables(int32_t glyph_id); + IndexSubTable::Builder* LinearSearchIndexSubTables(int32_t glyph_id); + IndexSubTable::Builder* BinarySearchIndexSubTables(int32_t glyph_id); + IndexSubTableBuilderList* GetIndexSubTableBuilders(); + void Initialize(ReadableFontData* data); + CALLER_ATTACH IndexSubTable::Builder* CreateIndexSubTableBuilder( + int32_t index); + + IndexSubTableBuilderList index_sub_tables_; + }; + + virtual ~BitmapSizeTable(); + + int32_t IndexSubTableArrayOffset(); + int32_t IndexTableSize(); + int32_t NumberOfIndexSubTables(); + int32_t ColorRef(); + // TODO(stuartg): SBitLineMetrics hori(); + // TODO(stuartg): SBitLineMetrics vert(); + int32_t StartGlyphIndex(); + int32_t EndGlyphIndex(); + int32_t PpemX(); + int32_t PpemY(); + int32_t BitDepth(); + int32_t FlagsAsInt(); + + // Note: renamed from indexSubTable() + IndexSubTable* GetIndexSubTable(int32_t index); + int32_t GlyphOffset(int32_t glyph_id); + int32_t GlyphLength(int32_t glyph_id); + CALLER_ATTACH BitmapGlyphInfo* GlyphInfo(int32_t glyph_id); + int32_t GlyphFormat(int32_t glyph_id); + + protected: + BitmapSizeTable(ReadableFontData* data, + ReadableFontData* master_data); + + private: + static int32_t NumberOfIndexSubTables(ReadableFontData* data, + int32_t table_offset); + IndexSubTable* SearchIndexSubTables(int32_t glyph_id); + IndexSubTable* LinearSearchIndexSubTables(int32_t glyph_id); + IndexSubTable* BinarySearchIndexSubTables(int32_t glyph_id); + CALLER_ATTACH IndexSubTable* CreateIndexSubTable(int32_t index); + IndexSubTableList* GetIndexSubTableList(); + + Lock index_subtables_lock_; + IndexSubTableList index_subtables_; +}; +typedef Ptr BitmapSizeTablePtr; +typedef std::vector BitmapSizeTableList; +typedef Ptr BitmapSizeTableBuilderPtr; +typedef std::vector BitmapSizeTableBuilderList; + +} // namespace sfntly + +#endif // SFNTLY_CPP_SRC_SFNTLY_TABLE_BITMAP_BITMAP_SIZE_TABLE_H_ diff --git a/src/sfntly/src/sfntly/table/bitmap/composite_bitmap_glyph.cc b/src/sfntly/src/sfntly/table/bitmap/composite_bitmap_glyph.cc new file mode 100644 index 000000000000..ae7dc5a7313e --- /dev/null +++ b/src/sfntly/src/sfntly/table/bitmap/composite_bitmap_glyph.cc @@ -0,0 +1,109 @@ +/* + * 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. + */ + +#include "sfntly/table/bitmap/composite_bitmap_glyph.h" + +namespace sfntly { +/****************************************************************************** + * CompositeBitmapGlyph class + ******************************************************************************/ +CompositeBitmapGlyph::CompositeBitmapGlyph(ReadableFontData* data, + int32_t format) + : BitmapGlyph(data, format) { + Initialize(format); +} + +CompositeBitmapGlyph::~CompositeBitmapGlyph() { +} + +int32_t CompositeBitmapGlyph::NumComponents() { + return data_->ReadUShort(num_components_offset_); +} + +CompositeBitmapGlyph::Component CompositeBitmapGlyph::GetComponent( + int32_t component_num) const { + int32_t component_offset = component_array_offset_ + + component_num * Offset::kEbdtComponentLength; + return CompositeBitmapGlyph::Component( + data_->ReadUShort(component_offset + Offset::kEbdtComponent_glyphCode), + data_->ReadChar(component_offset + Offset::kEbdtComponent_xOffset), + data_->ReadChar(component_offset + Offset::kEbdtComponent_yOffset)); +} + +void CompositeBitmapGlyph::Initialize(int32_t format) { + if (format == 8) { + num_components_offset_ = Offset::kGlyphFormat8_numComponents; + component_array_offset_ = Offset::kGlyphFormat8_componentArray; + } else if (format == 9) { + num_components_offset_ = Offset::kGlyphFormat9_numComponents; + component_array_offset_ = Offset::kGlyphFormat9_componentArray; + } else { +#if !defined (SFNTLY_NO_EXCEPTION) + throw IllegalStateException("Attempt to create a Composite Bitmap Glyph " + "with a non-composite format."); +#endif + } +} + +/****************************************************************************** + * CompositeBitmapGlyph::Component class + ******************************************************************************/ +CompositeBitmapGlyph::Component::Component(const Component& rhs) + : glyph_code_(rhs.glyph_code_), + x_offset_(rhs.x_offset_), + y_offset_(rhs.y_offset_) { +} + +bool CompositeBitmapGlyph::Component::operator==( + const CompositeBitmapGlyph::Component& rhs) { + return glyph_code_ == rhs.glyph_code_; +} + +CompositeBitmapGlyph::Component& CompositeBitmapGlyph::Component::operator=( + const CompositeBitmapGlyph::Component& rhs) { + glyph_code_ = rhs.glyph_code_; + x_offset_ = rhs.x_offset_; + y_offset_ = rhs.y_offset_; + return *this; +} + +CompositeBitmapGlyph::Component::Component(int32_t glyph_code, + int32_t x_offset, + int32_t y_offset) + : glyph_code_(glyph_code), x_offset_(x_offset), y_offset_(y_offset) { +} + +/****************************************************************************** + * CompositeBitmapGlyph::Builder class + ******************************************************************************/ +CompositeBitmapGlyph::Builder::Builder(ReadableFontData* data, int32_t format) + : BitmapGlyph::Builder(data, format) { +} + +CompositeBitmapGlyph::Builder::Builder(WritableFontData* data, int32_t format) + : BitmapGlyph::Builder(data, format) { +} + +CompositeBitmapGlyph::Builder::~Builder() { +} + +CALLER_ATTACH FontDataTable* +CompositeBitmapGlyph::Builder::SubBuildTable(ReadableFontData* data) { + Ptr glyph = new CompositeBitmapGlyph(data, format()); + return glyph.Detach(); +} + +} // namespace sfntly diff --git a/src/sfntly/src/sfntly/table/bitmap/composite_bitmap_glyph.h b/src/sfntly/src/sfntly/table/bitmap/composite_bitmap_glyph.h new file mode 100644 index 000000000000..897db7e22a70 --- /dev/null +++ b/src/sfntly/src/sfntly/table/bitmap/composite_bitmap_glyph.h @@ -0,0 +1,75 @@ +/* + * 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. + */ + +#ifndef SFNTLY_CPP_SRC_SFNTLY_TABLE_BITMAP_COMPOSITE_BITMAP_GLYPH_H_ +#define SFNTLY_CPP_SRC_SFNTLY_TABLE_BITMAP_COMPOSITE_BITMAP_GLYPH_H_ + +#include "sfntly/table/bitmap/bitmap_glyph.h" + +namespace sfntly { + +class CompositeBitmapGlyph : public BitmapGlyph, + public RefCounted { + public: + class Component { + public: + Component(const Component& rhs); + + int32_t glyph_code() { return glyph_code_; } + int32_t x_offset() { return x_offset_; } + int32_t y_offset() { return y_offset_; } + + // UNIMPLEMENTED: int hashCode() + bool operator==(const Component& rhs); + Component& operator=(const Component& rhs); + + protected: + Component(int32_t glyph_code, int32_t x_offset, int32_t y_offset); + + private: + int32_t glyph_code_; + int32_t x_offset_; + int32_t y_offset_; + + friend class CompositeBitmapGlyph; + }; + + class Builder : public BitmapGlyph::Builder, + public RefCounted { + public: + Builder(WritableFontData* data, int32_t format); + Builder(ReadableFontData* data, int32_t format); + virtual ~Builder(); + + virtual CALLER_ATTACH FontDataTable* SubBuildTable(ReadableFontData* data); + }; + + CompositeBitmapGlyph(ReadableFontData* data, int32_t format); + virtual ~CompositeBitmapGlyph(); + int32_t NumComponents(); + // Note: returned immutable object over stack. + Component GetComponent(int32_t component_num) const; + + private: + void Initialize(int32_t format); + + int32_t num_components_offset_; + int32_t component_array_offset_; +}; + +} // namespace sfntly + +#endif // SFNTLY_CPP_SRC_SFNTLY_TABLE_BITMAP_COMPOSITE_BITMAP_GLYPH_H_ diff --git a/src/sfntly/src/sfntly/table/bitmap/ebdt_table.cc b/src/sfntly/src/sfntly/table/bitmap/ebdt_table.cc new file mode 100644 index 000000000000..eeb1fa06b386 --- /dev/null +++ b/src/sfntly/src/sfntly/table/bitmap/ebdt_table.cc @@ -0,0 +1,236 @@ +/* + * 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. + */ + +#include "sfntly/table/bitmap/ebdt_table.h" + +#include + +#include "sfntly/table/bitmap/composite_bitmap_glyph.h" +#include "sfntly/table/bitmap/simple_bitmap_glyph.h" + +namespace sfntly { +/****************************************************************************** + * EbdtTable class + ******************************************************************************/ +EbdtTable::~EbdtTable() { +} + +int32_t EbdtTable::Version() { + return data_->ReadFixed(Offset::kVersion); +} + +CALLER_ATTACH +BitmapGlyph* EbdtTable::Glyph(int32_t offset, int32_t length, int32_t format) { + ReadableFontDataPtr glyph_data; + glyph_data.Attach(down_cast(data_->Slice(offset, length))); + return BitmapGlyph::CreateGlyph(glyph_data, format); +} + +EbdtTable::EbdtTable(Header* header, ReadableFontData* data) + : SubTableContainerTable(header, data) { +} + +/****************************************************************************** + * EbdtTable::Builder class + ******************************************************************************/ +EbdtTable::Builder::Builder(Header* header, WritableFontData* data) + : SubTableContainerTable::Builder(header, data) { +} + +EbdtTable::Builder::Builder(Header* header, ReadableFontData* data) + : SubTableContainerTable::Builder(header, data) { +} + +EbdtTable::Builder::~Builder() { +} + +CALLER_ATTACH FontDataTable* + EbdtTable::Builder::SubBuildTable(ReadableFontData* data) { + FontDataTablePtr table = new EbdtTable(header(), data); + return table.Detach(); +} + +void EbdtTable::Builder::SubDataSet() { + Revert(); +} + +int32_t EbdtTable::Builder::SubDataSizeToSerialize() { + if (glyph_builders_.empty()) { + return 0; + } + bool fixed = true; + int32_t size = Offset::kHeaderLength; + for (BitmapGlyphBuilderList::iterator builder_map = glyph_builders_.begin(), + builder_end = glyph_builders_.end(); + builder_map != builder_end; + builder_map++) { + for (BitmapGlyphBuilderMap::iterator glyph_entry = builder_map->begin(), + glyph_entry_end = builder_map->end(); + glyph_entry != glyph_entry_end; + glyph_entry++) { + int32_t glyph_size = glyph_entry->second->SubDataSizeToSerialize(); + size += abs(glyph_size); + fixed = (glyph_size <= 0) ? false : fixed; + } + } + return (fixed ? 1 : -1) * size; +} + +bool EbdtTable::Builder::SubReadyToSerialize() { + if (glyph_builders_.empty()) { + return false; + } + return true; +} + +int32_t EbdtTable::Builder::SubSerialize(WritableFontData* new_data) { + int32_t size = 0; + size += new_data->WriteFixed(Offset::kVersion, kVersion); + for (BitmapGlyphBuilderList::iterator builder_map = glyph_builders_.begin(), + builder_end = glyph_builders_.end(); + builder_map != builder_end; + builder_map++) { + for (BitmapGlyphBuilderMap::iterator glyph_entry = builder_map->begin(), + glyph_entry_end = builder_map->end(); + glyph_entry != glyph_entry_end; + glyph_entry++) { + WritableFontDataPtr slice; + slice.Attach(down_cast(new_data->Slice(size))); + size += glyph_entry->second->SubSerialize(slice); + } + } + return size; +} + +void EbdtTable::Builder::SetLoca(BitmapLocaList* loca_list) { + assert(loca_list); + Revert(); + glyph_loca_.resize(loca_list->size()); + std::copy(loca_list->begin(), loca_list->end(), glyph_loca_.begin()); +} + +void EbdtTable::Builder::GenerateLocaList(BitmapLocaList* output) { + assert(output); + output->clear(); + + if (glyph_builders_.empty()) { + if (glyph_loca_.empty()) { + return; + } + } + + int start_offset = Offset::kHeaderLength; + for (BitmapGlyphBuilderList::iterator builder_map = glyph_builders_.begin(), + builder_end = glyph_builders_.end(); + builder_map != builder_end; + builder_map++) { + BitmapGlyphInfoMap new_loca_map; + int32_t glyph_offset = 0; + for (BitmapGlyphBuilderMap::iterator glyph_entry = builder_map->begin(), + glyph_end = builder_map->end(); + glyph_entry != glyph_end; + glyph_entry++) { + BitmapGlyphBuilderPtr builder = glyph_entry->second; + int32_t size = builder->SubDataSizeToSerialize(); + BitmapGlyphInfoPtr info = new BitmapGlyphInfo(glyph_entry->first, + start_offset + glyph_offset, size, builder->format()); + new_loca_map[glyph_entry->first] = info; + glyph_offset += size; + } + start_offset += glyph_offset; + output->push_back(new_loca_map); + } +} + +BitmapGlyphBuilderList* EbdtTable::Builder::GlyphBuilders() { + return GetGlyphBuilders(); +} + +void EbdtTable::Builder::SetGlyphBuilders( + BitmapGlyphBuilderList* glyph_builders) { + glyph_builders_.clear(); + std::copy(glyph_builders->begin(), glyph_builders->end(), + glyph_builders_.begin()); + set_model_changed(); +} + +void EbdtTable::Builder::Revert() { + glyph_loca_.clear(); + glyph_builders_.clear(); + set_model_changed(false); +} + +CALLER_ATTACH +EbdtTable::Builder* EbdtTable::Builder::CreateBuilder(Header* header, + WritableFontData* data) { + Ptr builder; + builder = new Builder(header, data); + return builder.Detach(); +} + +CALLER_ATTACH +EbdtTable::Builder* EbdtTable::Builder::CreateBuilder(Header* header, + ReadableFontData* data) { + Ptr builder; + builder = new Builder(header, data); + return builder.Detach(); +} + +BitmapGlyphBuilderList* EbdtTable::Builder::GetGlyphBuilders() { + if (glyph_builders_.empty()) { + if (glyph_loca_.empty()) { +#if !defined (SFNTLY_NO_EXCEPTION) + throw IllegalStateException( + "Loca values not set - unable to parse glyph data."); +#endif + return NULL; + } + Initialize(InternalReadData(), &glyph_loca_, &glyph_builders_); + set_model_changed(); + } + return &glyph_builders_; +} + +void EbdtTable::Builder::Initialize(ReadableFontData* data, + BitmapLocaList* loca_list, + BitmapGlyphBuilderList* output) { + assert(loca_list); + assert(output); + + output->clear(); + if (data) { + for (BitmapLocaList::iterator loca_map = loca_list->begin(), + loca_end = loca_list->end(); + loca_map != loca_end; loca_map++) { + BitmapGlyphBuilderMap glyph_builder_map; + for (BitmapGlyphInfoMap::iterator entry = loca_map->begin(), + entry_end = loca_map->end(); + entry != entry_end; entry++) { + BitmapGlyphInfoPtr info = entry->second; + ReadableFontDataPtr slice; + slice.Attach(down_cast(data->Slice( + info->offset(), info->length()))); + BitmapGlyphBuilderPtr glyph_builder; + glyph_builder.Attach(BitmapGlyph::Builder::CreateGlyphBuilder( + slice, info->format())); + glyph_builder_map[entry->first] = glyph_builder; + } + output->push_back(glyph_builder_map); + } + } +} + +} // namespace sfntly diff --git a/src/sfntly/src/sfntly/table/bitmap/ebdt_table.h b/src/sfntly/src/sfntly/table/bitmap/ebdt_table.h new file mode 100644 index 000000000000..d138c14ca535 --- /dev/null +++ b/src/sfntly/src/sfntly/table/bitmap/ebdt_table.h @@ -0,0 +1,108 @@ +/* + * 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. + */ + +#ifndef SFNTLY_CPP_SRC_SFNTLY_TABLE_BITMAP_EBDT_TABLE_H_ +#define SFNTLY_CPP_SRC_SFNTLY_TABLE_BITMAP_EBDT_TABLE_H_ + +#include "sfntly/table/bitmap/bitmap_glyph.h" +#include "sfntly/table/bitmap/bitmap_glyph_info.h" +#include "sfntly/table/subtable_container_table.h" + +namespace sfntly { + +class EbdtTable : public SubTableContainerTable, + public RefCounted { + public: + struct Offset { + enum { + kVersion = 0, + kHeaderLength = DataSize::kFixed, + }; + }; + + class Builder : public SubTableContainerTable::Builder, + public RefCounted { + public: + // Constructor scope altered to public because C++ does not allow base + // class to instantiate derived class with protected constructors. + Builder(Header* header, WritableFontData* data); + Builder(Header* header, ReadableFontData* data); + virtual ~Builder(); + + virtual int32_t SubSerialize(WritableFontData* new_data); + virtual bool SubReadyToSerialize(); + virtual int32_t SubDataSizeToSerialize(); + virtual void SubDataSet(); + virtual CALLER_ATTACH FontDataTable* SubBuildTable(ReadableFontData* data); + + void SetLoca(BitmapLocaList* loca_list); + void GenerateLocaList(BitmapLocaList* output); + + // Gets the List of glyph builders for the glyph table builder. These may be + // manipulated in any way by the caller and the changes will be reflected in + // the final glyph table produced. + // If there is no current data for the glyph builder or the glyph builders + // have not been previously set then this will return an empty glyph builder + // List. If there is current data (i.e. data read from an existing font) and + // the loca list has not been set or is null, empty, or invalid, then an + // empty glyph builder List will be returned. + // @return the list of glyph builders + BitmapGlyphBuilderList* GlyphBuilders(); + + // Replace the internal glyph builders with the one provided. The provided + // list and all contained objects belong to this builder. + // This call is only required if the entire set of glyphs in the glyph + // table builder are being replaced. If the glyph builder list provided from + // the {@link EbdtTable.Builder#glyphBuilders()} is being used and modified + // then those changes will already be reflected in the glyph table builder. + // @param glyphBuilders the new glyph builders + void SetGlyphBuilders(BitmapGlyphBuilderList* glyph_builders); + + void Revert(); + + // Create a new builder using the header information and data provided. + // @param header the header information + // @param data the data holding the table + static CALLER_ATTACH Builder* CreateBuilder(Header* header, + WritableFontData* data); + static CALLER_ATTACH Builder* CreateBuilder(Header* header, + ReadableFontData* data); + + private: + BitmapGlyphBuilderList* GetGlyphBuilders(); + static void Initialize(ReadableFontData* data, + BitmapLocaList* loca_list, + BitmapGlyphBuilderList* output); + + static const int32_t kVersion = 0x00020000; // TODO(stuartg): const/enum + BitmapLocaList glyph_loca_; + BitmapGlyphBuilderList glyph_builders_; + }; + + virtual ~EbdtTable(); + int32_t Version(); + CALLER_ATTACH BitmapGlyph* Glyph(int32_t offset, + int32_t length, + int32_t format); + protected: + EbdtTable(Header* header, ReadableFontData* data); +}; +typedef Ptr EbdtTablePtr; +typedef Ptr EbdtTableBuilderPtr; + +} // namespace sfntly + +#endif // SFNTLY_CPP_SRC_SFNTLY_TABLE_BITMAP_EBDT_TABLE_H_ diff --git a/src/sfntly/src/sfntly/table/bitmap/eblc_table.cc b/src/sfntly/src/sfntly/table/bitmap/eblc_table.cc new file mode 100644 index 000000000000..0ad2764bf6ee --- /dev/null +++ b/src/sfntly/src/sfntly/table/bitmap/eblc_table.cc @@ -0,0 +1,313 @@ +/* + * 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. + */ + +#include "sfntly/table/bitmap/eblc_table.h" + +#include +#include + +#include "sfntly/math/font_math.h" + +namespace sfntly { +/****************************************************************************** + * EblcTable class + ******************************************************************************/ +int32_t EblcTable::Version() { + return data_->ReadFixed(Offset::kVersion); +} + +int32_t EblcTable::NumSizes() { + return data_->ReadULongAsInt(Offset::kNumSizes); +} + +BitmapSizeTable* EblcTable::GetBitmapSizeTable(int32_t index) { + if (index < 0 || index > NumSizes()) { +#if !defined (SFNTLY_NO_EXCEPTION) + throw IndexOutOfBoundException( + "Size table index is outside the range of tables."); +#endif + return NULL; + } + BitmapSizeTableList* bitmap_size_table_list = GetBitmapSizeTableList(); + if (bitmap_size_table_list) { + return (*bitmap_size_table_list)[index]; + } + return NULL; +} + +EblcTable::EblcTable(Header* header, ReadableFontData* data) + : SubTableContainerTable(header, data) { +} + +BitmapSizeTableList* EblcTable::GetBitmapSizeTableList() { + AutoLock lock(bitmap_size_table_lock_); + if (bitmap_size_table_.empty()) { + CreateBitmapSizeTable(data_, NumSizes(), &bitmap_size_table_); + } + return &bitmap_size_table_; +} + +// static +void EblcTable::CreateBitmapSizeTable(ReadableFontData* data, + int32_t num_sizes, + BitmapSizeTableList* output) { + assert(data); + assert(output); + for (int32_t i = 0; i < num_sizes; ++i) { + ReadableFontDataPtr new_data; + new_data.Attach(down_cast( + data->Slice(Offset::kBitmapSizeTableArrayStart + + i * Offset::kBitmapSizeTableLength, + Offset::kBitmapSizeTableLength))); + BitmapSizeTableBuilderPtr size_builder; + size_builder.Attach( + BitmapSizeTable::Builder::CreateBuilder(new_data, data)); + BitmapSizeTablePtr size; + size.Attach(down_cast(size_builder->Build())); + output->push_back(size); + } +} + +/****************************************************************************** + * EblcTable::Builder class + ******************************************************************************/ +EblcTable::Builder::Builder(Header* header, WritableFontData* data) + : SubTableContainerTable::Builder(header, data) { +} + +EblcTable::Builder::Builder(Header* header, ReadableFontData* data) + : SubTableContainerTable::Builder(header, data) { +} + +EblcTable::Builder::~Builder() { +} + +int32_t EblcTable::Builder::SubSerialize(WritableFontData* new_data) { + // header + int32_t size = new_data->WriteFixed(0, kVersion); + size += new_data->WriteULong(size, size_table_builders_.size()); + + // calculate the offsets + // offset to the start of the size table array + int32_t size_table_start_offset = size; + // walking offset in the size table array + int32_t size_table_offset = size_table_start_offset; + // offset to the start of the whole index subtable block + int32_t sub_table_block_start_offset = size_table_offset + + size_table_builders_.size() * Offset::kBitmapSizeTableLength; + // walking offset in the index subtable + // points to the start of the current subtable block + int32_t current_sub_table_block_start_offset = sub_table_block_start_offset; + +#if defined (SFNTLY_DEBUG_BITMAP) + int32_t size_index = 0; +#endif + for (BitmapSizeTableBuilderList::iterator + size_builder = size_table_builders_.begin(), + size_builder_end = size_table_builders_.end(); + size_builder != size_builder_end; size_builder++) { + (*size_builder)->SetIndexSubTableArrayOffset( + current_sub_table_block_start_offset); + IndexSubTableBuilderList* index_sub_table_builder_list = + (*size_builder)->IndexSubTableBuilders(); + + // walking offset within the current subTable array + int32_t index_sub_table_array_offset = current_sub_table_block_start_offset; + // walking offset within the subTable entries + int32_t index_sub_table_offset = index_sub_table_array_offset + + index_sub_table_builder_list->size() * Offset::kIndexSubHeaderLength; + +#if defined (SFNTLY_DEBUG_BITMAP) + fprintf(stderr, "size %d: sizeTable=%x, current subTable Block=%x, ", + size_index, size_table_offset, + current_sub_table_block_start_offset); + fprintf(stderr, "index subTableStart=%x\n", index_sub_table_offset); + size_index++; + int32_t sub_table_index = 0; +#endif + for (IndexSubTableBuilderList::iterator + index_sub_table_builder = index_sub_table_builder_list->begin(), + index_sub_table_builder_end = index_sub_table_builder_list->end(); + index_sub_table_builder != index_sub_table_builder_end; + index_sub_table_builder++) { +#if defined (SFNTLY_DEBUG_BITMAP) + fprintf(stderr, "\tsubTableIndex %d: format=%x, ", sub_table_index, + (*index_sub_table_builder)->index_format()); + fprintf(stderr, "indexSubTableArrayOffset=%x, indexSubTableOffset=%x\n", + index_sub_table_array_offset, index_sub_table_offset); + sub_table_index++; +#endif + // array entry + index_sub_table_array_offset += new_data->WriteUShort( + index_sub_table_array_offset, + (*index_sub_table_builder)->first_glyph_index()); + index_sub_table_array_offset += new_data->WriteUShort( + index_sub_table_array_offset, + (*index_sub_table_builder)->last_glyph_index()); + index_sub_table_array_offset += new_data->WriteULong( + index_sub_table_array_offset, + index_sub_table_offset - current_sub_table_block_start_offset); + + // index sub table + WritableFontDataPtr slice_index_sub_table; + slice_index_sub_table.Attach(down_cast( + new_data->Slice(index_sub_table_offset))); + int32_t current_sub_table_size = + (*index_sub_table_builder)->SubSerialize(slice_index_sub_table); + int32_t padding = FontMath::PaddingRequired(current_sub_table_size, + DataSize::kULONG); +#if defined (SFNTLY_DEBUG_BITMAP) + fprintf(stderr, "\t\tsubTableSize = %x, padding = %x\n", + current_sub_table_size, padding); +#endif + index_sub_table_offset += current_sub_table_size; + index_sub_table_offset += + new_data->WritePadding(index_sub_table_offset, padding); + } + + // serialize size table + (*size_builder)->SetIndexTableSize( + index_sub_table_offset - current_sub_table_block_start_offset); + WritableFontDataPtr slice_size_table; + slice_size_table.Attach(down_cast( + new_data->Slice(size_table_offset))); + size_table_offset += (*size_builder)->SubSerialize(slice_size_table); + + current_sub_table_block_start_offset = index_sub_table_offset; + } + return size + current_sub_table_block_start_offset; +} + +bool EblcTable::Builder::SubReadyToSerialize() { + if (size_table_builders_.empty()) { + return false; + } + for (BitmapSizeTableBuilderList::iterator b = size_table_builders_.begin(), + e = size_table_builders_.end(); + b != e; b++) { + if (!(*b)->SubReadyToSerialize()) { + return false; + } + } + return true; +} + +int32_t EblcTable::Builder::SubDataSizeToSerialize() { + if (size_table_builders_.empty()) { + return 0; + } + int32_t size = Offset::kHeaderLength; + bool variable = false; +#if defined (SFNTLY_DEBUG_BITMAP) + size_t size_index = 0; +#endif + for (BitmapSizeTableBuilderList::iterator b = size_table_builders_.begin(), + e = size_table_builders_.end(); + b != e; b++) { + int32_t size_builder_size = (*b)->SubDataSizeToSerialize(); +#if defined (SFNTLY_DEBUG_BITMAP) + fprintf(stderr, "sizeIndex = %d, sizeBuilderSize=0x%x (%d)\n", + size_index++, size_builder_size, size_builder_size); +#endif + variable = size_builder_size > 0 ? variable : true; + size += abs(size_builder_size); + } +#if defined (SFNTLY_DEBUG_BITMAP) + fprintf(stderr, "eblc size=%d\n", size); +#endif + return variable ? -size : size; +} + +void EblcTable::Builder::SubDataSet() { + Revert(); +} + +BitmapSizeTableBuilderList* EblcTable::Builder::BitmapSizeBuilders() { + return GetSizeList(); +} + +void EblcTable::Builder::Revert() { + size_table_builders_.clear(); + set_model_changed(false); +} + +void EblcTable::Builder::GenerateLocaList(BitmapLocaList* output) { + assert(output); + BitmapSizeTableBuilderList* size_builder_list = GetSizeList(); + output->clear(); +#if defined (SFNTLY_DEBUG_BITMAP) + int32_t size_index = 0; +#endif + for (BitmapSizeTableBuilderList::iterator b = size_builder_list->begin(), + e = size_builder_list->end(); + b != e; b++) { +#if defined (SFNTLY_DEBUG_BITMAP) + fprintf(stderr, "size table = %d\n", size_index++); +#endif + BitmapGlyphInfoMap loca_map; + (*b)->GenerateLocaMap(&loca_map); + output->push_back(loca_map); + } +} + +CALLER_ATTACH +FontDataTable* EblcTable::Builder::SubBuildTable(ReadableFontData* data) { + Ptr new_table = new EblcTable(header(), data); + return new_table.Detach(); +} + +// static +CALLER_ATTACH EblcTable::Builder* + EblcTable::Builder::CreateBuilder(Header* header, WritableFontData* data) { + Ptr new_builder = new EblcTable::Builder(header, data); + return new_builder.Detach(); +} + +// static +CALLER_ATTACH EblcTable::Builder* + EblcTable::Builder::CreateBuilder(Header* header, ReadableFontData* data) { + Ptr new_builder = new EblcTable::Builder(header, data); + return new_builder.Detach(); +} + +BitmapSizeTableBuilderList* EblcTable::Builder::GetSizeList() { + if (size_table_builders_.empty()) { + Initialize(InternalReadData(), &size_table_builders_); + set_model_changed(); + } + return &size_table_builders_; +} + +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( + 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); + } + } +} + +} // namespace sfntly diff --git a/src/sfntly/src/sfntly/table/bitmap/eblc_table.h b/src/sfntly/src/sfntly/table/bitmap/eblc_table.h new file mode 100644 index 000000000000..b04338a93b1a --- /dev/null +++ b/src/sfntly/src/sfntly/table/bitmap/eblc_table.h @@ -0,0 +1,194 @@ +/* + * 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. + */ + +#ifndef SFNTLY_CPP_SRC_SFNTLY_TABLE_BITMAP_EBLC_TABLE_H_ +#define SFNTLY_CPP_SRC_SFNTLY_TABLE_BITMAP_EBLC_TABLE_H_ + +#include "sfntly/port/lock.h" +#include "sfntly/table/bitmap/big_glyph_metrics.h" +#include "sfntly/table/bitmap/bitmap_glyph.h" +#include "sfntly/table/bitmap/bitmap_size_table.h" +#include "sfntly/table/subtable_container_table.h" + +namespace sfntly { + +class EblcTable : public SubTableContainerTable, + public RefCounted { + public: + struct Offset { + enum { + // header + kVersion = 0, + kNumSizes = 4, + kHeaderLength = kNumSizes + DataSize::kULONG, + + // bitmapSizeTable + kBitmapSizeTableArrayStart = kHeaderLength, + kBitmapSizeTableLength = 48, + kBitmapSizeTable_indexSubTableArrayOffset = 0, + kBitmapSizeTable_indexTableSize = 4, + kBitmapSizeTable_numberOfIndexSubTables = 8, + kBitmapSizeTable_colorRef = 12, + kBitmapSizeTable_hori = 16, + kBitmapSizeTable_vert = 28, + kBitmapSizeTable_startGlyphIndex = 40, + kBitmapSizeTable_endGlyphIndex = 42, + kBitmapSizeTable_ppemX = 44, + kBitmapSizeTable_ppemY = 45, + kBitmapSizeTable_bitDepth = 46, + kBitmapSizeTable_flags = 47, + + // sbitLineMetrics + kSbitLineMetricsLength = 12, + kSbitLineMetrics_ascender = 0, + kSbitLineMetrics_descender = 1, + kSbitLineMetrics_widthMax = 2, + kSbitLineMetrics_caretSlopeNumerator = 3, + kSbitLineMetrics_caretSlopeDenominator = 4, + kSbitLineMetrics_caretOffset = 5, + kSbitLineMetrics_minOriginSB = 6, + kSbitLineMetrics_minAdvanceSB = 7, + kSbitLineMetrics_maxBeforeBL = 8, + kSbitLineMetrics_minAfterBL = 9, + kSbitLineMetrics_pad1 = 10, + kSbitLineMetrics_pad2 = 11, + + // indexSubTable + kIndexSubTableEntryLength = 8, + kIndexSubTableEntry_firstGlyphIndex = 0, + kIndexSubTableEntry_lastGlyphIndex = 2, + kIndexSubTableEntry_additionalOffsetToIndexSubTable = 4, + + // indexSubHeader + kIndexSubHeaderLength = 8, + kIndexSubHeader_indexFormat = 0, + kIndexSubHeader_imageFormat = 2, + kIndexSubHeader_imageDataOffset = 4, + + // indexSubTable - all offset relative to the subtable start + + // indexSubTable1 + kIndexSubTable1_offsetArray = kIndexSubHeaderLength, + kIndexSubTable1_builderDataSize = kIndexSubHeaderLength, + + // kIndexSubTable2 + kIndexSubTable2Length = kIndexSubHeaderLength + + DataSize::kULONG + + BitmapGlyph::Offset::kBigGlyphMetricsLength, + kIndexSubTable2_imageSize = kIndexSubHeaderLength, + kIndexSubTable2_bigGlyphMetrics = kIndexSubTable2_imageSize + + DataSize::kULONG, + kIndexSubTable2_builderDataSize = kIndexSubTable2_bigGlyphMetrics + + BigGlyphMetrics::Offset::kMetricsLength, + + // kIndexSubTable3 + kIndexSubTable3_offsetArray = kIndexSubHeaderLength, + kIndexSubTable3_builderDataSize = kIndexSubTable3_offsetArray, + + // kIndexSubTable4 + kIndexSubTable4_numGlyphs = kIndexSubHeaderLength, + kIndexSubTable4_glyphArray = kIndexSubTable4_numGlyphs + + DataSize::kULONG, + kIndexSubTable4_codeOffsetPairLength = 2 * DataSize::kUSHORT, + kIndexSubTable4_codeOffsetPair_glyphCode = 0, + kIndexSubTable4_codeOffsetPair_offset = DataSize::kUSHORT, + kIndexSubTable4_builderDataSize = kIndexSubTable4_glyphArray, + + // kIndexSubTable5 + kIndexSubTable5_imageSize = kIndexSubHeaderLength, + kIndexSubTable5_bigGlyphMetrics = kIndexSubTable5_imageSize + + DataSize::kULONG, + kIndexSubTable5_numGlyphs = kIndexSubTable5_bigGlyphMetrics + + BitmapGlyph::Offset::kBigGlyphMetricsLength, + kIndexSubTable5_glyphArray = kIndexSubTable5_numGlyphs + + DataSize::kULONG, + kIndexSubTable5_builderDataSize = kIndexSubTable5_glyphArray, + + // codeOffsetPair + kCodeOffsetPairLength = 2 * DataSize::kUSHORT, + kCodeOffsetPair_glyphCode = 0, + kCodeOffsetPair_offset = DataSize::kUSHORT, + }; + }; + + class Builder : public SubTableContainerTable::Builder, + public RefCounted { + public: + // Constructor scope altered to public because C++ does not allow base + // class to instantiate derived class with protected constructors. + Builder(Header* header, WritableFontData* data); + Builder(Header* header, ReadableFontData* data); + virtual ~Builder(); + + virtual int32_t SubSerialize(WritableFontData* new_data); + virtual bool SubReadyToSerialize(); + virtual int32_t SubDataSizeToSerialize(); + virtual void SubDataSet(); + virtual CALLER_ATTACH FontDataTable* SubBuildTable(ReadableFontData* data); + + BitmapSizeTableBuilderList* BitmapSizeBuilders(); + void Revert(); + + // Generates the loca list for the EBDT table. The list is intended to be + // used by the EBDT to allow it to parse the glyph data and generate glyph + // objects. After returning from this method the list belongs to the caller. + // The list entries are in the same order as the size table builders are at + // the time of this call. + // @return the list of loca maps with one for each size table builder + void GenerateLocaList(BitmapLocaList* output); + + // Create a new builder using the header information and data provided. + // @param header the header information + // @param data the data holding the table + static CALLER_ATTACH Builder* CreateBuilder(Header* header, + WritableFontData* data); + static CALLER_ATTACH Builder* CreateBuilder(Header* header, + ReadableFontData* data); + + private: + BitmapSizeTableBuilderList* GetSizeList(); + void Initialize(ReadableFontData* data, BitmapSizeTableBuilderList* output); + + static const int32_t kVersion = 0x00020000; + BitmapSizeTableBuilderList size_table_builders_; + }; + + int32_t Version(); + int32_t NumSizes(); + // UNIMPLEMENTED: toString() + + BitmapSizeTable* GetBitmapSizeTable(int32_t index); + + static const int32_t NOTDEF = -1; + + protected: + EblcTable(Header* header, ReadableFontData* data); + + private: + BitmapSizeTableList* GetBitmapSizeTableList(); + + static void CreateBitmapSizeTable(ReadableFontData* data, + int32_t num_sizes, + BitmapSizeTableList* output); + + Lock bitmap_size_table_lock_; + BitmapSizeTableList bitmap_size_table_; +}; +typedef Ptr EblcTablePtr; +typedef Ptr EblcTableBuilderPtr; +} + +#endif // SFNTLY_CPP_SRC_SFNTLY_TABLE_BITMAP_EBLC_TABLE_H_ diff --git a/src/sfntly/src/sfntly/table/bitmap/ebsc_table.cc b/src/sfntly/src/sfntly/table/bitmap/ebsc_table.cc new file mode 100644 index 000000000000..458c2d49e837 --- /dev/null +++ b/src/sfntly/src/sfntly/table/bitmap/ebsc_table.cc @@ -0,0 +1,107 @@ +/* + * 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. + */ + +#include "sfntly/table/bitmap/ebsc_table.h" + +namespace sfntly { +/****************************************************************************** + * EbscTable class + ******************************************************************************/ +EbscTable::~EbscTable() { +} + +int32_t EbscTable::Version() { + return data_->ReadFixed(Offset::kVersion); +} + +int32_t EbscTable::NumSizes() { + return data_->ReadULongAsInt(Offset::kNumSizes); +} + +EbscTable::EbscTable(Header* header, ReadableFontData* data) + : Table(header, data) { +} + +/****************************************************************************** + * EbscTable::BitmapScaleTable class + ******************************************************************************/ +EbscTable::BitmapScaleTable::~BitmapScaleTable() { +} + +EbscTable::BitmapScaleTable::BitmapScaleTable(ReadableFontData* data) + : SubTable(data) { +} + +int32_t EbscTable::BitmapScaleTable::PpemX() { + return data_->ReadByte(Offset::kBitmapScaleTable_ppemX); +} + +int32_t EbscTable::BitmapScaleTable::PpemY() { + return data_->ReadByte(Offset::kBitmapScaleTable_ppemY); +} + +int32_t EbscTable::BitmapScaleTable::SubstitutePpemX() { + return data_->ReadByte(Offset::kBitmapScaleTable_substitutePpemX); +} + +int32_t EbscTable::BitmapScaleTable::SubstitutePpemY() { + return data_->ReadByte(Offset::kBitmapScaleTable_substitutePpemY); +} + +/****************************************************************************** + * EbscTable::Builder class + ******************************************************************************/ +EbscTable::Builder::~Builder() { +} + +CALLER_ATTACH EbscTable::Builder* EbscTable::Builder::CreateBuilder( + Header* header, WritableFontData* data) { + EbscTableBuilderPtr builder = new EbscTable::Builder(header, data); + return builder.Detach(); +} + +EbscTable::Builder::Builder(Header* header, WritableFontData* data) + : Table::Builder(header, data) { +} + +EbscTable::Builder::Builder(Header* header, ReadableFontData* data) + : Table::Builder(header, data) { +} + +CALLER_ATTACH +FontDataTable* EbscTable::Builder::SubBuildTable(ReadableFontData* data) { + EbscTablePtr output = new EbscTable(header(), data); + return output.Detach(); +} + +void EbscTable::Builder::SubDataSet() { + // NOP +} + +int32_t EbscTable::Builder::SubDataSizeToSerialize() { + return 0; +} + +bool EbscTable::Builder::SubReadyToSerialize() { + return false; +} + +int32_t EbscTable::Builder::SubSerialize(WritableFontData* new_data) { + UNREFERENCED_PARAMETER(new_data); + return 0; +} + +} // namespace sfntly diff --git a/src/sfntly/src/sfntly/table/bitmap/ebsc_table.h b/src/sfntly/src/sfntly/table/bitmap/ebsc_table.h new file mode 100644 index 000000000000..b79df380df73 --- /dev/null +++ b/src/sfntly/src/sfntly/table/bitmap/ebsc_table.h @@ -0,0 +1,101 @@ +/* + * 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. + */ + +#ifndef SFNTLY_CPP_SRC_SFNTLY_TABLE_BITMAP_EBSC_TABLE_H_ +#define SFNTLY_CPP_SRC_SFNTLY_TABLE_BITMAP_EBSC_TABLE_H_ + +#include "sfntly/table/bitmap/eblc_table.h" + +namespace sfntly { + +class EbscTable : public Table, + public RefCounted { + public: + struct Offset { + enum { + // header + kVersion = 0, + kNumSizes = DataSize::kFixed, + kHeaderLength = kNumSizes + DataSize::kULONG, + kBitmapScaleTableStart = kHeaderLength, + + // bitmapScaleTable + kBitmapScaleTable_hori = 0, + kBitmapScaleTable_vert = EblcTable::Offset::kSbitLineMetricsLength, + kBitmapScaleTable_ppemX = kBitmapScaleTable_vert + + EblcTable::Offset::kSbitLineMetricsLength, + kBitmapScaleTable_ppemY = kBitmapScaleTable_ppemX + DataSize::kBYTE, + kBitmapScaleTable_substitutePpemX = kBitmapScaleTable_ppemY + + DataSize::kBYTE, + kBitmapScaleTable_substitutePpemY = kBitmapScaleTable_substitutePpemX + + DataSize::kBYTE, + kBitmapScaleTableLength = kBitmapScaleTable_substitutePpemY + + DataSize::kBYTE, + }; + }; + + class BitmapScaleTable : public SubTable, + public RefCounted { + public: + virtual ~BitmapScaleTable(); + int32_t PpemX(); + int32_t PpemY(); + int32_t SubstitutePpemX(); + int32_t SubstitutePpemY(); + + protected: + // Note: caller to do data->Slice(offset, Offset::kBitmapScaleTableLength) + explicit BitmapScaleTable(ReadableFontData* data); + }; + + // TODO(stuartg): currently the builder just builds from initial data + // - need to make fully working but few if any examples to test with + class Builder : public Table::Builder, + public RefCounted { + public: + virtual ~Builder(); + + static CALLER_ATTACH Builder* CreateBuilder(Header* header, + WritableFontData* data); + + protected: + Builder(Header* header, WritableFontData* data); + Builder(Header* header, ReadableFontData* data); + + virtual CALLER_ATTACH FontDataTable* SubBuildTable(ReadableFontData* data); + virtual void SubDataSet(); + virtual int32_t SubDataSizeToSerialize(); + virtual bool SubReadyToSerialize(); + virtual int32_t SubSerialize(WritableFontData* new_data); + }; + + virtual ~EbscTable(); + + int32_t Version(); + int32_t NumSizes(); + // Note: renamed from bitmapScaleTable + CALLER_ATTACH BitmapScaleTable* GetBitmapScaleTable(int32_t index); + + private: + EbscTable(Header* header, ReadableFontData* data); + friend class Builder; +}; +typedef Ptr EbscTablePtr; +typedef Ptr EbscTableBuilderPtr; + +} // namespace sfntly + +#endif // SFNTLY_CPP_SRC_SFNTLY_TABLE_BITMAP_EBSC_TABLE_H_ diff --git a/src/sfntly/src/sfntly/table/bitmap/glyph_metrics.cc b/src/sfntly/src/sfntly/table/bitmap/glyph_metrics.cc new file mode 100644 index 000000000000..e91eb9921ee2 --- /dev/null +++ b/src/sfntly/src/sfntly/table/bitmap/glyph_metrics.cc @@ -0,0 +1,39 @@ +/* + * 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. + */ + +#include "sfntly/table/bitmap/glyph_metrics.h" + +namespace sfntly { + +GlyphMetrics::~GlyphMetrics() { +} + +GlyphMetrics::GlyphMetrics(ReadableFontData* data) + : SubTable(data) { +} + +GlyphMetrics::Builder::~Builder() { +} + +GlyphMetrics::Builder::Builder(WritableFontData* data) + : SubTable::Builder(data) { +} + +GlyphMetrics::Builder::Builder(ReadableFontData* data) + : SubTable::Builder(data) { +} + +} // namespace sfntly diff --git a/src/sfntly/src/sfntly/table/bitmap/glyph_metrics.h b/src/sfntly/src/sfntly/table/bitmap/glyph_metrics.h new file mode 100644 index 000000000000..5f16aaa661d9 --- /dev/null +++ b/src/sfntly/src/sfntly/table/bitmap/glyph_metrics.h @@ -0,0 +1,43 @@ +/* + * 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. + */ + +#ifndef SFNTLY_CPP_SRC_SFNTLY_TABLE_BITMAP_GLYPH_METRICS_H_ +#define SFNTLY_CPP_SRC_SFNTLY_TABLE_BITMAP_GLYPH_METRICS_H_ + +#include "sfntly/table/subtable.h" + +namespace sfntly { + +class GlyphMetrics : public SubTable { + public: + virtual ~GlyphMetrics(); + + protected: + class Builder : public SubTable::Builder { + public: + virtual ~Builder(); + + protected: + explicit Builder(WritableFontData* data); + explicit Builder(ReadableFontData* data); + }; + + explicit GlyphMetrics(ReadableFontData* data); +}; + +} // namespace sfntly + +#endif // SFNTLY_CPP_SRC_SFNTLY_TABLE_BITMAP_GLYPH_METRICS_H_ diff --git a/src/sfntly/src/sfntly/table/bitmap/index_sub_table.cc b/src/sfntly/src/sfntly/table/bitmap/index_sub_table.cc new file mode 100644 index 000000000000..5e297845042b --- /dev/null +++ b/src/sfntly/src/sfntly/table/bitmap/index_sub_table.cc @@ -0,0 +1,278 @@ +/* + * 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. + */ + +#include "sfntly/table/bitmap/index_sub_table.h" + +#include "sfntly/table/bitmap/eblc_table.h" +#include "sfntly/table/bitmap/index_sub_table_format1.h" +#include "sfntly/table/bitmap/index_sub_table_format2.h" +#include "sfntly/table/bitmap/index_sub_table_format3.h" +#include "sfntly/table/bitmap/index_sub_table_format4.h" +#include "sfntly/table/bitmap/index_sub_table_format5.h" + +namespace sfntly { +/****************************************************************************** + * IndexSubTable class + ******************************************************************************/ +CALLER_ATTACH BitmapGlyphInfo* IndexSubTable::GlyphInfo(int32_t glyph_id) { + int32_t loca = CheckGlyphRange(glyph_id); + if (loca == -1) { + return NULL; + } + if (GlyphStartOffset(glyph_id) == -1) { + return NULL; + } + BitmapGlyphInfoPtr output = new BitmapGlyphInfo(glyph_id, + image_data_offset(), + GlyphStartOffset(glyph_id), + GlyphLength(glyph_id), + image_format()); + return output.Detach(); +} + +int32_t IndexSubTable::GlyphOffset(int32_t glyph_id) { + int32_t glyph_start_offset = GlyphStartOffset(glyph_id); + if (glyph_start_offset == -1) { + return -1; + } + return image_data_offset() + glyph_start_offset; +} + +// static +CALLER_ATTACH IndexSubTable* + IndexSubTable::CreateIndexSubTable(ReadableFontData* data, + int32_t offset_to_index_sub_table_array, + int32_t array_index) { + IndexSubTableBuilderPtr builder; + builder.Attach(IndexSubTable::Builder::CreateBuilder( + data, offset_to_index_sub_table_array, array_index)); + return down_cast(builder->Build()); +} + +IndexSubTable::IndexSubTable(ReadableFontData* data, + int32_t first_glyph_index, + int32_t last_glyph_index) + : SubTable(data), + first_glyph_index_(first_glyph_index), + last_glyph_index_(last_glyph_index) { + index_format_ = + data_->ReadUShort(EblcTable::Offset::kIndexSubHeader_indexFormat); + image_format_ = + data_->ReadUShort(EblcTable::Offset::kIndexSubHeader_imageFormat); + image_data_offset_ = + data_->ReadULongAsInt(EblcTable::Offset::kIndexSubHeader_imageDataOffset); +} + +int32_t IndexSubTable::CheckGlyphRange(int32_t glyph_id) { + return CheckGlyphRange(glyph_id, first_glyph_index(), last_glyph_index()); +} + +// static +int32_t IndexSubTable::CheckGlyphRange(int32_t glyph_id, + int32_t first_glyph_id, + int32_t last_glyph_id) { + if (glyph_id < first_glyph_id || glyph_id > last_glyph_id) { +#if !defined (SFNTLY_NO_EXCEPTION) + throw IndexOutOfBoundException("Glyph ID is outside of the allowed range."); +#endif + return -1; + } + return glyph_id - first_glyph_id; +} + +/****************************************************************************** + * IndexSubTable::Builder class + ******************************************************************************/ +IndexSubTable::Builder::~Builder() { +} + +void IndexSubTable::Builder::Revert() { + set_model_changed(false); + Initialize(InternalReadData()); +} + +CALLER_ATTACH BitmapGlyphInfo* IndexSubTable::Builder::GlyphInfo( + int32_t glyph_id) { + BitmapGlyphInfoPtr glyph_info = + new BitmapGlyphInfo(glyph_id, + image_data_offset(), + GlyphStartOffset(glyph_id), + GlyphLength(glyph_id), + image_format()); + return glyph_info.Detach(); +} + +int32_t IndexSubTable::Builder::GlyphOffset(int32_t glyph_id) { + return image_data_offset() + GlyphStartOffset(glyph_id); +} + +// static +CALLER_ATTACH IndexSubTable::Builder* +IndexSubTable::Builder::CreateBuilder(int32_t index_format) { + switch (index_format) { + case Format::FORMAT_1: + return IndexSubTableFormat1::Builder::CreateBuilder(); + case Format::FORMAT_2: + return IndexSubTableFormat2::Builder::CreateBuilder(); + case Format::FORMAT_3: + return IndexSubTableFormat3::Builder::CreateBuilder(); + case Format::FORMAT_4: + return IndexSubTableFormat4::Builder::CreateBuilder(); + case Format::FORMAT_5: + return IndexSubTableFormat5::Builder::CreateBuilder(); + default: +#if !defined (SFNTLY_NO_EXCEPTION) + throw IllegalArgumentException("Invalid index subtable format"); +#endif + return NULL; + } +} + +// static +CALLER_ATTACH IndexSubTable::Builder* +IndexSubTable::Builder::CreateBuilder(ReadableFontData* data, + int32_t offset_to_index_sub_table_array, int32_t array_index) { + int32_t index_sub_table_entry_offset = + offset_to_index_sub_table_array + + array_index * EblcTable::Offset::kIndexSubTableEntryLength; + int32_t first_glyph_index = + data->ReadUShort(index_sub_table_entry_offset + + EblcTable::Offset::kIndexSubTableEntry_firstGlyphIndex); + int32_t last_glyph_index = + data->ReadUShort(index_sub_table_entry_offset + + EblcTable::Offset::kIndexSubTableEntry_lastGlyphIndex); + int32_t additional_offset_to_index_subtable = data->ReadULongAsInt( + index_sub_table_entry_offset + + EblcTable::Offset::kIndexSubTableEntry_additionalOffsetToIndexSubTable); + int32_t index_sub_table_offset = offset_to_index_sub_table_array + + additional_offset_to_index_subtable; + int32_t index_format = data->ReadUShort(index_sub_table_offset); + switch (index_format) { + case 1: + return IndexSubTableFormat1::Builder::CreateBuilder( + data, index_sub_table_offset, first_glyph_index, last_glyph_index); + case 2: + return IndexSubTableFormat2::Builder::CreateBuilder( + data, index_sub_table_offset, first_glyph_index, last_glyph_index); + case 3: + return IndexSubTableFormat3::Builder::CreateBuilder( + data, index_sub_table_offset, first_glyph_index, last_glyph_index); + case 4: + return IndexSubTableFormat4::Builder::CreateBuilder( + data, index_sub_table_offset, first_glyph_index, last_glyph_index); + case 5: + return IndexSubTableFormat5::Builder::CreateBuilder( + data, index_sub_table_offset, first_glyph_index, last_glyph_index); + default: + // Unknown format and unable to process. +#if !defined (SFNTLY_NO_EXCEPTION) + throw IllegalArgumentException("Invalid Index Subtable Format"); +#endif + break; + } + return NULL; +} + +CALLER_ATTACH +FontDataTable* IndexSubTable::Builder::SubBuildTable(ReadableFontData* data) { + UNREFERENCED_PARAMETER(data); + return NULL; +} + +void IndexSubTable::Builder::SubDataSet() { + // NOP +} + +int32_t IndexSubTable::Builder::SubDataSizeToSerialize() { + return 0; +} + +bool IndexSubTable::Builder::SubReadyToSerialize() { + return false; +} + +int32_t IndexSubTable::Builder::SubSerialize(WritableFontData* new_data) { + UNREFERENCED_PARAMETER(new_data); + return 0; +} + +IndexSubTable::Builder::Builder(int32_t data_size, int32_t index_format) + : SubTable::Builder(data_size), + first_glyph_index_(0), + last_glyph_index_(0), + index_format_(index_format), + image_format_(0), + image_data_offset_(0) { +} + +IndexSubTable::Builder::Builder(int32_t index_format, + int32_t image_format, + int32_t image_data_offset, + int32_t data_size) + : SubTable::Builder(data_size), + first_glyph_index_(0), + last_glyph_index_(0), + index_format_(index_format), + image_format_(image_format), + image_data_offset_(image_data_offset) { +} + +IndexSubTable::Builder::Builder(WritableFontData* data, + int32_t first_glyph_index, + int32_t last_glyph_index) + : SubTable::Builder(data), + first_glyph_index_(first_glyph_index), + last_glyph_index_(last_glyph_index) { + Initialize(data); +} + +IndexSubTable::Builder::Builder(ReadableFontData* data, + int32_t first_glyph_index, + int32_t last_glyph_index) + : SubTable::Builder(data), + first_glyph_index_(first_glyph_index), + last_glyph_index_(last_glyph_index) { + Initialize(data); +} + +int32_t IndexSubTable::Builder::CheckGlyphRange(int32_t glyph_id) { + return IndexSubTable::CheckGlyphRange(glyph_id, + first_glyph_index(), + last_glyph_index()); +} + +int32_t IndexSubTable::Builder::SerializeIndexSubHeader( + WritableFontData* data) { + int32_t size = + data->WriteUShort(EblcTable::Offset::kIndexSubHeader_indexFormat, + index_format()); + size += data->WriteUShort(EblcTable::Offset::kIndexSubHeader_imageFormat, + image_format()); + size += data->WriteULong(EblcTable::Offset::kIndexSubHeader_imageDataOffset, + image_data_offset()); + return size; +} + +void IndexSubTable::Builder::Initialize(ReadableFontData* data) { + index_format_ = + data->ReadUShort(EblcTable::Offset::kIndexSubHeader_indexFormat); + image_format_ = + data->ReadUShort(EblcTable::Offset::kIndexSubHeader_imageFormat); + image_data_offset_ = + data->ReadULongAsInt(EblcTable::Offset::kIndexSubHeader_imageDataOffset); +} + +} // namespace sfntly diff --git a/src/sfntly/src/sfntly/table/bitmap/index_sub_table.h b/src/sfntly/src/sfntly/table/bitmap/index_sub_table.h new file mode 100644 index 000000000000..6d27129ccd31 --- /dev/null +++ b/src/sfntly/src/sfntly/table/bitmap/index_sub_table.h @@ -0,0 +1,178 @@ +/* + * 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. + */ + +#ifndef SFNTLY_CPP_SRC_SFNTLY_TABLE_BITMAP_INDEX_SUBTABLE_H_ +#define SFNTLY_CPP_SRC_SFNTLY_TABLE_BITMAP_INDEX_SUBTABLE_H_ + +#include + +#include "sfntly/port/java_iterator.h" +#include "sfntly/table/subtable.h" +#include "sfntly/table/bitmap/bitmap_glyph_info.h" + +namespace sfntly { + +class IndexSubTable : public SubTable { + public: + struct Format { + enum { + FORMAT_1 = 1, + FORMAT_2 = 2, + FORMAT_3 = 3, + FORMAT_4 = 4, + FORMAT_5 = 5, + }; + }; + + class Builder : public SubTable::Builder { + public: + virtual ~Builder(); + + void Revert(); + + int32_t index_format() { return index_format_; } + int32_t first_glyph_index() { return first_glyph_index_; } + void set_first_glyph_index(int32_t v) { first_glyph_index_ = v; } + int32_t last_glyph_index() { return last_glyph_index_; } + void set_last_glyph_index(int32_t v) { last_glyph_index_ = v; } + int32_t image_format() { return image_format_; } + void set_image_format(int32_t v) { image_format_ = v; } + int32_t image_data_offset() { return image_data_offset_; } + void set_image_data_offset(int32_t v) { image_data_offset_ = v; } + + virtual int32_t NumGlyphs() = 0; + + // Gets the glyph info for the specified glyph id. + // @param glyphId the glyph id to look up + // @return the glyph info + CALLER_ATTACH virtual BitmapGlyphInfo* GlyphInfo(int32_t glyph_id); + + // Gets the full offset of the glyph within the EBDT table. + // @param glyphId the glyph id + // @return the glyph offset + virtual int32_t GlyphOffset(int32_t glyph_id); + + // Gets the offset of the glyph relative to the block for this index + // subtable. + // @param glyphId the glyph id + // @return the glyph offset + virtual int32_t GlyphStartOffset(int32_t glyph_id) = 0; + + // Gets the length of the glyph within the EBDT table. + // @param glyphId the glyph id + // @return the glyph offset + virtual int32_t GlyphLength(int32_t glyph_id) = 0; + + // Note: renamed from java iterator() + CALLER_ATTACH virtual Iterator* + GetIterator() = 0; + + // Static instantiation function. + static CALLER_ATTACH Builder* CreateBuilder(int32_t index_format); + static CALLER_ATTACH Builder* + CreateBuilder(ReadableFontData* data, + int32_t offset_to_index_sub_table_array, + int32_t array_index); + + // The following methods will never be called but they need to be here to + // allow the BitmapSizeTable to see these methods through an abstract + // reference. + virtual CALLER_ATTACH FontDataTable* SubBuildTable(ReadableFontData* data); + virtual void SubDataSet(); + virtual int32_t SubDataSizeToSerialize(); + virtual bool SubReadyToSerialize(); + virtual int32_t SubSerialize(WritableFontData* new_data); + + protected: + Builder(int32_t data_size, int32_t index_format); + Builder(int32_t index_format, + int32_t image_format, + int32_t image_data_offset, + int32_t data_size); + Builder(WritableFontData* data, + int32_t first_glyph_index, + int32_t last_glyph_index); + Builder(ReadableFontData* data, + int32_t first_glyph_index, + int32_t last_glyph_index); + + // Checks that the glyph id is within the correct range. If it returns the + // offset of the glyph id from the start of the range. + // @param glyphId + // @return the offset of the glyphId from the start of the glyph range + // @throws IndexOutOfBoundsException if the glyph id is not within the + // correct range + int32_t CheckGlyphRange(int32_t glyph_id); + int32_t SerializeIndexSubHeader(WritableFontData* data); + + private: + void Initialize(ReadableFontData* data); + + int32_t first_glyph_index_; + int32_t last_glyph_index_; + int32_t index_format_; + int32_t image_format_; + int32_t image_data_offset_; + }; + + int32_t index_format() { return index_format_; } + int32_t first_glyph_index() { return first_glyph_index_; } + int32_t last_glyph_index() { return last_glyph_index_; } + int32_t image_format() { return image_format_; } + int32_t image_data_offset() { return image_data_offset_; } + + CALLER_ATTACH BitmapGlyphInfo* GlyphInfo(int32_t glyph_id); + virtual int32_t GlyphOffset(int32_t glyph_id); + virtual int32_t GlyphStartOffset(int32_t glyph_id) = 0; + virtual int32_t GlyphLength(int32_t glyph_id) = 0; + virtual int32_t NumGlyphs() = 0; + + static CALLER_ATTACH IndexSubTable* + CreateIndexSubTable(ReadableFontData* data, + int32_t offset_to_index_sub_table_array, + int32_t array_index); + + protected: + // Note: the constructor does not implement offset/length form provided in + // Java to avoid heavy lifting in constructors. Callers to call + // GetDataLength() static method of the derived class to get proper + // length and slice ahead. + IndexSubTable(ReadableFontData* data, + int32_t first_glyph_index, + int32_t last_glyph_index); + + int32_t CheckGlyphRange(int32_t glyph_id); + static int32_t CheckGlyphRange(int32_t glyph_id, + int32_t first_glyph_id, + int32_t last_glyph_id); + + private: + int32_t first_glyph_index_; + int32_t last_glyph_index_; + int32_t index_format_; + int32_t image_format_; + int32_t image_data_offset_; +}; +typedef Ptr IndexSubTablePtr; +typedef std::vector IndexSubTableList; +typedef Ptr IndexSubTableBuilderPtr; +typedef std::vector IndexSubTableBuilderList; +typedef Iterator BitmapGlyphInfoIter; +typedef Ptr BitmapGlyphInfoIterPtr; + +} // namespace sfntly + +#endif // SFNTLY_CPP_SRC_SFNTLY_TABLE_BITMAP_INDEX_SUBTABLE_H_ diff --git a/src/sfntly/src/sfntly/table/bitmap/index_sub_table_format1.cc b/src/sfntly/src/sfntly/table/bitmap/index_sub_table_format1.cc new file mode 100644 index 000000000000..db73723916ac --- /dev/null +++ b/src/sfntly/src/sfntly/table/bitmap/index_sub_table_format1.cc @@ -0,0 +1,299 @@ +/* + * 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. + */ + +#include "sfntly/table/bitmap/index_sub_table_format1.h" + +#include "sfntly/table/bitmap/eblc_table.h" + +namespace sfntly { +/****************************************************************************** + * IndexSubTableFormat1 class + ******************************************************************************/ +// static +int32_t IndexSubTableFormat1::GetDataLength(ReadableFontData* data, + int32_t offset, + int32_t first, + int32_t last) { + UNREFERENCED_PARAMETER(data); + UNREFERENCED_PARAMETER(offset); + return (last - first + 1 + 1) * DataSize::kULONG; +} + +IndexSubTableFormat1::~IndexSubTableFormat1() { +} + +int32_t IndexSubTableFormat1::NumGlyphs() { + return last_glyph_index() - first_glyph_index() + 1; +} + +int32_t IndexSubTableFormat1::GlyphStartOffset(int32_t glyph_id) { + int32_t loca = CheckGlyphRange(glyph_id); + if (loca == -1) { + return -1; + } + return Loca(loca); +} + +int32_t IndexSubTableFormat1::GlyphLength(int32_t glyph_id) { + int32_t loca = CheckGlyphRange(glyph_id); + if (loca == -1) { + return -1; + } + return Loca(loca + 1) - Loca(loca); +} + +IndexSubTableFormat1::IndexSubTableFormat1(ReadableFontData* data, + int32_t first_glyph_index, + int32_t last_glyph_index) + : IndexSubTable(data, first_glyph_index, last_glyph_index) { +} + +int32_t IndexSubTableFormat1::Loca(int32_t loca) { + return image_data_offset() + + data_->ReadULongAsInt(EblcTable::Offset::kIndexSubTable1_offsetArray + + loca * DataSize::kULONG); +} + +/****************************************************************************** + * IndexSubTableFormat1::Builder class + ******************************************************************************/ +IndexSubTableFormat1::Builder::~Builder() { +} + +int32_t IndexSubTableFormat1::Builder::NumGlyphs() { + return GetOffsetArray()->size() - 1; +} + +int32_t IndexSubTableFormat1::Builder::GlyphLength(int32_t glyph_id) { + int32_t loca = CheckGlyphRange(glyph_id); + if (loca == -1) { + return 0; + } + IntegerList* offset_array = GetOffsetArray(); + return offset_array->at(loca + 1) - offset_array->at(loca); +} + +int32_t IndexSubTableFormat1::Builder::GlyphStartOffset(int32_t glyph_id) { + int32_t loca = CheckGlyphRange(glyph_id); + if (loca == -1) { + return -1; + } + return GetOffsetArray()->at(loca); +} + +CALLER_ATTACH IndexSubTableFormat1::Builder::BitmapGlyphInfoIterator* + IndexSubTableFormat1::Builder::GetIterator() { + Ptr it = + new IndexSubTableFormat1::Builder::BitmapGlyphInfoIterator(this); + return it.Detach(); +} + +// static +CALLER_ATTACH IndexSubTableFormat1::Builder* +IndexSubTableFormat1::Builder::CreateBuilder() { + IndexSubTableFormat1BuilderPtr output = new IndexSubTableFormat1::Builder(); + return output.Detach(); +} + +// static +CALLER_ATTACH IndexSubTableFormat1::Builder* +IndexSubTableFormat1::Builder::CreateBuilder(ReadableFontData* data, + int32_t index_sub_table_offset, + int32_t first_glyph_index, + int32_t last_glyph_index) { + int32_t length = Builder::DataLength(data, + index_sub_table_offset, + first_glyph_index, + last_glyph_index); + ReadableFontDataPtr new_data; + new_data.Attach(down_cast( + data->Slice(index_sub_table_offset, length))); + IndexSubTableFormat1BuilderPtr output = + new IndexSubTableFormat1::Builder(new_data, + first_glyph_index, + last_glyph_index); + return output.Detach(); +} + + +// static +CALLER_ATTACH IndexSubTableFormat1::Builder* +IndexSubTableFormat1::Builder::CreateBuilder(WritableFontData* data, + int32_t index_sub_table_offset, + int32_t first_glyph_index, + int32_t last_glyph_index) { + int32_t length = Builder::DataLength(data, + index_sub_table_offset, + first_glyph_index, + last_glyph_index); + WritableFontDataPtr new_data; + new_data.Attach(down_cast( + data->Slice(index_sub_table_offset, length))); + IndexSubTableFormat1BuilderPtr output = + new IndexSubTableFormat1::Builder(new_data, + first_glyph_index, + last_glyph_index); + return output.Detach(); +} + +CALLER_ATTACH FontDataTable* IndexSubTableFormat1::Builder::SubBuildTable( + ReadableFontData* data) { + IndexSubTableFormat1Ptr output = new IndexSubTableFormat1( + data, first_glyph_index(), last_glyph_index()); + return output.Detach(); +} + +void IndexSubTableFormat1::Builder::SubDataSet() { + Revert(); +} + +int32_t IndexSubTableFormat1::Builder::SubDataSizeToSerialize() { + if (offset_array_.empty()) { + return InternalReadData()->Length(); + } + return EblcTable::Offset::kIndexSubHeaderLength + + offset_array_.size() * DataSize::kULONG; +} + +bool IndexSubTableFormat1::Builder::SubReadyToSerialize() { + if (!offset_array_.empty()) { + return true; + } + return false; +} + +int32_t IndexSubTableFormat1::Builder::SubSerialize( + WritableFontData* new_data) { + int32_t size = SerializeIndexSubHeader(new_data); + if (!model_changed()) { + if (InternalReadData() == NULL) { + return size; + } + ReadableFontDataPtr source; + WritableFontDataPtr target; + source.Attach(down_cast(InternalReadData()->Slice( + EblcTable::Offset::kIndexSubTable1_offsetArray))); + target.Attach(down_cast(new_data->Slice( + EblcTable::Offset::kIndexSubTable1_offsetArray))); + size += source->CopyTo(target); + } else { + for (IntegerList::iterator b = GetOffsetArray()->begin(), + e = GetOffsetArray()->end(); b != e; b++) { + size += new_data->WriteLong(size, *b); + } + } + return size; +} + +IntegerList* IndexSubTableFormat1::Builder::OffsetArray() { + return GetOffsetArray(); +} + +void IndexSubTableFormat1::Builder::SetOffsetArray( + const IntegerList& offset_array) { + offset_array_.clear(); + offset_array_ = offset_array; + set_model_changed(); +} + +void IndexSubTableFormat1::Builder::Revert() { + offset_array_.clear(); + IndexSubTable::Builder::Revert(); +} + +IndexSubTableFormat1::Builder::Builder() + : IndexSubTable::Builder(EblcTable::Offset::kIndexSubTable1_builderDataSize, + IndexSubTable::Format::FORMAT_1) { +} + +IndexSubTableFormat1::Builder::Builder(WritableFontData* data, + int32_t first_glyph_index, + int32_t last_glyph_index) + : IndexSubTable::Builder(data, first_glyph_index, last_glyph_index) { +} + +IndexSubTableFormat1::Builder::Builder(ReadableFontData* data, + int32_t first_glyph_index, + int32_t last_glyph_index) + : IndexSubTable::Builder(data, first_glyph_index, last_glyph_index) { +} + +IntegerList* IndexSubTableFormat1::Builder::GetOffsetArray() { + if (offset_array_.empty()) { + Initialize(InternalReadData()); + set_model_changed(); + } + return &offset_array_; +} + +void IndexSubTableFormat1::Builder::Initialize(ReadableFontData* data) { + offset_array_.clear(); + if (data) { + int32_t num_offsets = (last_glyph_index() - first_glyph_index() + 1) + 1; + for (int32_t i = 0; i < num_offsets; ++i) { + offset_array_.push_back(data->ReadULongAsInt( + EblcTable::Offset::kIndexSubTable1_offsetArray + + i * DataSize::kULONG)); + } + } +} + +// static +int32_t IndexSubTableFormat1::Builder::DataLength( + ReadableFontData* data, + int32_t index_sub_table_offset, + int32_t first_glyph_index, + int32_t last_glyph_index) { + UNREFERENCED_PARAMETER(data); + UNREFERENCED_PARAMETER(index_sub_table_offset); + return EblcTable::Offset::kIndexSubHeaderLength + + (last_glyph_index - first_glyph_index + 1 + 1) * DataSize::kULONG; +} + +/****************************************************************************** + * IndexSubTableFormat1::Builder::BitmapGlyphInfoIterator class + ******************************************************************************/ +IndexSubTableFormat1::Builder::BitmapGlyphInfoIterator::BitmapGlyphInfoIterator( + IndexSubTableFormat1::Builder* container) + : RefIterator(container) { + glyph_id_ = container->first_glyph_index(); +} + +bool IndexSubTableFormat1::Builder::BitmapGlyphInfoIterator::HasNext() { + if (glyph_id_ <= container()->last_glyph_index()) { + return true; + } + return false; +} + +CALLER_ATTACH BitmapGlyphInfo* +IndexSubTableFormat1::Builder::BitmapGlyphInfoIterator::Next() { + BitmapGlyphInfoPtr output; + if (!HasNext()) { + // Note: In C++, we do not throw exception when there's no element. + return NULL; + } + output = new BitmapGlyphInfo(glyph_id_, + container()->image_data_offset(), + container()->GlyphStartOffset(glyph_id_), + container()->GlyphLength(glyph_id_), + container()->image_format()); + glyph_id_++; + return output.Detach(); +} + +} // namespace sfntly diff --git a/src/sfntly/src/sfntly/table/bitmap/index_sub_table_format1.h b/src/sfntly/src/sfntly/table/bitmap/index_sub_table_format1.h new file mode 100644 index 000000000000..33171c156115 --- /dev/null +++ b/src/sfntly/src/sfntly/table/bitmap/index_sub_table_format1.h @@ -0,0 +1,116 @@ +/* + * 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. + */ + +#ifndef SFNTLY_CPP_SRC_SFNTLY_TABLE_BITMAP_INDEX_SUBTABLE_FORMAT1_H_ +#define SFNTLY_CPP_SRC_SFNTLY_TABLE_BITMAP_INDEX_SUBTABLE_FORMAT1_H_ + +#include "sfntly/port/java_iterator.h" +#include "sfntly/table/bitmap/index_sub_table.h" + +namespace sfntly { +// Format 1 Index Subtable Entry. +class IndexSubTableFormat1 : public IndexSubTable, + public RefCounted { + public: + class Builder : public IndexSubTable::Builder, + public RefCounted { + public: + class BitmapGlyphInfoIterator + : public RefIterator { + public: + explicit BitmapGlyphInfoIterator(Builder* container); + virtual ~BitmapGlyphInfoIterator() {} + + virtual bool HasNext(); + CALLER_ATTACH virtual BitmapGlyphInfo* Next(); + + private: + int32_t glyph_id_; + }; + + virtual ~Builder(); + virtual int32_t NumGlyphs(); + virtual int32_t GlyphLength(int32_t glyph_id); + virtual int32_t GlyphStartOffset(int32_t glyph_id); + CALLER_ATTACH virtual BitmapGlyphInfoIterator* GetIterator(); + + virtual CALLER_ATTACH FontDataTable* SubBuildTable(ReadableFontData* data); + virtual void SubDataSet(); + virtual int32_t SubDataSizeToSerialize(); + virtual bool SubReadyToSerialize(); + virtual int32_t SubSerialize(WritableFontData* new_data); + + IntegerList* OffsetArray(); + void SetOffsetArray(const IntegerList& offset_array); + CALLER_ATTACH BitmapGlyphInfoIter* Iterator(); + + static CALLER_ATTACH Builder* CreateBuilder(); + static CALLER_ATTACH Builder* CreateBuilder(ReadableFontData* data, + int32_t index_sub_table_offset, + int32_t first_glyph_index, + int32_t last_glyph_index); + static CALLER_ATTACH Builder* CreateBuilder(WritableFontData* data, + int32_t index_sub_table_offset, + int32_t first_glyph_index, + int32_t last_glyph_index); + + protected: + void Revert(); + + private: + Builder(); + Builder(WritableFontData* data, + int32_t first_glyph_index, + int32_t last_glyph_index); + Builder(ReadableFontData* data, + int32_t first_glyph_index, + int32_t last_glyph_index); + IntegerList* GetOffsetArray(); + void Initialize(ReadableFontData* data); + + static int32_t DataLength(ReadableFontData* data, + int32_t index_sub_table_offset, + int32_t first_glyph_index, + int32_t last_glyph_index); + + IntegerList offset_array_; + }; + + virtual ~IndexSubTableFormat1(); + + virtual int32_t NumGlyphs(); + virtual int32_t GlyphStartOffset(int32_t glyph_id); + virtual int32_t GlyphLength(int32_t glyph_id); + + static int32_t GetDataLength(ReadableFontData* data, + int32_t offset, + int32_t first, + int32_t last); + + private: + IndexSubTableFormat1(ReadableFontData* data, + int32_t first_glyph_index, + int32_t last_glyph_index); + int32_t Loca(int32_t loca_index); + + friend class Builder; +}; +typedef Ptr IndexSubTableFormat1Ptr; +typedef Ptr IndexSubTableFormat1BuilderPtr; + +} // namespace sfntly + +#endif // SFNTLY_CPP_SRC_SFNTLY_TABLE_BITMAP_INDEX_SUBTABLE_FORMAT1_H_ diff --git a/src/sfntly/src/sfntly/table/bitmap/index_sub_table_format2.cc b/src/sfntly/src/sfntly/table/bitmap/index_sub_table_format2.cc new file mode 100644 index 000000000000..b3bffdad9189 --- /dev/null +++ b/src/sfntly/src/sfntly/table/bitmap/index_sub_table_format2.cc @@ -0,0 +1,272 @@ +/* + * 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. + */ + +#include "sfntly/table/bitmap/index_sub_table_format2.h" + +#include "sfntly/table/bitmap/eblc_table.h" + +namespace sfntly { +/****************************************************************************** + * IndexSubTableFormat2 class + ******************************************************************************/ +IndexSubTableFormat2::~IndexSubTableFormat2() { +} + +int32_t IndexSubTableFormat2::ImageSize() { + return data_->ReadULongAsInt(EblcTable::Offset::kIndexSubTable2_imageSize); +} + +CALLER_ATTACH BigGlyphMetrics* IndexSubTableFormat2::BigMetrics() { + ReadableFontDataPtr slice; + slice.Attach(down_cast( + data_->Slice(EblcTable::Offset::kIndexSubTable2_bigGlyphMetrics, + BigGlyphMetrics::Offset::kMetricsLength))); + BigGlyphMetricsPtr output = new BigGlyphMetrics(slice); + return output.Detach(); +} + +int32_t IndexSubTableFormat2::NumGlyphs() { + return last_glyph_index() - first_glyph_index() + 1; +} + +int32_t IndexSubTableFormat2::GlyphStartOffset(int32_t glyph_id) { + int32_t loca = CheckGlyphRange(glyph_id); + if (loca == -1) { + return -1; + } + return loca * image_size_; +} + +int32_t IndexSubTableFormat2::GlyphLength(int32_t glyph_id) { + if (CheckGlyphRange(glyph_id) == -1) { + return 0; + } + return image_size_; +} + +IndexSubTableFormat2::IndexSubTableFormat2(ReadableFontData* data, + int32_t first, + int32_t last) + : IndexSubTable(data, first, last) { + image_size_ = + data_->ReadULongAsInt(EblcTable::Offset::kIndexSubTable2_imageSize); +} + +/****************************************************************************** + * IndexSubTableFormat2::Builder class + ******************************************************************************/ +IndexSubTableFormat2::Builder::~Builder() { +} + +int32_t IndexSubTableFormat2::Builder::NumGlyphs() { + return last_glyph_index() - first_glyph_index() + 1; +} + +int32_t IndexSubTableFormat2::Builder::GlyphStartOffset(int32_t glyph_id) { + int32_t loca = CheckGlyphRange(glyph_id); + if (loca == -1) { + return -1; + } + return loca * ImageSize(); +} + +int32_t IndexSubTableFormat2::Builder::GlyphLength(int32_t glyph_id) { + int32_t loca = CheckGlyphRange(glyph_id); + if (loca == -1) { + return 0; + } + return ImageSize(); +} + +CALLER_ATTACH IndexSubTableFormat2::Builder::BitmapGlyphInfoIterator* + IndexSubTableFormat2::Builder::GetIterator() { + Ptr it = + new IndexSubTableFormat2::Builder::BitmapGlyphInfoIterator(this); + return it.Detach(); +} + +int32_t IndexSubTableFormat2::Builder::ImageSize() { + return InternalReadData()->ReadULongAsInt( + EblcTable::Offset::kIndexSubTable2_imageSize); +} + +void IndexSubTableFormat2::Builder::SetImageSize(int32_t image_size) { + InternalWriteData()->WriteULong(EblcTable::Offset::kIndexSubTable2_imageSize, + image_size); +} + +BigGlyphMetrics::Builder* IndexSubTableFormat2::Builder::BigMetrics() { + if (metrics_ == NULL) { + WritableFontDataPtr data; + data.Attach(down_cast(InternalWriteData()->Slice( + EblcTable::Offset::kIndexSubTable2_bigGlyphMetrics, + BigGlyphMetrics::Offset::kMetricsLength))); + metrics_ = new BigGlyphMetrics::Builder(data); + } + return metrics_; +} + +// static +CALLER_ATTACH IndexSubTableFormat2::Builder* +IndexSubTableFormat2::Builder::CreateBuilder() { + IndexSubTableFormat2BuilderPtr output = new IndexSubTableFormat2::Builder(); + return output.Detach(); +} + +// static +CALLER_ATTACH IndexSubTableFormat2::Builder* +IndexSubTableFormat2::Builder::CreateBuilder(ReadableFontData* data, + int32_t index_sub_table_offset, + int32_t first_glyph_index, + int32_t last_glyph_index) { + int32_t length = Builder::DataLength(data, + index_sub_table_offset, + first_glyph_index, + last_glyph_index); + ReadableFontDataPtr new_data; + new_data.Attach(down_cast( + data->Slice(index_sub_table_offset, length))); + IndexSubTableFormat2BuilderPtr output = + new IndexSubTableFormat2::Builder(new_data, + first_glyph_index, + last_glyph_index); + return output.Detach(); +} + +// static +CALLER_ATTACH IndexSubTableFormat2::Builder* +IndexSubTableFormat2::Builder::CreateBuilder(WritableFontData* data, + int32_t index_sub_table_offset, + int32_t first_glyph_index, + int32_t last_glyph_index) { + int32_t length = Builder::DataLength(data, + index_sub_table_offset, + first_glyph_index, + last_glyph_index); + WritableFontDataPtr new_data; + new_data.Attach(down_cast( + data->Slice(index_sub_table_offset, length))); + IndexSubTableFormat2BuilderPtr output = + new IndexSubTableFormat2::Builder(new_data, + first_glyph_index, + last_glyph_index); + return output.Detach(); +} + +CALLER_ATTACH FontDataTable* IndexSubTableFormat2::Builder::SubBuildTable( + ReadableFontData* data) { + IndexSubTableFormat2Ptr output = new IndexSubTableFormat2( + data, first_glyph_index(), last_glyph_index()); + return output.Detach(); +} + +void IndexSubTableFormat2::Builder::SubDataSet() { + Revert(); +} + +int32_t IndexSubTableFormat2::Builder::SubDataSizeToSerialize() { + return EblcTable::Offset::kIndexSubTable2Length; +} + +bool IndexSubTableFormat2::Builder::SubReadyToSerialize() { + return true; +} + +int32_t IndexSubTableFormat2::Builder::SubSerialize( + WritableFontData* new_data) { + int32_t size = SerializeIndexSubHeader(new_data); + if (metrics_ == NULL) { + ReadableFontDataPtr source; + WritableFontDataPtr target; + source.Attach(down_cast( + InternalReadData()->Slice(size))); + target.Attach(down_cast(new_data->Slice(size))); + size += source->CopyTo(target); + } else { + WritableFontDataPtr slice; + size += new_data->WriteLong(EblcTable::Offset::kIndexSubTable2_imageSize, + ImageSize()); + slice.Attach(down_cast(new_data->Slice(size))); + size += metrics_->SubSerialize(slice); + } + return size; +} + +IndexSubTableFormat2::Builder::Builder() + : IndexSubTable::Builder(EblcTable::Offset::kIndexSubTable3_builderDataSize, + IndexSubTable::Format::FORMAT_2) { + metrics_.Attach(BigGlyphMetrics::Builder::CreateBuilder()); +} + +IndexSubTableFormat2::Builder::Builder(WritableFontData* data, + int32_t first_glyph_index, + int32_t last_glyph_index) + : IndexSubTable::Builder(data, first_glyph_index, last_glyph_index) { +} + +IndexSubTableFormat2::Builder::Builder(ReadableFontData* data, + int32_t first_glyph_index, + int32_t last_glyph_index) + : IndexSubTable::Builder(data, first_glyph_index, last_glyph_index) { +} + +// static +int32_t IndexSubTableFormat2::Builder::DataLength( + ReadableFontData* data, + int32_t index_sub_table_offset, + int32_t first_glyph_index, + int32_t last_glyph_index) { + UNREFERENCED_PARAMETER(data); + UNREFERENCED_PARAMETER(index_sub_table_offset); + UNREFERENCED_PARAMETER(first_glyph_index); + UNREFERENCED_PARAMETER(last_glyph_index); + return EblcTable::Offset::kIndexSubTable2Length; +} + +/****************************************************************************** + * IndexSubTableFormat2::Builder::BitmapGlyphInfoIterator class + ******************************************************************************/ +IndexSubTableFormat2::Builder::BitmapGlyphInfoIterator::BitmapGlyphInfoIterator( + IndexSubTableFormat2::Builder* container) + : RefIterator(container) { + glyph_id_ = container->first_glyph_index(); +} + +bool IndexSubTableFormat2::Builder::BitmapGlyphInfoIterator::HasNext() { + if (glyph_id_ <= container()->last_glyph_index()) { + return true; + } + return false; +} + +CALLER_ATTACH BitmapGlyphInfo* +IndexSubTableFormat2::Builder::BitmapGlyphInfoIterator::Next() { + BitmapGlyphInfoPtr output; + if (!HasNext()) { + // Note: In C++, we do not throw exception when there's no element. + return NULL; + } + output = new BitmapGlyphInfo(glyph_id_, + container()->image_data_offset(), + container()->GlyphStartOffset(glyph_id_), + container()->GlyphLength(glyph_id_), + container()->image_format()); + glyph_id_++; + return output.Detach(); +} + +} // namespace sfntly diff --git a/src/sfntly/src/sfntly/table/bitmap/index_sub_table_format2.h b/src/sfntly/src/sfntly/table/bitmap/index_sub_table_format2.h new file mode 100644 index 000000000000..784e8a39fea1 --- /dev/null +++ b/src/sfntly/src/sfntly/table/bitmap/index_sub_table_format2.h @@ -0,0 +1,106 @@ +/* + * 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. + */ + +#ifndef SFNTLY_CPP_SRC_SFNTLY_TABLE_BITMAP_INDEX_SUBTABLE_FORMAT2_H_ +#define SFNTLY_CPP_SRC_SFNTLY_TABLE_BITMAP_INDEX_SUBTABLE_FORMAT2_H_ + +#include "sfntly/table/bitmap/index_sub_table.h" +#include "sfntly/table/bitmap/big_glyph_metrics.h" + +namespace sfntly { +// Format 2 Index Subtable Entry. +class IndexSubTableFormat2 : public IndexSubTable, + public RefCounted { + public: + class Builder : public IndexSubTable::Builder, + public RefCounted { + public: + class BitmapGlyphInfoIterator + : public RefIterator { + public: + explicit BitmapGlyphInfoIterator(Builder* container); + virtual ~BitmapGlyphInfoIterator() {} + + virtual bool HasNext(); + CALLER_ATTACH virtual BitmapGlyphInfo* Next(); + + private: + int32_t glyph_id_; + }; + + virtual ~Builder(); + virtual int32_t NumGlyphs(); + virtual int32_t GlyphStartOffset(int32_t glyph_id); + virtual int32_t GlyphLength(int32_t glyph_id); + CALLER_ATTACH virtual BitmapGlyphInfoIterator* GetIterator(); + + virtual CALLER_ATTACH FontDataTable* SubBuildTable(ReadableFontData* data); + virtual void SubDataSet(); + virtual int32_t SubDataSizeToSerialize(); + virtual bool SubReadyToSerialize(); + virtual int32_t SubSerialize(WritableFontData* new_data); + + int32_t ImageSize(); + void SetImageSize(int32_t image_size); + BigGlyphMetrics::Builder* BigMetrics(); + + static CALLER_ATTACH Builder* CreateBuilder(); + static CALLER_ATTACH Builder* CreateBuilder(ReadableFontData* data, + int32_t index_sub_table_offset, + int32_t first_glyph_index, + int32_t last_glyph_index); + static CALLER_ATTACH Builder* CreateBuilder(WritableFontData* data, + int32_t index_sub_table_offset, + int32_t first_glyph_index, + int32_t last_glyph_index); + private: + Builder(); + Builder(WritableFontData* data, + int32_t first_glyph_index, + int32_t last_glyph_index); + Builder(ReadableFontData* data, + int32_t first_glyph_index, + int32_t last_glyph_index); + + static int32_t DataLength(ReadableFontData* data, + int32_t index_sub_table_offset, + int32_t first_glyph_index, + int32_t last_glyph_index); + + BigGlyphMetricsBuilderPtr metrics_; + }; + + virtual ~IndexSubTableFormat2(); + + int32_t ImageSize(); + CALLER_ATTACH BigGlyphMetrics* BigMetrics(); + + virtual int32_t NumGlyphs(); + virtual int32_t GlyphStartOffset(int32_t glyph_id); + virtual int32_t GlyphLength(int32_t glyph_id); + + private: + IndexSubTableFormat2(ReadableFontData* data, int32_t first, int32_t last); + + int32_t image_size_; + friend class Builder; +}; +typedef Ptr IndexSubTableFormat2Ptr; +typedef Ptr IndexSubTableFormat2BuilderPtr; + +} // namespace sfntly + +#endif // SFNTLY_CPP_SRC_SFNTLY_TABLE_BITMAP_INDEX_SUBTABLE_FORMAT1_H_ diff --git a/src/sfntly/src/sfntly/table/bitmap/index_sub_table_format3.cc b/src/sfntly/src/sfntly/table/bitmap/index_sub_table_format3.cc new file mode 100644 index 000000000000..b3e418ff5484 --- /dev/null +++ b/src/sfntly/src/sfntly/table/bitmap/index_sub_table_format3.cc @@ -0,0 +1,295 @@ +/* + * 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. + */ + +#include "sfntly/table/bitmap/index_sub_table_format3.h" + +#include "sfntly/table/bitmap/eblc_table.h" + +namespace sfntly { +/****************************************************************************** + * IndexSubTableFormat3 class + ******************************************************************************/ +IndexSubTableFormat3::~IndexSubTableFormat3() { +} + +int32_t IndexSubTableFormat3::NumGlyphs() { + return last_glyph_index() - first_glyph_index() + 1; +} + +int32_t IndexSubTableFormat3::GlyphStartOffset(int32_t glyph_id) { + int32_t loca = CheckGlyphRange(glyph_id); + if (loca != -1) { + return Loca(loca); + } + return -1; +} + +int32_t IndexSubTableFormat3::GlyphLength(int32_t glyph_id) { + int32_t loca = CheckGlyphRange(glyph_id); + if (loca != -1) { + return Loca(glyph_id + 1) - Loca(glyph_id); + } + return 0; +} + +// static +int32_t IndexSubTableFormat3::GetDataLength(ReadableFontData* data, + int32_t offset, + int32_t first, + int32_t last) { + UNREFERENCED_PARAMETER(data); + UNREFERENCED_PARAMETER(offset); + return (last - first + 1 + 1) * DataSize::kUSHORT; +} + +IndexSubTableFormat3::IndexSubTableFormat3(ReadableFontData* data, + int32_t first_glyph_index, + int32_t last_glyph_index) + : IndexSubTable(data, first_glyph_index, last_glyph_index) { +} + +int32_t IndexSubTableFormat3::Loca(int32_t loca) { + int32_t read_offset = + data_->ReadUShort(EblcTable::Offset::kIndexSubTable3_offsetArray + + loca * DataSize::kUSHORT); + return read_offset; +} + +/****************************************************************************** + * IndexSubTableFormat3::Builder class + ******************************************************************************/ +IndexSubTableFormat3::Builder::~Builder() { +} + +int32_t IndexSubTableFormat3::Builder::NumGlyphs() { + return GetOffsetArray()->size() - 1; +} + +int32_t IndexSubTableFormat3::Builder::GlyphStartOffset(int32_t glyph_id) { + int32_t loca = CheckGlyphRange(glyph_id); + if (loca == -1) { + return -1; + } + return GetOffsetArray()->at(loca); +} + +int32_t IndexSubTableFormat3::Builder::GlyphLength(int32_t glyph_id) { + int32_t loca = CheckGlyphRange(glyph_id); + if (loca == -1) { + return 0; + } + IntegerList* offset_array = GetOffsetArray(); + return offset_array->at(loca + 1) - offset_array->at(loca); +} + +CALLER_ATTACH IndexSubTableFormat3::Builder::BitmapGlyphInfoIterator* + IndexSubTableFormat3::Builder::GetIterator() { + Ptr it = + new IndexSubTableFormat3::Builder::BitmapGlyphInfoIterator(this); + return it.Detach(); +} + +void IndexSubTableFormat3::Builder::Revert() { + offset_array_.clear(); + IndexSubTable::Builder::Revert(); +} + +void IndexSubTableFormat3::Builder::SetOffsetArray( + const IntegerList& offset_array) { + offset_array_.clear(); + offset_array_ = offset_array; + set_model_changed(); +} + +// static +CALLER_ATTACH IndexSubTableFormat3::Builder* +IndexSubTableFormat3::Builder::CreateBuilder() { + IndexSubTableFormat3BuilderPtr output = new IndexSubTableFormat3::Builder(); + return output.Detach(); +} + +// static +CALLER_ATTACH IndexSubTableFormat3::Builder* +IndexSubTableFormat3::Builder::CreateBuilder(ReadableFontData* data, + int32_t index_sub_table_offset, + int32_t first_glyph_index, + int32_t last_glyph_index) { + int32_t length = Builder::DataLength(data, + index_sub_table_offset, + first_glyph_index, + last_glyph_index); + ReadableFontDataPtr new_data; + new_data.Attach(down_cast( + data->Slice(index_sub_table_offset, length))); + IndexSubTableFormat3BuilderPtr output = + new IndexSubTableFormat3::Builder(new_data, + first_glyph_index, + last_glyph_index); + return output.Detach(); +} + +// static +CALLER_ATTACH IndexSubTableFormat3::Builder* +IndexSubTableFormat3::Builder::CreateBuilder(WritableFontData* data, + int32_t index_sub_table_offset, + int32_t first_glyph_index, + int32_t last_glyph_index) { + int32_t length = Builder::DataLength(data, + index_sub_table_offset, + first_glyph_index, + last_glyph_index); + WritableFontDataPtr new_data; + new_data.Attach(down_cast( + data->Slice(index_sub_table_offset, length))); + IndexSubTableFormat3BuilderPtr output = + new IndexSubTableFormat3::Builder(new_data, + first_glyph_index, + last_glyph_index); + return output.Detach(); +} + +CALLER_ATTACH FontDataTable* IndexSubTableFormat3::Builder::SubBuildTable( + ReadableFontData* data) { + IndexSubTableFormat3Ptr output = new IndexSubTableFormat3( + data, first_glyph_index(), last_glyph_index()); + return output.Detach(); +} + +void IndexSubTableFormat3::Builder::SubDataSet() { + Revert(); +} + +int32_t IndexSubTableFormat3::Builder::SubDataSizeToSerialize() { + if (offset_array_.empty()) { + return InternalReadData()->Length(); + } + return EblcTable::Offset::kIndexSubHeaderLength + + offset_array_.size() * DataSize::kULONG; +} + +bool IndexSubTableFormat3::Builder::SubReadyToSerialize() { + if (!offset_array_.empty()) { + return true; + } + return false; +} + +int32_t IndexSubTableFormat3::Builder::SubSerialize( + WritableFontData* new_data) { + int32_t size = SerializeIndexSubHeader(new_data); + if (!model_changed()) { + if (InternalReadData() == NULL) { + return size; + } + ReadableFontDataPtr source; + WritableFontDataPtr target; + source.Attach(down_cast(InternalReadData()->Slice( + EblcTable::Offset::kIndexSubTable3_offsetArray))); + target.Attach(down_cast(new_data->Slice( + EblcTable::Offset::kIndexSubTable3_offsetArray))); + size += source->CopyTo(target); + } else { + for (IntegerList::iterator b = GetOffsetArray()->begin(), + e = GetOffsetArray()->end(); b != e; b++) { + size += new_data->WriteUShort(size, *b); + } + } + return size; +} + +IndexSubTableFormat3::Builder::Builder() + : IndexSubTable::Builder(EblcTable::Offset::kIndexSubTable3_builderDataSize, + IndexSubTable::Format::FORMAT_3) { +} + +IndexSubTableFormat3::Builder::Builder(WritableFontData* data, + int32_t first_glyph_index, + int32_t last_glyph_index) + : IndexSubTable::Builder(data, first_glyph_index, last_glyph_index) { +} + +IndexSubTableFormat3::Builder::Builder(ReadableFontData* data, + int32_t first_glyph_index, + int32_t last_glyph_index) + : IndexSubTable::Builder(data, first_glyph_index, last_glyph_index) { +} + +IntegerList* IndexSubTableFormat3::Builder::GetOffsetArray() { + if (offset_array_.empty()) { + Initialize(InternalReadData()); + set_model_changed(); + } + return &offset_array_; +} + +void IndexSubTableFormat3::Builder::Initialize(ReadableFontData* data) { + offset_array_.clear(); + if (data) { + int32_t num_offsets = (last_glyph_index() - first_glyph_index() + 1) + 1; + for (int32_t i = 0; i < num_offsets; ++i) { + offset_array_.push_back(data->ReadUShort( + EblcTable::Offset::kIndexSubTable3_offsetArray + + i * DataSize::kUSHORT)); + } + } +} + +// static +int32_t IndexSubTableFormat3::Builder::DataLength( + ReadableFontData* data, + int32_t index_sub_table_offset, + int32_t first_glyph_index, + int32_t last_glyph_index) { + UNREFERENCED_PARAMETER(data); + UNREFERENCED_PARAMETER(index_sub_table_offset); + return EblcTable::Offset::kIndexSubHeaderLength + + (last_glyph_index - first_glyph_index + 1 + 1) * DataSize::kUSHORT; +} + +/****************************************************************************** + * IndexSubTableFormat3::Builder::BitmapGlyphInfoIterator class + ******************************************************************************/ +IndexSubTableFormat3::Builder::BitmapGlyphInfoIterator::BitmapGlyphInfoIterator( + IndexSubTableFormat3::Builder* container) + : RefIterator(container) { + glyph_id_ = container->first_glyph_index(); +} + +bool IndexSubTableFormat3::Builder::BitmapGlyphInfoIterator::HasNext() { + if (glyph_id_ <= container()->last_glyph_index()) { + return true; + } + return false; +} + +CALLER_ATTACH BitmapGlyphInfo* +IndexSubTableFormat3::Builder::BitmapGlyphInfoIterator::Next() { + BitmapGlyphInfoPtr output; + if (!HasNext()) { + // Note: In C++, we do not throw exception when there's no element. + return NULL; + } + output = new BitmapGlyphInfo(glyph_id_, + container()->image_data_offset(), + container()->GlyphStartOffset(glyph_id_), + container()->GlyphLength(glyph_id_), + container()->image_format()); + glyph_id_++; + return output.Detach(); +} + +} // namespace sfntly diff --git a/src/sfntly/src/sfntly/table/bitmap/index_sub_table_format3.h b/src/sfntly/src/sfntly/table/bitmap/index_sub_table_format3.h new file mode 100644 index 000000000000..d71f8573cc23 --- /dev/null +++ b/src/sfntly/src/sfntly/table/bitmap/index_sub_table_format3.h @@ -0,0 +1,113 @@ +/* + * 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. + */ + +#ifndef SFNTLY_CPP_SRC_SFNTLY_TABLE_BITMAP_INDEX_SUBTABLE_FORMAT3_H_ +#define SFNTLY_CPP_SRC_SFNTLY_TABLE_BITMAP_INDEX_SUBTABLE_FORMAT3_H_ + +#include "sfntly/table/bitmap/index_sub_table.h" + +namespace sfntly { +// Format 3 Index Subtable Entry. +class IndexSubTableFormat3 : public IndexSubTable, + public RefCounted { + public: + class Builder : public IndexSubTable::Builder, + public RefCounted { + public: + class BitmapGlyphInfoIterator + : public RefIterator { + public: + explicit BitmapGlyphInfoIterator(Builder* container); + virtual ~BitmapGlyphInfoIterator() {} + + virtual bool HasNext(); + CALLER_ATTACH virtual BitmapGlyphInfo* Next(); + + private: + int32_t glyph_id_; + }; + + virtual ~Builder(); + virtual int32_t NumGlyphs(); + virtual int32_t GlyphStartOffset(int32_t glyph_id); + virtual int32_t GlyphLength(int32_t glyph_id); + CALLER_ATTACH virtual BitmapGlyphInfoIterator* GetIterator(); + + virtual CALLER_ATTACH FontDataTable* SubBuildTable(ReadableFontData* data); + virtual void SubDataSet(); + virtual int32_t SubDataSizeToSerialize(); + virtual bool SubReadyToSerialize(); + virtual int32_t SubSerialize(WritableFontData* new_data); + + void SetOffsetArray(const IntegerList& offset_array); + + static CALLER_ATTACH Builder* CreateBuilder(); + static CALLER_ATTACH Builder* CreateBuilder(ReadableFontData* data, + int32_t index_sub_table_offset, + int32_t first_glyph_index, + int32_t last_glyph_index); + static CALLER_ATTACH Builder* CreateBuilder(WritableFontData* data, + int32_t index_sub_table_offset, + int32_t first_glyph_index, + int32_t last_glyph_index); + + protected: + void Revert(); + + private: + Builder(); + Builder(WritableFontData* data, + int32_t first_glyph_index, + int32_t last_glyph_index); + Builder(ReadableFontData* data, + int32_t first_glyph_index, + int32_t last_glyph_index); + IntegerList* GetOffsetArray(); + void Initialize(ReadableFontData* data); + + static int32_t DataLength(ReadableFontData* data, + int32_t index_sub_table_offset, + int32_t first_glyph_index, + int32_t last_glyph_index); + + IntegerList offset_array_; + }; + + virtual ~IndexSubTableFormat3(); + + virtual int32_t NumGlyphs(); + virtual int32_t GlyphStartOffset(int32_t glyph_id); + virtual int32_t GlyphLength(int32_t glyph_id); + + static int32_t GetDataLength(ReadableFontData* data, + int32_t offset, + int32_t first, + int32_t last); + + private: + IndexSubTableFormat3(ReadableFontData* data, + int32_t first_glyph_index, + int32_t last_glyph_index); + int32_t Loca(int32_t loca_index); + + friend class Builder; +}; +typedef Ptr IndexSubTableFormat3Ptr; +typedef Ptr IndexSubTableFormat3BuilderPtr; + +} // namespace sfntly + +#endif // SFNTLY_CPP_SRC_SFNTLY_TABLE_BITMAP_INDEX_SUBTABLE_FORMAT3_H_ diff --git a/src/sfntly/src/sfntly/table/bitmap/index_sub_table_format4.cc b/src/sfntly/src/sfntly/table/bitmap/index_sub_table_format4.cc new file mode 100644 index 000000000000..23f3e4740653 --- /dev/null +++ b/src/sfntly/src/sfntly/table/bitmap/index_sub_table_format4.cc @@ -0,0 +1,381 @@ +/* + * 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. + */ + +#include "sfntly/table/bitmap/index_sub_table_format4.h" + +#include "sfntly/table/bitmap/eblc_table.h" + +namespace sfntly { +/****************************************************************************** + * IndexSubTableFormat4 class + ******************************************************************************/ +IndexSubTableFormat4::~IndexSubTableFormat4() { +} + +int32_t IndexSubTableFormat4::NumGlyphs() { + return IndexSubTableFormat4::NumGlyphs(data_, 0); +} + +int32_t IndexSubTableFormat4::GlyphStartOffset(int32_t glyph_id) { + int32_t loca = CheckGlyphRange(glyph_id); + if (loca == -1) { + return -1; + } + int32_t pair_index = FindCodeOffsetPair(glyph_id); + if (pair_index < 0) { + return -1; + } + return data_->ReadUShort(EblcTable::Offset::kIndexSubTable4_glyphArray + + pair_index * + EblcTable::Offset::kCodeOffsetPairLength + + EblcTable::Offset::kCodeOffsetPair_offset); +} + +int32_t IndexSubTableFormat4::GlyphLength(int32_t glyph_id) { + int32_t loca = CheckGlyphRange(glyph_id); + if (loca == -1) { + return -1; + } + + int32_t pair_index = FindCodeOffsetPair(glyph_id); + if (pair_index < 0) { + return -1; + } + return data_->ReadUShort( + EblcTable::Offset::kIndexSubTable4_glyphArray + + (pair_index + 1) * EblcTable::Offset::kCodeOffsetPairLength + + EblcTable::Offset::kCodeOffsetPair_offset) - + data_->ReadUShort( + EblcTable::Offset::kIndexSubTable4_glyphArray + + (pair_index) * EblcTable::Offset::kCodeOffsetPairLength + + EblcTable::Offset::kCodeOffsetPair_offset); +} + +IndexSubTableFormat4::IndexSubTableFormat4(ReadableFontData* data, + int32_t first, + int32_t last) + : IndexSubTable(data, first, last) { +} + +int32_t IndexSubTableFormat4::FindCodeOffsetPair(int32_t glyph_id) { + return data_->SearchUShort(EblcTable::Offset::kIndexSubTable4_glyphArray, + EblcTable::Offset::kCodeOffsetPairLength, + NumGlyphs(), + glyph_id); +} + +int32_t IndexSubTableFormat4::NumGlyphs(ReadableFontData* data, + int32_t table_offset) { + int32_t num_glyphs = data->ReadULongAsInt(table_offset + + EblcTable::Offset::kIndexSubTable4_numGlyphs); + return num_glyphs; +} + +/****************************************************************************** + * IndexSubTableFormat4::CodeOffsetPair related class + ******************************************************************************/ +IndexSubTableFormat4::CodeOffsetPair::CodeOffsetPair(int32_t glyph_code, + int32_t offset) + : glyph_code_(glyph_code), offset_(offset) { +} + +IndexSubTableFormat4::CodeOffsetPairBuilder::CodeOffsetPairBuilder() + : CodeOffsetPair(0, 0) { +} + +IndexSubTableFormat4::CodeOffsetPairBuilder::CodeOffsetPairBuilder( + int32_t glyph_code, int32_t offset) + : CodeOffsetPair(glyph_code, offset) { +} + +bool IndexSubTableFormat4::CodeOffsetPairGlyphCodeComparator::operator()( + const CodeOffsetPair& lhs, const CodeOffsetPair& rhs) { + return lhs.glyph_code() < rhs.glyph_code(); +} + +/****************************************************************************** + * IndexSubTableFormat4::Builder class + ******************************************************************************/ +IndexSubTableFormat4::Builder::~Builder() { +} + +int32_t IndexSubTableFormat4::Builder::NumGlyphs() { + return GetOffsetArray()->size() - 1; +} + +int32_t IndexSubTableFormat4::Builder::GlyphLength(int32_t glyph_id) { + int32_t loca = CheckGlyphRange(glyph_id); + if (loca == -1) { + return 0; + } + int32_t pair_index = FindCodeOffsetPair(glyph_id); + if (pair_index == -1) { + return 0; + } + return GetOffsetArray()->at(pair_index + 1).offset() - + GetOffsetArray()->at(pair_index).offset(); +} + +int32_t IndexSubTableFormat4::Builder::GlyphStartOffset(int32_t glyph_id) { + int32_t loca = CheckGlyphRange(glyph_id); + if (loca == -1) { + return -1; + } + int32_t pair_index = FindCodeOffsetPair(glyph_id); + if (pair_index == -1) { + return -1; + } + return GetOffsetArray()->at(pair_index).offset(); +} + +CALLER_ATTACH IndexSubTableFormat4::Builder::BitmapGlyphInfoIterator* + IndexSubTableFormat4::Builder::GetIterator() { + Ptr it = + new IndexSubTableFormat4::Builder::BitmapGlyphInfoIterator(this); + return it.Detach(); +} + +// static +CALLER_ATTACH IndexSubTableFormat4::Builder* +IndexSubTableFormat4::Builder::CreateBuilder() { + IndexSubTableFormat4BuilderPtr output = new IndexSubTableFormat4::Builder(); + return output.Detach(); +} + +// static +CALLER_ATTACH IndexSubTableFormat4::Builder* +IndexSubTableFormat4::Builder::CreateBuilder(ReadableFontData* data, + int32_t index_sub_table_offset, + int32_t first_glyph_index, + int32_t last_glyph_index) { + int32_t length = Builder::DataLength(data, + index_sub_table_offset, + first_glyph_index, + last_glyph_index); + ReadableFontDataPtr new_data; + new_data.Attach(down_cast( + data->Slice(index_sub_table_offset, length))); + IndexSubTableFormat4BuilderPtr output = + new IndexSubTableFormat4::Builder(new_data, + first_glyph_index, + last_glyph_index); + return output.Detach(); +} + +// static +CALLER_ATTACH IndexSubTableFormat4::Builder* +IndexSubTableFormat4::Builder::CreateBuilder(WritableFontData* data, + int32_t index_sub_table_offset, + int32_t first_glyph_index, + int32_t last_glyph_index) { + int32_t length = Builder::DataLength(data, + index_sub_table_offset, + first_glyph_index, + last_glyph_index); + WritableFontDataPtr new_data; + new_data.Attach(down_cast( + data->Slice(index_sub_table_offset, length))); + IndexSubTableFormat4BuilderPtr output = + new IndexSubTableFormat4::Builder(new_data, + first_glyph_index, + last_glyph_index); + return output.Detach(); +} + +CALLER_ATTACH FontDataTable* IndexSubTableFormat4::Builder::SubBuildTable( + ReadableFontData* data) { + IndexSubTableFormat4Ptr output = new IndexSubTableFormat4( + data, first_glyph_index(), last_glyph_index()); + return output.Detach(); +} + +void IndexSubTableFormat4::Builder::SubDataSet() { + Revert(); +} + +int32_t IndexSubTableFormat4::Builder::SubDataSizeToSerialize() { + if (offset_pair_array_.empty()) { + return InternalReadData()->Length(); + } + return EblcTable::Offset::kIndexSubHeaderLength + DataSize::kULONG + + GetOffsetArray()->size() * + EblcTable::Offset::kIndexSubTable4_codeOffsetPairLength; +} + +bool IndexSubTableFormat4::Builder::SubReadyToSerialize() { + if (!offset_pair_array_.empty()) { + return true; + } + return false; +} + +int32_t IndexSubTableFormat4::Builder::SubSerialize( + WritableFontData* new_data) { + int32_t size = SerializeIndexSubHeader(new_data); + if (!model_changed()) { + if (InternalReadData() == NULL) { + return size; + } + ReadableFontDataPtr source; + WritableFontDataPtr target; + source.Attach(down_cast(InternalReadData()->Slice( + EblcTable::Offset::kIndexSubTable4_glyphArray))); + target.Attach(down_cast(new_data->Slice( + EblcTable::Offset::kIndexSubTable4_glyphArray))); + size += source->CopyTo(target); + } else { + size += new_data->WriteLong(size, offset_pair_array_.size() - 1); + for (std::vector::iterator + b = GetOffsetArray()->begin(), e = GetOffsetArray()->end(); + b != e; b++) { + size += new_data->WriteUShort(size, b->glyph_code()); + size += new_data->WriteUShort(size, b->offset()); + } + } + return size; +} + +void IndexSubTableFormat4::Builder::Revert() { + offset_pair_array_.clear(); + IndexSubTable::Builder::Revert(); +} + +void IndexSubTableFormat4::Builder::SetOffsetArray( + const std::vector& pair_array) { + offset_pair_array_.clear(); + offset_pair_array_ = pair_array; + set_model_changed(); +} + +IndexSubTableFormat4::Builder::Builder() + : IndexSubTable::Builder(EblcTable::Offset::kIndexSubTable4_builderDataSize, + Format::FORMAT_4) { +} + +IndexSubTableFormat4::Builder::Builder(WritableFontData* data, + int32_t first_glyph_index, + int32_t last_glyph_index) + : IndexSubTable::Builder(data, first_glyph_index, last_glyph_index) { +} + +IndexSubTableFormat4::Builder::Builder(ReadableFontData* data, + int32_t first_glyph_index, + int32_t last_glyph_index) + : IndexSubTable::Builder(data, first_glyph_index, last_glyph_index) { +} + +std::vector* +IndexSubTableFormat4::Builder::GetOffsetArray() { + if (offset_pair_array_.empty()) { + Initialize(InternalReadData()); + set_model_changed(); + } + return &offset_pair_array_; +} + +void IndexSubTableFormat4::Builder::Initialize(ReadableFontData* data) { + offset_pair_array_.clear(); + if (data) { + int32_t num_pairs = IndexSubTableFormat4::NumGlyphs(data, 0) + 1; + int32_t offset = EblcTable::Offset::kIndexSubTable4_glyphArray; + for (int32_t i = 0; i < num_pairs; ++i) { + int32_t glyph_code = data->ReadUShort(offset + + EblcTable::Offset::kIndexSubTable4_codeOffsetPair_glyphCode); + int32_t glyph_offset = data->ReadUShort(offset + + EblcTable::Offset::kIndexSubTable4_codeOffsetPair_offset); + offset += EblcTable::Offset::kIndexSubTable4_codeOffsetPairLength; + CodeOffsetPairBuilder pair_builder(glyph_code, glyph_offset); + offset_pair_array_.push_back(pair_builder); + } + } +} + +int32_t IndexSubTableFormat4::Builder::FindCodeOffsetPair(int32_t glyph_id) { + std::vector* pair_list = GetOffsetArray(); + int32_t location = 0; + int32_t bottom = 0; + int32_t top = pair_list->size(); + while (top != bottom) { + location = (top + bottom) / 2; + CodeOffsetPairBuilder* pair = &(pair_list->at(location)); + if (glyph_id < pair->glyph_code()) { + // location is below current location + top = location; + } else if (glyph_id > pair->glyph_code()) { + // location is above current location + bottom = location + 1; + } else { + return location; + } + } + return -1; +} + +// static +int32_t IndexSubTableFormat4::Builder::DataLength( + ReadableFontData* data, + int32_t index_sub_table_offset, + int32_t first_glyph_index, + int32_t last_glyph_index) { + int32_t num_glyphs = IndexSubTableFormat4::NumGlyphs(data, + index_sub_table_offset); + UNREFERENCED_PARAMETER(first_glyph_index); + UNREFERENCED_PARAMETER(last_glyph_index); + return EblcTable::Offset::kIndexSubTable4_glyphArray + + num_glyphs * EblcTable::Offset::kIndexSubTable4_codeOffsetPair_offset; +} + + +/****************************************************************************** + * IndexSubTableFormat4::Builder::BitmapGlyphInfoIterator class + ******************************************************************************/ +IndexSubTableFormat4::Builder::BitmapGlyphInfoIterator::BitmapGlyphInfoIterator( + IndexSubTableFormat4::Builder* container) + : RefIterator(container), + code_offset_pair_index_(0) { +} + +bool IndexSubTableFormat4::Builder::BitmapGlyphInfoIterator::HasNext() { + if (code_offset_pair_index_ < + (int32_t)(container()->GetOffsetArray()->size() - 1)) { + return true; + } + return false; +} + +CALLER_ATTACH BitmapGlyphInfo* +IndexSubTableFormat4::Builder::BitmapGlyphInfoIterator::Next() { + BitmapGlyphInfoPtr output; + if (!HasNext()) { + // Note: In C++, we do not throw exception when there's no element. + return NULL; + } + std::vector* offset_array = + container()->GetOffsetArray(); + int32_t offset = offset_array->at(code_offset_pair_index_).offset(); + int32_t next_offset = offset_array->at(code_offset_pair_index_ + 1).offset(); + int32_t glyph_code = offset_array->at(code_offset_pair_index_).glyph_code(); + output = new BitmapGlyphInfo(glyph_code, + container()->image_data_offset(), + offset, + next_offset - offset, + container()->image_format()); + code_offset_pair_index_++; + return output.Detach(); +} + +} // namespace sfntly diff --git a/src/sfntly/src/sfntly/table/bitmap/index_sub_table_format4.h b/src/sfntly/src/sfntly/table/bitmap/index_sub_table_format4.h new file mode 100644 index 000000000000..efd540f17813 --- /dev/null +++ b/src/sfntly/src/sfntly/table/bitmap/index_sub_table_format4.h @@ -0,0 +1,135 @@ +/* + * 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. + */ + +#ifndef SFNTLY_CPP_SRC_SFNTLY_TABLE_BITMAP_INDEX_SUBTABLE_FORMAT4_H_ +#define SFNTLY_CPP_SRC_SFNTLY_TABLE_BITMAP_INDEX_SUBTABLE_FORMAT4_H_ + +#include "sfntly/table/bitmap/index_sub_table.h" + +namespace sfntly { + +class IndexSubTableFormat4 : public IndexSubTable, + public RefCounted { + public: + class CodeOffsetPair { + public: + int32_t glyph_code() const { return glyph_code_; } + int32_t offset() const { return offset_; } + + protected: + CodeOffsetPair(int32_t glyph_code, int32_t offset); + + // TODO(arthurhsu): C++ style guide prohibits protected members. + int32_t glyph_code_; + int32_t offset_; + }; + + class CodeOffsetPairBuilder : public CodeOffsetPair { + public: + CodeOffsetPairBuilder(); + CodeOffsetPairBuilder(int32_t glyph_code, int32_t offset); + void set_glyph_code(int32_t v) { glyph_code_ = v; } + void set_offset(int32_t v) { offset_ = v; } + }; + + class CodeOffsetPairGlyphCodeComparator { + public: + bool operator()(const CodeOffsetPair& lhs, const CodeOffsetPair& rhs); + }; + + class Builder : public IndexSubTable::Builder, + public RefCounted { + public: + class BitmapGlyphInfoIterator + : public RefIterator { + public: + explicit BitmapGlyphInfoIterator(Builder* container); + virtual ~BitmapGlyphInfoIterator() {} + + virtual bool HasNext(); + CALLER_ATTACH virtual BitmapGlyphInfo* Next(); + + private: + int32_t code_offset_pair_index_; + }; + + virtual ~Builder(); + virtual int32_t NumGlyphs(); + virtual int32_t GlyphLength(int32_t glyph_id); + virtual int32_t GlyphStartOffset(int32_t glyph_id); + CALLER_ATTACH virtual BitmapGlyphInfoIterator* GetIterator(); + + virtual CALLER_ATTACH FontDataTable* SubBuildTable(ReadableFontData* data); + virtual void SubDataSet(); + virtual int32_t SubDataSizeToSerialize(); + virtual bool SubReadyToSerialize(); + virtual int32_t SubSerialize(WritableFontData* new_data); + + void Revert(); + void SetOffsetArray(const std::vector& pair_array); + + static CALLER_ATTACH Builder* CreateBuilder(); + static CALLER_ATTACH Builder* CreateBuilder(ReadableFontData* data, + int32_t index_sub_table_offset, + int32_t first_glyph_index, + int32_t last_glyph_index); + static CALLER_ATTACH Builder* CreateBuilder(WritableFontData* data, + int32_t index_sub_table_offset, + int32_t first_glyph_index, + int32_t last_glyph_index); + private: + Builder(); + Builder(WritableFontData* data, + int32_t first_glyph_index, + int32_t last_glyph_index); + Builder(ReadableFontData* data, + int32_t first_glyph_index, + int32_t last_glyph_index); + std::vector* GetOffsetArray(); + void Initialize(ReadableFontData* data); + int32_t FindCodeOffsetPair(int32_t glyph_id); + + static int32_t DataLength(ReadableFontData* data, + int32_t index_sub_table_offset, + int32_t first_glyph_index, + int32_t last_glyph_index); + + std::vector offset_pair_array_; + }; + + virtual ~IndexSubTableFormat4(); + + virtual int32_t NumGlyphs(); + virtual int32_t GlyphStartOffset(int32_t glyph_id); + virtual int32_t GlyphLength(int32_t glyph_id); + + private: + IndexSubTableFormat4(ReadableFontData* data, + int32_t first_glyph_index, + int32_t last_glyph_index); + + int32_t FindCodeOffsetPair(int32_t glyph_id); + static int32_t NumGlyphs(ReadableFontData* data, int32_t table_offset); + + friend class Builder; +}; +typedef Ptr IndexSubTableFormat4Ptr; +typedef Ptr IndexSubTableFormat4BuilderPtr; +typedef std::vector + CodeOffsetPairBuilderList; +} // namespace sfntly + +#endif // SFNTLY_CPP_SRC_SFNTLY_TABLE_BITMAP_INDEX_SUBTABLE_FORMAT4_H_ diff --git a/src/sfntly/src/sfntly/table/bitmap/index_sub_table_format5.cc b/src/sfntly/src/sfntly/table/bitmap/index_sub_table_format5.cc new file mode 100644 index 000000000000..b4ab1b8e9e7a --- /dev/null +++ b/src/sfntly/src/sfntly/table/bitmap/index_sub_table_format5.cc @@ -0,0 +1,344 @@ +/* + * 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. + */ + +#include "sfntly/table/bitmap/index_sub_table_format5.h" + +#include + +#include "sfntly/table/bitmap/eblc_table.h" + +namespace sfntly { +/****************************************************************************** + * IndexSubTableFormat5 class + ******************************************************************************/ +IndexSubTableFormat5::~IndexSubTableFormat5() { +} + +int32_t IndexSubTableFormat5::NumGlyphs() { + return NumGlyphs(data_, 0); +} + +int32_t IndexSubTableFormat5::GlyphStartOffset(int32_t glyph_id) { + int32_t check = CheckGlyphRange(glyph_id); + if (check == -1) { + return -1; + } + int32_t loca = ReadFontData()->SearchUShort( + EblcTable::Offset::kIndexSubTable5_glyphArray, + DataSize::kUSHORT, + NumGlyphs(), + glyph_id); + if (loca == -1) { + return loca; + } + return loca * ImageSize(); +} + +int32_t IndexSubTableFormat5::GlyphLength(int32_t glyph_id) { + int32_t check = CheckGlyphRange(glyph_id); + if (check == -1) { + return 0; + } + return image_size_; +} + +int32_t IndexSubTableFormat5::ImageSize() { + return data_->ReadULongAsInt(EblcTable::Offset::kIndexSubTable5_imageSize); +} + +CALLER_ATTACH BigGlyphMetrics* IndexSubTableFormat5::BigMetrics() { + ReadableFontDataPtr data; + data.Attach(down_cast(data_->Slice( + EblcTable::Offset::kIndexSubTable5_bigGlyphMetrics, + BigGlyphMetrics::Offset::kMetricsLength))); + BigGlyphMetricsPtr output = new BigGlyphMetrics(data); + return output.Detach(); +} + +IndexSubTableFormat5::IndexSubTableFormat5(ReadableFontData* data, + int32_t first_glyph_index, + int32_t last_glyph_index) + : IndexSubTable(data, first_glyph_index, last_glyph_index) { + image_size_ = data_->ReadULongAsInt( + EblcTable::Offset::kIndexSubTable5_imageSize); +} + +// static +int32_t IndexSubTableFormat5::NumGlyphs(ReadableFontData* data, + int32_t table_offset) { + int32_t num_glyphs = data->ReadULongAsInt(table_offset + + EblcTable::Offset::kIndexSubTable5_numGlyphs); + return num_glyphs; +} + +/****************************************************************************** + * IndexSubTableFormat5::Builder class + ******************************************************************************/ +IndexSubTableFormat5::Builder::~Builder() { +} + +int32_t IndexSubTableFormat5::Builder::NumGlyphs() { + return GetGlyphArray()->size(); +} + +int32_t IndexSubTableFormat5::Builder::GlyphLength(int32_t glyph_id) { + UNREFERENCED_PARAMETER(glyph_id); + return ImageSize(); +} + +int32_t IndexSubTableFormat5::Builder::GlyphStartOffset(int32_t glyph_id) { + int32_t check = CheckGlyphRange(glyph_id); + if (check == -1) { + return -1; + } + IntegerList* glyph_array = GetGlyphArray(); + IntegerList::iterator it = std::find(glyph_array->begin(), + glyph_array->end(), + glyph_id); + if (it == glyph_array->end()) { + return -1; + } + return (it - glyph_array->begin()) * ImageSize(); +} + +CALLER_ATTACH IndexSubTableFormat5::Builder::BitmapGlyphInfoIterator* + IndexSubTableFormat5::Builder::GetIterator() { + Ptr it = + new IndexSubTableFormat5::Builder::BitmapGlyphInfoIterator(this); + return it.Detach(); +} + +// static +CALLER_ATTACH IndexSubTableFormat5::Builder* +IndexSubTableFormat5::Builder::CreateBuilder() { + IndexSubTableFormat5BuilderPtr output = new IndexSubTableFormat5::Builder(); + return output.Detach(); +} + +// static +CALLER_ATTACH IndexSubTableFormat5::Builder* +IndexSubTableFormat5::Builder::CreateBuilder(ReadableFontData* data, + int32_t index_sub_table_offset, + int32_t first_glyph_index, + int32_t last_glyph_index) { + int32_t length = Builder::DataLength(data, + index_sub_table_offset, + first_glyph_index, + last_glyph_index); + ReadableFontDataPtr new_data; + new_data.Attach(down_cast( + data->Slice(index_sub_table_offset, length))); + IndexSubTableFormat5BuilderPtr output = + new IndexSubTableFormat5::Builder(new_data, + first_glyph_index, + last_glyph_index); + return output.Detach(); +} + +// static +CALLER_ATTACH IndexSubTableFormat5::Builder* +IndexSubTableFormat5::Builder::CreateBuilder(WritableFontData* data, + int32_t index_sub_table_offset, + int32_t first_glyph_index, + int32_t last_glyph_index) { + int32_t length = Builder::DataLength(data, + index_sub_table_offset, + first_glyph_index, + last_glyph_index); + WritableFontDataPtr new_data; + new_data.Attach(down_cast( + data->Slice(index_sub_table_offset, length))); + IndexSubTableFormat5BuilderPtr output = + new IndexSubTableFormat5::Builder(new_data, + first_glyph_index, + last_glyph_index); + return output.Detach(); +} + +CALLER_ATTACH FontDataTable* IndexSubTableFormat5::Builder::SubBuildTable( + ReadableFontData* data) { + IndexSubTableFormat5Ptr output = new IndexSubTableFormat5( + data, first_glyph_index(), last_glyph_index()); + return output.Detach(); +} + +void IndexSubTableFormat5::Builder::SubDataSet() { + Revert(); +} + +int32_t IndexSubTableFormat5::Builder::SubDataSizeToSerialize() { + if (glyph_array_.empty()) { + return InternalReadData()->Length(); + } + return EblcTable::Offset::kIndexSubTable5_builderDataSize + + glyph_array_.size() * DataSize::kUSHORT; +} + +bool IndexSubTableFormat5::Builder::SubReadyToSerialize() { + if (!glyph_array_.empty()) { + return true; + } + return false; +} + +int32_t IndexSubTableFormat5::Builder::SubSerialize( + WritableFontData* new_data) { + int32_t size = SerializeIndexSubHeader(new_data); + if (!model_changed()) { + ReadableFontDataPtr source; + WritableFontDataPtr target; + source.Attach(down_cast(InternalReadData()->Slice( + EblcTable::Offset::kIndexSubTable5_imageSize))); + target.Attach(down_cast(new_data->Slice( + EblcTable::Offset::kIndexSubTable5_imageSize))); + size += source->CopyTo(target); + } else { + size += new_data->WriteULong(EblcTable::Offset::kIndexSubTable5_imageSize, + ImageSize()); + WritableFontDataPtr slice; + slice.Attach(down_cast(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(); + b != e; b++) { + size += new_data->WriteUShort(size, *b); + } + } + return size; +} + +int32_t IndexSubTableFormat5::Builder::ImageSize() { + return InternalReadData()->ReadULongAsInt( + EblcTable::Offset::kIndexSubTable5_imageSize); +} + +void IndexSubTableFormat5::Builder::SetImageSize(int32_t image_size) { + InternalWriteData()->WriteULong( + EblcTable::Offset::kIndexSubTable5_imageSize, image_size); +} + +BigGlyphMetrics::Builder* IndexSubTableFormat5::Builder::BigMetrics() { + if (metrics_ == NULL) { + WritableFontDataPtr data; + data.Attach(down_cast(InternalWriteData()->Slice( + EblcTable::Offset::kIndexSubTable5_bigGlyphMetrics, + BigGlyphMetrics::Offset::kMetricsLength))); + metrics_ = new BigGlyphMetrics::Builder(data); + set_model_changed(); + } + return metrics_; +} + +IntegerList* IndexSubTableFormat5::Builder::GlyphArray() { + return GetGlyphArray(); +} + +void IndexSubTableFormat5::Builder::SetGlyphArray(const IntegerList& v) { + glyph_array_.clear(); + glyph_array_ = v; + set_model_changed(); +} + +void IndexSubTableFormat5::Builder::Revert() { + glyph_array_.clear(); + IndexSubTable::Builder::Revert(); +} + +IndexSubTableFormat5::Builder::Builder() + : IndexSubTable::Builder(EblcTable::Offset::kIndexSubTable5_builderDataSize, + IndexSubTable::Format::FORMAT_5) { +} + +IndexSubTableFormat5::Builder::Builder(WritableFontData* data, + int32_t first_glyph_index, + int32_t last_glyph_index) + : IndexSubTable::Builder(data, first_glyph_index, last_glyph_index) { +} + +IndexSubTableFormat5::Builder::Builder(ReadableFontData* data, + int32_t first_glyph_index, + int32_t last_glyph_index) + : IndexSubTable::Builder(data, first_glyph_index, last_glyph_index) { +} + +IntegerList* IndexSubTableFormat5::Builder::GetGlyphArray() { + if (glyph_array_.empty()) { + Initialize(InternalReadData()); + set_model_changed(); + } + return &glyph_array_; +} + +void IndexSubTableFormat5::Builder::Initialize(ReadableFontData* data) { + glyph_array_.clear(); + if (data) { + int32_t num_glyphs = IndexSubTableFormat5::NumGlyphs(data, 0); + for (int32_t i = 0; i < num_glyphs; ++i) { + glyph_array_.push_back(data->ReadUShort( + EblcTable::Offset::kIndexSubTable5_glyphArray + + i * DataSize::kUSHORT)); + } + } +} + +// static +int32_t IndexSubTableFormat5::Builder::DataLength( + ReadableFontData* data, + int32_t index_sub_table_offset, + int32_t first_glyph_index, + int32_t last_glyph_index) { + int32_t num_glyphs = IndexSubTableFormat5::NumGlyphs(data, + index_sub_table_offset); + UNREFERENCED_PARAMETER(first_glyph_index); + UNREFERENCED_PARAMETER(last_glyph_index); + return EblcTable::Offset::kIndexSubTable5_glyphArray + + num_glyphs * DataSize::kUSHORT; +} + +/****************************************************************************** + * IndexSubTableFormat5::Builder::BitmapGlyphInfoIterator class + ******************************************************************************/ +IndexSubTableFormat5::Builder::BitmapGlyphInfoIterator::BitmapGlyphInfoIterator( + IndexSubTableFormat5::Builder* container) + : RefIterator(container), + offset_index_(0) { +} + +bool IndexSubTableFormat5::Builder::BitmapGlyphInfoIterator::HasNext() { + if (offset_index_ < (int32_t)(container()->GetGlyphArray()->size())) { + return true; + } + return false; +} + +CALLER_ATTACH BitmapGlyphInfo* +IndexSubTableFormat5::Builder::BitmapGlyphInfoIterator::Next() { + BitmapGlyphInfoPtr output; + if (!HasNext()) { + // Note: In C++, we do not throw exception when there's no element. + return NULL; + } + output = new BitmapGlyphInfo(container()->GetGlyphArray()->at(offset_index_), + container()->image_data_offset(), + offset_index_ * container()->ImageSize(), + container()->ImageSize(), + container()->image_format()); + offset_index_++; + return output.Detach(); +} + +} // namespace sfntly diff --git a/src/sfntly/src/sfntly/table/bitmap/index_sub_table_format5.h b/src/sfntly/src/sfntly/table/bitmap/index_sub_table_format5.h new file mode 100644 index 000000000000..a39e88cacaae --- /dev/null +++ b/src/sfntly/src/sfntly/table/bitmap/index_sub_table_format5.h @@ -0,0 +1,118 @@ +/* + * 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. + */ + +#ifndef SFNTLY_CPP_SRC_SFNTLY_TABLE_BITMAP_INDEX_SUBTABLE_FORMAT5_H_ +#define SFNTLY_CPP_SRC_SFNTLY_TABLE_BITMAP_INDEX_SUBTABLE_FORMAT5_H_ + +#include "sfntly/table/bitmap/big_glyph_metrics.h" +#include "sfntly/table/bitmap/index_sub_table.h" + +namespace sfntly { + +class IndexSubTableFormat5 : public IndexSubTable, + public RefCounted { + public: + class Builder : public IndexSubTable::Builder, + public RefCounted { + public: + class BitmapGlyphInfoIterator + : public RefIterator { + public: + explicit BitmapGlyphInfoIterator(Builder* container); + virtual ~BitmapGlyphInfoIterator() {} + + virtual bool HasNext(); + CALLER_ATTACH virtual BitmapGlyphInfo* Next(); + + private: + int32_t offset_index_; + }; + virtual ~Builder(); + virtual int32_t NumGlyphs(); + virtual int32_t GlyphLength(int32_t glyph_id); + virtual int32_t GlyphStartOffset(int32_t glyph_id); + CALLER_ATTACH virtual BitmapGlyphInfoIterator* GetIterator(); + + virtual CALLER_ATTACH FontDataTable* SubBuildTable(ReadableFontData* data); + virtual void SubDataSet(); + virtual int32_t SubDataSizeToSerialize(); + virtual bool SubReadyToSerialize(); + virtual int32_t SubSerialize(WritableFontData* new_data); + + int32_t ImageSize(); + void SetImageSize(int32_t image_size); + BigGlyphMetrics::Builder* BigMetrics(); + IntegerList* GlyphArray(); + void SetGlyphArray(const IntegerList& v); + + static CALLER_ATTACH Builder* CreateBuilder(); + static CALLER_ATTACH Builder* CreateBuilder(ReadableFontData* data, + int32_t index_sub_table_offset, + int32_t first_glyph_index, + int32_t last_glyph_index); + static CALLER_ATTACH Builder* CreateBuilder(WritableFontData* data, + int32_t index_sub_table_offset, + int32_t first_glyph_index, + int32_t last_glyph_index); + protected: + void Revert(); + + private: + Builder(); + Builder(WritableFontData* data, + int32_t first_glyph_index, + int32_t last_glyph_index); + Builder(ReadableFontData* data, + int32_t first_glyph_index, + int32_t last_glyph_index); + + IntegerList* GetGlyphArray(); + void Initialize(ReadableFontData* data); + + static int32_t DataLength(ReadableFontData* data, + int32_t index_sub_table_offset, + int32_t first_glyph_index, + int32_t last_glyph_index); + + IntegerList glyph_array_; + BigGlyphMetricsBuilderPtr metrics_; + }; + virtual ~IndexSubTableFormat5(); + + virtual int32_t NumGlyphs(); + virtual int32_t GlyphStartOffset(int32_t glyph_id); + virtual int32_t GlyphLength(int32_t glyph_id); + + int32_t ImageSize(); + CALLER_ATTACH BigGlyphMetrics* BigMetrics(); + + private: + IndexSubTableFormat5(ReadableFontData* data, + int32_t first_glyph_index, + int32_t last_glyph_index); + + static int32_t NumGlyphs(ReadableFontData* dta, int32_t table_offset); + + int32_t image_size_; + + friend class Builder; +}; +typedef Ptr IndexSubTableFormat5Ptr; +typedef Ptr IndexSubTableFormat5BuilderPtr; + +} // namespace sfntly + +#endif // SFNTLY_CPP_SRC_SFNTLY_TABLE_BITMAP_INDEX_SUBTABLE_FORMAT5_H_ diff --git a/src/sfntly/src/sfntly/table/bitmap/simple_bitmap_glyph.cc b/src/sfntly/src/sfntly/table/bitmap/simple_bitmap_glyph.cc new file mode 100644 index 000000000000..87031a142bed --- /dev/null +++ b/src/sfntly/src/sfntly/table/bitmap/simple_bitmap_glyph.cc @@ -0,0 +1,45 @@ +/* + * 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. + */ + +#include "sfntly/table/bitmap/simple_bitmap_glyph.h" + +namespace sfntly { + +SimpleBitmapGlyph::SimpleBitmapGlyph(ReadableFontData* data, int32_t format) + : BitmapGlyph(data, format) { +} + +SimpleBitmapGlyph::~SimpleBitmapGlyph() { +} + +SimpleBitmapGlyph::Builder::Builder(ReadableFontData* data, int32_t format) + : BitmapGlyph::Builder(data, format) { +} + +SimpleBitmapGlyph::Builder::Builder(WritableFontData* data, int32_t format) + : BitmapGlyph::Builder(data, format) { +} + +SimpleBitmapGlyph::Builder::~Builder() { +} + +CALLER_ATTACH FontDataTable* +SimpleBitmapGlyph::Builder::SubBuildTable(ReadableFontData* data) { + Ptr glyph = new SimpleBitmapGlyph(data, format()); + return glyph.Detach(); +} + +} // namespace sfntly diff --git a/src/sfntly/src/sfntly/table/bitmap/simple_bitmap_glyph.h b/src/sfntly/src/sfntly/table/bitmap/simple_bitmap_glyph.h new file mode 100644 index 000000000000..56ede10538be --- /dev/null +++ b/src/sfntly/src/sfntly/table/bitmap/simple_bitmap_glyph.h @@ -0,0 +1,44 @@ +/* + * 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. + */ + +#ifndef SFNTLY_CPP_SRC_SFNTLY_TABLE_BITMAP_SIMPLE_BITMAP_GLYPH_H_ +#define SFNTLY_CPP_SRC_SFNTLY_TABLE_BITMAP_SIMPLE_BITMAP_GLYPH_H_ + +#include "sfntly/table/bitmap/bitmap_glyph.h" + +namespace sfntly { + +class SimpleBitmapGlyph : public BitmapGlyph, + public RefCounted { + public: + class Builder : public BitmapGlyph::Builder, + public RefCounted { + public: + Builder(WritableFontData* data, int32_t format); + Builder(ReadableFontData* data, int32_t format); + virtual ~Builder(); + + virtual CALLER_ATTACH FontDataTable* SubBuildTable(ReadableFontData* data); + }; + + SimpleBitmapGlyph(ReadableFontData* data, int32_t format); + virtual ~SimpleBitmapGlyph(); +}; +typedef Ptr SimpleBitmapGlyphPtr; + +} // namespace sfntly + +#endif // SFNTLY_CPP_SRC_SFNTLY_TABLE_BITMAP_SIMPLE_BITMAP_GLYPH_H_ diff --git a/src/sfntly/src/sfntly/table/bitmap/small_glyph_metrics.cc b/src/sfntly/src/sfntly/table/bitmap/small_glyph_metrics.cc new file mode 100644 index 000000000000..0f3c1e91d632 --- /dev/null +++ b/src/sfntly/src/sfntly/table/bitmap/small_glyph_metrics.cc @@ -0,0 +1,126 @@ +/* + * 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. + */ + +#include "sfntly/table/bitmap/small_glyph_metrics.h" + +namespace sfntly { +/****************************************************************************** + * SmallGlyphMetrics class + ******************************************************************************/ +SmallGlyphMetrics::SmallGlyphMetrics(ReadableFontData* data) + : GlyphMetrics(data) { +} + +SmallGlyphMetrics::~SmallGlyphMetrics() { +} + +int32_t SmallGlyphMetrics::Height() { + return data_->ReadByte(Offset::kHeight); +} + +int32_t SmallGlyphMetrics::Width() { + return data_->ReadByte(Offset::kWidth); +} + +int32_t SmallGlyphMetrics::BearingX() { + return data_->ReadByte(Offset::kBearingX); +} + +int32_t SmallGlyphMetrics::BearingY() { + return data_->ReadByte(Offset::kBearingY); +} + +int32_t SmallGlyphMetrics::Advance() { + return data_->ReadByte(Offset::kAdvance); +} + +/****************************************************************************** + * SmallGlyphMetrics::Builder class + ******************************************************************************/ +SmallGlyphMetrics::Builder::Builder(WritableFontData* data) + : GlyphMetrics::Builder(data) { +} + +SmallGlyphMetrics::Builder::Builder(ReadableFontData* data) + : GlyphMetrics::Builder(data) { +} + +SmallGlyphMetrics::Builder::~Builder() { +} + +int32_t SmallGlyphMetrics::Builder::Height() { + return InternalReadData()->ReadByte(Offset::kHeight); +} + +void SmallGlyphMetrics::Builder::SetHeight(byte_t height) { + InternalWriteData()->WriteByte(Offset::kHeight, height); +} + +int32_t SmallGlyphMetrics::Builder::Width() { + return InternalReadData()->ReadByte(Offset::kWidth); +} + +void SmallGlyphMetrics::Builder::SetWidth(byte_t width) { + InternalWriteData()->WriteByte(Offset::kWidth, width); +} + +int32_t SmallGlyphMetrics::Builder::BearingX() { + return InternalReadData()->ReadByte(Offset::kBearingX); +} + +void SmallGlyphMetrics::Builder::SetBearingX(byte_t bearing) { + InternalWriteData()->WriteByte(Offset::kBearingX, bearing); +} + +int32_t SmallGlyphMetrics::Builder::BearingY() { + return InternalReadData()->ReadByte(Offset::kBearingY); +} + +void SmallGlyphMetrics::Builder::SetBearingY(byte_t bearing) { + InternalWriteData()->WriteByte(Offset::kBearingY, bearing); +} + +int32_t SmallGlyphMetrics::Builder::Advance() { + return InternalReadData()->ReadByte(Offset::kAdvance); +} + +void SmallGlyphMetrics::Builder::SetAdvance(byte_t advance) { + InternalWriteData()->WriteByte(Offset::kAdvance, advance); +} + +CALLER_ATTACH FontDataTable* + SmallGlyphMetrics::Builder::SubBuildTable(ReadableFontData* data) { + SmallGlyphMetricsPtr output = new SmallGlyphMetrics(data); + return output.Detach(); +} + +void SmallGlyphMetrics::Builder::SubDataSet() { + // NOP. +} + +int32_t SmallGlyphMetrics::Builder::SubDataSizeToSerialize() { + return 0; +} + +bool SmallGlyphMetrics::Builder::SubReadyToSerialize() { + return false; +} + +int32_t SmallGlyphMetrics::Builder::SubSerialize(WritableFontData* new_data) { + return Data()->CopyTo(new_data); +} + +} // namespace sfntly diff --git a/src/sfntly/src/sfntly/table/bitmap/small_glyph_metrics.h b/src/sfntly/src/sfntly/table/bitmap/small_glyph_metrics.h new file mode 100644 index 000000000000..ea13720d8f2b --- /dev/null +++ b/src/sfntly/src/sfntly/table/bitmap/small_glyph_metrics.h @@ -0,0 +1,79 @@ +/* + * 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. + */ + +#ifndef SFNTLY_CPP_SRC_SFNTLY_TABLE_BITMAP_SMALL_GLYPH_METRICS_H_ +#define SFNTLY_CPP_SRC_SFNTLY_TABLE_BITMAP_SMALL_GLYPH_METRICS_H_ + +#include "sfntly/port/refcount.h" +#include "sfntly/table/bitmap/glyph_metrics.h" + +namespace sfntly { + +class SmallGlyphMetrics : public GlyphMetrics, + public RefCounted { + public: + struct Offset { + enum { + kMetricsLength = 5, + kHeight = 0, + kWidth = 1, + kBearingX = 2, + kBearingY = 3, + kAdvance = 4, + }; + }; + + class Builder : public GlyphMetrics::Builder, + public RefCounted { + public: + // Constructor scope altered to public because C++ does not allow base + // class to instantiate derived class with protected constructors. + explicit Builder(WritableFontData* data); + explicit Builder(ReadableFontData* data); + virtual ~Builder(); + + int32_t Height(); + void SetHeight(byte_t height); + int32_t Width(); + void SetWidth(byte_t width); + int32_t BearingX(); + void SetBearingX(byte_t bearing); + int32_t BearingY(); + void SetBearingY(byte_t bearing); + int32_t Advance(); + void SetAdvance(byte_t advance); + + virtual CALLER_ATTACH FontDataTable* SubBuildTable(ReadableFontData* data); + virtual void SubDataSet(); + virtual int32_t SubDataSizeToSerialize(); + virtual bool SubReadyToSerialize(); + virtual int32_t SubSerialize(WritableFontData* new_data); + }; + + explicit SmallGlyphMetrics(ReadableFontData* data); + virtual ~SmallGlyphMetrics(); + + int32_t Height(); + int32_t Width(); + int32_t BearingX(); + int32_t BearingY(); + int32_t Advance(); +}; +typedef Ptr SmallGlyphMetricsPtr; + +} // namespace sfntly + +#endif // SFNTLY_CPP_SRC_SFNTLY_TABLE_BITMAP_SMALL_GLYPH_METRICS_H_ diff --git a/src/sfntly/src/sfntly/table/byte_array_table_builder.cc b/src/sfntly/src/sfntly/table/byte_array_table_builder.cc new file mode 100644 index 000000000000..631a05fdd68b --- /dev/null +++ b/src/sfntly/src/sfntly/table/byte_array_table_builder.cc @@ -0,0 +1,70 @@ +/* + * 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. + */ + +#include "sfntly/table/byte_array_table_builder.h" + +namespace sfntly { + +ByteArrayTableBuilder::~ByteArrayTableBuilder() {} + +int32_t ByteArrayTableBuilder::ByteValue(int32_t index) { + ReadableFontDataPtr data = InternalReadData(); + if (data == NULL) { +#if !defined (SFNTLY_NO_EXCEPTION) + throw IOException("No font data for the table"); +#endif + return -1; + } + return data->ReadByte(index); +} + +void ByteArrayTableBuilder::SetByteValue(int32_t index, byte_t b) { + WritableFontDataPtr data = InternalWriteData(); + if (data == NULL) { +#if !defined (SFNTLY_NO_EXCEPTION) + throw IOException("No font data for the table"); +#endif + return; + } + data->WriteByte(index, b); +} + +int32_t ByteArrayTableBuilder::ByteCount() { + ReadableFontDataPtr data = InternalReadData(); + if (data == NULL) { +#if !defined (SFNTLY_NO_EXCEPTION) + throw IOException("No font data for the table"); +#endif + return 0; + } + return data->Length(); +} + +ByteArrayTableBuilder::ByteArrayTableBuilder(Header* header, + WritableFontData* data) + : TableBasedTableBuilder(header, data) { +} + +ByteArrayTableBuilder::ByteArrayTableBuilder(Header* header, + ReadableFontData* data) + : TableBasedTableBuilder(header, data) { +} + +ByteArrayTableBuilder::ByteArrayTableBuilder(Header* header) + : TableBasedTableBuilder(header) { +} + +} // namespace sfntly diff --git a/src/sfntly/src/sfntly/table/byte_array_table_builder.h b/src/sfntly/src/sfntly/table/byte_array_table_builder.h new file mode 100644 index 000000000000..42d27a8df007 --- /dev/null +++ b/src/sfntly/src/sfntly/table/byte_array_table_builder.h @@ -0,0 +1,53 @@ +/* + * 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. + */ + +#ifndef SFNTLY_CPP_SRC_SFNTLY_TABLE_BYTE_ARRAY_TABLE_BUILDER_H_ +#define SFNTLY_CPP_SRC_SFNTLY_TABLE_BYTE_ARRAY_TABLE_BUILDER_H_ + +#include "sfntly/table/table_based_table_builder.h" + +namespace sfntly { + +// An abstract builder base for byte array based tables. +class ByteArrayTableBuilder : public TableBasedTableBuilder { + public: + virtual ~ByteArrayTableBuilder(); + + // Get the byte value at the specified index. The index is relative to the + // start of the table. + // @param index index relative to the start of the table + // @return byte value at the given index + virtual int32_t ByteValue(int32_t index); + + // Set the byte value at the specified index. The index is relative to the + // 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); + + // Get the number of bytes set for this table. It may include padding bytes at + // the end. + virtual int32_t ByteCount(); + + protected: + ByteArrayTableBuilder(Header* header, WritableFontData* data); + ByteArrayTableBuilder(Header* header, ReadableFontData* data); + explicit ByteArrayTableBuilder(Header* header); +}; + +} // namespace sfntly + +#endif // SFNTLY_CPP_SRC_SFNTLY_TABLE_BYTE_ARRAY_TABLE_BUILDER_H_ diff --git a/src/sfntly/src/sfntly/table/core/cmap_table.cc b/src/sfntly/src/sfntly/table/core/cmap_table.cc new file mode 100644 index 000000000000..0b4f89a2bd0e --- /dev/null +++ b/src/sfntly/src/sfntly/table/core/cmap_table.cc @@ -0,0 +1,1288 @@ +/* + * 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. + */ + +// type.h needs to be included first because of building issues on Windows +// Type aliases we delcare are defined in other headers and make the build +// fail otherwise. +#include "sfntly/port/type.h" +#include "sfntly/table/core/cmap_table.h" + +#include +#include + +#include + +#include "sfntly/font.h" +#include "sfntly/math/font_math.h" +#include "sfntly/port/endian.h" +#include "sfntly/port/exception_type.h" +#include "sfntly/table/core/name_table.h" + +namespace sfntly { + +const int32_t CMapTable::NOTDEF = 0; + +CMapTable::CMapId CMapTable::WINDOWS_BMP = { + PlatformId::kWindows, + WindowsEncodingId::kUnicodeUCS2 +}; +CMapTable::CMapId CMapTable::WINDOWS_UCS4 = { + PlatformId::kWindows, + WindowsEncodingId::kUnicodeUCS4 +}; +CMapTable::CMapId CMapTable::MAC_ROMAN = { + PlatformId::kWindows, + MacintoshEncodingId::kRoman +}; + +/****************************************************************************** + * CMapTable class + ******************************************************************************/ +CMapTable::CMapTable(Header* header, ReadableFontData* data) + : SubTableContainerTable(header, data) { +} + +CMapTable::~CMapTable() {} + +CALLER_ATTACH CMapTable::CMap* CMapTable::GetCMap(const int32_t index) { + if (index < 0 || index > NumCMaps()) { +#ifndef SFNTLY_NO_EXCEPTION + throw IndexOutOfBoundException("Requested CMap index is out of bounds."); +#else + return NULL; +#endif + } + int32_t platform_id = PlatformId(index); + int32_t encoding_id = EncodingId(index); + CMapId cmap_id = NewCMapId(platform_id, encoding_id); + int32_t offset_ = Offset(index); + Ptr cmap_builder = + (CMap::Builder::GetBuilder(data_, offset_, cmap_id)); + if (!cmap_builder) { +#ifndef SFNTLY_NO_EXCEPTION + throw NoSuchElementException("Cannot find builder for requested CMap."); +#else + return NULL; +#endif + } + return down_cast(cmap_builder->Build()); +} + +CALLER_ATTACH CMapTable::CMap* CMapTable::GetCMap(const int32_t platform_id, + const int32_t encoding_id) { + return GetCMap(NewCMapId(platform_id, encoding_id)); +} + +CALLER_ATTACH CMapTable::CMap* +CMapTable::GetCMap(const CMapTable::CMapId cmap_id) { + CMapIdFilter id_filter(cmap_id); + CMapIterator cmap_iterator(this, &id_filter); + // There can only be one cmap with a particular CMapId + if (cmap_iterator.HasNext()) { + Ptr cmap; + cmap.Attach(cmap_iterator.Next()); + return cmap.Detach(); + } +#ifndef SFNTLY_NO_EXCEPTION + throw NoSuchElementException(); +#else + return NULL; +#endif +} + +int32_t CMapTable::Version() { + return data_->ReadUShort(Offset::kVersion); +} + +int32_t CMapTable::NumCMaps() { + return data_->ReadUShort(Offset::kNumTables); +} + +CMapTable::CMapId CMapTable::GetCMapId(int32_t index) { + return NewCMapId(PlatformId(index), EncodingId(index)); +} + +int32_t CMapTable::PlatformId(int32_t index) { + return data_->ReadUShort(Offset::kEncodingRecordPlatformId + + OffsetForEncodingRecord(index)); +} + +int32_t CMapTable::EncodingId(int32_t index) { + return data_->ReadUShort(Offset::kEncodingRecordEncodingId + + OffsetForEncodingRecord(index)); +} + +int32_t CMapTable::Offset(int32_t index) { + return data_->ReadULongAsInt(Offset::kEncodingRecordOffset + + OffsetForEncodingRecord(index)); +} + +int32_t CMapTable::OffsetForEncodingRecord(int32_t index) { + return Offset::kEncodingRecordStart + index * Offset::kEncodingRecordSize; +} + +CMapTable::CMapId CMapTable::NewCMapId(int32_t platform_id, + int32_t encoding_id) { + CMapId result; + result.platform_id = platform_id; + result.encoding_id = encoding_id; + return result; +} + +CMapTable::CMapId CMapTable::NewCMapId(const CMapId& obj) { + CMapId result; + result.platform_id = obj.platform_id; + result.encoding_id = obj.encoding_id; + return result; +} + +/****************************************************************************** + * CMapTable::CMapIterator class + ******************************************************************************/ +CMapTable::CMapIterator::CMapIterator(CMapTable* table, + const CMapFilter* filter) + : table_index_(0), filter_(filter), table_(table) { +} + +bool CMapTable::CMapIterator::HasNext() { + if (!filter_) { + if (table_index_ < table_->NumCMaps()) { + return true; + } + return false; + } + + for (; table_index_ < table_->NumCMaps(); ++table_index_) { + if (filter_->accept(table_->GetCMapId(table_index_))) { + return true; + } + } + return false; +} + +CALLER_ATTACH CMapTable::CMap* CMapTable::CMapIterator::Next() { + if (!HasNext()) { +#ifndef SFNTLY_NO_EXCEPTION + throw NoSuchElementException(); +#else + return NULL; +#endif + } + CMapPtr next_cmap; + next_cmap.Attach(table_->GetCMap(table_index_++)); + if (next_cmap == NULL) { +#ifndef SFNTLY_NO_EXCEPTION + throw NoSuchElementException("Error during the creation of the CMap"); +#else + return NULL; +#endif + } + return next_cmap.Detach(); +} + +/****************************************************************************** + * CMapTable::CMapId class + ******************************************************************************/ + +/****************************************************************************** + * CMapTable::CMapIdComparator class + ******************************************************************************/ + +bool CMapTable::CMapIdComparator::operator()(const CMapId& lhs, + const CMapId& rhs) const { + return ((lhs.platform_id << 8 | lhs.encoding_id) > + (rhs.platform_id << 8 | rhs.encoding_id)); +} + +/****************************************************************************** + * CMapTable::CMapIdFilter class + ******************************************************************************/ +CMapTable::CMapIdFilter::CMapIdFilter(const CMapId wanted_id) + : wanted_id_(wanted_id), + comparator_(NULL) { +} + +CMapTable::CMapIdFilter::CMapIdFilter(const CMapId wanted_id, + const CMapIdComparator* comparator) + : wanted_id_(wanted_id), + comparator_(comparator) { +} + +bool CMapTable::CMapIdFilter::accept(const CMapId& cmap_id) const { + if (!comparator_) + return wanted_id_ == cmap_id; + return (*comparator_)(wanted_id_, cmap_id); +} + +/****************************************************************************** + * CMapTable::CMap class + ******************************************************************************/ +CMapTable::CMap::CMap(ReadableFontData* data, int32_t format, + const CMapId& cmap_id) + : SubTable(data), format_(format), cmap_id_(cmap_id) { +} + +CMapTable::CMap::~CMap() { +} + +/****************************************************************************** + * CMapTable::CMap::Builder class + ******************************************************************************/ +CMapTable::CMap::Builder::~Builder() { +} + +CALLER_ATTACH CMapTable::CMap::Builder* + CMapTable::CMap::Builder::GetBuilder(ReadableFontData* data, int32_t offset, + const CMapId& cmap_id) { + // NOT IMPLEMENTED: Java enum value validation + int32_t format = data->ReadUShort(offset); + CMapBuilderPtr builder; + switch (format) { + case CMapFormat::kFormat0: + builder.Attach(CMapFormat0::Builder::NewInstance(data, offset, cmap_id)); + break; + case CMapFormat::kFormat2: +#if defined (SFNTLY_DEBUG_CMAP) + fprintf(stderr, "Requesting Format2 builder, but it's unsupported; " + "returning NULL\n"); +#endif + break; + case CMapFormat::kFormat4: + builder.Attach(CMapFormat4::Builder::NewInstance(data, offset, cmap_id)); + break; + default: +#ifdef SFNTLY_DEBUG_CMAP + fprintf(stderr, "Unknown builder format requested\n"); +#endif + break; + } + return builder.Detach(); +} + +CALLER_ATTACH CMapTable::CMap::Builder* +CMapTable::CMap::Builder::GetBuilder(int32_t format, const CMapId& cmap_id) { + Ptr builder; + switch (format) { + case CMapFormat::kFormat0: + builder.Attach(CMapFormat0::Builder::NewInstance(cmap_id)); + break; + case CMapFormat::kFormat2: +#if defined (SFNTLY_DEBUG_CMAP) + fprintf(stderr, "Requesting Format2 builder, but it's unsupported; " + "returning NULL\n"); +#endif + break; + case CMapFormat::kFormat4: + builder.Attach(CMapFormat4::Builder::NewInstance(cmap_id)); + break; + default: +#ifdef SFNTLY_DEBUG_CMAP + fprintf(stderr, "Unknown builder format requested\n"); +#endif + break; + } + return builder.Detach(); +} + +CMapTable::CMap::Builder::Builder(ReadableFontData* data, + int32_t format, + const CMapId& cmap_id) + : SubTable::Builder(data), + format_(format), + cmap_id_(cmap_id), + language_(0) { +} + +CMapTable::CMap::Builder::Builder(WritableFontData* data, + int32_t format, + const CMapId& cmap_id) + : SubTable::Builder(data), + format_(format), + cmap_id_(cmap_id), + language_(0) { +} + +int32_t CMapTable::CMap::Builder::SubSerialize(WritableFontData* new_data) { + return InternalReadData()->CopyTo(new_data); +} + +bool CMapTable::CMap::Builder::SubReadyToSerialize() { + return true; +} + +int32_t CMapTable::CMap::Builder::SubDataSizeToSerialize() { + ReadableFontDataPtr read_data = InternalReadData(); + if (!read_data) + return 0; + return read_data->Length(); +} + +void CMapTable::CMap::Builder::SubDataSet() { + // NOP +} + +/****************************************************************************** + * CMapTable::CMapFormat0 + ******************************************************************************/ +CMapTable::CMapFormat0::~CMapFormat0() { +} + +int32_t CMapTable::CMapFormat0::Language() { + return 0; +} + +int32_t CMapTable::CMapFormat0::GlyphId(int32_t character) { + if (character < 0 || character > 255) { + return CMapTable::NOTDEF; + } + return data_->ReadUByte(character + Offset::kFormat0GlyphIdArray); +} + +CMapTable::CMapFormat0::CMapFormat0(ReadableFontData* data, + const CMapId& cmap_id) + : CMap(data, CMapFormat::kFormat0, cmap_id) { +} + +CMapTable::CMap::CharacterIterator* CMapTable::CMapFormat0::Iterator() { + return new CMapTable::CMapFormat0::CharacterIterator(0, 0xff); +} + + +/****************************************************************************** + * CMapTable::CMapFormat0::CharacterIterator + ******************************************************************************/ +CMapTable::CMapFormat0::CharacterIterator::CharacterIterator(int32_t start, + int32_t end) + : character_(start), + max_character_(end) { +} + +CMapTable::CMapFormat0::CharacterIterator::~CharacterIterator() {} + +bool CMapTable::CMapFormat0::CharacterIterator::HasNext() { + return character_ < max_character_; +} + +int32_t CMapTable::CMapFormat0::CharacterIterator::Next() { + if (HasNext()) + return character_++; +#ifndef SFNTLY_NO_EXCEPTION + throw NoSuchElementException("No more characters to iterate."); +#endif + return -1; +} + +/****************************************************************************** + * CMapTable::CMapFormat0::Builder + ******************************************************************************/ +// static +CALLER_ATTACH CMapTable::CMapFormat0::Builder* +CMapTable::CMapFormat0::Builder::NewInstance(WritableFontData* data, + int32_t offset, + const CMapId& cmap_id) { + WritableFontDataPtr wdata; + if (data) { + wdata.Attach(down_cast( + data->Slice(offset, + data->ReadUShort(offset + Offset::kFormat0Length)))); + } + return new Builder(wdata, CMapFormat::kFormat0, cmap_id); +} + +// static +CALLER_ATTACH CMapTable::CMapFormat0::Builder* +CMapTable::CMapFormat0::Builder::NewInstance(ReadableFontData* data, + int32_t offset, + const CMapId& cmap_id) { + ReadableFontDataPtr rdata; + if (data) { + rdata.Attach(down_cast( + data->Slice(offset, + data->ReadUShort(offset + Offset::kFormat0Length)))); + } + return new Builder(rdata, CMapFormat::kFormat0, cmap_id); +} + +// static +CALLER_ATTACH CMapTable::CMapFormat0::Builder* +CMapTable::CMapFormat0::Builder::NewInstance(const CMapId& cmap_id) { + return new Builder(cmap_id); +} + +// Always call NewInstance instead of the constructor for creating a new builder +// object! This refactoring avoids memory leaks when slicing the font data. +CMapTable::CMapFormat0::Builder::Builder(WritableFontData* data, int32_t offset, + const CMapId& cmap_id) + : CMapTable::CMap::Builder(data, CMapFormat::kFormat0, cmap_id) { + UNREFERENCED_PARAMETER(offset); +} + +CMapTable::CMapFormat0::Builder::Builder( + ReadableFontData* data, + int32_t offset, + const CMapId& cmap_id) + : CMapTable::CMap::Builder(data, CMapFormat::kFormat0, cmap_id) { + UNREFERENCED_PARAMETER(offset); +} + +CMapTable::CMapFormat0::Builder::Builder(const CMapId& cmap_id) + : CMap::Builder(reinterpret_cast(NULL), + CMapFormat::kFormat0, + cmap_id) { +} + +CMapTable::CMapFormat0::Builder::~Builder() { +} + +CALLER_ATTACH FontDataTable* + CMapTable::CMapFormat0::Builder::SubBuildTable(ReadableFontData* data) { + FontDataTablePtr table = new CMapFormat0(data, cmap_id()); + return table.Detach(); +} + +/****************************************************************************** + * CMapTable::CMapFormat2 + ******************************************************************************/ +CMapTable::CMapFormat2::~CMapFormat2() { +} + +int32_t CMapTable::CMapFormat2::Language() { + return 0; +} + +int32_t CMapTable::CMapFormat2::GlyphId(int32_t character) { + if (character > 0xffff) { + return CMapTable::NOTDEF; + } + + uint32_t c = ToBE32(character); + byte_t high_byte = (c >> 8) & 0xff; + byte_t low_byte = c & 0xff; + int32_t offset = SubHeaderOffset(high_byte); + + if (offset == 0) { + low_byte = high_byte; + high_byte = 0; + } + + int32_t first_code = FirstCode(high_byte); + int32_t entry_count = EntryCount(high_byte); + + if (low_byte < first_code || low_byte >= first_code + entry_count) { + return CMapTable::NOTDEF; + } + + int32_t id_range_offset = IdRangeOffset(high_byte); + + // position of idRangeOffset + value of idRangeOffset + index for low byte + // = firstcode + int32_t p_location = (offset + Offset::kFormat2SubHeader_idRangeOffset) + + id_range_offset + + (low_byte - first_code) * DataSize::kUSHORT; + int p = data_->ReadUShort(p_location); + if (p == 0) { + return CMapTable::NOTDEF; + } + + if (offset == 0) { + return p; + } + int id_delta = IdDelta(high_byte); + return (p + id_delta) % 65536; +} + +int32_t CMapTable::CMapFormat2::BytesConsumed(int32_t character) { + uint32_t c = ToBE32(character); + int32_t high_byte = (c >> 8) & 0xff; + int32_t offset = SubHeaderOffset(high_byte); + return (offset == 0) ? 1 : 2; +} + +CMapTable::CMapFormat2::CMapFormat2(ReadableFontData* data, + const CMapId& cmap_id) + : CMap(data, CMapFormat::kFormat2, cmap_id) { +} + +int32_t CMapTable::CMapFormat2::SubHeaderOffset(int32_t sub_header_index) { + return data_->ReadUShort(Offset::kFormat2SubHeaderKeys + + sub_header_index * DataSize::kUSHORT); +} + +int32_t CMapTable::CMapFormat2::FirstCode(int32_t sub_header_index) { + int32_t sub_header_offset = SubHeaderOffset(sub_header_index); + return data_->ReadUShort(sub_header_offset + + Offset::kFormat2SubHeaderKeys + + Offset::kFormat2SubHeader_firstCode); +} + +int32_t CMapTable::CMapFormat2::EntryCount(int32_t sub_header_index) { + int32_t sub_header_offset = SubHeaderOffset(sub_header_index); + return data_->ReadUShort(sub_header_offset + + Offset::kFormat2SubHeaderKeys + + Offset::kFormat2SubHeader_entryCount); +} + +int32_t CMapTable::CMapFormat2::IdRangeOffset(int32_t sub_header_index) { + int32_t sub_header_offset = SubHeaderOffset(sub_header_index); + return data_->ReadUShort(sub_header_offset + + Offset::kFormat2SubHeaderKeys + + Offset::kFormat2SubHeader_idRangeOffset); +} + +int32_t CMapTable::CMapFormat2::IdDelta(int32_t sub_header_index) { + int32_t sub_header_offset = SubHeaderOffset(sub_header_index); + return data_->ReadUShort(sub_header_offset + + Offset::kFormat2SubHeaderKeys + + Offset::kFormat2SubHeader_idDelta); +} + +CMapTable::CMap::CharacterIterator* CMapTable::CMapFormat2::Iterator() { + // UNIMPLEMENTED + return NULL; +} + +/****************************************************************************** + * CMapTable::CMapFormat2::Builder + ******************************************************************************/ +CMapTable::CMapFormat2::Builder::Builder(WritableFontData* data, + int32_t offset, + const CMapId& cmap_id) + : CMapTable::CMap::Builder(data ? down_cast( + data->Slice(offset, data->ReadUShort( + offset + Offset::kFormat0Length))) + : reinterpret_cast(NULL), + CMapFormat::kFormat2, cmap_id) { + // TODO(arthurhsu): FIXIT: heavy lifting and leak, need fix. +} + +CMapTable::CMapFormat2::Builder::Builder(ReadableFontData* data, + int32_t offset, + const CMapId& cmap_id) + : CMapTable::CMap::Builder(data ? down_cast( + data->Slice(offset, data->ReadUShort( + offset + Offset::kFormat0Length))) + : reinterpret_cast(NULL), + CMapFormat::kFormat2, cmap_id) { + // TODO(arthurhsu): FIXIT: heavy lifting and leak, need fix. +} + +CMapTable::CMapFormat2::Builder::~Builder() { +} + +CALLER_ATTACH FontDataTable* + CMapTable::CMapFormat2::Builder::SubBuildTable(ReadableFontData* data) { + FontDataTablePtr table = new CMapFormat2(data, cmap_id()); + return table.Detach(); +} + +/****************************************************************************** + * CMapTable::CMapFormat4 + ******************************************************************************/ +CMapTable::CMapFormat4::CMapFormat4(ReadableFontData* data, + const CMapId& cmap_id) + : CMap(data, CMapFormat::kFormat4, cmap_id), + seg_count_(SegCount(data)), + start_code_offset_(StartCodeOffset(seg_count_)), + end_code_offset_(Offset::kFormat4EndCount), + id_delta_offset_(IdDeltaOffset(seg_count_)), + glyph_id_array_offset_(GlyphIdArrayOffset(seg_count_)) { +} + +CMapTable::CMapFormat4::~CMapFormat4() { +} + +int32_t CMapTable::CMapFormat4::GlyphId(int32_t character) { + int32_t segment = data_->SearchUShort(StartCodeOffset(seg_count_), + DataSize::kUSHORT, + Offset::kFormat4EndCount, + DataSize::kUSHORT, + seg_count_, + character); + if (segment == -1) { + return CMapTable::NOTDEF; + } + int32_t start_code = StartCode(segment); + return RetrieveGlyphId(segment, start_code, character); +} + +int32_t CMapTable::CMapFormat4::RetrieveGlyphId(int32_t segment, + int32_t start_code, + int32_t character) { + if (character < start_code) { + return CMapTable::NOTDEF; + } + int32_t id_range_offset = IdRangeOffset(segment); + if (id_range_offset == 0) { + return (character + IdDelta(segment)) % 65536; + } + return data_->ReadUShort(id_range_offset + + IdRangeOffsetLocation(segment) + + 2 * (character - start_code)); +} + +int32_t CMapTable::CMapFormat4::seg_count() { + return seg_count_; +} + +int32_t CMapTable::CMapFormat4::Length() { + return Length(data_); +} + +int32_t CMapTable::CMapFormat4::StartCode(int32_t segment) { + if (!IsValidIndex(segment)) { + return -1; + } + return StartCode(data_.p_, seg_count_, segment); +} + +// static +int32_t CMapTable::CMapFormat4::Language(ReadableFontData* data) { + int32_t language = data->ReadUShort(Offset::kFormat4Language); + return language; +} + +// static +int32_t CMapTable::CMapFormat4::Length(ReadableFontData* data) { + int32_t length = data->ReadUShort(Offset::kFormat4Length); + return length; +} + +// static +int32_t CMapTable::CMapFormat4::SegCount(ReadableFontData* data) { + int32_t seg_count = data->ReadUShort(Offset::kFormat4SegCountX2) / 2; + return seg_count; +} + +// static +int32_t CMapTable::CMapFormat4::StartCode(ReadableFontData* data, + int32_t seg_count, + int32_t index) { + int32_t start_code = data->ReadUShort(StartCodeOffset(seg_count) + + index * DataSize::kUSHORT); + return start_code; +} + +// static +int32_t CMapTable::CMapFormat4::StartCodeOffset(int32_t seg_count) { + int32_t start_code_offset = Offset::kFormat4EndCount + + (seg_count + 1) * DataSize::kUSHORT; + return start_code_offset; +} + +// static +int32_t CMapTable::CMapFormat4::EndCode(ReadableFontData* data, + int32_t seg_count, + int32_t index) { + UNREFERENCED_PARAMETER(seg_count); + int32_t end_code = data->ReadUShort(Offset::kFormat4EndCount + + index * DataSize::kUSHORT); + return end_code; +} + +// static +int32_t CMapTable::CMapFormat4::IdDelta(ReadableFontData* data, + int32_t seg_count, + int32_t index) { + int32_t id_delta = data->ReadUShort(IdDeltaOffset(seg_count) + + index * DataSize::kUSHORT); + return id_delta; +} + +// static +int32_t CMapTable::CMapFormat4::IdDeltaOffset(int32_t seg_count) { + int32_t id_delta_offset = + Offset::kFormat4EndCount + (2 * seg_count + 1) * DataSize::kUSHORT; + return id_delta_offset; +} + +// static +int32_t CMapTable::CMapFormat4::IdRangeOffset(ReadableFontData* data, + int32_t seg_count, + int32_t index) { + int32_t id_range_offset = + data->ReadUShort(IdRangeOffsetOffset(seg_count) + + index * DataSize::kUSHORT); + return id_range_offset; +} + +// static +int32_t CMapTable::CMapFormat4::IdRangeOffsetOffset(int32_t seg_count) { + int32_t id_range_offset_offset = + Offset::kFormat4EndCount + (2 * seg_count + 1) * DataSize::kUSHORT + + seg_count * DataSize::kSHORT; + return id_range_offset_offset; +} + +// static +int32_t CMapTable::CMapFormat4::GlyphIdArrayOffset(int32_t seg_count) { + int32_t glyph_id_array_offset = + Offset::kFormat4EndCount + (3 * seg_count + 1) * DataSize::kUSHORT + + seg_count * DataSize::kSHORT; + return glyph_id_array_offset; +} + +int32_t CMapTable::CMapFormat4::EndCode(int32_t segment) { + if (IsValidIndex(segment)) { + return EndCode(data_, seg_count_, segment); + } +#if defined (SFNTLY_NO_EXCEPTION) + return -1; +#else + throw IllegalArgumentException(); +#endif +} + +bool CMapTable::CMapFormat4::IsValidIndex(int32_t segment) { + if (segment < 0 || segment >= seg_count_) { +#if defined (SFNTLY_NO_EXCEPTION) + return false; +#else + throw IllegalArgumentException(); +#endif + } + return true; +} + +int32_t CMapTable::CMapFormat4::IdDelta(int32_t segment) { + if (IsValidIndex(segment)) + return IdDelta(data_, seg_count_, segment); + return -1; +} + +int32_t CMapTable::CMapFormat4::IdRangeOffset(int32_t segment) { + if (IsValidIndex(segment)) + return data_->ReadUShort(IdRangeOffsetLocation(segment)); + return -1; +} + +int32_t CMapTable::CMapFormat4::IdRangeOffsetLocation(int32_t segment) { + if (IsValidIndex(segment)) + return IdRangeOffsetOffset(seg_count_) + segment * DataSize::kUSHORT; + return -1; +} + +int32_t CMapTable::CMapFormat4::GlyphIdArray(int32_t index) { + return data_->ReadUShort(glyph_id_array_offset_ + index * DataSize::kUSHORT); +} + +int32_t CMapTable::CMapFormat4::Language() { + return Language(data_); +} + + +CMapTable::CMap::CharacterIterator* CMapTable::CMapFormat4::Iterator() { + return new CharacterIterator(this); +} + +/****************************************************************************** + * CMapTable::CMapFormat4::CharacterIterator class + ******************************************************************************/ +CMapTable::CMapFormat4::CharacterIterator::CharacterIterator( + CMapFormat4* parent) + : parent_(parent), + segment_index_(0), + first_char_in_segment_(-1), + last_char_in_segment_(-1), + next_char_(-1), + next_char_set_(false) { +} + +bool CMapTable::CMapFormat4::CharacterIterator::HasNext() { + if (next_char_set_) + return true; + while (segment_index_ < parent_->seg_count_) { + if (first_char_in_segment_ < 0) { + first_char_in_segment_ = parent_->StartCode(segment_index_); + last_char_in_segment_ = parent_->EndCode(segment_index_); + next_char_ = first_char_in_segment_; + next_char_set_ = true; + return true; + } + if (next_char_ < last_char_in_segment_) { + next_char_++; + next_char_set_ = true; + return true; + } + segment_index_++; + first_char_in_segment_ = -1; + } + return false; +} + +int32_t CMapTable::CMapFormat4::CharacterIterator::Next() { + if (!next_char_set_) { + if (!HasNext()) { +#if defined (SFNTLY_NO_EXCEPTION) + return -1; +#else + throw NoSuchElementException("No more characters to iterate."); +#endif + } + } + next_char_set_ = false; + return next_char_; +} + +/****************************************************************************** + * CMapTable::CMapFormat4::Builder::Segment class + ******************************************************************************/ +CMapTable::CMapFormat4::Builder::Segment::Segment() {} + +CMapTable::CMapFormat4::Builder::Segment::Segment(Segment* other) + : start_count_(other->start_count_), + end_count_(other->end_count_), + id_delta_(other->id_delta_), + id_range_offset_(other->id_range_offset_) { +} + +CMapTable::CMapFormat4::Builder::Segment::Segment(int32_t start_count, + int32_t end_count, + int32_t id_delta, + int32_t id_range_offset) + : start_count_(start_count), + end_count_(end_count), + id_delta_(id_delta), + id_range_offset_(id_range_offset) { +} + +CMapTable::CMapFormat4::Builder::Segment::~Segment() {} + +int32_t CMapTable::CMapFormat4::Builder::Segment::start_count() { + return start_count_; +} + +void +CMapTable::CMapFormat4::Builder::Segment::set_start_count(int32_t start_count) { + start_count_ = start_count; +} + +int32_t CMapTable::CMapFormat4::Builder::Segment::end_count() { + return end_count_; +} + +void +CMapTable::CMapFormat4::Builder::Segment::set_end_count(int32_t end_count) { + end_count_ = end_count; +} + +int32_t CMapTable::CMapFormat4::Builder::Segment::id_delta() { + return id_delta_; +} + +void +CMapTable::CMapFormat4::Builder::Segment::set_id_delta(int32_t id_delta) { + id_delta_ = id_delta; +} + +int32_t CMapTable::CMapFormat4::Builder::Segment::id_range_offset() { + return id_range_offset_; +} + +void +CMapTable::CMapFormat4::Builder::Segment:: +set_id_range_offset(int32_t id_range_offset) { + id_range_offset_ = id_range_offset; +} + +// static +CALLER_ATTACH SegmentList* +CMapTable::CMapFormat4::Builder::Segment::DeepCopy(SegmentList* original) { + SegmentList* list = new SegmentList; + for (SegmentList::iterator it = original->begin(), + e = original->end(); it != e; ++it) { + list->push_back(*it); + } + return list; +} + +/****************************************************************************** + * CMapTable::CMapFormat4::Builder class + ******************************************************************************/ +CALLER_ATTACH CMapTable::CMapFormat4::Builder* +CMapTable::CMapFormat4::Builder::NewInstance(ReadableFontData* data, + int32_t offset, + const CMapId& cmap_id) { + ReadableFontDataPtr rdata; + if (data) { + rdata.Attach + (down_cast + (data->Slice(offset, + data->ReadUShort(offset + Offset::kFormat4Length)))); + } + return new Builder(rdata, CMapFormat::kFormat4, cmap_id); +} + +CALLER_ATTACH CMapTable::CMapFormat4::Builder* +CMapTable::CMapFormat4::Builder::NewInstance(WritableFontData* data, + int32_t offset, + const CMapId& cmap_id) { + WritableFontDataPtr wdata; + if (data) { + wdata.Attach + (down_cast + (data->Slice(offset, + data->ReadUShort(offset + Offset::kFormat4Length)))); + } + return new Builder(wdata, CMapFormat::kFormat4, cmap_id); +} + +CALLER_ATTACH CMapTable::CMapFormat4::Builder* +CMapTable::CMapFormat4::Builder::NewInstance(const CMapId& cmap_id) { + return new Builder(cmap_id); +} + +CMapTable::CMapFormat4::Builder::Builder(ReadableFontData* data, int32_t offset, + const CMapId& cmap_id) + : CMap::Builder(data, CMapFormat::kFormat4, cmap_id) { + UNREFERENCED_PARAMETER(offset); +} + +CMapTable::CMapFormat4::Builder::Builder(WritableFontData* data, int32_t offset, + const CMapId& cmap_id) + : CMap::Builder(data, CMapFormat::kFormat4, cmap_id) { + UNREFERENCED_PARAMETER(offset); +} + +CMapTable::CMapFormat4::Builder::Builder(SegmentList* segments, + IntegerList* glyph_id_array, + const CMapId& cmap_id) + : CMap::Builder(reinterpret_cast(NULL), + CMapFormat::kFormat4, cmap_id), + segments_(segments->begin(), segments->end()), + glyph_id_array_(glyph_id_array->begin(), glyph_id_array->end()) { + set_model_changed(); +} + +CMapTable::CMapFormat4::Builder::Builder(const CMapId& cmap_id) + : CMap::Builder(reinterpret_cast(NULL), + CMapFormat::kFormat4, cmap_id) { +} + +CMapTable::CMapFormat4::Builder::~Builder() {} + +void CMapTable::CMapFormat4::Builder::Initialize(ReadableFontData* data) { + if (data == NULL || data->Length() == 0) + return; + + // build segments + int32_t seg_count = CMapFormat4::SegCount(data); + for (int32_t index = 0; index < seg_count; ++index) { + Ptr segment = new Segment; + segment->set_start_count(CMapFormat4::StartCode(data, seg_count, index)); +#if defined SFNTLY_DEBUG_CMAP + fprintf(stderr, "Segment %d; start %d\n", index, segment->start_count()); +#endif + segment->set_end_count(CMapFormat4::EndCode(data, seg_count, index)); + segment->set_id_delta(CMapFormat4::IdDelta(data, seg_count, index)); + segment->set_id_range_offset(CMapFormat4::IdRangeOffset(data, + seg_count, + index)); + segments_.push_back(segment); + } + + // build glyph id array + int32_t glyph_id_array_offset = CMapFormat4::GlyphIdArrayOffset(seg_count); + int32_t glyph_id_array_length = + (CMapFormat4::Length(data) - glyph_id_array_offset) + / DataSize::kUSHORT; + fprintf(stderr, "id array size %d\n", glyph_id_array_length); + for (int32_t i = 0; i < glyph_id_array_length; i += DataSize::kUSHORT) { + glyph_id_array_.push_back(data->ReadUShort(glyph_id_array_offset + i)); + } +} + +SegmentList* CMapTable::CMapFormat4::Builder::segments() { + if (segments_.empty()) { + Initialize(InternalReadData()); + set_model_changed(); + } + return &segments_; +} + +void CMapTable::CMapFormat4::Builder::set_segments(SegmentList* segments) { + segments_.assign(segments->begin(), segments->end()); + set_model_changed(); +} + +IntegerList* CMapTable::CMapFormat4::Builder::glyph_id_array() { + if (glyph_id_array_.empty()) { + Initialize(InternalReadData()); + set_model_changed(); + } + return &glyph_id_array_; +} + +void CMapTable::CMapFormat4::Builder:: +set_glyph_id_array(IntegerList* glyph_id_array) { + glyph_id_array_.assign(glyph_id_array->begin(), glyph_id_array->end()); + set_model_changed(); +} + +CALLER_ATTACH FontDataTable* +CMapTable::CMapFormat4::Builder::SubBuildTable(ReadableFontData* data) { + FontDataTablePtr table = new CMapFormat4(data, cmap_id()); + return table.Detach(); +} + +void CMapTable::CMapFormat4::Builder::SubDataSet() { + segments_.clear(); + glyph_id_array_.clear(); + set_model_changed(); +} + +int32_t CMapTable::CMapFormat4::Builder::SubDataSizeToSerialize() { + if (!model_changed()) { + return CMap::Builder::SubDataSizeToSerialize(); + } + int32_t size = Offset::kFormat4FixedSize + segments_.size() + * (3 * DataSize::kUSHORT + DataSize::kSHORT) + + glyph_id_array_.size() * DataSize::kSHORT; + return size; +} + +bool CMapTable::CMapFormat4::Builder::SubReadyToSerialize() { + if (!model_changed()) { + return CMap::Builder::SubReadyToSerialize(); + } + if (!segments()->empty()) { + return true; + } + return false; +} + +int32_t +CMapTable::CMapFormat4::Builder::SubSerialize(WritableFontData* new_data) { + if (!model_changed()) { + return CMap::Builder::SubSerialize(new_data); + } + int32_t index = 0; + index += new_data->WriteUShort(index, CMapFormat::kFormat4); + index += DataSize::kUSHORT; // length - write this at the end + index += new_data->WriteUShort(index, language()); + + int32_t seg_count = segments_.size(); + index += new_data->WriteUShort(index, seg_count * 2); + int32_t log2_seg_count = FontMath::Log2(seg_count); + int32_t search_range = 1 << (log2_seg_count + 1); + index += new_data->WriteUShort(index, search_range); + int32_t entry_selector = log2_seg_count; + index += new_data->WriteUShort(index, entry_selector); + int32_t range_shift = 2 * seg_count - search_range; + index += new_data->WriteUShort(index, range_shift); + + for (int32_t i = 0; i < seg_count; ++i) { + index += new_data->WriteUShort(index, segments_[i]->end_count()); + } + index += new_data->WriteUShort(index, 0); // reserved ushort + for (int32_t i = 0; i < seg_count; ++i) { +#if defined SFNTLY_DEBUG_CMAP + fprintf(stderr, "Segment %d; start %d\n", i, segments_[i]->start_count()); +#endif + index += new_data->WriteUShort(index, segments_[i]->start_count()); + } + for (int32_t i = 0; i < seg_count; ++i) { + index += new_data->WriteShort(index, segments_[i]->id_delta()); + } + for (int32_t i = 0; i < seg_count; ++i) { + index += new_data->WriteUShort(index, segments_[i]->id_range_offset()); + } + +#if defined SFNTLY_DEBUG_CMAP + fprintf(stderr, "Glyph id array size %lu\n", glyph_id_array_.size()); +#endif + for (size_t i = 0; i < glyph_id_array_.size(); ++i) { + index += new_data->WriteUShort(index, glyph_id_array_[i]); + } + + new_data->WriteUShort(Offset::kFormat4Length, index); + return index; +} + +/****************************************************************************** + * CMapTable::Builder class + ******************************************************************************/ +CMapTable::Builder::Builder(Header* header, WritableFontData* data) + : SubTableContainerTable::Builder(header, data), version_(0) { +} + +CMapTable::Builder::Builder(Header* header, ReadableFontData* data) + : SubTableContainerTable::Builder(header, data), version_(0) { +} + +CMapTable::Builder::~Builder() { +} + +int32_t CMapTable::Builder::SubSerialize(WritableFontData* new_data) { + int32_t size = new_data->WriteUShort(CMapTable::Offset::kVersion, + version_); + size += new_data->WriteUShort(CMapTable::Offset::kNumTables, + GetCMapBuilders()->size()); + + int32_t index_offset = size; + size += GetCMapBuilders()->size() * CMapTable::Offset::kEncodingRecordSize; + for (CMapBuilderMap::iterator it = GetCMapBuilders()->begin(), + e = GetCMapBuilders()->end(); it != e; ++it) { + CMapBuilderPtr b = it->second; + // header entry + index_offset += new_data->WriteUShort(index_offset, b->platform_id()); + index_offset += new_data->WriteUShort(index_offset, b->encoding_id()); + index_offset += new_data->WriteULong(index_offset, size); + + // cmap + FontDataPtr slice; + slice.Attach(new_data->Slice(size)); + size += b->SubSerialize(down_cast(slice.p_)); + } + return size; +} + +bool CMapTable::Builder::SubReadyToSerialize() { + if (GetCMapBuilders()->empty()) + return false; + + // check each table + for (CMapBuilderMap::iterator it = GetCMapBuilders()->begin(), + e = GetCMapBuilders()->end(); it != e; ++it) { + if (!it->second->SubReadyToSerialize()) + return false; + } + return true; +} + +int32_t CMapTable::Builder::SubDataSizeToSerialize() { + if (GetCMapBuilders()->empty()) + return 0; + + bool variable = false; + int32_t size = CMapTable::Offset::kEncodingRecordStart + + GetCMapBuilders()->size() * CMapTable::Offset::kEncodingRecordSize; + + // calculate size of each table + for (CMapBuilderMap::iterator it = GetCMapBuilders()->begin(), + e = GetCMapBuilders()->end(); it != e; ++it) { + int32_t cmap_size = it->second->SubDataSizeToSerialize(); + size += abs(cmap_size); + variable |= cmap_size <= 0; + } + return variable ? -size : size; +} + +void CMapTable::Builder::SubDataSet() { + GetCMapBuilders()->clear(); + Table::Builder::set_model_changed(); +} + +CALLER_ATTACH FontDataTable* + CMapTable::Builder::SubBuildTable(ReadableFontData* data) { + FontDataTablePtr table = new CMapTable(header(), data); + return table.Detach(); +} + +CALLER_ATTACH CMapTable::Builder* + CMapTable::Builder::CreateBuilder(Header* header, + WritableFontData* data) { + Ptr builder; + builder = new CMapTable::Builder(header, data); + return builder.Detach(); +} + +// static +CALLER_ATTACH CMapTable::CMap::Builder* + CMapTable::Builder::CMapBuilder(ReadableFontData* data, int32_t index) { + if (index < 0 || index > NumCMaps(data)) { +#if !defined (SFNTLY_NO_EXCEPTION) + throw IndexOutOfBoundException( + "CMap table is outside of the bounds of the known tables."); +#endif + return NULL; + } + + int32_t platform_id = data->ReadUShort(Offset::kEncodingRecordPlatformId + + OffsetForEncodingRecord(index)); + int32_t encoding_id = data->ReadUShort(Offset::kEncodingRecordEncodingId + + OffsetForEncodingRecord(index)); + int32_t offset = data->ReadULongAsInt(Offset::kEncodingRecordOffset + + OffsetForEncodingRecord(index)); + return CMap::Builder::GetBuilder(data, offset, + NewCMapId(platform_id, encoding_id)); +} + +// static +int32_t CMapTable::Builder::NumCMaps(ReadableFontData* data) { + if (data == NULL) { + return 0; + } + return data->ReadUShort(Offset::kNumTables); +} + +int32_t CMapTable::Builder::NumCMaps() { + return GetCMapBuilders()->size(); +} + +void CMapTable::Builder::Initialize(ReadableFontData* data) { + int32_t num_cmaps = NumCMaps(data); + for (int32_t i = 0; i < num_cmaps; ++i) { + CMapTable::CMap::Builder* cmap_builder = CMapBuilder(data, i); + if (!cmap_builder) + continue; + cmap_builders_[cmap_builder->cmap_id()] = cmap_builder; + } +} + +CMapTable::CMap::Builder* CMapTable::Builder::NewCMapBuilder( + const CMapId& cmap_id, + ReadableFontData* data) { + Ptr wfd; + wfd.Attach(WritableFontData::CreateWritableFontData(data->Size())); + data->CopyTo(wfd.p_); + CMapTable::CMapBuilderPtr builder; + builder.Attach(CMap::Builder::GetBuilder(wfd.p_, 0, cmap_id)); + CMapBuilderMap* cmap_builders = CMapTable::Builder::GetCMapBuilders(); + cmap_builders->insert(std::make_pair(cmap_id, builder.p_)); + return builder.Detach(); +} + +CMapTable::CMap::Builder* +CMapTable::Builder::NewCMapBuilder(int32_t format, const CMapId& cmap_id) { + Ptr cmap_builder; + cmap_builder.Attach(CMap::Builder::GetBuilder(format, cmap_id)); + CMapBuilderMap* cmap_builders = CMapTable::Builder::GetCMapBuilders(); + cmap_builders->insert(std::make_pair(cmap_id, cmap_builder.p_)); + return cmap_builder.Detach(); +} + +CMapTable::CMap::Builder* +CMapTable::Builder::CMapBuilder(const CMapId& cmap_id) { + CMapBuilderMap* cmap_builders = this->GetCMapBuilders(); + CMapBuilderMap::iterator builder = cmap_builders->find(cmap_id); + if (builder != cmap_builders->end()) + return builder->second; +#ifndef SFNTLY_NO_EXCEPTION + throw NoSuchElementException("No builder found for cmap_id"); +#else + return NULL; +#endif +} + +CMapTable::CMapBuilderMap* CMapTable::Builder::GetCMapBuilders() { + if (cmap_builders_.empty()) { + Initialize(InternalReadData()); + set_model_changed(); + } + return &cmap_builders_; +} + +} // namespace sfntly diff --git a/src/sfntly/src/sfntly/table/core/cmap_table.h b/src/sfntly/src/sfntly/table/core/cmap_table.h new file mode 100644 index 000000000000..29ce3e4189b0 --- /dev/null +++ b/src/sfntly/src/sfntly/table/core/cmap_table.h @@ -0,0 +1,711 @@ +/* + * 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. + */ + +#ifndef SFNTLY_CPP_SRC_SFNTLY_TABLE_CORE_CMAP_TABLE_H_ +#define SFNTLY_CPP_SRC_SFNTLY_TABLE_CORE_CMAP_TABLE_H_ + +// type.h needs to be included first because of building issues on Windows +// Type aliases we delcare are defined in other headers and make the build +// fail otherwise. +#include "sfntly/port/type.h" +#include +#include + +#include "sfntly/port/refcount.h" +#include "sfntly/table/subtable.h" +#include "sfntly/table/subtable_container_table.h" + +namespace sfntly { + +// CMap subtable formats +struct CMapFormat { + enum { + kFormat0 = 0, + kFormat2 = 2, + kFormat4 = 4, + kFormat6 = 6, + kFormat8 = 8, + kFormat10 = 10, + kFormat12 = 12, + kFormat13 = 13, + kFormat14 = 14 + }; +}; + +// A CMap table +class CMapTable : public SubTableContainerTable, public RefCounted { +public: + // CMapTable::CMapId + struct CMapId { + int32_t platform_id; + int32_t encoding_id; + bool operator==(const CMapId& obj) const { + return platform_id == obj.platform_id && encoding_id == obj.encoding_id; + } + }; + static CMapId WINDOWS_BMP; + static CMapId WINDOWS_UCS4; + static CMapId MAC_ROMAN; + + // CMapTable::CMapIdComparator + class CMapIdComparator { + public: + bool operator()(const CMapId& lhs, const CMapId& rhs) const; + }; + + // A filter on cmap + // CMapTable::CMapFilter + class CMapFilter { + public: + // Test on whether the cmap is acceptable or not + // @param cmap_id the id of the cmap + // @return true if the cmap is acceptable; false otherwise + virtual bool accept(const CMapId& cmap_id) const = 0; + // Make gcc -Wnon-virtual-dtor happy. + virtual ~CMapFilter() {} + }; + + // Filters CMaps by CMapId to implement CMapTable::get() + // wanted_id is the CMap we'd like to find. + // We compare the current CMap to it either by equality (==) or using a + // comparator. + // CMapTable::CMapIdFilter + class CMapIdFilter : public CMapFilter { + public: + explicit CMapIdFilter(const CMapId wanted_id); + CMapIdFilter(const CMapId wanted_id, + const CMapIdComparator* comparator); + ~CMapIdFilter() {} + virtual bool accept(const CMapId& cmap_id) const; + private: + CMapIdFilter& operator=(const CMapIdFilter& that); + const CMapId wanted_id_; + const CMapIdComparator *comparator_; + }; + + // The abstract base class for all cmaps. + // + // CMap equality is based on the equality of the (@link {@link CMapId} that + // defines the CMap. In the cmap table for a font there can only be one cmap + // with a given cmap id (pair of platform and encoding ids) no matter what the + // type of the cmap is. + // + // The cmap offers CharacterIterator to allow iteration over + // characters that are mapped by the cmap. This iteration mostly returns the + // characters mapped by the cmap. It will return all characters mapped by the + // cmap to anything but .notdef but it may return some that are not + // mapped or are mapped to .notdef. Various cmap tables provide ranges and + // such to describe characters for lookup but without going the full way to + // mapping to the glyph id it isn't always possible to tell if a character + // will end up with a valid glyph id. So, some of the characters returned from + // the Iterator may still end up pointing to the .notdef glyph. However, the + // number of such characters should be small in most cases with well designed + // cmaps. + class Builder; + class CMap : public SubTable { + public: + // CMapTable::CMap::Builder + class Builder : public SubTable::Builder { + public: + virtual ~Builder(); + + CALLER_ATTACH static Builder* + GetBuilder(ReadableFontData* data, + int32_t offset, + const CMapId& cmap_id); + CALLER_ATTACH static Builder* + GetBuilder(int32_t format, + const CMapId& cmap_id); + + // Note: yes, an object is returned on stack since it's small enough. + virtual CMapId cmap_id() { return cmap_id_; } + virtual int32_t platform_id() { return cmap_id_.platform_id; } + virtual int32_t encoding_id() { return cmap_id_.encoding_id; } + virtual int32_t format() { return format_; } + virtual int32_t language() { return language_; } + virtual void set_language(int32_t language) { language_ = language; } + + protected: + Builder(ReadableFontData* data, + int32_t format, + const CMapId& cmap_id); + Builder(WritableFontData* data, + int32_t format, + const CMapId& cmap_id); + + virtual int32_t SubSerialize(WritableFontData* new_data); + virtual bool SubReadyToSerialize(); + virtual int32_t SubDataSizeToSerialize(); + virtual void SubDataSet(); + + private: + int32_t format_; + CMapId cmap_id_; + int32_t language_; + + friend class CMapTable::Builder; + }; + // Abstract CMap character iterator + // The fully qualified name is CMapTable::CMap::CharacterIterator + class CharacterIterator { + public: + virtual ~CharacterIterator() {} + virtual bool HasNext() = 0; + // Returns -1 if there are no more characters to iterate through + // and exceptions are turned off + virtual int32_t Next() = 0; + + protected: + // Use the CMap::Iterator method below instead of directly requesting + // a CharacterIterator. + CharacterIterator() {} + }; + + CMap(ReadableFontData* data, int32_t format, const CMapId& cmap_id); + virtual ~CMap(); + + virtual CMap::CharacterIterator* Iterator() = 0; + + virtual int32_t format() { return format_; } + virtual CMapId cmap_id() { return cmap_id_; } + virtual int32_t platform_id() { return cmap_id_.platform_id; } + virtual int32_t encoding_id() { return cmap_id_.encoding_id; } + + // Get the language of the cmap. + // + // Note on the language field in 'cmap' subtables: The language field must + // be set to zero for all cmap subtables whose platform IDs are other than + // Macintosh (platform ID 1). For cmap subtables whose platform IDs are + // Macintosh, set this field to the Macintosh language ID of the cmap + // subtable plus one, or to zero if the cmap subtable is not + // language-specific. For example, a Mac OS Turkish cmap subtable must set + // this field to 18, since the Macintosh language ID for Turkish is 17. A + // Mac OS Roman cmap subtable must set this field to 0, since Mac OS Roman + // is not a language-specific encoding. + // + // @return the language id + virtual int32_t Language() = 0; + + // Gets the glyph id for the character code provided. + // The character code provided must be in the encoding used by the cmap + // table. + virtual int32_t GlyphId(int32_t character) = 0; + + private: + int32_t format_; + CMapId cmap_id_; + }; + typedef Ptr CMapPtr; + typedef Ptr CMapBuilderPtr; + typedef std::map CMapBuilderMap; + + // A cmap format 0 sub table + class CMapFormat0 : public CMap, public RefCounted { + public: + // The fully qualified name is CMapTable::CMapFormat0::Builder + class Builder : public CMap::Builder, + public RefCounted { + public: + CALLER_ATTACH static Builder* NewInstance(ReadableFontData* data, + int32_t offset, + const CMapId& cmap_id); + CALLER_ATTACH static Builder* NewInstance(WritableFontData* data, + int32_t offset, + const CMapId& cmap_id); + CALLER_ATTACH static Builder* NewInstance(const CMapId& cmap_id); + virtual ~Builder(); + + protected: + virtual CALLER_ATTACH FontDataTable* + SubBuildTable(ReadableFontData* data); + + private: + // When creating a new CMapFormat0 Builder, use NewInstance instead of + // the constructors! This avoids a memory leak when slicing the FontData. + Builder(ReadableFontData* data, int32_t offset, const CMapId& cmap_id); + Builder(WritableFontData* data, int32_t offset, const CMapId& cmap_id); + Builder(const CMapId& cmap_id); + }; + + // The fully qualified name is CMapTable::CMapFormat0::CharacterIterator + class CharacterIterator : public CMap::CharacterIterator { + public: + virtual ~CharacterIterator(); + virtual bool HasNext(); + virtual int32_t Next(); + + private: + CharacterIterator(int32_t start, int32_t end); + friend class CMapFormat0; + int32_t character_, max_character_; + }; + + virtual ~CMapFormat0(); + virtual int32_t Language(); + virtual int32_t GlyphId(int32_t character); + CMap::CharacterIterator* Iterator(); + + private: + CMapFormat0(ReadableFontData* data, const CMapId& cmap_id); + }; + + // A cmap format 2 sub table + // The format 2 cmap is used for multi-byte encodings such as SJIS, + // EUC-JP/KR/CN, Big5, etc. + class CMapFormat2 : public CMap, public RefCounted { + public: + // CMapTable::CMapFormat2::Builder + class Builder : public CMap::Builder, + public RefCounted { + public: + Builder(ReadableFontData* data, + int32_t offset, + const CMapId& cmap_id); + Builder(WritableFontData* data, + int32_t offset, + const CMapId& cmap_id); + virtual ~Builder(); + + protected: + virtual CALLER_ATTACH FontDataTable* + SubBuildTable(ReadableFontData* data); + }; + // CMapTable::CMapFormat2::CharacterIterator + class CharacterIterator : public CMap::CharacterIterator { + public: + virtual ~CharacterIterator(); + virtual bool hasNext(); + virtual int32_t next(); + + private: + CharacterIterator(); + }; + + virtual int32_t Language(); + virtual int32_t GlyphId(int32_t character); + + // Returns how many bytes would be consumed by a lookup of this character + // with this cmap. This comes about because the cmap format 2 table is + // designed around multi-byte encodings such as SJIS, EUC-JP, Big5, etc. + // return the number of bytes consumed from this "character" - either 1 or 2 + virtual int32_t BytesConsumed(int32_t character); + + virtual ~CMapFormat2(); + + private: + CMapFormat2(ReadableFontData* data, const CMapId& cmap_id); + + int32_t SubHeaderOffset(int32_t sub_header_index); + int32_t FirstCode(int32_t sub_header_index); + int32_t EntryCount(int32_t sub_header_index); + int32_t IdRangeOffset(int32_t sub_header_index); + int32_t IdDelta(int32_t sub_header_index); + CMap::CharacterIterator* Iterator(); + }; + + // CMapTable::CMapFormat4 + class CMapFormat4 : public CMap, + public RefCounted { + public: + // CMapTable::CMapFormat4::Builder + class Builder : public CMap::Builder, + public RefCounted { + public: + // CMapTable::CMapFormat4::Builder::Segment + class Segment : public RefCounted { + public: + Segment(); + explicit Segment(Segment* other); + Segment(int32_t start_count, + int32_t end_count, + int32_t id_delta, + int32_t id_range_offset); + ~Segment(); + + // @return the startCount + int32_t start_count(); + // @param startCount the startCount to set + void set_start_count(int32_t start_count); + // @return the endCount + int32_t end_count(); + // @param endcount the endCount to set + void set_end_count(int32_t end_count); + // @return the idDelta + int32_t id_delta(); + // @param idDelta the idDelta to set + void set_id_delta(int32_t id_delta); + // @return the idRangeOffset + int32_t id_range_offset(); + // @param idRangeOffset the idRangeOffset to set + void set_id_range_offset(int32_t id_range_offset); + + static CALLER_ATTACH + std::vector >* + DeepCopy(std::vector >* original); + + private: + int32_t start_count_; + int32_t end_count_; + int32_t id_delta_; + int32_t id_range_offset_; + }; + typedef std::vector > SegmentList; + + static CALLER_ATTACH Builder* NewInstance(WritableFontData* data, + int32_t offset, + const CMapId& cmap_id); + static CALLER_ATTACH Builder* NewInstance(ReadableFontData* data, + int32_t offset, + const CMapId& cmap_id); + static CALLER_ATTACH Builder* NewInstance(const CMapId& cmap_id); + virtual ~Builder(); + SegmentList* segments(); + void set_segments(SegmentList* segments); + IntegerList* glyph_id_array(); + void set_glyph_id_array(IntegerList* 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, + const CMapId& cmap_id); + explicit Builder(const CMapId& cmap_id); + + virtual CALLER_ATTACH FontDataTable* SubBuildTable( + ReadableFontData* data); + virtual void SubDataSet(); + virtual int32_t SubDataSizeToSerialize(); + virtual bool SubReadyToSerialize(); + virtual int32_t SubSerialize(WritableFontData* new_data); + + private: + void Initialize(ReadableFontData* data); + + SegmentList segments_; + IntegerList glyph_id_array_; + }; + + CMap::CharacterIterator* Iterator(); + // CMapTable::CMapFormat4::CharacterIterator + class CharacterIterator : public CMap::CharacterIterator { + public: + bool HasNext(); + int32_t Next(); + virtual ~CharacterIterator() {} + + private: + explicit CharacterIterator(CMapFormat4 *parent); + friend CMap::CharacterIterator* CMapFormat4::Iterator(); + + CMapFormat4* parent_; + int32_t segment_index_; + int32_t first_char_in_segment_; + int32_t last_char_in_segment_; + int32_t next_char_; + bool next_char_set_; + }; + + virtual int32_t GlyphId(int32_t character); + + // Lower level glyph code retrieval that requires processing the Format 4 + // segments to use. + // @param segment the cmap segment + // @param startCode the start code for the segment + // @param character the character to be looked up + // @return the glyph id for the character; CMapTable.NOTDEF if not found + int32_t RetrieveGlyphId(int32_t segment, + int32_t start_count, + int32_t character); + virtual int32_t Language(); + + // Get the count of the number of segments in this cmap. + // @return the number of segments + int32_t seg_count(); + int32_t Length(); + // Get the start code for a segment. + // @param segment the segment in the lookup table + // @return the start code for a segment + int32_t StartCode(int32_t segment); + // Get the end code for a segment. + // @param segment the segment in the look up table + // @return the end code for the segment + int32_t EndCode(int32_t segment); + // Get the id delta for a segment + // @param segment the segment in the look up table + // @return the id delta for the segment + int32_t IdDelta(int32_t segment); + // Get the id range offset for a segment + // @param segment the segment in the look up table + // @return the id range offset for the segment + int32_t IdRangeOffset(int32_t segment); + // Get the location of the id range offset for a segment + // @param segment the segment in the look up table + // @return the location of the id range offset for the segment + int32_t IdRangeOffsetLocation(int32_t segment); + // Declared above to allow friending inside CharacterIterator class. + // CMap::CharacterIterator* Iterator(); + virtual ~CMapFormat4(); + + protected: + CMapFormat4(ReadableFontData* data, const CMapId& cmap_id); + + private: + static int32_t Language(ReadableFontData* data); + static int32_t Length(ReadableFontData* data); + static int32_t SegCount(ReadableFontData* data); + static int32_t StartCode(ReadableFontData* data, + int32_t seg_count, + int32_t index); + static int32_t StartCodeOffset(int32_t seg_count); + static int32_t EndCode(ReadableFontData* data, + int32_t seg_count, + int32_t index); + static int32_t IdDelta(ReadableFontData* data, + int32_t seg_count, + int32_t index); + static int32_t IdDeltaOffset(int32_t seg_count); + static int32_t IdRangeOffset(ReadableFontData* data, + int32_t seg_count, + int32_t index); + static int32_t IdRangeOffsetOffset(int32_t seg_count); + static int32_t GlyphIdArrayOffset(int32_t seg_count); + // Refactored void to bool to work without exceptions. + bool IsValidIndex(int32_t segment); + int32_t GlyphIdArray(int32_t index); + + int32_t seg_count_; + int32_t start_code_offset_; + int32_t end_code_offset_; + int32_t id_delta_offset_; + int32_t id_range_offset_offset_; + int32_t glyph_id_array_offset_; + }; + + // CMapTable::Builder + class Builder : public SubTableContainerTable::Builder, + public RefCounted { + public: + // Constructor scope is public because C++ does not allow base class to + // instantiate derived class with protected constructors. + Builder(Header* header, WritableFontData* data); + Builder(Header* header, ReadableFontData* data); + virtual ~Builder(); + + virtual int32_t SubSerialize(WritableFontData* new_data); + virtual bool SubReadyToSerialize(); + virtual int32_t SubDataSizeToSerialize(); + virtual void SubDataSet(); + virtual CALLER_ATTACH FontDataTable* SubBuildTable(ReadableFontData* data); + + static CALLER_ATTACH Builder* CreateBuilder(Header* header, + WritableFontData* data); + + CMap::Builder* NewCMapBuilder(const CMapId& cmap_id, + ReadableFontData* data); + // Create a new empty CMapBuilder of the type specified in the id. + CMap::Builder* NewCMapBuilder(int32_t format, const CMapId& cmap_id); + CMap::Builder* CMapBuilder(const CMapId& cmap_id); + + int32_t NumCMaps(); + void SetVersion(int32_t version); + + CMapBuilderMap* GetCMapBuilders(); + + protected: + static CALLER_ATTACH CMap::Builder* CMapBuilder(ReadableFontData* data, + int32_t index); + + private: + void Initialize(ReadableFontData* data); + static int32_t NumCMaps(ReadableFontData* data); + + int32_t version_; + CMapBuilderMap cmap_builders_; + }; + typedef Ptr CMapTableBuilderPtr; + + class CMapIterator { + public: + // If filter is NULL, filter through all tables. + CMapIterator(CMapTable* table, const CMapFilter* filter); + bool HasNext(); + CMap* Next(); + + private: + int32_t table_index_; + const CMapFilter* filter_; + CMapTable* table_; + }; + + // Make a CMapId from a platform_id, encoding_id pair + static CMapId NewCMapId(int32_t platform_id, int32_t encoding_id); + // Make a CMapId from another CMapId + static CMapId NewCMapId(const CMapId& obj); + + // Get the CMap with the specified parameters if it exists. + // Returns NULL otherwise. + CALLER_ATTACH CMap* GetCMap(const int32_t index); + CALLER_ATTACH CMap* GetCMap(const int32_t platform_id, + const int32_t encoding_id); + CALLER_ATTACH CMap* GetCMap(const CMapId GetCMap_id); + + // Get the table version. + virtual int32_t Version(); + + // Get the number of cmaps within the CMap table. + virtual int32_t NumCMaps(); + + // Get the cmap id for the cmap with the given index. + // Note: yes, an object is returned on stack since it's small enough. + // This function is renamed from cmapId to GetCMapId(). + virtual CMapId GetCMapId(int32_t index); + + virtual int32_t PlatformId(int32_t index); + virtual int32_t EncodingId(int32_t index); + + // Get the offset in the table data for the cmap table with the given index. + // The offset is from the beginning of the table. + virtual int32_t Offset(int32_t index); + + virtual ~CMapTable(); + + static const int32_t NOTDEF; + + private: + // Offsets to specific elements in the underlying data. These offsets are + // relative to the start of the table or the start of sub-blocks within + // the table. + struct Offset { + enum { + kVersion = 0, + kNumTables = 2, + kEncodingRecordStart = 4, + + // offsets relative to the encoding record + kEncodingRecordPlatformId = 0, + kEncodingRecordEncodingId = 2, + kEncodingRecordOffset = 4, + kEncodingRecordSize = 8, + + kFormat = 0, + + // Format 0: Byte encoding table + kFormat0Format = 0, + kFormat0Length = 2, + kFormat0Language = 4, + kFormat0GlyphIdArray = 6, + + // Format 2: High-byte mapping through table + kFormat2Format = 0, + kFormat2Length = 2, + kFormat2Language = 4, + kFormat2SubHeaderKeys = 6, + kFormat2SubHeaders = 518, + // offset relative to the subHeader structure + kFormat2SubHeader_firstCode = 0, + kFormat2SubHeader_entryCount = 2, + kFormat2SubHeader_idDelta = 4, + kFormat2SubHeader_idRangeOffset = 6, + kFormat2SubHeader_structLength = 8, + + // Format 4: Segment mapping to delta values + kFormat4Format = 0, + kFormat4Length = 2, + kFormat4Language = 4, + kFormat4SegCountX2 = 6, + kFormat4SearchRange = 8, + kFormat4EntrySelector = 10, + kFormat4RangeShift = 12, + kFormat4EndCount = 14, + kFormat4FixedSize = 16, + + // format 6: Trimmed table mapping + kFormat6Format = 0, + kFormat6Length = 2, + kFormat6Language = 4, + kFormat6FirstCode = 6, + kFormat6EntryCount = 8, + kFormat6GlyphIdArray = 10, + + // Format 8: mixed 16-bit and 32-bit coverage + kFormat8Format = 0, + kFormat8Length = 4, + kFormat8Language = 8, + kFormat8Is32 = 12, + kFormat8nGroups204 = 8204, + kFormat8Groups208 = 8208, + // offset relative to the group structure + kFormat8Group_startCharCode = 0, + kFormat8Group_endCharCode = 4, + kFormat8Group_startGlyphId = 8, + kFormat8Group_structLength = 12, + + // Format 10: Trimmed array + kFormat10Format = 0, + kFormat10Length = 4, + kFormat10Language = 8, + kFormat10StartCharCode = 12, + kFormat10NumChars = 16, + kFormat10Glyphs0 = 20, + + // Format 12: Segmented coverage + kFormat12Format = 0, + kFormat12Length = 4, + kFormat12Language = 8, + kFormat12nGroups = 12, + kFormat12Groups = 16, + kFormat12Groups_structLength = 12, + // offsets within the group structure + kFormat12_startCharCode = 0, + kFormat12_endCharCode = 4, + kFormat12_startGlyphId = 8, + + // Format 13: Last Resort Font + kFormat13Format = 0, + kFormat13Length = 4, + kFormat13Language = 8, + kFormat13nGroups = 12, + kFormat13Groups = 16, + kFormat13Groups_structLength = 12, + // offsets within the group structure + kFormat13_startCharCode = 0, + kFormat13_endCharCode = 4, + kFormat13_glyphId = 8, + + // Format 14: Unicode Variation Sequences + kFormat14Format = 0, + kFormat14Length = 2, + + // TODO(stuartg): finish tables + // Default UVS Table + + // Non-default UVS Table + kLast = -1 + }; + }; + + CMapTable(Header* header, ReadableFontData* data); + + // Get the offset in the table data for the encoding record for the cmap with + // the given index. The offset is from the beginning of the table. + static int32_t OffsetForEncodingRecord(int32_t index); +}; +typedef std::vector CMapIdList; +typedef Ptr CMapTablePtr; +typedef std::vector > SegmentList; +} // namespace sfntly + +#endif // SFNTLY_CPP_SRC_SFNTLY_TABLE_CORE_CMAP_TABLE_H_ diff --git a/src/sfntly/src/sfntly/table/core/font_header_table.cc b/src/sfntly/src/sfntly/table/core/font_header_table.cc new file mode 100644 index 000000000000..60015ca9540e --- /dev/null +++ b/src/sfntly/src/sfntly/table/core/font_header_table.cc @@ -0,0 +1,265 @@ +/* + * 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. + */ + +#include "sfntly/table/core/font_header_table.h" + +namespace sfntly { +/****************************************************************************** + * FontHeaderTable class + ******************************************************************************/ +FontHeaderTable::~FontHeaderTable() {} + +int32_t FontHeaderTable::TableVersion() { + return data_->ReadFixed(Offset::kTableVersion); +} + +int32_t FontHeaderTable::FontRevision() { + return data_->ReadFixed(Offset::kFontRevision); +} + +int64_t FontHeaderTable::ChecksumAdjustment() { + return data_->ReadULong(Offset::kCheckSumAdjustment); +} + +int64_t FontHeaderTable::MagicNumber() { + return data_->ReadULong(Offset::kMagicNumber); +} + +int32_t FontHeaderTable::FlagsAsInt() { + return data_->ReadUShort(Offset::kFlags); +} + +int32_t FontHeaderTable::UnitsPerEm() { + return data_->ReadUShort(Offset::kUnitsPerEm); +} + +int64_t FontHeaderTable::Created() { + return data_->ReadDateTimeAsLong(Offset::kCreated); +} + +int64_t FontHeaderTable::Modified() { + return data_->ReadDateTimeAsLong(Offset::kModified); +} + +int32_t FontHeaderTable::XMin() { + return data_->ReadUShort(Offset::kXMin); +} + +int32_t FontHeaderTable::YMin() { + return data_->ReadUShort(Offset::kYMin); +} + +int32_t FontHeaderTable::XMax() { + return data_->ReadUShort(Offset::kXMax); +} + +int32_t FontHeaderTable::YMax() { + return data_->ReadUShort(Offset::kYMax); +} + +int32_t FontHeaderTable::MacStyleAsInt() { + return data_->ReadUShort(Offset::kMacStyle); +} + +int32_t FontHeaderTable::LowestRecPPEM() { + return data_->ReadUShort(Offset::kLowestRecPPEM); +} + +int32_t FontHeaderTable::FontDirectionHint() { + return data_->ReadShort(Offset::kFontDirectionHint); +} + +int32_t FontHeaderTable::IndexToLocFormat() { + return data_->ReadShort(Offset::kIndexToLocFormat); +} + +int32_t FontHeaderTable::GlyphDataFormat() { + return data_->ReadShort(Offset::kGlyphDataFormat); +} + +FontHeaderTable::FontHeaderTable(Header* header, ReadableFontData* data) + : Table(header, data) { + IntegerList checksum_ranges; + checksum_ranges.push_back(0); + checksum_ranges.push_back(Offset::kCheckSumAdjustment); + checksum_ranges.push_back(Offset::kMagicNumber); + data_->SetCheckSumRanges(checksum_ranges); +} + +/****************************************************************************** + * FontHeaderTable::Builder class + ******************************************************************************/ +FontHeaderTable::Builder::Builder(Header* header, WritableFontData* data) + : TableBasedTableBuilder(header, data) { +} + +FontHeaderTable::Builder::Builder(Header* header, ReadableFontData* data) + : TableBasedTableBuilder(header, data) { +} + +FontHeaderTable::Builder::~Builder() {} + +CALLER_ATTACH FontDataTable* FontHeaderTable::Builder::SubBuildTable( + ReadableFontData* data) { + FontDataTablePtr table = new FontHeaderTable(header(), data); + return table.Detach(); +} + +int32_t FontHeaderTable::Builder::TableVersion() { + return down_cast(GetTable())->TableVersion(); +} + +void FontHeaderTable::Builder::SetTableVersion(int32_t version) { + InternalWriteData()->WriteFixed(Offset::kTableVersion, version); +} + +int32_t FontHeaderTable::Builder::FontRevision() { + return down_cast(GetTable())->FontRevision(); +} + +void FontHeaderTable::Builder::SetFontRevision(int32_t revision) { + InternalWriteData()->WriteFixed(Offset::kFontRevision, revision); +} + +int64_t FontHeaderTable::Builder::ChecksumAdjustment() { + return down_cast(GetTable())->ChecksumAdjustment(); +} + +void FontHeaderTable::Builder::SetChecksumAdjustment(int64_t adjustment) { + InternalWriteData()->WriteULong(Offset::kCheckSumAdjustment, adjustment); +} + +int64_t FontHeaderTable::Builder::MagicNumber() { + return down_cast(GetTable())->MagicNumber(); +} + +void FontHeaderTable::Builder::SetMagicNumber(int64_t magic_number) { + InternalWriteData()->WriteULong(Offset::kMagicNumber, magic_number); +} + +int32_t FontHeaderTable::Builder::FlagsAsInt() { + return down_cast(GetTable())->FlagsAsInt(); +} + +void FontHeaderTable::Builder::SetFlagsAsInt(int32_t flags) { + InternalWriteData()->WriteUShort(Offset::kFlags, flags); +} + +int32_t FontHeaderTable::Builder::UnitsPerEm() { + return down_cast(GetTable())->UnitsPerEm(); +} + +void FontHeaderTable::Builder::SetUnitsPerEm(int32_t units) { + InternalWriteData()->WriteUShort(Offset::kUnitsPerEm, units); +} + +int64_t FontHeaderTable::Builder::Created() { + return down_cast(GetTable())->Created(); +} + +void FontHeaderTable::Builder::SetCreated(int64_t date) { + InternalWriteData()->WriteDateTime(Offset::kCreated, date); +} + +int64_t FontHeaderTable::Builder::Modified() { + return down_cast(GetTable())->Modified(); +} + +void FontHeaderTable::Builder::SetModified(int64_t date) { + InternalWriteData()->WriteDateTime(Offset::kModified, date); +} + +int32_t FontHeaderTable::Builder::XMin() { + return down_cast(GetTable())->XMin(); +} + +void FontHeaderTable::Builder::SetXMin(int32_t xmin) { + InternalWriteData()->WriteShort(Offset::kXMin, xmin); +} + +int32_t FontHeaderTable::Builder::YMin() { + return down_cast(GetTable())->YMin(); +} + +void FontHeaderTable::Builder::SetYMin(int32_t ymin) { + InternalWriteData()->WriteShort(Offset::kYMin, ymin); +} + +int32_t FontHeaderTable::Builder::XMax() { + return down_cast(GetTable())->XMax(); +} + +void FontHeaderTable::Builder::SetXMax(int32_t xmax) { + InternalWriteData()->WriteShort(Offset::kXMax, xmax); +} + +int32_t FontHeaderTable::Builder::YMax() { + return down_cast(GetTable())->YMax(); +} + +void FontHeaderTable::Builder::SetYMax(int32_t ymax) { + InternalWriteData()->WriteShort(Offset::kYMax, ymax); +} + +int32_t FontHeaderTable::Builder::MacStyleAsInt() { + return down_cast(GetTable())->MacStyleAsInt(); +} + +void FontHeaderTable::Builder::SetMacStyleAsInt(int32_t style) { + InternalWriteData()->WriteUShort(Offset::kMacStyle, style); +} + +int32_t FontHeaderTable::Builder::LowestRecPPEM() { + return down_cast(GetTable())->LowestRecPPEM(); +} + +void FontHeaderTable::Builder::SetLowestRecPPEM(int32_t size) { + InternalWriteData()->WriteUShort(Offset::kLowestRecPPEM, size); +} + +int32_t FontHeaderTable::Builder::FontDirectionHint() { + return down_cast(GetTable())->FontDirectionHint(); +} + +void FontHeaderTable::Builder::SetFontDirectionHint(int32_t hint) { + InternalWriteData()->WriteShort(Offset::kFontDirectionHint, hint); +} + +int32_t FontHeaderTable::Builder::IndexToLocFormat() { + return down_cast(GetTable())->IndexToLocFormat(); +} + +void FontHeaderTable::Builder::SetIndexToLocFormat(int32_t format) { + InternalWriteData()->WriteShort(Offset::kIndexToLocFormat, format); +} + +int32_t FontHeaderTable::Builder::GlyphDataFormat() { + return down_cast(GetTable())->GlyphDataFormat(); +} + +void FontHeaderTable::Builder::SetGlyphDataFormat(int32_t format) { + InternalWriteData()->WriteShort(Offset::kGlyphDataFormat, format); +} + +CALLER_ATTACH FontHeaderTable::Builder* + FontHeaderTable::Builder::CreateBuilder(Header* header, + WritableFontData* data) { + Ptr builder; + builder = new FontHeaderTable::Builder(header, data); + return builder.Detach(); +} + +} // namespace sfntly diff --git a/src/sfntly/src/sfntly/table/core/font_header_table.h b/src/sfntly/src/sfntly/table/core/font_header_table.h new file mode 100644 index 000000000000..841955b42385 --- /dev/null +++ b/src/sfntly/src/sfntly/table/core/font_header_table.h @@ -0,0 +1,168 @@ +/* + * 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. + */ + +#ifndef SFNTLY_CPP_SRC_SFNTLY_TABLE_CORE_FONT_HEADER_TABLE_H_ +#define SFNTLY_CPP_SRC_SFNTLY_TABLE_CORE_FONT_HEADER_TABLE_H_ + +#include "sfntly/table/table.h" +#include "sfntly/table/table_based_table_builder.h" + +namespace sfntly { + +struct IndexToLocFormat { + enum { + kShortOffset = 0, + kLongOffset = 1 + }; +}; + +struct FontDirectionHint { + enum { + kFullyMixed = 0, + kOnlyStrongLTR = 1, + kStrongLTRAndNeutral = 2, + kOnlyStrongRTL = -1, + kStrongRTLAndNeutral = -2 + }; +}; + +class FontHeaderTable : public Table, public RefCounted { + public: + class Builder : public TableBasedTableBuilder, public RefCounted { + public: + // Constructor scope altered to public because C++ does not allow base + // class to instantiate derived class with protected constructors. + Builder(Header* header, WritableFontData* data); + Builder(Header* header, ReadableFontData* data); + virtual ~Builder(); + virtual CALLER_ATTACH FontDataTable* SubBuildTable(ReadableFontData* data); + + virtual int32_t TableVersion(); + virtual void SetTableVersion(int32_t version); + virtual int32_t FontRevision(); + virtual void SetFontRevision(int32_t revision); + virtual int64_t ChecksumAdjustment(); + virtual void SetChecksumAdjustment(int64_t adjustment); + virtual int64_t MagicNumber(); + virtual void SetMagicNumber(int64_t magic_number); + virtual int32_t FlagsAsInt(); + virtual void SetFlagsAsInt(int32_t flags); + // TODO(arthurhsu): IMPLEMENT EnumSet Flags() + // TODO(arthurhsu): IMPLEMENT setFlags(EnumSet flags) + virtual int32_t UnitsPerEm(); + virtual void SetUnitsPerEm(int32_t units); + virtual int64_t Created(); + virtual void SetCreated(int64_t date); + virtual int64_t Modified(); + virtual void SetModified(int64_t date); + virtual int32_t XMin(); + virtual void SetXMin(int32_t xmin); + virtual int32_t YMin(); + virtual void SetYMin(int32_t ymin); + virtual int32_t XMax(); + virtual void SetXMax(int32_t xmax); + virtual int32_t YMax(); + virtual void SetYMax(int32_t ymax); + virtual int32_t MacStyleAsInt(); + virtual void SetMacStyleAsInt(int32_t style); + // TODO(arthurhsu): IMPLEMENT EnumSet macStyle() + // TODO(arthurhsu): IMPLEMENT setMacStyle(EnumSet style) + virtual int32_t LowestRecPPEM(); + virtual void SetLowestRecPPEM(int32_t size); + virtual int32_t FontDirectionHint(); + virtual void SetFontDirectionHint(int32_t hint); + virtual int32_t IndexToLocFormat(); + virtual void SetIndexToLocFormat(int32_t format); + virtual int32_t GlyphDataFormat(); + virtual void SetGlyphDataFormat(int32_t format); + + static CALLER_ATTACH Builder* CreateBuilder(Header* header, + WritableFontData* data); + }; + + virtual ~FontHeaderTable(); + int32_t TableVersion(); + int32_t FontRevision(); + + // Get the checksum adjustment. To compute: set it to 0, sum the entire font + // as ULONG, then store 0xB1B0AFBA - sum. + int64_t ChecksumAdjustment(); + + // Get the magic number. Set to 0x5F0F3CF5. + int64_t MagicNumber(); + + // TODO(arthurhsu): IMPLEMENT: EnumSet + int32_t FlagsAsInt(); + // TODO(arthurhsu): IMPLEMENT: Flags() returning EnumSet + + int32_t UnitsPerEm(); + + // Get the created date. Number of seconds since 12:00 midnight, January 1, + // 1904. 64-bit integer. + int64_t Created(); + // Get the modified date. Number of seconds since 12:00 midnight, January 1, + // 1904. 64-bit integer. + int64_t Modified(); + + // Get the x min. For all glyph bounding boxes. + int32_t XMin(); + // Get the y min. For all glyph bounding boxes. + int32_t YMin(); + // Get the x max. For all glyph bounding boxes. + int32_t XMax(); + // Get the y max. For all glyph bounding boxes. + int32_t YMax(); + + // TODO(arthurhsu): IMPLEMENT: EnumSet + int32_t MacStyleAsInt(); + // TODO(arthurhsu): IMPLEMENT: macStyle() returning EnumSet + + int32_t LowestRecPPEM(); + int32_t FontDirectionHint(); // Note: no AsInt() form, already int + int32_t IndexToLocFormat(); // Note: no AsInt() form, already int + int32_t GlyphDataFormat(); + + private: + struct Offset { + enum { + kTableVersion = 0, + kFontRevision = 4, + kCheckSumAdjustment = 8, + kMagicNumber = 12, + kFlags = 16, + kUnitsPerEm = 18, + kCreated = 20, + kModified = 28, + kXMin = 36, + kYMin = 38, + kXMax = 40, + kYMax = 42, + kMacStyle = 44, + kLowestRecPPEM = 46, + kFontDirectionHint = 48, + kIndexToLocFormat = 50, + kGlyphDataFormat = 52 + }; + }; + + FontHeaderTable(Header* header, ReadableFontData* data); +}; +typedef Ptr FontHeaderTablePtr; +typedef Ptr FontHeaderTableBuilderPtr; + +} // namespace sfntly + +#endif // SFNTLY_CPP_SRC_SFNTLY_TABLE_CORE_FONT_HEADER_TABLE_H_ diff --git a/src/sfntly/src/sfntly/table/core/horizontal_device_metrics_table.cc b/src/sfntly/src/sfntly/table/core/horizontal_device_metrics_table.cc new file mode 100644 index 000000000000..50b0cf579dc5 --- /dev/null +++ b/src/sfntly/src/sfntly/table/core/horizontal_device_metrics_table.cc @@ -0,0 +1,124 @@ +/* + * 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. + */ + +#include "sfntly/table/core/horizontal_device_metrics_table.h" + +namespace sfntly { +/****************************************************************************** + * HorizontalDeviceMetricsTable class + ******************************************************************************/ +HorizontalDeviceMetricsTable:: ~HorizontalDeviceMetricsTable() {} + +int32_t HorizontalDeviceMetricsTable::Version() { + return data_->ReadUShort(Offset::kVersion); +} + +int32_t HorizontalDeviceMetricsTable::NumRecords() { + return data_->ReadShort(Offset::kNumRecords); +} + +int32_t HorizontalDeviceMetricsTable::RecordSize() { + return data_->ReadLong(Offset::kSizeDeviceRecord); +} + +int32_t HorizontalDeviceMetricsTable::PixelSize(int32_t record_index) { + if (record_index < 0 || record_index >= NumRecords()) { +#if !defined (SFNTLY_NO_EXCEPTION) + throw IndexOutOfBoundsException(); +#endif + return -1; + } + return data_->ReadUByte(Offset::kRecords + record_index * RecordSize() + + Offset::kDeviceRecordPixelSize); +} + +int32_t HorizontalDeviceMetricsTable::MaxWidth(int32_t record_index) { + if (record_index < 0 || record_index >= NumRecords()) { +#if !defined (SFNTLY_NO_EXCEPTION) + throw IndexOutOfBoundsException(); +#endif + return -1; + } + return data_->ReadUByte(Offset::kRecords + record_index * RecordSize() + + Offset::kDeviceRecordMaxWidth); +} + +int32_t HorizontalDeviceMetricsTable::Width(int32_t record_index, + int32_t glyph_num) { + if (record_index < 0 || record_index >= NumRecords() || + glyph_num < 0 || glyph_num >= num_glyphs_) { +#if !defined (SFNTLY_NO_EXCEPTION) + throw IndexOutOfBoundsException(); +#endif + return -1; + } + return data_->ReadUByte(Offset::kRecords + record_index * RecordSize() + + Offset::kDeviceRecordWidths + glyph_num); +} + +HorizontalDeviceMetricsTable::HorizontalDeviceMetricsTable( + Header* header, + ReadableFontData* data, + int32_t num_glyphs) + : Table(header, data), num_glyphs_(num_glyphs) { +} + +/****************************************************************************** + * HorizontalDeviceMetricsTable::Builder class + ******************************************************************************/ +HorizontalDeviceMetricsTable::Builder::Builder(Header* header, + WritableFontData* data) + : TableBasedTableBuilder(header, data), num_glyphs_(-1) { +} + +HorizontalDeviceMetricsTable::Builder::Builder(Header* header, + ReadableFontData* data) + : TableBasedTableBuilder(header, data), num_glyphs_(-1) { +} + +HorizontalDeviceMetricsTable::Builder::~Builder() {} + +CALLER_ATTACH FontDataTable* +HorizontalDeviceMetricsTable::Builder::SubBuildTable(ReadableFontData* data) { + FontDataTablePtr table = new HorizontalDeviceMetricsTable(header(), data, + num_glyphs_); + return table.Detach(); +} + +void HorizontalDeviceMetricsTable::Builder::SetNumGlyphs(int32_t num_glyphs) { + if (num_glyphs < 0) { +#if !defined (SFNTLY_NO_EXCEPTION) + throw IllegalArgumentException("Number of glyphs can't be negative."); +#endif + return; + } + num_glyphs_ = num_glyphs; + HorizontalDeviceMetricsTable* table = + down_cast(GetTable()); + if (table) { + table->num_glyphs_ = num_glyphs; + } +} + +CALLER_ATTACH HorizontalDeviceMetricsTable::Builder* +HorizontalDeviceMetricsTable::Builder::CreateBuilder(Header* header, + WritableFontData* data) { + Ptr builder; + builder = new HorizontalDeviceMetricsTable::Builder(header, data); + return builder.Detach(); +} + +} // namespace sfntly diff --git a/src/sfntly/src/sfntly/table/core/horizontal_device_metrics_table.h b/src/sfntly/src/sfntly/table/core/horizontal_device_metrics_table.h new file mode 100644 index 000000000000..4a27ba0964d8 --- /dev/null +++ b/src/sfntly/src/sfntly/table/core/horizontal_device_metrics_table.h @@ -0,0 +1,82 @@ +/* + * 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. + */ + +#ifndef SFNTLY_CPP_SRC_SFNTLY_TABLE_CORE_HORIZONTAL_DEVICE_METRICS_TABLE_H_ +#define SFNTLY_CPP_SRC_SFNTLY_TABLE_CORE_HORIZONTAL_DEVICE_METRICS_TABLE_H_ + +#include "sfntly/table/table.h" +#include "sfntly/table/table_based_table_builder.h" + +namespace sfntly { + +// A Horizontal Device Metrics table - 'hdmx' +class HorizontalDeviceMetricsTable + : public Table, + public RefCounted { + public: + class Builder : public TableBasedTableBuilder, public RefCounted { + public: + // Constructor scope altered to public because C++ does not allow base + // class to instantiate derived class with protected constructors. + Builder(Header* header, WritableFontData* data); + Builder(Header* header, ReadableFontData* data); + virtual ~Builder(); + virtual CALLER_ATTACH FontDataTable* SubBuildTable(ReadableFontData* data); + + static CALLER_ATTACH Builder* CreateBuilder(Header* header, + WritableFontData* data); + + void SetNumGlyphs(int32_t num_glyphs); + + private: + int32_t num_glyphs_; + }; + + virtual ~HorizontalDeviceMetricsTable(); + + int32_t Version(); + int32_t NumRecords(); + int32_t RecordSize(); + int32_t PixelSize(int32_t record_index); + int32_t MaxWidth(int32_t record_index); + int32_t Width(int32_t record_index, int32_t glyph_num); + + private: + struct Offset { + enum { + kVersion = 0, + kNumRecords = 2, + kSizeDeviceRecord = 4, + kRecords = 8, + + // Offsets within a device record + kDeviceRecordPixelSize = 0, + kDeviceRecordMaxWidth = 1, + kDeviceRecordWidths = 2, + }; + }; + HorizontalDeviceMetricsTable(Header* header, + ReadableFontData* data, + int32_t num_glyphs); + + int32_t num_glyphs_; +}; +typedef Ptr HorizontalDeviceMetricsTablePtr; +typedef Ptr + HorizontalDeviceMetricsTableBuilderPtr; +} // namespace sfntly + +#endif // SFNTLY_CPP_SRC_SFNTLY_TABLE_CORE_HORIZONTAL_DEVICE_METRICS_TABLE_H_ diff --git a/src/sfntly/src/sfntly/table/core/horizontal_header_table.cc b/src/sfntly/src/sfntly/table/core/horizontal_header_table.cc new file mode 100644 index 000000000000..43c20585d3ab --- /dev/null +++ b/src/sfntly/src/sfntly/table/core/horizontal_header_table.cc @@ -0,0 +1,213 @@ +/* + * 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. + */ + +#include "sfntly/table/core/horizontal_header_table.h" + +namespace sfntly { +/****************************************************************************** + * HorizontalHeaderTable class + ******************************************************************************/ +HorizontalHeaderTable:: ~HorizontalHeaderTable() {} + +int32_t HorizontalHeaderTable::TableVersion() { + return data_->ReadFixed(Offset::kVersion); +} + +int32_t HorizontalHeaderTable::Ascender() { + return data_->ReadShort(Offset::kAscender); +} + +int32_t HorizontalHeaderTable::Descender() { + return data_->ReadShort(Offset::kDescender); +} + +int32_t HorizontalHeaderTable::LineGap() { + return data_->ReadShort(Offset::kLineGap); +} + +int32_t HorizontalHeaderTable::AdvanceWidthMax() { + return data_->ReadUShort(Offset::kAdvanceWidthMax); +} + +int32_t HorizontalHeaderTable::MinLeftSideBearing() { + return data_->ReadShort(Offset::kMinLeftSideBearing); +} + +int32_t HorizontalHeaderTable::MinRightSideBearing() { + return data_->ReadShort(Offset::kMinRightSideBearing); +} + +int32_t HorizontalHeaderTable::XMaxExtent() { + return data_->ReadShort(Offset::kXMaxExtent); +} + +int32_t HorizontalHeaderTable::CaretSlopeRise() { + return data_->ReadShort(Offset::kCaretSlopeRise); +} + +int32_t HorizontalHeaderTable::CaretSlopeRun() { + return data_->ReadShort(Offset::kCaretSlopeRun); +} + +int32_t HorizontalHeaderTable::CaretOffset() { + return data_->ReadShort(Offset::kCaretOffset); +} + +int32_t HorizontalHeaderTable::MetricDataFormat() { + return data_->ReadShort(Offset::kMetricDataFormat); +} + +int32_t HorizontalHeaderTable::NumberOfHMetrics() { + return data_->ReadUShort(Offset::kNumberOfHMetrics); +} + +HorizontalHeaderTable:: HorizontalHeaderTable(Header* header, + ReadableFontData* data) + : Table(header, data) { +} + +/****************************************************************************** + * HorizontalHeaderTable::Builder class + ******************************************************************************/ +HorizontalHeaderTable::Builder::Builder(Header* header, WritableFontData* data) + : TableBasedTableBuilder(header, data) { +} + +HorizontalHeaderTable::Builder::Builder(Header* header, ReadableFontData* data) + : TableBasedTableBuilder(header, data) { +} + +HorizontalHeaderTable::Builder::~Builder() {} + +CALLER_ATTACH FontDataTable* + HorizontalHeaderTable::Builder::SubBuildTable(ReadableFontData* data) { + FontDataTablePtr table = new HorizontalHeaderTable(header(), data); + return table.Detach(); +} + +CALLER_ATTACH HorizontalHeaderTable::Builder* + HorizontalHeaderTable::Builder::CreateBuilder(Header* header, + WritableFontData* data) { + Ptr builder; + builder = new HorizontalHeaderTable::Builder(header, data); + return builder.Detach(); +} + +int32_t HorizontalHeaderTable::Builder::TableVersion() { + return InternalReadData()->ReadFixed(Offset::kVersion); +} + +void HorizontalHeaderTable::Builder::SetTableVersion(int32_t version) { + InternalWriteData()->WriteFixed(Offset::kVersion, version); +} + +int32_t HorizontalHeaderTable::Builder::Ascender() { + return InternalReadData()->ReadShort(Offset::kAscender); +} + +void HorizontalHeaderTable::Builder::SetAscender(int32_t ascender) { + InternalWriteData()->WriteShort(Offset::kVersion, ascender); +} + +int32_t HorizontalHeaderTable::Builder::Descender() { + return InternalReadData()->ReadShort(Offset::kDescender); +} + +void HorizontalHeaderTable::Builder::SetDescender(int32_t descender) { + InternalWriteData()->WriteShort(Offset::kDescender, descender); +} + +int32_t HorizontalHeaderTable::Builder::LineGap() { + return InternalReadData()->ReadShort(Offset::kLineGap); +} + +void HorizontalHeaderTable::Builder::SetLineGap(int32_t line_gap) { + InternalWriteData()->WriteShort(Offset::kLineGap, line_gap); +} + +int32_t HorizontalHeaderTable::Builder::AdvanceWidthMax() { + return InternalReadData()->ReadUShort(Offset::kAdvanceWidthMax); +} + +void HorizontalHeaderTable::Builder::SetAdvanceWidthMax(int32_t value) { + InternalWriteData()->WriteUShort(Offset::kAdvanceWidthMax, value); +} + +int32_t HorizontalHeaderTable::Builder::MinLeftSideBearing() { + return InternalReadData()->ReadShort(Offset::kMinLeftSideBearing); +} + +void HorizontalHeaderTable::Builder::SetMinLeftSideBearing(int32_t value) { + InternalWriteData()->WriteShort(Offset::kMinLeftSideBearing, value); +} + +int32_t HorizontalHeaderTable::Builder::MinRightSideBearing() { + return InternalReadData()->ReadShort(Offset::kMinRightSideBearing); +} + +void HorizontalHeaderTable::Builder::SetMinRightSideBearing(int32_t value) { + InternalWriteData()->WriteShort(Offset::kMinRightSideBearing, value); +} + +int32_t HorizontalHeaderTable::Builder::XMaxExtent() { + return InternalReadData()->ReadShort(Offset::kXMaxExtent); +} + +void HorizontalHeaderTable::Builder::SetXMaxExtent(int32_t value) { + InternalWriteData()->WriteShort(Offset::kXMaxExtent, value); +} + +int32_t HorizontalHeaderTable::Builder::CaretSlopeRise() { + return InternalReadData()->ReadUShort(Offset::kCaretSlopeRise); +} + +void HorizontalHeaderTable::Builder::SetCaretSlopeRise(int32_t value) { + InternalWriteData()->WriteUShort(Offset::kCaretSlopeRise, value); +} + +int32_t HorizontalHeaderTable::Builder::CaretSlopeRun() { + return InternalReadData()->ReadUShort(Offset::kCaretSlopeRun); +} + +void HorizontalHeaderTable::Builder::SetCaretSlopeRun(int32_t value) { + InternalWriteData()->WriteUShort(Offset::kCaretSlopeRun, value); +} + +int32_t HorizontalHeaderTable::Builder::CaretOffset() { + return InternalReadData()->ReadUShort(Offset::kCaretOffset); +} + +void HorizontalHeaderTable::Builder::SetCaretOffset(int32_t value) { + InternalWriteData()->WriteUShort(Offset::kCaretOffset, value); +} + +int32_t HorizontalHeaderTable::Builder::MetricDataFormat() { + return InternalReadData()->ReadUShort(Offset::kMetricDataFormat); +} + +void HorizontalHeaderTable::Builder::SetMetricDataFormat(int32_t value) { + InternalWriteData()->WriteUShort(Offset::kMetricDataFormat, value); +} + +int32_t HorizontalHeaderTable::Builder::NumberOfHMetrics() { + return InternalReadData()->ReadUShort(Offset::kNumberOfHMetrics); +} + +void HorizontalHeaderTable::Builder::SetNumberOfHMetrics(int32_t value) { + InternalWriteData()->WriteUShort(Offset::kNumberOfHMetrics, value); +} + +} // namespace sfntly diff --git a/src/sfntly/src/sfntly/table/core/horizontal_header_table.h b/src/sfntly/src/sfntly/table/core/horizontal_header_table.h new file mode 100644 index 000000000000..71f30b447562 --- /dev/null +++ b/src/sfntly/src/sfntly/table/core/horizontal_header_table.h @@ -0,0 +1,111 @@ +/* + * 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. + */ + +#ifndef SFNTLY_CPP_SRC_SFNTLY_TABLE_CORE_HORIZONTAL_HEADER_TABLE_H_ +#define SFNTLY_CPP_SRC_SFNTLY_TABLE_CORE_HORIZONTAL_HEADER_TABLE_H_ + +#include "sfntly/table/table.h" +#include "sfntly/table/table_based_table_builder.h" + +namespace sfntly { + +// A Horizontal Header table - 'hhea'. +class HorizontalHeaderTable : public Table, + public RefCounted { + public: + // Builder for a Horizontal Header table - 'hhea'. + class Builder : public TableBasedTableBuilder, public RefCounted { + public: + // Constructor scope altered to public because C++ does not allow base + // class to instantiate derived class with protected constructors. + Builder(Header* header, WritableFontData* data); + Builder(Header* header, ReadableFontData* data); + virtual ~Builder(); + virtual CALLER_ATTACH FontDataTable* SubBuildTable(ReadableFontData* data); + + static CALLER_ATTACH Builder* CreateBuilder(Header* header, + WritableFontData* data); + + int32_t TableVersion(); + void SetTableVersion(int32_t version); + int32_t Ascender(); + void SetAscender(int32_t ascender); + int32_t Descender(); + void SetDescender(int32_t descender); + int32_t LineGap(); + void SetLineGap(int32_t line_gap); + int32_t AdvanceWidthMax(); + void SetAdvanceWidthMax(int32_t value); + int32_t MinLeftSideBearing(); + void SetMinLeftSideBearing(int32_t value); + int32_t MinRightSideBearing(); + void SetMinRightSideBearing(int32_t value); + int32_t XMaxExtent(); + void SetXMaxExtent(int32_t value); + int32_t CaretSlopeRise(); + void SetCaretSlopeRise(int32_t value); + int32_t CaretSlopeRun(); + void SetCaretSlopeRun(int32_t value); + int32_t CaretOffset(); + void SetCaretOffset(int32_t value); + int32_t MetricDataFormat(); + void SetMetricDataFormat(int32_t value); + int32_t NumberOfHMetrics(); + void SetNumberOfHMetrics(int32_t value); + }; + + virtual ~HorizontalHeaderTable(); + int32_t TableVersion(); + int32_t Ascender(); + int32_t Descender(); + int32_t LineGap(); + int32_t AdvanceWidthMax(); + int32_t MinLeftSideBearing(); + int32_t MinRightSideBearing(); + int32_t XMaxExtent(); + int32_t CaretSlopeRise(); + int32_t CaretSlopeRun(); + int32_t CaretOffset(); + int32_t MetricDataFormat(); + int32_t NumberOfHMetrics(); + + private: + struct Offset { + enum { + kVersion = 0, + kAscender = 4, + kDescender = 6, + kLineGap = 8, + kAdvanceWidthMax = 10, + kMinLeftSideBearing = 12, + kMinRightSideBearing = 14, + kXMaxExtent = 16, + kCaretSlopeRise = 18, + kCaretSlopeRun = 20, + kCaretOffset = 22, + kMetricDataFormat = 32, + kNumberOfHMetrics = 34, + }; + }; + + HorizontalHeaderTable(Header* header, ReadableFontData* data); +}; +typedef Ptr HorizontalHeaderTablePtr; +typedef Ptr HorizontalHeaderTableBuilderPtr; + +} // namespace sfntly + +#endif // SFNTLY_CPP_SRC_SFNTLY_TABLE_CORE_HORIZONTAL_HEADER_TABLE_H_ diff --git a/src/sfntly/src/sfntly/table/core/horizontal_metrics_table.cc b/src/sfntly/src/sfntly/table/core/horizontal_metrics_table.cc new file mode 100644 index 000000000000..156387daaf2a --- /dev/null +++ b/src/sfntly/src/sfntly/table/core/horizontal_metrics_table.cc @@ -0,0 +1,138 @@ +/* + * 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. + */ + +#include "sfntly/table/core/horizontal_metrics_table.h" +#include "sfntly/port/exception_type.h" + +namespace sfntly { +/****************************************************************************** + * HorizontalMetricsTable class + ******************************************************************************/ +HorizontalMetricsTable::~HorizontalMetricsTable() {} + +int32_t HorizontalMetricsTable::NumberOfHMetrics() { + return num_hmetrics_; +} + +int32_t HorizontalMetricsTable::NumberOfLSBs() { + return num_glyphs_ - num_hmetrics_; +} + +int32_t HorizontalMetricsTable::HMetricAdvanceWidth(int32_t entry) { + if (entry > num_hmetrics_) { +#if !defined (SFNTLY_NO_EXCEPTION) + throw IndexOutOfBoundException(); +#endif + return 0; + } + int32_t offset = Offset::kHMetricsStart + (entry * Offset::kHMetricsSize) + + Offset::kHMetricsAdvanceWidth; + return data_->ReadUShort(offset); +} + +int32_t HorizontalMetricsTable::HMetricLSB(int32_t entry) { + if (entry > num_hmetrics_) { +#if !defined (SFNTLY_NO_EXCEPTION) + throw IndexOutOfBoundException(); +#endif + return 0; + } + int32_t offset = Offset::kHMetricsStart + (entry * Offset::kHMetricsSize) + + Offset::kHMetricsLeftSideBearing; + return data_->ReadShort(offset); +} + +int32_t HorizontalMetricsTable::LsbTableEntry(int32_t entry) { + if (entry > num_hmetrics_) { +#if !defined (SFNTLY_NO_EXCEPTION) + throw IndexOutOfBoundException(); +#endif + return 0; + } + int32_t offset = Offset::kHMetricsStart + (entry * Offset::kHMetricsSize) + + Offset::kLeftSideBearingSize; + return data_->ReadShort(offset); +} + +int32_t HorizontalMetricsTable::AdvanceWidth(int32_t glyph_id) { + if (glyph_id < num_hmetrics_) { + return HMetricAdvanceWidth(glyph_id); + } + return HMetricAdvanceWidth(glyph_id - num_hmetrics_); +} + +int32_t HorizontalMetricsTable::LeftSideBearing(int32_t glyph_id) { + if (glyph_id < num_hmetrics_) { + return HMetricLSB(glyph_id); + } + return LsbTableEntry(glyph_id - num_hmetrics_); +} + +HorizontalMetricsTable::HorizontalMetricsTable(Header* header, + ReadableFontData* data, + int32_t num_hmetrics, + int32_t num_glyphs) + : Table(header, data), + num_hmetrics_(num_hmetrics), + num_glyphs_(num_glyphs) { +} + +/****************************************************************************** + * HorizontalMetricsTable::Builder class + ******************************************************************************/ +HorizontalMetricsTable::Builder::Builder(Header* header, WritableFontData* data) + : TableBasedTableBuilder(header, data), num_hmetrics_(-1), num_glyphs_(-1) { +} + +HorizontalMetricsTable::Builder::Builder(Header* header, ReadableFontData* data) + : TableBasedTableBuilder(header, data), num_hmetrics_(-1), num_glyphs_(-1) { +} + +HorizontalMetricsTable::Builder::~Builder() {} + +CALLER_ATTACH FontDataTable* + HorizontalMetricsTable::Builder::SubBuildTable(ReadableFontData* data) { + FontDataTablePtr table = + new HorizontalMetricsTable(header(), data, num_hmetrics_, num_glyphs_); + return table.Detach(); +} + +CALLER_ATTACH HorizontalMetricsTable::Builder* + HorizontalMetricsTable::Builder::CreateBuilder(Header* header, + WritableFontData* data) { + Ptr builder; + builder = new HorizontalMetricsTable::Builder(header, data); + return builder.Detach(); +} + +void HorizontalMetricsTable::Builder::SetNumberOfHMetrics( + int32_t num_hmetrics) { + assert(num_hmetrics >= 0); + num_hmetrics_ = num_hmetrics; + HorizontalMetricsTable* table = + down_cast(this->GetTable()); + table->num_hmetrics_ = num_hmetrics; +} + +void HorizontalMetricsTable::Builder::SetNumGlyphs(int32_t num_glyphs) { + assert(num_glyphs >= 0); + num_glyphs_ = num_glyphs; + HorizontalMetricsTable* table = + down_cast(this->GetTable()); + table->num_glyphs_ = num_glyphs; +} + +} // namespace sfntly diff --git a/src/sfntly/src/sfntly/table/core/horizontal_metrics_table.h b/src/sfntly/src/sfntly/table/core/horizontal_metrics_table.h new file mode 100644 index 000000000000..44b51f2d7922 --- /dev/null +++ b/src/sfntly/src/sfntly/table/core/horizontal_metrics_table.h @@ -0,0 +1,87 @@ +/* + * 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. + */ + +#ifndef SFNTLY_CPP_SRC_SFNTLY_TABLE_CORE_HORIZONTAL_METRICS_TABLE_H_ +#define SFNTLY_CPP_SRC_SFNTLY_TABLE_CORE_HORIZONTAL_METRICS_TABLE_H_ + +#include "sfntly/table/table.h" +#include "sfntly/table/table_based_table_builder.h" + +namespace sfntly { + +// A Horizontal Metrics table - 'hmtx'. +class HorizontalMetricsTable : public Table, + public RefCounted { + public: + // Builder for a Horizontal Metrics Table - 'hmtx'. + class Builder : public TableBasedTableBuilder, public RefCounted { + public: + // Constructor scope altered to public because C++ does not allow base + // class to instantiate derived class with protected constructors. + Builder(Header* header, WritableFontData* data); + Builder(Header* header, ReadableFontData* data); + virtual ~Builder(); + + virtual CALLER_ATTACH FontDataTable* SubBuildTable(ReadableFontData* data); + static CALLER_ATTACH Builder* CreateBuilder(Header* header, + WritableFontData* data); + + void SetNumberOfHMetrics(int32_t num_hmetrics); + void SetNumGlyphs(int32_t num_glyphs); + + private: + int32_t num_hmetrics_; + int32_t num_glyphs_; + }; + + virtual ~HorizontalMetricsTable(); + int32_t NumberOfHMetrics(); + int32_t NumberOfLSBs(); + int32_t HMetricAdvanceWidth(int32_t entry); + int32_t HMetricLSB(int32_t entry); + int32_t LsbTableEntry(int32_t entry); + int32_t AdvanceWidth(int32_t glyph_id); + int32_t LeftSideBearing(int32_t glyph_id); + + private: + struct Offset { + enum { + // hMetrics + kHMetricsStart = 0, + kHMetricsSize = 4, + + // Offset within an hMetric + kHMetricsAdvanceWidth = 0, + kHMetricsLeftSideBearing = 2, + + kLeftSideBearingSize = 2 + }; + }; + + HorizontalMetricsTable(Header* header, + ReadableFontData* data, + int32_t num_hmetrics, + int32_t num_glyphs); + + int32_t num_hmetrics_; + int32_t num_glyphs_; +}; +typedef Ptr HorizontalMetricsTablePtr; +typedef Ptr HorizontalMetricsTableBuilderPtr; + +} // namespace sfntly + +#endif // SFNTLY_CPP_SRC_SFNTLY_TABLE_CORE_HORIZONTAL_METRICS_TABLE_H_ diff --git a/src/sfntly/src/sfntly/table/core/maximum_profile_table.cc b/src/sfntly/src/sfntly/table/core/maximum_profile_table.cc new file mode 100644 index 000000000000..a8ac3bc93ab7 --- /dev/null +++ b/src/sfntly/src/sfntly/table/core/maximum_profile_table.cc @@ -0,0 +1,240 @@ +/* + * 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. + */ + +#include "sfntly/table/core/maximum_profile_table.h" + +namespace sfntly { +/****************************************************************************** + * MaximumProfileTable class + ******************************************************************************/ +MaximumProfileTable::~MaximumProfileTable() {} + +int32_t MaximumProfileTable::TableVersion() { + return data_->ReadFixed(Offset::kVersion); +} + +int32_t MaximumProfileTable::NumGlyphs() { + return data_->ReadUShort(Offset::kNumGlyphs); +} + +int32_t MaximumProfileTable::MaxPoints() { + return data_->ReadUShort(Offset::kMaxPoints); +} + +int32_t MaximumProfileTable::MaxContours() { + return data_->ReadUShort(Offset::kMaxContours); +} + +int32_t MaximumProfileTable::MaxCompositePoints() { + return data_->ReadUShort(Offset::kMaxCompositePoints); +} + +int32_t MaximumProfileTable::MaxCompositeContours() { + return data_->ReadUShort(Offset::kMaxCompositeContours); +} + +int32_t MaximumProfileTable::MaxZones() { + return data_->ReadUShort(Offset::kMaxZones); +} + +int32_t MaximumProfileTable::MaxTwilightPoints() { + return data_->ReadUShort(Offset::kMaxTwilightPoints); +} + +int32_t MaximumProfileTable::MaxStorage() { + return data_->ReadUShort(Offset::kMaxStorage); +} + +int32_t MaximumProfileTable::MaxFunctionDefs() { + return data_->ReadUShort(Offset::kMaxFunctionDefs); +} + +int32_t MaximumProfileTable::MaxStackElements() { + return data_->ReadUShort(Offset::kMaxStackElements); +} + +int32_t MaximumProfileTable::MaxSizeOfInstructions() { + return data_->ReadUShort(Offset::kMaxSizeOfInstructions); +} + +int32_t MaximumProfileTable::MaxComponentElements() { + return data_->ReadUShort(Offset::kMaxComponentElements); +} + +int32_t MaximumProfileTable::MaxComponentDepth() { + return data_->ReadUShort(Offset::kMaxComponentDepth); +} + +MaximumProfileTable::MaximumProfileTable(Header* header, + ReadableFontData* data) + : Table(header, data) { +} + +/****************************************************************************** + * MaximumProfileTable::Builder class + ******************************************************************************/ +MaximumProfileTable::Builder::Builder(Header* header, WritableFontData* data) + : TableBasedTableBuilder(header, data) { +} + +MaximumProfileTable::Builder::Builder(Header* header, ReadableFontData* data) + : TableBasedTableBuilder(header, data) { +} + +MaximumProfileTable::Builder::~Builder() {} + +CALLER_ATTACH FontDataTable* + MaximumProfileTable::Builder::SubBuildTable(ReadableFontData* data) { + FontDataTablePtr table = new MaximumProfileTable(header(), data); + return table.Detach(); +} + +CALLER_ATTACH MaximumProfileTable::Builder* + MaximumProfileTable::Builder::CreateBuilder(Header* header, + WritableFontData* data) { + Ptr builder; + builder = new MaximumProfileTable::Builder(header, data); + return builder.Detach(); +} + +int32_t MaximumProfileTable::Builder::TableVersion() { + return InternalReadData()->ReadUShort(Offset::kVersion); +} + +void MaximumProfileTable::Builder::SetTableVersion(int32_t version) { + InternalWriteData()->WriteUShort(Offset::kVersion, version); +} + +int32_t MaximumProfileTable::Builder::NumGlyphs() { + return InternalReadData()->ReadUShort(Offset::kNumGlyphs); +} + +void MaximumProfileTable::Builder::SetNumGlyphs(int32_t num_glyphs) { + InternalWriteData()->WriteUShort(Offset::kNumGlyphs, num_glyphs); +} + +int32_t MaximumProfileTable::Builder::MaxPoints() { + return InternalReadData()->ReadUShort(Offset::kMaxPoints); +} + +void MaximumProfileTable::Builder::SetMaxPoints(int32_t max_points) { + InternalWriteData()->WriteUShort(Offset::kMaxPoints, max_points); +} + +int32_t MaximumProfileTable::Builder::MaxContours() { + return InternalReadData()->ReadUShort(Offset::kMaxContours); +} + +void MaximumProfileTable::Builder::SetMaxContours(int32_t max_contours) { + InternalWriteData()->WriteUShort(Offset::kMaxContours, max_contours); +} + +int32_t MaximumProfileTable::Builder::MaxCompositePoints() { + return InternalReadData()->ReadUShort(Offset::kMaxCompositePoints); +} + +void MaximumProfileTable::Builder::SetMaxCompositePoints( + int32_t max_composite_points) { + InternalWriteData()->WriteUShort(Offset::kMaxCompositePoints, + max_composite_points); +} + +int32_t MaximumProfileTable::Builder::MaxCompositeContours() { + return InternalReadData()->ReadUShort(Offset::kMaxCompositeContours); +} + +void MaximumProfileTable::Builder::SetMaxCompositeContours( + int32_t max_composite_contours) { + InternalWriteData()->WriteUShort(Offset::kMaxCompositeContours, + max_composite_contours); +} + +int32_t MaximumProfileTable::Builder::MaxZones() { + return InternalReadData()->ReadUShort(Offset::kMaxZones); +} + +void MaximumProfileTable::Builder::SetMaxZones(int32_t max_zones) { + InternalWriteData()->WriteUShort(Offset::kMaxZones, max_zones); +} + +int32_t MaximumProfileTable::Builder::MaxTwilightPoints() { + return InternalReadData()->ReadUShort(Offset::kMaxTwilightPoints); +} + +void MaximumProfileTable::Builder::SetMaxTwilightPoints( + int32_t max_twilight_points) { + InternalWriteData()->WriteUShort(Offset::kMaxTwilightPoints, + max_twilight_points); +} + +int32_t MaximumProfileTable::Builder::MaxStorage() { + return InternalReadData()->ReadUShort(Offset::kMaxStorage); +} + +void MaximumProfileTable::Builder::SetMaxStorage(int32_t max_storage) { + InternalWriteData()->WriteUShort(Offset::kMaxStorage, max_storage); +} + +int32_t MaximumProfileTable::Builder::MaxFunctionDefs() { + return InternalReadData()->ReadUShort(Offset::kMaxFunctionDefs); +} + +void MaximumProfileTable::Builder::SetMaxFunctionDefs( + int32_t max_function_defs) { + InternalWriteData()->WriteUShort(Offset::kMaxFunctionDefs, max_function_defs); +} + +int32_t MaximumProfileTable::Builder::MaxStackElements() { + return InternalReadData()->ReadUShort(Offset::kMaxStackElements); +} + +void MaximumProfileTable::Builder::SetMaxStackElements( + int32_t max_stack_elements) { + InternalWriteData()->WriteUShort(Offset::kMaxStackElements, + max_stack_elements); +} + +int32_t MaximumProfileTable::Builder::MaxSizeOfInstructions() { + return InternalReadData()->ReadUShort(Offset::kMaxSizeOfInstructions); +} + +void MaximumProfileTable::Builder::SetMaxSizeOfInstructions( + int32_t max_size_of_instructions) { + InternalWriteData()->WriteUShort(Offset::kMaxSizeOfInstructions, + max_size_of_instructions); +} + +int32_t MaximumProfileTable::Builder::MaxComponentElements() { + return InternalReadData()->ReadUShort(Offset::kMaxComponentElements); +} + +void MaximumProfileTable::Builder::SetMaxComponentElements( + int32_t max_component_elements) { + InternalWriteData()->WriteUShort(Offset::kMaxComponentElements, + max_component_elements); +} + +int32_t MaximumProfileTable::Builder::MaxComponentDepth() { + return InternalReadData()->ReadUShort(Offset::kMaxComponentDepth); +} + +void MaximumProfileTable::Builder::SetMaxComponentDepth( + int32_t max_component_depth) { + InternalWriteData()->WriteUShort(Offset::kMaxComponentDepth, + max_component_depth); +} + +} // namespace sfntly diff --git a/src/sfntly/src/sfntly/table/core/maximum_profile_table.h b/src/sfntly/src/sfntly/table/core/maximum_profile_table.h new file mode 100644 index 000000000000..e7c5abb3ff42 --- /dev/null +++ b/src/sfntly/src/sfntly/table/core/maximum_profile_table.h @@ -0,0 +1,120 @@ +/* + * 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. + */ + +#ifndef SFNTLY_CPP_SRC_SFNTLY_TABLE_CORE_MAXIMUM_PROFILE_TABLE_H_ +#define SFNTLY_CPP_SRC_SFNTLY_TABLE_CORE_MAXIMUM_PROFILE_TABLE_H_ + +#include "sfntly/port/refcount.h" +#include "sfntly/table/table.h" +#include "sfntly/table/table_based_table_builder.h" + +namespace sfntly { + +// A Maximum Profile table - 'maxp'. +class MaximumProfileTable : public Table, + public RefCounted { + public: + // Builder for a Maximum Profile table - 'maxp'. + class Builder : public TableBasedTableBuilder, public RefCounted { + public: + // Constructor scope altered to public because C++ does not allow base + // class to instantiate derived class with protected constructors. + Builder(Header* header, WritableFontData* data); + Builder(Header* header, ReadableFontData* data); + virtual ~Builder(); + + virtual CALLER_ATTACH FontDataTable* SubBuildTable(ReadableFontData* data); + static CALLER_ATTACH Builder* CreateBuilder(Header* header, + WritableFontData* data); + + int32_t TableVersion(); + void SetTableVersion(int32_t version); + int32_t NumGlyphs(); + void SetNumGlyphs(int32_t num_glyphs); + int32_t MaxPoints(); + void SetMaxPoints(int32_t max_points); + int32_t MaxContours(); + void SetMaxContours(int32_t max_contours); + int32_t MaxCompositePoints(); + void SetMaxCompositePoints(int32_t max_composite_points); + int32_t MaxCompositeContours(); + void SetMaxCompositeContours(int32_t max_composite_contours); + int32_t MaxZones(); + void SetMaxZones(int32_t max_zones); + int32_t MaxTwilightPoints(); + void SetMaxTwilightPoints(int32_t max_twilight_points); + int32_t MaxStorage(); + void SetMaxStorage(int32_t max_storage); + int32_t MaxFunctionDefs(); + void SetMaxFunctionDefs(int32_t max_function_defs); + int32_t MaxStackElements(); + void SetMaxStackElements(int32_t max_stack_elements); + int32_t MaxSizeOfInstructions(); + void SetMaxSizeOfInstructions(int32_t max_size_of_instructions); + int32_t MaxComponentElements(); + void SetMaxComponentElements(int32_t max_component_elements); + int32_t MaxComponentDepth(); + void SetMaxComponentDepth(int32_t max_component_depth); + }; + + virtual ~MaximumProfileTable(); + int32_t TableVersion(); + int32_t NumGlyphs(); + int32_t MaxPoints(); + int32_t MaxContours(); + int32_t MaxCompositePoints(); + int32_t MaxCompositeContours(); + int32_t MaxZones(); + int32_t MaxTwilightPoints(); + int32_t MaxStorage(); + int32_t MaxFunctionDefs(); + int32_t MaxStackElements(); + int32_t MaxSizeOfInstructions(); + int32_t MaxComponentElements(); + int32_t MaxComponentDepth(); + + private: + struct Offset { + enum { + // version 0.5 and 1.0 + kVersion = 0, + kNumGlyphs = 4, + + // version 1.0 + kMaxPoints = 6, + kMaxContours = 8, + kMaxCompositePoints = 10, + kMaxCompositeContours = 12, + kMaxZones = 14, + kMaxTwilightPoints = 16, + kMaxStorage = 18, + kMaxFunctionDefs = 20, + kMaxInstructionDefs = 22, + kMaxStackElements = 24, + kMaxSizeOfInstructions = 26, + kMaxComponentElements = 28, + kMaxComponentDepth = 30, + }; + }; + + MaximumProfileTable(Header* header, ReadableFontData* data); +}; +typedef Ptr MaximumProfileTablePtr; +typedef Ptr MaximumProfileTableBuilderPtr; + +} // namespace sfntly + +#endif // SFNTLY_CPP_SRC_SFNTLY_TABLE_CORE_MAXIMUM_PROFILE_TABLE_H_ diff --git a/src/sfntly/src/sfntly/table/core/name_table.cc b/src/sfntly/src/sfntly/table/core/name_table.cc new file mode 100644 index 000000000000..5f6d5a51724d --- /dev/null +++ b/src/sfntly/src/sfntly/table/core/name_table.cc @@ -0,0 +1,721 @@ +/* + * 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. + */ + +#include "sfntly/table/core/name_table.h" + +#include +#include + +#include + +#include "sfntly/font.h" +#include "sfntly/port/exception_type.h" + +namespace sfntly { +/****************************************************************************** + * NameTable::NameEntryId class + ******************************************************************************/ +NameTable::NameEntryId::NameEntryId() + : platform_id_(0), + encoding_id_(0), + language_id_(0), + name_id_(0) { +} + +NameTable::NameEntryId::NameEntryId(int32_t platform_id, + int32_t encoding_id, + int32_t language_id, + int32_t name_id) + : platform_id_(platform_id), + encoding_id_(encoding_id), + language_id_(language_id), + name_id_(name_id) { +} + +NameTable::NameEntryId::NameEntryId(const NameTable::NameEntryId& rhs) { + *this = rhs; +} + +const NameTable::NameEntryId& + NameTable::NameEntryId::operator=(const NameTable::NameEntryId& rhs) const { + platform_id_ = rhs.platform_id_; + encoding_id_ = rhs.encoding_id_; + language_id_ = rhs.language_id_; + name_id_ = rhs.name_id_; + return *this; +} + +bool NameTable::NameEntryId::operator==(const NameEntryId& rhs) const { + return platform_id_ == rhs.platform_id_ && + encoding_id_ == rhs.encoding_id_ && + language_id_ == rhs.language_id_ && + name_id_ == rhs.name_id_; +} + +bool NameTable::NameEntryId::operator<(const NameEntryId& rhs) const { + if (platform_id_ != rhs.platform_id_) return platform_id_ < rhs.platform_id_; + if (encoding_id_ != rhs.encoding_id_) return encoding_id_ < rhs.encoding_id_; + if (language_id_ != rhs.language_id_) return language_id_ < rhs.language_id_; + return name_id_ < rhs.name_id_; +} + +/****************************************************************************** + * NameTable::NameEntry class + ******************************************************************************/ +NameTable::NameEntry::NameEntry() { + Init(0, 0, 0, 0, NULL); +} + +NameTable::NameEntry::NameEntry(const NameEntryId& name_entry_id, + const ByteVector& name_bytes) { + Init(name_entry_id.platform_id(), + name_entry_id.encoding_id(), + name_entry_id.language_id(), + name_entry_id.name_id(), + &name_bytes); +} + +NameTable::NameEntry::NameEntry(int32_t platform_id, + int32_t encoding_id, + int32_t language_id, + int32_t name_id, + const ByteVector& name_bytes) { + Init(platform_id, encoding_id, language_id, name_id, &name_bytes); +} + +NameTable::NameEntry::~NameEntry() {} + +ByteVector* NameTable::NameEntry::NameAsBytes() { + return &name_bytes_; +} + +int32_t NameTable::NameEntry::NameBytesLength() { + return name_bytes_.size(); +} + +UChar* NameTable::NameEntry::Name() { + return NameTable::ConvertFromNameBytes(&name_bytes_, + platform_id(), + encoding_id()); +} + +bool NameTable::NameEntry::operator==(const NameEntry& rhs) const { + return (name_entry_id_ == rhs.name_entry_id_ && + name_bytes_ == rhs.name_bytes_); +} + +void NameTable::NameEntry::Init(int32_t platform_id, + int32_t encoding_id, + int32_t language_id, + int32_t name_id, + const ByteVector* name_bytes) { + name_entry_id_ = NameEntryId(platform_id, encoding_id, language_id, name_id); + if (name_bytes) { + name_bytes_ = *name_bytes; + } else { + name_bytes_.clear(); + } +} + +/****************************************************************************** + * NameTable::NameEntryBuilder class + ******************************************************************************/ +NameTable::NameEntryBuilder::NameEntryBuilder() { + Init(0, 0, 0, 0, NULL); +} + +NameTable::NameEntryBuilder::NameEntryBuilder(const NameEntryId& name_entry_id, + const ByteVector& name_bytes) { + Init(name_entry_id.platform_id(), + name_entry_id.encoding_id(), + name_entry_id.language_id(), + name_entry_id.name_id(), + &name_bytes); +} + +NameTable::NameEntryBuilder::NameEntryBuilder( + const NameEntryId& name_entry_id) { + Init(name_entry_id.platform_id(), + name_entry_id.encoding_id(), + name_entry_id.language_id(), + name_entry_id.name_id(), + NULL); +} + +NameTable::NameEntryBuilder::NameEntryBuilder(NameEntry* b) { + Init(b->platform_id(), + b->encoding_id(), + b->language_id(), + b->name_id(), + b->NameAsBytes()); +} + +NameTable::NameEntryBuilder::~NameEntryBuilder() {} + +void NameTable::NameEntryBuilder::SetName(const UChar* name) { + if (name == NULL) { + name_entry_->name_bytes_.clear(); + return; + } + NameTable::ConvertToNameBytes(name, + name_entry_->platform_id(), + name_entry_->encoding_id(), + &name_entry_->name_bytes_); +} + +void NameTable::NameEntryBuilder::SetName(const ByteVector& 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, + int32_t offset, + int32_t length) { + name_entry_->name_bytes_.clear(); + std::copy(name_bytes.begin() + offset, + name_bytes.begin() + offset + length, + name_entry_->name_bytes_.begin()); +} + +void NameTable::NameEntryBuilder::Init(int32_t platform_id, + int32_t encoding_id, + int32_t language_id, + int32_t name_id, + const ByteVector* name_bytes) { + name_entry_ = new NameEntry(); + name_entry_->Init(platform_id, encoding_id, language_id, name_id, name_bytes); +} + +/****************************************************************************** + * NameTable::NameEntryFilterInPlace class (C++ port only) + ******************************************************************************/ +NameTable::NameEntryFilterInPlace::NameEntryFilterInPlace(int32_t platform_id, + int32_t encoding_id, + int32_t language_id, + int32_t name_id) + : platform_id_(platform_id), + encoding_id_(encoding_id), + language_id_(language_id), + name_id_(name_id) { +} + +bool NameTable::NameEntryFilterInPlace::Accept(int32_t platform_id, + int32_t encoding_id, + int32_t language_id, + int32_t name_id) { + return (platform_id_ == platform_id && + encoding_id_ == encoding_id && + language_id_ == language_id && + name_id_ == name_id); +} + +/****************************************************************************** + * NameTable::NameEntryIterator class + ******************************************************************************/ +NameTable::NameEntryIterator::NameEntryIterator(NameTable* table) + : RefIterator(table), + name_index_(0), + filter_(NULL) { +} + +NameTable::NameEntryIterator::NameEntryIterator(NameTable* table, + NameEntryFilter* filter) + : RefIterator(table), + name_index_(0), + filter_(filter) { +} + +bool NameTable::NameEntryIterator::HasNext() { + if (!filter_) { + if (name_index_ < container()->NameCount()) { + return true; + } + return false; + } + for (; name_index_ < container()->NameCount(); ++name_index_) { + if (filter_->Accept(container()->PlatformId(name_index_), + container()->EncodingId(name_index_), + container()->LanguageId(name_index_), + container()->NameId(name_index_))) { + return true; + } + } + return false; +} + +CALLER_ATTACH NameTable::NameEntry* NameTable::NameEntryIterator::Next() { + if (!HasNext()) + return NULL; + return container()->GetNameEntry(name_index_++); +} + +/****************************************************************************** + * NameTable::Builder class + ******************************************************************************/ +NameTable::Builder::Builder(Header* header, WritableFontData* data) + : SubTableContainerTable::Builder(header, data) { +} + +NameTable::Builder::Builder(Header* header, ReadableFontData* data) + : SubTableContainerTable::Builder(header, data) { +} + +CALLER_ATTACH NameTable::Builder* + NameTable::Builder::CreateBuilder(Header* header, + WritableFontData* data) { + Ptr builder; + builder = new NameTable::Builder(header, data); + return builder.Detach(); +} + +void NameTable::Builder::RevertNames() { + name_entry_map_.clear(); + set_model_changed(false); +} + +int32_t NameTable::Builder::BuilderCount() { + GetNameBuilders(); // Ensure name_entry_map_ is built. + return (int32_t)name_entry_map_.size(); +} + +bool NameTable::Builder::Has(int32_t platform_id, + int32_t encoding_id, + int32_t language_id, + int32_t name_id) { + NameEntryId probe(platform_id, encoding_id, language_id, name_id); + GetNameBuilders(); // Ensure name_entry_map_ is built. + return (name_entry_map_.find(probe) != name_entry_map_.end()); +} + +CALLER_ATTACH NameTable::NameEntryBuilder* + NameTable::Builder::NameBuilder(int32_t platform_id, + int32_t encoding_id, + int32_t language_id, + int32_t name_id) { + NameEntryId probe(platform_id, encoding_id, language_id, name_id); + NameEntryBuilderMap builders; + GetNameBuilders(); // Ensure name_entry_map_ is built. + if (name_entry_map_.find(probe) != name_entry_map_.end()) { + return name_entry_map_[probe]; + } + NameEntryBuilderPtr builder = new NameEntryBuilder(probe); + name_entry_map_[probe] = builder; + return builder.Detach(); +} + +bool NameTable::Builder::Remove(int32_t platform_id, + int32_t encoding_id, + int32_t language_id, + int32_t name_id) { + NameEntryId probe(platform_id, encoding_id, language_id, name_id); + GetNameBuilders(); // Ensure name_entry_map_ is built. + NameEntryBuilderMap::iterator position = name_entry_map_.find(probe); + if (position != name_entry_map_.end()) { + name_entry_map_.erase(position); + return true; + } + return false; +} + +CALLER_ATTACH FontDataTable* + NameTable::Builder::SubBuildTable(ReadableFontData* data) { + FontDataTablePtr table = new NameTable(header(), data); + return table.Detach(); +} + +void NameTable::Builder::SubDataSet() { + name_entry_map_.clear(); + set_model_changed(false); +} + +int32_t NameTable::Builder::SubDataSizeToSerialize() { + if (name_entry_map_.empty()) { + return 0; + } + + int32_t size = NameTable::Offset::kNameRecordStart + + name_entry_map_.size() * NameTable::Offset::kNameRecordSize; + for (NameEntryBuilderMap::iterator b = name_entry_map_.begin(), + end = name_entry_map_.end(); + b != end; ++b) { + NameEntryBuilderPtr p = b->second; + NameEntry* entry = p->name_entry(); + size += entry->NameBytesLength(); + } + return size; +} + +bool NameTable::Builder::SubReadyToSerialize() { + return !name_entry_map_.empty(); +} + +int32_t NameTable::Builder::SubSerialize(WritableFontData* new_data) { + int32_t string_table_start_offset = + NameTable::Offset::kNameRecordStart + + name_entry_map_.size() * NameTable::Offset::kNameRecordSize; + + // Header + new_data->WriteUShort(NameTable::Offset::kFormat, 0); + new_data->WriteUShort(NameTable::Offset::kCount, name_entry_map_.size()); + new_data->WriteUShort(NameTable::Offset::kStringOffset, + string_table_start_offset); + int32_t name_record_offset = NameTable::Offset::kNameRecordStart; + int32_t string_offset = 0; + // Note: we offered operator< in NameEntryId, which will be used by std::less, + // and therefore our map will act like TreeMap in Java to provide + // sorted key set. + for (NameEntryBuilderMap::iterator b = name_entry_map_.begin(), + end = name_entry_map_.end(); + b != end; ++b) { + new_data->WriteUShort( + name_record_offset + NameTable::Offset::kNameRecordPlatformId, + b->first.platform_id()); + new_data->WriteUShort( + name_record_offset + NameTable::Offset::kNameRecordEncodingId, + b->first.encoding_id()); + new_data->WriteUShort( + name_record_offset + NameTable::Offset::kNameRecordLanguageId, + b->first.language_id()); + new_data->WriteUShort( + name_record_offset + NameTable::Offset::kNameRecordNameId, + b->first.name_id()); + NameEntry* builder_entry = b->second->name_entry(); + new_data->WriteUShort( + name_record_offset + NameTable::Offset::kNameRecordStringLength, + builder_entry->NameBytesLength()); + new_data->WriteUShort( + name_record_offset + NameTable::Offset::kNameRecordStringOffset, + string_offset); + name_record_offset += NameTable::Offset::kNameRecordSize; + string_offset += new_data->WriteBytes( + string_offset + string_table_start_offset, + builder_entry->NameAsBytes()); + } + + return string_offset + string_table_start_offset; +} + +void NameTable::Builder::Initialize(ReadableFontData* data) { + if (data) { + NameTablePtr table = new NameTable(header(), data); + Ptr name_iter; + name_iter.Attach(table->Iterator()); + while (name_iter->HasNext()) { + NameEntryPtr name_entry; + name_entry.Attach(name_iter->Next()); + NameEntryBuilderPtr name_entry_builder = new NameEntryBuilder(name_entry); + NameEntry* builder_entry = name_entry_builder->name_entry(); + NameEntryId probe = builder_entry->name_entry_id(); + name_entry_map_[probe] = name_entry_builder; + } + } +} + +NameTable::NameEntryBuilderMap* NameTable::Builder::GetNameBuilders() { + if (name_entry_map_.empty()) { + Initialize(InternalReadData()); + } + set_model_changed(); + return &name_entry_map_; +} + +/****************************************************************************** + * NameTable class + ******************************************************************************/ +NameTable::~NameTable() {} + +int32_t NameTable::Format() { + return data_->ReadUShort(Offset::kFormat); +} + +int32_t NameTable::NameCount() { + return data_->ReadUShort(Offset::kCount); +} + +int32_t NameTable::PlatformId(int32_t index) { + return data_->ReadUShort(Offset::kNameRecordPlatformId + + OffsetForNameRecord(index)); +} + +int32_t NameTable::EncodingId(int32_t index) { + return data_->ReadUShort(Offset::kNameRecordEncodingId + + OffsetForNameRecord(index)); +} + +int32_t NameTable::LanguageId(int32_t index) { + return data_->ReadUShort(Offset::kNameRecordLanguageId + + OffsetForNameRecord(index)); +} + +int32_t NameTable::NameId(int32_t index) { + return data_->ReadUShort(Offset::kNameRecordNameId + + OffsetForNameRecord(index)); +} + +void NameTable::NameAsBytes(int32_t index, ByteVector* b) { + assert(b); + int32_t length = NameLength(index); + b->clear(); + b->resize(length); + data_->ReadBytes(NameOffset(index), &((*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) { + assert(b); + NameEntryPtr entry; + entry.Attach(GetNameEntry(platform_id, encoding_id, language_id, name_id)); + if (entry) { + ByteVector* name = entry->NameAsBytes(); + std::copy(name->begin(), name->end(), b->begin()); + } +} + +UChar* NameTable::Name(int32_t index) { + ByteVector b; + NameAsBytes(index, &b); + return ConvertFromNameBytes(&b, PlatformId(index), EncodingId(index)); +} + +UChar* NameTable::Name(int32_t platform_id, + int32_t encoding_id, + int32_t language_id, + int32_t name_id) { + NameEntryPtr entry; + entry.Attach(GetNameEntry(platform_id, encoding_id, language_id, name_id)); + if (entry) { + return entry->Name(); + } + return NULL; +} + +CALLER_ATTACH NameTable::NameEntry* NameTable::GetNameEntry(int32_t index) { + ByteVector b; + NameAsBytes(index, &b); + NameEntryPtr instance = new NameEntry(PlatformId(index), + EncodingId(index), + LanguageId(index), + NameId(index), b); + return instance.Detach(); +} + +CALLER_ATTACH NameTable::NameEntry* NameTable::GetNameEntry(int32_t platform_id, + int32_t encoding_id, + int32_t language_id, + int32_t name_id) { + NameTable::NameEntryFilterInPlace + filter(platform_id, encoding_id, language_id, name_id); + Ptr name_entry_iter; + name_entry_iter.Attach(Iterator(&filter)); + NameEntryPtr result; + if (name_entry_iter->HasNext()) { + result = name_entry_iter->Next(); + } + return result; +} + +CALLER_ATTACH NameTable::NameEntryIterator* NameTable::Iterator() { + Ptr output = new NameTable::NameEntryIterator(this); + return output.Detach(); +} + +CALLER_ATTACH +NameTable::NameEntryIterator* NameTable::Iterator(NameEntryFilter* filter) { + Ptr output = + new NameTable::NameEntryIterator(this, filter); + return output.Detach(); +} + +NameTable::NameTable(Header* header, ReadableFontData* data) + : SubTableContainerTable(header, data) {} + +int32_t NameTable::StringOffset() { + return data_->ReadUShort(Offset::kStringOffset); +} + +int32_t NameTable::OffsetForNameRecord(int32_t index) { + return Offset::kNameRecordStart + index * Offset::kNameRecordSize; +} + +int32_t NameTable::NameLength(int32_t index) { + return data_->ReadUShort(Offset::kNameRecordStringLength + + OffsetForNameRecord(index)); +} + +int32_t NameTable::NameOffset(int32_t index) { + return data_->ReadUShort(Offset::kNameRecordStringOffset + + OffsetForNameRecord(index)) + StringOffset(); +} + +const char* NameTable::GetEncodingName(int32_t platform_id, + int32_t encoding_id) { + switch (platform_id) { + case PlatformId::kUnicode: + return "UTF-16BE"; + case PlatformId::kMacintosh: + switch (encoding_id) { + case MacintoshEncodingId::kRoman: + return "MacRoman"; + case MacintoshEncodingId::kJapanese: + return "Shift-JIS"; + case MacintoshEncodingId::kChineseTraditional: + return "Big5"; + case MacintoshEncodingId::kKorean: + return "EUC-KR"; + case MacintoshEncodingId::kArabic: + return "MacArabic"; + case MacintoshEncodingId::kHebrew: + return "MacHebrew"; + case MacintoshEncodingId::kGreek: + return "MacGreek"; + case MacintoshEncodingId::kRussian: + return "MacCyrillic"; + case MacintoshEncodingId::kRSymbol: + return "MacSymbol"; + case MacintoshEncodingId::kThai: + return "MacThai"; + case MacintoshEncodingId::kChineseSimplified: + return "EUC-CN"; + default: // Note: unknown/unconfirmed cases are not ported. + break; + } + break; + case PlatformId::kISO: + break; + case PlatformId::kWindows: + switch (encoding_id) { + case WindowsEncodingId::kSymbol: + case WindowsEncodingId::kUnicodeUCS2: + return "UTF-16BE"; + case WindowsEncodingId::kShiftJIS: + return "windows-933"; + case WindowsEncodingId::kPRC: + return "windows-936"; + case WindowsEncodingId::kBig5: + return "windows-950"; + case WindowsEncodingId::kWansung: + return "windows-949"; + case WindowsEncodingId::kJohab: + return "ms1361"; + case WindowsEncodingId::kUnicodeUCS4: + return "UCS-4"; + } + break; + case PlatformId::kCustom: + break; + default: + break; + } + return NULL; +} + +UConverter* NameTable::GetCharset(int32_t platform_id, int32_t encoding_id) { + UErrorCode error_code = U_ZERO_ERROR; + UConverter* conv = ucnv_open(GetEncodingName(platform_id, encoding_id), + &error_code); + if (U_SUCCESS(error_code)) { + return conv; + } + + if (conv) { + ucnv_close(conv); + } + return NULL; +} + +void NameTable::ConvertToNameBytes(const UChar* name, + int32_t platform_id, + int32_t encoding_id, + ByteVector* b) { + assert(b); + assert(name); + b->clear(); + UConverter* cs = GetCharset(platform_id, encoding_id); + if (cs == NULL) { + return; + } + + // Preflight to get buffer size. + UErrorCode error_code = U_ZERO_ERROR; + int32_t length = ucnv_fromUChars(cs, NULL, 0, name, -1, &error_code); + b->resize(length + 4); // The longest termination "\0" is 4 bytes. + memset(&((*b)[0]), 0, length + 4); + error_code = U_ZERO_ERROR; + ucnv_fromUChars(cs, + reinterpret_cast(&((*b)[0])), + length + 4, + name, + -1, + &error_code); + if (!U_SUCCESS(error_code)) { + b->clear(); + } + ucnv_close(cs); +} + +UChar* NameTable::ConvertFromNameBytes(ByteVector* name_bytes, + int32_t platform_id, + int32_t encoding_id) { + if (name_bytes == NULL) { + return NULL; + } + UConverter* cs = GetCharset(platform_id, encoding_id); + UErrorCode error_code = U_ZERO_ERROR; + if (cs == NULL) { + char buffer[11] = {0}; +#if defined (WIN32) + _itoa_s(platform_id, buffer, 16); +#else + snprintf(buffer, sizeof(buffer), "%x", platform_id); +#endif + UChar* result = new UChar[12]; + memset(result, 0, sizeof(UChar) * 12); + cs = ucnv_open("utf-8", &error_code); + if (U_SUCCESS(error_code)) { + ucnv_toUChars(cs, result, 12, buffer, 11, &error_code); + ucnv_close(cs); + if (U_SUCCESS(error_code)) { + return result; + } + } + delete[] result; + return NULL; + } + + // No preflight needed here, we will be bigger. + UChar* output_buffer = new UChar[name_bytes->size() + 1]; + memset(output_buffer, 0, sizeof(UChar) * (name_bytes->size() + 1)); + int32_t length = ucnv_toUChars(cs, + output_buffer, + name_bytes->size(), + reinterpret_cast(&((*name_bytes)[0])), + name_bytes->size(), + &error_code); + ucnv_close(cs); + if (length > 0) { + return output_buffer; + } + + delete[] output_buffer; + return NULL; +} + +} // namespace sfntly diff --git a/src/sfntly/src/sfntly/table/core/name_table.h b/src/sfntly/src/sfntly/table/core/name_table.h new file mode 100644 index 000000000000..01d3b290761e --- /dev/null +++ b/src/sfntly/src/sfntly/table/core/name_table.h @@ -0,0 +1,744 @@ +/* + * 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. + */ + +#ifndef SFNTLY_CPP_SRC_SFNTLY_TABLE_CORE_NAME_TABLE_H_ +#define SFNTLY_CPP_SRC_SFNTLY_TABLE_CORE_NAME_TABLE_H_ + +// Must include this before ICU to avoid stdint redefinition issue. +#include "sfntly/port/type.h" + +#include +#include + +#include +#include + +#include "sfntly/port/java_iterator.h" +#include "sfntly/table/subtable_container_table.h" + +namespace sfntly { + +// The following code implements the name table defined in TTF/OTF spec, which +// can be found at http://www.microsoft.com/typography/otspec/name.htm. + +// Name IDs defined in TTF/OTF spec. +struct NameId { + enum { + kUnknown = -1, + kCopyrightNotice = 0, + kFontFamilyName = 1, + kFontSubfamilyName = 2, + kUniqueFontIdentifier = 3, + kFullFontName = 4, + kVersionString = 5, + kPostscriptName = 6, + kTrademark = 7, + kManufacturerName = 8, + kDesigner = 9, + kDescription = 10, + kVendorURL = 11, + kDesignerURL = 12, + kLicenseDescription = 13, + kLicenseInfoURL = 14, + kReserved15 = 15, + kPreferredFamily = 16, + kPreferredSubfamily = 17, + kCompatibleFullName = 18, + kSampleText = 19, + kPostscriptCID = 20, + kWWSFamilyName = 21, + kWWSSubfamilyName = 22 + }; +}; + +// Unicode language IDs used in Name Records. +struct UnicodeLanguageId { + enum { + kUnknown = -1, + kAll = 0 + }; +}; + +// Macintosh Language IDs (platform ID = 1) +struct MacintoshLanguageId { + enum { + kUnknown = -1, + kEnglish = 0, + kFrench = 1, + kGerman = 2, + kItalian = 3, + kDutch = 4, + kSwedish = 5, + kSpanish = 6, + kDanish = 7, + kPortuguese = 8, + kNorwegian = 9, + kHebrew = 10, + kJapanese = 11, + kArabic = 12, + kFinnish = 13, + kGreek = 14, + kIcelandic = 15, + kMaltese = 16, + kTurkish = 17, + kCroatian = 18, + kChinese_Traditional = 19, + kUrdu = 20, + kHindi = 21, + kThai = 22, + kKorean = 23, + kLithuanian = 24, + kPolish = 25, + kHungarian = 26, + kEstonian = 27, + kLatvian = 28, + kSami = 29, + kFaroese = 30, + kFarsiPersian = 31, + kRussian = 32, + kChinese_Simplified = 33, + kFlemish = 34, + kIrishGaelic = 35, + kAlbanian = 36, + kRomanian = 37, + kCzech = 38, + kSlovak = 39, + kSlovenian = 40, + kYiddish = 41, + kSerbian = 42, + kMacedonian = 43, + kBulgarian = 44, + kUkrainian = 45, + kByelorussian = 46, + kUzbek = 47, + kKazakh = 48, + kAzerbaijani_Cyrillic = 49, + kAzerbaijani_Arabic = 50, + kArmenian = 51, + kGeorgian = 52, + kMoldavian = 53, + kKirghiz = 54, + kTajiki = 55, + kTurkmen = 56, + kMongolian_Mongolian = 57, + kMongolian_Cyrillic = 58, + kPashto = 59, + kKurdish = 60, + kKashmiri = 61, + kSindhi = 62, + kTibetan = 63, + kNepali = 64, + kSanskrit = 65, + kMarathi = 66, + kBengali = 67, + kAssamese = 68, + kGujarati = 69, + kPunjabi = 70, + kOriya = 71, + kMalayalam = 72, + kKannada = 73, + kTamil = 74, + kTelugu = 75, + kSinhalese = 76, + kBurmese = 77, + kKhmer = 78, + kLao = 79, + kVietnamese = 80, + kIndonesian = 81, + kTagalong = 82, + kMalay_Roman = 83, + kMalay_Arabic = 84, + kAmharic = 85, + kTigrinya = 86, + kGalla = 87, + kSomali = 88, + kSwahili = 89, + kKinyarwandaRuanda = 90, + kRundi = 91, + kNyanjaChewa = 92, + kMalagasy = 93, + kEsperanto = 94, + kWelsh = 128, + kBasque = 129, + kCatalan = 130, + kLatin = 131, + kQuenchua = 132, + kGuarani = 133, + kAymara = 134, + kTatar = 135, + kUighur = 136, + kDzongkha = 137, + kJavanese_Roman = 138, + kSundanese_Roman = 139, + kGalician = 140, + kAfrikaans = 141, + kBreton = 142, + kInuktitut = 143, + kScottishGaelic = 144, + kManxGaelic = 145, + kIrishGaelic_WithDotAbove = 146, + kTongan = 147, + kGreek_Polytonic = 148, + kGreenlandic = 149, + kAzerbaijani_Roman = 150 + }; +}; + +// Windows Language IDs (platformID = 3) +struct WindowsLanguageId { + enum { + kUnknown = -1, + kAfrikaans_SouthAfrica = 0x0436, + kAlbanian_Albania = 0x041C, + kAlsatian_France = 0x0484, + kAmharic_Ethiopia = 0x045E, + kArabic_Algeria = 0x1401, + kArabic_Bahrain = 0x3C01, + kArabic_Egypt = 0x0C01, + kArabic_Iraq = 0x0801, + kArabic_Jordan = 0x2C01, + kArabic_Kuwait = 0x3401, + kArabic_Lebanon = 0x3001, + kArabic_Libya = 0x1001, + kArabic_Morocco = 0x1801, + kArabic_Oman = 0x2001, + kArabic_Qatar = 0x4001, + kArabic_SaudiArabia = 0x0401, + kArabic_Syria = 0x2801, + kArabic_Tunisia = 0x1C01, + kArabic_UAE = 0x3801, + kArabic_Yemen = 0x2401, + kArmenian_Armenia = 0x042B, + kAssamese_India = 0x044D, + kAzeri_Cyrillic_Azerbaijan = 0x082C, + kAzeri_Latin_Azerbaijan = 0x042C, + kBashkir_Russia = 0x046D, + kBasque_Basque = 0x042D, + kBelarusian_Belarus = 0x0423, + kBengali_Bangladesh = 0x0845, + kBengali_India = 0x0445, + kBosnian_Cyrillic_BosniaAndHerzegovina = 0x201A, + kBosnian_Latin_BosniaAndHerzegovina = 0x141A, + kBreton_France = 0x047E, + kBulgarian_Bulgaria = 0x0402, + kCatalan_Catalan = 0x0403, + kChinese_HongKongSAR = 0x0C04, + kChinese_MacaoSAR = 0x1404, + kChinese_PeoplesRepublicOfChina = 0x0804, + kChinese_Singapore = 0x1004, + kChinese_Taiwan = 0x0404, + kCorsican_France = 0x0483, + kCroatian_Croatia = 0x041A, + kCroatian_Latin_BosniaAndHerzegovina = 0x101A, + kCzech_CzechRepublic = 0x0405, + kDanish_Denmark = 0x0406, + kDari_Afghanistan = 0x048C, + kDivehi_Maldives = 0x0465, + kDutch_Belgium = 0x0813, + kDutch_Netherlands = 0x0413, + kEnglish_Australia = 0x0C09, + kEnglish_Belize = 0x2809, + kEnglish_Canada = 0x1009, + kEnglish_Caribbean = 0x2409, + kEnglish_India = 0x4009, + kEnglish_Ireland = 0x1809, + kEnglish_Jamaica = 0x2009, + kEnglish_Malaysia = 0x4409, + kEnglish_NewZealand = 0x1409, + kEnglish_RepublicOfThePhilippines = 0x3409, + kEnglish_Singapore = 0x4809, + kEnglish_SouthAfrica = 0x1C09, + kEnglish_TrinidadAndTobago = 0x2C09, + kEnglish_UnitedKingdom = 0x0809, + kEnglish_UnitedStates = 0x0409, + kEnglish_Zimbabwe = 0x3009, + kEstonian_Estonia = 0x0425, + kFaroese_FaroeIslands = 0x0438, + kFilipino_Philippines = 0x0464, + kFinnish_Finland = 0x040B, + kFrench_Belgium = 0x080C, + kFrench_Canada = 0x0C0C, + kFrench_France = 0x040C, + kFrench_Luxembourg = 0x140c, + kFrench_PrincipalityOfMonoco = 0x180C, + kFrench_Switzerland = 0x100C, + kFrisian_Netherlands = 0x0462, + kGalician_Galician = 0x0456, + kGeorgian_Georgia = 0x0437, + kGerman_Austria = 0x0C07, + kGerman_Germany = 0x0407, + kGerman_Liechtenstein = 0x1407, + kGerman_Luxembourg = 0x1007, + kGerman_Switzerland = 0x0807, + kGreek_Greece = 0x0408, + kGreenlandic_Greenland = 0x046F, + kGujarati_India = 0x0447, + kHausa_Latin_Nigeria = 0x0468, + kHebrew_Israel = 0x040D, + kHindi_India = 0x0439, + kHungarian_Hungary = 0x040E, + kIcelandic_Iceland = 0x040F, + kIgbo_Nigeria = 0x0470, + kIndonesian_Indonesia = 0x0421, + kInuktitut_Canada = 0x045D, + kInuktitut_Latin_Canada = 0x085D, + kIrish_Ireland = 0x083C, + kisiXhosa_SouthAfrica = 0x0434, + kisiZulu_SouthAfrica = 0x0435, + kItalian_Italy = 0x0410, + kItalian_Switzerland = 0x0810, + kJapanese_Japan = 0x0411, + kKannada_India = 0x044B, + kKazakh_Kazakhstan = 0x043F, + kKhmer_Cambodia = 0x0453, + kKiche_Guatemala = 0x0486, + kKinyarwanda_Rwanda = 0x0487, + kKiswahili_Kenya = 0x0441, + kKonkani_India = 0x0457, + kKorean_Korea = 0x0412, + kKyrgyz_Kyrgyzstan = 0x0440, + kLao_LaoPDR = 0x0454, + kLatvian_Latvia = 0x0426, + kLithuanian_Lithuania = 0x0427, + kLowerSorbian_Germany = 0x082E, + kLuxembourgish_Luxembourg = 0x046E, + kMacedonian_FYROM_FormerYugoslavRepublicOfMacedonia = 0x042F, + kMalay_BruneiDarussalam = 0x083E, + kMalay_Malaysia = 0x043E, + kMalayalam_India = 0x044C, + kMaltese_Malta = 0x043A, + kMaori_NewZealand = 0x0481, + kMapudungun_Chile = 0x047A, + kMarathi_India = 0x044E, + kMohawk_Mohawk = 0x047C, + kMongolian_Cyrillic_Mongolia = 0x0450, + kMongolian_Traditional_PeoplesRepublicOfChina = 0x0850, + kNepali_Nepal = 0x0461, + kNorwegian_Bokmal_Norway = 0x0414, + kNorwegian_Nynorsk_Norway = 0x0814, + kOccitan_France = 0x0482, + kOriya_India = 0x0448, + kPashto_Afghanistan = 0x0463, + kPolish_Poland = 0x0415, + kPortuguese_Brazil = 0x0416, + kPortuguese_Portugal = 0x0816, + kPunjabi_India = 0x0446, + kQuechua_Bolivia = 0x046B, + kQuechua_Ecuador = 0x086B, + kQuechua_Peru = 0x0C6B, + kRomanian_Romania = 0x0418, + kRomansh_Switzerland = 0x0417, + kRussian_Russia = 0x0419, + kSami_Inari_Finland = 0x243B, + kSami_Lule_Norway = 0x103B, + kSami_Lule_Sweden = 0x143B, + kSami_Northern_Finland = 0x0C3B, + kSami_Northern_Norway = 0x043B, + kSami_Northern_Sweden = 0x083B, + kSami_Skolt_Finland = 0x203B, + kSami_Southern_Norway = 0x183B, + kSami_Southern_Sweden = 0x1C3B, + kSanskrit_India = 0x044F, + kSerbian_Cyrillic_BosniaAndHerzegovina = 0x1C1A, + kSerbian_Cyrillic_Serbia = 0x0C1A, + kSerbian_Latin_BosniaAndHerzegovina = 0x181A, + kSerbian_Latin_Serbia = 0x081A, + kSesothoSaLeboa_SouthAfrica = 0x046C, + kSetswana_SouthAfrica = 0x0432, + kSinhala_SriLanka = 0x045B, + kSlovak_Slovakia = 0x041B, + kSlovenian_Slovenia = 0x0424, + kSpanish_Argentina = 0x2C0A, + kSpanish_Bolivia = 0x400A, + kSpanish_Chile = 0x340A, + kSpanish_Colombia = 0x240A, + kSpanish_CostaRica = 0x140A, + kSpanish_DominicanRepublic = 0x1C0A, + kSpanish_Ecuador = 0x300A, + kSpanish_ElSalvador = 0x440A, + kSpanish_Guatemala = 0x100A, + kSpanish_Honduras = 0x480A, + kSpanish_Mexico = 0x080A, + kSpanish_Nicaragua = 0x4C0A, + kSpanish_Panama = 0x180A, + kSpanish_Paraguay = 0x3C0A, + kSpanish_Peru = 0x280A, + kSpanish_PuertoRico = 0x500A, + kSpanish_ModernSort_Spain = 0x0C0A, + kSpanish_TraditionalSort_Spain = 0x040A, + kSpanish_UnitedStates = 0x540A, + kSpanish_Uruguay = 0x380A, + kSpanish_Venezuela = 0x200A, + kSweden_Finland = 0x081D, + kSwedish_Sweden = 0x041D, + kSyriac_Syria = 0x045A, + kTajik_Cyrillic_Tajikistan = 0x0428, + kTamazight_Latin_Algeria = 0x085F, + kTamil_India = 0x0449, + kTatar_Russia = 0x0444, + kTelugu_India = 0x044A, + kThai_Thailand = 0x041E, + kTibetan_PRC = 0x0451, + kTurkish_Turkey = 0x041F, + kTurkmen_Turkmenistan = 0x0442, + kUighur_PRC = 0x0480, + kUkrainian_Ukraine = 0x0422, + kUpperSorbian_Germany = 0x042E, + kUrdu_IslamicRepublicOfPakistan = 0x0420, + kUzbek_Cyrillic_Uzbekistan = 0x0843, + kUzbek_Latin_Uzbekistan = 0x0443, + kVietnamese_Vietnam = 0x042A, + kWelsh_UnitedKingdom = 0x0452, + kWolof_Senegal = 0x0448, + kYakut_Russia = 0x0485, + kYi_PRC = 0x0478, + kYoruba_Nigeria = 0x046A + }; +}; + +class NameTable : public SubTableContainerTable, public RefCounted { + public: + // Unique identifier for a given name record. + class NameEntryId { + public: + NameEntryId(); // C++ port only, must provide default constructor. + NameEntryId(int32_t platform_id, int32_t encoding_id, int32_t language_id, + int32_t name_id); + NameEntryId(const NameEntryId&); + // Make gcc -Wnon-virtual-dtor happy. + virtual ~NameEntryId() {} + + int32_t platform_id() const { return platform_id_; } + int32_t encoding_id() const { return encoding_id_; } + int32_t language_id() const { return language_id_; } + int32_t name_id() const { return name_id_; } + + const NameEntryId& operator=(const NameEntryId& rhs) const; + bool operator==(const NameEntryId& rhs) const; + bool operator<(const NameEntryId& rhs) const; + + // UNIMPLEMENTED: int hashCode() + // String toString() + + private: + mutable int32_t platform_id_; + mutable int32_t encoding_id_; + mutable int32_t language_id_; + mutable int32_t name_id_; + }; + + class NameEntryBuilder; + + // Class to represent a name entry in the name table. + class NameEntry : public RefCounted { + public: + NameEntry(); + NameEntry(const NameEntryId& name_entry_id, const ByteVector& name_bytes); + NameEntry(int32_t platform_id, + int32_t encoding_id, + int32_t language_id, + int32_t name_id, + const ByteVector& name_bytes); + virtual ~NameEntry(); + + NameEntryId& name_entry_id() { return name_entry_id_; } + int32_t platform_id() const { return name_entry_id_.platform_id(); } + int32_t encoding_id() const { return name_entry_id_.encoding_id(); } + int32_t language_id() const { return name_entry_id_.language_id(); } + int32_t name_id() const { return name_entry_id_.name_id(); } + + // Get the bytes for name. Returned pointer is the address of private + // member of this class, do not attempt to delete. + ByteVector* NameAsBytes(); + + // C++ port only: get the length of NameAsBytes. + int32_t NameBytesLength(); + + // Returns the name in Unicode as UChar array. + // Note: ICU UChar* convention requires caller to delete[] it. + UChar* Name(); + bool operator==(const NameEntry& rhs) const; + + // UNIMPLEMENTED: String toString() + // int hashCode() + + private: + void Init(int32_t platform_id, int32_t encoding_id, int32_t language_id, + int32_t name_id, const ByteVector* name_bytes); + + NameEntryId name_entry_id_; + int32_t length_; + ByteVector name_bytes_; + + friend class NameEntryBuilder; + }; + + // Builder of a name entry. + // C++ port: original Java hierarchy inherits from NameEntry. In C++ port, we + // opted not doing so to avoid ref count issues and nasty protected members. + class NameEntryBuilder : public RefCounted { + public: + NameEntryBuilder(); + NameEntryBuilder(const NameEntryId& name_entry_id, + const ByteVector& 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, + int32_t offset, + int32_t length); + + // C++ port only. CALLER_ATTACH is not added because the lifetime shall be + // controlled by this class, therefore the caller shall not increase the ref + // count. + NameEntry* name_entry() { return name_entry_; } + + private: + void Init(int32_t platform_id, int32_t encoding_id, int32_t language_id, + int32_t name_id, const ByteVector* name_bytes); + + Ptr name_entry_; + }; + typedef std::map > NameEntryBuilderMap; + + // An interface for a filter to use with the name entry iterator. This allows + // name entries to be iterated and only those acceptable to the filter will be + // returned. + class NameEntryFilter { + public: + virtual bool Accept(int32_t platform_id, + int32_t encoding_id, + int32_t language_id, + int32_t name_id) = 0; + // Make gcc -Wnon-virtual-dtor happy. + virtual ~NameEntryFilter() {} + }; + + // C++ port only: an in-place filter to mimic Java Iterator's filtering. + class NameEntryFilterInPlace : public NameEntryFilter { + public: + NameEntryFilterInPlace(int32_t platform_id, + int32_t encoding_id, + int32_t language_id, + int32_t name_id); + // Make gcc -Wnon-virtual-dtor happy. + virtual ~NameEntryFilterInPlace() {} + + virtual bool Accept(int32_t platform_id, + int32_t encoding_id, + int32_t language_id, + int32_t name_id); + + private: + int32_t platform_id_; + int32_t encoding_id_; + int32_t language_id_; + int32_t name_id_; + }; + + class NameEntryIterator : public RefIterator { + public: + // If filter is NULL, filter through all tables. + explicit NameEntryIterator(NameTable* table); + NameEntryIterator(NameTable* table, NameEntryFilter* filter); + virtual ~NameEntryIterator() {} + + virtual bool HasNext(); + virtual CALLER_ATTACH NameEntry* Next(); + + private: + int32_t name_index_; + NameEntryFilter* filter_; + }; + + // The builder to construct name table for outputting. + class Builder : public SubTableContainerTable::Builder, + public RefCounted { + public: + // Constructor scope altered to public because C++ does not allow base + // class to instantiate derived class with protected constructors. + Builder(Header* header, WritableFontData* data); + Builder(Header* header, ReadableFontData* data); + + static CALLER_ATTACH Builder* CreateBuilder(Header* header, + WritableFontData* data); + + // Revert the name builders for the name table to the last version that came + // from data. + void RevertNames(); + + // Number of name entry builders contained. + int32_t BuilderCount(); + + // Note: For C++ port, clear() is not implemented. The clear() function + // implies completely remove name entry builders, which is easy in + // Java but will take a lot of efforts in C++ to release the builders + // nicely and correctly. + // TODO(arthurhsu): IMPLEMENT + // Clear the name builders for the name table. + // void clear(); + + // Check the existance of a name entry builder by key. + bool Has(int32_t platform_id, int32_t encoding_id, int32_t language_id, + int32_t name_id); + + // Get name entry builder by key. + CALLER_ATTACH NameEntryBuilder* NameBuilder(int32_t platform_id, + int32_t encoding_id, int32_t language_id, int32_t name_id); + + // Remove name entry builder by key. + bool Remove(int32_t platform_id, int32_t encoding_id, int32_t language_id, + int32_t name_id); + + // FontDataTable::Builder API implementation + virtual CALLER_ATTACH FontDataTable* SubBuildTable(ReadableFontData* data); + virtual void SubDataSet(); + virtual int32_t SubDataSizeToSerialize(); + virtual bool SubReadyToSerialize(); + virtual int32_t SubSerialize(WritableFontData* new_data); + + private: + void Initialize(ReadableFontData* data); + NameEntryBuilderMap* GetNameBuilders(); + + // Note: callers should use the getter funtion provided above to ensure that + // this is lazily initialized instead of accessing directly. + NameEntryBuilderMap name_entry_map_; + }; + + /**************************************************************************** + * public methods of NameTable class + ****************************************************************************/ + virtual ~NameTable(); + + // Get the format used in the name table. + virtual int32_t Format(); + + // Get the number of names in the name table. + virtual int32_t NameCount(); + + // Get the platform id for the given name record. + virtual int32_t PlatformId(int32_t index); + + // Get the encoding id for the given name record. + // see MacintoshEncodingId, WindowsEncodingId, UnicodeEncodingId + virtual int32_t EncodingId(int32_t index); + + // Get the language id for the given name record. + virtual int32_t LanguageId(int32_t index); + + // Get the name id for given name record. + virtual int32_t NameId(int32_t index); + + // 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 platform_id, int32_t encoding_id, + int32_t language_id, int32_t name_id, + ByteVector* 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 + // UChar* will be returned. + // Note: ICU UChar* convention requires caller to delete[] it. + virtual UChar* Name(int32_t index); + + // Get the name as a UChar* for the specified name. If there is no entry for + // the requested name then NULL is returned. If there is no encoding + // conversion available for the name then a best attempt UChar* will be + // returned. + // Note: ICU UChar* convention requires caller to delete[] it. + virtual UChar* Name(int32_t platform_id, int32_t encoding_id, + int32_t language_id, int32_t name_id); + + // Note: These functions are renamed in C++ port. Their original Java name is + // nameEntry(). + virtual CALLER_ATTACH NameEntry* GetNameEntry(int32_t index); + virtual CALLER_ATTACH NameEntry* GetNameEntry(int32_t platform_id, + int32_t encoding_id, int32_t language_id, int32_t name_id); + + // Note: Not implemented in C++ port due to complexity and low usage. + // virtual void names(std::set*); + + // Get the iterator to iterate through all name entries. + virtual CALLER_ATTACH NameEntryIterator* Iterator(); + virtual CALLER_ATTACH NameEntryIterator* Iterator(NameEntryFilter* filter); + + private: + struct Offset { + enum { + kFormat = 0, + kCount = 2, + kStringOffset = 4, + kNameRecordStart = 6, + + // Format 1 - offset from the end of the name records + kLangTagCount = 0, + kLangTagRecord = 2, + + kNameRecordSize = 12, + // Name Records + kNameRecordPlatformId = 0, + kNameRecordEncodingId = 2, + kNameRecordLanguageId = 4, + kNameRecordNameId = 6, + kNameRecordStringLength = 8, + kNameRecordStringOffset = 10 + }; + }; + + // The table shall be constructed using Builder, no direct instantiation. + NameTable(Header* header, ReadableFontData* data); + + // Get the offset to the string data in the name table. + int32_t StringOffset(); + + // Get the offset for the given name record. + int32_t OffsetForNameRecord(int32_t index); + + // Get the length of the string data for the given name record. + int32_t NameLength(int32_t index); + + // Get the offset of the string data for the given name record. + int32_t NameOffset(int32_t index); + + // Note: string literals are returned. Caller shall not attempt to manipulate + // the returned pointer. + static const char* GetEncodingName(int32_t platform_id, int32_t encoding_id); + + // 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 + // erased and replaced with converted name bytes. + static void ConvertToNameBytes(const UChar* name, int32_t platform_id, + int32_t encoding_id, ByteVector* b); + + // Note: ICU UChar* convention requires caller to delete[] it. + static UChar* ConvertFromNameBytes(ByteVector* name_bytes, + int32_t platform_id, int32_t encoding_id); +}; // class NameTable +typedef Ptr NameTablePtr; +typedef Ptr NameEntryPtr; +typedef Ptr NameTableBuilderPtr; +typedef Ptr NameEntryBuilderPtr; + +} // namespace sfntly + +#endif // SFNTLY_CPP_SRC_SFNTLY_TABLE_CORE_NAME_TABLE_H_ diff --git a/src/sfntly/src/sfntly/table/core/os2_table.cc b/src/sfntly/src/sfntly/table/core/os2_table.cc new file mode 100644 index 000000000000..7ca9d9a4fd17 --- /dev/null +++ b/src/sfntly/src/sfntly/table/core/os2_table.cc @@ -0,0 +1,608 @@ +/* + * 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. + */ + +#include "sfntly/table/core/os2_table.h" + +namespace sfntly { +/****************************************************************************** + * Constants + ******************************************************************************/ +const int64_t CodePageRange::kLatin1_1252 = (int64_t)1 << 0; +const int64_t CodePageRange::kLatin2_1250 = (int64_t)1 << (int64_t)1; +const int64_t CodePageRange::kCyrillic_1251 = (int64_t)1 << 2; +const int64_t CodePageRange::kGreek_1253 = (int64_t)1 << 3; +const int64_t CodePageRange::kTurkish_1254 = (int64_t)1 << 4; +const int64_t CodePageRange::kHebrew_1255 = (int64_t)1 << 5; +const int64_t CodePageRange::kArabic_1256 = (int64_t)1 << 6; +const int64_t CodePageRange::kWindowsBaltic_1257 = (int64_t)1 << 7; +const int64_t CodePageRange::kVietnamese_1258 = (int64_t)1 << 8; +const int64_t CodePageRange::kAlternateANSI9 = (int64_t)1 << 9; +const int64_t CodePageRange::kAlternateANSI10 = (int64_t)1 << 10; +const int64_t CodePageRange::kAlternateANSI11 = (int64_t)1 << 11; +const int64_t CodePageRange::kAlternateANSI12 = (int64_t)1 << 12; +const int64_t CodePageRange::kAlternateANSI13 = (int64_t)1 << 13; +const int64_t CodePageRange::kAlternateANSI14 = (int64_t)1 << 14; +const int64_t CodePageRange::kAlternateANSI15 = (int64_t)1 << 15; +const int64_t CodePageRange::kThai_874 = (int64_t)1 << 16; +const int64_t CodePageRange::kJapanJIS_932 = (int64_t)1 << 17; +const int64_t CodePageRange::kChineseSimplified_936 = (int64_t)1 << 18; +const int64_t CodePageRange::kKoreanWansung_949 = (int64_t)1 << 19; +const int64_t CodePageRange::kChineseTraditional_950 = (int64_t)1 << 20; +const int64_t CodePageRange::kKoreanJohab_1361 = (int64_t)1 << 21; +const int64_t CodePageRange::kAlternateANSI22 = (int64_t)1 << 22; +const int64_t CodePageRange::kAlternateANSI23 = (int64_t)1 << 23; +const int64_t CodePageRange::kAlternateANSI24 = (int64_t)1 << 24; +const int64_t CodePageRange::kAlternateANSI25 = (int64_t)1 << 25; +const int64_t CodePageRange::kAlternateANSI26 = (int64_t)1 << 26; +const int64_t CodePageRange::kAlternateANSI27 = (int64_t)1 << 27; +const int64_t CodePageRange::kAlternateANSI28 = (int64_t)1 << 28; +const int64_t CodePageRange::kMacintoshCharacterSet = (int64_t)1 << 29; +const int64_t CodePageRange::kOEMCharacterSet = (int64_t)1 << 30; +const int64_t CodePageRange::kSymbolCharacterSet = (int64_t)1 << 31; +const int64_t CodePageRange::kReservedForOEM32 = (int64_t)1 << 32; +const int64_t CodePageRange::kReservedForOEM33 = (int64_t)1 << 33; +const int64_t CodePageRange::kReservedForOEM34 = (int64_t)1 << 34; +const int64_t CodePageRange::kReservedForOEM35 = (int64_t)1 << 35; +const int64_t CodePageRange::kReservedForOEM36 = (int64_t)1 << 36; +const int64_t CodePageRange::kReservedForOEM37 = (int64_t)1 << 37; +const int64_t CodePageRange::kReservedForOEM38 = (int64_t)1 << 38; +const int64_t CodePageRange::kReservedForOEM39 = (int64_t)1 << 39; +const int64_t CodePageRange::kReservedForOEM40 = (int64_t)1 << 40; +const int64_t CodePageRange::kReservedForOEM41 = (int64_t)1 << 41; +const int64_t CodePageRange::kReservedForOEM42 = (int64_t)1 << 42; +const int64_t CodePageRange::kReservedForOEM43 = (int64_t)1 << 43; +const int64_t CodePageRange::kReservedForOEM44 = (int64_t)1 << 44; +const int64_t CodePageRange::kReservedForOEM45 = (int64_t)1 << 45; +const int64_t CodePageRange::kReservedForOEM46 = (int64_t)1 << 46; +const int64_t CodePageRange::kReservedForOEM47 = (int64_t)1 << 47; +const int64_t CodePageRange::kIBMGreek_869 = (int64_t)1 << 48; +const int64_t CodePageRange::kMSDOSRussion_866 = (int64_t)1 << 49; +const int64_t CodePageRange::kMSDOSNordic_865 = (int64_t)1 << 50; +const int64_t CodePageRange::kArabic_864 = (int64_t)1 << 51; +const int64_t CodePageRange::kMSDOSCanadianFrench_863 = (int64_t)1 << 52; +const int64_t CodePageRange::kHebrew_862 = (int64_t)1 << 53; +const int64_t CodePageRange::kMSDOSIcelandic_861 = (int64_t)1 << 54; +const int64_t CodePageRange::kMSDOSPortugese_860 = (int64_t)1 << 55; +const int64_t CodePageRange::kIBMTurkish_857 = (int64_t)1 << 56; +const int64_t CodePageRange::kIBMCyrillic_855 = (int64_t)1 << 57; +const int64_t CodePageRange::kLatin2_852 = (int64_t)1 << 58; +const int64_t CodePageRange::kMSDOSBaltic_775 = (int64_t)1 << 59; +const int64_t CodePageRange::kGreek_737 = (int64_t)1 << 60; +const int64_t CodePageRange::kArabic_708 = (int64_t)1 << 61; +const int64_t CodePageRange::kLatin1_850 = (int64_t)1 << 62; +const int64_t CodePageRange::kUS_437 = (int64_t)1 << 63; + +/****************************************************************************** + * struct UnicodeRange + ******************************************************************************/ +int32_t UnicodeRange::range(int32_t bit) { + if (bit < 0 || bit > kLast) { + return -1; + } + return bit; +} + +/****************************************************************************** + * class OS2Table + ******************************************************************************/ +OS2Table::~OS2Table() {} + +int32_t OS2Table::TableVersion() { + return data_->ReadUShort(Offset::kVersion); +} + +int32_t OS2Table::XAvgCharWidth() { + return data_->ReadShort(Offset::kXAvgCharWidth); +} + +int32_t OS2Table::UsWeightClass() { + return data_->ReadUShort(Offset::kUsWeightClass); +} + +int32_t OS2Table::UsWidthClass() { + return data_->ReadUShort(Offset::kUsWidthClass); +} + +int32_t OS2Table::FsType() { + return data_->ReadUShort(Offset::kFsType); +} + +int32_t OS2Table::YSubscriptXSize() { + return data_->ReadShort(Offset::kYSubscriptXSize); +} + +int32_t OS2Table::YSubscriptYSize() { + return data_->ReadShort(Offset::kYSubscriptYSize); +} + +int32_t OS2Table::YSubscriptXOffset() { + return data_->ReadShort(Offset::kYSubscriptXOffset); +} + +int32_t OS2Table::YSubscriptYOffset() { + return data_->ReadShort(Offset::kYSubscriptYOffset); +} + +int32_t OS2Table::YSuperscriptXSize() { + return data_->ReadShort(Offset::kYSuperscriptXSize); +} + +int32_t OS2Table::YSuperscriptYSize() { + return data_->ReadShort(Offset::kYSuperscriptYSize); +} + +int32_t OS2Table::YSuperscriptXOffset() { + return data_->ReadShort(Offset::kYSuperscriptXOffset); +} + +int32_t OS2Table::YSuperscriptYOffset() { + return data_->ReadShort(Offset::kYSuperscriptYOffset); +} + +int32_t OS2Table::YStrikeoutSize() { + return data_->ReadShort(Offset::kYStrikeoutSize); +} + +int32_t OS2Table::YStrikeoutPosition() { + return data_->ReadShort(Offset::kYStrikeoutPosition); +} + +int32_t OS2Table::SFamilyClass() { + return data_->ReadShort(Offset::kSFamilyClass); +} + +void OS2Table::Panose(ByteVector* value) { + assert(value); + value->clear(); + value->resize(10); + data_->ReadBytes(Offset::kPanose, &((*value)[0]), 0, 10); +} + +int64_t OS2Table::UlUnicodeRange1() { + return data_->ReadULong(Offset::kUlUnicodeRange1); +} + +int64_t OS2Table::UlUnicodeRange2() { + return data_->ReadULong(Offset::kUlUnicodeRange2); +} + +int64_t OS2Table::UlUnicodeRange3() { + return data_->ReadULong(Offset::kUlUnicodeRange3); +} + +int64_t OS2Table::UlUnicodeRange4() { + return data_->ReadULong(Offset::kUlUnicodeRange4); +} + +void OS2Table::AchVendId(ByteVector* b) { + assert(b); + b->clear(); + b->resize(4); + data_->ReadBytes(Offset::kAchVendId, &((*b)[0]), 0, 4); +} + +int32_t OS2Table::FsSelection() { + return data_->ReadUShort(Offset::kFsSelection); +} + +int32_t OS2Table::UsFirstCharIndex() { + return data_->ReadUShort(Offset::kUsFirstCharIndex); +} + +int32_t OS2Table::UsLastCharIndex() { + return data_->ReadUShort(Offset::kUsLastCharIndex); +} + +int32_t OS2Table::STypoAscender() { + return data_->ReadShort(Offset::kSTypoAscender); +} + +int32_t OS2Table::STypoDescender() { + return data_->ReadShort(Offset::kSTypoDescender); +} + +int32_t OS2Table::STypoLineGap() { + return data_->ReadShort(Offset::kSTypoLineGap); +} + +int32_t OS2Table::UsWinAscent() { + return data_->ReadUShort(Offset::kUsWinAscent); +} + +int32_t OS2Table::UsWinDescent() { + return data_->ReadUShort(Offset::kUsWinDescent); +} + +int64_t OS2Table::UlCodePageRange1() { + return data_->ReadULong(Offset::kUlCodePageRange1); +} + +int64_t OS2Table::UlCodePageRange2() { + return data_->ReadULong(Offset::kUlCodePageRange2); +} + +int32_t OS2Table::SxHeight() { + return data_->ReadShort(Offset::kSxHeight); +} + +int32_t OS2Table::SCapHeight() { + return data_->ReadShort(Offset::kSCapHeight); +} + +int32_t OS2Table::UsDefaultChar() { + return data_->ReadUShort(Offset::kUsDefaultChar); +} + +int32_t OS2Table::UsBreakChar() { + return data_->ReadUShort(Offset::kUsBreakChar); +} + +int32_t OS2Table::UsMaxContext() { + return data_->ReadUShort(Offset::kUsMaxContext); +} + +OS2Table::OS2Table(Header* header, ReadableFontData* data) + : Table(header, data) { +} + +/****************************************************************************** + * class OS2Table::Builder + ******************************************************************************/ +OS2Table::Builder::Builder(Header* header, WritableFontData* data) + : TableBasedTableBuilder(header, data) { +} + +OS2Table::Builder::Builder(Header* header, ReadableFontData* data) + : TableBasedTableBuilder(header, data) { +} + +OS2Table::Builder::~Builder() {} + +CALLER_ATTACH FontDataTable* OS2Table::Builder::SubBuildTable( + ReadableFontData* data) { + FontDataTablePtr table = new OS2Table(header(), data); + return table.Detach(); +} + +CALLER_ATTACH OS2Table::Builder* + OS2Table::Builder::CreateBuilder(Header* header, + WritableFontData* data) { + Ptr builder; + builder = new OS2Table::Builder(header, data); + return builder.Detach(); +} + +int32_t OS2Table::Builder::TableVersion() { + return InternalReadData()->ReadUShort(Offset::kVersion); +} + +void OS2Table::Builder::SetTableVersion(int32_t version) { + InternalWriteData()->WriteUShort(Offset::kVersion, version); +} + +int32_t OS2Table::Builder::XAvgCharWidth() { + return InternalReadData()->ReadShort(Offset::kXAvgCharWidth); +} + +void OS2Table::Builder::SetXAvgCharWidth(int32_t width) { + InternalWriteData()->WriteShort(Offset::kXAvgCharWidth, width); +} + +int32_t OS2Table::Builder::UsWeightClass() { + return InternalReadData()->ReadUShort(Offset::kUsWeightClass); +} + +void OS2Table::Builder::SetUsWeightClass(int32_t weight) { + InternalWriteData()->WriteUShort(Offset::kUsWeightClass, weight); +} + +int32_t OS2Table::Builder::UsWidthClass() { + return InternalReadData()->ReadUShort(Offset::kUsWidthClass); +} + +void OS2Table::Builder::SetUsWidthClass(int32_t width) { + InternalWriteData()->WriteUShort(Offset::kUsWidthClass, width); +} + +int32_t OS2Table::Builder::FsType() { + return InternalReadData()->ReadUShort(Offset::kFsType); +} + +void OS2Table::Builder::SetFsType(int32_t fs_type) { + InternalWriteData()->WriteUShort(Offset::kFsType, fs_type); +} + +int32_t OS2Table::Builder::YSubscriptXSize() { + return InternalReadData()->ReadShort(Offset::kYSubscriptXSize); +} + +void OS2Table::Builder::SetYSubscriptXSize(int32_t size) { + InternalWriteData()->WriteShort(Offset::kYSubscriptXSize, size); +} + +int32_t OS2Table::Builder::YSubscriptYSize() { + return InternalReadData()->ReadShort(Offset::kYSubscriptYSize); +} + +void OS2Table::Builder::SetYSubscriptYSize(int32_t size) { + InternalWriteData()->WriteShort(Offset::kYSubscriptYSize, size); +} + +int32_t OS2Table::Builder::YSubscriptXOffset() { + return InternalReadData()->ReadShort(Offset::kYSubscriptXOffset); +} + +void OS2Table::Builder::SetYSubscriptXOffset(int32_t offset) { + InternalWriteData()->WriteShort(Offset::kYSubscriptXOffset, offset); +} + +int32_t OS2Table::Builder::YSubscriptYOffset() { + return InternalReadData()->ReadShort(Offset::kYSubscriptYOffset); +} + +void OS2Table::Builder::SetYSubscriptYOffset(int32_t offset) { + InternalWriteData()->WriteShort(Offset::kYSubscriptYOffset, offset); +} + +int32_t OS2Table::Builder::YSuperscriptXSize() { + return InternalReadData()->ReadShort(Offset::kYSuperscriptXSize); +} + +void OS2Table::Builder::SetYSuperscriptXSize(int32_t size) { + InternalWriteData()->WriteShort(Offset::kYSuperscriptXSize, size); +} + +int32_t OS2Table::Builder::YSuperscriptYSize() { + return InternalReadData()->ReadShort(Offset::kYSuperscriptYSize); +} + +void OS2Table::Builder::SetYSuperscriptYSize(int32_t size) { + InternalWriteData()->WriteShort(Offset::kYSuperscriptYSize, size); +} + +int32_t OS2Table::Builder::YSuperscriptXOffset() { + return InternalReadData()->ReadShort(Offset::kYSuperscriptXOffset); +} + +void OS2Table::Builder::SetYSuperscriptXOffset(int32_t offset) { + InternalWriteData()->WriteShort(Offset::kYSuperscriptXOffset, offset); +} + +int32_t OS2Table::Builder::YSuperscriptYOffset() { + return InternalReadData()->ReadShort(Offset::kYSuperscriptYOffset); +} + +void OS2Table::Builder::SetYSuperscriptYOffset(int32_t offset) { + InternalWriteData()->WriteShort(Offset::kYSuperscriptYOffset, offset); +} + +int32_t OS2Table::Builder::YStrikeoutSize() { + return InternalReadData()->ReadShort(Offset::kYStrikeoutSize); +} + +void OS2Table::Builder::SetYStrikeoutSize(int32_t size) { + InternalWriteData()->WriteShort(Offset::kYStrikeoutSize, size); +} + +int32_t OS2Table::Builder::YStrikeoutPosition() { + return InternalReadData()->ReadShort(Offset::kYStrikeoutPosition); +} + +void OS2Table::Builder::SetYStrikeoutPosition(int32_t position) { + InternalWriteData()->WriteShort(Offset::kYStrikeoutPosition, position); +} + +int32_t OS2Table::Builder::SFamilyClass() { + return InternalReadData()->ReadShort(Offset::kSFamilyClass); +} + +void OS2Table::Builder::SetSFamilyClass(int32_t family) { + InternalWriteData()->WriteShort(Offset::kSFamilyClass, family); +} + +void OS2Table::Builder::Panose(ByteVector* value) { + assert(value); + value->clear(); + value->resize(Offset::kPanoseLength); + InternalReadData()->ReadBytes(Offset::kPanose, + &((*value)[0]), + 0, + Offset::kPanoseLength); +} + +void OS2Table::Builder::SetPanose(ByteVector* panose) { + assert(panose); + if (panose->size() != Offset::kPanoseLength) { +#if !defined (SFNTLY_NO_EXCEPTION) + throw IllegalArgumentException("Panose bytes must be exactly 10 in length"); +#endif + return; + } + InternalWriteData()->WriteBytes(Offset::kPanose, panose); +} + +int64_t OS2Table::Builder::UlUnicodeRange1() { + return InternalReadData()->ReadULong(Offset::kUlUnicodeRange1); +} + +void OS2Table::Builder::SetUlUnicodeRange1(int64_t range) { + InternalWriteData()->WriteULong(Offset::kUlUnicodeRange1, range); +} + +int64_t OS2Table::Builder::UlUnicodeRange2() { + return InternalReadData()->ReadULong(Offset::kUlUnicodeRange2); +} + +void OS2Table::Builder::SetUlUnicodeRange2(int64_t range) { + InternalWriteData()->WriteULong(Offset::kUlUnicodeRange2, range); +} + +int64_t OS2Table::Builder::UlUnicodeRange3() { + return InternalReadData()->ReadULong(Offset::kUlUnicodeRange3); +} + +void OS2Table::Builder::SetUlUnicodeRange3(int64_t range) { + InternalWriteData()->WriteULong(Offset::kUlUnicodeRange3, range); +} + +int64_t OS2Table::Builder::UlUnicodeRange4() { + return InternalReadData()->ReadULong(Offset::kUlUnicodeRange4); +} + +void OS2Table::Builder::SetUlUnicodeRange4(int64_t range) { + InternalWriteData()->WriteULong(Offset::kUlUnicodeRange4, range); +} + +void OS2Table::Builder::AchVendId(ByteVector* b) { + assert(b); + b->clear(); + b->resize(4); + InternalReadData()->ReadBytes(Offset::kAchVendId, &((*b)[0]), 0, 4); +} + +void OS2Table::Builder::SetAchVendId(ByteVector* b) { + assert(b); + assert(b->size()); + InternalWriteData()->WriteBytesPad(Offset::kAchVendId, + b, + 0, + std::min( + (size_t)Offset::kAchVendIdLength, + b->size()), + static_cast(' ')); +} + +int32_t OS2Table::Builder::FsSelection() { + return InternalReadData()->ReadUShort(Offset::kFsSelection); +} + +void OS2Table::Builder::SetFsSelection(int32_t fs_selection) { + InternalWriteData()->WriteUShort(Offset::kFsSelection, fs_selection); +} + +int32_t OS2Table::Builder::UsFirstCharIndex() { + return InternalReadData()->ReadUShort(Offset::kUsFirstCharIndex); +} + +void OS2Table::Builder::SetUsFirstCharIndex(int32_t first_index) { + InternalWriteData()->WriteUShort(Offset::kUsFirstCharIndex, first_index); +} + +int32_t OS2Table::Builder::UsLastCharIndex() { + return InternalReadData()->ReadUShort(Offset::kUsLastCharIndex); +} + +void OS2Table::Builder::SetUsLastCharIndex(int32_t last_index) { + InternalWriteData()->WriteUShort(Offset::kUsLastCharIndex, last_index); +} + +int32_t OS2Table::Builder::STypoAscender() { + return InternalReadData()->ReadShort(Offset::kSTypoAscender); +} + +void OS2Table::Builder::SetSTypoAscender(int32_t ascender) { + InternalWriteData()->WriteShort(Offset::kSTypoAscender, ascender); +} + +int32_t OS2Table::Builder::STypoDescender() { + return InternalReadData()->ReadShort(Offset::kSTypoDescender); +} + +void OS2Table::Builder::SetSTypoDescender(int32_t descender) { + InternalWriteData()->WriteShort(Offset::kSTypoDescender, descender); +} + +int32_t OS2Table::Builder::STypoLineGap() { + return InternalReadData()->ReadShort(Offset::kSTypoLineGap); +} + +void OS2Table::Builder::SetSTypoLineGap(int32_t line_gap) { + InternalWriteData()->WriteShort(Offset::kSTypoLineGap, line_gap); +} + +int32_t OS2Table::Builder::UsWinAscent() { + return InternalReadData()->ReadUShort(Offset::kUsWinAscent); +} + +void OS2Table::Builder::SetUsWinAscent(int32_t ascent) { + InternalWriteData()->WriteUShort(Offset::kUsWinAscent, ascent); +} + +int32_t OS2Table::Builder::UsWinDescent() { + return InternalReadData()->ReadUShort(Offset::kUsWinDescent); +} + +void OS2Table::Builder::SetUsWinDescent(int32_t descent) { + InternalWriteData()->WriteUShort(Offset::kUsWinDescent, descent); +} + +int64_t OS2Table::Builder::UlCodePageRange1() { + return InternalReadData()->ReadULong(Offset::kUlCodePageRange1); +} + +void OS2Table::Builder::SetUlCodePageRange1(int64_t range) { + InternalWriteData()->WriteULong(Offset::kUlCodePageRange1, range); +} + +int64_t OS2Table::Builder::UlCodePageRange2() { + return InternalReadData()->ReadULong(Offset::kUlCodePageRange2); +} + +void OS2Table::Builder::SetUlCodePageRange2(int64_t range) { + InternalWriteData()->WriteULong(Offset::kUlCodePageRange2, range); +} + +int32_t OS2Table::Builder::SxHeight() { + return InternalReadData()->ReadShort(Offset::kSxHeight); +} + +void OS2Table::Builder::SetSxHeight(int32_t height) { + InternalWriteData()->WriteShort(Offset::kSxHeight, height); +} + +int32_t OS2Table::Builder::SCapHeight() { + return InternalReadData()->ReadShort(Offset::kSCapHeight); +} + +void OS2Table::Builder::SetSCapHeight(int32_t height) { + InternalWriteData()->WriteShort(Offset::kSCapHeight, height); +} + +int32_t OS2Table::Builder::UsDefaultChar() { + return InternalReadData()->ReadUShort(Offset::kUsDefaultChar); +} + +void OS2Table::Builder::SetUsDefaultChar(int32_t default_char) { + InternalWriteData()->WriteUShort(Offset::kUsDefaultChar, default_char); +} + +int32_t OS2Table::Builder::UsBreakChar() { + return InternalReadData()->ReadUShort(Offset::kUsBreakChar); +} + +void OS2Table::Builder::SetUsBreakChar(int32_t break_char) { + InternalWriteData()->WriteUShort(Offset::kUsBreakChar, break_char); +} + +int32_t OS2Table::Builder::UsMaxContext() { + return InternalReadData()->ReadUShort(Offset::kUsMaxContext); +} + +void OS2Table::Builder::SetUsMaxContext(int32_t max_context) { + InternalWriteData()->WriteUShort(Offset::kUsMaxContext, max_context); +} + +} // namespace sfntly diff --git a/src/sfntly/src/sfntly/table/core/os2_table.h b/src/sfntly/src/sfntly/table/core/os2_table.h new file mode 100644 index 000000000000..00d26d2a3bb4 --- /dev/null +++ b/src/sfntly/src/sfntly/table/core/os2_table.h @@ -0,0 +1,508 @@ +/* + * 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. + */ + +#ifndef SFNTLY_CPP_SRC_SFNTLY_TABLE_CORE_OS2_TABLE_H_ +#define SFNTLY_CPP_SRC_SFNTLY_TABLE_CORE_OS2_TABLE_H_ + +#include "sfntly/port/refcount.h" +#include "sfntly/table/table.h" +#include "sfntly/table/table_based_table_builder.h" + +namespace sfntly { + +struct WeightClass { + enum { + kThin = 100, + kExtraLight = 200, + kUltraLight = 200, + kLight = 300, + kNormal = 400, + kRegular = 400, + kMedium = 500, + kSemiBold = 600, + kDemiBold = 600, + kBold = 700, + kExtraBold = 800, + kUltraBold = 800, + kBlack = 900, + kHeavy = 900 + }; +}; + +struct WidthClass { + enum { + kUltraCondensed = 1, + kExtraCondensed = 2, + kCondensed = 3, + kSemiCondensed = 4, + kMedium = 5, + kNormal = 5, + kSemiExpanded = 6, + kExpanded = 7, + kExtraExpanded = 8, + kUltraExpanded = 9 + }; +}; + +// Flags to indicate the embedding licensing rights for a font. +struct EmbeddingFlags { + enum { + kReserved0 = 1 << 0, + kRestrictedLicenseEmbedding = 1 << 1, + kPreviewAndPrintEmbedding = 1 << 2, + kEditableEmbedding = 1 << 3, + kReserved4 = 1 << 4, + kReserved5 = 1 << 5, + kReserved6 = 1 << 6, + kReserved7 = 1 << 7, + kNoSubsetting = 1 << 8, + kBitmapEmbeddingOnly = 1 << 9, + kReserved10 = 1 << 10, + kReserved11 = 1 << 11, + kReserved12 = 1 << 12, + kReserved13 = 1 << 13, + kReserved14 = 1 << 14, + kReserved15 = 1 << 15 + }; +}; + +struct UnicodeRange { + enum { + // Do NOT reorder. This enum relies on the ordering of the data matching the + // ordinal numbers of the properties. + kBasicLatin, + kLatin1Supplement, + kLatinExtendedA, + kLatinExtendedB, + kIPAExtensions, + kSpacingModifierLetters, + kCombiningDiacriticalMarks, + kGreekAndCoptic, + kCoptic, + kCyrillic, + kArmenian, + kHebrew, + kVai, + kArabic, + kNKo, + kDevanagari, + kBengali, + kGurmukhi, + kGujarati, + kOriya, + kTamil, + kTelugu, + kKannada, + kMalayalam, + kThai, + kLao, + kGeorgian, + kBalinese, + kHangulJamo, + kLatinExtendedAdditional, + kGreekExtended, + kGeneralPunctuation, + kSuperscriptsAndSubscripts, + kCurrencySymbols, + kNumberForms, + kArrows, + kMathematicalOperators, + kMiscTechnical, + kControlPictures, + kOCR, + kEnclosedAlphanumerics, + kBoxDrawing, + kBlockElements, + kGeometricShapes, + kMiscSymbols, + kDingbats, + kCJKSymbolsAndPunctuation, + kHiragana, + kKatakana, + kBopomofo, + kHangulCompatibilityJamo, + kPhagspa, + kEnclosedCJKLettersAndMonths, + kCJKCompatibility, + kHangulSyllables, + kNonPlane0, + kPhoenician, + kCJKUnifiedIdeographs, + kPrivateUseAreaPlane0, + kCJKStrokes, + kAlphabeticPresentationForms, + kArabicPresentationFormsA, + kCombiningHalfMarks, + kVerticalForms, + kSmallFormVariants, + kArabicPresentationFormsB, + kHalfwidthAndFullwidthForms, + kSpecials, + kTibetan, + kSyriac, + kThaana, + kSinhala, + kMyanmar, + kEthiopic, + kCherokee, + kUnifiedCanadianAboriginalSyllabics, + kOgham, + kRunic, + kKhmer, + kMongolian, + kBraillePatterns, + kYiSyllables, + kTagalog, + kOldItalic, + kGothic, + kDeseret, + kMusicalSymbols, + kMathematicalAlphanumericSymbols, + kPrivateUsePlane15And16, + kVariationSelectors, + kTags, + kLimbu, + kTaiLe, + kNewTaiLue, + kBuginese, + kGlagolitic, + kTifnagh, + kYijingHexagramSymbols, + kSylotiNagari, + kLinearB, + kAncientGreekNumbers, + kUgaritic, + kOldPersian, + kShavian, + kOsmanya, + kCypriotSyllabary, + kKharoshthi, + kTaiXuanJingSymbols, + kCuneiform, + kCountingRodNumerals, + kSudanese, + kLepcha, + kOlChiki, + kSaurashtra, + kKayahLi, + kRejang, + kCharm, + kAncientSymbols, + kPhaistosDisc, + kCarian, + kDominoTiles, + kReserved123, + kReserved124, + kReserved125, + kReserved126, + kReserved127, + kLast = kReserved127 + }; + + int32_t range(int32_t bit); + // UNIMPLEMENTED: EnumSet asSet(long range1, long range2, + // long range3, long range4) + // long[] asArray(EnumSet rangeSet) +}; + +struct FsSelection { + enum { + kITALIC = 1 << 0, + kUNDERSCORE = 1 << 1, + kNEGATIVE = 1 << 2, + kOUTLINED = 1 << 3, + kSTRIKEOUT = 1 << 4, + kBOLD = 1 << 5, + kREGULAR = 1 << 6, + kUSE_TYPO_METRICS = 1 << 7, + kWWS = 1 << 8, + kOBLIQUE = 1 << 9 + }; + // UNIMPLEMENTED: EnumSet asSet(long range1, long range2, + // long range3, long range4) + // long[] asArray(EnumSet rangeSet) +}; + +// C++ port only: C++ does not support 64-bit enums until C++0x. For better +// portability, we need to use static const int64_t instead. +struct CodePageRange { + static const int64_t kLatin1_1252; + static const int64_t kLatin2_1250; + static const int64_t kCyrillic_1251; + static const int64_t kGreek_1253; + static const int64_t kTurkish_1254; + static const int64_t kHebrew_1255; + static const int64_t kArabic_1256; + static const int64_t kWindowsBaltic_1257; + static const int64_t kVietnamese_1258; + static const int64_t kAlternateANSI9; + static const int64_t kAlternateANSI10; + static const int64_t kAlternateANSI11; + static const int64_t kAlternateANSI12; + static const int64_t kAlternateANSI13; + static const int64_t kAlternateANSI14; + static const int64_t kAlternateANSI15; + static const int64_t kThai_874; + static const int64_t kJapanJIS_932; + static const int64_t kChineseSimplified_936; + static const int64_t kKoreanWansung_949; + static const int64_t kChineseTraditional_950; + static const int64_t kKoreanJohab_1361; + static const int64_t kAlternateANSI22; + static const int64_t kAlternateANSI23; + static const int64_t kAlternateANSI24; + static const int64_t kAlternateANSI25; + static const int64_t kAlternateANSI26; + static const int64_t kAlternateANSI27; + static const int64_t kAlternateANSI28; + static const int64_t kMacintoshCharacterSet; + static const int64_t kOEMCharacterSet; + static const int64_t kSymbolCharacterSet; + static const int64_t kReservedForOEM32; + static const int64_t kReservedForOEM33; + static const int64_t kReservedForOEM34; + static const int64_t kReservedForOEM35; + static const int64_t kReservedForOEM36; + static const int64_t kReservedForOEM37; + static const int64_t kReservedForOEM38; + static const int64_t kReservedForOEM39; + static const int64_t kReservedForOEM40; + static const int64_t kReservedForOEM41; + static const int64_t kReservedForOEM42; + static const int64_t kReservedForOEM43; + static const int64_t kReservedForOEM44; + static const int64_t kReservedForOEM45; + static const int64_t kReservedForOEM46; + static const int64_t kReservedForOEM47; + static const int64_t kIBMGreek_869; + static const int64_t kMSDOSRussion_866; + static const int64_t kMSDOSNordic_865; + static const int64_t kArabic_864; + static const int64_t kMSDOSCanadianFrench_863; + static const int64_t kHebrew_862; + static const int64_t kMSDOSIcelandic_861; + static const int64_t kMSDOSPortugese_860; + static const int64_t kIBMTurkish_857; + static const int64_t kIBMCyrillic_855; + static const int64_t kLatin2_852; + static const int64_t kMSDOSBaltic_775; + static const int64_t kGreek_737; + static const int64_t kArabic_708; + static const int64_t kLatin1_850; + static const int64_t kUS_437; + + // UNIMPLEMENTED: EnumSet asSet(long range1, long range2, + // long range3, long range4) + // long[] asArray(EnumSet rangeSet) +}; + +// An OS/2 table - 'OS/2'. +class OS2Table : public Table, public RefCounted { + public: + // A builder for the OS/2 table = 'OS/2'. + class Builder : public TableBasedTableBuilder, public RefCounted { + public: + Builder(Header* header, WritableFontData* data); + Builder(Header* header, ReadableFontData* data); + virtual ~Builder(); + virtual CALLER_ATTACH FontDataTable* SubBuildTable(ReadableFontData* data); + + static CALLER_ATTACH Builder* CreateBuilder(Header* header, + WritableFontData* data); + + int32_t TableVersion(); + void SetTableVersion(int32_t version); + int32_t XAvgCharWidth(); + void SetXAvgCharWidth(int32_t width); + int32_t UsWeightClass(); + void SetUsWeightClass(int32_t weight); + int32_t UsWidthClass(); + void SetUsWidthClass(int32_t width); + // UNIMPLEMENTED: EnumSet fsType() + // void setFsType(EnumSeT flagSet) + int32_t FsType(); + void SetFsType(int32_t fs_type); + int32_t YSubscriptXSize(); + void SetYSubscriptXSize(int32_t size); + int32_t YSubscriptYSize(); + void SetYSubscriptYSize(int32_t size); + int32_t YSubscriptXOffset(); + void SetYSubscriptXOffset(int32_t offset); + int32_t YSubscriptYOffset(); + void SetYSubscriptYOffset(int32_t offset); + int32_t YSuperscriptXSize(); + void SetYSuperscriptXSize(int32_t size); + int32_t YSuperscriptYSize(); + void SetYSuperscriptYSize(int32_t size); + int32_t YSuperscriptXOffset(); + void SetYSuperscriptXOffset(int32_t offset); + int32_t YSuperscriptYOffset(); + void SetYSuperscriptYOffset(int32_t offset); + int32_t YStrikeoutSize(); + void SetYStrikeoutSize(int32_t size); + int32_t YStrikeoutPosition(); + void SetYStrikeoutPosition(int32_t position); + int32_t SFamilyClass(); + void SetSFamilyClass(int32_t family); + void Panose(ByteVector* value); + void SetPanose(ByteVector* panose); + int64_t UlUnicodeRange1(); + void SetUlUnicodeRange1(int64_t range); + int64_t UlUnicodeRange2(); + void SetUlUnicodeRange2(int64_t range); + int64_t UlUnicodeRange3(); + void SetUlUnicodeRange3(int64_t range); + int64_t UlUnicodeRange4(); + void SetUlUnicodeRange4(int64_t range); + // UNIMPLEMENTED: EnumSet UlUnicodeRange() + // setUlUnicodeRange(EnumSet rangeSet) + void AchVendId(ByteVector* 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); + // UNIMPLEMENTED: public EnumSet fsSelection() + int32_t FsSelection(); + void SetFsSelection(int32_t fs_selection); + int32_t UsFirstCharIndex(); + void SetUsFirstCharIndex(int32_t first_index); + int32_t UsLastCharIndex(); + void SetUsLastCharIndex(int32_t last_index); + int32_t STypoAscender(); + void SetSTypoAscender(int32_t ascender); + int32_t STypoDescender(); + void SetSTypoDescender(int32_t descender); + int32_t STypoLineGap(); + void SetSTypoLineGap(int32_t line_gap); + int32_t UsWinAscent(); + void SetUsWinAscent(int32_t ascent); + int32_t UsWinDescent(); + void SetUsWinDescent(int32_t descent); + int64_t UlCodePageRange1(); + void SetUlCodePageRange1(int64_t range); + int64_t UlCodePageRange2(); + void SetUlCodePageRange2(int64_t range); + // UNIMPLEMENTED: EnumSet ulCodePageRange() + // void setUlCodePageRange(EnumSet rangeSet) + int32_t SxHeight(); + void SetSxHeight(int32_t height); + int32_t SCapHeight(); + void SetSCapHeight(int32_t height); + int32_t UsDefaultChar(); + void SetUsDefaultChar(int32_t default_char); + int32_t UsBreakChar(); + void SetUsBreakChar(int32_t break_char); + int32_t UsMaxContext(); + void SetUsMaxContext(int32_t max_context); + }; + + ~OS2Table(); + + int32_t TableVersion(); + int32_t XAvgCharWidth(); + int32_t UsWeightClass(); + int32_t UsWidthClass(); + // UNIMPLEMENTED: public EnumSet fsType() + int32_t FsType(); + int32_t YSubscriptXSize(); + int32_t YSubscriptYSize(); + int32_t YSubscriptXOffset(); + int32_t YSubscriptYOffset(); + int32_t YSuperscriptXSize(); + int32_t YSuperscriptYSize(); + int32_t YSuperscriptXOffset(); + int32_t YSuperscriptYOffset(); + int32_t YStrikeoutSize(); + int32_t YStrikeoutPosition(); + int32_t SFamilyClass(); + void Panose(ByteVector* value); + int64_t UlUnicodeRange1(); + int64_t UlUnicodeRange2(); + int64_t UlUnicodeRange3(); + int64_t UlUnicodeRange4(); + // UNIMPLEMENTED: public EnumSet UlUnicodeRange() + void AchVendId(ByteVector* b); + // UNIMPLEMENTED: public EnumSet fsSelection() + int32_t FsSelection(); + int32_t UsFirstCharIndex(); + int32_t UsLastCharIndex(); + int32_t STypoAscender(); + int32_t STypoDescender(); + int32_t STypoLineGap(); + int32_t UsWinAscent(); + int32_t UsWinDescent(); + int64_t UlCodePageRange1(); + int64_t UlCodePageRange2(); + // UNIMPLEMENTED: public EnumSet ulCodePageRange() + int32_t SxHeight(); + int32_t SCapHeight(); + int32_t UsDefaultChar(); + int32_t UsBreakChar(); + int32_t UsMaxContext(); + + private: + struct Offset { + enum { + kVersion = 0, + kXAvgCharWidth = 2, + kUsWeightClass = 4, + kUsWidthClass = 6, + kFsType = 8, + kYSubscriptXSize = 10, + kYSubscriptYSize = 12, + kYSubscriptXOffset = 14, + kYSubscriptYOffset = 16, + kYSuperscriptXSize = 18, + kYSuperscriptYSize = 20, + kYSuperscriptXOffset = 22, + kYSuperscriptYOffset = 24, + kYStrikeoutSize = 26, + kYStrikeoutPosition = 28, + kSFamilyClass = 30, + kPanose = 32, + kPanoseLength = 10, // Length of panose bytes. + kUlUnicodeRange1 = 42, + kUlUnicodeRange2 = 46, + kUlUnicodeRange3 = 50, + kUlUnicodeRange4 = 54, + kAchVendId = 58, + kAchVendIdLength = 4, // Length of ach vend id bytes. + kFsSelection = 62, + kUsFirstCharIndex = 64, + kUsLastCharIndex = 66, + kSTypoAscender = 68, + kSTypoDescender = 70, + kSTypoLineGap = 72, + kUsWinAscent = 74, + kUsWinDescent = 76, + kUlCodePageRange1 = 78, + kUlCodePageRange2 = 82, + kSxHeight = 86, + kSCapHeight = 88, + kUsDefaultChar = 90, + kUsBreakChar = 92, + kUsMaxContext = 94 + }; + }; + + OS2Table(Header* header, ReadableFontData* data); +}; +typedef Ptr OS2TablePtr; + +} // namespace sfntly + +#endif // SFNTLY_CPP_SRC_SFNTLY_TABLE_CORE_OS2_TABLE_H_ diff --git a/src/sfntly/src/sfntly/table/font_data_table.cc b/src/sfntly/src/sfntly/table/font_data_table.cc new file mode 100644 index 000000000000..0e27f7a7717d --- /dev/null +++ b/src/sfntly/src/sfntly/table/font_data_table.cc @@ -0,0 +1,193 @@ +/* + * 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. + */ + +#include "sfntly/table/font_data_table.h" + +#include "sfntly/data/font_output_stream.h" + +namespace sfntly { + +/****************************************************************************** + * FontDataTable class + ******************************************************************************/ + +FontDataTable::FontDataTable(ReadableFontData* data) { + data_ = data; +} + +FontDataTable::~FontDataTable() {} + +ReadableFontData* FontDataTable::ReadFontData() { + return data_; +} + +int32_t FontDataTable::DataLength() { + return data_->Length(); +} + +int32_t FontDataTable::Serialize(OutputStream* os) { + return data_->CopyTo(os); +} + +int32_t FontDataTable::Serialize(WritableFontData* data) { + return data_->CopyTo(data); +} + +/****************************************************************************** + * FontDataTable::Builder class + ******************************************************************************/ +CALLER_ATTACH WritableFontData* FontDataTable::Builder::Data() { + WritableFontDataPtr new_data; + if (model_changed_) { + if (!SubReadyToSerialize()) { +#if !defined (SFNTLY_NO_EXCEPTION) + throw IOException("Table not ready to build."); +#endif + return NULL; + } + int32_t size = SubDataSizeToSerialize(); + new_data.Attach(WritableFontData::CreateWritableFontData(size)); + SubSerialize(new_data); + } else { + ReadableFontDataPtr data = InternalReadData(); + new_data.Attach(WritableFontData::CreateWritableFontData( + data != NULL ? data->Length() : 0)); + if (data != NULL) { + data->CopyTo(new_data); + } + } + return new_data.Detach(); +} + +void FontDataTable::Builder::SetData(ReadableFontData* data) { + InternalSetData(data, true); +} + + +CALLER_ATTACH FontDataTable* FontDataTable::Builder::Build() { + FontDataTablePtr table; // NULL default table + ReadableFontDataPtr data = InternalReadData(); + if (model_changed_) { + // Let subclass serialize from model. + if (!SubReadyToSerialize()) { +#if !defined (SFNTLY_NO_EXCEPTION) + throw IOException("Table not ready to build."); +#endif + return NULL; + } + int32_t size = SubDataSizeToSerialize(); + WritableFontDataPtr new_data; + new_data.Attach(WritableFontData::CreateWritableFontData(size)); + SubSerialize(new_data); + data = new_data; + } + + if (data != NULL) { + table = SubBuildTable(data); + NotifyPostTableBuild(table); + } + + r_data_.Release(); + w_data_.Release(); + return table; +} + +bool FontDataTable::Builder::ReadyToBuild() { + return true; +} + +ReadableFontData* FontDataTable::Builder::InternalReadData() { + return (r_data_ != NULL) ? r_data_.p_ : + static_cast(w_data_.p_); +} + +WritableFontData* FontDataTable::Builder::InternalWriteData() { + if (w_data_ == NULL) { + WritableFontDataPtr new_data; + new_data.Attach(WritableFontData::CreateWritableFontData( + r_data_ == NULL ? 0 : r_data_->Length())); +#if !defined (SFNTLY_NO_EXCEPTION) + try { +#endif + if (r_data_) { + r_data_->CopyTo(new_data); + } +#if !defined (SFNTLY_NO_EXCEPTION) + } catch (IOException& e) { + // TODO(stuartg): fix when IOExceptions are cleaned up + } +#endif + InternalSetData(new_data, false); + } + return w_data_.p_; +} + +FontDataTable::Builder::Builder() + : model_changed_(false), + contained_model_changed_(false), + data_changed_(false) { +} + +FontDataTable::Builder::Builder(int32_t data_size) + : model_changed_(false), + contained_model_changed_(false), + data_changed_(false) { + w_data_.Attach(WritableFontData::CreateWritableFontData(data_size)); +} + +FontDataTable::Builder::Builder(WritableFontData* data) + : model_changed_(false), + contained_model_changed_(false), + data_changed_(false) { + w_data_ = data; +} + +FontDataTable::Builder::Builder(ReadableFontData* data) + : model_changed_(false), + contained_model_changed_(false), + data_changed_(false) { + r_data_ = data; +} + +FontDataTable::Builder::~Builder() { +} + +void FontDataTable::Builder::NotifyPostTableBuild(FontDataTable* table) { + // Default: NOP. + UNREFERENCED_PARAMETER(table); +} + +void FontDataTable::Builder::InternalSetData(WritableFontData* data, + bool data_changed) { + w_data_ = data; + r_data_ = NULL; + if (data_changed) { + data_changed_ = true; + SubDataSet(); + } +} + +void FontDataTable::Builder::InternalSetData(ReadableFontData* data, + bool data_changed) { + w_data_ = NULL; + r_data_ = data; + if (data_changed) { + data_changed_ = true; + SubDataSet(); + } +} + +} // namespace sfntly diff --git a/src/sfntly/src/sfntly/table/font_data_table.h b/src/sfntly/src/sfntly/table/font_data_table.h new file mode 100644 index 000000000000..5e437e2f345f --- /dev/null +++ b/src/sfntly/src/sfntly/table/font_data_table.h @@ -0,0 +1,123 @@ +/* + * 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. + */ + +#ifndef SFNTLY_CPP_SRC_SFNTLY_TABLE_FONT_DATA_TABLE_H_ +#define SFNTLY_CPP_SRC_SFNTLY_TABLE_FONT_DATA_TABLE_H_ + +#include "sfntly/data/readable_font_data.h" +#include "sfntly/data/writable_font_data.h" +#include "sfntly/port/refcount.h" + +namespace sfntly { + +// An abstract base for any table that contains a FontData. This is the root of +// the table class hierarchy. +class FontDataTable : virtual public RefCount { + public: + // Note: original version is abstract Builder + // C++ template is not designed that way so plain class is chosen. + class Builder : virtual public RefCount { + public: + // Get a snapshot copy of the internal data of the builder. + // This causes any internal data structures to be serialized to a new data + // object. This data object belongs to the caller and must be properly + // disposed of. No changes are made to the builder and any changes to the + // data directly do not affect the internal state. To do that a subsequent + // call must be made to {@link #SetData(WritableFontData)}. + // @return a copy of the internal data of the builder + CALLER_ATTACH WritableFontData* Data(); + virtual void SetData(ReadableFontData* data); + + // Note: changed from protected to avoid accessibility error in C++ + virtual CALLER_ATTACH FontDataTable* Build(); + virtual bool ReadyToBuild(); + + ReadableFontData* InternalReadData(); + WritableFontData* InternalWriteData(); + + bool data_changed() { return data_changed_; } + bool model_changed() { + return current_model_changed() || contained_model_changed(); + } + bool current_model_changed() { return model_changed_; } + bool contained_model_changed() { return contained_model_changed_; } + + bool set_model_changed() { return set_model_changed(true); } + bool set_model_changed(bool changed) { + bool old = model_changed_; + model_changed_ = changed; + return old; + } + + protected: + explicit Builder(); + + // Construct a FontDataTable.Builder with a WritableFontData backing store + // of size given. A positive size will create a fixed size backing store and + // a 0 or less size is an estimate for a growable backing store with the + // estimate being the absolute of the size. + // @param dataSize if positive then a fixed size; if 0 or less then an + // estimate for a growable size + Builder(int32_t data_size); + Builder(WritableFontData* data); + Builder(ReadableFontData* data); + virtual ~Builder(); + + // subclass API + virtual void NotifyPostTableBuild(FontDataTable* table); + virtual int32_t SubSerialize(WritableFontData* new_data) = 0; + virtual bool SubReadyToSerialize() = 0; + virtual int32_t SubDataSizeToSerialize() = 0; + virtual void SubDataSet() = 0; + virtual CALLER_ATTACH FontDataTable* + SubBuildTable(ReadableFontData* data) = 0; + + private: + void InternalSetData(WritableFontData* data, bool data_changed); + void InternalSetData(ReadableFontData* data, bool data_changed); + + WritableFontDataPtr w_data_; + ReadableFontDataPtr r_data_; + bool model_changed_; + bool contained_model_changed_; // may expand to list of submodel states + bool data_changed_; + }; + + explicit FontDataTable(ReadableFontData* data); + virtual ~FontDataTable(); + + // Get the readable font data for this table. + ReadableFontData* ReadFontData(); + + // Get the length of the data for this table in bytes. This is the full + // allocated length of the data underlying the table and may or may not + // include any padding. + virtual int32_t DataLength(); + + virtual int32_t Serialize(OutputStream* os); + + protected: + virtual int32_t Serialize(WritableFontData* data); + + // TODO(arthurhsu): style guide violation: protected member, need refactoring + ReadableFontDataPtr data_; +}; +typedef Ptr FontDataTablePtr; +typedef Ptr FontDataTableBuilderPtr; + +} // namespace sfntly + +#endif // SFNTLY_CPP_SRC_SFNTLY_TABLE_FONT_DATA_TABLE_H_ diff --git a/src/sfntly/src/sfntly/table/generic_table_builder.cc b/src/sfntly/src/sfntly/table/generic_table_builder.cc new file mode 100644 index 000000000000..78e679772c03 --- /dev/null +++ b/src/sfntly/src/sfntly/table/generic_table_builder.cc @@ -0,0 +1,49 @@ +/* + * 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. + */ + +#include "sfntly/table/generic_table_builder.h" + +namespace sfntly { + +GenericTableBuilder::~GenericTableBuilder() {} + +CALLER_ATTACH +FontDataTable* GenericTableBuilder::SubBuildTable(ReadableFontData* data) { + // Note: In C++ port, we use GenericTable, the ref-counted version of Table + UNREFERENCED_PARAMETER(data); + Ptr table = new GenericTable(header(), InternalReadData()); + return table.Detach(); +} + +// static +CALLER_ATTACH GenericTableBuilder* + GenericTableBuilder::CreateBuilder(Header* header, WritableFontData* data) { + Ptr builder = + new GenericTableBuilder(header, data); + return builder.Detach(); +} + +GenericTableBuilder::GenericTableBuilder(Header* header, + WritableFontData* data) + : TableBasedTableBuilder(header, data) { +} + +GenericTableBuilder::GenericTableBuilder(Header* header, + ReadableFontData* data) + : TableBasedTableBuilder(header, data) { +} + +} // namespace sfntly diff --git a/src/sfntly/src/sfntly/table/generic_table_builder.h b/src/sfntly/src/sfntly/table/generic_table_builder.h new file mode 100644 index 000000000000..a100ea072c30 --- /dev/null +++ b/src/sfntly/src/sfntly/table/generic_table_builder.h @@ -0,0 +1,42 @@ +/* + * 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. + */ + +#ifndef SFNTLY_CPP_SRC_SFNTLY_TABLE_GENERIC_TABLE_BUILDER_H_ +#define SFNTLY_CPP_SRC_SFNTLY_TABLE_GENERIC_TABLE_BUILDER_H_ + +#include "sfntly/table/table_based_table_builder.h" + +namespace sfntly { + +// A table builder to do the minimal table building for an unknown table type. +class GenericTableBuilder : public TableBasedTableBuilder, + public RefCounted { + public: + virtual ~GenericTableBuilder(); + + virtual CALLER_ATTACH FontDataTable* SubBuildTable(ReadableFontData* data); + + static CALLER_ATTACH GenericTableBuilder* + CreateBuilder(Header* header, WritableFontData* data); + + private: + GenericTableBuilder(Header* header, WritableFontData* data); + GenericTableBuilder(Header* header, ReadableFontData* data); +}; + +} // namespace sfntly + +#endif // SFNTLY_CPP_SRC_SFNTLY_TABLE_BYTE_ARRAY_TABLE_BUILDER_H_ diff --git a/src/sfntly/src/sfntly/table/header.cc b/src/sfntly/src/sfntly/table/header.cc new file mode 100644 index 000000000000..672ace5749d1 --- /dev/null +++ b/src/sfntly/src/sfntly/table/header.cc @@ -0,0 +1,66 @@ +/* + * 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. + */ + +#include "sfntly/table/header.h" + +namespace sfntly { + +/****************************************************************************** + * Header class + ******************************************************************************/ +Header::Header(int32_t tag) + : tag_(tag), + offset_(0), + offset_valid_(false), + length_(0), + length_valid_(false), + checksum_(0), + checksum_valid_(false) { +} + +Header::Header(int32_t tag, int32_t length) + : tag_(tag), + offset_(0), + offset_valid_(false), + length_(length), + length_valid_(true), + checksum_(0), + checksum_valid_(false) { +} + +Header::Header(int32_t tag, int64_t checksum, int32_t offset, int32_t length) + : tag_(tag), + offset_(offset), + offset_valid_(true), + length_(length), + length_valid_(true), + checksum_(checksum), + checksum_valid_(true) { +} + +Header::~Header() {} + +bool HeaderComparatorByOffset::operator() (const HeaderPtr lhs, + const HeaderPtr rhs) { + return lhs->offset_ > rhs->offset_; +} + +bool HeaderComparatorByTag::operator() (const HeaderPtr lhs, + const HeaderPtr rhs) { + return lhs->tag_ > rhs->tag_; +} + +} // namespace sfntly diff --git a/src/sfntly/src/sfntly/table/header.h b/src/sfntly/src/sfntly/table/header.h new file mode 100644 index 000000000000..280e556c472b --- /dev/null +++ b/src/sfntly/src/sfntly/table/header.h @@ -0,0 +1,114 @@ +/* + * 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. + */ + +#ifndef SFNTLY_CPP_SRC_SFNTLY_TABLE_HEADER_H_ +#define SFNTLY_CPP_SRC_SFNTLY_TABLE_HEADER_H_ + +#include "sfntly/port/refcount.h" + +namespace sfntly { + +class Header : public RefCounted
{ + public: + // Make a partial header with only the basic info for an empty new table. + explicit Header(int32_t tag); + + // Make a partial header with only the basic info for a new table. + Header(int32_t tag, int32_t length); + + // Make a full header as read from an existing font. + Header(int32_t tag, int64_t checksum, int32_t offset, int32_t length); + virtual ~Header(); + + // Get the table tag. + int32_t tag() { 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_; } + + // 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_; } + + // 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_; } + + // 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_; } + + // Get the checksum for the table as recorded in the table record header. + int64_t checksum() { 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_; } + + // 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_; + + friend class HeaderComparatorByOffset; + friend class HeaderComparatorByTag; +}; +typedef Ptr
HeaderPtr; + +class HeaderComparator { + public: + virtual ~HeaderComparator() {} + virtual bool operator()(const HeaderPtr h1, + const HeaderPtr h2) = 0; +}; + +class HeaderComparatorByOffset : public HeaderComparator { + public: + virtual ~HeaderComparatorByOffset() {} + virtual bool operator()(const HeaderPtr h1, + const HeaderPtr h2); +}; + +class HeaderComparatorByTag : public HeaderComparator { + public: + virtual ~HeaderComparatorByTag() {} + virtual bool operator()(const HeaderPtr h1, + const HeaderPtr h2); +}; + +typedef std::set HeaderOffsetSortedSet; +typedef std::set HeaderTagSortedSet; + +} // namespace sfntly + +#endif // SFNTLY_CPP_SRC_SFNTLY_TABLE_HEADER_H_ diff --git a/src/sfntly/src/sfntly/table/subtable.cc b/src/sfntly/src/sfntly/table/subtable.cc new file mode 100644 index 000000000000..e5b906fd376e --- /dev/null +++ b/src/sfntly/src/sfntly/table/subtable.cc @@ -0,0 +1,64 @@ +/* + * 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. + */ + +#include "sfntly/table/subtable.h" + +namespace sfntly { +/****************************************************************************** + * SubTable class + ******************************************************************************/ +SubTable::~SubTable() {} + +SubTable::SubTable(ReadableFontData* data, ReadableFontData* master_data) + : FontDataTable(data), padding_(0) { + master_data_ = master_data; +} + +SubTable::SubTable(ReadableFontData* data) + : FontDataTable(data), padding_(0) { +} + +/****************************************************************************** + * SubTable::Builder class + ******************************************************************************/ +SubTable::Builder::~Builder() { +} + +SubTable::Builder::Builder(int32_t data_size) + : FontDataTable::Builder(data_size) { +} + +SubTable::Builder::Builder(WritableFontData* data, + ReadableFontData* master_data) + : FontDataTable::Builder(data) { + master_data_ = master_data; +} + +SubTable::Builder::Builder(ReadableFontData* data, + ReadableFontData* master_data) + : FontDataTable::Builder(data) { + master_data_ = master_data; +} + +SubTable::Builder::Builder(WritableFontData* data) + : FontDataTable::Builder(data) { +} + +SubTable::Builder::Builder(ReadableFontData* data) + : FontDataTable::Builder(data) { +} + +} // namespace sfntly diff --git a/src/sfntly/src/sfntly/table/subtable.h b/src/sfntly/src/sfntly/table/subtable.h new file mode 100644 index 000000000000..fa6f4c6bcdb0 --- /dev/null +++ b/src/sfntly/src/sfntly/table/subtable.h @@ -0,0 +1,73 @@ +/* + * 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. + */ + +#ifndef SFNTLY_CPP_SRC_SFNTLY_TABLE_SUBTABLE_H_ +#define SFNTLY_CPP_SRC_SFNTLY_TABLE_SUBTABLE_H_ + +#include "sfntly/table/font_data_table.h" + +namespace sfntly { + +// An abstract base class for subtables. Subtables are smaller tables nested +// within other tables and don't have an entry in the main font index. Examples +// of these are the CMap subtables within CMap table (cmap) or a glyph within +// the glyph table (glyf). +class SubTable : public FontDataTable { + public: + class Builder : public FontDataTable::Builder { + public: + virtual ~Builder(); + + protected: + // @param data the data for the subtable being built + // @param master_data the data for the full table + Builder(int32_t data_size); + Builder(WritableFontData* data, ReadableFontData* master_data); + Builder(ReadableFontData* data, ReadableFontData* master_data); + explicit Builder(WritableFontData* data); + explicit Builder(ReadableFontData* data); + + ReadableFontData* master_read_data() { return master_data_; } + + private: + ReadableFontDataPtr master_data_; + }; + + virtual ~SubTable(); + virtual int32_t Padding() { return padding_; } + + // Sets the amount of padding that is part of the data being used by this + // subtable. + void set_padding(int32_t padding) { padding_ = padding; } + + protected: + SubTable(ReadableFontData* data, ReadableFontData* master_data); + + // Note: constructor refactored in C++ to avoid heavy lifting. + // caller need to do data->Slice(offset, length) beforehand. + explicit SubTable(ReadableFontData* data); + + ReadableFontData* master_read_data() { return master_data_; } + + private: + // The data for the whole table in which this subtable is contained. + ReadableFontDataPtr master_data_; + int32_t padding_; +}; + +} // namespace sfntly + +#endif // SFNTLY_CPP_SRC_SFNTLY_TABLE_SUBTABLE_H_ diff --git a/src/sfntly/src/sfntly/table/subtable_container_table.h b/src/sfntly/src/sfntly/table/subtable_container_table.h new file mode 100644 index 000000000000..0f099debb4c9 --- /dev/null +++ b/src/sfntly/src/sfntly/table/subtable_container_table.h @@ -0,0 +1,48 @@ +/* + * 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. + */ + +#ifndef TYPOGRAPHY_FONT_SFNTLY_SRC_SFNTLY_TABLE_SUBTABLE_CONTAINER_TABLE_H_ +#define TYPOGRAPHY_FONT_SFNTLY_SRC_SFNTLY_TABLE_SUBTABLE_CONTAINER_TABLE_H_ + +#include "sfntly/table/table.h" + +namespace sfntly { + +class SubTableContainerTable : public Table { + public: + class Builder : public Table::Builder { + public: + Builder(Header* header, WritableFontData* data) + : Table::Builder(header, data) { + } + + Builder(Header* header, ReadableFontData* data) + : Table::Builder(header, data) { + } + + virtual ~Builder() {} + }; + + SubTableContainerTable(Header* header, ReadableFontData* data) + : Table(header, data) { + } + + virtual ~SubTableContainerTable() {} +}; + +} // namespace sfntly + +#endif // TYPOGRAPHY_FONT_SFNTLY_SRC_SFNTLY_TABLE_SUBTABLE_CONTAINER_TABLE_H_ diff --git a/src/sfntly/src/sfntly/table/table.cc b/src/sfntly/src/sfntly/table/table.cc new file mode 100644 index 000000000000..cf574b838b64 --- /dev/null +++ b/src/sfntly/src/sfntly/table/table.cc @@ -0,0 +1,162 @@ +/* + * 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. + */ + +// type.h needs to be included first because of building issues on Windows +// Type aliases we delcare are defined in other headers and make the build +// fail otherwise. +#include "sfntly/port/type.h" +#include "sfntly/table/table.h" + +#include "sfntly/font.h" +#include "sfntly/tag.h" +#include "sfntly/table/bitmap/ebdt_table.h" +#include "sfntly/table/bitmap/eblc_table.h" +#include "sfntly/table/bitmap/ebsc_table.h" +#include "sfntly/table/core/cmap_table.h" +#include "sfntly/table/core/font_header_table.h" +#include "sfntly/table/core/horizontal_device_metrics_table.h" +#include "sfntly/table/core/horizontal_header_table.h" +#include "sfntly/table/core/horizontal_metrics_table.h" +#include "sfntly/table/core/maximum_profile_table.h" +#include "sfntly/table/core/name_table.h" +#include "sfntly/table/core/os2_table.h" +#include "sfntly/table/generic_table_builder.h" +#include "sfntly/table/table_based_table_builder.h" +#include "sfntly/table/truetype/glyph_table.h" +#include "sfntly/table/truetype/loca_table.h" + +namespace sfntly { + +/****************************************************************************** + * Table class + ******************************************************************************/ +Table::~Table() {} + +int64_t Table::CalculatedChecksum() { + return data_->Checksum(); +} + +void Table::SetFont(Font* font) { + font_ = font; +} + +Table::Table(Header* header, ReadableFontData* data) + : FontDataTable(data) { + header_ = header; +} + +/****************************************************************************** + * Table::Builder class + ******************************************************************************/ +Table::Builder::~Builder() { + header_.Release(); +} + +void Table::Builder::NotifyPostTableBuild(FontDataTable* table) { + if (model_changed() || data_changed()) { + Table* derived_table = down_cast(table); + derived_table->header_ = new Header(header()->tag(), + derived_table->DataLength()); + } +} + +CALLER_ATTACH +Table::Builder* Table::Builder::GetBuilder(Header* header, + WritableFontData* table_data) { + int32_t tag = header->tag(); + Table::Builder* builder_raw = NULL; + + // Note: Tables are commented out when they are not used/ported. + // TODO(arthurhsu): IMPLEMENT: finish tables that are not ported. + if (tag == Tag::head) { + builder_raw = static_cast( + FontHeaderTable::Builder::CreateBuilder(header, table_data)); +#if defined (SFNTLY_EXPERIMENTAL) + } else if (tag == Tag::cmap) { + builder_raw = static_cast( + CMapTable::Builder::CreateBuilder(header, table_data)); +#endif // SFNTLY_EXPERIMENTAL + } else if (tag == Tag::hhea) { + builder_raw = static_cast( + HorizontalHeaderTable::Builder::CreateBuilder(header, table_data)); + } else if (tag == Tag::hmtx) { + builder_raw = static_cast( + HorizontalMetricsTable::Builder::CreateBuilder(header, table_data)); + } else if (tag == Tag::maxp) { + builder_raw = static_cast( + MaximumProfileTable::Builder::CreateBuilder(header, table_data)); + } else if (tag == Tag::name) { + builder_raw = static_cast( + NameTable::Builder::CreateBuilder(header, table_data)); + } else if (tag == Tag::OS_2) { + builder_raw = static_cast( + OS2Table::Builder::CreateBuilder(header, table_data)); + }/* else if (tag == Tag::PostScript) { + builder_raw = static_cast( + PostScriptTable::Builder::CreateBuilder(header, table_data)); + } else if (tag == Tag::cvt) { + builder_raw = static_cast( + ControlValueTable::Builder::CreateBuilder(header, table_data)); + }*/ else if (tag == Tag::glyf) { + builder_raw = static_cast( + GlyphTable::Builder::CreateBuilder(header, table_data)); + } else if (tag == Tag::loca) { + builder_raw = static_cast( + LocaTable::Builder::CreateBuilder(header, table_data)); + } else if (tag == Tag::EBDT || tag == Tag::bdat) { + builder_raw = static_cast( + EbdtTable::Builder::CreateBuilder(header, table_data)); + } else if (tag == Tag::EBLC || tag == Tag::bloc) { + builder_raw = static_cast( + EblcTable::Builder::CreateBuilder(header, table_data)); + } else if (tag == Tag::EBSC) { + builder_raw = static_cast( + EbscTable::Builder::CreateBuilder(header, table_data)); + } /* else if (tag == Tag::prep) { + builder_raw = static_cast( + ControlProgramTable::Builder::CreateBuilder(header, table_data)); + }*/ else if (tag == Tag::bhed) { + builder_raw = static_cast( + FontHeaderTable::Builder::CreateBuilder(header, table_data)); +#if defined (SFNTLY_EXPERIMENTAL) + } else if (tag == Tag::hdmx) { + builder_raw = static_cast( + HorizontalDeviceMetricsTable::Builder::CreateBuilder(header, + table_data)); +#endif // SFNTLY_EXPERIMENTAL + } else { + builder_raw = static_cast( + GenericTableBuilder::CreateBuilder(header, table_data)); + } + + return builder_raw; +} + +Table::Builder::Builder(Header* header, WritableFontData* data) + : FontDataTable::Builder(data) { + header_ = header; +} + +Table::Builder::Builder(Header* header, ReadableFontData* data) + : FontDataTable::Builder(data) { + header_ = header; +} + +Table::Builder::Builder(Header* header) { + header_ = header; +} + +} // namespace sfntly diff --git a/src/sfntly/src/sfntly/table/table.h b/src/sfntly/src/sfntly/table/table.h new file mode 100644 index 000000000000..6ebc22df8ad7 --- /dev/null +++ b/src/sfntly/src/sfntly/table/table.h @@ -0,0 +1,119 @@ +/* + * 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. + */ + +#ifndef SFNTLY_CPP_SRC_SFNTLY_TABLE_TABLE_H_ +#define SFNTLY_CPP_SRC_SFNTLY_TABLE_TABLE_H_ + +#include +#include +#include +#include + +#include "sfntly/port/type.h" +#include "sfntly/table/font_data_table.h" +#include "sfntly/table/header.h" + +namespace sfntly { +class Font; + +// A concrete implementation of a root level table in the font. This is the base +// class used for all specific table implementations and is used as the generic +// table for all tables which have no specific implementations. +class Table : public FontDataTable { + public: + // Note: original version is Builder + // C++ template is not designed that way so plain old inheritance is + // chosen. + class Builder : public FontDataTable::Builder { + public: + virtual ~Builder(); + virtual Header* header() { return header_; } + virtual void NotifyPostTableBuild(FontDataTable* table); + + // Get a builder for the table type specified by the data in the header. + // @param header the header for the table + // @param tableData the data to be used to build the table from + // @return builder for the table specified + static CALLER_ATTACH Builder* GetBuilder(Header* header, + WritableFontData* table_data); + + // UNIMPLEMENTED: toString() + + protected: + Builder(Header* header, WritableFontData* data); + Builder(Header* header, ReadableFontData* data); + Builder(Header* header); + + private: + Ptr
header_; + }; + + // Note: GenericTableBuilder moved to table_based_table_builder.h to avoid + // circular inclusion. + + virtual ~Table(); + + // Get the calculated checksum for the data in the table. + virtual int64_t CalculatedChecksum(); + + // Get the header for the table. + virtual Header* header() { return header_; } + + // Get the tag for the table from the record header. + virtual int32_t header_tag() { return header_->tag(); } + + // Get the offset for the table from the record header. + virtual int32_t header_offset() { return header_->offset(); } + + // Get the length of the table from the record header. + virtual int32_t header_length() { return header_->length(); } + + // Get the checksum for the table from the record header. + virtual int64_t header_checksum() { return header_->checksum(); } + + // UNIMPLEMENTED: toString() + + virtual void SetFont(Font* font); + + protected: + Table(Header* header, ReadableFontData* data); + + private: + Ptr
header_; + Ptr font_; +}; + +// C++ port only +class GenericTable : public Table, public RefCounted { + public: + GenericTable(Header* header, ReadableFontData* data) : Table(header, data) {} + virtual ~GenericTable() {} +}; + +typedef Ptr TablePtr; +typedef std::vector TableHeaderList; +typedef Ptr TableBuilderPtr; +typedef std::map TableMap; +typedef std::pair TableMapEntry; + +typedef std::map DataBlockMap; +typedef std::pair DataBlockEntry; +typedef std::map TableBuilderMap; +typedef std::pair TableBuilderEntry; + +} // namespace sfntly + +#endif // SFNTLY_CPP_SRC_SFNTLY_TABLE_TABLE_H_ diff --git a/src/sfntly/src/sfntly/table/table_based_table_builder.cc b/src/sfntly/src/sfntly/table/table_based_table_builder.cc new file mode 100644 index 000000000000..b5057046385f --- /dev/null +++ b/src/sfntly/src/sfntly/table/table_based_table_builder.cc @@ -0,0 +1,69 @@ +/* + * 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. + */ + +#include "sfntly/table/table_based_table_builder.h" + +namespace sfntly { + +/****************************************************************************** + * TableBasedTableBuilder class + ******************************************************************************/ +TableBasedTableBuilder::~TableBasedTableBuilder() {} + +int32_t TableBasedTableBuilder::SubSerialize(WritableFontData* data) { + UNREFERENCED_PARAMETER(data); + return 0; +} + +bool TableBasedTableBuilder::SubReadyToSerialize() { + return false; +} + +int32_t TableBasedTableBuilder::SubDataSizeToSerialize() { + return 0; +} + +void TableBasedTableBuilder::SubDataSet() { + table_ = NULL; +} + +CALLER_ATTACH FontDataTable* TableBasedTableBuilder::Build() { + FontDataTablePtr table = static_cast(GetTable()); + return table.Detach(); +} + +TableBasedTableBuilder::TableBasedTableBuilder(Header* header, + WritableFontData* data) + : Table::Builder(header, data) { +} + +TableBasedTableBuilder::TableBasedTableBuilder(Header* header, + ReadableFontData* data) + : Table::Builder(header, data) { +} + +TableBasedTableBuilder::TableBasedTableBuilder(Header* header) + : Table::Builder(header) { +} + +Table* TableBasedTableBuilder::GetTable() { + if (table_ == NULL) { + table_.Attach(down_cast(SubBuildTable(InternalReadData()))); + } + return table_; +} + +} // namespace sfntly diff --git a/src/sfntly/src/sfntly/table/table_based_table_builder.h b/src/sfntly/src/sfntly/table/table_based_table_builder.h new file mode 100644 index 000000000000..d88eefd11eed --- /dev/null +++ b/src/sfntly/src/sfntly/table/table_based_table_builder.h @@ -0,0 +1,48 @@ +/* + * 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. + */ + +#ifndef SFNTLY_CPP_SRC_SFNTLY_TABLE_TABLE_BASED_TABLE_BUILDER_H_ +#define SFNTLY_CPP_SRC_SFNTLY_TABLE_TABLE_BASED_TABLE_BUILDER_H_ + +#include "sfntly/table/table.h" + +namespace sfntly { + +class TableBasedTableBuilder : public Table::Builder { + public: + virtual ~TableBasedTableBuilder(); + + virtual int32_t SubSerialize(WritableFontData* new_data); + virtual bool SubReadyToSerialize(); + virtual int32_t SubDataSizeToSerialize(); + virtual void SubDataSet(); + virtual CALLER_ATTACH FontDataTable* Build(); + + protected: + TableBasedTableBuilder(Header* header, WritableFontData* data); + TableBasedTableBuilder(Header* header, ReadableFontData* data); + explicit TableBasedTableBuilder(Header* header); + + // C++ port: renamed table() to GetTable() + virtual Table* GetTable(); + + // TODO(arthurhsu): style guide violation: protected member, need refactor + TablePtr table_; +}; + +} // namespace sfntly + +#endif // SFNTLY_CPP_SRC_SFNTLY_TABLE_TABLE_BASED_TABLE_BUILDER_H_ diff --git a/src/sfntly/src/sfntly/table/truetype/glyph_table.cc b/src/sfntly/src/sfntly/table/truetype/glyph_table.cc new file mode 100644 index 000000000000..f38fac5c5c4f --- /dev/null +++ b/src/sfntly/src/sfntly/table/truetype/glyph_table.cc @@ -0,0 +1,679 @@ +/* + * 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. + */ + +#include "sfntly/table/truetype/glyph_table.h" + +#include + +#include "sfntly/port/exception_type.h" + +namespace sfntly { +/****************************************************************************** + * Constants + ******************************************************************************/ +const int32_t GlyphTable::SimpleGlyph::kFLAG_ONCURVE = 1; +const int32_t GlyphTable::SimpleGlyph::kFLAG_XSHORT = 1 << 1; +const int32_t GlyphTable::SimpleGlyph::kFLAG_YSHORT = 1 << 2; +const int32_t GlyphTable::SimpleGlyph::kFLAG_REPEAT = 1 << 3; +const int32_t GlyphTable::SimpleGlyph::kFLAG_XREPEATSIGN = 1 << 4; +const int32_t GlyphTable::SimpleGlyph::kFLAG_YREPEATSIGN = 1 << 5; + +const int32_t GlyphTable::CompositeGlyph::kFLAG_ARG_1_AND_2_ARE_WORDS = 1 << 0; +const int32_t GlyphTable::CompositeGlyph::kFLAG_ARGS_ARE_XY_VALUES = 1 << 1; +const int32_t GlyphTable::CompositeGlyph::kFLAG_ROUND_XY_TO_GRID = 1 << 2; +const int32_t GlyphTable::CompositeGlyph::kFLAG_WE_HAVE_A_SCALE = 1 << 3; +const int32_t GlyphTable::CompositeGlyph::kFLAG_RESERVED = 1 << 4; +const int32_t GlyphTable::CompositeGlyph::kFLAG_MORE_COMPONENTS = 1 << 5; +const int32_t GlyphTable::CompositeGlyph::kFLAG_WE_HAVE_AN_X_AND_Y_SCALE = 1 << 6; +const int32_t GlyphTable::CompositeGlyph::kFLAG_WE_HAVE_A_TWO_BY_TWO = 1 << 7; +const int32_t GlyphTable::CompositeGlyph::kFLAG_WE_HAVE_INSTRUCTIONS = 1 << 8; +const int32_t GlyphTable::CompositeGlyph::kFLAG_USE_MY_METRICS = 1 << 9; +const int32_t GlyphTable::CompositeGlyph::kFLAG_OVERLAP_COMPOUND = 1 << 10; +const int32_t GlyphTable::CompositeGlyph::kFLAG_SCALED_COMPONENT_OFFSET = 1 << 11; +const int32_t GlyphTable::CompositeGlyph::kFLAG_UNSCALED_COMPONENT_OFFSET = 1 << 12; + +/****************************************************************************** + * GlyphTable class + ******************************************************************************/ +GlyphTable::~GlyphTable() { +} + +GlyphTable::Glyph* GlyphTable::GetGlyph(int32_t offset, int32_t length) { + return GlyphTable::Glyph::GetGlyph(this, this->data_, offset, length); +} + +GlyphTable::GlyphTable(Header* header, ReadableFontData* data) + : SubTableContainerTable(header, data) { +} + +/****************************************************************************** + * GlyphTable::Builder class + ******************************************************************************/ +GlyphTable::Builder::Builder(Header* header, ReadableFontData* data) + : SubTableContainerTable::Builder(header, data) { +} + +GlyphTable::Builder::~Builder() { +} + +void GlyphTable::Builder::SetLoca(const IntegerList& loca) { + loca_ = loca; + set_model_changed(false); + glyph_builders_.clear(); +} + +void GlyphTable::Builder::GenerateLocaList(IntegerList* locas) { + assert(locas); + GlyphBuilderList* glyph_builders = GetGlyphBuilders(); + locas->push_back(0); + if (glyph_builders->size() == 0) { + locas->push_back(0); + } else { + int32_t total = 0; + for (GlyphBuilderList::iterator b = glyph_builders->begin(), + b_end = glyph_builders->end(); + b != b_end; ++b) { + int32_t size = (*b)->SubDataSizeToSerialize(); + locas->push_back(total + size); + total += size; + } + } +} + +CALLER_ATTACH GlyphTable::Builder* + GlyphTable::Builder::CreateBuilder(Header* header, WritableFontData* data) { + Ptr builder; + builder = new GlyphTable::Builder(header, data); + return builder.Detach(); +} + +GlyphTable::GlyphBuilderList* GlyphTable::Builder::GlyphBuilders() { + return GetGlyphBuilders(); +} + +void GlyphTable::Builder::SetGlyphBuilders(GlyphBuilderList* glyph_builders) { + glyph_builders_ = *glyph_builders; + set_model_changed(); +} + +CALLER_ATTACH GlyphTable::Glyph::Builder* + GlyphTable::Builder::GlyphBuilder(ReadableFontData* data) { + return Glyph::Builder::GetBuilder(this, data); +} + +CALLER_ATTACH FontDataTable* + GlyphTable::Builder::SubBuildTable(ReadableFontData* data) { + FontDataTablePtr table = new GlyphTable(header(), data); + return table.Detach(); +} + +void GlyphTable::Builder::SubDataSet() { + glyph_builders_.clear(); + set_model_changed(false); +} + +int32_t GlyphTable::Builder::SubDataSizeToSerialize() { + if (glyph_builders_.empty()) + return 0; + + bool variable = false; + int32_t size = 0; + + // Calculate size of each table. + for (GlyphBuilderList::iterator b = glyph_builders_.begin(), + end = glyph_builders_.end(); b != end; ++b) { + int32_t glyph_size = (*b)->SubDataSizeToSerialize(); + size += abs(glyph_size); + variable |= glyph_size <= 0; + } + return variable ? -size : size; +} + +bool GlyphTable::Builder::SubReadyToSerialize() { + return !glyph_builders_.empty(); +} + +int32_t GlyphTable::Builder::SubSerialize(WritableFontData* new_data) { + int32_t size = 0; + for (GlyphBuilderList::iterator b = glyph_builders_.begin(), + end = glyph_builders_.end(); b != end; ++b) { + FontDataPtr data; + data.Attach(new_data->Slice(size)); + size += (*b)->SubSerialize(down_cast(data.p_)); + } + return size; +} + +void GlyphTable::Builder::Initialize(ReadableFontData* data, + const IntegerList& loca) { + if (data != NULL) { + if (loca_.empty()) { + return; + } + int32_t loca_value; + int32_t last_loca_value = loca[0]; + for (size_t i = 1; i < loca.size(); ++i) { + loca_value = loca[i]; + GlyphBuilderPtr builder; + builder.Attach( + Glyph::Builder::GetBuilder(this, + data, + last_loca_value /*offset*/, + loca_value - last_loca_value /*length*/)); + glyph_builders_.push_back(builder); + last_loca_value = loca_value; + } + } +} + +GlyphTable::GlyphBuilderList* GlyphTable::Builder::GetGlyphBuilders() { + if (glyph_builders_.empty()) { + if (InternalReadData() && !loca_.empty()) { +#if !defined (SFNTLY_NO_EXCEPTION) + throw IllegalStateException( + "Loca values not set - unable to parse glyph data."); +#endif + return NULL; + } + Initialize(InternalReadData(), loca_); + set_model_changed(); + } + return &glyph_builders_; +} + +void GlyphTable::Builder::Revert() { + glyph_builders_.clear(); + set_model_changed(false); +} + +/****************************************************************************** + * GlyphTable::Glyph class + ******************************************************************************/ +GlyphTable::Glyph::~Glyph() {} + +CALLER_ATTACH GlyphTable::Glyph* + GlyphTable::Glyph::GetGlyph(GlyphTable* table, + ReadableFontData* data, + int32_t offset, + int32_t length) { + UNREFERENCED_PARAMETER(table); + int32_t type = GlyphType(data, offset, length); + GlyphPtr glyph; + + ReadableFontDataPtr sliced_data; + sliced_data.Attach(down_cast(data->Slice(offset, length))); + if (type == GlyphType::kSimple) { + glyph = new SimpleGlyph(sliced_data); + } else { + glyph = new CompositeGlyph(sliced_data); + } + return glyph.Detach(); +} + +int32_t GlyphTable::Glyph::Padding() { + Initialize(); + return SubTable::Padding(); +} + +int32_t GlyphTable::Glyph::GlyphType() { + return glyph_type_; +} + +int32_t GlyphTable::Glyph::NumberOfContours() { + return number_of_contours_; +} + +int32_t GlyphTable::Glyph::XMin() { + return data_->ReadShort(Offset::kXMin); +} + +int32_t GlyphTable::Glyph::XMax() { + return data_->ReadShort(Offset::kXMax); +} + +int32_t GlyphTable::Glyph::YMin() { + return data_->ReadShort(Offset::kYMin); +} + +int32_t GlyphTable::Glyph::YMax() { + return data_->ReadShort(Offset::kYMax); +} + +GlyphTable::Glyph::Glyph(ReadableFontData* data, int32_t glyph_type) + : SubTable(data), + glyph_type_(glyph_type) { + if (data_->Length() == 0) { + number_of_contours_ = 0; + } else { + // -1 if composite + number_of_contours_ = data_->ReadShort(Offset::kNumberOfContours); + } +} + +int32_t GlyphTable::Glyph::GlyphType(ReadableFontData* data, + int32_t offset, + int32_t length) { + if (length == 0) { + return GlyphType::kSimple; + } + int32_t number_of_contours = data->ReadShort(offset); + if (number_of_contours >= 0) { + return GlyphType::kSimple; + } + return GlyphType::kComposite; +} + +/****************************************************************************** + * GlyphTable::Glyph::Builder class + ******************************************************************************/ +GlyphTable::Glyph::Builder::~Builder() { +} + +GlyphTable::Glyph::Builder::Builder(WritableFontData* data) + : SubTable::Builder(data) { +} + +GlyphTable::Glyph::Builder::Builder(ReadableFontData* data) + : SubTable::Builder(data) { +} + +CALLER_ATTACH GlyphTable::Glyph::Builder* + GlyphTable::Glyph::Builder::GetBuilder( + GlyphTable::Builder* table_builder, + ReadableFontData* data) { + return GetBuilder(table_builder, data, 0, data->Length()); +} + +CALLER_ATTACH GlyphTable::Glyph::Builder* + GlyphTable::Glyph::Builder::GetBuilder( + GlyphTable::Builder* table_builder, + ReadableFontData* data, + int32_t offset, + int32_t length) { + UNREFERENCED_PARAMETER(table_builder); + int32_t type = Glyph::GlyphType(data, offset, length); + GlyphBuilderPtr builder; + ReadableFontDataPtr sliced_data; + sliced_data.Attach(down_cast(data->Slice(offset, length))); + if (type == GlyphType::kSimple) { + builder = new SimpleGlyph::SimpleGlyphBuilder(sliced_data); + } else { + builder = new CompositeGlyph::CompositeGlyphBuilder(sliced_data); + } + return builder.Detach(); +} + +void GlyphTable::Glyph::Builder::SubDataSet() { + // NOP +} + +int32_t GlyphTable::Glyph::Builder::SubDataSizeToSerialize() { + return InternalReadData()->Length(); +} + +bool GlyphTable::Glyph::Builder::SubReadyToSerialize() { + return true; +} + +int32_t GlyphTable::Glyph::Builder::SubSerialize(WritableFontData* new_data) { + return InternalReadData()->CopyTo(new_data); +} + +/****************************************************************************** + * GlyphTable::SimpleGlyph + ******************************************************************************/ +GlyphTable::SimpleGlyph::SimpleGlyph(ReadableFontData* data) + : GlyphTable::Glyph(data, GlyphType::kSimple), initialized_(false) { +} + +GlyphTable::SimpleGlyph::~SimpleGlyph() { +} + +int32_t GlyphTable::SimpleGlyph::InstructionSize() { + Initialize(); + return instruction_size_; +} + +CALLER_ATTACH ReadableFontData* GlyphTable::SimpleGlyph::Instructions() { + Initialize(); + return down_cast( + 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_) { + return; + } + + if (ReadFontData()->Length() == 0) { + instruction_size_ = 0; + number_of_points_ = 0; + instructions_offset_ = 0; + flags_offset_ = 0; + x_coordinates_offset_ = 0; + y_coordinates_offset_ = 0; + return; + } + + instruction_size_ = data_->ReadUShort(Offset::kSimpleEndPtsOfCountours + + NumberOfContours() * DataSize::kUSHORT); + instructions_offset_ = Offset::kSimpleEndPtsOfCountours + + (NumberOfContours() + 1) * DataSize::kUSHORT; + flags_offset_ = instructions_offset_ + instruction_size_ * DataSize::kBYTE; + number_of_points_ = ContourEndPoint(NumberOfContours() - 1) + 1; + x_coordinates_.resize(number_of_points_); + y_coordinates_.resize(number_of_points_); + on_curve_.resize(number_of_points_); + ParseData(false); + x_coordinates_offset_ = flags_offset_ + flag_byte_count_ * DataSize::kBYTE; + y_coordinates_offset_ = x_coordinates_offset_ + x_byte_count_ * + DataSize::kBYTE; + contour_index_.resize(NumberOfContours() + 1); + contour_index_[0] = 0; + for (uint32_t contour = 0; contour < contour_index_.size() - 1; ++contour) { + contour_index_[contour + 1] = ContourEndPoint(contour) + 1; + } + ParseData(true); + int32_t non_padded_data_length = + 5 * DataSize::kSHORT + + (NumberOfContours() * DataSize::kUSHORT) + + DataSize::kUSHORT + + (instruction_size_ * DataSize::kBYTE) + + (flag_byte_count_ * DataSize::kBYTE) + + (x_byte_count_ * DataSize::kBYTE) + + (y_byte_count_ * DataSize::kBYTE); + set_padding(DataLength() - non_padded_data_length); + initialized_ = true; +} + +void GlyphTable::SimpleGlyph::ParseData(bool fill_arrays) { + int32_t flag = 0; + int32_t flag_repeat = 0; + int32_t flag_index = 0; + int32_t x_byte_index = 0; + int32_t y_byte_index = 0; + + for (int32_t point_index = 0; point_index < number_of_points_; + ++point_index) { + // get the flag for the current point + if (flag_repeat == 0) { + flag = FlagAsInt(flag_index++); + if ((flag & kFLAG_REPEAT) == kFLAG_REPEAT) { + flag_repeat = FlagAsInt(flag_index++); + } + } else { + flag_repeat--; + } + + // on the curve? + if (fill_arrays) { + on_curve_[point_index] = ((flag & kFLAG_ONCURVE) == kFLAG_ONCURVE); + } + // get the x coordinate + if ((flag & kFLAG_XSHORT) == kFLAG_XSHORT) { + // single byte x coord value + if (fill_arrays) { + x_coordinates_[point_index] = + data_->ReadUByte(x_coordinates_offset_ + x_byte_index); + x_coordinates_[point_index] *= + ((flag & kFLAG_XREPEATSIGN) == kFLAG_XREPEATSIGN) ? 1 : -1; + } + x_byte_index++; + } else { + // double byte coord value + if (!((flag & kFLAG_XREPEATSIGN) == kFLAG_XREPEATSIGN)) { + if (fill_arrays) { + x_coordinates_[point_index] = + data_->ReadShort(x_coordinates_offset_ + x_byte_index); + } + x_byte_index += 2; + } + } + if (fill_arrays && point_index > 0) { + x_coordinates_[point_index] += x_coordinates_[point_index - 1]; + } + + // get the y coordinate + if ((flag & kFLAG_YSHORT) == kFLAG_YSHORT) { + if (fill_arrays) { + y_coordinates_[point_index] = + data_->ReadUByte(y_coordinates_offset_ + y_byte_index); + y_coordinates_[point_index] *= + ((flag & kFLAG_YREPEATSIGN) == kFLAG_YREPEATSIGN) ? 1 : -1; + } + y_byte_index++; + } else { + if (!((flag & kFLAG_YREPEATSIGN) == kFLAG_YREPEATSIGN)) { + if (fill_arrays) { + y_coordinates_[point_index] = + data_->ReadShort(y_coordinates_offset_ + y_byte_index); + } + y_byte_index += 2; + } + } + if (fill_arrays && point_index > 0) { + y_coordinates_[point_index] += y_coordinates_[point_index - 1]; + } + } + flag_byte_count_ = flag_index; + x_byte_count_ = x_byte_index; + y_byte_count_ = y_byte_index; +} + +int32_t GlyphTable::SimpleGlyph::FlagAsInt(int32_t index) { + return data_->ReadUByte(flags_offset_ + index * DataSize::kBYTE); +} + +int32_t GlyphTable::SimpleGlyph::ContourEndPoint(int32_t contour) { + return data_->ReadUShort(contour * DataSize::kUSHORT + + Offset::kSimpleEndPtsOfCountours); +} + +/****************************************************************************** + * GlyphTable::SimpleGlyph::Builder + ******************************************************************************/ +GlyphTable::SimpleGlyph::SimpleGlyphBuilder::~SimpleGlyphBuilder() { +} + +GlyphTable::SimpleGlyph::SimpleGlyphBuilder::SimpleGlyphBuilder( + WritableFontData* data) + : Glyph::Builder(data) { +} + +GlyphTable::SimpleGlyph::SimpleGlyphBuilder::SimpleGlyphBuilder( + ReadableFontData* data) + : Glyph::Builder(data) { +} + +CALLER_ATTACH FontDataTable* + GlyphTable::SimpleGlyph::SimpleGlyphBuilder::SubBuildTable( + ReadableFontData* data) { + FontDataTablePtr table = new SimpleGlyph(data); + return table.Detach(); +} + +/****************************************************************************** + * GlyphTable::CompositeGlyph + ******************************************************************************/ +GlyphTable::CompositeGlyph::CompositeGlyph(ReadableFontData* data) + : GlyphTable::Glyph(data, GlyphType::kComposite), + instruction_size_(0), + instructions_offset_(0), + initialized_(false) { + Initialize(); +} + +GlyphTable::CompositeGlyph::~CompositeGlyph() { +} + +int32_t GlyphTable::CompositeGlyph::Flags(int32_t contour) { + return data_->ReadUShort(contour_index_[contour]); +} + +int32_t GlyphTable::CompositeGlyph::NumGlyphs() { + return contour_index_.size(); +} + +int32_t GlyphTable::CompositeGlyph::GlyphIndex(int32_t contour) { + 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_; +} + +CALLER_ATTACH ReadableFontData* GlyphTable::CompositeGlyph::Instructions() { + return down_cast( + data_->Slice(instructions_offset_, InstructionSize())); +} + +void GlyphTable::CompositeGlyph::Initialize() { + AutoLock lock(initialization_lock_); + if (initialized_) { + return; + } + + int32_t index = 5 * DataSize::kUSHORT; + int32_t flags = kFLAG_MORE_COMPONENTS; + + while ((flags & kFLAG_MORE_COMPONENTS) == kFLAG_MORE_COMPONENTS) { + contour_index_.push_back(index); + flags = data_->ReadUShort(index); + 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; + } else { + index += 2 * DataSize::kBYTE; + } + if ((flags & kFLAG_WE_HAVE_A_SCALE) == kFLAG_WE_HAVE_A_SCALE) { + index += DataSize::kF2DOT14; + } else if ((flags & kFLAG_WE_HAVE_AN_X_AND_Y_SCALE) == + kFLAG_WE_HAVE_AN_X_AND_Y_SCALE) { + index += 2 * DataSize::kF2DOT14; + } else if ((flags & kFLAG_WE_HAVE_A_TWO_BY_TWO) == + kFLAG_WE_HAVE_A_TWO_BY_TWO) { + index += 4 * DataSize::kF2DOT14; + } + int32_t non_padded_data_length = index; + if ((flags & kFLAG_WE_HAVE_INSTRUCTIONS) == kFLAG_WE_HAVE_INSTRUCTIONS) { + instruction_size_ = data_->ReadUShort(index); + index += DataSize::kUSHORT; + instructions_offset_ = index; + non_padded_data_length = index + (instruction_size_ * DataSize::kBYTE); + } + set_padding(DataLength() - non_padded_data_length); + } + + initialized_ = true; +} + +/****************************************************************************** + * GlyphTable::CompositeGlyph::Builder + ******************************************************************************/ +GlyphTable::CompositeGlyph::CompositeGlyphBuilder::~CompositeGlyphBuilder() { +} + +GlyphTable::CompositeGlyph::CompositeGlyphBuilder::CompositeGlyphBuilder( + WritableFontData* data) + : Glyph::Builder(data) { +} + +GlyphTable::CompositeGlyph::CompositeGlyphBuilder::CompositeGlyphBuilder( + ReadableFontData* data) + : Glyph::Builder(data) { +} + +CALLER_ATTACH FontDataTable* + GlyphTable::CompositeGlyph::CompositeGlyphBuilder::SubBuildTable( + ReadableFontData* data) { + FontDataTablePtr table = new CompositeGlyph(data); + return table.Detach(); +} + +} // namespace sfntly diff --git a/src/sfntly/src/sfntly/table/truetype/glyph_table.h b/src/sfntly/src/sfntly/table/truetype/glyph_table.h new file mode 100644 index 000000000000..08369718949c --- /dev/null +++ b/src/sfntly/src/sfntly/table/truetype/glyph_table.h @@ -0,0 +1,335 @@ +/* + * 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. + */ + +#ifndef SFNTLY_CPP_SRC_SFNTLY_TABLE_TRUETYPE_GLYPH_TABLE_H_ +#define SFNTLY_CPP_SRC_SFNTLY_TABLE_TRUETYPE_GLYPH_TABLE_H_ + +#include + +#include "sfntly/table/table.h" +#include "sfntly/table/subtable.h" +#include "sfntly/table/subtable_container_table.h" + +namespace sfntly { + +struct GlyphType { + enum { + kSimple = 0, + kComposite = 1 + }; +}; + +class GlyphTable : public SubTableContainerTable, + public RefCounted { + public: + class Builder; + class Glyph : public SubTable { + public: + // Note: Contour is an empty class for the version ported + class Contour { + protected: + Contour() {} + virtual ~Contour() {} + }; + + class Builder : public SubTable::Builder { + public: + virtual ~Builder(); + + protected: + // Incoming table_builder is GlyphTable::Builder*. + // Note: constructor refactored in C++ to avoid heavy lifting. + // caller need to do data->Slice(offset, length) beforehand. + explicit Builder(WritableFontData* data); + explicit Builder(ReadableFontData* data); + + static CALLER_ATTACH Builder* + GetBuilder(GlyphTable::Builder* table_builder, + ReadableFontData* data); + static CALLER_ATTACH Builder* + GetBuilder(GlyphTable::Builder* table_builder, + ReadableFontData* data, + int32_t offset, + int32_t length); + virtual void SubDataSet(); + virtual int32_t SubDataSizeToSerialize(); + virtual bool SubReadyToSerialize(); + virtual int32_t SubSerialize(WritableFontData* new_data); + + private: + int32_t format_; + friend class GlyphTable::Builder; + }; + + virtual ~Glyph(); + static CALLER_ATTACH Glyph* GetGlyph(GlyphTable* table, + ReadableFontData* data, + int32_t offset, + int32_t length); + + virtual int32_t Padding(); + virtual int32_t GlyphType(); + virtual int32_t NumberOfContours(); + virtual int32_t XMin(); + virtual int32_t XMax(); + virtual int32_t YMin(); + virtual int32_t YMax(); + + virtual int32_t InstructionSize() = 0; + virtual ReadableFontData* Instructions() = 0; + + protected: + // Note: constructor refactored in C++ to avoid heavy lifting. + // caller need to do data->Slice(offset, length) beforehand. + Glyph(ReadableFontData* data, int32_t glyph_type); + virtual void Initialize() = 0; + // Note: Derived class to define initialization_lock_. + + private: + static int32_t GlyphType(ReadableFontData* data, + int32_t offset, + int32_t length); + + int32_t glyph_type_; + int32_t number_of_contours_; + }; // class GlyphTable::Glyph + typedef Ptr GlyphBuilderPtr; + typedef std::vector GlyphBuilderList; + + class Builder : public SubTableContainerTable::Builder, + public RefCounted { + public: + // Note: Constructor scope altered to public for base class to instantiate. + Builder(Header* header, ReadableFontData* data); + virtual ~Builder(); + + virtual void SetLoca(const IntegerList& loca); + virtual void GenerateLocaList(IntegerList* locas); + + static CALLER_ATTACH Builder* CreateBuilder(Header* header, + WritableFontData* data); + + // Gets the List of glyph builders for the glyph table builder. These may be + // manipulated in any way by the caller and the changes will be reflected in + // the final glyph table produced. + // If there is no current data for the glyph builder or the glyph builders + // have not been previously set then this will return an empty glyph builder + // List. If there is current data (i.e. data read from an existing font) and + // the loca list has not been set or is null, empty, or + // invalid, then an empty glyph builder List will be returned. + GlyphBuilderList* GlyphBuilders(); + + // Replace the internal glyph builders with the one provided. The provided + // list and all contained objects belong to this builder. + // This call is only required if the entire set of glyphs in the glyph + // table builder are being replaced. If the glyph builder list provided from + // the GlyphTable.Builder::GlyphBuilders() is being used and modified + // then those changes will already be reflected in the glyph table builder. + void SetGlyphBuilders(GlyphBuilderList* glyph_builders); + + // Glyph builder factories + CALLER_ATTACH Glyph::Builder* GlyphBuilder(ReadableFontData* data); + + protected: // internal API for building + virtual CALLER_ATTACH FontDataTable* SubBuildTable(ReadableFontData* data); + virtual void SubDataSet(); + virtual int32_t SubDataSizeToSerialize(); + virtual bool SubReadyToSerialize(); + virtual int32_t SubSerialize(WritableFontData* new_data); + + private: + void Initialize(ReadableFontData* data, const IntegerList& loca); + GlyphBuilderList* GetGlyphBuilders(); + void Revert(); + + GlyphBuilderList glyph_builders_; + IntegerList loca_; + }; + + class SimpleGlyph : public Glyph, public RefCounted { + public: + static const int32_t kFLAG_ONCURVE; + static const int32_t kFLAG_XSHORT; + static const int32_t kFLAG_YSHORT; + static const int32_t kFLAG_REPEAT; + static const int32_t kFLAG_XREPEATSIGN; + static const int32_t kFLAG_YREPEATSIGN; + + class SimpleContour : public Glyph::Contour { + protected: + SimpleContour() {} + virtual ~SimpleContour() {} + }; + + class SimpleGlyphBuilder : public Glyph::Builder, + public RefCounted { + public: + virtual ~SimpleGlyphBuilder(); + + protected: + // Note: constructor refactored in C++ to avoid heavy lifting. + // caller need to do data->Slice(offset, length) beforehand. + explicit SimpleGlyphBuilder(WritableFontData* data); + explicit SimpleGlyphBuilder(ReadableFontData* data); + virtual CALLER_ATTACH FontDataTable* + SubBuildTable(ReadableFontData* data); + + private: + friend class Glyph::Builder; + }; + + // Note: constructor refactored in C++ to avoid heavy lifting. + // caller need to do data->Slice(offset, length) beforehand. + explicit SimpleGlyph(ReadableFontData* data); + virtual ~SimpleGlyph(); + + virtual int32_t InstructionSize(); + 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); + int32_t ContourEndPoint(int32_t contour); + + bool initialized_; + Lock initialization_lock_; + int32_t instruction_size_; + int32_t number_of_points_; + + // start offsets of the arrays + int32_t instructions_offset_; + int32_t flags_offset_; + int32_t x_coordinates_offset_; + int32_t y_coordinates_offset_; + + int32_t flag_byte_count_; + int32_t x_byte_count_; + int32_t y_byte_count_; + + IntegerList x_coordinates_; + IntegerList y_coordinates_; + std::vector on_curve_; + IntegerList contour_index_; + }; + + class CompositeGlyph : public Glyph, public RefCounted { + public: + static const int32_t kFLAG_ARG_1_AND_2_ARE_WORDS; + static const int32_t kFLAG_ARGS_ARE_XY_VALUES; + static const int32_t kFLAG_ROUND_XY_TO_GRID; + static const int32_t kFLAG_WE_HAVE_A_SCALE; + static const int32_t kFLAG_RESERVED; + static const int32_t kFLAG_MORE_COMPONENTS; + static const int32_t kFLAG_WE_HAVE_AN_X_AND_Y_SCALE; + static const int32_t kFLAG_WE_HAVE_A_TWO_BY_TWO; + static const int32_t kFLAG_WE_HAVE_INSTRUCTIONS; + static const int32_t kFLAG_USE_MY_METRICS; + static const int32_t kFLAG_OVERLAP_COMPOUND; + static const int32_t kFLAG_SCALED_COMPONENT_OFFSET; + static const int32_t kFLAG_UNSCALED_COMPONENT_OFFSET; + + class CompositeGlyphBuilder : public Glyph::Builder, + public RefCounted { + public: + virtual ~CompositeGlyphBuilder(); + + protected: + // Note: constructor refactored in C++ to avoid heavy lifting. + // caller need to do data->Slice(offset, length) beforehand. + explicit CompositeGlyphBuilder(WritableFontData* data); + explicit CompositeGlyphBuilder(ReadableFontData* data); + + virtual CALLER_ATTACH FontDataTable* + SubBuildTable(ReadableFontData* data); + + private: + friend class Glyph::Builder; + }; + + // Note: constructor refactored in C++ to avoid heavy lifting. + // caller need to do data->Slice(offset, length) beforehand. + explicit CompositeGlyph(ReadableFontData* data); + virtual ~CompositeGlyph(); + + 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(); + + protected: + virtual void Initialize(); + + private: + IntegerList contour_index_; + int32_t instruction_size_; + int32_t instructions_offset_; + bool initialized_; + Lock initialization_lock_; + }; + + virtual ~GlyphTable(); + + // C++ port: rename glyph() to GetGlyph(). + Glyph* GetGlyph(int32_t offset, int32_t length); + + private: + struct Offset { + enum { + // header + kNumberOfContours = 0, + kXMin = 2, + kYMin = 4, + kXMax = 6, + kYMax = 8, + + // Simple Glyph Description + kSimpleEndPtsOfCountours = 10, + // offset from the end of the contours array + kSimpleInstructionLength = 0, + kSimpleInstructions = 2, + // flags + // xCoordinates + // yCoordinates + + // Composite Glyph Description + kCompositeFlags = 0, + kCompositeGyphIndexWithoutFlag = 0, + kCompositeGlyphIndexWithFlag = 2, + }; + }; + + GlyphTable(Header* header, ReadableFontData* data); +}; +typedef Ptr GlyphTablePtr; +typedef Ptr GlyphTableBuilderPtr; +typedef std::vector GlyphTableBuilderList; +typedef Ptr GlyphPtr; +typedef Ptr GlyphBuilderPtr; + +} // namespace sfntly + +#endif // SFNTLY_CPP_SRC_SFNTLY_TABLE_TRUETYPE_GLYPH_TABLE_H_ diff --git a/src/sfntly/src/sfntly/table/truetype/loca_table.cc b/src/sfntly/src/sfntly/table/truetype/loca_table.cc new file mode 100644 index 000000000000..c692155da8d6 --- /dev/null +++ b/src/sfntly/src/sfntly/table/truetype/loca_table.cc @@ -0,0 +1,246 @@ +/* + * 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. + */ + +#include "sfntly/table/truetype/loca_table.h" +#include "sfntly/port/exception_type.h" + +namespace sfntly { +/****************************************************************************** + * LocaTable class + ******************************************************************************/ +LocaTable::~LocaTable() {} + +int32_t LocaTable::GlyphOffset(int32_t glyph_id) { + if (glyph_id < 0 || glyph_id >= num_glyphs_) { +#if !defined (SFNTLY_NO_EXCEPTION) + throw IndexOutOfBoundException("Glyph ID is out of bounds."); +#endif + return 0; + } + return Loca(glyph_id); +} + +int32_t LocaTable::GlyphLength(int32_t glyph_id) { + if (glyph_id < 0 || glyph_id >= num_glyphs_) { +#if !defined (SFNTLY_NO_EXCEPTION) + throw IndexOutOfBoundException("Glyph ID is out of bounds."); +#endif + return 0; + } + return Loca(glyph_id + 1) - Loca(glyph_id); +} + +int32_t LocaTable::NumLocas() { + return num_glyphs_ + 1; +} + +int32_t LocaTable::Loca(int32_t index) { + if (index > num_glyphs_) { +#if !defined (SFNTLY_NO_EXCEPTION) + throw IndexOutOfBoundException(); +#endif + return 0; + } + if (format_version_ == IndexToLocFormat::kShortOffset) { + return 2 * data_->ReadUShort(index * DataSize::kUSHORT); + } + return data_->ReadULongAsInt(index * DataSize::kULONG); +} + +LocaTable::LocaTable(Header* header, + ReadableFontData* data, + int32_t format_version, + int32_t num_glyphs) + : Table(header, data), + format_version_(format_version), + num_glyphs_(num_glyphs) { +} + +/****************************************************************************** + * LocaTable::Iterator class + ******************************************************************************/ +LocaTable::LocaIterator::LocaIterator(LocaTable* table) + : PODIterator(table), index_(-1) { +} + +bool LocaTable::LocaIterator::HasNext() { + return index_ <= container()->num_glyphs_; +} + +int32_t LocaTable::LocaIterator::Next() { + return container()->Loca(index_++); +} + +/****************************************************************************** + * LocaTable::Builder class + ******************************************************************************/ +LocaTable::Builder::Builder(Header* header, WritableFontData* data) + : Table::Builder(header, data), + format_version_(IndexToLocFormat::kLongOffset), + num_glyphs_(-1) { +} + +LocaTable::Builder::Builder(Header* header, ReadableFontData* data) + : Table::Builder(header, data), + format_version_(IndexToLocFormat::kLongOffset), + num_glyphs_(-1) { +} + +LocaTable::Builder::~Builder() {} + +CALLER_ATTACH +LocaTable::Builder* LocaTable::Builder::CreateBuilder(Header* header, + WritableFontData* data) { + Ptr builder; + builder = new LocaTable::Builder(header, data); + return builder.Detach(); +} + +IntegerList* LocaTable::Builder::LocaList() { + return GetLocaList(); +} + +void LocaTable::Builder::SetLocaList(IntegerList* list) { + loca_.clear(); + if (list) { + loca_ = *list; + set_model_changed(); + } +} + +int32_t LocaTable::Builder::GlyphOffset(int32_t glyph_id) { + if (CheckGlyphRange(glyph_id) == -1) { + return 0; + } + return GetLocaList()->at(glyph_id); +} + +int32_t LocaTable::Builder::GlyphLength(int32_t glyph_id) { + if (CheckGlyphRange(glyph_id) == -1) { + return 0; + } + return GetLocaList()->at(glyph_id + 1) - GetLocaList()->at(glyph_id); +} + +void LocaTable::Builder::SetNumGlyphs(int32_t num_glyphs) { + num_glyphs_ = num_glyphs; +} + +int32_t LocaTable::Builder::NumGlyphs() { + return LastGlyphIndex() - 1; +} + +void LocaTable::Builder::Revert() { + loca_.clear(); + set_model_changed(false); +} + +int32_t LocaTable::Builder::NumLocas() { + return GetLocaList()->size(); +} + +int32_t LocaTable::Builder::Loca(int32_t index) { + return GetLocaList()->at(index); +} + +CALLER_ATTACH +FontDataTable* LocaTable::Builder::SubBuildTable(ReadableFontData* data) { + FontDataTablePtr table = + new LocaTable(header(), data, format_version_, num_glyphs_); + return table.Detach(); +} + +void LocaTable::Builder::SubDataSet() { + Initialize(InternalReadData()); +} + +int32_t LocaTable::Builder::SubDataSizeToSerialize() { + if (loca_.empty()) { + return 0; + } + if (format_version_ == IndexToLocFormat::kLongOffset) { + return loca_.size() * DataSize::kULONG; + } + return loca_.size() * DataSize::kUSHORT; +} + +bool LocaTable::Builder::SubReadyToSerialize() { + return !loca_.empty(); +} + +int32_t LocaTable::Builder::SubSerialize(WritableFontData* new_data) { + int32_t size = 0; + for (IntegerList::iterator l = loca_.begin(), end = loca_.end(); + l != end; ++l) { + if (format_version_ == IndexToLocFormat::kLongOffset) { + size += new_data->WriteULong(size, *l); + } else { + size += new_data->WriteUShort(size, *l / 2); + } + } + num_glyphs_ = loca_.size() - 1; + return size; +} + +void LocaTable::Builder::Initialize(ReadableFontData* data) { + ClearLoca(false); + if (data) { + if (NumGlyphs() < 0) { +#if !defined (SFNTLY_NO_EXCEPTION) + throw IllegalStateException("numglyphs not set on LocaTable Builder."); +#endif + return; + } + LocaTablePtr table = + new LocaTable(header(), data, format_version_, num_glyphs_); + Ptr loca_iter = + new LocaTable::LocaIterator(table); + while (loca_iter->HasNext()) { + loca_.push_back(loca_iter->Next()); + } + } +} + +int32_t LocaTable::Builder::CheckGlyphRange(int32_t glyph_id) { + if (glyph_id < 0 || glyph_id > LastGlyphIndex()) { +#if !defined (SFNTLY_NO_EXCEPTION) + throw IndexOutOfBoundsException("Glyph ID is outside of the allowed range"); +#endif + return -1; + } + return glyph_id; +} + +int32_t LocaTable::Builder::LastGlyphIndex() { + return !loca_.empty() ? loca_.size() - 2 : num_glyphs_ - 1; +} + +IntegerList* LocaTable::Builder::GetLocaList() { + if (loca_.empty()) { + Initialize(InternalReadData()); + set_model_changed(); + } + return &loca_; +} + +void LocaTable::Builder::ClearLoca(bool nullify) { + // Note: in C++ port, nullify is not used at all. + UNREFERENCED_PARAMETER(nullify); + loca_.clear(); + set_model_changed(false); +} + +} // namespace sfntly diff --git a/src/sfntly/src/sfntly/table/truetype/loca_table.h b/src/sfntly/src/sfntly/table/truetype/loca_table.h new file mode 100644 index 000000000000..67c5749b05d9 --- /dev/null +++ b/src/sfntly/src/sfntly/table/truetype/loca_table.h @@ -0,0 +1,183 @@ +/* + * 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. + */ + +#ifndef SFNTLY_CPP_SRC_SFNTLY_TABLE_TRUETYPE_LOCA_TABLE_H_ +#define SFNTLY_CPP_SRC_SFNTLY_TABLE_TRUETYPE_LOCA_TABLE_H_ + +#include "sfntly/port/java_iterator.h" +#include "sfntly/table/table.h" +#include "sfntly/table/core/font_header_table.h" + +namespace sfntly { + +// A Loca table - 'loca'. +class LocaTable : public Table, public RefCounted { + public: + class LocaIterator : public PODIterator { + public: + explicit LocaIterator(LocaTable* table); + virtual ~LocaIterator() {} + + virtual bool HasNext(); + virtual int32_t Next(); + + private: + int32_t index_; + }; + + class Builder : public Table::Builder, public RefCounted { + public: + // Constructor scope altered to public for base class to instantiate. + Builder(Header* header, WritableFontData* data); + Builder(Header* header, ReadableFontData* data); + virtual ~Builder(); + + static CALLER_ATTACH Builder* CreateBuilder(Header* header, + WritableFontData* data); + + // Get the format version that will be used when the loca table is + // generated. + // @return the loca table format version + int32_t format_version() { return format_version_; } + void set_format_version(int32_t value) { format_version_ = value; } + + // Gets the List of locas for loca table builder. These may be manipulated + // in any way by the caller and the changes will be reflected in the final + // loca table produced as long as no subsequent call is made to the + // 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(); + + // 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); + + // 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 + // for the notdef glyph. The final entry beyond the last glyph id is used to + // calculate the size of the last glyph. + // @param glyphId the glyph id to get the offset for; must be less than or + // equal to one more than the number of glyph ids + // @return the offset in the glyph table to the specified glyph id + int32_t GlyphOffset(int32_t glyph_id); + + // Get the length of the data in the glyph table for the specified glyph id. + int32_t GlyphLength(int32_t glyph_id); + + // Set the number of glyphs. + // This method sets the number of glyphs that the builder will attempt to + // parse location data for from the raw binary data. This method only needs + // to be called (and must be) when the raw data for this builder has + // been changed. It does not by itself reset the data or clear any set loca + // list. + void SetNumGlyphs(int32_t num_glyphs); + + // Get the number of glyphs that this builder has support for. + int NumGlyphs(); + + // Revert the loca table builder to the state contained in the last raw data + // set on the builder. That raw data may be that read from a font file when + // the font builder was created, that set by a user of the loca table + // builder, or null data if this builder was created as a new empty builder. + void Revert(); + + // Get the number of locations or locas. This will be one more than the + // number of glyphs for this table since the last loca position is used to + // indicate the size of the final glyph. + int32_t NumLocas(); + + // Get the value from the loca table for the index specified. These are the + // raw values from the table that are used to compute the offset and size of + // a glyph in the glyph table. Valid index values run from 0 to the number + // of glyphs in the font. + int32_t Loca(int32_t index); + + virtual CALLER_ATTACH FontDataTable* SubBuildTable(ReadableFontData* data); + virtual void SubDataSet(); + virtual int32_t SubDataSizeToSerialize(); + virtual bool SubReadyToSerialize(); + virtual int32_t SubSerialize(WritableFontData* new_data); + + private: + // Initialize the internal state from the data. Done lazily since in many + // cases the builder will be just creating a table object with no parsing + // required. + // @param data the data to initialize from + void Initialize(ReadableFontData* data); + + // Checks that the glyph id is within the correct range. + // @return glyph_id if correct, -1 otherwise. + int32_t CheckGlyphRange(int32_t glyph_id); + + int32_t LastGlyphIndex(); + + // 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(); + + void ClearLoca(bool nullify); + + int32_t format_version_; // Note: IndexToLocFormat + int32_t num_glyphs_; + IntegerList loca_; + }; + + virtual ~LocaTable(); + + int32_t format_version() { return format_version_; } + int32_t num_glyphs() { return num_glyphs_; } + + // Return the offset for the given glyph id. Valid glyph ids are from 0 to the + // one less than the number of glyphs. The zero entry is the special entry for + // the notdef glyph. The final entry beyond the last glyph id is used to + // calculate the size of the last glyph. + // @param glyphId the glyph id to get the offset for; must be less than or + // equal to one more than the number of glyph ids + // @return the offset in the glyph table to the specified glyph id + int32_t GlyphOffset(int32_t glyph_id); + + // Get the length of the data in the glyph table for the specified glyph id. + int32_t GlyphLength(int32_t glyph_id); + + // Get the number of locations or locas. This will be one more than the number + // of glyphs for this table since the last loca position is used to indicate + // the size of the final glyph. + int32_t NumLocas(); + + // Get the value from the loca table for the index specified. Valid index + // values run from 0 to the number of glyphs in the font. + int32_t Loca(int32_t index); + + private: + LocaTable(Header* header, + ReadableFontData* data, + int32_t format_version, + int32_t num_glyphs); + + int32_t format_version_; // Note: Java's version, renamed to format_version_ + int32_t num_glyphs_; + + friend class LocaIterator; +}; +typedef Ptr LocaTablePtr; +typedef Ptr LocaTableBuilderPtr; + +} // namespace sfntly + +#endif // SFNTLY_CPP_SRC_SFNTLY_TABLE_TRUETYPE_LOCA_TABLE_H_ diff --git a/src/sfntly/src/sfntly/tag.cc b/src/sfntly/src/sfntly/tag.cc new file mode 100644 index 000000000000..c9d8c29878fb --- /dev/null +++ b/src/sfntly/src/sfntly/tag.cc @@ -0,0 +1,110 @@ +/* + * 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. + */ + +#include "sfntly/tag.h" +#include "sfntly/port/endian.h" + +// Use a macro instead of GenerateTag() because gcc 4.4.3 creates static +// initializers in that case. +#define TAG(a, b, c, d) ((a << 24) | (b << 16) | (c << 8) | d); + +namespace sfntly { + +const int32_t Tag::ttcf = TAG('t', 't', 'c', 'f'); +const int32_t Tag::cmap = TAG('c', 'm', 'a', 'p'); +const int32_t Tag::head = TAG('h', 'e', 'a', 'd'); +const int32_t Tag::hhea = TAG('h', 'h', 'e', 'a'); +const int32_t Tag::hmtx = TAG('h', 'm', 't', 'x'); +const int32_t Tag::maxp = TAG('m', 'a', 'x', 'p'); +const int32_t Tag::name = TAG('n', 'a', 'm', 'e'); +const int32_t Tag::OS_2 = TAG('O', 'S', '/', '2'); +const int32_t Tag::post = TAG('p', 'o', 's', 't'); +const int32_t Tag::cvt = TAG('c', 'v', 't', ' '); +const int32_t Tag::fpgm = TAG('f', 'p', 'g', 'm'); +const int32_t Tag::glyf = TAG('g', 'l', 'y', 'f'); +const int32_t Tag::loca = TAG('l', 'o', 'c', 'a'); +const int32_t Tag::prep = TAG('p', 'r', 'e', 'p'); +const int32_t Tag::CFF = TAG('C', 'F', 'F', ' '); +const int32_t Tag::VORG = TAG('V', 'O', 'R', 'G'); +const int32_t Tag::EBDT = TAG('E', 'B', 'D', 'T'); +const int32_t Tag::EBLC = TAG('E', 'B', 'L', 'C'); +const int32_t Tag::EBSC = TAG('E', 'B', 'S', 'C'); +const int32_t Tag::BASE = TAG('B', 'A', 'S', 'E'); +const int32_t Tag::GDEF = TAG('G', 'D', 'E', 'F'); +const int32_t Tag::GPOS = TAG('G', 'P', 'O', 'S'); +const int32_t Tag::GSUB = TAG('G', 'S', 'U', 'B'); +const int32_t Tag::JSTF = TAG('J', 'S', 'T', 'F'); +const int32_t Tag::DSIG = TAG('D', 'S', 'I', 'G'); +const int32_t Tag::gasp = TAG('g', 'a', 's', 'p'); +const int32_t Tag::hdmx = TAG('h', 'd', 'm', 'x'); +const int32_t Tag::kern = TAG('k', 'e', 'r', 'n'); +const int32_t Tag::LTSH = TAG('L', 'T', 'S', 'H'); +const int32_t Tag::PCLT = TAG('P', 'C', 'L', 'T'); +const int32_t Tag::VDMX = TAG('V', 'D', 'M', 'X'); +const int32_t Tag::vhea = TAG('v', 'h', 'e', 'a'); +const int32_t Tag::vmtx = TAG('v', 'm', 't', 'x'); +const int32_t Tag::bsln = TAG('b', 's', 'l', 'n'); +const int32_t Tag::feat = TAG('f', 'e', 'a', 't'); +const int32_t Tag::lcar = TAG('l', 'c', 'a', 'r'); +const int32_t Tag::morx = TAG('m', 'o', 'r', 'x'); +const int32_t Tag::opbd = TAG('o', 'p', 'b', 'd'); +const int32_t Tag::prop = TAG('p', 'r', 'o', 'p'); +const int32_t Tag::Feat = TAG('F', 'e', 'a', 't'); +const int32_t Tag::Glat = TAG('G', 'l', 'a', 't'); +const int32_t Tag::Gloc = TAG('G', 'l', 'o', 'c'); +const int32_t Tag::Sile = TAG('S', 'i', 'l', 'e'); +const int32_t Tag::Silf = TAG('S', 'i', 'l', 'f'); +const int32_t Tag::bhed = TAG('b', 'h', 'e', 'd'); +const int32_t Tag::bdat = TAG('b', 'd', 'a', 't'); +const int32_t Tag::bloc = TAG('b', 'l', 'o', 'c'); + +const int32_t CFF_TABLE_ORDERING[] = { + Tag::head, + Tag::hhea, + Tag::maxp, + Tag::OS_2, + Tag::name, + Tag::cmap, + Tag::post, + Tag::CFF }; +const size_t CFF_TABLE_ORDERING_SIZE = + sizeof(CFF_TABLE_ORDERING) / sizeof(int32_t); + +const int32_t TRUE_TYPE_TABLE_ORDERING[] = { + Tag::head, + Tag::hhea, + Tag::maxp, + Tag::OS_2, + Tag::hmtx, + Tag::LTSH, + Tag::VDMX, + Tag::hdmx, + Tag::cmap, + Tag::fpgm, + Tag::prep, + Tag::cvt, + Tag::loca, + Tag::glyf, + Tag::kern, + Tag::name, + Tag::post, + Tag::gasp, + Tag::PCLT, + Tag::DSIG }; +const size_t TRUE_TYPE_TABLE_ORDERING_SIZE = + sizeof(TRUE_TYPE_TABLE_ORDERING) / sizeof(int32_t); + +} // namespace sfntly diff --git a/src/sfntly/src/sfntly/tag.h b/src/sfntly/src/sfntly/tag.h new file mode 100644 index 000000000000..0ecbab85b4bc --- /dev/null +++ b/src/sfntly/src/sfntly/tag.h @@ -0,0 +1,123 @@ +/* + * 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. + */ + +#ifndef SFNTLY_CPP_SRC_SFNTLY_TAG_H_ +#define SFNTLY_CPP_SRC_SFNTLY_TAG_H_ + +#include + +#include "sfntly/port/type.h" + +namespace sfntly { + +// Font identification tags used for tables, features, etc. +// Tag names are consistent with the OpenType and sfnt specs. +struct Tag { + static const int32_t ttcf; + + // Table Type Tags + // required tables + static const int32_t cmap; + static const int32_t head; + static const int32_t hhea; + static const int32_t hmtx; + static const int32_t maxp; + static const int32_t name; + static const int32_t OS_2; + static const int32_t post; + + // TrueType outline tables + static const int32_t cvt; + static const int32_t fpgm; + static const int32_t glyf; + static const int32_t loca; + static const int32_t prep; + + // PostScript outline tables + static const int32_t CFF; + static const int32_t VORG; + + // opentype bitmap glyph outlines + static const int32_t EBDT; + static const int32_t EBLC; + static const int32_t EBSC; + + // advanced typographic features + static const int32_t BASE; + static const int32_t GDEF; + static const int32_t GPOS; + static const int32_t GSUB; + static const int32_t JSTF; + + // other + static const int32_t DSIG; + static const int32_t gasp; + static const int32_t hdmx; + static const int32_t kern; + static const int32_t LTSH; + static const int32_t PCLT; + static const int32_t VDMX; + static const int32_t vhea; + static const int32_t vmtx; + + // AAT tables + static const int32_t bsln; + static const int32_t feat; + static const int32_t lcar; + static const int32_t morx; + static const int32_t opbd; + static const int32_t prop; + + // Graphite tables + static const int32_t Feat; + static const int32_t Glat; + static const int32_t Gloc; + static const int32_t Sile; + static const int32_t Silf; + + // truetype bitmap font tables + static const int32_t bhed; + static const int32_t bdat; + static const int32_t bloc; +}; + +// Create integer tag value for human readable tag name. +inline int32_t GenerateTag(int32_t a, int32_t b, int32_t c, int32_t d) { + return (a << 24) | (b << 16) | (c << 8) | d; +} + +// Translate tag to human readable string. +// The Caller must delete[] the returned value. +inline char* TagToString(int32_t tag) { + char *name = new char[5]; + name[0] = static_cast((tag & 0xff000000) >> 24); + name[1] = static_cast((tag & 0x00ff0000) >> 16); + name[2] = static_cast((tag & 0x0000ff00) >> 8); + name[3] = static_cast(tag & 0x000000ff); + name[4] = 0; + return name; +} + +// Note: For Java, these two orderings are in Font class. Moved here to avoid +// VC++ bug of not populating correct values. +extern const int32_t CFF_TABLE_ORDERING[]; +extern const size_t CFF_TABLE_ORDERING_SIZE; +extern const int32_t TRUE_TYPE_TABLE_ORDERING[]; +extern const size_t TRUE_TYPE_TABLE_ORDERING_SIZE; + +} // namespace sfntly + +#endif // SFNTLY_CPP_SRC_SFNTLY_TAG_H_ diff --git a/src/sfntly/src/sfntly/tools/subsetter/glyph_table_subsetter.cc b/src/sfntly/src/sfntly/tools/subsetter/glyph_table_subsetter.cc new file mode 100644 index 000000000000..b3d6b07e4470 --- /dev/null +++ b/src/sfntly/src/sfntly/tools/subsetter/glyph_table_subsetter.cc @@ -0,0 +1,90 @@ +/* + * 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. + */ + +#include "sfntly/tools/subsetter/glyph_table_subsetter.h" + +#include "sfntly/table/truetype/glyph_table.h" +#include "sfntly/table/truetype/loca_table.h" +#include "sfntly/tag.h" +#include "sfntly/tools/subsetter/subsetter.h" +#include "sfntly/port/exception_type.h" + +namespace sfntly { + +const int32_t kGlyphTableSubsetterTags[2] = {Tag::glyf, Tag::loca}; + +GlyphTableSubsetter::GlyphTableSubsetter() + : TableSubsetterImpl(kGlyphTableSubsetterTags, 2) { +} + +GlyphTableSubsetter::~GlyphTableSubsetter() {} + +bool GlyphTableSubsetter::Subset(Subsetter* subsetter, + Font* font, + Font::Builder* font_builder) { + assert(font); + assert(subsetter); + assert(font_builder); + + IntegerList* permutation_table = subsetter->GlyphPermutationTable(); + if (!permutation_table || permutation_table->empty()) + return false; + + GlyphTablePtr glyph_table = down_cast(font->GetTable(Tag::glyf)); + LocaTablePtr loca_table = down_cast(font->GetTable(Tag::loca)); + if (glyph_table == NULL || loca_table == NULL) { +#if !defined (SFNTLY_NO_EXCEPTION) + throw RuntimeException("Font to subset is not valid."); +#endif + return false; + } + + GlyphTableBuilderPtr glyph_table_builder = + down_cast + (font_builder->NewTableBuilder(Tag::glyf)); + LocaTableBuilderPtr loca_table_builder = + down_cast + (font_builder->NewTableBuilder(Tag::loca)); + if (glyph_table_builder == NULL || loca_table_builder == NULL) { +#if !defined (SFNTLY_NO_EXCEPTION) + throw RuntimeException("Builder for subset is not valid."); +#endif + return false; + } + GlyphTable::GlyphBuilderList* glyph_builders = + glyph_table_builder->GlyphBuilders(); + for (IntegerList::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); + int old_length = loca_table->GlyphLength(*old_glyph_id); + GlyphPtr glyph; + glyph.Attach(glyph_table->GetGlyph(old_offset, old_length)); + ReadableFontDataPtr data = glyph->ReadFontData(); + WritableFontDataPtr copy_data; + copy_data.Attach(WritableFontData::CreateWritableFontData(data->Length())); + data->CopyTo(copy_data); + GlyphBuilderPtr glyph_builder; + glyph_builder.Attach(glyph_table_builder->GlyphBuilder(copy_data)); + glyph_builders->push_back(glyph_builder); + } + IntegerList loca_list; + glyph_table_builder->GenerateLocaList(&loca_list); + loca_table_builder->SetLocaList(&loca_list); + return true; +} + +} // namespace sfntly diff --git a/src/sfntly/src/sfntly/tools/subsetter/glyph_table_subsetter.h b/src/sfntly/src/sfntly/tools/subsetter/glyph_table_subsetter.h new file mode 100644 index 000000000000..88c704443f63 --- /dev/null +++ b/src/sfntly/src/sfntly/tools/subsetter/glyph_table_subsetter.h @@ -0,0 +1,37 @@ +/* + * 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. + */ + +#ifndef SFNTLY_CPP_SRC_SFNTLY_TOOLS_SUBSETTER_GLYPH_TABLE_SUBSETTER_H_ +#define SFNTLY_CPP_SRC_SFNTLY_TOOLS_SUBSETTER_GLYPH_TABLE_SUBSETTER_H_ + +#include "sfntly/tools/subsetter/table_subsetter_impl.h" + +namespace sfntly { + +class GlyphTableSubsetter : public TableSubsetterImpl, + public RefCounted { + public: + GlyphTableSubsetter(); + virtual ~GlyphTableSubsetter(); + + virtual bool Subset(Subsetter* subsetter, + Font* font, + Font::Builder* font_builder); +}; + +} // namespace sfntly + +#endif // SFNTLY_CPP_SRC_SFNTLY_TOOLS_SUBSETTER_GLYPH_TABLE_SUBSETTER_H_ diff --git a/src/sfntly/src/sfntly/tools/subsetter/subsetter.cc b/src/sfntly/src/sfntly/tools/subsetter/subsetter.cc new file mode 100644 index 000000000000..7d987796b994 --- /dev/null +++ b/src/sfntly/src/sfntly/tools/subsetter/subsetter.cc @@ -0,0 +1,102 @@ +/* + * 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. + */ + +#include "sfntly/tools/subsetter/subsetter.h" + +#include +#include + +#include "sfntly/tools/subsetter/glyph_table_subsetter.h" + +namespace sfntly { + +Subsetter::Subsetter(Font* font, FontFactory* font_factory) { + font_ = font; + font_factory_ = font_factory; + TableSubsetterPtr subsetter = new GlyphTableSubsetter(); + // TODO(arthurhsu): IMPLEMENT: CMap table subsetter + table_subsetters_.push_back(subsetter); +} + +Subsetter::~Subsetter() { + font_factory_.Release(); + font_.Release(); + table_subsetters_.clear(); +} + +void Subsetter::SetGlyphs(IntegerList* glyphs) { + new_to_old_glyphs_ = *glyphs; +} + +void Subsetter::SetCMaps(CMapIdList* cmap_ids, int32_t number) { + UNREFERENCED_PARAMETER(cmap_ids); + UNREFERENCED_PARAMETER(number); + // TODO(arthurhsu): IMPLEMENT +} + +void Subsetter::SetRemoveTables(IntegerSet* remove_tables) { + remove_tables_ = *remove_tables; +} + +CALLER_ATTACH Font::Builder* Subsetter::Subset() { + FontBuilderPtr font_builder; + font_builder.Attach(font_factory_->NewFontBuilder()); + + IntegerSet 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_difference(table_tags.begin(), table_tags.end(), + remove_tables_.begin(), remove_tables_.end(), + std::inserter(result, result.end())); + table_tags = result; + } + for (TableSubsetterList::iterator + table_subsetter = table_subsetters_.begin(), + table_subsetter_end = table_subsetters_.end(); + 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_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(), + tag_end = table_tags.end(); tag != tag_end; ++tag) { + Table* table = font_->GetTable(*tag); + if (table) { + font_builder->NewTableBuilder(*tag, table->ReadFontData()); + } + } + return font_builder.Detach(); +} + +IntegerList* Subsetter::GlyphPermutationTable() { + return &new_to_old_glyphs_; +} + +CMapIdList* Subsetter::CMapId() { + return &cmap_ids_; +} + +} // namespace sfntly diff --git a/src/sfntly/src/sfntly/tools/subsetter/subsetter.h b/src/sfntly/src/sfntly/tools/subsetter/subsetter.h new file mode 100644 index 000000000000..85940a792888 --- /dev/null +++ b/src/sfntly/src/sfntly/tools/subsetter/subsetter.h @@ -0,0 +1,72 @@ +/* + * 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. + */ + +#ifndef SFNTLY_CPP_SRC_SFNTLY_TOOLS_SUBSETTER_SUBSETTER_H_ +#define SFNTLY_CPP_SRC_SFNTLY_TOOLS_SUBSETTER_SUBSETTER_H_ + +#include + +#include "sfntly/font.h" +#include "sfntly/font_factory.h" +#include "sfntly/table/core/cmap_table.h" +#include "sfntly/tools/subsetter/table_subsetter.h" + +namespace sfntly { + +class Subsetter : public RefCounted { + public: + Subsetter(Font* font, FontFactory* font_factory); + virtual ~Subsetter(); + + virtual void SetGlyphs(IntegerList* 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 + // list should be put into the subsetted font. If there are no matches in the + // font for any of the provided cmap ids which would lead to a font with no + // cmap then an error will be thrown during subsetting. + // The two most common cases would be: + // * a list of one or more cmap ids with a count setting of 1 + // This will use the list of cmap ids as an ordered priority and look for + // an available cmap in the font that matches the requests. Only the first + // such match will be placed in the subsetted font. + // * a list of one or more cmap ids with a count setting equal to the list + // length + // This will use the list of cmap ids and try to place each one specified + // into the subsetted font. + // @param cmapIds the cmap ids to use for the subsetted font + // @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 CALLER_ATTACH Font::Builder* Subset(); + virtual IntegerList* GlyphPermutationTable(); + virtual CMapIdList* CMapId(); + + private: + FontPtr font_; + FontFactoryPtr font_factory_; + TableSubsetterList table_subsetters_; + + // Settings from user + IntegerSet remove_tables_; + IntegerList new_to_old_glyphs_; + CMapIdList cmap_ids_; +}; + +} // namespace sfntly + +#endif // SFNTLY_CPP_SRC_SFNTLY_TOOLS_SUBSETTER_SUBSETTER_H_ diff --git a/src/sfntly/src/sfntly/tools/subsetter/table_subsetter.h b/src/sfntly/src/sfntly/tools/subsetter/table_subsetter.h new file mode 100644 index 000000000000..1336615b07e4 --- /dev/null +++ b/src/sfntly/src/sfntly/tools/subsetter/table_subsetter.h @@ -0,0 +1,39 @@ +/* + * 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. + */ + +#ifndef SFNTLY_CPP_SRC_SFNTLY_TOOLS_SUBSETTER_TABLE_SUBSETTER_H_ +#define SFNTLY_CPP_SRC_SFNTLY_TOOLS_SUBSETTER_TABLE_SUBSETTER_H_ + +#include + +#include "sfntly/font.h" + +namespace sfntly { + +class Subsetter; +class TableSubsetter : virtual public RefCount { + public: + virtual IntegerSet* TagsHandled() = 0; + virtual bool TagHandled(int32_t tag) = 0; + virtual bool Subset(Subsetter* subsetter, Font* font, + Font::Builder* font_builder) = 0; +}; +typedef Ptr TableSubsetterPtr; +typedef std::vector TableSubsetterList; + +} // namespace sfntly + +#endif // SFNTLY_CPP_SRC_SFNTLY_TOOLS_SUBSETTER_TABLE_SUBSETTER_H_ diff --git a/src/sfntly/src/sfntly/tools/subsetter/table_subsetter_impl.cc b/src/sfntly/src/sfntly/tools/subsetter/table_subsetter_impl.cc new file mode 100644 index 000000000000..f239c78e3c2b --- /dev/null +++ b/src/sfntly/src/sfntly/tools/subsetter/table_subsetter_impl.cc @@ -0,0 +1,38 @@ +/* + * 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. + */ + +#include "sfntly/tools/subsetter/table_subsetter_impl.h" + +namespace sfntly { + +TableSubsetterImpl::TableSubsetterImpl(const int32_t* tags, + size_t tags_length) { + for (size_t i = 0; i < tags_length; ++i) { + tags_.insert(tags[i]); + } +} + +TableSubsetterImpl::~TableSubsetterImpl() {} + +bool TableSubsetterImpl::TagHandled(int32_t tag) { + return tags_.find(tag) != tags_.end(); +} + +IntegerSet* TableSubsetterImpl::TagsHandled() { + return &tags_; +} + +} // namespace sfntly diff --git a/src/sfntly/src/sfntly/tools/subsetter/table_subsetter_impl.h b/src/sfntly/src/sfntly/tools/subsetter/table_subsetter_impl.h new file mode 100644 index 000000000000..de0d9a98ca42 --- /dev/null +++ b/src/sfntly/src/sfntly/tools/subsetter/table_subsetter_impl.h @@ -0,0 +1,37 @@ +/* + * 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. + */ + +#ifndef SFNTLY_CPP_SRC_SFNTLY_TOOLS_SUBSETTER_TABLE_SUBSETTER_IMPL_H_ +#define SFNTLY_CPP_SRC_SFNTLY_TOOLS_SUBSETTER_TABLE_SUBSETTER_IMPL_H_ + +#include "sfntly/tools/subsetter/table_subsetter.h" + +namespace sfntly { + +class TableSubsetterImpl : public TableSubsetter { + public: + TableSubsetterImpl(const int32_t* tags, size_t tags_length); + virtual ~TableSubsetterImpl(); + virtual bool TagHandled(int32_t tag); + virtual IntegerSet* TagsHandled(); + + protected: + IntegerSet tags_; +}; + +} // namespace sfntly + +#endif // SFNTLY_CPP_SRC_SFNTLY_TOOLS_SUBSETTER_TABLE_SUBSETTER_IMPL_H_