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 "sfntly/port/type.h" 18#include <assert.h> 19#include <unicode/ucnv.h> 20 21#include <string> 22#include <iostream> 23 24#include "gtest/gtest.h" 25#include "sfntly/font.h" 26#include "sfntly/font_factory.h" 27#include "sfntly/table/core/cmap_table.h" 28#include "sfntly/data/memory_byte_array.h" 29#include "sfntly/table/core/font_header_table.h" 30#include "sfntly/tag.h" 31 32#include "test/test_utils.h" 33#include "test/test_font_utils.h" 34#include "test/test_data.h" 35 36#if GTEST_HAS_PARAM_TEST 37 38namespace sfntly { 39using ::testing::TestWithParam; 40using ::testing::Values; 41 42class CMapTestCase { 43 public: 44 CMapTestCase(const char* font_name, 45 int32_t first_platform_id, 46 int32_t first_encoding_id, 47 const char* first_charset_name, 48 int32_t second_platform_id, 49 int32_t second_encoding_id, 50 const char* second_charset_name, 51 int32_t low_char, 52 int32_t high_char) 53 : font_name_(font_name), 54 first_platform_id_(first_platform_id), 55 first_encoding_id_(first_encoding_id), 56 first_charset_name_(first_charset_name), 57 second_platform_id_(second_platform_id), 58 second_encoding_id_(second_encoding_id), 59 second_charset_name_(second_charset_name), 60 low_char_(low_char), 61 high_char_(high_char) { 62 } 63 64 const char* font_name() const { return font_name_; } 65 int32_t first_platform_id() const { return first_platform_id_; } 66 int32_t first_encoding_id() const { return first_encoding_id_; } 67 const char* first_charset_name() const { return first_charset_name_; } 68 int32_t second_platform_id() const { return second_platform_id_; } 69 int32_t second_encoding_id() const { return second_encoding_id_; } 70 const char* second_charset_name() const { return second_charset_name_; } 71 int32_t low_char() const { return low_char_; } 72 int32_t high_char() const { return high_char_; } 73 74 private: 75 const char* font_name_; 76 int32_t first_platform_id_; 77 int32_t first_encoding_id_; 78 const char* first_charset_name_; 79 int32_t second_platform_id_; 80 int32_t second_encoding_id_; 81 const char* second_charset_name_; 82 int32_t low_char_; 83 int32_t high_char_; 84}; 85 86class CMapTests : public :: testing::TestWithParam<CMapTestCase> { 87 public: 88 CMapTests() : encoder1_(NULL), encoder2_(NULL), successful_setup_(false) { 89 } 90 virtual void SetUp() {} 91 virtual void TearDown(); 92 93 void CommonSetUp(FontArray* font_array); 94 95 void CompareCMaps(); 96 97 Ptr<CMapTable::CMap> cmap1_; 98 Ptr<CMapTable::CMap> cmap2_; 99 UConverter* encoder1_; 100 UConverter* encoder2_; 101 bool successful_setup_; 102}; 103 104::std::ostream& operator<<(::std::ostream& os, const CMapTestCase *test_case) { 105 return os << "(" 106 << test_case->font_name() << ", " 107 << test_case->first_platform_id() << ", " 108 << test_case->first_encoding_id() << ", " 109 << test_case->first_charset_name() << ", " 110 << test_case->second_platform_id() << ", " 111 << test_case->second_encoding_id() << ", " 112 << test_case->second_charset_name() << ", " 113 << test_case->low_char() << ", " 114 << test_case->high_char() << ")"; 115} 116 117void CMapTests::CommonSetUp(FontArray* font_array) { 118 ASSERT_NE(font_array, reinterpret_cast<FontArray*>(NULL)); 119 ASSERT_FALSE(font_array->empty()); 120 Ptr<Font> font; 121 font = font_array->at(0); 122 ASSERT_NE(font, reinterpret_cast<Font*>(NULL)); 123 Ptr<CMapTable> cmap_table = 124 down_cast<CMapTable*>(font->GetTable(Tag::cmap)); 125 cmap1_.Attach(cmap_table->GetCMap(GetParam().first_platform_id(), 126 GetParam().first_encoding_id())); 127 ASSERT_NE((cmap1_), reinterpret_cast<CMapTable::CMap*>(NULL)); 128 cmap2_.Attach(cmap_table->GetCMap(GetParam().second_platform_id(), 129 GetParam().second_encoding_id())); 130 ASSERT_NE((cmap2_), reinterpret_cast<CMapTable::CMap*>(NULL)); 131 encoder1_ = TestUtils::GetEncoder(GetParam().first_charset_name()); 132 encoder2_ = TestUtils::GetEncoder(GetParam().second_charset_name()); 133 successful_setup_ = true; 134} 135 136void CMapTests::TearDown() { 137 if (encoder1_) 138 ucnv_close(encoder1_); 139 if (encoder2_) 140 ucnv_close(encoder2_); 141} 142 143void CMapTests::CompareCMaps() { 144 ASSERT_TRUE(successful_setup_); 145 for (int32_t uchar = GetParam().low_char(); 146 uchar <= GetParam().high_char(); ++uchar) { 147 int32_t c1 = uchar; 148 if (encoder1_ != NULL) 149 c1 = TestUtils::EncodeOneChar(encoder1_, (int16_t)uchar); 150 int32_t c2 = uchar; 151 if (encoder2_ != NULL) 152 c2 = TestUtils::EncodeOneChar(encoder2_, (int16_t)uchar); 153 int32_t glyph_id1 = cmap1_->GlyphId(c1); 154 int32_t glyph_id2 = cmap2_->GlyphId(c2); 155#ifdef SFNTLY_DEBUG_CMAP 156 if (glyph_id1 != glyph_id2) 157 fprintf(stderr, "%x: g1=%x, %x: g2=%x\n", c1, glyph_id1, c2, glyph_id2); 158#endif 159 ASSERT_EQ(glyph_id1, glyph_id2); 160 } 161#ifdef SFNTLY_SFNTLY_DEBUG_CMAPCMAP 162 fprintf(stderr, "\n"); 163#endif 164} 165 166TEST_P(CMapTests, GlyphsBetweenCMapsFingerprint) { 167 Ptr<FontFactory> font_factory; 168 font_factory.Attach(FontFactory::GetInstance()); 169 font_factory->FingerprintFont(true); 170 FontArray font_array; 171 LoadFont(GetParam().font_name(), font_factory, &font_array); 172 CommonSetUp(&font_array); 173 CompareCMaps(); 174} 175 176TEST_P(CMapTests, GlyphsBetweenCMapsNoFingerprint) { 177 Ptr<FontFactory> font_factory; 178 font_factory.Attach(FontFactory::GetInstance()); 179 FontArray font_array; 180 LoadFont(GetParam().font_name(), font_factory, &font_array); 181 CommonSetUp(&font_array); 182 CompareCMaps(); 183} 184 185TEST_P(CMapTests, GlyphsBetweenCMapsUsingByteVector) { 186 FontArray font_array; 187 LoadFontUsingByteVector(GetParam().font_name(), true, &font_array); 188 CommonSetUp(&font_array); 189 CompareCMaps(); 190} 191 192CMapTestCase kCMapTestsTestCases[] = { 193 CMapTestCase(SAMPLE_TTF_FILE, 194 PlatformId::kWindows, 195 WindowsEncodingId::kUnicodeUCS2, 196 NULL, 197 PlatformId::kUnicode, 198 UnicodeEncodingId::kUnicode2_0_BMP, 199 NULL, 200 (int32_t)0x20, 201 (int32_t)0x7f), 202}; 203 204INSTANTIATE_TEST_CASE_P(CMapTests, 205 CMapTests, 206 ::testing::ValuesIn(kCMapTestsTestCases)); 207} 208 209#else 210 211TEST(DummyTest, ValueParameterizedTestsAreNotSupportedOnThisPlatform) {} 212 213#endif // GTEST_HAS_PARAM 214