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
28static 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
45static void
46FreeFunc (HPDF_FontDef fontdef);
47
48
49static HPDF_STATUS
50LoadFontData (HPDF_FontDef fontdef,
51 HPDF_Stream stream,
52 HPDF_BOOL embedding,
53 HPDF_UINT offset);
54
55
56static HPDF_STATUS
57LoadFontData2 (HPDF_FontDef fontdef,
58 HPDF_Stream stream,
59 HPDF_UINT index,
60 HPDF_BOOL embedding);
61
62
63static void
64InitAttr (HPDF_FontDef fontdef);
65
66
67static HPDF_STATUS
68GetUINT32 (HPDF_Stream stream,
69 HPDF_UINT32 *value);
70
71
72static HPDF_STATUS
73GetUINT16 (HPDF_Stream stream,
74 HPDF_UINT16 *value);
75
76
77static HPDF_STATUS
78GetINT16 (HPDF_Stream stream,
79 HPDF_INT16 *value);
80
81
82static HPDF_STATUS
83WriteUINT32 (HPDF_Stream stream,
84 HPDF_UINT32 value);
85
86
87static HPDF_STATUS
88WriteUINT16 (HPDF_Stream stream,
89 HPDF_UINT16 value);
90
91
92static HPDF_STATUS
93WriteINT16 (HPDF_Stream stream,
94 HPDF_INT16 value);
95
96
97static void
98UINT32Swap (HPDF_UINT32 *value);
99
100
101static void
102UINT16Swap (HPDF_UINT16 *value);
103
104
105static void
106INT16Swap (HPDF_INT16 *value);
107
108
109static HPDF_STATUS
110LoadTTFTable (HPDF_FontDef fontdef);
111
112
113static HPDF_STATUS
114ParseHead (HPDF_FontDef fontdef);
115
116
117static HPDF_STATUS
118ParseMaxp (HPDF_FontDef fontdef);
119
120
121static HPDF_STATUS
122ParseHhea (HPDF_FontDef fontdef);
123
124
125static HPDF_STATUS
126ParseCMap (HPDF_FontDef fontdef);
127
128
129static HPDF_STATUS
130ParseCMAP_format0 (HPDF_FontDef fontdef,
131 HPDF_UINT32 offset);
132
133
134static HPDF_STATUS
135ParseCMAP_format4 (HPDF_FontDef fontdef,
136 HPDF_UINT32 offset);
137
138
139static HPDF_STATUS
140ParseHmtx (HPDF_FontDef fontdef);
141
142
143static HPDF_STATUS
144ParseLoca (HPDF_FontDef fontdef);
145
146
147static HPDF_STATUS
148LoadUnicodeName (HPDF_Stream stream,
149 HPDF_UINT offset,
150 HPDF_UINT len,
151 char *buf);
152
153static HPDF_STATUS
154ParseName (HPDF_FontDef fontdef);
155
156
157static HPDF_STATUS
158ParseOS2 (HPDF_FontDef fontdef);
159
160
161static HPDF_TTFTable*
162FindTable (HPDF_FontDef fontdef,
163 const char *tag);
164
165
166static void
167CleanFunc (HPDF_FontDef fontdef);
168
169
170static HPDF_STATUS
171CheckCompositGryph (HPDF_FontDef fontdef,
172 HPDF_UINT16 gid);
173
174
175/*---------------------------------------------------------------------------*/
176/*---------------------------------------------------------------------------*/
177
178static void
179FreeFunc (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
193static void
194CleanFunc (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
203static void
204InitAttr (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
248HPDF_FontDef
249HPDF_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
285HPDF_FontDef
286HPDF_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
312HPDF_FontDef
313HPDF_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
341static void
342DumpTable (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
408static HPDF_STATUS
409LoadFontData (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
481static HPDF_STATUS
482LoadFontData2 (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
535HPDF_Box
536HPDF_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
585static HPDF_STATUS
586GetUINT32 (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
604static HPDF_STATUS
605GetUINT16 (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
623static HPDF_STATUS
624GetINT16 (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
641static HPDF_STATUS
642WriteUINT32 (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
658static HPDF_STATUS
659WriteUINT16 (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
675static HPDF_STATUS
676WriteINT16 (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
692HPDF_STATUS
693LoadTTFTable (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
744static HPDF_STATUS
745ParseHead (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
801static HPDF_STATUS
802ParseMaxp (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
826static HPDF_STATUS
827ParseHhea (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
867static HPDF_STATUS
868ParseCMap (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
960static HPDF_STATUS
961ParseCMAP_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
1010static HPDF_STATUS
1011ParseCMAP_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
1129HPDF_UINT16
1130HPDF_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
1189HPDF_INT16
1190HPDF_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
1222static HPDF_STATUS
1223CheckCompositGryph (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
1308HPDF_INT16
1309HPDF_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
1337static HPDF_STATUS
1338ParseHmtx (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
1395static HPDF_STATUS
1396ParseLoca (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
1472static HPDF_STATUS
1473LoadUnicodeName (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
1503static HPDF_STATUS
1504ParseName (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
1675static HPDF_STATUS
1676ParseOS2 (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
1771static HPDF_STATUS
1772RecreateGLYF (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
1846static HPDF_STATUS
1847RecreateName (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
1943static HPDF_STATUS
1944WriteHeader (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
1985HPDF_STATUS
1986HPDF_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
2186Exit:
2187 HPDF_FreeMem (fontdef->mmgr, new_offsets);
2188 HPDF_Stream_Free (tmp_stream);
2189 return ret;
2190}
2191
2192void
2193HPDF_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/*
2221int
2222PdfTTFontDef::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
2228static HPDF_TTFTable*
2229FindTable (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
2247static void
2248UINT32Swap (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
2259static void
2260UINT16Swap (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
2268static void
2269INT16Swap (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