Subversion Repositories planix.SVN

Rev

Rev 2 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
2 - 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: gdevpdtf.c,v 1.46 2005/09/12 11:34:50 leonardo Exp $ */
18
/* Font and CMap resource implementation for pdfwrite text */
19
#include "memory_.h"
20
#include "string_.h"
21
#include "gx.h"
22
#include "gserrors.h"
23
#include "gsutil.h"		/* for bytes_compare */
24
#include "gxfcache.h"		/* for orig_fonts list */
25
#include "gxfcid.h"
26
#include "gxfcmap.h"
27
#include "gxfcopy.h"
28
#include "gxfont.h"
29
#include "gxfont1.h"
30
#include "gdevpsf.h"
31
#include "gdevpdfx.h"
32
#include "gdevpdtb.h"
33
#include "gdevpdtd.h"
34
#include "gdevpdtf.h"
35
#include "gdevpdtw.h"
36
 
37
/* GC descriptors */
38
public_st_pdf_font_resource();
39
private_st_pdf_encoding1();
40
private_st_pdf_encoding_element();
41
private_st_pdf_standard_font();
42
private_st_pdf_standard_font_element();
43
private_st_pdf_outline_fonts();
44
 
45
private
46
ENUM_PTRS_WITH(pdf_font_resource_enum_ptrs, pdf_font_resource_t *pdfont)
47
ENUM_PREFIX(st_pdf_resource, 12);
48
case 0: return ENUM_STRING(&pdfont->BaseFont);
49
case 1: ENUM_RETURN(pdfont->FontDescriptor);
50
case 2: ENUM_RETURN(pdfont->base_font);
51
case 3: ENUM_RETURN(pdfont->Widths);
52
case 4: ENUM_RETURN(pdfont->used);
53
case 5: ENUM_RETURN(pdfont->res_ToUnicode);
54
case 6: ENUM_RETURN(pdfont->cmap_ToUnicode);
55
case 7: switch (pdfont->FontType) {
56
 case ft_composite:
57
     ENUM_RETURN(pdfont->u.type0.DescendantFont);
58
 case ft_CID_encrypted:
59
 case ft_CID_TrueType:
60
     ENUM_RETURN(pdfont->u.cidfont.Widths2);
61
 default:
62
     ENUM_RETURN(pdfont->u.simple.Encoding);
63
}
64
case 8: switch (pdfont->FontType) {
65
 case ft_composite:
66
     return (pdfont->u.type0.cmap_is_standard ? ENUM_OBJ(0) :
67
	     ENUM_CONST_STRING(&pdfont->u.type0.CMapName));
68
 case ft_encrypted:
69
 case ft_encrypted2:
70
 case ft_TrueType:
71
 case ft_user_defined:
72
     ENUM_RETURN(pdfont->u.simple.v);
73
 case ft_CID_encrypted:
74
 case ft_CID_TrueType:
75
     ENUM_RETURN(pdfont->u.cidfont.v);
76
 default:
77
     ENUM_RETURN(0);
78
}
79
case 9: switch (pdfont->FontType) {
80
 case ft_user_defined:
81
     ENUM_RETURN(pdfont->u.simple.s.type3.char_procs);
82
 case ft_CID_encrypted:
83
 case ft_CID_TrueType:
84
     ENUM_RETURN(pdfont->u.cidfont.CIDToGIDMap);
85
 default:
86
     ENUM_RETURN(0);
87
}
88
case 10: switch (pdfont->FontType) {
89
 case ft_user_defined:
90
     ENUM_RETURN(pdfont->u.simple.s.type3.cached);
91
 case ft_CID_encrypted:
92
 case ft_CID_TrueType:
93
     ENUM_RETURN(pdfont->u.cidfont.parent);
94
 default:
95
     ENUM_RETURN(0);
96
}
97
case 11: switch (pdfont->FontType) {
98
 case ft_user_defined:
99
     ENUM_RETURN(pdfont->u.simple.s.type3.used_resources);
100
 case ft_CID_encrypted:
101
 case ft_CID_TrueType:
102
     ENUM_RETURN(pdfont->u.cidfont.used2);
103
 default:
104
     ENUM_RETURN(0);
105
}
106
ENUM_PTRS_END
107
private
108
RELOC_PTRS_WITH(pdf_font_resource_reloc_ptrs, pdf_font_resource_t *pdfont)
109
{
110
    RELOC_PREFIX(st_pdf_resource);
111
    RELOC_STRING_VAR(pdfont->BaseFont);
112
    RELOC_VAR(pdfont->FontDescriptor);
113
    RELOC_VAR(pdfont->base_font);
114
    RELOC_VAR(pdfont->Widths);
115
    RELOC_VAR(pdfont->used);
116
    RELOC_VAR(pdfont->res_ToUnicode);
117
    RELOC_VAR(pdfont->cmap_ToUnicode);
118
    switch (pdfont->FontType) {
119
    case ft_composite:
120
	if (!pdfont->u.type0.cmap_is_standard)
121
	    RELOC_CONST_STRING_VAR(pdfont->u.type0.CMapName);
122
	RELOC_VAR(pdfont->u.type0.DescendantFont);
123
	break;
124
    case ft_user_defined:
125
	RELOC_VAR(pdfont->u.simple.Encoding);
126
	RELOC_VAR(pdfont->u.simple.v);
127
	RELOC_VAR(pdfont->u.simple.s.type3.char_procs);
128
	RELOC_VAR(pdfont->u.simple.s.type3.cached);
129
	RELOC_VAR(pdfont->u.simple.s.type3.used_resources);
130
	break;
131
    case ft_CID_encrypted:
132
    case ft_CID_TrueType:
133
	RELOC_VAR(pdfont->u.cidfont.Widths2);
134
	RELOC_VAR(pdfont->u.cidfont.v);
135
	RELOC_VAR(pdfont->u.cidfont.CIDToGIDMap);
136
	RELOC_VAR(pdfont->u.cidfont.parent);
137
	RELOC_VAR(pdfont->u.cidfont.used2);
138
	break;
139
    default:
140
	RELOC_VAR(pdfont->u.simple.Encoding);
141
	RELOC_VAR(pdfont->u.simple.v);
142
	break;
143
    }
144
}
145
RELOC_PTRS_END
146
 
