1 /* Copyright (C) 2002 Aladdin Enterprises. All rights reserved.
2
3 This software is provided AS-IS with no warranty, either express or
4 implied.
5
6 This software is distributed under license and may not be copied,
7 modified or distributed except as expressly authorized under the terms
8 of the license contained in the file LICENSE in this distribution.
9
10 For more information about licensing, please refer to
11 http://www.ghostscript.com/licensing/. For information on
12 commercial licensing, go to http://www.artifex.com/licensing/ or
13 contact Artifex Software, Inc., 101 Lucas Valley Road #110,
14 San Rafael, CA 94903, U.S.A., +1(415)492-9861.
15 */
16
17 /* $Id: gdevpdtd.c,v 1.22 2005/04/05 15:44:44 igor Exp $ */
18 /* FontDescriptor implementation for pdfwrite */
19 #include "math_.h"
20 #include "memory_.h"
21 #include "gx.h"
22 #include "gserrors.h"
23 #include "gsrect.h" /* for rect_merge */
24 #include "gdevpdfx.h"
25 #include "gdevpdfo.h" /* for object->written */
26 #include "gdevpdtb.h"
27 #include "gdevpdtd.h"
28
29 /* ================ Types and structures ================ */
30
31 /*
32 * There are many different flavors of FontDescriptor. The first division
33 * is between FontDescriptors for actual fonts, and character class entries
34 * in the FD dictionary of a CID-keyed font. The latter include metrics and
35 * a FontName but nothing else. We represent these with a different C
36 * structure (pdf_sub_font_descriptor_t).
37 *
38 * Descriptors for actual fonts have three major orthogonal properties:
39 *
40 * - Whether they represent a CID-keyed font or a name-keyed
41 * (non-CID-keyed) font. We distinguish this by the FontType
42 * of the saved font (see below).
43 *
44 * - Whether the font they represent is embedded.
45 *
46 * - Whether the font they represent is a complete font or a subset.
47 * We always track which glyphs in a font are used: client code
48 * decides whether to treat the font as a subset when the
49 * descriptor (and, if embedded, the font) is written.
50 *
51 * Note that non-embedded fonts in the base set of 14 do not have
52 * descriptors, nor do Type 0 or (synthetic bitmap) Type 3 fonts.
53 */
54 /*
55 * Start by defining the elements common to font descriptors and sub-font
56 * (character class) descriptors.
57 */
58 typedef struct pdf_font_descriptor_values_s {
59 /* Required elements */
60 int Ascent, CapHeight, Descent, ItalicAngle, StemV;
61 gs_int_rect FontBBox;
62 gs_string FontName;
63 uint Flags;
64 /* Optional elements (default to 0) */
65 int AvgWidth, Leading, MaxWidth, MissingWidth, StemH, XHeight;
66 } pdf_font_descriptor_values_t;
67 typedef struct pdf_font_descriptor_common_s pdf_font_descriptor_common_t;
68 struct pdf_font_descriptor_common_s {
69 pdf_resource_common(pdf_font_descriptor_common_t);
70 pdf_font_descriptor_values_t values;
71 };
72 /* Flag bits */
73 /*#define FONT_IS_FIXED_WIDTH (1<<0)*/ /* defined in gxfont.h */
74 #define FONT_IS_SERIF (1<<1)
75 #define FONT_IS_SYMBOLIC (1<<2)
76 #define FONT_IS_SCRIPT (1<<3)
77 /*
78 * There is confusion over the meaning of the 1<<5 bit. According to the
79 * published PDF documentation, in PDF 1.1, it meant "font uses
80 * StandardEncoding", and as of PDF 1.2, it means "font uses (a subset of)
81 * the Adobe standard Latin character set"; however, Acrobat Reader 3 and 4
82 * seem to use the former interpretation, even if the font is embedded and
83 * the file is identified as a PDF 1.2 file. We have to use the former
84 * interpretation in order to produce output that Acrobat will handle
85 * correctly.
86 */
87 #define FONT_USES_STANDARD_ENCODING (1<<5) /* always used */
88 #define FONT_IS_ADOBE_ROMAN (1<<5) /* never used */
89 #define FONT_IS_ITALIC (1<<6)
90 #define FONT_IS_ALL_CAPS (1<<16)
91 #define FONT_IS_SMALL_CAPS (1<<17)
92 #define FONT_IS_FORCE_BOLD (1<<18)
93
94 /*
95 * Define a (top-level) FontDescriptor. CID-keyed vs. non-CID-keyed fonts
96 * are distinguished by their FontType.
97 */
98 #ifndef pdf_base_font_DEFINED
99 # define pdf_base_font_DEFINED
100 typedef struct pdf_base_font_s pdf_base_font_t;
101 #endif
102 struct pdf_font_descriptor_s {
103 pdf_font_descriptor_common_t common;
104 pdf_base_font_t *base_font;
105 font_type FontType; /* (copied from base_font) */
106 bool embed;
107 struct cid_ { /* (CIDFonts only) */
108 cos_dict_t *Style;
109 char Lang[3]; /* 2 chars + \0 */
110 cos_dict_t *FD; /* value = COS_VALUE_RESOURCE */
111 } cid;
112 };
113 /*
114 * Define a sub-descriptor for a character class (FD dictionary element).
115 */
116 typedef struct pdf_sub_font_descriptor_s {
117 pdf_font_descriptor_common_t common;
118 } pdf_sub_font_descriptor_t;
119
120 /*
121 * Font descriptors are pseudo-resources, so their GC descriptors
122 * must be public.
123 */
BASIC_PTRS(pdf_font_descriptor_ptrs)124 BASIC_PTRS(pdf_font_descriptor_ptrs) {
125 GC_STRING_ELT(pdf_font_descriptor_t, common.values.FontName),
126 GC_OBJ_ELT(pdf_font_descriptor_t, base_font),
127 GC_OBJ_ELT(pdf_font_descriptor_t, cid.Style),
128 GC_OBJ_ELT(pdf_font_descriptor_t, cid.FD)
129 };
130 gs_public_st_basic_super(st_pdf_font_descriptor, pdf_font_descriptor_t,
131 "pdf_font_descriptor_t", pdf_font_descriptor_ptrs,
132 pdf_font_descriptor_data, &st_pdf_resource, 0);
133
134 /*
135 * Sub-font descriptors are also pseudo-resources.
136 */
BASIC_PTRS(pdf_sub_font_descriptor_ptrs)137 BASIC_PTRS(pdf_sub_font_descriptor_ptrs) {
138 GC_STRING_ELT(pdf_sub_font_descriptor_t, common.values.FontName)
139 };
140 gs_public_st_basic_super(st_pdf_sub_font_descriptor,
141 pdf_sub_font_descriptor_t, "pdf_sub_font_descriptor_t",
142 pdf_sub_font_descriptor_ptrs, pdf_sub_font_descriptor_data,
143 &st_pdf_resource, 0);
144
145 /* ================ Procedures ================ */
146
147 /* ---------------- Private ---------------- */
148
149 /* Get the ID of font descriptor metrics. */
150 inline private long
pdf_font_descriptor_common_id(const pdf_font_descriptor_common_t * pfdc)151 pdf_font_descriptor_common_id(const pdf_font_descriptor_common_t *pfdc)
152 {
153 return pdf_resource_id((const pdf_resource_t *)pfdc);
154 }
155
156 /* Write the common part of a FontDescriptor, aside from the final >>. */
157 private int
write_FontDescriptor_common(gx_device_pdf * pdev,const pdf_font_descriptor_common_t * pfd)158 write_FontDescriptor_common(gx_device_pdf *pdev,
159 const pdf_font_descriptor_common_t *pfd)
160 {
161 stream *s;
162 int code;
163 param_printer_params_t params;
164 printer_param_list_t rlist;
165 gs_param_list *const plist = (gs_param_list *)&rlist;
166
167 pdf_open_separate(pdev, pdf_font_descriptor_common_id(pfd));
168 s = pdev->strm;
169 stream_puts(s, "<</Type/FontDescriptor/FontName");
170 pdf_put_name(pdev, pfd->values.FontName.data, pfd->values.FontName.size);
171 pdf_write_font_bbox(pdev, &pfd->values.FontBBox);
172 params = param_printer_params_default;
173 code = s_init_param_printer(&rlist, ¶ms, s);
174 if (code >= 0) {
175 #define DESC_INT(str, memb)\
176 {str, gs_param_type_int, offset_of(pdf_font_descriptor_common_t, values.memb)}
177 static const gs_param_item_t required_items[] = {
178 DESC_INT("Ascent", Ascent),
179 DESC_INT("CapHeight", CapHeight),
180 DESC_INT("Descent", Descent),
181 DESC_INT("ItalicAngle", ItalicAngle),
182 DESC_INT("StemV", StemV),
183 gs_param_item_end
184 };
185 static const gs_param_item_t optional_items[] = {
186 DESC_INT("AvgWidth", AvgWidth),
187 DESC_INT("Leading", Leading),
188 DESC_INT("MaxWidth", MaxWidth),
189 DESC_INT("MissingWidth", MissingWidth),
190 DESC_INT("StemH", StemH),
191 DESC_INT("XHeight", XHeight),
192 gs_param_item_end
193 };
194 #undef DESC_INT
195 int Flags = pfd->values.Flags;
196 pdf_font_descriptor_t defaults;
197
198 param_write_int(plist, "Flags", &Flags);
199 gs_param_write_items(plist, pfd, NULL, required_items);
200 memset(&defaults, 0, sizeof(defaults));
201 gs_param_write_items(plist, pfd, &defaults, optional_items);
202 s_release_param_printer(&rlist);
203 }
204 return 0;
205 }
206
207 /* ---------------- Public ---------------- */
208
209 /*
210 * Allocate a FontDescriptor, initializing the FontType and rid from the
211 * gs_font.
212 */
213 int
pdf_font_descriptor_alloc(gx_device_pdf * pdev,pdf_font_descriptor_t ** ppfd,gs_font_base * font,bool embed)214 pdf_font_descriptor_alloc(gx_device_pdf *pdev, pdf_font_descriptor_t **ppfd,
215 gs_font_base *font, bool embed)
216 {
217 pdf_font_descriptor_t *pfd;
218 pdf_base_font_t *pbfont;
219 int code = pdf_base_font_alloc(pdev, &pbfont, font,
220 (font->orig_FontMatrix.xx == 0 && font->orig_FontMatrix.xy == 0
221 ? &font->FontMatrix : &font->orig_FontMatrix), false, !embed);
222
223 if (code < 0)
224 return code;
225 code = pdf_alloc_resource(pdev, resourceFontDescriptor,
226 font->id, (pdf_resource_t **)&pfd, 0L);
227 if (code < 0) {
228 gs_free_object(pdev->pdf_memory, pbfont,
229 "pdf_font_descriptor_alloc(base_font)");
230 return code;
231 }
232 memset(&pfd->common.values, 0,
233 sizeof(*pfd) - offset_of(pdf_font_descriptor_t, common.values));
234 pfd->base_font = pbfont;
235 pfd->FontType = font->FontType;
236 pfd->embed = embed;
237 *ppfd = pfd;
238 return 0;
239 }
240
241 /* Get the object ID of a FontDescriptor. */
242 long
pdf_font_descriptor_id(const pdf_font_descriptor_t * pfd)243 pdf_font_descriptor_id(const pdf_font_descriptor_t *pfd)
244 {
245 return pdf_resource_id((const pdf_resource_t *)pfd);
246 }
247
248 /*
249 * Get the FontType of a FontDescriptor.
250 */
251 font_type
pdf_font_descriptor_FontType(const pdf_font_descriptor_t * pfd)252 pdf_font_descriptor_FontType(const pdf_font_descriptor_t *pfd)
253 {
254 return pfd->FontType;
255 }
256
257 /*
258 * Get the embedding status of a FontDescriptor.
259 */
260 bool
pdf_font_descriptor_embedding(const pdf_font_descriptor_t * pfd)261 pdf_font_descriptor_embedding(const pdf_font_descriptor_t *pfd)
262 {
263 return pfd->embed;
264 }
265
266 /*
267 * Check for subset font.
268 */
269 bool
pdf_font_descriptor_is_subset(const pdf_font_descriptor_t * pfd)270 pdf_font_descriptor_is_subset(const pdf_font_descriptor_t *pfd)
271 {
272 return pdf_base_font_is_subset(pfd->base_font);
273 }
274
275 /*
276 * Return a reference to the FontName of a FontDescriptor, similar to
277 * pdf_base_font_name.
278 */
pdf_font_descriptor_name(pdf_font_descriptor_t * pfd)279 gs_string *pdf_font_descriptor_name(pdf_font_descriptor_t *pfd)
280 {
281 return &pfd->common.values.FontName;
282 }
283
284 /*
285 * Return the (copied, subset or complete) font associated with a FontDescriptor.
286 * This procedure probably shouldn't exist....
287 */
288 gs_font_base *
pdf_font_descriptor_font(const pdf_font_descriptor_t * pfd,bool complete)289 pdf_font_descriptor_font(const pdf_font_descriptor_t *pfd, bool complete)
290 {
291 return pdf_base_font_font(pfd->base_font, complete);
292 }
293
294 /*
295 * Drop the copied complete font associated with a FontDescriptor.
296 */
297 void
pdf_font_descriptor_drop_complete_font(const pdf_font_descriptor_t * pfd)298 pdf_font_descriptor_drop_complete_font(const pdf_font_descriptor_t *pfd)
299 {
300 pdf_base_font_drop_complete(pfd->base_font);
301 }
302
303 /*
304 * Return a reference to the name of a FontDescriptor's base font, per
305 * pdf_base_font_name.
306 */
pdf_font_descriptor_base_name(const pdf_font_descriptor_t * pfd)307 gs_string *pdf_font_descriptor_base_name(const pdf_font_descriptor_t *pfd)
308 {
309 return pdf_base_font_name(pfd->base_font);
310 }
311
312 /*
313 * Copy a glyph from a font to the stable copy. Return 0 if this is a
314 * new glyph, 1 if it was already copied.
315 */
316 int
pdf_font_used_glyph(pdf_font_descriptor_t * pfd,gs_glyph glyph,gs_font_base * font)317 pdf_font_used_glyph(pdf_font_descriptor_t *pfd, gs_glyph glyph,
318 gs_font_base *font)
319 {
320 return pdf_base_font_copy_glyph(pfd->base_font, glyph, font);
321 }
322
323 /* Compute the FontDescriptor metrics for a font. */
324 int
pdf_compute_font_descriptor(pdf_font_descriptor_t * pfd)325 pdf_compute_font_descriptor(pdf_font_descriptor_t *pfd)
326 {
327 gs_font_base *bfont = pdf_base_font_font(pfd->base_font, false);
328 gs_glyph glyph, notdef;
329 int index;
330 int wmode = bfont->WMode;
331 int members = (GLYPH_INFO_WIDTH0 << wmode) |
332 GLYPH_INFO_BBOX | GLYPH_INFO_NUM_PIECES;
333 pdf_font_descriptor_values_t desc;
334 gs_matrix smat;
335 gs_matrix *pmat = NULL;
336 int fixed_width = 0;
337 int small_descent = 0, small_height = 0;
338 bool small_present = false;
339 int x_height = min_int;
340 int cap_height = 0;
341 gs_rect bbox_colon, bbox_period, bbox_I;
342 bool is_cid = (bfont->FontType == ft_CID_encrypted ||
343 bfont->FontType == ft_CID_TrueType);
344 bool have_colon = false, have_period = false, have_I = false;
345 int code;
346
347 memset(&desc, 0, sizeof(desc));
348 if (is_cid && bfont->FontBBox.p.x != bfont->FontBBox.q.x &&
349 bfont->FontBBox.p.y != bfont->FontBBox.q.y) {
350 int scale = (bfont->FontType == ft_TrueType || bfont->FontType == ft_CID_TrueType ? 1000 : 1);
351
352 desc.FontBBox.p.x = (int)(bfont->FontBBox.p.x * scale);
353 desc.FontBBox.p.y = (int)(bfont->FontBBox.p.y * scale);
354 desc.FontBBox.p.x = (int)(bfont->FontBBox.p.x * scale);
355 desc.FontBBox.q.y = (int)(bfont->FontBBox.q.y * scale);
356 desc.Ascent = desc.FontBBox.q.y;
357 members &= ~GLYPH_INFO_BBOX;
358 } else {
359 desc.FontBBox.p.x = desc.FontBBox.p.y = max_int;
360 desc.FontBBox.q.x = desc.FontBBox.q.y = min_int;
361 }
362 /*
363 * Embedded TrueType fonts use a 1000-unit character space, but the
364 * font itself uses a 1-unit space. Compensate for this here.
365 */
366 switch (bfont->FontType) {
367 case ft_TrueType:
368 case ft_CID_TrueType:
369 gs_make_scaling(1000.0, 1000.0, &smat);
370 pmat = &smat;
371 default:
372 break;
373 }
374 /*
375 * See the note on FONT_IS_ADOBE_ROMAN / FONT_USES_STANDARD_ENCODING
376 * in gdevpdtd.h for why the following substitution is made.
377 */
378 #if 0
379 # define CONSIDER_FONT_SYMBOLIC(bfont) font_is_symbolic(bfont)
380 #else
381 # define CONSIDER_FONT_SYMBOLIC(bfont)\
382 ((bfont)->encoding_index != ENCODING_INDEX_STANDARD)
383 #endif
384 if (CONSIDER_FONT_SYMBOLIC(bfont))
385 desc.Flags |= FONT_IS_SYMBOLIC;
386 /*
387 * Scan the entire glyph space to compute Ascent, Descent, FontBBox, and
388 * the fixed width if any. For non-symbolic fonts, also note the
389 * bounding boxes for Latin letters and a couple of other characters,
390 * for computing the remaining descriptor values (CapHeight,
391 * ItalicAngle, StemV, XHeight, and flags SERIF, SCRIPT, ITALIC,
392 * ALL_CAPS, and SMALL_CAPS). (The algorithms are pretty crude.)
393 */
394 notdef = GS_NO_GLYPH;
395 for (index = 0;
396 (code = bfont->procs.enumerate_glyph((gs_font *)bfont, &index,
397 (is_cid ? GLYPH_SPACE_INDEX : GLYPH_SPACE_NAME), &glyph)) >= 0 &&
398 index != 0;
399 ) {
400 gs_glyph_info_t info;
401 gs_const_string gname;
402
403 code = bfont->procs.glyph_info((gs_font *)bfont, glyph, pmat, members, &info);
404 if (code == gs_error_VMerror)
405 return code;
406 if (code < 0) {
407 /*
408 * Since this function may be indirtectly called from gx_device_finalize,
409 * we are unable to propagate error code to the interpreter.
410 * Therefore we skip it here hoping that few errors can be
411 * recovered by the integration through entire glyph set.
412 */
413 continue;
414 }
415 if (members & GLYPH_INFO_BBOX) {
416 /* rect_merge(desc.FontBBox, info.bbox); Expanding due to type cast :*/
417 if (info.bbox.p.x < desc.FontBBox.p.x) desc.FontBBox.p.x = (int)info.bbox.p.x;
418 if (info.bbox.q.x > desc.FontBBox.q.x) desc.FontBBox.q.x = (int)info.bbox.q.x;
419 if (info.bbox.p.y < desc.FontBBox.p.y) desc.FontBBox.p.y = (int)info.bbox.p.y;
420 if (info.bbox.q.y > desc.FontBBox.q.y) desc.FontBBox.q.y = (int)info.bbox.q.y;
421 if (!info.num_pieces)
422 desc.Ascent = max(desc.Ascent, (int)info.bbox.q.y);
423 }
424 if (notdef == GS_NO_GLYPH && gs_font_glyph_is_notdef(bfont, glyph)) {
425 notdef = glyph;
426 desc.MissingWidth = (int)info.width[wmode].x;
427 }
428 if (info.width[wmode].y != 0)
429 fixed_width = min_int;
430 else if (fixed_width == 0)
431 fixed_width = (int)info.width[wmode].x;
432 else if (info.width[wmode].x != fixed_width)
433 fixed_width = min_int;
434 if (desc.Flags & FONT_IS_SYMBOLIC)
435 continue; /* skip Roman-only computation */
436 if (is_cid)
437 continue;
438 code = bfont->procs.glyph_name((gs_font *)bfont, glyph, &gname);
439 if (code < 0)
440 continue;
441 switch (gname.size) {
442 case 5:
443 if (!memcmp(gname.data, "colon", 5))
444 bbox_colon = info.bbox, have_colon = true;
445 continue;
446 case 6:
447 if (!memcmp(gname.data, "period", 6))
448 bbox_period = info.bbox, have_period = true;
449 continue;
450 case 1:
451 break;
452 default:
453 continue;
454 }
455 if (gname.data[0] >= 'A' && gname.data[0] <= 'Z') {
456 cap_height = max(cap_height, (int)info.bbox.q.y);
457 if (gname.data[0] == 'I')
458 bbox_I = info.bbox, have_I = true;
459 } else if (gname.data[0] >= 'a' && gname.data[0] <= 'z') {
460 int y0 = (int)(info.bbox.p.y), y1 = (int)(info.bbox.q.y);
461
462 small_present = true;
463 switch (gname.data[0]) {
464 case 'b': case 'd': case 'f': case 'h':
465 case 'k': case 'l': case 't': /* ascender */
466 small_height = max(small_height, y1);
467 case 'i': /* anomalous ascent */
468 break;
469 case 'j': /* descender with anomalous ascent */
470 small_descent = min(small_descent, y0);
471 break;
472 case 'g': case 'p': case 'q': case 'y': /* descender */
473 small_descent = min(small_descent, y0);
474 default: /* no ascender or descender */
475 x_height = max(x_height, y1);
476 }
477 }
478 }
479 if (!(desc.Flags & FONT_IS_SYMBOLIC)) {
480 desc.Flags |= FONT_IS_ADOBE_ROMAN; /* required if not symbolic */
481 desc.XHeight = (int)x_height;
482 if (!small_present)
483 desc.Flags |= FONT_IS_ALL_CAPS;
484 desc.CapHeight = cap_height;
485 /*
486 * Look at various glyphs to determine ItalicAngle, StemV,
487 * SERIF, SCRIPT, and ITALIC.
488 */
489 if (have_colon && have_period) {
490 /* Calculate the dominant angle. */
491 int angle =
492 (int)(atan2((bbox_colon.q.y - bbox_colon.p.y) -
493 (bbox_period.q.y - bbox_period.p.y),
494 (bbox_colon.q.x - bbox_colon.p.x) -
495 (bbox_period.q.x - bbox_period.p.x)) *
496 radians_to_degrees) - 90;
497
498 /* Normalize to [-90..90]. */
499 while (angle > 90)
500 angle -= 180;
501 while (angle < -90)
502 angle += 180;
503 if (angle < -30)
504 angle = -30;
505 else if (angle > 30)
506 angle = 30;
507 /*
508 * For script or embellished fonts, we can get an angle that is
509 * slightly off from zero even for non-italic fonts.
510 * Compensate for this now.
511 */
512 if (angle <= 2 && angle >= -2)
513 angle = 0;
514 desc.ItalicAngle = angle;
515 }
516 if (desc.ItalicAngle)
517 desc.Flags |= FONT_IS_ITALIC;
518 if (have_I) {
519 double wdot = bbox_period.q.x - bbox_period.p.x;
520 double wcolon = bbox_I.q.x - bbox_I.p.x;
521 double wI = bbox_period.q.x - bbox_period.p.x;
522
523 desc.StemV = (int)wdot;
524 if (wI > wcolon * 2.5 || wI > (bbox_period.q.y - bbox_period.p.y) * 0.25)
525 desc.Flags |= FONT_IS_SERIF;
526 }
527 }
528 if (desc.Ascent == 0)
529 desc.Ascent = desc.FontBBox.q.y;
530 desc.Descent = desc.FontBBox.p.y;
531 if (!(desc.Flags & (FONT_IS_SYMBOLIC | FONT_IS_ALL_CAPS)) &&
532 (small_descent > desc.Descent / 3 || desc.XHeight > small_height * 0.9)
533 )
534 desc.Flags |= FONT_IS_SMALL_CAPS;
535 if (fixed_width > 0) {
536 desc.Flags |= FONT_IS_FIXED_WIDTH;
537 desc.AvgWidth = desc.MaxWidth = desc.MissingWidth = fixed_width;
538 }
539 if (desc.CapHeight == 0)
540 desc.CapHeight = desc.Ascent;
541 if (desc.StemV == 0)
542 desc.StemV = (int)(desc.FontBBox.q.x * 0.15);
543 pfd->common.values = desc;
544 return 0;
545 }
546
547 /*
548 * Finish a FontDescriptor by computing the metric values, and then
549 * writing the associated embedded font if any.
550 */
551 int
pdf_finish_FontDescriptor(gx_device_pdf * pdev,pdf_font_descriptor_t * pfd)552 pdf_finish_FontDescriptor(gx_device_pdf *pdev, pdf_font_descriptor_t *pfd)
553 {
554 int code = 0;
555 cos_dict_t *pcd = 0;
556
557 if (!pfd->common.object->written &&
558 (code = pdf_compute_font_descriptor(pfd)) >= 0 &&
559 (!pfd->embed ||
560 (code = pdf_write_embedded_font(pdev, pfd->base_font,
561 &pfd->common.values.FontBBox,
562 pfd->common.rid, &pcd)) >= 0)
563 ) {
564 pdf_set_FontFile_object(pfd->base_font, pcd);
565 }
566 return code;
567 }
568
569 /* Write a FontDescriptor. */
570 int
pdf_write_FontDescriptor(gx_device_pdf * pdev,pdf_font_descriptor_t * pfd)571 pdf_write_FontDescriptor(gx_device_pdf *pdev, pdf_font_descriptor_t *pfd)
572 {
573 font_type ftype = pfd->FontType;
574 long cidset_id = 0;
575 int code = 0;
576 stream *s;
577
578 if (pfd->common.object->written)
579 return 0;
580
581 /* If this is a CIDFont subset, write the CIDSet now. */
582 switch (ftype) {
583 case ft_CID_encrypted:
584 case ft_CID_TrueType:
585 if (pdf_do_subset_font(pdev, pfd->base_font, pfd->common.rid)) {
586 code = pdf_write_CIDSet(pdev, pfd->base_font, &cidset_id);
587 if (code < 0)
588 return code;
589 }
590 default:
591 break;
592 }
593
594 {
595 /*
596 * Hack: make all embedded subset TrueType fonts "symbolic" to
597 * work around undocumented assumptions in Acrobat Reader.
598 */
599 pdf_font_descriptor_common_t fd;
600
601 fd = pfd->common;
602 if (pfd->embed && pfd->FontType == ft_TrueType &&
603 pdf_do_subset_font(pdev, pfd->base_font, pfd->common.rid)
604 )
605 fd.values.Flags =
606 (fd.values.Flags & ~(FONT_IS_ADOBE_ROMAN)) | FONT_IS_SYMBOLIC;
607 code = write_FontDescriptor_common(pdev, &fd);
608 }
609 if (code < 0)
610 return code;
611 s = pdev->strm;
612 if (cidset_id != 0)
613 pprintld1(s, "/CIDSet %ld 0 R\n", cidset_id);
614 else if (pdf_do_subset_font(pdev, pfd->base_font, pfd->common.rid) &&
615 (ftype == ft_encrypted || ftype == ft_encrypted2)
616 ) {
617 stream_puts(s, "/CharSet");
618 code = pdf_write_CharSet(pdev, pfd->base_font);
619 if (code < 0)
620 return code;
621 }
622 if (pfd->embed) {
623 code = pdf_write_FontFile_entry(pdev, pfd->base_font);
624 if (code < 0)
625 return code;
626 }
627 if (pfd->cid.Style) {
628 stream_puts(s, "/Style");
629 COS_WRITE(pfd->cid.Style, pdev);
630 }
631 if (pfd->cid.Lang[0]) {
632 pprints1(s, "/Lang(%s)", pfd->cid.Lang);
633 }
634 if (pfd->cid.FD) {
635 stream_puts(s, "/FD");
636 COS_WRITE(pfd->cid.FD, pdev);
637 }
638 stream_puts(s, ">>\n");
639 pdf_end_separate(pdev);
640 pfd->common.object->written = true;
641 { const cos_object_t *pco = (const cos_object_t *)pdf_get_FontFile_object(pfd->base_font);
642 if (pco != NULL) {
643 code = COS_WRITE_OBJECT(pco, pdev);
644 if (code < 0)
645 return code;
646 }
647 }
648 return 0;
649 }
650
651 /*
652 * Release a FontDescriptor components.
653 */
654 int
pdf_release_FontDescriptor_components(gx_device_pdf * pdev,pdf_font_descriptor_t * pfd)655 pdf_release_FontDescriptor_components(gx_device_pdf *pdev, pdf_font_descriptor_t *pfd)
656 {
657 gs_free_object(pdev->pdf_memory, pfd->base_font, "pdf_release_FontDescriptor_components");
658 pfd->base_font = NULL;
659 /* fixme: underimplemented. */
660 return 0;
661 }
662