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 
CommonReadingTest(Font * raw_font)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   if (!bitmap_loca) {
62     return false;
63   }
64 
65   EXPECT_EQ(bitmap_loca->NumSizes(), NUM_STRIKES);
66 
67   // Strike 1
68   BitmapSizeTablePtr strike1 = bitmap_loca->GetBitmapSizeTable(0);
69   EXPECT_FALSE(strike1 == NULL);
70   if (!strike1) {
71     return false;
72   }
73   EXPECT_EQ(strike1->IndexSubTableArrayOffset(), STRIKE1_ARRAY_OFFSET);
74   EXPECT_EQ(strike1->NumberOfIndexSubTables(), STRIKE1_NUM_INDEX_TABLES);
75   EXPECT_EQ(strike1->ColorRef(), STRIKE1_COLOR_REF);
76   EXPECT_EQ(strike1->StartGlyphIndex(), STRIKE1_START_GLYPH_INDEX);
77   EXPECT_EQ(strike1->EndGlyphIndex(), STRIKE1_END_GLYPH_INDEX);
78   EXPECT_EQ(strike1->PpemX(), STRIKE1_PPEM_X);
79   EXPECT_EQ(strike1->PpemY(), STRIKE1_PPEM_Y);
80   EXPECT_EQ(strike1->BitDepth(), STRIKE1_BIT_DEPTH);
81   EXPECT_EQ(strike1->FlagsAsInt(), STRIKE1_FLAGS);
82 
83   // Strike 4
84   // In this test font, all strikes and all subtables have same glyphs.
85   BitmapSizeTablePtr strike4 = bitmap_loca->GetBitmapSizeTable(3);
86   EXPECT_FALSE(strike4 == NULL);
87   EXPECT_EQ(strike4->StartGlyphIndex(), STRIKE1_START_GLYPH_INDEX);
88   EXPECT_EQ(strike4->EndGlyphIndex(), STRIKE1_END_GLYPH_INDEX);
89   IndexSubTablePtr sub1 = strike4->GetIndexSubTable(0);
90   EXPECT_FALSE(sub1 == NULL);
91   EXPECT_EQ(sub1->image_format(), STRIKE4_SUB1_IMAGE_FORMAT);
92   EXPECT_EQ(sub1->first_glyph_index(), STRIKE1_START_GLYPH_INDEX);
93   EXPECT_EQ(sub1->last_glyph_index(), STRIKE1_END_GLYPH_INDEX);
94   EXPECT_EQ(sub1->image_data_offset(), STRIKE4_SUB1_IMAGE_DATA_OFFSET);
95 
96   for (int32_t i = 0; i < NUM_STRIKE4_SUB1_GLYPH_OFFSET; ++i) {
97       EXPECT_EQ(sub1->GlyphOffset(i), STRIKE4_SUB1_GLYPH_OFFSET[i]);
98   }
99   return true;
100 }
101 
TestReadingBitmapTable()102 bool TestReadingBitmapTable() {
103   FontFactoryPtr factory;
104   factory.Attach(FontFactory::GetInstance());
105   FontArray font_array;
106   LoadFont(SAMPLE_BITMAP_FONT, factory, &font_array);
107   FontPtr font = font_array[0];
108   EXPECT_TRUE(CommonReadingTest(font));
109 
110   EblcTablePtr bitmap_loca = down_cast<EblcTable*>(font->GetTable(Tag::EBLC));
111   BitmapSizeTablePtr strike1 = bitmap_loca->GetBitmapSizeTable(0);
112   BitmapSizeTablePtr strike4 = bitmap_loca->GetBitmapSizeTable(3);
113   IndexSubTablePtr sub1 = strike4->GetIndexSubTable(0);
114 
115   EXPECT_EQ(strike1->IndexTableSize(), STRIKE1_INDEX_TABLE_SIZE);
116   EXPECT_EQ(sub1->index_format(), STRIKE4_SUB1_INDEX_FORMAT);
117 
118   // Strike 4 Index Sub Table 1 is a Format 3
119   IndexSubTableFormat3Ptr sub3 =
120       down_cast<IndexSubTableFormat3*>(strike4->GetIndexSubTable(0));
121   EXPECT_FALSE(sub3 == NULL);
122   BitmapGlyphInfoPtr info;
123   info.Attach(sub3->GlyphInfo(2));
124   EXPECT_EQ(info->glyph_id(), 2);
125   EXPECT_EQ(info->block_offset(), STRIKE4_SUB1_IMAGE_DATA_OFFSET);
126   EXPECT_EQ(info->start_offset(),
127             STRIKE4_SUB1_GLYPH_OFFSET[2] - STRIKE4_SUB1_GLYPH_OFFSET[0]);
128   EXPECT_EQ(info->format(), STRIKE4_SUB1_IMAGE_FORMAT);
129   EXPECT_EQ(info->length(), STRIKE4_SUB1_GLYPH2_LENGTH);
130 
131   return true;
132 }
133 
134 // Function in subset_impl.cc
135 extern
136 void SubsetEBLC(EblcTable::Builder* eblc, const BitmapLocaList& new_loca);
137 
TestIndexFormatConversion()138 bool TestIndexFormatConversion() {
139   FontFactoryPtr factory;
140   factory.Attach(FontFactory::GetInstance());
141   FontBuilderArray builder_array;
142   BuilderForFontFile(SAMPLE_BITMAP_FONT, factory, &builder_array);
143 
144   FontBuilderPtr font_builder;
145   font_builder = builder_array[0];
146   EblcTableBuilderPtr eblc_builder =
147       down_cast<EblcTable::Builder*>(font_builder->GetTableBuilder(Tag::EBLC));
148   BitmapLocaList new_loca;
149   eblc_builder->GenerateLocaList(&new_loca);
150   SubsetEBLC(eblc_builder, new_loca);  // Format 3 -> 4
151 
152   FontPtr new_font;
153   new_font.Attach(font_builder->Build());
154 
155   // Serialize and reload the serialized font.
156   MemoryOutputStream os;
157   factory->SerializeFont(new_font, &os);
158 
159 #if defined (SFNTLY_DEBUG_BITMAP)
160   SerializeToFile(&os, "anon-mod.ttf");
161 #endif
162 
163   MemoryInputStream is;
164   is.Attach(os.Get(), os.Size());
165   FontArray font_array;
166   factory->LoadFonts(&is, &font_array);
167   new_font = font_array[0];
168 
169   EXPECT_TRUE(CommonReadingTest(new_font));
170 
171   // Strike 4 Index Sub Table 1 is a Format 4
172   EblcTablePtr bitmap_loca =
173       down_cast<EblcTable*>(new_font->GetTable(Tag::EBLC));
174   BitmapSizeTablePtr strike4 = bitmap_loca->GetBitmapSizeTable(3);
175   IndexSubTableFormat4Ptr sub4 =
176       down_cast<IndexSubTableFormat4*>(strike4->GetIndexSubTable(0));
177   EXPECT_FALSE(sub4 == NULL);
178 
179   // And this subtable shall have exactly the same offset as original table
180   // since no subsetting happens.
181   FontArray original_font_array;
182   LoadFont(SAMPLE_BITMAP_FONT, factory, &original_font_array);
183   FontPtr font = original_font_array[0];
184   EXPECT_FALSE(font == NULL);
185   EblcTablePtr original_loca = down_cast<EblcTable*>(font->GetTable(Tag::EBLC));
186   EXPECT_FALSE(original_loca == NULL);
187   BitmapSizeTablePtr original_strike4 = bitmap_loca->GetBitmapSizeTable(3);
188   EXPECT_FALSE(original_strike4 == NULL);
189   IndexSubTableFormat3Ptr sub3 =
190       down_cast<IndexSubTableFormat3*>(strike4->GetIndexSubTable(0));
191   EXPECT_FALSE(sub3 == NULL);
192   EXPECT_EQ(strike4->StartGlyphIndex(), original_strike4->StartGlyphIndex());
193   EXPECT_EQ(strike4->EndGlyphIndex(), original_strike4->EndGlyphIndex());
194   for (int32_t i = strike4->StartGlyphIndex();
195                i <= strike4->EndGlyphIndex(); ++i) {
196     BitmapGlyphInfoPtr info, original_info;
197     info.Attach(sub4->GlyphInfo(i));
198     original_info.Attach(sub3->GlyphInfo(i));
199     EXPECT_EQ(info->format(), original_info->format());
200     EXPECT_EQ(info->glyph_id(), original_info->glyph_id());
201     EXPECT_EQ(info->length(), original_info->length());
202     EXPECT_EQ(info->offset(), original_info->offset());
203   }
204 
205   return true;
206 }
207 
208 }  // namespace sfntly
209 
TEST(BitmapTable,Reading)210 TEST(BitmapTable, Reading) {
211   ASSERT_TRUE(sfntly::TestReadingBitmapTable());
212 }
213 
TEST(BitmapTable,IndexFormatConversion)214 TEST(BitmapTable, IndexFormatConversion) {
215   ASSERT_TRUE(sfntly::TestIndexFormatConversion());
216 }
217