147
/* ---------------- Standard fonts ---------------- */
148
 
149
/* ------ Private ------ */
150
 
151
/* Define the 14 standard built-in fonts. */
152
#define PDF_NUM_STANDARD_FONTS 14
153
typedef struct pdf_standard_font_info_s {
154
    const char *fname;
155
    int size;
156
    gs_encoding_index_t base_encoding;
157
} pdf_standard_font_info_t;
158
private const pdf_standard_font_info_t standard_font_info[] = {
159
    {"Courier",                7, ENCODING_INDEX_STANDARD},
160
    {"Courier-Bold",          12, ENCODING_INDEX_STANDARD},
161
    {"Courier-Oblique",       15, ENCODING_INDEX_STANDARD},
162
    {"Courier-BoldOblique",   19, ENCODING_INDEX_STANDARD},
163
    {"Helvetica",              9, ENCODING_INDEX_STANDARD},
164
    {"Helvetica-Bold",        14, ENCODING_INDEX_STANDARD},
165
    {"Helvetica-Oblique",     17, ENCODING_INDEX_STANDARD},
166
    {"Helvetica-BoldOblique", 21, ENCODING_INDEX_STANDARD},
167
    {"Symbol",                 6, ENCODING_INDEX_SYMBOL},
168
    {"Times-Roman",           11, ENCODING_INDEX_STANDARD},
169
    {"Times-Bold",            10, ENCODING_INDEX_STANDARD},
170
    {"Times-Italic",          12, ENCODING_INDEX_STANDARD},
171
    {"Times-BoldItalic",      16, ENCODING_INDEX_STANDARD},
172
    {"ZapfDingbats",          12, ENCODING_INDEX_DINGBATS},
173
    {0}
174
};
175
 
176
/* Return the index of a standard font name, or -1 if missing. */
177
private int
178
pdf_find_standard_font_name(const byte *str, uint size)
179
{
180
    const pdf_standard_font_info_t *ppsf;
181
 
182
    for (ppsf = standard_font_info; ppsf->fname; ++ppsf)
183
	if (ppsf->size == size &&
184
	    !memcmp(ppsf->fname, (const char *)str, size)
185
	    )
186
	    return ppsf - standard_font_info;
187
    return -1;
188
}
189
 
190
/*
191
 * If there is a standard font with the same appearance (CharStrings,
192
 * Private, WeightVector) as the given font, set *psame to the mask of
193
 * identical properties, and return the standard-font index; otherwise,
194
 * set *psame to 0 and return -1.
195
 */
196
private int
197
find_std_appearance(const gx_device_pdf *pdev, gs_font_base *bfont,
198
		    int mask, pdf_char_glyph_pair_t *pairs, int num_glyphs)
199
{
200
    bool has_uid = uid_is_UniqueID(&bfont->UID) && bfont->UID.id != 0;
201
    const pdf_standard_font_t *psf = pdf_standard_fonts(pdev);
202
    int i;
203
 
204
    switch (bfont->FontType) {
205
    case ft_encrypted:
206
    case ft_encrypted2:
207
    case ft_TrueType:
208
	break;
209
    default:
210
	return -1;
211
    }
212
 
213
    mask |= FONT_SAME_OUTLINES;
214
    for (i = 0; i < PDF_NUM_STANDARD_FONTS; ++psf, ++i) {
215
	gs_font_base *cfont;
216
	int code;
217
 
218
	if (!psf->pdfont)
219
	    continue;
220
	cfont = pdf_font_resource_font(psf->pdfont, false);
221
	if (has_uid) {
222
	    /*
223
	     * Require the UIDs to match.  The PostScript spec says this
224
	     * is the case iff the outlines are the same.
225
	     */
226
	    if (!uid_equal(&bfont->UID, &cfont->UID))
227
		continue;
228
	}
229
	/*
230
	 * Require the actual outlines to match (within the given subset).
231
	 */
232
	code = gs_copied_can_copy_glyphs((const gs_font *)cfont,
233
					 (const gs_font *)bfont,
234
					 &pairs[0].glyph, num_glyphs, 
235
					 sizeof(pdf_char_glyph_pair_t), true);
236
	if (code == gs_error_unregistered) /* Debug purpose only. */
237
	    return code;
238
	/* Note: code < 0 means an error. Skip it here. */
239
	if (code > 0)
240
	    return i;
241
    }
242
    return -1;
243
}
244
 
245
/*
246
 * Scan a font directory for standard fonts.  Return true if any new ones
247
 * were found.  A font is recognized as standard if it was loaded as a
248
 * resource, it has a UniqueId, and it has a standard name.
249
 */
