From 464987db923362e596195f9eebd34fc508c9a412 Mon Sep 17 00:00:00 2001 From: "arthurhsu@google.com" Date: Thu, 23 Jun 2011 17:20:41 +0000 Subject: Initial release git-svn-id: http://sfntly.googlecode.com/svn/trunk/cpp/src@2 672e30a5-4c29-85ac-ac6d-611c735e0a51 --- sample/subsetter/main.cc | 44 ++ sample/subsetter/subset_util.cc | 96 ++++ sample/subsetter/subset_util.h | 32 ++ sfntly/cmap_table.cc | 530 +++++++++++++++++++ sfntly/cmap_table.h | 408 +++++++++++++++ sfntly/data/byte_array.cc | 182 +++++++ sfntly/data/byte_array.h | 143 +++++ sfntly/data/font_data.cc | 97 ++++ sfntly/data/font_data.h | 118 +++++ sfntly/data/font_input_stream.cc | 145 +++++ sfntly/data/font_input_stream.h | 68 +++ sfntly/data/font_output_stream.cc | 107 ++++ sfntly/data/font_output_stream.h | 59 +++ sfntly/data/growable_memory_byte_array.cc | 67 +++ sfntly/data/growable_memory_byte_array.h | 48 ++ sfntly/data/memory_byte_array.cc | 85 +++ sfntly/data/memory_byte_array.h | 50 ++ sfntly/data/readable_font_data.cc | 197 +++++++ sfntly/data/readable_font_data.h | 124 +++++ sfntly/data/writable_font_data.cc | 128 +++++ sfntly/data/writable_font_data.h | 66 +++ sfntly/font.cc | 593 +++++++++++++++++++++ sfntly/font.h | 289 ++++++++++ sfntly/font_data_table.cc | 186 +++++++ sfntly/font_data_table.h | 111 ++++ sfntly/font_data_table_builder_container.h | 34 ++ sfntly/font_factory.cc | 250 +++++++++ sfntly/font_factory.h | 147 ++++++ sfntly/font_header_table.cc | 289 ++++++++++ sfntly/font_header_table.h | 163 ++++++ sfntly/glyph_table.cc | 645 +++++++++++++++++++++++ sfntly/glyph_table.h | 331 ++++++++++++ sfntly/horizontal_header_table.cc | 229 ++++++++ sfntly/horizontal_header_table.h | 108 ++++ sfntly/horizontal_metrics_table.cc | 137 +++++ sfntly/horizontal_metrics_table.h | 84 +++ sfntly/loca_table.cc | 221 ++++++++ sfntly/loca_table.h | 147 ++++++ sfntly/math/fixed1616.h | 41 ++ sfntly/math/font_math.h | 38 ++ sfntly/maximum_profile_table.cc | 241 +++++++++ sfntly/maximum_profile_table.h | 116 ++++ sfntly/name_table.cc | 668 ++++++++++++++++++++++++ sfntly/name_table.h | 530 +++++++++++++++++++ sfntly/os2_table.cc | 368 +++++++++++++ sfntly/os2_table.h | 393 ++++++++++++++ sfntly/port/atomic.h | 70 +++ sfntly/port/config.h | 28 + sfntly/port/endian.h | 77 +++ sfntly/port/exception_type.h | 107 ++++ sfntly/port/file_input_stream.cc | 139 +++++ sfntly/port/file_input_stream.h | 57 ++ sfntly/port/input_stream.h | 48 ++ sfntly/port/memory_output_stream.cc | 49 ++ sfntly/port/memory_output_stream.h | 49 ++ sfntly/port/output_stream.h | 38 ++ sfntly/port/refcount.h | 253 +++++++++ sfntly/port/type.h | 84 +++ sfntly/subtable.cc | 43 ++ sfntly/subtable.h | 50 ++ sfntly/table.cc | 275 ++++++++++ sfntly/table.h | 178 +++++++ sfntly/tag.cc | 95 ++++ sfntly/tag.h | 99 ++++ sfntly/tools/subsetter.cc | 106 ++++ sfntly/tools/subsetter/glyph_table_subsetter.cc | 82 +++ sfntly/tools/subsetter/glyph_table_subsetter.h | 36 ++ sfntly/tools/subsetter/subsetter.h | 72 +++ sfntly/tools/subsetter/table_subsetter.h | 39 ++ sfntly/tools/subsetter/table_subsetter_impl.cc | 38 ++ sfntly/tools/subsetter/table_subsetter_impl.h | 37 ++ test/byte_array_test.cc | 138 +++++ test/byte_array_test.h | 27 + test/endian_test.cc | 74 +++ test/endian_test.h | 26 + test/font_data_test.cc | 213 ++++++++ test/font_data_test.h | 25 + test/main.cc | 60 +++ test/open_type_data_test.cc | 66 +++ test/open_type_data_test.h | 27 + test/otf_basic_editing_test.cc | 97 ++++ test/otf_basic_editing_test.h | 26 + test/smart_pointer_test.cc | 76 +++ test/smart_pointer_test.h | 22 + 84 files changed, 12179 insertions(+) create mode 100644 sample/subsetter/main.cc create mode 100644 sample/subsetter/subset_util.cc create mode 100644 sample/subsetter/subset_util.h create mode 100644 sfntly/cmap_table.cc create mode 100644 sfntly/cmap_table.h create mode 100644 sfntly/data/byte_array.cc create mode 100644 sfntly/data/byte_array.h create mode 100644 sfntly/data/font_data.cc create mode 100644 sfntly/data/font_data.h create mode 100644 sfntly/data/font_input_stream.cc create mode 100644 sfntly/data/font_input_stream.h create mode 100644 sfntly/data/font_output_stream.cc create mode 100644 sfntly/data/font_output_stream.h create mode 100644 sfntly/data/growable_memory_byte_array.cc create mode 100644 sfntly/data/growable_memory_byte_array.h create mode 100644 sfntly/data/memory_byte_array.cc create mode 100644 sfntly/data/memory_byte_array.h create mode 100644 sfntly/data/readable_font_data.cc create mode 100644 sfntly/data/readable_font_data.h create mode 100644 sfntly/data/writable_font_data.cc create mode 100644 sfntly/data/writable_font_data.h create mode 100644 sfntly/font.cc create mode 100644 sfntly/font.h create mode 100644 sfntly/font_data_table.cc create mode 100644 sfntly/font_data_table.h create mode 100644 sfntly/font_data_table_builder_container.h create mode 100644 sfntly/font_factory.cc create mode 100644 sfntly/font_factory.h create mode 100644 sfntly/font_header_table.cc create mode 100644 sfntly/font_header_table.h create mode 100644 sfntly/glyph_table.cc create mode 100644 sfntly/glyph_table.h create mode 100644 sfntly/horizontal_header_table.cc create mode 100644 sfntly/horizontal_header_table.h create mode 100644 sfntly/horizontal_metrics_table.cc create mode 100644 sfntly/horizontal_metrics_table.h create mode 100644 sfntly/loca_table.cc create mode 100644 sfntly/loca_table.h create mode 100644 sfntly/math/fixed1616.h create mode 100644 sfntly/math/font_math.h create mode 100644 sfntly/maximum_profile_table.cc create mode 100644 sfntly/maximum_profile_table.h create mode 100644 sfntly/name_table.cc create mode 100644 sfntly/name_table.h create mode 100644 sfntly/os2_table.cc create mode 100644 sfntly/os2_table.h create mode 100644 sfntly/port/atomic.h create mode 100644 sfntly/port/config.h create mode 100644 sfntly/port/endian.h create mode 100644 sfntly/port/exception_type.h create mode 100644 sfntly/port/file_input_stream.cc create mode 100644 sfntly/port/file_input_stream.h create mode 100644 sfntly/port/input_stream.h create mode 100644 sfntly/port/memory_output_stream.cc create mode 100644 sfntly/port/memory_output_stream.h create mode 100644 sfntly/port/output_stream.h create mode 100644 sfntly/port/refcount.h create mode 100644 sfntly/port/type.h create mode 100644 sfntly/subtable.cc create mode 100644 sfntly/subtable.h create mode 100644 sfntly/table.cc create mode 100644 sfntly/table.h create mode 100644 sfntly/tag.cc create mode 100644 sfntly/tag.h create mode 100644 sfntly/tools/subsetter.cc create mode 100644 sfntly/tools/subsetter/glyph_table_subsetter.cc create mode 100644 sfntly/tools/subsetter/glyph_table_subsetter.h create mode 100644 sfntly/tools/subsetter/subsetter.h create mode 100644 sfntly/tools/subsetter/table_subsetter.h create mode 100644 sfntly/tools/subsetter/table_subsetter_impl.cc create mode 100644 sfntly/tools/subsetter/table_subsetter_impl.h create mode 100644 test/byte_array_test.cc create mode 100644 test/byte_array_test.h create mode 100644 test/endian_test.cc create mode 100644 test/endian_test.h create mode 100644 test/font_data_test.cc create mode 100644 test/font_data_test.h create mode 100644 test/main.cc create mode 100644 test/open_type_data_test.cc create mode 100644 test/open_type_data_test.h create mode 100644 test/otf_basic_editing_test.cc create mode 100644 test/otf_basic_editing_test.h create mode 100644 test/smart_pointer_test.cc create mode 100644 test/smart_pointer_test.h diff --git a/sample/subsetter/main.cc b/sample/subsetter/main.cc new file mode 100644 index 0000000..a9e1524 --- /dev/null +++ b/sample/subsetter/main.cc @@ -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. + */ + +#include +#if _MSC_VER > 12 + #define _CRTDBG_MAP_ALLOC + #include + #include +#endif + +#include "sample/subsetter/subset_util.h" + +int main(int argc, char** argv) { +#ifdef _CRTDBG_MAP_ALLOC + _CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF); +#endif + + if (argc < 3) { + printf("Usage: subsetter \n"); + return 0; + } + + sfntly::SubsetUtil subset_util; + subset_util.subset(argv[1], argv[2]); + +#ifdef _CRTDBG_MAP_ALLOC + _CrtDumpMemoryLeaks(); +#endif + + return 0; +} diff --git a/sample/subsetter/subset_util.cc b/sample/subsetter/subset_util.cc new file mode 100644 index 0000000..2266615 --- /dev/null +++ b/sample/subsetter/subset_util.cc @@ -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. + */ + +// Remove VC++ nag on fopen. +#define _CRT_SECURE_NO_WARNINGS + +#include +#include +#include + +#include "sfntly/port/type.h" +#include "sfntly/font.h" +#include "sfntly/tools/subsetter/subsetter.h" +#include "sample/subsetter/subset_util.h" +#include "sfntly/data/memory_byte_array.h" +#include "sfntly/port/memory_output_stream.h" +#include "sfntly/tag.h" + +namespace sfntly { + +SubsetUtil::SubsetUtil() { +} + +SubsetUtil::~SubsetUtil() { +} + +void SubsetUtil::subset(const char *input_file_path, + const char *output_file_path) { + UNREFERENCED_PARAMETER(output_file_path); + ByteVector input_buffer; + FILE* input_file = fopen(input_file_path, "rb"); + if (input_file == NULL) { + fprintf(stderr, "file not found\n"); + return; + } + fseek(input_file, 0, SEEK_END); + size_t file_size = ftell(input_file); + fseek(input_file, 0, SEEK_SET); + input_buffer.resize(file_size); + fread(&(input_buffer[0]), 1, file_size, input_file); + fclose(input_file); + + ByteArrayPtr ba = new MemoryByteArray(&(input_buffer[0]), file_size); + FontFactoryPtr factory; + factory.attach(FontFactory::getInstance()); + + FontArray font_array; + factory->loadFonts(ba, &font_array); + if (font_array.empty() || font_array[0] == NULL) + return; + + IntegerList glyphs; + for (int32_t i = 0; i < 10; i++) { + glyphs.push_back(i); + } + glyphs.push_back(11); + glyphs.push_back(10); + + Ptr subsetter = new Subsetter(font_array[0], factory); + subsetter->setGlyphs(&glyphs); + IntegerSet remove_tables; + remove_tables.insert(Tag::DSIG); + subsetter->setRemoveTables(&remove_tables); + + FontBuilderPtr font_builder; + font_builder.attach(subsetter->subset()); + + FontPtr new_font; + new_font.attach(font_builder->build()); + + // TODO(arthurhsu): glyph renumbering/Loca table + // TODO(arthurhsu): alter CMaps + + MemoryOutputStream output_stream; + factory->serializeFont(new_font, &output_stream); + + FILE* output_file = fopen(output_file_path, "wb"); + fwrite(output_stream.get(), 1, output_stream.size(), output_file); + fflush(output_file); + fclose(output_file); +} + +} // namespace sfntly diff --git a/sample/subsetter/subset_util.h b/sample/subsetter/subset_util.h new file mode 100644 index 0000000..bea28b8 --- /dev/null +++ b/sample/subsetter/subset_util.h @@ -0,0 +1,32 @@ +/* + * 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_SAMPLE_SUBSETTER_SUBSET_UTIL_H_ +#define TYPOGRAPHY_FONT_SFNTLY_SRC_SAMPLE_SUBSETTER_SUBSET_UTIL_H_ + +namespace sfntly { + +class SubsetUtil { + public: + SubsetUtil(); + virtual ~SubsetUtil(); + + void subset(const char* input_file_path, const char* output_file_path); +}; + +} // namespace sfntly + +#endif // TYPOGRAPHY_FONT_SFNTLY_SRC_SAMPLE_SUBSETTER_SUBSET_UTIL_H_ diff --git a/sfntly/cmap_table.cc b/sfntly/cmap_table.cc new file mode 100644 index 0000000..11b2b50 --- /dev/null +++ b/sfntly/cmap_table.cc @@ -0,0 +1,530 @@ +/* + * 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. + */ + +// TODO(arthurhsu): IMPLEMENT: not really used and tested, need cleanup + +#include "sfntly/cmap_table.h" +#include "sfntly/name_table.h" +#include "sfntly/font.h" +#include "sfntly/port/endian.h" + +namespace sfntly { + +/****************************************************************************** + * Constants + ******************************************************************************/ +const int32_t CMapTable::NOTDEF = 0; +const int32_t CMapTable::Offset::kVersion = 0; +const int32_t CMapTable::Offset::kNumTables = 2; +const int32_t CMapTable::Offset::kEncodingRecordStart = 4; +const int32_t CMapTable::Offset::kEncodingRecordPlatformId = 0; +const int32_t CMapTable::Offset::kEncodingRecordEncodingId = 2; +const int32_t CMapTable::Offset::kEncodingRecordOffset = 4; +const int32_t CMapTable::Offset::kEncodingRecordSize = 8; +const int32_t CMapTable::Offset::kFormat = 0; +const int32_t CMapTable::Offset::kFormat0Format = 0; +const int32_t CMapTable::Offset::kFormat0Length = 2; +const int32_t CMapTable::Offset::kFormat0Language = 4; +const int32_t CMapTable::Offset::kFormat0GlyphIdArray = 6; +const int32_t CMapTable::Offset::kFormat2Format = 0; +const int32_t CMapTable::Offset::kFormat2Length = 2; +const int32_t CMapTable::Offset::kFormat2Language = 4; +const int32_t CMapTable::Offset::kFormat2SubHeaderKeys = 6; +const int32_t CMapTable::Offset::kFormat2SubHeaders = 518; +const int32_t CMapTable::Offset::kFormat2SubHeader_firstCode = 0; +const int32_t CMapTable::Offset::kFormat2SubHeader_entryCount = 2; +const int32_t CMapTable::Offset::kFormat2SubHeader_idDelta = 4; +const int32_t CMapTable::Offset::kFormat2SubHeader_idRangeOffset = 6; +const int32_t CMapTable::Offset::kFormat2SubHeader_structLength = 8; +const int32_t CMapTable::Offset::kFormat4Format = 0; +const int32_t CMapTable::Offset::kFormat4Length = 2; +const int32_t CMapTable::Offset::kFormat4Language = 4; +const int32_t CMapTable::Offset::kFormat4SegCountX2 = 6; +const int32_t CMapTable::Offset::kFormat4SearchRange = 8; +const int32_t CMapTable::Offset::kFormat4EntrySelector = 10; +const int32_t CMapTable::Offset::kFormat4RangeShift = 12; +const int32_t CMapTable::Offset::kFormat4EndCount = 14; +const int32_t CMapTable::Offset::kFormat6Format = 0; +const int32_t CMapTable::Offset::kFormat6Length = 2; +const int32_t CMapTable::Offset::kFormat6Language = 4; +const int32_t CMapTable::Offset::kFormat6FirstCode = 6; +const int32_t CMapTable::Offset::kFormat6EntryCount = 8; +const int32_t CMapTable::Offset::kFormat6GlyphIdArray = 10; +const int32_t CMapTable::Offset::kFormat8Format = 0; +const int32_t CMapTable::Offset::kFormat8Length = 4; +const int32_t CMapTable::Offset::kFormat8Language = 8; +const int32_t CMapTable::Offset::kFormat8Is32 = 12; +const int32_t CMapTable::Offset::kFormat8nGroups204 = 8204; +const int32_t CMapTable::Offset::kFormat8Groups208 = 8208; +const int32_t CMapTable::Offset::kFormat8Group_startCharCode = 0; +const int32_t CMapTable::Offset::kFormat8Group_endCharCode = 4; +const int32_t CMapTable::Offset::kFormat8Group_startGlyphId = 8; +const int32_t CMapTable::Offset::kFormat8Group_structLength = 12; +const int32_t CMapTable::Offset::kFormat10Format = 0; +const int32_t CMapTable::Offset::kFormat10Length = 4; +const int32_t CMapTable::Offset::kFormat10Language = 8; +const int32_t CMapTable::Offset::kFormat10StartCharCode = 12; +const int32_t CMapTable::Offset::kFormat10NumChars = 16; +const int32_t CMapTable::Offset::kFormat10Glyphs0 = 20; +const int32_t CMapTable::Offset::kFormat12Format = 0; +const int32_t CMapTable::Offset::kFormat12Length = 4; +const int32_t CMapTable::Offset::kFormat12Language = 8; +const int32_t CMapTable::Offset::kFormat12nGroups = 12; +const int32_t CMapTable::Offset::kFormat12Groups = 16; +const int32_t CMapTable::Offset::kFormat12Groups_structLength = 12; +const int32_t CMapTable::Offset::kFormat12_startCharCode = 0; +const int32_t CMapTable::Offset::kFormat12_endCharCode = 4; +const int32_t CMapTable::Offset::kFormat12_startGlyphId = 8; +const int32_t CMapTable::Offset::kFormat13Format = 0; +const int32_t CMapTable::Offset::kFormat13Length = 4; +const int32_t CMapTable::Offset::kFormat13Language = 8; +const int32_t CMapTable::Offset::kFormat13nGroups = 12; +const int32_t CMapTable::Offset::kFormat13Groups = 16; +const int32_t CMapTable::Offset::kFormat13Groups_structLength = 12; +const int32_t CMapTable::Offset::kFormat13_startCharCode = 0; +const int32_t CMapTable::Offset::kFormat13_endCharCode = 4; +const int32_t CMapTable::Offset::kFormat13_glyphId = 8; +const int32_t CMapTable::Offset::kFormat14Format = 0; +const int32_t CMapTable::Offset::kFormat14Length = 2; +const int32_t CMapTable::Offset::kLast = -1; + +const int32_t CMapTable::CMapFormat::kFormat0 = 0; +const int32_t CMapTable::CMapFormat::kFormat2 = 2; +const int32_t CMapTable::CMapFormat::kFormat4 = 4; +const int32_t CMapTable::CMapFormat::kFormat6 = 6; +const int32_t CMapTable::CMapFormat::kFormat8 = 8; +const int32_t CMapTable::CMapFormat::kFormat10 = 10; +const int32_t CMapTable::CMapFormat::kFormat12 = 12; +const int32_t CMapTable::CMapFormat::kFormat13 = 13; +const int32_t CMapTable::CMapFormat::kFormat14 = 14; + +/****************************************************************************** + * CMapTable class + ******************************************************************************/ +CMapTable::CMapTable(Header* header, ReadableFontData* data) + : Table(header, data) {} +CMapTable::~CMapTable() {} + +int32_t CMapTable::version() { + return data_->readUShort(Offset::kVersion); +} + +int32_t CMapTable::numCMaps() { + return data_->readUShort(Offset::kNumTables); +} + +int32_t CMapTable::offsetForEncodingRecord(int32_t index) { + return Offset::kEncodingRecordStart + index * Offset::kEncodingRecordSize; +} + +CMapTable::CMapId CMapTable::cmapId(int32_t index) { + return CMapId(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)); +} + +/****************************************************************************** + * CMapTable::CMapId class + ******************************************************************************/ +CMapTable::CMapId::CMapId(int32_t platform_id, int32_t encoding_id) + : platform_id_(platform_id), encoding_id_(encoding_id) { +} + +CMapTable::CMapId::CMapId(const CMapId& obj) + : platform_id_(obj.platform_id_), encoding_id_(obj.encoding_id_) { +} + +int32_t CMapTable::CMapId::platformId() { return platform_id_; } +int32_t CMapTable::CMapId::encodingId() { return encoding_id_; } + +bool CMapTable::CMapId::operator==(const CMapTable::CMapId& obj) { + return obj.platform_id_ == platform_id_ && obj.encoding_id_ == encoding_id_; +} + +const CMapTable::CMapId& CMapTable::CMapId::operator=( + const CMapTable::CMapId& obj) { + platform_id_ = obj.platform_id_; + encoding_id_ = obj.encoding_id_; + return *this; +} + +int CMapTable::CMapId::hashCode() const { + return platform_id_ << 8 | encoding_id_; +} + +CMapTable::CMapId WINDOWS_BMP(PlatformId::kWindows, + WindowsEncodingId::kUnicodeUCS2); +CMapTable::CMapId WINDOWS_UCS4(PlatformId::kWindows, + WindowsEncodingId::kUnicodeUCS4); +CMapTable::CMapId MAC_ROMAN(PlatformId::kWindows, MacintoshEncodingId::kRoman); + +/****************************************************************************** + * CMapTable::CMapIdComparator class + ******************************************************************************/ + +bool CMapTable::CMapIdComparator::operator()(const CMapId& lhs, + const CMapId& rhs) { + return lhs.hashCode() > rhs.hashCode(); +} + +/****************************************************************************** + * 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() {} +int32_t CMapTable::CMap::format() { return format_; } +CMapTable::CMapId CMapTable::CMap::cmapId() { return cmap_id_; } +int32_t CMapTable::CMap::platformId() { return cmap_id_.platformId(); } +int32_t CMapTable::CMap::encodingId() { return cmap_id_.encodingId(); } + +/****************************************************************************** + * CMapTable::CMap::Builder class + ******************************************************************************/ +CMapTable::CMap::Builder::Builder(FontDataTableBuilderContainer* container, + ReadableFontData* data, int32_t format, const CMapId& cmap_id) : + SubTable::Builder(container, data), format_(format), cmap_id_(cmap_id) { +} + +CMapTable::CMap::Builder::Builder(FontDataTableBuilderContainer* container, + WritableFontData* data, int32_t format, const CMapId& cmap_id) : + SubTable::Builder(container, data), format_(format), cmap_id_(cmap_id) { +} + +CMapTable::CMap::Builder::~Builder() {} + +CMapTable::CMapId CMapTable::CMap::Builder::cmapId() { + return cmap_id_; +} + +int32_t CMapTable::CMap::Builder::platformId() { + return cmap_id_.platformId(); +} + +int32_t CMapTable::CMap::Builder::encodingId() { + return cmap_id_.encodingId(); +} + +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() { + return internalReadData()->length(); +} + +void CMapTable::CMap::Builder::subDataSet() { + // NOP +} + +CALLER_ATTACH CMapTable::CMap::Builder* CMapTable::CMap::Builder::getBuilder( + FontDataTableBuilderContainer* container, 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 = new CMapFormat0::Builder(container, data, offset, cmap_id); + case CMapFormat::kFormat2: + builder = new CMapFormat0::Builder(container, data, offset, cmap_id); + default: + break; + } + return builder.detach(); +} + +/****************************************************************************** + * CMapTable::CMapFormat0 and CMapTable::CMapFormat0::Builder + ******************************************************************************/ +CMapTable::CMapFormat0::CMapFormat0(ReadableFontData* data, + const CMapId& cmap_id) : CMap(data, CMapFormat::kFormat0, cmap_id) { +} + +CMapTable::CMapFormat0::~CMapFormat0() {} + +int32_t CMapTable::CMapFormat0::glyphId(int32_t character) { + if (character < 0 || character > 255) { + return CMapTable::NOTDEF; + } + return data_->readByte(character + Offset::kFormat0GlyphIdArray); +} + +int32_t CMapTable::CMapFormat0::language() { + return 0; +} + +CMapTable::CMapFormat0::Builder::Builder( + FontDataTableBuilderContainer* container, WritableFontData* data, + int32_t offset, const CMapId& cmap_id) + : CMapTable::CMap::Builder(container, + data ? down_cast( + data->slice(offset, data->readUShort( + offset + Offset::kFormat0Length))) + : reinterpret_cast(NULL), + CMapFormat::kFormat0, cmap_id) { + // TODO(arthurhsu): FIXIT: heavy lifting and leak, need fix. +} + +CMapTable::CMapFormat0::Builder::Builder( + FontDataTableBuilderContainer* container, ReadableFontData* data, + int32_t offset, const CMapId& cmap_id) + : CMapTable::CMap::Builder(container, + data ? down_cast( + data->slice(offset, data->readUShort( + offset + Offset::kFormat0Length))) + : reinterpret_cast(NULL), + CMapFormat::kFormat0, cmap_id) { + // TODO(arthurhsu): FIXIT: heavy lifting and leak, need fix. +} + +CMapTable::CMapFormat0::Builder::~Builder() {} + +CALLER_ATTACH FontDataTable* CMapTable::CMapFormat0::Builder::subBuildTable( + ReadableFontData* data) { + FontDataTablePtr table = new CMapFormat0(data, cmapId()); + return table.detach(); +} + +/****************************************************************************** + * CMapTable::CMapFormat2 and CMapTable::CMapFormat2::Builder + ******************************************************************************/ +CMapTable::CMapFormat2::CMapFormat2(ReadableFontData* data, + const CMapId& cmap_id) : CMap(data, CMapFormat::kFormat2, cmap_id) { +} + +CMapTable::CMapFormat2::~CMapFormat2() {} + +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); +} + +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; +} + +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::language() { + return 0; +} + +CMapTable::CMapFormat2::Builder::Builder( + FontDataTableBuilderContainer* container, WritableFontData* data, + int32_t offset, const CMapId& cmap_id) + : CMapTable::CMap::Builder(container, + 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( + FontDataTableBuilderContainer* container, ReadableFontData* data, + int32_t offset, const CMapId& cmap_id) + : CMapTable::CMap::Builder(container, + 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, cmapId()); + return table.detach(); +} + +/****************************************************************************** + * CMapTable::Iterator class + ******************************************************************************/ +CMapTable::CMapIterator::CMapIterator(CMapTable* table, CMapFilter* filter) + : table_index_(0), table_(table), filter_(filter) {} + +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_->cmapId(table_index_))) { + return true; + } + } + return false; +} + +/****************************************************************************** + * CMapTable::Builder class + ******************************************************************************/ +CMapTable::Builder::Builder(FontDataTableBuilderContainer* font_builder, + Header* header, WritableFontData* data) + : Table::ArrayElementTableBuilder(font_builder, header, data) { +} + +CMapTable::Builder::Builder(FontDataTableBuilderContainer* font_builder, + Header* header, ReadableFontData* data) + : Table::ArrayElementTableBuilder(font_builder, header, data) { +} + +int32_t CMapTable::Builder::subSerialize(WritableFontData* new_data) { + // TODO(arthurhsu): IMPLEMENT + UNREFERENCED_PARAMETER(new_data); + return 0; +} + +bool CMapTable::Builder::subReadyToSerialize() { + // TODO(arthurhsu): IMPLEMENT + return false; +} + +int32_t CMapTable::Builder::subDataSizeToSerialize() { + // TODO(arthurhsu): IMPLEMENT + return 0; +} + +void CMapTable::Builder::subDataSet() { + // TODO(arthurhsu): IMPLEMENT +} + +CALLER_ATTACH FontDataTable* CMapTable::Builder::subBuildTable( + ReadableFontData* data) { + FontDataTablePtr table = new CMapTable(header(), data); + return table.detach(); +} + +CALLER_ATTACH CMapTable::CMap::Builder* CMapTable::Builder::cmapBuilder( + FontDataTableBuilderContainer* container, ReadableFontData* data, + int32_t index) { + if (index < 0 || index > numCMaps(data)) + return NULL; + + int32_t record_offset = Offset::kEncodingRecordOffset + index * + Offset::kEncodingRecordSize; + int32_t platform_id = data->readUShort(Offset::kEncodingRecordPlatformId + + record_offset); + int32_t encoding_id = data->readUShort(Offset::kEncodingRecordEncodingId + + record_offset); + CMapId cmap_id(platform_id, encoding_id); + int32_t offset = data->readULongAsInt(Offset::kEncodingRecordOffset + + record_offset); + return CMap::Builder::getBuilder(container, data, offset, cmap_id); +} + +int32_t CMapTable::Builder::numCMaps(ReadableFontData* data) { + if (data == NULL) { + return 0; + } + return data->readUShort(Offset::kNumTables); +} + +} // namespace sfntly diff --git a/sfntly/cmap_table.h b/sfntly/cmap_table.h new file mode 100644 index 0000000..9e9aa87 --- /dev/null +++ b/sfntly/cmap_table.h @@ -0,0 +1,408 @@ +/* + * 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. + */ + +// TODO(arthurhsu): IMPLEMENT: not really used and tested, need cleanup +#ifndef TYPOGRAPHY_FONT_SFNTLY_SRC_SFNTLY_CMAP_TABLE_H_ +#define TYPOGRAPHY_FONT_SFNTLY_SRC_SFNTLY_CMAP_TABLE_H_ + +#include +#include + +#include "sfntly/port/refcount.h" +#include "sfntly/table.h" +#include "sfntly/subtable.h" + +namespace sfntly { + +// A CMap table +class CMapTable : public Table, public RefCounted { + private: + static const int32_t NOTDEF; + struct Offset { + static const int32_t kVersion; + static const int32_t kNumTables; + static const int32_t kEncodingRecordStart; + + // offsets relative to the encoding record + static const int32_t kEncodingRecordPlatformId; + static const int32_t kEncodingRecordEncodingId; + static const int32_t kEncodingRecordOffset; + static const int32_t kEncodingRecordSize; + + static const int32_t kFormat; + + // Format 0: Byte encoding table + static const int32_t kFormat0Format; + static const int32_t kFormat0Length; + static const int32_t kFormat0Language; + static const int32_t kFormat0GlyphIdArray; + + // Format 2: High-byte mapping through table + static const int32_t kFormat2Format; + static const int32_t kFormat2Length; + static const int32_t kFormat2Language; + static const int32_t kFormat2SubHeaderKeys; + static const int32_t kFormat2SubHeaders; + // offset relative to the subHeader structure + static const int32_t kFormat2SubHeader_firstCode; + static const int32_t kFormat2SubHeader_entryCount; + static const int32_t kFormat2SubHeader_idDelta; + static const int32_t kFormat2SubHeader_idRangeOffset; + static const int32_t kFormat2SubHeader_structLength; + + // Format 4: Segment mapping to delta values + static const int32_t kFormat4Format; + static const int32_t kFormat4Length; + static const int32_t kFormat4Language; + static const int32_t kFormat4SegCountX2; + static const int32_t kFormat4SearchRange; + static const int32_t kFormat4EntrySelector; + static const int32_t kFormat4RangeShift; + static const int32_t kFormat4EndCount; + + // format 6: Trimmed table mapping + static const int32_t kFormat6Format; + static const int32_t kFormat6Length; + static const int32_t kFormat6Language; + static const int32_t kFormat6FirstCode; + static const int32_t kFormat6EntryCount; + static const int32_t kFormat6GlyphIdArray; + + // Format 8: mixed 16-bit and 32-bit coverage + static const int32_t kFormat8Format; + static const int32_t kFormat8Length; + static const int32_t kFormat8Language; + static const int32_t kFormat8Is32; + static const int32_t kFormat8nGroups204; + static const int32_t kFormat8Groups208; + // ofset relative to the group structure + static const int32_t kFormat8Group_startCharCode; + static const int32_t kFormat8Group_endCharCode; + static const int32_t kFormat8Group_startGlyphId; + static const int32_t kFormat8Group_structLength; + + // Format 10: Trimmed array + static const int32_t kFormat10Format; + static const int32_t kFormat10Length; + static const int32_t kFormat10Language; + static const int32_t kFormat10StartCharCode; + static const int32_t kFormat10NumChars; + static const int32_t kFormat10Glyphs0; + + // Format 12: Segmented coverage + static const int32_t kFormat12Format; + static const int32_t kFormat12Length; + static const int32_t kFormat12Language; + static const int32_t kFormat12nGroups; + static const int32_t kFormat12Groups; + static const int32_t kFormat12Groups_structLength; + // offsets within the group structure + static const int32_t kFormat12_startCharCode; + static const int32_t kFormat12_endCharCode; + static const int32_t kFormat12_startGlyphId; + + // Format 13: Last Resort Font + static const int32_t kFormat13Format; + static const int32_t kFormat13Length; + static const int32_t kFormat13Language; + static const int32_t kFormat13nGroups; + static const int32_t kFormat13Groups; + static const int32_t kFormat13Groups_structLength; + // offsets within the group structure + static const int32_t kFormat13_startCharCode; + static const int32_t kFormat13_endCharCode; + static const int32_t kFormat13_glyphId; + + // Format 14: Unicode Variation Sequences + static const int32_t kFormat14Format; + static const int32_t kFormat14Length; + + // TODO(stuartg): finish tables + // Default UVS Table + + // Non-default UVS Table + static const int32_t kLast; + }; + + // CMap subtable formats + struct CMapFormat { + static const int32_t kFormat0; + static const int32_t kFormat2; + static const int32_t kFormat4; + static const int32_t kFormat6; + static const int32_t kFormat8; + static const int32_t kFormat10; + static const int32_t kFormat12; + static const int32_t kFormat13; + static const int32_t kFormat14; + }; + + public: + class CMapId { + public: + CMapId(int32_t platform_id, int32_t encoding_id); + CMapId(const CMapId& obj); + int32_t platformId(); + int32_t encodingId(); + bool operator==(const CMapId& obj); + const CMapId& operator=(const CMapId& obj); + int hashCode() const; + + friend class CMapIdComparator; + + private: + int32_t platform_id_; + int32_t encoding_id_; + }; + static CMapId WINDOWS_BMP; + static CMapId WINDOWS_UCS4; + static CMapId MAC_ROMAN; + + class CMapIdComparator { + public: + bool operator()(const CMapId& lhs, const CMapId& rhs); + }; + + class CMapFilter { + public: + virtual bool accept(CMapId cmap_id) = 0; + // Make gcc -Wnon-virtual-dtor happy. + virtual ~CMapFilter() {} + }; + + // 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 implements {@code Iterable} 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 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 CMap : public SubTable { + public: + CMap(ReadableFontData* data, int32_t format, const CMapId& cmap_id); + virtual ~CMap(); + virtual int32_t format(); + virtual CMapId cmapId(); + virtual int32_t platformId(); + virtual int32_t encodingId(); + + // 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; + + public: + class Builder : public SubTable::Builder { + protected: + Builder(FontDataTableBuilderContainer* container, ReadableFontData* data, + int32_t format, const CMapId& cmap_id); + Builder(FontDataTableBuilderContainer* container, WritableFontData* data, + int32_t format, const CMapId& cmap_id); + + public: + virtual ~Builder(); + CALLER_ATTACH static Builder* + getBuilder(FontDataTableBuilderContainer* container, + ReadableFontData* data, int32_t offset, + const CMapId& cmap_id); + + // Note: yes, an object is returned on stack since it's small enough. + virtual CMapId cmapId(); + virtual int32_t platformId(); + virtual int32_t encodingId(); + + protected: + virtual int32_t subSerialize(WritableFontData* new_data); + virtual bool subReadyToSerialize(); + virtual int32_t subDataSizeToSerialize(); + virtual void subDataSet(); + + private: + int32_t format_; + CMapId cmap_id_; + }; + + private: + int32_t format_; + CMapId cmap_id_; + }; + typedef Ptr CMapBuilderPtr; + typedef std::map CMapBuilderMap; + + // A cmap format 0 sub table + class CMapFormat0 : public CMap, public RefCounted { + protected: + CMapFormat0(ReadableFontData* data, const CMapId& cmap_id); + + public: + virtual ~CMapFormat0(); + virtual int32_t language(); + virtual int32_t glyphId(int32_t character); + + class Builder : public CMap::Builder, + public RefCounted { + public: + Builder(FontDataTableBuilderContainer* container, ReadableFontData* data, + int32_t offset, const CMapId& cmap_id); + Builder(FontDataTableBuilderContainer* container, WritableFontData* data, + int32_t offset, const CMapId& cmap_id); + virtual ~Builder(); + protected: + virtual CALLER_ATTACH FontDataTable* + subBuildTable(ReadableFontData* data); + }; + }; + + // 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 { + protected: + CMapFormat2(ReadableFontData* data, const CMapId& cmap_id); + + public: + virtual ~CMapFormat2(); + 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); + + private: + 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); + + class Builder : public CMap::Builder, + public RefCounted { + public: + Builder(FontDataTableBuilderContainer* container, ReadableFontData* data, + int32_t offset, const CMapId& cmap_id); + Builder(FontDataTableBuilderContainer* container, WritableFontData* data, + int32_t offset, const CMapId& cmap_id); + virtual ~Builder(); + protected: + virtual CALLER_ATTACH FontDataTable* + subBuildTable(ReadableFontData* data); + }; + }; + + class Builder : public Table::ArrayElementTableBuilder { + public: + // Constructor scope altered to public because C++ does not allow base + // class to instantiate derived class with protected constructors. + Builder(FontDataTableBuilderContainer* font_builder, Header* header, + WritableFontData* data); + Builder(FontDataTableBuilderContainer* font_builder, Header* header, + ReadableFontData* data); + + virtual int32_t subSerialize(WritableFontData* new_data); + virtual bool subReadyToSerialize(); + virtual int32_t subDataSizeToSerialize(); + virtual void subDataSet(); + virtual CALLER_ATTACH FontDataTable* subBuildTable(ReadableFontData* data); + + protected: + static CALLER_ATTACH CMap::Builder* cmapBuilder( + FontDataTableBuilderContainer* container, ReadableFontData* data, + int32_t index); + + private: + static int32_t numCMaps(ReadableFontData* data); + + private: + int32_t version_; + CMapBuilderMap cmap_builders_; + }; + + private: + class CMapIterator { + public: + // If filter is NULL, filter through all tables. + CMapIterator(CMapTable* table, CMapFilter* filter); + bool hasNext(); + CMap* next(); + + private: + int32_t table_index_; + CMapFilter* filter_; + CMapTable* table_; + }; + + private: + CMapTable(Header* header, ReadableFontData* data); + + public: + virtual ~CMapTable(); + + // 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. + virtual CMapId cmapId(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); + + private: + // 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. + int32_t offsetForEncodingRecord(int32_t index); +}; +typedef std::vector CMapIdList; + +} // namespace sfntly + +#endif // TYPOGRAPHY_FONT_SFNTLY_SRC_SFNTLY_CMAP_TABLE_H_ diff --git a/sfntly/data/byte_array.cc b/sfntly/data/byte_array.cc new file mode 100644 index 0000000..3511bfe --- /dev/null +++ b/sfntly/data/byte_array.cc @@ -0,0 +1,182 @@ +/* + * 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 "sfntly/data/byte_array.h" +#include "sfntly/port/exception_type.h" + +namespace sfntly { + +const int32_t ByteArray::COPY_BUFFER_SIZE = 8192; + +void ByteArray::init(int32_t filled_length, int32_t storage_length, + bool growable) { + storage_length_ = storage_length; + growable_ = growable; + setFilledLength(filled_length); +} + +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); +} + +ByteArray::~ByteArray() {} + +int32_t ByteArray::length() { return filled_length_; } +int32_t ByteArray::size() { return storage_length_; } +bool ByteArray::growable() { return growable_; } + +int32_t ByteArray::setFilledLength(int32_t filled_length) { + filled_length_ = std::min(filled_length, storage_length_); + return filled_length_; +} + +byte_t ByteArray::get(int32_t index) { + return internalGet(index); +} + +int32_t ByteArray::get(int32_t index, ByteVector* b) { + assert(b); + return get(index, b, 0, b->size()); +} + +int32_t ByteArray::get(int32_t index, ByteVector* b, int32_t offset, + int32_t length) { + assert(b); + if (index < 0 || index >= filled_length_) { + return -1; + } + int32_t actual_length = std::min(length, filled_length_ - index); + if (actual_length < 0) { + return -1; + } + return internalGet(index, b, offset, actual_length); +} + +bool ByteArray::put(int32_t index, byte_t b) { + if (index < 0 || index >= size()) { + return false; + } + bool result = internalPut(index, b); + filled_length_ = std::max(filled_length_, index + 1); + return result; +} + +int32_t ByteArray::put(int index, ByteVector* b) { + assert(b); + return put(index, b, 0, b->size()); +} + +int32_t ByteArray::put(int32_t index, ByteVector* b, int32_t offset, + int32_t length) { + assert(b); + if (index < 0 || index >= size()) { + return 0; + } + 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, buffer_length)) > 0) { + int bytes_written = array->put(index + dst_offset, &b, 0, bytes_read); + if (bytes_written != bytes_read) { + throw IOException("Error writing bytes."); + } + 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 = offset; + int32_t buffer_length = std::min(COPY_BUFFER_SIZE, length); + while ((bytes_read = get(index, &b, 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, bytes_read) != bytes_read) { + throw IOException("Error writing bytes."); + } + 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, bytes_read) != bytes_read) { + throw IOException("Error writing bytes."); + } + index += bytes_read; + } + return true; +} + +} // namespace sfntly diff --git a/sfntly/data/byte_array.h b/sfntly/data/byte_array.h new file mode 100644 index 0000000..edb4633 --- /dev/null +++ b/sfntly/data/byte_array.h @@ -0,0 +1,143 @@ +/* + * 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 TYPOGRAPHY_FONT_SFNTLY_SRC_SFNTLY_DATA_BYTE_ARRAY_H_ +#define TYPOGRAPHY_FONT_SFNTLY_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 interface abstraction to a byte array. Can be implemented to map to +// various types of data storage. +// C++ port of this class assumes that the data are stored in a linear region +// like std::vector. +class ByteArray : virtual public RefCount { + 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); + + static const int32_t COPY_BUFFER_SIZE; + + public: + virtual ~ByteArray(); + + // Get the current filled and readable length of the array. + int32_t length(); + + // Get 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(); + + bool growable(); + int32_t setFilledLength(int32_t filled_length); + + public: + // Get the byte from the given index. + virtual byte_t get(int32_t index); + + // Get 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. + virtual int32_t get(int32_t index, ByteVector* b); + + // Get 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 put into the buffer + virtual int32_t get(int32_t index, ByteVector* b, int32_t offset, + int32_t length); + + // Put 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 bool put(int32_t index, byte_t b); + + // Put 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); + + // Put 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, ByteVector* b, int32_t offset, + int32_t length); + + // Fully copy this ByteArray to another ByteArray to the extent that the + // destination array has storage for the data copied. + virtual int32_t copyTo(ByteArray* array); + + // Copy 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); + + // Copy 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); + + virtual int32_t copyTo(OutputStream* os); + virtual int32_t copyTo(OutputStream* os, int32_t offset, int32_t length); + virtual bool copyFrom(InputStream* is, int32_t length); + virtual bool copyFrom(InputStream* is); + + protected: + virtual bool internalPut(int32_t index, byte_t b) = 0; + virtual int32_t internalPut(int32_t index, ByteVector* b, int32_t offset, + int32_t length) = 0; + virtual byte_t internalGet(int32_t index) = 0; + virtual int32_t internalGet(int32_t index, ByteVector* b, int32_t offset, + int32_t length) = 0; + virtual void close() = 0; + + // C++ port only, raw pointer to the first element of storage + virtual byte_t* begin() = 0; + + private: + int32_t filled_length_; + int32_t storage_length_; + bool growable_; +}; +typedef Ptr ByteArrayPtr; + +} // namespace sfntly + +#endif // TYPOGRAPHY_FONT_SFNTLY_SRC_SFNTLY_DATA_BYTE_ARRAY_H_ diff --git a/sfntly/data/font_data.cc b/sfntly/data/font_data.cc new file mode 100644 index 0000000..8cda562 --- /dev/null +++ b/sfntly/data/font_data.cc @@ -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. + */ + +#include +#include +#include + +#include "sfntly/data/font_data.h" + +namespace sfntly { + +const int32_t DataSize::kBYTE = 1; +const int32_t DataSize::kCHAR = 1; +const int32_t DataSize::kUSHORT = 2; +const int32_t DataSize::kSHORT = 2; +const int32_t DataSize::kUINT24 = 3; +const int32_t DataSize::kULONG = 4; +const int32_t DataSize::kLONG = 4; +const int32_t DataSize::kFixed = 4; +const int32_t DataSize::kFUNIT = 4; +const int32_t DataSize::kFWORD = 2; +const int32_t DataSize::kUFWORD = 2; +const int32_t DataSize::kF2DOT14 = 2; +const int32_t DataSize::kLONGDATETIME = 8; +const int32_t DataSize::kTag = 4; +const int32_t DataSize::kGlyphID = 2; +const int32_t DataSize::kOffset = 2; + +FontData::~FontData() {} + +void FontData::init(ByteArray* ba) { + array_ = ba; + bound_offset_ = 0; + bound_length_ = INT_MAX; +} + +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(offset); +} + +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_); +} + +int32_t FontData::size() const { + return std::min(array_->size() - bound_offset_, bound_length_); +} + +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/sfntly/data/font_data.h b/sfntly/data/font_data.h new file mode 100644 index 0000000..5766cb8 --- /dev/null +++ b/sfntly/data/font_data.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 TYPOGRAPHY_FONT_SFNTLY_SRC_SFNTLY_DATA_FONT_DATA_H_ +#define TYPOGRAPHY_FONT_SFNTLY_SRC_SFNTLY_DATA_FONT_DATA_H_ + +#include +#include "sfntly/port/type.h" +#include "sfntly/data/byte_array.h" +#include "sfntly/port/refcount.h" + +namespace sfntly { + +struct DataSize { + static const int32_t kBYTE; + static const int32_t kCHAR; + static const int32_t kUSHORT; + static const int32_t kSHORT; + static const int32_t kUINT24; + static const int32_t kULONG; + static const int32_t kLONG; + static const int32_t kFixed; + static const int32_t kFUNIT; + static const int32_t kFWORD; + static const int32_t kUFWORD; + static const int32_t kF2DOT14; + static const int32_t kLONGDATETIME; + static const int32_t kTag; + static const int32_t kGlyphID; + static const int32_t kOffset; +}; + +class FontData : virtual public RefCount { + public: + // Get 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 size of this array + virtual int32_t size() const; + + // Sets limits on the size of the FontData. The font data is + // @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; + + // Get the length of the data. + virtual int32_t length() const; + + + protected: + virtual ~FontData(); + + // 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); + + void init(ByteArray* ba); + int32_t boundOffset(int32_t offset); + int32_t boundLength(int32_t offset, int32_t length); + + protected: + ByteArrayPtr array_; + + private: + int32_t bound_offset_; + int32_t bound_length_; +}; +typedef Ptr FontDataPtr; + +} // namespace sfntly + +#endif // TYPOGRAPHY_FONT_SFNTLY_SRC_SFNTLY_DATA_FONT_DATA_H_ diff --git a/sfntly/data/font_input_stream.cc b/sfntly/data/font_input_stream.cc new file mode 100644 index 0000000..8b1d798 --- /dev/null +++ b/sfntly/data/font_input_stream.cc @@ -0,0 +1,145 @@ +/* + * 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 "sfntly/data/font_input_stream.h" + +namespace sfntly { + +FontInputStream::FontInputStream(InputStream* is) + : position_(0), length_(0), bounded_(false), stream_(is) { +} + +FontInputStream::FontInputStream(InputStream* is, size_t length) + : position_(0), length_(length), bounded_(false), stream_(is) { +} + +FontInputStream::~FontInputStream() { + close(); +} + +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()); +} + +int64_t FontInputStream::position() { + return position_; +} + +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/sfntly/data/font_input_stream.h b/sfntly/data/font_input_stream.h new file mode 100644 index 0000000..ed8d364 --- /dev/null +++ b/sfntly/data/font_input_stream.h @@ -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. + */ + +#ifndef TYPOGRAPHY_FONT_SFNTLY_SRC_SFNTLY_DATA_FONT_INPUT_STREAM_H_ +#define TYPOGRAPHY_FONT_SFNTLY_SRC_SFNTLY_DATA_FONT_INPUT_STREAM_H_ + +#include "sfntly/port/type.h" +#include "sfntly/port/input_stream.h" + +namespace sfntly { + +// 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: + explicit FontInputStream(InputStream* is); + 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); + + virtual int64_t 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 // TYPOGRAPHY_FONT_SFNTLY_SRC_SFNTLY_DATA_FONT_INPUT_STREAM_H_ diff --git a/sfntly/data/font_output_stream.cc b/sfntly/data/font_output_stream.cc new file mode 100644 index 0000000..d5eaa82 --- /dev/null +++ b/sfntly/data/font_output_stream.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 + +#include "sfntly/data/font_output_stream.h" +#include "sfntly/port/endian.h" + +namespace sfntly { + +FontOutputStream::FontOutputStream(OutputStream* os) + : position_(0), stream_(os) { +} + +FontOutputStream::~FontOutputStream() { + close(); +} + +size_t FontOutputStream::position() { + return position_; +} + +void FontOutputStream::write(byte_t b) { + if (stream_) { + stream_->write(b); + } + position_++; +} + +void FontOutputStream::write(ByteVector* b) { + if (b) { + write(b, 0, b->size()); + } +} + +void FontOutputStream::write(ByteVector* b, int32_t offset, int32_t length) { + if (stream_ && b) { + stream_->write(b, offset, length); + } +} + +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(); + } +} + +} // namespace sfntly diff --git a/sfntly/data/font_output_stream.h b/sfntly/data/font_output_stream.h new file mode 100644 index 0000000..4bb923d --- /dev/null +++ b/sfntly/data/font_output_stream.h @@ -0,0 +1,59 @@ +/* + * 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_DATA_FONT_OUTPUT_STREAM_H_ +#define TYPOGRAPHY_FONT_SFNTLY_SRC_SFNTLY_DATA_FONT_OUTPUT_STREAM_H_ + +#include "sfntly/port/type.h" +#include "sfntly/port/output_stream.h" + +namespace sfntly { + +// 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 FontOutputStream : public OutputStream { + public: + explicit FontOutputStream(OutputStream* os); + virtual ~FontOutputStream(); + + virtual size_t position(); + + virtual void write(byte_t b); + virtual void write(ByteVector* b); + virtual void write(ByteVector* b, int32_t offset, 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); + + virtual void flush(); + virtual void close(); + + private: + OutputStream* stream_; + size_t position_; +}; + +} // namespace sfntly + +#endif // TYPOGRAPHY_FONT_SFNTLY_SRC_SFNTLY_DATA_FONT_OUTPUT_STREAM_H_ diff --git a/sfntly/data/growable_memory_byte_array.cc b/sfntly/data/growable_memory_byte_array.cc new file mode 100644 index 0000000..0821321 --- /dev/null +++ b/sfntly/data/growable_memory_byte_array.cc @@ -0,0 +1,67 @@ +/* + * 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 "sfntly/data/growable_memory_byte_array.h" + +namespace sfntly { + +GrowableMemoryByteArray::GrowableMemoryByteArray() + : ByteArray(0, INT_MAX, true) { +} + +GrowableMemoryByteArray::~GrowableMemoryByteArray() {} + +bool GrowableMemoryByteArray::internalPut(int32_t index, byte_t b) { + if ((size_t)index >= b_.capacity()) { + b_.resize((size_t)(index + 1) << 2); // grow exponentially + } + b_[index] = b; + return true; +} + +int32_t GrowableMemoryByteArray::internalPut(int32_t index, ByteVector* b, + int32_t offset, int32_t length) { + if ((size_t)index + length >= b_.capacity()) { + b_.resize((size_t)(index + length + 1) << 2); + } + std::copy(b->begin() + offset, b->begin() + (offset + length), + b_.begin() + index); + return length; +} + +byte_t GrowableMemoryByteArray::internalGet(int32_t index) { + return b_[index]; +} + +int32_t GrowableMemoryByteArray::internalGet(int32_t index, ByteVector* b, + int32_t offset, int32_t length) { + std::copy(b_.begin() + index, b_.begin() + (index + length), + b->begin() + offset); + return length; +} + +void GrowableMemoryByteArray::close() { + b_.clear(); +} + +byte_t* GrowableMemoryByteArray::begin() { + return &(b_[0]); +} + +} // namespace sfntly diff --git a/sfntly/data/growable_memory_byte_array.h b/sfntly/data/growable_memory_byte_array.h new file mode 100644 index 0000000..3c9d4f0 --- /dev/null +++ b/sfntly/data/growable_memory_byte_array.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_DATA_GROWABLE_MEMORY_BYTE_ARRAY_H_ +#define TYPOGRAPHY_FONT_SFNTLY_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(); + + protected: + virtual bool internalPut(int32_t index, byte_t b); + virtual int32_t internalPut(int32_t index, ByteVector* b, int32_t offset, + int32_t length); + virtual byte_t internalGet(int32_t index); + virtual int32_t internalGet(int32_t index, ByteVector* b, int32_t offset, + int32_t length); + virtual void close(); + virtual byte_t* begin(); + + private: + ByteVector b_; +}; + +} // namespace sfntly + +#endif // TYPOGRAPHY_FONT_SFNTLY_SRC_SFNTLY_DATA_GROWABLE_MEMORY_BYTE_ARRAY_H_ diff --git a/sfntly/data/memory_byte_array.cc b/sfntly/data/memory_byte_array.cc new file mode 100644 index 0000000..1e85ebd --- /dev/null +++ b/sfntly/data/memory_byte_array.cc @@ -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. + */ + +#include + +#include "sfntly/data/memory_byte_array.h" + +namespace sfntly { + +// Note: this constructor can fail under low-memory situation +MemoryByteArray::MemoryByteArray(int32_t length) + : ByteArray(0, length), allocated_(true), b_(NULL) { +} + +MemoryByteArray::MemoryByteArray(byte_t* b, int32_t buffer_length) + : ByteArray(buffer_length, buffer_length), b_(b), allocated_(false) { +} + +MemoryByteArray::MemoryByteArray(byte_t* b, int32_t buffer_length, + int32_t filled_length) + : ByteArray(filled_length, buffer_length), b_(b), allocated_(false) { +} + +MemoryByteArray::~MemoryByteArray() { + close(); +} + +void MemoryByteArray::init() { + if (allocated_ && b_ == NULL) { + b_ = new byte_t[size()]; + memset(b_, 0, size()); + } +} + +bool MemoryByteArray::internalPut(int32_t index, byte_t b) { + init(); + b_[index] = b; + return true; +} + +int32_t MemoryByteArray::internalPut(int32_t index, ByteVector* b, + int32_t offset, int32_t length) { + 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, ByteVector* b, + int32_t offset, int32_t length) { + 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/sfntly/data/memory_byte_array.h b/sfntly/data/memory_byte_array.h new file mode 100644 index 0000000..34b26a6 --- /dev/null +++ b/sfntly/data/memory_byte_array.h @@ -0,0 +1,50 @@ +/* + * 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_DATA_MEMORY_BYTE_ARRAY_H_ +#define TYPOGRAPHY_FONT_SFNTLY_SRC_SFNTLY_DATA_MEMORY_BYTE_ARRAY_H_ + +#include "sfntly/data/byte_array.h" + +namespace sfntly { + +class MemoryByteArray : public ByteArray, public RefCounted { + public: + explicit MemoryByteArray(int32_t length); + MemoryByteArray(byte_t* b, int32_t buffer_length); + MemoryByteArray(byte_t* b, int32_t buffer_length, int32_t filled_length); + virtual ~MemoryByteArray(); + + protected: + virtual bool internalPut(int32_t index, byte_t b); + virtual int32_t internalPut(int32_t index, ByteVector* b, int32_t offset, + int32_t length); + virtual byte_t internalGet(int32_t index); + virtual int32_t internalGet(int32_t index, ByteVector* 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 // TYPOGRAPHY_FONT_SFNTLY_SRC_SFNTLY_DATA_MEMORY_BYTE_ARRAY_H_ diff --git a/sfntly/data/readable_font_data.cc b/sfntly/data/readable_font_data.cc new file mode 100644 index 0000000..3073b03 --- /dev/null +++ b/sfntly/data/readable_font_data.cc @@ -0,0 +1,197 @@ +/* + * 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 "sfntly/data/writable_font_data.h" +#include "sfntly/port/exception_type.h" + +namespace sfntly { + +ReadableFontData::~ReadableFontData() {} + +ReadableFontData::ReadableFontData(ByteArray* array) + : FontData(array), checksum_(0), checksum_set_(false) { +} + +ReadableFontData::ReadableFontData(ReadableFontData* data, int32_t offset) + : FontData(data, offset), checksum_(0), checksum_set_(false) { +} + +ReadableFontData::ReadableFontData(ReadableFontData* data, int32_t offset, + int32_t length) + : FontData(data, offset, length), checksum_(0), checksum_set_(false) { +} + +int64_t ReadableFontData::checksum() { + // TODO(arthurhsu): IMPLEMENT: atomicity + if (!checksum_set_) { + computeChecksum(); + } + return checksum_; +} + +/* OpenType checksum +ULONG +CalcTableChecksum(ULONG *Table, ULONG Length) +{ +ULONG Sum = 0L; +ULONG *Endptr = Table+((Length+3) & ~3) / sizeof(ULONG); +while (Table < EndPtr) + Sum += *Table++; +return Sum; +} +*/ +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; + for (int32_t i = low_bound; i < high_bound; i += 4) { + int32_t b3 = readUByte(i); + b3 = (b3 == -1) ? 0 : b3; + int32_t b2 = readUByte(i + 1); + b2 = (b2 == -1) ? 0 : b2; + int32_t b1 = readUByte(i + 2); + b1 = (b1 == -1) ? 0 : b1; + int32_t b0 = readUByte(i + 3); + b0 = (b0 == -1) ? 0 : b0; + sum += (b3 << 24) | (b2 << 16) | (b1 << 8) | b0; + } + return sum; +} + +void ReadableFontData::setCheckSumRanges(const IntegerList& ranges) { + checksum_range_ = ranges; + checksum_set_ = false; // UNIMPLEMENTED: atomicity +} + +int32_t ReadableFontData::readUByte(int32_t index) { + return 0xff & array_->get(boundOffset(index)); +} + +int32_t ReadableFontData::readByte(int32_t index) { + return (array_->get(boundOffset(index)) << 24) >> 24; +} + +int32_t ReadableFontData::readBytes(int32_t index, ByteVector* 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 ((ulong & 0x80000000) == 0x80000000) { + throw ArithmeticException("Long value too large to fit into an integer."); + } + return ((int32_t)ulong) & ~0x80000000; +} + +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()); +} + +CALLER_ATTACH FontData* ReadableFontData::slice(int32_t offset, + int32_t length) { + if (offset < 0 || offset + length > size()) { + return NULL; + } + FontDataPtr slice = new ReadableFontData(this, offset, length); + // Note: exception not ported because the condition is always false in C++. + // if (slice == null) { throw new IndexOutOfBoundsException( ... + return slice.detach(); +} + +CALLER_ATTACH FontData* ReadableFontData::slice(int32_t offset) { + if (offset < 0 || offset > size()) { + return NULL; + } + FontDataPtr slice = new ReadableFontData(this, offset); + // Note: exception not ported because the condition is always false in C++. + // if (slice == null) { throw new IndexOutOfBoundsException( ... + return slice.detach(); +} + +} // namespace sfntly diff --git a/sfntly/data/readable_font_data.h b/sfntly/data/readable_font_data.h new file mode 100644 index 0000000..be466de --- /dev/null +++ b/sfntly/data/readable_font_data.h @@ -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. + */ + +#ifndef TYPOGRAPHY_FONT_SFNTLY_SRC_SFNTLY_DATA_READABLE_FONT_DATA_H_ +#define TYPOGRAPHY_FONT_SFNTLY_SRC_SFNTLY_DATA_READABLE_FONT_DATA_H_ + +#include "sfntly/port/refcount.h" +#include "sfntly/data/font_data.h" + +namespace sfntly { + +class WritableFontData; +class OutputStream; +class ReadableFontData : public FontData, + public RefCounted { + public: + explicit ReadableFontData(ByteArray* array); + virtual ~ReadableFontData(); + + 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 + ReadableFontData(ReadableFontData* data, int32_t offset, int32_t length); + + private: + void computeChecksum(); + int64_t computeCheckSum(int32_t low_bound, int32_t high_bound); + + public: + // Get 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); + + public: + virtual int32_t readUByte(int32_t index); + virtual int32_t readByte(int32_t index); + virtual int32_t readBytes(int32_t index, ByteVector* b, int32_t offset, + int32_t length); + virtual int32_t readChar(int32_t index); + virtual int32_t readUShort(int32_t index); + virtual int32_t readShort(int32_t index); + virtual int32_t readUInt24(int32_t index); + virtual int64_t readULong(int32_t index); + virtual int32_t readULongAsInt(int32_t index); + virtual int32_t readLong(int32_t index); + virtual int32_t readFixed(int32_t index); + virtual int64_t readDateTimeAsLong(int32_t index); + + virtual int32_t readFWord(int32_t index); + virtual int32_t readFUFWord(int32_t index); + + virtual int32_t copyTo(OutputStream* os); + virtual int32_t copyTo(WritableFontData* wfd); + virtual int32_t copyTo(ByteArray* ba); + + // TODO(arthurhsu): IMPLEMENT + /* + virtual int32_t readFUnit(int32_t index); + virtual int64_t readF2Dot14(int32_t index); + virtual int64_t readLongDateTime(int32_t index); + virtual int32_t searchUShort(int32_t start, int32_t length, int32_t key); + virtual int32_t searchUShort(int32_t start_index, int32_t start_offset, + int32_t count_index, int32_t count_offset, + int32_t length, int32_t key); + virtual 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); + */ + + // 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: + bool checksum_set_; // TODO(arthurhsu): IMPLEMENT: must be set atomically + int64_t checksum_; + IntegerList checksum_range_; +}; +typedef Ptr ReadableFontDataPtr; + +} // namespace sfntly + +#endif // TYPOGRAPHY_FONT_SFNTLY_SRC_SFNTLY_DATA_READABLE_FONT_DATA_H_ diff --git a/sfntly/data/writable_font_data.cc b/sfntly/data/writable_font_data.cc new file mode 100644 index 0000000..8588acb --- /dev/null +++ b/sfntly/data/writable_font_data.cc @@ -0,0 +1,128 @@ +/* + * 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" + +namespace sfntly { + +WritableFontData::~WritableFontData() {} + +WritableFontData::WritableFontData(ByteArray* ba) : ReadableFontData(ba) { +} + +WritableFontData::WritableFontData(WritableFontData* data, int32_t offset) + : ReadableFontData(data, offset) { +} + +WritableFontData::WritableFontData(WritableFontData* data, int32_t offset, + int32_t length) + : ReadableFontData(data, offset, length) { +} + +int32_t WritableFontData::writeByte(int32_t index, byte_t b) { + array_->put(boundOffset(index), b); + return 1; +} + +int32_t WritableFontData::writeBytes(int32_t offset, ByteVector* b, + int32_t index, int32_t length) { + return array_->put(boundOffset(offset), b, index, + boundLength(offset, length)); +} + +int32_t WritableFontData::writeBytes(int32_t index, ByteVector* b) { + return writeBytes(index, b, 0, b->size()); +} + +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 l) { + return writeLong(index, l); +} + +int32_t WritableFontData::writeDateTime(int32_t index, int64_t date) { + writeULong(index, (date >> 32) & 0xffffffff); + writeULong(index + 4, date & 0xffffffff); + return 8; +} + +CALLER_ATTACH FontData* WritableFontData::slice(int32_t offset, + int32_t length) { + if (offset < 0 || offset + length > size()) { + return NULL; + } + FontDataPtr slice = new WritableFontData(this, offset, length); + // Note: exception not ported because the condition is always false in C++. + // if (slice == null) { throw new IndexOutOfBoundsException( ... + return slice.detach(); +} + +CALLER_ATTACH FontData* WritableFontData::slice(int32_t offset) { + if (offset > size()) { + return NULL; + } + FontDataPtr slice = new WritableFontData(this, offset); + // Note: exception not ported because the condition is always false in C++. + // if (slice == null) { throw new IndexOutOfBoundsException( ... + return slice.detach(); +} + +} // namespace sfntly diff --git a/sfntly/data/writable_font_data.h b/sfntly/data/writable_font_data.h new file mode 100644 index 0000000..9542cd0 --- /dev/null +++ b/sfntly/data/writable_font_data.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 TYPOGRAPHY_FONT_SFNTLY_SRC_SFNTLY_DATA_WRITABLE_FONT_DATA_H_ +#define TYPOGRAPHY_FONT_SFNTLY_SRC_SFNTLY_DATA_WRITABLE_FONT_DATA_H_ + +#include "sfntly/data/readable_font_data.h" + +namespace sfntly { + +class WritableFontData : public ReadableFontData { + public: + explicit WritableFontData(ByteArray* ba); + virtual ~WritableFontData(); + + private: + WritableFontData(WritableFontData* data, int32_t offset); + WritableFontData(WritableFontData* data, int32_t offset, int32_t length); + + public: + virtual int32_t writeByte(int32_t index, byte_t b); + virtual int32_t writeBytes(int32_t offset, ByteVector* b, int32_t index, + int32_t length); + virtual int32_t writeBytes(int32_t index, ByteVector* b); + virtual int32_t writeChar(int32_t index, byte_t c); + virtual int32_t writeUShort(int32_t index, int32_t us); + virtual int32_t writeUShortLE(int32_t index, int32_t us); + virtual int32_t writeShort(int32_t index, int32_t s); + virtual int32_t writeUInt24(int32_t index, int32_t ui); + virtual int32_t writeULong(int32_t index, int64_t ul); + virtual int32_t writeULongLE(int32_t index, int64_t ul); + virtual int32_t writeLong(int32_t index, int64_t l); + virtual int32_t writeFixed(int32_t index, int32_t l); + virtual int32_t writeDateTime(int32_t index, int64_t date); + + // 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); +}; +typedef Ptr WritableFontDataPtr; + +} // namespace sfntly + +#endif // TYPOGRAPHY_FONT_SFNTLY_SRC_SFNTLY_DATA_WRITABLE_FONT_DATA_H_ diff --git a/sfntly/font.cc b/sfntly/font.cc new file mode 100644 index 0000000..1ef222a --- /dev/null +++ b/sfntly/font.cc @@ -0,0 +1,593 @@ +/* + * 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 + +#include "sfntly/font.h" +#include "sfntly/font_factory.h" +#include "sfntly/tag.h" +#include "sfntly/math/fixed1616.h" +#include "sfntly/math/font_math.h" +#include "sfntly/data/font_input_stream.h" +#include "sfntly/font_header_table.h" +#include "sfntly/horizontal_header_table.h" +#include "sfntly/horizontal_metrics_table.h" +#include "sfntly/maximum_profile_table.h" +#include "sfntly/loca_table.h" +#include "sfntly/port/exception_type.h" + +namespace sfntly { + +/****************************************************************************** + * constant definitions + ******************************************************************************/ +const int32_t PlatformId::kUnknown = -1; +const int32_t PlatformId::kUnicode = 0; +const int32_t PlatformId::kMacintosh = 1; +const int32_t PlatformId::kISO = 2; +const int32_t PlatformId::kWindows = 3; +const int32_t PlatformId::kCustom = 4; + +const int32_t UnicodeEncodingId::kUnknown = -1; +const int32_t UnicodeEncodingId::kUnicode1_0 = 0; +const int32_t UnicodeEncodingId::kUnicode1_1 = 1; +const int32_t UnicodeEncodingId::kISO10646 = 2; +const int32_t UnicodeEncodingId::kUnicode2_0_BMP = 3; +const int32_t UnicodeEncodingId::kUnicode2_0 = 4; +const int32_t UnicodeEncodingId::kUnicodeVariationSequences = 5; + +const int32_t WindowsEncodingId::kUnknown = 0xffffffff; +const int32_t WindowsEncodingId::kSymbol = 0; +const int32_t WindowsEncodingId::kUnicodeUCS2 = 1; +const int32_t WindowsEncodingId::kShiftJIS = 2; +const int32_t WindowsEncodingId::kPRC = 3; +const int32_t WindowsEncodingId::kBig5 = 4; +const int32_t WindowsEncodingId::kWansung = 5; +const int32_t WindowsEncodingId::kJohab = 6; +const int32_t WindowsEncodingId::kUnicodeUCS4 = 10; + +const int32_t MacintoshEncodingId::kUnknown = -1; +const int32_t MacintoshEncodingId::kRoman = 0; +const int32_t MacintoshEncodingId::kJapanese = 1; +const int32_t MacintoshEncodingId::kChineseTraditional = 2; +const int32_t MacintoshEncodingId::kKorean = 3; +const int32_t MacintoshEncodingId::kArabic = 4; +const int32_t MacintoshEncodingId::kHebrew = 5; +const int32_t MacintoshEncodingId::kGreek = 6; +const int32_t MacintoshEncodingId::kRussian = 7; +const int32_t MacintoshEncodingId::kRSymbol = 8; +const int32_t MacintoshEncodingId::kDevanagari = 9; +const int32_t MacintoshEncodingId::kGurmukhi = 10; +const int32_t MacintoshEncodingId::kGujarati = 11; +const int32_t MacintoshEncodingId::kOriya = 12; +const int32_t MacintoshEncodingId::kBengali = 13; +const int32_t MacintoshEncodingId::kTamil = 14; +const int32_t MacintoshEncodingId::kTelugu = 15; +const int32_t MacintoshEncodingId::kKannada = 16; +const int32_t MacintoshEncodingId::kMalayalam = 17; +const int32_t MacintoshEncodingId::kSinhalese = 18; +const int32_t MacintoshEncodingId::kBurmese = 19; +const int32_t MacintoshEncodingId::kKhmer = 20; +const int32_t MacintoshEncodingId::kThai = 21; +const int32_t MacintoshEncodingId::kLaotian = 22; +const int32_t MacintoshEncodingId::kGeorgian = 23; +const int32_t MacintoshEncodingId::kArmenian = 24; +const int32_t MacintoshEncodingId::kChineseSimplified = 25; +const int32_t MacintoshEncodingId::kTibetan = 26; +const int32_t MacintoshEncodingId::kMongolian = 27; +const int32_t MacintoshEncodingId::kGeez = 28; +const int32_t MacintoshEncodingId::kSlavic = 29; +const int32_t MacintoshEncodingId::kVietnamese = 30; +const int32_t MacintoshEncodingId::kSindhi = 31; +const int32_t MacintoshEncodingId::kUninterpreted = 32; + +const int32_t SFNTVERSION_1 = Fixed1616::fixed(1, 0); + +const int32_t Font::Offset::kSfntVersion = 0; +const int32_t Font::Offset::kNumTables = 4; +const int32_t Font::Offset::kSearchRange = 6; +const int32_t Font::Offset::kEntrySelector = 8; +const int32_t Font::Offset::kRangeShift = 10; +const int32_t Font::Offset::kTableRecordBegin = 12; +const int32_t Font::Offset::kSfntHeaderSize = 12; +const int32_t Font::Offset::kTableTag = 0; +const int32_t Font::Offset::kTableCheckSum = 4; +const int32_t Font::Offset::kTableOffset = 8; +const int32_t Font::Offset::kTableLength = 12; +const int32_t Font::Offset::kTableRecordSize = 16; + +/****************************************************************************** + * Font class + ******************************************************************************/ +Font::~Font() {} + +Font::Font(FontFactory* factory, int32_t sfnt_version, ByteVector* digest, + TableMap* tables) : + sfnt_version_(sfnt_version), factory_(factory) { + // non-trivial assignments that makes debugging hard if placed in + // initialization list + digest_ = *digest; + tables_ = *tables; +} + +int32_t Font::version() { + return sfnt_version_; +} + +ByteVector* Font::digest() { + return &digest_; +} + +int64_t Font::checksum() { + return checksum_; +} + +int32_t Font::numTables() { + return (int32_t)tables_.size(); +} + +bool Font::hasTable(int32_t tag) { + TableMap::const_iterator result = tables_.find(tag); + TableMap::const_iterator end = tables_.end(); + return (result != end); +} + +Table* Font::table(int32_t tag) { + if (!hasTable(tag)) { + return NULL; + } + return tables_[tag]; +} + +TableMap* Font::tables() { + return &tables_; +} + +void Font::serialize(OutputStream* os, IntegerList* table_ordering) { + assert(table_ordering); + IntegerList final_table_ordering; + tableOrdering(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); +} + +void Font::buildTableHeadersForSerialization(IntegerList* table_ordering, + TableHeaderList* table_headers) { + assert(table_headers); + assert(table_ordering); + + IntegerList final_table_ordering; + tableOrdering(table_ordering, &final_table_ordering); + int32_t table_offset = Offset::kTableRecordBegin + numTables() * + Offset::kTableRecordSize; + for (IntegerList::iterator tag = final_table_ordering.begin(), + tag_end = final_table_ordering.end(); + tag != tag_end; ++tag) { + TablePtr table = tables_[*tag]; + if (table != NULL) { + TableHeaderPtr header = + new Table::Header(*tag, table->calculatedChecksum(), table_offset, + table->length()); + table_headers->push_back(header); + table_offset += (table->length() + 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); + + for (TableHeaderList::iterator record = table_headers->begin(), + record_end = table_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) { + ByteVector SERIALIZATION_FILLER(3); + std::fill(SERIALIZATION_FILLER.begin(), SERIALIZATION_FILLER.end(), 0); + for (TableHeaderList::iterator record = table_headers->begin(), + end_of_headers = table_headers->end(); + record != end_of_headers; ++record) { + TablePtr target_table = table((*record)->tag()); + if (target_table == NULL) { + throw IOException("Table out of sync with font header."); + } + int32_t table_size = target_table->serialize(fos); + int32_t filler_size = ((table_size + 3) & ~3) - table_size; + fos->write(&SERIALIZATION_FILLER, 0, filler_size); + } +} + +void Font::tableOrdering(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()); +} + +CALLER_ATTACH WritableFontData* Font::getNewData(int32_t size) { + return factory_->getNewData(size); +} + +/****************************************************************************** + * Font::Builder class + ******************************************************************************/ +Font::Builder::~Builder() {} + +Font::Builder::Builder(FontFactory* factory) + : factory_(factory), sfnt_version_(SFNTVERSION_1) { +} + +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); + TableHeaderSortedSet records; + readHeader(&font_is, &records); + loadTableData(&records, &font_is, &data_blocks_); + buildAllTableBuilders(&data_blocks_, &table_builders_); + font_is.close(); +} + +void Font::Builder::loadFont(ByteArray* ba, + int32_t offset_to_offset_table) { + // Note: we do not throw exception here for is. This is more of an assertion. + assert(ba); + WritableFontDataPtr fd = new WritableFontData(ba); + TableHeaderSortedSet records; + readHeader(fd, offset_to_offset_table, &records); + loadTableData(&records, fd, &data_blocks_); + buildAllTableBuilders(&data_blocks_, &table_builders_); +} + +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, ByteArray* ba, int32_t offset_to_offset_table) { + FontBuilderPtr builder = new Builder(factory); + builder->loadFont(ba, 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() { + TableMap tables; + if (!table_builders_.empty()) { + buildTablesFromBuilders(&table_builders_, &tables); + } + FontPtr font = new Font(factory_, sfnt_version_, &digest_, &tables); + table_builders_.clear(); + data_blocks_.clear(); + return font.detach(); +} + +CALLER_ATTACH WritableFontData* Font::Builder::getNewData(int32_t capacity) { + return factory_->getNewData(capacity); +} + +CALLER_ATTACH WritableFontData* Font::Builder::getNewGrowableData( + ReadableFontData* src_data) { + return factory_->getNewGrowableData(src_data); +} + +void Font::Builder::setDigest(ByteVector* digest) { + digest_.clear(); + digest_ = *digest; +} + +void Font::Builder::cleanTableBuilders() { + 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; +} + +CALLER_ATTACH Table::Builder* Font::Builder::newTableBuilder(int32_t tag) { + TableHeaderPtr header = new Table::Header(tag); + TableBuilderPtr builder = Table::Builder::getBuilder(this, header, NULL); + table_builders_.insert(TableBuilderEntry(header->tag(), builder)); + return builder; +} + +CALLER_ATTACH Table::Builder* Font::Builder::newTableBuilder( + int32_t tag, ReadableFontData* src_data) { + WritableFontDataPtr data; + data.attach(getNewGrowableData(src_data)); + TableHeaderPtr header = new Table::Header(tag); + TableBuilderPtr builder = Table::Builder::getBuilder(this, header, data); + table_builders_.insert(TableBuilderEntry(tag, builder)); + return builder; +} + +TableBuilderMap* Font::Builder::tableBuilders() { + return &table_builders_; +} + +void Font::Builder::tableBuilderTags(IntegerSet* key_set) { + assert(key_set); + key_set->clear(); + for (TableBuilderMap::iterator i = table_builders_.begin(), + e = table_builders_.end(); i != e; ++i) { + key_set->insert(i->first); + } +} + +void Font::Builder::removeTableBuilder(int32_t tag) { + TableBuilderMap::iterator target = table_builders_.find(tag); + if (target != table_builders_.end()) { + table_builders_.erase(target); + } +} + +int32_t Font::Builder::numberOfTableBuilders() { + return (int32_t)table_builders_.size(); +} + +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( + Table::Header* header, WritableFontData* data) { + return Table::Builder::getBuilder(this, header, data); +} + +void Font::Builder::buildTablesFromBuilders(TableBuilderMap* builder_map, + TableMap* table_map) { + 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->readyToBuild()) { + try { + table.attach(down_cast(builder->second->build())); + } catch(IOException& e) { + std::string builder_string = "Unable to build table - "; + builder_string += typeid(builder->second).name(); + builder_string += e.what(); + throw RuntimeException(builder_string.c_str()); + } + } + if (table == NULL) { + std::string builder_string = "Unable to build table - "; + builder_string += typeid(builder->second).name(); + throw RuntimeException(builder_string.c_str()); + } + table_map->insert(TableMapEntry(table->header()->tag(), table)); + } +} + +void Font::Builder::interRelateBuilders(TableBuilderMap* builder_map) { + FontHeaderTableBuilderPtr header_table_builder = + down_cast((*builder_map)[Tag::head].p_); + HorizontalHeaderTableBuilderPtr horizontal_header_builder = + down_cast((*builder_map)[Tag::hhea].p_); + MaximumProfileTableBuilderPtr max_profile_builder = + down_cast((*builder_map)[Tag::maxp].p_); + LocaTableBuilderPtr loca_table_builder = + down_cast((*builder_map)[Tag::loca].p_); + HorizontalMetricsTableBuilderPtr horizontal_metrics_builder = + down_cast( + (*builder_map)[Tag::hmtx].p_); + + // 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->setFormatVersion( + header_table_builder->indexToLocFormat()); + } + } +} + +void Font::Builder::readHeader(FontInputStream* is, + TableHeaderSortedSet* 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(); + TableHeaderPtr table = new Table::Header(tag, checksum, offset, length); + records->insert(table); + } +} + +void Font::Builder::loadTableData(TableHeaderSortedSet* headers, + FontInputStream* is, + DataBlockMap* table_data) { + assert(table_data); + for (TableHeaderSortedSet::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()); + int32_t roundup_length = ((*table_header)->length() + 3) & ~3; + ByteArrayPtr array = factory_->getNewArray(roundup_length); + array->copyFrom(&table_is, (*table_header)->length()); + WritableFontDataPtr data = new WritableFontData(array); + table_data->insert(DataBlockEntry(*table_header, data)); + } +} + +void Font::Builder::readHeader(ReadableFontData* fd, int32_t offset, + TableHeaderSortedSet* 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); + TableHeaderPtr table = new Table::Header(tag, checksum, offset, length); + records->insert(table); + } +} + +void Font::Builder::loadTableData(TableHeaderSortedSet* headers, + WritableFontData* fd, + DataBlockMap* table_data) { + for (TableHeaderSortedSet::iterator + table_header = headers->begin(), table_end = headers->end(); + table_header != table_end; ++table_header) { + int32_t roundup_length = ((*table_header)->length() + 3) & ~3; + FontDataPtr sliced_data; + sliced_data.attach(fd->slice((*table_header)->offset(), roundup_length)); + WritableFontDataPtr data = down_cast(sliced_data.p_); + table_data->insert(DataBlockEntry(*table_header, data)); + } +} + +} // namespace sfntly diff --git a/sfntly/font.h b/sfntly/font.h new file mode 100644 index 0000000..4b1dc1b --- /dev/null +++ b/sfntly/font.h @@ -0,0 +1,289 @@ +/* + * 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_FONT_H_ +#define TYPOGRAPHY_FONT_SFNTLY_SRC_SFNTLY_FONT_H_ + +#include + +#include "sfntly/port/refcount.h" +#include "sfntly/port/type.h" +#include "sfntly/port/endian.h" +#include "sfntly/table.h" +#include "sfntly/font_data_table_builder_container.h" +#include "sfntly/data/font_input_stream.h" +#include "sfntly/data/font_output_stream.h" +#include "sfntly/data/writable_font_data.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 { + static const int32_t kUnknown; + static const int32_t kUnicode; + static const int32_t kMacintosh; + static const int32_t kISO; + static const int32_t kWindows; + static const int32_t kCustom; +}; + +// Unicode encoding ids. These are used in a number of places within the font +// whenever character encodings need to be specified. +struct UnicodeEncodingId { + static const int32_t kUnknown; + static const int32_t kUnicode1_0; + static const int32_t kUnicode1_1; + static const int32_t kISO10646; + static const int32_t kUnicode2_0_BMP; + static const int32_t kUnicode2_0; + static const int32_t kUnicodeVariationSequences; +}; + +// Windows encoding ids. These are used in a number of places within the font +// whenever character encodings need to be specified. +struct WindowsEncodingId { + static const int32_t kUnknown; + static const int32_t kSymbol; + static const int32_t kUnicodeUCS2; + static const int32_t kShiftJIS; + static const int32_t kPRC; + static const int32_t kBig5; + static const int32_t kWansung; + static const int32_t kJohab; + static const int32_t kUnicodeUCS4; +}; + +// 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 + static const int32_t kUnknown; + static const int32_t kRoman; + static const int32_t kJapanese; + static const int32_t kChineseTraditional; + static const int32_t kKorean; + static const int32_t kArabic; + static const int32_t kHebrew; + static const int32_t kGreek; + static const int32_t kRussian; + static const int32_t kRSymbol; + static const int32_t kDevanagari; + static const int32_t kGurmukhi; + static const int32_t kGujarati; + static const int32_t kOriya; + static const int32_t kBengali; + static const int32_t kTamil; + static const int32_t kTelugu; + static const int32_t kKannada; + static const int32_t kMalayalam; + static const int32_t kSinhalese; + static const int32_t kBurmese; + static const int32_t kKhmer; + static const int32_t kThai; + static const int32_t kLaotian; + static const int32_t kGeorgian; + static const int32_t kArmenian; + static const int32_t kChineseSimplified; + static const int32_t kTibetan; + static const int32_t kMongolian; + static const int32_t kGeez; + static const int32_t kSlavic; + static const int32_t kVietnamese; + static const int32_t kSindhi; + static const int32_t kUninterpreted; +}; + +extern const int32_t SFNTVERSION_1; + +class FontFactory; +class Font : public RefCounted { + 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 { + // Offsets within the main directory + static const int32_t kSfntVersion; + static const int32_t kNumTables; + static const int32_t kSearchRange; + static const int32_t kEntrySelector; + static const int32_t kRangeShift; + static const int32_t kTableRecordBegin; + static const int32_t kSfntHeaderSize; + + // Offsets within a specific table record + static const int32_t kTableTag; + static const int32_t kTableCheckSum; + static const int32_t kTableOffset; + static const int32_t kTableLength; + static const int32_t kTableRecordSize; + }; + + // 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[]; + + public: + virtual ~Font(); + + private: + Font(FontFactory* factory, int32_t sfnt_version, ByteVector* digest, + TableMap* tables); + + public: + // Gets the sfnt version set in the sfnt wrapper of the font. + virtual int32_t 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. + virtual ByteVector* digest(); + + // Get the checksum for this font. + virtual int64_t checksum(); + + // Get the number of tables in this font. + virtual int32_t numTables(); + + // Whether the font has a particular table. + virtual 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 + virtual Table* table(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 + virtual TableMap* tables(); + + // Serialize the font to the output stream. + // @param os the destination for the font serialization + // @param tableOrdering the table ordering to apply + virtual void serialize(OutputStream* os, IntegerList* table_ordering); + + private: + void buildTableHeadersForSerialization(IntegerList* table_ordering, + TableHeaderList* table_headers); + void serializeHeader(FontOutputStream* fos, TableHeaderList* table_headers); + void serializeTables(FontOutputStream* fos, TableHeaderList* table_headers); + void tableOrdering(IntegerList* default_table_ordering, + IntegerList* table_ordering); + void defaultTableOrdering(IntegerList* default_table_ordering); + + public: + class Builder : public FontDataTableBuilderContainer, + public RefCounted { + public: + virtual ~Builder(); + + private: + explicit Builder(FontFactory* factory); + virtual void loadFont(InputStream* is); + virtual void loadFont(ByteArray* buffer, int32_t offset_to_offset_table); + + public: + static CALLER_ATTACH Builder* + getOTFBuilder(FontFactory* factory, InputStream* is); + static CALLER_ATTACH Builder* + getOTFBuilder(FontFactory* factory, ByteArray* ba, + int32_t offset_to_offset_table); + static CALLER_ATTACH Builder* getOTFBuilder(FontFactory* factory); + virtual bool readyToBuild(); + virtual CALLER_ATTACH Font* build(); + virtual CALLER_ATTACH WritableFontData* getNewData(int32_t capacity); + virtual CALLER_ATTACH WritableFontData* + getNewGrowableData(ReadableFontData* data); + virtual void setDigest(ByteVector* digest); + virtual void cleanTableBuilders(); + virtual bool hasTableBuilder(int32_t tag); + virtual 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 CALLER_ATTACH Table::Builder* newTableBuilder(int32_t tag); + virtual CALLER_ATTACH Table::Builder* + newTableBuilder(int32_t tag, ReadableFontData* src_data); + virtual TableBuilderMap* tableBuilders(); + virtual void tableBuilderTags(IntegerSet* key_set); + // Note: different from Java: we don't return object in removeTableBuilder + virtual void removeTableBuilder(int32_t tag); + virtual int32_t numberOfTableBuilders(); + + private: + int32_t sfntWrapperSize(); + void buildAllTableBuilders(DataBlockMap* table_data, + TableBuilderMap* builder_map); + CALLER_ATTACH Table::Builder* + getTableBuilder(Table::Header* header, WritableFontData* data); + void buildTablesFromBuilders(TableBuilderMap* builder_map, + TableMap* tables); + static void interRelateBuilders(TableBuilderMap* builder_map); + void readHeader(FontInputStream* is, TableHeaderSortedSet* records); + void loadTableData(TableHeaderSortedSet* headers, FontInputStream* is, + DataBlockMap* table_data); + void readHeader(ReadableFontData* fd, int32_t offset, + TableHeaderSortedSet* records); + void loadTableData(TableHeaderSortedSet* headers, WritableFontData* fd, + DataBlockMap* table_data); + + private: + 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_; + }; + + public: + // Get a new data object. The size is a request for a data object and the + // returned data object will support at least that amount. A value greater + // than zero for the size is a request for a fixed size data object. A + // negative or zero value for the size is a request for a variable sized data + // object with the absolute value of the size being an estimate of the space + // required. + // @param size greater than zero is a request for a fixed size data object of + // the given size; less than or equal to zero is a request for a + // variable size data object with the absolute size as an estimate + CALLER_ATTACH WritableFontData* getNewData(int32_t size); + + private: + FontFactory* factory_; // dumb pointer, avoid circular ref-counting + 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 // TYPOGRAPHY_FONT_SFNTLY_SRC_SFNTLY_FONT_H_ diff --git a/sfntly/font_data_table.cc b/sfntly/font_data_table.cc new file mode 100644 index 0000000..9896b24 --- /dev/null +++ b/sfntly/font_data_table.cc @@ -0,0 +1,186 @@ +/* + * 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_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::length() { + return data_->length(); +} + +int32_t FontDataTable::padding() { + return -1; +} + +int32_t FontDataTable::dataLength() { + int32_t paddings = padding(); + return (paddings == -1) ? length() : length() - paddings; +} + +int32_t FontDataTable::serialize(OutputStream* os) { + return data_->copyTo(os); +} + +/****************************************************************************** + * FontDataTable::Builder class + ******************************************************************************/ +void FontDataTable::Builder::init(FontDataTableBuilderContainer* container) { + container_ = container; + model_changed_ = false; + data_changed_ = false; +} + +FontDataTable::Builder::Builder(FontDataTableBuilderContainer* container) { + init(container); +} + +FontDataTable::Builder::Builder(FontDataTableBuilderContainer* container, + WritableFontData* data) { + init(container); + w_data_ = data; +} + +FontDataTable::Builder::Builder(FontDataTableBuilderContainer* container, + ReadableFontData* data) { + init(container); + r_data_ = data; +} + +FontDataTable::Builder::~Builder() { +} + +WritableFontData* FontDataTable::Builder::data() { + WritableFontDataPtr new_data; + if (model_changed_) { + if (!subReadyToSerialize()) { + return NULL; + } + int32_t size = subDataSizeToSerialize(); + new_data.attach(container_->getNewData(size)); + subSerialize(new_data); + } else { + ReadableFontDataPtr data = internalReadData(); + new_data.attach(container_->getNewData(data != NULL ? data->length() : 0)); + data->copyTo(new_data); + } + return new_data.detach(); +} + +void FontDataTable::Builder::setData(ReadableFontData* data) { + internalSetData(data, true); +} + +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(); + } +} + +CALLER_ATTACH FontDataTable* FontDataTable::Builder::build() { + ReadableFontDataPtr data = internalReadData(); + if (model_changed_) { + // Let subclass serialize from model. + if (!subReadyToSerialize()) { + return NULL; + } + int32_t size = subDataSizeToSerialize(); + WritableFontDataPtr new_data; + new_data.attach(container_->getNewData(size)); + subSerialize(new_data); + data = new_data; + } + FontDataTablePtr table = subBuildTable(data); + notifyPostTableBuild(table); + 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(container_->getNewData(r_data_->length())); + r_data_->copyTo(new_data); + internalSetData(new_data, false); + } + return w_data_.p_; +} + +WritableFontData* FontDataTable::Builder::internalNewData(int32_t size) { + return container_->getNewData(size); +} + +bool FontDataTable::Builder::dataChanged() { + return data_changed_; +} + +bool FontDataTable::Builder::modelChanged() { + return model_changed_; +} + +bool FontDataTable::Builder::setModelChanged() { + return setModelChanged(true); +} + +bool FontDataTable::Builder::setModelChanged(bool changed) { + bool old = model_changed_; + model_changed_ = changed; + return old; +} + +void FontDataTable::Builder::notifyPostTableBuild(FontDataTable* table) { + // default: NOP + UNREFERENCED_PARAMETER(table); +} + +} // namespace sfntly diff --git a/sfntly/font_data_table.h b/sfntly/font_data_table.h new file mode 100644 index 0000000..28bec15 --- /dev/null +++ b/sfntly/font_data_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 TYPOGRAPHY_FONT_SFNTLY_SRC_SFNTLY_FONT_DATA_TABLE_H_ +#define TYPOGRAPHY_FONT_SFNTLY_SRC_SFNTLY_FONT_DATA_TABLE_H_ + +#include "sfntly/data/readable_font_data.h" +#include "sfntly/font_data_table_builder_container.h" +#include "sfntly/port/refcount.h" + +namespace sfntly { + +class FontDataTable : virtual public RefCount { + public: + 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 and may or may not include any padding. + virtual int32_t length(); + + // Get the number of bytes of padding used in the table. The padding bytes are + // used to align the table length to a 4 byte boundary. + virtual int32_t padding(); + + // Return the number of bytes of non-padded data in the table. If the padding + // is unknown or unknowable then the total number of bytes of data in the + // tables is returned. + virtual int32_t dataLength(); + + virtual int32_t serialize(OutputStream* os); + + public: + // Note: original version is abstract Builder + // C++ template is not designed that way so plain class is chosen. + class Builder : virtual public RefCount { + protected: + explicit Builder(FontDataTableBuilderContainer* container); + Builder(FontDataTableBuilderContainer* container, WritableFontData* data); + Builder(FontDataTableBuilderContainer* container, ReadableFontData* data); + virtual ~Builder(); + + void init(FontDataTableBuilderContainer* container); + + 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 + WritableFontData* data(); + virtual void setData(ReadableFontData* data); + + private: + void internalSetData(WritableFontData* data, bool data_changed); + void internalSetData(ReadableFontData* data, bool data_changed); + + public: // Note: changed from protected to avoid accessibility error in C++ + virtual FontDataTable* build(); + virtual bool readyToBuild(); + virtual ReadableFontData* internalReadData(); + virtual WritableFontData* internalWriteData(); + virtual WritableFontData* internalNewData(int32_t size); + virtual bool dataChanged(); + virtual bool modelChanged(); + virtual bool setModelChanged(); + virtual bool setModelChanged(bool changed); + + protected: // 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: + FontDataTableBuilderContainer* container_; // avoid circular ref-counting + WritableFontDataPtr w_data_; + ReadableFontDataPtr r_data_; + bool model_changed_; + bool data_changed_; + }; + + protected: + ReadableFontDataPtr data_; +}; +typedef Ptr FontDataTablePtr; + +} // namespace sfntly + +#endif // TYPOGRAPHY_FONT_SFNTLY_SRC_SFNTLY_FONT_DATA_TABLE_H_ diff --git a/sfntly/font_data_table_builder_container.h b/sfntly/font_data_table_builder_container.h new file mode 100644 index 0000000..7866a36 --- /dev/null +++ b/sfntly/font_data_table_builder_container.h @@ -0,0 +1,34 @@ +/* + * 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_FONT_DATA_TABLE_BUILDER_CONTAINER_H_ +#define TYPOGRAPHY_FONT_SFNTLY_SRC_SFNTLY_FONT_DATA_TABLE_BUILDER_CONTAINER_H_ + +#include "sfntly/data/writable_font_data.h" + +namespace sfntly { + +class FontDataTableBuilderContainer { + public: + virtual WritableFontData* getNewData(int32_t size) = 0; + // Make gcc -Wnon-virtual-dtor happy. + virtual ~FontDataTableBuilderContainer() {} +}; +typedef Ptr FontDataTableBuilderContainerPtr; + +} // namespace sfntly + +#endif // TYPOGRAPHY_FONT_SFNTLY_SRC_SFNTLY_FONT_DATA_TABLE_BUILDER_CONTAINER_H_ diff --git a/sfntly/font_factory.cc b/sfntly/font_factory.cc new file mode 100644 index 0000000..f1d1f25 --- /dev/null +++ b/sfntly/font_factory.cc @@ -0,0 +1,250 @@ +/* + * 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 "sfntly/font_factory.h" +#include "sfntly/tag.h" +#include "sfntly/data/memory_byte_array.h" +#include "sfntly/data/growable_memory_byte_array.h" + +namespace sfntly { + +const int32_t FontFactory::Offset::kTTCTag = 0; +const int32_t FontFactory::Offset::kVersion = 4; +const int32_t FontFactory::Offset::kNumFonts = 8; +const int32_t FontFactory::Offset::kOffsetTable = 12; +const int32_t FontFactory::Offset::kulDsigTag = 0; +const int32_t FontFactory::Offset::kulDsigLength = 4; +const int32_t FontFactory::Offset::kulDsigOffset = 8; + +FontFactory::FontFactory() : fingerprint_(false) { +} + +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 = loadSingleOTF(pbis); + 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); + } +} + +Font* FontFactory::loadSingleOTF(InputStream* is) { + FontBuilderPtr builder; + builder.attach(loadSingleOTFForBuilding(is)); + 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); + } +} + +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; +} + +void FontFactory::loadCollectionForBuilding(InputStream* is, + FontBuilderArray* builders) { + ByteArrayPtr ba = new GrowableMemoryByteArray(); + ba->copyFrom(is); + loadCollectionForBuilding(ba, builders); +} + +bool FontFactory::isCollection(PushbackInputStream* pbis) { + ByteVector tag(4); + pbis->read(&tag); + pbis->unread(&tag); + return Tag::ttcf == generate_tag(tag[0], tag[1], tag[2], tag[3]); +} + +void FontFactory::loadFonts(ByteArray* ba, FontArray* output) { + if (isCollection(ba)) { + loadCollection(ba, output); + return; + } + FontPtr font; + font.attach(loadSingleOTF(ba)); + if (font) { + output->push_back(font); + } +} + +void FontFactory::loadFontsForBuilding(ByteArray* ba, + FontBuilderArray* output) { + if (isCollection(ba)) { + loadCollectionForBuilding(ba, output); + return; + } + FontBuilderPtr builder; + builder.attach(loadSingleOTFForBuilding(ba, 0)); + if (builder) { + output->push_back(builder); + } +} + +Font* FontFactory::loadSingleOTF(ByteArray* ba) { + FontBuilderPtr builder; + builder.attach(loadSingleOTFForBuilding(ba, 0)); + return builder->build(); +} + +void FontFactory::loadCollection(ByteArray* ba, FontArray* output) { + FontBuilderArray builders; + loadCollectionForBuilding(ba, &builders); + output->reserve(ba->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); + } +} + +Font::Builder* FontFactory::loadSingleOTFForBuilding(ByteArray* ba, + int32_t offset_to_offset_table) { + // UNIMPLEMENTED: SHA-1 hash checking via Java DigestStream + Font::Builder* builder = + Font::Builder::getOTFBuilder(this, ba, offset_to_offset_table); + // UNIMPLEMENTED: setDigest + return builder; +} + +void FontFactory::loadCollectionForBuilding(ByteArray* ba, + FontBuilderArray* builders) { + ReadableFontDataPtr rfd = new ReadableFontData(ba); + int32_t ttc_tag = rfd->readULongAsInt(Offset::kTTCTag); + UNREFERENCED_PARAMETER(ttc_tag); + int32_t version = rfd->readFixed(Offset::kVersion); + UNREFERENCED_PARAMETER(version); + int32_t num_fonts = rfd->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 = rfd->readULongAsInt(offset_table_offset); + FontBuilderPtr builder; + builder.attach(loadSingleOTFForBuilding(ba, offset)); + builders->push_back(builder); + } +} + +bool FontFactory::isCollection(ByteArray* ba) { + return Tag::ttcf == + generate_tag(ba->get(0), ba->get(1), ba->get(2), ba->get(3)); +} + +CALLER_ATTACH WritableFontData* FontFactory::getNewData(int32_t capacity) { + // UNIMPLMENTED: if (capacity > 0) { this.getNewFixedData(capacity); } + // seems a no-op + return getNewGrowableData(capacity); +} + +CALLER_ATTACH WritableFontData* FontFactory::getNewFixedData(int32_t capacity) { + ByteArrayPtr buffer; + buffer.attach(getNewArray(capacity)); + WritableFontDataPtr new_fixed_data = new WritableFontData(buffer); + return new_fixed_data.detach(); +} + +CALLER_ATTACH WritableFontData* FontFactory::getNewGrowableData( + int32_t capacity) { + ByteArrayPtr buffer; + buffer.attach(getNewGrowableArray(capacity)); + WritableFontDataPtr new_growable_data = new WritableFontData(buffer); + return new_growable_data.detach(); +} + +CALLER_ATTACH WritableFontData* FontFactory::getNewGrowableData( + ReadableFontData* src_data) { + WritableFontDataPtr data; + data.attach(getNewGrowableData(src_data->length())); + src_data->copyTo(data); + return data.detach(); +} + +CALLER_ATTACH ByteArray* FontFactory::getNewArray(int32_t length) { + ByteArrayPtr new_fixed_array = new MemoryByteArray(length); + return new_fixed_array.detach(); +} + +CALLER_ATTACH ByteArray* FontFactory::getNewGrowableArray(int32_t length) { + UNREFERENCED_PARAMETER(length); + ByteArrayPtr new_growable_array = new GrowableMemoryByteArray(); + return new_growable_array.detach(); +} + +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); +} + +} // namespace sfntly diff --git a/sfntly/font_factory.h b/sfntly/font_factory.h new file mode 100644 index 0000000..9307d91 --- /dev/null +++ b/sfntly/font_factory.h @@ -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. + */ + +#ifndef TYPOGRAPHY_FONT_SFNTLY_SRC_SFNTLY_FONT_FACTORY_H_ +#define TYPOGRAPHY_FONT_SFNTLY_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 { + 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 { + // Offsets within the main directory + static const int32_t kTTCTag; + static const int32_t kVersion; + static const int32_t kNumFonts; + static const int32_t kOffsetTable; + + // TTC Version 2.0 extensions + // offsets from end of OffsetTable + static const int32_t kulDsigTag; + static const int32_t kulDsigLength; + static const int32_t kulDsigOffset; + }; + + FontFactory(); + + public: // class is final, no virtual functions unless from parent + 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); + + // 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); + + private: + Font* loadSingleOTF(InputStream* is); + void loadCollection(InputStream* is, FontArray* output); + Font::Builder* loadSingleOTFForBuilding(InputStream* is); + void loadCollectionForBuilding(InputStream* is, FontBuilderArray* builders); + static bool isCollection(PushbackInputStream* pbis); + + public: + // 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(ByteArray* ba, FontArray* 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(ByteArray* ba, FontBuilderArray* output); + + private: + CALLER_ATTACH Font* loadSingleOTF(ByteArray* ba); + void loadCollection(ByteArray* ba, FontArray* output); + CALLER_ATTACH Font::Builder* + loadSingleOTFForBuilding(ByteArray* ba, int32_t offset_to_offset_table); + void loadCollectionForBuilding(ByteArray* ba, FontBuilderArray* builders); + static bool isCollection(ByteArray* ba); + + public: + CALLER_ATTACH WritableFontData* getNewData(int32_t capacity); + CALLER_ATTACH WritableFontData* getNewFixedData(int32_t capacity); + CALLER_ATTACH WritableFontData* getNewGrowableData(int32_t capacity); + CALLER_ATTACH WritableFontData* + getNewGrowableData(ReadableFontData* src_data); + CALLER_ATTACH ByteArray* getNewArray(int32_t length); + CALLER_ATTACH ByteArray* getNewGrowableArray(int32_t length); + + public: + // 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: + bool fingerprint_; + IntegerList table_ordering_; +}; +typedef Ptr FontFactoryPtr; + +} // namespace sfntly + +#endif // TYPOGRAPHY_FONT_SFNTLY_SRC_SFNTLY_FONT_FACTORY_H_ diff --git a/sfntly/font_header_table.cc b/sfntly/font_header_table.cc new file mode 100644 index 0000000..5d23d39 --- /dev/null +++ b/sfntly/font_header_table.cc @@ -0,0 +1,289 @@ +/* + * 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_header_table.h" + +namespace sfntly { +/****************************************************************************** + * Constants + ******************************************************************************/ +const int32_t FontHeaderTable::Offset::kTableVersion = 0; +const int32_t FontHeaderTable::Offset::kFontRevision = 4; +const int32_t FontHeaderTable::Offset::kCheckSumAdjustment = 8; +const int32_t FontHeaderTable::Offset::kMagicNumber = 12; +const int32_t FontHeaderTable::Offset::kFlags = 16; +const int32_t FontHeaderTable::Offset::kUnitsPerEm = 18; +const int32_t FontHeaderTable::Offset::kCreated = 20; +const int32_t FontHeaderTable::Offset::kModified = 28; +const int32_t FontHeaderTable::Offset::kXMin = 36; +const int32_t FontHeaderTable::Offset::kYMin = 38; +const int32_t FontHeaderTable::Offset::kXMax = 40; +const int32_t FontHeaderTable::Offset::kYMax = 42; +const int32_t FontHeaderTable::Offset::kMacStyle = 44; +const int32_t FontHeaderTable::Offset::kLowestRecPPEM = 46; +const int32_t FontHeaderTable::Offset::kFontDirectionHint = 48; +const int32_t FontHeaderTable::Offset::kIndexToLocFormat = 50; +const int32_t FontHeaderTable::Offset::kGlyphDataFormat = 52; + +const int32_t IndexToLocFormat::kShortOffset = 0; +const int32_t IndexToLocFormat::kLongOffset = 1; + +const int32_t FontDirectionHint::kFullyMixed = 0; +const int32_t FontDirectionHint::kOnlyStrongLTR = 1; +const int32_t FontDirectionHint::kStrongLTRAndNeutral = 2; +const int32_t FontDirectionHint::kOnlyStrongRTL = -1; +const int32_t FontDirectionHint::kStrongRTLAndNeutral = -2; + +/****************************************************************************** + * FontHeaderTable class + ******************************************************************************/ +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::~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::Builder class + ******************************************************************************/ +FontHeaderTable::Builder::Builder(FontDataTableBuilderContainer* font_builder, + Header* header, WritableFontData* data) : + Table::TableBasedTableBuilder(font_builder, header, data) { +} + +FontHeaderTable::Builder::Builder(FontDataTableBuilderContainer* font_builder, + Header* header, ReadableFontData* data) : + Table::TableBasedTableBuilder(font_builder, 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(table())->tableVersion(); +} + +void FontHeaderTable::Builder::setTableVersion(int32_t version) { + internalWriteData()->writeFixed(Offset::kTableVersion, version); +} + +int32_t FontHeaderTable::Builder::fontRevision() { + return down_cast(table())->fontRevision(); +} + +void FontHeaderTable::Builder::setFontRevision(int32_t revision) { + internalWriteData()->writeFixed(Offset::kFontRevision, revision); +} + +int64_t FontHeaderTable::Builder::checksumAdjustment() { + return down_cast(table())->checksumAdjustment(); +} + +void FontHeaderTable::Builder::setChecksumAdjustment(int64_t adjustment) { + internalWriteData()->writeULong(Offset::kCheckSumAdjustment, adjustment); +} + +int64_t FontHeaderTable::Builder::magicNumber() { + return down_cast(table())->magicNumber(); +} + +void FontHeaderTable::Builder::setMagicNumber(int64_t magic_number) { + internalWriteData()->writeULong(Offset::kMagicNumber, magic_number); +} + +int32_t FontHeaderTable::Builder::flagsAsInt() { + return down_cast(table())->flagsAsInt(); +} + +void FontHeaderTable::Builder::setFlagsAsInt(int32_t flags) { + internalWriteData()->writeUShort(Offset::kFlags, flags); +} + +int32_t FontHeaderTable::Builder::unitsPerEm() { + return down_cast(table())->unitsPerEm(); +} + +void FontHeaderTable::Builder::setUnitsPerEm(int32_t units) { + internalWriteData()->writeUShort(Offset::kUnitsPerEm, units); +} + +int64_t FontHeaderTable::Builder::created() { + return down_cast(table())->modified(); +} + +void FontHeaderTable::Builder::setCreated(int64_t date) { + internalWriteData()->writeDateTime(Offset::kCreated, date); +} + +int64_t FontHeaderTable::Builder::modified() { + return down_cast(table())->modified(); +} + +void FontHeaderTable::Builder::setModified(int64_t date) { + internalWriteData()->writeDateTime(Offset::kModified, date); +} + +int32_t FontHeaderTable::Builder::xMin() { + return down_cast(table())->xMin(); +} + +void FontHeaderTable::Builder::setXMin(int32_t xmin) { + internalWriteData()->writeShort(Offset::kXMin, xmin); +} + +int32_t FontHeaderTable::Builder::yMin() { + return down_cast(table())->yMin(); +} + +void FontHeaderTable::Builder::setYMin(int32_t ymin) { + internalWriteData()->writeShort(Offset::kYMin, ymin); +} + +int32_t FontHeaderTable::Builder::xMax() { + return down_cast(table())->xMax(); +} + +void FontHeaderTable::Builder::setXMax(int32_t xmax) { + internalWriteData()->writeShort(Offset::kXMax, xmax); +} + +int32_t FontHeaderTable::Builder::yMax() { + return down_cast(table())->yMax(); +} + +void FontHeaderTable::Builder::setYMax(int32_t ymax) { + internalWriteData()->writeShort(Offset::kYMax, ymax); +} + +int32_t FontHeaderTable::Builder::macStyleAsInt() { + return down_cast(table())->macStyleAsInt(); +} + +void FontHeaderTable::Builder::setMacStyleAsInt(int32_t style) { + internalWriteData()->writeUShort(Offset::kMacStyle, style); +} + +int32_t FontHeaderTable::Builder::lowestRecPPEM() { + return down_cast(table())->lowestRecPPEM(); +} + +void FontHeaderTable::Builder::setLowestRecPPEM(int32_t size) { + internalWriteData()->writeUShort(Offset::kLowestRecPPEM, size); +} + +int32_t FontHeaderTable::Builder::fontDirectionHint() { + return down_cast(table())->fontDirectionHint(); +} + +void FontHeaderTable::Builder::setFontDirectionHint(int32_t hint) { + internalWriteData()->writeShort(Offset::kFontDirectionHint, hint); +} + +int32_t FontHeaderTable::Builder::indexToLocFormat() { + return down_cast(table())->indexToLocFormat(); +} + +void FontHeaderTable::Builder::setIndexToLocFormat(int32_t format) { + internalWriteData()->writeShort(Offset::kIndexToLocFormat, format); +} + +int32_t FontHeaderTable::Builder::glyphDataFormat() { + return down_cast(table())->glyphDataFormat(); +} + +void FontHeaderTable::Builder::setGlyphDataFormat(int32_t format) { + internalWriteData()->writeShort(Offset::kGlyphDataFormat, format); +} + +} // namespace sfntly diff --git a/sfntly/font_header_table.h b/sfntly/font_header_table.h new file mode 100644 index 0000000..cac33c8 --- /dev/null +++ b/sfntly/font_header_table.h @@ -0,0 +1,163 @@ +/* + * 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_FONT_HEADER_TABLE_H_ +#define TYPOGRAPHY_FONT_SFNTLY_SRC_SFNTLY_FONT_HEADER_TABLE_H_ + +#include "sfntly/table.h" + +namespace sfntly { + +struct IndexToLocFormat { + static const int32_t kShortOffset; + static const int32_t kLongOffset; +}; + +struct FontDirectionHint { + static const int32_t kFullyMixed; + static const int32_t kOnlyStrongLTR; + static const int32_t kStrongLTRAndNeutral; + static const int32_t kOnlyStrongRTL; + static const int32_t kStrongRTLAndNeutral; +}; + +class FontHeaderTable : public Table, public RefCounted { + private: + struct Offset { + static const int32_t kTableVersion; + static const int32_t kFontRevision; + static const int32_t kCheckSumAdjustment; + static const int32_t kMagicNumber; + static const int32_t kFlags; + static const int32_t kUnitsPerEm; + static const int32_t kCreated; + static const int32_t kModified; + static const int32_t kXMin; + static const int32_t kYMin; + static const int32_t kXMax; + static const int32_t kYMax; + static const int32_t kMacStyle; + static const int32_t kLowestRecPPEM; + static const int32_t kFontDirectionHint; + static const int32_t kIndexToLocFormat; + static const int32_t kGlyphDataFormat; + }; + + private: + FontHeaderTable(Header* header, ReadableFontData* data); + + public: // class is final, no virtual functions unless from parent + 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(); + + public: + class Builder : public Table::TableBasedTableBuilder, + public RefCounted { + public: + // Constructor scope altered to public because C++ does not allow base + // class to instantiate derived class with protected constructors. + Builder(FontDataTableBuilderContainer* font_builder, Header* header, + WritableFontData* data); + Builder(FontDataTableBuilderContainer* font_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); + }; +}; +typedef Ptr FontHeaderTablePtr; +typedef Ptr FontHeaderTableBuilderPtr; + +} // namespace sfntly + +#endif // TYPOGRAPHY_FONT_SFNTLY_SRC_SFNTLY_FONT_HEADER_TABLE_H_ diff --git a/sfntly/glyph_table.cc b/sfntly/glyph_table.cc new file mode 100644 index 0000000..72f6945 --- /dev/null +++ b/sfntly/glyph_table.cc @@ -0,0 +1,645 @@ +/* + * 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 "sfntly/glyph_table.h" +#include "sfntly/port/exception_type.h" + +namespace sfntly { +/****************************************************************************** + * Constants + ******************************************************************************/ +const int32_t GlyphTable::Offset::kNumberOfContours = 0; +const int32_t GlyphTable::Offset::kXMin = 2; +const int32_t GlyphTable::Offset::kYMin = 4; +const int32_t GlyphTable::Offset::kXMax = 6; +const int32_t GlyphTable::Offset::kYMax = 8; +const int32_t GlyphTable::Offset::kSimpleEndPtsOfCountours = 10; +const int32_t GlyphTable::Offset::kSimpleInstructionLength = 0; +const int32_t GlyphTable::Offset::kSimpleInstructions = 2; +const int32_t GlyphTable::Offset::kCompositeFlags = 0; +const int32_t GlyphTable::Offset::kCompositeGyphIndexWithoutFlag = 0; +const int32_t GlyphTable::Offset::kCompositeGlyphIndexWithFlag = 2; + +const int32_t GlyphType::kSimple = 0; +const int32_t GlyphType::kComposite = 1; + +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(Header* header, ReadableFontData* data) + : Table(header, data) {} + +GlyphTable::~GlyphTable() {} + +GlyphTable::Glyph* GlyphTable::glyph(int32_t offset, int32_t length) { + return GlyphTable::Glyph::getGlyph(data_, offset, length); +} + +/****************************************************************************** + * GlyphTable::Builder class + ******************************************************************************/ +GlyphTable::Builder::Builder(FontDataTableBuilderContainer* font_builder, + Header* header, WritableFontData* data) : + Table::ArrayElementTableBuilder(font_builder, header, data) {} + +GlyphTable::Builder::~Builder() {} + +void GlyphTable::Builder::setLoca(const IntegerList& loca) { + loca_ = loca; + setModelChanged(false); + glyph_builders_.clear(); +} + +void GlyphTable::Builder::generateLocaList(IntegerList* locas) { + assert(locas); + GlyphBuilderList* glyph_builders = getGlyphBuilders(); + locas->resize(glyph_builders->size()); + 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; + } + } +} + +void GlyphTable::Builder::initialize(ReadableFontData* data, + const IntegerList& loca) { + if (data != NULL) { + if (loca_.empty()) { + throw IllegalStateException( + "Loca values not set - unable to parse glyph data."); + } + 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()) { + initialize(internalReadData(), loca_); + setModelChanged(); + } + return &glyph_builders_; +} + +void GlyphTable::Builder::revert() { + glyph_builders_.clear(); + setModelChanged(false); +} + +GlyphTable::GlyphBuilderList* GlyphTable::Builder::glyphBuilders() { + return getGlyphBuilders(); +} + +void GlyphTable::Builder::setGlyphBuilders(GlyphBuilderList* glyph_builders) { + glyph_builders_ = *glyph_builders; + setModelChanged(); +} + +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(); + setModelChanged(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; +} + +/****************************************************************************** + * GlyphTable::Glyph class + ******************************************************************************/ +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); + } +} + +GlyphTable::Glyph::~Glyph() {} + +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; +} + +CALLER_ATTACH GlyphTable::Glyph* GlyphTable::Glyph::getGlyph( + ReadableFontData* data, int32_t offset, int32_t length) { + 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); + } + glyph = new CompositeGlyph(sliced_data); + return glyph.detach(); +} + +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); +} + +int32_t GlyphTable::Glyph::padding() { + return padding_; +} + +/****************************************************************************** + * GlyphTable::Glyph::Builder class + ******************************************************************************/ +GlyphTable::Glyph::Builder::Builder(FontDataTableBuilderContainer* font_builder, + WritableFontData* data) : + SubTable::Builder(font_builder, data) { +} + +GlyphTable::Glyph::Builder::Builder(FontDataTableBuilderContainer* font_builder, + ReadableFontData* data) : + SubTable::Builder(font_builder, data) { +} + +GlyphTable::Glyph::Builder::~Builder() {} + +CALLER_ATTACH GlyphTable::Glyph::Builder* + GlyphTable::Glyph::Builder::getBuilder( + FontDataTableBuilderContainer* table_builder, ReadableFontData* data) { + return getBuilder(table_builder, data, 0, data->length()); +} + +CALLER_ATTACH GlyphTable::Glyph::Builder* + GlyphTable::Glyph::Builder::getBuilder( + FontDataTableBuilderContainer* table_builder, ReadableFontData* data, + int32_t offset, int32_t length) { + 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(table_builder, sliced_data); + } else { + builder = new CompositeGlyph::CompositeGlyphBuilder(table_builder, + 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 and its builder + ******************************************************************************/ +GlyphTable::SimpleGlyph::SimpleGlyph(ReadableFontData* data) + : GlyphTable::Glyph(data, GlyphType::kSimple) { +} + +GlyphTable::SimpleGlyph::~SimpleGlyph() {} + +void GlyphTable::SimpleGlyph::initialize() { + 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); + padding_ = length() - 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); +} + +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]; +} + +GlyphTable::SimpleGlyph::SimpleGlyphBuilder::SimpleGlyphBuilder( + FontDataTableBuilderContainer* table_builder, WritableFontData* data) : + Glyph::Builder(table_builder, data) { +} + +GlyphTable::SimpleGlyph::SimpleGlyphBuilder::SimpleGlyphBuilder( + FontDataTableBuilderContainer* table_builder, ReadableFontData* data) : + Glyph::Builder(table_builder, data) { +} + +GlyphTable::SimpleGlyph::SimpleGlyphBuilder::~SimpleGlyphBuilder() {} + +CALLER_ATTACH FontDataTable* + GlyphTable::SimpleGlyph::SimpleGlyphBuilder::subBuildTable( + ReadableFontData* data) { + FontDataTablePtr table = new SimpleGlyph(data); + return table.detach(); +} + +/****************************************************************************** + * GlyphTable::CompositeGlyph and its builder + ******************************************************************************/ +GlyphTable::CompositeGlyph::CompositeGlyph(ReadableFontData* data) + : instruction_size_(0), instructions_offset_(0), + GlyphTable::Glyph(data, GlyphType::kComposite) { + parseData(); +} + +GlyphTable::CompositeGlyph::~CompositeGlyph() {} + +void GlyphTable::CompositeGlyph::parseData() { + 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); + } + padding_ = length() - non_padded_data_length; + } +} + +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, tsize); +} + +int32_t GlyphTable::CompositeGlyph::instructionSize() { + return instruction_size_; +} + +CALLER_ATTACH ReadableFontData* GlyphTable::CompositeGlyph::instructions() { + return down_cast( + data_->slice(instructions_offset_, instructionSize())); +} + +GlyphTable::CompositeGlyph::CompositeGlyphBuilder::CompositeGlyphBuilder( + FontDataTableBuilderContainer* table_builder, WritableFontData* data) : + Glyph::Builder(table_builder, data) { +} + +GlyphTable::CompositeGlyph::CompositeGlyphBuilder::CompositeGlyphBuilder( + FontDataTableBuilderContainer* table_builder, ReadableFontData* data) : + Glyph::Builder(table_builder, data) { +} + +GlyphTable::CompositeGlyph::CompositeGlyphBuilder::~CompositeGlyphBuilder() {} + +CALLER_ATTACH FontDataTable* + GlyphTable::CompositeGlyph::CompositeGlyphBuilder::subBuildTable( + ReadableFontData* data) { + FontDataTablePtr table = new CompositeGlyph(data); + return table.detach(); +} + +} // namespace sfntly diff --git a/sfntly/glyph_table.h b/sfntly/glyph_table.h new file mode 100644 index 0000000..6f04d45 --- /dev/null +++ b/sfntly/glyph_table.h @@ -0,0 +1,331 @@ +/* + * 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_GLYPH_TABLE_H_ +#define TYPOGRAPHY_FONT_SFNTLY_SRC_SFNTLY_GLYPH_TABLE_H_ + +#include + +#include "sfntly/table.h" +#include "sfntly/subtable.h" + +namespace sfntly { + +struct GlyphType { + static const int32_t kSimple; + static const int32_t kComposite; +}; + +// Note: due to the complexity of this class, the order of declaration is +// different from its Java counter part. GlyphTable::Glyph is defined +// before GlyphTable::Builder to avoid compilation errors. +class GlyphTable : public Table, public RefCounted { + public: + struct Offset { + // header + static const int32_t kNumberOfContours; + static const int32_t kXMin; + static const int32_t kYMin; + static const int32_t kXMax; + static const int32_t kYMax; + + // Simple Glyph Description + static const int32_t kSimpleEndPtsOfCountours; + // offset from the end of the contours array + static const int32_t kSimpleInstructionLength; + static const int32_t kSimpleInstructions; + // flags + // xCoordinates + // yCoordinates + + // Composite Glyph Description + static const int32_t kCompositeFlags; + static const int32_t kCompositeGyphIndexWithoutFlag; + static const int32_t kCompositeGlyphIndexWithFlag; + }; + + private: + GlyphTable(Header* header, ReadableFontData* data); + + public: + virtual ~GlyphTable(); + + class Glyph; + Glyph* glyph(int32_t offset, int32_t length); + + class Builder; + class Glyph : public SubTable { + 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); + + private: + static int32_t glyphType(ReadableFontData* data, int32_t offset, + int32_t length); + + public: + virtual ~Glyph(); + static CALLER_ATTACH Glyph* getGlyph(ReadableFontData* data, int32_t offset, + int32_t length); + 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 padding(); // override FontDataTable::padding() + + virtual int32_t instructionSize() = 0; + virtual ReadableFontData* instructions() = 0; + + // Note: Contour is an empty class for the version ported + class Contour { + protected: + Contour() {} + virtual ~Contour() {} + }; + + class Builder : public SubTable::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. + Builder(FontDataTableBuilderContainer* table_builder, + WritableFontData* data); + Builder(FontDataTableBuilderContainer* table_builder, + ReadableFontData* data); + + public: + virtual ~Builder(); + + protected: + static CALLER_ATTACH Builder* getBuilder( + FontDataTableBuilderContainer* table_builder, ReadableFontData* data); + static CALLER_ATTACH Builder* getBuilder( + FontDataTableBuilderContainer* 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); + + protected: + int32_t format_; + friend class GlyphTable::Builder; + }; + + private: + int32_t glyph_type_; + int32_t number_of_contours_; + + protected: + int32_t padding_; + }; + + typedef Ptr GlyphBuilderPtr; + typedef std::vector GlyphBuilderList; + + class Builder : public Table::ArrayElementTableBuilder, + public RefCounted { + public: + // Note: Constructor scope altered to public for base class to instantiate. + Builder(FontDataTableBuilderContainer* font_builder, Header* header, + WritableFontData* data); + virtual ~Builder(); + + virtual void setLoca(const IntegerList& loca); + virtual void generateLocaList(IntegerList* locas); + + private: + void initialize(ReadableFontData* data, const IntegerList& loca); + GlyphBuilderList* getGlyphBuilders(); + void revert(); + + public: + // 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. + 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: + 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; + + public: + // Note: constructor refactored in C++ to avoid heavy lifting. + // caller need to do data->slice(offset, length) beforehand. + explicit SimpleGlyph(ReadableFontData* data); + virtual ~SimpleGlyph(); + + public: + class SimpleContour : public Glyph::Contour { + protected: + SimpleContour() {} + virtual ~SimpleContour() {} + }; + + private: + void initialize(); + void parseData(bool fill_arrays); + int32_t flagAsInt(int32_t index); + int32_t contourEndPoint(int32_t contour); + + public: // class is final, , no virtual functions unless from parent + virtual int32_t instructionSize(); + virtual CALLER_ATTACH ReadableFontData* instructions(); + 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); + + public: + 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. + SimpleGlyphBuilder(FontDataTableBuilderContainer* table_builder, + WritableFontData* data); + SimpleGlyphBuilder(FontDataTableBuilderContainer* table_builder, + ReadableFontData* data); + virtual CALLER_ATTACH FontDataTable* + subBuildTable(ReadableFontData* data); + friend class Glyph::Builder; + }; + + private: + bool initialized_; + 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; + + public: + // Note: constructor refactored in C++ to avoid heavy lifting. + // caller need to do data->slice(offset, length) beforehand. + explicit CompositeGlyph(ReadableFontData* data); + virtual ~CompositeGlyph(); + + private: + void parseData(); + + public: // class is final, no virtual functions unless from parent + 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(); + + public: + 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. + CompositeGlyphBuilder(FontDataTableBuilderContainer* table_builder, + WritableFontData* data); + CompositeGlyphBuilder(FontDataTableBuilderContainer* table_builder, + ReadableFontData* data); + + virtual CALLER_ATTACH FontDataTable* + subBuildTable(ReadableFontData* data); + friend class Glyph::Builder; + }; + + private: + IntegerList contour_index_; + int32_t instruction_size_; + int32_t instructions_offset_; + }; +}; +typedef Ptr GlyphTablePtr; +typedef Ptr GlyphTableBuilderPtr; +typedef std::vector GlyphTableBuilderList; +typedef Ptr GlyphPtr; +typedef Ptr GlyphBuilderPtr; + +} // namespace sfntly + +#endif // TYPOGRAPHY_FONT_SFNTLY_SRC_SFNTLY_GLYPH_TABLE_H_ diff --git a/sfntly/horizontal_header_table.cc b/sfntly/horizontal_header_table.cc new file mode 100644 index 0000000..68afeea --- /dev/null +++ b/sfntly/horizontal_header_table.cc @@ -0,0 +1,229 @@ +/* + * 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. + */ + +// Note: original Java version is inconsistent itself (e.g. readUShort in +// Builder but readShort in Table. Need Fix. +// TODO(arthurhsu): check with Stuart G and fix it. + +#include "sfntly/horizontal_header_table.h" + +namespace sfntly { +/****************************************************************************** + * HorizontalHeaderTable::Builder class + ******************************************************************************/ +const int32_t HorizontalHeaderTable::Offset::kVersion = 0; +const int32_t HorizontalHeaderTable::Offset::kAscender = 4; +const int32_t HorizontalHeaderTable::Offset::kDescender = 6; +const int32_t HorizontalHeaderTable::Offset::kLineGap = 8; +const int32_t HorizontalHeaderTable::Offset::kAdvanceWidthMax = 10; +const int32_t HorizontalHeaderTable::Offset::kMinLeftSideBearing = 12; +const int32_t HorizontalHeaderTable::Offset::kMinRightSideBearing = 14; +const int32_t HorizontalHeaderTable::Offset::kXMaxExtent = 16; +const int32_t HorizontalHeaderTable::Offset::kCaretSlopeRise = 18; +const int32_t HorizontalHeaderTable::Offset::kCaretSlopeRun = 20; +const int32_t HorizontalHeaderTable::Offset::kCaretOffset = 22; +const int32_t HorizontalHeaderTable::Offset::kMetricDataFormat = 32; +const int32_t HorizontalHeaderTable::Offset::kNumberOfHMetrics = 34; + +/****************************************************************************** + * HorizontalHeaderTable class + ******************************************************************************/ +HorizontalHeaderTable:: HorizontalHeaderTable(Header* header, + ReadableFontData* data) : + Table(header, data) {} + +HorizontalHeaderTable:: ~HorizontalHeaderTable() {} + +int32_t HorizontalHeaderTable::version() { + 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::Builder class + ******************************************************************************/ +HorizontalHeaderTable::Builder::Builder( + FontDataTableBuilderContainer* font_builder, Header* header, + WritableFontData* data) : + Table::TableBasedTableBuilder(font_builder, header, data) { +} + +HorizontalHeaderTable::Builder::Builder( + FontDataTableBuilderContainer* font_builder, Header* header, + ReadableFontData* data) : + Table::TableBasedTableBuilder(font_builder, header, data) { +} + +HorizontalHeaderTable::Builder::~Builder() {} + +CALLER_ATTACH FontDataTable* HorizontalHeaderTable::Builder::subBuildTable( + ReadableFontData* data) { + FontDataTablePtr table = new HorizontalHeaderTable(header(), data); + return table.detach(); +} + +int32_t HorizontalHeaderTable::Builder::version() { + return internalReadData()->readFixed(Offset::kVersion); +} + +void HorizontalHeaderTable::Builder::setVersion(int32_t version) { + internalWriteData()->writeFixed(Offset::kVersion, version); +} + +int32_t HorizontalHeaderTable::Builder::ascender() { + return internalReadData()->readUShort(Offset::kAscender); +} + +void HorizontalHeaderTable::Builder::setAscender(int32_t ascender) { + internalWriteData()->writeUShort(Offset::kVersion, ascender); +} + +int32_t HorizontalHeaderTable::Builder::descender() { + return internalReadData()->readUShort(Offset::kDescender); +} + +void HorizontalHeaderTable::Builder::setDescender(int32_t descender) { + internalWriteData()->writeUShort(Offset::kDescender, descender); +} + +int32_t HorizontalHeaderTable::Builder::lineGap() { + return internalReadData()->readUShort(Offset::kLineGap); +} + +void HorizontalHeaderTable::Builder::setLineGap(int32_t line_gap) { + internalWriteData()->writeUShort(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()->readUShort(Offset::kMinLeftSideBearing); +} + +void HorizontalHeaderTable::Builder::setMinLeftSideBearing(int32_t value) { + internalWriteData()->writeUShort(Offset::kMinLeftSideBearing, value); +} + +int32_t HorizontalHeaderTable::Builder::minRightSideBearing() { + return internalReadData()->readUShort(Offset::kMinRightSideBearing); +} + +void HorizontalHeaderTable::Builder::setMinRightSideBearing(int32_t value) { + internalWriteData()->writeUShort(Offset::kMinRightSideBearing, value); +} + +int32_t HorizontalHeaderTable::Builder::xMaxExtent() { + return internalReadData()->readUShort(Offset::kXMaxExtent); +} + +void HorizontalHeaderTable::Builder::setXMaxExtent(int32_t value) { + internalWriteData()->writeUShort(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/sfntly/horizontal_header_table.h b/sfntly/horizontal_header_table.h new file mode 100644 index 0000000..36f4180 --- /dev/null +++ b/sfntly/horizontal_header_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 TYPOGRAPHY_FONT_SFNTLY_SRC_SFNTLY_HORIZONTAL_HEADER_TABLE_H_ +#define TYPOGRAPHY_FONT_SFNTLY_SRC_SFNTLY_HORIZONTAL_HEADER_TABLE_H_ + +#include "sfntly/table.h" + +namespace sfntly { + +class HorizontalHeaderTable : public Table, + public RefCounted { + private: + struct Offset { + static const int32_t kVersion; + static const int32_t kAscender; + static const int32_t kDescender; + static const int32_t kLineGap; + static const int32_t kAdvanceWidthMax; + static const int32_t kMinLeftSideBearing; + static const int32_t kMinRightSideBearing; + static const int32_t kXMaxExtent; + static const int32_t kCaretSlopeRise; + static const int32_t kCaretSlopeRun; + static const int32_t kCaretOffset; + static const int32_t kMetricDataFormat; + static const int32_t kNumberOfHMetrics; + }; + + private: + HorizontalHeaderTable(Header* header, ReadableFontData* data); + + public: + virtual ~HorizontalHeaderTable(); + int32_t version(); + 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(); + + public: + class Builder : public Table::TableBasedTableBuilder, + public RefCounted { + public: + // Constructor scope altered to public because C++ does not allow base + // class to instantiate derived class with protected constructors. + Builder(FontDataTableBuilderContainer* font_builder, Header* header, + WritableFontData* data); + Builder(FontDataTableBuilderContainer* font_builder, Header* header, + ReadableFontData* data); + virtual ~Builder(); + virtual CALLER_ATTACH FontDataTable* subBuildTable(ReadableFontData* data); + + int32_t version(); + void setVersion(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); + }; +}; +typedef Ptr HorizontalHeaderTablePtr; +typedef Ptr HorizontalHeaderTableBuilderPtr; + +} // namespace sfntly + +#endif // TYPOGRAPHY_FONT_SFNTLY_SRC_SFNTLY_HORIZONTAL_HEADER_TABLE_H_ diff --git a/sfntly/horizontal_metrics_table.cc b/sfntly/horizontal_metrics_table.cc new file mode 100644 index 0000000..4ed2d43 --- /dev/null +++ b/sfntly/horizontal_metrics_table.cc @@ -0,0 +1,137 @@ +/* + * 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/horizontal_metrics_table.h" +#include "sfntly/port/exception_type.h" + +namespace sfntly { +/****************************************************************************** + * Constants + ******************************************************************************/ +const int32_t HorizontalMetricsTable::Offset::kHMetricsStart = 0; +const int32_t HorizontalMetricsTable::Offset::kHMetricsSize = 4; +const int32_t HorizontalMetricsTable::Offset::kHMetricsAdvanceWidth = 0; +const int32_t HorizontalMetricsTable::Offset::kHMetricsLeftSideBearing = 2; +const int32_t HorizontalMetricsTable::Offset::kLeftSideBearingSize = 2; + +/****************************************************************************** + * HorizontalMetricsTable class + ******************************************************************************/ +HorizontalMetricsTable::HorizontalMetricsTable(Header* header, + ReadableFontData* data) : + Table(header, data) { +} + +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::~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_) { + throw IndexOutOfBoundException(); + } + 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_) { + throw IndexOutOfBoundException(); + } + 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_) { + throw IndexOutOfBoundException(); + } + 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_); +} + +/****************************************************************************** + * HorizontalMetricsTable::Builder class + ******************************************************************************/ +void HorizontalMetricsTable::Builder::init() { + num_hmetrics_ = -1; + num_glyphs_ = -1; +} + +HorizontalMetricsTable::Builder::Builder( + FontDataTableBuilderContainer* font_builder, Header* header, + WritableFontData* data) : + Table::TableBasedTableBuilder(font_builder, header, data) { + init(); +} + +HorizontalMetricsTable::Builder::Builder( + FontDataTableBuilderContainer* font_builder, Header* header, + ReadableFontData* data) : + Table::TableBasedTableBuilder(font_builder, header, data) { + init(); +} + +HorizontalMetricsTable::Builder::~Builder() {} + +CALLER_ATTACH FontDataTable* HorizontalMetricsTable::Builder::subBuildTable( + ReadableFontData* data) { + FontDataTablePtr table = + new HorizontalMetricsTable(header(), data, num_hmetrics_, num_glyphs_); + return table.detach(); +} + +void HorizontalMetricsTable::Builder::setNumberOfHMetrics( + int32_t num_hmetrics) { + assert(num_hmetrics >= 0); + num_hmetrics_ = num_hmetrics; + HorizontalMetricsTable* table = down_cast( + this->table()); + 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->table()); + table->num_glyphs_ = num_glyphs; +} + +} // namespace sfntly diff --git a/sfntly/horizontal_metrics_table.h b/sfntly/horizontal_metrics_table.h new file mode 100644 index 0000000..0f1d651 --- /dev/null +++ b/sfntly/horizontal_metrics_table.h @@ -0,0 +1,84 @@ +/* + * 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_HORIZONTAL_METRICS_TABLE_H_ +#define TYPOGRAPHY_FONT_SFNTLY_SRC_SFNTLY_HORIZONTAL_METRICS_TABLE_H_ + +#include "sfntly/table.h" + +namespace sfntly { + +class HorizontalMetricsTable : public Table, + public RefCounted { + private: + struct Offset { + // hMetrics + static const int32_t kHMetricsStart; + static const int32_t kHMetricsSize; + + // Offset within an hMetric + static const int32_t kHMetricsAdvanceWidth; + static const int32_t kHMetricsLeftSideBearing; + + static const int32_t kLeftSideBearingSize; + }; + + private: + HorizontalMetricsTable(Header* header, ReadableFontData* data); + HorizontalMetricsTable(Header* header, ReadableFontData* data, + int32_t num_hmetrics, int32_t num_glyphs); + + public: // class is final, no virtual functions unless inherited from parent. + 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); + + public: + class Builder : public Table::TableBasedTableBuilder, + public RefCounted { + public: + // Constructor scope altered to public because C++ does not allow base + // class to instantiate derived class with protected constructors. + Builder(FontDataTableBuilderContainer* font_builder, Header* header, + WritableFontData* data); + Builder(FontDataTableBuilderContainer* font_builder, Header* header, + ReadableFontData* data); + virtual ~Builder(); + void init(); + + virtual CALLER_ATTACH FontDataTable* subBuildTable(ReadableFontData* data); + void setNumberOfHMetrics(int32_t num_hmetrics); + void setNumGlyphs(int32_t num_glyphs); + + private: + int32_t num_hmetrics_; + int32_t num_glyphs_; + }; + + private: + int32_t num_hmetrics_; + int32_t num_glyphs_; +}; +typedef Ptr HorizontalMetricsTablePtr; +typedef Ptr HorizontalMetricsTableBuilderPtr; + +} // namespace sfntly + +#endif // TYPOGRAPHY_FONT_SFNTLY_SRC_SFNTLY_HORIZONTAL_METRICS_TABLE_H_ diff --git a/sfntly/loca_table.cc b/sfntly/loca_table.cc new file mode 100644 index 0000000..5bb5dd4 --- /dev/null +++ b/sfntly/loca_table.cc @@ -0,0 +1,221 @@ +/* + * 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/loca_table.h" +#include "sfntly/port/exception_type.h" + +namespace sfntly { +/****************************************************************************** + * LocaTable class + ******************************************************************************/ +LocaTable::LocaTable(Header* header, ReadableFontData* data) + : Table(header, data) {} + +LocaTable::LocaTable(Header* header, ReadableFontData* data, int32_t version, + int32_t num_glyphs) + : Table(header, data), version_(version), num_glyphs_(num_glyphs) {} + +LocaTable::~LocaTable() {} + +int32_t LocaTable::numGlyphs() { + return num_glyphs_; +} + +int32_t LocaTable::glyphOffset(int32_t glyph_id) { + if (glyph_id < 0 || glyph_id >= num_glyphs_) { + throw IndexOutOfBoundException("Glyph ID is out of bounds."); + } + return loca(glyph_id); +} + +int32_t LocaTable::glyphLength(int32_t glyph_id) { + if (glyph_id < 0 || glyph_id >= num_glyphs_) { + throw IndexOutOfBoundException("Glyph ID is out of bounds."); + } + 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_) { + throw IndexOutOfBoundException(); + } + if (version_ == IndexToLocFormat::kShortOffset) { + return 2 * data_->readShort(index * DataSize::kUSHORT); + } + return data_->readULongAsInt(index * DataSize::kULONG); +} + +/****************************************************************************** + * LocaTable::Builder class + ******************************************************************************/ +LocaTable::LocaIterator::LocaIterator(LocaTable* table) : index_(-1) { + table_ = table; +} + +bool LocaTable::LocaIterator::hasNext() { + return index_ <= table_->num_glyphs_; +} + +int32_t LocaTable::LocaIterator::next() { + return table_->loca(index_++); +} + +/****************************************************************************** + * LocaTable::Builder class + ******************************************************************************/ +void LocaTable::Builder::init() { + num_glyphs_ = -1; + format_version_ = IndexToLocFormat::kLongOffset; +} + +LocaTable::Builder::Builder(FontDataTableBuilderContainer* font_builder, + Header* header, WritableFontData* data) : + Table::ArrayElementTableBuilder(font_builder, header, data) { + init(); +} + +LocaTable::Builder::Builder(FontDataTableBuilderContainer* font_builder, + Header* header, ReadableFontData* data) : + Table::ArrayElementTableBuilder(font_builder, header, data) { + init(); +} + +LocaTable::Builder::~Builder() {} + +void LocaTable::Builder::initialize(ReadableFontData* data) { + if (data) { + if (numGlyphs() < 0) { + throw IllegalStateException("numglyphs not set on LocaTable Builder."); + } + LocaTablePtr table = + new LocaTable(header(), data, format_version_, num_glyphs_); + LocaTable::LocaIterator loca_iter(table); + while (loca_iter.hasNext()) { + loca_.push_back(loca_iter.next()); + } + } +} + +IntegerList* LocaTable::Builder::getLocaList() { + if (loca_.empty()) { + initialize(internalReadData()); + setModelChanged(); + } + return &loca_; +} + +void LocaTable::Builder::setFormatVersion(int32_t format_version) { + format_version_ = format_version; +} + +IntegerList* LocaTable::Builder::locaList() { + return getLocaList(); +} + +void LocaTable::Builder::setLocaList(IntegerList* list) { + loca_.clear(); + if (list) { + loca_ = *list; + num_glyphs_ = loca_.size(); + setModelChanged(); + } +} + +int32_t LocaTable::Builder::glyphOffset(int32_t glyph_id) { + if (glyph_id < 0 || glyph_id > (num_glyphs_ + 1)) { + throw IndexOutOfBoundException("Glyph ID is out of bounds."); + } + return loca(glyph_id); +} + +int32_t LocaTable::Builder::glyphLength(int32_t glyph_id) { + if (glyph_id < 0 || glyph_id > (num_glyphs_ + 1)) { + throw IndexOutOfBoundException("Glyph ID is out of bounds."); + } + return loca(glyph_id + 1) - loca(glyph_id); +} + +void LocaTable::Builder::setNumGlyphs(int32_t num_glyphs) { + num_glyphs_ = num_glyphs; +} + +int32_t LocaTable::Builder::numGlyphs() { + if (!loca_.empty()) { + return loca_.size() - 1; + } + return num_glyphs_; +} + +void LocaTable::Builder::revert() { + loca_.clear(); + setModelChanged(false); +} + +void LocaTable::Builder::clear() { + getLocaList()->clear(); +} + +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); + } + } + return 0; +} + +} // namespace sfntly diff --git a/sfntly/loca_table.h b/sfntly/loca_table.h new file mode 100644 index 0000000..741cb56 --- /dev/null +++ b/sfntly/loca_table.h @@ -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. + */ + +#ifndef TYPOGRAPHY_FONT_SFNTLY_SRC_SFNTLY_LOCA_TABLE_H_ +#define TYPOGRAPHY_FONT_SFNTLY_SRC_SFNTLY_LOCA_TABLE_H_ + +#include "sfntly/table.h" +#include "sfntly/font_header_table.h" + +namespace sfntly { + +class LocaTable : public Table, public RefCounted { + private: + LocaTable(Header* header, ReadableFontData* data); + LocaTable(Header* header, ReadableFontData* data, int32_t version, + int32_t num_glyphs); + + public: // class is final, no virtual unless inherited from parents. + virtual ~LocaTable(); + int32_t numGlyphs(); + + // 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); + + public: + // Note: different implementation than Java, caller to instantiate this class + // object directly from stack instead of calling LocaTable::iterator(). + class LocaIterator { + public: + explicit LocaIterator(LocaTable* table); + bool hasNext(); + int32_t next(); + + private: + int32_t index_; + LocaTable* table_; // use dumb pointer since it's a composition object + }; + friend class LocaIterator; + + class Builder : public Table::ArrayElementTableBuilder, + public RefCounted { + public: + // Constructor scope altered to public for base class to instantiate. + Builder(FontDataTableBuilderContainer* font_builder, Header* header, + WritableFontData* data); + Builder(FontDataTableBuilderContainer* font_builder, Header* header, + ReadableFontData* data); + virtual ~Builder(); + + private: + void init(); // short hand for common code in ctors, C++ port only + void initialize(ReadableFontData* data); // ported from Java + IntegerList* getLocaList(); + + public: // static class, no virtual function unless inherited from parent. + void setFormatVersion(int32_t format_version); + + // 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. + // 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(); + 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. + void setNumGlyphs(int32_t num_glyphs); + int numGlyphs(); + + void revert(); + void clear(); + + // 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(); + 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: + int32_t format_version_; // Note: IndexToLocFormat + int32_t num_glyphs_; + IntegerList loca_; + }; + + private: + int32_t version_; // Note: IndexToLocFormat + int32_t num_glyphs_; +}; +typedef Ptr LocaTablePtr; +typedef Ptr LocaTableBuilderPtr; + +} // namespace sfntly + +#endif // TYPOGRAPHY_FONT_SFNTLY_SRC_SFNTLY_LOCA_TABLE_H_ diff --git a/sfntly/math/fixed1616.h b/sfntly/math/fixed1616.h new file mode 100644 index 0000000..aa3a62b --- /dev/null +++ b/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 TYPOGRAPHY_FONT_SFNTLY_SRC_SFNTLY_MATH_FIXED1616_H_ +#define TYPOGRAPHY_FONT_SFNTLY_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 // TYPOGRAPHY_FONT_SFNTLY_SRC_SFNTLY_MATH_FIXED1616_H_ diff --git a/sfntly/math/font_math.h b/sfntly/math/font_math.h new file mode 100644 index 0000000..78b9e51 --- /dev/null +++ b/sfntly/math/font_math.h @@ -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. + */ + +#ifndef TYPOGRAPHY_FONT_SFNTLY_SRC_SFNTLY_MATH_FONT_MATH_H_ +#define TYPOGRAPHY_FONT_SFNTLY_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; + } +}; + +} // namespace sfntly + +#endif // TYPOGRAPHY_FONT_SFNTLY_SRC_SFNTLY_MATH_FONT_MATH_H_ diff --git a/sfntly/maximum_profile_table.cc b/sfntly/maximum_profile_table.cc new file mode 100644 index 0000000..a79d1e4 --- /dev/null +++ b/sfntly/maximum_profile_table.cc @@ -0,0 +1,241 @@ +/* + * 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/maximum_profile_table.h" + +namespace sfntly { +/****************************************************************************** + * Constants + ******************************************************************************/ +const int32_t MaximumProfileTable::Offset::kVersion = 0; +const int32_t MaximumProfileTable::Offset::kNumGlyphs = 4; +const int32_t MaximumProfileTable::Offset::kMaxPoints = 6; +const int32_t MaximumProfileTable::Offset::kMaxContours = 8; +const int32_t MaximumProfileTable::Offset::kMaxCompositePoints = 10; +const int32_t MaximumProfileTable::Offset::kMaxCompositeContours = 12; +const int32_t MaximumProfileTable::Offset::kMaxZones = 14; +const int32_t MaximumProfileTable::Offset::kMaxTwilightPoints = 16; +const int32_t MaximumProfileTable::Offset::kMaxStorage = 18; +const int32_t MaximumProfileTable::Offset::kMaxFunctionDefs = 20; +const int32_t MaximumProfileTable::Offset::kMaxInstructionDefs = 22; +const int32_t MaximumProfileTable::Offset::kMaxStackElements = 24; +const int32_t MaximumProfileTable::Offset::kMaxSizeOfInstructions = 26; +const int32_t MaximumProfileTable::Offset::kMaxComponentElements = 28; +const int32_t MaximumProfileTable::Offset::kMaxComponentDepth = 30; + +/****************************************************************************** + * MaximumProfileTable class + ******************************************************************************/ +MaximumProfileTable::MaximumProfileTable(Header* header, + ReadableFontData* data) : + Table(header, data) { +} + +MaximumProfileTable::~MaximumProfileTable() {} + +int32_t MaximumProfileTable::version() { + 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::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::Builder class + ******************************************************************************/ +MaximumProfileTable::Builder::Builder( + FontDataTableBuilderContainer* font_builder, Header* header, + WritableFontData* data) : + Table::TableBasedTableBuilder(font_builder, header, data) { +} + +MaximumProfileTable::Builder::Builder( + FontDataTableBuilderContainer* font_builder, Header* header, + ReadableFontData* data) : + Table::TableBasedTableBuilder(font_builder, header, data) { +} + +MaximumProfileTable::Builder::~Builder() {} + +CALLER_ATTACH FontDataTable* MaximumProfileTable::Builder::subBuildTable( + ReadableFontData* data) { + FontDataTablePtr table = new MaximumProfileTable(header(), data); + return table.detach(); +} + +int32_t MaximumProfileTable::Builder::version() { + return internalReadData()->readUShort(Offset::kVersion); +} + +void MaximumProfileTable::Builder::setVersion(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::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/sfntly/maximum_profile_table.h b/sfntly/maximum_profile_table.h new file mode 100644 index 0000000..7a0b941 --- /dev/null +++ b/sfntly/maximum_profile_table.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 TYPOGRAPHY_FONT_SFNTLY_SRC_SFNTLY_MAXIMUM_PROFILE_TABLE_H_ +#define TYPOGRAPHY_FONT_SFNTLY_SRC_SFNTLY_MAXIMUM_PROFILE_TABLE_H_ + +#include "sfntly/port/refcount.h" +#include "sfntly/table.h" + +namespace sfntly { + +class MaximumProfileTable : public Table, + public RefCounted { + private: + struct Offset { + // version 0.5 and 1.0 + static const int32_t kVersion; + static const int32_t kNumGlyphs; + + // version 1.0 + static const int32_t kMaxPoints; + static const int32_t kMaxContours; + static const int32_t kMaxCompositePoints; + static const int32_t kMaxCompositeContours; + static const int32_t kMaxZones; + static const int32_t kMaxTwilightPoints; + static const int32_t kMaxStorage; + static const int32_t kMaxFunctionDefs; + static const int32_t kMaxInstructionDefs; + static const int32_t kMaxStackElements; + static const int32_t kMaxSizeOfInstructions; + static const int32_t kMaxComponentElements; + static const int32_t kMaxComponentDepth; + }; + + private: + MaximumProfileTable(Header* header, ReadableFontData* data); + + public: // Class is final, no virtual functions unless derived from parent. + virtual ~MaximumProfileTable(); + int32_t version(); + int32_t numGlyphs(); + int32_t maxPoints(); + int32_t maxContours(); + int32_t maxCompositePoints(); + int32_t maxZones(); + int32_t maxTwilightPoints(); + int32_t maxStorage(); + int32_t maxFunctionDefs(); + int32_t maxStackElements(); + int32_t maxSizeOfInstructions(); + int32_t maxComponentElements(); + int32_t maxComponentDepth(); + + public: + class Builder : public Table::TableBasedTableBuilder, + public RefCounted { + public: + // Constructor scope altered to public because C++ does not allow base + // class to instantiate derived class with protected constructors. + Builder(FontDataTableBuilderContainer* font_builder, Header* header, + WritableFontData* data); + Builder(FontDataTableBuilderContainer* font_builder, Header* header, + ReadableFontData* data); + virtual ~Builder(); + + virtual CALLER_ATTACH FontDataTable* subBuildTable(ReadableFontData* data); + + public: // Class is static, no virtual functions unless derived from parent. + int32_t version(); + void setVersion(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 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); + }; +}; +typedef Ptr MaximumProfileTablePtr; +typedef Ptr MaximumProfileTableBuilderPtr; + +} // namespace sfntly + +#endif // TYPOGRAPHY_FONT_SFNTLY_SRC_SFNTLY_MAXIMUM_PROFILE_TABLE_H_ diff --git a/sfntly/name_table.cc b/sfntly/name_table.cc new file mode 100644 index 0000000..e303d6d --- /dev/null +++ b/sfntly/name_table.cc @@ -0,0 +1,668 @@ +/* + * 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. + */ + +// TODO(arthurhsu): IMPLEMENT: not really used and tested, need cleanup + +#include "sfntly/name_table.h" + +namespace sfntly { +/****************************************************************************** + * Constants + ******************************************************************************/ +const int32_t NameTable::Offset::kFormat = 0; +const int32_t NameTable::Offset::kCount = 2; +const int32_t NameTable::Offset::kStringOffset = 4; +const int32_t NameTable::Offset::kNameRecordStart = 6; +const int32_t NameTable::Offset::kLangTagCount = 0; +const int32_t NameTable::Offset::kLangTagRecord = 2; +const int32_t NameTable::Offset::kNameRecordSize = 12; +const int32_t NameTable::Offset::kNameRecordPlatformId = 0; +const int32_t NameTable::Offset::kNameRecordEncodingId = 2; +const int32_t NameTable::Offset::kNameRecordLanguageId = 4; +const int32_t NameTable::Offset::kNameRecordNameId = 6; +const int32_t NameTable::Offset::kNameRecordStringLength = 8; +const int32_t NameTable::Offset::kNameRecordStringOffset = 10; + +const int32_t NameTable::NameId::kUnknown = -1; +const int32_t NameTable::NameId::kCopyrightNotice = 0; +const int32_t NameTable::NameId::kFontFamilyName = 1; +const int32_t NameTable::NameId::kFontSubfamilyName = 2; +const int32_t NameTable::NameId::kUniqueFontIdentifier = 3; +const int32_t NameTable::NameId::kFullFontName = 4; +const int32_t NameTable::NameId::kVersionString = 5; +const int32_t NameTable::NameId::kPostscriptName = 6; +const int32_t NameTable::NameId::kTrademark = 7; +const int32_t NameTable::NameId::kManufacturerName = 8; +const int32_t NameTable::NameId::kDesigner = 9; +const int32_t NameTable::NameId::kDescription = 10; +const int32_t NameTable::NameId::kVendorURL = 11; +const int32_t NameTable::NameId::kDesignerURL = 12; +const int32_t NameTable::NameId::kLicenseDescription = 13; +const int32_t NameTable::NameId::kLicenseInfoURL = 14; +const int32_t NameTable::NameId::kReserved15 = 15; +const int32_t NameTable::NameId::kPreferredFamily = 16; +const int32_t NameTable::NameId::kPreferredSubfamily = 17; +const int32_t NameTable::NameId::kCompatibleFullName = 18; +const int32_t NameTable::NameId::kSampleText = 19; +const int32_t NameTable::NameId::kPostscriptCID = 20; +const int32_t NameTable::NameId::kWWSFamilyName = 21; +const int32_t NameTable::NameId::kWWSSubfamilyName = 22; + +const int32_t UnicodeLanguageId::kUnknown = -1; +const int32_t UnicodeLanguageId::kAll = 0; + +const int32_t MacintoshLanguageId::kUnknown = -1; +const int32_t MacintoshLanguageId::kEnglish = 0; +const int32_t MacintoshLanguageId::kFrench = 1; +const int32_t MacintoshLanguageId::kGerman = 2; +const int32_t MacintoshLanguageId::kItalian = 3; +const int32_t MacintoshLanguageId::kDutch = 4; +const int32_t MacintoshLanguageId::kSwedish = 5; +const int32_t MacintoshLanguageId::kSpanish = 6; +const int32_t MacintoshLanguageId::kDanish = 7; +const int32_t MacintoshLanguageId::kPortuguese = 8; +const int32_t MacintoshLanguageId::kNorwegian = 9; +const int32_t MacintoshLanguageId::kHebrew = 10; +const int32_t MacintoshLanguageId::kJapanese = 11; +const int32_t MacintoshLanguageId::kArabic = 12; +const int32_t MacintoshLanguageId::kFinnish = 13; +const int32_t MacintoshLanguageId::kGreek = 14; +const int32_t MacintoshLanguageId::kIcelandic = 15; +const int32_t MacintoshLanguageId::kMaltese = 16; +const int32_t MacintoshLanguageId::kTurkish = 17; +const int32_t MacintoshLanguageId::kCroatian = 18; +const int32_t MacintoshLanguageId::kChinese_Traditional = 19; +const int32_t MacintoshLanguageId::kUrdu = 20; +const int32_t MacintoshLanguageId::kHindi = 21; +const int32_t MacintoshLanguageId::kThai = 22; +const int32_t MacintoshLanguageId::kKorean = 23; +const int32_t MacintoshLanguageId::kLithuanian = 24; +const int32_t MacintoshLanguageId::kPolish = 25; +const int32_t MacintoshLanguageId::kHungarian = 26; +const int32_t MacintoshLanguageId::kEstonian = 27; +const int32_t MacintoshLanguageId::kLatvian = 28; +const int32_t MacintoshLanguageId::kSami = 29; +const int32_t MacintoshLanguageId::kFaroese = 30; +const int32_t MacintoshLanguageId::kFarsiPersian = 31; +const int32_t MacintoshLanguageId::kRussian = 32; +const int32_t MacintoshLanguageId::kChinese_Simplified = 33; +const int32_t MacintoshLanguageId::kFlemish = 34; +const int32_t MacintoshLanguageId::kIrishGaelic = 35; +const int32_t MacintoshLanguageId::kAlbanian = 36; +const int32_t MacintoshLanguageId::kRomanian = 37; +const int32_t MacintoshLanguageId::kCzech = 38; +const int32_t MacintoshLanguageId::kSlovak = 39; +const int32_t MacintoshLanguageId::kSlovenian = 40; +const int32_t MacintoshLanguageId::kYiddish = 41; +const int32_t MacintoshLanguageId::kSerbian = 42; +const int32_t MacintoshLanguageId::kMacedonian = 43; +const int32_t MacintoshLanguageId::kBulgarian = 44; +const int32_t MacintoshLanguageId::kUkrainian = 45; +const int32_t MacintoshLanguageId::kByelorussian = 46; +const int32_t MacintoshLanguageId::kUzbek = 47; +const int32_t MacintoshLanguageId::kKazakh = 48; +const int32_t MacintoshLanguageId::kAzerbaijani_Cyrillic = 49; +const int32_t MacintoshLanguageId::kAzerbaijani_Arabic = 50; +const int32_t MacintoshLanguageId::kArmenian = 51; +const int32_t MacintoshLanguageId::kGeorgian = 52; +const int32_t MacintoshLanguageId::kMoldavian = 53; +const int32_t MacintoshLanguageId::kKirghiz = 54; +const int32_t MacintoshLanguageId::kTajiki = 55; +const int32_t MacintoshLanguageId::kTurkmen = 56; +const int32_t MacintoshLanguageId::kMongolian_Mongolian = 57; +const int32_t MacintoshLanguageId::kMongolian_Cyrillic = 58; +const int32_t MacintoshLanguageId::kPashto = 59; +const int32_t MacintoshLanguageId::kKurdish = 60; +const int32_t MacintoshLanguageId::kKashmiri = 61; +const int32_t MacintoshLanguageId::kSindhi = 62; +const int32_t MacintoshLanguageId::kTibetan = 63; +const int32_t MacintoshLanguageId::kNepali = 64; +const int32_t MacintoshLanguageId::kSanskrit = 65; +const int32_t MacintoshLanguageId::kMarathi = 66; +const int32_t MacintoshLanguageId::kBengali = 67; +const int32_t MacintoshLanguageId::kAssamese = 68; +const int32_t MacintoshLanguageId::kGujarati = 69; +const int32_t MacintoshLanguageId::kPunjabi = 70; +const int32_t MacintoshLanguageId::kOriya = 71; +const int32_t MacintoshLanguageId::kMalayalam = 72; +const int32_t MacintoshLanguageId::kKannada = 73; +const int32_t MacintoshLanguageId::kTamil = 74; +const int32_t MacintoshLanguageId::kTelugu = 75; +const int32_t MacintoshLanguageId::kSinhalese = 76; +const int32_t MacintoshLanguageId::kBurmese = 77; +const int32_t MacintoshLanguageId::kKhmer = 78; +const int32_t MacintoshLanguageId::kLao = 79; +const int32_t MacintoshLanguageId::kVietnamese = 80; +const int32_t MacintoshLanguageId::kIndonesian = 81; +const int32_t MacintoshLanguageId::kTagalong = 82; +const int32_t MacintoshLanguageId::kMalay_Roman = 83; +const int32_t MacintoshLanguageId::kMalay_Arabic = 84; +const int32_t MacintoshLanguageId::kAmharic = 85; +const int32_t MacintoshLanguageId::kTigrinya = 86; +const int32_t MacintoshLanguageId::kGalla = 87; +const int32_t MacintoshLanguageId::kSomali = 88; +const int32_t MacintoshLanguageId::kSwahili = 89; +const int32_t MacintoshLanguageId::kKinyarwandaRuanda = 90; +const int32_t MacintoshLanguageId::kRundi = 91; +const int32_t MacintoshLanguageId::kNyanjaChewa = 92; +const int32_t MacintoshLanguageId::kMalagasy = 93; +const int32_t MacintoshLanguageId::kEsperanto = 94; +const int32_t MacintoshLanguageId::kWelsh = 128; +const int32_t MacintoshLanguageId::kBasque = 129; +const int32_t MacintoshLanguageId::kCatalan = 130; +const int32_t MacintoshLanguageId::kLatin = 131; +const int32_t MacintoshLanguageId::kQuenchua = 132; +const int32_t MacintoshLanguageId::kGuarani = 133; +const int32_t MacintoshLanguageId::kAymara = 134; +const int32_t MacintoshLanguageId::kTatar = 135; +const int32_t MacintoshLanguageId::kUighur = 136; +const int32_t MacintoshLanguageId::kDzongkha = 137; +const int32_t MacintoshLanguageId::kJavanese_Roman = 138; +const int32_t MacintoshLanguageId::kSundanese_Roman = 139; +const int32_t MacintoshLanguageId::kGalician = 140; +const int32_t MacintoshLanguageId::kAfrikaans = 141; +const int32_t MacintoshLanguageId::kBreton = 142; +const int32_t MacintoshLanguageId::kInuktitut = 143; +const int32_t MacintoshLanguageId::kScottishGaelic = 144; +const int32_t MacintoshLanguageId::kManxGaelic = 145; +const int32_t MacintoshLanguageId::kIrishGaelic_WithDotAbove = 146; +const int32_t MacintoshLanguageId::kTongan = 147; +const int32_t MacintoshLanguageId::kGreek_Polytonic = 148; +const int32_t MacintoshLanguageId::kGreenlandic = 149; +const int32_t MacintoshLanguageId::kAzerbaijani_Roman = 150; + +const int32_t WindowsLanguageId::kUnknown = -1; +const int32_t WindowsLanguageId::kAfrikaans_SouthAfrica = 0x0436; +const int32_t WindowsLanguageId::kAlbanian_Albania = 0x041C; +const int32_t WindowsLanguageId::kAlsatian_France = 0x0484; +const int32_t WindowsLanguageId::kAmharic_Ethiopia = 0x045E; +const int32_t WindowsLanguageId::kArabic_Algeria = 0x1401; +const int32_t WindowsLanguageId::kArabic_Bahrain = 0x3C01; +const int32_t WindowsLanguageId::kArabic_Egypt = 0x0C01; +const int32_t WindowsLanguageId::kArabic_Iraq = 0x0801; +const int32_t WindowsLanguageId::kArabic_Jordan = 0x2C01; +const int32_t WindowsLanguageId::kArabic_Kuwait = 0x3401; +const int32_t WindowsLanguageId::kArabic_Lebanon = 0x3001; +const int32_t WindowsLanguageId::kArabic_Libya = 0x1001; +const int32_t WindowsLanguageId::kArabic_Morocco = 0x1801; +const int32_t WindowsLanguageId::kArabic_Oman = 0x2001; +const int32_t WindowsLanguageId::kArabic_Qatar = 0x4001; +const int32_t WindowsLanguageId::kArabic_SaudiArabia = 0x0401; +const int32_t WindowsLanguageId::kArabic_Syria = 0x2801; +const int32_t WindowsLanguageId::kArabic_Tunisia = 0x1C01; +const int32_t WindowsLanguageId::kArabic_UAE = 0x3801; +const int32_t WindowsLanguageId::kArabic_Yemen = 0x2401; +const int32_t WindowsLanguageId::kArmenian_Armenia = 0x042B; +const int32_t WindowsLanguageId::kAssamese_India = 0x044D; +const int32_t WindowsLanguageId::kAzeri_Cyrillic_Azerbaijan = 0x082C; +const int32_t WindowsLanguageId::kAzeri_Latin_Azerbaijan = 0x042C; +const int32_t WindowsLanguageId::kBashkir_Russia = 0x046D; +const int32_t WindowsLanguageId::kBasque_Basque = 0x042D; +const int32_t WindowsLanguageId::kBelarusian_Belarus = 0x0423; +const int32_t WindowsLanguageId::kBengali_Bangladesh = 0x0845; +const int32_t WindowsLanguageId::kBengali_India = 0x0445; +const int32_t WindowsLanguageId::kBosnian_Cyrillic_BosniaAndHerzegovina = 0x201A; +const int32_t WindowsLanguageId::kBosnian_Latin_BosniaAndHerzegovina = 0x141A; +const int32_t WindowsLanguageId::kBreton_France = 0x047E; +const int32_t WindowsLanguageId::kBulgarian_Bulgaria = 0x0402; +const int32_t WindowsLanguageId::kCatalan_Catalan = 0x0403; +const int32_t WindowsLanguageId::kChinese_HongKongSAR = 0x0C04; +const int32_t WindowsLanguageId::kChinese_MacaoSAR = 0x1404; +const int32_t WindowsLanguageId::kChinese_PeoplesRepublicOfChina = 0x0804; +const int32_t WindowsLanguageId::kChinese_Singapore = 0x1004; +const int32_t WindowsLanguageId::kChinese_Taiwan = 0x0404; +const int32_t WindowsLanguageId::kCorsican_France = 0x0483; +const int32_t WindowsLanguageId::kCroatian_Croatia = 0x041A; +const int32_t WindowsLanguageId::kCroatian_Latin_BosniaAndHerzegovina = 0x101A; +const int32_t WindowsLanguageId::kCzech_CzechRepublic = 0x0405; +const int32_t WindowsLanguageId::kDanish_Denmark = 0x0406; +const int32_t WindowsLanguageId::kDari_Afghanistan = 0x048C; +const int32_t WindowsLanguageId::kDivehi_Maldives = 0x0465; +const int32_t WindowsLanguageId::kDutch_Belgium = 0x0813; +const int32_t WindowsLanguageId::kDutch_Netherlands = 0x0413; +const int32_t WindowsLanguageId::kEnglish_Australia = 0x0C09; +const int32_t WindowsLanguageId::kEnglish_Belize = 0x2809; +const int32_t WindowsLanguageId::kEnglish_Canada = 0x1009; +const int32_t WindowsLanguageId::kEnglish_Caribbean = 0x2409; +const int32_t WindowsLanguageId::kEnglish_India = 0x4009; +const int32_t WindowsLanguageId::kEnglish_Ireland = 0x1809; +const int32_t WindowsLanguageId::kEnglish_Jamaica = 0x2009; +const int32_t WindowsLanguageId::kEnglish_Malaysia = 0x4409; +const int32_t WindowsLanguageId::kEnglish_NewZealand = 0x1409; +const int32_t WindowsLanguageId::kEnglish_RepublicOfThePhilippines = 0x3409; +const int32_t WindowsLanguageId::kEnglish_Singapore = 0x4809; +const int32_t WindowsLanguageId::kEnglish_SouthAfrica = 0x1C09; +const int32_t WindowsLanguageId::kEnglish_TrinidadAndTobago = 0x2C09; +const int32_t WindowsLanguageId::kEnglish_UnitedKingdom = 0x0809; +const int32_t WindowsLanguageId::kEnglish_UnitedStates = 0x0409; +const int32_t WindowsLanguageId::kEnglish_Zimbabwe = 0x3009; +const int32_t WindowsLanguageId::kEstonian_Estonia = 0x0425; +const int32_t WindowsLanguageId::kFaroese_FaroeIslands = 0x0438; +const int32_t WindowsLanguageId::kFilipino_Philippines = 0x0464; +const int32_t WindowsLanguageId::kFinnish_Finland = 0x040B; +const int32_t WindowsLanguageId::kFrench_Belgium = 0x080C; +const int32_t WindowsLanguageId::kFrench_Canada = 0x0C0C; +const int32_t WindowsLanguageId::kFrench_France = 0x040C; +const int32_t WindowsLanguageId::kFrench_Luxembourg = 0x140c; +const int32_t WindowsLanguageId::kFrench_PrincipalityOfMonoco = 0x180C; +const int32_t WindowsLanguageId::kFrench_Switzerland = 0x100C; +const int32_t WindowsLanguageId::kFrisian_Netherlands = 0x0462; +const int32_t WindowsLanguageId::kGalician_Galician = 0x0456; +const int32_t WindowsLanguageId::kGeorgian_Georgia = 0x0437; +const int32_t WindowsLanguageId::kGerman_Austria = 0x0C07; +const int32_t WindowsLanguageId::kGerman_Germany = 0x0407; +const int32_t WindowsLanguageId::kGerman_Liechtenstein = 0x1407; +const int32_t WindowsLanguageId::kGerman_Luxembourg = 0x1007; +const int32_t WindowsLanguageId::kGerman_Switzerland = 0x0807; +const int32_t WindowsLanguageId::kGreek_Greece = 0x0408; +const int32_t WindowsLanguageId::kGreenlandic_Greenland = 0x046F; +const int32_t WindowsLanguageId::kGujarati_India = 0x0447; +const int32_t WindowsLanguageId::kHausa_Latin_Nigeria = 0x0468; +const int32_t WindowsLanguageId::kHebrew_Israel = 0x040D; +const int32_t WindowsLanguageId::kHindi_India = 0x0439; +const int32_t WindowsLanguageId::kHungarian_Hungary = 0x040E; +const int32_t WindowsLanguageId::kIcelandic_Iceland = 0x040F; +const int32_t WindowsLanguageId::kIgbo_Nigeria = 0x0470; +const int32_t WindowsLanguageId::kIndonesian_Indonesia = 0x0421; +const int32_t WindowsLanguageId::kInuktitut_Canada = 0x045D; +const int32_t WindowsLanguageId::kInuktitut_Latin_Canada = 0x085D; +const int32_t WindowsLanguageId::kIrish_Ireland = 0x083C; +const int32_t WindowsLanguageId::kisiXhosa_SouthAfrica = 0x0434; +const int32_t WindowsLanguageId::kisiZulu_SouthAfrica = 0x0435; +const int32_t WindowsLanguageId::kItalian_Italy = 0x0410; +const int32_t WindowsLanguageId::kItalian_Switzerland = 0x0810; +const int32_t WindowsLanguageId::kJapanese_Japan = 0x0411; +const int32_t WindowsLanguageId::kKannada_India = 0x044B; +const int32_t WindowsLanguageId::kKazakh_Kazakhstan = 0x043F; +const int32_t WindowsLanguageId::kKhmer_Cambodia = 0x0453; +const int32_t WindowsLanguageId::kKiche_Guatemala = 0x0486; +const int32_t WindowsLanguageId::kKinyarwanda_Rwanda = 0x0487; +const int32_t WindowsLanguageId::kKiswahili_Kenya = 0x0441; +const int32_t WindowsLanguageId::kKonkani_India = 0x0457; +const int32_t WindowsLanguageId::kKorean_Korea = 0x0412; +const int32_t WindowsLanguageId::kKyrgyz_Kyrgyzstan = 0x0440; +const int32_t WindowsLanguageId::kLao_LaoPDR = 0x0454; +const int32_t WindowsLanguageId::kLatvian_Latvia = 0x0426; +const int32_t WindowsLanguageId::kLithuanian_Lithuania = 0x0427; +const int32_t WindowsLanguageId::kLowerSorbian_Germany = 0x082E; +const int32_t WindowsLanguageId::kLuxembourgish_Luxembourg = 0x046E; +const int32_t WindowsLanguageId::kMacedonian_FYROM_FormerYugoslavRepublicOfMacedonia = 0x042F; +const int32_t WindowsLanguageId::kMalay_BruneiDarussalam = 0x083E; +const int32_t WindowsLanguageId::kMalay_Malaysia = 0x043E; +const int32_t WindowsLanguageId::kMalayalam_India = 0x044C; +const int32_t WindowsLanguageId::kMaltese_Malta = 0x043A; +const int32_t WindowsLanguageId::kMaori_NewZealand = 0x0481; +const int32_t WindowsLanguageId::kMapudungun_Chile = 0x047A; +const int32_t WindowsLanguageId::kMarathi_India = 0x044E; +const int32_t WindowsLanguageId::kMohawk_Mohawk = 0x047C; +const int32_t WindowsLanguageId::kMongolian_Cyrillic_Mongolia = 0x0450; +const int32_t WindowsLanguageId::kMongolian_Traditional_PeoplesRepublicOfChina = 0x0850; +const int32_t WindowsLanguageId::kNepali_Nepal = 0x0461; +const int32_t WindowsLanguageId::kNorwegian_Bokmal_Norway = 0x0414; +const int32_t WindowsLanguageId::kNorwegian_Nynorsk_Norway = 0x0814; +const int32_t WindowsLanguageId::kOccitan_France = 0x0482; +const int32_t WindowsLanguageId::kOriya_India = 0x0448; +const int32_t WindowsLanguageId::kPashto_Afghanistan = 0x0463; +const int32_t WindowsLanguageId::kPolish_Poland = 0x0415; +const int32_t WindowsLanguageId::kPortuguese_Brazil = 0x0416; +const int32_t WindowsLanguageId::kPortuguese_Portugal = 0x0816; +const int32_t WindowsLanguageId::kPunjabi_India = 0x0446; +const int32_t WindowsLanguageId::kQuechua_Bolivia = 0x046B; +const int32_t WindowsLanguageId::kQuechua_Ecuador = 0x086B; +const int32_t WindowsLanguageId::kQuechua_Peru = 0x0C6B; +const int32_t WindowsLanguageId::kRomanian_Romania = 0x0418; +const int32_t WindowsLanguageId::kRomansh_Switzerland = 0x0417; +const int32_t WindowsLanguageId::kRussian_Russia = 0x0419; +const int32_t WindowsLanguageId::kSami_Inari_Finland = 0x243B; +const int32_t WindowsLanguageId::kSami_Lule_Norway = 0x103B; +const int32_t WindowsLanguageId::kSami_Lule_Sweden = 0x143B; +const int32_t WindowsLanguageId::kSami_Northern_Finland = 0x0C3B; +const int32_t WindowsLanguageId::kSami_Northern_Norway = 0x043B; +const int32_t WindowsLanguageId::kSami_Northern_Sweden = 0x083B; +const int32_t WindowsLanguageId::kSami_Skolt_Finland = 0x203B; +const int32_t WindowsLanguageId::kSami_Southern_Norway = 0x183B; +const int32_t WindowsLanguageId::kSami_Southern_Sweden = 0x1C3B; +const int32_t WindowsLanguageId::kSanskrit_India = 0x044F; +const int32_t WindowsLanguageId::kSerbian_Cyrillic_BosniaAndHerzegovina = 0x1C1A; +const int32_t WindowsLanguageId::kSerbian_Cyrillic_Serbia = 0x0C1A; +const int32_t WindowsLanguageId::kSerbian_Latin_BosniaAndHerzegovina = 0x181A; +const int32_t WindowsLanguageId::kSerbian_Latin_Serbia = 0x081A; +const int32_t WindowsLanguageId::kSesothoSaLeboa_SouthAfrica = 0x046C; +const int32_t WindowsLanguageId::kSetswana_SouthAfrica = 0x0432; +const int32_t WindowsLanguageId::kSinhala_SriLanka = 0x045B; +const int32_t WindowsLanguageId::kSlovak_Slovakia = 0x041B; +const int32_t WindowsLanguageId::kSlovenian_Slovenia = 0x0424; +const int32_t WindowsLanguageId::kSpanish_Argentina = 0x2C0A; +const int32_t WindowsLanguageId::kSpanish_Bolivia = 0x400A; +const int32_t WindowsLanguageId::kSpanish_Chile = 0x340A; +const int32_t WindowsLanguageId::kSpanish_Colombia = 0x240A; +const int32_t WindowsLanguageId::kSpanish_CostaRica = 0x140A; +const int32_t WindowsLanguageId::kSpanish_DominicanRepublic = 0x1C0A; +const int32_t WindowsLanguageId::kSpanish_Ecuador = 0x300A; +const int32_t WindowsLanguageId::kSpanish_ElSalvador = 0x440A; +const int32_t WindowsLanguageId::kSpanish_Guatemala = 0x100A; +const int32_t WindowsLanguageId::kSpanish_Honduras = 0x480A; +const int32_t WindowsLanguageId::kSpanish_Mexico = 0x080A; +const int32_t WindowsLanguageId::kSpanish_Nicaragua = 0x4C0A; +const int32_t WindowsLanguageId::kSpanish_Panama = 0x180A; +const int32_t WindowsLanguageId::kSpanish_Paraguay = 0x3C0A; +const int32_t WindowsLanguageId::kSpanish_Peru = 0x280A; +const int32_t WindowsLanguageId::kSpanish_PuertoRico = 0x500A; +const int32_t WindowsLanguageId::kSpanish_ModernSort_Spain = 0x0C0A; +const int32_t WindowsLanguageId::kSpanish_TraditionalSort_Spain = 0x040A; +const int32_t WindowsLanguageId::kSpanish_UnitedStates = 0x540A; +const int32_t WindowsLanguageId::kSpanish_Uruguay = 0x380A; +const int32_t WindowsLanguageId::kSpanish_Venezuela = 0x200A; +const int32_t WindowsLanguageId::kSweden_Finland = 0x081D; +const int32_t WindowsLanguageId::kSwedish_Sweden = 0x041D; +const int32_t WindowsLanguageId::kSyriac_Syria = 0x045A; +const int32_t WindowsLanguageId::kTajik_Cyrillic_Tajikistan = 0x0428; +const int32_t WindowsLanguageId::kTamazight_Latin_Algeria = 0x085F; +const int32_t WindowsLanguageId::kTamil_India = 0x0449; +const int32_t WindowsLanguageId::kTatar_Russia = 0x0444; +const int32_t WindowsLanguageId::kTelugu_India = 0x044A; +const int32_t WindowsLanguageId::kThai_Thailand = 0x041E; +const int32_t WindowsLanguageId::kTibetan_PRC = 0x0451; +const int32_t WindowsLanguageId::kTurkish_Turkey = 0x041F; +const int32_t WindowsLanguageId::kTurkmen_Turkmenistan = 0x0442; +const int32_t WindowsLanguageId::kUighur_PRC = 0x0480; +const int32_t WindowsLanguageId::kUkrainian_Ukraine = 0x0422; +const int32_t WindowsLanguageId::kUpperSorbian_Germany = 0x042E; +const int32_t WindowsLanguageId::kUrdu_IslamicRepublicOfPakistan = 0x0420; +const int32_t WindowsLanguageId::kUzbek_Cyrillic_Uzbekistan = 0x0843; +const int32_t WindowsLanguageId::kUzbek_Latin_Uzbekistan = 0x0443; +const int32_t WindowsLanguageId::kVietnamese_Vietnam = 0x042A; +const int32_t WindowsLanguageId::kWelsh_UnitedKingdom = 0x0452; +const int32_t WindowsLanguageId::kWolof_Senegal = 0x0448; +const int32_t WindowsLanguageId::kYakut_Russia = 0x0485; +const int32_t WindowsLanguageId::kYi_PRC = 0x0478; +const int32_t WindowsLanguageId::kYoruba_Nigeria = 0x046A; + +/****************************************************************************** + * NameTable class + ******************************************************************************/ +NameTable::NameTable(Header* header, ReadableFontData* data) + : Table(header, data) {} + +NameTable::~NameTable() {} + +int32_t NameTable::format() { + return data_->readUShort(Offset::kFormat); +} + +int32_t NameTable::nameCount() { + return data_->readUShort(Offset::kCount); +} + +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::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)); +} + +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()); +} + +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, length); +} + +CALLER_ATTACH NameTable::NameEntry* NameTable::nameEntry(int32_t index) { + ByteVector b; + nameAsBytes(index, &b); + NameEntryPtr instance = new NameEntry(platformId(index), encodingId(index), + languageId(index), nameId(index), b); + return instance.detach(); +} + +/****************************************************************************** + * NameTable::NameEntry class + ******************************************************************************/ +void NameTable::NameEntry::init(int32_t platform_id, int32_t encoding_id, + int32_t language_id, int32_t name_id, + const ByteVector* name_bytes) { + platform_id_ = platform_id; + encoding_id_ = encoding_id; + language_id_ = language_id; + name_id_ = name_id; + if (name_bytes) + name_bytes_ = *name_bytes; +} + +NameTable::NameEntry::NameEntry() { + init(0, 0, 0, 0, NULL); +} + +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() {} +int32_t NameTable::NameEntry::platformId() { return platform_id_; } +int32_t NameTable::NameEntry::encodingId() { return encoding_id_; } +int32_t NameTable::NameEntry::languageId() { return language_id_; } +int32_t NameTable::NameEntry::nameId() { return name_id_; } +int32_t NameTable::NameEntry::nameBytesLength() { return name_bytes_.size(); } +ByteVector* NameTable::NameEntry::nameBytes() { return &name_bytes_; } + +bool NameTable::NameEntry::operator==(const NameEntry& obj) { + return (encoding_id_ == obj.encoding_id_ && + language_id_ == obj.language_id_ && + platform_id_ == obj.platform_id_ && + name_id_ == obj.name_id_); +} + +int NameTable::NameEntry::hashCode() { + return ((encoding_id_ & 0x3f) << 26) | ((name_id_ & 0x3f) << 16) | + ((platform_id_ & 0x0f) << 12) | (language_id_ & 0xff); +} + +int NameTable::NameEntry::compareTo(const NameEntry& o) { + if (platform_id_ != o.platform_id_) { + return platform_id_ - o.platform_id_; + } + if (encoding_id_ != o.encoding_id_) { + return encoding_id_ - o.encoding_id_; + } + if (language_id_ != o.language_id_) { + return language_id_ - o.language_id_; + } + return name_id_ - o.name_id_; +} + +/****************************************************************************** + * NameTable::NameEntryBuilder class + ******************************************************************************/ +NameTable::NameEntryBuilder::NameEntryBuilder() { + init(0, 0, 0, 0, NULL); +} + +NameTable::NameEntryBuilder::NameEntryBuilder( + 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::NameEntryBuilder::NameEntryBuilder( + int32_t platform_id, int32_t encoding_id, int32_t language_id, + int32_t name_id) { + init(platform_id, encoding_id, language_id, name_id, NULL); +} + +NameTable::NameEntryBuilder::NameEntryBuilder(NameEntry* b) { + init(b->platform_id_, b->encoding_id_, b->language_id_, b->name_id_, + b->nameBytes()); +} + +NameTable::NameEntryBuilder::~NameEntryBuilder() {} + +/****************************************************************************** + * NameTable::NameEntryIterator class + ******************************************************************************/ +NameTable::NameEntryIterator::NameEntryIterator(NameTable* table, + NameEntryFilter* filter) : + table_(table), filter_(filter), name_index_(0) { +} + +bool NameTable::NameEntryIterator::hasNext() { + if (!filter_) { + if (name_index_ < table_->nameCount()) { + return true; + } + return false; + } + for (; name_index_ < table_->nameCount(); ++name_index_) { + if (filter_->accept(table_->platformId(name_index_), + table_->encodingId(name_index_), + table_->languageId(name_index_), + table_->nameId(name_index_))) { + return true; + } + } + return false; +} + +NameTable::NameEntry* NameTable::NameEntryIterator::next() { + if (!hasNext()) + return NULL; + return table_->nameEntry(name_index_++); +} + +/****************************************************************************** + * NameTable::Builder class + ******************************************************************************/ +NameTable::Builder::Builder(FontDataTableBuilderContainer* font_builder, + Header* header, WritableFontData* data) : + Table::ArrayElementTableBuilder(font_builder, header, data) { +} + +NameTable::Builder::Builder(FontDataTableBuilderContainer* font_builder, + Header* header, ReadableFontData* data) : + Table::ArrayElementTableBuilder(font_builder, header, data) { +} + +void NameTable::Builder::initialize(ReadableFontData* data) { + if (data) { + NameTablePtr table = new NameTable(header(), data); + NameEntryIterator name_iter(table, NULL); + while (name_iter.hasNext()) { + NameEntryPtr name_entry(name_iter.next()); + NameEntryBuilderPtr name_entry_builder = new NameEntryBuilder(name_entry); + name_entry_map_.insert(NameEntryMapEntry(name_entry_builder, + name_entry_builder)); + } + } +} + +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; + for (NameEntryMap::iterator b = name_entry_map_.begin(), + end = name_entry_map_.end(); b != end; ++b) { + new_data->writeUShort(NameTable::Offset::kNameRecordPlatformId, + b->first->platformId()); + new_data->writeUShort(NameTable::Offset::kNameRecordEncodingId, + b->first->encodingId()); + new_data->writeUShort(NameTable::Offset::kNameRecordLanguageId, + b->first->languageId()); + new_data->writeUShort(NameTable::Offset::kNameRecordNameId, + b->first->nameId()); + new_data->writeUShort(NameTable::Offset::kNameRecordStringLength, + b->first->nameBytesLength()); + new_data->writeUShort(NameTable::Offset::kNameRecordStringOffset, + string_offset); + name_record_offset += NameTable::Offset::kNameRecordSize; + string_offset += new_data->writeBytes( + string_offset + string_table_start_offset, b->first->nameBytes()); + } + + return string_offset + string_table_start_offset; +} + +bool NameTable::Builder::subReadyToSerialize() { + return !name_entry_map_.empty(); +} + +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 (NameEntryMap::iterator b = name_entry_map_.begin(), + end = name_entry_map_.end(); b != end; ++b) { + size += b->first->nameBytesLength(); + } + return size; +} + +void NameTable::Builder::subDataSet() { + name_entry_map_.clear(); + setModelChanged(false); +} + +CALLER_ATTACH FontDataTable* NameTable::Builder::subBuildTable( + ReadableFontData* data) { + FontDataTablePtr table = new NameTable(header(), data); + return table.detach(); +} + +} // namespace sfntly diff --git a/sfntly/name_table.h b/sfntly/name_table.h new file mode 100644 index 0000000..7553aa0 --- /dev/null +++ b/sfntly/name_table.h @@ -0,0 +1,530 @@ +/* + * 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. + */ + +// TODO(arthurhsu): IMPLEMENT: not really used and tested, need cleanup +#ifndef TYPOGRAPHY_FONT_SFNTLY_SRC_SFNTLY_NAME_TABLE_H_ +#define TYPOGRAPHY_FONT_SFNTLY_SRC_SFNTLY_NAME_TABLE_H_ + +#include +#include + +#include "sfntly/table.h" + +namespace sfntly { + +struct UnicodeLanguageId { + static const int32_t kUnknown; + static const int32_t kAll; +}; + +// Macinstosh Language IDs (platform ID = 1) +struct MacintoshLanguageId { + static const int32_t kUnknown; + static const int32_t kEnglish; + static const int32_t kFrench; + static const int32_t kGerman; + static const int32_t kItalian; + static const int32_t kDutch; + static const int32_t kSwedish; + static const int32_t kSpanish; + static const int32_t kDanish; + static const int32_t kPortuguese; + static const int32_t kNorwegian; + static const int32_t kHebrew; + static const int32_t kJapanese; + static const int32_t kArabic; + static const int32_t kFinnish; + static const int32_t kGreek; + static const int32_t kIcelandic; + static const int32_t kMaltese; + static const int32_t kTurkish; + static const int32_t kCroatian; + static const int32_t kChinese_Traditional; + static const int32_t kUrdu; + static const int32_t kHindi; + static const int32_t kThai; + static const int32_t kKorean; + static const int32_t kLithuanian; + static const int32_t kPolish; + static const int32_t kHungarian; + static const int32_t kEstonian; + static const int32_t kLatvian; + static const int32_t kSami; + static const int32_t kFaroese; + static const int32_t kFarsiPersian; + static const int32_t kRussian; + static const int32_t kChinese_Simplified; + static const int32_t kFlemish; + static const int32_t kIrishGaelic; + static const int32_t kAlbanian; + static const int32_t kRomanian; + static const int32_t kCzech; + static const int32_t kSlovak; + static const int32_t kSlovenian; + static const int32_t kYiddish; + static const int32_t kSerbian; + static const int32_t kMacedonian; + static const int32_t kBulgarian; + static const int32_t kUkrainian; + static const int32_t kByelorussian; + static const int32_t kUzbek; + static const int32_t kKazakh; + static const int32_t kAzerbaijani_Cyrillic; + static const int32_t kAzerbaijani_Arabic; + static const int32_t kArmenian; + static const int32_t kGeorgian; + static const int32_t kMoldavian; + static const int32_t kKirghiz; + static const int32_t kTajiki; + static const int32_t kTurkmen; + static const int32_t kMongolian_Mongolian; + static const int32_t kMongolian_Cyrillic; + static const int32_t kPashto; + static const int32_t kKurdish; + static const int32_t kKashmiri; + static const int32_t kSindhi; + static const int32_t kTibetan; + static const int32_t kNepali; + static const int32_t kSanskrit; + static const int32_t kMarathi; + static const int32_t kBengali; + static const int32_t kAssamese; + static const int32_t kGujarati; + static const int32_t kPunjabi; + static const int32_t kOriya; + static const int32_t kMalayalam; + static const int32_t kKannada; + static const int32_t kTamil; + static const int32_t kTelugu; + static const int32_t kSinhalese; + static const int32_t kBurmese; + static const int32_t kKhmer; + static const int32_t kLao; + static const int32_t kVietnamese; + static const int32_t kIndonesian; + static const int32_t kTagalong; + static const int32_t kMalay_Roman; + static const int32_t kMalay_Arabic; + static const int32_t kAmharic; + static const int32_t kTigrinya; + static const int32_t kGalla; + static const int32_t kSomali; + static const int32_t kSwahili; + static const int32_t kKinyarwandaRuanda; + static const int32_t kRundi; + static const int32_t kNyanjaChewa; + static const int32_t kMalagasy; + static const int32_t kEsperanto; + static const int32_t kWelsh; + static const int32_t kBasque; + static const int32_t kCatalan; + static const int32_t kLatin; + static const int32_t kQuenchua; + static const int32_t kGuarani; + static const int32_t kAymara; + static const int32_t kTatar; + static const int32_t kUighur; + static const int32_t kDzongkha; + static const int32_t kJavanese_Roman; + static const int32_t kSundanese_Roman; + static const int32_t kGalician; + static const int32_t kAfrikaans; + static const int32_t kBreton; + static const int32_t kInuktitut; + static const int32_t kScottishGaelic; + static const int32_t kManxGaelic; + static const int32_t kIrishGaelic_WithDotAbove; + static const int32_t kTongan; + static const int32_t kGreek_Polytonic; + static const int32_t kGreenlandic; + static const int32_t kAzerbaijani_Roman; +}; + +// Windows Language IDs (platformID = 3) +struct WindowsLanguageId { + static const int32_t kUnknown; + static const int32_t kAfrikaans_SouthAfrica; + static const int32_t kAlbanian_Albania; + static const int32_t kAlsatian_France; + static const int32_t kAmharic_Ethiopia; + static const int32_t kArabic_Algeria; + static const int32_t kArabic_Bahrain; + static const int32_t kArabic_Egypt; + static const int32_t kArabic_Iraq; + static const int32_t kArabic_Jordan; + static const int32_t kArabic_Kuwait; + static const int32_t kArabic_Lebanon; + static const int32_t kArabic_Libya; + static const int32_t kArabic_Morocco; + static const int32_t kArabic_Oman; + static const int32_t kArabic_Qatar; + static const int32_t kArabic_SaudiArabia; + static const int32_t kArabic_Syria; + static const int32_t kArabic_Tunisia; + static const int32_t kArabic_UAE; + static const int32_t kArabic_Yemen; + static const int32_t kArmenian_Armenia; + static const int32_t kAssamese_India; + static const int32_t kAzeri_Cyrillic_Azerbaijan; + static const int32_t kAzeri_Latin_Azerbaijan; + static const int32_t kBashkir_Russia; + static const int32_t kBasque_Basque; + static const int32_t kBelarusian_Belarus; + static const int32_t kBengali_Bangladesh; + static const int32_t kBengali_India; + static const int32_t kBosnian_Cyrillic_BosniaAndHerzegovina; + static const int32_t kBosnian_Latin_BosniaAndHerzegovina; + static const int32_t kBreton_France; + static const int32_t kBulgarian_Bulgaria; + static const int32_t kCatalan_Catalan; + static const int32_t kChinese_HongKongSAR; + static const int32_t kChinese_MacaoSAR; + static const int32_t kChinese_PeoplesRepublicOfChina; + static const int32_t kChinese_Singapore; + static const int32_t kChinese_Taiwan; + static const int32_t kCorsican_France; + static const int32_t kCroatian_Croatia; + static const int32_t kCroatian_Latin_BosniaAndHerzegovina; + static const int32_t kCzech_CzechRepublic; + static const int32_t kDanish_Denmark; + static const int32_t kDari_Afghanistan; + static const int32_t kDivehi_Maldives; + static const int32_t kDutch_Belgium; + static const int32_t kDutch_Netherlands; + static const int32_t kEnglish_Australia; + static const int32_t kEnglish_Belize; + static const int32_t kEnglish_Canada; + static const int32_t kEnglish_Caribbean; + static const int32_t kEnglish_India; + static const int32_t kEnglish_Ireland; + static const int32_t kEnglish_Jamaica; + static const int32_t kEnglish_Malaysia; + static const int32_t kEnglish_NewZealand; + static const int32_t kEnglish_RepublicOfThePhilippines; + static const int32_t kEnglish_Singapore; + static const int32_t kEnglish_SouthAfrica; + static const int32_t kEnglish_TrinidadAndTobago; + static const int32_t kEnglish_UnitedKingdom; + static const int32_t kEnglish_UnitedStates; + static const int32_t kEnglish_Zimbabwe; + static const int32_t kEstonian_Estonia; + static const int32_t kFaroese_FaroeIslands; + static const int32_t kFilipino_Philippines; + static const int32_t kFinnish_Finland; + static const int32_t kFrench_Belgium; + static const int32_t kFrench_Canada; + static const int32_t kFrench_France; + static const int32_t kFrench_Luxembourg; + static const int32_t kFrench_PrincipalityOfMonoco; + static const int32_t kFrench_Switzerland; + static const int32_t kFrisian_Netherlands; + static const int32_t kGalician_Galician; + static const int32_t kGeorgian_Georgia; + static const int32_t kGerman_Austria; + static const int32_t kGerman_Germany; + static const int32_t kGerman_Liechtenstein; + static const int32_t kGerman_Luxembourg; + static const int32_t kGerman_Switzerland; + static const int32_t kGreek_Greece; + static const int32_t kGreenlandic_Greenland; + static const int32_t kGujarati_India; + static const int32_t kHausa_Latin_Nigeria; + static const int32_t kHebrew_Israel; + static const int32_t kHindi_India; + static const int32_t kHungarian_Hungary; + static const int32_t kIcelandic_Iceland; + static const int32_t kIgbo_Nigeria; + static const int32_t kIndonesian_Indonesia; + static const int32_t kInuktitut_Canada; + static const int32_t kInuktitut_Latin_Canada; + static const int32_t kIrish_Ireland; + static const int32_t kisiXhosa_SouthAfrica; + static const int32_t kisiZulu_SouthAfrica; + static const int32_t kItalian_Italy; + static const int32_t kItalian_Switzerland; + static const int32_t kJapanese_Japan; + static const int32_t kKannada_India; + static const int32_t kKazakh_Kazakhstan; + static const int32_t kKhmer_Cambodia; + static const int32_t kKiche_Guatemala; + static const int32_t kKinyarwanda_Rwanda; + static const int32_t kKiswahili_Kenya; + static const int32_t kKonkani_India; + static const int32_t kKorean_Korea; + static const int32_t kKyrgyz_Kyrgyzstan; + static const int32_t kLao_LaoPDR; + static const int32_t kLatvian_Latvia; + static const int32_t kLithuanian_Lithuania; + static const int32_t kLowerSorbian_Germany; + static const int32_t kLuxembourgish_Luxembourg; + static const int32_t kMacedonian_FYROM_FormerYugoslavRepublicOfMacedonia; + static const int32_t kMalay_BruneiDarussalam; + static const int32_t kMalay_Malaysia; + static const int32_t kMalayalam_India; + static const int32_t kMaltese_Malta; + static const int32_t kMaori_NewZealand; + static const int32_t kMapudungun_Chile; + static const int32_t kMarathi_India; + static const int32_t kMohawk_Mohawk; + static const int32_t kMongolian_Cyrillic_Mongolia; + static const int32_t kMongolian_Traditional_PeoplesRepublicOfChina; + static const int32_t kNepali_Nepal; + static const int32_t kNorwegian_Bokmal_Norway; + static const int32_t kNorwegian_Nynorsk_Norway; + static const int32_t kOccitan_France; + static const int32_t kOriya_India; + static const int32_t kPashto_Afghanistan; + static const int32_t kPolish_Poland; + static const int32_t kPortuguese_Brazil; + static const int32_t kPortuguese_Portugal; + static const int32_t kPunjabi_India; + static const int32_t kQuechua_Bolivia; + static const int32_t kQuechua_Ecuador; + static const int32_t kQuechua_Peru; + static const int32_t kRomanian_Romania; + static const int32_t kRomansh_Switzerland; + static const int32_t kRussian_Russia; + static const int32_t kSami_Inari_Finland; + static const int32_t kSami_Lule_Norway; + static const int32_t kSami_Lule_Sweden; + static const int32_t kSami_Northern_Finland; + static const int32_t kSami_Northern_Norway; + static const int32_t kSami_Northern_Sweden; + static const int32_t kSami_Skolt_Finland; + static const int32_t kSami_Southern_Norway; + static const int32_t kSami_Southern_Sweden; + static const int32_t kSanskrit_India; + static const int32_t kSerbian_Cyrillic_BosniaAndHerzegovina; + static const int32_t kSerbian_Cyrillic_Serbia; + static const int32_t kSerbian_Latin_BosniaAndHerzegovina; + static const int32_t kSerbian_Latin_Serbia; + static const int32_t kSesothoSaLeboa_SouthAfrica; + static const int32_t kSetswana_SouthAfrica; + static const int32_t kSinhala_SriLanka; + static const int32_t kSlovak_Slovakia; + static const int32_t kSlovenian_Slovenia; + static const int32_t kSpanish_Argentina; + static const int32_t kSpanish_Bolivia; + static const int32_t kSpanish_Chile; + static const int32_t kSpanish_Colombia; + static const int32_t kSpanish_CostaRica; + static const int32_t kSpanish_DominicanRepublic; + static const int32_t kSpanish_Ecuador; + static const int32_t kSpanish_ElSalvador; + static const int32_t kSpanish_Guatemala; + static const int32_t kSpanish_Honduras; + static const int32_t kSpanish_Mexico; + static const int32_t kSpanish_Nicaragua; + static const int32_t kSpanish_Panama; + static const int32_t kSpanish_Paraguay; + static const int32_t kSpanish_Peru; + static const int32_t kSpanish_PuertoRico; + static const int32_t kSpanish_ModernSort_Spain; + static const int32_t kSpanish_TraditionalSort_Spain; + static const int32_t kSpanish_UnitedStates; + static const int32_t kSpanish_Uruguay; + static const int32_t kSpanish_Venezuela; + static const int32_t kSweden_Finland; + static const int32_t kSwedish_Sweden; + static const int32_t kSyriac_Syria; + static const int32_t kTajik_Cyrillic_Tajikistan; + static const int32_t kTamazight_Latin_Algeria; + static const int32_t kTamil_India; + static const int32_t kTatar_Russia; + static const int32_t kTelugu_India; + static const int32_t kThai_Thailand; + static const int32_t kTibetan_PRC; + static const int32_t kTurkish_Turkey; + static const int32_t kTurkmen_Turkmenistan; + static const int32_t kUighur_PRC; + static const int32_t kUkrainian_Ukraine; + static const int32_t kUpperSorbian_Germany; + static const int32_t kUrdu_IslamicRepublicOfPakistan; + static const int32_t kUzbek_Cyrillic_Uzbekistan; + static const int32_t kUzbek_Latin_Uzbekistan; + static const int32_t kVietnamese_Vietnam; + static const int32_t kWelsh_UnitedKingdom; + static const int32_t kWolof_Senegal; + static const int32_t kYakut_Russia; + static const int32_t kYi_PRC; + static const int32_t kYoruba_Nigeria; +}; + +class NameTable : public Table, public RefCounted { + private: + struct Offset { + static const int32_t kFormat; + static const int32_t kCount; + static const int32_t kStringOffset; + static const int32_t kNameRecordStart; + + // format 1 - offset from the end of the name records + static const int32_t kLangTagCount; + static const int32_t kLangTagRecord; + + static const int32_t kNameRecordSize; + // Name Records + static const int32_t kNameRecordPlatformId; + static const int32_t kNameRecordEncodingId; + static const int32_t kNameRecordLanguageId; + static const int32_t kNameRecordNameId; + static const int32_t kNameRecordStringLength; + static const int32_t kNameRecordStringOffset; + }; + + struct NameId { + static const int32_t kUnknown; + static const int32_t kCopyrightNotice; + static const int32_t kFontFamilyName; + static const int32_t kFontSubfamilyName; + static const int32_t kUniqueFontIdentifier; + static const int32_t kFullFontName; + static const int32_t kVersionString; + static const int32_t kPostscriptName; + static const int32_t kTrademark; + static const int32_t kManufacturerName; + static const int32_t kDesigner; + static const int32_t kDescription; + static const int32_t kVendorURL; + static const int32_t kDesignerURL; + static const int32_t kLicenseDescription; + static const int32_t kLicenseInfoURL; + static const int32_t kReserved15; + static const int32_t kPreferredFamily; + static const int32_t kPreferredSubfamily; + static const int32_t kCompatibleFullName; + static const int32_t kSampleText; + static const int32_t kPostscriptCID; + static const int32_t kWWSFamilyName; + static const int32_t kWWSSubfamilyName; + }; + + public: + class NameEntryBuilder; + class NameEntry : public RefCounted { + public: + NameEntry(); + NameEntry(int32_t platform_id, int32_t encoding_id, int32_t language_id, + int32_t name_id, const ByteVector& name_bytes); + virtual void init(int32_t platform_id, int32_t encoding_id, + int32_t language_id, int32_t name_id, + const ByteVector* name_bytes); + virtual ~NameEntry(); + virtual int32_t platformId(); + virtual int32_t encodingId(); + virtual int32_t languageId(); + virtual int32_t nameId(); + virtual bool operator==(const NameEntry& obj); + virtual int hashCode(); + virtual int compareTo(const NameEntry& obj); + virtual int32_t nameBytesLength(); // C++ port only + virtual ByteVector* nameBytes(); + + protected: + int32_t platform_id_; + int32_t encoding_id_; + int32_t language_id_; + int32_t name_id_; + int32_t length_; + ByteVector name_bytes_; + + friend class NameEntryBuilder; + }; + + class NameEntryBuilder : public NameEntry { + public: + NameEntryBuilder(); + NameEntryBuilder(int32_t platform_id, int32_t encoding_id, + int32_t language_id, int32_t name_id, + const ByteVector& name_bytes); + NameEntryBuilder(int32_t platform_id, int32_t encoding_id, + int32_t language_id, int32_t name_id); + explicit NameEntryBuilder(NameEntry* entry); + virtual ~NameEntryBuilder(); + }; + typedef Ptr NameEntryBuilderPtr; + typedef std::map NameEntryMap; + typedef std::pair NameEntryMapEntry; + + 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() {} + }; + + class Builder : public Table::ArrayElementTableBuilder { + public: + // Constructor scope altered to public because C++ does not allow base + // class to instantiate derived class with protected constructors. + Builder(FontDataTableBuilderContainer* font_builder, Header* header, + WritableFontData* data); + Builder(FontDataTableBuilderContainer* font_builder, Header* header, + ReadableFontData* data); + + virtual int32_t subSerialize(WritableFontData* new_data); + virtual bool subReadyToSerialize(); + virtual int32_t subDataSizeToSerialize(); + virtual void subDataSet(); + virtual CALLER_ATTACH FontDataTable* subBuildTable(ReadableFontData* data); + + private: + void initialize(ReadableFontData* data); + + private: + NameEntryMap name_entry_map_; + }; + + class NameEntryIterator { + public: + // If filter is NULL, filter through all tables. + NameEntryIterator(NameTable* table, NameEntryFilter* filter); + bool hasNext(); + NameEntry* next(); + + private: + NameTable* table_; // use dumb pointer since it's a composition object + int32_t name_index_; + NameEntryFilter* filter_; + }; + + private: + NameTable(Header* header, ReadableFontData* data); + + public: + virtual ~NameTable(); + virtual int32_t format(); + virtual int32_t nameCount(); + virtual int32_t platformId(int32_t index); + virtual int32_t encodingId(int32_t index); + virtual int32_t languageId(int32_t index); + virtual int32_t nameId(int32_t index); + virtual void nameAsBytes(int32_t index, ByteVector* b); + virtual CALLER_ATTACH NameEntry* nameEntry(int32_t index); + + private: + int32_t stringOffset(); + int32_t offsetForNameRecord(int32_t index); + int32_t nameLength(int32_t index); + int32_t nameOffset(int32_t index); +}; +typedef Ptr NameTablePtr; +typedef Ptr NameEntryPtr; + +} // namespace sfntly + +#endif // TYPOGRAPHY_FONT_SFNTLY_SRC_SFNTLY_NAME_TABLE_H_ diff --git a/sfntly/os2_table.cc b/sfntly/os2_table.cc new file mode 100644 index 0000000..73d98cc --- /dev/null +++ b/sfntly/os2_table.cc @@ -0,0 +1,368 @@ +/* + * 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/os2_table.h" + +namespace sfntly { +/****************************************************************************** + * Constants + ******************************************************************************/ +const int32_t OS2Table::Offset::kVersion = 0; +const int32_t OS2Table::Offset::kXAvgCharWidth = 2; +const int32_t OS2Table::Offset::kUsWeightClass = 4; +const int32_t OS2Table::Offset::kUsWidthClass = 6; +const int32_t OS2Table::Offset::kFsType = 8; +const int32_t OS2Table::Offset::kYSubscriptXSize = 10; +const int32_t OS2Table::Offset::kYSubscriptYSize = 12; +const int32_t OS2Table::Offset::kYSubscriptXOffset = 14; +const int32_t OS2Table::Offset::kYSubscriptYOffset = 16; +const int32_t OS2Table::Offset::kYSuperscriptXSize = 18; +const int32_t OS2Table::Offset::kYSuperscriptYSize = 20; +const int32_t OS2Table::Offset::kYSuperscriptXOffset = 22; +const int32_t OS2Table::Offset::kYSuperscriptYOffset = 24; +const int32_t OS2Table::Offset::kYStrikeoutSize = 26; +const int32_t OS2Table::Offset::kYStrikeoutPosition = 28; +const int32_t OS2Table::Offset::kSFamilyClass = 30; +const int32_t OS2Table::Offset::kPanose = 32; +const int32_t OS2Table::Offset::kUlUnicodeRange1 = 42; +const int32_t OS2Table::Offset::kUlUnicodeRange2 = 46; +const int32_t OS2Table::Offset::kUlUnicodeRange3 = 50; +const int32_t OS2Table::Offset::kUlUnicodeRange4 = 54; +const int32_t OS2Table::Offset::kAchVendId = 58; +const int32_t OS2Table::Offset::kFsSelection = 62; +const int32_t OS2Table::Offset::kUsFirstCharIndex = 64; +const int32_t OS2Table::Offset::kUsLastCharIndex = 66; +const int32_t OS2Table::Offset::kSTypoAscender = 68; +const int32_t OS2Table::Offset::kSTypoDescender = 70; +const int32_t OS2Table::Offset::kSTypoLineGap = 72; +const int32_t OS2Table::Offset::kUsWinAscent = 74; +const int32_t OS2Table::Offset::kUsWinDescent = 76; +const int32_t OS2Table::Offset::kUlCodePageRange1 = 78; +const int32_t OS2Table::Offset::kUlCodePageRange2 = 82; +const int32_t OS2Table::Offset::kSxHeight = 86; +const int32_t OS2Table::Offset::kSCapHeight = 88; +const int32_t OS2Table::Offset::kUsDefaultChar = 90; +const int32_t OS2Table::Offset::kUsBreakChar = 92; +const int32_t OS2Table::Offset::kUsMaxContext = 94; + +const int32_t WeightClass::kThin = 100; +const int32_t WeightClass::kExtraLight = 200; +const int32_t WeightClass::kUltraLight = 200; +const int32_t WeightClass::kLight = 300; +const int32_t WeightClass::kNormal = 400; +const int32_t WeightClass::kRegular = 400; +const int32_t WeightClass::kMedium = 500; +const int32_t WeightClass::kSemiBold = 600; +const int32_t WeightClass::kDemiBold = 600; +const int32_t WeightClass::kBold = 700; +const int32_t WeightClass::kExtraBold = 800; +const int32_t WeightClass::kUltraBold = 800; +const int32_t WeightClass::kBlack = 900; +const int32_t WeightClass::kHeavy = 900; + +const int32_t WidthClass::kUltraCondensed = 1; +const int32_t WidthClass::kExtraCondensed = 2; +const int32_t WidthClass::kCondensed = 3; +const int32_t WidthClass::kSemiCondensed = 4; +const int32_t WidthClass::kMedium = 5; +const int32_t WidthClass::kNormal = 5; +const int32_t WidthClass::kSemiExpanded = 6; +const int32_t WidthClass::kExpanded = 7; +const int32_t WidthClass::kExtraExpanded = 8; +const int32_t WidthClass::kUltraExpanded = 9; + +const int32_t EmbeddingFlags::kReserved0 = 1 << 0; +const int32_t EmbeddingFlags::kRestrictedLicenseEmbedding = 1 << 1; +const int32_t EmbeddingFlags::kPreviewAndPrintEmbedding = 1 << 2; +const int32_t EmbeddingFlags::kEditableEmbedding = 1 << 3; +const int32_t EmbeddingFlags::kReserved4 = 1 << 4; +const int32_t EmbeddingFlags::kReserved5 = 1 << 5; +const int32_t EmbeddingFlags::kReserved6 = 1 << 6; +const int32_t EmbeddingFlags::kReserved7 = 1 << 7; +const int32_t EmbeddingFlags::kNoSubsetting = 1 << 8; +const int32_t EmbeddingFlags::kBitmapEmbeddingOnly = 1 << 9; +const int32_t EmbeddingFlags::kReserved10 = 1 << 10; +const int32_t EmbeddingFlags::kReserved11 = 1 << 11; +const int32_t EmbeddingFlags::kReserved12 = 1 << 12; +const int32_t EmbeddingFlags::kReserved13 = 1 << 13; +const int32_t EmbeddingFlags::kReserved14 = 1 << 14; +const int32_t EmbeddingFlags::kReserved15 = 1 << 15; + +const int32_t FsSelection::kITALIC = 1 << 0; +const int32_t FsSelection::kUNDERSCORE = 1 << 1; +const int32_t FsSelection::kNEGATIVE = 1 << 2; +const int32_t FsSelection::kOUTLINED = 1 << 3; +const int32_t FsSelection::kSTRIKEOUT = 1 << 4; +const int32_t FsSelection::kBOLD = 1 << 5; +const int32_t FsSelection::kREGULAR = 1 << 6; +const int32_t FsSelection::kUSE_TYPO_METRICS = 1 << 7; +const int32_t FsSelection::kWWS = 1 << 8; +const int32_t FsSelection::kOBLIQUE = 1 << 9; + +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(Header* header, ReadableFontData* data) + : Table(header, data) { +} + +OS2Table::~OS2Table() {} + +int32_t OS2Table::version() { + 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) { + value->clear(); + value->resize(10); + data_->readBytes(Offset::kPanose, value, 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) { + b->clear(); + b->resize(4); + data_->readBytes(Offset::kAchVendId, b, 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::sTypoDecender() { + 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); +} + +int64_t OS2Table::ulCodePageRange() { + return ((0xffffffff & ulCodePageRange2()) << 32) | + (0xffffffff & ulCodePageRange1()); +} + +int32_t OS2Table::sxHeight() { + return data_->readShort(Offset::kSxHeight); +} + +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); +} + +/****************************************************************************** + * class OS2Table::Builder + ******************************************************************************/ +OS2Table::Builder::Builder(FontDataTableBuilderContainer* font_builder, + Header* header, WritableFontData* data) : + Table::TableBasedTableBuilder(font_builder, header, data) { +} + +OS2Table::Builder::~Builder() {} + +CALLER_ATTACH FontDataTable* OS2Table::Builder::subBuildTable( + ReadableFontData* data) { + FontDataTablePtr table = new OS2Table(header(), data); + return table.detach(); +} + +} // namespace sfntly diff --git a/sfntly/os2_table.h b/sfntly/os2_table.h new file mode 100644 index 0000000..88d4769 --- /dev/null +++ b/sfntly/os2_table.h @@ -0,0 +1,393 @@ +/* + * 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_OS2_TABLE_H_ +#define TYPOGRAPHY_FONT_SFNTLY_SRC_SFNTLY_OS2_TABLE_H_ + +#include "sfntly/port/refcount.h" +#include "sfntly/table.h" + +namespace sfntly { + +struct WeightClass { + static const int32_t kThin; + static const int32_t kExtraLight; + static const int32_t kUltraLight; + static const int32_t kLight; + static const int32_t kNormal; + static const int32_t kRegular; + static const int32_t kMedium; + static const int32_t kSemiBold; + static const int32_t kDemiBold; + static const int32_t kBold; + static const int32_t kExtraBold; + static const int32_t kUltraBold; + static const int32_t kBlack; + static const int32_t kHeavy; +}; + +struct WidthClass { + static const int32_t kUltraCondensed; + static const int32_t kExtraCondensed; + static const int32_t kCondensed; + static const int32_t kSemiCondensed; + static const int32_t kMedium; + static const int32_t kNormal; + static const int32_t kSemiExpanded; + static const int32_t kExpanded; + static const int32_t kExtraExpanded; + static const int32_t kUltraExpanded; +}; + +struct EmbeddingFlags { + static const int32_t kReserved0; + static const int32_t kRestrictedLicenseEmbedding; + static const int32_t kPreviewAndPrintEmbedding; + static const int32_t kEditableEmbedding; + static const int32_t kReserved4; + static const int32_t kReserved5; + static const int32_t kReserved6; + static const int32_t kReserved7; + static const int32_t kNoSubsetting; + static const int32_t kBitmapEmbeddingOnly; + static const int32_t kReserved10; + static const int32_t kReserved11; + static const int32_t kReserved12; + static const int32_t kReserved13; + static const int32_t kReserved14; + static const int32_t kReserved15; +}; + +struct UnicodeRange { + enum { + 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) +}; + +struct FsSelection { + static const int32_t kITALIC; + static const int32_t kUNDERSCORE; + static const int32_t kNEGATIVE; + static const int32_t kOUTLINED; + static const int32_t kSTRIKEOUT; + static const int32_t kBOLD; + static const int32_t kREGULAR; + static const int32_t kUSE_TYPO_METRICS; + static const int32_t kWWS; + static const int32_t kOBLIQUE; +}; + +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; +}; + +class OS2Table : public Table, public RefCounted { + private: + struct Offset { + static const int32_t kVersion; + static const int32_t kXAvgCharWidth; + static const int32_t kUsWeightClass; + static const int32_t kUsWidthClass; + static const int32_t kFsType; + static const int32_t kYSubscriptXSize; + static const int32_t kYSubscriptYSize; + static const int32_t kYSubscriptXOffset; + static const int32_t kYSubscriptYOffset; + static const int32_t kYSuperscriptXSize; + static const int32_t kYSuperscriptYSize; + static const int32_t kYSuperscriptXOffset; + static const int32_t kYSuperscriptYOffset; + static const int32_t kYStrikeoutSize; + static const int32_t kYStrikeoutPosition; + static const int32_t kSFamilyClass; + static const int32_t kPanose; + static const int32_t kUlUnicodeRange1; + static const int32_t kUlUnicodeRange2; + static const int32_t kUlUnicodeRange3; + static const int32_t kUlUnicodeRange4; + static const int32_t kAchVendId; + static const int32_t kFsSelection; + static const int32_t kUsFirstCharIndex; + static const int32_t kUsLastCharIndex; + static const int32_t kSTypoAscender; + static const int32_t kSTypoDescender; + static const int32_t kSTypoLineGap; + static const int32_t kUsWinAscent; + static const int32_t kUsWinDescent; + static const int32_t kUlCodePageRange1; + static const int32_t kUlCodePageRange2; + static const int32_t kSxHeight; + static const int32_t kSCapHeight; + static const int32_t kUsDefaultChar; + static const int32_t kUsBreakChar; + static const int32_t kUsMaxContext; + }; + + OS2Table(Header* header, ReadableFontData* data); + + public: + ~OS2Table(); + + int32_t version(); + 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 sTypoDecender(); + int32_t sTypoLineGap(); + int32_t usWinAscent(); + int32_t usWinDescent(); + int64_t ulCodePageRange1(); + int64_t ulCodePageRange2(); + // UNIMPLEMENTED: public EnumSet ulCodePageRange() + int64_t ulCodePageRange(); + int32_t sxHeight(); + int32_t sCapHeight(); + int32_t usDefaultChar(); + int32_t usBreakChar(); + int32_t usMaxContext(); + + public: + class Builder : public Table::TableBasedTableBuilder, + public RefCounted { + public: + Builder(FontDataTableBuilderContainer* font_builder, Header* header, + WritableFontData* data); + virtual ~Builder(); + virtual CALLER_ATTACH FontDataTable* subBuildTable(ReadableFontData* data); + }; +}; + +} // namespace sfntly + +#endif // TYPOGRAPHY_FONT_SFNTLY_SRC_SFNTLY_OS2_TABLE_H_ diff --git a/sfntly/port/atomic.h b/sfntly/port/atomic.h new file mode 100644 index 0000000..10db2d5 --- /dev/null +++ b/sfntly/port/atomic.h @@ -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. + */ + +#ifndef TYPOGRAPHY_FONT_SFNTLY_SRC_SFNTLY_PORT_ATOMIC_H_ +#define TYPOGRAPHY_FONT_SFNTLY_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)); +} + +#elif defined (__GCC_HAVE_SYNC_COMPARE_AND_SWAP_4) + +#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); +} + +#else + +#error "Compiler not supported" + +#endif // WIN32 + +#endif // TYPOGRAPHY_FONT_SFNTLY_SRC_SFNTLY_PORT_ATOMIC_H_ diff --git a/sfntly/port/config.h b/sfntly/port/config.h new file mode 100644 index 0000000..8e610d0 --- /dev/null +++ b/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 TYPOGRAPHY_FONT_SFNTLY_SRC_SFNTLY_PORT_CONFIG_H_ +#define TYPOGRAPHY_FONT_SFNTLY_SRC_SFNTLY_PORT_CONFIG_H_ + +#if !defined(SFNTLY_BIG_ENDIAN) && !defined(SFNTLY_LITTLE_ENDIAN) + #if defined (__ppc__) || defined (__ppc64__) + #define TYPOGRAPHY_FONT_SFNTLY_BIG_ENDIAN + #else + #define TYPOGRAPHY_FONT_SFNTLY_LITTLE_ENDIAN + #endif +#endif + +#endif // TYPOGRAPHY_FONT_SFNTLY_SRC_SFNTLY_PORT_CONFIG_H_ diff --git a/sfntly/port/endian.h b/sfntly/port/endian.h new file mode 100644 index 0000000..c6898ee --- /dev/null +++ b/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 TYPOGRAPHY_FONT_SFNTLY_SRC_SFNTLY_PORT_ENDIAN_H_ +#define TYPOGRAPHY_FONT_SFNTLY_SRC_SFNTLY_PORT_ENDIAN_H_ + +#include "sfntly/port/config.h" +#include "sfntly/port/type.h" + +namespace sfntly { + +static inline uint16_t endian_swap16(uint16_t value) { + return (uint16_t)((value >> 8) | (value << 8)); +} + +static inline int32_t endian_swap32(int32_t value) { + return (((value & 0x000000ff) << 24) | + ((value & 0x0000ff00) << 8) | + ((value & 0x00ff0000) >> 8) | + ((value & 0xff000000) >> 24)); +} + +static inline uint64_t endian_swap64(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) endian_swap16(n) + #define toBE32(n) endian_swap32(n) + #define toBE64(n) endian_swap64(n) + #define toLE16(n) (n) + #define toLE32(n) (n) + #define toLE64(n) (n) + #define fromBE16(n) endian_swap16(n) + #define fromBE32(n) endian_swap32(n) + #define fromBE64(n) endian_swap64(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) endian_swap16(n) + #define toLE32(n) endian_swap32(n) + #define toLE64(n) endian_swap64(n) + #define fromBE16(n) (n) + #define fromBE32(n) (n) + #define fromBE64(n) (n) + #define fromLE16(n) endian_swap16(n) + #define fromLE32(n) endian_swap32(n) + #define fromLE64(n) endian_swap64(n) +#endif + +} // namespace sfntly + +#endif // TYPOGRAPHY_FONT_SFNTLY_SRC_SFNTLY_PORT_ENDIAN_H_ diff --git a/sfntly/port/exception_type.h b/sfntly/port/exception_type.h new file mode 100644 index 0000000..56a93ff --- /dev/null +++ b/sfntly/port/exception_type.h @@ -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. + */ + +// Exceptions used in sfntly + +#ifndef TYPOGRAPHY_FONT_SFNTLY_SRC_SFNTLY_PORT_EXCEPTION_TYPE_H_ +#define TYPOGRAPHY_FONT_SFNTLY_SRC_SFNTLY_PORT_EXCEPTION_TYPE_H_ + +#include +#include + +namespace sfntly { + +class Exception : public std::exception { + public: + explicit Exception(const char* message) throw() { + try { + what_ = message; + } catch (...) {} + } + virtual ~Exception() throw() {} + virtual const char* what() const throw() { return what_.c_str(); } + + private: + std::string what_; +}; + +class IndexOutOfBoundException : public Exception { + public: + IndexOutOfBoundException() throw() : Exception("Index out of bound") {} + explicit IndexOutOfBoundException(const char* message) throw() + : Exception(message) {} + 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 // TYPOGRAPHY_FONT_SFNTLY_SRC_SFNTLY_PORT_EXCEPTION_TYPE_H_ diff --git a/sfntly/port/file_input_stream.cc b/sfntly/port/file_input_stream.cc new file mode 100644 index 0000000..7505ab7 --- /dev/null +++ b/sfntly/port/file_input_stream.cc @@ -0,0 +1,139 @@ +/* + * 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), length_(0), position_(0) { +} + +FileInputStream::~FileInputStream() { + close(); +} + +int32_t FileInputStream::available() { + return length_ - position_; +} + +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; +} + +void FileInputStream::close() { + if (file_) { + fclose(file_); + length_ = 0; + position_ = 0; + } +} + +void FileInputStream::mark(int32_t readlimit) { + // NOP + UNREFERENCED_PARAMETER(readlimit); +} + +bool FileInputStream::markSupported() { + return false; +} + +int32_t FileInputStream::read() { + if (!file_) { + throw IOException("no opened file"); + } + if (feof(file_)) { + throw IOException("eof reached"); + } + byte_t value; + fread(&value, 1, 1, file_); + position_++; + return value; +} + +int32_t FileInputStream::read(ByteVector* b) { + return read(b, 0, b->capacity()); +} + +int32_t FileInputStream::read(ByteVector* b, int32_t offset, int32_t length) { + assert(b); + assert(b->size() >= (size_t)(offset + length)); + if (!file_) { + throw IOException("no opened file"); + } + if (feof(file_)) { + throw IOException("eof reached"); + } + size_t read_count = std::min(length_ - position_, length); + 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_) { + throw IOException("no opened file"); + } + if (n < 0) { + return 0; + } + size_t skip_count = std::min(length_ - position_, (size_t)n); + fseek(file_, skip_count, SEEK_CUR); + position_ += skip_count; + return skip_count; +} + +void FileInputStream::unread(ByteVector* b) { + unread(b, 0, b->capacity()); +} + +void FileInputStream::unread(ByteVector* b, int32_t offset, int32_t length) { + assert(b); + assert(b->size() >= size_t(offset + length)); + if (!file_) { + throw IOException("no opened file"); + } + size_t unread_count = std::min(position_, length); + fseek(file_, position_ - unread_count, SEEK_SET); + read(b, offset, length); + fseek(file_, position_ - unread_count, SEEK_SET); +} + +} // namespace sfntly diff --git a/sfntly/port/file_input_stream.h b/sfntly/port/file_input_stream.h new file mode 100644 index 0000000..0ec85b6 --- /dev/null +++ b/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 TYPOGRAPHY_FONT_SFNTLY_SRC_SFNTLY_PORT_FILE_INPUT_STREAM_H_ +#define TYPOGRAPHY_FONT_SFNTLY_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 // TYPOGRAPHY_FONT_SFNTLY_SRC_SFNTLY_PORT_FILE_INPUT_STREAM_H_ diff --git a/sfntly/port/input_stream.h b/sfntly/port/input_stream.h new file mode 100644 index 0000000..ebbccf0 --- /dev/null +++ b/sfntly/port/input_stream.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_PORT_INPUT_STREAM_H_ +#define TYPOGRAPHY_FONT_SFNTLY_SRC_SFNTLY_PORT_INPUT_STREAM_H_ + +#include "sfntly/port/type.h" + +namespace sfntly { + +// C++ equivalent to Java's OutputStream class +class InputStream { + public: + 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; + // Make gcc -Wnon-virtual-dtor happy. + virtual ~InputStream() {} +}; + +class PushbackInputStream : public InputStream { + public: + virtual void unread(ByteVector* b) = 0; + virtual void unread(ByteVector* b, int32_t offset, int32_t length) = 0; +}; + +} // namespace sfntly + +#endif // TYPOGRAPHY_FONT_SFNTLY_SRC_SFNTLY_PORT_INPUT_STREAM_H_ diff --git a/sfntly/port/memory_output_stream.cc b/sfntly/port/memory_output_stream.cc new file mode 100644 index 0000000..1f3ecd4 --- /dev/null +++ b/sfntly/port/memory_output_stream.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/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) { + store_.insert(store_.end(), buffer->begin() + offset, + buffer->begin() + offset + length); +} + +void MemoryOutputStream::write(byte_t b) { + store_.push_back(b); +} + +byte_t* MemoryOutputStream::get() { + return &(store_[0]); +} + +size_t MemoryOutputStream::size() { + return store_.size(); +} + +} // namespace sfntly diff --git a/sfntly/port/memory_output_stream.h b/sfntly/port/memory_output_stream.h new file mode 100644 index 0000000..a7654af --- /dev/null +++ b/sfntly/port/memory_output_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 TYPOGRAPHY_FONT_SFNTLY_SRC_SFNTLY_PORT_MEMORY_OUTPUT_STREAM_H_ +#define TYPOGRAPHY_FONT_SFNTLY_SRC_SFNTLY_PORT_MEMORY_OUTPUT_STREAM_H_ + +#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 b); + + byte_t* get(); + size_t size(); + + private: + std::vector store_; +}; + +} // namespace sfntly + +#endif // TYPOGRAPHY_FONT_SFNTLY_SRC_SFNTLY_PORT_MEMORY_OUTPUT_STREAM_H_ diff --git a/sfntly/port/output_stream.h b/sfntly/port/output_stream.h new file mode 100644 index 0000000..0b232e2 --- /dev/null +++ b/sfntly/port/output_stream.h @@ -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. + */ + +#ifndef TYPOGRAPHY_FONT_SFNTLY_SRC_SFNTLY_PORT_OUTPUT_STREAM_H_ +#define TYPOGRAPHY_FONT_SFNTLY_SRC_SFNTLY_PORT_OUTPUT_STREAM_H_ + +#include "sfntly/port/type.h" + +namespace sfntly { + +// C++ equivalent to Java's OutputStream class +class OutputStream { + public: + virtual void close() = 0; + virtual void flush() = 0; + virtual void write(ByteVector* buffer) = 0; + virtual void write(ByteVector* buffer, int32_t offset, int32_t length) = 0; + virtual void write(byte_t b) = 0; + // Make gcc -Wnon-virtual-dtor happy. + virtual ~OutputStream() {} +}; + +} // namespace sfntly + +#endif // TYPOGRAPHY_FONT_SFNTLY_SRC_SFNTLY_PORT_OUTPUT_STREAM_H_ diff --git a/sfntly/port/refcount.h b/sfntly/port/refcount.h new file mode 100644 index 0000000..c1e5a6d --- /dev/null +++ b/sfntly/port/refcount.h @@ -0,0 +1,253 @@ +/* + * 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. +// 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 TYPOGRAPHY_FONT_SFNTLY_SRC_SFNTLY_PORT_REFCOUNT_H_ +#define TYPOGRAPHY_FONT_SFNTLY_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: + virtual size_t addRef() const = 0; + virtual size_t release() const = 0; + // Make gcc -Wnon-virtual-dtor happy. + virtual ~RefCount() {} +}; + +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 // TYPOGRAPHY_FONT_SFNTLY_SRC_SFNTLY_PORT_REFCOUNT_H_ diff --git a/sfntly/port/type.h b/sfntly/port/type.h new file mode 100644 index 0000000..ab55b97 --- /dev/null +++ b/sfntly/port/type.h @@ -0,0 +1,84 @@ +/* + * 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_PORT_TYPE_H_ +#define TYPOGRAPHY_FONT_SFNTLY_SRC_SFNTLY_PORT_TYPE_H_ + +#include + +#if defined (_MSC_VER) && (_MSC_VER < 1600) + typedef unsigned char uint8_t; + typedef char int8_t; + typedef unsigned __int16 uint16_t; + typedef __int16 int16_t; + typedef unsigned __int32 uint32_t; + typedef __int32 int32_t; + typedef unsigned __int64 uint64_t; + typedef __int64 int64_t; +#else + #include +#endif + +#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; + +} // 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 + +#if !defined(NDEBUG) + assert(f == NULL || dynamic_cast(f) != NULL); // RTTI: debug mode only! +#endif + return static_cast(f); +} + +#if !defined(WIN32) + #define UNREFERENCED_PARAMETER(p) +#endif + +#endif // TYPOGRAPHY_FONT_SFNTLY_SRC_SFNTLY_PORT_TYPE_H_ diff --git a/sfntly/subtable.cc b/sfntly/subtable.cc new file mode 100644 index 0000000..9ca94f3 --- /dev/null +++ b/sfntly/subtable.cc @@ -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. + */ + +#include "sfntly/subtable.h" + +namespace sfntly { +/****************************************************************************** + * SubTable class + ******************************************************************************/ +SubTable::SubTable(ReadableFontData* data) : FontDataTable(data) { +} + +SubTable::~SubTable() {} + +/****************************************************************************** + * SubTable::Builder class + ******************************************************************************/ +SubTable::Builder::Builder(FontDataTableBuilderContainer* container, + WritableFontData* data) : + FontDataTable::Builder(container, data) { +} + +SubTable::Builder::Builder(FontDataTableBuilderContainer* container, + ReadableFontData* data) : + FontDataTable::Builder(container, data) { +} + +SubTable::Builder::~Builder() {} + +} // namespace sfntly diff --git a/sfntly/subtable.h b/sfntly/subtable.h new file mode 100644 index 0000000..23e1e42 --- /dev/null +++ b/sfntly/subtable.h @@ -0,0 +1,50 @@ +/* + * 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_SUBTABLE_H_ +#define TYPOGRAPHY_FONT_SFNTLY_SRC_SFNTLY_SUBTABLE_H_ + +#include "sfntly/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 { + protected: + // Note: constructor refactored in C++ to avoid heavy lifting. + // caller need to do data->slice(offset, length) beforehand. + explicit SubTable(ReadableFontData* data); + + public: + virtual ~SubTable(); + + public: + class Builder : public FontDataTable::Builder { + protected: + Builder(FontDataTableBuilderContainer* container, WritableFontData* data); + Builder(FontDataTableBuilderContainer* container, ReadableFontData* data); + + public: + virtual ~Builder(); + }; +}; + +} // namespace sfntly + +#endif // TYPOGRAPHY_FONT_SFNTLY_SRC_SFNTLY_SUBTABLE_H_ diff --git a/sfntly/table.cc b/sfntly/table.cc new file mode 100644 index 0000000..1215f50 --- /dev/null +++ b/sfntly/table.cc @@ -0,0 +1,275 @@ +/* + * 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.h" +#include "sfntly/font.h" +#include "sfntly/tag.h" +#include "sfntly/cmap_table.h" +#include "sfntly/font_header_table.h" +#include "sfntly/glyph_table.h" +#include "sfntly/horizontal_header_table.h" +#include "sfntly/horizontal_metrics_table.h" +#include "sfntly/loca_table.h" +#include "sfntly/maximum_profile_table.h" +#include "sfntly/name_table.h" +#include "sfntly/os2_table.h" + +namespace sfntly { + +/****************************************************************************** + * Table class + ******************************************************************************/ +Table::Table(Header* header, ReadableFontData* data) : FontDataTable(data) { + header_ = header; +} + +Table::~Table() {} + +int64_t Table::calculatedChecksum() { + return data_->checksum(); +} + +Table::Header* Table::header() { + return header_; +} + +int32_t Table::headerTag() { + return header_->tag(); +} + +int32_t Table::headerOffset() { + return header_->offset(); +} + +int32_t Table::headerLength() { + return header_->length(); +} + +int64_t Table::headerChecksum() { + return header_->checksum(); +} + +WritableFontData* Table::getNewData(int32_t size) { + return font_->getNewData(size); +} + +void Table::setFont(Font* font) { + font_ = font; +} + +/****************************************************************************** + * Table::Header class + ******************************************************************************/ +Table::Header::Header(int32_t tag) + : tag_(tag), checksum_(0), checksum_valid_(false), offset_(0), length_(0), + offset_valid_(false) { +} + +Table::Header::Header(int32_t tag, int32_t length) + : tag_(tag), checksum_(0), checksum_valid_(false), offset_(0), + length_(length), offset_valid_(false) { +} + +Table::Header::Header(int32_t tag, int64_t checksum, int32_t offset, + int32_t length) + : tag_(tag), checksum_(checksum), checksum_valid_(true), offset_(offset), + length_(length), offset_valid_(true) { +} + +Table::Header::~Header() {} + +bool TableHeaderComparator::operator() (const TableHeaderPtr lhs, + const TableHeaderPtr rhs) { + return lhs->offset_ > rhs->offset_; +} + +int32_t Table::Header::tag() { return tag_; } +int32_t Table::Header::offset() { return offset_; } +int32_t Table::Header::length() { return length_; } +bool Table::Header::offsetValid() { return offset_valid_; } +int64_t Table::Header::checksum() { return checksum_; } +bool Table::Header::checksumValid() { return checksum_valid_; } + +/****************************************************************************** + * Table::Builder class + ******************************************************************************/ +Table::Builder::Builder(FontDataTableBuilderContainer* font_builder, + Header* header, WritableFontData* data) : + FontDataTable::Builder(font_builder, data) { + header_ = header; +} + +Table::Builder::Builder(FontDataTableBuilderContainer* font_builder, + Header* header, ReadableFontData* data) : + FontDataTable::Builder(font_builder, data) { + header_ = header; +} + +Table::Builder::Builder(FontDataTableBuilderContainer* font_builder, + Header* header) : + FontDataTable::Builder(font_builder) { + header_ = header; +} + +Table::Builder::~Builder() { + header_.release(); +} + +Table::Header* Table::Builder::header() { + return header_; +} + +void Table::Builder::notifyPostTableBuild(FontDataTable* table) { + if (modelChanged() || dataChanged()) { + Table* derived_table = down_cast(table); + header_ = new Header(header()->tag(), + derived_table->readFontData()->length()); + } +} + +WritableFontData* Table::Builder::getNewData(int32_t size) { + UNREFERENCED_PARAMETER(size); + return internalWriteData(); +} + +CALLER_ATTACH Table::Builder* Table::Builder::getBuilder( + FontDataTableBuilderContainer* font_builder, Header* header, + WritableFontData* table_data) { + int32_t tag = header->tag(); + TableBuilderPtr builder; + 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::cmap) { + builder_raw = static_cast( + new CMapTable::Builder(font_builder, header, table_data)); + } else*/ if (tag == Tag::head) { + builder_raw = static_cast( + new FontHeaderTable::Builder(font_builder, header, table_data)); + } else if (tag == Tag::hhea) { + builder_raw = static_cast( + new HorizontalHeaderTable::Builder(font_builder, header, table_data)); + } else if (tag == Tag::hmtx) { + builder_raw = static_cast( + new HorizontalMetricsTable::Builder(font_builder, header, table_data)); + } else if (tag == Tag::maxp) { + builder_raw = static_cast( + new MaximumProfileTable::Builder(font_builder, header, table_data)); + }/* else if (tag == Tag::name) { + builder_raw = static_cast( + new NameTable::Builder(font_builder, header, table_data)); + }*/ else if (tag == Tag::OS_2) { + builder_raw = static_cast( + new OS2Table::Builder(font_builder, header, table_data)); + }/* else if (tag == Tag::PostScript) { + builder_raw = static_cast( + new PostScriptTable::Builder(font_builder, header, table_data)); + } else if (tag == Tag::cvt) { + builder_raw = static_cast( + new ControlValueTable::Builder(font_builder, header, table_data)); + }*/ else if (tag == Tag::glyf) { + builder_raw = static_cast( + new GlyphTable::Builder(font_builder, header, table_data)); + } else if (tag == Tag::loca) { + builder_raw = static_cast( + new LocaTable::Builder(font_builder, header, table_data)); + }/* else if (tag == Tag::prep) { + builder_raw = static_cast( + new ControlProgramTable::Builder(font_builder, header, table_data)); + }*/ else if (tag == Tag::bhed) { + builder_raw = static_cast( + new FontHeaderTable::Builder(font_builder, header, table_data)); + } else { + builder_raw = static_cast( + new Table::GenericTableBuilder(font_builder, header, table_data)); + } + + builder = builder_raw; + return builder.detach(); +} + +/****************************************************************************** + * Table::TableBasedTableBuilder class + ******************************************************************************/ +Table::TableBasedTableBuilder::TableBasedTableBuilder( + FontDataTableBuilderContainer* font_builder, Header* header, + WritableFontData* data) : Builder(font_builder, header, data) {} + +Table::TableBasedTableBuilder::TableBasedTableBuilder( + FontDataTableBuilderContainer* font_builder, Header* header, + ReadableFontData* data) : Builder(font_builder, header, data) {} + +Table::TableBasedTableBuilder::TableBasedTableBuilder( + FontDataTableBuilderContainer* font_builder, Header* header) : + Builder(font_builder, header) {} + +Table::TableBasedTableBuilder::~TableBasedTableBuilder() {} + +Table* Table::TableBasedTableBuilder::table() { + if (table_ == NULL) { + table_.attach(down_cast(subBuildTable(internalReadData()))); + } + return table_; +} + +void Table::TableBasedTableBuilder::subDataSet() { + table_ = NULL; +} + +int32_t Table::TableBasedTableBuilder::subDataSizeToSerialize() { + return 0; +} + +bool Table::TableBasedTableBuilder::subReadyToSerialize() { + return false; +} + +int32_t Table::TableBasedTableBuilder::subSerialize(WritableFontData* data) { + UNREFERENCED_PARAMETER(data); + return 0; +} + +/****************************************************************************** + * Table::GenericTableBuilder class + ******************************************************************************/ +Table::GenericTableBuilder::GenericTableBuilder( + FontDataTableBuilderContainer* font_builder, Header* header, + WritableFontData* data) : + TableBasedTableBuilder(font_builder, header, data) {} + +CALLER_ATTACH FontDataTable* Table::GenericTableBuilder::subBuildTable( + ReadableFontData* data) { + // Note: In C++ port, we use GenericTable, the ref-counted version of Table + UNREFERENCED_PARAMETER(data); + FontDataTablePtr table = new GenericTable(this->header(), internalReadData()); + return table.detach(); +} + +/****************************************************************************** + * Table::ArrayElementTableBuilder class + ******************************************************************************/ +Table::ArrayElementTableBuilder::ArrayElementTableBuilder( + FontDataTableBuilderContainer* font_builder, Header* header, + WritableFontData* data) : Builder(font_builder, header, data) {} + +Table::ArrayElementTableBuilder::ArrayElementTableBuilder( + FontDataTableBuilderContainer* font_builder, Header* header, + ReadableFontData* data) : Builder(font_builder, header, data) {} + +Table::ArrayElementTableBuilder::~ArrayElementTableBuilder() {} + +} // namespace sfntly diff --git a/sfntly/table.h b/sfntly/table.h new file mode 100644 index 0000000..9f05ef5 --- /dev/null +++ b/sfntly/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 TYPOGRAPHY_FONT_SFNTLY_SRC_SFNTLY_TABLE_H_ +#define TYPOGRAPHY_FONT_SFNTLY_SRC_SFNTLY_TABLE_H_ + +#include +#include +#include +#include + +#include "sfntly/port/type.h" +#include "sfntly/font_data_table.h" + +namespace sfntly { +class Font; +class Table : public FontDataTable, public FontDataTableBuilderContainer { + public: + class Header : public RefCounted
{ + public: + explicit Header(int32_t tag); + Header(int32_t tag, int32_t length); + Header(int32_t tag, int64_t checksum, int32_t offset, int32_t length); + virtual ~Header(); + + public: // class is final, no virtual functions unless from parent + int32_t tag(); + int32_t offset(); + int32_t length(); + bool offsetValid(); + int64_t checksum(); + bool checksumValid(); + + private: + int32_t tag_; + int32_t offset_; + int32_t length_; + bool offset_valid_; + int64_t checksum_; + bool checksum_valid_; + + friend class TableHeaderComparator; + }; + + // Note: original version is Builder + // C++ template is not designed that way so plain old inheritance is + // chosen. + class Builder : public FontDataTable::Builder, + public FontDataTableBuilderContainer { + protected: + // Note: original version is Font.Builder font_builder. This results in + // mutual inclusion happiness that Java solved for C++. Therefore, + // we need to avoid that happiness when we port it to C++. + Builder(FontDataTableBuilderContainer* font_builder, Header* header, + WritableFontData* data); + Builder(FontDataTableBuilderContainer* font_builder, Header* header, + ReadableFontData* data); + Builder(FontDataTableBuilderContainer* font_builder, Header* header); + + public: + virtual ~Builder(); + virtual Header* header(); + virtual void notifyPostTableBuild(FontDataTable* table); + virtual WritableFontData* getNewData(int32_t size); + + public: + static CALLER_ATTACH Builder* getBuilder( + FontDataTableBuilderContainer* font_builder, Header* header, + WritableFontData* table_data); + + private: + Ptr
header_; + }; + + class TableBasedTableBuilder : public Builder { + protected: + TableBasedTableBuilder(FontDataTableBuilderContainer* font_builder, + Header* header, WritableFontData* data); + TableBasedTableBuilder(FontDataTableBuilderContainer* font_builder, + Header* header, ReadableFontData* data); + TableBasedTableBuilder(FontDataTableBuilderContainer* font_builder, + Header* header); + public: + virtual ~TableBasedTableBuilder(); + + protected: + virtual Table* table(); + + public: + virtual int32_t subSerialize(WritableFontData* new_data); + virtual bool subReadyToSerialize(); + virtual int32_t subDataSizeToSerialize(); + virtual void subDataSet(); + + protected: + Ptr table_; + }; + + class GenericTableBuilder : public TableBasedTableBuilder, + public RefCounted { + public: + GenericTableBuilder(FontDataTableBuilderContainer* font_builder, + Header* header, WritableFontData* data); + virtual CALLER_ATTACH FontDataTable* subBuildTable(ReadableFontData* data); + }; + + class ArrayElementTableBuilder : public Builder { + protected: + ArrayElementTableBuilder(FontDataTableBuilderContainer* font_builder, + Header* header, WritableFontData* data); + ArrayElementTableBuilder(FontDataTableBuilderContainer* font_builder, + Header* header, ReadableFontData* data); + public: + virtual ~ArrayElementTableBuilder(); + }; + + protected: + Table(Header* header, ReadableFontData* data); + + public: + virtual ~Table(); + virtual int64_t calculatedChecksum(); + virtual Header* header(); + virtual int32_t headerTag(); + virtual int32_t headerOffset(); + virtual int32_t headerLength(); + virtual int64_t headerChecksum(); + + public: // FontDataTableBuilderContainer, deprecated + virtual WritableFontData* getNewData(int32_t size); + virtual void setFont(Font* font); + + 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 Ptr TableHeaderPtr; +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; + +class TableHeaderComparator { + public: + bool operator()(const TableHeaderPtr h1, const TableHeaderPtr h2); +}; +typedef std::set TableHeaderSortedSet; + +} // namespace sfntly + +#endif // TYPOGRAPHY_FONT_SFNTLY_SRC_SFNTLY_TABLE_H_ diff --git a/sfntly/tag.cc b/sfntly/tag.cc new file mode 100644 index 0000000..257e65f --- /dev/null +++ b/sfntly/tag.cc @@ -0,0 +1,95 @@ +/* + * 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" + +namespace sfntly { + +const int32_t Tag::ttcf = generate_tag('t', 't', 'c', 'f'); +const int32_t Tag::cmap = generate_tag('c', 'm', 'a', 'p'); +const int32_t Tag::head = generate_tag('h', 'e', 'a', 'd'); +const int32_t Tag::hhea = generate_tag('h', 'h', 'e', 'a'); +const int32_t Tag::hmtx = generate_tag('h', 'm', 't', 'x'); +const int32_t Tag::maxp = generate_tag('m', 'a', 'x', 'p'); +const int32_t Tag::name = generate_tag('n', 'a', 'm', 'e'); +const int32_t Tag::OS_2 = generate_tag('O', 'S', '/', '2'); +const int32_t Tag::post = generate_tag('p', 'o', 's', 't'); +const int32_t Tag::cvt = generate_tag('c', 'v', 't', ' '); +const int32_t Tag::fpgm = generate_tag('f', 'p', 'g', 'm'); +const int32_t Tag::glyf = generate_tag('g', 'l', 'y', 'f'); +const int32_t Tag::loca = generate_tag('l', 'o', 'c', 'a'); +const int32_t Tag::prep = generate_tag('p', 'r', 'e', 'p'); +const int32_t Tag::CFF = generate_tag('C', 'F', 'F', ' '); +const int32_t Tag::VORG = generate_tag('V', 'O', 'R', 'G'); +const int32_t Tag::EBDT = generate_tag('E', 'B', 'D', 'T'); +const int32_t Tag::EBLC = generate_tag('E', 'B', 'L', 'C'); +const int32_t Tag::EBSC = generate_tag('E', 'B', 'S', 'C'); +const int32_t Tag::BASE = generate_tag('B', 'A', 'S', 'E'); +const int32_t Tag::GDEF = generate_tag('G', 'D', 'E', 'F'); +const int32_t Tag::GPOS = generate_tag('G', 'P', 'O', 'S'); +const int32_t Tag::GSUB = generate_tag('G', 'S', 'U', 'B'); +const int32_t Tag::JSTF = generate_tag('J', 'S', 'T', 'F'); +const int32_t Tag::DSIG = generate_tag('D', 'S', 'I', 'G'); +const int32_t Tag::gasp = generate_tag('g', 'a', 's', 'p'); +const int32_t Tag::hdmx = generate_tag('h', 'd', 'm', 'x'); +const int32_t Tag::kern = generate_tag('k', 'e', 'r', 'n'); +const int32_t Tag::LTSH = generate_tag('L', 'T', 'S', 'H'); +const int32_t Tag::PCLT = generate_tag('P', 'C', 'L', 'T'); +const int32_t Tag::VDMX = generate_tag('V', 'D', 'M', 'X'); +const int32_t Tag::vhea = generate_tag('v', 'h', 'e', 'a'); +const int32_t Tag::vmtx = generate_tag('v', 'm', 't', 'x'); +const int32_t Tag::bhed = generate_tag('b', 'h', 'e', 'd'); +const int32_t Tag::bdat = generate_tag('b', 'd', 'a', 't'); +const int32_t Tag::bloc = generate_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/sfntly/tag.h b/sfntly/tag.h new file mode 100644 index 0000000..fdebacb --- /dev/null +++ b/sfntly/tag.h @@ -0,0 +1,99 @@ +/* + * 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_TAG_H_ +#define TYPOGRAPHY_FONT_SFNTLY_SRC_SFNTLY_TAG_H_ + +#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; + + // 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; + + // GX Tables + // TODO(stuartg): add these tables + + // Bitmap font tables + static const int32_t bhed; + static const int32_t bdat; + static const int32_t bloc; +}; + +inline int32_t generate_tag(char a, char b, char c, char d) { + return (((int32_t)(a) << 24) | + ((int32_t)(b) << 16) | + ((int32_t)(c) << 8) | + (int32_t)(d)); +} + +// 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 // TYPOGRAPHY_FONT_SFNTLY_SRC_SFNTLY_TAG_H_ diff --git a/sfntly/tools/subsetter.cc b/sfntly/tools/subsetter.cc new file mode 100644 index 0000000..44ba22e --- /dev/null +++ b/sfntly/tools/subsetter.cc @@ -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. + */ + +#include +#include + +#include "sfntly/tools/subsetter/subsetter.h" +#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::iterator i = font_->tables()->begin(), + e = font_->tables()->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_->table(*tag); + if (table) { + // The newTableBuilder() call will alter internal state of font_builder + // AND the reference count of returned object. Therefore we need to + // dereference it. + TableBuilderPtr dereference; + dereference.attach( + 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/sfntly/tools/subsetter/glyph_table_subsetter.cc b/sfntly/tools/subsetter/glyph_table_subsetter.cc new file mode 100644 index 0000000..93a8852 --- /dev/null +++ b/sfntly/tools/subsetter/glyph_table_subsetter.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/tag.h" +#include "sfntly/glyph_table.h" +#include "sfntly/loca_table.h" +#include "sfntly/tools/subsetter/subsetter.h" +#include "sfntly/tools/subsetter/glyph_table_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->table(Tag::glyf)); + LocaTablePtr loca_table = down_cast(font->table(Tag::loca)); + if (glyph_table == NULL || loca_table == NULL) { + throw RuntimeException("Font to subset is not valid."); + } + + GlyphTableBuilderPtr glyph_table_builder; + glyph_table_builder.attach(down_cast( + font_builder->newTableBuilder(Tag::glyf))); + LocaTableBuilderPtr loca_table_builder; + loca_table_builder.attach(down_cast( + font_builder->newTableBuilder(Tag::loca))); + if (glyph_table_builder == NULL || loca_table_builder == NULL) { + throw RuntimeException("Builder for subset is not valid."); + } + 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->glyph(old_offset, old_length)); + ReadableFontDataPtr data = glyph->readFontData(); + WritableFontDataPtr copy_data; + copy_data.attach(font_builder->getNewData(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/sfntly/tools/subsetter/glyph_table_subsetter.h b/sfntly/tools/subsetter/glyph_table_subsetter.h new file mode 100644 index 0000000..14e3c3d --- /dev/null +++ b/sfntly/tools/subsetter/glyph_table_subsetter.h @@ -0,0 +1,36 @@ +/* + * 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_TOOLS_SUBSETTER_GLYPH_TABLE_SUBSETTER_H_ +#define TYPOGRAPHY_FONT_SFNTLY_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 // TYPOGRAPHY_FONT_SFNTLY_SRC_SFNTLY_TOOLS_SUBSETTER_GLYPH_TABLE_SUBSETTER_H_ diff --git a/sfntly/tools/subsetter/subsetter.h b/sfntly/tools/subsetter/subsetter.h new file mode 100644 index 0000000..01308b5 --- /dev/null +++ b/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 TYPOGRAPHY_FONT_SFNTLY_SRC_SFNTLY_TOOLS_SUBSETTER_SUBSETTER_H_ +#define TYPOGRAPHY_FONT_SFNTLY_SRC_SFNTLY_TOOLS_SUBSETTER_SUBSETTER_H_ + +#include + +#include "sfntly/font.h" +#include "sfntly/font_factory.h" +#include "sfntly/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 // TYPOGRAPHY_FONT_SFNTLY_SRC_SFNTLY_TOOLS_SUBSETTER_SUBSETTER_H_ diff --git a/sfntly/tools/subsetter/table_subsetter.h b/sfntly/tools/subsetter/table_subsetter.h new file mode 100644 index 0000000..9565da6 --- /dev/null +++ b/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 TYPOGRAPHY_FONT_SFNTLY_SRC_SFNTLY_TOOLS_SUBSETTER_TABLE_SUBSETTER_H_ +#define TYPOGRAPHY_FONT_SFNTLY_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 // TYPOGRAPHY_FONT_SFNTLY_SRC_SFNTLY_TOOLS_SUBSETTER_TABLE_SUBSETTER_H_ diff --git a/sfntly/tools/subsetter/table_subsetter_impl.cc b/sfntly/tools/subsetter/table_subsetter_impl.cc new file mode 100644 index 0000000..481f10f --- /dev/null +++ b/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/sfntly/tools/subsetter/table_subsetter_impl.h b/sfntly/tools/subsetter/table_subsetter_impl.h new file mode 100644 index 0000000..7fabba8 --- /dev/null +++ b/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 TYPOGRAPHY_FONT_SFNTLY_SRC_SFNTLY_TOOLS_SUBSETTER_TABLE_SUBSETTER_IMPL_H_ +#define TYPOGRAPHY_FONT_SFNTLY_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 // TYPOGRAPHY_FONT_SFNTLY_SRC_SFNTLY_TOOLS_SUBSETTER_TABLE_SUBSETTER_IMPL_H_ diff --git a/test/byte_array_test.cc b/test/byte_array_test.cc new file mode 100644 index 0000000..d2c865f --- /dev/null +++ b/test/byte_array_test.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 + +#include "gtest/gtest.h" +#include "sfntly/data/memory_byte_array.h" +#include "sfntly/data/growable_memory_byte_array.h" +#include "test/byte_array_test.h" + +namespace sfntly { +namespace byte_array_test { + +const int32_t BYTE_ARRAY_SIZES[] = + {1, 7, 127, 128, 129, 255, 256, 257, 666, 1023, 10000, 0xffff, 0x10000}; + +void fillTestByteArray(ByteArray* ba, int32_t size) { + for (int32_t i = 0; i < size; ++i) { + ba->put(i, (byte_t)(i % 256)); + } +} + +void readByteArrayWithBuffer(ByteArray* ba, ByteVector* buffer, ByteVector* b) { + b->resize(ba->length()); + int32_t index = 0; + while (index < ba->length()) { + int32_t bytes_read = ba->get(index, buffer); + std::copy(buffer->begin(), buffer->begin() + bytes_read, + b->begin() + index); + index += bytes_read; + } +} + +void readByteArrayWithSlidingWindow(ByteArray* ba, int window_size, + ByteVector* b) { + b->resize(ba->length()); + int32_t index = 0; + int32_t actual_window_size = window_size; + while (index < ba->length()) { + actual_window_size = + std::min(actual_window_size, b->size() - index); + int32_t bytes_read = ba->get(index, b, index, actual_window_size); + index += bytes_read; + } +} + +bool readComparison(ByteArray* ba1, ByteArray* ba2) { + // single byte reads + for (int i = 0; i < ba1->length(); ++i) { + EXPECT_EQ(ba1->get(i), ba2->get(i)); + } + + ByteVector b1, b2; + // buffer reads + int increments = std::max(ba1->length() / 11, 1); + for (int buffer_size = 1; buffer_size < ba1->length(); + buffer_size += increments) { + ByteVector buffer(buffer_size); + readByteArrayWithBuffer(ba1, &buffer, &b1); + readByteArrayWithBuffer(ba2, &buffer, &b2); + EXPECT_GT(b1.size(), static_cast(0)); + EXPECT_EQ(b1.size(), b2.size()); + EXPECT_TRUE(std::equal(b1.begin(), b1.end(), b2.begin())); + } + + // sliding window reads + b1.clear(); + b2.clear(); + for (int window_size = 1; window_size < ba1->length(); + window_size += increments) { + readByteArrayWithSlidingWindow(ba1, window_size, &b1); + readByteArrayWithSlidingWindow(ba2, window_size, &b2); + EXPECT_GT(b1.size(), static_cast(0)); + EXPECT_EQ(b1.size(), b2.size()); + EXPECT_TRUE(std::equal(b1.begin(), b1.end(), b2.begin())); + } + + return true; +} + +bool copyTest(ByteArray* ba) { + ByteArrayPtr fixed_copy = new MemoryByteArray(ba->length()); + ba->copyTo(fixed_copy); + EXPECT_EQ(ba->length(), fixed_copy->length()); + EXPECT_TRUE(readComparison(ba, fixed_copy)); + + ByteArrayPtr growable_copy = new GrowableMemoryByteArray(); + ba->copyTo(growable_copy); + EXPECT_EQ(ba->length(), growable_copy->length()); + EXPECT_TRUE(readComparison(ba, growable_copy)); + + return true; +} + +bool byteArrayTester(ByteArray* ba) { + return copyTest(ba); +} + +} // namespace byte_array_test + +bool testMemoryByteArray() { + for (int32_t i = 0; + i < sizeof(byte_array_test::BYTE_ARRAY_SIZES) / sizeof(int32_t); ++i) { + int32_t size = byte_array_test::BYTE_ARRAY_SIZES[i]; + fprintf(stderr, "fixed mem: iteration %d, size %d\n", i, size); + ByteArrayPtr ba = new MemoryByteArray(size); + byte_array_test::fillTestByteArray(ba, size); + EXPECT_TRUE(byte_array_test::byteArrayTester(ba)); + } + return true; +} + +bool testGrowableMemoryByteArray() { + for (int32_t i = 0; + i < sizeof(byte_array_test::BYTE_ARRAY_SIZES) / sizeof(int32_t); ++i) { + int32_t size = byte_array_test::BYTE_ARRAY_SIZES[i]; + fprintf(stderr, "growable mem: iteration %d, size %d\n", i, size); + ByteArrayPtr ba = new GrowableMemoryByteArray(); + byte_array_test::fillTestByteArray(ba, size); + EXPECT_TRUE(byte_array_test::byteArrayTester(ba)); + } + return true; +} + +} // namespace sfntly diff --git a/test/byte_array_test.h b/test/byte_array_test.h new file mode 100644 index 0000000..0d67ca8 --- /dev/null +++ b/test/byte_array_test.h @@ -0,0 +1,27 @@ +/* + * 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_TEST_BYTE_ARRAY_TEST_H_ +#define TYPOGRAPHY_FONT_SFNTLY_SRC_TEST_BYTE_ARRAY_TEST_H_ + +namespace sfntly { + +bool testMemoryByteArray(); +bool testGrowableMemoryByteArray(); + +} // namespace sfntly + +#endif // TYPOGRAPHY_FONT_SFNTLY_SRC_TEST_BYTE_ARRAY_TEST_H_ diff --git a/test/endian_test.cc b/test/endian_test.cc new file mode 100644 index 0000000..887fed5 --- /dev/null +++ b/test/endian_test.cc @@ -0,0 +1,74 @@ +/* + * 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 "gtest/gtest.h" +#include "sfntly/tag.h" +#include "sfntly/data/growable_memory_byte_array.h" +#include "sfntly/data/writable_font_data.h" +#include "sfntly/math/fixed1616.h" +#include "sfntly/port/memory_output_stream.h" +#include "sfntly/data/font_output_stream.h" +#include "test/endian_test.h" + +namespace sfntly { + +bool testEndian() { + byte_t test_data[] = { + 0x68, 0x65, 0x61, 0x64, // 0: head + 0xca, 0xca, 0xca, 0xca, // 4: ubyte, byte, char + 0x00, 0x18, 0x80, 0x18, // 8: ushort, short + 0x00, 0x00, 0x18, 0x00, // 12: uint24 + 0x00, 0x00, 0x00, 0x18, // 16: ulong + 0xff, 0xff, 0xff, 0x00, // 20: long + 0x00, 0x01, 0x00, 0x00 // 24: fixed + }; + + ByteArrayPtr ba1 = new GrowableMemoryByteArray(); + for (size_t i = 0; i < sizeof(test_data); ++i) { + ba1->put(i, test_data[i]); + } + ReadableFontDataPtr rfd = new ReadableFontData(ba1); + EXPECT_EQ(rfd->readULongAsInt(0), Tag::head); + EXPECT_EQ(rfd->readUByte(4), 202); + EXPECT_EQ(rfd->readByte(5), -54); + EXPECT_EQ(rfd->readChar(6), 202); + EXPECT_EQ(rfd->readUShort(8), 24); + EXPECT_EQ(rfd->readShort(10), -32744); + EXPECT_EQ(rfd->readUInt24(12), 24); + EXPECT_EQ(rfd->readULong(16), 24); + EXPECT_EQ(rfd->readLong(20), -256); + EXPECT_EQ(rfd->readFixed(24), Fixed1616::fixed(1, 0)); + + MemoryOutputStream os; + FontOutputStream fos(&os); + fos.writeULong(Tag::head); + fos.write(202); + fos.write(202); + fos.write(202); + fos.write(202); + fos.writeUShort(24); + fos.writeShort(-32744); + fos.writeUInt24(24); + fos.writeChar(0); + fos.writeULong(24); + fos.writeLong(-256); + fos.writeFixed(Fixed1616::fixed(1, 0)); + EXPECT_EQ(memcmp(os.get(), test_data, sizeof(test_data)), 0); + + return true; +} + +} // namespace sfntly diff --git a/test/endian_test.h b/test/endian_test.h new file mode 100644 index 0000000..ce96251 --- /dev/null +++ b/test/endian_test.h @@ -0,0 +1,26 @@ +/* + * 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_TEST_ENDIAN_TEST_H_ +#define TYPOGRAPHY_FONT_SFNTLY_SRC_TEST_ENDIAN_TEST_H_ + +namespace sfntly { + +bool testEndian(); + +} // namespace sfntly + +#endif // TYPOGRAPHY_FONT_SFNTLY_SRC_TEST_ENDIAN_TEST_H_ diff --git a/test/font_data_test.cc b/test/font_data_test.cc new file mode 100644 index 0000000..1e81626 --- /dev/null +++ b/test/font_data_test.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 +#include + +#include "gtest/gtest.h" +#include "sfntly/port/type.h" +#include "sfntly/data/writable_font_data.h" +#include "sfntly/data/memory_byte_array.h" +#include "test/font_data_test.h" + +namespace sfntly { + +const int32_t BYTE_ARRAY_SIZES[] = + {1, 7, 127, 128, 129, 255, 256, 257, 666, 1023, 0x10000}; + +void fillTestByteArray(ByteArray* ba, int32_t size) { + for (int32_t i = 0; i < size; ++i) { + ba->put(i, (byte_t)(i % 256)); + } +} + +void readFontDataWithSingleByte(ReadableFontData* rfd, ByteVector* buffer) { + buffer->resize(rfd->length()); + for (int32_t index = 0; index < rfd->length(); ++index) { + (*buffer)[index] = (byte_t)(rfd->readByte(index)); + } +} + +void readFontDataWithBuffer(ReadableFontData* rfd, int32_t buffer_size, + ByteVector* b) { + ByteVector buffer(buffer_size); + b->resize(rfd->length()); + + int32_t index = 0; + while (index < rfd->length()) { + int32_t bytes_read = rfd->readBytes(index, &buffer, 0, buffer.size()); + EXPECT_GE(bytes_read, 0); + std::copy(buffer.begin(), buffer.begin() + bytes_read, b->begin() + index); + index += bytes_read; + } +} + +void readFontDataWithSlidingWindow(ReadableFontData* rfd, int32_t window_size, + ByteVector* b) { + b->resize(rfd->length()); + int32_t index = 0; + while (index < rfd->length()) { + int32_t actual_window_size = + std::min(window_size, b->size() - index); + int32_t bytes_read = rfd->readBytes(index, b, index, actual_window_size); + EXPECT_GE(bytes_read, 0); + index += bytes_read; + } +} + +void writeFontDataWithSingleByte(ReadableFontData* rfd, WritableFontData* wfd) { + for (int32_t index = 0; index < rfd->length(); ++index) { + byte_t b = (byte_t)(rfd->readByte(index)); + wfd->writeByte(index, b); + } +} + +void writeFontDataWithBuffer(ReadableFontData* rfd, WritableFontData* wfd, + int32_t buffer_size) { + ByteVector buffer(buffer_size); + int32_t index = 0; + while (index < rfd->length()) { + int32_t bytesRead = rfd->readBytes(index, &buffer, 0, buffer.size()); + wfd->writeBytes(index, &buffer, 0, buffer.size()); + index += bytesRead; + } +} + +void writeFontDataWithSlidingWindow(ReadableFontData* rfd, + WritableFontData* wfd, + int32_t window_size) { + ByteVector b(rfd->length()); + int32_t index = 0; + while (index < rfd->length()) { + int32_t sliding_size = std::min(window_size, b.size() - index); + int32_t bytes_read = rfd->readBytes(index, &b, index, sliding_size); + wfd->writeBytes(index, &b, index, sliding_size); + index += bytes_read; + } +} + +bool readComparison(int32_t offset, int32_t length, ReadableFontData* rfd1, + ReadableFontData* rfd2) { + EXPECT_TRUE(length == rfd2->length()); + ByteVector b1, b2; + b1.resize(length); + b2.resize(length); + + // single byte reads + readFontDataWithSingleByte(rfd1, &b1); + readFontDataWithSingleByte(rfd2, &b2); + EXPECT_EQ(memcmp(&(b1[offset]), &(b2[0]), length), 0); + + // buffer reads + int32_t increments = std::max(length / 11, 1); + for (int32_t buffer_size = 1; buffer_size <= length; + buffer_size += increments) { + b1.clear(); + b2.clear(); + b1.resize(length); + b2.resize(length); + readFontDataWithBuffer(rfd1, buffer_size, &b1); + readFontDataWithBuffer(rfd2, buffer_size, &b2); + int result = memcmp(&(b1[offset]), &(b2[0]), length); + EXPECT_EQ(result, 0); + } + + // sliding window reads + for (int32_t window_size = 1; window_size <= length; + window_size += increments) { + b1.clear(); + b2.clear(); + b1.resize(length); + b2.resize(length); + readFontDataWithSlidingWindow(rfd1, window_size, &b1); + readFontDataWithSlidingWindow(rfd2, window_size, &b2); + int result = memcmp(&(b1[offset]), &(b2[0]), length); + EXPECT_EQ(result, 0); + } + return true; +} + +void slicingReadTest(ReadableFontData* rfd) { + for (int32_t trim = 0; trim < (rfd->length() / 2) + 1; + trim += (rfd->length() / 21) + 1) { + fprintf(stderr, "\tread - trim = %d\n", trim); + int32_t length = rfd->length() - 2 * trim; + ReadableFontDataPtr slice; + slice.attach(down_cast(rfd->slice(trim, length))); + EXPECT_TRUE(readComparison(trim, length, rfd, slice)); + } +} + +void slicingWriteTest(ReadableFontData* rfd, WritableFontData* wfd) { + for (int32_t trim = 0; trim < (rfd->length() / 2) + 1; + trim += (rfd->length() / 21) + 1) { + fprintf(stderr, "\twrite - trim = %d\n", trim); + int32_t length = rfd->length() - 2 * trim; + WritableFontDataPtr w_slice; + ReadableFontDataPtr r_slice; + + // single byte writes + w_slice.attach(down_cast(wfd->slice(trim, length))); + r_slice.attach(down_cast(rfd->slice(trim, length))); + writeFontDataWithSingleByte(r_slice, w_slice); + EXPECT_TRUE(readComparison(trim, length, rfd, w_slice)); + + // buffer writes + int32_t increments = std::max(length / 11, 1); + for (int32_t buffer_size = 1; buffer_size < length; + buffer_size += increments) { + w_slice.attach(down_cast(wfd->slice(trim, length))); + r_slice.attach(down_cast(rfd->slice(trim, length))); + writeFontDataWithBuffer(r_slice, w_slice, buffer_size); + EXPECT_TRUE(readComparison(trim, length, rfd, w_slice)); + } + + // sliding window writes + for (int window_size = 1; window_size < length; window_size += increments) { + w_slice.attach(down_cast(wfd->slice(trim, length))); + r_slice.attach(down_cast(rfd->slice(trim, length))); + writeFontDataWithSlidingWindow(r_slice, w_slice, window_size); + EXPECT_TRUE(readComparison(trim, length, rfd, w_slice)); + } + } +} + +bool testReadableFontData() { + for (int32_t i = 0; i < sizeof(BYTE_ARRAY_SIZES) / sizeof(int32_t); ++i) { + int32_t size = BYTE_ARRAY_SIZES[i]; + ByteArrayPtr ba = new MemoryByteArray(size); + fillTestByteArray(ba, size); + ReadableFontDataPtr rfd = new ReadableFontData(ba); + slicingReadTest(rfd); + } + return true; +} + +bool testWritableFontData() { + for (int32_t i = 0; i < sizeof(BYTE_ARRAY_SIZES) / sizeof(int32_t); ++i) { + int32_t size = BYTE_ARRAY_SIZES[i]; + ByteArrayPtr ba = new MemoryByteArray(size); + fillTestByteArray(ba, size); + WritableFontDataPtr wfd = new WritableFontData(ba); + slicingReadTest(wfd); + ByteArrayPtr temp = new MemoryByteArray(size); + WritableFontDataPtr wfd_copy = new WritableFontData(temp); + slicingWriteTest(wfd, wfd_copy); + } + return true; +} + +} // namespace sfntly diff --git a/test/font_data_test.h b/test/font_data_test.h new file mode 100644 index 0000000..78e910d --- /dev/null +++ b/test/font_data_test.h @@ -0,0 +1,25 @@ +/* + * 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_TEST_FONT_DATA_TEST_H_ +#define TYPOGRAPHY_FONT_SFNTLY_SRC_TEST_FONT_DATA_TEST_H_ + +namespace sfntly { + bool testReadableFontData(); + bool testWritableFontData(); +} + +#endif // TYPOGRAPHY_FONT_SFNTLY_SRC_TEST_FONT_DATA_TEST_H_ diff --git a/test/main.cc b/test/main.cc new file mode 100644 index 0000000..27862c5 --- /dev/null +++ b/test/main.cc @@ -0,0 +1,60 @@ +/* + * 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. + */ + +// TODO(arthurhsu): wrap individul tests in ASSERTs so that they fail early + +#include + +#include "gtest/gtest.h" +#include "test/smart_pointer_test.h" +#include "test/endian_test.h" +#include "test/byte_array_test.h" +#include "test/font_data_test.h" +#include "test/open_type_data_test.h" +#include "test/otf_basic_editing_test.h" + +#define RUN_LENGTHY_TESTS + +TEST(SmartPointer, All) { + EXPECT_TRUE(testSmartPointer()); +} + +TEST(Endian, All) { + EXPECT_TRUE(sfntly::testEndian()); +} + +#if defined RUN_LENGTHY_TESTS +TEST(ByteArray, All) { + EXPECT_TRUE(sfntly::testMemoryByteArray()); + EXPECT_TRUE(sfntly::testGrowableMemoryByteArray()); +} +#endif + +#if defined RUN_LENGTHY_TESTS +TEST(FontData, All) { + EXPECT_TRUE(sfntly::testReadableFontData()); + EXPECT_TRUE(sfntly::testWritableFontData()); +} +#endif + +TEST(OpenTypeData, All) { + EXPECT_TRUE(sfntly::testOTFRead()); + EXPECT_TRUE(sfntly::testOTFCopy()); +} + +TEST(OTFBasicEditing, All) { + EXPECT_TRUE(sfntly::testOTFBasicEditing()); +} diff --git a/test/open_type_data_test.cc b/test/open_type_data_test.cc new file mode 100644 index 0000000..ef1d390 --- /dev/null +++ b/test/open_type_data_test.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 "gtest/gtest.h" +#include "sfntly/data/writable_font_data.h" +#include "sfntly/data/memory_byte_array.h" +#include "test/open_type_data_test.h" + +namespace sfntly { + +const byte_t TEST_OTF_DATA[] = + {0xff, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01}; + +bool testOTFRead() { + ByteVector bytes; + for (size_t i = 0; i < sizeof(TEST_OTF_DATA) / sizeof(byte_t); ++i) { + bytes.push_back(TEST_OTF_DATA[i]); + } + ByteArrayPtr array = new MemoryByteArray(&(bytes[0]), bytes.size()); + ReadableFontDataPtr data = new ReadableFontData(array); + + EXPECT_EQ(-1, data->readByte(0)); + EXPECT_EQ(0xff, data->readUByte(0)); + EXPECT_EQ(0x01, data->readByte(1)); + EXPECT_EQ(65281, data->readUShort(0)); + EXPECT_EQ(-255, data->readShort(0)); + EXPECT_EQ(16711937, data->readUInt24(0)); + EXPECT_EQ(4278255873LL, data->readULong(0)); + EXPECT_EQ(-16711423, data->readLong(0)); + return true; +} + +bool testOTFCopy() { + ByteVector source_bytes(1024); + for (size_t i = 0; i < source_bytes.size(); ++i) { + source_bytes[i] = (byte_t)(i & 0xff); + } + ByteArrayPtr source_array = new MemoryByteArray(&(source_bytes[0]), 1024); + ReadableFontDataPtr source = new ReadableFontData(source_array); + + ByteVector destination_bytes(1024); + ByteArrayPtr destination_array = + new MemoryByteArray(&(destination_bytes[0]), 1024); + WritableFontDataPtr destination = new WritableFontData(destination_array); + + int32_t length = source->copyTo(destination); + EXPECT_EQ(1024, length); + EXPECT_TRUE(std::equal(source_bytes.begin(), source_bytes.end(), + destination_bytes.begin())); + return true; +} + +} // namespace sfntly diff --git a/test/open_type_data_test.h b/test/open_type_data_test.h new file mode 100644 index 0000000..99bd422 --- /dev/null +++ b/test/open_type_data_test.h @@ -0,0 +1,27 @@ +/* + * 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_TEST_OPEN_TYPE_DATA_TEST_H_ +#define TYPOGRAPHY_FONT_SFNTLY_SRC_TEST_OPEN_TYPE_DATA_TEST_H_ + +namespace sfntly { + +bool testOTFRead(); +bool testOTFCopy(); + +} // namespace sfntly + +#endif // TYPOGRAPHY_FONT_SFNTLY_SRC_TEST_OPEN_TYPE_DATA_TEST_H_ diff --git a/test/otf_basic_editing_test.cc b/test/otf_basic_editing_test.cc new file mode 100644 index 0000000..233ef14 --- /dev/null +++ b/test/otf_basic_editing_test.cc @@ -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. + */ + +#include "gtest/gtest.h" +#include "sfntly/font.h" +#include "sfntly/font_factory.h" +#include "sfntly/data/memory_byte_array.h" +#include "sfntly/font_header_table.h" +#include "sfntly/tag.h" +#include "test/otf_basic_editing_test.h" + +namespace sfntly { + +// TODO(arthurhsu): port over TestFontUtils +bool testOTFBasicEditing() { + ByteVector input_buffer; +#if defined WIN32 + FILE* input_file; + fopen_s(&input_file, "..\\data\\ext\\arial.ttf", "rb"); +#else + FILE* input_file = fopen("../data/ext/arial.ttf", "rb"); +#endif + EXPECT_TRUE(input_file != NULL); + if (input_file == NULL) { + return false; + } + fseek(input_file, 0, SEEK_END); + size_t file_size = ftell(input_file); + fseek(input_file, 0, SEEK_SET); + input_buffer.resize(file_size); + fread(&(input_buffer[0]), 1, file_size, input_file); + fclose(input_file); + + ByteArrayPtr ba = new MemoryByteArray(&(input_buffer[0]), file_size); + FontFactoryPtr factory = FontFactory::getInstance(); + + FontBuilderArray font_builder_array; + factory->loadFontsForBuilding(ba, &font_builder_array); + EXPECT_GT(font_builder_array.size(), static_cast(0)); + FontBuilderPtr font_builder = font_builder_array[0]; + + // ensure the builder is not bogus + EXPECT_TRUE(font_builder != NULL); + TableBuilderMap* builder_map = font_builder->tableBuilders(); + EXPECT_TRUE(builder_map != NULL); + for (TableBuilderMap::iterator i = builder_map->begin(), + e = builder_map->end(); i != e; ++i) { + EXPECT_TRUE(i->second != NULL); + if (i->second == NULL) { + char tag[5] = {0}; + memcpy(tag, &(i->first), 4); + fprintf(stderr, "tag %s does not have valid builder\n", tag); + } + } + + IntegerSet builder_tags; + font_builder->tableBuilderTags(&builder_tags); + FontHeaderTableBuilderPtr header_builder = + down_cast( + font_builder->getTableBuilder(Tag::head)); + int64_t mod_date = header_builder->modified(); + header_builder->setModified(mod_date + 1); + FontPtr font; + font.attach(font_builder->build()); + + // ensure every table had a builder + TableMap* table_map = font->tables(); + for (TableMap::iterator i = table_map->begin(), e = table_map->end(); + i != e; ++i) { + TablePtr table = (*i).second; + TableHeaderPtr header = table->header(); + EXPECT_TRUE(builder_tags.find(header->tag()) != builder_tags.end()); + builder_tags.erase(header->tag()); + } + EXPECT_TRUE(builder_tags.empty()); + + FontHeaderTablePtr header = down_cast( + font->table(Tag::head)); + int64_t after_mod_date = header->modified(); + EXPECT_EQ(mod_date + 1, after_mod_date); + return true; +} + +} // namespace sfntly diff --git a/test/otf_basic_editing_test.h b/test/otf_basic_editing_test.h new file mode 100644 index 0000000..b3abfad --- /dev/null +++ b/test/otf_basic_editing_test.h @@ -0,0 +1,26 @@ +/* + * 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_TEST_OTF_BASIC_EDITING_TEST_H_ +#define TYPOGRAPHY_FONT_SFNTLY_SRC_TEST_OTF_BASIC_EDITING_TEST_H_ + +namespace sfntly { + +bool testOTFBasicEditing(); + +} // namespace sfntly + +#endif // TYPOGRAPHY_FONT_SFNTLY_SRC_TEST_OTF_BASIC_EDITING_TEST_H_ diff --git a/test/smart_pointer_test.cc b/test/smart_pointer_test.cc new file mode 100644 index 0000000..8bc9f99 --- /dev/null +++ b/test/smart_pointer_test.cc @@ -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. + */ + +#include "gtest/gtest.h" +#define ENABLE_OBJECT_COUNTER +#include "sfntly/port/refcount.h" +#include "test/smart_pointer_test.h" + +using sfntly::RefCounted; +using sfntly::Ptr; + +class Foo : public RefCounted { +public: // put in something to make sure it's not empty + int foo_; + int foo() { return foo_; } +}; + +bool testSmartPointer() { + // scope out allocation + { + Ptr p1; + p1 = new Foo(); + EXPECT_EQ(1, p1->ref_count_); + EXPECT_EQ(1, RefCounted::object_counter_); + + Ptr p2; + p2 = p1; + EXPECT_EQ(2, p1->ref_count_); + EXPECT_EQ(2, p2->ref_count_); + EXPECT_EQ(1, RefCounted::object_counter_); + + Ptr p3; + p3 = p1; + EXPECT_EQ(3, p1->ref_count_); + EXPECT_EQ(3, p2->ref_count_); + EXPECT_EQ(3, p3->ref_count_); + EXPECT_EQ(1, RefCounted::object_counter_); + + p2 = new Foo(); + EXPECT_EQ(2, p1->ref_count_); + EXPECT_EQ(1, p2->ref_count_); + EXPECT_EQ(2, p3->ref_count_); + EXPECT_EQ(2, RefCounted::object_counter_); + + p3.release(); + EXPECT_EQ(1, p1->ref_count_); + EXPECT_EQ(NULL, p3.p_); + EXPECT_EQ(2, RefCounted::object_counter_); + + p2 = NULL; + EXPECT_EQ(1, RefCounted::object_counter_); + + p1 = p1; + EXPECT_EQ(1, p1->ref_count_); + EXPECT_EQ(1, RefCounted::object_counter_); + + p1 = &(*p1); + EXPECT_EQ(1, p1->ref_count_); + EXPECT_EQ(1, RefCounted::object_counter_); + } + EXPECT_EQ(0, RefCounted::object_counter_); + return true; +} diff --git a/test/smart_pointer_test.h b/test/smart_pointer_test.h new file mode 100644 index 0000000..ebc0a1f --- /dev/null +++ b/test/smart_pointer_test.h @@ -0,0 +1,22 @@ +/* + * 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_TEST_SMART_POINTER_TEST_H_ +#define TYPOGRAPHY_FONT_SFNTLY_SRC_TEST_SMART_POINTER_TEST_H_ + +bool testSmartPointer(); + +#endif // TYPOGRAPHY_FONT_SFNTLY_SRC_TEST_SMART_POINTER_TEST_H_ -- cgit v1.2.3 From 0e411afcef9fc211b3f8f70d31bc1dfa4c0f85d3 Mon Sep 17 00:00:00 2001 From: "arthurhsu@google.com" Date: Mon, 27 Jun 2011 21:23:55 +0000 Subject: Added a preprocessor flag SFNTLY_NO_EXCEPTION to disable exception handling. Fixed the code to make GCC -Wall -Werror flags happy. git-svn-id: http://sfntly.googlecode.com/svn/trunk/cpp/src@3 672e30a5-4c29-85ac-ac6d-611c735e0a51 --- sfntly/cmap_table.cc | 2 +- sfntly/data/byte_array.cc | 12 +++++++ sfntly/data/font_input_stream.cc | 4 +-- sfntly/data/font_output_stream.cc | 2 +- sfntly/data/memory_byte_array.cc | 2 +- sfntly/data/readable_font_data.cc | 8 +++-- sfntly/font.cc | 16 ++++++++-- sfntly/glyph_table.cc | 8 +++-- sfntly/horizontal_metrics_table.cc | 12 +++++++ sfntly/loca_table.cc | 24 ++++++++++++++ sfntly/name_table.cc | 2 +- sfntly/port/exception_type.h | 4 +++ sfntly/port/file_input_stream.cc | 26 ++++++++++++++- sfntly/port/type.h | 2 +- sfntly/table.cc | 12 +++---- sfntly/tools/subsetter/glyph_table_subsetter.cc | 8 +++++ test/byte_array_test.cc | 8 ++--- test/font_data_test.cc | 4 +-- test/smart_pointer_test.cc | 42 ++++++++++++------------- 19 files changed, 150 insertions(+), 48 deletions(-) diff --git a/sfntly/cmap_table.cc b/sfntly/cmap_table.cc index 11b2b50..79b083a 100644 --- a/sfntly/cmap_table.cc +++ b/sfntly/cmap_table.cc @@ -445,7 +445,7 @@ CALLER_ATTACH FontDataTable* CMapTable::CMapFormat2::Builder::subBuildTable( * CMapTable::Iterator class ******************************************************************************/ CMapTable::CMapIterator::CMapIterator(CMapTable* table, CMapFilter* filter) - : table_index_(0), table_(table), filter_(filter) {} + : table_index_(0), filter_(filter), table_(table) {} bool CMapTable::CMapIterator::hasNext() { if (!filter_) { diff --git a/sfntly/data/byte_array.cc b/sfntly/data/byte_array.cc index 3511bfe..d5af22e 100644 --- a/sfntly/data/byte_array.cc +++ b/sfntly/data/byte_array.cc @@ -121,7 +121,11 @@ int32_t ByteArray::copyTo(int32_t dst_offset, ByteArray* array, while ((bytes_read = get(index + src_offset, &b, 0, buffer_length)) > 0) { int bytes_written = array->put(index + dst_offset, &b, 0, bytes_read); if (bytes_written != bytes_read) { +#if defined (SFNTLY_NO_EXCEPTION) + return 0; +#else throw IOException("Error writing bytes."); +#endif } index += bytes_read; remaining_length -= bytes_read; @@ -155,7 +159,11 @@ bool ByteArray::copyFrom(InputStream* is, int32_t length) { while ((bytes_read = is->read(&b, 0, buffer_length)) > 0) { if (put(index, &b, 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; @@ -172,7 +180,11 @@ bool ByteArray::copyFrom(InputStream* is) { while ((bytes_read = is->read(&b, 0, buffer_length)) > 0) { if (put(index, &b, 0, bytes_read) != bytes_read) { +#if defined (SFNTLY_NO_EXCEPTION) + return 0; +#else throw IOException("Error writing bytes."); +#endif } index += bytes_read; } diff --git a/sfntly/data/font_input_stream.cc b/sfntly/data/font_input_stream.cc index 8b1d798..97c5860 100644 --- a/sfntly/data/font_input_stream.cc +++ b/sfntly/data/font_input_stream.cc @@ -21,11 +21,11 @@ namespace sfntly { FontInputStream::FontInputStream(InputStream* is) - : position_(0), length_(0), bounded_(false), stream_(is) { + : stream_(is), position_(0), length_(0), bounded_(false) { } FontInputStream::FontInputStream(InputStream* is, size_t length) - : position_(0), length_(length), bounded_(false), stream_(is) { + : stream_(is), position_(0), length_(length), bounded_(false) { } FontInputStream::~FontInputStream() { diff --git a/sfntly/data/font_output_stream.cc b/sfntly/data/font_output_stream.cc index d5eaa82..86a153c 100644 --- a/sfntly/data/font_output_stream.cc +++ b/sfntly/data/font_output_stream.cc @@ -22,7 +22,7 @@ namespace sfntly { FontOutputStream::FontOutputStream(OutputStream* os) - : position_(0), stream_(os) { + : stream_(os), position_(0) { } FontOutputStream::~FontOutputStream() { diff --git a/sfntly/data/memory_byte_array.cc b/sfntly/data/memory_byte_array.cc index 1e85ebd..528979a 100644 --- a/sfntly/data/memory_byte_array.cc +++ b/sfntly/data/memory_byte_array.cc @@ -22,7 +22,7 @@ namespace sfntly { // Note: this constructor can fail under low-memory situation MemoryByteArray::MemoryByteArray(int32_t length) - : ByteArray(0, length), allocated_(true), b_(NULL) { + : ByteArray(0, length), b_(NULL), allocated_(true) { } MemoryByteArray::MemoryByteArray(byte_t* b, int32_t buffer_length) diff --git a/sfntly/data/readable_font_data.cc b/sfntly/data/readable_font_data.cc index 3073b03..fa7279e 100644 --- a/sfntly/data/readable_font_data.cc +++ b/sfntly/data/readable_font_data.cc @@ -23,16 +23,16 @@ namespace sfntly { ReadableFontData::~ReadableFontData() {} ReadableFontData::ReadableFontData(ByteArray* array) - : FontData(array), checksum_(0), checksum_set_(false) { + : FontData(array), checksum_set_(false), checksum_(0) { } ReadableFontData::ReadableFontData(ReadableFontData* data, int32_t offset) - : FontData(data, offset), checksum_(0), checksum_set_(false) { + : FontData(data, offset), checksum_set_(false), checksum_(0) { } ReadableFontData::ReadableFontData(ReadableFontData* data, int32_t offset, int32_t length) - : FontData(data, offset, length), checksum_(0), checksum_set_(false) { + : FontData(data, offset, length), checksum_set_(false), checksum_(0) { } int64_t ReadableFontData::checksum() { @@ -133,9 +133,11 @@ int64_t ReadableFontData::readULong(int32_t index) { 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 ((int32_t)ulong) & ~0x80000000; } diff --git a/sfntly/font.cc b/sfntly/font.cc index 1ef222a..46dc48c 100644 --- a/sfntly/font.cc +++ b/sfntly/font.cc @@ -118,8 +118,8 @@ const int32_t Font::Offset::kTableRecordSize = 16; Font::~Font() {} Font::Font(FontFactory* factory, int32_t sfnt_version, ByteVector* digest, - TableMap* tables) : - sfnt_version_(sfnt_version), factory_(factory) { + TableMap* tables) + : factory_(factory), sfnt_version_(sfnt_version) { // non-trivial assignments that makes debugging hard if placed in // initialization list digest_ = *digest; @@ -223,7 +223,11 @@ void Font::serializeTables(FontOutputStream* fos, record != end_of_headers; ++record) { TablePtr target_table = table((*record)->tag()); if (target_table == NULL) { +#if defined (SFNTLY_NO_EXCEPTION) + return; +#else throw IOException("Table out of sync with font header."); +#endif } int32_t table_size = target_table->serialize(fos); int32_t filler_size = ((table_size + 3) & ~3) - table_size; @@ -462,19 +466,27 @@ void Font::Builder::buildTablesFromBuilders(TableBuilderMap* builder_map, builder != builder_end; ++builder) { TablePtr table; if (builder->second->readyToBuild()) { +#if !defined (SFNTLY_NO_EXCEPTION) try { +#endif table.attach(down_cast(builder->second->build())); +#if !defined (SFNTLY_NO_EXCEPTION) } catch(IOException& e) { std::string builder_string = "Unable to build table - "; builder_string += typeid(builder->second).name(); builder_string += e.what(); throw RuntimeException(builder_string.c_str()); } +#endif } if (table == NULL) { +#if defined (SFNTLY_NO_EXCEPTION) + return; +#else std::string builder_string = "Unable to build table - "; builder_string += typeid(builder->second).name(); throw RuntimeException(builder_string.c_str()); +#endif } table_map->insert(TableMapEntry(table->header()->tag(), table)); } diff --git a/sfntly/glyph_table.cc b/sfntly/glyph_table.cc index 72f6945..4cd6436 100644 --- a/sfntly/glyph_table.cc +++ b/sfntly/glyph_table.cc @@ -109,8 +109,12 @@ void GlyphTable::Builder::initialize(ReadableFontData* data, const IntegerList& loca) { if (data != NULL) { if (loca_.empty()) { +#if defined (SFNTLY_NO_EXCEPTION) + return; +#else throw IllegalStateException( "Loca values not set - unable to parse glyph data."); +#endif } int32_t loca_value; int32_t last_loca_value = loca[0]; @@ -513,8 +517,8 @@ CALLER_ATTACH FontDataTable* * GlyphTable::CompositeGlyph and its builder ******************************************************************************/ GlyphTable::CompositeGlyph::CompositeGlyph(ReadableFontData* data) - : instruction_size_(0), instructions_offset_(0), - GlyphTable::Glyph(data, GlyphType::kComposite) { + : GlyphTable::Glyph(data, GlyphType::kComposite), + instruction_size_(0), instructions_offset_(0) { parseData(); } diff --git a/sfntly/horizontal_metrics_table.cc b/sfntly/horizontal_metrics_table.cc index 4ed2d43..d6beab1 100644 --- a/sfntly/horizontal_metrics_table.cc +++ b/sfntly/horizontal_metrics_table.cc @@ -54,7 +54,11 @@ int32_t HorizontalMetricsTable::numberOfLSBs() { int32_t HorizontalMetricsTable::hMetricAdvanceWidth(int32_t entry) { if (entry > num_hmetrics_) { +#if defined (SFNTLY_NO_EXCEPTION) + return 0; +#else throw IndexOutOfBoundException(); +#endif } int32_t offset = Offset::kHMetricsStart + (entry * Offset::kHMetricsSize) + Offset::kHMetricsAdvanceWidth; @@ -63,7 +67,11 @@ int32_t HorizontalMetricsTable::hMetricAdvanceWidth(int32_t entry) { int32_t HorizontalMetricsTable::hMetricLSB(int32_t entry) { if (entry > num_hmetrics_) { +#if defined (SFNTLY_NO_EXCEPTION) + return 0; +#else throw IndexOutOfBoundException(); +#endif } int32_t offset = Offset::kHMetricsStart + (entry * Offset::kHMetricsSize) + Offset::kHMetricsLeftSideBearing; @@ -72,7 +80,11 @@ int32_t HorizontalMetricsTable::hMetricLSB(int32_t entry) { int32_t HorizontalMetricsTable::lsbTableEntry(int32_t entry) { if (entry > num_hmetrics_) { +#if defined (SFNTLY_NO_EXCEPTION) + return 0; +#else throw IndexOutOfBoundException(); +#endif } int32_t offset = Offset::kHMetricsStart + (entry * Offset::kHMetricsSize) + Offset::kLeftSideBearingSize; diff --git a/sfntly/loca_table.cc b/sfntly/loca_table.cc index 5bb5dd4..1cd1d92 100644 --- a/sfntly/loca_table.cc +++ b/sfntly/loca_table.cc @@ -36,14 +36,22 @@ int32_t LocaTable::numGlyphs() { int32_t LocaTable::glyphOffset(int32_t glyph_id) { if (glyph_id < 0 || glyph_id >= num_glyphs_) { +#if defined (SFNTLY_NO_EXCEPTION) + return 0; +#else throw IndexOutOfBoundException("Glyph ID is out of bounds."); +#endif } 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) + return 0; +#else throw IndexOutOfBoundException("Glyph ID is out of bounds."); +#endif } return loca(glyph_id + 1) - loca(glyph_id); } @@ -54,7 +62,11 @@ int32_t LocaTable::numLocas() { int32_t LocaTable::loca(int32_t index) { if (index > num_glyphs_) { +#if defined (SFNTLY_NO_EXCEPTION) + return 0; +#else throw IndexOutOfBoundException(); +#endif } if (version_ == IndexToLocFormat::kShortOffset) { return 2 * data_->readShort(index * DataSize::kUSHORT); @@ -102,7 +114,11 @@ LocaTable::Builder::~Builder() {} void LocaTable::Builder::initialize(ReadableFontData* data) { if (data) { if (numGlyphs() < 0) { +#if defined (SFNTLY_NO_EXCEPTION) + return; +#else throw IllegalStateException("numglyphs not set on LocaTable Builder."); +#endif } LocaTablePtr table = new LocaTable(header(), data, format_version_, num_glyphs_); @@ -140,14 +156,22 @@ void LocaTable::Builder::setLocaList(IntegerList* list) { int32_t LocaTable::Builder::glyphOffset(int32_t glyph_id) { if (glyph_id < 0 || glyph_id > (num_glyphs_ + 1)) { +#if defined (SFNTLY_NO_EXCEPTION) + return 0; +#else throw IndexOutOfBoundException("Glyph ID is out of bounds."); +#endif } return loca(glyph_id); } int32_t LocaTable::Builder::glyphLength(int32_t glyph_id) { if (glyph_id < 0 || glyph_id > (num_glyphs_ + 1)) { +#if defined (SFNTLY_NO_EXCEPTION) + return 0; +#else throw IndexOutOfBoundException("Glyph ID is out of bounds."); +#endif } return loca(glyph_id + 1) - loca(glyph_id); } diff --git a/sfntly/name_table.cc b/sfntly/name_table.cc index e303d6d..b344bfa 100644 --- a/sfntly/name_table.cc +++ b/sfntly/name_table.cc @@ -549,7 +549,7 @@ NameTable::NameEntryBuilder::~NameEntryBuilder() {} ******************************************************************************/ NameTable::NameEntryIterator::NameEntryIterator(NameTable* table, NameEntryFilter* filter) : - table_(table), filter_(filter), name_index_(0) { + table_(table), name_index_(0), filter_(filter) { } bool NameTable::NameEntryIterator::hasNext() { diff --git a/sfntly/port/exception_type.h b/sfntly/port/exception_type.h index 56a93ff..2ba199a 100644 --- a/sfntly/port/exception_type.h +++ b/sfntly/port/exception_type.h @@ -19,6 +19,8 @@ #ifndef TYPOGRAPHY_FONT_SFNTLY_SRC_SFNTLY_PORT_EXCEPTION_TYPE_H_ #define TYPOGRAPHY_FONT_SFNTLY_SRC_SFNTLY_PORT_EXCEPTION_TYPE_H_ +#if !defined (SFNTLY_NO_EXCEPTION) + #include #include @@ -104,4 +106,6 @@ class IllegalStateException : public Exception { } // namespace sfntly +#endif // #if !defined (SFNTLY_NO_EXCEPTION) + #endif // TYPOGRAPHY_FONT_SFNTLY_SRC_SFNTLY_PORT_EXCEPTION_TYPE_H_ diff --git a/sfntly/port/file_input_stream.cc b/sfntly/port/file_input_stream.cc index 7505ab7..dcb37f7 100644 --- a/sfntly/port/file_input_stream.cc +++ b/sfntly/port/file_input_stream.cc @@ -23,7 +23,7 @@ namespace sfntly { -FileInputStream::FileInputStream() : file_(NULL), length_(0), position_(0) { +FileInputStream::FileInputStream() : file_(NULL), position_(0), length_(0) { } FileInputStream::~FileInputStream() { @@ -73,10 +73,18 @@ bool FileInputStream::markSupported() { int32_t FileInputStream::read() { if (!file_) { +#if defined (SFNTLY_NO_EXCEPTION) + return 0; +#else throw IOException("no opened file"); +#endif } if (feof(file_)) { +#if defined (SFNTLY_NO_EXCEPTION) + return 0; +#else throw IOException("eof reached"); +#endif } byte_t value; fread(&value, 1, 1, file_); @@ -92,10 +100,18 @@ int32_t FileInputStream::read(ByteVector* b, int32_t offset, int32_t length) { assert(b); assert(b->size() >= (size_t)(offset + length)); if (!file_) { +#if defined (SFNTLY_NO_EXCEPTION) + return 0; +#else throw IOException("no opened file"); +#endif } if (feof(file_)) { +#if defined (SFNTLY_NO_EXCEPTION) + return 0; +#else throw IOException("eof reached"); +#endif } size_t read_count = std::min(length_ - position_, length); int32_t actual_read = fread(&((*b)[offset]), 1, read_count, file_); @@ -109,7 +125,11 @@ void FileInputStream::reset() { int64_t FileInputStream::skip(int64_t n) { if (!file_) { +#if defined (SFNTLY_NO_EXCEPTION) + return 0; +#else throw IOException("no opened file"); +#endif } if (n < 0) { return 0; @@ -128,7 +148,11 @@ 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) + return; +#else throw IOException("no opened file"); +#endif } size_t unread_count = std::min(position_, length); fseek(file_, position_ - unread_count, SEEK_SET); diff --git a/sfntly/port/type.h b/sfntly/port/type.h index ab55b97..25b697e 100644 --- a/sfntly/port/type.h +++ b/sfntly/port/type.h @@ -78,7 +78,7 @@ inline To down_cast(From* f) { // so we only accept pointers } #if !defined(WIN32) - #define UNREFERENCED_PARAMETER(p) + #define UNREFERENCED_PARAMETER(p) do { (void)p; } while (0) #endif #endif // TYPOGRAPHY_FONT_SFNTLY_SRC_SFNTLY_PORT_TYPE_H_ diff --git a/sfntly/table.cc b/sfntly/table.cc index 1215f50..856f32e 100644 --- a/sfntly/table.cc +++ b/sfntly/table.cc @@ -74,19 +74,19 @@ void Table::setFont(Font* font) { * Table::Header class ******************************************************************************/ Table::Header::Header(int32_t tag) - : tag_(tag), checksum_(0), checksum_valid_(false), offset_(0), length_(0), - offset_valid_(false) { + : tag_(tag), offset_(0), length_(0), offset_valid_(false), checksum_(0), + checksum_valid_(false) { } Table::Header::Header(int32_t tag, int32_t length) - : tag_(tag), checksum_(0), checksum_valid_(false), offset_(0), - length_(length), offset_valid_(false) { + : tag_(tag), offset_(0), length_(length), offset_valid_(false), + checksum_(0), checksum_valid_(false) { } Table::Header::Header(int32_t tag, int64_t checksum, int32_t offset, int32_t length) - : tag_(tag), checksum_(checksum), checksum_valid_(true), offset_(offset), - length_(length), offset_valid_(true) { + : tag_(tag), offset_(offset), length_(length), offset_valid_(true), + checksum_(checksum), checksum_valid_(true) { } Table::Header::~Header() {} diff --git a/sfntly/tools/subsetter/glyph_table_subsetter.cc b/sfntly/tools/subsetter/glyph_table_subsetter.cc index 93a8852..04d0c48 100644 --- a/sfntly/tools/subsetter/glyph_table_subsetter.cc +++ b/sfntly/tools/subsetter/glyph_table_subsetter.cc @@ -44,7 +44,11 @@ bool GlyphTableSubsetter::subset(Subsetter* subsetter, Font* font, GlyphTablePtr glyph_table = down_cast(font->table(Tag::glyf)); LocaTablePtr loca_table = down_cast(font->table(Tag::loca)); if (glyph_table == NULL || loca_table == NULL) { +#if defined (SFNTLY_NO_EXCEPTION) + return false; +#else throw RuntimeException("Font to subset is not valid."); +#endif } GlyphTableBuilderPtr glyph_table_builder; @@ -54,7 +58,11 @@ bool GlyphTableSubsetter::subset(Subsetter* subsetter, Font* font, loca_table_builder.attach(down_cast( font_builder->newTableBuilder(Tag::loca))); if (glyph_table_builder == NULL || loca_table_builder == NULL) { +#if defined (SFNTLY_NO_EXCEPTION) + return false; +#else throw RuntimeException("Builder for subset is not valid."); +#endif } GlyphTable::GlyphBuilderList* glyph_builders = glyph_table_builder->glyphBuilders(); diff --git a/test/byte_array_test.cc b/test/byte_array_test.cc index d2c865f..7c6efa9 100644 --- a/test/byte_array_test.cc +++ b/test/byte_array_test.cc @@ -112,10 +112,10 @@ bool byteArrayTester(ByteArray* ba) { } // namespace byte_array_test bool testMemoryByteArray() { - for (int32_t i = 0; + for (size_t i = 0; i < sizeof(byte_array_test::BYTE_ARRAY_SIZES) / sizeof(int32_t); ++i) { int32_t size = byte_array_test::BYTE_ARRAY_SIZES[i]; - fprintf(stderr, "fixed mem: iteration %d, size %d\n", i, size); + fprintf(stderr, "fixed mem: iteration %ld, size %d\n", i, size); ByteArrayPtr ba = new MemoryByteArray(size); byte_array_test::fillTestByteArray(ba, size); EXPECT_TRUE(byte_array_test::byteArrayTester(ba)); @@ -124,10 +124,10 @@ bool testMemoryByteArray() { } bool testGrowableMemoryByteArray() { - for (int32_t i = 0; + for (size_t i = 0; i < sizeof(byte_array_test::BYTE_ARRAY_SIZES) / sizeof(int32_t); ++i) { int32_t size = byte_array_test::BYTE_ARRAY_SIZES[i]; - fprintf(stderr, "growable mem: iteration %d, size %d\n", i, size); + fprintf(stderr, "growable mem: iteration %ld, size %d\n", i, size); ByteArrayPtr ba = new GrowableMemoryByteArray(); byte_array_test::fillTestByteArray(ba, size); EXPECT_TRUE(byte_array_test::byteArrayTester(ba)); diff --git a/test/font_data_test.cc b/test/font_data_test.cc index 1e81626..ad30522 100644 --- a/test/font_data_test.cc +++ b/test/font_data_test.cc @@ -186,7 +186,7 @@ void slicingWriteTest(ReadableFontData* rfd, WritableFontData* wfd) { } bool testReadableFontData() { - for (int32_t i = 0; i < sizeof(BYTE_ARRAY_SIZES) / sizeof(int32_t); ++i) { + for (size_t i = 0; i < sizeof(BYTE_ARRAY_SIZES) / sizeof(int32_t); ++i) { int32_t size = BYTE_ARRAY_SIZES[i]; ByteArrayPtr ba = new MemoryByteArray(size); fillTestByteArray(ba, size); @@ -197,7 +197,7 @@ bool testReadableFontData() { } bool testWritableFontData() { - for (int32_t i = 0; i < sizeof(BYTE_ARRAY_SIZES) / sizeof(int32_t); ++i) { + for (size_t i = 0; i < sizeof(BYTE_ARRAY_SIZES) / sizeof(int32_t); ++i) { int32_t size = BYTE_ARRAY_SIZES[i]; ByteArrayPtr ba = new MemoryByteArray(size); fillTestByteArray(ba, size); diff --git a/test/smart_pointer_test.cc b/test/smart_pointer_test.cc index 8bc9f99..a35e289 100644 --- a/test/smart_pointer_test.cc +++ b/test/smart_pointer_test.cc @@ -33,44 +33,44 @@ bool testSmartPointer() { { Ptr p1; p1 = new Foo(); - EXPECT_EQ(1, p1->ref_count_); - EXPECT_EQ(1, RefCounted::object_counter_); + EXPECT_EQ(size_t(1), p1->ref_count_); + EXPECT_EQ(size_t(1), RefCounted::object_counter_); Ptr p2; p2 = p1; - EXPECT_EQ(2, p1->ref_count_); - EXPECT_EQ(2, p2->ref_count_); - EXPECT_EQ(1, RefCounted::object_counter_); + EXPECT_EQ(size_t(2), p1->ref_count_); + EXPECT_EQ(size_t(2), p2->ref_count_); + EXPECT_EQ(size_t(1), RefCounted::object_counter_); Ptr p3; p3 = p1; - EXPECT_EQ(3, p1->ref_count_); - EXPECT_EQ(3, p2->ref_count_); - EXPECT_EQ(3, p3->ref_count_); - EXPECT_EQ(1, RefCounted::object_counter_); + EXPECT_EQ(size_t(3), p1->ref_count_); + EXPECT_EQ(size_t(3), p2->ref_count_); + EXPECT_EQ(size_t(3), p3->ref_count_); + EXPECT_EQ(size_t(1), RefCounted::object_counter_); p2 = new Foo(); - EXPECT_EQ(2, p1->ref_count_); - EXPECT_EQ(1, p2->ref_count_); - EXPECT_EQ(2, p3->ref_count_); - EXPECT_EQ(2, RefCounted::object_counter_); + EXPECT_EQ(size_t(2), p1->ref_count_); + EXPECT_EQ(size_t(1), p2->ref_count_); + EXPECT_EQ(size_t(2), p3->ref_count_); + EXPECT_EQ(size_t(2), RefCounted::object_counter_); p3.release(); - EXPECT_EQ(1, p1->ref_count_); + EXPECT_EQ(size_t(1), p1->ref_count_); EXPECT_EQ(NULL, p3.p_); - EXPECT_EQ(2, RefCounted::object_counter_); + EXPECT_EQ(size_t(2), RefCounted::object_counter_); p2 = NULL; - EXPECT_EQ(1, RefCounted::object_counter_); + EXPECT_EQ(size_t(1), RefCounted::object_counter_); p1 = p1; - EXPECT_EQ(1, p1->ref_count_); - EXPECT_EQ(1, RefCounted::object_counter_); + EXPECT_EQ(size_t(1), p1->ref_count_); + EXPECT_EQ(size_t(1), RefCounted::object_counter_); p1 = &(*p1); - EXPECT_EQ(1, p1->ref_count_); - EXPECT_EQ(1, RefCounted::object_counter_); + EXPECT_EQ(size_t(1), p1->ref_count_); + EXPECT_EQ(size_t(1), RefCounted::object_counter_); } - EXPECT_EQ(0, RefCounted::object_counter_); + EXPECT_EQ(size_t(0), RefCounted::object_counter_); return true; } -- cgit v1.2.3 From 44bcb4a1475aeb0c4bce1cba0c30f5ee01eb50d9 Mon Sep 17 00:00:00 2001 From: "arthurhsu@google.com" Date: Fri, 8 Jul 2011 23:09:32 +0000 Subject: Update static const ints to enums so that these enums can be used in switch-case. There are two exceptions: 1. if original Java code uses static const int, we keep it that way. 2. C++ compilers may not support 64-bit enum so we need to define them as static const uint64_t git-svn-id: http://sfntly.googlecode.com/svn/trunk/cpp/src@6 672e30a5-4c29-85ac-ac6d-611c735e0a51 --- sfntly/cmap_table.cc | 86 ----- sfntly/cmap_table.h | 236 ++++++------ sfntly/data/font_data.cc | 17 - sfntly/data/font_data.h | 34 +- sfntly/font.cc | 76 ---- sfntly/font.h | 146 ++++---- sfntly/font_factory.cc | 8 - sfntly/font_factory.h | 24 +- sfntly/font_header_table.cc | 30 -- sfntly/font_header_table.h | 54 +-- sfntly/glyph_table.cc | 15 - sfntly/glyph_table.h | 48 +-- sfntly/horizontal_header_table.cc | 17 - sfntly/horizontal_header_table.h | 28 +- sfntly/horizontal_metrics_table.cc | 9 - sfntly/horizontal_metrics_table.h | 16 +- sfntly/maximum_profile_table.cc | 19 - sfntly/maximum_profile_table.h | 36 +- sfntly/name_table.cc | 372 ------------------ sfntly/name_table.h | 750 +++++++++++++++++++------------------ sfntly/os2_table.cc | 92 ----- sfntly/os2_table.h | 188 +++++----- 22 files changed, 809 insertions(+), 1492 deletions(-) diff --git a/sfntly/cmap_table.cc b/sfntly/cmap_table.cc index 79b083a..e73b657 100644 --- a/sfntly/cmap_table.cc +++ b/sfntly/cmap_table.cc @@ -23,93 +23,7 @@ namespace sfntly { -/****************************************************************************** - * Constants - ******************************************************************************/ const int32_t CMapTable::NOTDEF = 0; -const int32_t CMapTable::Offset::kVersion = 0; -const int32_t CMapTable::Offset::kNumTables = 2; -const int32_t CMapTable::Offset::kEncodingRecordStart = 4; -const int32_t CMapTable::Offset::kEncodingRecordPlatformId = 0; -const int32_t CMapTable::Offset::kEncodingRecordEncodingId = 2; -const int32_t CMapTable::Offset::kEncodingRecordOffset = 4; -const int32_t CMapTable::Offset::kEncodingRecordSize = 8; -const int32_t CMapTable::Offset::kFormat = 0; -const int32_t CMapTable::Offset::kFormat0Format = 0; -const int32_t CMapTable::Offset::kFormat0Length = 2; -const int32_t CMapTable::Offset::kFormat0Language = 4; -const int32_t CMapTable::Offset::kFormat0GlyphIdArray = 6; -const int32_t CMapTable::Offset::kFormat2Format = 0; -const int32_t CMapTable::Offset::kFormat2Length = 2; -const int32_t CMapTable::Offset::kFormat2Language = 4; -const int32_t CMapTable::Offset::kFormat2SubHeaderKeys = 6; -const int32_t CMapTable::Offset::kFormat2SubHeaders = 518; -const int32_t CMapTable::Offset::kFormat2SubHeader_firstCode = 0; -const int32_t CMapTable::Offset::kFormat2SubHeader_entryCount = 2; -const int32_t CMapTable::Offset::kFormat2SubHeader_idDelta = 4; -const int32_t CMapTable::Offset::kFormat2SubHeader_idRangeOffset = 6; -const int32_t CMapTable::Offset::kFormat2SubHeader_structLength = 8; -const int32_t CMapTable::Offset::kFormat4Format = 0; -const int32_t CMapTable::Offset::kFormat4Length = 2; -const int32_t CMapTable::Offset::kFormat4Language = 4; -const int32_t CMapTable::Offset::kFormat4SegCountX2 = 6; -const int32_t CMapTable::Offset::kFormat4SearchRange = 8; -const int32_t CMapTable::Offset::kFormat4EntrySelector = 10; -const int32_t CMapTable::Offset::kFormat4RangeShift = 12; -const int32_t CMapTable::Offset::kFormat4EndCount = 14; -const int32_t CMapTable::Offset::kFormat6Format = 0; -const int32_t CMapTable::Offset::kFormat6Length = 2; -const int32_t CMapTable::Offset::kFormat6Language = 4; -const int32_t CMapTable::Offset::kFormat6FirstCode = 6; -const int32_t CMapTable::Offset::kFormat6EntryCount = 8; -const int32_t CMapTable::Offset::kFormat6GlyphIdArray = 10; -const int32_t CMapTable::Offset::kFormat8Format = 0; -const int32_t CMapTable::Offset::kFormat8Length = 4; -const int32_t CMapTable::Offset::kFormat8Language = 8; -const int32_t CMapTable::Offset::kFormat8Is32 = 12; -const int32_t CMapTable::Offset::kFormat8nGroups204 = 8204; -const int32_t CMapTable::Offset::kFormat8Groups208 = 8208; -const int32_t CMapTable::Offset::kFormat8Group_startCharCode = 0; -const int32_t CMapTable::Offset::kFormat8Group_endCharCode = 4; -const int32_t CMapTable::Offset::kFormat8Group_startGlyphId = 8; -const int32_t CMapTable::Offset::kFormat8Group_structLength = 12; -const int32_t CMapTable::Offset::kFormat10Format = 0; -const int32_t CMapTable::Offset::kFormat10Length = 4; -const int32_t CMapTable::Offset::kFormat10Language = 8; -const int32_t CMapTable::Offset::kFormat10StartCharCode = 12; -const int32_t CMapTable::Offset::kFormat10NumChars = 16; -const int32_t CMapTable::Offset::kFormat10Glyphs0 = 20; -const int32_t CMapTable::Offset::kFormat12Format = 0; -const int32_t CMapTable::Offset::kFormat12Length = 4; -const int32_t CMapTable::Offset::kFormat12Language = 8; -const int32_t CMapTable::Offset::kFormat12nGroups = 12; -const int32_t CMapTable::Offset::kFormat12Groups = 16; -const int32_t CMapTable::Offset::kFormat12Groups_structLength = 12; -const int32_t CMapTable::Offset::kFormat12_startCharCode = 0; -const int32_t CMapTable::Offset::kFormat12_endCharCode = 4; -const int32_t CMapTable::Offset::kFormat12_startGlyphId = 8; -const int32_t CMapTable::Offset::kFormat13Format = 0; -const int32_t CMapTable::Offset::kFormat13Length = 4; -const int32_t CMapTable::Offset::kFormat13Language = 8; -const int32_t CMapTable::Offset::kFormat13nGroups = 12; -const int32_t CMapTable::Offset::kFormat13Groups = 16; -const int32_t CMapTable::Offset::kFormat13Groups_structLength = 12; -const int32_t CMapTable::Offset::kFormat13_startCharCode = 0; -const int32_t CMapTable::Offset::kFormat13_endCharCode = 4; -const int32_t CMapTable::Offset::kFormat13_glyphId = 8; -const int32_t CMapTable::Offset::kFormat14Format = 0; -const int32_t CMapTable::Offset::kFormat14Length = 2; -const int32_t CMapTable::Offset::kLast = -1; - -const int32_t CMapTable::CMapFormat::kFormat0 = 0; -const int32_t CMapTable::CMapFormat::kFormat2 = 2; -const int32_t CMapTable::CMapFormat::kFormat4 = 4; -const int32_t CMapTable::CMapFormat::kFormat6 = 6; -const int32_t CMapTable::CMapFormat::kFormat8 = 8; -const int32_t CMapTable::CMapFormat::kFormat10 = 10; -const int32_t CMapTable::CMapFormat::kFormat12 = 12; -const int32_t CMapTable::CMapFormat::kFormat13 = 13; -const int32_t CMapTable::CMapFormat::kFormat14 = 14; /****************************************************************************** * CMapTable class diff --git a/sfntly/cmap_table.h b/sfntly/cmap_table.h index 9e9aa87..c13318e 100644 --- a/sfntly/cmap_table.h +++ b/sfntly/cmap_table.h @@ -27,127 +27,131 @@ 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 Table, public RefCounted { private: static const int32_t NOTDEF; struct Offset { - static const int32_t kVersion; - static const int32_t kNumTables; - static const int32_t kEncodingRecordStart; - - // offsets relative to the encoding record - static const int32_t kEncodingRecordPlatformId; - static const int32_t kEncodingRecordEncodingId; - static const int32_t kEncodingRecordOffset; - static const int32_t kEncodingRecordSize; - - static const int32_t kFormat; - - // Format 0: Byte encoding table - static const int32_t kFormat0Format; - static const int32_t kFormat0Length; - static const int32_t kFormat0Language; - static const int32_t kFormat0GlyphIdArray; - - // Format 2: High-byte mapping through table - static const int32_t kFormat2Format; - static const int32_t kFormat2Length; - static const int32_t kFormat2Language; - static const int32_t kFormat2SubHeaderKeys; - static const int32_t kFormat2SubHeaders; - // offset relative to the subHeader structure - static const int32_t kFormat2SubHeader_firstCode; - static const int32_t kFormat2SubHeader_entryCount; - static const int32_t kFormat2SubHeader_idDelta; - static const int32_t kFormat2SubHeader_idRangeOffset; - static const int32_t kFormat2SubHeader_structLength; - - // Format 4: Segment mapping to delta values - static const int32_t kFormat4Format; - static const int32_t kFormat4Length; - static const int32_t kFormat4Language; - static const int32_t kFormat4SegCountX2; - static const int32_t kFormat4SearchRange; - static const int32_t kFormat4EntrySelector; - static const int32_t kFormat4RangeShift; - static const int32_t kFormat4EndCount; - - // format 6: Trimmed table mapping - static const int32_t kFormat6Format; - static const int32_t kFormat6Length; - static const int32_t kFormat6Language; - static const int32_t kFormat6FirstCode; - static const int32_t kFormat6EntryCount; - static const int32_t kFormat6GlyphIdArray; - - // Format 8: mixed 16-bit and 32-bit coverage - static const int32_t kFormat8Format; - static const int32_t kFormat8Length; - static const int32_t kFormat8Language; - static const int32_t kFormat8Is32; - static const int32_t kFormat8nGroups204; - static const int32_t kFormat8Groups208; - // ofset relative to the group structure - static const int32_t kFormat8Group_startCharCode; - static const int32_t kFormat8Group_endCharCode; - static const int32_t kFormat8Group_startGlyphId; - static const int32_t kFormat8Group_structLength; - - // Format 10: Trimmed array - static const int32_t kFormat10Format; - static const int32_t kFormat10Length; - static const int32_t kFormat10Language; - static const int32_t kFormat10StartCharCode; - static const int32_t kFormat10NumChars; - static const int32_t kFormat10Glyphs0; - - // Format 12: Segmented coverage - static const int32_t kFormat12Format; - static const int32_t kFormat12Length; - static const int32_t kFormat12Language; - static const int32_t kFormat12nGroups; - static const int32_t kFormat12Groups; - static const int32_t kFormat12Groups_structLength; - // offsets within the group structure - static const int32_t kFormat12_startCharCode; - static const int32_t kFormat12_endCharCode; - static const int32_t kFormat12_startGlyphId; - - // Format 13: Last Resort Font - static const int32_t kFormat13Format; - static const int32_t kFormat13Length; - static const int32_t kFormat13Language; - static const int32_t kFormat13nGroups; - static const int32_t kFormat13Groups; - static const int32_t kFormat13Groups_structLength; - // offsets within the group structure - static const int32_t kFormat13_startCharCode; - static const int32_t kFormat13_endCharCode; - static const int32_t kFormat13_glyphId; - - // Format 14: Unicode Variation Sequences - static const int32_t kFormat14Format; - static const int32_t kFormat14Length; - - // TODO(stuartg): finish tables - // Default UVS Table - - // Non-default UVS Table - static const int32_t kLast; - }; - - // CMap subtable formats - struct CMapFormat { - static const int32_t kFormat0; - static const int32_t kFormat2; - static const int32_t kFormat4; - static const int32_t kFormat6; - static const int32_t kFormat8; - static const int32_t kFormat10; - static const int32_t kFormat12; - static const int32_t kFormat13; - static const int32_t kFormat14; + 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, + + // 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 + }; }; public: diff --git a/sfntly/data/font_data.cc b/sfntly/data/font_data.cc index 8cda562..fdba5f8 100644 --- a/sfntly/data/font_data.cc +++ b/sfntly/data/font_data.cc @@ -22,23 +22,6 @@ namespace sfntly { -const int32_t DataSize::kBYTE = 1; -const int32_t DataSize::kCHAR = 1; -const int32_t DataSize::kUSHORT = 2; -const int32_t DataSize::kSHORT = 2; -const int32_t DataSize::kUINT24 = 3; -const int32_t DataSize::kULONG = 4; -const int32_t DataSize::kLONG = 4; -const int32_t DataSize::kFixed = 4; -const int32_t DataSize::kFUNIT = 4; -const int32_t DataSize::kFWORD = 2; -const int32_t DataSize::kUFWORD = 2; -const int32_t DataSize::kF2DOT14 = 2; -const int32_t DataSize::kLONGDATETIME = 8; -const int32_t DataSize::kTag = 4; -const int32_t DataSize::kGlyphID = 2; -const int32_t DataSize::kOffset = 2; - FontData::~FontData() {} void FontData::init(ByteArray* ba) { diff --git a/sfntly/data/font_data.h b/sfntly/data/font_data.h index 5766cb8..6bcdb73 100644 --- a/sfntly/data/font_data.h +++ b/sfntly/data/font_data.h @@ -25,22 +25,24 @@ namespace sfntly { struct DataSize { - static const int32_t kBYTE; - static const int32_t kCHAR; - static const int32_t kUSHORT; - static const int32_t kSHORT; - static const int32_t kUINT24; - static const int32_t kULONG; - static const int32_t kLONG; - static const int32_t kFixed; - static const int32_t kFUNIT; - static const int32_t kFWORD; - static const int32_t kUFWORD; - static const int32_t kF2DOT14; - static const int32_t kLONGDATETIME; - static const int32_t kTag; - static const int32_t kGlyphID; - static const int32_t kOffset; + 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 { diff --git a/sfntly/font.cc b/sfntly/font.cc index 46dc48c..1532f49 100644 --- a/sfntly/font.cc +++ b/sfntly/font.cc @@ -34,84 +34,8 @@ namespace sfntly { -/****************************************************************************** - * constant definitions - ******************************************************************************/ -const int32_t PlatformId::kUnknown = -1; -const int32_t PlatformId::kUnicode = 0; -const int32_t PlatformId::kMacintosh = 1; -const int32_t PlatformId::kISO = 2; -const int32_t PlatformId::kWindows = 3; -const int32_t PlatformId::kCustom = 4; - -const int32_t UnicodeEncodingId::kUnknown = -1; -const int32_t UnicodeEncodingId::kUnicode1_0 = 0; -const int32_t UnicodeEncodingId::kUnicode1_1 = 1; -const int32_t UnicodeEncodingId::kISO10646 = 2; -const int32_t UnicodeEncodingId::kUnicode2_0_BMP = 3; -const int32_t UnicodeEncodingId::kUnicode2_0 = 4; -const int32_t UnicodeEncodingId::kUnicodeVariationSequences = 5; - -const int32_t WindowsEncodingId::kUnknown = 0xffffffff; -const int32_t WindowsEncodingId::kSymbol = 0; -const int32_t WindowsEncodingId::kUnicodeUCS2 = 1; -const int32_t WindowsEncodingId::kShiftJIS = 2; -const int32_t WindowsEncodingId::kPRC = 3; -const int32_t WindowsEncodingId::kBig5 = 4; -const int32_t WindowsEncodingId::kWansung = 5; -const int32_t WindowsEncodingId::kJohab = 6; -const int32_t WindowsEncodingId::kUnicodeUCS4 = 10; - -const int32_t MacintoshEncodingId::kUnknown = -1; -const int32_t MacintoshEncodingId::kRoman = 0; -const int32_t MacintoshEncodingId::kJapanese = 1; -const int32_t MacintoshEncodingId::kChineseTraditional = 2; -const int32_t MacintoshEncodingId::kKorean = 3; -const int32_t MacintoshEncodingId::kArabic = 4; -const int32_t MacintoshEncodingId::kHebrew = 5; -const int32_t MacintoshEncodingId::kGreek = 6; -const int32_t MacintoshEncodingId::kRussian = 7; -const int32_t MacintoshEncodingId::kRSymbol = 8; -const int32_t MacintoshEncodingId::kDevanagari = 9; -const int32_t MacintoshEncodingId::kGurmukhi = 10; -const int32_t MacintoshEncodingId::kGujarati = 11; -const int32_t MacintoshEncodingId::kOriya = 12; -const int32_t MacintoshEncodingId::kBengali = 13; -const int32_t MacintoshEncodingId::kTamil = 14; -const int32_t MacintoshEncodingId::kTelugu = 15; -const int32_t MacintoshEncodingId::kKannada = 16; -const int32_t MacintoshEncodingId::kMalayalam = 17; -const int32_t MacintoshEncodingId::kSinhalese = 18; -const int32_t MacintoshEncodingId::kBurmese = 19; -const int32_t MacintoshEncodingId::kKhmer = 20; -const int32_t MacintoshEncodingId::kThai = 21; -const int32_t MacintoshEncodingId::kLaotian = 22; -const int32_t MacintoshEncodingId::kGeorgian = 23; -const int32_t MacintoshEncodingId::kArmenian = 24; -const int32_t MacintoshEncodingId::kChineseSimplified = 25; -const int32_t MacintoshEncodingId::kTibetan = 26; -const int32_t MacintoshEncodingId::kMongolian = 27; -const int32_t MacintoshEncodingId::kGeez = 28; -const int32_t MacintoshEncodingId::kSlavic = 29; -const int32_t MacintoshEncodingId::kVietnamese = 30; -const int32_t MacintoshEncodingId::kSindhi = 31; -const int32_t MacintoshEncodingId::kUninterpreted = 32; - const int32_t SFNTVERSION_1 = Fixed1616::fixed(1, 0); -const int32_t Font::Offset::kSfntVersion = 0; -const int32_t Font::Offset::kNumTables = 4; -const int32_t Font::Offset::kSearchRange = 6; -const int32_t Font::Offset::kEntrySelector = 8; -const int32_t Font::Offset::kRangeShift = 10; -const int32_t Font::Offset::kTableRecordBegin = 12; -const int32_t Font::Offset::kSfntHeaderSize = 12; -const int32_t Font::Offset::kTableTag = 0; -const int32_t Font::Offset::kTableCheckSum = 4; -const int32_t Font::Offset::kTableOffset = 8; -const int32_t Font::Offset::kTableLength = 12; -const int32_t Font::Offset::kTableRecordSize = 16; - /****************************************************************************** * Font class ******************************************************************************/ diff --git a/sfntly/font.h b/sfntly/font.h index 4b1dc1b..cbd9607 100644 --- a/sfntly/font.h +++ b/sfntly/font.h @@ -36,78 +36,86 @@ namespace sfntly { // Platform ids. These are used in a number of places within the font whenever // the platform needs to be specified. struct PlatformId { - static const int32_t kUnknown; - static const int32_t kUnicode; - static const int32_t kMacintosh; - static const int32_t kISO; - static const int32_t kWindows; - static const int32_t kCustom; + 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 { - static const int32_t kUnknown; - static const int32_t kUnicode1_0; - static const int32_t kUnicode1_1; - static const int32_t kISO10646; - static const int32_t kUnicode2_0_BMP; - static const int32_t kUnicode2_0; - static const int32_t kUnicodeVariationSequences; + 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 { - static const int32_t kUnknown; - static const int32_t kSymbol; - static const int32_t kUnicodeUCS2; - static const int32_t kShiftJIS; - static const int32_t kPRC; - static const int32_t kBig5; - static const int32_t kWansung; - static const int32_t kJohab; - static const int32_t kUnicodeUCS4; + 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 - static const int32_t kUnknown; - static const int32_t kRoman; - static const int32_t kJapanese; - static const int32_t kChineseTraditional; - static const int32_t kKorean; - static const int32_t kArabic; - static const int32_t kHebrew; - static const int32_t kGreek; - static const int32_t kRussian; - static const int32_t kRSymbol; - static const int32_t kDevanagari; - static const int32_t kGurmukhi; - static const int32_t kGujarati; - static const int32_t kOriya; - static const int32_t kBengali; - static const int32_t kTamil; - static const int32_t kTelugu; - static const int32_t kKannada; - static const int32_t kMalayalam; - static const int32_t kSinhalese; - static const int32_t kBurmese; - static const int32_t kKhmer; - static const int32_t kThai; - static const int32_t kLaotian; - static const int32_t kGeorgian; - static const int32_t kArmenian; - static const int32_t kChineseSimplified; - static const int32_t kTibetan; - static const int32_t kMongolian; - static const int32_t kGeez; - static const int32_t kSlavic; - static const int32_t kVietnamese; - static const int32_t kSindhi; - static const int32_t kUninterpreted; + 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 + }; }; extern const int32_t SFNTVERSION_1; @@ -119,21 +127,23 @@ class Font : public RefCounted { // relative to the start of the table or the start of sub-blocks within the // table. struct Offset { + enum { // Offsets within the main directory - static const int32_t kSfntVersion; - static const int32_t kNumTables; - static const int32_t kSearchRange; - static const int32_t kEntrySelector; - static const int32_t kRangeShift; - static const int32_t kTableRecordBegin; - static const int32_t kSfntHeaderSize; + kSfntVersion = 0, + kNumTables = 4, + kSearchRange = 6, + kEntrySelector = 8, + kRangeShift = 10, + kTableRecordBegin = 12, + kSfntHeaderSize = 12, // Offsets within a specific table record - static const int32_t kTableTag; - static const int32_t kTableCheckSum; - static const int32_t kTableOffset; - static const int32_t kTableLength; - static const int32_t kTableRecordSize; + kTableTag = 0, + kTableCheckSum = 4, + kTableOffset = 8, + kTableLength = 12, + kTableRecordSize = 16 + }; }; // Note: the two constants are moved to tag.h to avoid VC++ bug. diff --git a/sfntly/font_factory.cc b/sfntly/font_factory.cc index f1d1f25..b741f0a 100644 --- a/sfntly/font_factory.cc +++ b/sfntly/font_factory.cc @@ -23,14 +23,6 @@ namespace sfntly { -const int32_t FontFactory::Offset::kTTCTag = 0; -const int32_t FontFactory::Offset::kVersion = 4; -const int32_t FontFactory::Offset::kNumFonts = 8; -const int32_t FontFactory::Offset::kOffsetTable = 12; -const int32_t FontFactory::Offset::kulDsigTag = 0; -const int32_t FontFactory::Offset::kulDsigLength = 4; -const int32_t FontFactory::Offset::kulDsigOffset = 8; - FontFactory::FontFactory() : fingerprint_(false) { } diff --git a/sfntly/font_factory.h b/sfntly/font_factory.h index 9307d91..907ea66 100644 --- a/sfntly/font_factory.h +++ b/sfntly/font_factory.h @@ -31,17 +31,19 @@ class FontFactory : public RefCounted { // relative to the start of the table or the start of sub-blocks within the // table. struct Offset { - // Offsets within the main directory - static const int32_t kTTCTag; - static const int32_t kVersion; - static const int32_t kNumFonts; - static const int32_t kOffsetTable; - - // TTC Version 2.0 extensions - // offsets from end of OffsetTable - static const int32_t kulDsigTag; - static const int32_t kulDsigLength; - static const int32_t kulDsigOffset; + 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(); diff --git a/sfntly/font_header_table.cc b/sfntly/font_header_table.cc index 5d23d39..7710c5a 100644 --- a/sfntly/font_header_table.cc +++ b/sfntly/font_header_table.cc @@ -17,36 +17,6 @@ #include "sfntly/font_header_table.h" namespace sfntly { -/****************************************************************************** - * Constants - ******************************************************************************/ -const int32_t FontHeaderTable::Offset::kTableVersion = 0; -const int32_t FontHeaderTable::Offset::kFontRevision = 4; -const int32_t FontHeaderTable::Offset::kCheckSumAdjustment = 8; -const int32_t FontHeaderTable::Offset::kMagicNumber = 12; -const int32_t FontHeaderTable::Offset::kFlags = 16; -const int32_t FontHeaderTable::Offset::kUnitsPerEm = 18; -const int32_t FontHeaderTable::Offset::kCreated = 20; -const int32_t FontHeaderTable::Offset::kModified = 28; -const int32_t FontHeaderTable::Offset::kXMin = 36; -const int32_t FontHeaderTable::Offset::kYMin = 38; -const int32_t FontHeaderTable::Offset::kXMax = 40; -const int32_t FontHeaderTable::Offset::kYMax = 42; -const int32_t FontHeaderTable::Offset::kMacStyle = 44; -const int32_t FontHeaderTable::Offset::kLowestRecPPEM = 46; -const int32_t FontHeaderTable::Offset::kFontDirectionHint = 48; -const int32_t FontHeaderTable::Offset::kIndexToLocFormat = 50; -const int32_t FontHeaderTable::Offset::kGlyphDataFormat = 52; - -const int32_t IndexToLocFormat::kShortOffset = 0; -const int32_t IndexToLocFormat::kLongOffset = 1; - -const int32_t FontDirectionHint::kFullyMixed = 0; -const int32_t FontDirectionHint::kOnlyStrongLTR = 1; -const int32_t FontDirectionHint::kStrongLTRAndNeutral = 2; -const int32_t FontDirectionHint::kOnlyStrongRTL = -1; -const int32_t FontDirectionHint::kStrongRTLAndNeutral = -2; - /****************************************************************************** * FontHeaderTable class ******************************************************************************/ diff --git a/sfntly/font_header_table.h b/sfntly/font_header_table.h index cac33c8..c8aa9fe 100644 --- a/sfntly/font_header_table.h +++ b/sfntly/font_header_table.h @@ -22,38 +22,44 @@ namespace sfntly { struct IndexToLocFormat { - static const int32_t kShortOffset; - static const int32_t kLongOffset; + enum { + kShortOffset = 0, + kLongOffset = 1 + }; }; struct FontDirectionHint { - static const int32_t kFullyMixed; - static const int32_t kOnlyStrongLTR; - static const int32_t kStrongLTRAndNeutral; - static const int32_t kOnlyStrongRTL; - static const int32_t kStrongRTLAndNeutral; + enum { + kFullyMixed = 0, + kOnlyStrongLTR = 1, + kStrongLTRAndNeutral = 2, + kOnlyStrongRTL = -1, + kStrongRTLAndNeutral = -2 + }; }; class FontHeaderTable : public Table, public RefCounted { private: struct Offset { - static const int32_t kTableVersion; - static const int32_t kFontRevision; - static const int32_t kCheckSumAdjustment; - static const int32_t kMagicNumber; - static const int32_t kFlags; - static const int32_t kUnitsPerEm; - static const int32_t kCreated; - static const int32_t kModified; - static const int32_t kXMin; - static const int32_t kYMin; - static const int32_t kXMax; - static const int32_t kYMax; - static const int32_t kMacStyle; - static const int32_t kLowestRecPPEM; - static const int32_t kFontDirectionHint; - static const int32_t kIndexToLocFormat; - static const int32_t kGlyphDataFormat; + 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 + }; }; private: diff --git a/sfntly/glyph_table.cc b/sfntly/glyph_table.cc index 4cd6436..3ff6d97 100644 --- a/sfntly/glyph_table.cc +++ b/sfntly/glyph_table.cc @@ -23,21 +23,6 @@ namespace sfntly { /****************************************************************************** * Constants ******************************************************************************/ -const int32_t GlyphTable::Offset::kNumberOfContours = 0; -const int32_t GlyphTable::Offset::kXMin = 2; -const int32_t GlyphTable::Offset::kYMin = 4; -const int32_t GlyphTable::Offset::kXMax = 6; -const int32_t GlyphTable::Offset::kYMax = 8; -const int32_t GlyphTable::Offset::kSimpleEndPtsOfCountours = 10; -const int32_t GlyphTable::Offset::kSimpleInstructionLength = 0; -const int32_t GlyphTable::Offset::kSimpleInstructions = 2; -const int32_t GlyphTable::Offset::kCompositeFlags = 0; -const int32_t GlyphTable::Offset::kCompositeGyphIndexWithoutFlag = 0; -const int32_t GlyphTable::Offset::kCompositeGlyphIndexWithFlag = 2; - -const int32_t GlyphType::kSimple = 0; -const int32_t GlyphType::kComposite = 1; - 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; diff --git a/sfntly/glyph_table.h b/sfntly/glyph_table.h index 6f04d45..8a7a8aa 100644 --- a/sfntly/glyph_table.h +++ b/sfntly/glyph_table.h @@ -25,8 +25,10 @@ namespace sfntly { struct GlyphType { - static const int32_t kSimple; - static const int32_t kComposite; + enum { + kSimple = 0, + kComposite = 1 + }; }; // Note: due to the complexity of this class, the order of declaration is @@ -35,26 +37,28 @@ struct GlyphType { class GlyphTable : public Table, public RefCounted { public: struct Offset { - // header - static const int32_t kNumberOfContours; - static const int32_t kXMin; - static const int32_t kYMin; - static const int32_t kXMax; - static const int32_t kYMax; - - // Simple Glyph Description - static const int32_t kSimpleEndPtsOfCountours; - // offset from the end of the contours array - static const int32_t kSimpleInstructionLength; - static const int32_t kSimpleInstructions; - // flags - // xCoordinates - // yCoordinates - - // Composite Glyph Description - static const int32_t kCompositeFlags; - static const int32_t kCompositeGyphIndexWithoutFlag; - static const int32_t kCompositeGlyphIndexWithFlag; + 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, + }; }; private: diff --git a/sfntly/horizontal_header_table.cc b/sfntly/horizontal_header_table.cc index 68afeea..f30e8db 100644 --- a/sfntly/horizontal_header_table.cc +++ b/sfntly/horizontal_header_table.cc @@ -21,23 +21,6 @@ #include "sfntly/horizontal_header_table.h" namespace sfntly { -/****************************************************************************** - * HorizontalHeaderTable::Builder class - ******************************************************************************/ -const int32_t HorizontalHeaderTable::Offset::kVersion = 0; -const int32_t HorizontalHeaderTable::Offset::kAscender = 4; -const int32_t HorizontalHeaderTable::Offset::kDescender = 6; -const int32_t HorizontalHeaderTable::Offset::kLineGap = 8; -const int32_t HorizontalHeaderTable::Offset::kAdvanceWidthMax = 10; -const int32_t HorizontalHeaderTable::Offset::kMinLeftSideBearing = 12; -const int32_t HorizontalHeaderTable::Offset::kMinRightSideBearing = 14; -const int32_t HorizontalHeaderTable::Offset::kXMaxExtent = 16; -const int32_t HorizontalHeaderTable::Offset::kCaretSlopeRise = 18; -const int32_t HorizontalHeaderTable::Offset::kCaretSlopeRun = 20; -const int32_t HorizontalHeaderTable::Offset::kCaretOffset = 22; -const int32_t HorizontalHeaderTable::Offset::kMetricDataFormat = 32; -const int32_t HorizontalHeaderTable::Offset::kNumberOfHMetrics = 34; - /****************************************************************************** * HorizontalHeaderTable class ******************************************************************************/ diff --git a/sfntly/horizontal_header_table.h b/sfntly/horizontal_header_table.h index 36f4180..704391c 100644 --- a/sfntly/horizontal_header_table.h +++ b/sfntly/horizontal_header_table.h @@ -25,19 +25,21 @@ class HorizontalHeaderTable : public Table, public RefCounted { private: struct Offset { - static const int32_t kVersion; - static const int32_t kAscender; - static const int32_t kDescender; - static const int32_t kLineGap; - static const int32_t kAdvanceWidthMax; - static const int32_t kMinLeftSideBearing; - static const int32_t kMinRightSideBearing; - static const int32_t kXMaxExtent; - static const int32_t kCaretSlopeRise; - static const int32_t kCaretSlopeRun; - static const int32_t kCaretOffset; - static const int32_t kMetricDataFormat; - static const int32_t kNumberOfHMetrics; + 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, + }; }; private: diff --git a/sfntly/horizontal_metrics_table.cc b/sfntly/horizontal_metrics_table.cc index d6beab1..c151e18 100644 --- a/sfntly/horizontal_metrics_table.cc +++ b/sfntly/horizontal_metrics_table.cc @@ -18,15 +18,6 @@ #include "sfntly/port/exception_type.h" namespace sfntly { -/****************************************************************************** - * Constants - ******************************************************************************/ -const int32_t HorizontalMetricsTable::Offset::kHMetricsStart = 0; -const int32_t HorizontalMetricsTable::Offset::kHMetricsSize = 4; -const int32_t HorizontalMetricsTable::Offset::kHMetricsAdvanceWidth = 0; -const int32_t HorizontalMetricsTable::Offset::kHMetricsLeftSideBearing = 2; -const int32_t HorizontalMetricsTable::Offset::kLeftSideBearingSize = 2; - /****************************************************************************** * HorizontalMetricsTable class ******************************************************************************/ diff --git a/sfntly/horizontal_metrics_table.h b/sfntly/horizontal_metrics_table.h index 0f1d651..c393fee 100644 --- a/sfntly/horizontal_metrics_table.h +++ b/sfntly/horizontal_metrics_table.h @@ -25,15 +25,17 @@ class HorizontalMetricsTable : public Table, public RefCounted { private: struct Offset { - // hMetrics - static const int32_t kHMetricsStart; - static const int32_t kHMetricsSize; + enum { + // hMetrics + kHMetricsStart = 0, + kHMetricsSize = 4, - // Offset within an hMetric - static const int32_t kHMetricsAdvanceWidth; - static const int32_t kHMetricsLeftSideBearing; + // Offset within an hMetric + kHMetricsAdvanceWidth = 0, + kHMetricsLeftSideBearing = 2, - static const int32_t kLeftSideBearingSize; + kLeftSideBearingSize = 2 + }; }; private: diff --git a/sfntly/maximum_profile_table.cc b/sfntly/maximum_profile_table.cc index a79d1e4..61a176e 100644 --- a/sfntly/maximum_profile_table.cc +++ b/sfntly/maximum_profile_table.cc @@ -17,25 +17,6 @@ #include "sfntly/maximum_profile_table.h" namespace sfntly { -/****************************************************************************** - * Constants - ******************************************************************************/ -const int32_t MaximumProfileTable::Offset::kVersion = 0; -const int32_t MaximumProfileTable::Offset::kNumGlyphs = 4; -const int32_t MaximumProfileTable::Offset::kMaxPoints = 6; -const int32_t MaximumProfileTable::Offset::kMaxContours = 8; -const int32_t MaximumProfileTable::Offset::kMaxCompositePoints = 10; -const int32_t MaximumProfileTable::Offset::kMaxCompositeContours = 12; -const int32_t MaximumProfileTable::Offset::kMaxZones = 14; -const int32_t MaximumProfileTable::Offset::kMaxTwilightPoints = 16; -const int32_t MaximumProfileTable::Offset::kMaxStorage = 18; -const int32_t MaximumProfileTable::Offset::kMaxFunctionDefs = 20; -const int32_t MaximumProfileTable::Offset::kMaxInstructionDefs = 22; -const int32_t MaximumProfileTable::Offset::kMaxStackElements = 24; -const int32_t MaximumProfileTable::Offset::kMaxSizeOfInstructions = 26; -const int32_t MaximumProfileTable::Offset::kMaxComponentElements = 28; -const int32_t MaximumProfileTable::Offset::kMaxComponentDepth = 30; - /****************************************************************************** * MaximumProfileTable class ******************************************************************************/ diff --git a/sfntly/maximum_profile_table.h b/sfntly/maximum_profile_table.h index 7a0b941..044eccf 100644 --- a/sfntly/maximum_profile_table.h +++ b/sfntly/maximum_profile_table.h @@ -26,24 +26,26 @@ class MaximumProfileTable : public Table, public RefCounted { private: struct Offset { - // version 0.5 and 1.0 - static const int32_t kVersion; - static const int32_t kNumGlyphs; + enum { + // version 0.5 and 1.0 + kVersion = 0, + kNumGlyphs = 4, - // version 1.0 - static const int32_t kMaxPoints; - static const int32_t kMaxContours; - static const int32_t kMaxCompositePoints; - static const int32_t kMaxCompositeContours; - static const int32_t kMaxZones; - static const int32_t kMaxTwilightPoints; - static const int32_t kMaxStorage; - static const int32_t kMaxFunctionDefs; - static const int32_t kMaxInstructionDefs; - static const int32_t kMaxStackElements; - static const int32_t kMaxSizeOfInstructions; - static const int32_t kMaxComponentElements; - static const int32_t kMaxComponentDepth; + // 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, + }; }; private: diff --git a/sfntly/name_table.cc b/sfntly/name_table.cc index b344bfa..cee6e3d 100644 --- a/sfntly/name_table.cc +++ b/sfntly/name_table.cc @@ -19,378 +19,6 @@ #include "sfntly/name_table.h" namespace sfntly { -/****************************************************************************** - * Constants - ******************************************************************************/ -const int32_t NameTable::Offset::kFormat = 0; -const int32_t NameTable::Offset::kCount = 2; -const int32_t NameTable::Offset::kStringOffset = 4; -const int32_t NameTable::Offset::kNameRecordStart = 6; -const int32_t NameTable::Offset::kLangTagCount = 0; -const int32_t NameTable::Offset::kLangTagRecord = 2; -const int32_t NameTable::Offset::kNameRecordSize = 12; -const int32_t NameTable::Offset::kNameRecordPlatformId = 0; -const int32_t NameTable::Offset::kNameRecordEncodingId = 2; -const int32_t NameTable::Offset::kNameRecordLanguageId = 4; -const int32_t NameTable::Offset::kNameRecordNameId = 6; -const int32_t NameTable::Offset::kNameRecordStringLength = 8; -const int32_t NameTable::Offset::kNameRecordStringOffset = 10; - -const int32_t NameTable::NameId::kUnknown = -1; -const int32_t NameTable::NameId::kCopyrightNotice = 0; -const int32_t NameTable::NameId::kFontFamilyName = 1; -const int32_t NameTable::NameId::kFontSubfamilyName = 2; -const int32_t NameTable::NameId::kUniqueFontIdentifier = 3; -const int32_t NameTable::NameId::kFullFontName = 4; -const int32_t NameTable::NameId::kVersionString = 5; -const int32_t NameTable::NameId::kPostscriptName = 6; -const int32_t NameTable::NameId::kTrademark = 7; -const int32_t NameTable::NameId::kManufacturerName = 8; -const int32_t NameTable::NameId::kDesigner = 9; -const int32_t NameTable::NameId::kDescription = 10; -const int32_t NameTable::NameId::kVendorURL = 11; -const int32_t NameTable::NameId::kDesignerURL = 12; -const int32_t NameTable::NameId::kLicenseDescription = 13; -const int32_t NameTable::NameId::kLicenseInfoURL = 14; -const int32_t NameTable::NameId::kReserved15 = 15; -const int32_t NameTable::NameId::kPreferredFamily = 16; -const int32_t NameTable::NameId::kPreferredSubfamily = 17; -const int32_t NameTable::NameId::kCompatibleFullName = 18; -const int32_t NameTable::NameId::kSampleText = 19; -const int32_t NameTable::NameId::kPostscriptCID = 20; -const int32_t NameTable::NameId::kWWSFamilyName = 21; -const int32_t NameTable::NameId::kWWSSubfamilyName = 22; - -const int32_t UnicodeLanguageId::kUnknown = -1; -const int32_t UnicodeLanguageId::kAll = 0; - -const int32_t MacintoshLanguageId::kUnknown = -1; -const int32_t MacintoshLanguageId::kEnglish = 0; -const int32_t MacintoshLanguageId::kFrench = 1; -const int32_t MacintoshLanguageId::kGerman = 2; -const int32_t MacintoshLanguageId::kItalian = 3; -const int32_t MacintoshLanguageId::kDutch = 4; -const int32_t MacintoshLanguageId::kSwedish = 5; -const int32_t MacintoshLanguageId::kSpanish = 6; -const int32_t MacintoshLanguageId::kDanish = 7; -const int32_t MacintoshLanguageId::kPortuguese = 8; -const int32_t MacintoshLanguageId::kNorwegian = 9; -const int32_t MacintoshLanguageId::kHebrew = 10; -const int32_t MacintoshLanguageId::kJapanese = 11; -const int32_t MacintoshLanguageId::kArabic = 12; -const int32_t MacintoshLanguageId::kFinnish = 13; -const int32_t MacintoshLanguageId::kGreek = 14; -const int32_t MacintoshLanguageId::kIcelandic = 15; -const int32_t MacintoshLanguageId::kMaltese = 16; -const int32_t MacintoshLanguageId::kTurkish = 17; -const int32_t MacintoshLanguageId::kCroatian = 18; -const int32_t MacintoshLanguageId::kChinese_Traditional = 19; -const int32_t MacintoshLanguageId::kUrdu = 20; -const int32_t MacintoshLanguageId::kHindi = 21; -const int32_t MacintoshLanguageId::kThai = 22; -const int32_t MacintoshLanguageId::kKorean = 23; -const int32_t MacintoshLanguageId::kLithuanian = 24; -const int32_t MacintoshLanguageId::kPolish = 25; -const int32_t MacintoshLanguageId::kHungarian = 26; -const int32_t MacintoshLanguageId::kEstonian = 27; -const int32_t MacintoshLanguageId::kLatvian = 28; -const int32_t MacintoshLanguageId::kSami = 29; -const int32_t MacintoshLanguageId::kFaroese = 30; -const int32_t MacintoshLanguageId::kFarsiPersian = 31; -const int32_t MacintoshLanguageId::kRussian = 32; -const int32_t MacintoshLanguageId::kChinese_Simplified = 33; -const int32_t MacintoshLanguageId::kFlemish = 34; -const int32_t MacintoshLanguageId::kIrishGaelic = 35; -const int32_t MacintoshLanguageId::kAlbanian = 36; -const int32_t MacintoshLanguageId::kRomanian = 37; -const int32_t MacintoshLanguageId::kCzech = 38; -const int32_t MacintoshLanguageId::kSlovak = 39; -const int32_t MacintoshLanguageId::kSlovenian = 40; -const int32_t MacintoshLanguageId::kYiddish = 41; -const int32_t MacintoshLanguageId::kSerbian = 42; -const int32_t MacintoshLanguageId::kMacedonian = 43; -const int32_t MacintoshLanguageId::kBulgarian = 44; -const int32_t MacintoshLanguageId::kUkrainian = 45; -const int32_t MacintoshLanguageId::kByelorussian = 46; -const int32_t MacintoshLanguageId::kUzbek = 47; -const int32_t MacintoshLanguageId::kKazakh = 48; -const int32_t MacintoshLanguageId::kAzerbaijani_Cyrillic = 49; -const int32_t MacintoshLanguageId::kAzerbaijani_Arabic = 50; -const int32_t MacintoshLanguageId::kArmenian = 51; -const int32_t MacintoshLanguageId::kGeorgian = 52; -const int32_t MacintoshLanguageId::kMoldavian = 53; -const int32_t MacintoshLanguageId::kKirghiz = 54; -const int32_t MacintoshLanguageId::kTajiki = 55; -const int32_t MacintoshLanguageId::kTurkmen = 56; -const int32_t MacintoshLanguageId::kMongolian_Mongolian = 57; -const int32_t MacintoshLanguageId::kMongolian_Cyrillic = 58; -const int32_t MacintoshLanguageId::kPashto = 59; -const int32_t MacintoshLanguageId::kKurdish = 60; -const int32_t MacintoshLanguageId::kKashmiri = 61; -const int32_t MacintoshLanguageId::kSindhi = 62; -const int32_t MacintoshLanguageId::kTibetan = 63; -const int32_t MacintoshLanguageId::kNepali = 64; -const int32_t MacintoshLanguageId::kSanskrit = 65; -const int32_t MacintoshLanguageId::kMarathi = 66; -const int32_t MacintoshLanguageId::kBengali = 67; -const int32_t MacintoshLanguageId::kAssamese = 68; -const int32_t MacintoshLanguageId::kGujarati = 69; -const int32_t MacintoshLanguageId::kPunjabi = 70; -const int32_t MacintoshLanguageId::kOriya = 71; -const int32_t MacintoshLanguageId::kMalayalam = 72; -const int32_t MacintoshLanguageId::kKannada = 73; -const int32_t MacintoshLanguageId::kTamil = 74; -const int32_t MacintoshLanguageId::kTelugu = 75; -const int32_t MacintoshLanguageId::kSinhalese = 76; -const int32_t MacintoshLanguageId::kBurmese = 77; -const int32_t MacintoshLanguageId::kKhmer = 78; -const int32_t MacintoshLanguageId::kLao = 79; -const int32_t MacintoshLanguageId::kVietnamese = 80; -const int32_t MacintoshLanguageId::kIndonesian = 81; -const int32_t MacintoshLanguageId::kTagalong = 82; -const int32_t MacintoshLanguageId::kMalay_Roman = 83; -const int32_t MacintoshLanguageId::kMalay_Arabic = 84; -const int32_t MacintoshLanguageId::kAmharic = 85; -const int32_t MacintoshLanguageId::kTigrinya = 86; -const int32_t MacintoshLanguageId::kGalla = 87; -const int32_t MacintoshLanguageId::kSomali = 88; -const int32_t MacintoshLanguageId::kSwahili = 89; -const int32_t MacintoshLanguageId::kKinyarwandaRuanda = 90; -const int32_t MacintoshLanguageId::kRundi = 91; -const int32_t MacintoshLanguageId::kNyanjaChewa = 92; -const int32_t MacintoshLanguageId::kMalagasy = 93; -const int32_t MacintoshLanguageId::kEsperanto = 94; -const int32_t MacintoshLanguageId::kWelsh = 128; -const int32_t MacintoshLanguageId::kBasque = 129; -const int32_t MacintoshLanguageId::kCatalan = 130; -const int32_t MacintoshLanguageId::kLatin = 131; -const int32_t MacintoshLanguageId::kQuenchua = 132; -const int32_t MacintoshLanguageId::kGuarani = 133; -const int32_t MacintoshLanguageId::kAymara = 134; -const int32_t MacintoshLanguageId::kTatar = 135; -const int32_t MacintoshLanguageId::kUighur = 136; -const int32_t MacintoshLanguageId::kDzongkha = 137; -const int32_t MacintoshLanguageId::kJavanese_Roman = 138; -const int32_t MacintoshLanguageId::kSundanese_Roman = 139; -const int32_t MacintoshLanguageId::kGalician = 140; -const int32_t MacintoshLanguageId::kAfrikaans = 141; -const int32_t MacintoshLanguageId::kBreton = 142; -const int32_t MacintoshLanguageId::kInuktitut = 143; -const int32_t MacintoshLanguageId::kScottishGaelic = 144; -const int32_t MacintoshLanguageId::kManxGaelic = 145; -const int32_t MacintoshLanguageId::kIrishGaelic_WithDotAbove = 146; -const int32_t MacintoshLanguageId::kTongan = 147; -const int32_t MacintoshLanguageId::kGreek_Polytonic = 148; -const int32_t MacintoshLanguageId::kGreenlandic = 149; -const int32_t MacintoshLanguageId::kAzerbaijani_Roman = 150; - -const int32_t WindowsLanguageId::kUnknown = -1; -const int32_t WindowsLanguageId::kAfrikaans_SouthAfrica = 0x0436; -const int32_t WindowsLanguageId::kAlbanian_Albania = 0x041C; -const int32_t WindowsLanguageId::kAlsatian_France = 0x0484; -const int32_t WindowsLanguageId::kAmharic_Ethiopia = 0x045E; -const int32_t WindowsLanguageId::kArabic_Algeria = 0x1401; -const int32_t WindowsLanguageId::kArabic_Bahrain = 0x3C01; -const int32_t WindowsLanguageId::kArabic_Egypt = 0x0C01; -const int32_t WindowsLanguageId::kArabic_Iraq = 0x0801; -const int32_t WindowsLanguageId::kArabic_Jordan = 0x2C01; -const int32_t WindowsLanguageId::kArabic_Kuwait = 0x3401; -const int32_t WindowsLanguageId::kArabic_Lebanon = 0x3001; -const int32_t WindowsLanguageId::kArabic_Libya = 0x1001; -const int32_t WindowsLanguageId::kArabic_Morocco = 0x1801; -const int32_t WindowsLanguageId::kArabic_Oman = 0x2001; -const int32_t WindowsLanguageId::kArabic_Qatar = 0x4001; -const int32_t WindowsLanguageId::kArabic_SaudiArabia = 0x0401; -const int32_t WindowsLanguageId::kArabic_Syria = 0x2801; -const int32_t WindowsLanguageId::kArabic_Tunisia = 0x1C01; -const int32_t WindowsLanguageId::kArabic_UAE = 0x3801; -const int32_t WindowsLanguageId::kArabic_Yemen = 0x2401; -const int32_t WindowsLanguageId::kArmenian_Armenia = 0x042B; -const int32_t WindowsLanguageId::kAssamese_India = 0x044D; -const int32_t WindowsLanguageId::kAzeri_Cyrillic_Azerbaijan = 0x082C; -const int32_t WindowsLanguageId::kAzeri_Latin_Azerbaijan = 0x042C; -const int32_t WindowsLanguageId::kBashkir_Russia = 0x046D; -const int32_t WindowsLanguageId::kBasque_Basque = 0x042D; -const int32_t WindowsLanguageId::kBelarusian_Belarus = 0x0423; -const int32_t WindowsLanguageId::kBengali_Bangladesh = 0x0845; -const int32_t WindowsLanguageId::kBengali_India = 0x0445; -const int32_t WindowsLanguageId::kBosnian_Cyrillic_BosniaAndHerzegovina = 0x201A; -const int32_t WindowsLanguageId::kBosnian_Latin_BosniaAndHerzegovina = 0x141A; -const int32_t WindowsLanguageId::kBreton_France = 0x047E; -const int32_t WindowsLanguageId::kBulgarian_Bulgaria = 0x0402; -const int32_t WindowsLanguageId::kCatalan_Catalan = 0x0403; -const int32_t WindowsLanguageId::kChinese_HongKongSAR = 0x0C04; -const int32_t WindowsLanguageId::kChinese_MacaoSAR = 0x1404; -const int32_t WindowsLanguageId::kChinese_PeoplesRepublicOfChina = 0x0804; -const int32_t WindowsLanguageId::kChinese_Singapore = 0x1004; -const int32_t WindowsLanguageId::kChinese_Taiwan = 0x0404; -const int32_t WindowsLanguageId::kCorsican_France = 0x0483; -const int32_t WindowsLanguageId::kCroatian_Croatia = 0x041A; -const int32_t WindowsLanguageId::kCroatian_Latin_BosniaAndHerzegovina = 0x101A; -const int32_t WindowsLanguageId::kCzech_CzechRepublic = 0x0405; -const int32_t WindowsLanguageId::kDanish_Denmark = 0x0406; -const int32_t WindowsLanguageId::kDari_Afghanistan = 0x048C; -const int32_t WindowsLanguageId::kDivehi_Maldives = 0x0465; -const int32_t WindowsLanguageId::kDutch_Belgium = 0x0813; -const int32_t WindowsLanguageId::kDutch_Netherlands = 0x0413; -const int32_t WindowsLanguageId::kEnglish_Australia = 0x0C09; -const int32_t WindowsLanguageId::kEnglish_Belize = 0x2809; -const int32_t WindowsLanguageId::kEnglish_Canada = 0x1009; -const int32_t WindowsLanguageId::kEnglish_Caribbean = 0x2409; -const int32_t WindowsLanguageId::kEnglish_India = 0x4009; -const int32_t WindowsLanguageId::kEnglish_Ireland = 0x1809; -const int32_t WindowsLanguageId::kEnglish_Jamaica = 0x2009; -const int32_t WindowsLanguageId::kEnglish_Malaysia = 0x4409; -const int32_t WindowsLanguageId::kEnglish_NewZealand = 0x1409; -const int32_t WindowsLanguageId::kEnglish_RepublicOfThePhilippines = 0x3409; -const int32_t WindowsLanguageId::kEnglish_Singapore = 0x4809; -const int32_t WindowsLanguageId::kEnglish_SouthAfrica = 0x1C09; -const int32_t WindowsLanguageId::kEnglish_TrinidadAndTobago = 0x2C09; -const int32_t WindowsLanguageId::kEnglish_UnitedKingdom = 0x0809; -const int32_t WindowsLanguageId::kEnglish_UnitedStates = 0x0409; -const int32_t WindowsLanguageId::kEnglish_Zimbabwe = 0x3009; -const int32_t WindowsLanguageId::kEstonian_Estonia = 0x0425; -const int32_t WindowsLanguageId::kFaroese_FaroeIslands = 0x0438; -const int32_t WindowsLanguageId::kFilipino_Philippines = 0x0464; -const int32_t WindowsLanguageId::kFinnish_Finland = 0x040B; -const int32_t WindowsLanguageId::kFrench_Belgium = 0x080C; -const int32_t WindowsLanguageId::kFrench_Canada = 0x0C0C; -const int32_t WindowsLanguageId::kFrench_France = 0x040C; -const int32_t WindowsLanguageId::kFrench_Luxembourg = 0x140c; -const int32_t WindowsLanguageId::kFrench_PrincipalityOfMonoco = 0x180C; -const int32_t WindowsLanguageId::kFrench_Switzerland = 0x100C; -const int32_t WindowsLanguageId::kFrisian_Netherlands = 0x0462; -const int32_t WindowsLanguageId::kGalician_Galician = 0x0456; -const int32_t WindowsLanguageId::kGeorgian_Georgia = 0x0437; -const int32_t WindowsLanguageId::kGerman_Austria = 0x0C07; -const int32_t WindowsLanguageId::kGerman_Germany = 0x0407; -const int32_t WindowsLanguageId::kGerman_Liechtenstein = 0x1407; -const int32_t WindowsLanguageId::kGerman_Luxembourg = 0x1007; -const int32_t WindowsLanguageId::kGerman_Switzerland = 0x0807; -const int32_t WindowsLanguageId::kGreek_Greece = 0x0408; -const int32_t WindowsLanguageId::kGreenlandic_Greenland = 0x046F; -const int32_t WindowsLanguageId::kGujarati_India = 0x0447; -const int32_t WindowsLanguageId::kHausa_Latin_Nigeria = 0x0468; -const int32_t WindowsLanguageId::kHebrew_Israel = 0x040D; -const int32_t WindowsLanguageId::kHindi_India = 0x0439; -const int32_t WindowsLanguageId::kHungarian_Hungary = 0x040E; -const int32_t WindowsLanguageId::kIcelandic_Iceland = 0x040F; -const int32_t WindowsLanguageId::kIgbo_Nigeria = 0x0470; -const int32_t WindowsLanguageId::kIndonesian_Indonesia = 0x0421; -const int32_t WindowsLanguageId::kInuktitut_Canada = 0x045D; -const int32_t WindowsLanguageId::kInuktitut_Latin_Canada = 0x085D; -const int32_t WindowsLanguageId::kIrish_Ireland = 0x083C; -const int32_t WindowsLanguageId::kisiXhosa_SouthAfrica = 0x0434; -const int32_t WindowsLanguageId::kisiZulu_SouthAfrica = 0x0435; -const int32_t WindowsLanguageId::kItalian_Italy = 0x0410; -const int32_t WindowsLanguageId::kItalian_Switzerland = 0x0810; -const int32_t WindowsLanguageId::kJapanese_Japan = 0x0411; -const int32_t WindowsLanguageId::kKannada_India = 0x044B; -const int32_t WindowsLanguageId::kKazakh_Kazakhstan = 0x043F; -const int32_t WindowsLanguageId::kKhmer_Cambodia = 0x0453; -const int32_t WindowsLanguageId::kKiche_Guatemala = 0x0486; -const int32_t WindowsLanguageId::kKinyarwanda_Rwanda = 0x0487; -const int32_t WindowsLanguageId::kKiswahili_Kenya = 0x0441; -const int32_t WindowsLanguageId::kKonkani_India = 0x0457; -const int32_t WindowsLanguageId::kKorean_Korea = 0x0412; -const int32_t WindowsLanguageId::kKyrgyz_Kyrgyzstan = 0x0440; -const int32_t WindowsLanguageId::kLao_LaoPDR = 0x0454; -const int32_t WindowsLanguageId::kLatvian_Latvia = 0x0426; -const int32_t WindowsLanguageId::kLithuanian_Lithuania = 0x0427; -const int32_t WindowsLanguageId::kLowerSorbian_Germany = 0x082E; -const int32_t WindowsLanguageId::kLuxembourgish_Luxembourg = 0x046E; -const int32_t WindowsLanguageId::kMacedonian_FYROM_FormerYugoslavRepublicOfMacedonia = 0x042F; -const int32_t WindowsLanguageId::kMalay_BruneiDarussalam = 0x083E; -const int32_t WindowsLanguageId::kMalay_Malaysia = 0x043E; -const int32_t WindowsLanguageId::kMalayalam_India = 0x044C; -const int32_t WindowsLanguageId::kMaltese_Malta = 0x043A; -const int32_t WindowsLanguageId::kMaori_NewZealand = 0x0481; -const int32_t WindowsLanguageId::kMapudungun_Chile = 0x047A; -const int32_t WindowsLanguageId::kMarathi_India = 0x044E; -const int32_t WindowsLanguageId::kMohawk_Mohawk = 0x047C; -const int32_t WindowsLanguageId::kMongolian_Cyrillic_Mongolia = 0x0450; -const int32_t WindowsLanguageId::kMongolian_Traditional_PeoplesRepublicOfChina = 0x0850; -const int32_t WindowsLanguageId::kNepali_Nepal = 0x0461; -const int32_t WindowsLanguageId::kNorwegian_Bokmal_Norway = 0x0414; -const int32_t WindowsLanguageId::kNorwegian_Nynorsk_Norway = 0x0814; -const int32_t WindowsLanguageId::kOccitan_France = 0x0482; -const int32_t WindowsLanguageId::kOriya_India = 0x0448; -const int32_t WindowsLanguageId::kPashto_Afghanistan = 0x0463; -const int32_t WindowsLanguageId::kPolish_Poland = 0x0415; -const int32_t WindowsLanguageId::kPortuguese_Brazil = 0x0416; -const int32_t WindowsLanguageId::kPortuguese_Portugal = 0x0816; -const int32_t WindowsLanguageId::kPunjabi_India = 0x0446; -const int32_t WindowsLanguageId::kQuechua_Bolivia = 0x046B; -const int32_t WindowsLanguageId::kQuechua_Ecuador = 0x086B; -const int32_t WindowsLanguageId::kQuechua_Peru = 0x0C6B; -const int32_t WindowsLanguageId::kRomanian_Romania = 0x0418; -const int32_t WindowsLanguageId::kRomansh_Switzerland = 0x0417; -const int32_t WindowsLanguageId::kRussian_Russia = 0x0419; -const int32_t WindowsLanguageId::kSami_Inari_Finland = 0x243B; -const int32_t WindowsLanguageId::kSami_Lule_Norway = 0x103B; -const int32_t WindowsLanguageId::kSami_Lule_Sweden = 0x143B; -const int32_t WindowsLanguageId::kSami_Northern_Finland = 0x0C3B; -const int32_t WindowsLanguageId::kSami_Northern_Norway = 0x043B; -const int32_t WindowsLanguageId::kSami_Northern_Sweden = 0x083B; -const int32_t WindowsLanguageId::kSami_Skolt_Finland = 0x203B; -const int32_t WindowsLanguageId::kSami_Southern_Norway = 0x183B; -const int32_t WindowsLanguageId::kSami_Southern_Sweden = 0x1C3B; -const int32_t WindowsLanguageId::kSanskrit_India = 0x044F; -const int32_t WindowsLanguageId::kSerbian_Cyrillic_BosniaAndHerzegovina = 0x1C1A; -const int32_t WindowsLanguageId::kSerbian_Cyrillic_Serbia = 0x0C1A; -const int32_t WindowsLanguageId::kSerbian_Latin_BosniaAndHerzegovina = 0x181A; -const int32_t WindowsLanguageId::kSerbian_Latin_Serbia = 0x081A; -const int32_t WindowsLanguageId::kSesothoSaLeboa_SouthAfrica = 0x046C; -const int32_t WindowsLanguageId::kSetswana_SouthAfrica = 0x0432; -const int32_t WindowsLanguageId::kSinhala_SriLanka = 0x045B; -const int32_t WindowsLanguageId::kSlovak_Slovakia = 0x041B; -const int32_t WindowsLanguageId::kSlovenian_Slovenia = 0x0424; -const int32_t WindowsLanguageId::kSpanish_Argentina = 0x2C0A; -const int32_t WindowsLanguageId::kSpanish_Bolivia = 0x400A; -const int32_t WindowsLanguageId::kSpanish_Chile = 0x340A; -const int32_t WindowsLanguageId::kSpanish_Colombia = 0x240A; -const int32_t WindowsLanguageId::kSpanish_CostaRica = 0x140A; -const int32_t WindowsLanguageId::kSpanish_DominicanRepublic = 0x1C0A; -const int32_t WindowsLanguageId::kSpanish_Ecuador = 0x300A; -const int32_t WindowsLanguageId::kSpanish_ElSalvador = 0x440A; -const int32_t WindowsLanguageId::kSpanish_Guatemala = 0x100A; -const int32_t WindowsLanguageId::kSpanish_Honduras = 0x480A; -const int32_t WindowsLanguageId::kSpanish_Mexico = 0x080A; -const int32_t WindowsLanguageId::kSpanish_Nicaragua = 0x4C0A; -const int32_t WindowsLanguageId::kSpanish_Panama = 0x180A; -const int32_t WindowsLanguageId::kSpanish_Paraguay = 0x3C0A; -const int32_t WindowsLanguageId::kSpanish_Peru = 0x280A; -const int32_t WindowsLanguageId::kSpanish_PuertoRico = 0x500A; -const int32_t WindowsLanguageId::kSpanish_ModernSort_Spain = 0x0C0A; -const int32_t WindowsLanguageId::kSpanish_TraditionalSort_Spain = 0x040A; -const int32_t WindowsLanguageId::kSpanish_UnitedStates = 0x540A; -const int32_t WindowsLanguageId::kSpanish_Uruguay = 0x380A; -const int32_t WindowsLanguageId::kSpanish_Venezuela = 0x200A; -const int32_t WindowsLanguageId::kSweden_Finland = 0x081D; -const int32_t WindowsLanguageId::kSwedish_Sweden = 0x041D; -const int32_t WindowsLanguageId::kSyriac_Syria = 0x045A; -const int32_t WindowsLanguageId::kTajik_Cyrillic_Tajikistan = 0x0428; -const int32_t WindowsLanguageId::kTamazight_Latin_Algeria = 0x085F; -const int32_t WindowsLanguageId::kTamil_India = 0x0449; -const int32_t WindowsLanguageId::kTatar_Russia = 0x0444; -const int32_t WindowsLanguageId::kTelugu_India = 0x044A; -const int32_t WindowsLanguageId::kThai_Thailand = 0x041E; -const int32_t WindowsLanguageId::kTibetan_PRC = 0x0451; -const int32_t WindowsLanguageId::kTurkish_Turkey = 0x041F; -const int32_t WindowsLanguageId::kTurkmen_Turkmenistan = 0x0442; -const int32_t WindowsLanguageId::kUighur_PRC = 0x0480; -const int32_t WindowsLanguageId::kUkrainian_Ukraine = 0x0422; -const int32_t WindowsLanguageId::kUpperSorbian_Germany = 0x042E; -const int32_t WindowsLanguageId::kUrdu_IslamicRepublicOfPakistan = 0x0420; -const int32_t WindowsLanguageId::kUzbek_Cyrillic_Uzbekistan = 0x0843; -const int32_t WindowsLanguageId::kUzbek_Latin_Uzbekistan = 0x0443; -const int32_t WindowsLanguageId::kVietnamese_Vietnam = 0x042A; -const int32_t WindowsLanguageId::kWelsh_UnitedKingdom = 0x0452; -const int32_t WindowsLanguageId::kWolof_Senegal = 0x0448; -const int32_t WindowsLanguageId::kYakut_Russia = 0x0485; -const int32_t WindowsLanguageId::kYi_PRC = 0x0478; -const int32_t WindowsLanguageId::kYoruba_Nigeria = 0x046A; - /****************************************************************************** * NameTable class ******************************************************************************/ diff --git a/sfntly/name_table.h b/sfntly/name_table.h index 7553aa0..948c6b9 100644 --- a/sfntly/name_table.h +++ b/sfntly/name_table.h @@ -25,391 +25,401 @@ namespace sfntly { +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 + }; +}; + struct UnicodeLanguageId { - static const int32_t kUnknown; - static const int32_t kAll; + enum { + kUnknown = -1, + kAll = 0 + }; }; -// Macinstosh Language IDs (platform ID = 1) +// Macintosh Language IDs (platform ID = 1) struct MacintoshLanguageId { - static const int32_t kUnknown; - static const int32_t kEnglish; - static const int32_t kFrench; - static const int32_t kGerman; - static const int32_t kItalian; - static const int32_t kDutch; - static const int32_t kSwedish; - static const int32_t kSpanish; - static const int32_t kDanish; - static const int32_t kPortuguese; - static const int32_t kNorwegian; - static const int32_t kHebrew; - static const int32_t kJapanese; - static const int32_t kArabic; - static const int32_t kFinnish; - static const int32_t kGreek; - static const int32_t kIcelandic; - static const int32_t kMaltese; - static const int32_t kTurkish; - static const int32_t kCroatian; - static const int32_t kChinese_Traditional; - static const int32_t kUrdu; - static const int32_t kHindi; - static const int32_t kThai; - static const int32_t kKorean; - static const int32_t kLithuanian; - static const int32_t kPolish; - static const int32_t kHungarian; - static const int32_t kEstonian; - static const int32_t kLatvian; - static const int32_t kSami; - static const int32_t kFaroese; - static const int32_t kFarsiPersian; - static const int32_t kRussian; - static const int32_t kChinese_Simplified; - static const int32_t kFlemish; - static const int32_t kIrishGaelic; - static const int32_t kAlbanian; - static const int32_t kRomanian; - static const int32_t kCzech; - static const int32_t kSlovak; - static const int32_t kSlovenian; - static const int32_t kYiddish; - static const int32_t kSerbian; - static const int32_t kMacedonian; - static const int32_t kBulgarian; - static const int32_t kUkrainian; - static const int32_t kByelorussian; - static const int32_t kUzbek; - static const int32_t kKazakh; - static const int32_t kAzerbaijani_Cyrillic; - static const int32_t kAzerbaijani_Arabic; - static const int32_t kArmenian; - static const int32_t kGeorgian; - static const int32_t kMoldavian; - static const int32_t kKirghiz; - static const int32_t kTajiki; - static const int32_t kTurkmen; - static const int32_t kMongolian_Mongolian; - static const int32_t kMongolian_Cyrillic; - static const int32_t kPashto; - static const int32_t kKurdish; - static const int32_t kKashmiri; - static const int32_t kSindhi; - static const int32_t kTibetan; - static const int32_t kNepali; - static const int32_t kSanskrit; - static const int32_t kMarathi; - static const int32_t kBengali; - static const int32_t kAssamese; - static const int32_t kGujarati; - static const int32_t kPunjabi; - static const int32_t kOriya; - static const int32_t kMalayalam; - static const int32_t kKannada; - static const int32_t kTamil; - static const int32_t kTelugu; - static const int32_t kSinhalese; - static const int32_t kBurmese; - static const int32_t kKhmer; - static const int32_t kLao; - static const int32_t kVietnamese; - static const int32_t kIndonesian; - static const int32_t kTagalong; - static const int32_t kMalay_Roman; - static const int32_t kMalay_Arabic; - static const int32_t kAmharic; - static const int32_t kTigrinya; - static const int32_t kGalla; - static const int32_t kSomali; - static const int32_t kSwahili; - static const int32_t kKinyarwandaRuanda; - static const int32_t kRundi; - static const int32_t kNyanjaChewa; - static const int32_t kMalagasy; - static const int32_t kEsperanto; - static const int32_t kWelsh; - static const int32_t kBasque; - static const int32_t kCatalan; - static const int32_t kLatin; - static const int32_t kQuenchua; - static const int32_t kGuarani; - static const int32_t kAymara; - static const int32_t kTatar; - static const int32_t kUighur; - static const int32_t kDzongkha; - static const int32_t kJavanese_Roman; - static const int32_t kSundanese_Roman; - static const int32_t kGalician; - static const int32_t kAfrikaans; - static const int32_t kBreton; - static const int32_t kInuktitut; - static const int32_t kScottishGaelic; - static const int32_t kManxGaelic; - static const int32_t kIrishGaelic_WithDotAbove; - static const int32_t kTongan; - static const int32_t kGreek_Polytonic; - static const int32_t kGreenlandic; - static const int32_t kAzerbaijani_Roman; + 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 { - static const int32_t kUnknown; - static const int32_t kAfrikaans_SouthAfrica; - static const int32_t kAlbanian_Albania; - static const int32_t kAlsatian_France; - static const int32_t kAmharic_Ethiopia; - static const int32_t kArabic_Algeria; - static const int32_t kArabic_Bahrain; - static const int32_t kArabic_Egypt; - static const int32_t kArabic_Iraq; - static const int32_t kArabic_Jordan; - static const int32_t kArabic_Kuwait; - static const int32_t kArabic_Lebanon; - static const int32_t kArabic_Libya; - static const int32_t kArabic_Morocco; - static const int32_t kArabic_Oman; - static const int32_t kArabic_Qatar; - static const int32_t kArabic_SaudiArabia; - static const int32_t kArabic_Syria; - static const int32_t kArabic_Tunisia; - static const int32_t kArabic_UAE; - static const int32_t kArabic_Yemen; - static const int32_t kArmenian_Armenia; - static const int32_t kAssamese_India; - static const int32_t kAzeri_Cyrillic_Azerbaijan; - static const int32_t kAzeri_Latin_Azerbaijan; - static const int32_t kBashkir_Russia; - static const int32_t kBasque_Basque; - static const int32_t kBelarusian_Belarus; - static const int32_t kBengali_Bangladesh; - static const int32_t kBengali_India; - static const int32_t kBosnian_Cyrillic_BosniaAndHerzegovina; - static const int32_t kBosnian_Latin_BosniaAndHerzegovina; - static const int32_t kBreton_France; - static const int32_t kBulgarian_Bulgaria; - static const int32_t kCatalan_Catalan; - static const int32_t kChinese_HongKongSAR; - static const int32_t kChinese_MacaoSAR; - static const int32_t kChinese_PeoplesRepublicOfChina; - static const int32_t kChinese_Singapore; - static const int32_t kChinese_Taiwan; - static const int32_t kCorsican_France; - static const int32_t kCroatian_Croatia; - static const int32_t kCroatian_Latin_BosniaAndHerzegovina; - static const int32_t kCzech_CzechRepublic; - static const int32_t kDanish_Denmark; - static const int32_t kDari_Afghanistan; - static const int32_t kDivehi_Maldives; - static const int32_t kDutch_Belgium; - static const int32_t kDutch_Netherlands; - static const int32_t kEnglish_Australia; - static const int32_t kEnglish_Belize; - static const int32_t kEnglish_Canada; - static const int32_t kEnglish_Caribbean; - static const int32_t kEnglish_India; - static const int32_t kEnglish_Ireland; - static const int32_t kEnglish_Jamaica; - static const int32_t kEnglish_Malaysia; - static const int32_t kEnglish_NewZealand; - static const int32_t kEnglish_RepublicOfThePhilippines; - static const int32_t kEnglish_Singapore; - static const int32_t kEnglish_SouthAfrica; - static const int32_t kEnglish_TrinidadAndTobago; - static const int32_t kEnglish_UnitedKingdom; - static const int32_t kEnglish_UnitedStates; - static const int32_t kEnglish_Zimbabwe; - static const int32_t kEstonian_Estonia; - static const int32_t kFaroese_FaroeIslands; - static const int32_t kFilipino_Philippines; - static const int32_t kFinnish_Finland; - static const int32_t kFrench_Belgium; - static const int32_t kFrench_Canada; - static const int32_t kFrench_France; - static const int32_t kFrench_Luxembourg; - static const int32_t kFrench_PrincipalityOfMonoco; - static const int32_t kFrench_Switzerland; - static const int32_t kFrisian_Netherlands; - static const int32_t kGalician_Galician; - static const int32_t kGeorgian_Georgia; - static const int32_t kGerman_Austria; - static const int32_t kGerman_Germany; - static const int32_t kGerman_Liechtenstein; - static const int32_t kGerman_Luxembourg; - static const int32_t kGerman_Switzerland; - static const int32_t kGreek_Greece; - static const int32_t kGreenlandic_Greenland; - static const int32_t kGujarati_India; - static const int32_t kHausa_Latin_Nigeria; - static const int32_t kHebrew_Israel; - static const int32_t kHindi_India; - static const int32_t kHungarian_Hungary; - static const int32_t kIcelandic_Iceland; - static const int32_t kIgbo_Nigeria; - static const int32_t kIndonesian_Indonesia; - static const int32_t kInuktitut_Canada; - static const int32_t kInuktitut_Latin_Canada; - static const int32_t kIrish_Ireland; - static const int32_t kisiXhosa_SouthAfrica; - static const int32_t kisiZulu_SouthAfrica; - static const int32_t kItalian_Italy; - static const int32_t kItalian_Switzerland; - static const int32_t kJapanese_Japan; - static const int32_t kKannada_India; - static const int32_t kKazakh_Kazakhstan; - static const int32_t kKhmer_Cambodia; - static const int32_t kKiche_Guatemala; - static const int32_t kKinyarwanda_Rwanda; - static const int32_t kKiswahili_Kenya; - static const int32_t kKonkani_India; - static const int32_t kKorean_Korea; - static const int32_t kKyrgyz_Kyrgyzstan; - static const int32_t kLao_LaoPDR; - static const int32_t kLatvian_Latvia; - static const int32_t kLithuanian_Lithuania; - static const int32_t kLowerSorbian_Germany; - static const int32_t kLuxembourgish_Luxembourg; - static const int32_t kMacedonian_FYROM_FormerYugoslavRepublicOfMacedonia; - static const int32_t kMalay_BruneiDarussalam; - static const int32_t kMalay_Malaysia; - static const int32_t kMalayalam_India; - static const int32_t kMaltese_Malta; - static const int32_t kMaori_NewZealand; - static const int32_t kMapudungun_Chile; - static const int32_t kMarathi_India; - static const int32_t kMohawk_Mohawk; - static const int32_t kMongolian_Cyrillic_Mongolia; - static const int32_t kMongolian_Traditional_PeoplesRepublicOfChina; - static const int32_t kNepali_Nepal; - static const int32_t kNorwegian_Bokmal_Norway; - static const int32_t kNorwegian_Nynorsk_Norway; - static const int32_t kOccitan_France; - static const int32_t kOriya_India; - static const int32_t kPashto_Afghanistan; - static const int32_t kPolish_Poland; - static const int32_t kPortuguese_Brazil; - static const int32_t kPortuguese_Portugal; - static const int32_t kPunjabi_India; - static const int32_t kQuechua_Bolivia; - static const int32_t kQuechua_Ecuador; - static const int32_t kQuechua_Peru; - static const int32_t kRomanian_Romania; - static const int32_t kRomansh_Switzerland; - static const int32_t kRussian_Russia; - static const int32_t kSami_Inari_Finland; - static const int32_t kSami_Lule_Norway; - static const int32_t kSami_Lule_Sweden; - static const int32_t kSami_Northern_Finland; - static const int32_t kSami_Northern_Norway; - static const int32_t kSami_Northern_Sweden; - static const int32_t kSami_Skolt_Finland; - static const int32_t kSami_Southern_Norway; - static const int32_t kSami_Southern_Sweden; - static const int32_t kSanskrit_India; - static const int32_t kSerbian_Cyrillic_BosniaAndHerzegovina; - static const int32_t kSerbian_Cyrillic_Serbia; - static const int32_t kSerbian_Latin_BosniaAndHerzegovina; - static const int32_t kSerbian_Latin_Serbia; - static const int32_t kSesothoSaLeboa_SouthAfrica; - static const int32_t kSetswana_SouthAfrica; - static const int32_t kSinhala_SriLanka; - static const int32_t kSlovak_Slovakia; - static const int32_t kSlovenian_Slovenia; - static const int32_t kSpanish_Argentina; - static const int32_t kSpanish_Bolivia; - static const int32_t kSpanish_Chile; - static const int32_t kSpanish_Colombia; - static const int32_t kSpanish_CostaRica; - static const int32_t kSpanish_DominicanRepublic; - static const int32_t kSpanish_Ecuador; - static const int32_t kSpanish_ElSalvador; - static const int32_t kSpanish_Guatemala; - static const int32_t kSpanish_Honduras; - static const int32_t kSpanish_Mexico; - static const int32_t kSpanish_Nicaragua; - static const int32_t kSpanish_Panama; - static const int32_t kSpanish_Paraguay; - static const int32_t kSpanish_Peru; - static const int32_t kSpanish_PuertoRico; - static const int32_t kSpanish_ModernSort_Spain; - static const int32_t kSpanish_TraditionalSort_Spain; - static const int32_t kSpanish_UnitedStates; - static const int32_t kSpanish_Uruguay; - static const int32_t kSpanish_Venezuela; - static const int32_t kSweden_Finland; - static const int32_t kSwedish_Sweden; - static const int32_t kSyriac_Syria; - static const int32_t kTajik_Cyrillic_Tajikistan; - static const int32_t kTamazight_Latin_Algeria; - static const int32_t kTamil_India; - static const int32_t kTatar_Russia; - static const int32_t kTelugu_India; - static const int32_t kThai_Thailand; - static const int32_t kTibetan_PRC; - static const int32_t kTurkish_Turkey; - static const int32_t kTurkmen_Turkmenistan; - static const int32_t kUighur_PRC; - static const int32_t kUkrainian_Ukraine; - static const int32_t kUpperSorbian_Germany; - static const int32_t kUrdu_IslamicRepublicOfPakistan; - static const int32_t kUzbek_Cyrillic_Uzbekistan; - static const int32_t kUzbek_Latin_Uzbekistan; - static const int32_t kVietnamese_Vietnam; - static const int32_t kWelsh_UnitedKingdom; - static const int32_t kWolof_Senegal; - static const int32_t kYakut_Russia; - static const int32_t kYi_PRC; - static const int32_t kYoruba_Nigeria; + 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 Table, public RefCounted { private: struct Offset { - static const int32_t kFormat; - static const int32_t kCount; - static const int32_t kStringOffset; - static const int32_t kNameRecordStart; + enum { + kFormat = 0, + kCount = 2, + kStringOffset = 4, + kNameRecordStart = 6, - // format 1 - offset from the end of the name records - static const int32_t kLangTagCount; - static const int32_t kLangTagRecord; - - static const int32_t kNameRecordSize; - // Name Records - static const int32_t kNameRecordPlatformId; - static const int32_t kNameRecordEncodingId; - static const int32_t kNameRecordLanguageId; - static const int32_t kNameRecordNameId; - static const int32_t kNameRecordStringLength; - static const int32_t kNameRecordStringOffset; - }; + // format 1 - offset from the end of the name records + kLangTagCount = 0, + kLangTagRecord = 2, - struct NameId { - static const int32_t kUnknown; - static const int32_t kCopyrightNotice; - static const int32_t kFontFamilyName; - static const int32_t kFontSubfamilyName; - static const int32_t kUniqueFontIdentifier; - static const int32_t kFullFontName; - static const int32_t kVersionString; - static const int32_t kPostscriptName; - static const int32_t kTrademark; - static const int32_t kManufacturerName; - static const int32_t kDesigner; - static const int32_t kDescription; - static const int32_t kVendorURL; - static const int32_t kDesignerURL; - static const int32_t kLicenseDescription; - static const int32_t kLicenseInfoURL; - static const int32_t kReserved15; - static const int32_t kPreferredFamily; - static const int32_t kPreferredSubfamily; - static const int32_t kCompatibleFullName; - static const int32_t kSampleText; - static const int32_t kPostscriptCID; - static const int32_t kWWSFamilyName; - static const int32_t kWWSSubfamilyName; + kNameRecordSize = 12, + // Name Records + kNameRecordPlatformId = 0, + kNameRecordEncodingId = 2, + kNameRecordLanguageId = 4, + kNameRecordNameId = 6, + kNameRecordStringLength = 8, + kNameRecordStringOffset = 10 + }; }; public: diff --git a/sfntly/os2_table.cc b/sfntly/os2_table.cc index 73d98cc..4e7189d 100644 --- a/sfntly/os2_table.cc +++ b/sfntly/os2_table.cc @@ -20,98 +20,6 @@ namespace sfntly { /****************************************************************************** * Constants ******************************************************************************/ -const int32_t OS2Table::Offset::kVersion = 0; -const int32_t OS2Table::Offset::kXAvgCharWidth = 2; -const int32_t OS2Table::Offset::kUsWeightClass = 4; -const int32_t OS2Table::Offset::kUsWidthClass = 6; -const int32_t OS2Table::Offset::kFsType = 8; -const int32_t OS2Table::Offset::kYSubscriptXSize = 10; -const int32_t OS2Table::Offset::kYSubscriptYSize = 12; -const int32_t OS2Table::Offset::kYSubscriptXOffset = 14; -const int32_t OS2Table::Offset::kYSubscriptYOffset = 16; -const int32_t OS2Table::Offset::kYSuperscriptXSize = 18; -const int32_t OS2Table::Offset::kYSuperscriptYSize = 20; -const int32_t OS2Table::Offset::kYSuperscriptXOffset = 22; -const int32_t OS2Table::Offset::kYSuperscriptYOffset = 24; -const int32_t OS2Table::Offset::kYStrikeoutSize = 26; -const int32_t OS2Table::Offset::kYStrikeoutPosition = 28; -const int32_t OS2Table::Offset::kSFamilyClass = 30; -const int32_t OS2Table::Offset::kPanose = 32; -const int32_t OS2Table::Offset::kUlUnicodeRange1 = 42; -const int32_t OS2Table::Offset::kUlUnicodeRange2 = 46; -const int32_t OS2Table::Offset::kUlUnicodeRange3 = 50; -const int32_t OS2Table::Offset::kUlUnicodeRange4 = 54; -const int32_t OS2Table::Offset::kAchVendId = 58; -const int32_t OS2Table::Offset::kFsSelection = 62; -const int32_t OS2Table::Offset::kUsFirstCharIndex = 64; -const int32_t OS2Table::Offset::kUsLastCharIndex = 66; -const int32_t OS2Table::Offset::kSTypoAscender = 68; -const int32_t OS2Table::Offset::kSTypoDescender = 70; -const int32_t OS2Table::Offset::kSTypoLineGap = 72; -const int32_t OS2Table::Offset::kUsWinAscent = 74; -const int32_t OS2Table::Offset::kUsWinDescent = 76; -const int32_t OS2Table::Offset::kUlCodePageRange1 = 78; -const int32_t OS2Table::Offset::kUlCodePageRange2 = 82; -const int32_t OS2Table::Offset::kSxHeight = 86; -const int32_t OS2Table::Offset::kSCapHeight = 88; -const int32_t OS2Table::Offset::kUsDefaultChar = 90; -const int32_t OS2Table::Offset::kUsBreakChar = 92; -const int32_t OS2Table::Offset::kUsMaxContext = 94; - -const int32_t WeightClass::kThin = 100; -const int32_t WeightClass::kExtraLight = 200; -const int32_t WeightClass::kUltraLight = 200; -const int32_t WeightClass::kLight = 300; -const int32_t WeightClass::kNormal = 400; -const int32_t WeightClass::kRegular = 400; -const int32_t WeightClass::kMedium = 500; -const int32_t WeightClass::kSemiBold = 600; -const int32_t WeightClass::kDemiBold = 600; -const int32_t WeightClass::kBold = 700; -const int32_t WeightClass::kExtraBold = 800; -const int32_t WeightClass::kUltraBold = 800; -const int32_t WeightClass::kBlack = 900; -const int32_t WeightClass::kHeavy = 900; - -const int32_t WidthClass::kUltraCondensed = 1; -const int32_t WidthClass::kExtraCondensed = 2; -const int32_t WidthClass::kCondensed = 3; -const int32_t WidthClass::kSemiCondensed = 4; -const int32_t WidthClass::kMedium = 5; -const int32_t WidthClass::kNormal = 5; -const int32_t WidthClass::kSemiExpanded = 6; -const int32_t WidthClass::kExpanded = 7; -const int32_t WidthClass::kExtraExpanded = 8; -const int32_t WidthClass::kUltraExpanded = 9; - -const int32_t EmbeddingFlags::kReserved0 = 1 << 0; -const int32_t EmbeddingFlags::kRestrictedLicenseEmbedding = 1 << 1; -const int32_t EmbeddingFlags::kPreviewAndPrintEmbedding = 1 << 2; -const int32_t EmbeddingFlags::kEditableEmbedding = 1 << 3; -const int32_t EmbeddingFlags::kReserved4 = 1 << 4; -const int32_t EmbeddingFlags::kReserved5 = 1 << 5; -const int32_t EmbeddingFlags::kReserved6 = 1 << 6; -const int32_t EmbeddingFlags::kReserved7 = 1 << 7; -const int32_t EmbeddingFlags::kNoSubsetting = 1 << 8; -const int32_t EmbeddingFlags::kBitmapEmbeddingOnly = 1 << 9; -const int32_t EmbeddingFlags::kReserved10 = 1 << 10; -const int32_t EmbeddingFlags::kReserved11 = 1 << 11; -const int32_t EmbeddingFlags::kReserved12 = 1 << 12; -const int32_t EmbeddingFlags::kReserved13 = 1 << 13; -const int32_t EmbeddingFlags::kReserved14 = 1 << 14; -const int32_t EmbeddingFlags::kReserved15 = 1 << 15; - -const int32_t FsSelection::kITALIC = 1 << 0; -const int32_t FsSelection::kUNDERSCORE = 1 << 1; -const int32_t FsSelection::kNEGATIVE = 1 << 2; -const int32_t FsSelection::kOUTLINED = 1 << 3; -const int32_t FsSelection::kSTRIKEOUT = 1 << 4; -const int32_t FsSelection::kBOLD = 1 << 5; -const int32_t FsSelection::kREGULAR = 1 << 6; -const int32_t FsSelection::kUSE_TYPO_METRICS = 1 << 7; -const int32_t FsSelection::kWWS = 1 << 8; -const int32_t FsSelection::kOBLIQUE = 1 << 9; - 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; diff --git a/sfntly/os2_table.h b/sfntly/os2_table.h index 88d4769..9bf33c2 100644 --- a/sfntly/os2_table.h +++ b/sfntly/os2_table.h @@ -23,56 +23,64 @@ namespace sfntly { struct WeightClass { - static const int32_t kThin; - static const int32_t kExtraLight; - static const int32_t kUltraLight; - static const int32_t kLight; - static const int32_t kNormal; - static const int32_t kRegular; - static const int32_t kMedium; - static const int32_t kSemiBold; - static const int32_t kDemiBold; - static const int32_t kBold; - static const int32_t kExtraBold; - static const int32_t kUltraBold; - static const int32_t kBlack; - static const int32_t kHeavy; + 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 { - static const int32_t kUltraCondensed; - static const int32_t kExtraCondensed; - static const int32_t kCondensed; - static const int32_t kSemiCondensed; - static const int32_t kMedium; - static const int32_t kNormal; - static const int32_t kSemiExpanded; - static const int32_t kExpanded; - static const int32_t kExtraExpanded; - static const int32_t kUltraExpanded; + enum { + kUltraCondensed = 1, + kExtraCondensed = 2, + kCondensed = 3, + kSemiCondensed = 4, + kMedium = 5, + kNormal = 5, + kSemiExpanded = 6, + kExpanded = 7, + kExtraExpanded = 8, + kUltraExpanded = 9 + }; }; struct EmbeddingFlags { - static const int32_t kReserved0; - static const int32_t kRestrictedLicenseEmbedding; - static const int32_t kPreviewAndPrintEmbedding; - static const int32_t kEditableEmbedding; - static const int32_t kReserved4; - static const int32_t kReserved5; - static const int32_t kReserved6; - static const int32_t kReserved7; - static const int32_t kNoSubsetting; - static const int32_t kBitmapEmbeddingOnly; - static const int32_t kReserved10; - static const int32_t kReserved11; - static const int32_t kReserved12; - static const int32_t kReserved13; - static const int32_t kReserved14; - static const int32_t kReserved15; + 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 { + // This enum relies on the ordering of the data matching the ordinal numbers + // of the properties. kBasicLatin, kLatin1Supplement, kLatinExtendedA, @@ -208,18 +216,22 @@ struct UnicodeRange { }; struct FsSelection { - static const int32_t kITALIC; - static const int32_t kUNDERSCORE; - static const int32_t kNEGATIVE; - static const int32_t kOUTLINED; - static const int32_t kSTRIKEOUT; - static const int32_t kBOLD; - static const int32_t kREGULAR; - static const int32_t kUSE_TYPO_METRICS; - static const int32_t kWWS; - static const int32_t kOBLIQUE; + 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 + }; }; +// 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; @@ -290,43 +302,45 @@ struct CodePageRange { class OS2Table : public Table, public RefCounted { private: struct Offset { - static const int32_t kVersion; - static const int32_t kXAvgCharWidth; - static const int32_t kUsWeightClass; - static const int32_t kUsWidthClass; - static const int32_t kFsType; - static const int32_t kYSubscriptXSize; - static const int32_t kYSubscriptYSize; - static const int32_t kYSubscriptXOffset; - static const int32_t kYSubscriptYOffset; - static const int32_t kYSuperscriptXSize; - static const int32_t kYSuperscriptYSize; - static const int32_t kYSuperscriptXOffset; - static const int32_t kYSuperscriptYOffset; - static const int32_t kYStrikeoutSize; - static const int32_t kYStrikeoutPosition; - static const int32_t kSFamilyClass; - static const int32_t kPanose; - static const int32_t kUlUnicodeRange1; - static const int32_t kUlUnicodeRange2; - static const int32_t kUlUnicodeRange3; - static const int32_t kUlUnicodeRange4; - static const int32_t kAchVendId; - static const int32_t kFsSelection; - static const int32_t kUsFirstCharIndex; - static const int32_t kUsLastCharIndex; - static const int32_t kSTypoAscender; - static const int32_t kSTypoDescender; - static const int32_t kSTypoLineGap; - static const int32_t kUsWinAscent; - static const int32_t kUsWinDescent; - static const int32_t kUlCodePageRange1; - static const int32_t kUlCodePageRange2; - static const int32_t kSxHeight; - static const int32_t kSCapHeight; - static const int32_t kUsDefaultChar; - static const int32_t kUsBreakChar; - static const int32_t kUsMaxContext; + 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, + kUlUnicodeRange1 = 42, + kUlUnicodeRange2 = 46, + kUlUnicodeRange3 = 50, + kUlUnicodeRange4 = 54, + kAchVendId = 58, + 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); -- cgit v1.2.3 From 2aa6d0f9873471e25e471f778153eec1001e42e0 Mon Sep 17 00:00:00 2001 From: "arthurhsu@google.com" Date: Mon, 11 Jul 2011 19:04:17 +0000 Subject: Fix bugs and add unit tests to FileInputStream class. Add the class to Linux/Mac builds. git-svn-id: http://sfntly.googlecode.com/svn/trunk/cpp/src@7 672e30a5-4c29-85ac-ac6d-611c735e0a51 --- sfntly/port/file_input_stream.cc | 21 +++++-- test/file_io_test.cc | 131 +++++++++++++++++++++++++++++++++++++++ test/file_io_test.h | 27 ++++++++ test/main.cc | 6 ++ test/test_font_utils.cc | 86 +++++++++++++++++++++++++ test/test_font_utils.h | 36 +++++++++++ 6 files changed, 301 insertions(+), 6 deletions(-) create mode 100644 test/file_io_test.cc create mode 100644 test/file_io_test.h create mode 100644 test/test_font_utils.cc create mode 100644 test/test_font_utils.h diff --git a/sfntly/port/file_input_stream.cc b/sfntly/port/file_input_stream.cc index dcb37f7..d4432bb 100644 --- a/sfntly/port/file_input_stream.cc +++ b/sfntly/port/file_input_stream.cc @@ -59,6 +59,7 @@ void FileInputStream::close() { fclose(file_); length_ = 0; position_ = 0; + file_ = NULL; } } @@ -98,7 +99,6 @@ int32_t FileInputStream::read(ByteVector* b) { int32_t FileInputStream::read(ByteVector* b, int32_t offset, int32_t length) { assert(b); - assert(b->size() >= (size_t)(offset + length)); if (!file_) { #if defined (SFNTLY_NO_EXCEPTION) return 0; @@ -114,6 +114,9 @@ int32_t FileInputStream::read(ByteVector* b, int32_t offset, int32_t length) { #endif } 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; @@ -131,12 +134,16 @@ int64_t FileInputStream::skip(int64_t n) { throw IOException("no opened file"); #endif } - if (n < 0) { - 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); } - size_t skip_count = std::min(length_ - position_, (size_t)n); - fseek(file_, skip_count, SEEK_CUR); - position_ += skip_count; return skip_count; } @@ -156,8 +163,10 @@ void FileInputStream::unread(ByteVector* b, int32_t offset, int32_t length) { } 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; } } // namespace sfntly diff --git a/test/file_io_test.cc b/test/file_io_test.cc new file mode 100644 index 0000000..f3b93ea --- /dev/null +++ b/test/file_io_test.cc @@ -0,0 +1,131 @@ +/* + * 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 "gtest/gtest.h" +#include "sfntly/port/file_input_stream.h" +#include "sfntly/data/font_input_stream.h" + +namespace sfntly { + +bool testFileInputStream() { + const char* test_file = "arial.ttf"; + FILE* file_handle = NULL; +#if defined (WIN32) + fopen_s(&file_handle, test_file, "rb"); +#else + file_handle = fopen(test_file, "rb"); +#endif + if (file_handle == NULL) { + return false; + } + fseek(file_handle, 0, SEEK_END); + size_t length = ftell(file_handle); + fseek(file_handle, 0, SEEK_SET); + ByteVector b1; + b1.resize(length); + fread(&(b1[0]), 1, length, file_handle); + fclose(file_handle); + + // Full file reading test + FileInputStream is; + is.open(test_file); + EXPECT_EQ(length, is.available()); + ByteVector b2; + is.read(&b2, 0, length); + is.close(); + EXPECT_EQ(memcmp(&(b1[0]), &(b2[0]), length), 0); + b2.clear(); + + // Partial reading test + is.open(test_file); + is.skip(89); + is.read(&b2, 0, 100); + EXPECT_EQ(memcmp(&(b1[89]), &(b2[0]), 100), 0); + b2.clear(); + + // Skip test + is.skip(-89); + is.read(&b2, 0, 100); + EXPECT_EQ(memcmp(&(b1[100]), &(b2[0]), 100), 0); + b2.clear(); + is.skip(100); + is.read(&b2, 0, 100); + EXPECT_EQ(memcmp(&(b1[300]), &(b2[0]), 100), 0); + is.skip(-400); + b2.clear(); + + // Offset test + is.read(&b2, 0, 100); + is.read(&b2, 100, 100); + EXPECT_EQ(memcmp(&(b1[0]), &(b2[0]), 200), 0); + + // Unread test + ByteVector b3; + b3.resize(200); + is.unread(&b3); + EXPECT_EQ(memcmp(&(b3[0]), &(b2[0]), 200), 0); + + return true; +} + +bool testFontInputStream() { + const char* test_file = "arial.ttf"; + FILE* file_handle = NULL; +#if defined (WIN32) + fopen_s(&file_handle, test_file, "rb"); +#else + file_handle = fopen(test_file, "rb"); +#endif + if (file_handle == NULL) { + return false; + } + fseek(file_handle, 0, SEEK_END); + size_t length = ftell(file_handle); + fseek(file_handle, 0, SEEK_SET); + ByteVector b1; + b1.resize(length); + fread(&(b1[0]), 1, length, file_handle); + fclose(file_handle); + + FileInputStream is; + is.open(test_file); + FontInputStream font_is1(&is); + EXPECT_EQ(font_is1.available(), length); + + ByteVector b2; + font_is1.read(&b2, 0, length); + font_is1.close(); + EXPECT_EQ(memcmp(&(b1[0]), &(b2[0]), length), 0); + b2.clear(); + + is.open(test_file); + is.skip(89); + FontInputStream font_is2(&is, 200); + font_is2.read(&b2, 0, 100); + EXPECT_EQ(memcmp(&(b1[89]), &(b2[0]), 100), 0); + font_is2.read(&b2, 100, 100); + EXPECT_EQ(memcmp(&(b1[89]), &(b2[0]), 200), 0); + b2.clear(); + font_is2.skip(-200); + font_is2.read(&b2, 0, 100); + EXPECT_EQ(memcmp(&(b1[89]), &(b2[0]), 100), 0); + + return true; +} + +} // namespace sfntly diff --git a/test/file_io_test.h b/test/file_io_test.h new file mode 100644 index 0000000..f929ab4 --- /dev/null +++ b/test/file_io_test.h @@ -0,0 +1,27 @@ +/* + * 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_TEST_FILE_IO_TEST_H_ +#define TYPOGRAPHY_FONT_SFNTLY_SRC_TEST_FILE_IO_TEST_H_ + +namespace sfntly { + +bool testFileInputStream(); +bool testFontInputStream(); + +} // namespace sfntly + +#endif // TYPOGRAPHY_FONT_SFNTLY_SRC_TEST_FILE_IO_TEST_H_ diff --git a/test/main.cc b/test/main.cc index 27862c5..ea17ae3 100644 --- a/test/main.cc +++ b/test/main.cc @@ -22,6 +22,7 @@ #include "test/smart_pointer_test.h" #include "test/endian_test.h" #include "test/byte_array_test.h" +#include "test/file_io_test.h" #include "test/font_data_test.h" #include "test/open_type_data_test.h" #include "test/otf_basic_editing_test.h" @@ -50,6 +51,11 @@ TEST(FontData, All) { } #endif +TEST(FileIO, All) { + EXPECT_TRUE(sfntly::testFileInputStream()); + EXPECT_TRUE(sfntly::testFontInputStream()); +} + TEST(OpenTypeData, All) { EXPECT_TRUE(sfntly::testOTFRead()); EXPECT_TRUE(sfntly::testOTFCopy()); diff --git a/test/test_font_utils.cc b/test/test_font_utils.cc new file mode 100644 index 0000000..d8a7220 --- /dev/null +++ b/test/test_font_utils.cc @@ -0,0 +1,86 @@ +/* + * 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 "gtest/gtest.h" +#include "sfntly/data/memory_byte_array.h" +#include "sfntly/port/file_input_stream.h" +#include "test/test_font_utils.h" + +namespace sfntly { + +void builderForFontFile(const char* font_path, FontFactory* factory, + FontBuilderArray* builders) { + assert(factory); + FileInputStream is; + is.open(font_path); + factory->loadFontsForBuilding(&is, builders); + EXPECT_GT(builders->size(), static_cast(0)); +} + +void serializeFont(const char* font_path, FontFactory* factory, Font* font) { + assert(font_path); + assert(factory); + assert(font); + MemoryOutputStream output_stream; + factory->serializeFont(font, &output_stream); + serializeToFile(&output_stream, font_path); +} + +void loadFont(const char* font_path, FontFactory* factory, FontArray* fonts) { + FileInputStream is; + is.open(font_path); + factory->loadFonts(&is, fonts); + is.close(); +} + +void loadFile(const char* input_file_path, ByteVector* input_buffer) { + assert(input_file_path); + assert(input_buffer); + + FILE* input_file = NULL; +#if defined WIN32 + fopen_s(&input_file, input_file_path, "rb"); +#else + input_file = fopen(input_file_path, "rb"); +#endif + EXPECT_NE(input_file, reinterpret_cast(NULL)); + fseek(input_file, 0, SEEK_END); + size_t file_size = ftell(input_file); + fseek(input_file, 0, SEEK_SET); + input_buffer->resize(file_size); + fread(&((*input_buffer)[0]), 1, file_size, input_file); + fclose(input_file); +} + +void serializeToFile(MemoryOutputStream* output_stream, const char* file_path) { + assert(file_path); + assert(output_stream); + + FILE* output_file = NULL; +#if defined WIN32 + fopen_s(&output_file, file_path, "wb"); +#else + output_file = fopen(file_path, "wb"); +#endif + EXPECT_NE(output_file, reinterpret_cast(NULL)); + fwrite(output_stream->get(), 1, output_stream->size(), output_file); + fflush(output_file); + fclose(output_file); +} + +} // namespace sfntly diff --git a/test/test_font_utils.h b/test/test_font_utils.h new file mode 100644 index 0000000..d3f516d --- /dev/null +++ b/test/test_font_utils.h @@ -0,0 +1,36 @@ +/* + * 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_TEST_TEST_FONT_UTILS_H_ +#define TYPOGRAPHY_FONT_SFNTLY_SRC_TEST_TEST_FONT_UTILS_H_ + +#include "sfntly/font.h" +#include "sfntly/font_factory.h" +#include "sfntly/port/memory_output_stream.h" + +namespace sfntly { + +void builderForFontFile(const char* font_path, FontFactory* factory, + FontBuilderArray* builders); +void serializeFont(const char* font_path, FontFactory* factory, Font* font); +void loadFont(const char* font_path, FontFactory* factory, FontArray* fonts); + +void loadFile(const char* input_file_path, ByteVector* input_buffer); +void serializeToFile(MemoryOutputStream* output_stream, const char* file_path); + +} // namespace sfntly + +#endif // TYPOGRAPHY_FONT_SFNTLY_SRC_TEST_TEST_FONT_UTILS_H_ -- cgit v1.2.3 From ed8406cf320973d04bbe348c681090b1feba3d68 Mon Sep 17 00:00:00 2001 From: "arthurhsu@google.com" Date: Wed, 13 Jul 2011 00:02:17 +0000 Subject: Add more unit tests and fix I/O bugs. Add a public domain font and restructure tests. Change cmake to default output debug builds. Fix VC 2008 compilation issues. git-svn-id: http://sfntly.googlecode.com/svn/trunk/cpp/src@8 672e30a5-4c29-85ac-ac6d-611c735e0a51 --- sfntly/data/byte_array.cc | 4 +- sfntly/data/font_input_stream.cc | 2 +- sfntly/data/font_output_stream.cc | 7 +- sfntly/font.cc | 3 + sfntly/port/memory_output_stream.h | 1 + sfntly/port/type.h | 22 +++++-- sfntly/tag.h | 2 + test/file_io_test.cc | 51 ++++++++++----- test/file_io_test.h | 3 +- test/font_parsing_test.cc | 130 +++++++++++++++++++++++++++++++++++++ test/font_parsing_test.h | 28 ++++++++ test/main.cc | 10 ++- test/otf_basic_editing_test.cc | 34 +++------- test/test_data.cc | 69 ++++++++++++++++++++ test/test_data.h | 44 +++++++++++++ test/test_font_utils.cc | 16 +++++ test/test_font_utils.h | 2 + 17 files changed, 376 insertions(+), 52 deletions(-) create mode 100644 test/font_parsing_test.cc create mode 100644 test/font_parsing_test.h create mode 100644 test/test_data.cc create mode 100644 test/test_data.h diff --git a/sfntly/data/byte_array.cc b/sfntly/data/byte_array.cc index d5af22e..b8c3717 100644 --- a/sfntly/data/byte_array.cc +++ b/sfntly/data/byte_array.cc @@ -141,9 +141,9 @@ int32_t ByteArray::copyTo(OutputStream* os) { 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 = offset; + int32_t index = 0; int32_t buffer_length = std::min(COPY_BUFFER_SIZE, length); - while ((bytes_read = get(index, &b, 0, buffer_length)) > 0) { + while ((bytes_read = get(index + offset, &b, 0, buffer_length)) > 0) { os->write(&b, 0, bytes_read); index += bytes_read; buffer_length = std::min(b.size(), length - index); diff --git a/sfntly/data/font_input_stream.cc b/sfntly/data/font_input_stream.cc index 97c5860..b9eccdb 100644 --- a/sfntly/data/font_input_stream.cc +++ b/sfntly/data/font_input_stream.cc @@ -29,7 +29,7 @@ FontInputStream::FontInputStream(InputStream* is, size_t length) } FontInputStream::~FontInputStream() { - close(); + // Do not close here, underlying InputStream will close themselves. } int32_t FontInputStream::available() { diff --git a/sfntly/data/font_output_stream.cc b/sfntly/data/font_output_stream.cc index 86a153c..f0f4744 100644 --- a/sfntly/data/font_output_stream.cc +++ b/sfntly/data/font_output_stream.cc @@ -26,7 +26,7 @@ FontOutputStream::FontOutputStream(OutputStream* os) } FontOutputStream::~FontOutputStream() { - close(); + // Do not close, underlying stream shall clean up themselves. } size_t FontOutputStream::position() { @@ -36,19 +36,21 @@ size_t FontOutputStream::position() { void FontOutputStream::write(byte_t b) { if (stream_) { stream_->write(b); + position_++; } - position_++; } void FontOutputStream::write(ByteVector* b) { if (b) { write(b, 0, b->size()); + position_ += b->size(); } } void FontOutputStream::write(ByteVector* b, int32_t offset, int32_t length) { if (stream_ && b) { stream_->write(b, offset, length); + position_ += length; } } @@ -101,6 +103,7 @@ void FontOutputStream::close() { if (stream_) { stream_->flush(); stream_->close(); + position_ = 0; } } diff --git a/sfntly/font.cc b/sfntly/font.cc index 1532f49..bd5614f 100644 --- a/sfntly/font.cc +++ b/sfntly/font.cc @@ -154,6 +154,9 @@ void Font::serializeTables(FontOutputStream* fos, #endif } 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; fos->write(&SERIALIZATION_FILLER, 0, filler_size); } diff --git a/sfntly/port/memory_output_stream.h b/sfntly/port/memory_output_stream.h index a7654af..4a7cb74 100644 --- a/sfntly/port/memory_output_stream.h +++ b/sfntly/port/memory_output_stream.h @@ -17,6 +17,7 @@ #ifndef TYPOGRAPHY_FONT_SFNTLY_SRC_SFNTLY_PORT_MEMORY_OUTPUT_STREAM_H_ #define TYPOGRAPHY_FONT_SFNTLY_SRC_SFNTLY_PORT_MEMORY_OUTPUT_STREAM_H_ +#include #include #include "sfntly/port/type.h" diff --git a/sfntly/port/type.h b/sfntly/port/type.h index 25b697e..bb51993 100644 --- a/sfntly/port/type.h +++ b/sfntly/port/type.h @@ -21,17 +21,27 @@ #if defined (_MSC_VER) && (_MSC_VER < 1600) typedef unsigned char uint8_t; - typedef char int8_t; + typedef signed char int8_t; typedef unsigned __int16 uint16_t; - typedef __int16 int16_t; + typedef signed __int16 int16_t; typedef unsigned __int32 uint32_t; - typedef __int32 int32_t; + typedef signed __int32 int32_t; typedef unsigned __int64 uint64_t; - typedef __int64 int64_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 @@ -71,7 +81,9 @@ inline To down_cast(From* f) { // so we only accept pointers #pragma warning(pop) #endif -#if !defined(NDEBUG) +// The following code is the only place for RTTI. It is done so to allow VC++ +// to perform additional type checking in DEBUG builds. +#if defined (_MSC_VER) && !defined(NDEBUG) assert(f == NULL || dynamic_cast(f) != NULL); // RTTI: debug mode only! #endif return static_cast(f); diff --git a/sfntly/tag.h b/sfntly/tag.h index fdebacb..fe6da46 100644 --- a/sfntly/tag.h +++ b/sfntly/tag.h @@ -17,6 +17,8 @@ #ifndef TYPOGRAPHY_FONT_SFNTLY_SRC_SFNTLY_TAG_H_ #define TYPOGRAPHY_FONT_SFNTLY_SRC_SFNTLY_TAG_H_ +#include + #include "sfntly/port/type.h" namespace sfntly { diff --git a/test/file_io_test.cc b/test/file_io_test.cc index f3b93ea..68ab4e5 100644 --- a/test/file_io_test.cc +++ b/test/file_io_test.cc @@ -19,16 +19,16 @@ #include "gtest/gtest.h" #include "sfntly/port/file_input_stream.h" #include "sfntly/data/font_input_stream.h" +#include "test/test_data.h" namespace sfntly { bool testFileInputStream() { - const char* test_file = "arial.ttf"; - FILE* file_handle = NULL; + FILE* file_handle = NULL; #if defined (WIN32) - fopen_s(&file_handle, test_file, "rb"); + fopen_s(&file_handle, SAMPLE_TTF_FILE, "rb"); #else - file_handle = fopen(test_file, "rb"); + file_handle = fopen(SAMPLE_TTF_FILE, "rb"); #endif if (file_handle == NULL) { return false; @@ -43,8 +43,8 @@ bool testFileInputStream() { // Full file reading test FileInputStream is; - is.open(test_file); - EXPECT_EQ(length, is.available()); + is.open(SAMPLE_TTF_FILE); + EXPECT_EQ(length, (size_t)is.available()); ByteVector b2; is.read(&b2, 0, length); is.close(); @@ -52,7 +52,7 @@ bool testFileInputStream() { b2.clear(); // Partial reading test - is.open(test_file); + is.open(SAMPLE_TTF_FILE); is.skip(89); is.read(&b2, 0, 100); EXPECT_EQ(memcmp(&(b1[89]), &(b2[0]), 100), 0); @@ -83,13 +83,12 @@ bool testFileInputStream() { return true; } -bool testFontInputStream() { - const char* test_file = "arial.ttf"; - FILE* file_handle = NULL; +bool testFontInputStreamBasic() { + FILE* file_handle = NULL; #if defined (WIN32) - fopen_s(&file_handle, test_file, "rb"); + fopen_s(&file_handle, SAMPLE_TTF_FILE, "rb"); #else - file_handle = fopen(test_file, "rb"); + file_handle = fopen(SAMPLE_TTF_FILE, "rb"); #endif if (file_handle == NULL) { return false; @@ -103,9 +102,9 @@ bool testFontInputStream() { fclose(file_handle); FileInputStream is; - is.open(test_file); + is.open(SAMPLE_TTF_FILE); FontInputStream font_is1(&is); - EXPECT_EQ(font_is1.available(), length); + EXPECT_EQ((size_t)font_is1.available(), length); ByteVector b2; font_is1.read(&b2, 0, length); @@ -113,7 +112,7 @@ bool testFontInputStream() { EXPECT_EQ(memcmp(&(b1[0]), &(b2[0]), length), 0); b2.clear(); - is.open(test_file); + is.open(SAMPLE_TTF_FILE); is.skip(89); FontInputStream font_is2(&is, 200); font_is2.read(&b2, 0, 100); @@ -128,4 +127,26 @@ bool testFontInputStream() { return true; } +bool testFontInputStreamTableLoading() { + FileInputStream is; + is.open(SAMPLE_TTF_FILE); + FontInputStream font_is(&is); + + font_is.skip(TTF_OFFSET[SAMPLE_TTF_GDEF]); + FontInputStream gdef_is(&font_is, TTF_LENGTH[SAMPLE_TTF_GDEF]); + ByteVector gdef_data; + gdef_is.read(&gdef_data, 0, TTF_LENGTH[SAMPLE_TTF_GDEF]); + EXPECT_EQ(memcmp(&(gdef_data[0]), TTF_GDEF_DATA, + TTF_LENGTH[SAMPLE_TTF_GDEF]), 0); + + font_is.skip(TTF_OFFSET[SAMPLE_TTF_HEAD] - font_is.position()); + FontInputStream head_is(&font_is, TTF_LENGTH[SAMPLE_TTF_HEAD]); + ByteVector head_data; + head_is.read(&head_data, 0, TTF_LENGTH[SAMPLE_TTF_HEAD]); + EXPECT_EQ(memcmp(&(head_data[0]), TTF_HEAD_DATA, + TTF_LENGTH[SAMPLE_TTF_HEAD]), 0); + + return true; +} + } // namespace sfntly diff --git a/test/file_io_test.h b/test/file_io_test.h index f929ab4..ab5c109 100644 --- a/test/file_io_test.h +++ b/test/file_io_test.h @@ -20,7 +20,8 @@ namespace sfntly { bool testFileInputStream(); -bool testFontInputStream(); +bool testFontInputStreamBasic(); +bool testFontInputStreamTableLoading(); } // namespace sfntly diff --git a/test/font_parsing_test.cc b/test/font_parsing_test.cc new file mode 100644 index 0000000..3c9f732 --- /dev/null +++ b/test/font_parsing_test.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 "gtest/gtest.h" + +#include "sfntly/font.h" +#include "sfntly/font_factory.h" +#include "sfntly/font_header_table.h" +#include "sfntly/tag.h" +#include "sfntly/table.h" +#include "sfntly/data/font_input_stream.h" +#include "sfntly/data/memory_byte_array.h" +#include "sfntly/port/file_input_stream.h" +#include "test/font_parsing_test.h" +#include "test/test_data.h" +#include "test/test_font_utils.h" + +namespace sfntly { + +bool testFontParsing() { + ByteVector input_buffer; + loadFile(SAMPLE_TTF_FILE, &input_buffer); + ByteArrayPtr ba = new MemoryByteArray(&(input_buffer[0]), + input_buffer.size()); + + FontFactoryPtr factory = FontFactory::getInstance(); + // File based + FontBuilderArray font_builder_array; + builderForFontFile(SAMPLE_TTF_FILE, factory, &font_builder_array); + FontBuilderPtr font_builder = font_builder_array[0]; + // Memory based + FontBuilderArray font_builder_array2; + factory->loadFontsForBuilding(ba, &font_builder_array2); + FontBuilderPtr font_builder2 = font_builder_array2[0]; + + for (size_t i = 0; i < SAMPLE_TTF_KNOWN_TAGS; ++i) { + EXPECT_TRUE(font_builder->hasTableBuilder(TTF_KNOWN_TAGS[i])); + EXPECT_TRUE(font_builder2->hasTableBuilder(TTF_KNOWN_TAGS[i])); + } + + // Generic table + Ptr gdef_builder = + down_cast( + font_builder->getTableBuilder(Tag::GDEF)); + Ptr gdef_header = gdef_builder->header(); + EXPECT_EQ(gdef_header->length(), TTF_LENGTH[SAMPLE_TTF_GDEF]); + EXPECT_EQ(gdef_header->offset(), TTF_OFFSET[SAMPLE_TTF_GDEF]); + EXPECT_EQ(gdef_header->checksum(), TTF_CHECKSUM[SAMPLE_TTF_GDEF]); + EXPECT_TRUE(gdef_header->checksumValid()); + + WritableFontDataPtr wfd = gdef_builder->data(); + ByteVector b; + b.resize(TTF_LENGTH[SAMPLE_TTF_GDEF]); + wfd->readBytes(0, &b, 0, TTF_LENGTH[SAMPLE_TTF_GDEF]); + EXPECT_EQ(memcmp(&(b[0]), TTF_GDEF_DATA, TTF_LENGTH[SAMPLE_TTF_GDEF]), 0); + + // Header table + FontHeaderTableBuilderPtr header_builder = + down_cast( + font_builder->getTableBuilder(Tag::head)); + Ptr header_header = header_builder->header(); + EXPECT_EQ(header_header->length(), TTF_LENGTH[SAMPLE_TTF_HEAD]); + EXPECT_EQ(header_header->offset(), TTF_OFFSET[SAMPLE_TTF_HEAD]); + EXPECT_EQ(header_header->checksum(), TTF_CHECKSUM[SAMPLE_TTF_HEAD]); + EXPECT_TRUE(header_header->checksumValid()); + + // Data conformance + for (size_t i = 0; i < SAMPLE_TTF_KNOWN_TAGS; ++i) { + ByteVector b1, b2; + b1.resize(TTF_LENGTH[i]); + b2.resize(TTF_LENGTH[i]); + TableBuilderPtr builder1 = + font_builder->getTableBuilder(TTF_KNOWN_TAGS[i]); + TableBuilderPtr builder2 = + font_builder2->getTableBuilder(TTF_KNOWN_TAGS[i]); + WritableFontDataPtr wfd1 = builder1->data(); + WritableFontDataPtr wfd2 = builder2->data(); + wfd1->readBytes(0, &b1, 0, TTF_LENGTH[i]); + wfd2->readBytes(0, &b2, 0, TTF_LENGTH[i]); + EXPECT_EQ(memcmp(&(b1[0]), &(b2[0]), TTF_LENGTH[i]), 0); + } + + return true; +} + +bool testTTFReadWrite() { + FontFactoryPtr factory = FontFactory::getInstance(); + FontBuilderArray font_builder_array; + builderForFontFile(SAMPLE_TTF_FILE, factory, &font_builder_array); + FontBuilderPtr font_builder = font_builder_array[0]; + FontPtr font = font_builder->build(); + MemoryOutputStream output_stream; + factory->serializeFont(font, &output_stream); + EXPECT_GE(output_stream.size(), SAMPLE_TTF_SIZE); + + return true; +} + +bool testTTFMemoryBasedReadWrite() { + ByteVector input_buffer; + loadFile(SAMPLE_TTF_FILE, &input_buffer); + + FontFactoryPtr factory = FontFactory::getInstance(); + FontBuilderArray font_builder_array; + ByteArrayPtr ba = new MemoryByteArray(&(input_buffer[0]), + input_buffer.size()); + factory->loadFontsForBuilding(ba, &font_builder_array); + FontBuilderPtr font_builder = font_builder_array[0]; + FontPtr font = font_builder->build(); + MemoryOutputStream output_stream; + factory->serializeFont(font, &output_stream); + EXPECT_GE(output_stream.size(), input_buffer.size()); + + return true; +} + +} // namespace sfntly diff --git a/test/font_parsing_test.h b/test/font_parsing_test.h new file mode 100644 index 0000000..d66689f --- /dev/null +++ b/test/font_parsing_test.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 TYPOGRAPHY_FONT_SFNTLY_SRC_TEST_FONT_PARSING_TEST_H_ +#define TYPOGRAPHY_FONT_SFNTLY_SRC_TEST_FONT_PARSING_TEST_H_ + +namespace sfntly { + +bool testFontParsing(); +bool testTTFReadWrite(); +bool testTTFMemoryBasedReadWrite(); + +} // namespace sfntly + +#endif // TYPOGRAPHY_FONT_SFNTLY_SRC_TEST_FONT_PARSING_TEST_H_ diff --git a/test/main.cc b/test/main.cc index ea17ae3..4ce1d18 100644 --- a/test/main.cc +++ b/test/main.cc @@ -24,6 +24,7 @@ #include "test/byte_array_test.h" #include "test/file_io_test.h" #include "test/font_data_test.h" +#include "test/font_parsing_test.h" #include "test/open_type_data_test.h" #include "test/otf_basic_editing_test.h" @@ -53,7 +54,8 @@ TEST(FontData, All) { TEST(FileIO, All) { EXPECT_TRUE(sfntly::testFileInputStream()); - EXPECT_TRUE(sfntly::testFontInputStream()); + EXPECT_TRUE(sfntly::testFontInputStreamBasic()); + EXPECT_TRUE(sfntly::testFontInputStreamTableLoading()); } TEST(OpenTypeData, All) { @@ -61,6 +63,12 @@ TEST(OpenTypeData, All) { EXPECT_TRUE(sfntly::testOTFCopy()); } +TEST(FontParsing, All) { + EXPECT_TRUE(sfntly::testFontParsing()); + EXPECT_TRUE(sfntly::testTTFReadWrite()); + EXPECT_TRUE(sfntly::testTTFMemoryBasedReadWrite()); +} + TEST(OTFBasicEditing, All) { EXPECT_TRUE(sfntly::testOTFBasicEditing()); } diff --git a/test/otf_basic_editing_test.cc b/test/otf_basic_editing_test.cc index 233ef14..6c8bde9 100644 --- a/test/otf_basic_editing_test.cc +++ b/test/otf_basic_editing_test.cc @@ -17,39 +17,22 @@ #include "gtest/gtest.h" #include "sfntly/font.h" #include "sfntly/font_factory.h" -#include "sfntly/data/memory_byte_array.h" #include "sfntly/font_header_table.h" #include "sfntly/tag.h" +#include "sfntly/data/memory_byte_array.h" +#include "sfntly/port/endian.h" +#include "sfntly/port/file_input_stream.h" +#include "sfntly/port/memory_output_stream.h" #include "test/otf_basic_editing_test.h" +#include "test/test_data.h" +#include "test/test_font_utils.h" namespace sfntly { -// TODO(arthurhsu): port over TestFontUtils bool testOTFBasicEditing() { - ByteVector input_buffer; -#if defined WIN32 - FILE* input_file; - fopen_s(&input_file, "..\\data\\ext\\arial.ttf", "rb"); -#else - FILE* input_file = fopen("../data/ext/arial.ttf", "rb"); -#endif - EXPECT_TRUE(input_file != NULL); - if (input_file == NULL) { - return false; - } - fseek(input_file, 0, SEEK_END); - size_t file_size = ftell(input_file); - fseek(input_file, 0, SEEK_SET); - input_buffer.resize(file_size); - fread(&(input_buffer[0]), 1, file_size, input_file); - fclose(input_file); - - ByteArrayPtr ba = new MemoryByteArray(&(input_buffer[0]), file_size); FontFactoryPtr factory = FontFactory::getInstance(); - FontBuilderArray font_builder_array; - factory->loadFontsForBuilding(ba, &font_builder_array); - EXPECT_GT(font_builder_array.size(), static_cast(0)); + builderForFontFile(SAMPLE_TTF_FILE, factory, &font_builder_array); FontBuilderPtr font_builder = font_builder_array[0]; // ensure the builder is not bogus @@ -61,7 +44,8 @@ bool testOTFBasicEditing() { EXPECT_TRUE(i->second != NULL); if (i->second == NULL) { char tag[5] = {0}; - memcpy(tag, &(i->first), 4); + int32_t value = toBE32(i->first); + memcpy(tag, &value, 4); fprintf(stderr, "tag %s does not have valid builder\n", tag); } } diff --git a/test/test_data.cc b/test/test_data.cc new file mode 100644 index 0000000..b81f8d9 --- /dev/null +++ b/test/test_data.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/tag.cc" +#include "test/test_data.h" + +namespace sfntly { + +#if defined WIN32 +const char* SAMPLE_TTF_FILE = "Tuffy.ttf"; +const char* SAMPLE_OTF_FILE = "Tuffy.otf"; +#else +const char* SAMPLE_TTF_FILE = "Tuffy.ttf"; +const char* SAMPLE_OTF_FILE = "Tuffy.otf"; +#endif + +const size_t SAMPLE_TTF_SIZE = 18444; +const size_t SAMPLE_TTF_TABLES = 16; +const size_t SAMPLE_TTF_KNOWN_TAGS = 15; +const size_t SAMPLE_TTF_GDEF = 0; +const size_t SAMPLE_TTF_HEAD = 8; + +const int32_t TTF_KNOWN_TAGS[] = { + Tag::GDEF, Tag::GPOS, Tag::GSUB, Tag::OS_2, Tag::cmap, Tag::cvt, + Tag::gasp, Tag::glyf, Tag::head, Tag::hhea, Tag::hmtx, Tag::loca, + Tag::maxp, Tag::name, Tag::post }; + +const int64_t TTF_CHECKSUM[] = { + 0x002900cb, 0xe1b5ef99, 0x6c91748f, 0xae08cb6b, 0xc62ba2e8, 0x00210279, + 0xffff0003, 0x8ed2ba01, 0xe8afc442, 0x0dce8e86, 0x77c44a8a, 0xbfd5cd52, + 0x011200bc, 0x2f64d0e9, 0x6548bddf }; + +const int64_t TTF_OFFSET[] = { + 0x4650, 0x4690, 0x4670, 0x0188, 0x04f4, 0x0738, + 0x4648, 0x08c8, 0x010c, 0x0144, 0x01e0, 0x073c, + 0x0168, 0x3d9c, 0x4468 }; + +const int32_t TTF_LENGTH[] = { + 0x001e, 0x015e, 0x0020, 0x0056, 0x0242, 0x0004, + 0x0008, 0x34d4, 0x0036, 0x0024, 0x0314, 0x018c, + 0x0020, 0x06cb, 0x01dd }; + +const unsigned char TTF_GDEF_DATA[] = { + 0, 1, 0, 0, 0, 0x0c, 0, 0, 0, 0x16, 0, 0, 0, 2, 0, 1, + 0, 3, 0, 0xc4, 0, 1, 0, 4, 0, 0, 0, 2, 0, 0 }; + +const unsigned char TTF_HEAD_DATA[] = { + 0, 1, 0, 0, + 0, 1, 0x19, 0x99, 9, 6, 0x34, 0xb7, 0x5f, 0xf, 0x3c, 0xf5, 0, 0xb, 8, 0, + 0, 0, 0, 0, 0xc1, 0xf5, 0x2f, 0xd2, 0, 0, 0, 0, 0xc1, 0xf5, 0x2f, 0xd2, + 0xff, 0x89, 0xfe, 0x3f, 6, 0x1d, 7, 0xc9, 0, 0, 0, 8, 0, 2, 0, 0, + 0, 0 }; + +const size_t SAMPLE_OTF_SIZE = 18900; + +} // namespace sfntly diff --git a/test/test_data.h b/test/test_data.h new file mode 100644 index 0000000..a505dca --- /dev/null +++ b/test/test_data.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 TYPOGRAPHY_FONT_SFNTLY_SRC_TEST_TEST_DATA_H_ +#define TYPOGRAPHY_FONT_SFNTLY_SRC_TEST_TEST_DATA_H_ + +#include "sfntly/tag.h" + +namespace sfntly { + +extern const char* SAMPLE_TTF_FILE; +extern const char* SAMPLE_OTF_FILE; + +extern const size_t SAMPLE_TTF_SIZE; +extern const size_t SAMPLE_TTF_TABLES; +extern const size_t SAMPLE_TTF_KNOWN_TAGS; +extern const size_t SAMPLE_TTF_GDEF; +extern const size_t SAMPLE_TTF_HEAD; + +extern const int32_t TTF_KNOWN_TAGS[]; +extern const int64_t TTF_CHECKSUM[]; +extern const int64_t TTF_OFFSET[]; +extern const int32_t TTF_LENGTH[]; +extern const unsigned char TTF_GDEF_DATA[]; +extern const unsigned char TTF_HEAD_DATA[]; + +extern const size_t SAMPLE_OTF_SIZE; + +} // namespace sfntly + +#endif // TYPOGRAPHY_FONT_SFNTLY_SRC_TEST_TEST_DATA_H_ diff --git a/test/test_font_utils.cc b/test/test_font_utils.cc index d8a7220..8c3c55f 100644 --- a/test/test_font_utils.cc +++ b/test/test_font_utils.cc @@ -83,4 +83,20 @@ void serializeToFile(MemoryOutputStream* output_stream, const char* file_path) { fclose(output_file); } +void hexDump(const unsigned char* byte_data, size_t length) { + if (byte_data == NULL || length == 0) { + fprintf(stderr, "\n"); + return; + } + + fprintf(stderr, "data length = %ld (%lx)\n", length, length); + for (size_t i = 0; i < length; ++i) { + fprintf(stderr, "%02x ", byte_data[i]); + if ((i & 0xf) == 0xf) { + fprintf(stderr, "\n"); + } + } + fprintf(stderr, "\n"); +} + } // namespace sfntly diff --git a/test/test_font_utils.h b/test/test_font_utils.h index d3f516d..b0c5696 100644 --- a/test/test_font_utils.h +++ b/test/test_font_utils.h @@ -31,6 +31,8 @@ void loadFont(const char* font_path, FontFactory* factory, FontArray* fonts); void loadFile(const char* input_file_path, ByteVector* input_buffer); void serializeToFile(MemoryOutputStream* output_stream, const char* file_path); +void hexDump(const unsigned char* byte_data, size_t length); + } // namespace sfntly #endif // TYPOGRAPHY_FONT_SFNTLY_SRC_TEST_TEST_FONT_UTILS_H_ -- cgit v1.2.3 From 090ea9e59646e627865c40f9758cfed067a575a1 Mon Sep 17 00:00:00 2001 From: "arthurhsu@google.com" Date: Thu, 14 Jul 2011 22:02:49 +0000 Subject: Porting name table implementation, also the corresponding test cases. git-svn-id: http://sfntly.googlecode.com/svn/trunk/cpp/src@9 672e30a5-4c29-85ac-ac6d-611c735e0a51 --- sfntly/name_table.cc | 580 +++++++++++++++++++++++++++++++++++++++------- sfntly/name_table.h | 262 ++++++++++++++++----- sfntly/table.cc | 4 +- test/main.cc | 7 + test/name_editing_test.cc | 227 ++++++++++++++++++ test/name_editing_test.h | 31 +++ 6 files changed, 966 insertions(+), 145 deletions(-) create mode 100644 test/name_editing_test.cc create mode 100644 test/name_editing_test.h diff --git a/sfntly/name_table.cc b/sfntly/name_table.cc index cee6e3d..471c054 100644 --- a/sfntly/name_table.cc +++ b/sfntly/name_table.cc @@ -14,9 +14,14 @@ * limitations under the License. */ -// TODO(arthurhsu): IMPLEMENT: not really used and tested, need cleanup +#include +#include + +#include #include "sfntly/name_table.h" +#include "sfntly/font.h" +#include "sfntly/port/exception_type.h" namespace sfntly { /****************************************************************************** @@ -70,7 +75,7 @@ int32_t NameTable::nameLength(int32_t index) { int32_t NameTable::nameOffset(int32_t index) { return data_->readUShort(Offset::kNameRecordStringOffset + - offsetForNameRecord(index) + stringOffset()); + offsetForNameRecord(index)) + stringOffset(); } void NameTable::nameAsBytes(int32_t index, ByteVector* b) { @@ -81,6 +86,34 @@ void NameTable::nameAsBytes(int32_t index, ByteVector* b) { data_->readBytes(nameOffset(index), b, 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(nameEntry(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(int 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(nameEntry(platform_id, encoding_id, language_id, name_id)); + if (entry) { + return entry->name(); + } + return NULL; +} + CALLER_ATTACH NameTable::NameEntry* NameTable::nameEntry(int32_t index) { ByteVector b; nameAsBytes(index, &b); @@ -89,24 +122,254 @@ CALLER_ATTACH NameTable::NameEntry* NameTable::nameEntry(int32_t index) { return instance.detach(); } +CALLER_ATTACH NameTable::NameEntry* NameTable::nameEntry(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); + NameTable::NameEntryIterator* name_entry_iter = iterator(&filter); + NameEntryPtr result; + if (name_entry_iter->hasNext()) { + result = name_entry_iter->next(); + delete name_entry_iter; + return result; + } + delete name_entry_iter; + return NULL; +} + +NameTable::NameEntryIterator* NameTable::iterator() { + return new NameTable::NameEntryIterator(this); +} + +NameTable::NameEntryIterator* NameTable::iterator(NameEntryFilter* filter) { + return new NameTable::NameEntryIterator(this, filter); +} + +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: // 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; +} + +/****************************************************************************** + * 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; +} + +NameTable::NameEntryId::~NameEntryId() {} + +int32_t NameTable::NameEntryId::getPlatformId() const { + return platform_id_; +} + +int32_t NameTable::NameEntryId::getEncodingId() const { + return encoding_id_; +} + +int32_t NameTable::NameEntryId::getLanguageId() const { + return language_id_; +} + +int32_t NameTable::NameEntryId::getNameId() const { + return name_id_; +} + +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 ******************************************************************************/ void NameTable::NameEntry::init(int32_t platform_id, int32_t encoding_id, int32_t language_id, int32_t name_id, const ByteVector* name_bytes) { - platform_id_ = platform_id; - encoding_id_ = encoding_id; - language_id_ = language_id; - name_id_ = name_id; - if (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::NameEntry::NameEntry() { init(0, 0, 0, 0, NULL); } +NameTable::NameEntry::NameEntry(const NameEntryId& name_entry_id, + const ByteVector& name_bytes) { + init(name_entry_id.getPlatformId(), name_entry_id.getEncodingId(), + name_entry_id.getLanguageId(), name_entry_id.getNameId(), &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) { @@ -114,36 +377,43 @@ NameTable::NameEntry::NameEntry(int32_t platform_id, int32_t encoding_id, } NameTable::NameEntry::~NameEntry() {} -int32_t NameTable::NameEntry::platformId() { return platform_id_; } -int32_t NameTable::NameEntry::encodingId() { return encoding_id_; } -int32_t NameTable::NameEntry::languageId() { return language_id_; } -int32_t NameTable::NameEntry::nameId() { return name_id_; } -int32_t NameTable::NameEntry::nameBytesLength() { return name_bytes_.size(); } -ByteVector* NameTable::NameEntry::nameBytes() { return &name_bytes_; } -bool NameTable::NameEntry::operator==(const NameEntry& obj) { - return (encoding_id_ == obj.encoding_id_ && - language_id_ == obj.language_id_ && - platform_id_ == obj.platform_id_ && - name_id_ == obj.name_id_); +NameTable::NameEntryId& NameTable::NameEntry::getNameEntryId() { + return name_entry_id_; } -int NameTable::NameEntry::hashCode() { - return ((encoding_id_ & 0x3f) << 26) | ((name_id_ & 0x3f) << 16) | - ((platform_id_ & 0x0f) << 12) | (language_id_ & 0xff); +int32_t NameTable::NameEntry::platformId() { + return name_entry_id_.getPlatformId(); } -int NameTable::NameEntry::compareTo(const NameEntry& o) { - if (platform_id_ != o.platform_id_) { - return platform_id_ - o.platform_id_; - } - if (encoding_id_ != o.encoding_id_) { - return encoding_id_ - o.encoding_id_; - } - if (language_id_ != o.language_id_) { - return language_id_ - o.language_id_; - } - return name_id_ - o.name_id_; +int32_t NameTable::NameEntry::encodingId() { + return name_entry_id_.getEncodingId(); +} + +int32_t NameTable::NameEntry::languageId() { + return name_entry_id_.getLanguageId(); +} + +int32_t NameTable::NameEntry::nameId() { + return name_entry_id_.getNameId(); +} + +int32_t NameTable::NameEntry::nameBytesLength() { + return name_bytes_.size(); +} + +ByteVector* NameTable::NameEntry::nameAsBytes() { + return &name_bytes_; +} + +UChar* NameTable::NameEntry::name() { + return NameTable::convertFromNameBytes(&name_bytes_, platformId(), + encodingId()); +} + +bool NameTable::NameEntry::operator==(const NameEntry& rhs) const { + return (name_entry_id_ == rhs.name_entry_id_ && + name_bytes_ == rhs.name_bytes_); } /****************************************************************************** @@ -154,30 +424,92 @@ NameTable::NameEntryBuilder::NameEntryBuilder() { } NameTable::NameEntryBuilder::NameEntryBuilder( - 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); + const NameEntryId& name_entry_id, const ByteVector& name_bytes) { + init(name_entry_id.getPlatformId(), name_entry_id.getEncodingId(), + name_entry_id.getLanguageId(), name_entry_id.getNameId(), &name_bytes); } NameTable::NameEntryBuilder::NameEntryBuilder( - int32_t platform_id, int32_t encoding_id, int32_t language_id, - int32_t name_id) { - init(platform_id, encoding_id, language_id, name_id, NULL); + const NameEntryId& name_entry_id) { + init(name_entry_id.getPlatformId(), name_entry_id.getEncodingId(), + name_entry_id.getLanguageId(), name_entry_id.getNameId(), NULL); } NameTable::NameEntryBuilder::NameEntryBuilder(NameEntry* b) { - init(b->platform_id_, b->encoding_id_, b->language_id_, b->name_id_, - b->nameBytes()); + init(b->platformId(), b->encodingId(), b->languageId(), b->nameId(), + 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_->platformId(), + name_entry_->encodingId(), + &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()); +} + +CALLER_ATTACH NameTable::NameEntry* NameTable::NameEntryBuilder::entry() { + return name_entry_; +} + +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 ******************************************************************************/ +void NameTable::NameEntryIterator::init(NameTable* table, + NameEntryFilter* filter) { + table_ = table; + filter_ = filter; + name_index_ = 0; +} + +NameTable::NameEntryIterator::NameEntryIterator(NameTable* table) { + init(table, NULL); +} + NameTable::NameEntryIterator::NameEntryIterator(NameTable* table, - NameEntryFilter* filter) : - table_(table), name_index_(0), filter_(filter) { + NameEntryFilter* filter) { + init(table, filter); +} + +NameTable::NameEntryIterator::~NameEntryIterator() { } bool NameTable::NameEntryIterator::hasNext() { @@ -198,12 +530,19 @@ bool NameTable::NameEntryIterator::hasNext() { return false; } -NameTable::NameEntry* NameTable::NameEntryIterator::next() { +CALLER_ATTACH NameTable::NameEntry* NameTable::NameEntryIterator::next() { if (!hasNext()) return NULL; return table_->nameEntry(name_index_++); } +void NameTable::NameEntryIterator::remove() { +#if !defined (SFNTLY_NO_EXCEPTION) + throw UnsupportedOperationException( + "Cannot remove a CMap table from an existing font."); +#endif +} + /****************************************************************************** * NameTable::Builder class ******************************************************************************/ @@ -222,50 +561,75 @@ void NameTable::Builder::initialize(ReadableFontData* data) { NameTablePtr table = new NameTable(header(), data); NameEntryIterator name_iter(table, NULL); while (name_iter.hasNext()) { - NameEntryPtr name_entry(name_iter.next()); + NameEntryPtr name_entry = name_iter.next(); NameEntryBuilderPtr name_entry_builder = new NameEntryBuilder(name_entry); - name_entry_map_.insert(NameEntryMapEntry(name_entry_builder, - name_entry_builder)); + NameEntry* builder_entry = name_entry_builder->entry(); + NameEntryId probe = builder_entry->getNameEntryId(); + name_entry_map_[probe] = name_entry_builder; } } } -int32_t NameTable::Builder::subSerialize(WritableFontData* new_data) { - int32_t string_table_start_offset = - NameTable::Offset::kNameRecordStart + name_entry_map_.size() * - NameTable::Offset::kNameRecordSize; +NameTable::NameEntryBuilderMap* NameTable::Builder::getNameBuilders() { + if (name_entry_map_.empty()) { + initialize(internalReadData()); + } + setModelChanged(); + return &name_entry_map_; +} - // 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; - for (NameEntryMap::iterator b = name_entry_map_.begin(), - end = name_entry_map_.end(); b != end; ++b) { - new_data->writeUShort(NameTable::Offset::kNameRecordPlatformId, - b->first->platformId()); - new_data->writeUShort(NameTable::Offset::kNameRecordEncodingId, - b->first->encodingId()); - new_data->writeUShort(NameTable::Offset::kNameRecordLanguageId, - b->first->languageId()); - new_data->writeUShort(NameTable::Offset::kNameRecordNameId, - b->first->nameId()); - new_data->writeUShort(NameTable::Offset::kNameRecordStringLength, - b->first->nameBytesLength()); - new_data->writeUShort(NameTable::Offset::kNameRecordStringOffset, - string_offset); - name_record_offset += NameTable::Offset::kNameRecordSize; - string_offset += new_data->writeBytes( - string_offset + string_table_start_offset, b->first->nameBytes()); +void NameTable::Builder::revertNames() { + name_entry_map_.clear(); + setModelChanged(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; +} - return string_offset + string_table_start_offset; +CALLER_ATTACH FontDataTable* NameTable::Builder::subBuildTable( + ReadableFontData* data) { + FontDataTablePtr table = new NameTable(header(), data); + return table.detach(); } -bool NameTable::Builder::subReadyToSerialize() { - return !name_entry_map_.empty(); +void NameTable::Builder::subDataSet() { + name_entry_map_.clear(); + setModelChanged(false); } int32_t NameTable::Builder::subDataSizeToSerialize() { @@ -275,22 +639,64 @@ int32_t NameTable::Builder::subDataSizeToSerialize() { int32_t size = NameTable::Offset::kNameRecordStart + name_entry_map_.size() * NameTable::Offset::kNameRecordSize; - for (NameEntryMap::iterator b = name_entry_map_.begin(), - end = name_entry_map_.end(); b != end; ++b) { - size += b->first->nameBytesLength(); + for (NameEntryBuilderMap::iterator b = name_entry_map_.begin(), + end = name_entry_map_.end(); + b != end; ++b) { + NameEntryBuilderPtr p = b->second; + NameEntry* entry = p->entry(); + size += entry->nameBytesLength(); } return size; } -void NameTable::Builder::subDataSet() { - name_entry_map_.clear(); - setModelChanged(false); +bool NameTable::Builder::subReadyToSerialize() { + return !name_entry_map_.empty(); } -CALLER_ATTACH FontDataTable* NameTable::Builder::subBuildTable( - ReadableFontData* data) { - FontDataTablePtr table = new NameTable(header(), data); - return table.detach(); +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.getPlatformId()); + new_data->writeUShort( + name_record_offset + NameTable::Offset::kNameRecordEncodingId, + b->first.getEncodingId()); + new_data->writeUShort( + name_record_offset + NameTable::Offset::kNameRecordLanguageId, + b->first.getLanguageId()); + new_data->writeUShort( + name_record_offset + NameTable::Offset::kNameRecordNameId, + b->first.getNameId()); + NameEntry* builder_entry = b->second->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; } } // namespace sfntly diff --git a/sfntly/name_table.h b/sfntly/name_table.h index 948c6b9..6d5df2b 100644 --- a/sfntly/name_table.h +++ b/sfntly/name_table.h @@ -14,15 +14,24 @@ * limitations under the License. */ -// TODO(arthurhsu): IMPLEMENT: not really used and tested, need cleanup #ifndef TYPOGRAPHY_FONT_SFNTLY_SRC_SFNTLY_NAME_TABLE_H_ #define TYPOGRAPHY_FONT_SFNTLY_SRC_SFNTLY_NAME_TABLE_H_ +// Must include this before ICU to avoid stdint redefinition issue. +#include "sfntly/port/type.h" + +#include +#include + #include #include #include "sfntly/table.h" +#if defined U_USING_ICU_NAMESPACE + U_NAMESPACE_USE +#endif + namespace sfntly { struct NameId { @@ -422,52 +431,152 @@ class NameTable : public Table, public RefCounted { }; }; + NameTable(Header* header, ReadableFontData* data); + + public: + virtual ~NameTable(); + virtual int32_t format(); + + // Get the number of names in the name table. + virtual int32_t nameCount(); + + private: + // 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); + + public: + // 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); + + private: + // 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); + public: + // 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(int 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); + + class NameEntry; + virtual CALLER_ATTACH NameEntry* nameEntry(int32_t index); + virtual CALLER_ATTACH NameEntry* nameEntry(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*); + + class NameEntryId { + protected: + mutable int32_t platform_id_; + mutable int32_t encoding_id_; + mutable int32_t language_id_; + mutable int32_t name_id_; + + 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&); + virtual ~NameEntryId(); + virtual int32_t getPlatformId() const; + virtual int32_t getEncodingId() const; + virtual int32_t getLanguageId() const; + virtual int32_t getNameId() const; + virtual const NameEntryId& operator=(const NameEntryId& rhs) const; + virtual bool operator==(const NameEntryId& rhs) const; + virtual bool operator<(const NameEntryId& rhs) const; + }; + + // Class to represent a name entry in the name table. class NameEntryBuilder; 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 void init(int32_t platform_id, int32_t encoding_id, - int32_t language_id, int32_t name_id, - const ByteVector* name_bytes); virtual ~NameEntry(); + virtual NameEntryId& getNameEntryId(); virtual int32_t platformId(); virtual int32_t encodingId(); virtual int32_t languageId(); virtual int32_t nameId(); - virtual bool operator==(const NameEntry& obj); - virtual int hashCode(); - virtual int compareTo(const NameEntry& obj); virtual int32_t nameBytesLength(); // C++ port only - virtual ByteVector* nameBytes(); + virtual ByteVector* nameAsBytes(); + virtual UChar* name(); + virtual bool operator==(const NameEntry& rhs) const; - protected: - int32_t platform_id_; - int32_t encoding_id_; - int32_t language_id_; - int32_t name_id_; + 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; }; - class NameEntryBuilder : public NameEntry { + // C++ port: we don't use original Java hierarchy to avoid ref count issues + // and nasty protected members. + class NameEntryBuilder : public RefCounted { public: NameEntryBuilder(); - NameEntryBuilder(int32_t platform_id, int32_t encoding_id, - int32_t language_id, int32_t name_id, + NameEntryBuilder(const NameEntryId& name_entry_id, const ByteVector& name_bytes); - NameEntryBuilder(int32_t platform_id, int32_t encoding_id, - int32_t language_id, int32_t name_id); + 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 member functions. CALLER_ATTACH is not added because the + // lifetime shall be controlled by build, therefore the caller shall not + // increase the ref count. + NameEntry* 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 Ptr NameEntryBuilderPtr; - typedef std::map NameEntryMap; - typedef std::pair NameEntryMapEntry; class NameEntryFilter { public: @@ -477,63 +586,104 @@ class NameTable : public Table, public RefCounted { virtual ~NameEntryFilter() {} }; - class Builder : public Table::ArrayElementTableBuilder { + // C++ port only + class NameEntryFilterInPlace : public NameEntryFilter { public: - // Constructor scope altered to public because C++ does not allow base - // class to instantiate derived class with protected constructors. - Builder(FontDataTableBuilderContainer* font_builder, Header* header, - WritableFontData* data); - Builder(FontDataTableBuilderContainer* font_builder, Header* header, - ReadableFontData* data); - - virtual int32_t subSerialize(WritableFontData* new_data); - virtual bool subReadyToSerialize(); - virtual int32_t subDataSizeToSerialize(); - virtual void subDataSet(); - virtual CALLER_ATTACH FontDataTable* subBuildTable(ReadableFontData* data); - - private: - void initialize(ReadableFontData* data); + 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: - NameEntryMap name_entry_map_; + int32_t platform_id_; + int32_t encoding_id_; + int32_t language_id_; + int32_t name_id_; }; class NameEntryIterator { public: // If filter is NULL, filter through all tables. + explicit NameEntryIterator(NameTable* table); NameEntryIterator(NameTable* table, NameEntryFilter* filter); - bool hasNext(); - NameEntry* next(); + // Make gcc -Wnon-virtual-dtor happy. + virtual ~NameEntryIterator(); + virtual bool hasNext(); + virtual CALLER_ATTACH NameEntry* next(); + virtual void remove(); private: + void init(NameTable* table, NameEntryFilter* filter); + NameTable* table_; // use dumb pointer since it's a composition object int32_t name_index_; NameEntryFilter* filter_; }; + // caller delete the object + virtual NameEntryIterator* iterator(); + virtual NameEntryIterator* iterator(NameEntryFilter* filter); + private: - NameTable(Header* header, ReadableFontData* data); + static const char* getEncodingName(int32_t platform_id, int32_t encoding_id); + static UConverter* getCharset(int32_t platform_id, int32_t encoding_id); + static void convertToNameBytes(const UChar* name, int32_t platform_id, + int32_t encoding_id, ByteVector* b); + static UChar* convertFromNameBytes(ByteVector* name_bytes, + int32_t platform_id, int32_t encoding_id); public: - virtual ~NameTable(); - virtual int32_t format(); - virtual int32_t nameCount(); - virtual int32_t platformId(int32_t index); - virtual int32_t encodingId(int32_t index); - virtual int32_t languageId(int32_t index); - virtual int32_t nameId(int32_t index); - virtual void nameAsBytes(int32_t index, ByteVector* b); - virtual CALLER_ATTACH NameEntry* nameEntry(int32_t index); + typedef std::map > NameEntryBuilderMap; - private: - int32_t stringOffset(); - int32_t offsetForNameRecord(int32_t index); - int32_t nameLength(int32_t index); - int32_t nameOffset(int32_t index); -}; + class Builder : public Table::ArrayElementTableBuilder, + public RefCounted { + public: + // Constructor scope altered to public because C++ does not allow base + // class to instantiate derived class with protected constructors. + Builder(FontDataTableBuilderContainer* font_builder, Header* header, + WritableFontData* data); + Builder(FontDataTableBuilderContainer* font_builder, Header* header, + ReadableFontData* data); + + private: + void initialize(ReadableFontData* data); + NameEntryBuilderMap* getNameBuilders(); + + public: // static class in Java, functions are not virtual unless inherited + void revertNames(); + int32_t builderCount(); + + // Note: For C++ port, this is not implemented so far. 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(); + + bool has(int32_t platform_id, int32_t encoding_id, int32_t language_id, + int32_t name_id); + CALLER_ATTACH NameEntryBuilder* nameBuilder(int32_t platform_id, + int32_t encoding_id, int32_t language_id, int32_t name_id); + bool remove(int32_t platform_id, int32_t encoding_id, int32_t language_id, + int32_t name_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: + NameEntryBuilderMap name_entry_map_; + }; +}; // class NameTable typedef Ptr NameTablePtr; typedef Ptr NameEntryPtr; +typedef Ptr NameTableBuilderPtr; +typedef Ptr NameEntryBuilderPtr; } // namespace sfntly diff --git a/sfntly/table.cc b/sfntly/table.cc index 856f32e..8a1ec02 100644 --- a/sfntly/table.cc +++ b/sfntly/table.cc @@ -169,10 +169,10 @@ CALLER_ATTACH Table::Builder* Table::Builder::getBuilder( } else if (tag == Tag::maxp) { builder_raw = static_cast( new MaximumProfileTable::Builder(font_builder, header, table_data)); - }/* else if (tag == Tag::name) { + } else if (tag == Tag::name) { builder_raw = static_cast( new NameTable::Builder(font_builder, header, table_data)); - }*/ else if (tag == Tag::OS_2) { + } else if (tag == Tag::OS_2) { builder_raw = static_cast( new OS2Table::Builder(font_builder, header, table_data)); }/* else if (tag == Tag::PostScript) { diff --git a/test/main.cc b/test/main.cc index 4ce1d18..72cc4ea 100644 --- a/test/main.cc +++ b/test/main.cc @@ -27,6 +27,7 @@ #include "test/font_parsing_test.h" #include "test/open_type_data_test.h" #include "test/otf_basic_editing_test.h" +#include "test/name_editing_test.h" #define RUN_LENGTHY_TESTS @@ -72,3 +73,9 @@ TEST(FontParsing, All) { TEST(OTFBasicEditing, All) { EXPECT_TRUE(sfntly::testOTFBasicEditing()); } + +TEST(NameEditing, All) { + EXPECT_TRUE(sfntly::testChangeOneName()); + EXPECT_TRUE(sfntly::testModifyNameTableAndRevert()); + EXPECT_TRUE(sfntly::testRemoveOneName()); +} diff --git a/test/name_editing_test.cc b/test/name_editing_test.cc new file mode 100644 index 0000000..7b87b78 --- /dev/null +++ b/test/name_editing_test.cc @@ -0,0 +1,227 @@ +/* + * 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. + */ + +// Must include this before ICU to avoid stdint redefinition issue. +#include "sfntly/port/type.h" + +#include +#include + +#include "gtest/gtest.h" +#include "sfntly/font.h" +#include "sfntly/font_factory.h" +#include "sfntly/name_table.h" +#include "sfntly/tag.h" +#include "sfntly/data/memory_byte_array.h" +#include "sfntly/port/memory_output_stream.h" +#include "test/test_data.h" +#include "test/test_font_utils.h" +#include "test/name_editing_test.h" + +namespace sfntly { + +static ByteVector input_buffer; +static ByteArrayPtr ba; + +void loadTestFile(FontFactory* factory, FontBuilderArray* font_builders) { + assert(factory); + assert(font_builders); + if (ba == NULL) { + loadFile(SAMPLE_TTF_FILE, &input_buffer); + ba = new MemoryByteArray(&(input_buffer[0]), input_buffer.size()); + } + + factory->loadFontsForBuilding(ba, font_builders); +} + +bool testChangeOneName() { + FontFactoryPtr factory = FontFactory::getInstance(); + FontBuilderArray font_builder_array; + loadTestFile(factory, &font_builder_array); + FontBuilderPtr font_builder = font_builder_array[0]; + + NameTableBuilderPtr name_builder = down_cast( + font_builder->getTableBuilder(Tag::name)); + + // Change the font name. + NameEntryBuilderPtr neb = + name_builder->nameBuilder(PlatformId::kWindows, + WindowsEncodingId::kUnicodeUCS2, + WindowsLanguageId::kEnglish_UnitedStates, + NameId::kFontFamilyName); + U_STRING_DECL(new_name, "Timothy", 7); + neb->setName(new_name); + + // Build the font. + FontPtr font = font_builder->build(); + + // Serialize and reload the serialized font. + MemoryOutputStream os; + factory->serializeFont(font, &os); + FontArray font_array; + ByteArrayPtr new_ba = new MemoryByteArray(os.get(), os.size()); + factory->loadFonts(new_ba, &font_array); + FontPtr new_font = font_array[0]; + + // Check the font name. + NameTablePtr name_table = down_cast(font->table(Tag::name)); + UChar* name = name_table->name(PlatformId::kWindows, + WindowsEncodingId::kUnicodeUCS2, + WindowsLanguageId::kEnglish_UnitedStates, + NameId::kFontFamilyName); + EXPECT_TRUE(name != NULL); + EXPECT_EQ(u_strcmp(name, new_name), 0); + delete[] name; + return true; +} + +bool testModifyNameTableAndRevert() { + FontFactoryPtr factory = FontFactory::getInstance(); + FontBuilderArray font_builder_array; + loadTestFile(factory, &font_builder_array); + FontBuilderPtr font_builder = font_builder_array[0]; + + NameTableBuilderPtr name_builder = down_cast( + font_builder->getTableBuilder(Tag::name)); + + // Change the font name. + NameEntryBuilderPtr neb = + name_builder->nameBuilder(PlatformId::kWindows, + WindowsEncodingId::kUnicodeUCS2, + WindowsLanguageId::kEnglish_UnitedStates, + NameId::kFontFamilyName); + NameTable::NameEntry* neb_entry = neb->entry(); + UChar* original_name = neb_entry->name(); + EXPECT_TRUE(original_name != NULL); + + U_STRING_DECL(new_name, "Timothy", 7); + neb->setName(new_name); + name_builder->revertNames(); + + // Build the font. + FontPtr font = font_builder->build(); + + // Serialize and reload the serialized font. + MemoryOutputStream os; + factory->serializeFont(font, &os); + FontArray font_array; + ByteArrayPtr new_ba = new MemoryByteArray(os.get(), os.size()); + factory->loadFonts(new_ba, &font_array); + FontPtr new_font = font_array[0]; + + // Check the font name. + NameTablePtr name_table = down_cast(font->table(Tag::name)); + UChar* name = name_table->name(PlatformId::kWindows, + WindowsEncodingId::kUnicodeUCS2, + WindowsLanguageId::kEnglish_UnitedStates, + NameId::kFontFamilyName); + + EXPECT_EQ(u_strcmp(name, original_name), 0); + delete name; + delete original_name; + + return true; +} + +bool testRemoveOneName() { + FontFactoryPtr factory = FontFactory::getInstance(); + FontBuilderArray font_builder_array; + loadTestFile(factory, &font_builder_array); + FontBuilderPtr font_builder = font_builder_array[0]; + + NameTableBuilderPtr name_builder = down_cast( + font_builder->getTableBuilder(Tag::name)); + + EXPECT_TRUE(name_builder->has(PlatformId::kWindows, + WindowsEncodingId::kUnicodeUCS2, + WindowsLanguageId::kEnglish_UnitedStates, + NameId::kFontFamilyName)); + EXPECT_TRUE(name_builder->remove(PlatformId::kWindows, + WindowsEncodingId::kUnicodeUCS2, + WindowsLanguageId::kEnglish_UnitedStates, + NameId::kFontFamilyName)); + + // Build the font. + FontPtr font = font_builder->build(); + + // Serialize and reload the serialized font. + MemoryOutputStream os; + factory->serializeFont(font, &os); + FontArray font_array; + ByteArrayPtr new_ba = new MemoryByteArray(os.get(), os.size()); + factory->loadFonts(new_ba, &font_array); + FontPtr new_font = font_array[0]; + + // Check the font name. + NameTablePtr name_table = down_cast(font->table(Tag::name)); + UChar* name = name_table->name(PlatformId::kWindows, + WindowsEncodingId::kUnicodeUCS2, + WindowsLanguageId::kEnglish_UnitedStates, + NameId::kFontFamilyName); + EXPECT_TRUE(name == NULL); + + return true; +} + +// Note: Function is not implemented but the test case is built. Uncomment +// when NameTable::clear() is implemented. +/* +bool testClearAllNamesAndSetOne() { + FontFactoryPtr factory = FontFactory::getInstance(); + FontBuilderArray font_builder_array; + loadTestFile(factory, &font_builder_array); + FontBuilderPtr font_builder = font_builder_array[0]; + + NameTableBuilderPtr name_builder = down_cast( + font_builder->getTableBuilder(Tag::name)); + + EXPECT_GT(name_builder->builderCount(), 0); + name_builder->clear(); + EXPECT_EQ(name_builder->builderCount(), 0); + + // Change the font name. + NameEntryBuilderPtr neb = + name_builder->nameBuilder(PlatformId::kWindows, + WindowsEncodingId::kUnicodeUCS2, + WindowsLanguageId::kEnglish_UnitedStates, + NameId::kFontFamilyName); + U_STRING_DECL(new_name, "Fred", 4); + neb->setName(new_name); + + // Build the font. + FontPtr font = font_builder->build(); + + // Serialize and reload the serialized font. + MemoryOutputStream os; + factory->serializeFont(font, &os); + FontArray font_array; + ByteArrayPtr new_ba = new MemoryByteArray(os.get(), os.size()); + factory->loadFonts(new_ba, &font_array); + FontPtr new_font = font_array[0]; + + // Check the font name. + NameTablePtr name_table = down_cast(font->table(Tag::name)); + UChar* name = name_table->name(PlatformId::kWindows, + WindowsEncodingId::kUnicodeUCS2, + WindowsLanguageId::kEnglish_UnitedStates, + NameId::kFontFamilyName); + EXPECT_EQ(name_table->nameCount(), 1); + EXPECT_EQ(u_strcmp(name, new_name), 0); + return true; +} +*/ + +} // namespace sfntly diff --git a/test/name_editing_test.h b/test/name_editing_test.h new file mode 100644 index 0000000..b5edf0f --- /dev/null +++ b/test/name_editing_test.h @@ -0,0 +1,31 @@ +/* + * 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_TEST_NAME_EDITING_TEST_H_ +#define TYPOGRAPHY_FONT_SFNTLY_SRC_TEST_NAME_EDITING_TEST_H_ + +namespace sfntly { + +bool testChangeOneName(); +bool testModifyNameTableAndRevert(); +bool testRemoveOneName(); +// Note: Function is not implemented but the test case is built. Uncomment +// when NameTable::clear() is implemented. +// bool testClearAllNamesAndSetOne(); + +} // namespace sfntly + +#endif // TYPOGRAPHY_FONT_SFNTLY_SRC_TEST_NAME_EDITING_TEST_H_ -- cgit v1.2.3 From 6b5ae74df6b2ff199c63923219c9a18bd9c4d931 Mon Sep 17 00:00:00 2001 From: "arthurhsu@google.com" Date: Thu, 21 Jul 2011 17:54:40 +0000 Subject: CMap porting and unit tests (partial) Author: Dan-george Filimon (dfilimon@google.com) Checked in by arthur@google.com since Dan hasn't got committer status yet. git-svn-id: http://sfntly.googlecode.com/svn/trunk/cpp/src@18 672e30a5-4c29-85ac-ac6d-611c735e0a51 --- sfntly/cmap_table.cc | 117 +++++++++++++++++++++++++++++++++--------------- sfntly/cmap_table.h | 35 ++++++++++++--- test/main.cc | 13 ++++++ test/test_utils.cc | 88 ++++++++++++++++++++++++++++++++++++ test/test_utils.h | 100 +++++++++++++++++++++++++++++++++++++++++ test/test_utils_test.cc | 87 +++++++++++++++++++++++++++++++++++ test/test_utils_test.h | 28 ++++++++++++ 7 files changed, 426 insertions(+), 42 deletions(-) create mode 100644 test/test_utils.cc create mode 100644 test/test_utils.h create mode 100644 test/test_utils_test.cc create mode 100644 test/test_utils_test.h diff --git a/sfntly/cmap_table.cc b/sfntly/cmap_table.cc index e73b657..8cbc83e 100644 --- a/sfntly/cmap_table.cc +++ b/sfntly/cmap_table.cc @@ -16,6 +16,8 @@ // TODO(arthurhsu): IMPLEMENT: not really used and tested, need cleanup +#include + #include "sfntly/cmap_table.h" #include "sfntly/name_table.h" #include "sfntly/font.h" @@ -125,13 +127,15 @@ int32_t CMapTable::CMap::encodingId() { return cmap_id_.encodingId(); } * CMapTable::CMap::Builder class ******************************************************************************/ CMapTable::CMap::Builder::Builder(FontDataTableBuilderContainer* container, - ReadableFontData* data, int32_t format, const CMapId& cmap_id) : - SubTable::Builder(container, data), format_(format), cmap_id_(cmap_id) { + ReadableFontData* data, int32_t format, + const CMapId& cmap_id) + : SubTable::Builder(container, data), format_(format), cmap_id_(cmap_id) { } CMapTable::CMap::Builder::Builder(FontDataTableBuilderContainer* container, - WritableFontData* data, int32_t format, const CMapId& cmap_id) : - SubTable::Builder(container, data), format_(format), cmap_id_(cmap_id) { + WritableFontData* data, int32_t format, + const CMapId& cmap_id) + : SubTable::Builder(container, data), format_(format), cmap_id_(cmap_id) { } CMapTable::CMap::Builder::~Builder() {} @@ -171,12 +175,12 @@ CALLER_ATTACH CMapTable::CMap::Builder* CMapTable::CMap::Builder::getBuilder( int32_t format = data->readUShort(offset); CMapBuilderPtr builder; switch (format) { - case CMapFormat::kFormat0: - builder = new CMapFormat0::Builder(container, data, offset, cmap_id); - case CMapFormat::kFormat2: - builder = new CMapFormat0::Builder(container, data, offset, cmap_id); - default: - break; + case CMapFormat::kFormat0: + builder = new CMapFormat0::Builder(container, data, offset, cmap_id); + case CMapFormat::kFormat2: + builder = new CMapFormat0::Builder(container, data, offset, cmap_id); + default: + break; } return builder.detach(); } @@ -185,7 +189,8 @@ CALLER_ATTACH CMapTable::CMap::Builder* CMapTable::CMap::Builder::getBuilder( * CMapTable::CMapFormat0 and CMapTable::CMapFormat0::Builder ******************************************************************************/ CMapTable::CMapFormat0::CMapFormat0(ReadableFontData* data, - const CMapId& cmap_id) : CMap(data, CMapFormat::kFormat0, cmap_id) { + const CMapId& cmap_id) + : CMap(data, CMapFormat::kFormat0, cmap_id) { } CMapTable::CMapFormat0::~CMapFormat0() {} @@ -206,9 +211,9 @@ CMapTable::CMapFormat0::Builder::Builder( int32_t offset, const CMapId& cmap_id) : CMapTable::CMap::Builder(container, data ? down_cast( - data->slice(offset, data->readUShort( - offset + Offset::kFormat0Length))) - : reinterpret_cast(NULL), + data->slice(offset, data->readUShort( + offset + Offset::kFormat0Length))) + : reinterpret_cast(NULL), CMapFormat::kFormat0, cmap_id) { // TODO(arthurhsu): FIXIT: heavy lifting and leak, need fix. } @@ -218,9 +223,9 @@ CMapTable::CMapFormat0::Builder::Builder( int32_t offset, const CMapId& cmap_id) : CMapTable::CMap::Builder(container, data ? down_cast( - data->slice(offset, data->readUShort( - offset + Offset::kFormat0Length))) - : reinterpret_cast(NULL), + data->slice(offset, data->readUShort( + offset + Offset::kFormat0Length))) + : reinterpret_cast(NULL), CMapFormat::kFormat0, cmap_id) { // TODO(arthurhsu): FIXIT: heavy lifting and leak, need fix. } @@ -237,7 +242,8 @@ CALLER_ATTACH FontDataTable* CMapTable::CMapFormat0::Builder::subBuildTable( * CMapTable::CMapFormat2 and CMapTable::CMapFormat2::Builder ******************************************************************************/ CMapTable::CMapFormat2::CMapFormat2(ReadableFontData* data, - const CMapId& cmap_id) : CMap(data, CMapFormat::kFormat2, cmap_id) { + const CMapId& cmap_id) + : CMap(data, CMapFormat::kFormat2, cmap_id) { } CMapTable::CMapFormat2::~CMapFormat2() {} @@ -305,8 +311,8 @@ int32_t CMapTable::CMapFormat2::glyphId(int32_t character) { // 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; + id_range_offset + + (low_byte - first_code) * DataSize::kUSHORT; int p = data_->readUShort(p_location); if (p == 0) { return CMapTable::NOTDEF; @@ -328,9 +334,9 @@ CMapTable::CMapFormat2::Builder::Builder( int32_t offset, const CMapId& cmap_id) : CMapTable::CMap::Builder(container, data ? down_cast( - data->slice(offset, data->readUShort( - offset + Offset::kFormat0Length))) - : reinterpret_cast(NULL), + data->slice(offset, data->readUShort( + offset + Offset::kFormat0Length))) + : reinterpret_cast(NULL), CMapFormat::kFormat2, cmap_id) { // TODO(arthurhsu): FIXIT: heavy lifting and leak, need fix. } @@ -340,9 +346,9 @@ CMapTable::CMapFormat2::Builder::Builder( int32_t offset, const CMapId& cmap_id) : CMapTable::CMap::Builder(container, data ? down_cast( - data->slice(offset, data->readUShort( - offset + Offset::kFormat0Length))) - : reinterpret_cast(NULL), + data->slice(offset, data->readUShort( + offset + Offset::kFormat0Length))) + : reinterpret_cast(NULL), CMapFormat::kFormat2, cmap_id) { // TODO(arthurhsu): FIXIT: heavy lifting and leak, need fix. } @@ -391,23 +397,64 @@ CMapTable::Builder::Builder(FontDataTableBuilderContainer* font_builder, } int32_t CMapTable::Builder::subSerialize(WritableFontData* new_data) { - // TODO(arthurhsu): IMPLEMENT - UNREFERENCED_PARAMETER(new_data); - return 0; + int32_t size = new_data->writeUShort(CMapTable::Offset::kVersion, + version_); + size += new_data->writeUShort(CMapTable::Offset::kNumTables, + cmap_builders_.size()); + + int32_t index_offset = size; + size += cmap_builders_.size() * CMapTable::Offset::kEncodingRecordSize; + for (CMapBuilderMap::iterator it = cmap_builders_.begin(), + e = cmap_builders_.end(); it != e; ++it) { + CMapBuilderPtr b = it->second; + // header entry + index_offset += new_data->writeUShort(index_offset, b->platformId()); + index_offset += new_data->writeUShort(index_offset, b->encodingId()); + 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() { - // TODO(arthurhsu): IMPLEMENT - return false; + if (cmap_builders_.empty()) + return false; + + // check each table + for (CMapBuilderMap::iterator it = cmap_builders_.begin(), + e = cmap_builders_.end(); it != e; ++it) { + if (!it->second->subReadyToSerialize()) + return false; + } + return true; } int32_t CMapTable::Builder::subDataSizeToSerialize() { - // TODO(arthurhsu): IMPLEMENT - return 0; + if (cmap_builders_.empty()) + return 0; + + bool variable = false; + int32_t size = CMapTable::Offset::kEncodingRecordStart + + cmap_builders_.size() * CMapTable::Offset::kEncodingRecordSize; + + // calculate size of each table + for (CMapBuilderMap::iterator it = cmap_builders_.begin(), + e = cmap_builders_.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() { - // TODO(arthurhsu): IMPLEMENT + cmap_builders_.clear(); + Table::Builder::setModelChanged(false); } CALLER_ATTACH FontDataTable* CMapTable::Builder::subBuildTable( @@ -423,7 +470,7 @@ CALLER_ATTACH CMapTable::CMap::Builder* CMapTable::Builder::cmapBuilder( return NULL; int32_t record_offset = Offset::kEncodingRecordOffset + index * - Offset::kEncodingRecordSize; + Offset::kEncodingRecordSize; int32_t platform_id = data->readUShort(Offset::kEncodingRecordPlatformId + record_offset); int32_t encoding_id = data->readUShort(Offset::kEncodingRecordEncodingId + diff --git a/sfntly/cmap_table.h b/sfntly/cmap_table.h index c13318e..a102b82 100644 --- a/sfntly/cmap_table.h +++ b/sfntly/cmap_table.h @@ -46,6 +46,10 @@ struct CMapFormat { class CMapTable : public Table, public RefCounted { private: static const int32_t NOTDEF; + + // 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, @@ -155,6 +159,7 @@ class CMapTable : public Table, public RefCounted { }; public: + // CMapTable::CMapId class CMapId { public: CMapId(int32_t platform_id, int32_t encoding_id); @@ -175,13 +180,19 @@ class CMapTable : public Table, public RefCounted { static CMapId WINDOWS_UCS4; static CMapId MAC_ROMAN; + // CMapTable::CMapIdComparator class CMapIdComparator { public: bool operator()(const CMapId& lhs, const CMapId& rhs); }; + // 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(CMapId cmap_id) = 0; // Make gcc -Wnon-virtual-dtor happy. virtual ~CMapFilter() {} @@ -197,14 +208,15 @@ class CMapTable : public Table, public RefCounted { // The cmap implements {@code Iterable} 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 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 + // 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: CMap(ReadableFontData* data, int32_t format, const CMapId& cmap_id); @@ -235,7 +247,11 @@ class CMapTable : public Table, public RefCounted { virtual int32_t glyphId(int32_t character) = 0; public: + // CMapTable::CMap::Builder class Builder : public SubTable::Builder { + public: + friend class CMapTable::Builder; + protected: Builder(FontDataTableBuilderContainer* container, ReadableFontData* data, int32_t format, const CMapId& cmap_id); @@ -282,6 +298,7 @@ class CMapTable : public Table, public RefCounted { virtual int32_t language(); virtual int32_t glyphId(int32_t character); + // CMapTable::CMapFormat0::Builder class Builder : public CMap::Builder, public RefCounted { public: @@ -321,6 +338,7 @@ class CMapTable : public Table, public RefCounted { int32_t idRangeOffset(int32_t sub_header_index); int32_t idDelta(int32_t sub_header_index); + // CMapTable::CMapFormat2::Builder class Builder : public CMap::Builder, public RefCounted { public: @@ -335,7 +353,9 @@ class CMapTable : public Table, public RefCounted { }; }; - class Builder : public Table::ArrayElementTableBuilder { + // CMapTable::Builder + class Builder : public Table::ArrayElementTableBuilder, + public RefCounted { public: // Constructor scope altered to public because C++ does not allow base // class to instantiate derived class with protected constructors. @@ -406,6 +426,7 @@ class CMapTable : public Table, public RefCounted { int32_t offsetForEncodingRecord(int32_t index); }; typedef std::vector CMapIdList; +typedef Ptr CMapTablePtr; } // namespace sfntly diff --git a/test/main.cc b/test/main.cc index 72cc4ea..0838b94 100644 --- a/test/main.cc +++ b/test/main.cc @@ -28,9 +28,12 @@ #include "test/open_type_data_test.h" #include "test/otf_basic_editing_test.h" #include "test/name_editing_test.h" +#include "test/test_utils_test.h" #define RUN_LENGTHY_TESTS +namespace sfntly { + TEST(SmartPointer, All) { EXPECT_TRUE(testSmartPointer()); } @@ -79,3 +82,13 @@ TEST(NameEditing, All) { EXPECT_TRUE(sfntly::testModifyNameTableAndRevert()); EXPECT_TRUE(sfntly::testRemoveOneName()); } + +TEST(TestUtils, Extension) { + EXPECT_TRUE(sfntly::testExtension()); +} + +TEST(TestUtils, Encoding) { + EXPECT_TRUE(sfntly::testEncoding()); +} + +} // namespace sfntly diff --git a/test/test_utils.cc b/test/test_utils.cc new file mode 100644 index 0000000..5efff4f --- /dev/null +++ b/test/test_utils.cc @@ -0,0 +1,88 @@ +/* + * 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 "gtest/gtest.h" +#include "sfntly/font.h" +#include "sfntly/data/memory_byte_array.h" +#include "sfntly/data/growable_memory_byte_array.h" +#include "sfntly/port/file_input_stream.h" +#include "test/test_utils.h" + +namespace sfntly { +TestUtils::TestUtils() {} + +// static +// OutputStream createOutputStream(const char *file_path) { +// } + +// static +// void TestUtils::createNewFile(const char* file_path) { +// } + +// static +int32_t TestUtils::encodeOneChar(UConverter* encoder, int16_t uchar) { + char* target = new char[ucnv_getMaxCharSize(encoder) * 2]; + char* target_end; + UChar* source = new UChar[2]; + UChar* source_end; + source[0] = (UChar)uchar; + source[1] = 0; + UErrorCode status = U_ZERO_ERROR; + source_end = source; + target_end = target; + ucnv_fromUnicode(encoder, &target_end, target + 4, + (const UChar**)&source_end, source + sizeof(UChar), + NULL, TRUE, &status); + if (!U_SUCCESS(status)) { + fprintf(stderr, "Error occured in conversion of %d: %s\n", + uchar, u_errorName(status)); + delete[] source; + delete[] target; + return 0; + } + int32_t enc_char = 0; + for (int32_t position = 0; position < target_end - target; ++position) { + enc_char <<= 8; + enc_char |= (target[position] & 0xff); + } + delete[] source; + delete[] target; + return enc_char; +} + +// static +UConverter* TestUtils::getEncoder(const char* charset_name) { + if (charset_name == NULL || strcmp(charset_name, "") == 0) + return NULL; + UErrorCode status = U_ZERO_ERROR; + UConverter* conv = ucnv_open(charset_name, &status); + // if (!U_SUCCESS(status)) + // return NULL; + return conv; // returns NULL @ error anyway +} + +// Get a file's extension +// static +const char* TestUtils::extension(const char* file_path) { + if (!file_path) + return NULL; + return strrchr(file_path, EXTENSION_SEPARATOR); +} +} diff --git a/test/test_utils.h b/test/test_utils.h new file mode 100644 index 0000000..076f3a7 --- /dev/null +++ b/test/test_utils.h @@ -0,0 +1,100 @@ +/* + * 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_TEST_TEST_UTILS_H_ +#define TYPOGRAPHY_FONT_SFNTLY_SRC_TEST_TEST_UTILS_H_ + +#include +#include +#include "sfntly/font.h" +#include "sfntly/data/memory_byte_array.h" + +namespace sfntly { +class TestUtils { + TestUtils(); + + public: + // Compare sections of two byte arrays for equality + // @param b1 byte array 1 + // @param offset1 offset for comparison in byte array 1 + // @param b2 byte array 2 + // @param offset2 offset for comparison in byte array 2 + // @param length the length of the byte arrays to compare + // @return true if the array segments are equal; false otherwise + // TODO(dfilimon): implement + static bool equals(ByteArray* b1, int32_t offset1, + ByteArray* b2, int32_t offset2); + + // @param offset1 offset to start comparing the first ByteArray from + // @param ba1 the first ByteArray + // @param offset2 offset to start comparing the second ByteArray from + // @param ba2 the second ByteArray + // @param length the number of bytes to compare + // @return true if all bytes in the ranges given are equal; false otherwise + // TODO(dfilimon): implement + static bool equals(ByteArray* b1, int32_t offset1, + ByteArray* b2, int32_t offset2, int32_t length); + + // TODO(dfilimon): implement FileOutputStream in port/file_output_stream.* + // static OutputStream createOutputStream(const char* file_path); + + // TODO(dfilimon): adapt & implement + // static FileChannel createFilechannelForWriting(File file); + + // Creates a new file including deleting an already existing file with the + // same path and name and creating any needed directories. + // TODO(dfilimon): implement + static void createNewFile(const char* file_path); + + // Converts an integer into a 4 character string using the ASCII encoding. + // @param i the value to convert + // @return the String based on the number + // TODO(dfilimon): implement + static void dumpLongAsString(int32_t i, std::string* result); + + // Calculate an OpenType checksum from the array. + // @param b the array to calculate checksum on + // @param offset the starting index in the array + // @param length the number of bytes to check; must be a multiple of 4 + // @return checksum + // TODO(dfilimon): implement + static int64_t checkSum(ByteArray* b, int32_t offset, int32_t length); + + // Encode a single character in UTF-16. + // We only support the BMP for now + // @param encoder the encoder to use for the encoding + // @param uchar the Unicode character to encode + // @return the encoded character + static int32_t encodeOneChar(UConverter* encoder, int16_t uchar); + + // Get an encoder for the charset name. + // If the name is null or the empty string then just return null. + // @param charsetName the charset to get an encoder for + // @return an encoder or null if no encoder available for charset name + static UConverter* getEncoder(const char* charsetName); + + private: + static const char EXTENSION_SEPARATOR = '.'; + + public: + // Get the extension of a file's name. + // @param file the whose name to process + // @return string containing the extension or an empty string if + // there is no extension + static const char* extension(const char* file_path); +}; +} +#endif // TYPOGRAPHY_FONT_SFNTLY_SRC_TEST_TEST_UTILS_H_ diff --git a/test/test_utils_test.cc b/test/test_utils_test.cc new file mode 100644 index 0000000..600461a --- /dev/null +++ b/test/test_utils_test.cc @@ -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. + */ + +#include +#include +#include + +#include "gtest/gtest.h" +#include "test/test_utils.h" +#include "test/test_utils_test.h" + +namespace sfntly { + +// Check if proper encoding is being performed +// Conversion is done from UTF16 to UTF8, SJIS +bool testEncoding() { + UConverter* conv = TestUtils::getEncoder("utf8"); + EXPECT_TRUE(conv != NULL); + // Ūnĭcōde̽ + UChar from[8] = {0x016A, 0x006E, 0x012D, 0x0063, 0x014D, 0x0064, 0x0065, + 0x033D}; + int32_t want[12] = {0xc5, 0xaa, 0x6e, 0xc4, 0xad, 0x63, 0xc5, 0x8d, 0x64, + 0x65, 0xcc, 0xbd}; + int32_t i, j = 0; + for (i = 0; i < 7; ++i) { + int32_t encoded = TestUtils::encodeOneChar(conv, (int16_t)from[i]); + for (; encoded; encoded <<= 8) { + byte_t b = (encoded & 0xff000000) >> 24; + if (!b) + continue; + EXPECT_EQ(want[j], b); + if (want[j++] != b) { + ucnv_close(conv); + return false; + } + } + } + ucnv_close(conv); + return true; +} + +// Check if the proper extension is obtained +bool testExtension() { + char *test = new char[32]; + // usual file name + memset(test, 0, 32); + strncpy(test, "../data/ext/arial.ttf", 31); + const char *result; + result = TestUtils::extension(test); + EXPECT_EQ(strcmp(result, ".ttf"), 0); + + // more than one 'extension' + memset(test, 0, 32); + strncpy(test, "arial.ttf.fake", 31); + result = TestUtils::extension(test); + EXPECT_EQ(strcmp(result, ".fake"), 0); + + // no extension + memset(test, 0, 32); + strncpy(test, "arial", 31); + result = TestUtils::extension(test); + EXPECT_STREQ(result, NULL); + + // bogus extension + memset(test, 0, 32); + strncpy(test, "arial.", 31); + result = TestUtils::extension(test); + EXPECT_EQ(strcmp(result, "."), 0); + + delete[] test; + return true; +} + +} // namespace sfntly diff --git a/test/test_utils_test.h b/test/test_utils_test.h new file mode 100644 index 0000000..e3b6bbc --- /dev/null +++ b/test/test_utils_test.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 TYPOGRAPHY_FONT_SFNTLY_SRC_TEST_TEST_UTILS_TEST_H_ +#define TYPOGRAPHY_FONT_SFNTLY_SRC_TEST_TEST_UTILS_TEST_H_ + +namespace sfntly { + +bool testEncoding(); +bool testExtension(); +bool testReadFile(); + +} // namespace sfntly + +#endif // TYPOGRAPHY_FONT_SFNTLY_SRC_TEST_TEST_UTILS_TEST_H_ -- cgit v1.2.3 From 050736d52301766cd6bd3838766575dab3944551 Mon Sep 17 00:00:00 2001 From: "arthurhsu@google.com" Date: Thu, 21 Jul 2011 22:30:37 +0000 Subject: Update for clang to successfully build sfntly. git-svn-id: http://sfntly.googlecode.com/svn/trunk/cpp/src@20 672e30a5-4c29-85ac-ac6d-611c735e0a51 --- sfntly/port/atomic.h | 11 ++++++----- sfntly/port/refcount.h | 23 +++++++++++++++++++++++ 2 files changed, 29 insertions(+), 5 deletions(-) diff --git a/sfntly/port/atomic.h b/sfntly/port/atomic.h index 10db2d5..4c2d65b 100644 --- a/sfntly/port/atomic.h +++ b/sfntly/port/atomic.h @@ -49,7 +49,12 @@ static inline size_t atomicDecrement(size_t* address) { return OSAtomicDecrement32Barrier(reinterpret_cast(address)); } -#elif defined (__GCC_HAVE_SYNC_COMPARE_AND_SWAP_4) +// 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 @@ -61,10 +66,6 @@ static inline size_t atomicDecrement(size_t* address) { return __sync_sub_and_fetch(address, 1); } -#else - -#error "Compiler not supported" - #endif // WIN32 #endif // TYPOGRAPHY_FONT_SFNTLY_SRC_SFNTLY_PORT_ATOMIC_H_ diff --git a/sfntly/port/refcount.h b/sfntly/port/refcount.h index c1e5a6d..ed1fa96 100644 --- a/sfntly/port/refcount.h +++ b/sfntly/port/refcount.h @@ -15,6 +15,29 @@ */ // 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. -- cgit v1.2.3 From 74250f66a0f41c5f6ae15cfcebaa402f4f355d5a Mon Sep 17 00:00:00 2001 From: "arthurhsu@google.com" Date: Fri, 22 Jul 2011 20:25:44 +0000 Subject: Fix VC build breakage git-svn-id: http://sfntly.googlecode.com/svn/trunk/cpp/src@24 672e30a5-4c29-85ac-ac6d-611c735e0a51 --- test/test_utils.cc | 3 ++- test/test_utils.h | 5 +++++ test/test_utils_test.cc | 21 ++++++--------------- test/test_utils_test.h | 2 ++ 4 files changed, 15 insertions(+), 16 deletions(-) diff --git a/test/test_utils.cc b/test/test_utils.cc index 5efff4f..4b4644e 100644 --- a/test/test_utils.cc +++ b/test/test_utils.cc @@ -14,6 +14,8 @@ * limitations under the License. */ +#include "test/test_utils.h" + #include #include #include @@ -23,7 +25,6 @@ #include "sfntly/data/memory_byte_array.h" #include "sfntly/data/growable_memory_byte_array.h" #include "sfntly/port/file_input_stream.h" -#include "test/test_utils.h" namespace sfntly { TestUtils::TestUtils() {} diff --git a/test/test_utils.h b/test/test_utils.h index 076f3a7..6aa4d99 100644 --- a/test/test_utils.h +++ b/test/test_utils.h @@ -17,8 +17,13 @@ #ifndef TYPOGRAPHY_FONT_SFNTLY_SRC_TEST_TEST_UTILS_H_ #define TYPOGRAPHY_FONT_SFNTLY_SRC_TEST_TEST_UTILS_H_ +// Must include this before ICU to avoid stdint redefinition issue. +#include "sfntly/port/type.h" + #include + #include + #include "sfntly/font.h" #include "sfntly/data/memory_byte_array.h" diff --git a/test/test_utils_test.cc b/test/test_utils_test.cc index 600461a..12c5512 100644 --- a/test/test_utils_test.cc +++ b/test/test_utils_test.cc @@ -14,13 +14,14 @@ * limitations under the License. */ +#include "test/test_utils_test.h" + #include #include #include #include "gtest/gtest.h" #include "test/test_utils.h" -#include "test/test_utils_test.h" namespace sfntly { @@ -54,33 +55,23 @@ bool testEncoding() { // Check if the proper extension is obtained bool testExtension() { - char *test = new char[32]; // usual file name - memset(test, 0, 32); - strncpy(test, "../data/ext/arial.ttf", 31); const char *result; - result = TestUtils::extension(test); + result = TestUtils::extension("../data/ext/arial.ttf"); EXPECT_EQ(strcmp(result, ".ttf"), 0); // more than one 'extension' - memset(test, 0, 32); - strncpy(test, "arial.ttf.fake", 31); - result = TestUtils::extension(test); + result = TestUtils::extension("arial.ttf.fake"); EXPECT_EQ(strcmp(result, ".fake"), 0); // no extension - memset(test, 0, 32); - strncpy(test, "arial", 31); - result = TestUtils::extension(test); + result = TestUtils::extension("arial"); EXPECT_STREQ(result, NULL); // bogus extension - memset(test, 0, 32); - strncpy(test, "arial.", 31); - result = TestUtils::extension(test); + result = TestUtils::extension("arial."); EXPECT_EQ(strcmp(result, "."), 0); - delete[] test; return true; } diff --git a/test/test_utils_test.h b/test/test_utils_test.h index e3b6bbc..1b4649e 100644 --- a/test/test_utils_test.h +++ b/test/test_utils_test.h @@ -17,6 +17,8 @@ #ifndef TYPOGRAPHY_FONT_SFNTLY_SRC_TEST_TEST_UTILS_TEST_H_ #define TYPOGRAPHY_FONT_SFNTLY_SRC_TEST_TEST_UTILS_TEST_H_ +#include "sfntly/port/type.h" + namespace sfntly { bool testEncoding(); -- cgit v1.2.3 From 81d75f74d4ecf6c5ba67de75aef6dcca644607b2 Mon Sep 17 00:00:00 2001 From: "arthurhsu@google.com" Date: Tue, 26 Jul 2011 17:07:40 +0000 Subject: Fix crash issue when users specify /GR- in VC's compilation flag. git-svn-id: http://sfntly.googlecode.com/svn/trunk/cpp/src@25 672e30a5-4c29-85ac-ac6d-611c735e0a51 --- sfntly/port/type.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/sfntly/port/type.h b/sfntly/port/type.h index bb51993..4691a82 100644 --- a/sfntly/port/type.h +++ b/sfntly/port/type.h @@ -81,10 +81,10 @@ inline To down_cast(From* f) { // so we only accept pointers #pragma warning(pop) #endif -// The following code is the only place for RTTI. It is done so to allow VC++ -// to perform additional type checking in DEBUG builds. -#if defined (_MSC_VER) && !defined(NDEBUG) - assert(f == NULL || dynamic_cast(f) != NULL); // RTTI: debug mode only! +// 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); } -- cgit v1.2.3 From e3f8c4bcb6f8678bf1f3cba96420077ad133592b Mon Sep 17 00:00:00 2001 From: "dfilimon@google.com" Date: Tue, 26 Jul 2011 20:25:35 +0000 Subject: Fixed a memory leak in font.cc:520 caused by not attaching to a pointer returned by getNewArray that would not ever get deleted. Also fixed the cmap builder map bug. git-svn-id: http://sfntly.googlecode.com/svn/trunk/cpp/src@26 672e30a5-4c29-85ac-ac6d-611c735e0a51 --- sfntly/font.cc | 42 +++++++++++++++++++++++++++++------------- 1 file changed, 29 insertions(+), 13 deletions(-) diff --git a/sfntly/font.cc b/sfntly/font.cc index bd5614f..3df3d5b 100644 --- a/sfntly/font.cc +++ b/sfntly/font.cc @@ -392,7 +392,7 @@ void Font::Builder::buildTablesFromBuilders(TableBuilderMap* builder_map, builder_end = builder_map->end(); builder != builder_end; ++builder) { TablePtr table; - if (builder->second->readyToBuild()) { + if (builder->second && builder->second->readyToBuild()) { #if !defined (SFNTLY_NO_EXCEPTION) try { #endif @@ -420,17 +420,32 @@ void Font::Builder::buildTablesFromBuilders(TableBuilderMap* builder_map, } void Font::Builder::interRelateBuilders(TableBuilderMap* builder_map) { - FontHeaderTableBuilderPtr header_table_builder = - down_cast((*builder_map)[Tag::head].p_); - HorizontalHeaderTableBuilderPtr horizontal_header_builder = - down_cast((*builder_map)[Tag::hhea].p_); - MaximumProfileTableBuilderPtr max_profile_builder = - down_cast((*builder_map)[Tag::maxp].p_); - LocaTableBuilderPtr loca_table_builder = - down_cast((*builder_map)[Tag::loca].p_); - HorizontalMetricsTableBuilderPtr horizontal_metrics_builder = - down_cast( - (*builder_map)[Tag::hmtx].p_); + TableBuilderMap::iterator end_iterator = builder_map->end(), + header_iterator = builder_map->find(Tag::head), + horizontal_header_iterator = builder_map->find(Tag::hhea), + max_profile_iterator = builder_map->find(Tag::maxp), + loca_table_iterator = builder_map->find(Tag::loca), + horizontal_metrics_iterator = builder_map->find(Tag::hmtx); + FontHeaderTableBuilderPtr header_table_builder; + HorizontalHeaderTableBuilderPtr horizontal_header_builder; + MaximumProfileTableBuilderPtr max_profile_builder; + LocaTableBuilderPtr loca_table_builder; + HorizontalMetricsTableBuilderPtr horizontal_metrics_builder; + header_table_builder = (header_iterator != end_iterator) ? + down_cast + (header_iterator->second.p_) : NULL; + horizontal_header_builder = (horizontal_header_iterator != end_iterator) ? + down_cast + (horizontal_header_iterator->second.p_) : NULL; + max_profile_builder = (max_profile_iterator != end_iterator) ? + down_cast + (max_profile_iterator->second.p_) : NULL; + loca_table_builder = (loca_table_iterator != end_iterator) ? + down_cast + (loca_table_iterator->second.p_) : NULL; + horizontal_metrics_builder = (horizontal_metrics_iterator != end_iterator) ? + down_cast + (horizontal_metrics_iterator->second.p_) : NULL; // set the inter table data required to build certain tables if (horizontal_metrics_builder != NULL) { @@ -486,7 +501,8 @@ void Font::Builder::loadTableData(TableHeaderSortedSet* headers, is->skip((*table_header)->offset() - is->position()); FontInputStream table_is(is, (*table_header)->length()); int32_t roundup_length = ((*table_header)->length() + 3) & ~3; - ByteArrayPtr array = factory_->getNewArray(roundup_length); + ByteArrayPtr array; + array.attach(factory_->getNewArray(roundup_length)); array->copyFrom(&table_is, (*table_header)->length()); WritableFontDataPtr data = new WritableFontData(array); table_data->insert(DataBlockEntry(*table_header, data)); -- cgit v1.2.3 From a669e0e4de0f658c4a36789886f86418d99c962e Mon Sep 17 00:00:00 2001 From: "arthurhsu@google.com" Date: Tue, 26 Jul 2011 20:37:26 +0000 Subject: Removing changes from revision 26 git-svn-id: http://sfntly.googlecode.com/svn/trunk/cpp/src@27 672e30a5-4c29-85ac-ac6d-611c735e0a51 --- sfntly/font.cc | 42 +++++++++++++----------------------------- 1 file changed, 13 insertions(+), 29 deletions(-) diff --git a/sfntly/font.cc b/sfntly/font.cc index 3df3d5b..bd5614f 100644 --- a/sfntly/font.cc +++ b/sfntly/font.cc @@ -392,7 +392,7 @@ void Font::Builder::buildTablesFromBuilders(TableBuilderMap* builder_map, builder_end = builder_map->end(); builder != builder_end; ++builder) { TablePtr table; - if (builder->second && builder->second->readyToBuild()) { + if (builder->second->readyToBuild()) { #if !defined (SFNTLY_NO_EXCEPTION) try { #endif @@ -420,32 +420,17 @@ void Font::Builder::buildTablesFromBuilders(TableBuilderMap* builder_map, } void Font::Builder::interRelateBuilders(TableBuilderMap* builder_map) { - TableBuilderMap::iterator end_iterator = builder_map->end(), - header_iterator = builder_map->find(Tag::head), - horizontal_header_iterator = builder_map->find(Tag::hhea), - max_profile_iterator = builder_map->find(Tag::maxp), - loca_table_iterator = builder_map->find(Tag::loca), - horizontal_metrics_iterator = builder_map->find(Tag::hmtx); - FontHeaderTableBuilderPtr header_table_builder; - HorizontalHeaderTableBuilderPtr horizontal_header_builder; - MaximumProfileTableBuilderPtr max_profile_builder; - LocaTableBuilderPtr loca_table_builder; - HorizontalMetricsTableBuilderPtr horizontal_metrics_builder; - header_table_builder = (header_iterator != end_iterator) ? - down_cast - (header_iterator->second.p_) : NULL; - horizontal_header_builder = (horizontal_header_iterator != end_iterator) ? - down_cast - (horizontal_header_iterator->second.p_) : NULL; - max_profile_builder = (max_profile_iterator != end_iterator) ? - down_cast - (max_profile_iterator->second.p_) : NULL; - loca_table_builder = (loca_table_iterator != end_iterator) ? - down_cast - (loca_table_iterator->second.p_) : NULL; - horizontal_metrics_builder = (horizontal_metrics_iterator != end_iterator) ? - down_cast - (horizontal_metrics_iterator->second.p_) : NULL; + FontHeaderTableBuilderPtr header_table_builder = + down_cast((*builder_map)[Tag::head].p_); + HorizontalHeaderTableBuilderPtr horizontal_header_builder = + down_cast((*builder_map)[Tag::hhea].p_); + MaximumProfileTableBuilderPtr max_profile_builder = + down_cast((*builder_map)[Tag::maxp].p_); + LocaTableBuilderPtr loca_table_builder = + down_cast((*builder_map)[Tag::loca].p_); + HorizontalMetricsTableBuilderPtr horizontal_metrics_builder = + down_cast( + (*builder_map)[Tag::hmtx].p_); // set the inter table data required to build certain tables if (horizontal_metrics_builder != NULL) { @@ -501,8 +486,7 @@ void Font::Builder::loadTableData(TableHeaderSortedSet* headers, is->skip((*table_header)->offset() - is->position()); FontInputStream table_is(is, (*table_header)->length()); int32_t roundup_length = ((*table_header)->length() + 3) & ~3; - ByteArrayPtr array; - array.attach(factory_->getNewArray(roundup_length)); + ByteArrayPtr array = factory_->getNewArray(roundup_length); array->copyFrom(&table_is, (*table_header)->length()); WritableFontDataPtr data = new WritableFontData(array); table_data->insert(DataBlockEntry(*table_header, data)); -- cgit v1.2.3 From 35a9bf28a889295528bfe46ab51902a460be5407 Mon Sep 17 00:00:00 2001 From: "arthurhsu@google.com" Date: Wed, 27 Jul 2011 00:52:05 +0000 Subject: Fix compilation warnings when used by Chrome. Make sure the warn unused return is not disabled. git-svn-id: http://sfntly.googlecode.com/svn/trunk/cpp/src@28 672e30a5-4c29-85ac-ac6d-611c735e0a51 --- sample/subsetter/subset_util.cc | 3 ++- sfntly/port/file_input_stream.cc | 4 ++-- test/file_io_test.cc | 6 ++++-- test/test_font_utils.cc | 3 ++- 4 files changed, 10 insertions(+), 6 deletions(-) diff --git a/sample/subsetter/subset_util.cc b/sample/subsetter/subset_util.cc index 2266615..013a903 100644 --- a/sample/subsetter/subset_util.cc +++ b/sample/subsetter/subset_util.cc @@ -50,7 +50,8 @@ void SubsetUtil::subset(const char *input_file_path, size_t file_size = ftell(input_file); fseek(input_file, 0, SEEK_SET); input_buffer.resize(file_size); - fread(&(input_buffer[0]), 1, file_size, input_file); + size_t bytes_read = fread(&(input_buffer[0]), 1, file_size, input_file); + UNREFERENCED_PARAMETER(bytes_read); fclose(input_file); ByteArrayPtr ba = new MemoryByteArray(&(input_buffer[0]), file_size); diff --git a/sfntly/port/file_input_stream.cc b/sfntly/port/file_input_stream.cc index d4432bb..04a0fd6 100644 --- a/sfntly/port/file_input_stream.cc +++ b/sfntly/port/file_input_stream.cc @@ -88,8 +88,8 @@ int32_t FileInputStream::read() { #endif } byte_t value; - fread(&value, 1, 1, file_); - position_++; + size_t length = fread(&value, 1, 1, file_); + position_ += length; return value; } diff --git a/test/file_io_test.cc b/test/file_io_test.cc index 68ab4e5..1c02b0a 100644 --- a/test/file_io_test.cc +++ b/test/file_io_test.cc @@ -38,7 +38,8 @@ bool testFileInputStream() { fseek(file_handle, 0, SEEK_SET); ByteVector b1; b1.resize(length); - fread(&(b1[0]), 1, length, file_handle); + size_t bytes_read = fread(&(b1[0]), 1, length, file_handle); + EXPECT_EQ(bytes_read, length); fclose(file_handle); // Full file reading test @@ -98,7 +99,8 @@ bool testFontInputStreamBasic() { fseek(file_handle, 0, SEEK_SET); ByteVector b1; b1.resize(length); - fread(&(b1[0]), 1, length, file_handle); + size_t bytes_read = fread(&(b1[0]), 1, length, file_handle); + EXPECT_EQ(bytes_read, length); fclose(file_handle); FileInputStream is; diff --git a/test/test_font_utils.cc b/test/test_font_utils.cc index 8c3c55f..830f96e 100644 --- a/test/test_font_utils.cc +++ b/test/test_font_utils.cc @@ -63,7 +63,8 @@ void loadFile(const char* input_file_path, ByteVector* input_buffer) { size_t file_size = ftell(input_file); fseek(input_file, 0, SEEK_SET); input_buffer->resize(file_size); - fread(&((*input_buffer)[0]), 1, file_size, input_file); + size_t bytes_read = fread(&((*input_buffer)[0]), 1, file_size, input_file); + EXPECT_EQ(bytes_read, file_size); fclose(input_file); } -- cgit v1.2.3 From 2538405b412d47c3772cb2bebfe96fb96217b1f1 Mon Sep 17 00:00:00 2001 From: "dfilimon@google.com" Date: Sat, 30 Jul 2011 05:49:09 +0000 Subject: Quick fix for compile on Windows. git-svn-id: http://sfntly.googlecode.com/svn/trunk/cpp/src@29 672e30a5-4c29-85ac-ac6d-611c735e0a51 --- sfntly/name_table.cc | 2 ++ 1 file changed, 2 insertions(+) diff --git a/sfntly/name_table.cc b/sfntly/name_table.cc index 471c054..0858603 100644 --- a/sfntly/name_table.cc +++ b/sfntly/name_table.cc @@ -14,6 +14,8 @@ * limitations under the License. */ +#include "port/type.h" + #include #include -- cgit v1.2.3 From 246300f7fab1f2539c3207ce5ec28cc355465be8 Mon Sep 17 00:00:00 2001 From: "arthurhsu@google.com" Date: Mon, 1 Aug 2011 17:26:13 +0000 Subject: Readability clean up. The code conforms to Google C++ Coding Style. git-svn-id: http://sfntly.googlecode.com/svn/trunk/cpp/src@30 672e30a5-4c29-85ac-ac6d-611c735e0a51 --- sample/subsetter/main.cc | 2 +- sample/subsetter/subset_util.cc | 18 +- sample/subsetter/subset_util.h | 2 +- sfntly/cmap_table.cc | 396 +++++----- sfntly/cmap_table.h | 484 ++++++------ sfntly/data/byte_array.cc | 118 +-- sfntly/data/byte_array.h | 80 +- sfntly/data/font_data.cc | 60 +- sfntly/data/font_data.h | 25 +- sfntly/data/font_input_stream.cc | 80 +- sfntly/data/font_input_stream.h | 40 +- sfntly/data/font_output_stream.cc | 80 +- sfntly/data/font_output_stream.h | 32 +- sfntly/data/growable_memory_byte_array.cc | 33 +- sfntly/data/growable_memory_byte_array.h | 16 +- sfntly/data/memory_byte_array.cc | 47 +- sfntly/data/memory_byte_array.h | 18 +- sfntly/data/readable_font_data.cc | 230 +++--- sfntly/data/readable_font_data.h | 95 ++- sfntly/data/writable_font_data.cc | 115 +-- sfntly/data/writable_font_data.h | 41 +- sfntly/font.cc | 357 +++++---- sfntly/font.h | 223 +++--- sfntly/font_data_table.cc | 169 ++--- sfntly/font_data_table.h | 115 +-- sfntly/font_data_table_builder_container.h | 2 +- sfntly/font_factory.cc | 270 +++---- sfntly/font_factory.h | 125 ++-- sfntly/font_header_table.cc | 226 +++--- sfntly/font_header_table.h | 186 +++-- sfntly/glyph_table.cc | 548 +++++++------- sfntly/glyph_table.h | 277 ++++--- sfntly/horizontal_header_table.cc | 185 ++--- sfntly/horizontal_header_table.h | 116 +-- sfntly/horizontal_metrics_table.cc | 96 +-- sfntly/horizontal_metrics_table.h | 72 +- sfntly/loca_table.cc | 169 ++--- sfntly/loca_table.h | 109 ++- sfntly/math/fixed1616.h | 6 +- sfntly/math/font_math.h | 2 +- sfntly/maximum_profile_table.cc | 186 ++--- sfntly/maximum_profile_table.h | 117 ++- sfntly/name_table.cc | 943 ++++++++++++------------ sfntly/name_table.h | 373 ++++++---- sfntly/os2_table.cc | 163 ++-- sfntly/os2_table.h | 111 ++- sfntly/port/atomic.h | 12 +- sfntly/port/endian.h | 54 +- sfntly/port/file_input_stream.cc | 75 +- sfntly/port/file_input_stream.h | 24 +- sfntly/port/input_stream.h | 23 +- sfntly/port/memory_output_stream.cc | 14 +- sfntly/port/memory_output_stream.h | 16 +- sfntly/port/output_stream.h | 11 +- sfntly/port/refcount.h | 49 +- sfntly/subtable.cc | 19 +- sfntly/subtable.h | 21 +- sfntly/table.cc | 224 +++--- sfntly/table.h | 115 +-- sfntly/tag.cc | 72 +- sfntly/tag.h | 2 +- sfntly/tools/subsetter.cc | 39 +- sfntly/tools/subsetter/glyph_table_subsetter.cc | 40 +- sfntly/tools/subsetter/glyph_table_subsetter.h | 3 +- sfntly/tools/subsetter/subsetter.h | 12 +- sfntly/tools/subsetter/table_subsetter.h | 6 +- sfntly/tools/subsetter/table_subsetter_impl.cc | 4 +- sfntly/tools/subsetter/table_subsetter_impl.h | 4 +- test/byte_array_test.cc | 72 +- test/byte_array_test.h | 4 +- test/endian_test.cc | 50 +- test/endian_test.h | 2 +- test/file_io_test.cc | 66 +- test/file_io_test.h | 6 +- test/font_data_test.cc | 132 ++-- test/font_data_test.h | 4 +- test/font_parsing_test.cc | 64 +- test/font_parsing_test.h | 6 +- test/main.cc | 40 +- test/name_editing_test.cc | 114 +-- test/name_editing_test.h | 8 +- test/open_type_data_test.cc | 22 +- test/open_type_data_test.h | 4 +- test/otf_basic_editing_test.cc | 28 +- test/otf_basic_editing_test.h | 2 +- test/smart_pointer_test.cc | 4 +- test/smart_pointer_test.h | 2 +- test/test_font_utils.cc | 28 +- test/test_font_utils.h | 12 +- test/test_utils.cc | 10 +- test/test_utils.h | 25 +- test/test_utils_test.cc | 16 +- test/test_utils_test.h | 6 +- 93 files changed, 4451 insertions(+), 4273 deletions(-) diff --git a/sample/subsetter/main.cc b/sample/subsetter/main.cc index a9e1524..19a3e0e 100644 --- a/sample/subsetter/main.cc +++ b/sample/subsetter/main.cc @@ -34,7 +34,7 @@ int main(int argc, char** argv) { } sfntly::SubsetUtil subset_util; - subset_util.subset(argv[1], argv[2]); + subset_util.Subset(argv[1], argv[2]); #ifdef _CRTDBG_MAP_ALLOC _CrtDumpMemoryLeaks(); diff --git a/sample/subsetter/subset_util.cc b/sample/subsetter/subset_util.cc index 013a903..9e4e652 100644 --- a/sample/subsetter/subset_util.cc +++ b/sample/subsetter/subset_util.cc @@ -37,7 +37,7 @@ SubsetUtil::SubsetUtil() { SubsetUtil::~SubsetUtil() { } -void SubsetUtil::subset(const char *input_file_path, +void SubsetUtil::Subset(const char *input_file_path, const char *output_file_path) { UNREFERENCED_PARAMETER(output_file_path); ByteVector input_buffer; @@ -56,10 +56,10 @@ void SubsetUtil::subset(const char *input_file_path, ByteArrayPtr ba = new MemoryByteArray(&(input_buffer[0]), file_size); FontFactoryPtr factory; - factory.attach(FontFactory::getInstance()); + factory.Attach(FontFactory::GetInstance()); FontArray font_array; - factory->loadFonts(ba, &font_array); + factory->LoadFonts(ba, &font_array); if (font_array.empty() || font_array[0] == NULL) return; @@ -71,25 +71,25 @@ void SubsetUtil::subset(const char *input_file_path, glyphs.push_back(10); Ptr subsetter = new Subsetter(font_array[0], factory); - subsetter->setGlyphs(&glyphs); + subsetter->SetGlyphs(&glyphs); IntegerSet remove_tables; remove_tables.insert(Tag::DSIG); - subsetter->setRemoveTables(&remove_tables); + subsetter->SetRemoveTables(&remove_tables); FontBuilderPtr font_builder; - font_builder.attach(subsetter->subset()); + font_builder.Attach(subsetter->Subset()); FontPtr new_font; - new_font.attach(font_builder->build()); + new_font.Attach(font_builder->Build()); // TODO(arthurhsu): glyph renumbering/Loca table // TODO(arthurhsu): alter CMaps MemoryOutputStream output_stream; - factory->serializeFont(new_font, &output_stream); + factory->SerializeFont(new_font, &output_stream); FILE* output_file = fopen(output_file_path, "wb"); - fwrite(output_stream.get(), 1, output_stream.size(), output_file); + fwrite(output_stream.Get(), 1, output_stream.Size(), output_file); fflush(output_file); fclose(output_file); } diff --git a/sample/subsetter/subset_util.h b/sample/subsetter/subset_util.h index bea28b8..109d63a 100644 --- a/sample/subsetter/subset_util.h +++ b/sample/subsetter/subset_util.h @@ -24,7 +24,7 @@ class SubsetUtil { SubsetUtil(); virtual ~SubsetUtil(); - void subset(const char* input_file_path, const char* output_file_path); + void Subset(const char* input_file_path, const char* output_file_path); }; } // namespace sfntly diff --git a/sfntly/cmap_table.cc b/sfntly/cmap_table.cc index 8cbc83e..668dc07 100644 --- a/sfntly/cmap_table.cc +++ b/sfntly/cmap_table.cc @@ -30,39 +30,41 @@ const int32_t CMapTable::NOTDEF = 0; /****************************************************************************** * CMapTable class ******************************************************************************/ -CMapTable::CMapTable(Header* header, ReadableFontData* data) - : Table(header, data) {} CMapTable::~CMapTable() {} -int32_t CMapTable::version() { - return data_->readUShort(Offset::kVersion); +int32_t CMapTable::Version() { + return data_->ReadUShort(Offset::kVersion); } -int32_t CMapTable::numCMaps() { - return data_->readUShort(Offset::kNumTables); +int32_t CMapTable::NumCMaps() { + return data_->ReadUShort(Offset::kNumTables); } -int32_t CMapTable::offsetForEncodingRecord(int32_t index) { - return Offset::kEncodingRecordStart + index * Offset::kEncodingRecordSize; +CMapTable::CMapId CMapTable::GetCMapId(int32_t index) { + return CMapId(PlatformId(index), EncodingId(index)); } -CMapTable::CMapId CMapTable::cmapId(int32_t index) { - return CMapId(platformId(index), encodingId(index)); +int32_t CMapTable::PlatformId(int32_t index) { + return data_->ReadUShort(Offset::kEncodingRecordPlatformId + + OffsetForEncodingRecord(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::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::offset(int32_t index) { - return data_->readULongAsInt(Offset::kEncodingRecordOffset + - offsetForEncodingRecord(index)); +CMapTable::CMapTable(Header* header, ReadableFontData* data) + : Table(header, data) { +} + +int32_t CMapTable::OffsetForEncodingRecord(int32_t index) { + return Offset::kEncodingRecordStart + index * Offset::kEncodingRecordSize; } /****************************************************************************** @@ -76,9 +78,6 @@ CMapTable::CMapId::CMapId(const CMapId& obj) : platform_id_(obj.platform_id_), encoding_id_(obj.encoding_id_) { } -int32_t CMapTable::CMapId::platformId() { return platform_id_; } -int32_t CMapTable::CMapId::encodingId() { return encoding_id_; } - bool CMapTable::CMapId::operator==(const CMapTable::CMapId& obj) { return obj.platform_id_ == platform_id_ && obj.encoding_id_ == encoding_id_; } @@ -90,7 +89,7 @@ const CMapTable::CMapId& CMapTable::CMapId::operator=( return *this; } -int CMapTable::CMapId::hashCode() const { +int CMapTable::CMapId::HashCode() const { return platform_id_ << 8 | encoding_id_; } @@ -106,7 +105,7 @@ CMapTable::CMapId MAC_ROMAN(PlatformId::kWindows, MacintoshEncodingId::kRoman); bool CMapTable::CMapIdComparator::operator()(const CMapId& lhs, const CMapId& rhs) { - return lhs.hashCode() > rhs.hashCode(); + return lhs.HashCode() > rhs.HashCode(); } /****************************************************************************** @@ -117,101 +116,102 @@ CMapTable::CMap::CMap(ReadableFontData* data, int32_t format, : SubTable(data), format_(format), cmap_id_(cmap_id) { } -CMapTable::CMap::~CMap() {} -int32_t CMapTable::CMap::format() { return format_; } -CMapTable::CMapId CMapTable::CMap::cmapId() { return cmap_id_; } -int32_t CMapTable::CMap::platformId() { return cmap_id_.platformId(); } -int32_t CMapTable::CMap::encodingId() { return cmap_id_.encodingId(); } +CMapTable::CMap::~CMap() { +} /****************************************************************************** * CMapTable::CMap::Builder class ******************************************************************************/ +CMapTable::CMap::Builder::~Builder() { +} + +CALLER_ATTACH CMapTable::CMap::Builder* + CMapTable::CMap::Builder::GetBuilder( + FontDataTableBuilderContainer* container, + 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 = new CMapFormat0::Builder(container, data, offset, cmap_id); + break; + case CMapFormat::kFormat2: + builder = new CMapFormat0::Builder(container, data, offset, cmap_id); + break; + default: + break; + } + return builder.Detach(); +} + CMapTable::CMap::Builder::Builder(FontDataTableBuilderContainer* container, ReadableFontData* data, int32_t format, const CMapId& cmap_id) - : SubTable::Builder(container, data), format_(format), cmap_id_(cmap_id) { + : SubTable::Builder(container, data), + format_(format), + cmap_id_(cmap_id) { } CMapTable::CMap::Builder::Builder(FontDataTableBuilderContainer* container, WritableFontData* data, int32_t format, const CMapId& cmap_id) - : SubTable::Builder(container, data), format_(format), cmap_id_(cmap_id) { -} - -CMapTable::CMap::Builder::~Builder() {} - -CMapTable::CMapId CMapTable::CMap::Builder::cmapId() { - return cmap_id_; + : SubTable::Builder(container, data), + format_(format), + cmap_id_(cmap_id) { } -int32_t CMapTable::CMap::Builder::platformId() { - return cmap_id_.platformId(); +int32_t CMapTable::CMap::Builder::SubSerialize(WritableFontData* new_data) { + return InternalReadData()->CopyTo(new_data); } -int32_t CMapTable::CMap::Builder::encodingId() { - return cmap_id_.encodingId(); -} - -int32_t CMapTable::CMap::Builder::subSerialize(WritableFontData* new_data) { - return internalReadData()->copyTo(new_data); -} - -bool CMapTable::CMap::Builder::subReadyToSerialize() { +bool CMapTable::CMap::Builder::SubReadyToSerialize() { return true; } -int32_t CMapTable::CMap::Builder::subDataSizeToSerialize() { - return internalReadData()->length(); +int32_t CMapTable::CMap::Builder::SubDataSizeToSerialize() { + return InternalReadData()->Length(); } -void CMapTable::CMap::Builder::subDataSet() { +void CMapTable::CMap::Builder::SubDataSet() { // NOP } -CALLER_ATTACH CMapTable::CMap::Builder* CMapTable::CMap::Builder::getBuilder( - FontDataTableBuilderContainer* container, 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 = new CMapFormat0::Builder(container, data, offset, cmap_id); - case CMapFormat::kFormat2: - builder = new CMapFormat0::Builder(container, data, offset, cmap_id); - default: - break; - } - return builder.detach(); -} - /****************************************************************************** - * CMapTable::CMapFormat0 and CMapTable::CMapFormat0::Builder + * CMapTable::CMapFormat0 ******************************************************************************/ -CMapTable::CMapFormat0::CMapFormat0(ReadableFontData* data, - const CMapId& cmap_id) - : CMap(data, CMapFormat::kFormat0, cmap_id) { +CMapTable::CMapFormat0::~CMapFormat0() { } -CMapTable::CMapFormat0::~CMapFormat0() {} +int32_t CMapTable::CMapFormat0::Language() { + return 0; +} -int32_t CMapTable::CMapFormat0::glyphId(int32_t character) { +int32_t CMapTable::CMapFormat0::GlyphId(int32_t character) { if (character < 0 || character > 255) { return CMapTable::NOTDEF; } - return data_->readByte(character + Offset::kFormat0GlyphIdArray); + return data_->ReadByte(character + Offset::kFormat0GlyphIdArray); } -int32_t CMapTable::CMapFormat0::language() { - return 0; +CMapTable::CMapFormat0::CMapFormat0(ReadableFontData* data, + const CMapId& cmap_id) + : CMap(data, CMapFormat::kFormat0, cmap_id) { } +/****************************************************************************** + * CMapTable::CMapFormat0::Builder + ******************************************************************************/ CMapTable::CMapFormat0::Builder::Builder( - FontDataTableBuilderContainer* container, WritableFontData* data, - int32_t offset, const CMapId& cmap_id) + FontDataTableBuilderContainer* container, + WritableFontData* data, + int32_t offset, + const CMapId& cmap_id) : CMapTable::CMap::Builder(container, data ? down_cast( - data->slice(offset, data->readUShort( + data->Slice(offset, data->ReadUShort( offset + Offset::kFormat0Length))) : reinterpret_cast(NULL), CMapFormat::kFormat0, cmap_id) { @@ -219,101 +219,68 @@ CMapTable::CMapFormat0::Builder::Builder( } CMapTable::CMapFormat0::Builder::Builder( - FontDataTableBuilderContainer* container, ReadableFontData* data, - int32_t offset, const CMapId& cmap_id) + FontDataTableBuilderContainer* container, + ReadableFontData* data, + int32_t offset, + const CMapId& cmap_id) : CMapTable::CMap::Builder(container, data ? down_cast( - data->slice(offset, data->readUShort( + data->Slice(offset, data->ReadUShort( offset + Offset::kFormat0Length))) : reinterpret_cast(NULL), CMapFormat::kFormat0, cmap_id) { // TODO(arthurhsu): FIXIT: heavy lifting and leak, need fix. } -CMapTable::CMapFormat0::Builder::~Builder() {} +CMapTable::CMapFormat0::Builder::~Builder() { +} -CALLER_ATTACH FontDataTable* CMapTable::CMapFormat0::Builder::subBuildTable( - ReadableFontData* data) { - FontDataTablePtr table = new CMapFormat0(data, cmapId()); - return table.detach(); +CALLER_ATTACH FontDataTable* + CMapTable::CMapFormat0::Builder::SubBuildTable(ReadableFontData* data) { + FontDataTablePtr table = new CMapFormat0(data, cmap_id()); + return table.Detach(); } /****************************************************************************** - * CMapTable::CMapFormat2 and CMapTable::CMapFormat2::Builder + * CMapTable::CMapFormat2 ******************************************************************************/ -CMapTable::CMapFormat2::CMapFormat2(ReadableFontData* data, - const CMapId& cmap_id) - : CMap(data, CMapFormat::kFormat2, cmap_id) { +CMapTable::CMapFormat2::~CMapFormat2() { } -CMapTable::CMapFormat2::~CMapFormat2() {} - -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); -} - -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; +int32_t CMapTable::CMapFormat2::Language() { + return 0; } -int32_t CMapTable::CMapFormat2::glyphId(int32_t character) { +int32_t CMapTable::CMapFormat2::GlyphId(int32_t character) { if (character > 0xffff) { return CMapTable::NOTDEF; } - uint32_t c = toBE32(character); + uint32_t c = ToBE32(character); byte_t high_byte = (c >> 8) & 0xff; byte_t low_byte = c & 0xff; - int32_t offset = subHeaderOffset(high_byte); + 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); + 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); + 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); + int p = data_->ReadUShort(p_location); if (p == 0) { return CMapTable::NOTDEF; } @@ -321,20 +288,66 @@ int32_t CMapTable::CMapFormat2::glyphId(int32_t character) { if (offset == 0) { return p; } - int id_delta = idDelta(high_byte); + int id_delta = IdDelta(high_byte); return (p + id_delta) % 65536; } -int32_t CMapTable::CMapFormat2::language() { - return 0; +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::CMapFormat2::Builder + ******************************************************************************/ CMapTable::CMapFormat2::Builder::Builder( - FontDataTableBuilderContainer* container, WritableFontData* data, - int32_t offset, const CMapId& cmap_id) + FontDataTableBuilderContainer* container, + WritableFontData* data, + int32_t offset, + const CMapId& cmap_id) : CMapTable::CMap::Builder(container, data ? down_cast( - data->slice(offset, data->readUShort( + data->Slice(offset, data->ReadUShort( offset + Offset::kFormat0Length))) : reinterpret_cast(NULL), CMapFormat::kFormat2, cmap_id) { @@ -342,23 +355,26 @@ CMapTable::CMapFormat2::Builder::Builder( } CMapTable::CMapFormat2::Builder::Builder( - FontDataTableBuilderContainer* container, ReadableFontData* data, - int32_t offset, const CMapId& cmap_id) + FontDataTableBuilderContainer* container, + ReadableFontData* data, + int32_t offset, + const CMapId& cmap_id) : CMapTable::CMap::Builder(container, data ? down_cast( - data->slice(offset, data->readUShort( + 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() {} +CMapTable::CMapFormat2::Builder::~Builder() { +} -CALLER_ATTACH FontDataTable* CMapTable::CMapFormat2::Builder::subBuildTable( - ReadableFontData* data) { - FontDataTablePtr table = new CMapFormat2(data, cmapId()); - return table.detach(); +CALLER_ATTACH FontDataTable* + CMapTable::CMapFormat2::Builder::SubBuildTable(ReadableFontData* data) { + FontDataTablePtr table = new CMapFormat2(data, cmap_id()); + return table.Detach(); } /****************************************************************************** @@ -367,16 +383,16 @@ CALLER_ATTACH FontDataTable* CMapTable::CMapFormat2::Builder::subBuildTable( CMapTable::CMapIterator::CMapIterator(CMapTable* table, CMapFilter* filter) : table_index_(0), filter_(filter), table_(table) {} -bool CMapTable::CMapIterator::hasNext() { +bool CMapTable::CMapIterator::HasNext() { if (!filter_) { - if (table_index_ < table_->numCMaps()) { + if (table_index_ < table_->NumCMaps()) { return true; } return false; } - for (; table_index_ < table_->numCMaps(); ++table_index_) { - if (filter_->accept(table_->cmapId(table_index_))) { + for (; table_index_ < table_->NumCMaps(); ++table_index_) { + if (filter_->accept(table_->GetCMapId(table_index_))) { return true; } } @@ -387,105 +403,109 @@ bool CMapTable::CMapIterator::hasNext() { * CMapTable::Builder class ******************************************************************************/ CMapTable::Builder::Builder(FontDataTableBuilderContainer* font_builder, - Header* header, WritableFontData* data) + Header* header, + WritableFontData* data) : Table::ArrayElementTableBuilder(font_builder, header, data) { } CMapTable::Builder::Builder(FontDataTableBuilderContainer* font_builder, - Header* header, ReadableFontData* data) + Header* header, + ReadableFontData* data) : Table::ArrayElementTableBuilder(font_builder, header, data) { } -int32_t CMapTable::Builder::subSerialize(WritableFontData* new_data) { - int32_t size = new_data->writeUShort(CMapTable::Offset::kVersion, +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, + size += new_data->WriteUShort(CMapTable::Offset::kNumTables, cmap_builders_.size()); int32_t index_offset = size; size += cmap_builders_.size() * CMapTable::Offset::kEncodingRecordSize; for (CMapBuilderMap::iterator it = cmap_builders_.begin(), - e = cmap_builders_.end(); it != e; ++it) { + e = cmap_builders_.end(); it != e; ++it) { CMapBuilderPtr b = it->second; // header entry - index_offset += new_data->writeUShort(index_offset, b->platformId()); - index_offset += new_data->writeUShort(index_offset, b->encodingId()); - index_offset += new_data->writeULong(index_offset, size); + 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_)); + slice.Attach(new_data->Slice(size)); + size += b->SubSerialize(down_cast(slice.p_)); } return size; } -bool CMapTable::Builder::subReadyToSerialize() { +bool CMapTable::Builder::SubReadyToSerialize() { if (cmap_builders_.empty()) return false; // check each table for (CMapBuilderMap::iterator it = cmap_builders_.begin(), - e = cmap_builders_.end(); it != e; ++it) { - if (!it->second->subReadyToSerialize()) + e = cmap_builders_.end(); it != e; ++it) { + if (!it->second->SubReadyToSerialize()) return false; } return true; } -int32_t CMapTable::Builder::subDataSizeToSerialize() { +int32_t CMapTable::Builder::SubDataSizeToSerialize() { if (cmap_builders_.empty()) return 0; bool variable = false; int32_t size = CMapTable::Offset::kEncodingRecordStart + - cmap_builders_.size() * CMapTable::Offset::kEncodingRecordSize; + cmap_builders_.size() * CMapTable::Offset::kEncodingRecordSize; // calculate size of each table for (CMapBuilderMap::iterator it = cmap_builders_.begin(), - e = cmap_builders_.end(); it != e; ++it) { - int32_t cmap_size = it->second->subDataSizeToSerialize(); + e = cmap_builders_.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() { +void CMapTable::Builder::SubDataSet() { cmap_builders_.clear(); - Table::Builder::setModelChanged(false); + Table::Builder::set_model_changed(false); } -CALLER_ATTACH FontDataTable* CMapTable::Builder::subBuildTable( - ReadableFontData* data) { +CALLER_ATTACH FontDataTable* + CMapTable::Builder::SubBuildTable(ReadableFontData* data) { FontDataTablePtr table = new CMapTable(header(), data); - return table.detach(); + return table.Detach(); } -CALLER_ATTACH CMapTable::CMap::Builder* CMapTable::Builder::cmapBuilder( +CALLER_ATTACH CMapTable::CMap::Builder* CMapTable::Builder::CMapBuilder( FontDataTableBuilderContainer* container, ReadableFontData* data, int32_t index) { - if (index < 0 || index > numCMaps(data)) + if (index < 0 || index > NumCMaps(data)) return NULL; int32_t record_offset = Offset::kEncodingRecordOffset + index * Offset::kEncodingRecordSize; - int32_t platform_id = data->readUShort(Offset::kEncodingRecordPlatformId + - record_offset); - int32_t encoding_id = data->readUShort(Offset::kEncodingRecordEncodingId + - record_offset); + int32_t platform_id = + data->ReadUShort(Offset::kEncodingRecordPlatformId + record_offset); + int32_t encoding_id = + data->ReadUShort(Offset::kEncodingRecordEncodingId + record_offset); CMapId cmap_id(platform_id, encoding_id); - int32_t offset = data->readULongAsInt(Offset::kEncodingRecordOffset + - record_offset); - return CMap::Builder::getBuilder(container, data, offset, cmap_id); + int32_t offset = + data->ReadULongAsInt(Offset::kEncodingRecordOffset + record_offset); + return CMap::Builder::GetBuilder(container, data, offset, cmap_id); } -int32_t CMapTable::Builder::numCMaps(ReadableFontData* data) { +int32_t CMapTable::Builder::NumCMaps(ReadableFontData* data) { if (data == NULL) { return 0; } - return data->readUShort(Offset::kNumTables); + return data->ReadUShort(Offset::kNumTables); } } // namespace sfntly diff --git a/sfntly/cmap_table.h b/sfntly/cmap_table.h index a102b82..cdbcad8 100644 --- a/sfntly/cmap_table.h +++ b/sfntly/cmap_table.h @@ -44,131 +44,19 @@ struct CMapFormat { // A CMap table class CMapTable : public Table, public RefCounted { - private: - static const int32_t NOTDEF; - - // 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, - - // 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 - }; - }; - - public: +public: // CMapTable::CMapId class CMapId { public: CMapId(int32_t platform_id, int32_t encoding_id); CMapId(const CMapId& obj); - int32_t platformId(); - int32_t encodingId(); + + int32_t platform_id() { return platform_id_; } + int32_t encoding_id() { return encoding_id_; } + bool operator==(const CMapId& obj); const CMapId& operator=(const CMapId& obj); - int hashCode() const; + int HashCode() const; friend class CMapIdComparator; @@ -219,12 +107,50 @@ class CMapTable : public Table, public RefCounted { class Builder; class CMap : public SubTable { public: + // CMapTable::CMap::Builder + class Builder : public SubTable::Builder { + public: + virtual ~Builder(); + + CALLER_ATTACH static Builder* + GetBuilder(FontDataTableBuilderContainer* container, + ReadableFontData* data, + int32_t offset, + 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(); } + + protected: + Builder(FontDataTableBuilderContainer* container, + ReadableFontData* data, + int32_t format, + const CMapId& cmap_id); + Builder(FontDataTableBuilderContainer* container, + 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_; + + friend class CMapTable::Builder; + }; + CMap(ReadableFontData* data, int32_t format, const CMapId& cmap_id); virtual ~CMap(); - virtual int32_t format(); - virtual CMapId cmapId(); - virtual int32_t platformId(); - virtual int32_t encodingId(); + 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. // @@ -239,47 +165,12 @@ class CMapTable : public Table, public RefCounted { // is not a language-specific encoding. // // @return the language id - virtual int32_t language() = 0; + 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; - - public: - // CMapTable::CMap::Builder - class Builder : public SubTable::Builder { - public: - friend class CMapTable::Builder; - - protected: - Builder(FontDataTableBuilderContainer* container, ReadableFontData* data, - int32_t format, const CMapId& cmap_id); - Builder(FontDataTableBuilderContainer* container, WritableFontData* data, - int32_t format, const CMapId& cmap_id); - - public: - virtual ~Builder(); - CALLER_ATTACH static Builder* - getBuilder(FontDataTableBuilderContainer* container, - ReadableFontData* data, int32_t offset, - const CMapId& cmap_id); - - // Note: yes, an object is returned on stack since it's small enough. - virtual CMapId cmapId(); - virtual int32_t platformId(); - virtual int32_t encodingId(); - - protected: - virtual int32_t subSerialize(WritableFontData* new_data); - virtual bool subReadyToSerialize(); - virtual int32_t subDataSizeToSerialize(); - virtual void subDataSet(); - - private: - int32_t format_; - CMapId cmap_id_; - }; + virtual int32_t GlyphId(int32_t character) = 0; private: int32_t format_; @@ -290,67 +181,76 @@ class CMapTable : public Table, public RefCounted { // A cmap format 0 sub table class CMapFormat0 : public CMap, public RefCounted { - protected: - CMapFormat0(ReadableFontData* data, const CMapId& cmap_id); - public: - virtual ~CMapFormat0(); - virtual int32_t language(); - virtual int32_t glyphId(int32_t character); - // CMapTable::CMapFormat0::Builder class Builder : public CMap::Builder, public RefCounted { public: - Builder(FontDataTableBuilderContainer* container, ReadableFontData* data, - int32_t offset, const CMapId& cmap_id); - Builder(FontDataTableBuilderContainer* container, WritableFontData* data, - int32_t offset, const CMapId& cmap_id); + Builder(FontDataTableBuilderContainer* container, + ReadableFontData* data, + int32_t offset, + const CMapId& cmap_id); + Builder(FontDataTableBuilderContainer* container, + WritableFontData* data, + int32_t offset, + const CMapId& cmap_id); virtual ~Builder(); + protected: virtual CALLER_ATTACH FontDataTable* - subBuildTable(ReadableFontData* data); + SubBuildTable(ReadableFontData* data); }; + + virtual ~CMapFormat0(); + virtual int32_t Language(); + virtual int32_t GlyphId(int32_t character); + + 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 { - protected: - CMapFormat2(ReadableFontData* data, const CMapId& cmap_id); - public: + // CMapTable::CMapFormat2::Builder + class Builder : public CMap::Builder, + public RefCounted { + public: + Builder(FontDataTableBuilderContainer* container, + ReadableFontData* data, + int32_t offset, + const CMapId& cmap_id); + Builder(FontDataTableBuilderContainer* container, + WritableFontData* data, + int32_t offset, + const CMapId& cmap_id); + virtual ~Builder(); + + protected: + virtual CALLER_ATTACH FontDataTable* + SubBuildTable(ReadableFontData* data); + }; + virtual ~CMapFormat2(); - virtual int32_t language(); - virtual int32_t glyphId(int32_t character); + 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 int32_t BytesConsumed(int32_t character); private: - 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); + CMapFormat2(ReadableFontData* data, const CMapId& cmap_id); - // CMapTable::CMapFormat2::Builder - class Builder : public CMap::Builder, - public RefCounted { - public: - Builder(FontDataTableBuilderContainer* container, ReadableFontData* data, - int32_t offset, const CMapId& cmap_id); - Builder(FontDataTableBuilderContainer* container, WritableFontData* data, - int32_t offset, const CMapId& cmap_id); - virtual ~Builder(); - protected: - virtual CALLER_ATTACH FontDataTable* - subBuildTable(ReadableFontData* data); - }; + 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); }; // CMapTable::Builder @@ -359,71 +259,185 @@ class CMapTable : public Table, public RefCounted { public: // Constructor scope altered to public because C++ does not allow base // class to instantiate derived class with protected constructors. - Builder(FontDataTableBuilderContainer* font_builder, Header* header, - WritableFontData* data); - Builder(FontDataTableBuilderContainer* font_builder, Header* header, - ReadableFontData* data); - - virtual int32_t subSerialize(WritableFontData* new_data); - virtual bool subReadyToSerialize(); - virtual int32_t subDataSizeToSerialize(); - virtual void subDataSet(); - virtual CALLER_ATTACH FontDataTable* subBuildTable(ReadableFontData* data); + Builder(FontDataTableBuilderContainer* font_builder, + Header* header, + WritableFontData* data); + Builder(FontDataTableBuilderContainer* font_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); protected: - static CALLER_ATTACH CMap::Builder* cmapBuilder( - FontDataTableBuilderContainer* container, ReadableFontData* data, - int32_t index); + static CALLER_ATTACH CMap::Builder* + CMapBuilder(FontDataTableBuilderContainer* container, + ReadableFontData* data, + int32_t index); private: - static int32_t numCMaps(ReadableFontData* data); + static int32_t NumCMaps(ReadableFontData* data); - private: int32_t version_; CMapBuilderMap cmap_builders_; }; - private: - class CMapIterator { - public: - // If filter is NULL, filter through all tables. - CMapIterator(CMapTable* table, CMapFilter* filter); - bool hasNext(); - CMap* next(); - - private: - int32_t table_index_; - CMapFilter* filter_; - CMapTable* table_; - }; - - private: - CMapTable(Header* header, ReadableFontData* data); - - public: virtual ~CMapTable(); // Get the table version. - virtual int32_t version(); + virtual int32_t Version(); // Get the number of cmaps within the CMap table. - virtual int32_t numCMaps(); + 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. - virtual CMapId cmapId(int32_t index); + // 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); + 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 int32_t Offset(int32_t index); private: + static const int32_t NOTDEF; + + // 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, + + // 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 + }; + }; + + class CMapIterator { + public: + // If filter is NULL, filter through all tables. + CMapIterator(CMapTable* table, CMapFilter* filter); + bool HasNext(); + CMap* Next(); + + private: + int32_t table_index_; + CMapFilter* filter_; + CMapTable* table_; + }; + + 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. - int32_t offsetForEncodingRecord(int32_t index); + int32_t OffsetForEncodingRecord(int32_t index); }; typedef std::vector CMapIdList; typedef Ptr CMapTablePtr; diff --git a/sfntly/data/byte_array.cc b/sfntly/data/byte_array.cc index b8c3717..5502185 100644 --- a/sfntly/data/byte_array.cc +++ b/sfntly/data/byte_array.cc @@ -14,52 +14,38 @@ * limitations under the License. */ +#include "sfntly/data/byte_array.h" + #include -#include "sfntly/data/byte_array.h" #include "sfntly/port/exception_type.h" namespace sfntly { const int32_t ByteArray::COPY_BUFFER_SIZE = 8192; -void ByteArray::init(int32_t filled_length, int32_t storage_length, - bool growable) { - storage_length_ = storage_length; - growable_ = growable; - setFilledLength(filled_length); -} - -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); -} - ByteArray::~ByteArray() {} -int32_t ByteArray::length() { return filled_length_; } -int32_t ByteArray::size() { return storage_length_; } -bool ByteArray::growable() { return growable_; } +int32_t ByteArray::Length() { return filled_length_; } +int32_t ByteArray::Size() { return storage_length_; } -int32_t ByteArray::setFilledLength(int32_t filled_length) { +int32_t ByteArray::SetFilledLength(int32_t filled_length) { filled_length_ = std::min(filled_length, storage_length_); return filled_length_; } -byte_t ByteArray::get(int32_t index) { - return internalGet(index); +byte_t ByteArray::Get(int32_t index) { + return InternalGet(index); } -int32_t ByteArray::get(int32_t index, ByteVector* b) { +int32_t ByteArray::Get(int32_t index, ByteVector* b) { assert(b); - return get(index, b, 0, b->size()); + return Get(index, b, 0, b->size()); } -int32_t ByteArray::get(int32_t index, ByteVector* b, int32_t offset, +int32_t ByteArray::Get(int32_t index, + ByteVector* b, + int32_t offset, int32_t length) { assert(b); if (index < 0 || index >= filled_length_) { @@ -69,47 +55,49 @@ int32_t ByteArray::get(int32_t index, ByteVector* b, int32_t offset, if (actual_length < 0) { return -1; } - return internalGet(index, b, offset, actual_length); + return InternalGet(index, b, offset, actual_length); } -bool ByteArray::put(int32_t index, byte_t b) { - if (index < 0 || index >= size()) { +bool ByteArray::Put(int32_t index, byte_t b) { + if (index < 0 || index >= Size()) { return false; } - bool result = internalPut(index, b); + bool result = InternalPut(index, b); filled_length_ = std::max(filled_length_, index + 1); return result; } -int32_t ByteArray::put(int index, ByteVector* b) { +int32_t ByteArray::Put(int index, ByteVector* b) { assert(b); - return put(index, b, 0, b->size()); + return Put(index, b, 0, b->size()); } -int32_t ByteArray::put(int32_t index, ByteVector* b, int32_t offset, +int32_t ByteArray::Put(int32_t index, + ByteVector* b, + int32_t offset, int32_t length) { assert(b); - if (index < 0 || index >= size()) { + if (index < 0 || index >= Size()) { return 0; } - int32_t actual_length = std::min(length, size() - index); - int32_t bytes_written = internalPut(index, b, offset, actual_length); + 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) { + 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(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 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 + if (array->Size() < dst_offset + length) { // insufficient space return -1; } @@ -118,8 +106,8 @@ int32_t ByteArray::copyTo(int32_t dst_offset, ByteArray* array, 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, buffer_length)) > 0) { - int bytes_written = array->put(index + dst_offset, &b, 0, bytes_read); + while ((bytes_read = Get(index + src_offset, &b, 0, buffer_length)) > 0) { + int bytes_written = array->Put(index + dst_offset, &b, 0, bytes_read); if (bytes_written != bytes_read) { #if defined (SFNTLY_NO_EXCEPTION) return 0; @@ -134,31 +122,30 @@ int32_t ByteArray::copyTo(int32_t dst_offset, ByteArray* array, return index; } -int32_t ByteArray::copyTo(OutputStream* os) { - return copyTo(os, 0, length()); +int32_t ByteArray::CopyTo(OutputStream* os) { + return CopyTo(os, 0, Length()); } -int32_t ByteArray::copyTo(OutputStream* os, int32_t offset, int32_t 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, buffer_length)) > 0) { - os->write(&b, 0, bytes_read); + while ((bytes_read = Get(index + offset, &b, 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) { +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, bytes_read) != bytes_read) { + while ((bytes_read = is->Read(&b, 0, buffer_length)) > 0) { + if (Put(index, &b, 0, bytes_read) != bytes_read) { #if defined (SFNTLY_NO_EXCEPTION) return 0; #else @@ -172,14 +159,13 @@ bool ByteArray::copyFrom(InputStream* is, int32_t length) { return true; } -bool ByteArray::copyFrom(InputStream* is) { +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, bytes_read) != bytes_read) { + while ((bytes_read = is->Read(&b, 0, buffer_length)) > 0) { + if (Put(index, &b, 0, bytes_read) != bytes_read) { #if defined (SFNTLY_NO_EXCEPTION) return 0; #else @@ -191,4 +177,22 @@ bool ByteArray::copyFrom(InputStream* is) { 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/sfntly/data/byte_array.h b/sfntly/data/byte_array.h index edb4633..9ac56c0 100644 --- a/sfntly/data/byte_array.h +++ b/sfntly/data/byte_array.h @@ -29,38 +29,27 @@ namespace sfntly { // C++ port of this class assumes that the data are stored in a linear region // like std::vector. class ByteArray : virtual public RefCount { - 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); - - static const int32_t COPY_BUFFER_SIZE; - public: virtual ~ByteArray(); // Get the current filled and readable length of the array. - int32_t length(); + int32_t Length(); // Get the maximum size of the array. This is the maximum number of bytes that // the array can hold and all of it may not be filled with data or even fully // allocated yet. - int32_t size(); + int32_t Size(); - bool growable(); - int32_t setFilledLength(int32_t filled_length); + bool growable() { return growable_; } + int32_t SetFilledLength(int32_t filled_length); - public: // Get the byte from the given index. - virtual byte_t get(int32_t index); + virtual byte_t Get(int32_t index); // Get 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. - virtual int32_t get(int32_t index, ByteVector* b); + virtual int32_t Get(int32_t index, ByteVector* b); // Get 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 @@ -70,17 +59,19 @@ class ByteArray : virtual public RefCount { // @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 put into the buffer - virtual int32_t get(int32_t index, ByteVector* b, int32_t offset, + virtual int32_t Get(int32_t index, + ByteVector* b, + int32_t offset, int32_t length); // Put 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 bool put(int32_t index, byte_t b); + virtual bool Put(int32_t index, byte_t b); // Put the specified bytes into the array at the given index. The entire // buffer is put into the array unless that would extend beyond the length and // the array isn't growable. - virtual int32_t put(int32_t index, ByteVector* b); + virtual int32_t Put(int32_t index, ByteVector* b); // Put 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 @@ -91,19 +82,21 @@ class ByteArray : virtual public RefCount { // @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, ByteVector* b, int32_t offset, + virtual int32_t Put(int32_t index, + ByteVector* b, + int32_t offset, int32_t length); // Fully copy this ByteArray to another ByteArray to the extent that the // destination array has storage for the data copied. - virtual int32_t copyTo(ByteArray* array); + virtual int32_t CopyTo(ByteArray* array); // Copy 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); + virtual int32_t CopyTo(ByteArray* array, int32_t offset, int32_t length); // Copy this ByteArray to another ByteArray. // @param dstOffset the offset in the destination array to start copying to @@ -111,25 +104,40 @@ class ByteArray : virtual public RefCount { // @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); + virtual int32_t CopyTo(int32_t dst_offset, + ByteArray* array, + int32_t src_offset, + int32_t length); - virtual int32_t copyTo(OutputStream* os); - virtual int32_t copyTo(OutputStream* os, int32_t offset, int32_t length); - virtual bool copyFrom(InputStream* is, int32_t length); - virtual bool copyFrom(InputStream* is); + virtual int32_t CopyTo(OutputStream* os); + virtual int32_t CopyTo(OutputStream* os, int32_t offset, int32_t length); + virtual bool CopyFrom(InputStream* is, int32_t length); + virtual bool CopyFrom(InputStream* is); protected: - virtual bool internalPut(int32_t index, byte_t b) = 0; - virtual int32_t internalPut(int32_t index, ByteVector* b, int32_t offset, + // 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); + + virtual bool InternalPut(int32_t index, byte_t b) = 0; + virtual int32_t InternalPut(int32_t index, + ByteVector* b, + int32_t offset, int32_t length) = 0; - virtual byte_t internalGet(int32_t index) = 0; - virtual int32_t internalGet(int32_t index, ByteVector* b, int32_t offset, + virtual byte_t InternalGet(int32_t index) = 0; + virtual int32_t InternalGet(int32_t index, + ByteVector* b, + int32_t offset, int32_t length) = 0; - virtual void close() = 0; + virtual void Close() = 0; + + // C++ port only, raw pointer to the first element of storage. + virtual byte_t* Begin() = 0; - // C++ port only, raw pointer to the first element of storage - virtual byte_t* begin() = 0; + static const int32_t COPY_BUFFER_SIZE; private: int32_t filled_length_; diff --git a/sfntly/data/font_data.cc b/sfntly/data/font_data.cc index fdba5f8..437a810 100644 --- a/sfntly/data/font_data.cc +++ b/sfntly/data/font_data.cc @@ -22,30 +22,12 @@ namespace sfntly { -FontData::~FontData() {} - -void FontData::init(ByteArray* ba) { - array_ = ba; - bound_offset_ = 0; - bound_length_ = INT_MAX; -} - -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(offset); +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) +bool FontData::Bound(int32_t offset, int32_t length) { + if (offset + length > Size() || offset < 0 || length < 0) return false; bound_offset_ += offset; @@ -53,27 +35,45 @@ bool FontData::bound(int32_t offset, int32_t length) { return true; } -bool FontData::bound(int32_t offset) { -if (offset > size() || offset < 0) +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_); +int32_t FontData::Length() const { + return std::min(array_->Length() - bound_offset_, bound_length_); } -int32_t FontData::size() const { - return std::min(array_->size() - 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(offset); +} + +FontData::~FontData() {} + +void FontData::Init(ByteArray* ba) { + array_ = ba; + bound_offset_ = 0; + bound_length_ = INT_MAX; } -int32_t FontData::boundOffset(int32_t offset) { +int32_t FontData::BoundOffset(int32_t offset) { return offset + bound_offset_; } -int32_t FontData::boundLength(int32_t offset, int32_t length) { +int32_t FontData::BoundLength(int32_t offset, int32_t length) { return std::min(length, bound_length_ - offset); } diff --git a/sfntly/data/font_data.h b/sfntly/data/font_data.h index 6bcdb73..ab5cf54 100644 --- a/sfntly/data/font_data.h +++ b/sfntly/data/font_data.h @@ -18,6 +18,7 @@ #define TYPOGRAPHY_FONT_SFNTLY_SRC_SFNTLY_DATA_FONT_DATA_H_ #include + #include "sfntly/port/type.h" #include "sfntly/data/byte_array.h" #include "sfntly/port/refcount.h" @@ -51,13 +52,13 @@ class FontData : virtual public RefCount { // that the font data can hold and all of it may not be filled with data or // even fully allocated yet. // @return the size of this array - virtual int32_t size() const; + virtual int32_t Size() const; // Sets limits on the size of the FontData. The font data is // @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); + 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 @@ -65,28 +66,25 @@ class FontData : virtual public RefCount { // @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); + 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; + 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; + virtual CALLER_ATTACH FontData* Slice(int32_t offset) = 0; // Get the length of the data. - virtual int32_t length() const; - + virtual int32_t Length() const; protected: - virtual ~FontData(); - // Constructor. // @param ba the byte array to use for the backing data explicit FontData(ByteArray* ba); @@ -101,12 +99,13 @@ class FontData : virtual public RefCount { // @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); - int32_t boundOffset(int32_t offset); - int32_t boundLength(int32_t offset, int32_t length); + void Init(ByteArray* ba); + int32_t BoundOffset(int32_t offset); + int32_t BoundLength(int32_t offset, int32_t length); - protected: + // TODO(arthurhsu): style guide violation: refactor this protected member ByteArrayPtr array_; private: diff --git a/sfntly/data/font_input_stream.cc b/sfntly/data/font_input_stream.cc index b9eccdb..a1fbe44 100644 --- a/sfntly/data/font_input_stream.cc +++ b/sfntly/data/font_input_stream.cc @@ -14,10 +14,10 @@ * limitations under the License. */ -#include - #include "sfntly/data/font_input_stream.h" +#include + namespace sfntly { FontInputStream::FontInputStream(InputStream* is) @@ -32,50 +32,50 @@ FontInputStream::~FontInputStream() { // Do not close here, underlying InputStream will close themselves. } -int32_t FontInputStream::available() { +int32_t FontInputStream::Available() { if (stream_) { - return stream_->available(); + return stream_->Available(); } return 0; } -void FontInputStream::close() { +void FontInputStream::Close() { if (stream_) { - stream_->close(); + stream_->Close(); } } -void FontInputStream::mark(int32_t readlimit) { +void FontInputStream::Mark(int32_t readlimit) { if (stream_) { - stream_->mark(readlimit); + stream_->Mark(readlimit); } } -bool FontInputStream::markSupported() { +bool FontInputStream::MarkSupported() { if (stream_) { - return stream_->markSupported(); + return stream_->MarkSupported(); } return false; } -void FontInputStream::reset() { +void FontInputStream::Reset() { if (stream_) { - stream_->reset(); + stream_->Reset(); } } -int32_t FontInputStream::read() { +int32_t FontInputStream::Read() { if (!stream_ || (bounded_ && position_ >= length_)) { return -1; } - int32_t b = stream_->read(); + int32_t b = stream_->Read(); if (b >= 0) { position_++; } return b; } -int32_t FontInputStream::read(ByteVector* b, int32_t offset, int32_t length) { +int32_t FontInputStream::Read(ByteVector* b, int32_t offset, int32_t length) { if (!stream_ || offset < 0 || length < 0 || (bounded_ && position_ >= length_)) { return -1; @@ -83,59 +83,55 @@ int32_t FontInputStream::read(ByteVector* b, int32_t offset, int32_t length) { 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); + 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()); -} - -int64_t FontInputStream::position() { - return position_; +int32_t FontInputStream::Read(ByteVector* b) { + return Read(b, 0, b->size()); } -int32_t FontInputStream::readChar() { - return read(); +int32_t FontInputStream::ReadChar() { + return Read(); } -int32_t FontInputStream::readUShort() { - return 0xffff & (read() << 8 | read()); +int32_t FontInputStream::ReadUShort() { + return 0xffff & (Read() << 8 | Read()); } -int32_t FontInputStream::readShort() { - return ((read() << 8 | read()) << 16) >> 16; +int32_t FontInputStream::ReadShort() { + return ((Read() << 8 | Read()) << 16) >> 16; } -int32_t FontInputStream::readUInt24() { - return 0xffffff & (read() << 16 | read() << 8 | read()); +int32_t FontInputStream::ReadUInt24() { + return 0xffffff & (Read() << 16 | Read() << 8 | Read()); } -int64_t FontInputStream::readULong() { - return 0xffffffffL & readLong(); +int64_t FontInputStream::ReadULong() { + return 0xffffffffL & ReadLong(); } -int32_t FontInputStream::readULongAsInt() { - int64_t ulong = readULong(); +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::ReadLong() { + return Read() << 24 | Read() << 16 | Read() << 8 | Read(); } -int32_t FontInputStream::readFixed() { - return readLong(); +int32_t FontInputStream::ReadFixed() { + return ReadLong(); } -int64_t FontInputStream::readDateTimeAsLong() { - return (int64_t)readULong() << 32 | readULong(); +int64_t FontInputStream::ReadDateTimeAsLong() { + return (int64_t)ReadULong() << 32 | ReadULong(); } -int64_t FontInputStream::skip(int64_t n) { +int64_t FontInputStream::Skip(int64_t n) { if (stream_) { - int64_t skipped = stream_->skip(n); + int64_t skipped = stream_->Skip(n); position_ += skipped; return skipped; } diff --git a/sfntly/data/font_input_stream.h b/sfntly/data/font_input_stream.h index ed8d364..7404825 100644 --- a/sfntly/data/font_input_stream.h +++ b/sfntly/data/font_input_stream.h @@ -33,33 +33,33 @@ class FontInputStream : public InputStream { 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 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); + virtual int32_t Read(); + virtual int32_t Read(ByteVector* buffer); + virtual int32_t Read(ByteVector* buffer, int32_t offset, int32_t length); - virtual int64_t position(); + 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 + 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 + int64_t length_; // Bound on length of data to read. bool bounded_; }; diff --git a/sfntly/data/font_output_stream.cc b/sfntly/data/font_output_stream.cc index f0f4744..a88a29e 100644 --- a/sfntly/data/font_output_stream.cc +++ b/sfntly/data/font_output_stream.cc @@ -14,95 +14,91 @@ * limitations under the License. */ -#include - #include "sfntly/data/font_output_stream.h" -#include "sfntly/port/endian.h" + +#include namespace sfntly { FontOutputStream::FontOutputStream(OutputStream* os) - : stream_(os), position_(0) { + : stream_(os), + position_(0) { } FontOutputStream::~FontOutputStream() { // Do not close, underlying stream shall clean up themselves. } -size_t FontOutputStream::position() { - return position_; -} - -void FontOutputStream::write(byte_t b) { +void FontOutputStream::Write(byte_t b) { if (stream_) { - stream_->write(b); + stream_->Write(b); position_++; } } -void FontOutputStream::write(ByteVector* b) { +void FontOutputStream::Write(ByteVector* b) { if (b) { - write(b, 0, b->size()); + Write(b, 0, b->size()); position_ += b->size(); } } -void FontOutputStream::write(ByteVector* b, int32_t offset, int32_t length) { +void FontOutputStream::Write(ByteVector* b, int32_t offset, int32_t length) { if (stream_ && b) { - stream_->write(b, offset, length); + stream_->Write(b, offset, length); position_ += length; } } -void FontOutputStream::writeChar(byte_t c) { - write(c); +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::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::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::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::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::WriteLong(int64_t l) { + WriteULong(l); } -void FontOutputStream::writeFixed(int32_t f) { - writeULong(f); +void FontOutputStream::WriteFixed(int32_t f) { + WriteULong(f); } -void FontOutputStream::writeDateTime(int64_t date) { - writeULong((date >> 32) & 0xffffffff); - writeULong(date & 0xffffffff); +void FontOutputStream::WriteDateTime(int64_t date) { + WriteULong((date >> 32) & 0xffffffff); + WriteULong(date & 0xffffffff); } -void FontOutputStream::flush() { +void FontOutputStream::Flush() { if (stream_) { - stream_->flush(); + stream_->Flush(); } } -void FontOutputStream::close() { +void FontOutputStream::Close() { if (stream_) { - stream_->flush(); - stream_->close(); + stream_->Flush(); + stream_->Close(); position_ = 0; } } diff --git a/sfntly/data/font_output_stream.h b/sfntly/data/font_output_stream.h index 4bb923d..6938b66 100644 --- a/sfntly/data/font_output_stream.h +++ b/sfntly/data/font_output_stream.h @@ -32,22 +32,22 @@ class FontOutputStream : public OutputStream { explicit FontOutputStream(OutputStream* os); virtual ~FontOutputStream(); - virtual size_t position(); - - virtual void write(byte_t b); - virtual void write(ByteVector* b); - virtual void write(ByteVector* b, int32_t offset, 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); - - virtual void flush(); - virtual void close(); + virtual size_t position() { return position_; } + + virtual void Write(byte_t b); + virtual void Write(ByteVector* b); + virtual void Write(ByteVector* b, int32_t offset, 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); + + virtual void Flush(); + virtual void Close(); private: OutputStream* stream_; diff --git a/sfntly/data/growable_memory_byte_array.cc b/sfntly/data/growable_memory_byte_array.cc index 0821321..9e1a043 100644 --- a/sfntly/data/growable_memory_byte_array.cc +++ b/sfntly/data/growable_memory_byte_array.cc @@ -14,10 +14,11 @@ * limitations under the License. */ +#include "sfntly/data/growable_memory_byte_array.h" + #include -#include -#include "sfntly/data/growable_memory_byte_array.h" +#include namespace sfntly { @@ -27,40 +28,46 @@ GrowableMemoryByteArray::GrowableMemoryByteArray() GrowableMemoryByteArray::~GrowableMemoryByteArray() {} -bool GrowableMemoryByteArray::internalPut(int32_t index, byte_t b) { +bool GrowableMemoryByteArray::InternalPut(int32_t index, byte_t b) { if ((size_t)index >= b_.capacity()) { - b_.resize((size_t)(index + 1) << 2); // grow exponentially + b_.resize((size_t)(index + 1) << 2); // Grow exponentially. } b_[index] = b; return true; } -int32_t GrowableMemoryByteArray::internalPut(int32_t index, ByteVector* b, - int32_t offset, int32_t length) { +int32_t GrowableMemoryByteArray::InternalPut(int32_t index, + ByteVector* b, + int32_t offset, + int32_t length) { if ((size_t)index + length >= b_.capacity()) { b_.resize((size_t)(index + length + 1) << 2); } - std::copy(b->begin() + offset, b->begin() + (offset + length), + std::copy(b->begin() + offset, + b->begin() + (offset + length), b_.begin() + index); return length; } -byte_t GrowableMemoryByteArray::internalGet(int32_t index) { +byte_t GrowableMemoryByteArray::InternalGet(int32_t index) { return b_[index]; } -int32_t GrowableMemoryByteArray::internalGet(int32_t index, ByteVector* b, - int32_t offset, int32_t length) { - std::copy(b_.begin() + index, b_.begin() + (index + length), +int32_t GrowableMemoryByteArray::InternalGet(int32_t index, + ByteVector* b, + int32_t offset, + int32_t length) { + std::copy(b_.begin() + index, + b_.begin() + (index + length), b->begin() + offset); return length; } -void GrowableMemoryByteArray::close() { +void GrowableMemoryByteArray::Close() { b_.clear(); } -byte_t* GrowableMemoryByteArray::begin() { +byte_t* GrowableMemoryByteArray::Begin() { return &(b_[0]); } diff --git a/sfntly/data/growable_memory_byte_array.h b/sfntly/data/growable_memory_byte_array.h index 3c9d4f0..dc59f62 100644 --- a/sfntly/data/growable_memory_byte_array.h +++ b/sfntly/data/growable_memory_byte_array.h @@ -30,14 +30,18 @@ class GrowableMemoryByteArray : public ByteArray, virtual ~GrowableMemoryByteArray(); protected: - virtual bool internalPut(int32_t index, byte_t b); - virtual int32_t internalPut(int32_t index, ByteVector* b, int32_t offset, + virtual bool InternalPut(int32_t index, byte_t b); + virtual int32_t InternalPut(int32_t index, + ByteVector* b, + int32_t offset, int32_t length); - virtual byte_t internalGet(int32_t index); - virtual int32_t internalGet(int32_t index, ByteVector* b, int32_t offset, + virtual byte_t InternalGet(int32_t index); + virtual int32_t InternalGet(int32_t index, + ByteVector* b, + int32_t offset, int32_t length); - virtual void close(); - virtual byte_t* begin(); + virtual void Close(); + virtual byte_t* Begin(); private: ByteVector b_; diff --git a/sfntly/data/memory_byte_array.cc b/sfntly/data/memory_byte_array.cc index 528979a..0138b21 100644 --- a/sfntly/data/memory_byte_array.cc +++ b/sfntly/data/memory_byte_array.cc @@ -14,13 +14,13 @@ * limitations under the License. */ -#include - #include "sfntly/data/memory_byte_array.h" +#include + namespace sfntly { -// Note: this constructor can fail under low-memory situation +// Note: this constructor can fail under low-memory situation. MemoryByteArray::MemoryByteArray(int32_t length) : ByteArray(0, length), b_(NULL), allocated_(true) { } @@ -29,56 +29,61 @@ MemoryByteArray::MemoryByteArray(byte_t* b, int32_t buffer_length) : ByteArray(buffer_length, buffer_length), b_(b), allocated_(false) { } -MemoryByteArray::MemoryByteArray(byte_t* b, int32_t buffer_length, +MemoryByteArray::MemoryByteArray(byte_t* b, + int32_t buffer_length, int32_t filled_length) : ByteArray(filled_length, buffer_length), b_(b), allocated_(false) { } MemoryByteArray::~MemoryByteArray() { - close(); + Close(); } -void MemoryByteArray::init() { +void MemoryByteArray::Init() { if (allocated_ && b_ == NULL) { - b_ = new byte_t[size()]; - memset(b_, 0, size()); + b_ = new byte_t[Size()]; + memset(b_, 0, Size()); } } -bool MemoryByteArray::internalPut(int32_t index, byte_t b) { - init(); +bool MemoryByteArray::InternalPut(int32_t index, byte_t b) { + Init(); b_[index] = b; return true; } -int32_t MemoryByteArray::internalPut(int32_t index, ByteVector* b, - int32_t offset, int32_t length) { - init(); +int32_t MemoryByteArray::InternalPut(int32_t index, + ByteVector* b, + int32_t offset, + int32_t length) { + Init(); memcpy(b_ + index, &((*b)[offset]), length); return length; } -byte_t MemoryByteArray::internalGet(int32_t index) { - init(); +byte_t MemoryByteArray::InternalGet(int32_t index) { + Init(); return b_[index]; } -int32_t MemoryByteArray::internalGet(int32_t index, ByteVector* b, - int32_t offset, int32_t length) { - init(); +int32_t MemoryByteArray::InternalGet(int32_t index, + ByteVector* b, + int32_t offset, + int32_t length) { + Init(); memcpy(&((*b)[offset]), b_ + index, length); return length; } -void MemoryByteArray::close() { +void MemoryByteArray::Close() { if (allocated_ && b_) { delete[] b_; } b_ = NULL; } -byte_t* MemoryByteArray::begin() { - init(); +byte_t* MemoryByteArray::Begin() { + Init(); return b_; } diff --git a/sfntly/data/memory_byte_array.h b/sfntly/data/memory_byte_array.h index 34b26a6..171dcc7 100644 --- a/sfntly/data/memory_byte_array.h +++ b/sfntly/data/memory_byte_array.h @@ -29,17 +29,21 @@ class MemoryByteArray : public ByteArray, public RefCounted { virtual ~MemoryByteArray(); protected: - virtual bool internalPut(int32_t index, byte_t b); - virtual int32_t internalPut(int32_t index, ByteVector* b, int32_t offset, + virtual bool InternalPut(int32_t index, byte_t b); + virtual int32_t InternalPut(int32_t index, + ByteVector* b, + int32_t offset, int32_t length); - virtual byte_t internalGet(int32_t index); - virtual int32_t internalGet(int32_t index, ByteVector* b, int32_t offset, + virtual byte_t InternalGet(int32_t index); + virtual int32_t InternalGet(int32_t index, + ByteVector* b, + int32_t offset, int32_t length); - virtual void close(); - virtual byte_t* begin(); + virtual void Close(); + virtual byte_t* Begin(); private: - void init(); // C++ port only, used to allocate memory outside constructor. + void Init(); // C++ port only, used to allocate memory outside constructor. byte_t* b_; bool allocated_; diff --git a/sfntly/data/readable_font_data.cc b/sfntly/data/readable_font_data.cc index fa7279e..5f8478d 100644 --- a/sfntly/data/readable_font_data.cc +++ b/sfntly/data/readable_font_data.cc @@ -20,119 +20,69 @@ namespace sfntly { -ReadableFontData::~ReadableFontData() {} - ReadableFontData::ReadableFontData(ByteArray* array) - : FontData(array), checksum_set_(false), checksum_(0) { -} - -ReadableFontData::ReadableFontData(ReadableFontData* data, int32_t offset) - : FontData(data, offset), checksum_set_(false), checksum_(0) { + : FontData(array), + checksum_set_(false), + checksum_(0) { } -ReadableFontData::ReadableFontData(ReadableFontData* data, int32_t offset, - int32_t length) - : FontData(data, offset, length), checksum_set_(false), checksum_(0) { -} +ReadableFontData::~ReadableFontData() {} -int64_t ReadableFontData::checksum() { +int64_t ReadableFontData::Checksum() { // TODO(arthurhsu): IMPLEMENT: atomicity if (!checksum_set_) { - computeChecksum(); + ComputeChecksum(); } return checksum_; } -/* OpenType checksum -ULONG -CalcTableChecksum(ULONG *Table, ULONG Length) -{ -ULONG Sum = 0L; -ULONG *Endptr = Table+((Length+3) & ~3) / sizeof(ULONG); -while (Table < EndPtr) - Sum += *Table++; -return Sum; -} -*/ -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; - for (int32_t i = low_bound; i < high_bound; i += 4) { - int32_t b3 = readUByte(i); - b3 = (b3 == -1) ? 0 : b3; - int32_t b2 = readUByte(i + 1); - b2 = (b2 == -1) ? 0 : b2; - int32_t b1 = readUByte(i + 2); - b1 = (b1 == -1) ? 0 : b1; - int32_t b0 = readUByte(i + 3); - b0 = (b0 == -1) ? 0 : b0; - sum += (b3 << 24) | (b2 << 16) | (b1 << 8) | b0; - } - return sum; -} - -void ReadableFontData::setCheckSumRanges(const IntegerList& ranges) { +void ReadableFontData::SetCheckSumRanges(const IntegerList& ranges) { checksum_range_ = ranges; checksum_set_ = false; // UNIMPLEMENTED: atomicity } -int32_t ReadableFontData::readUByte(int32_t index) { - return 0xff & array_->get(boundOffset(index)); +int32_t ReadableFontData::ReadUByte(int32_t index) { + return 0xff & array_->Get(BoundOffset(index)); } -int32_t ReadableFontData::readByte(int32_t index) { - return (array_->get(boundOffset(index)) << 24) >> 24; +int32_t ReadableFontData::ReadByte(int32_t index) { + return (array_->Get(BoundOffset(index)) << 24) >> 24; } -int32_t ReadableFontData::readBytes(int32_t index, ByteVector* b, - int32_t offset, int32_t length) { - return array_->get(boundOffset(index), b, offset, boundLength(index, length)); +int32_t ReadableFontData::ReadBytes(int32_t index, + ByteVector* 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::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::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::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)); +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)); +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); +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."); @@ -141,59 +91,125 @@ int32_t ReadableFontData::readULongAsInt(int32_t index) { return ((int32_t)ulong) & ~0x80000000; } -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::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); +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); +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::ReadFWord(int32_t index) { + return ReadShort(index); } -int32_t ReadableFontData::readFUFWord(int32_t index) { - return readUShort(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(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(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::CopyTo(ByteArray* ba) { + return array_->CopyTo(ba, BoundOffset(0), Length()); } -CALLER_ATTACH FontData* ReadableFontData::slice(int32_t offset, +CALLER_ATTACH FontData* ReadableFontData::Slice(int32_t offset, int32_t length) { - if (offset < 0 || offset + length > size()) { + if (offset < 0 || offset + length > Size()) { return NULL; } FontDataPtr slice = new ReadableFontData(this, offset, length); // Note: exception not ported because the condition is always false in C++. // if (slice == null) { throw new IndexOutOfBoundsException( ... - return slice.detach(); + return slice.Detach(); } -CALLER_ATTACH FontData* ReadableFontData::slice(int32_t offset) { - if (offset < 0 || offset > size()) { +CALLER_ATTACH FontData* ReadableFontData::Slice(int32_t offset) { + if (offset < 0 || offset > Size()) { return NULL; } FontDataPtr slice = new ReadableFontData(this, offset); // Note: exception not ported because the condition is always false in C++. // if (slice == null) { throw new IndexOutOfBoundsException( ... - return slice.detach(); + 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) { +} + +/* OpenType checksum +ULONG +CalcTableChecksum(ULONG *Table, ULONG Length) +{ +ULONG Sum = 0L; +ULONG *Endptr = Table+((Length+3) & ~3) / sizeof(ULONG); +while (Table < EndPtr) + Sum += *Table++; +return Sum; +} +*/ +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; + for (int32_t i = low_bound; i < high_bound; i += 4) { + int32_t b3 = ReadUByte(i); + b3 = (b3 == -1) ? 0 : b3; + int32_t b2 = ReadUByte(i + 1); + b2 = (b2 == -1) ? 0 : b2; + int32_t b1 = ReadUByte(i + 2); + b1 = (b1 == -1) ? 0 : b1; + int32_t b0 = ReadUByte(i + 3); + b0 = (b0 == -1) ? 0 : b0; + sum += (b3 << 24) | (b2 << 16) | (b1 << 8) | b0; + } + return sum; } } // namespace sfntly diff --git a/sfntly/data/readable_font_data.h b/sfntly/data/readable_font_data.h index be466de..b1ca846 100644 --- a/sfntly/data/readable_font_data.h +++ b/sfntly/data/readable_font_data.h @@ -30,71 +30,52 @@ class ReadableFontData : public FontData, explicit ReadableFontData(ByteArray* array); virtual ~ReadableFontData(); - 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 - ReadableFontData(ReadableFontData* data, int32_t offset, int32_t length); - - private: - void computeChecksum(); - int64_t computeCheckSum(int32_t low_bound, int32_t high_bound); - - public: // Get 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(); + 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); + void SetCheckSumRanges(const IntegerList& ranges); - public: - virtual int32_t readUByte(int32_t index); - virtual int32_t readByte(int32_t index); - virtual int32_t readBytes(int32_t index, ByteVector* b, int32_t offset, + virtual int32_t ReadUByte(int32_t index); + virtual int32_t ReadByte(int32_t index); + virtual int32_t ReadBytes(int32_t index, ByteVector* b, int32_t offset, int32_t length); - virtual int32_t readChar(int32_t index); - virtual int32_t readUShort(int32_t index); - virtual int32_t readShort(int32_t index); - virtual int32_t readUInt24(int32_t index); - virtual int64_t readULong(int32_t index); - virtual int32_t readULongAsInt(int32_t index); - virtual int32_t readLong(int32_t index); - virtual int32_t readFixed(int32_t index); - virtual int64_t readDateTimeAsLong(int32_t index); - - virtual int32_t readFWord(int32_t index); - virtual int32_t readFUFWord(int32_t index); - - virtual int32_t copyTo(OutputStream* os); - virtual int32_t copyTo(WritableFontData* wfd); - virtual int32_t copyTo(ByteArray* ba); + virtual int32_t ReadChar(int32_t index); + virtual int32_t ReadUShort(int32_t index); + virtual int32_t ReadShort(int32_t index); + virtual int32_t ReadUInt24(int32_t index); + virtual int64_t ReadULong(int32_t index); + virtual int32_t ReadULongAsInt(int32_t index); + virtual int32_t ReadLong(int32_t index); + virtual int32_t ReadFixed(int32_t index); + virtual int64_t ReadDateTimeAsLong(int32_t index); + + virtual int32_t ReadFWord(int32_t index); + virtual int32_t ReadFUFWord(int32_t index); + + virtual int32_t CopyTo(OutputStream* os); + virtual int32_t CopyTo(WritableFontData* wfd); + virtual int32_t CopyTo(ByteArray* ba); // TODO(arthurhsu): IMPLEMENT /* - virtual int32_t readFUnit(int32_t index); - virtual int64_t readF2Dot14(int32_t index); - virtual int64_t readLongDateTime(int32_t index); - virtual int32_t searchUShort(int32_t start, int32_t length, int32_t key); - virtual int32_t searchUShort(int32_t start_index, int32_t start_offset, + virtual int32_t ReadFUnit(int32_t index); + virtual int64_t ReadF2Dot14(int32_t index); + virtual int64_t ReadLongDateTime(int32_t index); + virtual int32_t SearchUShort(int32_t start, int32_t length, int32_t key); + virtual int32_t SearchUShort(int32_t start_index, int32_t start_offset, int32_t count_index, int32_t count_offset, int32_t length, int32_t key); - virtual int32_t searchULong(int32_t start_index, int32_t start_offset, + virtual 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); */ @@ -104,16 +85,32 @@ class ReadableFontData : public 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); + 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); + virtual CALLER_ATTACH FontData* Slice(int32_t offset); + + 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 + ReadableFontData(ReadableFontData* data, int32_t offset, int32_t length); private: - bool checksum_set_; // TODO(arthurhsu): IMPLEMENT: must be set atomically + void ComputeChecksum(); + int64_t ComputeCheckSum(int32_t low_bound, int32_t high_bound); + + bool checksum_set_; // TODO(arthurhsu): IMPLEMENT: must be set atomically. int64_t checksum_; IntegerList checksum_range_; }; diff --git a/sfntly/data/writable_font_data.cc b/sfntly/data/writable_font_data.cc index 8588acb..586acc1 100644 --- a/sfntly/data/writable_font_data.cc +++ b/sfntly/data/writable_font_data.cc @@ -18,111 +18,116 @@ namespace sfntly { -WritableFontData::~WritableFontData() {} - WritableFontData::WritableFontData(ByteArray* ba) : ReadableFontData(ba) { } -WritableFontData::WritableFontData(WritableFontData* data, int32_t offset) - : ReadableFontData(data, offset) { -} - -WritableFontData::WritableFontData(WritableFontData* data, int32_t offset, - int32_t length) - : ReadableFontData(data, offset, length) { -} +WritableFontData::~WritableFontData() {} -int32_t WritableFontData::writeByte(int32_t index, byte_t b) { - array_->put(boundOffset(index), b); +int32_t WritableFontData::WriteByte(int32_t index, byte_t b) { + array_->Put(BoundOffset(index), b); return 1; } -int32_t WritableFontData::writeBytes(int32_t offset, ByteVector* b, - int32_t index, int32_t length) { - return array_->put(boundOffset(offset), b, index, - boundLength(offset, length)); +int32_t WritableFontData::WriteBytes(int32_t offset, + ByteVector* b, + int32_t index, + int32_t length) { + return array_->Put(BoundOffset(offset), + b, + index, + BoundLength(offset, length)); } -int32_t WritableFontData::writeBytes(int32_t index, ByteVector* b) { - return writeBytes(index, b, 0, b->size()); +int32_t WritableFontData::WriteBytes(int32_t index, ByteVector* b) { + return WriteBytes(index, b, 0, b->size()); } -int32_t WritableFontData::writeChar(int32_t index, byte_t c) { - return writeByte(index, c); +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)); +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)); +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::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)); +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)); +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)); +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::WriteLong(int32_t index, int64_t l) { + return WriteULong(index, l); } -int32_t WritableFontData::writeFixed(int32_t index, int32_t l) { - return writeLong(index, l); +int32_t WritableFontData::WriteFixed(int32_t index, int32_t l) { + return WriteLong(index, l); } -int32_t WritableFontData::writeDateTime(int32_t index, int64_t date) { - writeULong(index, (date >> 32) & 0xffffffff); - writeULong(index + 4, date & 0xffffffff); +int32_t WritableFontData::WriteDateTime(int32_t index, int64_t date) { + WriteULong(index, (date >> 32) & 0xffffffff); + WriteULong(index + 4, date & 0xffffffff); return 8; } -CALLER_ATTACH FontData* WritableFontData::slice(int32_t offset, +CALLER_ATTACH FontData* WritableFontData::Slice(int32_t offset, int32_t length) { - if (offset < 0 || offset + length > size()) { + if (offset < 0 || offset + length > Size()) { return NULL; } FontDataPtr slice = new WritableFontData(this, offset, length); // Note: exception not ported because the condition is always false in C++. // if (slice == null) { throw new IndexOutOfBoundsException( ... - return slice.detach(); + return slice.Detach(); } -CALLER_ATTACH FontData* WritableFontData::slice(int32_t offset) { - if (offset > size()) { +CALLER_ATTACH FontData* WritableFontData::Slice(int32_t offset) { + if (offset > Size()) { return NULL; } FontDataPtr slice = new WritableFontData(this, offset); // Note: exception not ported because the condition is always false in C++. // if (slice == null) { throw new IndexOutOfBoundsException( ... - return slice.detach(); + 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/sfntly/data/writable_font_data.h b/sfntly/data/writable_font_data.h index 9542cd0..98c9204 100644 --- a/sfntly/data/writable_font_data.h +++ b/sfntly/data/writable_font_data.h @@ -26,38 +26,39 @@ class WritableFontData : public ReadableFontData { explicit WritableFontData(ByteArray* ba); virtual ~WritableFontData(); - private: - WritableFontData(WritableFontData* data, int32_t offset); - WritableFontData(WritableFontData* data, int32_t offset, int32_t length); - - public: - virtual int32_t writeByte(int32_t index, byte_t b); - virtual int32_t writeBytes(int32_t offset, ByteVector* b, int32_t index, + virtual int32_t WriteByte(int32_t index, byte_t b); + virtual int32_t WriteBytes(int32_t offset, + ByteVector* b, + int32_t index, int32_t length); - virtual int32_t writeBytes(int32_t index, ByteVector* b); - virtual int32_t writeChar(int32_t index, byte_t c); - virtual int32_t writeUShort(int32_t index, int32_t us); - virtual int32_t writeUShortLE(int32_t index, int32_t us); - virtual int32_t writeShort(int32_t index, int32_t s); - virtual int32_t writeUInt24(int32_t index, int32_t ui); - virtual int32_t writeULong(int32_t index, int64_t ul); - virtual int32_t writeULongLE(int32_t index, int64_t ul); - virtual int32_t writeLong(int32_t index, int64_t l); - virtual int32_t writeFixed(int32_t index, int32_t l); - virtual int32_t writeDateTime(int32_t index, int64_t date); + virtual int32_t WriteBytes(int32_t index, ByteVector* b); + virtual int32_t WriteChar(int32_t index, byte_t c); + virtual int32_t WriteUShort(int32_t index, int32_t us); + virtual int32_t WriteUShortLE(int32_t index, int32_t us); + virtual int32_t WriteShort(int32_t index, int32_t s); + virtual int32_t WriteUInt24(int32_t index, int32_t ui); + virtual int32_t WriteULong(int32_t index, int64_t ul); + virtual int32_t WriteULongLE(int32_t index, int64_t ul); + virtual int32_t WriteLong(int32_t index, int64_t l); + virtual int32_t WriteFixed(int32_t index, int32_t l); + virtual int32_t WriteDateTime(int32_t index, int64_t date); // 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); + 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); + virtual CALLER_ATTACH FontData* Slice(int32_t offset); + + private: + WritableFontData(WritableFontData* data, int32_t offset); + WritableFontData(WritableFontData* data, int32_t offset, int32_t length); }; typedef Ptr WritableFontDataPtr; diff --git a/sfntly/font.cc b/sfntly/font.cc index bd5614f..fefa17e 100644 --- a/sfntly/font.cc +++ b/sfntly/font.cc @@ -14,95 +14,85 @@ * limitations under the License. */ +#include "sfntly/font.h" + #include #include #include #include -#include "sfntly/font.h" +#include "sfntly/data/font_input_stream.h" #include "sfntly/font_factory.h" -#include "sfntly/tag.h" #include "sfntly/math/fixed1616.h" #include "sfntly/math/font_math.h" -#include "sfntly/data/font_input_stream.h" #include "sfntly/font_header_table.h" #include "sfntly/horizontal_header_table.h" #include "sfntly/horizontal_metrics_table.h" -#include "sfntly/maximum_profile_table.h" #include "sfntly/loca_table.h" +#include "sfntly/maximum_profile_table.h" #include "sfntly/port/exception_type.h" +#include "sfntly/tag.h" namespace sfntly { -const int32_t SFNTVERSION_1 = Fixed1616::fixed(1, 0); +const int32_t SFNTVERSION_1 = Fixed1616::Fixed(1, 0); /****************************************************************************** * Font class ******************************************************************************/ Font::~Font() {} -Font::Font(FontFactory* factory, int32_t sfnt_version, ByteVector* digest, - TableMap* tables) - : factory_(factory), sfnt_version_(sfnt_version) { - // non-trivial assignments that makes debugging hard if placed in - // initialization list - digest_ = *digest; - tables_ = *tables; -} - -int32_t Font::version() { - return sfnt_version_; -} - -ByteVector* Font::digest() { - return &digest_; -} - -int64_t Font::checksum() { - return checksum_; -} - -int32_t Font::numTables() { - return (int32_t)tables_.size(); -} - -bool Font::hasTable(int32_t tag) { +bool Font::HasTable(int32_t tag) { TableMap::const_iterator result = tables_.find(tag); TableMap::const_iterator end = tables_.end(); return (result != end); } -Table* Font::table(int32_t tag) { - if (!hasTable(tag)) { +Table* Font::GetTable(int32_t tag) { + if (!HasTable(tag)) { return NULL; } return tables_[tag]; } -TableMap* Font::tables() { +TableMap* Font::Tables() { return &tables_; } -void Font::serialize(OutputStream* os, IntegerList* table_ordering) { +void Font::Serialize(OutputStream* os, IntegerList* table_ordering) { assert(table_ordering); IntegerList final_table_ordering; - tableOrdering(table_ordering, &final_table_ordering); + TableOrdering(table_ordering, &final_table_ordering); TableHeaderList table_records; - buildTableHeadersForSerialization(&final_table_ordering, &table_records); + BuildTableHeadersForSerialization(&final_table_ordering, &table_records); FontOutputStream fos(os); - serializeHeader(&fos, &table_records); - serializeTables(&fos, &table_records); + SerializeHeader(&fos, &table_records); + SerializeTables(&fos, &table_records); +} + +CALLER_ATTACH WritableFontData* Font::GetNewData(int32_t size) { + return factory_->GetNewData(size); +} + +Font::Font(FontFactory* factory, int32_t sfnt_version, ByteVector* digest, + TableMap* tables) + : factory_(factory), + sfnt_version_(sfnt_version) { + // non-trivial assignments that makes debugging hard if placed in + // initialization list + digest_ = *digest; + tables_ = *tables; } -void Font::buildTableHeadersForSerialization(IntegerList* table_ordering, +void Font::BuildTableHeadersForSerialization(IntegerList* table_ordering, TableHeaderList* table_headers) { assert(table_headers); assert(table_ordering); IntegerList final_table_ordering; - tableOrdering(table_ordering, &final_table_ordering); - int32_t table_offset = Offset::kTableRecordBegin + numTables() * + TableOrdering(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(); @@ -110,42 +100,42 @@ void Font::buildTableHeadersForSerialization(IntegerList* table_ordering, TablePtr table = tables_[*tag]; if (table != NULL) { TableHeaderPtr header = - new Table::Header(*tag, table->calculatedChecksum(), table_offset, - table->length()); + new Table::Header(*tag, table->CalculatedChecksum(), table_offset, + table->Length()); table_headers->push_back(header); - table_offset += (table->length() + 3) & ~3; + table_offset += (table->Length() + 3) & ~3; } } } -void Font::serializeHeader(FontOutputStream* fos, +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()); + 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); + fos->WriteUShort(search_range); + fos->WriteUShort(log2_of_max_power_of_2); + fos->WriteUShort((table_headers->size() * 16) - search_range); for (TableHeaderList::iterator record = table_headers->begin(), record_end = table_headers->end(); record != record_end; ++record) { - fos->writeULong((*record)->tag()); - fos->writeULong((int32_t)((*record)->checksum())); - fos->writeULong((*record)->offset()); - fos->writeULong((*record)->length()); + fos->WriteULong((*record)->tag()); + fos->WriteULong((int32_t)((*record)->checksum())); + fos->WriteULong((*record)->offset()); + fos->WriteULong((*record)->length()); } } -void Font::serializeTables(FontOutputStream* fos, +void Font::SerializeTables(FontOutputStream* fos, TableHeaderList* table_headers) { ByteVector SERIALIZATION_FILLER(3); std::fill(SERIALIZATION_FILLER.begin(), SERIALIZATION_FILLER.end(), 0); for (TableHeaderList::iterator record = table_headers->begin(), end_of_headers = table_headers->end(); record != end_of_headers; ++record) { - TablePtr target_table = table((*record)->tag()); + TablePtr target_table = GetTable((*record)->tag()); if (target_table == NULL) { #if defined (SFNTLY_NO_EXCEPTION) return; @@ -153,22 +143,22 @@ void Font::serializeTables(FontOutputStream* fos, throw IOException("Table out of sync with font header."); #endif } - int32_t table_size = target_table->serialize(fos); + 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; - fos->write(&SERIALIZATION_FILLER, 0, filler_size); + fos->Write(&SERIALIZATION_FILLER, 0, filler_size); } } -void Font::tableOrdering(IntegerList* default_table_ordering, +void Font::TableOrdering(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); + DefaultTableOrdering(default_table_ordering); } typedef std::map Int2Bool; @@ -181,7 +171,7 @@ void Font::tableOrdering(IntegerList* default_table_ordering, for (IntegerList::iterator tag = default_table_ordering->begin(), tag_end = default_table_ordering->end(); tag != tag_end; ++tag) { - if (hasTable(*tag)) { + if (HasTable(*tag)) { table_ordering->push_back(*tag); tables_in_font[*tag] = true; } @@ -194,10 +184,10 @@ void Font::tableOrdering(IntegerList* default_table_ordering, } } -void Font::defaultTableOrdering(IntegerList* default_table_ordering) { +void Font::DefaultTableOrdering(IntegerList* default_table_ordering) { assert(default_table_ordering); default_table_ordering->clear(); - if (hasTable(Tag::CFF)) { + 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()); @@ -209,62 +199,32 @@ void Font::defaultTableOrdering(IntegerList* default_table_ordering) { default_table_ordering->begin()); } -CALLER_ATTACH WritableFontData* Font::getNewData(int32_t size) { - return factory_->getNewData(size); -} - /****************************************************************************** * Font::Builder class ******************************************************************************/ Font::Builder::~Builder() {} -Font::Builder::Builder(FontFactory* factory) - : factory_(factory), sfnt_version_(SFNTVERSION_1) { -} - -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); - TableHeaderSortedSet records; - readHeader(&font_is, &records); - loadTableData(&records, &font_is, &data_blocks_); - buildAllTableBuilders(&data_blocks_, &table_builders_); - font_is.close(); -} - -void Font::Builder::loadFont(ByteArray* ba, - int32_t offset_to_offset_table) { - // Note: we do not throw exception here for is. This is more of an assertion. - assert(ba); - WritableFontDataPtr fd = new WritableFontData(ba); - TableHeaderSortedSet records; - readHeader(fd, offset_to_offset_table, &records); - loadTableData(&records, fd, &data_blocks_); - buildAllTableBuilders(&data_blocks_, &table_builders_); -} - -CALLER_ATTACH Font::Builder* Font::Builder::getOTFBuilder( +CALLER_ATTACH Font::Builder* Font::Builder::GetOTFBuilder( FontFactory* factory, InputStream* is) { FontBuilderPtr builder = new Builder(factory); - builder->loadFont(is); - return builder.detach(); + builder->LoadFont(is); + return builder.Detach(); } -CALLER_ATTACH Font::Builder* Font::Builder::getOTFBuilder( +CALLER_ATTACH Font::Builder* Font::Builder::GetOTFBuilder( FontFactory* factory, ByteArray* ba, int32_t offset_to_offset_table) { FontBuilderPtr builder = new Builder(factory); - builder->loadFont(ba, offset_to_offset_table); - return builder.detach(); + builder->LoadFont(ba, offset_to_offset_table); + return builder.Detach(); } -CALLER_ATTACH Font::Builder* Font::Builder::getOTFBuilder( +CALLER_ATTACH Font::Builder* Font::Builder::GetOTFBuilder( FontFactory* factory) { FontBuilderPtr builder = new Builder(factory); - return builder.detach(); + return builder.Detach(); } -bool Font::Builder::readyToBuild() { +bool Font::Builder::ReadyToBuild() { // just read in data with no manipulation if (table_builders_.empty() && !data_blocks_.empty()) { return true; @@ -275,73 +235,69 @@ bool Font::Builder::readyToBuild() { table_builder_end = table_builders_.end(); table_builder != table_builder_end; ++table_builder) { - if (!table_builder->second->readyToBuild()) + if (!table_builder->second->ReadyToBuild()) return false; } return true; } -CALLER_ATTACH Font* Font::Builder::build() { +CALLER_ATTACH Font* Font::Builder::Build() { TableMap tables; if (!table_builders_.empty()) { - buildTablesFromBuilders(&table_builders_, &tables); + BuildTablesFromBuilders(&table_builders_, &tables); } FontPtr font = new Font(factory_, sfnt_version_, &digest_, &tables); table_builders_.clear(); data_blocks_.clear(); - return font.detach(); + return font.Detach(); } -CALLER_ATTACH WritableFontData* Font::Builder::getNewData(int32_t capacity) { - return factory_->getNewData(capacity); +CALLER_ATTACH WritableFontData* Font::Builder::GetNewData(int32_t capacity) { + return factory_->GetNewData(capacity); } -CALLER_ATTACH WritableFontData* Font::Builder::getNewGrowableData( +CALLER_ATTACH WritableFontData* Font::Builder::GetNewGrowableData( ReadableFontData* src_data) { - return factory_->getNewGrowableData(src_data); + return factory_->GetNewGrowableData(src_data); } -void Font::Builder::setDigest(ByteVector* digest) { +void Font::Builder::SetDigest(ByteVector* digest) { digest_.clear(); digest_ = *digest; } -void Font::Builder::cleanTableBuilders() { +void Font::Builder::CleanTableBuilders() { table_builders_.clear(); } -bool Font::Builder::hasTableBuilder(int32_t tag) { +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)) +Table::Builder* Font::Builder::GetTableBuilder(int32_t tag) { + if (HasTableBuilder(tag)) return table_builders_[tag]; return NULL; } -CALLER_ATTACH Table::Builder* Font::Builder::newTableBuilder(int32_t tag) { +CALLER_ATTACH Table::Builder* Font::Builder::NewTableBuilder(int32_t tag) { TableHeaderPtr header = new Table::Header(tag); - TableBuilderPtr builder = Table::Builder::getBuilder(this, header, NULL); + TableBuilderPtr builder = Table::Builder::GetBuilder(this, header, NULL); table_builders_.insert(TableBuilderEntry(header->tag(), builder)); return builder; } -CALLER_ATTACH Table::Builder* Font::Builder::newTableBuilder( - int32_t tag, ReadableFontData* src_data) { +CALLER_ATTACH Table::Builder* + Font::Builder::NewTableBuilder(int32_t tag, ReadableFontData* src_data) { WritableFontDataPtr data; - data.attach(getNewGrowableData(src_data)); + data.Attach(GetNewGrowableData(src_data)); TableHeaderPtr header = new Table::Header(tag); - TableBuilderPtr builder = Table::Builder::getBuilder(this, header, data); + TableBuilderPtr builder = Table::Builder::GetBuilder(this, header, data); table_builders_.insert(TableBuilderEntry(tag, builder)); return builder; } -TableBuilderMap* Font::Builder::tableBuilders() { - return &table_builders_; -} - -void Font::Builder::tableBuilderTags(IntegerSet* key_set) { +void Font::Builder::TableBuilderTags(IntegerSet* key_set) { assert(key_set); key_set->clear(); for (TableBuilderMap::iterator i = table_builders_.begin(), @@ -350,53 +306,76 @@ void Font::Builder::tableBuilderTags(IntegerSet* key_set) { } } -void Font::Builder::removeTableBuilder(int32_t tag) { +void Font::Builder::RemoveTableBuilder(int32_t tag) { TableBuilderMap::iterator target = table_builders_.find(tag); if (target != table_builders_.end()) { table_builders_.erase(target); } } -int32_t Font::Builder::numberOfTableBuilders() { - return (int32_t)table_builders_.size(); +Font::Builder::Builder(FontFactory* factory) + : factory_(factory), sfnt_version_(SFNTVERSION_1) { +} + +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); + TableHeaderSortedSet records; + ReadHeader(&font_is, &records); + LoadTableData(&records, &font_is, &data_blocks_); + BuildAllTableBuilders(&data_blocks_, &table_builders_); + font_is.Close(); +} + +void Font::Builder::LoadFont(ByteArray* ba, + int32_t offset_to_offset_table) { + // Note: we do not throw exception here for is. This is more of an assertion. + assert(ba); + WritableFontDataPtr fd = new WritableFontData(ba); + TableHeaderSortedSet records; + ReadHeader(fd, offset_to_offset_table, &records); + LoadTableData(&records, fd, &data_blocks_); + BuildAllTableBuilders(&data_blocks_, &table_builders_); } -int32_t Font::Builder::sfntWrapperSize() { +int32_t Font::Builder::SfntWrapperSize() { return Offset::kSfntHeaderSize + (Offset::kTableRecordSize * table_builders_.size()); } -void Font::Builder::buildAllTableBuilders(DataBlockMap* table_data, +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.Attach(GetTableBuilder(record->first.p_, record->second.p_)); builder_map->insert(TableBuilderEntry(record->first->tag(), builder)); } - interRelateBuilders(&table_builders_); + InterRelateBuilders(&table_builders_); } -CALLER_ATTACH Table::Builder* Font::Builder::getTableBuilder( - Table::Header* header, WritableFontData* data) { - return Table::Builder::getBuilder(this, header, data); +CALLER_ATTACH Table::Builder* + Font::Builder::GetTableBuilder(Table::Header* header, + WritableFontData* data) { + return Table::Builder::GetBuilder(this, header, data); } -void Font::Builder::buildTablesFromBuilders(TableBuilderMap* builder_map, +void Font::Builder::BuildTablesFromBuilders(TableBuilderMap* builder_map, TableMap* table_map) { - interRelateBuilders(builder_map); + 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->readyToBuild()) { + if (builder->second->ReadyToBuild()) { #if !defined (SFNTLY_NO_EXCEPTION) try { #endif - table.attach(down_cast(builder->second->build())); + table.Attach(down_cast(builder->second->Build())); #if !defined (SFNTLY_NO_EXCEPTION) } catch(IOException& e) { std::string builder_string = "Unable to build table - "; @@ -419,7 +398,7 @@ void Font::Builder::buildTablesFromBuilders(TableBuilderMap* builder_map, } } -void Font::Builder::interRelateBuilders(TableBuilderMap* builder_map) { +void Font::Builder::InterRelateBuilders(TableBuilderMap* builder_map) { FontHeaderTableBuilderPtr header_table_builder = down_cast((*builder_map)[Tag::head].p_); HorizontalHeaderTableBuilderPtr horizontal_header_builder = @@ -435,87 +414,89 @@ void Font::Builder::interRelateBuilders(TableBuilderMap* builder_map) { // set the inter table data required to build certain tables if (horizontal_metrics_builder != NULL) { if (max_profile_builder != NULL) { - horizontal_metrics_builder->setNumGlyphs( - max_profile_builder->numGlyphs()); + horizontal_metrics_builder->SetNumGlyphs( + max_profile_builder->NumGlyphs()); } if (horizontal_header_builder != NULL) { - horizontal_metrics_builder->setNumberOfHMetrics( - horizontal_header_builder->numberOfHMetrics()); + 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()); + loca_table_builder->SetNumGlyphs(max_profile_builder->NumGlyphs()); } if (header_table_builder != NULL) { - loca_table_builder->setFormatVersion( - header_table_builder->indexToLocFormat()); + loca_table_builder->SetFormatVersion( + header_table_builder->IndexToLocFormat()); } } } -void Font::Builder::readHeader(FontInputStream* is, +void Font::Builder::ReadHeader(FontInputStream* is, TableHeaderSortedSet* records) { assert(records); - sfnt_version_ = is->readFixed(); - num_tables_ = is->readUShort(); - search_range_ = is->readUShort(); - entry_selector_ = is->readUShort(); - range_shift_ = is->readUShort(); + 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(); + int32_t tag = is->ReadULongAsInt(); + int64_t checksum = is->ReadULong(); + int32_t offset = is->ReadULongAsInt(); + int32_t length = is->ReadULongAsInt(); TableHeaderPtr table = new Table::Header(tag, checksum, offset, length); records->insert(table); } } -void Font::Builder::loadTableData(TableHeaderSortedSet* headers, +void Font::Builder::ReadHeader(ReadableFontData* fd, + int32_t offset, + TableHeaderSortedSet* 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); + TableHeaderPtr table = new Table::Header(tag, checksum, offset, length); + records->insert(table); + } +} + +void Font::Builder::LoadTableData(TableHeaderSortedSet* headers, FontInputStream* is, DataBlockMap* table_data) { assert(table_data); for (TableHeaderSortedSet::iterator table_header = headers->begin(), table_end = headers->end(); table_header != table_end; ++table_header) { - is->skip((*table_header)->offset() - is->position()); + is->Skip((*table_header)->offset() - is->position()); FontInputStream table_is(is, (*table_header)->length()); int32_t roundup_length = ((*table_header)->length() + 3) & ~3; - ByteArrayPtr array = factory_->getNewArray(roundup_length); - array->copyFrom(&table_is, (*table_header)->length()); + ByteArrayPtr array; + array.Attach(factory_->GetNewArray(roundup_length)); + array->CopyFrom(&table_is, (*table_header)->length()); WritableFontDataPtr data = new WritableFontData(array); table_data->insert(DataBlockEntry(*table_header, data)); } } -void Font::Builder::readHeader(ReadableFontData* fd, int32_t offset, - TableHeaderSortedSet* 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); - TableHeaderPtr table = new Table::Header(tag, checksum, offset, length); - records->insert(table); - } -} - -void Font::Builder::loadTableData(TableHeaderSortedSet* headers, +void Font::Builder::LoadTableData(TableHeaderSortedSet* headers, WritableFontData* fd, DataBlockMap* table_data) { for (TableHeaderSortedSet::iterator @@ -523,7 +504,7 @@ void Font::Builder::loadTableData(TableHeaderSortedSet* headers, table_header != table_end; ++table_header) { int32_t roundup_length = ((*table_header)->length() + 3) & ~3; FontDataPtr sliced_data; - sliced_data.attach(fd->slice((*table_header)->offset(), roundup_length)); + sliced_data.Attach(fd->Slice((*table_header)->offset(), roundup_length)); WritableFontDataPtr data = down_cast(sliced_data.p_); table_data->insert(DataBlockEntry(*table_header, data)); } diff --git a/sfntly/font.h b/sfntly/font.h index cbd9607..5ce7f17 100644 --- a/sfntly/font.h +++ b/sfntly/font.h @@ -122,143 +122,68 @@ extern const int32_t SFNTVERSION_1; class FontFactory; class Font : public RefCounted { - 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[]; - - public: - virtual ~Font(); - - private: - Font(FontFactory* factory, int32_t sfnt_version, ByteVector* digest, - TableMap* tables); - - public: - // Gets the sfnt version set in the sfnt wrapper of the font. - virtual int32_t 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. - virtual ByteVector* digest(); - - // Get the checksum for this font. - virtual int64_t checksum(); - - // Get the number of tables in this font. - virtual int32_t numTables(); - - // Whether the font has a particular table. - virtual 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 - virtual Table* table(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 - virtual TableMap* tables(); - - // Serialize the font to the output stream. - // @param os the destination for the font serialization - // @param tableOrdering the table ordering to apply - virtual void serialize(OutputStream* os, IntegerList* table_ordering); - - private: - void buildTableHeadersForSerialization(IntegerList* table_ordering, - TableHeaderList* table_headers); - void serializeHeader(FontOutputStream* fos, TableHeaderList* table_headers); - void serializeTables(FontOutputStream* fos, TableHeaderList* table_headers); - void tableOrdering(IntegerList* default_table_ordering, - IntegerList* table_ordering); - void defaultTableOrdering(IntegerList* default_table_ordering); - public: class Builder : public FontDataTableBuilderContainer, public RefCounted { public: virtual ~Builder(); - private: - explicit Builder(FontFactory* factory); - virtual void loadFont(InputStream* is); - virtual void loadFont(ByteArray* buffer, int32_t offset_to_offset_table); - - public: static CALLER_ATTACH Builder* - getOTFBuilder(FontFactory* factory, InputStream* is); + GetOTFBuilder(FontFactory* factory, InputStream* is); static CALLER_ATTACH Builder* - getOTFBuilder(FontFactory* factory, ByteArray* ba, + GetOTFBuilder(FontFactory* factory, + ByteArray* ba, int32_t offset_to_offset_table); - static CALLER_ATTACH Builder* getOTFBuilder(FontFactory* factory); - virtual bool readyToBuild(); - virtual CALLER_ATTACH Font* build(); - virtual CALLER_ATTACH WritableFontData* getNewData(int32_t capacity); + static CALLER_ATTACH Builder* GetOTFBuilder(FontFactory* factory); + virtual bool ReadyToBuild(); + virtual CALLER_ATTACH Font* Build(); + virtual CALLER_ATTACH WritableFontData* GetNewData(int32_t capacity); virtual CALLER_ATTACH WritableFontData* - getNewGrowableData(ReadableFontData* data); - virtual void setDigest(ByteVector* digest); - virtual void cleanTableBuilders(); - virtual bool hasTableBuilder(int32_t tag); - virtual Table::Builder* getTableBuilder(int32_t tag); + GetNewGrowableData(ReadableFontData* data); + virtual void SetDigest(ByteVector* digest); + virtual void CleanTableBuilders(); + virtual bool HasTableBuilder(int32_t tag); + virtual 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 CALLER_ATTACH Table::Builder* newTableBuilder(int32_t tag); + virtual CALLER_ATTACH Table::Builder* NewTableBuilder(int32_t tag); virtual CALLER_ATTACH Table::Builder* - newTableBuilder(int32_t tag, ReadableFontData* src_data); - virtual TableBuilderMap* tableBuilders(); - virtual void tableBuilderTags(IntegerSet* key_set); + NewTableBuilder(int32_t tag, ReadableFontData* src_data); + virtual TableBuilderMap* table_builders() { return &table_builders_; } + virtual void TableBuilderTags(IntegerSet* key_set); // Note: different from Java: we don't return object in removeTableBuilder - virtual void removeTableBuilder(int32_t tag); - virtual int32_t numberOfTableBuilders(); + virtual void RemoveTableBuilder(int32_t tag); + virtual int32_t number_of_table_builders() { + return (int32_t)table_builders_.size(); + } private: - int32_t sfntWrapperSize(); - void buildAllTableBuilders(DataBlockMap* table_data, + explicit Builder(FontFactory* factory); + virtual void LoadFont(InputStream* is); + virtual void LoadFont(ByteArray* buffer, int32_t offset_to_offset_table); + int32_t SfntWrapperSize(); + void BuildAllTableBuilders(DataBlockMap* table_data, TableBuilderMap* builder_map); CALLER_ATTACH Table::Builder* - getTableBuilder(Table::Header* header, WritableFontData* data); - void buildTablesFromBuilders(TableBuilderMap* builder_map, + GetTableBuilder(Table::Header* header, WritableFontData* data); + void BuildTablesFromBuilders(TableBuilderMap* builder_map, TableMap* tables); - static void interRelateBuilders(TableBuilderMap* builder_map); - void readHeader(FontInputStream* is, TableHeaderSortedSet* records); - void loadTableData(TableHeaderSortedSet* headers, FontInputStream* is, - DataBlockMap* table_data); - void readHeader(ReadableFontData* fd, int32_t offset, + static void InterRelateBuilders(TableBuilderMap* builder_map); + void ReadHeader(FontInputStream* is, TableHeaderSortedSet* records); + void ReadHeader(ReadableFontData* fd, + int32_t offset, TableHeaderSortedSet* records); - void loadTableData(TableHeaderSortedSet* headers, WritableFontData* fd, + void LoadTableData(TableHeaderSortedSet* headers, + FontInputStream* is, + DataBlockMap* table_data); + void LoadTableData(TableHeaderSortedSet* headers, + WritableFontData* fd, DataBlockMap* table_data); - private: TableBuilderMap table_builders_; FontFactory* factory_; // dumb pointer, avoid circular refcounting int32_t sfnt_version_; @@ -270,7 +195,41 @@ class Font : public RefCounted { ByteVector digest_; }; - public: + virtual ~Font(); + + // Gets the sfnt version set in the sfnt wrapper of the font. + int32_t 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 + TableMap* Tables(); + + // 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); + // Get a new data object. The size is a request for a data object and the // returned data object will support at least that amount. A value greater // than zero for the size is a request for a fixed size data object. A @@ -280,9 +239,47 @@ class Font : public RefCounted { // @param size greater than zero is a request for a fixed size data object of // the given size; less than or equal to zero is a request for a // variable size data object with the absolute size as an estimate - CALLER_ATTACH WritableFontData* getNewData(int32_t size); + CALLER_ATTACH WritableFontData* GetNewData(int32_t size); 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[]; + + Font(FontFactory* factory, int32_t sfnt_version, ByteVector* digest, + TableMap* tables); + + void BuildTableHeadersForSerialization(IntegerList* table_ordering, + TableHeaderList* table_headers); + void SerializeHeader(FontOutputStream* fos, TableHeaderList* table_headers); + void SerializeTables(FontOutputStream* fos, TableHeaderList* table_headers); + void TableOrdering(IntegerList* default_table_ordering, + IntegerList* table_ordering); + void DefaultTableOrdering(IntegerList* default_table_ordering); + FontFactory* factory_; // dumb pointer, avoid circular ref-counting int32_t sfnt_version_; ByteVector digest_; diff --git a/sfntly/font_data_table.cc b/sfntly/font_data_table.cc index 9896b24..1f9d1cc 100644 --- a/sfntly/font_data_table.cc +++ b/sfntly/font_data_table.cc @@ -15,6 +15,7 @@ */ #include "sfntly/font_data_table.h" + #include "sfntly/data/font_output_stream.h" namespace sfntly { @@ -29,158 +30,142 @@ FontDataTable::FontDataTable(ReadableFontData* data) { FontDataTable::~FontDataTable() {} -ReadableFontData* FontDataTable::readFontData() { +ReadableFontData* FontDataTable::ReadFontData() { return data_; } -int32_t FontDataTable::length() { - return data_->length(); +int32_t FontDataTable::Length() { + return data_->Length(); } -int32_t FontDataTable::padding() { +int32_t FontDataTable::Padding() { return -1; } -int32_t FontDataTable::dataLength() { - int32_t paddings = padding(); - return (paddings == -1) ? length() : length() - paddings; +int32_t FontDataTable::DataLength() { + int32_t paddings = Padding(); + return (paddings == -1) ? Length() : Length() - paddings; } -int32_t FontDataTable::serialize(OutputStream* os) { - return data_->copyTo(os); +int32_t FontDataTable::Serialize(OutputStream* os) { + return data_->CopyTo(os); } /****************************************************************************** * FontDataTable::Builder class ******************************************************************************/ -void FontDataTable::Builder::init(FontDataTableBuilderContainer* container) { - container_ = container; - model_changed_ = false; - data_changed_ = false; -} - -FontDataTable::Builder::Builder(FontDataTableBuilderContainer* container) { - init(container); -} - -FontDataTable::Builder::Builder(FontDataTableBuilderContainer* container, - WritableFontData* data) { - init(container); - w_data_ = data; -} - -FontDataTable::Builder::Builder(FontDataTableBuilderContainer* container, - ReadableFontData* data) { - init(container); - r_data_ = data; -} - -FontDataTable::Builder::~Builder() { -} - -WritableFontData* FontDataTable::Builder::data() { +CALLER_ATTACH WritableFontData* FontDataTable::Builder::Data() { WritableFontDataPtr new_data; if (model_changed_) { - if (!subReadyToSerialize()) { + if (!SubReadyToSerialize()) { return NULL; } - int32_t size = subDataSizeToSerialize(); - new_data.attach(container_->getNewData(size)); - subSerialize(new_data); + int32_t size = SubDataSizeToSerialize(); + new_data.Attach(container_->GetNewData(size)); + SubSerialize(new_data); } else { - ReadableFontDataPtr data = internalReadData(); - new_data.attach(container_->getNewData(data != NULL ? data->length() : 0)); - data->copyTo(new_data); + ReadableFontDataPtr data = InternalReadData(); + new_data.Attach(container_->GetNewData(data != NULL ? data->Length() : 0)); + data->CopyTo(new_data); } - return new_data.detach(); -} - -void FontDataTable::Builder::setData(ReadableFontData* data) { - internalSetData(data, true); + return new_data.Detach(); } -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::SetData(ReadableFontData* data) { + InternalSetData(data, true); } -void FontDataTable::Builder::internalSetData(ReadableFontData* data, - bool data_changed) { - w_data_ = NULL; - r_data_ = data; - if (data_changed) { - data_changed_ = true; - subDataSet(); - } -} -CALLER_ATTACH FontDataTable* FontDataTable::Builder::build() { - ReadableFontDataPtr data = internalReadData(); +CALLER_ATTACH FontDataTable* FontDataTable::Builder::Build() { + ReadableFontDataPtr data = InternalReadData(); if (model_changed_) { // Let subclass serialize from model. - if (!subReadyToSerialize()) { + if (!SubReadyToSerialize()) { return NULL; } - int32_t size = subDataSizeToSerialize(); + int32_t size = SubDataSizeToSerialize(); WritableFontDataPtr new_data; - new_data.attach(container_->getNewData(size)); - subSerialize(new_data); + new_data.Attach(container_->GetNewData(size)); + SubSerialize(new_data); data = new_data; } - FontDataTablePtr table = subBuildTable(data); - notifyPostTableBuild(table); + FontDataTablePtr table = SubBuildTable(data); + NotifyPostTableBuild(table); return table; } -bool FontDataTable::Builder::readyToBuild() { +bool FontDataTable::Builder::ReadyToBuild() { return true; } -ReadableFontData* FontDataTable::Builder::internalReadData() { +ReadableFontData* FontDataTable::Builder::InternalReadData() { return (r_data_ != NULL) ? r_data_.p_ : static_cast(w_data_.p_); } -WritableFontData* FontDataTable::Builder::internalWriteData() { +WritableFontData* FontDataTable::Builder::InternalWriteData() { if (w_data_ == NULL) { WritableFontDataPtr new_data; - new_data.attach(container_->getNewData(r_data_->length())); - r_data_->copyTo(new_data); - internalSetData(new_data, false); + new_data.Attach(container_->GetNewData(r_data_->Length())); + r_data_->CopyTo(new_data); + InternalSetData(new_data, false); } return w_data_.p_; } -WritableFontData* FontDataTable::Builder::internalNewData(int32_t size) { - return container_->getNewData(size); +CALLER_ATTACH WritableFontData* + FontDataTable::Builder::InternalNewData(int32_t size) { + return container_->GetNewData(size); } -bool FontDataTable::Builder::dataChanged() { - return data_changed_; +FontDataTable::Builder::Builder(FontDataTableBuilderContainer* container) { + Init(container); } -bool FontDataTable::Builder::modelChanged() { - return model_changed_; +FontDataTable::Builder::Builder(FontDataTableBuilderContainer* container, + WritableFontData* data) { + Init(container); + w_data_ = data; } -bool FontDataTable::Builder::setModelChanged() { - return setModelChanged(true); +FontDataTable::Builder::Builder(FontDataTableBuilderContainer* container, + ReadableFontData* data) { + Init(container); + r_data_ = data; +} + +FontDataTable::Builder::~Builder() { } -bool FontDataTable::Builder::setModelChanged(bool changed) { - bool old = model_changed_; - model_changed_ = changed; - return old; +void FontDataTable::Builder::Init(FontDataTableBuilderContainer* container) { + container_ = container; + model_changed_ = false; + data_changed_ = false; } -void FontDataTable::Builder::notifyPostTableBuild(FontDataTable* table) { - // default: NOP +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/sfntly/font_data_table.h b/sfntly/font_data_table.h index 28bec15..9b3b467 100644 --- a/sfntly/font_data_table.h +++ b/sfntly/font_data_table.h @@ -24,76 +24,59 @@ namespace sfntly { class FontDataTable : virtual public RefCount { - public: - 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 and may or may not include any padding. - virtual int32_t length(); - - // Get the number of bytes of padding used in the table. The padding bytes are - // used to align the table length to a 4 byte boundary. - virtual int32_t padding(); - - // Return the number of bytes of non-padded data in the table. If the padding - // is unknown or unknowable then the total number of bytes of data in the - // tables is returned. - virtual int32_t dataLength(); - - virtual int32_t serialize(OutputStream* os); - public: // Note: original version is abstract Builder // C++ template is not designed that way so plain class is chosen. class Builder : virtual public RefCount { - protected: - explicit Builder(FontDataTableBuilderContainer* container); - Builder(FontDataTableBuilderContainer* container, WritableFontData* data); - Builder(FontDataTableBuilderContainer* container, ReadableFontData* data); - virtual ~Builder(); - - void init(FontDataTableBuilderContainer* container); - 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)}. + // call must be made to {@link #SetData(WritableFontData)}. // @return a copy of the internal data of the builder - WritableFontData* data(); - virtual void setData(ReadableFontData* data); + 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(); + CALLER_ATTACH WritableFontData* InternalNewData(int32_t size); + + bool data_changed() { return data_changed_; } + bool modelChanged() { return 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; + } - private: - void internalSetData(WritableFontData* data, bool data_changed); - void internalSetData(ReadableFontData* data, bool data_changed); - - public: // Note: changed from protected to avoid accessibility error in C++ - virtual FontDataTable* build(); - virtual bool readyToBuild(); - virtual ReadableFontData* internalReadData(); - virtual WritableFontData* internalWriteData(); - virtual WritableFontData* internalNewData(int32_t size); - virtual bool dataChanged(); - virtual bool modelChanged(); - virtual bool setModelChanged(); - virtual bool setModelChanged(bool changed); - - protected: // 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; + protected: + explicit Builder(FontDataTableBuilderContainer* container); + Builder(FontDataTableBuilderContainer* container, WritableFontData* data); + Builder(FontDataTableBuilderContainer* container, ReadableFontData* data); + virtual ~Builder(); + + void Init(FontDataTableBuilderContainer* container); + + // 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; + SubBuildTable(ReadableFontData* data) = 0; private: + void InternalSetData(WritableFontData* data, bool data_changed); + void InternalSetData(ReadableFontData* data, bool data_changed); + FontDataTableBuilderContainer* container_; // avoid circular ref-counting WritableFontDataPtr w_data_; ReadableFontDataPtr r_data_; @@ -101,7 +84,29 @@ class FontDataTable : virtual public RefCount { 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 and may or may not include any padding. + virtual int32_t Length(); + + // Get the number of bytes of padding used in the table. The padding bytes are + // used to align the table length to a 4 byte boundary. + virtual int32_t Padding(); + + // Return the number of bytes of non-padded data in the table. If the padding + // is unknown or unknowable then the total number of bytes of data in the + // tables is returned. + virtual int32_t DataLength(); + + virtual int32_t Serialize(OutputStream* os); + protected: + // TODO(arthurhsu): style guide violation: protected member, need refactoring ReadableFontDataPtr data_; }; typedef Ptr FontDataTablePtr; diff --git a/sfntly/font_data_table_builder_container.h b/sfntly/font_data_table_builder_container.h index 7866a36..f3ccf61 100644 --- a/sfntly/font_data_table_builder_container.h +++ b/sfntly/font_data_table_builder_container.h @@ -23,7 +23,7 @@ namespace sfntly { class FontDataTableBuilderContainer { public: - virtual WritableFontData* getNewData(int32_t size) = 0; + virtual WritableFontData* GetNewData(int32_t size) = 0; // Make gcc -Wnon-virtual-dtor happy. virtual ~FontDataTableBuilderContainer() {} }; diff --git a/sfntly/font_factory.cc b/sfntly/font_factory.cc index b741f0a..d5b2397 100644 --- a/sfntly/font_factory.cc +++ b/sfntly/font_factory.cc @@ -14,229 +14,233 @@ * limitations under the License. */ +#include "sfntly/font_factory.h" + #include -#include "sfntly/font_factory.h" #include "sfntly/tag.h" #include "sfntly/data/memory_byte_array.h" #include "sfntly/data/growable_memory_byte_array.h" namespace sfntly { -FontFactory::FontFactory() : fingerprint_(false) { -} - FontFactory::~FontFactory() { } -CALLER_ATTACH FontFactory* FontFactory::getInstance() { +CALLER_ATTACH FontFactory* FontFactory::GetInstance() { FontFactoryPtr instance = new FontFactory(); - return instance.detach(); + return instance.Detach(); } -void FontFactory::fingerprintFont(bool fingerprint) { +void FontFactory::FingerprintFont(bool fingerprint) { fingerprint_ = fingerprint; } -bool FontFactory::fingerprintFont() { +bool FontFactory::FingerprintFont() { return fingerprint_; } -void FontFactory::loadFonts(InputStream* is, FontArray* output) { +void FontFactory::LoadFonts(InputStream* is, FontArray* output) { assert(output); PushbackInputStream* pbis = down_cast(is); - if (isCollection(pbis)) { - loadCollection(pbis, output); + if (IsCollection(pbis)) { + LoadCollection(pbis, output); + return; + } + FontPtr font = LoadSingleOTF(pbis); + if (font) { + output->push_back(font); + } +} + +void FontFactory::LoadFonts(ByteArray* ba, FontArray* output) { + if (IsCollection(ba)) { + LoadCollection(ba, output); return; } - FontPtr font = loadSingleOTF(pbis); + FontPtr font; + font.Attach(LoadSingleOTF(ba)); if (font) { output->push_back(font); } } -void FontFactory::loadFontsForBuilding(InputStream* is, +void FontFactory::LoadFontsForBuilding(InputStream* is, FontBuilderArray* output) { PushbackInputStream* pbis = down_cast(is); - if (isCollection(pbis)) { - loadCollectionForBuilding(pbis, output); + if (IsCollection(pbis)) { + LoadCollectionForBuilding(pbis, output); return; } FontBuilderPtr builder; - builder.attach(loadSingleOTFForBuilding(pbis)); + builder.Attach(LoadSingleOTFForBuilding(pbis)); if (builder) { output->push_back(builder); } } -Font* FontFactory::loadSingleOTF(InputStream* is) { +void FontFactory::LoadFontsForBuilding(ByteArray* ba, + FontBuilderArray* output) { + if (IsCollection(ba)) { + LoadCollectionForBuilding(ba, output); + return; + } FontBuilderPtr builder; - builder.attach(loadSingleOTFForBuilding(is)); - return builder->build(); + builder.Attach(LoadSingleOTFForBuilding(ba, 0)); + if (builder) { + output->push_back(builder); + } } -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); - } +CALLER_ATTACH WritableFontData* FontFactory::GetNewData(int32_t capacity) { + // UNIMPLMENTED: if (capacity > 0) { this.GetNewFixedData(capacity); } + // Seems a no-op. + return GetNewGrowableData(capacity); } -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 WritableFontData* FontFactory::GetNewFixedData(int32_t capacity) { + ByteArrayPtr buffer; + buffer.Attach(GetNewArray(capacity)); + WritableFontDataPtr new_fixed_data = new WritableFontData(buffer); + return new_fixed_data.Detach(); } -void FontFactory::loadCollectionForBuilding(InputStream* is, - FontBuilderArray* builders) { - ByteArrayPtr ba = new GrowableMemoryByteArray(); - ba->copyFrom(is); - loadCollectionForBuilding(ba, builders); +CALLER_ATTACH WritableFontData* FontFactory::GetNewGrowableData( + int32_t capacity) { + ByteArrayPtr buffer; + buffer.Attach(GetNewGrowableArray(capacity)); + WritableFontDataPtr new_growable_data = new WritableFontData(buffer); + return new_growable_data.Detach(); } -bool FontFactory::isCollection(PushbackInputStream* pbis) { - ByteVector tag(4); - pbis->read(&tag); - pbis->unread(&tag); - return Tag::ttcf == generate_tag(tag[0], tag[1], tag[2], tag[3]); +CALLER_ATTACH WritableFontData* FontFactory::GetNewGrowableData( + ReadableFontData* src_data) { + WritableFontDataPtr data; + data.Attach(GetNewGrowableData(src_data->Length())); + src_data->CopyTo(data); + return data.Detach(); } -void FontFactory::loadFonts(ByteArray* ba, FontArray* output) { - if (isCollection(ba)) { - loadCollection(ba, output); - return; - } - FontPtr font; - font.attach(loadSingleOTF(ba)); - if (font) { - output->push_back(font); - } +CALLER_ATTACH ByteArray* FontFactory::GetNewArray(int32_t length) { + ByteArrayPtr new_fixed_array = new MemoryByteArray(length); + return new_fixed_array.Detach(); } -void FontFactory::loadFontsForBuilding(ByteArray* ba, - FontBuilderArray* output) { - if (isCollection(ba)) { - loadCollectionForBuilding(ba, output); - return; - } +CALLER_ATTACH ByteArray* FontFactory::GetNewGrowableArray(int32_t length) { + UNREFERENCED_PARAMETER(length); + ByteArrayPtr new_growable_array = new GrowableMemoryByteArray(); + return new_growable_array.Detach(); +} + +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(ba, 0)); - if (builder) { - output->push_back(builder); - } + builder.Attach(LoadSingleOTFForBuilding(is)); + return builder->Build(); } -Font* FontFactory::loadSingleOTF(ByteArray* ba) { +CALLER_ATTACH Font* FontFactory::LoadSingleOTF(ByteArray* ba) { FontBuilderPtr builder; - builder.attach(loadSingleOTFForBuilding(ba, 0)); - return builder->build(); + builder.Attach(LoadSingleOTFForBuilding(ba, 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(ByteArray* ba, FontArray* output) { +void FontFactory::LoadCollection(ByteArray* ba, FontArray* output) { FontBuilderArray builders; - loadCollectionForBuilding(ba, &builders); - output->reserve(ba->size()); + LoadCollectionForBuilding(ba, &builders); + output->reserve(ba->Size()); for (FontBuilderArray::iterator - builder = builders.begin(), builders_end = builders.end(); + builder = builders.begin(), builders_end = builders.end(); builder != builders_end; ++builder) { FontPtr font; - font.attach((*builder)->build()); + font.Attach((*builder)->Build()); output->push_back(font); } } -Font::Builder* FontFactory::loadSingleOTFForBuilding(ByteArray* ba, - int32_t offset_to_offset_table) { +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(ByteArray* ba, + int32_t offset_to_offset_table) { // UNIMPLEMENTED: SHA-1 hash checking via Java DigestStream Font::Builder* builder = - Font::Builder::getOTFBuilder(this, ba, offset_to_offset_table); + Font::Builder::GetOTFBuilder(this, ba, offset_to_offset_table); // UNIMPLEMENTED: setDigest return builder; } -void FontFactory::loadCollectionForBuilding(ByteArray* ba, +void FontFactory::LoadCollectionForBuilding(InputStream* is, + FontBuilderArray* builders) { + ByteArrayPtr ba = new GrowableMemoryByteArray(); + ba->CopyFrom(is); + LoadCollectionForBuilding(ba, builders); +} + +void FontFactory::LoadCollectionForBuilding(ByteArray* ba, FontBuilderArray* builders) { ReadableFontDataPtr rfd = new ReadableFontData(ba); - int32_t ttc_tag = rfd->readULongAsInt(Offset::kTTCTag); + int32_t ttc_tag = rfd->ReadULongAsInt(Offset::kTTCTag); UNREFERENCED_PARAMETER(ttc_tag); - int32_t version = rfd->readFixed(Offset::kVersion); + int32_t version = rfd->ReadFixed(Offset::kVersion); UNREFERENCED_PARAMETER(version); - int32_t num_fonts = rfd->readULongAsInt(Offset::kNumFonts); + int32_t num_fonts = rfd->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 = rfd->readULongAsInt(offset_table_offset); + int32_t offset = rfd->ReadULongAsInt(offset_table_offset); FontBuilderPtr builder; - builder.attach(loadSingleOTFForBuilding(ba, offset)); + builder.Attach(LoadSingleOTFForBuilding(ba, offset)); builders->push_back(builder); } } -bool FontFactory::isCollection(ByteArray* ba) { - return Tag::ttcf == - generate_tag(ba->get(0), ba->get(1), ba->get(2), ba->get(3)); -} - -CALLER_ATTACH WritableFontData* FontFactory::getNewData(int32_t capacity) { - // UNIMPLMENTED: if (capacity > 0) { this.getNewFixedData(capacity); } - // seems a no-op - return getNewGrowableData(capacity); -} - -CALLER_ATTACH WritableFontData* FontFactory::getNewFixedData(int32_t capacity) { - ByteArrayPtr buffer; - buffer.attach(getNewArray(capacity)); - WritableFontDataPtr new_fixed_data = new WritableFontData(buffer); - return new_fixed_data.detach(); -} - -CALLER_ATTACH WritableFontData* FontFactory::getNewGrowableData( - int32_t capacity) { - ByteArrayPtr buffer; - buffer.attach(getNewGrowableArray(capacity)); - WritableFontDataPtr new_growable_data = new WritableFontData(buffer); - return new_growable_data.detach(); -} - -CALLER_ATTACH WritableFontData* FontFactory::getNewGrowableData( - ReadableFontData* src_data) { - WritableFontDataPtr data; - data.attach(getNewGrowableData(src_data->length())); - src_data->copyTo(data); - return data.detach(); -} - -CALLER_ATTACH ByteArray* FontFactory::getNewArray(int32_t length) { - ByteArrayPtr new_fixed_array = new MemoryByteArray(length); - return new_fixed_array.detach(); -} - -CALLER_ATTACH ByteArray* FontFactory::getNewGrowableArray(int32_t length) { - UNREFERENCED_PARAMETER(length); - ByteArrayPtr new_growable_array = new GrowableMemoryByteArray(); - return new_growable_array.detach(); -} - -void FontFactory::serializeFont(Font* font, OutputStream* os) { - font->serialize(os, &table_ordering_); +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]); } -void FontFactory::setSerializationTableOrdering( - const IntegerList& table_ordering) { - table_ordering_ = table_ordering; +bool FontFactory::IsCollection(ByteArray* ba) { + return Tag::ttcf == + GenerateTag(ba->Get(0), ba->Get(1), ba->Get(2), ba->Get(3)); } -CALLER_ATTACH Font::Builder* FontFactory::newFontBuilder() { - return Font::Builder::getOTFBuilder(this); +FontFactory::FontFactory() + : fingerprint_(false) { } } // namespace sfntly diff --git a/sfntly/font_factory.h b/sfntly/font_factory.h index 907ea66..7be0841 100644 --- a/sfntly/font_factory.h +++ b/sfntly/font_factory.h @@ -26,33 +26,11 @@ namespace sfntly { class FontFactory : public RefCounted { - 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(); - - public: // class is final, no virtual functions unless from parent + public: virtual ~FontFactory(); // Factory method for the construction of a font factory. - static CALLER_ATTACH FontFactory* getInstance(); + 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 @@ -60,8 +38,8 @@ class FontFactory : public RefCounted { // 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(); + 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 @@ -69,24 +47,8 @@ class FontFactory : public RefCounted { // 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); - - // 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); - - private: - Font* loadSingleOTF(InputStream* is); - void loadCollection(InputStream* is, FontArray* output); - Font::Builder* loadSingleOTFForBuilding(InputStream* is); - void loadCollectionForBuilding(InputStream* is, FontBuilderArray* builders); - static bool isCollection(PushbackInputStream* pbis); + void LoadFonts(InputStream* is, FontArray* output); - public: // 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 @@ -94,51 +56,86 @@ class FontFactory : public RefCounted { // 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(ByteArray* ba, FontArray* output); + void LoadFonts(ByteArray* ba, FontArray* output); - // Load the font(s) from the byte array into font builders. The current + // 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(ByteArray* ba, FontBuilderArray* output); + void LoadFontsForBuilding(InputStream* is, FontBuilderArray* output); - private: - CALLER_ATTACH Font* loadSingleOTF(ByteArray* ba); - void loadCollection(ByteArray* ba, FontArray* output); - CALLER_ATTACH Font::Builder* - loadSingleOTFForBuilding(ByteArray* ba, int32_t offset_to_offset_table); - void loadCollectionForBuilding(ByteArray* ba, FontBuilderArray* builders); - static bool isCollection(ByteArray* ba); + // 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(ByteArray* ba, FontBuilderArray* output); - public: - CALLER_ATTACH WritableFontData* getNewData(int32_t capacity); - CALLER_ATTACH WritableFontData* getNewFixedData(int32_t capacity); - CALLER_ATTACH WritableFontData* getNewGrowableData(int32_t capacity); + CALLER_ATTACH WritableFontData* GetNewData(int32_t capacity); + CALLER_ATTACH WritableFontData* GetNewFixedData(int32_t capacity); + CALLER_ATTACH WritableFontData* GetNewGrowableData(int32_t capacity); CALLER_ATTACH WritableFontData* - getNewGrowableData(ReadableFontData* src_data); - CALLER_ATTACH ByteArray* getNewArray(int32_t length); - CALLER_ATTACH ByteArray* getNewGrowableArray(int32_t length); + GetNewGrowableData(ReadableFontData* src_data); + CALLER_ATTACH ByteArray* GetNewArray(int32_t length); + CALLER_ATTACH ByteArray* GetNewGrowableArray(int32_t length); - public: // 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); + 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); + void SetSerializationTableOrdering(const IntegerList& table_ordering); // Get an empty font builder for creating a new font from scratch. - CALLER_ATTACH Font::Builder* newFontBuilder(); + 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(ByteArray* ba); + + void LoadCollection(InputStream* is, FontArray* output); + void LoadCollection(ByteArray* ba, FontArray* output); + + CALLER_ATTACH Font::Builder* LoadSingleOTFForBuilding(InputStream* is); + CALLER_ATTACH Font::Builder* + LoadSingleOTFForBuilding(ByteArray* ba, int32_t offset_to_offset_table); + + void LoadCollectionForBuilding(InputStream* is, FontBuilderArray* builders); + void LoadCollectionForBuilding(ByteArray* ba, FontBuilderArray* builders); + + static bool IsCollection(PushbackInputStream* pbis); + static bool IsCollection(ByteArray* ba); + bool fingerprint_; IntegerList table_ordering_; }; diff --git a/sfntly/font_header_table.cc b/sfntly/font_header_table.cc index 7710c5a..f896001 100644 --- a/sfntly/font_header_table.cc +++ b/sfntly/font_header_table.cc @@ -20,83 +20,83 @@ namespace sfntly { /****************************************************************************** * FontHeaderTable class ******************************************************************************/ -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::~FontHeaderTable() {} -int32_t FontHeaderTable::tableVersion() { - return data_->readFixed(Offset::kTableVersion); +int32_t FontHeaderTable::TableVersion() { + return data_->ReadFixed(Offset::kTableVersion); } -int32_t FontHeaderTable::fontRevision() { - return data_->readFixed(Offset::kFontRevision); +int32_t FontHeaderTable::FontRevision() { + return data_->ReadFixed(Offset::kFontRevision); } -int64_t FontHeaderTable::checksumAdjustment() { - return data_->readULong(Offset::kCheckSumAdjustment); +int64_t FontHeaderTable::ChecksumAdjustment() { + return data_->ReadULong(Offset::kCheckSumAdjustment); } -int64_t FontHeaderTable::magicNumber() { - return data_->readULong(Offset::kMagicNumber); +int64_t FontHeaderTable::MagicNumber() { + return data_->ReadULong(Offset::kMagicNumber); } -int32_t FontHeaderTable::flagsAsInt() { - return data_->readUShort(Offset::kFlags); +int32_t FontHeaderTable::FlagsAsInt() { + return data_->ReadUShort(Offset::kFlags); } -int32_t FontHeaderTable::unitsPerEm() { - return data_->readUShort(Offset::kUnitsPerEm); +int32_t FontHeaderTable::UnitsPerEm() { + return data_->ReadUShort(Offset::kUnitsPerEm); } -int64_t FontHeaderTable::created() { - return data_->readDateTimeAsLong(Offset::kCreated); +int64_t FontHeaderTable::Created() { + return data_->ReadDateTimeAsLong(Offset::kCreated); } -int64_t FontHeaderTable::modified() { - return data_->readDateTimeAsLong(Offset::kModified); +int64_t FontHeaderTable::Modified() { + return data_->ReadDateTimeAsLong(Offset::kModified); } -int32_t FontHeaderTable::xMin() { - return data_->readUShort(Offset::kXMin); +int32_t FontHeaderTable::XMin() { + return data_->ReadUShort(Offset::kXMin); } -int32_t FontHeaderTable::yMin() { - return data_->readUShort(Offset::kYMin); +int32_t FontHeaderTable::YMin() { + return data_->ReadUShort(Offset::kYMin); } -int32_t FontHeaderTable::xMax() { - return data_->readUShort(Offset::kXMax); +int32_t FontHeaderTable::XMax() { + return data_->ReadUShort(Offset::kXMax); } -int32_t FontHeaderTable::yMax() { - return data_->readUShort(Offset::kYMax); +int32_t FontHeaderTable::YMax() { + return data_->ReadUShort(Offset::kYMax); } -int32_t FontHeaderTable::macStyleAsInt() { - return data_->readUShort(Offset::kMacStyle); +int32_t FontHeaderTable::MacStyleAsInt() { + return data_->ReadUShort(Offset::kMacStyle); } -int32_t FontHeaderTable::lowestRecPPEM() { - return data_->readUShort(Offset::kLowestRecPPEM); +int32_t FontHeaderTable::LowestRecPPEM() { + return data_->ReadUShort(Offset::kLowestRecPPEM); } -int32_t FontHeaderTable::fontDirectionHint() { - return data_->readShort(Offset::kFontDirectionHint); +int32_t FontHeaderTable::FontDirectionHint() { + return data_->ReadShort(Offset::kFontDirectionHint); } -int32_t FontHeaderTable::indexToLocFormat() { - return data_->readShort(Offset::kIndexToLocFormat); +int32_t FontHeaderTable::IndexToLocFormat() { + return data_->ReadShort(Offset::kIndexToLocFormat); } -int32_t FontHeaderTable::glyphDataFormat() { - return data_->readShort(Offset::kGlyphDataFormat); +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); } /****************************************************************************** @@ -114,146 +114,146 @@ FontHeaderTable::Builder::Builder(FontDataTableBuilderContainer* font_builder, FontHeaderTable::Builder::~Builder() {} -CALLER_ATTACH FontDataTable* FontHeaderTable::Builder::subBuildTable( +CALLER_ATTACH FontDataTable* FontHeaderTable::Builder::SubBuildTable( ReadableFontData* data) { FontDataTablePtr table = new FontHeaderTable(header(), data); - return table.detach(); + return table.Detach(); } -int32_t FontHeaderTable::Builder::tableVersion() { - return down_cast(table())->tableVersion(); +int32_t FontHeaderTable::Builder::TableVersion() { + return down_cast(GetTable())->TableVersion(); } -void FontHeaderTable::Builder::setTableVersion(int32_t version) { - internalWriteData()->writeFixed(Offset::kTableVersion, version); +void FontHeaderTable::Builder::SetTableVersion(int32_t version) { + InternalWriteData()->WriteFixed(Offset::kTableVersion, version); } -int32_t FontHeaderTable::Builder::fontRevision() { - return down_cast(table())->fontRevision(); +int32_t FontHeaderTable::Builder::FontRevision() { + return down_cast(GetTable())->FontRevision(); } -void FontHeaderTable::Builder::setFontRevision(int32_t revision) { - internalWriteData()->writeFixed(Offset::kFontRevision, revision); +void FontHeaderTable::Builder::SetFontRevision(int32_t revision) { + InternalWriteData()->WriteFixed(Offset::kFontRevision, revision); } -int64_t FontHeaderTable::Builder::checksumAdjustment() { - return down_cast(table())->checksumAdjustment(); +int64_t FontHeaderTable::Builder::ChecksumAdjustment() { + return down_cast(GetTable())->ChecksumAdjustment(); } -void FontHeaderTable::Builder::setChecksumAdjustment(int64_t adjustment) { - internalWriteData()->writeULong(Offset::kCheckSumAdjustment, adjustment); +void FontHeaderTable::Builder::SetChecksumAdjustment(int64_t adjustment) { + InternalWriteData()->WriteULong(Offset::kCheckSumAdjustment, adjustment); } -int64_t FontHeaderTable::Builder::magicNumber() { - return down_cast(table())->magicNumber(); +int64_t FontHeaderTable::Builder::MagicNumber() { + return down_cast(GetTable())->MagicNumber(); } -void FontHeaderTable::Builder::setMagicNumber(int64_t magic_number) { - internalWriteData()->writeULong(Offset::kMagicNumber, magic_number); +void FontHeaderTable::Builder::SetMagicNumber(int64_t magic_number) { + InternalWriteData()->WriteULong(Offset::kMagicNumber, magic_number); } -int32_t FontHeaderTable::Builder::flagsAsInt() { - return down_cast(table())->flagsAsInt(); +int32_t FontHeaderTable::Builder::FlagsAsInt() { + return down_cast(GetTable())->FlagsAsInt(); } -void FontHeaderTable::Builder::setFlagsAsInt(int32_t flags) { - internalWriteData()->writeUShort(Offset::kFlags, flags); +void FontHeaderTable::Builder::SetFlagsAsInt(int32_t flags) { + InternalWriteData()->WriteUShort(Offset::kFlags, flags); } -int32_t FontHeaderTable::Builder::unitsPerEm() { - return down_cast(table())->unitsPerEm(); +int32_t FontHeaderTable::Builder::UnitsPerEm() { + return down_cast(GetTable())->UnitsPerEm(); } -void FontHeaderTable::Builder::setUnitsPerEm(int32_t units) { - internalWriteData()->writeUShort(Offset::kUnitsPerEm, units); +void FontHeaderTable::Builder::SetUnitsPerEm(int32_t units) { + InternalWriteData()->WriteUShort(Offset::kUnitsPerEm, units); } -int64_t FontHeaderTable::Builder::created() { - return down_cast(table())->modified(); +int64_t FontHeaderTable::Builder::Created() { + return down_cast(GetTable())->Created(); } -void FontHeaderTable::Builder::setCreated(int64_t date) { - internalWriteData()->writeDateTime(Offset::kCreated, date); +void FontHeaderTable::Builder::SetCreated(int64_t date) { + InternalWriteData()->WriteDateTime(Offset::kCreated, date); } -int64_t FontHeaderTable::Builder::modified() { - return down_cast(table())->modified(); +int64_t FontHeaderTable::Builder::Modified() { + return down_cast(GetTable())->Modified(); } -void FontHeaderTable::Builder::setModified(int64_t date) { - internalWriteData()->writeDateTime(Offset::kModified, date); +void FontHeaderTable::Builder::SetModified(int64_t date) { + InternalWriteData()->WriteDateTime(Offset::kModified, date); } -int32_t FontHeaderTable::Builder::xMin() { - return down_cast(table())->xMin(); +int32_t FontHeaderTable::Builder::XMin() { + return down_cast(GetTable())->XMin(); } -void FontHeaderTable::Builder::setXMin(int32_t xmin) { - internalWriteData()->writeShort(Offset::kXMin, xmin); +void FontHeaderTable::Builder::SetXMin(int32_t xmin) { + InternalWriteData()->WriteShort(Offset::kXMin, xmin); } -int32_t FontHeaderTable::Builder::yMin() { - return down_cast(table())->yMin(); +int32_t FontHeaderTable::Builder::YMin() { + return down_cast(GetTable())->YMin(); } -void FontHeaderTable::Builder::setYMin(int32_t ymin) { - internalWriteData()->writeShort(Offset::kYMin, ymin); +void FontHeaderTable::Builder::SetYMin(int32_t ymin) { + InternalWriteData()->WriteShort(Offset::kYMin, ymin); } -int32_t FontHeaderTable::Builder::xMax() { - return down_cast(table())->xMax(); +int32_t FontHeaderTable::Builder::XMax() { + return down_cast(GetTable())->XMax(); } -void FontHeaderTable::Builder::setXMax(int32_t xmax) { - internalWriteData()->writeShort(Offset::kXMax, xmax); +void FontHeaderTable::Builder::SetXMax(int32_t xmax) { + InternalWriteData()->WriteShort(Offset::kXMax, xmax); } -int32_t FontHeaderTable::Builder::yMax() { - return down_cast(table())->yMax(); +int32_t FontHeaderTable::Builder::YMax() { + return down_cast(GetTable())->YMax(); } -void FontHeaderTable::Builder::setYMax(int32_t ymax) { - internalWriteData()->writeShort(Offset::kYMax, ymax); +void FontHeaderTable::Builder::SetYMax(int32_t ymax) { + InternalWriteData()->WriteShort(Offset::kYMax, ymax); } -int32_t FontHeaderTable::Builder::macStyleAsInt() { - return down_cast(table())->macStyleAsInt(); +int32_t FontHeaderTable::Builder::MacStyleAsInt() { + return down_cast(GetTable())->MacStyleAsInt(); } -void FontHeaderTable::Builder::setMacStyleAsInt(int32_t style) { - internalWriteData()->writeUShort(Offset::kMacStyle, style); +void FontHeaderTable::Builder::SetMacStyleAsInt(int32_t style) { + InternalWriteData()->WriteUShort(Offset::kMacStyle, style); } -int32_t FontHeaderTable::Builder::lowestRecPPEM() { - return down_cast(table())->lowestRecPPEM(); +int32_t FontHeaderTable::Builder::LowestRecPPEM() { + return down_cast(GetTable())->LowestRecPPEM(); } -void FontHeaderTable::Builder::setLowestRecPPEM(int32_t size) { - internalWriteData()->writeUShort(Offset::kLowestRecPPEM, size); +void FontHeaderTable::Builder::SetLowestRecPPEM(int32_t size) { + InternalWriteData()->WriteUShort(Offset::kLowestRecPPEM, size); } -int32_t FontHeaderTable::Builder::fontDirectionHint() { - return down_cast(table())->fontDirectionHint(); +int32_t FontHeaderTable::Builder::FontDirectionHint() { + return down_cast(GetTable())->FontDirectionHint(); } -void FontHeaderTable::Builder::setFontDirectionHint(int32_t hint) { - internalWriteData()->writeShort(Offset::kFontDirectionHint, hint); +void FontHeaderTable::Builder::SetFontDirectionHint(int32_t hint) { + InternalWriteData()->WriteShort(Offset::kFontDirectionHint, hint); } -int32_t FontHeaderTable::Builder::indexToLocFormat() { - return down_cast(table())->indexToLocFormat(); +int32_t FontHeaderTable::Builder::IndexToLocFormat() { + return down_cast(GetTable())->IndexToLocFormat(); } -void FontHeaderTable::Builder::setIndexToLocFormat(int32_t format) { - internalWriteData()->writeShort(Offset::kIndexToLocFormat, format); +void FontHeaderTable::Builder::SetIndexToLocFormat(int32_t format) { + InternalWriteData()->WriteShort(Offset::kIndexToLocFormat, format); } -int32_t FontHeaderTable::Builder::glyphDataFormat() { - return down_cast(table())->glyphDataFormat(); +int32_t FontHeaderTable::Builder::GlyphDataFormat() { + return down_cast(GetTable())->GlyphDataFormat(); } -void FontHeaderTable::Builder::setGlyphDataFormat(int32_t format) { - internalWriteData()->writeShort(Offset::kGlyphDataFormat, format); +void FontHeaderTable::Builder::SetGlyphDataFormat(int32_t format) { + InternalWriteData()->WriteShort(Offset::kGlyphDataFormat, format); } } // namespace sfntly diff --git a/sfntly/font_header_table.h b/sfntly/font_header_table.h index c8aa9fe..dd6f593 100644 --- a/sfntly/font_header_table.h +++ b/sfntly/font_header_table.h @@ -39,127 +39,125 @@ struct FontDirectionHint { }; class FontHeaderTable : public Table, public RefCounted { - 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 - }; + public: + class Builder : public Table::TableBasedTableBuilder, + public RefCounted { + public: + // Constructor scope altered to public because C++ does not allow base + // class to instantiate derived class with protected constructors. + Builder(FontDataTableBuilderContainer* font_builder, Header* header, + WritableFontData* data); + Builder(FontDataTableBuilderContainer* font_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); }; - private: - FontHeaderTable(Header* header, ReadableFontData* data); - - public: // class is final, no virtual functions unless from parent virtual ~FontHeaderTable(); - int32_t tableVersion(); - int32_t fontRevision(); + 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(); + int64_t ChecksumAdjustment(); // Get the magic number. Set to 0x5F0F3CF5. - int64_t magicNumber(); + int64_t MagicNumber(); // TODO(arthurhsu): IMPLEMENT: EnumSet - int32_t flagsAsInt(); - // TODO(arthurhsu): IMPLEMENT: flags() returning EnumSet + int32_t FlagsAsInt(); + // TODO(arthurhsu): IMPLEMENT: Flags() returning EnumSet - int32_t unitsPerEm(); + int32_t UnitsPerEm(); // Get the created date. Number of seconds since 12:00 midnight, January 1, // 1904. 64-bit integer. - int64_t created(); + int64_t Created(); // Get the modified date. Number of seconds since 12:00 midnight, January 1, // 1904. 64-bit integer. - int64_t modified(); + int64_t Modified(); // Get the x min. For all glyph bounding boxes. - int32_t xMin(); + int32_t XMin(); // Get the y min. For all glyph bounding boxes. - int32_t yMin(); + int32_t YMin(); // Get the x max. For all glyph bounding boxes. - int32_t xMax(); + int32_t XMax(); // Get the y max. For all glyph bounding boxes. - int32_t yMax(); + int32_t YMax(); // TODO(arthurhsu): IMPLEMENT: EnumSet - int32_t macStyleAsInt(); + 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(); + int32_t LowestRecPPEM(); + int32_t FontDirectionHint(); // Note: no AsInt() form, already int + int32_t IndexToLocFormat(); // Note: no AsInt() form, already int + int32_t GlyphDataFormat(); - public: - class Builder : public Table::TableBasedTableBuilder, - public RefCounted { - public: - // Constructor scope altered to public because C++ does not allow base - // class to instantiate derived class with protected constructors. - Builder(FontDataTableBuilderContainer* font_builder, Header* header, - WritableFontData* data); - Builder(FontDataTableBuilderContainer* font_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); + 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; diff --git a/sfntly/glyph_table.cc b/sfntly/glyph_table.cc index 3ff6d97..99e7c06 100644 --- a/sfntly/glyph_table.cc +++ b/sfntly/glyph_table.cc @@ -14,9 +14,10 @@ * limitations under the License. */ +#include "sfntly/glyph_table.h" + #include -#include "sfntly/glyph_table.h" #include "sfntly/port/exception_type.h" namespace sfntly { @@ -47,33 +48,38 @@ const int32_t GlyphTable::CompositeGlyph::kFLAG_UNSCALED_COMPONENT_OFFSET = 1 << /****************************************************************************** * GlyphTable class ******************************************************************************/ -GlyphTable::GlyphTable(Header* header, ReadableFontData* data) - : Table(header, data) {} +GlyphTable::~GlyphTable() { +} -GlyphTable::~GlyphTable() {} +GlyphTable::Glyph* GlyphTable::GetGlyph(int32_t offset, int32_t length) { + return GlyphTable::Glyph::GetGlyph(data_, offset, length); +} -GlyphTable::Glyph* GlyphTable::glyph(int32_t offset, int32_t length) { - return GlyphTable::Glyph::getGlyph(data_, offset, length); +GlyphTable::GlyphTable(Header* header, ReadableFontData* data) + : Table(header, data) { } /****************************************************************************** * GlyphTable::Builder class ******************************************************************************/ GlyphTable::Builder::Builder(FontDataTableBuilderContainer* font_builder, - Header* header, WritableFontData* data) : - Table::ArrayElementTableBuilder(font_builder, header, data) {} + Header* header, + WritableFontData* data) + : Table::ArrayElementTableBuilder(font_builder, header, data) { +} -GlyphTable::Builder::~Builder() {} +GlyphTable::Builder::~Builder() { +} -void GlyphTable::Builder::setLoca(const IntegerList& loca) { +void GlyphTable::Builder::SetLoca(const IntegerList& loca) { loca_ = loca; - setModelChanged(false); + set_model_changed(false); glyph_builders_.clear(); } -void GlyphTable::Builder::generateLocaList(IntegerList* locas) { +void GlyphTable::Builder::GenerateLocaList(IntegerList* locas) { assert(locas); - GlyphBuilderList* glyph_builders = getGlyphBuilders(); + GlyphBuilderList* glyph_builders = GetGlyphBuilders(); locas->resize(glyph_builders->size()); locas->push_back(0); if (glyph_builders->size() == 0) { @@ -83,76 +89,39 @@ void GlyphTable::Builder::generateLocaList(IntegerList* locas) { for (GlyphBuilderList::iterator b = glyph_builders->begin(), b_end = glyph_builders->end(); b != b_end; ++b) { - int32_t size = (*b)->subDataSizeToSerialize(); + int32_t size = (*b)->SubDataSizeToSerialize(); locas->push_back(total + size); total += size; } } } -void GlyphTable::Builder::initialize(ReadableFontData* data, - const IntegerList& loca) { - if (data != NULL) { - if (loca_.empty()) { -#if defined (SFNTLY_NO_EXCEPTION) - return; -#else - throw IllegalStateException( - "Loca values not set - unable to parse glyph data."); -#endif - } - 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::GlyphBuilders() { + return GetGlyphBuilders(); } -GlyphTable::GlyphBuilderList* GlyphTable::Builder::getGlyphBuilders() { - if (glyph_builders_.empty()) { - initialize(internalReadData(), loca_); - setModelChanged(); - } - return &glyph_builders_; -} - -void GlyphTable::Builder::revert() { - glyph_builders_.clear(); - setModelChanged(false); -} - -GlyphTable::GlyphBuilderList* GlyphTable::Builder::glyphBuilders() { - return getGlyphBuilders(); -} - -void GlyphTable::Builder::setGlyphBuilders(GlyphBuilderList* glyph_builders) { +void GlyphTable::Builder::SetGlyphBuilders(GlyphBuilderList* glyph_builders) { glyph_builders_ = *glyph_builders; - setModelChanged(); + set_model_changed(); } -CALLER_ATTACH GlyphTable::Glyph::Builder* GlyphTable::Builder::glyphBuilder( - ReadableFontData* data) { - return Glyph::Builder::getBuilder(this, data); +CALLER_ATTACH GlyphTable::Glyph::Builder* + GlyphTable::Builder::GlyphBuilder(ReadableFontData* data) { + return Glyph::Builder::GetBuilder(this, data); } -CALLER_ATTACH FontDataTable* GlyphTable::Builder::subBuildTable( - ReadableFontData* data) { +CALLER_ATTACH FontDataTable* + GlyphTable::Builder::SubBuildTable(ReadableFontData* data) { FontDataTablePtr table = new GlyphTable(header(), data); - return table.detach(); + return table.Detach(); } -void GlyphTable::Builder::subDataSet() { +void GlyphTable::Builder::SubDataSet() { glyph_builders_.clear(); - setModelChanged(false); + set_model_changed(false); } -int32_t GlyphTable::Builder::subDataSizeToSerialize() { +int32_t GlyphTable::Builder::SubDataSizeToSerialize() { if (glyph_builders_.empty()) return 0; @@ -162,166 +131,249 @@ int32_t GlyphTable::Builder::subDataSizeToSerialize() { // 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(); + int32_t glyph_size = (*b)->SubDataSizeToSerialize(); size += abs(glyph_size); variable |= glyph_size <= 0; } return variable ? -size : size; } -bool GlyphTable::Builder::subReadyToSerialize() { +bool GlyphTable::Builder::SubReadyToSerialize() { return !glyph_builders_.empty(); } -int32_t GlyphTable::Builder::subSerialize(WritableFontData* new_data) { +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_)); + data.Attach(new_data->Slice(size)); + size += (*b)->SubSerialize(down_cast(data.p_)); } return size; } -/****************************************************************************** - * GlyphTable::Glyph class - ******************************************************************************/ -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); +void GlyphTable::Builder::Initialize(ReadableFontData* data, + const IntegerList& loca) { + if (data != NULL) { + if (loca_.empty()) { +#if defined (SFNTLY_NO_EXCEPTION) + return; +#else + throw IllegalStateException( + "Loca values not set - unable to parse glyph data."); +#endif + } + 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::Glyph::~Glyph() {} - -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; +GlyphTable::GlyphBuilderList* GlyphTable::Builder::GetGlyphBuilders() { + if (glyph_builders_.empty()) { + Initialize(InternalReadData(), loca_); + set_model_changed(); } - return GlyphType::kComposite; + return &glyph_builders_; +} + +void GlyphTable::Builder::Revert() { + glyph_builders_.clear(); + set_model_changed(false); } -CALLER_ATTACH GlyphTable::Glyph* GlyphTable::Glyph::getGlyph( - ReadableFontData* data, int32_t offset, int32_t length) { - int32_t type = glyphType(data, offset, length); +/****************************************************************************** + * GlyphTable::Glyph class + ******************************************************************************/ +GlyphTable::Glyph::~Glyph() {} + +CALLER_ATTACH GlyphTable::Glyph* + GlyphTable::Glyph::GetGlyph(ReadableFontData* data, + int32_t offset, + int32_t length) { + int32_t type = GlyphType(data, offset, length); GlyphPtr glyph; ReadableFontDataPtr sliced_data; - sliced_data.attach(down_cast(data->slice(offset, length))); + sliced_data.Attach(down_cast(data->Slice(offset, length))); if (type == GlyphType::kSimple) { glyph = new SimpleGlyph(sliced_data); } glyph = new CompositeGlyph(sliced_data); - return glyph.detach(); + return glyph.Detach(); } -int32_t GlyphTable::Glyph::glyphType() { +int32_t GlyphTable::Glyph::GlyphType() { return glyph_type_; } -int32_t GlyphTable::Glyph::numberOfContours() { +int32_t GlyphTable::Glyph::NumberOfContours() { return number_of_contours_; } -int32_t GlyphTable::Glyph::xMin() { - return data_->readShort(Offset::kXMin); +int32_t GlyphTable::Glyph::XMin() { + return data_->ReadShort(Offset::kXMin); } -int32_t GlyphTable::Glyph::xMax() { - return data_->readShort(Offset::kXMax); +int32_t GlyphTable::Glyph::XMax() { + return data_->ReadShort(Offset::kXMax); } -int32_t GlyphTable::Glyph::yMin() { - return data_->readShort(Offset::kYMin); +int32_t GlyphTable::Glyph::YMin() { + return data_->ReadShort(Offset::kYMin); } -int32_t GlyphTable::Glyph::yMax() { - return data_->readShort(Offset::kYMax); +int32_t GlyphTable::Glyph::YMax() { + return data_->ReadShort(Offset::kYMax); } -int32_t GlyphTable::Glyph::padding() { +int32_t GlyphTable::Glyph::Padding() { return padding_; } +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(FontDataTableBuilderContainer* font_builder, - WritableFontData* data) : - SubTable::Builder(font_builder, data) { +GlyphTable::Glyph::Builder::~Builder() { } GlyphTable::Glyph::Builder::Builder(FontDataTableBuilderContainer* font_builder, - ReadableFontData* data) : - SubTable::Builder(font_builder, data) { + WritableFontData* data) + : SubTable::Builder(font_builder, data) { } -GlyphTable::Glyph::Builder::~Builder() {} +GlyphTable::Glyph::Builder::Builder(FontDataTableBuilderContainer* font_builder, + ReadableFontData* data) + : SubTable::Builder(font_builder, data) { +} CALLER_ATTACH GlyphTable::Glyph::Builder* - GlyphTable::Glyph::Builder::getBuilder( - FontDataTableBuilderContainer* table_builder, ReadableFontData* data) { - return getBuilder(table_builder, data, 0, data->length()); + GlyphTable::Glyph::Builder::GetBuilder( + FontDataTableBuilderContainer* table_builder, + ReadableFontData* data) { + return GetBuilder(table_builder, data, 0, data->Length()); } CALLER_ATTACH GlyphTable::Glyph::Builder* - GlyphTable::Glyph::Builder::getBuilder( - FontDataTableBuilderContainer* table_builder, ReadableFontData* data, - int32_t offset, int32_t length) { - int32_t type = Glyph::glyphType(data, offset, length); + GlyphTable::Glyph::Builder::GetBuilder( + FontDataTableBuilderContainer* table_builder, + ReadableFontData* data, + int32_t offset, + int32_t length) { + int32_t type = Glyph::GlyphType(data, offset, length); GlyphBuilderPtr builder; ReadableFontDataPtr sliced_data; - sliced_data.attach(down_cast(data->slice(offset, length))); + sliced_data.Attach(down_cast(data->Slice(offset, length))); if (type == GlyphType::kSimple) { builder = new SimpleGlyph::SimpleGlyphBuilder(table_builder, sliced_data); } else { builder = new CompositeGlyph::CompositeGlyphBuilder(table_builder, sliced_data); } - return builder.detach(); + return builder.Detach(); } -void GlyphTable::Glyph::Builder::subDataSet() { +void GlyphTable::Glyph::Builder::SubDataSet() { // NOP } -int32_t GlyphTable::Glyph::Builder::subDataSizeToSerialize() { - return internalReadData()->length(); +int32_t GlyphTable::Glyph::Builder::SubDataSizeToSerialize() { + return InternalReadData()->Length(); } -bool GlyphTable::Glyph::Builder::subReadyToSerialize() { +bool GlyphTable::Glyph::Builder::SubReadyToSerialize() { return true; } -int32_t GlyphTable::Glyph::Builder::subSerialize(WritableFontData* new_data) { - return internalReadData()->copyTo(new_data); +int32_t GlyphTable::Glyph::Builder::SubSerialize(WritableFontData* new_data) { + return InternalReadData()->CopyTo(new_data); } /****************************************************************************** - * GlyphTable::SimpleGlyph and its builder + * GlyphTable::SimpleGlyph ******************************************************************************/ GlyphTable::SimpleGlyph::SimpleGlyph(ReadableFontData* data) : GlyphTable::Glyph(data, GlyphType::kSimple) { } -GlyphTable::SimpleGlyph::~SimpleGlyph() {} +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]; +} -void GlyphTable::SimpleGlyph::initialize() { +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() { if (initialized_) { return; } - if (readFontData()->length() == 0) { + if (ReadFontData()->Length() == 0) { instruction_size_ = 0; number_of_points_ = 0; instructions_offset_ = 0; @@ -331,38 +383,38 @@ void GlyphTable::SimpleGlyph::initialize() { return; } - instruction_size_ = data_->readUShort(Offset::kSimpleEndPtsOfCountours + - numberOfContours() * DataSize::kUSHORT); + instruction_size_ = data_->ReadUShort(Offset::kSimpleEndPtsOfCountours + + NumberOfContours() * DataSize::kUSHORT); instructions_offset_ = Offset::kSimpleEndPtsOfCountours + - (numberOfContours() + 1) * DataSize::kUSHORT; + (NumberOfContours() + 1) * DataSize::kUSHORT; flags_offset_ = instructions_offset_ + instruction_size_ * DataSize::kBYTE; - number_of_points_ = contourEndPoint(numberOfContours() - 1) + 1; + 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); + 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_.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; + contour_index_[contour + 1] = ContourEndPoint(contour) + 1; } - parseData(true); + ParseData(true); int32_t non_padded_data_length = 5 * DataSize::kSHORT + - (numberOfContours() * DataSize::kUSHORT) + + (NumberOfContours() * DataSize::kUSHORT) + DataSize::kUSHORT + (instruction_size_ * DataSize::kBYTE) + (flag_byte_count_ * DataSize::kBYTE) + (x_byte_count_ * DataSize::kBYTE) + (y_byte_count_ * DataSize::kBYTE); - padding_ = length() - non_padded_data_length; + padding_ = Length() - non_padded_data_length; initialized_ = true; } -void GlyphTable::SimpleGlyph::parseData(bool fill_arrays) { +void GlyphTable::SimpleGlyph::ParseData(bool fill_arrays) { int32_t flag = 0; int32_t flag_repeat = 0; int32_t flag_index = 0; @@ -373,9 +425,9 @@ void GlyphTable::SimpleGlyph::parseData(bool fill_arrays) { ++point_index) { // get the flag for the current point if (flag_repeat == 0) { - flag = flagAsInt(flag_index++); + flag = FlagAsInt(flag_index++); if ((flag & kFLAG_REPEAT) == kFLAG_REPEAT) { - flag_repeat = flagAsInt(flag_index++); + flag_repeat = FlagAsInt(flag_index++); } } else { flag_repeat--; @@ -390,7 +442,7 @@ void GlyphTable::SimpleGlyph::parseData(bool fill_arrays) { // single byte x coord value if (fill_arrays) { x_coordinates_[point_index] = - data_->readUByte(x_coordinates_offset_ + x_byte_index); + data_->ReadUByte(x_coordinates_offset_ + x_byte_index); x_coordinates_[point_index] *= ((flag & kFLAG_XREPEATSIGN) == kFLAG_XREPEATSIGN) ? 1 : -1; } @@ -400,7 +452,7 @@ void GlyphTable::SimpleGlyph::parseData(bool fill_arrays) { if (!((flag & kFLAG_XREPEATSIGN) == kFLAG_XREPEATSIGN)) { if (fill_arrays) { x_coordinates_[point_index] = - data_->readShort(x_coordinates_offset_ + x_byte_index); + data_->ReadShort(x_coordinates_offset_ + x_byte_index); } x_byte_index += 2; } @@ -413,7 +465,7 @@ void GlyphTable::SimpleGlyph::parseData(bool fill_arrays) { if ((flag & kFLAG_YSHORT) == kFLAG_YSHORT) { if (fill_arrays) { y_coordinates_[point_index] = - data_->readUByte(y_coordinates_offset_ + y_byte_index); + data_->ReadUByte(y_coordinates_offset_ + y_byte_index); y_coordinates_[point_index] *= ((flag & kFLAG_YREPEATSIGN) == kFLAG_YREPEATSIGN) ? 1 : -1; } @@ -422,7 +474,7 @@ void GlyphTable::SimpleGlyph::parseData(bool fill_arrays) { if (!((flag & kFLAG_YREPEATSIGN) == kFLAG_YREPEATSIGN)) { if (fill_arrays) { y_coordinates_[point_index] = - data_->readShort(y_coordinates_offset_ + y_byte_index); + data_->ReadShort(y_coordinates_offset_ + y_byte_index); } y_byte_index += 2; } @@ -436,146 +488,87 @@ void GlyphTable::SimpleGlyph::parseData(bool fill_arrays) { 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::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 + +int32_t GlyphTable::SimpleGlyph::ContourEndPoint(int32_t contour) { + return data_->ReadUShort(contour * DataSize::kUSHORT + Offset::kSimpleEndPtsOfCountours); } -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]; +/****************************************************************************** + * GlyphTable::SimpleGlyph::Builder + ******************************************************************************/ +GlyphTable::SimpleGlyph::SimpleGlyphBuilder::~SimpleGlyphBuilder() { } GlyphTable::SimpleGlyph::SimpleGlyphBuilder::SimpleGlyphBuilder( - FontDataTableBuilderContainer* table_builder, WritableFontData* data) : - Glyph::Builder(table_builder, data) { + FontDataTableBuilderContainer* table_builder, + WritableFontData* data) + : Glyph::Builder(table_builder, data) { } GlyphTable::SimpleGlyph::SimpleGlyphBuilder::SimpleGlyphBuilder( - FontDataTableBuilderContainer* table_builder, ReadableFontData* data) : - Glyph::Builder(table_builder, data) { + FontDataTableBuilderContainer* table_builder, + ReadableFontData* data) + : Glyph::Builder(table_builder, data) { } -GlyphTable::SimpleGlyph::SimpleGlyphBuilder::~SimpleGlyphBuilder() {} - CALLER_ATTACH FontDataTable* - GlyphTable::SimpleGlyph::SimpleGlyphBuilder::subBuildTable( + GlyphTable::SimpleGlyph::SimpleGlyphBuilder::SubBuildTable( ReadableFontData* data) { FontDataTablePtr table = new SimpleGlyph(data); - return table.detach(); + return table.Detach(); } /****************************************************************************** - * GlyphTable::CompositeGlyph and its builder + * GlyphTable::CompositeGlyph ******************************************************************************/ GlyphTable::CompositeGlyph::CompositeGlyph(ReadableFontData* data) : GlyphTable::Glyph(data, GlyphType::kComposite), - instruction_size_(0), instructions_offset_(0) { - parseData(); + instruction_size_(0), + instructions_offset_(0) { + ParseData(); } -GlyphTable::CompositeGlyph::~CompositeGlyph() {} - -void GlyphTable::CompositeGlyph::parseData() { - 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); - } - padding_ = length() - non_padded_data_length; - } +GlyphTable::CompositeGlyph::~CompositeGlyph() { } -int32_t GlyphTable::CompositeGlyph::flags(int32_t contour) { - return data_->readUShort(contour_index_[contour]); +int32_t GlyphTable::CompositeGlyph::Flags(int32_t contour) { + return data_->ReadUShort(contour_index_[contour]); } -int32_t GlyphTable::CompositeGlyph::numGlyphs() { +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::GlyphIndex(int32_t contour) { + return data_->ReadUShort(DataSize::kUSHORT + contour_index_[contour]); } -int32_t GlyphTable::CompositeGlyph::argument1(int32_t contour) { +int32_t GlyphTable::CompositeGlyph::Argument1(int32_t contour) { int32_t index = 2 * DataSize::kUSHORT + contour_index_[contour]; - int32_t contour_flags = flags(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_->ReadUShort(index); } - return data_->readByte(index); + return data_->ReadByte(index); } -int32_t GlyphTable::CompositeGlyph::argument2(int32_t contour) { +int32_t GlyphTable::CompositeGlyph::Argument2(int32_t contour) { int32_t index = 2 * DataSize::kUSHORT + contour_index_[contour]; - int32_t contour_flags = flags(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_->ReadUShort(index + DataSize::kUSHORT); } - return data_->readByte(index + DataSize::kUSHORT); + return data_->ReadByte(index + DataSize::kUSHORT); } -int32_t GlyphTable::CompositeGlyph::transformationSize(int32_t contour) { - int32_t contour_flags = flags(contour); +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) == @@ -588,9 +581,9 @@ int32_t GlyphTable::CompositeGlyph::transformationSize(int32_t contour) { return 0; } -void GlyphTable::CompositeGlyph::transformation(int32_t contour, +void GlyphTable::CompositeGlyph::Transformation(int32_t contour, ByteVector* transformation) { - int32_t contour_flags = flags(contour); + 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) { @@ -598,37 +591,76 @@ void GlyphTable::CompositeGlyph::transformation(int32_t contour, } else { index += 2 * DataSize::kBYTE; } - int32_t tsize = transformationSize(contour); + int32_t tsize = TransformationSize(contour); transformation->resize(tsize); - data_->readBytes(index, transformation, 0, tsize); + data_->ReadBytes(index, transformation, 0, tsize); } -int32_t GlyphTable::CompositeGlyph::instructionSize() { +int32_t GlyphTable::CompositeGlyph::InstructionSize() { return instruction_size_; } -CALLER_ATTACH ReadableFontData* GlyphTable::CompositeGlyph::instructions() { +CALLER_ATTACH ReadableFontData* GlyphTable::CompositeGlyph::Instructions() { return down_cast( - data_->slice(instructions_offset_, instructionSize())); + data_->Slice(instructions_offset_, InstructionSize())); } -GlyphTable::CompositeGlyph::CompositeGlyphBuilder::CompositeGlyphBuilder( - FontDataTableBuilderContainer* table_builder, WritableFontData* data) : - Glyph::Builder(table_builder, data) { +void GlyphTable::CompositeGlyph::ParseData() { + 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); + } + padding_ = Length() - non_padded_data_length; + } +} + +/****************************************************************************** + * GlyphTable::CompositeGlyph::Builder + ******************************************************************************/ +GlyphTable::CompositeGlyph::CompositeGlyphBuilder::~CompositeGlyphBuilder() { } GlyphTable::CompositeGlyph::CompositeGlyphBuilder::CompositeGlyphBuilder( - FontDataTableBuilderContainer* table_builder, ReadableFontData* data) : - Glyph::Builder(table_builder, data) { + FontDataTableBuilderContainer* table_builder, + WritableFontData* data) + : Glyph::Builder(table_builder, data) { } -GlyphTable::CompositeGlyph::CompositeGlyphBuilder::~CompositeGlyphBuilder() {} +GlyphTable::CompositeGlyph::CompositeGlyphBuilder::CompositeGlyphBuilder( + FontDataTableBuilderContainer* table_builder, + ReadableFontData* data) + : Glyph::Builder(table_builder, data) { +} CALLER_ATTACH FontDataTable* - GlyphTable::CompositeGlyph::CompositeGlyphBuilder::subBuildTable( + GlyphTable::CompositeGlyph::CompositeGlyphBuilder::SubBuildTable( ReadableFontData* data) { FontDataTablePtr table = new CompositeGlyph(data); - return table.detach(); + return table.Detach(); } } // namespace sfntly diff --git a/sfntly/glyph_table.h b/sfntly/glyph_table.h index 8a7a8aa..c066d47 100644 --- a/sfntly/glyph_table.h +++ b/sfntly/glyph_table.h @@ -36,66 +36,9 @@ struct GlyphType { // before GlyphTable::Builder to avoid compilation errors. class GlyphTable : public Table, public RefCounted { public: - 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, - }; - }; - - private: - GlyphTable(Header* header, ReadableFontData* data); - - public: - virtual ~GlyphTable(); - - class Glyph; - Glyph* glyph(int32_t offset, int32_t length); - class Builder; class Glyph : public SubTable { - 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); - - private: - static int32_t glyphType(ReadableFontData* data, int32_t offset, - int32_t length); - public: - virtual ~Glyph(); - static CALLER_ATTACH Glyph* getGlyph(ReadableFontData* data, int32_t offset, - int32_t length); - 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 padding(); // override FontDataTable::padding() - - virtual int32_t instructionSize() = 0; - virtual ReadableFontData* instructions() = 0; - // Note: Contour is an empty class for the version ported class Contour { protected: @@ -104,42 +47,67 @@ class GlyphTable : public Table, public RefCounted { }; 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. + // caller need to do data->Slice(offset, length) beforehand. Builder(FontDataTableBuilderContainer* table_builder, WritableFontData* data); Builder(FontDataTableBuilderContainer* table_builder, ReadableFontData* data); - public: - virtual ~Builder(); - - protected: - static CALLER_ATTACH Builder* getBuilder( - FontDataTableBuilderContainer* table_builder, ReadableFontData* data); - static CALLER_ATTACH Builder* getBuilder( - FontDataTableBuilderContainer* 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); - - protected: + static CALLER_ATTACH Builder* + GetBuilder(FontDataTableBuilderContainer* table_builder, + ReadableFontData* data); + static CALLER_ATTACH Builder* + GetBuilder(FontDataTableBuilderContainer* 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; }; - private: - int32_t glyph_type_; - int32_t number_of_contours_; + virtual ~Glyph(); + static CALLER_ATTACH Glyph* GetGlyph(ReadableFontData* data, + int32_t offset, + int32_t length); + 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 Padding(); // override FontDataTable::Padding() + + 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); + + // TODO(arthurhsu): violating C++ style guide, need refactoring. int32_t padding_; - }; + 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; @@ -147,19 +115,14 @@ class GlyphTable : public Table, public RefCounted { public RefCounted { public: // Note: Constructor scope altered to public for base class to instantiate. - Builder(FontDataTableBuilderContainer* font_builder, Header* header, + Builder(FontDataTableBuilderContainer* font_builder, + Header* header, WritableFontData* data); virtual ~Builder(); - virtual void setLoca(const IntegerList& loca); - virtual void generateLocaList(IntegerList* locas); + virtual void SetLoca(const IntegerList& loca); + virtual void GenerateLocaList(IntegerList* locas); - private: - void initialize(ReadableFontData* data, const IntegerList& loca); - GlyphBuilderList* getGlyphBuilders(); - void revert(); - - public: // 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. @@ -168,22 +131,26 @@ class GlyphTable : public Table, public RefCounted { // 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(); + GlyphBuilderList* GlyphBuilders(); // Replace the internal glyph builders with the one provided. - void setGlyphBuilders(GlyphBuilderList* glyph_builders); + void SetGlyphBuilders(GlyphBuilderList* glyph_builders); // Glyph builder factories - CALLER_ATTACH Glyph::Builder* glyphBuilder(ReadableFontData* data); + 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); + 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_; }; @@ -197,34 +164,12 @@ class GlyphTable : public Table, public RefCounted { static const int32_t kFLAG_XREPEATSIGN; static const int32_t kFLAG_YREPEATSIGN; - public: - // Note: constructor refactored in C++ to avoid heavy lifting. - // caller need to do data->slice(offset, length) beforehand. - explicit SimpleGlyph(ReadableFontData* data); - virtual ~SimpleGlyph(); - - public: class SimpleContour : public Glyph::Contour { protected: SimpleContour() {} virtual ~SimpleContour() {} }; - private: - void initialize(); - void parseData(bool fill_arrays); - int32_t flagAsInt(int32_t index); - int32_t contourEndPoint(int32_t contour); - - public: // class is final, , no virtual functions unless from parent - virtual int32_t instructionSize(); - virtual CALLER_ATTACH ReadableFontData* instructions(); - 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); - - public: class SimpleGlyphBuilder : public Glyph::Builder, public RefCounted { public: @@ -232,17 +177,36 @@ class GlyphTable : public Table, public RefCounted { protected: // Note: constructor refactored in C++ to avoid heavy lifting. - // caller need to do data->slice(offset, length) beforehand. + // caller need to do data->Slice(offset, length) beforehand. SimpleGlyphBuilder(FontDataTableBuilderContainer* table_builder, WritableFontData* data); SimpleGlyphBuilder(FontDataTableBuilderContainer* table_builder, ReadableFontData* data); virtual CALLER_ATTACH FontDataTable* - subBuildTable(ReadableFontData* data); + 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(); + 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 Initialize(); + void ParseData(bool fill_arrays); + int32_t FlagAsInt(int32_t index); + int32_t ContourEndPoint(int32_t contour); + bool initialized_; int32_t instruction_size_; int32_t number_of_points_; @@ -279,27 +243,6 @@ class GlyphTable : public Table, public RefCounted { static const int32_t kFLAG_SCALED_COMPONENT_OFFSET; static const int32_t kFLAG_UNSCALED_COMPONENT_OFFSET; - public: - // Note: constructor refactored in C++ to avoid heavy lifting. - // caller need to do data->slice(offset, length) beforehand. - explicit CompositeGlyph(ReadableFontData* data); - virtual ~CompositeGlyph(); - - private: - void parseData(); - - public: // class is final, no virtual functions unless from parent - 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(); - - public: class CompositeGlyphBuilder : public Glyph::Builder, public RefCounted { public: @@ -307,22 +250,74 @@ class GlyphTable : public Table, public RefCounted { protected: // Note: constructor refactored in C++ to avoid heavy lifting. - // caller need to do data->slice(offset, length) beforehand. + // caller need to do data->Slice(offset, length) beforehand. CompositeGlyphBuilder(FontDataTableBuilderContainer* table_builder, WritableFontData* data); CompositeGlyphBuilder(FontDataTableBuilderContainer* table_builder, ReadableFontData* data); virtual CALLER_ATTACH FontDataTable* - subBuildTable(ReadableFontData* data); + 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(); + private: + void ParseData(); + IntegerList contour_index_; int32_t instruction_size_; int32_t instructions_offset_; }; + + 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; diff --git a/sfntly/horizontal_header_table.cc b/sfntly/horizontal_header_table.cc index f30e8db..a987d70 100644 --- a/sfntly/horizontal_header_table.cc +++ b/sfntly/horizontal_header_table.cc @@ -24,189 +24,192 @@ namespace sfntly { /****************************************************************************** * HorizontalHeaderTable class ******************************************************************************/ -HorizontalHeaderTable:: HorizontalHeaderTable(Header* header, - ReadableFontData* data) : - Table(header, data) {} - HorizontalHeaderTable:: ~HorizontalHeaderTable() {} -int32_t HorizontalHeaderTable::version() { - return data_->readFixed(Offset::kVersion); +int32_t HorizontalHeaderTable::Version() { + return data_->ReadFixed(Offset::kVersion); } -int32_t HorizontalHeaderTable::ascender() { - return data_->readShort(Offset::kAscender); +int32_t HorizontalHeaderTable::Ascender() { + return data_->ReadShort(Offset::kAscender); } -int32_t HorizontalHeaderTable::descender() { - return data_->readShort(Offset::kDescender); +int32_t HorizontalHeaderTable::Descender() { + return data_->ReadShort(Offset::kDescender); } -int32_t HorizontalHeaderTable::lineGap() { - return data_->readShort(Offset::kLineGap); +int32_t HorizontalHeaderTable::LineGap() { + return data_->ReadShort(Offset::kLineGap); } -int32_t HorizontalHeaderTable::advanceWidthMax() { - return data_->readUShort(Offset::kAdvanceWidthMax); +int32_t HorizontalHeaderTable::AdvanceWidthMax() { + return data_->ReadUShort(Offset::kAdvanceWidthMax); } -int32_t HorizontalHeaderTable::minLeftSideBearing() { - return data_->readShort(Offset::kMinLeftSideBearing); +int32_t HorizontalHeaderTable::MinLeftSideBearing() { + return data_->ReadShort(Offset::kMinLeftSideBearing); } -int32_t HorizontalHeaderTable::minRightSideBearing() { - return data_->readShort(Offset::kMinRightSideBearing); +int32_t HorizontalHeaderTable::MinRightSideBearing() { + return data_->ReadShort(Offset::kMinRightSideBearing); } -int32_t HorizontalHeaderTable::xMaxExtent() { - return data_->readShort(Offset::kXMaxExtent); +int32_t HorizontalHeaderTable::XMaxExtent() { + return data_->ReadShort(Offset::kXMaxExtent); } -int32_t HorizontalHeaderTable::caretSlopeRise() { - return data_->readShort(Offset::kCaretSlopeRise); +int32_t HorizontalHeaderTable::CaretSlopeRise() { + return data_->ReadShort(Offset::kCaretSlopeRise); } -int32_t HorizontalHeaderTable::caretSlopeRun() { - return data_->readShort(Offset::kCaretSlopeRun); +int32_t HorizontalHeaderTable::CaretSlopeRun() { + return data_->ReadShort(Offset::kCaretSlopeRun); } -int32_t HorizontalHeaderTable::caretOffset() { - return data_->readShort(Offset::kCaretOffset); +int32_t HorizontalHeaderTable::CaretOffset() { + return data_->ReadShort(Offset::kCaretOffset); } -int32_t HorizontalHeaderTable::metricDataFormat() { - return data_->readShort(Offset::kMetricDataFormat); +int32_t HorizontalHeaderTable::MetricDataFormat() { + return data_->ReadShort(Offset::kMetricDataFormat); } -int32_t HorizontalHeaderTable::numberOfHMetrics() { - return data_->readUShort(Offset::kNumberOfHMetrics); +int32_t HorizontalHeaderTable::NumberOfHMetrics() { + return data_->ReadUShort(Offset::kNumberOfHMetrics); +} + +HorizontalHeaderTable:: HorizontalHeaderTable(Header* header, + ReadableFontData* data) + : Table(header, data) { } /****************************************************************************** * HorizontalHeaderTable::Builder class ******************************************************************************/ HorizontalHeaderTable::Builder::Builder( - FontDataTableBuilderContainer* font_builder, Header* header, - WritableFontData* data) : - Table::TableBasedTableBuilder(font_builder, header, data) { + FontDataTableBuilderContainer* font_builder, + Header* header, + WritableFontData* data) + : Table::TableBasedTableBuilder(font_builder, header, data) { } HorizontalHeaderTable::Builder::Builder( - FontDataTableBuilderContainer* font_builder, Header* header, - ReadableFontData* data) : - Table::TableBasedTableBuilder(font_builder, header, data) { + FontDataTableBuilderContainer* font_builder, + Header* header, + ReadableFontData* data) + : Table::TableBasedTableBuilder(font_builder, header, data) { } HorizontalHeaderTable::Builder::~Builder() {} -CALLER_ATTACH FontDataTable* HorizontalHeaderTable::Builder::subBuildTable( - ReadableFontData* data) { +CALLER_ATTACH FontDataTable* + HorizontalHeaderTable::Builder::SubBuildTable(ReadableFontData* data) { FontDataTablePtr table = new HorizontalHeaderTable(header(), data); - return table.detach(); + return table.Detach(); } -int32_t HorizontalHeaderTable::Builder::version() { - return internalReadData()->readFixed(Offset::kVersion); +int32_t HorizontalHeaderTable::Builder::Version() { + return InternalReadData()->ReadFixed(Offset::kVersion); } -void HorizontalHeaderTable::Builder::setVersion(int32_t version) { - internalWriteData()->writeFixed(Offset::kVersion, version); +void HorizontalHeaderTable::Builder::SetVersion(int32_t version) { + InternalWriteData()->WriteFixed(Offset::kVersion, version); } -int32_t HorizontalHeaderTable::Builder::ascender() { - return internalReadData()->readUShort(Offset::kAscender); +int32_t HorizontalHeaderTable::Builder::Ascender() { + return InternalReadData()->ReadUShort(Offset::kAscender); } -void HorizontalHeaderTable::Builder::setAscender(int32_t ascender) { - internalWriteData()->writeUShort(Offset::kVersion, ascender); +void HorizontalHeaderTable::Builder::SetAscender(int32_t ascender) { + InternalWriteData()->WriteUShort(Offset::kVersion, ascender); } -int32_t HorizontalHeaderTable::Builder::descender() { - return internalReadData()->readUShort(Offset::kDescender); +int32_t HorizontalHeaderTable::Builder::Descender() { + return InternalReadData()->ReadUShort(Offset::kDescender); } -void HorizontalHeaderTable::Builder::setDescender(int32_t descender) { - internalWriteData()->writeUShort(Offset::kDescender, descender); +void HorizontalHeaderTable::Builder::SetDescender(int32_t descender) { + InternalWriteData()->WriteUShort(Offset::kDescender, descender); } -int32_t HorizontalHeaderTable::Builder::lineGap() { - return internalReadData()->readUShort(Offset::kLineGap); +int32_t HorizontalHeaderTable::Builder::LineGap() { + return InternalReadData()->ReadUShort(Offset::kLineGap); } -void HorizontalHeaderTable::Builder::setLineGap(int32_t line_gap) { - internalWriteData()->writeUShort(Offset::kLineGap, line_gap); +void HorizontalHeaderTable::Builder::SetLineGap(int32_t line_gap) { + InternalWriteData()->WriteUShort(Offset::kLineGap, line_gap); } -int32_t HorizontalHeaderTable::Builder::advanceWidthMax() { - return internalReadData()->readUShort(Offset::kAdvanceWidthMax); +int32_t HorizontalHeaderTable::Builder::AdvanceWidthMax() { + return InternalReadData()->ReadUShort(Offset::kAdvanceWidthMax); } -void HorizontalHeaderTable::Builder::setAdvanceWidthMax(int32_t value) { - internalWriteData()->writeUShort(Offset::kAdvanceWidthMax, value); +void HorizontalHeaderTable::Builder::SetAdvanceWidthMax(int32_t value) { + InternalWriteData()->WriteUShort(Offset::kAdvanceWidthMax, value); } -int32_t HorizontalHeaderTable::Builder::minLeftSideBearing() { - return internalReadData()->readUShort(Offset::kMinLeftSideBearing); +int32_t HorizontalHeaderTable::Builder::MinLeftSideBearing() { + return InternalReadData()->ReadUShort(Offset::kMinLeftSideBearing); } -void HorizontalHeaderTable::Builder::setMinLeftSideBearing(int32_t value) { - internalWriteData()->writeUShort(Offset::kMinLeftSideBearing, value); +void HorizontalHeaderTable::Builder::SetMinLeftSideBearing(int32_t value) { + InternalWriteData()->WriteUShort(Offset::kMinLeftSideBearing, value); } -int32_t HorizontalHeaderTable::Builder::minRightSideBearing() { - return internalReadData()->readUShort(Offset::kMinRightSideBearing); +int32_t HorizontalHeaderTable::Builder::MinRightSideBearing() { + return InternalReadData()->ReadUShort(Offset::kMinRightSideBearing); } -void HorizontalHeaderTable::Builder::setMinRightSideBearing(int32_t value) { - internalWriteData()->writeUShort(Offset::kMinRightSideBearing, value); +void HorizontalHeaderTable::Builder::SetMinRightSideBearing(int32_t value) { + InternalWriteData()->WriteUShort(Offset::kMinRightSideBearing, value); } -int32_t HorizontalHeaderTable::Builder::xMaxExtent() { - return internalReadData()->readUShort(Offset::kXMaxExtent); +int32_t HorizontalHeaderTable::Builder::XMaxExtent() { + return InternalReadData()->ReadUShort(Offset::kXMaxExtent); } -void HorizontalHeaderTable::Builder::setXMaxExtent(int32_t value) { - internalWriteData()->writeUShort(Offset::kXMaxExtent, value); +void HorizontalHeaderTable::Builder::SetXMaxExtent(int32_t value) { + InternalWriteData()->WriteUShort(Offset::kXMaxExtent, value); } -int32_t HorizontalHeaderTable::Builder::caretSlopeRise() { - return internalReadData()->readUShort(Offset::kCaretSlopeRise); +int32_t HorizontalHeaderTable::Builder::CaretSlopeRise() { + return InternalReadData()->ReadUShort(Offset::kCaretSlopeRise); } -void HorizontalHeaderTable::Builder::setCaretSlopeRise(int32_t value) { - internalWriteData()->writeUShort(Offset::kCaretSlopeRise, value); +void HorizontalHeaderTable::Builder::SetCaretSlopeRise(int32_t value) { + InternalWriteData()->WriteUShort(Offset::kCaretSlopeRise, value); } -int32_t HorizontalHeaderTable::Builder::caretSlopeRun() { - return internalReadData()->readUShort(Offset::kCaretSlopeRun); +int32_t HorizontalHeaderTable::Builder::CaretSlopeRun() { + return InternalReadData()->ReadUShort(Offset::kCaretSlopeRun); } -void HorizontalHeaderTable::Builder::setCaretSlopeRun(int32_t value) { - internalWriteData()->writeUShort(Offset::kCaretSlopeRun, value); +void HorizontalHeaderTable::Builder::SetCaretSlopeRun(int32_t value) { + InternalWriteData()->WriteUShort(Offset::kCaretSlopeRun, value); } -int32_t HorizontalHeaderTable::Builder::caretOffset() { - return internalReadData()->readUShort(Offset::kCaretOffset); +int32_t HorizontalHeaderTable::Builder::CaretOffset() { + return InternalReadData()->ReadUShort(Offset::kCaretOffset); } -void HorizontalHeaderTable::Builder::setCaretOffset(int32_t value) { - internalWriteData()->writeUShort(Offset::kCaretOffset, value); +void HorizontalHeaderTable::Builder::SetCaretOffset(int32_t value) { + InternalWriteData()->WriteUShort(Offset::kCaretOffset, value); } -int32_t HorizontalHeaderTable::Builder::metricDataFormat() { - return internalReadData()->readUShort(Offset::kMetricDataFormat); +int32_t HorizontalHeaderTable::Builder::MetricDataFormat() { + return InternalReadData()->ReadUShort(Offset::kMetricDataFormat); } -void HorizontalHeaderTable::Builder::setMetricDataFormat(int32_t value) { - internalWriteData()->writeUShort(Offset::kMetricDataFormat, value); +void HorizontalHeaderTable::Builder::SetMetricDataFormat(int32_t value) { + InternalWriteData()->WriteUShort(Offset::kMetricDataFormat, value); } -int32_t HorizontalHeaderTable::Builder::numberOfHMetrics() { - return internalReadData()->readUShort(Offset::kNumberOfHMetrics); +int32_t HorizontalHeaderTable::Builder::NumberOfHMetrics() { + return InternalReadData()->ReadUShort(Offset::kNumberOfHMetrics); } -void HorizontalHeaderTable::Builder::setNumberOfHMetrics(int32_t value) { - internalWriteData()->writeUShort(Offset::kNumberOfHMetrics, value); +void HorizontalHeaderTable::Builder::SetNumberOfHMetrics(int32_t value) { + InternalWriteData()->WriteUShort(Offset::kNumberOfHMetrics, value); } } // namespace sfntly diff --git a/sfntly/horizontal_header_table.h b/sfntly/horizontal_header_table.h index 704391c..e8a3534 100644 --- a/sfntly/horizontal_header_table.h +++ b/sfntly/horizontal_header_table.h @@ -23,6 +23,64 @@ namespace sfntly { class HorizontalHeaderTable : public Table, public RefCounted { + public: + class Builder : public Table::TableBasedTableBuilder, + public RefCounted { + public: + // Constructor scope altered to public because C++ does not allow base + // class to instantiate derived class with protected constructors. + Builder(FontDataTableBuilderContainer* font_builder, + Header* header, + WritableFontData* data); + Builder(FontDataTableBuilderContainer* font_builder, + Header* header, + ReadableFontData* data); + virtual ~Builder(); + virtual CALLER_ATTACH FontDataTable* SubBuildTable(ReadableFontData* data); + + int32_t Version(); + void SetVersion(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 Version(); + 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 { @@ -42,65 +100,7 @@ class HorizontalHeaderTable : public Table, }; }; - private: HorizontalHeaderTable(Header* header, ReadableFontData* data); - - public: - virtual ~HorizontalHeaderTable(); - int32_t version(); - 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(); - - public: - class Builder : public Table::TableBasedTableBuilder, - public RefCounted { - public: - // Constructor scope altered to public because C++ does not allow base - // class to instantiate derived class with protected constructors. - Builder(FontDataTableBuilderContainer* font_builder, Header* header, - WritableFontData* data); - Builder(FontDataTableBuilderContainer* font_builder, Header* header, - ReadableFontData* data); - virtual ~Builder(); - virtual CALLER_ATTACH FontDataTable* subBuildTable(ReadableFontData* data); - - int32_t version(); - void setVersion(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); - }; }; typedef Ptr HorizontalHeaderTablePtr; typedef Ptr HorizontalHeaderTableBuilderPtr; diff --git a/sfntly/horizontal_metrics_table.cc b/sfntly/horizontal_metrics_table.cc index c151e18..921d8bc 100644 --- a/sfntly/horizontal_metrics_table.cc +++ b/sfntly/horizontal_metrics_table.cc @@ -21,29 +21,17 @@ namespace sfntly { /****************************************************************************** * HorizontalMetricsTable class ******************************************************************************/ -HorizontalMetricsTable::HorizontalMetricsTable(Header* header, - ReadableFontData* data) : - Table(header, data) { -} - -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::~HorizontalMetricsTable() {} -int32_t HorizontalMetricsTable::numberOfHMetrics() { +int32_t HorizontalMetricsTable::NumberOfHMetrics() { return num_hmetrics_; } -int32_t HorizontalMetricsTable::numberOfLSBs() { +int32_t HorizontalMetricsTable::NumberOfLSBs() { return num_glyphs_ - num_hmetrics_; } -int32_t HorizontalMetricsTable::hMetricAdvanceWidth(int32_t entry) { +int32_t HorizontalMetricsTable::HMetricAdvanceWidth(int32_t entry) { if (entry > num_hmetrics_) { #if defined (SFNTLY_NO_EXCEPTION) return 0; @@ -53,10 +41,10 @@ int32_t HorizontalMetricsTable::hMetricAdvanceWidth(int32_t entry) { } int32_t offset = Offset::kHMetricsStart + (entry * Offset::kHMetricsSize) + Offset::kHMetricsAdvanceWidth; - return data_->readUShort(offset); + return data_->ReadUShort(offset); } -int32_t HorizontalMetricsTable::hMetricLSB(int32_t entry) { +int32_t HorizontalMetricsTable::HMetricLSB(int32_t entry) { if (entry > num_hmetrics_) { #if defined (SFNTLY_NO_EXCEPTION) return 0; @@ -66,10 +54,10 @@ int32_t HorizontalMetricsTable::hMetricLSB(int32_t entry) { } int32_t offset = Offset::kHMetricsStart + (entry * Offset::kHMetricsSize) + Offset::kHMetricsLeftSideBearing; - return data_->readShort(offset); + return data_->ReadShort(offset); } -int32_t HorizontalMetricsTable::lsbTableEntry(int32_t entry) { +int32_t HorizontalMetricsTable::LsbTableEntry(int32_t entry) { if (entry > num_hmetrics_) { #if defined (SFNTLY_NO_EXCEPTION) return 0; @@ -79,62 +67,78 @@ int32_t HorizontalMetricsTable::lsbTableEntry(int32_t entry) { } int32_t offset = Offset::kHMetricsStart + (entry * Offset::kHMetricsSize) + Offset::kLeftSideBearingSize; - return data_->readShort(offset); + return data_->ReadShort(offset); } -int32_t HorizontalMetricsTable::advanceWidth(int32_t glyph_id) { +int32_t HorizontalMetricsTable::AdvanceWidth(int32_t glyph_id) { if (glyph_id < num_hmetrics_) { - return hMetricAdvanceWidth(glyph_id); + return HMetricAdvanceWidth(glyph_id); } - return hMetricAdvanceWidth(glyph_id - num_hmetrics_); + return HMetricAdvanceWidth(glyph_id - num_hmetrics_); +} + +HorizontalMetricsTable::HorizontalMetricsTable(Header* header, + ReadableFontData* data) + : Table(header, data) { +} + +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 ******************************************************************************/ -void HorizontalMetricsTable::Builder::init() { - num_hmetrics_ = -1; - num_glyphs_ = -1; -} - HorizontalMetricsTable::Builder::Builder( - FontDataTableBuilderContainer* font_builder, Header* header, - WritableFontData* data) : - Table::TableBasedTableBuilder(font_builder, header, data) { - init(); + FontDataTableBuilderContainer* font_builder, + Header* header, + WritableFontData* data) + : Table::TableBasedTableBuilder(font_builder, header, data) { + Init(); } HorizontalMetricsTable::Builder::Builder( - FontDataTableBuilderContainer* font_builder, Header* header, - ReadableFontData* data) : - Table::TableBasedTableBuilder(font_builder, header, data) { - init(); + FontDataTableBuilderContainer* font_builder, + Header* header, + ReadableFontData* data) + : Table::TableBasedTableBuilder(font_builder, header, data) { + Init(); } HorizontalMetricsTable::Builder::~Builder() {} -CALLER_ATTACH FontDataTable* HorizontalMetricsTable::Builder::subBuildTable( - ReadableFontData* data) { +CALLER_ATTACH FontDataTable* + HorizontalMetricsTable::Builder::SubBuildTable(ReadableFontData* data) { FontDataTablePtr table = new HorizontalMetricsTable(header(), data, num_hmetrics_, num_glyphs_); - return table.detach(); + return table.Detach(); } -void HorizontalMetricsTable::Builder::setNumberOfHMetrics( - int32_t num_hmetrics) { +void HorizontalMetricsTable::Builder::SetNumberOfHMetrics( + int32_t num_hmetrics) { assert(num_hmetrics >= 0); num_hmetrics_ = num_hmetrics; - HorizontalMetricsTable* table = down_cast( - this->table()); + HorizontalMetricsTable* table = + down_cast(this->GetTable()); table->num_hmetrics_ = num_hmetrics; } -void HorizontalMetricsTable::Builder::setNumGlyphs(int32_t num_glyphs) { +void HorizontalMetricsTable::Builder::SetNumGlyphs(int32_t num_glyphs) { assert(num_glyphs >= 0); num_glyphs_ = num_glyphs; - HorizontalMetricsTable* table = down_cast( - this->table()); + HorizontalMetricsTable* table = + down_cast(this->GetTable()); table->num_glyphs_ = num_glyphs; } +void HorizontalMetricsTable::Builder::Init() { + num_hmetrics_ = -1; + num_glyphs_ = -1; +} + } // namespace sfntly diff --git a/sfntly/horizontal_metrics_table.h b/sfntly/horizontal_metrics_table.h index c393fee..aead6fa 100644 --- a/sfntly/horizontal_metrics_table.h +++ b/sfntly/horizontal_metrics_table.h @@ -23,58 +23,60 @@ namespace sfntly { class HorizontalMetricsTable : public Table, public RefCounted { - private: - struct Offset { - enum { - // hMetrics - kHMetricsStart = 0, - kHMetricsSize = 4, - - // Offset within an hMetric - kHMetricsAdvanceWidth = 0, - kHMetricsLeftSideBearing = 2, - - kLeftSideBearingSize = 2 - }; - }; - - private: - HorizontalMetricsTable(Header* header, ReadableFontData* data); - HorizontalMetricsTable(Header* header, ReadableFontData* data, - int32_t num_hmetrics, int32_t num_glyphs); - - public: // class is final, no virtual functions unless inherited from parent. - 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); - public: class Builder : public Table::TableBasedTableBuilder, public RefCounted { public: // Constructor scope altered to public because C++ does not allow base // class to instantiate derived class with protected constructors. - Builder(FontDataTableBuilderContainer* font_builder, Header* header, + Builder(FontDataTableBuilderContainer* font_builder, + Header* header, WritableFontData* data); - Builder(FontDataTableBuilderContainer* font_builder, Header* header, + Builder(FontDataTableBuilderContainer* font_builder, + Header* header, ReadableFontData* data); virtual ~Builder(); - void init(); - virtual CALLER_ATTACH FontDataTable* subBuildTable(ReadableFontData* data); - void setNumberOfHMetrics(int32_t num_hmetrics); - void setNumGlyphs(int32_t num_glyphs); + virtual CALLER_ATTACH FontDataTable* SubBuildTable(ReadableFontData* data); + void SetNumberOfHMetrics(int32_t num_hmetrics); + void SetNumGlyphs(int32_t num_glyphs); private: + void Init(); + 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); + private: + struct Offset { + enum { + // hMetrics + kHMetricsStart = 0, + kHMetricsSize = 4, + + // Offset within an hMetric + kHMetricsAdvanceWidth = 0, + kHMetricsLeftSideBearing = 2, + + kLeftSideBearingSize = 2 + }; + }; + + HorizontalMetricsTable(Header* header, ReadableFontData* data); + HorizontalMetricsTable(Header* header, + ReadableFontData* data, + int32_t num_hmetrics, + int32_t num_glyphs); + int32_t num_hmetrics_; int32_t num_glyphs_; }; diff --git a/sfntly/loca_table.cc b/sfntly/loca_table.cc index 1cd1d92..e82f709 100644 --- a/sfntly/loca_table.cc +++ b/sfntly/loca_table.cc @@ -21,20 +21,13 @@ namespace sfntly { /****************************************************************************** * LocaTable class ******************************************************************************/ -LocaTable::LocaTable(Header* header, ReadableFontData* data) - : Table(header, data) {} - -LocaTable::LocaTable(Header* header, ReadableFontData* data, int32_t version, - int32_t num_glyphs) - : Table(header, data), version_(version), num_glyphs_(num_glyphs) {} - LocaTable::~LocaTable() {} -int32_t LocaTable::numGlyphs() { +int32_t LocaTable::NumGlyphs() { return num_glyphs_; } -int32_t LocaTable::glyphOffset(int32_t glyph_id) { +int32_t LocaTable::GlyphOffset(int32_t glyph_id) { if (glyph_id < 0 || glyph_id >= num_glyphs_) { #if defined (SFNTLY_NO_EXCEPTION) return 0; @@ -42,10 +35,10 @@ int32_t LocaTable::glyphOffset(int32_t glyph_id) { throw IndexOutOfBoundException("Glyph ID is out of bounds."); #endif } - return loca(glyph_id); + return Loca(glyph_id); } -int32_t LocaTable::glyphLength(int32_t glyph_id) { +int32_t LocaTable::GlyphLength(int32_t glyph_id) { if (glyph_id < 0 || glyph_id >= num_glyphs_) { #if defined (SFNTLY_NO_EXCEPTION) return 0; @@ -53,14 +46,14 @@ int32_t LocaTable::glyphLength(int32_t glyph_id) { throw IndexOutOfBoundException("Glyph ID is out of bounds."); #endif } - return loca(glyph_id + 1) - loca(glyph_id); + return Loca(glyph_id + 1) - Loca(glyph_id); } -int32_t LocaTable::numLocas() { +int32_t LocaTable::NumLocas() { return num_glyphs_ + 1; } -int32_t LocaTable::loca(int32_t index) { +int32_t LocaTable::Loca(int32_t index) { if (index > num_glyphs_) { #if defined (SFNTLY_NO_EXCEPTION) return 0; @@ -69,92 +62,73 @@ int32_t LocaTable::loca(int32_t index) { #endif } if (version_ == IndexToLocFormat::kShortOffset) { - return 2 * data_->readShort(index * DataSize::kUSHORT); + return 2 * data_->ReadShort(index * DataSize::kUSHORT); } - return data_->readULongAsInt(index * DataSize::kULONG); + return data_->ReadULongAsInt(index * DataSize::kULONG); +} + +LocaTable::LocaTable(Header* header, ReadableFontData* data) + : Table(header, data) { +} + +LocaTable::LocaTable(Header* header, + ReadableFontData* data, + int32_t version, + int32_t num_glyphs) + : Table(header, data), version_(version), num_glyphs_(num_glyphs) { } /****************************************************************************** - * LocaTable::Builder class + * LocaTable::Iterator class ******************************************************************************/ -LocaTable::LocaIterator::LocaIterator(LocaTable* table) : index_(-1) { +LocaTable::LocaIterator::LocaIterator(LocaTable* table) + : index_(-1) { table_ = table; } -bool LocaTable::LocaIterator::hasNext() { +bool LocaTable::LocaIterator::HasNext() { return index_ <= table_->num_glyphs_; } -int32_t LocaTable::LocaIterator::next() { - return table_->loca(index_++); +int32_t LocaTable::LocaIterator::Next() { + return table_->Loca(index_++); } /****************************************************************************** * LocaTable::Builder class ******************************************************************************/ -void LocaTable::Builder::init() { - num_glyphs_ = -1; - format_version_ = IndexToLocFormat::kLongOffset; -} - LocaTable::Builder::Builder(FontDataTableBuilderContainer* font_builder, Header* header, WritableFontData* data) : Table::ArrayElementTableBuilder(font_builder, header, data) { - init(); + Init(); } LocaTable::Builder::Builder(FontDataTableBuilderContainer* font_builder, Header* header, ReadableFontData* data) : Table::ArrayElementTableBuilder(font_builder, header, data) { - init(); + Init(); } LocaTable::Builder::~Builder() {} -void LocaTable::Builder::initialize(ReadableFontData* data) { - if (data) { - if (numGlyphs() < 0) { -#if defined (SFNTLY_NO_EXCEPTION) - return; -#else - throw IllegalStateException("numglyphs not set on LocaTable Builder."); -#endif - } - LocaTablePtr table = - new LocaTable(header(), data, format_version_, num_glyphs_); - LocaTable::LocaIterator loca_iter(table); - while (loca_iter.hasNext()) { - loca_.push_back(loca_iter.next()); - } - } -} - -IntegerList* LocaTable::Builder::getLocaList() { - if (loca_.empty()) { - initialize(internalReadData()); - setModelChanged(); - } - return &loca_; -} - -void LocaTable::Builder::setFormatVersion(int32_t format_version) { +void LocaTable::Builder::SetFormatVersion(int32_t format_version) { format_version_ = format_version; } -IntegerList* LocaTable::Builder::locaList() { - return getLocaList(); +IntegerList* LocaTable::Builder::LocaList() { + return GetLocaList(); } -void LocaTable::Builder::setLocaList(IntegerList* list) { +void LocaTable::Builder::SetLocaList(IntegerList* list) { loca_.clear(); if (list) { loca_ = *list; num_glyphs_ = loca_.size(); - setModelChanged(); + set_model_changed(); } } -int32_t LocaTable::Builder::glyphOffset(int32_t glyph_id) { +int32_t LocaTable::Builder::GlyphOffset(int32_t glyph_id) { if (glyph_id < 0 || glyph_id > (num_glyphs_ + 1)) { #if defined (SFNTLY_NO_EXCEPTION) return 0; @@ -162,10 +136,10 @@ int32_t LocaTable::Builder::glyphOffset(int32_t glyph_id) { throw IndexOutOfBoundException("Glyph ID is out of bounds."); #endif } - return loca(glyph_id); + return Loca(glyph_id); } -int32_t LocaTable::Builder::glyphLength(int32_t glyph_id) { +int32_t LocaTable::Builder::GlyphLength(int32_t glyph_id) { if (glyph_id < 0 || glyph_id > (num_glyphs_ + 1)) { #if defined (SFNTLY_NO_EXCEPTION) return 0; @@ -173,49 +147,49 @@ int32_t LocaTable::Builder::glyphLength(int32_t glyph_id) { throw IndexOutOfBoundException("Glyph ID is out of bounds."); #endif } - return loca(glyph_id + 1) - loca(glyph_id); + return Loca(glyph_id + 1) - Loca(glyph_id); } -void LocaTable::Builder::setNumGlyphs(int32_t num_glyphs) { +void LocaTable::Builder::SetNumGlyphs(int32_t num_glyphs) { num_glyphs_ = num_glyphs; } -int32_t LocaTable::Builder::numGlyphs() { +int32_t LocaTable::Builder::NumGlyphs() { if (!loca_.empty()) { return loca_.size() - 1; } return num_glyphs_; } -void LocaTable::Builder::revert() { +void LocaTable::Builder::Revert() { loca_.clear(); - setModelChanged(false); + set_model_changed(false); } -void LocaTable::Builder::clear() { - getLocaList()->clear(); +void LocaTable::Builder::Clear() { + GetLocaList()->clear(); } -int32_t LocaTable::Builder::numLocas() { - return getLocaList()->size(); +int32_t LocaTable::Builder::NumLocas() { + return GetLocaList()->size(); } -int32_t LocaTable::Builder::loca(int32_t index) { - return getLocaList()->at(index); +int32_t LocaTable::Builder::Loca(int32_t index) { + return GetLocaList()->at(index); } -CALLER_ATTACH FontDataTable* LocaTable::Builder::subBuildTable( +CALLER_ATTACH FontDataTable* LocaTable::Builder::SubBuildTable( ReadableFontData* data) { FontDataTablePtr table = new LocaTable(header(), data, format_version_, num_glyphs_); - return table.detach(); + return table.Detach(); } -void LocaTable::Builder::subDataSet() { - initialize(internalReadData()); +void LocaTable::Builder::SubDataSet() { + Initialize(InternalReadData()); } -int32_t LocaTable::Builder::subDataSizeToSerialize() { +int32_t LocaTable::Builder::SubDataSizeToSerialize() { if (loca_.empty()) { return 0; } @@ -225,21 +199,52 @@ int32_t LocaTable::Builder::subDataSizeToSerialize() { return loca_.size() * DataSize::kUSHORT; } -bool LocaTable::Builder::subReadyToSerialize() { +bool LocaTable::Builder::SubReadyToSerialize() { return !loca_.empty(); } -int32_t LocaTable::Builder::subSerialize(WritableFontData* new_data) { +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); + size += new_data->WriteULong(size, *l); } else { - size += new_data->writeUShort(size, *l / 2); + size += new_data->WriteUShort(size, *l / 2); } } return 0; } +void LocaTable::Builder::Init() { + num_glyphs_ = -1; + format_version_ = IndexToLocFormat::kLongOffset; +} + +void LocaTable::Builder::Initialize(ReadableFontData* data) { + if (data) { + if (NumGlyphs() < 0) { +#if defined (SFNTLY_NO_EXCEPTION) + return; +#else + throw IllegalStateException("numglyphs not set on LocaTable Builder."); +#endif + } + LocaTablePtr table = + new LocaTable(header(), data, format_version_, num_glyphs_); + LocaTable::LocaIterator loca_iter(table); + while (loca_iter.HasNext()) { + loca_.push_back(loca_iter.Next()); + } + } +} + +IntegerList* LocaTable::Builder::GetLocaList() { + if (loca_.empty()) { + Initialize(InternalReadData()); + set_model_changed(); + } + return &loca_; +} + } // namespace sfntly diff --git a/sfntly/loca_table.h b/sfntly/loca_table.h index 741cb56..dcf9715 100644 --- a/sfntly/loca_table.h +++ b/sfntly/loca_table.h @@ -23,50 +23,19 @@ namespace sfntly { class LocaTable : public Table, public RefCounted { - private: - LocaTable(Header* header, ReadableFontData* data); - LocaTable(Header* header, ReadableFontData* data, int32_t version, - int32_t num_glyphs); - - public: // class is final, no virtual unless inherited from parents. - virtual ~LocaTable(); - int32_t numGlyphs(); - - // 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); - public: // Note: different implementation than Java, caller to instantiate this class // object directly from stack instead of calling LocaTable::iterator(). class LocaIterator { public: explicit LocaIterator(LocaTable* table); - bool hasNext(); - int32_t next(); + bool HasNext(); + int32_t Next(); private: int32_t index_; LocaTable* table_; // use dumb pointer since it's a composition object }; - friend class LocaIterator; class Builder : public Table::ArrayElementTableBuilder, public RefCounted { @@ -78,21 +47,15 @@ class LocaTable : public Table, public RefCounted { ReadableFontData* data); virtual ~Builder(); - private: - void init(); // short hand for common code in ctors, C++ port only - void initialize(ReadableFontData* data); // ported from Java - IntegerList* getLocaList(); - - public: // static class, no virtual function unless inherited from parent. - void setFormatVersion(int32_t format_version); + void SetFormatVersion(int32_t format_version); // 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. // 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(); - void setLocaList(IntegerList* list); + IntegerList* LocaList(); + 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 @@ -101,43 +64,79 @@ class LocaTable : public Table, public RefCounted { // @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); + 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); + 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. - void setNumGlyphs(int32_t num_glyphs); - int numGlyphs(); + void SetNumGlyphs(int32_t num_glyphs); + int NumGlyphs(); - void revert(); - void clear(); + void Revert(); + void Clear(); // 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(); - int32_t loca(int32_t index); + int32_t NumLocas(); + 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); + 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 Init(); // short hand for common code in ctors, C++ port only + void Initialize(ReadableFontData* data); // ported from Java + IntegerList* GetLocaList(); + int32_t format_version_; // Note: IndexToLocFormat int32_t num_glyphs_; IntegerList loca_; }; + virtual ~LocaTable(); + int32_t NumGlyphs(); + + // 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); + LocaTable(Header* header, + ReadableFontData* data, + int32_t version, + int32_t num_glyphs); + int32_t version_; // Note: IndexToLocFormat int32_t num_glyphs_; + + friend class LocaIterator; }; typedef Ptr LocaTablePtr; typedef Ptr LocaTableBuilderPtr; diff --git a/sfntly/math/fixed1616.h b/sfntly/math/fixed1616.h index aa3a62b..843da51 100644 --- a/sfntly/math/fixed1616.h +++ b/sfntly/math/fixed1616.h @@ -23,15 +23,15 @@ namespace sfntly { class Fixed1616 { public: - static inline int32_t integral(int32_t fixed) { + static inline int32_t Integral(int32_t fixed) { return (fixed >> 16); } - static inline int32_t fractional(int32_t fixed) { + static inline int32_t Fractional(int32_t fixed) { return (fixed & 0xffff); } - static inline int32_t fixed(int32_t integral, int32_t fractional) { + static inline int32_t Fixed(int32_t integral, int32_t fractional) { return ((integral & 0xffff) << 16) | (fractional & 0xffff); } }; diff --git a/sfntly/math/font_math.h b/sfntly/math/font_math.h index 78b9e51..f15a786 100644 --- a/sfntly/math/font_math.h +++ b/sfntly/math/font_math.h @@ -23,7 +23,7 @@ namespace sfntly { class FontMath { public: - static int32_t log2(int32_t a) { + static int32_t Log2(int32_t a) { int r = 0; // r will be lg(a) while (a != 0) { a >>= 1; diff --git a/sfntly/maximum_profile_table.cc b/sfntly/maximum_profile_table.cc index 61a176e..0ab2aaf 100644 --- a/sfntly/maximum_profile_table.cc +++ b/sfntly/maximum_profile_table.cc @@ -20,202 +20,204 @@ namespace sfntly { /****************************************************************************** * MaximumProfileTable class ******************************************************************************/ -MaximumProfileTable::MaximumProfileTable(Header* header, - ReadableFontData* data) : - Table(header, data) { -} - MaximumProfileTable::~MaximumProfileTable() {} -int32_t MaximumProfileTable::version() { - return data_->readFixed(Offset::kVersion); +int32_t MaximumProfileTable::Version() { + return data_->ReadFixed(Offset::kVersion); } -int32_t MaximumProfileTable::numGlyphs() { - return data_->readUShort(Offset::kNumGlyphs); +int32_t MaximumProfileTable::NumGlyphs() { + return data_->ReadUShort(Offset::kNumGlyphs); } -int32_t MaximumProfileTable::maxPoints() { - return data_->readUShort(Offset::kMaxPoints); +int32_t MaximumProfileTable::MaxPoints() { + return data_->ReadUShort(Offset::kMaxPoints); } -int32_t MaximumProfileTable::maxContours() { - return data_->readUShort(Offset::kMaxContours); +int32_t MaximumProfileTable::MaxContours() { + return data_->ReadUShort(Offset::kMaxContours); } -int32_t MaximumProfileTable::maxCompositePoints() { - return data_->readUShort(Offset::kMaxCompositePoints); +int32_t MaximumProfileTable::MaxCompositePoints() { + return data_->ReadUShort(Offset::kMaxCompositePoints); } -int32_t MaximumProfileTable::maxZones() { - return data_->readUShort(Offset::kMaxZones); +int32_t MaximumProfileTable::MaxZones() { + return data_->ReadUShort(Offset::kMaxZones); } -int32_t MaximumProfileTable::maxTwilightPoints() { - return data_->readUShort(Offset::kMaxTwilightPoints); +int32_t MaximumProfileTable::MaxTwilightPoints() { + return data_->ReadUShort(Offset::kMaxTwilightPoints); } -int32_t MaximumProfileTable::maxStorage() { - return data_->readUShort(Offset::kMaxStorage); +int32_t MaximumProfileTable::MaxStorage() { + return data_->ReadUShort(Offset::kMaxStorage); } -int32_t MaximumProfileTable::maxFunctionDefs() { - return data_->readUShort(Offset::kMaxFunctionDefs); +int32_t MaximumProfileTable::MaxFunctionDefs() { + return data_->ReadUShort(Offset::kMaxFunctionDefs); } -int32_t MaximumProfileTable::maxStackElements() { - return data_->readUShort(Offset::kMaxStackElements); +int32_t MaximumProfileTable::MaxStackElements() { + return data_->ReadUShort(Offset::kMaxStackElements); } -int32_t MaximumProfileTable::maxSizeOfInstructions() { - return data_->readUShort(Offset::kMaxSizeOfInstructions); +int32_t MaximumProfileTable::MaxSizeOfInstructions() { + return data_->ReadUShort(Offset::kMaxSizeOfInstructions); } -int32_t MaximumProfileTable::maxComponentElements() { - return data_->readUShort(Offset::kMaxComponentElements); +int32_t MaximumProfileTable::MaxComponentElements() { + return data_->ReadUShort(Offset::kMaxComponentElements); } -int32_t MaximumProfileTable::maxComponentDepth() { - return data_->readUShort(Offset::kMaxComponentDepth); +int32_t MaximumProfileTable::MaxComponentDepth() { + return data_->ReadUShort(Offset::kMaxComponentDepth); +} + +MaximumProfileTable::MaximumProfileTable(Header* header, + ReadableFontData* data) + : Table(header, data) { } /****************************************************************************** * MaximumProfileTable::Builder class ******************************************************************************/ MaximumProfileTable::Builder::Builder( - FontDataTableBuilderContainer* font_builder, Header* header, - WritableFontData* data) : - Table::TableBasedTableBuilder(font_builder, header, data) { + FontDataTableBuilderContainer* font_builder, + Header* header, + WritableFontData* data) + : Table::TableBasedTableBuilder(font_builder, header, data) { } MaximumProfileTable::Builder::Builder( - FontDataTableBuilderContainer* font_builder, Header* header, - ReadableFontData* data) : - Table::TableBasedTableBuilder(font_builder, header, data) { + FontDataTableBuilderContainer* font_builder, + Header* header, + ReadableFontData* data) + : Table::TableBasedTableBuilder(font_builder, header, data) { } MaximumProfileTable::Builder::~Builder() {} -CALLER_ATTACH FontDataTable* MaximumProfileTable::Builder::subBuildTable( - ReadableFontData* data) { +CALLER_ATTACH FontDataTable* + MaximumProfileTable::Builder::SubBuildTable(ReadableFontData* data) { FontDataTablePtr table = new MaximumProfileTable(header(), data); - return table.detach(); + return table.Detach(); } -int32_t MaximumProfileTable::Builder::version() { - return internalReadData()->readUShort(Offset::kVersion); +int32_t MaximumProfileTable::Builder::Version() { + return InternalReadData()->ReadUShort(Offset::kVersion); } -void MaximumProfileTable::Builder::setVersion(int32_t version) { - internalWriteData()->writeUShort(Offset::kVersion, version); +void MaximumProfileTable::Builder::SetVersion(int32_t version) { + InternalWriteData()->WriteUShort(Offset::kVersion, version); } -int32_t MaximumProfileTable::Builder::numGlyphs() { - return internalReadData()->readUShort(Offset::kNumGlyphs); +int32_t MaximumProfileTable::Builder::NumGlyphs() { + return InternalReadData()->ReadUShort(Offset::kNumGlyphs); } -void MaximumProfileTable::Builder::setNumGlyphs(int32_t num_glyphs) { - internalWriteData()->writeUShort(Offset::kNumGlyphs, num_glyphs); +void MaximumProfileTable::Builder::SetNumGlyphs(int32_t num_glyphs) { + InternalWriteData()->WriteUShort(Offset::kNumGlyphs, num_glyphs); } -int32_t MaximumProfileTable::Builder::maxPoints() { - return internalReadData()->readUShort(Offset::kMaxPoints); +int32_t MaximumProfileTable::Builder::MaxPoints() { + return InternalReadData()->ReadUShort(Offset::kMaxPoints); } -void MaximumProfileTable::Builder::setMaxPoints(int32_t max_points) { - internalWriteData()->writeUShort(Offset::kMaxPoints, max_points); +void MaximumProfileTable::Builder::SetMaxPoints(int32_t max_points) { + InternalWriteData()->WriteUShort(Offset::kMaxPoints, max_points); } -int32_t MaximumProfileTable::Builder::maxContours() { - return internalReadData()->readUShort(Offset::kMaxContours); +int32_t MaximumProfileTable::Builder::MaxContours() { + return InternalReadData()->ReadUShort(Offset::kMaxContours); } -void MaximumProfileTable::Builder::setMaxContours(int32_t max_contours) { - internalWriteData()->writeUShort(Offset::kMaxContours, max_contours); +void MaximumProfileTable::Builder::SetMaxContours(int32_t max_contours) { + InternalWriteData()->WriteUShort(Offset::kMaxContours, max_contours); } -int32_t MaximumProfileTable::Builder::maxCompositePoints() { - return internalReadData()->readUShort(Offset::kMaxCompositePoints); +int32_t MaximumProfileTable::Builder::MaxCompositePoints() { + return InternalReadData()->ReadUShort(Offset::kMaxCompositePoints); } -void MaximumProfileTable::Builder::setMaxCompositePoints( +void MaximumProfileTable::Builder::SetMaxCompositePoints( int32_t max_composite_points) { - internalWriteData()->writeUShort(Offset::kMaxCompositePoints, + InternalWriteData()->WriteUShort(Offset::kMaxCompositePoints, max_composite_points); } -int32_t MaximumProfileTable::Builder::maxZones() { - return internalReadData()->readUShort(Offset::kMaxZones); +int32_t MaximumProfileTable::Builder::MaxZones() { + return InternalReadData()->ReadUShort(Offset::kMaxZones); } -void MaximumProfileTable::Builder::setMaxZones(int32_t max_zones) { - internalWriteData()->writeUShort(Offset::kMaxZones, max_zones); +void MaximumProfileTable::Builder::SetMaxZones(int32_t max_zones) { + InternalWriteData()->WriteUShort(Offset::kMaxZones, max_zones); } -int32_t MaximumProfileTable::Builder::maxTwilightPoints() { - return internalReadData()->readUShort(Offset::kMaxTwilightPoints); +int32_t MaximumProfileTable::Builder::MaxTwilightPoints() { + return InternalReadData()->ReadUShort(Offset::kMaxTwilightPoints); } -void MaximumProfileTable::Builder::setMaxTwilightPoints( +void MaximumProfileTable::Builder::SetMaxTwilightPoints( int32_t max_twilight_points) { - internalWriteData()->writeUShort(Offset::kMaxTwilightPoints, + InternalWriteData()->WriteUShort(Offset::kMaxTwilightPoints, max_twilight_points); } -int32_t MaximumProfileTable::Builder::maxStorage() { - return internalReadData()->readUShort(Offset::kMaxStorage); +int32_t MaximumProfileTable::Builder::MaxStorage() { + return InternalReadData()->ReadUShort(Offset::kMaxStorage); } -void MaximumProfileTable::Builder::setMaxStorage(int32_t max_storage) { - internalWriteData()->writeUShort(Offset::kMaxStorage, max_storage); +void MaximumProfileTable::Builder::SetMaxStorage(int32_t max_storage) { + InternalWriteData()->WriteUShort(Offset::kMaxStorage, max_storage); } -int32_t MaximumProfileTable::Builder::maxFunctionDefs() { - return internalReadData()->readUShort(Offset::kMaxFunctionDefs); +int32_t MaximumProfileTable::Builder::MaxFunctionDefs() { + return InternalReadData()->ReadUShort(Offset::kMaxFunctionDefs); } -void MaximumProfileTable::Builder::setMaxFunctionDefs( +void MaximumProfileTable::Builder::SetMaxFunctionDefs( int32_t max_function_defs) { - internalWriteData()->writeUShort(Offset::kMaxFunctionDefs, max_function_defs); + InternalWriteData()->WriteUShort(Offset::kMaxFunctionDefs, max_function_defs); } -int32_t MaximumProfileTable::Builder::maxStackElements() { - return internalReadData()->readUShort(Offset::kMaxStackElements); +int32_t MaximumProfileTable::Builder::MaxStackElements() { + return InternalReadData()->ReadUShort(Offset::kMaxStackElements); } -void MaximumProfileTable::Builder::setMaxStackElements( +void MaximumProfileTable::Builder::SetMaxStackElements( int32_t max_stack_elements) { - internalWriteData()->writeUShort(Offset::kMaxStackElements, + InternalWriteData()->WriteUShort(Offset::kMaxStackElements, max_stack_elements); } -int32_t MaximumProfileTable::Builder::maxSizeOfInstructions() { - return internalReadData()->readUShort(Offset::kMaxSizeOfInstructions); +int32_t MaximumProfileTable::Builder::MaxSizeOfInstructions() { + return InternalReadData()->ReadUShort(Offset::kMaxSizeOfInstructions); } -void MaximumProfileTable::Builder::setMaxSizeOfInstructions( +void MaximumProfileTable::Builder::SetMaxSizeOfInstructions( int32_t max_size_of_instructions) { - internalWriteData()->writeUShort(Offset::kMaxSizeOfInstructions, + InternalWriteData()->WriteUShort(Offset::kMaxSizeOfInstructions, max_size_of_instructions); } -int32_t MaximumProfileTable::Builder::maxComponentElements() { - return internalReadData()->readUShort(Offset::kMaxComponentElements); +int32_t MaximumProfileTable::Builder::MaxComponentElements() { + return InternalReadData()->ReadUShort(Offset::kMaxComponentElements); } -void MaximumProfileTable::Builder::setMaxComponentElements( +void MaximumProfileTable::Builder::SetMaxComponentElements( int32_t max_component_elements) { - internalWriteData()->writeUShort(Offset::kMaxComponentElements, + InternalWriteData()->WriteUShort(Offset::kMaxComponentElements, max_component_elements); } -int32_t MaximumProfileTable::Builder::maxComponentDepth() { - return internalReadData()->readUShort(Offset::kMaxComponentDepth); +int32_t MaximumProfileTable::Builder::MaxComponentDepth() { + return InternalReadData()->ReadUShort(Offset::kMaxComponentDepth); } -void MaximumProfileTable::Builder::setMaxComponentDepth( +void MaximumProfileTable::Builder::SetMaxComponentDepth( int32_t max_component_depth) { - internalWriteData()->writeUShort(Offset::kMaxComponentDepth, + InternalWriteData()->WriteUShort(Offset::kMaxComponentDepth, max_component_depth); } diff --git a/sfntly/maximum_profile_table.h b/sfntly/maximum_profile_table.h index 044eccf..9e0d0a6 100644 --- a/sfntly/maximum_profile_table.h +++ b/sfntly/maximum_profile_table.h @@ -24,6 +24,63 @@ namespace sfntly { class MaximumProfileTable : public Table, public RefCounted { + public: + class Builder : public Table::TableBasedTableBuilder, + public RefCounted { + public: + // Constructor scope altered to public because C++ does not allow base + // class to instantiate derived class with protected constructors. + Builder(FontDataTableBuilderContainer* font_builder, Header* header, + WritableFontData* data); + Builder(FontDataTableBuilderContainer* font_builder, Header* header, + ReadableFontData* data); + virtual ~Builder(); + + virtual CALLER_ATTACH FontDataTable* SubBuildTable(ReadableFontData* data); + + int32_t Version(); + void SetVersion(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 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 Version(); + int32_t NumGlyphs(); + int32_t MaxPoints(); + int32_t MaxContours(); + int32_t MaxCompositePoints(); + 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 { @@ -48,67 +105,7 @@ class MaximumProfileTable : public Table, }; }; - private: MaximumProfileTable(Header* header, ReadableFontData* data); - - public: // Class is final, no virtual functions unless derived from parent. - virtual ~MaximumProfileTable(); - int32_t version(); - int32_t numGlyphs(); - int32_t maxPoints(); - int32_t maxContours(); - int32_t maxCompositePoints(); - int32_t maxZones(); - int32_t maxTwilightPoints(); - int32_t maxStorage(); - int32_t maxFunctionDefs(); - int32_t maxStackElements(); - int32_t maxSizeOfInstructions(); - int32_t maxComponentElements(); - int32_t maxComponentDepth(); - - public: - class Builder : public Table::TableBasedTableBuilder, - public RefCounted { - public: - // Constructor scope altered to public because C++ does not allow base - // class to instantiate derived class with protected constructors. - Builder(FontDataTableBuilderContainer* font_builder, Header* header, - WritableFontData* data); - Builder(FontDataTableBuilderContainer* font_builder, Header* header, - ReadableFontData* data); - virtual ~Builder(); - - virtual CALLER_ATTACH FontDataTable* subBuildTable(ReadableFontData* data); - - public: // Class is static, no virtual functions unless derived from parent. - int32_t version(); - void setVersion(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 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); - }; }; typedef Ptr MaximumProfileTablePtr; typedef Ptr MaximumProfileTableBuilderPtr; diff --git a/sfntly/name_table.cc b/sfntly/name_table.cc index 0858603..19c299c 100644 --- a/sfntly/name_table.cc +++ b/sfntly/name_table.cc @@ -14,321 +14,43 @@ * limitations under the License. */ -#include "port/type.h" +#include "sfntly/name_table.h" #include #include #include -#include "sfntly/name_table.h" #include "sfntly/font.h" #include "sfntly/port/exception_type.h" namespace sfntly { -/****************************************************************************** - * NameTable class - ******************************************************************************/ -NameTable::NameTable(Header* header, ReadableFontData* data) - : Table(header, data) {} - -NameTable::~NameTable() {} - -int32_t NameTable::format() { - return data_->readUShort(Offset::kFormat); -} - -int32_t NameTable::nameCount() { - return data_->readUShort(Offset::kCount); -} - -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::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)); -} - -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(); -} - -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, 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(nameEntry(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(int 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(nameEntry(platform_id, encoding_id, language_id, name_id)); - if (entry) { - return entry->name(); - } - return NULL; -} - -CALLER_ATTACH NameTable::NameEntry* NameTable::nameEntry(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::nameEntry(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); - NameTable::NameEntryIterator* name_entry_iter = iterator(&filter); - NameEntryPtr result; - if (name_entry_iter->hasNext()) { - result = name_entry_iter->next(); - delete name_entry_iter; - return result; - } - delete name_entry_iter; - return NULL; -} - -NameTable::NameEntryIterator* NameTable::iterator() { - return new NameTable::NameEntryIterator(this); -} - -NameTable::NameEntryIterator* NameTable::iterator(NameEntryFilter* filter) { - return new NameTable::NameEntryIterator(this, filter); -} - -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: // 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; -} - /****************************************************************************** * NameTable::NameEntryId class ******************************************************************************/ NameTable::NameEntryId::NameEntryId() - : platform_id_(0), encoding_id_(0), language_id_(0), name_id_(0) { + : 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(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; } -NameTable::NameEntryId::~NameEntryId() {} - -int32_t NameTable::NameEntryId::getPlatformId() const { - return platform_id_; -} - -int32_t NameTable::NameEntryId::getEncodingId() const { - return encoding_id_; -} - -int32_t NameTable::NameEntryId::getLanguageId() const { - return language_id_; -} - -int32_t NameTable::NameEntryId::getNameId() const { - return name_id_; -} - -const NameTable::NameEntryId& NameTable::NameEntryId::operator=( - const NameTable::NameEntryId& rhs) const { +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_; @@ -337,8 +59,10 @@ const NameTable::NameEntryId& NameTable::NameEntryId::operator=( } 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_; + 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 { @@ -351,66 +75,41 @@ bool NameTable::NameEntryId::operator<(const NameEntryId& rhs) const { /****************************************************************************** * NameTable::NameEntry class ******************************************************************************/ -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::NameEntry::NameEntry() { - init(0, 0, 0, 0, NULL); + Init(0, 0, 0, 0, NULL); } NameTable::NameEntry::NameEntry(const NameEntryId& name_entry_id, const ByteVector& name_bytes) { - init(name_entry_id.getPlatformId(), name_entry_id.getEncodingId(), - name_entry_id.getLanguageId(), name_entry_id.getNameId(), &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, +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); + Init(platform_id, encoding_id, language_id, name_id, &name_bytes); } NameTable::NameEntry::~NameEntry() {} -NameTable::NameEntryId& NameTable::NameEntry::getNameEntryId() { - return name_entry_id_; -} - -int32_t NameTable::NameEntry::platformId() { - return name_entry_id_.getPlatformId(); -} - -int32_t NameTable::NameEntry::encodingId() { - return name_entry_id_.getEncodingId(); -} - -int32_t NameTable::NameEntry::languageId() { - return name_entry_id_.getLanguageId(); -} - -int32_t NameTable::NameEntry::nameId() { - return name_entry_id_.getNameId(); +ByteVector* NameTable::NameEntry::NameAsBytes() { + return &name_bytes_; } -int32_t NameTable::NameEntry::nameBytesLength() { +int32_t NameTable::NameEntry::NameBytesLength() { return name_bytes_.size(); } -ByteVector* NameTable::NameEntry::nameAsBytes() { - return &name_bytes_; -} - -UChar* NameTable::NameEntry::name() { - return NameTable::convertFromNameBytes(&name_bytes_, platformId(), - encodingId()); +UChar* NameTable::NameEntry::Name() { + return NameTable::ConvertFromNameBytes(&name_bytes_, + platform_id(), + encoding_id()); } bool NameTable::NameEntry::operator==(const NameEntry& rhs) const { @@ -418,203 +117,219 @@ bool NameTable::NameEntry::operator==(const NameEntry& rhs) const { 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); + Init(0, 0, 0, 0, NULL); } NameTable::NameEntryBuilder::NameEntryBuilder( const NameEntryId& name_entry_id, const ByteVector& name_bytes) { - init(name_entry_id.getPlatformId(), name_entry_id.getEncodingId(), - name_entry_id.getLanguageId(), name_entry_id.getNameId(), &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.getPlatformId(), name_entry_id.getEncodingId(), - name_entry_id.getLanguageId(), name_entry_id.getNameId(), NULL); + 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->platformId(), b->encodingId(), b->languageId(), b->nameId(), - b->nameAsBytes()); + 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) { +void NameTable::NameEntryBuilder::SetName(const UChar* name) { if (name == NULL) { name_entry_->name_bytes_.clear(); return; } - NameTable::convertToNameBytes(name, name_entry_->platformId(), - name_entry_->encodingId(), + NameTable::ConvertToNameBytes(name, + name_entry_->platform_id(), + name_entry_->encoding_id(), &name_entry_->name_bytes_); } -void NameTable::NameEntryBuilder::setName(const ByteVector& name_bytes) { +void NameTable::NameEntryBuilder::SetName(const ByteVector& name_bytes) { name_entry_->name_bytes_.clear(); - std::copy(name_bytes.begin(), name_bytes.end(), + 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) { +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, + std::copy(name_bytes.begin() + offset, + name_bytes.begin() + offset + length, name_entry_->name_bytes_.begin()); } -CALLER_ATTACH NameTable::NameEntry* NameTable::NameEntryBuilder::entry() { - return name_entry_; -} - -void NameTable::NameEntryBuilder::init(int32_t platform_id, int32_t encoding_id, - int32_t language_id, int32_t name_id, const ByteVector* name_bytes) { +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); + 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) { + 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); +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 ******************************************************************************/ -void NameTable::NameEntryIterator::init(NameTable* table, - NameEntryFilter* filter) { - table_ = table; - filter_ = filter; - name_index_ = 0; -} - NameTable::NameEntryIterator::NameEntryIterator(NameTable* table) { - init(table, NULL); + Init(table, NULL); } NameTable::NameEntryIterator::NameEntryIterator(NameTable* table, NameEntryFilter* filter) { - init(table, filter); -} - -NameTable::NameEntryIterator::~NameEntryIterator() { + Init(table, filter); } -bool NameTable::NameEntryIterator::hasNext() { +bool NameTable::NameEntryIterator::HasNext() { if (!filter_) { - if (name_index_ < table_->nameCount()) { + if (name_index_ < table_->NameCount()) { return true; } return false; } - for (; name_index_ < table_->nameCount(); ++name_index_) { - if (filter_->accept(table_->platformId(name_index_), - table_->encodingId(name_index_), - table_->languageId(name_index_), - table_->nameId(name_index_))) { + for (; name_index_ < table_->NameCount(); ++name_index_) { + if (filter_->Accept(table_->PlatformId(name_index_), + table_->EncodingId(name_index_), + table_->LanguageId(name_index_), + table_->NameId(name_index_))) { return true; } } return false; } -CALLER_ATTACH NameTable::NameEntry* NameTable::NameEntryIterator::next() { - if (!hasNext()) +CALLER_ATTACH NameTable::NameEntry* NameTable::NameEntryIterator::Next() { + if (!HasNext()) return NULL; - return table_->nameEntry(name_index_++); + return table_->GetNameEntry(name_index_++); } -void NameTable::NameEntryIterator::remove() { +void NameTable::NameEntryIterator::Remove() { #if !defined (SFNTLY_NO_EXCEPTION) throw UnsupportedOperationException( "Cannot remove a CMap table from an existing font."); #endif } +void NameTable::NameEntryIterator::Init(NameTable* table, + NameEntryFilter* filter) { + table_ = table; + filter_ = filter; + name_index_ = 0; +} + /****************************************************************************** * NameTable::Builder class ******************************************************************************/ NameTable::Builder::Builder(FontDataTableBuilderContainer* font_builder, - Header* header, WritableFontData* data) : - Table::ArrayElementTableBuilder(font_builder, header, data) { + Header* header, + WritableFontData* data) + : Table::ArrayElementTableBuilder(font_builder, header, data) { } NameTable::Builder::Builder(FontDataTableBuilderContainer* font_builder, - Header* header, ReadableFontData* data) : - Table::ArrayElementTableBuilder(font_builder, header, data) { -} - -void NameTable::Builder::initialize(ReadableFontData* data) { - if (data) { - NameTablePtr table = new NameTable(header(), data); - NameEntryIterator name_iter(table, NULL); - while (name_iter.hasNext()) { - NameEntryPtr name_entry = name_iter.next(); - NameEntryBuilderPtr name_entry_builder = new NameEntryBuilder(name_entry); - NameEntry* builder_entry = name_entry_builder->entry(); - NameEntryId probe = builder_entry->getNameEntryId(); - name_entry_map_[probe] = name_entry_builder; - } - } + Header* header, + ReadableFontData* data) + : Table::ArrayElementTableBuilder(font_builder, header, data) { } -NameTable::NameEntryBuilderMap* NameTable::Builder::getNameBuilders() { - if (name_entry_map_.empty()) { - initialize(internalReadData()); - } - setModelChanged(); - return &name_entry_map_; -} - -void NameTable::Builder::revertNames() { +void NameTable::Builder::RevertNames() { name_entry_map_.clear(); - setModelChanged(false); + set_model_changed(false); } -int32_t NameTable::Builder::builderCount() { - getNameBuilders(); // ensure name_entry_map_ is built +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) { +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 + 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) { +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 + 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(); + return builder.Detach(); } -bool NameTable::Builder::remove(int32_t platform_id, int32_t encoding_id, - int32_t language_id, int32_t name_id) { +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 + 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); @@ -623,47 +338,47 @@ bool NameTable::Builder::remove(int32_t platform_id, int32_t encoding_id, return false; } -CALLER_ATTACH FontDataTable* NameTable::Builder::subBuildTable( - ReadableFontData* data) { +CALLER_ATTACH FontDataTable* + NameTable::Builder::SubBuildTable(ReadableFontData* data) { FontDataTablePtr table = new NameTable(header(), data); - return table.detach(); + return table.Detach(); } -void NameTable::Builder::subDataSet() { +void NameTable::Builder::SubDataSet() { name_entry_map_.clear(); - setModelChanged(false); + set_model_changed(false); } -int32_t NameTable::Builder::subDataSizeToSerialize() { +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; + 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->entry(); - size += entry->nameBytesLength(); + NameEntry* entry = p->name_entry(); + size += entry->NameBytesLength(); } return size; } -bool NameTable::Builder::subReadyToSerialize() { +bool NameTable::Builder::SubReadyToSerialize() { return !name_entry_map_.empty(); } -int32_t NameTable::Builder::subSerialize(WritableFontData* new_data) { +int32_t NameTable::Builder::SubSerialize(WritableFontData* new_data) { int32_t string_table_start_offset = - NameTable::Offset::kNameRecordStart + name_entry_map_.size() * - NameTable::Offset::kNameRecordSize; + 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, + // 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; @@ -673,32 +388,334 @@ int32_t NameTable::Builder::subSerialize(WritableFontData* new_data) { for (NameEntryBuilderMap::iterator b = name_entry_map_.begin(), end = name_entry_map_.end(); b != end; ++b) { - new_data->writeUShort( + new_data->WriteUShort( name_record_offset + NameTable::Offset::kNameRecordPlatformId, - b->first.getPlatformId()); - new_data->writeUShort( + b->first.platform_id()); + new_data->WriteUShort( name_record_offset + NameTable::Offset::kNameRecordEncodingId, - b->first.getEncodingId()); - new_data->writeUShort( + b->first.encoding_id()); + new_data->WriteUShort( name_record_offset + NameTable::Offset::kNameRecordLanguageId, - b->first.getLanguageId()); - new_data->writeUShort( + b->first.language_id()); + new_data->WriteUShort( name_record_offset + NameTable::Offset::kNameRecordNameId, - b->first.getNameId()); - NameEntry* builder_entry = b->second->entry(); - new_data->writeUShort( + 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( + 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 += new_data->WriteBytes( string_offset + string_table_start_offset, - builder_entry->nameAsBytes()); + builder_entry->NameAsBytes()); } return string_offset + string_table_start_offset; } +void NameTable::Builder::Initialize(ReadableFontData* data) { + if (data) { + NameTablePtr table = new NameTable(header(), data); + NameEntryIterator name_iter(table, NULL); + while (name_iter.HasNext()) { + NameEntryPtr name_entry = 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, 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(int 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); + NameTable::NameEntryIterator* name_entry_iter = Iterator(&filter); + NameEntryPtr result; + if (name_entry_iter->HasNext()) { + result = name_entry_iter->Next(); + } + delete name_entry_iter; + return result; +} + +NameTable::NameEntryIterator* NameTable::Iterator() { + return new NameTable::NameEntryIterator(this); +} + +NameTable::NameEntryIterator* NameTable::Iterator(NameEntryFilter* filter) { + return new NameTable::NameEntryIterator(this, filter); +} + +NameTable::NameTable(Header* header, ReadableFontData* data) + : Table(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/sfntly/name_table.h b/sfntly/name_table.h index 6d5df2b..d0dd345 100644 --- a/sfntly/name_table.h +++ b/sfntly/name_table.h @@ -34,6 +34,10 @@ 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, @@ -63,6 +67,7 @@ struct NameId { }; }; +// Unicode language IDs used in Name Records. struct UnicodeLanguageId { enum { kUnknown = -1, @@ -408,120 +413,36 @@ struct WindowsLanguageId { }; class NameTable : public Table, public RefCounted { - 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 - }; - }; - - NameTable(Header* header, ReadableFontData* data); - - public: - virtual ~NameTable(); - virtual int32_t format(); - - // Get the number of names in the name table. - virtual int32_t nameCount(); - - private: - // 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); - - public: - // 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); - - private: - // 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); - public: - // 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(int 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); + // 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() {} - class NameEntry; - virtual CALLER_ATTACH NameEntry* nameEntry(int32_t index); - virtual CALLER_ATTACH NameEntry* nameEntry(int32_t platform_id, - int32_t encoding_id, int32_t language_id, int32_t name_id); + 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_; } - // Note: Not implemented in C++ port due to complexity and low usage. - // virtual void names(std::set*); + const NameEntryId& operator=(const NameEntryId& rhs) const; + bool operator==(const NameEntryId& rhs) const; + bool operator<(const NameEntryId& rhs) const; - class NameEntryId { - protected: + private: mutable int32_t platform_id_; mutable int32_t encoding_id_; mutable int32_t language_id_; mutable int32_t name_id_; - - 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&); - virtual ~NameEntryId(); - virtual int32_t getPlatformId() const; - virtual int32_t getEncodingId() const; - virtual int32_t getLanguageId() const; - virtual int32_t getNameId() const; - virtual const NameEntryId& operator=(const NameEntryId& rhs) const; - virtual bool operator==(const NameEntryId& rhs) const; - virtual bool operator<(const NameEntryId& rhs) const; }; - // Class to represent a name entry in the name table. class NameEntryBuilder; + + // Class to represent a name entry in the name table. class NameEntry : public RefCounted { public: NameEntry(); @@ -529,18 +450,27 @@ class NameTable : public Table, public RefCounted { NameEntry(int32_t platform_id, int32_t encoding_id, int32_t language_id, int32_t name_id, const ByteVector& name_bytes); virtual ~NameEntry(); - virtual NameEntryId& getNameEntryId(); - virtual int32_t platformId(); - virtual int32_t encodingId(); - virtual int32_t languageId(); - virtual int32_t nameId(); - virtual int32_t nameBytesLength(); // C++ port only - virtual ByteVector* nameAsBytes(); - virtual UChar* name(); - virtual bool operator==(const NameEntry& rhs) const; + + 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; private: - void init(int32_t platform_id, int32_t encoding_id, int32_t language_id, + 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_; @@ -550,8 +480,9 @@ class NameTable : public Table, public RefCounted { friend class NameEntryBuilder; }; - // C++ port: we don't use original Java hierarchy to avoid ref count issues - // and nasty protected members. + // 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(); @@ -561,39 +492,44 @@ class NameTable : public Table, public RefCounted { 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, + 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 member functions. CALLER_ATTACH is not added because the - // lifetime shall be controlled by build, therefore the caller shall not - // increase the ref count. - NameEntry* entry(); + // 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, + 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, + 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 + // 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, + + virtual bool Accept(int32_t platform_id, int32_t encoding_id, int32_t language_id, int32_t name_id); private: @@ -603,40 +539,28 @@ class NameTable : public Table, public RefCounted { int32_t name_id_; }; + // Mimic Java's iterator to iterate through the entries within the name table. class NameEntryIterator { public: // If filter is NULL, filter through all tables. explicit NameEntryIterator(NameTable* table); NameEntryIterator(NameTable* table, NameEntryFilter* filter); // Make gcc -Wnon-virtual-dtor happy. - virtual ~NameEntryIterator(); - virtual bool hasNext(); - virtual CALLER_ATTACH NameEntry* next(); - virtual void remove(); + virtual ~NameEntryIterator() {} + + virtual bool HasNext(); + virtual CALLER_ATTACH NameEntry* Next(); + virtual void Remove(); private: - void init(NameTable* table, NameEntryFilter* filter); + void Init(NameTable* table, NameEntryFilter* filter); - NameTable* table_; // use dumb pointer since it's a composition object + NameTable* table_; // Use dumb pointer since it's a composition object. int32_t name_index_; NameEntryFilter* filter_; }; - // caller delete the object - virtual NameEntryIterator* iterator(); - virtual NameEntryIterator* iterator(NameEntryFilter* filter); - - private: - static const char* getEncodingName(int32_t platform_id, int32_t encoding_id); - static UConverter* getCharset(int32_t platform_id, int32_t encoding_id); - static void convertToNameBytes(const UChar* name, int32_t platform_id, - int32_t encoding_id, ByteVector* b); - static UChar* convertFromNameBytes(ByteVector* name_bytes, - int32_t platform_id, int32_t encoding_id); - - public: - typedef std::map > NameEntryBuilderMap; - + // The builder to construct name table for outputting. class Builder : public Table::ArrayElementTableBuilder, public RefCounted { public: @@ -647,15 +571,14 @@ class NameTable : public Table, public RefCounted { Builder(FontDataTableBuilderContainer* font_builder, Header* header, ReadableFontData* data); - private: - void initialize(ReadableFontData* data); - NameEntryBuilderMap* getNameBuilders(); + // Revert the name builders for the name table to the last version that came + // from data. + void RevertNames(); - public: // static class in Java, functions are not virtual unless inherited - void revertNames(); - int32_t builderCount(); + // Number of name entry builders contained. + int32_t BuilderCount(); - // Note: For C++ port, this is not implemented so far. The clear() function + // 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. @@ -663,22 +586,146 @@ class NameTable : public Table, public RefCounted { // Clear the name builders for the name table. // void clear(); - bool has(int32_t platform_id, int32_t encoding_id, int32_t language_id, + // 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); - CALLER_ATTACH NameEntryBuilder* nameBuilder(int32_t platform_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); - bool remove(int32_t platform_id, int32_t encoding_id, int32_t language_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); - virtual CALLER_ATTACH FontDataTable* subBuildTable(ReadableFontData* data); - virtual void subDataSet(); - virtual int32_t subDataSizeToSerialize(); - virtual bool subReadyToSerialize(); - virtual int32_t subSerialize(WritableFontData* new_data); + // 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(int 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. + // Note: Caller delete the returned object. + virtual NameEntryIterator* Iterator(); + virtual 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; diff --git a/sfntly/os2_table.cc b/sfntly/os2_table.cc index 4e7189d..6d6d338 100644 --- a/sfntly/os2_table.cc +++ b/sfntly/os2_table.cc @@ -98,163 +98,164 @@ int32_t UnicodeRange::range(int32_t bit) { /****************************************************************************** * class OS2Table ******************************************************************************/ -OS2Table::OS2Table(Header* header, ReadableFontData* data) - : Table(header, data) { -} - OS2Table::~OS2Table() {} -int32_t OS2Table::version() { - return data_->readUShort(Offset::kVersion); +int32_t OS2Table::Version() { + return data_->ReadUShort(Offset::kVersion); } -int32_t OS2Table::xAvgCharWidth() { - return data_->readShort(Offset::kXAvgCharWidth); +int32_t OS2Table::XAvgCharWidth() { + return data_->ReadShort(Offset::kXAvgCharWidth); } -int32_t OS2Table::usWeightClass() { - return data_->readUShort(Offset::kUsWeightClass); +int32_t OS2Table::UsWeightClass() { + return data_->ReadUShort(Offset::kUsWeightClass); } -int32_t OS2Table::usWidthClass() { - return data_->readUShort(Offset::kUsWidthClass); +int32_t OS2Table::UsWidthClass() { + return data_->ReadUShort(Offset::kUsWidthClass); } -int32_t OS2Table::fsType() { - return data_->readUShort(Offset::kFsType); +int32_t OS2Table::FsType() { + return data_->ReadUShort(Offset::kFsType); } -int32_t OS2Table::ySubscriptXSize() { - return data_->readShort(Offset::kYSubscriptXSize); +int32_t OS2Table::YSubscriptXSize() { + return data_->ReadShort(Offset::kYSubscriptXSize); } -int32_t OS2Table::ySubscriptYSize() { - return data_->readShort(Offset::kYSubscriptYSize); +int32_t OS2Table::YSubscriptYSize() { + return data_->ReadShort(Offset::kYSubscriptYSize); } -int32_t OS2Table::ySubscriptXOffset() { - return data_->readShort(Offset::kYSubscriptXOffset); +int32_t OS2Table::YSubscriptXOffset() { + return data_->ReadShort(Offset::kYSubscriptXOffset); } -int32_t OS2Table::ySubscriptYOffset() { - return data_->readShort(Offset::kYSubscriptYOffset); +int32_t OS2Table::YSubscriptYOffset() { + return data_->ReadShort(Offset::kYSubscriptYOffset); } -int32_t OS2Table::ySuperscriptXSize() { - return data_->readShort(Offset::kYSuperscriptXSize); +int32_t OS2Table::YSuperscriptXSize() { + return data_->ReadShort(Offset::kYSuperscriptXSize); } -int32_t OS2Table::ySuperscriptYSize() { - return data_->readShort(Offset::kYSuperscriptYSize); +int32_t OS2Table::YSuperscriptYSize() { + return data_->ReadShort(Offset::kYSuperscriptYSize); } -int32_t OS2Table::ySuperscriptXOffset() { - return data_->readShort(Offset::kYSuperscriptXOffset); +int32_t OS2Table::YSuperscriptXOffset() { + return data_->ReadShort(Offset::kYSuperscriptXOffset); } -int32_t OS2Table::ySuperscriptYOffset() { - return data_->readShort(Offset::kYSuperscriptYOffset); +int32_t OS2Table::YSuperscriptYOffset() { + return data_->ReadShort(Offset::kYSuperscriptYOffset); } -int32_t OS2Table::yStrikeoutSize() { - return data_->readShort(Offset::kYStrikeoutSize); +int32_t OS2Table::YStrikeoutSize() { + return data_->ReadShort(Offset::kYStrikeoutSize); } -int32_t OS2Table::yStrikeoutPosition() { - return data_->readShort(Offset::kYStrikeoutPosition); +int32_t OS2Table::YStrikeoutPosition() { + return data_->ReadShort(Offset::kYStrikeoutPosition); } -int32_t OS2Table::sFamilyClass() { - return data_->readShort(Offset::kSFamilyClass); +int32_t OS2Table::SFamilyClass() { + return data_->ReadShort(Offset::kSFamilyClass); } -void OS2Table::panose(ByteVector* value) { +void OS2Table::Panose(ByteVector* value) { value->clear(); value->resize(10); - data_->readBytes(Offset::kPanose, value, 0, 10); + data_->ReadBytes(Offset::kPanose, value, 0, 10); } -int64_t OS2Table::ulUnicodeRange1() { - return data_->readULong(Offset::kUlUnicodeRange1); +int64_t OS2Table::UlUnicodeRange1() { + return data_->ReadULong(Offset::kUlUnicodeRange1); } -int64_t OS2Table::ulUnicodeRange2() { - return data_->readULong(Offset::kUlUnicodeRange2); +int64_t OS2Table::UlUnicodeRange2() { + return data_->ReadULong(Offset::kUlUnicodeRange2); } -int64_t OS2Table::ulUnicodeRange3() { - return data_->readULong(Offset::kUlUnicodeRange3); +int64_t OS2Table::UlUnicodeRange3() { + return data_->ReadULong(Offset::kUlUnicodeRange3); } -int64_t OS2Table::ulUnicodeRange4() { - return data_->readULong(Offset::kUlUnicodeRange4); +int64_t OS2Table::UlUnicodeRange4() { + return data_->ReadULong(Offset::kUlUnicodeRange4); } -void OS2Table::achVendId(ByteVector* b) { +void OS2Table::AchVendId(ByteVector* b) { b->clear(); b->resize(4); - data_->readBytes(Offset::kAchVendId, b, 0, 4); + data_->ReadBytes(Offset::kAchVendId, b, 0, 4); } -int32_t OS2Table::fsSelection() { - return data_->readUShort(Offset::kFsSelection); +int32_t OS2Table::FsSelection() { + return data_->ReadUShort(Offset::kFsSelection); } -int32_t OS2Table::usFirstCharIndex() { - return data_->readUShort(Offset::kUsFirstCharIndex); +int32_t OS2Table::UsFirstCharIndex() { + return data_->ReadUShort(Offset::kUsFirstCharIndex); } -int32_t OS2Table::usLastCharIndex() { - return data_->readUShort(Offset::kUsLastCharIndex); +int32_t OS2Table::UsLastCharIndex() { + return data_->ReadUShort(Offset::kUsLastCharIndex); } -int32_t OS2Table::sTypoAscender() { - return data_->readShort(Offset::kSTypoAscender); +int32_t OS2Table::STypoAscender() { + return data_->ReadShort(Offset::kSTypoAscender); } -int32_t OS2Table::sTypoDecender() { - return data_->readShort(Offset::kSTypoDescender); +int32_t OS2Table::STypoDecender() { + return data_->ReadShort(Offset::kSTypoDescender); } -int32_t OS2Table::sTypoLineGap() { - return data_->readShort(Offset::kSTypoLineGap); +int32_t OS2Table::STypoLineGap() { + return data_->ReadShort(Offset::kSTypoLineGap); } -int32_t OS2Table::usWinAscent() { - return data_->readUShort(Offset::kUsWinAscent); +int32_t OS2Table::UsWinAscent() { + return data_->ReadUShort(Offset::kUsWinAscent); } -int32_t OS2Table::usWinDescent() { - return data_->readUShort(Offset::kUsWinDescent); +int32_t OS2Table::UsWinDescent() { + return data_->ReadUShort(Offset::kUsWinDescent); } -int64_t OS2Table::ulCodePageRange1() { - return data_->readULong(Offset::kUlCodePageRange1); +int64_t OS2Table::UlCodePageRange1() { + return data_->ReadULong(Offset::kUlCodePageRange1); } -int64_t OS2Table::ulCodePageRange2() { - return data_->readULong(Offset::kUlCodePageRange2); +int64_t OS2Table::UlCodePageRange2() { + return data_->ReadULong(Offset::kUlCodePageRange2); } -int64_t OS2Table::ulCodePageRange() { - return ((0xffffffff & ulCodePageRange2()) << 32) | - (0xffffffff & ulCodePageRange1()); +int64_t OS2Table::UlCodePageRange() { + // TODO(arthurhsu): Possible bug point, check with stuartg. + return ((0xffffffff & UlCodePageRange2()) << 32) | + (0xffffffff & UlCodePageRange1()); } -int32_t OS2Table::sxHeight() { - return data_->readShort(Offset::kSxHeight); +int32_t OS2Table::SxHeight() { + return data_->ReadShort(Offset::kSxHeight); } -int32_t OS2Table::usDefaultChar() { - return data_->readUShort(Offset::kUsDefaultChar); +int32_t OS2Table::UsDefaultChar() { + return data_->ReadUShort(Offset::kUsDefaultChar); } -int32_t OS2Table::usBreakChar() { - return data_->readUShort(Offset::kUsBreakChar); +int32_t OS2Table::UsBreakChar() { + return data_->ReadUShort(Offset::kUsBreakChar); } -int32_t OS2Table::usMaxContext() { - return data_->readUShort(Offset::kUsMaxContext); +int32_t OS2Table::UsMaxContext() { + return data_->ReadUShort(Offset::kUsMaxContext); +} + +OS2Table::OS2Table(Header* header, ReadableFontData* data) + : Table(header, data) { } /****************************************************************************** @@ -267,10 +268,10 @@ OS2Table::Builder::Builder(FontDataTableBuilderContainer* font_builder, OS2Table::Builder::~Builder() {} -CALLER_ATTACH FontDataTable* OS2Table::Builder::subBuildTable( +CALLER_ATTACH FontDataTable* OS2Table::Builder::SubBuildTable( ReadableFontData* data) { FontDataTablePtr table = new OS2Table(header(), data); - return table.detach(); + return table.Detach(); } } // namespace sfntly diff --git a/sfntly/os2_table.h b/sfntly/os2_table.h index 9bf33c2..058435a 100644 --- a/sfntly/os2_table.h +++ b/sfntly/os2_table.h @@ -300,6 +300,61 @@ struct CodePageRange { }; class OS2Table : public Table, public RefCounted { + public: + class Builder : public Table::TableBasedTableBuilder, + public RefCounted { + public: + Builder(FontDataTableBuilderContainer* font_builder, Header* header, + WritableFontData* data); + virtual ~Builder(); + virtual CALLER_ATTACH FontDataTable* SubBuildTable(ReadableFontData* data); + }; + + ~OS2Table(); + + int32_t Version(); + 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 STypoDecender(); + int32_t STypoLineGap(); + int32_t UsWinAscent(); + int32_t UsWinDescent(); + int64_t UlCodePageRange1(); + int64_t UlCodePageRange2(); + // UNIMPLEMENTED: public EnumSet ulCodePageRange() + int64_t UlCodePageRange(); + int32_t SxHeight(); + int32_t SCapHeight(); + int32_t UsDefaultChar(); + int32_t UsBreakChar(); + int32_t UsMaxContext(); + private: struct Offset { enum { @@ -344,62 +399,6 @@ class OS2Table : public Table, public RefCounted { }; OS2Table(Header* header, ReadableFontData* data); - - public: - ~OS2Table(); - - int32_t version(); - 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 sTypoDecender(); - int32_t sTypoLineGap(); - int32_t usWinAscent(); - int32_t usWinDescent(); - int64_t ulCodePageRange1(); - int64_t ulCodePageRange2(); - // UNIMPLEMENTED: public EnumSet ulCodePageRange() - int64_t ulCodePageRange(); - int32_t sxHeight(); - int32_t sCapHeight(); - int32_t usDefaultChar(); - int32_t usBreakChar(); - int32_t usMaxContext(); - - public: - class Builder : public Table::TableBasedTableBuilder, - public RefCounted { - public: - Builder(FontDataTableBuilderContainer* font_builder, Header* header, - WritableFontData* data); - virtual ~Builder(); - virtual CALLER_ATTACH FontDataTable* subBuildTable(ReadableFontData* data); - }; }; } // namespace sfntly diff --git a/sfntly/port/atomic.h b/sfntly/port/atomic.h index 4c2d65b..abfc429 100644 --- a/sfntly/port/atomic.h +++ b/sfntly/port/atomic.h @@ -21,7 +21,7 @@ #include -static inline size_t atomicIncrement(size_t* address) { +static inline size_t AtomicIncrement(size_t* address) { #if defined (_WIN64) return InterlockedIncrement64(reinterpret_cast(address)); #else @@ -29,7 +29,7 @@ static inline size_t atomicIncrement(size_t* address) { #endif } -static inline size_t atomicDecrement(size_t* address) { +static inline size_t AtomicDecrement(size_t* address) { #if defined (_WIN64) return InterlockedDecrement64(reinterpret_cast(address)); #else @@ -41,11 +41,11 @@ static inline size_t atomicDecrement(size_t* address) { #include -static inline size_t atomicIncrement(size_t* address) { +static inline size_t AtomicIncrement(size_t* address) { return OSAtomicIncrement32Barrier(reinterpret_cast(address)); } -static inline size_t atomicDecrement(size_t* address) { +static inline size_t AtomicDecrement(size_t* address) { return OSAtomicDecrement32Barrier(reinterpret_cast(address)); } @@ -58,11 +58,11 @@ static inline size_t atomicDecrement(size_t* address) { #include -static inline size_t atomicIncrement(size_t* address) { +static inline size_t AtomicIncrement(size_t* address) { return __sync_add_and_fetch(address, 1); } -static inline size_t atomicDecrement(size_t* address) { +static inline size_t AtomicDecrement(size_t* address) { return __sync_sub_and_fetch(address, 1); } diff --git a/sfntly/port/endian.h b/sfntly/port/endian.h index c6898ee..1364e42 100644 --- a/sfntly/port/endian.h +++ b/sfntly/port/endian.h @@ -22,18 +22,18 @@ namespace sfntly { -static inline uint16_t endian_swap16(uint16_t value) { +static inline uint16_t EndianSwap16(uint16_t value) { return (uint16_t)((value >> 8) | (value << 8)); } -static inline int32_t endian_swap32(int32_t value) { +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 endian_swap64(uint64_t value) { +static inline uint64_t EndianSwap64(uint64_t value) { return (((value & 0x00000000000000ffLL) << 56) | ((value & 0x000000000000ff00LL) << 40) | ((value & 0x0000000000ff0000LL) << 24) | @@ -45,31 +45,31 @@ static inline uint64_t endian_swap64(uint64_t value) { } #ifdef SFNTLY_LITTLE_ENDIAN - #define toBE16(n) endian_swap16(n) - #define toBE32(n) endian_swap32(n) - #define toBE64(n) endian_swap64(n) - #define toLE16(n) (n) - #define toLE32(n) (n) - #define toLE64(n) (n) - #define fromBE16(n) endian_swap16(n) - #define fromBE32(n) endian_swap32(n) - #define fromBE64(n) endian_swap64(n) - #define fromLE16(n) (n) - #define fromLE32(n) (n) - #define fromLE64(n) (n) + #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) endian_swap16(n) - #define toLE32(n) endian_swap32(n) - #define toLE64(n) endian_swap64(n) - #define fromBE16(n) (n) - #define fromBE32(n) (n) - #define fromBE64(n) (n) - #define fromLE16(n) endian_swap16(n) - #define fromLE32(n) endian_swap32(n) - #define fromLE64(n) endian_swap64(n) + #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 diff --git a/sfntly/port/file_input_stream.cc b/sfntly/port/file_input_stream.cc index 04a0fd6..661b6fd 100644 --- a/sfntly/port/file_input_stream.cc +++ b/sfntly/port/file_input_stream.cc @@ -23,38 +23,21 @@ namespace sfntly { -FileInputStream::FileInputStream() : file_(NULL), position_(0), length_(0) { +FileInputStream::FileInputStream() + : file_(NULL), + position_(0), + length_(0) { } FileInputStream::~FileInputStream() { - close(); + Close(); } -int32_t FileInputStream::available() { +int32_t FileInputStream::Available() { return length_ - position_; } -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; -} - -void FileInputStream::close() { +void FileInputStream::Close() { if (file_) { fclose(file_); length_ = 0; @@ -63,16 +46,16 @@ void FileInputStream::close() { } } -void FileInputStream::mark(int32_t readlimit) { +void FileInputStream::Mark(int32_t readlimit) { // NOP UNREFERENCED_PARAMETER(readlimit); } -bool FileInputStream::markSupported() { +bool FileInputStream::MarkSupported() { return false; } -int32_t FileInputStream::read() { +int32_t FileInputStream::Read() { if (!file_) { #if defined (SFNTLY_NO_EXCEPTION) return 0; @@ -93,11 +76,11 @@ int32_t FileInputStream::read() { return value; } -int32_t FileInputStream::read(ByteVector* b) { - return read(b, 0, b->capacity()); +int32_t FileInputStream::Read(ByteVector* b) { + return Read(b, 0, b->capacity()); } -int32_t FileInputStream::read(ByteVector* b, int32_t offset, int32_t length) { +int32_t FileInputStream::Read(ByteVector* b, int32_t offset, int32_t length) { assert(b); if (!file_) { #if defined (SFNTLY_NO_EXCEPTION) @@ -122,11 +105,11 @@ int32_t FileInputStream::read(ByteVector* b, int32_t offset, int32_t length) { return actual_read; } -void FileInputStream::reset() { +void FileInputStream::Reset() { // NOP } -int64_t FileInputStream::skip(int64_t n) { +int64_t FileInputStream::Skip(int64_t n) { if (!file_) { #if defined (SFNTLY_NO_EXCEPTION) return 0; @@ -147,11 +130,11 @@ int64_t FileInputStream::skip(int64_t n) { return skip_count; } -void FileInputStream::unread(ByteVector* b) { - unread(b, 0, b->capacity()); +void FileInputStream::Unread(ByteVector* b) { + Unread(b, 0, b->capacity()); } -void FileInputStream::unread(ByteVector* b, int32_t offset, int32_t length) { +void FileInputStream::Unread(ByteVector* b, int32_t offset, int32_t length) { assert(b); assert(b->size() >= size_t(offset + length)); if (!file_) { @@ -164,9 +147,29 @@ void FileInputStream::unread(ByteVector* b, int32_t offset, int32_t length) { size_t unread_count = std::min(position_, length); fseek(file_, position_ - unread_count, SEEK_SET); position_ -= unread_count; - read(b, offset, length); + 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/sfntly/port/file_input_stream.h b/sfntly/port/file_input_stream.h index 0ec85b6..a63726f 100644 --- a/sfntly/port/file_input_stream.h +++ b/sfntly/port/file_input_stream.h @@ -29,22 +29,22 @@ class FileInputStream : public PushbackInputStream { 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); + 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); + 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); + virtual bool Open(const char* file_path); private: FILE* file_; diff --git a/sfntly/port/input_stream.h b/sfntly/port/input_stream.h index ebbccf0..a56afb9 100644 --- a/sfntly/port/input_stream.h +++ b/sfntly/port/input_stream.h @@ -24,23 +24,24 @@ namespace sfntly { // C++ equivalent to Java's OutputStream class class InputStream { public: - 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; // 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; + virtual void Unread(ByteVector* b) = 0; + virtual void Unread(ByteVector* b, int32_t offset, int32_t length) = 0; }; } // namespace sfntly diff --git a/sfntly/port/memory_output_stream.cc b/sfntly/port/memory_output_stream.cc index 1f3ecd4..5ddeec2 100644 --- a/sfntly/port/memory_output_stream.cc +++ b/sfntly/port/memory_output_stream.cc @@ -24,25 +24,27 @@ MemoryOutputStream::MemoryOutputStream() { MemoryOutputStream::~MemoryOutputStream() { } -void MemoryOutputStream::write(ByteVector* buffer) { +void MemoryOutputStream::Write(ByteVector* buffer) { store_.insert(store_.end(), buffer->begin(), buffer->end()); } -void MemoryOutputStream::write(ByteVector* buffer, int32_t offset, +void MemoryOutputStream::Write(ByteVector* buffer, + int32_t offset, int32_t length) { - store_.insert(store_.end(), buffer->begin() + offset, + store_.insert(store_.end(), + buffer->begin() + offset, buffer->begin() + offset + length); } -void MemoryOutputStream::write(byte_t b) { +void MemoryOutputStream::Write(byte_t b) { store_.push_back(b); } -byte_t* MemoryOutputStream::get() { +byte_t* MemoryOutputStream::Get() { return &(store_[0]); } -size_t MemoryOutputStream::size() { +size_t MemoryOutputStream::Size() { return store_.size(); } diff --git a/sfntly/port/memory_output_stream.h b/sfntly/port/memory_output_stream.h index 4a7cb74..a0befea 100644 --- a/sfntly/port/memory_output_stream.h +++ b/sfntly/port/memory_output_stream.h @@ -32,14 +32,14 @@ class MemoryOutputStream : public OutputStream { 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 b); - - byte_t* get(); - size_t size(); + 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 b); + + byte_t* Get(); + size_t Size(); private: std::vector store_; diff --git a/sfntly/port/output_stream.h b/sfntly/port/output_stream.h index 0b232e2..c5d71cf 100644 --- a/sfntly/port/output_stream.h +++ b/sfntly/port/output_stream.h @@ -24,13 +24,14 @@ namespace sfntly { // C++ equivalent to Java's OutputStream class class OutputStream { public: - virtual void close() = 0; - virtual void flush() = 0; - virtual void write(ByteVector* buffer) = 0; - virtual void write(ByteVector* buffer, int32_t offset, int32_t length) = 0; - virtual void write(byte_t b) = 0; // 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(ByteVector* buffer, int32_t offset, int32_t length) = 0; + virtual void Write(byte_t b) = 0; }; } // namespace sfntly diff --git a/sfntly/port/refcount.h b/sfntly/port/refcount.h index ed1fa96..6ac09bb 100644 --- a/sfntly/port/refcount.h +++ b/sfntly/port/refcount.h @@ -27,16 +27,16 @@ // public: // static Foo* CreateInstance() { // Ptr obj = new Foo(); // ref count = 1 -// return obj.detach(); +// return obj.Detach(); // } // }; // typedef Ptr FooPtr; // common short-hand notation // FooPtr obj; -// obj.attach(Foo::CreatedInstance()); // ref count = 1 +// 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 +// obj.Release(); // ref count = 0, object destroyed // Notes on usage: // 1. Virtual inherit from RefCount interface in base class if smart pointers @@ -57,10 +57,10 @@ // 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* createFoo() { FooPtr obj = new Foo(); return obj.Detach(); } // Foo* passthru() { FooPtr obj = createFoo(), return obj; } // FooPtr end_scope_pointer; -// end_scope_pointer.attach(passThrough); +// end_scope_pointer.Attach(passThrough); // If you are not passing that object back, you are the end of scope. #ifndef TYPOGRAPHY_FONT_SFNTLY_SRC_SFNTLY_PORT_REFCOUNT_H_ @@ -101,10 +101,11 @@ namespace sfntly { class RefCount { public: - virtual size_t addRef() const = 0; - virtual size_t release() const = 0; // Make gcc -Wnon-virtual-dtor happy. virtual ~RefCount() {} + + virtual size_t AddRef() const = 0; + virtual size_t Release() const = 0; }; template @@ -114,8 +115,8 @@ class NoAddRefRelease : public T { ~NoAddRefRelease(); private: - virtual size_t addRef() const = 0; - virtual size_t release() const = 0; + virtual size_t AddRef() const = 0; + virtual size_t Release() const = 0; }; template @@ -123,15 +124,15 @@ class RefCounted : virtual public RefCount { public: RefCounted() : ref_count_(0) { #if defined (ENABLE_OBJECT_COUNTER) - object_id_ = atomicIncrement(&next_id_); - atomicIncrement(&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_); + AtomicDecrement(&object_counter_); DEBUG_OUTPUT("D "); #endif } @@ -141,14 +142,14 @@ class RefCounted : virtual public RefCount { return *this; } - virtual size_t addRef() const { - size_t new_count = atomicIncrement(&ref_count_); + 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_); + 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. @@ -189,7 +190,7 @@ class Ptr { } ~Ptr() { - release(); + Release(); } T* operator=(T* pT) { @@ -201,9 +202,9 @@ class Ptr { if (p == NULL) { return NULL; } - p->addRef(); // always addRef() before release() + p->AddRef(); // always AddRef() before Release() } - release(); + Release(); p_ = pT; return p_; } @@ -243,26 +244,26 @@ class Ptr { return (p_ == pT); } - size_t release() const { + size_t Release() const { size_t ref_count = 0; if (p_) { RefCount* p = static_cast(p_); if (p) { - ref_count = p->release(); + ref_count = p->Release(); } p_ = NULL; } return ref_count; } - void attach(T* pT) { + void Attach(T* pT) { if (p_ != pT) { - release(); + Release(); p_ = pT; } } - T* detach() { + T* Detach() { T* pT = p_; p_ = NULL; return pT; diff --git a/sfntly/subtable.cc b/sfntly/subtable.cc index 9ca94f3..782fd80 100644 --- a/sfntly/subtable.cc +++ b/sfntly/subtable.cc @@ -20,24 +20,25 @@ namespace sfntly { /****************************************************************************** * SubTable class ******************************************************************************/ -SubTable::SubTable(ReadableFontData* data) : FontDataTable(data) { -} - SubTable::~SubTable() {} +SubTable::SubTable(ReadableFontData* data) + : FontDataTable(data) { +} + /****************************************************************************** * SubTable::Builder class ******************************************************************************/ +SubTable::Builder::~Builder() {} + SubTable::Builder::Builder(FontDataTableBuilderContainer* container, - WritableFontData* data) : - FontDataTable::Builder(container, data) { + WritableFontData* data) + : FontDataTable::Builder(container, data) { } SubTable::Builder::Builder(FontDataTableBuilderContainer* container, - ReadableFontData* data) : - FontDataTable::Builder(container, data) { + ReadableFontData* data) + : FontDataTable::Builder(container, data) { } -SubTable::Builder::~Builder() {} - } // namespace sfntly diff --git a/sfntly/subtable.h b/sfntly/subtable.h index 23e1e42..30ecf66 100644 --- a/sfntly/subtable.h +++ b/sfntly/subtable.h @@ -26,23 +26,22 @@ namespace sfntly { // of these are the CMap subtables within CMap table (cmap) or a glyph within // the glyph table (glyf). class SubTable : public FontDataTable { - protected: - // Note: constructor refactored in C++ to avoid heavy lifting. - // caller need to do data->slice(offset, length) beforehand. - explicit SubTable(ReadableFontData* data); - - public: - virtual ~SubTable(); - public: class Builder : public FontDataTable::Builder { + public: + virtual ~Builder(); + protected: Builder(FontDataTableBuilderContainer* container, WritableFontData* data); Builder(FontDataTableBuilderContainer* container, ReadableFontData* data); - - public: - virtual ~Builder(); }; + + virtual ~SubTable(); + + protected: + // Note: constructor refactored in C++ to avoid heavy lifting. + // caller need to do data->Slice(offset, length) beforehand. + explicit SubTable(ReadableFontData* data); }; } // namespace sfntly diff --git a/sfntly/table.cc b/sfntly/table.cc index 8a1ec02..a11177e 100644 --- a/sfntly/table.cc +++ b/sfntly/table.cc @@ -15,6 +15,7 @@ */ #include "sfntly/table.h" + #include "sfntly/font.h" #include "sfntly/tag.h" #include "sfntly/cmap_table.h" @@ -32,61 +33,56 @@ namespace sfntly { /****************************************************************************** * Table class ******************************************************************************/ -Table::Table(Header* header, ReadableFontData* data) : FontDataTable(data) { - header_ = header; -} - Table::~Table() {} -int64_t Table::calculatedChecksum() { - return data_->checksum(); -} - -Table::Header* Table::header() { - return header_; -} - -int32_t Table::headerTag() { - return header_->tag(); -} - -int32_t Table::headerOffset() { - return header_->offset(); +int64_t Table::CalculatedChecksum() { + return data_->Checksum(); } -int32_t Table::headerLength() { - return header_->length(); +WritableFontData* Table::GetNewData(int32_t size) { + return font_->GetNewData(size); } -int64_t Table::headerChecksum() { - return header_->checksum(); -} - -WritableFontData* Table::getNewData(int32_t size) { - return font_->getNewData(size); +void Table::SetFont(Font* font) { + font_ = font; } -void Table::setFont(Font* font) { - font_ = font; +Table::Table(Header* header, ReadableFontData* data) + : FontDataTable(data) { + header_ = header; } /****************************************************************************** * Table::Header class ******************************************************************************/ Table::Header::Header(int32_t tag) - : tag_(tag), offset_(0), length_(0), offset_valid_(false), checksum_(0), + : tag_(tag), + offset_(0), + length_(0), + offset_valid_(false), + checksum_(0), checksum_valid_(false) { } Table::Header::Header(int32_t tag, int32_t length) - : tag_(tag), offset_(0), length_(length), offset_valid_(false), - checksum_(0), checksum_valid_(false) { + : tag_(tag), + offset_(0), + length_(length), + offset_valid_(false), + checksum_(0), + checksum_valid_(false) { } -Table::Header::Header(int32_t tag, int64_t checksum, int32_t offset, +Table::Header::Header(int32_t tag, + int64_t checksum, + int32_t offset, int32_t length) - : tag_(tag), offset_(offset), length_(length), offset_valid_(true), - checksum_(checksum), checksum_valid_(true) { + : tag_(tag), + offset_(offset), + length_(length), + offset_valid_(true), + checksum_(checksum), + checksum_valid_(true) { } Table::Header::~Header() {} @@ -96,58 +92,30 @@ bool TableHeaderComparator::operator() (const TableHeaderPtr lhs, return lhs->offset_ > rhs->offset_; } -int32_t Table::Header::tag() { return tag_; } -int32_t Table::Header::offset() { return offset_; } -int32_t Table::Header::length() { return length_; } -bool Table::Header::offsetValid() { return offset_valid_; } -int64_t Table::Header::checksum() { return checksum_; } -bool Table::Header::checksumValid() { return checksum_valid_; } - /****************************************************************************** * Table::Builder class ******************************************************************************/ -Table::Builder::Builder(FontDataTableBuilderContainer* font_builder, - Header* header, WritableFontData* data) : - FontDataTable::Builder(font_builder, data) { - header_ = header; -} - -Table::Builder::Builder(FontDataTableBuilderContainer* font_builder, - Header* header, ReadableFontData* data) : - FontDataTable::Builder(font_builder, data) { - header_ = header; -} - -Table::Builder::Builder(FontDataTableBuilderContainer* font_builder, - Header* header) : - FontDataTable::Builder(font_builder) { - header_ = header; -} - Table::Builder::~Builder() { - header_.release(); + header_.Release(); } -Table::Header* Table::Builder::header() { - return header_; -} - -void Table::Builder::notifyPostTableBuild(FontDataTable* table) { - if (modelChanged() || dataChanged()) { +void Table::Builder::NotifyPostTableBuild(FontDataTable* table) { + if (modelChanged() || data_changed()) { Table* derived_table = down_cast(table); header_ = new Header(header()->tag(), - derived_table->readFontData()->length()); + derived_table->ReadFontData()->Length()); } } -WritableFontData* Table::Builder::getNewData(int32_t size) { +WritableFontData* Table::Builder::GetNewData(int32_t size) { UNREFERENCED_PARAMETER(size); - return internalWriteData(); + return InternalWriteData(); } -CALLER_ATTACH Table::Builder* Table::Builder::getBuilder( - FontDataTableBuilderContainer* font_builder, Header* header, - WritableFontData* table_data) { +CALLER_ATTACH Table::Builder* + Table::Builder::GetBuilder(FontDataTableBuilderContainer* font_builder, + Header* header, + WritableFontData* table_data) { int32_t tag = header->tag(); TableBuilderPtr builder; Table::Builder* builder_raw = NULL; @@ -199,77 +167,113 @@ CALLER_ATTACH Table::Builder* Table::Builder::getBuilder( } builder = builder_raw; - return builder.detach(); + return builder.Detach(); +} + +Table::Builder::Builder(FontDataTableBuilderContainer* font_builder, + Header* header, + WritableFontData* data) + : FontDataTable::Builder(font_builder, data) { + header_ = header; +} + +Table::Builder::Builder(FontDataTableBuilderContainer* font_builder, + Header* header, + ReadableFontData* data) + : FontDataTable::Builder(font_builder, data) { + header_ = header; +} + +Table::Builder::Builder(FontDataTableBuilderContainer* font_builder, + Header* header) + : FontDataTable::Builder(font_builder) { + header_ = header; } /****************************************************************************** * Table::TableBasedTableBuilder class ******************************************************************************/ -Table::TableBasedTableBuilder::TableBasedTableBuilder( - FontDataTableBuilderContainer* font_builder, Header* header, - WritableFontData* data) : Builder(font_builder, header, data) {} - -Table::TableBasedTableBuilder::TableBasedTableBuilder( - FontDataTableBuilderContainer* font_builder, Header* header, - ReadableFontData* data) : Builder(font_builder, header, data) {} +Table::TableBasedTableBuilder::~TableBasedTableBuilder() {} -Table::TableBasedTableBuilder::TableBasedTableBuilder( - FontDataTableBuilderContainer* font_builder, Header* header) : - Builder(font_builder, header) {} +int32_t Table::TableBasedTableBuilder::SubSerialize(WritableFontData* data) { + UNREFERENCED_PARAMETER(data); + return 0; +} -Table::TableBasedTableBuilder::~TableBasedTableBuilder() {} +bool Table::TableBasedTableBuilder::SubReadyToSerialize() { + return false; +} -Table* Table::TableBasedTableBuilder::table() { - if (table_ == NULL) { - table_.attach(down_cast(subBuildTable(internalReadData()))); - } - return table_; +int32_t Table::TableBasedTableBuilder::SubDataSizeToSerialize() { + return 0; } -void Table::TableBasedTableBuilder::subDataSet() { +void Table::TableBasedTableBuilder::SubDataSet() { table_ = NULL; } -int32_t Table::TableBasedTableBuilder::subDataSizeToSerialize() { - return 0; +Table::TableBasedTableBuilder::TableBasedTableBuilder( + FontDataTableBuilderContainer* font_builder, + Header* header, + WritableFontData* data) + : Builder(font_builder, header, data) { } -bool Table::TableBasedTableBuilder::subReadyToSerialize() { - return false; +Table::TableBasedTableBuilder::TableBasedTableBuilder( + FontDataTableBuilderContainer* font_builder, + Header* header, + ReadableFontData* data) + : Builder(font_builder, header, data) { } -int32_t Table::TableBasedTableBuilder::subSerialize(WritableFontData* data) { - UNREFERENCED_PARAMETER(data); - return 0; +Table::TableBasedTableBuilder::TableBasedTableBuilder( + FontDataTableBuilderContainer* font_builder, + Header* header) + : Builder(font_builder, header) { +} + +Table* Table::TableBasedTableBuilder::GetTable() { + if (table_ == NULL) { + table_.Attach(down_cast(SubBuildTable(InternalReadData()))); + } + return table_; } /****************************************************************************** * Table::GenericTableBuilder class ******************************************************************************/ Table::GenericTableBuilder::GenericTableBuilder( - FontDataTableBuilderContainer* font_builder, Header* header, - WritableFontData* data) : - TableBasedTableBuilder(font_builder, header, data) {} + FontDataTableBuilderContainer* font_builder, + Header* header, + WritableFontData* data) + : TableBasedTableBuilder(font_builder, header, data) { +} -CALLER_ATTACH FontDataTable* Table::GenericTableBuilder::subBuildTable( - ReadableFontData* data) { +CALLER_ATTACH FontDataTable* + Table::GenericTableBuilder::SubBuildTable(ReadableFontData* data) { // Note: In C++ port, we use GenericTable, the ref-counted version of Table UNREFERENCED_PARAMETER(data); - FontDataTablePtr table = new GenericTable(this->header(), internalReadData()); - return table.detach(); + FontDataTablePtr table = new GenericTable(this->header(), InternalReadData()); + return table.Detach(); } /****************************************************************************** * Table::ArrayElementTableBuilder class ******************************************************************************/ -Table::ArrayElementTableBuilder::ArrayElementTableBuilder( - FontDataTableBuilderContainer* font_builder, Header* header, - WritableFontData* data) : Builder(font_builder, header, data) {} +Table::ArrayElementTableBuilder::~ArrayElementTableBuilder() {} Table::ArrayElementTableBuilder::ArrayElementTableBuilder( - FontDataTableBuilderContainer* font_builder, Header* header, - ReadableFontData* data) : Builder(font_builder, header, data) {} + FontDataTableBuilderContainer* font_builder, + Header* header, + WritableFontData* data) + : Builder(font_builder, header, data) { +} -Table::ArrayElementTableBuilder::~ArrayElementTableBuilder() {} +Table::ArrayElementTableBuilder::ArrayElementTableBuilder( + FontDataTableBuilderContainer* font_builder, + Header* header, + ReadableFontData* data) + : Builder(font_builder, header, data) { +} } // namespace sfntly diff --git a/sfntly/table.h b/sfntly/table.h index 9f05ef5..217abcd 100644 --- a/sfntly/table.h +++ b/sfntly/table.h @@ -36,13 +36,12 @@ class Table : public FontDataTable, public FontDataTableBuilderContainer { Header(int32_t tag, int64_t checksum, int32_t offset, int32_t length); virtual ~Header(); - public: // class is final, no virtual functions unless from parent - int32_t tag(); - int32_t offset(); - int32_t length(); - bool offsetValid(); - int64_t checksum(); - bool checksumValid(); + int32_t tag() { return tag_; } + int32_t offset() { return offset_; } + int32_t length() { return length_; } + bool offset_valid() { return offset_valid_; } + int64_t checksum() { return checksum_; } + bool checksum_valid() { return checksum_valid_; } private: int32_t tag_; @@ -60,89 +59,95 @@ class Table : public FontDataTable, public FontDataTableBuilderContainer { // chosen. class Builder : public FontDataTable::Builder, public FontDataTableBuilderContainer { + public: + virtual ~Builder(); + virtual Header* header() { return header_; } + virtual void NotifyPostTableBuild(FontDataTable* table); + virtual WritableFontData* GetNewData(int32_t size); + + static CALLER_ATTACH Builder* + GetBuilder(FontDataTableBuilderContainer* font_builder, + Header* header, + WritableFontData* table_data); + protected: // Note: original version is Font.Builder font_builder. This results in // mutual inclusion happiness that Java solved for C++. Therefore, // we need to avoid that happiness when we port it to C++. - Builder(FontDataTableBuilderContainer* font_builder, Header* header, + Builder(FontDataTableBuilderContainer* font_builder, + Header* header, WritableFontData* data); - Builder(FontDataTableBuilderContainer* font_builder, Header* header, + Builder(FontDataTableBuilderContainer* font_builder, + Header* header, ReadableFontData* data); - Builder(FontDataTableBuilderContainer* font_builder, Header* header); - - public: - virtual ~Builder(); - virtual Header* header(); - virtual void notifyPostTableBuild(FontDataTable* table); - virtual WritableFontData* getNewData(int32_t size); - - public: - static CALLER_ATTACH Builder* getBuilder( - FontDataTableBuilderContainer* font_builder, Header* header, - WritableFontData* table_data); + Builder(FontDataTableBuilderContainer* font_builder, + Header* header); private: Ptr
header_; }; class TableBasedTableBuilder : public Builder { - protected: - TableBasedTableBuilder(FontDataTableBuilderContainer* font_builder, - Header* header, WritableFontData* data); - TableBasedTableBuilder(FontDataTableBuilderContainer* font_builder, - Header* header, ReadableFontData* data); - TableBasedTableBuilder(FontDataTableBuilderContainer* font_builder, - Header* header); public: virtual ~TableBasedTableBuilder(); + virtual int32_t SubSerialize(WritableFontData* new_data); + virtual bool SubReadyToSerialize(); + virtual int32_t SubDataSizeToSerialize(); + virtual void SubDataSet(); + protected: - virtual Table* table(); + TableBasedTableBuilder(FontDataTableBuilderContainer* font_builder, + Header* header, + WritableFontData* data); + TableBasedTableBuilder(FontDataTableBuilderContainer* font_builder, + Header* header, + ReadableFontData* data); + TableBasedTableBuilder(FontDataTableBuilderContainer* font_builder, + Header* header); - public: - virtual int32_t subSerialize(WritableFontData* new_data); - virtual bool subReadyToSerialize(); - virtual int32_t subDataSizeToSerialize(); - virtual void subDataSet(); + // C++ port: renamed table() to GetTable() + virtual Table* GetTable(); - protected: + // TODO(arthurhsu): style guide violation: protected member, need refactor Ptr
table_; }; class GenericTableBuilder : public TableBasedTableBuilder, - public RefCounted { + public RefCounted { public: GenericTableBuilder(FontDataTableBuilderContainer* font_builder, - Header* header, WritableFontData* data); - virtual CALLER_ATTACH FontDataTable* subBuildTable(ReadableFontData* data); + Header* header, + WritableFontData* data); + virtual CALLER_ATTACH FontDataTable* SubBuildTable(ReadableFontData* data); }; class ArrayElementTableBuilder : public Builder { + public: + virtual ~ArrayElementTableBuilder(); + protected: ArrayElementTableBuilder(FontDataTableBuilderContainer* font_builder, - Header* header, WritableFontData* data); + Header* header, + WritableFontData* data); ArrayElementTableBuilder(FontDataTableBuilderContainer* font_builder, - Header* header, ReadableFontData* data); - public: - virtual ~ArrayElementTableBuilder(); + Header* header, + ReadableFontData* data); }; + virtual ~Table(); + virtual int64_t CalculatedChecksum(); + virtual Header* header() { return header_; } + virtual int32_t header_tag() { return header_->tag(); } + virtual int32_t header_offset() { return header_->offset(); } + virtual int32_t header_length() { return header_->length(); } + virtual int64_t header_checksum() { return header_->checksum(); } + virtual WritableFontData* GetNewData(int32_t size); + virtual void SetFont(Font* font); + protected: Table(Header* header, ReadableFontData* data); - public: - virtual ~Table(); - virtual int64_t calculatedChecksum(); - virtual Header* header(); - virtual int32_t headerTag(); - virtual int32_t headerOffset(); - virtual int32_t headerLength(); - virtual int64_t headerChecksum(); - - public: // FontDataTableBuilderContainer, deprecated - virtual WritableFontData* getNewData(int32_t size); - virtual void setFont(Font* font); - private: Ptr
header_; Ptr font_; diff --git a/sfntly/tag.cc b/sfntly/tag.cc index 257e65f..e3c11cd 100644 --- a/sfntly/tag.cc +++ b/sfntly/tag.cc @@ -19,42 +19,42 @@ namespace sfntly { -const int32_t Tag::ttcf = generate_tag('t', 't', 'c', 'f'); -const int32_t Tag::cmap = generate_tag('c', 'm', 'a', 'p'); -const int32_t Tag::head = generate_tag('h', 'e', 'a', 'd'); -const int32_t Tag::hhea = generate_tag('h', 'h', 'e', 'a'); -const int32_t Tag::hmtx = generate_tag('h', 'm', 't', 'x'); -const int32_t Tag::maxp = generate_tag('m', 'a', 'x', 'p'); -const int32_t Tag::name = generate_tag('n', 'a', 'm', 'e'); -const int32_t Tag::OS_2 = generate_tag('O', 'S', '/', '2'); -const int32_t Tag::post = generate_tag('p', 'o', 's', 't'); -const int32_t Tag::cvt = generate_tag('c', 'v', 't', ' '); -const int32_t Tag::fpgm = generate_tag('f', 'p', 'g', 'm'); -const int32_t Tag::glyf = generate_tag('g', 'l', 'y', 'f'); -const int32_t Tag::loca = generate_tag('l', 'o', 'c', 'a'); -const int32_t Tag::prep = generate_tag('p', 'r', 'e', 'p'); -const int32_t Tag::CFF = generate_tag('C', 'F', 'F', ' '); -const int32_t Tag::VORG = generate_tag('V', 'O', 'R', 'G'); -const int32_t Tag::EBDT = generate_tag('E', 'B', 'D', 'T'); -const int32_t Tag::EBLC = generate_tag('E', 'B', 'L', 'C'); -const int32_t Tag::EBSC = generate_tag('E', 'B', 'S', 'C'); -const int32_t Tag::BASE = generate_tag('B', 'A', 'S', 'E'); -const int32_t Tag::GDEF = generate_tag('G', 'D', 'E', 'F'); -const int32_t Tag::GPOS = generate_tag('G', 'P', 'O', 'S'); -const int32_t Tag::GSUB = generate_tag('G', 'S', 'U', 'B'); -const int32_t Tag::JSTF = generate_tag('J', 'S', 'T', 'F'); -const int32_t Tag::DSIG = generate_tag('D', 'S', 'I', 'G'); -const int32_t Tag::gasp = generate_tag('g', 'a', 's', 'p'); -const int32_t Tag::hdmx = generate_tag('h', 'd', 'm', 'x'); -const int32_t Tag::kern = generate_tag('k', 'e', 'r', 'n'); -const int32_t Tag::LTSH = generate_tag('L', 'T', 'S', 'H'); -const int32_t Tag::PCLT = generate_tag('P', 'C', 'L', 'T'); -const int32_t Tag::VDMX = generate_tag('V', 'D', 'M', 'X'); -const int32_t Tag::vhea = generate_tag('v', 'h', 'e', 'a'); -const int32_t Tag::vmtx = generate_tag('v', 'm', 't', 'x'); -const int32_t Tag::bhed = generate_tag('b', 'h', 'e', 'd'); -const int32_t Tag::bdat = generate_tag('b', 'd', 'a', 't'); -const int32_t Tag::bloc = generate_tag('b', 'l', 'o', 'c'); +const int32_t Tag::ttcf = GenerateTag('t', 't', 'c', 'f'); +const int32_t Tag::cmap = GenerateTag('c', 'm', 'a', 'p'); +const int32_t Tag::head = GenerateTag('h', 'e', 'a', 'd'); +const int32_t Tag::hhea = GenerateTag('h', 'h', 'e', 'a'); +const int32_t Tag::hmtx = GenerateTag('h', 'm', 't', 'x'); +const int32_t Tag::maxp = GenerateTag('m', 'a', 'x', 'p'); +const int32_t Tag::name = GenerateTag('n', 'a', 'm', 'e'); +const int32_t Tag::OS_2 = GenerateTag('O', 'S', '/', '2'); +const int32_t Tag::post = GenerateTag('p', 'o', 's', 't'); +const int32_t Tag::cvt = GenerateTag('c', 'v', 't', ' '); +const int32_t Tag::fpgm = GenerateTag('f', 'p', 'g', 'm'); +const int32_t Tag::glyf = GenerateTag('g', 'l', 'y', 'f'); +const int32_t Tag::loca = GenerateTag('l', 'o', 'c', 'a'); +const int32_t Tag::prep = GenerateTag('p', 'r', 'e', 'p'); +const int32_t Tag::CFF = GenerateTag('C', 'F', 'F', ' '); +const int32_t Tag::VORG = GenerateTag('V', 'O', 'R', 'G'); +const int32_t Tag::EBDT = GenerateTag('E', 'B', 'D', 'T'); +const int32_t Tag::EBLC = GenerateTag('E', 'B', 'L', 'C'); +const int32_t Tag::EBSC = GenerateTag('E', 'B', 'S', 'C'); +const int32_t Tag::BASE = GenerateTag('B', 'A', 'S', 'E'); +const int32_t Tag::GDEF = GenerateTag('G', 'D', 'E', 'F'); +const int32_t Tag::GPOS = GenerateTag('G', 'P', 'O', 'S'); +const int32_t Tag::GSUB = GenerateTag('G', 'S', 'U', 'B'); +const int32_t Tag::JSTF = GenerateTag('J', 'S', 'T', 'F'); +const int32_t Tag::DSIG = GenerateTag('D', 'S', 'I', 'G'); +const int32_t Tag::gasp = GenerateTag('g', 'a', 's', 'p'); +const int32_t Tag::hdmx = GenerateTag('h', 'd', 'm', 'x'); +const int32_t Tag::kern = GenerateTag('k', 'e', 'r', 'n'); +const int32_t Tag::LTSH = GenerateTag('L', 'T', 'S', 'H'); +const int32_t Tag::PCLT = GenerateTag('P', 'C', 'L', 'T'); +const int32_t Tag::VDMX = GenerateTag('V', 'D', 'M', 'X'); +const int32_t Tag::vhea = GenerateTag('v', 'h', 'e', 'a'); +const int32_t Tag::vmtx = GenerateTag('v', 'm', 't', 'x'); +const int32_t Tag::bhed = GenerateTag('b', 'h', 'e', 'd'); +const int32_t Tag::bdat = GenerateTag('b', 'd', 'a', 't'); +const int32_t Tag::bloc = GenerateTag('b', 'l', 'o', 'c'); const int32_t CFF_TABLE_ORDERING[] = { Tag::head, diff --git a/sfntly/tag.h b/sfntly/tag.h index fe6da46..9e73007 100644 --- a/sfntly/tag.h +++ b/sfntly/tag.h @@ -82,7 +82,7 @@ struct Tag { static const int32_t bloc; }; -inline int32_t generate_tag(char a, char b, char c, char d) { +inline int32_t GenerateTag(char a, char b, char c, char d) { return (((int32_t)(a) << 24) | ((int32_t)(b) << 16) | ((int32_t)(c) << 8) | diff --git a/sfntly/tools/subsetter.cc b/sfntly/tools/subsetter.cc index 44ba22e..c234a1e 100644 --- a/sfntly/tools/subsetter.cc +++ b/sfntly/tools/subsetter.cc @@ -14,10 +14,11 @@ * limitations under the License. */ +#include "sfntly/tools/subsetter/subsetter.h" + #include #include -#include "sfntly/tools/subsetter/subsetter.h" #include "sfntly/tools/subsetter/glyph_table_subsetter.h" namespace sfntly { @@ -31,32 +32,32 @@ Subsetter::Subsetter(Font* font, FontFactory* font_factory) { } Subsetter::~Subsetter() { - font_factory_.release(); - font_.release(); + font_factory_.Release(); + font_.Release(); table_subsetters_.clear(); } -void Subsetter::setGlyphs(IntegerList* glyphs) { +void Subsetter::SetGlyphs(IntegerList* glyphs) { new_to_old_glyphs_ = *glyphs; } -void Subsetter::setCMaps(CMapIdList* cmap_ids, int32_t number) { +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) { +void Subsetter::SetRemoveTables(IntegerSet* remove_tables) { remove_tables_ = *remove_tables; } -CALLER_ATTACH Font::Builder* Subsetter::subset() { +CALLER_ATTACH Font::Builder* Subsetter::Subset() { FontBuilderPtr font_builder; - font_builder.attach(font_factory_->newFontBuilder()); + font_builder.Attach(font_factory_->NewFontBuilder()); IntegerSet table_tags; - for (TableMap::iterator i = font_->tables()->begin(), - e = font_->tables()->end(); i != e; ++i) { + for (TableMap::iterator i = font_->Tables()->begin(), + e = font_->Tables()->end(); i != e; ++i) { table_tags.insert(i->first); } if (!remove_tables_.empty()) { @@ -70,9 +71,9 @@ CALLER_ATTACH Font::Builder* Subsetter::subset() { 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); + bool handled = (*table_subsetter)->Subset(this, font_, font_builder); if (handled) { - IntegerSet* handled_tags = (*table_subsetter)->tagsHandled(); + IntegerSet* handled_tags = (*table_subsetter)->TagsHandled(); IntegerSet result; std::set_difference(table_tags.begin(), table_tags.end(), handled_tags->begin(), handled_tags->end(), @@ -82,24 +83,24 @@ CALLER_ATTACH Font::Builder* Subsetter::subset() { } for (IntegerSet::iterator tag = table_tags.begin(), tag_end = table_tags.end(); tag != tag_end; ++tag) { - Table* table = font_->table(*tag); + Table* table = font_->GetTable(*tag); if (table) { - // The newTableBuilder() call will alter internal state of font_builder + // The NewTableBuilder() call will alter internal state of font_builder // AND the reference count of returned object. Therefore we need to // dereference it. TableBuilderPtr dereference; - dereference.attach( - font_builder->newTableBuilder(*tag, table->readFontData())); + dereference.Attach( + font_builder->NewTableBuilder(*tag, table->ReadFontData())); } } - return font_builder.detach(); + return font_builder.Detach(); } -IntegerList* Subsetter::glyphPermutationTable() { +IntegerList* Subsetter::GlyphPermutationTable() { return &new_to_old_glyphs_; } -CMapIdList* Subsetter::cmapId() { +CMapIdList* Subsetter::CMapId() { return &cmap_ids_; } diff --git a/sfntly/tools/subsetter/glyph_table_subsetter.cc b/sfntly/tools/subsetter/glyph_table_subsetter.cc index 04d0c48..7609f74 100644 --- a/sfntly/tools/subsetter/glyph_table_subsetter.cc +++ b/sfntly/tools/subsetter/glyph_table_subsetter.cc @@ -14,11 +14,12 @@ * limitations under the License. */ +#include "sfntly/tools/subsetter/glyph_table_subsetter.h" + #include "sfntly/tag.h" #include "sfntly/glyph_table.h" #include "sfntly/loca_table.h" #include "sfntly/tools/subsetter/subsetter.h" -#include "sfntly/tools/subsetter/glyph_table_subsetter.h" #include "sfntly/port/exception_type.h" namespace sfntly { @@ -31,18 +32,19 @@ GlyphTableSubsetter::GlyphTableSubsetter() GlyphTableSubsetter::~GlyphTableSubsetter() {} -bool GlyphTableSubsetter::subset(Subsetter* subsetter, Font* font, +bool GlyphTableSubsetter::Subset(Subsetter* subsetter, + Font* font, Font::Builder* font_builder) { assert(font); assert(subsetter); assert(font_builder); - IntegerList* permutation_table = subsetter->glyphPermutationTable(); + IntegerList* permutation_table = subsetter->GlyphPermutationTable(); if (!permutation_table || permutation_table->empty()) return false; - GlyphTablePtr glyph_table = down_cast(font->table(Tag::glyf)); - LocaTablePtr loca_table = down_cast(font->table(Tag::loca)); + 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) return false; @@ -52,11 +54,11 @@ bool GlyphTableSubsetter::subset(Subsetter* subsetter, Font* font, } GlyphTableBuilderPtr glyph_table_builder; - glyph_table_builder.attach(down_cast( - font_builder->newTableBuilder(Tag::glyf))); + glyph_table_builder.Attach(down_cast( + font_builder->NewTableBuilder(Tag::glyf))); LocaTableBuilderPtr loca_table_builder; - loca_table_builder.attach(down_cast( - font_builder->newTableBuilder(Tag::loca))); + loca_table_builder.Attach(down_cast( + font_builder->NewTableBuilder(Tag::loca))); if (glyph_table_builder == NULL || loca_table_builder == NULL) { #if defined (SFNTLY_NO_EXCEPTION) return false; @@ -65,25 +67,25 @@ bool GlyphTableSubsetter::subset(Subsetter* subsetter, Font* font, #endif } GlyphTable::GlyphBuilderList* glyph_builders = - glyph_table_builder->glyphBuilders(); + 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); + int old_offset = loca_table->GlyphOffset(*old_glyph_id); + int old_length = loca_table->GlyphLength(*old_glyph_id); GlyphPtr glyph; - glyph.attach(glyph_table->glyph(old_offset, old_length)); - ReadableFontDataPtr data = glyph->readFontData(); + glyph.Attach(glyph_table->GetGlyph(old_offset, old_length)); + ReadableFontDataPtr data = glyph->ReadFontData(); WritableFontDataPtr copy_data; - copy_data.attach(font_builder->getNewData(data->length())); - data->copyTo(copy_data); + copy_data.Attach(font_builder->GetNewData(data->Length())); + data->CopyTo(copy_data); GlyphBuilderPtr glyph_builder; - glyph_builder.attach(glyph_table_builder->glyphBuilder(copy_data)); + 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); + glyph_table_builder->GenerateLocaList(&loca_list); + loca_table_builder->SetLocaList(&loca_list); return true; } diff --git a/sfntly/tools/subsetter/glyph_table_subsetter.h b/sfntly/tools/subsetter/glyph_table_subsetter.h index 14e3c3d..3687e27 100644 --- a/sfntly/tools/subsetter/glyph_table_subsetter.h +++ b/sfntly/tools/subsetter/glyph_table_subsetter.h @@ -27,7 +27,8 @@ class GlyphTableSubsetter : public TableSubsetterImpl, GlyphTableSubsetter(); virtual ~GlyphTableSubsetter(); - virtual bool subset(Subsetter* subsetter, Font* font, + virtual bool Subset(Subsetter* subsetter, + Font* font, Font::Builder* font_builder); }; diff --git a/sfntly/tools/subsetter/subsetter.h b/sfntly/tools/subsetter/subsetter.h index 01308b5..df417ad 100644 --- a/sfntly/tools/subsetter/subsetter.h +++ b/sfntly/tools/subsetter/subsetter.h @@ -31,7 +31,7 @@ class Subsetter : public RefCounted { Subsetter(Font* font, FontFactory* font_factory); virtual ~Subsetter(); - virtual void setGlyphs(IntegerList* glyphs); + 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 @@ -49,12 +49,12 @@ class Subsetter : public RefCounted { // 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 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(); + virtual void SetRemoveTables(IntegerSet* remove_tables); + virtual CALLER_ATTACH Font::Builder* Subset(); + virtual IntegerList* GlyphPermutationTable(); + virtual CMapIdList* CMapId(); private: FontPtr font_; diff --git a/sfntly/tools/subsetter/table_subsetter.h b/sfntly/tools/subsetter/table_subsetter.h index 9565da6..437705c 100644 --- a/sfntly/tools/subsetter/table_subsetter.h +++ b/sfntly/tools/subsetter/table_subsetter.h @@ -26,9 +26,9 @@ 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, + 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; diff --git a/sfntly/tools/subsetter/table_subsetter_impl.cc b/sfntly/tools/subsetter/table_subsetter_impl.cc index 481f10f..f239c78 100644 --- a/sfntly/tools/subsetter/table_subsetter_impl.cc +++ b/sfntly/tools/subsetter/table_subsetter_impl.cc @@ -27,11 +27,11 @@ TableSubsetterImpl::TableSubsetterImpl(const int32_t* tags, TableSubsetterImpl::~TableSubsetterImpl() {} -bool TableSubsetterImpl::tagHandled(int32_t tag) { +bool TableSubsetterImpl::TagHandled(int32_t tag) { return tags_.find(tag) != tags_.end(); } -IntegerSet* TableSubsetterImpl::tagsHandled() { +IntegerSet* TableSubsetterImpl::TagsHandled() { return &tags_; } diff --git a/sfntly/tools/subsetter/table_subsetter_impl.h b/sfntly/tools/subsetter/table_subsetter_impl.h index 7fabba8..162464a 100644 --- a/sfntly/tools/subsetter/table_subsetter_impl.h +++ b/sfntly/tools/subsetter/table_subsetter_impl.h @@ -25,8 +25,8 @@ 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(); + virtual bool TagHandled(int32_t tag); + virtual IntegerSet* TagsHandled(); protected: IntegerSet tags_; diff --git a/test/byte_array_test.cc b/test/byte_array_test.cc index 7c6efa9..89478f4 100644 --- a/test/byte_array_test.cc +++ b/test/byte_array_test.cc @@ -27,50 +27,50 @@ namespace byte_array_test { const int32_t BYTE_ARRAY_SIZES[] = {1, 7, 127, 128, 129, 255, 256, 257, 666, 1023, 10000, 0xffff, 0x10000}; -void fillTestByteArray(ByteArray* ba, int32_t size) { +void FillTestByteArray(ByteArray* ba, int32_t size) { for (int32_t i = 0; i < size; ++i) { - ba->put(i, (byte_t)(i % 256)); + ba->Put(i, (byte_t)(i % 256)); } } -void readByteArrayWithBuffer(ByteArray* ba, ByteVector* buffer, ByteVector* b) { - b->resize(ba->length()); +void ReadByteArrayWithBuffer(ByteArray* ba, ByteVector* buffer, ByteVector* b) { + b->resize(ba->Length()); int32_t index = 0; - while (index < ba->length()) { - int32_t bytes_read = ba->get(index, buffer); + while (index < ba->Length()) { + int32_t bytes_read = ba->Get(index, buffer); std::copy(buffer->begin(), buffer->begin() + bytes_read, b->begin() + index); index += bytes_read; } } -void readByteArrayWithSlidingWindow(ByteArray* ba, int window_size, +void ReadByteArrayWithSlidingWindow(ByteArray* ba, int window_size, ByteVector* b) { - b->resize(ba->length()); + b->resize(ba->Length()); int32_t index = 0; int32_t actual_window_size = window_size; - while (index < ba->length()) { + while (index < ba->Length()) { actual_window_size = std::min(actual_window_size, b->size() - index); - int32_t bytes_read = ba->get(index, b, index, actual_window_size); + int32_t bytes_read = ba->Get(index, b, index, actual_window_size); index += bytes_read; } } -bool readComparison(ByteArray* ba1, ByteArray* ba2) { +bool ReadComparison(ByteArray* ba1, ByteArray* ba2) { // single byte reads - for (int i = 0; i < ba1->length(); ++i) { - EXPECT_EQ(ba1->get(i), ba2->get(i)); + for (int i = 0; i < ba1->Length(); ++i) { + EXPECT_EQ(ba1->Get(i), ba2->Get(i)); } ByteVector b1, b2; // buffer reads - int increments = std::max(ba1->length() / 11, 1); - for (int buffer_size = 1; buffer_size < ba1->length(); + int increments = std::max(ba1->Length() / 11, 1); + for (int buffer_size = 1; buffer_size < ba1->Length(); buffer_size += increments) { ByteVector buffer(buffer_size); - readByteArrayWithBuffer(ba1, &buffer, &b1); - readByteArrayWithBuffer(ba2, &buffer, &b2); + ReadByteArrayWithBuffer(ba1, &buffer, &b1); + ReadByteArrayWithBuffer(ba2, &buffer, &b2); EXPECT_GT(b1.size(), static_cast(0)); EXPECT_EQ(b1.size(), b2.size()); EXPECT_TRUE(std::equal(b1.begin(), b1.end(), b2.begin())); @@ -79,10 +79,10 @@ bool readComparison(ByteArray* ba1, ByteArray* ba2) { // sliding window reads b1.clear(); b2.clear(); - for (int window_size = 1; window_size < ba1->length(); + for (int window_size = 1; window_size < ba1->Length(); window_size += increments) { - readByteArrayWithSlidingWindow(ba1, window_size, &b1); - readByteArrayWithSlidingWindow(ba2, window_size, &b2); + ReadByteArrayWithSlidingWindow(ba1, window_size, &b1); + ReadByteArrayWithSlidingWindow(ba2, window_size, &b2); EXPECT_GT(b1.size(), static_cast(0)); EXPECT_EQ(b1.size(), b2.size()); EXPECT_TRUE(std::equal(b1.begin(), b1.end(), b2.begin())); @@ -91,46 +91,46 @@ bool readComparison(ByteArray* ba1, ByteArray* ba2) { return true; } -bool copyTest(ByteArray* ba) { - ByteArrayPtr fixed_copy = new MemoryByteArray(ba->length()); - ba->copyTo(fixed_copy); - EXPECT_EQ(ba->length(), fixed_copy->length()); - EXPECT_TRUE(readComparison(ba, fixed_copy)); +bool CopyTest(ByteArray* ba) { + ByteArrayPtr fixed_copy = new MemoryByteArray(ba->Length()); + ba->CopyTo(fixed_copy); + EXPECT_EQ(ba->Length(), fixed_copy->Length()); + EXPECT_TRUE(ReadComparison(ba, fixed_copy)); ByteArrayPtr growable_copy = new GrowableMemoryByteArray(); - ba->copyTo(growable_copy); - EXPECT_EQ(ba->length(), growable_copy->length()); - EXPECT_TRUE(readComparison(ba, growable_copy)); + ba->CopyTo(growable_copy); + EXPECT_EQ(ba->Length(), growable_copy->Length()); + EXPECT_TRUE(ReadComparison(ba, growable_copy)); return true; } -bool byteArrayTester(ByteArray* ba) { - return copyTest(ba); +bool ByteArrayTester(ByteArray* ba) { + return CopyTest(ba); } } // namespace byte_array_test -bool testMemoryByteArray() { +bool TestMemoryByteArray() { for (size_t i = 0; i < sizeof(byte_array_test::BYTE_ARRAY_SIZES) / sizeof(int32_t); ++i) { int32_t size = byte_array_test::BYTE_ARRAY_SIZES[i]; fprintf(stderr, "fixed mem: iteration %ld, size %d\n", i, size); ByteArrayPtr ba = new MemoryByteArray(size); - byte_array_test::fillTestByteArray(ba, size); - EXPECT_TRUE(byte_array_test::byteArrayTester(ba)); + byte_array_test::FillTestByteArray(ba, size); + EXPECT_TRUE(byte_array_test::ByteArrayTester(ba)); } return true; } -bool testGrowableMemoryByteArray() { +bool TestGrowableMemoryByteArray() { for (size_t i = 0; i < sizeof(byte_array_test::BYTE_ARRAY_SIZES) / sizeof(int32_t); ++i) { int32_t size = byte_array_test::BYTE_ARRAY_SIZES[i]; fprintf(stderr, "growable mem: iteration %ld, size %d\n", i, size); ByteArrayPtr ba = new GrowableMemoryByteArray(); - byte_array_test::fillTestByteArray(ba, size); - EXPECT_TRUE(byte_array_test::byteArrayTester(ba)); + byte_array_test::FillTestByteArray(ba, size); + EXPECT_TRUE(byte_array_test::ByteArrayTester(ba)); } return true; } diff --git a/test/byte_array_test.h b/test/byte_array_test.h index 0d67ca8..88e8ce8 100644 --- a/test/byte_array_test.h +++ b/test/byte_array_test.h @@ -19,8 +19,8 @@ namespace sfntly { -bool testMemoryByteArray(); -bool testGrowableMemoryByteArray(); +bool TestMemoryByteArray(); +bool TestGrowableMemoryByteArray(); } // namespace sfntly diff --git a/test/endian_test.cc b/test/endian_test.cc index 887fed5..50beeeb 100644 --- a/test/endian_test.cc +++ b/test/endian_test.cc @@ -25,7 +25,7 @@ namespace sfntly { -bool testEndian() { +bool TestEndian() { byte_t test_data[] = { 0x68, 0x65, 0x61, 0x64, // 0: head 0xca, 0xca, 0xca, 0xca, // 4: ubyte, byte, char @@ -38,35 +38,35 @@ bool testEndian() { ByteArrayPtr ba1 = new GrowableMemoryByteArray(); for (size_t i = 0; i < sizeof(test_data); ++i) { - ba1->put(i, test_data[i]); + ba1->Put(i, test_data[i]); } ReadableFontDataPtr rfd = new ReadableFontData(ba1); - EXPECT_EQ(rfd->readULongAsInt(0), Tag::head); - EXPECT_EQ(rfd->readUByte(4), 202); - EXPECT_EQ(rfd->readByte(5), -54); - EXPECT_EQ(rfd->readChar(6), 202); - EXPECT_EQ(rfd->readUShort(8), 24); - EXPECT_EQ(rfd->readShort(10), -32744); - EXPECT_EQ(rfd->readUInt24(12), 24); - EXPECT_EQ(rfd->readULong(16), 24); - EXPECT_EQ(rfd->readLong(20), -256); - EXPECT_EQ(rfd->readFixed(24), Fixed1616::fixed(1, 0)); + EXPECT_EQ(rfd->ReadULongAsInt(0), Tag::head); + EXPECT_EQ(rfd->ReadUByte(4), 202); + EXPECT_EQ(rfd->ReadByte(5), -54); + EXPECT_EQ(rfd->ReadChar(6), 202); + EXPECT_EQ(rfd->ReadUShort(8), 24); + EXPECT_EQ(rfd->ReadShort(10), -32744); + EXPECT_EQ(rfd->ReadUInt24(12), 24); + EXPECT_EQ(rfd->ReadULong(16), 24); + EXPECT_EQ(rfd->ReadLong(20), -256); + EXPECT_EQ(rfd->ReadFixed(24), Fixed1616::Fixed(1, 0)); MemoryOutputStream os; FontOutputStream fos(&os); - fos.writeULong(Tag::head); - fos.write(202); - fos.write(202); - fos.write(202); - fos.write(202); - fos.writeUShort(24); - fos.writeShort(-32744); - fos.writeUInt24(24); - fos.writeChar(0); - fos.writeULong(24); - fos.writeLong(-256); - fos.writeFixed(Fixed1616::fixed(1, 0)); - EXPECT_EQ(memcmp(os.get(), test_data, sizeof(test_data)), 0); + fos.WriteULong(Tag::head); + fos.Write(202); + fos.Write(202); + fos.Write(202); + fos.Write(202); + fos.WriteUShort(24); + fos.WriteShort(-32744); + fos.WriteUInt24(24); + fos.WriteChar(0); + fos.WriteULong(24); + fos.WriteLong(-256); + fos.WriteFixed(Fixed1616::Fixed(1, 0)); + EXPECT_EQ(memcmp(os.Get(), test_data, sizeof(test_data)), 0); return true; } diff --git a/test/endian_test.h b/test/endian_test.h index ce96251..8fc36ff 100644 --- a/test/endian_test.h +++ b/test/endian_test.h @@ -19,7 +19,7 @@ namespace sfntly { -bool testEndian(); +bool TestEndian(); } // namespace sfntly diff --git a/test/file_io_test.cc b/test/file_io_test.cc index 1c02b0a..6c48a27 100644 --- a/test/file_io_test.cc +++ b/test/file_io_test.cc @@ -23,7 +23,7 @@ namespace sfntly { -bool testFileInputStream() { +bool TestFileInputStream() { FILE* file_handle = NULL; #if defined (WIN32) fopen_s(&file_handle, SAMPLE_TTF_FILE, "rb"); @@ -44,47 +44,47 @@ bool testFileInputStream() { // Full file reading test FileInputStream is; - is.open(SAMPLE_TTF_FILE); - EXPECT_EQ(length, (size_t)is.available()); + is.Open(SAMPLE_TTF_FILE); + EXPECT_EQ(length, (size_t)is.Available()); ByteVector b2; - is.read(&b2, 0, length); - is.close(); + is.Read(&b2, 0, length); + is.Close(); EXPECT_EQ(memcmp(&(b1[0]), &(b2[0]), length), 0); b2.clear(); // Partial reading test - is.open(SAMPLE_TTF_FILE); - is.skip(89); - is.read(&b2, 0, 100); + is.Open(SAMPLE_TTF_FILE); + is.Skip(89); + is.Read(&b2, 0, 100); EXPECT_EQ(memcmp(&(b1[89]), &(b2[0]), 100), 0); b2.clear(); // Skip test - is.skip(-89); - is.read(&b2, 0, 100); + is.Skip(-89); + is.Read(&b2, 0, 100); EXPECT_EQ(memcmp(&(b1[100]), &(b2[0]), 100), 0); b2.clear(); - is.skip(100); - is.read(&b2, 0, 100); + is.Skip(100); + is.Read(&b2, 0, 100); EXPECT_EQ(memcmp(&(b1[300]), &(b2[0]), 100), 0); - is.skip(-400); + is.Skip(-400); b2.clear(); // Offset test - is.read(&b2, 0, 100); - is.read(&b2, 100, 100); + is.Read(&b2, 0, 100); + is.Read(&b2, 100, 100); EXPECT_EQ(memcmp(&(b1[0]), &(b2[0]), 200), 0); // Unread test ByteVector b3; b3.resize(200); - is.unread(&b3); + is.Unread(&b3); EXPECT_EQ(memcmp(&(b3[0]), &(b2[0]), 200), 0); return true; } -bool testFontInputStreamBasic() { +bool TestFontInputStreamBasic() { FILE* file_handle = NULL; #if defined (WIN32) fopen_s(&file_handle, SAMPLE_TTF_FILE, "rb"); @@ -104,47 +104,47 @@ bool testFontInputStreamBasic() { fclose(file_handle); FileInputStream is; - is.open(SAMPLE_TTF_FILE); + is.Open(SAMPLE_TTF_FILE); FontInputStream font_is1(&is); - EXPECT_EQ((size_t)font_is1.available(), length); + EXPECT_EQ((size_t)font_is1.Available(), length); ByteVector b2; - font_is1.read(&b2, 0, length); - font_is1.close(); + font_is1.Read(&b2, 0, length); + font_is1.Close(); EXPECT_EQ(memcmp(&(b1[0]), &(b2[0]), length), 0); b2.clear(); - is.open(SAMPLE_TTF_FILE); - is.skip(89); + is.Open(SAMPLE_TTF_FILE); + is.Skip(89); FontInputStream font_is2(&is, 200); - font_is2.read(&b2, 0, 100); + font_is2.Read(&b2, 0, 100); EXPECT_EQ(memcmp(&(b1[89]), &(b2[0]), 100), 0); - font_is2.read(&b2, 100, 100); + font_is2.Read(&b2, 100, 100); EXPECT_EQ(memcmp(&(b1[89]), &(b2[0]), 200), 0); b2.clear(); - font_is2.skip(-200); - font_is2.read(&b2, 0, 100); + font_is2.Skip(-200); + font_is2.Read(&b2, 0, 100); EXPECT_EQ(memcmp(&(b1[89]), &(b2[0]), 100), 0); return true; } -bool testFontInputStreamTableLoading() { +bool TestFontInputStreamTableLoading() { FileInputStream is; - is.open(SAMPLE_TTF_FILE); + is.Open(SAMPLE_TTF_FILE); FontInputStream font_is(&is); - font_is.skip(TTF_OFFSET[SAMPLE_TTF_GDEF]); + font_is.Skip(TTF_OFFSET[SAMPLE_TTF_GDEF]); FontInputStream gdef_is(&font_is, TTF_LENGTH[SAMPLE_TTF_GDEF]); ByteVector gdef_data; - gdef_is.read(&gdef_data, 0, TTF_LENGTH[SAMPLE_TTF_GDEF]); + gdef_is.Read(&gdef_data, 0, TTF_LENGTH[SAMPLE_TTF_GDEF]); EXPECT_EQ(memcmp(&(gdef_data[0]), TTF_GDEF_DATA, TTF_LENGTH[SAMPLE_TTF_GDEF]), 0); - font_is.skip(TTF_OFFSET[SAMPLE_TTF_HEAD] - font_is.position()); + font_is.Skip(TTF_OFFSET[SAMPLE_TTF_HEAD] - font_is.position()); FontInputStream head_is(&font_is, TTF_LENGTH[SAMPLE_TTF_HEAD]); ByteVector head_data; - head_is.read(&head_data, 0, TTF_LENGTH[SAMPLE_TTF_HEAD]); + head_is.Read(&head_data, 0, TTF_LENGTH[SAMPLE_TTF_HEAD]); EXPECT_EQ(memcmp(&(head_data[0]), TTF_HEAD_DATA, TTF_LENGTH[SAMPLE_TTF_HEAD]), 0); diff --git a/test/file_io_test.h b/test/file_io_test.h index ab5c109..9ff1972 100644 --- a/test/file_io_test.h +++ b/test/file_io_test.h @@ -19,9 +19,9 @@ namespace sfntly { -bool testFileInputStream(); -bool testFontInputStreamBasic(); -bool testFontInputStreamTableLoading(); +bool TestFileInputStream(); +bool TestFontInputStreamBasic(); +bool TestFontInputStreamTableLoading(); } // namespace sfntly diff --git a/test/font_data_test.cc b/test/font_data_test.cc index ad30522..3686856 100644 --- a/test/font_data_test.cc +++ b/test/font_data_test.cc @@ -28,87 +28,91 @@ namespace sfntly { const int32_t BYTE_ARRAY_SIZES[] = {1, 7, 127, 128, 129, 255, 256, 257, 666, 1023, 0x10000}; -void fillTestByteArray(ByteArray* ba, int32_t size) { +void FillTestByteArray(ByteArray* ba, int32_t size) { for (int32_t i = 0; i < size; ++i) { - ba->put(i, (byte_t)(i % 256)); + ba->Put(i, (byte_t)(i % 256)); } } -void readFontDataWithSingleByte(ReadableFontData* rfd, ByteVector* buffer) { - buffer->resize(rfd->length()); - for (int32_t index = 0; index < rfd->length(); ++index) { - (*buffer)[index] = (byte_t)(rfd->readByte(index)); +void ReadFontDataWithSingleByte(ReadableFontData* rfd, ByteVector* buffer) { + buffer->resize(rfd->Length()); + for (int32_t index = 0; index < rfd->Length(); ++index) { + (*buffer)[index] = (byte_t)(rfd->ReadByte(index)); } } -void readFontDataWithBuffer(ReadableFontData* rfd, int32_t buffer_size, +void ReadFontDataWithBuffer(ReadableFontData* rfd, + int32_t buffer_size, ByteVector* b) { ByteVector buffer(buffer_size); - b->resize(rfd->length()); + b->resize(rfd->Length()); int32_t index = 0; - while (index < rfd->length()) { - int32_t bytes_read = rfd->readBytes(index, &buffer, 0, buffer.size()); + while (index < rfd->Length()) { + int32_t bytes_read = rfd->ReadBytes(index, &buffer, 0, buffer.size()); EXPECT_GE(bytes_read, 0); std::copy(buffer.begin(), buffer.begin() + bytes_read, b->begin() + index); index += bytes_read; } } -void readFontDataWithSlidingWindow(ReadableFontData* rfd, int32_t window_size, +void ReadFontDataWithSlidingWindow(ReadableFontData* rfd, int32_t window_size, ByteVector* b) { - b->resize(rfd->length()); + b->resize(rfd->Length()); int32_t index = 0; - while (index < rfd->length()) { + while (index < rfd->Length()) { int32_t actual_window_size = std::min(window_size, b->size() - index); - int32_t bytes_read = rfd->readBytes(index, b, index, actual_window_size); + int32_t bytes_read = rfd->ReadBytes(index, b, index, actual_window_size); EXPECT_GE(bytes_read, 0); index += bytes_read; } } -void writeFontDataWithSingleByte(ReadableFontData* rfd, WritableFontData* wfd) { - for (int32_t index = 0; index < rfd->length(); ++index) { - byte_t b = (byte_t)(rfd->readByte(index)); - wfd->writeByte(index, b); +void WriteFontDataWithSingleByte(ReadableFontData* rfd, WritableFontData* wfd) { + for (int32_t index = 0; index < rfd->Length(); ++index) { + byte_t b = (byte_t)(rfd->ReadByte(index)); + wfd->WriteByte(index, b); } } -void writeFontDataWithBuffer(ReadableFontData* rfd, WritableFontData* wfd, +void WriteFontDataWithBuffer(ReadableFontData* rfd, + WritableFontData* wfd, int32_t buffer_size) { ByteVector buffer(buffer_size); int32_t index = 0; - while (index < rfd->length()) { - int32_t bytesRead = rfd->readBytes(index, &buffer, 0, buffer.size()); - wfd->writeBytes(index, &buffer, 0, buffer.size()); + while (index < rfd->Length()) { + int32_t bytesRead = rfd->ReadBytes(index, &buffer, 0, buffer.size()); + wfd->WriteBytes(index, &buffer, 0, buffer.size()); index += bytesRead; } } -void writeFontDataWithSlidingWindow(ReadableFontData* rfd, +void WriteFontDataWithSlidingWindow(ReadableFontData* rfd, WritableFontData* wfd, int32_t window_size) { - ByteVector b(rfd->length()); + ByteVector b(rfd->Length()); int32_t index = 0; - while (index < rfd->length()) { + while (index < rfd->Length()) { int32_t sliding_size = std::min(window_size, b.size() - index); - int32_t bytes_read = rfd->readBytes(index, &b, index, sliding_size); - wfd->writeBytes(index, &b, index, sliding_size); + int32_t bytes_read = rfd->ReadBytes(index, &b, index, sliding_size); + wfd->WriteBytes(index, &b, index, sliding_size); index += bytes_read; } } -bool readComparison(int32_t offset, int32_t length, ReadableFontData* rfd1, +bool ReadComparison(int32_t offset, + int32_t length, + ReadableFontData* rfd1, ReadableFontData* rfd2) { - EXPECT_TRUE(length == rfd2->length()); + EXPECT_TRUE(length == rfd2->Length()); ByteVector b1, b2; b1.resize(length); b2.resize(length); // single byte reads - readFontDataWithSingleByte(rfd1, &b1); - readFontDataWithSingleByte(rfd2, &b2); + ReadFontDataWithSingleByte(rfd1, &b1); + ReadFontDataWithSingleByte(rfd2, &b2); EXPECT_EQ(memcmp(&(b1[offset]), &(b2[0]), length), 0); // buffer reads @@ -119,8 +123,8 @@ bool readComparison(int32_t offset, int32_t length, ReadableFontData* rfd1, b2.clear(); b1.resize(length); b2.resize(length); - readFontDataWithBuffer(rfd1, buffer_size, &b1); - readFontDataWithBuffer(rfd2, buffer_size, &b2); + ReadFontDataWithBuffer(rfd1, buffer_size, &b1); + ReadFontDataWithBuffer(rfd2, buffer_size, &b2); int result = memcmp(&(b1[offset]), &(b2[0]), length); EXPECT_EQ(result, 0); } @@ -132,80 +136,80 @@ bool readComparison(int32_t offset, int32_t length, ReadableFontData* rfd1, b2.clear(); b1.resize(length); b2.resize(length); - readFontDataWithSlidingWindow(rfd1, window_size, &b1); - readFontDataWithSlidingWindow(rfd2, window_size, &b2); + ReadFontDataWithSlidingWindow(rfd1, window_size, &b1); + ReadFontDataWithSlidingWindow(rfd2, window_size, &b2); int result = memcmp(&(b1[offset]), &(b2[0]), length); EXPECT_EQ(result, 0); } return true; } -void slicingReadTest(ReadableFontData* rfd) { - for (int32_t trim = 0; trim < (rfd->length() / 2) + 1; - trim += (rfd->length() / 21) + 1) { +void SlicingReadTest(ReadableFontData* rfd) { + for (int32_t trim = 0; trim < (rfd->Length() / 2) + 1; + trim += (rfd->Length() / 21) + 1) { fprintf(stderr, "\tread - trim = %d\n", trim); - int32_t length = rfd->length() - 2 * trim; + int32_t length = rfd->Length() - 2 * trim; ReadableFontDataPtr slice; - slice.attach(down_cast(rfd->slice(trim, length))); - EXPECT_TRUE(readComparison(trim, length, rfd, slice)); + slice.Attach(down_cast(rfd->Slice(trim, length))); + EXPECT_TRUE(ReadComparison(trim, length, rfd, slice)); } } -void slicingWriteTest(ReadableFontData* rfd, WritableFontData* wfd) { - for (int32_t trim = 0; trim < (rfd->length() / 2) + 1; - trim += (rfd->length() / 21) + 1) { +void SlicingWriteTest(ReadableFontData* rfd, WritableFontData* wfd) { + for (int32_t trim = 0; trim < (rfd->Length() / 2) + 1; + trim += (rfd->Length() / 21) + 1) { fprintf(stderr, "\twrite - trim = %d\n", trim); - int32_t length = rfd->length() - 2 * trim; + int32_t length = rfd->Length() - 2 * trim; WritableFontDataPtr w_slice; ReadableFontDataPtr r_slice; // single byte writes - w_slice.attach(down_cast(wfd->slice(trim, length))); - r_slice.attach(down_cast(rfd->slice(trim, length))); - writeFontDataWithSingleByte(r_slice, w_slice); - EXPECT_TRUE(readComparison(trim, length, rfd, w_slice)); + w_slice.Attach(down_cast(wfd->Slice(trim, length))); + r_slice.Attach(down_cast(rfd->Slice(trim, length))); + WriteFontDataWithSingleByte(r_slice, w_slice); + EXPECT_TRUE(ReadComparison(trim, length, rfd, w_slice)); // buffer writes int32_t increments = std::max(length / 11, 1); for (int32_t buffer_size = 1; buffer_size < length; buffer_size += increments) { - w_slice.attach(down_cast(wfd->slice(trim, length))); - r_slice.attach(down_cast(rfd->slice(trim, length))); - writeFontDataWithBuffer(r_slice, w_slice, buffer_size); - EXPECT_TRUE(readComparison(trim, length, rfd, w_slice)); + w_slice.Attach(down_cast(wfd->Slice(trim, length))); + r_slice.Attach(down_cast(rfd->Slice(trim, length))); + WriteFontDataWithBuffer(r_slice, w_slice, buffer_size); + EXPECT_TRUE(ReadComparison(trim, length, rfd, w_slice)); } // sliding window writes for (int window_size = 1; window_size < length; window_size += increments) { - w_slice.attach(down_cast(wfd->slice(trim, length))); - r_slice.attach(down_cast(rfd->slice(trim, length))); - writeFontDataWithSlidingWindow(r_slice, w_slice, window_size); - EXPECT_TRUE(readComparison(trim, length, rfd, w_slice)); + w_slice.Attach(down_cast(wfd->Slice(trim, length))); + r_slice.Attach(down_cast(rfd->Slice(trim, length))); + WriteFontDataWithSlidingWindow(r_slice, w_slice, window_size); + EXPECT_TRUE(ReadComparison(trim, length, rfd, w_slice)); } } } -bool testReadableFontData() { +bool TestReadableFontData() { for (size_t i = 0; i < sizeof(BYTE_ARRAY_SIZES) / sizeof(int32_t); ++i) { int32_t size = BYTE_ARRAY_SIZES[i]; ByteArrayPtr ba = new MemoryByteArray(size); - fillTestByteArray(ba, size); + FillTestByteArray(ba, size); ReadableFontDataPtr rfd = new ReadableFontData(ba); - slicingReadTest(rfd); + SlicingReadTest(rfd); } return true; } -bool testWritableFontData() { +bool TestWritableFontData() { for (size_t i = 0; i < sizeof(BYTE_ARRAY_SIZES) / sizeof(int32_t); ++i) { int32_t size = BYTE_ARRAY_SIZES[i]; ByteArrayPtr ba = new MemoryByteArray(size); - fillTestByteArray(ba, size); + FillTestByteArray(ba, size); WritableFontDataPtr wfd = new WritableFontData(ba); - slicingReadTest(wfd); + SlicingReadTest(wfd); ByteArrayPtr temp = new MemoryByteArray(size); WritableFontDataPtr wfd_copy = new WritableFontData(temp); - slicingWriteTest(wfd, wfd_copy); + SlicingWriteTest(wfd, wfd_copy); } return true; } diff --git a/test/font_data_test.h b/test/font_data_test.h index 78e910d..bca1924 100644 --- a/test/font_data_test.h +++ b/test/font_data_test.h @@ -18,8 +18,8 @@ #define TYPOGRAPHY_FONT_SFNTLY_SRC_TEST_FONT_DATA_TEST_H_ namespace sfntly { - bool testReadableFontData(); - bool testWritableFontData(); + bool TestReadableFontData(); + bool TestWritableFontData(); } #endif // TYPOGRAPHY_FONT_SFNTLY_SRC_TEST_FONT_DATA_TEST_H_ diff --git a/test/font_parsing_test.cc b/test/font_parsing_test.cc index 3c9f732..71446ec 100644 --- a/test/font_parsing_test.cc +++ b/test/font_parsing_test.cc @@ -30,52 +30,52 @@ namespace sfntly { -bool testFontParsing() { +bool TestFontParsing() { ByteVector input_buffer; - loadFile(SAMPLE_TTF_FILE, &input_buffer); + LoadFile(SAMPLE_TTF_FILE, &input_buffer); ByteArrayPtr ba = new MemoryByteArray(&(input_buffer[0]), input_buffer.size()); - FontFactoryPtr factory = FontFactory::getInstance(); + FontFactoryPtr factory = FontFactory::GetInstance(); // File based FontBuilderArray font_builder_array; - builderForFontFile(SAMPLE_TTF_FILE, factory, &font_builder_array); + BuilderForFontFile(SAMPLE_TTF_FILE, factory, &font_builder_array); FontBuilderPtr font_builder = font_builder_array[0]; // Memory based FontBuilderArray font_builder_array2; - factory->loadFontsForBuilding(ba, &font_builder_array2); + factory->LoadFontsForBuilding(ba, &font_builder_array2); FontBuilderPtr font_builder2 = font_builder_array2[0]; for (size_t i = 0; i < SAMPLE_TTF_KNOWN_TAGS; ++i) { - EXPECT_TRUE(font_builder->hasTableBuilder(TTF_KNOWN_TAGS[i])); - EXPECT_TRUE(font_builder2->hasTableBuilder(TTF_KNOWN_TAGS[i])); + EXPECT_TRUE(font_builder->HasTableBuilder(TTF_KNOWN_TAGS[i])); + EXPECT_TRUE(font_builder2->HasTableBuilder(TTF_KNOWN_TAGS[i])); } // Generic table Ptr gdef_builder = down_cast( - font_builder->getTableBuilder(Tag::GDEF)); + font_builder->GetTableBuilder(Tag::GDEF)); Ptr gdef_header = gdef_builder->header(); EXPECT_EQ(gdef_header->length(), TTF_LENGTH[SAMPLE_TTF_GDEF]); EXPECT_EQ(gdef_header->offset(), TTF_OFFSET[SAMPLE_TTF_GDEF]); EXPECT_EQ(gdef_header->checksum(), TTF_CHECKSUM[SAMPLE_TTF_GDEF]); - EXPECT_TRUE(gdef_header->checksumValid()); + EXPECT_TRUE(gdef_header->checksum_valid()); - WritableFontDataPtr wfd = gdef_builder->data(); + WritableFontDataPtr wfd = gdef_builder->Data(); ByteVector b; b.resize(TTF_LENGTH[SAMPLE_TTF_GDEF]); - wfd->readBytes(0, &b, 0, TTF_LENGTH[SAMPLE_TTF_GDEF]); + wfd->ReadBytes(0, &b, 0, TTF_LENGTH[SAMPLE_TTF_GDEF]); EXPECT_EQ(memcmp(&(b[0]), TTF_GDEF_DATA, TTF_LENGTH[SAMPLE_TTF_GDEF]), 0); // Header table FontHeaderTableBuilderPtr header_builder = down_cast( - font_builder->getTableBuilder(Tag::head)); + font_builder->GetTableBuilder(Tag::head)); Ptr header_header = header_builder->header(); EXPECT_EQ(header_header->length(), TTF_LENGTH[SAMPLE_TTF_HEAD]); EXPECT_EQ(header_header->offset(), TTF_OFFSET[SAMPLE_TTF_HEAD]); EXPECT_EQ(header_header->checksum(), TTF_CHECKSUM[SAMPLE_TTF_HEAD]); - EXPECT_TRUE(header_header->checksumValid()); + EXPECT_TRUE(header_header->checksum_valid()); // Data conformance for (size_t i = 0; i < SAMPLE_TTF_KNOWN_TAGS; ++i) { @@ -83,46 +83,46 @@ bool testFontParsing() { b1.resize(TTF_LENGTH[i]); b2.resize(TTF_LENGTH[i]); TableBuilderPtr builder1 = - font_builder->getTableBuilder(TTF_KNOWN_TAGS[i]); + font_builder->GetTableBuilder(TTF_KNOWN_TAGS[i]); TableBuilderPtr builder2 = - font_builder2->getTableBuilder(TTF_KNOWN_TAGS[i]); - WritableFontDataPtr wfd1 = builder1->data(); - WritableFontDataPtr wfd2 = builder2->data(); - wfd1->readBytes(0, &b1, 0, TTF_LENGTH[i]); - wfd2->readBytes(0, &b2, 0, TTF_LENGTH[i]); + font_builder2->GetTableBuilder(TTF_KNOWN_TAGS[i]); + WritableFontDataPtr wfd1 = builder1->Data(); + WritableFontDataPtr wfd2 = builder2->Data(); + wfd1->ReadBytes(0, &b1, 0, TTF_LENGTH[i]); + wfd2->ReadBytes(0, &b2, 0, TTF_LENGTH[i]); EXPECT_EQ(memcmp(&(b1[0]), &(b2[0]), TTF_LENGTH[i]), 0); } return true; } -bool testTTFReadWrite() { - FontFactoryPtr factory = FontFactory::getInstance(); +bool TestTTFReadWrite() { + FontFactoryPtr factory = FontFactory::GetInstance(); FontBuilderArray font_builder_array; - builderForFontFile(SAMPLE_TTF_FILE, factory, &font_builder_array); + BuilderForFontFile(SAMPLE_TTF_FILE, factory, &font_builder_array); FontBuilderPtr font_builder = font_builder_array[0]; - FontPtr font = font_builder->build(); + FontPtr font = font_builder->Build(); MemoryOutputStream output_stream; - factory->serializeFont(font, &output_stream); - EXPECT_GE(output_stream.size(), SAMPLE_TTF_SIZE); + factory->SerializeFont(font, &output_stream); + EXPECT_GE(output_stream.Size(), SAMPLE_TTF_SIZE); return true; } -bool testTTFMemoryBasedReadWrite() { +bool TestTTFMemoryBasedReadWrite() { ByteVector input_buffer; - loadFile(SAMPLE_TTF_FILE, &input_buffer); + LoadFile(SAMPLE_TTF_FILE, &input_buffer); - FontFactoryPtr factory = FontFactory::getInstance(); + FontFactoryPtr factory = FontFactory::GetInstance(); FontBuilderArray font_builder_array; ByteArrayPtr ba = new MemoryByteArray(&(input_buffer[0]), input_buffer.size()); - factory->loadFontsForBuilding(ba, &font_builder_array); + factory->LoadFontsForBuilding(ba, &font_builder_array); FontBuilderPtr font_builder = font_builder_array[0]; - FontPtr font = font_builder->build(); + FontPtr font = font_builder->Build(); MemoryOutputStream output_stream; - factory->serializeFont(font, &output_stream); - EXPECT_GE(output_stream.size(), input_buffer.size()); + factory->SerializeFont(font, &output_stream); + EXPECT_GE(output_stream.Size(), input_buffer.size()); return true; } diff --git a/test/font_parsing_test.h b/test/font_parsing_test.h index d66689f..7b69a27 100644 --- a/test/font_parsing_test.h +++ b/test/font_parsing_test.h @@ -19,9 +19,9 @@ namespace sfntly { -bool testFontParsing(); -bool testTTFReadWrite(); -bool testTTFMemoryBasedReadWrite(); +bool TestFontParsing(); +bool TestTTFReadWrite(); +bool TestTTFMemoryBasedReadWrite(); } // namespace sfntly diff --git a/test/main.cc b/test/main.cc index 0838b94..2c77eda 100644 --- a/test/main.cc +++ b/test/main.cc @@ -35,60 +35,60 @@ namespace sfntly { TEST(SmartPointer, All) { - EXPECT_TRUE(testSmartPointer()); + EXPECT_TRUE(TestSmartPointer()); } TEST(Endian, All) { - EXPECT_TRUE(sfntly::testEndian()); + EXPECT_TRUE(sfntly::TestEndian()); } #if defined RUN_LENGTHY_TESTS TEST(ByteArray, All) { - EXPECT_TRUE(sfntly::testMemoryByteArray()); - EXPECT_TRUE(sfntly::testGrowableMemoryByteArray()); + EXPECT_TRUE(sfntly::TestMemoryByteArray()); + EXPECT_TRUE(sfntly::TestGrowableMemoryByteArray()); } #endif #if defined RUN_LENGTHY_TESTS TEST(FontData, All) { - EXPECT_TRUE(sfntly::testReadableFontData()); - EXPECT_TRUE(sfntly::testWritableFontData()); + EXPECT_TRUE(sfntly::TestReadableFontData()); + EXPECT_TRUE(sfntly::TestWritableFontData()); } #endif TEST(FileIO, All) { - EXPECT_TRUE(sfntly::testFileInputStream()); - EXPECT_TRUE(sfntly::testFontInputStreamBasic()); - EXPECT_TRUE(sfntly::testFontInputStreamTableLoading()); + EXPECT_TRUE(sfntly::TestFileInputStream()); + EXPECT_TRUE(sfntly::TestFontInputStreamBasic()); + EXPECT_TRUE(sfntly::TestFontInputStreamTableLoading()); } TEST(OpenTypeData, All) { - EXPECT_TRUE(sfntly::testOTFRead()); - EXPECT_TRUE(sfntly::testOTFCopy()); + EXPECT_TRUE(sfntly::TestOTFRead()); + EXPECT_TRUE(sfntly::TestOTFCopy()); } TEST(FontParsing, All) { - EXPECT_TRUE(sfntly::testFontParsing()); - EXPECT_TRUE(sfntly::testTTFReadWrite()); - EXPECT_TRUE(sfntly::testTTFMemoryBasedReadWrite()); + EXPECT_TRUE(sfntly::TestFontParsing()); + EXPECT_TRUE(sfntly::TestTTFReadWrite()); + EXPECT_TRUE(sfntly::TestTTFMemoryBasedReadWrite()); } TEST(OTFBasicEditing, All) { - EXPECT_TRUE(sfntly::testOTFBasicEditing()); + EXPECT_TRUE(sfntly::TestOTFBasicEditing()); } TEST(NameEditing, All) { - EXPECT_TRUE(sfntly::testChangeOneName()); - EXPECT_TRUE(sfntly::testModifyNameTableAndRevert()); - EXPECT_TRUE(sfntly::testRemoveOneName()); + EXPECT_TRUE(sfntly::TestChangeOneName()); + EXPECT_TRUE(sfntly::TestModifyNameTableAndRevert()); + EXPECT_TRUE(sfntly::TestRemoveOneName()); } TEST(TestUtils, Extension) { - EXPECT_TRUE(sfntly::testExtension()); + EXPECT_TRUE(sfntly::TestExtension()); } TEST(TestUtils, Encoding) { - EXPECT_TRUE(sfntly::testEncoding()); + EXPECT_TRUE(sfntly::TestEncoding()); } } // namespace sfntly diff --git a/test/name_editing_test.cc b/test/name_editing_test.cc index 7b87b78..6822bf0 100644 --- a/test/name_editing_test.cc +++ b/test/name_editing_test.cc @@ -36,49 +36,49 @@ namespace sfntly { static ByteVector input_buffer; static ByteArrayPtr ba; -void loadTestFile(FontFactory* factory, FontBuilderArray* font_builders) { +void LoadTestFile(FontFactory* factory, FontBuilderArray* font_builders) { assert(factory); assert(font_builders); if (ba == NULL) { - loadFile(SAMPLE_TTF_FILE, &input_buffer); + LoadFile(SAMPLE_TTF_FILE, &input_buffer); ba = new MemoryByteArray(&(input_buffer[0]), input_buffer.size()); } - factory->loadFontsForBuilding(ba, font_builders); + factory->LoadFontsForBuilding(ba, font_builders); } -bool testChangeOneName() { - FontFactoryPtr factory = FontFactory::getInstance(); +bool TestChangeOneName() { + FontFactoryPtr factory = FontFactory::GetInstance(); FontBuilderArray font_builder_array; - loadTestFile(factory, &font_builder_array); + LoadTestFile(factory, &font_builder_array); FontBuilderPtr font_builder = font_builder_array[0]; NameTableBuilderPtr name_builder = down_cast( - font_builder->getTableBuilder(Tag::name)); + font_builder->GetTableBuilder(Tag::name)); // Change the font name. NameEntryBuilderPtr neb = - name_builder->nameBuilder(PlatformId::kWindows, + name_builder->NameBuilder(PlatformId::kWindows, WindowsEncodingId::kUnicodeUCS2, WindowsLanguageId::kEnglish_UnitedStates, NameId::kFontFamilyName); U_STRING_DECL(new_name, "Timothy", 7); - neb->setName(new_name); + neb->SetName(new_name); // Build the font. - FontPtr font = font_builder->build(); + FontPtr font = font_builder->Build(); // Serialize and reload the serialized font. MemoryOutputStream os; - factory->serializeFont(font, &os); + factory->SerializeFont(font, &os); FontArray font_array; - ByteArrayPtr new_ba = new MemoryByteArray(os.get(), os.size()); - factory->loadFonts(new_ba, &font_array); + ByteArrayPtr new_ba = new MemoryByteArray(os.Get(), os.Size()); + factory->LoadFonts(new_ba, &font_array); FontPtr new_font = font_array[0]; // Check the font name. - NameTablePtr name_table = down_cast(font->table(Tag::name)); - UChar* name = name_table->name(PlatformId::kWindows, + NameTablePtr name_table = down_cast(font->GetTable(Tag::name)); + UChar* name = name_table->Name(PlatformId::kWindows, WindowsEncodingId::kUnicodeUCS2, WindowsLanguageId::kEnglish_UnitedStates, NameId::kFontFamilyName); @@ -88,86 +88,86 @@ bool testChangeOneName() { return true; } -bool testModifyNameTableAndRevert() { - FontFactoryPtr factory = FontFactory::getInstance(); +bool TestModifyNameTableAndRevert() { + FontFactoryPtr factory = FontFactory::GetInstance(); FontBuilderArray font_builder_array; - loadTestFile(factory, &font_builder_array); + LoadTestFile(factory, &font_builder_array); FontBuilderPtr font_builder = font_builder_array[0]; NameTableBuilderPtr name_builder = down_cast( - font_builder->getTableBuilder(Tag::name)); + font_builder->GetTableBuilder(Tag::name)); // Change the font name. NameEntryBuilderPtr neb = - name_builder->nameBuilder(PlatformId::kWindows, + name_builder->NameBuilder(PlatformId::kWindows, WindowsEncodingId::kUnicodeUCS2, WindowsLanguageId::kEnglish_UnitedStates, NameId::kFontFamilyName); - NameTable::NameEntry* neb_entry = neb->entry(); - UChar* original_name = neb_entry->name(); + NameTable::NameEntry* neb_entry = neb->name_entry(); + UChar* original_name = neb_entry->Name(); EXPECT_TRUE(original_name != NULL); U_STRING_DECL(new_name, "Timothy", 7); - neb->setName(new_name); - name_builder->revertNames(); + neb->SetName(new_name); + name_builder->RevertNames(); // Build the font. - FontPtr font = font_builder->build(); + FontPtr font = font_builder->Build(); // Serialize and reload the serialized font. MemoryOutputStream os; - factory->serializeFont(font, &os); + factory->SerializeFont(font, &os); FontArray font_array; - ByteArrayPtr new_ba = new MemoryByteArray(os.get(), os.size()); - factory->loadFonts(new_ba, &font_array); + ByteArrayPtr new_ba = new MemoryByteArray(os.Get(), os.Size()); + factory->LoadFonts(new_ba, &font_array); FontPtr new_font = font_array[0]; // Check the font name. - NameTablePtr name_table = down_cast(font->table(Tag::name)); - UChar* name = name_table->name(PlatformId::kWindows, + NameTablePtr name_table = down_cast(font->GetTable(Tag::name)); + UChar* name = name_table->Name(PlatformId::kWindows, WindowsEncodingId::kUnicodeUCS2, WindowsLanguageId::kEnglish_UnitedStates, NameId::kFontFamilyName); EXPECT_EQ(u_strcmp(name, original_name), 0); - delete name; - delete original_name; + delete[] name; + delete[] original_name; return true; } -bool testRemoveOneName() { - FontFactoryPtr factory = FontFactory::getInstance(); +bool TestRemoveOneName() { + FontFactoryPtr factory = FontFactory::GetInstance(); FontBuilderArray font_builder_array; - loadTestFile(factory, &font_builder_array); + LoadTestFile(factory, &font_builder_array); FontBuilderPtr font_builder = font_builder_array[0]; NameTableBuilderPtr name_builder = down_cast( - font_builder->getTableBuilder(Tag::name)); + font_builder->GetTableBuilder(Tag::name)); - EXPECT_TRUE(name_builder->has(PlatformId::kWindows, + EXPECT_TRUE(name_builder->Has(PlatformId::kWindows, WindowsEncodingId::kUnicodeUCS2, WindowsLanguageId::kEnglish_UnitedStates, NameId::kFontFamilyName)); - EXPECT_TRUE(name_builder->remove(PlatformId::kWindows, + EXPECT_TRUE(name_builder->Remove(PlatformId::kWindows, WindowsEncodingId::kUnicodeUCS2, WindowsLanguageId::kEnglish_UnitedStates, NameId::kFontFamilyName)); // Build the font. - FontPtr font = font_builder->build(); + FontPtr font = font_builder->Build(); // Serialize and reload the serialized font. MemoryOutputStream os; - factory->serializeFont(font, &os); + factory->SerializeFont(font, &os); FontArray font_array; - ByteArrayPtr new_ba = new MemoryByteArray(os.get(), os.size()); - factory->loadFonts(new_ba, &font_array); + ByteArrayPtr new_ba = new MemoryByteArray(os.Get(), os.Size()); + factory->LoadFonts(new_ba, &font_array); FontPtr new_font = font_array[0]; // Check the font name. - NameTablePtr name_table = down_cast(font->table(Tag::name)); - UChar* name = name_table->name(PlatformId::kWindows, + NameTablePtr name_table = down_cast(font->GetTable(Tag::name)); + UChar* name = name_table->Name(PlatformId::kWindows, WindowsEncodingId::kUnicodeUCS2, WindowsLanguageId::kEnglish_UnitedStates, NameId::kFontFamilyName); @@ -179,14 +179,14 @@ bool testRemoveOneName() { // Note: Function is not implemented but the test case is built. Uncomment // when NameTable::clear() is implemented. /* -bool testClearAllNamesAndSetOne() { - FontFactoryPtr factory = FontFactory::getInstance(); +bool TestClearAllNamesAndSetOne() { + FontFactoryPtr factory = FontFactory::GetInstance(); FontBuilderArray font_builder_array; - loadTestFile(factory, &font_builder_array); + LoadTestFile(factory, &font_builder_array); FontBuilderPtr font_builder = font_builder_array[0]; NameTableBuilderPtr name_builder = down_cast( - font_builder->getTableBuilder(Tag::name)); + font_builder->GetTableBuilder(Tag::name)); EXPECT_GT(name_builder->builderCount(), 0); name_builder->clear(); @@ -194,32 +194,34 @@ bool testClearAllNamesAndSetOne() { // Change the font name. NameEntryBuilderPtr neb = - name_builder->nameBuilder(PlatformId::kWindows, + name_builder->NameBuilder(PlatformId::kWindows, WindowsEncodingId::kUnicodeUCS2, WindowsLanguageId::kEnglish_UnitedStates, NameId::kFontFamilyName); U_STRING_DECL(new_name, "Fred", 4); - neb->setName(new_name); + neb->SetName(new_name); // Build the font. - FontPtr font = font_builder->build(); + FontPtr font = font_builder->Build(); // Serialize and reload the serialized font. MemoryOutputStream os; - factory->serializeFont(font, &os); + factory->SerializeFont(font, &os); FontArray font_array; - ByteArrayPtr new_ba = new MemoryByteArray(os.get(), os.size()); - factory->loadFonts(new_ba, &font_array); + ByteArrayPtr new_ba = new MemoryByteArray(os.Get(), os.Size()); + factory->LoadFonts(new_ba, &font_array); FontPtr new_font = font_array[0]; // Check the font name. NameTablePtr name_table = down_cast(font->table(Tag::name)); - UChar* name = name_table->name(PlatformId::kWindows, + UChar* name = name_table->Name(PlatformId::kWindows, WindowsEncodingId::kUnicodeUCS2, WindowsLanguageId::kEnglish_UnitedStates, NameId::kFontFamilyName); - EXPECT_EQ(name_table->nameCount(), 1); + EXPECT_EQ(name_table->NameCount(), 1); EXPECT_EQ(u_strcmp(name, new_name), 0); + + delete[] name; return true; } */ diff --git a/test/name_editing_test.h b/test/name_editing_test.h index b5edf0f..dff38d8 100644 --- a/test/name_editing_test.h +++ b/test/name_editing_test.h @@ -19,12 +19,12 @@ namespace sfntly { -bool testChangeOneName(); -bool testModifyNameTableAndRevert(); -bool testRemoveOneName(); +bool TestChangeOneName(); +bool TestModifyNameTableAndRevert(); +bool TestRemoveOneName(); // Note: Function is not implemented but the test case is built. Uncomment // when NameTable::clear() is implemented. -// bool testClearAllNamesAndSetOne(); +// bool TestClearAllNamesAndSetOne(); } // namespace sfntly diff --git a/test/open_type_data_test.cc b/test/open_type_data_test.cc index ef1d390..da07e69 100644 --- a/test/open_type_data_test.cc +++ b/test/open_type_data_test.cc @@ -24,7 +24,7 @@ namespace sfntly { const byte_t TEST_OTF_DATA[] = {0xff, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01}; -bool testOTFRead() { +bool TestOTFRead() { ByteVector bytes; for (size_t i = 0; i < sizeof(TEST_OTF_DATA) / sizeof(byte_t); ++i) { bytes.push_back(TEST_OTF_DATA[i]); @@ -32,18 +32,18 @@ bool testOTFRead() { ByteArrayPtr array = new MemoryByteArray(&(bytes[0]), bytes.size()); ReadableFontDataPtr data = new ReadableFontData(array); - EXPECT_EQ(-1, data->readByte(0)); - EXPECT_EQ(0xff, data->readUByte(0)); - EXPECT_EQ(0x01, data->readByte(1)); - EXPECT_EQ(65281, data->readUShort(0)); - EXPECT_EQ(-255, data->readShort(0)); - EXPECT_EQ(16711937, data->readUInt24(0)); - EXPECT_EQ(4278255873LL, data->readULong(0)); - EXPECT_EQ(-16711423, data->readLong(0)); + EXPECT_EQ(-1, data->ReadByte(0)); + EXPECT_EQ(0xff, data->ReadUByte(0)); + EXPECT_EQ(0x01, data->ReadByte(1)); + EXPECT_EQ(65281, data->ReadUShort(0)); + EXPECT_EQ(-255, data->ReadShort(0)); + EXPECT_EQ(16711937, data->ReadUInt24(0)); + EXPECT_EQ(4278255873LL, data->ReadULong(0)); + EXPECT_EQ(-16711423, data->ReadLong(0)); return true; } -bool testOTFCopy() { +bool TestOTFCopy() { ByteVector source_bytes(1024); for (size_t i = 0; i < source_bytes.size(); ++i) { source_bytes[i] = (byte_t)(i & 0xff); @@ -56,7 +56,7 @@ bool testOTFCopy() { new MemoryByteArray(&(destination_bytes[0]), 1024); WritableFontDataPtr destination = new WritableFontData(destination_array); - int32_t length = source->copyTo(destination); + int32_t length = source->CopyTo(destination); EXPECT_EQ(1024, length); EXPECT_TRUE(std::equal(source_bytes.begin(), source_bytes.end(), destination_bytes.begin())); diff --git a/test/open_type_data_test.h b/test/open_type_data_test.h index 99bd422..30d8a54 100644 --- a/test/open_type_data_test.h +++ b/test/open_type_data_test.h @@ -19,8 +19,8 @@ namespace sfntly { -bool testOTFRead(); -bool testOTFCopy(); +bool TestOTFRead(); +bool TestOTFCopy(); } // namespace sfntly diff --git a/test/otf_basic_editing_test.cc b/test/otf_basic_editing_test.cc index 6c8bde9..e9f4bcd 100644 --- a/test/otf_basic_editing_test.cc +++ b/test/otf_basic_editing_test.cc @@ -29,39 +29,39 @@ namespace sfntly { -bool testOTFBasicEditing() { - FontFactoryPtr factory = FontFactory::getInstance(); +bool TestOTFBasicEditing() { + FontFactoryPtr factory = FontFactory::GetInstance(); FontBuilderArray font_builder_array; - builderForFontFile(SAMPLE_TTF_FILE, factory, &font_builder_array); + BuilderForFontFile(SAMPLE_TTF_FILE, factory, &font_builder_array); FontBuilderPtr font_builder = font_builder_array[0]; // ensure the builder is not bogus EXPECT_TRUE(font_builder != NULL); - TableBuilderMap* builder_map = font_builder->tableBuilders(); + TableBuilderMap* builder_map = font_builder->table_builders(); EXPECT_TRUE(builder_map != NULL); for (TableBuilderMap::iterator i = builder_map->begin(), e = builder_map->end(); i != e; ++i) { EXPECT_TRUE(i->second != NULL); if (i->second == NULL) { char tag[5] = {0}; - int32_t value = toBE32(i->first); + int32_t value = ToBE32(i->first); memcpy(tag, &value, 4); fprintf(stderr, "tag %s does not have valid builder\n", tag); } } IntegerSet builder_tags; - font_builder->tableBuilderTags(&builder_tags); + font_builder->TableBuilderTags(&builder_tags); FontHeaderTableBuilderPtr header_builder = down_cast( - font_builder->getTableBuilder(Tag::head)); - int64_t mod_date = header_builder->modified(); - header_builder->setModified(mod_date + 1); + font_builder->GetTableBuilder(Tag::head)); + int64_t mod_date = header_builder->Modified(); + header_builder->SetModified(mod_date + 1); FontPtr font; - font.attach(font_builder->build()); + font.Attach(font_builder->Build()); // ensure every table had a builder - TableMap* table_map = font->tables(); + TableMap* table_map = font->Tables(); for (TableMap::iterator i = table_map->begin(), e = table_map->end(); i != e; ++i) { TablePtr table = (*i).second; @@ -71,9 +71,9 @@ bool testOTFBasicEditing() { } EXPECT_TRUE(builder_tags.empty()); - FontHeaderTablePtr header = down_cast( - font->table(Tag::head)); - int64_t after_mod_date = header->modified(); + FontHeaderTablePtr header = + down_cast(font->GetTable(Tag::head)); + int64_t after_mod_date = header->Modified(); EXPECT_EQ(mod_date + 1, after_mod_date); return true; } diff --git a/test/otf_basic_editing_test.h b/test/otf_basic_editing_test.h index b3abfad..483ed90 100644 --- a/test/otf_basic_editing_test.h +++ b/test/otf_basic_editing_test.h @@ -19,7 +19,7 @@ namespace sfntly { -bool testOTFBasicEditing(); +bool TestOTFBasicEditing(); } // namespace sfntly diff --git a/test/smart_pointer_test.cc b/test/smart_pointer_test.cc index a35e289..7eac019 100644 --- a/test/smart_pointer_test.cc +++ b/test/smart_pointer_test.cc @@ -28,7 +28,7 @@ public: // put in something to make sure it's not empty int foo() { return foo_; } }; -bool testSmartPointer() { +bool TestSmartPointer() { // scope out allocation { Ptr p1; @@ -55,7 +55,7 @@ bool testSmartPointer() { EXPECT_EQ(size_t(2), p3->ref_count_); EXPECT_EQ(size_t(2), RefCounted::object_counter_); - p3.release(); + p3.Release(); EXPECT_EQ(size_t(1), p1->ref_count_); EXPECT_EQ(NULL, p3.p_); EXPECT_EQ(size_t(2), RefCounted::object_counter_); diff --git a/test/smart_pointer_test.h b/test/smart_pointer_test.h index ebc0a1f..b57f614 100644 --- a/test/smart_pointer_test.h +++ b/test/smart_pointer_test.h @@ -17,6 +17,6 @@ #ifndef TYPOGRAPHY_FONT_SFNTLY_SRC_TEST_SMART_POINTER_TEST_H_ #define TYPOGRAPHY_FONT_SFNTLY_SRC_TEST_SMART_POINTER_TEST_H_ -bool testSmartPointer(); +bool TestSmartPointer(); #endif // TYPOGRAPHY_FONT_SFNTLY_SRC_TEST_SMART_POINTER_TEST_H_ diff --git a/test/test_font_utils.cc b/test/test_font_utils.cc index 830f96e..2c7e1fe 100644 --- a/test/test_font_utils.cc +++ b/test/test_font_utils.cc @@ -23,32 +23,32 @@ namespace sfntly { -void builderForFontFile(const char* font_path, FontFactory* factory, +void BuilderForFontFile(const char* font_path, FontFactory* factory, FontBuilderArray* builders) { assert(factory); FileInputStream is; - is.open(font_path); - factory->loadFontsForBuilding(&is, builders); + is.Open(font_path); + factory->LoadFontsForBuilding(&is, builders); EXPECT_GT(builders->size(), static_cast(0)); } -void serializeFont(const char* font_path, FontFactory* factory, Font* font) { +void SerializeFont(const char* font_path, FontFactory* factory, Font* font) { assert(font_path); assert(factory); assert(font); MemoryOutputStream output_stream; - factory->serializeFont(font, &output_stream); - serializeToFile(&output_stream, font_path); + factory->SerializeFont(font, &output_stream); + SerializeToFile(&output_stream, font_path); } -void loadFont(const char* font_path, FontFactory* factory, FontArray* fonts) { +void LoadFont(const char* font_path, FontFactory* factory, FontArray* fonts) { FileInputStream is; - is.open(font_path); - factory->loadFonts(&is, fonts); - is.close(); + is.Open(font_path); + factory->LoadFonts(&is, fonts); + is.Close(); } -void loadFile(const char* input_file_path, ByteVector* input_buffer) { +void LoadFile(const char* input_file_path, ByteVector* input_buffer) { assert(input_file_path); assert(input_buffer); @@ -68,7 +68,7 @@ void loadFile(const char* input_file_path, ByteVector* input_buffer) { fclose(input_file); } -void serializeToFile(MemoryOutputStream* output_stream, const char* file_path) { +void SerializeToFile(MemoryOutputStream* output_stream, const char* file_path) { assert(file_path); assert(output_stream); @@ -79,12 +79,12 @@ void serializeToFile(MemoryOutputStream* output_stream, const char* file_path) { output_file = fopen(file_path, "wb"); #endif EXPECT_NE(output_file, reinterpret_cast(NULL)); - fwrite(output_stream->get(), 1, output_stream->size(), output_file); + fwrite(output_stream->Get(), 1, output_stream->Size(), output_file); fflush(output_file); fclose(output_file); } -void hexDump(const unsigned char* byte_data, size_t length) { +void HexDump(const unsigned char* byte_data, size_t length) { if (byte_data == NULL || length == 0) { fprintf(stderr, "\n"); return; diff --git a/test/test_font_utils.h b/test/test_font_utils.h index b0c5696..6c70edc 100644 --- a/test/test_font_utils.h +++ b/test/test_font_utils.h @@ -23,15 +23,15 @@ namespace sfntly { -void builderForFontFile(const char* font_path, FontFactory* factory, +void BuilderForFontFile(const char* font_path, FontFactory* factory, FontBuilderArray* builders); -void serializeFont(const char* font_path, FontFactory* factory, Font* font); -void loadFont(const char* font_path, FontFactory* factory, FontArray* fonts); +void SerializeFont(const char* font_path, FontFactory* factory, Font* font); +void LoadFont(const char* font_path, FontFactory* factory, FontArray* fonts); -void loadFile(const char* input_file_path, ByteVector* input_buffer); -void serializeToFile(MemoryOutputStream* output_stream, const char* file_path); +void LoadFile(const char* input_file_path, ByteVector* input_buffer); +void SerializeToFile(MemoryOutputStream* output_stream, const char* file_path); -void hexDump(const unsigned char* byte_data, size_t length); +void HexDump(const unsigned char* byte_data, size_t length); } // namespace sfntly diff --git a/test/test_utils.cc b/test/test_utils.cc index 4b4644e..4751b92 100644 --- a/test/test_utils.cc +++ b/test/test_utils.cc @@ -30,15 +30,15 @@ namespace sfntly { TestUtils::TestUtils() {} // static -// OutputStream createOutputStream(const char *file_path) { +// OutputStream CreateOutputStream(const char *file_path) { // } // static -// void TestUtils::createNewFile(const char* file_path) { +// void TestUtils::CreateNewFile(const char* file_path) { // } // static -int32_t TestUtils::encodeOneChar(UConverter* encoder, int16_t uchar) { +int32_t TestUtils::EncodeOneChar(UConverter* encoder, int16_t uchar) { char* target = new char[ucnv_getMaxCharSize(encoder) * 2]; char* target_end; UChar* source = new UChar[2]; @@ -69,7 +69,7 @@ int32_t TestUtils::encodeOneChar(UConverter* encoder, int16_t uchar) { } // static -UConverter* TestUtils::getEncoder(const char* charset_name) { +UConverter* TestUtils::GetEncoder(const char* charset_name) { if (charset_name == NULL || strcmp(charset_name, "") == 0) return NULL; UErrorCode status = U_ZERO_ERROR; @@ -81,7 +81,7 @@ UConverter* TestUtils::getEncoder(const char* charset_name) { // Get a file's extension // static -const char* TestUtils::extension(const char* file_path) { +const char* TestUtils::Extension(const char* file_path) { if (!file_path) return NULL; return strrchr(file_path, EXTENSION_SEPARATOR); diff --git a/test/test_utils.h b/test/test_utils.h index 6aa4d99..4d692e1 100644 --- a/test/test_utils.h +++ b/test/test_utils.h @@ -40,8 +40,10 @@ class TestUtils { // @param length the length of the byte arrays to compare // @return true if the array segments are equal; false otherwise // TODO(dfilimon): implement - static bool equals(ByteArray* b1, int32_t offset1, - ByteArray* b2, int32_t offset2); + static bool Equals(ByteArray* b1, + int32_t offset1, + ByteArray* b2, + int32_t offset2); // @param offset1 offset to start comparing the first ByteArray from // @param ba1 the first ByteArray @@ -50,8 +52,11 @@ class TestUtils { // @param length the number of bytes to compare // @return true if all bytes in the ranges given are equal; false otherwise // TODO(dfilimon): implement - static bool equals(ByteArray* b1, int32_t offset1, - ByteArray* b2, int32_t offset2, int32_t length); + static bool Equals(ByteArray* b1, + int32_t offset1, + ByteArray* b2, + int32_t offset2, + int32_t length); // TODO(dfilimon): implement FileOutputStream in port/file_output_stream.* // static OutputStream createOutputStream(const char* file_path); @@ -62,13 +67,13 @@ class TestUtils { // Creates a new file including deleting an already existing file with the // same path and name and creating any needed directories. // TODO(dfilimon): implement - static void createNewFile(const char* file_path); + static void CreateNewFile(const char* file_path); // Converts an integer into a 4 character string using the ASCII encoding. // @param i the value to convert // @return the String based on the number // TODO(dfilimon): implement - static void dumpLongAsString(int32_t i, std::string* result); + static void DumpLongAsString(int32_t i, std::string* result); // Calculate an OpenType checksum from the array. // @param b the array to calculate checksum on @@ -76,20 +81,20 @@ class TestUtils { // @param length the number of bytes to check; must be a multiple of 4 // @return checksum // TODO(dfilimon): implement - static int64_t checkSum(ByteArray* b, int32_t offset, int32_t length); + static int64_t CheckSum(ByteArray* b, int32_t offset, int32_t length); // Encode a single character in UTF-16. // We only support the BMP for now // @param encoder the encoder to use for the encoding // @param uchar the Unicode character to encode // @return the encoded character - static int32_t encodeOneChar(UConverter* encoder, int16_t uchar); + static int32_t EncodeOneChar(UConverter* encoder, int16_t uchar); // Get an encoder for the charset name. // If the name is null or the empty string then just return null. // @param charsetName the charset to get an encoder for // @return an encoder or null if no encoder available for charset name - static UConverter* getEncoder(const char* charsetName); + static UConverter* GetEncoder(const char* charsetName); private: static const char EXTENSION_SEPARATOR = '.'; @@ -99,7 +104,7 @@ class TestUtils { // @param file the whose name to process // @return string containing the extension or an empty string if // there is no extension - static const char* extension(const char* file_path); + static const char* Extension(const char* file_path); }; } #endif // TYPOGRAPHY_FONT_SFNTLY_SRC_TEST_TEST_UTILS_H_ diff --git a/test/test_utils_test.cc b/test/test_utils_test.cc index 12c5512..41ba905 100644 --- a/test/test_utils_test.cc +++ b/test/test_utils_test.cc @@ -27,8 +27,8 @@ namespace sfntly { // Check if proper encoding is being performed // Conversion is done from UTF16 to UTF8, SJIS -bool testEncoding() { - UConverter* conv = TestUtils::getEncoder("utf8"); +bool TestEncoding() { + UConverter* conv = TestUtils::GetEncoder("utf8"); EXPECT_TRUE(conv != NULL); // Ūnĭcōde̽ UChar from[8] = {0x016A, 0x006E, 0x012D, 0x0063, 0x014D, 0x0064, 0x0065, @@ -37,7 +37,7 @@ bool testEncoding() { 0x65, 0xcc, 0xbd}; int32_t i, j = 0; for (i = 0; i < 7; ++i) { - int32_t encoded = TestUtils::encodeOneChar(conv, (int16_t)from[i]); + int32_t encoded = TestUtils::EncodeOneChar(conv, (int16_t)from[i]); for (; encoded; encoded <<= 8) { byte_t b = (encoded & 0xff000000) >> 24; if (!b) @@ -54,22 +54,22 @@ bool testEncoding() { } // Check if the proper extension is obtained -bool testExtension() { +bool TestExtension() { // usual file name const char *result; - result = TestUtils::extension("../data/ext/arial.ttf"); + result = TestUtils::Extension("../data/ext/tuffy.ttf"); EXPECT_EQ(strcmp(result, ".ttf"), 0); // more than one 'extension' - result = TestUtils::extension("arial.ttf.fake"); + result = TestUtils::Extension("tuffy.ttf.fake"); EXPECT_EQ(strcmp(result, ".fake"), 0); // no extension - result = TestUtils::extension("arial"); + result = TestUtils::Extension("tuffy"); EXPECT_STREQ(result, NULL); // bogus extension - result = TestUtils::extension("arial."); + result = TestUtils::Extension("tuffy."); EXPECT_EQ(strcmp(result, "."), 0); return true; diff --git a/test/test_utils_test.h b/test/test_utils_test.h index 1b4649e..c830ed1 100644 --- a/test/test_utils_test.h +++ b/test/test_utils_test.h @@ -21,9 +21,9 @@ namespace sfntly { -bool testEncoding(); -bool testExtension(); -bool testReadFile(); +bool TestEncoding(); +bool TestExtension(); +bool TestReadFile(); } // namespace sfntly -- cgit v1.2.3 From bd74f6c542ef6b6d279edf08d6d7e5952bc4980e Mon Sep 17 00:00:00 2001 From: "arthurhsu@google.com" Date: Mon, 1 Aug 2011 20:50:21 +0000 Subject: Fix possible NULL pointer dereferencing. git-svn-id: http://sfntly.googlecode.com/svn/trunk/cpp/src@32 672e30a5-4c29-85ac-ac6d-611c735e0a51 --- sfntly/font.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sfntly/font.cc b/sfntly/font.cc index fefa17e..86030a8 100644 --- a/sfntly/font.cc +++ b/sfntly/font.cc @@ -371,7 +371,7 @@ void Font::Builder::BuildTablesFromBuilders(TableBuilderMap* builder_map, builder_end = builder_map->end(); builder != builder_end; ++builder) { TablePtr table; - if (builder->second->ReadyToBuild()) { + if (builder->second && builder->second->ReadyToBuild()) { #if !defined (SFNTLY_NO_EXCEPTION) try { #endif -- cgit v1.2.3 From 335643ef4bbe8029047fec80feaa5912a05b84f0 Mon Sep 17 00:00:00 2001 From: "arthurhsu@google.com" Date: Mon, 1 Aug 2011 23:35:27 +0000 Subject: Original change by dfilimon Redo since the readability CL invalidated it. Fix bad usage of STL map that created NULL pointers in table builder map. git-svn-id: http://sfntly.googlecode.com/svn/trunk/cpp/src@33 672e30a5-4c29-85ac-ac6d-611c735e0a51 --- sfntly/font.cc | 55 ++++++++++++++++++++++++++++++++++++++++++++----------- 1 file changed, 44 insertions(+), 11 deletions(-) diff --git a/sfntly/font.cc b/sfntly/font.cc index 86030a8..814e2ee 100644 --- a/sfntly/font.cc +++ b/sfntly/font.cc @@ -398,18 +398,51 @@ void Font::Builder::BuildTablesFromBuilders(TableBuilderMap* builder_map, } } +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) { - FontHeaderTableBuilderPtr header_table_builder = - down_cast((*builder_map)[Tag::head].p_); - HorizontalHeaderTableBuilderPtr horizontal_header_builder = - down_cast((*builder_map)[Tag::hhea].p_); - MaximumProfileTableBuilderPtr max_profile_builder = - down_cast((*builder_map)[Tag::maxp].p_); - LocaTableBuilderPtr loca_table_builder = - down_cast((*builder_map)[Tag::loca].p_); - HorizontalMetricsTableBuilderPtr horizontal_metrics_builder = - down_cast( - (*builder_map)[Tag::hmtx].p_); + 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); + } // set the inter table data required to build certain tables if (horizontal_metrics_builder != NULL) { -- cgit v1.2.3 From 7b78f49e6ea3a141a398dd56c99069ca8404ca47 Mon Sep 17 00:00:00 2001 From: "dfilimon@google.com" Date: Mon, 1 Aug 2011 23:44:12 +0000 Subject: Fixes memory leak in font_factory. git-svn-id: http://sfntly.googlecode.com/svn/trunk/cpp/src@34 672e30a5-4c29-85ac-ac6d-611c735e0a51 --- sfntly/font_factory.cc | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/sfntly/font_factory.cc b/sfntly/font_factory.cc index d5b2397..859ca4e 100644 --- a/sfntly/font_factory.cc +++ b/sfntly/font_factory.cc @@ -47,7 +47,8 @@ void FontFactory::LoadFonts(InputStream* is, FontArray* output) { LoadCollection(pbis, output); return; } - FontPtr font = LoadSingleOTF(pbis); + FontPtr font; + font.attach(loadSingleOTF(pbis)); if (font) { output->push_back(font); } -- cgit v1.2.3 From 943fc3bbbc953ac73890e8e7783a87acb397b227 Mon Sep 17 00:00:00 2001 From: "dfilimon@google.com" Date: Mon, 1 Aug 2011 23:53:39 +0000 Subject: Fixed fix. Didn't have SVN repo updated before committing. git-svn-id: http://sfntly.googlecode.com/svn/trunk/cpp/src@35 672e30a5-4c29-85ac-ac6d-611c735e0a51 --- sfntly/font_factory.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sfntly/font_factory.cc b/sfntly/font_factory.cc index 859ca4e..a306bcd 100644 --- a/sfntly/font_factory.cc +++ b/sfntly/font_factory.cc @@ -48,7 +48,7 @@ void FontFactory::LoadFonts(InputStream* is, FontArray* output) { return; } FontPtr font; - font.attach(loadSingleOTF(pbis)); + font.Attach(LoadSingleOTF(pbis)); if (font) { output->push_back(font); } -- cgit v1.2.3 From b4655d76bd3b64a2ce0624c371772e58241bcbbf Mon Sep 17 00:00:00 2001 From: "arthurhsu@google.com" Date: Tue, 2 Aug 2011 20:50:44 +0000 Subject: Fix loca bug caused by typo. git-svn-id: http://sfntly.googlecode.com/svn/trunk/cpp/src@36 672e30a5-4c29-85ac-ac6d-611c735e0a51 --- sfntly/loca_table.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sfntly/loca_table.cc b/sfntly/loca_table.cc index e82f709..1869e15 100644 --- a/sfntly/loca_table.cc +++ b/sfntly/loca_table.cc @@ -62,7 +62,7 @@ int32_t LocaTable::Loca(int32_t index) { #endif } if (version_ == IndexToLocFormat::kShortOffset) { - return 2 * data_->ReadShort(index * DataSize::kUSHORT); + return 2 * data_->ReadUShort(index * DataSize::kUSHORT); } return data_->ReadULongAsInt(index * DataSize::kULONG); } -- cgit v1.2.3 From f8dcae69a9ab5b147c115b1ab04132c876c2f35c Mon Sep 17 00:00:00 2001 From: "dfilimon@google.com" Date: Fri, 5 Aug 2011 21:36:29 +0000 Subject: Added LoadFontUsingByteArray to TestFontUtils. git-svn-id: http://sfntly.googlecode.com/svn/trunk/cpp/src@37 672e30a5-4c29-85ac-ac6d-611c735e0a51 --- test/test_font_utils.cc | 14 ++++++++++++++ test/test_font_utils.h | 3 +++ 2 files changed, 17 insertions(+) diff --git a/test/test_font_utils.cc b/test/test_font_utils.cc index 2c7e1fe..99b65fe 100644 --- a/test/test_font_utils.cc +++ b/test/test_font_utils.cc @@ -18,6 +18,7 @@ #include "gtest/gtest.h" #include "sfntly/data/memory_byte_array.h" +#include "sfntly/data/growable_memory_byte_array.h" #include "sfntly/port/file_input_stream.h" #include "test/test_font_utils.h" @@ -48,6 +49,19 @@ void LoadFont(const char* font_path, FontFactory* factory, FontArray* fonts) { is.Close(); } +void LoadFontUsingByteArray(const char* font_path, + bool fingerprint, + FontArray* fonts) { + ByteArrayPtr b = new GrowableMemoryByteArray; + ByteVector bv; + LoadFile(font_path, &bv); + b->Put(0, &bv); + FontFactoryPtr factory; + factory.Attach(FontFactory::GetInstance()); + factory->FingerprintFont(fingerprint); + factory->LoadFonts(b, fonts); +} + void LoadFile(const char* input_file_path, ByteVector* input_buffer) { assert(input_file_path); assert(input_buffer); diff --git a/test/test_font_utils.h b/test/test_font_utils.h index 6c70edc..21296f1 100644 --- a/test/test_font_utils.h +++ b/test/test_font_utils.h @@ -27,6 +27,9 @@ void BuilderForFontFile(const char* font_path, FontFactory* factory, FontBuilderArray* builders); void SerializeFont(const char* font_path, FontFactory* factory, Font* font); void LoadFont(const char* font_path, FontFactory* factory, FontArray* fonts); +void LoadFontUsingByteArray(const char* font_path, + bool fingerprint, + FontArray* fonts); void LoadFile(const char* input_file_path, ByteVector* input_buffer); void SerializeToFile(MemoryOutputStream* output_stream, const char* file_path); -- cgit v1.2.3 From 8427926b2267e501fa38649cffeb9d62a550af56 Mon Sep 17 00:00:00 2001 From: "dfilimon@google.com" Date: Fri, 5 Aug 2011 21:46:13 +0000 Subject: Small style fix. git-svn-id: http://sfntly.googlecode.com/svn/trunk/cpp/src@38 672e30a5-4c29-85ac-ac6d-611c735e0a51 --- sfntly/font_data_table.h | 3 ++- sfntly/table.cc | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/sfntly/font_data_table.h b/sfntly/font_data_table.h index 9b3b467..207d492 100644 --- a/sfntly/font_data_table.h +++ b/sfntly/font_data_table.h @@ -48,7 +48,7 @@ class FontDataTable : virtual public RefCount { CALLER_ATTACH WritableFontData* InternalNewData(int32_t size); bool data_changed() { return data_changed_; } - bool modelChanged() { return model_changed_; } + bool model_changed() { return model_changed_; } bool set_model_changed() { return set_model_changed(true); } bool set_model_changed(bool changed) { bool old = model_changed_; @@ -110,6 +110,7 @@ class FontDataTable : virtual public RefCount { ReadableFontDataPtr data_; }; typedef Ptr FontDataTablePtr; +typedef Ptr FontDataTableBuilderPtr; } // namespace sfntly diff --git a/sfntly/table.cc b/sfntly/table.cc index a11177e..fc09d10 100644 --- a/sfntly/table.cc +++ b/sfntly/table.cc @@ -100,7 +100,7 @@ Table::Builder::~Builder() { } void Table::Builder::NotifyPostTableBuild(FontDataTable* table) { - if (modelChanged() || data_changed()) { + if (model_changed() || data_changed()) { Table* derived_table = down_cast(table); header_ = new Header(header()->tag(), derived_table->ReadFontData()->Length()); -- cgit v1.2.3 From 2b411c787a15a455c83abb03f2d458830f8b02de Mon Sep 17 00:00:00 2001 From: "dfilimon@google.com" Date: Fri, 5 Aug 2011 21:51:33 +0000 Subject: Added generate_name from tag. Useful for debugging and used in future tests. git-svn-id: http://sfntly.googlecode.com/svn/trunk/cpp/src@39 672e30a5-4c29-85ac-ac6d-611c735e0a51 --- sfntly/tag.h | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/sfntly/tag.h b/sfntly/tag.h index 9e73007..791d4ab 100644 --- a/sfntly/tag.h +++ b/sfntly/tag.h @@ -82,6 +82,7 @@ struct Tag { static const int32_t bloc; }; +// Create integer tag value for human readable tag name. inline int32_t GenerateTag(char a, char b, char c, char d) { return (((int32_t)(a) << 24) | ((int32_t)(b) << 16) | @@ -89,6 +90,18 @@ inline int32_t GenerateTag(char a, char b, char c, char d) { (int32_t)(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] = (tag & 0xff000000) >> 24; + name[1] = (tag & 0x00ff0000) >> 16; + name[2] = (tag & 0x0000ff00) >> 8; + name[3] = (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[]; -- cgit v1.2.3 From 6a22b959c06e66a039c630e6ac514234114b46cb Mon Sep 17 00:00:00 2001 From: "arthurhsu@google.com" Date: Mon, 8 Aug 2011 18:37:09 +0000 Subject: Reorg test structure, fix memory leaks. git-svn-id: http://sfntly.googlecode.com/svn/trunk/cpp/src@40 672e30a5-4c29-85ac-ac6d-611c735e0a51 --- sfntly/name_table.cc | 3 +- test/byte_array_test.cc | 14 +++++-- test/byte_array_test.h | 27 ------------ test/endian_test.cc | 5 ++- test/endian_test.h | 26 ------------ test/file_io_test.cc | 6 +++ test/file_io_test.h | 28 ------------- test/font_data_test.cc | 14 +++++-- test/font_data_test.h | 25 ----------- test/font_parsing_test.cc | 31 ++++++++++---- test/font_parsing_test.h | 28 ------------- test/main.cc | 94 ------------------------------------------ test/name_editing_test.cc | 35 +++++++++++----- test/name_editing_test.h | 31 -------------- test/open_type_data_test.cc | 6 ++- test/open_type_data_test.h | 27 ------------ test/otf_basic_editing_test.cc | 8 +++- test/otf_basic_editing_test.h | 26 ------------ test/smart_pointer_test.cc | 5 ++- test/smart_pointer_test.h | 22 ---------- test/test_utils_test.cc | 8 +++- test/test_utils_test.h | 30 -------------- 22 files changed, 102 insertions(+), 397 deletions(-) delete mode 100644 test/byte_array_test.h delete mode 100644 test/endian_test.h delete mode 100644 test/file_io_test.h delete mode 100644 test/font_data_test.h delete mode 100644 test/font_parsing_test.h delete mode 100644 test/main.cc delete mode 100644 test/name_editing_test.h delete mode 100644 test/open_type_data_test.h delete mode 100644 test/otf_basic_editing_test.h delete mode 100644 test/smart_pointer_test.h delete mode 100644 test/test_utils_test.h diff --git a/sfntly/name_table.cc b/sfntly/name_table.cc index 19c299c..c1d3c59 100644 --- a/sfntly/name_table.cc +++ b/sfntly/name_table.cc @@ -421,7 +421,8 @@ void NameTable::Builder::Initialize(ReadableFontData* data) { NameTablePtr table = new NameTable(header(), data); NameEntryIterator name_iter(table, NULL); while (name_iter.HasNext()) { - NameEntryPtr name_entry = name_iter.Next(); + 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(); diff --git a/test/byte_array_test.cc b/test/byte_array_test.cc index 89478f4..74b5290 100644 --- a/test/byte_array_test.cc +++ b/test/byte_array_test.cc @@ -19,7 +19,6 @@ #include "gtest/gtest.h" #include "sfntly/data/memory_byte_array.h" #include "sfntly/data/growable_memory_byte_array.h" -#include "test/byte_array_test.h" namespace sfntly { namespace byte_array_test { @@ -112,27 +111,36 @@ bool ByteArrayTester(ByteArray* ba) { } // namespace byte_array_test bool TestMemoryByteArray() { + fprintf(stderr, "fixed mem: size "); for (size_t i = 0; i < sizeof(byte_array_test::BYTE_ARRAY_SIZES) / sizeof(int32_t); ++i) { int32_t size = byte_array_test::BYTE_ARRAY_SIZES[i]; - fprintf(stderr, "fixed mem: iteration %ld, size %d\n", i, size); + fprintf(stderr, "%d ", size); ByteArrayPtr ba = new MemoryByteArray(size); byte_array_test::FillTestByteArray(ba, size); EXPECT_TRUE(byte_array_test::ByteArrayTester(ba)); } + fprintf(stderr, "\n"); return true; } bool TestGrowableMemoryByteArray() { + fprintf(stderr, "growable mem: size "); for (size_t i = 0; i < sizeof(byte_array_test::BYTE_ARRAY_SIZES) / sizeof(int32_t); ++i) { int32_t size = byte_array_test::BYTE_ARRAY_SIZES[i]; - fprintf(stderr, "growable mem: iteration %ld, size %d\n", i, size); + fprintf(stderr, "%d ", size); ByteArrayPtr ba = new GrowableMemoryByteArray(); byte_array_test::FillTestByteArray(ba, size); EXPECT_TRUE(byte_array_test::ByteArrayTester(ba)); } + fprintf(stderr, "\n"); return true; } } // namespace sfntly + +TEST(ByteArray, All) { + ASSERT_TRUE(sfntly::TestMemoryByteArray()); + ASSERT_TRUE(sfntly::TestGrowableMemoryByteArray()); +} diff --git a/test/byte_array_test.h b/test/byte_array_test.h deleted file mode 100644 index 88e8ce8..0000000 --- a/test/byte_array_test.h +++ /dev/null @@ -1,27 +0,0 @@ -/* - * 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_TEST_BYTE_ARRAY_TEST_H_ -#define TYPOGRAPHY_FONT_SFNTLY_SRC_TEST_BYTE_ARRAY_TEST_H_ - -namespace sfntly { - -bool TestMemoryByteArray(); -bool TestGrowableMemoryByteArray(); - -} // namespace sfntly - -#endif // TYPOGRAPHY_FONT_SFNTLY_SRC_TEST_BYTE_ARRAY_TEST_H_ diff --git a/test/endian_test.cc b/test/endian_test.cc index 50beeeb..0d9da09 100644 --- a/test/endian_test.cc +++ b/test/endian_test.cc @@ -21,7 +21,6 @@ #include "sfntly/math/fixed1616.h" #include "sfntly/port/memory_output_stream.h" #include "sfntly/data/font_output_stream.h" -#include "test/endian_test.h" namespace sfntly { @@ -72,3 +71,7 @@ bool TestEndian() { } } // namespace sfntly + +TEST(Endian, All) { + ASSERT_TRUE(sfntly::TestEndian()); +} diff --git a/test/endian_test.h b/test/endian_test.h deleted file mode 100644 index 8fc36ff..0000000 --- a/test/endian_test.h +++ /dev/null @@ -1,26 +0,0 @@ -/* - * 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_TEST_ENDIAN_TEST_H_ -#define TYPOGRAPHY_FONT_SFNTLY_SRC_TEST_ENDIAN_TEST_H_ - -namespace sfntly { - -bool TestEndian(); - -} // namespace sfntly - -#endif // TYPOGRAPHY_FONT_SFNTLY_SRC_TEST_ENDIAN_TEST_H_ diff --git a/test/file_io_test.cc b/test/file_io_test.cc index 6c48a27..e6801d5 100644 --- a/test/file_io_test.cc +++ b/test/file_io_test.cc @@ -152,3 +152,9 @@ bool TestFontInputStreamTableLoading() { } } // namespace sfntly + +TEST(FileIO, All) { + ASSERT_TRUE(sfntly::TestFileInputStream()); + ASSERT_TRUE(sfntly::TestFontInputStreamBasic()); + ASSERT_TRUE(sfntly::TestFontInputStreamTableLoading()); +} diff --git a/test/file_io_test.h b/test/file_io_test.h deleted file mode 100644 index 9ff1972..0000000 --- a/test/file_io_test.h +++ /dev/null @@ -1,28 +0,0 @@ -/* - * 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_TEST_FILE_IO_TEST_H_ -#define TYPOGRAPHY_FONT_SFNTLY_SRC_TEST_FILE_IO_TEST_H_ - -namespace sfntly { - -bool TestFileInputStream(); -bool TestFontInputStreamBasic(); -bool TestFontInputStreamTableLoading(); - -} // namespace sfntly - -#endif // TYPOGRAPHY_FONT_SFNTLY_SRC_TEST_FILE_IO_TEST_H_ diff --git a/test/font_data_test.cc b/test/font_data_test.cc index 3686856..5a80fb3 100644 --- a/test/font_data_test.cc +++ b/test/font_data_test.cc @@ -21,7 +21,6 @@ #include "sfntly/port/type.h" #include "sfntly/data/writable_font_data.h" #include "sfntly/data/memory_byte_array.h" -#include "test/font_data_test.h" namespace sfntly { @@ -145,20 +144,23 @@ bool ReadComparison(int32_t offset, } void SlicingReadTest(ReadableFontData* rfd) { + fprintf(stderr, "read - trim = "); for (int32_t trim = 0; trim < (rfd->Length() / 2) + 1; trim += (rfd->Length() / 21) + 1) { - fprintf(stderr, "\tread - trim = %d\n", trim); + fprintf(stderr, "%d ", trim); int32_t length = rfd->Length() - 2 * trim; ReadableFontDataPtr slice; slice.Attach(down_cast(rfd->Slice(trim, length))); EXPECT_TRUE(ReadComparison(trim, length, rfd, slice)); } + fprintf(stderr, "\n"); } void SlicingWriteTest(ReadableFontData* rfd, WritableFontData* wfd) { + fprintf(stderr, "write - trim = "); for (int32_t trim = 0; trim < (rfd->Length() / 2) + 1; trim += (rfd->Length() / 21) + 1) { - fprintf(stderr, "\twrite - trim = %d\n", trim); + fprintf(stderr, "%d ", trim); int32_t length = rfd->Length() - 2 * trim; WritableFontDataPtr w_slice; ReadableFontDataPtr r_slice; @@ -187,6 +189,7 @@ void SlicingWriteTest(ReadableFontData* rfd, WritableFontData* wfd) { EXPECT_TRUE(ReadComparison(trim, length, rfd, w_slice)); } } + fprintf(stderr, "\n"); } bool TestReadableFontData() { @@ -215,3 +218,8 @@ bool TestWritableFontData() { } } // namespace sfntly + +TEST(FontData, All) { + ASSERT_TRUE(sfntly::TestReadableFontData()); + ASSERT_TRUE(sfntly::TestWritableFontData()); +} diff --git a/test/font_data_test.h b/test/font_data_test.h deleted file mode 100644 index bca1924..0000000 --- a/test/font_data_test.h +++ /dev/null @@ -1,25 +0,0 @@ -/* - * 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_TEST_FONT_DATA_TEST_H_ -#define TYPOGRAPHY_FONT_SFNTLY_SRC_TEST_FONT_DATA_TEST_H_ - -namespace sfntly { - bool TestReadableFontData(); - bool TestWritableFontData(); -} - -#endif // TYPOGRAPHY_FONT_SFNTLY_SRC_TEST_FONT_DATA_TEST_H_ diff --git a/test/font_parsing_test.cc b/test/font_parsing_test.cc index 71446ec..ee794d1 100644 --- a/test/font_parsing_test.cc +++ b/test/font_parsing_test.cc @@ -24,7 +24,6 @@ #include "sfntly/data/font_input_stream.h" #include "sfntly/data/memory_byte_array.h" #include "sfntly/port/file_input_stream.h" -#include "test/font_parsing_test.h" #include "test/test_data.h" #include "test/test_font_utils.h" @@ -36,7 +35,8 @@ bool TestFontParsing() { ByteArrayPtr ba = new MemoryByteArray(&(input_buffer[0]), input_buffer.size()); - FontFactoryPtr factory = FontFactory::GetInstance(); + FontFactoryPtr factory; + factory.Attach(FontFactory::GetInstance()); // File based FontBuilderArray font_builder_array; BuilderForFontFile(SAMPLE_TTF_FILE, factory, &font_builder_array); @@ -61,7 +61,8 @@ bool TestFontParsing() { EXPECT_EQ(gdef_header->checksum(), TTF_CHECKSUM[SAMPLE_TTF_GDEF]); EXPECT_TRUE(gdef_header->checksum_valid()); - WritableFontDataPtr wfd = gdef_builder->Data(); + WritableFontDataPtr wfd; + wfd.Attach(gdef_builder->Data()); ByteVector b; b.resize(TTF_LENGTH[SAMPLE_TTF_GDEF]); wfd->ReadBytes(0, &b, 0, TTF_LENGTH[SAMPLE_TTF_GDEF]); @@ -86,8 +87,10 @@ bool TestFontParsing() { font_builder->GetTableBuilder(TTF_KNOWN_TAGS[i]); TableBuilderPtr builder2 = font_builder2->GetTableBuilder(TTF_KNOWN_TAGS[i]); - WritableFontDataPtr wfd1 = builder1->Data(); - WritableFontDataPtr wfd2 = builder2->Data(); + WritableFontDataPtr wfd1; + wfd1.Attach(builder1->Data()); + WritableFontDataPtr wfd2; + wfd2.Attach(builder2->Data()); wfd1->ReadBytes(0, &b1, 0, TTF_LENGTH[i]); wfd2->ReadBytes(0, &b2, 0, TTF_LENGTH[i]); EXPECT_EQ(memcmp(&(b1[0]), &(b2[0]), TTF_LENGTH[i]), 0); @@ -97,11 +100,13 @@ bool TestFontParsing() { } bool TestTTFReadWrite() { - FontFactoryPtr factory = FontFactory::GetInstance(); + FontFactoryPtr factory; + factory.Attach(FontFactory::GetInstance()); FontBuilderArray font_builder_array; BuilderForFontFile(SAMPLE_TTF_FILE, factory, &font_builder_array); FontBuilderPtr font_builder = font_builder_array[0]; - FontPtr font = font_builder->Build(); + FontPtr font; + font.Attach(font_builder->Build()); MemoryOutputStream output_stream; factory->SerializeFont(font, &output_stream); EXPECT_GE(output_stream.Size(), SAMPLE_TTF_SIZE); @@ -113,13 +118,15 @@ bool TestTTFMemoryBasedReadWrite() { ByteVector input_buffer; LoadFile(SAMPLE_TTF_FILE, &input_buffer); - FontFactoryPtr factory = FontFactory::GetInstance(); + FontFactoryPtr factory; + factory.Attach(FontFactory::GetInstance()); FontBuilderArray font_builder_array; ByteArrayPtr ba = new MemoryByteArray(&(input_buffer[0]), input_buffer.size()); factory->LoadFontsForBuilding(ba, &font_builder_array); FontBuilderPtr font_builder = font_builder_array[0]; - FontPtr font = font_builder->Build(); + FontPtr font; + font.Attach(font_builder->Build()); MemoryOutputStream output_stream; factory->SerializeFont(font, &output_stream); EXPECT_GE(output_stream.Size(), input_buffer.size()); @@ -128,3 +135,9 @@ bool TestTTFMemoryBasedReadWrite() { } } // namespace sfntly + +TEST(FontParsing, All) { + ASSERT_TRUE(sfntly::TestFontParsing()); + ASSERT_TRUE(sfntly::TestTTFReadWrite()); + ASSERT_TRUE(sfntly::TestTTFMemoryBasedReadWrite()); +} diff --git a/test/font_parsing_test.h b/test/font_parsing_test.h deleted file mode 100644 index 7b69a27..0000000 --- a/test/font_parsing_test.h +++ /dev/null @@ -1,28 +0,0 @@ -/* - * 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_TEST_FONT_PARSING_TEST_H_ -#define TYPOGRAPHY_FONT_SFNTLY_SRC_TEST_FONT_PARSING_TEST_H_ - -namespace sfntly { - -bool TestFontParsing(); -bool TestTTFReadWrite(); -bool TestTTFMemoryBasedReadWrite(); - -} // namespace sfntly - -#endif // TYPOGRAPHY_FONT_SFNTLY_SRC_TEST_FONT_PARSING_TEST_H_ diff --git a/test/main.cc b/test/main.cc deleted file mode 100644 index 2c77eda..0000000 --- a/test/main.cc +++ /dev/null @@ -1,94 +0,0 @@ -/* - * 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. - */ - -// TODO(arthurhsu): wrap individul tests in ASSERTs so that they fail early - -#include - -#include "gtest/gtest.h" -#include "test/smart_pointer_test.h" -#include "test/endian_test.h" -#include "test/byte_array_test.h" -#include "test/file_io_test.h" -#include "test/font_data_test.h" -#include "test/font_parsing_test.h" -#include "test/open_type_data_test.h" -#include "test/otf_basic_editing_test.h" -#include "test/name_editing_test.h" -#include "test/test_utils_test.h" - -#define RUN_LENGTHY_TESTS - -namespace sfntly { - -TEST(SmartPointer, All) { - EXPECT_TRUE(TestSmartPointer()); -} - -TEST(Endian, All) { - EXPECT_TRUE(sfntly::TestEndian()); -} - -#if defined RUN_LENGTHY_TESTS -TEST(ByteArray, All) { - EXPECT_TRUE(sfntly::TestMemoryByteArray()); - EXPECT_TRUE(sfntly::TestGrowableMemoryByteArray()); -} -#endif - -#if defined RUN_LENGTHY_TESTS -TEST(FontData, All) { - EXPECT_TRUE(sfntly::TestReadableFontData()); - EXPECT_TRUE(sfntly::TestWritableFontData()); -} -#endif - -TEST(FileIO, All) { - EXPECT_TRUE(sfntly::TestFileInputStream()); - EXPECT_TRUE(sfntly::TestFontInputStreamBasic()); - EXPECT_TRUE(sfntly::TestFontInputStreamTableLoading()); -} - -TEST(OpenTypeData, All) { - EXPECT_TRUE(sfntly::TestOTFRead()); - EXPECT_TRUE(sfntly::TestOTFCopy()); -} - -TEST(FontParsing, All) { - EXPECT_TRUE(sfntly::TestFontParsing()); - EXPECT_TRUE(sfntly::TestTTFReadWrite()); - EXPECT_TRUE(sfntly::TestTTFMemoryBasedReadWrite()); -} - -TEST(OTFBasicEditing, All) { - EXPECT_TRUE(sfntly::TestOTFBasicEditing()); -} - -TEST(NameEditing, All) { - EXPECT_TRUE(sfntly::TestChangeOneName()); - EXPECT_TRUE(sfntly::TestModifyNameTableAndRevert()); - EXPECT_TRUE(sfntly::TestRemoveOneName()); -} - -TEST(TestUtils, Extension) { - EXPECT_TRUE(sfntly::TestExtension()); -} - -TEST(TestUtils, Encoding) { - EXPECT_TRUE(sfntly::TestEncoding()); -} - -} // namespace sfntly diff --git a/test/name_editing_test.cc b/test/name_editing_test.cc index 6822bf0..90076cf 100644 --- a/test/name_editing_test.cc +++ b/test/name_editing_test.cc @@ -29,26 +29,27 @@ #include "sfntly/port/memory_output_stream.h" #include "test/test_data.h" #include "test/test_font_utils.h" -#include "test/name_editing_test.h" namespace sfntly { static ByteVector input_buffer; -static ByteArrayPtr ba; void LoadTestFile(FontFactory* factory, FontBuilderArray* font_builders) { assert(factory); assert(font_builders); - if (ba == NULL) { + if (input_buffer.empty()) { LoadFile(SAMPLE_TTF_FILE, &input_buffer); - ba = new MemoryByteArray(&(input_buffer[0]), input_buffer.size()); } + ByteArrayPtr ba = + new MemoryByteArray(&(input_buffer[0]), input_buffer.size()); + factory->LoadFontsForBuilding(ba, font_builders); } bool TestChangeOneName() { - FontFactoryPtr factory = FontFactory::GetInstance(); + FontFactoryPtr factory; + factory.Attach(FontFactory::GetInstance()); FontBuilderArray font_builder_array; LoadTestFile(factory, &font_builder_array); FontBuilderPtr font_builder = font_builder_array[0]; @@ -66,7 +67,8 @@ bool TestChangeOneName() { neb->SetName(new_name); // Build the font. - FontPtr font = font_builder->Build(); + FontPtr font; + font.Attach(font_builder->Build()); // Serialize and reload the serialized font. MemoryOutputStream os; @@ -89,7 +91,8 @@ bool TestChangeOneName() { } bool TestModifyNameTableAndRevert() { - FontFactoryPtr factory = FontFactory::GetInstance(); + FontFactoryPtr factory; + factory.Attach(FontFactory::GetInstance()); FontBuilderArray font_builder_array; LoadTestFile(factory, &font_builder_array); FontBuilderPtr font_builder = font_builder_array[0]; @@ -112,7 +115,8 @@ bool TestModifyNameTableAndRevert() { name_builder->RevertNames(); // Build the font. - FontPtr font = font_builder->Build(); + FontPtr font; + font.Attach(font_builder->Build()); // Serialize and reload the serialized font. MemoryOutputStream os; @@ -137,7 +141,8 @@ bool TestModifyNameTableAndRevert() { } bool TestRemoveOneName() { - FontFactoryPtr factory = FontFactory::GetInstance(); + FontFactoryPtr factory; + factory.Attach(FontFactory::GetInstance()); FontBuilderArray font_builder_array; LoadTestFile(factory, &font_builder_array); FontBuilderPtr font_builder = font_builder_array[0]; @@ -155,7 +160,8 @@ bool TestRemoveOneName() { NameId::kFontFamilyName)); // Build the font. - FontPtr font = font_builder->Build(); + FontPtr font; + font.Attach(font_builder->Build()); // Serialize and reload the serialized font. MemoryOutputStream os; @@ -180,7 +186,8 @@ bool TestRemoveOneName() { // when NameTable::clear() is implemented. /* bool TestClearAllNamesAndSetOne() { - FontFactoryPtr factory = FontFactory::GetInstance(); + FontFactoryPtr factory; + factory.Attach(FontFactory::GetInstance()); FontBuilderArray font_builder_array; LoadTestFile(factory, &font_builder_array); FontBuilderPtr font_builder = font_builder_array[0]; @@ -227,3 +234,9 @@ bool TestClearAllNamesAndSetOne() { */ } // namespace sfntly + +TEST(NameEditing, All) { + EXPECT_TRUE(sfntly::TestChangeOneName()); + EXPECT_TRUE(sfntly::TestModifyNameTableAndRevert()); + EXPECT_TRUE(sfntly::TestRemoveOneName()); +} diff --git a/test/name_editing_test.h b/test/name_editing_test.h deleted file mode 100644 index dff38d8..0000000 --- a/test/name_editing_test.h +++ /dev/null @@ -1,31 +0,0 @@ -/* - * 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_TEST_NAME_EDITING_TEST_H_ -#define TYPOGRAPHY_FONT_SFNTLY_SRC_TEST_NAME_EDITING_TEST_H_ - -namespace sfntly { - -bool TestChangeOneName(); -bool TestModifyNameTableAndRevert(); -bool TestRemoveOneName(); -// Note: Function is not implemented but the test case is built. Uncomment -// when NameTable::clear() is implemented. -// bool TestClearAllNamesAndSetOne(); - -} // namespace sfntly - -#endif // TYPOGRAPHY_FONT_SFNTLY_SRC_TEST_NAME_EDITING_TEST_H_ diff --git a/test/open_type_data_test.cc b/test/open_type_data_test.cc index da07e69..0917aab 100644 --- a/test/open_type_data_test.cc +++ b/test/open_type_data_test.cc @@ -17,7 +17,6 @@ #include "gtest/gtest.h" #include "sfntly/data/writable_font_data.h" #include "sfntly/data/memory_byte_array.h" -#include "test/open_type_data_test.h" namespace sfntly { @@ -64,3 +63,8 @@ bool TestOTFCopy() { } } // namespace sfntly + +TEST(OpenTypeData, All) { + ASSERT_TRUE(sfntly::TestOTFRead()); + ASSERT_TRUE(sfntly::TestOTFCopy()); +} diff --git a/test/open_type_data_test.h b/test/open_type_data_test.h deleted file mode 100644 index 30d8a54..0000000 --- a/test/open_type_data_test.h +++ /dev/null @@ -1,27 +0,0 @@ -/* - * 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_TEST_OPEN_TYPE_DATA_TEST_H_ -#define TYPOGRAPHY_FONT_SFNTLY_SRC_TEST_OPEN_TYPE_DATA_TEST_H_ - -namespace sfntly { - -bool TestOTFRead(); -bool TestOTFCopy(); - -} // namespace sfntly - -#endif // TYPOGRAPHY_FONT_SFNTLY_SRC_TEST_OPEN_TYPE_DATA_TEST_H_ diff --git a/test/otf_basic_editing_test.cc b/test/otf_basic_editing_test.cc index e9f4bcd..0489c50 100644 --- a/test/otf_basic_editing_test.cc +++ b/test/otf_basic_editing_test.cc @@ -23,14 +23,14 @@ #include "sfntly/port/endian.h" #include "sfntly/port/file_input_stream.h" #include "sfntly/port/memory_output_stream.h" -#include "test/otf_basic_editing_test.h" #include "test/test_data.h" #include "test/test_font_utils.h" namespace sfntly { bool TestOTFBasicEditing() { - FontFactoryPtr factory = FontFactory::GetInstance(); + FontFactoryPtr factory; + factory.Attach(FontFactory::GetInstance()); FontBuilderArray font_builder_array; BuilderForFontFile(SAMPLE_TTF_FILE, factory, &font_builder_array); FontBuilderPtr font_builder = font_builder_array[0]; @@ -79,3 +79,7 @@ bool TestOTFBasicEditing() { } } // namespace sfntly + +TEST(OTFBasicEditing, All) { + ASSERT_TRUE(sfntly::TestOTFBasicEditing()); +} diff --git a/test/otf_basic_editing_test.h b/test/otf_basic_editing_test.h deleted file mode 100644 index 483ed90..0000000 --- a/test/otf_basic_editing_test.h +++ /dev/null @@ -1,26 +0,0 @@ -/* - * 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_TEST_OTF_BASIC_EDITING_TEST_H_ -#define TYPOGRAPHY_FONT_SFNTLY_SRC_TEST_OTF_BASIC_EDITING_TEST_H_ - -namespace sfntly { - -bool TestOTFBasicEditing(); - -} // namespace sfntly - -#endif // TYPOGRAPHY_FONT_SFNTLY_SRC_TEST_OTF_BASIC_EDITING_TEST_H_ diff --git a/test/smart_pointer_test.cc b/test/smart_pointer_test.cc index 7eac019..9e81baa 100644 --- a/test/smart_pointer_test.cc +++ b/test/smart_pointer_test.cc @@ -17,7 +17,6 @@ #include "gtest/gtest.h" #define ENABLE_OBJECT_COUNTER #include "sfntly/port/refcount.h" -#include "test/smart_pointer_test.h" using sfntly::RefCounted; using sfntly::Ptr; @@ -74,3 +73,7 @@ bool TestSmartPointer() { EXPECT_EQ(size_t(0), RefCounted::object_counter_); return true; } + +TEST(SmartPointer, All) { + ASSERT_TRUE(TestSmartPointer()); +} diff --git a/test/smart_pointer_test.h b/test/smart_pointer_test.h deleted file mode 100644 index b57f614..0000000 --- a/test/smart_pointer_test.h +++ /dev/null @@ -1,22 +0,0 @@ -/* - * 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_TEST_SMART_POINTER_TEST_H_ -#define TYPOGRAPHY_FONT_SFNTLY_SRC_TEST_SMART_POINTER_TEST_H_ - -bool TestSmartPointer(); - -#endif // TYPOGRAPHY_FONT_SFNTLY_SRC_TEST_SMART_POINTER_TEST_H_ diff --git a/test/test_utils_test.cc b/test/test_utils_test.cc index 41ba905..9afc03c 100644 --- a/test/test_utils_test.cc +++ b/test/test_utils_test.cc @@ -14,7 +14,8 @@ * limitations under the License. */ -#include "test/test_utils_test.h" +// Must include at the first line to avoid ICU / stdint conflict. +#include "sfntly/port/type.h" #include #include @@ -76,3 +77,8 @@ bool TestExtension() { } } // namespace sfntly + +TEST(TestUtils, All) { + ASSERT_TRUE(sfntly::TestExtension()); + ASSERT_TRUE(sfntly::TestEncoding()); +} diff --git a/test/test_utils_test.h b/test/test_utils_test.h deleted file mode 100644 index c830ed1..0000000 --- a/test/test_utils_test.h +++ /dev/null @@ -1,30 +0,0 @@ -/* - * 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_TEST_TEST_UTILS_TEST_H_ -#define TYPOGRAPHY_FONT_SFNTLY_SRC_TEST_TEST_UTILS_TEST_H_ - -#include "sfntly/port/type.h" - -namespace sfntly { - -bool TestEncoding(); -bool TestExtension(); -bool TestReadFile(); - -} // namespace sfntly - -#endif // TYPOGRAPHY_FONT_SFNTLY_SRC_TEST_TEST_UTILS_TEST_H_ -- cgit v1.2.3 From 3da8d09b9fe5128f3897f98a35f9d6c7de64835d Mon Sep 17 00:00:00 2001 From: "arthurhsu@google.com" Date: Tue, 9 Aug 2011 00:18:33 +0000 Subject: Fix VC compilation warnings. git-svn-id: http://sfntly.googlecode.com/svn/trunk/cpp/src@41 672e30a5-4c29-85ac-ac6d-611c735e0a51 --- sfntly/tag.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/sfntly/tag.h b/sfntly/tag.h index 791d4ab..d802351 100644 --- a/sfntly/tag.h +++ b/sfntly/tag.h @@ -94,10 +94,10 @@ inline int32_t GenerateTag(char a, char b, char c, char d) { // The Caller must delete[] the returned value. inline char* TagToString(int32_t tag) { char *name = new char[5]; - name[0] = (tag & 0xff000000) >> 24; - name[1] = (tag & 0x00ff0000) >> 16; - name[2] = (tag & 0x0000ff00) >> 8; - name[3] = (tag & 0x000000ff); + name[0] = (char)((tag & 0xff000000) >> 24); + name[1] = (char)((tag & 0x00ff0000) >> 16); + name[2] = (char)((tag & 0x0000ff00) >> 8); + name[3] = (char)(tag & 0x000000ff); name[4] = 0; return name; } -- cgit v1.2.3 From db6755301647bc1ad0616d7e370138bc822b4b06 Mon Sep 17 00:00:00 2001 From: "arthurhsu@google.com" Date: Tue, 9 Aug 2011 20:55:55 +0000 Subject: Add checksum test for generic table builder (validating the checksum algorithm). git-svn-id: http://sfntly.googlecode.com/svn/trunk/cpp/src@42 672e30a5-4c29-85ac-ac6d-611c735e0a51 --- test/otf_basic_editing_test.cc | 4 ++++ test/test_data.cc | 1 + test/test_data.h | 1 + 3 files changed, 6 insertions(+) diff --git a/test/otf_basic_editing_test.cc b/test/otf_basic_editing_test.cc index 0489c50..1db2d1e 100644 --- a/test/otf_basic_editing_test.cc +++ b/test/otf_basic_editing_test.cc @@ -75,6 +75,10 @@ bool TestOTFBasicEditing() { down_cast(font->GetTable(Tag::head)); int64_t after_mod_date = header->Modified(); EXPECT_EQ(mod_date + 1, after_mod_date); + + // Checksum correctness of builder. + TablePtr post = font->GetTable(Tag::post); + EXPECT_EQ(post->CalculatedChecksum(), TTF_CHECKSUM[SAMPLE_TTF_POST]); return true; } diff --git a/test/test_data.cc b/test/test_data.cc index b81f8d9..1746121 100644 --- a/test/test_data.cc +++ b/test/test_data.cc @@ -32,6 +32,7 @@ const size_t SAMPLE_TTF_TABLES = 16; const size_t SAMPLE_TTF_KNOWN_TAGS = 15; const size_t SAMPLE_TTF_GDEF = 0; const size_t SAMPLE_TTF_HEAD = 8; +const size_t SAMPLE_TTF_POST = 14; const int32_t TTF_KNOWN_TAGS[] = { Tag::GDEF, Tag::GPOS, Tag::GSUB, Tag::OS_2, Tag::cmap, Tag::cvt, diff --git a/test/test_data.h b/test/test_data.h index a505dca..b6aa4ea 100644 --- a/test/test_data.h +++ b/test/test_data.h @@ -29,6 +29,7 @@ extern const size_t SAMPLE_TTF_TABLES; extern const size_t SAMPLE_TTF_KNOWN_TAGS; extern const size_t SAMPLE_TTF_GDEF; extern const size_t SAMPLE_TTF_HEAD; +extern const size_t SAMPLE_TTF_POST; extern const int32_t TTF_KNOWN_TAGS[]; extern const int64_t TTF_CHECKSUM[]; -- cgit v1.2.3 From 3daf7a5c855b0640e2dd3904abe378e76a43829d Mon Sep 17 00:00:00 2001 From: "arthurhsu@google.com" Date: Wed, 10 Aug 2011 20:06:32 +0000 Subject: Fortify font build against error cases. git-svn-id: http://sfntly.googlecode.com/svn/trunk/cpp/src@43 672e30a5-4c29-85ac-ac6d-611c735e0a51 --- sfntly/font.cc | 1 + sfntly/font_data_table.cc | 5 +++++ 2 files changed, 6 insertions(+) diff --git a/sfntly/font.cc b/sfntly/font.cc index 814e2ee..32ecca7 100644 --- a/sfntly/font.cc +++ b/sfntly/font.cc @@ -387,6 +387,7 @@ void Font::Builder::BuildTablesFromBuilders(TableBuilderMap* builder_map, } if (table == NULL) { #if defined (SFNTLY_NO_EXCEPTION) + table_map->clear(); return; #else std::string builder_string = "Unable to build table - "; diff --git a/sfntly/font_data_table.cc b/sfntly/font_data_table.cc index 1f9d1cc..e6d0984 100644 --- a/sfntly/font_data_table.cc +++ b/sfntly/font_data_table.cc @@ -89,6 +89,11 @@ CALLER_ATTACH FontDataTable* FontDataTable::Builder::Build() { SubSerialize(new_data); data = new_data; } + + if (data == NULL) { + return NULL; // Do not build table with NULL data. + } + FontDataTablePtr table = SubBuildTable(data); NotifyPostTableBuild(table); return table; -- cgit v1.2.3 From deec0e7851d8f029cf3718bcb61633e8a262c275 Mon Sep 17 00:00:00 2001 From: "arthurhsu@google.com" Date: Thu, 11 Aug 2011 01:59:20 +0000 Subject: Port serialization test. git-svn-id: http://sfntly.googlecode.com/svn/trunk/cpp/src@44 672e30a5-4c29-85ac-ac6d-611c735e0a51 --- test/serialization_test.cc | 82 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 82 insertions(+) create mode 100755 test/serialization_test.cc diff --git a/test/serialization_test.cc b/test/serialization_test.cc new file mode 100755 index 0000000..0923659 --- /dev/null +++ b/test/serialization_test.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 "gtest/gtest.h" +#include "sfntly/font.h" +#include "sfntly/font_factory.h" +#include "sfntly/data/memory_byte_array.h" +#include "test/test_data.h" +#include "test/test_font_utils.h" + +namespace sfntly { + +bool TestSerialization() { + FontFactoryPtr factory1, factory2, factory3; + factory1.Attach(FontFactory::GetInstance()); + FontArray font_array; + LoadFont(SAMPLE_TTF_FILE, factory1, &font_array); + FontPtr original = font_array[0]; + + factory2.Attach(FontFactory::GetInstance()); + FontBuilderArray font_builder_array; + BuilderForFontFile(SAMPLE_TTF_FILE, factory2, &font_builder_array); + FontBuilderPtr font_builder = font_builder_array[0]; + + FontPtr intermediate; + intermediate.Attach(font_builder->Build()); + MemoryOutputStream os; + factory2->SerializeFont(intermediate, &os); + + factory3.Attach(FontFactory::GetInstance()); + FontArray new_font_array; + ByteArrayPtr ba = new MemoryByteArray(os.Get(), os.Size()); + factory3->LoadFonts(ba, &new_font_array); + FontPtr serialized = new_font_array[0]; + + // Check number of tables + EXPECT_EQ(original->num_tables(), serialized->num_tables()); + + // Check if same set of tables + TableMap* original_tables = original->Tables(); + TableMap* serialized_tables = serialized->Tables(); + EXPECT_EQ(original_tables->size(), serialized_tables->size()); + TableMap::iterator not_found = serialized_tables->end(); + for (TableMap::iterator b = original_tables->begin(), + e = original_tables->end(); b != e; ++b) { + EXPECT_TRUE((serialized_tables->find(b->first) != not_found)); + } + + // TODO(arthurhsu): check cmap equivalence + // Check checksum equivalence + for (size_t i = 0; i < SAMPLE_TTF_KNOWN_TAGS; ++i) { + TablePtr original_table = original->GetTable(TTF_KNOWN_TAGS[i]); + TablePtr serialized_table = serialized->GetTable(TTF_KNOWN_TAGS[i]); + EXPECT_EQ(original_table->CalculatedChecksum(), + serialized_table->CalculatedChecksum()); + EXPECT_EQ(((original_table->Length() + 3) & ~3), + ((serialized_table->Length() + 3) & ~3)); + } + + return true; +} + +} // namespace sfntly + +TEST(Serialization, All) { + ASSERT_TRUE(sfntly::TestSerialization()); +} -- cgit v1.2.3 From 33e4b13b001b82d8b26a2066ba77fe04bbd6f9a8 Mon Sep 17 00:00:00 2001 From: "dfilimon@google.com" Date: Fri, 12 Aug 2011 01:04:03 +0000 Subject: Added CreateWritableFontData factory methods to WritableFontData. git-svn-id: http://sfntly.googlecode.com/svn/trunk/cpp/src@46 672e30a5-4c29-85ac-ac6d-611c735e0a51 --- sfntly/data/writable_font_data.cc | 26 ++++++++++++++++++++++++++ sfntly/data/writable_font_data.h | 18 ++++++++++++++++++ 2 files changed, 44 insertions(+) diff --git a/sfntly/data/writable_font_data.cc b/sfntly/data/writable_font_data.cc index 586acc1..bf03516 100644 --- a/sfntly/data/writable_font_data.cc +++ b/sfntly/data/writable_font_data.cc @@ -16,6 +16,9 @@ #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) { @@ -23,6 +26,29 @@ 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(); +} + +// static +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; diff --git a/sfntly/data/writable_font_data.h b/sfntly/data/writable_font_data.h index 98c9204..ec74da7 100644 --- a/sfntly/data/writable_font_data.h +++ b/sfntly/data/writable_font_data.h @@ -26,6 +26,24 @@ class WritableFontData : public ReadableFontData { 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); + virtual int32_t WriteByte(int32_t index, byte_t b); virtual int32_t WriteBytes(int32_t offset, ByteVector* b, -- cgit v1.2.3 From f7c13bf6ff210e3c018971a6f219bb626ae00378 Mon Sep 17 00:00:00 2001 From: "arthurhsu@google.com" Date: Fri, 12 Aug 2011 01:04:16 +0000 Subject: More thorough unit tests. git-svn-id: http://sfntly.googlecode.com/svn/trunk/cpp/src@47 672e30a5-4c29-85ac-ac6d-611c735e0a51 --- sfntly/horizontal_metrics_table.cc | 7 + sfntly/horizontal_metrics_table.h | 1 + sfntly/name_table.cc | 2 +- sfntly/name_table.h | 4 +- sfntly/os2_table.cc | 2 +- sfntly/os2_table.h | 3 +- test/serialization_test.cc | 19 ++- test/serialization_test.h | 34 +++++ test/test_data.cc | 11 +- test/verify_glyf.cc | 59 +++++++++ test/verify_hhea.cc | 62 +++++++++ test/verify_hmtx.cc | 260 +++++++++++++++++++++++++++++++++++++ test/verify_loca.cc | 248 +++++++++++++++++++++++++++++++++++ test/verify_maxp.cc | 72 ++++++++++ test/verify_name.cc | 88 +++++++++++++ test/verify_os2.cc | 126 ++++++++++++++++++ 16 files changed, 986 insertions(+), 12 deletions(-) create mode 100644 test/serialization_test.h create mode 100644 test/verify_glyf.cc create mode 100644 test/verify_hhea.cc create mode 100644 test/verify_hmtx.cc create mode 100644 test/verify_loca.cc create mode 100644 test/verify_maxp.cc create mode 100644 test/verify_name.cc create mode 100644 test/verify_os2.cc diff --git a/sfntly/horizontal_metrics_table.cc b/sfntly/horizontal_metrics_table.cc index 921d8bc..026891d 100644 --- a/sfntly/horizontal_metrics_table.cc +++ b/sfntly/horizontal_metrics_table.cc @@ -77,6 +77,13 @@ int32_t HorizontalMetricsTable::AdvanceWidth(int32_t 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) : Table(header, data) { diff --git a/sfntly/horizontal_metrics_table.h b/sfntly/horizontal_metrics_table.h index aead6fa..55acce6 100644 --- a/sfntly/horizontal_metrics_table.h +++ b/sfntly/horizontal_metrics_table.h @@ -55,6 +55,7 @@ class HorizontalMetricsTable : public Table, 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 { diff --git a/sfntly/name_table.cc b/sfntly/name_table.cc index c1d3c59..d65f251 100644 --- a/sfntly/name_table.cc +++ b/sfntly/name_table.cc @@ -494,7 +494,7 @@ void NameTable::NameAsBytes(int32_t platform_id, } } -UChar* NameTable::Name(int index) { +UChar* NameTable::Name(int32_t index) { ByteVector b; NameAsBytes(index, &b); return ConvertFromNameBytes(&b, PlatformId(index), EncodingId(index)); diff --git a/sfntly/name_table.h b/sfntly/name_table.h index d0dd345..64353d6 100644 --- a/sfntly/name_table.h +++ b/sfntly/name_table.h @@ -454,7 +454,7 @@ class NameTable : public Table, public RefCounted { 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 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 @@ -649,7 +649,7 @@ class NameTable : public Table, public RefCounted { // 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(int index); + 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 diff --git a/sfntly/os2_table.cc b/sfntly/os2_table.cc index 6d6d338..5b6181d 100644 --- a/sfntly/os2_table.cc +++ b/sfntly/os2_table.cc @@ -208,7 +208,7 @@ int32_t OS2Table::STypoAscender() { return data_->ReadShort(Offset::kSTypoAscender); } -int32_t OS2Table::STypoDecender() { +int32_t OS2Table::STypoDescender() { return data_->ReadShort(Offset::kSTypoDescender); } diff --git a/sfntly/os2_table.h b/sfntly/os2_table.h index 058435a..dcad188 100644 --- a/sfntly/os2_table.h +++ b/sfntly/os2_table.h @@ -341,7 +341,7 @@ class OS2Table : public Table, public RefCounted { int32_t UsFirstCharIndex(); int32_t UsLastCharIndex(); int32_t STypoAscender(); - int32_t STypoDecender(); + int32_t STypoDescender(); int32_t STypoLineGap(); int32_t UsWinAscent(); int32_t UsWinDescent(); @@ -400,6 +400,7 @@ class OS2Table : public Table, public RefCounted { OS2Table(Header* header, ReadableFontData* data); }; +typedef Ptr OS2TablePtr; } // namespace sfntly diff --git a/test/serialization_test.cc b/test/serialization_test.cc index 0923659..507a98c 100755 --- a/test/serialization_test.cc +++ b/test/serialization_test.cc @@ -14,14 +14,13 @@ * limitations under the License. */ -#include - #include "gtest/gtest.h" #include "sfntly/font.h" #include "sfntly/font_factory.h" #include "sfntly/data/memory_byte_array.h" #include "test/test_data.h" #include "test/test_font_utils.h" +#include "test/serialization_test.h" namespace sfntly { @@ -70,6 +69,22 @@ bool TestSerialization() { serialized_table->CalculatedChecksum()); EXPECT_EQ(((original_table->Length() + 3) & ~3), ((serialized_table->Length() + 3) & ~3)); + + if (TTF_KNOWN_TAGS[i] == Tag::hhea) { + EXPECT_TRUE(VerifyHHEA(original_table, serialized_table)); + } else if (TTF_KNOWN_TAGS[i] == Tag::glyf) { + EXPECT_TRUE(VerifyGLYF(original_table, serialized_table)); + } else if (TTF_KNOWN_TAGS[i] == Tag::hmtx) { + EXPECT_TRUE(VerifyHMTX(original_table, serialized_table)); + } else if (TTF_KNOWN_TAGS[i] == Tag::loca) { + EXPECT_TRUE(VerifyLOCA(original_table, serialized_table)); + } else if (TTF_KNOWN_TAGS[i] == Tag::maxp) { + EXPECT_TRUE(VerifyMAXP(original_table, serialized_table)); + } else if (TTF_KNOWN_TAGS[i] == Tag::name) { + EXPECT_TRUE(VerifyNAME(original_table, serialized_table)); + } else if (TTF_KNOWN_TAGS[i] == Tag::OS_2) { + EXPECT_TRUE(VerifyOS_2(original_table, serialized_table)); + } } return true; diff --git a/test/serialization_test.h b/test/serialization_test.h new file mode 100644 index 0000000..0718f32 --- /dev/null +++ b/test/serialization_test.h @@ -0,0 +1,34 @@ +/* + * 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_TEST_SERIALIZATION_TEST_H_ +#define TYPOGRAPHY_FONT_SFNTLY_SRC_TEST_SERIALIZATION_TEST_H_ + +#include "sfntly/table.h" + +namespace sfntly { + +bool VerifyHHEA(Table* original, Table* target); +bool VerifyGLYF(Table* original, Table* target); +bool VerifyHMTX(Table* original, Table* target); +bool VerifyLOCA(Table* original, Table* target); +bool VerifyMAXP(Table* original, Table* target); +bool VerifyNAME(Table* original, Table* target); +bool VerifyOS_2(Table* original, Table* target); + +} // namespace sfntly + +#endif // TYPOGRAPHY_FONT_SFNTLY_SRC_TEST_SERIALIZATION_TEST_H_ diff --git a/test/test_data.cc b/test/test_data.cc index 1746121..e4cabbe 100644 --- a/test/test_data.cc +++ b/test/test_data.cc @@ -19,13 +19,14 @@ namespace sfntly { -#if defined WIN32 -const char* SAMPLE_TTF_FILE = "Tuffy.ttf"; -const char* SAMPLE_OTF_FILE = "Tuffy.otf"; -#else +// If the TTF file used in test changed, the verify*.cc in test need to be +// changed also. +// TODO(arthurhsu): Refactor this into a test class and have all const inside. +// This way we can test multiple fonts using same set of +// code. + const char* SAMPLE_TTF_FILE = "Tuffy.ttf"; const char* SAMPLE_OTF_FILE = "Tuffy.otf"; -#endif const size_t SAMPLE_TTF_SIZE = 18444; const size_t SAMPLE_TTF_TABLES = 16; diff --git a/test/verify_glyf.cc b/test/verify_glyf.cc new file mode 100644 index 0000000..f13f5ce --- /dev/null +++ b/test/verify_glyf.cc @@ -0,0 +1,59 @@ +/* + * 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 "gtest/gtest.h" +#include "sfntly/font.h" +#include "sfntly/glyph_table.h" +#include "test/serialization_test.h" + +namespace sfntly { + +// We spot check only glyph id 33. +const int32_t GLYPH33_OFFSET = 0xA70; +const int32_t GLYPH33_LENGTH = 40; +const int32_t GLYPH33_XMIN = 92; +const int32_t GLYPH33_YMIN = 20; +const int32_t GLYPH33_XMAX = 797; +const int32_t GLYPH33_YMAX = 1235; + +// TODO(arthurhsu): Tuffy does not have composite glyphs. Need better testing. +static bool VerifyGLYF(Table* table) { + GlyphTablePtr glyf_table = down_cast(table); + if (glyf_table == NULL) { + return false; + } + + GlyphPtr glyf; + glyf.Attach(glyf_table->GetGlyph(GLYPH33_OFFSET, GLYPH33_LENGTH)); + if (glyf == NULL) { + return false; + } + + EXPECT_EQ(glyf->XMin(), GLYPH33_XMIN); + EXPECT_EQ(glyf->YMin(), GLYPH33_YMIN); + EXPECT_EQ(glyf->XMax(), GLYPH33_XMAX); + EXPECT_EQ(glyf->YMax(), GLYPH33_YMAX); + + return true; +} + +bool VerifyGLYF(Table* original, Table* target) { + EXPECT_TRUE(VerifyGLYF(original)); + EXPECT_TRUE(VerifyGLYF(target)); + return true; +} + +} // namespace sfntly diff --git a/test/verify_hhea.cc b/test/verify_hhea.cc new file mode 100644 index 0000000..537b224 --- /dev/null +++ b/test/verify_hhea.cc @@ -0,0 +1,62 @@ +/* + * 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 "gtest/gtest.h" +#include "sfntly/font.h" +#include "sfntly/horizontal_header_table.h" +#include "test/serialization_test.h" + +namespace sfntly { + +const int32_t HHEA_ASCENDER = 1993; +const int32_t HHEA_DESCENDER = -449; +const int32_t HHEA_LINE_GAP = 93; +const int32_t HHEA_ADVANCE_WIDTH_MAX = 3969; +const int32_t HHEA_MIN_LSB = -119; +const int32_t HHEA_MIN_RSB = -32768; +const int32_t HHEA_X_MAX_EXTENT = 1565; +const int32_t HHEA_METRIC_DATA_FORMAT = 0; +const int32_t HHEA_NUM_METRICS = 197; + +static bool VerifyHHEA(Table* table) { + HorizontalHeaderTablePtr hhea = down_cast(table); + if (hhea == NULL) { + return false; + } + + EXPECT_EQ(hhea->Version(), SFNTVERSION_1); + EXPECT_EQ(hhea->Ascender(), HHEA_ASCENDER); + EXPECT_EQ(hhea->Descender(), HHEA_DESCENDER); + EXPECT_EQ(hhea->AdvanceWidthMax(), HHEA_ADVANCE_WIDTH_MAX); + EXPECT_EQ(hhea->MinLeftSideBearing(), HHEA_MIN_LSB); + EXPECT_EQ(hhea->MinRightSideBearing(), HHEA_MIN_RSB); + EXPECT_EQ(hhea->XMaxExtent(), HHEA_X_MAX_EXTENT); + // TODO(arthurhsu): CaretSlopeRise() not tested + // TODO(arthurhsu): CaretSlopeRun() not tested + // TODO(arthurhsu): CaretOffset() not tested + EXPECT_EQ(hhea->MetricDataFormat(), HHEA_METRIC_DATA_FORMAT); + EXPECT_EQ(hhea->NumberOfHMetrics(), HHEA_NUM_METRICS); + + return true; +} + +bool VerifyHHEA(Table* original, Table* target) { + EXPECT_TRUE(VerifyHHEA(original)); + EXPECT_TRUE(VerifyHHEA(target)); + return true; +} + +} // namespace sfntly diff --git a/test/verify_hmtx.cc b/test/verify_hmtx.cc new file mode 100644 index 0000000..000597a --- /dev/null +++ b/test/verify_hmtx.cc @@ -0,0 +1,260 @@ +/* + * 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 "gtest/gtest.h" +#include "sfntly/font.h" +#include "sfntly/horizontal_metrics_table.h" +#include "test/serialization_test.h" + +namespace sfntly { + +const int32_t HMTX_ENTRIES_COUNT = 197; +const int32_t HMTX_LSB_COUNT = 0; + +struct HmtxEntry { + int32_t advance_width_; + int32_t lsb_; + + HmtxEntry(int32_t advance_width, int32_t lsb) + : advance_width_(advance_width), lsb_(lsb) {} +}; + +const HmtxEntry HMTX_ENTRIES[] = { + HmtxEntry(32768, 0), // 0 + HmtxEntry(0, 0), // 1 + HmtxEntry(682, 0), // 2 + HmtxEntry(616, 0), // 3 + HmtxEntry(421, 103), // 4 + HmtxEntry(690, 129), // 5 + HmtxEntry(1589, 129), // 6 + HmtxEntry(1017, 25), // 7 + HmtxEntry(1402, 104), // 8 + HmtxEntry(1241, 100), // 9 + HmtxEntry(382, 129), // 10 + HmtxEntry(548, 41), // 11 + HmtxEntry(536, 90), // 12 + HmtxEntry(913, 33), // 13 + HmtxEntry(894, 78), // 14 + HmtxEntry(399, 103), // 15 + HmtxEntry(866, 109), // 16 + HmtxEntry(405, 103), // 17 + HmtxEntry(808, -23), // 18 + HmtxEntry(1136, 100), // 19 + HmtxEntry(1136, 424), // 20 + HmtxEntry(1136, 109), // 21 + HmtxEntry(1126, 113), // 22 + HmtxEntry(1136, 88), // 23 + HmtxEntry(1136, 135), // 24 + HmtxEntry(1136, 129), // 25 + HmtxEntry(1136, 111), // 26 + HmtxEntry(1136, 104), // 27 + HmtxEntry(1136, 143), // 28 + HmtxEntry(423, 113), // 29 + HmtxEntry(423, 113), // 30 + HmtxEntry(843, 84), // 31 + HmtxEntry(907, 66), // 32 + HmtxEntry(856, 92), // 33 + HmtxEntry(985, 57), // 34 + HmtxEntry(1624, 41), // 35 + HmtxEntry(1302, 72), // 36 + HmtxEntry(1179, 121), // 37 + HmtxEntry(1220, 100), // 38 + HmtxEntry(1220, 121), // 39 + HmtxEntry(1142, 121), // 40 + HmtxEntry(1146, 121), // 41 + HmtxEntry(1363, 100), // 42 + HmtxEntry(1198, 121), // 43 + HmtxEntry(444, 154), // 44 + HmtxEntry(1140, 113), // 45 + HmtxEntry(1239, 121), // 46 + HmtxEntry(1105, 121), // 47 + HmtxEntry(1562, 121), // 48 + HmtxEntry(1271, 121), // 49 + HmtxEntry(1333, 92), // 50 + HmtxEntry(1099, 121), // 51 + HmtxEntry(1370, 92), // 52 + HmtxEntry(1101, 121), // 53 + HmtxEntry(1079, 45), // 54 + HmtxEntry(1243, 88), // 55 + HmtxEntry(1265, 121), // 56 + HmtxEntry(1245, 80), // 57 + HmtxEntry(1576, 84), // 58 + HmtxEntry(1214, 74), // 59 + HmtxEntry(1179, 76), // 60 + HmtxEntry(1325, 100), // 61 + HmtxEntry(626, 131), // 62 + HmtxEntry(811, -29), // 63 + HmtxEntry(638, 129), // 64 + HmtxEntry(927, 133), // 65 + HmtxEntry(1241, 88), // 66 + HmtxEntry(516, 96), // 67 + HmtxEntry(993, 84), // 68 + HmtxEntry(1044, 129), // 69 + HmtxEntry(921, 76), // 70 + HmtxEntry(1044, 73), // 71 + HmtxEntry(1013, 98), // 72 + HmtxEntry(716, 125), // 73 + HmtxEntry(1021, 73), // 74 + HmtxEntry(1064, 129), // 75 + HmtxEntry(430, 131), // 76 + HmtxEntry(468, -119), // 77 + HmtxEntry(944, 129), // 78 + HmtxEntry(430, 150), // 79 + HmtxEntry(1533, 129), // 80 + HmtxEntry(1064, 129), // 81 + HmtxEntry(1054, 102), // 82 + HmtxEntry(1044, 129), // 83 + HmtxEntry(1048, 73), // 84 + HmtxEntry(686, 129), // 85 + HmtxEntry(921, 96), // 86 + HmtxEntry(696, 102), // 87 + HmtxEntry(1064, 120), // 88 + HmtxEntry(1024, 82), // 89 + HmtxEntry(1374, 68), // 90 + HmtxEntry(901, 53), // 91 + HmtxEntry(1064, 120), // 92 + HmtxEntry(962, 90), // 93 + HmtxEntry(747, 90), // 94 + HmtxEntry(368, 125), // 95 + HmtxEntry(747, 133), // 96 + HmtxEntry(735, 63), // 97 + HmtxEntry(309, 28), // 98 + HmtxEntry(808, 80), // 99 + HmtxEntry(1120, 84), // 100 + HmtxEntry(856, 63), // 101 + HmtxEntry(1110, 74), // 102 + HmtxEntry(305, 90), // 103 + HmtxEntry(686, 43), // 104 + HmtxEntry(794, 76), // 105 + HmtxEntry(942, 41), // 106 + HmtxEntry(872, 59), // 107 + HmtxEntry(1026, 154), // 108 + HmtxEntry(950, 109), // 109 + HmtxEntry(1189, 94), // 110 + HmtxEntry(706, 63), // 111 + HmtxEntry(598, 49), // 112 + HmtxEntry(983, 150), // 113 + HmtxEntry(550, 97), // 114 + HmtxEntry(1003, 154), // 115 + HmtxEntry(1150, 121), // 116 + HmtxEntry(438, 142), // 117 + HmtxEntry(473, 117), // 118 + HmtxEntry(933, 98), // 119 + HmtxEntry(954, 18), // 120 + HmtxEntry(1292, 82), // 121 + HmtxEntry(1292, 82), // 122 + HmtxEntry(1292, 82), // 123 + HmtxEntry(1292, 82), // 124 + HmtxEntry(1292, 82), // 125 + HmtxEntry(1292, 82), // 126 + HmtxEntry(1388, 83), // 127 + HmtxEntry(1220, 120), // 128 + HmtxEntry(1146, 131), // 129 + HmtxEntry(1146, 131), // 130 + HmtxEntry(1146, 131), // 131 + HmtxEntry(1146, 131), // 132 + HmtxEntry(440, -53), // 133 + HmtxEntry(440, 164), // 134 + HmtxEntry(440, -103), // 135 + HmtxEntry(440, -90), // 136 + HmtxEntry(3969, 144), // 137 + HmtxEntry(1292, 131), // 138 + HmtxEntry(1329, 102), // 139 + HmtxEntry(1329, 102), // 140 + HmtxEntry(1329, 102), // 141 + HmtxEntry(1329, 102), // 142 + HmtxEntry(1329, 102), // 143 + HmtxEntry(833, 108), // 144 + HmtxEntry(2416, 96), // 145 + HmtxEntry(1298, 131), // 146 + HmtxEntry(1298, 131), // 147 + HmtxEntry(1298, 131), // 148 + HmtxEntry(1298, 131), // 149 + HmtxEntry(1179, 86), // 150 + HmtxEntry(1329, 145), // 151 + HmtxEntry(1212, 92), // 152 + HmtxEntry(1036, 94), // 153 + HmtxEntry(1036, 94), // 154 + HmtxEntry(1036, 94), // 155 + HmtxEntry(1036, 94), // 156 + HmtxEntry(1036, 94), // 157 + HmtxEntry(1036, 94), // 158 + HmtxEntry(1486, 84), // 159 + HmtxEntry(1011, 86), // 160 + HmtxEntry(1046, 108), // 161 + HmtxEntry(1046, 108), // 162 + HmtxEntry(1046, 108), // 163 + HmtxEntry(1046, 108), // 164 + HmtxEntry(428, -75), // 165 + HmtxEntry(421, 150), // 166 + HmtxEntry(888, 115), // 167 + HmtxEntry(667, 8), // 168 + HmtxEntry(1030, 82), // 169 + HmtxEntry(1044, 139), // 170 + HmtxEntry(1060, 112), // 171 + HmtxEntry(1062, 112), // 172 + HmtxEntry(1062, 112), // 173 + HmtxEntry(1062, 112), // 174 + HmtxEntry(1060, 112), // 175 + HmtxEntry(911, 119), // 176 + HmtxEntry(1024, 86), // 177 + HmtxEntry(1032, 130), // 178 + HmtxEntry(1064, 130), // 179 + HmtxEntry(1064, 130), // 180 + HmtxEntry(1064, 130), // 181 + HmtxEntry(1064, 130), // 182 + HmtxEntry(1003, 129), // 183 + HmtxEntry(1064, 130), // 184 + HmtxEntry(1087, 170), // 185 + HmtxEntry(1001, 170), // 186 + HmtxEntry(1290, 150), // 187 + HmtxEntry(385, 83), // 188 + HmtxEntry(385, 95), // 189 + HmtxEntry(385, 99), // 190 + HmtxEntry(385, 106), // 191 + HmtxEntry(677, 81), // 192 + HmtxEntry(677, 97), // 193 + HmtxEntry(688, 113), // 194 + HmtxEntry(688, 91), // 195 + HmtxEntry(1089, 135), // 196 + + HmtxEntry(32768, 0) // 197: no such element, used to check the logic. +}; + +static bool VerifyHMTX(Table* table) { + HorizontalMetricsTablePtr hmtx = down_cast(table); + if (hmtx == NULL) { + return false; + } + + EXPECT_EQ(hmtx->NumberOfHMetrics(), HMTX_ENTRIES_COUNT); + EXPECT_EQ(hmtx->NumberOfLSBs(), HMTX_LSB_COUNT); + + for (int32_t i = 0; i < HMTX_ENTRIES_COUNT + 1; ++i) { + EXPECT_EQ(hmtx->AdvanceWidth(i), HMTX_ENTRIES[i].advance_width_); + EXPECT_EQ(hmtx->LeftSideBearing(i), HMTX_ENTRIES[i].lsb_); + } + + return true; +} + +bool VerifyHMTX(Table* original, Table* target) { + EXPECT_TRUE(VerifyHMTX(original)); + EXPECT_TRUE(VerifyHMTX(target)); + return true; +} + +} // namespace sfntly diff --git a/test/verify_loca.cc b/test/verify_loca.cc new file mode 100644 index 0000000..a1f14c2 --- /dev/null +++ b/test/verify_loca.cc @@ -0,0 +1,248 @@ +/* + * 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 "gtest/gtest.h" +#include "sfntly/font.h" +#include "sfntly/loca_table.h" +#include "test/serialization_test.h" + +namespace sfntly { + +const int32_t LOCA_NUM_LOCAS = 198; +const int32_t LOCAS[] = { + 0x00000, // 0 + 0x00000, // 1 + 0x00000, // 2 + 0x00000, // 3 + 0x00000, // 4 + 0x00060, // 5 + 0x000E0, // 6 + 0x0014C, // 7 + 0x001FC, // 8 + 0x002C8, // 9 + 0x00358, // 10 + 0x0039C, // 11 + 0x003D4, // 12 + 0x0040C, // 13 + 0x004B4, // 14 + 0x004E4, // 15 + 0x00530, // 16 + 0x0054C, // 17 + 0x00584, // 18 + 0x005A0, // 19 + 0x0061C, // 20 + 0x0063C, // 21 + 0x006C4, // 22 + 0x0074C, // 23 + 0x0078C, // 24 + 0x00804, // 25 + 0x00888, // 26 + 0x008AC, // 27 + 0x0096C, // 28 + 0x009F0, // 29 + 0x00A08, // 30 + 0x00A20, // 31 + 0x00A48, // 32 + 0x00A70, // 33 + 0x00A98, // 34 + 0x00B44, // 35 + 0x00C40, // 36 + 0x00C78, // 37 + 0x00D24, // 38 + 0x00D9C, // 39 + 0x00DF8, // 40 + 0x00E28, // 41 + 0x00E54, // 42 + 0x00EDC, // 43 + 0x00F0C, // 44 + 0x00F24, // 45 + 0x00F6C, // 46 + 0x00FA4, // 47 + 0x00FC4, // 48 + 0x00FFC, // 49 + 0x01028, // 50 + 0x010BC, // 51 + 0x01114, // 52 + 0x011C0, // 53 + 0x0121C, // 54 + 0x012C0, // 55 + 0x012E8, // 56 + 0x0133C, // 57 + 0x01364, // 58 + 0x013A0, // 59 + 0x013E0, // 60 + 0x01410, // 61 + 0x0143C, // 62 + 0x01460, // 63 + 0x01480, // 64 + 0x014A4, // 65 + 0x014C8, // 66 + 0x014E0, // 67 + 0x0152C, // 68 + 0x015AC, // 69 + 0x01618, // 70 + 0x01680, // 71 + 0x016EC, // 72 + 0x0175C, // 73 + 0x017B0, // 74 + 0x01848, // 75 + 0x01898, // 76 + 0x018DC, // 77 + 0x01948, // 78 + 0x01980, // 79 + 0x019B0, // 80 + 0x01A28, // 81 + 0x01A74, // 82 + 0x01AE0, // 83 + 0x01B4C, // 84 + 0x01BC0, // 85 + 0x01BFC, // 86 + 0x01C94, // 87 + 0x01CCC, // 88 + 0x01D1C, // 89 + 0x01D48, // 90 + 0x01D84, // 91 + 0x01DBC, // 92 + 0x01E2C, // 93 + 0x01E54, // 94 + 0x01F04, // 95 + 0x01F1C, // 96 + 0x01FCC, // 97 + 0x02028, // 98 + 0x02044, // 99 + 0x020AC, // 100 + 0x02128, // 101 + 0x021B8, // 102 + 0x0220C, // 103 + 0x02234, // 104 + 0x022E0, // 105 + 0x02348, // 106 + 0x023F4, // 107 + 0x02430, // 108 + 0x02450, // 109 + 0x02464, // 110 + 0x02540, // 111 + 0x0255C, // 112 + 0x025C0, // 113 + 0x025DC, // 114 + 0x02628, // 115 + 0x02680, // 116 + 0x0270C, // 117 + 0x02720, // 118 + 0x02768, // 119 + 0x027A4, // 120 + 0x027B8, // 121 + 0x027D0, // 122 + 0x027E8, // 123 + 0x02800, // 124 + 0x02818, // 125 + 0x02830, // 126 + 0x02848, // 127 + 0x02898, // 128 + 0x028B0, // 129 + 0x028C8, // 130 + 0x028E0, // 131 + 0x028F8, // 132 + 0x02910, // 133 + 0x02928, // 134 + 0x02940, // 135 + 0x02958, // 136 + 0x02970, // 137 + 0x029D8, // 138 + 0x029F0, // 139 + 0x02A08, // 140 + 0x02A20, // 141 + 0x02A38, // 142 + 0x02A50, // 143 + 0x02A68, // 144 + 0x02A84, // 145 + 0x02B30, // 146 + 0x02B48, // 147 + 0x02B60, // 148 + 0x02B78, // 149 + 0x02B90, // 150 + 0x02BA8, // 151 + 0x02C00, // 152 + 0x02CCC, // 153 + 0x02CE4, // 154 + 0x02CFC, // 155 + 0x02D14, // 156 + 0x02D2C, // 157 + 0x02D44, // 158 + 0x02D5C, // 159 + 0x02E6C, // 160 + 0x02E84, // 161 + 0x02E9C, // 162 + 0x02EB4, // 163 + 0x02ECC, // 164 + 0x02EE4, // 165 + 0x02F3C, // 166 + 0x02F94, // 167 + 0x02FC8, // 168 + 0x0303C, // 169 + 0x030FC, // 170 + 0x03114, // 171 + 0x0312C, // 172 + 0x03144, // 173 + 0x0315C, // 174 + 0x03174, // 175 + 0x0318C, // 176 + 0x031A4, // 177 + 0x03240, // 178 + 0x03258, // 179 + 0x03270, // 180 + 0x03288, // 181 + 0x032A0, // 182 + 0x032B8, // 183 + 0x0333C, // 184 + 0x03354, // 185 + 0x03370, // 186 + 0x0338C, // 187 + 0x033A8, // 188 + 0x033BC, // 189 + 0x033D0, // 190 + 0x033E4, // 191 + 0x033F4, // 192 + 0x0340C, // 193 + 0x03424, // 194 + 0x03438, // 195 + 0x03448, // 196 + 0x034D4 // 197 +}; + +static bool VerifyLOCA(Table* table) { + LocaTablePtr loca = down_cast(table); + if (loca == NULL) { + return false; + } + + EXPECT_EQ(loca->NumLocas(), LOCA_NUM_LOCAS); + EXPECT_EQ(loca->NumGlyphs(), LOCA_NUM_LOCAS - 1); + + for (int32_t i = 0; i < LOCA_NUM_LOCAS - 1; ++i) { + EXPECT_EQ(loca->GlyphOffset(i), LOCAS[i]); + EXPECT_EQ(loca->GlyphLength(i), LOCAS[i + 1] - LOCAS[i]); + } + return true; +} + +bool VerifyLOCA(Table* original, Table* target) { + EXPECT_TRUE(VerifyLOCA(original)); + EXPECT_TRUE(VerifyLOCA(target)); + return true; +} + +} // namespace sfntly diff --git a/test/verify_maxp.cc b/test/verify_maxp.cc new file mode 100644 index 0000000..d789fdb --- /dev/null +++ b/test/verify_maxp.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 "gtest/gtest.h" +#include "sfntly/font.h" +#include "sfntly/maximum_profile_table.h" +#include "test/serialization_test.h" + +namespace sfntly { + +const int32_t MAXP_NUM_GLYPHS = 197; +const int32_t MAXP_MAX_POINTS = 98; +const int32_t MAXP_MAX_CONTOURS = 5; +const int32_t MAXP_MAX_COMPOSITE_POINTS = 84; +const int32_t MAXP_MAX_COMPOSITE_CONTOURS = 4; +const int32_t MAXP_MAX_ZONES = 2; +const int32_t MAXP_MAX_TWILIGHT_POINTS = 0; +const int32_t MAXP_MAX_STORAGE = 1; +const int32_t MAXP_MAX_FUNCTION_DEFS = 1; +const int32_t MAXP_MAX_INSTR_DEFS = 0; +const int32_t MAXP_MAX_STACK_ELEMENTS = 64; +const int32_t MAXP_MAX_INSTR_SIZE = 0; +const int32_t MAXP_MAX_COMPONENT_ELEMENTS = 2; +const int32_t MAXP_MAX_COMPONENT_DEPTH = 3; + +static bool VerifyMAXP(Table* table) { + MaximumProfileTablePtr maxp = down_cast(table); + if (maxp == NULL) { + return false; + } + + EXPECT_EQ(maxp->Version(), SFNTVERSION_1); + EXPECT_EQ(maxp->NumGlyphs(), MAXP_NUM_GLYPHS); + EXPECT_EQ(maxp->MaxPoints(), MAXP_MAX_POINTS); + EXPECT_EQ(maxp->MaxContours(), MAXP_MAX_CONTOURS); + EXPECT_EQ(maxp->MaxCompositePoints(), MAXP_MAX_COMPOSITE_POINTS); + // TODO(arthurhsu): maxCompositeContours observed in Microsoft TTF report. + // Check with stuartg and see if this is a miss. + EXPECT_EQ(maxp->MaxZones(), MAXP_MAX_ZONES); + EXPECT_EQ(maxp->MaxTwilightPoints(), MAXP_MAX_TWILIGHT_POINTS); + EXPECT_EQ(maxp->MaxStorage(), MAXP_MAX_STORAGE); + EXPECT_EQ(maxp->MaxFunctionDefs(), MAXP_MAX_FUNCTION_DEFS); + // TODO(arthurhsu): maxInstructionDefs observed in Microsoft TTF report. + // Check with stuartg and see if this is a miss. + EXPECT_EQ(maxp->MaxStackElements(), MAXP_MAX_STACK_ELEMENTS); + EXPECT_EQ(maxp->MaxSizeOfInstructions(), MAXP_MAX_INSTR_SIZE); + EXPECT_EQ(maxp->MaxComponentElements(), MAXP_MAX_COMPONENT_ELEMENTS); + EXPECT_EQ(maxp->MaxComponentDepth(), MAXP_MAX_COMPONENT_DEPTH); + + return true; +} + +bool VerifyMAXP(Table* original, Table* target) { + EXPECT_TRUE(VerifyMAXP(original)); + EXPECT_TRUE(VerifyMAXP(target)); + return true; +} + +} // namespace sfntly diff --git a/test/verify_name.cc b/test/verify_name.cc new file mode 100644 index 0000000..d55d924 --- /dev/null +++ b/test/verify_name.cc @@ -0,0 +1,88 @@ +/* + * 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 "gtest/gtest.h" +#include "sfntly/font.h" +#include "sfntly/name_table.h" +#include "test/serialization_test.h" + +namespace sfntly { + +const int32_t NAME_FORMAT = 0; +const int32_t NAME_COUNT = 31; +const NameTable::NameEntryId NAME_IDS[] = { + NameTable::NameEntryId(1, 0, 0, 0), // 0 + NameTable::NameEntryId(1, 0, 0, 1), // 1 + NameTable::NameEntryId(1, 0, 0, 2), // 2 + NameTable::NameEntryId(1, 0, 0, 3), // 3 + NameTable::NameEntryId(1, 0, 0, 4), // 4 + NameTable::NameEntryId(1, 0, 0, 5), // 5 + NameTable::NameEntryId(1, 0, 0, 6), // 6 + NameTable::NameEntryId(1, 0, 0, 9), // 7 + NameTable::NameEntryId(1, 0, 0, 11), // 8 + NameTable::NameEntryId(1, 0, 0, 12), // 9 + NameTable::NameEntryId(1, 0, 0, 13), // 10 + NameTable::NameEntryId(3, 1, 1031, 2), // 11 + NameTable::NameEntryId(3, 1, 1033, 0), // 12 + NameTable::NameEntryId(3, 1, 1033, 1), // 13 + NameTable::NameEntryId(3, 1, 1033, 2), // 14 + NameTable::NameEntryId(3, 1, 1033, 3), // 15 + NameTable::NameEntryId(3, 1, 1033, 4), // 16 + NameTable::NameEntryId(3, 1, 1033, 5), // 17 + NameTable::NameEntryId(3, 1, 1033, 6), // 18 + NameTable::NameEntryId(3, 1, 1033, 9), // 19 + NameTable::NameEntryId(3, 1, 1033, 11), // 20 + NameTable::NameEntryId(3, 1, 1033, 12), // 21 + NameTable::NameEntryId(3, 1, 1033, 13), // 22 + NameTable::NameEntryId(3, 1, 1034, 2), // 23 + NameTable::NameEntryId(3, 1, 1036, 2), // 24 + NameTable::NameEntryId(3, 1, 1038, 2), // 25 + NameTable::NameEntryId(3, 1, 1040, 2), // 26 + NameTable::NameEntryId(3, 1, 1043, 2), // 27 + NameTable::NameEntryId(3, 1, 1044, 2), // 28 + NameTable::NameEntryId(3, 1, 1049, 2), // 29 + NameTable::NameEntryId(3, 1, 1053, 2), // 30 +}; + +static bool VerifyNAME(Table* table) { + // TODO(arthurhsu): Better testing can be done here. Right now we just + // iterate through the entries and get entry ids. + NameTablePtr name = down_cast(table); + if (name == NULL) { + return false; + } + + EXPECT_EQ(name->Format(), NAME_FORMAT); + EXPECT_EQ(name->NameCount(), NAME_COUNT); + fprintf(stderr, "checking name entry: "); + for (int32_t i = 0; i < NAME_COUNT; ++i) { + fprintf(stderr, "%d ", i); + EXPECT_EQ(name->PlatformId(i), NAME_IDS[i].platform_id()); + EXPECT_EQ(name->EncodingId(i), NAME_IDS[i].encoding_id()); + EXPECT_EQ(name->LanguageId(i), NAME_IDS[i].language_id()); + EXPECT_EQ(name->NameId(i), NAME_IDS[i].name_id()); + } + fprintf(stderr, "\n"); + return true; +} + +bool VerifyNAME(Table* original, Table* target) { + EXPECT_TRUE(VerifyNAME(original)); + EXPECT_TRUE(VerifyNAME(target)); + return true; +} + +} // namespace sfntly diff --git a/test/verify_os2.cc b/test/verify_os2.cc new file mode 100644 index 0000000..e604be9 --- /dev/null +++ b/test/verify_os2.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 "gtest/gtest.h" +#include "sfntly/font.h" +#include "sfntly/os2_table.h" +#include "test/serialization_test.h" + +namespace sfntly { + +const int32_t OS2_VERSION = 1; +const int32_t OS2_XAVG_CHAR_WIDTH = 863; +const int32_t OS2_US_WEIGHT_CLASS = 500; +const int32_t OS2_US_WIDTH_CLASS = 5; +const int32_t OS2_FS_TYPE = 0; +const int32_t OS2_YSUBS_XSIZE = 0; +const int32_t OS2_YSUBS_YSIZE = 2; +const int32_t OS2_YSUBS_XOFFSET = -16560; +const int32_t OS2_YSUBS_YOFFSET = 0; +const int32_t OS2_YSUPS_XSIZE = -25944; +const int32_t OS2_YSUPS_YSIZE = -27176; +const int32_t OS2_YSUPS_XOFFSET = -16376; +const int32_t OS2_YSUPS_YOFFSET = 1; +const int32_t OS2_YSTRIKEOUT_SIZE = 12312; +const int32_t OS2_YSTRIKEOUT_POS = -16224; +const int32_t OS2_SFAMILY_CLASS = 0; +const byte_t OS2_PANOSE[] = { 2, 11, 6, 3, 6, 1, 0, 0, 0, 0 }; +const int64_t OS2_UL_UNICODE_RANGE1 = 0x80000003L; +const int64_t OS2_UL_UNICODE_RANGE2 = 2L; +const int64_t OS2_UL_UNICODE_RANGE3 = 0L; +const int64_t OS2_UL_UNICODE_RANGE4 = 0L; +const byte_t OS2_ACH_VEND_ID[] = { 'P', 'f', 'E', 'd' }; +const int32_t OS2_FS_SELECTION = 0; +const int32_t OS2_US_FIRST_CHAR_IDX = 0x20; +const int32_t OS2_US_LAST_CHAR_IDX = 0x20AC; +const int32_t OS2_STYPO_ASCENDER = 1597; +const int32_t OS2_STYPO_DESCENDER = -451; +const int32_t OS2_STYPO_LINE_GAP = 0; +const int32_t OS2_US_WIN_ASCENT = 1993; +const int32_t OS2_US_WIN_DESCENT = 449; +const int64_t OS2_UL_CODE_PAGE_RANGE1 = 1L; +const int64_t OS2_UL_CODE_PAGE_RANGE2 = 0x80D40000L; + +static bool VerifyOS_2(Table* table) { + OS2TablePtr os2 = down_cast(table); + if (os2 == NULL) { + return false; + } + + EXPECT_EQ(os2->Version(), OS2_VERSION); + EXPECT_EQ(os2->XAvgCharWidth(), OS2_XAVG_CHAR_WIDTH); + EXPECT_EQ(os2->UsWeightClass(), OS2_US_WEIGHT_CLASS); + EXPECT_EQ(os2->UsWidthClass(), OS2_US_WIDTH_CLASS); + EXPECT_EQ(os2->FsType(), OS2_FS_TYPE); + EXPECT_EQ(os2->YSubscriptXSize(), OS2_YSUBS_XSIZE); + EXPECT_EQ(os2->YSubscriptYSize(), OS2_YSUBS_YSIZE); + EXPECT_EQ(os2->YSubscriptXOffset(), OS2_YSUBS_XOFFSET); + EXPECT_EQ(os2->YSubscriptYOffset(), OS2_YSUBS_YOFFSET); + EXPECT_EQ(os2->YSuperscriptXSize(), OS2_YSUPS_XSIZE); + EXPECT_EQ(os2->YSuperscriptYSize(), OS2_YSUPS_YSIZE); + EXPECT_EQ(os2->YSuperscriptXOffset(), OS2_YSUPS_XOFFSET); + EXPECT_EQ(os2->YSuperscriptYOffset(), OS2_YSUPS_YOFFSET); + EXPECT_EQ(os2->YStrikeoutSize(), OS2_YSTRIKEOUT_SIZE); + EXPECT_EQ(os2->YStrikeoutPosition(), OS2_YSTRIKEOUT_POS); + EXPECT_EQ(os2->SFamilyClass(), OS2_SFAMILY_CLASS); + + ByteVector panose; + os2->Panose(&panose); + EXPECT_EQ(panose.size(), sizeof(OS2_PANOSE)); + for (size_t i = 0; i < panose.size(); ++i) { + EXPECT_EQ(panose[i], OS2_PANOSE[i]); + } + + EXPECT_EQ(os2->UlUnicodeRange1(), OS2_UL_UNICODE_RANGE1); + EXPECT_EQ(os2->UlUnicodeRange2(), OS2_UL_UNICODE_RANGE2); + EXPECT_EQ(os2->UlUnicodeRange3(), OS2_UL_UNICODE_RANGE3); + EXPECT_EQ(os2->UlUnicodeRange4(), OS2_UL_UNICODE_RANGE4); + + ByteVector vend_id; + os2->AchVendId(&vend_id); + EXPECT_EQ(vend_id.size(), sizeof(OS2_ACH_VEND_ID)); + for (size_t i = 0; i < vend_id.size(); ++i) { + EXPECT_EQ(vend_id[i], OS2_ACH_VEND_ID[i]); + } + + EXPECT_EQ(os2->FsSelection(), OS2_FS_SELECTION); + EXPECT_EQ(os2->UsFirstCharIndex(), OS2_US_FIRST_CHAR_IDX); + EXPECT_EQ(os2->UsLastCharIndex(), OS2_US_LAST_CHAR_IDX); + EXPECT_EQ(os2->STypoAscender(), OS2_STYPO_ASCENDER); + EXPECT_EQ(os2->STypoDescender(), OS2_STYPO_DESCENDER); + EXPECT_EQ(os2->STypoLineGap(), OS2_STYPO_LINE_GAP); + EXPECT_EQ(os2->UsWinAscent(), OS2_US_WIN_ASCENT); + EXPECT_EQ(os2->UsWinDescent(), OS2_US_WIN_DESCENT); + EXPECT_EQ(os2->UlCodePageRange1(), OS2_UL_CODE_PAGE_RANGE1); + EXPECT_EQ(os2->UlCodePageRange2(), OS2_UL_CODE_PAGE_RANGE2); + + // TODO(arthurhsu): UlCodePageRange() not tested + // TODO(arthurhsu): SxHeight() not tested + // TODO(arthurhsu): SCapHeight() not tested + // TODO(arthurhsu): UsDefaultChar() not tested + // TODO(arthurhsu): UsBreakChar() not tested + // TODO(arthurhsu): UsMaxContext() not tested + + return true; +} + +bool VerifyOS_2(Table* original, Table* target) { + EXPECT_TRUE(VerifyOS_2(original)); + EXPECT_TRUE(VerifyOS_2(target)); + return true; +} + +} // namespace sfntly -- cgit v1.2.3 From 3c1c27438043c7423a1725101d2cf5a5b3b7fa12 Mon Sep 17 00:00:00 2001 From: "dfilimon@google.com" Date: Fri, 12 Aug 2011 21:02:37 +0000 Subject: Commit for testing the buildbots. Nothing changed except for a comment. git-svn-id: http://sfntly.googlecode.com/svn/trunk/cpp/src@48 672e30a5-4c29-85ac-ac6d-611c735e0a51 --- test/test_utils.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/test_utils.h b/test/test_utils.h index 4d692e1..a92cd5b 100644 --- a/test/test_utils.h +++ b/test/test_utils.h @@ -39,7 +39,7 @@ class TestUtils { // @param offset2 offset for comparison in byte array 2 // @param length the length of the byte arrays to compare // @return true if the array segments are equal; false otherwise - // TODO(dfilimon): implement + // TODO(dfilimon): implement sometime in the future :) static bool Equals(ByteArray* b1, int32_t offset1, ByteArray* b2, -- cgit v1.2.3 From 633131f1440aad16805eefd9ff04455f93429433 Mon Sep 17 00:00:00 2001 From: "arthurhsu@google.com" Date: Tue, 16 Aug 2011 02:26:47 +0000 Subject: Add test case: chrome subsetter git-svn-id: http://sfntly.googlecode.com/svn/trunk/cpp/src@52 672e30a5-4c29-85ac-ac6d-611c735e0a51 --- test/chrome_subsetter.cc | 75 +++++++++++ test/font_subsetter.cc | 41 ++++++ test/font_subsetter.h | 51 +++++++ test/subsetter_impl.cc | 343 +++++++++++++++++++++++++++++++++++++++++++++++ test/subsetter_impl.h | 75 +++++++++++ 5 files changed, 585 insertions(+) create mode 100644 test/chrome_subsetter.cc create mode 100644 test/font_subsetter.cc create mode 100644 test/font_subsetter.h create mode 100644 test/subsetter_impl.cc create mode 100644 test/subsetter_impl.h diff --git a/test/chrome_subsetter.cc b/test/chrome_subsetter.cc new file mode 100644 index 0000000..0c5c9ca --- /dev/null +++ b/test/chrome_subsetter.cc @@ -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. + */ + +#include "gtest/gtest.h" +#include "test/font_subsetter.h" +#include "test/test_data.h" +#include "test/test_font_utils.h" + +namespace { + // Use an additional variable to easily change name for testing. + const char* kInputFileName = sfntly::SAMPLE_TTF_FILE; + const char* kFontName = "Tuffy"; + const char* kOutputFileName = "tuffy-s.ttf"; + // The subset we want: Hello, world! + // The array is unsorted to verify that the subsetter gets the glyph id + // correctly. + const unsigned int kGlyphIds[] = { 43, 72, 79, 82, 15, 3, 90, 85, 71, 4 }; + const unsigned int kGlyphIdsCount = sizeof(kGlyphIds) / sizeof(unsigned int); +} + +// This function is deliberately located at global namespace. +bool TestChromeSubsetter() { + sfntly::ByteVector input_buffer; + sfntly::LoadFile(kInputFileName, &input_buffer); + EXPECT_GT(input_buffer.size(), (size_t)0); + + unsigned char* output_buffer = NULL; + int output_length = + SfntlyWrapper::SubsetFont(kFontName, + &(input_buffer[0]), + input_buffer.size(), + kGlyphIds, + kGlyphIdsCount, + &output_buffer); + + EXPECT_GT(output_length, 0); + + if (output_length > 0) { + FILE* output_file = NULL; +#if defined WIN32 + fopen_s(&output_file, kOutputFileName, "wb"); +#else + output_file = fopen(kOutputFileName, "wb"); +#endif + EXPECT_TRUE((output_file != NULL)); + if (output_file) { + int byte_count = fwrite(output_buffer, 1, output_length, output_file); + EXPECT_EQ(byte_count, output_length); + fflush(output_file); + fclose(output_file); + } + + delete[] output_buffer; + return true; + } + + return false; +} + +TEST(ChromeSubsetter, All) { + EXPECT_TRUE(TestChromeSubsetter()); +} diff --git a/test/font_subsetter.cc b/test/font_subsetter.cc new file mode 100644 index 0000000..401c9f5 --- /dev/null +++ b/test/font_subsetter.cc @@ -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. + */ +// File is originally from Chromium third_party/sfntly/src/subsetter. +// Use as test case in sfntly so that problems can be caught in upstream early. + +#include "test/font_subsetter.h" + +#include "test/subsetter_impl.h" + +int SfntlyWrapper::SubsetFont(const char* font_name, + const unsigned char* original_font, + size_t font_size, + const unsigned int* glyph_ids, + size_t glyph_count, + unsigned char** output_buffer) { + if (output_buffer == NULL || + original_font == NULL || font_size == 0 || + glyph_ids == NULL || glyph_count == 0) { + return 0; + } + + sfntly::SubsetterImpl subsetter; + if (!subsetter.LoadFont(font_name, original_font, font_size)) { + return -1; // Load error or font not found. + } + + return subsetter.SubsetFont(glyph_ids, glyph_count, output_buffer); +} diff --git a/test/font_subsetter.h b/test/font_subsetter.h new file mode 100644 index 0000000..6d001eb --- /dev/null +++ b/test/font_subsetter.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. + */ +// File is originally from Chromium third_party/sfntly/src/subsetter. +// Use as test case in sfntly so that problems can be caught in upstream early. +#ifndef TYPOGRAPHY_FONT_SFNTLY_SRC_TEST_FONT_SUBSETTER_H_ +#define TYPOGRAPHY_FONT_SFNTLY_SRC_TEST_FONT_SUBSETTER_H_ + +#include + +class SfntlyWrapper { + public: + + // Font subsetting API + // + // Input TTF/TTC/OTF fonts, specify the glyph IDs to subset, and the subset + // font is returned in |output_buffer| (caller to delete[]). Return value is + // the length of output_buffer allocated. + // + // If subsetting fails, a negative value is returned. If none of the glyph + // IDs specified is found, the function will return 0. + // + // |font_name| Font name, required for TTC files. If specified NULL, + // the first available font is selected. + // |original_font| Original font file contents. + // |font_size| Size of |original_font| in bytes. + // |glyph_ids| Glyph IDs to subset. If the specified glyph ID is not + // found in the font file, it will be ignored silently. + // |glyph_count| Number of glyph IDs in |glyph_ids| + // |output_buffer| Generated subset font. Caller to delete[]. + static int SubsetFont(const char* font_name, + const unsigned char* original_font, + size_t font_size, + const unsigned int* glyph_ids, + size_t glyph_count, + unsigned char** output_buffer); +}; + +#endif // TYPOGRAPHY_FONT_SFNTLY_SRC_TEST_FONT_SUBSETTER_H_ diff --git a/test/subsetter_impl.cc b/test/subsetter_impl.cc new file mode 100644 index 0000000..7999f50 --- /dev/null +++ b/test/subsetter_impl.cc @@ -0,0 +1,343 @@ +/* + * 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. + */ +// File is originally from Chromium third_party/sfntly/src/subsetter. +// Use as test case in sfntly so that problems can be caught in upstream early. + +#include "test/subsetter_impl.h" + +#include + +#include +#include + +#include "sfntly/glyph_table.h" +#include "sfntly/loca_table.h" +#include "sfntly/name_table.h" +#include "sfntly/tag.h" +#include "sfntly/data/memory_byte_array.h" +#include "sfntly/port/memory_output_stream.h" + +namespace sfntly { + +void ConstructName(UChar* name_part, UnicodeString* name, int32_t name_id) { + switch(name_id) { + case NameId::kFullFontName: + *name = name_part; + break; + case NameId::kFontFamilyName: + case NameId::kPreferredFamily: + case NameId::kWWSFamilyName: { + UnicodeString original = *name; + *name = name_part; + *name += original; + break; + } + case NameId::kFontSubfamilyName: + case NameId::kPreferredSubfamily: + case NameId::kWWSSubfamilyName: + *name += name_part; + break; + default: + // This name part is not used to construct font name (e.g. copyright). + // Simply ignore it. + break; + } +} + +int32_t HashCode(int32_t platform_id, int32_t encoding_id, int32_t language_id, + int32_t name_id) { + int32_t result = platform_id << 24 | encoding_id << 16 | language_id << 8; + if (name_id == NameId::kFullFontName) { + result |= 0xff; + } else if (name_id == NameId::kPreferredFamily || + name_id == NameId::kPreferredSubfamily) { + result |= 0xf; + } else if (name_id == NameId::kWWSFamilyName || + name_id == NameId::kWWSSubfamilyName) { + result |= 1; + } + return result; +} + +SubsetterImpl::SubsetterImpl() { +} + +SubsetterImpl::~SubsetterImpl() { +} + +bool SubsetterImpl::LoadFont(const char* font_name, + const unsigned char* original_font, + size_t font_size) { + ByteArrayPtr raw_font = + new MemoryByteArray((byte_t*)original_font, font_size); + if (factory_ == NULL) { + factory_.Attach(FontFactory::GetInstance()); + } + + FontArray font_array; + factory_->LoadFonts(raw_font, &font_array); + font_ = FindFont(font_name, font_array); + if (font_ == NULL) { + return false; + } + + return true; +} + +int SubsetterImpl::SubsetFont(const unsigned int* glyph_ids, + size_t glyph_count, + unsigned char** output_buffer) { + if (factory_ == NULL || font_ == NULL) { + return -1; + } + + IntegerSet glyph_id_processed; + if (!ResolveCompositeGlyphs(glyph_ids, glyph_count, &glyph_id_processed) || + glyph_id_processed.empty()) { + return 0; + } + + FontPtr new_font; + new_font.Attach(Subset(glyph_id_processed)); + if (new_font == NULL) { + return 0; + } + + MemoryOutputStream output_stream; + factory_->SerializeFont(new_font, &output_stream); + int length = static_cast(output_stream.Size()); + if (length > 0) { + *output_buffer = new unsigned char[length]; + memcpy(*output_buffer, output_stream.Get(), length); + } + + return length; +} + +Font* SubsetterImpl::FindFont(const char* font_name, + const FontArray& font_array) { + if (font_array.empty() || font_array[0] == NULL) { + return NULL; + } + + if (font_name && strlen(font_name)) { + for (FontArray::const_iterator b = font_array.begin(), e = font_array.end(); + b != e; ++b) { + if (HasName(font_name, (*b).p_)) { + return (*b).p_; + } + } + } + + return font_array[0].p_; +} + +bool SubsetterImpl::HasName(const char* font_name, Font* font) { + UnicodeString font_string = UnicodeString::fromUTF8(font_name); + if (font_string.isEmpty()) + return false; + UnicodeString regular_suffix = UnicodeString::fromUTF8(" Regular"); + UnicodeString alt_font_string = font_string; + alt_font_string += regular_suffix; + + typedef std::map NameMap; + NameMap names; + NameTablePtr name_table = down_cast(font->GetTable(Tag::name)); + if (name_table == NULL) { + return false; + } + + for (int32_t i = 0; i < name_table->NameCount(); ++i) { + switch(name_table->NameId(i)) { + case NameId::kFontFamilyName: + case NameId::kFontSubfamilyName: + case NameId::kFullFontName: + case NameId::kPreferredFamily: + case NameId::kPreferredSubfamily: + case NameId::kWWSFamilyName: + case NameId::kWWSSubfamilyName: { + int32_t hash_code = HashCode(name_table->PlatformId(i), + name_table->EncodingId(i), + name_table->LanguageId(i), + name_table->NameId(i)); + UChar* name_part = name_table->Name(i); + ConstructName(name_part, &(names[hash_code]), name_table->NameId(i)); + delete[] name_part; + break; + } + default: + break; + } + } + + if (!names.empty()) { + for (NameMap::iterator b = names.begin(), e = names.end(); b != e; ++b) { + if (b->second.caseCompare(font_string, 0) == 0 || + b->second.caseCompare(alt_font_string, 0) == 0) { + return true; + } + } + } + return false; +} + +bool SubsetterImpl::ResolveCompositeGlyphs(const unsigned int* glyph_ids, + size_t glyph_count, + IntegerSet* glyph_id_processed) { + if (glyph_ids == NULL || glyph_count == 0 || glyph_id_processed == NULL) { + return false; + } + + // Find glyf and loca table. + 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) { + // The font is invalid. + return false; + } + + // Sort and uniquify glyph ids. + IntegerSet glyph_id_remaining; + glyph_id_remaining.insert(0); // Always include glyph id 0. + for (size_t i = 0; i < glyph_count; ++i) { + glyph_id_remaining.insert(glyph_ids[i]); + } + + // Identify if any given glyph id maps to a composite glyph. If so, include + // the glyphs referenced by that composite glyph. + while (!glyph_id_remaining.empty()) { + IntegerSet comp_glyph_id; + for (IntegerSet::iterator i = glyph_id_remaining.begin(), + e = glyph_id_remaining.end(); i != e; ++i) { + if (*i < 0 || *i >= loca_table->NumGlyphs()) { + // Invalid glyph id, ignore. + continue; + } + + int32_t length = loca_table->GlyphLength(*i); + if (length == 0) { + // Empty glyph, ignore. + continue; + } + int32_t offset = loca_table->GlyphOffset(*i); + + GlyphPtr glyph; + glyph.Attach(glyph_table->GetGlyph(offset, length)); + if (glyph == NULL) { + // Error finding glyph, ignore. + continue; + } + + if (glyph->GlyphType() == GlyphType::kComposite) { + Ptr comp_glyph = + down_cast(glyph.p_); + for (int32_t j = 0; j < comp_glyph->NumGlyphs(); ++j) { + int32_t glyph_id = comp_glyph->GlyphIndex(j); + if (glyph_id_processed->find(glyph_id) == glyph_id_processed->end() && + glyph_id_remaining.find(glyph_id) == glyph_id_remaining.end()) { + comp_glyph_id.insert(comp_glyph->GlyphIndex(j)); + } + } + } + + glyph_id_processed->insert(*i); + } + + glyph_id_remaining.clear(); + glyph_id_remaining = comp_glyph_id; + } + + return true; +} + +CALLER_ATTACH Font* SubsetterImpl::Subset(const IntegerSet& glyph_ids) { + // The tables are already checked in ResolveCompositeGlyphs(). + GlyphTablePtr glyph_table = + down_cast(font_->GetTable(Tag::glyf)); + LocaTablePtr loca_table = down_cast(font_->GetTable(Tag::loca)); + + // Setup font builders we need. + FontBuilderPtr font_builder; + font_builder.Attach(factory_->NewFontBuilder()); + + GlyphTableBuilderPtr glyph_table_builder; + glyph_table_builder.Attach(down_cast( + font_builder->NewTableBuilder(Tag::glyf))); + LocaTableBuilderPtr loca_table_builder; + loca_table_builder.Attach(down_cast( + font_builder->NewTableBuilder(Tag::loca))); + if (glyph_table_builder == NULL || loca_table_builder == NULL) { + // Out of memory. + return NULL; + } + + // Extract glyphs and setup loca list. + IntegerList loca_list; + loca_list.resize(loca_table->NumGlyphs()); + loca_list.push_back(0); + int32_t last_glyph_id = 0; + int32_t last_offset = 0; + GlyphTable::GlyphBuilderList* glyph_builders = + glyph_table_builder->GlyphBuilders(); + for (IntegerSet::const_iterator i = glyph_ids.begin(), e = glyph_ids.end(); + i != e; ++i) { + int32_t length = loca_table->GlyphLength(*i); + int32_t offset = loca_table->GlyphOffset(*i); + + GlyphPtr glyph; + glyph.Attach(glyph_table->GetGlyph(offset, length)); + + // Add glyph to new glyf table. + ReadableFontDataPtr data = glyph->ReadFontData(); + WritableFontDataPtr copy_data; + copy_data.Attach(font_builder->GetNewData(data->Length())); + data->CopyTo(copy_data); + GlyphBuilderPtr glyph_builder; + glyph_builder.Attach(glyph_table_builder->GlyphBuilder(copy_data)); + glyph_builders->push_back(glyph_builder); + + // Configure loca list. + for (int32_t j = last_glyph_id + 1; j <= *i; ++j) { + loca_list[j] = last_offset; + } + last_offset += length; + loca_list[*i + 1] = last_offset; + last_glyph_id = *i; + } + for (int32_t j = last_glyph_id + 1; j <= loca_table->NumGlyphs(); ++j) { + loca_list[j] = last_offset; + } + loca_table_builder->SetLocaList(&loca_list); + + // Setup remaining builders. + for (TableMap::iterator i = font_->Tables()->begin(), + e = font_->Tables()->end(); i != e; ++i) { + // We already build the builder for glyph and loca. + if (i->first != Tag::glyf && i->first != Tag::loca) { + // The newTableBuilder() call will alter internal state of font_builder + // AND the reference count of returned object. Therefore we need to + // dereference it. + TableBuilderPtr dereference; + dereference.Attach( + font_builder->NewTableBuilder(i->first, i->second->ReadFontData())); + } + } + + return font_builder->Build(); +} + +} // namespace sfntly diff --git a/test/subsetter_impl.h b/test/subsetter_impl.h new file mode 100644 index 0000000..6ce0aee --- /dev/null +++ b/test/subsetter_impl.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. + */ +// File is originally from Chromium third_party/sfntly/src/subsetter. +// Use as test case in sfntly so that problems can be caught in upstream early. + +#ifndef TYPOGRAPHY_FONT_SFNTLY_SRC_TEST_SUBSETTER_IMPL_H_ +#define TYPOGRAPHY_FONT_SFNTLY_SRC_TEST_SUBSETTER_IMPL_H_ + +#include "sfntly/font.h" +#include "sfntly/font_factory.h" + +namespace sfntly { + +// 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 + +class SubsetterImpl { + public: + SubsetterImpl(); + ~SubsetterImpl(); + + bool LoadFont(const char* font_name, + const unsigned char* original_font, + size_t font_size); + int SubsetFont(const unsigned int* glyph_ids, + size_t glyph_count, + unsigned char** output_buffer); + + private: + Font* FindFont(const char* font_name, const FontArray& font_array); + bool HasName(const char* font_name, Font* font); + bool ResolveCompositeGlyphs(const unsigned int* glyph_ids, + size_t glyph_count, + IntegerSet* glyph_id_processed); + CALLER_ATTACH Font* Subset(const IntegerSet& glyph_ids); + + FontFactoryPtr factory_; + FontPtr font_; +}; + +} // namespace sfntly + +#endif // TYPOGRAPHY_FONT_SFNTLY_SRC_TEST_SUBSETTER_IMPL_H_ -- cgit v1.2.3 From c10c3d53cd1401f158e89697b7fe019b6828fa00 Mon Sep 17 00:00:00 2001 From: "arthurhsu@google.com" Date: Wed, 17 Aug 2011 01:29:17 +0000 Subject: Bug fix: when table is located at the end of file, original code will determine the wrong size and refuse to read it. Also reverted changes in r48 due to its test nature. git-svn-id: http://sfntly.googlecode.com/svn/trunk/cpp/src@54 672e30a5-4c29-85ac-ac6d-611c735e0a51 --- sfntly/data/readable_font_data.cc | 21 ++++++++++++--------- sfntly/data/writable_font_data.cc | 8 ++++++++ sfntly/data/writable_font_data.h | 3 +++ sfntly/font.cc | 13 ++++++------- test/serialization_test.cc | 3 +-- test/test_utils.h | 2 +- 6 files changed, 31 insertions(+), 19 deletions(-) diff --git a/sfntly/data/readable_font_data.cc b/sfntly/data/readable_font_data.cc index 5f8478d..904e7db 100644 --- a/sfntly/data/readable_font_data.cc +++ b/sfntly/data/readable_font_data.cc @@ -198,15 +198,18 @@ void ReadableFontData::ComputeChecksum() { int64_t ReadableFontData::ComputeCheckSum(int32_t low_bound, int32_t high_bound) { int64_t sum = 0; - for (int32_t i = low_bound; i < high_bound; i += 4) { - int32_t b3 = ReadUByte(i); - b3 = (b3 == -1) ? 0 : b3; - int32_t b2 = ReadUByte(i + 1); - b2 = (b2 == -1) ? 0 : b2; - int32_t b1 = ReadUByte(i + 2); - b1 = (b1 == -1) ? 0 : b1; - int32_t b0 = ReadUByte(i + 3); - b0 = (b0 == -1) ? 0 : b0; + // 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; diff --git a/sfntly/data/writable_font_data.cc b/sfntly/data/writable_font_data.cc index bf03516..5f694be 100644 --- a/sfntly/data/writable_font_data.cc +++ b/sfntly/data/writable_font_data.cc @@ -125,6 +125,14 @@ int32_t WritableFontData::WriteDateTime(int32_t index, int64_t date) { 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()) { diff --git a/sfntly/data/writable_font_data.h b/sfntly/data/writable_font_data.h index ec74da7..ceefb30 100644 --- a/sfntly/data/writable_font_data.h +++ b/sfntly/data/writable_font_data.h @@ -61,6 +61,9 @@ class WritableFontData : public ReadableFontData { virtual int32_t WriteFixed(int32_t index, int32_t l); virtual int32_t WriteDateTime(int32_t index, int64_t date); + virtual void CopyFrom(InputStream* is, int32_t length); + 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 diff --git a/sfntly/font.cc b/sfntly/font.cc index 32ecca7..8d264b5 100644 --- a/sfntly/font.cc +++ b/sfntly/font.cc @@ -521,11 +521,10 @@ void Font::Builder::LoadTableData(TableHeaderSortedSet* headers, table_header != table_end; ++table_header) { is->Skip((*table_header)->offset() - is->position()); FontInputStream table_is(is, (*table_header)->length()); - int32_t roundup_length = ((*table_header)->length() + 3) & ~3; - ByteArrayPtr array; - array.Attach(factory_->GetNewArray(roundup_length)); - array->CopyFrom(&table_is, (*table_header)->length()); - WritableFontDataPtr data = new WritableFontData(array); + WritableFontDataPtr data; + data.Attach( + WritableFontData::CreateWritableFontData((*table_header)->length())); + data->CopyFrom(&table_is, (*table_header)->length()); table_data->insert(DataBlockEntry(*table_header, data)); } } @@ -536,9 +535,9 @@ void Font::Builder::LoadTableData(TableHeaderSortedSet* headers, for (TableHeaderSortedSet::iterator table_header = headers->begin(), table_end = headers->end(); table_header != table_end; ++table_header) { - int32_t roundup_length = ((*table_header)->length() + 3) & ~3; FontDataPtr sliced_data; - sliced_data.Attach(fd->Slice((*table_header)->offset(), roundup_length)); + 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)); } diff --git a/test/serialization_test.cc b/test/serialization_test.cc index 507a98c..08c8288 100755 --- a/test/serialization_test.cc +++ b/test/serialization_test.cc @@ -67,8 +67,7 @@ bool TestSerialization() { TablePtr serialized_table = serialized->GetTable(TTF_KNOWN_TAGS[i]); EXPECT_EQ(original_table->CalculatedChecksum(), serialized_table->CalculatedChecksum()); - EXPECT_EQ(((original_table->Length() + 3) & ~3), - ((serialized_table->Length() + 3) & ~3)); + EXPECT_EQ(original_table->Length(), serialized_table->Length()); if (TTF_KNOWN_TAGS[i] == Tag::hhea) { EXPECT_TRUE(VerifyHHEA(original_table, serialized_table)); diff --git a/test/test_utils.h b/test/test_utils.h index a92cd5b..4d692e1 100644 --- a/test/test_utils.h +++ b/test/test_utils.h @@ -39,7 +39,7 @@ class TestUtils { // @param offset2 offset for comparison in byte array 2 // @param length the length of the byte arrays to compare // @return true if the array segments are equal; false otherwise - // TODO(dfilimon): implement sometime in the future :) + // TODO(dfilimon): implement static bool Equals(ByteArray* b1, int32_t offset1, ByteArray* b2, -- cgit v1.2.3 From 32a01c7c6e7be46dda9bfc78de9ce32d99e4c8b7 Mon Sep 17 00:00:00 2001 From: "arthurhsu@google.com" Date: Fri, 19 Aug 2011 22:05:08 +0000 Subject: Port files under /data to Aug 11 version. ReadableFontData.Search*() not ported since they're already in another CL under review. git-svn-id: http://sfntly.googlecode.com/svn/trunk/cpp/src@55 672e30a5-4c29-85ac-ac6d-611c735e0a51 --- sfntly/data/byte_array.cc | 45 ++++++---- sfntly/data/byte_array.h | 92 ++++++++++++++----- sfntly/data/font_data.cc | 2 +- sfntly/data/font_data.h | 23 +++-- sfntly/data/font_input_stream.cc | 2 +- sfntly/data/font_input_stream.h | 29 ++++++ sfntly/data/font_output_stream.cc | 32 ++++++- sfntly/data/font_output_stream.h | 32 +++++-- sfntly/data/growable_memory_byte_array.cc | 36 +++++--- sfntly/data/growable_memory_byte_array.h | 24 +++-- sfntly/data/memory_byte_array.cc | 33 +++---- sfntly/data/memory_byte_array.h | 37 ++++++-- sfntly/data/readable_font_data.cc | 46 ++++++---- sfntly/data/readable_font_data.h | 141 ++++++++++++++++++++++++++++-- sfntly/data/writable_font_data.cc | 23 ++--- sfntly/data/writable_font_data.h | 106 ++++++++++++++++++++-- sfntly/glyph_table.cc | 2 +- sfntly/name_table.cc | 2 +- sfntly/os2_table.cc | 4 +- sfntly/port/exception_type.h | 20 ++++- sfntly/port/memory_output_stream.cc | 27 +++++- sfntly/port/memory_output_stream.h | 1 + sfntly/port/output_stream.h | 9 +- sfntly/tag.h | 7 +- test/byte_array_test.cc | 2 +- test/font_data_test.cc | 13 +-- test/font_parsing_test.cc | 6 +- 27 files changed, 636 insertions(+), 160 deletions(-) diff --git a/sfntly/data/byte_array.cc b/sfntly/data/byte_array.cc index 5502185..c820adc 100644 --- a/sfntly/data/byte_array.cc +++ b/sfntly/data/byte_array.cc @@ -34,51 +34,57 @@ int32_t ByteArray::SetFilledLength(int32_t filled_length) { return filled_length_; } -byte_t ByteArray::Get(int32_t index) { - return InternalGet(index); +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, b->size()); + return Get(index, &((*b)[0]), 0, b->size()); } int32_t ByteArray::Get(int32_t index, - ByteVector* b, + byte_t* b, int32_t offset, int32_t length) { assert(b); if (index < 0 || index >= filled_length_) { - return -1; + return 0; } int32_t actual_length = std::min(length, filled_length_ - index); - if (actual_length < 0) { - return -1; - } return InternalGet(index, b, offset, actual_length); } -bool ByteArray::Put(int32_t index, byte_t b) { +void ByteArray::Put(int32_t index, byte_t b) { if (index < 0 || index >= Size()) { - return false; +#if defined (SFNTLY_NO_EXCEPTION) + return; +#else + throw IndexOutOfBoundException( + "Attempt to write outside the bounds of the data"); +#endif } - bool result = InternalPut(index, b); + InternalPut(index, b); filled_length_ = std::max(filled_length_, index + 1); - return result; } int32_t ByteArray::Put(int index, ByteVector* b) { assert(b); - return Put(index, b, 0, b->size()); + return Put(index, &((*b)[0]), 0, b->size()); } int32_t ByteArray::Put(int32_t index, - ByteVector* b, + 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); @@ -106,8 +112,9 @@ int32_t ByteArray::CopyTo(int32_t dst_offset, ByteArray* array, 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, buffer_length)) > 0) { - int bytes_written = array->Put(index + dst_offset, &b, 0, bytes_read); + 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); if (bytes_written != bytes_read) { #if defined (SFNTLY_NO_EXCEPTION) return 0; @@ -131,7 +138,7 @@ int32_t ByteArray::CopyTo(OutputStream* os, int32_t offset, int32_t length) { 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, buffer_length)) > 0) { + 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); @@ -145,7 +152,7 @@ bool ByteArray::CopyFrom(InputStream* is, int32_t length) { 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, bytes_read) != bytes_read) { + if (Put(index, &(b[0]), 0, bytes_read) != bytes_read) { #if defined (SFNTLY_NO_EXCEPTION) return 0; #else @@ -165,7 +172,7 @@ bool ByteArray::CopyFrom(InputStream* is) { 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, bytes_read) != bytes_read) { + if (Put(index, &b[0], 0, bytes_read) != bytes_read) { #if defined (SFNTLY_NO_EXCEPTION) return 0; #else diff --git a/sfntly/data/byte_array.h b/sfntly/data/byte_array.h index 9ac56c0..3375244 100644 --- a/sfntly/data/byte_array.h +++ b/sfntly/data/byte_array.h @@ -24,56 +24,62 @@ namespace sfntly { -// An interface abstraction to a byte array. Can be implemented to map to -// various types of data storage. +// 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(); - // Get the current filled and readable length of the array. + // Gets the current filled and readable length of the array. int32_t Length(); - // Get the maximum size of the array. This is the maximum number of bytes that + // 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); - // Get the byte from the given index. - virtual byte_t Get(int32_t index); + // 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); - // Get the bytes from the given index and fill the buffer with them. As many + // 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); - // Get the bytes from the given index and fill the buffer with them starting + // 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 put into the buffer + // @return the number of bytes read from the buffer virtual int32_t Get(int32_t index, - ByteVector* b, + byte_t* b, int32_t offset, int32_t length); - // Put the specified byte into the array at the given index unless that would + // 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 bool Put(int32_t index, byte_t b); + virtual void Put(int32_t index, byte_t b); - // Put the specified bytes into the array at the given index. The entire + // 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); - // Put the specified bytes into the array at the given index. All of the bytes + // 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. @@ -83,22 +89,22 @@ class ByteArray : virtual public RefCount { // @param length the number of bytes to copy into the array // @return the number of bytes actually written virtual int32_t Put(int32_t index, - ByteVector* b, + byte_t* b, int32_t offset, int32_t length); - // Fully copy this ByteArray to another ByteArray to the extent that the + // 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); - // Copy a segment of this ByteArray to another ByteArray. + // 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); - // Copy this ByteArray to another ByteArray. + // 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 @@ -109,9 +115,25 @@ class ByteArray : virtual public RefCount { 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: @@ -122,24 +144,52 @@ class ByteArray : virtual public RefCount { ByteArray(int32_t filled_length, int32_t storage_length); void Init(int32_t filled_length, int32_t storage_length, bool growable); - virtual bool InternalPut(int32_t index, byte_t b) = 0; + // 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, - ByteVector* b, + 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, - ByteVector* b, + 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_; diff --git a/sfntly/data/font_data.cc b/sfntly/data/font_data.cc index 437a810..ccc2a19 100644 --- a/sfntly/data/font_data.cc +++ b/sfntly/data/font_data.cc @@ -58,7 +58,7 @@ FontData::FontData(FontData* data, int32_t offset, int32_t length) { FontData::FontData(FontData* data, int32_t offset) { Init(data->array_); - Bound(offset); + Bound(data->bound_offset_ + offset); } FontData::~FontData() {} diff --git a/sfntly/data/font_data.h b/sfntly/data/font_data.h index ab5cf54..6ac4d5d 100644 --- a/sfntly/data/font_data.h +++ b/sfntly/data/font_data.h @@ -48,13 +48,14 @@ struct DataSize { class FontData : virtual public RefCount { public: - // Get the maximum size of the FontData. This is the maximum number of bytes + // 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 size of this array + // @return the maximum size of this font data virtual int32_t Size() const; - // Sets limits on the size of the FontData. The font data is + // 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 @@ -69,19 +70,19 @@ class FontData : virtual public RefCount { virtual bool Bound(int32_t offset); // Makes a slice of this FontData. The returned slice will share the data with - // the original FontData. + // 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. + // 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; - // Get the length of the data. + // Gets the length of the data. virtual int32_t Length() const; protected: @@ -102,7 +103,17 @@ class FontData : virtual public RefCount { 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); // TODO(arthurhsu): style guide violation: refactor this protected member diff --git a/sfntly/data/font_input_stream.cc b/sfntly/data/font_input_stream.cc index a1fbe44..dcf8be3 100644 --- a/sfntly/data/font_input_stream.cc +++ b/sfntly/data/font_input_stream.cc @@ -25,7 +25,7 @@ FontInputStream::FontInputStream(InputStream* is) } FontInputStream::FontInputStream(InputStream* is, size_t length) - : stream_(is), position_(0), length_(length), bounded_(false) { + : stream_(is), position_(0), length_(length), bounded_(true) { } FontInputStream::~FontInputStream() { diff --git a/sfntly/data/font_input_stream.h b/sfntly/data/font_input_stream.h index 7404825..5d9959d 100644 --- a/sfntly/data/font_input_stream.h +++ b/sfntly/data/font_input_stream.h @@ -22,6 +22,25 @@ 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 @@ -29,10 +48,18 @@ namespace sfntly { // 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); @@ -43,6 +70,8 @@ class FontInputStream : public InputStream { 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(); diff --git a/sfntly/data/font_output_stream.cc b/sfntly/data/font_output_stream.cc index a88a29e..3422a22 100644 --- a/sfntly/data/font_output_stream.cc +++ b/sfntly/data/font_output_stream.cc @@ -43,11 +43,35 @@ void FontOutputStream::Write(ByteVector* b) { } } -void FontOutputStream::Write(ByteVector* b, int32_t offset, int32_t length) { - if (stream_ && b) { - stream_->Write(b, offset, length); - position_ += length; +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) { diff --git a/sfntly/data/font_output_stream.h b/sfntly/data/font_output_stream.h index 6938b66..f420af4 100644 --- a/sfntly/data/font_output_stream.h +++ b/sfntly/data/font_output_stream.h @@ -22,11 +22,27 @@ namespace sfntly { -// 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). +// 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); @@ -36,7 +52,8 @@ class FontOutputStream : public OutputStream { virtual void Write(byte_t b); virtual void Write(ByteVector* b); - virtual void Write(ByteVector* b, int32_t offset, int32_t len); + 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); @@ -46,10 +63,13 @@ class FontOutputStream : public OutputStream { 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_; }; diff --git a/sfntly/data/growable_memory_byte_array.cc b/sfntly/data/growable_memory_byte_array.cc index 9e1a043..c335614 100644 --- a/sfntly/data/growable_memory_byte_array.cc +++ b/sfntly/data/growable_memory_byte_array.cc @@ -17,6 +17,7 @@ #include "sfntly/data/growable_memory_byte_array.h" #include +#include #include @@ -24,28 +25,37 @@ 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() {} -bool GrowableMemoryByteArray::InternalPut(int32_t index, byte_t b) { - if ((size_t)index >= b_.capacity()) { - b_.resize((size_t)(index + 1) << 2); // Grow exponentially. +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; - return true; } int32_t GrowableMemoryByteArray::InternalPut(int32_t index, - ByteVector* b, + byte_t* b, int32_t offset, int32_t length) { - if ((size_t)index + length >= b_.capacity()) { - b_.resize((size_t)(index + length + 1) << 2); + 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->begin() + offset, - b->begin() + (offset + length), - b_.begin() + index); + std::copy(b + offset, b + offset + length, b_.begin() + index); return length; } @@ -54,12 +64,10 @@ byte_t GrowableMemoryByteArray::InternalGet(int32_t index) { } int32_t GrowableMemoryByteArray::InternalGet(int32_t index, - ByteVector* b, + byte_t* b, int32_t offset, int32_t length) { - std::copy(b_.begin() + index, - b_.begin() + (index + length), - b->begin() + offset); + memcpy(b + offset, &(b_[0]) + index, length); return length; } diff --git a/sfntly/data/growable_memory_byte_array.h b/sfntly/data/growable_memory_byte_array.h index dc59f62..0e35de6 100644 --- a/sfntly/data/growable_memory_byte_array.h +++ b/sfntly/data/growable_memory_byte_array.h @@ -21,23 +21,37 @@ 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() +// 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 bool InternalPut(int32_t index, byte_t b); + virtual void InternalPut(int32_t index, byte_t b); virtual int32_t InternalPut(int32_t index, - ByteVector* b, + byte_t* b, int32_t offset, int32_t length); virtual byte_t InternalGet(int32_t index); virtual int32_t InternalGet(int32_t index, - ByteVector* b, + byte_t* b, int32_t offset, int32_t length); virtual void Close(); diff --git a/sfntly/data/memory_byte_array.cc b/sfntly/data/memory_byte_array.cc index 0138b21..d6c9c48 100644 --- a/sfntly/data/memory_byte_array.cc +++ b/sfntly/data/memory_byte_array.cc @@ -20,25 +20,27 @@ namespace sfntly { -// Note: this constructor can fail under low-memory situation. MemoryByteArray::MemoryByteArray(int32_t length) : ByteArray(0, length), b_(NULL), allocated_(true) { } -MemoryByteArray::MemoryByteArray(byte_t* b, int32_t buffer_length) - : ByteArray(buffer_length, buffer_length), b_(b), allocated_(false) { -} - -MemoryByteArray::MemoryByteArray(byte_t* b, - int32_t buffer_length, - int32_t filled_length) - : ByteArray(filled_length, buffer_length), b_(b), allocated_(false) { +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()]; @@ -46,18 +48,18 @@ void MemoryByteArray::Init() { } } -bool MemoryByteArray::InternalPut(int32_t index, byte_t b) { +void MemoryByteArray::InternalPut(int32_t index, byte_t b) { Init(); b_[index] = b; - return true; } int32_t MemoryByteArray::InternalPut(int32_t index, - ByteVector* b, + byte_t* b, int32_t offset, int32_t length) { + assert(b); Init(); - memcpy(b_ + index, &((*b)[offset]), length); + memcpy(b_ + index, b + offset, length); return length; } @@ -67,11 +69,12 @@ byte_t MemoryByteArray::InternalGet(int32_t index) { } int32_t MemoryByteArray::InternalGet(int32_t index, - ByteVector* b, + byte_t* b, int32_t offset, int32_t length) { + assert(b); Init(); - memcpy(&((*b)[offset]), b_ + index, length); + memcpy(b + offset, b_ + index, length); return length; } diff --git a/sfntly/data/memory_byte_array.h b/sfntly/data/memory_byte_array.h index 171dcc7..9de5230 100644 --- a/sfntly/data/memory_byte_array.h +++ b/sfntly/data/memory_byte_array.h @@ -23,20 +23,47 @@ 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); - MemoryByteArray(byte_t* b, int32_t buffer_length); - MemoryByteArray(byte_t* b, int32_t buffer_length, int32_t filled_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 bool InternalPut(int32_t index, byte_t b); + virtual void InternalPut(int32_t index, byte_t b); virtual int32_t InternalPut(int32_t index, - ByteVector* b, + byte_t* b, int32_t offset, int32_t length); virtual byte_t InternalGet(int32_t index); virtual int32_t InternalGet(int32_t index, - ByteVector* b, + byte_t* b, int32_t offset, int32_t length); virtual void Close(); diff --git a/sfntly/data/readable_font_data.cc b/sfntly/data/readable_font_data.cc index 904e7db..8f43575 100644 --- a/sfntly/data/readable_font_data.cc +++ b/sfntly/data/readable_font_data.cc @@ -14,6 +14,7 @@ * limitations under the License. */ +#include "sfntly/data/memory_byte_array.h" #include "sfntly/data/readable_font_data.h" #include "sfntly/data/writable_font_data.h" #include "sfntly/port/exception_type.h" @@ -28,6 +29,18 @@ ReadableFontData::ReadableFontData(ByteArray* array) 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() { // TODO(arthurhsu): IMPLEMENT: atomicity if (!checksum_set_) { @@ -42,15 +55,29 @@ void ReadableFontData::SetCheckSumRanges(const IntegerList& ranges) { } int32_t ReadableFontData::ReadUByte(int32_t index) { - return 0xff & array_->Get(BoundOffset(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) { - return (array_->Get(BoundOffset(index)) << 24) >> 24; + 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, - ByteVector* b, + byte_t* b, int32_t offset, int32_t length) { return array_->Get(BoundOffset(index), b, offset, BoundLength(index, length)); @@ -88,7 +115,7 @@ int32_t ReadableFontData::ReadULongAsInt(int32_t index) { throw ArithmeticException("Long value too large to fit into an integer."); } #endif - return ((int32_t)ulong) & ~0x80000000; + return static_cast(ulong); } int32_t ReadableFontData::ReadLong(int32_t index) { @@ -164,17 +191,6 @@ ReadableFontData::ReadableFontData(ReadableFontData* data, checksum_(0) { } -/* OpenType checksum -ULONG -CalcTableChecksum(ULONG *Table, ULONG Length) -{ -ULONG Sum = 0L; -ULONG *Endptr = Table+((Length+3) & ~3) / sizeof(ULONG); -while (Table < EndPtr) - Sum += *Table++; -return Sum; -} -*/ void ReadableFontData::ComputeChecksum() { // TODO(arthurhsu): IMPLEMENT: synchronization/atomicity int64_t sum = 0; diff --git a/sfntly/data/readable_font_data.h b/sfntly/data/readable_font_data.h index b1ca846..e7b3170 100644 --- a/sfntly/data/readable_font_data.h +++ b/sfntly/data/readable_font_data.h @@ -24,13 +24,36 @@ 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(); - // Get a computed checksum for the data. This checksum uses the OpenType spec + 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 @@ -45,32 +68,120 @@ class ReadableFontData : public FontData, // @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); - virtual int32_t ReadBytes(int32_t index, ByteVector* b, int32_t offset, + + // 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 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); - // TODO(arthurhsu): IMPLEMENT + // TODO(dfilimon): Implementation of following in review, need to merge. /* - virtual int32_t ReadFUnit(int32_t index); - virtual int64_t ReadF2Dot14(int32_t index); - virtual int64_t ReadLongDateTime(int32_t index); virtual int32_t SearchUShort(int32_t start, int32_t length, int32_t key); virtual int32_t SearchUShort(int32_t start_index, int32_t start_offset, int32_t count_index, int32_t count_offset, @@ -85,14 +196,18 @@ class ReadableFontData : public 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. @@ -104,10 +219,24 @@ class ReadableFontData : public FontData, // 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); bool checksum_set_; // TODO(arthurhsu): IMPLEMENT: must be set atomically. diff --git a/sfntly/data/writable_font_data.cc b/sfntly/data/writable_font_data.cc index 5f694be..c690956 100644 --- a/sfntly/data/writable_font_data.cc +++ b/sfntly/data/writable_font_data.cc @@ -40,7 +40,9 @@ WritableFontData* WritableFontData::CreateWritableFontData(int32_t length) { return wfd.Detach(); } -// static +// 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(); @@ -54,18 +56,19 @@ int32_t WritableFontData::WriteByte(int32_t index, byte_t b) { return 1; } -int32_t WritableFontData::WriteBytes(int32_t offset, - ByteVector* b, - int32_t index, +int32_t WritableFontData::WriteBytes(int32_t index, + byte_t* b, + int32_t offset, int32_t length) { - return array_->Put(BoundOffset(offset), + return array_->Put(BoundOffset(index), b, - index, - BoundLength(offset, length)); + offset, + BoundLength(index, length)); } int32_t WritableFontData::WriteBytes(int32_t index, ByteVector* b) { - return WriteBytes(index, b, 0, b->size()); + assert(b); + return WriteBytes(index, &((*b)[0]), 0, b->size()); } int32_t WritableFontData::WriteChar(int32_t index, byte_t c) { @@ -115,8 +118,8 @@ int32_t WritableFontData::WriteLong(int32_t index, int64_t l) { return WriteULong(index, l); } -int32_t WritableFontData::WriteFixed(int32_t index, int32_t l) { - return WriteLong(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) { diff --git a/sfntly/data/writable_font_data.h b/sfntly/data/writable_font_data.h index ceefb30..f674ae1 100644 --- a/sfntly/data/writable_font_data.h +++ b/sfntly/data/writable_font_data.h @@ -21,6 +21,8 @@ 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); @@ -30,7 +32,6 @@ class WritableFontData : public ReadableFontData { // 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 @@ -39,29 +40,114 @@ class WritableFontData : public ReadableFontData { // 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); - virtual int32_t WriteBytes(int32_t offset, - ByteVector* b, - int32_t index, + + // 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 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); - virtual int32_t WriteFixed(int32_t index, int32_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 @@ -78,7 +164,15 @@ class WritableFontData : public ReadableFontData { 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; diff --git a/sfntly/glyph_table.cc b/sfntly/glyph_table.cc index 99e7c06..79c10dd 100644 --- a/sfntly/glyph_table.cc +++ b/sfntly/glyph_table.cc @@ -593,7 +593,7 @@ void GlyphTable::CompositeGlyph::Transformation(int32_t contour, } int32_t tsize = TransformationSize(contour); transformation->resize(tsize); - data_->ReadBytes(index, transformation, 0, tsize); + data_->ReadBytes(index, &((*transformation)[0]), 0, tsize); } int32_t GlyphTable::CompositeGlyph::InstructionSize() { diff --git a/sfntly/name_table.cc b/sfntly/name_table.cc index d65f251..649baed 100644 --- a/sfntly/name_table.cc +++ b/sfntly/name_table.cc @@ -477,7 +477,7 @@ void NameTable::NameAsBytes(int32_t index, ByteVector* b) { int32_t length = NameLength(index); b->clear(); b->resize(length); - data_->ReadBytes(NameOffset(index), b, 0, length); + data_->ReadBytes(NameOffset(index), &((*b)[0]), 0, length); } void NameTable::NameAsBytes(int32_t platform_id, diff --git a/sfntly/os2_table.cc b/sfntly/os2_table.cc index 5b6181d..24ef4e9 100644 --- a/sfntly/os2_table.cc +++ b/sfntly/os2_table.cc @@ -167,7 +167,7 @@ int32_t OS2Table::SFamilyClass() { void OS2Table::Panose(ByteVector* value) { value->clear(); value->resize(10); - data_->ReadBytes(Offset::kPanose, value, 0, 10); + data_->ReadBytes(Offset::kPanose, &((*value)[0]), 0, 10); } int64_t OS2Table::UlUnicodeRange1() { @@ -189,7 +189,7 @@ int64_t OS2Table::UlUnicodeRange4() { void OS2Table::AchVendId(ByteVector* b) { b->clear(); b->resize(4); - data_->ReadBytes(Offset::kAchVendId, b, 0, 4); + data_->ReadBytes(Offset::kAchVendId, &((*b)[0]), 0, 4); } int32_t OS2Table::FsSelection() { diff --git a/sfntly/port/exception_type.h b/sfntly/port/exception_type.h index 2ba199a..ddeb95b 100644 --- a/sfntly/port/exception_type.h +++ b/sfntly/port/exception_type.h @@ -23,18 +23,23 @@ #include #include +#include namespace sfntly { class Exception : public std::exception { public: - explicit Exception(const char* message) throw() { + 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 (...) {} } - virtual ~Exception() throw() {} - virtual const char* what() const throw() { return what_.c_str(); } private: std::string what_; @@ -45,6 +50,15 @@ class IndexOutOfBoundException : public Exception { 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() {} }; diff --git a/sfntly/port/memory_output_stream.cc b/sfntly/port/memory_output_stream.cc index 5ddeec2..f2ff2e3 100644 --- a/sfntly/port/memory_output_stream.cc +++ b/sfntly/port/memory_output_stream.cc @@ -31,9 +31,27 @@ void MemoryOutputStream::Write(ByteVector* buffer) { void MemoryOutputStream::Write(ByteVector* buffer, int32_t offset, int32_t length) { - store_.insert(store_.end(), - buffer->begin() + offset, - buffer->begin() + offset + 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) { @@ -41,6 +59,9 @@ void MemoryOutputStream::Write(byte_t b) { } byte_t* MemoryOutputStream::Get() { + if (store_.empty()) { + return NULL; + } return &(store_[0]); } diff --git a/sfntly/port/memory_output_stream.h b/sfntly/port/memory_output_stream.h index a0befea..8983ab0 100644 --- a/sfntly/port/memory_output_stream.h +++ b/sfntly/port/memory_output_stream.h @@ -36,6 +36,7 @@ class MemoryOutputStream : public OutputStream { 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(); diff --git a/sfntly/port/output_stream.h b/sfntly/port/output_stream.h index c5d71cf..d813333 100644 --- a/sfntly/port/output_stream.h +++ b/sfntly/port/output_stream.h @@ -30,8 +30,15 @@ class OutputStream { virtual void Close() = 0; virtual void Flush() = 0; virtual void Write(ByteVector* buffer) = 0; - virtual void Write(ByteVector* buffer, int32_t offset, int32_t length) = 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 diff --git a/sfntly/tag.h b/sfntly/tag.h index d802351..9a548f6 100644 --- a/sfntly/tag.h +++ b/sfntly/tag.h @@ -83,11 +83,8 @@ struct Tag { }; // Create integer tag value for human readable tag name. -inline int32_t GenerateTag(char a, char b, char c, char d) { - return (((int32_t)(a) << 24) | - ((int32_t)(b) << 16) | - ((int32_t)(c) << 8) | - (int32_t)(d)); +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. diff --git a/test/byte_array_test.cc b/test/byte_array_test.cc index 74b5290..40a6489 100644 --- a/test/byte_array_test.cc +++ b/test/byte_array_test.cc @@ -51,7 +51,7 @@ void ReadByteArrayWithSlidingWindow(ByteArray* ba, int window_size, while (index < ba->Length()) { actual_window_size = std::min(actual_window_size, b->size() - index); - int32_t bytes_read = ba->Get(index, b, index, actual_window_size); + int32_t bytes_read = ba->Get(index, &((*b)[0]), index, actual_window_size); index += bytes_read; } } diff --git a/test/font_data_test.cc b/test/font_data_test.cc index 5a80fb3..4de6fff 100644 --- a/test/font_data_test.cc +++ b/test/font_data_test.cc @@ -48,7 +48,7 @@ void ReadFontDataWithBuffer(ReadableFontData* rfd, int32_t index = 0; while (index < rfd->Length()) { - int32_t bytes_read = rfd->ReadBytes(index, &buffer, 0, buffer.size()); + int32_t bytes_read = rfd->ReadBytes(index, &(buffer[0]), 0, buffer.size()); EXPECT_GE(bytes_read, 0); std::copy(buffer.begin(), buffer.begin() + bytes_read, b->begin() + index); index += bytes_read; @@ -62,7 +62,8 @@ void ReadFontDataWithSlidingWindow(ReadableFontData* rfd, int32_t window_size, while (index < rfd->Length()) { int32_t actual_window_size = std::min(window_size, b->size() - index); - int32_t bytes_read = rfd->ReadBytes(index, b, index, actual_window_size); + int32_t bytes_read = + rfd->ReadBytes(index, &((*b)[0]), index, actual_window_size); EXPECT_GE(bytes_read, 0); index += bytes_read; } @@ -81,8 +82,8 @@ void WriteFontDataWithBuffer(ReadableFontData* rfd, ByteVector buffer(buffer_size); int32_t index = 0; while (index < rfd->Length()) { - int32_t bytesRead = rfd->ReadBytes(index, &buffer, 0, buffer.size()); - wfd->WriteBytes(index, &buffer, 0, buffer.size()); + int32_t bytesRead = rfd->ReadBytes(index, &(buffer[0]), 0, buffer.size()); + wfd->WriteBytes(index, &(buffer[0]), 0, buffer.size()); index += bytesRead; } } @@ -94,8 +95,8 @@ void WriteFontDataWithSlidingWindow(ReadableFontData* rfd, int32_t index = 0; while (index < rfd->Length()) { int32_t sliding_size = std::min(window_size, b.size() - index); - int32_t bytes_read = rfd->ReadBytes(index, &b, index, sliding_size); - wfd->WriteBytes(index, &b, index, sliding_size); + int32_t bytes_read = rfd->ReadBytes(index, &(b[0]), index, sliding_size); + wfd->WriteBytes(index, &(b[0]), index, sliding_size); index += bytes_read; } } diff --git a/test/font_parsing_test.cc b/test/font_parsing_test.cc index ee794d1..3dcbda2 100644 --- a/test/font_parsing_test.cc +++ b/test/font_parsing_test.cc @@ -65,7 +65,7 @@ bool TestFontParsing() { wfd.Attach(gdef_builder->Data()); ByteVector b; b.resize(TTF_LENGTH[SAMPLE_TTF_GDEF]); - wfd->ReadBytes(0, &b, 0, TTF_LENGTH[SAMPLE_TTF_GDEF]); + wfd->ReadBytes(0, &(b[0]), 0, TTF_LENGTH[SAMPLE_TTF_GDEF]); EXPECT_EQ(memcmp(&(b[0]), TTF_GDEF_DATA, TTF_LENGTH[SAMPLE_TTF_GDEF]), 0); // Header table @@ -91,8 +91,8 @@ bool TestFontParsing() { wfd1.Attach(builder1->Data()); WritableFontDataPtr wfd2; wfd2.Attach(builder2->Data()); - wfd1->ReadBytes(0, &b1, 0, TTF_LENGTH[i]); - wfd2->ReadBytes(0, &b2, 0, TTF_LENGTH[i]); + wfd1->ReadBytes(0, &(b1[0]), 0, TTF_LENGTH[i]); + wfd2->ReadBytes(0, &(b2[0]), 0, TTF_LENGTH[i]); EXPECT_EQ(memcmp(&(b1[0]), &(b2[0]), TTF_LENGTH[i]), 0); } -- cgit v1.2.3 From 67ba2eb32c6a62282a93926c983f08bf9248cd58 Mon Sep 17 00:00:00 2001 From: "dfilimon@google.com" Date: Tue, 23 Aug 2011 00:27:00 +0000 Subject: Fixed bug where all glyphs would be set to composite. git-svn-id: http://sfntly.googlecode.com/svn/trunk/cpp/src@56 672e30a5-4c29-85ac-ac6d-611c735e0a51 --- sfntly/glyph_table.cc | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/sfntly/glyph_table.cc b/sfntly/glyph_table.cc index 79c10dd..ac85ab2 100644 --- a/sfntly/glyph_table.cc +++ b/sfntly/glyph_table.cc @@ -209,8 +209,9 @@ CALLER_ATTACH GlyphTable::Glyph* sliced_data.Attach(down_cast(data->Slice(offset, length))); if (type == GlyphType::kSimple) { glyph = new SimpleGlyph(sliced_data); + } else { + glyph = new CompositeGlyph(sliced_data); } - glyph = new CompositeGlyph(sliced_data); return glyph.Detach(); } -- cgit v1.2.3 From 760e6005f25f8d45d413d286ab5a38263ece63ad Mon Sep 17 00:00:00 2001 From: "dfilimon@google.com" Date: Tue, 23 Aug 2011 00:31:41 +0000 Subject: Added SearchUShort and SearchULong. git-svn-id: http://sfntly.googlecode.com/svn/trunk/cpp/src@57 672e30a5-4c29-85ac-ac6d-611c735e0a51 --- sfntly/data/readable_font_data.cc | 68 +++++++++++++++++++++++ sfntly/data/readable_font_data.h | 56 ++++++++++++++++--- test/font_data_test.cc | 113 +++++++++++++++++++++++++++++++++++++- 3 files changed, 228 insertions(+), 9 deletions(-) diff --git a/sfntly/data/readable_font_data.cc b/sfntly/data/readable_font_data.cc index 8f43575..6ceb38c 100644 --- a/sfntly/data/readable_font_data.cc +++ b/sfntly/data/readable_font_data.cc @@ -16,6 +16,9 @@ #include "sfntly/data/memory_byte_array.h" #include "sfntly/data/readable_font_data.h" + +#include + #include "sfntly/data/writable_font_data.h" #include "sfntly/port/exception_type.h" @@ -156,6 +159,71 @@ 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::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()) { diff --git a/sfntly/data/readable_font_data.h b/sfntly/data/readable_font_data.h index e7b3170..48b3e77 100644 --- a/sfntly/data/readable_font_data.h +++ b/sfntly/data/readable_font_data.h @@ -180,15 +180,55 @@ class ReadableFontData : public FontData, // Make gcc -Woverloaded-virtual happy. virtual int32_t CopyTo(ByteArray* ba); - // TODO(dfilimon): Implementation of following in review, need to merge. + // 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 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 SearchUShort(int32_t start, int32_t length, int32_t key); - virtual int32_t SearchUShort(int32_t start_index, int32_t start_offset, - int32_t count_index, int32_t count_offset, - int32_t length, int32_t key); - virtual 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); + 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 diff --git a/test/font_data_test.cc b/test/font_data_test.cc index 4de6fff..ecf9a62 100644 --- a/test/font_data_test.cc +++ b/test/font_data_test.cc @@ -25,7 +25,114 @@ namespace sfntly { const int32_t BYTE_ARRAY_SIZES[] = - {1, 7, 127, 128, 129, 255, 256, 257, 666, 1023, 0x10000}; + {1, 7, 127, 128, 129, 255, 256, 257, 666, 1023, 0x10000}; + +// array data for searching +const int32_t LOWER_BYTE_ARRAY_FOR_SEARCHING[] = {2, 4, 7, 13, 127}; +const int32_t UPPER_BYTE_ARRAY_FOR_SEARCHING[] = {2, 5, 12, 16, 256}; +const int32_t kLowerByteArrayForSearchingLength = 5; +const int32_t kUpperByteArrayForSearchingLength = 5; + +// search test result pairs - number to search for; index found at +const int32_t SEARCH_TEST_PAIRS[][2] = { + {0, -1}, {1, -1}, {2, 0}, {3, -1}, {4, 1}, {5, 1}, {6, -1}, {12, 2}, + {13, 3}, {17, -1}, {126, -1}, {127, 4}, {256, 4}, {257, -1}, {0x1000, -1} +}; +const int32_t kSearchTestPairsLength = 15; + +// offset and start index data for searching data +// array data size, lower_start_index, lower_offset, upper_start_index, +// upper_offset +const int32_t SEARCH_TEST_OFFSETS[][5] = { + // lower[], upper[] + { (kLowerByteArrayForSearchingLength + kUpperByteArrayForSearchingLength) + * sizeof(ushort), + 0, + sizeof(ushort), + kLowerByteArrayForSearchingLength * sizeof(ushort), + sizeof(ushort) }, + + // {lower, upper} [] + { (kLowerByteArrayForSearchingLength + kUpperByteArrayForSearchingLength) + * sizeof(ushort), + 0, + 2 * sizeof(ushort), + sizeof(ushort), + 2 * sizeof(ushort) }, + + // upper[], lower[] + { (kLowerByteArrayForSearchingLength + kUpperByteArrayForSearchingLength) + * sizeof(ushort), + kLowerByteArrayForSearchingLength * sizeof(ushort), + sizeof(ushort), + 0, + sizeof(ushort) }, + + // {upper, lower} [] + { (kLowerByteArrayForSearchingLength + kUpperByteArrayForSearchingLength) + * sizeof(ushort), + sizeof(ushort), + 2 * sizeof(ushort), + 0, + 2 * sizeof(ushort) } +}; +const int32_t kSearchTestOffsetLength = 4; + +ReadableFontData* +FillTestFontDataWithShortsForSearching(WritableFontData* wfd, + const int32_t* lower_data, + int32_t lower_start_index, + int32_t lower_offset, + const int32_t* upper_data, + int32_t upper_start_index, + int32_t upper_offset) { + // lower data + int offset = lower_start_index; + for (int32_t i = 0; i < kLowerByteArrayForSearchingLength; ++i) { + wfd->WriteUShort(offset, lower_data[i]); + offset += lower_offset; + } + + // upper data + offset = upper_start_index; + for (int32_t i = 0; i < kUpperByteArrayForSearchingLength; ++i) { + wfd->WriteUShort(offset, upper_data[i]); + offset += upper_offset; + } + + return wfd; +} + +bool TestReadableFontDataSearching() { + for (int32_t i = 0; i < kSearchTestOffsetLength; ++i) { + const int32_t* array_setup_offset = SEARCH_TEST_OFFSETS[i]; + WritableFontDataPtr wfd; + wfd.Attach(WritableFontData::CreateWritableFontData(array_setup_offset[0])); + FillTestFontDataWithShortsForSearching(wfd, + LOWER_BYTE_ARRAY_FOR_SEARCHING, + array_setup_offset[1], + array_setup_offset[2], + UPPER_BYTE_ARRAY_FOR_SEARCHING, + array_setup_offset[3], + array_setup_offset[4]); + for (int32_t j = 0; j < kSearchTestPairsLength; ++j) { + const int32_t* test_case = SEARCH_TEST_PAIRS[j]; + int32_t found = wfd->SearchUShort(array_setup_offset[1], + array_setup_offset[2], + array_setup_offset[3], + array_setup_offset[4], + kLowerByteArrayForSearchingLength, + test_case[0]); +#if defined (SFNTLY_DEBUG_FONTDATA) + fprintf(stderr, "Searching for %d; Got %d; Expected %d; " + "[test %d][offset %d]\n", + test_case[0], found, test_case[1], j, i); +#endif + EXPECT_EQ(test_case[1], found); + } + } + return true; +} void FillTestByteArray(ByteArray* ba, int32_t size) { for (int32_t i = 0; i < size; ++i) { @@ -220,6 +327,10 @@ bool TestWritableFontData() { } // namespace sfntly +TEST(FontData, ReadableFontDataSearching) { + ASSERT_TRUE(sfntly::TestReadableFontDataSearching()); +} + TEST(FontData, All) { ASSERT_TRUE(sfntly::TestReadableFontData()); ASSERT_TRUE(sfntly::TestWritableFontData()); -- cgit v1.2.3 From 5af34fd773f8cfee82321393504f558ddf67c628 Mon Sep 17 00:00:00 2001 From: "arthurhsu@google.com" Date: Tue, 23 Aug 2011 00:48:46 +0000 Subject: Reorg folder structure to aligned with latest Java version. Change header guards. Updated font_data_test.cc so that VC compilation is not broken. Updated CMakeLists.txt so that files are grouped in folders in VC. git-svn-id: http://sfntly.googlecode.com/svn/trunk/cpp/src@58 672e30a5-4c29-85ac-ac6d-611c735e0a51 --- sample/subsetter/subset_util.cc | 8 +- sample/subsetter/subset_util.h | 6 +- sfntly/cmap_table.cc | 511 ---------------- sfntly/cmap_table.h | 447 -------------- sfntly/data/byte_array.h | 6 +- sfntly/data/font_data.h | 6 +- sfntly/data/font_input_stream.h | 6 +- sfntly/data/font_output_stream.h | 6 +- sfntly/data/growable_memory_byte_array.h | 6 +- sfntly/data/memory_byte_array.h | 6 +- sfntly/data/readable_font_data.h | 6 +- sfntly/data/writable_font_data.h | 6 +- sfntly/font.cc | 10 +- sfntly/font.h | 8 +- sfntly/font_data_table.cc | 176 ------ sfntly/font_data_table.h | 117 ---- sfntly/font_data_table_builder_container.h | 6 +- sfntly/font_factory.h | 6 +- sfntly/font_header_table.cc | 259 --------- sfntly/font_header_table.h | 167 ------ sfntly/glyph_table.cc | 667 --------------------- sfntly/glyph_table.h | 330 ----------- sfntly/horizontal_header_table.cc | 215 ------- sfntly/horizontal_header_table.h | 110 ---- sfntly/horizontal_metrics_table.cc | 151 ----- sfntly/horizontal_metrics_table.h | 89 --- sfntly/loca_table.cc | 250 -------- sfntly/loca_table.h | 146 ----- sfntly/math/fixed1616.h | 6 +- sfntly/math/font_math.h | 6 +- sfntly/maximum_profile_table.cc | 224 ------- sfntly/maximum_profile_table.h | 115 ---- sfntly/name_table.cc | 722 ----------------------- sfntly/name_table.h | 737 ------------------------ sfntly/os2_table.cc | 277 --------- sfntly/os2_table.h | 407 ------------- sfntly/port/atomic.h | 6 +- sfntly/port/config.h | 10 +- sfntly/port/endian.h | 6 +- sfntly/port/exception_type.h | 6 +- sfntly/port/file_input_stream.h | 6 +- sfntly/port/input_stream.h | 6 +- sfntly/port/memory_output_stream.h | 6 +- sfntly/port/output_stream.h | 6 +- sfntly/port/refcount.h | 6 +- sfntly/port/type.h | 6 +- sfntly/subtable.cc | 44 -- sfntly/subtable.h | 49 -- sfntly/table.cc | 279 --------- sfntly/table.h | 183 ------ sfntly/table/core/cmap_table.cc | 511 ++++++++++++++++ sfntly/table/core/cmap_table.h | 447 ++++++++++++++ sfntly/table/core/font_header_table.cc | 259 +++++++++ sfntly/table/core/font_header_table.h | 167 ++++++ sfntly/table/core/horizontal_header_table.cc | 211 +++++++ sfntly/table/core/horizontal_header_table.h | 110 ++++ sfntly/table/core/horizontal_metrics_table.cc | 151 +++++ sfntly/table/core/horizontal_metrics_table.h | 89 +++ sfntly/table/core/maximum_profile_table.cc | 224 +++++++ sfntly/table/core/maximum_profile_table.h | 115 ++++ sfntly/table/core/name_table.cc | 722 +++++++++++++++++++++++ sfntly/table/core/name_table.h | 737 ++++++++++++++++++++++++ sfntly/table/core/os2_table.cc | 277 +++++++++ sfntly/table/core/os2_table.h | 407 +++++++++++++ sfntly/table/font_data_table.cc | 176 ++++++ sfntly/table/font_data_table.h | 117 ++++ sfntly/table/subtable.cc | 44 ++ sfntly/table/subtable.h | 49 ++ sfntly/table/table.cc | 279 +++++++++ sfntly/table/table.h | 183 ++++++ sfntly/table/truetype/glyph_table.cc | 667 +++++++++++++++++++++ sfntly/table/truetype/glyph_table.h | 330 +++++++++++ sfntly/table/truetype/loca_table.cc | 250 ++++++++ sfntly/table/truetype/loca_table.h | 146 +++++ sfntly/tag.h | 6 +- sfntly/tools/subsetter.cc | 107 ---- sfntly/tools/subsetter/glyph_table_subsetter.cc | 4 +- sfntly/tools/subsetter/glyph_table_subsetter.h | 6 +- sfntly/tools/subsetter/subsetter.cc | 107 ++++ sfntly/tools/subsetter/subsetter.h | 8 +- sfntly/tools/subsetter/table_subsetter.h | 6 +- sfntly/tools/subsetter/table_subsetter_impl.h | 6 +- test/font_data_test.cc | 32 +- test/font_parsing_test.cc | 8 +- test/font_subsetter.h | 6 +- test/name_editing_test.cc | 4 +- test/otf_basic_editing_test.cc | 2 +- test/serialization_test.h | 8 +- test/subsetter_impl.cc | 6 +- test/subsetter_impl.h | 6 +- test/test_data.h | 6 +- test/test_font_utils.h | 6 +- test/test_utils.h | 6 +- test/verify_glyf.cc | 2 +- test/verify_hhea.cc | 2 +- test/verify_hmtx.cc | 2 +- test/verify_loca.cc | 2 +- test/verify_maxp.cc | 2 +- test/verify_name.cc | 2 +- test/verify_os2.cc | 2 +- 100 files changed, 6930 insertions(+), 6932 deletions(-) delete mode 100644 sfntly/cmap_table.cc delete mode 100644 sfntly/cmap_table.h delete mode 100644 sfntly/font_data_table.cc delete mode 100644 sfntly/font_data_table.h delete mode 100644 sfntly/font_header_table.cc delete mode 100644 sfntly/font_header_table.h delete mode 100644 sfntly/glyph_table.cc delete mode 100644 sfntly/glyph_table.h delete mode 100644 sfntly/horizontal_header_table.cc delete mode 100644 sfntly/horizontal_header_table.h delete mode 100644 sfntly/horizontal_metrics_table.cc delete mode 100644 sfntly/horizontal_metrics_table.h delete mode 100644 sfntly/loca_table.cc delete mode 100644 sfntly/loca_table.h delete mode 100644 sfntly/maximum_profile_table.cc delete mode 100644 sfntly/maximum_profile_table.h delete mode 100644 sfntly/name_table.cc delete mode 100644 sfntly/name_table.h delete mode 100644 sfntly/os2_table.cc delete mode 100644 sfntly/os2_table.h delete mode 100644 sfntly/subtable.cc delete mode 100644 sfntly/subtable.h delete mode 100644 sfntly/table.cc delete mode 100644 sfntly/table.h create mode 100644 sfntly/table/core/cmap_table.cc create mode 100644 sfntly/table/core/cmap_table.h create mode 100644 sfntly/table/core/font_header_table.cc create mode 100644 sfntly/table/core/font_header_table.h create mode 100644 sfntly/table/core/horizontal_header_table.cc create mode 100644 sfntly/table/core/horizontal_header_table.h create mode 100644 sfntly/table/core/horizontal_metrics_table.cc create mode 100644 sfntly/table/core/horizontal_metrics_table.h create mode 100644 sfntly/table/core/maximum_profile_table.cc create mode 100644 sfntly/table/core/maximum_profile_table.h create mode 100644 sfntly/table/core/name_table.cc create mode 100644 sfntly/table/core/name_table.h create mode 100644 sfntly/table/core/os2_table.cc create mode 100644 sfntly/table/core/os2_table.h create mode 100644 sfntly/table/font_data_table.cc create mode 100644 sfntly/table/font_data_table.h create mode 100644 sfntly/table/subtable.cc create mode 100644 sfntly/table/subtable.h create mode 100644 sfntly/table/table.cc create mode 100644 sfntly/table/table.h create mode 100644 sfntly/table/truetype/glyph_table.cc create mode 100644 sfntly/table/truetype/glyph_table.h create mode 100644 sfntly/table/truetype/loca_table.cc create mode 100644 sfntly/table/truetype/loca_table.h delete mode 100644 sfntly/tools/subsetter.cc create mode 100644 sfntly/tools/subsetter/subsetter.cc diff --git a/sample/subsetter/subset_util.cc b/sample/subsetter/subset_util.cc index 9e4e652..26da65f 100644 --- a/sample/subsetter/subset_util.cc +++ b/sample/subsetter/subset_util.cc @@ -17,17 +17,19 @@ // Remove VC++ nag on fopen. #define _CRT_SECURE_NO_WARNINGS +#include "sample/subsetter/subset_util.h" + #include + #include #include -#include "sfntly/port/type.h" #include "sfntly/font.h" -#include "sfntly/tools/subsetter/subsetter.h" -#include "sample/subsetter/subset_util.h" #include "sfntly/data/memory_byte_array.h" #include "sfntly/port/memory_output_stream.h" +#include "sfntly/port/type.h" #include "sfntly/tag.h" +#include "sfntly/tools/subsetter/subsetter.h" namespace sfntly { diff --git a/sample/subsetter/subset_util.h b/sample/subsetter/subset_util.h index 109d63a..5eb4fe4 100644 --- a/sample/subsetter/subset_util.h +++ b/sample/subsetter/subset_util.h @@ -14,8 +14,8 @@ * limitations under the License. */ -#ifndef TYPOGRAPHY_FONT_SFNTLY_SRC_SAMPLE_SUBSETTER_SUBSET_UTIL_H_ -#define TYPOGRAPHY_FONT_SFNTLY_SRC_SAMPLE_SUBSETTER_SUBSET_UTIL_H_ +#ifndef SFNTLY_CPP_SRC_SAMPLE_SUBSETTER_SUBSET_UTIL_H_ +#define SFNTLY_CPP_SRC_SAMPLE_SUBSETTER_SUBSET_UTIL_H_ namespace sfntly { @@ -29,4 +29,4 @@ class SubsetUtil { } // namespace sfntly -#endif // TYPOGRAPHY_FONT_SFNTLY_SRC_SAMPLE_SUBSETTER_SUBSET_UTIL_H_ +#endif // SFNTLY_CPP_SRC_SAMPLE_SUBSETTER_SUBSET_UTIL_H_ diff --git a/sfntly/cmap_table.cc b/sfntly/cmap_table.cc deleted file mode 100644 index 668dc07..0000000 --- a/sfntly/cmap_table.cc +++ /dev/null @@ -1,511 +0,0 @@ -/* - * 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. - */ - -// TODO(arthurhsu): IMPLEMENT: not really used and tested, need cleanup - -#include - -#include "sfntly/cmap_table.h" -#include "sfntly/name_table.h" -#include "sfntly/font.h" -#include "sfntly/port/endian.h" - -namespace sfntly { - -const int32_t CMapTable::NOTDEF = 0; - -/****************************************************************************** - * CMapTable class - ******************************************************************************/ -CMapTable::~CMapTable() {} - -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 CMapId(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)); -} - -CMapTable::CMapTable(Header* header, ReadableFontData* data) - : Table(header, data) { -} - -int32_t CMapTable::OffsetForEncodingRecord(int32_t index) { - return Offset::kEncodingRecordStart + index * Offset::kEncodingRecordSize; -} - -/****************************************************************************** - * CMapTable::CMapId class - ******************************************************************************/ -CMapTable::CMapId::CMapId(int32_t platform_id, int32_t encoding_id) - : platform_id_(platform_id), encoding_id_(encoding_id) { -} - -CMapTable::CMapId::CMapId(const CMapId& obj) - : platform_id_(obj.platform_id_), encoding_id_(obj.encoding_id_) { -} - -bool CMapTable::CMapId::operator==(const CMapTable::CMapId& obj) { - return obj.platform_id_ == platform_id_ && obj.encoding_id_ == encoding_id_; -} - -const CMapTable::CMapId& CMapTable::CMapId::operator=( - const CMapTable::CMapId& obj) { - platform_id_ = obj.platform_id_; - encoding_id_ = obj.encoding_id_; - return *this; -} - -int CMapTable::CMapId::HashCode() const { - return platform_id_ << 8 | encoding_id_; -} - -CMapTable::CMapId WINDOWS_BMP(PlatformId::kWindows, - WindowsEncodingId::kUnicodeUCS2); -CMapTable::CMapId WINDOWS_UCS4(PlatformId::kWindows, - WindowsEncodingId::kUnicodeUCS4); -CMapTable::CMapId MAC_ROMAN(PlatformId::kWindows, MacintoshEncodingId::kRoman); - -/****************************************************************************** - * CMapTable::CMapIdComparator class - ******************************************************************************/ - -bool CMapTable::CMapIdComparator::operator()(const CMapId& lhs, - const CMapId& rhs) { - return lhs.HashCode() > rhs.HashCode(); -} - -/****************************************************************************** - * 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( - FontDataTableBuilderContainer* container, - 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 = new CMapFormat0::Builder(container, data, offset, cmap_id); - break; - case CMapFormat::kFormat2: - builder = new CMapFormat0::Builder(container, data, offset, cmap_id); - break; - default: - break; - } - return builder.Detach(); -} - -CMapTable::CMap::Builder::Builder(FontDataTableBuilderContainer* container, - ReadableFontData* data, int32_t format, - const CMapId& cmap_id) - : SubTable::Builder(container, data), - format_(format), - cmap_id_(cmap_id) { -} - -CMapTable::CMap::Builder::Builder(FontDataTableBuilderContainer* container, - WritableFontData* data, int32_t format, - const CMapId& cmap_id) - : SubTable::Builder(container, data), - format_(format), - cmap_id_(cmap_id) { -} - -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() { - return InternalReadData()->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_->ReadByte(character + Offset::kFormat0GlyphIdArray); -} - -CMapTable::CMapFormat0::CMapFormat0(ReadableFontData* data, - const CMapId& cmap_id) - : CMap(data, CMapFormat::kFormat0, cmap_id) { -} - -/****************************************************************************** - * CMapTable::CMapFormat0::Builder - ******************************************************************************/ -CMapTable::CMapFormat0::Builder::Builder( - FontDataTableBuilderContainer* container, - WritableFontData* data, - int32_t offset, - const CMapId& cmap_id) - : CMapTable::CMap::Builder(container, - data ? down_cast( - data->Slice(offset, data->ReadUShort( - offset + Offset::kFormat0Length))) - : reinterpret_cast(NULL), - CMapFormat::kFormat0, cmap_id) { - // TODO(arthurhsu): FIXIT: heavy lifting and leak, need fix. -} - -CMapTable::CMapFormat0::Builder::Builder( - FontDataTableBuilderContainer* container, - ReadableFontData* data, - int32_t offset, - const CMapId& cmap_id) - : CMapTable::CMap::Builder(container, - data ? down_cast( - data->Slice(offset, data->ReadUShort( - offset + Offset::kFormat0Length))) - : reinterpret_cast(NULL), - CMapFormat::kFormat0, cmap_id) { - // TODO(arthurhsu): FIXIT: heavy lifting and leak, need fix. -} - -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::CMapFormat2::Builder - ******************************************************************************/ -CMapTable::CMapFormat2::Builder::Builder( - FontDataTableBuilderContainer* container, - WritableFontData* data, - int32_t offset, - const CMapId& cmap_id) - : CMapTable::CMap::Builder(container, - 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( - FontDataTableBuilderContainer* container, - ReadableFontData* data, - int32_t offset, - const CMapId& cmap_id) - : CMapTable::CMap::Builder(container, - 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::Iterator class - ******************************************************************************/ -CMapTable::CMapIterator::CMapIterator(CMapTable* table, 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; -} - -/****************************************************************************** - * CMapTable::Builder class - ******************************************************************************/ -CMapTable::Builder::Builder(FontDataTableBuilderContainer* font_builder, - Header* header, - WritableFontData* data) - : Table::ArrayElementTableBuilder(font_builder, header, data) { -} - -CMapTable::Builder::Builder(FontDataTableBuilderContainer* font_builder, - Header* header, - ReadableFontData* data) - : Table::ArrayElementTableBuilder(font_builder, header, data) { -} - -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, - cmap_builders_.size()); - - int32_t index_offset = size; - size += cmap_builders_.size() * CMapTable::Offset::kEncodingRecordSize; - for (CMapBuilderMap::iterator it = cmap_builders_.begin(), - e = cmap_builders_.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 (cmap_builders_.empty()) - return false; - - // check each table - for (CMapBuilderMap::iterator it = cmap_builders_.begin(), - e = cmap_builders_.end(); it != e; ++it) { - if (!it->second->SubReadyToSerialize()) - return false; - } - return true; -} - -int32_t CMapTable::Builder::SubDataSizeToSerialize() { - if (cmap_builders_.empty()) - return 0; - - bool variable = false; - int32_t size = CMapTable::Offset::kEncodingRecordStart + - cmap_builders_.size() * CMapTable::Offset::kEncodingRecordSize; - - // calculate size of each table - for (CMapBuilderMap::iterator it = cmap_builders_.begin(), - e = cmap_builders_.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() { - cmap_builders_.clear(); - Table::Builder::set_model_changed(false); -} - -CALLER_ATTACH FontDataTable* - CMapTable::Builder::SubBuildTable(ReadableFontData* data) { - FontDataTablePtr table = new CMapTable(header(), data); - return table.Detach(); -} - -CALLER_ATTACH CMapTable::CMap::Builder* CMapTable::Builder::CMapBuilder( - FontDataTableBuilderContainer* container, ReadableFontData* data, - int32_t index) { - if (index < 0 || index > NumCMaps(data)) - return NULL; - - int32_t record_offset = Offset::kEncodingRecordOffset + index * - Offset::kEncodingRecordSize; - int32_t platform_id = - data->ReadUShort(Offset::kEncodingRecordPlatformId + record_offset); - int32_t encoding_id = - data->ReadUShort(Offset::kEncodingRecordEncodingId + record_offset); - CMapId cmap_id(platform_id, encoding_id); - int32_t offset = - data->ReadULongAsInt(Offset::kEncodingRecordOffset + record_offset); - return CMap::Builder::GetBuilder(container, data, offset, cmap_id); -} - -int32_t CMapTable::Builder::NumCMaps(ReadableFontData* data) { - if (data == NULL) { - return 0; - } - return data->ReadUShort(Offset::kNumTables); -} - -} // namespace sfntly diff --git a/sfntly/cmap_table.h b/sfntly/cmap_table.h deleted file mode 100644 index cdbcad8..0000000 --- a/sfntly/cmap_table.h +++ /dev/null @@ -1,447 +0,0 @@ -/* - * 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. - */ - -// TODO(arthurhsu): IMPLEMENT: not really used and tested, need cleanup -#ifndef TYPOGRAPHY_FONT_SFNTLY_SRC_SFNTLY_CMAP_TABLE_H_ -#define TYPOGRAPHY_FONT_SFNTLY_SRC_SFNTLY_CMAP_TABLE_H_ - -#include -#include - -#include "sfntly/port/refcount.h" -#include "sfntly/table.h" -#include "sfntly/subtable.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 Table, public RefCounted { -public: - // CMapTable::CMapId - class CMapId { - public: - CMapId(int32_t platform_id, int32_t encoding_id); - CMapId(const CMapId& obj); - - int32_t platform_id() { return platform_id_; } - int32_t encoding_id() { return encoding_id_; } - - bool operator==(const CMapId& obj); - const CMapId& operator=(const CMapId& obj); - int HashCode() const; - - friend class CMapIdComparator; - - private: - int32_t platform_id_; - int32_t 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); - }; - - // 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(CMapId cmap_id) = 0; - // Make gcc -Wnon-virtual-dtor happy. - virtual ~CMapFilter() {} - }; - - // 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 implements {@code Iterable} 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(FontDataTableBuilderContainer* container, - ReadableFontData* data, - int32_t offset, - 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(); } - - protected: - Builder(FontDataTableBuilderContainer* container, - ReadableFontData* data, - int32_t format, - const CMapId& cmap_id); - Builder(FontDataTableBuilderContainer* container, - 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_; - - friend class CMapTable::Builder; - }; - - CMap(ReadableFontData* data, int32_t format, const CMapId& cmap_id); - virtual ~CMap(); - 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 CMapBuilderPtr; - typedef std::map CMapBuilderMap; - - // A cmap format 0 sub table - class CMapFormat0 : public CMap, public RefCounted { - public: - // CMapTable::CMapFormat0::Builder - class Builder : public CMap::Builder, - public RefCounted { - public: - Builder(FontDataTableBuilderContainer* container, - ReadableFontData* data, - int32_t offset, - const CMapId& cmap_id); - Builder(FontDataTableBuilderContainer* container, - WritableFontData* data, - int32_t offset, - const CMapId& cmap_id); - virtual ~Builder(); - - protected: - virtual CALLER_ATTACH FontDataTable* - SubBuildTable(ReadableFontData* data); - }; - - virtual ~CMapFormat0(); - virtual int32_t Language(); - virtual int32_t GlyphId(int32_t character); - - 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(FontDataTableBuilderContainer* container, - ReadableFontData* data, - int32_t offset, - const CMapId& cmap_id); - Builder(FontDataTableBuilderContainer* container, - WritableFontData* data, - int32_t offset, - const CMapId& cmap_id); - virtual ~Builder(); - - protected: - virtual CALLER_ATTACH FontDataTable* - SubBuildTable(ReadableFontData* data); - }; - - virtual ~CMapFormat2(); - 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); - - 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); - }; - - // CMapTable::Builder - class Builder : public Table::ArrayElementTableBuilder, - public RefCounted { - public: - // Constructor scope altered to public because C++ does not allow base - // class to instantiate derived class with protected constructors. - Builder(FontDataTableBuilderContainer* font_builder, - Header* header, - WritableFontData* data); - Builder(FontDataTableBuilderContainer* font_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); - - protected: - static CALLER_ATTACH CMap::Builder* - CMapBuilder(FontDataTableBuilderContainer* container, - ReadableFontData* data, - int32_t index); - - private: - static int32_t NumCMaps(ReadableFontData* data); - - int32_t version_; - CMapBuilderMap cmap_builders_; - }; - - virtual ~CMapTable(); - - // 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); - - private: - static const int32_t NOTDEF; - - // 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, - - // 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 - }; - }; - - class CMapIterator { - public: - // If filter is NULL, filter through all tables. - CMapIterator(CMapTable* table, CMapFilter* filter); - bool HasNext(); - CMap* Next(); - - private: - int32_t table_index_; - CMapFilter* filter_; - CMapTable* table_; - }; - - 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. - int32_t OffsetForEncodingRecord(int32_t index); -}; -typedef std::vector CMapIdList; -typedef Ptr CMapTablePtr; - -} // namespace sfntly - -#endif // TYPOGRAPHY_FONT_SFNTLY_SRC_SFNTLY_CMAP_TABLE_H_ diff --git a/sfntly/data/byte_array.h b/sfntly/data/byte_array.h index 3375244..70dc92f 100644 --- a/sfntly/data/byte_array.h +++ b/sfntly/data/byte_array.h @@ -14,8 +14,8 @@ * limitations under the License. */ -#ifndef TYPOGRAPHY_FONT_SFNTLY_SRC_SFNTLY_DATA_BYTE_ARRAY_H_ -#define TYPOGRAPHY_FONT_SFNTLY_SRC_SFNTLY_DATA_BYTE_ARRAY_H_ +#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" @@ -198,4 +198,4 @@ typedef Ptr ByteArrayPtr; } // namespace sfntly -#endif // TYPOGRAPHY_FONT_SFNTLY_SRC_SFNTLY_DATA_BYTE_ARRAY_H_ +#endif // SFNTLY_CPP_SRC_SFNTLY_DATA_BYTE_ARRAY_H_ diff --git a/sfntly/data/font_data.h b/sfntly/data/font_data.h index 6ac4d5d..ec87c72 100644 --- a/sfntly/data/font_data.h +++ b/sfntly/data/font_data.h @@ -14,8 +14,8 @@ * limitations under the License. */ -#ifndef TYPOGRAPHY_FONT_SFNTLY_SRC_SFNTLY_DATA_FONT_DATA_H_ -#define TYPOGRAPHY_FONT_SFNTLY_SRC_SFNTLY_DATA_FONT_DATA_H_ +#ifndef SFNTLY_CPP_SRC_SFNTLY_DATA_FONT_DATA_H_ +#define SFNTLY_CPP_SRC_SFNTLY_DATA_FONT_DATA_H_ #include @@ -127,4 +127,4 @@ typedef Ptr FontDataPtr; } // namespace sfntly -#endif // TYPOGRAPHY_FONT_SFNTLY_SRC_SFNTLY_DATA_FONT_DATA_H_ +#endif // SFNTLY_CPP_SRC_SFNTLY_DATA_FONT_DATA_H_ diff --git a/sfntly/data/font_input_stream.h b/sfntly/data/font_input_stream.h index 5d9959d..9992b07 100644 --- a/sfntly/data/font_input_stream.h +++ b/sfntly/data/font_input_stream.h @@ -14,8 +14,8 @@ * limitations under the License. */ -#ifndef TYPOGRAPHY_FONT_SFNTLY_SRC_SFNTLY_DATA_FONT_INPUT_STREAM_H_ -#define TYPOGRAPHY_FONT_SFNTLY_SRC_SFNTLY_DATA_FONT_INPUT_STREAM_H_ +#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" @@ -94,4 +94,4 @@ class FontInputStream : public InputStream { } // namespace sfntly -#endif // TYPOGRAPHY_FONT_SFNTLY_SRC_SFNTLY_DATA_FONT_INPUT_STREAM_H_ +#endif // SFNTLY_CPP_SRC_SFNTLY_DATA_FONT_INPUT_STREAM_H_ diff --git a/sfntly/data/font_output_stream.h b/sfntly/data/font_output_stream.h index f420af4..fcd48e8 100644 --- a/sfntly/data/font_output_stream.h +++ b/sfntly/data/font_output_stream.h @@ -14,8 +14,8 @@ * limitations under the License. */ -#ifndef TYPOGRAPHY_FONT_SFNTLY_SRC_SFNTLY_DATA_FONT_OUTPUT_STREAM_H_ -#define TYPOGRAPHY_FONT_SFNTLY_SRC_SFNTLY_DATA_FONT_OUTPUT_STREAM_H_ +#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" @@ -76,4 +76,4 @@ class FontOutputStream : public OutputStream { } // namespace sfntly -#endif // TYPOGRAPHY_FONT_SFNTLY_SRC_SFNTLY_DATA_FONT_OUTPUT_STREAM_H_ +#endif // SFNTLY_CPP_SRC_SFNTLY_DATA_FONT_OUTPUT_STREAM_H_ diff --git a/sfntly/data/growable_memory_byte_array.h b/sfntly/data/growable_memory_byte_array.h index 0e35de6..8583a0d 100644 --- a/sfntly/data/growable_memory_byte_array.h +++ b/sfntly/data/growable_memory_byte_array.h @@ -14,8 +14,8 @@ * limitations under the License. */ -#ifndef TYPOGRAPHY_FONT_SFNTLY_SRC_SFNTLY_DATA_GROWABLE_MEMORY_BYTE_ARRAY_H_ -#define TYPOGRAPHY_FONT_SFNTLY_SRC_SFNTLY_DATA_GROWABLE_MEMORY_BYTE_ARRAY_H_ +#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" @@ -63,4 +63,4 @@ class GrowableMemoryByteArray : public ByteArray, } // namespace sfntly -#endif // TYPOGRAPHY_FONT_SFNTLY_SRC_SFNTLY_DATA_GROWABLE_MEMORY_BYTE_ARRAY_H_ +#endif // SFNTLY_CPP_SRC_SFNTLY_DATA_GROWABLE_MEMORY_BYTE_ARRAY_H_ diff --git a/sfntly/data/memory_byte_array.h b/sfntly/data/memory_byte_array.h index 9de5230..838fd1a 100644 --- a/sfntly/data/memory_byte_array.h +++ b/sfntly/data/memory_byte_array.h @@ -14,8 +14,8 @@ * limitations under the License. */ -#ifndef TYPOGRAPHY_FONT_SFNTLY_SRC_SFNTLY_DATA_MEMORY_BYTE_ARRAY_H_ -#define TYPOGRAPHY_FONT_SFNTLY_SRC_SFNTLY_DATA_MEMORY_BYTE_ARRAY_H_ +#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" @@ -78,4 +78,4 @@ class MemoryByteArray : public ByteArray, public RefCounted { } // namespace sfntly -#endif // TYPOGRAPHY_FONT_SFNTLY_SRC_SFNTLY_DATA_MEMORY_BYTE_ARRAY_H_ +#endif // SFNTLY_CPP_SRC_SFNTLY_DATA_MEMORY_BYTE_ARRAY_H_ diff --git a/sfntly/data/readable_font_data.h b/sfntly/data/readable_font_data.h index 48b3e77..34d7179 100644 --- a/sfntly/data/readable_font_data.h +++ b/sfntly/data/readable_font_data.h @@ -14,8 +14,8 @@ * limitations under the License. */ -#ifndef TYPOGRAPHY_FONT_SFNTLY_SRC_SFNTLY_DATA_READABLE_FONT_DATA_H_ -#define TYPOGRAPHY_FONT_SFNTLY_SRC_SFNTLY_DATA_READABLE_FONT_DATA_H_ +#ifndef SFNTLY_CPP_SRC_SFNTLY_DATA_READABLE_FONT_DATA_H_ +#define SFNTLY_CPP_SRC_SFNTLY_DATA_READABLE_FONT_DATA_H_ #include "sfntly/port/refcount.h" #include "sfntly/data/font_data.h" @@ -287,4 +287,4 @@ typedef Ptr ReadableFontDataPtr; } // namespace sfntly -#endif // TYPOGRAPHY_FONT_SFNTLY_SRC_SFNTLY_DATA_READABLE_FONT_DATA_H_ +#endif // SFNTLY_CPP_SRC_SFNTLY_DATA_READABLE_FONT_DATA_H_ diff --git a/sfntly/data/writable_font_data.h b/sfntly/data/writable_font_data.h index f674ae1..7fac998 100644 --- a/sfntly/data/writable_font_data.h +++ b/sfntly/data/writable_font_data.h @@ -14,8 +14,8 @@ * limitations under the License. */ -#ifndef TYPOGRAPHY_FONT_SFNTLY_SRC_SFNTLY_DATA_WRITABLE_FONT_DATA_H_ -#define TYPOGRAPHY_FONT_SFNTLY_SRC_SFNTLY_DATA_WRITABLE_FONT_DATA_H_ +#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" @@ -179,4 +179,4 @@ typedef Ptr WritableFontDataPtr; } // namespace sfntly -#endif // TYPOGRAPHY_FONT_SFNTLY_SRC_SFNTLY_DATA_WRITABLE_FONT_DATA_H_ +#endif // SFNTLY_CPP_SRC_SFNTLY_DATA_WRITABLE_FONT_DATA_H_ diff --git a/sfntly/font.cc b/sfntly/font.cc index 8d264b5..14f1505 100644 --- a/sfntly/font.cc +++ b/sfntly/font.cc @@ -25,12 +25,12 @@ #include "sfntly/font_factory.h" #include "sfntly/math/fixed1616.h" #include "sfntly/math/font_math.h" -#include "sfntly/font_header_table.h" -#include "sfntly/horizontal_header_table.h" -#include "sfntly/horizontal_metrics_table.h" -#include "sfntly/loca_table.h" -#include "sfntly/maximum_profile_table.h" #include "sfntly/port/exception_type.h" +#include "sfntly/table/core/font_header_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 { diff --git a/sfntly/font.h b/sfntly/font.h index 5ce7f17..72b10ac 100644 --- a/sfntly/font.h +++ b/sfntly/font.h @@ -14,19 +14,19 @@ * limitations under the License. */ -#ifndef TYPOGRAPHY_FONT_SFNTLY_SRC_SFNTLY_FONT_H_ -#define TYPOGRAPHY_FONT_SFNTLY_SRC_SFNTLY_FONT_H_ +#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/table.h" #include "sfntly/font_data_table_builder_container.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 { @@ -293,4 +293,4 @@ typedef std::vector FontBuilderArray; } // namespace sfntly -#endif // TYPOGRAPHY_FONT_SFNTLY_SRC_SFNTLY_FONT_H_ +#endif // SFNTLY_CPP_SRC_SFNTLY_FONT_H_ diff --git a/sfntly/font_data_table.cc b/sfntly/font_data_table.cc deleted file mode 100644 index e6d0984..0000000 --- a/sfntly/font_data_table.cc +++ /dev/null @@ -1,176 +0,0 @@ -/* - * 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_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::Length() { - return data_->Length(); -} - -int32_t FontDataTable::Padding() { - return -1; -} - -int32_t FontDataTable::DataLength() { - int32_t paddings = Padding(); - return (paddings == -1) ? Length() : Length() - paddings; -} - -int32_t FontDataTable::Serialize(OutputStream* os) { - return data_->CopyTo(os); -} - -/****************************************************************************** - * FontDataTable::Builder class - ******************************************************************************/ -CALLER_ATTACH WritableFontData* FontDataTable::Builder::Data() { - WritableFontDataPtr new_data; - if (model_changed_) { - if (!SubReadyToSerialize()) { - return NULL; - } - int32_t size = SubDataSizeToSerialize(); - new_data.Attach(container_->GetNewData(size)); - SubSerialize(new_data); - } else { - ReadableFontDataPtr data = InternalReadData(); - new_data.Attach(container_->GetNewData(data != NULL ? data->Length() : 0)); - data->CopyTo(new_data); - } - return new_data.Detach(); -} - -void FontDataTable::Builder::SetData(ReadableFontData* data) { - InternalSetData(data, true); -} - - -CALLER_ATTACH FontDataTable* FontDataTable::Builder::Build() { - ReadableFontDataPtr data = InternalReadData(); - if (model_changed_) { - // Let subclass serialize from model. - if (!SubReadyToSerialize()) { - return NULL; - } - int32_t size = SubDataSizeToSerialize(); - WritableFontDataPtr new_data; - new_data.Attach(container_->GetNewData(size)); - SubSerialize(new_data); - data = new_data; - } - - if (data == NULL) { - return NULL; // Do not build table with NULL data. - } - - FontDataTablePtr table = SubBuildTable(data); - NotifyPostTableBuild(table); - 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(container_->GetNewData(r_data_->Length())); - r_data_->CopyTo(new_data); - InternalSetData(new_data, false); - } - return w_data_.p_; -} - -CALLER_ATTACH WritableFontData* - FontDataTable::Builder::InternalNewData(int32_t size) { - return container_->GetNewData(size); -} - -FontDataTable::Builder::Builder(FontDataTableBuilderContainer* container) { - Init(container); -} - -FontDataTable::Builder::Builder(FontDataTableBuilderContainer* container, - WritableFontData* data) { - Init(container); - w_data_ = data; -} - -FontDataTable::Builder::Builder(FontDataTableBuilderContainer* container, - ReadableFontData* data) { - Init(container); - r_data_ = data; -} - -FontDataTable::Builder::~Builder() { -} - -void FontDataTable::Builder::Init(FontDataTableBuilderContainer* container) { - container_ = container; - model_changed_ = false; - data_changed_ = false; -} - -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/sfntly/font_data_table.h b/sfntly/font_data_table.h deleted file mode 100644 index 207d492..0000000 --- a/sfntly/font_data_table.h +++ /dev/null @@ -1,117 +0,0 @@ -/* - * 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_FONT_DATA_TABLE_H_ -#define TYPOGRAPHY_FONT_SFNTLY_SRC_SFNTLY_FONT_DATA_TABLE_H_ - -#include "sfntly/data/readable_font_data.h" -#include "sfntly/font_data_table_builder_container.h" -#include "sfntly/port/refcount.h" - -namespace sfntly { - -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(); - CALLER_ATTACH WritableFontData* InternalNewData(int32_t size); - - bool data_changed() { return data_changed_; } - bool model_changed() { return 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(FontDataTableBuilderContainer* container); - Builder(FontDataTableBuilderContainer* container, WritableFontData* data); - Builder(FontDataTableBuilderContainer* container, ReadableFontData* data); - virtual ~Builder(); - - void Init(FontDataTableBuilderContainer* container); - - // 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); - - FontDataTableBuilderContainer* container_; // avoid circular ref-counting - WritableFontDataPtr w_data_; - ReadableFontDataPtr r_data_; - bool model_changed_; - 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 and may or may not include any padding. - virtual int32_t Length(); - - // Get the number of bytes of padding used in the table. The padding bytes are - // used to align the table length to a 4 byte boundary. - virtual int32_t Padding(); - - // Return the number of bytes of non-padded data in the table. If the padding - // is unknown or unknowable then the total number of bytes of data in the - // tables is returned. - virtual int32_t DataLength(); - - virtual int32_t Serialize(OutputStream* os); - - protected: - // TODO(arthurhsu): style guide violation: protected member, need refactoring - ReadableFontDataPtr data_; -}; -typedef Ptr FontDataTablePtr; -typedef Ptr FontDataTableBuilderPtr; - -} // namespace sfntly - -#endif // TYPOGRAPHY_FONT_SFNTLY_SRC_SFNTLY_FONT_DATA_TABLE_H_ diff --git a/sfntly/font_data_table_builder_container.h b/sfntly/font_data_table_builder_container.h index f3ccf61..2818464 100644 --- a/sfntly/font_data_table_builder_container.h +++ b/sfntly/font_data_table_builder_container.h @@ -14,8 +14,8 @@ * limitations under the License. */ -#ifndef TYPOGRAPHY_FONT_SFNTLY_SRC_SFNTLY_FONT_DATA_TABLE_BUILDER_CONTAINER_H_ -#define TYPOGRAPHY_FONT_SFNTLY_SRC_SFNTLY_FONT_DATA_TABLE_BUILDER_CONTAINER_H_ +#ifndef SFNTLY_CPP_SRC_SFNTLY_FONT_DATA_TABLE_BUILDER_CONTAINER_H_ +#define SFNTLY_CPP_SRC_SFNTLY_FONT_DATA_TABLE_BUILDER_CONTAINER_H_ #include "sfntly/data/writable_font_data.h" @@ -31,4 +31,4 @@ typedef Ptr FontDataTableBuilderContainerPtr; } // namespace sfntly -#endif // TYPOGRAPHY_FONT_SFNTLY_SRC_SFNTLY_FONT_DATA_TABLE_BUILDER_CONTAINER_H_ +#endif // SFNTLY_CPP_SRC_SFNTLY_FONT_DATA_TABLE_BUILDER_CONTAINER_H_ diff --git a/sfntly/font_factory.h b/sfntly/font_factory.h index 7be0841..b706b92 100644 --- a/sfntly/font_factory.h +++ b/sfntly/font_factory.h @@ -14,8 +14,8 @@ * limitations under the License. */ -#ifndef TYPOGRAPHY_FONT_SFNTLY_SRC_SFNTLY_FONT_FACTORY_H_ -#define TYPOGRAPHY_FONT_SFNTLY_SRC_SFNTLY_FONT_FACTORY_H_ +#ifndef SFNTLY_CPP_SRC_SFNTLY_FONT_FACTORY_H_ +#define SFNTLY_CPP_SRC_SFNTLY_FONT_FACTORY_H_ #include @@ -143,4 +143,4 @@ typedef Ptr FontFactoryPtr; } // namespace sfntly -#endif // TYPOGRAPHY_FONT_SFNTLY_SRC_SFNTLY_FONT_FACTORY_H_ +#endif // SFNTLY_CPP_SRC_SFNTLY_FONT_FACTORY_H_ diff --git a/sfntly/font_header_table.cc b/sfntly/font_header_table.cc deleted file mode 100644 index f896001..0000000 --- a/sfntly/font_header_table.cc +++ /dev/null @@ -1,259 +0,0 @@ -/* - * 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_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(FontDataTableBuilderContainer* font_builder, - Header* header, WritableFontData* data) : - Table::TableBasedTableBuilder(font_builder, header, data) { -} - -FontHeaderTable::Builder::Builder(FontDataTableBuilderContainer* font_builder, - Header* header, ReadableFontData* data) : - Table::TableBasedTableBuilder(font_builder, 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); -} - -} // namespace sfntly diff --git a/sfntly/font_header_table.h b/sfntly/font_header_table.h deleted file mode 100644 index dd6f593..0000000 --- a/sfntly/font_header_table.h +++ /dev/null @@ -1,167 +0,0 @@ -/* - * 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_FONT_HEADER_TABLE_H_ -#define TYPOGRAPHY_FONT_SFNTLY_SRC_SFNTLY_FONT_HEADER_TABLE_H_ - -#include "sfntly/table.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 Table::TableBasedTableBuilder, - public RefCounted { - public: - // Constructor scope altered to public because C++ does not allow base - // class to instantiate derived class with protected constructors. - Builder(FontDataTableBuilderContainer* font_builder, Header* header, - WritableFontData* data); - Builder(FontDataTableBuilderContainer* font_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); - }; - - 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 // TYPOGRAPHY_FONT_SFNTLY_SRC_SFNTLY_FONT_HEADER_TABLE_H_ diff --git a/sfntly/glyph_table.cc b/sfntly/glyph_table.cc deleted file mode 100644 index ac85ab2..0000000 --- a/sfntly/glyph_table.cc +++ /dev/null @@ -1,667 +0,0 @@ -/* - * 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/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(data_, offset, length); -} - -GlyphTable::GlyphTable(Header* header, ReadableFontData* data) - : Table(header, data) { -} - -/****************************************************************************** - * GlyphTable::Builder class - ******************************************************************************/ -GlyphTable::Builder::Builder(FontDataTableBuilderContainer* font_builder, - Header* header, - WritableFontData* data) - : Table::ArrayElementTableBuilder(font_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->resize(glyph_builders->size()); - 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; - } - } -} - -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()) { -#if defined (SFNTLY_NO_EXCEPTION) - return; -#else - throw IllegalStateException( - "Loca values not set - unable to parse glyph data."); -#endif - } - 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()) { - 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(ReadableFontData* data, - int32_t offset, - int32_t length) { - 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::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); -} - -int32_t GlyphTable::Glyph::Padding() { - return padding_; -} - -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(FontDataTableBuilderContainer* font_builder, - WritableFontData* data) - : SubTable::Builder(font_builder, data) { -} - -GlyphTable::Glyph::Builder::Builder(FontDataTableBuilderContainer* font_builder, - ReadableFontData* data) - : SubTable::Builder(font_builder, data) { -} - -CALLER_ATTACH GlyphTable::Glyph::Builder* - GlyphTable::Glyph::Builder::GetBuilder( - FontDataTableBuilderContainer* table_builder, - ReadableFontData* data) { - return GetBuilder(table_builder, data, 0, data->Length()); -} - -CALLER_ATTACH GlyphTable::Glyph::Builder* - GlyphTable::Glyph::Builder::GetBuilder( - FontDataTableBuilderContainer* table_builder, - ReadableFontData* data, - int32_t offset, - int32_t length) { - 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(table_builder, sliced_data); - } else { - builder = new CompositeGlyph::CompositeGlyphBuilder(table_builder, - 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) { -} - -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() { - 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); - padding_ = Length() - 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( - FontDataTableBuilderContainer* table_builder, - WritableFontData* data) - : Glyph::Builder(table_builder, data) { -} - -GlyphTable::SimpleGlyph::SimpleGlyphBuilder::SimpleGlyphBuilder( - FontDataTableBuilderContainer* table_builder, - ReadableFontData* data) - : Glyph::Builder(table_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) { - ParseData(); -} - -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::ParseData() { - 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); - } - padding_ = Length() - non_padded_data_length; - } -} - -/****************************************************************************** - * GlyphTable::CompositeGlyph::Builder - ******************************************************************************/ -GlyphTable::CompositeGlyph::CompositeGlyphBuilder::~CompositeGlyphBuilder() { -} - -GlyphTable::CompositeGlyph::CompositeGlyphBuilder::CompositeGlyphBuilder( - FontDataTableBuilderContainer* table_builder, - WritableFontData* data) - : Glyph::Builder(table_builder, data) { -} - -GlyphTable::CompositeGlyph::CompositeGlyphBuilder::CompositeGlyphBuilder( - FontDataTableBuilderContainer* table_builder, - ReadableFontData* data) - : Glyph::Builder(table_builder, data) { -} - -CALLER_ATTACH FontDataTable* - GlyphTable::CompositeGlyph::CompositeGlyphBuilder::SubBuildTable( - ReadableFontData* data) { - FontDataTablePtr table = new CompositeGlyph(data); - return table.Detach(); -} - -} // namespace sfntly diff --git a/sfntly/glyph_table.h b/sfntly/glyph_table.h deleted file mode 100644 index c066d47..0000000 --- a/sfntly/glyph_table.h +++ /dev/null @@ -1,330 +0,0 @@ -/* - * 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_GLYPH_TABLE_H_ -#define TYPOGRAPHY_FONT_SFNTLY_SRC_SFNTLY_GLYPH_TABLE_H_ - -#include - -#include "sfntly/table.h" -#include "sfntly/subtable.h" - -namespace sfntly { - -struct GlyphType { - enum { - kSimple = 0, - kComposite = 1 - }; -}; - -// Note: due to the complexity of this class, the order of declaration is -// different from its Java counter part. GlyphTable::Glyph is defined -// before GlyphTable::Builder to avoid compilation errors. -class GlyphTable : public Table, 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. - Builder(FontDataTableBuilderContainer* table_builder, - WritableFontData* data); - Builder(FontDataTableBuilderContainer* table_builder, - ReadableFontData* data); - - static CALLER_ATTACH Builder* - GetBuilder(FontDataTableBuilderContainer* table_builder, - ReadableFontData* data); - static CALLER_ATTACH Builder* - GetBuilder(FontDataTableBuilderContainer* 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(ReadableFontData* data, - int32_t offset, - int32_t length); - 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 Padding(); // override FontDataTable::Padding() - - 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); - - // TODO(arthurhsu): violating C++ style guide, need refactoring. - int32_t padding_; - - 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 Table::ArrayElementTableBuilder, - public RefCounted { - public: - // Note: Constructor scope altered to public for base class to instantiate. - Builder(FontDataTableBuilderContainer* font_builder, - Header* header, - WritableFontData* data); - virtual ~Builder(); - - virtual void SetLoca(const IntegerList& loca); - virtual void GenerateLocaList(IntegerList* locas); - - // 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. - 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. - SimpleGlyphBuilder(FontDataTableBuilderContainer* table_builder, - WritableFontData* data); - SimpleGlyphBuilder(FontDataTableBuilderContainer* table_builder, - 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(); - 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 Initialize(); - void ParseData(bool fill_arrays); - int32_t FlagAsInt(int32_t index); - int32_t ContourEndPoint(int32_t contour); - - bool initialized_; - 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. - CompositeGlyphBuilder(FontDataTableBuilderContainer* table_builder, - WritableFontData* data); - CompositeGlyphBuilder(FontDataTableBuilderContainer* table_builder, - 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(); - - private: - void ParseData(); - - IntegerList contour_index_; - int32_t instruction_size_; - int32_t instructions_offset_; - }; - - 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 // TYPOGRAPHY_FONT_SFNTLY_SRC_SFNTLY_GLYPH_TABLE_H_ diff --git a/sfntly/horizontal_header_table.cc b/sfntly/horizontal_header_table.cc deleted file mode 100644 index a987d70..0000000 --- a/sfntly/horizontal_header_table.cc +++ /dev/null @@ -1,215 +0,0 @@ -/* - * 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. - */ - -// Note: original Java version is inconsistent itself (e.g. readUShort in -// Builder but readShort in Table. Need Fix. -// TODO(arthurhsu): check with Stuart G and fix it. - -#include "sfntly/horizontal_header_table.h" - -namespace sfntly { -/****************************************************************************** - * HorizontalHeaderTable class - ******************************************************************************/ -HorizontalHeaderTable:: ~HorizontalHeaderTable() {} - -int32_t HorizontalHeaderTable::Version() { - 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( - FontDataTableBuilderContainer* font_builder, - Header* header, - WritableFontData* data) - : Table::TableBasedTableBuilder(font_builder, header, data) { -} - -HorizontalHeaderTable::Builder::Builder( - FontDataTableBuilderContainer* font_builder, - Header* header, - ReadableFontData* data) - : Table::TableBasedTableBuilder(font_builder, header, data) { -} - -HorizontalHeaderTable::Builder::~Builder() {} - -CALLER_ATTACH FontDataTable* - HorizontalHeaderTable::Builder::SubBuildTable(ReadableFontData* data) { - FontDataTablePtr table = new HorizontalHeaderTable(header(), data); - return table.Detach(); -} - -int32_t HorizontalHeaderTable::Builder::Version() { - return InternalReadData()->ReadFixed(Offset::kVersion); -} - -void HorizontalHeaderTable::Builder::SetVersion(int32_t version) { - InternalWriteData()->WriteFixed(Offset::kVersion, version); -} - -int32_t HorizontalHeaderTable::Builder::Ascender() { - return InternalReadData()->ReadUShort(Offset::kAscender); -} - -void HorizontalHeaderTable::Builder::SetAscender(int32_t ascender) { - InternalWriteData()->WriteUShort(Offset::kVersion, ascender); -} - -int32_t HorizontalHeaderTable::Builder::Descender() { - return InternalReadData()->ReadUShort(Offset::kDescender); -} - -void HorizontalHeaderTable::Builder::SetDescender(int32_t descender) { - InternalWriteData()->WriteUShort(Offset::kDescender, descender); -} - -int32_t HorizontalHeaderTable::Builder::LineGap() { - return InternalReadData()->ReadUShort(Offset::kLineGap); -} - -void HorizontalHeaderTable::Builder::SetLineGap(int32_t line_gap) { - InternalWriteData()->WriteUShort(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()->ReadUShort(Offset::kMinLeftSideBearing); -} - -void HorizontalHeaderTable::Builder::SetMinLeftSideBearing(int32_t value) { - InternalWriteData()->WriteUShort(Offset::kMinLeftSideBearing, value); -} - -int32_t HorizontalHeaderTable::Builder::MinRightSideBearing() { - return InternalReadData()->ReadUShort(Offset::kMinRightSideBearing); -} - -void HorizontalHeaderTable::Builder::SetMinRightSideBearing(int32_t value) { - InternalWriteData()->WriteUShort(Offset::kMinRightSideBearing, value); -} - -int32_t HorizontalHeaderTable::Builder::XMaxExtent() { - return InternalReadData()->ReadUShort(Offset::kXMaxExtent); -} - -void HorizontalHeaderTable::Builder::SetXMaxExtent(int32_t value) { - InternalWriteData()->WriteUShort(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/sfntly/horizontal_header_table.h b/sfntly/horizontal_header_table.h deleted file mode 100644 index e8a3534..0000000 --- a/sfntly/horizontal_header_table.h +++ /dev/null @@ -1,110 +0,0 @@ -/* - * 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_HORIZONTAL_HEADER_TABLE_H_ -#define TYPOGRAPHY_FONT_SFNTLY_SRC_SFNTLY_HORIZONTAL_HEADER_TABLE_H_ - -#include "sfntly/table.h" - -namespace sfntly { - -class HorizontalHeaderTable : public Table, - public RefCounted { - public: - class Builder : public Table::TableBasedTableBuilder, - public RefCounted { - public: - // Constructor scope altered to public because C++ does not allow base - // class to instantiate derived class with protected constructors. - Builder(FontDataTableBuilderContainer* font_builder, - Header* header, - WritableFontData* data); - Builder(FontDataTableBuilderContainer* font_builder, - Header* header, - ReadableFontData* data); - virtual ~Builder(); - virtual CALLER_ATTACH FontDataTable* SubBuildTable(ReadableFontData* data); - - int32_t Version(); - void SetVersion(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 Version(); - 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 // TYPOGRAPHY_FONT_SFNTLY_SRC_SFNTLY_HORIZONTAL_HEADER_TABLE_H_ diff --git a/sfntly/horizontal_metrics_table.cc b/sfntly/horizontal_metrics_table.cc deleted file mode 100644 index 026891d..0000000 --- a/sfntly/horizontal_metrics_table.cc +++ /dev/null @@ -1,151 +0,0 @@ -/* - * 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/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) - return 0; -#else - throw IndexOutOfBoundException(); -#endif - } - 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) - return 0; -#else - throw IndexOutOfBoundException(); -#endif - } - 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) - return 0; -#else - throw IndexOutOfBoundException(); -#endif - } - 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) - : Table(header, data) { -} - -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( - FontDataTableBuilderContainer* font_builder, - Header* header, - WritableFontData* data) - : Table::TableBasedTableBuilder(font_builder, header, data) { - Init(); -} - -HorizontalMetricsTable::Builder::Builder( - FontDataTableBuilderContainer* font_builder, - Header* header, - ReadableFontData* data) - : Table::TableBasedTableBuilder(font_builder, header, data) { - Init(); -} - -HorizontalMetricsTable::Builder::~Builder() {} - -CALLER_ATTACH FontDataTable* - HorizontalMetricsTable::Builder::SubBuildTable(ReadableFontData* data) { - FontDataTablePtr table = - new HorizontalMetricsTable(header(), data, num_hmetrics_, num_glyphs_); - return table.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; -} - -void HorizontalMetricsTable::Builder::Init() { - num_hmetrics_ = -1; - num_glyphs_ = -1; -} - -} // namespace sfntly diff --git a/sfntly/horizontal_metrics_table.h b/sfntly/horizontal_metrics_table.h deleted file mode 100644 index 55acce6..0000000 --- a/sfntly/horizontal_metrics_table.h +++ /dev/null @@ -1,89 +0,0 @@ -/* - * 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_HORIZONTAL_METRICS_TABLE_H_ -#define TYPOGRAPHY_FONT_SFNTLY_SRC_SFNTLY_HORIZONTAL_METRICS_TABLE_H_ - -#include "sfntly/table.h" - -namespace sfntly { - -class HorizontalMetricsTable : public Table, - public RefCounted { - public: - class Builder : public Table::TableBasedTableBuilder, - public RefCounted { - public: - // Constructor scope altered to public because C++ does not allow base - // class to instantiate derived class with protected constructors. - Builder(FontDataTableBuilderContainer* font_builder, - Header* header, - WritableFontData* data); - Builder(FontDataTableBuilderContainer* font_builder, - Header* header, - ReadableFontData* data); - virtual ~Builder(); - - virtual CALLER_ATTACH FontDataTable* SubBuildTable(ReadableFontData* data); - void SetNumberOfHMetrics(int32_t num_hmetrics); - void SetNumGlyphs(int32_t num_glyphs); - - private: - void Init(); - - 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); - 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 // TYPOGRAPHY_FONT_SFNTLY_SRC_SFNTLY_HORIZONTAL_METRICS_TABLE_H_ diff --git a/sfntly/loca_table.cc b/sfntly/loca_table.cc deleted file mode 100644 index 1869e15..0000000 --- a/sfntly/loca_table.cc +++ /dev/null @@ -1,250 +0,0 @@ -/* - * 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/loca_table.h" -#include "sfntly/port/exception_type.h" - -namespace sfntly { -/****************************************************************************** - * LocaTable class - ******************************************************************************/ -LocaTable::~LocaTable() {} - -int32_t LocaTable::NumGlyphs() { - return num_glyphs_; -} - -int32_t LocaTable::GlyphOffset(int32_t glyph_id) { - if (glyph_id < 0 || glyph_id >= num_glyphs_) { -#if defined (SFNTLY_NO_EXCEPTION) - return 0; -#else - throw IndexOutOfBoundException("Glyph ID is out of bounds."); -#endif - } - 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) - return 0; -#else - throw IndexOutOfBoundException("Glyph ID is out of bounds."); -#endif - } - 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) - return 0; -#else - throw IndexOutOfBoundException(); -#endif - } - if (version_ == IndexToLocFormat::kShortOffset) { - return 2 * data_->ReadUShort(index * DataSize::kUSHORT); - } - return data_->ReadULongAsInt(index * DataSize::kULONG); -} - -LocaTable::LocaTable(Header* header, ReadableFontData* data) - : Table(header, data) { -} - -LocaTable::LocaTable(Header* header, - ReadableFontData* data, - int32_t version, - int32_t num_glyphs) - : Table(header, data), version_(version), num_glyphs_(num_glyphs) { -} - -/****************************************************************************** - * LocaTable::Iterator class - ******************************************************************************/ -LocaTable::LocaIterator::LocaIterator(LocaTable* table) - : index_(-1) { - table_ = table; -} - -bool LocaTable::LocaIterator::HasNext() { - return index_ <= table_->num_glyphs_; -} - -int32_t LocaTable::LocaIterator::Next() { - return table_->Loca(index_++); -} - -/****************************************************************************** - * LocaTable::Builder class - ******************************************************************************/ -LocaTable::Builder::Builder(FontDataTableBuilderContainer* font_builder, - Header* header, WritableFontData* data) : - Table::ArrayElementTableBuilder(font_builder, header, data) { - Init(); -} - -LocaTable::Builder::Builder(FontDataTableBuilderContainer* font_builder, - Header* header, ReadableFontData* data) : - Table::ArrayElementTableBuilder(font_builder, header, data) { - Init(); -} - -LocaTable::Builder::~Builder() {} - -void LocaTable::Builder::SetFormatVersion(int32_t format_version) { - format_version_ = format_version; -} - -IntegerList* LocaTable::Builder::LocaList() { - return GetLocaList(); -} - -void LocaTable::Builder::SetLocaList(IntegerList* list) { - loca_.clear(); - if (list) { - loca_ = *list; - num_glyphs_ = loca_.size(); - set_model_changed(); - } -} - -int32_t LocaTable::Builder::GlyphOffset(int32_t glyph_id) { - if (glyph_id < 0 || glyph_id > (num_glyphs_ + 1)) { -#if defined (SFNTLY_NO_EXCEPTION) - return 0; -#else - throw IndexOutOfBoundException("Glyph ID is out of bounds."); -#endif - } - return Loca(glyph_id); -} - -int32_t LocaTable::Builder::GlyphLength(int32_t glyph_id) { - if (glyph_id < 0 || glyph_id > (num_glyphs_ + 1)) { -#if defined (SFNTLY_NO_EXCEPTION) - return 0; -#else - throw IndexOutOfBoundException("Glyph ID is out of bounds."); -#endif - } - return Loca(glyph_id + 1) - Loca(glyph_id); -} - -void LocaTable::Builder::SetNumGlyphs(int32_t num_glyphs) { - num_glyphs_ = num_glyphs; -} - -int32_t LocaTable::Builder::NumGlyphs() { - if (!loca_.empty()) { - return loca_.size() - 1; - } - return num_glyphs_; -} - -void LocaTable::Builder::Revert() { - loca_.clear(); - set_model_changed(false); -} - -void LocaTable::Builder::Clear() { - GetLocaList()->clear(); -} - -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); - } - } - return 0; -} - -void LocaTable::Builder::Init() { - num_glyphs_ = -1; - format_version_ = IndexToLocFormat::kLongOffset; -} - -void LocaTable::Builder::Initialize(ReadableFontData* data) { - if (data) { - if (NumGlyphs() < 0) { -#if defined (SFNTLY_NO_EXCEPTION) - return; -#else - throw IllegalStateException("numglyphs not set on LocaTable Builder."); -#endif - } - LocaTablePtr table = - new LocaTable(header(), data, format_version_, num_glyphs_); - LocaTable::LocaIterator loca_iter(table); - while (loca_iter.HasNext()) { - loca_.push_back(loca_iter.Next()); - } - } -} - -IntegerList* LocaTable::Builder::GetLocaList() { - if (loca_.empty()) { - Initialize(InternalReadData()); - set_model_changed(); - } - return &loca_; -} - -} // namespace sfntly diff --git a/sfntly/loca_table.h b/sfntly/loca_table.h deleted file mode 100644 index dcf9715..0000000 --- a/sfntly/loca_table.h +++ /dev/null @@ -1,146 +0,0 @@ -/* - * 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_LOCA_TABLE_H_ -#define TYPOGRAPHY_FONT_SFNTLY_SRC_SFNTLY_LOCA_TABLE_H_ - -#include "sfntly/table.h" -#include "sfntly/font_header_table.h" - -namespace sfntly { - -class LocaTable : public Table, public RefCounted { - public: - // Note: different implementation than Java, caller to instantiate this class - // object directly from stack instead of calling LocaTable::iterator(). - class LocaIterator { - public: - explicit LocaIterator(LocaTable* table); - bool HasNext(); - int32_t Next(); - - private: - int32_t index_; - LocaTable* table_; // use dumb pointer since it's a composition object - }; - - class Builder : public Table::ArrayElementTableBuilder, - public RefCounted { - public: - // Constructor scope altered to public for base class to instantiate. - Builder(FontDataTableBuilderContainer* font_builder, Header* header, - WritableFontData* data); - Builder(FontDataTableBuilderContainer* font_builder, Header* header, - ReadableFontData* data); - virtual ~Builder(); - - void SetFormatVersion(int32_t format_version); - - // 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. - // 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(); - 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. - void SetNumGlyphs(int32_t num_glyphs); - int NumGlyphs(); - - void Revert(); - void Clear(); - - // 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(); - 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: - void Init(); // short hand for common code in ctors, C++ port only - void Initialize(ReadableFontData* data); // ported from Java - IntegerList* GetLocaList(); - - int32_t format_version_; // Note: IndexToLocFormat - int32_t num_glyphs_; - IntegerList loca_; - }; - - virtual ~LocaTable(); - int32_t NumGlyphs(); - - // 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); - LocaTable(Header* header, - ReadableFontData* data, - int32_t version, - int32_t num_glyphs); - - int32_t version_; // Note: IndexToLocFormat - int32_t num_glyphs_; - - friend class LocaIterator; -}; -typedef Ptr LocaTablePtr; -typedef Ptr LocaTableBuilderPtr; - -} // namespace sfntly - -#endif // TYPOGRAPHY_FONT_SFNTLY_SRC_SFNTLY_LOCA_TABLE_H_ diff --git a/sfntly/math/fixed1616.h b/sfntly/math/fixed1616.h index 843da51..4abbe18 100644 --- a/sfntly/math/fixed1616.h +++ b/sfntly/math/fixed1616.h @@ -14,8 +14,8 @@ * limitations under the License. */ -#ifndef TYPOGRAPHY_FONT_SFNTLY_SRC_SFNTLY_MATH_FIXED1616_H_ -#define TYPOGRAPHY_FONT_SFNTLY_SRC_SFNTLY_MATH_FIXED1616_H_ +#ifndef SFNTLY_CPP_SRC_SFNTLY_MATH_FIXED1616_H_ +#define SFNTLY_CPP_SRC_SFNTLY_MATH_FIXED1616_H_ #include "sfntly/port/type.h" @@ -38,4 +38,4 @@ class Fixed1616 { } // namespace sfntly -#endif // TYPOGRAPHY_FONT_SFNTLY_SRC_SFNTLY_MATH_FIXED1616_H_ +#endif // SFNTLY_CPP_SRC_SFNTLY_MATH_FIXED1616_H_ diff --git a/sfntly/math/font_math.h b/sfntly/math/font_math.h index f15a786..c469347 100644 --- a/sfntly/math/font_math.h +++ b/sfntly/math/font_math.h @@ -14,8 +14,8 @@ * limitations under the License. */ -#ifndef TYPOGRAPHY_FONT_SFNTLY_SRC_SFNTLY_MATH_FONT_MATH_H_ -#define TYPOGRAPHY_FONT_SFNTLY_SRC_SFNTLY_MATH_FONT_MATH_H_ +#ifndef SFNTLY_CPP_SRC_SFNTLY_MATH_FONT_MATH_H_ +#define SFNTLY_CPP_SRC_SFNTLY_MATH_FONT_MATH_H_ #include "sfntly/port/type.h" @@ -35,4 +35,4 @@ class FontMath { } // namespace sfntly -#endif // TYPOGRAPHY_FONT_SFNTLY_SRC_SFNTLY_MATH_FONT_MATH_H_ +#endif // SFNTLY_CPP_SRC_SFNTLY_MATH_FONT_MATH_H_ diff --git a/sfntly/maximum_profile_table.cc b/sfntly/maximum_profile_table.cc deleted file mode 100644 index 0ab2aaf..0000000 --- a/sfntly/maximum_profile_table.cc +++ /dev/null @@ -1,224 +0,0 @@ -/* - * 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/maximum_profile_table.h" - -namespace sfntly { -/****************************************************************************** - * MaximumProfileTable class - ******************************************************************************/ -MaximumProfileTable::~MaximumProfileTable() {} - -int32_t MaximumProfileTable::Version() { - 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::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( - FontDataTableBuilderContainer* font_builder, - Header* header, - WritableFontData* data) - : Table::TableBasedTableBuilder(font_builder, header, data) { -} - -MaximumProfileTable::Builder::Builder( - FontDataTableBuilderContainer* font_builder, - Header* header, - ReadableFontData* data) - : Table::TableBasedTableBuilder(font_builder, header, data) { -} - -MaximumProfileTable::Builder::~Builder() {} - -CALLER_ATTACH FontDataTable* - MaximumProfileTable::Builder::SubBuildTable(ReadableFontData* data) { - FontDataTablePtr table = new MaximumProfileTable(header(), data); - return table.Detach(); -} - -int32_t MaximumProfileTable::Builder::Version() { - return InternalReadData()->ReadUShort(Offset::kVersion); -} - -void MaximumProfileTable::Builder::SetVersion(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::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/sfntly/maximum_profile_table.h b/sfntly/maximum_profile_table.h deleted file mode 100644 index 9e0d0a6..0000000 --- a/sfntly/maximum_profile_table.h +++ /dev/null @@ -1,115 +0,0 @@ -/* - * 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_MAXIMUM_PROFILE_TABLE_H_ -#define TYPOGRAPHY_FONT_SFNTLY_SRC_SFNTLY_MAXIMUM_PROFILE_TABLE_H_ - -#include "sfntly/port/refcount.h" -#include "sfntly/table.h" - -namespace sfntly { - -class MaximumProfileTable : public Table, - public RefCounted { - public: - class Builder : public Table::TableBasedTableBuilder, - public RefCounted { - public: - // Constructor scope altered to public because C++ does not allow base - // class to instantiate derived class with protected constructors. - Builder(FontDataTableBuilderContainer* font_builder, Header* header, - WritableFontData* data); - Builder(FontDataTableBuilderContainer* font_builder, Header* header, - ReadableFontData* data); - virtual ~Builder(); - - virtual CALLER_ATTACH FontDataTable* SubBuildTable(ReadableFontData* data); - - int32_t Version(); - void SetVersion(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 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 Version(); - int32_t NumGlyphs(); - int32_t MaxPoints(); - int32_t MaxContours(); - int32_t MaxCompositePoints(); - 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 // TYPOGRAPHY_FONT_SFNTLY_SRC_SFNTLY_MAXIMUM_PROFILE_TABLE_H_ diff --git a/sfntly/name_table.cc b/sfntly/name_table.cc deleted file mode 100644 index 649baed..0000000 --- a/sfntly/name_table.cc +++ /dev/null @@ -1,722 +0,0 @@ -/* - * 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/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) { - Init(table, NULL); -} - -NameTable::NameEntryIterator::NameEntryIterator(NameTable* table, - NameEntryFilter* filter) { - Init(table, filter); -} - -bool NameTable::NameEntryIterator::HasNext() { - if (!filter_) { - if (name_index_ < table_->NameCount()) { - return true; - } - return false; - } - for (; name_index_ < table_->NameCount(); ++name_index_) { - if (filter_->Accept(table_->PlatformId(name_index_), - table_->EncodingId(name_index_), - table_->LanguageId(name_index_), - table_->NameId(name_index_))) { - return true; - } - } - return false; -} - -CALLER_ATTACH NameTable::NameEntry* NameTable::NameEntryIterator::Next() { - if (!HasNext()) - return NULL; - return table_->GetNameEntry(name_index_++); -} - -void NameTable::NameEntryIterator::Remove() { -#if !defined (SFNTLY_NO_EXCEPTION) - throw UnsupportedOperationException( - "Cannot remove a CMap table from an existing font."); -#endif -} - -void NameTable::NameEntryIterator::Init(NameTable* table, - NameEntryFilter* filter) { - table_ = table; - filter_ = filter; - name_index_ = 0; -} - -/****************************************************************************** - * NameTable::Builder class - ******************************************************************************/ -NameTable::Builder::Builder(FontDataTableBuilderContainer* font_builder, - Header* header, - WritableFontData* data) - : Table::ArrayElementTableBuilder(font_builder, header, data) { -} - -NameTable::Builder::Builder(FontDataTableBuilderContainer* font_builder, - Header* header, - ReadableFontData* data) - : Table::ArrayElementTableBuilder(font_builder, header, data) { -} - -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); - NameEntryIterator name_iter(table, NULL); - 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); - NameTable::NameEntryIterator* name_entry_iter = Iterator(&filter); - NameEntryPtr result; - if (name_entry_iter->HasNext()) { - result = name_entry_iter->Next(); - } - delete name_entry_iter; - return result; -} - -NameTable::NameEntryIterator* NameTable::Iterator() { - return new NameTable::NameEntryIterator(this); -} - -NameTable::NameEntryIterator* NameTable::Iterator(NameEntryFilter* filter) { - return new NameTable::NameEntryIterator(this, filter); -} - -NameTable::NameTable(Header* header, ReadableFontData* data) - : Table(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/sfntly/name_table.h b/sfntly/name_table.h deleted file mode 100644 index 64353d6..0000000 --- a/sfntly/name_table.h +++ /dev/null @@ -1,737 +0,0 @@ -/* - * 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_NAME_TABLE_H_ -#define TYPOGRAPHY_FONT_SFNTLY_SRC_SFNTLY_NAME_TABLE_H_ - -// Must include this before ICU to avoid stdint redefinition issue. -#include "sfntly/port/type.h" - -#include -#include - -#include -#include - -#include "sfntly/table.h" - -#if defined U_USING_ICU_NAMESPACE - U_NAMESPACE_USE -#endif - -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 Table, 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; - - 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; - - 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_; - }; - - // Mimic Java's iterator to iterate through the entries within the name table. - class NameEntryIterator { - public: - // If filter is NULL, filter through all tables. - explicit NameEntryIterator(NameTable* table); - NameEntryIterator(NameTable* table, NameEntryFilter* filter); - // Make gcc -Wnon-virtual-dtor happy. - virtual ~NameEntryIterator() {} - - virtual bool HasNext(); - virtual CALLER_ATTACH NameEntry* Next(); - virtual void Remove(); - - private: - void Init(NameTable* table, NameEntryFilter* filter); - - NameTable* table_; // Use dumb pointer since it's a composition object. - int32_t name_index_; - NameEntryFilter* filter_; - }; - - // The builder to construct name table for outputting. - class Builder : public Table::ArrayElementTableBuilder, - public RefCounted { - public: - // Constructor scope altered to public because C++ does not allow base - // class to instantiate derived class with protected constructors. - Builder(FontDataTableBuilderContainer* font_builder, Header* header, - WritableFontData* data); - Builder(FontDataTableBuilderContainer* font_builder, Header* header, - ReadableFontData* 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. - // Note: Caller delete the returned object. - virtual NameEntryIterator* Iterator(); - virtual 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 // TYPOGRAPHY_FONT_SFNTLY_SRC_SFNTLY_NAME_TABLE_H_ diff --git a/sfntly/os2_table.cc b/sfntly/os2_table.cc deleted file mode 100644 index 24ef4e9..0000000 --- a/sfntly/os2_table.cc +++ /dev/null @@ -1,277 +0,0 @@ -/* - * 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/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::Version() { - 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) { - 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) { - 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); -} - -int64_t OS2Table::UlCodePageRange() { - // TODO(arthurhsu): Possible bug point, check with stuartg. - return ((0xffffffff & UlCodePageRange2()) << 32) | - (0xffffffff & UlCodePageRange1()); -} - -int32_t OS2Table::SxHeight() { - return data_->ReadShort(Offset::kSxHeight); -} - -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(FontDataTableBuilderContainer* font_builder, - Header* header, WritableFontData* data) : - Table::TableBasedTableBuilder(font_builder, header, data) { -} - -OS2Table::Builder::~Builder() {} - -CALLER_ATTACH FontDataTable* OS2Table::Builder::SubBuildTable( - ReadableFontData* data) { - FontDataTablePtr table = new OS2Table(header(), data); - return table.Detach(); -} - -} // namespace sfntly diff --git a/sfntly/os2_table.h b/sfntly/os2_table.h deleted file mode 100644 index dcad188..0000000 --- a/sfntly/os2_table.h +++ /dev/null @@ -1,407 +0,0 @@ -/* - * 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_OS2_TABLE_H_ -#define TYPOGRAPHY_FONT_SFNTLY_SRC_SFNTLY_OS2_TABLE_H_ - -#include "sfntly/port/refcount.h" -#include "sfntly/table.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 - }; -}; - -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 { - // 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) -}; - -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 - }; -}; - -// 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; -}; - -class OS2Table : public Table, public RefCounted { - public: - class Builder : public Table::TableBasedTableBuilder, - public RefCounted { - public: - Builder(FontDataTableBuilderContainer* font_builder, Header* header, - WritableFontData* data); - virtual ~Builder(); - virtual CALLER_ATTACH FontDataTable* SubBuildTable(ReadableFontData* data); - }; - - ~OS2Table(); - - int32_t Version(); - 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() - int64_t 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, - kUlUnicodeRange1 = 42, - kUlUnicodeRange2 = 46, - kUlUnicodeRange3 = 50, - kUlUnicodeRange4 = 54, - kAchVendId = 58, - 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 // TYPOGRAPHY_FONT_SFNTLY_SRC_SFNTLY_OS2_TABLE_H_ diff --git a/sfntly/port/atomic.h b/sfntly/port/atomic.h index abfc429..b381a52 100644 --- a/sfntly/port/atomic.h +++ b/sfntly/port/atomic.h @@ -14,8 +14,8 @@ * limitations under the License. */ -#ifndef TYPOGRAPHY_FONT_SFNTLY_SRC_SFNTLY_PORT_ATOMIC_H_ -#define TYPOGRAPHY_FONT_SFNTLY_SRC_SFNTLY_PORT_ATOMIC_H_ +#ifndef SFNTLY_CPP_SRC_SFNTLY_PORT_ATOMIC_H_ +#define SFNTLY_CPP_SRC_SFNTLY_PORT_ATOMIC_H_ #if defined (WIN32) @@ -68,4 +68,4 @@ static inline size_t AtomicDecrement(size_t* address) { #endif // WIN32 -#endif // TYPOGRAPHY_FONT_SFNTLY_SRC_SFNTLY_PORT_ATOMIC_H_ +#endif // SFNTLY_CPP_SRC_SFNTLY_PORT_ATOMIC_H_ diff --git a/sfntly/port/config.h b/sfntly/port/config.h index 8e610d0..01c4685 100644 --- a/sfntly/port/config.h +++ b/sfntly/port/config.h @@ -14,15 +14,15 @@ * limitations under the License. */ -#ifndef TYPOGRAPHY_FONT_SFNTLY_SRC_SFNTLY_PORT_CONFIG_H_ -#define TYPOGRAPHY_FONT_SFNTLY_SRC_SFNTLY_PORT_CONFIG_H_ +#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 TYPOGRAPHY_FONT_SFNTLY_BIG_ENDIAN + #define SFNTLY_CPP_BIG_ENDIAN #else - #define TYPOGRAPHY_FONT_SFNTLY_LITTLE_ENDIAN + #define SFNTLY_CPP_LITTLE_ENDIAN #endif #endif -#endif // TYPOGRAPHY_FONT_SFNTLY_SRC_SFNTLY_PORT_CONFIG_H_ +#endif // SFNTLY_CPP_SRC_SFNTLY_PORT_CONFIG_H_ diff --git a/sfntly/port/endian.h b/sfntly/port/endian.h index 1364e42..db58f0a 100644 --- a/sfntly/port/endian.h +++ b/sfntly/port/endian.h @@ -14,8 +14,8 @@ * limitations under the License. */ -#ifndef TYPOGRAPHY_FONT_SFNTLY_SRC_SFNTLY_PORT_ENDIAN_H_ -#define TYPOGRAPHY_FONT_SFNTLY_SRC_SFNTLY_PORT_ENDIAN_H_ +#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" @@ -74,4 +74,4 @@ static inline uint64_t EndianSwap64(uint64_t value) { } // namespace sfntly -#endif // TYPOGRAPHY_FONT_SFNTLY_SRC_SFNTLY_PORT_ENDIAN_H_ +#endif // SFNTLY_CPP_SRC_SFNTLY_PORT_ENDIAN_H_ diff --git a/sfntly/port/exception_type.h b/sfntly/port/exception_type.h index ddeb95b..b96efcb 100644 --- a/sfntly/port/exception_type.h +++ b/sfntly/port/exception_type.h @@ -16,8 +16,8 @@ // Exceptions used in sfntly -#ifndef TYPOGRAPHY_FONT_SFNTLY_SRC_SFNTLY_PORT_EXCEPTION_TYPE_H_ -#define TYPOGRAPHY_FONT_SFNTLY_SRC_SFNTLY_PORT_EXCEPTION_TYPE_H_ +#ifndef SFNTLY_CPP_SRC_SFNTLY_PORT_EXCEPTION_TYPE_H_ +#define SFNTLY_CPP_SRC_SFNTLY_PORT_EXCEPTION_TYPE_H_ #if !defined (SFNTLY_NO_EXCEPTION) @@ -122,4 +122,4 @@ class IllegalStateException : public Exception { #endif // #if !defined (SFNTLY_NO_EXCEPTION) -#endif // TYPOGRAPHY_FONT_SFNTLY_SRC_SFNTLY_PORT_EXCEPTION_TYPE_H_ +#endif // SFNTLY_CPP_SRC_SFNTLY_PORT_EXCEPTION_TYPE_H_ diff --git a/sfntly/port/file_input_stream.h b/sfntly/port/file_input_stream.h index a63726f..cbca25f 100644 --- a/sfntly/port/file_input_stream.h +++ b/sfntly/port/file_input_stream.h @@ -14,8 +14,8 @@ * limitations under the License. */ -#ifndef TYPOGRAPHY_FONT_SFNTLY_SRC_SFNTLY_PORT_FILE_INPUT_STREAM_H_ -#define TYPOGRAPHY_FONT_SFNTLY_SRC_SFNTLY_PORT_FILE_INPUT_STREAM_H_ +#ifndef SFNTLY_CPP_SRC_SFNTLY_PORT_FILE_INPUT_STREAM_H_ +#define SFNTLY_CPP_SRC_SFNTLY_PORT_FILE_INPUT_STREAM_H_ #include @@ -54,4 +54,4 @@ class FileInputStream : public PushbackInputStream { } // namespace sfntly -#endif // TYPOGRAPHY_FONT_SFNTLY_SRC_SFNTLY_PORT_FILE_INPUT_STREAM_H_ +#endif // SFNTLY_CPP_SRC_SFNTLY_PORT_FILE_INPUT_STREAM_H_ diff --git a/sfntly/port/input_stream.h b/sfntly/port/input_stream.h index a56afb9..5d24036 100644 --- a/sfntly/port/input_stream.h +++ b/sfntly/port/input_stream.h @@ -14,8 +14,8 @@ * limitations under the License. */ -#ifndef TYPOGRAPHY_FONT_SFNTLY_SRC_SFNTLY_PORT_INPUT_STREAM_H_ -#define TYPOGRAPHY_FONT_SFNTLY_SRC_SFNTLY_PORT_INPUT_STREAM_H_ +#ifndef SFNTLY_CPP_SRC_SFNTLY_PORT_INPUT_STREAM_H_ +#define SFNTLY_CPP_SRC_SFNTLY_PORT_INPUT_STREAM_H_ #include "sfntly/port/type.h" @@ -46,4 +46,4 @@ class PushbackInputStream : public InputStream { } // namespace sfntly -#endif // TYPOGRAPHY_FONT_SFNTLY_SRC_SFNTLY_PORT_INPUT_STREAM_H_ +#endif // SFNTLY_CPP_SRC_SFNTLY_PORT_INPUT_STREAM_H_ diff --git a/sfntly/port/memory_output_stream.h b/sfntly/port/memory_output_stream.h index 8983ab0..d1eda7f 100644 --- a/sfntly/port/memory_output_stream.h +++ b/sfntly/port/memory_output_stream.h @@ -14,8 +14,8 @@ * limitations under the License. */ -#ifndef TYPOGRAPHY_FONT_SFNTLY_SRC_SFNTLY_PORT_MEMORY_OUTPUT_STREAM_H_ -#define TYPOGRAPHY_FONT_SFNTLY_SRC_SFNTLY_PORT_MEMORY_OUTPUT_STREAM_H_ +#ifndef SFNTLY_CPP_SRC_SFNTLY_PORT_MEMORY_OUTPUT_STREAM_H_ +#define SFNTLY_CPP_SRC_SFNTLY_PORT_MEMORY_OUTPUT_STREAM_H_ #include #include @@ -48,4 +48,4 @@ class MemoryOutputStream : public OutputStream { } // namespace sfntly -#endif // TYPOGRAPHY_FONT_SFNTLY_SRC_SFNTLY_PORT_MEMORY_OUTPUT_STREAM_H_ +#endif // SFNTLY_CPP_SRC_SFNTLY_PORT_MEMORY_OUTPUT_STREAM_H_ diff --git a/sfntly/port/output_stream.h b/sfntly/port/output_stream.h index d813333..64a6024 100644 --- a/sfntly/port/output_stream.h +++ b/sfntly/port/output_stream.h @@ -14,8 +14,8 @@ * limitations under the License. */ -#ifndef TYPOGRAPHY_FONT_SFNTLY_SRC_SFNTLY_PORT_OUTPUT_STREAM_H_ -#define TYPOGRAPHY_FONT_SFNTLY_SRC_SFNTLY_PORT_OUTPUT_STREAM_H_ +#ifndef SFNTLY_CPP_SRC_SFNTLY_PORT_OUTPUT_STREAM_H_ +#define SFNTLY_CPP_SRC_SFNTLY_PORT_OUTPUT_STREAM_H_ #include "sfntly/port/type.h" @@ -43,4 +43,4 @@ class OutputStream { } // namespace sfntly -#endif // TYPOGRAPHY_FONT_SFNTLY_SRC_SFNTLY_PORT_OUTPUT_STREAM_H_ +#endif // SFNTLY_CPP_SRC_SFNTLY_PORT_OUTPUT_STREAM_H_ diff --git a/sfntly/port/refcount.h b/sfntly/port/refcount.h index 6ac09bb..eed5162 100644 --- a/sfntly/port/refcount.h +++ b/sfntly/port/refcount.h @@ -63,8 +63,8 @@ // end_scope_pointer.Attach(passThrough); // If you are not passing that object back, you are the end of scope. -#ifndef TYPOGRAPHY_FONT_SFNTLY_SRC_SFNTLY_PORT_REFCOUNT_H_ -#define TYPOGRAPHY_FONT_SFNTLY_SRC_SFNTLY_PORT_REFCOUNT_H_ +#ifndef SFNTLY_CPP_SRC_SFNTLY_PORT_REFCOUNT_H_ +#define SFNTLY_CPP_SRC_SFNTLY_PORT_REFCOUNT_H_ #if !defined (NDEBUG) #define ENABLE_OBJECT_COUNTER @@ -274,4 +274,4 @@ class Ptr { } // namespace sfntly -#endif // TYPOGRAPHY_FONT_SFNTLY_SRC_SFNTLY_PORT_REFCOUNT_H_ +#endif // SFNTLY_CPP_SRC_SFNTLY_PORT_REFCOUNT_H_ diff --git a/sfntly/port/type.h b/sfntly/port/type.h index 4691a82..458a364 100644 --- a/sfntly/port/type.h +++ b/sfntly/port/type.h @@ -14,8 +14,8 @@ * limitations under the License. */ -#ifndef TYPOGRAPHY_FONT_SFNTLY_SRC_SFNTLY_PORT_TYPE_H_ -#define TYPOGRAPHY_FONT_SFNTLY_SRC_SFNTLY_PORT_TYPE_H_ +#ifndef SFNTLY_CPP_SRC_SFNTLY_PORT_TYPE_H_ +#define SFNTLY_CPP_SRC_SFNTLY_PORT_TYPE_H_ #include @@ -93,4 +93,4 @@ inline To down_cast(From* f) { // so we only accept pointers #define UNREFERENCED_PARAMETER(p) do { (void)p; } while (0) #endif -#endif // TYPOGRAPHY_FONT_SFNTLY_SRC_SFNTLY_PORT_TYPE_H_ +#endif // SFNTLY_CPP_SRC_SFNTLY_PORT_TYPE_H_ diff --git a/sfntly/subtable.cc b/sfntly/subtable.cc deleted file mode 100644 index 782fd80..0000000 --- a/sfntly/subtable.cc +++ /dev/null @@ -1,44 +0,0 @@ -/* - * 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/subtable.h" - -namespace sfntly { -/****************************************************************************** - * SubTable class - ******************************************************************************/ -SubTable::~SubTable() {} - -SubTable::SubTable(ReadableFontData* data) - : FontDataTable(data) { -} - -/****************************************************************************** - * SubTable::Builder class - ******************************************************************************/ -SubTable::Builder::~Builder() {} - -SubTable::Builder::Builder(FontDataTableBuilderContainer* container, - WritableFontData* data) - : FontDataTable::Builder(container, data) { -} - -SubTable::Builder::Builder(FontDataTableBuilderContainer* container, - ReadableFontData* data) - : FontDataTable::Builder(container, data) { -} - -} // namespace sfntly diff --git a/sfntly/subtable.h b/sfntly/subtable.h deleted file mode 100644 index 30ecf66..0000000 --- a/sfntly/subtable.h +++ /dev/null @@ -1,49 +0,0 @@ -/* - * 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_SUBTABLE_H_ -#define TYPOGRAPHY_FONT_SFNTLY_SRC_SFNTLY_SUBTABLE_H_ - -#include "sfntly/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: - Builder(FontDataTableBuilderContainer* container, WritableFontData* data); - Builder(FontDataTableBuilderContainer* container, ReadableFontData* data); - }; - - virtual ~SubTable(); - - protected: - // Note: constructor refactored in C++ to avoid heavy lifting. - // caller need to do data->Slice(offset, length) beforehand. - explicit SubTable(ReadableFontData* data); -}; - -} // namespace sfntly - -#endif // TYPOGRAPHY_FONT_SFNTLY_SRC_SFNTLY_SUBTABLE_H_ diff --git a/sfntly/table.cc b/sfntly/table.cc deleted file mode 100644 index fc09d10..0000000 --- a/sfntly/table.cc +++ /dev/null @@ -1,279 +0,0 @@ -/* - * 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.h" - -#include "sfntly/font.h" -#include "sfntly/tag.h" -#include "sfntly/cmap_table.h" -#include "sfntly/font_header_table.h" -#include "sfntly/glyph_table.h" -#include "sfntly/horizontal_header_table.h" -#include "sfntly/horizontal_metrics_table.h" -#include "sfntly/loca_table.h" -#include "sfntly/maximum_profile_table.h" -#include "sfntly/name_table.h" -#include "sfntly/os2_table.h" - -namespace sfntly { - -/****************************************************************************** - * Table class - ******************************************************************************/ -Table::~Table() {} - -int64_t Table::CalculatedChecksum() { - return data_->Checksum(); -} - -WritableFontData* Table::GetNewData(int32_t size) { - return font_->GetNewData(size); -} - -void Table::SetFont(Font* font) { - font_ = font; -} - -Table::Table(Header* header, ReadableFontData* data) - : FontDataTable(data) { - header_ = header; -} - -/****************************************************************************** - * Table::Header class - ******************************************************************************/ -Table::Header::Header(int32_t tag) - : tag_(tag), - offset_(0), - length_(0), - offset_valid_(false), - checksum_(0), - checksum_valid_(false) { -} - -Table::Header::Header(int32_t tag, int32_t length) - : tag_(tag), - offset_(0), - length_(length), - offset_valid_(false), - checksum_(0), - checksum_valid_(false) { -} - -Table::Header::Header(int32_t tag, - int64_t checksum, - int32_t offset, - int32_t length) - : tag_(tag), - offset_(offset), - length_(length), - offset_valid_(true), - checksum_(checksum), - checksum_valid_(true) { -} - -Table::Header::~Header() {} - -bool TableHeaderComparator::operator() (const TableHeaderPtr lhs, - const TableHeaderPtr rhs) { - return lhs->offset_ > rhs->offset_; -} - -/****************************************************************************** - * 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); - header_ = new Header(header()->tag(), - derived_table->ReadFontData()->Length()); - } -} - -WritableFontData* Table::Builder::GetNewData(int32_t size) { - UNREFERENCED_PARAMETER(size); - return InternalWriteData(); -} - -CALLER_ATTACH Table::Builder* - Table::Builder::GetBuilder(FontDataTableBuilderContainer* font_builder, - Header* header, - WritableFontData* table_data) { - int32_t tag = header->tag(); - TableBuilderPtr builder; - 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::cmap) { - builder_raw = static_cast( - new CMapTable::Builder(font_builder, header, table_data)); - } else*/ if (tag == Tag::head) { - builder_raw = static_cast( - new FontHeaderTable::Builder(font_builder, header, table_data)); - } else if (tag == Tag::hhea) { - builder_raw = static_cast( - new HorizontalHeaderTable::Builder(font_builder, header, table_data)); - } else if (tag == Tag::hmtx) { - builder_raw = static_cast( - new HorizontalMetricsTable::Builder(font_builder, header, table_data)); - } else if (tag == Tag::maxp) { - builder_raw = static_cast( - new MaximumProfileTable::Builder(font_builder, header, table_data)); - } else if (tag == Tag::name) { - builder_raw = static_cast( - new NameTable::Builder(font_builder, header, table_data)); - } else if (tag == Tag::OS_2) { - builder_raw = static_cast( - new OS2Table::Builder(font_builder, header, table_data)); - }/* else if (tag == Tag::PostScript) { - builder_raw = static_cast( - new PostScriptTable::Builder(font_builder, header, table_data)); - } else if (tag == Tag::cvt) { - builder_raw = static_cast( - new ControlValueTable::Builder(font_builder, header, table_data)); - }*/ else if (tag == Tag::glyf) { - builder_raw = static_cast( - new GlyphTable::Builder(font_builder, header, table_data)); - } else if (tag == Tag::loca) { - builder_raw = static_cast( - new LocaTable::Builder(font_builder, header, table_data)); - }/* else if (tag == Tag::prep) { - builder_raw = static_cast( - new ControlProgramTable::Builder(font_builder, header, table_data)); - }*/ else if (tag == Tag::bhed) { - builder_raw = static_cast( - new FontHeaderTable::Builder(font_builder, header, table_data)); - } else { - builder_raw = static_cast( - new Table::GenericTableBuilder(font_builder, header, table_data)); - } - - builder = builder_raw; - return builder.Detach(); -} - -Table::Builder::Builder(FontDataTableBuilderContainer* font_builder, - Header* header, - WritableFontData* data) - : FontDataTable::Builder(font_builder, data) { - header_ = header; -} - -Table::Builder::Builder(FontDataTableBuilderContainer* font_builder, - Header* header, - ReadableFontData* data) - : FontDataTable::Builder(font_builder, data) { - header_ = header; -} - -Table::Builder::Builder(FontDataTableBuilderContainer* font_builder, - Header* header) - : FontDataTable::Builder(font_builder) { - header_ = header; -} - -/****************************************************************************** - * Table::TableBasedTableBuilder class - ******************************************************************************/ -Table::TableBasedTableBuilder::~TableBasedTableBuilder() {} - -int32_t Table::TableBasedTableBuilder::SubSerialize(WritableFontData* data) { - UNREFERENCED_PARAMETER(data); - return 0; -} - -bool Table::TableBasedTableBuilder::SubReadyToSerialize() { - return false; -} - -int32_t Table::TableBasedTableBuilder::SubDataSizeToSerialize() { - return 0; -} - -void Table::TableBasedTableBuilder::SubDataSet() { - table_ = NULL; -} - -Table::TableBasedTableBuilder::TableBasedTableBuilder( - FontDataTableBuilderContainer* font_builder, - Header* header, - WritableFontData* data) - : Builder(font_builder, header, data) { -} - -Table::TableBasedTableBuilder::TableBasedTableBuilder( - FontDataTableBuilderContainer* font_builder, - Header* header, - ReadableFontData* data) - : Builder(font_builder, header, data) { -} - -Table::TableBasedTableBuilder::TableBasedTableBuilder( - FontDataTableBuilderContainer* font_builder, - Header* header) - : Builder(font_builder, header) { -} - -Table* Table::TableBasedTableBuilder::GetTable() { - if (table_ == NULL) { - table_.Attach(down_cast(SubBuildTable(InternalReadData()))); - } - return table_; -} - -/****************************************************************************** - * Table::GenericTableBuilder class - ******************************************************************************/ -Table::GenericTableBuilder::GenericTableBuilder( - FontDataTableBuilderContainer* font_builder, - Header* header, - WritableFontData* data) - : TableBasedTableBuilder(font_builder, header, data) { -} - -CALLER_ATTACH FontDataTable* - Table::GenericTableBuilder::SubBuildTable(ReadableFontData* data) { - // Note: In C++ port, we use GenericTable, the ref-counted version of Table - UNREFERENCED_PARAMETER(data); - FontDataTablePtr table = new GenericTable(this->header(), InternalReadData()); - return table.Detach(); -} - -/****************************************************************************** - * Table::ArrayElementTableBuilder class - ******************************************************************************/ -Table::ArrayElementTableBuilder::~ArrayElementTableBuilder() {} - -Table::ArrayElementTableBuilder::ArrayElementTableBuilder( - FontDataTableBuilderContainer* font_builder, - Header* header, - WritableFontData* data) - : Builder(font_builder, header, data) { -} - -Table::ArrayElementTableBuilder::ArrayElementTableBuilder( - FontDataTableBuilderContainer* font_builder, - Header* header, - ReadableFontData* data) - : Builder(font_builder, header, data) { -} - -} // namespace sfntly diff --git a/sfntly/table.h b/sfntly/table.h deleted file mode 100644 index 217abcd..0000000 --- a/sfntly/table.h +++ /dev/null @@ -1,183 +0,0 @@ -/* - * 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_H_ -#define TYPOGRAPHY_FONT_SFNTLY_SRC_SFNTLY_TABLE_H_ - -#include -#include -#include -#include - -#include "sfntly/port/type.h" -#include "sfntly/font_data_table.h" - -namespace sfntly { -class Font; -class Table : public FontDataTable, public FontDataTableBuilderContainer { - public: - class Header : public RefCounted
{ - public: - explicit Header(int32_t tag); - Header(int32_t tag, int32_t length); - Header(int32_t tag, int64_t checksum, int32_t offset, int32_t length); - virtual ~Header(); - - int32_t tag() { return tag_; } - int32_t offset() { return offset_; } - int32_t length() { return length_; } - bool offset_valid() { return offset_valid_; } - int64_t checksum() { return checksum_; } - bool checksum_valid() { return checksum_valid_; } - - private: - int32_t tag_; - int32_t offset_; - int32_t length_; - bool offset_valid_; - int64_t checksum_; - bool checksum_valid_; - - friend class TableHeaderComparator; - }; - - // Note: original version is Builder - // C++ template is not designed that way so plain old inheritance is - // chosen. - class Builder : public FontDataTable::Builder, - public FontDataTableBuilderContainer { - public: - virtual ~Builder(); - virtual Header* header() { return header_; } - virtual void NotifyPostTableBuild(FontDataTable* table); - virtual WritableFontData* GetNewData(int32_t size); - - static CALLER_ATTACH Builder* - GetBuilder(FontDataTableBuilderContainer* font_builder, - Header* header, - WritableFontData* table_data); - - protected: - // Note: original version is Font.Builder font_builder. This results in - // mutual inclusion happiness that Java solved for C++. Therefore, - // we need to avoid that happiness when we port it to C++. - Builder(FontDataTableBuilderContainer* font_builder, - Header* header, - WritableFontData* data); - Builder(FontDataTableBuilderContainer* font_builder, - Header* header, - ReadableFontData* data); - Builder(FontDataTableBuilderContainer* font_builder, - Header* header); - - private: - Ptr
header_; - }; - - class TableBasedTableBuilder : public Builder { - public: - virtual ~TableBasedTableBuilder(); - - virtual int32_t SubSerialize(WritableFontData* new_data); - virtual bool SubReadyToSerialize(); - virtual int32_t SubDataSizeToSerialize(); - virtual void SubDataSet(); - - protected: - TableBasedTableBuilder(FontDataTableBuilderContainer* font_builder, - Header* header, - WritableFontData* data); - TableBasedTableBuilder(FontDataTableBuilderContainer* font_builder, - Header* header, - ReadableFontData* data); - TableBasedTableBuilder(FontDataTableBuilderContainer* font_builder, - Header* header); - - // C++ port: renamed table() to GetTable() - virtual Table* GetTable(); - - // TODO(arthurhsu): style guide violation: protected member, need refactor - Ptr
table_; - }; - - class GenericTableBuilder : public TableBasedTableBuilder, - public RefCounted { - public: - GenericTableBuilder(FontDataTableBuilderContainer* font_builder, - Header* header, - WritableFontData* data); - virtual CALLER_ATTACH FontDataTable* SubBuildTable(ReadableFontData* data); - }; - - class ArrayElementTableBuilder : public Builder { - public: - virtual ~ArrayElementTableBuilder(); - - protected: - ArrayElementTableBuilder(FontDataTableBuilderContainer* font_builder, - Header* header, - WritableFontData* data); - ArrayElementTableBuilder(FontDataTableBuilderContainer* font_builder, - Header* header, - ReadableFontData* data); - }; - - virtual ~Table(); - virtual int64_t CalculatedChecksum(); - virtual Header* header() { return header_; } - virtual int32_t header_tag() { return header_->tag(); } - virtual int32_t header_offset() { return header_->offset(); } - virtual int32_t header_length() { return header_->length(); } - virtual int64_t header_checksum() { return header_->checksum(); } - virtual WritableFontData* GetNewData(int32_t size); - 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 Ptr TableHeaderPtr; -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; - -class TableHeaderComparator { - public: - bool operator()(const TableHeaderPtr h1, const TableHeaderPtr h2); -}; -typedef std::set TableHeaderSortedSet; - -} // namespace sfntly - -#endif // TYPOGRAPHY_FONT_SFNTLY_SRC_SFNTLY_TABLE_H_ diff --git a/sfntly/table/core/cmap_table.cc b/sfntly/table/core/cmap_table.cc new file mode 100644 index 0000000..7217265 --- /dev/null +++ b/sfntly/table/core/cmap_table.cc @@ -0,0 +1,511 @@ +/* + * 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. + */ + +// TODO(arthurhsu): IMPLEMENT: not really used and tested, need cleanup + +#include + +#include "sfntly/table/core/cmap_table.h" +#include "sfntly/table/core/name_table.h" +#include "sfntly/font.h" +#include "sfntly/port/endian.h" + +namespace sfntly { + +const int32_t CMapTable::NOTDEF = 0; + +/****************************************************************************** + * CMapTable class + ******************************************************************************/ +CMapTable::~CMapTable() {} + +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 CMapId(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)); +} + +CMapTable::CMapTable(Header* header, ReadableFontData* data) + : Table(header, data) { +} + +int32_t CMapTable::OffsetForEncodingRecord(int32_t index) { + return Offset::kEncodingRecordStart + index * Offset::kEncodingRecordSize; +} + +/****************************************************************************** + * CMapTable::CMapId class + ******************************************************************************/ +CMapTable::CMapId::CMapId(int32_t platform_id, int32_t encoding_id) + : platform_id_(platform_id), encoding_id_(encoding_id) { +} + +CMapTable::CMapId::CMapId(const CMapId& obj) + : platform_id_(obj.platform_id_), encoding_id_(obj.encoding_id_) { +} + +bool CMapTable::CMapId::operator==(const CMapTable::CMapId& obj) { + return obj.platform_id_ == platform_id_ && obj.encoding_id_ == encoding_id_; +} + +const CMapTable::CMapId& CMapTable::CMapId::operator=( + const CMapTable::CMapId& obj) { + platform_id_ = obj.platform_id_; + encoding_id_ = obj.encoding_id_; + return *this; +} + +int CMapTable::CMapId::HashCode() const { + return platform_id_ << 8 | encoding_id_; +} + +CMapTable::CMapId WINDOWS_BMP(PlatformId::kWindows, + WindowsEncodingId::kUnicodeUCS2); +CMapTable::CMapId WINDOWS_UCS4(PlatformId::kWindows, + WindowsEncodingId::kUnicodeUCS4); +CMapTable::CMapId MAC_ROMAN(PlatformId::kWindows, MacintoshEncodingId::kRoman); + +/****************************************************************************** + * CMapTable::CMapIdComparator class + ******************************************************************************/ + +bool CMapTable::CMapIdComparator::operator()(const CMapId& lhs, + const CMapId& rhs) { + return lhs.HashCode() > rhs.HashCode(); +} + +/****************************************************************************** + * 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( + FontDataTableBuilderContainer* container, + 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 = new CMapFormat0::Builder(container, data, offset, cmap_id); + break; + case CMapFormat::kFormat2: + builder = new CMapFormat0::Builder(container, data, offset, cmap_id); + break; + default: + break; + } + return builder.Detach(); +} + +CMapTable::CMap::Builder::Builder(FontDataTableBuilderContainer* container, + ReadableFontData* data, int32_t format, + const CMapId& cmap_id) + : SubTable::Builder(container, data), + format_(format), + cmap_id_(cmap_id) { +} + +CMapTable::CMap::Builder::Builder(FontDataTableBuilderContainer* container, + WritableFontData* data, int32_t format, + const CMapId& cmap_id) + : SubTable::Builder(container, data), + format_(format), + cmap_id_(cmap_id) { +} + +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() { + return InternalReadData()->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_->ReadByte(character + Offset::kFormat0GlyphIdArray); +} + +CMapTable::CMapFormat0::CMapFormat0(ReadableFontData* data, + const CMapId& cmap_id) + : CMap(data, CMapFormat::kFormat0, cmap_id) { +} + +/****************************************************************************** + * CMapTable::CMapFormat0::Builder + ******************************************************************************/ +CMapTable::CMapFormat0::Builder::Builder( + FontDataTableBuilderContainer* container, + WritableFontData* data, + int32_t offset, + const CMapId& cmap_id) + : CMapTable::CMap::Builder(container, + data ? down_cast( + data->Slice(offset, data->ReadUShort( + offset + Offset::kFormat0Length))) + : reinterpret_cast(NULL), + CMapFormat::kFormat0, cmap_id) { + // TODO(arthurhsu): FIXIT: heavy lifting and leak, need fix. +} + +CMapTable::CMapFormat0::Builder::Builder( + FontDataTableBuilderContainer* container, + ReadableFontData* data, + int32_t offset, + const CMapId& cmap_id) + : CMapTable::CMap::Builder(container, + data ? down_cast( + data->Slice(offset, data->ReadUShort( + offset + Offset::kFormat0Length))) + : reinterpret_cast(NULL), + CMapFormat::kFormat0, cmap_id) { + // TODO(arthurhsu): FIXIT: heavy lifting and leak, need fix. +} + +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::CMapFormat2::Builder + ******************************************************************************/ +CMapTable::CMapFormat2::Builder::Builder( + FontDataTableBuilderContainer* container, + WritableFontData* data, + int32_t offset, + const CMapId& cmap_id) + : CMapTable::CMap::Builder(container, + 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( + FontDataTableBuilderContainer* container, + ReadableFontData* data, + int32_t offset, + const CMapId& cmap_id) + : CMapTable::CMap::Builder(container, + 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::Iterator class + ******************************************************************************/ +CMapTable::CMapIterator::CMapIterator(CMapTable* table, 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; +} + +/****************************************************************************** + * CMapTable::Builder class + ******************************************************************************/ +CMapTable::Builder::Builder(FontDataTableBuilderContainer* font_builder, + Header* header, + WritableFontData* data) + : Table::ArrayElementTableBuilder(font_builder, header, data) { +} + +CMapTable::Builder::Builder(FontDataTableBuilderContainer* font_builder, + Header* header, + ReadableFontData* data) + : Table::ArrayElementTableBuilder(font_builder, header, data) { +} + +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, + cmap_builders_.size()); + + int32_t index_offset = size; + size += cmap_builders_.size() * CMapTable::Offset::kEncodingRecordSize; + for (CMapBuilderMap::iterator it = cmap_builders_.begin(), + e = cmap_builders_.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 (cmap_builders_.empty()) + return false; + + // check each table + for (CMapBuilderMap::iterator it = cmap_builders_.begin(), + e = cmap_builders_.end(); it != e; ++it) { + if (!it->second->SubReadyToSerialize()) + return false; + } + return true; +} + +int32_t CMapTable::Builder::SubDataSizeToSerialize() { + if (cmap_builders_.empty()) + return 0; + + bool variable = false; + int32_t size = CMapTable::Offset::kEncodingRecordStart + + cmap_builders_.size() * CMapTable::Offset::kEncodingRecordSize; + + // calculate size of each table + for (CMapBuilderMap::iterator it = cmap_builders_.begin(), + e = cmap_builders_.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() { + cmap_builders_.clear(); + Table::Builder::set_model_changed(false); +} + +CALLER_ATTACH FontDataTable* + CMapTable::Builder::SubBuildTable(ReadableFontData* data) { + FontDataTablePtr table = new CMapTable(header(), data); + return table.Detach(); +} + +CALLER_ATTACH CMapTable::CMap::Builder* CMapTable::Builder::CMapBuilder( + FontDataTableBuilderContainer* container, ReadableFontData* data, + int32_t index) { + if (index < 0 || index > NumCMaps(data)) + return NULL; + + int32_t record_offset = Offset::kEncodingRecordOffset + index * + Offset::kEncodingRecordSize; + int32_t platform_id = + data->ReadUShort(Offset::kEncodingRecordPlatformId + record_offset); + int32_t encoding_id = + data->ReadUShort(Offset::kEncodingRecordEncodingId + record_offset); + CMapId cmap_id(platform_id, encoding_id); + int32_t offset = + data->ReadULongAsInt(Offset::kEncodingRecordOffset + record_offset); + return CMap::Builder::GetBuilder(container, data, offset, cmap_id); +} + +int32_t CMapTable::Builder::NumCMaps(ReadableFontData* data) { + if (data == NULL) { + return 0; + } + return data->ReadUShort(Offset::kNumTables); +} + +} // namespace sfntly diff --git a/sfntly/table/core/cmap_table.h b/sfntly/table/core/cmap_table.h new file mode 100644 index 0000000..76b4266 --- /dev/null +++ b/sfntly/table/core/cmap_table.h @@ -0,0 +1,447 @@ +/* + * 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. + */ + +// TODO(arthurhsu): IMPLEMENT: not really used and tested, need cleanup +#ifndef SFNTLY_CPP_SRC_SFNTLY_TABLE_CORE_CMAP_TABLE_H_ +#define SFNTLY_CPP_SRC_SFNTLY_TABLE_CORE_CMAP_TABLE_H_ + +#include +#include + +#include "sfntly/port/refcount.h" +#include "sfntly/table/table.h" +#include "sfntly/table/subtable.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 Table, public RefCounted { +public: + // CMapTable::CMapId + class CMapId { + public: + CMapId(int32_t platform_id, int32_t encoding_id); + CMapId(const CMapId& obj); + + int32_t platform_id() { return platform_id_; } + int32_t encoding_id() { return encoding_id_; } + + bool operator==(const CMapId& obj); + const CMapId& operator=(const CMapId& obj); + int HashCode() const; + + friend class CMapIdComparator; + + private: + int32_t platform_id_; + int32_t 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); + }; + + // 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(CMapId cmap_id) = 0; + // Make gcc -Wnon-virtual-dtor happy. + virtual ~CMapFilter() {} + }; + + // 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 implements {@code Iterable} 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(FontDataTableBuilderContainer* container, + ReadableFontData* data, + int32_t offset, + 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(); } + + protected: + Builder(FontDataTableBuilderContainer* container, + ReadableFontData* data, + int32_t format, + const CMapId& cmap_id); + Builder(FontDataTableBuilderContainer* container, + 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_; + + friend class CMapTable::Builder; + }; + + CMap(ReadableFontData* data, int32_t format, const CMapId& cmap_id); + virtual ~CMap(); + 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 CMapBuilderPtr; + typedef std::map CMapBuilderMap; + + // A cmap format 0 sub table + class CMapFormat0 : public CMap, public RefCounted { + public: + // CMapTable::CMapFormat0::Builder + class Builder : public CMap::Builder, + public RefCounted { + public: + Builder(FontDataTableBuilderContainer* container, + ReadableFontData* data, + int32_t offset, + const CMapId& cmap_id); + Builder(FontDataTableBuilderContainer* container, + WritableFontData* data, + int32_t offset, + const CMapId& cmap_id); + virtual ~Builder(); + + protected: + virtual CALLER_ATTACH FontDataTable* + SubBuildTable(ReadableFontData* data); + }; + + virtual ~CMapFormat0(); + virtual int32_t Language(); + virtual int32_t GlyphId(int32_t character); + + 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(FontDataTableBuilderContainer* container, + ReadableFontData* data, + int32_t offset, + const CMapId& cmap_id); + Builder(FontDataTableBuilderContainer* container, + WritableFontData* data, + int32_t offset, + const CMapId& cmap_id); + virtual ~Builder(); + + protected: + virtual CALLER_ATTACH FontDataTable* + SubBuildTable(ReadableFontData* data); + }; + + virtual ~CMapFormat2(); + 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); + + 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); + }; + + // CMapTable::Builder + class Builder : public Table::ArrayElementTableBuilder, + public RefCounted { + public: + // Constructor scope altered to public because C++ does not allow base + // class to instantiate derived class with protected constructors. + Builder(FontDataTableBuilderContainer* font_builder, + Header* header, + WritableFontData* data); + Builder(FontDataTableBuilderContainer* font_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); + + protected: + static CALLER_ATTACH CMap::Builder* + CMapBuilder(FontDataTableBuilderContainer* container, + ReadableFontData* data, + int32_t index); + + private: + static int32_t NumCMaps(ReadableFontData* data); + + int32_t version_; + CMapBuilderMap cmap_builders_; + }; + + virtual ~CMapTable(); + + // 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); + + private: + static const int32_t NOTDEF; + + // 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, + + // 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 + }; + }; + + class CMapIterator { + public: + // If filter is NULL, filter through all tables. + CMapIterator(CMapTable* table, CMapFilter* filter); + bool HasNext(); + CMap* Next(); + + private: + int32_t table_index_; + CMapFilter* filter_; + CMapTable* table_; + }; + + 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. + int32_t OffsetForEncodingRecord(int32_t index); +}; +typedef std::vector CMapIdList; +typedef Ptr CMapTablePtr; + +} // namespace sfntly + +#endif // SFNTLY_CPP_SRC_SFNTLY_TABLE_CORE_CMAP_TABLE_H_ diff --git a/sfntly/table/core/font_header_table.cc b/sfntly/table/core/font_header_table.cc new file mode 100644 index 0000000..da19258 --- /dev/null +++ b/sfntly/table/core/font_header_table.cc @@ -0,0 +1,259 @@ +/* + * 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(FontDataTableBuilderContainer* font_builder, + Header* header, WritableFontData* data) : + Table::TableBasedTableBuilder(font_builder, header, data) { +} + +FontHeaderTable::Builder::Builder(FontDataTableBuilderContainer* font_builder, + Header* header, ReadableFontData* data) : + Table::TableBasedTableBuilder(font_builder, 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); +} + +} // namespace sfntly diff --git a/sfntly/table/core/font_header_table.h b/sfntly/table/core/font_header_table.h new file mode 100644 index 0000000..343e62c --- /dev/null +++ b/sfntly/table/core/font_header_table.h @@ -0,0 +1,167 @@ +/* + * 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" + +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 Table::TableBasedTableBuilder, + public RefCounted { + public: + // Constructor scope altered to public because C++ does not allow base + // class to instantiate derived class with protected constructors. + Builder(FontDataTableBuilderContainer* font_builder, Header* header, + WritableFontData* data); + Builder(FontDataTableBuilderContainer* font_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); + }; + + 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/sfntly/table/core/horizontal_header_table.cc b/sfntly/table/core/horizontal_header_table.cc new file mode 100644 index 0000000..52b0de2 --- /dev/null +++ b/sfntly/table/core/horizontal_header_table.cc @@ -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. + */ + +#include "sfntly/table/core/horizontal_header_table.h" + +namespace sfntly { +/****************************************************************************** + * HorizontalHeaderTable class + ******************************************************************************/ +HorizontalHeaderTable:: ~HorizontalHeaderTable() {} + +int32_t HorizontalHeaderTable::Version() { + 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( + FontDataTableBuilderContainer* font_builder, + Header* header, + WritableFontData* data) + : Table::TableBasedTableBuilder(font_builder, header, data) { +} + +HorizontalHeaderTable::Builder::Builder( + FontDataTableBuilderContainer* font_builder, + Header* header, + ReadableFontData* data) + : Table::TableBasedTableBuilder(font_builder, header, data) { +} + +HorizontalHeaderTable::Builder::~Builder() {} + +CALLER_ATTACH FontDataTable* + HorizontalHeaderTable::Builder::SubBuildTable(ReadableFontData* data) { + FontDataTablePtr table = new HorizontalHeaderTable(header(), data); + return table.Detach(); +} + +int32_t HorizontalHeaderTable::Builder::Version() { + return InternalReadData()->ReadFixed(Offset::kVersion); +} + +void HorizontalHeaderTable::Builder::SetVersion(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/sfntly/table/core/horizontal_header_table.h b/sfntly/table/core/horizontal_header_table.h new file mode 100644 index 0000000..3a3eb6f --- /dev/null +++ b/sfntly/table/core/horizontal_header_table.h @@ -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. + */ + +#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" + +namespace sfntly { + +class HorizontalHeaderTable : public Table, + public RefCounted { + public: + class Builder : public Table::TableBasedTableBuilder, + public RefCounted { + public: + // Constructor scope altered to public because C++ does not allow base + // class to instantiate derived class with protected constructors. + Builder(FontDataTableBuilderContainer* font_builder, + Header* header, + WritableFontData* data); + Builder(FontDataTableBuilderContainer* font_builder, + Header* header, + ReadableFontData* data); + virtual ~Builder(); + virtual CALLER_ATTACH FontDataTable* SubBuildTable(ReadableFontData* data); + + int32_t Version(); + void SetVersion(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 Version(); + 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/sfntly/table/core/horizontal_metrics_table.cc b/sfntly/table/core/horizontal_metrics_table.cc new file mode 100644 index 0000000..b2463b9 --- /dev/null +++ b/sfntly/table/core/horizontal_metrics_table.cc @@ -0,0 +1,151 @@ +/* + * 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) + return 0; +#else + throw IndexOutOfBoundException(); +#endif + } + 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) + return 0; +#else + throw IndexOutOfBoundException(); +#endif + } + 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) + return 0; +#else + throw IndexOutOfBoundException(); +#endif + } + 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) + : Table(header, data) { +} + +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( + FontDataTableBuilderContainer* font_builder, + Header* header, + WritableFontData* data) + : Table::TableBasedTableBuilder(font_builder, header, data) { + Init(); +} + +HorizontalMetricsTable::Builder::Builder( + FontDataTableBuilderContainer* font_builder, + Header* header, + ReadableFontData* data) + : Table::TableBasedTableBuilder(font_builder, header, data) { + Init(); +} + +HorizontalMetricsTable::Builder::~Builder() {} + +CALLER_ATTACH FontDataTable* + HorizontalMetricsTable::Builder::SubBuildTable(ReadableFontData* data) { + FontDataTablePtr table = + new HorizontalMetricsTable(header(), data, num_hmetrics_, num_glyphs_); + return table.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; +} + +void HorizontalMetricsTable::Builder::Init() { + num_hmetrics_ = -1; + num_glyphs_ = -1; +} + +} // namespace sfntly diff --git a/sfntly/table/core/horizontal_metrics_table.h b/sfntly/table/core/horizontal_metrics_table.h new file mode 100644 index 0000000..aa3fa65 --- /dev/null +++ b/sfntly/table/core/horizontal_metrics_table.h @@ -0,0 +1,89 @@ +/* + * 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" + +namespace sfntly { + +class HorizontalMetricsTable : public Table, + public RefCounted { + public: + class Builder : public Table::TableBasedTableBuilder, + public RefCounted { + public: + // Constructor scope altered to public because C++ does not allow base + // class to instantiate derived class with protected constructors. + Builder(FontDataTableBuilderContainer* font_builder, + Header* header, + WritableFontData* data); + Builder(FontDataTableBuilderContainer* font_builder, + Header* header, + ReadableFontData* data); + virtual ~Builder(); + + virtual CALLER_ATTACH FontDataTable* SubBuildTable(ReadableFontData* data); + void SetNumberOfHMetrics(int32_t num_hmetrics); + void SetNumGlyphs(int32_t num_glyphs); + + private: + void Init(); + + 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); + 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/sfntly/table/core/maximum_profile_table.cc b/sfntly/table/core/maximum_profile_table.cc new file mode 100644 index 0000000..fec508a --- /dev/null +++ b/sfntly/table/core/maximum_profile_table.cc @@ -0,0 +1,224 @@ +/* + * 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::Version() { + 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::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( + FontDataTableBuilderContainer* font_builder, + Header* header, + WritableFontData* data) + : Table::TableBasedTableBuilder(font_builder, header, data) { +} + +MaximumProfileTable::Builder::Builder( + FontDataTableBuilderContainer* font_builder, + Header* header, + ReadableFontData* data) + : Table::TableBasedTableBuilder(font_builder, header, data) { +} + +MaximumProfileTable::Builder::~Builder() {} + +CALLER_ATTACH FontDataTable* + MaximumProfileTable::Builder::SubBuildTable(ReadableFontData* data) { + FontDataTablePtr table = new MaximumProfileTable(header(), data); + return table.Detach(); +} + +int32_t MaximumProfileTable::Builder::Version() { + return InternalReadData()->ReadUShort(Offset::kVersion); +} + +void MaximumProfileTable::Builder::SetVersion(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::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/sfntly/table/core/maximum_profile_table.h b/sfntly/table/core/maximum_profile_table.h new file mode 100644 index 0000000..10ec872 --- /dev/null +++ b/sfntly/table/core/maximum_profile_table.h @@ -0,0 +1,115 @@ +/* + * 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" + +namespace sfntly { + +class MaximumProfileTable : public Table, + public RefCounted { + public: + class Builder : public Table::TableBasedTableBuilder, + public RefCounted { + public: + // Constructor scope altered to public because C++ does not allow base + // class to instantiate derived class with protected constructors. + Builder(FontDataTableBuilderContainer* font_builder, Header* header, + WritableFontData* data); + Builder(FontDataTableBuilderContainer* font_builder, Header* header, + ReadableFontData* data); + virtual ~Builder(); + + virtual CALLER_ATTACH FontDataTable* SubBuildTable(ReadableFontData* data); + + int32_t Version(); + void SetVersion(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 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 Version(); + int32_t NumGlyphs(); + int32_t MaxPoints(); + int32_t MaxContours(); + int32_t MaxCompositePoints(); + 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/sfntly/table/core/name_table.cc b/sfntly/table/core/name_table.cc new file mode 100644 index 0000000..00c4519 --- /dev/null +++ b/sfntly/table/core/name_table.cc @@ -0,0 +1,722 @@ +/* + * 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) { + Init(table, NULL); +} + +NameTable::NameEntryIterator::NameEntryIterator(NameTable* table, + NameEntryFilter* filter) { + Init(table, filter); +} + +bool NameTable::NameEntryIterator::HasNext() { + if (!filter_) { + if (name_index_ < table_->NameCount()) { + return true; + } + return false; + } + for (; name_index_ < table_->NameCount(); ++name_index_) { + if (filter_->Accept(table_->PlatformId(name_index_), + table_->EncodingId(name_index_), + table_->LanguageId(name_index_), + table_->NameId(name_index_))) { + return true; + } + } + return false; +} + +CALLER_ATTACH NameTable::NameEntry* NameTable::NameEntryIterator::Next() { + if (!HasNext()) + return NULL; + return table_->GetNameEntry(name_index_++); +} + +void NameTable::NameEntryIterator::Remove() { +#if !defined (SFNTLY_NO_EXCEPTION) + throw UnsupportedOperationException( + "Cannot remove a CMap table from an existing font."); +#endif +} + +void NameTable::NameEntryIterator::Init(NameTable* table, + NameEntryFilter* filter) { + table_ = table; + filter_ = filter; + name_index_ = 0; +} + +/****************************************************************************** + * NameTable::Builder class + ******************************************************************************/ +NameTable::Builder::Builder(FontDataTableBuilderContainer* font_builder, + Header* header, + WritableFontData* data) + : Table::ArrayElementTableBuilder(font_builder, header, data) { +} + +NameTable::Builder::Builder(FontDataTableBuilderContainer* font_builder, + Header* header, + ReadableFontData* data) + : Table::ArrayElementTableBuilder(font_builder, header, data) { +} + +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); + NameEntryIterator name_iter(table, NULL); + 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); + NameTable::NameEntryIterator* name_entry_iter = Iterator(&filter); + NameEntryPtr result; + if (name_entry_iter->HasNext()) { + result = name_entry_iter->Next(); + } + delete name_entry_iter; + return result; +} + +NameTable::NameEntryIterator* NameTable::Iterator() { + return new NameTable::NameEntryIterator(this); +} + +NameTable::NameEntryIterator* NameTable::Iterator(NameEntryFilter* filter) { + return new NameTable::NameEntryIterator(this, filter); +} + +NameTable::NameTable(Header* header, ReadableFontData* data) + : Table(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/sfntly/table/core/name_table.h b/sfntly/table/core/name_table.h new file mode 100644 index 0000000..b5a7f9a --- /dev/null +++ b/sfntly/table/core/name_table.h @@ -0,0 +1,737 @@ +/* + * 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/table/table.h" + +#if defined U_USING_ICU_NAMESPACE + U_NAMESPACE_USE +#endif + +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 Table, 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; + + 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; + + 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_; + }; + + // Mimic Java's iterator to iterate through the entries within the name table. + class NameEntryIterator { + public: + // If filter is NULL, filter through all tables. + explicit NameEntryIterator(NameTable* table); + NameEntryIterator(NameTable* table, NameEntryFilter* filter); + // Make gcc -Wnon-virtual-dtor happy. + virtual ~NameEntryIterator() {} + + virtual bool HasNext(); + virtual CALLER_ATTACH NameEntry* Next(); + virtual void Remove(); + + private: + void Init(NameTable* table, NameEntryFilter* filter); + + NameTable* table_; // Use dumb pointer since it's a composition object. + int32_t name_index_; + NameEntryFilter* filter_; + }; + + // The builder to construct name table for outputting. + class Builder : public Table::ArrayElementTableBuilder, + public RefCounted { + public: + // Constructor scope altered to public because C++ does not allow base + // class to instantiate derived class with protected constructors. + Builder(FontDataTableBuilderContainer* font_builder, Header* header, + WritableFontData* data); + Builder(FontDataTableBuilderContainer* font_builder, Header* header, + ReadableFontData* 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. + // Note: Caller delete the returned object. + virtual NameEntryIterator* Iterator(); + virtual 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/sfntly/table/core/os2_table.cc b/sfntly/table/core/os2_table.cc new file mode 100644 index 0000000..8ab435b --- /dev/null +++ b/sfntly/table/core/os2_table.cc @@ -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. + */ + +#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::Version() { + 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) { + 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) { + 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); +} + +int64_t OS2Table::UlCodePageRange() { + // TODO(arthurhsu): Possible bug point, check with stuartg. + return ((0xffffffff & UlCodePageRange2()) << 32) | + (0xffffffff & UlCodePageRange1()); +} + +int32_t OS2Table::SxHeight() { + return data_->ReadShort(Offset::kSxHeight); +} + +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(FontDataTableBuilderContainer* font_builder, + Header* header, WritableFontData* data) : + Table::TableBasedTableBuilder(font_builder, header, data) { +} + +OS2Table::Builder::~Builder() {} + +CALLER_ATTACH FontDataTable* OS2Table::Builder::SubBuildTable( + ReadableFontData* data) { + FontDataTablePtr table = new OS2Table(header(), data); + return table.Detach(); +} + +} // namespace sfntly diff --git a/sfntly/table/core/os2_table.h b/sfntly/table/core/os2_table.h new file mode 100644 index 0000000..24b6027 --- /dev/null +++ b/sfntly/table/core/os2_table.h @@ -0,0 +1,407 @@ +/* + * 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" + +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 + }; +}; + +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 { + // 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) +}; + +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 + }; +}; + +// 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; +}; + +class OS2Table : public Table, public RefCounted { + public: + class Builder : public Table::TableBasedTableBuilder, + public RefCounted { + public: + Builder(FontDataTableBuilderContainer* font_builder, Header* header, + WritableFontData* data); + virtual ~Builder(); + virtual CALLER_ATTACH FontDataTable* SubBuildTable(ReadableFontData* data); + }; + + ~OS2Table(); + + int32_t Version(); + 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() + int64_t 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, + kUlUnicodeRange1 = 42, + kUlUnicodeRange2 = 46, + kUlUnicodeRange3 = 50, + kUlUnicodeRange4 = 54, + kAchVendId = 58, + 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/sfntly/table/font_data_table.cc b/sfntly/table/font_data_table.cc new file mode 100644 index 0000000..7be3f77 --- /dev/null +++ b/sfntly/table/font_data_table.cc @@ -0,0 +1,176 @@ +/* + * 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::Length() { + return data_->Length(); +} + +int32_t FontDataTable::Padding() { + return -1; +} + +int32_t FontDataTable::DataLength() { + int32_t paddings = Padding(); + return (paddings == -1) ? Length() : Length() - paddings; +} + +int32_t FontDataTable::Serialize(OutputStream* os) { + return data_->CopyTo(os); +} + +/****************************************************************************** + * FontDataTable::Builder class + ******************************************************************************/ +CALLER_ATTACH WritableFontData* FontDataTable::Builder::Data() { + WritableFontDataPtr new_data; + if (model_changed_) { + if (!SubReadyToSerialize()) { + return NULL; + } + int32_t size = SubDataSizeToSerialize(); + new_data.Attach(container_->GetNewData(size)); + SubSerialize(new_data); + } else { + ReadableFontDataPtr data = InternalReadData(); + new_data.Attach(container_->GetNewData(data != NULL ? data->Length() : 0)); + data->CopyTo(new_data); + } + return new_data.Detach(); +} + +void FontDataTable::Builder::SetData(ReadableFontData* data) { + InternalSetData(data, true); +} + + +CALLER_ATTACH FontDataTable* FontDataTable::Builder::Build() { + ReadableFontDataPtr data = InternalReadData(); + if (model_changed_) { + // Let subclass serialize from model. + if (!SubReadyToSerialize()) { + return NULL; + } + int32_t size = SubDataSizeToSerialize(); + WritableFontDataPtr new_data; + new_data.Attach(container_->GetNewData(size)); + SubSerialize(new_data); + data = new_data; + } + + if (data == NULL) { + return NULL; // Do not build table with NULL data. + } + + FontDataTablePtr table = SubBuildTable(data); + NotifyPostTableBuild(table); + 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(container_->GetNewData(r_data_->Length())); + r_data_->CopyTo(new_data); + InternalSetData(new_data, false); + } + return w_data_.p_; +} + +CALLER_ATTACH WritableFontData* + FontDataTable::Builder::InternalNewData(int32_t size) { + return container_->GetNewData(size); +} + +FontDataTable::Builder::Builder(FontDataTableBuilderContainer* container) { + Init(container); +} + +FontDataTable::Builder::Builder(FontDataTableBuilderContainer* container, + WritableFontData* data) { + Init(container); + w_data_ = data; +} + +FontDataTable::Builder::Builder(FontDataTableBuilderContainer* container, + ReadableFontData* data) { + Init(container); + r_data_ = data; +} + +FontDataTable::Builder::~Builder() { +} + +void FontDataTable::Builder::Init(FontDataTableBuilderContainer* container) { + container_ = container; + model_changed_ = false; + data_changed_ = false; +} + +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/sfntly/table/font_data_table.h b/sfntly/table/font_data_table.h new file mode 100644 index 0000000..a2b026f --- /dev/null +++ b/sfntly/table/font_data_table.h @@ -0,0 +1,117 @@ +/* + * 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/font_data_table_builder_container.h" +#include "sfntly/port/refcount.h" + +namespace sfntly { + +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(); + CALLER_ATTACH WritableFontData* InternalNewData(int32_t size); + + bool data_changed() { return data_changed_; } + bool model_changed() { return 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(FontDataTableBuilderContainer* container); + Builder(FontDataTableBuilderContainer* container, WritableFontData* data); + Builder(FontDataTableBuilderContainer* container, ReadableFontData* data); + virtual ~Builder(); + + void Init(FontDataTableBuilderContainer* container); + + // 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); + + FontDataTableBuilderContainer* container_; // avoid circular ref-counting + WritableFontDataPtr w_data_; + ReadableFontDataPtr r_data_; + bool model_changed_; + 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 and may or may not include any padding. + virtual int32_t Length(); + + // Get the number of bytes of padding used in the table. The padding bytes are + // used to align the table length to a 4 byte boundary. + virtual int32_t Padding(); + + // Return the number of bytes of non-padded data in the table. If the padding + // is unknown or unknowable then the total number of bytes of data in the + // tables is returned. + virtual int32_t DataLength(); + + virtual int32_t Serialize(OutputStream* os); + + protected: + // 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/sfntly/table/subtable.cc b/sfntly/table/subtable.cc new file mode 100644 index 0000000..4869a97 --- /dev/null +++ b/sfntly/table/subtable.cc @@ -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. + */ + +#include "sfntly/table/subtable.h" + +namespace sfntly { +/****************************************************************************** + * SubTable class + ******************************************************************************/ +SubTable::~SubTable() {} + +SubTable::SubTable(ReadableFontData* data) + : FontDataTable(data) { +} + +/****************************************************************************** + * SubTable::Builder class + ******************************************************************************/ +SubTable::Builder::~Builder() {} + +SubTable::Builder::Builder(FontDataTableBuilderContainer* container, + WritableFontData* data) + : FontDataTable::Builder(container, data) { +} + +SubTable::Builder::Builder(FontDataTableBuilderContainer* container, + ReadableFontData* data) + : FontDataTable::Builder(container, data) { +} + +} // namespace sfntly diff --git a/sfntly/table/subtable.h b/sfntly/table/subtable.h new file mode 100644 index 0000000..c542881 --- /dev/null +++ b/sfntly/table/subtable.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_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: + Builder(FontDataTableBuilderContainer* container, WritableFontData* data); + Builder(FontDataTableBuilderContainer* container, ReadableFontData* data); + }; + + virtual ~SubTable(); + + protected: + // Note: constructor refactored in C++ to avoid heavy lifting. + // caller need to do data->Slice(offset, length) beforehand. + explicit SubTable(ReadableFontData* data); +}; + +} // namespace sfntly + +#endif // SFNTLY_CPP_SRC_SFNTLY_TABLE_SUBTABLE_H_ diff --git a/sfntly/table/table.cc b/sfntly/table/table.cc new file mode 100644 index 0000000..568f889 --- /dev/null +++ b/sfntly/table/table.cc @@ -0,0 +1,279 @@ +/* + * 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.h" + +#include "sfntly/font.h" +#include "sfntly/tag.h" +#include "sfntly/table/core/cmap_table.h" +#include "sfntly/table/core/font_header_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/truetype/glyph_table.h" +#include "sfntly/table/truetype/loca_table.h" + +namespace sfntly { + +/****************************************************************************** + * Table class + ******************************************************************************/ +Table::~Table() {} + +int64_t Table::CalculatedChecksum() { + return data_->Checksum(); +} + +WritableFontData* Table::GetNewData(int32_t size) { + return font_->GetNewData(size); +} + +void Table::SetFont(Font* font) { + font_ = font; +} + +Table::Table(Header* header, ReadableFontData* data) + : FontDataTable(data) { + header_ = header; +} + +/****************************************************************************** + * Table::Header class + ******************************************************************************/ +Table::Header::Header(int32_t tag) + : tag_(tag), + offset_(0), + length_(0), + offset_valid_(false), + checksum_(0), + checksum_valid_(false) { +} + +Table::Header::Header(int32_t tag, int32_t length) + : tag_(tag), + offset_(0), + length_(length), + offset_valid_(false), + checksum_(0), + checksum_valid_(false) { +} + +Table::Header::Header(int32_t tag, + int64_t checksum, + int32_t offset, + int32_t length) + : tag_(tag), + offset_(offset), + length_(length), + offset_valid_(true), + checksum_(checksum), + checksum_valid_(true) { +} + +Table::Header::~Header() {} + +bool TableHeaderComparator::operator() (const TableHeaderPtr lhs, + const TableHeaderPtr rhs) { + return lhs->offset_ > rhs->offset_; +} + +/****************************************************************************** + * 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); + header_ = new Header(header()->tag(), + derived_table->ReadFontData()->Length()); + } +} + +WritableFontData* Table::Builder::GetNewData(int32_t size) { + UNREFERENCED_PARAMETER(size); + return InternalWriteData(); +} + +CALLER_ATTACH Table::Builder* + Table::Builder::GetBuilder(FontDataTableBuilderContainer* font_builder, + Header* header, + WritableFontData* table_data) { + int32_t tag = header->tag(); + TableBuilderPtr builder; + 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::cmap) { + builder_raw = static_cast( + new CMapTable::Builder(font_builder, header, table_data)); + } else*/ if (tag == Tag::head) { + builder_raw = static_cast( + new FontHeaderTable::Builder(font_builder, header, table_data)); + } else if (tag == Tag::hhea) { + builder_raw = static_cast( + new HorizontalHeaderTable::Builder(font_builder, header, table_data)); + } else if (tag == Tag::hmtx) { + builder_raw = static_cast( + new HorizontalMetricsTable::Builder(font_builder, header, table_data)); + } else if (tag == Tag::maxp) { + builder_raw = static_cast( + new MaximumProfileTable::Builder(font_builder, header, table_data)); + } else if (tag == Tag::name) { + builder_raw = static_cast( + new NameTable::Builder(font_builder, header, table_data)); + } else if (tag == Tag::OS_2) { + builder_raw = static_cast( + new OS2Table::Builder(font_builder, header, table_data)); + }/* else if (tag == Tag::PostScript) { + builder_raw = static_cast( + new PostScriptTable::Builder(font_builder, header, table_data)); + } else if (tag == Tag::cvt) { + builder_raw = static_cast( + new ControlValueTable::Builder(font_builder, header, table_data)); + }*/ else if (tag == Tag::glyf) { + builder_raw = static_cast( + new GlyphTable::Builder(font_builder, header, table_data)); + } else if (tag == Tag::loca) { + builder_raw = static_cast( + new LocaTable::Builder(font_builder, header, table_data)); + }/* else if (tag == Tag::prep) { + builder_raw = static_cast( + new ControlProgramTable::Builder(font_builder, header, table_data)); + }*/ else if (tag == Tag::bhed) { + builder_raw = static_cast( + new FontHeaderTable::Builder(font_builder, header, table_data)); + } else { + builder_raw = static_cast( + new Table::GenericTableBuilder(font_builder, header, table_data)); + } + + builder = builder_raw; + return builder.Detach(); +} + +Table::Builder::Builder(FontDataTableBuilderContainer* font_builder, + Header* header, + WritableFontData* data) + : FontDataTable::Builder(font_builder, data) { + header_ = header; +} + +Table::Builder::Builder(FontDataTableBuilderContainer* font_builder, + Header* header, + ReadableFontData* data) + : FontDataTable::Builder(font_builder, data) { + header_ = header; +} + +Table::Builder::Builder(FontDataTableBuilderContainer* font_builder, + Header* header) + : FontDataTable::Builder(font_builder) { + header_ = header; +} + +/****************************************************************************** + * Table::TableBasedTableBuilder class + ******************************************************************************/ +Table::TableBasedTableBuilder::~TableBasedTableBuilder() {} + +int32_t Table::TableBasedTableBuilder::SubSerialize(WritableFontData* data) { + UNREFERENCED_PARAMETER(data); + return 0; +} + +bool Table::TableBasedTableBuilder::SubReadyToSerialize() { + return false; +} + +int32_t Table::TableBasedTableBuilder::SubDataSizeToSerialize() { + return 0; +} + +void Table::TableBasedTableBuilder::SubDataSet() { + table_ = NULL; +} + +Table::TableBasedTableBuilder::TableBasedTableBuilder( + FontDataTableBuilderContainer* font_builder, + Header* header, + WritableFontData* data) + : Builder(font_builder, header, data) { +} + +Table::TableBasedTableBuilder::TableBasedTableBuilder( + FontDataTableBuilderContainer* font_builder, + Header* header, + ReadableFontData* data) + : Builder(font_builder, header, data) { +} + +Table::TableBasedTableBuilder::TableBasedTableBuilder( + FontDataTableBuilderContainer* font_builder, + Header* header) + : Builder(font_builder, header) { +} + +Table* Table::TableBasedTableBuilder::GetTable() { + if (table_ == NULL) { + table_.Attach(down_cast(SubBuildTable(InternalReadData()))); + } + return table_; +} + +/****************************************************************************** + * Table::GenericTableBuilder class + ******************************************************************************/ +Table::GenericTableBuilder::GenericTableBuilder( + FontDataTableBuilderContainer* font_builder, + Header* header, + WritableFontData* data) + : TableBasedTableBuilder(font_builder, header, data) { +} + +CALLER_ATTACH FontDataTable* + Table::GenericTableBuilder::SubBuildTable(ReadableFontData* data) { + // Note: In C++ port, we use GenericTable, the ref-counted version of Table + UNREFERENCED_PARAMETER(data); + FontDataTablePtr table = new GenericTable(this->header(), InternalReadData()); + return table.Detach(); +} + +/****************************************************************************** + * Table::ArrayElementTableBuilder class + ******************************************************************************/ +Table::ArrayElementTableBuilder::~ArrayElementTableBuilder() {} + +Table::ArrayElementTableBuilder::ArrayElementTableBuilder( + FontDataTableBuilderContainer* font_builder, + Header* header, + WritableFontData* data) + : Builder(font_builder, header, data) { +} + +Table::ArrayElementTableBuilder::ArrayElementTableBuilder( + FontDataTableBuilderContainer* font_builder, + Header* header, + ReadableFontData* data) + : Builder(font_builder, header, data) { +} + +} // namespace sfntly diff --git a/sfntly/table/table.h b/sfntly/table/table.h new file mode 100644 index 0000000..8c8fcc8 --- /dev/null +++ b/sfntly/table/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_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" + +namespace sfntly { +class Font; +class Table : public FontDataTable, public FontDataTableBuilderContainer { + public: + class Header : public RefCounted
{ + public: + explicit Header(int32_t tag); + Header(int32_t tag, int32_t length); + Header(int32_t tag, int64_t checksum, int32_t offset, int32_t length); + virtual ~Header(); + + int32_t tag() { return tag_; } + int32_t offset() { return offset_; } + int32_t length() { return length_; } + bool offset_valid() { return offset_valid_; } + int64_t checksum() { return checksum_; } + bool checksum_valid() { return checksum_valid_; } + + private: + int32_t tag_; + int32_t offset_; + int32_t length_; + bool offset_valid_; + int64_t checksum_; + bool checksum_valid_; + + friend class TableHeaderComparator; + }; + + // Note: original version is Builder + // C++ template is not designed that way so plain old inheritance is + // chosen. + class Builder : public FontDataTable::Builder, + public FontDataTableBuilderContainer { + public: + virtual ~Builder(); + virtual Header* header() { return header_; } + virtual void NotifyPostTableBuild(FontDataTable* table); + virtual WritableFontData* GetNewData(int32_t size); + + static CALLER_ATTACH Builder* + GetBuilder(FontDataTableBuilderContainer* font_builder, + Header* header, + WritableFontData* table_data); + + protected: + // Note: original version is Font.Builder font_builder. This results in + // mutual inclusion happiness that Java solved for C++. Therefore, + // we need to avoid that happiness when we port it to C++. + Builder(FontDataTableBuilderContainer* font_builder, + Header* header, + WritableFontData* data); + Builder(FontDataTableBuilderContainer* font_builder, + Header* header, + ReadableFontData* data); + Builder(FontDataTableBuilderContainer* font_builder, + Header* header); + + private: + Ptr
header_; + }; + + class TableBasedTableBuilder : public Builder { + public: + virtual ~TableBasedTableBuilder(); + + virtual int32_t SubSerialize(WritableFontData* new_data); + virtual bool SubReadyToSerialize(); + virtual int32_t SubDataSizeToSerialize(); + virtual void SubDataSet(); + + protected: + TableBasedTableBuilder(FontDataTableBuilderContainer* font_builder, + Header* header, + WritableFontData* data); + TableBasedTableBuilder(FontDataTableBuilderContainer* font_builder, + Header* header, + ReadableFontData* data); + TableBasedTableBuilder(FontDataTableBuilderContainer* font_builder, + Header* header); + + // C++ port: renamed table() to GetTable() + virtual Table* GetTable(); + + // TODO(arthurhsu): style guide violation: protected member, need refactor + Ptr
table_; + }; + + class GenericTableBuilder : public TableBasedTableBuilder, + public RefCounted { + public: + GenericTableBuilder(FontDataTableBuilderContainer* font_builder, + Header* header, + WritableFontData* data); + virtual CALLER_ATTACH FontDataTable* SubBuildTable(ReadableFontData* data); + }; + + class ArrayElementTableBuilder : public Builder { + public: + virtual ~ArrayElementTableBuilder(); + + protected: + ArrayElementTableBuilder(FontDataTableBuilderContainer* font_builder, + Header* header, + WritableFontData* data); + ArrayElementTableBuilder(FontDataTableBuilderContainer* font_builder, + Header* header, + ReadableFontData* data); + }; + + virtual ~Table(); + virtual int64_t CalculatedChecksum(); + virtual Header* header() { return header_; } + virtual int32_t header_tag() { return header_->tag(); } + virtual int32_t header_offset() { return header_->offset(); } + virtual int32_t header_length() { return header_->length(); } + virtual int64_t header_checksum() { return header_->checksum(); } + virtual WritableFontData* GetNewData(int32_t size); + 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 Ptr TableHeaderPtr; +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; + +class TableHeaderComparator { + public: + bool operator()(const TableHeaderPtr h1, const TableHeaderPtr h2); +}; +typedef std::set TableHeaderSortedSet; + +} // namespace sfntly + +#endif // SFNTLY_CPP_SRC_SFNTLY_TABLE_TABLE_H_ diff --git a/sfntly/table/truetype/glyph_table.cc b/sfntly/table/truetype/glyph_table.cc new file mode 100644 index 0000000..ff289f3 --- /dev/null +++ b/sfntly/table/truetype/glyph_table.cc @@ -0,0 +1,667 @@ +/* + * 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(data_, offset, length); +} + +GlyphTable::GlyphTable(Header* header, ReadableFontData* data) + : Table(header, data) { +} + +/****************************************************************************** + * GlyphTable::Builder class + ******************************************************************************/ +GlyphTable::Builder::Builder(FontDataTableBuilderContainer* font_builder, + Header* header, + WritableFontData* data) + : Table::ArrayElementTableBuilder(font_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->resize(glyph_builders->size()); + 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; + } + } +} + +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()) { +#if defined (SFNTLY_NO_EXCEPTION) + return; +#else + throw IllegalStateException( + "Loca values not set - unable to parse glyph data."); +#endif + } + 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()) { + 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(ReadableFontData* data, + int32_t offset, + int32_t length) { + 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::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); +} + +int32_t GlyphTable::Glyph::Padding() { + return padding_; +} + +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(FontDataTableBuilderContainer* font_builder, + WritableFontData* data) + : SubTable::Builder(font_builder, data) { +} + +GlyphTable::Glyph::Builder::Builder(FontDataTableBuilderContainer* font_builder, + ReadableFontData* data) + : SubTable::Builder(font_builder, data) { +} + +CALLER_ATTACH GlyphTable::Glyph::Builder* + GlyphTable::Glyph::Builder::GetBuilder( + FontDataTableBuilderContainer* table_builder, + ReadableFontData* data) { + return GetBuilder(table_builder, data, 0, data->Length()); +} + +CALLER_ATTACH GlyphTable::Glyph::Builder* + GlyphTable::Glyph::Builder::GetBuilder( + FontDataTableBuilderContainer* table_builder, + ReadableFontData* data, + int32_t offset, + int32_t length) { + 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(table_builder, sliced_data); + } else { + builder = new CompositeGlyph::CompositeGlyphBuilder(table_builder, + 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) { +} + +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() { + 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); + padding_ = Length() - 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( + FontDataTableBuilderContainer* table_builder, + WritableFontData* data) + : Glyph::Builder(table_builder, data) { +} + +GlyphTable::SimpleGlyph::SimpleGlyphBuilder::SimpleGlyphBuilder( + FontDataTableBuilderContainer* table_builder, + ReadableFontData* data) + : Glyph::Builder(table_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) { + ParseData(); +} + +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::ParseData() { + 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); + } + padding_ = Length() - non_padded_data_length; + } +} + +/****************************************************************************** + * GlyphTable::CompositeGlyph::Builder + ******************************************************************************/ +GlyphTable::CompositeGlyph::CompositeGlyphBuilder::~CompositeGlyphBuilder() { +} + +GlyphTable::CompositeGlyph::CompositeGlyphBuilder::CompositeGlyphBuilder( + FontDataTableBuilderContainer* table_builder, + WritableFontData* data) + : Glyph::Builder(table_builder, data) { +} + +GlyphTable::CompositeGlyph::CompositeGlyphBuilder::CompositeGlyphBuilder( + FontDataTableBuilderContainer* table_builder, + ReadableFontData* data) + : Glyph::Builder(table_builder, data) { +} + +CALLER_ATTACH FontDataTable* + GlyphTable::CompositeGlyph::CompositeGlyphBuilder::SubBuildTable( + ReadableFontData* data) { + FontDataTablePtr table = new CompositeGlyph(data); + return table.Detach(); +} + +} // namespace sfntly diff --git a/sfntly/table/truetype/glyph_table.h b/sfntly/table/truetype/glyph_table.h new file mode 100644 index 0000000..320c522 --- /dev/null +++ b/sfntly/table/truetype/glyph_table.h @@ -0,0 +1,330 @@ +/* + * 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" + +namespace sfntly { + +struct GlyphType { + enum { + kSimple = 0, + kComposite = 1 + }; +}; + +// Note: due to the complexity of this class, the order of declaration is +// different from its Java counter part. GlyphTable::Glyph is defined +// before GlyphTable::Builder to avoid compilation errors. +class GlyphTable : public Table, 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. + Builder(FontDataTableBuilderContainer* table_builder, + WritableFontData* data); + Builder(FontDataTableBuilderContainer* table_builder, + ReadableFontData* data); + + static CALLER_ATTACH Builder* + GetBuilder(FontDataTableBuilderContainer* table_builder, + ReadableFontData* data); + static CALLER_ATTACH Builder* + GetBuilder(FontDataTableBuilderContainer* 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(ReadableFontData* data, + int32_t offset, + int32_t length); + 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 Padding(); // override FontDataTable::Padding() + + 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); + + // TODO(arthurhsu): violating C++ style guide, need refactoring. + int32_t padding_; + + 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 Table::ArrayElementTableBuilder, + public RefCounted { + public: + // Note: Constructor scope altered to public for base class to instantiate. + Builder(FontDataTableBuilderContainer* font_builder, + Header* header, + WritableFontData* data); + virtual ~Builder(); + + virtual void SetLoca(const IntegerList& loca); + virtual void GenerateLocaList(IntegerList* locas); + + // 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. + 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. + SimpleGlyphBuilder(FontDataTableBuilderContainer* table_builder, + WritableFontData* data); + SimpleGlyphBuilder(FontDataTableBuilderContainer* table_builder, + 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(); + 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 Initialize(); + void ParseData(bool fill_arrays); + int32_t FlagAsInt(int32_t index); + int32_t ContourEndPoint(int32_t contour); + + bool initialized_; + 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. + CompositeGlyphBuilder(FontDataTableBuilderContainer* table_builder, + WritableFontData* data); + CompositeGlyphBuilder(FontDataTableBuilderContainer* table_builder, + 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(); + + private: + void ParseData(); + + IntegerList contour_index_; + int32_t instruction_size_; + int32_t instructions_offset_; + }; + + 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/sfntly/table/truetype/loca_table.cc b/sfntly/table/truetype/loca_table.cc new file mode 100644 index 0000000..537e433 --- /dev/null +++ b/sfntly/table/truetype/loca_table.cc @@ -0,0 +1,250 @@ +/* + * 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::NumGlyphs() { + return num_glyphs_; +} + +int32_t LocaTable::GlyphOffset(int32_t glyph_id) { + if (glyph_id < 0 || glyph_id >= num_glyphs_) { +#if defined (SFNTLY_NO_EXCEPTION) + return 0; +#else + throw IndexOutOfBoundException("Glyph ID is out of bounds."); +#endif + } + 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) + return 0; +#else + throw IndexOutOfBoundException("Glyph ID is out of bounds."); +#endif + } + 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) + return 0; +#else + throw IndexOutOfBoundException(); +#endif + } + if (version_ == IndexToLocFormat::kShortOffset) { + return 2 * data_->ReadUShort(index * DataSize::kUSHORT); + } + return data_->ReadULongAsInt(index * DataSize::kULONG); +} + +LocaTable::LocaTable(Header* header, ReadableFontData* data) + : Table(header, data) { +} + +LocaTable::LocaTable(Header* header, + ReadableFontData* data, + int32_t version, + int32_t num_glyphs) + : Table(header, data), version_(version), num_glyphs_(num_glyphs) { +} + +/****************************************************************************** + * LocaTable::Iterator class + ******************************************************************************/ +LocaTable::LocaIterator::LocaIterator(LocaTable* table) + : index_(-1) { + table_ = table; +} + +bool LocaTable::LocaIterator::HasNext() { + return index_ <= table_->num_glyphs_; +} + +int32_t LocaTable::LocaIterator::Next() { + return table_->Loca(index_++); +} + +/****************************************************************************** + * LocaTable::Builder class + ******************************************************************************/ +LocaTable::Builder::Builder(FontDataTableBuilderContainer* font_builder, + Header* header, WritableFontData* data) : + Table::ArrayElementTableBuilder(font_builder, header, data) { + Init(); +} + +LocaTable::Builder::Builder(FontDataTableBuilderContainer* font_builder, + Header* header, ReadableFontData* data) : + Table::ArrayElementTableBuilder(font_builder, header, data) { + Init(); +} + +LocaTable::Builder::~Builder() {} + +void LocaTable::Builder::SetFormatVersion(int32_t format_version) { + format_version_ = format_version; +} + +IntegerList* LocaTable::Builder::LocaList() { + return GetLocaList(); +} + +void LocaTable::Builder::SetLocaList(IntegerList* list) { + loca_.clear(); + if (list) { + loca_ = *list; + num_glyphs_ = loca_.size(); + set_model_changed(); + } +} + +int32_t LocaTable::Builder::GlyphOffset(int32_t glyph_id) { + if (glyph_id < 0 || glyph_id > (num_glyphs_ + 1)) { +#if defined (SFNTLY_NO_EXCEPTION) + return 0; +#else + throw IndexOutOfBoundException("Glyph ID is out of bounds."); +#endif + } + return Loca(glyph_id); +} + +int32_t LocaTable::Builder::GlyphLength(int32_t glyph_id) { + if (glyph_id < 0 || glyph_id > (num_glyphs_ + 1)) { +#if defined (SFNTLY_NO_EXCEPTION) + return 0; +#else + throw IndexOutOfBoundException("Glyph ID is out of bounds."); +#endif + } + return Loca(glyph_id + 1) - Loca(glyph_id); +} + +void LocaTable::Builder::SetNumGlyphs(int32_t num_glyphs) { + num_glyphs_ = num_glyphs; +} + +int32_t LocaTable::Builder::NumGlyphs() { + if (!loca_.empty()) { + return loca_.size() - 1; + } + return num_glyphs_; +} + +void LocaTable::Builder::Revert() { + loca_.clear(); + set_model_changed(false); +} + +void LocaTable::Builder::Clear() { + GetLocaList()->clear(); +} + +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); + } + } + return 0; +} + +void LocaTable::Builder::Init() { + num_glyphs_ = -1; + format_version_ = IndexToLocFormat::kLongOffset; +} + +void LocaTable::Builder::Initialize(ReadableFontData* data) { + if (data) { + if (NumGlyphs() < 0) { +#if defined (SFNTLY_NO_EXCEPTION) + return; +#else + throw IllegalStateException("numglyphs not set on LocaTable Builder."); +#endif + } + LocaTablePtr table = + new LocaTable(header(), data, format_version_, num_glyphs_); + LocaTable::LocaIterator loca_iter(table); + while (loca_iter.HasNext()) { + loca_.push_back(loca_iter.Next()); + } + } +} + +IntegerList* LocaTable::Builder::GetLocaList() { + if (loca_.empty()) { + Initialize(InternalReadData()); + set_model_changed(); + } + return &loca_; +} + +} // namespace sfntly diff --git a/sfntly/table/truetype/loca_table.h b/sfntly/table/truetype/loca_table.h new file mode 100644 index 0000000..ce7fa44 --- /dev/null +++ b/sfntly/table/truetype/loca_table.h @@ -0,0 +1,146 @@ +/* + * 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/table/table.h" +#include "sfntly/table/core/font_header_table.h" + +namespace sfntly { + +class LocaTable : public Table, public RefCounted { + public: + // Note: different implementation than Java, caller to instantiate this class + // object directly from stack instead of calling LocaTable::iterator(). + class LocaIterator { + public: + explicit LocaIterator(LocaTable* table); + bool HasNext(); + int32_t Next(); + + private: + int32_t index_; + LocaTable* table_; // use dumb pointer since it's a composition object + }; + + class Builder : public Table::ArrayElementTableBuilder, + public RefCounted { + public: + // Constructor scope altered to public for base class to instantiate. + Builder(FontDataTableBuilderContainer* font_builder, Header* header, + WritableFontData* data); + Builder(FontDataTableBuilderContainer* font_builder, Header* header, + ReadableFontData* data); + virtual ~Builder(); + + void SetFormatVersion(int32_t format_version); + + // 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. + // 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(); + 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. + void SetNumGlyphs(int32_t num_glyphs); + int NumGlyphs(); + + void Revert(); + void Clear(); + + // 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(); + 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: + void Init(); // short hand for common code in ctors, C++ port only + void Initialize(ReadableFontData* data); // ported from Java + IntegerList* GetLocaList(); + + int32_t format_version_; // Note: IndexToLocFormat + int32_t num_glyphs_; + IntegerList loca_; + }; + + virtual ~LocaTable(); + int32_t NumGlyphs(); + + // 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); + LocaTable(Header* header, + ReadableFontData* data, + int32_t version, + int32_t num_glyphs); + + int32_t version_; // Note: IndexToLocFormat + 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/sfntly/tag.h b/sfntly/tag.h index 9a548f6..9b50a85 100644 --- a/sfntly/tag.h +++ b/sfntly/tag.h @@ -14,8 +14,8 @@ * limitations under the License. */ -#ifndef TYPOGRAPHY_FONT_SFNTLY_SRC_SFNTLY_TAG_H_ -#define TYPOGRAPHY_FONT_SFNTLY_SRC_SFNTLY_TAG_H_ +#ifndef SFNTLY_CPP_SRC_SFNTLY_TAG_H_ +#define SFNTLY_CPP_SRC_SFNTLY_TAG_H_ #include @@ -108,4 +108,4 @@ extern const size_t TRUE_TYPE_TABLE_ORDERING_SIZE; } // namespace sfntly -#endif // TYPOGRAPHY_FONT_SFNTLY_SRC_SFNTLY_TAG_H_ +#endif // SFNTLY_CPP_SRC_SFNTLY_TAG_H_ diff --git a/sfntly/tools/subsetter.cc b/sfntly/tools/subsetter.cc deleted file mode 100644 index c234a1e..0000000 --- a/sfntly/tools/subsetter.cc +++ /dev/null @@ -1,107 +0,0 @@ -/* - * 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::iterator i = font_->Tables()->begin(), - e = font_->Tables()->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) { - // The NewTableBuilder() call will alter internal state of font_builder - // AND the reference count of returned object. Therefore we need to - // dereference it. - TableBuilderPtr dereference; - dereference.Attach( - 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/sfntly/tools/subsetter/glyph_table_subsetter.cc b/sfntly/tools/subsetter/glyph_table_subsetter.cc index 7609f74..76f8624 100644 --- a/sfntly/tools/subsetter/glyph_table_subsetter.cc +++ b/sfntly/tools/subsetter/glyph_table_subsetter.cc @@ -16,9 +16,9 @@ #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/glyph_table.h" -#include "sfntly/loca_table.h" #include "sfntly/tools/subsetter/subsetter.h" #include "sfntly/port/exception_type.h" diff --git a/sfntly/tools/subsetter/glyph_table_subsetter.h b/sfntly/tools/subsetter/glyph_table_subsetter.h index 3687e27..88c7044 100644 --- a/sfntly/tools/subsetter/glyph_table_subsetter.h +++ b/sfntly/tools/subsetter/glyph_table_subsetter.h @@ -14,8 +14,8 @@ * limitations under the License. */ -#ifndef TYPOGRAPHY_FONT_SFNTLY_SRC_SFNTLY_TOOLS_SUBSETTER_GLYPH_TABLE_SUBSETTER_H_ -#define TYPOGRAPHY_FONT_SFNTLY_SRC_SFNTLY_TOOLS_SUBSETTER_GLYPH_TABLE_SUBSETTER_H_ +#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" @@ -34,4 +34,4 @@ class GlyphTableSubsetter : public TableSubsetterImpl, } // namespace sfntly -#endif // TYPOGRAPHY_FONT_SFNTLY_SRC_SFNTLY_TOOLS_SUBSETTER_GLYPH_TABLE_SUBSETTER_H_ +#endif // SFNTLY_CPP_SRC_SFNTLY_TOOLS_SUBSETTER_GLYPH_TABLE_SUBSETTER_H_ diff --git a/sfntly/tools/subsetter/subsetter.cc b/sfntly/tools/subsetter/subsetter.cc new file mode 100644 index 0000000..c234a1e --- /dev/null +++ b/sfntly/tools/subsetter/subsetter.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/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::iterator i = font_->Tables()->begin(), + e = font_->Tables()->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) { + // The NewTableBuilder() call will alter internal state of font_builder + // AND the reference count of returned object. Therefore we need to + // dereference it. + TableBuilderPtr dereference; + dereference.Attach( + 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/sfntly/tools/subsetter/subsetter.h b/sfntly/tools/subsetter/subsetter.h index df417ad..85940a7 100644 --- a/sfntly/tools/subsetter/subsetter.h +++ b/sfntly/tools/subsetter/subsetter.h @@ -14,14 +14,14 @@ * limitations under the License. */ -#ifndef TYPOGRAPHY_FONT_SFNTLY_SRC_SFNTLY_TOOLS_SUBSETTER_SUBSETTER_H_ -#define TYPOGRAPHY_FONT_SFNTLY_SRC_SFNTLY_TOOLS_SUBSETTER_SUBSETTER_H_ +#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/cmap_table.h" +#include "sfntly/table/core/cmap_table.h" #include "sfntly/tools/subsetter/table_subsetter.h" namespace sfntly { @@ -69,4 +69,4 @@ class Subsetter : public RefCounted { } // namespace sfntly -#endif // TYPOGRAPHY_FONT_SFNTLY_SRC_SFNTLY_TOOLS_SUBSETTER_SUBSETTER_H_ +#endif // SFNTLY_CPP_SRC_SFNTLY_TOOLS_SUBSETTER_SUBSETTER_H_ diff --git a/sfntly/tools/subsetter/table_subsetter.h b/sfntly/tools/subsetter/table_subsetter.h index 437705c..1336615 100644 --- a/sfntly/tools/subsetter/table_subsetter.h +++ b/sfntly/tools/subsetter/table_subsetter.h @@ -14,8 +14,8 @@ * limitations under the License. */ -#ifndef TYPOGRAPHY_FONT_SFNTLY_SRC_SFNTLY_TOOLS_SUBSETTER_TABLE_SUBSETTER_H_ -#define TYPOGRAPHY_FONT_SFNTLY_SRC_SFNTLY_TOOLS_SUBSETTER_TABLE_SUBSETTER_H_ +#ifndef SFNTLY_CPP_SRC_SFNTLY_TOOLS_SUBSETTER_TABLE_SUBSETTER_H_ +#define SFNTLY_CPP_SRC_SFNTLY_TOOLS_SUBSETTER_TABLE_SUBSETTER_H_ #include @@ -36,4 +36,4 @@ typedef std::vector TableSubsetterList; } // namespace sfntly -#endif // TYPOGRAPHY_FONT_SFNTLY_SRC_SFNTLY_TOOLS_SUBSETTER_TABLE_SUBSETTER_H_ +#endif // SFNTLY_CPP_SRC_SFNTLY_TOOLS_SUBSETTER_TABLE_SUBSETTER_H_ diff --git a/sfntly/tools/subsetter/table_subsetter_impl.h b/sfntly/tools/subsetter/table_subsetter_impl.h index 162464a..de0d9a9 100644 --- a/sfntly/tools/subsetter/table_subsetter_impl.h +++ b/sfntly/tools/subsetter/table_subsetter_impl.h @@ -14,8 +14,8 @@ * limitations under the License. */ -#ifndef TYPOGRAPHY_FONT_SFNTLY_SRC_SFNTLY_TOOLS_SUBSETTER_TABLE_SUBSETTER_IMPL_H_ -#define TYPOGRAPHY_FONT_SFNTLY_SRC_SFNTLY_TOOLS_SUBSETTER_TABLE_SUBSETTER_IMPL_H_ +#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" @@ -34,4 +34,4 @@ class TableSubsetterImpl : public TableSubsetter { } // namespace sfntly -#endif // TYPOGRAPHY_FONT_SFNTLY_SRC_SFNTLY_TOOLS_SUBSETTER_TABLE_SUBSETTER_IMPL_H_ +#endif // SFNTLY_CPP_SRC_SFNTLY_TOOLS_SUBSETTER_TABLE_SUBSETTER_IMPL_H_ diff --git a/test/font_data_test.cc b/test/font_data_test.cc index ecf9a62..4b0db64 100644 --- a/test/font_data_test.cc +++ b/test/font_data_test.cc @@ -46,35 +46,35 @@ const int32_t kSearchTestPairsLength = 15; const int32_t SEARCH_TEST_OFFSETS[][5] = { // lower[], upper[] { (kLowerByteArrayForSearchingLength + kUpperByteArrayForSearchingLength) - * sizeof(ushort), + * DataSize::kUSHORT, 0, - sizeof(ushort), - kLowerByteArrayForSearchingLength * sizeof(ushort), - sizeof(ushort) }, + DataSize::kUSHORT, + kLowerByteArrayForSearchingLength * DataSize::kUSHORT, + DataSize::kUSHORT }, // {lower, upper} [] { (kLowerByteArrayForSearchingLength + kUpperByteArrayForSearchingLength) - * sizeof(ushort), + * DataSize::kUSHORT, 0, - 2 * sizeof(ushort), - sizeof(ushort), - 2 * sizeof(ushort) }, + 2 * DataSize::kUSHORT, + DataSize::kUSHORT, + 2 * DataSize::kUSHORT }, // upper[], lower[] { (kLowerByteArrayForSearchingLength + kUpperByteArrayForSearchingLength) - * sizeof(ushort), - kLowerByteArrayForSearchingLength * sizeof(ushort), - sizeof(ushort), + * DataSize::kUSHORT, + kLowerByteArrayForSearchingLength * DataSize::kUSHORT, + DataSize::kUSHORT, 0, - sizeof(ushort) }, + DataSize::kUSHORT }, // {upper, lower} [] { (kLowerByteArrayForSearchingLength + kUpperByteArrayForSearchingLength) - * sizeof(ushort), - sizeof(ushort), - 2 * sizeof(ushort), + * DataSize::kUSHORT, + DataSize::kUSHORT, + 2 * DataSize::kUSHORT, 0, - 2 * sizeof(ushort) } + 2 * DataSize::kUSHORT } }; const int32_t kSearchTestOffsetLength = 4; diff --git a/test/font_parsing_test.cc b/test/font_parsing_test.cc index 3dcbda2..2e35c20 100644 --- a/test/font_parsing_test.cc +++ b/test/font_parsing_test.cc @@ -16,13 +16,13 @@ #include "gtest/gtest.h" +#include "sfntly/data/font_input_stream.h" +#include "sfntly/data/memory_byte_array.h" #include "sfntly/font.h" #include "sfntly/font_factory.h" -#include "sfntly/font_header_table.h" +#include "sfntly/table/core/font_header_table.h" +#include "sfntly/table/table.h" #include "sfntly/tag.h" -#include "sfntly/table.h" -#include "sfntly/data/font_input_stream.h" -#include "sfntly/data/memory_byte_array.h" #include "sfntly/port/file_input_stream.h" #include "test/test_data.h" #include "test/test_font_utils.h" diff --git a/test/font_subsetter.h b/test/font_subsetter.h index 6d001eb..07b1b5b 100644 --- a/test/font_subsetter.h +++ b/test/font_subsetter.h @@ -15,8 +15,8 @@ */ // File is originally from Chromium third_party/sfntly/src/subsetter. // Use as test case in sfntly so that problems can be caught in upstream early. -#ifndef TYPOGRAPHY_FONT_SFNTLY_SRC_TEST_FONT_SUBSETTER_H_ -#define TYPOGRAPHY_FONT_SFNTLY_SRC_TEST_FONT_SUBSETTER_H_ +#ifndef SFNTLY_CPP_SRC_TEST_FONT_SUBSETTER_H_ +#define SFNTLY_CPP_SRC_TEST_FONT_SUBSETTER_H_ #include @@ -48,4 +48,4 @@ class SfntlyWrapper { unsigned char** output_buffer); }; -#endif // TYPOGRAPHY_FONT_SFNTLY_SRC_TEST_FONT_SUBSETTER_H_ +#endif // SFNTLY_CPP_SRC_TEST_FONT_SUBSETTER_H_ diff --git a/test/name_editing_test.cc b/test/name_editing_test.cc index 90076cf..ce12cd3 100644 --- a/test/name_editing_test.cc +++ b/test/name_editing_test.cc @@ -21,11 +21,11 @@ #include #include "gtest/gtest.h" +#include "sfntly/data/memory_byte_array.h" #include "sfntly/font.h" #include "sfntly/font_factory.h" -#include "sfntly/name_table.h" +#include "sfntly/table/core/name_table.h" #include "sfntly/tag.h" -#include "sfntly/data/memory_byte_array.h" #include "sfntly/port/memory_output_stream.h" #include "test/test_data.h" #include "test/test_font_utils.h" diff --git a/test/otf_basic_editing_test.cc b/test/otf_basic_editing_test.cc index 1db2d1e..32ba248 100644 --- a/test/otf_basic_editing_test.cc +++ b/test/otf_basic_editing_test.cc @@ -17,7 +17,7 @@ #include "gtest/gtest.h" #include "sfntly/font.h" #include "sfntly/font_factory.h" -#include "sfntly/font_header_table.h" +#include "sfntly/table/core/font_header_table.h" #include "sfntly/tag.h" #include "sfntly/data/memory_byte_array.h" #include "sfntly/port/endian.h" diff --git a/test/serialization_test.h b/test/serialization_test.h index 0718f32..8996793 100644 --- a/test/serialization_test.h +++ b/test/serialization_test.h @@ -14,10 +14,10 @@ * limitations under the License. */ -#ifndef TYPOGRAPHY_FONT_SFNTLY_SRC_TEST_SERIALIZATION_TEST_H_ -#define TYPOGRAPHY_FONT_SFNTLY_SRC_TEST_SERIALIZATION_TEST_H_ +#ifndef SFNTLY_CPP_SRC_TEST_SERIALIZATION_TEST_H_ +#define SFNTLY_CPP_SRC_TEST_SERIALIZATION_TEST_H_ -#include "sfntly/table.h" +#include "sfntly/table/table.h" namespace sfntly { @@ -31,4 +31,4 @@ bool VerifyOS_2(Table* original, Table* target); } // namespace sfntly -#endif // TYPOGRAPHY_FONT_SFNTLY_SRC_TEST_SERIALIZATION_TEST_H_ +#endif // SFNTLY_CPP_SRC_TEST_SERIALIZATION_TEST_H_ diff --git a/test/subsetter_impl.cc b/test/subsetter_impl.cc index 7999f50..ea886c0 100644 --- a/test/subsetter_impl.cc +++ b/test/subsetter_impl.cc @@ -23,9 +23,9 @@ #include #include -#include "sfntly/glyph_table.h" -#include "sfntly/loca_table.h" -#include "sfntly/name_table.h" +#include "sfntly/table/core/name_table.h" +#include "sfntly/table/truetype/glyph_table.h" +#include "sfntly/table/truetype/loca_table.h" #include "sfntly/tag.h" #include "sfntly/data/memory_byte_array.h" #include "sfntly/port/memory_output_stream.h" diff --git a/test/subsetter_impl.h b/test/subsetter_impl.h index 6ce0aee..f3a8bf3 100644 --- a/test/subsetter_impl.h +++ b/test/subsetter_impl.h @@ -16,8 +16,8 @@ // File is originally from Chromium third_party/sfntly/src/subsetter. // Use as test case in sfntly so that problems can be caught in upstream early. -#ifndef TYPOGRAPHY_FONT_SFNTLY_SRC_TEST_SUBSETTER_IMPL_H_ -#define TYPOGRAPHY_FONT_SFNTLY_SRC_TEST_SUBSETTER_IMPL_H_ +#ifndef SFNTLY_CPP_SRC_TEST_SUBSETTER_IMPL_H_ +#define SFNTLY_CPP_SRC_TEST_SUBSETTER_IMPL_H_ #include "sfntly/font.h" #include "sfntly/font_factory.h" @@ -72,4 +72,4 @@ class SubsetterImpl { } // namespace sfntly -#endif // TYPOGRAPHY_FONT_SFNTLY_SRC_TEST_SUBSETTER_IMPL_H_ +#endif // SFNTLY_CPP_SRC_TEST_SUBSETTER_IMPL_H_ diff --git a/test/test_data.h b/test/test_data.h index b6aa4ea..1b50549 100644 --- a/test/test_data.h +++ b/test/test_data.h @@ -14,8 +14,8 @@ * limitations under the License. */ -#ifndef TYPOGRAPHY_FONT_SFNTLY_SRC_TEST_TEST_DATA_H_ -#define TYPOGRAPHY_FONT_SFNTLY_SRC_TEST_TEST_DATA_H_ +#ifndef SFNTLY_CPP_SRC_TEST_TEST_DATA_H_ +#define SFNTLY_CPP_SRC_TEST_TEST_DATA_H_ #include "sfntly/tag.h" @@ -42,4 +42,4 @@ extern const size_t SAMPLE_OTF_SIZE; } // namespace sfntly -#endif // TYPOGRAPHY_FONT_SFNTLY_SRC_TEST_TEST_DATA_H_ +#endif // SFNTLY_CPP_SRC_TEST_TEST_DATA_H_ diff --git a/test/test_font_utils.h b/test/test_font_utils.h index 21296f1..b8a93b9 100644 --- a/test/test_font_utils.h +++ b/test/test_font_utils.h @@ -14,8 +14,8 @@ * limitations under the License. */ -#ifndef TYPOGRAPHY_FONT_SFNTLY_SRC_TEST_TEST_FONT_UTILS_H_ -#define TYPOGRAPHY_FONT_SFNTLY_SRC_TEST_TEST_FONT_UTILS_H_ +#ifndef SFNTLY_CPP_SRC_TEST_TEST_FONT_UTILS_H_ +#define SFNTLY_CPP_SRC_TEST_TEST_FONT_UTILS_H_ #include "sfntly/font.h" #include "sfntly/font_factory.h" @@ -38,4 +38,4 @@ void HexDump(const unsigned char* byte_data, size_t length); } // namespace sfntly -#endif // TYPOGRAPHY_FONT_SFNTLY_SRC_TEST_TEST_FONT_UTILS_H_ +#endif // SFNTLY_CPP_SRC_TEST_TEST_FONT_UTILS_H_ diff --git a/test/test_utils.h b/test/test_utils.h index 4d692e1..af3ffd6 100644 --- a/test/test_utils.h +++ b/test/test_utils.h @@ -14,8 +14,8 @@ * limitations under the License. */ -#ifndef TYPOGRAPHY_FONT_SFNTLY_SRC_TEST_TEST_UTILS_H_ -#define TYPOGRAPHY_FONT_SFNTLY_SRC_TEST_TEST_UTILS_H_ +#ifndef SFNTLY_CPP_SRC_TEST_TEST_UTILS_H_ +#define SFNTLY_CPP_SRC_TEST_TEST_UTILS_H_ // Must include this before ICU to avoid stdint redefinition issue. #include "sfntly/port/type.h" @@ -107,4 +107,4 @@ class TestUtils { static const char* Extension(const char* file_path); }; } -#endif // TYPOGRAPHY_FONT_SFNTLY_SRC_TEST_TEST_UTILS_H_ +#endif // SFNTLY_CPP_SRC_TEST_TEST_UTILS_H_ diff --git a/test/verify_glyf.cc b/test/verify_glyf.cc index f13f5ce..ff89638 100644 --- a/test/verify_glyf.cc +++ b/test/verify_glyf.cc @@ -16,7 +16,7 @@ #include "gtest/gtest.h" #include "sfntly/font.h" -#include "sfntly/glyph_table.h" +#include "sfntly/table/truetype/glyph_table.h" #include "test/serialization_test.h" namespace sfntly { diff --git a/test/verify_hhea.cc b/test/verify_hhea.cc index 537b224..491238a 100644 --- a/test/verify_hhea.cc +++ b/test/verify_hhea.cc @@ -16,7 +16,7 @@ #include "gtest/gtest.h" #include "sfntly/font.h" -#include "sfntly/horizontal_header_table.h" +#include "sfntly/table/core/horizontal_header_table.h" #include "test/serialization_test.h" namespace sfntly { diff --git a/test/verify_hmtx.cc b/test/verify_hmtx.cc index 000597a..67ea6a3 100644 --- a/test/verify_hmtx.cc +++ b/test/verify_hmtx.cc @@ -16,7 +16,7 @@ #include "gtest/gtest.h" #include "sfntly/font.h" -#include "sfntly/horizontal_metrics_table.h" +#include "sfntly/table/core/horizontal_metrics_table.h" #include "test/serialization_test.h" namespace sfntly { diff --git a/test/verify_loca.cc b/test/verify_loca.cc index a1f14c2..0e36ce8 100644 --- a/test/verify_loca.cc +++ b/test/verify_loca.cc @@ -16,7 +16,7 @@ #include "gtest/gtest.h" #include "sfntly/font.h" -#include "sfntly/loca_table.h" +#include "sfntly/table/truetype/loca_table.h" #include "test/serialization_test.h" namespace sfntly { diff --git a/test/verify_maxp.cc b/test/verify_maxp.cc index d789fdb..3bd4490 100644 --- a/test/verify_maxp.cc +++ b/test/verify_maxp.cc @@ -16,7 +16,7 @@ #include "gtest/gtest.h" #include "sfntly/font.h" -#include "sfntly/maximum_profile_table.h" +#include "sfntly/table/core/maximum_profile_table.h" #include "test/serialization_test.h" namespace sfntly { diff --git a/test/verify_name.cc b/test/verify_name.cc index d55d924..fa56de5 100644 --- a/test/verify_name.cc +++ b/test/verify_name.cc @@ -16,7 +16,7 @@ #include "gtest/gtest.h" #include "sfntly/font.h" -#include "sfntly/name_table.h" +#include "sfntly/table/core/name_table.h" #include "test/serialization_test.h" namespace sfntly { diff --git a/test/verify_os2.cc b/test/verify_os2.cc index e604be9..8f6b9ed 100644 --- a/test/verify_os2.cc +++ b/test/verify_os2.cc @@ -16,7 +16,7 @@ #include "gtest/gtest.h" #include "sfntly/font.h" -#include "sfntly/os2_table.h" +#include "sfntly/table/core/os2_table.h" #include "test/serialization_test.h" namespace sfntly { -- cgit v1.2.3 From 6c4f92bcc799598f6fcba4b3c7d4d549da9a8491 Mon Sep 17 00:00:00 2001 From: "dfilimon@google.com" Date: Mon, 29 Aug 2011 17:13:42 +0000 Subject: Modified NewTableBuilder so it would no longer require CALLER_ATTACH. git-svn-id: http://sfntly.googlecode.com/svn/trunk/cpp/src@60 672e30a5-4c29-85ac-ac6d-611c735e0a51 --- sfntly/font.cc | 32 +++++++++++++++++-------- sfntly/font.h | 6 ++--- sfntly/tools/subsetter/glyph_table_subsetter.cc | 12 +++++----- sfntly/tools/subsetter/subsetter.cc | 7 +----- test/subsetter_impl.cc | 17 ++++--------- 5 files changed, 37 insertions(+), 37 deletions(-) diff --git a/sfntly/font.cc b/sfntly/font.cc index 14f1505..d66c9f6 100644 --- a/sfntly/font.cc +++ b/sfntly/font.cc @@ -16,9 +16,12 @@ #include "sfntly/font.h" +#include + #include #include #include +#include #include #include "sfntly/data/font_input_stream.h" @@ -280,19 +283,21 @@ Table::Builder* Font::Builder::GetTableBuilder(int32_t tag) { return NULL; } -CALLER_ATTACH Table::Builder* Font::Builder::NewTableBuilder(int32_t tag) { +Table::Builder* Font::Builder::NewTableBuilder(int32_t tag) { TableHeaderPtr header = new Table::Header(tag); - TableBuilderPtr builder = Table::Builder::GetBuilder(this, header, NULL); + TableBuilderPtr builder; + builder.Attach(Table::Builder::GetBuilder(this, header, NULL)); table_builders_.insert(TableBuilderEntry(header->tag(), builder)); return builder; } -CALLER_ATTACH Table::Builder* - Font::Builder::NewTableBuilder(int32_t tag, ReadableFontData* src_data) { +Table::Builder* Font::Builder::NewTableBuilder(int32_t tag, + ReadableFontData* src_data) { WritableFontDataPtr data; data.Attach(GetNewGrowableData(src_data)); TableHeaderPtr header = new Table::Header(tag); - TableBuilderPtr builder = Table::Builder::GetBuilder(this, header, data); + TableBuilderPtr builder; + builder.Attach(Table::Builder::GetBuilder(this, header, data)); table_builders_.insert(TableBuilderEntry(tag, builder)); return builder; } @@ -369,7 +374,7 @@ void Font::Builder::BuildTablesFromBuilders(TableBuilderMap* builder_map, // Now build all the tables. for (TableBuilderMap::iterator builder = builder_map->begin(), builder_end = builder_map->end(); - builder != builder_end; ++builder) { + builder != builder_end; ++builder) { TablePtr table; if (builder->second && builder->second->ReadyToBuild()) { #if !defined (SFNTLY_NO_EXCEPTION) @@ -379,19 +384,26 @@ void Font::Builder::BuildTablesFromBuilders(TableBuilderMap* builder_map, #if !defined (SFNTLY_NO_EXCEPTION) } catch(IOException& e) { std::string builder_string = "Unable to build table - "; - builder_string += typeid(builder->second).name(); - builder_string += e.what(); + char *table_name = TagToString(builder->first); + builder_string += table_name; + delete[] table_name; throw RuntimeException(builder_string.c_str()); } #endif } if (table == NULL) { + std::string builder_string = "Unable to build table - "; + char *table_name = TagToString(builder->first); + builder_string += table_name; + delete[] table_name; #if defined (SFNTLY_NO_EXCEPTION) +#if defined (SFNTLY_DEBUG) + fprintf(stderr, "Aborting table construction: %s\n", + builder_string.c_str()); +#endif table_map->clear(); return; #else - std::string builder_string = "Unable to build table - "; - builder_string += typeid(builder->second).name(); throw RuntimeException(builder_string.c_str()); #endif } diff --git a/sfntly/font.h b/sfntly/font.h index 72b10ac..2badece 100644 --- a/sfntly/font.h +++ b/sfntly/font.h @@ -150,9 +150,9 @@ class Font : public RefCounted { // 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 CALLER_ATTACH Table::Builder* NewTableBuilder(int32_t tag); - virtual CALLER_ATTACH Table::Builder* - NewTableBuilder(int32_t tag, ReadableFontData* src_data); + virtual Table::Builder* NewTableBuilder(int32_t tag); + virtual Table::Builder* NewTableBuilder(int32_t tag, + ReadableFontData* src_data); virtual TableBuilderMap* table_builders() { return &table_builders_; } virtual void TableBuilderTags(IntegerSet* key_set); // Note: different from Java: we don't return object in removeTableBuilder diff --git a/sfntly/tools/subsetter/glyph_table_subsetter.cc b/sfntly/tools/subsetter/glyph_table_subsetter.cc index 76f8624..644e137 100644 --- a/sfntly/tools/subsetter/glyph_table_subsetter.cc +++ b/sfntly/tools/subsetter/glyph_table_subsetter.cc @@ -53,12 +53,12 @@ bool GlyphTableSubsetter::Subset(Subsetter* subsetter, #endif } - GlyphTableBuilderPtr glyph_table_builder; - glyph_table_builder.Attach(down_cast( - font_builder->NewTableBuilder(Tag::glyf))); - LocaTableBuilderPtr loca_table_builder; - loca_table_builder.Attach(down_cast( - font_builder->NewTableBuilder(Tag::loca))); + 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) return false; diff --git a/sfntly/tools/subsetter/subsetter.cc b/sfntly/tools/subsetter/subsetter.cc index c234a1e..d1b64d9 100644 --- a/sfntly/tools/subsetter/subsetter.cc +++ b/sfntly/tools/subsetter/subsetter.cc @@ -85,12 +85,7 @@ CALLER_ATTACH Font::Builder* Subsetter::Subset() { tag_end = table_tags.end(); tag != tag_end; ++tag) { Table* table = font_->GetTable(*tag); if (table) { - // The NewTableBuilder() call will alter internal state of font_builder - // AND the reference count of returned object. Therefore we need to - // dereference it. - TableBuilderPtr dereference; - dereference.Attach( - font_builder->NewTableBuilder(*tag, table->ReadFontData())); + font_builder->NewTableBuilder(*tag, table->ReadFontData()); } } return font_builder.Detach(); diff --git a/test/subsetter_impl.cc b/test/subsetter_impl.cc index ea886c0..572f00e 100644 --- a/test/subsetter_impl.cc +++ b/test/subsetter_impl.cc @@ -274,12 +274,10 @@ CALLER_ATTACH Font* SubsetterImpl::Subset(const IntegerSet& glyph_ids) { FontBuilderPtr font_builder; font_builder.Attach(factory_->NewFontBuilder()); - GlyphTableBuilderPtr glyph_table_builder; - glyph_table_builder.Attach(down_cast( - font_builder->NewTableBuilder(Tag::glyf))); - LocaTableBuilderPtr loca_table_builder; - loca_table_builder.Attach(down_cast( - font_builder->NewTableBuilder(Tag::loca))); + 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) { // Out of memory. return NULL; @@ -328,12 +326,7 @@ CALLER_ATTACH Font* SubsetterImpl::Subset(const IntegerSet& glyph_ids) { e = font_->Tables()->end(); i != e; ++i) { // We already build the builder for glyph and loca. if (i->first != Tag::glyf && i->first != Tag::loca) { - // The newTableBuilder() call will alter internal state of font_builder - // AND the reference count of returned object. Therefore we need to - // dereference it. - TableBuilderPtr dereference; - dereference.Attach( - font_builder->NewTableBuilder(i->first, i->second->ReadFontData())); + font_builder->NewTableBuilder(i->first, i->second->ReadFontData()); } } -- cgit v1.2.3 From b54cce09c1fc2b09e2adae43d7eb017b47b0cccf Mon Sep 17 00:00:00 2001 From: "arthurhsu@google.com" Date: Thu, 1 Sep 2011 18:23:15 +0000 Subject: Advance C++ port to Aug 11 Java snapshot git-svn-id: http://sfntly.googlecode.com/svn/trunk/cpp/src@70 672e30a5-4c29-85ac-ac6d-611c735e0a51 --- sample/subsetter/subset_util.cc | 3 +- sfntly/font.cc | 176 ++++++------ sfntly/font.h | 136 ++++++--- sfntly/font_data_table_builder_container.h | 34 --- sfntly/font_factory.cc | 119 +++----- sfntly/font_factory.h | 24 +- sfntly/port/config.h | 4 +- sfntly/port/file_input_stream.cc | 34 +-- sfntly/port/memory_input_stream.cc | 147 ++++++++++ sfntly/port/memory_input_stream.h | 57 ++++ sfntly/table/core/cmap_table.cc | 118 ++++---- sfntly/table/core/cmap_table.h | 47 ++-- sfntly/table/core/font_header_table.cc | 18 +- sfntly/table/core/font_header_table.h | 9 +- sfntly/table/core/horizontal_header_table.cc | 28 +- sfntly/table/core/horizontal_header_table.h | 19 +- sfntly/table/core/horizontal_metrics_table.cc | 53 ++-- sfntly/table/core/horizontal_metrics_table.h | 16 +- sfntly/table/core/maximum_profile_table.cc | 42 ++- sfntly/table/core/maximum_profile_table.h | 19 +- sfntly/table/core/name_table.cc | 28 +- sfntly/table/core/name_table.h | 49 ++-- sfntly/table/core/os2_table.cc | 350 +++++++++++++++++++++++- sfntly/table/core/os2_table.h | 109 +++++++- sfntly/table/font_data_table.cc | 53 ++-- sfntly/table/font_data_table.h | 36 ++- sfntly/table/subtable.cc | 12 +- sfntly/table/subtable.h | 10 +- sfntly/table/subtable_container_table.h | 48 ++++ sfntly/table/table.cc | 144 ++++------ sfntly/table/table.h | 147 ++++++---- sfntly/table/truetype/glyph_table.cc | 66 +++-- sfntly/table/truetype/glyph_table.h | 45 ++- sfntly/table/truetype/loca_table.cc | 83 +++--- sfntly/table/truetype/loca_table.h | 58 +++- sfntly/tools/subsetter/glyph_table_subsetter.cc | 12 +- sfntly/tools/subsetter/subsetter.cc | 4 +- test/font_parsing_test.cc | 8 +- test/memory_io_test.cc | 102 +++++++ test/name_editing_test.cc | 24 +- test/otf_basic_editing_test.cc | 11 +- test/serialization_test.cc | 20 +- test/subsetter_impl.cc | 19 +- test/test_font_utils.cc | 6 +- test/test_font_utils.h | 2 +- test/verify_hhea.cc | 2 +- test/verify_loca.cc | 2 +- test/verify_maxp.cc | 5 +- test/verify_os2.cc | 3 +- 49 files changed, 1675 insertions(+), 886 deletions(-) delete mode 100644 sfntly/font_data_table_builder_container.h create mode 100755 sfntly/port/memory_input_stream.cc create mode 100755 sfntly/port/memory_input_stream.h create mode 100644 sfntly/table/subtable_container_table.h create mode 100755 test/memory_io_test.cc diff --git a/sample/subsetter/subset_util.cc b/sample/subsetter/subset_util.cc index 26da65f..f35eb25 100644 --- a/sample/subsetter/subset_util.cc +++ b/sample/subsetter/subset_util.cc @@ -56,12 +56,11 @@ void SubsetUtil::Subset(const char *input_file_path, UNREFERENCED_PARAMETER(bytes_read); fclose(input_file); - ByteArrayPtr ba = new MemoryByteArray(&(input_buffer[0]), file_size); FontFactoryPtr factory; factory.Attach(FontFactory::GetInstance()); FontArray font_array; - factory->LoadFonts(ba, &font_array); + factory->LoadFonts(&input_buffer, &font_array); if (font_array.empty() || font_array[0] == NULL) return; diff --git a/sfntly/font.cc b/sfntly/font.cc index d66c9f6..e5e4401 100644 --- a/sfntly/font.cc +++ b/sfntly/font.cc @@ -23,6 +23,7 @@ #include #include #include +#include #include "sfntly/data/font_input_stream.h" #include "sfntly/font_factory.h" @@ -58,14 +59,14 @@ Table* Font::GetTable(int32_t tag) { return tables_[tag]; } -TableMap* Font::Tables() { +const TableMap* Font::GetTableMap() { return &tables_; } void Font::Serialize(OutputStream* os, IntegerList* table_ordering) { assert(table_ordering); IntegerList final_table_ordering; - TableOrdering(table_ordering, &final_table_ordering); + GenerateTableOrdering(table_ordering, &final_table_ordering); TableHeaderList table_records; BuildTableHeadersForSerialization(&final_table_ordering, &table_records); @@ -74,18 +75,11 @@ void Font::Serialize(OutputStream* os, IntegerList* table_ordering) { SerializeTables(&fos, &table_records); } -CALLER_ATTACH WritableFontData* Font::GetNewData(int32_t size) { - return factory_->GetNewData(size); -} - -Font::Font(FontFactory* factory, int32_t sfnt_version, ByteVector* digest, - TableMap* tables) - : factory_(factory), - sfnt_version_(sfnt_version) { +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; - tables_ = *tables; } void Font::BuildTableHeadersForSerialization(IntegerList* table_ordering, @@ -94,19 +88,22 @@ void Font::BuildTableHeadersForSerialization(IntegerList* table_ordering, assert(table_ordering); IntegerList final_table_ordering; - TableOrdering(table_ordering, &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) { TableHeaderPtr header = new Table::Header(*tag, table->CalculatedChecksum(), table_offset, - table->Length()); + table->header()->length()); table_headers->push_back(header); - table_offset += (table->Length() + 3) & ~3; + table_offset += (table->DataLength() + 3) & ~3; } } } @@ -121,9 +118,14 @@ void Font::SerializeHeader(FontOutputStream* fos, fos->WriteUShort(log2_of_max_power_of_2); fos->WriteUShort((table_headers->size() * 16) - search_range); - for (TableHeaderList::iterator record = table_headers->begin(), - record_end = table_headers->end(); - record != record_end; ++record) { + 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()); @@ -133,30 +135,31 @@ void Font::SerializeHeader(FontOutputStream* fos, void Font::SerializeTables(FontOutputStream* fos, TableHeaderList* table_headers) { - ByteVector SERIALIZATION_FILLER(3); - std::fill(SERIALIZATION_FILLER.begin(), SERIALIZATION_FILLER.end(), 0); + 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) - return; -#else +#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; - fos->Write(&SERIALIZATION_FILLER, 0, filler_size); + for (int32_t i = 0; i < filler_size; ++i) { + fos->Write(static_cast(0)); + } } } -void Font::TableOrdering(IntegerList* default_table_ordering, - IntegerList* table_ordering) { +void Font::GenerateTableOrdering(IntegerList* default_table_ordering, + IntegerList* table_ordering) { assert(default_table_ordering); assert(table_ordering); table_ordering->clear(); @@ -207,17 +210,19 @@ void Font::DefaultTableOrdering(IntegerList* default_table_ordering) { ******************************************************************************/ Font::Builder::~Builder() {} -CALLER_ATTACH Font::Builder* Font::Builder::GetOTFBuilder( - FontFactory* factory, InputStream* is) { +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, ByteArray* ba, int32_t offset_to_offset_table) { + FontFactory* factory, + WritableFontData* wfd, + int32_t offset_to_offset_table) { FontBuilderPtr builder = new Builder(factory); - builder->LoadFont(ba, offset_to_offset_table); + builder->LoadFont(wfd, offset_to_offset_table); return builder.Detach(); } @@ -233,7 +238,7 @@ bool Font::Builder::ReadyToBuild() { return true; } - // TODO(stuartg): font level checks - required tables etc. + // 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; @@ -245,31 +250,25 @@ bool Font::Builder::ReadyToBuild() { } CALLER_ATTACH Font* Font::Builder::Build() { - TableMap tables; + FontPtr font = new Font(sfnt_version_, &digest_); + if (!table_builders_.empty()) { - BuildTablesFromBuilders(&table_builders_, &tables); + // Note: Different from Java. Directly use font->tables_ here to avoid + // STL container copying. + BuildTablesFromBuilders(font, &table_builders_, &font->tables_); } - FontPtr font = new Font(factory_, sfnt_version_, &digest_, &tables); + table_builders_.clear(); data_blocks_.clear(); return font.Detach(); } -CALLER_ATTACH WritableFontData* Font::Builder::GetNewData(int32_t capacity) { - return factory_->GetNewData(capacity); -} - -CALLER_ATTACH WritableFontData* Font::Builder::GetNewGrowableData( - ReadableFontData* src_data) { - return factory_->GetNewGrowableData(src_data); -} - void Font::Builder::SetDigest(ByteVector* digest) { digest_.clear(); digest_ = *digest; } -void Font::Builder::CleanTableBuilders() { +void Font::Builder::ClearTableBuilders() { table_builders_.clear(); } @@ -286,31 +285,32 @@ Table::Builder* Font::Builder::GetTableBuilder(int32_t tag) { Table::Builder* Font::Builder::NewTableBuilder(int32_t tag) { TableHeaderPtr header = new Table::Header(tag); TableBuilderPtr builder; - builder.Attach(Table::Builder::GetBuilder(this, header, NULL)); + 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(GetNewGrowableData(src_data)); - TableHeaderPtr header = new Table::Header(tag); + data.Attach(WritableFontData::CreateWritableFontData(src_data->Length())); +#if !defined (SFNTLY_NO_EXCEPTION) + try { +#endif + src_data->CopyTo(data); +#if !defined (SFNTLY_NO_EXCEPTION) + } catch (IOException& e) { + return NULL; + } +#endif + TableHeaderPtr header = new Table::Header(tag, data->Length()); TableBuilderPtr builder; - builder.Attach(Table::Builder::GetBuilder(this, header, data)); + builder.Attach(Table::Builder::GetBuilder(header, data)); table_builders_.insert(TableBuilderEntry(tag, builder)); return builder; } -void Font::Builder::TableBuilderTags(IntegerSet* key_set) { - assert(key_set); - key_set->clear(); - for (TableBuilderMap::iterator i = table_builders_.begin(), - e = table_builders_.end(); i != e; ++i) { - key_set->insert(i->first); - } -} - void Font::Builder::RemoveTableBuilder(int32_t tag) { TableBuilderMap::iterator target = table_builders_.find(tag); if (target != table_builders_.end()) { @@ -326,21 +326,20 @@ 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); - TableHeaderSortedSet records; + HeaderOffsetSortedSet records; ReadHeader(&font_is, &records); LoadTableData(&records, &font_is, &data_blocks_); BuildAllTableBuilders(&data_blocks_, &table_builders_); font_is.Close(); } -void Font::Builder::LoadFont(ByteArray* ba, +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(ba); - WritableFontDataPtr fd = new WritableFontData(ba); - TableHeaderSortedSet records; - ReadHeader(fd, offset_to_offset_table, &records); - LoadTableData(&records, fd, &data_blocks_); + assert(wfd); + HeaderOffsetSortedSet records; + ReadHeader(wfd, offset_to_offset_table, &records); + LoadTableData(&records, wfd, &data_blocks_); BuildAllTableBuilders(&data_blocks_, &table_builders_); } @@ -361,14 +360,16 @@ void Font::Builder::BuildAllTableBuilders(DataBlockMap* table_data, InterRelateBuilders(&table_builders_); } -CALLER_ATTACH Table::Builder* - Font::Builder::GetTableBuilder(Table::Header* header, - WritableFontData* data) { - return Table::Builder::GetBuilder(this, header, data); +CALLER_ATTACH +Table::Builder* Font::Builder::GetTableBuilder(Table::Header* header, + WritableFontData* data) { + return Table::Builder::GetBuilder(header, data); } -void Font::Builder::BuildTablesFromBuilders(TableBuilderMap* builder_map, +void Font::Builder::BuildTablesFromBuilders(Font* font, + TableBuilderMap* builder_map, TableMap* table_map) { + UNREFERENCED_PARAMETER(font); InterRelateBuilders(builder_map); // Now build all the tables. @@ -384,7 +385,7 @@ void Font::Builder::BuildTablesFromBuilders(TableBuilderMap* builder_map, #if !defined (SFNTLY_NO_EXCEPTION) } catch(IOException& e) { std::string builder_string = "Unable to build table - "; - char *table_name = TagToString(builder->first); + char* table_name = TagToString(builder->first); builder_string += table_name; delete[] table_name; throw RuntimeException(builder_string.c_str()); @@ -392,20 +393,19 @@ void Font::Builder::BuildTablesFromBuilders(TableBuilderMap* builder_map, #endif } if (table == NULL) { - std::string builder_string = "Unable to build table - "; - char *table_name = TagToString(builder->first); - builder_string += table_name; - delete[] table_name; -#if defined (SFNTLY_NO_EXCEPTION) #if defined (SFNTLY_DEBUG) fprintf(stderr, "Aborting table construction: %s\n", builder_string.c_str()); #endif table_map->clear(); - return; -#else +#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)); } @@ -474,14 +474,14 @@ void Font::Builder::InterRelateBuilders(TableBuilderMap* builder_map) { loca_table_builder->SetNumGlyphs(max_profile_builder->NumGlyphs()); } if (header_table_builder != NULL) { - loca_table_builder->SetFormatVersion( + loca_table_builder->set_format_version( header_table_builder->IndexToLocFormat()); } } } void Font::Builder::ReadHeader(FontInputStream* is, - TableHeaderSortedSet* records) { + HeaderOffsetSortedSet* records) { assert(records); sfnt_version_ = is->ReadFixed(); num_tables_ = is->ReadUShort(); @@ -503,7 +503,7 @@ void Font::Builder::ReadHeader(FontInputStream* is, void Font::Builder::ReadHeader(ReadableFontData* fd, int32_t offset, - TableHeaderSortedSet* records) { + HeaderOffsetSortedSet* records) { assert(records); sfnt_version_ = fd->ReadFixed(offset + Offset::kSfntVersion); num_tables_ = fd->ReadUShort(offset + Offset::kNumTables); @@ -524,13 +524,14 @@ void Font::Builder::ReadHeader(ReadableFontData* fd, } } -void Font::Builder::LoadTableData(TableHeaderSortedSet* headers, +void Font::Builder::LoadTableData(HeaderOffsetSortedSet* headers, FontInputStream* is, DataBlockMap* table_data) { assert(table_data); - for (TableHeaderSortedSet::iterator - table_header = headers->begin(), table_end = headers->end(); - table_header != table_end; ++table_header) { + 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; @@ -541,12 +542,13 @@ void Font::Builder::LoadTableData(TableHeaderSortedSet* headers, } } -void Font::Builder::LoadTableData(TableHeaderSortedSet* headers, +void Font::Builder::LoadTableData(HeaderOffsetSortedSet* headers, WritableFontData* fd, DataBlockMap* table_data) { - for (TableHeaderSortedSet::iterator - table_header = headers->begin(), table_end = headers->end(); - table_header != table_end; ++table_header) { + 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())); diff --git a/sfntly/font.h b/sfntly/font.h index 2badece..1a714a6 100644 --- a/sfntly/font.h +++ b/sfntly/font.h @@ -22,7 +22,6 @@ #include "sfntly/port/refcount.h" #include "sfntly/port/type.h" #include "sfntly/port/endian.h" -#include "sfntly/font_data_table_builder_container.h" #include "sfntly/data/font_input_stream.h" #include "sfntly/data/font_output_stream.h" #include "sfntly/data/writable_font_data.h" @@ -121,10 +120,16 @@ struct MacintoshEncodingId { extern const int32_t SFNTVERSION_1; 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: - class Builder : public FontDataTableBuilderContainer, - public RefCounted { + // 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(); @@ -132,18 +137,31 @@ class Font : public RefCounted { GetOTFBuilder(FontFactory* factory, InputStream* is); static CALLER_ATTACH Builder* GetOTFBuilder(FontFactory* factory, - ByteArray* ba, + WritableFontData* ba, int32_t offset_to_offset_table); static CALLER_ATTACH Builder* GetOTFBuilder(FontFactory* factory); - virtual bool ReadyToBuild(); - virtual CALLER_ATTACH Font* Build(); - virtual CALLER_ATTACH WritableFontData* GetNewData(int32_t capacity); - virtual CALLER_ATTACH WritableFontData* - GetNewGrowableData(ReadableFontData* data); - virtual void SetDigest(ByteVector* digest); - virtual void CleanTableBuilders(); - virtual bool HasTableBuilder(int32_t tag); - virtual Table::Builder* GetTableBuilder(int32_t tag); + + // 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 @@ -151,12 +169,23 @@ class Font : public RefCounted { // @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_; } - virtual void TableBuilderTags(IntegerSet* key_set); + + // 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(); } @@ -164,23 +193,30 @@ class Font : public RefCounted { private: explicit Builder(FontFactory* factory); virtual void LoadFont(InputStream* is); - virtual void LoadFont(ByteArray* buffer, int32_t offset_to_offset_table); + 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(Table::Header* header, WritableFontData* data); - void BuildTablesFromBuilders(TableBuilderMap* builder_map, + void BuildTablesFromBuilders(Font* font, + TableBuilderMap* builder_map, TableMap* tables); static void InterRelateBuilders(TableBuilderMap* builder_map); - void ReadHeader(FontInputStream* is, TableHeaderSortedSet* records); + + void ReadHeader(FontInputStream* is, + HeaderOffsetSortedSet* records); + void ReadHeader(ReadableFontData* fd, int32_t offset, - TableHeaderSortedSet* records); - void LoadTableData(TableHeaderSortedSet* headers, + HeaderOffsetSortedSet* records); + + void LoadTableData(HeaderOffsetSortedSet* headers, FontInputStream* is, DataBlockMap* table_data); - void LoadTableData(TableHeaderSortedSet* headers, + + void LoadTableData(HeaderOffsetSortedSet* headers, WritableFontData* fd, DataBlockMap* table_data); @@ -198,7 +234,7 @@ class Font : public RefCounted { virtual ~Font(); // Gets the sfnt version set in the sfnt wrapper of the font. - int32_t version() { return sfnt_version_; } + 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. @@ -223,24 +259,16 @@ class Font : public RefCounted { // Get a map of the tables in this font accessed by table tag. // @return an unmodifiable view of the tables in this font - TableMap* Tables(); + // 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); - // Get a new data object. The size is a request for a data object and the - // returned data object will support at least that amount. A value greater - // than zero for the size is a request for a fixed size data object. A - // negative or zero value for the size is a request for a variable sized data - // object with the absolute value of the size being an estimate of the space - // required. - // @param size greater than zero is a request for a fixed size data object of - // the given size; less than or equal to zero is a request for a - // variable size data object with the absolute size as an estimate - CALLER_ATTACH WritableFontData* GetNewData(int32_t size); - 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 @@ -269,18 +297,48 @@ class Font : public RefCounted { // static const int32_t CFF_TABLE_ORDERING[]; // static const int32_t TRUE_TYPE_TABLE_ORDERING[]; - Font(FontFactory* factory, int32_t sfnt_version, ByteVector* digest, - TableMap* tables); - + // 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); - void TableOrdering(IntegerList* default_table_ordering, - IntegerList* table_ordering); + + // 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); - FontFactory* factory_; // dumb pointer, avoid circular ref-counting int32_t sfnt_version_; ByteVector digest_; int64_t checksum_; diff --git a/sfntly/font_data_table_builder_container.h b/sfntly/font_data_table_builder_container.h deleted file mode 100644 index 2818464..0000000 --- a/sfntly/font_data_table_builder_container.h +++ /dev/null @@ -1,34 +0,0 @@ -/* - * 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_DATA_TABLE_BUILDER_CONTAINER_H_ -#define SFNTLY_CPP_SRC_SFNTLY_FONT_DATA_TABLE_BUILDER_CONTAINER_H_ - -#include "sfntly/data/writable_font_data.h" - -namespace sfntly { - -class FontDataTableBuilderContainer { - public: - virtual WritableFontData* GetNewData(int32_t size) = 0; - // Make gcc -Wnon-virtual-dtor happy. - virtual ~FontDataTableBuilderContainer() {} -}; -typedef Ptr FontDataTableBuilderContainerPtr; - -} // namespace sfntly - -#endif // SFNTLY_CPP_SRC_SFNTLY_FONT_DATA_TABLE_BUILDER_CONTAINER_H_ diff --git a/sfntly/font_factory.cc b/sfntly/font_factory.cc index a306bcd..c162a77 100644 --- a/sfntly/font_factory.cc +++ b/sfntly/font_factory.cc @@ -19,8 +19,6 @@ #include #include "sfntly/tag.h" -#include "sfntly/data/memory_byte_array.h" -#include "sfntly/data/growable_memory_byte_array.h" namespace sfntly { @@ -54,13 +52,15 @@ void FontFactory::LoadFonts(InputStream* is, FontArray* output) { } } -void FontFactory::LoadFonts(ByteArray* ba, FontArray* output) { - if (IsCollection(ba)) { - LoadCollection(ba, output); +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(ba)); + font.Attach(LoadSingleOTF(wfd)); if (font) { output->push_back(font); } @@ -80,59 +80,21 @@ void FontFactory::LoadFontsForBuilding(InputStream* is, } } -void FontFactory::LoadFontsForBuilding(ByteArray* ba, +void FontFactory::LoadFontsForBuilding(ByteVector* b, FontBuilderArray* output) { - if (IsCollection(ba)) { - LoadCollectionForBuilding(ba, output); + WritableFontDataPtr wfd; + wfd.Attach(WritableFontData::CreateWritableFontData(b)); + if (IsCollection(wfd)) { + LoadCollectionForBuilding(wfd, output); return; } FontBuilderPtr builder; - builder.Attach(LoadSingleOTFForBuilding(ba, 0)); + builder.Attach(LoadSingleOTFForBuilding(wfd, 0)); if (builder) { output->push_back(builder); } } -CALLER_ATTACH WritableFontData* FontFactory::GetNewData(int32_t capacity) { - // UNIMPLMENTED: if (capacity > 0) { this.GetNewFixedData(capacity); } - // Seems a no-op. - return GetNewGrowableData(capacity); -} - -CALLER_ATTACH WritableFontData* FontFactory::GetNewFixedData(int32_t capacity) { - ByteArrayPtr buffer; - buffer.Attach(GetNewArray(capacity)); - WritableFontDataPtr new_fixed_data = new WritableFontData(buffer); - return new_fixed_data.Detach(); -} - -CALLER_ATTACH WritableFontData* FontFactory::GetNewGrowableData( - int32_t capacity) { - ByteArrayPtr buffer; - buffer.Attach(GetNewGrowableArray(capacity)); - WritableFontDataPtr new_growable_data = new WritableFontData(buffer); - return new_growable_data.Detach(); -} - -CALLER_ATTACH WritableFontData* FontFactory::GetNewGrowableData( - ReadableFontData* src_data) { - WritableFontDataPtr data; - data.Attach(GetNewGrowableData(src_data->Length())); - src_data->CopyTo(data); - return data.Detach(); -} - -CALLER_ATTACH ByteArray* FontFactory::GetNewArray(int32_t length) { - ByteArrayPtr new_fixed_array = new MemoryByteArray(length); - return new_fixed_array.Detach(); -} - -CALLER_ATTACH ByteArray* FontFactory::GetNewGrowableArray(int32_t length) { - UNREFERENCED_PARAMETER(length); - ByteArrayPtr new_growable_array = new GrowableMemoryByteArray(); - return new_growable_array.Detach(); -} - void FontFactory::SerializeFont(Font* font, OutputStream* os) { font->Serialize(os, &table_ordering_); } @@ -152,9 +114,9 @@ CALLER_ATTACH Font* FontFactory::LoadSingleOTF(InputStream* is) { return builder->Build(); } -CALLER_ATTACH Font* FontFactory::LoadSingleOTF(ByteArray* ba) { +CALLER_ATTACH Font* FontFactory::LoadSingleOTF(WritableFontData* wfd) { FontBuilderPtr builder; - builder.Attach(LoadSingleOTFForBuilding(ba, 0)); + builder.Attach(LoadSingleOTFForBuilding(wfd, 0)); return builder->Build(); } @@ -170,21 +132,21 @@ void FontFactory::LoadCollection(InputStream* is, FontArray* output) { } } -void FontFactory::LoadCollection(ByteArray* ba, FontArray* output) { +void FontFactory::LoadCollection(WritableFontData* wfd, FontArray* output) { FontBuilderArray builders; - LoadCollectionForBuilding(ba, &builders); - output->reserve(ba->Size()); - for (FontBuilderArray::iterator - builder = builders.begin(), builders_end = builders.end(); - builder != builders_end; ++builder) { + 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) { +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 @@ -192,38 +154,41 @@ CALLER_ATTACH Font::Builder* } CALLER_ATTACH Font::Builder* - FontFactory::LoadSingleOTFForBuilding(ByteArray* ba, + 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, ba, offset_to_offset_table); + Font::Builder::GetOTFBuilder(this, wfd, offset_to_offset_table); // UNIMPLEMENTED: setDigest return builder; } void FontFactory::LoadCollectionForBuilding(InputStream* is, FontBuilderArray* builders) { - ByteArrayPtr ba = new GrowableMemoryByteArray(); - ba->CopyFrom(is); - LoadCollectionForBuilding(ba, builders); + assert(is); + assert(builders); + WritableFontDataPtr wfd; + wfd.Attach(WritableFontData::CreateWritableFontData(is->Available())); + wfd->CopyFrom(is); + LoadCollectionForBuilding(wfd, builders); } -void FontFactory::LoadCollectionForBuilding(ByteArray* ba, +void FontFactory::LoadCollectionForBuilding(WritableFontData* wfd, FontBuilderArray* builders) { - ReadableFontDataPtr rfd = new ReadableFontData(ba); - int32_t ttc_tag = rfd->ReadULongAsInt(Offset::kTTCTag); + int32_t ttc_tag = wfd->ReadULongAsInt(Offset::kTTCTag); UNREFERENCED_PARAMETER(ttc_tag); - int32_t version = rfd->ReadFixed(Offset::kVersion); + int32_t version = wfd->ReadFixed(Offset::kVersion); UNREFERENCED_PARAMETER(version); - int32_t num_fonts = rfd->ReadULongAsInt(Offset::kNumFonts); + 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 = rfd->ReadULongAsInt(offset_table_offset); + 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(ba, offset)); + builder.Attach(LoadSingleOTFForBuilding(wfd, offset)); builders->push_back(builder); } } @@ -235,9 +200,11 @@ bool FontFactory::IsCollection(PushbackInputStream* pbis) { return Tag::ttcf == GenerateTag(tag[0], tag[1], tag[2], tag[3]); } -bool FontFactory::IsCollection(ByteArray* ba) { +bool FontFactory::IsCollection(ReadableFontData* rfd) { + ByteVector tag(4); + rfd->ReadBytes(0, &(tag[0]), 0, tag.size()); return Tag::ttcf == - GenerateTag(ba->Get(0), ba->Get(1), ba->Get(2), ba->Get(3)); + GenerateTag(tag[0], tag[1], tag[2], tag[3]); } FontFactory::FontFactory() diff --git a/sfntly/font_factory.h b/sfntly/font_factory.h index b706b92..63deff4 100644 --- a/sfntly/font_factory.h +++ b/sfntly/font_factory.h @@ -56,7 +56,7 @@ class FontFactory : public RefCounted { // 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(ByteArray* ba, FontArray* output); + 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 @@ -72,15 +72,7 @@ class FontFactory : public RefCounted { // 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(ByteArray* ba, FontBuilderArray* output); - - CALLER_ATTACH WritableFontData* GetNewData(int32_t capacity); - CALLER_ATTACH WritableFontData* GetNewFixedData(int32_t capacity); - CALLER_ATTACH WritableFontData* GetNewGrowableData(int32_t capacity); - CALLER_ATTACH WritableFontData* - GetNewGrowableData(ReadableFontData* src_data); - CALLER_ATTACH ByteArray* GetNewArray(int32_t length); - CALLER_ATTACH ByteArray* GetNewGrowableArray(int32_t length); + void LoadFontsForBuilding(ByteVector* b, FontBuilderArray* output); // Font serialization // Serialize the font to the output stream. @@ -121,20 +113,22 @@ class FontFactory : public RefCounted { FontFactory(); CALLER_ATTACH Font* LoadSingleOTF(InputStream* is); - CALLER_ATTACH Font* LoadSingleOTF(ByteArray* ba); + CALLER_ATTACH Font* LoadSingleOTF(WritableFontData* wfd); void LoadCollection(InputStream* is, FontArray* output); - void LoadCollection(ByteArray* ba, FontArray* output); + void LoadCollection(WritableFontData* wfd, FontArray* output); CALLER_ATTACH Font::Builder* LoadSingleOTFForBuilding(InputStream* is); CALLER_ATTACH Font::Builder* - LoadSingleOTFForBuilding(ByteArray* ba, int32_t offset_to_offset_table); + LoadSingleOTFForBuilding(WritableFontData* wfd, + int32_t offset_to_offset_table); void LoadCollectionForBuilding(InputStream* is, FontBuilderArray* builders); - void LoadCollectionForBuilding(ByteArray* ba, FontBuilderArray* builders); + void LoadCollectionForBuilding(WritableFontData* ba, + FontBuilderArray* builders); static bool IsCollection(PushbackInputStream* pbis); - static bool IsCollection(ByteArray* ba); + static bool IsCollection(ReadableFontData* wfd); bool fingerprint_; IntegerList table_ordering_; diff --git a/sfntly/port/config.h b/sfntly/port/config.h index 01c4685..0fcdffe 100644 --- a/sfntly/port/config.h +++ b/sfntly/port/config.h @@ -19,9 +19,9 @@ #if !defined(SFNTLY_BIG_ENDIAN) && !defined(SFNTLY_LITTLE_ENDIAN) #if defined (__ppc__) || defined (__ppc64__) - #define SFNTLY_CPP_BIG_ENDIAN + #define SFNTLY_BIG_ENDIAN #else - #define SFNTLY_CPP_LITTLE_ENDIAN + #define SFNTLY_LITTLE_ENDIAN #endif #endif diff --git a/sfntly/port/file_input_stream.cc b/sfntly/port/file_input_stream.cc index 661b6fd..5bcb434 100644 --- a/sfntly/port/file_input_stream.cc +++ b/sfntly/port/file_input_stream.cc @@ -57,18 +57,16 @@ bool FileInputStream::MarkSupported() { int32_t FileInputStream::Read() { if (!file_) { -#if defined (SFNTLY_NO_EXCEPTION) - return 0; -#else +#if !defined (SFNTLY_NO_EXCEPTION) throw IOException("no opened file"); #endif + return 0; } if (feof(file_)) { -#if defined (SFNTLY_NO_EXCEPTION) - return 0; -#else +#if !defined (SFNTLY_NO_EXCEPTION) throw IOException("eof reached"); #endif + return 0; } byte_t value; size_t length = fread(&value, 1, 1, file_); @@ -77,24 +75,22 @@ int32_t FileInputStream::Read() { } int32_t FileInputStream::Read(ByteVector* b) { - return Read(b, 0, b->capacity()); + 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) - return 0; -#else +#if !defined (SFNTLY_NO_EXCEPTION) throw IOException("no opened file"); #endif + return 0; } if (feof(file_)) { -#if defined (SFNTLY_NO_EXCEPTION) - return 0; -#else +#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)) { @@ -111,11 +107,10 @@ void FileInputStream::Reset() { int64_t FileInputStream::Skip(int64_t n) { if (!file_) { -#if defined (SFNTLY_NO_EXCEPTION) - return 0; -#else +#if !defined (SFNTLY_NO_EXCEPTION) throw IOException("no opened file"); #endif + return 0; } int64_t skip_count = 0; if (n < 0) { // move backwards @@ -131,18 +126,17 @@ int64_t FileInputStream::Skip(int64_t n) { } void FileInputStream::Unread(ByteVector* b) { - Unread(b, 0, b->capacity()); + 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) - return; -#else +#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); diff --git a/sfntly/port/memory_input_stream.cc b/sfntly/port/memory_input_stream.cc new file mode 100755 index 0000000..56ee81e --- /dev/null +++ b/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/sfntly/port/memory_input_stream.h b/sfntly/port/memory_input_stream.h new file mode 100755 index 0000000..bc861c3 --- /dev/null +++ b/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/sfntly/table/core/cmap_table.cc b/sfntly/table/core/cmap_table.cc index 7217265..dd43996 100644 --- a/sfntly/table/core/cmap_table.cc +++ b/sfntly/table/core/cmap_table.cc @@ -60,7 +60,7 @@ int32_t CMapTable::Offset(int32_t index) { } CMapTable::CMapTable(Header* header, ReadableFontData* data) - : Table(header, data) { + : SubTableContainerTable(header, data) { } int32_t CMapTable::OffsetForEncodingRecord(int32_t index) { @@ -126,20 +126,18 @@ CMapTable::CMap::Builder::~Builder() { } CALLER_ATTACH CMapTable::CMap::Builder* - CMapTable::CMap::Builder::GetBuilder( - FontDataTableBuilderContainer* container, - ReadableFontData* data, - int32_t offset, - const CMapId& cmap_id) { + 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 = new CMapFormat0::Builder(container, data, offset, cmap_id); + builder = new CMapFormat0::Builder(data, offset, cmap_id); break; case CMapFormat::kFormat2: - builder = new CMapFormat0::Builder(container, data, offset, cmap_id); + builder = new CMapFormat0::Builder(data, offset, cmap_id); break; default: break; @@ -147,18 +145,18 @@ CALLER_ATTACH CMapTable::CMap::Builder* return builder.Detach(); } -CMapTable::CMap::Builder::Builder(FontDataTableBuilderContainer* container, - ReadableFontData* data, int32_t format, +CMapTable::CMap::Builder::Builder(ReadableFontData* data, + int32_t format, const CMapId& cmap_id) - : SubTable::Builder(container, data), + : SubTable::Builder(data), format_(format), cmap_id_(cmap_id) { } -CMapTable::CMap::Builder::Builder(FontDataTableBuilderContainer* container, - WritableFontData* data, int32_t format, +CMapTable::CMap::Builder::Builder(WritableFontData* data, + int32_t format, const CMapId& cmap_id) - : SubTable::Builder(container, data), + : SubTable::Builder(data), format_(format), cmap_id_(cmap_id) { } @@ -204,13 +202,10 @@ CMapTable::CMapFormat0::CMapFormat0(ReadableFontData* data, /****************************************************************************** * CMapTable::CMapFormat0::Builder ******************************************************************************/ -CMapTable::CMapFormat0::Builder::Builder( - FontDataTableBuilderContainer* container, - WritableFontData* data, - int32_t offset, - const CMapId& cmap_id) - : CMapTable::CMap::Builder(container, - data ? down_cast( +CMapTable::CMapFormat0::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), @@ -218,13 +213,10 @@ CMapTable::CMapFormat0::Builder::Builder( // TODO(arthurhsu): FIXIT: heavy lifting and leak, need fix. } -CMapTable::CMapFormat0::Builder::Builder( - FontDataTableBuilderContainer* container, - ReadableFontData* data, - int32_t offset, - const CMapId& cmap_id) - : CMapTable::CMap::Builder(container, - data ? down_cast( +CMapTable::CMapFormat0::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), @@ -340,13 +332,10 @@ int32_t CMapTable::CMapFormat2::IdDelta(int32_t sub_header_index) { /****************************************************************************** * CMapTable::CMapFormat2::Builder ******************************************************************************/ -CMapTable::CMapFormat2::Builder::Builder( - FontDataTableBuilderContainer* container, - WritableFontData* data, - int32_t offset, - const CMapId& cmap_id) - : CMapTable::CMap::Builder(container, - data ? down_cast( +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), @@ -354,13 +343,10 @@ CMapTable::CMapFormat2::Builder::Builder( // TODO(arthurhsu): FIXIT: heavy lifting and leak, need fix. } -CMapTable::CMapFormat2::Builder::Builder( - FontDataTableBuilderContainer* container, - ReadableFontData* data, - int32_t offset, - const CMapId& cmap_id) - : CMapTable::CMap::Builder(container, - data ? down_cast( +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), @@ -402,16 +388,12 @@ bool CMapTable::CMapIterator::HasNext() { /****************************************************************************** * CMapTable::Builder class ******************************************************************************/ -CMapTable::Builder::Builder(FontDataTableBuilderContainer* font_builder, - Header* header, - WritableFontData* data) - : Table::ArrayElementTableBuilder(font_builder, header, data) { +CMapTable::Builder::Builder(Header* header, WritableFontData* data) + : SubTableContainerTable::Builder(header, data) { } -CMapTable::Builder::Builder(FontDataTableBuilderContainer* font_builder, - Header* header, - ReadableFontData* data) - : Table::ArrayElementTableBuilder(font_builder, header, data) { +CMapTable::Builder::Builder(Header* header, ReadableFontData* data) + : SubTableContainerTable::Builder(header, data) { } CMapTable::Builder::~Builder() { @@ -483,22 +465,32 @@ CALLER_ATTACH FontDataTable* return table.Detach(); } -CALLER_ATTACH CMapTable::CMap::Builder* CMapTable::Builder::CMapBuilder( - FontDataTableBuilderContainer* container, ReadableFontData* data, - int32_t index) { - if (index < 0 || index > NumCMaps(data)) +CALLER_ATTACH CMapTable::Builder* + CMapTable::Builder::CreateBuilder(Header* header, + WritableFontData* data) { + Ptr builder; + builder = new CMapTable::Builder(header, data); + return builder.Detach(); +} + +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 record_offset = Offset::kEncodingRecordOffset + index * - Offset::kEncodingRecordSize; - int32_t platform_id = - data->ReadUShort(Offset::kEncodingRecordPlatformId + record_offset); - int32_t encoding_id = - data->ReadUShort(Offset::kEncodingRecordEncodingId + record_offset); + 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)); CMapId cmap_id(platform_id, encoding_id); - int32_t offset = - data->ReadULongAsInt(Offset::kEncodingRecordOffset + record_offset); - return CMap::Builder::GetBuilder(container, data, offset, cmap_id); + return CMap::Builder::GetBuilder(data, offset, cmap_id); } int32_t CMapTable::Builder::NumCMaps(ReadableFontData* data) { diff --git a/sfntly/table/core/cmap_table.h b/sfntly/table/core/cmap_table.h index 76b4266..6455ef6 100644 --- a/sfntly/table/core/cmap_table.h +++ b/sfntly/table/core/cmap_table.h @@ -22,8 +22,8 @@ #include #include "sfntly/port/refcount.h" -#include "sfntly/table/table.h" #include "sfntly/table/subtable.h" +#include "sfntly/table/subtable_container_table.h" namespace sfntly { @@ -43,7 +43,7 @@ struct CMapFormat { }; // A CMap table -class CMapTable : public Table, public RefCounted { +class CMapTable : public SubTableContainerTable, public RefCounted { public: // CMapTable::CMapId class CMapId { @@ -113,8 +113,7 @@ public: virtual ~Builder(); CALLER_ATTACH static Builder* - GetBuilder(FontDataTableBuilderContainer* container, - ReadableFontData* data, + GetBuilder(ReadableFontData* data, int32_t offset, const CMapId& cmap_id); @@ -124,12 +123,10 @@ public: virtual int32_t encoding_id() { return cmap_id_.encoding_id(); } protected: - Builder(FontDataTableBuilderContainer* container, - ReadableFontData* data, + Builder(ReadableFontData* data, int32_t format, const CMapId& cmap_id); - Builder(FontDataTableBuilderContainer* container, - WritableFontData* data, + Builder(WritableFontData* data, int32_t format, const CMapId& cmap_id); @@ -186,12 +183,10 @@ public: class Builder : public CMap::Builder, public RefCounted { public: - Builder(FontDataTableBuilderContainer* container, - ReadableFontData* data, + Builder(ReadableFontData* data, int32_t offset, const CMapId& cmap_id); - Builder(FontDataTableBuilderContainer* container, - WritableFontData* data, + Builder(WritableFontData* data, int32_t offset, const CMapId& cmap_id); virtual ~Builder(); @@ -218,12 +213,10 @@ public: class Builder : public CMap::Builder, public RefCounted { public: - Builder(FontDataTableBuilderContainer* container, - ReadableFontData* data, + Builder(ReadableFontData* data, int32_t offset, const CMapId& cmap_id); - Builder(FontDataTableBuilderContainer* container, - WritableFontData* data, + Builder(WritableFontData* data, int32_t offset, const CMapId& cmap_id); virtual ~Builder(); @@ -254,17 +247,13 @@ public: }; // CMapTable::Builder - class Builder : public Table::ArrayElementTableBuilder, + 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(FontDataTableBuilderContainer* font_builder, - Header* header, - WritableFontData* data); - Builder(FontDataTableBuilderContainer* font_builder, - Header* header, - ReadableFontData* data); + Builder(Header* header, WritableFontData* data); + Builder(Header* header, ReadableFontData* data); virtual ~Builder(); virtual int32_t SubSerialize(WritableFontData* new_data); @@ -273,11 +262,12 @@ public: virtual void SubDataSet(); virtual CALLER_ATTACH FontDataTable* SubBuildTable(ReadableFontData* data); + static CALLER_ATTACH Builder* CreateBuilder(Header* header, + WritableFontData* data); + protected: - static CALLER_ATTACH CMap::Builder* - CMapBuilder(FontDataTableBuilderContainer* container, - ReadableFontData* data, - int32_t index); + static CALLER_ATTACH CMap::Builder* CMapBuilder(ReadableFontData* data, + int32_t index); private: static int32_t NumCMaps(ReadableFontData* data); @@ -354,6 +344,7 @@ public: kFormat4EntrySelector = 10, kFormat4RangeShift = 12, kFormat4EndCount = 14, + kFormat4FixedSize = 16, // format 6: Trimmed table mapping kFormat6Format = 0, @@ -437,7 +428,7 @@ public: // 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. - int32_t OffsetForEncodingRecord(int32_t index); + static int32_t OffsetForEncodingRecord(int32_t index); }; typedef std::vector CMapIdList; typedef Ptr CMapTablePtr; diff --git a/sfntly/table/core/font_header_table.cc b/sfntly/table/core/font_header_table.cc index da19258..3713b02 100644 --- a/sfntly/table/core/font_header_table.cc +++ b/sfntly/table/core/font_header_table.cc @@ -102,14 +102,12 @@ FontHeaderTable::FontHeaderTable(Header* header, ReadableFontData* data) /****************************************************************************** * FontHeaderTable::Builder class ******************************************************************************/ -FontHeaderTable::Builder::Builder(FontDataTableBuilderContainer* font_builder, - Header* header, WritableFontData* data) : - Table::TableBasedTableBuilder(font_builder, header, data) { +FontHeaderTable::Builder::Builder(Header* header, WritableFontData* data) + : Table::TableBasedTableBuilder(header, data) { } -FontHeaderTable::Builder::Builder(FontDataTableBuilderContainer* font_builder, - Header* header, ReadableFontData* data) : - Table::TableBasedTableBuilder(font_builder, header, data) { +FontHeaderTable::Builder::Builder(Header* header, ReadableFontData* data) + : Table::TableBasedTableBuilder(header, data) { } FontHeaderTable::Builder::~Builder() {} @@ -256,4 +254,12 @@ 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/sfntly/table/core/font_header_table.h b/sfntly/table/core/font_header_table.h index 343e62c..3b20863 100644 --- a/sfntly/table/core/font_header_table.h +++ b/sfntly/table/core/font_header_table.h @@ -45,10 +45,8 @@ class FontHeaderTable : public Table, public RefCounted { public: // Constructor scope altered to public because C++ does not allow base // class to instantiate derived class with protected constructors. - Builder(FontDataTableBuilderContainer* font_builder, Header* header, - WritableFontData* data); - Builder(FontDataTableBuilderContainer* font_builder, Header* header, - ReadableFontData* data); + Builder(Header* header, WritableFontData* data); + Builder(Header* header, ReadableFontData* data); virtual ~Builder(); virtual CALLER_ATTACH FontDataTable* SubBuildTable(ReadableFontData* data); @@ -90,6 +88,9 @@ class FontHeaderTable : public Table, public RefCounted { 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(); diff --git a/sfntly/table/core/horizontal_header_table.cc b/sfntly/table/core/horizontal_header_table.cc index 52b0de2..f07ab01 100644 --- a/sfntly/table/core/horizontal_header_table.cc +++ b/sfntly/table/core/horizontal_header_table.cc @@ -22,7 +22,7 @@ namespace sfntly { ******************************************************************************/ HorizontalHeaderTable:: ~HorizontalHeaderTable() {} -int32_t HorizontalHeaderTable::Version() { +int32_t HorizontalHeaderTable::TableVersion() { return data_->ReadFixed(Offset::kVersion); } @@ -82,18 +82,12 @@ HorizontalHeaderTable:: HorizontalHeaderTable(Header* header, /****************************************************************************** * HorizontalHeaderTable::Builder class ******************************************************************************/ -HorizontalHeaderTable::Builder::Builder( - FontDataTableBuilderContainer* font_builder, - Header* header, - WritableFontData* data) - : Table::TableBasedTableBuilder(font_builder, header, data) { +HorizontalHeaderTable::Builder::Builder(Header* header, WritableFontData* data) + : Table::TableBasedTableBuilder(header, data) { } -HorizontalHeaderTable::Builder::Builder( - FontDataTableBuilderContainer* font_builder, - Header* header, - ReadableFontData* data) - : Table::TableBasedTableBuilder(font_builder, header, data) { +HorizontalHeaderTable::Builder::Builder(Header* header, ReadableFontData* data) + : Table::TableBasedTableBuilder(header, data) { } HorizontalHeaderTable::Builder::~Builder() {} @@ -104,11 +98,19 @@ CALLER_ATTACH FontDataTable* return table.Detach(); } -int32_t HorizontalHeaderTable::Builder::Version() { +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::SetVersion(int32_t version) { +void HorizontalHeaderTable::Builder::SetTableVersion(int32_t version) { InternalWriteData()->WriteFixed(Offset::kVersion, version); } diff --git a/sfntly/table/core/horizontal_header_table.h b/sfntly/table/core/horizontal_header_table.h index 3a3eb6f..c79a7b6 100644 --- a/sfntly/table/core/horizontal_header_table.h +++ b/sfntly/table/core/horizontal_header_table.h @@ -21,25 +21,26 @@ namespace sfntly { +// A Horizontal Header table - 'hhea'. class HorizontalHeaderTable : public Table, public RefCounted { public: + // Builder for a Horizontal Header table - 'hhea'. class Builder : public Table::TableBasedTableBuilder, public RefCounted { public: // Constructor scope altered to public because C++ does not allow base // class to instantiate derived class with protected constructors. - Builder(FontDataTableBuilderContainer* font_builder, - Header* header, - WritableFontData* data); - Builder(FontDataTableBuilderContainer* font_builder, - Header* header, - ReadableFontData* data); + Builder(Header* header, WritableFontData* data); + Builder(Header* header, ReadableFontData* data); virtual ~Builder(); virtual CALLER_ATTACH FontDataTable* SubBuildTable(ReadableFontData* data); - int32_t Version(); - void SetVersion(int32_t version); + 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(); @@ -67,7 +68,7 @@ class HorizontalHeaderTable : public Table, }; virtual ~HorizontalHeaderTable(); - int32_t Version(); + int32_t TableVersion(); int32_t Ascender(); int32_t Descender(); int32_t LineGap(); diff --git a/sfntly/table/core/horizontal_metrics_table.cc b/sfntly/table/core/horizontal_metrics_table.cc index b2463b9..67e99e0 100644 --- a/sfntly/table/core/horizontal_metrics_table.cc +++ b/sfntly/table/core/horizontal_metrics_table.cc @@ -33,11 +33,10 @@ int32_t HorizontalMetricsTable::NumberOfLSBs() { int32_t HorizontalMetricsTable::HMetricAdvanceWidth(int32_t entry) { if (entry > num_hmetrics_) { -#if defined (SFNTLY_NO_EXCEPTION) - return 0; -#else +#if !defined (SFNTLY_NO_EXCEPTION) throw IndexOutOfBoundException(); #endif + return 0; } int32_t offset = Offset::kHMetricsStart + (entry * Offset::kHMetricsSize) + Offset::kHMetricsAdvanceWidth; @@ -46,11 +45,10 @@ int32_t HorizontalMetricsTable::HMetricAdvanceWidth(int32_t entry) { int32_t HorizontalMetricsTable::HMetricLSB(int32_t entry) { if (entry > num_hmetrics_) { -#if defined (SFNTLY_NO_EXCEPTION) - return 0; -#else +#if !defined (SFNTLY_NO_EXCEPTION) throw IndexOutOfBoundException(); #endif + return 0; } int32_t offset = Offset::kHMetricsStart + (entry * Offset::kHMetricsSize) + Offset::kHMetricsLeftSideBearing; @@ -59,11 +57,10 @@ int32_t HorizontalMetricsTable::HMetricLSB(int32_t entry) { int32_t HorizontalMetricsTable::LsbTableEntry(int32_t entry) { if (entry > num_hmetrics_) { -#if defined (SFNTLY_NO_EXCEPTION) - return 0; -#else +#if !defined (SFNTLY_NO_EXCEPTION) throw IndexOutOfBoundException(); #endif + return 0; } int32_t offset = Offset::kHMetricsStart + (entry * Offset::kHMetricsSize) + Offset::kLeftSideBearingSize; @@ -84,11 +81,6 @@ int32_t HorizontalMetricsTable::LeftSideBearing(int32_t glyph_id) { return LsbTableEntry(glyph_id - num_hmetrics_); } -HorizontalMetricsTable::HorizontalMetricsTable(Header* header, - ReadableFontData* data) - : Table(header, data) { -} - HorizontalMetricsTable::HorizontalMetricsTable(Header* header, ReadableFontData* data, int32_t num_hmetrics, @@ -101,20 +93,16 @@ HorizontalMetricsTable::HorizontalMetricsTable(Header* header, /****************************************************************************** * HorizontalMetricsTable::Builder class ******************************************************************************/ -HorizontalMetricsTable::Builder::Builder( - FontDataTableBuilderContainer* font_builder, - Header* header, - WritableFontData* data) - : Table::TableBasedTableBuilder(font_builder, header, data) { - Init(); +HorizontalMetricsTable::Builder::Builder(Header* header, WritableFontData* data) + : Table::TableBasedTableBuilder(header, data), + num_hmetrics_(-1), + num_glyphs_(-1) { } -HorizontalMetricsTable::Builder::Builder( - FontDataTableBuilderContainer* font_builder, - Header* header, - ReadableFontData* data) - : Table::TableBasedTableBuilder(font_builder, header, data) { - Init(); +HorizontalMetricsTable::Builder::Builder(Header* header, ReadableFontData* data) + : Table::TableBasedTableBuilder(header, data), + num_hmetrics_(-1), + num_glyphs_(-1) { } HorizontalMetricsTable::Builder::~Builder() {} @@ -126,6 +114,14 @@ CALLER_ATTACH FontDataTable* 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); @@ -143,9 +139,4 @@ void HorizontalMetricsTable::Builder::SetNumGlyphs(int32_t num_glyphs) { table->num_glyphs_ = num_glyphs; } -void HorizontalMetricsTable::Builder::Init() { - num_hmetrics_ = -1; - num_glyphs_ = -1; -} - } // namespace sfntly diff --git a/sfntly/table/core/horizontal_metrics_table.h b/sfntly/table/core/horizontal_metrics_table.h index aa3fa65..eaf79e4 100644 --- a/sfntly/table/core/horizontal_metrics_table.h +++ b/sfntly/table/core/horizontal_metrics_table.h @@ -21,29 +21,28 @@ namespace sfntly { +// A Horizontal Metrics table - 'hmtx'. class HorizontalMetricsTable : public Table, public RefCounted { public: + // Builder for a Horizontal Metrics Table - 'hmtx'. class Builder : public Table::TableBasedTableBuilder, public RefCounted { public: // Constructor scope altered to public because C++ does not allow base // class to instantiate derived class with protected constructors. - Builder(FontDataTableBuilderContainer* font_builder, - Header* header, - WritableFontData* data); - Builder(FontDataTableBuilderContainer* font_builder, - Header* header, - ReadableFontData* data); + 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: - void Init(); - int32_t num_hmetrics_; int32_t num_glyphs_; }; @@ -72,7 +71,6 @@ class HorizontalMetricsTable : public Table, }; }; - HorizontalMetricsTable(Header* header, ReadableFontData* data); HorizontalMetricsTable(Header* header, ReadableFontData* data, int32_t num_hmetrics, diff --git a/sfntly/table/core/maximum_profile_table.cc b/sfntly/table/core/maximum_profile_table.cc index fec508a..e457621 100644 --- a/sfntly/table/core/maximum_profile_table.cc +++ b/sfntly/table/core/maximum_profile_table.cc @@ -22,7 +22,7 @@ namespace sfntly { ******************************************************************************/ MaximumProfileTable::~MaximumProfileTable() {} -int32_t MaximumProfileTable::Version() { +int32_t MaximumProfileTable::TableVersion() { return data_->ReadFixed(Offset::kVersion); } @@ -42,6 +42,10 @@ 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); } @@ -82,18 +86,12 @@ MaximumProfileTable::MaximumProfileTable(Header* header, /****************************************************************************** * MaximumProfileTable::Builder class ******************************************************************************/ -MaximumProfileTable::Builder::Builder( - FontDataTableBuilderContainer* font_builder, - Header* header, - WritableFontData* data) - : Table::TableBasedTableBuilder(font_builder, header, data) { +MaximumProfileTable::Builder::Builder(Header* header, WritableFontData* data) + : Table::TableBasedTableBuilder(header, data) { } -MaximumProfileTable::Builder::Builder( - FontDataTableBuilderContainer* font_builder, - Header* header, - ReadableFontData* data) - : Table::TableBasedTableBuilder(font_builder, header, data) { +MaximumProfileTable::Builder::Builder(Header* header, ReadableFontData* data) + : Table::TableBasedTableBuilder(header, data) { } MaximumProfileTable::Builder::~Builder() {} @@ -104,11 +102,19 @@ CALLER_ATTACH FontDataTable* return table.Detach(); } -int32_t MaximumProfileTable::Builder::Version() { +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::SetVersion(int32_t version) { +void MaximumProfileTable::Builder::SetTableVersion(int32_t version) { InternalWriteData()->WriteUShort(Offset::kVersion, version); } @@ -146,6 +152,16 @@ void MaximumProfileTable::Builder::SetMaxCompositePoints( 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); } diff --git a/sfntly/table/core/maximum_profile_table.h b/sfntly/table/core/maximum_profile_table.h index 10ec872..9b89617 100644 --- a/sfntly/table/core/maximum_profile_table.h +++ b/sfntly/table/core/maximum_profile_table.h @@ -22,24 +22,26 @@ namespace sfntly { +// A Maximum Profile table - 'maxp'. class MaximumProfileTable : public Table, public RefCounted { public: + // Builder for a Maximum Profile table - 'maxp'. class Builder : public Table::TableBasedTableBuilder, public RefCounted { public: // Constructor scope altered to public because C++ does not allow base // class to instantiate derived class with protected constructors. - Builder(FontDataTableBuilderContainer* font_builder, Header* header, - WritableFontData* data); - Builder(FontDataTableBuilderContainer* font_builder, Header* header, - ReadableFontData* data); + 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 Version(); - void SetVersion(int32_t version); + int32_t TableVersion(); + void SetTableVersion(int32_t version); int32_t NumGlyphs(); void SetNumGlyphs(int32_t num_glyphs); int32_t MaxPoints(); @@ -48,6 +50,8 @@ class MaximumProfileTable : public Table, 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(); @@ -67,11 +71,12 @@ class MaximumProfileTable : public Table, }; virtual ~MaximumProfileTable(); - int32_t Version(); + 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(); diff --git a/sfntly/table/core/name_table.cc b/sfntly/table/core/name_table.cc index 00c4519..9853130 100644 --- a/sfntly/table/core/name_table.cc +++ b/sfntly/table/core/name_table.cc @@ -137,8 +137,8 @@ NameTable::NameEntryBuilder::NameEntryBuilder() { Init(0, 0, 0, 0, NULL); } -NameTable::NameEntryBuilder::NameEntryBuilder( - const NameEntryId& name_entry_id, const ByteVector& name_bytes) { +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(), @@ -263,7 +263,7 @@ CALLER_ATTACH NameTable::NameEntry* NameTable::NameEntryIterator::Next() { void NameTable::NameEntryIterator::Remove() { #if !defined (SFNTLY_NO_EXCEPTION) throw UnsupportedOperationException( - "Cannot remove a CMap table from an existing font."); + "Cannot remove a name table from an existing font."); #endif } @@ -277,16 +277,20 @@ void NameTable::NameEntryIterator::Init(NameTable* table, /****************************************************************************** * NameTable::Builder class ******************************************************************************/ -NameTable::Builder::Builder(FontDataTableBuilderContainer* font_builder, - Header* header, - WritableFontData* data) - : Table::ArrayElementTableBuilder(font_builder, header, data) { +NameTable::Builder::Builder(Header* header, WritableFontData* data) + : SubTableContainerTable::Builder(header, data) { +} + +NameTable::Builder::Builder(Header* header, ReadableFontData* data) + : SubTableContainerTable::Builder(header, data) { } -NameTable::Builder::Builder(FontDataTableBuilderContainer* font_builder, - Header* header, - ReadableFontData* data) - : Table::ArrayElementTableBuilder(font_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() { @@ -546,7 +550,7 @@ NameTable::NameEntryIterator* NameTable::Iterator(NameEntryFilter* filter) { } NameTable::NameTable(Header* header, ReadableFontData* data) - : Table(header, data) {} + : SubTableContainerTable(header, data) {} int32_t NameTable::StringOffset() { return data_->ReadUShort(Offset::kStringOffset); diff --git a/sfntly/table/core/name_table.h b/sfntly/table/core/name_table.h index b5a7f9a..0c657da 100644 --- a/sfntly/table/core/name_table.h +++ b/sfntly/table/core/name_table.h @@ -26,7 +26,7 @@ #include #include -#include "sfntly/table/table.h" +#include "sfntly/table/subtable_container_table.h" #if defined U_USING_ICU_NAMESPACE U_NAMESPACE_USE @@ -412,7 +412,7 @@ struct WindowsLanguageId { }; }; -class NameTable : public Table, public RefCounted { +class NameTable : public SubTableContainerTable, public RefCounted { public: // Unique identifier for a given name record. class NameEntryId { @@ -433,6 +433,9 @@ class NameTable : public Table, public RefCounted { 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_; @@ -447,8 +450,11 @@ class NameTable : public Table, 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); + 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_; } @@ -469,6 +475,9 @@ class NameTable : public Table, public RefCounted { 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); @@ -494,7 +503,8 @@ class NameTable : public Table, public RefCounted { virtual void SetName(const UChar* name); virtual void SetName(const ByteVector& name_bytes); - virtual void SetName(const ByteVector& name_bytes, int32_t offset, + 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 @@ -515,8 +525,10 @@ class NameTable : public Table, public RefCounted { // returned. class NameEntryFilter { public: - virtual bool Accept(int32_t platform_id, int32_t encoding_id, - int32_t language_id, int32_t name_id) = 0; + 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() {} }; @@ -524,13 +536,17 @@ class NameTable : public Table, public RefCounted { // 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); + 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); + virtual bool Accept(int32_t platform_id, + int32_t encoding_id, + int32_t language_id, + int32_t name_id); private: int32_t platform_id_; @@ -561,15 +577,16 @@ class NameTable : public Table, public RefCounted { }; // The builder to construct name table for outputting. - class Builder : public Table::ArrayElementTableBuilder, + 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(FontDataTableBuilderContainer* font_builder, Header* header, - WritableFontData* data); - Builder(FontDataTableBuilderContainer* font_builder, Header* header, - ReadableFontData* data); + 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. diff --git a/sfntly/table/core/os2_table.cc b/sfntly/table/core/os2_table.cc index 8ab435b..024b03a 100644 --- a/sfntly/table/core/os2_table.cc +++ b/sfntly/table/core/os2_table.cc @@ -100,7 +100,7 @@ int32_t UnicodeRange::range(int32_t bit) { ******************************************************************************/ OS2Table::~OS2Table() {} -int32_t OS2Table::Version() { +int32_t OS2Table::TableVersion() { return data_->ReadUShort(Offset::kVersion); } @@ -165,6 +165,7 @@ int32_t OS2Table::SFamilyClass() { } void OS2Table::Panose(ByteVector* value) { + assert(value); value->clear(); value->resize(10); data_->ReadBytes(Offset::kPanose, &((*value)[0]), 0, 10); @@ -187,6 +188,7 @@ int64_t OS2Table::UlUnicodeRange4() { } void OS2Table::AchVendId(ByteVector* b) { + assert(b); b->clear(); b->resize(4); data_->ReadBytes(Offset::kAchVendId, &((*b)[0]), 0, 4); @@ -232,16 +234,14 @@ int64_t OS2Table::UlCodePageRange2() { return data_->ReadULong(Offset::kUlCodePageRange2); } -int64_t OS2Table::UlCodePageRange() { - // TODO(arthurhsu): Possible bug point, check with stuartg. - return ((0xffffffff & UlCodePageRange2()) << 32) | - (0xffffffff & UlCodePageRange1()); -} - 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); } @@ -261,9 +261,12 @@ OS2Table::OS2Table(Header* header, ReadableFontData* data) /****************************************************************************** * class OS2Table::Builder ******************************************************************************/ -OS2Table::Builder::Builder(FontDataTableBuilderContainer* font_builder, - Header* header, WritableFontData* data) : - Table::TableBasedTableBuilder(font_builder, header, data) { +OS2Table::Builder::Builder(Header* header, WritableFontData* data) : + Table::TableBasedTableBuilder(header, data) { +} + +OS2Table::Builder::Builder(Header* header, ReadableFontData* data) : + Table::TableBasedTableBuilder(header, data) { } OS2Table::Builder::~Builder() {} @@ -274,4 +277,331 @@ CALLER_ATTACH FontDataTable* OS2Table::Builder::SubBuildTable( 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()->WriteBytes(Offset::kAchVendId, + &((*b)[0]), + 0, + std::min( + (size_t)Offset::kAchVendIdLength, + b->size())); +} + +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/sfntly/table/core/os2_table.h b/sfntly/table/core/os2_table.h index 24b6027..cd34ff8 100644 --- a/sfntly/table/core/os2_table.h +++ b/sfntly/table/core/os2_table.h @@ -56,6 +56,7 @@ struct WidthClass { }; }; +// Flags to indicate the embedding licensing rights for a font. struct EmbeddingFlags { enum { kReserved0 = 1 << 0, @@ -79,8 +80,8 @@ struct EmbeddingFlags { struct UnicodeRange { enum { - // This enum relies on the ordering of the data matching the ordinal numbers - // of the properties. + // Do NOT reorder. This enum relies on the ordering of the data matching the + // ordinal numbers of the properties. kBasicLatin, kLatin1Supplement, kLatinExtendedA, @@ -213,6 +214,7 @@ struct UnicodeRange { int32_t range(int32_t bit); // UNIMPLEMENTED: EnumSet asSet(long range1, long range2, // long range3, long range4) + // long[] asArray(EnumSet rangeSet) }; struct FsSelection { @@ -228,6 +230,9 @@ struct FsSelection { 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 @@ -297,22 +302,113 @@ struct CodePageRange { 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 Table::TableBasedTableBuilder, public RefCounted { public: - Builder(FontDataTableBuilderContainer* font_builder, Header* header, - WritableFontData* data); + 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); + 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 Version(); + int32_t TableVersion(); int32_t XAvgCharWidth(); int32_t UsWeightClass(); int32_t UsWidthClass(); @@ -348,7 +444,6 @@ class OS2Table : public Table, public RefCounted { int64_t UlCodePageRange1(); int64_t UlCodePageRange2(); // UNIMPLEMENTED: public EnumSet ulCodePageRange() - int64_t UlCodePageRange(); int32_t SxHeight(); int32_t SCapHeight(); int32_t UsDefaultChar(); @@ -375,11 +470,13 @@ class OS2Table : public Table, public RefCounted { 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, diff --git a/sfntly/table/font_data_table.cc b/sfntly/table/font_data_table.cc index 7be3f77..d662e42 100644 --- a/sfntly/table/font_data_table.cc +++ b/sfntly/table/font_data_table.cc @@ -34,23 +34,18 @@ ReadableFontData* FontDataTable::ReadFontData() { return data_; } -int32_t FontDataTable::Length() { - return data_->Length(); -} - -int32_t FontDataTable::Padding() { - return -1; -} - int32_t FontDataTable::DataLength() { - int32_t paddings = Padding(); - return (paddings == -1) ? Length() : Length() - paddings; + 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 ******************************************************************************/ @@ -61,11 +56,12 @@ CALLER_ATTACH WritableFontData* FontDataTable::Builder::Data() { return NULL; } int32_t size = SubDataSizeToSerialize(); - new_data.Attach(container_->GetNewData(size)); + new_data.Attach(WritableFontData::CreateWritableFontData(size)); SubSerialize(new_data); } else { ReadableFontDataPtr data = InternalReadData(); - new_data.Attach(container_->GetNewData(data != NULL ? data->Length() : 0)); + new_data.Attach(WritableFontData::CreateWritableFontData( + data != NULL ? data->Length() : 0)); data->CopyTo(new_data); } return new_data.Detach(); @@ -85,7 +81,7 @@ CALLER_ATTACH FontDataTable* FontDataTable::Builder::Build() { } int32_t size = SubDataSizeToSerialize(); WritableFontDataPtr new_data; - new_data.Attach(container_->GetNewData(size)); + new_data.Attach(WritableFontData::CreateWritableFontData(size)); SubSerialize(new_data); data = new_data; } @@ -111,43 +107,32 @@ ReadableFontData* FontDataTable::Builder::InternalReadData() { WritableFontData* FontDataTable::Builder::InternalWriteData() { if (w_data_ == NULL) { WritableFontDataPtr new_data; - new_data.Attach(container_->GetNewData(r_data_->Length())); - r_data_->CopyTo(new_data); + new_data.Attach(WritableFontData::CreateWritableFontData( + r_data_ == NULL ? 0 : r_data_->Length())); + if (r_data_) { + r_data_->CopyTo(new_data); + } InternalSetData(new_data, false); } return w_data_.p_; } -CALLER_ATTACH WritableFontData* - FontDataTable::Builder::InternalNewData(int32_t size) { - return container_->GetNewData(size); -} - -FontDataTable::Builder::Builder(FontDataTableBuilderContainer* container) { - Init(container); +FontDataTable::Builder::Builder() { } -FontDataTable::Builder::Builder(FontDataTableBuilderContainer* container, - WritableFontData* data) { - Init(container); +FontDataTable::Builder::Builder(WritableFontData* data) + : model_changed_(false), data_changed_(false) { w_data_ = data; } -FontDataTable::Builder::Builder(FontDataTableBuilderContainer* container, - ReadableFontData* data) { - Init(container); +FontDataTable::Builder::Builder(ReadableFontData* data) + : model_changed_(false), data_changed_(false) { r_data_ = data; } FontDataTable::Builder::~Builder() { } -void FontDataTable::Builder::Init(FontDataTableBuilderContainer* container) { - container_ = container; - model_changed_ = false; - data_changed_ = false; -} - void FontDataTable::Builder::NotifyPostTableBuild(FontDataTable* table) { // Default: NOP. UNREFERENCED_PARAMETER(table); diff --git a/sfntly/table/font_data_table.h b/sfntly/table/font_data_table.h index a2b026f..ce5433b 100644 --- a/sfntly/table/font_data_table.h +++ b/sfntly/table/font_data_table.h @@ -18,11 +18,13 @@ #define SFNTLY_CPP_SRC_SFNTLY_TABLE_FONT_DATA_TABLE_H_ #include "sfntly/data/readable_font_data.h" -#include "sfntly/font_data_table_builder_container.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 @@ -45,10 +47,14 @@ class FontDataTable : virtual public RefCount { ReadableFontData* InternalReadData(); WritableFontData* InternalWriteData(); - CALLER_ATTACH WritableFontData* InternalNewData(int32_t size); bool data_changed() { return data_changed_; } - bool model_changed() { return model_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_; @@ -57,13 +63,11 @@ class FontDataTable : virtual public RefCount { } protected: - explicit Builder(FontDataTableBuilderContainer* container); - Builder(FontDataTableBuilderContainer* container, WritableFontData* data); - Builder(FontDataTableBuilderContainer* container, ReadableFontData* data); + explicit Builder(); + Builder(WritableFontData* data); + Builder(ReadableFontData* data); virtual ~Builder(); - void Init(FontDataTableBuilderContainer* container); - // subclass API virtual void NotifyPostTableBuild(FontDataTable* table); virtual int32_t SubSerialize(WritableFontData* new_data) = 0; @@ -77,10 +81,10 @@ class FontDataTable : virtual public RefCount { void InternalSetData(WritableFontData* data, bool data_changed); void InternalSetData(ReadableFontData* data, bool data_changed); - FontDataTableBuilderContainer* container_; // avoid circular ref-counting WritableFontDataPtr w_data_; ReadableFontDataPtr r_data_; bool model_changed_; + bool contained_model_changed_; // may expand to list of submodel states bool data_changed_; }; @@ -91,21 +95,15 @@ class FontDataTable : virtual public RefCount { ReadableFontData* ReadFontData(); // Get the length of the data for this table in bytes. This is the full - // allocated length of the data and may or may not include any padding. - virtual int32_t Length(); - - // Get the number of bytes of padding used in the table. The padding bytes are - // used to align the table length to a 4 byte boundary. - virtual int32_t Padding(); - - // Return the number of bytes of non-padded data in the table. If the padding - // is unknown or unknowable then the total number of bytes of data in the - // tables is returned. + // 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_; }; diff --git a/sfntly/table/subtable.cc b/sfntly/table/subtable.cc index 4869a97..d70b18c 100644 --- a/sfntly/table/subtable.cc +++ b/sfntly/table/subtable.cc @@ -23,7 +23,7 @@ namespace sfntly { SubTable::~SubTable() {} SubTable::SubTable(ReadableFontData* data) - : FontDataTable(data) { + : FontDataTable(data), padding_(0) { } /****************************************************************************** @@ -31,14 +31,12 @@ SubTable::SubTable(ReadableFontData* data) ******************************************************************************/ SubTable::Builder::~Builder() {} -SubTable::Builder::Builder(FontDataTableBuilderContainer* container, - WritableFontData* data) - : FontDataTable::Builder(container, data) { +SubTable::Builder::Builder(WritableFontData* data) + : FontDataTable::Builder(data) { } -SubTable::Builder::Builder(FontDataTableBuilderContainer* container, - ReadableFontData* data) - : FontDataTable::Builder(container, data) { +SubTable::Builder::Builder(ReadableFontData* data) + : FontDataTable::Builder(data) { } } // namespace sfntly diff --git a/sfntly/table/subtable.h b/sfntly/table/subtable.h index c542881..e5ec748 100644 --- a/sfntly/table/subtable.h +++ b/sfntly/table/subtable.h @@ -32,16 +32,22 @@ class SubTable : public FontDataTable { virtual ~Builder(); protected: - Builder(FontDataTableBuilderContainer* container, WritableFontData* data); - Builder(FontDataTableBuilderContainer* container, ReadableFontData* data); + Builder(WritableFontData* data); + Builder(ReadableFontData* data); }; virtual ~SubTable(); + int32_t padding() { return padding_; } + void set_padding(int32_t padding) { padding_ = padding; } + protected: // Note: constructor refactored in C++ to avoid heavy lifting. // caller need to do data->Slice(offset, length) beforehand. explicit SubTable(ReadableFontData* data); + + private: + int32_t padding_; }; } // namespace sfntly diff --git a/sfntly/table/subtable_container_table.h b/sfntly/table/subtable_container_table.h new file mode 100644 index 0000000..e77ebbb --- /dev/null +++ b/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_ \ No newline at end of file diff --git a/sfntly/table/table.cc b/sfntly/table/table.cc index 568f889..10276aa 100644 --- a/sfntly/table/table.cc +++ b/sfntly/table/table.cc @@ -39,10 +39,6 @@ int64_t Table::CalculatedChecksum() { return data_->Checksum(); } -WritableFontData* Table::GetNewData(int32_t size) { - return font_->GetNewData(size); -} - void Table::SetFont(Font* font) { font_ = font; } @@ -58,8 +54,9 @@ Table::Table(Header* header, ReadableFontData* data) Table::Header::Header(int32_t tag) : tag_(tag), offset_(0), - length_(0), offset_valid_(false), + length_(0), + length_valid_(false), checksum_(0), checksum_valid_(false) { } @@ -67,8 +64,9 @@ Table::Header::Header(int32_t tag) Table::Header::Header(int32_t tag, int32_t length) : tag_(tag), offset_(0), - length_(length), offset_valid_(false), + length_(length), + length_valid_(true), checksum_(0), checksum_valid_(false) { } @@ -79,19 +77,25 @@ Table::Header::Header(int32_t tag, int32_t length) : tag_(tag), offset_(offset), - length_(length), offset_valid_(true), + length_(length), + length_valid_(true), checksum_(checksum), checksum_valid_(true) { } Table::Header::~Header() {} -bool TableHeaderComparator::operator() (const TableHeaderPtr lhs, - const TableHeaderPtr rhs) { +bool HeaderComparatorByOffset::operator() (const TableHeaderPtr lhs, + const TableHeaderPtr rhs) { return lhs->offset_ > rhs->offset_; } +bool HeaderComparatorByTag::operator() (const TableHeaderPtr lhs, + const TableHeaderPtr rhs) { + return lhs->tag_ > rhs->tag_; +} + /****************************************************************************** * Table::Builder class ******************************************************************************/ @@ -102,91 +106,77 @@ Table::Builder::~Builder() { void Table::Builder::NotifyPostTableBuild(FontDataTable* table) { if (model_changed() || data_changed()) { Table* derived_table = down_cast(table); - header_ = new Header(header()->tag(), - derived_table->ReadFontData()->Length()); + derived_table->header_ = new Header(header()->tag(), + derived_table->DataLength()); } } -WritableFontData* Table::Builder::GetNewData(int32_t size) { - UNREFERENCED_PARAMETER(size); - return InternalWriteData(); -} - -CALLER_ATTACH Table::Builder* - Table::Builder::GetBuilder(FontDataTableBuilderContainer* font_builder, - Header* header, - WritableFontData* table_data) { +CALLER_ATTACH +Table::Builder* Table::Builder::GetBuilder(Header* header, + WritableFontData* table_data) { int32_t tag = header->tag(); - TableBuilderPtr builder; 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::cmap) { builder_raw = static_cast( - new CMapTable::Builder(font_builder, header, table_data)); + CMapTable::CreateBuilder(font_builder, header, table_data)); } else*/ if (tag == Tag::head) { builder_raw = static_cast( - new FontHeaderTable::Builder(font_builder, header, table_data)); + FontHeaderTable::Builder::CreateBuilder(header, table_data)); } else if (tag == Tag::hhea) { builder_raw = static_cast( - new HorizontalHeaderTable::Builder(font_builder, header, table_data)); + HorizontalHeaderTable::Builder::CreateBuilder(header, table_data)); } else if (tag == Tag::hmtx) { builder_raw = static_cast( - new HorizontalMetricsTable::Builder(font_builder, header, table_data)); + HorizontalMetricsTable::Builder::CreateBuilder(header, table_data)); } else if (tag == Tag::maxp) { builder_raw = static_cast( - new MaximumProfileTable::Builder(font_builder, header, table_data)); + MaximumProfileTable::Builder::CreateBuilder(header, table_data)); } else if (tag == Tag::name) { builder_raw = static_cast( - new NameTable::Builder(font_builder, header, table_data)); + NameTable::Builder::CreateBuilder(header, table_data)); } else if (tag == Tag::OS_2) { builder_raw = static_cast( - new OS2Table::Builder(font_builder, header, table_data)); + OS2Table::Builder::CreateBuilder(header, table_data)); }/* else if (tag == Tag::PostScript) { builder_raw = static_cast( - new PostScriptTable::Builder(font_builder, header, table_data)); + PostScriptTable::Builder::CreateBuilder(header, table_data)); } else if (tag == Tag::cvt) { builder_raw = static_cast( - new ControlValueTable::Builder(font_builder, header, table_data)); + ControlValueTable::Builder::CreateBuilder(header, table_data)); }*/ else if (tag == Tag::glyf) { builder_raw = static_cast( - new GlyphTable::Builder(font_builder, header, table_data)); + GlyphTable::Builder::CreateBuilder(header, table_data)); } else if (tag == Tag::loca) { builder_raw = static_cast( - new LocaTable::Builder(font_builder, header, table_data)); + LocaTable::Builder::CreateBuilder(header, table_data)); }/* else if (tag == Tag::prep) { builder_raw = static_cast( - new ControlProgramTable::Builder(font_builder, header, table_data)); + ControlProgramTable::Builder::CreateBuilder(header, table_data)); }*/ else if (tag == Tag::bhed) { builder_raw = static_cast( - new FontHeaderTable::Builder(font_builder, header, table_data)); + FontHeaderTable::Builder::CreateBuilder(header, table_data)); } else { builder_raw = static_cast( - new Table::GenericTableBuilder(font_builder, header, table_data)); + Table::GenericTableBuilder::CreateBuilder(header, table_data)); } - builder = builder_raw; - return builder.Detach(); + return builder_raw; } -Table::Builder::Builder(FontDataTableBuilderContainer* font_builder, - Header* header, - WritableFontData* data) - : FontDataTable::Builder(font_builder, data) { +Table::Builder::Builder(Header* header, WritableFontData* data) + : FontDataTable::Builder(data) { header_ = header; } -Table::Builder::Builder(FontDataTableBuilderContainer* font_builder, - Header* header, - ReadableFontData* data) - : FontDataTable::Builder(font_builder, data) { +Table::Builder::Builder(Header* header, ReadableFontData* data) + : FontDataTable::Builder(data) { header_ = header; } -Table::Builder::Builder(FontDataTableBuilderContainer* font_builder, - Header* header) - : FontDataTable::Builder(font_builder) { +Table::Builder::Builder(Header* header) { header_ = header; } @@ -212,24 +202,23 @@ void Table::TableBasedTableBuilder::SubDataSet() { table_ = NULL; } -Table::TableBasedTableBuilder::TableBasedTableBuilder( - FontDataTableBuilderContainer* font_builder, - Header* header, - WritableFontData* data) - : Builder(font_builder, header, data) { +CALLER_ATTACH FontDataTable* Table::TableBasedTableBuilder::Build() { + FontDataTablePtr table = static_cast(GetTable()); + return table.Detach(); +} + +Table::TableBasedTableBuilder::TableBasedTableBuilder(Header* header, + WritableFontData* data) + : Builder(header, data) { } -Table::TableBasedTableBuilder::TableBasedTableBuilder( - FontDataTableBuilderContainer* font_builder, - Header* header, - ReadableFontData* data) - : Builder(font_builder, header, data) { +Table::TableBasedTableBuilder::TableBasedTableBuilder(Header* header, + ReadableFontData* data) + : Builder(header, data) { } -Table::TableBasedTableBuilder::TableBasedTableBuilder( - FontDataTableBuilderContainer* font_builder, - Header* header) - : Builder(font_builder, header) { +Table::TableBasedTableBuilder::TableBasedTableBuilder(Header* header) + : Builder(header) { } Table* Table::TableBasedTableBuilder::GetTable() { @@ -242,11 +231,9 @@ Table* Table::TableBasedTableBuilder::GetTable() { /****************************************************************************** * Table::GenericTableBuilder class ******************************************************************************/ -Table::GenericTableBuilder::GenericTableBuilder( - FontDataTableBuilderContainer* font_builder, - Header* header, - WritableFontData* data) - : TableBasedTableBuilder(font_builder, header, data) { +Table::GenericTableBuilder::GenericTableBuilder(Header* header, + WritableFontData* data) + : TableBasedTableBuilder(header, data) { } CALLER_ATTACH FontDataTable* @@ -257,23 +244,12 @@ CALLER_ATTACH FontDataTable* return table.Detach(); } -/****************************************************************************** - * Table::ArrayElementTableBuilder class - ******************************************************************************/ -Table::ArrayElementTableBuilder::~ArrayElementTableBuilder() {} - -Table::ArrayElementTableBuilder::ArrayElementTableBuilder( - FontDataTableBuilderContainer* font_builder, - Header* header, - WritableFontData* data) - : Builder(font_builder, header, data) { -} - -Table::ArrayElementTableBuilder::ArrayElementTableBuilder( - FontDataTableBuilderContainer* font_builder, - Header* header, - ReadableFontData* data) - : Builder(font_builder, header, data) { +CALLER_ATTACH Table::GenericTableBuilder* + Table::GenericTableBuilder::CreateBuilder(Header* header, + WritableFontData* data) { + Ptr builder = + new Table::GenericTableBuilder(header, data); + return builder.Detach(); } } // namespace sfntly diff --git a/sfntly/table/table.h b/sfntly/table/table.h index 8c8fcc8..5adbfb1 100644 --- a/sfntly/table/table.h +++ b/sfntly/table/table.h @@ -27,61 +27,91 @@ namespace sfntly { class Font; -class Table : public FontDataTable, public FontDataTableBuilderContainer { + +// 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: 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. int32_t offset() { return offset_; } - int32_t length() { return length_; } + + // 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. + 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. + 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_; - int32_t length_; bool offset_valid_; + int32_t length_; + bool length_valid_; int64_t checksum_; bool checksum_valid_; - friend class TableHeaderComparator; + friend class HeaderComparatorByOffset; + friend class HeaderComparatorByTag; }; // Note: original version is Builder // C++ template is not designed that way so plain old inheritance is // chosen. - class Builder : public FontDataTable::Builder, - public FontDataTableBuilderContainer { + class Builder : public FontDataTable::Builder { public: virtual ~Builder(); virtual Header* header() { return header_; } virtual void NotifyPostTableBuild(FontDataTable* table); - virtual WritableFontData* GetNewData(int32_t size); - static CALLER_ATTACH Builder* - GetBuilder(FontDataTableBuilderContainer* font_builder, - Header* header, - WritableFontData* table_data); + // 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: - // Note: original version is Font.Builder font_builder. This results in - // mutual inclusion happiness that Java solved for C++. Therefore, - // we need to avoid that happiness when we port it to C++. - Builder(FontDataTableBuilderContainer* font_builder, - Header* header, - WritableFontData* data); - Builder(FontDataTableBuilderContainer* font_builder, - Header* header, - ReadableFontData* data); - Builder(FontDataTableBuilderContainer* font_builder, - Header* header); + Builder(Header* header, WritableFontData* data); + Builder(Header* header, ReadableFontData* data); + Builder(Header* header); private: Ptr
header_; @@ -95,16 +125,12 @@ class Table : public FontDataTable, public FontDataTableBuilderContainer { virtual bool SubReadyToSerialize(); virtual int32_t SubDataSizeToSerialize(); virtual void SubDataSet(); + virtual CALLER_ATTACH FontDataTable* Build(); protected: - TableBasedTableBuilder(FontDataTableBuilderContainer* font_builder, - Header* header, - WritableFontData* data); - TableBasedTableBuilder(FontDataTableBuilderContainer* font_builder, - Header* header, - ReadableFontData* data); - TableBasedTableBuilder(FontDataTableBuilderContainer* font_builder, - Header* header); + TableBasedTableBuilder(Header* header, WritableFontData* data); + TableBasedTableBuilder(Header* header, ReadableFontData* data); + TableBasedTableBuilder(Header* header); // C++ port: renamed table() to GetTable() virtual Table* GetTable(); @@ -116,33 +142,36 @@ class Table : public FontDataTable, public FontDataTableBuilderContainer { class GenericTableBuilder : public TableBasedTableBuilder, public RefCounted { public: - GenericTableBuilder(FontDataTableBuilderContainer* font_builder, - Header* header, - WritableFontData* data); + GenericTableBuilder(Header* header, WritableFontData* data); virtual CALLER_ATTACH FontDataTable* SubBuildTable(ReadableFontData* data); - }; - - class ArrayElementTableBuilder : public Builder { - public: - virtual ~ArrayElementTableBuilder(); - protected: - ArrayElementTableBuilder(FontDataTableBuilderContainer* font_builder, - Header* header, - WritableFontData* data); - ArrayElementTableBuilder(FontDataTableBuilderContainer* font_builder, - Header* header, - ReadableFontData* data); + static CALLER_ATTACH + GenericTableBuilder* CreateBuilder(Header* header, + WritableFontData* data); }; 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(); } - virtual WritableFontData* GetNewData(int32_t size); + + // UNIMPLEMENTED: toString() + virtual void SetFont(Font* font); protected: @@ -172,11 +201,31 @@ typedef std::pair DataBlockEntry; typedef std::map TableBuilderMap; typedef std::pair TableBuilderEntry; -class TableHeaderComparator { +class HeaderComparator { + public: + virtual ~HeaderComparator() {} + virtual bool operator()(const TableHeaderPtr h1, + const TableHeaderPtr h2) = 0; +}; + +class HeaderComparatorByOffset : public HeaderComparator { public: - bool operator()(const TableHeaderPtr h1, const TableHeaderPtr h2); + virtual ~HeaderComparatorByOffset() {} + virtual bool operator()(const TableHeaderPtr h1, + const TableHeaderPtr h2); }; -typedef std::set TableHeaderSortedSet; + +class HeaderComparatorByTag : public HeaderComparator { + public: + virtual ~HeaderComparatorByTag() {} + virtual bool operator()(const TableHeaderPtr h1, + const TableHeaderPtr h2); +}; + +typedef std::set + HeaderOffsetSortedSet; +typedef std::set + HeaderTagSortedSet; } // namespace sfntly diff --git a/sfntly/table/truetype/glyph_table.cc b/sfntly/table/truetype/glyph_table.cc index ff289f3..dc1163a 100644 --- a/sfntly/table/truetype/glyph_table.cc +++ b/sfntly/table/truetype/glyph_table.cc @@ -52,20 +52,18 @@ GlyphTable::~GlyphTable() { } GlyphTable::Glyph* GlyphTable::GetGlyph(int32_t offset, int32_t length) { - return GlyphTable::Glyph::GetGlyph(data_, offset, length); + return GlyphTable::Glyph::GetGlyph(this, this->data_, offset, length); } GlyphTable::GlyphTable(Header* header, ReadableFontData* data) - : Table(header, data) { + : SubTableContainerTable(header, data) { } /****************************************************************************** * GlyphTable::Builder class ******************************************************************************/ -GlyphTable::Builder::Builder(FontDataTableBuilderContainer* font_builder, - Header* header, - WritableFontData* data) - : Table::ArrayElementTableBuilder(font_builder, header, data) { +GlyphTable::Builder::Builder(Header* header, ReadableFontData* data) + : SubTableContainerTable::Builder(header, data) { } GlyphTable::Builder::~Builder() { @@ -96,6 +94,13 @@ void GlyphTable::Builder::GenerateLocaList(IntegerList* locas) { } } +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(); } @@ -157,12 +162,11 @@ void GlyphTable::Builder::Initialize(ReadableFontData* data, const IntegerList& loca) { if (data != NULL) { if (loca_.empty()) { -#if defined (SFNTLY_NO_EXCEPTION) - return; -#else +#if !defined (SFNTLY_NO_EXCEPTION) throw IllegalStateException( "Loca values not set - unable to parse glyph data."); #endif + return; } int32_t loca_value; int32_t last_loca_value = loca[0]; @@ -199,9 +203,11 @@ void GlyphTable::Builder::Revert() { GlyphTable::Glyph::~Glyph() {} CALLER_ATTACH GlyphTable::Glyph* - GlyphTable::Glyph::GetGlyph(ReadableFontData* data, + 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; @@ -239,10 +245,6 @@ int32_t GlyphTable::Glyph::YMax() { return data_->ReadShort(Offset::kYMax); } -int32_t GlyphTable::Glyph::Padding() { - return padding_; -} - GlyphTable::Glyph::Glyph(ReadableFontData* data, int32_t glyph_type) : SubTable(data), glyph_type_(glyph_type) { @@ -273,38 +275,36 @@ int32_t GlyphTable::Glyph::GlyphType(ReadableFontData* data, GlyphTable::Glyph::Builder::~Builder() { } -GlyphTable::Glyph::Builder::Builder(FontDataTableBuilderContainer* font_builder, - WritableFontData* data) - : SubTable::Builder(font_builder, data) { +GlyphTable::Glyph::Builder::Builder(WritableFontData* data) + : SubTable::Builder(data) { } -GlyphTable::Glyph::Builder::Builder(FontDataTableBuilderContainer* font_builder, - ReadableFontData* data) - : SubTable::Builder(font_builder, data) { +GlyphTable::Glyph::Builder::Builder(ReadableFontData* data) + : SubTable::Builder(data) { } CALLER_ATTACH GlyphTable::Glyph::Builder* GlyphTable::Glyph::Builder::GetBuilder( - FontDataTableBuilderContainer* table_builder, + GlyphTable::Builder* table_builder, ReadableFontData* data) { return GetBuilder(table_builder, data, 0, data->Length()); } CALLER_ATTACH GlyphTable::Glyph::Builder* GlyphTable::Glyph::Builder::GetBuilder( - FontDataTableBuilderContainer* table_builder, + 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(table_builder, sliced_data); + builder = new SimpleGlyph::SimpleGlyphBuilder(sliced_data); } else { - builder = new CompositeGlyph::CompositeGlyphBuilder(table_builder, - sliced_data); + builder = new CompositeGlyph::CompositeGlyphBuilder(sliced_data); } return builder.Detach(); } @@ -411,7 +411,7 @@ void GlyphTable::SimpleGlyph::Initialize() { (flag_byte_count_ * DataSize::kBYTE) + (x_byte_count_ * DataSize::kBYTE) + (y_byte_count_ * DataSize::kBYTE); - padding_ = Length() - non_padded_data_length; + set_padding(DataLength() - non_padded_data_length); initialized_ = true; } @@ -505,15 +505,13 @@ GlyphTable::SimpleGlyph::SimpleGlyphBuilder::~SimpleGlyphBuilder() { } GlyphTable::SimpleGlyph::SimpleGlyphBuilder::SimpleGlyphBuilder( - FontDataTableBuilderContainer* table_builder, WritableFontData* data) - : Glyph::Builder(table_builder, data) { + : Glyph::Builder(data) { } GlyphTable::SimpleGlyph::SimpleGlyphBuilder::SimpleGlyphBuilder( - FontDataTableBuilderContainer* table_builder, ReadableFontData* data) - : Glyph::Builder(table_builder, data) { + : Glyph::Builder(data) { } CALLER_ATTACH FontDataTable* @@ -635,7 +633,7 @@ void GlyphTable::CompositeGlyph::ParseData() { instructions_offset_ = index; non_padded_data_length = index + (instruction_size_ * DataSize::kBYTE); } - padding_ = Length() - non_padded_data_length; + set_padding(DataLength() - non_padded_data_length); } } @@ -646,15 +644,13 @@ GlyphTable::CompositeGlyph::CompositeGlyphBuilder::~CompositeGlyphBuilder() { } GlyphTable::CompositeGlyph::CompositeGlyphBuilder::CompositeGlyphBuilder( - FontDataTableBuilderContainer* table_builder, WritableFontData* data) - : Glyph::Builder(table_builder, data) { + : Glyph::Builder(data) { } GlyphTable::CompositeGlyph::CompositeGlyphBuilder::CompositeGlyphBuilder( - FontDataTableBuilderContainer* table_builder, ReadableFontData* data) - : Glyph::Builder(table_builder, data) { + : Glyph::Builder(data) { } CALLER_ATTACH FontDataTable* diff --git a/sfntly/table/truetype/glyph_table.h b/sfntly/table/truetype/glyph_table.h index 320c522..3ba9cac 100644 --- a/sfntly/table/truetype/glyph_table.h +++ b/sfntly/table/truetype/glyph_table.h @@ -21,6 +21,7 @@ #include "sfntly/table/table.h" #include "sfntly/table/subtable.h" +#include "sfntly/table/subtable_container_table.h" namespace sfntly { @@ -31,10 +32,8 @@ struct GlyphType { }; }; -// Note: due to the complexity of this class, the order of declaration is -// different from its Java counter part. GlyphTable::Glyph is defined -// before GlyphTable::Builder to avoid compilation errors. -class GlyphTable : public Table, public RefCounted { +class GlyphTable : public SubTableContainerTable, + public RefCounted { public: class Builder; class Glyph : public SubTable { @@ -54,16 +53,14 @@ class GlyphTable : public Table, public RefCounted { // Incoming table_builder is GlyphTable::Builder*. // Note: constructor refactored in C++ to avoid heavy lifting. // caller need to do data->Slice(offset, length) beforehand. - Builder(FontDataTableBuilderContainer* table_builder, - WritableFontData* data); - Builder(FontDataTableBuilderContainer* table_builder, - ReadableFontData* data); + Builder(WritableFontData* data); + Builder(ReadableFontData* data); static CALLER_ATTACH Builder* - GetBuilder(FontDataTableBuilderContainer* table_builder, + GetBuilder(GlyphTable::Builder* table_builder, ReadableFontData* data); static CALLER_ATTACH Builder* - GetBuilder(FontDataTableBuilderContainer* table_builder, + GetBuilder(GlyphTable::Builder* table_builder, ReadableFontData* data, int32_t offset, int32_t length); @@ -78,7 +75,8 @@ class GlyphTable : public Table, public RefCounted { }; virtual ~Glyph(); - static CALLER_ATTACH Glyph* GetGlyph(ReadableFontData* data, + static CALLER_ATTACH Glyph* GetGlyph(GlyphTable* table, + ReadableFontData* data, int32_t offset, int32_t length); virtual int32_t GlyphType(); @@ -87,7 +85,6 @@ class GlyphTable : public Table, public RefCounted { virtual int32_t XMax(); virtual int32_t YMin(); virtual int32_t YMax(); - virtual int32_t Padding(); // override FontDataTable::Padding() virtual int32_t InstructionSize() = 0; virtual ReadableFontData* Instructions() = 0; @@ -97,9 +94,6 @@ class GlyphTable : public Table, public RefCounted { // caller need to do data->Slice(offset, length) beforehand. Glyph(ReadableFontData* data, int32_t glyph_type); - // TODO(arthurhsu): violating C++ style guide, need refactoring. - int32_t padding_; - private: static int32_t GlyphType(ReadableFontData* data, int32_t offset, @@ -111,18 +105,19 @@ class GlyphTable : public Table, public RefCounted { typedef Ptr GlyphBuilderPtr; typedef std::vector GlyphBuilderList; - class Builder : public Table::ArrayElementTableBuilder, + class Builder : public SubTableContainerTable::Builder, public RefCounted { public: // Note: Constructor scope altered to public for base class to instantiate. - Builder(FontDataTableBuilderContainer* font_builder, - Header* header, - WritableFontData* data); + 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. @@ -178,10 +173,8 @@ class GlyphTable : public Table, public RefCounted { protected: // Note: constructor refactored in C++ to avoid heavy lifting. // caller need to do data->Slice(offset, length) beforehand. - SimpleGlyphBuilder(FontDataTableBuilderContainer* table_builder, - WritableFontData* data); - SimpleGlyphBuilder(FontDataTableBuilderContainer* table_builder, - ReadableFontData* data); + SimpleGlyphBuilder(WritableFontData* data); + SimpleGlyphBuilder(ReadableFontData* data); virtual CALLER_ATTACH FontDataTable* SubBuildTable(ReadableFontData* data); @@ -251,10 +244,8 @@ class GlyphTable : public Table, public RefCounted { protected: // Note: constructor refactored in C++ to avoid heavy lifting. // caller need to do data->Slice(offset, length) beforehand. - CompositeGlyphBuilder(FontDataTableBuilderContainer* table_builder, - WritableFontData* data); - CompositeGlyphBuilder(FontDataTableBuilderContainer* table_builder, - ReadableFontData* data); + CompositeGlyphBuilder(WritableFontData* data); + CompositeGlyphBuilder(ReadableFontData* data); virtual CALLER_ATTACH FontDataTable* SubBuildTable(ReadableFontData* data); diff --git a/sfntly/table/truetype/loca_table.cc b/sfntly/table/truetype/loca_table.cc index 537e433..0a579ae 100644 --- a/sfntly/table/truetype/loca_table.cc +++ b/sfntly/table/truetype/loca_table.cc @@ -23,28 +23,22 @@ namespace sfntly { ******************************************************************************/ LocaTable::~LocaTable() {} -int32_t LocaTable::NumGlyphs() { - return num_glyphs_; -} - int32_t LocaTable::GlyphOffset(int32_t glyph_id) { if (glyph_id < 0 || glyph_id >= num_glyphs_) { -#if defined (SFNTLY_NO_EXCEPTION) - return 0; -#else +#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) - return 0; -#else +#if !defined (SFNTLY_NO_EXCEPTION) throw IndexOutOfBoundException("Glyph ID is out of bounds."); #endif + return 0; } return Loca(glyph_id + 1) - Loca(glyph_id); } @@ -55,27 +49,24 @@ int32_t LocaTable::NumLocas() { int32_t LocaTable::Loca(int32_t index) { if (index > num_glyphs_) { -#if defined (SFNTLY_NO_EXCEPTION) - return 0; -#else +#if !defined (SFNTLY_NO_EXCEPTION) throw IndexOutOfBoundException(); #endif + return 0; } - if (version_ == IndexToLocFormat::kShortOffset) { + if (format_version_ == IndexToLocFormat::kShortOffset) { return 2 * data_->ReadUShort(index * DataSize::kUSHORT); } return data_->ReadULongAsInt(index * DataSize::kULONG); } -LocaTable::LocaTable(Header* header, ReadableFontData* data) - : Table(header, data) { -} - LocaTable::LocaTable(Header* header, ReadableFontData* data, - int32_t version, + int32_t format_version, int32_t num_glyphs) - : Table(header, data), version_(version), num_glyphs_(num_glyphs) { + : Table(header, data), + format_version_(format_version), + num_glyphs_(num_glyphs) { } /****************************************************************************** @@ -97,22 +88,26 @@ int32_t LocaTable::LocaIterator::Next() { /****************************************************************************** * LocaTable::Builder class ******************************************************************************/ -LocaTable::Builder::Builder(FontDataTableBuilderContainer* font_builder, - Header* header, WritableFontData* data) : - Table::ArrayElementTableBuilder(font_builder, header, data) { - Init(); +LocaTable::Builder::Builder(Header* header, WritableFontData* data) + : Table::Builder(header, data), + format_version_(IndexToLocFormat::kLongOffset), + num_glyphs_(-1) { } -LocaTable::Builder::Builder(FontDataTableBuilderContainer* font_builder, - Header* header, ReadableFontData* data) : - Table::ArrayElementTableBuilder(font_builder, header, data) { - Init(); +LocaTable::Builder::Builder(Header* header, ReadableFontData* data) + : Table::Builder(header, data), + format_version_(IndexToLocFormat::kLongOffset), + num_glyphs_(-1) { } LocaTable::Builder::~Builder() {} -void LocaTable::Builder::SetFormatVersion(int32_t format_version) { - format_version_ = format_version; +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() { @@ -130,22 +125,20 @@ void LocaTable::Builder::SetLocaList(IntegerList* list) { int32_t LocaTable::Builder::GlyphOffset(int32_t glyph_id) { if (glyph_id < 0 || glyph_id > (num_glyphs_ + 1)) { -#if defined (SFNTLY_NO_EXCEPTION) - return 0; -#else +#if !defined (SFNTLY_NO_EXCEPTION) throw IndexOutOfBoundException("Glyph ID is out of bounds."); #endif + return 0; } return Loca(glyph_id); } int32_t LocaTable::Builder::GlyphLength(int32_t glyph_id) { if (glyph_id < 0 || glyph_id > (num_glyphs_ + 1)) { -#if defined (SFNTLY_NO_EXCEPTION) - return 0; -#else +#if !defined (SFNTLY_NO_EXCEPTION) throw IndexOutOfBoundException("Glyph ID is out of bounds."); #endif + return 0; } return Loca(glyph_id + 1) - Loca(glyph_id); } @@ -166,10 +159,6 @@ void LocaTable::Builder::Revert() { set_model_changed(false); } -void LocaTable::Builder::Clear() { - GetLocaList()->clear(); -} - int32_t LocaTable::Builder::NumLocas() { return GetLocaList()->size(); } @@ -178,8 +167,8 @@ int32_t LocaTable::Builder::Loca(int32_t index) { return GetLocaList()->at(index); } -CALLER_ATTACH FontDataTable* LocaTable::Builder::SubBuildTable( - ReadableFontData* data) { +CALLER_ATTACH +FontDataTable* LocaTable::Builder::SubBuildTable(ReadableFontData* data) { FontDataTablePtr table = new LocaTable(header(), data, format_version_, num_glyphs_); return table.Detach(); @@ -216,19 +205,13 @@ int32_t LocaTable::Builder::SubSerialize(WritableFontData* new_data) { return 0; } -void LocaTable::Builder::Init() { - num_glyphs_ = -1; - format_version_ = IndexToLocFormat::kLongOffset; -} - void LocaTable::Builder::Initialize(ReadableFontData* data) { if (data) { if (NumGlyphs() < 0) { -#if defined (SFNTLY_NO_EXCEPTION) - return; -#else +#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_); diff --git a/sfntly/table/truetype/loca_table.h b/sfntly/table/truetype/loca_table.h index ce7fa44..0ec13bd 100644 --- a/sfntly/table/truetype/loca_table.h +++ b/sfntly/table/truetype/loca_table.h @@ -22,6 +22,7 @@ namespace sfntly { +// A Loca table - 'loca'. class LocaTable : public Table, public RefCounted { public: // Note: different implementation than Java, caller to instantiate this class @@ -37,24 +38,33 @@ class LocaTable : public Table, public RefCounted { LocaTable* table_; // use dumb pointer since it's a composition object }; - class Builder : public Table::ArrayElementTableBuilder, - public RefCounted { + class Builder : public Table::Builder, public RefCounted { public: // Constructor scope altered to public for base class to instantiate. - Builder(FontDataTableBuilderContainer* font_builder, Header* header, - WritableFontData* data); - Builder(FontDataTableBuilderContainer* font_builder, Header* header, - ReadableFontData* data); + Builder(Header* header, WritableFontData* data); + Builder(Header* header, ReadableFontData* data); virtual ~Builder(); - void SetFormatVersion(int32_t format_version); + 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. + // 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 @@ -75,15 +85,25 @@ class LocaTable : public Table, public RefCounted { // to be called (and must be) when the raw data for this builder has // been changed. 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(); - void Clear(); // 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); @@ -93,8 +113,15 @@ class LocaTable : public Table, public RefCounted { virtual int32_t SubSerialize(WritableFontData* new_data); private: - void Init(); // short hand for common code in ctors, C++ port only - void Initialize(ReadableFontData* data); // ported from Java + // 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); + + // 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(); int32_t format_version_; // Note: IndexToLocFormat @@ -103,7 +130,9 @@ class LocaTable : public Table, public RefCounted { }; virtual ~LocaTable(); - int32_t NumGlyphs(); + + 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 @@ -127,13 +156,12 @@ class LocaTable : public Table, public RefCounted { int32_t Loca(int32_t index); private: - LocaTable(Header* header, ReadableFontData* data); LocaTable(Header* header, ReadableFontData* data, - int32_t version, + int32_t format_version, int32_t num_glyphs); - int32_t version_; // Note: IndexToLocFormat + int32_t format_version_; // Note: Java's version, renamed to format_version_ int32_t num_glyphs_; friend class LocaIterator; diff --git a/sfntly/tools/subsetter/glyph_table_subsetter.cc b/sfntly/tools/subsetter/glyph_table_subsetter.cc index 644e137..b3d6b07 100644 --- a/sfntly/tools/subsetter/glyph_table_subsetter.cc +++ b/sfntly/tools/subsetter/glyph_table_subsetter.cc @@ -46,11 +46,10 @@ bool GlyphTableSubsetter::Subset(Subsetter* subsetter, 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) - return false; -#else +#if !defined (SFNTLY_NO_EXCEPTION) throw RuntimeException("Font to subset is not valid."); #endif + return false; } GlyphTableBuilderPtr glyph_table_builder = @@ -60,11 +59,10 @@ bool GlyphTableSubsetter::Subset(Subsetter* subsetter, down_cast (font_builder->NewTableBuilder(Tag::loca)); if (glyph_table_builder == NULL || loca_table_builder == NULL) { -#if defined (SFNTLY_NO_EXCEPTION) - return false; -#else +#if !defined (SFNTLY_NO_EXCEPTION) throw RuntimeException("Builder for subset is not valid."); #endif + return false; } GlyphTable::GlyphBuilderList* glyph_builders = glyph_table_builder->GlyphBuilders(); @@ -77,7 +75,7 @@ bool GlyphTableSubsetter::Subset(Subsetter* subsetter, glyph.Attach(glyph_table->GetGlyph(old_offset, old_length)); ReadableFontDataPtr data = glyph->ReadFontData(); WritableFontDataPtr copy_data; - copy_data.Attach(font_builder->GetNewData(data->Length())); + copy_data.Attach(WritableFontData::CreateWritableFontData(data->Length())); data->CopyTo(copy_data); GlyphBuilderPtr glyph_builder; glyph_builder.Attach(glyph_table_builder->GlyphBuilder(copy_data)); diff --git a/sfntly/tools/subsetter/subsetter.cc b/sfntly/tools/subsetter/subsetter.cc index d1b64d9..7d98779 100644 --- a/sfntly/tools/subsetter/subsetter.cc +++ b/sfntly/tools/subsetter/subsetter.cc @@ -56,8 +56,8 @@ CALLER_ATTACH Font::Builder* Subsetter::Subset() { font_builder.Attach(font_factory_->NewFontBuilder()); IntegerSet table_tags; - for (TableMap::iterator i = font_->Tables()->begin(), - e = font_->Tables()->end(); i != e; ++i) { + for (TableMap::const_iterator i = font_->GetTableMap()->begin(), + e = font_->GetTableMap()->end(); i != e; ++i) { table_tags.insert(i->first); } if (!remove_tables_.empty()) { diff --git a/test/font_parsing_test.cc b/test/font_parsing_test.cc index 2e35c20..fb161a6 100644 --- a/test/font_parsing_test.cc +++ b/test/font_parsing_test.cc @@ -32,8 +32,6 @@ namespace sfntly { bool TestFontParsing() { ByteVector input_buffer; LoadFile(SAMPLE_TTF_FILE, &input_buffer); - ByteArrayPtr ba = new MemoryByteArray(&(input_buffer[0]), - input_buffer.size()); FontFactoryPtr factory; factory.Attach(FontFactory::GetInstance()); @@ -43,7 +41,7 @@ bool TestFontParsing() { FontBuilderPtr font_builder = font_builder_array[0]; // Memory based FontBuilderArray font_builder_array2; - factory->LoadFontsForBuilding(ba, &font_builder_array2); + factory->LoadFontsForBuilding(&input_buffer, &font_builder_array2); FontBuilderPtr font_builder2 = font_builder_array2[0]; for (size_t i = 0; i < SAMPLE_TTF_KNOWN_TAGS; ++i) { @@ -121,9 +119,7 @@ bool TestTTFMemoryBasedReadWrite() { FontFactoryPtr factory; factory.Attach(FontFactory::GetInstance()); FontBuilderArray font_builder_array; - ByteArrayPtr ba = new MemoryByteArray(&(input_buffer[0]), - input_buffer.size()); - factory->LoadFontsForBuilding(ba, &font_builder_array); + factory->LoadFontsForBuilding(&input_buffer, &font_builder_array); FontBuilderPtr font_builder = font_builder_array[0]; FontPtr font; font.Attach(font_builder->Build()); diff --git a/test/memory_io_test.cc b/test/memory_io_test.cc new file mode 100755 index 0000000..b34e1e7 --- /dev/null +++ b/test/memory_io_test.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 + +#include + +#include "gtest/gtest.h" +#include "sfntly/port/memory_input_stream.h" +#include "sfntly/port/memory_output_stream.h" +#include "sfntly/port/type.h" + +namespace { + const char* kTestData = +"01234567890123456789012345678901234567890123456789" // 50 +"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwx" // 100 +"yz"; // 102 + const size_t kTestBufferLen = 102; +} + +namespace sfntly { + +bool TestMemoryInputStream() { + ByteVector test_buffer; + test_buffer.resize(kTestBufferLen); + std::copy(kTestData, kTestData + kTestBufferLen, test_buffer.begin()); + + MemoryInputStream is; + is.Attach(&(test_buffer[0]), kTestBufferLen); + EXPECT_EQ(is.Available(), (int32_t)kTestBufferLen); + + // Read one byte + EXPECT_EQ(is.Read(), '0'); // position 1 + EXPECT_EQ(is.Read(), '1'); // position 2 + EXPECT_EQ(is.Read(), '2'); // position 3 + + // Read byte vector + ByteVector b; + b.resize(7); + EXPECT_EQ(is.Read(&b), 7); // position 10 + EXPECT_EQ(memcmp(&(b[0]), &(test_buffer[0]) + 3, 7), 0); + + b.resize(17); + EXPECT_EQ(is.Read(&b, 7, 10), 10); // position 20 + EXPECT_EQ(memcmp(&(b[0]), &(test_buffer[0]) + 3, 17), 0); + + // Test skip + b.clear(); + b.resize(10); + EXPECT_EQ(is.Skip(30), 30); // position 50 + EXPECT_EQ(is.Read(&b), 10); // position 60 + EXPECT_EQ(memcmp(&(b[0]), &(test_buffer[0]) + 50, 10), 0); + b.clear(); + b.resize(10); + EXPECT_EQ(is.Skip(-20), -20); // position 40 + EXPECT_EQ(is.Read(&b), 10); // position 50 + EXPECT_EQ(memcmp(&(b[0]), &(test_buffer[0]) + 40, 10), 0); + + EXPECT_EQ(is.Available(), (int32_t)kTestBufferLen - 50); + EXPECT_EQ(is.Skip(-60), -50); // Out of bound, position 0 + EXPECT_EQ(is.Skip(kTestBufferLen + 10), (int32_t)kTestBufferLen); + + b.clear(); + b.resize(10); + is.Unread(&b); + EXPECT_EQ(memcmp(&(b[0]), &(test_buffer[0]) + kTestBufferLen - 10, 10), 0); + + return true; +} + +bool TestMemoryOutputStream() { + ByteVector test_buffer; + test_buffer.resize(kTestBufferLen); + std::copy(kTestData, kTestData + kTestBufferLen, test_buffer.begin()); + + MemoryOutputStream os; + os.Write(&(test_buffer[0]), (int32_t)50, (int32_t)(kTestBufferLen - 50)); + EXPECT_EQ(os.Size(), kTestBufferLen - 50); + EXPECT_EQ(memcmp(os.Get(), &(test_buffer[0]) + 50, kTestBufferLen - 50), 0); + + return true; +} + +} // namespace sfntly + +TEST(MemoryIO, All) { + ASSERT_TRUE(sfntly::TestMemoryInputStream()); + ASSERT_TRUE(sfntly::TestMemoryOutputStream()); +} diff --git a/test/name_editing_test.cc b/test/name_editing_test.cc index ce12cd3..260d9d4 100644 --- a/test/name_editing_test.cc +++ b/test/name_editing_test.cc @@ -24,9 +24,10 @@ #include "sfntly/data/memory_byte_array.h" #include "sfntly/font.h" #include "sfntly/font_factory.h" +#include "sfntly/port/memory_input_stream.h" +#include "sfntly/port/memory_output_stream.h" #include "sfntly/table/core/name_table.h" #include "sfntly/tag.h" -#include "sfntly/port/memory_output_stream.h" #include "test/test_data.h" #include "test/test_font_utils.h" @@ -40,11 +41,7 @@ void LoadTestFile(FontFactory* factory, FontBuilderArray* font_builders) { if (input_buffer.empty()) { LoadFile(SAMPLE_TTF_FILE, &input_buffer); } - - ByteArrayPtr ba = - new MemoryByteArray(&(input_buffer[0]), input_buffer.size()); - - factory->LoadFontsForBuilding(ba, font_builders); + factory->LoadFontsForBuilding(&input_buffer, font_builders); } bool TestChangeOneName() { @@ -73,9 +70,10 @@ bool TestChangeOneName() { // Serialize and reload the serialized font. MemoryOutputStream os; factory->SerializeFont(font, &os); + MemoryInputStream is; + is.Attach(os.Get(), os.Size()); FontArray font_array; - ByteArrayPtr new_ba = new MemoryByteArray(os.Get(), os.Size()); - factory->LoadFonts(new_ba, &font_array); + factory->LoadFonts(&is, &font_array); FontPtr new_font = font_array[0]; // Check the font name. @@ -121,9 +119,10 @@ bool TestModifyNameTableAndRevert() { // Serialize and reload the serialized font. MemoryOutputStream os; factory->SerializeFont(font, &os); + MemoryInputStream is; + is.Attach(os.Get(), os.Size()); FontArray font_array; - ByteArrayPtr new_ba = new MemoryByteArray(os.Get(), os.Size()); - factory->LoadFonts(new_ba, &font_array); + factory->LoadFonts(&is, &font_array); FontPtr new_font = font_array[0]; // Check the font name. @@ -166,9 +165,10 @@ bool TestRemoveOneName() { // Serialize and reload the serialized font. MemoryOutputStream os; factory->SerializeFont(font, &os); + MemoryInputStream is; + is.Attach(os.Get(), os.Size()); FontArray font_array; - ByteArrayPtr new_ba = new MemoryByteArray(os.Get(), os.Size()); - factory->LoadFonts(new_ba, &font_array); + factory->LoadFonts(&is, &font_array); FontPtr new_font = font_array[0]; // Check the font name. diff --git a/test/otf_basic_editing_test.cc b/test/otf_basic_editing_test.cc index 32ba248..c99a3a3 100644 --- a/test/otf_basic_editing_test.cc +++ b/test/otf_basic_editing_test.cc @@ -39,6 +39,7 @@ bool TestOTFBasicEditing() { EXPECT_TRUE(font_builder != NULL); TableBuilderMap* builder_map = font_builder->table_builders(); EXPECT_TRUE(builder_map != NULL); + IntegerSet builder_tags; for (TableBuilderMap::iterator i = builder_map->begin(), e = builder_map->end(); i != e; ++i) { EXPECT_TRUE(i->second != NULL); @@ -47,11 +48,11 @@ bool TestOTFBasicEditing() { int32_t value = ToBE32(i->first); memcpy(tag, &value, 4); fprintf(stderr, "tag %s does not have valid builder\n", tag); + } else { + builder_tags.insert(i->first); } } - IntegerSet builder_tags; - font_builder->TableBuilderTags(&builder_tags); FontHeaderTableBuilderPtr header_builder = down_cast( font_builder->GetTableBuilder(Tag::head)); @@ -61,9 +62,9 @@ bool TestOTFBasicEditing() { font.Attach(font_builder->Build()); // ensure every table had a builder - TableMap* table_map = font->Tables(); - for (TableMap::iterator i = table_map->begin(), e = table_map->end(); - i != e; ++i) { + const TableMap* table_map = font->GetTableMap(); + for (TableMap::const_iterator i = table_map->begin(), e = table_map->end(); + i != e; ++i) { TablePtr table = (*i).second; TableHeaderPtr header = table->header(); EXPECT_TRUE(builder_tags.find(header->tag()) != builder_tags.end()); diff --git a/test/serialization_test.cc b/test/serialization_test.cc index 08c8288..3df6d95 100755 --- a/test/serialization_test.cc +++ b/test/serialization_test.cc @@ -17,7 +17,8 @@ #include "gtest/gtest.h" #include "sfntly/font.h" #include "sfntly/font_factory.h" -#include "sfntly/data/memory_byte_array.h" +#include "sfntly/port/memory_input_stream.h" +#include "sfntly/port/memory_output_stream.h" #include "test/test_data.h" #include "test/test_font_utils.h" #include "test/serialization_test.h" @@ -43,20 +44,21 @@ bool TestSerialization() { factory3.Attach(FontFactory::GetInstance()); FontArray new_font_array; - ByteArrayPtr ba = new MemoryByteArray(os.Get(), os.Size()); - factory3->LoadFonts(ba, &new_font_array); + MemoryInputStream is; + is.Attach(os.Get(), os.Size()); + factory3->LoadFonts(&is, &new_font_array); FontPtr serialized = new_font_array[0]; // Check number of tables EXPECT_EQ(original->num_tables(), serialized->num_tables()); // Check if same set of tables - TableMap* original_tables = original->Tables(); - TableMap* serialized_tables = serialized->Tables(); + const TableMap* original_tables = original->GetTableMap(); + const TableMap* serialized_tables = serialized->GetTableMap(); EXPECT_EQ(original_tables->size(), serialized_tables->size()); - TableMap::iterator not_found = serialized_tables->end(); - for (TableMap::iterator b = original_tables->begin(), - e = original_tables->end(); b != e; ++b) { + TableMap::const_iterator not_found = serialized_tables->end(); + for (TableMap::const_iterator b = original_tables->begin(), + e = original_tables->end(); b != e; ++b) { EXPECT_TRUE((serialized_tables->find(b->first) != not_found)); } @@ -67,7 +69,7 @@ bool TestSerialization() { TablePtr serialized_table = serialized->GetTable(TTF_KNOWN_TAGS[i]); EXPECT_EQ(original_table->CalculatedChecksum(), serialized_table->CalculatedChecksum()); - EXPECT_EQ(original_table->Length(), serialized_table->Length()); + EXPECT_EQ(original_table->DataLength(), serialized_table->DataLength()); if (TTF_KNOWN_TAGS[i] == Tag::hhea) { EXPECT_TRUE(VerifyHHEA(original_table, serialized_table)); diff --git a/test/subsetter_impl.cc b/test/subsetter_impl.cc index 572f00e..f82a674 100644 --- a/test/subsetter_impl.cc +++ b/test/subsetter_impl.cc @@ -28,6 +28,7 @@ #include "sfntly/table/truetype/loca_table.h" #include "sfntly/tag.h" #include "sfntly/data/memory_byte_array.h" +#include "sfntly/port/memory_input_stream.h" #include "sfntly/port/memory_output_stream.h" namespace sfntly { @@ -81,14 +82,14 @@ SubsetterImpl::~SubsetterImpl() { bool SubsetterImpl::LoadFont(const char* font_name, const unsigned char* original_font, size_t font_size) { - ByteArrayPtr raw_font = - new MemoryByteArray((byte_t*)original_font, font_size); + MemoryInputStream mis; + mis.Attach(original_font, font_size); if (factory_ == NULL) { factory_.Attach(FontFactory::GetInstance()); } FontArray font_array; - factory_->LoadFonts(raw_font, &font_array); + factory_->LoadFonts(&mis, &font_array); font_ = FindFont(font_name, font_array); if (font_ == NULL) { return false; @@ -223,7 +224,7 @@ bool SubsetterImpl::ResolveCompositeGlyphs(const unsigned int* glyph_ids, IntegerSet comp_glyph_id; for (IntegerSet::iterator i = glyph_id_remaining.begin(), e = glyph_id_remaining.end(); i != e; ++i) { - if (*i < 0 || *i >= loca_table->NumGlyphs()) { + if (*i < 0 || *i >= loca_table->num_glyphs()) { // Invalid glyph id, ignore. continue; } @@ -285,7 +286,7 @@ CALLER_ATTACH Font* SubsetterImpl::Subset(const IntegerSet& glyph_ids) { // Extract glyphs and setup loca list. IntegerList loca_list; - loca_list.resize(loca_table->NumGlyphs()); + loca_list.resize(loca_table->num_glyphs()); loca_list.push_back(0); int32_t last_glyph_id = 0; int32_t last_offset = 0; @@ -302,7 +303,7 @@ CALLER_ATTACH Font* SubsetterImpl::Subset(const IntegerSet& glyph_ids) { // Add glyph to new glyf table. ReadableFontDataPtr data = glyph->ReadFontData(); WritableFontDataPtr copy_data; - copy_data.Attach(font_builder->GetNewData(data->Length())); + copy_data.Attach(WritableFontData::CreateWritableFontData(data->Length())); data->CopyTo(copy_data); GlyphBuilderPtr glyph_builder; glyph_builder.Attach(glyph_table_builder->GlyphBuilder(copy_data)); @@ -316,14 +317,14 @@ CALLER_ATTACH Font* SubsetterImpl::Subset(const IntegerSet& glyph_ids) { loca_list[*i + 1] = last_offset; last_glyph_id = *i; } - for (int32_t j = last_glyph_id + 1; j <= loca_table->NumGlyphs(); ++j) { + for (int32_t j = last_glyph_id + 1; j <= loca_table->num_glyphs(); ++j) { loca_list[j] = last_offset; } loca_table_builder->SetLocaList(&loca_list); // Setup remaining builders. - for (TableMap::iterator i = font_->Tables()->begin(), - e = font_->Tables()->end(); i != e; ++i) { + for (TableMap::const_iterator i = font_->GetTableMap()->begin(), + e = font_->GetTableMap()->end(); i != e; ++i) { // We already build the builder for glyph and loca. if (i->first != Tag::glyf && i->first != Tag::loca) { font_builder->NewTableBuilder(i->first, i->second->ReadFontData()); diff --git a/test/test_font_utils.cc b/test/test_font_utils.cc index 99b65fe..d59b52b 100644 --- a/test/test_font_utils.cc +++ b/test/test_font_utils.cc @@ -49,17 +49,15 @@ void LoadFont(const char* font_path, FontFactory* factory, FontArray* fonts) { is.Close(); } -void LoadFontUsingByteArray(const char* font_path, +void LoadFontUsingByteVector(const char* font_path, bool fingerprint, FontArray* fonts) { - ByteArrayPtr b = new GrowableMemoryByteArray; ByteVector bv; LoadFile(font_path, &bv); - b->Put(0, &bv); FontFactoryPtr factory; factory.Attach(FontFactory::GetInstance()); factory->FingerprintFont(fingerprint); - factory->LoadFonts(b, fonts); + factory->LoadFonts(&bv, fonts); } void LoadFile(const char* input_file_path, ByteVector* input_buffer) { diff --git a/test/test_font_utils.h b/test/test_font_utils.h index b8a93b9..57fde7a 100644 --- a/test/test_font_utils.h +++ b/test/test_font_utils.h @@ -27,7 +27,7 @@ void BuilderForFontFile(const char* font_path, FontFactory* factory, FontBuilderArray* builders); void SerializeFont(const char* font_path, FontFactory* factory, Font* font); void LoadFont(const char* font_path, FontFactory* factory, FontArray* fonts); -void LoadFontUsingByteArray(const char* font_path, +void LoadFontUsingByteVector(const char* font_path, bool fingerprint, FontArray* fonts); diff --git a/test/verify_hhea.cc b/test/verify_hhea.cc index 491238a..05886d4 100644 --- a/test/verify_hhea.cc +++ b/test/verify_hhea.cc @@ -37,7 +37,7 @@ static bool VerifyHHEA(Table* table) { return false; } - EXPECT_EQ(hhea->Version(), SFNTVERSION_1); + EXPECT_EQ(hhea->TableVersion(), SFNTVERSION_1); EXPECT_EQ(hhea->Ascender(), HHEA_ASCENDER); EXPECT_EQ(hhea->Descender(), HHEA_DESCENDER); EXPECT_EQ(hhea->AdvanceWidthMax(), HHEA_ADVANCE_WIDTH_MAX); diff --git a/test/verify_loca.cc b/test/verify_loca.cc index 0e36ce8..3090841 100644 --- a/test/verify_loca.cc +++ b/test/verify_loca.cc @@ -230,7 +230,7 @@ static bool VerifyLOCA(Table* table) { } EXPECT_EQ(loca->NumLocas(), LOCA_NUM_LOCAS); - EXPECT_EQ(loca->NumGlyphs(), LOCA_NUM_LOCAS - 1); + EXPECT_EQ(loca->num_glyphs(), LOCA_NUM_LOCAS - 1); for (int32_t i = 0; i < LOCA_NUM_LOCAS - 1; ++i) { EXPECT_EQ(loca->GlyphOffset(i), LOCAS[i]); diff --git a/test/verify_maxp.cc b/test/verify_maxp.cc index 3bd4490..3b8e183 100644 --- a/test/verify_maxp.cc +++ b/test/verify_maxp.cc @@ -42,13 +42,12 @@ static bool VerifyMAXP(Table* table) { return false; } - EXPECT_EQ(maxp->Version(), SFNTVERSION_1); + EXPECT_EQ(maxp->TableVersion(), SFNTVERSION_1); EXPECT_EQ(maxp->NumGlyphs(), MAXP_NUM_GLYPHS); EXPECT_EQ(maxp->MaxPoints(), MAXP_MAX_POINTS); EXPECT_EQ(maxp->MaxContours(), MAXP_MAX_CONTOURS); EXPECT_EQ(maxp->MaxCompositePoints(), MAXP_MAX_COMPOSITE_POINTS); - // TODO(arthurhsu): maxCompositeContours observed in Microsoft TTF report. - // Check with stuartg and see if this is a miss. + EXPECT_EQ(maxp->MaxCompositeContours(), MAXP_MAX_COMPOSITE_CONTOURS); EXPECT_EQ(maxp->MaxZones(), MAXP_MAX_ZONES); EXPECT_EQ(maxp->MaxTwilightPoints(), MAXP_MAX_TWILIGHT_POINTS); EXPECT_EQ(maxp->MaxStorage(), MAXP_MAX_STORAGE); diff --git a/test/verify_os2.cc b/test/verify_os2.cc index 8f6b9ed..4713e44 100644 --- a/test/verify_os2.cc +++ b/test/verify_os2.cc @@ -60,7 +60,7 @@ static bool VerifyOS_2(Table* table) { return false; } - EXPECT_EQ(os2->Version(), OS2_VERSION); + EXPECT_EQ(os2->TableVersion(), OS2_VERSION); EXPECT_EQ(os2->XAvgCharWidth(), OS2_XAVG_CHAR_WIDTH); EXPECT_EQ(os2->UsWeightClass(), OS2_US_WEIGHT_CLASS); EXPECT_EQ(os2->UsWidthClass(), OS2_US_WIDTH_CLASS); @@ -107,7 +107,6 @@ static bool VerifyOS_2(Table* table) { EXPECT_EQ(os2->UlCodePageRange1(), OS2_UL_CODE_PAGE_RANGE1); EXPECT_EQ(os2->UlCodePageRange2(), OS2_UL_CODE_PAGE_RANGE2); - // TODO(arthurhsu): UlCodePageRange() not tested // TODO(arthurhsu): SxHeight() not tested // TODO(arthurhsu): SCapHeight() not tested // TODO(arthurhsu): UsDefaultChar() not tested -- cgit v1.2.3 From 6b8e073e978eed96605da6f92d6db740a39864ba Mon Sep 17 00:00:00 2001 From: "arthurhsu@google.com" Date: Thu, 8 Sep 2011 21:42:50 +0000 Subject: Advance C++ port to Sep 1 11 snapshot Update test font to use OFL-compliant fonts git-svn-id: http://sfntly.googlecode.com/svn/trunk/cpp/src@71 672e30a5-4c29-85ac-ac6d-611c735e0a51 --- sfntly/data/readable_font_data.cc | 23 +++ sfntly/data/readable_font_data.h | 21 ++- sfntly/data/writable_font_data.cc | 17 ++ sfntly/data/writable_font_data.h | 16 ++ sfntly/font.cc | 22 ++- sfntly/font.h | 2 +- sfntly/table/bitmap/bitmap_glyph.cc | 66 ++++++++ sfntly/table/bitmap/bitmap_glyph.h | 102 ++++++++++++ sfntly/table/bitmap/bitmap_size_table.cc | 147 +++++++++++++++++ sfntly/table/bitmap/bitmap_size_table.h | 68 ++++++++ sfntly/table/bitmap/composite_bitmap_glyph.cc | 89 +++++++++++ sfntly/table/bitmap/composite_bitmap_glyph.h | 65 ++++++++ sfntly/table/bitmap/ebdt_table.cc | 109 +++++++++++++ sfntly/table/bitmap/ebdt_table.h | 67 ++++++++ sfntly/table/bitmap/eblc_table.cc | 119 ++++++++++++++ sfntly/table/bitmap/eblc_table.h | 154 ++++++++++++++++++ sfntly/table/bitmap/index_sub_table.cc | 137 ++++++++++++++++ sfntly/table/bitmap/index_sub_table.h | 64 ++++++++ sfntly/table/bitmap/index_sub_table_format1.cc | 67 ++++++++ sfntly/table/bitmap/index_sub_table_format1.h | 49 ++++++ sfntly/table/bitmap/index_sub_table_format2.cc | 64 ++++++++ sfntly/table/bitmap/index_sub_table_format2.h | 51 ++++++ sfntly/table/bitmap/index_sub_table_format3.cc | 67 ++++++++ sfntly/table/bitmap/index_sub_table_format3.h | 49 ++++++ sfntly/table/bitmap/index_sub_table_format4.cc | 88 ++++++++++ sfntly/table/bitmap/index_sub_table_format4.h | 49 ++++++ sfntly/table/bitmap/index_sub_table_format5.cc | 65 ++++++++ sfntly/table/bitmap/index_sub_table_format5.h | 46 ++++++ sfntly/table/bitmap/simple_bitmap_glyph.cc | 28 ++++ sfntly/table/bitmap/simple_bitmap_glyph.h | 33 ++++ sfntly/table/core/font_header_table.cc | 4 +- sfntly/table/core/font_header_table.h | 4 +- sfntly/table/core/horizontal_header_table.cc | 4 +- sfntly/table/core/horizontal_header_table.h | 4 +- sfntly/table/core/horizontal_metrics_table.cc | 8 +- sfntly/table/core/horizontal_metrics_table.h | 4 +- sfntly/table/core/maximum_profile_table.cc | 4 +- sfntly/table/core/maximum_profile_table.h | 4 +- sfntly/table/core/os2_table.cc | 21 +-- sfntly/table/core/os2_table.h | 8 +- sfntly/table/font_data_table.cc | 27 +++- sfntly/table/header.cc | 66 ++++++++ sfntly/table/header.h | 108 +++++++++++++ sfntly/table/table.cc | 134 ++-------------- sfntly/table/table.h | 125 +-------------- sfntly/table/table_based_table_builder.cc | 93 +++++++++++ sfntly/table/table_based_table_builder.h | 59 +++++++ sfntly/tag.cc | 11 ++ sfntly/tag.h | 24 ++- test/bitmap_table_test.cc | 98 ++++++++++++ test/file_io_test.cc | 19 +-- test/font_parsing_test.cc | 22 +-- test/otf_basic_editing_test.cc | 2 +- test/test_data.cc | 57 ++++--- test/test_data.h | 9 +- test/verify_glyf.cc | 2 +- test/verify_hhea.cc | 14 +- test/verify_hmtx.cc | 202 ++--------------------- test/verify_loca.cc | 212 ++----------------------- test/verify_maxp.cc | 14 +- test/verify_name.cc | 26 +-- test/verify_os2.cc | 18 +-- 62 files changed, 2546 insertions(+), 805 deletions(-) create mode 100644 sfntly/table/bitmap/bitmap_glyph.cc create mode 100644 sfntly/table/bitmap/bitmap_glyph.h create mode 100644 sfntly/table/bitmap/bitmap_size_table.cc create mode 100644 sfntly/table/bitmap/bitmap_size_table.h create mode 100644 sfntly/table/bitmap/composite_bitmap_glyph.cc create mode 100644 sfntly/table/bitmap/composite_bitmap_glyph.h create mode 100644 sfntly/table/bitmap/ebdt_table.cc create mode 100644 sfntly/table/bitmap/ebdt_table.h create mode 100644 sfntly/table/bitmap/eblc_table.cc create mode 100644 sfntly/table/bitmap/eblc_table.h create mode 100644 sfntly/table/bitmap/index_sub_table.cc create mode 100644 sfntly/table/bitmap/index_sub_table.h create mode 100644 sfntly/table/bitmap/index_sub_table_format1.cc create mode 100644 sfntly/table/bitmap/index_sub_table_format1.h create mode 100644 sfntly/table/bitmap/index_sub_table_format2.cc create mode 100644 sfntly/table/bitmap/index_sub_table_format2.h create mode 100644 sfntly/table/bitmap/index_sub_table_format3.cc create mode 100644 sfntly/table/bitmap/index_sub_table_format3.h create mode 100644 sfntly/table/bitmap/index_sub_table_format4.cc create mode 100644 sfntly/table/bitmap/index_sub_table_format4.h create mode 100644 sfntly/table/bitmap/index_sub_table_format5.cc create mode 100644 sfntly/table/bitmap/index_sub_table_format5.h create mode 100644 sfntly/table/bitmap/simple_bitmap_glyph.cc create mode 100644 sfntly/table/bitmap/simple_bitmap_glyph.h create mode 100644 sfntly/table/header.cc create mode 100644 sfntly/table/header.h create mode 100644 sfntly/table/table_based_table_builder.cc create mode 100644 sfntly/table/table_based_table_builder.h create mode 100644 test/bitmap_table_test.cc diff --git a/sfntly/data/readable_font_data.cc b/sfntly/data/readable_font_data.cc index 6ceb38c..ec67757 100644 --- a/sfntly/data/readable_font_data.cc +++ b/sfntly/data/readable_font_data.cc @@ -191,6 +191,29 @@ int32_t ReadableFontData::SearchUShort(int32_t start_index, 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, diff --git a/sfntly/data/readable_font_data.h b/sfntly/data/readable_font_data.h index 34d7179..a0d341f 100644 --- a/sfntly/data/readable_font_data.h +++ b/sfntly/data/readable_font_data.h @@ -181,11 +181,9 @@ class ReadableFontData : public FontData, 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 + // 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 @@ -201,13 +199,26 @@ class ReadableFontData : public FontData, 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 diff --git a/sfntly/data/writable_font_data.cc b/sfntly/data/writable_font_data.cc index c690956..0b271a3 100644 --- a/sfntly/data/writable_font_data.cc +++ b/sfntly/data/writable_font_data.cc @@ -71,6 +71,23 @@ int32_t WritableFontData::WriteBytes(int32_t index, ByteVector* 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))); + for (; written < length; written++) { + array_->Put(written + index, pad); + } + return written; +} + int32_t WritableFontData::WriteChar(int32_t index, byte_t c) { return WriteByte(index, c); } diff --git a/sfntly/data/writable_font_data.h b/sfntly/data/writable_font_data.h index 7fac998..9a9bd7b 100644 --- a/sfntly/data/writable_font_data.h +++ b/sfntly/data/writable_font_data.h @@ -69,6 +69,22 @@ class WritableFontData : public ReadableFontData { // 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); + // Write the CHAR at the given index. // @param index index into the font data // @param c the CHAR diff --git a/sfntly/font.cc b/sfntly/font.cc index e5e4401..524932b 100644 --- a/sfntly/font.cc +++ b/sfntly/font.cc @@ -99,9 +99,9 @@ void Font::BuildTableHeadersForSerialization(IntegerList* table_ordering, } TablePtr table = tables_[*tag]; if (table != NULL) { - TableHeaderPtr header = - new Table::Header(*tag, table->CalculatedChecksum(), table_offset, - table->header()->length()); + HeaderPtr header = + new Header(*tag, table->CalculatedChecksum(), table_offset, + table->header()->length()); table_headers->push_back(header); table_offset += (table->DataLength() + 3) & ~3; } @@ -283,7 +283,7 @@ Table::Builder* Font::Builder::GetTableBuilder(int32_t tag) { } Table::Builder* Font::Builder::NewTableBuilder(int32_t tag) { - TableHeaderPtr header = new Table::Header(tag); + HeaderPtr header = new Header(tag); TableBuilderPtr builder; builder.Attach(Table::Builder::GetBuilder(header, NULL)); table_builders_.insert(TableBuilderEntry(header->tag(), builder)); @@ -304,7 +304,7 @@ Table::Builder* Font::Builder::NewTableBuilder(int32_t tag, return NULL; } #endif - TableHeaderPtr header = new Table::Header(tag, data->Length()); + HeaderPtr header = new Header(tag, data->Length()); TableBuilderPtr builder; builder.Attach(Table::Builder::GetBuilder(header, data)); table_builders_.insert(TableBuilderEntry(tag, builder)); @@ -361,7 +361,7 @@ void Font::Builder::BuildAllTableBuilders(DataBlockMap* table_data, } CALLER_ATTACH -Table::Builder* Font::Builder::GetTableBuilder(Table::Header* header, +Table::Builder* Font::Builder::GetTableBuilder(Header* header, WritableFontData* data) { return Table::Builder::GetBuilder(header, data); } @@ -375,7 +375,7 @@ void Font::Builder::BuildTablesFromBuilders(Font* font, // Now build all the tables. for (TableBuilderMap::iterator builder = builder_map->begin(), builder_end = builder_map->end(); - builder != builder_end; ++builder) { + builder != builder_end; ++builder) { TablePtr table; if (builder->second && builder->second->ReadyToBuild()) { #if !defined (SFNTLY_NO_EXCEPTION) @@ -393,10 +393,6 @@ void Font::Builder::BuildTablesFromBuilders(Font* font, #endif } if (table == NULL) { -#if defined (SFNTLY_DEBUG) - fprintf(stderr, "Aborting table construction: %s\n", - builder_string.c_str()); -#endif table_map->clear(); #if !defined (SFNTLY_NO_EXCEPTION) std::string builder_string = "Unable to build table - "; @@ -496,7 +492,7 @@ void Font::Builder::ReadHeader(FontInputStream* is, int64_t checksum = is->ReadULong(); int32_t offset = is->ReadULongAsInt(); int32_t length = is->ReadULongAsInt(); - TableHeaderPtr table = new Table::Header(tag, checksum, offset, length); + HeaderPtr table = new Header(tag, checksum, offset, length); records->insert(table); } } @@ -519,7 +515,7 @@ void Font::Builder::ReadHeader(ReadableFontData* fd, int64_t checksum = fd->ReadULong(table_offset + Offset::kTableCheckSum); int32_t offset = fd->ReadULongAsInt(table_offset + Offset::kTableOffset); int32_t length = fd->ReadULongAsInt(table_offset + Offset::kTableLength); - TableHeaderPtr table = new Table::Header(tag, checksum, offset, length); + HeaderPtr table = new Header(tag, checksum, offset, length); records->insert(table); } } diff --git a/sfntly/font.h b/sfntly/font.h index 1a714a6..dd31c13 100644 --- a/sfntly/font.h +++ b/sfntly/font.h @@ -199,7 +199,7 @@ class Font : public RefCounted { void BuildAllTableBuilders(DataBlockMap* table_data, TableBuilderMap* builder_map); CALLER_ATTACH Table::Builder* - GetTableBuilder(Table::Header* header, WritableFontData* data); + GetTableBuilder(Header* header, WritableFontData* data); void BuildTablesFromBuilders(Font* font, TableBuilderMap* builder_map, TableMap* tables); diff --git a/sfntly/table/bitmap/bitmap_glyph.cc b/sfntly/table/bitmap/bitmap_glyph.cc new file mode 100644 index 0000000..82d78b3 --- /dev/null +++ b/sfntly/table/bitmap/bitmap_glyph.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/bitmap/bitmap_glyph.h" + +namespace sfntly { +/****************************************************************************** + * BitmapGlyph class + ******************************************************************************/ +BitmapGlyph::~BitmapGlyph() { +} + +BitmapGlyph::BitmapGlyph(ReadableFontData* data, int32_t format) + : SubTable(data), format_(format) { +} + +/****************************************************************************** + * BitmapGlyph::Builder class + ******************************************************************************/ +BitmapGlyph::Builder::~Builder() { +} + +BitmapGlyph::Builder::Builder(WritableFontData* data) + : SubTable::Builder(data) { +} + +BitmapGlyph::Builder::Builder(ReadableFontData* data) + : SubTable::Builder(data) { +} + +CALLER_ATTACH +FontDataTable* BitmapGlyph::Builder::SubBuildTable(ReadableFontData* data) { + UNREFERENCED_PARAMETER(data); + return NULL; +} + +void BitmapGlyph::Builder::SubDataSet() { +} + +int32_t BitmapGlyph::Builder::SubDataSizeToSerialize() { + return 0; +} + +bool BitmapGlyph::Builder::SubReadyToSerialize() { + return false; +} + +int32_t BitmapGlyph::Builder::SubSerialize(WritableFontData* new_data) { + UNREFERENCED_PARAMETER(new_data); + return 0; +} + +} // namespace sfntly diff --git a/sfntly/table/bitmap/bitmap_glyph.h b/sfntly/table/bitmap/bitmap_glyph.h new file mode 100644 index 0000000..47afbe1 --- /dev/null +++ b/sfntly/table/bitmap/bitmap_glyph.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_TABLE_BITMAP_BITMAP_GLYPH_H_ +#define SFNTLY_CPP_SRC_SFNTLY_TABLE_BITMAP_BITMAP_GLYPH_H_ + +#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(); + + protected: + Builder(WritableFontData* data); + Builder(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 ~BitmapGlyph(); + int32_t format() { return format_; } + + // UNIMPLEMENTED: toString() + + protected: + BitmapGlyph(ReadableFontData* data, int32_t format); + + private: + int32_t format_; +}; +typedef Ptr BitmapGlyphPtr; + +} // namespace sfntly + +#endif // SFNTLY_CPP_SRC_SFNTLY_TABLE_BITMAP_BITMAP_GLYPH_H_ diff --git a/sfntly/table/bitmap/bitmap_size_table.cc b/sfntly/table/bitmap/bitmap_size_table.cc new file mode 100644 index 0000000..2b5b9bb --- /dev/null +++ b/sfntly/table/bitmap/bitmap_size_table.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. + */ + +#include "sfntly/table/bitmap/bitmap_size_table.h" + +#include "sfntly/table/bitmap/eblc_table.h" + +namespace sfntly { + +BitmapSizeTable::BitmapSizeTable(ReadableFontData* data, + ReadableFontData* master_data) + : SubTable(data) { + master_data_ = master_data; +} + +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 data_->ReadULongAsInt( + EblcTable::Offset::kBitmapSizeTable_numberOfIndexSubTables); +} + +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); +} + +int32_t BitmapSizeTable::GlyphFormat(int32_t glyph_id) { + IndexSubTable* subtable = SearchIndexSubTables(glyph_id); + if (subtable == NULL) { + return -1; + } + return subtable->image_format(); +} + +IndexSubTable* BitmapSizeTable::SearchIndexSubTables(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_data_, + IndexSubTableArrayOffset(), + index); +} + +IndexSubTableList* BitmapSizeTable::GetIndexSubTableList() { + if (atomic_subtables.empty()) { + for (int32_t i = 0; i < NumberOfIndexSubTables(); ++i) { + IndexSubTablePtr table; + table.Attach(CreateIndexSubTable(i)); + atomic_subtables.push_back(table); + } + } + return &atomic_subtables; +} + +} // namespace sfntly diff --git a/sfntly/table/bitmap/bitmap_size_table.h b/sfntly/table/bitmap/bitmap_size_table.h new file mode 100644 index 0000000..3b8e30c --- /dev/null +++ b/sfntly/table/bitmap/bitmap_size_table.h @@ -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. + */ + +#ifndef SFNTLY_CPP_SRC_SFNTLY_TABLE_BITMAP_BITMAP_SIZE_TABLE_H_ +#define SFNTLY_CPP_SRC_SFNTLY_TABLE_BITMAP_BITMAP_SIZE_TABLE_H_ + +#include + +#include "sfntly/table/bitmap/index_sub_table.h" + +namespace sfntly { + +class BitmapSizeTable : public SubTable, + public RefCounted { + public: + // Note: C++ port take two ReadableFontData. The first is sliced data, and + // the second is unsliced data. The second one is used to correctly + // construct index sub tables since Java version calculate the offset + // based on unsliced data. + BitmapSizeTable(ReadableFontData* data, + ReadableFontData* master_data); + virtual ~BitmapSizeTable(); + + int32_t IndexSubTableArrayOffset(); + int32_t IndexTableSize(); + int32_t NumberOfIndexSubTables(); + int32_t ColorRef(); + 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); + int32_t GlyphFormat(int32_t glyph_id); + + private: + IndexSubTable* SearchIndexSubTables(int32_t glyph_id); + CALLER_ATTACH IndexSubTable* CreateIndexSubTable(int32_t index); + IndexSubTableList* GetIndexSubTableList(); + + ReadableFontDataPtr master_data_; + IndexSubTableList atomic_subtables; +}; +typedef Ptr BitmapSizeTablePtr; +typedef std::vector BitmapSizeTableList; + +} // namespace sfntly + +#endif // SFNTLY_CPP_SRC_SFNTLY_TABLE_BITMAP_BITMAP_SIZE_TABLE_H_ diff --git a/sfntly/table/bitmap/composite_bitmap_glyph.cc b/sfntly/table/bitmap/composite_bitmap_glyph.cc new file mode 100644 index 0000000..bd680e4 --- /dev/null +++ b/sfntly/table/bitmap/composite_bitmap_glyph.cc @@ -0,0 +1,89 @@ +/* + * 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) { +} + +} // namespace sfntly diff --git a/sfntly/table/bitmap/composite_bitmap_glyph.h b/sfntly/table/bitmap/composite_bitmap_glyph.h new file mode 100644 index 0000000..0521213 --- /dev/null +++ b/sfntly/table/bitmap/composite_bitmap_glyph.h @@ -0,0 +1,65 @@ +/* + * 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; + }; + + 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/sfntly/table/bitmap/ebdt_table.cc b/sfntly/table/bitmap/ebdt_table.cc new file mode 100644 index 0000000..a131f5a --- /dev/null +++ b/sfntly/table/bitmap/ebdt_table.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/ebdt_table.h" + +#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 new_data; + new_data.Attach(down_cast(data_->Slice(offset, length))); + BitmapGlyphPtr glyph; + switch (format) { + case 1: + case 2: + case 3: + case 4: + case 5: + case 6: + case 7: + glyph = new SimpleBitmapGlyph(new_data, format); + break; + case 8: + case 9: + glyph = new CompositeBitmapGlyph(new_data, format); + break; + default: + assert(false); + break; + } + return glyph.Detach(); +} + +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() { + // NOP +} + +int32_t EbdtTable::Builder::SubDataSizeToSerialize() { + return 0; +} + +bool EbdtTable::Builder::SubReadyToSerialize() { + return false; +} + +int32_t EbdtTable::Builder::SubSerialize(WritableFontData* new_data) { + UNREFERENCED_PARAMETER(new_data); + return 0; +} + +CALLER_ATTACH +EbdtTable::Builder* EbdtTable::Builder::CreateBuilder(Header* header, + WritableFontData* data) { + Ptr builder; + builder = new Builder(header, data); + return builder.Detach(); +} + + +} // namespace sfntly diff --git a/sfntly/table/bitmap/ebdt_table.h b/sfntly/table/bitmap/ebdt_table.h new file mode 100644 index 0000000..998541e --- /dev/null +++ b/sfntly/table/bitmap/ebdt_table.h @@ -0,0 +1,67 @@ +/* + * 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/subtable_container_table.h" + +namespace sfntly { + +class EbdtTable : public SubTableContainerTable, + public RefCounted { + public: + 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); + + static CALLER_ATTACH Builder* CreateBuilder(Header* header, + WritableFontData* data); + }; + + virtual ~EbdtTable(); + int32_t Version(); + CALLER_ATTACH BitmapGlyph* Glyph(int32_t offset, + int32_t length, + int32_t format); + + protected: + EbdtTable(Header* header, ReadableFontData* data); + + private: + struct Offset { + enum { + kVersion = 0, + }; + }; +}; +typedef Ptr EbdtTablePtr; + +} // namespace sfntly + +#endif // SFNTLY_CPP_SRC_SFNTLY_TABLE_BITMAP_EBDT_TABLE_H_ diff --git a/sfntly/table/bitmap/eblc_table.cc b/sfntly/table/bitmap/eblc_table.cc new file mode 100644 index 0000000..a198c10 --- /dev/null +++ b/sfntly/table/bitmap/eblc_table.cc @@ -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. + */ + +#include "sfntly/table/bitmap/eblc_table.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() { + // TODO(arthurhsu): thread locking. + 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))); + BitmapSizeTablePtr new_table = new BitmapSizeTable(new_data, data); + output->push_back(new_table); + } +} + +/****************************************************************************** + * 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) { + UNREFERENCED_PARAMETER(new_data); + return 0; +} + +bool EblcTable::Builder::SubReadyToSerialize() { + return false; +} + +int32_t EblcTable::Builder::SubDataSizeToSerialize() { + return 0; +} + +void EblcTable::Builder::SubDataSet() { + // NOP +} + +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(); +} + +} // namespace sfntly diff --git a/sfntly/table/bitmap/eblc_table.h b/sfntly/table/bitmap/eblc_table.h new file mode 100644 index 0000000..bf7cb15 --- /dev/null +++ b/sfntly/table/bitmap/eblc_table.h @@ -0,0 +1,154 @@ +/* + * 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/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, + + // bitmapSizeTable + kBitmapSizeTableArrayStart = 8, + 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, + + // kIndexSubTable2 + kIndexSubTable2Length = kIndexSubHeaderLength + + DataSize::kULONG + + BitmapGlyph::Offset::kBigGlyphMetricsLength, + kIndexSubTable2_imageSize = kIndexSubHeaderLength, + kIndexSubTable2_bigGlyphMetrics = kIndexSubTable2_imageSize + 4, + + // kIndexSubTable3 + kIndexSubTable3_offsetArray = kIndexSubHeaderLength, + + // kIndexSubTable4 + kIndexSubTable4_numGlyphs = kIndexSubHeaderLength, + kIndexSubTable4_glyphArray = kIndexSubTable4_numGlyphs + + DataSize::kULONG, + + // kIndexSubTable5 + kIndexSubTable5_imageSize = kIndexSubHeaderLength, + kIndexSubTable5_bigMetrics = kIndexSubTable5_imageSize + + DataSize::kULONG, + kIndexSubTable5_numGlyphs = kIndexSubTable5_bigMetrics + + BitmapGlyph::Offset::kBigGlyphMetricsLength, + kIndexSubTable5_glyphArray = kIndexSubTable5_numGlyphs + + DataSize::kULONG, + + // 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); + + static CALLER_ATTACH Builder* CreateBuilder(Header* header, + WritableFontData* data); + }; + + int32_t Version(); + int32_t NumSizes(); + // UNIMPLEMENTED: toString() + + BitmapSizeTable* GetBitmapSizeTable(int32_t index); + + protected: + EblcTable(Header* header, ReadableFontData* data); + + private: + BitmapSizeTableList* GetBitmapSizeTableList(); + static void CreateBitmapSizeTable(ReadableFontData* data, + int32_t num_sizes, + BitmapSizeTableList* output); + + // TODO(arthurhsu): this table must be accessed atomically. + BitmapSizeTableList bitmap_size_table_; +}; +typedef Ptr EblcTablePtr; +} + +#endif // SFNTLY_CPP_SRC_SFNTLY_TABLE_BITMAP_EBLC_TABLE_H_ diff --git a/sfntly/table/bitmap/index_sub_table.cc b/sfntly/table/bitmap/index_sub_table.cc new file mode 100644 index 0000000..329179d --- /dev/null +++ b/sfntly/table/bitmap/index_sub_table.cc @@ -0,0 +1,137 @@ +/* + * 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 { + +bool IndexSubTable::CheckGlyphRange(int32_t glyph_id) { + if (glyph_id < first_glyph_index() || glyph_id > last_glyph_index()) { +#if !defined (SFNTLY_NO_EXCEPTION) + throw IndexOutOfBoundException("Glyph ID is outside of the allowed range"); +#endif + return false; + } + return true; +} + +template +static IndexSubTableType* CreateTable(ReadableFontData* data, + int32_t index_sub_table_offset, + int32_t first_glyph_index, + int32_t last_glyph_index) { + ReadableFontDataPtr new_data; + new_data.Attach(down_cast( + data->Slice(index_sub_table_offset, + IndexSubTableType::GetDataLength(data, + index_sub_table_offset, + first_glyph_index, + last_glyph_index)))); + return new IndexSubTableType(new_data, first_glyph_index, last_glyph_index); +} + +// static +CALLER_ATTACH IndexSubTable* + IndexSubTable::CreateIndexSubTable(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); + IndexSubTablePtr new_table; + ReadableFontDataPtr new_data; + switch (index_format) { + case 1: + new_table = CreateTable(data, + index_sub_table_offset, + first_glyph_index, + last_glyph_index); + break; + + case 2: + new_table = CreateTable(data, + index_sub_table_offset, + first_glyph_index, + last_glyph_index); + break; + + case 3: + new_table = CreateTable(data, + index_sub_table_offset, + first_glyph_index, + last_glyph_index); + break; + + case 4: + new_table = CreateTable(data, + index_sub_table_offset, + first_glyph_index, + last_glyph_index); + break; + + case 5: + new_table = CreateTable(data, + index_sub_table_offset, + first_glyph_index, + last_glyph_index); + break; + + default: + // Unknown format and unable to process. +#if !defined (SFNTLY_NO_EXCEPTION) + throw IllegalArgumentException("Invalid Index Subtable Format"); +#endif + break; + } + + return new_table.Detach(); +} + +IndexSubTable::IndexSubTable(ReadableFontData* data, + int32_t first, + int32_t last) + : SubTable(data), first_glyph_index_(first), last_glyph_index_(last) { + 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/sfntly/table/bitmap/index_sub_table.h b/sfntly/table/bitmap/index_sub_table.h new file mode 100644 index 0000000..253f165 --- /dev/null +++ b/sfntly/table/bitmap/index_sub_table.h @@ -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. + */ + +#ifndef SFNTLY_CPP_SRC_SFNTLY_TABLE_BITMAP_INDEX_SUBTABLE_H_ +#define SFNTLY_CPP_SRC_SFNTLY_TABLE_BITMAP_INDEX_SUBTABLE_H_ + +#include + +#include "sfntly/table/subtable.h" + +namespace sfntly { + +class IndexSubTable : public SubTable { + public: + 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_; } + + virtual int32_t GlyphOffset(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, int32_t last); + + // Note: change return type to bool in C++ since we may not throw. + bool CheckGlyphRange(int32_t 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; + +} // namespace sfntly + +#endif // SFNTLY_CPP_SRC_SFNTLY_TABLE_BITMAP_INDEX_SUBTABLE_H_ diff --git a/sfntly/table/bitmap/index_sub_table_format1.cc b/sfntly/table/bitmap/index_sub_table_format1.cc new file mode 100644 index 0000000..b98655a --- /dev/null +++ b/sfntly/table/bitmap/index_sub_table_format1.cc @@ -0,0 +1,67 @@ +/* + * 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 { + +// 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(ReadableFontData* data, + int32_t first, + int32_t last) + : IndexSubTable(data, first, last) { +} + +IndexSubTableFormat1::~IndexSubTableFormat1() { +} + +int32_t IndexSubTableFormat1::NumGlyphs() { + return last_glyph_index() - first_glyph_index() + 1; +} + +int32_t IndexSubTableFormat1::GlyphOffset(int32_t glyph_id) { + if (CheckGlyphRange(glyph_id)) { + return Loca(glyph_id); + } + return -1; +} + +int32_t IndexSubTableFormat1::GlyphLength(int32_t glyph_id) { + if (CheckGlyphRange(glyph_id)) { + return Loca(glyph_id + 1) - Loca(glyph_id); + } + return -1; +} + +int32_t IndexSubTableFormat1::Loca(int32_t loca_index) { + return image_data_offset() + + data_->ReadULongAsInt(EblcTable::Offset::kIndexSubTable1_offsetArray + + (loca_index - first_glyph_index()) * + DataSize::kULONG); +} + +} // namespace sfntly diff --git a/sfntly/table/bitmap/index_sub_table_format1.h b/sfntly/table/bitmap/index_sub_table_format1.h new file mode 100644 index 0000000..3329bc9 --- /dev/null +++ b/sfntly/table/bitmap/index_sub_table_format1.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_TABLE_BITMAP_INDEX_SUBTABLE_FORMAT1_H_ +#define SFNTLY_CPP_SRC_SFNTLY_TABLE_BITMAP_INDEX_SUBTABLE_FORMAT1_H_ + +#include "sfntly/table/bitmap/index_sub_table.h" + +namespace sfntly { + +class IndexSubTableFormat1 : public IndexSubTable, + public RefCounted { + public: + static int32_t GetDataLength(ReadableFontData* data, + int32_t offset, + int32_t first, + int32_t last); + + // 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. + IndexSubTableFormat1(ReadableFontData* data, int32_t first, int32_t last); + virtual ~IndexSubTableFormat1(); + + virtual int32_t NumGlyphs(); + virtual int32_t GlyphOffset(int32_t glyph_id); + virtual int32_t GlyphLength(int32_t glyph_id); + + private: + int32_t Loca(int32_t loca_index); +}; + +} // namespace sfntly + +#endif // SFNTLY_CPP_SRC_SFNTLY_TABLE_BITMAP_INDEX_SUBTABLE_FORMAT1_H_ diff --git a/sfntly/table/bitmap/index_sub_table_format2.cc b/sfntly/table/bitmap/index_sub_table_format2.cc new file mode 100644 index 0000000..82deef3 --- /dev/null +++ b/sfntly/table/bitmap/index_sub_table_format2.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/bitmap/index_sub_table_format2.h" + +#include "sfntly/table/bitmap/eblc_table.h" + +namespace sfntly { + +// static +int32_t IndexSubTableFormat2::GetDataLength(ReadableFontData* data, + int32_t offset, + int32_t first, + int32_t last) { + UNREFERENCED_PARAMETER(data); + UNREFERENCED_PARAMETER(offset); + UNREFERENCED_PARAMETER(first); + UNREFERENCED_PARAMETER(last); + return EblcTable::Offset::kIndexSubTable2Length; +} + +IndexSubTableFormat2::IndexSubTableFormat2(ReadableFontData* data, + int32_t first, + int32_t last) + : IndexSubTable(data, first, last) { + image_size_ = + data_->ReadULongAsInt(EblcTable::Offset::kIndexSubTable2_imageSize); +} + +IndexSubTableFormat2::~IndexSubTableFormat2() { +} + +int32_t IndexSubTableFormat2::NumGlyphs() { + return last_glyph_index() - first_glyph_index() + 1; +} + +int32_t IndexSubTableFormat2::GlyphOffset(int32_t glyph_id) { + if (CheckGlyphRange(glyph_id)) { + return image_data_offset() + (glyph_id - first_glyph_index()) * image_size_; + } + return -1; +} + +int32_t IndexSubTableFormat2::GlyphLength(int32_t glyph_id) { + if (CheckGlyphRange(glyph_id)) { + return image_size_; + } + return -1; +} + +} // namespace sfntly diff --git a/sfntly/table/bitmap/index_sub_table_format2.h b/sfntly/table/bitmap/index_sub_table_format2.h new file mode 100644 index 0000000..b325ccd --- /dev/null +++ b/sfntly/table/bitmap/index_sub_table_format2.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_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" + +namespace sfntly { + +class IndexSubTableFormat2 : public IndexSubTable, + public RefCounted { + public: + static int32_t GetDataLength(ReadableFontData* data, + int32_t offset, + int32_t first, + int32_t last); + + // 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. + IndexSubTableFormat2(ReadableFontData* data, int32_t first, int32_t last); + virtual ~IndexSubTableFormat2(); + + virtual int32_t NumGlyphs(); + virtual int32_t GlyphOffset(int32_t glyph_id); + virtual int32_t GlyphLength(int32_t glyph_id); + + private: + int32_t Loca(int32_t loca_index); + + int32_t image_size_; +}; + +} // namespace sfntly + +#endif // SFNTLY_CPP_SRC_SFNTLY_TABLE_BITMAP_INDEX_SUBTABLE_FORMAT1_H_ diff --git a/sfntly/table/bitmap/index_sub_table_format3.cc b/sfntly/table/bitmap/index_sub_table_format3.cc new file mode 100644 index 0000000..4fa529e --- /dev/null +++ b/sfntly/table/bitmap/index_sub_table_format3.cc @@ -0,0 +1,67 @@ +/* + * 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 { + +// 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, + int32_t last) + : IndexSubTable(data, first, last) { +} + +IndexSubTableFormat3::~IndexSubTableFormat3() { +} + +int32_t IndexSubTableFormat3::NumGlyphs() { + return last_glyph_index() - first_glyph_index() + 1; +} + +int32_t IndexSubTableFormat3::GlyphOffset(int32_t glyph_id) { + if (CheckGlyphRange(glyph_id)) { + return Loca(glyph_id); + } + return -1; +} + +int32_t IndexSubTableFormat3::GlyphLength(int32_t glyph_id) { + if (CheckGlyphRange(glyph_id)) { + return Loca(glyph_id + 1) - Loca(glyph_id); + } + return -1; +} + +int32_t IndexSubTableFormat3::Loca(int32_t loca_index) { + int32_t read_offset = + data_->ReadUShort(EblcTable::Offset::kIndexSubTable3_offsetArray + + (loca_index - first_glyph_index()) * DataSize::kUSHORT); + return image_data_offset() + read_offset; +} + +} // namespace sfntly diff --git a/sfntly/table/bitmap/index_sub_table_format3.h b/sfntly/table/bitmap/index_sub_table_format3.h new file mode 100644 index 0000000..1e45f23 --- /dev/null +++ b/sfntly/table/bitmap/index_sub_table_format3.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_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 { + +class IndexSubTableFormat3 : public IndexSubTable, + public RefCounted { + public: + static int32_t GetDataLength(ReadableFontData* data, + int32_t offset, + int32_t first, + int32_t last); + + // 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. + IndexSubTableFormat3(ReadableFontData* data, int32_t first, int32_t last); + virtual ~IndexSubTableFormat3(); + + virtual int32_t NumGlyphs(); + virtual int32_t GlyphOffset(int32_t glyph_id); + virtual int32_t GlyphLength(int32_t glyph_id); + + private: + int32_t Loca(int32_t loca_index); +}; + +} // namespace sfntly + +#endif // SFNTLY_CPP_SRC_SFNTLY_TABLE_BITMAP_INDEX_SUBTABLE_FORMAT3_H_ diff --git a/sfntly/table/bitmap/index_sub_table_format4.cc b/sfntly/table/bitmap/index_sub_table_format4.cc new file mode 100644 index 0000000..9ef681c --- /dev/null +++ b/sfntly/table/bitmap/index_sub_table_format4.cc @@ -0,0 +1,88 @@ +/* + * 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 { + +// static +int32_t IndexSubTableFormat4::GetDataLength(ReadableFontData* data, + int32_t offset, + int32_t first, + int32_t last) { + UNREFERENCED_PARAMETER(first); + UNREFERENCED_PARAMETER(last); + assert(data); + return data->ReadULongAsInt(offset + + EblcTable::Offset::kIndexSubTable4_numGlyphs) * + EblcTable::Offset::kCodeOffsetPairLength; +} + +IndexSubTableFormat4::IndexSubTableFormat4(ReadableFontData* data, + int32_t first, + int32_t last) + : IndexSubTable(data, first, last) { +} + +IndexSubTableFormat4::~IndexSubTableFormat4() { +} + +int32_t IndexSubTableFormat4::NumGlyphs() { + return data_->ReadULongAsInt(EblcTable::Offset::kIndexSubTable4_numGlyphs); +} + +int32_t IndexSubTableFormat4::GlyphOffset(int32_t glyph_id) { + if (CheckGlyphRange(glyph_id)) { + 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); + } + return -1; +} + +int32_t IndexSubTableFormat4::GlyphLength(int32_t glyph_id) { + if (CheckGlyphRange(glyph_id)) { + 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); + } + return -1; +} + +int32_t IndexSubTableFormat4::FindCodeOffsetPair(int32_t glyph_id) { + return data_->SearchUShort(EblcTable::Offset::kIndexSubTable4_glyphArray, + EblcTable::Offset::kCodeOffsetPairLength, + NumGlyphs(), + glyph_id); +} + +} // namespace sfntly diff --git a/sfntly/table/bitmap/index_sub_table_format4.h b/sfntly/table/bitmap/index_sub_table_format4.h new file mode 100644 index 0000000..821acca --- /dev/null +++ b/sfntly/table/bitmap/index_sub_table_format4.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_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: + static int32_t GetDataLength(ReadableFontData* data, + int32_t offset, + int32_t first, + int32_t last); + + // 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. + IndexSubTableFormat4(ReadableFontData* data, int32_t first, int32_t last); + virtual ~IndexSubTableFormat4(); + + virtual int32_t NumGlyphs(); + virtual int32_t GlyphOffset(int32_t glyph_id); + virtual int32_t GlyphLength(int32_t glyph_id); + + private: + int32_t FindCodeOffsetPair(int32_t glyph_id); +}; + +} // namespace sfntly + +#endif // SFNTLY_CPP_SRC_SFNTLY_TABLE_BITMAP_INDEX_SUBTABLE_FORMAT4_H_ diff --git a/sfntly/table/bitmap/index_sub_table_format5.cc b/sfntly/table/bitmap/index_sub_table_format5.cc new file mode 100644 index 0000000..a2aed5c --- /dev/null +++ b/sfntly/table/bitmap/index_sub_table_format5.cc @@ -0,0 +1,65 @@ +/* + * 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 "sfntly/table/bitmap/eblc_table.h" + +namespace sfntly { + +// static +int32_t IndexSubTableFormat5::GetDataLength(ReadableFontData* data, + int32_t offset, + int32_t first, + int32_t last) { + UNREFERENCED_PARAMETER(first); + UNREFERENCED_PARAMETER(last); + assert(data); + return data->ReadULongAsInt(offset + + EblcTable::Offset::kIndexSubTable5_numGlyphs) * + EblcTable::Offset::kCodeOffsetPairLength; +} + +IndexSubTableFormat5::IndexSubTableFormat5(ReadableFontData* data, + int32_t first, + int32_t last) + : IndexSubTable(data, first, last) { +} + +IndexSubTableFormat5::~IndexSubTableFormat5() { +} + +int32_t IndexSubTableFormat5::NumGlyphs() { + return data_->ReadULongAsInt(EblcTable::Offset::kIndexSubTable5_numGlyphs); +} + +int32_t IndexSubTableFormat5::GlyphOffset(int32_t glyph_id) { + if (CheckGlyphRange(glyph_id)) { + return data_->ReadUShort( + EblcTable::Offset::kIndexSubTable5_glyphArray + + glyph_id * DataSize::kUSHORT); + } + return -1; +} + +int32_t IndexSubTableFormat5::GlyphLength(int32_t glyph_id) { + if (CheckGlyphRange(glyph_id)) { + return data_->ReadULongAsInt(EblcTable::Offset::kIndexSubTable5_imageSize); + } + return -1; +} + +} // namespace sfntly diff --git a/sfntly/table/bitmap/index_sub_table_format5.h b/sfntly/table/bitmap/index_sub_table_format5.h new file mode 100644 index 0000000..354834e --- /dev/null +++ b/sfntly/table/bitmap/index_sub_table_format5.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_TABLE_BITMAP_INDEX_SUBTABLE_FORMAT5_H_ +#define SFNTLY_CPP_SRC_SFNTLY_TABLE_BITMAP_INDEX_SUBTABLE_FORMAT5_H_ + +#include "sfntly/table/bitmap/index_sub_table.h" + +namespace sfntly { + +class IndexSubTableFormat5 : public IndexSubTable, + public RefCounted { + public: + static int32_t GetDataLength(ReadableFontData* data, + int32_t offset, + int32_t first, + int32_t last); + + // 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. + IndexSubTableFormat5(ReadableFontData* data, int32_t first, int32_t last); + virtual ~IndexSubTableFormat5(); + + virtual int32_t NumGlyphs(); + virtual int32_t GlyphOffset(int32_t glyph_id); + virtual int32_t GlyphLength(int32_t glyph_id); +}; + +} // namespace sfntly + +#endif // SFNTLY_CPP_SRC_SFNTLY_TABLE_BITMAP_INDEX_SUBTABLE_FORMAT5_H_ diff --git a/sfntly/table/bitmap/simple_bitmap_glyph.cc b/sfntly/table/bitmap/simple_bitmap_glyph.cc new file mode 100644 index 0000000..85364fd --- /dev/null +++ b/sfntly/table/bitmap/simple_bitmap_glyph.cc @@ -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. + */ + +#include "sfntly/table/bitmap/simple_bitmap_glyph.h" + +namespace sfntly { + +SimpleBitmapGlyph::SimpleBitmapGlyph(ReadableFontData* data, int32_t format) + : BitmapGlyph(data, format) { +} + +SimpleBitmapGlyph::~SimpleBitmapGlyph() { +} + +} // namespace sfntly diff --git a/sfntly/table/bitmap/simple_bitmap_glyph.h b/sfntly/table/bitmap/simple_bitmap_glyph.h new file mode 100644 index 0000000..48bca98 --- /dev/null +++ b/sfntly/table/bitmap/simple_bitmap_glyph.h @@ -0,0 +1,33 @@ +/* + * 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: + SimpleBitmapGlyph(ReadableFontData* data, int32_t format); + virtual ~SimpleBitmapGlyph(); +}; + +} // namespace sfntly + +#endif // SFNTLY_CPP_SRC_SFNTLY_TABLE_BITMAP_SIMPLE_BITMAP_GLYPH_H_ diff --git a/sfntly/table/core/font_header_table.cc b/sfntly/table/core/font_header_table.cc index 3713b02..60015ca 100644 --- a/sfntly/table/core/font_header_table.cc +++ b/sfntly/table/core/font_header_table.cc @@ -103,11 +103,11 @@ FontHeaderTable::FontHeaderTable(Header* header, ReadableFontData* data) * FontHeaderTable::Builder class ******************************************************************************/ FontHeaderTable::Builder::Builder(Header* header, WritableFontData* data) - : Table::TableBasedTableBuilder(header, data) { + : TableBasedTableBuilder(header, data) { } FontHeaderTable::Builder::Builder(Header* header, ReadableFontData* data) - : Table::TableBasedTableBuilder(header, data) { + : TableBasedTableBuilder(header, data) { } FontHeaderTable::Builder::~Builder() {} diff --git a/sfntly/table/core/font_header_table.h b/sfntly/table/core/font_header_table.h index 3b20863..841955b 100644 --- a/sfntly/table/core/font_header_table.h +++ b/sfntly/table/core/font_header_table.h @@ -18,6 +18,7 @@ #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 { @@ -40,8 +41,7 @@ struct FontDirectionHint { class FontHeaderTable : public Table, public RefCounted { public: - class Builder : public Table::TableBasedTableBuilder, - public RefCounted { + 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. diff --git a/sfntly/table/core/horizontal_header_table.cc b/sfntly/table/core/horizontal_header_table.cc index f07ab01..43c2058 100644 --- a/sfntly/table/core/horizontal_header_table.cc +++ b/sfntly/table/core/horizontal_header_table.cc @@ -83,11 +83,11 @@ HorizontalHeaderTable:: HorizontalHeaderTable(Header* header, * HorizontalHeaderTable::Builder class ******************************************************************************/ HorizontalHeaderTable::Builder::Builder(Header* header, WritableFontData* data) - : Table::TableBasedTableBuilder(header, data) { + : TableBasedTableBuilder(header, data) { } HorizontalHeaderTable::Builder::Builder(Header* header, ReadableFontData* data) - : Table::TableBasedTableBuilder(header, data) { + : TableBasedTableBuilder(header, data) { } HorizontalHeaderTable::Builder::~Builder() {} diff --git a/sfntly/table/core/horizontal_header_table.h b/sfntly/table/core/horizontal_header_table.h index c79a7b6..71f30b4 100644 --- a/sfntly/table/core/horizontal_header_table.h +++ b/sfntly/table/core/horizontal_header_table.h @@ -18,6 +18,7 @@ #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 { @@ -26,8 +27,7 @@ class HorizontalHeaderTable : public Table, public RefCounted { public: // Builder for a Horizontal Header table - 'hhea'. - class Builder : public Table::TableBasedTableBuilder, - public RefCounted { + 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. diff --git a/sfntly/table/core/horizontal_metrics_table.cc b/sfntly/table/core/horizontal_metrics_table.cc index 67e99e0..156387d 100644 --- a/sfntly/table/core/horizontal_metrics_table.cc +++ b/sfntly/table/core/horizontal_metrics_table.cc @@ -94,15 +94,11 @@ HorizontalMetricsTable::HorizontalMetricsTable(Header* header, * HorizontalMetricsTable::Builder class ******************************************************************************/ HorizontalMetricsTable::Builder::Builder(Header* header, WritableFontData* data) - : Table::TableBasedTableBuilder(header, data), - num_hmetrics_(-1), - num_glyphs_(-1) { + : TableBasedTableBuilder(header, data), num_hmetrics_(-1), num_glyphs_(-1) { } HorizontalMetricsTable::Builder::Builder(Header* header, ReadableFontData* data) - : Table::TableBasedTableBuilder(header, data), - num_hmetrics_(-1), - num_glyphs_(-1) { + : TableBasedTableBuilder(header, data), num_hmetrics_(-1), num_glyphs_(-1) { } HorizontalMetricsTable::Builder::~Builder() {} diff --git a/sfntly/table/core/horizontal_metrics_table.h b/sfntly/table/core/horizontal_metrics_table.h index eaf79e4..44b51f2 100644 --- a/sfntly/table/core/horizontal_metrics_table.h +++ b/sfntly/table/core/horizontal_metrics_table.h @@ -18,6 +18,7 @@ #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 { @@ -26,8 +27,7 @@ class HorizontalMetricsTable : public Table, public RefCounted { public: // Builder for a Horizontal Metrics Table - 'hmtx'. - class Builder : public Table::TableBasedTableBuilder, - public RefCounted { + 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. diff --git a/sfntly/table/core/maximum_profile_table.cc b/sfntly/table/core/maximum_profile_table.cc index e457621..a8ac3bc 100644 --- a/sfntly/table/core/maximum_profile_table.cc +++ b/sfntly/table/core/maximum_profile_table.cc @@ -87,11 +87,11 @@ MaximumProfileTable::MaximumProfileTable(Header* header, * MaximumProfileTable::Builder class ******************************************************************************/ MaximumProfileTable::Builder::Builder(Header* header, WritableFontData* data) - : Table::TableBasedTableBuilder(header, data) { + : TableBasedTableBuilder(header, data) { } MaximumProfileTable::Builder::Builder(Header* header, ReadableFontData* data) - : Table::TableBasedTableBuilder(header, data) { + : TableBasedTableBuilder(header, data) { } MaximumProfileTable::Builder::~Builder() {} diff --git a/sfntly/table/core/maximum_profile_table.h b/sfntly/table/core/maximum_profile_table.h index 9b89617..e7c5abb 100644 --- a/sfntly/table/core/maximum_profile_table.h +++ b/sfntly/table/core/maximum_profile_table.h @@ -19,6 +19,7 @@ #include "sfntly/port/refcount.h" #include "sfntly/table/table.h" +#include "sfntly/table/table_based_table_builder.h" namespace sfntly { @@ -27,8 +28,7 @@ class MaximumProfileTable : public Table, public RefCounted { public: // Builder for a Maximum Profile table - 'maxp'. - class Builder : public Table::TableBasedTableBuilder, - public RefCounted { + 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. diff --git a/sfntly/table/core/os2_table.cc b/sfntly/table/core/os2_table.cc index 024b03a..7ca9d9a 100644 --- a/sfntly/table/core/os2_table.cc +++ b/sfntly/table/core/os2_table.cc @@ -261,12 +261,12 @@ OS2Table::OS2Table(Header* header, ReadableFontData* data) /****************************************************************************** * class OS2Table::Builder ******************************************************************************/ -OS2Table::Builder::Builder(Header* header, WritableFontData* data) : - Table::TableBasedTableBuilder(header, data) { +OS2Table::Builder::Builder(Header* header, WritableFontData* data) + : TableBasedTableBuilder(header, data) { } -OS2Table::Builder::Builder(Header* header, ReadableFontData* data) : - Table::TableBasedTableBuilder(header, data) { +OS2Table::Builder::Builder(Header* header, ReadableFontData* data) + : TableBasedTableBuilder(header, data) { } OS2Table::Builder::~Builder() {} @@ -476,12 +476,13 @@ void OS2Table::Builder::AchVendId(ByteVector* b) { void OS2Table::Builder::SetAchVendId(ByteVector* b) { assert(b); assert(b->size()); - InternalWriteData()->WriteBytes(Offset::kAchVendId, - &((*b)[0]), - 0, - std::min( - (size_t)Offset::kAchVendIdLength, - b->size())); + InternalWriteData()->WriteBytesPad(Offset::kAchVendId, + b, + 0, + std::min( + (size_t)Offset::kAchVendIdLength, + b->size()), + static_cast(' ')); } int32_t OS2Table::Builder::FsSelection() { diff --git a/sfntly/table/core/os2_table.h b/sfntly/table/core/os2_table.h index cd34ff8..00d26d2 100644 --- a/sfntly/table/core/os2_table.h +++ b/sfntly/table/core/os2_table.h @@ -19,6 +19,7 @@ #include "sfntly/port/refcount.h" #include "sfntly/table/table.h" +#include "sfntly/table/table_based_table_builder.h" namespace sfntly { @@ -312,8 +313,7 @@ struct CodePageRange { class OS2Table : public Table, public RefCounted { public: // A builder for the OS/2 table = 'OS/2'. - class Builder : public Table::TableBasedTableBuilder, - public RefCounted { + class Builder : public TableBasedTableBuilder, public RefCounted { public: Builder(Header* header, WritableFontData* data); Builder(Header* header, ReadableFontData* data); @@ -370,6 +370,10 @@ class OS2Table : public Table, public RefCounted { // 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(); diff --git a/sfntly/table/font_data_table.cc b/sfntly/table/font_data_table.cc index d662e42..0197bbd 100644 --- a/sfntly/table/font_data_table.cc +++ b/sfntly/table/font_data_table.cc @@ -62,7 +62,9 @@ CALLER_ATTACH WritableFontData* FontDataTable::Builder::Data() { ReadableFontDataPtr data = InternalReadData(); new_data.Attach(WritableFontData::CreateWritableFontData( data != NULL ? data->Length() : 0)); - data->CopyTo(new_data); + if (data != NULL) { + data->CopyTo(new_data); + } } return new_data.Detach(); } @@ -73,6 +75,7 @@ void FontDataTable::Builder::SetData(ReadableFontData* data) { CALLER_ATTACH FontDataTable* FontDataTable::Builder::Build() { + FontDataTablePtr table; // NULL default table ReadableFontDataPtr data = InternalReadData(); if (model_changed_) { // Let subclass serialize from model. @@ -86,12 +89,13 @@ CALLER_ATTACH FontDataTable* FontDataTable::Builder::Build() { data = new_data; } - if (data == NULL) { - return NULL; // Do not build table with NULL data. + if (data != NULL) { + table = SubBuildTable(data); + NotifyPostTableBuild(table); } - FontDataTablePtr table = SubBuildTable(data); - NotifyPostTableBuild(table); + r_data_.Release(); + w_data_.Release(); return table; } @@ -117,16 +121,23 @@ WritableFontData* FontDataTable::Builder::InternalWriteData() { return w_data_.p_; } -FontDataTable::Builder::Builder() { +FontDataTable::Builder::Builder() + : model_changed_(false), + contained_model_changed_(false), + data_changed_(false) { } FontDataTable::Builder::Builder(WritableFontData* data) - : model_changed_(false), data_changed_(false) { + : model_changed_(false), + contained_model_changed_(false), + data_changed_(false) { w_data_ = data; } FontDataTable::Builder::Builder(ReadableFontData* data) - : model_changed_(false), data_changed_(false) { + : model_changed_(false), + contained_model_changed_(false), + data_changed_(false) { r_data_ = data; } diff --git a/sfntly/table/header.cc b/sfntly/table/header.cc new file mode 100644 index 0000000..672ace5 --- /dev/null +++ b/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/sfntly/table/header.h b/sfntly/table/header.h new file mode 100644 index 0000000..117da95 --- /dev/null +++ b/sfntly/table/header.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_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. + 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. + 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. + 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/sfntly/table/table.cc b/sfntly/table/table.cc index 10276aa..7183d38 100644 --- a/sfntly/table/table.cc +++ b/sfntly/table/table.cc @@ -18,6 +18,8 @@ #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/core/cmap_table.h" #include "sfntly/table/core/font_header_table.h" #include "sfntly/table/core/horizontal_header_table.h" @@ -25,6 +27,7 @@ #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/table_based_table_builder.h" #include "sfntly/table/truetype/glyph_table.h" #include "sfntly/table/truetype/loca_table.h" @@ -48,54 +51,6 @@ Table::Table(Header* header, ReadableFontData* data) header_ = header; } -/****************************************************************************** - * Table::Header class - ******************************************************************************/ -Table::Header::Header(int32_t tag) - : tag_(tag), - offset_(0), - offset_valid_(false), - length_(0), - length_valid_(false), - checksum_(0), - checksum_valid_(false) { -} - -Table::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) { -} - -Table::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) { -} - -Table::Header::~Header() {} - -bool HeaderComparatorByOffset::operator() (const TableHeaderPtr lhs, - const TableHeaderPtr rhs) { - return lhs->offset_ > rhs->offset_; -} - -bool HeaderComparatorByTag::operator() (const TableHeaderPtr lhs, - const TableHeaderPtr rhs) { - return lhs->tag_ > rhs->tag_; -} - /****************************************************************************** * Table::Builder class ******************************************************************************/ @@ -155,12 +110,21 @@ Table::Builder* Table::Builder::GetBuilder(Header* header, }/* else if (tag == Tag::prep) { builder_raw = static_cast( ControlProgramTable::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::bhed) { builder_raw = static_cast( FontHeaderTable::Builder::CreateBuilder(header, table_data)); } else { builder_raw = static_cast( - Table::GenericTableBuilder::CreateBuilder(header, table_data)); + GenericTableBuilder::CreateBuilder(header, table_data)); } return builder_raw; @@ -180,76 +144,4 @@ Table::Builder::Builder(Header* header) { header_ = header; } -/****************************************************************************** - * Table::TableBasedTableBuilder class - ******************************************************************************/ -Table::TableBasedTableBuilder::~TableBasedTableBuilder() {} - -int32_t Table::TableBasedTableBuilder::SubSerialize(WritableFontData* data) { - UNREFERENCED_PARAMETER(data); - return 0; -} - -bool Table::TableBasedTableBuilder::SubReadyToSerialize() { - return false; -} - -int32_t Table::TableBasedTableBuilder::SubDataSizeToSerialize() { - return 0; -} - -void Table::TableBasedTableBuilder::SubDataSet() { - table_ = NULL; -} - -CALLER_ATTACH FontDataTable* Table::TableBasedTableBuilder::Build() { - FontDataTablePtr table = static_cast(GetTable()); - return table.Detach(); -} - -Table::TableBasedTableBuilder::TableBasedTableBuilder(Header* header, - WritableFontData* data) - : Builder(header, data) { -} - -Table::TableBasedTableBuilder::TableBasedTableBuilder(Header* header, - ReadableFontData* data) - : Builder(header, data) { -} - -Table::TableBasedTableBuilder::TableBasedTableBuilder(Header* header) - : Builder(header) { -} - -Table* Table::TableBasedTableBuilder::GetTable() { - if (table_ == NULL) { - table_.Attach(down_cast(SubBuildTable(InternalReadData()))); - } - return table_; -} - -/****************************************************************************** - * Table::GenericTableBuilder class - ******************************************************************************/ -Table::GenericTableBuilder::GenericTableBuilder(Header* header, - WritableFontData* data) - : TableBasedTableBuilder(header, data) { -} - -CALLER_ATTACH FontDataTable* - Table::GenericTableBuilder::SubBuildTable(ReadableFontData* data) { - // Note: In C++ port, we use GenericTable, the ref-counted version of Table - UNREFERENCED_PARAMETER(data); - FontDataTablePtr table = new GenericTable(this->header(), InternalReadData()); - return table.Detach(); -} - -CALLER_ATTACH Table::GenericTableBuilder* - Table::GenericTableBuilder::CreateBuilder(Header* header, - WritableFontData* data) { - Ptr builder = - new Table::GenericTableBuilder(header, data); - return builder.Detach(); -} - } // namespace sfntly diff --git a/sfntly/table/table.h b/sfntly/table/table.h index 5adbfb1..6ebc22d 100644 --- a/sfntly/table/table.h +++ b/sfntly/table/table.h @@ -24,6 +24,7 @@ #include "sfntly/port/type.h" #include "sfntly/table/font_data_table.h" +#include "sfntly/table/header.h" namespace sfntly { class Font; @@ -33,63 +34,6 @@ class Font; // table for all tables which have no specific implementations. class Table : public FontDataTable { public: - 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. - 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. - 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. - 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; - }; - // Note: original version is Builder // C++ template is not designed that way so plain old inheritance is // chosen. @@ -117,38 +61,8 @@ class Table : public FontDataTable { Ptr
header_; }; - class TableBasedTableBuilder : public 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); - TableBasedTableBuilder(Header* header); - - // C++ port: renamed table() to GetTable() - virtual Table* GetTable(); - - // TODO(arthurhsu): style guide violation: protected member, need refactor - Ptr
table_; - }; - - class GenericTableBuilder : public TableBasedTableBuilder, - public RefCounted { - public: - GenericTableBuilder(Header* header, WritableFontData* data); - virtual CALLER_ATTACH FontDataTable* SubBuildTable(ReadableFontData* data); - - static CALLER_ATTACH - GenericTableBuilder* CreateBuilder(Header* header, - WritableFontData* data); - }; + // Note: GenericTableBuilder moved to table_based_table_builder.h to avoid + // circular inclusion. virtual ~Table(); @@ -190,43 +104,16 @@ class GenericTable : public Table, public RefCounted { }; typedef Ptr
TablePtr; -typedef Ptr TableHeaderPtr; -typedef std::vector TableHeaderList; +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 DataBlockMap; +typedef std::pair DataBlockEntry; typedef std::map TableBuilderMap; typedef std::pair TableBuilderEntry; -class HeaderComparator { - public: - virtual ~HeaderComparator() {} - virtual bool operator()(const TableHeaderPtr h1, - const TableHeaderPtr h2) = 0; -}; - -class HeaderComparatorByOffset : public HeaderComparator { - public: - virtual ~HeaderComparatorByOffset() {} - virtual bool operator()(const TableHeaderPtr h1, - const TableHeaderPtr h2); -}; - -class HeaderComparatorByTag : public HeaderComparator { - public: - virtual ~HeaderComparatorByTag() {} - virtual bool operator()(const TableHeaderPtr h1, - const TableHeaderPtr h2); -}; - -typedef std::set - HeaderOffsetSortedSet; -typedef std::set - HeaderTagSortedSet; - } // namespace sfntly #endif // SFNTLY_CPP_SRC_SFNTLY_TABLE_TABLE_H_ diff --git a/sfntly/table/table_based_table_builder.cc b/sfntly/table/table_based_table_builder.cc new file mode 100644 index 0000000..6e6a46a --- /dev/null +++ b/sfntly/table/table_based_table_builder.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/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_; +} + +/****************************************************************************** + * GenericTableBuilder class + ******************************************************************************/ +GenericTableBuilder::GenericTableBuilder(Header* header, + WritableFontData* data) + : TableBasedTableBuilder(header, data) { +} + +CALLER_ATTACH FontDataTable* + GenericTableBuilder::SubBuildTable(ReadableFontData* data) { + // Note: In C++ port, we use GenericTable, the ref-counted version of Table + UNREFERENCED_PARAMETER(data); + FontDataTablePtr table = new GenericTable(this->header(), InternalReadData()); + return table.Detach(); +} + +CALLER_ATTACH GenericTableBuilder* + GenericTableBuilder::CreateBuilder(Header* header, WritableFontData* data) { + Ptr builder = + new GenericTableBuilder(header, data); + return builder.Detach(); +} + +} // namespace sfntly diff --git a/sfntly/table/table_based_table_builder.h b/sfntly/table/table_based_table_builder.h new file mode 100644 index 0000000..3868d46 --- /dev/null +++ b/sfntly/table/table_based_table_builder.h @@ -0,0 +1,59 @@ +/* + * 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); + TableBasedTableBuilder(Header* header); + + // C++ port: renamed table() to GetTable() + virtual Table* GetTable(); + + // TODO(arthurhsu): style guide violation: protected member, need refactor + TablePtr table_; +}; + +class GenericTableBuilder : public TableBasedTableBuilder, + public RefCounted { + public: + GenericTableBuilder(Header* header, WritableFontData* data); + virtual CALLER_ATTACH FontDataTable* SubBuildTable(ReadableFontData* data); + + static CALLER_ATTACH + GenericTableBuilder* CreateBuilder(Header* header, + WritableFontData* data); +}; + +} // namespace sfntly + +#endif // SFNTLY_CPP_SRC_SFNTLY_TABLE_TABLE_BASED_TABLE_BUILDER_H_ diff --git a/sfntly/tag.cc b/sfntly/tag.cc index e3c11cd..893b74d 100644 --- a/sfntly/tag.cc +++ b/sfntly/tag.cc @@ -52,6 +52,17 @@ const int32_t Tag::PCLT = GenerateTag('P', 'C', 'L', 'T'); const int32_t Tag::VDMX = GenerateTag('V', 'D', 'M', 'X'); const int32_t Tag::vhea = GenerateTag('v', 'h', 'e', 'a'); const int32_t Tag::vmtx = GenerateTag('v', 'm', 't', 'x'); +const int32_t Tag::bsln = GenerateTag('b', 's', 'l', 'n'); +const int32_t Tag::feat = GenerateTag('f', 'e', 'a', 't'); +const int32_t Tag::lcar = GenerateTag('l', 'c', 'a', 'r'); +const int32_t Tag::morx = GenerateTag('m', 'o', 'r', 'x'); +const int32_t Tag::opbd = GenerateTag('o', 'p', 'b', 'd'); +const int32_t Tag::prop = GenerateTag('p', 'r', 'o', 'p'); +const int32_t Tag::Feat = GenerateTag('F', 'e', 'a', 't'); +const int32_t Tag::Glat = GenerateTag('G', 'l', 'a', 't'); +const int32_t Tag::Gloc = GenerateTag('G', 'l', 'o', 'c'); +const int32_t Tag::Sile = GenerateTag('S', 'i', 'l', 'e'); +const int32_t Tag::Silf = GenerateTag('S', 'i', 'l', 'f'); const int32_t Tag::bhed = GenerateTag('b', 'h', 'e', 'd'); const int32_t Tag::bdat = GenerateTag('b', 'd', 'a', 't'); const int32_t Tag::bloc = GenerateTag('b', 'l', 'o', 'c'); diff --git a/sfntly/tag.h b/sfntly/tag.h index 9b50a85..87d2837 100644 --- a/sfntly/tag.h +++ b/sfntly/tag.h @@ -73,8 +73,20 @@ struct Tag { static const int32_t vhea; static const int32_t vmtx; - // GX Tables - // TODO(stuartg): add these tables + // 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; // Bitmap font tables static const int32_t bhed; @@ -91,10 +103,10 @@ inline int32_t GenerateTag(int32_t a, int32_t b, int32_t c, int32_t d) { // The Caller must delete[] the returned value. inline char* TagToString(int32_t tag) { char *name = new char[5]; - name[0] = (char)((tag & 0xff000000) >> 24); - name[1] = (char)((tag & 0x00ff0000) >> 16); - name[2] = (char)((tag & 0x0000ff00) >> 8); - name[3] = (char)(tag & 0x000000ff); + 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; } diff --git a/test/bitmap_table_test.cc b/test/bitmap_table_test.cc new file mode 100644 index 0000000..c8f239c --- /dev/null +++ b/test/bitmap_table_test.cc @@ -0,0 +1,98 @@ +/* + * 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 "gtest/gtest.h" +#include "sfntly/font.h" +#include "sfntly/table/bitmap/ebdt_table.h" +#include "sfntly/table/bitmap/eblc_table.h" +#include "test/test_data.h" +#include "test/test_font_utils.h" + +namespace sfntly { + +const int32_t NUM_STRIKES = 4; +const int32_t STRIKE1_ARRAY_OFFSET = 0xc8; +const int32_t STRIKE1_INDEX_TABLE_SIZE = 0x4f4; +const int32_t STRIKE1_NUM_INDEX_TABLES = 1; +const int32_t STRIKE1_COLOR_REF = 0; +const int32_t STRIKE1_START_GLYPH_INDEX = 0; +const int32_t STRIKE1_END_GLYPH_INDEX = 623; +const int32_t STRIKE1_PPEM_X = 10; +const int32_t STRIKE1_PPEM_Y = 10; +const int32_t STRIKE1_BIT_DEPTH = 1; +const int32_t STRIKE1_FLAGS = 0x01; + +const int32_t STRIKE4_SUB1_IMAGE_FORMAT = 1; +const int32_t STRIKE4_SUB1_IMAGE_DATA_OFFSET = 0x00005893; +const int32_t STRIKE4_SUB1_GLYPH_OFFSET[] = { + 0x00005893, 0x00005898, 0x0000589d, 0x000058a2, 0x000058a7, + 0x000058b2, 0x000058c2, 0x000058d0, 0x000058de, 0x000058e6 }; +const int32_t NUM_STRIKE4_SUB1_GLYPH_OFFSET = 10; // must be 1 less + +bool TestReadingBitmapTable() { + FontFactoryPtr factory; + factory.Attach(FontFactory::GetInstance()); + FontArray font_array; + LoadFont(SAMPLE_BITMAP_FONT, factory, &font_array); + FontPtr font = font_array[0]; + + EblcTablePtr bitmap_loca = down_cast(font->GetTable(Tag::EBLC)); + EbdtTablePtr bitmap_table = down_cast(font->GetTable(Tag::EBDT)); + + EXPECT_FALSE(bitmap_loca == NULL); + EXPECT_FALSE(bitmap_table == NULL); + + EXPECT_EQ(bitmap_loca->NumSizes(), NUM_STRIKES); + + // Strike 1 + BitmapSizeTablePtr strike1 = bitmap_loca->GetBitmapSizeTable(0); + EXPECT_FALSE(strike1 == NULL); + EXPECT_EQ(strike1->IndexSubTableArrayOffset(), STRIKE1_ARRAY_OFFSET); + EXPECT_EQ(strike1->IndexTableSize(), STRIKE1_INDEX_TABLE_SIZE); + EXPECT_EQ(strike1->NumberOfIndexSubTables(), STRIKE1_NUM_INDEX_TABLES); + EXPECT_EQ(strike1->ColorRef(), STRIKE1_COLOR_REF); + EXPECT_EQ(strike1->StartGlyphIndex(), STRIKE1_START_GLYPH_INDEX); + EXPECT_EQ(strike1->EndGlyphIndex(), STRIKE1_END_GLYPH_INDEX); + EXPECT_EQ(strike1->PpemX(), STRIKE1_PPEM_X); + EXPECT_EQ(strike1->PpemY(), STRIKE1_PPEM_Y); + EXPECT_EQ(strike1->BitDepth(), STRIKE1_BIT_DEPTH); + EXPECT_EQ(strike1->FlagsAsInt(), STRIKE1_FLAGS); + + // Strike 4 + // In this test font, all strikes and all subtables have same glyphs. + BitmapSizeTablePtr strike4 = bitmap_loca->GetBitmapSizeTable(3); + EXPECT_FALSE(strike4 == NULL); + EXPECT_EQ(strike4->StartGlyphIndex(), STRIKE1_START_GLYPH_INDEX); + EXPECT_EQ(strike4->EndGlyphIndex(), STRIKE1_END_GLYPH_INDEX); + IndexSubTablePtr sub1 = strike4->GetIndexSubTable(0); + EXPECT_FALSE(sub1 == NULL); + EXPECT_EQ(sub1->first_glyph_index(), STRIKE1_START_GLYPH_INDEX); + EXPECT_EQ(sub1->last_glyph_index(), STRIKE1_END_GLYPH_INDEX); + EXPECT_EQ(sub1->image_format(), STRIKE4_SUB1_IMAGE_FORMAT); + EXPECT_EQ(sub1->image_data_offset(), STRIKE4_SUB1_IMAGE_DATA_OFFSET); + + for (int32_t i = 0; i < NUM_STRIKE4_SUB1_GLYPH_OFFSET; ++i) { + EXPECT_EQ(sub1->GlyphOffset(i), STRIKE4_SUB1_GLYPH_OFFSET[i]); + } + + return true; +} + +} // namespace sfntly + +TEST(BitmapTable, All) { + ASSERT_TRUE(sfntly::TestReadingBitmapTable()); +} diff --git a/test/file_io_test.cc b/test/file_io_test.cc index e6801d5..3cec4d6 100644 --- a/test/file_io_test.cc +++ b/test/file_io_test.cc @@ -134,19 +134,12 @@ bool TestFontInputStreamTableLoading() { is.Open(SAMPLE_TTF_FILE); FontInputStream font_is(&is); - font_is.Skip(TTF_OFFSET[SAMPLE_TTF_GDEF]); - FontInputStream gdef_is(&font_is, TTF_LENGTH[SAMPLE_TTF_GDEF]); - ByteVector gdef_data; - gdef_is.Read(&gdef_data, 0, TTF_LENGTH[SAMPLE_TTF_GDEF]); - EXPECT_EQ(memcmp(&(gdef_data[0]), TTF_GDEF_DATA, - TTF_LENGTH[SAMPLE_TTF_GDEF]), 0); - - font_is.Skip(TTF_OFFSET[SAMPLE_TTF_HEAD] - font_is.position()); - FontInputStream head_is(&font_is, TTF_LENGTH[SAMPLE_TTF_HEAD]); - ByteVector head_data; - head_is.Read(&head_data, 0, TTF_LENGTH[SAMPLE_TTF_HEAD]); - EXPECT_EQ(memcmp(&(head_data[0]), TTF_HEAD_DATA, - TTF_LENGTH[SAMPLE_TTF_HEAD]), 0); + font_is.Skip(TTF_OFFSET[SAMPLE_TTF_FEAT]); + FontInputStream gdef_is(&font_is, TTF_LENGTH[SAMPLE_TTF_FEAT]); + ByteVector feat_data; + gdef_is.Read(&feat_data, 0, TTF_LENGTH[SAMPLE_TTF_FEAT]); + EXPECT_EQ(memcmp(&(feat_data[0]), TTF_FEAT_DATA, + TTF_LENGTH[SAMPLE_TTF_FEAT]), 0); return true; } diff --git a/test/font_parsing_test.cc b/test/font_parsing_test.cc index fb161a6..60c5524 100644 --- a/test/font_parsing_test.cc +++ b/test/font_parsing_test.cc @@ -22,6 +22,7 @@ #include "sfntly/font_factory.h" #include "sfntly/table/core/font_header_table.h" #include "sfntly/table/table.h" +#include "sfntly/table/table_based_table_builder.h" #include "sfntly/tag.h" #include "sfntly/port/file_input_stream.h" #include "test/test_data.h" @@ -50,27 +51,26 @@ bool TestFontParsing() { } // Generic table - Ptr gdef_builder = - down_cast( - font_builder->GetTableBuilder(Tag::GDEF)); - Ptr gdef_header = gdef_builder->header(); - EXPECT_EQ(gdef_header->length(), TTF_LENGTH[SAMPLE_TTF_GDEF]); - EXPECT_EQ(gdef_header->offset(), TTF_OFFSET[SAMPLE_TTF_GDEF]); - EXPECT_EQ(gdef_header->checksum(), TTF_CHECKSUM[SAMPLE_TTF_GDEF]); + Ptr gdef_builder = + down_cast(font_builder->GetTableBuilder(Tag::feat)); + HeaderPtr gdef_header = gdef_builder->header(); + EXPECT_EQ(gdef_header->length(), TTF_LENGTH[SAMPLE_TTF_FEAT]); + EXPECT_EQ(gdef_header->offset(), TTF_OFFSET[SAMPLE_TTF_FEAT]); + EXPECT_EQ(gdef_header->checksum(), TTF_CHECKSUM[SAMPLE_TTF_FEAT]); EXPECT_TRUE(gdef_header->checksum_valid()); WritableFontDataPtr wfd; wfd.Attach(gdef_builder->Data()); ByteVector b; - b.resize(TTF_LENGTH[SAMPLE_TTF_GDEF]); - wfd->ReadBytes(0, &(b[0]), 0, TTF_LENGTH[SAMPLE_TTF_GDEF]); - EXPECT_EQ(memcmp(&(b[0]), TTF_GDEF_DATA, TTF_LENGTH[SAMPLE_TTF_GDEF]), 0); + b.resize(TTF_LENGTH[SAMPLE_TTF_FEAT]); + wfd->ReadBytes(0, &(b[0]), 0, TTF_LENGTH[SAMPLE_TTF_FEAT]); + EXPECT_EQ(memcmp(&(b[0]), TTF_FEAT_DATA, TTF_LENGTH[SAMPLE_TTF_FEAT]), 0); // Header table FontHeaderTableBuilderPtr header_builder = down_cast( font_builder->GetTableBuilder(Tag::head)); - Ptr header_header = header_builder->header(); + HeaderPtr header_header = header_builder->header(); EXPECT_EQ(header_header->length(), TTF_LENGTH[SAMPLE_TTF_HEAD]); EXPECT_EQ(header_header->offset(), TTF_OFFSET[SAMPLE_TTF_HEAD]); EXPECT_EQ(header_header->checksum(), TTF_CHECKSUM[SAMPLE_TTF_HEAD]); diff --git a/test/otf_basic_editing_test.cc b/test/otf_basic_editing_test.cc index c99a3a3..7388fac 100644 --- a/test/otf_basic_editing_test.cc +++ b/test/otf_basic_editing_test.cc @@ -66,7 +66,7 @@ bool TestOTFBasicEditing() { for (TableMap::const_iterator i = table_map->begin(), e = table_map->end(); i != e; ++i) { TablePtr table = (*i).second; - TableHeaderPtr header = table->header(); + HeaderPtr header = table->header(); EXPECT_TRUE(builder_tags.find(header->tag()) != builder_tags.end()); builder_tags.erase(header->tag()); } diff --git a/test/test_data.cc b/test/test_data.cc index e4cabbe..6c26f0e 100644 --- a/test/test_data.cc +++ b/test/test_data.cc @@ -26,46 +26,43 @@ namespace sfntly { // code. const char* SAMPLE_TTF_FILE = "Tuffy.ttf"; -const char* SAMPLE_OTF_FILE = "Tuffy.otf"; +const char* SAMPLE_BITMAP_FONT = "AnonymousPro-Regular.ttf"; -const size_t SAMPLE_TTF_SIZE = 18444; -const size_t SAMPLE_TTF_TABLES = 16; -const size_t SAMPLE_TTF_KNOWN_TAGS = 15; -const size_t SAMPLE_TTF_GDEF = 0; -const size_t SAMPLE_TTF_HEAD = 8; +const size_t SAMPLE_TTF_SIZE = 183936; +const size_t SAMPLE_TTF_TABLES = 17; +const size_t SAMPLE_TTF_KNOWN_TAGS = 16; +const size_t SAMPLE_TTF_FEAT = 3; +const size_t SAMPLE_TTF_HEAD = 6; const size_t SAMPLE_TTF_POST = 14; const int32_t TTF_KNOWN_TAGS[] = { - Tag::GDEF, Tag::GPOS, Tag::GSUB, Tag::OS_2, Tag::cmap, Tag::cvt, - Tag::gasp, Tag::glyf, Tag::head, Tag::hhea, Tag::hmtx, Tag::loca, - Tag::maxp, Tag::name, Tag::post }; + Tag::OS_2, Tag::cmap, Tag::cvt, Tag::feat, Tag::gasp, + Tag::glyf, Tag::head, Tag::hhea, Tag::hmtx, Tag::kern, + Tag::loca, Tag::maxp, Tag::morx, Tag::name, Tag::post, + Tag::prop }; const int64_t TTF_CHECKSUM[] = { - 0x002900cb, 0xe1b5ef99, 0x6c91748f, 0xae08cb6b, 0xc62ba2e8, 0x00210279, - 0xffff0003, 0x8ed2ba01, 0xe8afc442, 0x0dce8e86, 0x77c44a8a, 0xbfd5cd52, - 0x011200bc, 0x2f64d0e9, 0x6548bddf }; + 0xD463FC48, 0x252028D1, 0x0065078A, 0xC01407B5, 0xFFFF0003, + 0x9544342B, 0xFC8F16AD, 0x0EC30C7A, 0xA029CD5D, 0x32513087, + 0x05C323B0, 0x06320195, 0x3B67E701, 0xE7DB08F3, 0xD46E5E89, + 0xE6EB4A27 }; const int64_t TTF_OFFSET[] = { - 0x4650, 0x4690, 0x4670, 0x0188, 0x04f4, 0x0738, - 0x4648, 0x08c8, 0x010c, 0x0144, 0x01e0, 0x073c, - 0x0168, 0x3d9c, 0x4468 }; + 0x00000198, 0x00001964, 0x000025B0, 0x0002CA74, 0x0002C854, + 0x00003D34, 0x0000011C, 0x00000154, 0x000001F0, 0x000245D8, + 0x000025B8, 0x00000178, 0x0002CAB4, 0x00024860, 0x00028854, + 0x0002C85C }; const int32_t TTF_LENGTH[] = { - 0x001e, 0x015e, 0x0020, 0x0056, 0x0242, 0x0004, - 0x0008, 0x34d4, 0x0036, 0x0024, 0x0314, 0x018c, - 0x0020, 0x06cb, 0x01dd }; + 86, 3146, 8, 64, 8, + 133284, 54, 36, 6002, 648, + 6012, 32, 944, 16371, 16383, + 536 }; -const unsigned char TTF_GDEF_DATA[] = { - 0, 1, 0, 0, 0, 0x0c, 0, 0, 0, 0x16, 0, 0, 0, 2, 0, 1, - 0, 3, 0, 0xc4, 0, 1, 0, 4, 0, 0, 0, 2, 0, 0 }; - -const unsigned char TTF_HEAD_DATA[] = { - 0, 1, 0, 0, - 0, 1, 0x19, 0x99, 9, 6, 0x34, 0xb7, 0x5f, 0xf, 0x3c, 0xf5, 0, 0xb, 8, 0, - 0, 0, 0, 0, 0xc1, 0xf5, 0x2f, 0xd2, 0, 0, 0, 0, 0xc1, 0xf5, 0x2f, 0xd2, - 0xff, 0x89, 0xfe, 0x3f, 6, 0x1d, 7, 0xc9, 0, 0, 0, 8, 0, 2, 0, 0, - 0, 0 }; - -const size_t SAMPLE_OTF_SIZE = 18900; +const unsigned char TTF_FEAT_DATA[] = { + 0, 1, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, + 0, 0, 0, 0x30, 0, 0, 1, 0, 0, 1, 0, 1, 0, 0, 0, 0x34, + 0, 0, 1, 1, 0, 0xB, 0, 2, 0, 0, 0, 0x38, 0xC0, 0, 1, 2, + 0, 0, 1, 3, 0, 2, 1, 4, 0, 0, 1, 5, 0, 2, 1, 6 }; } // namespace sfntly diff --git a/test/test_data.h b/test/test_data.h index 1b50549..b6a5ed6 100644 --- a/test/test_data.h +++ b/test/test_data.h @@ -22,12 +22,12 @@ namespace sfntly { extern const char* SAMPLE_TTF_FILE; -extern const char* SAMPLE_OTF_FILE; +extern const char* SAMPLE_BITMAP_FONT; extern const size_t SAMPLE_TTF_SIZE; extern const size_t SAMPLE_TTF_TABLES; extern const size_t SAMPLE_TTF_KNOWN_TAGS; -extern const size_t SAMPLE_TTF_GDEF; +extern const size_t SAMPLE_TTF_FEAT; extern const size_t SAMPLE_TTF_HEAD; extern const size_t SAMPLE_TTF_POST; @@ -35,10 +35,7 @@ extern const int32_t TTF_KNOWN_TAGS[]; extern const int64_t TTF_CHECKSUM[]; extern const int64_t TTF_OFFSET[]; extern const int32_t TTF_LENGTH[]; -extern const unsigned char TTF_GDEF_DATA[]; -extern const unsigned char TTF_HEAD_DATA[]; - -extern const size_t SAMPLE_OTF_SIZE; +extern const unsigned char TTF_FEAT_DATA[]; } // namespace sfntly diff --git a/test/verify_glyf.cc b/test/verify_glyf.cc index ff89638..abfe1ab 100644 --- a/test/verify_glyf.cc +++ b/test/verify_glyf.cc @@ -22,7 +22,7 @@ namespace sfntly { // We spot check only glyph id 33. -const int32_t GLYPH33_OFFSET = 0xA70; +const int32_t GLYPH33_OFFSET = 0xAC8; const int32_t GLYPH33_LENGTH = 40; const int32_t GLYPH33_XMIN = 92; const int32_t GLYPH33_YMIN = 20; diff --git a/test/verify_hhea.cc b/test/verify_hhea.cc index 05886d4..021c189 100644 --- a/test/verify_hhea.cc +++ b/test/verify_hhea.cc @@ -21,15 +21,15 @@ namespace sfntly { -const int32_t HHEA_ASCENDER = 1993; -const int32_t HHEA_DESCENDER = -449; +const int32_t HHEA_ASCENDER = 2023; +const int32_t HHEA_DESCENDER = -648; const int32_t HHEA_LINE_GAP = 93; -const int32_t HHEA_ADVANCE_WIDTH_MAX = 3969; -const int32_t HHEA_MIN_LSB = -119; -const int32_t HHEA_MIN_RSB = -32768; -const int32_t HHEA_X_MAX_EXTENT = 1565; +const int32_t HHEA_ADVANCE_WIDTH_MAX = 2753; +const int32_t HHEA_MIN_LSB = -968; +const int32_t HHEA_MIN_RSB = -411; +const int32_t HHEA_X_MAX_EXTENT = 2628; const int32_t HHEA_METRIC_DATA_FORMAT = 0; -const int32_t HHEA_NUM_METRICS = 197; +const int32_t HHEA_NUM_METRICS = 1499; static bool VerifyHHEA(Table* table) { HorizontalHeaderTablePtr hhea = down_cast(table); diff --git a/test/verify_hmtx.cc b/test/verify_hmtx.cc index 67ea6a3..d37bba9 100644 --- a/test/verify_hmtx.cc +++ b/test/verify_hmtx.cc @@ -21,8 +21,8 @@ namespace sfntly { -const int32_t HMTX_ENTRIES_COUNT = 197; -const int32_t HMTX_LSB_COUNT = 0; +const int32_t HMTX_ENTRIES_COUNT = 1499; +const int32_t HMTX_LSB_COUNT = 3; struct HmtxEntry { int32_t advance_width_; @@ -33,7 +33,7 @@ struct HmtxEntry { }; const HmtxEntry HMTX_ENTRIES[] = { - HmtxEntry(32768, 0), // 0 + HmtxEntry(748, 68), // 0 HmtxEntry(0, 0), // 1 HmtxEntry(682, 0), // 2 HmtxEntry(616, 0), // 3 @@ -43,196 +43,8 @@ const HmtxEntry HMTX_ENTRIES[] = { HmtxEntry(1017, 25), // 7 HmtxEntry(1402, 104), // 8 HmtxEntry(1241, 100), // 9 - HmtxEntry(382, 129), // 10 - HmtxEntry(548, 41), // 11 - HmtxEntry(536, 90), // 12 - HmtxEntry(913, 33), // 13 - HmtxEntry(894, 78), // 14 - HmtxEntry(399, 103), // 15 - HmtxEntry(866, 109), // 16 - HmtxEntry(405, 103), // 17 - HmtxEntry(808, -23), // 18 - HmtxEntry(1136, 100), // 19 - HmtxEntry(1136, 424), // 20 - HmtxEntry(1136, 109), // 21 - HmtxEntry(1126, 113), // 22 - HmtxEntry(1136, 88), // 23 - HmtxEntry(1136, 135), // 24 - HmtxEntry(1136, 129), // 25 - HmtxEntry(1136, 111), // 26 - HmtxEntry(1136, 104), // 27 - HmtxEntry(1136, 143), // 28 - HmtxEntry(423, 113), // 29 - HmtxEntry(423, 113), // 30 - HmtxEntry(843, 84), // 31 - HmtxEntry(907, 66), // 32 - HmtxEntry(856, 92), // 33 - HmtxEntry(985, 57), // 34 - HmtxEntry(1624, 41), // 35 - HmtxEntry(1302, 72), // 36 - HmtxEntry(1179, 121), // 37 - HmtxEntry(1220, 100), // 38 - HmtxEntry(1220, 121), // 39 - HmtxEntry(1142, 121), // 40 - HmtxEntry(1146, 121), // 41 - HmtxEntry(1363, 100), // 42 - HmtxEntry(1198, 121), // 43 - HmtxEntry(444, 154), // 44 - HmtxEntry(1140, 113), // 45 - HmtxEntry(1239, 121), // 46 - HmtxEntry(1105, 121), // 47 - HmtxEntry(1562, 121), // 48 - HmtxEntry(1271, 121), // 49 - HmtxEntry(1333, 92), // 50 - HmtxEntry(1099, 121), // 51 - HmtxEntry(1370, 92), // 52 - HmtxEntry(1101, 121), // 53 - HmtxEntry(1079, 45), // 54 - HmtxEntry(1243, 88), // 55 - HmtxEntry(1265, 121), // 56 - HmtxEntry(1245, 80), // 57 - HmtxEntry(1576, 84), // 58 - HmtxEntry(1214, 74), // 59 - HmtxEntry(1179, 76), // 60 - HmtxEntry(1325, 100), // 61 - HmtxEntry(626, 131), // 62 - HmtxEntry(811, -29), // 63 - HmtxEntry(638, 129), // 64 - HmtxEntry(927, 133), // 65 - HmtxEntry(1241, 88), // 66 - HmtxEntry(516, 96), // 67 - HmtxEntry(993, 84), // 68 - HmtxEntry(1044, 129), // 69 - HmtxEntry(921, 76), // 70 - HmtxEntry(1044, 73), // 71 - HmtxEntry(1013, 98), // 72 - HmtxEntry(716, 125), // 73 - HmtxEntry(1021, 73), // 74 - HmtxEntry(1064, 129), // 75 - HmtxEntry(430, 131), // 76 - HmtxEntry(468, -119), // 77 - HmtxEntry(944, 129), // 78 - HmtxEntry(430, 150), // 79 - HmtxEntry(1533, 129), // 80 - HmtxEntry(1064, 129), // 81 - HmtxEntry(1054, 102), // 82 - HmtxEntry(1044, 129), // 83 - HmtxEntry(1048, 73), // 84 - HmtxEntry(686, 129), // 85 - HmtxEntry(921, 96), // 86 - HmtxEntry(696, 102), // 87 - HmtxEntry(1064, 120), // 88 - HmtxEntry(1024, 82), // 89 - HmtxEntry(1374, 68), // 90 - HmtxEntry(901, 53), // 91 - HmtxEntry(1064, 120), // 92 - HmtxEntry(962, 90), // 93 - HmtxEntry(747, 90), // 94 - HmtxEntry(368, 125), // 95 - HmtxEntry(747, 133), // 96 - HmtxEntry(735, 63), // 97 - HmtxEntry(309, 28), // 98 - HmtxEntry(808, 80), // 99 - HmtxEntry(1120, 84), // 100 - HmtxEntry(856, 63), // 101 - HmtxEntry(1110, 74), // 102 - HmtxEntry(305, 90), // 103 - HmtxEntry(686, 43), // 104 - HmtxEntry(794, 76), // 105 - HmtxEntry(942, 41), // 106 - HmtxEntry(872, 59), // 107 - HmtxEntry(1026, 154), // 108 - HmtxEntry(950, 109), // 109 - HmtxEntry(1189, 94), // 110 - HmtxEntry(706, 63), // 111 - HmtxEntry(598, 49), // 112 - HmtxEntry(983, 150), // 113 - HmtxEntry(550, 97), // 114 - HmtxEntry(1003, 154), // 115 - HmtxEntry(1150, 121), // 116 - HmtxEntry(438, 142), // 117 - HmtxEntry(473, 117), // 118 - HmtxEntry(933, 98), // 119 - HmtxEntry(954, 18), // 120 - HmtxEntry(1292, 82), // 121 - HmtxEntry(1292, 82), // 122 - HmtxEntry(1292, 82), // 123 - HmtxEntry(1292, 82), // 124 - HmtxEntry(1292, 82), // 125 - HmtxEntry(1292, 82), // 126 - HmtxEntry(1388, 83), // 127 - HmtxEntry(1220, 120), // 128 - HmtxEntry(1146, 131), // 129 - HmtxEntry(1146, 131), // 130 - HmtxEntry(1146, 131), // 131 - HmtxEntry(1146, 131), // 132 - HmtxEntry(440, -53), // 133 - HmtxEntry(440, 164), // 134 - HmtxEntry(440, -103), // 135 - HmtxEntry(440, -90), // 136 - HmtxEntry(3969, 144), // 137 - HmtxEntry(1292, 131), // 138 - HmtxEntry(1329, 102), // 139 - HmtxEntry(1329, 102), // 140 - HmtxEntry(1329, 102), // 141 - HmtxEntry(1329, 102), // 142 - HmtxEntry(1329, 102), // 143 - HmtxEntry(833, 108), // 144 - HmtxEntry(2416, 96), // 145 - HmtxEntry(1298, 131), // 146 - HmtxEntry(1298, 131), // 147 - HmtxEntry(1298, 131), // 148 - HmtxEntry(1298, 131), // 149 - HmtxEntry(1179, 86), // 150 - HmtxEntry(1329, 145), // 151 - HmtxEntry(1212, 92), // 152 - HmtxEntry(1036, 94), // 153 - HmtxEntry(1036, 94), // 154 - HmtxEntry(1036, 94), // 155 - HmtxEntry(1036, 94), // 156 - HmtxEntry(1036, 94), // 157 - HmtxEntry(1036, 94), // 158 - HmtxEntry(1486, 84), // 159 - HmtxEntry(1011, 86), // 160 - HmtxEntry(1046, 108), // 161 - HmtxEntry(1046, 108), // 162 - HmtxEntry(1046, 108), // 163 - HmtxEntry(1046, 108), // 164 - HmtxEntry(428, -75), // 165 - HmtxEntry(421, 150), // 166 - HmtxEntry(888, 115), // 167 - HmtxEntry(667, 8), // 168 - HmtxEntry(1030, 82), // 169 - HmtxEntry(1044, 139), // 170 - HmtxEntry(1060, 112), // 171 - HmtxEntry(1062, 112), // 172 - HmtxEntry(1062, 112), // 173 - HmtxEntry(1062, 112), // 174 - HmtxEntry(1060, 112), // 175 - HmtxEntry(911, 119), // 176 - HmtxEntry(1024, 86), // 177 - HmtxEntry(1032, 130), // 178 - HmtxEntry(1064, 130), // 179 - HmtxEntry(1064, 130), // 180 - HmtxEntry(1064, 130), // 181 - HmtxEntry(1064, 130), // 182 - HmtxEntry(1003, 129), // 183 - HmtxEntry(1064, 130), // 184 - HmtxEntry(1087, 170), // 185 - HmtxEntry(1001, 170), // 186 - HmtxEntry(1290, 150), // 187 - HmtxEntry(385, 83), // 188 - HmtxEntry(385, 95), // 189 - HmtxEntry(385, 99), // 190 - HmtxEntry(385, 106), // 191 - HmtxEntry(677, 81), // 192 - HmtxEntry(677, 97), // 193 - HmtxEntry(688, 113), // 194 - HmtxEntry(688, 91), // 195 - HmtxEntry(1089, 135), // 196 - - HmtxEntry(32768, 0) // 197: no such element, used to check the logic. }; +const int32_t NUM_HMTX_ENTRIES = 10; static bool VerifyHMTX(Table* table) { HorizontalMetricsTablePtr hmtx = down_cast(table); @@ -243,11 +55,15 @@ static bool VerifyHMTX(Table* table) { EXPECT_EQ(hmtx->NumberOfHMetrics(), HMTX_ENTRIES_COUNT); EXPECT_EQ(hmtx->NumberOfLSBs(), HMTX_LSB_COUNT); - for (int32_t i = 0; i < HMTX_ENTRIES_COUNT + 1; ++i) { + for (int32_t i = 0; i < NUM_HMTX_ENTRIES; ++i) { EXPECT_EQ(hmtx->AdvanceWidth(i), HMTX_ENTRIES[i].advance_width_); EXPECT_EQ(hmtx->LeftSideBearing(i), HMTX_ENTRIES[i].lsb_); } + // No such element case. + EXPECT_EQ(hmtx->AdvanceWidth(HMTX_ENTRIES_COUNT), + HMTX_ENTRIES[0].advance_width_); + EXPECT_EQ(hmtx->LeftSideBearing(HMTX_ENTRIES_COUNT), HMTX_ENTRIES[0].lsb_); return true; } diff --git a/test/verify_loca.cc b/test/verify_loca.cc index 3090841..4a32928 100644 --- a/test/verify_loca.cc +++ b/test/verify_loca.cc @@ -21,207 +21,21 @@ namespace sfntly { -const int32_t LOCA_NUM_LOCAS = 198; +const int32_t LOCA_NUM_LOCAS = 1503; const int32_t LOCAS[] = { 0x00000, // 0 - 0x00000, // 1 - 0x00000, // 2 - 0x00000, // 3 - 0x00000, // 4 - 0x00060, // 5 - 0x000E0, // 6 - 0x0014C, // 7 - 0x001FC, // 8 - 0x002C8, // 9 - 0x00358, // 10 - 0x0039C, // 11 - 0x003D4, // 12 - 0x0040C, // 13 - 0x004B4, // 14 - 0x004E4, // 15 - 0x00530, // 16 - 0x0054C, // 17 - 0x00584, // 18 - 0x005A0, // 19 - 0x0061C, // 20 - 0x0063C, // 21 - 0x006C4, // 22 - 0x0074C, // 23 - 0x0078C, // 24 - 0x00804, // 25 - 0x00888, // 26 - 0x008AC, // 27 - 0x0096C, // 28 - 0x009F0, // 29 - 0x00A08, // 30 - 0x00A20, // 31 - 0x00A48, // 32 - 0x00A70, // 33 - 0x00A98, // 34 - 0x00B44, // 35 - 0x00C40, // 36 - 0x00C78, // 37 - 0x00D24, // 38 - 0x00D9C, // 39 - 0x00DF8, // 40 - 0x00E28, // 41 - 0x00E54, // 42 - 0x00EDC, // 43 - 0x00F0C, // 44 - 0x00F24, // 45 - 0x00F6C, // 46 - 0x00FA4, // 47 - 0x00FC4, // 48 - 0x00FFC, // 49 - 0x01028, // 50 - 0x010BC, // 51 - 0x01114, // 52 - 0x011C0, // 53 - 0x0121C, // 54 - 0x012C0, // 55 - 0x012E8, // 56 - 0x0133C, // 57 - 0x01364, // 58 - 0x013A0, // 59 - 0x013E0, // 60 - 0x01410, // 61 - 0x0143C, // 62 - 0x01460, // 63 - 0x01480, // 64 - 0x014A4, // 65 - 0x014C8, // 66 - 0x014E0, // 67 - 0x0152C, // 68 - 0x015AC, // 69 - 0x01618, // 70 - 0x01680, // 71 - 0x016EC, // 72 - 0x0175C, // 73 - 0x017B0, // 74 - 0x01848, // 75 - 0x01898, // 76 - 0x018DC, // 77 - 0x01948, // 78 - 0x01980, // 79 - 0x019B0, // 80 - 0x01A28, // 81 - 0x01A74, // 82 - 0x01AE0, // 83 - 0x01B4C, // 84 - 0x01BC0, // 85 - 0x01BFC, // 86 - 0x01C94, // 87 - 0x01CCC, // 88 - 0x01D1C, // 89 - 0x01D48, // 90 - 0x01D84, // 91 - 0x01DBC, // 92 - 0x01E2C, // 93 - 0x01E54, // 94 - 0x01F04, // 95 - 0x01F1C, // 96 - 0x01FCC, // 97 - 0x02028, // 98 - 0x02044, // 99 - 0x020AC, // 100 - 0x02128, // 101 - 0x021B8, // 102 - 0x0220C, // 103 - 0x02234, // 104 - 0x022E0, // 105 - 0x02348, // 106 - 0x023F4, // 107 - 0x02430, // 108 - 0x02450, // 109 - 0x02464, // 110 - 0x02540, // 111 - 0x0255C, // 112 - 0x025C0, // 113 - 0x025DC, // 114 - 0x02628, // 115 - 0x02680, // 116 - 0x0270C, // 117 - 0x02720, // 118 - 0x02768, // 119 - 0x027A4, // 120 - 0x027B8, // 121 - 0x027D0, // 122 - 0x027E8, // 123 - 0x02800, // 124 - 0x02818, // 125 - 0x02830, // 126 - 0x02848, // 127 - 0x02898, // 128 - 0x028B0, // 129 - 0x028C8, // 130 - 0x028E0, // 131 - 0x028F8, // 132 - 0x02910, // 133 - 0x02928, // 134 - 0x02940, // 135 - 0x02958, // 136 - 0x02970, // 137 - 0x029D8, // 138 - 0x029F0, // 139 - 0x02A08, // 140 - 0x02A20, // 141 - 0x02A38, // 142 - 0x02A50, // 143 - 0x02A68, // 144 - 0x02A84, // 145 - 0x02B30, // 146 - 0x02B48, // 147 - 0x02B60, // 148 - 0x02B78, // 149 - 0x02B90, // 150 - 0x02BA8, // 151 - 0x02C00, // 152 - 0x02CCC, // 153 - 0x02CE4, // 154 - 0x02CFC, // 155 - 0x02D14, // 156 - 0x02D2C, // 157 - 0x02D44, // 158 - 0x02D5C, // 159 - 0x02E6C, // 160 - 0x02E84, // 161 - 0x02E9C, // 162 - 0x02EB4, // 163 - 0x02ECC, // 164 - 0x02EE4, // 165 - 0x02F3C, // 166 - 0x02F94, // 167 - 0x02FC8, // 168 - 0x0303C, // 169 - 0x030FC, // 170 - 0x03114, // 171 - 0x0312C, // 172 - 0x03144, // 173 - 0x0315C, // 174 - 0x03174, // 175 - 0x0318C, // 176 - 0x031A4, // 177 - 0x03240, // 178 - 0x03258, // 179 - 0x03270, // 180 - 0x03288, // 181 - 0x032A0, // 182 - 0x032B8, // 183 - 0x0333C, // 184 - 0x03354, // 185 - 0x03370, // 186 - 0x0338C, // 187 - 0x033A8, // 188 - 0x033BC, // 189 - 0x033D0, // 190 - 0x033E4, // 191 - 0x033F4, // 192 - 0x0340C, // 193 - 0x03424, // 194 - 0x03438, // 195 - 0x03448, // 196 - 0x034D4 // 197 + 0x00058, // 1 + 0x00058, // 2 + 0x00058, // 3 + 0x00058, // 4 + 0x000B8, // 5 + 0x00138, // 6 + 0x001A4, // 7 + 0x0025C, // 8 + 0x00328, // 9 + 0x003B8, // 10 }; +const int32_t NUM_TEST_LOCAS = 11; static bool VerifyLOCA(Table* table) { LocaTablePtr loca = down_cast(table); @@ -232,7 +46,7 @@ static bool VerifyLOCA(Table* table) { EXPECT_EQ(loca->NumLocas(), LOCA_NUM_LOCAS); EXPECT_EQ(loca->num_glyphs(), LOCA_NUM_LOCAS - 1); - for (int32_t i = 0; i < LOCA_NUM_LOCAS - 1; ++i) { + for (int32_t i = 0; i < NUM_TEST_LOCAS - 1; ++i) { EXPECT_EQ(loca->GlyphOffset(i), LOCAS[i]); EXPECT_EQ(loca->GlyphLength(i), LOCAS[i + 1] - LOCAS[i]); } diff --git a/test/verify_maxp.cc b/test/verify_maxp.cc index 3b8e183..437c0dd 100644 --- a/test/verify_maxp.cc +++ b/test/verify_maxp.cc @@ -21,19 +21,19 @@ namespace sfntly { -const int32_t MAXP_NUM_GLYPHS = 197; -const int32_t MAXP_MAX_POINTS = 98; -const int32_t MAXP_MAX_CONTOURS = 5; -const int32_t MAXP_MAX_COMPOSITE_POINTS = 84; -const int32_t MAXP_MAX_COMPOSITE_CONTOURS = 4; +const int32_t MAXP_NUM_GLYPHS = 1502; +const int32_t MAXP_MAX_POINTS = 181; +const int32_t MAXP_MAX_CONTOURS = 9; +const int32_t MAXP_MAX_COMPOSITE_POINTS = 172; +const int32_t MAXP_MAX_COMPOSITE_CONTOURS = 5; const int32_t MAXP_MAX_ZONES = 2; const int32_t MAXP_MAX_TWILIGHT_POINTS = 0; const int32_t MAXP_MAX_STORAGE = 1; const int32_t MAXP_MAX_FUNCTION_DEFS = 1; const int32_t MAXP_MAX_INSTR_DEFS = 0; const int32_t MAXP_MAX_STACK_ELEMENTS = 64; -const int32_t MAXP_MAX_INSTR_SIZE = 0; -const int32_t MAXP_MAX_COMPONENT_ELEMENTS = 2; +const int32_t MAXP_MAX_INSTR_SIZE = 46; +const int32_t MAXP_MAX_COMPONENT_ELEMENTS = 4; const int32_t MAXP_MAX_COMPONENT_DEPTH = 3; static bool VerifyMAXP(Table* table) { diff --git a/test/verify_name.cc b/test/verify_name.cc index fa56de5..e1101c0 100644 --- a/test/verify_name.cc +++ b/test/verify_name.cc @@ -22,7 +22,7 @@ namespace sfntly { const int32_t NAME_FORMAT = 0; -const int32_t NAME_COUNT = 31; +const int32_t NAME_COUNT = 75; const NameTable::NameEntryId NAME_IDS[] = { NameTable::NameEntryId(1, 0, 0, 0), // 0 NameTable::NameEntryId(1, 0, 0, 1), // 1 @@ -34,28 +34,8 @@ const NameTable::NameEntryId NAME_IDS[] = { NameTable::NameEntryId(1, 0, 0, 9), // 7 NameTable::NameEntryId(1, 0, 0, 11), // 8 NameTable::NameEntryId(1, 0, 0, 12), // 9 - NameTable::NameEntryId(1, 0, 0, 13), // 10 - NameTable::NameEntryId(3, 1, 1031, 2), // 11 - NameTable::NameEntryId(3, 1, 1033, 0), // 12 - NameTable::NameEntryId(3, 1, 1033, 1), // 13 - NameTable::NameEntryId(3, 1, 1033, 2), // 14 - NameTable::NameEntryId(3, 1, 1033, 3), // 15 - NameTable::NameEntryId(3, 1, 1033, 4), // 16 - NameTable::NameEntryId(3, 1, 1033, 5), // 17 - NameTable::NameEntryId(3, 1, 1033, 6), // 18 - NameTable::NameEntryId(3, 1, 1033, 9), // 19 - NameTable::NameEntryId(3, 1, 1033, 11), // 20 - NameTable::NameEntryId(3, 1, 1033, 12), // 21 - NameTable::NameEntryId(3, 1, 1033, 13), // 22 - NameTable::NameEntryId(3, 1, 1034, 2), // 23 - NameTable::NameEntryId(3, 1, 1036, 2), // 24 - NameTable::NameEntryId(3, 1, 1038, 2), // 25 - NameTable::NameEntryId(3, 1, 1040, 2), // 26 - NameTable::NameEntryId(3, 1, 1043, 2), // 27 - NameTable::NameEntryId(3, 1, 1044, 2), // 28 - NameTable::NameEntryId(3, 1, 1049, 2), // 29 - NameTable::NameEntryId(3, 1, 1053, 2), // 30 }; +const int32_t NAME_IDS_TEST = 10; static bool VerifyNAME(Table* table) { // TODO(arthurhsu): Better testing can be done here. Right now we just @@ -68,7 +48,7 @@ static bool VerifyNAME(Table* table) { EXPECT_EQ(name->Format(), NAME_FORMAT); EXPECT_EQ(name->NameCount(), NAME_COUNT); fprintf(stderr, "checking name entry: "); - for (int32_t i = 0; i < NAME_COUNT; ++i) { + for (int32_t i = 0; i < NAME_IDS_TEST; ++i) { fprintf(stderr, "%d ", i); EXPECT_EQ(name->PlatformId(i), NAME_IDS[i].platform_id()); EXPECT_EQ(name->EncodingId(i), NAME_IDS[i].encoding_id()); diff --git a/test/verify_os2.cc b/test/verify_os2.cc index 4713e44..4897e87 100644 --- a/test/verify_os2.cc +++ b/test/verify_os2.cc @@ -38,21 +38,21 @@ const int32_t OS2_YSTRIKEOUT_SIZE = 12312; const int32_t OS2_YSTRIKEOUT_POS = -16224; const int32_t OS2_SFAMILY_CLASS = 0; const byte_t OS2_PANOSE[] = { 2, 11, 6, 3, 6, 1, 0, 0, 0, 0 }; -const int64_t OS2_UL_UNICODE_RANGE1 = 0x80000003L; -const int64_t OS2_UL_UNICODE_RANGE2 = 2L; +const int64_t OS2_UL_UNICODE_RANGE1 = 0xE00002FFL; +const int64_t OS2_UL_UNICODE_RANGE2 = 0x520020FBL; const int64_t OS2_UL_UNICODE_RANGE3 = 0L; const int64_t OS2_UL_UNICODE_RANGE4 = 0L; const byte_t OS2_ACH_VEND_ID[] = { 'P', 'f', 'E', 'd' }; -const int32_t OS2_FS_SELECTION = 0; -const int32_t OS2_US_FIRST_CHAR_IDX = 0x20; -const int32_t OS2_US_LAST_CHAR_IDX = 0x20AC; +const int32_t OS2_FS_SELECTION = 0x0040; +const int32_t OS2_US_FIRST_CHAR_IDX = 0x0020; +const int32_t OS2_US_LAST_CHAR_IDX = 0xFFFF; const int32_t OS2_STYPO_ASCENDER = 1597; const int32_t OS2_STYPO_DESCENDER = -451; const int32_t OS2_STYPO_LINE_GAP = 0; -const int32_t OS2_US_WIN_ASCENT = 1993; -const int32_t OS2_US_WIN_DESCENT = 449; -const int64_t OS2_UL_CODE_PAGE_RANGE1 = 1L; -const int64_t OS2_UL_CODE_PAGE_RANGE2 = 0x80D40000L; +const int32_t OS2_US_WIN_ASCENT = 2023; +const int32_t OS2_US_WIN_DESCENT = 648; +const int64_t OS2_UL_CODE_PAGE_RANGE1 = 0x2000019FL; +const int64_t OS2_UL_CODE_PAGE_RANGE2 = 0x00000000L; static bool VerifyOS_2(Table* table) { OS2TablePtr os2 = down_cast(table); -- cgit v1.2.3 From 053885bde4e83c53465ea42257ba056d083afb07 Mon Sep 17 00:00:00 2001 From: "arthurhsu@google.com" Date: Mon, 12 Sep 2011 20:07:59 +0000 Subject: Add mutex git-svn-id: http://sfntly.googlecode.com/svn/trunk/cpp/src@72 672e30a5-4c29-85ac-ac6d-611c735e0a51 --- sfntly/port/lock.cc | 72 ++++++++++++++ sfntly/port/lock.h | 76 +++++++++++++++ sfntly/port/type.h | 6 ++ test/lock_test.cc | 244 ++++++++++++++++++++++++++++++++++++++++++++++++ test/platform_thread.cc | 101 ++++++++++++++++++++ test/platform_thread.h | 75 +++++++++++++++ 6 files changed, 574 insertions(+) create mode 100644 sfntly/port/lock.cc create mode 100644 sfntly/port/lock.h create mode 100644 test/lock_test.cc create mode 100644 test/platform_thread.cc create mode 100644 test/platform_thread.h diff --git a/sfntly/port/lock.cc b/sfntly/port/lock.cc new file mode 100644 index 0000000..6c0c309 --- /dev/null +++ b/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/sfntly/port/lock.h b/sfntly/port/lock.h new file mode 100644 index 0000000..b2e29bf --- /dev/null +++ b/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/sfntly/port/type.h b/sfntly/port/type.h index 458a364..20a5ba8 100644 --- a/sfntly/port/type.h +++ b/sfntly/port/type.h @@ -56,6 +56,12 @@ 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. diff --git a/test/lock_test.cc b/test/lock_test.cc new file mode 100644 index 0000000..b29a4bf --- /dev/null +++ b/test/lock_test.cc @@ -0,0 +1,244 @@ +/* + * 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 "gtest/gtest.h" +#include "sfntly/port/lock.h" +#include "test/platform_thread.h" + +namespace sfntly { + +// Basic test to make sure that Acquire()/Unlock()/Try() don't crash + +class BasicLockTestThread : public PlatformThread::Delegate { + public: + BasicLockTestThread(Lock* lock) : lock_(lock), acquired_(0) {} + + virtual void ThreadMain() { + for (int i = 0; i < 10; i++) { + lock_->Acquire(); + acquired_++; + lock_->Unlock(); + } + for (int i = 0; i < 10; i++) { + lock_->Acquire(); + acquired_++; + PlatformThread::Sleep(rand() % 20); + lock_->Unlock(); + } + for (int i = 0; i < 10; i++) { + if (lock_->Try()) { + acquired_++; + PlatformThread::Sleep(rand() % 20); + lock_->Unlock(); + } + } + } + + int acquired() const { return acquired_; } + + private: + Lock* lock_; + int acquired_; + + NO_COPY_AND_ASSIGN(BasicLockTestThread); +}; + +bool BasicLockTest() { + Lock lock; + BasicLockTestThread thread(&lock); + PlatformThreadHandle handle = kNullThreadHandle; + + EXPECT_TRUE(PlatformThread::Create(&thread, &handle)); + + int acquired = 0; + for (int i = 0; i < 5; i++) { + lock.Acquire(); + acquired++; + lock.Unlock(); + } + for (int i = 0; i < 10; i++) { + lock.Acquire(); + acquired++; + PlatformThread::Sleep(rand() % 20); + lock.Unlock(); + } + for (int i = 0; i < 10; i++) { + if (lock.Try()) { + acquired++; + PlatformThread::Sleep(rand() % 20); + lock.Unlock(); + } + } + for (int i = 0; i < 5; i++) { + lock.Acquire(); + acquired++; + PlatformThread::Sleep(rand() % 20); + lock.Unlock(); + } + + PlatformThread::Join(handle); + + EXPECT_GE(acquired, 20); + EXPECT_GE(thread.acquired(), 20); + + return true; +} + +// Test that Try() works as expected ------------------------------------------- + +class TryLockTestThread : public PlatformThread::Delegate { + public: + TryLockTestThread(Lock* lock) : lock_(lock), got_lock_(false) {} + + virtual void ThreadMain() { + got_lock_ = lock_->Try(); + if (got_lock_) + lock_->Unlock(); + } + + bool got_lock() const { return got_lock_; } + + private: + Lock* lock_; + bool got_lock_; + + NO_COPY_AND_ASSIGN(TryLockTestThread); +}; + +bool TryLockTest() { + Lock lock; + + EXPECT_TRUE(lock.Try()); + // We now have the lock.... + + // This thread will not be able to get the lock. + { + TryLockTestThread thread(&lock); + PlatformThreadHandle handle = kNullThreadHandle; + + EXPECT_TRUE(PlatformThread::Create(&thread, &handle)); + + PlatformThread::Join(handle); + + EXPECT_FALSE(thread.got_lock()); + } + + lock.Unlock(); + + // This thread will.... + { + TryLockTestThread thread(&lock); + PlatformThreadHandle handle = kNullThreadHandle; + + EXPECT_TRUE(PlatformThread::Create(&thread, &handle)); + + PlatformThread::Join(handle); + + EXPECT_TRUE(thread.got_lock()); + // But it released it.... + EXPECT_TRUE(lock.Try()); + } + + lock.Unlock(); + return true; +} + +// Tests that locks actually exclude ------------------------------------------- + +class MutexLockTestThread : public PlatformThread::Delegate { + public: + MutexLockTestThread(Lock* lock, int* value) : lock_(lock), value_(value) {} + + // Static helper which can also be called from the main thread. + static void DoStuff(Lock* lock, int* value) { + for (int i = 0; i < 40; i++) { + lock->Acquire(); + int v = *value; + PlatformThread::Sleep(rand() % 10); + *value = v + 1; + lock->Unlock(); + } + } + + virtual void ThreadMain() { + DoStuff(lock_, value_); + } + + private: + Lock* lock_; + int* value_; + + NO_COPY_AND_ASSIGN(MutexLockTestThread); +}; + +bool MutexTwoThreads() { + Lock lock; + int value = 0; + + MutexLockTestThread thread(&lock, &value); + PlatformThreadHandle handle = kNullThreadHandle; + + EXPECT_TRUE(PlatformThread::Create(&thread, &handle)); + + MutexLockTestThread::DoStuff(&lock, &value); + + PlatformThread::Join(handle); + + EXPECT_EQ(2 * 40, value); + return true; +} + +bool MutexFourThreads() { + Lock lock; + int value = 0; + + MutexLockTestThread thread1(&lock, &value); + MutexLockTestThread thread2(&lock, &value); + MutexLockTestThread thread3(&lock, &value); + PlatformThreadHandle handle1 = kNullThreadHandle; + PlatformThreadHandle handle2 = kNullThreadHandle; + PlatformThreadHandle handle3 = kNullThreadHandle; + + EXPECT_TRUE(PlatformThread::Create(&thread1, &handle1)); + EXPECT_TRUE(PlatformThread::Create(&thread2, &handle2)); + EXPECT_TRUE(PlatformThread::Create(&thread3, &handle3)); + + MutexLockTestThread::DoStuff(&lock, &value); + + PlatformThread::Join(handle1); + PlatformThread::Join(handle2); + PlatformThread::Join(handle3); + + EXPECT_EQ(4 * 40, value); + return true; +} + +} // namespace sfntly + +TEST(LockTest, Basic) { + ASSERT_TRUE(sfntly::BasicLockTest()); +} + +TEST(LockTest, TryLock) { + ASSERT_TRUE(sfntly::TryLockTest()); +} + +TEST(LockTest, Mutex) { + ASSERT_TRUE(sfntly::MutexTwoThreads()); + ASSERT_TRUE(sfntly::MutexFourThreads()); +} diff --git a/test/platform_thread.cc b/test/platform_thread.cc new file mode 100644 index 0000000..6a0b84b --- /dev/null +++ b/test/platform_thread.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 "test/platform_thread.h" + +namespace sfntly { + +#if defined (WIN32) + +DWORD __stdcall ThreadFunc(void* params) { + PlatformThread::Delegate* delegate = + static_cast(params); + delegate->ThreadMain(); + return 0; +} + +// static +bool PlatformThread::Create(Delegate* delegate, + PlatformThreadHandle* thread_handle) { + assert(thread_handle); + *thread_handle = CreateThread(NULL, 0, ThreadFunc, delegate, 0, NULL); + if (!(*thread_handle)) { + return false; + } + + return true; +} + +// static +void PlatformThread::Join(PlatformThreadHandle thread_handle) { + assert(thread_handle); + DWORD result = WaitForSingleObject(thread_handle, INFINITE); + assert(result == WAIT_OBJECT_0); + CloseHandle(thread_handle); +} + +// static +void PlatformThread::Sleep(int32_t duration_ms) { + ::Sleep(duration_ms); +} + +#else + +void* ThreadFunc(void* params) { + PlatformThread::Delegate* delegate = + static_cast(params); + delegate->ThreadMain(); + return NULL; +} + +// static +bool PlatformThread::Create(Delegate* delegate, + PlatformThreadHandle* thread_handle) { + assert(thread_handle); + + bool success = false; + pthread_attr_t attributes; + pthread_attr_init(&attributes); + success = !pthread_create(thread_handle, &attributes, ThreadFunc, delegate); + pthread_attr_destroy(&attributes); + + return success; +} + +// static +void PlatformThread::Join(PlatformThreadHandle thread_handle) { + assert(thread_handle); + pthread_join(thread_handle, NULL); +} + +// static +void PlatformThread::Sleep(int32_t duration_ms) { + struct timespec sleep_time, remaining; + + // Contains the portion of duration_ms >= 1 sec. + sleep_time.tv_sec = duration_ms / 1000; + duration_ms -= sleep_time.tv_sec * 1000; + + // Contains the portion of duration_ms < 1 sec. + sleep_time.tv_nsec = duration_ms * 1000 * 1000; // nanoseconds. + + while (nanosleep(&sleep_time, &remaining) == -1 && errno == EINTR) + sleep_time = remaining; +} + +#endif // WIN32 + +} // namespace sfntly diff --git a/test/platform_thread.h b/test/platform_thread.h new file mode 100644 index 0000000..f236f4c --- /dev/null +++ b/test/platform_thread.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. + */ + +// Simple platform thread implementation used to test our cross-platform locks. +// This is a trimmed down version of Chromium base/threading/platform_thread.h. + +#ifndef SFNTLY_CPP_SRC_TEST_PLATFORM_THREAD_H_ +#define SFNTLY_CPP_SRC_TEST_PLATFORM_THREAD_H_ + +#if defined (WIN32) +#include +#else // Assume pthread +#include +#include +#include +#endif // if defined (WIN32) + +#include "sfntly/port/type.h" + +namespace sfntly { + +#if defined (WIN32) +typedef HANDLE PlatformThreadHandle; +const PlatformThreadHandle kNullThreadHandle = NULL; +#else // Assume pthread +typedef pthread_t PlatformThreadHandle; +const PlatformThreadHandle kNullThreadHandle = 0; +#endif + +class PlatformThread { + public: + class Delegate { + public: + virtual ~Delegate() {} + virtual void ThreadMain() = 0; + }; + + // Sleeps for the specified duration (units are milliseconds). + static void Sleep(int32_t duration_ms); + + // Creates a new thread using default stack size. Upon success, + // |*thread_handle| will be assigned a handle to the newly created thread, + // and |delegate|'s ThreadMain method will be executed on the newly created + // thread. + // NOTE: When you are done with the thread handle, you must call Join to + // release system resources associated with the thread. You must ensure that + // the Delegate object outlives the thread. + static bool Create(Delegate* delegate, PlatformThreadHandle* thread_handle); + + // Joins with a thread created via the Create function. This function blocks + // the caller until the designated thread exits. This will invalidate + // |thread_handle|. + static void Join(PlatformThreadHandle thread_handle); + +private: + PlatformThread() {} + NO_COPY_AND_ASSIGN(PlatformThread); +}; + +} // namespace sfntly + +#endif // SFNTLY_CPP_SRC_TEST_PLATFORM_THREAD_H_ -- cgit v1.2.3 From a2725711c28771ab66670264bdf0caa797ebb22a Mon Sep 17 00:00:00 2001 From: "dfilimon@google.com" Date: Thu, 15 Sep 2011 19:13:49 +0000 Subject: Adding autogenerated tests to the repo. git-svn-id: http://sfntly.googlecode.com/svn/trunk/cpp/src@75 672e30a5-4c29-85ac-ac6d-611c735e0a51 --- test/autogenerated/cmap_basic_test.cc | 104 + test/autogenerated/cmap_test_data.cc | 3435 +++++++++++++++++++++++++++++++++ test/autogenerated/cmap_test_data.h | 353 ++++ 3 files changed, 3892 insertions(+) create mode 100644 test/autogenerated/cmap_basic_test.cc create mode 100644 test/autogenerated/cmap_test_data.cc create mode 100644 test/autogenerated/cmap_test_data.h diff --git a/test/autogenerated/cmap_basic_test.cc b/test/autogenerated/cmap_basic_test.cc new file mode 100644 index 0000000..e12aedd --- /dev/null +++ b/test/autogenerated/cmap_basic_test.cc @@ -0,0 +1,104 @@ +/* + * 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 +#include + +#include "gtest/gtest.h" +#include "sfntly/data/memory_byte_array.h" +#include "sfntly/font.h" +#include "sfntly/font_factory.h" +#include "sfntly/table/core/cmap_table.h" +#include "sfntly/table/core/font_header_table.h" +#include "sfntly/tag.h" +#include "test/autogenerated/cmap_test_data.h" +#include "test/test_font_utils.h" +#include "test/test_utils.h" + +namespace sfntly { + +#if GTEST_HAS_PARAM_TEST + +using ::testing::TestWithParam; +using ::testing::Values; + +class CMapBasicTests : public :: testing::TestWithParam { + public: + CMapBasicTests() {} + virtual void SetUp(); + virtual void TearDown() {} + + void BasicTest(int32_t index); + + Ptr cmap_table_; +}; + +void CMapBasicTests::SetUp() { + Ptr font_factory; + font_factory.Attach(FontFactory::GetInstance()); + FontArray font_array; + std::string font_name("../../"); +#if defined (WIN32) + font_name += "../"; +#endif + font_name += std::string(GetParam().name); + LoadFont(font_name.c_str(), font_factory, &font_array); + ASSERT_FALSE(font_array.empty()); + Ptr font = font_array.at(0); + ASSERT_NE(font, reinterpret_cast(NULL)); + cmap_table_ = down_cast(font->GetTable(Tag::cmap)); + if (!cmap_table_) + fprintf(stderr, "No CMap: %s\n", font_name.c_str()); + ASSERT_NE(cmap_table_, reinterpret_cast(NULL)); +} + +void CMapBasicTests::BasicTest(int32_t index) { + const ProtoCMap* test = &GetParam().cmaps[index]; + Ptr cmap; + cmap.Attach(cmap_table_->GetCMap(test->platform_id, test->encoding_id)); + if (!cmap) { + fprintf(stderr, "Cannot test unsupported CMapFormat%d\n", test->format); + return; + } + ASSERT_EQ(cmap->platform_id(), test->platform_id); + ASSERT_EQ(cmap->encoding_id(), test->encoding_id); + ASSERT_EQ(cmap->format(), test->format); + // There is no length() method for a CMap! + // ASSERT_EQ(cmap->length(), test->length); + for (int32_t i = 0; i < test->num_mappings; ++i) + ASSERT_EQ(cmap->GlyphId(test->chars[i]), test->glyph_ids[i]); +} + +TEST_P(CMapBasicTests, BasicTest) { + for (int32_t i = 0; i < GetParam().num_cmaps; ++i) + BasicTest(i); +} + + +INSTANTIATE_TEST_CASE_P(CMapBasicTests, + CMapBasicTests, + ::testing::ValuesIn(kAllTestCMaps)); + +#else + +TEST(DummyTest, ValueParameterizedTestsAreNotSupportedOnThisPlatform) {} + +#endif // GTEST_HAS_PARAM +} diff --git a/test/autogenerated/cmap_test_data.cc b/test/autogenerated/cmap_test_data.cc new file mode 100644 index 0000000..95ee15c --- /dev/null +++ b/test/autogenerated/cmap_test_data.cc @@ -0,0 +1,3435 @@ +/* + * !!! DO NOT EDIT !!! + * THIS FILE IS GENERATED BY A SCRIPT. + * FOR MORE DETAILS SEE 'README-test_data.txt'. + */ + +/* + * 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 "test/autogenerated/cmap_test_data.h" + +namespace sfntly +{ + TestCMap kTestCousine_BoldItalic_ttf_xml = { + "data/fonts/cousine/Cousine-BoldItalic.ttf", + 2, + { + { + 344, // length + 4, // format + 3, // platform id + 1, // encoding id + 10, // num_mappings + {32, 53, 75, 96, 117, 171, 192, 213, 234, 255} + , // chars + {3, 24, 45, 66, 87, 107, 127, 148, 169, 190} + , // glyph ids + } + , + { + 262, // length + 0, // format + 1, // platform id + 0, // encoding id + 10, // num_mappings + {0, 25, 50, 75, 100, 125, 150, 175, 200, 225} + , // chars + {1, 0, 21, 45, 70, 95, 176, 151, 122, 118} + , // glyph ids + } + } + }; + + TestCMap kTestCousine_Bold_ttf_xml = { + "data/fonts/cousine/Cousine-Bold.ttf", + 2, + { + { + 344, // length + 4, // format + 3, // platform id + 1, // encoding id + 10, // num_mappings + {32, 53, 75, 96, 117, 171, 192, 213, 234, 255} + , // chars + {3, 24, 45, 66, 87, 107, 127, 148, 169, 190} + , // glyph ids + } + , + { + 262, // length + 0, // format + 1, // platform id + 0, // encoding id + 10, // num_mappings + {0, 25, 50, 75, 100, 125, 150, 175, 200, 225} + , // chars + {1, 0, 21, 45, 70, 95, 176, 151, 122, 118} + , // glyph ids + } + } + }; + + TestCMap kTestCousine_Regular_ttf_xml = { + "data/fonts/cousine/Cousine-Regular.ttf", + 2, + { + { + 344, // length + 4, // format + 3, // platform id + 1, // encoding id + 10, // num_mappings + {32, 53, 75, 96, 117, 171, 192, 213, 234, 255} + , // chars + {3, 24, 45, 66, 87, 107, 127, 148, 169, 190} + , // glyph ids + } + , + { + 262, // length + 0, // format + 1, // platform id + 0, // encoding id + 10, // num_mappings + {0, 25, 50, 75, 100, 125, 150, 175, 200, 225} + , // chars + {1, 0, 21, 45, 70, 95, 176, 151, 122, 118} + , // glyph ids + } + } + }; + + TestCMap kTestCousine_Italic_ttf_xml = { + "data/fonts/cousine/Cousine-Italic.ttf", + 2, + { + { + 344, // length + 4, // format + 3, // platform id + 1, // encoding id + 10, // num_mappings + {32, 53, 75, 96, 117, 171, 192, 213, 234, 255} + , // chars + {3, 24, 45, 66, 87, 107, 127, 148, 169, 190} + , // glyph ids + } + , + { + 262, // length + 0, // format + 1, // platform id + 0, // encoding id + 10, // num_mappings + {0, 25, 50, 75, 100, 125, 150, 175, 200, 225} + , // chars + {1, 0, 21, 45, 70, 95, 176, 151, 122, 118} + , // glyph ids + } + } + }; + + TestCMap kTestCedarville_Cursive_ttf_xml = { + "data/fonts/cedarvillecursive/Cedarville-Cursive.ttf", + 1, + { + { + 240, // length + 4, // format + 3, // platform id + 1, // encoding id + 10, // num_mappings + {32, 67, 102, 170, 205, 240, 278, 317, 355, 710} + , // chars + {3, 38, 73, 108, 143, 178, 213, 248, 283, 318} + , // glyph ids + } + } + }; + + TestCMap kTestDancingScript_Bold_ttf_xml = { + "data/fonts/dancingscript/DancingScript-Bold.ttf", + 1, + { + { + 216, // length + 4, // format + 3, // platform id + 1, // encoding id + 10, // num_mappings + {32, 54, 76, 98, 120, 177, 199, 221, 243, 710} + , // chars + {3, 25, 47, 69, 91, 113, 135, 157, 179, 201} + , // glyph ids + } + } + }; + + TestCMap kTestDancingScript_Regular_ttf_xml = { + "data/fonts/dancingscript/DancingScript-Regular.ttf", + 1, + { + { + 216, // length + 4, // format + 3, // platform id + 1, // encoding id + 10, // num_mappings + {32, 54, 76, 98, 120, 177, 199, 221, 243, 710} + , // chars + {3, 25, 47, 69, 91, 113, 135, 157, 179, 201} + , // glyph ids + } + } + }; + + TestCMap kTestDamion_Regular_ttf_xml = { + "data/fonts/damion/Damion-Regular.ttf", + 1, + { + { + 314, // length + 4, // format + 3, // platform id + 1, // encoding id + 10, // num_mappings + {32, 58, 84, 110, 169, 197, 223, 249, 520, 733} + , // chars + {3, 29, 55, 81, 106, 132, 158, 184, 210, 236} + , // glyph ids + } + } + }; + + TestCMap kTestAnnieUseYourTelescope_ttf_xml = { + "data/fonts/annieuseyourtelescope/AnnieUseYourTelescope.ttf", + 1, + { + { + 248, // length + 4, // format + 3, // platform id + 1, // encoding id + 10, // num_mappings + {32, 67, 102, 170, 205, 240, 275, 317, 353, 710} + , // chars + {3, 38, 73, 108, 143, 178, 213, 248, 283, 318} + , // glyph ids + } + } + }; + + TestCMap kTestDeliusSwashCaps_Regular_ttf_xml = { + "data/fonts/deliusswashcaps/DeliusSwashCaps-Regular.ttf", + 1, + { + { + 288, // length + 4, // format + 3, // platform id + 1, // encoding id + 10, // num_mappings + {32, 58, 84, 110, 169, 195, 221, 247, 323, 8224} + , // chars + {3, 29, 55, 81, 107, 133, 159, 185, 211, 237} + , // glyph ids + } + } + }; + + TestCMap kTestDelius_Regular_ttf_xml = { + "data/fonts/delius/Delius-Regular.ttf", + 1, + { + { + 288, // length + 4, // format + 3, // platform id + 1, // encoding id + 10, // num_mappings + {32, 58, 84, 110, 169, 195, 221, 247, 323, 8224} + , // chars + {3, 29, 55, 81, 107, 133, 159, 185, 211, 237} + , // glyph ids + } + } + }; + + TestCMap kTestCoveredByYourGrace_ttf_xml = { + "data/fonts/coveredbyyourgrace/CoveredByYourGrace.ttf", + 1, + { + { + 478, // length + 4, // format + 3, // platform id + 1, // encoding id + 10, // num_mappings + {32, 66, 100, 167, 201, 235, 269, 311, 350, 509} + , // chars + {3, 37, 71, 104, 138, 172, 206, 240, 274, 308} + , // glyph ids + } + } + }; + + TestCMap kTestEBGaramond_Regular_ttf_xml = { + "data/fonts/ebgaramond/EBGaramond-Regular.ttf", + 1, + { + { + 1048, // length + 4, // format + 3, // platform id + 1, // encoding id + 10, // num_mappings + {32, 217, 369, 523, 678, 1032, 7470, 7794, 8137, 8566} + , // chars + {3, 155, 307, 459, 611, 763, 915, 1067, 1219, 1371} + , // glyph ids + } + } + }; + + TestCMap kTestCabinSketch_Bold_ttf_xml = { + "data/fonts/cabinsketch/CabinSketch-Bold.ttf", + 2, + { + { + 230, // length + 4, // format + 3, // platform id + 1, // encoding id + 10, // num_mappings + {32, 54, 76, 98, 120, 176, 198, 220, 242, 402} + , // chars + {3, 25, 47, 69, 91, 112, 134, 156, 178, 200} + , // glyph ids + } + , + { + 262, // length + 0, // format + 1, // platform id + 0, // encoding id + 10, // num_mappings + {0, 25, 50, 75, 100, 125, 150, 175, 200, 225} + , // chars + {1, 0, 21, 46, 71, 96, 177, 152, 123, 119} + , // glyph ids + } + } + }; + + TestCMap kTestAllan_Bold_ttf_xml = { + "data/fonts/allan/Allan-Bold.ttf", + 2, + { + { + 232, // length + 4, // format + 3, // platform id + 1, // encoding id + 10, // num_mappings + {32, 54, 76, 98, 120, 176, 198, 220, 242, 382} + , // chars + {3, 25, 47, 69, 91, 113, 135, 157, 179, 201} + , // glyph ids + } + , + { + 262, // length + 0, // format + 1, // platform id + 0, // encoding id + 10, // num_mappings + {0, 25, 50, 75, 100, 125, 150, 175, 200, 225} + , // chars + {1, 0, 21, 46, 71, 96, 178, 153, 124, 120} + , // glyph ids + } + } + }; + + TestCMap kTestCoda_Caption_Heavy_ttf_xml = { + "data/fonts/coda/Coda-Caption-Heavy.ttf", + 1, + { + { + 256, // length + 4, // format + 3, // platform id + 1, // encoding id + 10, // num_mappings + {32, 72, 112, 185, 225, 265, 305, 345, 452, 526} + , // chars + {3, 43, 83, 123, 163, 203, 243, 283, 323, 363} + , // glyph ids + } + } + }; + + TestCMap kTestCoda_Heavy_ttf_xml = { + "data/fonts/coda/Coda-Heavy.ttf", + 1, + { + { + 240, // length + 4, // format + 3, // platform id + 1, // encoding id + 10, // num_mappings + {32, 64, 96, 162, 195, 227, 259, 301, 336, 378} + , // chars + {3, 35, 67, 99, 131, 163, 195, 227, 259, 291} + , // glyph ids + } + } + }; + + TestCMap kTestForum_Regular_ttf_xml = { + "data/fonts/forum/Forum-Regular.ttf", + 2, + { + { + 1262, // length + 4, // format + 3, // platform id + 1, // encoding id + 10, // num_mappings + {32, 89, 183, 245, 302, 361, 1029, 1086, 1187, 1265} + , // chars + {3, 60, 163, 156, 235, 565, 365, 426, 479, 531} + , // glyph ids + } + , + { + 262, // length + 0, // format + 1, // platform id + 0, // encoding id + 10, // num_mappings + {0, 25, 50, 75, 100, 125, 150, 175, 200, 225} + , // chars + {1, 0, 193, 31, 97, 83, 112, 142, 19, 66} + , // glyph ids + } + } + }; + + TestCMap kTestAlike_Regular_ttf_xml = { + "data/fonts/alike/Alike-Regular.ttf", + 2, + { + { + 152, // length + 4, // format + 3, // platform id + 1, // encoding id + 10, // num_mappings + {32, 53, 74, 95, 116, 170, 191, 212, 233, 254} + , // chars + {3, 24, 45, 66, 87, 108, 129, 150, 171, 192} + , // glyph ids + } + , + { + 262, // length + 0, // format + 1, // platform id + 0, // encoding id + 10, // num_mappings + {0, 25, 50, 75, 100, 125, 150, 175, 200, 225} + , // chars + {1, 0, 21, 46, 71, 96, 179, 154, 125, 121} + , // glyph ids + } + } + }; + + TestCMap kTestCorben_Bold_ttf_xml = { + "data/fonts/corben/Corben-Bold.ttf", + 1, + { + { + 344, // length + 4, // format + 3, // platform id + 1, // encoding id + 10, // num_mappings + {32, 70, 108, 179, 217, 255, 294, 339, 377, 7779} + , // chars + {3, 41, 79, 117, 155, 193, 231, 269, 307, 344} + , // glyph ids + } + } + }; + + TestCMap kTestCaudex_Regular_ttf_xml = { + "data/fonts/caudex/Caudex-Regular.ttf", + 1, + { + { + 3272, // length + 4, // format + 3, // platform id + 1, // encoding id + 10, // num_mappings + {32, 266, 537, 928, 7684, 8052, 8595, 57446, 59571, 61226} + , // chars + {3, 204, 405, 606, 807, 1008, 1209, 1410, 1611, 1812} + , // glyph ids + } + } + }; + + TestCMap kTestCaudex_BoldItalic_ttf_xml = { + "data/fonts/caudex/Caudex-BoldItalic.ttf", + 1, + { + { + 3272, // length + 4, // format + 3, // platform id + 1, // encoding id + 10, // num_mappings + {32, 266, 537, 928, 7684, 8052, 8595, 57446, 59571, 61226} + , // chars + {3, 204, 405, 606, 807, 1008, 1209, 1410, 1611, 1812} + , // glyph ids + } + } + }; + + TestCMap kTestCaudex_Italic_ttf_xml = { + "data/fonts/caudex/Caudex-Italic.ttf", + 1, + { + { + 3272, // length + 4, // format + 3, // platform id + 1, // encoding id + 10, // num_mappings + {32, 266, 537, 928, 7684, 8052, 8595, 57446, 59571, 61226} + , // chars + {3, 204, 405, 606, 807, 1008, 1209, 1410, 1611, 1812} + , // glyph ids + } + } + }; + + TestCMap kTestCaudex_Bold_ttf_xml = { + "data/fonts/caudex/Caudex-Bold.ttf", + 1, + { + { + 3272, // length + 4, // format + 3, // platform id + 1, // encoding id + 10, // num_mappings + {32, 266, 537, 928, 7684, 8052, 8595, 57446, 59571, 61226} + , // chars + {3, 204, 405, 606, 807, 1008, 1209, 1410, 1611, 1812} + , // glyph ids + } + } + }; + + TestCMap kTestCabin_MediumItalic_ttf_xml = { + "data/fonts/cabin/Cabin-MediumItalic.ttf", + 1, + { + { + 232, // length + 4, // format + 3, // platform id + 1, // encoding id + 10, // num_mappings + {32, 55, 78, 101, 124, 181, 204, 227, 250, 8217} + , // chars + {1, 24, 47, 70, 93, 116, 139, 162, 185, 208} + , // glyph ids + } + } + }; + + TestCMap kTestCabin_SemiBold_ttf_xml = { + "data/fonts/cabin/Cabin-SemiBold.ttf", + 1, + { + { + 224, // length + 4, // format + 3, // platform id + 1, // encoding id + 10, // num_mappings + {32, 55, 78, 101, 124, 181, 204, 227, 250, 8217} + , // chars + {1, 24, 47, 70, 93, 116, 139, 162, 185, 208} + , // glyph ids + } + } + }; + + TestCMap kTestCabin_SemiBoldItalic_ttf_xml = { + "data/fonts/cabin/Cabin-SemiBoldItalic.ttf", + 1, + { + { + 224, // length + 4, // format + 3, // platform id + 1, // encoding id + 10, // num_mappings + {32, 55, 78, 101, 124, 181, 204, 227, 250, 8217} + , // chars + {1, 24, 47, 70, 93, 116, 139, 162, 185, 208} + , // glyph ids + } + } + }; + + TestCMap kTestCabin_BoldItalic_ttf_xml = { + "data/fonts/cabin/Cabin-BoldItalic.ttf", + 1, + { + { + 224, // length + 4, // format + 3, // platform id + 1, // encoding id + 10, // num_mappings + {32, 55, 78, 101, 124, 181, 204, 227, 250, 8217} + , // chars + {1, 24, 47, 70, 93, 116, 139, 162, 185, 208} + , // glyph ids + } + } + }; + + TestCMap kTestCabin_Medium_ttf_xml = { + "data/fonts/cabin/Cabin-Medium.ttf", + 1, + { + { + 224, // length + 4, // format + 3, // platform id + 1, // encoding id + 10, // num_mappings + {32, 55, 78, 101, 124, 181, 204, 227, 250, 8217} + , // chars + {1, 24, 47, 70, 93, 116, 139, 162, 185, 208} + , // glyph ids + } + } + }; + + TestCMap kTestCabin_Italic_ttf_xml = { + "data/fonts/cabin/Cabin-Italic.ttf", + 1, + { + { + 224, // length + 4, // format + 3, // platform id + 1, // encoding id + 10, // num_mappings + {32, 55, 78, 101, 124, 181, 204, 227, 250, 8217} + , // chars + {1, 24, 47, 70, 93, 116, 139, 162, 185, 208} + , // glyph ids + } + } + }; + + TestCMap kTestCabin_Bold_ttf_xml = { + "data/fonts/cabin/Cabin-Bold.ttf", + 1, + { + { + 224, // length + 4, // format + 3, // platform id + 1, // encoding id + 10, // num_mappings + {32, 55, 78, 101, 124, 181, 204, 227, 250, 8217} + , // chars + {1, 24, 47, 70, 93, 116, 139, 162, 185, 208} + , // glyph ids + } + } + }; + + TestCMap kTestCabin_Regular_ttf_xml = { + "data/fonts/cabin/Cabin-Regular.ttf", + 1, + { + { + 224, // length + 4, // format + 3, // platform id + 1, // encoding id + 10, // num_mappings + {32, 55, 78, 101, 124, 181, 204, 227, 250, 8217} + , // chars + {1, 24, 47, 70, 93, 116, 139, 162, 185, 208} + , // glyph ids + } + } + }; + + TestCMap kTestDawningofaNewDay_ttf_xml = { + "data/fonts/dawningofanewday/DawningofaNewDay.ttf", + 1, + { + { + 280, // length + 4, // format + 3, // platform id + 1, // encoding id + 10, // num_mappings + {32, 58, 84, 110, 169, 196, 222, 248, 336, 711} + , // chars + {3, 29, 55, 81, 107, 133, 159, 185, 211, 237} + , // glyph ids + } + } + }; + + TestCMap kTestDangrek_ttf_xml = { + "data/fonts/dangrek/Dangrek.ttf", + 2, + { + { + 96, // length + 4, // format + 3, // platform id + 1, // encoding id + 10, // num_mappings + {32, 45, 58, 6019, 6032, 6045, 6058, 6073, 6086, 6099} + , // chars + {3, 16, 29, 39, 52, 65, 78, 91, 104, 117} + , // glyph ids + } + , + { + 262, // length + 0, // format + 1, // platform id + 0, // encoding id + 10, // num_mappings + {0, 25, 50, 75, 100, 125, 150, 175, 200, 225} + , // chars + {1, 0, 21, 0, 0, 0, 0, 0, 0, 0} + , // glyph ids + } + } + }; + + TestCMap kTestBlackOpsOne_ttf_xml = { + "data/fonts/blackopsone/BlackOpsOne.ttf", + 1, + { + { + 256, // length + 4, // format + 3, // platform id + 1, // encoding id + 10, // num_mappings + {1, 39, 65, 91, 117, 176, 202, 228, 254, 567} + , // chars + {3, 29, 55, 81, 107, 133, 159, 185, 211, 237} + , // glyph ids + } + } + }; + + TestCMap kTestFrancoisOne_ttf_xml = { + "data/fonts/francoisone/FrancoisOne.ttf", + 1, + { + { + 456, // length + 4, // format + 3, // platform id + 1, // encoding id + 10, // num_mappings + {2, 72, 115, 192, 235, 278, 322, 365, 515, 7779} + , // chars + {3, 46, 89, 132, 175, 218, 261, 304, 347, 390} + , // glyph ids + } + } + }; + + TestCMap kTestBowlbyOne_ttf_xml = { + "data/fonts/bowlbyone/BowlbyOne.ttf", + 1, + { + { + 368, // length + 4, // format + 3, // platform id + 1, // encoding id + 10, // num_mappings + {32, 60, 88, 116, 178, 206, 234, 353, 535, 8226} + , // chars + {3, 31, 59, 87, 115, 143, 171, 199, 227, 255} + , // glyph ids + } + } + }; + + TestCMap kTestBowlbyOneSC_ttf_xml = { + "data/fonts/bowlbyone/BowlbyOneSC.ttf", + 1, + { + { + 384, // length + 4, // format + 3, // platform id + 1, // encoding id + 10, // num_mappings + {32, 62, 92, 122, 185, 215, 245, 520, 806, 8240} + , // chars + {3, 33, 63, 93, 123, 153, 183, 213, 243, 273} + , // glyph ids + } + } + }; + + TestCMap kTestCalligraffiti_ttf_xml = { + "data/fonts/calligraffiti/Calligraffiti.ttf", + 2, + { + { + 412, // length + 4, // format + 3, // platform id + 1, // encoding id + 10, // num_mappings + {32, 54, 76, 98, 120, 175, 197, 219, 241, 376} + , // chars + {21, 43, 65, 87, 109, 217, 117, 212, 138, 188} + , // glyph ids + } + , + { + 262, // length + 0, // format + 1, // platform id + 0, // encoding id + 10, // num_mappings + {0, 25, 50, 75, 100, 125, 150, 175, 200, 225} + , // chars + {0, 0, 39, 64, 89, 114, 138, 160, 172, 195} + , // glyph ids + } + } + }; + + TestCMap kTestBangers_ttf_xml = { + "data/fonts/bangers/Bangers.ttf", + 2, + { + { + 296, // length + 4, // format + 3, // platform id + 1, // encoding id + 10, // num_mappings + {9, 46, 70, 94, 118, 174, 200, 224, 248, 8212} + , // chars + {3, 27, 51, 75, 99, 123, 147, 171, 195, 219} + , // glyph ids + } + , + { + 262, // length + 0, // format + 1, // platform id + 0, // encoding id + 10, // num_mappings + {0, 25, 50, 75, 100, 125, 150, 175, 200, 225} + , // chars + {1, 0, 31, 56, 81, 106, 188, 163, 134, 130} + , // glyph ids + } + } + }; + + TestCMap kTestAstloch_Regular_ttf_xml = { + "data/fonts/astloch/Astloch-Regular.ttf", + 2, + { + { + 128, // length + 4, // format + 3, // platform id + 1, // encoding id + 10, // num_mappings + {32, 52, 72, 92, 112, 165, 185, 205, 225, 245} + , // chars + {3, 23, 43, 63, 83, 103, 123, 143, 163, 183} + , // glyph ids + } + , + { + 262, // length + 0, // format + 1, // platform id + 0, // encoding id + 10, // num_mappings + {0, 25, 50, 75, 100, 125, 150, 175, 200, 225} + , // chars + {1, 0, 21, 46, 71, 96, 179, 154, 125, 121} + , // glyph ids + } + } + }; + + TestCMap kTestAstloch_Bold_ttf_xml = { + "data/fonts/astloch/Astloch-Bold.ttf", + 2, + { + { + 128, // length + 4, // format + 3, // platform id + 1, // encoding id + 10, // num_mappings + {32, 52, 72, 92, 112, 165, 185, 205, 225, 245} + , // chars + {3, 23, 43, 63, 83, 103, 123, 143, 163, 183} + , // glyph ids + } + , + { + 262, // length + 0, // format + 1, // platform id + 0, // encoding id + 10, // num_mappings + {0, 25, 50, 75, 100, 125, 150, 175, 200, 225} + , // chars + {1, 0, 21, 46, 71, 96, 179, 154, 125, 121} + , // glyph ids + } + } + }; + + TestCMap kTestAngkor_ttf_xml = { + "data/fonts/angkor/Angkor.ttf", + 2, + { + { + 88, // length + 4, // format + 3, // platform id + 1, // encoding id + 10, // num_mappings + {32, 45, 58, 6019, 6032, 6045, 6058, 6073, 6086, 6099} + , // chars + {3, 16, 29, 39, 52, 65, 78, 91, 104, 117} + , // glyph ids + } + , + { + 262, // length + 0, // format + 1, // platform id + 0, // encoding id + 10, // num_mappings + {0, 25, 50, 75, 100, 125, 150, 175, 200, 225} + , // chars + {1, 0, 21, 0, 0, 0, 0, 0, 0, 0} + , // glyph ids + } + } + }; + + TestCMap kTestAbrilFatface_Regular_ttf_xml = { + "data/fonts/abrilfatface/AbrilFatface-Regular.ttf", + 1, + { + { + 360, // length + 4, // format + 3, // platform id + 1, // encoding id + 10, // num_mappings + {32, 71, 110, 182, 221, 260, 299, 338, 377, 7922} + , // chars + {3, 42, 81, 120, 159, 198, 237, 276, 315, 354} + , // glyph ids + } + } + }; + + TestCMap kTestCantarell_BoldOblique_ttf_xml = { + "data/fonts/cantarell/Cantarell-BoldOblique.ttf", + 1, + { + { + 264, // length + 4, // format + 3, // platform id + 1, // encoding id + 10, // num_mappings + {32, 70, 108, 179, 217, 255, 293, 331, 369, 7767} + , // chars + {3, 41, 79, 117, 155, 193, 231, 269, 307, 345} + , // glyph ids + } + } + }; + + TestCMap kTestCantarell_Oblique_ttf_xml = { + "data/fonts/cantarell/Cantarell-Oblique.ttf", + 1, + { + { + 264, // length + 4, // format + 3, // platform id + 1, // encoding id + 10, // num_mappings + {32, 70, 108, 179, 217, 255, 293, 331, 369, 7767} + , // chars + {3, 41, 79, 117, 155, 193, 231, 269, 307, 345} + , // glyph ids + } + } + }; + + TestCMap kTestCantarell_Bold_ttf_xml = { + "data/fonts/cantarell/Cantarell-Bold.ttf", + 1, + { + { + 264, // length + 4, // format + 3, // platform id + 1, // encoding id + 10, // num_mappings + {32, 70, 108, 179, 217, 255, 293, 331, 369, 7767} + , // chars + {3, 41, 79, 117, 155, 193, 231, 269, 307, 345} + , // glyph ids + } + } + }; + + TestCMap kTestCantarell_Regular_ttf_xml = { + "data/fonts/cantarell/Cantarell-Regular.ttf", + 1, + { + { + 264, // length + 4, // format + 3, // platform id + 1, // encoding id + 10, // num_mappings + {32, 70, 108, 179, 217, 255, 293, 331, 369, 7767} + , // chars + {3, 41, 79, 117, 155, 193, 231, 269, 307, 345} + , // glyph ids + } + } + }; + + TestCMap kTestArvo_Bold_ttf_xml = { + "data/fonts/arvo/Arvo-Bold.ttf", + 1, + { + { + 504, // length + 4, // format + 3, // platform id + 1, // encoding id + 10, // num_mappings + {32, 54, 76, 98, 120, 177, 199, 221, 243, 711} + , // chars + {28, 65, 13, 31, 53, 99, 166, 181, 200, 123} + , // glyph ids + } + } + }; + + TestCMap kTestArvo_Italic_ttf_xml = { + "data/fonts/arvo/Arvo-Italic.ttf", + 1, + { + { + 522, // length + 4, // format + 3, // platform id + 1, // encoding id + 10, // num_mappings + {32, 54, 76, 98, 120, 176, 198, 220, 242, 729} + , // chars + {28, 65, 13, 31, 53, 124, 131, 180, 199, 129} + , // glyph ids + } + } + }; + + TestCMap kTestArvo_BoldItalic_ttf_xml = { + "data/fonts/arvo/Arvo-BoldItalic.ttf", + 1, + { + { + 522, // length + 4, // format + 3, // platform id + 1, // encoding id + 10, // num_mappings + {32, 54, 76, 98, 120, 176, 198, 220, 242, 710} + , // chars + {28, 65, 13, 31, 53, 124, 131, 180, 199, 116} + , // glyph ids + } + } + }; + + TestCMap kTestArvo_Regular_ttf_xml = { + "data/fonts/arvo/Arvo-Regular.ttf", + 1, + { + { + 542, // length + 4, // format + 3, // platform id + 1, // encoding id + 10, // num_mappings + {32, 54, 76, 98, 120, 176, 198, 220, 242, 710} + , // chars + {28, 65, 13, 31, 53, 124, 131, 167, 206, 116} + , // glyph ids + } + } + }; + + TestCMap kTestChewy_ttf_xml = { + "data/fonts/chewy/Chewy.ttf", + 2, + { + { + 420, // length + 4, // format + 3, // platform id + 1, // encoding id + 10, // num_mappings + {32, 54, 76, 98, 120, 175, 197, 219, 241, 376} + , // chars + {21, 43, 65, 87, 109, 217, 117, 212, 138, 188} + , // glyph ids + } + , + { + 262, // length + 0, // format + 1, // platform id + 0, // encoding id + 10, // num_mappings + {0, 25, 50, 75, 100, 125, 150, 175, 200, 225} + , // chars + {0, 0, 39, 64, 89, 114, 138, 161, 172, 195} + , // glyph ids + } + } + }; + + TestCMap kTestBigshotOne_ttf_xml = { + "data/fonts/bigshotone/BigshotOne.ttf", + 2, + { + { + 176, // length + 4, // format + 3, // platform id + 1, // encoding id + 10, // num_mappings + {32, 53, 74, 95, 116, 170, 191, 212, 233, 254} + , // chars + {3, 24, 45, 66, 87, 108, 129, 150, 171, 192} + , // glyph ids + } + , + { + 262, // length + 0, // format + 1, // platform id + 0, // encoding id + 10, // num_mappings + {0, 25, 50, 75, 100, 125, 150, 175, 200, 225} + , // chars + {1, 0, 21, 46, 71, 96, 179, 154, 125, 121} + , // glyph ids + } + } + }; + + TestCMap kTestChenla_ttf_xml = { + "data/fonts/chenla/Chenla.ttf", + 2, + { + { + 88, // length + 4, // format + 3, // platform id + 1, // encoding id + 10, // num_mappings + {32, 45, 58, 6019, 6032, 6045, 6058, 6073, 6086, 6099} + , // chars + {3, 16, 29, 39, 52, 65, 78, 91, 104, 117} + , // glyph ids + } + , + { + 262, // length + 0, // format + 1, // platform id + 0, // encoding id + 10, // num_mappings + {0, 25, 50, 75, 100, 125, 150, 175, 200, 225} + , // chars + {1, 0, 21, 0, 0, 0, 0, 0, 0, 0} + , // glyph ids + } + } + }; + + TestCMap kTestBayon_ttf_xml = { + "data/fonts/bayon/Bayon.ttf", + 2, + { + { + 88, // length + 4, // format + 3, // platform id + 1, // encoding id + 10, // num_mappings + {32, 45, 58, 6019, 6032, 6045, 6058, 6073, 6086, 6099} + , // chars + {3, 16, 29, 39, 52, 65, 78, 91, 104, 117} + , // glyph ids + } + , + { + 262, // length + 0, // format + 1, // platform id + 0, // encoding id + 10, // num_mappings + {0, 25, 50, 75, 100, 125, 150, 175, 200, 225} + , // chars + {1, 0, 21, 0, 0, 0, 0, 0, 0, 0} + , // glyph ids + } + } + }; + + TestCMap kTestCoustard_Black_ttf_xml = { + "data/fonts/coustard/Coustard-Black.ttf", + 1, + { + { + 272, // length + 4, // format + 3, // platform id + 1, // encoding id + 10, // num_mappings + {32, 64, 96, 161, 193, 225, 257, 299, 336, 381} + , // chars + {3, 35, 67, 99, 131, 163, 195, 227, 259, 291} + , // glyph ids + } + } + }; + + TestCMap kTestCoustard_Regular_ttf_xml = { + "data/fonts/coustard/Coustard-Regular.ttf", + 1, + { + { + 884, // length + 4, // format + 3, // platform id + 1, // encoding id + 10, // num_mappings + {32, 64, 96, 161, 193, 225, 257, 299, 336, 381} + , // chars + {3, 35, 120, 98, 166, 195, 242, 246, 285, 194} + , // glyph ids + } + } + }; + + TestCMap kTestAmaticSC_Bold_ttf_xml = { + "data/fonts/amaticsc/AmaticSC-Bold.ttf", + 1, + { + { + 248, // length + 4, // format + 3, // platform id + 1, // encoding id + 10, // num_mappings + {32, 70, 108, 182, 221, 259, 297, 336, 376, 531} + , // chars + {3, 41, 79, 117, 155, 193, 231, 269, 307, 345} + , // glyph ids + } + } + }; + + TestCMap kTestAmaticSC_Regular_ttf_xml = { + "data/fonts/amaticsc/AmaticSC-Regular.ttf", + 1, + { + { + 240, // length + 4, // format + 3, // platform id + 1, // encoding id + 10, // num_mappings + {32, 69, 106, 178, 216, 253, 290, 327, 365, 498} + , // chars + {3, 40, 77, 114, 151, 188, 225, 262, 299, 336} + , // glyph ids + } + } + }; + + TestCMap kTestComfortaa_Light_ttf_xml = { + "data/fonts/comfortaa/Comfortaa-Light.ttf", + 1, + { + { + 620, // length + 4, // format + 3, // platform id + 1, // encoding id + 10, // num_mappings + {32, 92, 185, 245, 305, 365, 925, 1036, 1097, 8217} + , // chars + {3, 63, 121, 181, 192, 345, 394, 482, 542, 206} + , // glyph ids + } + } + }; + + TestCMap kTestComfortaa_Bold_ttf_xml = { + "data/fonts/comfortaa/Comfortaa-Bold.ttf", + 1, + { + { + 620, // length + 4, // format + 3, // platform id + 1, // encoding id + 10, // num_mappings + {32, 92, 185, 245, 305, 365, 925, 1036, 1097, 8217} + , // chars + {3, 63, 121, 181, 192, 345, 394, 482, 542, 206} + , // glyph ids + } + } + }; + + TestCMap kTestComfortaa_Regular_ttf_xml = { + "data/fonts/comfortaa/Comfortaa-Regular.ttf", + 1, + { + { + 620, // length + 4, // format + 3, // platform id + 1, // encoding id + 10, // num_mappings + {32, 92, 185, 245, 305, 365, 925, 1036, 1097, 8217} + , // chars + {3, 63, 121, 181, 192, 345, 394, 482, 542, 206} + , // glyph ids + } + } + }; + + TestCMap kTestExpletusSans_Bold_ttf_xml = { + "data/fonts/expletussans/ExpletusSans-Bold.ttf", + 2, + { + { + 366, // length + 4, // format + 3, // platform id + 1, // encoding id + 10, // num_mappings + {32, 53, 74, 95, 116, 171, 192, 213, 234, 255} + , // chars + {9, 60, 33, 86, 11, 127, 148, 169, 190, 211} + , // glyph ids + } + , + { + 262, // length + 0, // format + 1, // platform id + 0, // encoding id + 10, // num_mappings + {0, 25, 50, 75, 100, 125, 150, 175, 200, 225} + , // chars + {0, 0, 57, 34, 3, 90, 197, 172, 143, 139} + , // glyph ids + } + } + }; + + TestCMap kTestExpletusSans_MediumItalic_ttf_xml = { + "data/fonts/expletussans/ExpletusSans-MediumItalic.ttf", + 2, + { + { + 578, // length + 4, // format + 3, // platform id + 1, // encoding id + 10, // num_mappings + {32, 53, 74, 95, 116, 171, 192, 213, 234, 255} + , // chars + {7, 140, 41, 29, 66, 182, 110, 112, 87, 166} + , // glyph ids + } + , + { + 262, // length + 0, // format + 1, // platform id + 0, // encoding id + 10, // num_mappings + {0, 25, 50, 75, 100, 125, 150, 175, 200, 225} + , // chars + {0, 0, 137, 42, 62, 58, 93, 164, 181, 157} + , // glyph ids + } + } + }; + + TestCMap kTestExpletusSans_Medium_ttf_xml = { + "data/fonts/expletussans/ExpletusSans-Medium.ttf", + 2, + { + { + 578, // length + 4, // format + 3, // platform id + 1, // encoding id + 10, // num_mappings + {32, 53, 74, 95, 116, 171, 192, 213, 234, 255} + , // chars + {7, 146, 41, 29, 66, 188, 116, 118, 93, 172} + , // glyph ids + } + , + { + 262, // length + 0, // format + 1, // platform id + 0, // encoding id + 10, // num_mappings + {0, 25, 50, 75, 100, 125, 150, 175, 200, 225} + , // chars + {0, 0, 143, 42, 62, 58, 99, 170, 187, 163} + , // glyph ids + } + } + }; + + TestCMap kTestExpletusSans_SemiBold_ttf_xml = { + "data/fonts/expletussans/ExpletusSans-SemiBold.ttf", + 2, + { + { + 578, // length + 4, // format + 3, // platform id + 1, // encoding id + 10, // num_mappings + {32, 53, 74, 95, 116, 171, 192, 213, 234, 255} + , // chars + {7, 146, 41, 29, 66, 188, 116, 118, 93, 172} + , // glyph ids + } + , + { + 262, // length + 0, // format + 1, // platform id + 0, // encoding id + 10, // num_mappings + {0, 25, 50, 75, 100, 125, 150, 175, 200, 225} + , // chars + {0, 0, 143, 42, 62, 58, 99, 170, 187, 163} + , // glyph ids + } + } + }; + + TestCMap kTestExpletusSans_Regular_ttf_xml = { + "data/fonts/expletussans/ExpletusSans-Regular.ttf", + 2, + { + { + 570, // length + 4, // format + 3, // platform id + 1, // encoding id + 10, // num_mappings + {32, 53, 74, 95, 116, 171, 192, 213, 234, 255} + , // chars + {7, 146, 41, 29, 66, 188, 116, 118, 93, 172} + , // glyph ids + } + , + { + 262, // length + 0, // format + 1, // platform id + 0, // encoding id + 10, // num_mappings + {0, 25, 50, 75, 100, 125, 150, 175, 200, 225} + , // chars + {0, 0, 143, 42, 62, 58, 99, 170, 187, 163} + , // glyph ids + } + } + }; + + TestCMap kTestExpletusSans_Italic_ttf_xml = { + "data/fonts/expletussans/ExpletusSans-Italic.ttf", + 2, + { + { + 570, // length + 4, // format + 3, // platform id + 1, // encoding id + 10, // num_mappings + {32, 53, 74, 95, 116, 171, 192, 213, 234, 255} + , // chars + {7, 140, 41, 29, 66, 182, 110, 112, 87, 166} + , // glyph ids + } + , + { + 262, // length + 0, // format + 1, // platform id + 0, // encoding id + 10, // num_mappings + {0, 25, 50, 75, 100, 125, 150, 175, 200, 225} + , // chars + {0, 0, 137, 42, 62, 58, 93, 164, 181, 157} + , // glyph ids + } + } + }; + + TestCMap kTestExpletusSans_SemiBoldItalic_ttf_xml = { + "data/fonts/expletussans/ExpletusSans-SemiBoldItalic.ttf", + 2, + { + { + 578, // length + 4, // format + 3, // platform id + 1, // encoding id + 10, // num_mappings + {32, 53, 74, 95, 116, 171, 192, 213, 234, 255} + , // chars + {7, 139, 41, 29, 65, 181, 109, 111, 86, 165} + , // glyph ids + } + , + { + 262, // length + 0, // format + 1, // platform id + 0, // encoding id + 10, // num_mappings + {0, 25, 50, 75, 100, 125, 150, 175, 200, 225} + , // chars + {0, 0, 136, 42, 62, 58, 92, 163, 180, 156} + , // glyph ids + } + } + }; + + TestCMap kTestExpletusSans_BoldItalic_ttf_xml = { + "data/fonts/expletussans/ExpletusSans-BoldItalic.ttf", + 2, + { + { + 382, // length + 4, // format + 3, // platform id + 1, // encoding id + 10, // num_mappings + {32, 53, 74, 95, 116, 171, 192, 213, 234, 255} + , // chars + {9, 60, 33, 86, 11, 127, 148, 169, 190, 211} + , // glyph ids + } + , + { + 262, // length + 0, // format + 1, // platform id + 0, // encoding id + 10, // num_mappings + {0, 25, 50, 75, 100, 125, 150, 175, 200, 225} + , // chars + {0, 0, 57, 34, 3, 90, 197, 172, 143, 139} + , // glyph ids + } + } + }; + + TestCMap kTestAubrey_Regular_ttf_xml = { + "data/fonts/aubrey/Aubrey-Regular.ttf", + 1, + { + { + 168, // length + 4, // format + 3, // platform id + 1, // encoding id + 10, // num_mappings + {32, 53, 74, 95, 116, 170, 191, 212, 233, 254} + , // chars + {3, 24, 45, 66, 87, 108, 129, 150, 171, 192} + , // glyph ids + } + } + }; + + TestCMap kTestAntic_Regular_ttf_xml = { + "data/fonts/antic/Antic-Regular.ttf", + 2, + { + { + 194, // length + 4, // format + 3, // platform id + 1, // encoding id + 10, // num_mappings + {32, 53, 74, 95, 116, 171, 193, 214, 235, 305} + , // chars + {3, 24, 45, 66, 87, 107, 128, 149, 170, 191} + , // glyph ids + } + , + { + 262, // length + 0, // format + 1, // platform id + 0, // encoding id + 10, // num_mappings + {0, 25, 50, 75, 100, 125, 150, 175, 200, 225} + , // chars + {1, 0, 21, 46, 71, 96, 176, 151, 122, 118} + , // glyph ids + } + } + }; + + TestCMap kTestCopse_Regular_ttf_xml = { + "data/fonts/copse/Copse-Regular.ttf", + 2, + { + { + 152, // length + 4, // format + 3, // platform id + 1, // encoding id + 10, // num_mappings + {0, 51, 72, 93, 114, 168, 189, 210, 231, 252} + , // chars + {1, 22, 43, 64, 85, 106, 127, 148, 169, 190} + , // glyph ids + } + , + { + 262, // length + 0, // format + 1, // platform id + 0, // encoding id + 10, // num_mappings + {0, 25, 50, 75, 100, 125, 150, 175, 200, 225} + , // chars + {1, 0, 21, 46, 71, 96, 179, 154, 125, 121} + , // glyph ids + } + } + }; + + TestCMap kTestDaysOne_Regular_ttf_xml = { + "data/fonts/daysone/DaysOne-Regular.ttf", + 1, + { + { + 320, // length + 4, // format + 3, // platform id + 1, // encoding id + 10, // num_mappings + {32, 67, 102, 170, 206, 241, 321, 1033, 1069, 1105} + , // chars + {3, 38, 73, 108, 143, 178, 213, 248, 283, 318} + , // glyph ids + } + } + }; + + TestCMap kTestActor_Regular_ttf_xml = { + "data/fonts/actor/Actor-Regular.ttf", + 2, + { + { + 702, // length + 4, // format + 3, // platform id + 1, // encoding id + 10, // num_mappings + {32, 55, 78, 101, 124, 180, 203, 226, 249, 731} + , // chars + {3, 195, 33, 105, 79, 65, 16, 64, 209, 234} + , // glyph ids + } + , + { + 262, // length + 0, // format + 1, // platform id + 0, // encoding id + 10, // num_mappings + {0, 25, 50, 75, 100, 125, 150, 175, 200, 225} + , // chars + {1, 0, 204, 29, 96, 81, 154, 41, 129, 173} + , // glyph ids + } + } + }; + + TestCMap kTestBentham_Regular_ttf_xml = { + "data/fonts/bentham/Bentham-Regular.ttf", + 1, + { + { + 248, // length + 4, // format + 3, // platform id + 1, // encoding id + 10, // num_mappings + {19, 62, 93, 124, 208, 242, 275, 306, 339, 370} + , // chars + {3, 34, 65, 96, 127, 158, 189, 220, 251, 282} + , // glyph ids + } + } + }; + + TestCMap kTestFedero_Regular_ttf_xml = { + "data/fonts/federo/Federo-Regular.ttf", + 1, + { + { + 160, // length + 4, // format + 3, // platform id + 1, // encoding id + 10, // num_mappings + {32, 53, 74, 95, 116, 170, 191, 212, 233, 254} + , // chars + {3, 24, 45, 66, 87, 108, 129, 150, 171, 192} + , // glyph ids + } + } + }; + + TestCMap kTestArimo_Italic_ttf_xml = { + "data/fonts/arimo/Arimo-Italic.ttf", + 2, + { + { + 352, // length + 4, // format + 3, // platform id + 1, // encoding id + 10, // num_mappings + {32, 53, 75, 96, 117, 171, 192, 213, 234, 255} + , // chars + {3, 24, 45, 66, 87, 107, 127, 148, 169, 190} + , // glyph ids + } + , + { + 262, // length + 0, // format + 1, // platform id + 0, // encoding id + 10, // num_mappings + {0, 25, 50, 75, 100, 125, 150, 175, 200, 225} + , // chars + {1, 0, 21, 45, 70, 95, 176, 151, 122, 118} + , // glyph ids + } + } + }; + + TestCMap kTestArimo_BoldItalic_ttf_xml = { + "data/fonts/arimo/Arimo-BoldItalic.ttf", + 2, + { + { + 352, // length + 4, // format + 3, // platform id + 1, // encoding id + 10, // num_mappings + {32, 53, 75, 96, 117, 171, 192, 213, 234, 255} + , // chars + {3, 24, 45, 66, 87, 107, 127, 148, 169, 190} + , // glyph ids + } + , + { + 262, // length + 0, // format + 1, // platform id + 0, // encoding id + 10, // num_mappings + {0, 25, 50, 75, 100, 125, 150, 175, 200, 225} + , // chars + {1, 0, 21, 45, 70, 95, 176, 151, 122, 118} + , // glyph ids + } + } + }; + + TestCMap kTestArimo_Bold_ttf_xml = { + "data/fonts/arimo/Arimo-Bold.ttf", + 2, + { + { + 352, // length + 4, // format + 3, // platform id + 1, // encoding id + 10, // num_mappings + {32, 53, 75, 96, 117, 171, 192, 213, 234, 255} + , // chars + {3, 24, 45, 66, 87, 107, 127, 148, 169, 190} + , // glyph ids + } + , + { + 262, // length + 0, // format + 1, // platform id + 0, // encoding id + 10, // num_mappings + {0, 25, 50, 75, 100, 125, 150, 175, 200, 225} + , // chars + {1, 0, 21, 45, 70, 95, 176, 151, 122, 118} + , // glyph ids + } + } + }; + + TestCMap kTestArimo_Regular_ttf_xml = { + "data/fonts/arimo/Arimo-Regular.ttf", + 2, + { + { + 352, // length + 4, // format + 3, // platform id + 1, // encoding id + 10, // num_mappings + {32, 53, 75, 96, 117, 171, 192, 213, 234, 255} + , // chars + {3, 24, 45, 66, 87, 107, 127, 148, 169, 190} + , // glyph ids + } + , + { + 262, // length + 0, // format + 1, // platform id + 0, // encoding id + 10, // num_mappings + {0, 25, 50, 75, 100, 125, 150, 175, 200, 225} + , // chars + {1, 0, 21, 45, 70, 95, 176, 151, 122, 118} + , // glyph ids + } + } + }; + + TestCMap kTestIMFeDPsc28P_ttf_xml = { + "data/fonts/felltypes/IMFeDPsc28P.ttf", + 1, + { + { + 428, // length + 4, // format + 3, // platform id + 1, // encoding id + 10, // num_mappings + {32, 66, 100, 167, 201, 235, 273, 328, 375, 8216} + , // chars + {3, 37, 71, 104, 137, 171, 205, 239, 273, 303} + , // glyph ids + } + } + }; + + TestCMap kTestIMFeGPrm28P_ttf_xml = { + "data/fonts/felltypes/IMFeGPrm28P.ttf", + 1, + { + { + 452, // length + 4, // format + 3, // platform id + 1, // encoding id + 10, // num_mappings + {32, 67, 102, 170, 205, 240, 281, 340, 383, 8225} + , // chars + {3, 38, 73, 107, 141, 176, 211, 246, 281, 311} + , // glyph ids + } + } + }; + + TestCMap kTestIMFeENsc28P_ttf_xml = { + "data/fonts/felltypes/IMFeENsc28P.ttf", + 1, + { + { + 428, // length + 4, // format + 3, // platform id + 1, // encoding id + 10, // num_mappings + {32, 66, 100, 167, 201, 235, 273, 328, 375, 8216} + , // chars + {3, 37, 71, 104, 137, 171, 205, 239, 273, 303} + , // glyph ids + } + } + }; + + TestCMap kTestIMFePIit28P_ttf_xml = { + "data/fonts/felltypes/IMFePIit28P.ttf", + 1, + { + { + 492, // length + 4, // format + 3, // platform id + 1, // encoding id + 10, // num_mappings + {32, 68, 104, 173, 209, 245, 291, 346, 711, 8482} + , // chars + {3, 39, 75, 16, 145, 181, 217, 253, 287, 320} + , // glyph ids + } + } + }; + + TestCMap kTestIMFeDPrm28P_ttf_xml = { + "data/fonts/felltypes/IMFeDPrm28P.ttf", + 1, + { + { + 452, // length + 4, // format + 3, // platform id + 1, // encoding id + 10, // num_mappings + {32, 67, 102, 170, 205, 240, 281, 340, 383, 8225} + , // chars + {3, 38, 73, 107, 141, 176, 211, 246, 281, 311} + , // glyph ids + } + } + }; + + TestCMap kTestIMFePIrm28P_ttf_xml = { + "data/fonts/felltypes/IMFePIrm28P.ttf", + 1, + { + { + 444, // length + 4, // format + 3, // platform id + 1, // encoding id + 10, // num_mappings + {32, 67, 102, 170, 205, 240, 281, 340, 383, 8226} + , // chars + {3, 38, 73, 107, 141, 176, 211, 246, 281, 312} + , // glyph ids + } + } + }; + + TestCMap kTestIMFeFCrm28P_ttf_xml = { + "data/fonts/felltypes/IMFeFCrm28P.ttf", + 1, + { + { + 460, // length + 4, // format + 3, // platform id + 1, // encoding id + 10, // num_mappings + {32, 67, 102, 170, 205, 240, 281, 340, 383, 8225} + , // chars + {3, 38, 73, 107, 141, 176, 211, 246, 281, 311} + , // glyph ids + } + } + }; + + TestCMap kTestIMFeGPit28P_ttf_xml = { + "data/fonts/felltypes/IMFeGPit28P.ttf", + 1, + { + { + 484, // length + 4, // format + 3, // platform id + 1, // encoding id + 10, // num_mappings + {32, 69, 106, 176, 213, 250, 305, 356, 894, 9758} + , // chars + {3, 40, 77, 112, 149, 186, 223, 260, 30, 327} + , // glyph ids + } + } + }; + + TestCMap kTestIMFeENit28P_ttf_xml = { + "data/fonts/felltypes/IMFeENit28P.ttf", + 1, + { + { + 500, // length + 4, // format + 3, // platform id + 1, // encoding id + 10, // num_mappings + {32, 68, 104, 173, 209, 245, 291, 346, 711, 8482} + , // chars + {3, 39, 75, 16, 145, 181, 217, 253, 287, 320} + , // glyph ids + } + } + }; + + TestCMap kTestIMFeDPit28P_ttf_xml = { + "data/fonts/felltypes/IMFeDPit28P.ttf", + 1, + { + { + 476, // length + 4, // format + 3, // platform id + 1, // encoding id + 10, // num_mappings + {32, 70, 108, 179, 217, 255, 315, 368, 7813, 57355} + , // chars + {3, 41, 79, 115, 153, 191, 229, 267, 300, 336} + , // glyph ids + } + } + }; + + TestCMap kTestIMFeENrm28P_ttf_xml = { + "data/fonts/felltypes/IMFeENrm28P.ttf", + 1, + { + { + 468, // length + 4, // format + 3, // platform id + 1, // encoding id + 10, // num_mappings + {32, 67, 102, 170, 205, 240, 281, 340, 383, 8225} + , // chars + {3, 38, 73, 107, 141, 176, 211, 246, 281, 311} + , // glyph ids + } + } + }; + + TestCMap kTestIMFeGPsc28P_ttf_xml = { + "data/fonts/felltypes/IMFeGPsc28P.ttf", + 1, + { + { + 428, // length + 4, // format + 3, // platform id + 1, // encoding id + 10, // num_mappings + {32, 66, 100, 167, 201, 235, 273, 328, 375, 8216} + , // chars + {3, 37, 71, 104, 137, 171, 205, 239, 273, 303} + , // glyph ids + } + } + }; + + TestCMap kTestIMFePIsc28P_ttf_xml = { + "data/fonts/felltypes/IMFePIsc28P.ttf", + 1, + { + { + 428, // length + 4, // format + 3, // platform id + 1, // encoding id + 10, // num_mappings + {32, 66, 100, 167, 201, 235, 273, 328, 375, 8216} + , // chars + {3, 37, 71, 104, 137, 171, 205, 239, 273, 303} + , // glyph ids + } + } + }; + + TestCMap kTestIMFeFCsc28P_ttf_xml = { + "data/fonts/felltypes/IMFeFCsc28P.ttf", + 1, + { + { + 436, // length + 4, // format + 3, // platform id + 1, // encoding id + 10, // num_mappings + {32, 66, 100, 167, 201, 235, 273, 328, 375, 8212} + , // chars + {3, 37, 71, 104, 137, 171, 205, 239, 273, 302} + , // glyph ids + } + } + }; + + TestCMap kTestIMFeFCit28P_ttf_xml = { + "data/fonts/felltypes/IMFeFCit28P.ttf", + 1, + { + { + 452, // length + 4, // format + 3, // platform id + 1, // encoding id + 10, // num_mappings + {32, 69, 106, 176, 213, 250, 305, 356, 894, 9758} + , // chars + {3, 40, 77, 112, 149, 186, 223, 260, 30, 327} + , // glyph ids + } + } + }; + + TestCMap kTestBokor_ttf_xml = { + "data/fonts/bokor/Bokor.ttf", + 2, + { + { + 96, // length + 4, // format + 3, // platform id + 1, // encoding id + 10, // num_mappings + {32, 45, 58, 6019, 6032, 6045, 6058, 6073, 6086, 6099} + , // chars + {3, 16, 29, 39, 52, 65, 78, 91, 104, 117} + , // glyph ids + } + , + { + 262, // length + 0, // format + 1, // platform id + 0, // encoding id + 10, // num_mappings + {0, 25, 50, 75, 100, 125, 150, 175, 200, 225} + , // chars + {1, 0, 21, 0, 0, 0, 0, 0, 0, 0} + , // glyph ids + } + } + }; + + TestCMap kTestDidactGothic_ttf_xml = { + "data/fonts/didactgothic/DidactGothic.ttf", + 1, + { + { + 1048, // length + 4, // format + 3, // platform id + 1, // encoding id + 10, // num_mappings + {32, 179, 293, 430, 772, 1033, 1189, 7701, 7960, 8082} + , // chars + {3, 117, 231, 345, 459, 573, 687, 801, 915, 1029} + , // glyph ids + } + } + }; + + TestCMap kTestAllerta_Medium_ttf_xml = { + "data/fonts/allerta/Allerta-Medium.ttf", + 2, + { + { + 252, // length + 4, // format + 3, // platform id + 1, // encoding id + 10, // num_mappings + {32, 51, 69, 87, 107, 161, 200, 219, 238, 321} + , // chars + {3, 21, 39, 57, 75, 92, 110, 128, 146, 164} + , // glyph ids + } + , + { + 262, // length + 0, // format + 1, // platform id + 0, // encoding id + 10, // num_mappings + {0, 25, 50, 75, 100, 125, 150, 175, 200, 225} + , // chars + {1, 0, 20, 45, 68, 0, 149, 0, 101, 0} + , // glyph ids + } + } + }; + + TestCMap kTestAllerta_Stencil_ttf_xml = { + "data/fonts/allerta/Allerta-Stencil.ttf", + 2, + { + { + 252, // length + 4, // format + 3, // platform id + 1, // encoding id + 10, // num_mappings + {32, 51, 69, 87, 107, 161, 200, 219, 238, 321} + , // chars + {3, 21, 39, 57, 75, 92, 110, 128, 146, 164} + , // glyph ids + } + , + { + 262, // length + 0, // format + 1, // platform id + 0, // encoding id + 10, // num_mappings + {0, 25, 50, 75, 100, 125, 150, 175, 200, 225} + , // chars + {1, 0, 20, 45, 68, 0, 149, 0, 101, 0} + , // glyph ids + } + } + }; + + TestCMap kTestBuda_Light_ttf_xml = { + "data/fonts/buda/Buda-Light.ttf", + 2, + { + { + 552, // length + 4, // format + 3, // platform id + 1, // encoding id + 10, // num_mappings + {32, 53, 74, 95, 116, 170, 192, 213, 234, 255} + , // chars + {191, 114, 30, 206, 193, 158, 8, 42, 103, 212} + , // glyph ids + } + , + { + 262, // length + 0, // format + 1, // platform id + 0, // encoding id + 10, // num_mappings + {0, 25, 50, 75, 100, 125, 150, 175, 200, 225} + , // chars + {1, 0, 199, 31, 94, 78, 146, 41, 124, 168} + , // glyph ids + } + } + }; + + TestCMap kTestBrawler_Regular_ttf_xml = { + "data/fonts/brawler/Brawler-Regular.ttf", + 2, + { + { + 242, // length + 4, // format + 3, // platform id + 1, // encoding id + 10, // num_mappings + {32, 54, 76, 98, 120, 175, 197, 219, 241, 730} + , // chars + {2, 24, 46, 68, 90, 111, 129, 151, 173, 192} + , // glyph ids + } + , + { + 262, // length + 0, // format + 1, // platform id + 0, // encoding id + 10, // num_mappings + {0, 25, 50, 75, 100, 125, 150, 175, 200, 225} + , // chars + {0, 0, 20, 45, 70, 95, 173, 148, 119, 116} + , // glyph ids + } + } + }; + + TestCMap kTestCarterOne_ttf_xml = { + "data/fonts/carterone/CarterOne.ttf", + 1, + { + { + 322, // length + 4, // format + 3, // platform id + 1, // encoding id + 10, // num_mappings + {32, 58, 84, 110, 169, 197, 223, 249, 515, 711} + , // chars + {3, 29, 55, 81, 106, 132, 158, 184, 210, 236} + , // glyph ids + } + } + }; + + TestCMap kTestCandal_ttf_xml = { + "data/fonts/candal/Candal.ttf", + 1, + { + { + 448, // length + 4, // format + 3, // platform id + 1, // encoding id + 10, // num_mappings + {0, 61, 95, 162, 196, 230, 270, 340, 518, 806} + , // chars + {1, 36, 70, 104, 138, 172, 206, 240, 274, 308} + , // glyph ids + } + } + }; + + TestCMap kTestDorsa_Regular_ttf_xml = { + "data/fonts/dorsa/Dorsa-Regular.ttf", + 2, + { + { + 194, // length + 4, // format + 3, // platform id + 1, // encoding id + 10, // num_mappings + {32, 53, 74, 95, 116, 170, 193, 214, 235, 338} + , // chars + {3, 24, 45, 66, 87, 107, 128, 149, 170, 191} + , // glyph ids + } + , + { + 262, // length + 0, // format + 1, // platform id + 0, // encoding id + 10, // num_mappings + {0, 25, 50, 75, 100, 125, 150, 175, 200, 225} + , // chars + {1, 0, 21, 46, 71, 96, 176, 151, 122, 118} + , // glyph ids + } + } + }; + + TestCMap kTestCrimsonText_BoldItalic_ttf_xml = { + "data/fonts/crimson/CrimsonText-BoldItalic.ttf", + 1, + { + { + 336, // length + 4, // format + 3, // platform id + 1, // encoding id + 10, // num_mappings + {32, 75, 118, 195, 238, 281, 324, 368, 8194, 8730} + , // chars + {3, 46, 89, 132, 175, 218, 261, 304, 347, 390} + , // glyph ids + } + } + }; + + TestCMap kTestCrimsonText_Bold_ttf_xml = { + "data/fonts/crimson/CrimsonText-Bold.ttf", + 1, + { + { + 464, // length + 4, // format + 3, // platform id + 1, // encoding id + 10, // num_mappings + {32, 105, 212, 285, 359, 550, 7719, 7794, 7873, 8222} + , // chars + {3, 76, 149, 222, 295, 368, 441, 514, 587, 660} + , // glyph ids + } + } + }; + + TestCMap kTestCrimsonText_Italic_ttf_xml = { + "data/fonts/crimson/CrimsonText-Italic.ttf", + 1, + { + { + 328, // length + 4, // format + 3, // platform id + 1, // encoding id + 10, // num_mappings + {32, 75, 118, 195, 238, 281, 324, 367, 779, 8733} + , // chars + {3, 46, 89, 132, 175, 218, 261, 304, 347, 390} + , // glyph ids + } + } + }; + + TestCMap kTestCrimsonText_Roman_ttf_xml = { + "data/fonts/crimson/CrimsonText-Roman.ttf", + 1, + { + { + 712, // length + 4, // format + 3, // platform id + 1, // encoding id + 10, // num_mappings + {32, 188, 310, 770, 995, 1117, 7792, 7920, 8060, 8195} + , // chars + {3, 125, 247, 369, 491, 613, 735, 857, 979, 1101} + , // glyph ids + } + } + }; + + TestCMap kTestCrimsonText_Semibold_ttf_xml = { + "data/fonts/crimson/CrimsonText-Semibold.ttf", + 1, + { + { + 336, // length + 4, // format + 3, // platform id + 1, // encoding id + 10, // num_mappings + {32, 76, 120, 198, 242, 286, 331, 375, 779, 8712} + , // chars + {3, 47, 91, 135, 179, 223, 267, 311, 355, 399} + , // glyph ids + } + } + }; + + TestCMap kTestCrimsonText_SemiboldItalic_ttf_xml = { + "data/fonts/crimson/CrimsonText-SemiboldItalic.ttf", + 1, + { + { + 296, // length + 4, // format + 3, // platform id + 1, // encoding id + 10, // num_mappings + {32, 75, 118, 195, 238, 281, 324, 368, 775, 8722} + , // chars + {3, 46, 89, 132, 175, 218, 261, 304, 347, 390} + , // glyph ids + } + } + }; + + TestCMap kTestAmaranth_Italic_ttf_xml = { + "data/fonts/amaranth/Amaranth-Italic.ttf", + 2, + { + { + 566, // length + 4, // format + 3, // platform id + 1, // encoding id + 10, // num_mappings + {32, 53, 74, 95, 116, 170, 191, 212, 233, 254} + , // chars + {3, 62, 41, 120, 22, 78, 105, 170, 193, 144} + , // glyph ids + } + , + { + 262, // length + 0, // format + 1, // platform id + 0, // encoding id + 10, // num_mappings + {0, 25, 50, 75, 100, 125, 150, 175, 200, 225} + , // chars + {1, 0, 63, 40, 216, 125, 198, 108, 141, 123} + , // glyph ids + } + } + }; + + TestCMap kTestAmaranth_Bold_ttf_xml = { + "data/fonts/amaranth/Amaranth-Bold.ttf", + 2, + { + { + 566, // length + 4, // format + 3, // platform id + 1, // encoding id + 10, // num_mappings + {32, 53, 74, 95, 116, 170, 191, 212, 233, 254} + , // chars + {3, 62, 41, 121, 22, 78, 106, 168, 191, 145} + , // glyph ids + } + , + { + 262, // length + 0, // format + 1, // platform id + 0, // encoding id + 10, // num_mappings + {0, 25, 50, 75, 100, 125, 150, 175, 200, 225} + , // chars + {1, 0, 63, 40, 216, 126, 196, 109, 142, 124} + , // glyph ids + } + } + }; + + TestCMap kTestAmaranth_Regular_ttf_xml = { + "data/fonts/amaranth/Amaranth-Regular.ttf", + 2, + { + { + 566, // length + 4, // format + 3, // platform id + 1, // encoding id + 10, // num_mappings + {32, 53, 74, 95, 116, 170, 191, 212, 233, 254} + , // chars + {3, 62, 41, 121, 22, 78, 106, 168, 191, 145} + , // glyph ids + } + , + { + 262, // length + 0, // format + 1, // platform id + 0, // encoding id + 10, // num_mappings + {0, 25, 50, 75, 100, 125, 150, 175, 200, 225} + , // chars + {1, 0, 63, 40, 216, 126, 196, 109, 142, 124} + , // glyph ids + } + } + }; + + TestCMap kTestAmaranth_BoldItalic_ttf_xml = { + "data/fonts/amaranth/Amaranth-BoldItalic.ttf", + 2, + { + { + 566, // length + 4, // format + 3, // platform id + 1, // encoding id + 10, // num_mappings + {32, 53, 74, 95, 116, 170, 191, 212, 233, 254} + , // chars + {3, 62, 41, 120, 22, 78, 105, 177, 200, 144} + , // glyph ids + } + , + { + 262, // length + 0, // format + 1, // platform id + 0, // encoding id + 10, // num_mappings + {0, 25, 50, 75, 100, 125, 150, 175, 200, 225} + , // chars + {1, 0, 63, 40, 223, 125, 205, 108, 141, 123} + , // glyph ids + } + } + }; + + TestCMap kTestCrushed_ttf_xml = { + "data/fonts/crushed/Crushed.ttf", + 1, + { + { + 696, // length + 4, // format + 3, // platform id + 1, // encoding id + 10, // num_mappings + {32, 68, 104, 173, 209, 245, 281, 318, 354, 711} + , // chars + {362, 4, 34, 345, 160, 178, 109, 155, 209, 355} + , // glyph ids + } + } + }; + + TestCMap kTestAdamina_Regular_ttf_xml = { + "data/fonts/adamina/Adamina-Regular.ttf", + 2, + { + { + 160, // length + 4, // format + 3, // platform id + 1, // encoding id + 10, // num_mappings + {32, 53, 74, 95, 116, 170, 191, 212, 233, 254} + , // chars + {3, 24, 45, 66, 87, 108, 129, 150, 171, 192} + , // glyph ids + } + , + { + 262, // length + 0, // format + 1, // platform id + 0, // encoding id + 10, // num_mappings + {0, 25, 50, 75, 100, 125, 150, 175, 200, 225} + , // chars + {1, 0, 21, 46, 71, 96, 179, 154, 125, 121} + , // glyph ids + } + } + }; + + TestCMap kTestAldrich_Regular_ttf_xml = { + "data/fonts/aldrich/Aldrich-Regular.ttf", + 1, + { + { + 262, // length + 4, // format + 3, // platform id + 1, // encoding id + 10, // num_mappings + {32, 56, 80, 104, 161, 186, 210, 234, 297, 381} + , // chars + {3, 25, 49, 73, 97, 121, 145, 169, 193, 217} + , // glyph ids + } + } + }; + + TestCMap kTestFanwoodText_Italic_ttf_xml = { + "data/fonts/fanwoodtext/FanwoodText-Italic.ttf", + 1, + { + { + 312, // length + 4, // format + 3, // platform id + 1, // encoding id + 10, // num_mappings + {32, 73, 114, 188, 229, 270, 311, 352, 711, 8193} + , // chars + {3, 44, 85, 126, 167, 208, 249, 290, 331, 372} + , // glyph ids + } + } + }; + + TestCMap kTestFanwoodText_Regular_ttf_xml = { + "data/fonts/fanwoodtext/FanwoodText-Regular.ttf", + 1, + { + { + 312, // length + 4, // format + 3, // platform id + 1, // encoding id + 10, // num_mappings + {32, 73, 114, 188, 229, 270, 311, 352, 711, 8193} + , // chars + {3, 44, 85, 126, 167, 208, 249, 290, 331, 372} + , // glyph ids + } + } + }; + + TestCMap kTestAnonymousPro_Regular_ttf_xml = { + "data/fonts/anonymouspro/AnonymousPro-Regular.ttf", + 1, + { + { + 974, // length + 4, // format + 3, // platform id + 1, // encoding id + 10, // num_mappings + {0, 92, 187, 249, 311, 373, 938, 1051, 1114, 8963} + , // chars + {1, 61, 168, 125, 297, 357, 408, 469, 531, 563} + , // glyph ids + } + } + }; + + TestCMap kTestAnonymousPro_Bold_ttf_xml = { + "data/fonts/anonymouspro/AnonymousPro-Bold.ttf", + 1, + { + { + 974, // length + 4, // format + 3, // platform id + 1, // encoding id + 10, // num_mappings + {0, 92, 187, 249, 311, 373, 938, 1051, 1114, 8963} + , // chars + {1, 61, 168, 125, 297, 357, 408, 469, 531, 563} + , // glyph ids + } + } + }; + + TestCMap kTestAnonymousPro_Italic_ttf_xml = { + "data/fonts/anonymouspro/AnonymousPro-Italic.ttf", + 1, + { + { + 974, // length + 4, // format + 3, // platform id + 1, // encoding id + 10, // num_mappings + {0, 92, 187, 249, 311, 373, 938, 1051, 1114, 8963} + , // chars + {1, 61, 168, 125, 297, 357, 408, 469, 531, 563} + , // glyph ids + } + } + }; + + TestCMap kTestAnonymousPro_BoldItalic_ttf_xml = { + "data/fonts/anonymouspro/AnonymousPro-BoldItalic.ttf", + 1, + { + { + 974, // length + 4, // format + 3, // platform id + 1, // encoding id + 10, // num_mappings + {0, 92, 187, 249, 311, 373, 938, 1051, 1114, 8963} + , // chars + {1, 61, 168, 125, 297, 357, 408, 469, 531, 563} + , // glyph ids + } + } + }; + + TestCMap kTestBevan_ttf_xml = { + "data/fonts/bevan/Bevan.ttf", + 1, + { + { + 400, // length + 4, // format + 3, // platform id + 1, // encoding id + 10, // num_mappings + {32, 75, 118, 194, 237, 280, 325, 368, 531, 8200} + , // chars + {3, 46, 89, 132, 175, 218, 261, 304, 347, 390} + , // glyph ids + } + } + }; + + TestCMap kTestArtifika_Regular_ttf_xml = { + "data/fonts/artifika/Artifika-Regular.ttf", + 1, + { + { + 160, // length + 4, // format + 3, // platform id + 1, // encoding id + 10, // num_mappings + {2, 52, 73, 94, 115, 169, 190, 211, 232, 253} + , // chars + {3, 24, 45, 66, 87, 108, 129, 150, 171, 192} + , // glyph ids + } + } + }; + + TestCMap kTestAnton_ttf_xml = { + "data/fonts/anton/Anton.ttf", + 1, + { + { + 384, // length + 4, // format + 3, // platform id + 1, // encoding id + 10, // num_mappings + {32, 73, 114, 189, 230, 271, 315, 356, 517, 7809} + , // chars + {3, 44, 85, 126, 167, 208, 249, 290, 331, 372} + , // glyph ids + } + } + }; + + TestCMap kTestBattambang_Regular_ttf_xml = { + "data/fonts/battambang/Battambang-Regular.ttf", + 2, + { + { + 96, // length + 4, // format + 3, // platform id + 1, // encoding id + 10, // num_mappings + {32, 45, 58, 6019, 6032, 6045, 6058, 6073, 6086, 6099} + , // chars + {3, 16, 29, 39, 52, 65, 78, 91, 104, 117} + , // glyph ids + } + , + { + 262, // length + 0, // format + 1, // platform id + 0, // encoding id + 10, // num_mappings + {0, 25, 50, 75, 100, 125, 150, 175, 200, 225} + , // chars + {1, 0, 21, 0, 0, 0, 0, 0, 0, 0} + , // glyph ids + } + } + }; + + TestCMap kTestBattambang_Bold_ttf_xml = { + "data/fonts/battambang/Battambang-Bold.ttf", + 2, + { + { + 96, // length + 4, // format + 3, // platform id + 1, // encoding id + 10, // num_mappings + {32, 45, 58, 6019, 6032, 6045, 6058, 6073, 6086, 6099} + , // chars + {3, 16, 29, 39, 52, 65, 78, 91, 104, 117} + , // glyph ids + } + , + { + 262, // length + 0, // format + 1, // platform id + 0, // encoding id + 10, // num_mappings + {0, 25, 50, 75, 100, 125, 150, 175, 200, 225} + , // chars + {1, 0, 21, 0, 0, 0, 0, 0, 0, 0} + , // glyph ids + } + } + }; + + TestCMap kTestCarme_Regular_ttf_xml = { + "data/fonts/carme/Carme-Regular.ttf", + 2, + { + { + 256, // length + 4, // format + 3, // platform id + 1, // encoding id + 10, // num_mappings + {32, 53, 74, 96, 117, 179, 204, 227, 249, 8201} + , // chars + {3, 24, 45, 66, 87, 108, 129, 150, 171, 192} + , // glyph ids + } + , + { + 262, // length + 0, // format + 1, // platform id + 0, // encoding id + 10, // num_mappings + {0, 25, 50, 75, 100, 125, 150, 175, 200, 225} + , // chars + {1, 0, 21, 46, 70, 95, 164, 140, 0, 0} + , // glyph ids + } + } + }; + + TestCMap kTestCherryCreamSoda_ttf_xml = { + "data/fonts/cherrycreamsoda/CherryCreamSoda.ttf", + 2, + { + { + 422, // length + 4, // format + 3, // platform id + 1, // encoding id + 10, // num_mappings + {32, 54, 76, 98, 120, 175, 198, 220, 242, 381} + , // chars + {21, 43, 65, 87, 109, 217, 159, 122, 140, 10} + , // glyph ids + } + , + { + 262, // length + 0, // format + 1, // platform id + 0, // encoding id + 10, // num_mappings + {0, 25, 50, 75, 100, 125, 150, 175, 200, 225} + , // chars + {0, 0, 39, 64, 89, 114, 138, 160, 172, 195} + , // glyph ids + } + } + }; + + TestCMap kTestDeliusUnicase_Regular_ttf_xml = { + "data/fonts/deliusunicase/DeliusUnicase-Regular.ttf", + 2, + { + { + 240, // length + 4, // format + 3, // platform id + 1, // encoding id + 10, // num_mappings + {32, 57, 82, 107, 165, 190, 215, 240, 309, 956} + , // chars + {3, 28, 53, 78, 103, 128, 153, 178, 203, 119} + , // glyph ids + } + , + { + 262, // length + 0, // format + 1, // platform id + 0, // encoding id + 10, // num_mappings + {0, 25, 50, 75, 100, 125, 150, 175, 200, 225} + , // chars + {1, 0, 21, 46, 71, 96, 179, 154, 125, 121} + , // glyph ids + } + } + }; + + TestCMap kTestComingSoon_ttf_xml = { + "data/fonts/comingsoon/ComingSoon.ttf", + 2, + { + { + 412, // length + 4, // format + 3, // platform id + 1, // encoding id + 10, // num_mappings + {32, 54, 76, 98, 120, 175, 197, 219, 241, 376} + , // chars + {21, 43, 65, 87, 109, 216, 117, 211, 138, 187} + , // glyph ids + } + , + { + 262, // length + 0, // format + 1, // platform id + 0, // encoding id + 10, // num_mappings + {0, 25, 50, 75, 100, 125, 150, 175, 200, 225} + , // chars + {0, 0, 39, 64, 89, 114, 138, 160, 171, 194} + , // glyph ids + } + } + }; + + TestCMap kTestFreehand_ttf_xml = { + "data/fonts/freehand/Freehand.ttf", + 2, + { + { + 96, // length + 4, // format + 3, // platform id + 1, // encoding id + 10, // num_mappings + {32, 45, 58, 6019, 6032, 6045, 6058, 6073, 6086, 6099} + , // chars + {3, 16, 29, 39, 52, 65, 78, 91, 104, 117} + , // glyph ids + } + , + { + 262, // length + 0, // format + 1, // platform id + 0, // encoding id + 10, // num_mappings + {0, 25, 50, 75, 100, 125, 150, 175, 200, 225} + , // chars + {1, 0, 21, 0, 0, 0, 0, 0, 0, 0} + , // glyph ids + } + } + }; + + TestCMap kTestAlice_Regular_ttf_xml = { + "data/fonts/alice/Alice-Regular.ttf", + 1, + { + { + 160, // length + 4, // format + 3, // platform id + 1, // encoding id + 10, // num_mappings + {32, 53, 74, 95, 116, 170, 191, 212, 233, 254} + , // chars + {3, 24, 45, 66, 87, 108, 129, 150, 171, 192} + , // glyph ids + } + } + }; + + TestCMap kTestContrail_Regular_ttf_xml = { + "data/fonts/contrail/Contrail-Regular.ttf", + 2, + { + { + 368, // length + 4, // format + 3, // platform id + 1, // encoding id + 10, // num_mappings + {32, 55, 78, 101, 124, 180, 203, 226, 249, 339} + , // chars + {3, 26, 49, 72, 95, 117, 140, 163, 186, 209} + , // glyph ids + } + , + { + 262, // length + 0, // format + 1, // platform id + 0, // encoding id + 10, // num_mappings + {0, 25, 50, 75, 100, 125, 150, 175, 200, 225} + , // chars + {1, 0, 21, 46, 71, 96, 178, 153, 124, 120} + , // glyph ids + } + } + }; + + TestCMap kTestCardo_Bold_ttf_xml = { + "data/fonts/cardo/Cardo-Bold.ttf", + 1, + { + { + 3676, // length + 4, // format + 3, // platform id + 1, // encoding id + 10, // num_mappings + {32, 295, 653, 883, 5792, 7961, 8212, 10219, 58808, 61909} + , // chars + {3, 232, 461, 691, 921, 1151, 1381, 1610, 1840, 2070} + , // glyph ids + } + } + }; + + TestCMap kTestCardo_Italic_ttf_xml = { + "data/fonts/cardo/Cardo-Italic.ttf", + 1, + { + { + 3788, // length + 4, // format + 3, // platform id + 1, // encoding id + 10, // num_mappings + {32, 306, 662, 921, 5833, 8008, 8313, 42804, 58625, 61889} + , // chars + {3, 243, 483, 724, 965, 1206, 1447, 1687, 1926, 2139} + , // glyph ids + } + } + }; + + TestCMap kTestCardo_Regular_ttf_xml = { + "data/fonts/cardo/Cardo-Regular.ttf", + 1, + { + { + 4686, // length + 4, // format + 3, // platform id + 1, // encoding id + 10, // num_mappings + {32, 376, 802, 4347, 8000, 8710, 57497, 59336, 61431, 62510} + , // chars + {3, 313, 623, 934, 1245, 729, 1866, 2175, 2481, 2792} + , // glyph ids + } + } + }; + + TestCMap kTestAsset_ttf_xml = { + "data/fonts/asset/Asset.ttf", + 2, + { + { + 210, // length + 4, // format + 3, // platform id + 1, // encoding id + 10, // num_mappings + {32, 54, 76, 98, 120, 176, 198, 220, 242, 312} + , // chars + {3, 25, 47, 69, 91, 112, 134, 156, 178, 200} + , // glyph ids + } + , + { + 262, // length + 0, // format + 1, // platform id + 0, // encoding id + 10, // num_mappings + {0, 25, 50, 75, 100, 125, 150, 175, 200, 225} + , // chars + {1, 0, 21, 46, 71, 96, 177, 152, 123, 119} + , // glyph ids + } + } + }; + + TestCMap kTestChangaOne_Regular_ttf_xml = { + "data/fonts/changaone/ChangaOne-Regular.ttf", + 2, + { + { + 320, // length + 4, // format + 3, // platform id + 1, // encoding id + 10, // num_mappings + {32, 56, 80, 104, 162, 188, 212, 236, 339, 8224} + , // chars + {3, 27, 51, 75, 99, 123, 147, 171, 195, 219} + , // glyph ids + } + , + { + 262, // length + 0, // format + 1, // platform id + 0, // encoding id + 10, // num_mappings + {0, 25, 50, 75, 100, 125, 150, 175, 200, 225} + , // chars + {1, 0, 21, 46, 71, 96, 176, 151, 122, 118} + , // glyph ids + } + } + }; + + TestCMap kTestAclonica_ttf_xml = { + "data/fonts/aclonica/Aclonica.ttf", + 2, + { + { + 718, // length + 4, // format + 3, // platform id + 1, // encoding id + 10, // num_mappings + {32, 68, 104, 173, 209, 245, 281, 317, 353, 711} + , // chars + {3, 50, 86, 233, 201, 224, 267, 333, 172, 170} + , // glyph ids + } + , + { + 262, // length + 0, // format + 1, // platform id + 0, // encoding id + 10, // num_mappings + {0, 25, 50, 75, 100, 125, 150, 175, 200, 225} + , // chars + {1, 0, 32, 57, 82, 107, 219, 124, 140, 156} + , // glyph ids + } + } + }; + + TestCMap kTestCraftyGirls_ttf_xml = { + "data/fonts/craftygirls/CraftyGirls.ttf", + 2, + { + { + 428, // length + 4, // format + 3, // platform id + 1, // encoding id + 10, // num_mappings + {32, 54, 76, 98, 120, 175, 197, 219, 241, 376} + , // chars + {21, 43, 65, 87, 109, 219, 117, 214, 138, 189} + , // glyph ids + } + , + { + 262, // length + 0, // format + 1, // platform id + 0, // encoding id + 10, // num_mappings + {0, 25, 50, 75, 100, 125, 150, 175, 200, 225} + , // chars + {0, 0, 39, 64, 89, 114, 138, 160, 173, 196} + , // glyph ids + } + } + }; + + TestCMap kTestArchitectsDaughter_ttf_xml = { + "data/fonts/architectsdaughter/ArchitectsDaughter.ttf", + 1, + { + { + 282, // length + 4, // format + 3, // platform id + 1, // encoding id + 10, // num_mappings + {32, 66, 100, 167, 202, 236, 270, 311, 349, 508} + , // chars + {3, 37, 71, 104, 138, 172, 206, 240, 274, 308} + , // glyph ids + } + } + }; + + TestCMap kTestContent_Bold_ttf_xml = { + "data/fonts/content/Content-Bold.ttf", + 2, + { + { + 96, // length + 4, // format + 3, // platform id + 1, // encoding id + 10, // num_mappings + {32, 45, 58, 6019, 6032, 6045, 6058, 6073, 6086, 6099} + , // chars + {3, 16, 29, 39, 52, 65, 78, 91, 104, 117} + , // glyph ids + } + , + { + 262, // length + 0, // format + 1, // platform id + 0, // encoding id + 10, // num_mappings + {0, 25, 50, 75, 100, 125, 150, 175, 200, 225} + , // chars + {1, 0, 21, 0, 0, 0, 0, 0, 0, 0} + , // glyph ids + } + } + }; + + TestCMap kTestContent_Regular_ttf_xml = { + "data/fonts/content/Content-Regular.ttf", + 2, + { + { + 96, // length + 4, // format + 3, // platform id + 1, // encoding id + 10, // num_mappings + {32, 45, 58, 6019, 6032, 6045, 6058, 6073, 6086, 6099} + , // chars + {3, 16, 29, 39, 52, 65, 78, 91, 104, 117} + , // glyph ids + } + , + { + 262, // length + 0, // format + 1, // platform id + 0, // encoding id + 10, // num_mappings + {0, 25, 50, 75, 100, 125, 150, 175, 200, 225} + , // chars + {1, 0, 21, 0, 0, 0, 0, 0, 0, 0} + , // glyph ids + } + } + }; + + TestCMap kTestAbel_Regular_ttf_xml = { + "data/fonts/abel/Abel-Regular.ttf", + 2, + { + { + 248, // length + 4, // format + 3, // platform id + 1, // encoding id + 10, // num_mappings + {32, 56, 80, 104, 161, 186, 210, 234, 297, 381} + , // chars + {3, 27, 51, 75, 99, 123, 147, 171, 195, 219} + , // glyph ids + } + , + { + 262, // length + 0, // format + 1, // platform id + 0, // encoding id + 10, // num_mappings + {0, 25, 50, 75, 100, 125, 150, 175, 200, 225} + , // chars + {1, 0, 21, 46, 71, 96, 178, 153, 124, 120} + , // glyph ids + } + } + }; + + TestCMap kTestCuprum_ttf_xml = { + "data/fonts/cuprum/Cuprum.ttf", + 1, + { + { + 352, // length + 4, // format + 3, // platform id + 1, // encoding id + 10, // num_mappings + {32, 69, 106, 176, 213, 250, 324, 1028, 1066, 1103} + , // chars + {3, 40, 77, 114, 151, 188, 225, 262, 299, 336} + , // glyph ids + } + } + }; + + TestCMap kTestAndika_R_ttf_xml = { + "data/fonts/andika/Andika-R.ttf", + 1, + { + { + 4792, // length + 4, // format + 3, // platform id + 1, // encoding id + 10, // num_mappings + {13, 281, 498, 715, 1067, 7424, 7691, 7908, 8580, 61860} + , // chars + {2, 817, 745, 2639, 597, 474, 699, 2213, 644, 876} + , // glyph ids + } + } + }; + +} // namespace sfntly diff --git a/test/autogenerated/cmap_test_data.h b/test/autogenerated/cmap_test_data.h new file mode 100644 index 0000000..63fd9c9 --- /dev/null +++ b/test/autogenerated/cmap_test_data.h @@ -0,0 +1,353 @@ +/* + * !!! DO NOT EDIT !!! + * THIS FILE IS GENERATED BY A SCRIPT. + * FOR MORE DETAILS SEE 'README-test_data.txt'. + */ + +/* + * 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_TEST_CMAP_TEST_DATA_H_ +#define SFNTLY_CPP_SRC_TEST_CMAP_TEST_DATA_H_ + +#include "sfntly/port/type.h" + +namespace sfntly +{ + struct ProtoCMap + { + int32_t length; + int32_t format; + int32_t platform_id; + int32_t encoding_id; + int32_t num_mappings; + int32_t chars[10]; + int32_t glyph_ids[10]; + }; + + struct TestCMap + { + const char *name; + int32_t num_cmaps; + ProtoCMap cmaps[2]; + }; + + extern TestCMap kTestCousine_BoldItalic_ttf_xml; + extern TestCMap kTestCousine_Bold_ttf_xml; + extern TestCMap kTestCousine_Regular_ttf_xml; + extern TestCMap kTestCousine_Italic_ttf_xml; + extern TestCMap kTestCedarville_Cursive_ttf_xml; + extern TestCMap kTestDancingScript_Bold_ttf_xml; + extern TestCMap kTestDancingScript_Regular_ttf_xml; + extern TestCMap kTestDamion_Regular_ttf_xml; + extern TestCMap kTestAnnieUseYourTelescope_ttf_xml; + extern TestCMap kTestDeliusSwashCaps_Regular_ttf_xml; + extern TestCMap kTestDelius_Regular_ttf_xml; + extern TestCMap kTestCoveredByYourGrace_ttf_xml; + extern TestCMap kTestEBGaramond_Regular_ttf_xml; + extern TestCMap kTestCabinSketch_Bold_ttf_xml; + extern TestCMap kTestAllan_Bold_ttf_xml; + extern TestCMap kTestCoda_Caption_Heavy_ttf_xml; + extern TestCMap kTestCoda_Heavy_ttf_xml; + extern TestCMap kTestForum_Regular_ttf_xml; + extern TestCMap kTestAlike_Regular_ttf_xml; + extern TestCMap kTestCorben_Bold_ttf_xml; + extern TestCMap kTestCaudex_Regular_ttf_xml; + extern TestCMap kTestCaudex_BoldItalic_ttf_xml; + extern TestCMap kTestCaudex_Italic_ttf_xml; + extern TestCMap kTestCaudex_Bold_ttf_xml; + extern TestCMap kTestCabin_MediumItalic_ttf_xml; + extern TestCMap kTestCabin_SemiBold_ttf_xml; + extern TestCMap kTestCabin_SemiBoldItalic_ttf_xml; + extern TestCMap kTestCabin_BoldItalic_ttf_xml; + extern TestCMap kTestCabin_Medium_ttf_xml; + extern TestCMap kTestCabin_Italic_ttf_xml; + extern TestCMap kTestCabin_Bold_ttf_xml; + extern TestCMap kTestCabin_Regular_ttf_xml; + extern TestCMap kTestDawningofaNewDay_ttf_xml; + extern TestCMap kTestDangrek_ttf_xml; + extern TestCMap kTestBlackOpsOne_ttf_xml; + extern TestCMap kTestFrancoisOne_ttf_xml; + extern TestCMap kTestBowlbyOne_ttf_xml; + extern TestCMap kTestBowlbyOneSC_ttf_xml; + extern TestCMap kTestCalligraffiti_ttf_xml; + extern TestCMap kTestBangers_ttf_xml; + extern TestCMap kTestAstloch_Regular_ttf_xml; + extern TestCMap kTestAstloch_Bold_ttf_xml; + extern TestCMap kTestAngkor_ttf_xml; + extern TestCMap kTestAbrilFatface_Regular_ttf_xml; + extern TestCMap kTestCantarell_BoldOblique_ttf_xml; + extern TestCMap kTestCantarell_Oblique_ttf_xml; + extern TestCMap kTestCantarell_Bold_ttf_xml; + extern TestCMap kTestCantarell_Regular_ttf_xml; + extern TestCMap kTestArvo_Bold_ttf_xml; + extern TestCMap kTestArvo_Italic_ttf_xml; + extern TestCMap kTestArvo_BoldItalic_ttf_xml; + extern TestCMap kTestArvo_Regular_ttf_xml; + extern TestCMap kTestChewy_ttf_xml; + extern TestCMap kTestBigshotOne_ttf_xml; + extern TestCMap kTestChenla_ttf_xml; + extern TestCMap kTestBayon_ttf_xml; + extern TestCMap kTestCoustard_Black_ttf_xml; + extern TestCMap kTestCoustard_Regular_ttf_xml; + extern TestCMap kTestAmaticSC_Bold_ttf_xml; + extern TestCMap kTestAmaticSC_Regular_ttf_xml; + extern TestCMap kTestComfortaa_Light_ttf_xml; + extern TestCMap kTestComfortaa_Bold_ttf_xml; + extern TestCMap kTestComfortaa_Regular_ttf_xml; + extern TestCMap kTestExpletusSans_Bold_ttf_xml; + extern TestCMap kTestExpletusSans_MediumItalic_ttf_xml; + extern TestCMap kTestExpletusSans_Medium_ttf_xml; + extern TestCMap kTestExpletusSans_SemiBold_ttf_xml; + extern TestCMap kTestExpletusSans_Regular_ttf_xml; + extern TestCMap kTestExpletusSans_Italic_ttf_xml; + extern TestCMap kTestExpletusSans_SemiBoldItalic_ttf_xml; + extern TestCMap kTestExpletusSans_BoldItalic_ttf_xml; + extern TestCMap kTestAubrey_Regular_ttf_xml; + extern TestCMap kTestAntic_Regular_ttf_xml; + extern TestCMap kTestCopse_Regular_ttf_xml; + extern TestCMap kTestDaysOne_Regular_ttf_xml; + extern TestCMap kTestActor_Regular_ttf_xml; + extern TestCMap kTestBentham_Regular_ttf_xml; + extern TestCMap kTestFedero_Regular_ttf_xml; + extern TestCMap kTestArimo_Italic_ttf_xml; + extern TestCMap kTestArimo_BoldItalic_ttf_xml; + extern TestCMap kTestArimo_Bold_ttf_xml; + extern TestCMap kTestArimo_Regular_ttf_xml; + extern TestCMap kTestIMFeDPsc28P_ttf_xml; + extern TestCMap kTestIMFeGPrm28P_ttf_xml; + extern TestCMap kTestIMFeENsc28P_ttf_xml; + extern TestCMap kTestIMFePIit28P_ttf_xml; + extern TestCMap kTestIMFeDPrm28P_ttf_xml; + extern TestCMap kTestIMFePIrm28P_ttf_xml; + extern TestCMap kTestIMFeFCrm28P_ttf_xml; + extern TestCMap kTestIMFeGPit28P_ttf_xml; + extern TestCMap kTestIMFeENit28P_ttf_xml; + extern TestCMap kTestIMFeDPit28P_ttf_xml; + extern TestCMap kTestIMFeENrm28P_ttf_xml; + extern TestCMap kTestIMFeGPsc28P_ttf_xml; + extern TestCMap kTestIMFePIsc28P_ttf_xml; + extern TestCMap kTestIMFeFCsc28P_ttf_xml; + extern TestCMap kTestIMFeFCit28P_ttf_xml; + extern TestCMap kTestBokor_ttf_xml; + extern TestCMap kTestDidactGothic_ttf_xml; + extern TestCMap kTestAllerta_Medium_ttf_xml; + extern TestCMap kTestAllerta_Stencil_ttf_xml; + extern TestCMap kTestBuda_Light_ttf_xml; + extern TestCMap kTestBrawler_Regular_ttf_xml; + extern TestCMap kTestCarterOne_ttf_xml; + extern TestCMap kTestCandal_ttf_xml; + extern TestCMap kTestDorsa_Regular_ttf_xml; + extern TestCMap kTestCrimsonText_BoldItalic_ttf_xml; + extern TestCMap kTestCrimsonText_Bold_ttf_xml; + extern TestCMap kTestCrimsonText_Italic_ttf_xml; + extern TestCMap kTestCrimsonText_Roman_ttf_xml; + extern TestCMap kTestCrimsonText_Semibold_ttf_xml; + extern TestCMap kTestCrimsonText_SemiboldItalic_ttf_xml; + extern TestCMap kTestAmaranth_Italic_ttf_xml; + extern TestCMap kTestAmaranth_Bold_ttf_xml; + extern TestCMap kTestAmaranth_Regular_ttf_xml; + extern TestCMap kTestAmaranth_BoldItalic_ttf_xml; + extern TestCMap kTestCrushed_ttf_xml; + extern TestCMap kTestAdamina_Regular_ttf_xml; + extern TestCMap kTestAldrich_Regular_ttf_xml; + extern TestCMap kTestFanwoodText_Italic_ttf_xml; + extern TestCMap kTestFanwoodText_Regular_ttf_xml; + extern TestCMap kTestAnonymousPro_Regular_ttf_xml; + extern TestCMap kTestAnonymousPro_Bold_ttf_xml; + extern TestCMap kTestAnonymousPro_Italic_ttf_xml; + extern TestCMap kTestAnonymousPro_BoldItalic_ttf_xml; + extern TestCMap kTestBevan_ttf_xml; + extern TestCMap kTestArtifika_Regular_ttf_xml; + extern TestCMap kTestAnton_ttf_xml; + extern TestCMap kTestBattambang_Regular_ttf_xml; + extern TestCMap kTestBattambang_Bold_ttf_xml; + extern TestCMap kTestCarme_Regular_ttf_xml; + extern TestCMap kTestCherryCreamSoda_ttf_xml; + extern TestCMap kTestDeliusUnicase_Regular_ttf_xml; + extern TestCMap kTestComingSoon_ttf_xml; + extern TestCMap kTestFreehand_ttf_xml; + extern TestCMap kTestAlice_Regular_ttf_xml; + extern TestCMap kTestContrail_Regular_ttf_xml; + extern TestCMap kTestCardo_Bold_ttf_xml; + extern TestCMap kTestCardo_Italic_ttf_xml; + extern TestCMap kTestCardo_Regular_ttf_xml; + extern TestCMap kTestAsset_ttf_xml; + extern TestCMap kTestChangaOne_Regular_ttf_xml; + extern TestCMap kTestAclonica_ttf_xml; + extern TestCMap kTestCraftyGirls_ttf_xml; + extern TestCMap kTestArchitectsDaughter_ttf_xml; + extern TestCMap kTestContent_Bold_ttf_xml; + extern TestCMap kTestContent_Regular_ttf_xml; + extern TestCMap kTestAbel_Regular_ttf_xml; + extern TestCMap kTestCuprum_ttf_xml; + extern TestCMap kTestAndika_R_ttf_xml; + + const TestCMap kAllTestCMaps[] = { + kTestCousine_BoldItalic_ttf_xml, + kTestCousine_Bold_ttf_xml, + kTestCousine_Regular_ttf_xml, + kTestCousine_Italic_ttf_xml, + kTestCedarville_Cursive_ttf_xml, + kTestDancingScript_Bold_ttf_xml, + kTestDancingScript_Regular_ttf_xml, + kTestDamion_Regular_ttf_xml, + kTestAnnieUseYourTelescope_ttf_xml, + kTestDeliusSwashCaps_Regular_ttf_xml, + kTestDelius_Regular_ttf_xml, + kTestCoveredByYourGrace_ttf_xml, + kTestEBGaramond_Regular_ttf_xml, + kTestCabinSketch_Bold_ttf_xml, + kTestAllan_Bold_ttf_xml, + kTestCoda_Caption_Heavy_ttf_xml, + kTestCoda_Heavy_ttf_xml, + kTestForum_Regular_ttf_xml, + kTestAlike_Regular_ttf_xml, + kTestCorben_Bold_ttf_xml, + kTestCaudex_Regular_ttf_xml, + kTestCaudex_BoldItalic_ttf_xml, + kTestCaudex_Italic_ttf_xml, + kTestCaudex_Bold_ttf_xml, + kTestCabin_MediumItalic_ttf_xml, + kTestCabin_SemiBold_ttf_xml, + kTestCabin_SemiBoldItalic_ttf_xml, + kTestCabin_BoldItalic_ttf_xml, + kTestCabin_Medium_ttf_xml, + kTestCabin_Italic_ttf_xml, + kTestCabin_Bold_ttf_xml, + kTestCabin_Regular_ttf_xml, + kTestDawningofaNewDay_ttf_xml, + kTestDangrek_ttf_xml, + kTestBlackOpsOne_ttf_xml, + kTestFrancoisOne_ttf_xml, + kTestBowlbyOne_ttf_xml, + kTestBowlbyOneSC_ttf_xml, + kTestCalligraffiti_ttf_xml, + kTestBangers_ttf_xml, + kTestAstloch_Regular_ttf_xml, + kTestAstloch_Bold_ttf_xml, + kTestAngkor_ttf_xml, + kTestAbrilFatface_Regular_ttf_xml, + kTestCantarell_BoldOblique_ttf_xml, + kTestCantarell_Oblique_ttf_xml, + kTestCantarell_Bold_ttf_xml, + kTestCantarell_Regular_ttf_xml, + kTestArvo_Bold_ttf_xml, + kTestArvo_Italic_ttf_xml, + kTestArvo_BoldItalic_ttf_xml, + kTestArvo_Regular_ttf_xml, + kTestChewy_ttf_xml, + kTestBigshotOne_ttf_xml, + kTestChenla_ttf_xml, + kTestBayon_ttf_xml, + kTestCoustard_Black_ttf_xml, + kTestCoustard_Regular_ttf_xml, + kTestAmaticSC_Bold_ttf_xml, + kTestAmaticSC_Regular_ttf_xml, + kTestComfortaa_Light_ttf_xml, + kTestComfortaa_Bold_ttf_xml, + kTestComfortaa_Regular_ttf_xml, + kTestExpletusSans_Bold_ttf_xml, + kTestExpletusSans_MediumItalic_ttf_xml, + kTestExpletusSans_Medium_ttf_xml, + kTestExpletusSans_SemiBold_ttf_xml, + kTestExpletusSans_Regular_ttf_xml, + kTestExpletusSans_Italic_ttf_xml, + kTestExpletusSans_SemiBoldItalic_ttf_xml, + kTestExpletusSans_BoldItalic_ttf_xml, + kTestAubrey_Regular_ttf_xml, + kTestAntic_Regular_ttf_xml, + kTestCopse_Regular_ttf_xml, + kTestDaysOne_Regular_ttf_xml, + kTestActor_Regular_ttf_xml, + kTestBentham_Regular_ttf_xml, + kTestFedero_Regular_ttf_xml, + kTestArimo_Italic_ttf_xml, + kTestArimo_BoldItalic_ttf_xml, + kTestArimo_Bold_ttf_xml, + kTestArimo_Regular_ttf_xml, + kTestIMFeDPsc28P_ttf_xml, + kTestIMFeGPrm28P_ttf_xml, + kTestIMFeENsc28P_ttf_xml, + kTestIMFePIit28P_ttf_xml, + kTestIMFeDPrm28P_ttf_xml, + kTestIMFePIrm28P_ttf_xml, + kTestIMFeFCrm28P_ttf_xml, + kTestIMFeGPit28P_ttf_xml, + kTestIMFeENit28P_ttf_xml, + kTestIMFeDPit28P_ttf_xml, + kTestIMFeENrm28P_ttf_xml, + kTestIMFeGPsc28P_ttf_xml, + kTestIMFePIsc28P_ttf_xml, + kTestIMFeFCsc28P_ttf_xml, + kTestIMFeFCit28P_ttf_xml, + kTestBokor_ttf_xml, + kTestDidactGothic_ttf_xml, + kTestAllerta_Medium_ttf_xml, + kTestAllerta_Stencil_ttf_xml, + kTestBuda_Light_ttf_xml, + kTestBrawler_Regular_ttf_xml, + kTestCarterOne_ttf_xml, + kTestCandal_ttf_xml, + kTestDorsa_Regular_ttf_xml, + kTestCrimsonText_BoldItalic_ttf_xml, + kTestCrimsonText_Bold_ttf_xml, + kTestCrimsonText_Italic_ttf_xml, + kTestCrimsonText_Roman_ttf_xml, + kTestCrimsonText_Semibold_ttf_xml, + kTestCrimsonText_SemiboldItalic_ttf_xml, + kTestAmaranth_Italic_ttf_xml, + kTestAmaranth_Bold_ttf_xml, + kTestAmaranth_Regular_ttf_xml, + kTestAmaranth_BoldItalic_ttf_xml, + kTestCrushed_ttf_xml, + kTestAdamina_Regular_ttf_xml, + kTestAldrich_Regular_ttf_xml, + kTestFanwoodText_Italic_ttf_xml, + kTestFanwoodText_Regular_ttf_xml, + kTestAnonymousPro_Regular_ttf_xml, + kTestAnonymousPro_Bold_ttf_xml, + kTestAnonymousPro_Italic_ttf_xml, + kTestAnonymousPro_BoldItalic_ttf_xml, + kTestBevan_ttf_xml, + kTestArtifika_Regular_ttf_xml, + kTestAnton_ttf_xml, + kTestBattambang_Regular_ttf_xml, + kTestBattambang_Bold_ttf_xml, + kTestCarme_Regular_ttf_xml, + kTestCherryCreamSoda_ttf_xml, + kTestDeliusUnicase_Regular_ttf_xml, + kTestComingSoon_ttf_xml, + kTestFreehand_ttf_xml, + kTestAlice_Regular_ttf_xml, + kTestContrail_Regular_ttf_xml, + kTestCardo_Bold_ttf_xml, + kTestCardo_Italic_ttf_xml, + kTestCardo_Regular_ttf_xml, + kTestAsset_ttf_xml, + kTestChangaOne_Regular_ttf_xml, + kTestAclonica_ttf_xml, + kTestCraftyGirls_ttf_xml, + kTestArchitectsDaughter_ttf_xml, + kTestContent_Bold_ttf_xml, + kTestContent_Regular_ttf_xml, + kTestAbel_Regular_ttf_xml, + kTestCuprum_ttf_xml, + kTestAndika_R_ttf_xml + }; +} // namespace sfntly + +#endif //SFNTLY_CPP_SRC_TEST_CMAP_TEST_DATA_H_ -- cgit v1.2.3 From bb035e4061737ef1ac7ee3e1263c443b55c123e9 Mon Sep 17 00:00:00 2001 From: "dfilimon@google.com" Date: Thu, 15 Sep 2011 19:14:16 +0000 Subject: Adding CMapTable support for Format0. git-svn-id: http://sfntly.googlecode.com/svn/trunk/cpp/src@76 672e30a5-4c29-85ac-ac6d-611c735e0a51 --- sfntly/table/core/cmap_table.cc | 454 +++++++++++++++++++++++++++++++--------- sfntly/table/core/cmap_table.h | 192 ++++++++++++----- sfntly/table/table.cc | 6 +- 3 files changed, 506 insertions(+), 146 deletions(-) diff --git a/sfntly/table/core/cmap_table.cc b/sfntly/table/core/cmap_table.cc index dd43996..bbe4497 100644 --- a/sfntly/table/core/cmap_table.cc +++ b/sfntly/table/core/cmap_table.cc @@ -14,24 +14,93 @@ * limitations under the License. */ -// TODO(arthurhsu): IMPLEMENT: not really used and tested, need cleanup +#include "sfntly/table/core/cmap_table.h" -#include +#include +#include + +#include -#include "sfntly/table/core/cmap_table.h" -#include "sfntly/table/core/name_table.h" #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 reinterpret_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 = new CMapIdFilter(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()); + delete id_filter; + return cmap.Detach(); + } + delete id_filter; +#ifndef SFNTLY_NO_EXCEPTION + throw NoSuchElementException(); +#else + return NULL; +#endif +} + int32_t CMapTable::Version() { return data_->ReadUShort(Offset::kVersion); } @@ -41,7 +110,7 @@ int32_t CMapTable::NumCMaps() { } CMapTable::CMapId CMapTable::GetCMapId(int32_t index) { - return CMapId(PlatformId(index), EncodingId(index)); + return NewCMapId(PlatformId(index), EncodingId(index)); } int32_t CMapTable::PlatformId(int32_t index) { @@ -59,53 +128,101 @@ int32_t CMapTable::Offset(int32_t index) { OffsetForEncodingRecord(index)); } -CMapTable::CMapTable(Header* header, ReadableFontData* data) - : SubTableContainerTable(header, data) { -} - int32_t CMapTable::OffsetForEncodingRecord(int32_t index) { return Offset::kEncodingRecordStart + index * Offset::kEncodingRecordSize; } -/****************************************************************************** - * CMapTable::CMapId class - ******************************************************************************/ -CMapTable::CMapId::CMapId(int32_t platform_id, int32_t encoding_id) - : platform_id_(platform_id), encoding_id_(encoding_id) { +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::CMapId(const CMapId& obj) - : platform_id_(obj.platform_id_), encoding_id_(obj.encoding_id_) { +CMapTable::CMapId CMapTable::NewCMapId(const CMapId& obj) { + CMapId result; + result.platform_id = obj.platform_id; + result.encoding_id = obj.encoding_id; + return result; } -bool CMapTable::CMapId::operator==(const CMapTable::CMapId& obj) { - return obj.platform_id_ == platform_id_ && obj.encoding_id_ == encoding_id_; +/****************************************************************************** + * CMapTable::CMapIterator class + ******************************************************************************/ +CMapTable::CMapIterator::CMapIterator(CMapTable* table, + const CMapFilter* filter) + : table_index_(0), filter_(filter), table_(table) { } -const CMapTable::CMapId& CMapTable::CMapId::operator=( - const CMapTable::CMapId& obj) { - platform_id_ = obj.platform_id_; - encoding_id_ = obj.encoding_id_; - return *this; +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; } -int CMapTable::CMapId::HashCode() const { - return platform_id_ << 8 | encoding_id_; +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 WINDOWS_BMP(PlatformId::kWindows, - WindowsEncodingId::kUnicodeUCS2); -CMapTable::CMapId WINDOWS_UCS4(PlatformId::kWindows, - WindowsEncodingId::kUnicodeUCS4); -CMapTable::CMapId MAC_ROMAN(PlatformId::kWindows, MacintoshEncodingId::kRoman); +/****************************************************************************** + * CMapTable::CMapId class + ******************************************************************************/ /****************************************************************************** * CMapTable::CMapIdComparator class ******************************************************************************/ bool CMapTable::CMapIdComparator::operator()(const CMapId& lhs, - const CMapId& rhs) { - return lhs.HashCode() > rhs.HashCode(); + 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); } /****************************************************************************** @@ -126,20 +243,59 @@ CMapTable::CMap::Builder::~Builder() { } CALLER_ATTACH CMapTable::CMap::Builder* - CMapTable::CMap::Builder::GetBuilder(ReadableFontData* data, - int32_t offset, + 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 = new CMapFormat0::Builder(data, offset, cmap_id); + builder.Attach(CMapFormat0::Builder::NewInstance(data, offset, cmap_id)); break; case CMapFormat::kFormat2: - builder = new CMapFormat0::Builder(data, offset, cmap_id); +#if defined (SFNTLY_DEBUG_CMAP) + fprintf(stderr, "Requesting Format2 builder, but it's unsupported; " + "returning NULL\n"); +#endif + break; + case CMapFormat::kFormat4: +#if defined (SFNTLY_DEBUG_CMAP) + fprintf(stderr, "Requesting Format4 builder, but it's unsupported; " + "returning NULL\n"); +#endif 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: +#if defined (SFNTLY_DEBUG_CMAP) + fprintf(stderr, "Requesting Format4 builder, but it's unsupported; " + "returning NULL\n"); +#endif + break; + default: +#ifdef SFNTLY_DEBUG_CMAP + fprintf(stderr, "Unknown builder format requested\n"); +#endif break; } return builder.Detach(); @@ -150,7 +306,8 @@ CMapTable::CMap::Builder::Builder(ReadableFontData* data, const CMapId& cmap_id) : SubTable::Builder(data), format_(format), - cmap_id_(cmap_id) { + cmap_id_(cmap_id), + language_(0) { } CMapTable::CMap::Builder::Builder(WritableFontData* data, @@ -158,7 +315,8 @@ CMapTable::CMap::Builder::Builder(WritableFontData* data, const CMapId& cmap_id) : SubTable::Builder(data), format_(format), - cmap_id_(cmap_id) { + cmap_id_(cmap_id), + language_(0) { } int32_t CMapTable::CMap::Builder::SubSerialize(WritableFontData* new_data) { @@ -170,7 +328,10 @@ bool CMapTable::CMap::Builder::SubReadyToSerialize() { } int32_t CMapTable::CMap::Builder::SubDataSizeToSerialize() { - return InternalReadData()->Length(); + ReadableFontDataPtr read_data = InternalReadData(); + if (!read_data) + return 0; + return read_data->Length(); } void CMapTable::CMap::Builder::SubDataSet() { @@ -191,7 +352,7 @@ int32_t CMapTable::CMapFormat0::GlyphId(int32_t character) { if (character < 0 || character > 255) { return CMapTable::NOTDEF; } - return data_->ReadByte(character + Offset::kFormat0GlyphIdArray); + return data_->ReadUByte(character + Offset::kFormat0GlyphIdArray); } CMapTable::CMapFormat0::CMapFormat0(ReadableFontData* data, @@ -199,29 +360,94 @@ CMapTable::CMapFormat0::CMapFormat0(ReadableFontData* data, : CMap(data, CMapFormat::kFormat0, cmap_id) { } +void +CMapTable::CMapFormat0::Iterator(CMapTable::CMap::CharacterIterator* output) { + output = 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 ******************************************************************************/ -CMapTable::CMapFormat0::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::kFormat0, cmap_id) { - // TODO(arthurhsu): FIXIT: heavy lifting and leak, need fix. +// 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); } -CMapTable::CMapFormat0::Builder::Builder(ReadableFontData* data, - int32_t offset, +// 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 ? down_cast( - data->Slice(offset, data->ReadUShort( - offset + Offset::kFormat0Length))) - : reinterpret_cast(NULL), - CMapFormat::kFormat0, cmap_id) { - // TODO(arthurhsu): FIXIT: heavy lifting and leak, need fix. + : 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() { @@ -363,28 +589,6 @@ CALLER_ATTACH FontDataTable* return table.Detach(); } -/****************************************************************************** - * CMapTable::Iterator class - ******************************************************************************/ -CMapTable::CMapIterator::CMapIterator(CMapTable* table, 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; -} - /****************************************************************************** * CMapTable::Builder class ******************************************************************************/ @@ -403,12 +607,12 @@ 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, - cmap_builders_.size()); + GetCMapBuilders()->size()); int32_t index_offset = size; - size += cmap_builders_.size() * CMapTable::Offset::kEncodingRecordSize; - for (CMapBuilderMap::iterator it = cmap_builders_.begin(), - e = cmap_builders_.end(); it != e; ++it) { + 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()); @@ -424,12 +628,12 @@ int32_t CMapTable::Builder::SubSerialize(WritableFontData* new_data) { } bool CMapTable::Builder::SubReadyToSerialize() { - if (cmap_builders_.empty()) + if (GetCMapBuilders()->empty()) return false; // check each table - for (CMapBuilderMap::iterator it = cmap_builders_.begin(), - e = cmap_builders_.end(); it != e; ++it) { + for (CMapBuilderMap::iterator it = GetCMapBuilders()->begin(), + e = GetCMapBuilders()->end(); it != e; ++it) { if (!it->second->SubReadyToSerialize()) return false; } @@ -437,16 +641,16 @@ bool CMapTable::Builder::SubReadyToSerialize() { } int32_t CMapTable::Builder::SubDataSizeToSerialize() { - if (cmap_builders_.empty()) + if (GetCMapBuilders()->empty()) return 0; bool variable = false; int32_t size = CMapTable::Offset::kEncodingRecordStart + - cmap_builders_.size() * CMapTable::Offset::kEncodingRecordSize; + GetCMapBuilders()->size() * CMapTable::Offset::kEncodingRecordSize; // calculate size of each table - for (CMapBuilderMap::iterator it = cmap_builders_.begin(), - e = cmap_builders_.end(); it != e; ++it) { + 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; @@ -455,8 +659,8 @@ int32_t CMapTable::Builder::SubDataSizeToSerialize() { } void CMapTable::Builder::SubDataSet() { - cmap_builders_.clear(); - Table::Builder::set_model_changed(false); + GetCMapBuilders()->clear(); + Table::Builder::set_model_changed(); } CALLER_ATTACH FontDataTable* @@ -473,6 +677,7 @@ CALLER_ATTACH CMapTable::Builder* return builder.Detach(); } +// static CALLER_ATTACH CMapTable::CMap::Builder* CMapTable::Builder::CMapBuilder(ReadableFontData* data, int32_t index) { if (index < 0 || index > NumCMaps(data)) { @@ -489,10 +694,11 @@ CALLER_ATTACH CMapTable::CMap::Builder* OffsetForEncodingRecord(index)); int32_t offset = data->ReadULongAsInt(Offset::kEncodingRecordOffset + OffsetForEncodingRecord(index)); - CMapId cmap_id(platform_id, encoding_id); - return CMap::Builder::GetBuilder(data, offset, cmap_id); + return CMap::Builder::GetBuilder(data, offset, + NewCMapId(platform_id, encoding_id)); } +// static int32_t CMapTable::Builder::NumCMaps(ReadableFontData* data) { if (data == NULL) { return 0; @@ -500,4 +706,64 @@ int32_t CMapTable::Builder::NumCMaps(ReadableFontData* data) { 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) { + Ptr cmap_builder; + cmap_builder.Attach(CMapBuilder(data, i)); + if (!cmap_builder) + continue; + cmap_builders_[cmap_builder->cmap_id()] = cmap_builder; + cmap_builders_.insert(std::make_pair(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/sfntly/table/core/cmap_table.h b/sfntly/table/core/cmap_table.h index 6455ef6..2242613 100644 --- a/sfntly/table/core/cmap_table.h +++ b/sfntly/table/core/cmap_table.h @@ -14,7 +14,6 @@ * limitations under the License. */ -// TODO(arthurhsu): IMPLEMENT: not really used and tested, need cleanup #ifndef SFNTLY_CPP_SRC_SFNTLY_TABLE_CORE_CMAP_TABLE_H_ #define SFNTLY_CPP_SRC_SFNTLY_TABLE_CORE_CMAP_TABLE_H_ @@ -46,23 +45,12 @@ struct CMapFormat { class CMapTable : public SubTableContainerTable, public RefCounted { public: // CMapTable::CMapId - class CMapId { - public: - CMapId(int32_t platform_id, int32_t encoding_id); - CMapId(const CMapId& obj); - - int32_t platform_id() { return platform_id_; } - int32_t encoding_id() { return encoding_id_; } - - bool operator==(const CMapId& obj); - const CMapId& operator=(const CMapId& obj); - int HashCode() const; - - friend class CMapIdComparator; - - private: - int32_t platform_id_; - int32_t encoding_id_; + 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; @@ -71,7 +59,7 @@ public: // CMapTable::CMapIdComparator class CMapIdComparator { public: - bool operator()(const CMapId& lhs, const CMapId& rhs); + bool operator()(const CMapId& lhs, const CMapId& rhs) const; }; // A filter on cmap @@ -81,11 +69,28 @@ 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(CMapId cmap_id) = 0; + 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: + 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 @@ -93,7 +98,7 @@ public: // with a given cmap id (pair of platform and encoding ids) no matter what the // type of the cmap is. // - // The cmap implements {@code Iterable} to allow iteration over + // 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 @@ -101,7 +106,7 @@ public: // 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 + // 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; @@ -116,11 +121,17 @@ public: 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 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, @@ -138,16 +149,31 @@ public: 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: + CharacterIterator() {} + 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; + }; CMap(ReadableFontData* data, int32_t format, const CMapId& cmap_id); virtual ~CMap(); + + virtual void Iterator(CMapTable::CMap::CharacterIterator* output) = 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(); } + 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. // @@ -173,32 +199,63 @@ public: 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: - // CMapTable::CMapFormat0::Builder + // 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); - virtual ~Builder(); + Builder( + const CMapId& cmap_id); + }; - protected: - virtual CALLER_ATTACH FontDataTable* - SubBuildTable(ReadableFontData* data); + // 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); + virtual void Iterator(CMap::CharacterIterator* output); private: CMapFormat0(ReadableFontData* data, const CMapId& cmap_id); @@ -225,8 +282,17 @@ public: 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 ~CMapFormat2(); virtual int32_t Language(); virtual int32_t GlyphId(int32_t character); @@ -236,6 +302,8 @@ public: // 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); @@ -244,14 +312,15 @@ public: int32_t EntryCount(int32_t sub_header_index); int32_t IdRangeOffset(int32_t sub_header_index); int32_t IdDelta(int32_t sub_header_index); + void Iterator(CMapTable::CMap::CharacterIterator* output) { } }; // CMapTable::Builder 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. + // 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(); @@ -265,18 +334,54 @@ public: 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; - virtual ~CMapTable(); + 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(); @@ -296,9 +401,11 @@ public: // The offset is from the beginning of the table. virtual int32_t Offset(int32_t index); - private: + 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. @@ -411,19 +518,6 @@ public: }; }; - class CMapIterator { - public: - // If filter is NULL, filter through all tables. - CMapIterator(CMapTable* table, CMapFilter* filter); - bool HasNext(); - CMap* Next(); - - private: - int32_t table_index_; - CMapFilter* filter_; - CMapTable* table_; - }; - CMapTable(Header* header, ReadableFontData* data); // Get the offset in the table data for the encoding record for the cmap with diff --git a/sfntly/table/table.cc b/sfntly/table/table.cc index 7183d38..02f13e7 100644 --- a/sfntly/table/table.cc +++ b/sfntly/table/table.cc @@ -74,10 +74,10 @@ Table::Builder* Table::Builder::GetBuilder(Header* header, // Note: Tables are commented out when they are not used/ported. // TODO(arthurhsu): IMPLEMENT: finish tables that are not ported. - /*if (tag == Tag::cmap) { + if (tag == Tag::cmap) { builder_raw = static_cast( - CMapTable::CreateBuilder(font_builder, header, table_data)); - } else*/ if (tag == Tag::head) { + CMapTable::Builder::CreateBuilder(header, table_data)); + } else if (tag == Tag::head) { builder_raw = static_cast( FontHeaderTable::Builder::CreateBuilder(header, table_data)); } else if (tag == Tag::hhea) { -- cgit v1.2.3 From 9b84c9cb838074805aa1d9931fe937304c92f0a3 Mon Sep 17 00:00:00 2001 From: "dfilimon@google.com" Date: Thu, 15 Sep 2011 19:18:58 +0000 Subject: Added UNREFERENCED_PARAMATER fix for CMapFormat2 iterator. git-svn-id: http://sfntly.googlecode.com/svn/trunk/cpp/src@77 672e30a5-4c29-85ac-ac6d-611c735e0a51 --- sfntly/table/core/cmap_table.h | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/sfntly/table/core/cmap_table.h b/sfntly/table/core/cmap_table.h index 2242613..bfd69aa 100644 --- a/sfntly/table/core/cmap_table.h +++ b/sfntly/table/core/cmap_table.h @@ -312,7 +312,9 @@ public: int32_t EntryCount(int32_t sub_header_index); int32_t IdRangeOffset(int32_t sub_header_index); int32_t IdDelta(int32_t sub_header_index); - void Iterator(CMapTable::CMap::CharacterIterator* output) { } + void Iterator(CMapTable::CMap::CharacterIterator* output) { + UNREFERENCED_PARAMETER(output); + } }; // CMapTable::Builder -- cgit v1.2.3 From abb68accf47583a130eba5578baa89b4257e5679 Mon Sep 17 00:00:00 2001 From: "dfilimon@google.com" Date: Thu, 15 Sep 2011 19:22:43 +0000 Subject: Added fix for operator= generation failure for CMapIdFilter on Windows. git-svn-id: http://sfntly.googlecode.com/svn/trunk/cpp/src@78 672e30a5-4c29-85ac-ac6d-611c735e0a51 --- sfntly/table/core/cmap_table.cc | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/sfntly/table/core/cmap_table.cc b/sfntly/table/core/cmap_table.cc index bbe4497..29bf3fe 100644 --- a/sfntly/table/core/cmap_table.cc +++ b/sfntly/table/core/cmap_table.cc @@ -84,16 +84,14 @@ CALLER_ATTACH CMapTable::CMap* CMapTable::GetCMap(const int32_t platform_id, CALLER_ATTACH CMapTable::CMap* CMapTable::GetCMap(const CMapTable::CMapId cmap_id) { - CMapIdFilter* id_filter = new CMapIdFilter(cmap_id); - CMapIterator cmap_iterator(this, id_filter); + 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()); - delete id_filter; return cmap.Detach(); } - delete id_filter; #ifndef SFNTLY_NO_EXCEPTION throw NoSuchElementException(); #else -- cgit v1.2.3 From 089c48270e5b0ee5f437a0b81e25c46fb93a6d93 Mon Sep 17 00:00:00 2001 From: "dfilimon@google.com" Date: Thu, 15 Sep 2011 19:32:31 +0000 Subject: Added private operator= for CMapIdFilter to get the code to compile with Visual Studio. git-svn-id: http://sfntly.googlecode.com/svn/trunk/cpp/src@79 672e30a5-4c29-85ac-ac6d-611c735e0a51 --- sfntly/table/core/cmap_table.h | 1 + 1 file changed, 1 insertion(+) diff --git a/sfntly/table/core/cmap_table.h b/sfntly/table/core/cmap_table.h index bfd69aa..6287642 100644 --- a/sfntly/table/core/cmap_table.h +++ b/sfntly/table/core/cmap_table.h @@ -87,6 +87,7 @@ public: ~CMapIdFilter() {} virtual bool accept(const CMapId& cmap_id) const; private: + CMapIdFilter& operator=(const CMapIdFilter& that); const CMapId wanted_id_; const CMapIdComparator *comparator_; }; -- cgit v1.2.3 From ba91573e890c0871c6949e480a365bc85d408e77 Mon Sep 17 00:00:00 2001 From: "dfilimon@google.com" Date: Thu, 15 Sep 2011 19:48:41 +0000 Subject: Added port/type.h before other headers to fix the Visual Studio redefintion issue. git-svn-id: http://sfntly.googlecode.com/svn/trunk/cpp/src@81 672e30a5-4c29-85ac-ac6d-611c735e0a51 --- sfntly/table/core/cmap_table.cc | 1 + sfntly/table/core/cmap_table.h | 2 ++ test/autogenerated/cmap_basic_test.cc | 2 ++ 3 files changed, 5 insertions(+) diff --git a/sfntly/table/core/cmap_table.cc b/sfntly/table/core/cmap_table.cc index 29bf3fe..0f907b7 100644 --- a/sfntly/table/core/cmap_table.cc +++ b/sfntly/table/core/cmap_table.cc @@ -15,6 +15,7 @@ */ #include "sfntly/table/core/cmap_table.h" +#include "sfntly/port/type.h" #include #include diff --git a/sfntly/table/core/cmap_table.h b/sfntly/table/core/cmap_table.h index 6287642..8ff9706 100644 --- a/sfntly/table/core/cmap_table.h +++ b/sfntly/table/core/cmap_table.h @@ -17,6 +17,8 @@ #ifndef SFNTLY_CPP_SRC_SFNTLY_TABLE_CORE_CMAP_TABLE_H_ #define SFNTLY_CPP_SRC_SFNTLY_TABLE_CORE_CMAP_TABLE_H_ +#include "sfntly/port/type.h" + #include #include diff --git a/test/autogenerated/cmap_basic_test.cc b/test/autogenerated/cmap_basic_test.cc index e12aedd..119906d 100644 --- a/test/autogenerated/cmap_basic_test.cc +++ b/test/autogenerated/cmap_basic_test.cc @@ -14,6 +14,8 @@ * limitations under the License. */ +#include "sfntly/port/type.h" + #include #include #include -- cgit v1.2.3 From 79fe62d80f2ab09a217c5948a9adbcd019f4455d Mon Sep 17 00:00:00 2001 From: "dfilimon@google.com" Date: Fri, 16 Sep 2011 01:24:51 +0000 Subject: Minor cleanup. git-svn-id: http://sfntly.googlecode.com/svn/trunk/cpp/src@82 672e30a5-4c29-85ac-ac6d-611c735e0a51 --- sfntly/table/core/cmap_table.cc | 25 ++++++++++-------- sfntly/table/core/cmap_table.h | 48 +++++++++++++++-------------------- sfntly/table/table.cc | 4 +++ test/autogenerated/cmap_basic_test.cc | 4 ++- 4 files changed, 42 insertions(+), 39 deletions(-) diff --git a/sfntly/table/core/cmap_table.cc b/sfntly/table/core/cmap_table.cc index 0f907b7..9df1158 100644 --- a/sfntly/table/core/cmap_table.cc +++ b/sfntly/table/core/cmap_table.cc @@ -14,8 +14,11 @@ * limitations under the License. */ -#include "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 "sfntly/table/core/cmap_table.h" #include #include @@ -75,7 +78,7 @@ CALLER_ATTACH CMapTable::CMap* CMapTable::GetCMap(const int32_t index) { return NULL; #endif } - return reinterpret_cast(cmap_builder->Build()); + return down_cast(cmap_builder->Build()); } CALLER_ATTACH CMapTable::CMap* CMapTable::GetCMap(const int32_t platform_id, @@ -359,9 +362,8 @@ CMapTable::CMapFormat0::CMapFormat0(ReadableFontData* data, : CMap(data, CMapFormat::kFormat0, cmap_id) { } -void -CMapTable::CMapFormat0::Iterator(CMapTable::CMap::CharacterIterator* output) { - output = new CMapTable::CMapFormat0::CharacterIterator(0, 0xff); +CMapTable::CMap::CharacterIterator* CMapTable::CMapFormat0::Iterator() { + return new CMapTable::CMapFormat0::CharacterIterator(0, 0xff); } @@ -442,8 +444,7 @@ CMapTable::CMapFormat0::Builder::Builder( UNREFERENCED_PARAMETER(offset); } -CMapTable::CMapFormat0::Builder:: -Builder(const CMapId& cmap_id) +CMapTable::CMapFormat0::Builder::Builder(const CMapId& cmap_id) : CMap::Builder(reinterpret_cast(NULL), CMapFormat::kFormat0, cmap_id) { @@ -554,6 +555,11 @@ int32_t CMapTable::CMapFormat2::IdDelta(int32_t sub_header_index) { Offset::kFormat2SubHeader_idDelta); } +CMapTable::CMap::CharacterIterator* CMapTable::CMapFormat2::Iterator() { + // UNIMPLEMENTED + return NULL; +} + /****************************************************************************** * CMapTable::CMapFormat2::Builder ******************************************************************************/ @@ -712,13 +718,10 @@ int32_t CMapTable::Builder::NumCMaps() { void CMapTable::Builder::Initialize(ReadableFontData* data) { int32_t num_cmaps = NumCMaps(data); for (int32_t i = 0; i < num_cmaps; ++i) { - Ptr cmap_builder; - cmap_builder.Attach(CMapBuilder(data, i)); + CMapTable::CMap::Builder* cmap_builder = CMapBuilder(data, i); if (!cmap_builder) continue; cmap_builders_[cmap_builder->cmap_id()] = cmap_builder; - cmap_builders_.insert(std::make_pair(cmap_builder->cmap_id(), - cmap_builder)); } } diff --git a/sfntly/table/core/cmap_table.h b/sfntly/table/core/cmap_table.h index 8ff9706..bbdc7b5 100644 --- a/sfntly/table/core/cmap_table.h +++ b/sfntly/table/core/cmap_table.h @@ -17,8 +17,10 @@ #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 @@ -89,7 +91,6 @@ public: ~CMapIdFilter() {} virtual bool accept(const CMapId& cmap_id) const; private: - CMapIdFilter& operator=(const CMapIdFilter& that); const CMapId wanted_id_; const CMapIdComparator *comparator_; }; @@ -160,18 +161,22 @@ public: // The fully qualified name is CMapTable::CMap::CharacterIterator class CharacterIterator { public: - CharacterIterator() {} 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 void Iterator(CMapTable::CMap::CharacterIterator* output) = 0; + virtual CMap::CharacterIterator* Iterator() = 0; virtual int32_t format() { return format_; } virtual CMapId cmap_id() { return cmap_id_; } @@ -213,16 +218,13 @@ public: 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); + 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: @@ -232,14 +234,9 @@ public: 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); + 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 @@ -258,7 +255,7 @@ public: virtual ~CMapFormat0(); virtual int32_t Language(); virtual int32_t GlyphId(int32_t character); - virtual void Iterator(CMap::CharacterIterator* output); + CMap::CharacterIterator* Iterator(); private: CMapFormat0(ReadableFontData* data, const CMapId& cmap_id); @@ -315,9 +312,7 @@ public: int32_t EntryCount(int32_t sub_header_index); int32_t IdRangeOffset(int32_t sub_header_index); int32_t IdDelta(int32_t sub_header_index); - void Iterator(CMapTable::CMap::CharacterIterator* output) { - UNREFERENCED_PARAMETER(output); - } + CMap::CharacterIterator* Iterator(); }; // CMapTable::Builder @@ -531,7 +526,6 @@ public: }; typedef std::vector CMapIdList; typedef Ptr CMapTablePtr; - } // namespace sfntly #endif // SFNTLY_CPP_SRC_SFNTLY_TABLE_CORE_CMAP_TABLE_H_ diff --git a/sfntly/table/table.cc b/sfntly/table/table.cc index 02f13e7..8f4571e 100644 --- a/sfntly/table/table.cc +++ b/sfntly/table/table.cc @@ -14,6 +14,10 @@ * 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" diff --git a/test/autogenerated/cmap_basic_test.cc b/test/autogenerated/cmap_basic_test.cc index 119906d..0c09199 100644 --- a/test/autogenerated/cmap_basic_test.cc +++ b/test/autogenerated/cmap_basic_test.cc @@ -14,8 +14,10 @@ * 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 #include #include -- cgit v1.2.3 From b99e552907981fc5230ba71b3e4ada3eee6e7e08 Mon Sep 17 00:00:00 2001 From: "dfilimon@google.com" Date: Fri, 16 Sep 2011 01:30:38 +0000 Subject: Assignment operator fix for IdFilter. git-svn-id: http://sfntly.googlecode.com/svn/trunk/cpp/src@83 672e30a5-4c29-85ac-ac6d-611c735e0a51 --- sfntly/table/core/cmap_table.h | 1 + 1 file changed, 1 insertion(+) diff --git a/sfntly/table/core/cmap_table.h b/sfntly/table/core/cmap_table.h index bbdc7b5..326236f 100644 --- a/sfntly/table/core/cmap_table.h +++ b/sfntly/table/core/cmap_table.h @@ -91,6 +91,7 @@ public: ~CMapIdFilter() {} virtual bool accept(const CMapId& cmap_id) const; private: + CMapId& operator=(const CMapId& that); const CMapId wanted_id_; const CMapIdComparator *comparator_; }; -- cgit v1.2.3 From f01bd0d3b63716aefcc01ca3250d4bce2be09fcd Mon Sep 17 00:00:00 2001 From: "dfilimon@google.com" Date: Fri, 16 Sep 2011 01:34:15 +0000 Subject: Typo in last commit. git-svn-id: http://sfntly.googlecode.com/svn/trunk/cpp/src@84 672e30a5-4c29-85ac-ac6d-611c735e0a51 --- sfntly/table/core/cmap_table.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sfntly/table/core/cmap_table.h b/sfntly/table/core/cmap_table.h index 326236f..f002ddc 100644 --- a/sfntly/table/core/cmap_table.h +++ b/sfntly/table/core/cmap_table.h @@ -91,7 +91,7 @@ public: ~CMapIdFilter() {} virtual bool accept(const CMapId& cmap_id) const; private: - CMapId& operator=(const CMapId& that); + CMapIdFilter& operator=(const CMapIdFilter& that); const CMapId wanted_id_; const CMapIdComparator *comparator_; }; -- cgit v1.2.3 From a8be98eb7c7b56644732b866346cf8b852592170 Mon Sep 17 00:00:00 2001 From: "dfilimon@google.com" Date: Sat, 17 Sep 2011 22:39:06 +0000 Subject: Adding support for CMapFormat4. git-svn-id: http://sfntly.googlecode.com/svn/trunk/cpp/src@85 672e30a5-4c29-85ac-ac6d-611c735e0a51 --- sfntly/table/core/cmap_table.cc | 534 +++++++++++++++++++++++++++++++++++++++- sfntly/table/core/cmap_table.h | 179 ++++++++++++++ test/cmap_editing_test.cc | 101 ++++++++ test/cmap_iterator_test.cc | 156 ++++++++++++ test/cmap_test.cc | 212 ++++++++++++++++ 5 files changed, 1172 insertions(+), 10 deletions(-) create mode 100644 test/cmap_editing_test.cc create mode 100644 test/cmap_iterator_test.cc create mode 100644 test/cmap_test.cc diff --git a/sfntly/table/core/cmap_table.cc b/sfntly/table/core/cmap_table.cc index 9df1158..bfc7f86 100644 --- a/sfntly/table/core/cmap_table.cc +++ b/sfntly/table/core/cmap_table.cc @@ -261,10 +261,7 @@ CALLER_ATTACH CMapTable::CMap::Builder* #endif break; case CMapFormat::kFormat4: -#if defined (SFNTLY_DEBUG_CMAP) - fprintf(stderr, "Requesting Format4 builder, but it's unsupported; " - "returning NULL\n"); -#endif + builder.Attach(CMapFormat4::Builder::NewInstance(data, offset, cmap_id)); break; default: #ifdef SFNTLY_DEBUG_CMAP @@ -289,10 +286,7 @@ CMapTable::CMap::Builder::GetBuilder(int32_t format, const CMapId& cmap_id) { #endif break; case CMapFormat::kFormat4: -#if defined (SFNTLY_DEBUG_CMAP) - fprintf(stderr, "Requesting Format4 builder, but it's unsupported; " - "returning NULL\n"); -#endif + builder.Attach(CMapFormat4::Builder::NewInstance(cmap_id)); break; default: #ifdef SFNTLY_DEBUG_CMAP @@ -594,15 +588,535 @@ CALLER_ATTACH FontDataTable* return table.Detach(); } +/****************************************************************************** + * CMapTable::CMapFormat4 + ******************************************************************************/ +CMapTable::CMapFormat4::CMapFormat4(ReadableFontData* data, + const CMapId& cmap_id) + : CMapTable::CMap::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) { + 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) { +} + +CMapTable::CMapFormat4::Builder::Builder(WritableFontData* data, int32_t offset, + const CMapId& cmap_id) + : CMap::Builder(data, CMapFormat::kFormat4, cmap_id) { +} + +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) { + : SubTableContainerTable::Builder(header, data), version_(0) { } CMapTable::Builder::Builder(Header* header, ReadableFontData* data) - : SubTableContainerTable::Builder(header, data) { + : SubTableContainerTable::Builder(header, data), version_(0) { } CMapTable::Builder::~Builder() { diff --git a/sfntly/table/core/cmap_table.h b/sfntly/table/core/cmap_table.h index f002ddc..29ce3e4 100644 --- a/sfntly/table/core/cmap_table.h +++ b/sfntly/table/core/cmap_table.h @@ -316,6 +316,184 @@ public: 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 { @@ -527,6 +705,7 @@ public: }; 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/test/cmap_editing_test.cc b/test/cmap_editing_test.cc new file mode 100644 index 0000000..6df2720 --- /dev/null +++ b/test/cmap_editing_test.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 +#include + +#include "sfntly/font.h" +#include "sfntly/font_factory.h" +#include "sfntly/table/core/font_header_table.h" +#include "sfntly/tag.h" +#include "sfntly/data/memory_byte_array.h" +#include "sfntly/port/endian.h" +#include "sfntly/port/file_input_stream.h" +#include "sfntly/port/memory_output_stream.h" +#include "test/test_data.h" +#include "test/test_font_utils.h" +#include "sfntly/table/core/cmap_table.h" +#include "sfntly/port/refcount.h" +#include "gtest/gtest.h" + +namespace sfntly { +TEST(CMapEditingTest, RemoveAllButOneCMap) { + FontBuilderArray builders; + FontFactoryPtr font_factory; + font_factory.Attach(FontFactory::GetInstance()); + BuilderForFontFile(SAMPLE_TTF_FILE, font_factory, &builders); + ASSERT_FALSE(builders.empty()); + FontBuilderPtr font_builder = builders[0]; + Ptr cmap_table_builder = + (CMapTable::Builder*)font_builder->GetTableBuilder(Tag::cmap); + ASSERT_NE(cmap_table_builder, reinterpret_cast(NULL)); + CMapTable::CMapBuilderMap* + cmap_builders = cmap_table_builder->GetCMapBuilders(); + ASSERT_FALSE(cmap_builders->empty()); + + for (CMapTable::CMapBuilderMap::iterator + it = cmap_builders->begin(); it != cmap_builders->end();) { + if (it->second->cmap_id() == CMapTable::WINDOWS_BMP) { + ++it; + } else { + cmap_builders->erase(it++); + } + } + ASSERT_EQ(cmap_builders->size(), (uint32_t)1); + Font* font = font_builder->Build(); + CMapTablePtr cmap_table = down_cast(font->GetTable(Tag::cmap)); + ASSERT_EQ(1, cmap_table->NumCMaps()); + CMapTable::CMapPtr cmap; + cmap.Attach(cmap_table->GetCMap(CMapTable::WINDOWS_BMP)); + ASSERT_EQ(CMapTable::WINDOWS_BMP, cmap->cmap_id()); + delete font; +} + +TEST(CMapEditingTest, CopyAllCMapsToNewFont) { + FontArray fonts; + FontFactoryPtr font_factory; + font_factory.Attach(FontFactory::GetInstance()); + LoadFont(SAMPLE_TTF_FILE, font_factory, &fonts); + + ASSERT_FALSE(fonts.empty()); + ASSERT_FALSE(fonts[0] == NULL); + FontPtr font = fonts[0]; + CMapTablePtr cmap_table = down_cast(font->GetTable(Tag::cmap)); + FontBuilderPtr font_builder; + font_builder.Attach(font_factory->NewFontBuilder()); + Ptr cmap_table_builder = + (CMapTable::Builder*)font_builder->NewTableBuilder(Tag::cmap); + + CMapTable::CMapIterator cmap_iter(cmap_table, NULL); + while (cmap_iter.HasNext()) { + CMapTable::CMapPtr cmap; + cmap.Attach(cmap_iter.Next()); + if (!cmap) + continue; + cmap_table_builder->NewCMapBuilder(cmap->cmap_id(), cmap->ReadFontData()); + } + + FontPtr new_font; + new_font.Attach(font_builder->Build()); + CMapTablePtr new_cmap_table = + down_cast(font->GetTable(Tag::cmap)); + ASSERT_EQ(cmap_table->NumCMaps(), new_cmap_table->NumCMaps()); + CMapTable::CMapPtr cmap; + cmap.Attach(cmap_table->GetCMap(CMapTable::WINDOWS_BMP)); + ASSERT_NE(cmap, reinterpret_cast(NULL)); + ASSERT_EQ(CMapTable::WINDOWS_BMP, cmap->cmap_id()); +} +} diff --git a/test/cmap_iterator_test.cc b/test/cmap_iterator_test.cc new file mode 100644 index 0000000..2e8e6fe --- /dev/null +++ b/test/cmap_iterator_test.cc @@ -0,0 +1,156 @@ +/* + * 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 + +#include "sfntly/font.h" +#include "sfntly/font_factory.h" +#include "sfntly/table/core/cmap_table.h" +#include "sfntly/tag.h" +#include "sfntly/port/type.h" +#include "sfntly/port/refcount.h" +#include "test/test_data.h" +#include "test/test_font_utils.h" + +#include "gtest/gtest.h" + +#if GTEST_HAS_PARAM_TEST + +namespace sfntly { +using ::testing::TestWithParam; +using ::testing::Values; + +typedef std::vector BitSet; + +class CMapIteratorTestCase { + public: + CMapIteratorTestCase(int32_t platform_id, int32_t encoding_id, + const char* file_name) + : platform_id_(platform_id), + encoding_id_(encoding_id), + file_name_(file_name) { + } + ~CMapIteratorTestCase() {} + int32_t platform_id() const { return platform_id_; } + int32_t encoding_id() const { return encoding_id_; } + const char* file_name() const { return file_name_; } + + private: + int32_t platform_id_; + int32_t encoding_id_; + const char* file_name_; +}; + +class CMapIteratorTests + : public ::testing::TestWithParam { + public: + virtual void SetUp(); + virtual void TearDown() {} + + BitSet* GenerateCMapEntries(int32_t start, int32_t count); + int32_t CompareCMapIterAndBitSet(CMapTable::CMap::CharacterIterator* + character_iterator, + BitSet* bit_set); + + Ptr cmap_; +}; + +void CMapIteratorTests::SetUp() { + FontArray fonts; + Ptr font_factory; + const char* file_name = GetParam().file_name(); + LoadFont(file_name, font_factory, &fonts); + Ptr font; + font.Attach(fonts[0].Detach()); + Ptr cmap_table = down_cast(font->GetTable(Tag::cmap)); + ASSERT_FALSE(cmap_table == NULL); + cmap_.Attach(cmap_table->GetCMap(GetParam().platform_id(), + GetParam().encoding_id())); + ASSERT_FALSE(cmap_ == NULL); +} + +BitSet* CMapIteratorTests::GenerateCMapEntries(int32_t start, int32_t count) { + BitSet* entries = new BitSet(count); + for (int32_t c = start; c < start + count; ++c) { + int32_t g = cmap_->GlyphId(c); + if (g != CMapTable::NOTDEF) + (*entries)[c] = true; + } + return entries; +} + +int32_t +CMapIteratorTests:: +CompareCMapIterAndBitSet(CMapTable::CMap::CharacterIterator* character_iterator, + BitSet* bit_set) { + int32_t iterator_not_bitset_count = 0; + BitSet::iterator end = bit_set->end(), + beginning = bit_set->begin(), + init_beginning = beginning, + current = std::find(beginning, end, true); + for (int32_t next_bit = current - beginning; + character_iterator->HasNext() && current != end; + next_bit = current - init_beginning) { + int32_t c = character_iterator->Next(); + EXPECT_TRUE(c <= next_bit || current == end); + if (!(c <= next_bit || current == end)) + return -1; + if (c == next_bit) { + beginning = current + 1; + current = std::find(beginning, end, true); + } else { + iterator_not_bitset_count++; + } + } + EXPECT_EQ(end, current); +#if defined (SFNTLY_DEBUG_CMAP) + fprintf(stderr, "%s %d: Differences between iterator and bitset: %d\n", + cmap_->format(), GetParam().file_name(), iterator_not_bitset_count); +#endif + return iterator_not_bitset_count; +} + +TEST_P(CMapIteratorTests, IteratorTest) { + BitSet* bit_set = GenerateCMapEntries(0, 0x10ffff); + CMapTable::CMap::CharacterIterator* character_iterator = NULL; + character_iterator = cmap_->Iterator(); + EXPECT_NE(character_iterator, + reinterpret_cast(NULL)); + CompareCMapIterAndBitSet(character_iterator, bit_set); + delete character_iterator; + delete bit_set; +} + +CMapIteratorTestCase kCMapIteratorTestsTestCases[] = { + CMapIteratorTestCase(CMapTable::WINDOWS_BMP.platform_id, + CMapTable::WINDOWS_BMP.encoding_id, + SAMPLE_TTF_FILE) +}; + +INSTANTIATE_TEST_CASE_P(CMapIteratorTests, + CMapIteratorTests, + ::testing::ValuesIn(kCMapIteratorTestsTestCases)); +} + +#else + +TEST(DummyTest, ValueParameterizedTestsAreNotSupportedOnThisPlatform) {} + +#endif // GTEST_HAS_PARAM diff --git a/test/cmap_test.cc b/test/cmap_test.cc new file mode 100644 index 0000000..f870184 --- /dev/null +++ b/test/cmap_test.cc @@ -0,0 +1,212 @@ +/* + * 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 + +#include "gtest/gtest.h" +#include "sfntly/font.h" +#include "sfntly/font_factory.h" +#include "sfntly/table/core/cmap_table.h" +#include "sfntly/data/memory_byte_array.h" +#include "sfntly/table/core/font_header_table.h" +#include "sfntly/tag.h" + +#include "test/test_utils.h" +#include "test/test_font_utils.h" +#include "test/test_data.h" + +#if GTEST_HAS_PARAM_TEST + +namespace sfntly { +using ::testing::TestWithParam; +using ::testing::Values; + +class CMapTestCase { + public: + CMapTestCase(const char* font_name, + int32_t first_platform_id, + int32_t first_encoding_id, + const char* first_charset_name, + int32_t second_platform_id, + int32_t second_encoding_id, + const char* second_charset_name, + int32_t low_char, + int32_t high_char) + : font_name_(font_name), + first_platform_id_(first_platform_id), + first_encoding_id_(first_encoding_id), + first_charset_name_(first_charset_name), + second_platform_id_(second_platform_id), + second_encoding_id_(second_encoding_id), + second_charset_name_(second_charset_name), + low_char_(low_char), + high_char_(high_char) { + } + + const char* font_name() const { return font_name_; } + int32_t first_platform_id() const { return first_platform_id_; } + int32_t first_encoding_id() const { return first_encoding_id_; } + const char* first_charset_name() const { return first_charset_name_; } + int32_t second_platform_id() const { return second_platform_id_; } + int32_t second_encoding_id() const { return second_encoding_id_; } + const char* second_charset_name() const { return second_charset_name_; } + int32_t low_char() const { return low_char_; } + int32_t high_char() const { return high_char_; } + + private: + const char* font_name_; + int32_t first_platform_id_; + int32_t first_encoding_id_; + const char* first_charset_name_; + int32_t second_platform_id_; + int32_t second_encoding_id_; + const char* second_charset_name_; + int32_t low_char_; + int32_t high_char_; +}; + +class CMapTests : public :: testing::TestWithParam { + public: + CMapTests() : encoder1_(NULL), encoder2_(NULL), successful_setup_(false) { + } + virtual void SetUp() {} + virtual void TearDown(); + + void CommonSetUp(FontArray* font_array); + + void CompareCMaps(); + + Ptr cmap1_; + Ptr cmap2_; + UConverter* encoder1_; + UConverter* encoder2_; + bool successful_setup_; +}; + +::std::ostream& operator<<(::std::ostream& os, const CMapTestCase *test_case) { + return os << "(" + << test_case->font_name() << ", " + << test_case->first_platform_id() << ", " + << test_case->first_encoding_id() << ", " + << test_case->first_charset_name() << ", " + << test_case->second_platform_id() << ", " + << test_case->second_encoding_id() << ", " + << test_case->second_charset_name() << ", " + << test_case->low_char() << ", " + << test_case->high_char() << ")"; +} + +void CMapTests::CommonSetUp(FontArray* font_array) { + ASSERT_NE(font_array, reinterpret_cast(NULL)); + ASSERT_FALSE(font_array->empty()); + Ptr font; + font = font_array->at(0); + ASSERT_NE(font, reinterpret_cast(NULL)); + Ptr cmap_table = + down_cast(font->GetTable(Tag::cmap)); + cmap1_.Attach(cmap_table->GetCMap(GetParam().first_platform_id(), + GetParam().first_encoding_id())); + ASSERT_NE((cmap1_), reinterpret_cast(NULL)); + cmap2_.Attach(cmap_table->GetCMap(GetParam().second_platform_id(), + GetParam().second_encoding_id())); + ASSERT_NE((cmap2_), reinterpret_cast(NULL)); + encoder1_ = TestUtils::GetEncoder(GetParam().first_charset_name()); + encoder2_ = TestUtils::GetEncoder(GetParam().second_charset_name()); + successful_setup_ = true; +} + +void CMapTests::TearDown() { + if (encoder1_) + ucnv_close(encoder1_); + if (encoder2_) + ucnv_close(encoder2_); +} + +void CMapTests::CompareCMaps() { + ASSERT_TRUE(successful_setup_); + for (int32_t uchar = GetParam().low_char(); + uchar <= GetParam().high_char(); ++uchar) { + int32_t c1 = uchar; + if (encoder1_ != NULL) + c1 = TestUtils::EncodeOneChar(encoder1_, uchar); + int32_t c2 = uchar; + if (encoder2_ != NULL) + c2 = TestUtils::EncodeOneChar(encoder2_, uchar); + int32_t glyph_id1 = cmap1_->GlyphId(c1); + int32_t glyph_id2 = cmap2_->GlyphId(c2); +#ifdef SFNTLY_DEBUG_CMAP + if (glyph_id1 != glyph_id2) + fprintf(stderr, "%x: g1=%x, %x: g2=%x\n", c1, glyph_id1, c2, glyph_id2); +#endif + ASSERT_EQ(glyph_id1, glyph_id2); + } +#ifdef SFNTLY_SFNTLY_DEBUG_CMAPCMAP + fprintf(stderr, "\n"); +#endif +} + +TEST_P(CMapTests, GlyphsBetweenCMapsFingerprint) { + Ptr font_factory; + font_factory.Attach(FontFactory::GetInstance()); + font_factory->FingerprintFont(true); + FontArray font_array; + LoadFont(GetParam().font_name(), font_factory, &font_array); + CommonSetUp(&font_array); + CompareCMaps(); +} + +TEST_P(CMapTests, GlyphsBetweenCMapsNoFingerprint) { + Ptr font_factory; + font_factory.Attach(FontFactory::GetInstance()); + FontArray font_array; + LoadFont(GetParam().font_name(), font_factory, &font_array); + CommonSetUp(&font_array); + CompareCMaps(); +} + +TEST_P(CMapTests, GlyphsBetweenCMapsUsingByteVector) { + FontArray font_array; + LoadFontUsingByteVector(GetParam().font_name(), true, &font_array); + CommonSetUp(&font_array); + CompareCMaps(); +} + +CMapTestCase kCMapTestsTestCases[] = { + CMapTestCase(SAMPLE_TTF_FILE, + PlatformId::kWindows, + WindowsEncodingId::kUnicodeUCS2, + NULL, + PlatformId::kUnicode, + UnicodeEncodingId::kUnicode2_0_BMP, + NULL, + (int32_t)0x20, + (int32_t)0x7f), +}; + +INSTANTIATE_TEST_CASE_P(CMapTests, + CMapTests, + ::testing::ValuesIn(kCMapTestsTestCases)); +} + +#else + +TEST(DummyTest, ValueParameterizedTestsAreNotSupportedOnThisPlatform) {} + +#endif // GTEST_HAS_PARAM -- cgit v1.2.3 From 7bb24d45ed7d04c85f27ecdc3866153a8350ed44 Mon Sep 17 00:00:00 2001 From: "dfilimon@google.com" Date: Sat, 17 Sep 2011 22:58:38 +0000 Subject: Fixing compile errors on Windows. git-svn-id: http://sfntly.googlecode.com/svn/trunk/cpp/src@86 672e30a5-4c29-85ac-ac6d-611c735e0a51 --- sfntly/table/core/cmap_table.cc | 2 +- test/cmap_test.cc | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/sfntly/table/core/cmap_table.cc b/sfntly/table/core/cmap_table.cc index bfc7f86..6911660 100644 --- a/sfntly/table/core/cmap_table.cc +++ b/sfntly/table/core/cmap_table.cc @@ -593,7 +593,7 @@ CALLER_ATTACH FontDataTable* ******************************************************************************/ CMapTable::CMapFormat4::CMapFormat4(ReadableFontData* data, const CMapId& cmap_id) - : CMapTable::CMap::CMap(data, CMapFormat::kFormat4, cmap_id), + : CMap(data, CMapFormat::kFormat4, cmap_id), seg_count_(SegCount(data)), start_code_offset_(StartCodeOffset(seg_count_)), end_code_offset_(Offset::kFormat4EndCount), diff --git a/test/cmap_test.cc b/test/cmap_test.cc index f870184..e67137c 100644 --- a/test/cmap_test.cc +++ b/test/cmap_test.cc @@ -14,6 +14,7 @@ * limitations under the License. */ +#include "sfntly/port/type.h" #include #include -- cgit v1.2.3 From ce2471a4cd4a9d39f3e761bfe6739fb454bf0dc3 Mon Sep 17 00:00:00 2001 From: "dfilimon@google.com" Date: Sat, 17 Sep 2011 23:04:28 +0000 Subject: Fixing Windows build, round 2. git-svn-id: http://sfntly.googlecode.com/svn/trunk/cpp/src@87 672e30a5-4c29-85ac-ac6d-611c735e0a51 --- sfntly/table/core/cmap_table.cc | 3 +++ 1 file changed, 3 insertions(+) diff --git a/sfntly/table/core/cmap_table.cc b/sfntly/table/core/cmap_table.cc index 6911660..0b4f89a 100644 --- a/sfntly/table/core/cmap_table.cc +++ b/sfntly/table/core/cmap_table.cc @@ -686,6 +686,7 @@ int32_t CMapTable::CMapFormat4::StartCodeOffset(int32_t seg_count) { 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; @@ -946,11 +947,13 @@ CMapTable::CMapFormat4::Builder::NewInstance(const CMapId& 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, -- cgit v1.2.3 From 15c65e73fa282ac33c3d4e464ceed659672d4c7e Mon Sep 17 00:00:00 2001 From: "dfilimon@google.com" Date: Sat, 17 Sep 2011 23:09:54 +0000 Subject: Fixind Windows build, round 3. git-svn-id: http://sfntly.googlecode.com/svn/trunk/cpp/src@88 672e30a5-4c29-85ac-ac6d-611c735e0a51 --- test/cmap_test.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/cmap_test.cc b/test/cmap_test.cc index e67137c..02bf8a2 100644 --- a/test/cmap_test.cc +++ b/test/cmap_test.cc @@ -146,10 +146,10 @@ void CMapTests::CompareCMaps() { uchar <= GetParam().high_char(); ++uchar) { int32_t c1 = uchar; if (encoder1_ != NULL) - c1 = TestUtils::EncodeOneChar(encoder1_, uchar); + c1 = TestUtils::EncodeOneChar(encoder1_, (int16_t)uchar); int32_t c2 = uchar; if (encoder2_ != NULL) - c2 = TestUtils::EncodeOneChar(encoder2_, uchar); + c2 = TestUtils::EncodeOneChar(encoder2_, (int16_t)uchar); int32_t glyph_id1 = cmap1_->GlyphId(c1); int32_t glyph_id2 = cmap2_->GlyphId(c2); #ifdef SFNTLY_DEBUG_CMAP -- cgit v1.2.3 From 09f3dda615ba59d0b686e8c36f1e8426b9235746 Mon Sep 17 00:00:00 2001 From: "arthurhsu@google.com" Date: Tue, 20 Sep 2011 20:03:14 +0000 Subject: Add atomicity to whereever needed. git-svn-id: http://sfntly.googlecode.com/svn/trunk/cpp/src@89 672e30a5-4c29-85ac-ac6d-611c735e0a51 --- sfntly/data/readable_font_data.cc | 4 ++-- sfntly/data/readable_font_data.h | 5 +++-- sfntly/table/bitmap/bitmap_size_table.cc | 1 + sfntly/table/bitmap/bitmap_size_table.h | 2 ++ sfntly/table/bitmap/eblc_table.cc | 2 +- sfntly/table/bitmap/eblc_table.h | 3 ++- 6 files changed, 11 insertions(+), 6 deletions(-) diff --git a/sfntly/data/readable_font_data.cc b/sfntly/data/readable_font_data.cc index ec67757..fb083cb 100644 --- a/sfntly/data/readable_font_data.cc +++ b/sfntly/data/readable_font_data.cc @@ -14,11 +14,11 @@ * limitations under the License. */ -#include "sfntly/data/memory_byte_array.h" #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" @@ -45,7 +45,7 @@ ReadableFontData* ReadableFontData::CreateReadableFontData(ByteVector* b) { } int64_t ReadableFontData::Checksum() { - // TODO(arthurhsu): IMPLEMENT: atomicity + AutoLock lock(checksum_lock_); if (!checksum_set_) { ComputeChecksum(); } diff --git a/sfntly/data/readable_font_data.h b/sfntly/data/readable_font_data.h index a0d341f..c5833e8 100644 --- a/sfntly/data/readable_font_data.h +++ b/sfntly/data/readable_font_data.h @@ -17,8 +17,8 @@ #ifndef SFNTLY_CPP_SRC_SFNTLY_DATA_READABLE_FONT_DATA_H_ #define SFNTLY_CPP_SRC_SFNTLY_DATA_READABLE_FONT_DATA_H_ -#include "sfntly/port/refcount.h" #include "sfntly/data/font_data.h" +#include "sfntly/port/lock.h" namespace sfntly { @@ -290,7 +290,8 @@ class ReadableFontData : public FontData, // @return the checksum for the total range int64_t ComputeCheckSum(int32_t low_bound, int32_t high_bound); - bool checksum_set_; // TODO(arthurhsu): IMPLEMENT: must be set atomically. + Lock checksum_lock_; + bool checksum_set_; int64_t checksum_; IntegerList checksum_range_; }; diff --git a/sfntly/table/bitmap/bitmap_size_table.cc b/sfntly/table/bitmap/bitmap_size_table.cc index 2b5b9bb..00488ea 100644 --- a/sfntly/table/bitmap/bitmap_size_table.cc +++ b/sfntly/table/bitmap/bitmap_size_table.cc @@ -134,6 +134,7 @@ IndexSubTable* BitmapSizeTable::CreateIndexSubTable(int32_t index) { } IndexSubTableList* BitmapSizeTable::GetIndexSubTableList() { + AutoLock lock(atomic_subtables_lock_); if (atomic_subtables.empty()) { for (int32_t i = 0; i < NumberOfIndexSubTables(); ++i) { IndexSubTablePtr table; diff --git a/sfntly/table/bitmap/bitmap_size_table.h b/sfntly/table/bitmap/bitmap_size_table.h index 3b8e30c..ee58bca 100644 --- a/sfntly/table/bitmap/bitmap_size_table.h +++ b/sfntly/table/bitmap/bitmap_size_table.h @@ -19,6 +19,7 @@ #include +#include "sfntly/port/lock.h" #include "sfntly/table/bitmap/index_sub_table.h" namespace sfntly { @@ -58,6 +59,7 @@ class BitmapSizeTable : public SubTable, IndexSubTableList* GetIndexSubTableList(); ReadableFontDataPtr master_data_; + Lock atomic_subtables_lock_; IndexSubTableList atomic_subtables; }; typedef Ptr BitmapSizeTablePtr; diff --git a/sfntly/table/bitmap/eblc_table.cc b/sfntly/table/bitmap/eblc_table.cc index a198c10..decbadf 100644 --- a/sfntly/table/bitmap/eblc_table.cc +++ b/sfntly/table/bitmap/eblc_table.cc @@ -48,7 +48,7 @@ EblcTable::EblcTable(Header* header, ReadableFontData* data) } BitmapSizeTableList* EblcTable::GetBitmapSizeTableList() { - // TODO(arthurhsu): thread locking. + AutoLock lock(bitmap_size_table_lock_); if (bitmap_size_table_.empty()) { CreateBitmapSizeTable(data_, NumSizes(), &bitmap_size_table_); } diff --git a/sfntly/table/bitmap/eblc_table.h b/sfntly/table/bitmap/eblc_table.h index bf7cb15..84831ef 100644 --- a/sfntly/table/bitmap/eblc_table.h +++ b/sfntly/table/bitmap/eblc_table.h @@ -17,6 +17,7 @@ #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/bitmap_glyph.h" #include "sfntly/table/bitmap/bitmap_size_table.h" #include "sfntly/table/subtable_container_table.h" @@ -145,7 +146,7 @@ class EblcTable : public SubTableContainerTable, int32_t num_sizes, BitmapSizeTableList* output); - // TODO(arthurhsu): this table must be accessed atomically. + Lock bitmap_size_table_lock_; BitmapSizeTableList bitmap_size_table_; }; typedef Ptr EblcTablePtr; -- cgit v1.2.3 From 8c433a9f5819ad995a14c8476c266487c8a82f53 Mon Sep 17 00:00:00 2001 From: "dfilimon@google.com" Date: Wed, 21 Sep 2011 03:56:38 +0000 Subject: Added sample subsetter and merger. git-svn-id: http://sfntly.googlecode.com/svn/trunk/cpp/src@91 672e30a5-4c29-85ac-ac6d-611c735e0a51 --- sample/subtly/character_predicate.cc | 52 +++++++ sample/subtly/character_predicate.h | 68 ++++++++++ sample/subtly/debug_main.cc | 64 +++++++++ sample/subtly/font_assembler.cc | 227 +++++++++++++++++++++++++++++++ sample/subtly/font_assembler.h | 67 +++++++++ sample/subtly/font_info.cc | 256 +++++++++++++++++++++++++++++++++++ sample/subtly/font_info.h | 128 ++++++++++++++++++ sample/subtly/merger.cc | 87 ++++++++++++ sample/subtly/merger.h | 45 ++++++ sample/subtly/merger_main.cc | 69 ++++++++++ sample/subtly/stats.cc | 82 +++++++++++ sample/subtly/stats.h | 40 ++++++ sample/subtly/subsetter.cc | 67 +++++++++ sample/subtly/subsetter.h | 41 ++++++ sample/subtly/subsetter_main.cc | 82 +++++++++++ sample/subtly/utils.cc | 91 +++++++++++++ sample/subtly/utils.h | 38 ++++++ 17 files changed, 1504 insertions(+) create mode 100644 sample/subtly/character_predicate.cc create mode 100644 sample/subtly/character_predicate.h create mode 100644 sample/subtly/debug_main.cc create mode 100644 sample/subtly/font_assembler.cc create mode 100644 sample/subtly/font_assembler.h create mode 100644 sample/subtly/font_info.cc create mode 100644 sample/subtly/font_info.h create mode 100644 sample/subtly/merger.cc create mode 100644 sample/subtly/merger.h create mode 100644 sample/subtly/merger_main.cc create mode 100644 sample/subtly/stats.cc create mode 100644 sample/subtly/stats.h create mode 100644 sample/subtly/subsetter.cc create mode 100644 sample/subtly/subsetter.h create mode 100644 sample/subtly/subsetter_main.cc create mode 100644 sample/subtly/utils.cc create mode 100644 sample/subtly/utils.h diff --git a/sample/subtly/character_predicate.cc b/sample/subtly/character_predicate.cc new file mode 100644 index 0000000..1509260 --- /dev/null +++ b/sample/subtly/character_predicate.cc @@ -0,0 +1,52 @@ +/* + * 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/refcount.h" +#include "subtly/character_predicate.h" + +namespace subtly { +using namespace sfntly; + +// AcceptRange predicate +AcceptRange::AcceptRange(int32_t start, int32_t end) + : start_(start), + end_(end) { +} + +AcceptRange::~AcceptRange() {} + +bool AcceptRange::operator()(int32_t character) const { + return start_ <= character && character <= end_; +} + +// AcceptSet predicate +AcceptSet::AcceptSet(IntegerSet* characters) + : characters_(characters) { +} + +AcceptSet::~AcceptSet() { + delete characters_; +} + +bool AcceptSet::operator()(int32_t character) const { + return characters_->find(character) != characters_->end(); +} + +// AcceptAll predicate +bool AcceptAll::operator()(int32_t character) const { + return true; +} +} diff --git a/sample/subtly/character_predicate.h b/sample/subtly/character_predicate.h new file mode 100644 index 0000000..a6e3ea3 --- /dev/null +++ b/sample/subtly/character_predicate.h @@ -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. + */ + +#ifndef TYPOGRAPHY_FONT_SFNTLY_SRC_SAMPLE_SUBTLY_CHARACTER_PREDICATE_H_ +#define TYPOGRAPHY_FONT_SFNTLY_SRC_SAMPLE_SUBTLY_CHARACTER_PREDICATE_H_ + +#include "sfntly/port/refcount.h" +#include "sfntly/port/type.h" + +namespace subtly { +class CharacterPredicate : virtual public sfntly::RefCount { + public: + CharacterPredicate() {} + virtual ~CharacterPredicate() {} + virtual bool operator()(int32_t character) const = 0; +}; + +// All characters except for those between [start, end] are rejected +class AcceptRange : public CharacterPredicate, + public sfntly::RefCounted { + public: + AcceptRange(int32_t start, int32_t end); + ~AcceptRange(); + virtual bool operator()(int32_t character) const; + + private: + int32_t start_; + int32_t end_; +}; + +// All characters in IntegerSet +// The set is OWNED by the predicate! Do not modify it. +// It will be freed when the predicate is destroyed. +class AcceptSet : public CharacterPredicate, + public sfntly::RefCounted { + public: + explicit AcceptSet(sfntly::IntegerSet* characters); + ~AcceptSet(); + virtual bool operator()(int32_t character) const; + + private: + sfntly::IntegerSet* characters_; +}; + +// All characters +class AcceptAll : public CharacterPredicate, + public sfntly::RefCounted { + public: + AcceptAll() {} + ~AcceptAll() {} + virtual bool operator()(int32_t character) const; +}; +} + +#endif // TYPOGRAPHY_FONT_SFNTLY_SRC_SAMPLE_SUBTLY_CHARACTER_PREDICATE_H_ diff --git a/sample/subtly/debug_main.cc b/sample/subtly/debug_main.cc new file mode 100644 index 0000000..8324cde --- /dev/null +++ b/sample/subtly/debug_main.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 +#include + +#include +#include + +#include "sfntly/font.h" +#include "sfntly/table/core/cmap_table.h" +#include "sfntly/tag.h" +#include "subtly/stats.h" +#include "subtly/subsetter.h" +#include "subtly/utils.h" + +using namespace subtly; + +void PrintUsage(const char* program_name) { + fprintf(stdout, "Usage: %s \n", program_name); +} + +int main(int argc, const char** argv) { + const char* program_name = argv[0]; + if (argc < 2) { + PrintUsage(program_name); + exit(1); + } + + const char* input_font_path = argv[1]; + const char* output_font_path = argv[2]; + FontPtr font; + font.Attach(subtly::LoadFont(input_font_path)); + + int32_t original_size = TotalFontSize(font); + Ptr subsetter = new Subsetter(font, NULL); + Ptr new_font; + new_font.Attach(subsetter->Subset()); + if (!new_font) { + fprintf(stdout, "Cannot create subset.\n"); + return 0; + } + + subtly::SerializeFont(output_font_path, new_font); + subtly::PrintComparison(stdout, font, new_font); + int32_t new_size = TotalFontSize(new_font); + fprintf(stdout, "Went from %d to %d: %lf%% of original\n", + original_size, new_size, + static_cast(new_size) / original_size * 100); + return 0; +} diff --git a/sample/subtly/font_assembler.cc b/sample/subtly/font_assembler.cc new file mode 100644 index 0000000..2f7cd11 --- /dev/null +++ b/sample/subtly/font_assembler.cc @@ -0,0 +1,227 @@ +/* + * 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 "subtly/font_assembler.h" + +#include + +#include +#include + +#include "sfntly/tag.h" +#include "sfntly/font.h" +#include "sfntly/font_factory.h" +#include "sfntly/table/core/cmap_table.h" +#include "sfntly/table/truetype/loca_table.h" +#include "sfntly/table/truetype/glyph_table.h" +#include "sfntly/table/core/maximum_profile_table.h" +#include "sfntly/port/type.h" +#include "sfntly/port/refcount.h" +#include "subtly/font_info.h" + +namespace subtly { +using namespace sfntly; + +FontAssembler::FontAssembler(FontInfo* font_info, + IntegerSet* table_blacklist) + : table_blacklist_(table_blacklist) { + font_info_ = font_info; + Initialize(); +} + +FontAssembler::FontAssembler(FontInfo* font_info) + : table_blacklist_(NULL) { + font_info_ = font_info; + Initialize(); +} + +void FontAssembler::Initialize() { + font_factory_.Attach(sfntly::FontFactory::GetInstance()); + font_builder_.Attach(font_factory_->NewFontBuilder()); +} + +CALLER_ATTACH Font* FontAssembler::Assemble() { + // Assemble tables we can subset. + if (!AssembleCMapTable() || !AssembleGlyphAndLocaTables()) { + return NULL; + } + // For all other tables, either include them unmodified or don't at all. + const TableMap* common_table_map = + font_info_->GetTableMap(font_info_->fonts()->begin()->first); + for (TableMap::const_iterator it = common_table_map->begin(), + e = common_table_map->end(); it != e; ++it) { + if (table_blacklist_ + && table_blacklist_->find(it->first) != table_blacklist_->end()) { + continue; + } + font_builder_->NewTableBuilder(it->first, it->second->ReadFontData()); + } + return font_builder_->Build(); +} + +bool FontAssembler::AssembleCMapTable() { + // Creating the new CMapTable and the new format 4 CMap + Ptr cmap_table_builder = + down_cast + (font_builder_->NewTableBuilder(Tag::cmap)); + if (!cmap_table_builder) + return false; + Ptr cmap_builder = + down_cast + (cmap_table_builder->NewCMapBuilder(CMapFormat::kFormat4, + CMapTable::WINDOWS_BMP)); + if (!cmap_builder) + return false; + // Creating the segments and the glyph id array + CharacterMap* chars_to_glyph_ids = font_info_->chars_to_glyph_ids(); + SegmentList* segment_list = new SegmentList; + IntegerList* glyph_id_array = new IntegerList; + int32_t last_chararacter = -2; + int32_t last_offset = 0; + Ptr current_segment; + + // For simplicity, we will have one segment per contiguous range. + // To test the algorithm, we've replaced the original CMap with the CMap + // generated by this code without removing any character. + // Tuffy.ttf: CMap went from 3146 to 3972 bytes (1.7% to 2.17% of file) + // AnonymousPro.ttf: CMap went from 1524 to 1900 bytes (0.96% to 1.2%) + for (CharacterMap::iterator it = chars_to_glyph_ids->begin(), + e = chars_to_glyph_ids->end(); it != e; ++it) { + int32_t character = it->first; + int32_t glyph_id = it->second.glyph_id(); + if (character != last_chararacter + 1) { // new segment + if (current_segment != NULL) { + current_segment->set_end_count(last_chararacter); + segment_list->push_back(current_segment); + } + // start_code = character + // end_code = -1 (unknown for now) + // id_delta = 0 (we don't use id_delta for this representation) + // id_range_offset = last_offset (offset into the glyph_id_array) + current_segment = + new CMapTable::CMapFormat4::Builder:: + Segment(character, -1, 0, last_offset); + } + glyph_id_array->push_back(glyph_id); + last_offset += DataSize::kSHORT; + last_chararacter = character; + } + // The last segment is still open. + current_segment->set_end_count(last_chararacter); + segment_list->push_back(current_segment); + // Updating the id_range_offset for every segment. + for (int32_t i = 0, num_segs = segment_list->size(); i < num_segs; ++i) { + Ptr segment = segment_list->at(i); + segment->set_id_range_offset(segment->id_range_offset() + + (num_segs - i + 1) * DataSize::kSHORT); + } + // Adding the final, required segment. + current_segment = + new CMapTable::CMapFormat4::Builder::Segment(0xffff, 0xffff, 1, 0); + segment_list->push_back(current_segment); + // Writing the segments and glyph id array to the CMap + cmap_builder->set_segments(segment_list); + cmap_builder->set_glyph_id_array(glyph_id_array); + delete segment_list; + delete glyph_id_array; + return true; +} + +bool FontAssembler::AssembleGlyphAndLocaTables() { + Ptr loca_table_builder = + down_cast + (font_builder_->NewTableBuilder(Tag::loca)); + Ptr glyph_table_builder = + down_cast + (font_builder_->NewTableBuilder(Tag::glyf)); + + GlyphIdSet* resolved_glyph_ids = font_info_->resolved_glyph_ids(); + IntegerList loca_list; + // Basic sanity check: all LOCA tables are of the same size + // This is necessary but not suficient! + int32_t previous_size = -1; + for (FontIdMap::iterator it = font_info_->fonts()->begin(); + it != font_info_->fonts()->end(); ++it) { + Ptr loca_table = + down_cast(font_info_->GetTable(it->first, Tag::loca)); + int32_t current_size = loca_table->header_length(); + if (previous_size != -1 && current_size != previous_size) { + return false; + } + previous_size = current_size; + } + + // Assuming all fonts referenced by the FontInfo are the subsets of the same + // font, their loca tables should all have the same sizes. + // We'll just get the size of the first font's LOCA table for simplicty. + Ptr first_loca_table = + down_cast + (font_info_->GetTable(font_info_->fonts()->begin()->first, Tag::loca)); + int32_t num_loca_glyphs = first_loca_table->num_glyphs(); + loca_list.resize(num_loca_glyphs); + loca_list.push_back(0); + int32_t last_glyph_id = 0; + int32_t last_offset = 0; + GlyphTable::GlyphBuilderList* glyph_builders = + glyph_table_builder->GlyphBuilders(); + + for (GlyphIdSet::iterator it = resolved_glyph_ids->begin(), + e = resolved_glyph_ids->end(); it != e; ++it) { + // Get the glyph for this resolved_glyph_id. + int32_t resolved_glyph_id = it->glyph_id(); + int32_t font_id = it->font_id(); + // Get the LOCA table for the current glyph id. + Ptr loca_table = + down_cast + (font_info_->GetTable(font_id, Tag::loca)); + int32_t length = loca_table->GlyphLength(resolved_glyph_id); + int32_t offset = loca_table->GlyphOffset(resolved_glyph_id); + + // Get the GLYF table for the current glyph id. + Ptr glyph_table = + down_cast + (font_info_->GetTable(font_id, Tag::glyf)); + GlyphPtr glyph; + glyph.Attach(glyph_table->GetGlyph(offset, length)); + + // The data reference by the glyph is copied into a new glyph and + // added to the glyph_builders belonging to the glyph_table_builder. + // When Build gets called, all the glyphs will be built. + Ptr data = glyph->ReadFontData(); + Ptr 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); + + // If there are missing glyphs between the last glyph_id and the + // current resolved_glyph_id, since the LOCA table needs to have the same + // size, the offset is kept the same. + for (int32_t i = last_glyph_id + 1; i <= resolved_glyph_id; ++i) + loca_list[i] = last_offset; + last_offset += length; + loca_list[resolved_glyph_id + 1] = last_offset; + last_glyph_id = resolved_glyph_id + 1; + } + // If there are missing glyph ids, their loca entries must all point + // to the same offset as the last valid glyph id making them all zero length. + for (int32_t i = last_glyph_id + 1; i <= num_loca_glyphs; ++i) + loca_list[i] = last_offset; + loca_table_builder->SetLocaList(&loca_list); + return true; +} +} diff --git a/sample/subtly/font_assembler.h b/sample/subtly/font_assembler.h new file mode 100644 index 0000000..c53c21f --- /dev/null +++ b/sample/subtly/font_assembler.h @@ -0,0 +1,67 @@ +/* + * 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_SAMPLE_SUBTLY_FONT_ASSEMBLER_H_ +#define TYPOGRAPHY_FONT_SFNTLY_SRC_SAMPLE_SUBTLY_FONT_ASSEMBLER_H_ + +#include +#include + +#include "subtly/font_info.h" + +#include "sfntly/tag.h" +#include "sfntly/font.h" +#include "sfntly/port/type.h" +#include "sfntly/port/refcount.h" +#include "sfntly/table/core/cmap_table.h" +#include "sfntly/table/truetype/glyph_table.h" +#include "sfntly/table/truetype/loca_table.h" + +namespace subtly { +// Assembles FontInfo into font builders. +// Does not take ownership of data passed to it. +class FontAssembler : public sfntly::RefCounted { + public: + // font_info is the FontInfo which will be used for the new font + // table_blacklist is used to decide which tables to exclude from the + // final font. + FontAssembler(FontInfo* font_info, sfntly::IntegerSet* table_blacklist); + explicit FontAssembler(FontInfo* font_info); + ~FontAssembler() { } + + // Assemble a new font from the font info object. + virtual CALLER_ATTACH sfntly::Font* Assemble(); + + sfntly::IntegerSet* table_blacklist() const { return table_blacklist_; } + void set_table_blacklist(sfntly::IntegerSet* table_blacklist) { + table_blacklist_ = table_blacklist; + } + + protected: + virtual bool AssembleCMapTable(); + virtual bool AssembleGlyphAndLocaTables(); + + virtual void Initialize(); + + private: + sfntly::Ptr font_info_; + sfntly::Ptr font_factory_; + sfntly::Ptr font_builder_; + sfntly::IntegerSet* table_blacklist_; +}; +} + +#endif // TYPOGRAPHY_FONT_SFNTLY_SRC_SAMPLE_SUBTLY_FONT_ASSEMBLER_H_ diff --git a/sample/subtly/font_info.cc b/sample/subtly/font_info.cc new file mode 100644 index 0000000..6eb6a38 --- /dev/null +++ b/sample/subtly/font_info.cc @@ -0,0 +1,256 @@ +/* + * 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 "subtly/font_info.h" + +#include + +#include +#include + +#include "subtly/character_predicate.h" + +#include "sfntly/tag.h" +#include "sfntly/font.h" +#include "sfntly/font_factory.h" +#include "sfntly/table/core/cmap_table.h" +#include "sfntly/table/truetype/loca_table.h" +#include "sfntly/table/truetype/glyph_table.h" +#include "sfntly/table/core/maximum_profile_table.h" +#include "sfntly/port/type.h" +#include "sfntly/port/refcount.h" + +namespace subtly { +using namespace sfntly; +/****************************************************************************** + * GlyphId class + ******************************************************************************/ +GlyphId::GlyphId(int32_t glyph_id, FontId font_id) + : glyph_id_(glyph_id), + font_id_(font_id) { +} + +bool GlyphId::operator==(const GlyphId& other) const { + return glyph_id_ == other.glyph_id(); +} + +bool GlyphId::operator<(const GlyphId& other) const { + return glyph_id_ < other.glyph_id(); +} + +/****************************************************************************** + * FontInfo class + ******************************************************************************/ +FontInfo::FontInfo() + : chars_to_glyph_ids_(new CharacterMap), + resolved_glyph_ids_(new GlyphIdSet), + fonts_(new FontIdMap) { +} + +FontInfo::FontInfo(CharacterMap* chars_to_glyph_ids, + GlyphIdSet* resolved_glyph_ids, + FontIdMap* fonts) { + chars_to_glyph_ids_ = new CharacterMap(chars_to_glyph_ids->begin(), + chars_to_glyph_ids->end()); + resolved_glyph_ids_ = new GlyphIdSet(resolved_glyph_ids->begin(), + resolved_glyph_ids->end()); + fonts_ = new FontIdMap(fonts->begin(), fonts->end()); +} + +FontInfo::~FontInfo() { + delete chars_to_glyph_ids_; + delete resolved_glyph_ids_; + delete fonts_; +} + +FontDataTable* FontInfo::GetTable(FontId font_id, int32_t tag) { + if (!fonts_) + return NULL; + FontIdMap::iterator it = fonts_->find(font_id); + if (it == fonts_->end()) + return NULL; + return it->second->GetTable(tag); +} + +const TableMap* FontInfo::GetTableMap(FontId font_id) { + if (!fonts_) + return NULL; + FontIdMap::iterator it = fonts_->find(font_id); + if (it == fonts_->end()) + return NULL; + return it->second->GetTableMap(); +} + +void FontInfo::set_chars_to_glyph_ids(CharacterMap* chars_to_glyph_ids) { + *chars_to_glyph_ids_ = *chars_to_glyph_ids; +} + +void FontInfo::set_resolved_glyph_ids(GlyphIdSet* resolved_glyph_ids) { + *resolved_glyph_ids_ = *resolved_glyph_ids; +} + +void FontInfo::set_fonts(FontIdMap* fonts) { + *fonts_ = *fonts; +} + +/****************************************************************************** + * FontSourcedInfoBuilder class + ******************************************************************************/ +FontSourcedInfoBuilder::FontSourcedInfoBuilder(Font* font, FontId font_id) + : font_(font), + font_id_(font_id), + predicate_(NULL) { + Initialize(); +} + +FontSourcedInfoBuilder::FontSourcedInfoBuilder(Font* font, + FontId font_id, + CharacterPredicate* predicate) + : font_(font), + font_id_(font_id), + predicate_(predicate) { + Initialize(); +} + +void FontSourcedInfoBuilder::Initialize() { + Ptr cmap_table = down_cast(font_->GetTable(Tag::cmap)); + // We prefer Windows BMP format 4 cmaps. + cmap_.Attach(cmap_table->GetCMap(CMapTable::WINDOWS_BMP)); + // But if none is found, + if (!cmap_) { + return; + } + loca_table_ = down_cast(font_->GetTable(Tag::loca)); + glyph_table_ = down_cast(font_->GetTable(Tag::glyf)); +} + +CALLER_ATTACH FontInfo* FontSourcedInfoBuilder::GetFontInfo() { + CharacterMap* chars_to_glyph_ids = new CharacterMap; + bool success = GetCharacterMap(chars_to_glyph_ids); + if (!success) { + delete chars_to_glyph_ids; +#if defined (SUBTLY_DEBUG) + fprintf(stderr, "Error creating character map.\n"); +#endif + return NULL; + } + GlyphIdSet* resolved_glyph_ids = new GlyphIdSet; + success = ResolveCompositeGlyphs(chars_to_glyph_ids, resolved_glyph_ids); + if (!success) { + delete chars_to_glyph_ids; + delete resolved_glyph_ids; +#if defined (SUBTLY_DEBUG) + fprintf(stderr, "Error resolving composite glyphs.\n"); +#endif + return NULL; + } + Ptr font_info = new FontInfo; + font_info->set_chars_to_glyph_ids(chars_to_glyph_ids); + font_info->set_resolved_glyph_ids(resolved_glyph_ids); + FontIdMap* font_id_map = new FontIdMap; + font_id_map->insert(std::make_pair(font_id_, font_)); + font_info->set_fonts(font_id_map); + delete chars_to_glyph_ids; + delete resolved_glyph_ids; + delete font_id_map; + return font_info.Detach(); +} + +bool FontSourcedInfoBuilder::GetCharacterMap(CharacterMap* chars_to_glyph_ids) { + if (!cmap_ || !chars_to_glyph_ids) + return false; + chars_to_glyph_ids->clear(); + CMapTable::CMap::CharacterIterator* character_iterator = cmap_->Iterator(); + if (!character_iterator) + return false; + while (character_iterator->HasNext()) { + int32_t character = character_iterator->Next(); + if (!predicate_ || (*predicate_)(character)) { + chars_to_glyph_ids->insert + (std::make_pair(character, + GlyphId(cmap_->GlyphId(character), font_id_))); + } + } + delete character_iterator; + return true; +} + +bool +FontSourcedInfoBuilder::ResolveCompositeGlyphs(CharacterMap* chars_to_glyph_ids, + GlyphIdSet* resolved_glyph_ids) { + if (!chars_to_glyph_ids || !resolved_glyph_ids) + return false; + resolved_glyph_ids->clear(); + resolved_glyph_ids->insert(GlyphId(0, font_id_)); + IntegerSet* unresolved_glyph_ids = new IntegerSet; + // Since composite glyph elements might themselves be composite, we would need + // to recursively resolve the elements too. To avoid the recursion we + // create two sets, |unresolved_glyph_ids| for the unresolved glyphs, + // initially containing all the ids and |resolved_glyph_ids|, initially empty. + // We'll remove glyph ids from |unresolved_glyph_ids| until it is empty and, + // if the glyph is composite, add its elements to the unresolved set. + for (CharacterMap::iterator it = chars_to_glyph_ids->begin(), + e = chars_to_glyph_ids->end(); it != e; ++it) { + unresolved_glyph_ids->insert(it->second.glyph_id()); + } + // As long as there are unresolved glyph ids. + while (!unresolved_glyph_ids->empty()) { + // Get the corresponding glyph. + int32_t glyph_id = *(unresolved_glyph_ids->begin()); + unresolved_glyph_ids->erase(unresolved_glyph_ids->begin()); + if (glyph_id < 0 || glyph_id > loca_table_->num_glyphs()) { +#if defined (SUBTLY_DEBUG) + fprintf(stderr, "%d larger than %d or smaller than 0\n", glyph_id, + loca_table_->num_glyphs()); +#endif + continue; + } + int32_t length = loca_table_->GlyphLength(glyph_id); + if (length == 0) { +#if defined (SUBTLY_DEBUG) + fprintf(stderr, "Zero length glyph %d\n", glyph_id); +#endif + continue; + } + int32_t offset = loca_table_->GlyphOffset(glyph_id); + GlyphPtr glyph; + glyph.Attach(glyph_table_->GetGlyph(offset, length)); + if (glyph == NULL) { +#if defined (SUBTLY_DEBUG) + fprintf(stderr, "GetGlyph returned NULL for %d\n", glyph_id); +#endif + continue; + } + // Mark the glyph as resolved. + resolved_glyph_ids->insert(GlyphId(glyph_id, font_id_)); + // If it is composite, add all its components to the unresolved glyph set. + if (glyph->GlyphType() == GlyphType::kComposite) { + Ptr composite_glyph = + down_cast(glyph.p_); + int32_t num_glyphs = composite_glyph->NumGlyphs(); + for (int32_t i = 0; i < num_glyphs; ++i) { + int32_t glyph_id = composite_glyph->GlyphIndex(i); + if (resolved_glyph_ids->find(GlyphId(glyph_id, -1)) + == resolved_glyph_ids->end()) { + unresolved_glyph_ids->insert(glyph_id); + } + } + } + } + delete unresolved_glyph_ids; + return true; +} +} diff --git a/sample/subtly/font_info.h b/sample/subtly/font_info.h new file mode 100644 index 0000000..6f42d73 --- /dev/null +++ b/sample/subtly/font_info.h @@ -0,0 +1,128 @@ +/* + * 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_SAMPLE_SUBTLY_FONT_INFO_H_ +#define TYPOGRAPHY_FONT_SFNTLY_SRC_SAMPLE_SUBTLY_FONT_INFO_H_ + +#include +#include + +#include "sfntly/font.h" +#include "sfntly/port/type.h" +#include "sfntly/port/refcount.h" +#include "sfntly/table/core/cmap_table.h" +#include "sfntly/table/truetype/glyph_table.h" +#include "sfntly/table/truetype/loca_table.h" + +namespace subtly { +class CharacterPredicate; + +typedef int32_t FontId; +typedef std::map > FontIdMap; + +// Glyph id pair that contains the loca table glyph id as well as the +// font id that has the glyph table this glyph belongs to. +class GlyphId { + public: + GlyphId(int32_t glyph_id, FontId font_id); + ~GlyphId() {} + + bool operator==(const GlyphId& other) const; + bool operator<(const GlyphId& other) const; + + int32_t glyph_id() const { return glyph_id_; } + void set_glyph_id(const int32_t glyph_id) { glyph_id_ = glyph_id; } + FontId font_id() const { return font_id_; } + void set_font_id(const FontId font_id) { font_id_ = font_id; } + + private: + int32_t glyph_id_; + FontId font_id_; +}; + +typedef std::map CharacterMap; +typedef std::set GlyphIdSet; + +// Font information used for FontAssembler in the construction of a new font. +// Will make copies of character map, glyph id set and font id map. +class FontInfo : public sfntly::RefCounted { + public: + // Empty FontInfo object. + FontInfo(); + // chars_to_glyph_ids maps characters to GlyphIds for CMap construction + // resolved_glyph_ids defines GlyphIds which should be in the final font + // fonts is a map of font ids to fonts to reference any needed table + FontInfo(CharacterMap* chars_to_glyph_ids, + GlyphIdSet* resolved_glyph_ids, + FontIdMap* fonts); + virtual ~FontInfo(); + + // Gets the table with the specified tag from the font corresponding to + // font_id or NULL if there is no such font/table. + // font_id is the id of the font that contains the table + // tag identifies the table to be obtained + virtual sfntly::FontDataTable* GetTable(FontId font_id, int32_t tag); + // Gets the table map of the font whose id is font_id + virtual const sfntly::TableMap* GetTableMap(FontId); + + CharacterMap* chars_to_glyph_ids() const { return chars_to_glyph_ids_; } + // Takes ownership of the chars_to_glyph_ids CharacterMap. + void set_chars_to_glyph_ids(CharacterMap* chars_to_glyph_ids); + GlyphIdSet* resolved_glyph_ids() const { return resolved_glyph_ids_; } + // Takes ownership of the glyph_ids GlyphIdSet. + void set_resolved_glyph_ids(GlyphIdSet* glyph_ids); + FontIdMap* fonts() const { return fonts_; } + // Takes ownership of the fonts FontIdMap. + void set_fonts(FontIdMap* fonts); + + private: + CharacterMap* chars_to_glyph_ids_; + GlyphIdSet* resolved_glyph_ids_; + FontIdMap* fonts_; +}; + +// FontSourcedInfoBuilder is used to create a FontInfo object from a Font +// optionally specifying a CharacterPredicate to filter out some of +// the font's characters. +// It does not take ownership or copy the values its constructor receives. +class FontSourcedInfoBuilder : + public sfntly::RefCounted { + public: + FontSourcedInfoBuilder(sfntly::Font* font, FontId font_id); + FontSourcedInfoBuilder(sfntly::Font* font, + FontId font_id, + CharacterPredicate* predicate); + virtual ~FontSourcedInfoBuilder() { } + + virtual CALLER_ATTACH FontInfo* GetFontInfo(); + + protected: + bool GetCharacterMap(CharacterMap* chars_to_glyph_ids); + bool ResolveCompositeGlyphs(CharacterMap* chars_to_glyph_ids, + GlyphIdSet* resolved_glyph_ids); + void Initialize(); + + private: + sfntly::Ptr font_; + FontId font_id_; + CharacterPredicate* predicate_; + + sfntly::Ptr cmap_; + sfntly::Ptr loca_table_; + sfntly::Ptr glyph_table_; +}; +} +#endif // TYPOGRAPHY_FONT_SFNTLY_SRC_SAMPLE_SUBTLY_FONT_INFO_H_ diff --git a/sample/subtly/merger.cc b/sample/subtly/merger.cc new file mode 100644 index 0000000..7875c2d --- /dev/null +++ b/sample/subtly/merger.cc @@ -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. + */ + +#include "subtly/merger.h" + +#include + +#include "sfntly/font.h" +#include "sfntly/font_factory.h" +#include "subtly/character_predicate.h" +#include "subtly/font_assembler.h" +#include "subtly/font_info.h" +#include "subtly/utils.h" + +namespace subtly { +using namespace sfntly; + +/****************************************************************************** + * Merger class + ******************************************************************************/ +Merger::Merger(FontArray* fonts) { + if (!fonts) { + return; + } + int32_t num_fonts = fonts->size(); + for (int32_t i = 0; i < num_fonts; ++i) { + fonts_.insert(std::make_pair(i, fonts->at(i))); + } +} + +CALLER_ATTACH Font* Merger::Merge() { + Ptr merged_info; + merged_info.Attach(MergeFontInfos()); + if (!merged_info) { +#if defined (SUBTLY_DEBUG) + fprintf(stderr, "Could not create merged font info\n"); +#endif + return NULL; + } + Ptr font_assembler = new FontAssembler(merged_info); + return font_assembler->Assemble(); +} + +CALLER_ATTACH FontInfo* Merger::MergeFontInfos() { + Ptr font_info = new FontInfo; + font_info->set_fonts(&fonts_); + for (FontIdMap::iterator it = fonts_.begin(), + e = fonts_.end(); it != e; ++it) { + Ptr info_builder = + new FontSourcedInfoBuilder(it->second, it->first, NULL); + Ptr current_font_info; + current_font_info.Attach(info_builder->GetFontInfo()); + if (!current_font_info) { +#if defined (SUBTLY_DEBUG) + fprintf(stderr, "Couldn't create font info. " + "No subset will be generated.\n"); +#endif + return NULL; + } + font_info->chars_to_glyph_ids()->insert( + current_font_info->chars_to_glyph_ids()->begin(), + current_font_info->chars_to_glyph_ids()->end()); + font_info->resolved_glyph_ids()->insert( + current_font_info->resolved_glyph_ids()->begin(), + current_font_info->resolved_glyph_ids()->end()); +#if defined (SUBTLY_DEBUG) + fprintf(stderr, "Counts: chars_to_glyph_ids: %d; resoved_glyph_ids: %d\n", + font_info->chars_to_glyph_ids()->size(), + font_info->resolved_glyph_ids()->size()); +#endif + } + return font_info.Detach(); +} +} diff --git a/sample/subtly/merger.h b/sample/subtly/merger.h new file mode 100644 index 0000000..43764a8 --- /dev/null +++ b/sample/subtly/merger.h @@ -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. + */ + +#ifndef TYPOGRAPHY_FONT_SFNTLY_SRC_SAMPLE_SUBTLY_MERGER_H_ +#define TYPOGRAPHY_FONT_SFNTLY_SRC_SAMPLE_SUBTLY_MERGER_H_ + +#include "subtly/character_predicate.h" +#include "subtly/font_info.h" + +namespace sfntly { +class Font; +} + +namespace subtly { +// Merges the subsets in the font array into a single font. +class Merger : public sfntly::RefCounted { + public: + explicit Merger(sfntly::FontArray* fonts); + virtual ~Merger() { } + + // Performs merging returning the subsetted font. + virtual CALLER_ATTACH sfntly::Font* Merge(); + + protected: + virtual CALLER_ATTACH FontInfo* MergeFontInfos(); + + private: + FontIdMap fonts_; +}; +} + +#endif // TYPOGRAPHY_FONT_SFNTLY_SRC_SAMPLE_SUBTLY_MERGER_H_ diff --git a/sample/subtly/merger_main.cc b/sample/subtly/merger_main.cc new file mode 100644 index 0000000..a977aa7 --- /dev/null +++ b/sample/subtly/merger_main.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 +#include + +#include +#include + +#include "sfntly/font.h" +#include "subtly/merger.h" +#include "subtly/stats.h" +#include "subtly/utils.h" + +using namespace subtly; + +void PrintUsage(const char* program_name) { + fprintf(stdout, "Usage: %s ..." + " \n", + program_name); +} + +void CheckLoading(const char* font_path, Font* font) { + if (!font || font->num_tables() == 0) { + fprintf(stderr, "Could not load font %s. Terminating.\n", font_path); + exit(1); + } +} + +int main(int argc, const char** argv) { + if (argc < 3) { + PrintUsage(argv[0]); + exit(1); + } + + FontArray fonts; + for (int32_t i = 1; i < argc - 1; ++i) { + Ptr font; + font.Attach(LoadFont(argv[i])); + CheckLoading(argv[i], font); + fonts.push_back(font); + } + + Ptr merger = new Merger(&fonts); + FontPtr new_font; + new_font.Attach(merger->Merge()); + + fprintf(stderr, "Serializing font to %s\n", argv[argc - 1]); + SerializeFont(argv[argc - 1], new_font); + if (!new_font) { + fprintf(stdout, "Cannot create merged font.\n"); + return 1; + } + + return 0; +} diff --git a/sample/subtly/stats.cc b/sample/subtly/stats.cc new file mode 100644 index 0000000..769f691 --- /dev/null +++ b/sample/subtly/stats.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 "sfntly/font.h" +#include "sfntly/table/table.h" +#include "sfntly/tag.h" +#include "subtly/stats.h" + +namespace subtly { +using namespace sfntly; + +int32_t TotalFontSize(Font* font) { + int32_t size = 0; + const TableMap* table_map = font->GetTableMap(); + for (TableMap::const_iterator it = table_map->begin(), + e = table_map->end(); it != e; ++it) { + size += it->second->DataLength(); + } + return size; +} + +double TableSizePercent(Font* font, int32_t tag) { + TablePtr table = font->GetTable(tag); + return static_cast(table->DataLength()) / TotalFontSize(font) * 100; +} + +void PrintComparison(FILE* out, Font* font, Font* new_font) { + fprintf(out, "====== Table Comparison (original v. subset) ======\n"); + const TableMap* tables = font->GetTableMap(); + for (TableMap::const_iterator it = tables->begin(), + e = tables->end(); it != e; ++it) { + char *name = TagToString(it->first); + int32_t size = it->second->DataLength(); + fprintf(out, "-- %s: %d (%lf%%) ", name, size, + TableSizePercent(font, it->first)); + delete[] name; + + Ptr new_table = new_font->GetTable(it->first); + int32_t new_size = 0; + double size_percent = 0; + if (new_table) { + new_size = new_table->DataLength(); + size_percent = subtly::TableSizePercent(new_font, it->first); + } + + if (new_size == size) { + fprintf(out, "| same size\n"); + } else { + fprintf(out, "-> %d (%lf%%) | %lf%% of original\n", new_size, + size_percent, static_cast(new_size) / size * 100); + } + } +} + +void PrintStats(FILE* out, Font* font) { + fprintf(out, "====== Table Stats ======\n"); + const TableMap* tables = font->GetTableMap(); + for (TableMap::const_iterator it = tables->begin(), + e = tables->end(); it != e; ++it) { + char *name = TagToString(it->first); + int32_t size = it->second->DataLength(); + fprintf(out, "-- %s: %d (%lf%%)\n", name, size, + TableSizePercent(font, it->first)); + delete[] name; + } +} +} diff --git a/sample/subtly/stats.h b/sample/subtly/stats.h new file mode 100644 index 0000000..89ef2ae --- /dev/null +++ b/sample/subtly/stats.h @@ -0,0 +1,40 @@ +/* + * 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_SAMPLE_SUBTLY_STATS_H_ +#define TYPOGRAPHY_FONT_SFNTLY_SRC_SAMPLE_SUBTLY_STATS_H_ + +#include + +#include "sfntly/port/type.h" + +namespace sfntly { +class Font; +} + +namespace subtly { +using namespace sfntly; + +int32_t TotalFontSize(Font* font); + +double TableSizePercent(Font* font, int32_t tag); + +void PrintComparison(FILE* out, Font* font, Font* new_font); + +void PrintStats(FILE* out, Font* font); +} + +#endif // TYPOGRAPHY_FONT_SFNTLY_SRC_SAMPLE_SUBTLY_STATS_H_ diff --git a/sample/subtly/subsetter.cc b/sample/subtly/subsetter.cc new file mode 100644 index 0000000..d09627c --- /dev/null +++ b/sample/subtly/subsetter.cc @@ -0,0 +1,67 @@ +/* + * 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 "subtly/subsetter.h" + +#include + +#include "sfntly/font.h" +#include "sfntly/font_factory.h" +#include "sfntly/tag.h" +#include "subtly/character_predicate.h" +#include "subtly/font_assembler.h" +#include "subtly/font_info.h" +#include "subtly/utils.h" + +namespace subtly { +using namespace sfntly; + +/****************************************************************************** + * Subsetter class + ******************************************************************************/ +Subsetter::Subsetter(Font* font, CharacterPredicate* predicate) + : font_(font), + predicate_(predicate) { +} + +Subsetter::Subsetter(const char* font_path, CharacterPredicate* predicate) + : predicate_(predicate) { + font_.Attach(LoadFont(font_path)); +} + +CALLER_ATTACH Font* Subsetter::Subset() { + Ptr info_builder = + new FontSourcedInfoBuilder(font_, 0, predicate_); + + Ptr font_info; + font_info.Attach(info_builder->GetFontInfo()); + if (!font_info) { +#if defined (SUBTLY_DEBUG) + fprintf(stderr, + "Couldn't create font info. No subset will be generated.\n"); +#endif + return NULL; + } + IntegerSet* table_blacklist = new IntegerSet; + table_blacklist->insert(Tag::DSIG); + Ptr font_assembler = new FontAssembler(font_info, + table_blacklist); + Ptr font_subset; + font_subset.Attach(font_assembler->Assemble()); + delete table_blacklist; + return font_subset.Detach(); +} +} diff --git a/sample/subtly/subsetter.h b/sample/subtly/subsetter.h new file mode 100644 index 0000000..a93747f --- /dev/null +++ b/sample/subtly/subsetter.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 TYPOGRAPHY_FONT_SFNTLY_SRC_SAMPLE_SUBTLY_SUBSETTER_H_ +#define TYPOGRAPHY_FONT_SFNTLY_SRC_SAMPLE_SUBTLY_SUBSETTER_H_ + +#include "sfntly/font.h" +// Cannot remove this header due to Ptr instantiation issue +#include "subtly/character_predicate.h" + +namespace subtly { +// Subsets a given font using a character predicate. +class Subsetter : public sfntly::RefCounted { + public: + Subsetter(sfntly::Font* font, CharacterPredicate* predicate); + Subsetter(const char* font_path, CharacterPredicate* predicate); + virtual ~Subsetter() { } + + // Performs subsetting returning the subsetted font. + virtual CALLER_ATTACH sfntly::Font* Subset(); + + private: + sfntly::Ptr font_; + sfntly::Ptr predicate_; +}; +} + +#endif // TYPOGRAPHY_FONT_SFNTLY_SRC_SAMPLE_SUBTLY_SUBSETTER_H_ diff --git a/sample/subtly/subsetter_main.cc b/sample/subtly/subsetter_main.cc new file mode 100644 index 0000000..d438148 --- /dev/null +++ b/sample/subtly/subsetter_main.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 + +#include "sfntly/font.h" +#include "subtly/character_predicate.h" +#include "subtly/stats.h" +#include "subtly/subsetter.h" +#include "subtly/utils.h" + +using namespace subtly; + +void PrintUsage(const char* program_name) { + fprintf(stdout, "Usage: %s " + " \n", program_name); +} + +int main(int argc, const char** argv) { + const char* program_name = argv[0]; + if (argc < 5) { + PrintUsage(program_name); + exit(1); + } + + const char* input_font_path = argv[1]; + const char* output_font_path = argv[2]; + FontPtr font; + font.Attach(subtly::LoadFont(input_font_path)); + if (font->num_tables() == 0) { + fprintf(stderr, "Could not load font %s.\n", input_font_path); + exit(1); + } + + const char* start_char = argv[3]; + const char* end_char = argv[4]; + if (start_char[1] != 0) { + fprintf(stderr, "Start character %c invalid.\n", start_char[0]); + exit(1); + } + if (end_char[1] != 0) { + fprintf(stderr, "Start character %c invalid.\n", end_char[0]); + exit(1); + } + int32_t original_size = TotalFontSize(font); + + + Ptr range_predicate = + new AcceptRange(start_char[0], end_char[0]); + Ptr subsetter = new Subsetter(font, range_predicate); + Ptr new_font; + new_font.Attach(subsetter->Subset()); + if (!new_font) { + fprintf(stdout, "Cannot create subset.\n"); + return 0; + } + + subtly::SerializeFont(output_font_path, new_font); + subtly::PrintComparison(stdout, font, new_font); + int32_t new_size = TotalFontSize(new_font); + fprintf(stdout, "Went from %d to %d: %lf%% of original\n", + original_size, new_size, + static_cast(new_size) / original_size * 100); + return 0; +} diff --git a/sample/subtly/utils.cc b/sample/subtly/utils.cc new file mode 100644 index 0000000..0d59155 --- /dev/null +++ b/sample/subtly/utils.cc @@ -0,0 +1,91 @@ +/* + * 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 "subtly/utils.h" + +#include "sfntly/data/growable_memory_byte_array.h" +#include "sfntly/data/memory_byte_array.h" +#include "sfntly/font.h" +#include "sfntly/font_factory.h" +#include "sfntly/port/file_input_stream.h" +#include "sfntly/port/memory_output_stream.h" + +namespace subtly { +using namespace sfntly; + +CALLER_ATTACH Font* LoadFont(const char* font_path) { + Ptr font_factory; + font_factory.Attach(FontFactory::GetInstance()); + FontArray fonts; + LoadFonts(font_path, font_factory, &fonts); + return fonts[0].Detach(); +} + +CALLER_ATTACH Font::Builder* LoadFontBuilder(const char* font_path) { + FontFactoryPtr font_factory; + font_factory.Attach(FontFactory::GetInstance()); + FontBuilderArray builders; + LoadFontBuilders(font_path, font_factory, &builders); + return builders[0].Detach(); +} + +void LoadFonts(const char* font_path, FontFactory* factory, FontArray* fonts) { + FileInputStream input_stream; + input_stream.Open(font_path); + factory->LoadFonts(&input_stream, fonts); + input_stream.Close(); +} + +void LoadFontBuilders(const char* font_path, + FontFactory* factory, + FontBuilderArray* builders) { + FileInputStream input_stream; + input_stream.Open(font_path); + factory->LoadFontsForBuilding(&input_stream, builders); + input_stream.Close(); +} + +bool SerializeFont(const char* font_path, Font* font) { + if (!font_path) + return false; + FontFactoryPtr font_factory; + font_factory.Attach(FontFactory::GetInstance()); + return SerializeFont(font_path, font_factory, font); +} + +bool SerializeFont(const char* font_path, FontFactory* factory, Font* font) { + if (!font_path || !factory || !font) + return false; + // Serializing the font to a stream. + MemoryOutputStream output_stream; + factory->SerializeFont(font, &output_stream); + // Serializing the stream to a file. + FILE* output_file = NULL; +#if defined WIN32 + fopen_s(&output_file, font_path, "wb"); +#else + output_file = fopen(font_path, "wb"); +#endif + if (output_file == reinterpret_cast(NULL)) + return false; + for (int32_t i = 0; i < output_stream.Size(); ++i) { + fwrite(&(output_stream.Get()[i]), 1, 1, output_file); + } + fflush(output_file); + fclose(output_file); + return true; +} +}; diff --git a/sample/subtly/utils.h b/sample/subtly/utils.h new file mode 100644 index 0000000..ba9f0d4 --- /dev/null +++ b/sample/subtly/utils.h @@ -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. + */ + +#ifndef TYPOGRAPHY_FONT_SFNTLY_SRC_SAMPLE_SUBTLY_UTILS_H_ +#define TYPOGRAPHY_FONT_SFNTLY_SRC_SAMPLE_SUBTLY_UTILS_H_ + +#include "sfntly/font.h" +#include "sfntly/font_factory.h" + +namespace subtly { +CALLER_ATTACH sfntly::Font* LoadFont(const char* font_path); +CALLER_ATTACH sfntly::Font::Builder* LoadFontBuilder(const char* font_path); + +void LoadFonts(const char* font_path, sfntly::FontFactory* factory, + sfntly::FontArray* fonts); +void LoadFontBuilders(const char* font_path, + sfntly::FontFactory* factory, + sfntly::FontBuilderArray* builders); + +bool SerializeFont(const char* font_path, sfntly::Font* font); +bool SerializeFont(const char* font_path, sfntly::FontFactory* factory, + sfntly::Font* font); +} + +#endif // TYPOGRAPHY_FONT_SFNTLY_SRC_SAMPLE_SUBTLY_UTILS_H_ -- cgit v1.2.3 From 6009adcf56a33ec11ceaac67dc778a24be3ea866 Mon Sep 17 00:00:00 2001 From: "dfilimon@google.com" Date: Wed, 21 Sep 2011 04:02:37 +0000 Subject: Fixing build breakages on GCC and VC. git-svn-id: http://sfntly.googlecode.com/svn/trunk/cpp/src@92 672e30a5-4c29-85ac-ac6d-611c735e0a51 --- sample/subtly/character_predicate.cc | 1 + sample/subtly/utils.cc | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/sample/subtly/character_predicate.cc b/sample/subtly/character_predicate.cc index 1509260..b9c6cc7 100644 --- a/sample/subtly/character_predicate.cc +++ b/sample/subtly/character_predicate.cc @@ -47,6 +47,7 @@ bool AcceptSet::operator()(int32_t character) const { // AcceptAll predicate bool AcceptAll::operator()(int32_t character) const { + UNREFERENCED_PARAMETER(character); return true; } } diff --git a/sample/subtly/utils.cc b/sample/subtly/utils.cc index 0d59155..3c204d3 100644 --- a/sample/subtly/utils.cc +++ b/sample/subtly/utils.cc @@ -81,7 +81,7 @@ bool SerializeFont(const char* font_path, FontFactory* factory, Font* font) { #endif if (output_file == reinterpret_cast(NULL)) return false; - for (int32_t i = 0; i < output_stream.Size(); ++i) { + for (size_t i = 0; i < output_stream.Size(); ++i) { fwrite(&(output_stream.Get()[i]), 1, 1, output_file); } fflush(output_file); -- cgit v1.2.3 From 0c18481adaebdef466bb1b5b0965f9f8db5e2081 Mon Sep 17 00:00:00 2001 From: "dfilimon@google.com" Date: Thu, 22 Sep 2011 21:01:00 +0000 Subject: Migrated CMapBasicTests to use XML source. - added TinyXML library code and helper functions - removed old Python scripts that generated C++ files - added Python script that generates a list of fonts to test (.h file) - modified test/autogenerated/cmap_basic_test.cc - update test/autogenerated/cmap_test_data.h git-svn-id: http://sfntly.googlecode.com/svn/trunk/cpp/src@93 672e30a5-4c29-85ac-ac6d-611c735e0a51 --- test/autogenerated/cmap_basic_test.cc | 69 +- test/autogenerated/cmap_test_data.cc | 3435 --------------------------------- test/autogenerated/cmap_test_data.h | 486 ++--- test/test_xml_utils.cc | 50 + test/test_xml_utils.h | 33 + test/tinyxml/tinystr.cpp | 111 ++ test/tinyxml/tinystr.h | 305 +++ test/tinyxml/tinyxml.cpp | 1886 ++++++++++++++++++ test/tinyxml/tinyxml.h | 1805 +++++++++++++++++ test/tinyxml/tinyxmlerror.cpp | 52 + test/tinyxml/tinyxmlparser.cpp | 1638 ++++++++++++++++ 11 files changed, 6083 insertions(+), 3787 deletions(-) delete mode 100644 test/autogenerated/cmap_test_data.cc create mode 100644 test/test_xml_utils.cc create mode 100644 test/test_xml_utils.h create mode 100644 test/tinyxml/tinystr.cpp create mode 100644 test/tinyxml/tinystr.h create mode 100644 test/tinyxml/tinyxml.cpp create mode 100644 test/tinyxml/tinyxml.h create mode 100644 test/tinyxml/tinyxmlerror.cpp create mode 100644 test/tinyxml/tinyxmlparser.cpp diff --git a/test/autogenerated/cmap_basic_test.cc b/test/autogenerated/cmap_basic_test.cc index 0c09199..ddf3aa5 100644 --- a/test/autogenerated/cmap_basic_test.cc +++ b/test/autogenerated/cmap_basic_test.cc @@ -35,6 +35,7 @@ #include "test/autogenerated/cmap_test_data.h" #include "test/test_font_utils.h" #include "test/test_utils.h" +#include "test/test_xml_utils.h" namespace sfntly { @@ -43,26 +44,26 @@ namespace sfntly { using ::testing::TestWithParam; using ::testing::Values; -class CMapBasicTests : public :: testing::TestWithParam { +class CMapBasicTests : public :: testing::TestWithParam { public: CMapBasicTests() {} virtual void SetUp(); virtual void TearDown() {} - void BasicTest(int32_t index); - Ptr cmap_table_; + TiXmlDocument document_; }; void CMapBasicTests::SetUp() { + // Loading the font Ptr font_factory; font_factory.Attach(FontFactory::GetInstance()); FontArray font_array; - std::string font_name("../../"); + std::string font_name = "../../"; #if defined (WIN32) font_name += "../"; #endif - font_name += std::string(GetParam().name); + font_name += std::string(GetParam()); LoadFont(font_name.c_str(), font_factory, &font_array); ASSERT_FALSE(font_array.empty()); Ptr font = font_array.at(0); @@ -71,34 +72,52 @@ void CMapBasicTests::SetUp() { if (!cmap_table_) fprintf(stderr, "No CMap: %s\n", font_name.c_str()); ASSERT_NE(cmap_table_, reinterpret_cast(NULL)); -} -void CMapBasicTests::BasicTest(int32_t index) { - const ProtoCMap* test = &GetParam().cmaps[index]; - Ptr cmap; - cmap.Attach(cmap_table_->GetCMap(test->platform_id, test->encoding_id)); - if (!cmap) { - fprintf(stderr, "Cannot test unsupported CMapFormat%d\n", test->format); - return; - } - ASSERT_EQ(cmap->platform_id(), test->platform_id); - ASSERT_EQ(cmap->encoding_id(), test->encoding_id); - ASSERT_EQ(cmap->format(), test->format); - // There is no length() method for a CMap! - // ASSERT_EQ(cmap->length(), test->length); - for (int32_t i = 0; i < test->num_mappings; ++i) - ASSERT_EQ(cmap->GlyphId(test->chars[i]), test->glyph_ids[i]); + // Loading the XML file + document_ = TiXmlDocument((font_name + ".xml").c_str()); + ASSERT_TRUE(document_.LoadFile()); } TEST_P(CMapBasicTests, BasicTest) { - for (int32_t i = 0; i < GetParam().num_cmaps; ++i) - BasicTest(i); + TiXmlNodeVector* cmap_table = GetNodesWithName(&document_, "cmap_table"); + // A font can only have one CMap table + ASSERT_EQ(cmap_table->size(), 1); + TiXmlNodeVector* cmaps = GetNodesWithName(cmap_table->at(0), "cmap"); + const TiXmlAttribute* num_cmaps_attr = GetAttribute(cmap_table->at(0), + "num_cmaps"); + ASSERT_NE(num_cmaps_attr, reinterpret_cast(NULL)); + // But there may be more than one CMap in this table + ASSERT_LE(cmaps->size(), num_cmaps_attr->IntValue()); + for (TiXmlNodeVector::iterator it = cmaps->begin(); + it != cmaps->end(); ++it) { + int32_t platform_id = GetAttribute(*it, "platform_id")->IntValue(); + int32_t encoding_id = GetAttribute(*it, "encoding_id")->IntValue(); + Ptr cmap; + cmap.Attach(cmap_table_->GetCMap(platform_id, encoding_id)); + if (!cmap) { + fprintf(stderr, "Cannot test unsupported CMapFormat%d\n", + GetAttribute(*it, "format")->IntValue()); + continue; + } + ASSERT_EQ(cmap->platform_id(), platform_id); + ASSERT_EQ(cmap->encoding_id(), encoding_id); + TiXmlNodeVector* maps = GetNodesWithName(*it, "map"); + for (TiXmlNodeVector::iterator jt = maps->begin(); + jt != maps->end(); ++jt) { + int32_t character; + sscanf(GetAttribute(*jt, "char")->Value(), "%x", &character); + int32_t glyph_id = GetAttribute(*jt, "gid")->IntValue(); + ASSERT_EQ(cmap->GlyphId(character), glyph_id); + } + delete maps; + } + delete cmaps; + delete cmap_table; } - INSTANTIATE_TEST_CASE_P(CMapBasicTests, CMapBasicTests, - ::testing::ValuesIn(kAllTestCMaps)); + ::testing::ValuesIn(cmap_test_data::kAllTests)); #else diff --git a/test/autogenerated/cmap_test_data.cc b/test/autogenerated/cmap_test_data.cc deleted file mode 100644 index 95ee15c..0000000 --- a/test/autogenerated/cmap_test_data.cc +++ /dev/null @@ -1,3435 +0,0 @@ -/* - * !!! DO NOT EDIT !!! - * THIS FILE IS GENERATED BY A SCRIPT. - * FOR MORE DETAILS SEE 'README-test_data.txt'. - */ - -/* - * 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 "test/autogenerated/cmap_test_data.h" - -namespace sfntly -{ - TestCMap kTestCousine_BoldItalic_ttf_xml = { - "data/fonts/cousine/Cousine-BoldItalic.ttf", - 2, - { - { - 344, // length - 4, // format - 3, // platform id - 1, // encoding id - 10, // num_mappings - {32, 53, 75, 96, 117, 171, 192, 213, 234, 255} - , // chars - {3, 24, 45, 66, 87, 107, 127, 148, 169, 190} - , // glyph ids - } - , - { - 262, // length - 0, // format - 1, // platform id - 0, // encoding id - 10, // num_mappings - {0, 25, 50, 75, 100, 125, 150, 175, 200, 225} - , // chars - {1, 0, 21, 45, 70, 95, 176, 151, 122, 118} - , // glyph ids - } - } - }; - - TestCMap kTestCousine_Bold_ttf_xml = { - "data/fonts/cousine/Cousine-Bold.ttf", - 2, - { - { - 344, // length - 4, // format - 3, // platform id - 1, // encoding id - 10, // num_mappings - {32, 53, 75, 96, 117, 171, 192, 213, 234, 255} - , // chars - {3, 24, 45, 66, 87, 107, 127, 148, 169, 190} - , // glyph ids - } - , - { - 262, // length - 0, // format - 1, // platform id - 0, // encoding id - 10, // num_mappings - {0, 25, 50, 75, 100, 125, 150, 175, 200, 225} - , // chars - {1, 0, 21, 45, 70, 95, 176, 151, 122, 118} - , // glyph ids - } - } - }; - - TestCMap kTestCousine_Regular_ttf_xml = { - "data/fonts/cousine/Cousine-Regular.ttf", - 2, - { - { - 344, // length - 4, // format - 3, // platform id - 1, // encoding id - 10, // num_mappings - {32, 53, 75, 96, 117, 171, 192, 213, 234, 255} - , // chars - {3, 24, 45, 66, 87, 107, 127, 148, 169, 190} - , // glyph ids - } - , - { - 262, // length - 0, // format - 1, // platform id - 0, // encoding id - 10, // num_mappings - {0, 25, 50, 75, 100, 125, 150, 175, 200, 225} - , // chars - {1, 0, 21, 45, 70, 95, 176, 151, 122, 118} - , // glyph ids - } - } - }; - - TestCMap kTestCousine_Italic_ttf_xml = { - "data/fonts/cousine/Cousine-Italic.ttf", - 2, - { - { - 344, // length - 4, // format - 3, // platform id - 1, // encoding id - 10, // num_mappings - {32, 53, 75, 96, 117, 171, 192, 213, 234, 255} - , // chars - {3, 24, 45, 66, 87, 107, 127, 148, 169, 190} - , // glyph ids - } - , - { - 262, // length - 0, // format - 1, // platform id - 0, // encoding id - 10, // num_mappings - {0, 25, 50, 75, 100, 125, 150, 175, 200, 225} - , // chars - {1, 0, 21, 45, 70, 95, 176, 151, 122, 118} - , // glyph ids - } - } - }; - - TestCMap kTestCedarville_Cursive_ttf_xml = { - "data/fonts/cedarvillecursive/Cedarville-Cursive.ttf", - 1, - { - { - 240, // length - 4, // format - 3, // platform id - 1, // encoding id - 10, // num_mappings - {32, 67, 102, 170, 205, 240, 278, 317, 355, 710} - , // chars - {3, 38, 73, 108, 143, 178, 213, 248, 283, 318} - , // glyph ids - } - } - }; - - TestCMap kTestDancingScript_Bold_ttf_xml = { - "data/fonts/dancingscript/DancingScript-Bold.ttf", - 1, - { - { - 216, // length - 4, // format - 3, // platform id - 1, // encoding id - 10, // num_mappings - {32, 54, 76, 98, 120, 177, 199, 221, 243, 710} - , // chars - {3, 25, 47, 69, 91, 113, 135, 157, 179, 201} - , // glyph ids - } - } - }; - - TestCMap kTestDancingScript_Regular_ttf_xml = { - "data/fonts/dancingscript/DancingScript-Regular.ttf", - 1, - { - { - 216, // length - 4, // format - 3, // platform id - 1, // encoding id - 10, // num_mappings - {32, 54, 76, 98, 120, 177, 199, 221, 243, 710} - , // chars - {3, 25, 47, 69, 91, 113, 135, 157, 179, 201} - , // glyph ids - } - } - }; - - TestCMap kTestDamion_Regular_ttf_xml = { - "data/fonts/damion/Damion-Regular.ttf", - 1, - { - { - 314, // length - 4, // format - 3, // platform id - 1, // encoding id - 10, // num_mappings - {32, 58, 84, 110, 169, 197, 223, 249, 520, 733} - , // chars - {3, 29, 55, 81, 106, 132, 158, 184, 210, 236} - , // glyph ids - } - } - }; - - TestCMap kTestAnnieUseYourTelescope_ttf_xml = { - "data/fonts/annieuseyourtelescope/AnnieUseYourTelescope.ttf", - 1, - { - { - 248, // length - 4, // format - 3, // platform id - 1, // encoding id - 10, // num_mappings - {32, 67, 102, 170, 205, 240, 275, 317, 353, 710} - , // chars - {3, 38, 73, 108, 143, 178, 213, 248, 283, 318} - , // glyph ids - } - } - }; - - TestCMap kTestDeliusSwashCaps_Regular_ttf_xml = { - "data/fonts/deliusswashcaps/DeliusSwashCaps-Regular.ttf", - 1, - { - { - 288, // length - 4, // format - 3, // platform id - 1, // encoding id - 10, // num_mappings - {32, 58, 84, 110, 169, 195, 221, 247, 323, 8224} - , // chars - {3, 29, 55, 81, 107, 133, 159, 185, 211, 237} - , // glyph ids - } - } - }; - - TestCMap kTestDelius_Regular_ttf_xml = { - "data/fonts/delius/Delius-Regular.ttf", - 1, - { - { - 288, // length - 4, // format - 3, // platform id - 1, // encoding id - 10, // num_mappings - {32, 58, 84, 110, 169, 195, 221, 247, 323, 8224} - , // chars - {3, 29, 55, 81, 107, 133, 159, 185, 211, 237} - , // glyph ids - } - } - }; - - TestCMap kTestCoveredByYourGrace_ttf_xml = { - "data/fonts/coveredbyyourgrace/CoveredByYourGrace.ttf", - 1, - { - { - 478, // length - 4, // format - 3, // platform id - 1, // encoding id - 10, // num_mappings - {32, 66, 100, 167, 201, 235, 269, 311, 350, 509} - , // chars - {3, 37, 71, 104, 138, 172, 206, 240, 274, 308} - , // glyph ids - } - } - }; - - TestCMap kTestEBGaramond_Regular_ttf_xml = { - "data/fonts/ebgaramond/EBGaramond-Regular.ttf", - 1, - { - { - 1048, // length - 4, // format - 3, // platform id - 1, // encoding id - 10, // num_mappings - {32, 217, 369, 523, 678, 1032, 7470, 7794, 8137, 8566} - , // chars - {3, 155, 307, 459, 611, 763, 915, 1067, 1219, 1371} - , // glyph ids - } - } - }; - - TestCMap kTestCabinSketch_Bold_ttf_xml = { - "data/fonts/cabinsketch/CabinSketch-Bold.ttf", - 2, - { - { - 230, // length - 4, // format - 3, // platform id - 1, // encoding id - 10, // num_mappings - {32, 54, 76, 98, 120, 176, 198, 220, 242, 402} - , // chars - {3, 25, 47, 69, 91, 112, 134, 156, 178, 200} - , // glyph ids - } - , - { - 262, // length - 0, // format - 1, // platform id - 0, // encoding id - 10, // num_mappings - {0, 25, 50, 75, 100, 125, 150, 175, 200, 225} - , // chars - {1, 0, 21, 46, 71, 96, 177, 152, 123, 119} - , // glyph ids - } - } - }; - - TestCMap kTestAllan_Bold_ttf_xml = { - "data/fonts/allan/Allan-Bold.ttf", - 2, - { - { - 232, // length - 4, // format - 3, // platform id - 1, // encoding id - 10, // num_mappings - {32, 54, 76, 98, 120, 176, 198, 220, 242, 382} - , // chars - {3, 25, 47, 69, 91, 113, 135, 157, 179, 201} - , // glyph ids - } - , - { - 262, // length - 0, // format - 1, // platform id - 0, // encoding id - 10, // num_mappings - {0, 25, 50, 75, 100, 125, 150, 175, 200, 225} - , // chars - {1, 0, 21, 46, 71, 96, 178, 153, 124, 120} - , // glyph ids - } - } - }; - - TestCMap kTestCoda_Caption_Heavy_ttf_xml = { - "data/fonts/coda/Coda-Caption-Heavy.ttf", - 1, - { - { - 256, // length - 4, // format - 3, // platform id - 1, // encoding id - 10, // num_mappings - {32, 72, 112, 185, 225, 265, 305, 345, 452, 526} - , // chars - {3, 43, 83, 123, 163, 203, 243, 283, 323, 363} - , // glyph ids - } - } - }; - - TestCMap kTestCoda_Heavy_ttf_xml = { - "data/fonts/coda/Coda-Heavy.ttf", - 1, - { - { - 240, // length - 4, // format - 3, // platform id - 1, // encoding id - 10, // num_mappings - {32, 64, 96, 162, 195, 227, 259, 301, 336, 378} - , // chars - {3, 35, 67, 99, 131, 163, 195, 227, 259, 291} - , // glyph ids - } - } - }; - - TestCMap kTestForum_Regular_ttf_xml = { - "data/fonts/forum/Forum-Regular.ttf", - 2, - { - { - 1262, // length - 4, // format - 3, // platform id - 1, // encoding id - 10, // num_mappings - {32, 89, 183, 245, 302, 361, 1029, 1086, 1187, 1265} - , // chars - {3, 60, 163, 156, 235, 565, 365, 426, 479, 531} - , // glyph ids - } - , - { - 262, // length - 0, // format - 1, // platform id - 0, // encoding id - 10, // num_mappings - {0, 25, 50, 75, 100, 125, 150, 175, 200, 225} - , // chars - {1, 0, 193, 31, 97, 83, 112, 142, 19, 66} - , // glyph ids - } - } - }; - - TestCMap kTestAlike_Regular_ttf_xml = { - "data/fonts/alike/Alike-Regular.ttf", - 2, - { - { - 152, // length - 4, // format - 3, // platform id - 1, // encoding id - 10, // num_mappings - {32, 53, 74, 95, 116, 170, 191, 212, 233, 254} - , // chars - {3, 24, 45, 66, 87, 108, 129, 150, 171, 192} - , // glyph ids - } - , - { - 262, // length - 0, // format - 1, // platform id - 0, // encoding id - 10, // num_mappings - {0, 25, 50, 75, 100, 125, 150, 175, 200, 225} - , // chars - {1, 0, 21, 46, 71, 96, 179, 154, 125, 121} - , // glyph ids - } - } - }; - - TestCMap kTestCorben_Bold_ttf_xml = { - "data/fonts/corben/Corben-Bold.ttf", - 1, - { - { - 344, // length - 4, // format - 3, // platform id - 1, // encoding id - 10, // num_mappings - {32, 70, 108, 179, 217, 255, 294, 339, 377, 7779} - , // chars - {3, 41, 79, 117, 155, 193, 231, 269, 307, 344} - , // glyph ids - } - } - }; - - TestCMap kTestCaudex_Regular_ttf_xml = { - "data/fonts/caudex/Caudex-Regular.ttf", - 1, - { - { - 3272, // length - 4, // format - 3, // platform id - 1, // encoding id - 10, // num_mappings - {32, 266, 537, 928, 7684, 8052, 8595, 57446, 59571, 61226} - , // chars - {3, 204, 405, 606, 807, 1008, 1209, 1410, 1611, 1812} - , // glyph ids - } - } - }; - - TestCMap kTestCaudex_BoldItalic_ttf_xml = { - "data/fonts/caudex/Caudex-BoldItalic.ttf", - 1, - { - { - 3272, // length - 4, // format - 3, // platform id - 1, // encoding id - 10, // num_mappings - {32, 266, 537, 928, 7684, 8052, 8595, 57446, 59571, 61226} - , // chars - {3, 204, 405, 606, 807, 1008, 1209, 1410, 1611, 1812} - , // glyph ids - } - } - }; - - TestCMap kTestCaudex_Italic_ttf_xml = { - "data/fonts/caudex/Caudex-Italic.ttf", - 1, - { - { - 3272, // length - 4, // format - 3, // platform id - 1, // encoding id - 10, // num_mappings - {32, 266, 537, 928, 7684, 8052, 8595, 57446, 59571, 61226} - , // chars - {3, 204, 405, 606, 807, 1008, 1209, 1410, 1611, 1812} - , // glyph ids - } - } - }; - - TestCMap kTestCaudex_Bold_ttf_xml = { - "data/fonts/caudex/Caudex-Bold.ttf", - 1, - { - { - 3272, // length - 4, // format - 3, // platform id - 1, // encoding id - 10, // num_mappings - {32, 266, 537, 928, 7684, 8052, 8595, 57446, 59571, 61226} - , // chars - {3, 204, 405, 606, 807, 1008, 1209, 1410, 1611, 1812} - , // glyph ids - } - } - }; - - TestCMap kTestCabin_MediumItalic_ttf_xml = { - "data/fonts/cabin/Cabin-MediumItalic.ttf", - 1, - { - { - 232, // length - 4, // format - 3, // platform id - 1, // encoding id - 10, // num_mappings - {32, 55, 78, 101, 124, 181, 204, 227, 250, 8217} - , // chars - {1, 24, 47, 70, 93, 116, 139, 162, 185, 208} - , // glyph ids - } - } - }; - - TestCMap kTestCabin_SemiBold_ttf_xml = { - "data/fonts/cabin/Cabin-SemiBold.ttf", - 1, - { - { - 224, // length - 4, // format - 3, // platform id - 1, // encoding id - 10, // num_mappings - {32, 55, 78, 101, 124, 181, 204, 227, 250, 8217} - , // chars - {1, 24, 47, 70, 93, 116, 139, 162, 185, 208} - , // glyph ids - } - } - }; - - TestCMap kTestCabin_SemiBoldItalic_ttf_xml = { - "data/fonts/cabin/Cabin-SemiBoldItalic.ttf", - 1, - { - { - 224, // length - 4, // format - 3, // platform id - 1, // encoding id - 10, // num_mappings - {32, 55, 78, 101, 124, 181, 204, 227, 250, 8217} - , // chars - {1, 24, 47, 70, 93, 116, 139, 162, 185, 208} - , // glyph ids - } - } - }; - - TestCMap kTestCabin_BoldItalic_ttf_xml = { - "data/fonts/cabin/Cabin-BoldItalic.ttf", - 1, - { - { - 224, // length - 4, // format - 3, // platform id - 1, // encoding id - 10, // num_mappings - {32, 55, 78, 101, 124, 181, 204, 227, 250, 8217} - , // chars - {1, 24, 47, 70, 93, 116, 139, 162, 185, 208} - , // glyph ids - } - } - }; - - TestCMap kTestCabin_Medium_ttf_xml = { - "data/fonts/cabin/Cabin-Medium.ttf", - 1, - { - { - 224, // length - 4, // format - 3, // platform id - 1, // encoding id - 10, // num_mappings - {32, 55, 78, 101, 124, 181, 204, 227, 250, 8217} - , // chars - {1, 24, 47, 70, 93, 116, 139, 162, 185, 208} - , // glyph ids - } - } - }; - - TestCMap kTestCabin_Italic_ttf_xml = { - "data/fonts/cabin/Cabin-Italic.ttf", - 1, - { - { - 224, // length - 4, // format - 3, // platform id - 1, // encoding id - 10, // num_mappings - {32, 55, 78, 101, 124, 181, 204, 227, 250, 8217} - , // chars - {1, 24, 47, 70, 93, 116, 139, 162, 185, 208} - , // glyph ids - } - } - }; - - TestCMap kTestCabin_Bold_ttf_xml = { - "data/fonts/cabin/Cabin-Bold.ttf", - 1, - { - { - 224, // length - 4, // format - 3, // platform id - 1, // encoding id - 10, // num_mappings - {32, 55, 78, 101, 124, 181, 204, 227, 250, 8217} - , // chars - {1, 24, 47, 70, 93, 116, 139, 162, 185, 208} - , // glyph ids - } - } - }; - - TestCMap kTestCabin_Regular_ttf_xml = { - "data/fonts/cabin/Cabin-Regular.ttf", - 1, - { - { - 224, // length - 4, // format - 3, // platform id - 1, // encoding id - 10, // num_mappings - {32, 55, 78, 101, 124, 181, 204, 227, 250, 8217} - , // chars - {1, 24, 47, 70, 93, 116, 139, 162, 185, 208} - , // glyph ids - } - } - }; - - TestCMap kTestDawningofaNewDay_ttf_xml = { - "data/fonts/dawningofanewday/DawningofaNewDay.ttf", - 1, - { - { - 280, // length - 4, // format - 3, // platform id - 1, // encoding id - 10, // num_mappings - {32, 58, 84, 110, 169, 196, 222, 248, 336, 711} - , // chars - {3, 29, 55, 81, 107, 133, 159, 185, 211, 237} - , // glyph ids - } - } - }; - - TestCMap kTestDangrek_ttf_xml = { - "data/fonts/dangrek/Dangrek.ttf", - 2, - { - { - 96, // length - 4, // format - 3, // platform id - 1, // encoding id - 10, // num_mappings - {32, 45, 58, 6019, 6032, 6045, 6058, 6073, 6086, 6099} - , // chars - {3, 16, 29, 39, 52, 65, 78, 91, 104, 117} - , // glyph ids - } - , - { - 262, // length - 0, // format - 1, // platform id - 0, // encoding id - 10, // num_mappings - {0, 25, 50, 75, 100, 125, 150, 175, 200, 225} - , // chars - {1, 0, 21, 0, 0, 0, 0, 0, 0, 0} - , // glyph ids - } - } - }; - - TestCMap kTestBlackOpsOne_ttf_xml = { - "data/fonts/blackopsone/BlackOpsOne.ttf", - 1, - { - { - 256, // length - 4, // format - 3, // platform id - 1, // encoding id - 10, // num_mappings - {1, 39, 65, 91, 117, 176, 202, 228, 254, 567} - , // chars - {3, 29, 55, 81, 107, 133, 159, 185, 211, 237} - , // glyph ids - } - } - }; - - TestCMap kTestFrancoisOne_ttf_xml = { - "data/fonts/francoisone/FrancoisOne.ttf", - 1, - { - { - 456, // length - 4, // format - 3, // platform id - 1, // encoding id - 10, // num_mappings - {2, 72, 115, 192, 235, 278, 322, 365, 515, 7779} - , // chars - {3, 46, 89, 132, 175, 218, 261, 304, 347, 390} - , // glyph ids - } - } - }; - - TestCMap kTestBowlbyOne_ttf_xml = { - "data/fonts/bowlbyone/BowlbyOne.ttf", - 1, - { - { - 368, // length - 4, // format - 3, // platform id - 1, // encoding id - 10, // num_mappings - {32, 60, 88, 116, 178, 206, 234, 353, 535, 8226} - , // chars - {3, 31, 59, 87, 115, 143, 171, 199, 227, 255} - , // glyph ids - } - } - }; - - TestCMap kTestBowlbyOneSC_ttf_xml = { - "data/fonts/bowlbyone/BowlbyOneSC.ttf", - 1, - { - { - 384, // length - 4, // format - 3, // platform id - 1, // encoding id - 10, // num_mappings - {32, 62, 92, 122, 185, 215, 245, 520, 806, 8240} - , // chars - {3, 33, 63, 93, 123, 153, 183, 213, 243, 273} - , // glyph ids - } - } - }; - - TestCMap kTestCalligraffiti_ttf_xml = { - "data/fonts/calligraffiti/Calligraffiti.ttf", - 2, - { - { - 412, // length - 4, // format - 3, // platform id - 1, // encoding id - 10, // num_mappings - {32, 54, 76, 98, 120, 175, 197, 219, 241, 376} - , // chars - {21, 43, 65, 87, 109, 217, 117, 212, 138, 188} - , // glyph ids - } - , - { - 262, // length - 0, // format - 1, // platform id - 0, // encoding id - 10, // num_mappings - {0, 25, 50, 75, 100, 125, 150, 175, 200, 225} - , // chars - {0, 0, 39, 64, 89, 114, 138, 160, 172, 195} - , // glyph ids - } - } - }; - - TestCMap kTestBangers_ttf_xml = { - "data/fonts/bangers/Bangers.ttf", - 2, - { - { - 296, // length - 4, // format - 3, // platform id - 1, // encoding id - 10, // num_mappings - {9, 46, 70, 94, 118, 174, 200, 224, 248, 8212} - , // chars - {3, 27, 51, 75, 99, 123, 147, 171, 195, 219} - , // glyph ids - } - , - { - 262, // length - 0, // format - 1, // platform id - 0, // encoding id - 10, // num_mappings - {0, 25, 50, 75, 100, 125, 150, 175, 200, 225} - , // chars - {1, 0, 31, 56, 81, 106, 188, 163, 134, 130} - , // glyph ids - } - } - }; - - TestCMap kTestAstloch_Regular_ttf_xml = { - "data/fonts/astloch/Astloch-Regular.ttf", - 2, - { - { - 128, // length - 4, // format - 3, // platform id - 1, // encoding id - 10, // num_mappings - {32, 52, 72, 92, 112, 165, 185, 205, 225, 245} - , // chars - {3, 23, 43, 63, 83, 103, 123, 143, 163, 183} - , // glyph ids - } - , - { - 262, // length - 0, // format - 1, // platform id - 0, // encoding id - 10, // num_mappings - {0, 25, 50, 75, 100, 125, 150, 175, 200, 225} - , // chars - {1, 0, 21, 46, 71, 96, 179, 154, 125, 121} - , // glyph ids - } - } - }; - - TestCMap kTestAstloch_Bold_ttf_xml = { - "data/fonts/astloch/Astloch-Bold.ttf", - 2, - { - { - 128, // length - 4, // format - 3, // platform id - 1, // encoding id - 10, // num_mappings - {32, 52, 72, 92, 112, 165, 185, 205, 225, 245} - , // chars - {3, 23, 43, 63, 83, 103, 123, 143, 163, 183} - , // glyph ids - } - , - { - 262, // length - 0, // format - 1, // platform id - 0, // encoding id - 10, // num_mappings - {0, 25, 50, 75, 100, 125, 150, 175, 200, 225} - , // chars - {1, 0, 21, 46, 71, 96, 179, 154, 125, 121} - , // glyph ids - } - } - }; - - TestCMap kTestAngkor_ttf_xml = { - "data/fonts/angkor/Angkor.ttf", - 2, - { - { - 88, // length - 4, // format - 3, // platform id - 1, // encoding id - 10, // num_mappings - {32, 45, 58, 6019, 6032, 6045, 6058, 6073, 6086, 6099} - , // chars - {3, 16, 29, 39, 52, 65, 78, 91, 104, 117} - , // glyph ids - } - , - { - 262, // length - 0, // format - 1, // platform id - 0, // encoding id - 10, // num_mappings - {0, 25, 50, 75, 100, 125, 150, 175, 200, 225} - , // chars - {1, 0, 21, 0, 0, 0, 0, 0, 0, 0} - , // glyph ids - } - } - }; - - TestCMap kTestAbrilFatface_Regular_ttf_xml = { - "data/fonts/abrilfatface/AbrilFatface-Regular.ttf", - 1, - { - { - 360, // length - 4, // format - 3, // platform id - 1, // encoding id - 10, // num_mappings - {32, 71, 110, 182, 221, 260, 299, 338, 377, 7922} - , // chars - {3, 42, 81, 120, 159, 198, 237, 276, 315, 354} - , // glyph ids - } - } - }; - - TestCMap kTestCantarell_BoldOblique_ttf_xml = { - "data/fonts/cantarell/Cantarell-BoldOblique.ttf", - 1, - { - { - 264, // length - 4, // format - 3, // platform id - 1, // encoding id - 10, // num_mappings - {32, 70, 108, 179, 217, 255, 293, 331, 369, 7767} - , // chars - {3, 41, 79, 117, 155, 193, 231, 269, 307, 345} - , // glyph ids - } - } - }; - - TestCMap kTestCantarell_Oblique_ttf_xml = { - "data/fonts/cantarell/Cantarell-Oblique.ttf", - 1, - { - { - 264, // length - 4, // format - 3, // platform id - 1, // encoding id - 10, // num_mappings - {32, 70, 108, 179, 217, 255, 293, 331, 369, 7767} - , // chars - {3, 41, 79, 117, 155, 193, 231, 269, 307, 345} - , // glyph ids - } - } - }; - - TestCMap kTestCantarell_Bold_ttf_xml = { - "data/fonts/cantarell/Cantarell-Bold.ttf", - 1, - { - { - 264, // length - 4, // format - 3, // platform id - 1, // encoding id - 10, // num_mappings - {32, 70, 108, 179, 217, 255, 293, 331, 369, 7767} - , // chars - {3, 41, 79, 117, 155, 193, 231, 269, 307, 345} - , // glyph ids - } - } - }; - - TestCMap kTestCantarell_Regular_ttf_xml = { - "data/fonts/cantarell/Cantarell-Regular.ttf", - 1, - { - { - 264, // length - 4, // format - 3, // platform id - 1, // encoding id - 10, // num_mappings - {32, 70, 108, 179, 217, 255, 293, 331, 369, 7767} - , // chars - {3, 41, 79, 117, 155, 193, 231, 269, 307, 345} - , // glyph ids - } - } - }; - - TestCMap kTestArvo_Bold_ttf_xml = { - "data/fonts/arvo/Arvo-Bold.ttf", - 1, - { - { - 504, // length - 4, // format - 3, // platform id - 1, // encoding id - 10, // num_mappings - {32, 54, 76, 98, 120, 177, 199, 221, 243, 711} - , // chars - {28, 65, 13, 31, 53, 99, 166, 181, 200, 123} - , // glyph ids - } - } - }; - - TestCMap kTestArvo_Italic_ttf_xml = { - "data/fonts/arvo/Arvo-Italic.ttf", - 1, - { - { - 522, // length - 4, // format - 3, // platform id - 1, // encoding id - 10, // num_mappings - {32, 54, 76, 98, 120, 176, 198, 220, 242, 729} - , // chars - {28, 65, 13, 31, 53, 124, 131, 180, 199, 129} - , // glyph ids - } - } - }; - - TestCMap kTestArvo_BoldItalic_ttf_xml = { - "data/fonts/arvo/Arvo-BoldItalic.ttf", - 1, - { - { - 522, // length - 4, // format - 3, // platform id - 1, // encoding id - 10, // num_mappings - {32, 54, 76, 98, 120, 176, 198, 220, 242, 710} - , // chars - {28, 65, 13, 31, 53, 124, 131, 180, 199, 116} - , // glyph ids - } - } - }; - - TestCMap kTestArvo_Regular_ttf_xml = { - "data/fonts/arvo/Arvo-Regular.ttf", - 1, - { - { - 542, // length - 4, // format - 3, // platform id - 1, // encoding id - 10, // num_mappings - {32, 54, 76, 98, 120, 176, 198, 220, 242, 710} - , // chars - {28, 65, 13, 31, 53, 124, 131, 167, 206, 116} - , // glyph ids - } - } - }; - - TestCMap kTestChewy_ttf_xml = { - "data/fonts/chewy/Chewy.ttf", - 2, - { - { - 420, // length - 4, // format - 3, // platform id - 1, // encoding id - 10, // num_mappings - {32, 54, 76, 98, 120, 175, 197, 219, 241, 376} - , // chars - {21, 43, 65, 87, 109, 217, 117, 212, 138, 188} - , // glyph ids - } - , - { - 262, // length - 0, // format - 1, // platform id - 0, // encoding id - 10, // num_mappings - {0, 25, 50, 75, 100, 125, 150, 175, 200, 225} - , // chars - {0, 0, 39, 64, 89, 114, 138, 161, 172, 195} - , // glyph ids - } - } - }; - - TestCMap kTestBigshotOne_ttf_xml = { - "data/fonts/bigshotone/BigshotOne.ttf", - 2, - { - { - 176, // length - 4, // format - 3, // platform id - 1, // encoding id - 10, // num_mappings - {32, 53, 74, 95, 116, 170, 191, 212, 233, 254} - , // chars - {3, 24, 45, 66, 87, 108, 129, 150, 171, 192} - , // glyph ids - } - , - { - 262, // length - 0, // format - 1, // platform id - 0, // encoding id - 10, // num_mappings - {0, 25, 50, 75, 100, 125, 150, 175, 200, 225} - , // chars - {1, 0, 21, 46, 71, 96, 179, 154, 125, 121} - , // glyph ids - } - } - }; - - TestCMap kTestChenla_ttf_xml = { - "data/fonts/chenla/Chenla.ttf", - 2, - { - { - 88, // length - 4, // format - 3, // platform id - 1, // encoding id - 10, // num_mappings - {32, 45, 58, 6019, 6032, 6045, 6058, 6073, 6086, 6099} - , // chars - {3, 16, 29, 39, 52, 65, 78, 91, 104, 117} - , // glyph ids - } - , - { - 262, // length - 0, // format - 1, // platform id - 0, // encoding id - 10, // num_mappings - {0, 25, 50, 75, 100, 125, 150, 175, 200, 225} - , // chars - {1, 0, 21, 0, 0, 0, 0, 0, 0, 0} - , // glyph ids - } - } - }; - - TestCMap kTestBayon_ttf_xml = { - "data/fonts/bayon/Bayon.ttf", - 2, - { - { - 88, // length - 4, // format - 3, // platform id - 1, // encoding id - 10, // num_mappings - {32, 45, 58, 6019, 6032, 6045, 6058, 6073, 6086, 6099} - , // chars - {3, 16, 29, 39, 52, 65, 78, 91, 104, 117} - , // glyph ids - } - , - { - 262, // length - 0, // format - 1, // platform id - 0, // encoding id - 10, // num_mappings - {0, 25, 50, 75, 100, 125, 150, 175, 200, 225} - , // chars - {1, 0, 21, 0, 0, 0, 0, 0, 0, 0} - , // glyph ids - } - } - }; - - TestCMap kTestCoustard_Black_ttf_xml = { - "data/fonts/coustard/Coustard-Black.ttf", - 1, - { - { - 272, // length - 4, // format - 3, // platform id - 1, // encoding id - 10, // num_mappings - {32, 64, 96, 161, 193, 225, 257, 299, 336, 381} - , // chars - {3, 35, 67, 99, 131, 163, 195, 227, 259, 291} - , // glyph ids - } - } - }; - - TestCMap kTestCoustard_Regular_ttf_xml = { - "data/fonts/coustard/Coustard-Regular.ttf", - 1, - { - { - 884, // length - 4, // format - 3, // platform id - 1, // encoding id - 10, // num_mappings - {32, 64, 96, 161, 193, 225, 257, 299, 336, 381} - , // chars - {3, 35, 120, 98, 166, 195, 242, 246, 285, 194} - , // glyph ids - } - } - }; - - TestCMap kTestAmaticSC_Bold_ttf_xml = { - "data/fonts/amaticsc/AmaticSC-Bold.ttf", - 1, - { - { - 248, // length - 4, // format - 3, // platform id - 1, // encoding id - 10, // num_mappings - {32, 70, 108, 182, 221, 259, 297, 336, 376, 531} - , // chars - {3, 41, 79, 117, 155, 193, 231, 269, 307, 345} - , // glyph ids - } - } - }; - - TestCMap kTestAmaticSC_Regular_ttf_xml = { - "data/fonts/amaticsc/AmaticSC-Regular.ttf", - 1, - { - { - 240, // length - 4, // format - 3, // platform id - 1, // encoding id - 10, // num_mappings - {32, 69, 106, 178, 216, 253, 290, 327, 365, 498} - , // chars - {3, 40, 77, 114, 151, 188, 225, 262, 299, 336} - , // glyph ids - } - } - }; - - TestCMap kTestComfortaa_Light_ttf_xml = { - "data/fonts/comfortaa/Comfortaa-Light.ttf", - 1, - { - { - 620, // length - 4, // format - 3, // platform id - 1, // encoding id - 10, // num_mappings - {32, 92, 185, 245, 305, 365, 925, 1036, 1097, 8217} - , // chars - {3, 63, 121, 181, 192, 345, 394, 482, 542, 206} - , // glyph ids - } - } - }; - - TestCMap kTestComfortaa_Bold_ttf_xml = { - "data/fonts/comfortaa/Comfortaa-Bold.ttf", - 1, - { - { - 620, // length - 4, // format - 3, // platform id - 1, // encoding id - 10, // num_mappings - {32, 92, 185, 245, 305, 365, 925, 1036, 1097, 8217} - , // chars - {3, 63, 121, 181, 192, 345, 394, 482, 542, 206} - , // glyph ids - } - } - }; - - TestCMap kTestComfortaa_Regular_ttf_xml = { - "data/fonts/comfortaa/Comfortaa-Regular.ttf", - 1, - { - { - 620, // length - 4, // format - 3, // platform id - 1, // encoding id - 10, // num_mappings - {32, 92, 185, 245, 305, 365, 925, 1036, 1097, 8217} - , // chars - {3, 63, 121, 181, 192, 345, 394, 482, 542, 206} - , // glyph ids - } - } - }; - - TestCMap kTestExpletusSans_Bold_ttf_xml = { - "data/fonts/expletussans/ExpletusSans-Bold.ttf", - 2, - { - { - 366, // length - 4, // format - 3, // platform id - 1, // encoding id - 10, // num_mappings - {32, 53, 74, 95, 116, 171, 192, 213, 234, 255} - , // chars - {9, 60, 33, 86, 11, 127, 148, 169, 190, 211} - , // glyph ids - } - , - { - 262, // length - 0, // format - 1, // platform id - 0, // encoding id - 10, // num_mappings - {0, 25, 50, 75, 100, 125, 150, 175, 200, 225} - , // chars - {0, 0, 57, 34, 3, 90, 197, 172, 143, 139} - , // glyph ids - } - } - }; - - TestCMap kTestExpletusSans_MediumItalic_ttf_xml = { - "data/fonts/expletussans/ExpletusSans-MediumItalic.ttf", - 2, - { - { - 578, // length - 4, // format - 3, // platform id - 1, // encoding id - 10, // num_mappings - {32, 53, 74, 95, 116, 171, 192, 213, 234, 255} - , // chars - {7, 140, 41, 29, 66, 182, 110, 112, 87, 166} - , // glyph ids - } - , - { - 262, // length - 0, // format - 1, // platform id - 0, // encoding id - 10, // num_mappings - {0, 25, 50, 75, 100, 125, 150, 175, 200, 225} - , // chars - {0, 0, 137, 42, 62, 58, 93, 164, 181, 157} - , // glyph ids - } - } - }; - - TestCMap kTestExpletusSans_Medium_ttf_xml = { - "data/fonts/expletussans/ExpletusSans-Medium.ttf", - 2, - { - { - 578, // length - 4, // format - 3, // platform id - 1, // encoding id - 10, // num_mappings - {32, 53, 74, 95, 116, 171, 192, 213, 234, 255} - , // chars - {7, 146, 41, 29, 66, 188, 116, 118, 93, 172} - , // glyph ids - } - , - { - 262, // length - 0, // format - 1, // platform id - 0, // encoding id - 10, // num_mappings - {0, 25, 50, 75, 100, 125, 150, 175, 200, 225} - , // chars - {0, 0, 143, 42, 62, 58, 99, 170, 187, 163} - , // glyph ids - } - } - }; - - TestCMap kTestExpletusSans_SemiBold_ttf_xml = { - "data/fonts/expletussans/ExpletusSans-SemiBold.ttf", - 2, - { - { - 578, // length - 4, // format - 3, // platform id - 1, // encoding id - 10, // num_mappings - {32, 53, 74, 95, 116, 171, 192, 213, 234, 255} - , // chars - {7, 146, 41, 29, 66, 188, 116, 118, 93, 172} - , // glyph ids - } - , - { - 262, // length - 0, // format - 1, // platform id - 0, // encoding id - 10, // num_mappings - {0, 25, 50, 75, 100, 125, 150, 175, 200, 225} - , // chars - {0, 0, 143, 42, 62, 58, 99, 170, 187, 163} - , // glyph ids - } - } - }; - - TestCMap kTestExpletusSans_Regular_ttf_xml = { - "data/fonts/expletussans/ExpletusSans-Regular.ttf", - 2, - { - { - 570, // length - 4, // format - 3, // platform id - 1, // encoding id - 10, // num_mappings - {32, 53, 74, 95, 116, 171, 192, 213, 234, 255} - , // chars - {7, 146, 41, 29, 66, 188, 116, 118, 93, 172} - , // glyph ids - } - , - { - 262, // length - 0, // format - 1, // platform id - 0, // encoding id - 10, // num_mappings - {0, 25, 50, 75, 100, 125, 150, 175, 200, 225} - , // chars - {0, 0, 143, 42, 62, 58, 99, 170, 187, 163} - , // glyph ids - } - } - }; - - TestCMap kTestExpletusSans_Italic_ttf_xml = { - "data/fonts/expletussans/ExpletusSans-Italic.ttf", - 2, - { - { - 570, // length - 4, // format - 3, // platform id - 1, // encoding id - 10, // num_mappings - {32, 53, 74, 95, 116, 171, 192, 213, 234, 255} - , // chars - {7, 140, 41, 29, 66, 182, 110, 112, 87, 166} - , // glyph ids - } - , - { - 262, // length - 0, // format - 1, // platform id - 0, // encoding id - 10, // num_mappings - {0, 25, 50, 75, 100, 125, 150, 175, 200, 225} - , // chars - {0, 0, 137, 42, 62, 58, 93, 164, 181, 157} - , // glyph ids - } - } - }; - - TestCMap kTestExpletusSans_SemiBoldItalic_ttf_xml = { - "data/fonts/expletussans/ExpletusSans-SemiBoldItalic.ttf", - 2, - { - { - 578, // length - 4, // format - 3, // platform id - 1, // encoding id - 10, // num_mappings - {32, 53, 74, 95, 116, 171, 192, 213, 234, 255} - , // chars - {7, 139, 41, 29, 65, 181, 109, 111, 86, 165} - , // glyph ids - } - , - { - 262, // length - 0, // format - 1, // platform id - 0, // encoding id - 10, // num_mappings - {0, 25, 50, 75, 100, 125, 150, 175, 200, 225} - , // chars - {0, 0, 136, 42, 62, 58, 92, 163, 180, 156} - , // glyph ids - } - } - }; - - TestCMap kTestExpletusSans_BoldItalic_ttf_xml = { - "data/fonts/expletussans/ExpletusSans-BoldItalic.ttf", - 2, - { - { - 382, // length - 4, // format - 3, // platform id - 1, // encoding id - 10, // num_mappings - {32, 53, 74, 95, 116, 171, 192, 213, 234, 255} - , // chars - {9, 60, 33, 86, 11, 127, 148, 169, 190, 211} - , // glyph ids - } - , - { - 262, // length - 0, // format - 1, // platform id - 0, // encoding id - 10, // num_mappings - {0, 25, 50, 75, 100, 125, 150, 175, 200, 225} - , // chars - {0, 0, 57, 34, 3, 90, 197, 172, 143, 139} - , // glyph ids - } - } - }; - - TestCMap kTestAubrey_Regular_ttf_xml = { - "data/fonts/aubrey/Aubrey-Regular.ttf", - 1, - { - { - 168, // length - 4, // format - 3, // platform id - 1, // encoding id - 10, // num_mappings - {32, 53, 74, 95, 116, 170, 191, 212, 233, 254} - , // chars - {3, 24, 45, 66, 87, 108, 129, 150, 171, 192} - , // glyph ids - } - } - }; - - TestCMap kTestAntic_Regular_ttf_xml = { - "data/fonts/antic/Antic-Regular.ttf", - 2, - { - { - 194, // length - 4, // format - 3, // platform id - 1, // encoding id - 10, // num_mappings - {32, 53, 74, 95, 116, 171, 193, 214, 235, 305} - , // chars - {3, 24, 45, 66, 87, 107, 128, 149, 170, 191} - , // glyph ids - } - , - { - 262, // length - 0, // format - 1, // platform id - 0, // encoding id - 10, // num_mappings - {0, 25, 50, 75, 100, 125, 150, 175, 200, 225} - , // chars - {1, 0, 21, 46, 71, 96, 176, 151, 122, 118} - , // glyph ids - } - } - }; - - TestCMap kTestCopse_Regular_ttf_xml = { - "data/fonts/copse/Copse-Regular.ttf", - 2, - { - { - 152, // length - 4, // format - 3, // platform id - 1, // encoding id - 10, // num_mappings - {0, 51, 72, 93, 114, 168, 189, 210, 231, 252} - , // chars - {1, 22, 43, 64, 85, 106, 127, 148, 169, 190} - , // glyph ids - } - , - { - 262, // length - 0, // format - 1, // platform id - 0, // encoding id - 10, // num_mappings - {0, 25, 50, 75, 100, 125, 150, 175, 200, 225} - , // chars - {1, 0, 21, 46, 71, 96, 179, 154, 125, 121} - , // glyph ids - } - } - }; - - TestCMap kTestDaysOne_Regular_ttf_xml = { - "data/fonts/daysone/DaysOne-Regular.ttf", - 1, - { - { - 320, // length - 4, // format - 3, // platform id - 1, // encoding id - 10, // num_mappings - {32, 67, 102, 170, 206, 241, 321, 1033, 1069, 1105} - , // chars - {3, 38, 73, 108, 143, 178, 213, 248, 283, 318} - , // glyph ids - } - } - }; - - TestCMap kTestActor_Regular_ttf_xml = { - "data/fonts/actor/Actor-Regular.ttf", - 2, - { - { - 702, // length - 4, // format - 3, // platform id - 1, // encoding id - 10, // num_mappings - {32, 55, 78, 101, 124, 180, 203, 226, 249, 731} - , // chars - {3, 195, 33, 105, 79, 65, 16, 64, 209, 234} - , // glyph ids - } - , - { - 262, // length - 0, // format - 1, // platform id - 0, // encoding id - 10, // num_mappings - {0, 25, 50, 75, 100, 125, 150, 175, 200, 225} - , // chars - {1, 0, 204, 29, 96, 81, 154, 41, 129, 173} - , // glyph ids - } - } - }; - - TestCMap kTestBentham_Regular_ttf_xml = { - "data/fonts/bentham/Bentham-Regular.ttf", - 1, - { - { - 248, // length - 4, // format - 3, // platform id - 1, // encoding id - 10, // num_mappings - {19, 62, 93, 124, 208, 242, 275, 306, 339, 370} - , // chars - {3, 34, 65, 96, 127, 158, 189, 220, 251, 282} - , // glyph ids - } - } - }; - - TestCMap kTestFedero_Regular_ttf_xml = { - "data/fonts/federo/Federo-Regular.ttf", - 1, - { - { - 160, // length - 4, // format - 3, // platform id - 1, // encoding id - 10, // num_mappings - {32, 53, 74, 95, 116, 170, 191, 212, 233, 254} - , // chars - {3, 24, 45, 66, 87, 108, 129, 150, 171, 192} - , // glyph ids - } - } - }; - - TestCMap kTestArimo_Italic_ttf_xml = { - "data/fonts/arimo/Arimo-Italic.ttf", - 2, - { - { - 352, // length - 4, // format - 3, // platform id - 1, // encoding id - 10, // num_mappings - {32, 53, 75, 96, 117, 171, 192, 213, 234, 255} - , // chars - {3, 24, 45, 66, 87, 107, 127, 148, 169, 190} - , // glyph ids - } - , - { - 262, // length - 0, // format - 1, // platform id - 0, // encoding id - 10, // num_mappings - {0, 25, 50, 75, 100, 125, 150, 175, 200, 225} - , // chars - {1, 0, 21, 45, 70, 95, 176, 151, 122, 118} - , // glyph ids - } - } - }; - - TestCMap kTestArimo_BoldItalic_ttf_xml = { - "data/fonts/arimo/Arimo-BoldItalic.ttf", - 2, - { - { - 352, // length - 4, // format - 3, // platform id - 1, // encoding id - 10, // num_mappings - {32, 53, 75, 96, 117, 171, 192, 213, 234, 255} - , // chars - {3, 24, 45, 66, 87, 107, 127, 148, 169, 190} - , // glyph ids - } - , - { - 262, // length - 0, // format - 1, // platform id - 0, // encoding id - 10, // num_mappings - {0, 25, 50, 75, 100, 125, 150, 175, 200, 225} - , // chars - {1, 0, 21, 45, 70, 95, 176, 151, 122, 118} - , // glyph ids - } - } - }; - - TestCMap kTestArimo_Bold_ttf_xml = { - "data/fonts/arimo/Arimo-Bold.ttf", - 2, - { - { - 352, // length - 4, // format - 3, // platform id - 1, // encoding id - 10, // num_mappings - {32, 53, 75, 96, 117, 171, 192, 213, 234, 255} - , // chars - {3, 24, 45, 66, 87, 107, 127, 148, 169, 190} - , // glyph ids - } - , - { - 262, // length - 0, // format - 1, // platform id - 0, // encoding id - 10, // num_mappings - {0, 25, 50, 75, 100, 125, 150, 175, 200, 225} - , // chars - {1, 0, 21, 45, 70, 95, 176, 151, 122, 118} - , // glyph ids - } - } - }; - - TestCMap kTestArimo_Regular_ttf_xml = { - "data/fonts/arimo/Arimo-Regular.ttf", - 2, - { - { - 352, // length - 4, // format - 3, // platform id - 1, // encoding id - 10, // num_mappings - {32, 53, 75, 96, 117, 171, 192, 213, 234, 255} - , // chars - {3, 24, 45, 66, 87, 107, 127, 148, 169, 190} - , // glyph ids - } - , - { - 262, // length - 0, // format - 1, // platform id - 0, // encoding id - 10, // num_mappings - {0, 25, 50, 75, 100, 125, 150, 175, 200, 225} - , // chars - {1, 0, 21, 45, 70, 95, 176, 151, 122, 118} - , // glyph ids - } - } - }; - - TestCMap kTestIMFeDPsc28P_ttf_xml = { - "data/fonts/felltypes/IMFeDPsc28P.ttf", - 1, - { - { - 428, // length - 4, // format - 3, // platform id - 1, // encoding id - 10, // num_mappings - {32, 66, 100, 167, 201, 235, 273, 328, 375, 8216} - , // chars - {3, 37, 71, 104, 137, 171, 205, 239, 273, 303} - , // glyph ids - } - } - }; - - TestCMap kTestIMFeGPrm28P_ttf_xml = { - "data/fonts/felltypes/IMFeGPrm28P.ttf", - 1, - { - { - 452, // length - 4, // format - 3, // platform id - 1, // encoding id - 10, // num_mappings - {32, 67, 102, 170, 205, 240, 281, 340, 383, 8225} - , // chars - {3, 38, 73, 107, 141, 176, 211, 246, 281, 311} - , // glyph ids - } - } - }; - - TestCMap kTestIMFeENsc28P_ttf_xml = { - "data/fonts/felltypes/IMFeENsc28P.ttf", - 1, - { - { - 428, // length - 4, // format - 3, // platform id - 1, // encoding id - 10, // num_mappings - {32, 66, 100, 167, 201, 235, 273, 328, 375, 8216} - , // chars - {3, 37, 71, 104, 137, 171, 205, 239, 273, 303} - , // glyph ids - } - } - }; - - TestCMap kTestIMFePIit28P_ttf_xml = { - "data/fonts/felltypes/IMFePIit28P.ttf", - 1, - { - { - 492, // length - 4, // format - 3, // platform id - 1, // encoding id - 10, // num_mappings - {32, 68, 104, 173, 209, 245, 291, 346, 711, 8482} - , // chars - {3, 39, 75, 16, 145, 181, 217, 253, 287, 320} - , // glyph ids - } - } - }; - - TestCMap kTestIMFeDPrm28P_ttf_xml = { - "data/fonts/felltypes/IMFeDPrm28P.ttf", - 1, - { - { - 452, // length - 4, // format - 3, // platform id - 1, // encoding id - 10, // num_mappings - {32, 67, 102, 170, 205, 240, 281, 340, 383, 8225} - , // chars - {3, 38, 73, 107, 141, 176, 211, 246, 281, 311} - , // glyph ids - } - } - }; - - TestCMap kTestIMFePIrm28P_ttf_xml = { - "data/fonts/felltypes/IMFePIrm28P.ttf", - 1, - { - { - 444, // length - 4, // format - 3, // platform id - 1, // encoding id - 10, // num_mappings - {32, 67, 102, 170, 205, 240, 281, 340, 383, 8226} - , // chars - {3, 38, 73, 107, 141, 176, 211, 246, 281, 312} - , // glyph ids - } - } - }; - - TestCMap kTestIMFeFCrm28P_ttf_xml = { - "data/fonts/felltypes/IMFeFCrm28P.ttf", - 1, - { - { - 460, // length - 4, // format - 3, // platform id - 1, // encoding id - 10, // num_mappings - {32, 67, 102, 170, 205, 240, 281, 340, 383, 8225} - , // chars - {3, 38, 73, 107, 141, 176, 211, 246, 281, 311} - , // glyph ids - } - } - }; - - TestCMap kTestIMFeGPit28P_ttf_xml = { - "data/fonts/felltypes/IMFeGPit28P.ttf", - 1, - { - { - 484, // length - 4, // format - 3, // platform id - 1, // encoding id - 10, // num_mappings - {32, 69, 106, 176, 213, 250, 305, 356, 894, 9758} - , // chars - {3, 40, 77, 112, 149, 186, 223, 260, 30, 327} - , // glyph ids - } - } - }; - - TestCMap kTestIMFeENit28P_ttf_xml = { - "data/fonts/felltypes/IMFeENit28P.ttf", - 1, - { - { - 500, // length - 4, // format - 3, // platform id - 1, // encoding id - 10, // num_mappings - {32, 68, 104, 173, 209, 245, 291, 346, 711, 8482} - , // chars - {3, 39, 75, 16, 145, 181, 217, 253, 287, 320} - , // glyph ids - } - } - }; - - TestCMap kTestIMFeDPit28P_ttf_xml = { - "data/fonts/felltypes/IMFeDPit28P.ttf", - 1, - { - { - 476, // length - 4, // format - 3, // platform id - 1, // encoding id - 10, // num_mappings - {32, 70, 108, 179, 217, 255, 315, 368, 7813, 57355} - , // chars - {3, 41, 79, 115, 153, 191, 229, 267, 300, 336} - , // glyph ids - } - } - }; - - TestCMap kTestIMFeENrm28P_ttf_xml = { - "data/fonts/felltypes/IMFeENrm28P.ttf", - 1, - { - { - 468, // length - 4, // format - 3, // platform id - 1, // encoding id - 10, // num_mappings - {32, 67, 102, 170, 205, 240, 281, 340, 383, 8225} - , // chars - {3, 38, 73, 107, 141, 176, 211, 246, 281, 311} - , // glyph ids - } - } - }; - - TestCMap kTestIMFeGPsc28P_ttf_xml = { - "data/fonts/felltypes/IMFeGPsc28P.ttf", - 1, - { - { - 428, // length - 4, // format - 3, // platform id - 1, // encoding id - 10, // num_mappings - {32, 66, 100, 167, 201, 235, 273, 328, 375, 8216} - , // chars - {3, 37, 71, 104, 137, 171, 205, 239, 273, 303} - , // glyph ids - } - } - }; - - TestCMap kTestIMFePIsc28P_ttf_xml = { - "data/fonts/felltypes/IMFePIsc28P.ttf", - 1, - { - { - 428, // length - 4, // format - 3, // platform id - 1, // encoding id - 10, // num_mappings - {32, 66, 100, 167, 201, 235, 273, 328, 375, 8216} - , // chars - {3, 37, 71, 104, 137, 171, 205, 239, 273, 303} - , // glyph ids - } - } - }; - - TestCMap kTestIMFeFCsc28P_ttf_xml = { - "data/fonts/felltypes/IMFeFCsc28P.ttf", - 1, - { - { - 436, // length - 4, // format - 3, // platform id - 1, // encoding id - 10, // num_mappings - {32, 66, 100, 167, 201, 235, 273, 328, 375, 8212} - , // chars - {3, 37, 71, 104, 137, 171, 205, 239, 273, 302} - , // glyph ids - } - } - }; - - TestCMap kTestIMFeFCit28P_ttf_xml = { - "data/fonts/felltypes/IMFeFCit28P.ttf", - 1, - { - { - 452, // length - 4, // format - 3, // platform id - 1, // encoding id - 10, // num_mappings - {32, 69, 106, 176, 213, 250, 305, 356, 894, 9758} - , // chars - {3, 40, 77, 112, 149, 186, 223, 260, 30, 327} - , // glyph ids - } - } - }; - - TestCMap kTestBokor_ttf_xml = { - "data/fonts/bokor/Bokor.ttf", - 2, - { - { - 96, // length - 4, // format - 3, // platform id - 1, // encoding id - 10, // num_mappings - {32, 45, 58, 6019, 6032, 6045, 6058, 6073, 6086, 6099} - , // chars - {3, 16, 29, 39, 52, 65, 78, 91, 104, 117} - , // glyph ids - } - , - { - 262, // length - 0, // format - 1, // platform id - 0, // encoding id - 10, // num_mappings - {0, 25, 50, 75, 100, 125, 150, 175, 200, 225} - , // chars - {1, 0, 21, 0, 0, 0, 0, 0, 0, 0} - , // glyph ids - } - } - }; - - TestCMap kTestDidactGothic_ttf_xml = { - "data/fonts/didactgothic/DidactGothic.ttf", - 1, - { - { - 1048, // length - 4, // format - 3, // platform id - 1, // encoding id - 10, // num_mappings - {32, 179, 293, 430, 772, 1033, 1189, 7701, 7960, 8082} - , // chars - {3, 117, 231, 345, 459, 573, 687, 801, 915, 1029} - , // glyph ids - } - } - }; - - TestCMap kTestAllerta_Medium_ttf_xml = { - "data/fonts/allerta/Allerta-Medium.ttf", - 2, - { - { - 252, // length - 4, // format - 3, // platform id - 1, // encoding id - 10, // num_mappings - {32, 51, 69, 87, 107, 161, 200, 219, 238, 321} - , // chars - {3, 21, 39, 57, 75, 92, 110, 128, 146, 164} - , // glyph ids - } - , - { - 262, // length - 0, // format - 1, // platform id - 0, // encoding id - 10, // num_mappings - {0, 25, 50, 75, 100, 125, 150, 175, 200, 225} - , // chars - {1, 0, 20, 45, 68, 0, 149, 0, 101, 0} - , // glyph ids - } - } - }; - - TestCMap kTestAllerta_Stencil_ttf_xml = { - "data/fonts/allerta/Allerta-Stencil.ttf", - 2, - { - { - 252, // length - 4, // format - 3, // platform id - 1, // encoding id - 10, // num_mappings - {32, 51, 69, 87, 107, 161, 200, 219, 238, 321} - , // chars - {3, 21, 39, 57, 75, 92, 110, 128, 146, 164} - , // glyph ids - } - , - { - 262, // length - 0, // format - 1, // platform id - 0, // encoding id - 10, // num_mappings - {0, 25, 50, 75, 100, 125, 150, 175, 200, 225} - , // chars - {1, 0, 20, 45, 68, 0, 149, 0, 101, 0} - , // glyph ids - } - } - }; - - TestCMap kTestBuda_Light_ttf_xml = { - "data/fonts/buda/Buda-Light.ttf", - 2, - { - { - 552, // length - 4, // format - 3, // platform id - 1, // encoding id - 10, // num_mappings - {32, 53, 74, 95, 116, 170, 192, 213, 234, 255} - , // chars - {191, 114, 30, 206, 193, 158, 8, 42, 103, 212} - , // glyph ids - } - , - { - 262, // length - 0, // format - 1, // platform id - 0, // encoding id - 10, // num_mappings - {0, 25, 50, 75, 100, 125, 150, 175, 200, 225} - , // chars - {1, 0, 199, 31, 94, 78, 146, 41, 124, 168} - , // glyph ids - } - } - }; - - TestCMap kTestBrawler_Regular_ttf_xml = { - "data/fonts/brawler/Brawler-Regular.ttf", - 2, - { - { - 242, // length - 4, // format - 3, // platform id - 1, // encoding id - 10, // num_mappings - {32, 54, 76, 98, 120, 175, 197, 219, 241, 730} - , // chars - {2, 24, 46, 68, 90, 111, 129, 151, 173, 192} - , // glyph ids - } - , - { - 262, // length - 0, // format - 1, // platform id - 0, // encoding id - 10, // num_mappings - {0, 25, 50, 75, 100, 125, 150, 175, 200, 225} - , // chars - {0, 0, 20, 45, 70, 95, 173, 148, 119, 116} - , // glyph ids - } - } - }; - - TestCMap kTestCarterOne_ttf_xml = { - "data/fonts/carterone/CarterOne.ttf", - 1, - { - { - 322, // length - 4, // format - 3, // platform id - 1, // encoding id - 10, // num_mappings - {32, 58, 84, 110, 169, 197, 223, 249, 515, 711} - , // chars - {3, 29, 55, 81, 106, 132, 158, 184, 210, 236} - , // glyph ids - } - } - }; - - TestCMap kTestCandal_ttf_xml = { - "data/fonts/candal/Candal.ttf", - 1, - { - { - 448, // length - 4, // format - 3, // platform id - 1, // encoding id - 10, // num_mappings - {0, 61, 95, 162, 196, 230, 270, 340, 518, 806} - , // chars - {1, 36, 70, 104, 138, 172, 206, 240, 274, 308} - , // glyph ids - } - } - }; - - TestCMap kTestDorsa_Regular_ttf_xml = { - "data/fonts/dorsa/Dorsa-Regular.ttf", - 2, - { - { - 194, // length - 4, // format - 3, // platform id - 1, // encoding id - 10, // num_mappings - {32, 53, 74, 95, 116, 170, 193, 214, 235, 338} - , // chars - {3, 24, 45, 66, 87, 107, 128, 149, 170, 191} - , // glyph ids - } - , - { - 262, // length - 0, // format - 1, // platform id - 0, // encoding id - 10, // num_mappings - {0, 25, 50, 75, 100, 125, 150, 175, 200, 225} - , // chars - {1, 0, 21, 46, 71, 96, 176, 151, 122, 118} - , // glyph ids - } - } - }; - - TestCMap kTestCrimsonText_BoldItalic_ttf_xml = { - "data/fonts/crimson/CrimsonText-BoldItalic.ttf", - 1, - { - { - 336, // length - 4, // format - 3, // platform id - 1, // encoding id - 10, // num_mappings - {32, 75, 118, 195, 238, 281, 324, 368, 8194, 8730} - , // chars - {3, 46, 89, 132, 175, 218, 261, 304, 347, 390} - , // glyph ids - } - } - }; - - TestCMap kTestCrimsonText_Bold_ttf_xml = { - "data/fonts/crimson/CrimsonText-Bold.ttf", - 1, - { - { - 464, // length - 4, // format - 3, // platform id - 1, // encoding id - 10, // num_mappings - {32, 105, 212, 285, 359, 550, 7719, 7794, 7873, 8222} - , // chars - {3, 76, 149, 222, 295, 368, 441, 514, 587, 660} - , // glyph ids - } - } - }; - - TestCMap kTestCrimsonText_Italic_ttf_xml = { - "data/fonts/crimson/CrimsonText-Italic.ttf", - 1, - { - { - 328, // length - 4, // format - 3, // platform id - 1, // encoding id - 10, // num_mappings - {32, 75, 118, 195, 238, 281, 324, 367, 779, 8733} - , // chars - {3, 46, 89, 132, 175, 218, 261, 304, 347, 390} - , // glyph ids - } - } - }; - - TestCMap kTestCrimsonText_Roman_ttf_xml = { - "data/fonts/crimson/CrimsonText-Roman.ttf", - 1, - { - { - 712, // length - 4, // format - 3, // platform id - 1, // encoding id - 10, // num_mappings - {32, 188, 310, 770, 995, 1117, 7792, 7920, 8060, 8195} - , // chars - {3, 125, 247, 369, 491, 613, 735, 857, 979, 1101} - , // glyph ids - } - } - }; - - TestCMap kTestCrimsonText_Semibold_ttf_xml = { - "data/fonts/crimson/CrimsonText-Semibold.ttf", - 1, - { - { - 336, // length - 4, // format - 3, // platform id - 1, // encoding id - 10, // num_mappings - {32, 76, 120, 198, 242, 286, 331, 375, 779, 8712} - , // chars - {3, 47, 91, 135, 179, 223, 267, 311, 355, 399} - , // glyph ids - } - } - }; - - TestCMap kTestCrimsonText_SemiboldItalic_ttf_xml = { - "data/fonts/crimson/CrimsonText-SemiboldItalic.ttf", - 1, - { - { - 296, // length - 4, // format - 3, // platform id - 1, // encoding id - 10, // num_mappings - {32, 75, 118, 195, 238, 281, 324, 368, 775, 8722} - , // chars - {3, 46, 89, 132, 175, 218, 261, 304, 347, 390} - , // glyph ids - } - } - }; - - TestCMap kTestAmaranth_Italic_ttf_xml = { - "data/fonts/amaranth/Amaranth-Italic.ttf", - 2, - { - { - 566, // length - 4, // format - 3, // platform id - 1, // encoding id - 10, // num_mappings - {32, 53, 74, 95, 116, 170, 191, 212, 233, 254} - , // chars - {3, 62, 41, 120, 22, 78, 105, 170, 193, 144} - , // glyph ids - } - , - { - 262, // length - 0, // format - 1, // platform id - 0, // encoding id - 10, // num_mappings - {0, 25, 50, 75, 100, 125, 150, 175, 200, 225} - , // chars - {1, 0, 63, 40, 216, 125, 198, 108, 141, 123} - , // glyph ids - } - } - }; - - TestCMap kTestAmaranth_Bold_ttf_xml = { - "data/fonts/amaranth/Amaranth-Bold.ttf", - 2, - { - { - 566, // length - 4, // format - 3, // platform id - 1, // encoding id - 10, // num_mappings - {32, 53, 74, 95, 116, 170, 191, 212, 233, 254} - , // chars - {3, 62, 41, 121, 22, 78, 106, 168, 191, 145} - , // glyph ids - } - , - { - 262, // length - 0, // format - 1, // platform id - 0, // encoding id - 10, // num_mappings - {0, 25, 50, 75, 100, 125, 150, 175, 200, 225} - , // chars - {1, 0, 63, 40, 216, 126, 196, 109, 142, 124} - , // glyph ids - } - } - }; - - TestCMap kTestAmaranth_Regular_ttf_xml = { - "data/fonts/amaranth/Amaranth-Regular.ttf", - 2, - { - { - 566, // length - 4, // format - 3, // platform id - 1, // encoding id - 10, // num_mappings - {32, 53, 74, 95, 116, 170, 191, 212, 233, 254} - , // chars - {3, 62, 41, 121, 22, 78, 106, 168, 191, 145} - , // glyph ids - } - , - { - 262, // length - 0, // format - 1, // platform id - 0, // encoding id - 10, // num_mappings - {0, 25, 50, 75, 100, 125, 150, 175, 200, 225} - , // chars - {1, 0, 63, 40, 216, 126, 196, 109, 142, 124} - , // glyph ids - } - } - }; - - TestCMap kTestAmaranth_BoldItalic_ttf_xml = { - "data/fonts/amaranth/Amaranth-BoldItalic.ttf", - 2, - { - { - 566, // length - 4, // format - 3, // platform id - 1, // encoding id - 10, // num_mappings - {32, 53, 74, 95, 116, 170, 191, 212, 233, 254} - , // chars - {3, 62, 41, 120, 22, 78, 105, 177, 200, 144} - , // glyph ids - } - , - { - 262, // length - 0, // format - 1, // platform id - 0, // encoding id - 10, // num_mappings - {0, 25, 50, 75, 100, 125, 150, 175, 200, 225} - , // chars - {1, 0, 63, 40, 223, 125, 205, 108, 141, 123} - , // glyph ids - } - } - }; - - TestCMap kTestCrushed_ttf_xml = { - "data/fonts/crushed/Crushed.ttf", - 1, - { - { - 696, // length - 4, // format - 3, // platform id - 1, // encoding id - 10, // num_mappings - {32, 68, 104, 173, 209, 245, 281, 318, 354, 711} - , // chars - {362, 4, 34, 345, 160, 178, 109, 155, 209, 355} - , // glyph ids - } - } - }; - - TestCMap kTestAdamina_Regular_ttf_xml = { - "data/fonts/adamina/Adamina-Regular.ttf", - 2, - { - { - 160, // length - 4, // format - 3, // platform id - 1, // encoding id - 10, // num_mappings - {32, 53, 74, 95, 116, 170, 191, 212, 233, 254} - , // chars - {3, 24, 45, 66, 87, 108, 129, 150, 171, 192} - , // glyph ids - } - , - { - 262, // length - 0, // format - 1, // platform id - 0, // encoding id - 10, // num_mappings - {0, 25, 50, 75, 100, 125, 150, 175, 200, 225} - , // chars - {1, 0, 21, 46, 71, 96, 179, 154, 125, 121} - , // glyph ids - } - } - }; - - TestCMap kTestAldrich_Regular_ttf_xml = { - "data/fonts/aldrich/Aldrich-Regular.ttf", - 1, - { - { - 262, // length - 4, // format - 3, // platform id - 1, // encoding id - 10, // num_mappings - {32, 56, 80, 104, 161, 186, 210, 234, 297, 381} - , // chars - {3, 25, 49, 73, 97, 121, 145, 169, 193, 217} - , // glyph ids - } - } - }; - - TestCMap kTestFanwoodText_Italic_ttf_xml = { - "data/fonts/fanwoodtext/FanwoodText-Italic.ttf", - 1, - { - { - 312, // length - 4, // format - 3, // platform id - 1, // encoding id - 10, // num_mappings - {32, 73, 114, 188, 229, 270, 311, 352, 711, 8193} - , // chars - {3, 44, 85, 126, 167, 208, 249, 290, 331, 372} - , // glyph ids - } - } - }; - - TestCMap kTestFanwoodText_Regular_ttf_xml = { - "data/fonts/fanwoodtext/FanwoodText-Regular.ttf", - 1, - { - { - 312, // length - 4, // format - 3, // platform id - 1, // encoding id - 10, // num_mappings - {32, 73, 114, 188, 229, 270, 311, 352, 711, 8193} - , // chars - {3, 44, 85, 126, 167, 208, 249, 290, 331, 372} - , // glyph ids - } - } - }; - - TestCMap kTestAnonymousPro_Regular_ttf_xml = { - "data/fonts/anonymouspro/AnonymousPro-Regular.ttf", - 1, - { - { - 974, // length - 4, // format - 3, // platform id - 1, // encoding id - 10, // num_mappings - {0, 92, 187, 249, 311, 373, 938, 1051, 1114, 8963} - , // chars - {1, 61, 168, 125, 297, 357, 408, 469, 531, 563} - , // glyph ids - } - } - }; - - TestCMap kTestAnonymousPro_Bold_ttf_xml = { - "data/fonts/anonymouspro/AnonymousPro-Bold.ttf", - 1, - { - { - 974, // length - 4, // format - 3, // platform id - 1, // encoding id - 10, // num_mappings - {0, 92, 187, 249, 311, 373, 938, 1051, 1114, 8963} - , // chars - {1, 61, 168, 125, 297, 357, 408, 469, 531, 563} - , // glyph ids - } - } - }; - - TestCMap kTestAnonymousPro_Italic_ttf_xml = { - "data/fonts/anonymouspro/AnonymousPro-Italic.ttf", - 1, - { - { - 974, // length - 4, // format - 3, // platform id - 1, // encoding id - 10, // num_mappings - {0, 92, 187, 249, 311, 373, 938, 1051, 1114, 8963} - , // chars - {1, 61, 168, 125, 297, 357, 408, 469, 531, 563} - , // glyph ids - } - } - }; - - TestCMap kTestAnonymousPro_BoldItalic_ttf_xml = { - "data/fonts/anonymouspro/AnonymousPro-BoldItalic.ttf", - 1, - { - { - 974, // length - 4, // format - 3, // platform id - 1, // encoding id - 10, // num_mappings - {0, 92, 187, 249, 311, 373, 938, 1051, 1114, 8963} - , // chars - {1, 61, 168, 125, 297, 357, 408, 469, 531, 563} - , // glyph ids - } - } - }; - - TestCMap kTestBevan_ttf_xml = { - "data/fonts/bevan/Bevan.ttf", - 1, - { - { - 400, // length - 4, // format - 3, // platform id - 1, // encoding id - 10, // num_mappings - {32, 75, 118, 194, 237, 280, 325, 368, 531, 8200} - , // chars - {3, 46, 89, 132, 175, 218, 261, 304, 347, 390} - , // glyph ids - } - } - }; - - TestCMap kTestArtifika_Regular_ttf_xml = { - "data/fonts/artifika/Artifika-Regular.ttf", - 1, - { - { - 160, // length - 4, // format - 3, // platform id - 1, // encoding id - 10, // num_mappings - {2, 52, 73, 94, 115, 169, 190, 211, 232, 253} - , // chars - {3, 24, 45, 66, 87, 108, 129, 150, 171, 192} - , // glyph ids - } - } - }; - - TestCMap kTestAnton_ttf_xml = { - "data/fonts/anton/Anton.ttf", - 1, - { - { - 384, // length - 4, // format - 3, // platform id - 1, // encoding id - 10, // num_mappings - {32, 73, 114, 189, 230, 271, 315, 356, 517, 7809} - , // chars - {3, 44, 85, 126, 167, 208, 249, 290, 331, 372} - , // glyph ids - } - } - }; - - TestCMap kTestBattambang_Regular_ttf_xml = { - "data/fonts/battambang/Battambang-Regular.ttf", - 2, - { - { - 96, // length - 4, // format - 3, // platform id - 1, // encoding id - 10, // num_mappings - {32, 45, 58, 6019, 6032, 6045, 6058, 6073, 6086, 6099} - , // chars - {3, 16, 29, 39, 52, 65, 78, 91, 104, 117} - , // glyph ids - } - , - { - 262, // length - 0, // format - 1, // platform id - 0, // encoding id - 10, // num_mappings - {0, 25, 50, 75, 100, 125, 150, 175, 200, 225} - , // chars - {1, 0, 21, 0, 0, 0, 0, 0, 0, 0} - , // glyph ids - } - } - }; - - TestCMap kTestBattambang_Bold_ttf_xml = { - "data/fonts/battambang/Battambang-Bold.ttf", - 2, - { - { - 96, // length - 4, // format - 3, // platform id - 1, // encoding id - 10, // num_mappings - {32, 45, 58, 6019, 6032, 6045, 6058, 6073, 6086, 6099} - , // chars - {3, 16, 29, 39, 52, 65, 78, 91, 104, 117} - , // glyph ids - } - , - { - 262, // length - 0, // format - 1, // platform id - 0, // encoding id - 10, // num_mappings - {0, 25, 50, 75, 100, 125, 150, 175, 200, 225} - , // chars - {1, 0, 21, 0, 0, 0, 0, 0, 0, 0} - , // glyph ids - } - } - }; - - TestCMap kTestCarme_Regular_ttf_xml = { - "data/fonts/carme/Carme-Regular.ttf", - 2, - { - { - 256, // length - 4, // format - 3, // platform id - 1, // encoding id - 10, // num_mappings - {32, 53, 74, 96, 117, 179, 204, 227, 249, 8201} - , // chars - {3, 24, 45, 66, 87, 108, 129, 150, 171, 192} - , // glyph ids - } - , - { - 262, // length - 0, // format - 1, // platform id - 0, // encoding id - 10, // num_mappings - {0, 25, 50, 75, 100, 125, 150, 175, 200, 225} - , // chars - {1, 0, 21, 46, 70, 95, 164, 140, 0, 0} - , // glyph ids - } - } - }; - - TestCMap kTestCherryCreamSoda_ttf_xml = { - "data/fonts/cherrycreamsoda/CherryCreamSoda.ttf", - 2, - { - { - 422, // length - 4, // format - 3, // platform id - 1, // encoding id - 10, // num_mappings - {32, 54, 76, 98, 120, 175, 198, 220, 242, 381} - , // chars - {21, 43, 65, 87, 109, 217, 159, 122, 140, 10} - , // glyph ids - } - , - { - 262, // length - 0, // format - 1, // platform id - 0, // encoding id - 10, // num_mappings - {0, 25, 50, 75, 100, 125, 150, 175, 200, 225} - , // chars - {0, 0, 39, 64, 89, 114, 138, 160, 172, 195} - , // glyph ids - } - } - }; - - TestCMap kTestDeliusUnicase_Regular_ttf_xml = { - "data/fonts/deliusunicase/DeliusUnicase-Regular.ttf", - 2, - { - { - 240, // length - 4, // format - 3, // platform id - 1, // encoding id - 10, // num_mappings - {32, 57, 82, 107, 165, 190, 215, 240, 309, 956} - , // chars - {3, 28, 53, 78, 103, 128, 153, 178, 203, 119} - , // glyph ids - } - , - { - 262, // length - 0, // format - 1, // platform id - 0, // encoding id - 10, // num_mappings - {0, 25, 50, 75, 100, 125, 150, 175, 200, 225} - , // chars - {1, 0, 21, 46, 71, 96, 179, 154, 125, 121} - , // glyph ids - } - } - }; - - TestCMap kTestComingSoon_ttf_xml = { - "data/fonts/comingsoon/ComingSoon.ttf", - 2, - { - { - 412, // length - 4, // format - 3, // platform id - 1, // encoding id - 10, // num_mappings - {32, 54, 76, 98, 120, 175, 197, 219, 241, 376} - , // chars - {21, 43, 65, 87, 109, 216, 117, 211, 138, 187} - , // glyph ids - } - , - { - 262, // length - 0, // format - 1, // platform id - 0, // encoding id - 10, // num_mappings - {0, 25, 50, 75, 100, 125, 150, 175, 200, 225} - , // chars - {0, 0, 39, 64, 89, 114, 138, 160, 171, 194} - , // glyph ids - } - } - }; - - TestCMap kTestFreehand_ttf_xml = { - "data/fonts/freehand/Freehand.ttf", - 2, - { - { - 96, // length - 4, // format - 3, // platform id - 1, // encoding id - 10, // num_mappings - {32, 45, 58, 6019, 6032, 6045, 6058, 6073, 6086, 6099} - , // chars - {3, 16, 29, 39, 52, 65, 78, 91, 104, 117} - , // glyph ids - } - , - { - 262, // length - 0, // format - 1, // platform id - 0, // encoding id - 10, // num_mappings - {0, 25, 50, 75, 100, 125, 150, 175, 200, 225} - , // chars - {1, 0, 21, 0, 0, 0, 0, 0, 0, 0} - , // glyph ids - } - } - }; - - TestCMap kTestAlice_Regular_ttf_xml = { - "data/fonts/alice/Alice-Regular.ttf", - 1, - { - { - 160, // length - 4, // format - 3, // platform id - 1, // encoding id - 10, // num_mappings - {32, 53, 74, 95, 116, 170, 191, 212, 233, 254} - , // chars - {3, 24, 45, 66, 87, 108, 129, 150, 171, 192} - , // glyph ids - } - } - }; - - TestCMap kTestContrail_Regular_ttf_xml = { - "data/fonts/contrail/Contrail-Regular.ttf", - 2, - { - { - 368, // length - 4, // format - 3, // platform id - 1, // encoding id - 10, // num_mappings - {32, 55, 78, 101, 124, 180, 203, 226, 249, 339} - , // chars - {3, 26, 49, 72, 95, 117, 140, 163, 186, 209} - , // glyph ids - } - , - { - 262, // length - 0, // format - 1, // platform id - 0, // encoding id - 10, // num_mappings - {0, 25, 50, 75, 100, 125, 150, 175, 200, 225} - , // chars - {1, 0, 21, 46, 71, 96, 178, 153, 124, 120} - , // glyph ids - } - } - }; - - TestCMap kTestCardo_Bold_ttf_xml = { - "data/fonts/cardo/Cardo-Bold.ttf", - 1, - { - { - 3676, // length - 4, // format - 3, // platform id - 1, // encoding id - 10, // num_mappings - {32, 295, 653, 883, 5792, 7961, 8212, 10219, 58808, 61909} - , // chars - {3, 232, 461, 691, 921, 1151, 1381, 1610, 1840, 2070} - , // glyph ids - } - } - }; - - TestCMap kTestCardo_Italic_ttf_xml = { - "data/fonts/cardo/Cardo-Italic.ttf", - 1, - { - { - 3788, // length - 4, // format - 3, // platform id - 1, // encoding id - 10, // num_mappings - {32, 306, 662, 921, 5833, 8008, 8313, 42804, 58625, 61889} - , // chars - {3, 243, 483, 724, 965, 1206, 1447, 1687, 1926, 2139} - , // glyph ids - } - } - }; - - TestCMap kTestCardo_Regular_ttf_xml = { - "data/fonts/cardo/Cardo-Regular.ttf", - 1, - { - { - 4686, // length - 4, // format - 3, // platform id - 1, // encoding id - 10, // num_mappings - {32, 376, 802, 4347, 8000, 8710, 57497, 59336, 61431, 62510} - , // chars - {3, 313, 623, 934, 1245, 729, 1866, 2175, 2481, 2792} - , // glyph ids - } - } - }; - - TestCMap kTestAsset_ttf_xml = { - "data/fonts/asset/Asset.ttf", - 2, - { - { - 210, // length - 4, // format - 3, // platform id - 1, // encoding id - 10, // num_mappings - {32, 54, 76, 98, 120, 176, 198, 220, 242, 312} - , // chars - {3, 25, 47, 69, 91, 112, 134, 156, 178, 200} - , // glyph ids - } - , - { - 262, // length - 0, // format - 1, // platform id - 0, // encoding id - 10, // num_mappings - {0, 25, 50, 75, 100, 125, 150, 175, 200, 225} - , // chars - {1, 0, 21, 46, 71, 96, 177, 152, 123, 119} - , // glyph ids - } - } - }; - - TestCMap kTestChangaOne_Regular_ttf_xml = { - "data/fonts/changaone/ChangaOne-Regular.ttf", - 2, - { - { - 320, // length - 4, // format - 3, // platform id - 1, // encoding id - 10, // num_mappings - {32, 56, 80, 104, 162, 188, 212, 236, 339, 8224} - , // chars - {3, 27, 51, 75, 99, 123, 147, 171, 195, 219} - , // glyph ids - } - , - { - 262, // length - 0, // format - 1, // platform id - 0, // encoding id - 10, // num_mappings - {0, 25, 50, 75, 100, 125, 150, 175, 200, 225} - , // chars - {1, 0, 21, 46, 71, 96, 176, 151, 122, 118} - , // glyph ids - } - } - }; - - TestCMap kTestAclonica_ttf_xml = { - "data/fonts/aclonica/Aclonica.ttf", - 2, - { - { - 718, // length - 4, // format - 3, // platform id - 1, // encoding id - 10, // num_mappings - {32, 68, 104, 173, 209, 245, 281, 317, 353, 711} - , // chars - {3, 50, 86, 233, 201, 224, 267, 333, 172, 170} - , // glyph ids - } - , - { - 262, // length - 0, // format - 1, // platform id - 0, // encoding id - 10, // num_mappings - {0, 25, 50, 75, 100, 125, 150, 175, 200, 225} - , // chars - {1, 0, 32, 57, 82, 107, 219, 124, 140, 156} - , // glyph ids - } - } - }; - - TestCMap kTestCraftyGirls_ttf_xml = { - "data/fonts/craftygirls/CraftyGirls.ttf", - 2, - { - { - 428, // length - 4, // format - 3, // platform id - 1, // encoding id - 10, // num_mappings - {32, 54, 76, 98, 120, 175, 197, 219, 241, 376} - , // chars - {21, 43, 65, 87, 109, 219, 117, 214, 138, 189} - , // glyph ids - } - , - { - 262, // length - 0, // format - 1, // platform id - 0, // encoding id - 10, // num_mappings - {0, 25, 50, 75, 100, 125, 150, 175, 200, 225} - , // chars - {0, 0, 39, 64, 89, 114, 138, 160, 173, 196} - , // glyph ids - } - } - }; - - TestCMap kTestArchitectsDaughter_ttf_xml = { - "data/fonts/architectsdaughter/ArchitectsDaughter.ttf", - 1, - { - { - 282, // length - 4, // format - 3, // platform id - 1, // encoding id - 10, // num_mappings - {32, 66, 100, 167, 202, 236, 270, 311, 349, 508} - , // chars - {3, 37, 71, 104, 138, 172, 206, 240, 274, 308} - , // glyph ids - } - } - }; - - TestCMap kTestContent_Bold_ttf_xml = { - "data/fonts/content/Content-Bold.ttf", - 2, - { - { - 96, // length - 4, // format - 3, // platform id - 1, // encoding id - 10, // num_mappings - {32, 45, 58, 6019, 6032, 6045, 6058, 6073, 6086, 6099} - , // chars - {3, 16, 29, 39, 52, 65, 78, 91, 104, 117} - , // glyph ids - } - , - { - 262, // length - 0, // format - 1, // platform id - 0, // encoding id - 10, // num_mappings - {0, 25, 50, 75, 100, 125, 150, 175, 200, 225} - , // chars - {1, 0, 21, 0, 0, 0, 0, 0, 0, 0} - , // glyph ids - } - } - }; - - TestCMap kTestContent_Regular_ttf_xml = { - "data/fonts/content/Content-Regular.ttf", - 2, - { - { - 96, // length - 4, // format - 3, // platform id - 1, // encoding id - 10, // num_mappings - {32, 45, 58, 6019, 6032, 6045, 6058, 6073, 6086, 6099} - , // chars - {3, 16, 29, 39, 52, 65, 78, 91, 104, 117} - , // glyph ids - } - , - { - 262, // length - 0, // format - 1, // platform id - 0, // encoding id - 10, // num_mappings - {0, 25, 50, 75, 100, 125, 150, 175, 200, 225} - , // chars - {1, 0, 21, 0, 0, 0, 0, 0, 0, 0} - , // glyph ids - } - } - }; - - TestCMap kTestAbel_Regular_ttf_xml = { - "data/fonts/abel/Abel-Regular.ttf", - 2, - { - { - 248, // length - 4, // format - 3, // platform id - 1, // encoding id - 10, // num_mappings - {32, 56, 80, 104, 161, 186, 210, 234, 297, 381} - , // chars - {3, 27, 51, 75, 99, 123, 147, 171, 195, 219} - , // glyph ids - } - , - { - 262, // length - 0, // format - 1, // platform id - 0, // encoding id - 10, // num_mappings - {0, 25, 50, 75, 100, 125, 150, 175, 200, 225} - , // chars - {1, 0, 21, 46, 71, 96, 178, 153, 124, 120} - , // glyph ids - } - } - }; - - TestCMap kTestCuprum_ttf_xml = { - "data/fonts/cuprum/Cuprum.ttf", - 1, - { - { - 352, // length - 4, // format - 3, // platform id - 1, // encoding id - 10, // num_mappings - {32, 69, 106, 176, 213, 250, 324, 1028, 1066, 1103} - , // chars - {3, 40, 77, 114, 151, 188, 225, 262, 299, 336} - , // glyph ids - } - } - }; - - TestCMap kTestAndika_R_ttf_xml = { - "data/fonts/andika/Andika-R.ttf", - 1, - { - { - 4792, // length - 4, // format - 3, // platform id - 1, // encoding id - 10, // num_mappings - {13, 281, 498, 715, 1067, 7424, 7691, 7908, 8580, 61860} - , // chars - {2, 817, 745, 2639, 597, 474, 699, 2213, 644, 876} - , // glyph ids - } - } - }; - -} // namespace sfntly diff --git a/test/autogenerated/cmap_test_data.h b/test/autogenerated/cmap_test_data.h index 63fd9c9..4a9f267 100644 --- a/test/autogenerated/cmap_test_data.h +++ b/test/autogenerated/cmap_test_data.h @@ -20,334 +20,166 @@ * limitations under the License. */ -#ifndef SFNTLY_CPP_SRC_TEST_CMAP_TEST_DATA_H_ -#define SFNTLY_CPP_SRC_TEST_CMAP_TEST_DATA_H_ +#ifndef TYPOGRAPHY_FONT_SFNTLY_SRC_TEST_AUTOGENERATED_CMAP_TEST_DATA_H_ +#define TYPOGRAPHY_FONT_SFNTLY_SRC_TEST_AUTOGENERATED_CMAP_TEST_DATA_H_ #include "sfntly/port/type.h" -namespace sfntly -{ - struct ProtoCMap - { - int32_t length; - int32_t format; - int32_t platform_id; - int32_t encoding_id; - int32_t num_mappings; - int32_t chars[10]; - int32_t glyph_ids[10]; - }; +namespace sfntly { +namespace cmap_test_data { +const char* kAllTests[] = { + "data/fonts/cousine/Cousine-BoldItalic.ttf", + "data/fonts/cousine/Cousine-Bold.ttf", + "data/fonts/cousine/Cousine-Regular.ttf", + "data/fonts/cousine/Cousine-Italic.ttf", + "data/fonts/cedarvillecursive/Cedarville-Cursive.ttf", + "data/fonts/dancingscript/DancingScript-Bold.ttf", + "data/fonts/dancingscript/DancingScript-Regular.ttf", + "data/fonts/damion/Damion-Regular.ttf", + "data/fonts/annieuseyourtelescope/AnnieUseYourTelescope.ttf", + "data/fonts/deliusswashcaps/DeliusSwashCaps-Regular.ttf", + "data/fonts/delius/Delius-Regular.ttf", + "data/fonts/coveredbyyourgrace/CoveredByYourGrace.ttf", + "data/fonts/ebgaramond/EBGaramond-Regular.ttf", + "data/fonts/cabinsketch/CabinSketch-Bold.ttf", + "data/fonts/allan/Allan-Bold.ttf", + "data/fonts/coda/Coda-Caption-Heavy.ttf", + "data/fonts/coda/Coda-Heavy.ttf", + "data/fonts/forum/Forum-Regular.ttf", + "data/fonts/alike/Alike-Regular.ttf", + "data/fonts/corben/Corben-Bold.ttf", + "data/fonts/caudex/Caudex-Regular.ttf", + "data/fonts/caudex/Caudex-BoldItalic.ttf", + "data/fonts/caudex/Caudex-Italic.ttf", + "data/fonts/caudex/Caudex-Bold.ttf", + "data/fonts/cabin/Cabin-MediumItalic.ttf", + "data/fonts/cabin/Cabin-SemiBold.ttf", + "data/fonts/cabin/Cabin-SemiBoldItalic.ttf", + "data/fonts/cabin/Cabin-BoldItalic.ttf", + "data/fonts/cabin/Cabin-Medium.ttf", + "data/fonts/cabin/Cabin-Italic.ttf", + "data/fonts/cabin/Cabin-Bold.ttf", + "data/fonts/cabin/Cabin-Regular.ttf", + "data/fonts/dawningofanewday/DawningofaNewDay.ttf", + "data/fonts/dangrek/Dangrek.ttf", + "data/fonts/blackopsone/BlackOpsOne.ttf", + "data/fonts/francoisone/FrancoisOne.ttf", + "data/fonts/bowlbyone/BowlbyOne.ttf", + "data/fonts/bowlbyone/BowlbyOneSC.ttf", + "data/fonts/calligraffiti/Calligraffiti.ttf", + "data/fonts/bangers/Bangers.ttf", + "data/fonts/astloch/Astloch-Regular.ttf", + "data/fonts/astloch/Astloch-Bold.ttf", + "data/fonts/angkor/Angkor.ttf", + "data/fonts/abrilfatface/AbrilFatface-Regular.ttf", + "data/fonts/cantarell/Cantarell-BoldOblique.ttf", + "data/fonts/cantarell/Cantarell-Oblique.ttf", + "data/fonts/cantarell/Cantarell-Bold.ttf", + "data/fonts/cantarell/Cantarell-Regular.ttf", + "data/fonts/arvo/Arvo-Bold.ttf", + "data/fonts/arvo/Arvo-Italic.ttf", + "data/fonts/arvo/Arvo-BoldItalic.ttf", + "data/fonts/arvo/Arvo-Regular.ttf", + "data/fonts/chewy/Chewy.ttf", + "data/fonts/bigshotone/BigshotOne.ttf", + "data/fonts/chenla/Chenla.ttf", + "data/fonts/bayon/Bayon.ttf", + "data/fonts/coustard/Coustard-Black.ttf", + "data/fonts/coustard/Coustard-Regular.ttf", + "data/fonts/amaticsc/AmaticSC-Bold.ttf", + "data/fonts/amaticsc/AmaticSC-Regular.ttf", + "data/fonts/comfortaa/Comfortaa-Light.ttf", + "data/fonts/comfortaa/Comfortaa-Bold.ttf", + "data/fonts/comfortaa/Comfortaa-Regular.ttf", + "data/fonts/expletussans/ExpletusSans-Bold.ttf", + "data/fonts/expletussans/ExpletusSans-MediumItalic.ttf", + "data/fonts/expletussans/ExpletusSans-Medium.ttf", + "data/fonts/expletussans/ExpletusSans-SemiBold.ttf", + "data/fonts/expletussans/ExpletusSans-Regular.ttf", + "data/fonts/expletussans/ExpletusSans-Italic.ttf", + "data/fonts/expletussans/ExpletusSans-SemiBoldItalic.ttf", + "data/fonts/expletussans/ExpletusSans-BoldItalic.ttf", + "data/fonts/aubrey/Aubrey-Regular.ttf", + "data/fonts/antic/Antic-Regular.ttf", + "data/fonts/copse/Copse-Regular.ttf", + "data/fonts/daysone/DaysOne-Regular.ttf", + "data/fonts/actor/Actor-Regular.ttf", + "data/fonts/bentham/Bentham-Regular.ttf", + "data/fonts/federo/Federo-Regular.ttf", + "data/fonts/arimo/Arimo-Italic.ttf", + "data/fonts/arimo/Arimo-BoldItalic.ttf", + "data/fonts/arimo/Arimo-Bold.ttf", + "data/fonts/arimo/Arimo-Regular.ttf", + "data/fonts/felltypes/IMFeDPsc28P.ttf", + "data/fonts/felltypes/IMFeGPrm28P.ttf", + "data/fonts/felltypes/IMFeENsc28P.ttf", + "data/fonts/felltypes/IMFePIit28P.ttf", + "data/fonts/felltypes/IMFeDPrm28P.ttf", + "data/fonts/felltypes/IMFePIrm28P.ttf", + "data/fonts/felltypes/IMFeFCrm28P.ttf", + "data/fonts/felltypes/IMFeGPit28P.ttf", + "data/fonts/felltypes/IMFeENit28P.ttf", + "data/fonts/felltypes/IMFeDPit28P.ttf", + "data/fonts/felltypes/IMFeENrm28P.ttf", + "data/fonts/felltypes/IMFeGPsc28P.ttf", + "data/fonts/felltypes/IMFePIsc28P.ttf", + "data/fonts/felltypes/IMFeFCsc28P.ttf", + "data/fonts/felltypes/IMFeFCit28P.ttf", + "data/fonts/bokor/Bokor.ttf", + "data/fonts/didactgothic/DidactGothic.ttf", + "data/fonts/allerta/Allerta-Medium.ttf", + "data/fonts/allerta/Allerta-Stencil.ttf", + "data/fonts/buda/Buda-Light.ttf", + "data/fonts/brawler/Brawler-Regular.ttf", + "data/fonts/carterone/CarterOne.ttf", + "data/fonts/candal/Candal.ttf", + "data/fonts/dorsa/Dorsa-Regular.ttf", + "data/fonts/crimson/CrimsonText-BoldItalic.ttf", + "data/fonts/crimson/CrimsonText-Bold.ttf", + "data/fonts/crimson/CrimsonText-Italic.ttf", + "data/fonts/crimson/CrimsonText-Roman.ttf", + "data/fonts/crimson/CrimsonText-Semibold.ttf", + "data/fonts/crimson/CrimsonText-SemiboldItalic.ttf", + "data/fonts/amaranth/Amaranth-Italic.ttf", + "data/fonts/amaranth/Amaranth-Bold.ttf", + "data/fonts/amaranth/Amaranth-Regular.ttf", + "data/fonts/amaranth/Amaranth-BoldItalic.ttf", + "data/fonts/crushed/Crushed.ttf", + "data/fonts/adamina/Adamina-Regular.ttf", + "data/fonts/aldrich/Aldrich-Regular.ttf", + "data/fonts/fanwoodtext/FanwoodText-Italic.ttf", + "data/fonts/fanwoodtext/FanwoodText-Regular.ttf", + "data/fonts/anonymouspro/AnonymousPro-Regular.ttf", + "data/fonts/anonymouspro/AnonymousPro-Bold.ttf", + "data/fonts/anonymouspro/AnonymousPro-Italic.ttf", + "data/fonts/anonymouspro/AnonymousPro-BoldItalic.ttf", + "data/fonts/bevan/Bevan.ttf", + "data/fonts/artifika/Artifika-Regular.ttf", + "data/fonts/anton/Anton.ttf", + "data/fonts/battambang/Battambang-Regular.ttf", + "data/fonts/battambang/Battambang-Bold.ttf", + "data/fonts/carme/Carme-Regular.ttf", + "data/fonts/cherrycreamsoda/CherryCreamSoda.ttf", + "data/fonts/deliusunicase/DeliusUnicase-Regular.ttf", + "data/fonts/comingsoon/ComingSoon.ttf", + "data/fonts/freehand/Freehand.ttf", + "data/fonts/alice/Alice-Regular.ttf", + "data/fonts/contrail/Contrail-Regular.ttf", + "data/fonts/cardo/Cardo-Bold.ttf", + "data/fonts/cardo/Cardo-Italic.ttf", + "data/fonts/cardo/Cardo-Regular.ttf", + "data/fonts/asset/Asset.ttf", + "data/fonts/changaone/ChangaOne-Regular.ttf", + "data/fonts/aclonica/Aclonica.ttf", + "data/fonts/craftygirls/CraftyGirls.ttf", + "data/fonts/architectsdaughter/ArchitectsDaughter.ttf", + "data/fonts/content/Content-Bold.ttf", + "data/fonts/content/Content-Regular.ttf", + "data/fonts/abel/Abel-Regular.ttf", + "data/fonts/cuprum/Cuprum.ttf", + "data/fonts/andika/Andika-R.ttf" +}; +} // namespace cmap_test_data +} // namespace sfntly - struct TestCMap - { - const char *name; - int32_t num_cmaps; - ProtoCMap cmaps[2]; - }; - - extern TestCMap kTestCousine_BoldItalic_ttf_xml; - extern TestCMap kTestCousine_Bold_ttf_xml; - extern TestCMap kTestCousine_Regular_ttf_xml; - extern TestCMap kTestCousine_Italic_ttf_xml; - extern TestCMap kTestCedarville_Cursive_ttf_xml; - extern TestCMap kTestDancingScript_Bold_ttf_xml; - extern TestCMap kTestDancingScript_Regular_ttf_xml; - extern TestCMap kTestDamion_Regular_ttf_xml; - extern TestCMap kTestAnnieUseYourTelescope_ttf_xml; - extern TestCMap kTestDeliusSwashCaps_Regular_ttf_xml; - extern TestCMap kTestDelius_Regular_ttf_xml; - extern TestCMap kTestCoveredByYourGrace_ttf_xml; - extern TestCMap kTestEBGaramond_Regular_ttf_xml; - extern TestCMap kTestCabinSketch_Bold_ttf_xml; - extern TestCMap kTestAllan_Bold_ttf_xml; - extern TestCMap kTestCoda_Caption_Heavy_ttf_xml; - extern TestCMap kTestCoda_Heavy_ttf_xml; - extern TestCMap kTestForum_Regular_ttf_xml; - extern TestCMap kTestAlike_Regular_ttf_xml; - extern TestCMap kTestCorben_Bold_ttf_xml; - extern TestCMap kTestCaudex_Regular_ttf_xml; - extern TestCMap kTestCaudex_BoldItalic_ttf_xml; - extern TestCMap kTestCaudex_Italic_ttf_xml; - extern TestCMap kTestCaudex_Bold_ttf_xml; - extern TestCMap kTestCabin_MediumItalic_ttf_xml; - extern TestCMap kTestCabin_SemiBold_ttf_xml; - extern TestCMap kTestCabin_SemiBoldItalic_ttf_xml; - extern TestCMap kTestCabin_BoldItalic_ttf_xml; - extern TestCMap kTestCabin_Medium_ttf_xml; - extern TestCMap kTestCabin_Italic_ttf_xml; - extern TestCMap kTestCabin_Bold_ttf_xml; - extern TestCMap kTestCabin_Regular_ttf_xml; - extern TestCMap kTestDawningofaNewDay_ttf_xml; - extern TestCMap kTestDangrek_ttf_xml; - extern TestCMap kTestBlackOpsOne_ttf_xml; - extern TestCMap kTestFrancoisOne_ttf_xml; - extern TestCMap kTestBowlbyOne_ttf_xml; - extern TestCMap kTestBowlbyOneSC_ttf_xml; - extern TestCMap kTestCalligraffiti_ttf_xml; - extern TestCMap kTestBangers_ttf_xml; - extern TestCMap kTestAstloch_Regular_ttf_xml; - extern TestCMap kTestAstloch_Bold_ttf_xml; - extern TestCMap kTestAngkor_ttf_xml; - extern TestCMap kTestAbrilFatface_Regular_ttf_xml; - extern TestCMap kTestCantarell_BoldOblique_ttf_xml; - extern TestCMap kTestCantarell_Oblique_ttf_xml; - extern TestCMap kTestCantarell_Bold_ttf_xml; - extern TestCMap kTestCantarell_Regular_ttf_xml; - extern TestCMap kTestArvo_Bold_ttf_xml; - extern TestCMap kTestArvo_Italic_ttf_xml; - extern TestCMap kTestArvo_BoldItalic_ttf_xml; - extern TestCMap kTestArvo_Regular_ttf_xml; - extern TestCMap kTestChewy_ttf_xml; - extern TestCMap kTestBigshotOne_ttf_xml; - extern TestCMap kTestChenla_ttf_xml; - extern TestCMap kTestBayon_ttf_xml; - extern TestCMap kTestCoustard_Black_ttf_xml; - extern TestCMap kTestCoustard_Regular_ttf_xml; - extern TestCMap kTestAmaticSC_Bold_ttf_xml; - extern TestCMap kTestAmaticSC_Regular_ttf_xml; - extern TestCMap kTestComfortaa_Light_ttf_xml; - extern TestCMap kTestComfortaa_Bold_ttf_xml; - extern TestCMap kTestComfortaa_Regular_ttf_xml; - extern TestCMap kTestExpletusSans_Bold_ttf_xml; - extern TestCMap kTestExpletusSans_MediumItalic_ttf_xml; - extern TestCMap kTestExpletusSans_Medium_ttf_xml; - extern TestCMap kTestExpletusSans_SemiBold_ttf_xml; - extern TestCMap kTestExpletusSans_Regular_ttf_xml; - extern TestCMap kTestExpletusSans_Italic_ttf_xml; - extern TestCMap kTestExpletusSans_SemiBoldItalic_ttf_xml; - extern TestCMap kTestExpletusSans_BoldItalic_ttf_xml; - extern TestCMap kTestAubrey_Regular_ttf_xml; - extern TestCMap kTestAntic_Regular_ttf_xml; - extern TestCMap kTestCopse_Regular_ttf_xml; - extern TestCMap kTestDaysOne_Regular_ttf_xml; - extern TestCMap kTestActor_Regular_ttf_xml; - extern TestCMap kTestBentham_Regular_ttf_xml; - extern TestCMap kTestFedero_Regular_ttf_xml; - extern TestCMap kTestArimo_Italic_ttf_xml; - extern TestCMap kTestArimo_BoldItalic_ttf_xml; - extern TestCMap kTestArimo_Bold_ttf_xml; - extern TestCMap kTestArimo_Regular_ttf_xml; - extern TestCMap kTestIMFeDPsc28P_ttf_xml; - extern TestCMap kTestIMFeGPrm28P_ttf_xml; - extern TestCMap kTestIMFeENsc28P_ttf_xml; - extern TestCMap kTestIMFePIit28P_ttf_xml; - extern TestCMap kTestIMFeDPrm28P_ttf_xml; - extern TestCMap kTestIMFePIrm28P_ttf_xml; - extern TestCMap kTestIMFeFCrm28P_ttf_xml; - extern TestCMap kTestIMFeGPit28P_ttf_xml; - extern TestCMap kTestIMFeENit28P_ttf_xml; - extern TestCMap kTestIMFeDPit28P_ttf_xml; - extern TestCMap kTestIMFeENrm28P_ttf_xml; - extern TestCMap kTestIMFeGPsc28P_ttf_xml; - extern TestCMap kTestIMFePIsc28P_ttf_xml; - extern TestCMap kTestIMFeFCsc28P_ttf_xml; - extern TestCMap kTestIMFeFCit28P_ttf_xml; - extern TestCMap kTestBokor_ttf_xml; - extern TestCMap kTestDidactGothic_ttf_xml; - extern TestCMap kTestAllerta_Medium_ttf_xml; - extern TestCMap kTestAllerta_Stencil_ttf_xml; - extern TestCMap kTestBuda_Light_ttf_xml; - extern TestCMap kTestBrawler_Regular_ttf_xml; - extern TestCMap kTestCarterOne_ttf_xml; - extern TestCMap kTestCandal_ttf_xml; - extern TestCMap kTestDorsa_Regular_ttf_xml; - extern TestCMap kTestCrimsonText_BoldItalic_ttf_xml; - extern TestCMap kTestCrimsonText_Bold_ttf_xml; - extern TestCMap kTestCrimsonText_Italic_ttf_xml; - extern TestCMap kTestCrimsonText_Roman_ttf_xml; - extern TestCMap kTestCrimsonText_Semibold_ttf_xml; - extern TestCMap kTestCrimsonText_SemiboldItalic_ttf_xml; - extern TestCMap kTestAmaranth_Italic_ttf_xml; - extern TestCMap kTestAmaranth_Bold_ttf_xml; - extern TestCMap kTestAmaranth_Regular_ttf_xml; - extern TestCMap kTestAmaranth_BoldItalic_ttf_xml; - extern TestCMap kTestCrushed_ttf_xml; - extern TestCMap kTestAdamina_Regular_ttf_xml; - extern TestCMap kTestAldrich_Regular_ttf_xml; - extern TestCMap kTestFanwoodText_Italic_ttf_xml; - extern TestCMap kTestFanwoodText_Regular_ttf_xml; - extern TestCMap kTestAnonymousPro_Regular_ttf_xml; - extern TestCMap kTestAnonymousPro_Bold_ttf_xml; - extern TestCMap kTestAnonymousPro_Italic_ttf_xml; - extern TestCMap kTestAnonymousPro_BoldItalic_ttf_xml; - extern TestCMap kTestBevan_ttf_xml; - extern TestCMap kTestArtifika_Regular_ttf_xml; - extern TestCMap kTestAnton_ttf_xml; - extern TestCMap kTestBattambang_Regular_ttf_xml; - extern TestCMap kTestBattambang_Bold_ttf_xml; - extern TestCMap kTestCarme_Regular_ttf_xml; - extern TestCMap kTestCherryCreamSoda_ttf_xml; - extern TestCMap kTestDeliusUnicase_Regular_ttf_xml; - extern TestCMap kTestComingSoon_ttf_xml; - extern TestCMap kTestFreehand_ttf_xml; - extern TestCMap kTestAlice_Regular_ttf_xml; - extern TestCMap kTestContrail_Regular_ttf_xml; - extern TestCMap kTestCardo_Bold_ttf_xml; - extern TestCMap kTestCardo_Italic_ttf_xml; - extern TestCMap kTestCardo_Regular_ttf_xml; - extern TestCMap kTestAsset_ttf_xml; - extern TestCMap kTestChangaOne_Regular_ttf_xml; - extern TestCMap kTestAclonica_ttf_xml; - extern TestCMap kTestCraftyGirls_ttf_xml; - extern TestCMap kTestArchitectsDaughter_ttf_xml; - extern TestCMap kTestContent_Bold_ttf_xml; - extern TestCMap kTestContent_Regular_ttf_xml; - extern TestCMap kTestAbel_Regular_ttf_xml; - extern TestCMap kTestCuprum_ttf_xml; - extern TestCMap kTestAndika_R_ttf_xml; - - const TestCMap kAllTestCMaps[] = { - kTestCousine_BoldItalic_ttf_xml, - kTestCousine_Bold_ttf_xml, - kTestCousine_Regular_ttf_xml, - kTestCousine_Italic_ttf_xml, - kTestCedarville_Cursive_ttf_xml, - kTestDancingScript_Bold_ttf_xml, - kTestDancingScript_Regular_ttf_xml, - kTestDamion_Regular_ttf_xml, - kTestAnnieUseYourTelescope_ttf_xml, - kTestDeliusSwashCaps_Regular_ttf_xml, - kTestDelius_Regular_ttf_xml, - kTestCoveredByYourGrace_ttf_xml, - kTestEBGaramond_Regular_ttf_xml, - kTestCabinSketch_Bold_ttf_xml, - kTestAllan_Bold_ttf_xml, - kTestCoda_Caption_Heavy_ttf_xml, - kTestCoda_Heavy_ttf_xml, - kTestForum_Regular_ttf_xml, - kTestAlike_Regular_ttf_xml, - kTestCorben_Bold_ttf_xml, - kTestCaudex_Regular_ttf_xml, - kTestCaudex_BoldItalic_ttf_xml, - kTestCaudex_Italic_ttf_xml, - kTestCaudex_Bold_ttf_xml, - kTestCabin_MediumItalic_ttf_xml, - kTestCabin_SemiBold_ttf_xml, - kTestCabin_SemiBoldItalic_ttf_xml, - kTestCabin_BoldItalic_ttf_xml, - kTestCabin_Medium_ttf_xml, - kTestCabin_Italic_ttf_xml, - kTestCabin_Bold_ttf_xml, - kTestCabin_Regular_ttf_xml, - kTestDawningofaNewDay_ttf_xml, - kTestDangrek_ttf_xml, - kTestBlackOpsOne_ttf_xml, - kTestFrancoisOne_ttf_xml, - kTestBowlbyOne_ttf_xml, - kTestBowlbyOneSC_ttf_xml, - kTestCalligraffiti_ttf_xml, - kTestBangers_ttf_xml, - kTestAstloch_Regular_ttf_xml, - kTestAstloch_Bold_ttf_xml, - kTestAngkor_ttf_xml, - kTestAbrilFatface_Regular_ttf_xml, - kTestCantarell_BoldOblique_ttf_xml, - kTestCantarell_Oblique_ttf_xml, - kTestCantarell_Bold_ttf_xml, - kTestCantarell_Regular_ttf_xml, - kTestArvo_Bold_ttf_xml, - kTestArvo_Italic_ttf_xml, - kTestArvo_BoldItalic_ttf_xml, - kTestArvo_Regular_ttf_xml, - kTestChewy_ttf_xml, - kTestBigshotOne_ttf_xml, - kTestChenla_ttf_xml, - kTestBayon_ttf_xml, - kTestCoustard_Black_ttf_xml, - kTestCoustard_Regular_ttf_xml, - kTestAmaticSC_Bold_ttf_xml, - kTestAmaticSC_Regular_ttf_xml, - kTestComfortaa_Light_ttf_xml, - kTestComfortaa_Bold_ttf_xml, - kTestComfortaa_Regular_ttf_xml, - kTestExpletusSans_Bold_ttf_xml, - kTestExpletusSans_MediumItalic_ttf_xml, - kTestExpletusSans_Medium_ttf_xml, - kTestExpletusSans_SemiBold_ttf_xml, - kTestExpletusSans_Regular_ttf_xml, - kTestExpletusSans_Italic_ttf_xml, - kTestExpletusSans_SemiBoldItalic_ttf_xml, - kTestExpletusSans_BoldItalic_ttf_xml, - kTestAubrey_Regular_ttf_xml, - kTestAntic_Regular_ttf_xml, - kTestCopse_Regular_ttf_xml, - kTestDaysOne_Regular_ttf_xml, - kTestActor_Regular_ttf_xml, - kTestBentham_Regular_ttf_xml, - kTestFedero_Regular_ttf_xml, - kTestArimo_Italic_ttf_xml, - kTestArimo_BoldItalic_ttf_xml, - kTestArimo_Bold_ttf_xml, - kTestArimo_Regular_ttf_xml, - kTestIMFeDPsc28P_ttf_xml, - kTestIMFeGPrm28P_ttf_xml, - kTestIMFeENsc28P_ttf_xml, - kTestIMFePIit28P_ttf_xml, - kTestIMFeDPrm28P_ttf_xml, - kTestIMFePIrm28P_ttf_xml, - kTestIMFeFCrm28P_ttf_xml, - kTestIMFeGPit28P_ttf_xml, - kTestIMFeENit28P_ttf_xml, - kTestIMFeDPit28P_ttf_xml, - kTestIMFeENrm28P_ttf_xml, - kTestIMFeGPsc28P_ttf_xml, - kTestIMFePIsc28P_ttf_xml, - kTestIMFeFCsc28P_ttf_xml, - kTestIMFeFCit28P_ttf_xml, - kTestBokor_ttf_xml, - kTestDidactGothic_ttf_xml, - kTestAllerta_Medium_ttf_xml, - kTestAllerta_Stencil_ttf_xml, - kTestBuda_Light_ttf_xml, - kTestBrawler_Regular_ttf_xml, - kTestCarterOne_ttf_xml, - kTestCandal_ttf_xml, - kTestDorsa_Regular_ttf_xml, - kTestCrimsonText_BoldItalic_ttf_xml, - kTestCrimsonText_Bold_ttf_xml, - kTestCrimsonText_Italic_ttf_xml, - kTestCrimsonText_Roman_ttf_xml, - kTestCrimsonText_Semibold_ttf_xml, - kTestCrimsonText_SemiboldItalic_ttf_xml, - kTestAmaranth_Italic_ttf_xml, - kTestAmaranth_Bold_ttf_xml, - kTestAmaranth_Regular_ttf_xml, - kTestAmaranth_BoldItalic_ttf_xml, - kTestCrushed_ttf_xml, - kTestAdamina_Regular_ttf_xml, - kTestAldrich_Regular_ttf_xml, - kTestFanwoodText_Italic_ttf_xml, - kTestFanwoodText_Regular_ttf_xml, - kTestAnonymousPro_Regular_ttf_xml, - kTestAnonymousPro_Bold_ttf_xml, - kTestAnonymousPro_Italic_ttf_xml, - kTestAnonymousPro_BoldItalic_ttf_xml, - kTestBevan_ttf_xml, - kTestArtifika_Regular_ttf_xml, - kTestAnton_ttf_xml, - kTestBattambang_Regular_ttf_xml, - kTestBattambang_Bold_ttf_xml, - kTestCarme_Regular_ttf_xml, - kTestCherryCreamSoda_ttf_xml, - kTestDeliusUnicase_Regular_ttf_xml, - kTestComingSoon_ttf_xml, - kTestFreehand_ttf_xml, - kTestAlice_Regular_ttf_xml, - kTestContrail_Regular_ttf_xml, - kTestCardo_Bold_ttf_xml, - kTestCardo_Italic_ttf_xml, - kTestCardo_Regular_ttf_xml, - kTestAsset_ttf_xml, - kTestChangaOne_Regular_ttf_xml, - kTestAclonica_ttf_xml, - kTestCraftyGirls_ttf_xml, - kTestArchitectsDaughter_ttf_xml, - kTestContent_Bold_ttf_xml, - kTestContent_Regular_ttf_xml, - kTestAbel_Regular_ttf_xml, - kTestCuprum_ttf_xml, - kTestAndika_R_ttf_xml - }; -} // namespace sfntly - -#endif //SFNTLY_CPP_SRC_TEST_CMAP_TEST_DATA_H_ +#endif // TYPOGRAPHY_FONT_SFNTLY_SRC_TEST_AUTOGENERATED_CMAP_TEST_DATA_H_ diff --git a/test/test_xml_utils.cc b/test/test_xml_utils.cc new file mode 100644 index 0000000..dc65add --- /dev/null +++ b/test/test_xml_utils.cc @@ -0,0 +1,50 @@ +/* + * 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 "test/test_xml_utils.h" +#include "test/tinyxml/tinyxml.h" + +namespace sfntly { +void InternalGetNodesWithName(const TiXmlNode* node, const std::string& name, + TiXmlNodeVector* wanted_nodes) { + if (node->ValueStr() == name) + wanted_nodes->push_back(node); + for (const TiXmlNode* child = node->FirstChild(); + child != NULL; child = child->NextSibling()) { + InternalGetNodesWithName(child, name, wanted_nodes); + } +} + +TiXmlNodeVector* GetNodesWithName(const TiXmlNode* node, + const std::string& name) { + TiXmlNodeVector* wanted_nodes = new TiXmlNodeVector; + InternalGetNodesWithName(node, name, wanted_nodes); + return wanted_nodes; +} + +const TiXmlAttribute* GetAttribute(const TiXmlNode* node, + const std::string& name) { + for (const TiXmlAttribute* attribute = node->ToElement()->FirstAttribute(); + attribute != NULL; attribute = attribute->Next()) { + if (attribute->Name() == name) { + return attribute; + } + } + return NULL; +} +} diff --git a/test/test_xml_utils.h b/test/test_xml_utils.h new file mode 100644 index 0000000..7a5fe49 --- /dev/null +++ b/test/test_xml_utils.h @@ -0,0 +1,33 @@ +/* + * 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/refcount.h" +#include "test/tinyxml/tinyxml.h" + +#ifndef SFNTLY_CPP_SRC_TEST_TEST_XML_UTILS_H_ +#define SFNTLY_CPP_SRC_TEST_TEST_XML_UTILS_H_ + +namespace sfntly { +typedef std::map AttributeMap; +typedef std::vector TiXmlNodeVector; + +TiXmlNodeVector* GetNodesWithName(const TiXmlNode* node, + const std::string& name); +const TiXmlAttribute* GetAttribute(const TiXmlNode* node, + const std::string& name); +} // namespace sfntly + +#endif // SFNTLY_CPP_SRC_TEST_TEST_XML_UTILS_H_ diff --git a/test/tinyxml/tinystr.cpp b/test/tinyxml/tinystr.cpp new file mode 100644 index 0000000..0665768 --- /dev/null +++ b/test/tinyxml/tinystr.cpp @@ -0,0 +1,111 @@ +/* +www.sourceforge.net/projects/tinyxml + +This software is provided 'as-is', without any express or implied +warranty. In no event will the authors be held liable for any +damages arising from the use of this software. + +Permission is granted to anyone to use this software for any +purpose, including commercial applications, and to alter it and +redistribute it freely, subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must +not claim that you wrote the original software. If you use this +software in a product, an acknowledgment in the product documentation +would be appreciated but is not required. + +2. Altered source versions must be plainly marked as such, and +must not be misrepresented as being the original software. + +3. This notice may not be removed or altered from any source +distribution. +*/ + + +#ifndef TIXML_USE_STL + +#include "tinystr.h" + +// Error value for find primitive +const TiXmlString::size_type TiXmlString::npos = static_cast< TiXmlString::size_type >(-1); + + +// Null rep. +TiXmlString::Rep TiXmlString::nullrep_ = { 0, 0, { '\0' } }; + + +void TiXmlString::reserve (size_type cap) +{ + if (cap > capacity()) + { + TiXmlString tmp; + tmp.init(length(), cap); + memcpy(tmp.start(), data(), length()); + swap(tmp); + } +} + + +TiXmlString& TiXmlString::assign(const char* str, size_type len) +{ + size_type cap = capacity(); + if (len > cap || cap > 3*(len + 8)) + { + TiXmlString tmp; + tmp.init(len); + memcpy(tmp.start(), str, len); + swap(tmp); + } + else + { + memmove(start(), str, len); + set_size(len); + } + return *this; +} + + +TiXmlString& TiXmlString::append(const char* str, size_type len) +{ + size_type newsize = length() + len; + if (newsize > capacity()) + { + reserve (newsize + capacity()); + } + memmove(finish(), str, len); + set_size(newsize); + return *this; +} + + +TiXmlString operator + (const TiXmlString & a, const TiXmlString & b) +{ + TiXmlString tmp; + tmp.reserve(a.length() + b.length()); + tmp += a; + tmp += b; + return tmp; +} + +TiXmlString operator + (const TiXmlString & a, const char* b) +{ + TiXmlString tmp; + TiXmlString::size_type b_len = static_cast( strlen(b) ); + tmp.reserve(a.length() + b_len); + tmp += a; + tmp.append(b, b_len); + return tmp; +} + +TiXmlString operator + (const char* a, const TiXmlString & b) +{ + TiXmlString tmp; + TiXmlString::size_type a_len = static_cast( strlen(a) ); + tmp.reserve(a_len + b.length()); + tmp.append(a, a_len); + tmp += b; + return tmp; +} + + +#endif // TIXML_USE_STL diff --git a/test/tinyxml/tinystr.h b/test/tinyxml/tinystr.h new file mode 100644 index 0000000..89cca33 --- /dev/null +++ b/test/tinyxml/tinystr.h @@ -0,0 +1,305 @@ +/* +www.sourceforge.net/projects/tinyxml + +This software is provided 'as-is', without any express or implied +warranty. In no event will the authors be held liable for any +damages arising from the use of this software. + +Permission is granted to anyone to use this software for any +purpose, including commercial applications, and to alter it and +redistribute it freely, subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must +not claim that you wrote the original software. If you use this +software in a product, an acknowledgment in the product documentation +would be appreciated but is not required. + +2. Altered source versions must be plainly marked as such, and +must not be misrepresented as being the original software. + +3. This notice may not be removed or altered from any source +distribution. +*/ + + +#ifndef TIXML_USE_STL + +#ifndef TIXML_STRING_INCLUDED +#define TIXML_STRING_INCLUDED + +#include +#include + +/* The support for explicit isn't that universal, and it isn't really + required - it is used to check that the TiXmlString class isn't incorrectly + used. Be nice to old compilers and macro it here: +*/ +#if defined(_MSC_VER) && (_MSC_VER >= 1200 ) + // Microsoft visual studio, version 6 and higher. + #define TIXML_EXPLICIT explicit +#elif defined(__GNUC__) && (__GNUC__ >= 3 ) + // GCC version 3 and higher.s + #define TIXML_EXPLICIT explicit +#else + #define TIXML_EXPLICIT +#endif + + +/* + TiXmlString is an emulation of a subset of the std::string template. + Its purpose is to allow compiling TinyXML on compilers with no or poor STL support. + Only the member functions relevant to the TinyXML project have been implemented. + The buffer allocation is made by a simplistic power of 2 like mechanism : if we increase + a string and there's no more room, we allocate a buffer twice as big as we need. +*/ +class TiXmlString +{ + public : + // The size type used + typedef size_t size_type; + + // Error value for find primitive + static const size_type npos; // = -1; + + + // TiXmlString empty constructor + TiXmlString () : rep_(&nullrep_) + { + } + + // TiXmlString copy constructor + TiXmlString ( const TiXmlString & copy) : rep_(0) + { + init(copy.length()); + memcpy(start(), copy.data(), length()); + } + + // TiXmlString constructor, based on a string + TIXML_EXPLICIT TiXmlString ( const char * copy) : rep_(0) + { + init( static_cast( strlen(copy) )); + memcpy(start(), copy, length()); + } + + // TiXmlString constructor, based on a string + TIXML_EXPLICIT TiXmlString ( const char * str, size_type len) : rep_(0) + { + init(len); + memcpy(start(), str, len); + } + + // TiXmlString destructor + ~TiXmlString () + { + quit(); + } + + TiXmlString& operator = (const char * copy) + { + return assign( copy, (size_type)strlen(copy)); + } + + TiXmlString& operator = (const TiXmlString & copy) + { + return assign(copy.start(), copy.length()); + } + + + // += operator. Maps to append + TiXmlString& operator += (const char * suffix) + { + return append(suffix, static_cast( strlen(suffix) )); + } + + // += operator. Maps to append + TiXmlString& operator += (char single) + { + return append(&single, 1); + } + + // += operator. Maps to append + TiXmlString& operator += (const TiXmlString & suffix) + { + return append(suffix.data(), suffix.length()); + } + + + // Convert a TiXmlString into a null-terminated char * + const char * c_str () const { return rep_->str; } + + // Convert a TiXmlString into a char * (need not be null terminated). + const char * data () const { return rep_->str; } + + // Return the length of a TiXmlString + size_type length () const { return rep_->size; } + + // Alias for length() + size_type size () const { return rep_->size; } + + // Checks if a TiXmlString is empty + bool empty () const { return rep_->size == 0; } + + // Return capacity of string + size_type capacity () const { return rep_->capacity; } + + + // single char extraction + const char& at (size_type index) const + { + assert( index < length() ); + return rep_->str[ index ]; + } + + // [] operator + char& operator [] (size_type index) const + { + assert( index < length() ); + return rep_->str[ index ]; + } + + // find a char in a string. Return TiXmlString::npos if not found + size_type find (char lookup) const + { + return find(lookup, 0); + } + + // find a char in a string from an offset. Return TiXmlString::npos if not found + size_type find (char tofind, size_type offset) const + { + if (offset >= length()) return npos; + + for (const char* p = c_str() + offset; *p != '\0'; ++p) + { + if (*p == tofind) return static_cast< size_type >( p - c_str() ); + } + return npos; + } + + void clear () + { + //Lee: + //The original was just too strange, though correct: + // TiXmlString().swap(*this); + //Instead use the quit & re-init: + quit(); + init(0,0); + } + + /* Function to reserve a big amount of data when we know we'll need it. Be aware that this + function DOES NOT clear the content of the TiXmlString if any exists. + */ + void reserve (size_type cap); + + TiXmlString& assign (const char* str, size_type len); + + TiXmlString& append (const char* str, size_type len); + + void swap (TiXmlString& other) + { + Rep* r = rep_; + rep_ = other.rep_; + other.rep_ = r; + } + + private: + + void init(size_type sz) { init(sz, sz); } + void set_size(size_type sz) { rep_->str[ rep_->size = sz ] = '\0'; } + char* start() const { return rep_->str; } + char* finish() const { return rep_->str + rep_->size; } + + struct Rep + { + size_type size, capacity; + char str[1]; + }; + + void init(size_type sz, size_type cap) + { + if (cap) + { + // Lee: the original form: + // rep_ = static_cast(operator new(sizeof(Rep) + cap)); + // doesn't work in some cases of new being overloaded. Switching + // to the normal allocation, although use an 'int' for systems + // that are overly picky about structure alignment. + const size_type bytesNeeded = sizeof(Rep) + cap; + const size_type intsNeeded = ( bytesNeeded + sizeof(int) - 1 ) / sizeof( int ); + rep_ = reinterpret_cast( new int[ intsNeeded ] ); + + rep_->str[ rep_->size = sz ] = '\0'; + rep_->capacity = cap; + } + else + { + rep_ = &nullrep_; + } + } + + void quit() + { + if (rep_ != &nullrep_) + { + // The rep_ is really an array of ints. (see the allocator, above). + // Cast it back before delete, so the compiler won't incorrectly call destructors. + delete [] ( reinterpret_cast( rep_ ) ); + } + } + + Rep * rep_; + static Rep nullrep_; + +} ; + + +inline bool operator == (const TiXmlString & a, const TiXmlString & b) +{ + return ( a.length() == b.length() ) // optimization on some platforms + && ( strcmp(a.c_str(), b.c_str()) == 0 ); // actual compare +} +inline bool operator < (const TiXmlString & a, const TiXmlString & b) +{ + return strcmp(a.c_str(), b.c_str()) < 0; +} + +inline bool operator != (const TiXmlString & a, const TiXmlString & b) { return !(a == b); } +inline bool operator > (const TiXmlString & a, const TiXmlString & b) { return b < a; } +inline bool operator <= (const TiXmlString & a, const TiXmlString & b) { return !(b < a); } +inline bool operator >= (const TiXmlString & a, const TiXmlString & b) { return !(a < b); } + +inline bool operator == (const TiXmlString & a, const char* b) { return strcmp(a.c_str(), b) == 0; } +inline bool operator == (const char* a, const TiXmlString & b) { return b == a; } +inline bool operator != (const TiXmlString & a, const char* b) { return !(a == b); } +inline bool operator != (const char* a, const TiXmlString & b) { return !(b == a); } + +TiXmlString operator + (const TiXmlString & a, const TiXmlString & b); +TiXmlString operator + (const TiXmlString & a, const char* b); +TiXmlString operator + (const char* a, const TiXmlString & b); + + +/* + TiXmlOutStream is an emulation of std::ostream. It is based on TiXmlString. + Only the operators that we need for TinyXML have been developped. +*/ +class TiXmlOutStream : public TiXmlString +{ +public : + + // TiXmlOutStream << operator. + TiXmlOutStream & operator << (const TiXmlString & in) + { + *this += in; + return *this; + } + + // TiXmlOutStream << operator. + TiXmlOutStream & operator << (const char * in) + { + *this += in; + return *this; + } + +} ; + +#endif // TIXML_STRING_INCLUDED +#endif // TIXML_USE_STL diff --git a/test/tinyxml/tinyxml.cpp b/test/tinyxml/tinyxml.cpp new file mode 100644 index 0000000..9c161df --- /dev/null +++ b/test/tinyxml/tinyxml.cpp @@ -0,0 +1,1886 @@ +/* +www.sourceforge.net/projects/tinyxml +Original code by Lee Thomason (www.grinninglizard.com) + +This software is provided 'as-is', without any express or implied +warranty. In no event will the authors be held liable for any +damages arising from the use of this software. + +Permission is granted to anyone to use this software for any +purpose, including commercial applications, and to alter it and +redistribute it freely, subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must +not claim that you wrote the original software. If you use this +software in a product, an acknowledgment in the product documentation +would be appreciated but is not required. + +2. Altered source versions must be plainly marked as such, and +must not be misrepresented as being the original software. + +3. This notice may not be removed or altered from any source +distribution. +*/ + +#include + +#ifdef TIXML_USE_STL +#include +#include +#endif + +#include "tinyxml.h" + +FILE* TiXmlFOpen( const char* filename, const char* mode ); + +bool TiXmlBase::condenseWhiteSpace = true; + +// Microsoft compiler security +FILE* TiXmlFOpen( const char* filename, const char* mode ) +{ + #if defined(_MSC_VER) && (_MSC_VER >= 1400 ) + FILE* fp = 0; + errno_t err = fopen_s( &fp, filename, mode ); + if ( !err && fp ) + return fp; + return 0; + #else + return fopen( filename, mode ); + #endif +} + +void TiXmlBase::EncodeString( const TIXML_STRING& str, TIXML_STRING* outString ) +{ + int i=0; + + while( i<(int)str.length() ) + { + unsigned char c = (unsigned char) str[i]; + + if ( c == '&' + && i < ( (int)str.length() - 2 ) + && str[i+1] == '#' + && str[i+2] == 'x' ) + { + // Hexadecimal character reference. + // Pass through unchanged. + // © -- copyright symbol, for example. + // + // The -1 is a bug fix from Rob Laveaux. It keeps + // an overflow from happening if there is no ';'. + // There are actually 2 ways to exit this loop - + // while fails (error case) and break (semicolon found). + // However, there is no mechanism (currently) for + // this function to return an error. + while ( i<(int)str.length()-1 ) + { + outString->append( str.c_str() + i, 1 ); + ++i; + if ( str[i] == ';' ) + break; + } + } + else if ( c == '&' ) + { + outString->append( entity[0].str, entity[0].strLength ); + ++i; + } + else if ( c == '<' ) + { + outString->append( entity[1].str, entity[1].strLength ); + ++i; + } + else if ( c == '>' ) + { + outString->append( entity[2].str, entity[2].strLength ); + ++i; + } + else if ( c == '\"' ) + { + outString->append( entity[3].str, entity[3].strLength ); + ++i; + } + else if ( c == '\'' ) + { + outString->append( entity[4].str, entity[4].strLength ); + ++i; + } + else if ( c < 32 ) + { + // Easy pass at non-alpha/numeric/symbol + // Below 32 is symbolic. + char buf[ 32 ]; + + #if defined(TIXML_SNPRINTF) + TIXML_SNPRINTF( buf, sizeof(buf), "&#x%02X;", (unsigned) ( c & 0xff ) ); + #else + sprintf( buf, "&#x%02X;", (unsigned) ( c & 0xff ) ); + #endif + + //*ME: warning C4267: convert 'size_t' to 'int' + //*ME: Int-Cast to make compiler happy ... + outString->append( buf, (int)strlen( buf ) ); + ++i; + } + else + { + //char realc = (char) c; + //outString->append( &realc, 1 ); + *outString += (char) c; // somewhat more efficient function call. + ++i; + } + } +} + + +TiXmlNode::TiXmlNode( NodeType _type ) : TiXmlBase() +{ + parent = 0; + type = _type; + firstChild = 0; + lastChild = 0; + prev = 0; + next = 0; +} + + +TiXmlNode::~TiXmlNode() +{ + TiXmlNode* node = firstChild; + TiXmlNode* temp = 0; + + while ( node ) + { + temp = node; + node = node->next; + delete temp; + } +} + + +void TiXmlNode::CopyTo( TiXmlNode* target ) const +{ + target->SetValue (value.c_str() ); + target->userData = userData; + target->location = location; +} + + +void TiXmlNode::Clear() +{ + TiXmlNode* node = firstChild; + TiXmlNode* temp = 0; + + while ( node ) + { + temp = node; + node = node->next; + delete temp; + } + + firstChild = 0; + lastChild = 0; +} + + +TiXmlNode* TiXmlNode::LinkEndChild( TiXmlNode* node ) +{ + assert( node->parent == 0 || node->parent == this ); + assert( node->GetDocument() == 0 || node->GetDocument() == this->GetDocument() ); + + if ( node->Type() == TiXmlNode::TINYXML_DOCUMENT ) + { + delete node; + if ( GetDocument() ) + GetDocument()->SetError( TIXML_ERROR_DOCUMENT_TOP_ONLY, 0, 0, TIXML_ENCODING_UNKNOWN ); + return 0; + } + + node->parent = this; + + node->prev = lastChild; + node->next = 0; + + if ( lastChild ) + lastChild->next = node; + else + firstChild = node; // it was an empty list. + + lastChild = node; + return node; +} + + +TiXmlNode* TiXmlNode::InsertEndChild( const TiXmlNode& addThis ) +{ + if ( addThis.Type() == TiXmlNode::TINYXML_DOCUMENT ) + { + if ( GetDocument() ) + GetDocument()->SetError( TIXML_ERROR_DOCUMENT_TOP_ONLY, 0, 0, TIXML_ENCODING_UNKNOWN ); + return 0; + } + TiXmlNode* node = addThis.Clone(); + if ( !node ) + return 0; + + return LinkEndChild( node ); +} + + +TiXmlNode* TiXmlNode::InsertBeforeChild( TiXmlNode* beforeThis, const TiXmlNode& addThis ) +{ + if ( !beforeThis || beforeThis->parent != this ) { + return 0; + } + if ( addThis.Type() == TiXmlNode::TINYXML_DOCUMENT ) + { + if ( GetDocument() ) + GetDocument()->SetError( TIXML_ERROR_DOCUMENT_TOP_ONLY, 0, 0, TIXML_ENCODING_UNKNOWN ); + return 0; + } + + TiXmlNode* node = addThis.Clone(); + if ( !node ) + return 0; + node->parent = this; + + node->next = beforeThis; + node->prev = beforeThis->prev; + if ( beforeThis->prev ) + { + beforeThis->prev->next = node; + } + else + { + assert( firstChild == beforeThis ); + firstChild = node; + } + beforeThis->prev = node; + return node; +} + + +TiXmlNode* TiXmlNode::InsertAfterChild( TiXmlNode* afterThis, const TiXmlNode& addThis ) +{ + if ( !afterThis || afterThis->parent != this ) { + return 0; + } + if ( addThis.Type() == TiXmlNode::TINYXML_DOCUMENT ) + { + if ( GetDocument() ) + GetDocument()->SetError( TIXML_ERROR_DOCUMENT_TOP_ONLY, 0, 0, TIXML_ENCODING_UNKNOWN ); + return 0; + } + + TiXmlNode* node = addThis.Clone(); + if ( !node ) + return 0; + node->parent = this; + + node->prev = afterThis; + node->next = afterThis->next; + if ( afterThis->next ) + { + afterThis->next->prev = node; + } + else + { + assert( lastChild == afterThis ); + lastChild = node; + } + afterThis->next = node; + return node; +} + + +TiXmlNode* TiXmlNode::ReplaceChild( TiXmlNode* replaceThis, const TiXmlNode& withThis ) +{ + if ( !replaceThis ) + return 0; + + if ( replaceThis->parent != this ) + return 0; + + if ( withThis.ToDocument() ) { + // A document can never be a child. Thanks to Noam. + TiXmlDocument* document = GetDocument(); + if ( document ) + document->SetError( TIXML_ERROR_DOCUMENT_TOP_ONLY, 0, 0, TIXML_ENCODING_UNKNOWN ); + return 0; + } + + TiXmlNode* node = withThis.Clone(); + if ( !node ) + return 0; + + node->next = replaceThis->next; + node->prev = replaceThis->prev; + + if ( replaceThis->next ) + replaceThis->next->prev = node; + else + lastChild = node; + + if ( replaceThis->prev ) + replaceThis->prev->next = node; + else + firstChild = node; + + delete replaceThis; + node->parent = this; + return node; +} + + +bool TiXmlNode::RemoveChild( TiXmlNode* removeThis ) +{ + if ( !removeThis ) { + return false; + } + + if ( removeThis->parent != this ) + { + assert( 0 ); + return false; + } + + if ( removeThis->next ) + removeThis->next->prev = removeThis->prev; + else + lastChild = removeThis->prev; + + if ( removeThis->prev ) + removeThis->prev->next = removeThis->next; + else + firstChild = removeThis->next; + + delete removeThis; + return true; +} + +const TiXmlNode* TiXmlNode::FirstChild( const char * _value ) const +{ + const TiXmlNode* node; + for ( node = firstChild; node; node = node->next ) + { + if ( strcmp( node->Value(), _value ) == 0 ) + return node; + } + return 0; +} + + +const TiXmlNode* TiXmlNode::LastChild( const char * _value ) const +{ + const TiXmlNode* node; + for ( node = lastChild; node; node = node->prev ) + { + if ( strcmp( node->Value(), _value ) == 0 ) + return node; + } + return 0; +} + + +const TiXmlNode* TiXmlNode::IterateChildren( const TiXmlNode* previous ) const +{ + if ( !previous ) + { + return FirstChild(); + } + else + { + assert( previous->parent == this ); + return previous->NextSibling(); + } +} + + +const TiXmlNode* TiXmlNode::IterateChildren( const char * val, const TiXmlNode* previous ) const +{ + if ( !previous ) + { + return FirstChild( val ); + } + else + { + assert( previous->parent == this ); + return previous->NextSibling( val ); + } +} + + +const TiXmlNode* TiXmlNode::NextSibling( const char * _value ) const +{ + const TiXmlNode* node; + for ( node = next; node; node = node->next ) + { + if ( strcmp( node->Value(), _value ) == 0 ) + return node; + } + return 0; +} + + +const TiXmlNode* TiXmlNode::PreviousSibling( const char * _value ) const +{ + const TiXmlNode* node; + for ( node = prev; node; node = node->prev ) + { + if ( strcmp( node->Value(), _value ) == 0 ) + return node; + } + return 0; +} + + +void TiXmlElement::RemoveAttribute( const char * name ) +{ + #ifdef TIXML_USE_STL + TIXML_STRING str( name ); + TiXmlAttribute* node = attributeSet.Find( str ); + #else + TiXmlAttribute* node = attributeSet.Find( name ); + #endif + if ( node ) + { + attributeSet.Remove( node ); + delete node; + } +} + +const TiXmlElement* TiXmlNode::FirstChildElement() const +{ + const TiXmlNode* node; + + for ( node = FirstChild(); + node; + node = node->NextSibling() ) + { + if ( node->ToElement() ) + return node->ToElement(); + } + return 0; +} + + +const TiXmlElement* TiXmlNode::FirstChildElement( const char * _value ) const +{ + const TiXmlNode* node; + + for ( node = FirstChild( _value ); + node; + node = node->NextSibling( _value ) ) + { + if ( node->ToElement() ) + return node->ToElement(); + } + return 0; +} + + +const TiXmlElement* TiXmlNode::NextSiblingElement() const +{ + const TiXmlNode* node; + + for ( node = NextSibling(); + node; + node = node->NextSibling() ) + { + if ( node->ToElement() ) + return node->ToElement(); + } + return 0; +} + + +const TiXmlElement* TiXmlNode::NextSiblingElement( const char * _value ) const +{ + const TiXmlNode* node; + + for ( node = NextSibling( _value ); + node; + node = node->NextSibling( _value ) ) + { + if ( node->ToElement() ) + return node->ToElement(); + } + return 0; +} + + +const TiXmlDocument* TiXmlNode::GetDocument() const +{ + const TiXmlNode* node; + + for( node = this; node; node = node->parent ) + { + if ( node->ToDocument() ) + return node->ToDocument(); + } + return 0; +} + + +TiXmlElement::TiXmlElement (const char * _value) + : TiXmlNode( TiXmlNode::TINYXML_ELEMENT ) +{ + firstChild = lastChild = 0; + value = _value; +} + + +#ifdef TIXML_USE_STL +TiXmlElement::TiXmlElement( const std::string& _value ) + : TiXmlNode( TiXmlNode::TINYXML_ELEMENT ) +{ + firstChild = lastChild = 0; + value = _value; +} +#endif + + +TiXmlElement::TiXmlElement( const TiXmlElement& copy) + : TiXmlNode( TiXmlNode::TINYXML_ELEMENT ) +{ + firstChild = lastChild = 0; + copy.CopyTo( this ); +} + + +TiXmlElement& TiXmlElement::operator=( const TiXmlElement& base ) +{ + ClearThis(); + base.CopyTo( this ); + return *this; +} + + +TiXmlElement::~TiXmlElement() +{ + ClearThis(); +} + + +void TiXmlElement::ClearThis() +{ + Clear(); + while( attributeSet.First() ) + { + TiXmlAttribute* node = attributeSet.First(); + attributeSet.Remove( node ); + delete node; + } +} + + +const char* TiXmlElement::Attribute( const char* name ) const +{ + const TiXmlAttribute* node = attributeSet.Find( name ); + if ( node ) + return node->Value(); + return 0; +} + + +#ifdef TIXML_USE_STL +const std::string* TiXmlElement::Attribute( const std::string& name ) const +{ + const TiXmlAttribute* attrib = attributeSet.Find( name ); + if ( attrib ) + return &attrib->ValueStr(); + return 0; +} +#endif + + +const char* TiXmlElement::Attribute( const char* name, int* i ) const +{ + const TiXmlAttribute* attrib = attributeSet.Find( name ); + const char* result = 0; + + if ( attrib ) { + result = attrib->Value(); + if ( i ) { + attrib->QueryIntValue( i ); + } + } + return result; +} + + +#ifdef TIXML_USE_STL +const std::string* TiXmlElement::Attribute( const std::string& name, int* i ) const +{ + const TiXmlAttribute* attrib = attributeSet.Find( name ); + const std::string* result = 0; + + if ( attrib ) { + result = &attrib->ValueStr(); + if ( i ) { + attrib->QueryIntValue( i ); + } + } + return result; +} +#endif + + +const char* TiXmlElement::Attribute( const char* name, double* d ) const +{ + const TiXmlAttribute* attrib = attributeSet.Find( name ); + const char* result = 0; + + if ( attrib ) { + result = attrib->Value(); + if ( d ) { + attrib->QueryDoubleValue( d ); + } + } + return result; +} + + +#ifdef TIXML_USE_STL +const std::string* TiXmlElement::Attribute( const std::string& name, double* d ) const +{ + const TiXmlAttribute* attrib = attributeSet.Find( name ); + const std::string* result = 0; + + if ( attrib ) { + result = &attrib->ValueStr(); + if ( d ) { + attrib->QueryDoubleValue( d ); + } + } + return result; +} +#endif + + +int TiXmlElement::QueryIntAttribute( const char* name, int* ival ) const +{ + const TiXmlAttribute* attrib = attributeSet.Find( name ); + if ( !attrib ) + return TIXML_NO_ATTRIBUTE; + return attrib->QueryIntValue( ival ); +} + + +int TiXmlElement::QueryUnsignedAttribute( const char* name, unsigned* value ) const +{ + const TiXmlAttribute* node = attributeSet.Find( name ); + if ( !node ) + return TIXML_NO_ATTRIBUTE; + + int ival = 0; + int result = node->QueryIntValue( &ival ); + *value = (unsigned)ival; + return result; +} + + +int TiXmlElement::QueryBoolAttribute( const char* name, bool* bval ) const +{ + const TiXmlAttribute* node = attributeSet.Find( name ); + if ( !node ) + return TIXML_NO_ATTRIBUTE; + + int result = TIXML_WRONG_TYPE; + if ( StringEqual( node->Value(), "true", true, TIXML_ENCODING_UNKNOWN ) + || StringEqual( node->Value(), "yes", true, TIXML_ENCODING_UNKNOWN ) + || StringEqual( node->Value(), "1", true, TIXML_ENCODING_UNKNOWN ) ) + { + *bval = true; + result = TIXML_SUCCESS; + } + else if ( StringEqual( node->Value(), "false", true, TIXML_ENCODING_UNKNOWN ) + || StringEqual( node->Value(), "no", true, TIXML_ENCODING_UNKNOWN ) + || StringEqual( node->Value(), "0", true, TIXML_ENCODING_UNKNOWN ) ) + { + *bval = false; + result = TIXML_SUCCESS; + } + return result; +} + + + +#ifdef TIXML_USE_STL +int TiXmlElement::QueryIntAttribute( const std::string& name, int* ival ) const +{ + const TiXmlAttribute* attrib = attributeSet.Find( name ); + if ( !attrib ) + return TIXML_NO_ATTRIBUTE; + return attrib->QueryIntValue( ival ); +} +#endif + + +int TiXmlElement::QueryDoubleAttribute( const char* name, double* dval ) const +{ + const TiXmlAttribute* attrib = attributeSet.Find( name ); + if ( !attrib ) + return TIXML_NO_ATTRIBUTE; + return attrib->QueryDoubleValue( dval ); +} + + +#ifdef TIXML_USE_STL +int TiXmlElement::QueryDoubleAttribute( const std::string& name, double* dval ) const +{ + const TiXmlAttribute* attrib = attributeSet.Find( name ); + if ( !attrib ) + return TIXML_NO_ATTRIBUTE; + return attrib->QueryDoubleValue( dval ); +} +#endif + + +void TiXmlElement::SetAttribute( const char * name, int val ) +{ + TiXmlAttribute* attrib = attributeSet.FindOrCreate( name ); + if ( attrib ) { + attrib->SetIntValue( val ); + } +} + + +#ifdef TIXML_USE_STL +void TiXmlElement::SetAttribute( const std::string& name, int val ) +{ + TiXmlAttribute* attrib = attributeSet.FindOrCreate( name ); + if ( attrib ) { + attrib->SetIntValue( val ); + } +} +#endif + + +void TiXmlElement::SetDoubleAttribute( const char * name, double val ) +{ + TiXmlAttribute* attrib = attributeSet.FindOrCreate( name ); + if ( attrib ) { + attrib->SetDoubleValue( val ); + } +} + + +#ifdef TIXML_USE_STL +void TiXmlElement::SetDoubleAttribute( const std::string& name, double val ) +{ + TiXmlAttribute* attrib = attributeSet.FindOrCreate( name ); + if ( attrib ) { + attrib->SetDoubleValue( val ); + } +} +#endif + + +void TiXmlElement::SetAttribute( const char * cname, const char * cvalue ) +{ + TiXmlAttribute* attrib = attributeSet.FindOrCreate( cname ); + if ( attrib ) { + attrib->SetValue( cvalue ); + } +} + + +#ifdef TIXML_USE_STL +void TiXmlElement::SetAttribute( const std::string& _name, const std::string& _value ) +{ + TiXmlAttribute* attrib = attributeSet.FindOrCreate( _name ); + if ( attrib ) { + attrib->SetValue( _value ); + } +} +#endif + + +void TiXmlElement::Print( FILE* cfile, int depth ) const +{ + int i; + assert( cfile ); + for ( i=0; iNext() ) + { + fprintf( cfile, " " ); + attrib->Print( cfile, depth ); + } + + // There are 3 different formatting approaches: + // 1) An element without children is printed as a node + // 2) An element with only a text child is printed as text + // 3) An element with children is printed on multiple lines. + TiXmlNode* node; + if ( !firstChild ) + { + fprintf( cfile, " />" ); + } + else if ( firstChild == lastChild && firstChild->ToText() ) + { + fprintf( cfile, ">" ); + firstChild->Print( cfile, depth + 1 ); + fprintf( cfile, "", value.c_str() ); + } + else + { + fprintf( cfile, ">" ); + + for ( node = firstChild; node; node=node->NextSibling() ) + { + if ( !node->ToText() ) + { + fprintf( cfile, "\n" ); + } + node->Print( cfile, depth+1 ); + } + fprintf( cfile, "\n" ); + for( i=0; i", value.c_str() ); + } +} + + +void TiXmlElement::CopyTo( TiXmlElement* target ) const +{ + // superclass: + TiXmlNode::CopyTo( target ); + + // Element class: + // Clone the attributes, then clone the children. + const TiXmlAttribute* attribute = 0; + for( attribute = attributeSet.First(); + attribute; + attribute = attribute->Next() ) + { + target->SetAttribute( attribute->Name(), attribute->Value() ); + } + + TiXmlNode* node = 0; + for ( node = firstChild; node; node = node->NextSibling() ) + { + target->LinkEndChild( node->Clone() ); + } +} + +bool TiXmlElement::Accept( TiXmlVisitor* visitor ) const +{ + if ( visitor->VisitEnter( *this, attributeSet.First() ) ) + { + for ( const TiXmlNode* node=FirstChild(); node; node=node->NextSibling() ) + { + if ( !node->Accept( visitor ) ) + break; + } + } + return visitor->VisitExit( *this ); +} + + +TiXmlNode* TiXmlElement::Clone() const +{ + TiXmlElement* clone = new TiXmlElement( Value() ); + if ( !clone ) + return 0; + + CopyTo( clone ); + return clone; +} + + +const char* TiXmlElement::GetText() const +{ + const TiXmlNode* child = this->FirstChild(); + if ( child ) { + const TiXmlText* childText = child->ToText(); + if ( childText ) { + return childText->Value(); + } + } + return 0; +} + + +TiXmlDocument::TiXmlDocument() : TiXmlNode( TiXmlNode::TINYXML_DOCUMENT ) +{ + tabsize = 4; + useMicrosoftBOM = false; + ClearError(); +} + +TiXmlDocument::TiXmlDocument( const char * documentName ) : TiXmlNode( TiXmlNode::TINYXML_DOCUMENT ) +{ + tabsize = 4; + useMicrosoftBOM = false; + value = documentName; + ClearError(); +} + + +#ifdef TIXML_USE_STL +TiXmlDocument::TiXmlDocument( const std::string& documentName ) : TiXmlNode( TiXmlNode::TINYXML_DOCUMENT ) +{ + tabsize = 4; + useMicrosoftBOM = false; + value = documentName; + ClearError(); +} +#endif + + +TiXmlDocument::TiXmlDocument( const TiXmlDocument& copy ) : TiXmlNode( TiXmlNode::TINYXML_DOCUMENT ) +{ + copy.CopyTo( this ); +} + + +TiXmlDocument& TiXmlDocument::operator=( const TiXmlDocument& copy ) +{ + Clear(); + copy.CopyTo( this ); + return *this; +} + + +bool TiXmlDocument::LoadFile( TiXmlEncoding encoding ) +{ + return LoadFile( Value(), encoding ); +} + + +bool TiXmlDocument::SaveFile() const +{ + return SaveFile( Value() ); +} + +bool TiXmlDocument::LoadFile( const char* _filename, TiXmlEncoding encoding ) +{ + TIXML_STRING filename( _filename ); + value = filename; + + // reading in binary mode so that tinyxml can normalize the EOL + FILE* file = TiXmlFOpen( value.c_str (), "rb" ); + + if ( file ) + { + bool result = LoadFile( file, encoding ); + fclose( file ); + return result; + } + else + { + SetError( TIXML_ERROR_OPENING_FILE, 0, 0, TIXML_ENCODING_UNKNOWN ); + return false; + } +} + +bool TiXmlDocument::LoadFile( FILE* file, TiXmlEncoding encoding ) +{ + if ( !file ) + { + SetError( TIXML_ERROR_OPENING_FILE, 0, 0, TIXML_ENCODING_UNKNOWN ); + return false; + } + + // Delete the existing data: + Clear(); + location.Clear(); + + // Get the file size, so we can pre-allocate the string. HUGE speed impact. + long length = 0; + fseek( file, 0, SEEK_END ); + length = ftell( file ); + fseek( file, 0, SEEK_SET ); + + // Strange case, but good to handle up front. + if ( length <= 0 ) + { + SetError( TIXML_ERROR_DOCUMENT_EMPTY, 0, 0, TIXML_ENCODING_UNKNOWN ); + return false; + } + + // Subtle bug here. TinyXml did use fgets. But from the XML spec: + // 2.11 End-of-Line Handling + // + // + // ...the XML processor MUST behave as if it normalized all line breaks in external + // parsed entities (including the document entity) on input, before parsing, by translating + // both the two-character sequence #xD #xA and any #xD that is not followed by #xA to + // a single #xA character. + // + // + // It is not clear fgets does that, and certainly isn't clear it works cross platform. + // Generally, you expect fgets to translate from the convention of the OS to the c/unix + // convention, and not work generally. + + /* + while( fgets( buf, sizeof(buf), file ) ) + { + data += buf; + } + */ + + char* buf = new char[ length+1 ]; + buf[0] = 0; + + if ( fread( buf, length, 1, file ) != 1 ) { + delete [] buf; + SetError( TIXML_ERROR_OPENING_FILE, 0, 0, TIXML_ENCODING_UNKNOWN ); + return false; + } + + // Process the buffer in place to normalize new lines. (See comment above.) + // Copies from the 'p' to 'q' pointer, where p can advance faster if + // a newline-carriage return is hit. + // + // Wikipedia: + // Systems based on ASCII or a compatible character set use either LF (Line feed, '\n', 0x0A, 10 in decimal) or + // CR (Carriage return, '\r', 0x0D, 13 in decimal) individually, or CR followed by LF (CR+LF, 0x0D 0x0A)... + // * LF: Multics, Unix and Unix-like systems (GNU/Linux, AIX, Xenix, Mac OS X, FreeBSD, etc.), BeOS, Amiga, RISC OS, and others + // * CR+LF: DEC RT-11 and most other early non-Unix, non-IBM OSes, CP/M, MP/M, DOS, OS/2, Microsoft Windows, Symbian OS + // * CR: Commodore 8-bit machines, Apple II family, Mac OS up to version 9 and OS-9 + + const char* p = buf; // the read head + char* q = buf; // the write head + const char CR = 0x0d; + const char LF = 0x0a; + + buf[length] = 0; + while( *p ) { + assert( p < (buf+length) ); + assert( q <= (buf+length) ); + assert( q <= p ); + + if ( *p == CR ) { + *q++ = LF; + p++; + if ( *p == LF ) { // check for CR+LF (and skip LF) + p++; + } + } + else { + *q++ = *p++; + } + } + assert( q <= (buf+length) ); + *q = 0; + + Parse( buf, 0, encoding ); + + delete [] buf; + return !Error(); +} + + +bool TiXmlDocument::SaveFile( const char * filename ) const +{ + // The old c stuff lives on... + FILE* fp = TiXmlFOpen( filename, "w" ); + if ( fp ) + { + bool result = SaveFile( fp ); + fclose( fp ); + return result; + } + return false; +} + + +bool TiXmlDocument::SaveFile( FILE* fp ) const +{ + if ( useMicrosoftBOM ) + { + const unsigned char TIXML_UTF_LEAD_0 = 0xefU; + const unsigned char TIXML_UTF_LEAD_1 = 0xbbU; + const unsigned char TIXML_UTF_LEAD_2 = 0xbfU; + + fputc( TIXML_UTF_LEAD_0, fp ); + fputc( TIXML_UTF_LEAD_1, fp ); + fputc( TIXML_UTF_LEAD_2, fp ); + } + Print( fp, 0 ); + return (ferror(fp) == 0); +} + + +void TiXmlDocument::CopyTo( TiXmlDocument* target ) const +{ + TiXmlNode::CopyTo( target ); + + target->error = error; + target->errorId = errorId; + target->errorDesc = errorDesc; + target->tabsize = tabsize; + target->errorLocation = errorLocation; + target->useMicrosoftBOM = useMicrosoftBOM; + + TiXmlNode* node = 0; + for ( node = firstChild; node; node = node->NextSibling() ) + { + target->LinkEndChild( node->Clone() ); + } +} + + +TiXmlNode* TiXmlDocument::Clone() const +{ + TiXmlDocument* clone = new TiXmlDocument(); + if ( !clone ) + return 0; + + CopyTo( clone ); + return clone; +} + + +void TiXmlDocument::Print( FILE* cfile, int depth ) const +{ + assert( cfile ); + for ( const TiXmlNode* node=FirstChild(); node; node=node->NextSibling() ) + { + node->Print( cfile, depth ); + fprintf( cfile, "\n" ); + } +} + + +bool TiXmlDocument::Accept( TiXmlVisitor* visitor ) const +{ + if ( visitor->VisitEnter( *this ) ) + { + for ( const TiXmlNode* node=FirstChild(); node; node=node->NextSibling() ) + { + if ( !node->Accept( visitor ) ) + break; + } + } + return visitor->VisitExit( *this ); +} + + +const TiXmlAttribute* TiXmlAttribute::Next() const +{ + // We are using knowledge of the sentinel. The sentinel + // have a value or name. + if ( next->value.empty() && next->name.empty() ) + return 0; + return next; +} + +/* +TiXmlAttribute* TiXmlAttribute::Next() +{ + // We are using knowledge of the sentinel. The sentinel + // have a value or name. + if ( next->value.empty() && next->name.empty() ) + return 0; + return next; +} +*/ + +const TiXmlAttribute* TiXmlAttribute::Previous() const +{ + // We are using knowledge of the sentinel. The sentinel + // have a value or name. + if ( prev->value.empty() && prev->name.empty() ) + return 0; + return prev; +} + +/* +TiXmlAttribute* TiXmlAttribute::Previous() +{ + // We are using knowledge of the sentinel. The sentinel + // have a value or name. + if ( prev->value.empty() && prev->name.empty() ) + return 0; + return prev; +} +*/ + +void TiXmlAttribute::Print( FILE* cfile, int /*depth*/, TIXML_STRING* str ) const +{ + TIXML_STRING n, v; + + EncodeString( name, &n ); + EncodeString( value, &v ); + + if (value.find ('\"') == TIXML_STRING::npos) { + if ( cfile ) { + fprintf (cfile, "%s=\"%s\"", n.c_str(), v.c_str() ); + } + if ( str ) { + (*str) += n; (*str) += "=\""; (*str) += v; (*str) += "\""; + } + } + else { + if ( cfile ) { + fprintf (cfile, "%s='%s'", n.c_str(), v.c_str() ); + } + if ( str ) { + (*str) += n; (*str) += "='"; (*str) += v; (*str) += "'"; + } + } +} + + +int TiXmlAttribute::QueryIntValue( int* ival ) const +{ + if ( TIXML_SSCANF( value.c_str(), "%d", ival ) == 1 ) + return TIXML_SUCCESS; + return TIXML_WRONG_TYPE; +} + +int TiXmlAttribute::QueryDoubleValue( double* dval ) const +{ + if ( TIXML_SSCANF( value.c_str(), "%lf", dval ) == 1 ) + return TIXML_SUCCESS; + return TIXML_WRONG_TYPE; +} + +void TiXmlAttribute::SetIntValue( int _value ) +{ + char buf [64]; + #if defined(TIXML_SNPRINTF) + TIXML_SNPRINTF(buf, sizeof(buf), "%d", _value); + #else + sprintf (buf, "%d", _value); + #endif + SetValue (buf); +} + +void TiXmlAttribute::SetDoubleValue( double _value ) +{ + char buf [256]; + #if defined(TIXML_SNPRINTF) + TIXML_SNPRINTF( buf, sizeof(buf), "%g", _value); + #else + sprintf (buf, "%g", _value); + #endif + SetValue (buf); +} + +int TiXmlAttribute::IntValue() const +{ + return atoi (value.c_str ()); +} + +double TiXmlAttribute::DoubleValue() const +{ + return atof (value.c_str ()); +} + + +TiXmlComment::TiXmlComment( const TiXmlComment& copy ) : TiXmlNode( TiXmlNode::TINYXML_COMMENT ) +{ + copy.CopyTo( this ); +} + + +TiXmlComment& TiXmlComment::operator=( const TiXmlComment& base ) +{ + Clear(); + base.CopyTo( this ); + return *this; +} + + +void TiXmlComment::Print( FILE* cfile, int depth ) const +{ + assert( cfile ); + for ( int i=0; i", value.c_str() ); +} + + +void TiXmlComment::CopyTo( TiXmlComment* target ) const +{ + TiXmlNode::CopyTo( target ); +} + + +bool TiXmlComment::Accept( TiXmlVisitor* visitor ) const +{ + return visitor->Visit( *this ); +} + + +TiXmlNode* TiXmlComment::Clone() const +{ + TiXmlComment* clone = new TiXmlComment(); + + if ( !clone ) + return 0; + + CopyTo( clone ); + return clone; +} + + +void TiXmlText::Print( FILE* cfile, int depth ) const +{ + assert( cfile ); + if ( cdata ) + { + int i; + fprintf( cfile, "\n" ); + for ( i=0; i\n", value.c_str() ); // unformatted output + } + else + { + TIXML_STRING buffer; + EncodeString( value, &buffer ); + fprintf( cfile, "%s", buffer.c_str() ); + } +} + + +void TiXmlText::CopyTo( TiXmlText* target ) const +{ + TiXmlNode::CopyTo( target ); + target->cdata = cdata; +} + + +bool TiXmlText::Accept( TiXmlVisitor* visitor ) const +{ + return visitor->Visit( *this ); +} + + +TiXmlNode* TiXmlText::Clone() const +{ + TiXmlText* clone = 0; + clone = new TiXmlText( "" ); + + if ( !clone ) + return 0; + + CopyTo( clone ); + return clone; +} + + +TiXmlDeclaration::TiXmlDeclaration( const char * _version, + const char * _encoding, + const char * _standalone ) + : TiXmlNode( TiXmlNode::TINYXML_DECLARATION ) +{ + version = _version; + encoding = _encoding; + standalone = _standalone; +} + + +#ifdef TIXML_USE_STL +TiXmlDeclaration::TiXmlDeclaration( const std::string& _version, + const std::string& _encoding, + const std::string& _standalone ) + : TiXmlNode( TiXmlNode::TINYXML_DECLARATION ) +{ + version = _version; + encoding = _encoding; + standalone = _standalone; +} +#endif + + +TiXmlDeclaration::TiXmlDeclaration( const TiXmlDeclaration& copy ) + : TiXmlNode( TiXmlNode::TINYXML_DECLARATION ) +{ + copy.CopyTo( this ); +} + + +TiXmlDeclaration& TiXmlDeclaration::operator=( const TiXmlDeclaration& copy ) +{ + Clear(); + copy.CopyTo( this ); + return *this; +} + + +void TiXmlDeclaration::Print( FILE* cfile, int /*depth*/, TIXML_STRING* str ) const +{ + if ( cfile ) fprintf( cfile, "" ); + if ( str ) (*str) += "?>"; +} + + +void TiXmlDeclaration::CopyTo( TiXmlDeclaration* target ) const +{ + TiXmlNode::CopyTo( target ); + + target->version = version; + target->encoding = encoding; + target->standalone = standalone; +} + + +bool TiXmlDeclaration::Accept( TiXmlVisitor* visitor ) const +{ + return visitor->Visit( *this ); +} + + +TiXmlNode* TiXmlDeclaration::Clone() const +{ + TiXmlDeclaration* clone = new TiXmlDeclaration(); + + if ( !clone ) + return 0; + + CopyTo( clone ); + return clone; +} + + +void TiXmlUnknown::Print( FILE* cfile, int depth ) const +{ + for ( int i=0; i", value.c_str() ); +} + + +void TiXmlUnknown::CopyTo( TiXmlUnknown* target ) const +{ + TiXmlNode::CopyTo( target ); +} + + +bool TiXmlUnknown::Accept( TiXmlVisitor* visitor ) const +{ + return visitor->Visit( *this ); +} + + +TiXmlNode* TiXmlUnknown::Clone() const +{ + TiXmlUnknown* clone = new TiXmlUnknown(); + + if ( !clone ) + return 0; + + CopyTo( clone ); + return clone; +} + + +TiXmlAttributeSet::TiXmlAttributeSet() +{ + sentinel.next = &sentinel; + sentinel.prev = &sentinel; +} + + +TiXmlAttributeSet::~TiXmlAttributeSet() +{ + assert( sentinel.next == &sentinel ); + assert( sentinel.prev == &sentinel ); +} + + +void TiXmlAttributeSet::Add( TiXmlAttribute* addMe ) +{ + #ifdef TIXML_USE_STL + assert( !Find( TIXML_STRING( addMe->Name() ) ) ); // Shouldn't be multiply adding to the set. + #else + assert( !Find( addMe->Name() ) ); // Shouldn't be multiply adding to the set. + #endif + + addMe->next = &sentinel; + addMe->prev = sentinel.prev; + + sentinel.prev->next = addMe; + sentinel.prev = addMe; +} + +void TiXmlAttributeSet::Remove( TiXmlAttribute* removeMe ) +{ + TiXmlAttribute* node; + + for( node = sentinel.next; node != &sentinel; node = node->next ) + { + if ( node == removeMe ) + { + node->prev->next = node->next; + node->next->prev = node->prev; + node->next = 0; + node->prev = 0; + return; + } + } + assert( 0 ); // we tried to remove a non-linked attribute. +} + + +#ifdef TIXML_USE_STL +TiXmlAttribute* TiXmlAttributeSet::Find( const std::string& name ) const +{ + for( TiXmlAttribute* node = sentinel.next; node != &sentinel; node = node->next ) + { + if ( node->name == name ) + return node; + } + return 0; +} + +TiXmlAttribute* TiXmlAttributeSet::FindOrCreate( const std::string& _name ) +{ + TiXmlAttribute* attrib = Find( _name ); + if ( !attrib ) { + attrib = new TiXmlAttribute(); + Add( attrib ); + attrib->SetName( _name ); + } + return attrib; +} +#endif + + +TiXmlAttribute* TiXmlAttributeSet::Find( const char* name ) const +{ + for( TiXmlAttribute* node = sentinel.next; node != &sentinel; node = node->next ) + { + if ( strcmp( node->name.c_str(), name ) == 0 ) + return node; + } + return 0; +} + + +TiXmlAttribute* TiXmlAttributeSet::FindOrCreate( const char* _name ) +{ + TiXmlAttribute* attrib = Find( _name ); + if ( !attrib ) { + attrib = new TiXmlAttribute(); + Add( attrib ); + attrib->SetName( _name ); + } + return attrib; +} + + +#ifdef TIXML_USE_STL +std::istream& operator>> (std::istream & in, TiXmlNode & base) +{ + TIXML_STRING tag; + tag.reserve( 8 * 1000 ); + base.StreamIn( &in, &tag ); + + base.Parse( tag.c_str(), 0, TIXML_DEFAULT_ENCODING ); + return in; +} +#endif + + +#ifdef TIXML_USE_STL +std::ostream& operator<< (std::ostream & out, const TiXmlNode & base) +{ + TiXmlPrinter printer; + printer.SetStreamPrinting(); + base.Accept( &printer ); + out << printer.Str(); + + return out; +} + + +std::string& operator<< (std::string& out, const TiXmlNode& base ) +{ + TiXmlPrinter printer; + printer.SetStreamPrinting(); + base.Accept( &printer ); + out.append( printer.Str() ); + + return out; +} +#endif + + +TiXmlHandle TiXmlHandle::FirstChild() const +{ + if ( node ) + { + TiXmlNode* child = node->FirstChild(); + if ( child ) + return TiXmlHandle( child ); + } + return TiXmlHandle( 0 ); +} + + +TiXmlHandle TiXmlHandle::FirstChild( const char * value ) const +{ + if ( node ) + { + TiXmlNode* child = node->FirstChild( value ); + if ( child ) + return TiXmlHandle( child ); + } + return TiXmlHandle( 0 ); +} + + +TiXmlHandle TiXmlHandle::FirstChildElement() const +{ + if ( node ) + { + TiXmlElement* child = node->FirstChildElement(); + if ( child ) + return TiXmlHandle( child ); + } + return TiXmlHandle( 0 ); +} + + +TiXmlHandle TiXmlHandle::FirstChildElement( const char * value ) const +{ + if ( node ) + { + TiXmlElement* child = node->FirstChildElement( value ); + if ( child ) + return TiXmlHandle( child ); + } + return TiXmlHandle( 0 ); +} + + +TiXmlHandle TiXmlHandle::Child( int count ) const +{ + if ( node ) + { + int i; + TiXmlNode* child = node->FirstChild(); + for ( i=0; + child && iNextSibling(), ++i ) + { + // nothing + } + if ( child ) + return TiXmlHandle( child ); + } + return TiXmlHandle( 0 ); +} + + +TiXmlHandle TiXmlHandle::Child( const char* value, int count ) const +{ + if ( node ) + { + int i; + TiXmlNode* child = node->FirstChild( value ); + for ( i=0; + child && iNextSibling( value ), ++i ) + { + // nothing + } + if ( child ) + return TiXmlHandle( child ); + } + return TiXmlHandle( 0 ); +} + + +TiXmlHandle TiXmlHandle::ChildElement( int count ) const +{ + if ( node ) + { + int i; + TiXmlElement* child = node->FirstChildElement(); + for ( i=0; + child && iNextSiblingElement(), ++i ) + { + // nothing + } + if ( child ) + return TiXmlHandle( child ); + } + return TiXmlHandle( 0 ); +} + + +TiXmlHandle TiXmlHandle::ChildElement( const char* value, int count ) const +{ + if ( node ) + { + int i; + TiXmlElement* child = node->FirstChildElement( value ); + for ( i=0; + child && iNextSiblingElement( value ), ++i ) + { + // nothing + } + if ( child ) + return TiXmlHandle( child ); + } + return TiXmlHandle( 0 ); +} + + +bool TiXmlPrinter::VisitEnter( const TiXmlDocument& ) +{ + return true; +} + +bool TiXmlPrinter::VisitExit( const TiXmlDocument& ) +{ + return true; +} + +bool TiXmlPrinter::VisitEnter( const TiXmlElement& element, const TiXmlAttribute* firstAttribute ) +{ + DoIndent(); + buffer += "<"; + buffer += element.Value(); + + for( const TiXmlAttribute* attrib = firstAttribute; attrib; attrib = attrib->Next() ) + { + buffer += " "; + attrib->Print( 0, 0, &buffer ); + } + + if ( !element.FirstChild() ) + { + buffer += " />"; + DoLineBreak(); + } + else + { + buffer += ">"; + if ( element.FirstChild()->ToText() + && element.LastChild() == element.FirstChild() + && element.FirstChild()->ToText()->CDATA() == false ) + { + simpleTextPrint = true; + // no DoLineBreak()! + } + else + { + DoLineBreak(); + } + } + ++depth; + return true; +} + + +bool TiXmlPrinter::VisitExit( const TiXmlElement& element ) +{ + --depth; + if ( !element.FirstChild() ) + { + // nothing. + } + else + { + if ( simpleTextPrint ) + { + simpleTextPrint = false; + } + else + { + DoIndent(); + } + buffer += ""; + DoLineBreak(); + } + return true; +} + + +bool TiXmlPrinter::Visit( const TiXmlText& text ) +{ + if ( text.CDATA() ) + { + DoIndent(); + buffer += ""; + DoLineBreak(); + } + else if ( simpleTextPrint ) + { + TIXML_STRING str; + TiXmlBase::EncodeString( text.ValueTStr(), &str ); + buffer += str; + } + else + { + DoIndent(); + TIXML_STRING str; + TiXmlBase::EncodeString( text.ValueTStr(), &str ); + buffer += str; + DoLineBreak(); + } + return true; +} + + +bool TiXmlPrinter::Visit( const TiXmlDeclaration& declaration ) +{ + DoIndent(); + declaration.Print( 0, 0, &buffer ); + DoLineBreak(); + return true; +} + + +bool TiXmlPrinter::Visit( const TiXmlComment& comment ) +{ + DoIndent(); + buffer += ""; + DoLineBreak(); + return true; +} + + +bool TiXmlPrinter::Visit( const TiXmlUnknown& unknown ) +{ + DoIndent(); + buffer += "<"; + buffer += unknown.Value(); + buffer += ">"; + DoLineBreak(); + return true; +} + diff --git a/test/tinyxml/tinyxml.h b/test/tinyxml/tinyxml.h new file mode 100644 index 0000000..a3589e5 --- /dev/null +++ b/test/tinyxml/tinyxml.h @@ -0,0 +1,1805 @@ +/* +www.sourceforge.net/projects/tinyxml +Original code by Lee Thomason (www.grinninglizard.com) + +This software is provided 'as-is', without any express or implied +warranty. In no event will the authors be held liable for any +damages arising from the use of this software. + +Permission is granted to anyone to use this software for any +purpose, including commercial applications, and to alter it and +redistribute it freely, subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must +not claim that you wrote the original software. If you use this +software in a product, an acknowledgment in the product documentation +would be appreciated but is not required. + +2. Altered source versions must be plainly marked as such, and +must not be misrepresented as being the original software. + +3. This notice may not be removed or altered from any source +distribution. +*/ + + +#ifndef TINYXML_INCLUDED +#define TINYXML_INCLUDED + +#ifdef _MSC_VER +#pragma warning( push ) +#pragma warning( disable : 4530 ) +#pragma warning( disable : 4786 ) +#endif + +#include +#include +#include +#include +#include + +// Help out windows: +#if defined( _DEBUG ) && !defined( DEBUG ) +#define DEBUG +#endif + +#ifdef TIXML_USE_STL + #include + #include + #include + #define TIXML_STRING std::string +#else + #include "tinystr.h" + #define TIXML_STRING TiXmlString +#endif + +// Deprecated library function hell. Compilers want to use the +// new safe versions. This probably doesn't fully address the problem, +// but it gets closer. There are too many compilers for me to fully +// test. If you get compilation troubles, undefine TIXML_SAFE +#define TIXML_SAFE + +#ifdef TIXML_SAFE + #if defined(_MSC_VER) && (_MSC_VER >= 1400 ) + // Microsoft visual studio, version 2005 and higher. + #define TIXML_SNPRINTF _snprintf_s + #define TIXML_SSCANF sscanf_s + #elif defined(_MSC_VER) && (_MSC_VER >= 1200 ) + // Microsoft visual studio, version 6 and higher. + //#pragma message( "Using _sn* functions." ) + #define TIXML_SNPRINTF _snprintf + #define TIXML_SSCANF sscanf + #elif defined(__GNUC__) && (__GNUC__ >= 3 ) + // GCC version 3 and higher.s + //#warning( "Using sn* functions." ) + #define TIXML_SNPRINTF snprintf + #define TIXML_SSCANF sscanf + #else + #define TIXML_SNPRINTF snprintf + #define TIXML_SSCANF sscanf + #endif +#endif + +class TiXmlDocument; +class TiXmlElement; +class TiXmlComment; +class TiXmlUnknown; +class TiXmlAttribute; +class TiXmlText; +class TiXmlDeclaration; +class TiXmlParsingData; + +const int TIXML_MAJOR_VERSION = 2; +const int TIXML_MINOR_VERSION = 6; +const int TIXML_PATCH_VERSION = 2; + +/* Internal structure for tracking location of items + in the XML file. +*/ +struct TiXmlCursor +{ + TiXmlCursor() { Clear(); } + void Clear() { row = col = -1; } + + int row; // 0 based. + int col; // 0 based. +}; + + +/** + Implements the interface to the "Visitor pattern" (see the Accept() method.) + If you call the Accept() method, it requires being passed a TiXmlVisitor + class to handle callbacks. For nodes that contain other nodes (Document, Element) + you will get called with a VisitEnter/VisitExit pair. Nodes that are always leaves + are simply called with Visit(). + + If you return 'true' from a Visit method, recursive parsing will continue. If you return + false, no children of this node or its sibilings will be Visited. + + All flavors of Visit methods have a default implementation that returns 'true' (continue + visiting). You need to only override methods that are interesting to you. + + Generally Accept() is called on the TiXmlDocument, although all nodes suppert Visiting. + + You should never change the document from a callback. + + @sa TiXmlNode::Accept() +*/ +class TiXmlVisitor +{ +public: + virtual ~TiXmlVisitor() {} + + /// Visit a document. + virtual bool VisitEnter( const TiXmlDocument& /*doc*/ ) { return true; } + /// Visit a document. + virtual bool VisitExit( const TiXmlDocument& /*doc*/ ) { return true; } + + /// Visit an element. + virtual bool VisitEnter( const TiXmlElement& /*element*/, const TiXmlAttribute* /*firstAttribute*/ ) { return true; } + /// Visit an element. + virtual bool VisitExit( const TiXmlElement& /*element*/ ) { return true; } + + /// Visit a declaration + virtual bool Visit( const TiXmlDeclaration& /*declaration*/ ) { return true; } + /// Visit a text node + virtual bool Visit( const TiXmlText& /*text*/ ) { return true; } + /// Visit a comment node + virtual bool Visit( const TiXmlComment& /*comment*/ ) { return true; } + /// Visit an unknown node + virtual bool Visit( const TiXmlUnknown& /*unknown*/ ) { return true; } +}; + +// Only used by Attribute::Query functions +enum +{ + TIXML_SUCCESS, + TIXML_NO_ATTRIBUTE, + TIXML_WRONG_TYPE +}; + + +// Used by the parsing routines. +enum TiXmlEncoding +{ + TIXML_ENCODING_UNKNOWN, + TIXML_ENCODING_UTF8, + TIXML_ENCODING_LEGACY +}; + +const TiXmlEncoding TIXML_DEFAULT_ENCODING = TIXML_ENCODING_UNKNOWN; + +/** TiXmlBase is a base class for every class in TinyXml. + It does little except to establish that TinyXml classes + can be printed and provide some utility functions. + + In XML, the document and elements can contain + other elements and other types of nodes. + + @verbatim + A Document can contain: Element (container or leaf) + Comment (leaf) + Unknown (leaf) + Declaration( leaf ) + + An Element can contain: Element (container or leaf) + Text (leaf) + Attributes (not on tree) + Comment (leaf) + Unknown (leaf) + + A Decleration contains: Attributes (not on tree) + @endverbatim +*/ +class TiXmlBase +{ + friend class TiXmlNode; + friend class TiXmlElement; + friend class TiXmlDocument; + +public: + TiXmlBase() : userData(0) {} + virtual ~TiXmlBase() {} + + /** All TinyXml classes can print themselves to a filestream + or the string class (TiXmlString in non-STL mode, std::string + in STL mode.) Either or both cfile and str can be null. + + This is a formatted print, and will insert + tabs and newlines. + + (For an unformatted stream, use the << operator.) + */ + virtual void Print( FILE* cfile, int depth ) const = 0; + + /** The world does not agree on whether white space should be kept or + not. In order to make everyone happy, these global, static functions + are provided to set whether or not TinyXml will condense all white space + into a single space or not. The default is to condense. Note changing this + value is not thread safe. + */ + static void SetCondenseWhiteSpace( bool condense ) { condenseWhiteSpace = condense; } + + /// Return the current white space setting. + static bool IsWhiteSpaceCondensed() { return condenseWhiteSpace; } + + /** Return the position, in the original source file, of this node or attribute. + The row and column are 1-based. (That is the first row and first column is + 1,1). If the returns values are 0 or less, then the parser does not have + a row and column value. + + Generally, the row and column value will be set when the TiXmlDocument::Load(), + TiXmlDocument::LoadFile(), or any TiXmlNode::Parse() is called. It will NOT be set + when the DOM was created from operator>>. + + The values reflect the initial load. Once the DOM is modified programmatically + (by adding or changing nodes and attributes) the new values will NOT update to + reflect changes in the document. + + There is a minor performance cost to computing the row and column. Computation + can be disabled if TiXmlDocument::SetTabSize() is called with 0 as the value. + + @sa TiXmlDocument::SetTabSize() + */ + int Row() const { return location.row + 1; } + int Column() const { return location.col + 1; } ///< See Row() + + void SetUserData( void* user ) { userData = user; } ///< Set a pointer to arbitrary user data. + void* GetUserData() { return userData; } ///< Get a pointer to arbitrary user data. + const void* GetUserData() const { return userData; } ///< Get a pointer to arbitrary user data. + + // Table that returs, for a given lead byte, the total number of bytes + // in the UTF-8 sequence. + static const int utf8ByteTable[256]; + + virtual const char* Parse( const char* p, + TiXmlParsingData* data, + TiXmlEncoding encoding /*= TIXML_ENCODING_UNKNOWN */ ) = 0; + + /** Expands entities in a string. Note this should not contian the tag's '<', '>', etc, + or they will be transformed into entities! + */ + static void EncodeString( const TIXML_STRING& str, TIXML_STRING* out ); + + enum + { + TIXML_NO_ERROR = 0, + TIXML_ERROR, + TIXML_ERROR_OPENING_FILE, + TIXML_ERROR_PARSING_ELEMENT, + TIXML_ERROR_FAILED_TO_READ_ELEMENT_NAME, + TIXML_ERROR_READING_ELEMENT_VALUE, + TIXML_ERROR_READING_ATTRIBUTES, + TIXML_ERROR_PARSING_EMPTY, + TIXML_ERROR_READING_END_TAG, + TIXML_ERROR_PARSING_UNKNOWN, + TIXML_ERROR_PARSING_COMMENT, + TIXML_ERROR_PARSING_DECLARATION, + TIXML_ERROR_DOCUMENT_EMPTY, + TIXML_ERROR_EMBEDDED_NULL, + TIXML_ERROR_PARSING_CDATA, + TIXML_ERROR_DOCUMENT_TOP_ONLY, + + TIXML_ERROR_STRING_COUNT + }; + +protected: + + static const char* SkipWhiteSpace( const char*, TiXmlEncoding encoding ); + + inline static bool IsWhiteSpace( char c ) + { + return ( isspace( (unsigned char) c ) || c == '\n' || c == '\r' ); + } + inline static bool IsWhiteSpace( int c ) + { + if ( c < 256 ) + return IsWhiteSpace( (char) c ); + return false; // Again, only truly correct for English/Latin...but usually works. + } + + #ifdef TIXML_USE_STL + static bool StreamWhiteSpace( std::istream * in, TIXML_STRING * tag ); + static bool StreamTo( std::istream * in, int character, TIXML_STRING * tag ); + #endif + + /* Reads an XML name into the string provided. Returns + a pointer just past the last character of the name, + or 0 if the function has an error. + */ + static const char* ReadName( const char* p, TIXML_STRING* name, TiXmlEncoding encoding ); + + /* Reads text. Returns a pointer past the given end tag. + Wickedly complex options, but it keeps the (sensitive) code in one place. + */ + static const char* ReadText( const char* in, // where to start + TIXML_STRING* text, // the string read + bool ignoreWhiteSpace, // whether to keep the white space + const char* endTag, // what ends this text + bool ignoreCase, // whether to ignore case in the end tag + TiXmlEncoding encoding ); // the current encoding + + // If an entity has been found, transform it into a character. + static const char* GetEntity( const char* in, char* value, int* length, TiXmlEncoding encoding ); + + // Get a character, while interpreting entities. + // The length can be from 0 to 4 bytes. + inline static const char* GetChar( const char* p, char* _value, int* length, TiXmlEncoding encoding ) + { + assert( p ); + if ( encoding == TIXML_ENCODING_UTF8 ) + { + *length = utf8ByteTable[ *((const unsigned char*)p) ]; + assert( *length >= 0 && *length < 5 ); + } + else + { + *length = 1; + } + + if ( *length == 1 ) + { + if ( *p == '&' ) + return GetEntity( p, _value, length, encoding ); + *_value = *p; + return p+1; + } + else if ( *length ) + { + //strncpy( _value, p, *length ); // lots of compilers don't like this function (unsafe), + // and the null terminator isn't needed + for( int i=0; p[i] && i<*length; ++i ) { + _value[i] = p[i]; + } + return p + (*length); + } + else + { + // Not valid text. + return 0; + } + } + + // Return true if the next characters in the stream are any of the endTag sequences. + // Ignore case only works for english, and should only be relied on when comparing + // to English words: StringEqual( p, "version", true ) is fine. + static bool StringEqual( const char* p, + const char* endTag, + bool ignoreCase, + TiXmlEncoding encoding ); + + static const char* errorString[ TIXML_ERROR_STRING_COUNT ]; + + TiXmlCursor location; + + /// Field containing a generic user pointer + void* userData; + + // None of these methods are reliable for any language except English. + // Good for approximation, not great for accuracy. + static int IsAlpha( unsigned char anyByte, TiXmlEncoding encoding ); + static int IsAlphaNum( unsigned char anyByte, TiXmlEncoding encoding ); + inline static int ToLower( int v, TiXmlEncoding encoding ) + { + if ( encoding == TIXML_ENCODING_UTF8 ) + { + if ( v < 128 ) return tolower( v ); + return v; + } + else + { + return tolower( v ); + } + } + static void ConvertUTF32ToUTF8( unsigned long input, char* output, int* length ); + +private: + TiXmlBase( const TiXmlBase& ); // not implemented. + void operator=( const TiXmlBase& base ); // not allowed. + + struct Entity + { + const char* str; + unsigned int strLength; + char chr; + }; + enum + { + NUM_ENTITY = 5, + MAX_ENTITY_LENGTH = 6 + + }; + static Entity entity[ NUM_ENTITY ]; + static bool condenseWhiteSpace; +}; + + +/** The parent class for everything in the Document Object Model. + (Except for attributes). + Nodes have siblings, a parent, and children. A node can be + in a document, or stand on its own. The type of a TiXmlNode + can be queried, and it can be cast to its more defined type. +*/ +class TiXmlNode : public TiXmlBase +{ + friend class TiXmlDocument; + friend class TiXmlElement; + +public: + #ifdef TIXML_USE_STL + + /** An input stream operator, for every class. Tolerant of newlines and + formatting, but doesn't expect them. + */ + friend std::istream& operator >> (std::istream& in, TiXmlNode& base); + + /** An output stream operator, for every class. Note that this outputs + without any newlines or formatting, as opposed to Print(), which + includes tabs and new lines. + + The operator<< and operator>> are not completely symmetric. Writing + a node to a stream is very well defined. You'll get a nice stream + of output, without any extra whitespace or newlines. + + But reading is not as well defined. (As it always is.) If you create + a TiXmlElement (for example) and read that from an input stream, + the text needs to define an element or junk will result. This is + true of all input streams, but it's worth keeping in mind. + + A TiXmlDocument will read nodes until it reads a root element, and + all the children of that root element. + */ + friend std::ostream& operator<< (std::ostream& out, const TiXmlNode& base); + + /// Appends the XML node or attribute to a std::string. + friend std::string& operator<< (std::string& out, const TiXmlNode& base ); + + #endif + + /** The types of XML nodes supported by TinyXml. (All the + unsupported types are picked up by UNKNOWN.) + */ + enum NodeType + { + TINYXML_DOCUMENT, + TINYXML_ELEMENT, + TINYXML_COMMENT, + TINYXML_UNKNOWN, + TINYXML_TEXT, + TINYXML_DECLARATION, + TINYXML_TYPECOUNT + }; + + virtual ~TiXmlNode(); + + /** The meaning of 'value' changes for the specific type of + TiXmlNode. + @verbatim + Document: filename of the xml file + Element: name of the element + Comment: the comment text + Unknown: the tag contents + Text: the text string + @endverbatim + + The subclasses will wrap this function. + */ + const char *Value() const { return value.c_str (); } + + #ifdef TIXML_USE_STL + /** Return Value() as a std::string. If you only use STL, + this is more efficient than calling Value(). + Only available in STL mode. + */ + const std::string& ValueStr() const { return value; } + #endif + + const TIXML_STRING& ValueTStr() const { return value; } + + /** Changes the value of the node. Defined as: + @verbatim + Document: filename of the xml file + Element: name of the element + Comment: the comment text + Unknown: the tag contents + Text: the text string + @endverbatim + */ + void SetValue(const char * _value) { value = _value;} + + #ifdef TIXML_USE_STL + /// STL std::string form. + void SetValue( const std::string& _value ) { value = _value; } + #endif + + /// Delete all the children of this node. Does not affect 'this'. + void Clear(); + + /// One step up the DOM. + TiXmlNode* Parent() { return parent; } + const TiXmlNode* Parent() const { return parent; } + + const TiXmlNode* FirstChild() const { return firstChild; } ///< The first child of this node. Will be null if there are no children. + TiXmlNode* FirstChild() { return firstChild; } + const TiXmlNode* FirstChild( const char * value ) const; ///< The first child of this node with the matching 'value'. Will be null if none found. + /// The first child of this node with the matching 'value'. Will be null if none found. + TiXmlNode* FirstChild( const char * _value ) { + // Call through to the const version - safe since nothing is changed. Exiting syntax: cast this to a const (always safe) + // call the method, cast the return back to non-const. + return const_cast< TiXmlNode* > ((const_cast< const TiXmlNode* >(this))->FirstChild( _value )); + } + const TiXmlNode* LastChild() const { return lastChild; } /// The last child of this node. Will be null if there are no children. + TiXmlNode* LastChild() { return lastChild; } + + const TiXmlNode* LastChild( const char * value ) const; /// The last child of this node matching 'value'. Will be null if there are no children. + TiXmlNode* LastChild( const char * _value ) { + return const_cast< TiXmlNode* > ((const_cast< const TiXmlNode* >(this))->LastChild( _value )); + } + + #ifdef TIXML_USE_STL + const TiXmlNode* FirstChild( const std::string& _value ) const { return FirstChild (_value.c_str ()); } ///< STL std::string form. + TiXmlNode* FirstChild( const std::string& _value ) { return FirstChild (_value.c_str ()); } ///< STL std::string form. + const TiXmlNode* LastChild( const std::string& _value ) const { return LastChild (_value.c_str ()); } ///< STL std::string form. + TiXmlNode* LastChild( const std::string& _value ) { return LastChild (_value.c_str ()); } ///< STL std::string form. + #endif + + /** An alternate way to walk the children of a node. + One way to iterate over nodes is: + @verbatim + for( child = parent->FirstChild(); child; child = child->NextSibling() ) + @endverbatim + + IterateChildren does the same thing with the syntax: + @verbatim + child = 0; + while( child = parent->IterateChildren( child ) ) + @endverbatim + + IterateChildren takes the previous child as input and finds + the next one. If the previous child is null, it returns the + first. IterateChildren will return null when done. + */ + const TiXmlNode* IterateChildren( const TiXmlNode* previous ) const; + TiXmlNode* IterateChildren( const TiXmlNode* previous ) { + return const_cast< TiXmlNode* >( (const_cast< const TiXmlNode* >(this))->IterateChildren( previous ) ); + } + + /// This flavor of IterateChildren searches for children with a particular 'value' + const TiXmlNode* IterateChildren( const char * value, const TiXmlNode* previous ) const; + TiXmlNode* IterateChildren( const char * _value, const TiXmlNode* previous ) { + return const_cast< TiXmlNode* >( (const_cast< const TiXmlNode* >(this))->IterateChildren( _value, previous ) ); + } + + #ifdef TIXML_USE_STL + const TiXmlNode* IterateChildren( const std::string& _value, const TiXmlNode* previous ) const { return IterateChildren (_value.c_str (), previous); } ///< STL std::string form. + TiXmlNode* IterateChildren( const std::string& _value, const TiXmlNode* previous ) { return IterateChildren (_value.c_str (), previous); } ///< STL std::string form. + #endif + + /** Add a new node related to this. Adds a child past the LastChild. + Returns a pointer to the new object or NULL if an error occured. + */ + TiXmlNode* InsertEndChild( const TiXmlNode& addThis ); + + + /** Add a new node related to this. Adds a child past the LastChild. + + NOTE: the node to be added is passed by pointer, and will be + henceforth owned (and deleted) by tinyXml. This method is efficient + and avoids an extra copy, but should be used with care as it + uses a different memory model than the other insert functions. + + @sa InsertEndChild + */ + TiXmlNode* LinkEndChild( TiXmlNode* addThis ); + + /** Add a new node related to this. Adds a child before the specified child. + Returns a pointer to the new object or NULL if an error occured. + */ + TiXmlNode* InsertBeforeChild( TiXmlNode* beforeThis, const TiXmlNode& addThis ); + + /** Add a new node related to this. Adds a child after the specified child. + Returns a pointer to the new object or NULL if an error occured. + */ + TiXmlNode* InsertAfterChild( TiXmlNode* afterThis, const TiXmlNode& addThis ); + + /** Replace a child of this node. + Returns a pointer to the new object or NULL if an error occured. + */ + TiXmlNode* ReplaceChild( TiXmlNode* replaceThis, const TiXmlNode& withThis ); + + /// Delete a child of this node. + bool RemoveChild( TiXmlNode* removeThis ); + + /// Navigate to a sibling node. + const TiXmlNode* PreviousSibling() const { return prev; } + TiXmlNode* PreviousSibling() { return prev; } + + /// Navigate to a sibling node. + const TiXmlNode* PreviousSibling( const char * ) const; + TiXmlNode* PreviousSibling( const char *_prev ) { + return const_cast< TiXmlNode* >( (const_cast< const TiXmlNode* >(this))->PreviousSibling( _prev ) ); + } + + #ifdef TIXML_USE_STL + const TiXmlNode* PreviousSibling( const std::string& _value ) const { return PreviousSibling (_value.c_str ()); } ///< STL std::string form. + TiXmlNode* PreviousSibling( const std::string& _value ) { return PreviousSibling (_value.c_str ()); } ///< STL std::string form. + const TiXmlNode* NextSibling( const std::string& _value) const { return NextSibling (_value.c_str ()); } ///< STL std::string form. + TiXmlNode* NextSibling( const std::string& _value) { return NextSibling (_value.c_str ()); } ///< STL std::string form. + #endif + + /// Navigate to a sibling node. + const TiXmlNode* NextSibling() const { return next; } + TiXmlNode* NextSibling() { return next; } + + /// Navigate to a sibling node with the given 'value'. + const TiXmlNode* NextSibling( const char * ) const; + TiXmlNode* NextSibling( const char* _next ) { + return const_cast< TiXmlNode* >( (const_cast< const TiXmlNode* >(this))->NextSibling( _next ) ); + } + + /** Convenience function to get through elements. + Calls NextSibling and ToElement. Will skip all non-Element + nodes. Returns 0 if there is not another element. + */ + const TiXmlElement* NextSiblingElement() const; + TiXmlElement* NextSiblingElement() { + return const_cast< TiXmlElement* >( (const_cast< const TiXmlNode* >(this))->NextSiblingElement() ); + } + + /** Convenience function to get through elements. + Calls NextSibling and ToElement. Will skip all non-Element + nodes. Returns 0 if there is not another element. + */ + const TiXmlElement* NextSiblingElement( const char * ) const; + TiXmlElement* NextSiblingElement( const char *_next ) { + return const_cast< TiXmlElement* >( (const_cast< const TiXmlNode* >(this))->NextSiblingElement( _next ) ); + } + + #ifdef TIXML_USE_STL + const TiXmlElement* NextSiblingElement( const std::string& _value) const { return NextSiblingElement (_value.c_str ()); } ///< STL std::string form. + TiXmlElement* NextSiblingElement( const std::string& _value) { return NextSiblingElement (_value.c_str ()); } ///< STL std::string form. + #endif + + /// Convenience function to get through elements. + const TiXmlElement* FirstChildElement() const; + TiXmlElement* FirstChildElement() { + return const_cast< TiXmlElement* >( (const_cast< const TiXmlNode* >(this))->FirstChildElement() ); + } + + /// Convenience function to get through elements. + const TiXmlElement* FirstChildElement( const char * _value ) const; + TiXmlElement* FirstChildElement( const char * _value ) { + return const_cast< TiXmlElement* >( (const_cast< const TiXmlNode* >(this))->FirstChildElement( _value ) ); + } + + #ifdef TIXML_USE_STL + const TiXmlElement* FirstChildElement( const std::string& _value ) const { return FirstChildElement (_value.c_str ()); } ///< STL std::string form. + TiXmlElement* FirstChildElement( const std::string& _value ) { return FirstChildElement (_value.c_str ()); } ///< STL std::string form. + #endif + + /** Query the type (as an enumerated value, above) of this node. + The possible types are: TINYXML_DOCUMENT, TINYXML_ELEMENT, TINYXML_COMMENT, + TINYXML_UNKNOWN, TINYXML_TEXT, and TINYXML_DECLARATION. + */ + int Type() const { return type; } + + /** Return a pointer to the Document this node lives in. + Returns null if not in a document. + */ + const TiXmlDocument* GetDocument() const; + TiXmlDocument* GetDocument() { + return const_cast< TiXmlDocument* >( (const_cast< const TiXmlNode* >(this))->GetDocument() ); + } + + /// Returns true if this node has no children. + bool NoChildren() const { return !firstChild; } + + virtual const TiXmlDocument* ToDocument() const { return 0; } ///< Cast to a more defined type. Will return null if not of the requested type. + virtual const TiXmlElement* ToElement() const { return 0; } ///< Cast to a more defined type. Will return null if not of the requested type. + virtual const TiXmlComment* ToComment() const { return 0; } ///< Cast to a more defined type. Will return null if not of the requested type. + virtual const TiXmlUnknown* ToUnknown() const { return 0; } ///< Cast to a more defined type. Will return null if not of the requested type. + virtual const TiXmlText* ToText() const { return 0; } ///< Cast to a more defined type. Will return null if not of the requested type. + virtual const TiXmlDeclaration* ToDeclaration() const { return 0; } ///< Cast to a more defined type. Will return null if not of the requested type. + + virtual TiXmlDocument* ToDocument() { return 0; } ///< Cast to a more defined type. Will return null if not of the requested type. + virtual TiXmlElement* ToElement() { return 0; } ///< Cast to a more defined type. Will return null if not of the requested type. + virtual TiXmlComment* ToComment() { return 0; } ///< Cast to a more defined type. Will return null if not of the requested type. + virtual TiXmlUnknown* ToUnknown() { return 0; } ///< Cast to a more defined type. Will return null if not of the requested type. + virtual TiXmlText* ToText() { return 0; } ///< Cast to a more defined type. Will return null if not of the requested type. + virtual TiXmlDeclaration* ToDeclaration() { return 0; } ///< Cast to a more defined type. Will return null if not of the requested type. + + /** Create an exact duplicate of this node and return it. The memory must be deleted + by the caller. + */ + virtual TiXmlNode* Clone() const = 0; + + /** Accept a hierchical visit the nodes in the TinyXML DOM. Every node in the + XML tree will be conditionally visited and the host will be called back + via the TiXmlVisitor interface. + + This is essentially a SAX interface for TinyXML. (Note however it doesn't re-parse + the XML for the callbacks, so the performance of TinyXML is unchanged by using this + interface versus any other.) + + The interface has been based on ideas from: + + - http://www.saxproject.org/ + - http://c2.com/cgi/wiki?HierarchicalVisitorPattern + + Which are both good references for "visiting". + + An example of using Accept(): + @verbatim + TiXmlPrinter printer; + tinyxmlDoc.Accept( &printer ); + const char* xmlcstr = printer.CStr(); + @endverbatim + */ + virtual bool Accept( TiXmlVisitor* visitor ) const = 0; + +protected: + TiXmlNode( NodeType _type ); + + // Copy to the allocated object. Shared functionality between Clone, Copy constructor, + // and the assignment operator. + void CopyTo( TiXmlNode* target ) const; + + #ifdef TIXML_USE_STL + // The real work of the input operator. + virtual void StreamIn( std::istream* in, TIXML_STRING* tag ) = 0; + #endif + + // Figure out what is at *p, and parse it. Returns null if it is not an xml node. + TiXmlNode* Identify( const char* start, TiXmlEncoding encoding ); + + TiXmlNode* parent; + NodeType type; + + TiXmlNode* firstChild; + TiXmlNode* lastChild; + + TIXML_STRING value; + + TiXmlNode* prev; + TiXmlNode* next; + +private: + TiXmlNode( const TiXmlNode& ); // not implemented. + void operator=( const TiXmlNode& base ); // not allowed. +}; + + +/** An attribute is a name-value pair. Elements have an arbitrary + number of attributes, each with a unique name. + + @note The attributes are not TiXmlNodes, since they are not + part of the tinyXML document object model. There are other + suggested ways to look at this problem. +*/ +class TiXmlAttribute : public TiXmlBase +{ + friend class TiXmlAttributeSet; + +public: + /// Construct an empty attribute. + TiXmlAttribute() : TiXmlBase() + { + document = 0; + prev = next = 0; + } + + #ifdef TIXML_USE_STL + /// std::string constructor. + TiXmlAttribute( const std::string& _name, const std::string& _value ) + { + name = _name; + value = _value; + document = 0; + prev = next = 0; + } + #endif + + /// Construct an attribute with a name and value. + TiXmlAttribute( const char * _name, const char * _value ) + { + name = _name; + value = _value; + document = 0; + prev = next = 0; + } + + const char* Name() const { return name.c_str(); } ///< Return the name of this attribute. + const char* Value() const { return value.c_str(); } ///< Return the value of this attribute. + #ifdef TIXML_USE_STL + const std::string& ValueStr() const { return value; } ///< Return the value of this attribute. + #endif + int IntValue() const; ///< Return the value of this attribute, converted to an integer. + double DoubleValue() const; ///< Return the value of this attribute, converted to a double. + + // Get the tinyxml string representation + const TIXML_STRING& NameTStr() const { return name; } + + /** QueryIntValue examines the value string. It is an alternative to the + IntValue() method with richer error checking. + If the value is an integer, it is stored in 'value' and + the call returns TIXML_SUCCESS. If it is not + an integer, it returns TIXML_WRONG_TYPE. + + A specialized but useful call. Note that for success it returns 0, + which is the opposite of almost all other TinyXml calls. + */ + int QueryIntValue( int* _value ) const; + /// QueryDoubleValue examines the value string. See QueryIntValue(). + int QueryDoubleValue( double* _value ) const; + + void SetName( const char* _name ) { name = _name; } ///< Set the name of this attribute. + void SetValue( const char* _value ) { value = _value; } ///< Set the value. + + void SetIntValue( int _value ); ///< Set the value from an integer. + void SetDoubleValue( double _value ); ///< Set the value from a double. + + #ifdef TIXML_USE_STL + /// STL std::string form. + void SetName( const std::string& _name ) { name = _name; } + /// STL std::string form. + void SetValue( const std::string& _value ) { value = _value; } + #endif + + /// Get the next sibling attribute in the DOM. Returns null at end. + const TiXmlAttribute* Next() const; + TiXmlAttribute* Next() { + return const_cast< TiXmlAttribute* >( (const_cast< const TiXmlAttribute* >(this))->Next() ); + } + + /// Get the previous sibling attribute in the DOM. Returns null at beginning. + const TiXmlAttribute* Previous() const; + TiXmlAttribute* Previous() { + return const_cast< TiXmlAttribute* >( (const_cast< const TiXmlAttribute* >(this))->Previous() ); + } + + bool operator==( const TiXmlAttribute& rhs ) const { return rhs.name == name; } + bool operator<( const TiXmlAttribute& rhs ) const { return name < rhs.name; } + bool operator>( const TiXmlAttribute& rhs ) const { return name > rhs.name; } + + /* Attribute parsing starts: first letter of the name + returns: the next char after the value end quote + */ + virtual const char* Parse( const char* p, TiXmlParsingData* data, TiXmlEncoding encoding ); + + // Prints this Attribute to a FILE stream. + virtual void Print( FILE* cfile, int depth ) const { + Print( cfile, depth, 0 ); + } + void Print( FILE* cfile, int depth, TIXML_STRING* str ) const; + + // [internal use] + // Set the document pointer so the attribute can report errors. + void SetDocument( TiXmlDocument* doc ) { document = doc; } + +private: + TiXmlAttribute( const TiXmlAttribute& ); // not implemented. + void operator=( const TiXmlAttribute& base ); // not allowed. + + TiXmlDocument* document; // A pointer back to a document, for error reporting. + TIXML_STRING name; + TIXML_STRING value; + TiXmlAttribute* prev; + TiXmlAttribute* next; +}; + + +/* A class used to manage a group of attributes. + It is only used internally, both by the ELEMENT and the DECLARATION. + + The set can be changed transparent to the Element and Declaration + classes that use it, but NOT transparent to the Attribute + which has to implement a next() and previous() method. Which makes + it a bit problematic and prevents the use of STL. + + This version is implemented with circular lists because: + - I like circular lists + - it demonstrates some independence from the (typical) doubly linked list. +*/ +class TiXmlAttributeSet +{ +public: + TiXmlAttributeSet(); + ~TiXmlAttributeSet(); + + void Add( TiXmlAttribute* attribute ); + void Remove( TiXmlAttribute* attribute ); + + const TiXmlAttribute* First() const { return ( sentinel.next == &sentinel ) ? 0 : sentinel.next; } + TiXmlAttribute* First() { return ( sentinel.next == &sentinel ) ? 0 : sentinel.next; } + const TiXmlAttribute* Last() const { return ( sentinel.prev == &sentinel ) ? 0 : sentinel.prev; } + TiXmlAttribute* Last() { return ( sentinel.prev == &sentinel ) ? 0 : sentinel.prev; } + + TiXmlAttribute* Find( const char* _name ) const; + TiXmlAttribute* FindOrCreate( const char* _name ); + +# ifdef TIXML_USE_STL + TiXmlAttribute* Find( const std::string& _name ) const; + TiXmlAttribute* FindOrCreate( const std::string& _name ); +# endif + + +private: + //*ME: Because of hidden/disabled copy-construktor in TiXmlAttribute (sentinel-element), + //*ME: this class must be also use a hidden/disabled copy-constructor !!! + TiXmlAttributeSet( const TiXmlAttributeSet& ); // not allowed + void operator=( const TiXmlAttributeSet& ); // not allowed (as TiXmlAttribute) + + TiXmlAttribute sentinel; +}; + + +/** The element is a container class. It has a value, the element name, + and can contain other elements, text, comments, and unknowns. + Elements also contain an arbitrary number of attributes. +*/ +class TiXmlElement : public TiXmlNode +{ +public: + /// Construct an element. + TiXmlElement (const char * in_value); + + #ifdef TIXML_USE_STL + /// std::string constructor. + TiXmlElement( const std::string& _value ); + #endif + + TiXmlElement( const TiXmlElement& ); + + TiXmlElement& operator=( const TiXmlElement& base ); + + virtual ~TiXmlElement(); + + /** Given an attribute name, Attribute() returns the value + for the attribute of that name, or null if none exists. + */ + const char* Attribute( const char* name ) const; + + /** Given an attribute name, Attribute() returns the value + for the attribute of that name, or null if none exists. + If the attribute exists and can be converted to an integer, + the integer value will be put in the return 'i', if 'i' + is non-null. + */ + const char* Attribute( const char* name, int* i ) const; + + /** Given an attribute name, Attribute() returns the value + for the attribute of that name, or null if none exists. + If the attribute exists and can be converted to an double, + the double value will be put in the return 'd', if 'd' + is non-null. + */ + const char* Attribute( const char* name, double* d ) const; + + /** QueryIntAttribute examines the attribute - it is an alternative to the + Attribute() method with richer error checking. + If the attribute is an integer, it is stored in 'value' and + the call returns TIXML_SUCCESS. If it is not + an integer, it returns TIXML_WRONG_TYPE. If the attribute + does not exist, then TIXML_NO_ATTRIBUTE is returned. + */ + int QueryIntAttribute( const char* name, int* _value ) const; + /// QueryUnsignedAttribute examines the attribute - see QueryIntAttribute(). + int QueryUnsignedAttribute( const char* name, unsigned* _value ) const; + /** QueryBoolAttribute examines the attribute - see QueryIntAttribute(). + Note that '1', 'true', or 'yes' are considered true, while '0', 'false' + and 'no' are considered false. + */ + int QueryBoolAttribute( const char* name, bool* _value ) const; + /// QueryDoubleAttribute examines the attribute - see QueryIntAttribute(). + int QueryDoubleAttribute( const char* name, double* _value ) const; + /// QueryFloatAttribute examines the attribute - see QueryIntAttribute(). + int QueryFloatAttribute( const char* name, float* _value ) const { + double d; + int result = QueryDoubleAttribute( name, &d ); + if ( result == TIXML_SUCCESS ) { + *_value = (float)d; + } + return result; + } + + #ifdef TIXML_USE_STL + /// QueryStringAttribute examines the attribute - see QueryIntAttribute(). + int QueryStringAttribute( const char* name, std::string* _value ) const { + const char* cstr = Attribute( name ); + if ( cstr ) { + *_value = std::string( cstr ); + return TIXML_SUCCESS; + } + return TIXML_NO_ATTRIBUTE; + } + + /** Template form of the attribute query which will try to read the + attribute into the specified type. Very easy, very powerful, but + be careful to make sure to call this with the correct type. + + NOTE: This method doesn't work correctly for 'string' types that contain spaces. + + @return TIXML_SUCCESS, TIXML_WRONG_TYPE, or TIXML_NO_ATTRIBUTE + */ + template< typename T > int QueryValueAttribute( const std::string& name, T* outValue ) const + { + const TiXmlAttribute* node = attributeSet.Find( name ); + if ( !node ) + return TIXML_NO_ATTRIBUTE; + + std::stringstream sstream( node->ValueStr() ); + sstream >> *outValue; + if ( !sstream.fail() ) + return TIXML_SUCCESS; + return TIXML_WRONG_TYPE; + } + + int QueryValueAttribute( const std::string& name, std::string* outValue ) const + { + const TiXmlAttribute* node = attributeSet.Find( name ); + if ( !node ) + return TIXML_NO_ATTRIBUTE; + *outValue = node->ValueStr(); + return TIXML_SUCCESS; + } + #endif + + /** Sets an attribute of name to a given value. The attribute + will be created if it does not exist, or changed if it does. + */ + void SetAttribute( const char* name, const char * _value ); + + #ifdef TIXML_USE_STL + const std::string* Attribute( const std::string& name ) const; + const std::string* Attribute( const std::string& name, int* i ) const; + const std::string* Attribute( const std::string& name, double* d ) const; + int QueryIntAttribute( const std::string& name, int* _value ) const; + int QueryDoubleAttribute( const std::string& name, double* _value ) const; + + /// STL std::string form. + void SetAttribute( const std::string& name, const std::string& _value ); + ///< STL std::string form. + void SetAttribute( const std::string& name, int _value ); + ///< STL std::string form. + void SetDoubleAttribute( const std::string& name, double value ); + #endif + + /** Sets an attribute of name to a given value. The attribute + will be created if it does not exist, or changed if it does. + */ + void SetAttribute( const char * name, int value ); + + /** Sets an attribute of name to a given value. The attribute + will be created if it does not exist, or changed if it does. + */ + void SetDoubleAttribute( const char * name, double value ); + + /** Deletes an attribute with the given name. + */ + void RemoveAttribute( const char * name ); + #ifdef TIXML_USE_STL + void RemoveAttribute( const std::string& name ) { RemoveAttribute (name.c_str ()); } ///< STL std::string form. + #endif + + const TiXmlAttribute* FirstAttribute() const { return attributeSet.First(); } ///< Access the first attribute in this element. + TiXmlAttribute* FirstAttribute() { return attributeSet.First(); } + const TiXmlAttribute* LastAttribute() const { return attributeSet.Last(); } ///< Access the last attribute in this element. + TiXmlAttribute* LastAttribute() { return attributeSet.Last(); } + + /** Convenience function for easy access to the text inside an element. Although easy + and concise, GetText() is limited compared to getting the TiXmlText child + and accessing it directly. + + If the first child of 'this' is a TiXmlText, the GetText() + returns the character string of the Text node, else null is returned. + + This is a convenient method for getting the text of simple contained text: + @verbatim + This is text + const char* str = fooElement->GetText(); + @endverbatim + + 'str' will be a pointer to "This is text". + + Note that this function can be misleading. If the element foo was created from + this XML: + @verbatim + This is text + @endverbatim + + then the value of str would be null. The first child node isn't a text node, it is + another element. From this XML: + @verbatim + This is text + @endverbatim + GetText() will return "This is ". + + WARNING: GetText() accesses a child node - don't become confused with the + similarly named TiXmlHandle::Text() and TiXmlNode::ToText() which are + safe type casts on the referenced node. + */ + const char* GetText() const; + + /// Creates a new Element and returns it - the returned element is a copy. + virtual TiXmlNode* Clone() const; + // Print the Element to a FILE stream. + virtual void Print( FILE* cfile, int depth ) const; + + /* Attribtue parsing starts: next char past '<' + returns: next char past '>' + */ + virtual const char* Parse( const char* p, TiXmlParsingData* data, TiXmlEncoding encoding ); + + virtual const TiXmlElement* ToElement() const { return this; } ///< Cast to a more defined type. Will return null not of the requested type. + virtual TiXmlElement* ToElement() { return this; } ///< Cast to a more defined type. Will return null not of the requested type. + + /** Walk the XML tree visiting this node and all of its children. + */ + virtual bool Accept( TiXmlVisitor* visitor ) const; + +protected: + + void CopyTo( TiXmlElement* target ) const; + void ClearThis(); // like clear, but initializes 'this' object as well + + // Used to be public [internal use] + #ifdef TIXML_USE_STL + virtual void StreamIn( std::istream * in, TIXML_STRING * tag ); + #endif + /* [internal use] + Reads the "value" of the element -- another element, or text. + This should terminate with the current end tag. + */ + const char* ReadValue( const char* in, TiXmlParsingData* prevData, TiXmlEncoding encoding ); + +private: + TiXmlAttributeSet attributeSet; +}; + + +/** An XML comment. +*/ +class TiXmlComment : public TiXmlNode +{ +public: + /// Constructs an empty comment. + TiXmlComment() : TiXmlNode( TiXmlNode::TINYXML_COMMENT ) {} + /// Construct a comment from text. + TiXmlComment( const char* _value ) : TiXmlNode( TiXmlNode::TINYXML_COMMENT ) { + SetValue( _value ); + } + TiXmlComment( const TiXmlComment& ); + TiXmlComment& operator=( const TiXmlComment& base ); + + virtual ~TiXmlComment() {} + + /// Returns a copy of this Comment. + virtual TiXmlNode* Clone() const; + // Write this Comment to a FILE stream. + virtual void Print( FILE* cfile, int depth ) const; + + /* Attribtue parsing starts: at the ! of the !-- + returns: next char past '>' + */ + virtual const char* Parse( const char* p, TiXmlParsingData* data, TiXmlEncoding encoding ); + + virtual const TiXmlComment* ToComment() const { return this; } ///< Cast to a more defined type. Will return null not of the requested type. + virtual TiXmlComment* ToComment() { return this; } ///< Cast to a more defined type. Will return null not of the requested type. + + /** Walk the XML tree visiting this node and all of its children. + */ + virtual bool Accept( TiXmlVisitor* visitor ) const; + +protected: + void CopyTo( TiXmlComment* target ) const; + + // used to be public + #ifdef TIXML_USE_STL + virtual void StreamIn( std::istream * in, TIXML_STRING * tag ); + #endif +// virtual void StreamOut( TIXML_OSTREAM * out ) const; + +private: + +}; + + +/** XML text. A text node can have 2 ways to output the next. "normal" output + and CDATA. It will default to the mode it was parsed from the XML file and + you generally want to leave it alone, but you can change the output mode with + SetCDATA() and query it with CDATA(). +*/ +class TiXmlText : public TiXmlNode +{ + friend class TiXmlElement; +public: + /** Constructor for text element. By default, it is treated as + normal, encoded text. If you want it be output as a CDATA text + element, set the parameter _cdata to 'true' + */ + TiXmlText (const char * initValue ) : TiXmlNode (TiXmlNode::TINYXML_TEXT) + { + SetValue( initValue ); + cdata = false; + } + virtual ~TiXmlText() {} + + #ifdef TIXML_USE_STL + /// Constructor. + TiXmlText( const std::string& initValue ) : TiXmlNode (TiXmlNode::TINYXML_TEXT) + { + SetValue( initValue ); + cdata = false; + } + #endif + + TiXmlText( const TiXmlText& copy ) : TiXmlNode( TiXmlNode::TINYXML_TEXT ) { copy.CopyTo( this ); } + TiXmlText& operator=( const TiXmlText& base ) { base.CopyTo( this ); return *this; } + + // Write this text object to a FILE stream. + virtual void Print( FILE* cfile, int depth ) const; + + /// Queries whether this represents text using a CDATA section. + bool CDATA() const { return cdata; } + /// Turns on or off a CDATA representation of text. + void SetCDATA( bool _cdata ) { cdata = _cdata; } + + virtual const char* Parse( const char* p, TiXmlParsingData* data, TiXmlEncoding encoding ); + + virtual const TiXmlText* ToText() const { return this; } ///< Cast to a more defined type. Will return null not of the requested type. + virtual TiXmlText* ToText() { return this; } ///< Cast to a more defined type. Will return null not of the requested type. + + /** Walk the XML tree visiting this node and all of its children. + */ + virtual bool Accept( TiXmlVisitor* content ) const; + +protected : + /// [internal use] Creates a new Element and returns it. + virtual TiXmlNode* Clone() const; + void CopyTo( TiXmlText* target ) const; + + bool Blank() const; // returns true if all white space and new lines + // [internal use] + #ifdef TIXML_USE_STL + virtual void StreamIn( std::istream * in, TIXML_STRING * tag ); + #endif + +private: + bool cdata; // true if this should be input and output as a CDATA style text element +}; + + +/** In correct XML the declaration is the first entry in the file. + @verbatim + + @endverbatim + + TinyXml will happily read or write files without a declaration, + however. There are 3 possible attributes to the declaration: + version, encoding, and standalone. + + Note: In this version of the code, the attributes are + handled as special cases, not generic attributes, simply + because there can only be at most 3 and they are always the same. +*/ +class TiXmlDeclaration : public TiXmlNode +{ +public: + /// Construct an empty declaration. + TiXmlDeclaration() : TiXmlNode( TiXmlNode::TINYXML_DECLARATION ) {} + +#ifdef TIXML_USE_STL + /// Constructor. + TiXmlDeclaration( const std::string& _version, + const std::string& _encoding, + const std::string& _standalone ); +#endif + + /// Construct. + TiXmlDeclaration( const char* _version, + const char* _encoding, + const char* _standalone ); + + TiXmlDeclaration( const TiXmlDeclaration& copy ); + TiXmlDeclaration& operator=( const TiXmlDeclaration& copy ); + + virtual ~TiXmlDeclaration() {} + + /// Version. Will return an empty string if none was found. + const char *Version() const { return version.c_str (); } + /// Encoding. Will return an empty string if none was found. + const char *Encoding() const { return encoding.c_str (); } + /// Is this a standalone document? + const char *Standalone() const { return standalone.c_str (); } + + /// Creates a copy of this Declaration and returns it. + virtual TiXmlNode* Clone() const; + // Print this declaration to a FILE stream. + virtual void Print( FILE* cfile, int depth, TIXML_STRING* str ) const; + virtual void Print( FILE* cfile, int depth ) const { + Print( cfile, depth, 0 ); + } + + virtual const char* Parse( const char* p, TiXmlParsingData* data, TiXmlEncoding encoding ); + + virtual const TiXmlDeclaration* ToDeclaration() const { return this; } ///< Cast to a more defined type. Will return null not of the requested type. + virtual TiXmlDeclaration* ToDeclaration() { return this; } ///< Cast to a more defined type. Will return null not of the requested type. + + /** Walk the XML tree visiting this node and all of its children. + */ + virtual bool Accept( TiXmlVisitor* visitor ) const; + +protected: + void CopyTo( TiXmlDeclaration* target ) const; + // used to be public + #ifdef TIXML_USE_STL + virtual void StreamIn( std::istream * in, TIXML_STRING * tag ); + #endif + +private: + + TIXML_STRING version; + TIXML_STRING encoding; + TIXML_STRING standalone; +}; + + +/** Any tag that tinyXml doesn't recognize is saved as an + unknown. It is a tag of text, but should not be modified. + It will be written back to the XML, unchanged, when the file + is saved. + + DTD tags get thrown into TiXmlUnknowns. +*/ +class TiXmlUnknown : public TiXmlNode +{ +public: + TiXmlUnknown() : TiXmlNode( TiXmlNode::TINYXML_UNKNOWN ) {} + virtual ~TiXmlUnknown() {} + + TiXmlUnknown( const TiXmlUnknown& copy ) : TiXmlNode( TiXmlNode::TINYXML_UNKNOWN ) { copy.CopyTo( this ); } + TiXmlUnknown& operator=( const TiXmlUnknown& copy ) { copy.CopyTo( this ); return *this; } + + /// Creates a copy of this Unknown and returns it. + virtual TiXmlNode* Clone() const; + // Print this Unknown to a FILE stream. + virtual void Print( FILE* cfile, int depth ) const; + + virtual const char* Parse( const char* p, TiXmlParsingData* data, TiXmlEncoding encoding ); + + virtual const TiXmlUnknown* ToUnknown() const { return this; } ///< Cast to a more defined type. Will return null not of the requested type. + virtual TiXmlUnknown* ToUnknown() { return this; } ///< Cast to a more defined type. Will return null not of the requested type. + + /** Walk the XML tree visiting this node and all of its children. + */ + virtual bool Accept( TiXmlVisitor* content ) const; + +protected: + void CopyTo( TiXmlUnknown* target ) const; + + #ifdef TIXML_USE_STL + virtual void StreamIn( std::istream * in, TIXML_STRING * tag ); + #endif + +private: + +}; + + +/** Always the top level node. A document binds together all the + XML pieces. It can be saved, loaded, and printed to the screen. + The 'value' of a document node is the xml file name. +*/ +class TiXmlDocument : public TiXmlNode +{ +public: + /// Create an empty document, that has no name. + TiXmlDocument(); + /// Create a document with a name. The name of the document is also the filename of the xml. + TiXmlDocument( const char * documentName ); + + #ifdef TIXML_USE_STL + /// Constructor. + TiXmlDocument( const std::string& documentName ); + #endif + + TiXmlDocument( const TiXmlDocument& copy ); + TiXmlDocument& operator=( const TiXmlDocument& copy ); + + virtual ~TiXmlDocument() {} + + /** Load a file using the current document value. + Returns true if successful. Will delete any existing + document data before loading. + */ + bool LoadFile( TiXmlEncoding encoding = TIXML_DEFAULT_ENCODING ); + /// Save a file using the current document value. Returns true if successful. + bool SaveFile() const; + /// Load a file using the given filename. Returns true if successful. + bool LoadFile( const char * filename, TiXmlEncoding encoding = TIXML_DEFAULT_ENCODING ); + /// Save a file using the given filename. Returns true if successful. + bool SaveFile( const char * filename ) const; + /** Load a file using the given FILE*. Returns true if successful. Note that this method + doesn't stream - the entire object pointed at by the FILE* + will be interpreted as an XML file. TinyXML doesn't stream in XML from the current + file location. Streaming may be added in the future. + */ + bool LoadFile( FILE*, TiXmlEncoding encoding = TIXML_DEFAULT_ENCODING ); + /// Save a file using the given FILE*. Returns true if successful. + bool SaveFile( FILE* ) const; + + #ifdef TIXML_USE_STL + bool LoadFile( const std::string& filename, TiXmlEncoding encoding = TIXML_DEFAULT_ENCODING ) ///< STL std::string version. + { + return LoadFile( filename.c_str(), encoding ); + } + bool SaveFile( const std::string& filename ) const ///< STL std::string version. + { + return SaveFile( filename.c_str() ); + } + #endif + + /** Parse the given null terminated block of xml data. Passing in an encoding to this + method (either TIXML_ENCODING_LEGACY or TIXML_ENCODING_UTF8 will force TinyXml + to use that encoding, regardless of what TinyXml might otherwise try to detect. + */ + virtual const char* Parse( const char* p, TiXmlParsingData* data = 0, TiXmlEncoding encoding = TIXML_DEFAULT_ENCODING ); + + /** Get the root element -- the only top level element -- of the document. + In well formed XML, there should only be one. TinyXml is tolerant of + multiple elements at the document level. + */ + const TiXmlElement* RootElement() const { return FirstChildElement(); } + TiXmlElement* RootElement() { return FirstChildElement(); } + + /** If an error occurs, Error will be set to true. Also, + - The ErrorId() will contain the integer identifier of the error (not generally useful) + - The ErrorDesc() method will return the name of the error. (very useful) + - The ErrorRow() and ErrorCol() will return the location of the error (if known) + */ + bool Error() const { return error; } + + /// Contains a textual (english) description of the error if one occurs. + const char * ErrorDesc() const { return errorDesc.c_str (); } + + /** Generally, you probably want the error string ( ErrorDesc() ). But if you + prefer the ErrorId, this function will fetch it. + */ + int ErrorId() const { return errorId; } + + /** Returns the location (if known) of the error. The first column is column 1, + and the first row is row 1. A value of 0 means the row and column wasn't applicable + (memory errors, for example, have no row/column) or the parser lost the error. (An + error in the error reporting, in that case.) + + @sa SetTabSize, Row, Column + */ + int ErrorRow() const { return errorLocation.row+1; } + int ErrorCol() const { return errorLocation.col+1; } ///< The column where the error occured. See ErrorRow() + + /** SetTabSize() allows the error reporting functions (ErrorRow() and ErrorCol()) + to report the correct values for row and column. It does not change the output + or input in any way. + + By calling this method, with a tab size + greater than 0, the row and column of each node and attribute is stored + when the file is loaded. Very useful for tracking the DOM back in to + the source file. + + The tab size is required for calculating the location of nodes. If not + set, the default of 4 is used. The tabsize is set per document. Setting + the tabsize to 0 disables row/column tracking. + + Note that row and column tracking is not supported when using operator>>. + + The tab size needs to be enabled before the parse or load. Correct usage: + @verbatim + TiXmlDocument doc; + doc.SetTabSize( 8 ); + doc.Load( "myfile.xml" ); + @endverbatim + + @sa Row, Column + */ + void SetTabSize( int _tabsize ) { tabsize = _tabsize; } + + int TabSize() const { return tabsize; } + + /** If you have handled the error, it can be reset with this call. The error + state is automatically cleared if you Parse a new XML block. + */ + void ClearError() { error = false; + errorId = 0; + errorDesc = ""; + errorLocation.row = errorLocation.col = 0; + //errorLocation.last = 0; + } + + /** Write the document to standard out using formatted printing ("pretty print"). */ + void Print() const { Print( stdout, 0 ); } + + /* Write the document to a string using formatted printing ("pretty print"). This + will allocate a character array (new char[]) and return it as a pointer. The + calling code pust call delete[] on the return char* to avoid a memory leak. + */ + //char* PrintToMemory() const; + + /// Print this Document to a FILE stream. + virtual void Print( FILE* cfile, int depth = 0 ) const; + // [internal use] + void SetError( int err, const char* errorLocation, TiXmlParsingData* prevData, TiXmlEncoding encoding ); + + virtual const TiXmlDocument* ToDocument() const { return this; } ///< Cast to a more defined type. Will return null not of the requested type. + virtual TiXmlDocument* ToDocument() { return this; } ///< Cast to a more defined type. Will return null not of the requested type. + + /** Walk the XML tree visiting this node and all of its children. + */ + virtual bool Accept( TiXmlVisitor* content ) const; + +protected : + // [internal use] + virtual TiXmlNode* Clone() const; + #ifdef TIXML_USE_STL + virtual void StreamIn( std::istream * in, TIXML_STRING * tag ); + #endif + +private: + void CopyTo( TiXmlDocument* target ) const; + + bool error; + int errorId; + TIXML_STRING errorDesc; + int tabsize; + TiXmlCursor errorLocation; + bool useMicrosoftBOM; // the UTF-8 BOM were found when read. Note this, and try to write. +}; + + +/** + A TiXmlHandle is a class that wraps a node pointer with null checks; this is + an incredibly useful thing. Note that TiXmlHandle is not part of the TinyXml + DOM structure. It is a separate utility class. + + Take an example: + @verbatim + + + + + + + @endverbatim + + Assuming you want the value of "attributeB" in the 2nd "Child" element, it's very + easy to write a *lot* of code that looks like: + + @verbatim + TiXmlElement* root = document.FirstChildElement( "Document" ); + if ( root ) + { + TiXmlElement* element = root->FirstChildElement( "Element" ); + if ( element ) + { + TiXmlElement* child = element->FirstChildElement( "Child" ); + if ( child ) + { + TiXmlElement* child2 = child->NextSiblingElement( "Child" ); + if ( child2 ) + { + // Finally do something useful. + @endverbatim + + And that doesn't even cover "else" cases. TiXmlHandle addresses the verbosity + of such code. A TiXmlHandle checks for null pointers so it is perfectly safe + and correct to use: + + @verbatim + TiXmlHandle docHandle( &document ); + TiXmlElement* child2 = docHandle.FirstChild( "Document" ).FirstChild( "Element" ).Child( "Child", 1 ).ToElement(); + if ( child2 ) + { + // do something useful + @endverbatim + + Which is MUCH more concise and useful. + + It is also safe to copy handles - internally they are nothing more than node pointers. + @verbatim + TiXmlHandle handleCopy = handle; + @endverbatim + + What they should not be used for is iteration: + + @verbatim + int i=0; + while ( true ) + { + TiXmlElement* child = docHandle.FirstChild( "Document" ).FirstChild( "Element" ).Child( "Child", i ).ToElement(); + if ( !child ) + break; + // do something + ++i; + } + @endverbatim + + It seems reasonable, but it is in fact two embedded while loops. The Child method is + a linear walk to find the element, so this code would iterate much more than it needs + to. Instead, prefer: + + @verbatim + TiXmlElement* child = docHandle.FirstChild( "Document" ).FirstChild( "Element" ).FirstChild( "Child" ).ToElement(); + + for( child; child; child=child->NextSiblingElement() ) + { + // do something + } + @endverbatim +*/ +class TiXmlHandle +{ +public: + /// Create a handle from any node (at any depth of the tree.) This can be a null pointer. + TiXmlHandle( TiXmlNode* _node ) { this->node = _node; } + /// Copy constructor + TiXmlHandle( const TiXmlHandle& ref ) { this->node = ref.node; } + TiXmlHandle operator=( const TiXmlHandle& ref ) { if ( &ref != this ) this->node = ref.node; return *this; } + + /// Return a handle to the first child node. + TiXmlHandle FirstChild() const; + /// Return a handle to the first child node with the given name. + TiXmlHandle FirstChild( const char * value ) const; + /// Return a handle to the first child element. + TiXmlHandle FirstChildElement() const; + /// Return a handle to the first child element with the given name. + TiXmlHandle FirstChildElement( const char * value ) const; + + /** Return a handle to the "index" child with the given name. + The first child is 0, the second 1, etc. + */ + TiXmlHandle Child( const char* value, int index ) const; + /** Return a handle to the "index" child. + The first child is 0, the second 1, etc. + */ + TiXmlHandle Child( int index ) const; + /** Return a handle to the "index" child element with the given name. + The first child element is 0, the second 1, etc. Note that only TiXmlElements + are indexed: other types are not counted. + */ + TiXmlHandle ChildElement( const char* value, int index ) const; + /** Return a handle to the "index" child element. + The first child element is 0, the second 1, etc. Note that only TiXmlElements + are indexed: other types are not counted. + */ + TiXmlHandle ChildElement( int index ) const; + + #ifdef TIXML_USE_STL + TiXmlHandle FirstChild( const std::string& _value ) const { return FirstChild( _value.c_str() ); } + TiXmlHandle FirstChildElement( const std::string& _value ) const { return FirstChildElement( _value.c_str() ); } + + TiXmlHandle Child( const std::string& _value, int index ) const { return Child( _value.c_str(), index ); } + TiXmlHandle ChildElement( const std::string& _value, int index ) const { return ChildElement( _value.c_str(), index ); } + #endif + + /** Return the handle as a TiXmlNode. This may return null. + */ + TiXmlNode* ToNode() const { return node; } + /** Return the handle as a TiXmlElement. This may return null. + */ + TiXmlElement* ToElement() const { return ( ( node && node->ToElement() ) ? node->ToElement() : 0 ); } + /** Return the handle as a TiXmlText. This may return null. + */ + TiXmlText* ToText() const { return ( ( node && node->ToText() ) ? node->ToText() : 0 ); } + /** Return the handle as a TiXmlUnknown. This may return null. + */ + TiXmlUnknown* ToUnknown() const { return ( ( node && node->ToUnknown() ) ? node->ToUnknown() : 0 ); } + + /** @deprecated use ToNode. + Return the handle as a TiXmlNode. This may return null. + */ + TiXmlNode* Node() const { return ToNode(); } + /** @deprecated use ToElement. + Return the handle as a TiXmlElement. This may return null. + */ + TiXmlElement* Element() const { return ToElement(); } + /** @deprecated use ToText() + Return the handle as a TiXmlText. This may return null. + */ + TiXmlText* Text() const { return ToText(); } + /** @deprecated use ToUnknown() + Return the handle as a TiXmlUnknown. This may return null. + */ + TiXmlUnknown* Unknown() const { return ToUnknown(); } + +private: + TiXmlNode* node; +}; + + +/** Print to memory functionality. The TiXmlPrinter is useful when you need to: + + -# Print to memory (especially in non-STL mode) + -# Control formatting (line endings, etc.) + + When constructed, the TiXmlPrinter is in its default "pretty printing" mode. + Before calling Accept() you can call methods to control the printing + of the XML document. After TiXmlNode::Accept() is called, the printed document can + be accessed via the CStr(), Str(), and Size() methods. + + TiXmlPrinter uses the Visitor API. + @verbatim + TiXmlPrinter printer; + printer.SetIndent( "\t" ); + + doc.Accept( &printer ); + fprintf( stdout, "%s", printer.CStr() ); + @endverbatim +*/ +class TiXmlPrinter : public TiXmlVisitor +{ +public: + TiXmlPrinter() : depth( 0 ), simpleTextPrint( false ), + buffer(), indent( " " ), lineBreak( "\n" ) {} + + virtual bool VisitEnter( const TiXmlDocument& doc ); + virtual bool VisitExit( const TiXmlDocument& doc ); + + virtual bool VisitEnter( const TiXmlElement& element, const TiXmlAttribute* firstAttribute ); + virtual bool VisitExit( const TiXmlElement& element ); + + virtual bool Visit( const TiXmlDeclaration& declaration ); + virtual bool Visit( const TiXmlText& text ); + virtual bool Visit( const TiXmlComment& comment ); + virtual bool Visit( const TiXmlUnknown& unknown ); + + /** Set the indent characters for printing. By default 4 spaces + but tab (\t) is also useful, or null/empty string for no indentation. + */ + void SetIndent( const char* _indent ) { indent = _indent ? _indent : "" ; } + /// Query the indention string. + const char* Indent() { return indent.c_str(); } + /** Set the line breaking string. By default set to newline (\n). + Some operating systems prefer other characters, or can be + set to the null/empty string for no indenation. + */ + void SetLineBreak( const char* _lineBreak ) { lineBreak = _lineBreak ? _lineBreak : ""; } + /// Query the current line breaking string. + const char* LineBreak() { return lineBreak.c_str(); } + + /** Switch over to "stream printing" which is the most dense formatting without + linebreaks. Common when the XML is needed for network transmission. + */ + void SetStreamPrinting() { indent = ""; + lineBreak = ""; + } + /// Return the result. + const char* CStr() { return buffer.c_str(); } + /// Return the length of the result string. + size_t Size() { return buffer.size(); } + + #ifdef TIXML_USE_STL + /// Return the result. + const std::string& Str() { return buffer; } + #endif + +private: + void DoIndent() { + for( int i=0; i +#include + +#include "tinyxml.h" + +//#define DEBUG_PARSER +#if defined( DEBUG_PARSER ) +# if defined( DEBUG ) && defined( _MSC_VER ) +# include +# define TIXML_LOG OutputDebugString +# else +# define TIXML_LOG printf +# endif +#endif + +// Note tha "PutString" hardcodes the same list. This +// is less flexible than it appears. Changing the entries +// or order will break putstring. +TiXmlBase::Entity TiXmlBase::entity[ TiXmlBase::NUM_ENTITY ] = +{ + { "&", 5, '&' }, + { "<", 4, '<' }, + { ">", 4, '>' }, + { """, 6, '\"' }, + { "'", 6, '\'' } +}; + +// Bunch of unicode info at: +// http://www.unicode.org/faq/utf_bom.html +// Including the basic of this table, which determines the #bytes in the +// sequence from the lead byte. 1 placed for invalid sequences -- +// although the result will be junk, pass it through as much as possible. +// Beware of the non-characters in UTF-8: +// ef bb bf (Microsoft "lead bytes") +// ef bf be +// ef bf bf + +const unsigned char TIXML_UTF_LEAD_0 = 0xefU; +const unsigned char TIXML_UTF_LEAD_1 = 0xbbU; +const unsigned char TIXML_UTF_LEAD_2 = 0xbfU; + +const int TiXmlBase::utf8ByteTable[256] = +{ + // 0 1 2 3 4 5 6 7 8 9 a b c d e f + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x00 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x10 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x20 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x30 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x40 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x50 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x60 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x70 End of ASCII range + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x80 0x80 to 0xc1 invalid + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x90 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0xa0 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0xb0 + 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, // 0xc0 0xc2 to 0xdf 2 byte + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, // 0xd0 + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, // 0xe0 0xe0 to 0xef 3 byte + 4, 4, 4, 4, 4, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 // 0xf0 0xf0 to 0xf4 4 byte, 0xf5 and higher invalid +}; + + +void TiXmlBase::ConvertUTF32ToUTF8( unsigned long input, char* output, int* length ) +{ + const unsigned long BYTE_MASK = 0xBF; + const unsigned long BYTE_MARK = 0x80; + const unsigned long FIRST_BYTE_MARK[7] = { 0x00, 0x00, 0xC0, 0xE0, 0xF0, 0xF8, 0xFC }; + + if (input < 0x80) + *length = 1; + else if ( input < 0x800 ) + *length = 2; + else if ( input < 0x10000 ) + *length = 3; + else if ( input < 0x200000 ) + *length = 4; + else + { *length = 0; return; } // This code won't covert this correctly anyway. + + output += *length; + + // Scary scary fall throughs. + switch (*length) + { + case 4: + --output; + *output = (char)((input | BYTE_MARK) & BYTE_MASK); + input >>= 6; + case 3: + --output; + *output = (char)((input | BYTE_MARK) & BYTE_MASK); + input >>= 6; + case 2: + --output; + *output = (char)((input | BYTE_MARK) & BYTE_MASK); + input >>= 6; + case 1: + --output; + *output = (char)(input | FIRST_BYTE_MARK[*length]); + } +} + + +/*static*/ int TiXmlBase::IsAlpha( unsigned char anyByte, TiXmlEncoding /*encoding*/ ) +{ + // This will only work for low-ascii, everything else is assumed to be a valid + // letter. I'm not sure this is the best approach, but it is quite tricky trying + // to figure out alhabetical vs. not across encoding. So take a very + // conservative approach. + +// if ( encoding == TIXML_ENCODING_UTF8 ) +// { + if ( anyByte < 127 ) + return isalpha( anyByte ); + else + return 1; // What else to do? The unicode set is huge...get the english ones right. +// } +// else +// { +// return isalpha( anyByte ); +// } +} + + +/*static*/ int TiXmlBase::IsAlphaNum( unsigned char anyByte, TiXmlEncoding /*encoding*/ ) +{ + // This will only work for low-ascii, everything else is assumed to be a valid + // letter. I'm not sure this is the best approach, but it is quite tricky trying + // to figure out alhabetical vs. not across encoding. So take a very + // conservative approach. + +// if ( encoding == TIXML_ENCODING_UTF8 ) +// { + if ( anyByte < 127 ) + return isalnum( anyByte ); + else + return 1; // What else to do? The unicode set is huge...get the english ones right. +// } +// else +// { +// return isalnum( anyByte ); +// } +} + + +class TiXmlParsingData +{ + friend class TiXmlDocument; + public: + void Stamp( const char* now, TiXmlEncoding encoding ); + + const TiXmlCursor& Cursor() const { return cursor; } + + private: + // Only used by the document! + TiXmlParsingData( const char* start, int _tabsize, int row, int col ) + { + assert( start ); + stamp = start; + tabsize = _tabsize; + cursor.row = row; + cursor.col = col; + } + + TiXmlCursor cursor; + const char* stamp; + int tabsize; +}; + + +void TiXmlParsingData::Stamp( const char* now, TiXmlEncoding encoding ) +{ + assert( now ); + + // Do nothing if the tabsize is 0. + if ( tabsize < 1 ) + { + return; + } + + // Get the current row, column. + int row = cursor.row; + int col = cursor.col; + const char* p = stamp; + assert( p ); + + while ( p < now ) + { + // Treat p as unsigned, so we have a happy compiler. + const unsigned char* pU = (const unsigned char*)p; + + // Code contributed by Fletcher Dunn: (modified by lee) + switch (*pU) { + case 0: + // We *should* never get here, but in case we do, don't + // advance past the terminating null character, ever + return; + + case '\r': + // bump down to the next line + ++row; + col = 0; + // Eat the character + ++p; + + // Check for \r\n sequence, and treat this as a single character + if (*p == '\n') { + ++p; + } + break; + + case '\n': + // bump down to the next line + ++row; + col = 0; + + // Eat the character + ++p; + + // Check for \n\r sequence, and treat this as a single + // character. (Yes, this bizarre thing does occur still + // on some arcane platforms...) + if (*p == '\r') { + ++p; + } + break; + + case '\t': + // Eat the character + ++p; + + // Skip to next tab stop + col = (col / tabsize + 1) * tabsize; + break; + + case TIXML_UTF_LEAD_0: + if ( encoding == TIXML_ENCODING_UTF8 ) + { + if ( *(p+1) && *(p+2) ) + { + // In these cases, don't advance the column. These are + // 0-width spaces. + if ( *(pU+1)==TIXML_UTF_LEAD_1 && *(pU+2)==TIXML_UTF_LEAD_2 ) + p += 3; + else if ( *(pU+1)==0xbfU && *(pU+2)==0xbeU ) + p += 3; + else if ( *(pU+1)==0xbfU && *(pU+2)==0xbfU ) + p += 3; + else + { p +=3; ++col; } // A normal character. + } + } + else + { + ++p; + ++col; + } + break; + + default: + if ( encoding == TIXML_ENCODING_UTF8 ) + { + // Eat the 1 to 4 byte utf8 character. + int step = TiXmlBase::utf8ByteTable[*((const unsigned char*)p)]; + if ( step == 0 ) + step = 1; // Error case from bad encoding, but handle gracefully. + p += step; + + // Just advance one column, of course. + ++col; + } + else + { + ++p; + ++col; + } + break; + } + } + cursor.row = row; + cursor.col = col; + assert( cursor.row >= -1 ); + assert( cursor.col >= -1 ); + stamp = p; + assert( stamp ); +} + + +const char* TiXmlBase::SkipWhiteSpace( const char* p, TiXmlEncoding encoding ) +{ + if ( !p || !*p ) + { + return 0; + } + if ( encoding == TIXML_ENCODING_UTF8 ) + { + while ( *p ) + { + const unsigned char* pU = (const unsigned char*)p; + + // Skip the stupid Microsoft UTF-8 Byte order marks + if ( *(pU+0)==TIXML_UTF_LEAD_0 + && *(pU+1)==TIXML_UTF_LEAD_1 + && *(pU+2)==TIXML_UTF_LEAD_2 ) + { + p += 3; + continue; + } + else if(*(pU+0)==TIXML_UTF_LEAD_0 + && *(pU+1)==0xbfU + && *(pU+2)==0xbeU ) + { + p += 3; + continue; + } + else if(*(pU+0)==TIXML_UTF_LEAD_0 + && *(pU+1)==0xbfU + && *(pU+2)==0xbfU ) + { + p += 3; + continue; + } + + if ( IsWhiteSpace( *p ) ) // Still using old rules for white space. + ++p; + else + break; + } + } + else + { + while ( *p && IsWhiteSpace( *p ) ) + ++p; + } + + return p; +} + +#ifdef TIXML_USE_STL +/*static*/ bool TiXmlBase::StreamWhiteSpace( std::istream * in, TIXML_STRING * tag ) +{ + for( ;; ) + { + if ( !in->good() ) return false; + + int c = in->peek(); + // At this scope, we can't get to a document. So fail silently. + if ( !IsWhiteSpace( c ) || c <= 0 ) + return true; + + *tag += (char) in->get(); + } +} + +/*static*/ bool TiXmlBase::StreamTo( std::istream * in, int character, TIXML_STRING * tag ) +{ + //assert( character > 0 && character < 128 ); // else it won't work in utf-8 + while ( in->good() ) + { + int c = in->peek(); + if ( c == character ) + return true; + if ( c <= 0 ) // Silent failure: can't get document at this scope + return false; + + in->get(); + *tag += (char) c; + } + return false; +} +#endif + +// One of TinyXML's more performance demanding functions. Try to keep the memory overhead down. The +// "assign" optimization removes over 10% of the execution time. +// +const char* TiXmlBase::ReadName( const char* p, TIXML_STRING * name, TiXmlEncoding encoding ) +{ + // Oddly, not supported on some comilers, + //name->clear(); + // So use this: + *name = ""; + assert( p ); + + // Names start with letters or underscores. + // Of course, in unicode, tinyxml has no idea what a letter *is*. The + // algorithm is generous. + // + // After that, they can be letters, underscores, numbers, + // hyphens, or colons. (Colons are valid ony for namespaces, + // but tinyxml can't tell namespaces from names.) + if ( p && *p + && ( IsAlpha( (unsigned char) *p, encoding ) || *p == '_' ) ) + { + const char* start = p; + while( p && *p + && ( IsAlphaNum( (unsigned char ) *p, encoding ) + || *p == '_' + || *p == '-' + || *p == '.' + || *p == ':' ) ) + { + //(*name) += *p; // expensive + ++p; + } + if ( p-start > 0 ) { + name->assign( start, p-start ); + } + return p; + } + return 0; +} + +const char* TiXmlBase::GetEntity( const char* p, char* value, int* length, TiXmlEncoding encoding ) +{ + // Presume an entity, and pull it out. + TIXML_STRING ent; + int i; + *length = 0; + + if ( *(p+1) && *(p+1) == '#' && *(p+2) ) + { + unsigned long ucs = 0; + ptrdiff_t delta = 0; + unsigned mult = 1; + + if ( *(p+2) == 'x' ) + { + // Hexadecimal. + if ( !*(p+3) ) return 0; + + const char* q = p+3; + q = strchr( q, ';' ); + + if ( !q || !*q ) return 0; + + delta = q-p; + --q; + + while ( *q != 'x' ) + { + if ( *q >= '0' && *q <= '9' ) + ucs += mult * (*q - '0'); + else if ( *q >= 'a' && *q <= 'f' ) + ucs += mult * (*q - 'a' + 10); + else if ( *q >= 'A' && *q <= 'F' ) + ucs += mult * (*q - 'A' + 10 ); + else + return 0; + mult *= 16; + --q; + } + } + else + { + // Decimal. + if ( !*(p+2) ) return 0; + + const char* q = p+2; + q = strchr( q, ';' ); + + if ( !q || !*q ) return 0; + + delta = q-p; + --q; + + while ( *q != '#' ) + { + if ( *q >= '0' && *q <= '9' ) + ucs += mult * (*q - '0'); + else + return 0; + mult *= 10; + --q; + } + } + if ( encoding == TIXML_ENCODING_UTF8 ) + { + // convert the UCS to UTF-8 + ConvertUTF32ToUTF8( ucs, value, length ); + } + else + { + *value = (char)ucs; + *length = 1; + } + return p + delta + 1; + } + + // Now try to match it. + for( i=0; iappend( cArr, len ); + } + } + else + { + bool whitespace = false; + + // Remove leading white space: + p = SkipWhiteSpace( p, encoding ); + while ( p && *p + && !StringEqual( p, endTag, caseInsensitive, encoding ) ) + { + if ( *p == '\r' || *p == '\n' ) + { + whitespace = true; + ++p; + } + else if ( IsWhiteSpace( *p ) ) + { + whitespace = true; + ++p; + } + else + { + // If we've found whitespace, add it before the + // new character. Any whitespace just becomes a space. + if ( whitespace ) + { + (*text) += ' '; + whitespace = false; + } + int len; + char cArr[4] = { 0, 0, 0, 0 }; + p = GetChar( p, cArr, &len, encoding ); + if ( len == 1 ) + (*text) += cArr[0]; // more efficient + else + text->append( cArr, len ); + } + } + } + if ( p && *p ) + p += strlen( endTag ); + return ( p && *p ) ? p : 0; +} + +#ifdef TIXML_USE_STL + +void TiXmlDocument::StreamIn( std::istream * in, TIXML_STRING * tag ) +{ + // The basic issue with a document is that we don't know what we're + // streaming. Read something presumed to be a tag (and hope), then + // identify it, and call the appropriate stream method on the tag. + // + // This "pre-streaming" will never read the closing ">" so the + // sub-tag can orient itself. + + if ( !StreamTo( in, '<', tag ) ) + { + SetError( TIXML_ERROR_PARSING_EMPTY, 0, 0, TIXML_ENCODING_UNKNOWN ); + return; + } + + while ( in->good() ) + { + int tagIndex = (int) tag->length(); + while ( in->good() && in->peek() != '>' ) + { + int c = in->get(); + if ( c <= 0 ) + { + SetError( TIXML_ERROR_EMBEDDED_NULL, 0, 0, TIXML_ENCODING_UNKNOWN ); + break; + } + (*tag) += (char) c; + } + + if ( in->good() ) + { + // We now have something we presume to be a node of + // some sort. Identify it, and call the node to + // continue streaming. + TiXmlNode* node = Identify( tag->c_str() + tagIndex, TIXML_DEFAULT_ENCODING ); + + if ( node ) + { + node->StreamIn( in, tag ); + bool isElement = node->ToElement() != 0; + delete node; + node = 0; + + // If this is the root element, we're done. Parsing will be + // done by the >> operator. + if ( isElement ) + { + return; + } + } + else + { + SetError( TIXML_ERROR, 0, 0, TIXML_ENCODING_UNKNOWN ); + return; + } + } + } + // We should have returned sooner. + SetError( TIXML_ERROR, 0, 0, TIXML_ENCODING_UNKNOWN ); +} + +#endif + +const char* TiXmlDocument::Parse( const char* p, TiXmlParsingData* prevData, TiXmlEncoding encoding ) +{ + ClearError(); + + // Parse away, at the document level. Since a document + // contains nothing but other tags, most of what happens + // here is skipping white space. + if ( !p || !*p ) + { + SetError( TIXML_ERROR_DOCUMENT_EMPTY, 0, 0, TIXML_ENCODING_UNKNOWN ); + return 0; + } + + // Note that, for a document, this needs to come + // before the while space skip, so that parsing + // starts from the pointer we are given. + location.Clear(); + if ( prevData ) + { + location.row = prevData->cursor.row; + location.col = prevData->cursor.col; + } + else + { + location.row = 0; + location.col = 0; + } + TiXmlParsingData data( p, TabSize(), location.row, location.col ); + location = data.Cursor(); + + if ( encoding == TIXML_ENCODING_UNKNOWN ) + { + // Check for the Microsoft UTF-8 lead bytes. + const unsigned char* pU = (const unsigned char*)p; + if ( *(pU+0) && *(pU+0) == TIXML_UTF_LEAD_0 + && *(pU+1) && *(pU+1) == TIXML_UTF_LEAD_1 + && *(pU+2) && *(pU+2) == TIXML_UTF_LEAD_2 ) + { + encoding = TIXML_ENCODING_UTF8; + useMicrosoftBOM = true; + } + } + + p = SkipWhiteSpace( p, encoding ); + if ( !p ) + { + SetError( TIXML_ERROR_DOCUMENT_EMPTY, 0, 0, TIXML_ENCODING_UNKNOWN ); + return 0; + } + + while ( p && *p ) + { + TiXmlNode* node = Identify( p, encoding ); + if ( node ) + { + p = node->Parse( p, &data, encoding ); + LinkEndChild( node ); + } + else + { + break; + } + + // Did we get encoding info? + if ( encoding == TIXML_ENCODING_UNKNOWN + && node->ToDeclaration() ) + { + TiXmlDeclaration* dec = node->ToDeclaration(); + const char* enc = dec->Encoding(); + assert( enc ); + + if ( *enc == 0 ) + encoding = TIXML_ENCODING_UTF8; + else if ( StringEqual( enc, "UTF-8", true, TIXML_ENCODING_UNKNOWN ) ) + encoding = TIXML_ENCODING_UTF8; + else if ( StringEqual( enc, "UTF8", true, TIXML_ENCODING_UNKNOWN ) ) + encoding = TIXML_ENCODING_UTF8; // incorrect, but be nice + else + encoding = TIXML_ENCODING_LEGACY; + } + + p = SkipWhiteSpace( p, encoding ); + } + + // Was this empty? + if ( !firstChild ) { + SetError( TIXML_ERROR_DOCUMENT_EMPTY, 0, 0, encoding ); + return 0; + } + + // All is well. + return p; +} + +void TiXmlDocument::SetError( int err, const char* pError, TiXmlParsingData* data, TiXmlEncoding encoding ) +{ + // The first error in a chain is more accurate - don't set again! + if ( error ) + return; + + assert( err > 0 && err < TIXML_ERROR_STRING_COUNT ); + error = true; + errorId = err; + errorDesc = errorString[ errorId ]; + + errorLocation.Clear(); + if ( pError && data ) + { + data->Stamp( pError, encoding ); + errorLocation = data->Cursor(); + } +} + + +TiXmlNode* TiXmlNode::Identify( const char* p, TiXmlEncoding encoding ) +{ + TiXmlNode* returnNode = 0; + + p = SkipWhiteSpace( p, encoding ); + if( !p || !*p || *p != '<' ) + { + return 0; + } + + p = SkipWhiteSpace( p, encoding ); + + if ( !p || !*p ) + { + return 0; + } + + // What is this thing? + // - Elements start with a letter or underscore, but xml is reserved. + // - Comments: "; + + if ( !StringEqual( p, startTag, false, encoding ) ) + { + if ( document ) + document->SetError( TIXML_ERROR_PARSING_COMMENT, p, data, encoding ); + return 0; + } + p += strlen( startTag ); + + // [ 1475201 ] TinyXML parses entities in comments + // Oops - ReadText doesn't work, because we don't want to parse the entities. + // p = ReadText( p, &value, false, endTag, false, encoding ); + // + // from the XML spec: + /* + [Definition: Comments may appear anywhere in a document outside other markup; in addition, + they may appear within the document type declaration at places allowed by the grammar. + They are not part of the document's character data; an XML processor MAY, but need not, + make it possible for an application to retrieve the text of comments. For compatibility, + the string "--" (double-hyphen) MUST NOT occur within comments.] Parameter entity + references MUST NOT be recognized within comments. + + An example of a comment: + + + */ + + value = ""; + // Keep all the white space. + while ( p && *p && !StringEqual( p, endTag, false, encoding ) ) + { + value.append( p, 1 ); + ++p; + } + if ( p && *p ) + p += strlen( endTag ); + + return p; +} + + +const char* TiXmlAttribute::Parse( const char* p, TiXmlParsingData* data, TiXmlEncoding encoding ) +{ + p = SkipWhiteSpace( p, encoding ); + if ( !p || !*p ) return 0; + + if ( data ) + { + data->Stamp( p, encoding ); + location = data->Cursor(); + } + // Read the name, the '=' and the value. + const char* pErr = p; + p = ReadName( p, &name, encoding ); + if ( !p || !*p ) + { + if ( document ) document->SetError( TIXML_ERROR_READING_ATTRIBUTES, pErr, data, encoding ); + return 0; + } + p = SkipWhiteSpace( p, encoding ); + if ( !p || !*p || *p != '=' ) + { + if ( document ) document->SetError( TIXML_ERROR_READING_ATTRIBUTES, p, data, encoding ); + return 0; + } + + ++p; // skip '=' + p = SkipWhiteSpace( p, encoding ); + if ( !p || !*p ) + { + if ( document ) document->SetError( TIXML_ERROR_READING_ATTRIBUTES, p, data, encoding ); + return 0; + } + + const char* end; + const char SINGLE_QUOTE = '\''; + const char DOUBLE_QUOTE = '\"'; + + if ( *p == SINGLE_QUOTE ) + { + ++p; + end = "\'"; // single quote in string + p = ReadText( p, &value, false, end, false, encoding ); + } + else if ( *p == DOUBLE_QUOTE ) + { + ++p; + end = "\""; // double quote in string + p = ReadText( p, &value, false, end, false, encoding ); + } + else + { + // All attribute values should be in single or double quotes. + // But this is such a common error that the parser will try + // its best, even without them. + value = ""; + while ( p && *p // existence + && !IsWhiteSpace( *p ) // whitespace + && *p != '/' && *p != '>' ) // tag end + { + if ( *p == SINGLE_QUOTE || *p == DOUBLE_QUOTE ) { + // [ 1451649 ] Attribute values with trailing quotes not handled correctly + // We did not have an opening quote but seem to have a + // closing one. Give up and throw an error. + if ( document ) document->SetError( TIXML_ERROR_READING_ATTRIBUTES, p, data, encoding ); + return 0; + } + value += *p; + ++p; + } + } + return p; +} + +#ifdef TIXML_USE_STL +void TiXmlText::StreamIn( std::istream * in, TIXML_STRING * tag ) +{ + while ( in->good() ) + { + int c = in->peek(); + if ( !cdata && (c == '<' ) ) + { + return; + } + if ( c <= 0 ) + { + TiXmlDocument* document = GetDocument(); + if ( document ) + document->SetError( TIXML_ERROR_EMBEDDED_NULL, 0, 0, TIXML_ENCODING_UNKNOWN ); + return; + } + + (*tag) += (char) c; + in->get(); // "commits" the peek made above + + if ( cdata && c == '>' && tag->size() >= 3 ) { + size_t len = tag->size(); + if ( (*tag)[len-2] == ']' && (*tag)[len-3] == ']' ) { + // terminator of cdata. + return; + } + } + } +} +#endif + +const char* TiXmlText::Parse( const char* p, TiXmlParsingData* data, TiXmlEncoding encoding ) +{ + value = ""; + TiXmlDocument* document = GetDocument(); + + if ( data ) + { + data->Stamp( p, encoding ); + location = data->Cursor(); + } + + const char* const startTag = ""; + + if ( cdata || StringEqual( p, startTag, false, encoding ) ) + { + cdata = true; + + if ( !StringEqual( p, startTag, false, encoding ) ) + { + if ( document ) + document->SetError( TIXML_ERROR_PARSING_CDATA, p, data, encoding ); + return 0; + } + p += strlen( startTag ); + + // Keep all the white space, ignore the encoding, etc. + while ( p && *p + && !StringEqual( p, endTag, false, encoding ) + ) + { + value += *p; + ++p; + } + + TIXML_STRING dummy; + p = ReadText( p, &dummy, false, endTag, false, encoding ); + return p; + } + else + { + bool ignoreWhite = true; + + const char* end = "<"; + p = ReadText( p, &value, ignoreWhite, end, false, encoding ); + if ( p && *p ) + return p-1; // don't truncate the '<' + return 0; + } +} + +#ifdef TIXML_USE_STL +void TiXmlDeclaration::StreamIn( std::istream * in, TIXML_STRING * tag ) +{ + while ( in->good() ) + { + int c = in->get(); + if ( c <= 0 ) + { + TiXmlDocument* document = GetDocument(); + if ( document ) + document->SetError( TIXML_ERROR_EMBEDDED_NULL, 0, 0, TIXML_ENCODING_UNKNOWN ); + return; + } + (*tag) += (char) c; + + if ( c == '>' ) + { + // All is well. + return; + } + } +} +#endif + +const char* TiXmlDeclaration::Parse( const char* p, TiXmlParsingData* data, TiXmlEncoding _encoding ) +{ + p = SkipWhiteSpace( p, _encoding ); + // Find the beginning, find the end, and look for + // the stuff in-between. + TiXmlDocument* document = GetDocument(); + if ( !p || !*p || !StringEqual( p, "SetError( TIXML_ERROR_PARSING_DECLARATION, 0, 0, _encoding ); + return 0; + } + if ( data ) + { + data->Stamp( p, _encoding ); + location = data->Cursor(); + } + p += 5; + + version = ""; + encoding = ""; + standalone = ""; + + while ( p && *p ) + { + if ( *p == '>' ) + { + ++p; + return p; + } + + p = SkipWhiteSpace( p, _encoding ); + if ( StringEqual( p, "version", true, _encoding ) ) + { + TiXmlAttribute attrib; + p = attrib.Parse( p, data, _encoding ); + version = attrib.Value(); + } + else if ( StringEqual( p, "encoding", true, _encoding ) ) + { + TiXmlAttribute attrib; + p = attrib.Parse( p, data, _encoding ); + encoding = attrib.Value(); + } + else if ( StringEqual( p, "standalone", true, _encoding ) ) + { + TiXmlAttribute attrib; + p = attrib.Parse( p, data, _encoding ); + standalone = attrib.Value(); + } + else + { + // Read over whatever it is. + while( p && *p && *p != '>' && !IsWhiteSpace( *p ) ) + ++p; + } + } + return 0; +} + +bool TiXmlText::Blank() const +{ + for ( unsigned i=0; i Date: Thu, 22 Sep 2011 21:12:57 +0000 Subject: Fixing compilation issues on Windows. git-svn-id: http://sfntly.googlecode.com/svn/trunk/cpp/src@95 672e30a5-4c29-85ac-ac6d-611c735e0a51 --- test/autogenerated/cmap_basic_test.cc | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/test/autogenerated/cmap_basic_test.cc b/test/autogenerated/cmap_basic_test.cc index ddf3aa5..07c54e1 100644 --- a/test/autogenerated/cmap_basic_test.cc +++ b/test/autogenerated/cmap_basic_test.cc @@ -81,7 +81,7 @@ void CMapBasicTests::SetUp() { TEST_P(CMapBasicTests, BasicTest) { TiXmlNodeVector* cmap_table = GetNodesWithName(&document_, "cmap_table"); // A font can only have one CMap table - ASSERT_EQ(cmap_table->size(), 1); + ASSERT_EQ(cmap_table->size(), (int32_t)1); TiXmlNodeVector* cmaps = GetNodesWithName(cmap_table->at(0), "cmap"); const TiXmlAttribute* num_cmaps_attr = GetAttribute(cmap_table->at(0), "num_cmaps"); @@ -105,7 +105,11 @@ TEST_P(CMapBasicTests, BasicTest) { for (TiXmlNodeVector::iterator jt = maps->begin(); jt != maps->end(); ++jt) { int32_t character; +#if defined (WIN32) + sscanf_s(GetAttribute(*jt, "char")->Value(), "%x", &character); +#else sscanf(GetAttribute(*jt, "char")->Value(), "%x", &character); +#endif int32_t glyph_id = GetAttribute(*jt, "gid")->IntValue(); ASSERT_EQ(cmap->GlyphId(character), glyph_id); } -- cgit v1.2.3 From 8dd54cd13ca1dfe7ef6245056d4a322b43a7fae5 Mon Sep 17 00:00:00 2001 From: "dfilimon@google.com" Date: Thu, 22 Sep 2011 21:17:23 +0000 Subject: Fixing signed/unsigned comparison mismatch. git-svn-id: http://sfntly.googlecode.com/svn/trunk/cpp/src@96 672e30a5-4c29-85ac-ac6d-611c735e0a51 --- test/autogenerated/cmap_basic_test.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/autogenerated/cmap_basic_test.cc b/test/autogenerated/cmap_basic_test.cc index 07c54e1..22cbdd2 100644 --- a/test/autogenerated/cmap_basic_test.cc +++ b/test/autogenerated/cmap_basic_test.cc @@ -81,7 +81,7 @@ void CMapBasicTests::SetUp() { TEST_P(CMapBasicTests, BasicTest) { TiXmlNodeVector* cmap_table = GetNodesWithName(&document_, "cmap_table"); // A font can only have one CMap table - ASSERT_EQ(cmap_table->size(), (int32_t)1); + ASSERT_EQ(cmap_table->size(), (size_t)1); TiXmlNodeVector* cmaps = GetNodesWithName(cmap_table->at(0), "cmap"); const TiXmlAttribute* num_cmaps_attr = GetAttribute(cmap_table->at(0), "num_cmaps"); -- cgit v1.2.3 From f247d4b0f53526631581f74a6862a2f2ca952f75 Mon Sep 17 00:00:00 2001 From: "dfilimon@google.com" Date: Thu, 22 Sep 2011 21:23:42 +0000 Subject: Fixing another signed/unsigned comparison issue. git-svn-id: http://sfntly.googlecode.com/svn/trunk/cpp/src@97 672e30a5-4c29-85ac-ac6d-611c735e0a51 --- test/autogenerated/cmap_basic_test.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/autogenerated/cmap_basic_test.cc b/test/autogenerated/cmap_basic_test.cc index 22cbdd2..aae35e1 100644 --- a/test/autogenerated/cmap_basic_test.cc +++ b/test/autogenerated/cmap_basic_test.cc @@ -87,7 +87,7 @@ TEST_P(CMapBasicTests, BasicTest) { "num_cmaps"); ASSERT_NE(num_cmaps_attr, reinterpret_cast(NULL)); // But there may be more than one CMap in this table - ASSERT_LE(cmaps->size(), num_cmaps_attr->IntValue()); + ASSERT_LE(cmaps->size(), (size_t)num_cmaps_attr->IntValue()); for (TiXmlNodeVector::iterator it = cmaps->begin(); it != cmaps->end(); ++it) { int32_t platform_id = GetAttribute(*it, "platform_id")->IntValue(); -- cgit v1.2.3 From dc47db9a1c26e13a4e8be6185bd0ecf89c0d1f81 Mon Sep 17 00:00:00 2001 From: "arthurhsu@google.com" Date: Mon, 26 Sep 2011 17:58:32 +0000 Subject: Temporary disable CMap and Bitmap processing by default. git-svn-id: http://sfntly.googlecode.com/svn/trunk/cpp/src@98 672e30a5-4c29-85ac-ac6d-611c735e0a51 --- sfntly/table/table.cc | 23 ++++++++++++++--------- 1 file changed, 14 insertions(+), 9 deletions(-) diff --git a/sfntly/table/table.cc b/sfntly/table/table.cc index 8f4571e..6cfe1f8 100644 --- a/sfntly/table/table.cc +++ b/sfntly/table/table.cc @@ -78,12 +78,14 @@ Table::Builder* Table::Builder::GetBuilder(Header* header, // Note: Tables are commented out when they are not used/ported. // TODO(arthurhsu): IMPLEMENT: finish tables that are not ported. - if (tag == Tag::cmap) { - builder_raw = static_cast( - CMapTable::Builder::CreateBuilder(header, table_data)); - } else if (tag == Tag::head) { + if (tag == Tag::head) { builder_raw = static_cast( FontHeaderTable::Builder::CreateBuilder(header, table_data)); +#if defined (SFNTLY_ENABLE_CMAP_HANDLING) + } else if (tag == Tag::cmap) { + builder_raw = static_cast( + CMapTable::Builder::CreateBuilder(header, table_data)); +#endif // SFNTLY_ENABLE_CMAP_HANDLING } else if (tag == Tag::hhea) { builder_raw = static_cast( HorizontalHeaderTable::Builder::CreateBuilder(header, table_data)); @@ -111,18 +113,21 @@ Table::Builder* Table::Builder::GetBuilder(Header* header, } else if (tag == Tag::loca) { builder_raw = static_cast( LocaTable::Builder::CreateBuilder(header, table_data)); - }/* else if (tag == Tag::prep) { - builder_raw = static_cast( - ControlProgramTable::Builder::CreateBuilder(header, table_data)); - }*/ else if (tag == Tag::EBDT || tag == Tag::bdat) { +#if defined (SFNTLY_ENABLE_BITMAP_HANDLING) + } 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) { +#endif // SFNTLY_ENABLE_BITMAP_HANDLING + } /* 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)); -- cgit v1.2.3 From 333edd91cb32d6acfd0307ba2ae8f60baed75ff4 Mon Sep 17 00:00:00 2001 From: "arthurhsu@google.com" Date: Tue, 11 Oct 2011 01:01:16 +0000 Subject: Update to Sep 30 snapshot, include all current EBXX support. Refine Iterator ports: all java-style Iterator objects are ref-counted and have automatic memory management now. git-svn-id: http://sfntly.googlecode.com/svn/trunk/cpp/src@100 672e30a5-4c29-85ac-ac6d-611c735e0a51 --- sfntly/data/byte_array.cc | 8 +- sfntly/data/font_data.cc | 6 +- sfntly/data/font_data.h | 7 +- sfntly/data/readable_font_data.cc | 7 + sfntly/data/readable_font_data.h | 6 + sfntly/data/writable_font_data.cc | 16 +- sfntly/data/writable_font_data.h | 13 + sfntly/font.cc | 26 +- sfntly/math/font_math.h | 11 + sfntly/port/java_iterator.h | 94 ++++++ sfntly/table/bitmap/big_glyph_metrics.cc | 162 +++++++++ sfntly/table/bitmap/big_glyph_metrics.h | 92 ++++++ sfntly/table/bitmap/bitmap_glyph.cc | 51 ++- sfntly/table/bitmap/bitmap_glyph.h | 25 +- sfntly/table/bitmap/bitmap_glyph_info.cc | 68 ++++ sfntly/table/bitmap/bitmap_glyph_info.h | 85 +++++ sfntly/table/bitmap/bitmap_size_table.cc | 440 ++++++++++++++++++++++++- sfntly/table/bitmap/bitmap_size_table.h | 125 ++++++- sfntly/table/bitmap/composite_bitmap_glyph.cc | 20 ++ sfntly/table/bitmap/composite_bitmap_glyph.h | 10 + sfntly/table/bitmap/ebdt_table.cc | 182 ++++++++-- sfntly/table/bitmap/ebdt_table.h | 47 ++- sfntly/table/bitmap/eblc_table.cc | 199 ++++++++++- sfntly/table/bitmap/eblc_table.h | 32 +- sfntly/table/bitmap/ebsc_table.cc | 107 ++++++ sfntly/table/bitmap/ebsc_table.h | 102 ++++++ sfntly/table/bitmap/glyph_metrics.cc | 39 +++ sfntly/table/bitmap/glyph_metrics.h | 43 +++ sfntly/table/bitmap/index_sub_table.cc | 222 +++++++++---- sfntly/table/bitmap/index_sub_table.h | 104 +++++- sfntly/table/bitmap/index_sub_table_format1.cc | 247 +++++++++++++- sfntly/table/bitmap/index_sub_table_format1.h | 86 ++++- sfntly/table/bitmap/index_sub_table_format2.cc | 210 ++++++++++-- sfntly/table/bitmap/index_sub_table_format2.h | 74 ++++- sfntly/table/bitmap/index_sub_table_format3.cc | 251 ++++++++++++-- sfntly/table/bitmap/index_sub_table_format3.h | 84 ++++- sfntly/table/bitmap/index_sub_table_format4.cc | 358 +++++++++++++++++--- sfntly/table/bitmap/index_sub_table_format4.h | 109 +++++- sfntly/table/bitmap/index_sub_table_format5.cc | 328 ++++++++++++++++-- sfntly/table/bitmap/index_sub_table_format5.h | 91 ++++- sfntly/table/bitmap/simple_bitmap_glyph.cc | 17 + sfntly/table/bitmap/simple_bitmap_glyph.h | 11 + sfntly/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 +++ sfntly/table/core/name_table.cc | 61 ++-- sfntly/table/core/name_table.h | 14 +- sfntly/table/font_data_table.cc | 18 +- sfntly/table/generic_table_builder.cc | 49 +++ sfntly/table/generic_table_builder.h | 42 +++ sfntly/table/header.h | 16 +- sfntly/table/subtable.cc | 23 +- sfntly/table/subtable.h | 23 +- sfntly/table/table.cc | 1 + sfntly/table/table_based_table_builder.cc | 24 -- sfntly/table/table_based_table_builder.h | 13 +- sfntly/table/truetype/glyph_table.cc | 11 +- sfntly/table/truetype/glyph_table.h | 19 +- sfntly/table/truetype/loca_table.cc | 59 ++-- sfntly/table/truetype/loca_table.h | 23 +- test/font_parsing_test.cc | 1 + 62 files changed, 4449 insertions(+), 491 deletions(-) create mode 100644 sfntly/port/java_iterator.h create mode 100644 sfntly/table/bitmap/big_glyph_metrics.cc create mode 100644 sfntly/table/bitmap/big_glyph_metrics.h create mode 100644 sfntly/table/bitmap/bitmap_glyph_info.cc create mode 100644 sfntly/table/bitmap/bitmap_glyph_info.h create mode 100644 sfntly/table/bitmap/ebsc_table.cc create mode 100644 sfntly/table/bitmap/ebsc_table.h create mode 100644 sfntly/table/bitmap/glyph_metrics.cc create mode 100644 sfntly/table/bitmap/glyph_metrics.h create mode 100644 sfntly/table/bitmap/small_glyph_metrics.cc create mode 100644 sfntly/table/bitmap/small_glyph_metrics.h create mode 100644 sfntly/table/byte_array_table_builder.cc create mode 100644 sfntly/table/byte_array_table_builder.h create mode 100644 sfntly/table/generic_table_builder.cc create mode 100644 sfntly/table/generic_table_builder.h diff --git a/sfntly/data/byte_array.cc b/sfntly/data/byte_array.cc index c820adc..915a40c 100644 --- a/sfntly/data/byte_array.cc +++ b/sfntly/data/byte_array.cc @@ -115,13 +115,7 @@ int32_t ByteArray::CopyTo(int32_t dst_offset, ByteArray* array, 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); - if (bytes_written != bytes_read) { -#if defined (SFNTLY_NO_EXCEPTION) - return 0; -#else - throw IOException("Error writing bytes."); -#endif - } + UNREFERENCED_PARAMETER(bytes_written); index += bytes_read; remaining_length -= bytes_read; buffer_length = std::min(b.size(), remaining_length); diff --git a/sfntly/data/font_data.cc b/sfntly/data/font_data.cc index ccc2a19..d2b95ea 100644 --- a/sfntly/data/font_data.cc +++ b/sfntly/data/font_data.cc @@ -58,7 +58,9 @@ FontData::FontData(FontData* data, int32_t offset, int32_t length) { FontData::FontData(FontData* data, int32_t offset) { Init(data->array_); - Bound(data->bound_offset_ + offset); + Bound(data->bound_offset_ + offset, + (data->bound_length_ == GROWABLE_SIZE) + ? GROWABLE_SIZE : data->bound_length_ - offset); } FontData::~FontData() {} @@ -66,7 +68,7 @@ FontData::~FontData() {} void FontData::Init(ByteArray* ba) { array_ = ba; bound_offset_ = 0; - bound_length_ = INT_MAX; + bound_length_ = GROWABLE_SIZE; } int32_t FontData::BoundOffset(int32_t offset) { diff --git a/sfntly/data/font_data.h b/sfntly/data/font_data.h index ec87c72..d02e8b7 100644 --- a/sfntly/data/font_data.h +++ b/sfntly/data/font_data.h @@ -17,6 +17,8 @@ #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" @@ -110,12 +112,15 @@ class FontData : virtual public RefCount { // @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. + // 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_; diff --git a/sfntly/data/readable_font_data.cc b/sfntly/data/readable_font_data.cc index fb083cb..bb58c26 100644 --- a/sfntly/data/readable_font_data.cc +++ b/sfntly/data/readable_font_data.cc @@ -121,6 +121,13 @@ int32_t ReadableFontData::ReadULongAsInt(int32_t index) { 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 | diff --git a/sfntly/data/readable_font_data.h b/sfntly/data/readable_font_data.h index c5833e8..b43c626 100644 --- a/sfntly/data/readable_font_data.h +++ b/sfntly/data/readable_font_data.h @@ -128,6 +128,12 @@ class ReadableFontData : public FontData, // @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 diff --git a/sfntly/data/writable_font_data.cc b/sfntly/data/writable_font_data.cc index 0b271a3..ace387c 100644 --- a/sfntly/data/writable_font_data.cc +++ b/sfntly/data/writable_font_data.cc @@ -82,12 +82,22 @@ int32_t WritableFontData::WriteBytesPad(int32_t index, offset, BoundLength(index, std::min(length, b->size() - offset))); - for (; written < length; written++) { - array_->Put(written + index, pad); - } + 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); } diff --git a/sfntly/data/writable_font_data.h b/sfntly/data/writable_font_data.h index 9a9bd7b..f88a986 100644 --- a/sfntly/data/writable_font_data.h +++ b/sfntly/data/writable_font_data.h @@ -85,6 +85,19 @@ class WritableFontData : public ReadableFontData { 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 diff --git a/sfntly/font.cc b/sfntly/font.cc index 524932b..3fa77b0 100644 --- a/sfntly/font.cc +++ b/sfntly/font.cc @@ -295,15 +295,9 @@ Table::Builder* Font::Builder::NewTableBuilder(int32_t tag, assert(src_data); WritableFontDataPtr data; data.Attach(WritableFontData::CreateWritableFontData(src_data->Length())); -#if !defined (SFNTLY_NO_EXCEPTION) - try { -#endif - src_data->CopyTo(data); -#if !defined (SFNTLY_NO_EXCEPTION) - } catch (IOException& e) { - return NULL; - } -#endif + // 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)); @@ -378,19 +372,7 @@ void Font::Builder::BuildTablesFromBuilders(Font* font, builder != builder_end; ++builder) { TablePtr table; if (builder->second && builder->second->ReadyToBuild()) { -#if !defined (SFNTLY_NO_EXCEPTION) - try { -#endif - table.Attach(down_cast(builder->second->Build())); -#if !defined (SFNTLY_NO_EXCEPTION) - } catch(IOException& e) { - 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 + table.Attach(down_cast(builder->second->Build())); } if (table == NULL) { table_map->clear(); diff --git a/sfntly/math/font_math.h b/sfntly/math/font_math.h index c469347..f1cd2d2 100644 --- a/sfntly/math/font_math.h +++ b/sfntly/math/font_math.h @@ -31,6 +31,17 @@ class FontMath { } 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 diff --git a/sfntly/port/java_iterator.h b/sfntly/port/java_iterator.h new file mode 100644 index 0000000..0a99bca --- /dev/null +++ b/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/sfntly/table/bitmap/big_glyph_metrics.cc b/sfntly/table/bitmap/big_glyph_metrics.cc new file mode 100644 index 0000000..d2519cd --- /dev/null +++ b/sfntly/table/bitmap/big_glyph_metrics.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. + */ + +#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); +} + +} // namespace sfntly diff --git a/sfntly/table/bitmap/big_glyph_metrics.h b/sfntly/table/bitmap/big_glyph_metrics.h new file mode 100644 index 0000000..55963b4 --- /dev/null +++ b/sfntly/table/bitmap/big_glyph_metrics.h @@ -0,0 +1,92 @@ +/* + * 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); + }; + + 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/sfntly/table/bitmap/bitmap_glyph.cc b/sfntly/table/bitmap/bitmap_glyph.cc index 82d78b3..334a0c0 100644 --- a/sfntly/table/bitmap/bitmap_glyph.cc +++ b/sfntly/table/bitmap/bitmap_glyph.cc @@ -15,6 +15,8 @@ */ #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 { /****************************************************************************** @@ -23,6 +25,17 @@ namespace sfntly { 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) { } @@ -33,12 +46,34 @@ BitmapGlyph::BitmapGlyph(ReadableFontData* data, int32_t format) BitmapGlyph::Builder::~Builder() { } -BitmapGlyph::Builder::Builder(WritableFontData* data) - : SubTable::Builder(data) { +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) - : SubTable::Builder(data) { +BitmapGlyph::Builder::Builder(ReadableFontData* data, int32_t format) + : SubTable::Builder(data), format_(format) { } CALLER_ATTACH @@ -48,19 +83,19 @@ FontDataTable* BitmapGlyph::Builder::SubBuildTable(ReadableFontData* data) { } void BitmapGlyph::Builder::SubDataSet() { + // NOP } int32_t BitmapGlyph::Builder::SubDataSizeToSerialize() { - return 0; + return InternalReadData()->Length(); } bool BitmapGlyph::Builder::SubReadyToSerialize() { - return false; + return true; } int32_t BitmapGlyph::Builder::SubSerialize(WritableFontData* new_data) { - UNREFERENCED_PARAMETER(new_data); - return 0; + return InternalReadData()->CopyTo(new_data); } } // namespace sfntly diff --git a/sfntly/table/bitmap/bitmap_glyph.h b/sfntly/table/bitmap/bitmap_glyph.h index 47afbe1..2dd4c3a 100644 --- a/sfntly/table/bitmap/bitmap_glyph.h +++ b/sfntly/table/bitmap/bitmap_glyph.h @@ -17,6 +17,9 @@ #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 { @@ -73,18 +76,29 @@ class BitmapGlyph : public SubTable { public: virtual ~Builder(); - protected: - Builder(WritableFontData* data); - Builder(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); + + 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() @@ -96,6 +110,9 @@ class BitmapGlyph : public SubTable { int32_t format_; }; typedef Ptr BitmapGlyphPtr; +typedef Ptr BitmapGlyphBuilderPtr; +typedef std::map BitmapGlyphBuilderMap; +typedef std::vector BitmapGlyphBuilderList; } // namespace sfntly diff --git a/sfntly/table/bitmap/bitmap_glyph_info.cc b/sfntly/table/bitmap/bitmap_glyph_info.cc new file mode 100644 index 0000000..ab9953b --- /dev/null +++ b/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/sfntly/table/bitmap/bitmap_glyph_info.h b/sfntly/table/bitmap/bitmap_glyph_info.h new file mode 100644 index 0000000..9921d0d --- /dev/null +++ b/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/sfntly/table/bitmap/bitmap_size_table.cc b/sfntly/table/bitmap/bitmap_size_table.cc index 00488ea..93b8625 100644 --- a/sfntly/table/bitmap/bitmap_size_table.cc +++ b/sfntly/table/bitmap/bitmap_size_table.cc @@ -16,16 +16,19 @@ #include "sfntly/table/bitmap/bitmap_size_table.h" +#include + #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::BitmapSizeTable(ReadableFontData* data, - ReadableFontData* master_data) - : SubTable(data) { - master_data_ = master_data; -} - +/****************************************************************************** + * BitmapSizeTable class + ******************************************************************************/ BitmapSizeTable::~BitmapSizeTable() { } @@ -40,8 +43,7 @@ int32_t BitmapSizeTable::IndexTableSize() { } int32_t BitmapSizeTable::NumberOfIndexSubTables() { - return data_->ReadULongAsInt( - EblcTable::Offset::kBitmapSizeTable_numberOfIndexSubTables); + return NumberOfIndexSubTables(data_, 0); } int32_t BitmapSizeTable::ColorRef() { @@ -96,6 +98,14 @@ int32_t BitmapSizeTable::GlyphLength(int32_t glyph_id) { 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) { @@ -104,7 +114,41 @@ int32_t BitmapSizeTable::GlyphFormat(int32_t glyph_id) { 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; @@ -128,21 +172,389 @@ IndexSubTable* BitmapSizeTable::SearchIndexSubTables(int32_t glyph_id) { CALLER_ATTACH IndexSubTable* BitmapSizeTable::CreateIndexSubTable(int32_t index) { - return IndexSubTable::CreateIndexSubTable(master_data_, + return IndexSubTable::CreateIndexSubTable(master_read_data(), IndexSubTableArrayOffset(), index); } IndexSubTableList* BitmapSizeTable::GetIndexSubTableList() { - AutoLock lock(atomic_subtables_lock_); - if (atomic_subtables.empty()) { + AutoLock lock(index_subtables_lock_); + if (index_subtables_.empty()) { for (int32_t i = 0; i < NumberOfIndexSubTables(); ++i) { IndexSubTablePtr table; table.Attach(CreateIndexSubTable(i)); - atomic_subtables.push_back(table); + 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(); + variable = (sub_table_size > 0) ? variable : true; + size += abs(sub_table_size); + } + return 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::GetIndexSubTable( + int32_t index) { + IndexSubTableBuilderList* sub_table_list = GetIndexSubTableBuilders(); + return sub_table_list->at(index); +} + +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) { + 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); + for (int32_t i = 0; i < number_of_index_subtables; ++i) { + index_sub_tables_[index_sub_tables_.size()].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 &atomic_subtables; + return NULL; } } // namespace sfntly diff --git a/sfntly/table/bitmap/bitmap_size_table.h b/sfntly/table/bitmap/bitmap_size_table.h index ee58bca..2bc91da 100644 --- a/sfntly/table/bitmap/bitmap_size_table.h +++ b/sfntly/table/bitmap/bitmap_size_table.h @@ -17,28 +17,120 @@ #ifndef SFNTLY_CPP_SRC_SFNTLY_TABLE_BITMAP_BITMAP_SIZE_TABLE_H_ #define SFNTLY_CPP_SRC_SFNTLY_TABLE_BITMAP_BITMAP_SIZE_TABLE_H_ -#include - #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: - // Note: C++ port take two ReadableFontData. The first is sliced data, and - // the second is unsliced data. The second one is used to correctly - // construct index sub tables since Java version calculate the offset - // based on unsliced data. - BitmapSizeTable(ReadableFontData* data, - ReadableFontData* master_data); + 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(); + + // Note: renamed from indexSubTable() + IndexSubTable::Builder* GetIndexSubTable(int32_t index); + 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); + 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(); @@ -48,22 +140,31 @@ class BitmapSizeTable : public SubTable, // 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(); - ReadableFontDataPtr master_data_; - Lock atomic_subtables_lock_; - IndexSubTableList atomic_subtables; + Lock index_subtables_lock_; + IndexSubTableList index_subtables_; }; typedef Ptr BitmapSizeTablePtr; typedef std::vector BitmapSizeTableList; +typedef Ptr BitmapSizeTableBuilderPtr; +typedef std::vector BitmapSizeTableBuilderList; } // namespace sfntly diff --git a/sfntly/table/bitmap/composite_bitmap_glyph.cc b/sfntly/table/bitmap/composite_bitmap_glyph.cc index bd680e4..ae7dc5a 100644 --- a/sfntly/table/bitmap/composite_bitmap_glyph.cc +++ b/sfntly/table/bitmap/composite_bitmap_glyph.cc @@ -86,4 +86,24 @@ CompositeBitmapGlyph::Component::Component(int32_t glyph_code, : 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/sfntly/table/bitmap/composite_bitmap_glyph.h b/sfntly/table/bitmap/composite_bitmap_glyph.h index 0521213..897db7e 100644 --- a/sfntly/table/bitmap/composite_bitmap_glyph.h +++ b/sfntly/table/bitmap/composite_bitmap_glyph.h @@ -47,6 +47,16 @@ class CompositeBitmapGlyph : public BitmapGlyph, 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(); diff --git a/sfntly/table/bitmap/ebdt_table.cc b/sfntly/table/bitmap/ebdt_table.cc index a131f5a..75a5080 100644 --- a/sfntly/table/bitmap/ebdt_table.cc +++ b/sfntly/table/bitmap/ebdt_table.cc @@ -16,6 +16,8 @@ #include "sfntly/table/bitmap/ebdt_table.h" +#include + #include "sfntly/table/bitmap/composite_bitmap_glyph.h" #include "sfntly/table/bitmap/simple_bitmap_glyph.h" @@ -32,28 +34,9 @@ int32_t EbdtTable::Version() { CALLER_ATTACH BitmapGlyph* EbdtTable::Glyph(int32_t offset, int32_t length, int32_t format) { - ReadableFontDataPtr new_data; - new_data.Attach(down_cast(data_->Slice(offset, length))); - BitmapGlyphPtr glyph; - switch (format) { - case 1: - case 2: - case 3: - case 4: - case 5: - case 6: - case 7: - glyph = new SimpleBitmapGlyph(new_data, format); - break; - case 8: - case 9: - glyph = new CompositeBitmapGlyph(new_data, format); - break; - default: - assert(false); - break; - } - return glyph.Detach(); + ReadableFontDataPtr glyph_data; + glyph_data.Attach(down_cast(data_->Slice(offset, length))); + return BitmapGlyph::CreateGlyph(glyph_data, format); } EbdtTable::EbdtTable(Header* header, ReadableFontData* data) @@ -81,20 +64,113 @@ CALLER_ATTACH FontDataTable* } void EbdtTable::Builder::SubDataSet() { - // NOP + Revert(); } int32_t EbdtTable::Builder::SubDataSizeToSerialize() { - return 0; + 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() { - return false; + if (glyph_builders_.empty()) { + return false; + } + return true; } int32_t EbdtTable::Builder::SubSerialize(WritableFontData* new_data) { - UNREFERENCED_PARAMETER(new_data); - return 0; + 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(); + 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; + } + } + + output->resize(glyph_builders_.size()); + 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 @@ -105,5 +181,57 @@ EbdtTable::Builder* EbdtTable::Builder::CreateBuilder(Header* header, 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(); + output->resize(loca_list->size()); + 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->start_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/sfntly/table/bitmap/ebdt_table.h b/sfntly/table/bitmap/ebdt_table.h index 998541e..723c3f9 100644 --- a/sfntly/table/bitmap/ebdt_table.h +++ b/sfntly/table/bitmap/ebdt_table.h @@ -18,6 +18,7 @@ #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 { @@ -40,8 +41,48 @@ class EbdtTable : public SubTableContainerTable, 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(); @@ -51,14 +92,14 @@ class EbdtTable : public SubTableContainerTable, int32_t format); protected: - EbdtTable(Header* header, ReadableFontData* data); - - private: struct Offset { enum { kVersion = 0, + kHeaderLength = DataSize::kFixed, }; }; + + EbdtTable(Header* header, ReadableFontData* data); }; typedef Ptr EbdtTablePtr; diff --git a/sfntly/table/bitmap/eblc_table.cc b/sfntly/table/bitmap/eblc_table.cc index decbadf..bb36db0 100644 --- a/sfntly/table/bitmap/eblc_table.cc +++ b/sfntly/table/bitmap/eblc_table.cc @@ -16,6 +16,10 @@ #include "sfntly/table/bitmap/eblc_table.h" +#include + +#include "sfntly/math/font_math.h" + namespace sfntly { /****************************************************************************** * EblcTable class @@ -67,8 +71,12 @@ void EblcTable::CreateBitmapSizeTable(ReadableFontData* data, data->Slice(Offset::kBitmapSizeTableArrayStart + i * Offset::kBitmapSizeTableLength, Offset::kBitmapSizeTableLength))); - BitmapSizeTablePtr new_table = new BitmapSizeTable(new_data, data); - output->push_back(new_table); + 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); } } @@ -87,20 +95,163 @@ EblcTable::Builder::~Builder() { } int32_t EblcTable::Builder::SubSerialize(WritableFontData* new_data) { - UNREFERENCED_PARAMETER(new_data); - return 0; + // 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); + 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() { - return false; + 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() { - return 0; + if (size_table_builders_.empty()) { + return 0; + } + int32_t size = Offset::kHeaderLength; + bool variable = false; + for (BitmapSizeTableBuilderList::iterator b = size_table_builders_.begin(), + e = size_table_builders_.end(); + b != e; b++) { + int32_t size_builder_size = (*b)->SubDataSizeToSerialize(); + variable = size_builder_size > 0 ? variable : true; + size += abs(size_builder_size); + } + return -size; + // TODO(stuartg): need to fix to get size calculated accurately + // return variable ? -size : size; } void EblcTable::Builder::SubDataSet() { - // NOP + 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(); + output->resize(size_builder_list->size()); +#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 @@ -116,4 +267,38 @@ CALLER_ATTACH EblcTable::Builder* 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/sfntly/table/bitmap/eblc_table.h b/sfntly/table/bitmap/eblc_table.h index 84831ef..f8f052d 100644 --- a/sfntly/table/bitmap/eblc_table.h +++ b/sfntly/table/bitmap/eblc_table.h @@ -32,9 +32,10 @@ class EblcTable : public SubTableContainerTable, // header kVersion = 0, kNumSizes = 4, + kHeaderLength = kNumSizes + DataSize::kULONG, // bitmapSizeTable - kBitmapSizeTableArrayStart = 8, + kBitmapSizeTableArrayStart = kHeaderLength, kBitmapSizeTableLength = 48, kBitmapSizeTable_indexSubTableArrayOffset = 0, kBitmapSizeTable_indexTableSize = 4, @@ -95,6 +96,9 @@ class EblcTable : public SubTableContainerTable, kIndexSubTable4_numGlyphs = kIndexSubHeaderLength, kIndexSubTable4_glyphArray = kIndexSubTable4_numGlyphs + DataSize::kULONG, + kIndexSubTable4_codeOffsetPairLength = 2 * DataSize::kUSHORT, + kIndexSubTable4_codeOffsetPair_glyphCode = 0, + kIndexSubTable4_codeOffsetPair_offset = DataSize::kUSHORT, // kIndexSubTable5 kIndexSubTable5_imageSize = kIndexSubHeaderLength, @@ -127,8 +131,31 @@ class EblcTable : public SubTableContainerTable, 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(); @@ -137,11 +164,14 @@ class EblcTable : public SubTableContainerTable, 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); diff --git a/sfntly/table/bitmap/ebsc_table.cc b/sfntly/table/bitmap/ebsc_table.cc new file mode 100644 index 0000000..458c2d4 --- /dev/null +++ b/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/sfntly/table/bitmap/ebsc_table.h b/sfntly/table/bitmap/ebsc_table.h new file mode 100644 index 0000000..43088fd --- /dev/null +++ b/sfntly/table/bitmap/ebsc_table.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_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 is minimally functional + // -just builds from initial data + // - need to make fully working + 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/sfntly/table/bitmap/glyph_metrics.cc b/sfntly/table/bitmap/glyph_metrics.cc new file mode 100644 index 0000000..e91eb99 --- /dev/null +++ b/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/sfntly/table/bitmap/glyph_metrics.h b/sfntly/table/bitmap/glyph_metrics.h new file mode 100644 index 0000000..5f16aaa --- /dev/null +++ b/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/sfntly/table/bitmap/index_sub_table.cc b/sfntly/table/bitmap/index_sub_table.cc index 329179d..66d2d83 100644 --- a/sfntly/table/bitmap/index_sub_table.cc +++ b/sfntly/table/bitmap/index_sub_table.cc @@ -24,30 +24,31 @@ #include "sfntly/table/bitmap/index_sub_table_format5.h" namespace sfntly { - -bool IndexSubTable::CheckGlyphRange(int32_t glyph_id) { - if (glyph_id < first_glyph_index() || glyph_id > last_glyph_index()) { -#if !defined (SFNTLY_NO_EXCEPTION) - throw IndexOutOfBoundException("Glyph ID is outside of the allowed range"); -#endif - return false; +/****************************************************************************** + * IndexSubTable class + ******************************************************************************/ +CALLER_ATTACH BitmapGlyphInfo* IndexSubTable::GlyphInfo(int32_t glyph_id) { + int32_t loca = CheckGlyphRange(glyph_id); + if (loca == -1) { + return NULL; } - return true; + 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(); } -template -static IndexSubTableType* CreateTable(ReadableFontData* data, - int32_t index_sub_table_offset, - int32_t first_glyph_index, - int32_t last_glyph_index) { - ReadableFontDataPtr new_data; - new_data.Attach(down_cast( - data->Slice(index_sub_table_offset, - IndexSubTableType::GetDataLength(data, - index_sub_table_offset, - first_glyph_index, - last_glyph_index)))); - return new IndexSubTableType(new_data, first_glyph_index, last_glyph_index); +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 @@ -55,10 +56,65 @@ 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()); +} + +int32_t IndexSubTable::Builder::GlyphOffset(int32_t glyph_id) { + return image_data_offset() + GlyphStartOffset(glyph_id); +} + +// 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); @@ -68,49 +124,25 @@ CALLER_ATTACH IndexSubTable* 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); - IndexSubTablePtr new_table; - ReadableFontDataPtr new_data; switch (index_format) { case 1: - new_table = CreateTable(data, - index_sub_table_offset, - first_glyph_index, - last_glyph_index); - break; - + return IndexSubTableFormat1::Builder::CreateBuilder( + data, index_sub_table_offset, first_glyph_index, last_glyph_index); case 2: - new_table = CreateTable(data, - index_sub_table_offset, - first_glyph_index, - last_glyph_index); - break; - + return IndexSubTableFormat2::Builder::CreateBuilder( + data, index_sub_table_offset, first_glyph_index, last_glyph_index); case 3: - new_table = CreateTable(data, - index_sub_table_offset, - first_glyph_index, - last_glyph_index); - break; - + return IndexSubTableFormat3::Builder::CreateBuilder( + data, index_sub_table_offset, first_glyph_index, last_glyph_index); case 4: - new_table = CreateTable(data, - index_sub_table_offset, - first_glyph_index, - last_glyph_index); - break; - + return IndexSubTableFormat4::Builder::CreateBuilder( + data, index_sub_table_offset, first_glyph_index, last_glyph_index); case 5: - new_table = CreateTable(data, - index_sub_table_offset, - first_glyph_index, - last_glyph_index); - break; - + 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) @@ -118,20 +150,82 @@ CALLER_ATTACH IndexSubTable* #endif break; } + return NULL; +} - return new_table.Detach(); +CALLER_ATTACH +FontDataTable* IndexSubTable::Builder::SubBuildTable(ReadableFontData* data) { + UNREFERENCED_PARAMETER(data); + return NULL; } -IndexSubTable::IndexSubTable(ReadableFontData* data, - int32_t first, - int32_t last) - : SubTable(data), first_glyph_index_(first), last_glyph_index_(last) { +void IndexSubTable::Builder::SubDataSet() { +} + +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(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); +} + +IndexSubTable::Builder::Builder(int32_t index_format, + int32_t image_format, + int32_t image_data_offset) + : index_format_(index_format), + image_format_(image_format), + image_data_offset_(image_data_offset) { +} + +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); + data->ReadUShort(EblcTable::Offset::kIndexSubHeader_indexFormat); image_format_ = - data_->ReadUShort(EblcTable::Offset::kIndexSubHeader_imageFormat); + data->ReadUShort(EblcTable::Offset::kIndexSubHeader_imageFormat); image_data_offset_ = - data_->ReadULongAsInt(EblcTable::Offset::kIndexSubHeader_imageDataOffset); + data->ReadULongAsInt(EblcTable::Offset::kIndexSubHeader_imageDataOffset); } } // namespace sfntly diff --git a/sfntly/table/bitmap/index_sub_table.h b/sfntly/table/bitmap/index_sub_table.h index 253f165..c2be7d1 100644 --- a/sfntly/table/bitmap/index_sub_table.h +++ b/sfntly/table/bitmap/index_sub_table.h @@ -19,18 +19,106 @@ #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: + 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 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(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(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); + Builder(int32_t index_format, + int32_t image_format, + int32_t image_data_offset); + + // 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_; } - virtual int32_t GlyphOffset(int32_t glyph_id) = 0; + 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; @@ -44,10 +132,14 @@ class IndexSubTable : public SubTable { // 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, int32_t last); + IndexSubTable(ReadableFontData* data, + int32_t first_glyph_index, + int32_t last_glyph_index); - // Note: change return type to bool in C++ since we may not throw. - bool CheckGlyphRange(int32_t glyph_id); + 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_; @@ -58,6 +150,10 @@ class IndexSubTable : public SubTable { }; typedef Ptr IndexSubTablePtr; typedef std::vector IndexSubTableList; +typedef Ptr IndexSubTableBuilderPtr; +typedef std::vector IndexSubTableBuilderList; +typedef Iterator BitmapGlyphInfoIter; +typedef Ptr BitmapGlyphInfoIterPtr; } // namespace sfntly diff --git a/sfntly/table/bitmap/index_sub_table_format1.cc b/sfntly/table/bitmap/index_sub_table_format1.cc index b98655a..809412d 100644 --- a/sfntly/table/bitmap/index_sub_table_format1.cc +++ b/sfntly/table/bitmap/index_sub_table_format1.cc @@ -19,7 +19,9 @@ #include "sfntly/table/bitmap/eblc_table.h" namespace sfntly { - +/****************************************************************************** + * IndexSubTableFormat1 class + ******************************************************************************/ // static int32_t IndexSubTableFormat1::GetDataLength(ReadableFontData* data, int32_t offset, @@ -30,12 +32,6 @@ int32_t IndexSubTableFormat1::GetDataLength(ReadableFontData* data, return (last - first + 1 + 1) * DataSize::kULONG; } -IndexSubTableFormat1::IndexSubTableFormat1(ReadableFontData* data, - int32_t first, - int32_t last) - : IndexSubTable(data, first, last) { -} - IndexSubTableFormat1::~IndexSubTableFormat1() { } @@ -43,25 +39,242 @@ int32_t IndexSubTableFormat1::NumGlyphs() { return last_glyph_index() - first_glyph_index() + 1; } -int32_t IndexSubTableFormat1::GlyphOffset(int32_t glyph_id) { - if (CheckGlyphRange(glyph_id)) { - return Loca(glyph_id); +int32_t IndexSubTableFormat1::GlyphStartOffset(int32_t glyph_id) { + int32_t loca = CheckGlyphRange(glyph_id); + if (loca == -1) { + return -1; } - return -1; + return Loca(loca); } int32_t IndexSubTableFormat1::GlyphLength(int32_t glyph_id) { - if (CheckGlyphRange(glyph_id)) { - return Loca(glyph_id + 1) - Loca(glyph_id); + int32_t loca = CheckGlyphRange(glyph_id); + if (loca == -1) { + return -1; } - return -1; + return Loca(loca + 1) - Loca(loca); } -int32_t IndexSubTableFormat1::Loca(int32_t loca_index) { +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_index - first_glyph_index()) * - DataSize::kULONG); + 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 +BitmapGlyphInfoIter* IndexSubTableFormat1::Builder::GetIterator() { + Ptr it = + new IndexSubTableFormat1::Builder::BitmapGlyphInfoIterator(this); + return it.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 0; + } + 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()) { + 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); + return size; + } + for (IntegerList::iterator b = GetOffsetArray()->begin(), + e = GetOffsetArray()->end(); b != e; b++) { + size += new_data->WriteLong(size, *b); + } + return size; +} + +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(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/sfntly/table/bitmap/index_sub_table_format1.h b/sfntly/table/bitmap/index_sub_table_format1.h index 3329bc9..c36bf18 100644 --- a/sfntly/table/bitmap/index_sub_table_format1.h +++ b/sfntly/table/bitmap/index_sub_table_format1.h @@ -17,32 +17,96 @@ #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: - static int32_t GetDataLength(ReadableFontData* data, - int32_t offset, - int32_t first, - int32_t last); + 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 BitmapGlyphInfoIter* 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); + CALLER_ATTACH BitmapGlyphInfoIter* Iterator(); + + 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(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_; + }; - // 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. - IndexSubTableFormat1(ReadableFontData* data, int32_t first, int32_t last); virtual ~IndexSubTableFormat1(); virtual int32_t NumGlyphs(); - virtual int32_t GlyphOffset(int32_t glyph_id); + 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 diff --git a/sfntly/table/bitmap/index_sub_table_format2.cc b/sfntly/table/bitmap/index_sub_table_format2.cc index 82deef3..e54481b 100644 --- a/sfntly/table/bitmap/index_sub_table_format2.cc +++ b/sfntly/table/bitmap/index_sub_table_format2.cc @@ -19,17 +19,29 @@ #include "sfntly/table/bitmap/eblc_table.h" namespace sfntly { +/****************************************************************************** + * IndexSubTableFormat2 class + ******************************************************************************/ +IndexSubTableFormat2::~IndexSubTableFormat2() { +} -// static -int32_t IndexSubTableFormat2::GetDataLength(ReadableFontData* data, - int32_t offset, - int32_t first, - int32_t last) { - UNREFERENCED_PARAMETER(data); - UNREFERENCED_PARAMETER(offset); - UNREFERENCED_PARAMETER(first); - UNREFERENCED_PARAMETER(last); - return EblcTable::Offset::kIndexSubTable2Length; +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, @@ -40,25 +52,183 @@ IndexSubTableFormat2::IndexSubTableFormat2(ReadableFontData* data, data_->ReadULongAsInt(EblcTable::Offset::kIndexSubTable2_imageSize); } -IndexSubTableFormat2::~IndexSubTableFormat2() { +/****************************************************************************** + * IndexSubTableFormat2::Builder class + ******************************************************************************/ +IndexSubTableFormat2::Builder::~Builder() { } -int32_t IndexSubTableFormat2::NumGlyphs() { +int32_t IndexSubTableFormat2::Builder::NumGlyphs() { return last_glyph_index() - first_glyph_index() + 1; } -int32_t IndexSubTableFormat2::GlyphOffset(int32_t glyph_id) { - if (CheckGlyphRange(glyph_id)) { - return image_data_offset() + (glyph_id - first_glyph_index()) * image_size_; +int32_t IndexSubTableFormat2::Builder::GlyphStartOffset(int32_t glyph_id) { + int32_t loca = CheckGlyphRange(glyph_id); + if (loca == -1) { + return -1; } - return -1; + return loca * ImageSize(); } -int32_t IndexSubTableFormat2::GlyphLength(int32_t glyph_id) { - if (CheckGlyphRange(glyph_id)) { - return image_size_; +int32_t IndexSubTableFormat2::Builder::GlyphLength(int32_t glyph_id) { + int32_t loca = CheckGlyphRange(glyph_id); + if (loca == -1) { + return 0; + } + return ImageSize(); +} + +CALLER_ATTACH +BitmapGlyphInfoIter* 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); +} + +CALLER_ATTACH BigGlyphMetrics* IndexSubTableFormat2::Builder::BigMetrics() { + WritableFontDataPtr data; + data.Attach(down_cast(InternalWriteData()->Slice( + EblcTable::Offset::kIndexSubTable2_bigGlyphMetrics, + BigGlyphMetrics::Offset::kMetricsLength))); + BigGlyphMetricsPtr output = new BigGlyphMetrics(data); + 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() { +} + +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); + ReadableFontDataPtr source; + WritableFontDataPtr target; + source.Attach(down_cast(InternalReadData()->Slice(size))); + target.Attach(down_cast(new_data->Slice(size))); + size += source->CopyTo(target); + return size; +} + +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; } - return -1; + 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/sfntly/table/bitmap/index_sub_table_format2.h b/sfntly/table/bitmap/index_sub_table_format2.h index b325ccd..7b13d60 100644 --- a/sfntly/table/bitmap/index_sub_table_format2.h +++ b/sfntly/table/bitmap/index_sub_table_format2.h @@ -18,33 +18,81 @@ #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: - static int32_t GetDataLength(ReadableFontData* data, - int32_t offset, - int32_t first, - int32_t last); - - // 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. - IndexSubTableFormat2(ReadableFontData* data, int32_t first, int32_t last); + 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 BitmapGlyphInfoIter* 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); + CALLER_ATTACH BigGlyphMetrics* BigMetrics(); + + 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(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); + }; + virtual ~IndexSubTableFormat2(); virtual int32_t NumGlyphs(); - virtual int32_t GlyphOffset(int32_t glyph_id); + virtual int32_t GlyphStartOffset(int32_t glyph_id); virtual int32_t GlyphLength(int32_t glyph_id); private: - int32_t Loca(int32_t loca_index); + IndexSubTableFormat2(ReadableFontData* data, int32_t first, int32_t last); int32_t image_size_; + friend class Builder; }; +typedef Ptr IndexSubTableFormat2Ptr; +typedef Ptr IndexSubTableFormat2BuilderPtr; } // namespace sfntly diff --git a/sfntly/table/bitmap/index_sub_table_format3.cc b/sfntly/table/bitmap/index_sub_table_format3.cc index 4fa529e..75ff14c 100644 --- a/sfntly/table/bitmap/index_sub_table_format3.cc +++ b/sfntly/table/bitmap/index_sub_table_format3.cc @@ -19,6 +19,31 @@ #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, @@ -31,37 +56,225 @@ int32_t IndexSubTableFormat3::GetDataLength(ReadableFontData* data, } IndexSubTableFormat3::IndexSubTableFormat3(ReadableFontData* data, - int32_t first, - int32_t last) - : IndexSubTable(data, first, last) { + int32_t first_glyph_index, + int32_t last_glyph_index) + : IndexSubTable(data, first_glyph_index, last_glyph_index) { } -IndexSubTableFormat3::~IndexSubTableFormat3() { +int32_t IndexSubTableFormat3::Loca(int32_t loca) { + int32_t read_offset = + data_->ReadUShort(EblcTable::Offset::kIndexSubTable3_offsetArray + + loca * DataSize::kUSHORT); + return read_offset; } -int32_t IndexSubTableFormat3::NumGlyphs() { - return last_glyph_index() - first_glyph_index() + 1; +/****************************************************************************** + * IndexSubTableFormat3::Builder class + ******************************************************************************/ +IndexSubTableFormat3::Builder::~Builder() { +} + +int32_t IndexSubTableFormat3::Builder::NumGlyphs() { + return GetOffsetArray()->size() - 1; } -int32_t IndexSubTableFormat3::GlyphOffset(int32_t glyph_id) { - if (CheckGlyphRange(glyph_id)) { - return Loca(glyph_id); +int32_t IndexSubTableFormat3::Builder::GlyphStartOffset(int32_t glyph_id) { + int32_t loca = CheckGlyphRange(glyph_id); + if (loca == -1) { + return -1; } - return -1; + return GetOffsetArray()->at(loca); } -int32_t IndexSubTableFormat3::GlyphLength(int32_t glyph_id) { - if (CheckGlyphRange(glyph_id)) { - return Loca(glyph_id + 1) - Loca(glyph_id); +int32_t IndexSubTableFormat3::Builder::GlyphLength(int32_t glyph_id) { + int32_t loca = CheckGlyphRange(glyph_id); + if (loca == -1) { + return 0; } - return -1; + IntegerList* offset_array = GetOffsetArray(); + return offset_array->at(loca + 1) - offset_array->at(loca); } -int32_t IndexSubTableFormat3::Loca(int32_t loca_index) { - int32_t read_offset = - data_->ReadUShort(EblcTable::Offset::kIndexSubTable3_offsetArray + - (loca_index - first_glyph_index()) * DataSize::kUSHORT); - return image_data_offset() + read_offset; +CALLER_ATTACH +BitmapGlyphInfoIter* 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(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 0; + } + 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()) { + 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); + return size; + } + for (IntegerList::iterator b = GetOffsetArray()->begin(), + e = GetOffsetArray()->end(); b != e; b++) { + size += new_data->WriteUShort(size, *b); + } + return size; +} + +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->ReadULongAsInt( + EblcTable::Offset::kIndexSubTable3_offsetArray + + i * DataSize::kULONG)); + } + } +} + +// 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/sfntly/table/bitmap/index_sub_table_format3.h b/sfntly/table/bitmap/index_sub_table_format3.h index 1e45f23..2c4004c 100644 --- a/sfntly/table/bitmap/index_sub_table_format3.h +++ b/sfntly/table/bitmap/index_sub_table_format3.h @@ -20,29 +20,91 @@ #include "sfntly/table/bitmap/index_sub_table.h" namespace sfntly { - +// Format 3 Index Subtable Entry. class IndexSubTableFormat3 : public IndexSubTable, public RefCounted { public: - static int32_t GetDataLength(ReadableFontData* data, - int32_t offset, - int32_t first, - int32_t last); + 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 BitmapGlyphInfoIter* 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(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(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_; + }; - // 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. - IndexSubTableFormat3(ReadableFontData* data, int32_t first, int32_t last); virtual ~IndexSubTableFormat3(); virtual int32_t NumGlyphs(); - virtual int32_t GlyphOffset(int32_t glyph_id); + 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 diff --git a/sfntly/table/bitmap/index_sub_table_format4.cc b/sfntly/table/bitmap/index_sub_table_format4.cc index 9ef681c..efa5f28 100644 --- a/sfntly/table/bitmap/index_sub_table_format4.cc +++ b/sfntly/table/bitmap/index_sub_table_format4.cc @@ -19,18 +19,49 @@ #include "sfntly/table/bitmap/eblc_table.h" namespace sfntly { +/****************************************************************************** + * IndexSubTableFormat4 class + ******************************************************************************/ +IndexSubTableFormat4::~IndexSubTableFormat4() { +} -// static -int32_t IndexSubTableFormat4::GetDataLength(ReadableFontData* data, - int32_t offset, - int32_t first, - int32_t last) { - UNREFERENCED_PARAMETER(first); - UNREFERENCED_PARAMETER(last); - assert(data); - return data->ReadULongAsInt(offset + - EblcTable::Offset::kIndexSubTable4_numGlyphs) * - EblcTable::Offset::kCodeOffsetPairLength; +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, @@ -39,50 +70,293 @@ IndexSubTableFormat4::IndexSubTableFormat4(ReadableFontData* data, : IndexSubTable(data, first, last) { } -IndexSubTableFormat4::~IndexSubTableFormat4() { +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() { - return data_->ReadULongAsInt(EblcTable::Offset::kIndexSubTable4_numGlyphs); +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( + 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 +BitmapGlyphInfoIter* IndexSubTableFormat4::Builder::GetIterator() { + Ptr it = + new IndexSubTableFormat4::Builder::BitmapGlyphInfoIterator(this); + return it.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 0; + } + return EblcTable::Offset::kIndexSubHeaderLength + DataSize::kULONG + + GetOffsetArray()->size() * + EblcTable::Offset::kIndexSubTable4_codeOffsetPair_offset; +} + +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()) { + 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); + return size; + } + + 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(WritableFontData* data, + int32_t first_glyph_index, + int32_t last_glyph_index) + : IndexSubTable::Builder(data, first_glyph_index, last_glyph_index) { } -int32_t IndexSubTableFormat4::GlyphOffset(int32_t glyph_id) { - if (CheckGlyphRange(glyph_id)) { - int32_t pair_index = FindCodeOffsetPair(glyph_id); - if (pair_index < 0) { - return -1; +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); + CodeOffsetPairBuilder pair_builder(glyph_code, glyph_offset); + offset_pair_array_.push_back(pair_builder); } - return data_->ReadUShort( - EblcTable::Offset::kIndexSubTable4_glyphArray + - pair_index * EblcTable::Offset::kCodeOffsetPairLength + - EblcTable::Offset::kCodeOffsetPair_offset); } - return -1; } -int32_t IndexSubTableFormat4::GlyphLength(int32_t glyph_id) { - if (CheckGlyphRange(glyph_id)) { - int32_t pair_index = FindCodeOffsetPair(glyph_id); - if (pair_index < 0) { - return -1; +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 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); } return -1; } -int32_t IndexSubTableFormat4::FindCodeOffsetPair(int32_t glyph_id) { - return data_->SearchUShort(EblcTable::Offset::kIndexSubTable4_glyphArray, - EblcTable::Offset::kCodeOffsetPairLength, - NumGlyphs(), - glyph_id); +// 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/sfntly/table/bitmap/index_sub_table_format4.h b/sfntly/table/bitmap/index_sub_table_format4.h index 821acca..258998d 100644 --- a/sfntly/table/bitmap/index_sub_table_format4.h +++ b/sfntly/table/bitmap/index_sub_table_format4.h @@ -24,25 +24,112 @@ namespace sfntly { class IndexSubTableFormat4 : public IndexSubTable, public RefCounted { public: - static int32_t GetDataLength(ReadableFontData* data, - int32_t offset, - int32_t first, - int32_t last); - - // 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. - IndexSubTableFormat4(ReadableFontData* data, int32_t first, int32_t last); + 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 Builder; + class CodeOffsetPairBuilder : public CodeOffsetPair { + public: + void set_glyph_code(int32_t v) { glyph_code_ = v; } + void set_offset(int32_t v) { offset_ = v; } + + private: + CodeOffsetPairBuilder(int32_t glyph_code, int32_t offset); + + friend class Builder; + }; + + 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 BitmapGlyphInfoIter* 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(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(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 GlyphOffset(int32_t glyph_id); + 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; } // namespace sfntly diff --git a/sfntly/table/bitmap/index_sub_table_format5.cc b/sfntly/table/bitmap/index_sub_table_format5.cc index a2aed5c..7ba78ec 100644 --- a/sfntly/table/bitmap/index_sub_table_format5.cc +++ b/sfntly/table/bitmap/index_sub_table_format5.cc @@ -16,50 +16,324 @@ #include "sfntly/table/bitmap/index_sub_table_format5.h" +#include + #include "sfntly/table/bitmap/eblc_table.h" namespace sfntly { +/****************************************************************************** + * IndexSubTableFormat5 class + ******************************************************************************/ +IndexSubTableFormat5::~IndexSubTableFormat5() { +} -// static -int32_t IndexSubTableFormat5::GetDataLength(ReadableFontData* data, - int32_t offset, - int32_t first, - int32_t last) { - UNREFERENCED_PARAMETER(first); - UNREFERENCED_PARAMETER(last); - assert(data); - return data->ReadULongAsInt(offset + - EblcTable::Offset::kIndexSubTable5_numGlyphs) * - EblcTable::Offset::kCodeOffsetPairLength; +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_bigMetrics, + BigGlyphMetrics::Offset::kMetricsLength))); + BigGlyphMetricsPtr output = new BigGlyphMetrics(data); + return output.Detach(); } IndexSubTableFormat5::IndexSubTableFormat5(ReadableFontData* data, - int32_t first, - int32_t last) - : IndexSubTable(data, first, last) { + 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); } -IndexSubTableFormat5::~IndexSubTableFormat5() { +// static +int32_t IndexSubTableFormat5::NumGlyphs(ReadableFontData* data, + int32_t table_offset) { + UNREFERENCED_PARAMETER(table_offset); + int32_t num_glyphs = data->ReadULongAsInt( + EblcTable::Offset::kIndexSubTable5_numGlyphs); + return num_glyphs; } -int32_t IndexSubTableFormat5::NumGlyphs() { - return data_->ReadULongAsInt(EblcTable::Offset::kIndexSubTable5_numGlyphs); +/****************************************************************************** + * IndexSubTableFormat5::Builder class + ******************************************************************************/ +IndexSubTableFormat5::Builder::~Builder() { } -int32_t IndexSubTableFormat5::GlyphOffset(int32_t glyph_id) { - if (CheckGlyphRange(glyph_id)) { - return data_->ReadUShort( - EblcTable::Offset::kIndexSubTable5_glyphArray + - glyph_id * DataSize::kUSHORT); +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 -1; + return (it - glyph_array->begin()) * ImageSize(); } -int32_t IndexSubTableFormat5::GlyphLength(int32_t glyph_id) { - if (CheckGlyphRange(glyph_id)) { - return data_->ReadULongAsInt(EblcTable::Offset::kIndexSubTable5_imageSize); +CALLER_ATTACH +BitmapGlyphInfoIter* IndexSubTableFormat5::Builder::GetIterator() { + Ptr it = + new IndexSubTableFormat5::Builder::BitmapGlyphInfoIterator(this); + return it.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() { + if (model_changed()) { + Initialize(InternalReadData()); + } +} + +int32_t IndexSubTableFormat5::Builder::SubDataSizeToSerialize() { + if (glyph_array_.empty()) { + return 0; + } + return EblcTable::Offset::kIndexSubHeaderLength + + 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); + return size; + } else { + ReadableFontDataPtr source; + WritableFontDataPtr target; + source.Attach(down_cast(InternalReadData()->Slice( + EblcTable::Offset::kIndexSubTable5_imageSize, + EblcTable::Offset::kIndexSubTable5_numGlyphs))); + target.Attach(down_cast(new_data->Slice( + EblcTable::Offset::kIndexSubTable5_imageSize, + EblcTable::Offset::kIndexSubTable5_numGlyphs))); + size += source->CopyTo(target); + } + + size += new_data->WriteLong(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); +} + +CALLER_ATTACH +BigGlyphMetrics::Builder* IndexSubTableFormat5::Builder::BigMetrics() { + WritableFontDataPtr data; + data.Attach(down_cast(InternalWriteData()->Slice( + EblcTable::Offset::kIndexSubTable5_bigMetrics, + BigGlyphMetrics::Offset::kMetricsLength))); + BigGlyphMetricsBuilderPtr output = new BigGlyphMetrics::Builder(data); + return output.Detach(); +} + +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(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->ReadULongAsInt( + 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; } - return -1; + 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/sfntly/table/bitmap/index_sub_table_format5.h b/sfntly/table/bitmap/index_sub_table_format5.h index 354834e..c480fd8 100644 --- a/sfntly/table/bitmap/index_sub_table_format5.h +++ b/sfntly/table/bitmap/index_sub_table_format5.h @@ -17,6 +17,7 @@ #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 { @@ -24,22 +25,90 @@ namespace sfntly { class IndexSubTableFormat5 : public IndexSubTable, public RefCounted { public: - static int32_t GetDataLength(ReadableFontData* data, - int32_t offset, - int32_t first, - int32_t last); - - // 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. - IndexSubTableFormat5(ReadableFontData* data, int32_t first, int32_t last); + 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 BitmapGlyphInfoIter* 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); + CALLER_ATTACH BigGlyphMetrics::Builder* BigMetrics(); + IntegerList* GlyphArray(); + void SetGlyphArray(const IntegerList& v); + + 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(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_; + }; virtual ~IndexSubTableFormat5(); virtual int32_t NumGlyphs(); - virtual int32_t GlyphOffset(int32_t glyph_id); + 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 diff --git a/sfntly/table/bitmap/simple_bitmap_glyph.cc b/sfntly/table/bitmap/simple_bitmap_glyph.cc index 85364fd..87031a1 100644 --- a/sfntly/table/bitmap/simple_bitmap_glyph.cc +++ b/sfntly/table/bitmap/simple_bitmap_glyph.cc @@ -25,4 +25,21 @@ SimpleBitmapGlyph::SimpleBitmapGlyph(ReadableFontData* data, int32_t 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/sfntly/table/bitmap/simple_bitmap_glyph.h b/sfntly/table/bitmap/simple_bitmap_glyph.h index 48bca98..56ede10 100644 --- a/sfntly/table/bitmap/simple_bitmap_glyph.h +++ b/sfntly/table/bitmap/simple_bitmap_glyph.h @@ -24,9 +24,20 @@ 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 diff --git a/sfntly/table/bitmap/small_glyph_metrics.cc b/sfntly/table/bitmap/small_glyph_metrics.cc new file mode 100644 index 0000000..0f3c1e9 --- /dev/null +++ b/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/sfntly/table/bitmap/small_glyph_metrics.h b/sfntly/table/bitmap/small_glyph_metrics.h new file mode 100644 index 0000000..ea13720 --- /dev/null +++ b/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/sfntly/table/byte_array_table_builder.cc b/sfntly/table/byte_array_table_builder.cc new file mode 100644 index 0000000..631a05f --- /dev/null +++ b/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/sfntly/table/byte_array_table_builder.h b/sfntly/table/byte_array_table_builder.h new file mode 100644 index 0000000..42d27a8 --- /dev/null +++ b/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/sfntly/table/core/name_table.cc b/sfntly/table/core/name_table.cc index 9853130..5f6d5a5 100644 --- a/sfntly/table/core/name_table.cc +++ b/sfntly/table/core/name_table.cc @@ -227,27 +227,31 @@ bool NameTable::NameEntryFilterInPlace::Accept(int32_t platform_id, /****************************************************************************** * NameTable::NameEntryIterator class ******************************************************************************/ -NameTable::NameEntryIterator::NameEntryIterator(NameTable* table) { - Init(table, NULL); +NameTable::NameEntryIterator::NameEntryIterator(NameTable* table) + : RefIterator(table), + name_index_(0), + filter_(NULL) { } NameTable::NameEntryIterator::NameEntryIterator(NameTable* table, - NameEntryFilter* filter) { - Init(table, filter); + NameEntryFilter* filter) + : RefIterator(table), + name_index_(0), + filter_(filter) { } bool NameTable::NameEntryIterator::HasNext() { if (!filter_) { - if (name_index_ < table_->NameCount()) { + if (name_index_ < container()->NameCount()) { return true; } return false; } - for (; name_index_ < table_->NameCount(); ++name_index_) { - if (filter_->Accept(table_->PlatformId(name_index_), - table_->EncodingId(name_index_), - table_->LanguageId(name_index_), - table_->NameId(name_index_))) { + 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; } } @@ -257,21 +261,7 @@ bool NameTable::NameEntryIterator::HasNext() { CALLER_ATTACH NameTable::NameEntry* NameTable::NameEntryIterator::Next() { if (!HasNext()) return NULL; - return table_->GetNameEntry(name_index_++); -} - -void NameTable::NameEntryIterator::Remove() { -#if !defined (SFNTLY_NO_EXCEPTION) - throw UnsupportedOperationException( - "Cannot remove a name table from an existing font."); -#endif -} - -void NameTable::NameEntryIterator::Init(NameTable* table, - NameEntryFilter* filter) { - table_ = table; - filter_ = filter; - name_index_ = 0; + return container()->GetNameEntry(name_index_++); } /****************************************************************************** @@ -423,10 +413,11 @@ int32_t NameTable::Builder::SubSerialize(WritableFontData* new_data) { void NameTable::Builder::Initialize(ReadableFontData* data) { if (data) { NameTablePtr table = new NameTable(header(), data); - NameEntryIterator name_iter(table, NULL); - while (name_iter.HasNext()) { + Ptr name_iter; + name_iter.Attach(table->Iterator()); + while (name_iter->HasNext()) { NameEntryPtr name_entry; - name_entry.Attach(name_iter.Next()); + 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(); @@ -532,21 +523,25 @@ CALLER_ATTACH NameTable::NameEntry* NameTable::GetNameEntry(int32_t platform_id, int32_t name_id) { NameTable::NameEntryFilterInPlace filter(platform_id, encoding_id, language_id, name_id); - NameTable::NameEntryIterator* name_entry_iter = Iterator(&filter); + Ptr name_entry_iter; + name_entry_iter.Attach(Iterator(&filter)); NameEntryPtr result; if (name_entry_iter->HasNext()) { result = name_entry_iter->Next(); } - delete name_entry_iter; return result; } -NameTable::NameEntryIterator* NameTable::Iterator() { - return new NameTable::NameEntryIterator(this); +CALLER_ATTACH NameTable::NameEntryIterator* NameTable::Iterator() { + Ptr output = new NameTable::NameEntryIterator(this); + return output.Detach(); } +CALLER_ATTACH NameTable::NameEntryIterator* NameTable::Iterator(NameEntryFilter* filter) { - return new NameTable::NameEntryIterator(this, filter); + Ptr output = + new NameTable::NameEntryIterator(this, filter); + return output.Detach(); } NameTable::NameTable(Header* header, ReadableFontData* data) diff --git a/sfntly/table/core/name_table.h b/sfntly/table/core/name_table.h index 0c657da..9c007a1 100644 --- a/sfntly/table/core/name_table.h +++ b/sfntly/table/core/name_table.h @@ -26,6 +26,7 @@ #include #include +#include "sfntly/port/java_iterator.h" #include "sfntly/table/subtable_container_table.h" #if defined U_USING_ICU_NAMESPACE @@ -555,23 +556,17 @@ class NameTable : public SubTableContainerTable, public RefCounted { int32_t name_id_; }; - // Mimic Java's iterator to iterate through the entries within the name table. - class NameEntryIterator { + class NameEntryIterator : public RefIterator { public: // If filter is NULL, filter through all tables. explicit NameEntryIterator(NameTable* table); NameEntryIterator(NameTable* table, NameEntryFilter* filter); - // Make gcc -Wnon-virtual-dtor happy. virtual ~NameEntryIterator() {} virtual bool HasNext(); virtual CALLER_ATTACH NameEntry* Next(); - virtual void Remove(); private: - void Init(NameTable* table, NameEntryFilter* filter); - - NameTable* table_; // Use dumb pointer since it's a composition object. int32_t name_index_; NameEntryFilter* filter_; }; @@ -686,9 +681,8 @@ class NameTable : public SubTableContainerTable, public RefCounted { // virtual void names(std::set*); // Get the iterator to iterate through all name entries. - // Note: Caller delete the returned object. - virtual NameEntryIterator* Iterator(); - virtual NameEntryIterator* Iterator(NameEntryFilter* filter); + virtual CALLER_ATTACH NameEntryIterator* Iterator(); + virtual CALLER_ATTACH NameEntryIterator* Iterator(NameEntryFilter* filter); private: struct Offset { diff --git a/sfntly/table/font_data_table.cc b/sfntly/table/font_data_table.cc index 0197bbd..7953269 100644 --- a/sfntly/table/font_data_table.cc +++ b/sfntly/table/font_data_table.cc @@ -53,6 +53,9 @@ 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(); @@ -80,6 +83,9 @@ CALLER_ATTACH FontDataTable* FontDataTable::Builder::Build() { 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(); @@ -113,9 +119,17 @@ WritableFontData* FontDataTable::Builder::InternalWriteData() { WritableFontDataPtr new_data; new_data.Attach(WritableFontData::CreateWritableFontData( r_data_ == NULL ? 0 : r_data_->Length())); - if (r_data_) { - r_data_->CopyTo(new_data); +#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_; diff --git a/sfntly/table/generic_table_builder.cc b/sfntly/table/generic_table_builder.cc new file mode 100644 index 0000000..78e6797 --- /dev/null +++ b/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/sfntly/table/generic_table_builder.h b/sfntly/table/generic_table_builder.h new file mode 100644 index 0000000..a100ea0 --- /dev/null +++ b/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/sfntly/table/header.h b/sfntly/table/header.h index 117da95..280e556 100644 --- a/sfntly/table/header.h +++ b/sfntly/table/header.h @@ -22,7 +22,7 @@ namespace sfntly { class Header : public RefCounted
{ - public: + public: // Make a partial header with only the basic info for an empty new table. explicit Header(int32_t tag); @@ -36,7 +36,10 @@ class Header : public RefCounted
{ // Get the table tag. int32_t tag() { return tag_; } - // Get the table offset. The offset is from the start of the font file. + // 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 @@ -44,12 +47,15 @@ class Header : public RefCounted
{ // font file. bool offset_valid() { return offset_valid_; } - // Get the length of the table as recorded in the table record header. + // 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. + // 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. @@ -65,7 +71,7 @@ class Header : public RefCounted
{ // int hashCode() // string toString() - private: + private: int32_t tag_; int32_t offset_; bool offset_valid_; diff --git a/sfntly/table/subtable.cc b/sfntly/table/subtable.cc index d70b18c..b990c7c 100644 --- a/sfntly/table/subtable.cc +++ b/sfntly/table/subtable.cc @@ -22,6 +22,11 @@ namespace sfntly { ******************************************************************************/ 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) { } @@ -29,7 +34,23 @@ SubTable::SubTable(ReadableFontData* data) /****************************************************************************** * SubTable::Builder class ******************************************************************************/ -SubTable::Builder::~Builder() {} +SubTable::Builder::Builder() { +} + +SubTable::Builder::~Builder() { +} + +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) { diff --git a/sfntly/table/subtable.h b/sfntly/table/subtable.h index e5ec748..fbfb4b0 100644 --- a/sfntly/table/subtable.h +++ b/sfntly/table/subtable.h @@ -29,24 +29,43 @@ class SubTable : public FontDataTable { public: class Builder : public FontDataTable::Builder { public: + // Creates a new empty sub-table. + Builder(); virtual ~Builder(); protected: - Builder(WritableFontData* data); - Builder(ReadableFontData* data); + // @param data the data for the subtable being built + // @param master_data the data for the full table + 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(); 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_; }; diff --git a/sfntly/table/table.cc b/sfntly/table/table.cc index 6cfe1f8..f1ff63d 100644 --- a/sfntly/table/table.cc +++ b/sfntly/table/table.cc @@ -31,6 +31,7 @@ #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" diff --git a/sfntly/table/table_based_table_builder.cc b/sfntly/table/table_based_table_builder.cc index 6e6a46a..b505704 100644 --- a/sfntly/table/table_based_table_builder.cc +++ b/sfntly/table/table_based_table_builder.cc @@ -18,7 +18,6 @@ namespace sfntly { - /****************************************************************************** * TableBasedTableBuilder class ******************************************************************************/ @@ -67,27 +66,4 @@ Table* TableBasedTableBuilder::GetTable() { return table_; } -/****************************************************************************** - * GenericTableBuilder class - ******************************************************************************/ -GenericTableBuilder::GenericTableBuilder(Header* header, - WritableFontData* data) - : TableBasedTableBuilder(header, data) { -} - -CALLER_ATTACH FontDataTable* - GenericTableBuilder::SubBuildTable(ReadableFontData* data) { - // Note: In C++ port, we use GenericTable, the ref-counted version of Table - UNREFERENCED_PARAMETER(data); - FontDataTablePtr table = new GenericTable(this->header(), InternalReadData()); - return table.Detach(); -} - -CALLER_ATTACH GenericTableBuilder* - GenericTableBuilder::CreateBuilder(Header* header, WritableFontData* data) { - Ptr builder = - new GenericTableBuilder(header, data); - return builder.Detach(); -} - } // namespace sfntly diff --git a/sfntly/table/table_based_table_builder.h b/sfntly/table/table_based_table_builder.h index 3868d46..d88eefd 100644 --- a/sfntly/table/table_based_table_builder.h +++ b/sfntly/table/table_based_table_builder.h @@ -34,7 +34,7 @@ class TableBasedTableBuilder : public Table::Builder { protected: TableBasedTableBuilder(Header* header, WritableFontData* data); TableBasedTableBuilder(Header* header, ReadableFontData* data); - TableBasedTableBuilder(Header* header); + explicit TableBasedTableBuilder(Header* header); // C++ port: renamed table() to GetTable() virtual Table* GetTable(); @@ -43,17 +43,6 @@ class TableBasedTableBuilder : public Table::Builder { TablePtr table_; }; -class GenericTableBuilder : public TableBasedTableBuilder, - public RefCounted { - public: - GenericTableBuilder(Header* header, WritableFontData* data); - virtual CALLER_ATTACH FontDataTable* SubBuildTable(ReadableFontData* data); - - static CALLER_ATTACH - GenericTableBuilder* CreateBuilder(Header* header, - WritableFontData* data); -}; - } // namespace sfntly #endif // SFNTLY_CPP_SRC_SFNTLY_TABLE_TABLE_BASED_TABLE_BUILDER_H_ diff --git a/sfntly/table/truetype/glyph_table.cc b/sfntly/table/truetype/glyph_table.cc index dc1163a..bec9c89 100644 --- a/sfntly/table/truetype/glyph_table.cc +++ b/sfntly/table/truetype/glyph_table.cc @@ -162,10 +162,6 @@ void GlyphTable::Builder::Initialize(ReadableFontData* data, const IntegerList& loca) { if (data != NULL) { if (loca_.empty()) { -#if !defined (SFNTLY_NO_EXCEPTION) - throw IllegalStateException( - "Loca values not set - unable to parse glyph data."); -#endif return; } int32_t loca_value; @@ -186,6 +182,13 @@ void GlyphTable::Builder::Initialize(ReadableFontData* data, 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(); } diff --git a/sfntly/table/truetype/glyph_table.h b/sfntly/table/truetype/glyph_table.h index 3ba9cac..f8a7c33 100644 --- a/sfntly/table/truetype/glyph_table.h +++ b/sfntly/table/truetype/glyph_table.h @@ -53,8 +53,8 @@ class GlyphTable : public SubTableContainerTable, // Incoming table_builder is GlyphTable::Builder*. // Note: constructor refactored in C++ to avoid heavy lifting. // caller need to do data->Slice(offset, length) beforehand. - Builder(WritableFontData* data); - Builder(ReadableFontData* data); + explicit Builder(WritableFontData* data); + explicit Builder(ReadableFontData* data); static CALLER_ATTACH Builder* GetBuilder(GlyphTable::Builder* table_builder, @@ -128,7 +128,12 @@ class GlyphTable : public SubTableContainerTable, // invalid, then an empty glyph builder List will be returned. GlyphBuilderList* GlyphBuilders(); - // Replace the internal glyph builders with the one provided. + // 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 @@ -173,8 +178,8 @@ class GlyphTable : public SubTableContainerTable, protected: // Note: constructor refactored in C++ to avoid heavy lifting. // caller need to do data->Slice(offset, length) beforehand. - SimpleGlyphBuilder(WritableFontData* data); - SimpleGlyphBuilder(ReadableFontData* data); + explicit SimpleGlyphBuilder(WritableFontData* data); + explicit SimpleGlyphBuilder(ReadableFontData* data); virtual CALLER_ATTACH FontDataTable* SubBuildTable(ReadableFontData* data); @@ -244,8 +249,8 @@ class GlyphTable : public SubTableContainerTable, protected: // Note: constructor refactored in C++ to avoid heavy lifting. // caller need to do data->Slice(offset, length) beforehand. - CompositeGlyphBuilder(WritableFontData* data); - CompositeGlyphBuilder(ReadableFontData* data); + explicit CompositeGlyphBuilder(WritableFontData* data); + explicit CompositeGlyphBuilder(ReadableFontData* data); virtual CALLER_ATTACH FontDataTable* SubBuildTable(ReadableFontData* data); diff --git a/sfntly/table/truetype/loca_table.cc b/sfntly/table/truetype/loca_table.cc index 0a579ae..c692155 100644 --- a/sfntly/table/truetype/loca_table.cc +++ b/sfntly/table/truetype/loca_table.cc @@ -73,16 +73,15 @@ LocaTable::LocaTable(Header* header, * LocaTable::Iterator class ******************************************************************************/ LocaTable::LocaIterator::LocaIterator(LocaTable* table) - : index_(-1) { - table_ = table; + : PODIterator(table), index_(-1) { } bool LocaTable::LocaIterator::HasNext() { - return index_ <= table_->num_glyphs_; + return index_ <= container()->num_glyphs_; } int32_t LocaTable::LocaIterator::Next() { - return table_->Loca(index_++); + return container()->Loca(index_++); } /****************************************************************************** @@ -118,29 +117,22 @@ void LocaTable::Builder::SetLocaList(IntegerList* list) { loca_.clear(); if (list) { loca_ = *list; - num_glyphs_ = loca_.size(); set_model_changed(); } } int32_t LocaTable::Builder::GlyphOffset(int32_t glyph_id) { - if (glyph_id < 0 || glyph_id > (num_glyphs_ + 1)) { -#if !defined (SFNTLY_NO_EXCEPTION) - throw IndexOutOfBoundException("Glyph ID is out of bounds."); -#endif + if (CheckGlyphRange(glyph_id) == -1) { return 0; } - return Loca(glyph_id); + return GetLocaList()->at(glyph_id); } int32_t LocaTable::Builder::GlyphLength(int32_t glyph_id) { - if (glyph_id < 0 || glyph_id > (num_glyphs_ + 1)) { -#if !defined (SFNTLY_NO_EXCEPTION) - throw IndexOutOfBoundException("Glyph ID is out of bounds."); -#endif + if (CheckGlyphRange(glyph_id) == -1) { return 0; } - return Loca(glyph_id + 1) - Loca(glyph_id); + return GetLocaList()->at(glyph_id + 1) - GetLocaList()->at(glyph_id); } void LocaTable::Builder::SetNumGlyphs(int32_t num_glyphs) { @@ -148,10 +140,7 @@ void LocaTable::Builder::SetNumGlyphs(int32_t num_glyphs) { } int32_t LocaTable::Builder::NumGlyphs() { - if (!loca_.empty()) { - return loca_.size() - 1; - } - return num_glyphs_; + return LastGlyphIndex() - 1; } void LocaTable::Builder::Revert() { @@ -202,10 +191,12 @@ int32_t LocaTable::Builder::SubSerialize(WritableFontData* new_data) { size += new_data->WriteUShort(size, *l / 2); } } - return 0; + 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) @@ -215,13 +206,28 @@ void LocaTable::Builder::Initialize(ReadableFontData* data) { } LocaTablePtr table = new LocaTable(header(), data, format_version_, num_glyphs_); - LocaTable::LocaIterator loca_iter(table); - while (loca_iter.HasNext()) { - loca_.push_back(loca_iter.Next()); + 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()); @@ -230,4 +236,11 @@ IntegerList* LocaTable::Builder::GetLocaList() { 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/sfntly/table/truetype/loca_table.h b/sfntly/table/truetype/loca_table.h index 0ec13bd..67c5749 100644 --- a/sfntly/table/truetype/loca_table.h +++ b/sfntly/table/truetype/loca_table.h @@ -17,6 +17,7 @@ #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" @@ -25,17 +26,16 @@ namespace sfntly { // A Loca table - 'loca'. class LocaTable : public Table, public RefCounted { public: - // Note: different implementation than Java, caller to instantiate this class - // object directly from stack instead of calling LocaTable::iterator(). - class LocaIterator { + class LocaIterator : public PODIterator { public: explicit LocaIterator(LocaTable* table); - bool HasNext(); - int32_t Next(); + virtual ~LocaIterator() {} + + virtual bool HasNext(); + virtual int32_t Next(); private: int32_t index_; - LocaTable* table_; // use dumb pointer since it's a composition object }; class Builder : public Table::Builder, public RefCounted { @@ -83,7 +83,8 @@ class LocaTable : public Table, public RefCounted { // 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. + // 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. @@ -119,11 +120,19 @@ class LocaTable : public Table, public RefCounted { // @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_; diff --git a/test/font_parsing_test.cc b/test/font_parsing_test.cc index 60c5524..6fd5c3b 100644 --- a/test/font_parsing_test.cc +++ b/test/font_parsing_test.cc @@ -22,6 +22,7 @@ #include "sfntly/font_factory.h" #include "sfntly/table/core/font_header_table.h" #include "sfntly/table/table.h" +#include "sfntly/table/generic_table_builder.h" #include "sfntly/table/table_based_table_builder.h" #include "sfntly/tag.h" #include "sfntly/port/file_input_stream.h" -- cgit v1.2.3 From be87cfe77f08387d23cabc3a403fa53531b687a8 Mon Sep 17 00:00:00 2001 From: "arthurhsu@google.com" Date: Tue, 18 Oct 2011 19:32:16 +0000 Subject: Update to 10-12-11 snapshot Created new chrome_subsetter program to test font subsetter used in Chromium Fix several porting bugs in previous CL git-svn-id: http://sfntly.googlecode.com/svn/trunk/cpp/src@101 672e30a5-4c29-85ac-ac6d-611c735e0a51 --- sample/chromium/chrome_subsetter.cc | 131 +++++ sfntly/table/bitmap/bitmap_size_table.cc | 4 +- sfntly/table/bitmap/ebdt_table.cc | 3 +- sfntly/table/bitmap/ebdt_table.h | 31 +- sfntly/table/bitmap/eblc_table.cc | 1 - sfntly/table/bitmap/eblc_table.h | 1 + sfntly/table/bitmap/ebsc_table.h | 5 +- sfntly/table/bitmap/index_sub_table_format1.cc | 8 +- sfntly/table/bitmap/index_sub_table_format1.h | 3 +- sfntly/table/bitmap/index_sub_table_format2.cc | 4 +- sfntly/table/bitmap/index_sub_table_format2.h | 2 +- sfntly/table/bitmap/index_sub_table_format3.cc | 8 +- sfntly/table/bitmap/index_sub_table_format3.h | 2 +- sfntly/table/bitmap/index_sub_table_format4.cc | 8 +- sfntly/table/bitmap/index_sub_table_format4.h | 9 +- sfntly/table/bitmap/index_sub_table_format5.cc | 9 +- sfntly/table/bitmap/index_sub_table_format5.h | 2 +- sfntly/table/subtable.h | 2 +- sfntly/table/truetype/glyph_table.cc | 23 +- sfntly/table/truetype/glyph_table.h | 15 +- sfntly/tag.h | 4 +- test/bitmap_table_test.cc | 21 +- test/subsetter_impl.cc | 642 +++++++++++++++++++++---- test/subsetter_impl.h | 13 +- 24 files changed, 786 insertions(+), 165 deletions(-) create mode 100644 sample/chromium/chrome_subsetter.cc diff --git a/sample/chromium/chrome_subsetter.cc b/sample/chromium/chrome_subsetter.cc new file mode 100644 index 0000000..6f5788e --- /dev/null +++ b/sample/chromium/chrome_subsetter.cc @@ -0,0 +1,131 @@ +/* + * 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 + +#include "sfntly/port/type.h" +#include "test/font_subsetter.h" + +template +class HexTo { + public: + explicit HexTo(const char* in) { + std::stringstream ss; + ss << std::hex << in; + ss >> value_; + } + operator T() const { return value_; } + + private: + T value_; +}; + +bool LoadFile(const char* input_file_path, sfntly::ByteVector* input_buffer) { + assert(input_file_path); + assert(input_buffer); + + FILE* input_file = NULL; +#if defined WIN32 + fopen_s(&input_file, input_file_path, "rb"); +#else + input_file = fopen(input_file_path, "rb"); +#endif + if (input_file == NULL) { + return false; + } + fseek(input_file, 0, SEEK_END); + size_t file_size = ftell(input_file); + fseek(input_file, 0, SEEK_SET); + input_buffer->resize(file_size); + size_t bytes_read = fread(&((*input_buffer)[0]), 1, file_size, input_file); + fclose(input_file); + return bytes_read == file_size; +} + +bool SaveFile(const char* output_file_path, const unsigned char* output_buffer, + int buffer_length) { + int byte_count = 0; + if (buffer_length > 0) { + FILE* output_file = NULL; +#if defined WIN32 + fopen_s(&output_file, output_file_path, "wb"); +#else + output_file = fopen(output_file_path, "wb"); +#endif + if (output_file) { + byte_count = fwrite(output_buffer, 1, buffer_length, output_file); + fflush(output_file); + fclose(output_file); + } + return buffer_length == byte_count; + } + return false; +} + +bool StringToGlyphId(const char* input, std::vector* glyph_ids) { + assert(input); + std::string hex_csv = input; + size_t start = 0; + size_t end = hex_csv.find_first_of(","); + while (end != std::string::npos) { + glyph_ids->push_back( + HexTo(hex_csv.substr(start, end - start).c_str())); + start = end + 1; + end = hex_csv.find_first_of(",", start); + } + glyph_ids->push_back(HexTo(hex_csv.substr(start).c_str())); + return glyph_ids->size() > 0; +} + +int main(int argc, char** argv) { + if (argc < 5) { + fprintf(stderr, + "Usage: %s \n", + argv[0]); + fprintf(stderr, "\tGlyph ids are comma separated hex values\n"); + fprintf(stderr, "\te.g. 20,1a,3b,4f\n"); + return 0; + } + + sfntly::ByteVector input_buffer; + if (!LoadFile(argv[1], &input_buffer)) { + fprintf(stderr, "ERROR: unable to load font file %s\n", argv[1]); + return 0; + } + + std::vector glyph_ids; + if (!StringToGlyphId(argv[4], &glyph_ids)) { + fprintf(stderr, "ERROR: unable to parse input glyph id\n"); + return 0; + } + + unsigned char* output_buffer = NULL; + int output_length = + SfntlyWrapper::SubsetFont(argv[3], + &(input_buffer[0]), + input_buffer.size(), + &(glyph_ids[0]), + glyph_ids.size(), + &output_buffer); + + int result = SaveFile(argv[2], output_buffer, output_length) ? 1 : 0; + delete[] output_buffer; + return result; +} diff --git a/sfntly/table/bitmap/bitmap_size_table.cc b/sfntly/table/bitmap/bitmap_size_table.cc index 93b8625..5e0c237 100644 --- a/sfntly/table/bitmap/bitmap_size_table.cc +++ b/sfntly/table/bitmap/bitmap_size_table.cc @@ -418,9 +418,9 @@ void BitmapSizeTable::Builder::Initialize(ReadableFontData* data) { 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_[index_sub_tables_.size()].Attach( - CreateIndexSubTableBuilder(i)); + index_sub_tables_[i].Attach(CreateIndexSubTableBuilder(i)); } } } diff --git a/sfntly/table/bitmap/ebdt_table.cc b/sfntly/table/bitmap/ebdt_table.cc index 75a5080..19e5e55 100644 --- a/sfntly/table/bitmap/ebdt_table.cc +++ b/sfntly/table/bitmap/ebdt_table.cc @@ -118,6 +118,7 @@ int32_t EbdtTable::Builder::SubSerialize(WritableFontData* new_data) { 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()); } @@ -131,7 +132,6 @@ void EbdtTable::Builder::GenerateLocaList(BitmapLocaList* output) { } } - output->resize(glyph_builders_.size()); int start_offset = Offset::kHeaderLength; for (BitmapGlyphBuilderList::iterator builder_map = glyph_builders_.begin(), builder_end = glyph_builders_.end(); @@ -211,7 +211,6 @@ void EbdtTable::Builder::Initialize(ReadableFontData* data, assert(output); output->clear(); - output->resize(loca_list->size()); if (data) { for (BitmapLocaList::iterator loca_map = loca_list->begin(), loca_end = loca_list->end(); diff --git a/sfntly/table/bitmap/ebdt_table.h b/sfntly/table/bitmap/ebdt_table.h index 723c3f9..79852c3 100644 --- a/sfntly/table/bitmap/ebdt_table.h +++ b/sfntly/table/bitmap/ebdt_table.h @@ -43,24 +43,24 @@ class EbdtTable : public SubTableContainerTable, 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. + + // 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. + // 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); @@ -102,6 +102,7 @@ class EbdtTable : public SubTableContainerTable, EbdtTable(Header* header, ReadableFontData* data); }; typedef Ptr EbdtTablePtr; +typedef Ptr EbdtTableBuilderPtr; } // namespace sfntly diff --git a/sfntly/table/bitmap/eblc_table.cc b/sfntly/table/bitmap/eblc_table.cc index bb36db0..6691b04 100644 --- a/sfntly/table/bitmap/eblc_table.cc +++ b/sfntly/table/bitmap/eblc_table.cc @@ -238,7 +238,6 @@ void EblcTable::Builder::GenerateLocaList(BitmapLocaList* output) { assert(output); BitmapSizeTableBuilderList* size_builder_list = GetSizeList(); output->clear(); - output->resize(size_builder_list->size()); #if defined (SFNTLY_DEBUG_BITMAP) int32_t size_index = 0; #endif diff --git a/sfntly/table/bitmap/eblc_table.h b/sfntly/table/bitmap/eblc_table.h index f8f052d..3a9b4c4 100644 --- a/sfntly/table/bitmap/eblc_table.h +++ b/sfntly/table/bitmap/eblc_table.h @@ -180,6 +180,7 @@ class EblcTable : public SubTableContainerTable, BitmapSizeTableList bitmap_size_table_; }; typedef Ptr EblcTablePtr; +typedef Ptr EblcTableBuilderPtr; } #endif // SFNTLY_CPP_SRC_SFNTLY_TABLE_BITMAP_EBLC_TABLE_H_ diff --git a/sfntly/table/bitmap/ebsc_table.h b/sfntly/table/bitmap/ebsc_table.h index 43088fd..b79df38 100644 --- a/sfntly/table/bitmap/ebsc_table.h +++ b/sfntly/table/bitmap/ebsc_table.h @@ -61,9 +61,8 @@ class EbscTable : public Table, explicit BitmapScaleTable(ReadableFontData* data); }; - // TODO(stuartg): currently the builder is minimally functional - // -just builds from initial data - // - need to make fully working + // 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: diff --git a/sfntly/table/bitmap/index_sub_table_format1.cc b/sfntly/table/bitmap/index_sub_table_format1.cc index 809412d..634fbb0 100644 --- a/sfntly/table/bitmap/index_sub_table_format1.cc +++ b/sfntly/table/bitmap/index_sub_table_format1.cc @@ -94,8 +94,8 @@ int32_t IndexSubTableFormat1::Builder::GlyphStartOffset(int32_t glyph_id) { return GetOffsetArray()->at(loca); } -CALLER_ATTACH -BitmapGlyphInfoIter* IndexSubTableFormat1::Builder::GetIterator() { +CALLER_ATTACH IndexSubTableFormat1::Builder::BitmapGlyphInfoIterator* + IndexSubTableFormat1::Builder::GetIterator() { Ptr it = new IndexSubTableFormat1::Builder::BitmapGlyphInfoIterator(this); return it.Detach(); @@ -188,6 +188,10 @@ int32_t IndexSubTableFormat1::Builder::SubSerialize( return size; } +IntegerList* IndexSubTableFormat1::Builder::OffsetArray() { + return GetOffsetArray(); +} + void IndexSubTableFormat1::Builder::SetOffsetArray( const IntegerList& offset_array) { offset_array_.clear(); diff --git a/sfntly/table/bitmap/index_sub_table_format1.h b/sfntly/table/bitmap/index_sub_table_format1.h index c36bf18..1078831 100644 --- a/sfntly/table/bitmap/index_sub_table_format1.h +++ b/sfntly/table/bitmap/index_sub_table_format1.h @@ -45,7 +45,7 @@ class IndexSubTableFormat1 : public IndexSubTable, virtual int32_t NumGlyphs(); virtual int32_t GlyphLength(int32_t glyph_id); virtual int32_t GlyphStartOffset(int32_t glyph_id); - CALLER_ATTACH virtual BitmapGlyphInfoIter* GetIterator(); + CALLER_ATTACH virtual BitmapGlyphInfoIterator* GetIterator(); virtual CALLER_ATTACH FontDataTable* SubBuildTable(ReadableFontData* data); virtual void SubDataSet(); @@ -53,6 +53,7 @@ class IndexSubTableFormat1 : public IndexSubTable, virtual bool SubReadyToSerialize(); virtual int32_t SubSerialize(WritableFontData* new_data); + IntegerList* OffsetArray(); void SetOffsetArray(const IntegerList& offset_array); CALLER_ATTACH BitmapGlyphInfoIter* Iterator(); diff --git a/sfntly/table/bitmap/index_sub_table_format2.cc b/sfntly/table/bitmap/index_sub_table_format2.cc index e54481b..58881f4 100644 --- a/sfntly/table/bitmap/index_sub_table_format2.cc +++ b/sfntly/table/bitmap/index_sub_table_format2.cc @@ -78,8 +78,8 @@ int32_t IndexSubTableFormat2::Builder::GlyphLength(int32_t glyph_id) { return ImageSize(); } -CALLER_ATTACH -BitmapGlyphInfoIter* IndexSubTableFormat2::Builder::GetIterator() { +CALLER_ATTACH IndexSubTableFormat2::Builder::BitmapGlyphInfoIterator* + IndexSubTableFormat2::Builder::GetIterator() { Ptr it = new IndexSubTableFormat2::Builder::BitmapGlyphInfoIterator(this); return it.Detach(); diff --git a/sfntly/table/bitmap/index_sub_table_format2.h b/sfntly/table/bitmap/index_sub_table_format2.h index 7b13d60..52a9ae0 100644 --- a/sfntly/table/bitmap/index_sub_table_format2.h +++ b/sfntly/table/bitmap/index_sub_table_format2.h @@ -45,7 +45,7 @@ class IndexSubTableFormat2 : public IndexSubTable, virtual int32_t NumGlyphs(); virtual int32_t GlyphStartOffset(int32_t glyph_id); virtual int32_t GlyphLength(int32_t glyph_id); - CALLER_ATTACH virtual BitmapGlyphInfoIter* GetIterator(); + CALLER_ATTACH virtual BitmapGlyphInfoIterator* GetIterator(); virtual CALLER_ATTACH FontDataTable* SubBuildTable(ReadableFontData* data); virtual void SubDataSet(); diff --git a/sfntly/table/bitmap/index_sub_table_format3.cc b/sfntly/table/bitmap/index_sub_table_format3.cc index 75ff14c..eedc500 100644 --- a/sfntly/table/bitmap/index_sub_table_format3.cc +++ b/sfntly/table/bitmap/index_sub_table_format3.cc @@ -95,8 +95,8 @@ int32_t IndexSubTableFormat3::Builder::GlyphLength(int32_t glyph_id) { return offset_array->at(loca + 1) - offset_array->at(loca); } -CALLER_ATTACH -BitmapGlyphInfoIter* IndexSubTableFormat3::Builder::GetIterator() { +CALLER_ATTACH IndexSubTableFormat3::Builder::BitmapGlyphInfoIterator* + IndexSubTableFormat3::Builder::GetIterator() { Ptr it = new IndexSubTableFormat3::Builder::BitmapGlyphInfoIterator(this); return it.Detach(); @@ -225,9 +225,9 @@ void IndexSubTableFormat3::Builder::Initialize(ReadableFontData* data) { 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( + offset_array_.push_back(data->ReadUShort( EblcTable::Offset::kIndexSubTable3_offsetArray + - i * DataSize::kULONG)); + i * DataSize::kUSHORT)); } } } diff --git a/sfntly/table/bitmap/index_sub_table_format3.h b/sfntly/table/bitmap/index_sub_table_format3.h index 2c4004c..e9f1fa2 100644 --- a/sfntly/table/bitmap/index_sub_table_format3.h +++ b/sfntly/table/bitmap/index_sub_table_format3.h @@ -44,7 +44,7 @@ class IndexSubTableFormat3 : public IndexSubTable, virtual int32_t NumGlyphs(); virtual int32_t GlyphStartOffset(int32_t glyph_id); virtual int32_t GlyphLength(int32_t glyph_id); - CALLER_ATTACH virtual BitmapGlyphInfoIter* GetIterator(); + CALLER_ATTACH virtual BitmapGlyphInfoIterator* GetIterator(); virtual CALLER_ATTACH FontDataTable* SubBuildTable(ReadableFontData* data); virtual void SubDataSet(); diff --git a/sfntly/table/bitmap/index_sub_table_format4.cc b/sfntly/table/bitmap/index_sub_table_format4.cc index efa5f28..898e288 100644 --- a/sfntly/table/bitmap/index_sub_table_format4.cc +++ b/sfntly/table/bitmap/index_sub_table_format4.cc @@ -92,6 +92,10 @@ IndexSubTableFormat4::CodeOffsetPair::CodeOffsetPair(int32_t glyph_code, : 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) { @@ -137,8 +141,8 @@ int32_t IndexSubTableFormat4::Builder::GlyphStartOffset(int32_t glyph_id) { return GetOffsetArray()->at(pair_index).offset(); } -CALLER_ATTACH -BitmapGlyphInfoIter* IndexSubTableFormat4::Builder::GetIterator() { +CALLER_ATTACH IndexSubTableFormat4::Builder::BitmapGlyphInfoIterator* + IndexSubTableFormat4::Builder::GetIterator() { Ptr it = new IndexSubTableFormat4::Builder::BitmapGlyphInfoIterator(this); return it.Detach(); diff --git a/sfntly/table/bitmap/index_sub_table_format4.h b/sfntly/table/bitmap/index_sub_table_format4.h index 258998d..be96628 100644 --- a/sfntly/table/bitmap/index_sub_table_format4.h +++ b/sfntly/table/bitmap/index_sub_table_format4.h @@ -40,12 +40,12 @@ class IndexSubTableFormat4 : public IndexSubTable, class Builder; 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; } private: - CodeOffsetPairBuilder(int32_t glyph_code, int32_t offset); - friend class Builder; }; @@ -74,7 +74,7 @@ class IndexSubTableFormat4 : public IndexSubTable, virtual int32_t NumGlyphs(); virtual int32_t GlyphLength(int32_t glyph_id); virtual int32_t GlyphStartOffset(int32_t glyph_id); - CALLER_ATTACH virtual BitmapGlyphInfoIter* GetIterator(); + CALLER_ATTACH virtual BitmapGlyphInfoIterator* GetIterator(); virtual CALLER_ATTACH FontDataTable* SubBuildTable(ReadableFontData* data); virtual void SubDataSet(); @@ -130,7 +130,8 @@ class IndexSubTableFormat4 : public IndexSubTable, }; 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/sfntly/table/bitmap/index_sub_table_format5.cc b/sfntly/table/bitmap/index_sub_table_format5.cc index 7ba78ec..1ddce05 100644 --- a/sfntly/table/bitmap/index_sub_table_format5.cc +++ b/sfntly/table/bitmap/index_sub_table_format5.cc @@ -79,8 +79,7 @@ IndexSubTableFormat5::IndexSubTableFormat5(ReadableFontData* data, // static int32_t IndexSubTableFormat5::NumGlyphs(ReadableFontData* data, int32_t table_offset) { - UNREFERENCED_PARAMETER(table_offset); - int32_t num_glyphs = data->ReadULongAsInt( + int32_t num_glyphs = data->ReadULongAsInt(table_offset + EblcTable::Offset::kIndexSubTable5_numGlyphs); return num_glyphs; } @@ -115,8 +114,8 @@ int32_t IndexSubTableFormat5::Builder::GlyphStartOffset(int32_t glyph_id) { return (it - glyph_array->begin()) * ImageSize(); } -CALLER_ATTACH -BitmapGlyphInfoIter* IndexSubTableFormat5::Builder::GetIterator() { +CALLER_ATTACH IndexSubTableFormat5::Builder::BitmapGlyphInfoIterator* + IndexSubTableFormat5::Builder::GetIterator() { Ptr it = new IndexSubTableFormat5::Builder::BitmapGlyphInfoIterator(this); return it.Detach(); @@ -282,7 +281,7 @@ void IndexSubTableFormat5::Builder::Initialize(ReadableFontData* data) { if (data) { int32_t num_glyphs = IndexSubTableFormat5::NumGlyphs(data, 0); for (int32_t i = 0; i < num_glyphs; ++i) { - glyph_array_.push_back(data->ReadULongAsInt( + glyph_array_.push_back(data->ReadUShort( EblcTable::Offset::kIndexSubTable5_glyphArray + i * DataSize::kUSHORT)); } diff --git a/sfntly/table/bitmap/index_sub_table_format5.h b/sfntly/table/bitmap/index_sub_table_format5.h index c480fd8..511f1fc 100644 --- a/sfntly/table/bitmap/index_sub_table_format5.h +++ b/sfntly/table/bitmap/index_sub_table_format5.h @@ -44,7 +44,7 @@ class IndexSubTableFormat5 : public IndexSubTable, virtual int32_t NumGlyphs(); virtual int32_t GlyphLength(int32_t glyph_id); virtual int32_t GlyphStartOffset(int32_t glyph_id); - CALLER_ATTACH virtual BitmapGlyphInfoIter* GetIterator(); + CALLER_ATTACH virtual BitmapGlyphInfoIterator* GetIterator(); virtual CALLER_ATTACH FontDataTable* SubBuildTable(ReadableFontData* data); virtual void SubDataSet(); diff --git a/sfntly/table/subtable.h b/sfntly/table/subtable.h index fbfb4b0..902d281 100644 --- a/sfntly/table/subtable.h +++ b/sfntly/table/subtable.h @@ -48,8 +48,8 @@ class SubTable : public FontDataTable { }; virtual ~SubTable(); + virtual int32_t Padding() { return padding_; } - 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; } diff --git a/sfntly/table/truetype/glyph_table.cc b/sfntly/table/truetype/glyph_table.cc index bec9c89..f38fac5 100644 --- a/sfntly/table/truetype/glyph_table.cc +++ b/sfntly/table/truetype/glyph_table.cc @@ -78,7 +78,6 @@ void GlyphTable::Builder::SetLoca(const IntegerList& loca) { void GlyphTable::Builder::GenerateLocaList(IntegerList* locas) { assert(locas); GlyphBuilderList* glyph_builders = GetGlyphBuilders(); - locas->resize(glyph_builders->size()); locas->push_back(0); if (glyph_builders->size() == 0) { locas->push_back(0); @@ -224,6 +223,11 @@ CALLER_ATTACH GlyphTable::Glyph* return glyph.Detach(); } +int32_t GlyphTable::Glyph::Padding() { + Initialize(); + return SubTable::Padding(); +} + int32_t GlyphTable::Glyph::GlyphType() { return glyph_type_; } @@ -332,7 +336,7 @@ int32_t GlyphTable::Glyph::Builder::SubSerialize(WritableFontData* new_data) { * GlyphTable::SimpleGlyph ******************************************************************************/ GlyphTable::SimpleGlyph::SimpleGlyph(ReadableFontData* data) - : GlyphTable::Glyph(data, GlyphType::kSimple) { + : GlyphTable::Glyph(data, GlyphType::kSimple), initialized_(false) { } GlyphTable::SimpleGlyph::~SimpleGlyph() { @@ -373,6 +377,7 @@ bool GlyphTable::SimpleGlyph::OnCurve(int32_t contour, int32_t point) { } void GlyphTable::SimpleGlyph::Initialize() { + AutoLock lock(initialization_lock_); if (initialized_) { return; } @@ -530,8 +535,9 @@ CALLER_ATTACH FontDataTable* GlyphTable::CompositeGlyph::CompositeGlyph(ReadableFontData* data) : GlyphTable::Glyph(data, GlyphType::kComposite), instruction_size_(0), - instructions_offset_(0) { - ParseData(); + instructions_offset_(0), + initialized_(false) { + Initialize(); } GlyphTable::CompositeGlyph::~CompositeGlyph() { @@ -607,7 +613,12 @@ CALLER_ATTACH ReadableFontData* GlyphTable::CompositeGlyph::Instructions() { data_->Slice(instructions_offset_, InstructionSize())); } -void GlyphTable::CompositeGlyph::ParseData() { +void GlyphTable::CompositeGlyph::Initialize() { + AutoLock lock(initialization_lock_); + if (initialized_) { + return; + } + int32_t index = 5 * DataSize::kUSHORT; int32_t flags = kFLAG_MORE_COMPONENTS; @@ -638,6 +649,8 @@ void GlyphTable::CompositeGlyph::ParseData() { } set_padding(DataLength() - non_padded_data_length); } + + initialized_ = true; } /****************************************************************************** diff --git a/sfntly/table/truetype/glyph_table.h b/sfntly/table/truetype/glyph_table.h index f8a7c33..0836971 100644 --- a/sfntly/table/truetype/glyph_table.h +++ b/sfntly/table/truetype/glyph_table.h @@ -79,6 +79,8 @@ class GlyphTable : public SubTableContainerTable, ReadableFontData* data, int32_t offset, int32_t length); + + virtual int32_t Padding(); virtual int32_t GlyphType(); virtual int32_t NumberOfContours(); virtual int32_t XMin(); @@ -93,6 +95,8 @@ class GlyphTable : public SubTableContainerTable, // 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, @@ -194,18 +198,20 @@ class GlyphTable : public SubTableContainerTable, 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 Initialize(); 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_; @@ -274,12 +280,15 @@ class GlyphTable : public SubTableContainerTable, virtual int32_t InstructionSize(); virtual CALLER_ATTACH ReadableFontData* Instructions(); - private: - void ParseData(); + protected: + virtual void Initialize(); + private: IntegerList contour_index_; int32_t instruction_size_; int32_t instructions_offset_; + bool initialized_; + Lock initialization_lock_; }; virtual ~GlyphTable(); diff --git a/sfntly/tag.h b/sfntly/tag.h index 87d2837..0ecbab8 100644 --- a/sfntly/tag.h +++ b/sfntly/tag.h @@ -50,7 +50,7 @@ struct Tag { static const int32_t CFF; static const int32_t VORG; - // bitmap glyph outlines + // opentype bitmap glyph outlines static const int32_t EBDT; static const int32_t EBLC; static const int32_t EBSC; @@ -88,7 +88,7 @@ struct Tag { static const int32_t Sile; static const int32_t Silf; - // Bitmap font tables + // truetype bitmap font tables static const int32_t bhed; static const int32_t bdat; static const int32_t bloc; diff --git a/test/bitmap_table_test.cc b/test/bitmap_table_test.cc index c8f239c..d5d718d 100644 --- a/test/bitmap_table_test.cc +++ b/test/bitmap_table_test.cc @@ -18,6 +18,7 @@ #include "sfntly/font.h" #include "sfntly/table/bitmap/ebdt_table.h" #include "sfntly/table/bitmap/eblc_table.h" +#include "sfntly/table/bitmap/index_sub_table_format3.h" #include "test/test_data.h" #include "test/test_font_utils.h" @@ -35,12 +36,14 @@ const int32_t STRIKE1_PPEM_Y = 10; const int32_t STRIKE1_BIT_DEPTH = 1; const int32_t STRIKE1_FLAGS = 0x01; +const int32_t STRIKE4_SUB1_INDEX_FORMAT = 3; const int32_t STRIKE4_SUB1_IMAGE_FORMAT = 1; const int32_t STRIKE4_SUB1_IMAGE_DATA_OFFSET = 0x00005893; const int32_t STRIKE4_SUB1_GLYPH_OFFSET[] = { 0x00005893, 0x00005898, 0x0000589d, 0x000058a2, 0x000058a7, 0x000058b2, 0x000058c2, 0x000058d0, 0x000058de, 0x000058e6 }; -const int32_t NUM_STRIKE4_SUB1_GLYPH_OFFSET = 10; // must be 1 less +const int32_t NUM_STRIKE4_SUB1_GLYPH_OFFSET = 10; +const int32_t STRIKE4_SUB1_GLYPH2_LENGTH = 0x58a2 - 0x589d; bool TestReadingBitmapTable() { FontFactoryPtr factory; @@ -79,15 +82,29 @@ bool TestReadingBitmapTable() { EXPECT_EQ(strike4->EndGlyphIndex(), STRIKE1_END_GLYPH_INDEX); IndexSubTablePtr sub1 = strike4->GetIndexSubTable(0); EXPECT_FALSE(sub1 == NULL); + EXPECT_EQ(sub1->index_format(), STRIKE4_SUB1_INDEX_FORMAT); + EXPECT_EQ(sub1->image_format(), STRIKE4_SUB1_IMAGE_FORMAT); EXPECT_EQ(sub1->first_glyph_index(), STRIKE1_START_GLYPH_INDEX); EXPECT_EQ(sub1->last_glyph_index(), STRIKE1_END_GLYPH_INDEX); - EXPECT_EQ(sub1->image_format(), STRIKE4_SUB1_IMAGE_FORMAT); EXPECT_EQ(sub1->image_data_offset(), STRIKE4_SUB1_IMAGE_DATA_OFFSET); for (int32_t i = 0; i < NUM_STRIKE4_SUB1_GLYPH_OFFSET; ++i) { EXPECT_EQ(sub1->GlyphOffset(i), STRIKE4_SUB1_GLYPH_OFFSET[i]); } + // Strike 4 Index Sub Table 1 is a Format 3 + IndexSubTableFormat3Ptr sub3 = + down_cast(strike4->GetIndexSubTable(0)); + EXPECT_FALSE(sub3 == NULL); + BitmapGlyphInfoPtr info; + info.Attach(sub3->GlyphInfo(2)); + EXPECT_EQ(info->glyph_id(), 2); + EXPECT_EQ(info->block_offset(), STRIKE4_SUB1_IMAGE_DATA_OFFSET); + EXPECT_EQ(info->start_offset(), + STRIKE4_SUB1_GLYPH_OFFSET[2] - STRIKE4_SUB1_GLYPH_OFFSET[0]); + EXPECT_EQ(info->format(), STRIKE4_SUB1_IMAGE_FORMAT); + EXPECT_EQ(info->length(), STRIKE4_SUB1_GLYPH2_LENGTH); + return true; } diff --git a/test/subsetter_impl.cc b/test/subsetter_impl.cc index f82a674..7934085 100644 --- a/test/subsetter_impl.cc +++ b/test/subsetter_impl.cc @@ -23,6 +23,14 @@ #include #include +#include "sfntly/table/bitmap/eblc_table.h" +#include "sfntly/table/bitmap/ebdt_table.h" +#include "sfntly/table/bitmap/index_sub_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" #include "sfntly/table/core/name_table.h" #include "sfntly/table/truetype/glyph_table.h" #include "sfntly/table/truetype/loca_table.h" @@ -34,7 +42,7 @@ namespace sfntly { void ConstructName(UChar* name_part, UnicodeString* name, int32_t name_id) { - switch(name_id) { + switch (name_id) { case NameId::kFullFontName: *name = name_part; break; @@ -73,80 +81,7 @@ int32_t HashCode(int32_t platform_id, int32_t encoding_id, int32_t language_id, return result; } -SubsetterImpl::SubsetterImpl() { -} - -SubsetterImpl::~SubsetterImpl() { -} - -bool SubsetterImpl::LoadFont(const char* font_name, - const unsigned char* original_font, - size_t font_size) { - MemoryInputStream mis; - mis.Attach(original_font, font_size); - if (factory_ == NULL) { - factory_.Attach(FontFactory::GetInstance()); - } - - FontArray font_array; - factory_->LoadFonts(&mis, &font_array); - font_ = FindFont(font_name, font_array); - if (font_ == NULL) { - return false; - } - - return true; -} - -int SubsetterImpl::SubsetFont(const unsigned int* glyph_ids, - size_t glyph_count, - unsigned char** output_buffer) { - if (factory_ == NULL || font_ == NULL) { - return -1; - } - - IntegerSet glyph_id_processed; - if (!ResolveCompositeGlyphs(glyph_ids, glyph_count, &glyph_id_processed) || - glyph_id_processed.empty()) { - return 0; - } - - FontPtr new_font; - new_font.Attach(Subset(glyph_id_processed)); - if (new_font == NULL) { - return 0; - } - - MemoryOutputStream output_stream; - factory_->SerializeFont(new_font, &output_stream); - int length = static_cast(output_stream.Size()); - if (length > 0) { - *output_buffer = new unsigned char[length]; - memcpy(*output_buffer, output_stream.Get(), length); - } - - return length; -} - -Font* SubsetterImpl::FindFont(const char* font_name, - const FontArray& font_array) { - if (font_array.empty() || font_array[0] == NULL) { - return NULL; - } - - if (font_name && strlen(font_name)) { - for (FontArray::const_iterator b = font_array.begin(), e = font_array.end(); - b != e; ++b) { - if (HasName(font_name, (*b).p_)) { - return (*b).p_; - } - } - } - - return font_array[0].p_; -} - -bool SubsetterImpl::HasName(const char* font_name, Font* font) { +bool HasName(const char* font_name, Font* font) { UnicodeString font_string = UnicodeString::fromUTF8(font_name); if (font_string.isEmpty()) return false; @@ -162,7 +97,7 @@ bool SubsetterImpl::HasName(const char* font_name, Font* font) { } for (int32_t i = 0; i < name_table->NameCount(); ++i) { - switch(name_table->NameId(i)) { + switch (name_table->NameId(i)) { case NameId::kFontFamilyName: case NameId::kFontSubfamilyName: case NameId::kFullFontName: @@ -195,22 +130,37 @@ bool SubsetterImpl::HasName(const char* font_name, Font* font) { return false; } -bool SubsetterImpl::ResolveCompositeGlyphs(const unsigned int* glyph_ids, - size_t glyph_count, - IntegerSet* glyph_id_processed) { - if (glyph_ids == NULL || glyph_count == 0 || glyph_id_processed == NULL) { - return false; +Font* FindFont(const char* font_name, const FontArray& font_array) { + if (font_array.empty() || font_array[0] == NULL) { + return NULL; } - // Find glyf and loca table. - 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) { - // The font is invalid. + if (font_name && strlen(font_name)) { + for (FontArray::const_iterator b = font_array.begin(), e = font_array.end(); + b != e; ++b) { + if (HasName(font_name, (*b).p_)) { + return (*b).p_; + } + } + } + + return font_array[0].p_; +} + +bool ResolveCompositeGlyphs(GlyphTable* glyf, + LocaTable* loca, + const unsigned int* glyph_ids, + size_t glyph_count, + IntegerSet* glyph_id_processed) { + if (glyf == NULL || loca == NULL || glyph_ids == NULL || glyph_count == 0 || + glyph_id_processed == NULL) { return false; } + // Find glyf and loca table. + GlyphTablePtr glyph_table = glyf; + LocaTablePtr loca_table = loca; + // Sort and uniquify glyph ids. IntegerSet glyph_id_remaining; glyph_id_remaining.insert(0); // Always include glyph id 0. @@ -265,23 +215,26 @@ bool SubsetterImpl::ResolveCompositeGlyphs(const unsigned int* glyph_ids, return true; } -CALLER_ATTACH Font* SubsetterImpl::Subset(const IntegerSet& glyph_ids) { - // The tables are already checked in ResolveCompositeGlyphs(). - GlyphTablePtr glyph_table = - down_cast(font_->GetTable(Tag::glyf)); - LocaTablePtr loca_table = down_cast(font_->GetTable(Tag::loca)); +bool SetupGlyfBuilders(Font::Builder* builder, + GlyphTable* glyf, + LocaTable* loca, + const IntegerSet& glyph_ids) { + if (!builder || !glyf || !loca) { + return false; + } - // Setup font builders we need. - FontBuilderPtr font_builder; - font_builder.Attach(factory_->NewFontBuilder()); + // The tables are already checked in ResolveCompositeGlyphs(). + GlyphTablePtr glyph_table = glyf; + LocaTablePtr loca_table = loca; + FontBuilderPtr font_builder = builder; 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) { // Out of memory. - return NULL; + return false; } // Extract glyphs and setup loca list. @@ -322,12 +275,499 @@ CALLER_ATTACH Font* SubsetterImpl::Subset(const IntegerSet& glyph_ids) { } loca_table_builder->SetLocaList(&loca_list); + return true; +} + +bool HasOverlap(int32_t range1_begin, int32_t range1_end, + int32_t range2_begin, int32_t range2_end) { + return (range2_begin < range1_end && range2_begin > range1_begin) || + (range1_begin < range2_end && range1_begin > range2_begin); +} + +// Initialize builder, returns false if glyph_id subset is not covered. +bool ShallSubset(EbdtTable::Builder* ebdt, EblcTable::Builder* eblc, + const IntegerSet& glyph_ids) { + EblcTableBuilderPtr eblc_builder = eblc; + EbdtTableBuilderPtr ebdt_builder = ebdt; + + BitmapLocaList loca_list; + BitmapSizeTableBuilderList* strikes = eblc_builder->BitmapSizeBuilders(); + + // Note: Do not call eblc_builder->GenerateLocaList(&loca_list) and then + // ebdt_builder->SetLoca(loca_list). For fonts like SimSun, there are + // >28K glyphs inside, where a typical usage will be <1K glyphs. Doing + // the calls inproperly will result in creation of >100K objects that + // will be destroyed immediately and result in significant slowness. + IntegerList removed_strikes; + for (size_t i = 0; i < strikes->size(); i++) { + if (!HasOverlap((*strikes)[i]->StartGlyphIndex(), + (*strikes)[i]->EndGlyphIndex(), + *(glyph_ids.begin()), *(glyph_ids.rbegin()))) { + removed_strikes.push_back(i); + continue; + } + + IndexSubTableBuilderList* index_builders = + (*strikes)[i]->IndexSubTableBuilders(); + IntegerList removed_indexes; + for (size_t j = 0; j < index_builders->size(); ++j) { + BitmapGlyphInfoMap info_map; + for (IntegerSet::const_iterator gid = glyph_ids.begin(), + gid_end = glyph_ids.end(); + gid != gid_end; gid++) { + if ((*index_builders)[j]->first_glyph_index() <= *gid && + (*index_builders)[j]->last_glyph_index() >= *gid && + (*index_builders)[j]->GlyphStartOffset(*gid) != -1) { + BitmapGlyphInfoPtr info = + new BitmapGlyphInfo(*gid, + (*index_builders)[j]->image_data_offset() + + (*index_builders)[j]->GlyphStartOffset(*gid), + (*index_builders)[j]->GlyphLength(*gid), + (*index_builders)[j]->image_format()); + info_map[*gid] = info; + } + } + if (!info_map.empty()) { + loca_list.push_back(info_map); + } else { + removed_indexes.push_back(j); + } + } + + // Remove unused index sub tables + for (IntegerList::reverse_iterator j = removed_indexes.rbegin(), + e = removed_indexes.rend(); + j != e; j++) { + index_builders->erase(index_builders->begin() + *j); + } + } + if (removed_strikes.size() == strikes->size() || loca_list.empty()) { + return false; // All strikes shall be gone. + } + + // Remove unused strikes + for (IntegerList::reverse_iterator j = removed_strikes.rbegin(), + e = removed_strikes.rend(); j != e; j++) { + strikes->erase(strikes->begin() + *j); + } + + ebdt_builder->SetLoca(&loca_list); + ebdt_builder->GlyphBuilders(); // Initialize the builder. + return true; +} + +void GenerateOffsetArray(int32_t first_gid, int32_t last_gid, + const BitmapGlyphInfoMap& loca, + IntegerList* new_offsets) { + int32_t offset = 0; + int32_t length = 0; + for (int32_t i = first_gid; i <= last_gid; ++i) { + BitmapGlyphInfoMap::const_iterator it = loca.find(i); + if (it != loca.end()) { + offset = it->second->offset(); + length = it->second->length(); + new_offsets->push_back(offset); + if (i == last_gid) { + new_offsets->push_back(offset + length); + } + } else { // Glyph id is not in subset. + offset += length; + new_offsets->push_back(offset); + length = 0; + } + } +} + +/****************************************************************************** + * EXPERIMENTAL CODE STARTS + * + * The following code is used for experiment. Will obsolete once we have + * support to create format 4 and 5 index sub tables from scratch. + *****************************************************************************/ +void SubsetIndexSubTableFormat1(IndexSubTable::Builder* b, + const BitmapGlyphInfoMap& loca) { + IndexSubTableFormat1BuilderPtr builder = + down_cast(b); + if (builder->first_glyph_index() < loca.begin()->first) { + builder->set_first_glyph_index(loca.begin()->first); + } + if (builder->last_glyph_index() > loca.rbegin()->first) { + builder->set_last_glyph_index(loca.rbegin()->first); + } + builder->set_image_data_offset(loca.begin()->second->block_offset()); + + IntegerList new_offsets; + GenerateOffsetArray(builder->first_glyph_index(), builder->last_glyph_index(), + loca, &new_offsets); + builder->SetOffsetArray(new_offsets); +} + +void SubsetIndexSubTableFormat2(IndexSubTable::Builder* b, + const BitmapGlyphInfoMap& loca) { + UNREFERENCED_PARAMETER(b); + UNREFERENCED_PARAMETER(loca); +} + +void SubsetIndexSubTableFormat3(IndexSubTable::Builder* b, + const BitmapGlyphInfoMap& loca) { + IndexSubTableFormat3BuilderPtr builder = + down_cast(b); + if (builder->first_glyph_index() < loca.begin()->first) { + builder->set_first_glyph_index(loca.begin()->first); + } + if (builder->last_glyph_index() > loca.rbegin()->first) { + builder->set_last_glyph_index(loca.rbegin()->first); + } + builder->set_image_data_offset(loca.begin()->second->block_offset()); + + IntegerList new_offsets; + GenerateOffsetArray(builder->first_glyph_index(), builder->last_glyph_index(), + loca, &new_offsets); + builder->SetOffsetArray(new_offsets); +} + +void SubsetIndexSubTableFormat4(IndexSubTable::Builder* b, + const BitmapGlyphInfoMap& loca) { + IndexSubTableFormat4BuilderPtr builder = + down_cast(b); + CodeOffsetPairBuilderList pairs; + pairs.resize(loca.size()); + size_t index = 0; + for (BitmapGlyphInfoMap::const_iterator i = loca.begin(), e = loca.end(); + i != e; i++) { + pairs[index].set_glyph_code(i->first); + pairs[index].set_offset(i->second->offset()); + index++; + } + builder->SetOffsetArray(pairs); +} + +void SubsetIndexSubTableFormat5(IndexSubTable::Builder* b, + const BitmapGlyphInfoMap& loca) { + IndexSubTableFormat5BuilderPtr builder = + down_cast(b); + IntegerList* glyph_array = builder->GlyphArray(); + for (IntegerList::iterator i = glyph_array->begin(); i != glyph_array->end(); + i++) { + if (loca.find(*i) == loca.end()) { + glyph_array->erase(i); + } + } + if (!glyph_array->empty()) { + builder->set_first_glyph_index(*(glyph_array->begin())); + builder->set_last_glyph_index(*(glyph_array->rbegin())); + } else { + builder->set_first_glyph_index(0); + builder->set_last_glyph_index(0); + } +} + +void SubsetIndexSubTable(IndexSubTable::Builder* builder, + const BitmapGlyphInfoMap& loca) { + switch (builder->index_format()) { + case 1: + SubsetIndexSubTableFormat1(builder, loca); + break; + case 2: + SubsetIndexSubTableFormat2(builder, loca); + break; + case 3: + SubsetIndexSubTableFormat3(builder, loca); + break; + case 4: + SubsetIndexSubTableFormat4(builder, loca); + break; + case 5: + SubsetIndexSubTableFormat5(builder, loca); + break; + default: + assert(false); // Shall not be here. + break; + } +} + +void SubsetEBLC(EblcTable::Builder* eblc, const BitmapLocaList& new_loca) { + EblcTableBuilderPtr eblc_builder = eblc; + BitmapSizeTableBuilderList* size_builders = eblc->BitmapSizeBuilders(); + if (size_builders == NULL) { + return; // No valid EBLC. + } + + for (size_t strike = 0; strike < size_builders->size(); ++strike) { + IndexSubTableBuilderList* index_builders = + (*size_builders)[strike]->IndexSubTableBuilders(); + bool format4_processed = false; + for (size_t index = 0; index < index_builders->size(); ++index) { + // Only one format 4 table per strike. + if ((*index_builders)[index]->index_format() == 4 && format4_processed) { + continue; + } + SubsetIndexSubTable((*index_builders)[index], new_loca[strike]); + if ((*index_builders)[index]->index_format() == 4) { + format4_processed = true; + } + } + } +} +/****************************************************************************** + * EXPERIMENTAL CODE ENDS + *****************************************************************************/ + +/****************************************************************************** + Long background comments + +EBLC structure: + header + bitmapSizeTable[] + one per strike + holds strike metrics - sbitLineMetrics + holds info about indexSubTableArray + indexSubTableArray[][] + one per strike and then one per indexSubTable for that strike + holds info about the indexSubTable + the indexSubTable entries pointed to can be of different formats + indexSubTable + one per indexSubTableArray entry + tells how to get the glyphs + may hold the glyph metrics if they are uniform for all the glyphs in range + +There is nothing that says that the indexSubTableArray entries and/or the +indexSubTable items need to be unique. They may be shared between strikes. + +EBDT structure: + header + glyphs + amorphous blob of data + different glyphs that are only able to be figured out from the EBLC table + may hold metrics - depends on the EBLC entry that pointed to them + +Subsetting EBLC table: + Most pages use only a fraction (hundreds or less) glyphs out of a given font + (which can have >20K glyphs for CJK). It's safe to assume that the subset + font will have sparse bitmap glyphs. As a result, the EBLC table shall be + reconstructed to either format 4 or 5. +*******************************************************************************/ +bool SetupBitmapBuilders(Font* font, Font::Builder* builder, + const IntegerSet& glyph_ids) { + if (!font || !builder) { + return false; + } + + // Check if bitmap table exists. + bool use_ebdt = true; + EbdtTablePtr ebdt_table = down_cast(font->GetTable(Tag::EBDT)); + EblcTablePtr eblc_table = down_cast(font->GetTable(Tag::EBLC)); + if (ebdt_table == NULL && eblc_table == NULL) { + use_ebdt = false; + // Check BDAT variants. + ebdt_table = down_cast(font->GetTable(Tag::bdat)); + eblc_table = down_cast(font->GetTable(Tag::bloc)); + } + if (ebdt_table == NULL || eblc_table == NULL) { + // There's no bitmap tables. + return true; + } + + // If the bitmap table's size is too small, skip subsetting. + // TODO(arthurhsu): temporarily comment out to use smaller font for testing. + /* + if (ebdt_table->DataLength() + eblc_table->DataLength() < + BITMAP_SIZE_THRESHOLD) { + return true; + } + */ + + // Get the builders. + FontBuilderPtr font_builder = builder; + EbdtTableBuilderPtr ebdt_table_builder = down_cast( + font_builder->NewTableBuilder(use_ebdt ? Tag::EBDT : Tag::bdat, + ebdt_table->ReadFontData())); + EblcTableBuilderPtr eblc_table_builder = down_cast( + font_builder->NewTableBuilder(use_ebdt ? Tag::EBLC : Tag::bloc, + eblc_table->ReadFontData())); + if (ebdt_table_builder == NULL || eblc_table_builder == NULL) { + // Out of memory. + return false; + } + + if (!ShallSubset(ebdt_table_builder, eblc_table_builder, glyph_ids)) { + // Bitmap tables do not cover the glyphs in our subset. + ebdt_table_builder.Release(); + eblc_table_builder.Release(); + font_builder->RemoveTableBuilder(use_ebdt ? Tag::EBDT : Tag::bdat); + font_builder->RemoveTableBuilder(use_ebdt ? Tag::EBLC : Tag::bloc); + return true; + } + + BitmapLocaList new_loca; + ebdt_table_builder->GenerateLocaList(&new_loca); + SubsetEBLC(eblc_table_builder, new_loca); + + return true; +} + +SubsetterImpl::SubsetterImpl() { +} + +SubsetterImpl::~SubsetterImpl() { +} + +bool SubsetterImpl::LoadFont(const char* font_name, + const unsigned char* original_font, + size_t font_size) { + MemoryInputStream mis; + mis.Attach(original_font, font_size); + if (factory_ == NULL) { + factory_.Attach(FontFactory::GetInstance()); + } + + FontArray font_array; + factory_->LoadFonts(&mis, &font_array); + font_ = FindFont(font_name, font_array); + if (font_ == NULL) { + return false; + } + + return true; +} + +int SubsetterImpl::SubsetFont(const unsigned int* glyph_ids, + size_t glyph_count, + unsigned char** output_buffer) { + if (factory_ == NULL || font_ == NULL) { + return -1; + } + + // Find glyf and loca table. + 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) { + // We are not able to subset the font. + return 0; + } + + IntegerSet glyph_id_processed; + if (!ResolveCompositeGlyphs(glyph_table, loca_table, + glyph_ids, glyph_count, &glyph_id_processed) || + glyph_id_processed.empty()) { + return 0; + } + + FontPtr new_font; + new_font.Attach(Subset(glyph_id_processed)); + if (new_font == NULL) { + return 0; + } + + MemoryOutputStream output_stream; + factory_->SerializeFont(new_font, &output_stream); + int length = static_cast(output_stream.Size()); + if (length > 0) { + *output_buffer = new unsigned char[length]; + memcpy(*output_buffer, output_stream.Get(), length); + } + + return length; +} + +/******************************************************************************* + Long comments regarding TTF tables and PDF + +According to PDF spec (section 9.9), the following tables must present: + head, hhea, loca, maxp, cvt, prep, glyf, hmtx, fpgm + cmap if font is used as a TTF and not a CIDFont dict + +Other tables we need to keep for PDF rendering to support zoom in/out: + bdat, bloc, ebdt, eblc, ebsc, gasp + +Special table: + CFF - if you have this table then you shouldn't have a glyf table and this is + the table with all the glyphs. Shall skip subsetting completely since + sfntly is not capable of subsetting it for now. + post - extra info here for printing on PostScript printers but maybe not + enough to outweigh the space taken by the names + +Tables to break apart: + name - could throw away all but one language and one platform strings / might + throw away some of the name entries + cmap - could strip out non-needed cmap subtables + - format 4 subtable can be subsetted as well using sfntly + +Graphite tables: + silf, glat, gloc, feat - shall be okay to strip out + +Tables that can be discarded: + OS/2 - everything here is for layout and description of the font that is + elsewhere (some in the PDF objects) + BASE, GDEF, GSUB, GPOS, JSTF - all used for layout + kern - old style layout + DSIG - this will be invalid after subsetting + hdmx - layout + PCLT - metadata that's not needed + vmtx - layout + vhea - layout + VDMX + VORG - not used by TT/OT - used by CFF + hsty - would be surprised if you saw one of these - used on the Newton + AAT tables - mort, morx, feat, acnt, bsin, just, lcar, fdsc, fmtx, prop, + Zapf, opbd, trak, fvar, gvar, avar, cvar + - these are all layout tables and once layout happens are not + needed anymore + LTSH - layout +*******************************************************************************/ +CALLER_ATTACH Font* SubsetterImpl::Subset(const IntegerSet& glyph_ids) { + // The const is initialized here to workaround VC bug of rendering all Tag::* + // as 0. These tags represents the TTF tables that we will embed in subset + // font. + const int32_t VALID_TABLE_TAG[] = { + Tag::head, Tag::hhea, Tag::loca, Tag::maxp, Tag::cvt, + Tag::prep, Tag::glyf, Tag::hmtx, Tag::fpgm, Tag::EBDT, + Tag::EBLC, Tag::EBSC, Tag::bdat, Tag::bloc, Tag::bhed, + Tag::cmap, // Keep here for future tagged PDF development. + Tag::name, // Keep here due to legal concerns: copyright info inside. + }; + + // Setup font builders we need. + FontBuilderPtr font_builder; + font_builder.Attach(factory_->NewFontBuilder()); + IntegerSet remove_tags; + + GlyphTablePtr glyph_table = + down_cast(font_->GetTable(Tag::glyf)); + LocaTablePtr loca_table = down_cast(font_->GetTable(Tag::loca)); + + if (SetupGlyfBuilders(font_builder, glyph_table, loca_table, glyph_ids)) { + remove_tags.insert(Tag::glyf); + remove_tags.insert(Tag::loca); + } + if (SetupBitmapBuilders(font_, font_builder, glyph_ids)) { + remove_tags.insert(Tag::bdat); + remove_tags.insert(Tag::bloc); + remove_tags.insert(Tag::bhed); + remove_tags.insert(Tag::EBDT); + remove_tags.insert(Tag::EBLC); + remove_tags.insert(Tag::EBSC); + } + + IntegerSet allowed_tags; + for (size_t i = 0; i < sizeof(VALID_TABLE_TAG) / sizeof(int32_t); ++i) { + allowed_tags.insert(VALID_TABLE_TAG[i]); + } + for (IntegerSet::iterator i = remove_tags.begin(), e = remove_tags.end(); + i != e; i++) { + IntegerSet::iterator it = allowed_tags.find(*i); + if (it != allowed_tags.end()) { + allowed_tags.erase(it); + } + } + // Setup remaining builders. - for (TableMap::const_iterator i = font_->GetTableMap()->begin(), - e = font_->GetTableMap()->end(); i != e; ++i) { - // We already build the builder for glyph and loca. - if (i->first != Tag::glyf && i->first != Tag::loca) { - font_builder->NewTableBuilder(i->first, i->second->ReadFontData()); + for (IntegerSet::iterator i = allowed_tags.begin(), e = allowed_tags.end(); + i != e; ++i) { + Table* table = font_->GetTable(*i); + if (table) { + font_builder->NewTableBuilder(*i, table->ReadFontData()); } } diff --git a/test/subsetter_impl.h b/test/subsetter_impl.h index f3a8bf3..abcc420 100644 --- a/test/subsetter_impl.h +++ b/test/subsetter_impl.h @@ -21,6 +21,7 @@ #include "sfntly/font.h" #include "sfntly/font_factory.h" +#include "sfntly/tag.h" namespace sfntly { @@ -46,6 +47,13 @@ namespace sfntly { // } // ref count = 1, obj2 out of scope // obj.release(); // ref count = 0, object destroyed +namespace { + +// The bitmap tables must be greater than 256KB to trigger bitmap subsetter. +static const int BITMAP_SIZE_THRESHOLD = 262144; + +} + class SubsetterImpl { public: SubsetterImpl(); @@ -59,11 +67,6 @@ class SubsetterImpl { unsigned char** output_buffer); private: - Font* FindFont(const char* font_name, const FontArray& font_array); - bool HasName(const char* font_name, Font* font); - bool ResolveCompositeGlyphs(const unsigned int* glyph_ids, - size_t glyph_count, - IntegerSet* glyph_id_processed); CALLER_ATTACH Font* Subset(const IntegerSet& glyph_ids); FontFactoryPtr factory_; -- cgit v1.2.3 From e860660394805c945cb59d70dc431b1a7537c608 Mon Sep 17 00:00:00 2001 From: "arthurhsu@google.com" Date: Thu, 20 Oct 2011 20:30:19 +0000 Subject: Fix issue 3: no new line at end of file git-svn-id: http://sfntly.googlecode.com/svn/trunk/cpp/src@102 672e30a5-4c29-85ac-ac6d-611c735e0a51 --- sfntly/table/subtable_container_table.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sfntly/table/subtable_container_table.h b/sfntly/table/subtable_container_table.h index e77ebbb..0f099de 100644 --- a/sfntly/table/subtable_container_table.h +++ b/sfntly/table/subtable_container_table.h @@ -45,4 +45,4 @@ class SubTableContainerTable : public Table { } // namespace sfntly -#endif // TYPOGRAPHY_FONT_SFNTLY_SRC_SFNTLY_TABLE_SUBTABLE_CONTAINER_TABLE_H_ \ No newline at end of file +#endif // TYPOGRAPHY_FONT_SFNTLY_SRC_SFNTLY_TABLE_SUBTABLE_CONTAINER_TABLE_H_ -- cgit v1.2.3 From 144e5cb2b372c30d8a4b90267b52646368dd89fc Mon Sep 17 00:00:00 2001 From: "arthurhsu@google.com" Date: Fri, 21 Oct 2011 00:33:26 +0000 Subject: Update to 10-17-11 snapshot git-svn-id: http://sfntly.googlecode.com/svn/trunk/cpp/src@103 672e30a5-4c29-85ac-ac6d-611c735e0a51 --- sfntly/data/readable_font_data.cc | 12 +++++++---- sfntly/data/writable_font_data.cc | 12 +++++++---- sfntly/table/bitmap/bitmap_size_table.cc | 34 ++++++++++++++++++++++++++++++++ sfntly/table/bitmap/bitmap_size_table.h | 3 +++ sfntly/table/bitmap/ebdt_table.cc | 2 +- sfntly/table/bitmap/index_sub_table.cc | 11 +++++++++++ sfntly/table/bitmap/index_sub_table.h | 5 +++++ test/subsetter_impl.cc | 24 +++++++++------------- 8 files changed, 79 insertions(+), 24 deletions(-) diff --git a/sfntly/data/readable_font_data.cc b/sfntly/data/readable_font_data.cc index bb58c26..06d783f 100644 --- a/sfntly/data/readable_font_data.cc +++ b/sfntly/data/readable_font_data.cc @@ -257,21 +257,25 @@ int32_t ReadableFontData::SearchULong(int32_t start_index, 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); - // Note: exception not ported because the condition is always false in C++. - // if (slice == null) { throw new IndexOutOfBoundsException( ... 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); - // Note: exception not ported because the condition is always false in C++. - // if (slice == null) { throw new IndexOutOfBoundsException( ... return slice.Detach(); } diff --git a/sfntly/data/writable_font_data.cc b/sfntly/data/writable_font_data.cc index ace387c..7f6f72f 100644 --- a/sfntly/data/writable_font_data.cc +++ b/sfntly/data/writable_font_data.cc @@ -166,21 +166,25 @@ void WritableFontData::CopyFrom(InputStream* 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); - // Note: exception not ported because the condition is always false in C++. - // if (slice == null) { throw new IndexOutOfBoundsException( ... 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); - // Note: exception not ported because the condition is always false in C++. - // if (slice == null) { throw new IndexOutOfBoundsException( ... return slice.Detach(); } diff --git a/sfntly/table/bitmap/bitmap_size_table.cc b/sfntly/table/bitmap/bitmap_size_table.cc index 5e0c237..bde903a 100644 --- a/sfntly/table/bitmap/bitmap_size_table.cc +++ b/sfntly/table/bitmap/bitmap_size_table.cc @@ -316,6 +316,15 @@ IndexSubTable::Builder* BitmapSizeTable::Builder::GetIndexSubTable( 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) { @@ -384,6 +393,31 @@ void BitmapSizeTable::Builder::SetNumberOfIndexSubTables(int32_t 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; diff --git a/sfntly/table/bitmap/bitmap_size_table.h b/sfntly/table/bitmap/bitmap_size_table.h index 2bc91da..4f4a961 100644 --- a/sfntly/table/bitmap/bitmap_size_table.h +++ b/sfntly/table/bitmap/bitmap_size_table.h @@ -98,6 +98,7 @@ class BitmapSizeTable : public SubTable, // Note: renamed from indexSubTable() IndexSubTable::Builder* GetIndexSubTable(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); @@ -115,6 +116,8 @@ class BitmapSizeTable : public SubTable, 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( diff --git a/sfntly/table/bitmap/ebdt_table.cc b/sfntly/table/bitmap/ebdt_table.cc index 19e5e55..eeb1fa0 100644 --- a/sfntly/table/bitmap/ebdt_table.cc +++ b/sfntly/table/bitmap/ebdt_table.cc @@ -222,7 +222,7 @@ void EbdtTable::Builder::Initialize(ReadableFontData* data, BitmapGlyphInfoPtr info = entry->second; ReadableFontDataPtr slice; slice.Attach(down_cast(data->Slice( - info->start_offset(), info->length()))); + info->offset(), info->length()))); BitmapGlyphBuilderPtr glyph_builder; glyph_builder.Attach(BitmapGlyph::Builder::CreateGlyphBuilder( slice, info->format())); diff --git a/sfntly/table/bitmap/index_sub_table.cc b/sfntly/table/bitmap/index_sub_table.cc index 66d2d83..80c0ffe 100644 --- a/sfntly/table/bitmap/index_sub_table.cc +++ b/sfntly/table/bitmap/index_sub_table.cc @@ -104,6 +104,17 @@ void IndexSubTable::Builder::Revert() { 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); } diff --git a/sfntly/table/bitmap/index_sub_table.h b/sfntly/table/bitmap/index_sub_table.h index c2be7d1..0993e76 100644 --- a/sfntly/table/bitmap/index_sub_table.h +++ b/sfntly/table/bitmap/index_sub_table.h @@ -45,6 +45,11 @@ class IndexSubTable : public SubTable { 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 diff --git a/test/subsetter_impl.cc b/test/subsetter_impl.cc index 7934085..292e83f 100644 --- a/test/subsetter_impl.cc +++ b/test/subsetter_impl.cc @@ -315,15 +315,9 @@ bool ShallSubset(EbdtTable::Builder* ebdt, EblcTable::Builder* eblc, for (IntegerSet::const_iterator gid = glyph_ids.begin(), gid_end = glyph_ids.end(); gid != gid_end; gid++) { - if ((*index_builders)[j]->first_glyph_index() <= *gid && - (*index_builders)[j]->last_glyph_index() >= *gid && - (*index_builders)[j]->GlyphStartOffset(*gid) != -1) { - BitmapGlyphInfoPtr info = - new BitmapGlyphInfo(*gid, - (*index_builders)[j]->image_data_offset() + - (*index_builders)[j]->GlyphStartOffset(*gid), - (*index_builders)[j]->GlyphLength(*gid), - (*index_builders)[j]->image_format()); + BitmapGlyphInfoPtr info; + info.Attach((*index_builders)[j]->GlyphInfo(*gid)); + if (info) { info_map[*gid] = info; } } @@ -356,6 +350,12 @@ bool ShallSubset(EbdtTable::Builder* ebdt, EblcTable::Builder* eblc, return true; } +/****************************************************************************** + * EXPERIMENTAL CODE STARTS + * + * The following code is used for experiment. Will obsolete once we have + * support to create format 4 and 5 index sub tables from scratch. + *****************************************************************************/ void GenerateOffsetArray(int32_t first_gid, int32_t last_gid, const BitmapGlyphInfoMap& loca, IntegerList* new_offsets) { @@ -378,12 +378,6 @@ void GenerateOffsetArray(int32_t first_gid, int32_t last_gid, } } -/****************************************************************************** - * EXPERIMENTAL CODE STARTS - * - * The following code is used for experiment. Will obsolete once we have - * support to create format 4 and 5 index sub tables from scratch. - *****************************************************************************/ void SubsetIndexSubTableFormat1(IndexSubTable::Builder* b, const BitmapGlyphInfoMap& loca) { IndexSubTableFormat1BuilderPtr builder = -- cgit v1.2.3 From a7acde600e171e08e75138318308de83f38b3097 Mon Sep 17 00:00:00 2001 From: "arthurhsu@google.com" Date: Tue, 15 Nov 2011 19:34:35 +0000 Subject: Update to Java initial release (except bitmap tables) TBR(stuartg) git-svn-id: http://sfntly.googlecode.com/svn/trunk/cpp/src@105 672e30a5-4c29-85ac-ac6d-611c735e0a51 --- sfntly/font.cc | 17 +++ .../table/core/horizontal_device_metrics_table.cc | 124 +++++++++++++++++++++ .../table/core/horizontal_device_metrics_table.h | 82 ++++++++++++++ sfntly/table/table.cc | 21 ++-- test/hdmx_test.cc | 82 ++++++++++++++ 5 files changed, 319 insertions(+), 7 deletions(-) create mode 100644 sfntly/table/core/horizontal_device_metrics_table.cc create mode 100644 sfntly/table/core/horizontal_device_metrics_table.h create mode 100644 test/hdmx_test.cc diff --git a/sfntly/font.cc b/sfntly/font.cc index 3fa77b0..c9798c8 100644 --- a/sfntly/font.cc +++ b/sfntly/font.cc @@ -31,6 +31,7 @@ #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" @@ -435,6 +436,15 @@ void Font::Builder::InterRelateBuilders(TableBuilderMap* builder_map) { 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) { @@ -456,6 +466,13 @@ void Font::Builder::InterRelateBuilders(TableBuilderMap* builder_map) { 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, diff --git a/sfntly/table/core/horizontal_device_metrics_table.cc b/sfntly/table/core/horizontal_device_metrics_table.cc new file mode 100644 index 0000000..34d03e6 --- /dev/null +++ b/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."); + return; +#endif + } + 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/sfntly/table/core/horizontal_device_metrics_table.h b/sfntly/table/core/horizontal_device_metrics_table.h new file mode 100644 index 0000000..4a27ba0 --- /dev/null +++ b/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/sfntly/table/table.cc b/sfntly/table/table.cc index f1ff63d..63b1aff 100644 --- a/sfntly/table/table.cc +++ b/sfntly/table/table.cc @@ -24,8 +24,10 @@ #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" @@ -82,11 +84,11 @@ Table::Builder* Table::Builder::GetBuilder(Header* header, if (tag == Tag::head) { builder_raw = static_cast( FontHeaderTable::Builder::CreateBuilder(header, table_data)); -#if defined (SFNTLY_ENABLE_CMAP_HANDLING) +#if defined (SFNTLY_EXPERIMENTAL) } else if (tag == Tag::cmap) { builder_raw = static_cast( CMapTable::Builder::CreateBuilder(header, table_data)); -#endif // SFNTLY_ENABLE_CMAP_HANDLING +#endif // SFNTLY_EXPERIMENTAL } else if (tag == Tag::hhea) { builder_raw = static_cast( HorizontalHeaderTable::Builder::CreateBuilder(header, table_data)); @@ -114,24 +116,29 @@ Table::Builder* Table::Builder::GetBuilder(Header* header, } else if (tag == Tag::loca) { builder_raw = static_cast( LocaTable::Builder::CreateBuilder(header, table_data)); -#if defined (SFNTLY_ENABLE_BITMAP_HANDLING) +#if defined (SFNTLY_EXPERIMENTAL) } 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)); -#endif // SFNTLY_ENABLE_BITMAP_HANDLING - } /* else if (tag == Tag::EBSC) { + } else if (tag == Tag::EBSC) { builder_raw = static_cast( EbscTable::Builder::CreateBuilder(header, table_data)); - }*/ - /* else if (tag == Tag::prep) { +#endif // SFNTLY_EXPERIMENTAL + } /* 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)); diff --git a/test/hdmx_test.cc b/test/hdmx_test.cc new file mode 100644 index 0000000..cdc4ed0 --- /dev/null +++ b/test/hdmx_test.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 "gtest/gtest.h" +#include "sfntly/font.h" +#include "sfntly/table/core/horizontal_device_metrics_table.h" +#include "test/test_data.h" +#include "test/test_font_utils.h" + +namespace sfntly { + +const int32_t HDMX_VERSION = 0; +const int32_t HDMX_NUM_RECORDS = 4; +const int32_t HDMX_RECORD_SIZE = 628; +const int32_t HDMX_PIXEL_SIZE[] = {10, 11, 12, 13}; +const int32_t HDMX_MAX_WIDTH[] = {5, 6, 7, 7}; + +bool TestReadingHdmxTable() { + FontFactoryPtr factory; + factory.Attach(FontFactory::GetInstance()); + FontArray font_array; + LoadFont(SAMPLE_BITMAP_FONT, factory, &font_array); + FontPtr font = font_array[0]; + + HorizontalDeviceMetricsTablePtr hdmx_table = + down_cast(font->GetTable(Tag::hdmx)); + + EXPECT_FALSE(hdmx_table == NULL); + + EXPECT_EQ(hdmx_table->Version(), HDMX_VERSION); + EXPECT_EQ(hdmx_table->NumRecords(), HDMX_NUM_RECORDS); + EXPECT_EQ(hdmx_table->RecordSize(), HDMX_RECORD_SIZE); + + for (int32_t i = 0; i < HDMX_NUM_RECORDS; ++i) { + EXPECT_EQ(hdmx_table->PixelSize(i), HDMX_PIXEL_SIZE[i]); + EXPECT_EQ(hdmx_table->MaxWidth(i), HDMX_MAX_WIDTH[i]); + } + + EXPECT_EQ(hdmx_table->Width(0, 0), HDMX_MAX_WIDTH[0]); + EXPECT_EQ(hdmx_table->Width(0, 19), HDMX_MAX_WIDTH[0]); + EXPECT_EQ(hdmx_table->Width(0, 623), HDMX_MAX_WIDTH[0]); + EXPECT_EQ(hdmx_table->Width(1, 0), HDMX_MAX_WIDTH[1]); + EXPECT_EQ(hdmx_table->Width(1, 19), HDMX_MAX_WIDTH[1]); + EXPECT_EQ(hdmx_table->Width(1, 623), HDMX_MAX_WIDTH[1]); + EXPECT_EQ(hdmx_table->Width(2, 0), HDMX_MAX_WIDTH[2]); + EXPECT_EQ(hdmx_table->Width(2, 19), HDMX_MAX_WIDTH[2]); + EXPECT_EQ(hdmx_table->Width(2, 623), HDMX_MAX_WIDTH[2]); + EXPECT_EQ(hdmx_table->Width(3, 0), HDMX_MAX_WIDTH[3]); + EXPECT_EQ(hdmx_table->Width(3, 19), HDMX_MAX_WIDTH[3]); + EXPECT_EQ(hdmx_table->Width(3, 623), HDMX_MAX_WIDTH[3]); + +#if defined(SFNTLY_NO_EXCEPTION) + EXPECT_EQ(hdmx_table->PixelSize(4), -1); + EXPECT_EQ(hdmx_table->PixelSize(-1), -1); + EXPECT_EQ(hdmx_table->MaxWidth(4), -1); + EXPECT_EQ(hdmx_table->MaxWidth(-1), -1); + EXPECT_EQ(hdmx_table->Width(0, 624), -1); + EXPECT_EQ(hdmx_table->Width(1, -1), -1); + EXPECT_EQ(hdmx_table->Width(-1, 0), -1); + EXPECT_EQ(hdmx_table->Width(-1, -1), -1); +#endif + return true; +} + +} // namespace sfntly + +TEST(HdmxTable, All) { + ASSERT_TRUE(sfntly::TestReadingHdmxTable()); +} -- cgit v1.2.3 From 5768f5055c95f4fdd9dad479ac1f56604a29aba2 Mon Sep 17 00:00:00 2001 From: "arthurhsu@google.com" Date: Wed, 16 Nov 2011 02:16:53 +0000 Subject: Fix bug in HDMX table (from stuartg's code review) git-svn-id: http://sfntly.googlecode.com/svn/trunk/cpp/src@106 672e30a5-4c29-85ac-ac6d-611c735e0a51 --- sfntly/table/core/horizontal_device_metrics_table.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sfntly/table/core/horizontal_device_metrics_table.cc b/sfntly/table/core/horizontal_device_metrics_table.cc index 34d03e6..50b0cf5 100644 --- a/sfntly/table/core/horizontal_device_metrics_table.cc +++ b/sfntly/table/core/horizontal_device_metrics_table.cc @@ -102,8 +102,8 @@ 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."); - return; #endif + return; } num_glyphs_ = num_glyphs; HorizontalDeviceMetricsTable* table = -- cgit v1.2.3 From 53847b66af7e0c1af9928e4da2e978ed3b7c2a25 Mon Sep 17 00:00:00 2001 From: "arthurhsu@google.com" Date: Mon, 28 Nov 2011 18:20:03 +0000 Subject: Finish bitmap subsetting support git-svn-id: http://sfntly.googlecode.com/svn/trunk/cpp/src@107 672e30a5-4c29-85ac-ac6d-611c735e0a51 --- sfntly/data/writable_font_data.h | 14 +- sfntly/table/bitmap/big_glyph_metrics.cc | 21 ++ sfntly/table/bitmap/big_glyph_metrics.h | 7 + sfntly/table/bitmap/bitmap_size_table.cc | 16 +- sfntly/table/bitmap/bitmap_size_table.h | 3 +- sfntly/table/bitmap/ebdt_table.h | 15 +- sfntly/table/bitmap/eblc_table.cc | 18 +- sfntly/table/bitmap/eblc_table.h | 16 +- sfntly/table/bitmap/index_sub_table.cc | 45 ++- sfntly/table/bitmap/index_sub_table.h | 19 +- sfntly/table/bitmap/index_sub_table_format1.cc | 27 +- sfntly/table/bitmap/index_sub_table_format1.h | 2 + sfntly/table/bitmap/index_sub_table_format2.cc | 60 +++- sfntly/table/bitmap/index_sub_table_format2.h | 9 +- sfntly/table/bitmap/index_sub_table_format3.cc | 27 +- sfntly/table/bitmap/index_sub_table_format3.h | 2 + sfntly/table/bitmap/index_sub_table_format4.cc | 37 ++- sfntly/table/bitmap/index_sub_table_format4.h | 6 +- sfntly/table/bitmap/index_sub_table_format5.cc | 64 +++-- sfntly/table/bitmap/index_sub_table_format5.h | 5 +- sfntly/table/font_data_table.cc | 7 + sfntly/table/font_data_table.h | 8 + sfntly/table/subtable.cc | 5 +- sfntly/table/subtable.h | 3 +- test/bitmap_table_test.cc | 112 +++++++- test/serialization_test.cc | 55 +++- test/subsetter_impl.cc | 372 ++++++++++++++----------- test/subsetter_impl.h | 7 - test/test_data.cc | 7 + test/test_data.h | 2 + 30 files changed, 694 insertions(+), 297 deletions(-) diff --git a/sfntly/data/writable_font_data.h b/sfntly/data/writable_font_data.h index f88a986..d2a049e 100644 --- a/sfntly/data/writable_font_data.h +++ b/sfntly/data/writable_font_data.h @@ -85,16 +85,16 @@ class WritableFontData : public ReadableFontData { 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 + // 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 + // 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); diff --git a/sfntly/table/bitmap/big_glyph_metrics.cc b/sfntly/table/bitmap/big_glyph_metrics.cc index d2519cd..2a30829 100644 --- a/sfntly/table/bitmap/big_glyph_metrics.cc +++ b/sfntly/table/bitmap/big_glyph_metrics.cc @@ -137,6 +137,18 @@ void BigGlyphMetrics::Builder::SetVertAdvance(byte_t advance) { InternalWriteData()->WriteByte(Offset::kVertAdvance, advance); } +// Note: C++ port only +void BigGlyphMetrics::Builder::CopyFrom(BigGlyphMetrics::Builder* source) { + SetHeight(static_cast(source->Height())); + SetWidth(static_cast(source->Width())); + SetHoriBearingX(static_cast(source->HoriBearingX())); + SetHoriBearingY(static_cast(source->HoriBearingY())); + SetHoriAdvance(static_cast(source->HoriAdvance())); + SetVertBearingX(static_cast(source->VertBearingX())); + SetVertBearingY(static_cast(source->VertBearingY())); + SetVertAdvance(static_cast(source->VertAdvance())); +} + CALLER_ATTACH FontDataTable* BigGlyphMetrics::Builder::SubBuildTable(ReadableFontData* data) { BigGlyphMetricsPtr output = new BigGlyphMetrics(data); @@ -159,4 +171,13 @@ 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/sfntly/table/bitmap/big_glyph_metrics.h b/sfntly/table/bitmap/big_glyph_metrics.h index 55963b4..b62aada 100644 --- a/sfntly/table/bitmap/big_glyph_metrics.h +++ b/sfntly/table/bitmap/big_glyph_metrics.h @@ -46,6 +46,7 @@ class BigGlyphMetrics : public GlyphMetrics, // class to instantiate derived class with protected constructors. explicit Builder(WritableFontData* data); explicit Builder(ReadableFontData* data); + virtual ~Builder(); int32_t Height(); @@ -65,11 +66,17 @@ class BigGlyphMetrics : public GlyphMetrics, int32_t VertAdvance(); void SetVertAdvance(byte_t advance); + // Note: C++ port only + void CopyFrom(Builder* source); + 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); diff --git a/sfntly/table/bitmap/bitmap_size_table.cc b/sfntly/table/bitmap/bitmap_size_table.cc index bde903a..6c7d731 100644 --- a/sfntly/table/bitmap/bitmap_size_table.cc +++ b/sfntly/table/bitmap/bitmap_size_table.cc @@ -16,8 +16,10 @@ #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" @@ -216,10 +218,18 @@ int32_t BitmapSizeTable::Builder::SubDataSizeToSerialize() { 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); + size += abs(sub_table_size) + padding; } - return size; +#if defined (SFNTLY_DEBUG_BITMAP) + fprintf(stderr, "bitmap table size=%d\n", variable ? -size : size); +#endif + return variable ? -size : size; } bool BitmapSizeTable::Builder::SubReadyToSerialize() { @@ -310,7 +320,7 @@ int32_t BitmapSizeTable::Builder::FlagsAsInt() { EblcTable::Offset::kBitmapSizeTable_flags); } -IndexSubTable::Builder* BitmapSizeTable::Builder::GetIndexSubTable( +IndexSubTable::Builder* BitmapSizeTable::Builder::IndexSubTableBuilder( int32_t index) { IndexSubTableBuilderList* sub_table_list = GetIndexSubTableBuilders(); return sub_table_list->at(index); diff --git a/sfntly/table/bitmap/bitmap_size_table.h b/sfntly/table/bitmap/bitmap_size_table.h index 4f4a961..6733e20 100644 --- a/sfntly/table/bitmap/bitmap_size_table.h +++ b/sfntly/table/bitmap/bitmap_size_table.h @@ -96,8 +96,7 @@ class BitmapSizeTable : public SubTable, int32_t BitDepth(); int32_t FlagsAsInt(); - // Note: renamed from indexSubTable() - IndexSubTable::Builder* GetIndexSubTable(int32_t index); + 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); diff --git a/sfntly/table/bitmap/ebdt_table.h b/sfntly/table/bitmap/ebdt_table.h index 79852c3..d138c14 100644 --- a/sfntly/table/bitmap/ebdt_table.h +++ b/sfntly/table/bitmap/ebdt_table.h @@ -26,6 +26,13 @@ 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: @@ -90,15 +97,7 @@ class EbdtTable : public SubTableContainerTable, CALLER_ATTACH BitmapGlyph* Glyph(int32_t offset, int32_t length, int32_t format); - protected: - struct Offset { - enum { - kVersion = 0, - kHeaderLength = DataSize::kFixed, - }; - }; - EbdtTable(Header* header, ReadableFontData* data); }; typedef Ptr EbdtTablePtr; diff --git a/sfntly/table/bitmap/eblc_table.cc b/sfntly/table/bitmap/eblc_table.cc index 6691b04..0ad2764 100644 --- a/sfntly/table/bitmap/eblc_table.cc +++ b/sfntly/table/bitmap/eblc_table.cc @@ -16,6 +16,7 @@ #include "sfntly/table/bitmap/eblc_table.h" +#include #include #include "sfntly/math/font_math.h" @@ -131,7 +132,8 @@ int32_t EblcTable::Builder::SubSerialize(WritableFontData* new_data) { #if defined (SFNTLY_DEBUG_BITMAP) fprintf(stderr, "size %d: sizeTable=%x, current subTable Block=%x, ", - size_index, size_table_offset); + 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; @@ -209,16 +211,24 @@ int32_t EblcTable::Builder::SubDataSizeToSerialize() { } 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); } - return -size; - // TODO(stuartg): need to fix to get size calculated accurately - // return variable ? -size : size; +#if defined (SFNTLY_DEBUG_BITMAP) + fprintf(stderr, "eblc size=%d\n", size); +#endif + return variable ? -size : size; } void EblcTable::Builder::SubDataSet() { diff --git a/sfntly/table/bitmap/eblc_table.h b/sfntly/table/bitmap/eblc_table.h index 3a9b4c4..b04338a 100644 --- a/sfntly/table/bitmap/eblc_table.h +++ b/sfntly/table/bitmap/eblc_table.h @@ -18,6 +18,7 @@ #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" @@ -81,16 +82,21 @@ class EblcTable : public SubTableContainerTable, // indexSubTable1 kIndexSubTable1_offsetArray = kIndexSubHeaderLength, + kIndexSubTable1_builderDataSize = kIndexSubHeaderLength, // kIndexSubTable2 kIndexSubTable2Length = kIndexSubHeaderLength + DataSize::kULONG + BitmapGlyph::Offset::kBigGlyphMetricsLength, kIndexSubTable2_imageSize = kIndexSubHeaderLength, - kIndexSubTable2_bigGlyphMetrics = kIndexSubTable2_imageSize + 4, + 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, @@ -99,15 +105,17 @@ class EblcTable : public SubTableContainerTable, kIndexSubTable4_codeOffsetPairLength = 2 * DataSize::kUSHORT, kIndexSubTable4_codeOffsetPair_glyphCode = 0, kIndexSubTable4_codeOffsetPair_offset = DataSize::kUSHORT, + kIndexSubTable4_builderDataSize = kIndexSubTable4_glyphArray, // kIndexSubTable5 kIndexSubTable5_imageSize = kIndexSubHeaderLength, - kIndexSubTable5_bigMetrics = kIndexSubTable5_imageSize + - DataSize::kULONG, - kIndexSubTable5_numGlyphs = kIndexSubTable5_bigMetrics + + 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, diff --git a/sfntly/table/bitmap/index_sub_table.cc b/sfntly/table/bitmap/index_sub_table.cc index 80c0ffe..d302aed 100644 --- a/sfntly/table/bitmap/index_sub_table.cc +++ b/sfntly/table/bitmap/index_sub_table.cc @@ -119,6 +119,28 @@ 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, @@ -171,6 +193,7 @@ FontDataTable* IndexSubTable::Builder::SubBuildTable(ReadableFontData* data) { } void IndexSubTable::Builder::SubDataSet() { + // NOP } int32_t IndexSubTable::Builder::SubDataSizeToSerialize() { @@ -186,6 +209,20 @@ int32_t IndexSubTable::Builder::SubSerialize(WritableFontData* new_data) { return 0; } +IndexSubTable::Builder::Builder(int32_t data_size, int32_t index_format) + : SubTable::Builder(data_size), index_format_(index_format) { +} + +IndexSubTable::Builder::Builder(int32_t index_format, + int32_t image_format, + int32_t image_data_offset, + int32_t data_size) + : SubTable::Builder(data_size), + 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) @@ -204,14 +241,6 @@ IndexSubTable::Builder::Builder(ReadableFontData* data, Initialize(data); } -IndexSubTable::Builder::Builder(int32_t index_format, - int32_t image_format, - int32_t image_data_offset) - : index_format_(index_format), - image_format_(image_format), - image_data_offset_(image_data_offset) { -} - int32_t IndexSubTable::Builder::CheckGlyphRange(int32_t glyph_id) { return IndexSubTable::CheckGlyphRange(glyph_id, first_glyph_index(), diff --git a/sfntly/table/bitmap/index_sub_table.h b/sfntly/table/bitmap/index_sub_table.h index 0993e76..6d27129 100644 --- a/sfntly/table/bitmap/index_sub_table.h +++ b/sfntly/table/bitmap/index_sub_table.h @@ -27,6 +27,16 @@ 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(); @@ -71,6 +81,7 @@ class IndexSubTable : public SubTable { 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, @@ -86,15 +97,17 @@ class IndexSubTable : public SubTable { 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); - Builder(int32_t index_format, - int32_t image_format, - int32_t image_data_offset); // 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. diff --git a/sfntly/table/bitmap/index_sub_table_format1.cc b/sfntly/table/bitmap/index_sub_table_format1.cc index 634fbb0..db73723 100644 --- a/sfntly/table/bitmap/index_sub_table_format1.cc +++ b/sfntly/table/bitmap/index_sub_table_format1.cc @@ -101,6 +101,13 @@ CALLER_ATTACH IndexSubTableFormat1::Builder::BitmapGlyphInfoIterator* 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, @@ -155,7 +162,7 @@ void IndexSubTableFormat1::Builder::SubDataSet() { int32_t IndexSubTableFormat1::Builder::SubDataSizeToSerialize() { if (offset_array_.empty()) { - return 0; + return InternalReadData()->Length(); } return EblcTable::Offset::kIndexSubHeaderLength + offset_array_.size() * DataSize::kULONG; @@ -172,6 +179,9 @@ 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( @@ -179,11 +189,11 @@ int32_t IndexSubTableFormat1::Builder::SubSerialize( target.Attach(down_cast(new_data->Slice( EblcTable::Offset::kIndexSubTable1_offsetArray))); size += source->CopyTo(target); - return size; - } - for (IntegerList::iterator b = GetOffsetArray()->begin(), - e = GetOffsetArray()->end(); b != e; b++) { - size += new_data->WriteLong(size, *b); + } else { + for (IntegerList::iterator b = GetOffsetArray()->begin(), + e = GetOffsetArray()->end(); b != e; b++) { + size += new_data->WriteLong(size, *b); + } } return size; } @@ -204,6 +214,11 @@ void IndexSubTableFormat1::Builder::Revert() { 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) diff --git a/sfntly/table/bitmap/index_sub_table_format1.h b/sfntly/table/bitmap/index_sub_table_format1.h index 1078831..33171c1 100644 --- a/sfntly/table/bitmap/index_sub_table_format1.h +++ b/sfntly/table/bitmap/index_sub_table_format1.h @@ -57,6 +57,7 @@ class IndexSubTableFormat1 : public IndexSubTable, 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, @@ -70,6 +71,7 @@ class IndexSubTableFormat1 : public IndexSubTable, void Revert(); private: + Builder(); Builder(WritableFontData* data, int32_t first_glyph_index, int32_t last_glyph_index); diff --git a/sfntly/table/bitmap/index_sub_table_format2.cc b/sfntly/table/bitmap/index_sub_table_format2.cc index 58881f4..b3bffda 100644 --- a/sfntly/table/bitmap/index_sub_table_format2.cc +++ b/sfntly/table/bitmap/index_sub_table_format2.cc @@ -25,6 +25,19 @@ namespace sfntly { 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; } @@ -95,12 +108,21 @@ void IndexSubTableFormat2::Builder::SetImageSize(int32_t image_size) { image_size); } -CALLER_ATTACH BigGlyphMetrics* IndexSubTableFormat2::Builder::BigMetrics() { - WritableFontDataPtr data; - data.Attach(down_cast(InternalWriteData()->Slice( - EblcTable::Offset::kIndexSubTable2_bigGlyphMetrics, - BigGlyphMetrics::Offset::kMetricsLength))); - BigGlyphMetricsPtr output = new BigGlyphMetrics(data); +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(); } @@ -152,6 +174,7 @@ CALLER_ATTACH FontDataTable* IndexSubTableFormat2::Builder::SubBuildTable( } void IndexSubTableFormat2::Builder::SubDataSet() { + Revert(); } int32_t IndexSubTableFormat2::Builder::SubDataSizeToSerialize() { @@ -165,14 +188,29 @@ bool IndexSubTableFormat2::Builder::SubReadyToSerialize() { int32_t IndexSubTableFormat2::Builder::SubSerialize( WritableFontData* new_data) { int32_t size = SerializeIndexSubHeader(new_data); - ReadableFontDataPtr source; - WritableFontDataPtr target; - source.Attach(down_cast(InternalReadData()->Slice(size))); - target.Attach(down_cast(new_data->Slice(size))); - size += source->CopyTo(target); + 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) diff --git a/sfntly/table/bitmap/index_sub_table_format2.h b/sfntly/table/bitmap/index_sub_table_format2.h index 52a9ae0..784e8a3 100644 --- a/sfntly/table/bitmap/index_sub_table_format2.h +++ b/sfntly/table/bitmap/index_sub_table_format2.h @@ -55,8 +55,9 @@ class IndexSubTableFormat2 : public IndexSubTable, int32_t ImageSize(); void SetImageSize(int32_t image_size); - CALLER_ATTACH BigGlyphMetrics* BigMetrics(); + 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, @@ -66,6 +67,7 @@ class IndexSubTableFormat2 : public IndexSubTable, 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); @@ -77,10 +79,15 @@ class IndexSubTableFormat2 : public IndexSubTable, 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); diff --git a/sfntly/table/bitmap/index_sub_table_format3.cc b/sfntly/table/bitmap/index_sub_table_format3.cc index eedc500..b3e418f 100644 --- a/sfntly/table/bitmap/index_sub_table_format3.cc +++ b/sfntly/table/bitmap/index_sub_table_format3.cc @@ -114,6 +114,13 @@ void IndexSubTableFormat3::Builder::SetOffsetArray( 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, @@ -167,7 +174,7 @@ void IndexSubTableFormat3::Builder::SubDataSet() { int32_t IndexSubTableFormat3::Builder::SubDataSizeToSerialize() { if (offset_array_.empty()) { - return 0; + return InternalReadData()->Length(); } return EblcTable::Offset::kIndexSubHeaderLength + offset_array_.size() * DataSize::kULONG; @@ -184,6 +191,9 @@ 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( @@ -191,15 +201,20 @@ int32_t IndexSubTableFormat3::Builder::SubSerialize( target.Attach(down_cast(new_data->Slice( EblcTable::Offset::kIndexSubTable3_offsetArray))); size += source->CopyTo(target); - return size; - } - for (IntegerList::iterator b = GetOffsetArray()->begin(), - e = GetOffsetArray()->end(); b != e; b++) { - size += new_data->WriteUShort(size, *b); + } 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) diff --git a/sfntly/table/bitmap/index_sub_table_format3.h b/sfntly/table/bitmap/index_sub_table_format3.h index e9f1fa2..d71f857 100644 --- a/sfntly/table/bitmap/index_sub_table_format3.h +++ b/sfntly/table/bitmap/index_sub_table_format3.h @@ -54,6 +54,7 @@ class IndexSubTableFormat3 : public IndexSubTable, 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, @@ -67,6 +68,7 @@ class IndexSubTableFormat3 : public IndexSubTable, void Revert(); private: + Builder(); Builder(WritableFontData* data, int32_t first_glyph_index, int32_t last_glyph_index); diff --git a/sfntly/table/bitmap/index_sub_table_format4.cc b/sfntly/table/bitmap/index_sub_table_format4.cc index 898e288..23f3e47 100644 --- a/sfntly/table/bitmap/index_sub_table_format4.cc +++ b/sfntly/table/bitmap/index_sub_table_format4.cc @@ -148,6 +148,13 @@ CALLER_ATTACH IndexSubTableFormat4::Builder::BitmapGlyphInfoIterator* 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, @@ -201,11 +208,11 @@ void IndexSubTableFormat4::Builder::SubDataSet() { int32_t IndexSubTableFormat4::Builder::SubDataSizeToSerialize() { if (offset_pair_array_.empty()) { - return 0; + return InternalReadData()->Length(); } return EblcTable::Offset::kIndexSubHeaderLength + DataSize::kULONG + GetOffsetArray()->size() * - EblcTable::Offset::kIndexSubTable4_codeOffsetPair_offset; + EblcTable::Offset::kIndexSubTable4_codeOffsetPairLength; } bool IndexSubTableFormat4::Builder::SubReadyToSerialize() { @@ -219,6 +226,9 @@ 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( @@ -226,15 +236,14 @@ int32_t IndexSubTableFormat4::Builder::SubSerialize( target.Attach(down_cast(new_data->Slice( EblcTable::Offset::kIndexSubTable4_glyphArray))); size += source->CopyTo(target); - return size; - } - - 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()); + } 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; } @@ -251,6 +260,11 @@ void IndexSubTableFormat4::Builder::SetOffsetArray( 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) @@ -282,6 +296,7 @@ void IndexSubTableFormat4::Builder::Initialize(ReadableFontData* data) { 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); } diff --git a/sfntly/table/bitmap/index_sub_table_format4.h b/sfntly/table/bitmap/index_sub_table_format4.h index be96628..efd540f 100644 --- a/sfntly/table/bitmap/index_sub_table_format4.h +++ b/sfntly/table/bitmap/index_sub_table_format4.h @@ -37,16 +37,12 @@ class IndexSubTableFormat4 : public IndexSubTable, int32_t offset_; }; - class Builder; 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; } - - private: - friend class Builder; }; class CodeOffsetPairGlyphCodeComparator { @@ -85,6 +81,7 @@ class IndexSubTableFormat4 : public IndexSubTable, 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, @@ -94,6 +91,7 @@ class IndexSubTableFormat4 : public IndexSubTable, 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); diff --git a/sfntly/table/bitmap/index_sub_table_format5.cc b/sfntly/table/bitmap/index_sub_table_format5.cc index 1ddce05..b4ab1b8 100644 --- a/sfntly/table/bitmap/index_sub_table_format5.cc +++ b/sfntly/table/bitmap/index_sub_table_format5.cc @@ -62,7 +62,7 @@ int32_t IndexSubTableFormat5::ImageSize() { CALLER_ATTACH BigGlyphMetrics* IndexSubTableFormat5::BigMetrics() { ReadableFontDataPtr data; data.Attach(down_cast(data_->Slice( - EblcTable::Offset::kIndexSubTable5_bigMetrics, + EblcTable::Offset::kIndexSubTable5_bigGlyphMetrics, BigGlyphMetrics::Offset::kMetricsLength))); BigGlyphMetricsPtr output = new BigGlyphMetrics(data); return output.Detach(); @@ -121,6 +121,13 @@ CALLER_ATTACH IndexSubTableFormat5::Builder::BitmapGlyphInfoIterator* 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, @@ -169,16 +176,14 @@ CALLER_ATTACH FontDataTable* IndexSubTableFormat5::Builder::SubBuildTable( } void IndexSubTableFormat5::Builder::SubDataSet() { - if (model_changed()) { - Initialize(InternalReadData()); - } + Revert(); } int32_t IndexSubTableFormat5::Builder::SubDataSizeToSerialize() { if (glyph_array_.empty()) { - return 0; + return InternalReadData()->Length(); } - return EblcTable::Offset::kIndexSubHeaderLength + + return EblcTable::Offset::kIndexSubTable5_builderDataSize + glyph_array_.size() * DataSize::kUSHORT; } @@ -200,23 +205,17 @@ int32_t IndexSubTableFormat5::Builder::SubSerialize( target.Attach(down_cast(new_data->Slice( EblcTable::Offset::kIndexSubTable5_imageSize))); size += source->CopyTo(target); - return size; } else { - ReadableFontDataPtr source; - WritableFontDataPtr target; - source.Attach(down_cast(InternalReadData()->Slice( - EblcTable::Offset::kIndexSubTable5_imageSize, - EblcTable::Offset::kIndexSubTable5_numGlyphs))); - target.Attach(down_cast(new_data->Slice( - EblcTable::Offset::kIndexSubTable5_imageSize, - EblcTable::Offset::kIndexSubTable5_numGlyphs))); - size += source->CopyTo(target); - } - - size += new_data->WriteLong(size, glyph_array_.size()); - for (IntegerList::iterator b = glyph_array_.begin(), e = glyph_array_.end(); - b != e; b++) { - size += new_data->WriteUShort(size, *b); + 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; } @@ -231,14 +230,16 @@ void IndexSubTableFormat5::Builder::SetImageSize(int32_t image_size) { EblcTable::Offset::kIndexSubTable5_imageSize, image_size); } -CALLER_ATTACH BigGlyphMetrics::Builder* IndexSubTableFormat5::Builder::BigMetrics() { - WritableFontDataPtr data; - data.Attach(down_cast(InternalWriteData()->Slice( - EblcTable::Offset::kIndexSubTable5_bigMetrics, - BigGlyphMetrics::Offset::kMetricsLength))); - BigGlyphMetricsBuilderPtr output = new BigGlyphMetrics::Builder(data); - return output.Detach(); + 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() { @@ -256,6 +257,11 @@ void IndexSubTableFormat5::Builder::Revert() { 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) diff --git a/sfntly/table/bitmap/index_sub_table_format5.h b/sfntly/table/bitmap/index_sub_table_format5.h index 511f1fc..a39e88c 100644 --- a/sfntly/table/bitmap/index_sub_table_format5.h +++ b/sfntly/table/bitmap/index_sub_table_format5.h @@ -54,10 +54,11 @@ class IndexSubTableFormat5 : public IndexSubTable, int32_t ImageSize(); void SetImageSize(int32_t image_size); - CALLER_ATTACH BigGlyphMetrics::Builder* BigMetrics(); + 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, @@ -70,6 +71,7 @@ class IndexSubTableFormat5 : public IndexSubTable, void Revert(); private: + Builder(); Builder(WritableFontData* data, int32_t first_glyph_index, int32_t last_glyph_index); @@ -86,6 +88,7 @@ class IndexSubTableFormat5 : public IndexSubTable, int32_t last_glyph_index); IntegerList glyph_array_; + BigGlyphMetricsBuilderPtr metrics_; }; virtual ~IndexSubTableFormat5(); diff --git a/sfntly/table/font_data_table.cc b/sfntly/table/font_data_table.cc index 7953269..0e27f7a 100644 --- a/sfntly/table/font_data_table.cc +++ b/sfntly/table/font_data_table.cc @@ -141,6 +141,13 @@ FontDataTable::Builder::Builder() 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), diff --git a/sfntly/table/font_data_table.h b/sfntly/table/font_data_table.h index ce5433b..5e437e2 100644 --- a/sfntly/table/font_data_table.h +++ b/sfntly/table/font_data_table.h @@ -64,6 +64,14 @@ class FontDataTable : virtual public RefCount { 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(); diff --git a/sfntly/table/subtable.cc b/sfntly/table/subtable.cc index b990c7c..e5b906f 100644 --- a/sfntly/table/subtable.cc +++ b/sfntly/table/subtable.cc @@ -34,10 +34,11 @@ SubTable::SubTable(ReadableFontData* data) /****************************************************************************** * SubTable::Builder class ******************************************************************************/ -SubTable::Builder::Builder() { +SubTable::Builder::~Builder() { } -SubTable::Builder::~Builder() { +SubTable::Builder::Builder(int32_t data_size) + : FontDataTable::Builder(data_size) { } SubTable::Builder::Builder(WritableFontData* data, diff --git a/sfntly/table/subtable.h b/sfntly/table/subtable.h index 902d281..fa6f4c6 100644 --- a/sfntly/table/subtable.h +++ b/sfntly/table/subtable.h @@ -29,13 +29,12 @@ class SubTable : public FontDataTable { public: class Builder : public FontDataTable::Builder { public: - // Creates a new empty sub-table. - Builder(); 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); diff --git a/test/bitmap_table_test.cc b/test/bitmap_table_test.cc index d5d718d..df3ffc0 100644 --- a/test/bitmap_table_test.cc +++ b/test/bitmap_table_test.cc @@ -16,9 +16,13 @@ #include "gtest/gtest.h" #include "sfntly/font.h" +#include "sfntly/port/file_input_stream.h" +#include "sfntly/port/memory_input_stream.h" +#include "sfntly/port/memory_output_stream.h" #include "sfntly/table/bitmap/ebdt_table.h" #include "sfntly/table/bitmap/eblc_table.h" #include "sfntly/table/bitmap/index_sub_table_format3.h" +#include "sfntly/table/bitmap/index_sub_table_format4.h" #include "test/test_data.h" #include "test/test_font_utils.h" @@ -45,12 +49,8 @@ const int32_t STRIKE4_SUB1_GLYPH_OFFSET[] = { const int32_t NUM_STRIKE4_SUB1_GLYPH_OFFSET = 10; const int32_t STRIKE4_SUB1_GLYPH2_LENGTH = 0x58a2 - 0x589d; -bool TestReadingBitmapTable() { - FontFactoryPtr factory; - factory.Attach(FontFactory::GetInstance()); - FontArray font_array; - LoadFont(SAMPLE_BITMAP_FONT, factory, &font_array); - FontPtr font = font_array[0]; +bool CommonReadingTest(Font* raw_font) { + FontPtr font = raw_font; EblcTablePtr bitmap_loca = down_cast(font->GetTable(Tag::EBLC)); EbdtTablePtr bitmap_table = down_cast(font->GetTable(Tag::EBDT)); @@ -64,7 +64,6 @@ bool TestReadingBitmapTable() { BitmapSizeTablePtr strike1 = bitmap_loca->GetBitmapSizeTable(0); EXPECT_FALSE(strike1 == NULL); EXPECT_EQ(strike1->IndexSubTableArrayOffset(), STRIKE1_ARRAY_OFFSET); - EXPECT_EQ(strike1->IndexTableSize(), STRIKE1_INDEX_TABLE_SIZE); EXPECT_EQ(strike1->NumberOfIndexSubTables(), STRIKE1_NUM_INDEX_TABLES); EXPECT_EQ(strike1->ColorRef(), STRIKE1_COLOR_REF); EXPECT_EQ(strike1->StartGlyphIndex(), STRIKE1_START_GLYPH_INDEX); @@ -82,7 +81,6 @@ bool TestReadingBitmapTable() { EXPECT_EQ(strike4->EndGlyphIndex(), STRIKE1_END_GLYPH_INDEX); IndexSubTablePtr sub1 = strike4->GetIndexSubTable(0); EXPECT_FALSE(sub1 == NULL); - EXPECT_EQ(sub1->index_format(), STRIKE4_SUB1_INDEX_FORMAT); EXPECT_EQ(sub1->image_format(), STRIKE4_SUB1_IMAGE_FORMAT); EXPECT_EQ(sub1->first_glyph_index(), STRIKE1_START_GLYPH_INDEX); EXPECT_EQ(sub1->last_glyph_index(), STRIKE1_END_GLYPH_INDEX); @@ -91,6 +89,24 @@ bool TestReadingBitmapTable() { for (int32_t i = 0; i < NUM_STRIKE4_SUB1_GLYPH_OFFSET; ++i) { EXPECT_EQ(sub1->GlyphOffset(i), STRIKE4_SUB1_GLYPH_OFFSET[i]); } + return true; +} + +bool TestReadingBitmapTable() { + FontFactoryPtr factory; + factory.Attach(FontFactory::GetInstance()); + FontArray font_array; + LoadFont(SAMPLE_BITMAP_FONT, factory, &font_array); + FontPtr font = font_array[0]; + EXPECT_TRUE(CommonReadingTest(font)); + + EblcTablePtr bitmap_loca = down_cast(font->GetTable(Tag::EBLC)); + BitmapSizeTablePtr strike1 = bitmap_loca->GetBitmapSizeTable(0); + BitmapSizeTablePtr strike4 = bitmap_loca->GetBitmapSizeTable(3); + IndexSubTablePtr sub1 = strike4->GetIndexSubTable(0); + + EXPECT_EQ(strike1->IndexTableSize(), STRIKE1_INDEX_TABLE_SIZE); + EXPECT_EQ(sub1->index_format(), STRIKE4_SUB1_INDEX_FORMAT); // Strike 4 Index Sub Table 1 is a Format 3 IndexSubTableFormat3Ptr sub3 = @@ -108,8 +124,86 @@ bool TestReadingBitmapTable() { return true; } +// Function in subset_impl.cc +extern +void SubsetEBLC(EblcTable::Builder* eblc, const BitmapLocaList& new_loca); + +bool TestIndexFormatConversion() { + FontFactoryPtr factory; + factory.Attach(FontFactory::GetInstance()); + FontBuilderArray builder_array; + BuilderForFontFile(SAMPLE_BITMAP_FONT, factory, &builder_array); + + FontBuilderPtr font_builder; + font_builder = builder_array[0]; + EblcTableBuilderPtr eblc_builder = + down_cast(font_builder->GetTableBuilder(Tag::EBLC)); + BitmapLocaList new_loca; + eblc_builder->GenerateLocaList(&new_loca); + SubsetEBLC(eblc_builder, new_loca); // Format 3 -> 4 + + FontPtr new_font; + new_font.Attach(font_builder->Build()); + + // Serialize and reload the serialized font. + MemoryOutputStream os; + factory->SerializeFont(new_font, &os); + +#if defined (SFNTLY_DEBUG_BITMAP) + SerializeToFile(&os, "anon-mod.ttf"); +#endif + + MemoryInputStream is; + is.Attach(os.Get(), os.Size()); + FontArray font_array; + factory->LoadFonts(&is, &font_array); + new_font = font_array[0]; + + EXPECT_TRUE(CommonReadingTest(new_font)); + + // Strike 4 Index Sub Table 1 is a Format 4 + EblcTablePtr bitmap_loca = + down_cast(new_font->GetTable(Tag::EBLC)); + BitmapSizeTablePtr strike4 = bitmap_loca->GetBitmapSizeTable(3); + IndexSubTableFormat4Ptr sub4 = + down_cast(strike4->GetIndexSubTable(0)); + EXPECT_FALSE(sub4 == NULL); + + // And this subtable shall have exactly the same offset as original table + // since no subsetting happens. + FontArray original_font_array; + LoadFont(SAMPLE_BITMAP_FONT, factory, &original_font_array); + FontPtr font = original_font_array[0]; + EXPECT_FALSE(font == NULL); + EblcTablePtr original_loca = down_cast(font->GetTable(Tag::EBLC)); + EXPECT_FALSE(original_loca == NULL); + BitmapSizeTablePtr original_strike4 = bitmap_loca->GetBitmapSizeTable(3); + EXPECT_FALSE(original_strike4 == NULL); + IndexSubTableFormat3Ptr sub3 = + down_cast(strike4->GetIndexSubTable(0)); + EXPECT_FALSE(sub3 == NULL); + EXPECT_EQ(strike4->StartGlyphIndex(), original_strike4->StartGlyphIndex()); + EXPECT_EQ(strike4->EndGlyphIndex(), original_strike4->EndGlyphIndex()); + for (int32_t i = strike4->StartGlyphIndex(); + i <= strike4->EndGlyphIndex(); ++i) { + BitmapGlyphInfoPtr info, original_info; + info.Attach(sub4->GlyphInfo(i)); + original_info.Attach(sub3->GlyphInfo(i)); + EXPECT_EQ(info->format(), original_info->format()); + EXPECT_EQ(info->glyph_id(), original_info->glyph_id()); + EXPECT_EQ(info->length(), original_info->length()); + EXPECT_EQ(info->offset(), original_info->offset()); + } + + return true; +} + } // namespace sfntly -TEST(BitmapTable, All) { +TEST(BitmapTable, Reading) { ASSERT_TRUE(sfntly::TestReadingBitmapTable()); } + +TEST(BitmapTable, IndexFormatConversion) { + ASSERT_TRUE(sfntly::TestIndexFormatConversion()); +} diff --git a/test/serialization_test.cc b/test/serialization_test.cc index 3df6d95..0f2f489 100755 --- a/test/serialization_test.cc +++ b/test/serialization_test.cc @@ -91,8 +91,61 @@ bool TestSerialization() { return true; } +bool TestSerializationBitmap() { + FontFactoryPtr factory1, factory2, factory3; + factory1.Attach(FontFactory::GetInstance()); + FontArray font_array; + LoadFont(SAMPLE_BITMAP_FONT, factory1, &font_array); + FontPtr original = font_array[0]; + + factory2.Attach(FontFactory::GetInstance()); + FontBuilderArray font_builder_array; + BuilderForFontFile(SAMPLE_BITMAP_FONT, factory2, &font_builder_array); + FontBuilderPtr font_builder = font_builder_array[0]; + + FontPtr intermediate; + intermediate.Attach(font_builder->Build()); + MemoryOutputStream os; + factory2->SerializeFont(intermediate, &os); + + factory3.Attach(FontFactory::GetInstance()); + FontArray new_font_array; + MemoryInputStream is; + is.Attach(os.Get(), os.Size()); + factory3->LoadFonts(&is, &new_font_array); + FontPtr serialized = new_font_array[0]; + + // Check number of tables + EXPECT_EQ(original->num_tables(), serialized->num_tables()); + + // Check if same set of tables + const TableMap* original_tables = original->GetTableMap(); + const TableMap* serialized_tables = serialized->GetTableMap(); + EXPECT_EQ(original_tables->size(), serialized_tables->size()); + TableMap::const_iterator not_found = serialized_tables->end(); + for (TableMap::const_iterator b = original_tables->begin(), + e = original_tables->end(); b != e; ++b) { + EXPECT_TRUE((serialized_tables->find(b->first) != not_found)); + } + + // Check checksum equivalence + for (size_t i = 0; i < SAMPLE_BITMAP_KNOWN_TAGS; ++i) { + TablePtr original_table = original->GetTable(BITMAP_KNOWN_TAGS[i]); + TablePtr serialized_table = serialized->GetTable(BITMAP_KNOWN_TAGS[i]); + EXPECT_EQ(original_table->CalculatedChecksum(), + serialized_table->CalculatedChecksum()); + EXPECT_EQ(original_table->DataLength(), serialized_table->DataLength()); + } + + return true; +} + } // namespace sfntly -TEST(Serialization, All) { +TEST(Serialization, Simple) { ASSERT_TRUE(sfntly::TestSerialization()); } + +TEST(Serialization, Bitmap) { + ASSERT_TRUE(sfntly::TestSerializationBitmap()); +} diff --git a/test/subsetter_impl.cc b/test/subsetter_impl.cc index 292e83f..f36fcd2 100644 --- a/test/subsetter_impl.cc +++ b/test/subsetter_impl.cc @@ -39,6 +39,14 @@ #include "sfntly/port/memory_input_stream.h" #include "sfntly/port/memory_output_stream.h" + +namespace { + +// The bitmap tables must be greater than 16KB to trigger bitmap subsetter. +static const int BITMAP_SIZE_THRESHOLD = 16384; + +} + namespace sfntly { void ConstructName(UChar* name_part, UnicodeString* name, int32_t name_id) { @@ -278,10 +286,16 @@ bool SetupGlyfBuilders(Font::Builder* builder, return true; } -bool HasOverlap(int32_t range1_begin, int32_t range1_end, - int32_t range2_begin, int32_t range2_end) { - return (range2_begin < range1_end && range2_begin > range1_begin) || - (range1_begin < range2_end && range1_begin > range2_begin); +bool HasOverlap(int32_t range_begin, int32_t range_end, + const IntegerSet& glyph_ids) { + if (range_begin == range_end) { + return glyph_ids.find(range_begin) != glyph_ids.end(); + } else if (range_end > range_begin) { + IntegerSet::const_iterator left = glyph_ids.lower_bound(range_begin); + IntegerSet::const_iterator right = glyph_ids.lower_bound(range_end); + return right != left; + } + return false; } // Initialize builder, returns false if glyph_id subset is not covered. @@ -296,13 +310,12 @@ bool ShallSubset(EbdtTable::Builder* ebdt, EblcTable::Builder* eblc, // Note: Do not call eblc_builder->GenerateLocaList(&loca_list) and then // ebdt_builder->SetLoca(loca_list). For fonts like SimSun, there are // >28K glyphs inside, where a typical usage will be <1K glyphs. Doing - // the calls inproperly will result in creation of >100K objects that - // will be destroyed immediately and result in significant slowness. + // the calls improperly will result in creation of >100K objects that + // will be destroyed immediately, inducing significant slowness. IntegerList removed_strikes; for (size_t i = 0; i < strikes->size(); i++) { if (!HasOverlap((*strikes)[i]->StartGlyphIndex(), - (*strikes)[i]->EndGlyphIndex(), - *(glyph_ids.begin()), *(glyph_ids.rbegin()))) { + (*strikes)[i]->EndGlyphIndex(), glyph_ids)) { removed_strikes.push_back(i); continue; } @@ -310,22 +323,27 @@ bool ShallSubset(EbdtTable::Builder* ebdt, EblcTable::Builder* eblc, IndexSubTableBuilderList* index_builders = (*strikes)[i]->IndexSubTableBuilders(); IntegerList removed_indexes; + BitmapGlyphInfoMap info_map; for (size_t j = 0; j < index_builders->size(); ++j) { - BitmapGlyphInfoMap info_map; + if (!HasOverlap((*index_builders)[j]->first_glyph_index(), + (*index_builders)[j]->last_glyph_index(), glyph_ids)) { + removed_indexes.push_back(j); + continue; + } for (IntegerSet::const_iterator gid = glyph_ids.begin(), gid_end = glyph_ids.end(); gid != gid_end; gid++) { BitmapGlyphInfoPtr info; info.Attach((*index_builders)[j]->GlyphInfo(*gid)); - if (info) { + if (info && info->length()) { // Do not include gid without bitmap info_map[*gid] = info; } } - if (!info_map.empty()) { - loca_list.push_back(info_map); - } else { - removed_indexes.push_back(j); - } + } + if (!info_map.empty()) { + loca_list.push_back(info_map); + } else { + removed_strikes.push_back(i); // Detected null entries. } // Remove unused index sub tables @@ -342,7 +360,11 @@ bool ShallSubset(EbdtTable::Builder* ebdt, EblcTable::Builder* eblc, // Remove unused strikes for (IntegerList::reverse_iterator j = removed_strikes.rbegin(), e = removed_strikes.rend(); j != e; j++) { - strikes->erase(strikes->begin() + *j); + strikes->erase(strikes->begin() + *j); + } + + if (strikes->empty()) { // no glyph covered, can safely drop the builders. + return false; } ebdt_builder->SetLoca(&loca_list); @@ -350,134 +372,134 @@ bool ShallSubset(EbdtTable::Builder* ebdt, EblcTable::Builder* eblc, return true; } -/****************************************************************************** - * EXPERIMENTAL CODE STARTS - * - * The following code is used for experiment. Will obsolete once we have - * support to create format 4 and 5 index sub tables from scratch. - *****************************************************************************/ -void GenerateOffsetArray(int32_t first_gid, int32_t last_gid, - const BitmapGlyphInfoMap& loca, - IntegerList* new_offsets) { - int32_t offset = 0; - int32_t length = 0; - for (int32_t i = first_gid; i <= last_gid; ++i) { - BitmapGlyphInfoMap::const_iterator it = loca.find(i); - if (it != loca.end()) { - offset = it->second->offset(); - length = it->second->length(); - new_offsets->push_back(offset); - if (i == last_gid) { - new_offsets->push_back(offset + length); - } - } else { // Glyph id is not in subset. - offset += length; - new_offsets->push_back(offset); - length = 0; +CALLER_ATTACH IndexSubTable::Builder* +ConstructIndexFormat4(IndexSubTable::Builder* b, const BitmapGlyphInfoMap& loca, + int32_t* image_data_offset) { + IndexSubTableFormat4BuilderPtr builder4; + builder4.Attach(IndexSubTableFormat4::Builder::CreateBuilder()); + CodeOffsetPairBuilderList offset_pairs; + + size_t offset = 0; + int32_t lower_bound = b->first_glyph_index(); + int32_t upper_bound = b->last_glyph_index(); + bool lower_bound_reached = false; + bool upper_bound_reached = false; + int32_t last_gid = -1; + BitmapGlyphInfoMap::const_iterator last_element = loca.end(); + --last_element; + for (BitmapGlyphInfoMap::const_iterator i = loca.begin(), e = loca.end(); + i != e; i++) { + int32_t gid = i->first; + if (gid < lower_bound) { + continue; + } + if (!lower_bound_reached) { + builder4->set_first_glyph_index(gid); + builder4->set_image_format(b->image_format()); + builder4->set_image_data_offset(*image_data_offset); + last_gid = gid; + lower_bound_reached = true; + } + if (gid > upper_bound || i == last_element) { + upper_bound_reached = true; + } + if (!upper_bound_reached || i == last_element) { + offset_pairs.push_back( + IndexSubTableFormat4::CodeOffsetPairBuilder(gid, offset)); + offset += i->second->length(); + last_gid = gid; + } + if (upper_bound_reached) { + offset_pairs.push_back( + IndexSubTableFormat4::CodeOffsetPairBuilder(-1, offset)); + builder4->set_last_glyph_index(last_gid); + *image_data_offset += offset; + break; } } -} - -void SubsetIndexSubTableFormat1(IndexSubTable::Builder* b, - const BitmapGlyphInfoMap& loca) { - IndexSubTableFormat1BuilderPtr builder = - down_cast(b); - if (builder->first_glyph_index() < loca.begin()->first) { - builder->set_first_glyph_index(loca.begin()->first); - } - if (builder->last_glyph_index() > loca.rbegin()->first) { - builder->set_last_glyph_index(loca.rbegin()->first); - } - builder->set_image_data_offset(loca.begin()->second->block_offset()); - - IntegerList new_offsets; - GenerateOffsetArray(builder->first_glyph_index(), builder->last_glyph_index(), - loca, &new_offsets); - builder->SetOffsetArray(new_offsets); -} - -void SubsetIndexSubTableFormat2(IndexSubTable::Builder* b, - const BitmapGlyphInfoMap& loca) { - UNREFERENCED_PARAMETER(b); - UNREFERENCED_PARAMETER(loca); -} - -void SubsetIndexSubTableFormat3(IndexSubTable::Builder* b, - const BitmapGlyphInfoMap& loca) { - IndexSubTableFormat3BuilderPtr builder = - down_cast(b); - if (builder->first_glyph_index() < loca.begin()->first) { - builder->set_first_glyph_index(loca.begin()->first); - } - if (builder->last_glyph_index() > loca.rbegin()->first) { - builder->set_last_glyph_index(loca.rbegin()->first); - } - builder->set_image_data_offset(loca.begin()->second->block_offset()); + builder4->SetOffsetArray(offset_pairs); - IntegerList new_offsets; - GenerateOffsetArray(builder->first_glyph_index(), builder->last_glyph_index(), - loca, &new_offsets); - builder->SetOffsetArray(new_offsets); + return builder4.Detach(); } -void SubsetIndexSubTableFormat4(IndexSubTable::Builder* b, - const BitmapGlyphInfoMap& loca) { - IndexSubTableFormat4BuilderPtr builder = - down_cast(b); - CodeOffsetPairBuilderList pairs; - pairs.resize(loca.size()); - size_t index = 0; +CALLER_ATTACH IndexSubTable::Builder* +ConstructIndexFormat5(IndexSubTable::Builder* b, const BitmapGlyphInfoMap& loca, + int32_t* image_data_offset) { + IndexSubTableFormat5BuilderPtr new_builder; + new_builder.Attach(IndexSubTableFormat5::Builder::CreateBuilder()); + + // Copy BigMetrics + int32_t image_size = 0; + if (b->index_format() == IndexSubTable::Format::FORMAT_2) { + IndexSubTableFormat2BuilderPtr builder2 = + down_cast(b); + new_builder->BigMetrics()->CopyFrom(builder2->BigMetrics()); + image_size = builder2->ImageSize(); + } else { + IndexSubTableFormat5BuilderPtr builder5 = + down_cast(b); + BigGlyphMetricsBuilderPtr metrics_builder; + new_builder->BigMetrics()->CopyFrom(builder5->BigMetrics()); + image_size = builder5->ImageSize(); + } + + IntegerList* glyph_array = new_builder->GlyphArray(); + size_t offset = 0; + int32_t lower_bound = b->first_glyph_index(); + int32_t upper_bound = b->last_glyph_index(); + bool lower_bound_reached = false; + bool upper_bound_reached = false; + int32_t last_gid = -1; + BitmapGlyphInfoMap::const_iterator last_element = loca.end(); + --last_element; for (BitmapGlyphInfoMap::const_iterator i = loca.begin(), e = loca.end(); i != e; i++) { - pairs[index].set_glyph_code(i->first); - pairs[index].set_offset(i->second->offset()); - index++; - } - builder->SetOffsetArray(pairs); -} - -void SubsetIndexSubTableFormat5(IndexSubTable::Builder* b, - const BitmapGlyphInfoMap& loca) { - IndexSubTableFormat5BuilderPtr builder = - down_cast(b); - IntegerList* glyph_array = builder->GlyphArray(); - for (IntegerList::iterator i = glyph_array->begin(); i != glyph_array->end(); - i++) { - if (loca.find(*i) == loca.end()) { - glyph_array->erase(i); + int32_t gid = i->first; + if (gid < lower_bound) { + continue; + } + if (!lower_bound_reached) { + new_builder->set_first_glyph_index(gid); + new_builder->set_image_format(b->image_format()); + new_builder->set_image_data_offset(*image_data_offset); + new_builder->SetImageSize(image_size); + last_gid = gid; + lower_bound_reached = true; + } + if (gid > upper_bound || i == last_element) { + upper_bound_reached = true; + } + if (!upper_bound_reached || i == last_element) { + glyph_array->push_back(gid); + offset += i->second->length(); + last_gid = gid; + } + if (upper_bound_reached) { + new_builder->set_last_glyph_index(last_gid); + *image_data_offset += offset; + break; } } - if (!glyph_array->empty()) { - builder->set_first_glyph_index(*(glyph_array->begin())); - builder->set_last_glyph_index(*(glyph_array->rbegin())); - } else { - builder->set_first_glyph_index(0); - builder->set_last_glyph_index(0); - } + return new_builder.Detach(); } -void SubsetIndexSubTable(IndexSubTable::Builder* builder, - const BitmapGlyphInfoMap& loca) { +CALLER_ATTACH IndexSubTable::Builder* +SubsetIndexSubTable(IndexSubTable::Builder* builder, + const BitmapGlyphInfoMap& loca, + int32_t* image_data_offset) { switch (builder->index_format()) { - case 1: - SubsetIndexSubTableFormat1(builder, loca); - break; - case 2: - SubsetIndexSubTableFormat2(builder, loca); - break; - case 3: - SubsetIndexSubTableFormat3(builder, loca); - break; - case 4: - SubsetIndexSubTableFormat4(builder, loca); - break; - case 5: - SubsetIndexSubTableFormat5(builder, loca); - break; + case IndexSubTable::Format::FORMAT_1: + case IndexSubTable::Format::FORMAT_3: + case IndexSubTable::Format::FORMAT_4: + return ConstructIndexFormat4(builder, loca, image_data_offset); + case IndexSubTable::Format::FORMAT_2: + case IndexSubTable::Format::FORMAT_5: + return ConstructIndexFormat5(builder, loca, image_data_offset); default: assert(false); // Shall not be here. break; } + return NULL; } void SubsetEBLC(EblcTable::Builder* eblc, const BitmapLocaList& new_loca) { @@ -487,25 +509,20 @@ void SubsetEBLC(EblcTable::Builder* eblc, const BitmapLocaList& new_loca) { return; // No valid EBLC. } + int32_t image_data_offset = EbdtTable::Offset::kHeaderLength; for (size_t strike = 0; strike < size_builders->size(); ++strike) { IndexSubTableBuilderList* index_builders = (*size_builders)[strike]->IndexSubTableBuilders(); - bool format4_processed = false; for (size_t index = 0; index < index_builders->size(); ++index) { - // Only one format 4 table per strike. - if ((*index_builders)[index]->index_format() == 4 && format4_processed) { - continue; - } - SubsetIndexSubTable((*index_builders)[index], new_loca[strike]); - if ((*index_builders)[index]->index_format() == 4) { - format4_processed = true; + IndexSubTable::Builder* new_builder_raw = + SubsetIndexSubTable((*index_builders)[index], new_loca[strike], + &image_data_offset); + if (NULL != new_builder_raw) { + (*index_builders)[index].Attach(new_builder_raw); } } } } -/****************************************************************************** - * EXPERIMENTAL CODE ENDS - *****************************************************************************/ /****************************************************************************** Long background comments @@ -542,34 +559,21 @@ Subsetting EBLC table: reconstructed to either format 4 or 5. *******************************************************************************/ bool SetupBitmapBuilders(Font* font, Font::Builder* builder, - const IntegerSet& glyph_ids) { + const IntegerSet& glyph_ids, bool use_ebdt) { if (!font || !builder) { return false; } - // Check if bitmap table exists. - bool use_ebdt = true; - EbdtTablePtr ebdt_table = down_cast(font->GetTable(Tag::EBDT)); - EblcTablePtr eblc_table = down_cast(font->GetTable(Tag::EBLC)); - if (ebdt_table == NULL && eblc_table == NULL) { - use_ebdt = false; - // Check BDAT variants. - ebdt_table = down_cast(font->GetTable(Tag::bdat)); - eblc_table = down_cast(font->GetTable(Tag::bloc)); - } - if (ebdt_table == NULL || eblc_table == NULL) { - // There's no bitmap tables. - return true; - } + EbdtTablePtr ebdt_table = + down_cast(font->GetTable(use_ebdt ? Tag::EBDT : Tag::bdat)); + EblcTablePtr eblc_table = + down_cast(font->GetTable(use_ebdt ? Tag::EBLC : Tag::bloc)); // If the bitmap table's size is too small, skip subsetting. - // TODO(arthurhsu): temporarily comment out to use smaller font for testing. - /* if (ebdt_table->DataLength() + eblc_table->DataLength() < BITMAP_SIZE_THRESHOLD) { return true; } - */ // Get the builders. FontBuilderPtr font_builder = builder; @@ -586,11 +590,9 @@ bool SetupBitmapBuilders(Font* font, Font::Builder* builder, if (!ShallSubset(ebdt_table_builder, eblc_table_builder, glyph_ids)) { // Bitmap tables do not cover the glyphs in our subset. - ebdt_table_builder.Release(); - eblc_table_builder.Release(); - font_builder->RemoveTableBuilder(use_ebdt ? Tag::EBDT : Tag::bdat); font_builder->RemoveTableBuilder(use_ebdt ? Tag::EBLC : Tag::bloc); - return true; + font_builder->RemoveTableBuilder(use_ebdt ? Tag::EBDT : Tag::bdat); + return false; } BitmapLocaList new_loca; @@ -600,6 +602,30 @@ bool SetupBitmapBuilders(Font* font, Font::Builder* builder, return true; } +enum BitmapDetection { + kNotFound, + kEBDTFound, + kOnlyBDATFound +}; + +// Some fonts have both EBDT/EBLC and bdat/bloc, we need only one set of them. +int DetectBitmapBuilders(Font* font) { + // Check if bitmap table exists. + EbdtTablePtr ebdt_table = down_cast(font->GetTable(Tag::EBDT)); + EblcTablePtr eblc_table = down_cast(font->GetTable(Tag::EBLC)); + if (ebdt_table == NULL && eblc_table == NULL) { + // Check BDAT variants. + ebdt_table = down_cast(font->GetTable(Tag::bdat)); + eblc_table = down_cast(font->GetTable(Tag::bloc)); + if (ebdt_table == NULL || eblc_table == NULL) { + // There's no bitmap tables. + return kNotFound; + } + return kOnlyBDATFound; + } + return kEBDTFound; +} + SubsetterImpl::SubsetterImpl() { } @@ -735,13 +761,23 @@ CALLER_ATTACH Font* SubsetterImpl::Subset(const IntegerSet& glyph_ids) { remove_tags.insert(Tag::glyf); remove_tags.insert(Tag::loca); } - if (SetupBitmapBuilders(font_, font_builder, glyph_ids)) { - remove_tags.insert(Tag::bdat); - remove_tags.insert(Tag::bloc); - remove_tags.insert(Tag::bhed); - remove_tags.insert(Tag::EBDT); - remove_tags.insert(Tag::EBLC); - remove_tags.insert(Tag::EBSC); + + int flag = DetectBitmapBuilders(font_); + if (flag != kNotFound) { + bool use_ebdt = (flag == kEBDTFound); + bool subset_success = + SetupBitmapBuilders(font_, font_builder, glyph_ids, use_ebdt); + + if (use_ebdt || !subset_success) { + remove_tags.insert(Tag::bdat); + remove_tags.insert(Tag::bloc); + remove_tags.insert(Tag::bhed); + } + if (use_ebdt && !subset_success) { + remove_tags.insert(Tag::EBDT); + remove_tags.insert(Tag::EBLC); + remove_tags.insert(Tag::EBSC); + } } IntegerSet allowed_tags; diff --git a/test/subsetter_impl.h b/test/subsetter_impl.h index abcc420..5e6debe 100644 --- a/test/subsetter_impl.h +++ b/test/subsetter_impl.h @@ -47,13 +47,6 @@ namespace sfntly { // } // ref count = 1, obj2 out of scope // obj.release(); // ref count = 0, object destroyed -namespace { - -// The bitmap tables must be greater than 256KB to trigger bitmap subsetter. -static const int BITMAP_SIZE_THRESHOLD = 262144; - -} - class SubsetterImpl { public: SubsetterImpl(); diff --git a/test/test_data.cc b/test/test_data.cc index 6c26f0e..05bc759 100644 --- a/test/test_data.cc +++ b/test/test_data.cc @@ -31,6 +31,7 @@ const char* SAMPLE_BITMAP_FONT = "AnonymousPro-Regular.ttf"; const size_t SAMPLE_TTF_SIZE = 183936; const size_t SAMPLE_TTF_TABLES = 17; const size_t SAMPLE_TTF_KNOWN_TAGS = 16; +const size_t SAMPLE_BITMAP_KNOWN_TAGS = 20; const size_t SAMPLE_TTF_FEAT = 3; const size_t SAMPLE_TTF_HEAD = 6; const size_t SAMPLE_TTF_POST = 14; @@ -41,6 +42,12 @@ const int32_t TTF_KNOWN_TAGS[] = { Tag::loca, Tag::maxp, Tag::morx, Tag::name, Tag::post, Tag::prop }; +const int32_t BITMAP_KNOWN_TAGS[] = { + Tag::EBDT, Tag::EBLC, Tag::EBSC, Tag::LTSH, Tag::OS_2, + Tag::VDMX, Tag::cmap, Tag::cvt, Tag::fpgm, Tag::gasp, + Tag::glyf, Tag::hdmx, Tag::head, Tag::hhea, Tag::hmtx, + Tag::loca, Tag::maxp, Tag::name, Tag::post, Tag::prep }; + const int64_t TTF_CHECKSUM[] = { 0xD463FC48, 0x252028D1, 0x0065078A, 0xC01407B5, 0xFFFF0003, 0x9544342B, 0xFC8F16AD, 0x0EC30C7A, 0xA029CD5D, 0x32513087, diff --git a/test/test_data.h b/test/test_data.h index b6a5ed6..d5e576f 100644 --- a/test/test_data.h +++ b/test/test_data.h @@ -27,11 +27,13 @@ extern const char* SAMPLE_BITMAP_FONT; extern const size_t SAMPLE_TTF_SIZE; extern const size_t SAMPLE_TTF_TABLES; extern const size_t SAMPLE_TTF_KNOWN_TAGS; +extern const size_t SAMPLE_BITMAP_KNOWN_TAGS; extern const size_t SAMPLE_TTF_FEAT; extern const size_t SAMPLE_TTF_HEAD; extern const size_t SAMPLE_TTF_POST; extern const int32_t TTF_KNOWN_TAGS[]; +extern const int32_t BITMAP_KNOWN_TAGS[]; extern const int64_t TTF_CHECKSUM[]; extern const int64_t TTF_OFFSET[]; extern const int32_t TTF_LENGTH[]; -- cgit v1.2.3 From 159f1cfee659ea765446c85399812a2a510fb917 Mon Sep 17 00:00:00 2001 From: "arthurhsu@google.com" Date: Mon, 28 Nov 2011 23:35:40 +0000 Subject: Update per code review comments from previous check-in git-svn-id: http://sfntly.googlecode.com/svn/trunk/cpp/src@108 672e30a5-4c29-85ac-ac6d-611c735e0a51 --- sfntly/table/bitmap/big_glyph_metrics.cc | 12 ------------ sfntly/table/bitmap/big_glyph_metrics.h | 3 --- test/subsetter_impl.cc | 16 ++++++++++++++-- 3 files changed, 14 insertions(+), 17 deletions(-) diff --git a/sfntly/table/bitmap/big_glyph_metrics.cc b/sfntly/table/bitmap/big_glyph_metrics.cc index 2a30829..d853212 100644 --- a/sfntly/table/bitmap/big_glyph_metrics.cc +++ b/sfntly/table/bitmap/big_glyph_metrics.cc @@ -137,18 +137,6 @@ void BigGlyphMetrics::Builder::SetVertAdvance(byte_t advance) { InternalWriteData()->WriteByte(Offset::kVertAdvance, advance); } -// Note: C++ port only -void BigGlyphMetrics::Builder::CopyFrom(BigGlyphMetrics::Builder* source) { - SetHeight(static_cast(source->Height())); - SetWidth(static_cast(source->Width())); - SetHoriBearingX(static_cast(source->HoriBearingX())); - SetHoriBearingY(static_cast(source->HoriBearingY())); - SetHoriAdvance(static_cast(source->HoriAdvance())); - SetVertBearingX(static_cast(source->VertBearingX())); - SetVertBearingY(static_cast(source->VertBearingY())); - SetVertAdvance(static_cast(source->VertAdvance())); -} - CALLER_ATTACH FontDataTable* BigGlyphMetrics::Builder::SubBuildTable(ReadableFontData* data) { BigGlyphMetricsPtr output = new BigGlyphMetrics(data); diff --git a/sfntly/table/bitmap/big_glyph_metrics.h b/sfntly/table/bitmap/big_glyph_metrics.h index b62aada..a91601c 100644 --- a/sfntly/table/bitmap/big_glyph_metrics.h +++ b/sfntly/table/bitmap/big_glyph_metrics.h @@ -66,9 +66,6 @@ class BigGlyphMetrics : public GlyphMetrics, int32_t VertAdvance(); void SetVertAdvance(byte_t advance); - // Note: C++ port only - void CopyFrom(Builder* source); - virtual CALLER_ATTACH FontDataTable* SubBuildTable(ReadableFontData* data); virtual void SubDataSet(); virtual int32_t SubDataSizeToSerialize(); diff --git a/test/subsetter_impl.cc b/test/subsetter_impl.cc index f36fcd2..d475d21 100644 --- a/test/subsetter_impl.cc +++ b/test/subsetter_impl.cc @@ -372,6 +372,18 @@ bool ShallSubset(EbdtTable::Builder* ebdt, EblcTable::Builder* eblc, return true; } +void CopyBigGlyphMetrics(BigGlyphMetrics::Builder* source, + BigGlyphMetrics::Builder* target) { + target->SetHeight(static_cast(source->Height())); + target->SetWidth(static_cast(source->Width())); + target->SetHoriBearingX(static_cast(source->HoriBearingX())); + target->SetHoriBearingY(static_cast(source->HoriBearingY())); + target->SetHoriAdvance(static_cast(source->HoriAdvance())); + target->SetVertBearingX(static_cast(source->VertBearingX())); + target->SetVertBearingY(static_cast(source->VertBearingY())); + target->SetVertAdvance(static_cast(source->VertAdvance())); +} + CALLER_ATTACH IndexSubTable::Builder* ConstructIndexFormat4(IndexSubTable::Builder* b, const BitmapGlyphInfoMap& loca, int32_t* image_data_offset) { @@ -433,13 +445,13 @@ ConstructIndexFormat5(IndexSubTable::Builder* b, const BitmapGlyphInfoMap& loca, if (b->index_format() == IndexSubTable::Format::FORMAT_2) { IndexSubTableFormat2BuilderPtr builder2 = down_cast(b); - new_builder->BigMetrics()->CopyFrom(builder2->BigMetrics()); + CopyBigGlyphMetrics(builder2->BigMetrics(), new_builder->BigMetrics()); image_size = builder2->ImageSize(); } else { IndexSubTableFormat5BuilderPtr builder5 = down_cast(b); BigGlyphMetricsBuilderPtr metrics_builder; - new_builder->BigMetrics()->CopyFrom(builder5->BigMetrics()); + CopyBigGlyphMetrics(builder5->BigMetrics(), new_builder->BigMetrics()); image_size = builder5->ImageSize(); } -- cgit v1.2.3 From c3c35420fcec18f324bc3958ad7ded238e5e56d5 Mon Sep 17 00:00:00 2001 From: "arthurhsu@google.com" Date: Tue, 29 Nov 2011 01:19:06 +0000 Subject: Fix subsetter bug (TBR, testing with Chrome integration, subjected to change) git-svn-id: http://sfntly.googlecode.com/svn/trunk/cpp/src@109 672e30a5-4c29-85ac-ac6d-611c735e0a51 --- test/subsetter_impl.cc | 20 +++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) diff --git a/test/subsetter_impl.cc b/test/subsetter_impl.cc index d475d21..8b64429 100644 --- a/test/subsetter_impl.cc +++ b/test/subsetter_impl.cc @@ -325,14 +325,21 @@ bool ShallSubset(EbdtTable::Builder* ebdt, EblcTable::Builder* eblc, IntegerList removed_indexes; BitmapGlyphInfoMap info_map; for (size_t j = 0; j < index_builders->size(); ++j) { - if (!HasOverlap((*index_builders)[j]->first_glyph_index(), - (*index_builders)[j]->last_glyph_index(), glyph_ids)) { + int32_t first_glyph_id = (*index_builders)[j]->first_glyph_index(); + int32_t last_glyph_id = (*index_builders)[j]->last_glyph_index(); + if (!HasOverlap(first_glyph_id, last_glyph_id, glyph_ids)) { removed_indexes.push_back(j); continue; } for (IntegerSet::const_iterator gid = glyph_ids.begin(), gid_end = glyph_ids.end(); gid != gid_end; gid++) { + if (*gid < first_glyph_id) { + continue; + } + if (*gid > last_glyph_id) { + break; + } BitmapGlyphInfoPtr info; info.Attach((*index_builders)[j]->GlyphInfo(*gid)); if (info && info->length()) { // Do not include gid without bitmap @@ -400,7 +407,7 @@ ConstructIndexFormat4(IndexSubTable::Builder* b, const BitmapGlyphInfoMap& loca, BitmapGlyphInfoMap::const_iterator last_element = loca.end(); --last_element; for (BitmapGlyphInfoMap::const_iterator i = loca.begin(), e = loca.end(); - i != e; i++) { + i != e; i++) { int32_t gid = i->first; if (gid < lower_bound) { continue; @@ -412,14 +419,17 @@ ConstructIndexFormat4(IndexSubTable::Builder* b, const BitmapGlyphInfoMap& loca, last_gid = gid; lower_bound_reached = true; } - if (gid > upper_bound || i == last_element) { + if (gid > upper_bound) { upper_bound_reached = true; } - if (!upper_bound_reached || i == last_element) { + if (!upper_bound_reached) { offset_pairs.push_back( IndexSubTableFormat4::CodeOffsetPairBuilder(gid, offset)); offset += i->second->length(); last_gid = gid; + if (i == last_element) { + upper_bound_reached = true; + } } if (upper_bound_reached) { offset_pairs.push_back( -- cgit v1.2.3 From 37447a81dec26fe9d509a0829e34217f26aaab1b Mon Sep 17 00:00:00 2001 From: "arthurhsu@google.com" Date: Tue, 29 Nov 2011 21:34:18 +0000 Subject: Graduate EBXX from experimental git-svn-id: http://sfntly.googlecode.com/svn/trunk/cpp/src@110 672e30a5-4c29-85ac-ac6d-611c735e0a51 --- sfntly/table/table.cc | 2 -- 1 file changed, 2 deletions(-) diff --git a/sfntly/table/table.cc b/sfntly/table/table.cc index 63b1aff..cf574b8 100644 --- a/sfntly/table/table.cc +++ b/sfntly/table/table.cc @@ -116,7 +116,6 @@ Table::Builder* Table::Builder::GetBuilder(Header* header, } else if (tag == Tag::loca) { builder_raw = static_cast( LocaTable::Builder::CreateBuilder(header, table_data)); -#if defined (SFNTLY_EXPERIMENTAL) } else if (tag == Tag::EBDT || tag == Tag::bdat) { builder_raw = static_cast( EbdtTable::Builder::CreateBuilder(header, table_data)); @@ -126,7 +125,6 @@ Table::Builder* Table::Builder::GetBuilder(Header* header, } else if (tag == Tag::EBSC) { builder_raw = static_cast( EbscTable::Builder::CreateBuilder(header, table_data)); -#endif // SFNTLY_EXPERIMENTAL } /* else if (tag == Tag::prep) { builder_raw = static_cast( ControlProgramTable::Builder::CreateBuilder(header, table_data)); -- cgit v1.2.3 From 5e3195449b63aecca4457041b2d0dd751f2da6b4 Mon Sep 17 00:00:00 2001 From: "arthurhsu@google.com" Date: Wed, 30 Nov 2011 01:43:19 +0000 Subject: Fix clang compilation errors in Chromium. git-svn-id: http://sfntly.googlecode.com/svn/trunk/cpp/src@111 672e30a5-4c29-85ac-ac6d-611c735e0a51 --- sfntly/table/core/name_table.h | 4 ---- test/subsetter_impl.cc | 3 +++ 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/sfntly/table/core/name_table.h b/sfntly/table/core/name_table.h index 9c007a1..01d3b29 100644 --- a/sfntly/table/core/name_table.h +++ b/sfntly/table/core/name_table.h @@ -29,10 +29,6 @@ #include "sfntly/port/java_iterator.h" #include "sfntly/table/subtable_container_table.h" -#if defined U_USING_ICU_NAMESPACE - U_NAMESPACE_USE -#endif - namespace sfntly { // The following code implements the name table defined in TTF/OTF spec, which diff --git a/test/subsetter_impl.cc b/test/subsetter_impl.cc index 8b64429..09cabc4 100644 --- a/test/subsetter_impl.cc +++ b/test/subsetter_impl.cc @@ -39,6 +39,9 @@ #include "sfntly/port/memory_input_stream.h" #include "sfntly/port/memory_output_stream.h" +#if defined U_USING_ICU_NAMESPACE + U_NAMESPACE_USE +#endif namespace { -- cgit v1.2.3 From 33247013aa2bd8f4f0e93cf54ff4d8b19b5b1363 Mon Sep 17 00:00:00 2001 From: "arthurhsu@google.com" Date: Fri, 9 Dec 2011 01:57:19 +0000 Subject: Update per Chromium side code review git-svn-id: http://sfntly.googlecode.com/svn/trunk/cpp/src@114 672e30a5-4c29-85ac-ac6d-611c735e0a51 --- test/subsetter_impl.cc | 448 +++++++++++++++++++++---------------------------- test/subsetter_impl.h | 5 +- 2 files changed, 199 insertions(+), 254 deletions(-) diff --git a/test/subsetter_impl.cc b/test/subsetter_impl.cc index 09cabc4..7759d09 100644 --- a/test/subsetter_impl.cc +++ b/test/subsetter_impl.cc @@ -20,6 +20,8 @@ #include +#include +#include #include #include @@ -32,8 +34,6 @@ #include "sfntly/table/bitmap/index_sub_table_format4.h" #include "sfntly/table/bitmap/index_sub_table_format5.h" #include "sfntly/table/core/name_table.h" -#include "sfntly/table/truetype/glyph_table.h" -#include "sfntly/table/truetype/loca_table.h" #include "sfntly/tag.h" #include "sfntly/data/memory_byte_array.h" #include "sfntly/port/memory_input_stream.h" @@ -45,13 +45,11 @@ namespace { +using namespace sfntly; + // The bitmap tables must be greater than 16KB to trigger bitmap subsetter. static const int BITMAP_SIZE_THRESHOLD = 16384; -} - -namespace sfntly { - void ConstructName(UChar* name_part, UnicodeString* name, int32_t name_id) { switch (name_id) { case NameId::kFullFontName: @@ -131,9 +129,9 @@ bool HasName(const char* font_name, Font* font) { } if (!names.empty()) { - for (NameMap::iterator b = names.begin(), e = names.end(); b != e; ++b) { - if (b->second.caseCompare(font_string, 0) == 0 || - b->second.caseCompare(alt_font_string, 0) == 0) { + for (NameMap::iterator i = names.begin(), e = names.end(); i != e; ++i) { + if (i->second.caseCompare(font_string, 0) == 0 || + i->second.caseCompare(alt_font_string, 0) == 0) { return true; } } @@ -147,10 +145,10 @@ Font* FindFont(const char* font_name, const FontArray& font_array) { } if (font_name && strlen(font_name)) { - for (FontArray::const_iterator b = font_array.begin(), e = font_array.end(); - b != e; ++b) { - if (HasName(font_name, (*b).p_)) { - return (*b).p_; + for (FontArray::const_iterator i = font_array.begin(), e = font_array.end(); + i != e; ++i) { + if (HasName(font_name, i->p_)) { + return i->p_; } } } @@ -158,20 +156,16 @@ Font* FindFont(const char* font_name, const FontArray& font_array) { return font_array[0].p_; } -bool ResolveCompositeGlyphs(GlyphTable* glyf, - LocaTable* loca, +bool ResolveCompositeGlyphs(GlyphTable* glyph_table, + LocaTable* loca_table, const unsigned int* glyph_ids, size_t glyph_count, IntegerSet* glyph_id_processed) { - if (glyf == NULL || loca == NULL || glyph_ids == NULL || glyph_count == 0 || - glyph_id_processed == NULL) { + if (glyph_table == NULL || loca_table == NULL || + glyph_ids == NULL || glyph_count == 0 || glyph_id_processed == NULL) { return false; } - // Find glyf and loca table. - GlyphTablePtr glyph_table = glyf; - LocaTablePtr loca_table = loca; - // Sort and uniquify glyph ids. IntegerSet glyph_id_remaining; glyph_id_remaining.insert(0); // Always include glyph id 0. @@ -226,19 +220,14 @@ bool ResolveCompositeGlyphs(GlyphTable* glyf, return true; } -bool SetupGlyfBuilders(Font::Builder* builder, - GlyphTable* glyf, - LocaTable* loca, +bool SetupGlyfBuilders(Font::Builder* font_builder, + GlyphTable* glyph_table, + LocaTable* loca_table, const IntegerSet& glyph_ids) { - if (!builder || !glyf || !loca) { + if (!font_builder || !glyph_table || !loca_table) { return false; } - // The tables are already checked in ResolveCompositeGlyphs(). - GlyphTablePtr glyph_table = glyf; - LocaTablePtr loca_table = loca; - - FontBuilderPtr font_builder = builder; GlyphTableBuilderPtr glyph_table_builder = down_cast(font_builder->NewTableBuilder(Tag::glyf)); LocaTableBuilderPtr loca_table_builder = @@ -302,13 +291,11 @@ bool HasOverlap(int32_t range_begin, int32_t range_end, } // Initialize builder, returns false if glyph_id subset is not covered. -bool ShallSubset(EbdtTable::Builder* ebdt, EblcTable::Builder* eblc, - const IntegerSet& glyph_ids) { - EblcTableBuilderPtr eblc_builder = eblc; - EbdtTableBuilderPtr ebdt_builder = ebdt; - +// Not thread-safe, caller to ensure object life-time. +bool InitializeBitmapBuilder(EbdtTable::Builder* ebdt, EblcTable::Builder* eblc, + const IntegerSet& glyph_ids) { BitmapLocaList loca_list; - BitmapSizeTableBuilderList* strikes = eblc_builder->BitmapSizeBuilders(); + BitmapSizeTableBuilderList* strikes = eblc->BitmapSizeBuilders(); // Note: Do not call eblc_builder->GenerateLocaList(&loca_list) and then // ebdt_builder->SetLoca(loca_list). For fonts like SimSun, there are @@ -364,21 +351,20 @@ bool ShallSubset(EbdtTable::Builder* ebdt, EblcTable::Builder* eblc, } } if (removed_strikes.size() == strikes->size() || loca_list.empty()) { - return false; // All strikes shall be gone. + return false; } - // Remove unused strikes - for (IntegerList::reverse_iterator j = removed_strikes.rbegin(), - e = removed_strikes.rend(); j != e; j++) { - strikes->erase(strikes->begin() + *j); + for (IntegerList::reverse_iterator i = removed_strikes.rbegin(), + e = removed_strikes.rend(); i != e; i++) { + strikes->erase(strikes->begin() + *i); } if (strikes->empty()) { // no glyph covered, can safely drop the builders. return false; } - ebdt_builder->SetLoca(&loca_list); - ebdt_builder->GlyphBuilders(); // Initialize the builder. + ebdt->SetLoca(&loca_list); + ebdt->GlyphBuilders(); // Initialize the builder. return true; } @@ -404,44 +390,29 @@ ConstructIndexFormat4(IndexSubTable::Builder* b, const BitmapGlyphInfoMap& loca, size_t offset = 0; int32_t lower_bound = b->first_glyph_index(); int32_t upper_bound = b->last_glyph_index(); - bool lower_bound_reached = false; - bool upper_bound_reached = false; int32_t last_gid = -1; - BitmapGlyphInfoMap::const_iterator last_element = loca.end(); - --last_element; - for (BitmapGlyphInfoMap::const_iterator i = loca.begin(), e = loca.end(); - i != e; i++) { + BitmapGlyphInfoMap::const_iterator i = loca.lower_bound(lower_bound); + BitmapGlyphInfoMap::const_iterator end = loca.end(); + if (i != end) { + last_gid = i->first; + builder4->set_first_glyph_index(last_gid); + builder4->set_image_format(b->image_format()); + builder4->set_image_data_offset(*image_data_offset); + } + for (; i != end; i++) { int32_t gid = i->first; - if (gid < lower_bound) { - continue; - } - if (!lower_bound_reached) { - builder4->set_first_glyph_index(gid); - builder4->set_image_format(b->image_format()); - builder4->set_image_data_offset(*image_data_offset); - last_gid = gid; - lower_bound_reached = true; - } if (gid > upper_bound) { - upper_bound_reached = true; - } - if (!upper_bound_reached) { - offset_pairs.push_back( - IndexSubTableFormat4::CodeOffsetPairBuilder(gid, offset)); - offset += i->second->length(); - last_gid = gid; - if (i == last_element) { - upper_bound_reached = true; - } - } - if (upper_bound_reached) { - offset_pairs.push_back( - IndexSubTableFormat4::CodeOffsetPairBuilder(-1, offset)); - builder4->set_last_glyph_index(last_gid); - *image_data_offset += offset; break; } - } + offset_pairs.push_back( + IndexSubTableFormat4::CodeOffsetPairBuilder(gid, offset)); + offset += i->second->length(); + last_gid = gid; + } + offset_pairs.push_back( + IndexSubTableFormat4::CodeOffsetPairBuilder(-1, offset)); + builder4->set_last_glyph_index(last_gid); + *image_data_offset += offset; builder4->SetOffsetArray(offset_pairs); return builder4.Detach(); @@ -472,39 +443,27 @@ ConstructIndexFormat5(IndexSubTable::Builder* b, const BitmapGlyphInfoMap& loca, size_t offset = 0; int32_t lower_bound = b->first_glyph_index(); int32_t upper_bound = b->last_glyph_index(); - bool lower_bound_reached = false; - bool upper_bound_reached = false; int32_t last_gid = -1; - BitmapGlyphInfoMap::const_iterator last_element = loca.end(); - --last_element; - for (BitmapGlyphInfoMap::const_iterator i = loca.begin(), e = loca.end(); - i != e; i++) { + BitmapGlyphInfoMap::const_iterator i = loca.lower_bound(lower_bound); + BitmapGlyphInfoMap::const_iterator end = loca.end(); + if (i != end) { + last_gid = i->first; + new_builder->set_first_glyph_index(last_gid); + new_builder->set_image_format(b->image_format()); + new_builder->set_image_data_offset(*image_data_offset); + new_builder->SetImageSize(image_size); + } + for (; i != end; i++) { int32_t gid = i->first; - if (gid < lower_bound) { - continue; - } - if (!lower_bound_reached) { - new_builder->set_first_glyph_index(gid); - new_builder->set_image_format(b->image_format()); - new_builder->set_image_data_offset(*image_data_offset); - new_builder->SetImageSize(image_size); - last_gid = gid; - lower_bound_reached = true; - } - if (gid > upper_bound || i == last_element) { - upper_bound_reached = true; - } - if (!upper_bound_reached || i == last_element) { - glyph_array->push_back(gid); - offset += i->second->length(); - last_gid = gid; - } - if (upper_bound_reached) { - new_builder->set_last_glyph_index(last_gid); - *image_data_offset += offset; + if (gid > upper_bound) { break; } + glyph_array->push_back(gid); + offset += i->second->length(); + last_gid = gid; } + new_builder->set_last_glyph_index(last_gid); + *image_data_offset += offset; return new_builder.Detach(); } @@ -521,17 +480,21 @@ SubsetIndexSubTable(IndexSubTable::Builder* builder, case IndexSubTable::Format::FORMAT_5: return ConstructIndexFormat5(builder, loca, image_data_offset); default: - assert(false); // Shall not be here. + assert(false); break; } return NULL; } +} + +namespace sfntly { + +// Not thread-safe, caller to ensure object life-time. void SubsetEBLC(EblcTable::Builder* eblc, const BitmapLocaList& new_loca) { - EblcTableBuilderPtr eblc_builder = eblc; BitmapSizeTableBuilderList* size_builders = eblc->BitmapSizeBuilders(); if (size_builders == NULL) { - return; // No valid EBLC. + return; } int32_t image_data_offset = EbdtTable::Offset::kHeaderLength; @@ -549,59 +512,68 @@ void SubsetEBLC(EblcTable::Builder* eblc, const BitmapLocaList& new_loca) { } } -/****************************************************************************** - Long background comments - -EBLC structure: - header - bitmapSizeTable[] - one per strike - holds strike metrics - sbitLineMetrics - holds info about indexSubTableArray - indexSubTableArray[][] - one per strike and then one per indexSubTable for that strike - holds info about the indexSubTable - the indexSubTable entries pointed to can be of different formats - indexSubTable - one per indexSubTableArray entry - tells how to get the glyphs - may hold the glyph metrics if they are uniform for all the glyphs in range - -There is nothing that says that the indexSubTableArray entries and/or the -indexSubTable items need to be unique. They may be shared between strikes. - -EBDT structure: - header - glyphs - amorphous blob of data - different glyphs that are only able to be figured out from the EBLC table - may hold metrics - depends on the EBLC entry that pointed to them - -Subsetting EBLC table: - Most pages use only a fraction (hundreds or less) glyphs out of a given font - (which can have >20K glyphs for CJK). It's safe to assume that the subset - font will have sparse bitmap glyphs. As a result, the EBLC table shall be - reconstructed to either format 4 or 5. -*******************************************************************************/ -bool SetupBitmapBuilders(Font* font, Font::Builder* builder, - const IntegerSet& glyph_ids, bool use_ebdt) { - if (!font || !builder) { +// EBLC structure (from stuartg) +// header +// bitmapSizeTable[] +// one per strike +// holds strike metrics - sbitLineMetrics +// holds info about indexSubTableArray +// indexSubTableArray[][] +// one per strike and then one per indexSubTable for that strike +// holds info about the indexSubTable +// the indexSubTable entries pointed to can be of different formats +// indexSubTable +// one per indexSubTableArray entry +// tells how to get the glyphs +// may hold the glyph metrics if they are uniform for all the glyphs in range +// +// There is nothing that says that the indexSubTableArray entries and/or the +// indexSubTable items need to be unique. They may be shared between strikes. +// +// EBDT structure: +// header +// glyphs +// amorphous blob of data +// different glyphs that are only able to be figured out from the EBLC table +// may hold metrics - depends on the EBLC entry that pointed to them + +// Subsetting EBLC table (from arthurhsu) +// Most pages use only a fraction (hundreds or less) glyphs out of a given font +// (which can have >20K glyphs for CJK). It's safe to assume that the subset +// font will have sparse bitmap glyphs. So we reconstruct the EBLC table as +// format 4 or 5 here. + +enum BuildersToRemove { + kRemoveNone, + kRemoveBDAT, + kRemoveBDATAndEBDT +}; + +int SetupBitmapBuilders(Font* font, Font::Builder* font_builder, + const IntegerSet& glyph_ids) { + if (!font || !font_builder) { return false; } - EbdtTablePtr ebdt_table = - down_cast(font->GetTable(use_ebdt ? Tag::EBDT : Tag::bdat)); - EblcTablePtr eblc_table = - down_cast(font->GetTable(use_ebdt ? Tag::EBLC : Tag::bloc)); + // Check if bitmap table exists. + EbdtTablePtr ebdt_table = down_cast(font->GetTable(Tag::EBDT)); + EblcTablePtr eblc_table = down_cast(font->GetTable(Tag::EBLC)); + bool use_ebdt = (ebdt_table != NULL && eblc_table != NULL); + if (!use_ebdt) { + ebdt_table = down_cast(font->GetTable(Tag::bdat)); + eblc_table = down_cast(font->GetTable(Tag::bloc)); + if (ebdt_table == NULL || eblc_table == NULL) { + return kRemoveNone; + } + } // If the bitmap table's size is too small, skip subsetting. if (ebdt_table->DataLength() + eblc_table->DataLength() < BITMAP_SIZE_THRESHOLD) { - return true; + return use_ebdt ? kRemoveBDAT : kRemoveNone; } // Get the builders. - FontBuilderPtr font_builder = builder; EbdtTableBuilderPtr ebdt_table_builder = down_cast( font_builder->NewTableBuilder(use_ebdt ? Tag::EBDT : Tag::bdat, ebdt_table->ReadFontData())); @@ -610,45 +582,22 @@ bool SetupBitmapBuilders(Font* font, Font::Builder* builder, eblc_table->ReadFontData())); if (ebdt_table_builder == NULL || eblc_table_builder == NULL) { // Out of memory. - return false; + return use_ebdt ? kRemoveBDAT : kRemoveNone; } - if (!ShallSubset(ebdt_table_builder, eblc_table_builder, glyph_ids)) { + if (!InitializeBitmapBuilder(ebdt_table_builder, eblc_table_builder, + glyph_ids)) { // Bitmap tables do not cover the glyphs in our subset. font_builder->RemoveTableBuilder(use_ebdt ? Tag::EBLC : Tag::bloc); font_builder->RemoveTableBuilder(use_ebdt ? Tag::EBDT : Tag::bdat); - return false; + return kRemoveBDATAndEBDT; } BitmapLocaList new_loca; ebdt_table_builder->GenerateLocaList(&new_loca); SubsetEBLC(eblc_table_builder, new_loca); - return true; -} - -enum BitmapDetection { - kNotFound, - kEBDTFound, - kOnlyBDATFound -}; - -// Some fonts have both EBDT/EBLC and bdat/bloc, we need only one set of them. -int DetectBitmapBuilders(Font* font) { - // Check if bitmap table exists. - EbdtTablePtr ebdt_table = down_cast(font->GetTable(Tag::EBDT)); - EblcTablePtr eblc_table = down_cast(font->GetTable(Tag::EBLC)); - if (ebdt_table == NULL && eblc_table == NULL) { - // Check BDAT variants. - ebdt_table = down_cast(font->GetTable(Tag::bdat)); - eblc_table = down_cast(font->GetTable(Tag::bloc)); - if (ebdt_table == NULL || eblc_table == NULL) { - // There's no bitmap tables. - return kNotFound; - } - return kOnlyBDATFound; - } - return kEBDTFound; + return use_ebdt ? kRemoveBDAT : kRemoveNone; } SubsetterImpl::SubsetterImpl() { @@ -700,7 +649,7 @@ int SubsetterImpl::SubsetFont(const unsigned int* glyph_ids, } FontPtr new_font; - new_font.Attach(Subset(glyph_id_processed)); + new_font.Attach(Subset(glyph_id_processed, glyph_table, loca_table)); if (new_font == NULL) { return 0; } @@ -716,56 +665,58 @@ int SubsetterImpl::SubsetFont(const unsigned int* glyph_ids, return length; } -/******************************************************************************* - Long comments regarding TTF tables and PDF - -According to PDF spec (section 9.9), the following tables must present: - head, hhea, loca, maxp, cvt, prep, glyf, hmtx, fpgm - cmap if font is used as a TTF and not a CIDFont dict - -Other tables we need to keep for PDF rendering to support zoom in/out: - bdat, bloc, ebdt, eblc, ebsc, gasp - -Special table: - CFF - if you have this table then you shouldn't have a glyf table and this is - the table with all the glyphs. Shall skip subsetting completely since - sfntly is not capable of subsetting it for now. - post - extra info here for printing on PostScript printers but maybe not - enough to outweigh the space taken by the names - -Tables to break apart: - name - could throw away all but one language and one platform strings / might - throw away some of the name entries - cmap - could strip out non-needed cmap subtables - - format 4 subtable can be subsetted as well using sfntly - -Graphite tables: - silf, glat, gloc, feat - shall be okay to strip out - -Tables that can be discarded: - OS/2 - everything here is for layout and description of the font that is - elsewhere (some in the PDF objects) - BASE, GDEF, GSUB, GPOS, JSTF - all used for layout - kern - old style layout - DSIG - this will be invalid after subsetting - hdmx - layout - PCLT - metadata that's not needed - vmtx - layout - vhea - layout - VDMX - VORG - not used by TT/OT - used by CFF - hsty - would be surprised if you saw one of these - used on the Newton - AAT tables - mort, morx, feat, acnt, bsin, just, lcar, fdsc, fmtx, prop, - Zapf, opbd, trak, fvar, gvar, avar, cvar - - these are all layout tables and once layout happens are not - needed anymore - LTSH - layout -*******************************************************************************/ -CALLER_ATTACH Font* SubsetterImpl::Subset(const IntegerSet& glyph_ids) { +// Long comments regarding TTF tables and PDF (from stuartg) +// +// According to PDF spec 1.4 (section 5.8), the following tables must be +// present: +// head, hhea, loca, maxp, cvt, prep, glyf, hmtx, fpgm +// cmap if font is used with a simple font dict and not a CIDFont dict +// +// Other tables we need to keep for PDF rendering to support zoom in/out: +// bdat, bloc, ebdt, eblc, ebsc, gasp +// +// Special table: +// CFF - if you have this table then you shouldn't have a glyf table and this +// is the table with all the glyphs. Shall skip subsetting completely +// since sfntly is not capable of subsetting it for now. +// post - extra info here for printing on PostScript printers but maybe not +// enough to outweigh the space taken by the names +// +// Tables to break apart: +// name - could throw away all but one language and one platform strings/ might +// throw away some of the name entries +// cmap - could strip out non-needed cmap subtables +// - format 4 subtable can be subsetted as well using sfntly +// +// Graphite tables: +// silf, glat, gloc, feat - should be okay to strip out +// +// Tables that can be discarded: +// OS/2 - everything here is for layout and description of the font that is +// elsewhere (some in the PDF objects) +// BASE, GDEF, GSUB, GPOS, JSTF - all used for layout +// kern - old style layout +// DSIG - this will be invalid after subsetting +// hdmx - layout +// PCLT - metadata that's not needed +// vmtx - layout +// vhea - layout +// VDMX +// VORG - not used by TT/OT - used by CFF +// hsty - would be surprised to see one of these - used on the Newton +// AAT tables - mort, morx, feat, acnt, bsin, just, lcar, fdsc, fmtx, prop, +// Zapf, opbd, trak, fvar, gvar, avar, cvar +// - these are all layout tables and once layout happens are not +// needed anymore +// LTSH - layout + +CALLER_ATTACH +Font* SubsetterImpl::Subset(const IntegerSet& glyph_ids, GlyphTable* glyf, + LocaTable* loca) { // The const is initialized here to workaround VC bug of rendering all Tag::* // as 0. These tags represents the TTF tables that we will embed in subset // font. - const int32_t VALID_TABLE_TAG[] = { + const int32_t TABLES_IN_SUBSET[] = { Tag::head, Tag::hhea, Tag::loca, Tag::maxp, Tag::cvt, Tag::prep, Tag::glyf, Tag::hmtx, Tag::fpgm, Tag::EBDT, Tag::EBLC, Tag::EBSC, Tag::bdat, Tag::bloc, Tag::bhed, @@ -778,45 +729,36 @@ CALLER_ATTACH Font* SubsetterImpl::Subset(const IntegerSet& glyph_ids) { font_builder.Attach(factory_->NewFontBuilder()); IntegerSet remove_tags; - GlyphTablePtr glyph_table = - down_cast(font_->GetTable(Tag::glyf)); - LocaTablePtr loca_table = down_cast(font_->GetTable(Tag::loca)); - - if (SetupGlyfBuilders(font_builder, glyph_table, loca_table, glyph_ids)) { + if (SetupGlyfBuilders(font_builder, glyf, loca, glyph_ids)) { remove_tags.insert(Tag::glyf); remove_tags.insert(Tag::loca); } - int flag = DetectBitmapBuilders(font_); - if (flag != kNotFound) { - bool use_ebdt = (flag == kEBDTFound); - bool subset_success = - SetupBitmapBuilders(font_, font_builder, glyph_ids, use_ebdt); - - if (use_ebdt || !subset_success) { - remove_tags.insert(Tag::bdat); - remove_tags.insert(Tag::bloc); - remove_tags.insert(Tag::bhed); - } - if (use_ebdt && !subset_success) { + switch (SetupBitmapBuilders(font_, font_builder, glyph_ids)) { + case kRemoveBDATAndEBDT: remove_tags.insert(Tag::EBDT); remove_tags.insert(Tag::EBLC); remove_tags.insert(Tag::EBSC); - } + case kRemoveBDAT: + remove_tags.insert(Tag::bdat); + remove_tags.insert(Tag::bloc); + remove_tags.insert(Tag::bhed); + break; + default: // kRemoveNone + break; } IntegerSet allowed_tags; - for (size_t i = 0; i < sizeof(VALID_TABLE_TAG) / sizeof(int32_t); ++i) { - allowed_tags.insert(VALID_TABLE_TAG[i]); - } - for (IntegerSet::iterator i = remove_tags.begin(), e = remove_tags.end(); - i != e; i++) { - IntegerSet::iterator it = allowed_tags.find(*i); - if (it != allowed_tags.end()) { - allowed_tags.erase(it); - } + for (size_t i = 0; i < sizeof(TABLES_IN_SUBSET) / sizeof(int32_t); ++i) { + allowed_tags.insert(TABLES_IN_SUBSET[i]); } + IntegerSet result; + std::set_difference(allowed_tags.begin(), allowed_tags.end(), + remove_tags.begin(), remove_tags.end(), + std::inserter(result, result.end())); + allowed_tags = result; + // Setup remaining builders. for (IntegerSet::iterator i = allowed_tags.begin(), e = allowed_tags.end(); i != e; ++i) { diff --git a/test/subsetter_impl.h b/test/subsetter_impl.h index 5e6debe..ffbf408 100644 --- a/test/subsetter_impl.h +++ b/test/subsetter_impl.h @@ -21,6 +21,8 @@ #include "sfntly/font.h" #include "sfntly/font_factory.h" +#include "sfntly/table/truetype/glyph_table.h" +#include "sfntly/table/truetype/loca_table.h" #include "sfntly/tag.h" namespace sfntly { @@ -60,7 +62,8 @@ class SubsetterImpl { unsigned char** output_buffer); private: - CALLER_ATTACH Font* Subset(const IntegerSet& glyph_ids); + CALLER_ATTACH Font* Subset(const IntegerSet& glyph_ids, + GlyphTable* glyf, LocaTable* loca); FontFactoryPtr factory_; FontPtr font_; -- cgit v1.2.3 From c73f0572c9f4b2b2d0afacbd1ccd64927cf2c8a3 Mon Sep 17 00:00:00 2001 From: "arthurhsu@google.com" Date: Fri, 9 Dec 2011 01:57:25 +0000 Subject: Update per code review git-svn-id: http://sfntly.googlecode.com/svn/trunk/cpp/src@115 672e30a5-4c29-85ac-ac6d-611c735e0a51 --- test/subsetter_impl.cc | 33 +++++++++++++++++++-------------- 1 file changed, 19 insertions(+), 14 deletions(-) diff --git a/test/subsetter_impl.cc b/test/subsetter_impl.cc index 7759d09..4786f7f 100644 --- a/test/subsetter_impl.cc +++ b/test/subsetter_impl.cc @@ -526,6 +526,9 @@ void SubsetEBLC(EblcTable::Builder* eblc, const BitmapLocaList& new_loca) { // one per indexSubTableArray entry // tells how to get the glyphs // may hold the glyph metrics if they are uniform for all the glyphs in range +// Please note that the structure can also be +// {indexSubTableArray[], indexSubTables[]}[] +// This way is also legal and in fact how Microsoft fonts are laid out. // // There is nothing that says that the indexSubTableArray entries and/or the // indexSubTable items need to be unique. They may be shared between strikes. @@ -546,7 +549,8 @@ void SubsetEBLC(EblcTable::Builder* eblc, const BitmapLocaList& new_loca) { enum BuildersToRemove { kRemoveNone, kRemoveBDAT, - kRemoveBDATAndEBDT + kRemoveBDATAndEBDT, + kRemoveEBDT }; int SetupBitmapBuilders(Font* font, Font::Builder* font_builder, @@ -590,7 +594,7 @@ int SetupBitmapBuilders(Font* font, Font::Builder* font_builder, // Bitmap tables do not cover the glyphs in our subset. font_builder->RemoveTableBuilder(use_ebdt ? Tag::EBLC : Tag::bloc); font_builder->RemoveTableBuilder(use_ebdt ? Tag::EBDT : Tag::bdat); - return kRemoveBDATAndEBDT; + return use_ebdt ? kRemoveBDATAndEBDT : kRemoveEBDT; } BitmapLocaList new_loca; @@ -734,18 +738,19 @@ Font* SubsetterImpl::Subset(const IntegerSet& glyph_ids, GlyphTable* glyf, remove_tags.insert(Tag::loca); } - switch (SetupBitmapBuilders(font_, font_builder, glyph_ids)) { - case kRemoveBDATAndEBDT: - remove_tags.insert(Tag::EBDT); - remove_tags.insert(Tag::EBLC); - remove_tags.insert(Tag::EBSC); - case kRemoveBDAT: - remove_tags.insert(Tag::bdat); - remove_tags.insert(Tag::bloc); - remove_tags.insert(Tag::bhed); - break; - default: // kRemoveNone - break; + // For old Apple bitmap fonts, they have only bdats and bhed is identical + // to head. As a result, we can't remove bdat tables for those fonts. + int setup_result = SetupBitmapBuilders(font_, font_builder, glyph_ids); + if (setup_result == kRemoveBDATAndEBDT || setup_result == kRemoveEBDT) { + remove_tags.insert(Tag::EBDT); + remove_tags.insert(Tag::EBLC); + remove_tags.insert(Tag::EBSC); + } + + if (setup_result == kRemoveBDAT || setup_result == kRemoveBDATAndEBDT) { + remove_tags.insert(Tag::bdat); + remove_tags.insert(Tag::bloc); + remove_tags.insert(Tag::bhed); } IntegerSet allowed_tags; -- cgit v1.2.3 From a70737a5b6ca5cd32e1a47adb847e1d016e1502b Mon Sep 17 00:00:00 2001 From: "arthurhsu@google.com" Date: Fri, 9 Dec 2011 02:13:39 +0000 Subject: Patch from Nico Weber: remove static initializers. This is needed because gcc 4.4.3 can't evaluate simple static functions at compile time. git-svn-id: http://sfntly.googlecode.com/svn/trunk/cpp/src@116 672e30a5-4c29-85ac-ac6d-611c735e0a51 --- sfntly/font.cc | 6 ++-- sfntly/tag.cc | 98 ++++++++++++++++++++++++++++++---------------------------- 2 files changed, 55 insertions(+), 49 deletions(-) diff --git a/sfntly/font.cc b/sfntly/font.cc index c9798c8..347e0c1 100644 --- a/sfntly/font.cc +++ b/sfntly/font.cc @@ -40,7 +40,8 @@ namespace sfntly { -const int32_t SFNTVERSION_1 = Fixed1616::Fixed(1, 0); +const int32_t SFNTVERSION_MAJOR = 1; +const int32_t SFNTVERSION_MINOR = 0; /****************************************************************************** * Font class @@ -314,7 +315,8 @@ void Font::Builder::RemoveTableBuilder(int32_t tag) { } Font::Builder::Builder(FontFactory* factory) - : factory_(factory), sfnt_version_(SFNTVERSION_1) { + : factory_(factory), + sfnt_version_(Fixed1616::Fixed(SFNTVERSION_MAJOR, SFNTVERSION_MINOR)) { } void Font::Builder::LoadFont(InputStream* is) { diff --git a/sfntly/tag.cc b/sfntly/tag.cc index 893b74d..c9d8c29 100644 --- a/sfntly/tag.cc +++ b/sfntly/tag.cc @@ -17,55 +17,59 @@ #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 = GenerateTag('t', 't', 'c', 'f'); -const int32_t Tag::cmap = GenerateTag('c', 'm', 'a', 'p'); -const int32_t Tag::head = GenerateTag('h', 'e', 'a', 'd'); -const int32_t Tag::hhea = GenerateTag('h', 'h', 'e', 'a'); -const int32_t Tag::hmtx = GenerateTag('h', 'm', 't', 'x'); -const int32_t Tag::maxp = GenerateTag('m', 'a', 'x', 'p'); -const int32_t Tag::name = GenerateTag('n', 'a', 'm', 'e'); -const int32_t Tag::OS_2 = GenerateTag('O', 'S', '/', '2'); -const int32_t Tag::post = GenerateTag('p', 'o', 's', 't'); -const int32_t Tag::cvt = GenerateTag('c', 'v', 't', ' '); -const int32_t Tag::fpgm = GenerateTag('f', 'p', 'g', 'm'); -const int32_t Tag::glyf = GenerateTag('g', 'l', 'y', 'f'); -const int32_t Tag::loca = GenerateTag('l', 'o', 'c', 'a'); -const int32_t Tag::prep = GenerateTag('p', 'r', 'e', 'p'); -const int32_t Tag::CFF = GenerateTag('C', 'F', 'F', ' '); -const int32_t Tag::VORG = GenerateTag('V', 'O', 'R', 'G'); -const int32_t Tag::EBDT = GenerateTag('E', 'B', 'D', 'T'); -const int32_t Tag::EBLC = GenerateTag('E', 'B', 'L', 'C'); -const int32_t Tag::EBSC = GenerateTag('E', 'B', 'S', 'C'); -const int32_t Tag::BASE = GenerateTag('B', 'A', 'S', 'E'); -const int32_t Tag::GDEF = GenerateTag('G', 'D', 'E', 'F'); -const int32_t Tag::GPOS = GenerateTag('G', 'P', 'O', 'S'); -const int32_t Tag::GSUB = GenerateTag('G', 'S', 'U', 'B'); -const int32_t Tag::JSTF = GenerateTag('J', 'S', 'T', 'F'); -const int32_t Tag::DSIG = GenerateTag('D', 'S', 'I', 'G'); -const int32_t Tag::gasp = GenerateTag('g', 'a', 's', 'p'); -const int32_t Tag::hdmx = GenerateTag('h', 'd', 'm', 'x'); -const int32_t Tag::kern = GenerateTag('k', 'e', 'r', 'n'); -const int32_t Tag::LTSH = GenerateTag('L', 'T', 'S', 'H'); -const int32_t Tag::PCLT = GenerateTag('P', 'C', 'L', 'T'); -const int32_t Tag::VDMX = GenerateTag('V', 'D', 'M', 'X'); -const int32_t Tag::vhea = GenerateTag('v', 'h', 'e', 'a'); -const int32_t Tag::vmtx = GenerateTag('v', 'm', 't', 'x'); -const int32_t Tag::bsln = GenerateTag('b', 's', 'l', 'n'); -const int32_t Tag::feat = GenerateTag('f', 'e', 'a', 't'); -const int32_t Tag::lcar = GenerateTag('l', 'c', 'a', 'r'); -const int32_t Tag::morx = GenerateTag('m', 'o', 'r', 'x'); -const int32_t Tag::opbd = GenerateTag('o', 'p', 'b', 'd'); -const int32_t Tag::prop = GenerateTag('p', 'r', 'o', 'p'); -const int32_t Tag::Feat = GenerateTag('F', 'e', 'a', 't'); -const int32_t Tag::Glat = GenerateTag('G', 'l', 'a', 't'); -const int32_t Tag::Gloc = GenerateTag('G', 'l', 'o', 'c'); -const int32_t Tag::Sile = GenerateTag('S', 'i', 'l', 'e'); -const int32_t Tag::Silf = GenerateTag('S', 'i', 'l', 'f'); -const int32_t Tag::bhed = GenerateTag('b', 'h', 'e', 'd'); -const int32_t Tag::bdat = GenerateTag('b', 'd', 'a', 't'); -const int32_t Tag::bloc = GenerateTag('b', 'l', 'o', 'c'); +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, -- cgit v1.2.3 From 2407b4212a6391f3993d46b5aae93da6556305a4 Mon Sep 17 00:00:00 2001 From: "arthurhsu@google.com" Date: Fri, 9 Dec 2011 02:25:57 +0000 Subject: Update test files for macro changes in previous CL git-svn-id: http://sfntly.googlecode.com/svn/trunk/cpp/src@117 672e30a5-4c29-85ac-ac6d-611c735e0a51 --- test/verify_hhea.cc | 3 ++- test/verify_maxp.cc | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/test/verify_hhea.cc b/test/verify_hhea.cc index 021c189..81ddb58 100644 --- a/test/verify_hhea.cc +++ b/test/verify_hhea.cc @@ -16,6 +16,7 @@ #include "gtest/gtest.h" #include "sfntly/font.h" +#include "sfntly/math/fixed1616.h" #include "sfntly/table/core/horizontal_header_table.h" #include "test/serialization_test.h" @@ -37,7 +38,7 @@ static bool VerifyHHEA(Table* table) { return false; } - EXPECT_EQ(hhea->TableVersion(), SFNTVERSION_1); + EXPECT_EQ(hhea->TableVersion(), Fixed1616::Fixed(1, 0)); EXPECT_EQ(hhea->Ascender(), HHEA_ASCENDER); EXPECT_EQ(hhea->Descender(), HHEA_DESCENDER); EXPECT_EQ(hhea->AdvanceWidthMax(), HHEA_ADVANCE_WIDTH_MAX); diff --git a/test/verify_maxp.cc b/test/verify_maxp.cc index 437c0dd..dcd776e 100644 --- a/test/verify_maxp.cc +++ b/test/verify_maxp.cc @@ -16,6 +16,7 @@ #include "gtest/gtest.h" #include "sfntly/font.h" +#include "sfntly/math/fixed1616.h" #include "sfntly/table/core/maximum_profile_table.h" #include "test/serialization_test.h" @@ -42,7 +43,7 @@ static bool VerifyMAXP(Table* table) { return false; } - EXPECT_EQ(maxp->TableVersion(), SFNTVERSION_1); + EXPECT_EQ(maxp->TableVersion(), Fixed1616::Fixed(1, 0)); EXPECT_EQ(maxp->NumGlyphs(), MAXP_NUM_GLYPHS); EXPECT_EQ(maxp->MaxPoints(), MAXP_MAX_POINTS); EXPECT_EQ(maxp->MaxContours(), MAXP_MAX_CONTOURS); -- cgit v1.2.3 From ca72e2646f852b6c39ef1b07fa9b250988ce9d54 Mon Sep 17 00:00:00 2001 From: "arthurhsu@google.com" Date: Mon, 12 Dec 2011 22:29:05 +0000 Subject: Move Chromium subsetter code to sample, update CMakeLists accordingly. Remove unused const in font.h. git-svn-id: http://sfntly.googlecode.com/svn/trunk/cpp/src@118 672e30a5-4c29-85ac-ac6d-611c735e0a51 --- sample/chromium/chrome_subsetter.cc | 2 +- sample/chromium/font_subsetter.cc | 39 ++ sample/chromium/font_subsetter.h | 51 +++ sample/chromium/subsetter_impl.cc | 777 +++++++++++++++++++++++++++++++++++ sample/chromium/subsetter_impl.h | 74 ++++ sfntly/font.h | 2 - test/chrome_subsetter.cc | 2 +- test/font_subsetter.cc | 41 -- test/font_subsetter.h | 51 --- test/subsetter_impl.cc | 779 ------------------------------------ test/subsetter_impl.h | 74 ---- 11 files changed, 943 insertions(+), 949 deletions(-) create mode 100644 sample/chromium/font_subsetter.cc create mode 100644 sample/chromium/font_subsetter.h create mode 100644 sample/chromium/subsetter_impl.cc create mode 100644 sample/chromium/subsetter_impl.h delete mode 100644 test/font_subsetter.cc delete mode 100644 test/font_subsetter.h delete mode 100644 test/subsetter_impl.cc delete mode 100644 test/subsetter_impl.h diff --git a/sample/chromium/chrome_subsetter.cc b/sample/chromium/chrome_subsetter.cc index 6f5788e..df15c18 100644 --- a/sample/chromium/chrome_subsetter.cc +++ b/sample/chromium/chrome_subsetter.cc @@ -21,7 +21,7 @@ #include #include "sfntly/port/type.h" -#include "test/font_subsetter.h" +#include "font_subsetter.h" template class HexTo { diff --git a/sample/chromium/font_subsetter.cc b/sample/chromium/font_subsetter.cc new file mode 100644 index 0000000..14f5494 --- /dev/null +++ b/sample/chromium/font_subsetter.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 "font_subsetter.h" + +#include "subsetter_impl.h" + +int SfntlyWrapper::SubsetFont(const char* font_name, + const unsigned char* original_font, + size_t font_size, + const unsigned int* glyph_ids, + size_t glyph_count, + unsigned char** output_buffer) { + if (output_buffer == NULL || + original_font == NULL || font_size == 0 || + glyph_ids == NULL || glyph_count == 0) { + return 0; + } + + sfntly::SubsetterImpl subsetter; + if (!subsetter.LoadFont(font_name, original_font, font_size)) { + return -1; // Load error or font not found. + } + + return subsetter.SubsetFont(glyph_ids, glyph_count, output_buffer); +} diff --git a/sample/chromium/font_subsetter.h b/sample/chromium/font_subsetter.h new file mode 100644 index 0000000..07b1b5b --- /dev/null +++ b/sample/chromium/font_subsetter.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. + */ +// File is originally from Chromium third_party/sfntly/src/subsetter. +// Use as test case in sfntly so that problems can be caught in upstream early. +#ifndef SFNTLY_CPP_SRC_TEST_FONT_SUBSETTER_H_ +#define SFNTLY_CPP_SRC_TEST_FONT_SUBSETTER_H_ + +#include + +class SfntlyWrapper { + public: + + // Font subsetting API + // + // Input TTF/TTC/OTF fonts, specify the glyph IDs to subset, and the subset + // font is returned in |output_buffer| (caller to delete[]). Return value is + // the length of output_buffer allocated. + // + // If subsetting fails, a negative value is returned. If none of the glyph + // IDs specified is found, the function will return 0. + // + // |font_name| Font name, required for TTC files. If specified NULL, + // the first available font is selected. + // |original_font| Original font file contents. + // |font_size| Size of |original_font| in bytes. + // |glyph_ids| Glyph IDs to subset. If the specified glyph ID is not + // found in the font file, it will be ignored silently. + // |glyph_count| Number of glyph IDs in |glyph_ids| + // |output_buffer| Generated subset font. Caller to delete[]. + static int SubsetFont(const char* font_name, + const unsigned char* original_font, + size_t font_size, + const unsigned int* glyph_ids, + size_t glyph_count, + unsigned char** output_buffer); +}; + +#endif // SFNTLY_CPP_SRC_TEST_FONT_SUBSETTER_H_ diff --git a/sample/chromium/subsetter_impl.cc b/sample/chromium/subsetter_impl.cc new file mode 100644 index 0000000..7e7cf61 --- /dev/null +++ b/sample/chromium/subsetter_impl.cc @@ -0,0 +1,777 @@ +/* + * 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 "subsetter_impl.h" + +#include + +#include +#include +#include +#include + +#include "sfntly/table/bitmap/eblc_table.h" +#include "sfntly/table/bitmap/ebdt_table.h" +#include "sfntly/table/bitmap/index_sub_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" +#include "sfntly/table/core/name_table.h" +#include "sfntly/tag.h" +#include "sfntly/data/memory_byte_array.h" +#include "sfntly/port/memory_input_stream.h" +#include "sfntly/port/memory_output_stream.h" + +#if defined U_USING_ICU_NAMESPACE + U_NAMESPACE_USE +#endif + +namespace { + +using namespace sfntly; + +// The bitmap tables must be greater than 16KB to trigger bitmap subsetter. +static const int BITMAP_SIZE_THRESHOLD = 16384; + +void ConstructName(UChar* name_part, UnicodeString* name, int32_t name_id) { + switch (name_id) { + case NameId::kFullFontName: + *name = name_part; + break; + case NameId::kFontFamilyName: + case NameId::kPreferredFamily: + case NameId::kWWSFamilyName: { + UnicodeString original = *name; + *name = name_part; + *name += original; + break; + } + case NameId::kFontSubfamilyName: + case NameId::kPreferredSubfamily: + case NameId::kWWSSubfamilyName: + *name += name_part; + break; + default: + // This name part is not used to construct font name (e.g. copyright). + // Simply ignore it. + break; + } +} + +int32_t HashCode(int32_t platform_id, int32_t encoding_id, int32_t language_id, + int32_t name_id) { + int32_t result = platform_id << 24 | encoding_id << 16 | language_id << 8; + if (name_id == NameId::kFullFontName) { + result |= 0xff; + } else if (name_id == NameId::kPreferredFamily || + name_id == NameId::kPreferredSubfamily) { + result |= 0xf; + } else if (name_id == NameId::kWWSFamilyName || + name_id == NameId::kWWSSubfamilyName) { + result |= 1; + } + return result; +} + +bool HasName(const char* font_name, Font* font) { + UnicodeString font_string = UnicodeString::fromUTF8(font_name); + if (font_string.isEmpty()) + return false; + UnicodeString regular_suffix = UnicodeString::fromUTF8(" Regular"); + UnicodeString alt_font_string = font_string; + alt_font_string += regular_suffix; + + typedef std::map NameMap; + NameMap names; + NameTablePtr name_table = down_cast(font->GetTable(Tag::name)); + if (name_table == NULL) { + return false; + } + + for (int32_t i = 0; i < name_table->NameCount(); ++i) { + switch (name_table->NameId(i)) { + case NameId::kFontFamilyName: + case NameId::kFontSubfamilyName: + case NameId::kFullFontName: + case NameId::kPreferredFamily: + case NameId::kPreferredSubfamily: + case NameId::kWWSFamilyName: + case NameId::kWWSSubfamilyName: { + int32_t hash_code = HashCode(name_table->PlatformId(i), + name_table->EncodingId(i), + name_table->LanguageId(i), + name_table->NameId(i)); + UChar* name_part = name_table->Name(i); + ConstructName(name_part, &(names[hash_code]), name_table->NameId(i)); + delete[] name_part; + break; + } + default: + break; + } + } + + if (!names.empty()) { + for (NameMap::iterator i = names.begin(), e = names.end(); i != e; ++i) { + if (i->second.caseCompare(font_string, 0) == 0 || + i->second.caseCompare(alt_font_string, 0) == 0) { + return true; + } + } + } + return false; +} + +Font* FindFont(const char* font_name, const FontArray& font_array) { + if (font_array.empty() || font_array[0] == NULL) { + return NULL; + } + + if (font_name && strlen(font_name)) { + for (FontArray::const_iterator i = font_array.begin(), e = font_array.end(); + i != e; ++i) { + if (HasName(font_name, i->p_)) { + return i->p_; + } + } + } + + return font_array[0].p_; +} + +bool ResolveCompositeGlyphs(GlyphTable* glyph_table, + LocaTable* loca_table, + const unsigned int* glyph_ids, + size_t glyph_count, + IntegerSet* glyph_id_processed) { + if (glyph_table == NULL || loca_table == NULL || + glyph_ids == NULL || glyph_count == 0 || glyph_id_processed == NULL) { + return false; + } + + // Sort and uniquify glyph ids. + IntegerSet glyph_id_remaining; + glyph_id_remaining.insert(0); // Always include glyph id 0. + for (size_t i = 0; i < glyph_count; ++i) { + glyph_id_remaining.insert(glyph_ids[i]); + } + + // Identify if any given glyph id maps to a composite glyph. If so, include + // the glyphs referenced by that composite glyph. + while (!glyph_id_remaining.empty()) { + IntegerSet comp_glyph_id; + for (IntegerSet::iterator i = glyph_id_remaining.begin(), + e = glyph_id_remaining.end(); i != e; ++i) { + if (*i < 0 || *i >= loca_table->num_glyphs()) { + // Invalid glyph id, ignore. + continue; + } + + int32_t length = loca_table->GlyphLength(*i); + if (length == 0) { + // Empty glyph, ignore. + continue; + } + int32_t offset = loca_table->GlyphOffset(*i); + + GlyphPtr glyph; + glyph.Attach(glyph_table->GetGlyph(offset, length)); + if (glyph == NULL) { + // Error finding glyph, ignore. + continue; + } + + if (glyph->GlyphType() == GlyphType::kComposite) { + Ptr comp_glyph = + down_cast(glyph.p_); + for (int32_t j = 0; j < comp_glyph->NumGlyphs(); ++j) { + int32_t glyph_id = comp_glyph->GlyphIndex(j); + if (glyph_id_processed->find(glyph_id) == glyph_id_processed->end() && + glyph_id_remaining.find(glyph_id) == glyph_id_remaining.end()) { + comp_glyph_id.insert(comp_glyph->GlyphIndex(j)); + } + } + } + + glyph_id_processed->insert(*i); + } + + glyph_id_remaining.clear(); + glyph_id_remaining = comp_glyph_id; + } + + return true; +} + +bool SetupGlyfBuilders(Font::Builder* font_builder, + GlyphTable* glyph_table, + LocaTable* loca_table, + const IntegerSet& glyph_ids) { + if (!font_builder || !glyph_table || !loca_table) { + 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) { + // Out of memory. + return false; + } + + // Extract glyphs and setup loca list. + IntegerList loca_list; + loca_list.resize(loca_table->num_glyphs()); + loca_list.push_back(0); + int32_t last_glyph_id = 0; + int32_t last_offset = 0; + GlyphTable::GlyphBuilderList* glyph_builders = + glyph_table_builder->GlyphBuilders(); + for (IntegerSet::const_iterator i = glyph_ids.begin(), e = glyph_ids.end(); + i != e; ++i) { + int32_t length = loca_table->GlyphLength(*i); + int32_t offset = loca_table->GlyphOffset(*i); + + GlyphPtr glyph; + glyph.Attach(glyph_table->GetGlyph(offset, length)); + + // Add glyph to new glyf table. + 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); + + // Configure loca list. + for (int32_t j = last_glyph_id + 1; j <= *i; ++j) { + loca_list[j] = last_offset; + } + last_offset += length; + loca_list[*i + 1] = last_offset; + last_glyph_id = *i; + } + for (int32_t j = last_glyph_id + 1; j <= loca_table->num_glyphs(); ++j) { + loca_list[j] = last_offset; + } + loca_table_builder->SetLocaList(&loca_list); + + return true; +} + +bool HasOverlap(int32_t range_begin, int32_t range_end, + const IntegerSet& glyph_ids) { + if (range_begin == range_end) { + return glyph_ids.find(range_begin) != glyph_ids.end(); + } else if (range_end > range_begin) { + IntegerSet::const_iterator left = glyph_ids.lower_bound(range_begin); + IntegerSet::const_iterator right = glyph_ids.lower_bound(range_end); + return right != left; + } + return false; +} + +// Initialize builder, returns false if glyph_id subset is not covered. +// Not thread-safe, caller to ensure object life-time. +bool InitializeBitmapBuilder(EbdtTable::Builder* ebdt, EblcTable::Builder* eblc, + const IntegerSet& glyph_ids) { + BitmapLocaList loca_list; + BitmapSizeTableBuilderList* strikes = eblc->BitmapSizeBuilders(); + + // Note: Do not call eblc_builder->GenerateLocaList(&loca_list) and then + // ebdt_builder->SetLoca(loca_list). For fonts like SimSun, there are + // >28K glyphs inside, where a typical usage will be <1K glyphs. Doing + // the calls improperly will result in creation of >100K objects that + // will be destroyed immediately, inducing significant slowness. + IntegerList removed_strikes; + for (size_t i = 0; i < strikes->size(); i++) { + if (!HasOverlap((*strikes)[i]->StartGlyphIndex(), + (*strikes)[i]->EndGlyphIndex(), glyph_ids)) { + removed_strikes.push_back(i); + continue; + } + + IndexSubTableBuilderList* index_builders = + (*strikes)[i]->IndexSubTableBuilders(); + IntegerList removed_indexes; + BitmapGlyphInfoMap info_map; + for (size_t j = 0; j < index_builders->size(); ++j) { + int32_t first_glyph_id = (*index_builders)[j]->first_glyph_index(); + int32_t last_glyph_id = (*index_builders)[j]->last_glyph_index(); + if (!HasOverlap(first_glyph_id, last_glyph_id, glyph_ids)) { + removed_indexes.push_back(j); + continue; + } + for (IntegerSet::const_iterator gid = glyph_ids.begin(), + gid_end = glyph_ids.end(); + gid != gid_end; gid++) { + if (*gid < first_glyph_id) { + continue; + } + if (*gid > last_glyph_id) { + break; + } + BitmapGlyphInfoPtr info; + info.Attach((*index_builders)[j]->GlyphInfo(*gid)); + if (info && info->length()) { // Do not include gid without bitmap + info_map[*gid] = info; + } + } + } + if (!info_map.empty()) { + loca_list.push_back(info_map); + } else { + removed_strikes.push_back(i); // Detected null entries. + } + + // Remove unused index sub tables + for (IntegerList::reverse_iterator j = removed_indexes.rbegin(), + e = removed_indexes.rend(); + j != e; j++) { + index_builders->erase(index_builders->begin() + *j); + } + } + if (removed_strikes.size() == strikes->size() || loca_list.empty()) { + return false; + } + + for (IntegerList::reverse_iterator i = removed_strikes.rbegin(), + e = removed_strikes.rend(); i != e; i++) { + strikes->erase(strikes->begin() + *i); + } + + if (strikes->empty()) { // no glyph covered, can safely drop the builders. + return false; + } + + ebdt->SetLoca(&loca_list); + ebdt->GlyphBuilders(); // Initialize the builder. + return true; +} + +void CopyBigGlyphMetrics(BigGlyphMetrics::Builder* source, + BigGlyphMetrics::Builder* target) { + target->SetHeight(static_cast(source->Height())); + target->SetWidth(static_cast(source->Width())); + target->SetHoriBearingX(static_cast(source->HoriBearingX())); + target->SetHoriBearingY(static_cast(source->HoriBearingY())); + target->SetHoriAdvance(static_cast(source->HoriAdvance())); + target->SetVertBearingX(static_cast(source->VertBearingX())); + target->SetVertBearingY(static_cast(source->VertBearingY())); + target->SetVertAdvance(static_cast(source->VertAdvance())); +} + +CALLER_ATTACH IndexSubTable::Builder* +ConstructIndexFormat4(IndexSubTable::Builder* b, const BitmapGlyphInfoMap& loca, + int32_t* image_data_offset) { + IndexSubTableFormat4BuilderPtr builder4; + builder4.Attach(IndexSubTableFormat4::Builder::CreateBuilder()); + CodeOffsetPairBuilderList offset_pairs; + + size_t offset = 0; + int32_t lower_bound = b->first_glyph_index(); + int32_t upper_bound = b->last_glyph_index(); + int32_t last_gid = -1; + BitmapGlyphInfoMap::const_iterator i = loca.lower_bound(lower_bound); + BitmapGlyphInfoMap::const_iterator end = loca.end(); + if (i != end) { + last_gid = i->first; + builder4->set_first_glyph_index(last_gid); + builder4->set_image_format(b->image_format()); + builder4->set_image_data_offset(*image_data_offset); + } + for (; i != end; i++) { + int32_t gid = i->first; + if (gid > upper_bound) { + break; + } + offset_pairs.push_back( + IndexSubTableFormat4::CodeOffsetPairBuilder(gid, offset)); + offset += i->second->length(); + last_gid = gid; + } + offset_pairs.push_back( + IndexSubTableFormat4::CodeOffsetPairBuilder(-1, offset)); + builder4->set_last_glyph_index(last_gid); + *image_data_offset += offset; + builder4->SetOffsetArray(offset_pairs); + + return builder4.Detach(); +} + +CALLER_ATTACH IndexSubTable::Builder* +ConstructIndexFormat5(IndexSubTable::Builder* b, const BitmapGlyphInfoMap& loca, + int32_t* image_data_offset) { + IndexSubTableFormat5BuilderPtr new_builder; + new_builder.Attach(IndexSubTableFormat5::Builder::CreateBuilder()); + + // Copy BigMetrics + int32_t image_size = 0; + if (b->index_format() == IndexSubTable::Format::FORMAT_2) { + IndexSubTableFormat2BuilderPtr builder2 = + down_cast(b); + CopyBigGlyphMetrics(builder2->BigMetrics(), new_builder->BigMetrics()); + image_size = builder2->ImageSize(); + } else { + IndexSubTableFormat5BuilderPtr builder5 = + down_cast(b); + BigGlyphMetricsBuilderPtr metrics_builder; + CopyBigGlyphMetrics(builder5->BigMetrics(), new_builder->BigMetrics()); + image_size = builder5->ImageSize(); + } + + IntegerList* glyph_array = new_builder->GlyphArray(); + size_t offset = 0; + int32_t lower_bound = b->first_glyph_index(); + int32_t upper_bound = b->last_glyph_index(); + int32_t last_gid = -1; + BitmapGlyphInfoMap::const_iterator i = loca.lower_bound(lower_bound); + BitmapGlyphInfoMap::const_iterator end = loca.end(); + if (i != end) { + last_gid = i->first; + new_builder->set_first_glyph_index(last_gid); + new_builder->set_image_format(b->image_format()); + new_builder->set_image_data_offset(*image_data_offset); + new_builder->SetImageSize(image_size); + } + for (; i != end; i++) { + int32_t gid = i->first; + if (gid > upper_bound) { + break; + } + glyph_array->push_back(gid); + offset += i->second->length(); + last_gid = gid; + } + new_builder->set_last_glyph_index(last_gid); + *image_data_offset += offset; + return new_builder.Detach(); +} + +CALLER_ATTACH IndexSubTable::Builder* +SubsetIndexSubTable(IndexSubTable::Builder* builder, + const BitmapGlyphInfoMap& loca, + int32_t* image_data_offset) { + switch (builder->index_format()) { + case IndexSubTable::Format::FORMAT_1: + case IndexSubTable::Format::FORMAT_3: + case IndexSubTable::Format::FORMAT_4: + return ConstructIndexFormat4(builder, loca, image_data_offset); + case IndexSubTable::Format::FORMAT_2: + case IndexSubTable::Format::FORMAT_5: + return ConstructIndexFormat5(builder, loca, image_data_offset); + default: + assert(false); + break; + } + return NULL; +} + +} + +namespace sfntly { + +// Not thread-safe, caller to ensure object life-time. +void SubsetEBLC(EblcTable::Builder* eblc, const BitmapLocaList& new_loca) { + BitmapSizeTableBuilderList* size_builders = eblc->BitmapSizeBuilders(); + if (size_builders == NULL) { + return; + } + + int32_t image_data_offset = EbdtTable::Offset::kHeaderLength; + for (size_t strike = 0; strike < size_builders->size(); ++strike) { + IndexSubTableBuilderList* index_builders = + (*size_builders)[strike]->IndexSubTableBuilders(); + for (size_t index = 0; index < index_builders->size(); ++index) { + IndexSubTable::Builder* new_builder_raw = + SubsetIndexSubTable((*index_builders)[index], new_loca[strike], + &image_data_offset); + if (NULL != new_builder_raw) { + (*index_builders)[index].Attach(new_builder_raw); + } + } + } +} + +// EBLC structure (from stuartg) +// header +// bitmapSizeTable[] +// one per strike +// holds strike metrics - sbitLineMetrics +// holds info about indexSubTableArray +// indexSubTableArray[][] +// one per strike and then one per indexSubTable for that strike +// holds info about the indexSubTable +// the indexSubTable entries pointed to can be of different formats +// indexSubTable +// one per indexSubTableArray entry +// tells how to get the glyphs +// may hold the glyph metrics if they are uniform for all the glyphs in range +// Please note that the structure can also be +// {indexSubTableArray[], indexSubTables[]}[] +// This way is also legal and in fact how Microsoft fonts are laid out. +// +// There is nothing that says that the indexSubTableArray entries and/or the +// indexSubTable items need to be unique. They may be shared between strikes. +// +// EBDT structure: +// header +// glyphs +// amorphous blob of data +// different glyphs that are only able to be figured out from the EBLC table +// may hold metrics - depends on the EBLC entry that pointed to them + +// Subsetting EBLC table (from arthurhsu) +// Most pages use only a fraction (hundreds or less) glyphs out of a given font +// (which can have >20K glyphs for CJK). It's safe to assume that the subset +// font will have sparse bitmap glyphs. So we reconstruct the EBLC table as +// format 4 or 5 here. + +enum BuildersToRemove { + kRemoveNone, + kRemoveBDAT, + kRemoveBDATAndEBDT, + kRemoveEBDT +}; + +int SetupBitmapBuilders(Font* font, Font::Builder* font_builder, + const IntegerSet& glyph_ids) { + if (!font || !font_builder) { + return false; + } + + // Check if bitmap table exists. + EbdtTablePtr ebdt_table = down_cast(font->GetTable(Tag::EBDT)); + EblcTablePtr eblc_table = down_cast(font->GetTable(Tag::EBLC)); + bool use_ebdt = (ebdt_table != NULL && eblc_table != NULL); + if (!use_ebdt) { + ebdt_table = down_cast(font->GetTable(Tag::bdat)); + eblc_table = down_cast(font->GetTable(Tag::bloc)); + if (ebdt_table == NULL || eblc_table == NULL) { + return kRemoveNone; + } + } + + // If the bitmap table's size is too small, skip subsetting. + if (ebdt_table->DataLength() + eblc_table->DataLength() < + BITMAP_SIZE_THRESHOLD) { + return use_ebdt ? kRemoveBDAT : kRemoveNone; + } + + // Get the builders. + EbdtTableBuilderPtr ebdt_table_builder = down_cast( + font_builder->NewTableBuilder(use_ebdt ? Tag::EBDT : Tag::bdat, + ebdt_table->ReadFontData())); + EblcTableBuilderPtr eblc_table_builder = down_cast( + font_builder->NewTableBuilder(use_ebdt ? Tag::EBLC : Tag::bloc, + eblc_table->ReadFontData())); + if (ebdt_table_builder == NULL || eblc_table_builder == NULL) { + // Out of memory. + return use_ebdt ? kRemoveBDAT : kRemoveNone; + } + + if (!InitializeBitmapBuilder(ebdt_table_builder, eblc_table_builder, + glyph_ids)) { + // Bitmap tables do not cover the glyphs in our subset. + font_builder->RemoveTableBuilder(use_ebdt ? Tag::EBLC : Tag::bloc); + font_builder->RemoveTableBuilder(use_ebdt ? Tag::EBDT : Tag::bdat); + return use_ebdt ? kRemoveBDATAndEBDT : kRemoveEBDT; + } + + BitmapLocaList new_loca; + ebdt_table_builder->GenerateLocaList(&new_loca); + SubsetEBLC(eblc_table_builder, new_loca); + + return use_ebdt ? kRemoveBDAT : kRemoveNone; +} + +SubsetterImpl::SubsetterImpl() { +} + +SubsetterImpl::~SubsetterImpl() { +} + +bool SubsetterImpl::LoadFont(const char* font_name, + const unsigned char* original_font, + size_t font_size) { + MemoryInputStream mis; + mis.Attach(original_font, font_size); + if (factory_ == NULL) { + factory_.Attach(FontFactory::GetInstance()); + } + + FontArray font_array; + factory_->LoadFonts(&mis, &font_array); + font_ = FindFont(font_name, font_array); + if (font_ == NULL) { + return false; + } + + return true; +} + +int SubsetterImpl::SubsetFont(const unsigned int* glyph_ids, + size_t glyph_count, + unsigned char** output_buffer) { + if (factory_ == NULL || font_ == NULL) { + return -1; + } + + // Find glyf and loca table. + 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) { + // We are not able to subset the font. + return 0; + } + + IntegerSet glyph_id_processed; + if (!ResolveCompositeGlyphs(glyph_table, loca_table, + glyph_ids, glyph_count, &glyph_id_processed) || + glyph_id_processed.empty()) { + return 0; + } + + FontPtr new_font; + new_font.Attach(Subset(glyph_id_processed, glyph_table, loca_table)); + if (new_font == NULL) { + return 0; + } + + MemoryOutputStream output_stream; + factory_->SerializeFont(new_font, &output_stream); + int length = static_cast(output_stream.Size()); + if (length > 0) { + *output_buffer = new unsigned char[length]; + memcpy(*output_buffer, output_stream.Get(), length); + } + + return length; +} + +// Long comments regarding TTF tables and PDF (from stuartg) +// +// According to PDF spec 1.4 (section 5.8), the following tables must be +// present: +// head, hhea, loca, maxp, cvt, prep, glyf, hmtx, fpgm +// cmap if font is used with a simple font dict and not a CIDFont dict +// +// Other tables we need to keep for PDF rendering to support zoom in/out: +// bdat, bloc, ebdt, eblc, ebsc, gasp +// +// Special table: +// CFF - if you have this table then you shouldn't have a glyf table and this +// is the table with all the glyphs. Shall skip subsetting completely +// since sfntly is not capable of subsetting it for now. +// post - extra info here for printing on PostScript printers but maybe not +// enough to outweigh the space taken by the names +// +// Tables to break apart: +// name - could throw away all but one language and one platform strings/ might +// throw away some of the name entries +// cmap - could strip out non-needed cmap subtables +// - format 4 subtable can be subsetted as well using sfntly +// +// Graphite tables: +// silf, glat, gloc, feat - should be okay to strip out +// +// Tables that can be discarded: +// OS/2 - everything here is for layout and description of the font that is +// elsewhere (some in the PDF objects) +// BASE, GDEF, GSUB, GPOS, JSTF - all used for layout +// kern - old style layout +// DSIG - this will be invalid after subsetting +// hdmx - layout +// PCLT - metadata that's not needed +// vmtx - layout +// vhea - layout +// VDMX +// VORG - not used by TT/OT - used by CFF +// hsty - would be surprised to see one of these - used on the Newton +// AAT tables - mort, morx, feat, acnt, bsin, just, lcar, fdsc, fmtx, prop, +// Zapf, opbd, trak, fvar, gvar, avar, cvar +// - these are all layout tables and once layout happens are not +// needed anymore +// LTSH - layout + +CALLER_ATTACH +Font* SubsetterImpl::Subset(const IntegerSet& glyph_ids, GlyphTable* glyf, + LocaTable* loca) { + // The const is initialized here to workaround VC bug of rendering all Tag::* + // as 0. These tags represents the TTF tables that we will embed in subset + // font. + const int32_t TABLES_IN_SUBSET[] = { + Tag::head, Tag::hhea, Tag::loca, Tag::maxp, Tag::cvt, + Tag::prep, Tag::glyf, Tag::hmtx, Tag::fpgm, Tag::EBDT, + Tag::EBLC, Tag::EBSC, Tag::bdat, Tag::bloc, Tag::bhed, + Tag::cmap, // Keep here for future tagged PDF development. + Tag::name, // Keep here due to legal concerns: copyright info inside. + }; + + // Setup font builders we need. + FontBuilderPtr font_builder; + font_builder.Attach(factory_->NewFontBuilder()); + IntegerSet remove_tags; + + if (SetupGlyfBuilders(font_builder, glyf, loca, glyph_ids)) { + remove_tags.insert(Tag::glyf); + remove_tags.insert(Tag::loca); + } + + // For old Apple bitmap fonts, they have only bdats and bhed is identical + // to head. As a result, we can't remove bdat tables for those fonts. + int setup_result = SetupBitmapBuilders(font_, font_builder, glyph_ids); + if (setup_result == kRemoveBDATAndEBDT || setup_result == kRemoveEBDT) { + remove_tags.insert(Tag::EBDT); + remove_tags.insert(Tag::EBLC); + remove_tags.insert(Tag::EBSC); + } + + if (setup_result == kRemoveBDAT || setup_result == kRemoveBDATAndEBDT) { + remove_tags.insert(Tag::bdat); + remove_tags.insert(Tag::bloc); + remove_tags.insert(Tag::bhed); + } + + IntegerSet allowed_tags; + for (size_t i = 0; i < sizeof(TABLES_IN_SUBSET) / sizeof(int32_t); ++i) { + allowed_tags.insert(TABLES_IN_SUBSET[i]); + } + + IntegerSet result; + std::set_difference(allowed_tags.begin(), allowed_tags.end(), + remove_tags.begin(), remove_tags.end(), + std::inserter(result, result.end())); + allowed_tags = result; + + // Setup remaining builders. + for (IntegerSet::iterator i = allowed_tags.begin(), e = allowed_tags.end(); + i != e; ++i) { + Table* table = font_->GetTable(*i); + if (table) { + font_builder->NewTableBuilder(*i, table->ReadFontData()); + } + } + + return font_builder->Build(); +} + +} // namespace sfntly diff --git a/sample/chromium/subsetter_impl.h b/sample/chromium/subsetter_impl.h new file mode 100644 index 0000000..ffbf408 --- /dev/null +++ b/sample/chromium/subsetter_impl.h @@ -0,0 +1,74 @@ +/* + * 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. + */ +// File is originally from Chromium third_party/sfntly/src/subsetter. +// Use as test case in sfntly so that problems can be caught in upstream early. + +#ifndef SFNTLY_CPP_SRC_TEST_SUBSETTER_IMPL_H_ +#define SFNTLY_CPP_SRC_TEST_SUBSETTER_IMPL_H_ + +#include "sfntly/font.h" +#include "sfntly/font_factory.h" +#include "sfntly/table/truetype/glyph_table.h" +#include "sfntly/table/truetype/loca_table.h" +#include "sfntly/tag.h" + +namespace sfntly { + +// 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 + +class SubsetterImpl { + public: + SubsetterImpl(); + ~SubsetterImpl(); + + bool LoadFont(const char* font_name, + const unsigned char* original_font, + size_t font_size); + int SubsetFont(const unsigned int* glyph_ids, + size_t glyph_count, + unsigned char** output_buffer); + + private: + CALLER_ATTACH Font* Subset(const IntegerSet& glyph_ids, + GlyphTable* glyf, LocaTable* loca); + + FontFactoryPtr factory_; + FontPtr font_; +}; + +} // namespace sfntly + +#endif // SFNTLY_CPP_SRC_TEST_SUBSETTER_IMPL_H_ diff --git a/sfntly/font.h b/sfntly/font.h index dd31c13..975e8cc 100644 --- a/sfntly/font.h +++ b/sfntly/font.h @@ -117,8 +117,6 @@ struct MacintoshEncodingId { }; }; -extern const int32_t SFNTVERSION_1; - class FontFactory; // An sfnt container font object. This object is immutable and thread safe. To diff --git a/test/chrome_subsetter.cc b/test/chrome_subsetter.cc index 0c5c9ca..9563ab1 100644 --- a/test/chrome_subsetter.cc +++ b/test/chrome_subsetter.cc @@ -15,7 +15,7 @@ */ #include "gtest/gtest.h" -#include "test/font_subsetter.h" +#include "sample/chromium/font_subsetter.h" #include "test/test_data.h" #include "test/test_font_utils.h" diff --git a/test/font_subsetter.cc b/test/font_subsetter.cc deleted file mode 100644 index 401c9f5..0000000 --- a/test/font_subsetter.cc +++ /dev/null @@ -1,41 +0,0 @@ -/* - * 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. - */ -// File is originally from Chromium third_party/sfntly/src/subsetter. -// Use as test case in sfntly so that problems can be caught in upstream early. - -#include "test/font_subsetter.h" - -#include "test/subsetter_impl.h" - -int SfntlyWrapper::SubsetFont(const char* font_name, - const unsigned char* original_font, - size_t font_size, - const unsigned int* glyph_ids, - size_t glyph_count, - unsigned char** output_buffer) { - if (output_buffer == NULL || - original_font == NULL || font_size == 0 || - glyph_ids == NULL || glyph_count == 0) { - return 0; - } - - sfntly::SubsetterImpl subsetter; - if (!subsetter.LoadFont(font_name, original_font, font_size)) { - return -1; // Load error or font not found. - } - - return subsetter.SubsetFont(glyph_ids, glyph_count, output_buffer); -} diff --git a/test/font_subsetter.h b/test/font_subsetter.h deleted file mode 100644 index 07b1b5b..0000000 --- a/test/font_subsetter.h +++ /dev/null @@ -1,51 +0,0 @@ -/* - * 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. - */ -// File is originally from Chromium third_party/sfntly/src/subsetter. -// Use as test case in sfntly so that problems can be caught in upstream early. -#ifndef SFNTLY_CPP_SRC_TEST_FONT_SUBSETTER_H_ -#define SFNTLY_CPP_SRC_TEST_FONT_SUBSETTER_H_ - -#include - -class SfntlyWrapper { - public: - - // Font subsetting API - // - // Input TTF/TTC/OTF fonts, specify the glyph IDs to subset, and the subset - // font is returned in |output_buffer| (caller to delete[]). Return value is - // the length of output_buffer allocated. - // - // If subsetting fails, a negative value is returned. If none of the glyph - // IDs specified is found, the function will return 0. - // - // |font_name| Font name, required for TTC files. If specified NULL, - // the first available font is selected. - // |original_font| Original font file contents. - // |font_size| Size of |original_font| in bytes. - // |glyph_ids| Glyph IDs to subset. If the specified glyph ID is not - // found in the font file, it will be ignored silently. - // |glyph_count| Number of glyph IDs in |glyph_ids| - // |output_buffer| Generated subset font. Caller to delete[]. - static int SubsetFont(const char* font_name, - const unsigned char* original_font, - size_t font_size, - const unsigned int* glyph_ids, - size_t glyph_count, - unsigned char** output_buffer); -}; - -#endif // SFNTLY_CPP_SRC_TEST_FONT_SUBSETTER_H_ diff --git a/test/subsetter_impl.cc b/test/subsetter_impl.cc deleted file mode 100644 index 4786f7f..0000000 --- a/test/subsetter_impl.cc +++ /dev/null @@ -1,779 +0,0 @@ -/* - * 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. - */ -// File is originally from Chromium third_party/sfntly/src/subsetter. -// Use as test case in sfntly so that problems can be caught in upstream early. - -#include "test/subsetter_impl.h" - -#include - -#include -#include -#include -#include - -#include "sfntly/table/bitmap/eblc_table.h" -#include "sfntly/table/bitmap/ebdt_table.h" -#include "sfntly/table/bitmap/index_sub_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" -#include "sfntly/table/core/name_table.h" -#include "sfntly/tag.h" -#include "sfntly/data/memory_byte_array.h" -#include "sfntly/port/memory_input_stream.h" -#include "sfntly/port/memory_output_stream.h" - -#if defined U_USING_ICU_NAMESPACE - U_NAMESPACE_USE -#endif - -namespace { - -using namespace sfntly; - -// The bitmap tables must be greater than 16KB to trigger bitmap subsetter. -static const int BITMAP_SIZE_THRESHOLD = 16384; - -void ConstructName(UChar* name_part, UnicodeString* name, int32_t name_id) { - switch (name_id) { - case NameId::kFullFontName: - *name = name_part; - break; - case NameId::kFontFamilyName: - case NameId::kPreferredFamily: - case NameId::kWWSFamilyName: { - UnicodeString original = *name; - *name = name_part; - *name += original; - break; - } - case NameId::kFontSubfamilyName: - case NameId::kPreferredSubfamily: - case NameId::kWWSSubfamilyName: - *name += name_part; - break; - default: - // This name part is not used to construct font name (e.g. copyright). - // Simply ignore it. - break; - } -} - -int32_t HashCode(int32_t platform_id, int32_t encoding_id, int32_t language_id, - int32_t name_id) { - int32_t result = platform_id << 24 | encoding_id << 16 | language_id << 8; - if (name_id == NameId::kFullFontName) { - result |= 0xff; - } else if (name_id == NameId::kPreferredFamily || - name_id == NameId::kPreferredSubfamily) { - result |= 0xf; - } else if (name_id == NameId::kWWSFamilyName || - name_id == NameId::kWWSSubfamilyName) { - result |= 1; - } - return result; -} - -bool HasName(const char* font_name, Font* font) { - UnicodeString font_string = UnicodeString::fromUTF8(font_name); - if (font_string.isEmpty()) - return false; - UnicodeString regular_suffix = UnicodeString::fromUTF8(" Regular"); - UnicodeString alt_font_string = font_string; - alt_font_string += regular_suffix; - - typedef std::map NameMap; - NameMap names; - NameTablePtr name_table = down_cast(font->GetTable(Tag::name)); - if (name_table == NULL) { - return false; - } - - for (int32_t i = 0; i < name_table->NameCount(); ++i) { - switch (name_table->NameId(i)) { - case NameId::kFontFamilyName: - case NameId::kFontSubfamilyName: - case NameId::kFullFontName: - case NameId::kPreferredFamily: - case NameId::kPreferredSubfamily: - case NameId::kWWSFamilyName: - case NameId::kWWSSubfamilyName: { - int32_t hash_code = HashCode(name_table->PlatformId(i), - name_table->EncodingId(i), - name_table->LanguageId(i), - name_table->NameId(i)); - UChar* name_part = name_table->Name(i); - ConstructName(name_part, &(names[hash_code]), name_table->NameId(i)); - delete[] name_part; - break; - } - default: - break; - } - } - - if (!names.empty()) { - for (NameMap::iterator i = names.begin(), e = names.end(); i != e; ++i) { - if (i->second.caseCompare(font_string, 0) == 0 || - i->second.caseCompare(alt_font_string, 0) == 0) { - return true; - } - } - } - return false; -} - -Font* FindFont(const char* font_name, const FontArray& font_array) { - if (font_array.empty() || font_array[0] == NULL) { - return NULL; - } - - if (font_name && strlen(font_name)) { - for (FontArray::const_iterator i = font_array.begin(), e = font_array.end(); - i != e; ++i) { - if (HasName(font_name, i->p_)) { - return i->p_; - } - } - } - - return font_array[0].p_; -} - -bool ResolveCompositeGlyphs(GlyphTable* glyph_table, - LocaTable* loca_table, - const unsigned int* glyph_ids, - size_t glyph_count, - IntegerSet* glyph_id_processed) { - if (glyph_table == NULL || loca_table == NULL || - glyph_ids == NULL || glyph_count == 0 || glyph_id_processed == NULL) { - return false; - } - - // Sort and uniquify glyph ids. - IntegerSet glyph_id_remaining; - glyph_id_remaining.insert(0); // Always include glyph id 0. - for (size_t i = 0; i < glyph_count; ++i) { - glyph_id_remaining.insert(glyph_ids[i]); - } - - // Identify if any given glyph id maps to a composite glyph. If so, include - // the glyphs referenced by that composite glyph. - while (!glyph_id_remaining.empty()) { - IntegerSet comp_glyph_id; - for (IntegerSet::iterator i = glyph_id_remaining.begin(), - e = glyph_id_remaining.end(); i != e; ++i) { - if (*i < 0 || *i >= loca_table->num_glyphs()) { - // Invalid glyph id, ignore. - continue; - } - - int32_t length = loca_table->GlyphLength(*i); - if (length == 0) { - // Empty glyph, ignore. - continue; - } - int32_t offset = loca_table->GlyphOffset(*i); - - GlyphPtr glyph; - glyph.Attach(glyph_table->GetGlyph(offset, length)); - if (glyph == NULL) { - // Error finding glyph, ignore. - continue; - } - - if (glyph->GlyphType() == GlyphType::kComposite) { - Ptr comp_glyph = - down_cast(glyph.p_); - for (int32_t j = 0; j < comp_glyph->NumGlyphs(); ++j) { - int32_t glyph_id = comp_glyph->GlyphIndex(j); - if (glyph_id_processed->find(glyph_id) == glyph_id_processed->end() && - glyph_id_remaining.find(glyph_id) == glyph_id_remaining.end()) { - comp_glyph_id.insert(comp_glyph->GlyphIndex(j)); - } - } - } - - glyph_id_processed->insert(*i); - } - - glyph_id_remaining.clear(); - glyph_id_remaining = comp_glyph_id; - } - - return true; -} - -bool SetupGlyfBuilders(Font::Builder* font_builder, - GlyphTable* glyph_table, - LocaTable* loca_table, - const IntegerSet& glyph_ids) { - if (!font_builder || !glyph_table || !loca_table) { - 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) { - // Out of memory. - return false; - } - - // Extract glyphs and setup loca list. - IntegerList loca_list; - loca_list.resize(loca_table->num_glyphs()); - loca_list.push_back(0); - int32_t last_glyph_id = 0; - int32_t last_offset = 0; - GlyphTable::GlyphBuilderList* glyph_builders = - glyph_table_builder->GlyphBuilders(); - for (IntegerSet::const_iterator i = glyph_ids.begin(), e = glyph_ids.end(); - i != e; ++i) { - int32_t length = loca_table->GlyphLength(*i); - int32_t offset = loca_table->GlyphOffset(*i); - - GlyphPtr glyph; - glyph.Attach(glyph_table->GetGlyph(offset, length)); - - // Add glyph to new glyf table. - 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); - - // Configure loca list. - for (int32_t j = last_glyph_id + 1; j <= *i; ++j) { - loca_list[j] = last_offset; - } - last_offset += length; - loca_list[*i + 1] = last_offset; - last_glyph_id = *i; - } - for (int32_t j = last_glyph_id + 1; j <= loca_table->num_glyphs(); ++j) { - loca_list[j] = last_offset; - } - loca_table_builder->SetLocaList(&loca_list); - - return true; -} - -bool HasOverlap(int32_t range_begin, int32_t range_end, - const IntegerSet& glyph_ids) { - if (range_begin == range_end) { - return glyph_ids.find(range_begin) != glyph_ids.end(); - } else if (range_end > range_begin) { - IntegerSet::const_iterator left = glyph_ids.lower_bound(range_begin); - IntegerSet::const_iterator right = glyph_ids.lower_bound(range_end); - return right != left; - } - return false; -} - -// Initialize builder, returns false if glyph_id subset is not covered. -// Not thread-safe, caller to ensure object life-time. -bool InitializeBitmapBuilder(EbdtTable::Builder* ebdt, EblcTable::Builder* eblc, - const IntegerSet& glyph_ids) { - BitmapLocaList loca_list; - BitmapSizeTableBuilderList* strikes = eblc->BitmapSizeBuilders(); - - // Note: Do not call eblc_builder->GenerateLocaList(&loca_list) and then - // ebdt_builder->SetLoca(loca_list). For fonts like SimSun, there are - // >28K glyphs inside, where a typical usage will be <1K glyphs. Doing - // the calls improperly will result in creation of >100K objects that - // will be destroyed immediately, inducing significant slowness. - IntegerList removed_strikes; - for (size_t i = 0; i < strikes->size(); i++) { - if (!HasOverlap((*strikes)[i]->StartGlyphIndex(), - (*strikes)[i]->EndGlyphIndex(), glyph_ids)) { - removed_strikes.push_back(i); - continue; - } - - IndexSubTableBuilderList* index_builders = - (*strikes)[i]->IndexSubTableBuilders(); - IntegerList removed_indexes; - BitmapGlyphInfoMap info_map; - for (size_t j = 0; j < index_builders->size(); ++j) { - int32_t first_glyph_id = (*index_builders)[j]->first_glyph_index(); - int32_t last_glyph_id = (*index_builders)[j]->last_glyph_index(); - if (!HasOverlap(first_glyph_id, last_glyph_id, glyph_ids)) { - removed_indexes.push_back(j); - continue; - } - for (IntegerSet::const_iterator gid = glyph_ids.begin(), - gid_end = glyph_ids.end(); - gid != gid_end; gid++) { - if (*gid < first_glyph_id) { - continue; - } - if (*gid > last_glyph_id) { - break; - } - BitmapGlyphInfoPtr info; - info.Attach((*index_builders)[j]->GlyphInfo(*gid)); - if (info && info->length()) { // Do not include gid without bitmap - info_map[*gid] = info; - } - } - } - if (!info_map.empty()) { - loca_list.push_back(info_map); - } else { - removed_strikes.push_back(i); // Detected null entries. - } - - // Remove unused index sub tables - for (IntegerList::reverse_iterator j = removed_indexes.rbegin(), - e = removed_indexes.rend(); - j != e; j++) { - index_builders->erase(index_builders->begin() + *j); - } - } - if (removed_strikes.size() == strikes->size() || loca_list.empty()) { - return false; - } - - for (IntegerList::reverse_iterator i = removed_strikes.rbegin(), - e = removed_strikes.rend(); i != e; i++) { - strikes->erase(strikes->begin() + *i); - } - - if (strikes->empty()) { // no glyph covered, can safely drop the builders. - return false; - } - - ebdt->SetLoca(&loca_list); - ebdt->GlyphBuilders(); // Initialize the builder. - return true; -} - -void CopyBigGlyphMetrics(BigGlyphMetrics::Builder* source, - BigGlyphMetrics::Builder* target) { - target->SetHeight(static_cast(source->Height())); - target->SetWidth(static_cast(source->Width())); - target->SetHoriBearingX(static_cast(source->HoriBearingX())); - target->SetHoriBearingY(static_cast(source->HoriBearingY())); - target->SetHoriAdvance(static_cast(source->HoriAdvance())); - target->SetVertBearingX(static_cast(source->VertBearingX())); - target->SetVertBearingY(static_cast(source->VertBearingY())); - target->SetVertAdvance(static_cast(source->VertAdvance())); -} - -CALLER_ATTACH IndexSubTable::Builder* -ConstructIndexFormat4(IndexSubTable::Builder* b, const BitmapGlyphInfoMap& loca, - int32_t* image_data_offset) { - IndexSubTableFormat4BuilderPtr builder4; - builder4.Attach(IndexSubTableFormat4::Builder::CreateBuilder()); - CodeOffsetPairBuilderList offset_pairs; - - size_t offset = 0; - int32_t lower_bound = b->first_glyph_index(); - int32_t upper_bound = b->last_glyph_index(); - int32_t last_gid = -1; - BitmapGlyphInfoMap::const_iterator i = loca.lower_bound(lower_bound); - BitmapGlyphInfoMap::const_iterator end = loca.end(); - if (i != end) { - last_gid = i->first; - builder4->set_first_glyph_index(last_gid); - builder4->set_image_format(b->image_format()); - builder4->set_image_data_offset(*image_data_offset); - } - for (; i != end; i++) { - int32_t gid = i->first; - if (gid > upper_bound) { - break; - } - offset_pairs.push_back( - IndexSubTableFormat4::CodeOffsetPairBuilder(gid, offset)); - offset += i->second->length(); - last_gid = gid; - } - offset_pairs.push_back( - IndexSubTableFormat4::CodeOffsetPairBuilder(-1, offset)); - builder4->set_last_glyph_index(last_gid); - *image_data_offset += offset; - builder4->SetOffsetArray(offset_pairs); - - return builder4.Detach(); -} - -CALLER_ATTACH IndexSubTable::Builder* -ConstructIndexFormat5(IndexSubTable::Builder* b, const BitmapGlyphInfoMap& loca, - int32_t* image_data_offset) { - IndexSubTableFormat5BuilderPtr new_builder; - new_builder.Attach(IndexSubTableFormat5::Builder::CreateBuilder()); - - // Copy BigMetrics - int32_t image_size = 0; - if (b->index_format() == IndexSubTable::Format::FORMAT_2) { - IndexSubTableFormat2BuilderPtr builder2 = - down_cast(b); - CopyBigGlyphMetrics(builder2->BigMetrics(), new_builder->BigMetrics()); - image_size = builder2->ImageSize(); - } else { - IndexSubTableFormat5BuilderPtr builder5 = - down_cast(b); - BigGlyphMetricsBuilderPtr metrics_builder; - CopyBigGlyphMetrics(builder5->BigMetrics(), new_builder->BigMetrics()); - image_size = builder5->ImageSize(); - } - - IntegerList* glyph_array = new_builder->GlyphArray(); - size_t offset = 0; - int32_t lower_bound = b->first_glyph_index(); - int32_t upper_bound = b->last_glyph_index(); - int32_t last_gid = -1; - BitmapGlyphInfoMap::const_iterator i = loca.lower_bound(lower_bound); - BitmapGlyphInfoMap::const_iterator end = loca.end(); - if (i != end) { - last_gid = i->first; - new_builder->set_first_glyph_index(last_gid); - new_builder->set_image_format(b->image_format()); - new_builder->set_image_data_offset(*image_data_offset); - new_builder->SetImageSize(image_size); - } - for (; i != end; i++) { - int32_t gid = i->first; - if (gid > upper_bound) { - break; - } - glyph_array->push_back(gid); - offset += i->second->length(); - last_gid = gid; - } - new_builder->set_last_glyph_index(last_gid); - *image_data_offset += offset; - return new_builder.Detach(); -} - -CALLER_ATTACH IndexSubTable::Builder* -SubsetIndexSubTable(IndexSubTable::Builder* builder, - const BitmapGlyphInfoMap& loca, - int32_t* image_data_offset) { - switch (builder->index_format()) { - case IndexSubTable::Format::FORMAT_1: - case IndexSubTable::Format::FORMAT_3: - case IndexSubTable::Format::FORMAT_4: - return ConstructIndexFormat4(builder, loca, image_data_offset); - case IndexSubTable::Format::FORMAT_2: - case IndexSubTable::Format::FORMAT_5: - return ConstructIndexFormat5(builder, loca, image_data_offset); - default: - assert(false); - break; - } - return NULL; -} - -} - -namespace sfntly { - -// Not thread-safe, caller to ensure object life-time. -void SubsetEBLC(EblcTable::Builder* eblc, const BitmapLocaList& new_loca) { - BitmapSizeTableBuilderList* size_builders = eblc->BitmapSizeBuilders(); - if (size_builders == NULL) { - return; - } - - int32_t image_data_offset = EbdtTable::Offset::kHeaderLength; - for (size_t strike = 0; strike < size_builders->size(); ++strike) { - IndexSubTableBuilderList* index_builders = - (*size_builders)[strike]->IndexSubTableBuilders(); - for (size_t index = 0; index < index_builders->size(); ++index) { - IndexSubTable::Builder* new_builder_raw = - SubsetIndexSubTable((*index_builders)[index], new_loca[strike], - &image_data_offset); - if (NULL != new_builder_raw) { - (*index_builders)[index].Attach(new_builder_raw); - } - } - } -} - -// EBLC structure (from stuartg) -// header -// bitmapSizeTable[] -// one per strike -// holds strike metrics - sbitLineMetrics -// holds info about indexSubTableArray -// indexSubTableArray[][] -// one per strike and then one per indexSubTable for that strike -// holds info about the indexSubTable -// the indexSubTable entries pointed to can be of different formats -// indexSubTable -// one per indexSubTableArray entry -// tells how to get the glyphs -// may hold the glyph metrics if they are uniform for all the glyphs in range -// Please note that the structure can also be -// {indexSubTableArray[], indexSubTables[]}[] -// This way is also legal and in fact how Microsoft fonts are laid out. -// -// There is nothing that says that the indexSubTableArray entries and/or the -// indexSubTable items need to be unique. They may be shared between strikes. -// -// EBDT structure: -// header -// glyphs -// amorphous blob of data -// different glyphs that are only able to be figured out from the EBLC table -// may hold metrics - depends on the EBLC entry that pointed to them - -// Subsetting EBLC table (from arthurhsu) -// Most pages use only a fraction (hundreds or less) glyphs out of a given font -// (which can have >20K glyphs for CJK). It's safe to assume that the subset -// font will have sparse bitmap glyphs. So we reconstruct the EBLC table as -// format 4 or 5 here. - -enum BuildersToRemove { - kRemoveNone, - kRemoveBDAT, - kRemoveBDATAndEBDT, - kRemoveEBDT -}; - -int SetupBitmapBuilders(Font* font, Font::Builder* font_builder, - const IntegerSet& glyph_ids) { - if (!font || !font_builder) { - return false; - } - - // Check if bitmap table exists. - EbdtTablePtr ebdt_table = down_cast(font->GetTable(Tag::EBDT)); - EblcTablePtr eblc_table = down_cast(font->GetTable(Tag::EBLC)); - bool use_ebdt = (ebdt_table != NULL && eblc_table != NULL); - if (!use_ebdt) { - ebdt_table = down_cast(font->GetTable(Tag::bdat)); - eblc_table = down_cast(font->GetTable(Tag::bloc)); - if (ebdt_table == NULL || eblc_table == NULL) { - return kRemoveNone; - } - } - - // If the bitmap table's size is too small, skip subsetting. - if (ebdt_table->DataLength() + eblc_table->DataLength() < - BITMAP_SIZE_THRESHOLD) { - return use_ebdt ? kRemoveBDAT : kRemoveNone; - } - - // Get the builders. - EbdtTableBuilderPtr ebdt_table_builder = down_cast( - font_builder->NewTableBuilder(use_ebdt ? Tag::EBDT : Tag::bdat, - ebdt_table->ReadFontData())); - EblcTableBuilderPtr eblc_table_builder = down_cast( - font_builder->NewTableBuilder(use_ebdt ? Tag::EBLC : Tag::bloc, - eblc_table->ReadFontData())); - if (ebdt_table_builder == NULL || eblc_table_builder == NULL) { - // Out of memory. - return use_ebdt ? kRemoveBDAT : kRemoveNone; - } - - if (!InitializeBitmapBuilder(ebdt_table_builder, eblc_table_builder, - glyph_ids)) { - // Bitmap tables do not cover the glyphs in our subset. - font_builder->RemoveTableBuilder(use_ebdt ? Tag::EBLC : Tag::bloc); - font_builder->RemoveTableBuilder(use_ebdt ? Tag::EBDT : Tag::bdat); - return use_ebdt ? kRemoveBDATAndEBDT : kRemoveEBDT; - } - - BitmapLocaList new_loca; - ebdt_table_builder->GenerateLocaList(&new_loca); - SubsetEBLC(eblc_table_builder, new_loca); - - return use_ebdt ? kRemoveBDAT : kRemoveNone; -} - -SubsetterImpl::SubsetterImpl() { -} - -SubsetterImpl::~SubsetterImpl() { -} - -bool SubsetterImpl::LoadFont(const char* font_name, - const unsigned char* original_font, - size_t font_size) { - MemoryInputStream mis; - mis.Attach(original_font, font_size); - if (factory_ == NULL) { - factory_.Attach(FontFactory::GetInstance()); - } - - FontArray font_array; - factory_->LoadFonts(&mis, &font_array); - font_ = FindFont(font_name, font_array); - if (font_ == NULL) { - return false; - } - - return true; -} - -int SubsetterImpl::SubsetFont(const unsigned int* glyph_ids, - size_t glyph_count, - unsigned char** output_buffer) { - if (factory_ == NULL || font_ == NULL) { - return -1; - } - - // Find glyf and loca table. - 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) { - // We are not able to subset the font. - return 0; - } - - IntegerSet glyph_id_processed; - if (!ResolveCompositeGlyphs(glyph_table, loca_table, - glyph_ids, glyph_count, &glyph_id_processed) || - glyph_id_processed.empty()) { - return 0; - } - - FontPtr new_font; - new_font.Attach(Subset(glyph_id_processed, glyph_table, loca_table)); - if (new_font == NULL) { - return 0; - } - - MemoryOutputStream output_stream; - factory_->SerializeFont(new_font, &output_stream); - int length = static_cast(output_stream.Size()); - if (length > 0) { - *output_buffer = new unsigned char[length]; - memcpy(*output_buffer, output_stream.Get(), length); - } - - return length; -} - -// Long comments regarding TTF tables and PDF (from stuartg) -// -// According to PDF spec 1.4 (section 5.8), the following tables must be -// present: -// head, hhea, loca, maxp, cvt, prep, glyf, hmtx, fpgm -// cmap if font is used with a simple font dict and not a CIDFont dict -// -// Other tables we need to keep for PDF rendering to support zoom in/out: -// bdat, bloc, ebdt, eblc, ebsc, gasp -// -// Special table: -// CFF - if you have this table then you shouldn't have a glyf table and this -// is the table with all the glyphs. Shall skip subsetting completely -// since sfntly is not capable of subsetting it for now. -// post - extra info here for printing on PostScript printers but maybe not -// enough to outweigh the space taken by the names -// -// Tables to break apart: -// name - could throw away all but one language and one platform strings/ might -// throw away some of the name entries -// cmap - could strip out non-needed cmap subtables -// - format 4 subtable can be subsetted as well using sfntly -// -// Graphite tables: -// silf, glat, gloc, feat - should be okay to strip out -// -// Tables that can be discarded: -// OS/2 - everything here is for layout and description of the font that is -// elsewhere (some in the PDF objects) -// BASE, GDEF, GSUB, GPOS, JSTF - all used for layout -// kern - old style layout -// DSIG - this will be invalid after subsetting -// hdmx - layout -// PCLT - metadata that's not needed -// vmtx - layout -// vhea - layout -// VDMX -// VORG - not used by TT/OT - used by CFF -// hsty - would be surprised to see one of these - used on the Newton -// AAT tables - mort, morx, feat, acnt, bsin, just, lcar, fdsc, fmtx, prop, -// Zapf, opbd, trak, fvar, gvar, avar, cvar -// - these are all layout tables and once layout happens are not -// needed anymore -// LTSH - layout - -CALLER_ATTACH -Font* SubsetterImpl::Subset(const IntegerSet& glyph_ids, GlyphTable* glyf, - LocaTable* loca) { - // The const is initialized here to workaround VC bug of rendering all Tag::* - // as 0. These tags represents the TTF tables that we will embed in subset - // font. - const int32_t TABLES_IN_SUBSET[] = { - Tag::head, Tag::hhea, Tag::loca, Tag::maxp, Tag::cvt, - Tag::prep, Tag::glyf, Tag::hmtx, Tag::fpgm, Tag::EBDT, - Tag::EBLC, Tag::EBSC, Tag::bdat, Tag::bloc, Tag::bhed, - Tag::cmap, // Keep here for future tagged PDF development. - Tag::name, // Keep here due to legal concerns: copyright info inside. - }; - - // Setup font builders we need. - FontBuilderPtr font_builder; - font_builder.Attach(factory_->NewFontBuilder()); - IntegerSet remove_tags; - - if (SetupGlyfBuilders(font_builder, glyf, loca, glyph_ids)) { - remove_tags.insert(Tag::glyf); - remove_tags.insert(Tag::loca); - } - - // For old Apple bitmap fonts, they have only bdats and bhed is identical - // to head. As a result, we can't remove bdat tables for those fonts. - int setup_result = SetupBitmapBuilders(font_, font_builder, glyph_ids); - if (setup_result == kRemoveBDATAndEBDT || setup_result == kRemoveEBDT) { - remove_tags.insert(Tag::EBDT); - remove_tags.insert(Tag::EBLC); - remove_tags.insert(Tag::EBSC); - } - - if (setup_result == kRemoveBDAT || setup_result == kRemoveBDATAndEBDT) { - remove_tags.insert(Tag::bdat); - remove_tags.insert(Tag::bloc); - remove_tags.insert(Tag::bhed); - } - - IntegerSet allowed_tags; - for (size_t i = 0; i < sizeof(TABLES_IN_SUBSET) / sizeof(int32_t); ++i) { - allowed_tags.insert(TABLES_IN_SUBSET[i]); - } - - IntegerSet result; - std::set_difference(allowed_tags.begin(), allowed_tags.end(), - remove_tags.begin(), remove_tags.end(), - std::inserter(result, result.end())); - allowed_tags = result; - - // Setup remaining builders. - for (IntegerSet::iterator i = allowed_tags.begin(), e = allowed_tags.end(); - i != e; ++i) { - Table* table = font_->GetTable(*i); - if (table) { - font_builder->NewTableBuilder(*i, table->ReadFontData()); - } - } - - return font_builder->Build(); -} - -} // namespace sfntly diff --git a/test/subsetter_impl.h b/test/subsetter_impl.h deleted file mode 100644 index ffbf408..0000000 --- a/test/subsetter_impl.h +++ /dev/null @@ -1,74 +0,0 @@ -/* - * 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. - */ -// File is originally from Chromium third_party/sfntly/src/subsetter. -// Use as test case in sfntly so that problems can be caught in upstream early. - -#ifndef SFNTLY_CPP_SRC_TEST_SUBSETTER_IMPL_H_ -#define SFNTLY_CPP_SRC_TEST_SUBSETTER_IMPL_H_ - -#include "sfntly/font.h" -#include "sfntly/font_factory.h" -#include "sfntly/table/truetype/glyph_table.h" -#include "sfntly/table/truetype/loca_table.h" -#include "sfntly/tag.h" - -namespace sfntly { - -// 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 - -class SubsetterImpl { - public: - SubsetterImpl(); - ~SubsetterImpl(); - - bool LoadFont(const char* font_name, - const unsigned char* original_font, - size_t font_size); - int SubsetFont(const unsigned int* glyph_ids, - size_t glyph_count, - unsigned char** output_buffer); - - private: - CALLER_ATTACH Font* Subset(const IntegerSet& glyph_ids, - GlyphTable* glyf, LocaTable* loca); - - FontFactoryPtr factory_; - FontPtr font_; -}; - -} // namespace sfntly - -#endif // SFNTLY_CPP_SRC_TEST_SUBSETTER_IMPL_H_ -- cgit v1.2.3 From 8f7575736031a19220e1a36ab2eb21c6d447dfef Mon Sep 17 00:00:00 2001 From: "arthurhsu@google.com" Date: Thu, 5 Jan 2012 00:14:30 +0000 Subject: Coverity fix: uninitialized scalar member. git-svn-id: http://sfntly.googlecode.com/svn/trunk/cpp/src@119 672e30a5-4c29-85ac-ac6d-611c735e0a51 --- sfntly/table/bitmap/index_sub_table.cc | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/sfntly/table/bitmap/index_sub_table.cc b/sfntly/table/bitmap/index_sub_table.cc index d302aed..5e29784 100644 --- a/sfntly/table/bitmap/index_sub_table.cc +++ b/sfntly/table/bitmap/index_sub_table.cc @@ -210,7 +210,12 @@ int32_t IndexSubTable::Builder::SubSerialize(WritableFontData* new_data) { } IndexSubTable::Builder::Builder(int32_t data_size, int32_t index_format) - : SubTable::Builder(data_size), index_format_(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, @@ -218,6 +223,8 @@ IndexSubTable::Builder::Builder(int32_t index_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) { -- cgit v1.2.3 From 127cef2a54a5b6e6777761d550c1ec90e736383f Mon Sep 17 00:00:00 2001 From: "arthurhsu@google.com" Date: Tue, 28 Feb 2012 03:19:21 +0000 Subject: Work around Apple MacOS X Lion AppleMyungjo font bug. git-svn-id: http://sfntly.googlecode.com/svn/trunk/cpp/src@128 672e30a5-4c29-85ac-ac6d-611c735e0a51 --- sample/chromium/subsetter_impl.cc | 5 +++++ sfntly/table/bitmap/index_sub_table_format1.cc | 3 +++ sfntly/table/bitmap/index_sub_table_format2.cc | 3 +++ sfntly/table/bitmap/index_sub_table_format3.cc | 3 +++ sfntly/table/bitmap/index_sub_table_format4.cc | 3 +++ sfntly/table/bitmap/index_sub_table_format5.cc | 3 +++ 6 files changed, 20 insertions(+) diff --git a/sample/chromium/subsetter_impl.cc b/sample/chromium/subsetter_impl.cc index 7e7cf61..3708f44 100644 --- a/sample/chromium/subsetter_impl.cc +++ b/sample/chromium/subsetter_impl.cc @@ -313,6 +313,11 @@ bool InitializeBitmapBuilder(EbdtTable::Builder* ebdt, EblcTable::Builder* eblc, IntegerList removed_indexes; BitmapGlyphInfoMap info_map; for (size_t j = 0; j < index_builders->size(); ++j) { + if ((*index_builders)[j] == NULL) { + // Subtable is malformed, let's just skip it. + removed_indexes.push_back(j); + continue; + } int32_t first_glyph_id = (*index_builders)[j]->first_glyph_index(); int32_t last_glyph_id = (*index_builders)[j]->last_glyph_index(); if (!HasOverlap(first_glyph_id, last_glyph_id, glyph_ids)) { diff --git a/sfntly/table/bitmap/index_sub_table_format1.cc b/sfntly/table/bitmap/index_sub_table_format1.cc index db73723..5199e18 100644 --- a/sfntly/table/bitmap/index_sub_table_format1.cc +++ b/sfntly/table/bitmap/index_sub_table_format1.cc @@ -121,6 +121,9 @@ IndexSubTableFormat1::Builder::CreateBuilder(ReadableFontData* data, ReadableFontDataPtr new_data; new_data.Attach(down_cast( data->Slice(index_sub_table_offset, length))); + if (new_data == NULL) { + return NULL; + } IndexSubTableFormat1BuilderPtr output = new IndexSubTableFormat1::Builder(new_data, first_glyph_index, diff --git a/sfntly/table/bitmap/index_sub_table_format2.cc b/sfntly/table/bitmap/index_sub_table_format2.cc index b3bffda..ce73e9b 100644 --- a/sfntly/table/bitmap/index_sub_table_format2.cc +++ b/sfntly/table/bitmap/index_sub_table_format2.cc @@ -139,6 +139,9 @@ IndexSubTableFormat2::Builder::CreateBuilder(ReadableFontData* data, ReadableFontDataPtr new_data; new_data.Attach(down_cast( data->Slice(index_sub_table_offset, length))); + if (new_data == NULL) { + return NULL; + } IndexSubTableFormat2BuilderPtr output = new IndexSubTableFormat2::Builder(new_data, first_glyph_index, diff --git a/sfntly/table/bitmap/index_sub_table_format3.cc b/sfntly/table/bitmap/index_sub_table_format3.cc index b3e418f..e2679b7 100644 --- a/sfntly/table/bitmap/index_sub_table_format3.cc +++ b/sfntly/table/bitmap/index_sub_table_format3.cc @@ -134,6 +134,9 @@ IndexSubTableFormat3::Builder::CreateBuilder(ReadableFontData* data, ReadableFontDataPtr new_data; new_data.Attach(down_cast( data->Slice(index_sub_table_offset, length))); + if (new_data == NULL) { + return NULL; + } IndexSubTableFormat3BuilderPtr output = new IndexSubTableFormat3::Builder(new_data, first_glyph_index, diff --git a/sfntly/table/bitmap/index_sub_table_format4.cc b/sfntly/table/bitmap/index_sub_table_format4.cc index 23f3e47..5baa2a5 100644 --- a/sfntly/table/bitmap/index_sub_table_format4.cc +++ b/sfntly/table/bitmap/index_sub_table_format4.cc @@ -168,6 +168,9 @@ IndexSubTableFormat4::Builder::CreateBuilder(ReadableFontData* data, ReadableFontDataPtr new_data; new_data.Attach(down_cast( data->Slice(index_sub_table_offset, length))); + if (new_data == NULL) { + return NULL; + } IndexSubTableFormat4BuilderPtr output = new IndexSubTableFormat4::Builder(new_data, first_glyph_index, diff --git a/sfntly/table/bitmap/index_sub_table_format5.cc b/sfntly/table/bitmap/index_sub_table_format5.cc index b4ab1b8..0ca21fe 100644 --- a/sfntly/table/bitmap/index_sub_table_format5.cc +++ b/sfntly/table/bitmap/index_sub_table_format5.cc @@ -141,6 +141,9 @@ IndexSubTableFormat5::Builder::CreateBuilder(ReadableFontData* data, ReadableFontDataPtr new_data; new_data.Attach(down_cast( data->Slice(index_sub_table_offset, length))); + if (new_data == NULL) { + return NULL; + } IndexSubTableFormat5BuilderPtr output = new IndexSubTableFormat5::Builder(new_data, first_glyph_index, -- cgit v1.2.3 From 0f57ae889297f20b96a4770602c5d611054194bd Mon Sep 17 00:00:00 2001 From: "arthurhsu@google.com" Date: Fri, 29 Jun 2012 17:27:00 +0000 Subject: Land Nico's warning fix. git-svn-id: http://sfntly.googlecode.com/svn/trunk/cpp/src@133 672e30a5-4c29-85ac-ac6d-611c735e0a51 --- sfntly/table/core/cmap_table.cc | 1 - sfntly/table/core/cmap_table.h | 2 -- sfntly/table/core/name_table.h | 1 - sfntly/table/truetype/glyph_table.h | 1 - 4 files changed, 5 deletions(-) diff --git a/sfntly/table/core/cmap_table.cc b/sfntly/table/core/cmap_table.cc index 0b4f89a..1c83d2e 100644 --- a/sfntly/table/core/cmap_table.cc +++ b/sfntly/table/core/cmap_table.cc @@ -596,7 +596,6 @@ CMapTable::CMapFormat4::CMapFormat4(ReadableFontData* data, : 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_)) { } diff --git a/sfntly/table/core/cmap_table.h b/sfntly/table/core/cmap_table.h index 29ce3e4..b264b07 100644 --- a/sfntly/table/core/cmap_table.h +++ b/sfntly/table/core/cmap_table.h @@ -488,9 +488,7 @@ public: 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_; }; diff --git a/sfntly/table/core/name_table.h b/sfntly/table/core/name_table.h index 01d3b29..4eaafbb 100644 --- a/sfntly/table/core/name_table.h +++ b/sfntly/table/core/name_table.h @@ -480,7 +480,6 @@ class NameTable : public SubTableContainerTable, public RefCounted { int32_t name_id, const ByteVector* name_bytes); NameEntryId name_entry_id_; - int32_t length_; ByteVector name_bytes_; friend class NameEntryBuilder; diff --git a/sfntly/table/truetype/glyph_table.h b/sfntly/table/truetype/glyph_table.h index 0836971..4ffddda 100644 --- a/sfntly/table/truetype/glyph_table.h +++ b/sfntly/table/truetype/glyph_table.h @@ -70,7 +70,6 @@ class GlyphTable : public SubTableContainerTable, virtual int32_t SubSerialize(WritableFontData* new_data); private: - int32_t format_; friend class GlyphTable::Builder; }; -- cgit v1.2.3 From cfb2f1743f0169ad8d01035458617bce97107539 Mon Sep 17 00:00:00 2001 From: "arthurhsu@google.com" Date: Mon, 9 Jul 2012 18:35:41 +0000 Subject: Gracefully fail when TTF name table contains a zero-length name. Backport from b/6733065. git-svn-id: http://sfntly.googlecode.com/svn/trunk/cpp/src@134 672e30a5-4c29-85ac-ac6d-611c735e0a51 --- sample/chromium/subsetter_impl.cc | 5 ++++- sfntly/table/core/name_table.cc | 6 ++++-- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/sample/chromium/subsetter_impl.cc b/sample/chromium/subsetter_impl.cc index 3708f44..528e336 100644 --- a/sample/chromium/subsetter_impl.cc +++ b/sample/chromium/subsetter_impl.cc @@ -112,11 +112,14 @@ bool HasName(const char* font_name, Font* font) { case NameId::kPreferredSubfamily: case NameId::kWWSFamilyName: case NameId::kWWSSubfamilyName: { + UChar* name_part = name_table->Name(i); + if (name_part == NULL) { + continue; + } int32_t hash_code = HashCode(name_table->PlatformId(i), name_table->EncodingId(i), name_table->LanguageId(i), name_table->NameId(i)); - UChar* name_part = name_table->Name(i); ConstructName(name_part, &(names[hash_code]), name_table->NameId(i)); delete[] name_part; break; diff --git a/sfntly/table/core/name_table.cc b/sfntly/table/core/name_table.cc index 5f6d5a5..8d2f64f 100644 --- a/sfntly/table/core/name_table.cc +++ b/sfntly/table/core/name_table.cc @@ -472,7 +472,9 @@ void NameTable::NameAsBytes(int32_t index, ByteVector* b) { int32_t length = NameLength(index); b->clear(); b->resize(length); - data_->ReadBytes(NameOffset(index), &((*b)[0]), 0, length); + if (length > 0) { + data_->ReadBytes(NameOffset(index), &((*b)[0]), 0, length); + } } void NameTable::NameAsBytes(int32_t platform_id, @@ -674,7 +676,7 @@ void NameTable::ConvertToNameBytes(const UChar* name, UChar* NameTable::ConvertFromNameBytes(ByteVector* name_bytes, int32_t platform_id, int32_t encoding_id) { - if (name_bytes == NULL) { + if (name_bytes == NULL || name_bytes->size() == 0) { return NULL; } UConverter* cs = GetCharset(platform_id, encoding_id); -- cgit v1.2.3 From 8f090032dd4f8f8908f338cc73bb840b788377f2 Mon Sep 17 00:00:00 2001 From: "stuartg@google.com" Date: Wed, 16 Oct 2013 23:04:01 +0000 Subject: ticket:38 Fix sfntly compilation on VS2013 git-svn-id: http://sfntly.googlecode.com/svn/trunk/cpp/src@228 672e30a5-4c29-85ac-ac6d-611c735e0a51 --- sfntly/data/writable_font_data.cc | 2 ++ sfntly/port/file_input_stream.cc | 2 ++ sfntly/port/memory_input_stream.cc | 2 ++ sfntly/table/core/os2_table.cc | 2 ++ 4 files changed, 8 insertions(+) diff --git a/sfntly/data/writable_font_data.cc b/sfntly/data/writable_font_data.cc index 7f6f72f..4b3b440 100644 --- a/sfntly/data/writable_font_data.cc +++ b/sfntly/data/writable_font_data.cc @@ -16,6 +16,8 @@ #include "sfntly/data/writable_font_data.h" +#include + #include "sfntly/data/memory_byte_array.h" #include "sfntly/data/growable_memory_byte_array.h" diff --git a/sfntly/port/file_input_stream.cc b/sfntly/port/file_input_stream.cc index 5bcb434..dfe9a7b 100644 --- a/sfntly/port/file_input_stream.cc +++ b/sfntly/port/file_input_stream.cc @@ -18,6 +18,8 @@ #include #endif +#include + #include "sfntly/port/file_input_stream.h" #include "sfntly/port/exception_type.h" diff --git a/sfntly/port/memory_input_stream.cc b/sfntly/port/memory_input_stream.cc index 56ee81e..f6f2b9b 100755 --- a/sfntly/port/memory_input_stream.cc +++ b/sfntly/port/memory_input_stream.cc @@ -20,6 +20,8 @@ #include +#include + #include "sfntly/port/memory_input_stream.h" #include "sfntly/port/exception_type.h" diff --git a/sfntly/table/core/os2_table.cc b/sfntly/table/core/os2_table.cc index 7ca9d9a..1fef309 100644 --- a/sfntly/table/core/os2_table.cc +++ b/sfntly/table/core/os2_table.cc @@ -16,6 +16,8 @@ #include "sfntly/table/core/os2_table.h" +#include + namespace sfntly { /****************************************************************************** * Constants -- cgit v1.2.3