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 | |
22 | static void |
23 | FreeWidth (HPDF_FontDef fontdef); |
24 | |
25 | |
26 | static void |
27 | FreeFunc (HPDF_FontDef fontdef); |
28 | |
29 | |
30 | static const char* |
31 | GetKeyword (const char *src, |
32 | char *keyword, |
33 | HPDF_UINT len); |
34 | |
35 | static HPDF_STATUS |
36 | LoadAfm (HPDF_FontDef fontdef, |
37 | HPDF_Stream stream); |
38 | |
39 | |
40 | static HPDF_STATUS |
41 | LoadFontData (HPDF_FontDef fontdef, |
42 | HPDF_Stream stream); |
43 | |
44 | |
45 | /*---------------------------------------------------------------------------*/ |
46 | |
47 | static void |
48 | FreeWidth (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 | |
60 | HPDF_FontDef |
61 | HPDF_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 | |
95 | static const char* |
96 | GetKeyword (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 | |
126 | static HPDF_STATUS |
127 | LoadAfm (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 | |
300 | static HPDF_STATUS |
301 | LoadFontData (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 | |
380 | HPDF_FontDef |
381 | HPDF_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 | |
416 | HPDF_FontDef |
417 | HPDF_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 | |
432 | HPDF_STATUS |
433 | HPDF_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 | |
477 | HPDF_INT16 |
478 | HPDF_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 | |
489 | HPDF_INT16 |
490 | HPDF_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 | |
508 | static void |
509 | FreeFunc (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 | |