250
private bool
251
scan_for_standard_fonts(gx_device_pdf *pdev, const gs_font_dir *dir)
252
{
253
    bool found = false;
254
    gs_font *orig = dir->orig_fonts;
255
 
256
    for (; orig; orig = orig->next) {
257
	gs_font_base *obfont;
258
 
259
	if (orig->FontType == ft_composite || !orig->is_resource)
260
	    continue;
261
	obfont = (gs_font_base *)orig;
262
	if (uid_is_UniqueID(&obfont->UID)) {
263
	    /* Is it one of the standard fonts? */
264
	    int i = pdf_find_standard_font_name(orig->key_name.chars,
265
						orig->key_name.size);
266
 
267
	    if (i >= 0 && pdf_standard_fonts(pdev)[i].pdfont == 0) {
268
		pdf_font_resource_t *pdfont;
269
		int code = pdf_font_std_alloc(pdev, &pdfont, true, orig->id, obfont,
270
					      i);
271
 
272
		if (code < 0)
273
		    continue;
274
		found = true;
275
	    }
276
	}
277
    }
278
    return found;
279
}
280
 
281
/* ---------------- Initialization ---------------- */
282
 
283
/*
284
 * Allocate and initialize bookkeeping for outline fonts.
285
 */
286
pdf_outline_fonts_t *
287
pdf_outline_fonts_alloc(gs_memory_t *mem)
288
{
289
    pdf_outline_fonts_t *pofs =
290
	gs_alloc_struct(mem, pdf_outline_fonts_t, &st_pdf_outline_fonts,
291
			"pdf_outline_fonts_alloc(outline_fonts)");
292
    pdf_standard_font_t *ppsf =
293
	gs_alloc_struct_array(mem, PDF_NUM_STANDARD_FONTS,
294
			      pdf_standard_font_t,
295
			      &st_pdf_standard_font_element,
296
			      "pdf_outline_fonts_alloc(standard_fonts)");
297
 
298
    if (pofs == 0 || ppsf == 0)
299
	return 0;
300
    memset(ppsf, 0, PDF_NUM_STANDARD_FONTS * sizeof(*ppsf));
301
    memset(pofs, 0, sizeof(*pofs));
302
    pofs->standard_fonts = ppsf;
303
    return pofs;
304
}
305
 
306
/*
307
 * Return the standard fonts array.
308
 */
309
pdf_standard_font_t *
310
pdf_standard_fonts(const gx_device_pdf *pdev)
311
{
312
    return pdev->text->outline_fonts->standard_fonts;
313
}
314
 
315
/*
316
 * Clean the standard fonts array.
317
 */
318
void
319
pdf_clean_standard_fonts(const gx_device_pdf *pdev)
320
{
321
    pdf_standard_font_t *ppsf = pdf_standard_fonts(pdev);
322
 
323
    memset(ppsf, 0, PDF_NUM_STANDARD_FONTS * sizeof(*ppsf));
324
}
325
 
326
 
327
/* ---------------- Font resources ---------------- */
328
 
329
/* ------ Private ------ */
330
 
331
 
332
private int pdf_resize_array(gs_memory_t *mem, void **p, int elem_size, int old_size, int new_size)
333
{
334
    void *q = gs_alloc_byte_array(mem, new_size, elem_size, "pdf_resize_array");
335
 
336
    if (q == NULL)
337
	return_error(gs_error_VMerror);
338
    memset((char *)q + elem_size * old_size, 0, elem_size * (new_size - old_size));
339
    memcpy(q, *p, elem_size * old_size);
340
    gs_free_object(mem, *p, "pdf_resize_array");
341
    *p = q;
342
    return 0;
343
}
344
 
345
/*
346
 * Allocate and (minimally) initialize a font resource.
347
 */
348
private int
349
font_resource_alloc(gx_device_pdf *pdev, pdf_font_resource_t **ppfres,
350
		    pdf_resource_type_t rtype, gs_id rid, font_type ftype,
351
		    int chars_count,
352
		    pdf_font_write_contents_proc_t write_contents)
353
{
354
    gs_memory_t *mem = pdev->pdf_memory;
355
    pdf_font_resource_t *pfres;
356
    double *widths = 0;
357
    byte *used = 0;
358
    int code;
359
    bool is_CID_font = (ftype == ft_CID_encrypted || ftype == ft_CID_TrueType);
360
 
361
    if (chars_count != 0) {
362
	uint size = (chars_count + 7) / 8;
363
 
364
	if (!is_CID_font) {
365
    	    widths = (void *)gs_alloc_byte_array(mem, chars_count, sizeof(*widths),
366
						"font_resource_alloc(Widths)");
367
	} else {
368
	    /*  Delay allocation because we don't know which WMode will be used. */
369
	}
370
	used = gs_alloc_bytes(mem, size, "font_resource_alloc(used)");
371
	if ((!is_CID_font && widths == 0) || used == 0) {
372
	    code = gs_note_error(gs_error_VMerror);
373
	    goto fail;
374
	}
375
	if (!is_CID_font)
376
	    memset(widths, 0, chars_count * sizeof(*widths));
377
	memset(used, 0, size);
378
    }
379
    code = pdf_alloc_resource(pdev, rtype, rid, (pdf_resource_t **)&pfres, 0L);
380
    if (code < 0)
381
	goto fail;
382
    memset((byte *)pfres + sizeof(pdf_resource_t), 0,
383
	   sizeof(*pfres) - sizeof(pdf_resource_t));
384
    pfres->FontType = ftype;
385
    pfres->count = chars_count;
386
    pfres->Widths = widths;
387
    pfres->used = used;
388
    pfres->write_contents = write_contents;
389
    pfres->res_ToUnicode = NULL;
390
    pfres->cmap_ToUnicode = NULL;
391
    *ppfres = pfres;
392
    return 0;
393
 fail:
394
    gs_free_object(mem, used, "font_resource_alloc(used)");
395
    gs_free_object(mem, widths, "font_resource_alloc(Widths)");
396
    return code;
397
}
398
private int
399
font_resource_simple_alloc(gx_device_pdf *pdev, pdf_font_resource_t **ppfres,
400
			   gs_id rid, font_type ftype, int chars_count,
401
			   pdf_font_write_contents_proc_t write_contents)
