1/*
2 * << Haru Free PDF Library >> -- hpdf_fontdef_type1.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 */
17
18#include "hpdf_conf.h"
19#include "hpdf_utils.h"
20#include "hpdf_fontdef.h"
21
22static void
23FreeWidth (HPDF_FontDef fontdef);
24
25
26static void
27FreeFunc (HPDF_FontDef fontdef);
28
29
30static const char*
31GetKeyword (const char *src,
32 char *keyword,
33 HPDF_UINT len);
34
35static HPDF_STATUS
36LoadAfm (HPDF_FontDef fontdef,
37 HPDF_Stream stream);
38
39
40static HPDF_STATUS
41LoadFontData (HPDF_FontDef fontdef,
42 HPDF_Stream stream);
43
44
45/*---------------------------------------------------------------------------*/
46
47static void
48FreeWidth (HPDF_FontDef fontdef)
49{
50 HPDF_Type1FontDefAttr attr = (HPDF_Type1FontDefAttr)fontdef->attr;
51
52 HPDF_PTRACE ((" FreeWidth\n"));
53
54 HPDF_FreeMem (fontdef->mmgr, attr->widths);
55 attr->widths = NULL;
56
57 fontdef->valid = HPDF_FALSE;
58}
59
60HPDF_FontDef
61HPDF_Type1FontDef_New (HPDF_MMgr mmgr)
62{
63 HPDF_FontDef fontdef;
64 HPDF_Type1FontDefAttr fontdef_attr;
65
66 HPDF_PTRACE ((" HPDF_Type1FontDef_New\n"));
67
68 if (!mmgr)
69 return NULL;
70
71 fontdef = HPDF_GetMem (mmgr, sizeof(HPDF_FontDef_Rec));
72 if (!fontdef)
73 return NULL;
74
75 HPDF_MemSet (fontdef, 0, sizeof (HPDF_FontDef_Rec));
76 fontdef->sig_bytes = HPDF_FONTDEF_SIG_BYTES;
77 fontdef->mmgr = mmgr;
78 fontdef->error = mmgr->error;
79 fontdef->type = HPDF_FONTDEF_TYPE_TYPE1;
80 fontdef->free_fn = FreeFunc;
81
82 fontdef_attr = HPDF_GetMem (mmgr, sizeof(HPDF_Type1FontDefAttr_Rec));
83 if (!fontdef_attr) {
84 HPDF_FreeMem (fontdef->mmgr, fontdef);
85 return NULL;
86 }
87
88 fontdef->attr = fontdef_attr;
89 HPDF_MemSet ((HPDF_BYTE *)fontdef_attr, 0, sizeof(HPDF_Type1FontDefAttr_Rec));
90 fontdef->flags = HPDF_FONT_STD_CHARSET;
91
92 return fontdef;
93}
94
95static const char*
96GetKeyword (const char *src,
97 char *keyword,
98 HPDF_UINT len)
99{
100 HPDF_UINT src_len = HPDF_StrLen (src, -1);
101
102 HPDF_PTRACE ((" GetKeyword\n"));
103
104 if (!keyword || src_len == 0 || len == 0)
105 return NULL;
106
107 *keyword = 0;
108
109 while (len > 1) {
110 if (HPDF_IS_WHITE_SPACE(*src)) {
111 *keyword = 0;
112
113 while (HPDF_IS_WHITE_SPACE(*src))
114 src++;
115 return src;
116 }
117
118 *keyword++ = *src++;
119 len--;
120 }
121
122 *keyword = 0;
123 return NULL;
124}
125
126static HPDF_STATUS
127LoadAfm (HPDF_FontDef fontdef,
128 HPDF_Stream stream)
129{
130 HPDF_Type1FontDefAttr attr = (HPDF_Type1FontDefAttr)fontdef->attr;
131 char buf[HPDF_TMP_BUF_SIZ];
132 HPDF_CharData* cdata;
133 HPDF_STATUS ret;
134 HPDF_UINT len;
135 char keyword[HPDF_LIMIT_MAX_NAME_LEN + 1];
136 HPDF_UINT i;
137
138 HPDF_PTRACE ((" LoadAfm\n"));
139
140 len = HPDF_TMP_BUF_SIZ;
141
142 /* chaeck AFM header */
143 if ((ret = HPDF_Stream_ReadLn (stream, buf, &len)) != HPDF_OK)
144 return ret;
145
146 GetKeyword (buf, keyword, HPDF_LIMIT_MAX_NAME_LEN + 1);
147
148 if (HPDF_StrCmp (keyword, "StartFontMetrics") != 0)
149 return HPDF_INVALID_AFM_HEADER;
150
151 /* Global Font Information */
152
153 for (;;) {
154 const char *s;
155
156 len = HPDF_TMP_BUF_SIZ;
157 if ((ret = HPDF_Stream_ReadLn (stream, buf, &len)) != HPDF_OK)
158 return ret;
159
160 s = GetKeyword (buf, keyword, HPDF_LIMIT_MAX_NAME_LEN + 1);
161
162 if (HPDF_StrCmp (keyword, "FontName") == 0) {
163 HPDF_StrCpy (fontdef->base_font, s,
164 fontdef->base_font + HPDF_LIMIT_MAX_NAME_LEN);
165 } else
166
167 if (HPDF_StrCmp (keyword, "Weight") == 0) {
168 if (HPDF_StrCmp (s, "Bold") == 0)
169 fontdef->flags |= HPDF_FONT_FOURCE_BOLD;
170 } else
171
172 if (HPDF_StrCmp (keyword, "IsFixedPitch") == 0) {
173 if (HPDF_StrCmp (s, "true") == 0)
174 fontdef->flags |= HPDF_FONT_FIXED_WIDTH;
175 } else
176
177 if (HPDF_StrCmp (keyword, "ItalicAngle") == 0) {
178 fontdef->italic_angle = (HPDF_INT16)HPDF_AToI (s);
179 if (fontdef->italic_angle != 0)
180 fontdef->flags |= HPDF_FONT_ITALIC;
181 } else
182
183 if (HPDF_StrCmp (keyword, "CharacterSet") == 0) {
184 HPDF_UINT len = HPDF_StrLen (s, HPDF_LIMIT_MAX_STRING_LEN);
185
186 if (len > 0) {
187 attr->char_set = HPDF_GetMem (fontdef->mmgr, len + 1);
188 if (!attr->char_set)
189 return HPDF_Error_GetCode (fontdef->error);
190
191 HPDF_StrCpy (attr->char_set, s, attr->char_set + len);
192 }
193 } else
194 if (HPDF_StrCmp (keyword, "FontBBox") == 0) {
195 char buf[HPDF_INT_LEN + 1];
196
197 s = GetKeyword (s, buf, HPDF_INT_LEN + 1);
198 fontdef->font_bbox.left = (HPDF_REAL)HPDF_AToI (buf);
199
200 s = GetKeyword (s, buf, HPDF_INT_LEN + 1);
201 fontdef->font_bbox.bottom = (HPDF_REAL)HPDF_AToI (buf);
202
203 s = GetKeyword (s, buf, HPDF_INT_LEN + 1);
204 fontdef->font_bbox.right = (HPDF_REAL)HPDF_AToI (buf);
205
206 GetKeyword (s, buf, HPDF_INT_LEN + 1);
207 fontdef->font_bbox.top = (HPDF_REAL)HPDF_AToI (buf);
208 } else
209 if (HPDF_StrCmp (keyword, "EncodingScheme") == 0) {
210 HPDF_StrCpy (attr->encoding_scheme, s,
211 attr->encoding_scheme + HPDF_LIMIT_MAX_NAME_LEN);
212 } else
213 if (HPDF_StrCmp (keyword, "CapHeight") == 0) {
214 fontdef->cap_height = (HPDF_UINT16)HPDF_AToI (s);
215 } else
216 if (HPDF_StrCmp (keyword, "Ascender") == 0) {
217 fontdef->ascent = (HPDF_INT16)HPDF_AToI (s);
218 } else
219 if (HPDF_StrCmp (keyword, "Descender") == 0) {
220 fontdef->descent = (HPDF_INT16)HPDF_AToI (s);
221 } else
222 if (HPDF_StrCmp (keyword, "STDHW") == 0) {
223 fontdef->stemh = (HPDF_UINT16)HPDF_AToI (s);
224 } else
225 if (HPDF_StrCmp (keyword, "STDHV") == 0) {
226 fontdef->stemv = (HPDF_UINT16)HPDF_AToI (s);
227 } else
228 if (HPDF_StrCmp (keyword, "StartCharMetrics") == 0) {
229 attr->widths_count = HPDF_AToI (s);
230 break;
231 }
232 }
233
234 cdata = (HPDF_CharData*)HPDF_GetMem (fontdef->mmgr,
235 sizeof(HPDF_CharData) * attr->widths_count);
236 if (cdata == NULL)
237 return HPDF_Error_GetCode (fontdef->error);
238
239 HPDF_MemSet (cdata, 0, sizeof(HPDF_CharData) * attr->widths_count);
240 attr->widths = cdata;
241
242 /* load CharMetrics */
243 for (i = 0; i < attr->widths_count; i++, cdata++) {
244 const char *s;
245 char buf2[HPDF_LIMIT_MAX_NAME_LEN + 1];
246
247 len = HPDF_TMP_BUF_SIZ;
248 if ((ret = HPDF_Stream_ReadLn (stream, buf, &len)) != HPDF_OK)
249 return ret;
250
251 /* C default character code. */
252 s = GetKeyword (buf, buf2, HPDF_LIMIT_MAX_NAME_LEN + 1);
253 if (HPDF_StrCmp (buf2, "CX") == 0) {
254 /* not suppoted yet. */
255 return HPDF_SetError (fontdef->error,
256 HPDF_INVALID_CHAR_MATRICS_DATA, 0);
257 } else
258 if (HPDF_StrCmp (buf2, "C") == 0) {
259 s += 2;
260
261 s = GetKeyword (s, buf2, HPDF_LIMIT_MAX_NAME_LEN + 1);
262 HPDF_AToI (buf2);
263
264 cdata->char_cd = (HPDF_INT16)HPDF_AToI (buf2);
265
266 } else
267 return HPDF_SetError (fontdef->error,
268 HPDF_INVALID_CHAR_MATRICS_DATA, 0);
269
270 /* WX Character width */
271 s = HPDF_StrStr (s, "WX ", 0);
272 if (!s)
273 return HPDF_SetError (fontdef->error, HPDF_INVALID_WX_DATA, 0);
274
275 s += 3;
276
277 s = GetKeyword (s, buf2, HPDF_LIMIT_MAX_NAME_LEN + 1);
278 if (buf2[0] == 0)
279 return HPDF_SetError (fontdef->error, HPDF_INVALID_WX_DATA, 0);
280
281 cdata->width = (HPDF_INT16)HPDF_AToI (buf2);
282
283 /* N PostScript language character name */
284 s = HPDF_StrStr (s, "N ", 0);
285 if (!s)
286 return HPDF_SetError (fontdef->error, HPDF_INVALID_N_DATA, 0);
287
288 s += 2;
289
290 GetKeyword (s, buf2, HPDF_LIMIT_MAX_NAME_LEN + 1);
291
292 cdata->unicode = HPDF_GryphNameToUnicode (buf2);
293
294 }
295
296 return HPDF_OK;
297}
298
299
300static HPDF_STATUS
301LoadFontData (HPDF_FontDef fontdef,
302 HPDF_Stream stream)
303{
304 HPDF_Type1FontDefAttr attr = (HPDF_Type1FontDefAttr)fontdef->attr;
305 char buf[HPDF_STREAM_BUF_SIZ];
306 char* pbuf = buf;
307 HPDF_UINT len = 0;
308 HPDF_STATUS ret;
309 HPDF_BOOL end_flg = HPDF_FALSE;
310
311 HPDF_PTRACE ((" LoadFontData\n"));
312
313 attr->font_data = HPDF_MemStream_New (fontdef->mmgr, HPDF_STREAM_BUF_SIZ);
314
315 if (!attr->font_data)
316 return HPDF_Error_GetCode (fontdef->error);
317
318 len = 11;
319 ret = HPDF_Stream_Read (stream, (HPDF_BYTE *)pbuf, &len);
320 if (ret != HPDF_OK)
321 return ret;
322 pbuf += 11;
323
324 for (;;) {
325 len = HPDF_STREAM_BUF_SIZ - 11;
326 ret = HPDF_Stream_Read (stream, (HPDF_BYTE *)pbuf, &len);
327 if (ret == HPDF_STREAM_EOF) {
328 end_flg = HPDF_TRUE;
329 } else if (ret != HPDF_OK)
330 return ret;
331
332 if (len > 0) {
333 if (attr->length1 == 0) {
334 const char *s1 = HPDF_StrStr (buf, "eexec", len + 11);
335
336 /* length1 indicate the size of ascii-data of font-file. */
337 if (s1)
338 attr->length1 = attr->font_data->size + (s1 - buf) + 6;
339 }
340
341 if (attr->length1 > 0 && attr->length2 == 0) {
342 const char *s2 = HPDF_StrStr (buf, "cleartomark",
343 len + 11);
344
345 if (s2)
346 attr->length2 = attr->font_data->size + - 520 -
347 attr->length1 + (s2 - buf);
348 /* length1 indicate the size of binary-data.
349 * in most fonts, it is all right at 520 bytes . but it need
350 * to modify because it does not fully satisfy the
351 * specification of type-1 font.
352 */
353 }
354 }
355
356 if (end_flg) {
357 if ((ret = HPDF_Stream_Write (attr->font_data, (HPDF_BYTE *)buf, len + 11)) !=
358 HPDF_OK)
359 return ret;
360
361 break;
362 } else {
363 if ((ret = HPDF_Stream_Write (attr->font_data, (HPDF_BYTE *)buf, len)) !=
364 HPDF_OK)
365 return ret;
366 HPDF_MemCpy ((HPDF_BYTE *)buf, (HPDF_BYTE *)buf + len, 11);
367 pbuf = buf + 11;
368 }
369 }
370
371 if (attr->length1 == 0 || attr->length2 == 0)
372 return HPDF_SetError (fontdef->error, HPDF_UNSUPPORTED_TYPE1_FONT, 0);
373
374 attr->length3 = attr->font_data->size - attr->length1 - attr->length2;
375
376 return HPDF_OK;
377}
378
379
380HPDF_FontDef
381HPDF_Type1FontDef_Load (HPDF_MMgr mmgr,
382 HPDF_Stream afm,
383 HPDF_Stream font_data)
384{
385 HPDF_FontDef fontdef;
386 HPDF_STATUS ret;
387
388 HPDF_PTRACE ((" HPDF_Type1FontDef_Load\n"));
389
390 if (!afm)
391 return NULL;
392
393 fontdef = HPDF_Type1FontDef_New (mmgr);
394
395 if (!fontdef)
396 return NULL;
397
398 ret = LoadAfm (fontdef, afm);
399 if (ret != HPDF_OK) {
400 HPDF_FontDef_Free (fontdef);
401 return NULL;
402 }
403
404 /* if font-data is specified, the font data is embeded */
405 if (font_data) {
406 ret = LoadFontData (fontdef, font_data);
407 if (ret != HPDF_OK) {
408 HPDF_FontDef_Free (fontdef);
409 return NULL;
410 }
411 }
412
413 return fontdef;
414}
415
416HPDF_FontDef
417HPDF_Type1FontDef_Duplicate (HPDF_MMgr mmgr,
418 HPDF_FontDef src)
419{
420 HPDF_FontDef fontdef = HPDF_Type1FontDef_New (mmgr);
421
422 HPDF_PTRACE ((" HPDF_Type1FontDef_Duplicate\n"));
423
424 fontdef->type = src->type;
425 fontdef->valid = src->valid;
426
427 /* copy data of attr,widths
428 attention to charset */
429 return NULL;
430}
431
432HPDF_STATUS
433HPDF_Type1FontDef_SetWidths (HPDF_FontDef fontdef,
434 const HPDF_CharData* widths)
435{
436 const HPDF_CharData* src = widths;
437 HPDF_Type1FontDefAttr attr = (HPDF_Type1FontDefAttr)fontdef->attr;
438 HPDF_CharData* dst;
439 HPDF_UINT i = 0;
440
441 HPDF_PTRACE ((" HPDF_Type1FontDef_SetWidths\n"));
442
443 FreeWidth (fontdef);
444
445 while (src->unicode != 0xFFFF) {
446 src++;
447 i++;
448 }
449
450 attr->widths_count = i;
451
452 dst = (HPDF_CharData*)HPDF_GetMem (fontdef->mmgr, sizeof(HPDF_CharData) *
453 attr->widths_count);
454 if (dst == NULL)
455 return HPDF_Error_GetCode (fontdef->error);
456
457 HPDF_MemSet (dst, 0, sizeof(HPDF_CharData) * attr->widths_count);
458 attr->widths = dst;
459
460 src = widths;
461 for (i = 0; i < attr->widths_count; i++) {
462 dst->char_cd = src->char_cd;
463 dst->unicode = src->unicode;
464 dst->width = src->width;
465 if (dst->unicode == 0x0020) {
466 fontdef->missing_width = src->width;
467 }
468
469 src++;
470 dst++;
471 }
472
473 return HPDF_OK;
474}
475
476
477HPDF_INT16
478HPDF_Type1FontDef_GetWidthByName (HPDF_FontDef fontdef,
479 const char* gryph_name)
480{
481 HPDF_UNICODE unicode = HPDF_GryphNameToUnicode (gryph_name);
482
483 HPDF_PTRACE ((" HPDF_Type1FontDef_GetWidthByName\n"));
484
485 return HPDF_Type1FontDef_GetWidth (fontdef, unicode);
486}
487
488
489HPDF_INT16
490HPDF_Type1FontDef_GetWidth (HPDF_FontDef fontdef,
491 HPDF_UNICODE unicode)
492{
493 HPDF_Type1FontDefAttr attr = (HPDF_Type1FontDefAttr)fontdef->attr;
494 HPDF_CharData *cdata = attr->widths;
495 HPDF_UINT i;
496
497 HPDF_PTRACE ((" HPDF_Type1FontDef_GetWidth\n"));
498
499 for (i = 0; i < attr->widths_count; i++) {
500 if (cdata->unicode == unicode)
501 return cdata->width;
502 cdata++;
503 }
504
505 return fontdef->missing_width;
506}
507
508static void
509FreeFunc (HPDF_FontDef fontdef)
510{
511 HPDF_Type1FontDefAttr attr = (HPDF_Type1FontDefAttr)fontdef->attr;
512
513 HPDF_PTRACE ((" FreeFunc\n"));
514
515 if (attr->char_set)
516 HPDF_FreeMem (fontdef->mmgr, attr->char_set);
517
518 if (attr->font_data)
519 HPDF_Stream_Free (attr->font_data);
520
521 HPDF_FreeMem (fontdef->mmgr, attr->widths);
522 HPDF_FreeMem (fontdef->mmgr, attr);
523}
524
525