1 /* This is dvipdfmx, an eXtended version of dvipdfm by Mark A. Wicks.
2
3 Copyright (C) 2002-2014 by Jin-Hwan Cho and Shunsaku Hirata,
4 the dvipdfmx project team.
5
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the 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
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
19 */
20
21 #ifdef HAVE_CONFIG_H
22 #include <config.h>
23 #endif
24
25 #include <stdio.h>
26
27 #include "system.h"
28 #include "error.h"
29 #include "mem.h"
30 #include "mfileio.h"
31
32 #include "sfnt.h"
33 #include "tt_table.h"
34
35 /*
36 tables contains information refered by other tables
37 maxp->numGlyphs, etc --> loca, etc
38 hhea->numOfLongHorMetrics --> hmtx
39 head->indexToLocFormat --> loca
40 head->glyphDataFormat --> glyf
41 */
42
tt_pack_head_table(struct tt_head_table * table)43 char *tt_pack_head_table (struct tt_head_table *table)
44 {
45 int i;
46 char *p, *data;
47
48 if (table == NULL)
49 ERROR("passed NULL pointer\n");
50
51 p = data = NEW(TT_HEAD_TABLE_SIZE, char);
52 p += sfnt_put_ulong(p, table->version);
53 p += sfnt_put_ulong(p, table->fontRevision);
54 p += sfnt_put_ulong(p, table->checkSumAdjustment);
55 p += sfnt_put_ulong(p, table->magicNumber);
56 p += sfnt_put_ushort(p, table->flags);
57 p += sfnt_put_ushort(p, table->unitsPerEm);
58 for (i=0; i<8; i++) {
59 *(p++) = (table->created)[i];
60 }
61 for (i=0; i<8; i++) {
62 *(p++) = (table->modified)[i];
63 }
64 p += sfnt_put_short(p, table->xMin);
65 p += sfnt_put_short(p, table->yMin);
66 p += sfnt_put_short(p, table->xMax);
67 p += sfnt_put_short(p, table->yMax);
68 p += sfnt_put_ushort(p, table->macStyle);
69 p += sfnt_put_ushort(p, table->lowestRecPPEM);
70 p += sfnt_put_short(p, table->fontDirectionHint);
71 p += sfnt_put_short(p, table->indexToLocFormat);
72 p += sfnt_put_short(p, table->glyphDataFormat);
73
74 return data;
75 }
76
tt_read_head_table(sfnt * sfont)77 struct tt_head_table *tt_read_head_table (sfnt *sfont)
78 {
79 int i;
80 struct tt_head_table *table = NEW(1, struct tt_head_table);
81
82 sfnt_locate_table(sfont, "head");
83
84 table->version = sfnt_get_ulong(sfont);
85 table->fontRevision = sfnt_get_ulong(sfont);
86 table->checkSumAdjustment = sfnt_get_ulong(sfont);
87 table->magicNumber = sfnt_get_ulong(sfont);
88 table->flags = sfnt_get_ushort(sfont);
89 table->unitsPerEm = sfnt_get_ushort(sfont);
90 for (i=0; i<8; i++) {
91 (table->created)[i] = sfnt_get_byte (sfont);
92 }
93 for (i=0; i<8; i++) {
94 (table->modified)[i] = sfnt_get_byte (sfont);
95 }
96 table->xMin = sfnt_get_short(sfont);
97 table->yMin = sfnt_get_short(sfont);
98 table->xMax = sfnt_get_short(sfont);
99 table->yMax = sfnt_get_short(sfont);
100 table->macStyle = sfnt_get_short(sfont);
101 table->lowestRecPPEM = sfnt_get_short(sfont);
102 table->fontDirectionHint = sfnt_get_short(sfont);
103 table->indexToLocFormat = sfnt_get_short(sfont);
104 table->glyphDataFormat = sfnt_get_short(sfont);
105
106 return table;
107 }
108
tt_pack_maxp_table(struct tt_maxp_table * table)109 char *tt_pack_maxp_table (struct tt_maxp_table *table)
110 {
111 char *p, *data;
112
113 p = data = NEW(TT_MAXP_TABLE_SIZE, char);
114 p += sfnt_put_ulong(p, table->version);
115 p += sfnt_put_ushort(p, table->numGlyphs);
116 p += sfnt_put_ushort(p, table->maxPoints);
117 p += sfnt_put_ushort(p, table->maxContours);
118 p += sfnt_put_ushort(p, table->maxComponentPoints);
119 p += sfnt_put_ushort(p, table->maxComponentContours);
120 p += sfnt_put_ushort(p, table->maxZones);
121 p += sfnt_put_ushort(p, table->maxTwilightPoints);
122 p += sfnt_put_ushort(p, table->maxStorage);
123 p += sfnt_put_ushort(p, table->maxFunctionDefs);
124 p += sfnt_put_ushort(p, table->maxInstructionDefs);
125 p += sfnt_put_ushort(p, table->maxStackElements);
126 p += sfnt_put_ushort(p, table->maxSizeOfInstructions);
127 p += sfnt_put_ushort(p, table->maxComponentElements);
128 p += sfnt_put_ushort(p, table->maxComponentDepth);
129
130 return data;
131 }
132
tt_read_maxp_table(sfnt * sfont)133 struct tt_maxp_table *tt_read_maxp_table (sfnt *sfont)
134 {
135 struct tt_maxp_table *table = NEW(1, struct tt_maxp_table);
136
137 sfnt_locate_table(sfont, "maxp");
138
139 table->version = sfnt_get_ulong(sfont);
140 table->numGlyphs = sfnt_get_ushort(sfont);
141 table->maxPoints = sfnt_get_ushort(sfont);
142 table->maxContours = sfnt_get_ushort(sfont);
143 table->maxComponentPoints = sfnt_get_ushort(sfont);
144 table->maxComponentContours = sfnt_get_ushort(sfont);
145 table->maxZones = sfnt_get_ushort(sfont);
146 table->maxTwilightPoints = sfnt_get_ushort(sfont);
147 table->maxStorage = sfnt_get_ushort(sfont);
148 table->maxFunctionDefs = sfnt_get_ushort(sfont);
149 table->maxInstructionDefs = sfnt_get_ushort(sfont);
150 table->maxStackElements = sfnt_get_ushort(sfont);
151 table->maxSizeOfInstructions = sfnt_get_ushort(sfont);
152 table->maxComponentElements = sfnt_get_ushort(sfont);
153 table->maxComponentDepth = sfnt_get_ushort(sfont);
154
155 return table;
156 }
157
tt_pack_hhea_table(struct tt_hhea_table * table)158 char *tt_pack_hhea_table (struct tt_hhea_table *table)
159 {
160 int i;
161 char *p, *data;
162
163 p = data = NEW(TT_HHEA_TABLE_SIZE, char);
164 p += sfnt_put_ulong(p, table->version);
165 p += sfnt_put_short(p, table->ascent);
166 p += sfnt_put_short(p, table->descent);
167 p += sfnt_put_short(p, table->lineGap);
168 p += sfnt_put_ushort(p, table->advanceWidthMax);
169 p += sfnt_put_short(p, table->minLeftSideBearing);
170 p += sfnt_put_short(p, table->minRightSideBearing);
171 p += sfnt_put_short(p, table->xMaxExtent);
172 p += sfnt_put_short(p, table->caretSlopeRise);
173 p += sfnt_put_short(p, table->caretSlopeRun);
174 p += sfnt_put_short(p, table->caretOffset);
175 for (i = 0; i < 4; i++) {
176 p += sfnt_put_short(p, table->reserved[i]);
177 }
178 p += sfnt_put_short(p, table->metricDataFormat);
179 p += sfnt_put_ushort(p, table->numOfLongHorMetrics);
180
181 return data;
182 }
183
184 struct tt_hhea_table *
tt_read_hhea_table(sfnt * sfont)185 tt_read_hhea_table (sfnt *sfont)
186 {
187 int i;
188 ULONG len;
189 struct tt_hhea_table *table = NEW(1, struct tt_hhea_table);
190
191 sfnt_locate_table(sfont, "hhea");
192
193 table->version = sfnt_get_ulong(sfont);
194 table->ascent = sfnt_get_short (sfont);
195 table->descent = sfnt_get_short(sfont);
196 table->lineGap = sfnt_get_short(sfont);
197 table->advanceWidthMax = sfnt_get_ushort(sfont);
198 table->minLeftSideBearing = sfnt_get_short(sfont);
199 table->minRightSideBearing = sfnt_get_short(sfont);
200 table->xMaxExtent = sfnt_get_short(sfont);
201 table->caretSlopeRise = sfnt_get_short(sfont);
202 table->caretSlopeRun = sfnt_get_short(sfont);
203 table->caretOffset = sfnt_get_short(sfont);
204 for(i = 0; i < 4; i++) {
205 table->reserved[i] = sfnt_get_short(sfont);
206 }
207 table->metricDataFormat = sfnt_get_short(sfont);
208 if (table->metricDataFormat != 0)
209 ERROR("unknown metricDataFormat");
210 table->numOfLongHorMetrics = sfnt_get_ushort(sfont);
211
212 len = sfnt_find_table_len(sfont, "hmtx");
213 table->numOfExSideBearings = (USHORT)((len - table->numOfLongHorMetrics * 4) / 2);
214
215 return table;
216 }
217
218 /* vhea */
219 #if 0
220 char *
221 tt_pack_vhea_table (struct tt_vhea_table *table)
222 {
223 int i;
224 char *p, *data;
225
226 p = data = NEW(TT_VHEA_TABLE_SIZE, char);
227 p += sfnt_put_ulong(p, table->version);
228 p += sfnt_put_short(p, table->vertTypoAscender);
229 p += sfnt_put_short(p, table->vertTypoDescender);
230 p += sfnt_put_short(p, table->vertTypoLineGap);
231 p += sfnt_put_short(p, table->advanceHeightMax); /* ushort ? */
232 p += sfnt_put_short(p, table->minTopSideBearing);
233 p += sfnt_put_short(p, table->minBottomSideBearing);
234 p += sfnt_put_short(p, table->yMaxExtent);
235 p += sfnt_put_short(p, table->caretSlopeRise);
236 p += sfnt_put_short(p, table->caretSlopeRun);
237 p += sfnt_put_short(p, table->caretOffset);
238 for(i = 0; i < 4; i++) {
239 p += sfnt_put_short(p, table->reserved[i]);
240 }
241 p += sfnt_put_short(p, table->metricDataFormat);
242 p += sfnt_put_ushort(p, table->numOfLongVerMetrics);
243
244 return data;
245 }
246 #endif
247
tt_read_vhea_table(sfnt * sfont)248 struct tt_vhea_table *tt_read_vhea_table (sfnt *sfont)
249 {
250 int i;
251 ULONG len;
252 struct tt_vhea_table *table = NEW(1, struct tt_vhea_table);
253
254 sfnt_locate_table(sfont, "vhea");
255
256 table->version = sfnt_get_ulong(sfont);
257 table->vertTypoAscender = sfnt_get_short (sfont);
258 table->vertTypoDescender = sfnt_get_short(sfont);
259 table->vertTypoLineGap = sfnt_get_short(sfont);
260 table->advanceHeightMax = sfnt_get_short(sfont); /* ushort ? */
261 table->minTopSideBearing = sfnt_get_short(sfont);
262 table->minBottomSideBearing = sfnt_get_short(sfont);
263 table->yMaxExtent = sfnt_get_short(sfont);
264 table->caretSlopeRise = sfnt_get_short(sfont);
265 table->caretSlopeRun = sfnt_get_short(sfont);
266 table->caretOffset = sfnt_get_short(sfont);
267 for(i = 0; i < 4; i++) {
268 (table->reserved)[i] = sfnt_get_short(sfont);
269 }
270 table->metricDataFormat = sfnt_get_short(sfont);
271 table->numOfLongVerMetrics = sfnt_get_ushort(sfont);
272
273 len = sfnt_find_table_len(sfont, "vmtx");
274 table->numOfExSideBearings = (USHORT)((len - table->numOfLongVerMetrics * 4) / 2);
275
276 return table;
277 }
278
279
280 struct tt_VORG_table *
tt_read_VORG_table(sfnt * sfont)281 tt_read_VORG_table (sfnt *sfont)
282 {
283 struct tt_VORG_table *vorg;
284 ULONG offset;
285 USHORT i;
286
287 offset = sfnt_find_table_pos(sfont, "VORG");
288
289 if (offset > 0) {
290 vorg = NEW(1, struct tt_VORG_table);
291
292 sfnt_locate_table(sfont, "VORG");
293 if (sfnt_get_ushort(sfont) != 1 ||
294 sfnt_get_ushort(sfont) != 0)
295 ERROR("Unsupported VORG version.");
296
297 vorg->defaultVertOriginY = sfnt_get_short(sfont);
298 vorg->numVertOriginYMetrics = sfnt_get_ushort(sfont);
299 vorg->vertOriginYMetrics = NEW(vorg->numVertOriginYMetrics,
300 struct tt_vertOriginYMetrics);
301 /*
302 * The vertOriginYMetrics array must be sorted in increasing
303 * glyphIndex order.
304 */
305 for (i = 0;
306 i < vorg->numVertOriginYMetrics; i++) {
307 vorg->vertOriginYMetrics[i].glyphIndex = sfnt_get_ushort(sfont);
308 vorg->vertOriginYMetrics[i].vertOriginY = sfnt_get_short(sfont);
309 }
310 } else {
311 vorg = NULL;
312 }
313
314 return vorg;
315 }
316
317 /*
318 * hmtx and vmtx
319 *
320 * Reading/writing hmtx and vmtx depend on other tables, maxp and hhea/vhea.
321 */
322
323 struct tt_longMetrics *
tt_read_longMetrics(sfnt * sfont,USHORT numGlyphs,USHORT numLongMetrics,USHORT numExSideBearings)324 tt_read_longMetrics (sfnt *sfont, USHORT numGlyphs, USHORT numLongMetrics, USHORT numExSideBearings)
325 {
326 struct tt_longMetrics *m;
327 USHORT gid, last_adv = 0;
328 SHORT last_esb = 0;
329
330 m = NEW(numGlyphs, struct tt_longMetrics);
331 for (gid = 0; gid < numGlyphs; gid++) {
332 if (gid < numLongMetrics)
333 last_adv = sfnt_get_ushort(sfont);
334 if (gid < numLongMetrics + numExSideBearings)
335 last_esb = sfnt_get_short(sfont);
336 m[gid].advance = last_adv;
337 m[gid].sideBearing = last_esb;
338 }
339
340 return m;
341 }
342
343 /* OS/2 table */
344 /* this table may not exist */
345 struct tt_os2__table *
tt_read_os2__table(sfnt * sfont)346 tt_read_os2__table (sfnt *sfont)
347 {
348 struct tt_os2__table *table = NULL;
349 int i;
350
351 table = NEW(1, struct tt_os2__table);
352
353 if (sfnt_find_table_pos(sfont, "OS/2") > 0) {
354 sfnt_locate_table(sfont, "OS/2");
355 table->version = sfnt_get_ushort(sfont);
356 table->xAvgCharWidth = sfnt_get_short(sfont);
357 table->usWeightClass = sfnt_get_ushort(sfont);
358 table->usWidthClass = sfnt_get_ushort(sfont);
359 table->fsType = sfnt_get_short(sfont);
360 table->ySubscriptXSize = sfnt_get_short(sfont);
361 table->ySubscriptYSize = sfnt_get_short(sfont);
362 table->ySubscriptXOffset = sfnt_get_short(sfont);
363 table->ySubscriptYOffset = sfnt_get_short(sfont);
364 table->ySuperscriptXSize = sfnt_get_short(sfont);
365 table->ySuperscriptYSize = sfnt_get_short(sfont);
366 table->ySuperscriptXOffset = sfnt_get_short(sfont);
367 table->ySuperscriptYOffset = sfnt_get_short(sfont);
368 table->yStrikeoutSize = sfnt_get_short(sfont);
369 table->yStrikeoutPosition = sfnt_get_short(sfont);
370 table->sFamilyClass = sfnt_get_short(sfont);
371 for (i = 0; i < 10; i++) {
372 table->panose[i] = sfnt_get_byte(sfont);
373 }
374 table->ulUnicodeRange1 = sfnt_get_ulong(sfont);
375 table->ulUnicodeRange2 = sfnt_get_ulong(sfont);
376 table->ulUnicodeRange3 = sfnt_get_ulong(sfont);
377 table->ulUnicodeRange4 = sfnt_get_ulong(sfont);
378 for (i = 0; i < 4; i++) {
379 table->achVendID[i] = sfnt_get_char(sfont);
380 }
381 table->fsSelection = sfnt_get_ushort(sfont);
382 table->usFirstCharIndex = sfnt_get_ushort(sfont);
383 table->usLastCharIndex = sfnt_get_ushort(sfont);
384 if (sfnt_find_table_len(sfont, "OS/2") >= 78) {
385 /* these fields are not present in the original Apple spec (68-byte table),
386 but Microsoft's version of "format 0" does include them... grr! */
387 table->sTypoAscender = sfnt_get_short(sfont);
388 table->sTypoDescender = sfnt_get_short(sfont);
389 table->sTypoLineGap = sfnt_get_short(sfont);
390 table->usWinAscent = sfnt_get_ushort(sfont);
391 table->usWinDescent = sfnt_get_ushort(sfont);
392 if (table->version > 0) {
393 /* format 1 adds the following 2 fields */
394 table->ulCodePageRange1 = sfnt_get_ulong(sfont);
395 table->ulCodePageRange2 = sfnt_get_ulong(sfont);
396 if (table->version > 1) {
397 /* and formats 2 and 3 (current) include 5 more.... these share the
398 same fields, only the precise definition of some was changed */
399 table->sxHeight = sfnt_get_short(sfont);
400 table->sCapHeight = sfnt_get_short(sfont);
401 table->usDefaultChar = sfnt_get_ushort(sfont);
402 table->usBreakChar = sfnt_get_ushort(sfont);
403 table->usMaxContext = sfnt_get_ushort(sfont);
404 }
405 }
406 }
407 } else {
408
409 /* used in add_CIDVMetrics() of cidtype0.c */
410 table->sTypoAscender = 880;
411 table->sTypoDescender = -120;
412 /* used in tt_get_fontdesc() of tt_aux.c */
413 table->usWeightClass = 400U; /* Normal(Regular) */
414 table->xAvgCharWidth = 0; /* ignore */
415 table->version = 0; /* TrueType rev 1.5 */
416 table->fsType = 0; /* Installable Embedding */
417 table->fsSelection = 0U; /* All undefined */
418 table->sFamilyClass = 0; /* No Classification */
419 for (i = 0; i < 10; i++) {
420 table->panose[i] = 0; /* All Any */
421 }
422 }
423
424 return table;
425 }
426
427 USHORT
tt_get_name(sfnt * sfont,char * dest,USHORT destlen,USHORT plat_id,USHORT enco_id,USHORT lang_id,USHORT name_id)428 tt_get_name (sfnt *sfont, char *dest, USHORT destlen,
429 USHORT plat_id, USHORT enco_id,
430 USHORT lang_id, USHORT name_id)
431 {
432 USHORT length = 0;
433 USHORT num_names, string_offset;
434 ULONG name_offset;
435 int i;
436
437 name_offset = sfnt_locate_table (sfont, "name");
438
439 if (sfnt_get_ushort(sfont))
440 ERROR ("Expecting zero");
441
442 num_names = sfnt_get_ushort(sfont);
443 string_offset = sfnt_get_ushort(sfont);
444 for (i=0;i<num_names;i++) {
445 USHORT p_id, e_id, n_id, l_id;
446 USHORT offset;
447
448 p_id = sfnt_get_ushort(sfont);
449 e_id = sfnt_get_ushort(sfont);
450 l_id = sfnt_get_ushort(sfont);
451 n_id = sfnt_get_ushort(sfont);
452 length = sfnt_get_ushort(sfont);
453 offset = sfnt_get_ushort(sfont);
454 /* language ID value 0xffffu for `accept any language ID' */
455 if ((p_id == plat_id) && (e_id == enco_id) &&
456 (lang_id == 0xffffu || l_id == lang_id) && (n_id == name_id)) {
457 if (length > destlen - 1) {
458 WARN ("Name string too long (%u), truncating to %u", length, destlen);
459 length = destlen - 1;
460 }
461 sfnt_seek_set (sfont, name_offset+string_offset+offset);
462 sfnt_read((unsigned char*)dest, length, sfont);
463 dest[length] = '\0';
464 break;
465 }
466 }
467 if (i == num_names) {
468 length = 0;
469 }
470
471 return length;
472 }
473
474 USHORT
tt_get_ps_fontname(sfnt * sfont,char * dest,USHORT destlen)475 tt_get_ps_fontname (sfnt *sfont, char *dest, USHORT destlen)
476 {
477 USHORT namelen = 0;
478
479 /* First try Mac-Roman PS name and then Win-Unicode PS name */
480 if ((namelen = tt_get_name(sfont, dest, destlen, 1, 0, 0, 6)) != 0 ||
481 (namelen = tt_get_name(sfont, dest, destlen, 3, 1, 0x409u, 6)) != 0 ||
482 (namelen = tt_get_name(sfont, dest, destlen, 3, 5, 0x412u, 6)) != 0)
483 return namelen;
484
485 WARN ("No valid PostScript name available");
486 /*
487 Workaround for some bad TTfonts:
488 Language ID value 0xffffu for `accept any language ID'
489 */
490 if ((namelen = tt_get_name(sfont, dest, destlen, 1, 0, 0xffffu, 6)) == 0) {
491 /*
492 Finally falling back to Mac Roman name field.
493 Warning: Some bad Japanese TTfonts using SJIS encoded string in the
494 Mac Roman name field.
495 */
496 namelen = tt_get_name(sfont, dest, destlen, 1, 0, 0, 1);
497 }
498
499 return namelen;
500 }
501