402
{
403
    pdf_font_resource_t *pfres;
404
    int code = font_resource_alloc(pdev, &pfres, resourceFont, rid, ftype,
405
				   chars_count, write_contents);
406
 
407
    if (code < 0)
408
	return code;
409
    pfres->u.simple.FirstChar = 256;
410
    pfres->u.simple.LastChar = -1;
411
    pfres->u.simple.BaseEncoding = -1;
412
    *ppfres = pfres;
413
    return 0;
414
}
415
int
416
font_resource_encoded_alloc(gx_device_pdf *pdev, pdf_font_resource_t **ppfres,
417
			    gs_id rid, font_type ftype,
418
			    pdf_font_write_contents_proc_t write_contents)
419
{
420
    pdf_encoding_element_t *Encoding =
421
	gs_alloc_struct_array(pdev->pdf_memory, 256, pdf_encoding_element_t,
422
			      &st_pdf_encoding_element,
423
			      "font_resource_encoded_alloc");
424
    gs_point *v = (gs_point *)gs_alloc_byte_array(pdev->pdf_memory, 
425
		    256, sizeof(gs_point), "pdf_font_simple_alloc");
426
    pdf_font_resource_t *pdfont;
427
    int code, i;
428
 
429
 
430
    if (v == 0 || Encoding == 0) {
431
	gs_free_object(pdev->pdf_memory, Encoding, 
432
		       "font_resource_encoded_alloc");
433
	gs_free_object(pdev->pdf_memory, v, 
434
	               "font_resource_encoded_alloc");
435
	return_error(gs_error_VMerror);
436
    }
437
    code = font_resource_simple_alloc(pdev, &pdfont, rid, ftype,
438
				      256, write_contents);
439
    if (code < 0) {
440
	gs_free_object(pdev->pdf_memory, Encoding, 
441
	               "font_resource_encoded_alloc");
442
	gs_free_object(pdev->pdf_memory, v, 
443
	               "font_resource_encoded_alloc");
444
	return_error(gs_error_VMerror);
445
    }
446
    if (code < 0) {
447
	return code;
448
    }
449
    memset(v, 0, 256 * sizeof(*v));
450
    memset(Encoding, 0, 256 * sizeof(*Encoding));
451
    for (i = 0; i < 256; ++i)
452
	Encoding[i].glyph = GS_NO_GLYPH;
453
    pdfont->u.simple.Encoding = Encoding;
454
    pdfont->u.simple.v = v;
455
    *ppfres = pdfont;
456
    return 0;
457
}
458
 
459
/*
460
 * Record whether a Type 1 or Type 2 font is a Multiple Master instance.
461
 */
462
private void
463
set_is_MM_instance(pdf_font_resource_t *pdfont, const gs_font_base *pfont)
464
{
465
    switch (pfont->FontType) {
466
    case ft_encrypted:
467
    case ft_encrypted2:
468
	pdfont->u.simple.s.type1.is_MM_instance =
469
	    ((const gs_font_type1 *)pfont)->data.WeightVector.count > 0;
470
    default:
471
	break;
472
    }
473
}
474
 
475
/* ------ Generic public ------ */
476
 
477
/* Resize font resource arrays. */
478
int 
479
pdf_resize_resource_arrays(gx_device_pdf *pdev, pdf_font_resource_t *pfres, int chars_count)
480
{
481
    /* This function fixes CID fonts that provide a lesser CIDCount than
482
       CIDs used in a document. Rather PS requires to print CID=0,
483
       we need to provide a bigger CIDCount since we don't 
484
       re-encode the text. The text should look fine if the 
485
       viewer application substitutes the font. */
486
    gs_memory_t *mem = pdev->pdf_memory;
487
    int code;
488
 
489
    if (chars_count < pfres->count)
490
	return 0;
491
    if (pfres->Widths != NULL) {
492
	code = pdf_resize_array(mem, (void **)&pfres->Widths, sizeof(*pfres->Widths), 
493
		    pfres->count, chars_count);    
494
	if (code < 0)
495
	    return code;
496
    }
497
    code = pdf_resize_array(mem, (void **)&pfres->used, sizeof(*pfres->used), 
498
		    (pfres->count + 7) / 8, (chars_count + 7) / 8);    
499
    if (code < 0)
500
	return code;
501
    if (pfres->FontType == ft_CID_encrypted || pfres->FontType == ft_CID_TrueType) {
502
	if (pfres->u.cidfont.v != NULL) {
503
	    code = pdf_resize_array(mem, (void **)&pfres->u.cidfont.v, 
504
		    sizeof(*pfres->u.cidfont.v), pfres->count * 2, chars_count * 2);    
505
	    if (code < 0)
506
		return code;
507
	}
508
	if (pfres->u.cidfont.Widths2 != NULL) {
509
	    code = pdf_resize_array(mem, (void **)&pfres->u.cidfont.Widths2, 
510
		    sizeof(*pfres->u.cidfont.Widths2), pfres->count, chars_count);    
511
	    if (code < 0)
512
		return code;
513
	}
514
    }
515
    if (pfres->FontType == ft_CID_TrueType) {
516
	if (pfres->u.cidfont.CIDToGIDMap != NULL) {
517
	    code = pdf_resize_array(mem, (void **)&pfres->u.cidfont.CIDToGIDMap, 
518
		    sizeof(*pfres->u.cidfont.CIDToGIDMap), pfres->count, chars_count);
519
	    if (code < 0)
520
		return code;
521
	}
522
    }
523
    if (pfres->FontType == ft_CID_encrypted || pfres->FontType == ft_CID_TrueType) {
524
	if (pfres->u.cidfont.used2 != NULL) {
525
	    code = pdf_resize_array(mem, (void **)&pfres->u.cidfont.used2, 
526
		    sizeof(*pfres->u.cidfont.used2), 
527
		    (pfres->count + 7) / 8, (chars_count + 7) / 8);
528
	    if (code < 0)
529
		return code;
530
	}
531
    }
532
    pfres->count = chars_count;
533
    return 0;
534
}
535
 
