1 /*
2  * << Haru Free PDF Library >> -- hpdf_fontdef_tt.c
3  *
4  * URL: http://libharu.org
5  *
6  * Copyright (c) 1999-2006 Takeshi Kanno <takeshi_kanno@est.hi-ho.ne.jp>
7  * Copyright (c) 2007-2009 Antony Dovgal <tony@daylessday.org>
8  *
9  * Permission to use, copy, modify, distribute and sell this software
10  * and its documentation for any purpose is hereby granted without fee,
11  * provided that the above copyright notice appear in all copies and
12  * that both that copyright notice and this permission notice appear
13  * in supporting documentation.
14  * It is provided "as is" without express or implied warranty.
15  *
16  * 2006.08.24 fixed for composite glyph description.
17  */
18 
19 #include "hpdf_conf.h"
20 #include "hpdf_utils.h"
21 #include "hpdf_fontdef.h"
22 
23 
24 #define HPDF_TTF_MAX_MEM_SIZ    10000
25 
26 #define HPDF_REQUIRED_TAGS_COUNT  13
27 
28 static const char * const REQUIRED_TAGS[HPDF_REQUIRED_TAGS_COUNT] = {
29     "OS/2",
30     "cmap",
31     "cvt ",
32     "fpgm",
33     "glyf",
34     "head",
35     "hhea",
36     "hmtx",
37     "loca",
38     "maxp",
39     "name",
40     "post",
41     "prep"
42 };
43 
44 
45 static void
46 FreeFunc (HPDF_FontDef  fontdef);
47 
48 
49 static HPDF_STATUS
50 LoadFontData (HPDF_FontDef  fontdef,
51               HPDF_Stream   stream,
52               HPDF_BOOL     embedding,
53               HPDF_UINT     offset);
54 
55 
56 static HPDF_STATUS
57 LoadFontData2 (HPDF_FontDef  fontdef,
58                HPDF_Stream   stream,
59                HPDF_UINT     index,
60                HPDF_BOOL     embedding);
61 
62 
63 static void
64 InitAttr (HPDF_FontDef  fontdef);
65 
66 
67 static HPDF_STATUS
68 GetUINT32 (HPDF_Stream   stream,
69            HPDF_UINT32  *value);
70 
71 
72 static HPDF_STATUS
73 GetUINT16 (HPDF_Stream   stream,
74            HPDF_UINT16  *value);
75 
76 
77 static HPDF_STATUS
78 GetINT16 (HPDF_Stream   stream,
79           HPDF_INT16    *value);
80 
81 
82 static HPDF_STATUS
83 WriteUINT32 (HPDF_Stream   stream,
84              HPDF_UINT32   value);
85 
86 
87 static HPDF_STATUS
88 WriteUINT16 (HPDF_Stream   stream,
89              HPDF_UINT16   value);
90 
91 
92 static HPDF_STATUS
93 WriteINT16 (HPDF_Stream   stream,
94             HPDF_INT16    value);
95 
96 
97 static void
98 UINT32Swap (HPDF_UINT32  *value);
99 
100 
101 static void
102 UINT16Swap (HPDF_UINT16  *value);
103 
104 
105 static void
106 INT16Swap (HPDF_INT16  *value);
107 
108 
109 static HPDF_STATUS
110 LoadTTFTable (HPDF_FontDef  fontdef);
111 
112 
113 static HPDF_STATUS
114 ParseHead (HPDF_FontDef  fontdef);
115 
116 
117 static HPDF_STATUS
118 ParseMaxp (HPDF_FontDef  fontdef);
119 
120 
121 static HPDF_STATUS
122 ParseHhea (HPDF_FontDef  fontdef);
123 
124 
125 static HPDF_STATUS
126 ParseCMap (HPDF_FontDef  fontdef);
127 
128 
129 static HPDF_STATUS
130 ParseCMAP_format0  (HPDF_FontDef  fontdef,
131                     HPDF_UINT32   offset);
132 
133 
134 static HPDF_STATUS
135 ParseCMAP_format4  (HPDF_FontDef  fontdef,
136                     HPDF_UINT32   offset);
137 
138 
139 static HPDF_STATUS
140 ParseHmtx  (HPDF_FontDef  fontdef);
141 
142 
143 static HPDF_STATUS
144 ParseLoca  (HPDF_FontDef  fontdef);
145 
146 
147 static HPDF_STATUS
148 LoadUnicodeName  (HPDF_Stream   stream,
149                   HPDF_UINT     offset,
150                   HPDF_UINT     len,
151                   char          *buf);
152 
153 static HPDF_STATUS
154 ParseName  (HPDF_FontDef  fontdef);
155 
156 
157 static HPDF_STATUS
158 ParseOS2  (HPDF_FontDef  fontdef);
159 
160 
161 static HPDF_TTFTable*
162 FindTable (HPDF_FontDef   fontdef,
163            const char    *tag);
164 
165 
166 static void
167 CleanFunc (HPDF_FontDef   fontdef);
168 
169 
170 static HPDF_STATUS
171 CheckCompositGryph  (HPDF_FontDef   fontdef,
172                      HPDF_UINT16    gid);
173 
174 
175 /*---------------------------------------------------------------------------*/
176 /*---------------------------------------------------------------------------*/
177 
178 static void
FreeFunc(HPDF_FontDef fontdef)179 FreeFunc (HPDF_FontDef  fontdef)
180 {
181     HPDF_TTFontDefAttr attr = (HPDF_TTFontDefAttr)fontdef->attr;
182 
183     HPDF_PTRACE ((" HPDF_TTFontDef_FreeFunc\n"));
184 
185     if (attr) {
186         InitAttr (fontdef);
187 
188         HPDF_FreeMem (fontdef->mmgr, attr);
189     }
190 }
191 
192 
193 static void
CleanFunc(HPDF_FontDef fontdef)194 CleanFunc (HPDF_FontDef   fontdef)
195 {
196     HPDF_TTFontDefAttr attr = (HPDF_TTFontDefAttr)fontdef->attr;
197     HPDF_MemSet (attr->glyph_tbl.flgs, 0,
198             sizeof (HPDF_BYTE) * attr->num_glyphs);
199     attr->glyph_tbl.flgs[0] = 1;
200 }
201 
202 
203 static void
InitAttr(HPDF_FontDef fontdef)204 InitAttr (HPDF_FontDef  fontdef)
205 {
206     HPDF_TTFontDefAttr attr = (HPDF_TTFontDefAttr)fontdef->attr;
207 
208     if (attr) {
209         if (attr->char_set)
210             HPDF_FreeMem (fontdef->mmgr, attr->char_set);
211 
212         if (attr->h_metric)
213             HPDF_FreeMem (fontdef->mmgr, attr->h_metric);
214 
215         if (attr->name_tbl.name_records)
216             HPDF_FreeMem (fontdef->mmgr, attr->name_tbl.name_records);
217 
218         if (attr->cmap.end_count)
219             HPDF_FreeMem (fontdef->mmgr, attr->cmap.end_count);
220 
221         if (attr->cmap.start_count)
222             HPDF_FreeMem (fontdef->mmgr, attr->cmap.start_count);
223 
224         if (attr->cmap.id_delta)
225             HPDF_FreeMem (fontdef->mmgr, attr->cmap.id_delta);
226 
227         if (attr->cmap.id_range_offset)
228             HPDF_FreeMem (fontdef->mmgr, attr->cmap.id_range_offset);
229 
230         if (attr->cmap.glyph_id_array)
231             HPDF_FreeMem (fontdef->mmgr, attr->cmap.glyph_id_array);
232 
233         if (attr->offset_tbl.table)
234             HPDF_FreeMem (fontdef->mmgr, attr->offset_tbl.table);
235 
236         if (attr->glyph_tbl.flgs)
237             HPDF_FreeMem (fontdef->mmgr, attr->glyph_tbl.flgs);
238 
239         if (attr->glyph_tbl.offsets)
240             HPDF_FreeMem (fontdef->mmgr, attr->glyph_tbl.offsets);
241 
242         if (attr->stream)
243             HPDF_Stream_Free (attr->stream);
244     }
245 }
246 
247 
248 HPDF_FontDef
HPDF_TTFontDef_New(HPDF_MMgr mmgr)249 HPDF_TTFontDef_New (HPDF_MMgr   mmgr)
250 {
251     HPDF_FontDef fontdef;
252     HPDF_TTFontDefAttr fontdef_attr;
253 
254     HPDF_PTRACE ((" HPDF_TTFontDef_New\n"));
255 
256     if (!mmgr)
257         return NULL;
258 
259     fontdef = HPDF_GetMem (mmgr, sizeof(HPDF_FontDef_Rec));
260     if (!fontdef)
261         return NULL;
262 
263     HPDF_MemSet (fontdef, 0, sizeof(HPDF_FontDef_Rec));
264     fontdef->sig_bytes = HPDF_FONTDEF_SIG_BYTES;
265     fontdef->mmgr = mmgr;
266     fontdef->error = mmgr->error;
267     fontdef->type = HPDF_FONTDEF_TYPE_TRUETYPE;
268     fontdef->clean_fn = CleanFunc;
269     fontdef->free_fn = FreeFunc;
270 
271     fontdef_attr = HPDF_GetMem (mmgr, sizeof(HPDF_TTFontDefAttr_Rec));
272     if (!fontdef_attr) {
273         HPDF_FreeMem (fontdef->mmgr, fontdef);
274         return NULL;
275     }
276 
277     fontdef->attr = fontdef_attr;
278     HPDF_MemSet ((HPDF_BYTE *)fontdef_attr, 0, sizeof(HPDF_TTFontDefAttr_Rec));
279     fontdef->flags = HPDF_FONT_STD_CHARSET;
280 
281     return fontdef;
282 }
283 
284 
285 HPDF_FontDef
HPDF_TTFontDef_Load(HPDF_MMgr mmgr,HPDF_Stream stream,HPDF_BOOL embedding)286 HPDF_TTFontDef_Load  (HPDF_MMgr     mmgr,
287                       HPDF_Stream   stream,
288                       HPDF_BOOL     embedding)
289 {
290     HPDF_STATUS ret;
291     HPDF_FontDef fontdef;
292 
293     HPDF_PTRACE ((" HPDF_TTFontDef_Load\n"));
294 
295     fontdef = HPDF_TTFontDef_New (mmgr);
296 
297     if (!fontdef) {
298         HPDF_Stream_Free (stream);
299         return NULL;
300     }
301 
302     ret = LoadFontData (fontdef, stream, embedding, 0);
303     if (ret != HPDF_OK) {
304         HPDF_FontDef_Free (fontdef);
305         return NULL;
306     }
307 
308     return fontdef;
309 }
310 
311 
312 HPDF_FontDef
HPDF_TTFontDef_Load2(HPDF_MMgr mmgr,HPDF_Stream stream,HPDF_UINT index,HPDF_BOOL embedding)313 HPDF_TTFontDef_Load2  (HPDF_MMgr     mmgr,
314                        HPDF_Stream   stream,
315                        HPDF_UINT     index,
316                        HPDF_BOOL     embedding)
317 {
318     HPDF_STATUS ret;
319     HPDF_FontDef fontdef;
320 
321     HPDF_PTRACE ((" HPDF_TTFontDef_Load\n"));
322 
323     fontdef = HPDF_TTFontDef_New (mmgr);
324 
325     if (!fontdef) {
326         HPDF_Stream_Free (stream);
327         return NULL;
328     }
329 
330     ret = LoadFontData2 (fontdef, stream, index, embedding);
331     if (ret != HPDF_OK) {
332         HPDF_FontDef_Free (fontdef);
333         return NULL;
334     }
335 
336     return fontdef;
337 }
338 
339 
340 #ifdef HPDF_TTF_DEBUG
341 static void
DumpTable(HPDF_FontDef fontdef)342 DumpTable (HPDF_FontDef   fontdef)
343 {
344     HPDF_TTFontDefAttr attr = (HPDF_TTFontDefAttr)fontdef->attr;
345     HPDF_Stream  stream;
346     HPDF_UINT i;
347 
348     for (i = 0; i < HPDF_REQUIRED_TAGS_COUNT; i++) {
349         char fname[9];
350         HPDF_TTFTable *tbl = FindTable (fontdef, REQUIRED_TAGS[i]);
351 
352         if (!tbl) {
353             HPDF_PTRACE ((" ERR: cannot seek %s\n", fname));
354             return;
355         }
356 
357         HPDF_MemSet (fname, 0, 9);
358         HPDF_MemCpy (fname, REQUIRED_TAGS[i], 4);
359         HPDF_MemCpy (fname + 4, ".dat", 4);
360         HPDF_PTRACE ((" %s open\n", fname));
361 
362         if (HPDF_MemCmp(fname, "OS/2", 4) == 0)
363             fname[2] = '_';
364 
365         stream = HPDF_FileWriter_New (fontdef->mmgr, fname);
366 
367         if (!stream) {
368             HPDF_PTRACE ((" ERR: cannot open %s\n", fname));
369         } else {
370             HPDF_STATUS ret;
371             HPDF_UINT tbl_len = tbl->length;
372 
373             ret = HPDF_Stream_Seek (attr->stream, tbl->offset, HPDF_SEEK_SET);
374             if (ret != HPDF_OK) {
375                 HPDF_PTRACE ((" ERR: cannot seek \n"));
376                 HPDF_Stream_Free (stream);
377                 return;
378             }
379 
380             for (;;) {
381                 HPDF_BYTE buf[HPDF_STREAM_BUF_SIZ];
382                 HPDF_UINT len = HPDF_STREAM_BUF_SIZ;
383 
384                 if (len > tbl_len)
385                     len = tbl_len;
386 
387                 HPDF_Stream_Read (attr->stream, buf, &len);
388                 if (len <= 0)
389                     break;
390 
391                 ret = HPDF_Stream_Write (stream, buf, len);
392                 if (ret != HPDF_OK) {
393                     HPDF_PTRACE ((" ERR: cannot write\n"));
394                     break;
395                 }
396 
397                 tbl_len -= len;
398                 if (tbl_len == 0)
399                     break;
400             }
401 
402             HPDF_Stream_Free (stream);
403         }
404     }
405 }
406 #endif
407 
408 static HPDF_STATUS
LoadFontData(HPDF_FontDef fontdef,HPDF_Stream stream,HPDF_BOOL embedding,HPDF_UINT offset)409 LoadFontData (HPDF_FontDef  fontdef,
410               HPDF_Stream   stream,
411               HPDF_BOOL     embedding,
412               HPDF_UINT     offset)
413 {
414     HPDF_TTFontDefAttr attr = (HPDF_TTFontDefAttr)fontdef->attr;
415     HPDF_STATUS ret;
416     HPDF_TTFTable *tbl;
417 
418     HPDF_PTRACE ((" HPDF_TTFontDef_LoadFontData\n"));
419 
420     attr->stream = stream;
421     attr->embedding = embedding;
422 
423     if ((ret = HPDF_Stream_Seek (stream, offset, HPDF_SEEK_SET)) != HPDF_OK)
424         return ret;
425 
426     if ((ret = LoadTTFTable (fontdef)) != HPDF_OK)
427         return ret;
428 
429 #ifdef HPDF_DUMP_FONTDATA
430     DumpTable (fontdef);
431 #endif /* HPDF_DUMP_FONTDATA */
432 
433     if ((ret = ParseHead (fontdef)) != HPDF_OK)
434         return ret;
435 
436     if ((ret = ParseMaxp (fontdef)) != HPDF_OK)
437         return ret;
438 
439     if ((ret = ParseHhea (fontdef)) != HPDF_OK)
440         return ret;
441 
442     if ((ret = ParseCMap (fontdef)) != HPDF_OK)
443         return ret;
444 
445     if ((ret = ParseHmtx (fontdef)) != HPDF_OK)
446         return ret;
447 
448     if ((ret = ParseLoca (fontdef)) != HPDF_OK)
449         return ret;
450 
451     if ((ret = ParseName (fontdef)) != HPDF_OK)
452         return ret;
453 
454     if ((ret = ParseOS2 (fontdef)) != HPDF_OK)
455         return ret;
456 
457     tbl = FindTable (fontdef, "glyf");
458     if (!tbl)
459         return HPDF_SetError (fontdef->error, HPDF_TTF_MISSING_TABLE, 4);
460 
461     attr->glyph_tbl.base_offset = tbl->offset;
462     fontdef->cap_height =
463                 (HPDF_UINT16)HPDF_TTFontDef_GetCharBBox (fontdef, (HPDF_UINT16)'H').top;
464     fontdef->x_height =
465                 (HPDF_UINT16)HPDF_TTFontDef_GetCharBBox (fontdef, (HPDF_UINT16)'x').top;
466     fontdef->missing_width = (HPDF_INT16)((HPDF_UINT32)attr->h_metric[0].advance_width * 1000 /
467                 attr->header.units_per_em);
468 
469     HPDF_PTRACE ((" fontdef->cap_height=%d\n", fontdef->cap_height));
470     HPDF_PTRACE ((" fontdef->x_height=%d\n", fontdef->x_height));
471     HPDF_PTRACE ((" fontdef->missing_width=%d\n", fontdef->missing_width));
472 
473     if (!embedding) {
474         HPDF_Stream_Free (attr->stream);
475         attr->stream = NULL;
476     }
477 
478     return HPDF_OK;
479 }
480 
481 static HPDF_STATUS
LoadFontData2(HPDF_FontDef fontdef,HPDF_Stream stream,HPDF_UINT index,HPDF_BOOL embedding)482 LoadFontData2 (HPDF_FontDef  fontdef,
483                HPDF_Stream   stream,
484                HPDF_UINT     index,
485                HPDF_BOOL     embedding)
486 {
487     HPDF_TTFontDefAttr attr = (HPDF_TTFontDefAttr)fontdef->attr;
488     HPDF_STATUS ret;
489     HPDF_BYTE tag[4];
490     HPDF_UINT32 num_fonts;
491     HPDF_UINT32 offset;
492     HPDF_UINT size;
493 
494     HPDF_PTRACE ((" HPDF_TTFontDef_LoadFontData2\n"));
495 
496     attr->stream = stream;
497     attr->embedding = embedding;
498 
499     ret = HPDF_Stream_Seek (stream, 0, HPDF_SEEK_SET);
500     if (ret != HPDF_OK)
501         return ret;
502 
503     size = 4;
504     if ((ret = HPDF_Stream_Read (stream, tag, &size)) != HPDF_OK)
505         return ret;
506 
507     if (HPDF_MemCmp (tag, (HPDF_BYTE *)"ttcf", 4) != 0)
508         return HPDF_SetError (fontdef->error, HPDF_INVALID_TTC_FILE, 0);
509 
510     if ((ret = HPDF_Stream_Seek (stream, 8, HPDF_SEEK_SET)) != HPDF_OK)
511         return ret;
512 
513     if ((ret = GetUINT32 (stream, &num_fonts)) != HPDF_OK)
514         return ret;
515 
516     HPDF_PTRACE((" HPDF_TTFontDef_LoadFontData2 num_fonts=%u\n",
517                 (HPDF_UINT)num_fonts));
518 
519     if (index >= num_fonts)
520         return HPDF_SetError (fontdef->error, HPDF_INVALID_TTC_INDEX, 0);
521 
522     /* read offset table for target font and set stream positioning to offset
523      * value.
524      */
525     if ((ret = HPDF_Stream_Seek (stream, 12 + index * 4, HPDF_SEEK_SET)) !=
526                 HPDF_OK)
527         return ret;
528 
529     if ((ret = GetUINT32 (stream, &offset)) != HPDF_OK)
530         return ret;
531 
532     return LoadFontData (fontdef, stream, embedding, offset);
533 }
534 
535 HPDF_Box
HPDF_TTFontDef_GetCharBBox(HPDF_FontDef fontdef,HPDF_UINT16 unicode)536 HPDF_TTFontDef_GetCharBBox  (HPDF_FontDef   fontdef,
537                              HPDF_UINT16    unicode)
538 {
539     HPDF_TTFontDefAttr attr = (HPDF_TTFontDefAttr)fontdef->attr;
540     HPDF_UINT16 gid = HPDF_TTFontDef_GetGlyphid(fontdef, unicode);
541     HPDF_STATUS ret;
542     HPDF_Box bbox = HPDF_ToBox(0, 0, 0, 0);
543     HPDF_INT16 i;
544     HPDF_INT m;
545 
546     if (gid == 0) {
547         HPDF_PTRACE ((" GetCharHeight cannot get gid char=0x%04x\n", unicode));
548         return bbox;
549     }
550 
551     if (attr->header.index_to_loc_format == 0)
552         m = 2;
553     else
554         m = 1;
555 
556     ret = HPDF_Stream_Seek (attr->stream, attr->glyph_tbl.base_offset +
557                      attr->glyph_tbl.offsets[gid] * m + 2, HPDF_SEEK_SET);
558 
559     if (ret != HPDF_OK)
560         return bbox;
561 
562     ret += GetINT16 (attr->stream, &i);
563     bbox.left = (HPDF_REAL)((HPDF_INT32)i * 1000 / attr->header.units_per_em);
564 
565     ret += GetINT16 (attr->stream, &i);
566     bbox.bottom = (HPDF_REAL)((HPDF_INT32)i * 1000 / attr->header.units_per_em);
567 
568     ret += GetINT16 (attr->stream, &i);
569     bbox.right = (HPDF_REAL)((HPDF_INT32)i * 1000 / attr->header.units_per_em);
570 
571     ret += GetINT16 (attr->stream, &i);
572     bbox.top = (HPDF_REAL)((HPDF_INT32)i * 1000 / attr->header.units_per_em);
573 
574     if (ret != HPDF_OK)
575         return HPDF_ToBox(0, 0, 0, 0);
576 
577     HPDF_PTRACE((" PdfTTFontDef_GetCharBBox char=0x%04X, "
578             "box=[%f,%f,%f,%f]\n", unicode, bbox.left, bbox.bottom, bbox.right,
579             bbox.top));
580 
581     return bbox;
582 }
583 
584 
585 static HPDF_STATUS
GetUINT32(HPDF_Stream stream,HPDF_UINT32 * value)586 GetUINT32 (HPDF_Stream         stream,
587            HPDF_UINT32         *value)
588 {
589     HPDF_STATUS ret;
590     HPDF_UINT size = sizeof (HPDF_UINT32);
591 
592     ret = HPDF_Stream_Read (stream, (HPDF_BYTE *)value, &size);
593     if (ret != HPDF_OK) {
594         *value = 0;
595         return ret;
596     }
597 
598     UINT32Swap (value);
599 
600     return HPDF_OK;
601 }
602 
603 
604 static HPDF_STATUS
GetUINT16(HPDF_Stream stream,HPDF_UINT16 * value)605 GetUINT16 (HPDF_Stream         stream,
606            HPDF_UINT16         *value)
607 {
608     HPDF_STATUS ret;
609     HPDF_UINT size = sizeof (HPDF_UINT16);
610 
611     ret = HPDF_Stream_Read (stream, (HPDF_BYTE *)value, &size);
612     if (ret != HPDF_OK) {
613         *value = 0;
614         return ret;
615     }
616 
617     UINT16Swap (value);
618 
619     return HPDF_OK;
620 }
621 
622 
623 static HPDF_STATUS
GetINT16(HPDF_Stream stream,HPDF_INT16 * value)624 GetINT16 (HPDF_Stream    stream,
625           HPDF_INT16    *value)
626 {
627     HPDF_STATUS ret;
628     HPDF_UINT size = sizeof (HPDF_INT16);
629 
630     ret = HPDF_Stream_Read (stream, (HPDF_BYTE *)value, &size);
631     if (ret != HPDF_OK) {
632         *value = 0;
633         return ret;
634     }
635 
636     INT16Swap (value);
637 
638     return HPDF_OK;
639 }
640 
641 static HPDF_STATUS
WriteUINT32(HPDF_Stream stream,HPDF_UINT32 value)642 WriteUINT32 (HPDF_Stream   stream,
643              HPDF_UINT32   value)
644 {
645     HPDF_STATUS ret;
646     HPDF_UINT32 tmp = value;
647 
648     UINT32Swap (&tmp);
649 
650     ret = HPDF_Stream_Write (stream, (HPDF_BYTE *)&tmp, sizeof(tmp));
651     if (ret != HPDF_OK)
652         return ret;
653 
654     return HPDF_OK;
655 }
656 
657 
658 static HPDF_STATUS
WriteUINT16(HPDF_Stream stream,HPDF_UINT16 value)659 WriteUINT16 (HPDF_Stream   stream,
660              HPDF_UINT16   value)
661 {
662     HPDF_STATUS ret;
663     HPDF_UINT16 tmp = value;
664 
665     UINT16Swap (&tmp);
666 
667     ret = HPDF_Stream_Write (stream, (HPDF_BYTE *)&tmp, sizeof(tmp));
668     if (ret != HPDF_OK)
669         return ret;
670 
671     return HPDF_OK;
672 }
673 
674 
675 static HPDF_STATUS
WriteINT16(HPDF_Stream stream,HPDF_INT16 value)676 WriteINT16 (HPDF_Stream   stream,
677             HPDF_INT16    value)
678 {
679     HPDF_STATUS ret;
680     HPDF_INT16 tmp = value;
681 
682     INT16Swap (&tmp);
683 
684     ret = HPDF_Stream_Write (stream, (HPDF_BYTE *)&tmp, sizeof(tmp));
685     if (ret != HPDF_OK)
686         return ret;
687 
688     return HPDF_OK;
689 }
690 
691 
692 HPDF_STATUS
LoadTTFTable(HPDF_FontDef fontdef)693 LoadTTFTable (HPDF_FontDef  fontdef)
694 {
695     HPDF_TTFontDefAttr attr = (HPDF_TTFontDefAttr)fontdef->attr;
696     HPDF_STATUS ret = HPDF_OK;
697     HPDF_INT i;
698     HPDF_TTFTable *tbl;
699 
700     HPDF_PTRACE ((" HPDF_TTFontDef_LoadTTFTable\n"));
701 
702     ret += GetUINT32 (attr->stream, &attr->offset_tbl.sfnt_version);
703     ret += GetUINT16 (attr->stream, &attr->offset_tbl.num_tables);
704     ret += GetUINT16 (attr->stream, &attr->offset_tbl.search_range);
705     ret += GetUINT16 (attr->stream, &attr->offset_tbl.entry_selector);
706     ret += GetUINT16 (attr->stream, &attr->offset_tbl.range_shift);
707 
708     if (ret != HPDF_OK)
709         return HPDF_Error_GetCode (fontdef->error);
710 
711     if (attr->offset_tbl.num_tables * sizeof(HPDF_TTFTable) >
712             HPDF_TTF_MAX_MEM_SIZ)
713         return HPDF_SetError (fontdef->error, HPDF_TTF_INVALID_FOMAT, 0);
714 
715     attr->offset_tbl.table = HPDF_GetMem (fontdef->mmgr,
716                         sizeof(HPDF_TTFTable) * attr->offset_tbl.num_tables);
717     if (!attr->offset_tbl.table)
718         return HPDF_Error_GetCode (fontdef->error);
719 
720     tbl = attr->offset_tbl.table;
721     for (i = 0; i < attr->offset_tbl.num_tables; i++) {
722         HPDF_UINT siz = 4;
723 
724         ret += HPDF_Stream_Read (attr->stream, (HPDF_BYTE *)tbl->tag, &siz);
725         ret += GetUINT32 (attr->stream, &tbl->check_sum);
726         ret += GetUINT32 (attr->stream, &tbl->offset);
727         ret += GetUINT32 (attr->stream, &tbl->length);
728 
729         HPDF_PTRACE((" [%d] tag=[%c%c%c%c] check_sum=%u offset=%u length=%u\n",
730                     i, tbl->tag[0], tbl->tag[1], tbl->tag[2], tbl->tag[3],
731                     (HPDF_UINT)tbl->check_sum, (HPDF_UINT)tbl->offset,
732                     (HPDF_UINT)tbl->length));
733 
734         if (ret != HPDF_OK)
735             return HPDF_Error_GetCode (fontdef->error);;
736 
737         tbl++;
738     }
739 
740     return HPDF_OK;
741 }
742 
743 
744 static HPDF_STATUS
ParseHead(HPDF_FontDef fontdef)745 ParseHead (HPDF_FontDef  fontdef)
746 {
747     HPDF_TTFontDefAttr attr = (HPDF_TTFontDefAttr)fontdef->attr;
748     HPDF_TTFTable *tbl = FindTable (fontdef, "head");
749     HPDF_STATUS ret;
750     HPDF_UINT siz;
751 
752     HPDF_PTRACE ((" HPDF_TTFontDef_ParseHead\n"));
753 
754     if (!tbl)
755         return HPDF_SetError (fontdef->error, HPDF_TTF_MISSING_TABLE, 5);
756 
757     ret = HPDF_Stream_Seek (attr->stream, tbl->offset, HPDF_SEEK_SET);
758     if (ret != HPDF_OK)
759         return ret;
760 
761     siz = 4;
762     ret += HPDF_Stream_Read (attr->stream,
763             (HPDF_BYTE *)&attr->header.version_number, &siz);
764     ret += GetUINT32 (attr->stream, &attr->header.font_revision);
765     ret += GetUINT32 (attr->stream, &attr->header.check_sum_adjustment);
766     ret += GetUINT32 (attr->stream, &attr->header.magic_number);
767     ret += GetUINT16 (attr->stream, &attr->header.flags);
768     ret += GetUINT16 (attr->stream, &attr->header.units_per_em);
769 
770     siz = 8;
771     ret += HPDF_Stream_Read (attr->stream, attr->header.created, &siz);
772     siz = 8;
773     ret += HPDF_Stream_Read (attr->stream, attr->header.modified, &siz);
774 
775     ret += GetINT16 (attr->stream, &attr->header.x_min);
776     ret += GetINT16 (attr->stream, &attr->header.y_min);
777     ret += GetINT16 (attr->stream, &attr->header.x_max);
778     ret += GetINT16 (attr->stream, &attr->header.y_max);
779     ret += GetUINT16 (attr->stream, &attr->header.mac_style);
780     ret += GetUINT16 (attr->stream, &attr->header.lowest_rec_ppem);
781     ret += GetINT16 (attr->stream, &attr->header.font_direction_hint);
782     ret += GetINT16 (attr->stream, &attr->header.index_to_loc_format);
783     ret += GetINT16 (attr->stream, &attr->header.glyph_data_format);
784 
785     if (ret != HPDF_OK)
786         return HPDF_Error_GetCode (fontdef->error);
787 
788     fontdef->font_bbox. left = (HPDF_REAL)((HPDF_INT32)attr->header.x_min * 1000 /
789                 attr->header.units_per_em);
790     fontdef->font_bbox. bottom = (HPDF_REAL)((HPDF_INT32)attr->header.y_min * 1000 /
791                 attr->header.units_per_em);
792     fontdef->font_bbox. right = (HPDF_REAL)((HPDF_INT32)attr->header.x_max * 1000 /
793                 attr->header.units_per_em);
794     fontdef->font_bbox. top = (HPDF_REAL)((HPDF_INT32)attr->header.y_max * 1000 /
795                 attr->header.units_per_em);
796 
797     return HPDF_OK;
798 }
799 
800 
801 static HPDF_STATUS
ParseMaxp(HPDF_FontDef fontdef)802 ParseMaxp (HPDF_FontDef  fontdef)
803 {
804     HPDF_TTFontDefAttr attr = (HPDF_TTFontDefAttr)fontdef->attr;
805     HPDF_TTFTable *tbl = FindTable (fontdef, "maxp");
806     HPDF_STATUS ret;
807 
808     HPDF_PTRACE ((" HPDF_TTFontDef_ParseMaxp\n"));
809 
810     if (!tbl)
811         return HPDF_SetError (fontdef->error, HPDF_TTF_MISSING_TABLE, 9);
812 
813     ret = HPDF_Stream_Seek (attr->stream, tbl->offset + 4, HPDF_SEEK_SET);
814     if (ret != HPDF_OK)
815         return ret;
816 
817     ret = GetUINT16 (attr->stream, &attr->num_glyphs);
818 
819     HPDF_PTRACE((" HPDF_TTFontDef_ParseMaxp num_glyphs=%u\n",
820             attr->num_glyphs));
821 
822     return ret;
823 }
824 
825 
826 static HPDF_STATUS
ParseHhea(HPDF_FontDef fontdef)827 ParseHhea (HPDF_FontDef  fontdef)
828 {
829     HPDF_TTFontDefAttr attr = (HPDF_TTFontDefAttr)fontdef->attr;
830     HPDF_TTFTable *tbl = FindTable (fontdef, "hhea");
831     HPDF_STATUS ret;
832 
833     HPDF_PTRACE ((" HPDF_TTFontDef_ParseHhea\n"));
834 
835     if (!tbl)
836         return HPDF_SetError (fontdef->error, HPDF_TTF_MISSING_TABLE, 6);
837 
838     ret = HPDF_Stream_Seek (attr->stream, tbl->offset + 4, HPDF_SEEK_SET);
839     if (ret != HPDF_OK)
840         return ret;
841 
842     ret += GetINT16 (attr->stream, &fontdef->ascent);
843     fontdef->ascent = (HPDF_INT16)((HPDF_INT32)fontdef->ascent * 1000 /
844                 attr->header.units_per_em);
845     ret += GetINT16 (attr->stream, &fontdef->descent);
846     fontdef->descent = (HPDF_INT16)((HPDF_INT32)fontdef->descent * 1000 /
847                 attr->header.units_per_em);
848 
849     if (ret != HPDF_OK)
850         return HPDF_Error_GetCode (fontdef->error);
851 
852     ret = HPDF_Stream_Seek (attr->stream, tbl->offset + 34, HPDF_SEEK_SET);
853     if (ret != HPDF_OK)
854         return ret;
855 
856     ret = GetUINT16 (attr->stream, &attr->num_h_metric);
857     if (ret != HPDF_OK)
858         return HPDF_Error_GetCode (fontdef->error);
859 
860     HPDF_PTRACE((" HPDF_TTFontDef_ParseHhea num_h_metric=%u\n",
861             attr->num_h_metric));
862 
863     return ret;
864 }
865 
866 
867 static HPDF_STATUS
ParseCMap(HPDF_FontDef fontdef)868 ParseCMap (HPDF_FontDef  fontdef)
869 {
870     HPDF_TTFontDefAttr attr = (HPDF_TTFontDefAttr)fontdef->attr;
871     HPDF_TTFTable *tbl = FindTable (fontdef, "cmap");
872     HPDF_STATUS ret;
873     HPDF_UINT16 version;
874     HPDF_UINT16 num_cmap;
875     HPDF_UINT i;
876     HPDF_UINT32 ms_unicode_encoding_offset = 0;
877     HPDF_UINT32 byte_encoding_offset = 0;
878 
879     HPDF_PTRACE ((" HPDF_TTFontDef_ParseCMap\n"));
880 
881     if (!tbl)
882         return HPDF_SetError (fontdef->error, HPDF_TTF_MISSING_TABLE, 1);
883 
884     ret = HPDF_Stream_Seek (attr->stream, tbl->offset, HPDF_SEEK_SET);
885     if (ret != HPDF_OK)
886         return ret;
887 
888     ret += GetUINT16 (attr->stream, &version);
889     if (ret != HPDF_OK)
890         return HPDF_Error_GetCode (fontdef->error);
891 
892     if (version != 0)
893         return HPDF_SetError (fontdef->error, HPDF_TTF_INVALID_FOMAT, 0);
894 
895     ret += GetUINT16 (attr->stream, &num_cmap);
896     if (ret != HPDF_OK)
897         return HPDF_Error_GetCode (fontdef->error);
898 
899     for (i = 0; i < num_cmap; i++) {
900         HPDF_UINT16 platformID;
901         HPDF_UINT16 encodingID;
902         HPDF_UINT16 format;
903         HPDF_UINT32 offset;
904         HPDF_INT32 save_offset;
905 
906         ret += GetUINT16 (attr->stream, &platformID);
907         ret += GetUINT16 (attr->stream, &encodingID);
908         ret += GetUINT32 (attr->stream, &offset);
909         if (ret != HPDF_OK)
910             return HPDF_Error_GetCode (fontdef->error);
911 
912         save_offset = HPDF_Stream_Tell (attr->stream);
913         if (save_offset < 0)
914            return HPDF_Error_GetCode (fontdef->error);
915 
916         ret = HPDF_Stream_Seek (attr->stream, tbl->offset + offset,
917                 HPDF_SEEK_SET);
918         if (ret != HPDF_OK)
919            return ret;
920 
921         ret = GetUINT16 (attr->stream, &format);
922         if (ret != HPDF_OK)
923            return ret;
924 
925         HPDF_PTRACE((" HPDF_TTFontDef_ParseCMap tables[%d] platformID=%u "
926                         "encodingID=%u format=%u offset=%u\n", i, platformID,
927                         encodingID, format, (HPDF_UINT)offset));
928 
929         /* MS-Unicode-CMAP is used for priority */
930         if (platformID == 3 && encodingID == 1 && format == 4) {
931             ms_unicode_encoding_offset = offset;
932             break;
933         }
934 
935         /* Byte-Encoding-CMAP will be used if MS-Unicode-CMAP is not found */
936         if (platformID == 1 && encodingID ==0 && format == 1)
937             byte_encoding_offset = offset;
938 
939         ret = HPDF_Stream_Seek (attr->stream, save_offset, HPDF_SEEK_SET);
940         if (ret != HPDF_OK)
941            return ret;
942     }
943 
944     if (ms_unicode_encoding_offset != 0) {
945         HPDF_PTRACE((" found microsoft unicode cmap.\n"));
946         ret = ParseCMAP_format4(fontdef, ms_unicode_encoding_offset +
947                 tbl->offset);
948     } else if (byte_encoding_offset != 0) {
949         HPDF_PTRACE((" found byte encoding cmap.\n"));
950         ret = ParseCMAP_format0(fontdef, byte_encoding_offset + tbl->offset);
951     } else {
952         HPDF_PTRACE((" cannot found target cmap.\n"));
953         return HPDF_SetError (fontdef->error, HPDF_TTF_INVALID_FOMAT, 0);
954     }
955 
956     return ret;
957 }
958 
959 
960 static HPDF_STATUS
ParseCMAP_format0(HPDF_FontDef fontdef,HPDF_UINT32 offset)961 ParseCMAP_format0  (HPDF_FontDef  fontdef,
962                     HPDF_UINT32   offset)
963 {
964     HPDF_TTFontDefAttr attr = (HPDF_TTFontDefAttr)fontdef->attr;
965     HPDF_STATUS ret;
966     HPDF_BYTE array[256];
967     HPDF_UINT size;
968     HPDF_UINT16 *parray;
969     HPDF_UINT i;
970 
971     HPDF_PTRACE((" ParseCMAP_format0\n"));
972 
973     ret = HPDF_Stream_Seek (attr->stream, offset, HPDF_SEEK_SET);
974     if (ret != HPDF_OK)
975         return ret;
976 
977     ret += GetUINT16 (attr->stream, &attr->cmap.format);
978     ret += GetUINT16 (attr->stream, &attr->cmap.length);
979     ret += GetUINT16 (attr->stream, &attr->cmap.language);
980 
981     if (ret != HPDF_OK)
982         return HPDF_Error_GetCode (fontdef->error);
983 
984     if (attr->cmap.format != 0)
985         return HPDF_SetError (fontdef->error, HPDF_TTF_INVALID_FOMAT, 0);
986 
987     size = 256;
988     ret = HPDF_Stream_Read (attr->stream, array, &size);
989     if (ret != HPDF_OK)
990         return ret;
991 
992     attr->cmap.glyph_id_array_count = 256;
993     attr->cmap.glyph_id_array = HPDF_GetMem (fontdef->mmgr,
994             sizeof (HPDF_UINT16) * 256);
995     if (!attr->cmap.glyph_id_array)
996         return HPDF_Error_GetCode (fontdef->error);
997 
998     parray = attr->cmap.glyph_id_array;
999     for (i = 0; i < 256; i++) {
1000         *parray = attr->cmap.glyph_id_array[i];
1001         HPDF_PTRACE((" ParseCMAP_format0 glyph_id_array[%d]=%u\n",
1002                     i, *parray));
1003         parray++;
1004     }
1005 
1006     return HPDF_OK;
1007 }
1008 
1009 
1010 static HPDF_STATUS
ParseCMAP_format4(HPDF_FontDef fontdef,HPDF_UINT32 offset)1011 ParseCMAP_format4  (HPDF_FontDef  fontdef,
1012                     HPDF_UINT32   offset)
1013 {
1014     HPDF_TTFontDefAttr attr = (HPDF_TTFontDefAttr)fontdef->attr;
1015     HPDF_STATUS ret;
1016     HPDF_UINT i;
1017     HPDF_UINT16 *pend_count;
1018     HPDF_UINT16 *pstart_count;
1019     HPDF_INT16 *pid_delta;
1020     HPDF_UINT16 *pid_range_offset;
1021     HPDF_UINT16 *pglyph_id_array;
1022     HPDF_INT32 num_read;
1023 
1024     HPDF_PTRACE((" ParseCMAP_format4\n"));
1025 
1026     if ((ret = HPDF_Stream_Seek (attr->stream, offset, HPDF_SEEK_SET)) !=
1027             HPDF_OK)
1028         return ret;
1029 
1030     ret += GetUINT16 (attr->stream, &attr->cmap.format);
1031     ret += GetUINT16 (attr->stream, &attr->cmap.length);
1032     ret += GetUINT16 (attr->stream, &attr->cmap.language);
1033 
1034     if (ret != HPDF_OK)
1035         return HPDF_Error_GetCode (fontdef->error);
1036 
1037     if (attr->cmap.format != 4)
1038         return HPDF_SetError (fontdef->error, HPDF_TTF_INVALID_FOMAT, 0);
1039 
1040     ret += GetUINT16 (attr->stream, &attr->cmap.seg_count_x2);
1041     ret += GetUINT16 (attr->stream, &attr->cmap.search_range);
1042     ret += GetUINT16 (attr->stream, &attr->cmap.entry_selector);
1043     ret += GetUINT16 (attr->stream, &attr->cmap.range_shift);
1044 
1045     if (ret != HPDF_OK)
1046         return HPDF_Error_GetCode (fontdef->error);
1047 
1048     /* end_count */
1049     attr->cmap.end_count = HPDF_GetMem (fontdef->mmgr,
1050             sizeof(HPDF_UINT16) * attr->cmap.seg_count_x2 / 2);
1051     if (!attr->cmap.end_count)
1052         return HPDF_Error_GetCode (fontdef->error);
1053 
1054     pend_count = attr->cmap.end_count;
1055     for (i = 0; i < (HPDF_UINT)attr->cmap.seg_count_x2 / 2; i++)
1056         if ((ret = GetUINT16 (attr->stream, pend_count++)) != HPDF_OK)
1057             return ret;
1058 
1059     if ((ret = GetUINT16 (attr->stream, &attr->cmap.reserved_pad)) != HPDF_OK)
1060         return ret;
1061 
1062     /* start_count */
1063     attr->cmap.start_count = HPDF_GetMem (fontdef->mmgr,
1064             sizeof(HPDF_UINT16) * attr->cmap.seg_count_x2 / 2);
1065     if (!attr->cmap.start_count)
1066         return HPDF_Error_GetCode (fontdef->error);
1067 
1068     pstart_count = attr->cmap.start_count;
1069     for (i = 0; i < (HPDF_UINT)attr->cmap.seg_count_x2 / 2; i++)
1070         if ((ret = GetUINT16 (attr->stream, pstart_count++)) != HPDF_OK)
1071             return ret;
1072 
1073     /* id_delta */
1074     attr->cmap.id_delta = HPDF_GetMem (fontdef->mmgr,
1075             sizeof(HPDF_UINT16) * attr->cmap.seg_count_x2 / 2);
1076     if (!attr->cmap.id_delta)
1077         return HPDF_Error_GetCode (fontdef->error);
1078 
1079     pid_delta = attr->cmap.id_delta;
1080     for (i = 0; i < (HPDF_UINT)attr->cmap.seg_count_x2 / 2; i++)
1081         if ((ret = GetINT16 (attr->stream, pid_delta++)) != HPDF_OK)
1082             return ret;
1083 
1084     /* id_range_offset */
1085     attr->cmap.id_range_offset = HPDF_GetMem (fontdef->mmgr,
1086             sizeof(HPDF_UINT16) * attr->cmap.seg_count_x2 / 2);
1087     if (!attr->cmap.id_range_offset)
1088         return HPDF_Error_GetCode (fontdef->error);
1089 
1090     pid_range_offset = attr->cmap.id_range_offset;
1091     for (i = 0; i < (HPDF_UINT)attr->cmap.seg_count_x2 / 2; i++)
1092         if ((ret = GetUINT16 (attr->stream, pid_range_offset++)) != HPDF_OK)
1093             return ret;
1094 
1095     num_read = HPDF_Stream_Tell (attr->stream) - offset;
1096     if (num_read < 0)
1097         return HPDF_Error_GetCode (fontdef->error);
1098 
1099     attr->cmap.glyph_id_array_count = (attr->cmap.length - num_read) / 2;
1100 
1101     if (attr->cmap.glyph_id_array_count > 0) {
1102         /* glyph_id_array */
1103         attr->cmap.glyph_id_array = HPDF_GetMem (fontdef->mmgr,
1104                 sizeof(HPDF_UINT16) * attr->cmap.glyph_id_array_count);
1105         if (!attr->cmap.glyph_id_array)
1106             return HPDF_Error_GetCode (fontdef->error);
1107 
1108         pglyph_id_array = attr->cmap.glyph_id_array;
1109         for (i = 0; i < attr->cmap.glyph_id_array_count; i++)
1110             if ((ret = GetUINT16 (attr->stream, pglyph_id_array++)) != HPDF_OK)
1111                 return ret;
1112     } else
1113         attr->cmap.glyph_id_array = NULL;
1114 
1115 #ifdef LIBHPDF_DEBUG
1116     /* print all elements of cmap table */
1117     for (i = 0; i < (HPDF_UINT)attr->cmap.seg_count_x2 / 2; i++) {
1118         HPDF_PTRACE((" ParseCMAP_format4[%d] start_count=0x%04X, "
1119                     "end_count=0x%04X, id_delta=%d, id_range_offset=%u\n", i,
1120                     attr->cmap.start_count[i], attr->cmap.end_count[i],
1121                     attr->cmap.id_delta[i], attr->cmap.id_range_offset[i]));
1122     }
1123 #endif
1124 
1125     return HPDF_OK;
1126 }
1127 
1128 
1129 HPDF_UINT16
HPDF_TTFontDef_GetGlyphid(HPDF_FontDef fontdef,HPDF_UINT16 unicode)1130 HPDF_TTFontDef_GetGlyphid  (HPDF_FontDef   fontdef,
1131                             HPDF_UINT16    unicode)
1132 {
1133     HPDF_TTFontDefAttr attr = (HPDF_TTFontDefAttr)fontdef->attr;
1134     HPDF_UINT16 *pend_count = attr->cmap.end_count;
1135     HPDF_UINT seg_count = attr->cmap.seg_count_x2 / 2;
1136     HPDF_UINT i;
1137 
1138     HPDF_PTRACE((" HPDF_TTFontDef_GetGlyphid\n"));
1139 
1140     /* format 0 */
1141     if (attr->cmap.format == 0) {
1142         unicode &= 0xFF;
1143         return attr->cmap.glyph_id_array[unicode];
1144     }
1145 
1146     /* format 4 */
1147     if (attr->cmap.seg_count_x2 == 0) {
1148         HPDF_SetError (fontdef->error, HPDF_TTF_INVALID_CMAP, 0);
1149         return 0;
1150     }
1151 
1152     for (i = 0; i < seg_count; i++) {
1153         if (unicode <= *pend_count)
1154             break;
1155         pend_count++;
1156     }
1157 
1158     if (attr->cmap.start_count[i] > unicode) {
1159         HPDF_PTRACE((" HPDF_TTFontDef_GetGlyphid undefined char(0x%04X)\n",
1160                     unicode));
1161         return 0;
1162     }
1163 
1164     if (attr->cmap.id_range_offset[i] == 0) {
1165         HPDF_PTRACE((" HPDF_TTFontDef_GetGlyphid idx=%u code=%u "
1166                     " ret=%u\n", i, unicode,
1167                     unicode + attr->cmap.id_delta[i]));
1168 
1169         return (HPDF_UINT16)(unicode + attr->cmap.id_delta[i]);
1170     } else {
1171         HPDF_UINT idx = attr->cmap.id_range_offset[i] / 2 +
1172             (unicode - attr->cmap.start_count[i]) - (seg_count - i);
1173 
1174         if (idx > attr->cmap.glyph_id_array_count) {
1175             HPDF_PTRACE((" HPDF_TTFontDef_GetGlyphid[%u] %u > %u\n",
1176                         i, idx, (HPDF_UINT)attr->cmap.glyph_id_array_count));
1177             return 0;
1178         } else {
1179             HPDF_UINT16 gid = (HPDF_UINT16)(attr->cmap.glyph_id_array[idx] +
1180                 attr->cmap.id_delta[i]);
1181             HPDF_PTRACE((" HPDF_TTFontDef_GetGlyphid idx=%u unicode=0x%04X "
1182                         "id=%u\n", idx, unicode, gid));
1183             return gid;
1184         }
1185     }
1186 }
1187 
1188 
1189 HPDF_INT16
HPDF_TTFontDef_GetCharWidth(HPDF_FontDef fontdef,HPDF_UINT16 unicode)1190 HPDF_TTFontDef_GetCharWidth  (HPDF_FontDef   fontdef,
1191                               HPDF_UINT16    unicode)
1192 {
1193     HPDF_UINT16 advance_width;
1194     HPDF_TTF_LongHorMetric hmetrics;
1195     HPDF_TTFontDefAttr attr = (HPDF_TTFontDefAttr)fontdef->attr;
1196     HPDF_UINT16 gid = HPDF_TTFontDef_GetGlyphid (fontdef, unicode);
1197 
1198     HPDF_PTRACE((" HPDF_TTFontDef_GetCharWidth\n"));
1199 
1200     if (gid >= attr->num_glyphs) {
1201         HPDF_PTRACE((" HPDF_TTFontDef_GetCharWidth WARNING gid > "
1202                     "num_glyphs %u > %u\n", gid, attr->num_glyphs));
1203         return fontdef->missing_width;
1204     }
1205 
1206     hmetrics = attr->h_metric[gid];
1207 
1208     if (!attr->glyph_tbl.flgs[gid]) {
1209         attr->glyph_tbl.flgs[gid] = 1;
1210 
1211         if (attr->embedding)
1212             CheckCompositGryph (fontdef, gid);
1213     }
1214 
1215     advance_width = (HPDF_UINT16)((HPDF_UINT)hmetrics.advance_width * 1000 /
1216             attr->header.units_per_em);
1217 
1218     return (HPDF_INT16)advance_width;
1219 }
1220 
1221 
1222 static HPDF_STATUS
CheckCompositGryph(HPDF_FontDef fontdef,HPDF_UINT16 gid)1223 CheckCompositGryph  (HPDF_FontDef   fontdef,
1224                      HPDF_UINT16    gid)
1225 {
1226     HPDF_TTFontDefAttr attr = (HPDF_TTFontDefAttr)fontdef->attr;
1227     HPDF_UINT offset = attr->glyph_tbl.offsets[gid];
1228     /* HPDF_UINT len = attr->glyph_tbl.offsets[gid + 1] - offset; */
1229     HPDF_STATUS ret;
1230 
1231     HPDF_PTRACE ((" CheckCompositGryph\n"));
1232 
1233     if (attr->header.index_to_loc_format == 0)
1234         offset *= 2;
1235 
1236     offset += attr->glyph_tbl.base_offset;
1237 
1238     if ((ret = HPDF_Stream_Seek (attr->stream, offset, HPDF_SEEK_SET))
1239             != HPDF_OK) {
1240         return ret;
1241     } else {
1242         HPDF_INT16 num_of_contours;
1243         HPDF_INT16 flags;
1244         HPDF_INT16 glyph_index;
1245         const HPDF_UINT16 ARG_1_AND_2_ARE_WORDS = 1;
1246         const HPDF_UINT16 WE_HAVE_A_SCALE  = 8;
1247         const HPDF_UINT16 MORE_COMPONENTS = 32;
1248         const HPDF_UINT16 WE_HAVE_AN_X_AND_Y_SCALE = 64;
1249         const HPDF_UINT16 WE_HAVE_A_TWO_BY_TWO = 128;
1250 
1251         if ((ret = GetINT16 (attr->stream, &num_of_contours)) != HPDF_OK)
1252             return ret;
1253 
1254         if (num_of_contours != -1)
1255             return HPDF_OK;
1256 
1257         HPDF_PTRACE ((" CheckCompositGryph composit font gid=%u\n", gid));
1258 
1259         if ((ret = HPDF_Stream_Seek (attr->stream, 8, HPDF_SEEK_CUR))
1260             != HPDF_OK)
1261             return ret;
1262 
1263         do {
1264             if ((ret = GetINT16 (attr->stream, &flags)) != HPDF_OK)
1265                 return ret;
1266 
1267             if ((ret = GetINT16 (attr->stream, &glyph_index)) != HPDF_OK)
1268                 return ret;
1269 
1270             if (flags & ARG_1_AND_2_ARE_WORDS) {
1271                 if ((ret = HPDF_Stream_Seek (attr->stream, 4, HPDF_SEEK_CUR))
1272                     != HPDF_OK)
1273                     return ret;
1274             } else {
1275                 if ((ret = HPDF_Stream_Seek (attr->stream, 2, HPDF_SEEK_CUR))
1276                     != HPDF_OK)
1277                     return ret;
1278             }
1279 
1280             if (flags & WE_HAVE_A_SCALE) {
1281                 if ((ret = HPDF_Stream_Seek (attr->stream, 2, HPDF_SEEK_CUR))
1282                     != HPDF_OK)
1283                     return ret;
1284             } else if (flags & WE_HAVE_AN_X_AND_Y_SCALE) {
1285                 if ((ret = HPDF_Stream_Seek (attr->stream, 4, HPDF_SEEK_CUR))
1286                     != HPDF_OK)
1287                     return ret;
1288             } else if (flags & WE_HAVE_A_TWO_BY_TWO) {
1289                 if ((ret = HPDF_Stream_Seek (attr->stream, 8, HPDF_SEEK_CUR))
1290                     != HPDF_OK)
1291                     return ret;
1292             }
1293 
1294             if (glyph_index > 0 && glyph_index < attr->num_glyphs)
1295                 attr->glyph_tbl.flgs[glyph_index] = 1;
1296 
1297             HPDF_PTRACE ((" gid=%d, num_of_contours=%d, flags=%d, "
1298                     "glyph_index=%d\n", gid, num_of_contours, flags,
1299                     glyph_index));
1300 
1301         } while (flags & MORE_COMPONENTS);
1302     }
1303 
1304     return HPDF_OK;
1305 }
1306 
1307 
1308 HPDF_INT16
HPDF_TTFontDef_GetGidWidth(HPDF_FontDef fontdef,HPDF_UINT16 gid)1309 HPDF_TTFontDef_GetGidWidth  (HPDF_FontDef   fontdef,
1310                              HPDF_UINT16    gid)
1311 {
1312     HPDF_UINT16 advance_width;
1313     HPDF_TTF_LongHorMetric hmetrics;
1314     HPDF_TTFontDefAttr attr = (HPDF_TTFontDefAttr)fontdef->attr;
1315 
1316     HPDF_PTRACE((" HPDF_TTFontDef_GetGidWidth\n"));
1317 
1318     if (gid >= attr->num_glyphs) {
1319         HPDF_PTRACE((" HPDF_TTFontDef_GetGidWidth WARNING gid > "
1320                     "num_glyphs %u > %u\n", gid, attr->num_glyphs));
1321         return fontdef->missing_width;
1322     }
1323 
1324     hmetrics = attr->h_metric[gid];
1325 
1326     advance_width = (HPDF_UINT16)((HPDF_UINT)hmetrics.advance_width * 1000 /
1327             attr->header.units_per_em);
1328 
1329     HPDF_PTRACE((" HPDF_TTFontDef_GetGidWidth gid=%u, width=%u\n",
1330                 gid, advance_width));
1331 
1332     return (HPDF_INT16)advance_width;
1333 }
1334 
1335 
1336 
1337 static HPDF_STATUS
ParseHmtx(HPDF_FontDef fontdef)1338 ParseHmtx  (HPDF_FontDef  fontdef)
1339 {
1340     HPDF_TTFontDefAttr attr = (HPDF_TTFontDefAttr)fontdef->attr;
1341     HPDF_TTFTable *tbl = FindTable (fontdef, "hmtx");
1342     HPDF_STATUS ret;
1343     HPDF_UINT i;
1344     HPDF_UINT16 save_aw = 0;
1345     HPDF_TTF_LongHorMetric *pmetric;
1346 
1347     HPDF_PTRACE ((" HPDF_TTFontDef_ParseHtmx\n"));
1348 
1349     if (!tbl)
1350         return HPDF_SetError (fontdef->error, HPDF_TTF_MISSING_TABLE, 7);
1351 
1352     ret = HPDF_Stream_Seek (attr->stream, tbl->offset, HPDF_SEEK_SET);
1353     if (ret != HPDF_OK)
1354         return ret;
1355 
1356     /* allocate memory for a table of holizontal matrix.
1357      * the count of metric records is same as the number of glyphs
1358      */
1359     attr->h_metric = HPDF_GetMem (fontdef->mmgr,
1360         sizeof (HPDF_TTF_LongHorMetric) * attr->num_glyphs);
1361 
1362     if (!attr->h_metric)
1363         return HPDF_Error_GetCode (fontdef->error);
1364 
1365     pmetric = attr->h_metric;
1366     for (i = 0; i < attr->num_h_metric; i++) {
1367         if ((ret = GetUINT16 (attr->stream, &pmetric->advance_width)) !=
1368                     HPDF_OK)
1369             return ret;
1370 
1371         if ((ret = GetINT16 (attr->stream, &pmetric->lsb)) != HPDF_OK)
1372             return ret;
1373 
1374         HPDF_PTRACE((" ParseHmtx metric[%u] aw=%u lsb=%d\n", i,
1375             pmetric->advance_width, pmetric->lsb));
1376 
1377         save_aw = pmetric->advance_width;
1378         pmetric++;
1379     }
1380 
1381     /* pad the advance_width of remaining metrics with the value of last metric */
1382     while (i < attr->num_glyphs) {
1383         pmetric->advance_width = save_aw;
1384 
1385         if ((ret = GetINT16 (attr->stream, &pmetric->lsb)) != HPDF_OK)
1386             return ret;
1387 
1388         pmetric++;
1389         i++;
1390     }
1391 
1392     return HPDF_OK;
1393 }
1394 
1395 static HPDF_STATUS
ParseLoca(HPDF_FontDef fontdef)1396 ParseLoca  (HPDF_FontDef  fontdef)
1397 {
1398     HPDF_TTFontDefAttr attr = (HPDF_TTFontDefAttr)fontdef->attr;
1399     HPDF_TTFTable *tbl = FindTable (fontdef, "loca");
1400     HPDF_STATUS ret;
1401     HPDF_UINT i;
1402     HPDF_UINT32 *poffset;
1403 
1404     HPDF_PTRACE ((" HPDF_TTFontDef_ParseLoca\n"));
1405 
1406     if (!tbl)
1407         return HPDF_SetError (fontdef->error, HPDF_TTF_MISSING_TABLE, 8);
1408 
1409     ret = HPDF_Stream_Seek (attr->stream, tbl->offset, HPDF_SEEK_SET);
1410     if (ret != HPDF_OK)
1411         return ret;
1412 
1413     /* allocate glyph-offset-table. */
1414     attr->glyph_tbl.offsets = HPDF_GetMem (fontdef->mmgr,
1415         sizeof (HPDF_UINT32) * (attr->num_glyphs + 1));
1416 
1417     if (!attr->glyph_tbl.offsets)
1418         return HPDF_Error_GetCode (fontdef->error);
1419 
1420     HPDF_MemSet (attr->glyph_tbl.offsets, 0,
1421             sizeof (HPDF_UINT32) * (attr->num_glyphs + 1));
1422 
1423     /* allocate glyph-flg-table.
1424      * this flgs are used to judge whether glyphs should be embedded.
1425      */
1426     attr->glyph_tbl.flgs = HPDF_GetMem (fontdef->mmgr,
1427         sizeof (HPDF_BYTE) * attr->num_glyphs);
1428 
1429     if (!attr->glyph_tbl.flgs)
1430         return HPDF_Error_GetCode (fontdef->error);
1431 
1432     HPDF_MemSet (attr->glyph_tbl.flgs, 0,
1433         sizeof (HPDF_BYTE) * attr->num_glyphs);
1434     attr->glyph_tbl.flgs[0] = 1;
1435 
1436     poffset = attr->glyph_tbl.offsets;
1437     if (attr->header.index_to_loc_format == 0) {
1438         /* short version */
1439         for (i = 0; i <= attr->num_glyphs; i++) {
1440             HPDF_UINT16 tmp = 0;
1441 
1442             if ((ret = GetUINT16 (attr->stream, &tmp)) != HPDF_OK)
1443                 return ret;
1444 
1445             *poffset = tmp;
1446             poffset++;
1447         }
1448     } else {
1449         /* long version */
1450         for (i = 0; i <= attr->num_glyphs; i++) {
1451             if ((ret = GetUINT32 (attr->stream, poffset)) != HPDF_OK)
1452                 return ret;
1453 
1454             poffset++;
1455         }
1456     }
1457 
1458 
1459 #ifdef LIBHPDF_DEBUG
1460     poffset = attr->glyph_tbl.offsets;
1461     for (i = 0; i <= attr->num_glyphs; i++) {
1462         HPDF_PTRACE((" ParseLOCA offset[%u]=%u\n", i, (HPDF_UINT)*poffset));
1463         poffset++;
1464     }
1465 #endif
1466 
1467 
1468     return HPDF_OK;
1469 }
1470 
1471 
1472 static HPDF_STATUS
LoadUnicodeName(HPDF_Stream stream,HPDF_UINT offset,HPDF_UINT len,char * buf)1473 LoadUnicodeName  (HPDF_Stream   stream,
1474                   HPDF_UINT     offset,
1475                   HPDF_UINT     len,
1476                   char    *buf)
1477 {
1478     HPDF_BYTE tmp[HPDF_LIMIT_MAX_NAME_LEN * 2 + 1];
1479     HPDF_UINT i = 0;
1480     HPDF_UINT j = 0;
1481     HPDF_STATUS ret;
1482 
1483     HPDF_MemSet (buf, 0, HPDF_LIMIT_MAX_NAME_LEN + 1);
1484 
1485     if ((ret = HPDF_Stream_Seek (stream, offset, HPDF_SEEK_SET)) !=
1486             HPDF_OK)
1487         return ret;
1488 
1489     if ((ret = HPDF_Stream_Read (stream, tmp, &len))
1490              != HPDF_OK)
1491         return ret;
1492 
1493     while (i < len) {
1494         i++;
1495         buf[j] = tmp[i];
1496         j++;
1497         i++;
1498     }
1499 
1500     return HPDF_OK;
1501 }
1502 
1503 static HPDF_STATUS
ParseName(HPDF_FontDef fontdef)1504 ParseName  (HPDF_FontDef  fontdef)
1505 {
1506     HPDF_TTFontDefAttr attr = (HPDF_TTFontDefAttr)fontdef->attr;
1507     HPDF_TTFTable *tbl = FindTable (fontdef, "name");
1508     HPDF_STATUS ret;
1509     HPDF_UINT i;
1510     HPDF_TTF_NameRecord *name_rec;
1511     HPDF_UINT offset_id1 = 0;
1512     HPDF_UINT offset_id2 = 0;
1513     HPDF_UINT offset_id1u = 0;
1514     HPDF_UINT offset_id2u = 0;
1515     HPDF_UINT len_id1 = 0;
1516     HPDF_UINT len_id2 = 0;
1517     HPDF_UINT len_id1u = 0;
1518     HPDF_UINT len_id2u = 0;
1519     char tmp[HPDF_LIMIT_MAX_NAME_LEN + 1];
1520 
1521     HPDF_PTRACE ((" HPDF_TTFontDef_ParseMaxp\n"));
1522 
1523     if (!tbl)
1524         return HPDF_SetError (fontdef->error, HPDF_TTF_MISSING_TABLE, 10);
1525 
1526     ret = HPDF_Stream_Seek (attr->stream, tbl->offset, HPDF_SEEK_SET);
1527     if (ret != HPDF_OK)
1528         return ret;
1529 
1530     ret += GetUINT16 (attr->stream, &attr->name_tbl.format);
1531     ret += GetUINT16 (attr->stream, &attr->name_tbl.count);
1532     ret += GetUINT16 (attr->stream, &attr->name_tbl.string_offset);
1533     if (ret != HPDF_OK)
1534         return HPDF_Error_GetCode (fontdef->error);
1535 
1536     HPDF_PTRACE((" ParseName() format=%u, count=%u, string_offset=%u\n",
1537                 attr->name_tbl.format, attr->name_tbl.count,
1538                 attr->name_tbl.string_offset));
1539 
1540     attr->name_tbl.name_records = HPDF_GetMem (fontdef->mmgr,
1541             sizeof (HPDF_TTF_NameRecord) * attr->name_tbl.count);
1542 
1543     if (!attr->name_tbl.name_records)
1544         return HPDF_Error_GetCode (fontdef->error);
1545 
1546     name_rec = attr->name_tbl.name_records;
1547 
1548    for (i = 0; i < attr->name_tbl.count; i++) {
1549         ret += GetUINT16 (attr->stream, &name_rec->platform_id);
1550         ret += GetUINT16 (attr->stream, &name_rec->encoding_id);
1551         ret += GetUINT16 (attr->stream, &name_rec->language_id);
1552         ret += GetUINT16 (attr->stream, &name_rec->name_id);
1553         ret += GetUINT16 (attr->stream, &name_rec->length);
1554         ret += GetUINT16 (attr->stream, &name_rec->offset);
1555 
1556         if (ret != HPDF_OK)
1557             return HPDF_Error_GetCode (fontdef->error);
1558 
1559         HPDF_PTRACE((" ParseName() platformID=%u, encodingID=%d, nameID=%d\n",
1560                     name_rec->platform_id, name_rec->encoding_id,
1561                     name_rec->name_id));
1562 
1563         if (name_rec->platform_id == 1 && name_rec->encoding_id == 0 &&
1564                 name_rec->name_id == 6) {
1565             offset_id1 = tbl->offset + name_rec->offset +
1566                     attr->name_tbl.string_offset;
1567             len_id1 = name_rec->length;
1568         }
1569 
1570         if (name_rec->platform_id == 1 && name_rec->encoding_id == 0 &&
1571                 name_rec->name_id == 2) {
1572             offset_id2 = tbl->offset + name_rec->offset +
1573                     attr->name_tbl.string_offset;
1574             len_id2 = name_rec->length;
1575         }
1576 
1577         if (name_rec->platform_id == 3 && name_rec->encoding_id == 1 &&
1578                 name_rec->name_id == 6 && name_rec->language_id == 0x0409) {
1579             offset_id1u = tbl->offset + name_rec->offset +
1580                     attr->name_tbl.string_offset;
1581             len_id1u = name_rec->length;
1582         }
1583 
1584         if (name_rec->platform_id == 3 && name_rec->encoding_id == 1 &&
1585                 name_rec->name_id == 2 && name_rec->language_id == 0x0409) {
1586             offset_id2u = tbl->offset + name_rec->offset +
1587                     attr->name_tbl.string_offset;
1588             len_id2u = name_rec->length;
1589         }
1590 
1591         name_rec++;
1592     }
1593 
1594     if ((!offset_id1 && !offset_id1u) ||
1595             (!offset_id2 && !offset_id2u))
1596         return HPDF_SetError (fontdef->error, HPDF_TTF_INVALID_FOMAT, 0);
1597 
1598     if (len_id1 == 0 && len_id1u > 0)
1599         len_id1 = len_id1u / 2 + len_id1u % 2;
1600 
1601     if (len_id2 == 0 && len_id2u > 0)
1602         len_id2 = len_id2u / 2 + len_id2u % 2;
1603 
1604     if (len_id1 + len_id2 + 8 > 127)
1605         return HPDF_SetError (fontdef->error, HPDF_TTF_INVALID_FOMAT, 0);
1606 
1607     HPDF_MemSet (attr->base_font, 0, HPDF_LIMIT_MAX_NAME_LEN + 1);
1608 
1609     if (offset_id1) {
1610         if ((ret = HPDF_Stream_Seek (attr->stream, offset_id1,
1611                 HPDF_SEEK_SET)) != HPDF_OK)
1612         return ret;
1613 
1614         if ((ret = HPDF_Stream_Read (attr->stream, (HPDF_BYTE *)attr->base_font, &len_id1))
1615                  != HPDF_OK)
1616             return ret;
1617     } else {
1618         if ((ret = LoadUnicodeName (attr->stream, offset_id1u, len_id1u,
1619                 attr->base_font)) != HPDF_OK)
1620             return ret;
1621     }
1622 
1623     HPDF_MemSet (tmp, 0, HPDF_LIMIT_MAX_NAME_LEN + 1);
1624 
1625     if (offset_id2) {
1626         if ((ret = HPDF_Stream_Seek (attr->stream, offset_id2, HPDF_SEEK_SET))
1627                 != HPDF_OK)
1628             return ret;
1629 
1630         if ((ret = HPDF_Stream_Read (attr->stream, (HPDF_BYTE *)tmp, &len_id2)) != HPDF_OK)
1631             return ret;
1632     } else {
1633         if ((ret = LoadUnicodeName (attr->stream, offset_id2u, len_id2u,
1634                 tmp)) != HPDF_OK)
1635             return ret;
1636     }
1637 
1638    /*
1639     * get "postscript name" of from a "name" table as BaseName.
1640     * if subfamily name is not "Regular", add subfamily name to BaseName.
1641     * if subfamily name includes the blank character, remove it.
1642     * if subfamily name is "Bold" or "Italic" or "BoldItalic", set flags
1643     * attribute.
1644     */
1645     if (HPDF_MemCmp ((HPDF_BYTE *)tmp, (HPDF_BYTE *)"Regular", 7) != 0) {
1646         char *dst = attr->base_font + len_id1;
1647         char *src = tmp;
1648         HPDF_UINT j;
1649 
1650         *dst++ = ',';
1651 
1652         for (j = 0; j < len_id2; j++) {
1653             if (*src != ' ')
1654                 *dst++ = *src++;
1655 
1656             if (dst >= attr->base_font + HPDF_LIMIT_MAX_NAME_LEN)
1657                 break;
1658         }
1659 
1660         *dst = 0;
1661 
1662         if (HPDF_StrStr (tmp, "Bold", len_id2))
1663             fontdef->flags |= HPDF_FONT_FOURCE_BOLD;
1664         if (HPDF_StrStr (tmp, "Italic", len_id2))
1665             fontdef->flags |= HPDF_FONT_ITALIC;
1666     }
1667 
1668     HPDF_MemCpy ((HPDF_BYTE *)fontdef->base_font, (HPDF_BYTE *)attr->base_font, HPDF_LIMIT_MAX_NAME_LEN + 1);
1669 
1670     HPDF_PTRACE(("  ParseName() base_font=%s\n", attr->base_font));
1671 
1672     return HPDF_OK;
1673 }
1674 
1675 static HPDF_STATUS
ParseOS2(HPDF_FontDef fontdef)1676 ParseOS2  (HPDF_FontDef  fontdef)
1677 {
1678     HPDF_TTFontDefAttr attr = (HPDF_TTFontDefAttr)fontdef->attr;
1679     HPDF_TTFTable *tbl = FindTable (fontdef, "OS/2");
1680     HPDF_STATUS ret;
1681     HPDF_UINT16 version;
1682     HPDF_UINT len;
1683 
1684     HPDF_PTRACE ((" ParseOS2\n"));
1685 
1686     if (!tbl)
1687         return HPDF_SetError (fontdef->error, HPDF_TTF_MISSING_TABLE, 0);
1688 
1689     /* get the number version. */
1690     ret = HPDF_Stream_Seek (attr->stream, tbl->offset, HPDF_SEEK_SET);
1691     if (ret != HPDF_OK)
1692         return ret;
1693 
1694     if ((ret = GetUINT16 (attr->stream, &version)) != HPDF_OK)
1695         return ret;
1696 
1697     /* check whether the font is allowed to be embedded. */
1698     ret = HPDF_Stream_Seek (attr->stream, tbl->offset + 8, HPDF_SEEK_SET);
1699     if (ret != HPDF_OK)
1700         return ret;
1701 
1702     if ((ret = GetUINT16 (attr->stream, &attr->fs_type)) != HPDF_OK)
1703         return ret;
1704 
1705     if (attr->fs_type  & (0x0002 | 0x0100 | 0x0200) && attr->embedding)
1706         return HPDF_SetError (fontdef->error, HPDF_TTF_CANNOT_EMBEDDING_FONT,
1707                 0);
1708 
1709     /* get fields sfamilyclass and panose. */
1710     if ((ret = HPDF_Stream_Seek (attr->stream, tbl->offset + 30, HPDF_SEEK_SET))
1711             != HPDF_OK)
1712         return ret;
1713 
1714     len = 2;
1715     if ((ret = HPDF_Stream_Read (attr->stream, attr->sfamilyclass, &len)) != HPDF_OK)
1716         return ret;
1717 
1718     len = 10;
1719     if ((ret = HPDF_Stream_Read (attr->stream, attr->panose, &len)) != HPDF_OK)
1720         return ret;
1721 
1722     HPDF_PTRACE((" ParseOS2 sFamilyClass=%d-%d "
1723             "Panose=%02X-%02X-%02X-%02X-%02X-%02X-%02X-%02X-%02X-%02X\n",
1724         attr->sfamilyclass[0], attr->sfamilyclass[1],
1725         attr->panose[0], attr->panose[1], attr->panose[2], attr->panose[3],
1726         attr->panose[4], attr->panose[5], attr->panose[6], attr->panose[7],
1727         attr->panose[8], attr->panose[9]));
1728 
1729     /* Class ID = 1   Oldstyle Serifs
1730        Class ID = 2   Transitional Serifs
1731        Class ID = 3   Modern Serifs
1732        Class ID = 4   Clarendon Serifs
1733        Class ID = 5   Slab Serifs
1734        Class ID = 6   (reserved for future use)
1735        Class ID = 7   Freeform Serifs
1736        Class ID = 8   Sans Serif
1737        Class ID = 9   Ornamentals
1738        Class ID = 10  Scripts
1739        Class ID = 11  (reserved for future use)
1740        Class ID = 12  Symbolic */
1741     if ((attr->sfamilyclass[0] > 0 && attr->sfamilyclass[0] < 6)
1742         || (attr->sfamilyclass[0] == 7))
1743         fontdef->flags = fontdef->flags | HPDF_FONT_SERIF;
1744 
1745     if (attr->sfamilyclass[0] == 10)
1746         fontdef->flags = fontdef->flags | HPDF_FONT_SCRIPT;
1747 
1748     if (attr->sfamilyclass[0] == 12)
1749         fontdef->flags = fontdef->flags | HPDF_FONT_SYMBOLIC;
1750 
1751     /* get fields ulCodePageRange1 and ulCodePageRange2 */
1752     if(version > 0) {
1753         if ((ret = HPDF_Stream_Seek (attr->stream, 36, HPDF_SEEK_CUR)) != HPDF_OK)
1754             return ret;
1755 
1756         if ((ret = GetUINT32 (attr->stream, &attr->code_page_range1)) != HPDF_OK)
1757             return ret;
1758 
1759         if ((ret = GetUINT32 (attr->stream, &attr->code_page_range2)) != HPDF_OK)
1760             return ret;
1761     }
1762 
1763     HPDF_PTRACE(("  ParseOS2 CodePageRange1=%08X CodePageRange2=%08X\n",
1764                 (HPDF_UINT)attr->code_page_range1,
1765                 (HPDF_UINT)attr->code_page_range2));
1766 
1767     return HPDF_OK;
1768 }
1769 
1770 
1771 static HPDF_STATUS
RecreateGLYF(HPDF_FontDef fontdef,HPDF_UINT32 * new_offsets,HPDF_Stream stream)1772 RecreateGLYF  (HPDF_FontDef   fontdef,
1773                HPDF_UINT32   *new_offsets,
1774                HPDF_Stream    stream)
1775 {
1776     HPDF_UINT32 save_offset = 0;
1777     HPDF_UINT32 start_offset = stream->size;
1778     HPDF_TTFontDefAttr attr = (HPDF_TTFontDefAttr)fontdef->attr;
1779     HPDF_STATUS ret;
1780     HPDF_INT i;
1781 
1782     HPDF_PTRACE ((" RecreateGLYF\n"));
1783 
1784     for (i = 0; i < attr->num_glyphs; i++) {
1785         HPDF_BYTE buf[HPDF_STREAM_BUF_SIZ];
1786 
1787         if (attr->glyph_tbl.flgs[i] == 1) {
1788             HPDF_UINT offset = attr->glyph_tbl.offsets[i];
1789             HPDF_UINT len = attr->glyph_tbl.offsets[i + 1] - offset;
1790 
1791             new_offsets[i] = stream->size - start_offset;
1792             if (attr->header.index_to_loc_format == 0) {
1793                 new_offsets[i] /= 2;
1794                 len *= 2;
1795             }
1796 
1797             HPDF_PTRACE((" RecreateGLYF[%u] move from [%u] to [%u]\n", i,
1798                         (HPDF_UINT)attr->glyph_tbl.base_offset + offset,
1799                         (HPDF_UINT)new_offsets[i]));
1800 
1801             if (attr->header.index_to_loc_format == 0)
1802                 offset *= 2;
1803 
1804             offset += attr->glyph_tbl.base_offset;
1805 
1806             if ((ret = HPDF_Stream_Seek (attr->stream, offset, HPDF_SEEK_SET))
1807                     != HPDF_OK)
1808                 return ret;
1809 
1810             while (len > 0) {
1811                 HPDF_UINT tmp_len =
1812                     (len > HPDF_STREAM_BUF_SIZ) ? HPDF_STREAM_BUF_SIZ : len;
1813 
1814                 HPDF_MemSet (buf, 0, tmp_len);
1815 
1816                 if ((ret = HPDF_Stream_Read (attr->stream, buf, &tmp_len))
1817                         != HPDF_OK)
1818                     return ret;
1819 
1820                 if ((ret = HPDF_Stream_Write (stream, buf, tmp_len)) !=
1821                         HPDF_OK)
1822                     return ret;
1823 
1824                 len -= tmp_len;
1825             }
1826 
1827             save_offset = stream->size - start_offset;
1828             if (attr->header.index_to_loc_format == 0)
1829                 save_offset /= 2;
1830         } else {
1831             new_offsets[i] = save_offset;
1832         }
1833     }
1834 
1835     new_offsets[attr->num_glyphs] = save_offset;
1836 
1837 #ifdef DEBUG
1838     for (i = 0; i <= attr->num_glyphs; i++) {
1839         HPDF_PTRACE((" RecreateGLYF[%u] offset=%u\n", i, new_offsets[i]));
1840     }
1841 #endif
1842 
1843     return HPDF_OK;
1844 }
1845 
1846 static HPDF_STATUS
RecreateName(HPDF_FontDef fontdef,HPDF_Stream stream)1847 RecreateName  (HPDF_FontDef   fontdef,
1848                HPDF_Stream    stream)
1849 {
1850     HPDF_TTFontDefAttr attr = (HPDF_TTFontDefAttr)fontdef->attr;
1851     HPDF_TTFTable *tbl = FindTable (fontdef, "name");
1852     HPDF_STATUS ret = HPDF_OK;
1853     HPDF_UINT i;
1854     HPDF_TTF_NameRecord *name_rec;
1855     HPDF_Stream tmp_stream = HPDF_MemStream_New (fontdef->mmgr,
1856                 HPDF_STREAM_BUF_SIZ);
1857 
1858     HPDF_PTRACE ((" RecreateName\n"));
1859 
1860     if (!tmp_stream)
1861         return HPDF_Error_GetCode (fontdef->error);
1862 
1863     ret += WriteUINT16 (stream, attr->name_tbl.format);
1864     ret += WriteUINT16 (stream, attr->name_tbl.count);
1865     ret += WriteUINT16 (stream, attr->name_tbl.string_offset);
1866 
1867     if (ret != HPDF_OK) {
1868         HPDF_Stream_Free (tmp_stream);
1869         return HPDF_Error_GetCode (fontdef->error);
1870     }
1871 
1872     name_rec = attr->name_tbl.name_records;
1873     for (i = 0; i < attr->name_tbl.count; i++) {
1874         HPDF_UINT name_len = name_rec->length;
1875         HPDF_BYTE buf[HPDF_STREAM_BUF_SIZ];
1876         HPDF_UINT tmp_len = name_len;
1877         HPDF_UINT offset = tbl->offset + attr->name_tbl.string_offset +
1878                 name_rec->offset;
1879         HPDF_UINT rec_offset = tmp_stream->size;
1880 
1881         /* add suffix to font-name. */
1882         if (name_rec->name_id == 1 || name_rec->name_id == 4) {
1883             if (name_rec->platform_id == 0 || name_rec->platform_id == 3) {
1884                 ret += HPDF_Stream_Write (tmp_stream, (HPDF_BYTE *)attr->tag_name2,
1885                         sizeof(attr->tag_name2));
1886                 name_len += sizeof(attr->tag_name2);
1887             } else {
1888                 ret += HPDF_Stream_Write (tmp_stream, (HPDF_BYTE *)attr->tag_name,
1889                         sizeof(attr->tag_name));
1890                 name_len += sizeof(attr->tag_name);
1891             }
1892         }
1893 
1894         ret += WriteUINT16 (stream, name_rec->platform_id);
1895         ret += WriteUINT16 (stream, name_rec->encoding_id);
1896         ret += WriteUINT16 (stream, name_rec->language_id);
1897         ret += WriteUINT16 (stream, name_rec->name_id);
1898         ret += WriteUINT16 (stream, (HPDF_UINT16)name_len);
1899         ret += WriteUINT16 (stream, (HPDF_UINT16)rec_offset);
1900 
1901         ret += HPDF_Stream_Seek (attr->stream, offset, HPDF_SEEK_SET);
1902 
1903         if (ret != HPDF_OK) {
1904             HPDF_Stream_Free (tmp_stream);
1905             return HPDF_Error_GetCode (fontdef->error);
1906         }
1907 
1908         while (tmp_len > 0) {
1909             HPDF_UINT len = (tmp_len > HPDF_STREAM_BUF_SIZ) ?
1910                     HPDF_STREAM_BUF_SIZ : tmp_len;
1911 
1912             if ((ret = HPDF_Stream_Read (attr->stream, buf, &len)) != HPDF_OK) {
1913                 HPDF_Stream_Free (tmp_stream);
1914                 return ret;
1915             }
1916 
1917             if ((ret = HPDF_Stream_Write (tmp_stream, buf, len)) != HPDF_OK) {
1918                 HPDF_Stream_Free (tmp_stream);
1919                 return ret;
1920             }
1921 
1922             tmp_len -= len;
1923         }
1924 
1925         HPDF_PTRACE((" RecreateNAME name_rec[%u] platform_id=%u "
1926                         "encoding_id=%u language_id=%u name_rec->name_id=%u "
1927                         "length=%u offset=%u\n", i, name_rec->platform_id,
1928                         name_rec->encoding_id, name_rec->language_id,
1929                         name_rec->name_id, name_len, rec_offset));
1930 
1931         name_rec++;
1932     }
1933 
1934     ret = HPDF_Stream_WriteToStream (tmp_stream, stream,
1935                 HPDF_STREAM_FILTER_NONE, NULL);
1936 
1937     HPDF_Stream_Free (tmp_stream);
1938 
1939     return ret;
1940 }
1941 
1942 
1943 static HPDF_STATUS
WriteHeader(HPDF_FontDef fontdef,HPDF_Stream stream,HPDF_UINT32 * check_sum_ptr)1944 WriteHeader (HPDF_FontDef   fontdef,
1945              HPDF_Stream    stream,
1946              HPDF_UINT32   *check_sum_ptr)
1947 {
1948     HPDF_TTFontDefAttr attr = (HPDF_TTFontDefAttr)fontdef->attr;
1949     HPDF_STATUS ret = HPDF_OK;
1950 
1951     HPDF_PTRACE ((" WriteHeader\n"));
1952 
1953     ret += HPDF_Stream_Write (stream, attr->header.version_number, 4);
1954     ret += WriteUINT32 (stream, attr->header.font_revision);
1955 
1956     /* save the address of checkSumAdjustment.
1957      * the value is rewrite to computed value after new check-sum-value is
1958      * generated.
1959      */
1960     *check_sum_ptr = stream->size;
1961 
1962     ret += WriteUINT32 (stream, 0);
1963     ret += WriteUINT32 (stream, attr->header.magic_number);
1964     ret += WriteUINT16 (stream, attr->header.flags);
1965     ret += WriteUINT16 (stream, attr->header.units_per_em);
1966     ret += HPDF_Stream_Write (stream, attr->header.created, 8);
1967     ret += HPDF_Stream_Write (stream, attr->header.modified, 8);
1968     ret += WriteINT16 (stream, attr->header.x_min);
1969     ret += WriteINT16 (stream, attr->header.y_min);
1970     ret += WriteINT16 (stream, attr->header.x_max);
1971     ret += WriteINT16 (stream, attr->header.y_max);
1972     ret += WriteUINT16 (stream, attr->header.mac_style);
1973     ret += WriteUINT16 (stream, attr->header.lowest_rec_ppem);
1974     ret += WriteINT16 (stream, attr->header.font_direction_hint);
1975     ret += WriteINT16 (stream, attr->header.index_to_loc_format);
1976     ret += WriteINT16 (stream, attr->header.glyph_data_format);
1977 
1978     if (ret != HPDF_OK)
1979         return HPDF_Error_GetCode (fontdef->error);
1980 
1981     return HPDF_OK;
1982 }
1983 
1984 
1985 HPDF_STATUS
HPDF_TTFontDef_SaveFontData(HPDF_FontDef fontdef,HPDF_Stream stream)1986 HPDF_TTFontDef_SaveFontData  (HPDF_FontDef   fontdef,
1987                               HPDF_Stream    stream)
1988 {
1989     HPDF_TTFontDefAttr attr = (HPDF_TTFontDefAttr)fontdef->attr;
1990     HPDF_TTFTable tmp_tbl[HPDF_REQUIRED_TAGS_COUNT];
1991     HPDF_Stream tmp_stream;
1992     HPDF_UINT32 *new_offsets;
1993     HPDF_UINT i;
1994     HPDF_UINT32 check_sum_ptr = 0;
1995     HPDF_STATUS ret;
1996     HPDF_UINT32 offset_base;
1997     HPDF_UINT32 tmp_check_sum = 0xB1B0AFBA;
1998     HPDF_TTFTable emptyTable;
1999     emptyTable.length = 0;
2000     emptyTable.offset = 0;
2001 
2002     HPDF_PTRACE ((" SaveFontData\n"));
2003 
2004     ret = WriteUINT32 (stream, attr->offset_tbl.sfnt_version);
2005     ret += WriteUINT16 (stream, HPDF_REQUIRED_TAGS_COUNT);
2006     ret += WriteUINT16 (stream, attr->offset_tbl.search_range);
2007     ret += WriteUINT16 (stream, attr->offset_tbl.entry_selector);
2008     ret += WriteUINT16 (stream, attr->offset_tbl.range_shift);
2009 
2010     if (ret != HPDF_OK)
2011         return HPDF_Error_GetCode (fontdef->error);
2012 
2013     tmp_stream = HPDF_MemStream_New (fontdef->mmgr, HPDF_STREAM_BUF_SIZ);
2014     if (!tmp_stream)
2015         return HPDF_Error_GetCode (fontdef->error);
2016 
2017     offset_base = 12 + 16 * HPDF_REQUIRED_TAGS_COUNT;
2018 
2019     new_offsets = HPDF_GetMem (fontdef->mmgr,
2020             sizeof (HPDF_UINT32) * (attr->num_glyphs + 1));
2021     if (!new_offsets) {
2022         HPDF_Stream_Free (tmp_stream);
2023         return HPDF_Error_GetCode (fontdef->error);
2024     }
2025 
2026     for (i = 0; i < HPDF_REQUIRED_TAGS_COUNT; i++) {
2027         HPDF_TTFTable *tbl = FindTable (fontdef, REQUIRED_TAGS[i]);
2028         HPDF_UINT32 length;
2029         HPDF_UINT new_offset;
2030         HPDF_UINT32 *poffset;
2031         HPDF_UINT32 value;
2032 
2033 	if (!tbl) {
2034 	    tbl = &emptyTable;
2035 	    HPDF_MemCpy((HPDF_BYTE *)tbl->tag,
2036 			(const HPDF_BYTE *)REQUIRED_TAGS[i], 4);
2037 	}
2038 
2039         if (!tbl) {
2040             ret = HPDF_SetError (fontdef->error, HPDF_TTF_MISSING_TABLE, i);
2041             goto Exit;
2042         }
2043 
2044         ret = HPDF_Stream_Seek (attr->stream, tbl->offset, HPDF_SEEK_SET);
2045         if (ret != HPDF_OK)
2046             goto Exit;
2047 
2048         length = tbl->length;
2049         new_offset = tmp_stream->size;
2050 
2051         if (HPDF_MemCmp ((HPDF_BYTE *)tbl->tag, (HPDF_BYTE *)"head", 4) == 0) {
2052             ret = WriteHeader (fontdef, tmp_stream, &check_sum_ptr);
2053         } else if (HPDF_MemCmp ((HPDF_BYTE *)tbl->tag, (HPDF_BYTE *)"glyf", 4) == 0) {
2054             ret = RecreateGLYF (fontdef, new_offsets, tmp_stream);
2055         } else if (HPDF_MemCmp ((HPDF_BYTE *)tbl->tag, (HPDF_BYTE *)"loca", 4) == 0) {
2056             HPDF_UINT j;
2057 
2058             HPDF_MemSet (&value, 0, 4);
2059             poffset = new_offsets;
2060 
2061             if (attr->header.index_to_loc_format == 0) {
2062                 for (j = 0; j <= attr->num_glyphs; j++) {
2063                     ret += WriteUINT16 (tmp_stream, (HPDF_UINT16)*poffset);
2064                     poffset++;
2065                 }
2066             } else {
2067                 for (j = 0; j <= attr->num_glyphs; j++) {
2068                     ret += WriteUINT32 (tmp_stream, *poffset);
2069                     poffset++;
2070                 }
2071             }
2072         } else if (HPDF_MemCmp ((HPDF_BYTE *)tbl->tag, (HPDF_BYTE *)"name", 4) == 0) {
2073             ret = RecreateName (fontdef, tmp_stream);
2074         } else {
2075             HPDF_UINT size = 4;
2076 
2077             while (length > 4) {
2078                 value = 0;
2079                 size = 4;
2080                 ret = HPDF_Stream_Read (attr->stream, (HPDF_BYTE *)&value, &size);
2081                 ret += HPDF_Stream_Write (tmp_stream, (HPDF_BYTE *)&value, size);
2082                 length -= 4;
2083             }
2084 
2085             value = 0;
2086             size = length;
2087             ret += HPDF_Stream_Read (attr->stream, (HPDF_BYTE *)&value, &size);
2088             ret += HPDF_Stream_Write (tmp_stream, (HPDF_BYTE *)&value, size);
2089         }
2090 
2091         tmp_tbl[i].offset = new_offset;
2092         tmp_tbl[i].length = tmp_stream->size - new_offset;
2093 
2094         if (ret != HPDF_OK)
2095             goto Exit;
2096     }
2097 
2098     /* recalcurate checksum */
2099     for (i = 0; i < HPDF_REQUIRED_TAGS_COUNT; i++) {
2100         HPDF_TTFTable tbl = tmp_tbl[i];
2101         HPDF_UINT32 buf;
2102         HPDF_UINT length = tbl.length;
2103 
2104         HPDF_PTRACE((" SaveFontData() tag[%s] length=%u\n",
2105                 REQUIRED_TAGS[i], length));
2106 
2107         if ((ret = HPDF_Stream_Seek (tmp_stream, tbl.offset, HPDF_SEEK_SET))
2108                 != HPDF_OK)
2109             break;
2110 
2111         tbl.check_sum = 0;
2112         while (length > 0) {
2113             HPDF_UINT rlen = (length > 4) ? 4 : length;
2114             buf = 0;
2115             if ((ret = HPDF_Stream_Read (tmp_stream, (HPDF_BYTE *)&buf, &rlen))
2116                     != HPDF_OK)
2117                 break;
2118 
2119             UINT32Swap (&buf);
2120             tbl.check_sum += buf;
2121             length -= rlen;
2122         }
2123 
2124         if (ret != HPDF_OK)
2125             break;
2126 
2127         HPDF_PTRACE((" SaveFontData tag[%s] check-sum=%u offset=%u\n",
2128                     REQUIRED_TAGS[i], (HPDF_UINT)tbl.check_sum,
2129                     (HPDF_UINT)tbl.offset));
2130 
2131         ret += HPDF_Stream_Write (stream, (HPDF_BYTE *)REQUIRED_TAGS[i], 4);
2132         ret += WriteUINT32 (stream, tbl.check_sum);
2133         tbl.offset += offset_base;
2134         ret += WriteUINT32 (stream, tbl.offset);
2135         ret += WriteUINT32 (stream, tbl.length);
2136 
2137         if (ret != HPDF_OK)
2138             break;
2139     }
2140 
2141     if (ret != HPDF_OK)
2142         goto Exit;
2143 
2144     /* calucurate checkSumAdjustment.*/
2145     ret = HPDF_Stream_Seek (tmp_stream, 0, HPDF_SEEK_SET);
2146     if (ret != HPDF_OK)
2147         goto Exit;
2148 
2149     for (;;) {
2150         HPDF_UINT32 buf;
2151         HPDF_UINT siz = sizeof(buf);
2152 
2153         ret = HPDF_Stream_Read (tmp_stream, (HPDF_BYTE *)&buf, &siz);
2154         if (ret != HPDF_OK || siz <= 0) {
2155             if (ret == HPDF_STREAM_EOF)
2156                 ret = HPDF_OK;
2157             break;
2158         }
2159 
2160         UINT32Swap (&buf);
2161         tmp_check_sum -= buf;
2162     }
2163 
2164     if (ret != HPDF_OK)
2165         goto Exit;
2166 
2167     HPDF_PTRACE((" SaveFontData new checkSumAdjustment=%u\n",
2168                 (HPDF_UINT)tmp_check_sum));
2169 
2170     UINT32Swap (&tmp_check_sum);
2171 
2172     ret = HPDF_Stream_Seek (tmp_stream, check_sum_ptr, HPDF_SEEK_SET);
2173     if (ret == HPDF_OK) {
2174         ret = HPDF_MemStream_Rewrite (tmp_stream, (HPDF_BYTE *)&tmp_check_sum,
2175             4);
2176     }
2177 
2178     if (ret != HPDF_OK)
2179         goto Exit;
2180 
2181     attr->length1 = tmp_stream->size + offset_base;
2182     ret = HPDF_Stream_WriteToStream (tmp_stream, stream, 0, NULL);
2183 
2184     goto Exit;
2185 
2186 Exit:
2187     HPDF_FreeMem (fontdef->mmgr, new_offsets);
2188     HPDF_Stream_Free (tmp_stream);
2189     return ret;
2190 }
2191 
2192 void
HPDF_TTFontDef_SetTagName(HPDF_FontDef fontdef,char * tag)2193 HPDF_TTFontDef_SetTagName  (HPDF_FontDef   fontdef,
2194                             char     *tag)
2195 {
2196     HPDF_TTFontDefAttr attr = (HPDF_TTFontDefAttr)fontdef->attr;
2197     char buf[HPDF_LIMIT_MAX_NAME_LEN + 1];
2198     HPDF_UINT i;
2199 
2200     HPDF_PTRACE ((" HPDF_TTFontDef_SetTagName\n"));
2201 
2202     if (HPDF_StrLen (tag, HPDF_LIMIT_MAX_NAME_LEN) != HPDF_TTF_FONT_TAG_LEN)
2203         return;
2204 
2205     HPDF_MemCpy ((HPDF_BYTE *)attr->tag_name, (HPDF_BYTE *)tag, HPDF_TTF_FONT_TAG_LEN);
2206     attr->tag_name[HPDF_TTF_FONT_TAG_LEN] = '+';
2207 
2208     for (i = 0; i < HPDF_TTF_FONT_TAG_LEN + 1; i++) {
2209         attr->tag_name2[i * 2] = 0x00;
2210         attr->tag_name2[i * 2 + 1] = attr->tag_name[i];
2211     }
2212 
2213     HPDF_MemSet (buf, 0, HPDF_LIMIT_MAX_NAME_LEN + 1);
2214     HPDF_MemCpy ((HPDF_BYTE *)buf, (HPDF_BYTE *)attr->tag_name, HPDF_TTF_FONT_TAG_LEN + 1);
2215     HPDF_MemCpy ((HPDF_BYTE *)buf + HPDF_TTF_FONT_TAG_LEN + 1, (HPDF_BYTE *)fontdef->base_font, HPDF_LIMIT_MAX_NAME_LEN - HPDF_TTF_FONT_TAG_LEN - 1);
2216 
2217     HPDF_MemCpy ((HPDF_BYTE *)attr->base_font, (HPDF_BYTE *)buf, HPDF_LIMIT_MAX_NAME_LEN + 1);
2218 }
2219 
2220 /*
2221 int
2222 PdfTTFontDef::GetNameAttr(unsigned char* buf, HPDF_UINT name_id,
2223         HPDF_UINT platform_id, HPDF_UINT lang_id, HPDF_UINT max_len)
2224 
2225 
2226 */
2227 
2228 static HPDF_TTFTable*
FindTable(HPDF_FontDef fontdef,const char * tag)2229 FindTable (HPDF_FontDef      fontdef,
2230            const char  *tag)
2231 {
2232     HPDF_TTFontDefAttr attr = (HPDF_TTFontDefAttr)fontdef->attr;
2233     HPDF_TTFTable* tbl = attr->offset_tbl.table;
2234     HPDF_UINT i;
2235 
2236     for (i = 0; i < attr->offset_tbl.num_tables; i++, tbl++) {
2237         if (HPDF_MemCmp ((HPDF_BYTE *)tbl->tag, (HPDF_BYTE *)tag, 4) == 0) {
2238             HPDF_PTRACE((" FindTable find table[%c%c%c%c]\n",
2239                         tbl->tag[0], tbl->tag[1], tbl->tag[2], tbl->tag[3]));
2240             return tbl;
2241         }
2242     }
2243 
2244     return NULL;
2245 }
2246 
2247 static void
UINT32Swap(HPDF_UINT32 * value)2248 UINT32Swap (HPDF_UINT32  *value)
2249 {
2250     HPDF_BYTE b[4];
2251 
2252     HPDF_MemCpy (b, (HPDF_BYTE *)value, 4);
2253     *value = (HPDF_UINT32)((HPDF_UINT32)b[0] << 24 |
2254              (HPDF_UINT32)b[1] << 16 |
2255              (HPDF_UINT32)b[2] << 8 |
2256              (HPDF_UINT32)b[3]);
2257 }
2258 
2259 static void
UINT16Swap(HPDF_UINT16 * value)2260 UINT16Swap (HPDF_UINT16  *value)
2261 {
2262     HPDF_BYTE b[2];
2263 
2264     HPDF_MemCpy (b, (HPDF_BYTE *)value, 2);
2265     *value = (HPDF_UINT16)((HPDF_UINT16)b[0] << 8 | (HPDF_UINT16)b[1]);
2266 }
2267 
2268 static void
INT16Swap(HPDF_INT16 * value)2269 INT16Swap (HPDF_INT16  *value)
2270 {
2271     HPDF_BYTE b[2];
2272 
2273     HPDF_MemCpy (b, (HPDF_BYTE *)value, 2);
2274     *value = (HPDF_INT16)((HPDF_INT16)b[0] << 8 | (HPDF_INT16)b[1]);
2275 }
2276