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
22static HPDF_Font
23CIDFontType0_New (HPDF_Font parent,
24 HPDF_Xref xref);
25
26
27static HPDF_Font
28CIDFontType2_New (HPDF_Font parent,
29 HPDF_Xref xref);
30
31
32static HPDF_TextWidth
33TextWidth (HPDF_Font font,
34 const HPDF_BYTE *text,
35 HPDF_UINT len);
36
37
38static HPDF_UINT
39MeasureText (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
50static char*
51UINT16ToHex (char *s,
52 HPDF_UINT16 val,
53 char *eptr,
54 HPDF_BYTE width);
55
56static char *
57CidRangeToHex (char *s,
58 HPDF_UINT16 from,
59 HPDF_UINT16 to,
60 char *eptr);
61
62static HPDF_Dict
63CreateCMap (HPDF_Encoder encoder,
64 HPDF_Xref xref);
65
66
67static void
68OnFree_Func (HPDF_Dict obj);
69
70
71static HPDF_STATUS
72CIDFontType2_BeforeWrite_Func (HPDF_Dict obj);
73
74
75/*--------------------------------------------------------------------------*/
76
77HPDF_Font
78HPDF_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
196static void
197OnFree_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
207static HPDF_Font
208CIDFontType0_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
343static HPDF_Font
344CIDFontType2_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
506static HPDF_STATUS
507CIDFontType2_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
586static HPDF_TextWidth
587TextWidth (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
664static HPDF_UINT
665MeasureText (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
784static char*
785UINT16ToHex (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
848static char*
849CidRangeToHex (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
864static HPDF_Dict
865CreateCMap (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