536
/* Get the object ID of a font resource. */
537
long
538
pdf_font_id(const pdf_font_resource_t *pdfont)
539
{
540
    return pdf_resource_id((const pdf_resource_t *)pdfont);
541
}
542
 
543
/*
544
 * Return the (copied, subset) font associated with a font resource.
545
 * If this font resource doesn't have one (Type 0 or Type 3), return 0.
546
 */
547
gs_font_base *
548
pdf_font_resource_font(const pdf_font_resource_t *pdfont, bool complete)
549
{
550
    if (pdfont->base_font != NULL)
551
	return pdf_base_font_font(pdfont->base_font, complete);
552
    if (pdfont->FontDescriptor == 0)
553
	return 0;
554
    return pdf_font_descriptor_font(pdfont->FontDescriptor, complete);
555
}
556
 
557
/*
558
 * Determine the embedding status of a font.  If the font is in the base
559
 * 14, store its index (0..13) in *pindex and its similarity to the base
560
 * font (as determined by the font's same_font procedure) in *psame.
561
 */
562
private bool
563
font_is_symbolic(const gs_font *font)
564
{
565
    if (font->FontType == ft_composite)
566
	return true;		/* arbitrary */
567
    switch (((const gs_font_base *)font)->nearest_encoding_index) {
568
    case ENCODING_INDEX_STANDARD:
569
    case ENCODING_INDEX_ISOLATIN1:
570
    case ENCODING_INDEX_WINANSI:
571
    case ENCODING_INDEX_MACROMAN:
572
	return false;
573
    default:
574
	return true;
575
    }
576
}
577
private bool
578
embed_list_includes(const gs_param_string_array *psa, const byte *chars,
579
		    uint size)
580
{
581
    uint i;
582
 
583
    for (i = 0; i < psa->size; ++i)
584
	if (!bytes_compare(psa->data[i].data, psa->data[i].size, chars, size))
585
	    return true;
586
    return false;
587
}
588
private bool
589
embed_as_standard(gx_device_pdf *pdev, gs_font *font, int index,
590
		  pdf_char_glyph_pair_t *pairs, int num_glyphs)
591
{
592
    if (font->is_resource) {
593
	return true;
594
    }
595
    if (find_std_appearance(pdev, (gs_font_base *)font, -1,
596
			    pairs, num_glyphs) == index)
597
	return true;
598
    if (!scan_for_standard_fonts(pdev, font->dir))
599
	return false;
600
    return (find_std_appearance(pdev, (gs_font_base *)font, -1,
601
				pairs, num_glyphs) == index);
602
}
603
private bool
604
has_extension_glyphs(gs_font *pfont)
605
{
606
    psf_glyph_enum_t genum;
607
    gs_glyph glyph;
608
    gs_const_string str;
609
    int code, j, l;
610
    const int sl = strlen(gx_extendeg_glyph_name_separator);
611
 
612
    psf_enumerate_glyphs_begin(&genum, (gs_font *)pfont, NULL, 0, GLYPH_SPACE_NAME);
613
    for (glyph = gs_no_glyph; (code = psf_enumerate_glyphs_next(&genum, &glyph)) != 1; ) {
614
	code = pfont->procs.glyph_name(pfont, glyph, &str);
615
	if (code < 0)
616
	    return code;
617
	l = str.size - sl, j;
618
	for (j = 0; j < l; j ++)
619
	    if (!memcmp(gx_extendeg_glyph_name_separator, str.data + j, sl))
620
		return true;
621
    }
622
    psf_enumerate_glyphs_reset(&genum);
623
    return false;
624
}
625
 
626
/*
627
 * Choose a name for embedded font.
628
 */
629
const gs_font_name *pdf_choose_font_name(gs_font *font, bool key_name)
630
{
631
    return key_name ? (font->key_name.size != 0 ? &font->key_name : &font->font_name)
632
	             : (font->font_name.size != 0 ? &font->font_name : &font->key_name);
633
}
634
pdf_font_embed_t
635
pdf_font_embed_status(gx_device_pdf *pdev, gs_font *font, int *pindex,
636
		      pdf_char_glyph_pair_t *pairs, int num_glyphs)
