1 /* GRAPHITE2 LICENSING
2
3 Copyright 2010, SIL International
4 All rights reserved.
5
6 This library is free software; you can redistribute it and/or modify
7 it under the terms of the GNU Lesser General Public License as published
8 by the Free Software Foundation; either version 2.1 of License, or
9 (at your option) any later version.
10
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 Lesser General Public License for more details.
15
16 You should also have received a copy of the GNU Lesser General Public
17 License along with this library in the file named "LICENSE".
18 If not, write to the Free Software Foundation, 51 Franklin Street,
19 Suite 500, Boston, MA 02110-1335, USA or visit their web page on the
20 internet at http://www.fsf.org/licenses/lgpl.html.
21 */
22 #include <cassert>
23 #include <cstdio>
24 #include <cstdlib>
25 #include <cstring>
26 #include <graphite2/Types.h>
27 #include "inc/Main.h"
28 #include "inc/Endian.h"
29 #include "inc/TtfTypes.h"
30 #include "inc/NameTable.h"
31
32 using namespace graphite2;
33
34 #pragma pack(push, 1)
35 struct NameTestA
36 {
37 TtfUtil::Sfnt::FontNames m_nameHeader;
38 TtfUtil::Sfnt::NameRecord m_records[5];
39 uint8 m_textData[27];
40 };
41
42 struct NameTestB
43 {
44 TtfUtil::Sfnt::FontNames m_nameHeader;
45 TtfUtil::Sfnt::NameRecord m_records[7];
46 uint16 m_langTagCount;
47 TtfUtil::Sfnt::LangTagRecord m_languages[2];
48 uint8 m_textData[59];
49 };
50 #pragma pack(pop)
51
52
53 NameTestA testA = {
54 {0, 6, (5 * sizeof(TtfUtil::Sfnt::NameRecord)) +
55 sizeof(TtfUtil::Sfnt::FontNames), {{0, 0, 0, 1, 1, 0}}},
56 {
57 {3, 1, 0x409, 1, 4, 1},
58 {3, 1, 0x409, 7, 6, 5},
59 {3, 1, 0x455, 7, 4, 11},
60 {3, 1, 0x809, 1, 4, 15},
61 {3, 1, 0x809, 7, 8, 19}
62 },
63 {0x41,
64 0,0x41,0,0x61,
65 0,0x41,0,0x42,0,0x43,
66 0x10,0x00,0x10,0x01,
67 0,0x61,0,0x61,
68 0,0x61,0,0x62,0,0x63,0,0x64}
69 };
70
71 NameTestB testB = {
72 {1, 8, (7 * sizeof(TtfUtil::Sfnt::NameRecord)) +
73 sizeof(TtfUtil::Sfnt::FontNames) +
74 2 + 2 * sizeof(TtfUtil::Sfnt::LangTagRecord),
75 {{0, 0, 0, 1, 1, 0}}},
76 {
77 {3, 1, 0x409, 1, 4, 1},
78 {3, 1, 0x409, 7, 6, 5},
79 {3, 1, 0x455, 7, 4, 11},
80 {3, 1, 0x809, 1, 4, 15},
81 {3, 1, 0x809, 7, 8, 19},
82 {3, 1, 0x8000, 7, 6, 27},
83 {3, 1, 0x8001, 7, 2, 33}
84 },
85 2,
86 {
87 {12,35},{12,47}
88 },
89 {0x41,
90 0,0x41,0,0x61,
91 0,0x41,0,0x42,0,0x43,
92 0x10,0x00,0x10,0x01,
93 0,0x61,0,0x61,
94 0,0x61,0,0x62,0,0x63,0,0x64,
95 0x10,0x00,0x10,0x62,0x10,0x64,
96 0x10,0x5c,
97 0,0x6b,0,0x73,0,0x77,0,0x2d,0,0x4d,0,0x4d,
98 0,0x6d,0,0x6e,0,0x77,0,0x2d,0,0x4d,0,0x4d
99 }
100 };
101
testName(void * data,size_t length,uint16 langId,uint16 actualLang,uint16 nameId,const char * utf8Text)102 void testName(void * data, size_t length, uint16 langId,
103 uint16 actualLang, uint16 nameId, const char * utf8Text)
104 {
105 NameTable name(data, length);
106 uint16 lang = langId;
107 uint32 strLen = 0;
108 char * n = reinterpret_cast<char*>(name.getName(lang, nameId, gr_utf8, strLen));
109 if ((n == NULL) || (strncmp(n, utf8Text, strLen) != 0))
110 {
111 fprintf(stderr, "name=%s expected=%s\n", n, utf8Text);
112 free(n);
113 exit(1);
114 }
115 free(n);
116 if (lang != actualLang)
117 {
118 fprintf(stderr, "lang=%x actual=%x\n", lang, actualLang);
119 exit(1);
120 }
121 }
122
testLangId(void * data,size_t length,const char * id,uint16 expected)123 void testLangId(void * data, size_t length, const char * id, uint16 expected)
124 {
125 NameTable table(data, length);
126 uint16 lId = table.getLanguageId(id);
127 if (lId != expected)
128 {
129 fprintf(stderr, "%s lang id: %d expected: %d\n", id, lId, expected);
130 }
131 }
132
toBigEndian(T & table)133 template <class T> T * toBigEndian(T & table)
134 {
135 T * bigEndian = gralloc<T>(1);
136 bigEndian->m_nameHeader.format = be::swap<uint16>(table.m_nameHeader.format);
137 bigEndian->m_nameHeader.count = be::swap<uint16>(table.m_nameHeader.count);
138 bigEndian->m_nameHeader.string_offset = be::swap<uint16>(table.m_nameHeader.string_offset);
139
140 for (uint16 i = 0; i < table.m_nameHeader.count; i++)
141 {
142 bigEndian->m_records[i].platform_id = be::swap<uint16>(table.m_records[i].platform_id);
143 bigEndian->m_records[i].platform_specific_id = be::swap<uint16>(table.m_records[i].platform_specific_id);
144 bigEndian->m_records[i].language_id = be::swap<uint16>(table.m_records[i].language_id);
145 bigEndian->m_records[i].name_id = be::swap<uint16>(table.m_records[i].name_id);
146 bigEndian->m_records[i].length = be::swap<uint16>(table.m_records[i].length);
147 bigEndian->m_records[i].offset = be::swap<uint16>(table.m_records[i].offset);
148 }
149
150 bigEndian->m_nameHeader.name_record[0].platform_id = be::swap<uint16>(table.m_nameHeader.name_record[0].platform_id);
151 bigEndian->m_nameHeader.name_record[0].platform_specific_id = be::swap<uint16>(table.m_nameHeader.name_record[0].platform_specific_id);
152 bigEndian->m_nameHeader.name_record[0].language_id = be::swap<uint16>(table.m_nameHeader.name_record[0].language_id);
153 bigEndian->m_nameHeader.name_record[0].name_id = be::swap<uint16>(table.m_nameHeader.name_record[0].name_id);
154 bigEndian->m_nameHeader.name_record[0].length = be::swap<uint16>(table.m_nameHeader.name_record[0].length);
155 bigEndian->m_nameHeader.name_record[0].offset = be::swap<uint16>(table.m_nameHeader.name_record[0].offset);
156
157 memcpy(bigEndian->m_textData, table.m_textData, sizeof(table.m_textData) );
158 return bigEndian;
159 }
160
toBigEndian1(T & table)161 template <class T> T * toBigEndian1(T & table)
162 {
163 T * bigEndian = toBigEndian<T>(table);
164 bigEndian->m_langTagCount = be::swap<uint16>(table.m_langTagCount);
165 for (size_t i = 0; i < table.m_langTagCount; i++)
166 {
167 bigEndian->m_languages[i] = be::swap<uint16>(table.m_languages[i]);
168 bigEndian->m_languages[i] = be::swap<uint16>(table.m_languages[i]);
169 }
170 }
171
main(int,char **)172 int main(int, char **)
173 {
174 struct NameTestA* testAData = toBigEndian<struct NameTestA>(testA);
175 testName(testAData, sizeof(NameTestA), 0x409, 0x409, 1, "Aa");
176 testName(testAData, sizeof(NameTestA), 0x809, 0x809, 1, "aa");
177 testName(testAData, sizeof(NameTestA), 0x455, 0x409, 1, "Aa");
178
179 testName(testAData, sizeof(NameTestA), 0x409, 0x409, 7, "ABC");
180 testName(testAData, sizeof(NameTestA), 0x809, 0x809, 7, "abcd");
181 testName(testAData, sizeof(NameTestA), 0x455, 0x455, 7, "ကခ");
182
183 testLangId(testAData, sizeof(NameTestA), "en-US", 0x409);
184 testLangId(testAData, sizeof(NameTestA), "en", 0x409);
185 testLangId(testAData, sizeof(NameTestA), "en-GB", 0x809);
186 testLangId(testAData, sizeof(NameTestA), "en-Latn-GB", 0x809);
187 testLangId(testAData, sizeof(NameTestA), "en-Latn-GB-Cockney", 0x809);
188 testLangId(testAData, sizeof(NameTestA), "my-MM", 0x455);
189 testLangId(testAData, sizeof(NameTestA), "my-Mymr", 0x455);
190 testLangId(testAData, sizeof(NameTestA), "my-Mymr-MM", 0x455);
191 testLangId(testAData, sizeof(NameTestA), "en-GB-Cockney", 0x809);
192 free(testAData);
193
194 struct NameTestB* testBData = toBigEndian<struct NameTestB>(testB);
195 testLangId(testBData, sizeof(NameTestB), "en-US", 0x409);
196 testLangId(testBData, sizeof(NameTestB), "en-GB", 0x809);
197 testLangId(testBData, sizeof(NameTestB), "ksw-MM", 0x8000);
198 testLangId(testBData, sizeof(NameTestB), "mnw-MM", 0x8001);
199 testName(testBData, sizeof(NameTestB), 0x809, 0x809, 7, "abcd");
200 testName(testBData, sizeof(NameTestB), 0x455, 0x455, 7, "ကခ");
201 testName(testBData, sizeof(NameTestB), 0x8000, 0x8000, 7, "ကၢၤ");
202 testName(testBData, sizeof(NameTestB), 0x8001, 0x8001, 7, "ၜ");
203 testName(testBData, sizeof(NameTestB), 0x8002, 0x409, 1, "Aa");
204 free(testBData);
205
206 return 0;
207 }
208