1*593dc095SDavid du Colombier /* Copyright (C) 2002 Aladdin Enterprises. All rights reserved.
2*593dc095SDavid du Colombier
3*593dc095SDavid du Colombier This software is provided AS-IS with no warranty, either express or
4*593dc095SDavid du Colombier implied.
5*593dc095SDavid du Colombier
6*593dc095SDavid du Colombier This software is distributed under license and may not be copied,
7*593dc095SDavid du Colombier modified or distributed except as expressly authorized under the terms
8*593dc095SDavid du Colombier of the license contained in the file LICENSE in this distribution.
9*593dc095SDavid du Colombier
10*593dc095SDavid du Colombier For more information about licensing, please refer to
11*593dc095SDavid du Colombier http://www.ghostscript.com/licensing/. For information on
12*593dc095SDavid du Colombier commercial licensing, go to http://www.artifex.com/licensing/ or
13*593dc095SDavid du Colombier contact Artifex Software, Inc., 101 Lucas Valley Road #110,
14*593dc095SDavid du Colombier San Rafael, CA 94903, U.S.A., +1(415)492-9861.
15*593dc095SDavid du Colombier */
16*593dc095SDavid du Colombier
17*593dc095SDavid du Colombier /* $Id: gdevpdtw.c,v 1.44 2005/06/06 15:32:22 igor Exp $ */
18*593dc095SDavid du Colombier /* Font resource writing for pdfwrite text */
19*593dc095SDavid du Colombier #include "memory_.h"
20*593dc095SDavid du Colombier #include "gx.h"
21*593dc095SDavid du Colombier #include "gserrors.h"
22*593dc095SDavid du Colombier #include "gxfcmap.h"
23*593dc095SDavid du Colombier #include "gxfont.h"
24*593dc095SDavid du Colombier #include "gscencs.h"
25*593dc095SDavid du Colombier #include "gdevpsf.h"
26*593dc095SDavid du Colombier #include "gdevpdfx.h"
27*593dc095SDavid du Colombier #include "gdevpdfo.h" /* for object->written */
28*593dc095SDavid du Colombier #include "gdevpdtd.h" /* for writing FontDescriptor */
29*593dc095SDavid du Colombier #include "gdevpdtf.h"
30*593dc095SDavid du Colombier #include "gdevpdti.h" /* for writing bitmap fonts Encoding */
31*593dc095SDavid du Colombier #include "gdevpdtw.h"
32*593dc095SDavid du Colombier #include "gdevpdtv.h"
33*593dc095SDavid du Colombier #include "sarc4.h"
34*593dc095SDavid du Colombier
35*593dc095SDavid du Colombier private const char *const encoding_names[] = {
36*593dc095SDavid du Colombier KNOWN_REAL_ENCODING_NAMES
37*593dc095SDavid du Colombier };
38*593dc095SDavid du Colombier
39*593dc095SDavid du Colombier /* ================ Font resource writing ================ */
40*593dc095SDavid du Colombier
41*593dc095SDavid du Colombier /* ---------------- Private ---------------- */
42*593dc095SDavid du Colombier
43*593dc095SDavid du Colombier /* Write the Widths for a font. */
44*593dc095SDavid du Colombier private int
pdf_write_Widths(gx_device_pdf * pdev,int first,int last,const double * widths)45*593dc095SDavid du Colombier pdf_write_Widths(gx_device_pdf *pdev, int first, int last, const double *widths)
46*593dc095SDavid du Colombier {
47*593dc095SDavid du Colombier stream *s = pdev->strm;
48*593dc095SDavid du Colombier int i;
49*593dc095SDavid du Colombier
50*593dc095SDavid du Colombier if (first > last)
51*593dc095SDavid du Colombier first = last = 0;
52*593dc095SDavid du Colombier pprintd2(s, "/FirstChar %d/LastChar %d/Widths[", first, last);
53*593dc095SDavid du Colombier for (i = first; i <= last; ++i)
54*593dc095SDavid du Colombier pprintg1(s, (i & 15 ? " %g" : "\n%g"), psdf_round(widths[i], 100, 10));
55*593dc095SDavid du Colombier stream_puts(s, "]\n");
56*593dc095SDavid du Colombier return 0;
57*593dc095SDavid du Colombier }
58*593dc095SDavid du Colombier
59*593dc095SDavid du Colombier /* Check strings equality. */
60*593dc095SDavid du Colombier private bool
strings_equal(const gs_const_string * str0,const gs_const_string * str1)61*593dc095SDavid du Colombier strings_equal(const gs_const_string *str0, const gs_const_string *str1)
62*593dc095SDavid du Colombier {
63*593dc095SDavid du Colombier return str0->size == str1->size &&
64*593dc095SDavid du Colombier !memcmp(str0->data, str1->data, str0->size);
65*593dc095SDavid du Colombier }
66*593dc095SDavid du Colombier
67*593dc095SDavid du Colombier /* Check if an encoding element differs from a standard one. */
68*593dc095SDavid du Colombier private int
pdf_different_encoding_element(const pdf_font_resource_t * pdfont,int ch,int encoding_index)69*593dc095SDavid du Colombier pdf_different_encoding_element(const pdf_font_resource_t *pdfont, int ch, int encoding_index)
70*593dc095SDavid du Colombier {
71*593dc095SDavid du Colombier if (pdfont->u.simple.Encoding[ch].is_difference)
72*593dc095SDavid du Colombier return 1;
73*593dc095SDavid du Colombier else if (encoding_index != ENCODING_INDEX_UNKNOWN) {
74*593dc095SDavid du Colombier gs_glyph glyph0 = gs_c_known_encode(ch, encoding_index);
75*593dc095SDavid du Colombier gs_glyph glyph1 = pdfont->u.simple.Encoding[ch].glyph;
76*593dc095SDavid du Colombier gs_const_string str;
77*593dc095SDavid du Colombier int code = gs_c_glyph_name(glyph0, &str);
78*593dc095SDavid du Colombier
79*593dc095SDavid du Colombier if (code < 0)
80*593dc095SDavid du Colombier return code; /* Must not happen */
81*593dc095SDavid du Colombier if (glyph1 != GS_NO_GLYPH)
82*593dc095SDavid du Colombier if (!strings_equal(&str, &pdfont->u.simple.Encoding[ch].str))
83*593dc095SDavid du Colombier return 1;
84*593dc095SDavid du Colombier }
85*593dc095SDavid du Colombier return 0;
86*593dc095SDavid du Colombier }
87*593dc095SDavid du Colombier
88*593dc095SDavid du Colombier /* Find an index of a different encoding element. */
89*593dc095SDavid du Colombier int
pdf_different_encoding_index(const pdf_font_resource_t * pdfont,int ch0)90*593dc095SDavid du Colombier pdf_different_encoding_index(const pdf_font_resource_t *pdfont, int ch0)
91*593dc095SDavid du Colombier {
92*593dc095SDavid du Colombier gs_encoding_index_t base_encoding = pdfont->u.simple.BaseEncoding;
93*593dc095SDavid du Colombier int ch, code;
94*593dc095SDavid du Colombier
95*593dc095SDavid du Colombier for (ch = ch0; ch < 256; ++ch) {
96*593dc095SDavid du Colombier code = pdf_different_encoding_element(pdfont, ch, base_encoding);
97*593dc095SDavid du Colombier if (code < 0)
98*593dc095SDavid du Colombier return code; /* Must not happen */
99*593dc095SDavid du Colombier if (code)
100*593dc095SDavid du Colombier break;
101*593dc095SDavid du Colombier }
102*593dc095SDavid du Colombier return ch;
103*593dc095SDavid du Colombier }
104*593dc095SDavid du Colombier
105*593dc095SDavid du Colombier /* Check for unknown encode (simple fonts only). */
106*593dc095SDavid du Colombier private bool
pdf_simple_font_needs_ToUnicode(const pdf_font_resource_t * pdfont)107*593dc095SDavid du Colombier pdf_simple_font_needs_ToUnicode(const pdf_font_resource_t *pdfont)
108*593dc095SDavid du Colombier {
109*593dc095SDavid du Colombier int ch;
110*593dc095SDavid du Colombier unsigned char mask = (pdfont->FontType == ft_encrypted || pdfont->FontType == ft_encrypted2
111*593dc095SDavid du Colombier ? GS_C_PDF_GOOD_GLYPH_MASK : GS_C_PDF_GOOD_NON_SYMBOL_MASK);
112*593dc095SDavid du Colombier
113*593dc095SDavid du Colombier if (pdfont->u.simple.Encoding == NULL)
114*593dc095SDavid du Colombier return true; /* Bitmap Type 3 fonts have no pdfont->u.simple.Encoding . */
115*593dc095SDavid du Colombier for (ch = 0; ch < 256; ++ch) {
116*593dc095SDavid du Colombier pdf_encoding_element_t *pet = &pdfont->u.simple.Encoding[ch];
117*593dc095SDavid du Colombier gs_glyph glyph = pet->glyph;
118*593dc095SDavid du Colombier
119*593dc095SDavid du Colombier if (glyph == GS_NO_GLYPH)
120*593dc095SDavid du Colombier continue;
121*593dc095SDavid du Colombier if (glyph < gs_c_min_std_encoding_glyph || glyph >= GS_MIN_CID_GLYPH) {
122*593dc095SDavid du Colombier if (pet->str.size == 0)
123*593dc095SDavid du Colombier return true;
124*593dc095SDavid du Colombier glyph = gs_c_name_glyph(pet->str.data, pet->str.size);
125*593dc095SDavid du Colombier if (glyph == GS_NO_GLYPH)
126*593dc095SDavid du Colombier return true;
127*593dc095SDavid du Colombier }
128*593dc095SDavid du Colombier glyph -= gs_c_min_std_encoding_glyph;
129*593dc095SDavid du Colombier if( glyph > GS_C_PDF_MAX_GOOD_GLYPH ||
130*593dc095SDavid du Colombier !(gs_c_pdf_glyph_type[glyph >> 2] & (mask << (( glyph & 3 )<<1) )))
131*593dc095SDavid du Colombier return true;
132*593dc095SDavid du Colombier }
133*593dc095SDavid du Colombier return false;
134*593dc095SDavid du Colombier }
135*593dc095SDavid du Colombier
136*593dc095SDavid du Colombier /* Write Encoding differencrs. */
137*593dc095SDavid du Colombier int
pdf_write_encoding(gx_device_pdf * pdev,const pdf_font_resource_t * pdfont,long id,int ch)138*593dc095SDavid du Colombier pdf_write_encoding(gx_device_pdf *pdev, const pdf_font_resource_t *pdfont, long id, int ch)
139*593dc095SDavid du Colombier {
140*593dc095SDavid du Colombier /* Note : this truncates extended glyph names to original names. */
141*593dc095SDavid du Colombier stream *s;
142*593dc095SDavid du Colombier gs_encoding_index_t base_encoding = pdfont->u.simple.BaseEncoding;
143*593dc095SDavid du Colombier const int sl = strlen(gx_extendeg_glyph_name_separator);
144*593dc095SDavid du Colombier int prev = 256, code;
145*593dc095SDavid du Colombier
146*593dc095SDavid du Colombier pdf_open_separate(pdev, id);
147*593dc095SDavid du Colombier s = pdev->strm;
148*593dc095SDavid du Colombier stream_puts(s, "<</Type/Encoding");
149*593dc095SDavid du Colombier if (base_encoding < 0 && pdev->ForOPDFRead)
150*593dc095SDavid du Colombier base_encoding = ENCODING_INDEX_STANDARD;
151*593dc095SDavid du Colombier if (base_encoding > 0)
152*593dc095SDavid du Colombier pprints1(s, "/BaseEncoding/%s", encoding_names[base_encoding]);
153*593dc095SDavid du Colombier stream_puts(s, "/Differences[");
154*593dc095SDavid du Colombier for (; ch < 256; ++ch) {
155*593dc095SDavid du Colombier code = pdf_different_encoding_element(pdfont, ch, base_encoding);
156*593dc095SDavid du Colombier if (code < 0)
157*593dc095SDavid du Colombier return code; /* Must not happen */
158*593dc095SDavid du Colombier if (code == 0 && pdfont->FontType == ft_user_defined) {
159*593dc095SDavid du Colombier /* PDF 1.4 spec Appendix H Note 42 says that
160*593dc095SDavid du Colombier * Acrobat 4 can't properly handle Base Encoding.
161*593dc095SDavid du Colombier * Enforce writing differences against that.
162*593dc095SDavid du Colombier */
163*593dc095SDavid du Colombier if (pdfont->used[ch >> 3] & 0x80 >> (ch & 7))
164*593dc095SDavid du Colombier if (pdfont->u.simple.Encoding[ch].str.size)
165*593dc095SDavid du Colombier code = 1;
166*593dc095SDavid du Colombier }
167*593dc095SDavid du Colombier if (code) {
168*593dc095SDavid du Colombier const byte *d = pdfont->u.simple.Encoding[ch].str.data;
169*593dc095SDavid du Colombier int i, l = pdfont->u.simple.Encoding[ch].str.size;
170*593dc095SDavid du Colombier
171*593dc095SDavid du Colombier if (pdev->HavePDFWidths) {
172*593dc095SDavid du Colombier for (i = 0; i + sl < l; i++)
173*593dc095SDavid du Colombier if (!memcmp(d + i, gx_extendeg_glyph_name_separator, sl)) {
174*593dc095SDavid du Colombier l = i;
175*593dc095SDavid du Colombier break;
176*593dc095SDavid du Colombier }
177*593dc095SDavid du Colombier }
178*593dc095SDavid du Colombier if (ch != prev + 1)
179*593dc095SDavid du Colombier pprintd1(s, "\n%d", ch);
180*593dc095SDavid du Colombier pdf_put_name(pdev, d, l);
181*593dc095SDavid du Colombier prev = ch;
182*593dc095SDavid du Colombier }
183*593dc095SDavid du Colombier }
184*593dc095SDavid du Colombier stream_puts(s, "]>>\n");
185*593dc095SDavid du Colombier pdf_end_separate(pdev);
186*593dc095SDavid du Colombier return 0;
187*593dc095SDavid du Colombier }
188*593dc095SDavid du Colombier
189*593dc095SDavid du Colombier /* Write Encoding reference. */
190*593dc095SDavid du Colombier int
pdf_write_encoding_ref(gx_device_pdf * pdev,const pdf_font_resource_t * pdfont,long id)191*593dc095SDavid du Colombier pdf_write_encoding_ref(gx_device_pdf *pdev,
192*593dc095SDavid du Colombier const pdf_font_resource_t *pdfont, long id)
193*593dc095SDavid du Colombier {
194*593dc095SDavid du Colombier stream *s = pdev->strm;
195*593dc095SDavid du Colombier
196*593dc095SDavid du Colombier if (id != 0)
197*593dc095SDavid du Colombier pprintld1(s, "/Encoding %ld 0 R", id);
198*593dc095SDavid du Colombier else if (pdfont->u.simple.BaseEncoding > 0) {
199*593dc095SDavid du Colombier gs_encoding_index_t base_encoding = pdfont->u.simple.BaseEncoding;
200*593dc095SDavid du Colombier pprints1(s, "/Encoding/%s", encoding_names[base_encoding]);
201*593dc095SDavid du Colombier }
202*593dc095SDavid du Colombier return 0;
203*593dc095SDavid du Colombier }
204*593dc095SDavid du Colombier
205*593dc095SDavid du Colombier /* Write the Subtype and Encoding for a simple font. */
206*593dc095SDavid du Colombier private int
pdf_write_simple_contents(gx_device_pdf * pdev,const pdf_font_resource_t * pdfont)207*593dc095SDavid du Colombier pdf_write_simple_contents(gx_device_pdf *pdev,
208*593dc095SDavid du Colombier const pdf_font_resource_t *pdfont)
209*593dc095SDavid du Colombier {
210*593dc095SDavid du Colombier stream *s = pdev->strm;
211*593dc095SDavid du Colombier long diff_id = 0;
212*593dc095SDavid du Colombier int ch = (pdfont->u.simple.Encoding ? 0 : 256);
213*593dc095SDavid du Colombier int code = 0;
214*593dc095SDavid du Colombier
215*593dc095SDavid du Colombier ch = pdf_different_encoding_index(pdfont, ch);
216*593dc095SDavid du Colombier if (ch < 256)
217*593dc095SDavid du Colombier diff_id = pdf_obj_ref(pdev);
218*593dc095SDavid du Colombier code = pdf_write_encoding_ref(pdev, pdfont, diff_id);
219*593dc095SDavid du Colombier if (code < 0)
220*593dc095SDavid du Colombier return code;
221*593dc095SDavid du Colombier pprints1(s, "/Subtype/%s>>\n",
222*593dc095SDavid du Colombier (pdfont->FontType == ft_TrueType ? "TrueType" :
223*593dc095SDavid du Colombier pdfont->u.simple.s.type1.is_MM_instance ? "MMType1" : "Type1"));
224*593dc095SDavid du Colombier pdf_end_separate(pdev);
225*593dc095SDavid du Colombier if (diff_id) {
226*593dc095SDavid du Colombier code = pdf_write_encoding(pdev, pdfont, diff_id, ch);
227*593dc095SDavid du Colombier if (code < 0)
228*593dc095SDavid du Colombier return code;
229*593dc095SDavid du Colombier }
230*593dc095SDavid du Colombier return 0;
231*593dc095SDavid du Colombier }
232*593dc095SDavid du Colombier
233*593dc095SDavid du Colombier /*
234*593dc095SDavid du Colombier * Write the W[2] entries for a CIDFont. *pdfont is known to be a
235*593dc095SDavid du Colombier * CIDFont (type 0 or 2).
236*593dc095SDavid du Colombier */
237*593dc095SDavid du Colombier private bool
pdf_compute_CIDFont_default_widths(const pdf_font_resource_t * pdfont,int wmode,int * pdw,int * pdv)238*593dc095SDavid du Colombier pdf_compute_CIDFont_default_widths(const pdf_font_resource_t *pdfont, int wmode, int *pdw, int *pdv)
239*593dc095SDavid du Colombier {
240*593dc095SDavid du Colombier psf_glyph_enum_t genum;
241*593dc095SDavid du Colombier gs_glyph glyph;
242*593dc095SDavid du Colombier ushort counts[1500]; /* Some CID fonts use vertical widths 1026 .*/
243*593dc095SDavid du Colombier int dw_count = 0, i, dwi = 0, neg_count = 0, pos_count = 0;
244*593dc095SDavid du Colombier double *w = (wmode ? pdfont->u.cidfont.Widths2 : pdfont->Widths);
245*593dc095SDavid du Colombier
246*593dc095SDavid du Colombier /* We don't wont to scan for both negative and positive widths,
247*593dc095SDavid du Colombier * to save the C stack space.
248*593dc095SDavid du Colombier * Doubtly they both are used in same font.
249*593dc095SDavid du Colombier * So just count positive and negative widths separately
250*593dc095SDavid du Colombier * and use the corresponding sign.
251*593dc095SDavid du Colombier * fixme : implement 2 hystograms.
252*593dc095SDavid du Colombier */
253*593dc095SDavid du Colombier psf_enumerate_bits_begin(&genum, NULL,
254*593dc095SDavid du Colombier wmode ? pdfont->u.cidfont.used2 : pdfont->used,
255*593dc095SDavid du Colombier pdfont->count, GLYPH_SPACE_INDEX);
256*593dc095SDavid du Colombier memset(counts, 0, sizeof(counts));
257*593dc095SDavid du Colombier while (!psf_enumerate_glyphs_next(&genum, &glyph)) {
258*593dc095SDavid du Colombier int i = glyph - GS_MIN_CID_GLYPH;
259*593dc095SDavid du Colombier
260*593dc095SDavid du Colombier if ( i < pdfont->count) { /* safety */
261*593dc095SDavid du Colombier int width = (int)(w[i] + 0.5);
262*593dc095SDavid du Colombier
263*593dc095SDavid du Colombier counts[min(any_abs(width), countof(counts) - 1)]++;
264*593dc095SDavid du Colombier if (width > 0)
265*593dc095SDavid du Colombier pos_count++;
266*593dc095SDavid du Colombier else if (width < 0)
267*593dc095SDavid du Colombier neg_count++;
268*593dc095SDavid du Colombier }
269*593dc095SDavid du Colombier }
270*593dc095SDavid du Colombier for (i = 1; i < countof(counts); ++i)
271*593dc095SDavid du Colombier if (counts[i] > dw_count)
272*593dc095SDavid du Colombier dwi = i, dw_count = counts[i];
273*593dc095SDavid du Colombier *pdw = (neg_count > pos_count ? -dwi : dwi);
274*593dc095SDavid du Colombier *pdv = 0;
275*593dc095SDavid du Colombier if (wmode) {
276*593dc095SDavid du Colombier psf_enumerate_glyphs_reset(&genum);
277*593dc095SDavid du Colombier while (!psf_enumerate_glyphs_next(&genum, &glyph)) {
278*593dc095SDavid du Colombier int i = glyph - GS_MIN_CID_GLYPH;
279*593dc095SDavid du Colombier
280*593dc095SDavid du Colombier if ( i < pdfont->count) { /* safety */
281*593dc095SDavid du Colombier int width = (int)(w[i] + 0.5);
282*593dc095SDavid du Colombier
283*593dc095SDavid du Colombier if (min(any_abs(width), countof(counts) - 1) == any_abs(dwi)) {
284*593dc095SDavid du Colombier *pdv = (int)(pdfont->u.cidfont.v[i * 2 + 1] + 0.5);
285*593dc095SDavid du Colombier break;
286*593dc095SDavid du Colombier }
287*593dc095SDavid du Colombier }
288*593dc095SDavid du Colombier }
289*593dc095SDavid du Colombier }
290*593dc095SDavid du Colombier return (dw_count + counts[0] > 0);
291*593dc095SDavid du Colombier }
292*593dc095SDavid du Colombier
293*593dc095SDavid du Colombier /*
294*593dc095SDavid du Colombier * Write the [D]W[2] entries for a CIDFont. *pdfont is known to be a
295*593dc095SDavid du Colombier * CIDFont (type 0 or 2).
296*593dc095SDavid du Colombier */
297*593dc095SDavid du Colombier private int
pdf_write_CIDFont_widths(gx_device_pdf * pdev,const pdf_font_resource_t * pdfont,int wmode)298*593dc095SDavid du Colombier pdf_write_CIDFont_widths(gx_device_pdf *pdev,
299*593dc095SDavid du Colombier const pdf_font_resource_t *pdfont, int wmode)
300*593dc095SDavid du Colombier {
301*593dc095SDavid du Colombier /*
302*593dc095SDavid du Colombier * The values of the CIDFont width keys are as follows:
303*593dc095SDavid du Colombier * DW = w (default 0)
304*593dc095SDavid du Colombier * W = [{c [w ...] | cfirst clast w}*]
305*593dc095SDavid du Colombier * DW2 = [vy w1y] (default [880 -1000])
306*593dc095SDavid du Colombier * W2 = [{c [w1y vx vy ...] | cfirst clast w1y vx vy}*]
307*593dc095SDavid du Colombier */
308*593dc095SDavid du Colombier stream *s = pdev->strm;
309*593dc095SDavid du Colombier psf_glyph_enum_t genum;
310*593dc095SDavid du Colombier gs_glyph glyph;
311*593dc095SDavid du Colombier int dw = 0, dv = 0, prev = -2;
312*593dc095SDavid du Colombier const char *Widths_key = (wmode ? "/W2" : "/W");
313*593dc095SDavid du Colombier double *w = (wmode ? pdfont->u.cidfont.Widths2 : pdfont->Widths);
314*593dc095SDavid du Colombier
315*593dc095SDavid du Colombier /* Compute and write default width : */
316*593dc095SDavid du Colombier if (pdf_compute_CIDFont_default_widths(pdfont, wmode, &dw, &dv)) {
317*593dc095SDavid du Colombier if (wmode) {
318*593dc095SDavid du Colombier pprintd2(s, "/DW2 [%d %d]\n", dv, dw);
319*593dc095SDavid du Colombier } else
320*593dc095SDavid du Colombier pprintd1(s, "/DW %d\n", dw);
321*593dc095SDavid du Colombier }
322*593dc095SDavid du Colombier
323*593dc095SDavid du Colombier /*
324*593dc095SDavid du Colombier * Now write all widths different from the default one. Currently we make no
325*593dc095SDavid du Colombier * attempt to optimize this: we write every width individually.
326*593dc095SDavid du Colombier */
327*593dc095SDavid du Colombier psf_enumerate_bits_begin(&genum, NULL,
328*593dc095SDavid du Colombier wmode ? pdfont->u.cidfont.used2 : pdfont->used,
329*593dc095SDavid du Colombier pdfont->count, GLYPH_SPACE_INDEX);
330*593dc095SDavid du Colombier {
331*593dc095SDavid du Colombier while (!psf_enumerate_glyphs_next(&genum, &glyph)) {
332*593dc095SDavid du Colombier int cid = glyph - GS_MIN_CID_GLYPH;
333*593dc095SDavid du Colombier int width = (int)(w[cid] + 0.5);
334*593dc095SDavid du Colombier
335*593dc095SDavid du Colombier #if 0 /* Must write zero widths - see test file of the bug Bug 687681.
336*593dc095SDavid du Colombier We don't enumerate unused glyphs here due to pdfont->used. */
337*593dc095SDavid du Colombier if (width == 0)
338*593dc095SDavid du Colombier continue; /* Don't write for unused glyphs. */
339*593dc095SDavid du Colombier #else
340*593dc095SDavid du Colombier { /* Check whether copied font really have this glyph.
341*593dc095SDavid du Colombier debugged with 401-01.ps, which uses undefined CIDs. */
342*593dc095SDavid du Colombier gs_font_base *pfont = pdf_font_resource_font(pdfont, false);
343*593dc095SDavid du Colombier gs_glyph_info_t info;
344*593dc095SDavid du Colombier
345*593dc095SDavid du Colombier if (pdfont != NULL) {
346*593dc095SDavid du Colombier if (pfont->procs.glyph_info((gs_font *)pfont, glyph, NULL, 0, &info) < 0)
347*593dc095SDavid du Colombier continue;
348*593dc095SDavid du Colombier }
349*593dc095SDavid du Colombier }
350*593dc095SDavid du Colombier #endif
351*593dc095SDavid du Colombier if (cid == prev + 1) {
352*593dc095SDavid du Colombier if (wmode) {
353*593dc095SDavid du Colombier int vx = (int)(pdfont->u.cidfont.v[cid * 2 + 0] + 0.5);
354*593dc095SDavid du Colombier int vy = (int)(pdfont->u.cidfont.v[cid * 2 + 1] + 0.5);
355*593dc095SDavid du Colombier
356*593dc095SDavid du Colombier pprintd3(s, "\n%d %d %d", width, vx, vy);
357*593dc095SDavid du Colombier } else
358*593dc095SDavid du Colombier pprintd1(s, "\n%d", width);
359*593dc095SDavid du Colombier } else if (width == dw &&
360*593dc095SDavid du Colombier (!wmode || (int)(pdfont->u.cidfont.v[cid * 2 + 0] + 0.5) ==
361*593dc095SDavid du Colombier (int)(pdfont->Widths[cid] / 2 + 0.5)) &&
362*593dc095SDavid du Colombier (!wmode || (int)(pdfont->u.cidfont.v[cid * 2 + 1] + 0.5) == dv))
363*593dc095SDavid du Colombier continue;
364*593dc095SDavid du Colombier else {
365*593dc095SDavid du Colombier if (prev >= 0)
366*593dc095SDavid du Colombier stream_puts(s, "]\n");
367*593dc095SDavid du Colombier else {
368*593dc095SDavid du Colombier stream_puts(s, Widths_key);
369*593dc095SDavid du Colombier stream_puts(s, "[");
370*593dc095SDavid du Colombier }
371*593dc095SDavid du Colombier if (wmode) {
372*593dc095SDavid du Colombier int vx = (int)(pdfont->u.cidfont.v[cid * 2 + 0] + 0.5);
373*593dc095SDavid du Colombier int vy = (int)(pdfont->u.cidfont.v[cid * 2 + 1] + 0.5);
374*593dc095SDavid du Colombier
375*593dc095SDavid du Colombier pprintd4(s, "%d[%d %d %d", cid, width, vx, vy);
376*593dc095SDavid du Colombier } else
377*593dc095SDavid du Colombier pprintd2(s, "%d[%d", cid, width);
378*593dc095SDavid du Colombier }
379*593dc095SDavid du Colombier prev = cid;
380*593dc095SDavid du Colombier }
381*593dc095SDavid du Colombier if (prev >= 0)
382*593dc095SDavid du Colombier stream_puts(s, "]]\n");
383*593dc095SDavid du Colombier }
384*593dc095SDavid du Colombier
385*593dc095SDavid du Colombier return 0;
386*593dc095SDavid du Colombier }
387*593dc095SDavid du Colombier
388*593dc095SDavid du Colombier /* ---------------- Specific FontTypes ---------------- */
389*593dc095SDavid du Colombier
390*593dc095SDavid du Colombier /* Write the contents of a Type 0 font resource. */
391*593dc095SDavid du Colombier int
pdf_write_contents_type0(gx_device_pdf * pdev,pdf_font_resource_t * pdfont)392*593dc095SDavid du Colombier pdf_write_contents_type0(gx_device_pdf *pdev, pdf_font_resource_t *pdfont)
393*593dc095SDavid du Colombier {
394*593dc095SDavid du Colombier stream *s = pdev->strm;
395*593dc095SDavid du Colombier
396*593dc095SDavid du Colombier /*
397*593dc095SDavid du Colombier * The Encoding name might be missing if an error occurred when
398*593dc095SDavid du Colombier * creating the font resource.
399*593dc095SDavid du Colombier */
400*593dc095SDavid du Colombier if (pdfont->u.type0.Encoding_name[0])
401*593dc095SDavid du Colombier pprints1(s, "/Encoding %s", pdfont->u.type0.Encoding_name);
402*593dc095SDavid du Colombier pprintld1(s, "/DescendantFonts[%ld 0 R]",
403*593dc095SDavid du Colombier pdf_font_id(pdfont->u.type0.DescendantFont));
404*593dc095SDavid du Colombier stream_puts(s, "/Subtype/Type0>>\n");
405*593dc095SDavid du Colombier pdf_end_separate(pdev);
406*593dc095SDavid du Colombier return 0;
407*593dc095SDavid du Colombier }
408*593dc095SDavid du Colombier
409*593dc095SDavid du Colombier /*
410*593dc095SDavid du Colombier * Finish writing the contents of a Type 3 font resource (FontBBox, Widths,
411*593dc095SDavid du Colombier * Subtype).
412*593dc095SDavid du Colombier */
413*593dc095SDavid du Colombier int
pdf_finish_write_contents_type3(gx_device_pdf * pdev,pdf_font_resource_t * pdfont)414*593dc095SDavid du Colombier pdf_finish_write_contents_type3(gx_device_pdf *pdev,
415*593dc095SDavid du Colombier pdf_font_resource_t *pdfont)
416*593dc095SDavid du Colombier {
417*593dc095SDavid du Colombier stream *s = pdev->strm;
418*593dc095SDavid du Colombier
419*593dc095SDavid du Colombier pdf_write_font_bbox(pdev, &pdfont->u.simple.s.type3.FontBBox);
420*593dc095SDavid du Colombier pdf_write_Widths(pdev, pdfont->u.simple.FirstChar,
421*593dc095SDavid du Colombier pdfont->u.simple.LastChar, pdfont->Widths);
422*593dc095SDavid du Colombier stream_puts(s, "/Subtype/Type3>>\n");
423*593dc095SDavid du Colombier pdf_end_separate(pdev);
424*593dc095SDavid du Colombier return 0;
425*593dc095SDavid du Colombier }
426*593dc095SDavid du Colombier
427*593dc095SDavid du Colombier /* Write the contents of a standard (base 14) font resource. */
428*593dc095SDavid du Colombier int
pdf_write_contents_std(gx_device_pdf * pdev,pdf_font_resource_t * pdfont)429*593dc095SDavid du Colombier pdf_write_contents_std(gx_device_pdf *pdev, pdf_font_resource_t *pdfont)
430*593dc095SDavid du Colombier {
431*593dc095SDavid du Colombier return pdf_write_simple_contents(pdev, pdfont);
432*593dc095SDavid du Colombier }
433*593dc095SDavid du Colombier
434*593dc095SDavid du Colombier /* Write the contents of a simple (Type 1 or Type 42) font resource. */
435*593dc095SDavid du Colombier int
pdf_write_contents_simple(gx_device_pdf * pdev,pdf_font_resource_t * pdfont)436*593dc095SDavid du Colombier pdf_write_contents_simple(gx_device_pdf *pdev, pdf_font_resource_t *pdfont)
437*593dc095SDavid du Colombier {
438*593dc095SDavid du Colombier pdf_write_Widths(pdev, pdfont->u.simple.FirstChar,
439*593dc095SDavid du Colombier pdfont->u.simple.LastChar, pdfont->Widths);
440*593dc095SDavid du Colombier return pdf_write_simple_contents(pdev, pdfont);
441*593dc095SDavid du Colombier }
442*593dc095SDavid du Colombier
443*593dc095SDavid du Colombier /* Write the contents of a CIDFont resource. */
444*593dc095SDavid du Colombier private int
write_contents_cid_common(gx_device_pdf * pdev,pdf_font_resource_t * pdfont,int subtype)445*593dc095SDavid du Colombier write_contents_cid_common(gx_device_pdf *pdev, pdf_font_resource_t *pdfont,
446*593dc095SDavid du Colombier int subtype)
447*593dc095SDavid du Colombier {
448*593dc095SDavid du Colombier /* Write [D]W[2], CIDSystemInfo, and Subtype, and close the object. */
449*593dc095SDavid du Colombier stream *s = pdev->strm;
450*593dc095SDavid du Colombier int code;
451*593dc095SDavid du Colombier
452*593dc095SDavid du Colombier if (pdfont->Widths != 0) {
453*593dc095SDavid du Colombier code = pdf_write_CIDFont_widths(pdev, pdfont, 0);
454*593dc095SDavid du Colombier if (code < 0)
455*593dc095SDavid du Colombier return code;
456*593dc095SDavid du Colombier } else {
457*593dc095SDavid du Colombier /* With a vertical font, the viewer uses /DW
458*593dc095SDavid du Colombier to determine glyph width to compute its v-vector. */
459*593dc095SDavid du Colombier stream_puts(s, "/DW 0\n");
460*593dc095SDavid du Colombier }
461*593dc095SDavid du Colombier if (pdfont->u.cidfont.Widths2 != 0) {
462*593dc095SDavid du Colombier code = pdf_write_CIDFont_widths(pdev, pdfont, 1);
463*593dc095SDavid du Colombier if (code < 0)
464*593dc095SDavid du Colombier return code;
465*593dc095SDavid du Colombier }
466*593dc095SDavid du Colombier if (pdfont->u.cidfont.CIDSystemInfo_id)
467*593dc095SDavid du Colombier pprintld1(s, "/CIDSystemInfo %ld 0 R",
468*593dc095SDavid du Colombier pdfont->u.cidfont.CIDSystemInfo_id);
469*593dc095SDavid du Colombier pprintd1(s, "/Subtype/CIDFontType%d>>\n", subtype);
470*593dc095SDavid du Colombier pdf_end_separate(pdev);
471*593dc095SDavid du Colombier return 0;
472*593dc095SDavid du Colombier }
473*593dc095SDavid du Colombier int
pdf_write_contents_cid0(gx_device_pdf * pdev,pdf_font_resource_t * pdfont)474*593dc095SDavid du Colombier pdf_write_contents_cid0(gx_device_pdf *pdev, pdf_font_resource_t *pdfont)
475*593dc095SDavid du Colombier {
476*593dc095SDavid du Colombier return write_contents_cid_common(pdev, pdfont, 0);
477*593dc095SDavid du Colombier }
478*593dc095SDavid du Colombier int
pdf_write_contents_cid2(gx_device_pdf * pdev,pdf_font_resource_t * pdfont)479*593dc095SDavid du Colombier pdf_write_contents_cid2(gx_device_pdf *pdev, pdf_font_resource_t *pdfont)
480*593dc095SDavid du Colombier {
481*593dc095SDavid du Colombier int count = pdfont->count;
482*593dc095SDavid du Colombier long map_id = 0;
483*593dc095SDavid du Colombier psf_glyph_enum_t genum;
484*593dc095SDavid du Colombier gs_glyph glyph;
485*593dc095SDavid du Colombier int code;
486*593dc095SDavid du Colombier
487*593dc095SDavid du Colombier /* Check for the identity CIDMap. */
488*593dc095SDavid du Colombier psf_enumerate_bits_begin(&genum, NULL, pdfont->used, count,
489*593dc095SDavid du Colombier GLYPH_SPACE_INDEX);
490*593dc095SDavid du Colombier while (!psf_enumerate_glyphs_next(&genum, &glyph)) {
491*593dc095SDavid du Colombier int cid = glyph - GS_MIN_CID_GLYPH;
492*593dc095SDavid du Colombier int gid = pdfont->u.cidfont.CIDToGIDMap[cid];
493*593dc095SDavid du Colombier
494*593dc095SDavid du Colombier if (gid != cid) { /* non-identity map */
495*593dc095SDavid du Colombier map_id = pdf_obj_ref(pdev);
496*593dc095SDavid du Colombier pprintld1(pdev->strm, "/CIDToGIDMap %ld 0 R\n", map_id);
497*593dc095SDavid du Colombier break;
498*593dc095SDavid du Colombier }
499*593dc095SDavid du Colombier }
500*593dc095SDavid du Colombier
501*593dc095SDavid du Colombier code = write_contents_cid_common(pdev, pdfont, 2);
502*593dc095SDavid du Colombier if (code < 0)
503*593dc095SDavid du Colombier return code;
504*593dc095SDavid du Colombier
505*593dc095SDavid du Colombier if (map_id) {
506*593dc095SDavid du Colombier pdf_data_writer_t writer;
507*593dc095SDavid du Colombier int i;
508*593dc095SDavid du Colombier
509*593dc095SDavid du Colombier pdf_begin_data_stream(pdev, &writer,
510*593dc095SDavid du Colombier DATA_STREAM_BINARY | DATA_STREAM_COMPRESS,
511*593dc095SDavid du Colombier /* Don't set DATA_STREAM_ENCRYPT since we write to a temporary file.
512*593dc095SDavid du Colombier See comment in pdf_begin_encrypt. */
513*593dc095SDavid du Colombier map_id);
514*593dc095SDavid du Colombier for (i = 0; i < count; ++i) {
515*593dc095SDavid du Colombier uint gid = pdfont->u.cidfont.CIDToGIDMap[i];
516*593dc095SDavid du Colombier
517*593dc095SDavid du Colombier stream_putc(writer.binary.strm, (byte)(gid >> 8));
518*593dc095SDavid du Colombier stream_putc(writer.binary.strm, (byte)(gid));
519*593dc095SDavid du Colombier }
520*593dc095SDavid du Colombier code = pdf_end_data(&writer);
521*593dc095SDavid du Colombier }
522*593dc095SDavid du Colombier return code;
523*593dc095SDavid du Colombier }
524*593dc095SDavid du Colombier
525*593dc095SDavid du Colombier /* ---------------- External entries ---------------- */
526*593dc095SDavid du Colombier
527*593dc095SDavid du Colombier /* Write a font resource. */
528*593dc095SDavid du Colombier private int
pdf_write_font_resource(gx_device_pdf * pdev,pdf_font_resource_t * pdfont)529*593dc095SDavid du Colombier pdf_write_font_resource(gx_device_pdf *pdev, pdf_font_resource_t *pdfont)
530*593dc095SDavid du Colombier {
531*593dc095SDavid du Colombier stream *s;
532*593dc095SDavid du Colombier
533*593dc095SDavid du Colombier if (pdfont->cmap_ToUnicode != NULL && pdfont->res_ToUnicode == NULL)
534*593dc095SDavid du Colombier if (((pdfont->FontType == ft_composite) &&
535*593dc095SDavid du Colombier !gs_cmap_is_identity(pdfont->cmap_ToUnicode, -1)) ||
536*593dc095SDavid du Colombier ((pdfont->FontType == ft_encrypted || pdfont->FontType == ft_encrypted2 ||
537*593dc095SDavid du Colombier pdfont->FontType == ft_TrueType || pdfont->FontType == ft_user_defined) &&
538*593dc095SDavid du Colombier pdf_simple_font_needs_ToUnicode(pdfont))
539*593dc095SDavid du Colombier ) {
540*593dc095SDavid du Colombier pdf_resource_t *prcmap;
541*593dc095SDavid du Colombier int code = pdf_cmap_alloc(pdev, pdfont->cmap_ToUnicode, &prcmap, -1);
542*593dc095SDavid du Colombier
543*593dc095SDavid du Colombier if (code < 0)
544*593dc095SDavid du Colombier return code;
545*593dc095SDavid du Colombier pdfont->res_ToUnicode = prcmap;
546*593dc095SDavid du Colombier }
547*593dc095SDavid du Colombier pdf_open_separate(pdev, pdf_font_id(pdfont));
548*593dc095SDavid du Colombier s = pdev->strm;
549*593dc095SDavid du Colombier stream_puts(s, "<<");
550*593dc095SDavid du Colombier if (pdfont->BaseFont.size > 0) {
551*593dc095SDavid du Colombier stream_puts(s, "/BaseFont");
552*593dc095SDavid du Colombier pdf_put_name(pdev, pdfont->BaseFont.data, pdfont->BaseFont.size);
553*593dc095SDavid du Colombier }
554*593dc095SDavid du Colombier if (pdfont->FontDescriptor)
555*593dc095SDavid du Colombier pprintld1(s, "/FontDescriptor %ld 0 R",
556*593dc095SDavid du Colombier pdf_font_descriptor_id(pdfont->FontDescriptor));
557*593dc095SDavid du Colombier if (pdfont->res_ToUnicode)
558*593dc095SDavid du Colombier pprintld1(s, "/ToUnicode %ld 0 R",
559*593dc095SDavid du Colombier pdf_resource_id((const pdf_resource_t *)pdfont->res_ToUnicode));
560*593dc095SDavid du Colombier if (pdev->CompatibilityLevel > 1.0)
561*593dc095SDavid du Colombier stream_puts(s, "/Type/Font\n");
562*593dc095SDavid du Colombier else
563*593dc095SDavid du Colombier pprintld1(s, "/Type/Font/Name/R%ld\n", pdf_font_id(pdfont));
564*593dc095SDavid du Colombier if (pdev->ForOPDFRead && pdfont->global)
565*593dc095SDavid du Colombier stream_puts(s, "/.Global true\n");
566*593dc095SDavid du Colombier return pdfont->write_contents(pdev, pdfont);
567*593dc095SDavid du Colombier }
568*593dc095SDavid du Colombier
569*593dc095SDavid du Colombier /*
570*593dc095SDavid du Colombier * Close the text-related parts of a document, including writing out font
571*593dc095SDavid du Colombier * and related resources.
572*593dc095SDavid du Colombier */
573*593dc095SDavid du Colombier private int
write_font_resources(gx_device_pdf * pdev,pdf_resource_list_t * prlist)574*593dc095SDavid du Colombier write_font_resources(gx_device_pdf *pdev, pdf_resource_list_t *prlist)
575*593dc095SDavid du Colombier {
576*593dc095SDavid du Colombier int j;
577*593dc095SDavid du Colombier pdf_resource_t *pres;
578*593dc095SDavid du Colombier
579*593dc095SDavid du Colombier for (j = 0; j < NUM_RESOURCE_CHAINS; ++j)
580*593dc095SDavid du Colombier for (pres = prlist->chains[j]; pres != 0; pres = pres->next) {
581*593dc095SDavid du Colombier pdf_font_resource_t *const pdfont = (pdf_font_resource_t *)pres;
582*593dc095SDavid du Colombier int code = pdf_compute_BaseFont(pdev, pdfont, true);
583*593dc095SDavid du Colombier
584*593dc095SDavid du Colombier if (code < 0)
585*593dc095SDavid du Colombier return code;
586*593dc095SDavid du Colombier code = pdf_write_font_resource(pdev, pdfont);
587*593dc095SDavid du Colombier if (code < 0)
588*593dc095SDavid du Colombier return code;
589*593dc095SDavid du Colombier pdfont->object->written = true;
590*593dc095SDavid du Colombier }
591*593dc095SDavid du Colombier return 0;
592*593dc095SDavid du Colombier }
593*593dc095SDavid du Colombier int
pdf_finish_font_descriptors(gx_device_pdf * pdev,int (* finish_proc)(gx_device_pdf *,pdf_font_descriptor_t *))594*593dc095SDavid du Colombier pdf_finish_font_descriptors(gx_device_pdf *pdev,
595*593dc095SDavid du Colombier int (*finish_proc)(gx_device_pdf *,
596*593dc095SDavid du Colombier pdf_font_descriptor_t *))
597*593dc095SDavid du Colombier {
598*593dc095SDavid du Colombier int j;
599*593dc095SDavid du Colombier pdf_resource_t *pres;
600*593dc095SDavid du Colombier
601*593dc095SDavid du Colombier for (j = 0; j < NUM_RESOURCE_CHAINS; ++j)
602*593dc095SDavid du Colombier for (pres = pdev->resources[resourceFontDescriptor].chains[j];
603*593dc095SDavid du Colombier pres != 0; pres = pres->next
604*593dc095SDavid du Colombier ) {
605*593dc095SDavid du Colombier int code = finish_proc(pdev, (pdf_font_descriptor_t *)pres);
606*593dc095SDavid du Colombier
607*593dc095SDavid du Colombier if (code < 0)
608*593dc095SDavid du Colombier return code;
609*593dc095SDavid du Colombier }
610*593dc095SDavid du Colombier return 0;
611*593dc095SDavid du Colombier }
612*593dc095SDavid du Colombier int
pdf_close_text_document(gx_device_pdf * pdev)613*593dc095SDavid du Colombier pdf_close_text_document(gx_device_pdf *pdev)
614*593dc095SDavid du Colombier {
615*593dc095SDavid du Colombier int code;
616*593dc095SDavid du Colombier
617*593dc095SDavid du Colombier /*
618*593dc095SDavid du Colombier * Finish the descriptors and write any embedded fonts, but don't
619*593dc095SDavid du Colombier * write the descriptors yet; then write the fonts; finally write
620*593dc095SDavid du Colombier * the descriptors.
621*593dc095SDavid du Colombier */
622*593dc095SDavid du Colombier
623*593dc095SDavid du Colombier pdf_clean_standard_fonts(pdev);
624*593dc095SDavid du Colombier if ((code = pdf_free_font_cache(pdev)) < 0 ||
625*593dc095SDavid du Colombier (code = pdf_write_resource_objects(pdev, resourceCharProc)) < 0 ||
626*593dc095SDavid du Colombier (code = pdf_finish_font_descriptors(pdev, pdf_finish_FontDescriptor)) < 0 ||
627*593dc095SDavid du Colombier (code = write_font_resources(pdev, &pdev->resources[resourceCIDFont])) < 0 ||
628*593dc095SDavid du Colombier (code = write_font_resources(pdev, &pdev->resources[resourceFont])) < 0 ||
629*593dc095SDavid du Colombier (code = pdf_finish_font_descriptors(pdev, pdf_write_FontDescriptor)) < 0
630*593dc095SDavid du Colombier )
631*593dc095SDavid du Colombier return code;
632*593dc095SDavid du Colombier
633*593dc095SDavid du Colombier /* If required, write the Encoding for Type 3 bitmap fonts. */
634*593dc095SDavid du Colombier
635*593dc095SDavid du Colombier return pdf_write_bitmap_fonts_Encoding(pdev);
636*593dc095SDavid du Colombier }
637*593dc095SDavid du Colombier
638*593dc095SDavid du Colombier /* ================ CMap resource writing ================ */
639*593dc095SDavid du Colombier
640*593dc095SDavid du Colombier /*
641*593dc095SDavid du Colombier * Write the CIDSystemInfo for a CIDFont or a CMap.
642*593dc095SDavid du Colombier */
643*593dc095SDavid du Colombier private int
pdf_write_cid_system_info_to_stream(gx_device_pdf * pdev,stream * s,const gs_cid_system_info_t * pcidsi,gs_id object_id)644*593dc095SDavid du Colombier pdf_write_cid_system_info_to_stream(gx_device_pdf *pdev, stream *s,
645*593dc095SDavid du Colombier const gs_cid_system_info_t *pcidsi, gs_id object_id)
646*593dc095SDavid du Colombier {
647*593dc095SDavid du Colombier byte Registry[32], Ordering[32];
648*593dc095SDavid du Colombier
649*593dc095SDavid du Colombier if (pcidsi->Registry.size > sizeof(Registry))
650*593dc095SDavid du Colombier return_error(gs_error_limitcheck);
651*593dc095SDavid du Colombier if (pcidsi->Ordering.size > sizeof(Ordering))
652*593dc095SDavid du Colombier return_error(gs_error_limitcheck);
653*593dc095SDavid du Colombier memcpy(Registry, pcidsi->Registry.data, pcidsi->Registry.size);
654*593dc095SDavid du Colombier memcpy(Ordering, pcidsi->Ordering.data, pcidsi->Ordering.size);
655*593dc095SDavid du Colombier if (pdev->KeyLength && object_id != 0) {
656*593dc095SDavid du Colombier stream_arcfour_state sarc4;
657*593dc095SDavid du Colombier int code;
658*593dc095SDavid du Colombier
659*593dc095SDavid du Colombier code = pdf_encrypt_init(pdev, object_id, &sarc4);
660*593dc095SDavid du Colombier if (code < 0)
661*593dc095SDavid du Colombier return code;
662*593dc095SDavid du Colombier s_arcfour_process_buffer(&sarc4, Registry, pcidsi->Registry.size);
663*593dc095SDavid du Colombier code = pdf_encrypt_init(pdev, object_id, &sarc4);
664*593dc095SDavid du Colombier if (code < 0)
665*593dc095SDavid du Colombier return code;
666*593dc095SDavid du Colombier s_arcfour_process_buffer(&sarc4, Ordering, pcidsi->Ordering.size);
667*593dc095SDavid du Colombier }
668*593dc095SDavid du Colombier stream_puts(s, "<<\n/Registry");
669*593dc095SDavid du Colombier s_write_ps_string(s, Registry, pcidsi->Registry.size, PRINT_HEX_NOT_OK);
670*593dc095SDavid du Colombier stream_puts(s, "\n/Ordering");
671*593dc095SDavid du Colombier s_write_ps_string(s, Ordering, pcidsi->Ordering.size, PRINT_HEX_NOT_OK);
672*593dc095SDavid du Colombier pprintd1(s, "\n/Supplement %d\n>>\n", pcidsi->Supplement);
673*593dc095SDavid du Colombier return 0;
674*593dc095SDavid du Colombier }
675*593dc095SDavid du Colombier
676*593dc095SDavid du Colombier int
pdf_write_cid_system_info(gx_device_pdf * pdev,const gs_cid_system_info_t * pcidsi,gs_id object_id)677*593dc095SDavid du Colombier pdf_write_cid_system_info(gx_device_pdf *pdev,
678*593dc095SDavid du Colombier const gs_cid_system_info_t *pcidsi, gs_id object_id)
679*593dc095SDavid du Colombier {
680*593dc095SDavid du Colombier return pdf_write_cid_system_info_to_stream(pdev, pdev->strm, pcidsi, object_id);
681*593dc095SDavid du Colombier }
682*593dc095SDavid du Colombier
683*593dc095SDavid du Colombier
684*593dc095SDavid du Colombier /*
685*593dc095SDavid du Colombier * Write a CMap resource. We pass the CMap object as well as the resource,
686*593dc095SDavid du Colombier * because we write CMaps when they are created.
687*593dc095SDavid du Colombier */
688*593dc095SDavid du Colombier int
pdf_write_cmap(gx_device_pdf * pdev,const gs_cmap_t * pcmap,pdf_resource_t ** ppres,int font_index_only)689*593dc095SDavid du Colombier pdf_write_cmap(gx_device_pdf *pdev, const gs_cmap_t *pcmap,
690*593dc095SDavid du Colombier pdf_resource_t **ppres /*CMap*/, int font_index_only)
691*593dc095SDavid du Colombier {
692*593dc095SDavid du Colombier int code;
693*593dc095SDavid du Colombier pdf_data_writer_t writer;
694*593dc095SDavid du Colombier
695*593dc095SDavid du Colombier code = pdf_begin_data_stream(pdev, &writer,
696*593dc095SDavid du Colombier DATA_STREAM_NOT_BINARY |
697*593dc095SDavid du Colombier /* Don't set DATA_STREAM_ENCRYPT since we write to a temporary file.
698*593dc095SDavid du Colombier See comment in pdf_begin_encrypt. */
699*593dc095SDavid du Colombier (pdev->CompressFonts ?
700*593dc095SDavid du Colombier DATA_STREAM_COMPRESS : 0), gs_no_id);
701*593dc095SDavid du Colombier if (code < 0)
702*593dc095SDavid du Colombier return code;
703*593dc095SDavid du Colombier *ppres = writer.pres;
704*593dc095SDavid du Colombier writer.pres->where_used = 0; /* CMap isn't a PDF resource. */
705*593dc095SDavid du Colombier if (!pcmap->ToUnicode) {
706*593dc095SDavid du Colombier byte buf[200];
707*593dc095SDavid du Colombier cos_dict_t *pcd = (cos_dict_t *)writer.pres->object;
708*593dc095SDavid du Colombier stream s;
709*593dc095SDavid du Colombier
710*593dc095SDavid du Colombier code = cos_dict_put_c_key_int(pcd, "/WMode", pcmap->WMode);
711*593dc095SDavid du Colombier if (code < 0)
712*593dc095SDavid du Colombier return code;
713*593dc095SDavid du Colombier buf[0] = '/';
714*593dc095SDavid du Colombier memcpy(buf + 1, pcmap->CMapName.data, pcmap->CMapName.size);
715*593dc095SDavid du Colombier code = cos_dict_put_c_key_string(pcd, "/CMapName",
716*593dc095SDavid du Colombier buf, pcmap->CMapName.size + 1);
717*593dc095SDavid du Colombier if (code < 0)
718*593dc095SDavid du Colombier return code;
719*593dc095SDavid du Colombier s_init(&s, pdev->memory);
720*593dc095SDavid du Colombier swrite_string(&s, buf, sizeof(buf));
721*593dc095SDavid du Colombier code = pdf_write_cid_system_info_to_stream(pdev, &s, pcmap->CIDSystemInfo, 0);
722*593dc095SDavid du Colombier if (code < 0)
723*593dc095SDavid du Colombier return code;
724*593dc095SDavid du Colombier code = cos_dict_put_c_key_string(pcd, "/CIDSystemInfo",
725*593dc095SDavid du Colombier buf, stell(&s));
726*593dc095SDavid du Colombier if (code < 0)
727*593dc095SDavid du Colombier return code;
728*593dc095SDavid du Colombier code = cos_dict_put_string_copy(pcd, "/Type", "/CMap");
729*593dc095SDavid du Colombier if (code < 0)
730*593dc095SDavid du Colombier return code;
731*593dc095SDavid du Colombier }
732*593dc095SDavid du Colombier code = psf_write_cmap(pdev->memory, writer.binary.strm, pcmap,
733*593dc095SDavid du Colombier pdf_put_name_chars_proc(pdev), NULL, font_index_only);
734*593dc095SDavid du Colombier if (code < 0)
735*593dc095SDavid du Colombier return code;
736*593dc095SDavid du Colombier code = pdf_end_data(&writer);
737*593dc095SDavid du Colombier if (code < 0)
738*593dc095SDavid du Colombier return code;
739*593dc095SDavid du Colombier return code;
740*593dc095SDavid du Colombier }
741