637
{
638
    const gs_font_name *fn = pdf_choose_font_name(font, false);
639
    const byte *chars = fn->chars;
640
    uint size = fn->size;
641
    int index = pdf_find_standard_font_name(chars, size);
642
    bool embed_as_standard_called = false;
643
    bool do_embed_as_standard = false; /* Quiet compiler. */
644
 
645
    /*
646
     * The behavior of Acrobat Distiller changed between 3.0 (PDF 1.2),
647
     * which will never embed the base 14 fonts, and 4.0 (PDF 1.3), which
648
     * doesn't treat them any differently from any other fonts.  However,
649
     * if any of the base 14 fonts is not embedded, it still requires
650
     * special treatment.
651
     */
652
    if (pindex)
653
	*pindex = index;
654
    if (pdev->PDFX)
655
	return FONT_EMBED_YES;
656
    if (pdev->CompatibilityLevel < 1.3) {
657
	if (index >= 0 && 
658
	    (embed_as_standard_called = true,
659
		do_embed_as_standard = embed_as_standard(pdev, font, index, pairs, num_glyphs))) {
660
	    if (pdev->ForOPDFRead && has_extension_glyphs(font))
661
		return FONT_EMBED_YES;
662
	    return FONT_EMBED_STANDARD;
663
	}
664
    }
665
    /* Check the Embed lists. */
666
    if (!embed_list_includes(&pdev->params.NeverEmbed, chars, size) ||
667
 	(index >= 0 && 
668
	    !(embed_as_standard_called ? do_embed_as_standard :
669
	     (embed_as_standard_called = true,
670
	      (do_embed_as_standard = embed_as_standard(pdev, font, index, pairs, num_glyphs)))))
671
 	/* Ignore NeverEmbed for a non-standard font with a standard name */
672
 	) {
673
	if (pdev->params.EmbedAllFonts || font_is_symbolic(font) ||
674
	    embed_list_includes(&pdev->params.AlwaysEmbed, chars, size))
675
	    return FONT_EMBED_YES;
676
    }
677
    if (index >= 0 && 
678
	(embed_as_standard_called ? do_embed_as_standard :
679
	 embed_as_standard(pdev, font, index, pairs, num_glyphs)))
680
	return FONT_EMBED_STANDARD;
681
    return FONT_EMBED_NO;
682
}
683
 
684
/*
685
 * Compute the BaseFont of a font according to the algorithm described
686
 * in gdevpdtf.h.
687
 */
688
int
689
pdf_compute_BaseFont(gx_device_pdf *pdev, pdf_font_resource_t *pdfont, bool finish)
690
{
691
    pdf_font_resource_t *pdsubf = pdfont;
692
    gs_string fname;
693
    uint size, extra = 0;
694
    byte *data;
695
 
696
    if (pdfont->FontType == ft_composite) {
697
	int code;
698
 
699
	pdsubf = pdfont->u.type0.DescendantFont;
700
	code = pdf_compute_BaseFont(pdev, pdsubf, finish);
701
	if (code < 0)
702
	    return code;
703
	fname = pdsubf->BaseFont;
704
	if (pdsubf->FontType == ft_CID_encrypted || pdsubf->FontType == ft_CID_TrueType)
705
	    extra = 1 + pdfont->u.type0.CMapName.size;
706
    }
707
    else if (pdfont->FontDescriptor == 0) {
708
	/* Type 3 font, or has its BaseFont computed in some other way. */
709
	return 0;
710
    } else
711
	fname = *pdf_font_descriptor_base_name(pdsubf->FontDescriptor);
712
    size = fname.size;
713
    data = gs_alloc_string(pdev->pdf_memory, size + extra,
714
			   "pdf_compute_BaseFont");
715
    if (data == 0)
716
	return_error(gs_error_VMerror);
717
    memcpy(data, fname.data, size);
718
    switch (pdfont->FontType) {
719
    case ft_composite:
720
	if (extra) {
721
	    data[size] = '-';
722
	    memcpy(data + size + 1, pdfont->u.type0.CMapName.data, extra - 1);
723
	    size += extra;
724
	}
725
	break;
726
    case ft_encrypted:
727
    case ft_encrypted2:
728
	if (pdfont->u.simple.s.type1.is_MM_instance &&
729
	    !pdf_font_descriptor_embedding(pdfont->FontDescriptor)
730
	    ) {
731
	    /* Replace spaces by underscores in the base name. */
732
	    uint i;
733
 
734
	    for (i = 0; i < size; ++i)
735
		if (data[i] == ' ')
736
		    data[i] = '_';
737
	}
738
	break;
739
    case ft_TrueType:
740
    case ft_CID_TrueType: {
741
	/* Remove spaces from the base name. */
742
	uint i, j;
743
 
744
	for (i = j = 0; i < size; ++i)
745
	    if (data[i] != ' ')
746
		data[j++] = data[i];
747
	data = gs_resize_string(pdev->pdf_memory, data, i, j,
748
				"pdf_compute_BaseFont");
749
	size = j;
750
	break;
751
    }
752
    default:
753
	break;
754
    }
755
    pdfont->BaseFont.data = fname.data = data;
756
    pdfont->BaseFont.size = fname.size = size;
757
    /* Compute names for subset fonts. */
758
    if (finish && pdfont->FontDescriptor != NULL &&
759
	pdf_font_descriptor_is_subset(pdfont->FontDescriptor) &&
760
	!pdf_has_subset_prefix(fname.data, fname.size) &&
761
	pdf_font_descriptor_embedding(pdfont->FontDescriptor)
762
	) {
763
	int code = pdf_add_subset_prefix(pdev, &fname, pdfont->used, pdfont->count);
764
 
765
	if (code < 0)
766
	    return code;
767
        pdfont->BaseFont = fname;
768
	/* Don't write a UID for subset fonts. */
769
	uid_set_invalid(&pdf_font_resource_font(pdfont, false)->UID);
770
    }
771
    if (pdfont->FontType != ft_composite && pdsubf->FontDescriptor)
772
	*pdf_font_descriptor_name(pdsubf->FontDescriptor) = fname;
773
    return 0;
774
}
775
 
