1 /* 2 * Copyright 2011 Google Inc. All Rights Reserved. 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 #include <string.h> 18 19 #include <vector> 20 #include <string> 21 #include <algorithm> 22 23 #include "sfntly/font.h" 24 #include "sfntly/font_factory.h" 25 #include "sfntly/table/core/cmap_table.h" 26 #include "sfntly/tag.h" 27 #include "sfntly/port/type.h" 28 #include "sfntly/port/refcount.h" 29 #include "test/test_data.h" 30 #include "test/test_font_utils.h" 31 32 #include "gtest/gtest.h" 33 34 #if GTEST_HAS_PARAM_TEST 35 36 namespace sfntly { 37 using ::testing::TestWithParam; 38 using ::testing::Values; 39 40 typedef std::vector<bool> BitSet; 41 42 class CMapIteratorTestCase { 43 public: 44 CMapIteratorTestCase(int32_t platform_id, int32_t encoding_id, 45 const char* file_name) 46 : platform_id_(platform_id), 47 encoding_id_(encoding_id), 48 file_name_(file_name) { 49 } 50 ~CMapIteratorTestCase() {} 51 int32_t platform_id() const { return platform_id_; } 52 int32_t encoding_id() const { return encoding_id_; } 53 const char* file_name() const { return file_name_; } 54 55 private: 56 int32_t platform_id_; 57 int32_t encoding_id_; 58 const char* file_name_; 59 }; 60 61 class CMapIteratorTests 62 : public ::testing::TestWithParam<CMapIteratorTestCase> { 63 public: 64 virtual void SetUp(); 65 virtual void TearDown() {} 66 67 BitSet* GenerateCMapEntries(int32_t start, int32_t count); 68 int32_t CompareCMapIterAndBitSet(CMapTable::CMap::CharacterIterator* 69 character_iterator, 70 BitSet* bit_set); 71 72 Ptr<CMapTable::CMap> cmap_; 73 }; 74 75 void CMapIteratorTests::SetUp() { 76 FontArray fonts; 77 Ptr<FontFactory> font_factory; 78 const char* file_name = GetParam().file_name(); 79 LoadFont(file_name, font_factory, &fonts); 80 Ptr<Font> font; 81 font.Attach(fonts[0].Detach()); 82 Ptr<CMapTable> cmap_table = down_cast<CMapTable*>(font->GetTable(Tag::cmap)); 83 ASSERT_FALSE(cmap_table == NULL); 84 cmap_.Attach(cmap_table->GetCMap(GetParam().platform_id(), 85 GetParam().encoding_id())); 86 ASSERT_FALSE(cmap_ == NULL); 87 } 88 89 BitSet* CMapIteratorTests::GenerateCMapEntries(int32_t start, int32_t count) { 90 BitSet* entries = new BitSet(count); 91 for (int32_t c = start; c < start + count; ++c) { 92 int32_t g = cmap_->GlyphId(c); 93 if (g != CMapTable::NOTDEF) 94 (*entries)[c] = true; 95 } 96 return entries; 97 } 98 99 int32_t 100 CMapIteratorTests:: 101 CompareCMapIterAndBitSet(CMapTable::CMap::CharacterIterator* character_iterator, 102 BitSet* bit_set) { 103 int32_t iterator_not_bitset_count = 0; 104 BitSet::iterator end = bit_set->end(), 105 beginning = bit_set->begin(), 106 init_beginning = beginning, 107 current = std::find(beginning, end, true); 108 for (int32_t next_bit = current - beginning; 109 character_iterator->HasNext() && current != end; 110 next_bit = current - init_beginning) { 111 int32_t c = character_iterator->Next(); 112 EXPECT_TRUE(c <= next_bit || current == end); 113 if (!(c <= next_bit || current == end)) 114 return -1; 115 if (c == next_bit) { 116 beginning = current + 1; 117 current = std::find(beginning, end, true); 118 } else { 119 iterator_not_bitset_count++; 120 } 121 } 122 EXPECT_EQ(end, current); 123 #if defined (SFNTLY_DEBUG_CMAP) 124 fprintf(stderr, "%s %d: Differences between iterator and bitset: %d\n", 125 cmap_->format(), GetParam().file_name(), iterator_not_bitset_count); 126 #endif 127 return iterator_not_bitset_count; 128 } 129 130 TEST_P(CMapIteratorTests, IteratorTest) { 131 BitSet* bit_set = GenerateCMapEntries(0, 0x10ffff); 132 CMapTable::CMap::CharacterIterator* character_iterator = NULL; 133 character_iterator = cmap_->Iterator(); 134 EXPECT_NE(character_iterator, 135 reinterpret_cast<CMapTable::CMap::CharacterIterator*>(NULL)); 136 CompareCMapIterAndBitSet(character_iterator, bit_set); 137 delete character_iterator; 138 delete bit_set; 139 } 140 141 CMapIteratorTestCase kCMapIteratorTestsTestCases[] = { 142 CMapIteratorTestCase(CMapTable::WINDOWS_BMP.platform_id, 143 CMapTable::WINDOWS_BMP.encoding_id, 144 SAMPLE_TTF_FILE) 145 }; 146 147 INSTANTIATE_TEST_CASE_P(CMapIteratorTests, 148 CMapIteratorTests, 149 ::testing::ValuesIn(kCMapIteratorTestsTestCases)); 150 } 151 152 #else 153 154 TEST(DummyTest, ValueParameterizedTestsAreNotSupportedOnThisPlatform) {} 155 156 #endif // GTEST_HAS_PARAM 157