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: gdevpdtb.c,v 1.36 2005/04/25 02:23:58 igor Exp $ */
|
|
|
18 |
/* BaseFont implementation for pdfwrite */
|
|
|
19 |
#include "memory_.h"
|
|
|
20 |
#include "ctype_.h"
|
|
|
21 |
#include "string_.h"
|
|
|
22 |
#include "gx.h"
|
|
|
23 |
#include "gserrors.h"
|
|
|
24 |
#include "gsutil.h" /* for bytes_compare */
|
|
|
25 |
#include "gxfcid.h"
|
|
|
26 |
#include "gxfcopy.h"
|
|
|
27 |
#include "gxfont.h" /* for gxfont42.h */
|
|
|
28 |
#include "gxfont42.h"
|
|
|
29 |
#include "gdevpsf.h"
|
|
|
30 |
#include "gdevpdfx.h"
|
|
|
31 |
#include "gdevpdfo.h"
|
|
|
32 |
#include "gdevpdtb.h"
|
|
|
33 |
#include "gdevpdtf.h"
|
|
|
34 |
|
|
|
35 |
/*
|
|
|
36 |
* Adobe's Distiller Parameters documentation for Acrobat Distiller 5
|
|
|
37 |
* says that all fonts other than Type 1 are always subsetted; the
|
|
|
38 |
* documentation for Distiller 4 says that fonts other than Type 1 and
|
|
|
39 |
* TrueType are subsetted. We do the latter, except that we always
|
|
|
40 |
* subset large TrueType fonts.
|
|
|
41 |
*/
|
|
|
42 |
#define MAX_NO_SUBSET_GLYPHS 500 /* arbitrary */
|
|
|
43 |
|
|
|
44 |
/* ---------------- Definitions ---------------- */
|
|
|
45 |
|
|
|
46 |
struct pdf_base_font_s {
|
|
|
47 |
/*
|
|
|
48 |
* For the standard 14 fonts, copied == complete is a complete copy
|
|
|
49 |
* of the font, and DO_SUBSET = NO.
|
|
|
50 |
*
|
|
|
51 |
* For fonts that MAY be subsetted, copied is a partial copy,
|
|
|
52 |
* complete is a complete copy, and DO_SUBSET = UNKNOWN until
|
|
|
53 |
* pdf_font_do_subset is called.
|
|
|
54 |
*
|
|
|
55 |
* For fonts that MUST be subsetted, copied == complete is a partial
|
|
|
56 |
* copy, and DO_SUBSET = YES.
|
|
|
57 |
*/
|
|
|
58 |
gs_font_base *copied;
|
|
|
59 |
gs_font_base *complete;
|
|
|
60 |
enum {
|
|
|
61 |
DO_SUBSET_UNKNOWN = 0,
|
|
|
62 |
DO_SUBSET_NO,
|
|
|
63 |
DO_SUBSET_YES
|
|
|
64 |
} do_subset;
|
|
|
65 |
bool is_standard;
|
|
|
66 |
/*
|
|
|
67 |
* For CIDFonts, which are always subsetted, num_glyphs is CIDCount.
|
|
|
68 |
* For optionally subsetted fonts, num_glyphs is the count of glyphs
|
|
|
69 |
* in the font when originally copied. Note that if the font is
|
|
|
70 |
* downloaded incrementally, num_glyphs may be 0.
|
|
|
71 |
*/
|
|
|
72 |
int num_glyphs;
|
|
|
73 |
byte *CIDSet; /* for CIDFonts */
|
|
|
74 |
gs_string font_name;
|
|
|
75 |
bool written;
|
|
|
76 |
cos_dict_t *FontFile;
|
|
|
77 |
};
|
|
|
78 |
BASIC_PTRS(pdf_base_font_ptrs) {
|
|
|
79 |
GC_OBJ_ELT(pdf_base_font_t, copied),
|
|
|
80 |
GC_OBJ_ELT(pdf_base_font_t, complete),
|
|
|
81 |
GC_OBJ_ELT(pdf_base_font_t, CIDSet),
|
|
|
82 |
GC_OBJ_ELT(pdf_base_font_t, FontFile),
|
|
|
83 |
GC_STRING_ELT(pdf_base_font_t, font_name)
|
|
|
84 |
};
|
|
|
85 |
gs_private_st_basic(st_pdf_base_font, pdf_base_font_t, "pdf_base_font_t",
|
|
|
86 |
pdf_base_font_ptrs, pdf_base_font_data);
|
|
|
87 |
|
|
|
88 |
/* ---------------- Private ---------------- */
|
|
|
89 |
|
|
|
90 |
#define SUBSET_PREFIX_SIZE 7 /* XXXXXX+ */
|
|
|
91 |
|
|
|
92 |
/*
|
|
|
93 |
* Determine whether a font is a subset font by examining the name.
|
|
|
94 |
*/
|
|
|
95 |
bool
|
|
|
96 |
pdf_has_subset_prefix(const byte *str, uint size)
|
|
|
97 |
{
|
|
|
98 |
int i;
|
|
|
99 |
|
|
|
100 |
if (size < SUBSET_PREFIX_SIZE || str[SUBSET_PREFIX_SIZE - 1] != '+')
|
|
|
101 |
return false;
|
|
|
102 |
for (i = 0; i < SUBSET_PREFIX_SIZE - 1; ++i)
|
|
|
103 |
if ((uint)(str[i] - 'A') >= 26)
|
|
|
104 |
return false;
|
|
|
105 |
return true;
|
|
|
106 |
}
|
|
|
107 |
|
|
|
108 |
private ulong
|
|
|
109 |
hash(ulong v, int index, ushort w)
|
|
|
110 |
{
|
|
|
111 |
return v * 3141592653u + w;
|
|
|
112 |
}
|
|
|
113 |
|
|
|
114 |
/*
|
|
|
115 |
* Add the XXXXXX+ prefix for a subset font.
|
|
|
116 |
*/
|
|
|
117 |
int
|
|
|
118 |
pdf_add_subset_prefix(const gx_device_pdf *pdev, gs_string *pstr, byte *used, int count)
|
|
|
119 |
{
|
|
|
120 |
uint size = pstr->size;
|
|
|
121 |
byte *data = gs_resize_string(pdev->pdf_memory, pstr->data, size,
|
|
|
122 |
size + SUBSET_PREFIX_SIZE,
|
|
|
123 |
"pdf_add_subset_prefix");
|
|
|
124 |
int len = (count + 7) / 8;
|
|
|
125 |
ulong v = 0;
|
|
|
126 |
ushort t = 0;
|
|
|
127 |
int i;
|
|
|
128 |
|
|
|
129 |
if (data == 0)
|
|
|
130 |
return_error(gs_error_VMerror);
|
|
|
131 |
/* Hash the 'used' array. */
|
|
|
132 |
for (i = 0; i < len; i += sizeof(ushort))
|
|
|
133 |
v = hash(v, i, *(ushort *)(used + i));
|
|
|
134 |
if (i < len) {
|
|
|
135 |
i -= sizeof(ushort);
|
|
|
136 |
memmove(&t, used + i, len - i);
|
|
|
137 |
v = hash(v, i, *(ushort *)(used + i));
|
|
|
138 |
}
|
|
|
139 |
memmove(data + SUBSET_PREFIX_SIZE, data, size);
|
|
|
140 |
for (i = 0; i < SUBSET_PREFIX_SIZE - 1; ++i, v /= 26)
|
|
|
141 |
data[i] = 'A' + (v % 26);
|
|
|
142 |
data[SUBSET_PREFIX_SIZE - 1] = '+';
|
|
|
143 |
pstr->data = data;
|
|
|
144 |
pstr->size = size + SUBSET_PREFIX_SIZE;
|
|
|
145 |
return 0;
|
|
|
146 |
}
|
|
|
147 |
|
|
|
148 |
/* Finish writing FontFile* data. */
|
|
|
149 |
private int
|
|
|
150 |
pdf_end_fontfile(gx_device_pdf *pdev, pdf_data_writer_t *pdw)
|
|
|
151 |
{
|
|
|
152 |
/* We would like to call pdf_end_data,
|
|
|
153 |
but we don't want to write the object to the output file now. */
|
|
|
154 |
return pdf_close_aside(pdw->pdev);
|
|
|
155 |
}
|
|
|
156 |
|
|
|
157 |
/* ---------------- Public ---------------- */
|
|
|
158 |
|
|
|
159 |
/*
|
|
|
160 |
* Allocate and initialize a base font structure, making the required
|
|
|
161 |
* stable copy/ies of the gs_font. Note that this removes any XXXXXX+
|
|
|
162 |
* font name prefix from the copy. If is_standard is true, the copy is
|
|
|
163 |
* a complete one, and adding glyphs or Encoding entries is not allowed.
|
|
|
164 |
*/
|
|
|
165 |
int
|
|
|
166 |
pdf_base_font_alloc(gx_device_pdf *pdev, pdf_base_font_t **ppbfont,
|
|
|
167 |
gs_font_base *font, const gs_matrix *orig_matrix,
|
|
|
168 |
bool is_standard, bool orig_name)
|
|
|
169 |
{
|
|
|
170 |
gs_memory_t *mem = pdev->pdf_memory;
|
|
|
171 |
gs_font *copied;
|
|
|
172 |
gs_font *complete;
|
|
|
173 |
pdf_base_font_t *pbfont =
|
|
|
174 |
gs_alloc_struct(mem, pdf_base_font_t,
|
|
|
175 |
&st_pdf_base_font, "pdf_base_font_alloc");
|
|
|
176 |
const gs_font_name *pfname = pdf_choose_font_name((gs_font *)font, orig_name);
|
|
|
177 |
gs_const_string font_name;
|
|
|
178 |
char fnbuf[3 + sizeof(long) / 3 + 1]; /* .F#######\0 */
|
|
|
179 |
int code;
|
|
|
180 |
|
|
|
181 |
if (pbfont == 0)
|
|
|
182 |
return_error(gs_error_VMerror);
|
|
|
183 |
code = gs_copy_font((gs_font *)font, orig_matrix, mem, &copied);
|
|
|
184 |
if (code < 0)
|
|
|
185 |
goto fail;
|
|
|
186 |
memset(pbfont, 0, sizeof(*pbfont));
|
|
|
187 |
{
|
|
|
188 |
/*
|
|
|
189 |
* Adobe Technical Note # 5012 "The Type 42 Font Format Specification" says :
|
|
|
190 |
*
|
|
|
191 |
* There is a known bug in the TrueType rasterizer included in versions of the
|
|
|
192 |
* PostScript interpreter previous to version 2013. The problem is that the
|
|
|
193 |
* translation components of the FontMatrix, as used as an argument to the
|
|
|
194 |
* definefont or makefont operators, are ignored. Translation of user space is
|
|
|
195 |
* not affected by this bug.
|
|
|
196 |
*
|
|
|
197 |
* Besides that, we found that Adobe Acrobat Reader 4 and 5 ignore
|
|
|
198 |
* FontMatrix.ty .
|
|
|
199 |
*/
|
|
|
200 |
copied->FontMatrix.tx = copied->FontMatrix.ty = 0;
|
|
|
201 |
}
|
|
|
202 |
switch (font->FontType) {
|
|
|
203 |
case ft_encrypted:
|
|
|
204 |
case ft_encrypted2:
|
|
|
205 |
pbfont->do_subset = (is_standard ? DO_SUBSET_NO : DO_SUBSET_UNKNOWN);
|
|
|
206 |
/* We will count the number of glyphs below. */
|
|
|
207 |
pbfont->num_glyphs = -1;
|
|
|
208 |
break;
|
|
|
209 |
case ft_TrueType:
|
|
|
210 |
pbfont->num_glyphs = ((gs_font_type42 *)font)->data.trueNumGlyphs;
|
|
|
211 |
pbfont->do_subset =
|
|
|
212 |
(pbfont->num_glyphs <= MAX_NO_SUBSET_GLYPHS ?
|
|
|
213 |
DO_SUBSET_UNKNOWN : DO_SUBSET_YES);
|
|
|
214 |
break;
|
|
|
215 |
case ft_CID_encrypted:
|
|
|
216 |
pbfont->num_glyphs = ((gs_font_cid0 *)font)->cidata.common.CIDCount;
|
|
|
217 |
goto cid;
|
|
|
218 |
case ft_CID_TrueType:
|
|
|
219 |
pbfont->num_glyphs = ((gs_font_cid2 *)font)->cidata.common.CIDCount;
|
|
|
220 |
cid:
|
|
|
221 |
pbfont->do_subset = DO_SUBSET_YES;
|
|
|
222 |
pbfont->CIDSet =
|
|
|
223 |
gs_alloc_bytes(mem, (pbfont->num_glyphs + 7) / 8,
|
|
|
224 |
"pdf_base_font_alloc(CIDSet)");
|
|
|
225 |
if (pbfont->CIDSet == 0) {
|
|
|
226 |
code = gs_note_error(gs_error_VMerror);
|
|
|
227 |
goto fail;
|
|
|
228 |
}
|
|
|
229 |
memset(pbfont->CIDSet, 0, (pbfont->num_glyphs + 7) / 8);
|
|
|
230 |
break;
|
|
|
231 |
default:
|
|
|
232 |
code = gs_note_error(gs_error_rangecheck);
|
|
|
233 |
goto fail;
|
|
|
234 |
}
|
|
|
235 |
if (pbfont->do_subset != DO_SUBSET_YES) {
|
|
|
236 |
/* The only possibly non-subsetted fonts are Type 1/2 and Type 42. */
|
|
|
237 |
if (is_standard)
|
|
|
238 |
complete = copied, code = 0;
|
|
|
239 |
else
|
|
|
240 |
code = gs_copy_font((gs_font *)font, &font->FontMatrix, mem, &complete);
|
|
|
241 |
if (code >= 0)
|
|
|
242 |
code = gs_copy_font_complete((gs_font *)font, complete);
|
|
|
243 |
if (pbfont->num_glyphs < 0) { /* Type 1 */
|
|
|
244 |
int index, count;
|
|
|
245 |
gs_glyph glyph;
|
|
|
246 |
|
|
|
247 |
for (index = 0, count = 0;
|
|
|
248 |
(font->procs.enumerate_glyph((gs_font *)font, &index,
|
|
|
249 |
GLYPH_SPACE_NAME, &glyph),
|
|
|
250 |
index != 0);
|
|
|
251 |
)
|
|
|
252 |
++count;
|
|
|
253 |
pbfont->num_glyphs = count;
|
|
|
254 |
}
|
|
|
255 |
} else
|
|
|
256 |
complete = copied;
|
|
|
257 |
pbfont->copied = (gs_font_base *)copied;
|
|
|
258 |
pbfont->complete = (gs_font_base *)complete;
|
|
|
259 |
pbfont->is_standard = is_standard;
|
|
|
260 |
if (pfname->size > 0) {
|
|
|
261 |
font_name.data = pfname->chars;
|
|
|
262 |
font_name.size = pfname->size;
|
|
|
263 |
while (pdf_has_subset_prefix(font_name.data, font_name.size)) {
|
|
|
264 |
/* Strip off an existing subset prefix. */
|
|
|
265 |
font_name.data += SUBSET_PREFIX_SIZE;
|
|
|
266 |
font_name.size -= SUBSET_PREFIX_SIZE;
|
|
|
267 |
}
|
|
|
268 |
} else {
|
|
|
269 |
sprintf(fnbuf, ".F%lx", (ulong)copied);
|
|
|
270 |
font_name.data = (byte *)fnbuf;
|
|
|
271 |
font_name.size = strlen(fnbuf);
|
|
|
272 |
}
|
|
|
273 |
pbfont->font_name.data =
|
|
|
274 |
gs_alloc_string(mem, font_name.size, "pdf_base_font_alloc(font_name)");
|
|
|
275 |
if (pbfont->font_name.data == 0)
|
|
|
276 |
goto fail;
|
|
|
277 |
memcpy(pbfont->font_name.data, font_name.data, font_name.size);
|
|
|
278 |
pbfont->font_name.size = font_name.size;
|
|
|
279 |
*ppbfont = pbfont;
|
|
|
280 |
return 0;
|
|
|
281 |
fail:
|
|
|
282 |
gs_free_object(mem, pbfont, "pdf_base_font_alloc");
|
|
|
283 |
return code;
|
|
|
284 |
}
|
|
|
285 |
|
|
|
286 |
/*
|
|
|
287 |
* Return a reference to the name of a base font. This name is guaranteed
|
|
|
288 |
* not to have a XXXXXX+ prefix. The client may change the name at will,
|
|
|
289 |
* but must not add a XXXXXX+ prefix.
|
|
|
290 |
*/
|
|
|
291 |
gs_string *
|
|
|
292 |
pdf_base_font_name(pdf_base_font_t *pbfont)
|
|
|
293 |
{
|
|
|
294 |
return &pbfont->font_name;
|
|
|
295 |
}
|
|
|
296 |
|
|
|
297 |
/*
|
|
|
298 |
* Return the (copied, subset) font associated with a base font.
|
|
|
299 |
* This procedure probably shouldn't exist....
|
|
|
300 |
*/
|
|
|
301 |
gs_font_base *
|
|
|
302 |
pdf_base_font_font(const pdf_base_font_t *pbfont, bool complete)
|
|
|
303 |
{
|
|
|
304 |
return (complete ? pbfont->complete : pbfont->copied);
|
|
|
305 |
}
|
|
|
306 |
|
|
|
307 |
/*
|
|
|
308 |
* Check for subset font.
|
|
|
309 |
*/
|
|
|
310 |
bool
|
|
|
311 |
pdf_base_font_is_subset(const pdf_base_font_t *pbfont)
|
|
|
312 |
{
|
|
|
313 |
return pbfont->do_subset == DO_SUBSET_YES;
|
|
|
314 |
}
|
|
|
315 |
|
|
|
316 |
/*
|
|
|
317 |
* Drop the copied complete font associated with a base font.
|
|
|
318 |
*/
|
|
|
319 |
void
|
|
|
320 |
pdf_base_font_drop_complete(pdf_base_font_t *pbfont)
|
|
|
321 |
{
|
|
|
322 |
pbfont->complete = NULL;
|
|
|
323 |
}
|
|
|
324 |
|
|
|
325 |
/*
|
|
|
326 |
* Copy a glyph (presumably one that was just used) into a saved base
|
|
|
327 |
* font. Note that it is the client's responsibility to determine that
|
|
|
328 |
* the source font is compatible with the target font. (Normally they
|
|
|
329 |
* will be the same.)
|
|
|
330 |
*/
|
|
|
331 |
int
|
|
|
332 |
pdf_base_font_copy_glyph(pdf_base_font_t *pbfont, gs_glyph glyph,
|
|
|
333 |
gs_font_base *font)
|
|
|
334 |
{
|
|
|
335 |
int code =
|
|
|
336 |
gs_copy_glyph_options((gs_font *)font, glyph,
|
|
|
337 |
(gs_font *)pbfont->copied,
|
|
|
338 |
(pbfont->is_standard ? COPY_GLYPH_NO_NEW : 0));
|
|
|
339 |
|
|
|
340 |
if (code < 0)
|
|
|
341 |
return code;
|
|
|
342 |
if (pbfont->CIDSet != 0 &&
|
|
|
343 |
(uint)(glyph - GS_MIN_CID_GLYPH) < pbfont->num_glyphs
|
|
|
344 |
) {
|
|
|
345 |
uint cid = glyph - GS_MIN_CID_GLYPH;
|
|
|
346 |
|
|
|
347 |
pbfont->CIDSet[cid >> 3] |= 0x80 >> (cid & 7);
|
|
|
348 |
}
|
|
|
349 |
return 0;
|
|
|
350 |
}
|
|
|
351 |
|
|
|
352 |
/*
|
|
|
353 |
* Determine whether a font should be subsetted.
|
|
|
354 |
*/
|
|
|
355 |
bool
|
|
|
356 |
pdf_do_subset_font(gx_device_pdf *pdev, pdf_base_font_t *pbfont, gs_id rid)
|
|
|
357 |
{
|
|
|
358 |
gs_font_base *copied = pbfont->copied;
|
|
|
359 |
|
|
|
360 |
/*
|
|
|
361 |
* If the decision has not been made already, determine whether or not
|
|
|
362 |
* to subset the font.
|
|
|
363 |
*/
|
|
|
364 |
if (pbfont->do_subset == DO_SUBSET_UNKNOWN) {
|
|
|
365 |
int max_pct = pdev->params.MaxSubsetPct;
|
|
|
366 |
bool do_subset = pdev->params.SubsetFonts && max_pct > 0;
|
|
|
367 |
|
|
|
368 |
if (do_subset && max_pct < 100) {
|
|
|
369 |
/* We want to subset iff used <= total * MaxSubsetPct / 100. */
|
|
|
370 |
do_subset = false;
|
|
|
371 |
if (max_pct > 0) {
|
|
|
372 |
int max_subset_used = pbfont->num_glyphs * max_pct / 100;
|
|
|
373 |
int used, index;
|
|
|
374 |
gs_glyph ignore_glyph;
|
|
|
375 |
|
|
|
376 |
do_subset = true;
|
|
|
377 |
for (index = 0, used = 0;
|
|
|
378 |
(copied->procs.enumerate_glyph((gs_font *)copied,
|
|
|
379 |
&index, GLYPH_SPACE_INDEX,
|
|
|
380 |
&ignore_glyph), index != 0);
|
|
|
381 |
)
|
|
|
382 |
if (++used > max_subset_used) {
|
|
|
383 |
do_subset = false;
|
|
|
384 |
break;
|
|
|
385 |
}
|
|
|
386 |
}
|
|
|
387 |
}
|
|
|
388 |
pbfont->do_subset = (do_subset ? DO_SUBSET_YES : DO_SUBSET_NO);
|
|
|
389 |
}
|
|
|
390 |
return (pbfont->do_subset == DO_SUBSET_YES);
|
|
|
391 |
}
|
|
|
392 |
|
|
|
393 |
/*
|
|
|
394 |
* Write the FontFile entry for an embedded font, /FontFile<n> # # R.
|
|
|
395 |
*/
|
|
|
396 |
int
|
|
|
397 |
pdf_write_FontFile_entry(gx_device_pdf *pdev, pdf_base_font_t *pbfont)
|
|
|
398 |
{
|
|
|
399 |
stream *s = pdev->strm;
|
|
|
400 |
const char *FontFile_key;
|
|
|
401 |
|
|
|
402 |
switch (pbfont->copied->FontType) {
|
|
|
403 |
case ft_TrueType:
|
|
|
404 |
case ft_CID_TrueType:
|
|
|
405 |
FontFile_key = "/FontFile2";
|
|
|
406 |
break;
|
|
|
407 |
default: /* Type 1/2, CIDFontType 0 */
|
|
|
408 |
if (pdev->ResourcesBeforeUsage)
|
|
|
409 |
FontFile_key = "/FontFile";
|
|
|
410 |
else
|
|
|
411 |
FontFile_key = "/FontFile3";
|
|
|
412 |
}
|
|
|
413 |
stream_puts(s, FontFile_key);
|
|
|
414 |
pprintld1(s, " %ld 0 R", pbfont->FontFile->id);
|
|
|
415 |
return 0;
|
|
|
416 |
}
|
|
|
417 |
|
|
|
418 |
/*
|
|
|
419 |
* Adjust font name for Acrobat Reader 3.
|
|
|
420 |
*/
|
|
|
421 |
private int
|
|
|
422 |
pdf_adjust_font_name(gx_device_pdf *pdev, long id, pdf_base_font_t *pbfont)
|
|
|
423 |
{
|
|
|
424 |
/*
|
|
|
425 |
* In contradiction with previous version of pdfwrite,
|
|
|
426 |
* this always adds a suffix. We don't check the original name
|
|
|
427 |
* for uniquity bacause the layered architecture
|
|
|
428 |
* (see gdevpdtx.h) doesn't provide an easy access for
|
|
|
429 |
* related information.
|
|
|
430 |
*/
|
|
|
431 |
int i;
|
|
|
432 |
byte *chars = (byte *)pbfont->font_name.data; /* break 'const' */
|
|
|
433 |
byte *data;
|
|
|
434 |
uint size = pbfont->font_name.size;
|
|
|
435 |
char suffix[sizeof(long) * 2 + 2];
|
|
|
436 |
uint suffix_size;
|
|
|
437 |
|
|
|
438 |
#define SUFFIX_CHAR '~'
|
|
|
439 |
/*
|
|
|
440 |
* If the name looks as though it has one of our unique suffixes,
|
|
|
441 |
* remove the suffix.
|
|
|
442 |
*/
|
|
|
443 |
for (i = size;
|
|
|
444 |
i > 0 && isxdigit(chars[i - 1]);
|
|
|
445 |
--i)
|
|
|
446 |
DO_NOTHING;
|
|
|
447 |
if (i < size && i > 0 && chars[i - 1] == SUFFIX_CHAR) {
|
|
|
448 |
do {
|
|
|
449 |
--i;
|
|
|
450 |
} while (i > 0 && chars[i - 1] == SUFFIX_CHAR);
|
|
|
451 |
size = i + 1;
|
|
|
452 |
}
|
|
|
453 |
/* Create a unique name. */
|
|
|
454 |
sprintf(suffix, "%c%lx", SUFFIX_CHAR, id);
|
|
|
455 |
suffix_size = strlen(suffix);
|
|
|
456 |
data = gs_resize_string(pdev->pdf_memory, chars, size,
|
|
|
457 |
size + suffix_size,
|
|
|
458 |
"pdf_adjust_font_name");
|
|
|
459 |
if (data == 0)
|
|
|
460 |
return_error(gs_error_VMerror);
|
|
|
461 |
memcpy(data + size, (const byte *)suffix, suffix_size);
|
|
|
462 |
pbfont->font_name.data = data;
|
|
|
463 |
pbfont->font_name.size = size + suffix_size;
|
|
|
464 |
#undef SUFFIX_CHAR
|
|
|
465 |
return 0;
|
|
|
466 |
}
|
|
|
467 |
|
|
|
468 |
/*
|
|
|
469 |
* Write an embedded font.
|
|
|
470 |
*/
|
|
|
471 |
int
|
|
|
472 |
pdf_write_embedded_font(gx_device_pdf *pdev, pdf_base_font_t *pbfont,
|
|
|
473 |
gs_int_rect *FontBBox, gs_id rid, cos_dict_t **ppcd)
|
|
|
474 |
{
|
|
|
475 |
bool do_subset = pdf_do_subset_font(pdev, pbfont, rid);
|
|
|
476 |
gs_font_base *out_font =
|
|
|
477 |
(do_subset || pbfont->complete == NULL ? pbfont->copied : pbfont->complete);
|
|
|
478 |
gs_const_string fnstr;
|
|
|
479 |
pdf_data_writer_t writer;
|
|
|
480 |
int code;
|
|
|
481 |
|
|
|
482 |
if (pbfont->written)
|
|
|
483 |
return 0; /* already written */
|
|
|
484 |
code = pdf_begin_data_stream(pdev, &writer, DATA_STREAM_BINARY |
|
|
|
485 |
/* Don't set DATA_STREAM_ENCRYPT since we write to a temporary file.
|
|
|
486 |
See comment in pdf_begin_encrypt. */
|
|
|
487 |
(pdev->CompressFonts ?
|
|
|
488 |
DATA_STREAM_COMPRESS : 0), 0);
|
|
|
489 |
if (code < 0)
|
|
|
490 |
return code;
|
|
|
491 |
if (pdev->CompatibilityLevel == 1.2 &&
|
|
|
492 |
!do_subset && !pbfont->is_standard ) {
|
|
|
493 |
/*
|
|
|
494 |
* Due to a bug in Acrobat Reader 3, we need to generate
|
|
|
495 |
* unique font names, except base 14 fonts being not embedded.
|
|
|
496 |
* To recognize base 14 fonts here we used the knowledge
|
|
|
497 |
* that pbfont->is_standard is true for base 14 fonts only.
|
|
|
498 |
* Note that subsetted fonts already have an unique name
|
|
|
499 |
* due to subset prefix.
|
|
|
500 |
*/
|
|
|
501 |
int code = pdf_adjust_font_name(pdev, writer.pres->object->id, pbfont);
|
|
|
502 |
if (code < 0)
|
|
|
503 |
return code;
|
|
|
504 |
}
|
|
|
505 |
fnstr.data = pbfont->font_name.data;
|
|
|
506 |
fnstr.size = pbfont->font_name.size;
|
|
|
507 |
/* Now write the font (or subset). */
|
|
|
508 |
switch (out_font->FontType) {
|
|
|
509 |
|
|
|
510 |
case ft_composite:
|
|
|
511 |
/* Nothing to embed -- the descendant fonts do it all. */
|
|
|
512 |
code = 0;
|
|
|
513 |
break;
|
|
|
514 |
|
|
|
515 |
case ft_encrypted2:
|
|
|
516 |
if (!pdev->HaveCFF) {
|
|
|
517 |
/* Must convert to Type 1 charstrings. */
|
|
|
518 |
return_error(gs_error_unregistered); /* Not implemented yet. */
|
|
|
519 |
}
|
|
|
520 |
case ft_encrypted:
|
|
|
521 |
if (pdev->HavePDFWidths) {
|
|
|
522 |
code = copied_drop_extension_glyphs((gs_font *)out_font);
|
|
|
523 |
if (code < 0)
|
|
|
524 |
return code;
|
|
|
525 |
}
|
|
|
526 |
if (!pdev->HaveCFF) {
|
|
|
527 |
/* Write the type 1 font with no converting to CFF. */
|
|
|
528 |
int lengths[3];
|
|
|
529 |
|
|
|
530 |
code = psf_write_type1_font(writer.binary.strm,
|
|
|
531 |
(gs_font_type1 *)out_font,
|
|
|
532 |
WRITE_TYPE1_WITH_LENIV |
|
|
|
533 |
WRITE_TYPE1_EEXEC | WRITE_TYPE1_EEXEC_PAD,
|
|
|
534 |
NULL, 0, &fnstr, lengths);
|
|
|
535 |
if (lengths[0] > 0) {
|
|
|
536 |
if (code < 0)
|
|
|
537 |
return code;
|
|
|
538 |
code = cos_dict_put_c_key_int((cos_dict_t *)writer.pres->object,
|
|
|
539 |
"/Length1", lengths[0]);
|
|
|
540 |
}
|
|
|
541 |
if (lengths[1] > 0) {
|
|
|
542 |
if (code < 0)
|
|
|
543 |
return code;
|
|
|
544 |
code = cos_dict_put_c_key_int((cos_dict_t *)writer.pres->object,
|
|
|
545 |
"/Length2", lengths[1]);
|
|
|
546 |
if (code < 0)
|
|
|
547 |
return code;
|
|
|
548 |
code = cos_dict_put_c_key_int((cos_dict_t *)writer.pres->object,
|
|
|
549 |
"/Length3", lengths[2]);
|
|
|
550 |
}
|
|
|
551 |
} else {
|
|
|
552 |
/*
|
|
|
553 |
* Since we only support PDF 1.2 and later, always write Type 1
|
|
|
554 |
* fonts as Type1C (Type 2). Acrobat Reader apparently doesn't
|
|
|
555 |
* accept CFF fonts with Type 1 CharStrings, so we need to convert
|
|
|
556 |
* them. Also remove lenIV, so Type 2 fonts will compress better.
|
|
|
557 |
*/
|
|
|
558 |
#define TYPE2_OPTIONS (WRITE_TYPE2_NO_LENIV | WRITE_TYPE2_CHARSTRINGS)
|
|
|
559 |
code = cos_dict_put_string_copy((cos_dict_t *)writer.pres->object, "/Subtype", "/Type1C");
|
|
|
560 |
if (code < 0)
|
|
|
561 |
return code;
|
|
|
562 |
code = psf_write_type2_font(writer.binary.strm,
|
|
|
563 |
(gs_font_type1 *)out_font,
|
|
|
564 |
TYPE2_OPTIONS |
|
|
|
565 |
(pdev->CompatibilityLevel < 1.3 ? WRITE_TYPE2_AR3 : 0),
|
|
|
566 |
NULL, 0, &fnstr, FontBBox);
|
|
|
567 |
}
|
|
|
568 |
goto finish;
|
|
|
569 |
|
|
|
570 |
case ft_TrueType: {
|
|
|
571 |
gs_font_type42 *const pfont = (gs_font_type42 *)out_font;
|
|
|
572 |
#define TRUETYPE_OPTIONS (WRITE_TRUETYPE_NAME | WRITE_TRUETYPE_HVMTX)
|
|
|
573 |
/* Acrobat Reader 3 doesn't handle cmap format 6 correctly. */
|
|
|
574 |
const int options = TRUETYPE_OPTIONS |
|
|
|
575 |
(pdev->CompatibilityLevel <= 1.2 ?
|
|
|
576 |
WRITE_TRUETYPE_NO_TRIMMED_TABLE : 0) |
|
|
|
577 |
/* Generate a cmap only for incrementally downloaded fonts
|
|
|
578 |
and for subsetted fonts. */
|
|
|
579 |
(pfont->data.numGlyphs != pfont->data.trueNumGlyphs ||
|
|
|
580 |
pbfont->do_subset == DO_SUBSET_YES ?
|
|
|
581 |
WRITE_TRUETYPE_CMAP : 0);
|
|
|
582 |
stream poss;
|
|
|
583 |
|
|
|
584 |
if (pdev->HavePDFWidths) {
|
|
|
585 |
code = copied_drop_extension_glyphs((gs_font *)out_font);
|
|
|
586 |
if (code < 0)
|
|
|
587 |
return code;
|
|
|
588 |
}
|
|
|
589 |
s_init(&poss, pdev->memory);
|
|
|
590 |
swrite_position_only(&poss);
|
|
|
591 |
code = psf_write_truetype_font(&poss, pfont, options, NULL, 0, &fnstr);
|
|
|
592 |
if (code < 0)
|
|
|
593 |
return code;
|
|
|
594 |
code = cos_dict_put_c_key_int((cos_dict_t *)writer.pres->object, "/Length1", stell(&poss));
|
|
|
595 |
if (code < 0)
|
|
|
596 |
return code;
|
|
|
597 |
if (code < 0)
|
|
|
598 |
return code;
|
|
|
599 |
code = psf_write_truetype_font(writer.binary.strm, pfont,
|
|
|
600 |
options, NULL, 0, &fnstr);
|
|
|
601 |
goto finish;
|
|
|
602 |
}
|
|
|
603 |
|
|
|
604 |
case ft_CID_encrypted:
|
|
|
605 |
code = cos_dict_put_string_copy((cos_dict_t *)writer.pres->object, "/Subtype", "/CIDFontType0C");
|
|
|
606 |
if (code < 0)
|
|
|
607 |
return code;
|
|
|
608 |
code = psf_write_cid0_font(writer.binary.strm,
|
|
|
609 |
(gs_font_cid0 *)out_font, TYPE2_OPTIONS,
|
|
|
610 |
NULL, 0, &fnstr);
|
|
|
611 |
goto finish;
|
|
|
612 |
|
|
|
613 |
case ft_CID_TrueType:
|
|
|
614 |
/* CIDFontType 2 fonts don't use cmap, name, OS/2, or post. */
|
|
|
615 |
#define CID2_OPTIONS WRITE_TRUETYPE_HVMTX
|
|
|
616 |
code = psf_write_cid2_font(writer.binary.strm,
|
|
|
617 |
(gs_font_cid2 *)out_font,
|
|
|
618 |
CID2_OPTIONS, NULL, 0, &fnstr);
|
|
|
619 |
finish:
|
|
|
620 |
*ppcd = (cos_dict_t *)writer.pres->object;
|
|
|
621 |
if (code < 0) {
|
|
|
622 |
pdf_end_fontfile(pdev, &writer);
|
|
|
623 |
return code;
|
|
|
624 |
}
|
|
|
625 |
code = pdf_end_fontfile(pdev, &writer);
|
|
|
626 |
break;
|
|
|
627 |
|
|
|
628 |
default:
|
|
|
629 |
code = gs_note_error(gs_error_rangecheck);
|
|
|
630 |
}
|
|
|
631 |
|
|
|
632 |
pbfont->written = true;
|
|
|
633 |
return code;
|
|
|
634 |
}
|
|
|
635 |
|
|
|
636 |
/*
|
|
|
637 |
* Write the CharSet for a subsetted font, as a PDF string.
|
|
|
638 |
*/
|
|
|
639 |
int
|
|
|
640 |
pdf_write_CharSet(gx_device_pdf *pdev, pdf_base_font_t *pbfont)
|
|
|
641 |
{
|
|
|
642 |
stream *s = pdev->strm;
|
|
|
643 |
gs_font_base *font = pbfont->copied;
|
|
|
644 |
int index;
|
|
|
645 |
gs_glyph glyph;
|
|
|
646 |
|
|
|
647 |
stream_puts(s, "(");
|
|
|
648 |
for (index = 0;
|
|
|
649 |
(font->procs.enumerate_glyph((gs_font *)font, &index,
|
|
|
650 |
GLYPH_SPACE_NAME, &glyph),
|
|
|
651 |
index != 0);
|
|
|
652 |
) {
|
|
|
653 |
gs_const_string gstr;
|
|
|
654 |
int code = font->procs.glyph_name((gs_font *)font, glyph, &gstr);
|
|
|
655 |
|
|
|
656 |
/* Don't include .notdef. */
|
|
|
657 |
if (code >= 0 &&
|
|
|
658 |
bytes_compare(gstr.data, gstr.size, (const byte *)".notdef", 7)
|
|
|
659 |
)
|
|
|
660 |
pdf_put_name(pdev, gstr.data, gstr.size);
|
|
|
661 |
}
|
|
|
662 |
stream_puts(s, ")");
|
|
|
663 |
return 0;
|
|
|
664 |
}
|
|
|
665 |
|
|
|
666 |
/*
|
|
|
667 |
* Write the CIDSet object for a subsetted CIDFont.
|
|
|
668 |
*/
|
|
|
669 |
int
|
|
|
670 |
pdf_write_CIDSet(gx_device_pdf *pdev, pdf_base_font_t *pbfont,
|
|
|
671 |
long *pcidset_id)
|
|
|
672 |
{
|
|
|
673 |
pdf_data_writer_t writer;
|
|
|
674 |
int code;
|
|
|
675 |
|
|
|
676 |
code = pdf_begin_data_stream(pdev, &writer,
|
|
|
677 |
DATA_STREAM_BINARY |
|
|
|
678 |
(pdev->CompressFonts ? DATA_STREAM_COMPRESS : 0),
|
|
|
679 |
gs_no_id);
|
|
|
680 |
if (code < 0)
|
|
|
681 |
return code;
|
|
|
682 |
stream_write(writer.binary.strm, pbfont->CIDSet,
|
|
|
683 |
(pbfont->num_glyphs + 7) / 8);
|
|
|
684 |
code = pdf_end_data(&writer);
|
|
|
685 |
if (code < 0)
|
|
|
686 |
return code;
|
|
|
687 |
*pcidset_id = pdf_resource_id(writer.pres);
|
|
|
688 |
return 0;
|
|
|
689 |
}
|
|
|
690 |
/*
|
|
|
691 |
* Check whether a base font is standard.
|
|
|
692 |
*/
|
|
|
693 |
bool
|
|
|
694 |
pdf_is_standard_font(pdf_base_font_t *bfont)
|
|
|
695 |
{ return bfont->is_standard;
|
|
|
696 |
}
|
|
|
697 |
|
|
|
698 |
void
|
|
|
699 |
pdf_set_FontFile_object(pdf_base_font_t *bfont, cos_dict_t *pcd)
|
|
|
700 |
{
|
|
|
701 |
bfont->FontFile = pcd;
|
|
|
702 |
}
|
|
|
703 |
const cos_dict_t *
|
|
|
704 |
pdf_get_FontFile_object(pdf_base_font_t *bfont)
|
|
|
705 |
{
|
|
|
706 |
return bfont->FontFile;
|
|
|
707 |
}
|