1/*---------------------------------------------------------------------------* 2 | PDFlib - A library for generating PDF on the fly | 3 +---------------------------------------------------------------------------+ 4 | Copyright (c) 1997-2004 Thomas Merz and PDFlib GmbH. All rights reserved. | 5 +---------------------------------------------------------------------------+ 6 | | 7 | This software is subject to the PDFlib license. It is NOT in the | 8 | public domain. Extended versions and commercial licenses are | 9 | available, please check http://www.pdflib.com. | 10 | | 11 *---------------------------------------------------------------------------*/ 12 13/* $Id: p_font.c 14574 2005-10-29 16:27:43Z bonefish $ 14 * 15 * PDFlib font handling routines 16 * 17 */ 18 19#define P_FONT_C 20 21#include "p_intern.h" 22#include "p_font.h" 23#include "p_truetype.h" 24 25 26static const pdc_keyconn pdf_extension_names[] = 27{ 28 {".ttf", 1}, 29 {".otf", 1}, 30 {".afm", 2}, 31 {".pfm", 3}, 32 {".ttc", 1}, 33 {".TTF", 1}, 34 {".OTF", 1}, 35 {".AFM", 2}, 36 {".PFM", 3}, 37 {".TTC", 1}, 38 {".pfa", 4}, 39 {".pfb", 4}, 40 {".PFA", 4}, 41 {".PFB", 4}, 42 {NULL, 0} 43}; 44 45static const pdc_keyconn pdf_fontstyle_pdfkeys[] = 46{ 47 {"Normal", pdc_Normal}, 48 {"Bold", pdc_Bold}, 49 {"Italic", pdc_Italic}, 50 {"BoldItalic", pdc_BoldItalic}, 51 {NULL, 0} 52}; 53 54const char * 55pdf_get_fontname(PDF *p) 56{ 57 if (p->fonts_number == 0 || p->tstate[p->sl].f == -1) /* no font set */ 58 pdc_error(p->pdc, PDF_E_TEXT_NOFONT_PAR, "fontname", 0, 0, 0); 59 60 return p->fonts[p->tstate[p->sl].f].name; 61} 62 63const char * 64pdf_get_fontstyle(PDF *p) 65{ 66 if (p->fonts_number == 0 || p->tstate[p->sl].f == -1) /* no font set */ 67 pdc_error(p->pdc, PDF_E_TEXT_NOFONT_PAR, "fontstyle", 0, 0, 0); 68 69 return pdc_get_keyword(p->fonts[p->tstate[p->sl].f].style, 70 pdf_fontstyle_keylist); 71} 72 73const char * 74pdf_get_fontencoding(PDF *p) 75{ 76 pdc_font *font; 77 const char *ret; 78 79 if (p->fonts_number == 0 || p->tstate[p->sl].f == -1) /* no font set */ 80 pdc_error(p->pdc, PDF_E_TEXT_NOFONT_PAR, "fontencoding", 0, 0, 0); 81 82 font = &p->fonts[p->tstate[p->sl].f]; 83 switch (font->encoding) 84 { 85 case pdc_cid: 86 ret = (const char *) font->cmapname; 87 break; 88 89 default: 90 ret = pdf_get_encoding_name(p, font->encoding); 91 } 92 93 return ret; 94} 95 96int 97pdf_get_monospace(PDF *p) 98{ 99 if (p->fonts_number == 0 || p->tstate[p->sl].f == -1) /* no font set */ 100 pdc_error(p->pdc, PDF_E_TEXT_NOFONT_PAR, "fontstyle", 0, 0, 0); 101 102 return p->fonts[p->tstate[p->sl].f].monospace; 103} 104 105int 106pdf_get_font(PDF *p) 107{ 108 if (p->fonts_number == 0 || p->tstate[p->sl].f == -1) /* no font set */ 109 pdc_error(p->pdc, PDF_E_TEXT_NOFONT_PAR, "font", 0, 0, 0); 110 111 return p->tstate[p->sl].f; 112} 113 114static void 115pdf_cleanup_font(PDF *p, pdc_font *font) 116{ 117 if (font->imgname) 118 pdf_unlock_pvf(p, font->imgname); 119 pdc_cleanup_font_struct(p->pdc, font); 120} 121 122void 123pdf_cleanup_fonts(PDF *p) 124{ 125 int slot; 126 127 if (p->fonts) 128 { 129 for (slot = 0; slot < p->fonts_number; slot++) 130 pdf_cleanup_font(p, &p->fonts[slot]); 131 132 if (p->fonts) 133 pdc_free(p->pdc, p->fonts); 134 p->fonts = NULL; 135 } 136} 137 138void 139pdf_init_fonts(PDF *p) 140{ 141 p->fonts_number = 0; 142 p->fonts_capacity = FONTS_CHUNKSIZE; 143 144 p->fonts = (pdc_font *) pdc_calloc(p->pdc, 145 sizeof(pdc_font) * p->fonts_capacity, "pdf_init_fonts"); 146 147 p->t3font = (pdc_t3font *) NULL; 148 149 pdf_init_encoding_ids(p); 150} 151 152void 153pdf_grow_fonts(PDF *p) 154{ 155 p->fonts = (pdc_font *) pdc_realloc(p->pdc, p->fonts, 156 sizeof(pdc_font) * 2 * p->fonts_capacity, "pdf_grow_fonts"); 157 158 p->fonts_capacity *= 2; 159} 160 161int 162pdf_init_newfont(PDF *p) 163{ 164 pdc_font *font; 165 int slot; 166 167 /* slot for font struct */ 168 slot = p->fonts_number; 169 if (slot >= p->fonts_capacity) 170 pdf_grow_fonts(p); 171 172 /* initialize font struct */ 173 font = &p->fonts[slot]; 174 pdc_init_font_struct(p->pdc, font); 175 176 /* inherite global settings */ 177 font->verbose = p->debug['F']; 178 font->verbose_open = font->verbose; 179 180 return slot; 181} 182 183static pdc_bool 184pdf_get_metrics_core(PDF *p, pdc_font *font, const char *fontname, 185 pdc_encoding enc) 186{ 187 const pdc_core_metric *metric; 188 189 metric = pdc_get_core_metric(fontname); 190 if (metric != NULL) 191 { 192 /* Fill up the font struct */ 193 pdc_fill_font_metric(p->pdc, font, metric); 194 font->encoding = enc; 195 196 /* Process metric data */ 197 if (pdf_process_metrics_data(p, font, fontname)) 198 { 199 if (!pdf_make_fontflag(p, font)) 200 return pdc_false; 201 202 if (font->monospace) 203 { 204 pdc_set_errmsg(p->pdc, PDC_E_OPT_IGNORED, "monospace", 0, 0, 0); 205 if (font->verbose == pdc_true) 206 pdc_error(p->pdc, -1, 0, 0, 0, 0); 207 return pdc_false; 208 } 209 return pdc_true; 210 } 211 } 212 return pdc_undef; 213} 214 215pdc_bool 216pdf_make_fontflag(PDF *p, pdc_font *font) 217{ 218 (void) p; 219 220 if (font->type != pdc_Type3) 221 { 222 if (font->isFixedPitch) 223 font->flags |= FIXEDWIDTH; 224 225 if (font->isstdlatin == pdc_true || 226 font->encoding == pdc_winansi || 227 font->encoding == pdc_macroman || 228 font->encoding == pdc_ebcdic) 229 font->flags |= ADOBESTANDARD; 230 else 231 font->flags |= SYMBOL; 232 233 if (font->italicAngle < 0 || 234 font->style == pdc_Italic || font->style == pdc_BoldItalic) 235 font->flags |= ITALIC; 236 if (font->italicAngle == 0 && font->flags & ITALIC) 237 font->italicAngle = PDC_DEF_ITALICANGLE; 238 239 /* heuristic to identify (small) caps fonts */ 240 if (font->name && 241 (strstr(font->name, "Caps") || 242 !strcmp(font->name + strlen(font->name) - 2, "SC"))) 243 font->flags |= SMALLCAPS; 244 245 if (font->style == pdc_Bold || font->style == pdc_BoldItalic) 246 font->StdVW = PDF_STEMV_BOLD; 247 248 if (strstr(font->name, "Bold") || font->StdVW > PDF_STEMV_SEMIBOLD) 249 font->flags |= FORCEBOLD; 250 } 251 252 if (font->style != pdc_Normal && 253 (font->embedding || font->type == pdc_Type1 || 254 font->type == pdc_MMType1 || font->type == pdc_Type3)) 255 { 256 pdc_set_errmsg(p->pdc, PDC_E_OPT_IGNORED, "fontstyle", 0, 0, 0); 257 if (font->verbose == pdc_true) 258 pdc_error(p->pdc, -1, 0, 0, 0, 0); 259 return pdc_false; 260 } 261 return pdc_true; 262} 263 264#define PDF_KERNING_FLAG PDC_OPT_UNSUPP 265 266#define PDF_SUBSETTING_FLAG PDC_OPT_UNSUPP 267#define PDF_AUTOSUBSETT_FLAG PDC_OPT_UNSUPP 268 269#define PDF_AUTOCIDFONT_FLAG PDC_OPT_UNSUPP 270 271/* definitions of image options */ 272static const pdc_defopt pdf_load_font_options[] = 273{ 274 {"fontwarning", pdc_booleanlist, 0, 1, 1, 0.0, 0.0, NULL}, 275 276 {"embedding", pdc_booleanlist, 0, 1, 1, 0.0, 0.0, NULL}, 277 278 {"kerning", pdc_booleanlist, PDF_KERNING_FLAG, 1, 1, 0.0, 0.0, NULL}, 279 280 {"subsetting", pdc_booleanlist, PDF_SUBSETTING_FLAG, 1, 1, 0.0, 0.0, 281 NULL}, 282 283 {"autosubsetting", pdc_booleanlist, PDF_AUTOSUBSETT_FLAG, 1, 1, 0.0, 0.0, 284 NULL}, 285 286 {"subsetlimit", pdc_floatlist, PDF_SUBSETTING_FLAG, 1, 1, 0.0, 100.0, 287 NULL}, 288 289 {"subsetminsize", pdc_floatlist, PDF_SUBSETTING_FLAG, 1, 1, 290 0.0, PDC_FLOAT_MAX, NULL}, 291 292 {"autocidfont", pdc_booleanlist, PDF_AUTOCIDFONT_FLAG, 1, 1, 0.0, 0.0, 293 NULL}, 294 295 {"unicodemap", pdc_booleanlist, PDF_AUTOCIDFONT_FLAG, 1, 1, 0.0, 0.0, 296 NULL}, 297 298 {"fontstyle", pdc_keywordlist, 0, 1, 1, 0.0, 0.0, 299 pdf_fontstyle_keylist}, 300 301 {"monospace", pdc_integerlist, 0, 1, 1, 1.0, 2048.0, 302 NULL}, 303 304 PDC_OPT_TERMINATE 305}; 306 307int 308pdf__load_font(PDF *p, const char *fontname, int inlen, 309 const char *encoding, const char *optlist) 310{ 311 static const char fn[] = "pdf__load_font"; 312 pdc_resopt *results; 313 pdc_encoding enc = pdc_invalidenc; 314 pdc_bool fontwarning; 315 pdc_bool kret; 316 int slot = -1; 317 size_t len; 318 int i; 319 int retval, inum; 320 pdc_font *font; 321 const char *extension = NULL; 322 char *fontname_p = NULL; 323 char *outfilename = NULL; 324 char *filename = NULL, testfilename[PDF_MAX_FONTNAME + 5]; 325 char *mmparam, mastername[PDF_MAX_FONTNAME + 1]; 326 327 if (encoding == NULL || *encoding == '\0') 328 pdc_error(p->pdc, PDC_E_ILLARG_EMPTY, "encoding", 0, 0, 0); 329 330 if (fontname == NULL) 331 pdc_error(p->pdc, PDC_E_ILLARG_EMPTY, "fontname", 0, 0, 0); 332 333 /* Converting fontname to UTF-8 */ 334 if (inlen) 335 { 336 pdc_byte *utf8fontname; 337 pdc_text_format textformat = pdc_bytes2; 338 pdc_text_format targettextformat = pdc_utf8; 339 int outlen; 340 341 if (pdc_convert_string(p->pdc, textformat, NULL, 342 (pdc_byte *) fontname, inlen, 343 &targettextformat, NULL, 344 &utf8fontname, &outlen, 345 PDC_CONV_WITHBOM | PDC_CONV_TRY7BYTES, 346 p->debug['F'])) 347 { 348 if (p->debug['F']) 349 pdc_error(p->pdc, -1, 0, 0, 0, 0); 350 return -1; 351 } 352 353 fontname = pdc_errprintf(p->pdc, "%s", utf8fontname); 354 pdc_free(p->pdc, utf8fontname); 355 } 356 357 if (*fontname == '\0') 358 pdc_error(p->pdc, PDC_E_ILLARG_EMPTY, "fontname", 0, 0, 0); 359 360 /* slot for new font struct */ 361 slot = pdf_init_newfont(p); 362 font = &p->fonts[slot]; 363 364 /* parsing optlist */ 365 font->verbose = p->debug['F']; 366 if (optlist && strlen(optlist)) 367 { 368 results = pdc_parse_optionlist(p->pdc, optlist, pdf_load_font_options, 369 NULL, font->verbose); 370 if (!results) 371 return -1; 372 373 /* save and check options */ 374 pdc_get_optvalues(p->pdc, "fontwarning", results, 375 &font->verbose, NULL); 376 377 pdc_get_optvalues(p->pdc, "embedding", results, 378 &font->embedding, NULL); 379 380 381 382 383 if (pdc_get_optvalues(p->pdc, "fontstyle", results, &inum, NULL)) 384 font->style = (pdc_fontstyle) inum; 385 386 pdc_get_optvalues(p->pdc, "monospace", results, 387 &font->monospace, NULL); 388 389 pdc_cleanup_optionlist(p->pdc, results); 390 } 391 392 /* search for a registered encoding */ 393 slot = -1; 394 kret = pdc_false; 395 fontwarning = p->debug['F']; 396 p->debug['F'] = (char) font->verbose; 397 enc = pdf_find_encoding(p, encoding); 398 399 if (enc == pdc_unicode || enc == pdc_glyphid) 400 pdc_error(p->pdc, PDF_E_UNSUPP_UNICODE, 0, 0, 0, 0); 401 402 if (enc == pdc_invalidenc) 403 { 404 /* check the known CMap names */ 405 slot = pdf_handle_cidfont(p, fontname, encoding); 406 if (slot == -1) 407 { 408 /* look for a new encoding */ 409 enc = pdf_insert_encoding(p, encoding); 410 if (enc == pdc_invalidenc) 411 kret = pdc_true; 412 } 413 else 414 { 415 kret = pdc_true; 416 if (slot == -2) /* error occurred in pdf_handle_cidfont() */ 417 slot = -1; 418 } 419 } 420 p->debug['F'] = (char) fontwarning; 421 if (kret) 422 return slot; 423 424 /* 425 * Look whether font is already in the cache. 426 * If a font with same encoding and same relevant options is found, 427 * return its descriptor. 428 * If a Type 3 font with the same name but different encoding 429 * is found, make a copy in a new slot and attach the requested encoding. 430 */ 431 432 for (slot = 0; slot < p->fonts_number; slot++) 433 { 434 if (!strcmp(p->fonts[slot].apiname, fontname) && 435 p->fonts[slot].style == font->style) 436 { 437 if (p->fonts[slot].type == pdc_Type3) 438 { 439 if (enc < 0 ) 440 { 441 pdc_set_errmsg(p->pdc, PDF_E_FONT_BADENC, 442 p->fonts[slot].name, 443 pdf_get_encoding_name(p, enc), 0, 0); 444 445 if (font->verbose == pdc_true) 446 pdc_error(p->pdc, -1, 0, 0, 0, 0); 447 448 return -1; 449 } 450 if (p->fonts[slot].encoding != enc) 451 slot = pdf_handle_t3font(p, fontname, enc, slot); 452 453 return slot; 454 } 455 else if (p->fonts[slot].monospace == font->monospace) 456 { 457 if (p->fonts[slot].encoding == enc) 458 { 459 return slot; 460 } 461 else if (p->fonts[slot].encoding >= 0) 462 { 463 char *encname, *adaptname; 464 int kc; 465 466 /* Comparing apiname of encoding */ 467 if (!strcmp(encoding, p->fonts[slot].encapiname)) 468 return slot; 469 470 /* Name of adapted to font encoding */ 471 encname = (char *) pdf_get_encoding_name(p, enc); 472 len = strlen(encname) + 1 + strlen(fontname) + 1; 473 adaptname = (char *) pdc_malloc(p->pdc, len, fn); 474 strcpy(adaptname, encname); 475 strcat(adaptname, PDC_ENC_MODSEPAR); 476 strcat(adaptname, fontname); 477 kc = strcmp(adaptname, 478 pdf_get_encoding_name(p, p->fonts[slot].encoding)); 479 pdc_free(p->pdc, adaptname); 480 if (!kc) 481 return slot; 482 } 483 } 484 } 485 } 486 487 488 /* Multiple Master handling: 489 * - strip MM parameters to build the master name 490 * - the master name is used to find the metrics 491 * - the instance name (client-supplied font name) is used in all places 492 * - although the master name is used for finding the metrics, the 493 * instance name is stored in the font struct. 494 */ 495 496 len = strlen(fontname); 497 if (len > PDF_MAX_FONTNAME) 498 { 499 pdc_set_errmsg(p->pdc, PDC_E_ILLARG_TOOLONG, "fontname", 500 pdc_errprintf(p->pdc, "%d", PDF_MAX_FONTNAME), 0, 0); 501 502 if (font->verbose) 503 pdc_error(p->pdc, -1, 0, 0, 0, 0); 504 505 return -1; 506 } 507 strcpy(mastername, fontname); 508 509 /* A Multiple Master font was requested */ 510 if ((mmparam = strstr(mastername, "MM_")) != NULL) 511 { 512 if (font->embedding) 513 { 514 pdc_set_errmsg(p->pdc, PDF_E_FONT_EMBEDMM, fontname, 0, 0, 0); 515 516 if (font->verbose) 517 pdc_error(p->pdc, -1, 0, 0, 0, 0); 518 519 return -1; 520 } 521 mmparam[2] = '\0'; /* strip the parameter from the master name */ 522 } 523 524 /* Font with vertical writing mode */ 525 fontname_p = mastername; 526 if (mastername[0] == '@') 527 { 528 font->vertical = pdc_true; 529 fontname_p = &mastername[1]; 530 } 531 532 /* API font name */ 533 font->apiname = pdc_strdup(p->pdc, fontname); 534 535 /* Font file search hierarchy 536 * - Check "FontOutline" resource entry and check TrueType font 537 * - Check "FontAFM" resource entry 538 * - Check "FontPFM" resource entry 539 * - Check "HostFont" resource entry 540 * - Check available in-core metrics 541 * - Check host font 542 */ 543 retval = pdc_false; 544 while (1) 545 { 546#ifdef PDF_TRUETYPE_SUPPORTED 547 /* Check specified TrueType file */ 548 filename = pdf_find_resource(p, "FontOutline", fontname_p); 549 if (filename) { 550 outfilename = filename; 551 retval = pdf_check_tt_font(p, filename, fontname_p, font); 552 if (retval == pdc_undef) { 553 retval = pdc_false; 554 break; 555 } 556 if (retval == pdc_true) { 557 retval = pdf_get_metrics_tt(p, font, fontname_p, enc, filename); 558 break; 559 } 560 } 561#endif /* PDF_TRUETYPE_SUPPORTED */ 562 563 /* Check specified AFM file */ 564 filename = pdf_find_resource(p, "FontAFM", fontname_p); 565 if (filename) { 566 retval = pdf_get_metrics_afm(p, font, fontname_p, enc, filename); 567 break; 568 } 569 570 /* Check specified PFM file */ 571 filename = pdf_find_resource(p, "FontPFM", fontname_p); 572 if (filename) { 573 retval = pdf_get_metrics_pfm(p, font, fontname_p, enc, filename); 574 break; 575 } 576 577 578 579 /* Check available in-core metrics */ 580 retval = pdf_get_metrics_core(p, font, fontname_p, enc); 581 if (retval != pdc_undef) break; 582 retval = pdc_false; 583 584 585 /* Search for a metric file */ 586 font->verbose_open = pdc_false; 587 filename = testfilename; 588 for (i = 0; i < 100; i++) 589 { 590 extension = pdf_extension_names[i].word; 591 if (!extension) break; 592 strcpy(testfilename, fontname_p); 593 strcat(testfilename, extension); 594 switch (pdf_extension_names[i].code) 595 { 596 case 1: 597 if (pdf_check_tt_font(p, filename, fontname_p, font) == 598 pdc_true) 599 retval = pdf_get_metrics_tt(p, font, fontname_p, enc, 600 filename); 601 break; 602 603 case 2: 604 retval = pdf_get_metrics_afm(p, font, fontname_p, enc, 605 filename); 606 break; 607 608 case 3: 609 retval = pdf_get_metrics_pfm(p, font, fontname_p, enc, 610 filename); 611 break; 612 } 613 if (retval == pdc_true) 614 { 615 if (pdf_extension_names[i].code == 1) 616 outfilename = filename; 617 break; 618 } 619 } 620 621 if (retval == pdc_false) 622 { 623 pdc_set_errmsg(p->pdc, PDF_E_FONT_NOMETRICS, fontname, 0, 0, 0); 624 625 if (font->verbose) 626 pdc_error(p->pdc, -1, 0, 0, 0, 0); 627 } 628 break; 629 } 630 631 if (retval == pdc_false) { 632 pdf_cleanup_font(p, font); 633 return -1; 634 } 635 636 /* store instance name instead of master name in the font structure */ 637 if (mmparam) { 638 pdc_free(p->pdc, font->name); 639 font->name = pdc_strdup(p->pdc, fontname); 640 } 641 642 /* If embedding was requested, check font file (or raise an exception) */ 643 font->verbose_open = font->verbose; 644 if (font->embedding) { 645 if (font->img == NULL) { 646 pdc_file *fp = NULL; 647 if (outfilename) { 648 if ((fp = pdf_fopen(p, outfilename, "font ", 0)) == NULL) 649 { 650 if (font->verbose) 651 pdc_error(p->pdc, -1, 0, 0, 0, 0); 652 653 retval = pdc_false; 654 } 655 if ((font->type == pdc_Type1 || font->type == pdc_MMType1) && 656 (pdf_t1check_fontfile(p, font, fp) == pdc_undef)) { 657 pdc_fclose(fp); 658 retval = pdc_false; 659 } 660 } else { 661 outfilename = testfilename; 662 for (i = 0; i < 100; i++) { 663 extension = pdf_extension_names[i].word; 664 if (!extension) break; 665 strcpy(testfilename, fontname_p); 666 strcat(testfilename, extension); 667 if (pdf_extension_names[i].code == 4 && 668 (fp = pdf_fopen(p, outfilename, NULL, 0)) != NULL) { 669 if (pdf_t1check_fontfile(p, font, fp) != pdc_undef) 670 break; 671 pdc_fclose(fp); 672 fp = NULL; 673 } 674 } 675 if (fp == NULL) 676 { 677 pdc_set_errmsg(p->pdc, PDF_E_FONT_NOOUTLINE, fontname, 678 0, 0, 0); 679 680 if (font->verbose) 681 pdc_error(p->pdc, -1, 0, 0, 0, 0); 682 683 retval = pdc_false; 684 } 685 } 686 if (retval == pdc_true) { 687 if (pdc_file_isvirtual(fp) == pdc_true) { 688 font->imgname = pdc_strdup(p->pdc, outfilename); 689 pdf_lock_pvf(p, font->imgname); 690 } 691 pdc_fclose(fp); 692 font->fontfilename = pdc_strdup(p->pdc, outfilename); 693 } 694 } 695 } else if (font->img) { 696 if (!font->imgname) { 697 pdc_free(p->pdc, font->img); 698 } else { 699 pdf_unlock_pvf(p, font->imgname); 700 pdc_free(p->pdc, font->imgname); 701 font->imgname = NULL; 702 } 703 font->img = NULL; 704 font->filelen = 0; 705 } 706 707 if (retval && font->monospace && font->embedding) 708 { 709 pdc_set_errmsg(p->pdc, PDC_E_OPT_IGNORED, "monospace", 0, 0, 0); 710 if (font->verbose == pdc_true) 711 pdc_error(p->pdc, -1, 0, 0, 0, 0); 712 retval = pdc_false; 713 } 714 715 if (retval == pdc_false) { 716 pdf_cleanup_font(p, font); 717 return -1; 718 } 719 720 /* Now everything is fine; fill the remaining font cache entries */ 721 722 p->fonts_number++; 723 724 font->verbose_open = pdc_true; 725 726 font->encapiname = pdc_strdup(p->pdc, encoding); 727 728 if (enc >= 0) 729 p->encodings[enc].ev->flags |= PDC_ENC_USED; 730 731 font->obj_id = pdc_alloc_id(p->out); 732 733 return slot; 734} 735 736PDFLIB_API int PDFLIB_CALL 737PDF_load_font(PDF *p, const char *fontname, int len, 738 const char *encoding, const char *optlist) 739{ 740 static const char fn[] = "PDF_load_font"; 741 int slot = -1; 742 743 if (pdf_enter_api(p, fn, 744 (pdf_state) (pdf_state_document | pdf_state_content), 745 "(p[%p], \"%s\", %d, \"%s\", \"%s\")", 746 (void *) p, pdc_strprint(p->pdc, fontname, len), len, encoding,optlist)) 747 { 748 slot = pdf__load_font(p, fontname, len, encoding, optlist); 749 } 750 751 PDF_RETURN_HANDLE(p, slot) 752} 753 754PDFLIB_API int PDFLIB_CALL 755PDF_findfont(PDF *p, const char *fontname, const char *encoding, int embed) 756{ 757 static const char fn[] = "PDF_findfont"; 758 char optlist[256]; 759 int slot = -1; 760 761 if (!pdf_enter_api(p, fn, 762 (pdf_state) (pdf_state_document | pdf_state_content), 763 "(p[%p], \"%s\", \"%s\", %d)", (void *) p, fontname, encoding, embed)) 764 { 765 PDF_RETURN_HANDLE(p, slot) 766 } 767 768 if (embed < 0 || embed > 1) 769 pdc_error(p->pdc, PDC_E_ILLARG_INT, 770 "embed", pdc_errprintf(p->pdc, "%d", embed), 0, 0); 771 772 optlist[0] = 0; 773 if (embed) 774 strcat(optlist, "embedding true "); 775 776 slot = pdf__load_font(p, fontname, 0, encoding, (const char *) optlist); 777 778 PDF_RETURN_HANDLE(p, slot) 779} 780 781PDFLIB_API int PDFLIB_CALL 782PDF_get_glyphid(PDF *p, int font, int code) 783{ 784 static const char fn[] = "PDF_get_glyphid"; 785 int gid = 0; 786 787 if (!pdf_enter_api(p, fn, 788 (pdf_state) (pdf_state_document | pdf_state_content | pdf_state_path), 789 "(p[%p], %d, %04X)", (void *) p, font, code)) 790 { 791 pdc_trace(p->pdc, "[%d]\n", gid); 792 return gid; 793 } 794 795 PDF_INPUT_HANDLE(p, font) 796 if (font < 0 || font >= p->fonts_number) 797 pdc_error(p->pdc, PDC_E_ILLARG_INT, 798 "font", pdc_errprintf(p->pdc, "%d", font), 0, 0); 799 800 if (code < 0 || code >= p->fonts[font].numOfCodes) 801 pdc_error(p->pdc, PDC_E_ILLARG_INT, 802 "code", pdc_errprintf(p->pdc, "%d", code), 0, 0); 803 804 if (p->fonts[font].code2GID) 805 gid = p->fonts[font].code2GID[code]; 806 else 807 pdc_error(p->pdc, PDF_E_FONT_NOGLYPHID, p->fonts[font].apiname, 0, 0,0); 808 809 pdc_trace(p->pdc, "[%d]\n", gid); 810 return gid; 811} 812 813 814static void 815pdf_write_fontdescriptor( 816 PDF *p, 817 pdc_font *font, 818 pdc_id fontdescriptor_id, 819 pdc_id fontfile_id) 820{ 821 /* 822 * Font descriptor object 823 */ 824 pdc_begin_obj(p->out, fontdescriptor_id); /* font descriptor obj */ 825 pdc_begin_dict(p->out); /* font descriptor dict */ 826 827 pdc_puts(p->out, "/Type/FontDescriptor\n"); 828 pdc_printf(p->out, "/Ascent %d\n", font->ascender); 829 pdc_printf(p->out, "/CapHeight %d\n", font->capHeight); 830 pdc_printf(p->out, "/Descent %d\n", font->descender); 831 pdc_printf(p->out, "/Flags %ld\n", font->flags); 832 pdc_printf(p->out, "/FontBBox[%d %d %d %d]\n", 833 (int) font->llx, (int) font->lly, (int) font->urx, (int) font->ury); 834 835 pdc_printf(p->out, "/FontName"); 836 pdc_put_pdfname(p->out, font->name, strlen(font->name)); 837 pdc_puts(p->out, "\n"); 838 839 pdc_printf(p->out, "/ItalicAngle %d\n", (int) (font->italicAngle)); 840 pdc_printf(p->out, "/StemV %d\n", font->StdVW); 841 842 if (font->StdHW > 0) 843 pdc_printf(p->out, "/StemH %d\n", font->StdHW); 844 845 if (font->xHeight > 0) 846 pdc_printf(p->out, "/XHeight %d\n", font->xHeight); 847 848 if (fontfile_id != PDC_BAD_ID) 849 { 850 switch(font->type) 851 { 852 case pdc_Type1: 853 case pdc_MMType1: 854 pdc_printf(p->out, "/FontFile %ld 0 R\n", fontfile_id); 855 break; 856 857#ifdef PDF_TRUETYPE_SUPPORTED 858 case pdc_TrueType: 859 case pdc_CIDFontType2: 860 pdc_printf(p->out, "/FontFile2 %ld 0 R\n", fontfile_id); 861 break; 862 863 case pdc_Type1C: 864 case pdc_CIDFontType0: 865 pdc_printf(p->out, "/FontFile3 %ld 0 R\n", fontfile_id); 866 break; 867#endif /* PDF_TRUETYPE_SUPPORTED */ 868 869 default: 870 break; 871 } 872 } 873 874 pdc_end_dict(p->out); /* font descriptor dict */ 875 pdc_end_obj(p->out); /* font descriptor obj */ 876} 877 878static void 879pdf_put_font(PDF *p, pdc_font *font) 880{ 881 const char *fontname = font->name; 882 pdc_id fontdescriptor_id = PDC_BAD_ID; 883 pdc_id fontfile_id = PDC_BAD_ID; 884 pdc_id encoding_id = PDC_BAD_ID; 885 const char *Adobe_str = "\101\144\157\142\145"; 886 pdc_id descendant_id = PDC_BAD_ID; 887 pdc_encoding enc = font->encoding; 888 pdc_bool base_font = pdc_false; 889 pdc_bool comp_font = pdc_false; 890 float a = (float) 1.0; 891 PDF_data_source src; 892 int slot, i, j; 893 894 /* 895 * This Type3 font has been defined, but never used. Ignore it. 896 * However, the font's object id has already been allocated. 897 * Write a dummy object in order to avoid a complaint 898 * of the object machinery. 899 */ 900 if (enc == pdc_invalidenc) 901 { 902 pdc_begin_obj(p->out, font->obj_id); /* dummy font obj */ 903 pdc_printf(p->out, "null %% unused Type 3 font '%s'\n", 904 font->apiname); 905 pdc_end_obj(p->out); 906 return; 907 } 908 909 910 /* ID for embedded font */ 911 if (font->embedding) 912 { 913 switch(font->type) 914 { 915 case pdc_Type1: 916 case pdc_MMType1: 917 case pdc_TrueType: 918 case pdc_CIDFontType2: 919 case pdc_Type1C: 920 case pdc_CIDFontType0: 921 fontfile_id = pdc_alloc_id(p->out); 922 break; 923 924 default: 925 break; 926 } 927 } 928 else if (font->type == pdc_Type1) 929 { 930 const char *basename; 931 932 /* check whether we have one of the base 14 fonts */ 933 for (slot = 0; ; slot++) 934 { 935 basename = pdc_get_base14_name(slot); 936 if (basename == NULL) 937 break; 938 if (!strcmp(basename, fontname)) 939 { 940 base_font = pdc_true; 941 break; 942 } 943 } 944 } 945 946 /* 947 * Font dictionary 948 */ 949 pdc_begin_obj(p->out, font->obj_id); /* font obj */ 950 pdc_begin_dict(p->out); /* font dict */ 951 pdc_puts(p->out, "/Type/Font\n"); 952 953 /* /Subtype */ 954 switch (font->type) 955 { 956 case pdc_Type1: 957 pdc_puts(p->out, "/Subtype/Type1\n"); 958 break; 959 960 case pdc_MMType1: 961 pdc_puts(p->out, "/Subtype/MMType1\n"); 962 break; 963 964 case pdc_TrueType: 965 pdc_puts(p->out, "/Subtype/TrueType\n"); 966 fontname = font->ttname; 967 break; 968 969 case pdc_Type1C: 970 fontname = font->ttname; 971 pdc_puts(p->out, "/Subtype/Type1\n"); 972 break; 973 974 case pdc_CIDFontType2: 975 case pdc_CIDFontType0: 976 fontname = font->ttname; 977 pdc_puts(p->out, "/Subtype/Type0\n"); 978 comp_font = pdc_true; 979 break; 980 981 case pdc_Type3: 982 pdc_puts(p->out, "/Subtype/Type3\n"); 983 break; 984 } 985 986 /* /Name */ 987 if (font->type == pdc_Type3) 988 { 989 /* 990 * The name is optional, but if we include it it will show up 991 * in Acrobat's font info box. However, if the same font name 992 * is used with different encodings Acrobat 4 will not be 993 * able to distinguish both. For this reason we add the 994 * encoding name to make the font name unique. 995 */ 996 pdc_puts(p->out, "/Name"); 997 pdc_put_pdfname(p->out, fontname, strlen(fontname)); 998 pdc_puts(p->out, "\n"); 999 } 1000 1001 /* /BaseFont */ 1002 switch (font->type) 1003 { 1004 case pdc_Type1: 1005 case pdc_MMType1: 1006 case pdc_TrueType: 1007 case pdc_Type1C: 1008 case pdc_CIDFontType2: 1009 case pdc_CIDFontType0: 1010 { 1011 pdc_puts(p->out, "/BaseFont"); 1012 pdc_put_pdfname(p->out, fontname, strlen(fontname)); 1013 if (font->cmapname) 1014 pdc_printf(p->out, "-%s", font->cmapname); 1015 if (font->style != pdc_Normal && !comp_font) 1016 pdc_printf(p->out, ",%s", 1017 pdc_get_keyword(font->style, pdf_fontstyle_pdfkeys)); 1018 pdc_puts(p->out, "\n"); 1019 } 1020 break; 1021 1022 /* /FontBBox, /FontMatrix, /CharProcs /Resources */ 1023 case pdc_Type3: 1024 pdc_printf(p->out, "/FontBBox[%f %f %f %f]\n", 1025 font->t3font->bbox.llx, font->t3font->bbox.lly, 1026 font->t3font->bbox.urx, font->t3font->bbox.ury); 1027 1028 pdc_printf(p->out, "/FontMatrix[%f %f %f %f %f %f]\n", 1029 font->t3font->matrix.a, font->t3font->matrix.b, 1030 font->t3font->matrix.c, font->t3font->matrix.d, 1031 font->t3font->matrix.e, font->t3font->matrix.f); 1032 pdc_printf(p->out, "/CharProcs %ld 0 R\n", font->t3font->charprocs_id); 1033 pdc_printf(p->out, "/Resources %ld 0 R\n", font->t3font->res_id); 1034 1035 /* We must apply a correctional factor since Type 3 fonts not 1036 * necessarily use 1000 units per em. We apply the correction 1037 * here, and store the 1000-based width values in the font in 1038 * order to speed up PDF_stringwidth(). 1039 */ 1040 a = (float) 1000 * font->t3font->matrix.a; 1041 break; 1042 } 1043 1044 /* /FontDescriptor, /FirstChar, /LastChar, /Widths */ 1045 switch (font->type) 1046 { 1047 case pdc_Type1: 1048 if (base_font == pdc_true) break; 1049 case pdc_MMType1: 1050 case pdc_TrueType: 1051 case pdc_Type1C: 1052 { 1053 fontdescriptor_id = pdc_alloc_id(p->out); 1054 pdc_printf(p->out, "/FontDescriptor %ld 0 R\n", fontdescriptor_id); 1055 } 1056 case pdc_Type3: 1057 { 1058 1059 pdc_puts(p->out, "/FirstChar 0\n"); 1060 pdc_puts(p->out, "/LastChar 255\n"); 1061 1062 pdc_puts(p->out, "/Widths[\n"); 1063 for (i = 0; i < 16; i++) 1064 { 1065 for (j = 0; j < 16; j++) 1066 pdc_printf(p->out, " %d", 1067 (int) ((font->widths[16*i + j]) / a + 0.5)); 1068 pdc_puts(p->out, "\n"); 1069 } 1070 pdc_puts(p->out, "]\n"); 1071 } 1072 break; 1073 1074 default: 1075 break; 1076 } 1077 1078 /* /Encoding */ 1079 switch (font->type) 1080 { 1081 case pdc_Type1: 1082 case pdc_MMType1: 1083 case pdc_TrueType: 1084 case pdc_Type1C: 1085 if (enc == pdc_winansi) 1086 { 1087 pdc_printf(p->out, "/Encoding/WinAnsiEncoding\n"); 1088 break; 1089 } 1090 if (enc == pdc_macroman && font->hasnomac == pdc_false) 1091 { 1092 pdc_printf(p->out, "/Encoding/MacRomanEncoding\n"); 1093 break; 1094 } 1095 case pdc_Type3: 1096 if (enc >= 0) 1097 { 1098 if (p->encodings[enc].id == PDC_BAD_ID) 1099 p->encodings[enc].id = pdc_alloc_id(p->out); 1100 encoding_id = p->encodings[enc].id; 1101 } 1102 if (encoding_id != PDC_BAD_ID) 1103 pdc_printf(p->out, "/Encoding %ld 0 R\n", encoding_id); 1104 break; 1105 1106 case pdc_CIDFontType2: 1107 case pdc_CIDFontType0: 1108 if (font->cmapname) 1109 pdc_printf(p->out, "/Encoding/%s\n", font->cmapname); 1110 break; 1111 } 1112 1113 1114 /* /DescendantFonts */ 1115 if (comp_font == pdc_true) 1116 { 1117 descendant_id = pdc_alloc_id(p->out); 1118 pdc_printf(p->out, "/DescendantFonts[%ld 0 R]\n", descendant_id); 1119 } 1120 1121 pdc_end_dict(p->out); /* font dict */ 1122 pdc_end_obj(p->out); /* font obj */ 1123 1124 /* 1125 * Encoding dictionary 1126 */ 1127 if (encoding_id != PDC_BAD_ID) 1128 { 1129 char *charname; 1130 1131 pdc_begin_obj(p->out, encoding_id); /* encoding obj */ 1132 pdc_begin_dict(p->out); /* encoding dict */ 1133 1134 pdc_puts(p->out, "/Type/Encoding\n"); 1135 1136 { 1137 pdc_encodingvector *ev = p->encodings[enc].ev; 1138 pdc_encodingvector *evb = NULL; 1139 int islatin1 = 1140 !strncmp((const char *) ev->apiname, "iso8859-1", 1141 strlen("iso8859-1")); 1142 1143 pdf_set_encoding_glyphnames(p, enc); 1144 1145 if (!strncmp(ev->apiname, PDC_ENC_MODWINANSI, 1146 strlen(PDC_ENC_MODWINANSI)) 1147 || islatin1) 1148 { 1149 pdc_puts(p->out, "/BaseEncoding/WinAnsiEncoding\n"); 1150 evb = p->encodings[pdc_winansi].ev; 1151 if (!evb) 1152 p->encodings[pdc_winansi].ev = 1153 pdc_copy_core_encoding(p->pdc, "winansi"); 1154 } 1155 if (!strncmp(ev->apiname, PDC_ENC_MODMACROMAN, 1156 strlen(PDC_ENC_MODMACROMAN))) 1157 { 1158 pdc_puts(p->out, "/BaseEncoding/MacRomanEncoding\n"); 1159 evb = p->encodings[pdc_macroman].ev; 1160 if (!evb) 1161 p->encodings[pdc_macroman].ev = 1162 pdc_copy_core_encoding(p->pdc, "macroman"); 1163 } 1164 1165 if (evb && font->type != pdc_Type3) 1166 { 1167 int iv = -1; 1168 for (i = 0; i < font->numOfCodes; i++) 1169 { 1170 if ((ev->chars[i] && !evb->chars[i]) || 1171 (!ev->chars[i] && evb->chars[i]) || 1172 (ev->chars[i] && evb->chars[i] && 1173 strcmp(ev->chars[i], evb->chars[i]))) 1174 { 1175 if (iv == -1) 1176 pdc_puts(p->out, "/Differences["); 1177 if (i > iv + 1) 1178 pdc_printf(p->out, "%d", i); 1179 charname = (char *) 1180 ev->chars[i] ? ev->chars[i] : (char *) ".notdef"; 1181 pdc_put_pdfname(p->out, charname, strlen(charname)); 1182 pdc_puts(p->out, "\n"); 1183 iv = i; 1184 } 1185 } 1186 if (iv > -1) 1187 pdc_puts(p->out, "]\n"); 1188 } 1189 else 1190 { 1191 pdc_puts(p->out, "/Differences[0"); 1192 for (i = 0; i < font->numOfCodes; i++) 1193 { 1194 charname = (char *) ev->chars[i] ? 1195 ev->chars[i] : (char *) ".notdef"; 1196 pdc_put_pdfname(p->out, charname, strlen(charname)); 1197 pdc_puts(p->out, "\n"); 1198 } 1199 pdc_puts(p->out, "]\n"); 1200 } 1201 } 1202 1203 pdc_end_dict(p->out); /* encoding dict */ 1204 pdc_end_obj(p->out); /* encoding obj */ 1205 1206 if (p->flush & pdf_flush_content) 1207 pdc_flush_stream(p->out); 1208 } 1209 1210 1211 /* 1212 * CID fonts dictionary 1213 */ 1214 if (descendant_id != PDC_BAD_ID) 1215 { 1216 const char *tmpstr; 1217 1218 pdc_begin_obj(p->out, descendant_id); /* CID font obj */ 1219 pdc_begin_dict(p->out); /* CID font dict */ 1220 pdc_puts(p->out, "/Type/Font\n"); 1221 1222 /* /Subtype */ 1223 if (font->type == pdc_CIDFontType0) 1224 pdc_puts(p->out, "/Subtype/CIDFontType0\n"); 1225 if (font->type == pdc_CIDFontType2) 1226 pdc_puts(p->out, "/Subtype/CIDFontType2\n"); 1227 1228 /* /BaseFont */ 1229 pdc_puts(p->out, "/BaseFont"); 1230 pdc_put_pdfname(p->out, fontname, strlen(fontname)); 1231 if (font->style != pdc_Normal) 1232 pdc_printf(p->out, ",%s", 1233 pdc_get_keyword(font->style, pdf_fontstyle_pdfkeys)); 1234 pdc_puts(p->out, "\n"); 1235 1236 /* /CIDSystemInfo */ 1237 tmpstr = pdf_get_ordering_cid(p, font); 1238 pdc_puts(p->out, "/CIDSystemInfo<</Registry"); 1239 pdc_put_pdfstring(p->out, Adobe_str, (int) strlen(Adobe_str)); 1240 pdc_puts(p->out, "/Ordering"); 1241 pdc_put_pdfstring(p->out, tmpstr, (int) strlen(tmpstr)); 1242 pdc_printf(p->out, "/Supplement %d>>\n", 1243 pdf_get_supplement_cid(p, font)); 1244 1245 /* /FontDescriptor */ 1246 fontdescriptor_id = pdc_alloc_id(p->out); 1247 pdc_printf(p->out, "/FontDescriptor %ld 0 R\n", fontdescriptor_id); 1248 1249 /* /DW /W */ 1250#ifdef PDF_CJKFONTWIDTHS_SUPPORTED 1251 if (enc == pdc_cid) 1252 pdf_put_cidglyph_widths(p, font); 1253#endif /* PDF_CJKFONTWIDTHS_SUPPORTED */ 1254 1255 1256 pdc_end_dict(p->out); /* CID font dict */ 1257 pdc_end_obj(p->out); /* CID font obj */ 1258 } 1259 1260 /* 1261 * FontDescriptor dictionary 1262 */ 1263 if (fontdescriptor_id != PDC_BAD_ID) 1264 pdf_write_fontdescriptor(p, font, fontdescriptor_id, fontfile_id); 1265 1266 /* 1267 * Font embedding 1268 */ 1269 if (fontfile_id != PDC_BAD_ID) 1270 { 1271 pdc_id length_id = PDC_BAD_ID; 1272 pdc_id length1_id = PDC_BAD_ID; 1273 pdc_id length2_id = PDC_BAD_ID; 1274 pdc_id length3_id = PDC_BAD_ID; 1275 pdc_bool hexencode = pdc_false; 1276 pdc_bool compress = pdc_false; 1277 1278 /* Prepare embedding */ 1279 switch(font->type) 1280 { 1281 case pdc_Type1: 1282 case pdc_MMType1: 1283 { 1284 pdf_make_t1src(p, font, &src); 1285 length1_id = pdc_alloc_id(p->out); 1286 length2_id = pdc_alloc_id(p->out); 1287 length3_id = pdc_alloc_id(p->out); 1288 } 1289 break; 1290 1291#ifdef PDF_TRUETYPE_SUPPORTED 1292 case pdc_TrueType: 1293 case pdc_CIDFontType2: 1294 { 1295 length1_id = pdc_alloc_id(p->out); 1296 } 1297 case pdc_Type1C: 1298 case pdc_CIDFontType0: 1299 { 1300 src.private_data = (void *) font->fontfilename; 1301 if (font->fontfilename) 1302 { 1303 /* Read the font from file */ 1304 src.init = pdf_data_source_file_init; 1305 src.fill = pdf_data_source_file_fill; 1306 src.terminate = pdf_data_source_file_terminate; 1307 switch(font->type) 1308 { 1309 case pdc_TrueType: 1310 case pdc_CIDFontType2: 1311 src.offset = (long) 0; 1312 src.length = (long) 0; 1313 break; 1314 1315 case pdc_Type1C: 1316 case pdc_CIDFontType0: 1317 src.offset = font->cff_offset; 1318 src.length = (long) font->cff_length; 1319 break; 1320 1321 default: 1322 break; 1323 } 1324 } 1325 else 1326 { 1327 /* Read the font from memory */ 1328 src.init = NULL; 1329 src.fill = pdf_data_source_buf_fill; 1330 src.terminate = NULL; 1331 switch(font->type) 1332 { 1333 case pdc_TrueType: 1334 case pdc_CIDFontType2: 1335 src.buffer_start = font->img; 1336 src.buffer_length = font->filelen; 1337 break; 1338 1339 case pdc_Type1C: 1340 case pdc_CIDFontType0: 1341 src.buffer_start = font->img + font->cff_offset; 1342 src.buffer_length = font->cff_length; 1343 break; 1344 1345 default: 1346 break; 1347 } 1348 src.bytes_available = 0; 1349 src.next_byte = NULL; 1350 } 1351 } 1352 break; 1353#endif /* PDF_TRUETYPE_SUPPORTED */ 1354 1355 default: 1356 break; 1357 } 1358 1359 /* Embedded font stream dictionary */ 1360 pdc_begin_obj(p->out, fontfile_id); /* Embedded font stream obj */ 1361 pdc_begin_dict(p->out); /* Embedded font stream dict */ 1362 1363 /* /Length, /Filter */ 1364 length_id = pdc_alloc_id(p->out); 1365 pdc_printf(p->out, "/Length %ld 0 R\n", length_id); 1366 switch(font->type) 1367 { 1368 case pdc_Type1: 1369 case pdc_MMType1: 1370 if (p->debug['a']) 1371 { 1372 hexencode = pdc_true; 1373 pdc_puts(p->out, "/Filter/ASCIIHexDecode\n"); 1374 } 1375 break; 1376 1377#ifdef PDF_TRUETYPE_SUPPORTED 1378 case pdc_TrueType: 1379 case pdc_CIDFontType2: 1380 case pdc_Type1C: 1381 case pdc_CIDFontType0: 1382 if (font->filelen != 0L) 1383 { 1384 compress = pdc_true; 1385 if (pdc_get_compresslevel(p->out)) 1386 pdc_puts(p->out, "/Filter/FlateDecode\n"); 1387 } 1388 break; 1389#endif /* PDF_TRUETYPE_SUPPORTED */ 1390 1391 default: 1392 break; 1393 } 1394 1395 /* /Length1, /Length2, Length3 */ 1396 if (length1_id != PDC_BAD_ID) 1397 pdc_printf(p->out, "/Length1 %ld 0 R\n", length1_id); 1398 if (length2_id != PDC_BAD_ID) 1399 pdc_printf(p->out, "/Length2 %ld 0 R\n", length2_id); 1400 if (length3_id != PDC_BAD_ID) 1401 pdc_printf(p->out, "/Length3 %ld 0 R\n", length3_id); 1402 1403#ifdef PDF_TRUETYPE_SUPPORTED 1404 /* /Subtype */ 1405 if(font->type == pdc_Type1C) 1406 pdc_puts(p->out, "/Subtype/Type1C\n"); 1407 if (font->type == pdc_CIDFontType0) 1408 pdc_puts(p->out, "/Subtype/CIDFontType0C\n"); 1409#endif /* PDF_TRUETYPE_SUPPORTED */ 1410 1411 pdc_end_dict(p->out); /* Embedded font stream dict */ 1412 1413 /* Stream */ 1414 if (hexencode == pdc_true) 1415 pdf_ASCIIHexEncode(p, &src); 1416 else 1417 pdf_copy_stream(p, &src, compress); 1418 1419 pdc_end_obj(p->out); /* Embedded font stream obj */ 1420 1421 pdc_put_pdfstreamlength(p->out, length_id); 1422 1423 /* Length objects */ 1424 switch(font->type) 1425 { 1426 case pdc_Type1: 1427 case pdc_MMType1: 1428 pdf_put_length_objs(p, &src, length1_id, length2_id, length3_id); 1429 break; 1430 1431#ifdef PDF_TRUETYPE_SUPPORTED 1432 case pdc_TrueType: 1433 case pdc_CIDFontType2: 1434 if (compress) 1435 { 1436 pdc_begin_obj(p->out, length1_id); /* Length1 obj */ 1437 pdc_printf(p->out, "%ld\n", (long) font->filelen); 1438 pdc_end_obj(p->out); /* Length1 obj */ 1439 } 1440 else 1441 { 1442 /* same as /Length */ 1443 pdc_put_pdfstreamlength(p->out, length1_id); 1444 } 1445 break; 1446#endif /* PDF_TRUETYPE_SUPPORTED */ 1447 1448 default: 1449 break; 1450 } 1451 } 1452 1453 if (p->flush & pdf_flush_content) 1454 pdc_flush_stream(p->out); 1455} 1456 1457void 1458pdf_write_doc_fonts(PDF *p) 1459{ 1460 int slot; 1461 1462 /* output pending font objects */ 1463 for (slot = 0; slot < p->fonts_number; slot++) 1464 { 1465 switch(p->fonts[slot].type) 1466 { 1467 case pdc_Type1: 1468 case pdc_MMType1: 1469#ifdef PDF_TRUETYPE_SUPPORTED 1470 case pdc_TrueType: 1471 case pdc_CIDFontType2: 1472 case pdc_Type1C: 1473#endif /* PDF_TRUETYPE_SUPPORTED */ 1474 case pdc_CIDFontType0: 1475 case pdc_Type3: 1476 pdf_put_font(p, &p->fonts[slot]); 1477 break; 1478 1479 default: 1480 break; 1481 } 1482 } 1483} 1484 1485void 1486pdf_write_page_fonts(PDF *p) 1487{ 1488 int i, total = 0; 1489 1490 /* This doesn't really belong here, but all modules which write 1491 * font resources also need this, so we include it here. 1492 * Note that keeping track of ProcSets is considered obsolete 1493 * starting with PDF 1.4, so we always include the full set. 1494 */ 1495 1496 pdc_puts(p->out, "/ProcSet[/PDF/ImageB/ImageC/ImageI/Text]\n"); 1497 1498 for (i = 0; i < p->fonts_number; i++) 1499 if (p->fonts[i].used_on_current_page == pdc_true) 1500 total++; 1501 1502 if (total > 0) 1503 { 1504 pdc_puts(p->out, "/Font"); 1505 1506 pdc_begin_dict(p->out); /* font resource dict */ 1507 1508 for (i = 0; i < p->fonts_number; i++) 1509 if (p->fonts[i].used_on_current_page == pdc_true) { 1510 p->fonts[i].used_on_current_page = pdc_false; /* reset */ 1511 pdc_printf(p->out, "/F%d %ld 0 R\n", i, p->fonts[i].obj_id); 1512 } 1513 1514 pdc_end_dict(p->out); /* font resource dict */ 1515 } 1516} 1517