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:
CMapIteratorTestCase(int32_t platform_id,int32_t encoding_id,const char * file_name)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 }
~CMapIteratorTestCase()50 ~CMapIteratorTestCase() {}
platform_id() const51 int32_t platform_id() const { return platform_id_; }
encoding_id() const52 int32_t encoding_id() const { return encoding_id_; }
file_name() const53 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();
TearDown()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
SetUp()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
GenerateCMapEntries(int32_t start,int32_t count)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::
CompareCMapIterAndBitSet(CMapTable::CMap::CharacterIterator * character_iterator,BitSet * bit_set)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
TEST_P(CMapIteratorTests,IteratorTest)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
TEST(DummyTest,ValueParameterizedTestsAreNotSupportedOnThisPlatform)154 TEST(DummyTest, ValueParameterizedTestsAreNotSupportedOnThisPlatform) {}
155
156 #endif // GTEST_HAS_PARAM
157