1 /* Copyright (C) 1996, 2000 Aladdin Enterprises. All rights reserved. 2 3 This file is part of Aladdin Ghostscript. 4 5 Aladdin Ghostscript is distributed with NO WARRANTY OF ANY KIND. No author 6 or distributor accepts any responsibility for the consequences of using it, 7 or for whether it serves any particular purpose or works at all, unless he 8 or she says so in writing. Refer to the Aladdin Ghostscript Free Public 9 License (the "License") for full details. 10 11 Every copy of Aladdin Ghostscript must include a copy of the License, 12 normally in a plain ASCII text file named PUBLIC. The License grants you 13 the right to copy, modify and redistribute Aladdin Ghostscript, but only 14 under certain conditions described in the License. Among other things, the 15 License requires that the copyright notice and this notice be preserved on 16 all copies. 17 */ 18 19 /*$Id: gdevpdft.c,v 1.3 2000/03/16 01:21:24 lpd Exp $ */ 20 /* Text handling for PDF-writing driver. */ 21 #include "math_.h" 22 #include "memory_.h" 23 #include "string_.h" 24 #include "gx.h" 25 #include "gserrors.h" 26 #include "gsmatrix.h" 27 #include "gsutil.h" /* for bytes_compare */ 28 #include "gxfixed.h" /* for gxfcache.h */ 29 #include "gxfont.h" 30 #include "gxfont0.h" 31 #include "gxfont1.h" 32 #include "gxfont42.h" 33 #include "gxfcache.h" /* for orig_fonts list */ 34 #include "gxpath.h" /* for getting current point */ 35 #include "gdevpdfx.h" 36 #include "gdevpdff.h" 37 #include "scommon.h" 38 39 /* 40 * The PDF documentation does a pretty shoddy job of specifying use of fonts 41 * beyond the base 14, and on top of that, Acrobat Reader has some serious 42 * bugs. Specifically, Acrobat Reader 3's Print function has a bug that 43 * make re-encoded characters print as blank if the font is substituted (not 44 * embedded or one of the base 14). 45 * 46 * We do have to handle re-encoded Type 1 fonts, because TeX output makes 47 * constant use of them. We have several alternatives for how to handle 48 * characters whose encoding doesn't match their encoding in the base font's 49 * built-in encoding. If a character's glyph doesn't match the character's 50 * glyph in the encoding built up so far, we check if the font has that 51 * glyph at all; if not, we fall back to a bitmap. Otherwise, we use one or 52 * both of the following algorithms: 53 * 54 * 1. If this is the first time a character at this position has been 55 * seen, assign its glyph to that position in the encoding. 56 * We do this step if the device parameter ReAssignCharacters is true. 57 * (This is the default.) 58 * 59 * 2. If the glyph is present in the encoding at some other position, 60 * substitute that position for the character; otherwise, assign the 61 * glyph to an unoccupied (.notdef) position. 62 * We do this step if the device parameter ReEncodeCharacters is true. 63 * (This is the default.) 64 * 65 * 3. Finally, fall back to using a bitmap. 66 * 67 * If it is essential that all strings in the output contain exactly the 68 * same character codes as the input, set ReEncodeCharacters to false. If 69 * it is important that strings be searchable, but some non-searchable 70 * strings can be tolerated, the defaults are appropriate. If searchability 71 * is not important, set ReAssignCharacters to false. 72 * 73 * Since the chars_used bit vector keeps track of characters by their 74 * position in the Encoding, not by their glyph identifier, it can't record 75 * use of unencoded characters. Therefore, if we ever use an unencoded 76 * character in an embedded font, we force writing the entire font rather 77 * than a subset. This is inelegant but (for the moment) too awkward to 78 * fix. 79 * 80 * Because of the AR3 printing bug, if CompatibilityLevel <= 1.2, for 81 * non-embedded non-base fonts, no substitutions or re-encodings are allowed. 82 */ 83 84 /* Forward references */ 85 private int pdf_set_font_and_size(P3(gx_device_pdf * pdev, pdf_font_t * font, 86 floatp size)); 87 private int pdf_set_text_matrix(P2(gx_device_pdf * pdev, 88 const gs_matrix * pmat)); 89 private int pdf_append_chars(P3(gx_device_pdf * pdev, const byte * str, 90 uint size)); 91 92 /* Define the text enumerator. */ 93 typedef struct pdf_text_enum_s { 94 gs_text_enum_common; 95 gs_text_enum_t *pte_default; 96 gs_fixed_point origin; 97 } pdf_text_enum_t; 98 extern_st(st_gs_text_enum); 99 gs_private_st_suffix_add1(st_pdf_text_enum, pdf_text_enum_t, "pdf_text_enum_t", 100 pdf_text_enum_enum_ptrs, pdf_text_enum_reloc_ptrs, st_gs_text_enum, 101 pte_default); 102 103 /* 104 * Define quantities derived from the current font and CTM, used within 105 * the text processing loop. 106 */ 107 typedef struct pdf_text_process_state_s { 108 float chars; /* scaled character spacing (Tc) */ 109 float words; /* scaled word spacing (Tw) */ 110 float size; /* font size for Tf */ 111 gs_matrix text_matrix; /* normalized FontMatrix * CTM for Tm */ 112 pdf_font_t *pdfont; 113 } pdf_text_process_state_t; 114 115 /* Define the auxiliary procedures for text processing. */ 116 private int 117 pdf_text_resync(gs_text_enum_t *pte, const gs_text_enum_t *pfrom) 118 { 119 pdf_text_enum_t *const penum = (pdf_text_enum_t *)pte; 120 121 if ((pte->text.operation ^ pfrom->text.operation) & ~TEXT_FROM_ANY) 122 return_error(gs_error_rangecheck); 123 if (penum->pte_default) { 124 int code = gs_text_resync(penum->pte_default, pfrom); 125 126 if (code < 0) 127 return code; 128 } 129 pte->text = pfrom->text; 130 gs_text_enum_copy_dynamic(pte, pfrom, false); 131 return 0; 132 } 133 private bool 134 pdf_text_is_width_only(const gs_text_enum_t *pte) 135 { 136 const pdf_text_enum_t *const penum = (const pdf_text_enum_t *)pte; 137 138 if (penum->pte_default) 139 return gs_text_is_width_only(penum->pte_default); 140 return false; 141 } 142 private int 143 pdf_text_current_width(const gs_text_enum_t *pte, gs_point *pwidth) 144 { 145 const pdf_text_enum_t *const penum = (const pdf_text_enum_t *)pte; 146 147 if (penum->pte_default) 148 return gs_text_current_width(penum->pte_default, pwidth); 149 return_error(gs_error_rangecheck); /* can't happen */ 150 } 151 private int 152 pdf_text_set_cache(gs_text_enum_t *pte, const double *pw, 153 gs_text_cache_control_t control) 154 { 155 pdf_text_enum_t *const penum = (pdf_text_enum_t *)pte; 156 157 if (penum->pte_default) 158 return gs_text_set_cache(penum->pte_default, pw, control); 159 return_error(gs_error_rangecheck); /* can't happen */ 160 } 161 private int 162 pdf_text_retry(gs_text_enum_t *pte) 163 { 164 pdf_text_enum_t *const penum = (pdf_text_enum_t *)pte; 165 166 if (penum->pte_default) 167 return gs_text_retry(penum->pte_default); 168 return_error(gs_error_rangecheck); /* can't happen */ 169 } 170 private void 171 pdf_text_release(gs_text_enum_t *pte, client_name_t cname) 172 { 173 pdf_text_enum_t *const penum = (pdf_text_enum_t *)pte; 174 175 if (penum->pte_default) { 176 gs_text_release(penum->pte_default, cname); 177 penum->pte_default = 0; 178 } 179 gx_default_text_release(pte, cname); 180 } 181 182 /* Begin processing text. */ 183 private text_enum_proc_process(pdf_text_process); 184 private const gs_text_enum_procs_t pdf_text_procs = { 185 pdf_text_resync, pdf_text_process, 186 pdf_text_is_width_only, pdf_text_current_width, 187 pdf_text_set_cache, pdf_text_retry, 188 pdf_text_release 189 }; 190 int 191 gdev_pdf_text_begin(gx_device * dev, gs_imager_state * pis, 192 const gs_text_params_t *text, gs_font * font, 193 gx_path * path, const gx_device_color * pdcolor, 194 const gx_clip_path * pcpath, 195 gs_memory_t * mem, gs_text_enum_t ** ppte) 196 { 197 gx_device_pdf *const pdev = (gx_device_pdf *)dev; 198 pdf_text_enum_t *penum; 199 gs_fixed_point cpt; 200 int code; 201 202 if ((text->operation & 203 ~(TEXT_FROM_STRING | TEXT_FROM_BYTES | 204 TEXT_ADD_TO_ALL_WIDTHS | TEXT_ADD_TO_SPACE_WIDTH | 205 TEXT_REPLACE_WIDTHS | 206 TEXT_DO_DRAW | TEXT_RETURN_WIDTH)) != 0 || 207 !gx_dc_is_pure(pdcolor) || 208 gx_path_current_point(path, &cpt) < 0 209 ) 210 return gx_default_text_begin(dev, pis, text, font, path, pdcolor, 211 pcpath, mem, ppte); 212 213 /* Set the clipping path and color. */ 214 215 if (pdf_must_put_clip_path(pdev, pcpath)) { 216 int code = pdf_open_page(pdev, PDF_IN_STREAM); 217 218 if (code < 0) 219 return code; 220 pdf_put_clip_path(pdev, pcpath); 221 } 222 pdf_set_color(pdev, gx_dc_pure_color(pdcolor), &pdev->fill_color, 223 &psdf_set_fill_color_commands); 224 225 /* Allocate and initialize the enumerator. */ 226 227 rc_alloc_struct_1(penum, pdf_text_enum_t, &st_pdf_text_enum, mem, 228 return_error(gs_error_VMerror), "gdev_pdf_text_begin"); 229 penum->rc.free = rc_free_text_enum; 230 penum->pte_default = 0; 231 code = gs_text_enum_init((gs_text_enum_t *)penum, &pdf_text_procs, 232 dev, pis, text, font, path, pdcolor, pcpath, mem); 233 if (code < 0) { 234 gs_free_object(mem, penum, "gdev_pdf_text_begin"); 235 return code; 236 } 237 238 if (text->operation & TEXT_RETURN_WIDTH) 239 gx_path_current_point(path, &penum->origin); 240 *ppte = (gs_text_enum_t *)penum; 241 242 return 0; 243 } 244 245 /* 246 * Create a new pdf_font for a gs_font. This is a separate procedure only 247 * for readability: it is only called from one place in 248 * pdf_update_text_state. 249 */ 250 private int 251 create_pdf_font(gx_device_pdf *pdev, gs_font *font, const gs_matrix *pomat, 252 pdf_font_t **pppf) 253 { 254 int index = -1; 255 pdf_font_t ftemp; 256 int BaseEncoding = ENCODING_INDEX_UNKNOWN; 257 int same = 0, base_same = 0; 258 pdf_font_embed_t embed = 259 pdf_font_embed_status(pdev, font, &index, &same); 260 bool have_widths = false; 261 bool is_standard = false; 262 long ffid = 0; 263 pdf_font_descriptor_t *pfd; 264 gs_font *base_font = font; 265 gs_font *below; 266 pdf_font_descriptor_t fdesc; 267 pdf_font_t *ppf; 268 int code; 269 #define BASE_UID(fnt) (&((const gs_font_base *)(fnt))->UID) 270 271 /* Find the "lowest" base font that has the same outlines. */ 272 while ((below = base_font->base) != base_font && 273 base_font->procs.same_font(base_font, below, 274 FONT_SAME_OUTLINES)) 275 base_font = below; 276 set_base: 277 if (base_font == font) 278 base_same = same; 279 else 280 embed = pdf_font_embed_status(pdev, base_font, &index, &base_same); 281 if (embed == FONT_EMBED_STANDARD && pdev->std_fonts[index].font != 0) { 282 /* Use the standard font as the base font. */ 283 base_font = pdev->std_fonts[index].font; 284 is_standard = true; 285 } else if (embed == FONT_EMBED_YES && 286 base_font->FontType != ft_composite && 287 uid_is_valid(BASE_UID(base_font)) && 288 !base_font->is_resource 289 ) { 290 /* 291 * The base font has a UID, but it isn't a resource. Look for a 292 * resource with the same UID, in the hope that that will be 293 * longer-lived. 294 */ 295 gs_font *orig = base_font->dir->orig_fonts; 296 297 for (; orig; orig = orig->next) 298 if (orig != base_font && orig->FontType == base_font->FontType && 299 orig->is_resource && 300 uid_equal(BASE_UID(base_font), BASE_UID(orig)) 301 ) { 302 /* Use this as the base font instead. */ 303 base_font = orig; 304 /* 305 * Recompute the embedding status of the base font. This 306 * can't lead to a loop, because base_font->is_resource is 307 * now known to be true. 308 */ 309 goto set_base; 310 } 311 } 312 313 /* See if we already have a descriptor for this base font. */ 314 pfd = (pdf_font_descriptor_t *) 315 pdf_find_resource_by_gs_id(pdev, resourceFontDescriptor, 316 base_font->id); 317 if (pfd != 0 && pfd->base_font != base_font) 318 pfd = 0; 319 320 /* Create an appropriate font and descriptor. */ 321 322 switch (embed) { 323 case FONT_EMBED_YES: 324 /* 325 * HACK: Acrobat Reader 3 has a bug that makes cmap formats 4 326 * and 6 not work in embedded TrueType fonts. Consequently, it 327 * can only handle embedded TrueType fonts if all the glyphs 328 * referenced by the Encoding have numbers 0-255. Check for 329 * this now. 330 */ 331 if (font->FontType == ft_TrueType && 332 pdev->CompatibilityLevel <= 1.2 333 ) { 334 int i; 335 336 for (i = 0; i <= 0xff; ++i) { 337 gs_glyph glyph = 338 font->procs.encode_char(font, (gs_char)i, 339 GLYPH_SPACE_INDEX); 340 341 if (glyph == gs_no_glyph || 342 (glyph >= gs_min_cid_glyph && 343 glyph <= gs_min_cid_glyph + 0xff) 344 ) 345 continue; 346 /* Can't embed, punt. */ 347 return_error(gs_error_rangecheck); 348 } 349 } 350 /* 351 * Acrobat Reader doesn't accept embedded Multiple Master 352 * instances, and we haven't been able to figure out why. 353 */ 354 if (font->FontType == ft_encrypted && 355 ((const gs_font_type1 *)font)->data.WeightVector.count > 0) 356 return_error(gs_error_rangecheck); 357 code = pdf_compute_font_descriptor(pdev, &fdesc, font, NULL); 358 if (code < 0) 359 return code; 360 ffid = pdf_obj_ref(pdev); 361 goto wf; 362 case FONT_EMBED_NO: 363 /* 364 * Per the PDF 1.3 documentation, there are only 3 BaseEncoding 365 * values allowed for non-embedded fonts. Pick one here. 366 */ 367 BaseEncoding = 368 ((const gs_font_base *)base_font)->nearest_encoding_index; 369 switch (BaseEncoding) { 370 default: 371 BaseEncoding = ENCODING_INDEX_WINANSI; 372 case ENCODING_INDEX_WINANSI: 373 case ENCODING_INDEX_MACROMAN: 374 case ENCODING_INDEX_MACEXPERT: 375 break; 376 } 377 code = pdf_compute_font_descriptor(pdev, &fdesc, font, NULL); 378 if (code < 0) 379 return code; 380 wf: 381 /* The font isn't standard: make sure we write the Widths. */ 382 same &= ~FONT_SAME_METRICS; 383 /* falls through */ 384 case FONT_EMBED_STANDARD: 385 if (~same & (FONT_SAME_METRICS | FONT_SAME_ENCODING)) { 386 /* 387 * Before allocating the font resource, check that we can 388 * get all the widths. 389 */ 390 int i; 391 392 memset(&ftemp, 0, sizeof(ftemp)); 393 for (i = 0; i <= 255; ++i) { 394 code = pdf_char_width(&ftemp, i, font, NULL); 395 if (code < 0 && code != gs_error_undefined) 396 return code; 397 } 398 have_widths = true; 399 } 400 if (pfd) { 401 code = pdf_alloc_font(pdev, font->id, &ppf, gs_no_id); 402 if (code < 0) 403 return code; 404 if_debug4('_', 405 "[_]created pdf_font_t 0x%lx, id %ld, FontDescriptor 0x%lx, id %ld (old)\n", 406 (ulong)ppf, pdf_resource_id((pdf_resource_t *)ppf), 407 (ulong)pfd, pdf_resource_id((pdf_resource_t *)pfd)); 408 ppf->FontDescriptor = pfd; 409 } else { 410 int name_index = index; 411 412 code = pdf_alloc_font(pdev, font->id, &ppf, base_font->id); 413 if (code < 0) 414 return code; 415 pfd = ppf->FontDescriptor; 416 if_debug4('_', 417 "[_]created pdf_font_t 0x%lx, id %ld, FontDescriptor 0x%lx, id %ld (new)\n", 418 (ulong)ppf, pdf_resource_id((pdf_resource_t *)ppf), 419 (ulong)pfd, pdf_resource_id((pdf_resource_t *)pfd)); 420 if (index < 0) { 421 int ignore_same; 422 423 memcpy(pfd->FontName.chars, base_font->font_name.chars, 424 base_font->font_name.size); 425 pfd->FontName.size = base_font->font_name.size; 426 pfd->values = fdesc.values; 427 pfd->FontFile_id = ffid; 428 pfd->base_font = base_font; 429 pfd->orig_matrix = *pomat; 430 /* Don't allow non-standard fonts with standard names. */ 431 pdf_font_embed_status(pdev, base_font, &name_index, 432 &ignore_same); 433 } else { 434 /* Use the standard name. */ 435 const pdf_standard_font_t *ppsf = &pdf_standard_fonts[index]; 436 const char *fnchars = ppsf->fname; 437 uint fnsize = strlen(fnchars); 438 439 memcpy(pfd->FontName.chars, fnchars, fnsize); 440 pfd->FontName.size = fnsize; 441 } 442 if (!is_standard) { 443 code = pdf_adjust_font_name(pdev, pfd, name_index >= 0); 444 if (code < 0) 445 return code; 446 } 447 } 448 ppf->FontType = font->FontType; 449 ppf->index = index; 450 switch (font->FontType) { 451 case ft_encrypted: 452 case ft_encrypted2: 453 ppf->is_MM_instance = 454 ((const gs_font_type1 *)font)->data.WeightVector.count > 0; 455 default: 456 DO_NOTHING; 457 } 458 ppf->BaseEncoding = BaseEncoding; 459 ppf->fname = pfd->FontName; 460 ppf->font = font; 461 if (~same & FONT_SAME_METRICS) { 462 /* 463 * Contrary to the PDF 1.3 documentation, FirstChar and 464 * LastChar are *not* simply a way to strip off initial and 465 * final entries in the Widths array that are equal to 466 * MissingWidth. Acrobat Reader assumes that characters 467 * with codes less than FirstChar or greater than LastChar 468 * are undefined, without bothering to consult the Encoding. 469 * Therefore, the implicit value of MissingWidth is pretty 470 * useless, because there must be explicit Width entries for 471 * every character in the font that is ever used. 472 * Furthermore, if there are several subsets of the same 473 * font in a document, it appears to be random as to which 474 * one Acrobat Reader uses to decide what the FirstChar and 475 * LastChar values are. Therefore, we must write the Widths 476 * array for the entire font even for subsets. 477 */ 478 ppf->write_Widths = true; 479 pdf_find_char_range(font, &ppf->FirstChar, &ppf->LastChar); 480 } 481 if (have_widths) { 482 /* 483 * C's bizarre coercion rules make us use memcpy here 484 * rather than direct assignments, even though sizeof() 485 * gives the correct value.... 486 */ 487 memcpy(ppf->Widths, ftemp.Widths, sizeof(ppf->Widths)); 488 memcpy(ppf->widths_known, ftemp.widths_known, 489 sizeof(ppf->widths_known)); 490 } 491 code = pdf_register_font(pdev, font, ppf); 492 } 493 494 *pppf = ppf; 495 return code; 496 } 497 498 /* 499 * Compute the cached values in the text state from the text parameters, 500 * current_font, and pis->ctm. 501 */ 502 private int 503 pdf_update_text_state(pdf_text_process_state_t *ppts, 504 const pdf_text_enum_t *penum, const gs_matrix *pfmat) 505 { 506 gx_device_pdf *const pdev = (gx_device_pdf *)penum->dev; 507 gs_font *font = penum->current_font; 508 pdf_font_t *ppf; 509 gs_fixed_point cpt; 510 gs_matrix orig_matrix, smat, tmat; 511 double 512 sx = pdev->HWResolution[0] / 72.0, 513 sy = pdev->HWResolution[1] / 72.0; 514 float chars, words, size; 515 int code = gx_path_current_point(penum->path, &cpt); 516 517 if (code < 0) 518 return code; 519 520 /* PDF always uses 1000 units per em for font metrics. */ 521 switch (font->FontType) { 522 case ft_TrueType: 523 /* 524 * ****** HACK ALERT ****** 525 * 526 * The code above that calls pdf_find_char_range does so the first 527 * time the font is used. This causes an incorrect (too small) 528 * Widths array to be written if the font is downloaded 529 * incrementally. In practice, this appears only to be a problem 530 * for TrueType fonts written by certain Windows drivers 531 * (including AdobePS5 for Windows NT). Fortunately, it is easy 532 * to determine whether the font is an incremental one: this is 533 * the case iff the font doesn't have glyf and loca entries. 534 * In this case, we punt and treat the font as bitmaps. 535 */ 536 if (((const gs_font_type42 *)font)->data.glyf == 0) 537 return_error(gs_error_rangecheck); /* incremental */ 538 /* The TrueType FontMatrix is 1 unit per em, which is what we want. */ 539 gs_make_identity(&orig_matrix); 540 break; 541 case ft_encrypted: 542 case ft_encrypted2: 543 gs_make_scaling(0.001, 0.001, &orig_matrix); 544 break; 545 default: 546 return_error(gs_error_rangecheck); 547 } 548 DISCARD(pdf_find_orig_font(pdev, font, &orig_matrix)); 549 550 /* Compute the scaling matrix and combined matrix. */ 551 552 gs_matrix_invert(&orig_matrix, &smat); 553 gs_matrix_multiply(&smat, pfmat, &smat); 554 tmat = ctm_only(penum->pis); 555 tmat.tx = tmat.ty = 0; 556 gs_matrix_multiply(&smat, &tmat, &tmat); 557 558 /* Try to find a reasonable size value. This isn't necessary, */ 559 /* but it's worth a little effort. */ 560 561 size = fabs(tmat.yy) / sy; 562 if (size < 0.01) 563 size = fabs(tmat.xx) / sx; 564 if (size < 0.01) 565 size = 1; 566 567 /* Check for spacing parameters we can handle, and transform them. */ 568 569 if (penum->text.operation & TEXT_ADD_TO_ALL_WIDTHS) { 570 gs_point pt; 571 572 gs_distance_transform_inverse(penum->text.delta_all.x, 573 penum->text.delta_all.y, 574 &smat, &pt); 575 if (pt.y != 0) 576 return_error(gs_error_rangecheck); 577 chars = pt.x * size; 578 } else 579 chars = 0.0; 580 581 if (penum->text.operation & TEXT_ADD_TO_SPACE_WIDTH) { 582 gs_point pt; 583 584 gs_distance_transform_inverse(penum->text.delta_space.x, 585 penum->text.delta_space.y, 586 &smat, &pt); 587 if (pt.y != 0 || penum->text.space.s_char != 32) 588 return_error(gs_error_rangecheck); 589 words = pt.x * size; 590 } else 591 words = 0.0; 592 593 /* Find or create the font resource. */ 594 595 ppf = (pdf_font_t *) 596 pdf_find_resource_by_gs_id(pdev, resourceFont, font->id); 597 /* Check for the possibility that the base font has been freed. */ 598 if (ppf && ppf->FontDescriptor->written) 599 ppf = 0; 600 if (ppf == 0 || ppf->font == 0) { 601 code = create_pdf_font(pdev, font, &orig_matrix, &ppf); 602 if (code < 0) 603 return code; 604 } 605 606 /* Store the updated values. */ 607 608 tmat.xx /= size; 609 tmat.xy /= size; 610 tmat.yx /= size; 611 tmat.yy /= size; 612 tmat.tx += fixed2float(cpt.x); 613 tmat.ty += fixed2float(cpt.y); 614 615 ppts->chars = chars; 616 ppts->words = words; 617 ppts->size = size; 618 ppts->text_matrix = tmat; 619 ppts->pdfont = ppf; 620 621 return 0; 622 } 623 624 /* Check whether a glyph exists in a (pseudo-)encoding. */ 625 private bool 626 encoding_has_glyph(gs_font_base *bfont, gs_glyph font_glyph, 627 gs_encoding_index_t index) 628 { 629 int ch; 630 gs_glyph glyph; 631 632 for (ch = 0; 633 (glyph = bfont->procs.callbacks.known_encode((gs_char)ch, index)) != 634 gs_no_glyph; 635 ++ch) 636 if (glyph == font_glyph) 637 return true; 638 return false; 639 } 640 641 /* 642 * For a given character, check whether the encoding of bfont (the current 643 * font) is compatible with that of the underlying unscaled, possibly 644 * standard, base font, and if not, whether we can re-encode the character 645 * using the base font's encoding. Return the (possibly re-encoded) 646 * character if successful. 647 */ 648 inline private void 649 record_used(pdf_font_descriptor_t *pfd, int c) 650 { 651 pfd->chars_used[c >> 3] |= 1 << (c & 7); 652 } 653 private int 654 pdf_encode_char(gx_device_pdf *pdev, int chr, gs_font_base *bfont, 655 pdf_font_t *ppf) 656 { 657 pdf_font_descriptor_t *const pfd = ppf->FontDescriptor; 658 /* 659 * bfont is the current font in which the text is being shown. 660 * ei is its encoding_index. 661 */ 662 gs_encoding_index_t ei = bfont->encoding_index; 663 /* 664 * base_font is the font that underlies this PDF font (i.e., this PDF 665 * font is base_font plus some possible Encoding and Widths differences, 666 * and possibly a different FontMatrix). base_font is 0 iff this PDF 667 * font is one of the standard 14 (i.e., ppf->index != 668 * ENCODING_INDEX_UNKNOWN). bei is the index of the BaseEncoding 669 * (explicit or, for the standard fonts, implicit) that will be written 670 * in the PDF file: it is not necessarily the same as 671 * base_font->encoding_index, or even base_font->nearest_encoding_index. 672 */ 673 gs_font *base_font = pfd->base_font; 674 bool have_font = base_font != 0 && base_font->FontType != ft_composite; 675 bool is_standard = ppf->index != ENCODING_INDEX_UNKNOWN; 676 gs_encoding_index_t bei = 677 (ppf->BaseEncoding != ENCODING_INDEX_UNKNOWN ? ppf->BaseEncoding : 678 is_standard ? pdf_standard_fonts[ppf->index].base_encoding : 679 ENCODING_INDEX_UNKNOWN); 680 pdf_encoding_element_t *pdiff = ppf->Differences; 681 /* 682 * If set, font_glyph is the glyph currently associated with chr in 683 * base_font + bei + diffs; glyph is the glyph corresponding to chr in 684 * bfont. 685 */ 686 gs_glyph font_glyph, glyph; 687 #define IS_USED(c)\ 688 (((pfd)->chars_used[(c) >> 3] & (1 << ((c) & 7))) != 0) 689 690 if (ei == bei && ei != ENCODING_INDEX_UNKNOWN && pdiff == 0) { 691 /* 692 * Just note that the character has been used with its original 693 * encoding. 694 */ 695 record_used(pfd, chr); 696 return chr; 697 } 698 if (!is_standard && !have_font) 699 return_error(gs_error_undefined); /* can't encode */ 700 701 #define ENCODE_NO_DIFF(ch)\ 702 (bei != ENCODING_INDEX_UNKNOWN ?\ 703 bfont->procs.callbacks.known_encode((gs_char)(ch), bei) :\ 704 /* have_font */ bfont->procs.encode_char(base_font, chr, GLYPH_SPACE_NAME)) 705 #define HAS_DIFF(ch) (pdiff != 0 && pdiff[ch].str.data != 0) 706 #define ENCODE_DIFF(ch) (pdiff[ch].glyph) 707 #define ENCODE(ch)\ 708 (HAS_DIFF(ch) ? ENCODE_DIFF(ch) : ENCODE_NO_DIFF(ch)) 709 710 font_glyph = ENCODE(chr); 711 glyph = 712 (ei == ENCODING_INDEX_UNKNOWN ? 713 bfont->procs.encode_char((gs_font *)bfont, chr, GLYPH_SPACE_NAME) : 714 bfont->procs.callbacks.known_encode(chr, ei)); 715 if (glyph == font_glyph) { 716 record_used(pfd, chr); 717 return chr; 718 } 719 720 if (ppf->index == ENCODING_INDEX_UNKNOWN && pfd->FontFile_id == 0 && 721 pdev->CompatibilityLevel <= 1.2 722 ) { 723 /* 724 * Work around the bug in Acrobat Reader 3's Print function 725 * that makes re-encoded characters in substituted fonts 726 * print as blank. 727 */ 728 return_error(gs_error_undefined); 729 } 730 731 /* 732 * TrueType fonts don't allow Differences in the encoding, but we might 733 * be able to re-encode the character if it appears elsewhere in the 734 * encoding. 735 */ 736 if (bfont->FontType == ft_TrueType) { 737 if (pdev->ReEncodeCharacters) { 738 int c; 739 740 for (c = 0; c < 256; ++c) 741 if (ENCODE_NO_DIFF(c) == glyph) { 742 record_used(pfd, c); 743 return c; 744 } 745 } 746 return_error(gs_error_undefined); 747 } 748 749 /* 750 * If the font isn't going to be embedded, check whether this glyph is 751 * available in the base font's glyph set at all. 752 */ 753 if (pfd->FontFile_id == 0) { 754 switch (bei) { 755 case ENCODING_INDEX_STANDARD: 756 case ENCODING_INDEX_ISOLATIN1: 757 case ENCODING_INDEX_WINANSI: 758 case ENCODING_INDEX_MACROMAN: 759 /* Check the full Adobe glyph set(s). */ 760 if (!encoding_has_glyph(bfont, glyph, ENCODING_INDEX_ALOGLYPH) && 761 (pdev->CompatibilityLevel < 1.3 || 762 !encoding_has_glyph(bfont, glyph, ENCODING_INDEX_ALXGLYPH)) 763 ) 764 return_error(gs_error_undefined); 765 default: 766 break; 767 } 768 } 769 770 if (pdev->ReAssignCharacters) { 771 /* 772 * If this is the first time we've seen this character, 773 * assign the glyph to its position in the encoding. 774 */ 775 if (!HAS_DIFF(chr) && !IS_USED(chr)) { 776 int code = 777 pdf_add_encoding_difference(pdev, ppf, chr, bfont, glyph); 778 779 if (code >= 0) { 780 /* 781 * As noted in the comments at the beginning of this file, 782 * we don't have any way to record, for the purpose of 783 * subsetting, the fact that a particular unencoded glyph 784 * was used. If this glyph doesn't appear anywhere else in 785 * the base encoding, fall back to writing the entire font. 786 */ 787 int c; 788 789 for (c = 0; c < 256; ++c) 790 if (ENCODE_NO_DIFF(c) == glyph) 791 break; 792 if (c < 256) /* found */ 793 record_used(pfd, c); 794 else /* not found */ 795 pfd->subset_ok = false; 796 return chr; 797 } 798 } 799 } 800 801 if (pdev->ReEncodeCharacters) { 802 /* 803 * Look for the character at some other position in the 804 * encoding. 805 */ 806 int c, code; 807 808 for (c = 0; c < 256; ++c) { 809 if (HAS_DIFF(c)) { 810 if (ENCODE_DIFF(c) == glyph) 811 return c; 812 } else if (ENCODE_NO_DIFF(c) == glyph) { 813 record_used(pfd, c); 814 return c; 815 } 816 } 817 /* 818 * The character isn't encoded anywhere. Look for a 819 * never-referenced .notdef position where we can put it. 820 */ 821 for (c = 0; c < 256; ++c) { 822 gs_const_string gnstr; 823 824 if (HAS_DIFF(c) || IS_USED(c)) 825 continue; /* slot already referenced */ 826 font_glyph = ENCODE_NO_DIFF(c); 827 if (font_glyph == gs_no_glyph) 828 break; 829 gnstr.data = (const byte *) 830 bfont->procs.callbacks.glyph_name(font_glyph, 831 &gnstr.size); 832 if (gnstr.size == 7 && 833 !memcmp(gnstr.data, ".notdef", 7) 834 ) 835 break; 836 } 837 if (c == 256) /* no .notdef positions left */ 838 return_error(gs_error_undefined); 839 code = pdf_add_encoding_difference(pdev, ppf, c, bfont, glyph); 840 if (code < 0) 841 return code; 842 /* See under ReAssignCharacters above regarding the following: */ 843 pfd->subset_ok = false; 844 return c; 845 } 846 847 return_error(gs_error_undefined); 848 849 #undef IS_USED 850 #undef ENCODE_NO_DIFF 851 #undef HAS_DIFF 852 #undef ENCODE_DIFF 853 #undef ENCODE 854 } 855 856 /* 857 * Write out commands to make the output state match the processing state. 858 */ 859 private int 860 pdf_write_text_process_state(gx_device_pdf *pdev, 861 const pdf_text_process_state_t *ppts, 862 const gs_const_string *pstr) 863 { 864 int code; 865 stream *s; 866 867 pdf_set_font_and_size(pdev, ppts->pdfont, ppts->size); 868 code = pdf_set_text_matrix(pdev, &ppts->text_matrix); 869 if (code < 0) 870 return code; 871 872 if (pdev->text.character_spacing != ppts->chars && 873 pstr->size + pdev->text.buffer_count > 1 874 ) { 875 code = pdf_open_page(pdev, PDF_IN_TEXT); 876 if (code < 0) 877 return code; 878 s = pdev->strm; 879 pprintg1(s, "%g Tc\n", ppts->chars); 880 pdev->text.character_spacing = ppts->chars; 881 } 882 883 if (pdev->text.word_spacing != ppts->words && 884 (memchr(pstr->data, 32, pstr->size) || 885 memchr(pdev->text.buffer, 32, pdev->text.buffer_count)) 886 ) { 887 code = pdf_open_page(pdev, PDF_IN_TEXT); 888 if (code < 0) 889 return code; 890 s = pdev->strm; 891 pprintg1(s, "%g Tw\n", ppts->words); 892 pdev->text.word_spacing = ppts->words; 893 } 894 895 return 0; 896 } 897 898 /* 899 * Continue processing text. Per the check in pdf_text_begin, we know the 900 * operation is TEXT_FROM_STRING/BYTES, TEXT_DO_DRAW, and possibly 901 * TEXT_ADD_TO_ALL_WIDTHS, TEXT_ADD_TO_SPACE_WIDTH, TEXT_REPLACE_WIDTHS, 902 * and/or TEXT_RETURN_WIDTH. 903 */ 904 private int 905 pdf_text_process(gs_text_enum_t *pte) 906 { 907 pdf_text_enum_t *const penum = (pdf_text_enum_t *)pte; 908 gx_device_pdf *const pdev = (gx_device_pdf *)penum->dev; 909 gs_text_enum_t *pte_default = penum->pte_default; 910 gs_font *font; 911 gs_matrix fmat; 912 const gs_text_params_t *text = &pte->text; 913 gs_text_params_t alt_text; 914 pdf_text_process_state_t text_state; 915 gs_const_string str; 916 int i; 917 byte strbuf[200]; /* arbitrary */ 918 int code; 919 920 top: 921 if (pte_default) { 922 /* Continue processing using the default algorithms. */ 923 code = gs_text_process(pte_default); 924 gs_text_enum_copy_dynamic(pte, pte_default, true); 925 if (code) 926 return code; 927 gs_text_release(pte_default, "pdf_text_process"); 928 penum->pte_default = pte_default = 0; 929 /****** FOR NOW ******/ 930 return 0; 931 } 932 str.data = text->data.bytes; 933 str.size = text->size; 934 font = penum->current_font; 935 fmat = font->FontMatrix; 936 fnt: 937 switch (font->FontType) { 938 case ft_TrueType: 939 case ft_encrypted: 940 case ft_encrypted2: 941 break; 942 case ft_composite: { 943 gs_font_type0 *const font0 = (gs_font_type0 *)font; 944 /* 945 * Support just one special format, which is used by some versions 946 * of the Adobe PS4 driver even for single-byte text. 947 */ 948 switch (font0->data.FMapType) { 949 case fmap_8_8: 950 if (str.size > sizeof(strbuf) * 2) 951 goto dflt; 952 for (i = 0; i < str.size; i += 2) { 953 if (str.data[i] != 0) 954 goto dflt; 955 strbuf[i >> 1] = str.data[i + 1]; 956 } 957 str.data = strbuf; 958 str.size >>= 1; 959 font = penum->current_font = font0->data.FDepVector[0]; 960 /* 961 * The FontMatrix of descendant base fonts is not scaled by 962 * scalefont/makefont. 963 */ 964 if (font->FontType != ft_composite) 965 gs_matrix_multiply(&fmat, &font->FontMatrix, &fmat); 966 goto fnt; 967 default: 968 goto dflt; 969 } 970 break; 971 } 972 default: 973 goto dflt; 974 } 975 976 code = pdf_update_text_state(&text_state, penum, &fmat); 977 if (code < 0) 978 goto dflt; 979 980 /* Check that all characters can be encoded. */ 981 982 for (i = 0; i < str.size; ++i) { 983 int chr = str.data[i]; 984 int code = pdf_encode_char(pdev, chr, (gs_font_base *)font, 985 text_state.pdfont); 986 987 if (code < 0) 988 goto dflt; 989 if (code != chr) { 990 /* 991 * It really simplifies things if we can buffer 992 * the entire string locally in one piece.... 993 */ 994 if (str.data != strbuf) { 995 if (str.size > sizeof(strbuf)) 996 goto dflt; 997 memcpy(strbuf, str.data, str.size); 998 str.data = strbuf; 999 } 1000 strbuf[i] = (byte)code; 1001 } 1002 } 1003 1004 /* Bring the text-related parameters in the output up to date. */ 1005 1006 code = pdf_write_text_process_state(pdev, &text_state, &str); 1007 if (code < 0) 1008 goto dflt; 1009 1010 if (text->operation & TEXT_REPLACE_WIDTHS) { 1011 gs_point w; 1012 gs_matrix tmat; 1013 1014 w.x = w.y = 0; 1015 tmat = text_state.text_matrix; 1016 for (; pte->index < str.size; pte->index++, pte->xy_index++) { 1017 gs_point d, dpt; 1018 1019 code = pdf_append_chars(pdev, str.data + pte->index, 1); 1020 if (code < 0) 1021 return code; 1022 gs_text_replaced_width(&pte->text, pte->xy_index, &d); 1023 w.x += d.x, w.y += d.y; 1024 gs_distance_transform(d.x, d.y, &ctm_only(pte->pis), &dpt); 1025 tmat.tx += dpt.x; 1026 tmat.ty += dpt.y; 1027 if (pte->index + 1 < str.size) { 1028 code = pdf_set_text_matrix(pdev, &tmat); 1029 if (code < 0) 1030 return code; 1031 } 1032 } 1033 pte->returned.total_width = w; 1034 return 1035 (text->operation & TEXT_RETURN_WIDTH ? 1036 gx_path_add_point(pte->path, float2fixed(tmat.tx), 1037 float2fixed(tmat.ty)) : 1038 0); 1039 } 1040 code = pdf_append_chars(pdev, str.data + pte->index, 1041 str.size - pte->index); 1042 pte->index = 0; 1043 if (code < 0) 1044 goto dflt; 1045 /* 1046 * If we don't need the widths, return now. If the widths are 1047 * available directly from the font, compute and return the total 1048 * width now. Otherwise, call the default implementation. 1049 */ 1050 if (!(text->operation & TEXT_RETURN_WIDTH)) 1051 return 0; 1052 { 1053 int i, w; 1054 double scale = (font->FontType == ft_TrueType ? 0.001 : 1.0); 1055 gs_point dpt; 1056 int num_spaces = 0; 1057 1058 for (i = pte->index, w = 0; i < str.size; ++i) { 1059 int cw; 1060 int code = 1061 pdf_char_width(text_state.pdfont, str.data[i], font, &cw); 1062 1063 if (code < 0) 1064 goto dflt_w; 1065 w += cw; 1066 if (str.data[i] == ' ') 1067 ++num_spaces; 1068 } 1069 gs_distance_transform(w * scale, 0.0, &font->FontMatrix, &dpt); 1070 if (text->operation & TEXT_ADD_TO_ALL_WIDTHS) { 1071 int num_chars = str.size - pte->index; 1072 1073 dpt.x += penum->text.delta_all.x * num_chars; 1074 dpt.y += penum->text.delta_all.y * num_chars; 1075 } 1076 if (text->operation & TEXT_ADD_TO_SPACE_WIDTH) { 1077 dpt.x += penum->text.delta_space.x * num_spaces; 1078 dpt.y += penum->text.delta_space.y * num_spaces; 1079 } 1080 pte->returned.total_width = dpt; 1081 gs_distance_transform(dpt.x, dpt.y, &ctm_only(pte->pis), &dpt); 1082 return gx_path_add_point(pte->path, 1083 penum->origin.x + float2fixed(dpt.x), 1084 penum->origin.y + float2fixed(dpt.y)); 1085 } 1086 dflt_w: 1087 alt_text = *text; 1088 alt_text.operation ^= TEXT_DO_DRAW | TEXT_DO_CHARWIDTH; 1089 text = &alt_text; 1090 dflt: 1091 code = gx_default_text_begin(pte->dev, pte->pis, text, pte->current_font, 1092 pte->path, pte->pdcolor, pte->pcpath, 1093 pte->memory, &penum->pte_default); 1094 if (code < 0) 1095 return code; 1096 pte_default = penum->pte_default; 1097 gs_text_enum_copy_dynamic(pte_default, pte, false); 1098 goto top; 1099 } 1100 1101 /* ---------------- Text and font utilities ---------------- */ 1102 1103 /* Forward declarations */ 1104 private int assign_char_code(P1(gx_device_pdf * pdev)); 1105 1106 /* 1107 * Set the current font and size, writing a Tf command if needed. 1108 */ 1109 private int 1110 pdf_set_font_and_size(gx_device_pdf * pdev, pdf_font_t * font, floatp size) 1111 { 1112 if (font != pdev->text.font || size != pdev->text.size) { 1113 int code = pdf_open_page(pdev, PDF_IN_TEXT); 1114 stream *s = pdev->strm; 1115 1116 if (code < 0) 1117 return code; 1118 pprints1(s, "/%s ", font->frname); 1119 pprintg1(s, "%g Tf\n", size); 1120 pdev->text.font = font; 1121 pdev->text.size = size; 1122 } 1123 font->used_on_page = true; 1124 return 0; 1125 } 1126 1127 /* 1128 * Set the text matrix for writing text. 1129 * The translation component of the matrix is the text origin. 1130 * If the non-translation components of the matrix differ from the 1131 * current ones, write a Tm command; otherwise, write either a Td command 1132 * or a Tj command using space pseudo-characters. 1133 */ 1134 private int 1135 set_text_distance(gs_point *pdist, const gs_point *ppt, const gs_matrix *pmat) 1136 { 1137 double rounded; 1138 1139 gs_distance_transform_inverse(pmat->tx - ppt->x, pmat->ty - ppt->y, 1140 pmat, pdist); 1141 /* If the distance is very close to integers, round it. */ 1142 if (fabs(pdist->x - (rounded = floor(pdist->x + 0.5))) < 0.0005) 1143 pdist->x = rounded; 1144 if (fabs(pdist->y - (rounded = floor(pdist->y + 0.5))) < 0.0005) 1145 pdist->y = rounded; 1146 return 0; 1147 } 1148 private int 1149 pdf_set_text_matrix(gx_device_pdf * pdev, const gs_matrix * pmat) 1150 { 1151 stream *s = pdev->strm; 1152 double sx = 72.0 / pdev->HWResolution[0], 1153 sy = 72.0 / pdev->HWResolution[1]; 1154 int code; 1155 1156 if (pmat->xx == pdev->text.matrix.xx && 1157 pmat->xy == pdev->text.matrix.xy && 1158 pmat->yx == pdev->text.matrix.yx && 1159 pmat->yy == pdev->text.matrix.yy && 1160 /* 1161 * If we aren't already in text context, BT will reset 1162 * the text matrix. 1163 */ 1164 (pdev->context == PDF_IN_TEXT || pdev->context == PDF_IN_STRING) 1165 ) { 1166 /* Use Td or a pseudo-character. */ 1167 gs_point dist; 1168 1169 set_text_distance(&dist, &pdev->text.current, pmat); 1170 if (dist.y == 0 && dist.x >= X_SPACE_MIN && 1171 dist.x <= X_SPACE_MAX && 1172 pdev->text.font != 0 && 1173 PDF_FONT_IS_SYNTHESIZED(pdev->text.font) 1174 ) { /* Use a pseudo-character. */ 1175 int dx = (int)dist.x; 1176 int dx_i = dx - X_SPACE_MIN; 1177 byte space_char = pdev->text.font->spaces[dx_i]; 1178 1179 if (space_char == 0) { 1180 if (pdev->text.font != pdev->open_font) 1181 goto td; 1182 code = assign_char_code(pdev); 1183 if (code <= 0) 1184 goto td; 1185 space_char = 1186 pdev->open_font->spaces[dx_i] = 1187 (byte) code; 1188 if (pdev->space_char_ids[dx_i] == 0) { 1189 /* Create the space char_proc now. */ 1190 char spstr[3 + 14 + 1]; 1191 stream *s; 1192 1193 sprintf(spstr, "%d 0 0 0 0 0 d1\n", dx); 1194 pdev->space_char_ids[dx_i] = pdf_begin_separate(pdev); 1195 s = pdev->strm; 1196 pprintd1(s, "<</Length %d>>\nstream\n", strlen(spstr)); 1197 pprints1(s, "%sendstream\n", spstr); 1198 pdf_end_separate(pdev); 1199 } 1200 } 1201 pdf_append_chars(pdev, &space_char, 1); 1202 pdev->text.current.x += dist.x * pmat->xx; 1203 return 0; 1204 } 1205 td: /* Use Td. */ 1206 code = pdf_open_page(pdev, PDF_IN_TEXT); 1207 if (code < 0) 1208 return code; 1209 set_text_distance(&dist, &pdev->text.line_start, pmat); 1210 pprintg2(s, "%g %g Td\n", dist.x, dist.y); 1211 } else { /* Use Tm. */ 1212 code = pdf_open_page(pdev, PDF_IN_TEXT); 1213 if (code < 0) 1214 return code; 1215 /* 1216 * See stream_to_text in gdevpdf.c for why we need the following 1217 * matrix adjustments. 1218 */ 1219 pprintg6(pdev->strm, "%g %g %g %g %g %g Tm\n", 1220 pmat->xx * sx, pmat->xy * sy, 1221 pmat->yx * sx, pmat->yy * sy, 1222 pmat->tx * sx, pmat->ty * sy); 1223 pdev->text.matrix = *pmat; 1224 } 1225 pdev->text.line_start.x = pmat->tx; 1226 pdev->text.line_start.y = pmat->ty; 1227 pdev->text.current.x = pmat->tx; 1228 pdev->text.current.y = pmat->ty; 1229 return 0; 1230 } 1231 1232 /* Append characters to a string being accumulated. */ 1233 private int 1234 pdf_append_chars(gx_device_pdf * pdev, const byte * str, uint size) 1235 { 1236 const byte *p = str; 1237 uint left = size; 1238 1239 while (left) 1240 if (pdev->text.buffer_count == max_text_buffer) { 1241 int code = pdf_open_page(pdev, PDF_IN_TEXT); 1242 1243 if (code < 0) 1244 return code; 1245 } else { 1246 int code = pdf_open_page(pdev, PDF_IN_STRING); 1247 uint copy; 1248 1249 if (code < 0) 1250 return code; 1251 copy = min(max_text_buffer - pdev->text.buffer_count, left); 1252 memcpy(pdev->text.buffer + pdev->text.buffer_count, p, copy); 1253 pdev->text.buffer_count += copy; 1254 p += copy; 1255 left -= copy; 1256 } 1257 return 0; 1258 } 1259 1260 /* ---------------- Synthesized fonts ---------------- */ 1261 1262 /* Assign a code for a char_proc. */ 1263 private int 1264 assign_char_code(gx_device_pdf * pdev) 1265 { 1266 pdf_font_t *font = pdev->open_font; 1267 1268 if (pdev->embedded_encoding_id == 0) { 1269 long id = pdf_begin_separate(pdev); 1270 stream *s = pdev->strm; 1271 int i; 1272 1273 /* 1274 * Even though the PDF reference documentation says that a 1275 * BaseEncoding key is required unless the encoding is 1276 * "based on the base font's encoding" (and there is no base 1277 * font in this case), Acrobat 2.1 gives an error if the 1278 * BaseEncoding key is present. 1279 */ 1280 pputs(s, "<</Type/Encoding/Differences[0"); 1281 for (i = 0; i < 256; ++i) { 1282 if (!(i & 15)) 1283 pputs(s, "\n"); 1284 pprintd1(s, "/a%d", i); 1285 } 1286 pputs(s, "\n] >>\n"); 1287 pdf_end_separate(pdev); 1288 pdev->embedded_encoding_id = id; 1289 } 1290 if (font == 0 || font->num_chars == 256) { 1291 /* Start a new synthesized font. */ 1292 int code = pdf_alloc_font(pdev, gs_no_id, &font, gs_no_id); 1293 char *pc; 1294 1295 if (code < 0) 1296 return code; 1297 strcpy(font->frname, pdev->open_font_name); 1298 for (pc = font->frname; *pc == 'Z'; ++pc) 1299 *pc = '@'; 1300 if ((*pc)++ == 0) 1301 *pc = 'A', pc[1] = 0; 1302 pdev->open_font = font; 1303 strcpy(pdev->open_font_name, font->frname); 1304 } 1305 return font->num_chars++; 1306 } 1307 1308 /* Begin a CharProc for a synthesized (bitmap) font. */ 1309 int 1310 pdf_begin_char_proc(gx_device_pdf * pdev, int w, int h, int x_width, 1311 int y_offset, gs_id id, pdf_char_proc_t ** ppcp, pdf_stream_position_t * ppos) 1312 { 1313 pdf_resource_t *pres; 1314 pdf_char_proc_t *pcp; 1315 int char_code = assign_char_code(pdev); 1316 pdf_font_t *font = pdev->open_font; 1317 int code; 1318 1319 if (char_code < 0) 1320 return char_code; 1321 code = pdf_begin_resource(pdev, resourceCharProc, id, &pres); 1322 if (code < 0) 1323 return code; 1324 pcp = (pdf_char_proc_t *) pres; 1325 pcp->font = font; 1326 pcp->char_next = font->char_procs; 1327 font->char_procs = pcp; 1328 pcp->char_code = char_code; 1329 pcp->width = w; 1330 pcp->height = h; 1331 pcp->x_width = x_width; 1332 pcp->y_offset = y_offset; 1333 font->max_y_offset = max(font->max_y_offset, h + (h >> 2)); 1334 *ppcp = pcp; 1335 { 1336 stream *s = pdev->strm; 1337 1338 /* 1339 * The resource file is positionable, so rather than use an 1340 * object reference for the length, we'll go back and fill it in 1341 * at the end of the definition. Take 10K as the longest 1342 * definition we can handle. 1343 */ 1344 pputs(s, "<</Length >>\nstream\n"); 1345 ppos->start_pos = stell(s); 1346 } 1347 return 0; 1348 } 1349 1350 /* End a CharProc. */ 1351 int 1352 pdf_end_char_proc(gx_device_pdf * pdev, pdf_stream_position_t * ppos) 1353 { 1354 stream *s = pdev->strm; 1355 long start_pos = ppos->start_pos; 1356 long end_pos = stell(s); 1357 long length = end_pos - start_pos; 1358 1359 if (length > 9999) 1360 return_error(gs_error_limitcheck); 1361 sseek(s, start_pos - 14); 1362 pprintd1(s, "%d", length); 1363 sseek(s, end_pos); 1364 pputs(s, "endstream\n"); 1365 pdf_end_separate(pdev); 1366 return 0; 1367 } 1368 1369 /* Put out a reference to an image as a character in a synthesized font. */ 1370 int 1371 pdf_do_char_image(gx_device_pdf * pdev, const pdf_char_proc_t * pcp, 1372 const gs_matrix * pimat) 1373 { 1374 pdf_set_font_and_size(pdev, pcp->font, 1.0); 1375 { 1376 gs_matrix tmat; 1377 1378 tmat = *pimat; 1379 tmat.ty -= pcp->y_offset; 1380 pdf_set_text_matrix(pdev, &tmat); 1381 } 1382 pdf_append_chars(pdev, &pcp->char_code, 1); 1383 pdev->text.current.x += pcp->x_width * pdev->text.matrix.xx; 1384 return 0; 1385 } 1386