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 "gtest/gtest.h" 18 #include "sfntly/font.h" 19 #include "sfntly/port/file_input_stream.h" 20 #include "sfntly/port/memory_input_stream.h" 21 #include "sfntly/port/memory_output_stream.h" 22 #include "sfntly/table/bitmap/ebdt_table.h" 23 #include "sfntly/table/bitmap/eblc_table.h" 24 #include "sfntly/table/bitmap/index_sub_table_format3.h" 25 #include "sfntly/table/bitmap/index_sub_table_format4.h" 26 #include "test/test_data.h" 27 #include "test/test_font_utils.h" 28 29 namespace sfntly { 30 31 const int32_t NUM_STRIKES = 4; 32 const int32_t STRIKE1_ARRAY_OFFSET = 0xc8; 33 const int32_t STRIKE1_INDEX_TABLE_SIZE = 0x4f4; 34 const int32_t STRIKE1_NUM_INDEX_TABLES = 1; 35 const int32_t STRIKE1_COLOR_REF = 0; 36 const int32_t STRIKE1_START_GLYPH_INDEX = 0; 37 const int32_t STRIKE1_END_GLYPH_INDEX = 623; 38 const int32_t STRIKE1_PPEM_X = 10; 39 const int32_t STRIKE1_PPEM_Y = 10; 40 const int32_t STRIKE1_BIT_DEPTH = 1; 41 const int32_t STRIKE1_FLAGS = 0x01; 42 43 const int32_t STRIKE4_SUB1_INDEX_FORMAT = 3; 44 const int32_t STRIKE4_SUB1_IMAGE_FORMAT = 1; 45 const int32_t STRIKE4_SUB1_IMAGE_DATA_OFFSET = 0x00005893; 46 const int32_t STRIKE4_SUB1_GLYPH_OFFSET[] = { 47 0x00005893, 0x00005898, 0x0000589d, 0x000058a2, 0x000058a7, 48 0x000058b2, 0x000058c2, 0x000058d0, 0x000058de, 0x000058e6 }; 49 const int32_t NUM_STRIKE4_SUB1_GLYPH_OFFSET = 10; 50 const int32_t STRIKE4_SUB1_GLYPH2_LENGTH = 0x58a2 - 0x589d; 51 52 bool CommonReadingTest(Font* raw_font) { 53 FontPtr font = raw_font; 54 55 EblcTablePtr bitmap_loca = down_cast<EblcTable*>(font->GetTable(Tag::EBLC)); 56 EbdtTablePtr bitmap_table = down_cast<EbdtTable*>(font->GetTable(Tag::EBDT)); 57 58 EXPECT_FALSE(bitmap_loca == NULL); 59 EXPECT_FALSE(bitmap_table == NULL); 60 61 EXPECT_EQ(bitmap_loca->NumSizes(), NUM_STRIKES); 62 63 // Strike 1 64 BitmapSizeTablePtr strike1 = bitmap_loca->GetBitmapSizeTable(0); 65 EXPECT_FALSE(strike1 == NULL); 66 EXPECT_EQ(strike1->IndexSubTableArrayOffset(), STRIKE1_ARRAY_OFFSET); 67 EXPECT_EQ(strike1->NumberOfIndexSubTables(), STRIKE1_NUM_INDEX_TABLES); 68 EXPECT_EQ(strike1->ColorRef(), STRIKE1_COLOR_REF); 69 EXPECT_EQ(strike1->StartGlyphIndex(), STRIKE1_START_GLYPH_INDEX); 70 EXPECT_EQ(strike1->EndGlyphIndex(), STRIKE1_END_GLYPH_INDEX); 71 EXPECT_EQ(strike1->PpemX(), STRIKE1_PPEM_X); 72 EXPECT_EQ(strike1->PpemY(), STRIKE1_PPEM_Y); 73 EXPECT_EQ(strike1->BitDepth(), STRIKE1_BIT_DEPTH); 74 EXPECT_EQ(strike1->FlagsAsInt(), STRIKE1_FLAGS); 75 76 // Strike 4 77 // In this test font, all strikes and all subtables have same glyphs. 78 BitmapSizeTablePtr strike4 = bitmap_loca->GetBitmapSizeTable(3); 79 EXPECT_FALSE(strike4 == NULL); 80 EXPECT_EQ(strike4->StartGlyphIndex(), STRIKE1_START_GLYPH_INDEX); 81 EXPECT_EQ(strike4->EndGlyphIndex(), STRIKE1_END_GLYPH_INDEX); 82 IndexSubTablePtr sub1 = strike4->GetIndexSubTable(0); 83 EXPECT_FALSE(sub1 == NULL); 84 EXPECT_EQ(sub1->image_format(), STRIKE4_SUB1_IMAGE_FORMAT); 85 EXPECT_EQ(sub1->first_glyph_index(), STRIKE1_START_GLYPH_INDEX); 86 EXPECT_EQ(sub1->last_glyph_index(), STRIKE1_END_GLYPH_INDEX); 87 EXPECT_EQ(sub1->image_data_offset(), STRIKE4_SUB1_IMAGE_DATA_OFFSET); 88 89 for (int32_t i = 0; i < NUM_STRIKE4_SUB1_GLYPH_OFFSET; ++i) { 90 EXPECT_EQ(sub1->GlyphOffset(i), STRIKE4_SUB1_GLYPH_OFFSET[i]); 91 } 92 return true; 93 } 94 95 bool TestReadingBitmapTable() { 96 FontFactoryPtr factory; 97 factory.Attach(FontFactory::GetInstance()); 98 FontArray font_array; 99 LoadFont(SAMPLE_BITMAP_FONT, factory, &font_array); 100 FontPtr font = font_array[0]; 101 EXPECT_TRUE(CommonReadingTest(font)); 102 103 EblcTablePtr bitmap_loca = down_cast<EblcTable*>(font->GetTable(Tag::EBLC)); 104 BitmapSizeTablePtr strike1 = bitmap_loca->GetBitmapSizeTable(0); 105 BitmapSizeTablePtr strike4 = bitmap_loca->GetBitmapSizeTable(3); 106 IndexSubTablePtr sub1 = strike4->GetIndexSubTable(0); 107 108 EXPECT_EQ(strike1->IndexTableSize(), STRIKE1_INDEX_TABLE_SIZE); 109 EXPECT_EQ(sub1->index_format(), STRIKE4_SUB1_INDEX_FORMAT); 110 111 // Strike 4 Index Sub Table 1 is a Format 3 112 IndexSubTableFormat3Ptr sub3 = 113 down_cast<IndexSubTableFormat3*>(strike4->GetIndexSubTable(0)); 114 EXPECT_FALSE(sub3 == NULL); 115 BitmapGlyphInfoPtr info; 116 info.Attach(sub3->GlyphInfo(2)); 117 EXPECT_EQ(info->glyph_id(), 2); 118 EXPECT_EQ(info->block_offset(), STRIKE4_SUB1_IMAGE_DATA_OFFSET); 119 EXPECT_EQ(info->start_offset(), 120 STRIKE4_SUB1_GLYPH_OFFSET[2] - STRIKE4_SUB1_GLYPH_OFFSET[0]); 121 EXPECT_EQ(info->format(), STRIKE4_SUB1_IMAGE_FORMAT); 122 EXPECT_EQ(info->length(), STRIKE4_SUB1_GLYPH2_LENGTH); 123 124 return true; 125 } 126 127 // Function in subset_impl.cc 128 extern 129 void SubsetEBLC(EblcTable::Builder* eblc, const BitmapLocaList& new_loca); 130 131 bool TestIndexFormatConversion() { 132 FontFactoryPtr factory; 133 factory.Attach(FontFactory::GetInstance()); 134 FontBuilderArray builder_array; 135 BuilderForFontFile(SAMPLE_BITMAP_FONT, factory, &builder_array); 136 137 FontBuilderPtr font_builder; 138 font_builder = builder_array[0]; 139 EblcTableBuilderPtr eblc_builder = 140 down_cast<EblcTable::Builder*>(font_builder->GetTableBuilder(Tag::EBLC)); 141 BitmapLocaList new_loca; 142 eblc_builder->GenerateLocaList(&new_loca); 143 SubsetEBLC(eblc_builder, new_loca); // Format 3 -> 4 144 145 FontPtr new_font; 146 new_font.Attach(font_builder->Build()); 147 148 // Serialize and reload the serialized font. 149 MemoryOutputStream os; 150 factory->SerializeFont(new_font, &os); 151 152 #if defined (SFNTLY_DEBUG_BITMAP) 153 SerializeToFile(&os, "anon-mod.ttf"); 154 #endif 155 156 MemoryInputStream is; 157 is.Attach(os.Get(), os.Size()); 158 FontArray font_array; 159 factory->LoadFonts(&is, &font_array); 160 new_font = font_array[0]; 161 162 EXPECT_TRUE(CommonReadingTest(new_font)); 163 164 // Strike 4 Index Sub Table 1 is a Format 4 165 EblcTablePtr bitmap_loca = 166 down_cast<EblcTable*>(new_font->GetTable(Tag::EBLC)); 167 BitmapSizeTablePtr strike4 = bitmap_loca->GetBitmapSizeTable(3); 168 IndexSubTableFormat4Ptr sub4 = 169 down_cast<IndexSubTableFormat4*>(strike4->GetIndexSubTable(0)); 170 EXPECT_FALSE(sub4 == NULL); 171 172 // And this subtable shall have exactly the same offset as original table 173 // since no subsetting happens. 174 FontArray original_font_array; 175 LoadFont(SAMPLE_BITMAP_FONT, factory, &original_font_array); 176 FontPtr font = original_font_array[0]; 177 EXPECT_FALSE(font == NULL); 178 EblcTablePtr original_loca = down_cast<EblcTable*>(font->GetTable(Tag::EBLC)); 179 EXPECT_FALSE(original_loca == NULL); 180 BitmapSizeTablePtr original_strike4 = bitmap_loca->GetBitmapSizeTable(3); 181 EXPECT_FALSE(original_strike4 == NULL); 182 IndexSubTableFormat3Ptr sub3 = 183 down_cast<IndexSubTableFormat3*>(strike4->GetIndexSubTable(0)); 184 EXPECT_FALSE(sub3 == NULL); 185 EXPECT_EQ(strike4->StartGlyphIndex(), original_strike4->StartGlyphIndex()); 186 EXPECT_EQ(strike4->EndGlyphIndex(), original_strike4->EndGlyphIndex()); 187 for (int32_t i = strike4->StartGlyphIndex(); 188 i <= strike4->EndGlyphIndex(); ++i) { 189 BitmapGlyphInfoPtr info, original_info; 190 info.Attach(sub4->GlyphInfo(i)); 191 original_info.Attach(sub3->GlyphInfo(i)); 192 EXPECT_EQ(info->format(), original_info->format()); 193 EXPECT_EQ(info->glyph_id(), original_info->glyph_id()); 194 EXPECT_EQ(info->length(), original_info->length()); 195 EXPECT_EQ(info->offset(), original_info->offset()); 196 } 197 198 return true; 199 } 200 201 } // namespace sfntly 202 203 TEST(BitmapTable, Reading) { 204 ASSERT_TRUE(sfntly::TestReadingBitmapTable()); 205 } 206 207 TEST(BitmapTable, IndexFormatConversion) { 208 ASSERT_TRUE(sfntly::TestIndexFormatConversion()); 209 } 210