]> git.saurik.com Git - apple/icu.git/blob - icuSources/test/letest/PortableFontInstance.cpp
ICU-3.13.tar.gz
[apple/icu.git] / icuSources / test / letest / PortableFontInstance.cpp
1 /*
2 *******************************************************************************
3 *
4 * Copyright (C) 1999-2003, International Business Machines
5 * Corporation and others. All Rights Reserved.
6 *
7 *******************************************************************************
8 * file name: PortableFontInstance.cpp
9 *
10 * created on: 11/22/1999
11 * created by: Eric R. Mader
12 */
13
14 #include <stdio.h>
15
16 #include "layout/LETypes.h"
17 #include "layout/LEFontInstance.h"
18 #include "layout/LESwaps.h"
19
20 #include "PortableFontInstance.h"
21
22 #include "sfnt.h"
23
24 #include <string.h>
25
26 //
27 // Finds the high bit by binary searching
28 // through the bits in n.
29 //
30 le_int8 PortableFontInstance::highBit(le_int32 value)
31 {
32 if (value <= 0) {
33 return -32;
34 }
35
36 le_uint8 bit = 0;
37
38 if (value >= 1 << 16) {
39 value >>= 16;
40 bit += 16;
41 }
42
43 if (value >= 1 << 8) {
44 value >>= 8;
45 bit += 8;
46 }
47
48 if (value >= 1 << 4) {
49 value >>= 4;
50 bit += 4;
51 }
52
53 if (value >= 1 << 2) {
54 value >>= 2;
55 bit += 2;
56 }
57
58 if (value >= 1 << 1) {
59 value >>= 1;
60 bit += 1;
61 }
62
63 return bit;
64 }
65
66
67 PortableFontInstance::PortableFontInstance(char *fileName, float pointSize, LEErrorCode &status)
68 : fFile(NULL), fUnitsPerEM(0), fPointSize(pointSize), fAscent(0), fDescent(0), fLeading(0),
69 fDirectory(NULL), fCMAPMapper(NULL), fHMTXTable(NULL), fNumGlyphs(0), fNumLongHorMetrics(0)
70 {
71 if (LE_FAILURE(status)) {
72 return;
73 }
74
75 // open the font file
76 fFile = fopen(fileName, "rb");
77
78 if (fFile == NULL) {
79 status = LE_FONT_FILE_NOT_FOUND_ERROR;
80 return;
81 }
82
83 // read in the directory
84 SFNTDirectory tempDir;
85
86 fread(&tempDir, sizeof tempDir, 1, fFile);
87
88 le_int32 dirSize = sizeof tempDir + ((SWAPW(tempDir.numTables) - ANY_NUMBER) * sizeof(DirectoryEntry));
89 const LETag headTag = LE_HEAD_TABLE_TAG;
90 const LETag hheaTag = LE_HHEA_TABLE_TAG;
91 const HEADTable *headTable = NULL;
92 const HHEATable *hheaTable = NULL;
93 le_uint16 numTables = 0;
94
95 fDirectory = (const SFNTDirectory *) LE_NEW_ARRAY(char, dirSize);
96
97 if (fDirectory == NULL) {
98 status = LE_MEMORY_ALLOCATION_ERROR;
99 goto error_exit;
100 }
101
102 fseek(fFile, 0L, SEEK_SET);
103 fread((void *) fDirectory, sizeof(char), dirSize, fFile);
104
105 //
106 // We calculate these numbers 'cause some fonts
107 // have bogus values for them in the directory header.
108 //
109 numTables = SWAPW(fDirectory->numTables);
110 fDirPower = 1 << highBit(numTables);
111 fDirExtra = numTables - fDirPower;
112
113 // read unitsPerEm from 'head' table
114 headTable = (const HEADTable *) readFontTable(headTag);
115
116 if (headTable == NULL) {
117 status = LE_MISSING_FONT_TABLE_ERROR;
118 goto error_exit;
119 }
120
121 fUnitsPerEM = SWAPW(headTable->unitsPerEm);
122 deleteTable(headTable);
123
124 hheaTable = (HHEATable *) readFontTable(hheaTag);
125
126 if (hheaTable == NULL) {
127 status = LE_MISSING_FONT_TABLE_ERROR;
128 goto error_exit;
129 }
130
131 fAscent = (le_int32) yUnitsToPoints((float) SWAPW(hheaTable->ascent));
132 fDescent = (le_int32) yUnitsToPoints((float) SWAPW(hheaTable->descent));
133 fLeading = (le_int32) yUnitsToPoints((float) SWAPW(hheaTable->lineGap));
134
135 fNumLongHorMetrics = SWAPW(hheaTable->numOfLongHorMetrics);
136
137 deleteTable((void *) hheaTable);
138
139 fCMAPMapper = findUnicodeMapper();
140
141 if (fCMAPMapper == NULL) {
142 status = LE_MISSING_FONT_TABLE_ERROR;
143 goto error_exit;
144 }
145
146 return;
147
148 error_exit:
149 fclose(fFile);
150 fFile = NULL;
151 return;
152 }
153
154 PortableFontInstance::~PortableFontInstance()
155 {
156 if (fFile != NULL) {
157 fclose(fFile);
158
159 deleteTable(fHMTXTable);
160
161 delete fCMAPMapper;
162
163 LE_DELETE_ARRAY(fDirectory);
164 }
165 };
166
167 void PortableFontInstance::deleteTable(const void *table) const
168 {
169 LE_DELETE_ARRAY(table);
170 }
171
172 const DirectoryEntry *PortableFontInstance::findTable(LETag tag) const
173 {
174 if (fDirectory != NULL) {
175 le_uint16 table = 0;
176 le_uint16 probe = fDirPower;
177
178 if (SWAPL(fDirectory->tableDirectory[fDirExtra].tag) <= tag) {
179 table = fDirExtra;
180 }
181
182 while (probe > (1 << 0)) {
183 probe >>= 1;
184
185 if (SWAPL(fDirectory->tableDirectory[table + probe].tag) <= tag) {
186 table += probe;
187 }
188 }
189
190 if (SWAPL(fDirectory->tableDirectory[table].tag) == tag) {
191 return &fDirectory->tableDirectory[table];
192 }
193 }
194
195 return NULL;
196 }
197
198 const void *PortableFontInstance::readTable(LETag tag, le_uint32 *length) const
199 {
200 const DirectoryEntry *entry = findTable(tag);
201
202 if (entry == NULL) {
203 *length = 0;
204 return NULL;
205 }
206
207 *length = SWAPL(entry->length);
208
209 void *table = LE_NEW_ARRAY(char, *length);
210
211 if (table != NULL) {
212 fseek(fFile, SWAPL(entry->offset), SEEK_SET);
213 fread(table, sizeof(char), *length, fFile);
214 }
215
216 return table;
217 }
218
219 const void *PortableFontInstance::getFontTable(LETag tableTag) const
220 {
221 return FontTableCache::find(tableTag);
222 }
223
224 const void *PortableFontInstance::readFontTable(LETag tableTag) const
225 {
226 le_uint32 len;
227
228 return readTable(tableTag, &len);
229 }
230
231 CMAPMapper *PortableFontInstance::findUnicodeMapper()
232 {
233 LETag cmapTag = LE_CMAP_TABLE_TAG;
234 const CMAPTable *cmap = (CMAPTable *) readFontTable(cmapTag);
235
236 if (cmap == NULL) {
237 return NULL;
238 }
239
240 return CMAPMapper::createUnicodeMapper(cmap);
241 }
242
243
244 void PortableFontInstance::getGlyphAdvance(LEGlyphID glyph, LEPoint &advance) const
245 {
246 TTGlyphID ttGlyph = (TTGlyphID) LE_GET_GLYPH(glyph);
247
248 if (fHMTXTable == NULL) {
249 LETag maxpTag = LE_MAXP_TABLE_TAG;
250 LETag hmtxTag = LE_HMTX_TABLE_TAG;
251 const MAXPTable *maxpTable = (MAXPTable *) readFontTable(maxpTag);
252 PortableFontInstance *realThis = (PortableFontInstance *) this;
253
254 if (maxpTable != NULL) {
255 realThis->fNumGlyphs = SWAPW(maxpTable->numGlyphs);
256 deleteTable(maxpTable);
257 }
258
259 realThis->fHMTXTable = (const HMTXTable *) readFontTable(hmtxTag);
260 }
261
262 le_uint16 index = ttGlyph;
263
264 if (ttGlyph >= fNumGlyphs || fHMTXTable == NULL) {
265 advance.fX = advance.fY = 0;
266 return;
267 }
268
269 if (ttGlyph >= fNumLongHorMetrics) {
270 index = fNumLongHorMetrics - 1;
271 }
272
273 advance.fX = xUnitsToPoints(SWAPW(fHMTXTable->hMetrics[index].advanceWidth));
274 advance.fY = 0;
275 }
276
277 le_bool PortableFontInstance::getGlyphPoint(LEGlyphID glyph, le_int32 pointNumber, LEPoint &point) const
278 {
279 return false;
280 }
281