776
/* ------ Type 0 ------ */
777
 
778
/* Allocate a Type 0 font resource. */
779
int
780
pdf_font_type0_alloc(gx_device_pdf *pdev, pdf_font_resource_t **ppfres,
781
		     gs_id rid, pdf_font_resource_t *DescendantFont, 
782
		     const gs_const_string *CMapName)
783
{
784
    int code = font_resource_alloc(pdev, ppfres, resourceFont, rid,
785
				   ft_composite, 0, pdf_write_contents_type0);
786
 
787
    if (code >= 0) {
788
	(*ppfres)->u.type0.DescendantFont = DescendantFont;
789
	(*ppfres)->u.type0.CMapName = *CMapName;
790
	code = pdf_compute_BaseFont(pdev, *ppfres, false);
791
    }
792
    return code;    
793
}
794
 
795
/* ------ Type 3 ------ */
796
 
797
/* Allocate a Type 3 font resource for sinthesyzed bitmap fonts. */
798
int
799
pdf_font_type3_alloc(gx_device_pdf *pdev, pdf_font_resource_t **ppfres,
800
		     pdf_font_write_contents_proc_t write_contents)
801
{
802
    return font_resource_simple_alloc(pdev, ppfres, gs_no_id, ft_user_defined,
803
				      256, write_contents);
804
}
805
 
806
/* ------ Standard (base 14) Type 1 or TrueType ------ */
807
 
808
/* Allocate a standard (base 14) font resource. */
809
int
810
pdf_font_std_alloc(gx_device_pdf *pdev, pdf_font_resource_t **ppfres,
811
		   bool is_original, gs_id rid, gs_font_base *pfont, int index)
812
{
813
    pdf_font_resource_t *pdfont;
814
    int code = font_resource_encoded_alloc(pdev, &pdfont, rid, pfont->FontType,
815
					   pdf_write_contents_std);
816
    const pdf_standard_font_info_t *psfi = &standard_font_info[index];
817
    pdf_standard_font_t *psf = &pdf_standard_fonts(pdev)[index];
818
    gs_matrix *orig_matrix = (is_original ? &pfont->FontMatrix : &psf->orig_matrix);
819
 
820
    if (code < 0 ||
821
	(code = pdf_base_font_alloc(pdev, &pdfont->base_font, pfont, orig_matrix, true, true)) < 0
822
	)
823
	return code;
824
    pdfont->BaseFont.data = (byte *)psfi->fname; /* break const */
825
    pdfont->BaseFont.size = strlen(psfi->fname);
826
    set_is_MM_instance(pdfont, pfont);
827
    if (is_original) {
828
	psf->pdfont = pdfont;
829
	psf->orig_matrix = pfont->FontMatrix;
830
    }
831
    *ppfres = pdfont;
832
    return 0;
833
}
834
 
835
/* ------ Other Type 1 or TrueType ------ */
836
 
837
/* Allocate a Type 1 or TrueType font resource. */
838
int
839
pdf_font_simple_alloc(gx_device_pdf *pdev, pdf_font_resource_t **ppfres,
840
		      gs_id rid, pdf_font_descriptor_t *pfd)
841
{
842
    pdf_font_resource_t *pdfont;
843
    int code;
844
 
845
    code = font_resource_encoded_alloc(pdev, &pdfont, rid,
846
					   pdf_font_descriptor_FontType(pfd),
847
					   pdf_write_contents_simple);
848
 
849
    pdfont->FontDescriptor = pfd;
850
    set_is_MM_instance(pdfont, pdf_font_descriptor_font(pfd, false));
851
    *ppfres = pdfont;
852
    return pdf_compute_BaseFont(pdev, pdfont, false);
853
}
854
 
855
/* ------ CID-keyed ------ */
856
 
857
/* Allocate a CIDFont resource. */
858
int
859
pdf_font_cidfont_alloc(gx_device_pdf *pdev, pdf_font_resource_t **ppfres,
860
		       gs_id rid, pdf_font_descriptor_t *pfd)
