OSDN Git Service

binding with libharu.
[putex/putex.git] / src / texsourc / lib / libhpdf / src / hpdf_fontdef_tt.c
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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_UINT len;
1682
1683     HPDF_PTRACE ((" ParseOS2\n"));
1684
1685     if (!tbl)
1686         return HPDF_SetError (fontdef->error, HPDF_TTF_MISSING_TABLE, 0);
1687
1688     ret = HPDF_Stream_Seek (attr->stream, tbl->offset + 8, HPDF_SEEK_SET);
1689     if (ret != HPDF_OK)
1690         return ret;
1691
1692     /* check whether the font is allowed to be embedded. */
1693     if ((ret = GetUINT16 (attr->stream, &attr->fs_type)) != HPDF_OK)
1694         return ret;
1695
1696     if (attr->fs_type  & (0x0002 | 0x0100 | 0x0200) && attr->embedding)
1697         return HPDF_SetError (fontdef->error, HPDF_TTF_CANNOT_EMBEDDING_FONT,
1698                 0);
1699
1700     if ((ret = HPDF_Stream_Seek (attr->stream, tbl->offset + 20, HPDF_SEEK_SET))
1701             != HPDF_OK)
1702         return ret;
1703
1704     len = 12;
1705     if ((ret = HPDF_Stream_Read (attr->stream, attr->panose, &len)) != HPDF_OK)
1706         return ret;
1707
1708     HPDF_PTRACE((" ParseOS2 PANOSE=%u-%u "
1709             "%02X-%02X-%02X-%02X-%02X-%02X-%02X-%02X-%02X-%02X\n",
1710         attr->panose[0], attr->panose[1], attr->panose[2], attr->panose[3],
1711         attr->panose[4], attr->panose[5], attr->panose[6], attr->panose[7],
1712         attr->panose[8], attr->panose[9], attr->panose[10], attr->panose[11]));
1713
1714     if (attr->panose[0] == 1 || attr->panose[0] == 4)
1715         fontdef->flags = fontdef->flags | HPDF_FONT_SERIF;
1716
1717     /* get ulCodePageRange1 */
1718     if ((ret = HPDF_Stream_Seek (attr->stream, 78, HPDF_SEEK_CUR)) != HPDF_OK)
1719         return ret;
1720
1721     if ((ret = GetUINT32 (attr->stream, &attr->code_page_range1)) != HPDF_OK)
1722         return ret;
1723
1724     if ((ret = GetUINT32 (attr->stream, &attr->code_page_range2)) != HPDF_OK)
1725         return ret;
1726
1727     HPDF_PTRACE(("  ParseOS2 CodePageRange1=%08X CodePageRange2=%08X\n",
1728                 (HPDF_UINT)attr->code_page_range1,
1729                 (HPDF_UINT)attr->code_page_range2));
1730
1731     return HPDF_OK;
1732 }
1733
1734
1735 static HPDF_STATUS
1736 RecreateGLYF  (HPDF_FontDef   fontdef,
1737                HPDF_UINT32   *new_offsets,
1738                HPDF_Stream    stream)
1739 {
1740     HPDF_UINT32 save_offset = 0;
1741     HPDF_UINT32 start_offset = stream->size;
1742     HPDF_TTFontDefAttr attr = (HPDF_TTFontDefAttr)fontdef->attr;
1743     HPDF_STATUS ret;
1744     HPDF_INT i;
1745
1746     HPDF_PTRACE ((" RecreateGLYF\n"));
1747
1748     for (i = 0; i < attr->num_glyphs; i++) {
1749         HPDF_BYTE buf[HPDF_STREAM_BUF_SIZ];
1750
1751         if (attr->glyph_tbl.flgs[i] == 1) {
1752             HPDF_UINT offset = attr->glyph_tbl.offsets[i];
1753             HPDF_UINT len = attr->glyph_tbl.offsets[i + 1] - offset;
1754
1755             new_offsets[i] = stream->size - start_offset;
1756             if (attr->header.index_to_loc_format == 0) {
1757                 new_offsets[i] /= 2;
1758                 len *= 2;
1759             }
1760
1761             HPDF_PTRACE((" RecreateGLYF[%u] move from [%u] to [%u]\n", i,
1762                         (HPDF_UINT)attr->glyph_tbl.base_offset + offset,
1763                         (HPDF_UINT)new_offsets[i]));
1764
1765             if (attr->header.index_to_loc_format == 0)
1766                 offset *= 2;
1767
1768             offset += attr->glyph_tbl.base_offset;
1769
1770             if ((ret = HPDF_Stream_Seek (attr->stream, offset, HPDF_SEEK_SET))
1771                     != HPDF_OK)
1772                 return ret;
1773
1774             while (len > 0) {
1775                 HPDF_UINT tmp_len =
1776                     (len > HPDF_STREAM_BUF_SIZ) ? HPDF_STREAM_BUF_SIZ : len;
1777
1778                 HPDF_MemSet (buf, 0, tmp_len);
1779
1780                 if ((ret = HPDF_Stream_Read (attr->stream, buf, &tmp_len))
1781                         != HPDF_OK)
1782                     return ret;
1783
1784                 if ((ret = HPDF_Stream_Write (stream, buf, tmp_len)) !=
1785                         HPDF_OK)
1786                     return ret;
1787
1788                 len -= tmp_len;
1789             }
1790
1791             save_offset = stream->size - start_offset;
1792             if (attr->header.index_to_loc_format == 0)
1793                 save_offset /= 2;
1794         } else {
1795             new_offsets[i] = save_offset;
1796         }
1797     }
1798
1799     new_offsets[attr->num_glyphs] = save_offset;
1800
1801 #ifdef DEBUG
1802     for (i = 0; i <= attr->num_glyphs; i++) {
1803         HPDF_PTRACE((" RecreateGLYF[%u] offset=%u\n", i, new_offsets[i]));
1804     }
1805 #endif
1806
1807     return HPDF_OK;
1808 }
1809
1810 static HPDF_STATUS
1811 RecreateName  (HPDF_FontDef   fontdef,
1812                HPDF_Stream    stream)
1813 {
1814     HPDF_TTFontDefAttr attr = (HPDF_TTFontDefAttr)fontdef->attr;
1815     HPDF_TTFTable *tbl = FindTable (fontdef, "name");
1816     HPDF_STATUS ret = HPDF_OK;
1817     HPDF_UINT i;
1818     HPDF_TTF_NameRecord *name_rec;
1819     HPDF_Stream tmp_stream = HPDF_MemStream_New (fontdef->mmgr,
1820                 HPDF_STREAM_BUF_SIZ);
1821
1822     HPDF_PTRACE ((" RecreateName\n"));
1823
1824     if (!tmp_stream)
1825         return HPDF_Error_GetCode (fontdef->error);
1826
1827     ret += WriteUINT16 (stream, attr->name_tbl.format);
1828     ret += WriteUINT16 (stream, attr->name_tbl.count);
1829     ret += WriteUINT16 (stream, attr->name_tbl.string_offset);
1830
1831     if (ret != HPDF_OK) {
1832         HPDF_Stream_Free (tmp_stream);
1833         return HPDF_Error_GetCode (fontdef->error);
1834     }
1835
1836     name_rec = attr->name_tbl.name_records;
1837     for (i = 0; i < attr->name_tbl.count; i++) {
1838         HPDF_UINT name_len = name_rec->length;
1839         HPDF_BYTE buf[HPDF_STREAM_BUF_SIZ];
1840         HPDF_UINT tmp_len = name_len;
1841         HPDF_UINT offset = tbl->offset + attr->name_tbl.string_offset +
1842                 name_rec->offset;
1843         HPDF_UINT rec_offset = tmp_stream->size;
1844
1845         /* add suffix to font-name. */
1846         if (name_rec->name_id == 1 || name_rec->name_id == 4) {
1847             if (name_rec->platform_id == 0 || name_rec->platform_id == 3) {
1848                 ret += HPDF_Stream_Write (tmp_stream, (HPDF_BYTE *)attr->tag_name2,
1849                         sizeof(attr->tag_name2));
1850                 name_len += sizeof(attr->tag_name2);
1851             } else {
1852                 ret += HPDF_Stream_Write (tmp_stream, (HPDF_BYTE *)attr->tag_name,
1853                         sizeof(attr->tag_name));
1854                 name_len += sizeof(attr->tag_name);
1855             }
1856         }
1857
1858         ret += WriteUINT16 (stream, name_rec->platform_id);
1859         ret += WriteUINT16 (stream, name_rec->encoding_id);
1860         ret += WriteUINT16 (stream, name_rec->language_id);
1861         ret += WriteUINT16 (stream, name_rec->name_id);
1862         ret += WriteUINT16 (stream, (HPDF_UINT16)name_len);
1863         ret += WriteUINT16 (stream, (HPDF_UINT16)rec_offset);
1864
1865         ret += HPDF_Stream_Seek (attr->stream, offset, HPDF_SEEK_SET);
1866
1867         if (ret != HPDF_OK) {
1868             HPDF_Stream_Free (tmp_stream);
1869             return HPDF_Error_GetCode (fontdef->error);
1870         }
1871
1872         while (tmp_len > 0) {
1873             HPDF_UINT len = (tmp_len > HPDF_STREAM_BUF_SIZ) ?
1874                     HPDF_STREAM_BUF_SIZ : tmp_len;
1875
1876             if ((ret = HPDF_Stream_Read (attr->stream, buf, &len)) != HPDF_OK) {
1877                 HPDF_Stream_Free (tmp_stream);
1878                 return ret;
1879             }
1880
1881             if ((ret = HPDF_Stream_Write (tmp_stream, buf, len)) != HPDF_OK) {
1882                 HPDF_Stream_Free (tmp_stream);
1883                 return ret;
1884             }
1885
1886             tmp_len -= len;
1887         }
1888
1889         HPDF_PTRACE((" RecreateNAME name_rec[%u] platform_id=%u "
1890                         "encoding_id=%u language_id=%u name_rec->name_id=%u "
1891                         "length=%u offset=%u\n", i, name_rec->platform_id,
1892                         name_rec->encoding_id, name_rec->language_id,
1893                         name_rec->name_id, name_len, rec_offset));
1894
1895         name_rec++;
1896     }
1897
1898     ret = HPDF_Stream_WriteToStream (tmp_stream, stream,
1899                 HPDF_STREAM_FILTER_NONE, NULL);
1900
1901     HPDF_Stream_Free (tmp_stream);
1902
1903     return ret;
1904 }
1905
1906
1907 static HPDF_STATUS
1908 WriteHeader (HPDF_FontDef   fontdef,
1909              HPDF_Stream    stream,
1910              HPDF_UINT32   *check_sum_ptr)
1911 {
1912     HPDF_TTFontDefAttr attr = (HPDF_TTFontDefAttr)fontdef->attr;
1913     HPDF_STATUS ret = HPDF_OK;
1914
1915     HPDF_PTRACE ((" WriteHeader\n"));
1916
1917     ret += HPDF_Stream_Write (stream, attr->header.version_number, 4);
1918     ret += WriteUINT32 (stream, attr->header.font_revision);
1919
1920     /* save the address of checkSumAdjustment.
1921      * the value is rewrite to computed value after new check-sum-value is
1922      * generated.
1923      */
1924     *check_sum_ptr = stream->size;
1925
1926     ret += WriteUINT32 (stream, 0);
1927     ret += WriteUINT32 (stream, attr->header.magic_number);
1928     ret += WriteUINT16 (stream, attr->header.flags);
1929     ret += WriteUINT16 (stream, attr->header.units_per_em);
1930     ret += HPDF_Stream_Write (stream, attr->header.created, 8);
1931     ret += HPDF_Stream_Write (stream, attr->header.modified, 8);
1932     ret += WriteINT16 (stream, attr->header.x_min);
1933     ret += WriteINT16 (stream, attr->header.y_min);
1934     ret += WriteINT16 (stream, attr->header.x_max);
1935     ret += WriteINT16 (stream, attr->header.y_max);
1936     ret += WriteUINT16 (stream, attr->header.mac_style);
1937     ret += WriteUINT16 (stream, attr->header.lowest_rec_ppem);
1938     ret += WriteINT16 (stream, attr->header.font_direction_hint);
1939     ret += WriteINT16 (stream, attr->header.index_to_loc_format);
1940     ret += WriteINT16 (stream, attr->header.glyph_data_format);
1941
1942     if (ret != HPDF_OK)
1943         return HPDF_Error_GetCode (fontdef->error);
1944
1945     return HPDF_OK;
1946 }
1947
1948
1949 HPDF_STATUS
1950 HPDF_TTFontDef_SaveFontData  (HPDF_FontDef   fontdef,
1951                               HPDF_Stream    stream)
1952 {
1953     HPDF_TTFontDefAttr attr = (HPDF_TTFontDefAttr)fontdef->attr;
1954     HPDF_TTFTable tmp_tbl[HPDF_REQUIRED_TAGS_COUNT];
1955     HPDF_Stream tmp_stream;
1956     HPDF_UINT32 *new_offsets;
1957     HPDF_UINT i;
1958     HPDF_UINT32 check_sum_ptr = 0;
1959     HPDF_STATUS ret;
1960     HPDF_UINT32 offset_base;
1961     HPDF_UINT32 tmp_check_sum = 0xB1B0AFBA;
1962
1963     HPDF_PTRACE ((" SaveFontData\n"));
1964
1965     ret = WriteUINT32 (stream, attr->offset_tbl.sfnt_version);
1966     ret += WriteUINT16 (stream, HPDF_REQUIRED_TAGS_COUNT);
1967     ret += WriteUINT16 (stream, attr->offset_tbl.search_range);
1968     ret += WriteUINT16 (stream, attr->offset_tbl.entry_selector);
1969     ret += WriteUINT16 (stream, attr->offset_tbl.range_shift);
1970
1971     if (ret != HPDF_OK)
1972         return HPDF_Error_GetCode (fontdef->error);
1973
1974     tmp_stream = HPDF_MemStream_New (fontdef->mmgr, HPDF_STREAM_BUF_SIZ);
1975     if (!tmp_stream)
1976         return HPDF_Error_GetCode (fontdef->error);
1977
1978     offset_base = 12 + 16 * HPDF_REQUIRED_TAGS_COUNT;
1979
1980     new_offsets = HPDF_GetMem (fontdef->mmgr,
1981             sizeof (HPDF_UINT32) * (attr->num_glyphs + 1));
1982     if (!new_offsets) {
1983         HPDF_Stream_Free (tmp_stream);
1984         return HPDF_Error_GetCode (fontdef->error);
1985     }
1986
1987     for (i = 0; i < HPDF_REQUIRED_TAGS_COUNT; i++) {
1988         HPDF_TTFTable *tbl = FindTable (fontdef, REQUIRED_TAGS[i]);
1989         HPDF_UINT32 length;
1990         HPDF_UINT new_offset;
1991         HPDF_UINT32 *poffset;
1992         HPDF_UINT32 value;
1993
1994         if (!tbl) {
1995             ret = HPDF_SetError (fontdef->error, HPDF_TTF_MISSING_TABLE, i);
1996             goto Exit;
1997         }
1998
1999         ret = HPDF_Stream_Seek (attr->stream, tbl->offset, HPDF_SEEK_SET);
2000         if (ret != HPDF_OK)
2001             goto Exit;
2002
2003         length = tbl->length;
2004         new_offset = tmp_stream->size;
2005
2006         if (HPDF_MemCmp ((HPDF_BYTE *)tbl->tag, (HPDF_BYTE *)"head", 4) == 0) {
2007             ret = WriteHeader (fontdef, tmp_stream, &check_sum_ptr);
2008         } else if (HPDF_MemCmp ((HPDF_BYTE *)tbl->tag, (HPDF_BYTE *)"glyf", 4) == 0) {
2009             ret = RecreateGLYF (fontdef, new_offsets, tmp_stream);
2010         } else if (HPDF_MemCmp ((HPDF_BYTE *)tbl->tag, (HPDF_BYTE *)"loca", 4) == 0) {
2011             HPDF_UINT j;
2012
2013             HPDF_MemSet (&value, 0, 4);
2014             poffset = new_offsets;
2015
2016             if (attr->header.index_to_loc_format == 0) {
2017                 for (j = 0; j <= attr->num_glyphs; j++) {
2018                     ret += WriteUINT16 (tmp_stream, (HPDF_UINT16)*poffset);
2019                     poffset++;
2020                 }
2021             } else {
2022                 for (j = 0; j <= attr->num_glyphs; j++) {
2023                     ret += WriteUINT32 (tmp_stream, *poffset);
2024                     poffset++;
2025                 }
2026             }
2027         } else if (HPDF_MemCmp ((HPDF_BYTE *)tbl->tag, (HPDF_BYTE *)"name", 4) == 0) {
2028             ret = RecreateName (fontdef, tmp_stream);
2029         } else {
2030             HPDF_UINT size = 4;
2031
2032             while (length > 4) {
2033                 value = 0;
2034                 size = 4;
2035                 ret = HPDF_Stream_Read (attr->stream, (HPDF_BYTE *)&value, &size);
2036                 ret += HPDF_Stream_Write (tmp_stream, (HPDF_BYTE *)&value, size);
2037                 length -= 4;
2038             }
2039
2040             value = 0;
2041             size = length;
2042             ret += HPDF_Stream_Read (attr->stream, (HPDF_BYTE *)&value, &size);
2043             ret += HPDF_Stream_Write (tmp_stream, (HPDF_BYTE *)&value, size);
2044         }
2045
2046         tmp_tbl[i].offset = new_offset;
2047         tmp_tbl[i].length = tmp_stream->size - new_offset;
2048
2049         if (ret != HPDF_OK)
2050             goto Exit;
2051     }
2052
2053     /* recalcurate checksum */
2054     for (i = 0; i < HPDF_REQUIRED_TAGS_COUNT; i++) {
2055         HPDF_TTFTable tbl = tmp_tbl[i];
2056         HPDF_UINT32 buf;
2057         HPDF_UINT length = tbl.length;
2058
2059         HPDF_PTRACE((" SaveFontData() tag[%s] length=%u\n",
2060                 REQUIRED_TAGS[i], length));
2061
2062         if ((ret = HPDF_Stream_Seek (tmp_stream, tbl.offset, HPDF_SEEK_SET))
2063                 != HPDF_OK)
2064             break;
2065
2066         tbl.check_sum = 0;
2067         while (length > 0) {
2068             HPDF_UINT rlen = (length > 4) ? 4 : length;
2069             buf = 0;
2070             if ((ret = HPDF_Stream_Read (tmp_stream, (HPDF_BYTE *)&buf, &rlen))
2071                     != HPDF_OK)
2072                 break;
2073
2074             UINT32Swap (&buf);
2075             tbl.check_sum += buf;
2076             length -= rlen;
2077         }
2078
2079         if (ret != HPDF_OK)
2080             break;
2081
2082         HPDF_PTRACE((" SaveFontData tag[%s] check-sum=%u offset=%u\n",
2083                     REQUIRED_TAGS[i], (HPDF_UINT)tbl.check_sum,
2084                     (HPDF_UINT)tbl.offset));
2085
2086         ret += HPDF_Stream_Write (stream, (HPDF_BYTE *)REQUIRED_TAGS[i], 4);
2087         ret += WriteUINT32 (stream, tbl.check_sum);
2088         tbl.offset += offset_base;
2089         ret += WriteUINT32 (stream, tbl.offset);
2090         ret += WriteUINT32 (stream, tbl.length);
2091
2092         if (ret != HPDF_OK)
2093             break;
2094     }
2095
2096     if (ret != HPDF_OK)
2097         goto Exit;
2098
2099     /* calucurate checkSumAdjustment.*/
2100     ret = HPDF_Stream_Seek (tmp_stream, 0, HPDF_SEEK_SET);
2101     if (ret != HPDF_OK)
2102         goto Exit;
2103
2104     for (;;) {
2105         HPDF_UINT32 buf;
2106         HPDF_UINT siz = sizeof(buf);
2107
2108         ret = HPDF_Stream_Read (tmp_stream, (HPDF_BYTE *)&buf, &siz);
2109         if (ret != HPDF_OK || siz <= 0) {
2110             if (ret == HPDF_STREAM_EOF)
2111                 ret = HPDF_OK;
2112             break;
2113         }
2114
2115         UINT32Swap (&buf);
2116         tmp_check_sum -= buf;
2117     }
2118
2119     if (ret != HPDF_OK)
2120         goto Exit;
2121
2122     HPDF_PTRACE((" SaveFontData new checkSumAdjustment=%u\n",
2123                 (HPDF_UINT)tmp_check_sum));
2124
2125     UINT32Swap (&tmp_check_sum);
2126
2127     ret = HPDF_Stream_Seek (tmp_stream, check_sum_ptr, HPDF_SEEK_SET);
2128     if (ret == HPDF_OK) {
2129         ret = HPDF_MemStream_Rewrite (tmp_stream, (HPDF_BYTE *)&tmp_check_sum,
2130             4);
2131     }
2132
2133     if (ret != HPDF_OK)
2134         goto Exit;
2135
2136     attr->length1 = tmp_stream->size + offset_base;
2137     ret = HPDF_Stream_WriteToStream (tmp_stream, stream, 0, NULL);
2138
2139     goto Exit;
2140
2141 Exit:
2142     HPDF_FreeMem (fontdef->mmgr, new_offsets);
2143     HPDF_Stream_Free (tmp_stream);
2144     return ret;
2145 }
2146
2147 void
2148 HPDF_TTFontDef_SetTagName  (HPDF_FontDef   fontdef,
2149                             char     *tag)
2150 {
2151     HPDF_TTFontDefAttr attr = (HPDF_TTFontDefAttr)fontdef->attr;
2152     char buf[HPDF_LIMIT_MAX_NAME_LEN + 1];
2153     HPDF_UINT i;
2154
2155     HPDF_PTRACE ((" HPDF_TTFontDef_SetTagName\n"));
2156
2157     if (HPDF_StrLen (tag, HPDF_LIMIT_MAX_NAME_LEN) != HPDF_TTF_FONT_TAG_LEN)
2158         return;
2159
2160     HPDF_MemCpy ((HPDF_BYTE *)attr->tag_name, (HPDF_BYTE *)tag, HPDF_TTF_FONT_TAG_LEN);
2161     attr->tag_name[HPDF_TTF_FONT_TAG_LEN] = '+';
2162
2163     for (i = 0; i < HPDF_TTF_FONT_TAG_LEN + 1; i++) {
2164         attr->tag_name2[i * 2] = 0x00;
2165         attr->tag_name2[i * 2 + 1] = attr->tag_name[i];
2166     }
2167
2168     HPDF_MemSet (buf, 0, HPDF_LIMIT_MAX_NAME_LEN + 1);
2169     HPDF_MemCpy ((HPDF_BYTE *)buf, (HPDF_BYTE *)attr->tag_name, HPDF_TTF_FONT_TAG_LEN + 1);
2170     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);
2171
2172     HPDF_MemCpy ((HPDF_BYTE *)attr->base_font, (HPDF_BYTE *)buf, HPDF_LIMIT_MAX_NAME_LEN + 1);
2173 }
2174
2175 /*
2176 int
2177 PdfTTFontDef::GetNameAttr(unsigned char* buf, HPDF_UINT name_id,
2178         HPDF_UINT platform_id, HPDF_UINT lang_id, HPDF_UINT max_len)
2179
2180
2181 */
2182
2183 static HPDF_TTFTable*
2184 FindTable (HPDF_FontDef      fontdef,
2185            const char  *tag)
2186 {
2187     HPDF_TTFontDefAttr attr = (HPDF_TTFontDefAttr)fontdef->attr;
2188     HPDF_TTFTable* tbl = attr->offset_tbl.table;
2189     HPDF_UINT i;
2190
2191     for (i = 0; i < attr->offset_tbl.num_tables; i++, tbl++) {
2192         if (HPDF_MemCmp ((HPDF_BYTE *)tbl->tag, (HPDF_BYTE *)tag, 4) == 0) {
2193             HPDF_PTRACE((" FindTable find table[%c%c%c%c]\n",
2194                         tbl->tag[0], tbl->tag[1], tbl->tag[2], tbl->tag[3]));
2195             return tbl;
2196         }
2197     }
2198
2199     return NULL;
2200 }
2201
2202 static void
2203 UINT32Swap (HPDF_UINT32  *value)
2204 {
2205     HPDF_BYTE b[4];
2206
2207     HPDF_MemCpy (b, (HPDF_BYTE *)value, 4);
2208     *value = (HPDF_UINT32)((HPDF_UINT32)b[0] << 24 |
2209              (HPDF_UINT32)b[1] << 16 |
2210              (HPDF_UINT32)b[2] << 8 |
2211              (HPDF_UINT32)b[3]);
2212 }
2213
2214 static void
2215 UINT16Swap (HPDF_UINT16  *value)
2216 {
2217     HPDF_BYTE b[2];
2218
2219     HPDF_MemCpy (b, (HPDF_BYTE *)value, 2);
2220     *value = (HPDF_UINT16)((HPDF_UINT16)b[0] << 8 | (HPDF_UINT16)b[1]);
2221 }
2222
2223 static void
2224 INT16Swap (HPDF_INT16  *value)
2225 {
2226     HPDF_BYTE b[2];
2227
2228     HPDF_MemCpy (b, (HPDF_BYTE *)value, 2);
2229     *value = (HPDF_INT16)((HPDF_INT16)b[0] << 8 | (HPDF_INT16)b[1]);
2230 }
2231