1 | /* |
2 | * << Haru Free PDF Library >> -- hpdf_font_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_font.h" |
21 | |
22 | static HPDF_STATUS |
23 | Type1Font_OnWrite (HPDF_Dict obj, |
24 | HPDF_Stream stream); |
25 | |
26 | |
27 | static void |
28 | Type1Font_OnFree (HPDF_Dict obj); |
29 | |
30 | |
31 | static HPDF_TextWidth |
32 | Type1Font_TextWidth (HPDF_Font font, |
33 | const HPDF_BYTE *text, |
34 | HPDF_UINT len); |
35 | |
36 | |
37 | static HPDF_UINT |
38 | Type1Font_MeasureText (HPDF_Font font, |
39 | const HPDF_BYTE *text, |
40 | HPDF_UINT len, |
41 | HPDF_REAL width, |
42 | HPDF_REAL font_size, |
43 | HPDF_REAL char_space, |
44 | HPDF_REAL word_space, |
45 | HPDF_BOOL wordwrap, |
46 | HPDF_REAL *real_width); |
47 | |
48 | |
49 | static HPDF_STATUS |
50 | Type1Font_CreateDescriptor (HPDF_MMgr mmgr, |
51 | HPDF_Font font, |
52 | HPDF_Xref xref); |
53 | |
54 | |
55 | HPDF_Font |
56 | HPDF_Type1Font_New (HPDF_MMgr mmgr, |
57 | HPDF_FontDef fontdef, |
58 | HPDF_Encoder encoder, |
59 | HPDF_Xref xref) |
60 | { |
61 | HPDF_Dict font; |
62 | HPDF_FontAttr attr; |
63 | HPDF_Type1FontDefAttr fontdef_attr; |
64 | HPDF_BasicEncoderAttr encoder_attr; |
65 | HPDF_STATUS ret = 0; |
66 | HPDF_UINT i; |
67 | |
68 | HPDF_PTRACE ((" HPDF_Type1Font_New\n" )); |
69 | |
70 | /* check whether the fontdef object and the encoder object is valid. */ |
71 | if (encoder->type != HPDF_ENCODER_TYPE_SINGLE_BYTE) { |
72 | HPDF_SetError(mmgr->error, HPDF_INVALID_ENCODER_TYPE, 0); |
73 | return NULL; |
74 | } |
75 | |
76 | if (fontdef->type != HPDF_FONTDEF_TYPE_TYPE1) { |
77 | HPDF_SetError(mmgr->error, HPDF_INVALID_FONTDEF_TYPE, 0); |
78 | return NULL; |
79 | } |
80 | |
81 | font = HPDF_Dict_New (mmgr); |
82 | if (!font) |
83 | return NULL; |
84 | |
85 | font->header.obj_class |= HPDF_OSUBCLASS_FONT; |
86 | |
87 | attr = HPDF_GetMem (mmgr, sizeof(HPDF_FontAttr_Rec)); |
88 | if (!attr) { |
89 | HPDF_Dict_Free (font); |
90 | return NULL; |
91 | } |
92 | |
93 | font->header.obj_class |= HPDF_OSUBCLASS_FONT; |
94 | font->write_fn = Type1Font_OnWrite; |
95 | font->free_fn = Type1Font_OnFree; |
96 | |
97 | HPDF_MemSet (attr, 0, sizeof(HPDF_FontAttr_Rec)); |
98 | |
99 | font->attr = attr; |
100 | attr->type = HPDF_FONT_TYPE1; |
101 | attr->writing_mode = HPDF_WMODE_HORIZONTAL; |
102 | attr->text_width_fn = Type1Font_TextWidth; |
103 | attr->measure_text_fn = Type1Font_MeasureText; |
104 | attr->fontdef = fontdef; |
105 | attr->encoder = encoder; |
106 | attr->xref = xref; |
107 | |
108 | /* singlebyte-font has a widths-array which is an array of 256 signed |
109 | * short integer. |
110 | */ |
111 | attr->widths = HPDF_GetMem (mmgr, sizeof(HPDF_INT16) * 256); |
112 | if (!attr->widths) { |
113 | HPDF_Dict_Free (font); |
114 | return NULL; |
115 | } |
116 | |
117 | encoder_attr = (HPDF_BasicEncoderAttr)encoder->attr; |
118 | |
119 | HPDF_MemSet (attr->widths, 0, sizeof(HPDF_INT16) * 256); |
120 | for (i = encoder_attr->first_char; i <= encoder_attr->last_char; i++) { |
121 | HPDF_UNICODE u = encoder_attr->unicode_map[i]; |
122 | |
123 | HPDF_UINT16 w = HPDF_Type1FontDef_GetWidth (fontdef, u); |
124 | attr->widths[i] = w; |
125 | } |
126 | |
127 | fontdef_attr = (HPDF_Type1FontDefAttr)fontdef->attr; |
128 | |
129 | ret += HPDF_Dict_AddName (font, "Type" , "Font" ); |
130 | ret += HPDF_Dict_AddName (font, "BaseFont" , fontdef->base_font); |
131 | ret += HPDF_Dict_AddName (font, "Subtype" , "Type1" ); |
132 | |
133 | if (!fontdef_attr->is_base14font) { |
134 | if (fontdef->missing_width != 0) |
135 | ret += HPDF_Dict_AddNumber (font, "MissingWidth" , |
136 | fontdef->missing_width); |
137 | |
138 | ret += Type1Font_CreateDescriptor (mmgr, font, xref); |
139 | } |
140 | |
141 | if (ret != HPDF_OK) { |
142 | HPDF_Dict_Free (font); |
143 | return NULL; |
144 | } |
145 | |
146 | if (HPDF_Xref_Add (xref, font) != HPDF_OK) |
147 | return NULL; |
148 | |
149 | return font; |
150 | } |
151 | |
152 | |
153 | static HPDF_STATUS |
154 | Type1Font_CreateDescriptor (HPDF_MMgr mmgr, |
155 | HPDF_Font font, |
156 | HPDF_Xref xref) |
157 | { |
158 | HPDF_FontAttr font_attr = (HPDF_FontAttr)font->attr; |
159 | HPDF_FontDef def = font_attr->fontdef; |
160 | HPDF_Type1FontDefAttr def_attr = (HPDF_Type1FontDefAttr)def->attr; |
161 | |
162 | HPDF_PTRACE ((" HPDF_Type1Font_CreateDescriptor\n" )); |
163 | |
164 | if (!font_attr->fontdef->descriptor) { |
165 | HPDF_Dict descriptor = HPDF_Dict_New (mmgr); |
166 | HPDF_STATUS ret = 0; |
167 | HPDF_Array array; |
168 | |
169 | if (!descriptor) |
170 | return HPDF_Error_GetCode (font->error); |
171 | |
172 | ret += HPDF_Xref_Add (xref, descriptor); |
173 | ret += HPDF_Dict_AddName (descriptor, "Type" , "FontDescriptor" ); |
174 | ret += HPDF_Dict_AddNumber (descriptor, "Ascent" , def->ascent); |
175 | ret += HPDF_Dict_AddNumber (descriptor, "Descent" , def->descent); |
176 | ret += HPDF_Dict_AddNumber (descriptor, "Flags" , def->flags); |
177 | |
178 | array = HPDF_Box_Array_New (mmgr, def->font_bbox); |
179 | ret += HPDF_Dict_Add (descriptor, "FontBBox" , array); |
180 | |
181 | ret += HPDF_Dict_AddName (descriptor, "FontName" , |
182 | font_attr->fontdef->base_font); |
183 | ret += HPDF_Dict_AddNumber (descriptor, "ItalicAngle" , |
184 | def->italic_angle); |
185 | ret += HPDF_Dict_AddNumber (descriptor, "StemV" , def->stemv); |
186 | ret += HPDF_Dict_AddNumber (descriptor, "XHeight" , def->x_height); |
187 | |
188 | if (def_attr->char_set) |
189 | ret += HPDF_Dict_AddName (descriptor, "CharSet" , |
190 | def_attr->char_set); |
191 | |
192 | if (ret != HPDF_OK) |
193 | return HPDF_Error_GetCode (font->error); |
194 | |
195 | if (def_attr->font_data) { |
196 | HPDF_Dict font_data = HPDF_DictStream_New (mmgr, xref); |
197 | |
198 | if (!font_data) |
199 | return HPDF_Error_GetCode (font->error); |
200 | |
201 | if (HPDF_Stream_WriteToStream (def_attr->font_data, |
202 | font_data->stream, HPDF_STREAM_FILTER_NONE, NULL) != HPDF_OK) |
203 | return HPDF_Error_GetCode (font->error); |
204 | |
205 | ret += HPDF_Dict_Add (descriptor, "FontFile" , font_data); |
206 | ret += HPDF_Dict_AddNumber (font_data, "Length1" , |
207 | def_attr->length1); |
208 | ret += HPDF_Dict_AddNumber (font_data, "Length2" , |
209 | def_attr->length2); |
210 | ret += HPDF_Dict_AddNumber (font_data, "Length3" , |
211 | def_attr->length3); |
212 | |
213 | font_data->filter = font->filter; |
214 | } |
215 | |
216 | if (ret != HPDF_OK) |
217 | return HPDF_Error_GetCode (font->error); |
218 | |
219 | font_attr->fontdef->descriptor = descriptor; |
220 | } |
221 | |
222 | return HPDF_Dict_Add (font, "FontDescriptor" , |
223 | font_attr->fontdef->descriptor); |
224 | } |
225 | |
226 | |
227 | static HPDF_TextWidth |
228 | Type1Font_TextWidth (HPDF_Font font, |
229 | const HPDF_BYTE *text, |
230 | HPDF_UINT len) |
231 | { |
232 | HPDF_FontAttr attr = (HPDF_FontAttr)font->attr; |
233 | HPDF_TextWidth ret = {0, 0, 0, 0}; |
234 | HPDF_UINT i; |
235 | HPDF_BYTE b = 0; |
236 | |
237 | HPDF_PTRACE ((" HPDF_Type1Font_TextWidth\n" )); |
238 | |
239 | if (attr->widths) { |
240 | for (i = 0; i < len; i++) { |
241 | b = text[i]; |
242 | ret.numchars++; |
243 | ret.width += attr->widths[b]; |
244 | |
245 | if (HPDF_IS_WHITE_SPACE(b)) { |
246 | ret.numspace++; |
247 | ret.numwords++; |
248 | } |
249 | } |
250 | } else |
251 | HPDF_SetError (font->error, HPDF_FONT_INVALID_WIDTHS_TABLE, 0); |
252 | |
253 | /* 2006.08.19 add. */ |
254 | if (HPDF_IS_WHITE_SPACE(b)) |
255 | ; /* do nothing. */ |
256 | else |
257 | ret.numwords++; |
258 | |
259 | return ret; |
260 | } |
261 | |
262 | |
263 | static HPDF_UINT |
264 | Type1Font_MeasureText (HPDF_Font font, |
265 | const HPDF_BYTE *text, |
266 | HPDF_UINT len, |
267 | HPDF_REAL width, |
268 | HPDF_REAL font_size, |
269 | HPDF_REAL char_space, |
270 | HPDF_REAL word_space, |
271 | HPDF_BOOL wordwrap, |
272 | HPDF_REAL *real_width) |
273 | { |
274 | HPDF_REAL w = 0; |
275 | HPDF_UINT tmp_len = 0; |
276 | HPDF_UINT i; |
277 | HPDF_FontAttr attr = (HPDF_FontAttr)font->attr; |
278 | |
279 | HPDF_PTRACE ((" HPDF_Type1Font_MeasureText\n" )); |
280 | |
281 | for (i = 0; i < len; i++) { |
282 | HPDF_BYTE b = text[i]; |
283 | |
284 | if (HPDF_IS_WHITE_SPACE(b)) { |
285 | tmp_len = i + 1; |
286 | |
287 | if (real_width) |
288 | *real_width = w; |
289 | |
290 | w += word_space; |
291 | } else if (!wordwrap) { |
292 | tmp_len = i; |
293 | |
294 | if (real_width) |
295 | *real_width = w; |
296 | } |
297 | |
298 | w += attr->widths[b] * font_size / 1000; |
299 | |
300 | /* 2006.08.04 break when it encountered line feed */ |
301 | if (w > width || b == 0x0A) |
302 | return tmp_len; |
303 | |
304 | if (i > 0) |
305 | w += char_space; |
306 | } |
307 | |
308 | /* all of text can be put in the specified width */ |
309 | if (real_width) |
310 | *real_width = w; |
311 | |
312 | return len; |
313 | } |
314 | |
315 | |
316 | static HPDF_STATUS |
317 | Type1Font_OnWrite (HPDF_Dict obj, |
318 | HPDF_Stream stream) |
319 | { |
320 | HPDF_FontAttr attr = (HPDF_FontAttr)obj->attr; |
321 | HPDF_Type1FontDefAttr fontdef_attr = |
322 | (HPDF_Type1FontDefAttr)attr->fontdef->attr; |
323 | HPDF_BasicEncoderAttr encoder_attr = |
324 | (HPDF_BasicEncoderAttr)attr->encoder->attr; |
325 | HPDF_UINT i; |
326 | HPDF_STATUS ret; |
327 | char buf[HPDF_TMP_BUF_SIZ]; |
328 | char *eptr = buf + HPDF_TMP_BUF_SIZ - 1; |
329 | |
330 | HPDF_PTRACE ((" HPDF_Font_Type1Font_OnWrite\n" )); |
331 | |
332 | /* if font is base14-font these entries is not required */ |
333 | if (!fontdef_attr->is_base14font || encoder_attr->has_differences) { |
334 | char *pbuf; |
335 | |
336 | pbuf = (char *)HPDF_StrCpy (buf, "/FirstChar " , eptr); |
337 | pbuf = HPDF_IToA (pbuf, encoder_attr->first_char, eptr); |
338 | HPDF_StrCpy (pbuf, "\012" , eptr); |
339 | if ((ret = HPDF_Stream_WriteStr (stream, buf)) != HPDF_OK) |
340 | return ret; |
341 | |
342 | pbuf = (char *)HPDF_StrCpy (buf, "/LastChar " , eptr); |
343 | pbuf = HPDF_IToA (pbuf, encoder_attr->last_char, eptr); |
344 | HPDF_StrCpy (pbuf, "\012" , eptr); |
345 | if ((ret = HPDF_Stream_WriteStr (stream, buf)) != HPDF_OK) |
346 | return ret; |
347 | |
348 | /* Widths entry */ |
349 | if ((ret = HPDF_Stream_WriteEscapeName (stream, "Widths" )) != HPDF_OK) |
350 | return ret; |
351 | |
352 | if ((ret = HPDF_Stream_WriteStr (stream, " [\012" )) != HPDF_OK) |
353 | return ret; |
354 | |
355 | pbuf = buf; |
356 | for (i = encoder_attr->first_char; i <= encoder_attr->last_char; i++) { |
357 | |
358 | pbuf = HPDF_IToA (pbuf, attr->widths[i], eptr); |
359 | *pbuf++ = ' '; |
360 | |
361 | if ((i + 1) % 16 == 0) { |
362 | HPDF_StrCpy(pbuf, "\012" , eptr); |
363 | if ((ret = HPDF_Stream_WriteStr (stream, buf)) != HPDF_OK) |
364 | return ret; |
365 | pbuf = buf; |
366 | } |
367 | } |
368 | |
369 | HPDF_StrCpy (pbuf, "]\012" , eptr); |
370 | |
371 | if ((ret = HPDF_Stream_WriteStr (stream, buf)) != HPDF_OK) |
372 | return ret; |
373 | } |
374 | |
375 | return attr->encoder->write_fn (attr->encoder, stream); |
376 | } |
377 | |
378 | |
379 | static void |
380 | Type1Font_OnFree (HPDF_Dict obj) |
381 | { |
382 | HPDF_FontAttr attr = (HPDF_FontAttr)obj->attr; |
383 | |
384 | HPDF_PTRACE ((" HPDF_Type1Font_OnFree\n" )); |
385 | |
386 | if (attr) { |
387 | if (attr->widths) { |
388 | HPDF_FreeMem (obj->mmgr, attr->widths); |
389 | } |
390 | HPDF_FreeMem (obj->mmgr, attr); |
391 | } |
392 | } |
393 | |
394 | |
395 | |