1 | /* |
2 | * << Haru Free PDF Library >> -- hpdf_font_cid.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_Font |
23 | CIDFontType0_New (HPDF_Font parent, |
24 | HPDF_Xref xref); |
25 | |
26 | |
27 | static HPDF_Font |
28 | CIDFontType2_New (HPDF_Font parent, |
29 | HPDF_Xref xref); |
30 | |
31 | |
32 | static HPDF_TextWidth |
33 | TextWidth (HPDF_Font font, |
34 | const HPDF_BYTE *text, |
35 | HPDF_UINT len); |
36 | |
37 | |
38 | static HPDF_UINT |
39 | MeasureText (HPDF_Font font, |
40 | const HPDF_BYTE *text, |
41 | HPDF_UINT len, |
42 | HPDF_REAL width, |
43 | HPDF_REAL font_size, |
44 | HPDF_REAL char_space, |
45 | HPDF_REAL word_space, |
46 | HPDF_BOOL wordwrap, |
47 | HPDF_REAL *real_width); |
48 | |
49 | |
50 | static char* |
51 | UINT16ToHex (char *s, |
52 | HPDF_UINT16 val, |
53 | char *eptr, |
54 | HPDF_BYTE width); |
55 | |
56 | static char * |
57 | CidRangeToHex (char *s, |
58 | HPDF_UINT16 from, |
59 | HPDF_UINT16 to, |
60 | char *eptr); |
61 | |
62 | static HPDF_Dict |
63 | CreateCMap (HPDF_Encoder encoder, |
64 | HPDF_Xref xref); |
65 | |
66 | |
67 | static void |
68 | OnFree_Func (HPDF_Dict obj); |
69 | |
70 | |
71 | static HPDF_STATUS |
72 | CIDFontType2_BeforeWrite_Func (HPDF_Dict obj); |
73 | |
74 | |
75 | /*--------------------------------------------------------------------------*/ |
76 | |
77 | HPDF_Font |
78 | HPDF_Type0Font_New (HPDF_MMgr mmgr, |
79 | HPDF_FontDef fontdef, |
80 | HPDF_Encoder encoder, |
81 | HPDF_Xref xref) |
82 | { |
83 | HPDF_Dict font; |
84 | HPDF_FontAttr attr; |
85 | HPDF_CMapEncoderAttr encoder_attr; |
86 | HPDF_STATUS ret = 0; |
87 | HPDF_Array descendant_fonts; |
88 | |
89 | HPDF_PTRACE ((" HPDF_Type0Font_New\n" )); |
90 | |
91 | font = HPDF_Dict_New (mmgr); |
92 | if (!font) |
93 | return NULL; |
94 | |
95 | font->header.obj_class |= HPDF_OSUBCLASS_FONT; |
96 | |
97 | /* check whether the fontdef object and the encoder object is valid. */ |
98 | if (encoder->type != HPDF_ENCODER_TYPE_DOUBLE_BYTE) { |
99 | HPDF_SetError(font->error, HPDF_INVALID_ENCODER_TYPE, 0); |
100 | return NULL; |
101 | } |
102 | |
103 | if (fontdef->type != HPDF_FONTDEF_TYPE_CID && |
104 | fontdef->type != HPDF_FONTDEF_TYPE_TRUETYPE) { |
105 | HPDF_SetError(font->error, HPDF_INVALID_FONTDEF_TYPE, 0); |
106 | return NULL; |
107 | } |
108 | |
109 | attr = HPDF_GetMem (mmgr, sizeof(HPDF_FontAttr_Rec)); |
110 | if (!attr) { |
111 | HPDF_Dict_Free (font); |
112 | return NULL; |
113 | } |
114 | |
115 | font->header.obj_class |= HPDF_OSUBCLASS_FONT; |
116 | font->write_fn = NULL; |
117 | font->free_fn = OnFree_Func; |
118 | font->attr = attr; |
119 | |
120 | encoder_attr = (HPDF_CMapEncoderAttr)encoder->attr; |
121 | |
122 | HPDF_MemSet (attr, 0, sizeof(HPDF_FontAttr_Rec)); |
123 | |
124 | attr->writing_mode = encoder_attr->writing_mode; |
125 | attr->text_width_fn = TextWidth; |
126 | attr->measure_text_fn = MeasureText; |
127 | attr->fontdef = fontdef; |
128 | attr->encoder = encoder; |
129 | attr->xref = xref; |
130 | |
131 | if (HPDF_Xref_Add (xref, font) != HPDF_OK) |
132 | return NULL; |
133 | |
134 | ret += HPDF_Dict_AddName (font, "Type" , "Font" ); |
135 | ret += HPDF_Dict_AddName (font, "BaseFont" , fontdef->base_font); |
136 | ret += HPDF_Dict_AddName (font, "Subtype" , "Type0" ); |
137 | |
138 | if (fontdef->type == HPDF_FONTDEF_TYPE_CID) { |
139 | ret += HPDF_Dict_AddName (font, "Encoding" , encoder->name); |
140 | } else { |
141 | /* |
142 | * Handle the Unicode encoding, see hpdf_encoding_utf.c For some |
143 | * reason, xpdf-based readers cannot deal with our cmap but work |
144 | * fine when using the predefined "Identity-H" |
145 | * encoding. However, text selection does not work, unless we |
146 | * add a ToUnicode cmap. This CMap should also be "Identity", |
147 | * but that does not work -- specifying our cmap as a stream however |
148 | * does work. Who can understand that ? |
149 | */ |
150 | if (HPDF_StrCmp(encoder_attr->ordering, "Identity-H" ) == 0) { |
151 | ret += HPDF_Dict_AddName (font, "Encoding" , "Identity-H" ); |
152 | attr->cmap_stream = CreateCMap (encoder, xref); |
153 | |
154 | if (attr->cmap_stream) { |
155 | ret += HPDF_Dict_Add (font, "ToUnicode" , attr->cmap_stream); |
156 | } else |
157 | return NULL; |
158 | } else { |
159 | attr->cmap_stream = CreateCMap (encoder, xref); |
160 | |
161 | if (attr->cmap_stream) { |
162 | ret += HPDF_Dict_Add (font, "Encoding" , attr->cmap_stream); |
163 | } else |
164 | return NULL; |
165 | } |
166 | } |
167 | |
168 | if (ret != HPDF_OK) |
169 | return NULL; |
170 | |
171 | descendant_fonts = HPDF_Array_New (mmgr); |
172 | if (!descendant_fonts) |
173 | return NULL; |
174 | |
175 | if (HPDF_Dict_Add (font, "DescendantFonts" , descendant_fonts) != HPDF_OK) |
176 | return NULL; |
177 | |
178 | if (fontdef->type == HPDF_FONTDEF_TYPE_CID) { |
179 | attr->descendant_font = CIDFontType0_New (font, xref); |
180 | attr->type = HPDF_FONT_TYPE0_CID; |
181 | } else { |
182 | attr->descendant_font = CIDFontType2_New (font, xref); |
183 | attr->type = HPDF_FONT_TYPE0_TT; |
184 | } |
185 | |
186 | if (!attr->descendant_font) |
187 | return NULL; |
188 | else |
189 | if (HPDF_Array_Add (descendant_fonts, attr->descendant_font) != |
190 | HPDF_OK) |
191 | return NULL; |
192 | |
193 | return font; |
194 | } |
195 | |
196 | static void |
197 | OnFree_Func (HPDF_Dict obj) |
198 | { |
199 | HPDF_FontAttr attr = (HPDF_FontAttr)obj->attr; |
200 | |
201 | HPDF_PTRACE ((" HPDF_Type0Font_OnFree\n" )); |
202 | |
203 | if (attr) |
204 | HPDF_FreeMem (obj->mmgr, attr); |
205 | } |
206 | |
207 | static HPDF_Font |
208 | CIDFontType0_New (HPDF_Font parent, HPDF_Xref xref) |
209 | { |
210 | HPDF_STATUS ret = HPDF_OK; |
211 | HPDF_FontAttr attr = (HPDF_FontAttr)parent->attr; |
212 | HPDF_FontDef fontdef = attr->fontdef; |
213 | HPDF_CIDFontDefAttr fontdef_attr = (HPDF_CIDFontDefAttr)fontdef->attr; |
214 | HPDF_Encoder encoder = attr->encoder; |
215 | HPDF_CMapEncoderAttr encoder_attr = |
216 | (HPDF_CMapEncoderAttr)encoder->attr; |
217 | |
218 | HPDF_UINT16 save_cid = 0; |
219 | HPDF_Font font; |
220 | HPDF_Array array; |
221 | HPDF_Array sub_array = NULL; |
222 | HPDF_UINT i; |
223 | |
224 | HPDF_Dict descriptor; |
225 | HPDF_Dict cid_system_info; |
226 | |
227 | HPDF_PTRACE ((" HPDF_CIDFontType0_New\n" )); |
228 | |
229 | font = HPDF_Dict_New (parent->mmgr); |
230 | if (!font) |
231 | return NULL; |
232 | |
233 | if (HPDF_Xref_Add (xref, font) != HPDF_OK) |
234 | return NULL; |
235 | |
236 | ret += HPDF_Dict_AddName (font, "Type" , "Font" ); |
237 | ret += HPDF_Dict_AddName (font, "Subtype" , "CIDFontType0" ); |
238 | ret += HPDF_Dict_AddNumber (font, "DW" , fontdef_attr->DW); |
239 | ret += HPDF_Dict_AddName (font, "BaseFont" , fontdef->base_font); |
240 | if (ret != HPDF_OK) |
241 | return NULL; |
242 | |
243 | /* add 'DW2' element */ |
244 | array = HPDF_Array_New (parent->mmgr); |
245 | if (!array) |
246 | return NULL; |
247 | |
248 | if (HPDF_Dict_Add (font, "DW2" , array) != HPDF_OK) |
249 | return NULL; |
250 | |
251 | ret += HPDF_Array_AddNumber (array, fontdef_attr->DW2[0]); |
252 | ret += HPDF_Array_AddNumber (array, fontdef_attr->DW2[1]); |
253 | |
254 | if (ret != HPDF_OK) |
255 | return NULL; |
256 | |
257 | /* add 'W' element */ |
258 | array = HPDF_Array_New (parent->mmgr); |
259 | if (!array) |
260 | return NULL; |
261 | |
262 | if (HPDF_Dict_Add (font, "W" , array) != HPDF_OK) |
263 | return NULL; |
264 | |
265 | /* Create W array. */ |
266 | for (i = 0; i< fontdef_attr->widths->count; i++) { |
267 | HPDF_CID_Width *w = |
268 | (HPDF_CID_Width *)HPDF_List_ItemAt (fontdef_attr->widths, i); |
269 | |
270 | if (w->cid != save_cid + 1 || !sub_array) { |
271 | sub_array = HPDF_Array_New (parent->mmgr); |
272 | if (!sub_array) |
273 | return NULL; |
274 | |
275 | ret += HPDF_Array_AddNumber (array, w->cid); |
276 | ret += HPDF_Array_Add (array, sub_array); |
277 | } |
278 | |
279 | ret += HPDF_Array_AddNumber (sub_array, w->width); |
280 | save_cid = w->cid; |
281 | |
282 | if (ret != HPDF_OK) |
283 | return NULL; |
284 | } |
285 | |
286 | /* create descriptor */ |
287 | descriptor = HPDF_Dict_New (parent->mmgr); |
288 | if (!descriptor) |
289 | return NULL; |
290 | |
291 | if (HPDF_Xref_Add (xref, descriptor) != HPDF_OK) |
292 | return NULL; |
293 | |
294 | if (HPDF_Dict_Add (font, "FontDescriptor" , descriptor) != HPDF_OK) |
295 | return NULL; |
296 | |
297 | ret += HPDF_Dict_AddName (descriptor, "Type" , "FontDescriptor" ); |
298 | ret += HPDF_Dict_AddName (descriptor, "FontName" , fontdef->base_font); |
299 | ret += HPDF_Dict_AddNumber (descriptor, "Ascent" , fontdef->ascent); |
300 | ret += HPDF_Dict_AddNumber (descriptor, "Descent" , fontdef->descent); |
301 | ret += HPDF_Dict_AddNumber (descriptor, "CapHeight" , |
302 | fontdef->cap_height); |
303 | ret += HPDF_Dict_AddNumber (descriptor, "MissingWidth" , |
304 | fontdef->missing_width); |
305 | ret += HPDF_Dict_AddNumber (descriptor, "Flags" , fontdef->flags); |
306 | |
307 | if (ret != HPDF_OK) |
308 | return NULL; |
309 | |
310 | array = HPDF_Box_Array_New (parent->mmgr, fontdef->font_bbox); |
311 | if (!array) |
312 | return NULL; |
313 | |
314 | ret += HPDF_Dict_Add (descriptor, "FontBBox" , array); |
315 | ret += HPDF_Dict_AddNumber (descriptor, "ItalicAngle" , |
316 | fontdef->italic_angle); |
317 | ret += HPDF_Dict_AddNumber (descriptor, "StemV" , fontdef->stemv); |
318 | |
319 | if (ret != HPDF_OK) |
320 | return NULL; |
321 | |
322 | /* create CIDSystemInfo dictionary */ |
323 | cid_system_info = HPDF_Dict_New (parent->mmgr); |
324 | if (!cid_system_info) |
325 | return NULL; |
326 | |
327 | if (HPDF_Dict_Add (font, "CIDSystemInfo" , cid_system_info) != HPDF_OK) |
328 | return NULL; |
329 | |
330 | ret += HPDF_Dict_Add (cid_system_info, "Registry" , |
331 | HPDF_String_New (parent->mmgr, encoder_attr->registry, NULL)); |
332 | ret += HPDF_Dict_Add (cid_system_info, "Ordering" , |
333 | HPDF_String_New (parent->mmgr, encoder_attr->ordering, NULL)); |
334 | ret += HPDF_Dict_AddNumber (cid_system_info, "Supplement" , |
335 | encoder_attr->suppliment); |
336 | |
337 | if (ret != HPDF_OK) |
338 | return NULL; |
339 | |
340 | return font; |
341 | } |
342 | |
343 | static HPDF_Font |
344 | CIDFontType2_New (HPDF_Font parent, HPDF_Xref xref) |
345 | { |
346 | HPDF_STATUS ret = HPDF_OK; |
347 | HPDF_FontAttr attr = (HPDF_FontAttr)parent->attr; |
348 | HPDF_FontDef fontdef = attr->fontdef; |
349 | HPDF_TTFontDefAttr fontdef_attr = (HPDF_TTFontDefAttr)fontdef->attr; |
350 | HPDF_Encoder encoder = attr->encoder; |
351 | HPDF_CMapEncoderAttr encoder_attr = |
352 | (HPDF_CMapEncoderAttr)encoder->attr; |
353 | |
354 | HPDF_Font font; |
355 | HPDF_Array array; |
356 | HPDF_UINT i; |
357 | HPDF_UNICODE tmp_map[65536]; |
358 | HPDF_Dict cid_system_info; |
359 | |
360 | HPDF_UINT16 max = 0; |
361 | |
362 | HPDF_PTRACE ((" HPDF_CIDFontType2_New\n" )); |
363 | |
364 | font = HPDF_Dict_New (parent->mmgr); |
365 | if (!font) |
366 | return NULL; |
367 | |
368 | if (HPDF_Xref_Add (xref, font) != HPDF_OK) |
369 | return NULL; |
370 | |
371 | parent->before_write_fn = CIDFontType2_BeforeWrite_Func; |
372 | |
373 | ret += HPDF_Dict_AddName (font, "Type" , "Font" ); |
374 | ret += HPDF_Dict_AddName (font, "Subtype" , "CIDFontType2" ); |
375 | ret += HPDF_Dict_AddNumber (font, "DW" , fontdef->missing_width); |
376 | if (ret != HPDF_OK) |
377 | return NULL; |
378 | |
379 | /* add 'DW2' element */ |
380 | array = HPDF_Array_New (font->mmgr); |
381 | if (!array) |
382 | return NULL; |
383 | |
384 | if (HPDF_Dict_Add (font, "DW2" , array) != HPDF_OK) |
385 | return NULL; |
386 | |
387 | ret += HPDF_Array_AddNumber (array, (HPDF_INT32)(fontdef->font_bbox.bottom)); |
388 | ret += HPDF_Array_AddNumber (array, (HPDF_INT32)(fontdef->font_bbox.bottom - |
389 | fontdef->font_bbox.top)); |
390 | |
391 | HPDF_MemSet (tmp_map, 0, sizeof(HPDF_UNICODE) * 65536); |
392 | |
393 | if (ret != HPDF_OK) |
394 | return NULL; |
395 | |
396 | for (i = 0; i < 256; i++) { |
397 | HPDF_UINT j; |
398 | |
399 | for (j = 0; j < 256; j++) { |
400 | if (encoder->to_unicode_fn == HPDF_CMapEncoder_ToUnicode) { |
401 | HPDF_UINT16 cid = encoder_attr->cid_map[i][j]; |
402 | if (cid != 0) { |
403 | HPDF_UNICODE unicode = encoder_attr->unicode_map[i][j]; |
404 | HPDF_UINT16 gid = HPDF_TTFontDef_GetGlyphid (fontdef, |
405 | unicode); |
406 | tmp_map[cid] = gid; |
407 | if (max < cid) |
408 | max = cid; |
409 | } |
410 | } else { |
411 | HPDF_UNICODE unicode = (i << 8) | j; |
412 | HPDF_UINT16 gid = HPDF_TTFontDef_GetGlyphid (fontdef, |
413 | unicode); |
414 | tmp_map[unicode] = gid; |
415 | if (max < unicode) |
416 | max = unicode; |
417 | } |
418 | } |
419 | } |
420 | |
421 | if (max > 0) { |
422 | HPDF_INT16 dw = fontdef->missing_width; |
423 | HPDF_UNICODE *ptmp_map = tmp_map; |
424 | HPDF_Array tmp_array = NULL; |
425 | |
426 | /* add 'W' element */ |
427 | array = HPDF_Array_New (font->mmgr); |
428 | if (!array) |
429 | return NULL; |
430 | |
431 | if (HPDF_Dict_Add (font, "W" , array) != HPDF_OK) |
432 | return NULL; |
433 | |
434 | for (i = 0; i < max; i++, ptmp_map++) { |
435 | HPDF_INT w = HPDF_TTFontDef_GetGidWidth (fontdef, *ptmp_map); |
436 | |
437 | if (w != dw) { |
438 | if (!tmp_array) { |
439 | if (HPDF_Array_AddNumber (array, i) != HPDF_OK) |
440 | return NULL; |
441 | |
442 | tmp_array = HPDF_Array_New (font->mmgr); |
443 | if (!tmp_array) |
444 | return NULL; |
445 | |
446 | if (HPDF_Array_Add (array, tmp_array) != HPDF_OK) |
447 | return NULL; |
448 | } |
449 | |
450 | if ((ret = HPDF_Array_AddNumber (tmp_array, w)) != HPDF_OK) |
451 | return NULL; |
452 | } else |
453 | tmp_array = NULL; |
454 | } |
455 | |
456 | /* create "CIDToGIDMap" data */ |
457 | if (fontdef_attr->embedding) { |
458 | attr->map_stream = HPDF_DictStream_New (font->mmgr, xref); |
459 | if (!attr->map_stream) |
460 | return NULL; |
461 | |
462 | if (HPDF_Dict_Add (font, "CIDToGIDMap" , attr->map_stream) != HPDF_OK) |
463 | return NULL; |
464 | |
465 | for (i = 0; i < max; i++) { |
466 | HPDF_BYTE u[2]; |
467 | HPDF_UINT16 gid = tmp_map[i]; |
468 | |
469 | u[0] = (HPDF_BYTE)(gid >> 8); |
470 | u[1] = (HPDF_BYTE)gid; |
471 | |
472 | HPDF_MemCpy ((HPDF_BYTE *)(tmp_map + i), u, 2); |
473 | } |
474 | |
475 | if ((ret = HPDF_Stream_Write (attr->map_stream->stream, |
476 | (HPDF_BYTE *)tmp_map, max * 2)) != HPDF_OK) |
477 | return NULL; |
478 | } |
479 | } else { |
480 | HPDF_SetError (font->error, HPDF_INVALID_FONTDEF_DATA, 0); |
481 | return 0; |
482 | } |
483 | |
484 | /* create CIDSystemInfo dictionary */ |
485 | cid_system_info = HPDF_Dict_New (parent->mmgr); |
486 | if (!cid_system_info) |
487 | return NULL; |
488 | |
489 | if (HPDF_Dict_Add (font, "CIDSystemInfo" , cid_system_info) != HPDF_OK) |
490 | return NULL; |
491 | |
492 | ret += HPDF_Dict_Add (cid_system_info, "Registry" , |
493 | HPDF_String_New (parent->mmgr, encoder_attr->registry, NULL)); |
494 | ret += HPDF_Dict_Add (cid_system_info, "Ordering" , |
495 | HPDF_String_New (parent->mmgr, encoder_attr->ordering, NULL)); |
496 | ret += HPDF_Dict_AddNumber (cid_system_info, "Supplement" , |
497 | encoder_attr->suppliment); |
498 | |
499 | if (ret != HPDF_OK) |
500 | return NULL; |
501 | |
502 | return font; |
503 | } |
504 | |
505 | |
506 | static HPDF_STATUS |
507 | CIDFontType2_BeforeWrite_Func (HPDF_Dict obj) |
508 | { |
509 | HPDF_FontAttr font_attr = (HPDF_FontAttr)obj->attr; |
510 | HPDF_FontDef def = font_attr->fontdef; |
511 | HPDF_TTFontDefAttr def_attr = (HPDF_TTFontDefAttr)def->attr; |
512 | HPDF_STATUS ret = 0; |
513 | |
514 | HPDF_PTRACE ((" CIDFontType2_BeforeWrite_Func\n" )); |
515 | |
516 | if (font_attr->map_stream) |
517 | font_attr->map_stream->filter = obj->filter; |
518 | |
519 | if (font_attr->cmap_stream) |
520 | font_attr->cmap_stream->filter = obj->filter; |
521 | |
522 | if (!font_attr->fontdef->descriptor) { |
523 | HPDF_Dict descriptor = HPDF_Dict_New (obj->mmgr); |
524 | HPDF_Array array; |
525 | |
526 | if (!descriptor) |
527 | return HPDF_Error_GetCode (obj->error); |
528 | |
529 | if (def_attr->embedding) { |
530 | HPDF_Dict font_data = HPDF_DictStream_New (obj->mmgr, |
531 | font_attr->xref); |
532 | |
533 | if (!font_data) |
534 | return HPDF_Error_GetCode (obj->error); |
535 | |
536 | if (HPDF_TTFontDef_SaveFontData (font_attr->fontdef, |
537 | font_data->stream) != HPDF_OK) |
538 | return HPDF_Error_GetCode (obj->error); |
539 | |
540 | ret += HPDF_Dict_Add (descriptor, "FontFile2" , font_data); |
541 | ret += HPDF_Dict_AddNumber (font_data, "Length1" , |
542 | def_attr->length1); |
543 | ret += HPDF_Dict_AddNumber (font_data, "Length2" , 0); |
544 | ret += HPDF_Dict_AddNumber (font_data, "Length3" , 0); |
545 | |
546 | font_data->filter = obj->filter; |
547 | |
548 | if (ret != HPDF_OK) |
549 | return HPDF_Error_GetCode (obj->error); |
550 | } |
551 | |
552 | ret += HPDF_Xref_Add (font_attr->xref, descriptor); |
553 | ret += HPDF_Dict_AddName (descriptor, "Type" , "FontDescriptor" ); |
554 | ret += HPDF_Dict_AddNumber (descriptor, "Ascent" , def->ascent); |
555 | ret += HPDF_Dict_AddNumber (descriptor, "Descent" , def->descent); |
556 | ret += HPDF_Dict_AddNumber (descriptor, "Flags" , def->flags); |
557 | |
558 | array = HPDF_Box_Array_New (obj->mmgr, def->font_bbox); |
559 | ret += HPDF_Dict_Add (descriptor, "FontBBox" , array); |
560 | |
561 | ret += HPDF_Dict_AddName (descriptor, "FontName" , def_attr->base_font); |
562 | ret += HPDF_Dict_AddNumber (descriptor, "ItalicAngle" , |
563 | def->italic_angle); |
564 | ret += HPDF_Dict_AddNumber (descriptor, "StemV" , def->stemv); |
565 | ret += HPDF_Dict_AddNumber (descriptor, "XHeight" , def->x_height); |
566 | |
567 | if (ret != HPDF_OK) |
568 | return HPDF_Error_GetCode (obj->error); |
569 | |
570 | font_attr->fontdef->descriptor = descriptor; |
571 | } |
572 | |
573 | if ((ret = HPDF_Dict_AddName (obj, "BaseFont" , |
574 | def_attr->base_font)) != HPDF_OK) |
575 | return ret; |
576 | |
577 | if ((ret = HPDF_Dict_AddName (font_attr->descendant_font, "BaseFont" , |
578 | def_attr->base_font)) != HPDF_OK) |
579 | return ret; |
580 | |
581 | return HPDF_Dict_Add (font_attr->descendant_font, "FontDescriptor" , |
582 | font_attr->fontdef->descriptor); |
583 | } |
584 | |
585 | |
586 | static HPDF_TextWidth |
587 | TextWidth (HPDF_Font font, |
588 | const HPDF_BYTE *text, |
589 | HPDF_UINT len) |
590 | { |
591 | HPDF_TextWidth tw = {0, 0, 0, 0}; |
592 | HPDF_FontAttr attr = (HPDF_FontAttr)font->attr; |
593 | HPDF_ParseText_Rec parse_state; |
594 | HPDF_Encoder encoder = attr->encoder; |
595 | HPDF_UINT i = 0; |
596 | HPDF_INT dw2; |
597 | HPDF_BYTE b = 0; |
598 | |
599 | HPDF_PTRACE ((" HPDF_Type0Font_TextWidth\n" )); |
600 | |
601 | if (attr->fontdef->type == HPDF_FONTDEF_TYPE_CID) { |
602 | HPDF_CIDFontDefAttr cid_fontdef_attr = |
603 | (HPDF_CIDFontDefAttr)attr->fontdef->attr; |
604 | dw2 = cid_fontdef_attr->DW2[1]; |
605 | } else { |
606 | dw2 = (HPDF_INT)(attr->fontdef->font_bbox.bottom - |
607 | attr->fontdef->font_bbox.top); |
608 | } |
609 | |
610 | HPDF_Encoder_SetParseText (encoder, &parse_state, text, len); |
611 | |
612 | while (i < len) { |
613 | HPDF_ByteType btype = (encoder->byte_type_fn)(encoder, &parse_state); |
614 | HPDF_UINT16 cid; |
615 | HPDF_UNICODE unicode; |
616 | HPDF_UINT16 code; |
617 | HPDF_UINT w = 0; |
618 | |
619 | b = *text++; |
620 | code = b; |
621 | |
622 | if (btype == HPDF_BYTE_TYPE_LEAD) { |
623 | code <<= 8; |
624 | code = (HPDF_UINT16)(code + *text); |
625 | } |
626 | |
627 | if (btype != HPDF_BYTE_TYPE_TRIAL) { |
628 | if (attr->writing_mode == HPDF_WMODE_HORIZONTAL) { |
629 | if (attr->fontdef->type == HPDF_FONTDEF_TYPE_CID) { |
630 | /* cid-based font */ |
631 | cid = HPDF_CMapEncoder_ToCID (encoder, code); |
632 | w = HPDF_CIDFontDef_GetCIDWidth (attr->fontdef, cid); |
633 | } else { |
634 | /* unicode-based font */ |
635 | unicode = (encoder->to_unicode_fn)(encoder, code); |
636 | w = HPDF_TTFontDef_GetCharWidth (attr->fontdef, unicode); |
637 | } |
638 | } else { |
639 | w = -dw2; |
640 | } |
641 | |
642 | tw.numchars++; |
643 | } |
644 | |
645 | if (HPDF_IS_WHITE_SPACE(code)) { |
646 | tw.numwords++; |
647 | tw.numspace++; |
648 | } |
649 | |
650 | tw.width += w; |
651 | i++; |
652 | } |
653 | |
654 | /* 2006.08.19 add. */ |
655 | if (HPDF_IS_WHITE_SPACE(b)) |
656 | ; /* do nothing. */ |
657 | else |
658 | tw.numwords++; |
659 | |
660 | return tw; |
661 | } |
662 | |
663 | |
664 | static HPDF_UINT |
665 | MeasureText (HPDF_Font font, |
666 | const HPDF_BYTE *text, |
667 | HPDF_UINT len, |
668 | HPDF_REAL width, |
669 | HPDF_REAL font_size, |
670 | HPDF_REAL char_space, |
671 | HPDF_REAL word_space, |
672 | HPDF_BOOL wordwrap, |
673 | HPDF_REAL *real_width) |
674 | { |
675 | HPDF_REAL w = 0; |
676 | HPDF_UINT tmp_len = 0; |
677 | HPDF_UINT i; |
678 | HPDF_FontAttr attr = (HPDF_FontAttr)font->attr; |
679 | HPDF_ByteType last_btype = HPDF_BYTE_TYPE_TRIAL; |
680 | HPDF_Encoder encoder = attr->encoder; |
681 | HPDF_ParseText_Rec parse_state; |
682 | HPDF_INT dw2; |
683 | |
684 | HPDF_PTRACE ((" HPDF_Type0Font_MeasureText\n" )); |
685 | |
686 | if (attr->fontdef->type == HPDF_FONTDEF_TYPE_CID) { |
687 | HPDF_CIDFontDefAttr cid_fontdef_attr = |
688 | (HPDF_CIDFontDefAttr)attr->fontdef->attr; |
689 | dw2 = cid_fontdef_attr->DW2[1]; |
690 | } else { |
691 | dw2 = (HPDF_INT)(attr->fontdef->font_bbox.bottom - |
692 | attr->fontdef->font_bbox.top); |
693 | } |
694 | |
695 | HPDF_Encoder_SetParseText (encoder, &parse_state, text, len); |
696 | |
697 | for (i = 0; i < len; i++) { |
698 | HPDF_BYTE b = *text++; |
699 | HPDF_BYTE b2 = *text; /* next byte */ |
700 | HPDF_ByteType btype = HPDF_Encoder_ByteType (encoder, &parse_state); |
701 | HPDF_UNICODE unicode; |
702 | HPDF_UINT16 code = b; |
703 | HPDF_UINT16 tmp_w = 0; |
704 | |
705 | if (btype == HPDF_BYTE_TYPE_LEAD) { |
706 | code <<= 8; |
707 | code = (HPDF_UINT16)(code + b2); |
708 | } |
709 | |
710 | if (!wordwrap) { |
711 | if (HPDF_IS_WHITE_SPACE(b)) { |
712 | tmp_len = i + 1; |
713 | if (real_width) |
714 | *real_width = w; |
715 | } else if (btype == HPDF_BYTE_TYPE_SINGLE || |
716 | btype == HPDF_BYTE_TYPE_LEAD) { |
717 | tmp_len = i; |
718 | if (real_width) |
719 | *real_width = w; |
720 | } |
721 | } else { |
722 | if (HPDF_IS_WHITE_SPACE(b)) { |
723 | tmp_len = i + 1; |
724 | if (real_width) |
725 | *real_width = w; |
726 | } /* else |
727 | //Commenting this out fixes problem with HPDF_Text_Rect() splitting the words |
728 | if (last_btype == HPDF_BYTE_TYPE_TRIAL || |
729 | (btype == HPDF_BYTE_TYPE_LEAD && |
730 | last_btype == HPDF_BYTE_TYPE_SINGLE)) { |
731 | if (!HPDF_Encoder_CheckJWWLineHead(encoder, code)) { |
732 | tmp_len = i; |
733 | if (real_width) |
734 | *real_width = w; |
735 | } |
736 | }*/ |
737 | } |
738 | |
739 | if (HPDF_IS_WHITE_SPACE(b)) { |
740 | w += word_space; |
741 | } |
742 | |
743 | if (btype != HPDF_BYTE_TYPE_TRIAL) { |
744 | if (attr->writing_mode == HPDF_WMODE_HORIZONTAL) { |
745 | if (attr->fontdef->type == HPDF_FONTDEF_TYPE_CID) { |
746 | /* cid-based font */ |
747 | HPDF_UINT16 cid = HPDF_CMapEncoder_ToCID (encoder, code); |
748 | tmp_w = HPDF_CIDFontDef_GetCIDWidth (attr->fontdef, cid); |
749 | } else { |
750 | /* unicode-based font */ |
751 | unicode = (encoder->to_unicode_fn)(encoder, code); |
752 | tmp_w = HPDF_TTFontDef_GetCharWidth (attr->fontdef, |
753 | unicode); |
754 | } |
755 | } else { |
756 | tmp_w = (HPDF_UINT16)(-dw2); |
757 | } |
758 | |
759 | if (i > 0) |
760 | w += char_space; |
761 | } |
762 | |
763 | w += (HPDF_REAL)((HPDF_DOUBLE)tmp_w * font_size / 1000); |
764 | |
765 | /* 2006.08.04 break when it encountered line feed */ |
766 | if (w > width || b == 0x0A) |
767 | return tmp_len; |
768 | |
769 | if (HPDF_IS_WHITE_SPACE(b)) |
770 | last_btype = HPDF_BYTE_TYPE_TRIAL; |
771 | else |
772 | last_btype = btype; |
773 | } |
774 | |
775 | /* all of text can be put in the specified width */ |
776 | if (real_width) |
777 | *real_width = w; |
778 | |
779 | return len; |
780 | } |
781 | |
782 | |
783 | |
784 | static char* |
785 | UINT16ToHex (char *s, |
786 | HPDF_UINT16 val, |
787 | char *eptr, |
788 | HPDF_BYTE width) |
789 | { |
790 | HPDF_BYTE b[2]; |
791 | HPDF_UINT16 val2; |
792 | char c; |
793 | |
794 | if (eptr - s < 7) |
795 | return s; |
796 | |
797 | /* align byte-order */ |
798 | HPDF_MemCpy (b, (HPDF_BYTE *)&val, 2); |
799 | val2 = (HPDF_UINT16)((HPDF_UINT16)b[0] << 8 | (HPDF_UINT16)b[1]); |
800 | |
801 | HPDF_MemCpy (b, (HPDF_BYTE *)&val2, 2); |
802 | |
803 | *s++ = '<'; |
804 | |
805 | /* |
806 | * In principle a range of <00> - <1F> can now not be |
807 | * distinguished from <0000> - <001F>..., this seems something |
808 | * that is wrong with CID ranges. For the UCS-2 encoding we need |
809 | * to add <0000> - <FFFF> and this cannot be <00> - <FFFF> (or at |
810 | * least, that crashes Mac OSX Preview). |
811 | */ |
812 | if (width == 2) { |
813 | c = b[0] >> 4; |
814 | if (c <= 9) |
815 | c += 0x30; |
816 | else |
817 | c += 0x41 - 10; |
818 | *s++ = c; |
819 | |
820 | c = (char)(b[0] & 0x0f); |
821 | if (c <= 9) |
822 | c += 0x30; |
823 | else |
824 | c += 0x41 - 10; |
825 | *s++ = c; |
826 | } |
827 | |
828 | c = (char)(b[1] >> 4); |
829 | if (c <= 9) |
830 | c += 0x30; |
831 | else |
832 | c += 0x41 - 10; |
833 | *s++ = c; |
834 | |
835 | c = (char)(b[1] & 0x0f); |
836 | if (c <= 9) |
837 | c += 0x30; |
838 | else |
839 | c += 0x41 - 10; |
840 | *s++ = c; |
841 | |
842 | *s++ = '>'; |
843 | *s = 0; |
844 | |
845 | return s; |
846 | } |
847 | |
848 | static char* |
849 | CidRangeToHex (char *s, |
850 | HPDF_UINT16 from, |
851 | HPDF_UINT16 to, |
852 | char *eptr) |
853 | { |
854 | HPDF_BYTE width = (to > 255) ? 2 : 1; |
855 | char *pbuf; |
856 | |
857 | pbuf = UINT16ToHex (s, from, eptr, width); |
858 | *pbuf++ = ' '; |
859 | pbuf = UINT16ToHex (pbuf, to, eptr, width); |
860 | |
861 | return pbuf; |
862 | } |
863 | |
864 | static HPDF_Dict |
865 | CreateCMap (HPDF_Encoder encoder, |
866 | HPDF_Xref xref) |
867 | { |
868 | HPDF_STATUS ret = HPDF_OK; |
869 | HPDF_Dict cmap = HPDF_DictStream_New (encoder->mmgr, xref); |
870 | HPDF_CMapEncoderAttr attr = (HPDF_CMapEncoderAttr)encoder->attr; |
871 | char buf[HPDF_TMP_BUF_SIZ]; |
872 | char *pbuf; |
873 | char *eptr = buf + HPDF_TMP_BUF_SIZ - 1; |
874 | HPDF_UINT i; |
875 | HPDF_UINT phase, odd; |
876 | HPDF_Dict sysinfo; |
877 | |
878 | if (!cmap) |
879 | return NULL; |
880 | |
881 | ret += HPDF_Dict_AddName (cmap, "Type" , "CMap" ); |
882 | ret += HPDF_Dict_AddName (cmap, "CMapName" , encoder->name); |
883 | |
884 | sysinfo = HPDF_Dict_New (encoder->mmgr); |
885 | if (!sysinfo) |
886 | return NULL; |
887 | |
888 | if (HPDF_Dict_Add (cmap, "CIDSystemInfo" , sysinfo) != HPDF_OK) |
889 | return NULL; |
890 | |
891 | ret += HPDF_Dict_Add (sysinfo, "Registry" , HPDF_String_New (encoder->mmgr, |
892 | attr->registry, NULL)); |
893 | ret += HPDF_Dict_Add (sysinfo, "Ordering" , HPDF_String_New (encoder->mmgr, |
894 | attr->ordering, NULL)); |
895 | ret += HPDF_Dict_AddNumber (sysinfo, "Supplement" , attr->suppliment); |
896 | ret += HPDF_Dict_AddNumber (cmap, "WMode" , |
897 | (HPDF_UINT32)attr->writing_mode); |
898 | |
899 | /* create cmap data from encoding data */ |
900 | ret += HPDF_Stream_WriteStr (cmap->stream, |
901 | "%!PS-Adobe-3.0 Resource-CMap\r\n" ); |
902 | ret += HPDF_Stream_WriteStr (cmap->stream, |
903 | "%%DocumentNeededResources: ProcSet (CIDInit)\r\n" ); |
904 | ret += HPDF_Stream_WriteStr (cmap->stream, |
905 | "%%IncludeResource: ProcSet (CIDInit)\r\n" ); |
906 | |
907 | pbuf = (char *)HPDF_StrCpy (buf, "%%BeginResource: CMap (" , eptr); |
908 | pbuf = (char *)HPDF_StrCpy (pbuf, encoder->name, eptr); |
909 | HPDF_StrCpy (pbuf, ")\r\n" , eptr); |
910 | ret += HPDF_Stream_WriteStr (cmap->stream, buf); |
911 | |
912 | pbuf = (char *)HPDF_StrCpy (buf, "%%Title: (" , eptr); |
913 | pbuf = (char *)HPDF_StrCpy (pbuf, encoder->name, eptr); |
914 | *pbuf++ = ' '; |
915 | pbuf = (char *)HPDF_StrCpy (pbuf, attr->registry, eptr); |
916 | *pbuf++ = ' '; |
917 | pbuf = (char *)HPDF_StrCpy (pbuf, attr->ordering, eptr); |
918 | *pbuf++ = ' '; |
919 | pbuf = HPDF_IToA (pbuf, attr->suppliment, eptr); |
920 | HPDF_StrCpy (pbuf, ")\r\n" , eptr); |
921 | ret += HPDF_Stream_WriteStr (cmap->stream, buf); |
922 | |
923 | ret += HPDF_Stream_WriteStr (cmap->stream, "%%Version: 1.0\r\n" ); |
924 | ret += HPDF_Stream_WriteStr (cmap->stream, "%%EndComments\r\n" ); |
925 | |
926 | ret += HPDF_Stream_WriteStr (cmap->stream, |
927 | "/CIDInit /ProcSet findresource begin\r\n\r\n" ); |
928 | |
929 | /* Adobe CMap and CIDFont Files Specification recommends to allocate |
930 | * five more elements to this dictionary than existing elements. |
931 | */ |
932 | ret += HPDF_Stream_WriteStr (cmap->stream, "12 dict begin\r\n\r\n" ); |
933 | |
934 | ret += HPDF_Stream_WriteStr (cmap->stream, "begincmap\r\n\r\n" ); |
935 | ret += HPDF_Stream_WriteStr (cmap->stream, |
936 | "/CIDSystemInfo 3 dict dup begin\r\n" ); |
937 | |
938 | pbuf = (char *)HPDF_StrCpy (buf, " /Registry (" , eptr); |
939 | pbuf = (char *)HPDF_StrCpy (pbuf, attr->registry, eptr); |
940 | HPDF_StrCpy (pbuf, ") def\r\n" , eptr); |
941 | ret += HPDF_Stream_WriteStr (cmap->stream, buf); |
942 | |
943 | pbuf = (char *)HPDF_StrCpy (buf, " /Ordering (" , eptr); |
944 | pbuf = (char *)HPDF_StrCpy (pbuf, attr->ordering, eptr); |
945 | HPDF_StrCpy (pbuf, ") def\r\n" , eptr); |
946 | ret += HPDF_Stream_WriteStr (cmap->stream, buf); |
947 | |
948 | pbuf = (char *)HPDF_StrCpy (buf, " /Supplement " , eptr); |
949 | pbuf = HPDF_IToA (pbuf, attr->suppliment, eptr); |
950 | pbuf = (char *)HPDF_StrCpy (pbuf, " def\r\n" , eptr); |
951 | HPDF_StrCpy (pbuf, "end def\r\n\r\n" , eptr); |
952 | ret += HPDF_Stream_WriteStr (cmap->stream, buf); |
953 | |
954 | pbuf = (char *)HPDF_StrCpy (buf, "/CMapName /" , eptr); |
955 | pbuf = (char *)HPDF_StrCpy (pbuf, encoder->name, eptr); |
956 | HPDF_StrCpy (pbuf, " def\r\n" , eptr); |
957 | ret += HPDF_Stream_WriteStr (cmap->stream, buf); |
958 | |
959 | ret += HPDF_Stream_WriteStr (cmap->stream, "/CMapVersion 1.0 def\r\n" ); |
960 | ret += HPDF_Stream_WriteStr (cmap->stream, "/CMapType 1 def\r\n\r\n" ); |
961 | |
962 | if (attr->uid_offset >= 0) { |
963 | pbuf = (char *)HPDF_StrCpy (buf, "/UIDOffset " , eptr); |
964 | pbuf = HPDF_IToA (pbuf, attr->uid_offset, eptr); |
965 | HPDF_StrCpy (pbuf, " def\r\n\r\n" , eptr); |
966 | ret += HPDF_Stream_WriteStr (cmap->stream, buf); |
967 | } |
968 | |
969 | pbuf = (char *)HPDF_StrCpy (buf, "/XUID [" , eptr); |
970 | pbuf = HPDF_IToA (pbuf, attr->xuid[0], eptr); |
971 | *pbuf++ = ' '; |
972 | pbuf = HPDF_IToA (pbuf, attr->xuid[1], eptr); |
973 | *pbuf++ = ' '; |
974 | pbuf = HPDF_IToA (pbuf, attr->xuid[2], eptr); |
975 | HPDF_StrCpy (pbuf, "] def\r\n\r\n" , eptr); |
976 | ret += HPDF_Stream_WriteStr (cmap->stream, buf); |
977 | |
978 | pbuf = (char *)HPDF_StrCpy (buf, "/WMode " , eptr); |
979 | pbuf = HPDF_IToA (pbuf, (HPDF_UINT32)attr->writing_mode, eptr); |
980 | HPDF_StrCpy (pbuf, " def\r\n\r\n" , eptr); |
981 | ret += HPDF_Stream_WriteStr (cmap->stream, buf); |
982 | |
983 | /* add code-space-range */ |
984 | pbuf = HPDF_IToA (buf, attr->code_space_range->count, eptr); |
985 | HPDF_StrCpy (pbuf, " begincodespacerange\r\n" , eptr); |
986 | ret += HPDF_Stream_WriteStr (cmap->stream, buf); |
987 | |
988 | for (i = 0; i < attr->code_space_range->count; i++) { |
989 | HPDF_CidRange_Rec *range = HPDF_List_ItemAt (attr->code_space_range, |
990 | i); |
991 | |
992 | pbuf = CidRangeToHex(buf, range->from, range->to, eptr); |
993 | |
994 | HPDF_StrCpy (pbuf, "\r\n" , eptr); |
995 | |
996 | ret += HPDF_Stream_WriteStr (cmap->stream, buf); |
997 | |
998 | if (ret != HPDF_OK) |
999 | return NULL; |
1000 | } |
1001 | |
1002 | HPDF_StrCpy (buf, "endcodespacerange\r\n\r\n" , eptr); |
1003 | ret += HPDF_Stream_WriteStr (cmap->stream, buf); |
1004 | if (ret != HPDF_OK) |
1005 | return NULL; |
1006 | |
1007 | /* add not-def-range */ |
1008 | pbuf = HPDF_IToA (buf, attr->notdef_range->count, eptr); |
1009 | HPDF_StrCpy (pbuf, " beginnotdefrange\r\n" , eptr); |
1010 | ret += HPDF_Stream_WriteStr (cmap->stream, buf); |
1011 | |
1012 | for (i = 0; i < attr->notdef_range->count; i++) { |
1013 | HPDF_CidRange_Rec *range = HPDF_List_ItemAt (attr->notdef_range, i); |
1014 | |
1015 | pbuf = CidRangeToHex(buf, range->from, range->to, eptr); |
1016 | *pbuf++ = ' '; |
1017 | pbuf = HPDF_IToA (pbuf, range->cid, eptr); |
1018 | HPDF_StrCpy (pbuf, "\r\n" , eptr); |
1019 | |
1020 | ret += HPDF_Stream_WriteStr (cmap->stream, buf); |
1021 | |
1022 | if (ret != HPDF_OK) |
1023 | return NULL; |
1024 | } |
1025 | |
1026 | HPDF_StrCpy (buf, "endnotdefrange\r\n\r\n" , eptr); |
1027 | ret += HPDF_Stream_WriteStr (cmap->stream, buf); |
1028 | if (ret != HPDF_OK) |
1029 | return NULL; |
1030 | |
1031 | /* add cid-range */ |
1032 | phase = attr->cmap_range->count / 100; |
1033 | odd = attr->cmap_range->count % 100; |
1034 | if (phase > 0) |
1035 | pbuf = HPDF_IToA (buf, 100, eptr); |
1036 | else |
1037 | pbuf = HPDF_IToA (buf, odd, eptr); |
1038 | HPDF_StrCpy (pbuf, " begincidrange\r\n" , eptr); |
1039 | ret += HPDF_Stream_WriteStr (cmap->stream, buf); |
1040 | |
1041 | for (i = 0; i < attr->cmap_range->count; i++) { |
1042 | HPDF_CidRange_Rec *range = HPDF_List_ItemAt (attr->cmap_range, i); |
1043 | |
1044 | pbuf = CidRangeToHex(buf, range->from, range->to, eptr); |
1045 | *pbuf++ = ' '; |
1046 | pbuf = HPDF_IToA (pbuf, range->cid, eptr); |
1047 | HPDF_StrCpy (pbuf, "\r\n" , eptr); |
1048 | |
1049 | ret += HPDF_Stream_WriteStr (cmap->stream, buf); |
1050 | |
1051 | if ((i + 1) %100 == 0) { |
1052 | phase--; |
1053 | pbuf = (char *)HPDF_StrCpy (buf, "endcidrange\r\n\r\n" , eptr); |
1054 | |
1055 | if (phase > 0) |
1056 | pbuf = HPDF_IToA (pbuf, 100, eptr); |
1057 | else |
1058 | pbuf = HPDF_IToA (pbuf, odd, eptr); |
1059 | |
1060 | HPDF_StrCpy (pbuf, " begincidrange\r\n" , eptr); |
1061 | |
1062 | ret += HPDF_Stream_WriteStr (cmap->stream, buf); |
1063 | } |
1064 | |
1065 | if (ret != HPDF_OK) |
1066 | return NULL; |
1067 | } |
1068 | |
1069 | if (odd > 0) |
1070 | pbuf = (char *)HPDF_StrCpy (buf, "endcidrange\r\n" , eptr); |
1071 | |
1072 | pbuf = (char *)HPDF_StrCpy (pbuf, "endcmap\r\n" , eptr); |
1073 | pbuf = (char *)HPDF_StrCpy (pbuf, "CMapName currentdict /CMap " |
1074 | "defineresource pop\r\n" , eptr); |
1075 | pbuf = (char *)HPDF_StrCpy (pbuf, "end\r\n" , eptr); |
1076 | pbuf = (char *)HPDF_StrCpy (pbuf, "end\r\n\r\n" , eptr); |
1077 | pbuf = (char *)HPDF_StrCpy (pbuf, "%%EndResource\r\n" , eptr); |
1078 | HPDF_StrCpy (pbuf, "%%EOF\r\n" , eptr); |
1079 | ret += HPDF_Stream_WriteStr (cmap->stream, buf); |
1080 | |
1081 | if (ret != HPDF_OK) |
1082 | return NULL; |
1083 | |
1084 | return cmap; |
1085 | } |
1086 | |
1087 | |