861
{
862
    font_type FontType = pdf_font_descriptor_FontType(pfd);
863
    gs_font_base *font = pdf_font_descriptor_font(pfd, false);
864
    int chars_count;
865
    int code;
866
    pdf_font_write_contents_proc_t write_contents;
867
    const gs_cid_system_info_t *pcidsi;
868
    ushort *map = 0;
869
    pdf_font_resource_t *pdfont;
870
 
871
    switch (FontType) {
872
    case ft_CID_encrypted:
873
	chars_count = ((const gs_font_cid0 *)font)->cidata.common.CIDCount;
874
	pcidsi = &((const gs_font_cid0 *)font)->cidata.common.CIDSystemInfo;
875
	write_contents = pdf_write_contents_cid0;
876
	break;
877
    case ft_CID_TrueType:
878
	chars_count = ((const gs_font_cid2 *)font)->cidata.common.CIDCount;
879
	pcidsi = &((const gs_font_cid2 *)font)->cidata.common.CIDSystemInfo;
880
	map = (void *)gs_alloc_byte_array(pdev->pdf_memory, chars_count,
881
					  sizeof(*map), "CIDToGIDMap");
882
	if (map == 0)
883
	    return_error(gs_error_VMerror);
884
	memset(map, 0, chars_count * sizeof(*map));
885
	write_contents = pdf_write_contents_cid2;
886
	break;
887
    default:
888
	return_error(gs_error_rangecheck);
889
    }
890
    code = font_resource_alloc(pdev, &pdfont, resourceCIDFont, rid, FontType,
891
			       chars_count, write_contents);
892
    if (code < 0)
893
	return code;
894
    pdfont->FontDescriptor = pfd;
895
    pdfont->u.cidfont.CIDToGIDMap = map;
896
    /* fixme : Likely pdfont->u.cidfont.CIDToGIDMap duplicates 
897
       pdfont->FontDescriptor->base_font->copied->client_data->CIDMap.
898
       Only difference is 0xFFFF designates unmapped CIDs.
899
     */
900
    pdfont->u.cidfont.Widths2 = NULL;
901
    pdfont->u.cidfont.v = NULL;
902
    pdfont->u.cidfont.parent = NULL;
903
    /* Don' know whether the font will use WMode 1,
904
       so reserve it now. */
905
    pdfont->u.cidfont.used2 = gs_alloc_bytes(pdev->pdf_memory, 
906
		(chars_count + 7) / 8, "pdf_font_cidfont_alloc");
907
    if (pdfont->u.cidfont.used2 == NULL)
908
        return_error(gs_error_VMerror);
909
    memset(pdfont->u.cidfont.used2, 0, (chars_count + 7) / 8);
910
    /*
911
     * Write the CIDSystemInfo now, so we don't try to access it after
912
     * the font may no longer be available.
913
     */
914
    {
915
	long cidsi_id = pdf_begin_separate(pdev);
916
 
917
	code = pdf_write_cid_system_info(pdev, pcidsi, cidsi_id);
918
	if (code < 0)
919
	    return code;
920
	pdf_end_separate(pdev);
921
	pdfont->u.cidfont.CIDSystemInfo_id = cidsi_id;
922
    }
923
    *ppfres = pdfont;
924
    return pdf_compute_BaseFont(pdev, pdfont, false);
925
}
926
 
927
int
928
pdf_obtain_cidfont_widths_arrays(gx_device_pdf *pdev, pdf_font_resource_t *pdfont, 
929
                                 int wmode, double **w, double **w0, double **v)
930
{
931
    gs_memory_t *mem = pdev->pdf_memory;
932
    double *ww, *vv = 0, *ww0 = 0;
933
    int chars_count = pdfont->count;
934
 
935
    *w0 = (wmode ? pdfont->Widths : NULL);
936
    *v = (wmode ? pdfont->u.cidfont.v : NULL);
937
    *w = (wmode ? pdfont->u.cidfont.Widths2 : pdfont->Widths);
938
    if (*w == NULL) {
939
	ww = (double *)gs_alloc_byte_array(mem, chars_count, sizeof(*ww),
940
						    "pdf_obtain_cidfont_widths_arrays");
941
	if (wmode) {
942
	    vv = (double *)gs_alloc_byte_array(mem, chars_count, sizeof(*vv) * 2,
943
						    "pdf_obtain_cidfont_widths_arrays");
944
	    if (pdfont->Widths == 0) {
945
		ww0 = (double *)gs_alloc_byte_array(mem, chars_count, sizeof(*ww0),
946
						    "pdf_obtain_cidfont_widths_arrays");
947
		pdfont->Widths = *w0 = ww0;
948
		if (ww0 != 0)
949
		    memset(ww0, 0, chars_count * sizeof(*ww));
950
	    } else
951
		*w0 = ww0 = pdfont->Widths;
952
	}
953
	if (ww == 0 || (wmode && vv == 0) || (wmode && ww0 == 0)) {
954
	    gs_free_object(mem, ww, "pdf_obtain_cidfont_widths_arrays");
955
	    gs_free_object(mem, vv, "pdf_obtain_cidfont_widths_arrays");
956
	    gs_free_object(mem, ww0, "pdf_obtain_cidfont_widths_arrays");
957
	    return_error(gs_error_VMerror);
958
	}
959
	if (wmode)
960
	    memset(vv, 0, chars_count * 2 * sizeof(*vv));
961
	memset(ww, 0, chars_count * sizeof(*ww));
962
	if (wmode) {
963
	    pdfont->u.cidfont.Widths2 = *w = ww;	
964
	    pdfont->u.cidfont.v = *v = vv;	
965
	} else {
966
	    pdfont->Widths = *w = ww;
967
	    *v = NULL;
968
	}
969
    }
970
    return 0;
971
}
972
 
973
/* ---------------- CMap resources ---------------- */
974
 
975
/*
976
 * Allocate a CMap resource.
977
 */
978
int
979
pdf_cmap_alloc(gx_device_pdf *pdev, const gs_cmap_t *pcmap,
980
	       pdf_resource_t **ppres, int font_index_only)
981
{
982
    return pdf_write_cmap(pdev, pcmap, ppres, font_index_only);
983
}