"Fossies" - the Fresh Open Source Software Archive 
As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style:
standard) with prefixed line numbers and
code folding option.
Alternatively you can here
view or
download the uninterpreted source code file.
1 /* Copyright (C) 1993-2005 Ghostgum Software Pty Ltd. 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 licence and may not be copied,
7 modified or distributed except as expressly authorised under the terms
8 of the licence contained in the file LICENCE in this distribution.
9
10 For more information about licensing, please refer to
11 http://www.ghostgum.com.au/ or contact Ghostsgum Software Pty Ltd,
12 218 Gallaghers Rd, Glen Waverley VIC 3150, AUSTRALIA,
13 Fax +61 3 9886 6616.
14 */
15
16 /* $Id: ceps.c,v 1.43 2005/06/10 08:45:36 ghostgum Exp $ */
17
18 /* EPS preview manipulation */
19
20 #include "common.h"
21 #include <time.h>
22 #include "gdevdsp.h"
23 #include "dscparse.h"
24 #include "capp.h"
25 #include "cbmp.h"
26 #define DEFINE_CDOC
27 #include "cdoc.h"
28 #include "cmac.h"
29 #include "ceps.h"
30 #include "cimg.h"
31 #include "cps.h"
32
33
34 #define DOSEPS_HEADER_SIZE 30
35
36 /* Local prototypes */
37 static void write_doseps_header(CDSCDOSEPS *doseps, GFile *outfile);
38 static void shift_preview(unsigned char *preview, int bwidth, int offset);
39 static void validate_devbbox(IMAGE *img, CDSCBBOX *devbbox);
40 int write_interchange(GFile *f, IMAGE *img, CDSCBBOX devbbox);
41 static void write_bitmap_info(IMAGE *img, LPBITMAP2 pbmi, GFile *f);
42 static void make_bmp_info(LPBITMAP2 pbmi, IMAGE *img, float xdpi, float ydpi);
43 void copy_nobbox(GFile *outfile, GFile *infile,
44 FILE_POS begin, FILE_POS end);
45 void copy_bbox_header(GFile *outfile,
46 GFile *infile, FILE_POS begin, FILE_POS end,
47 CDSCBBOX *bbox, CDSCFBBOX *hiresbbox);
48 static int without_eol(const char *str, int length);
49 static FILE_POS write_platefile_comments(Doc *doc, GFile *docfile,
50 GFile *epsfile, LPCTSTR epsname,
51 int offset, FILE_POS file_offset,
52 BOOL dcs2_multi, BOOL write_all, BOOL missing_separations,
53 const char *renamed[], BOOL some_renamed);
54 static FILE_POS write_singlefile_separations(Doc *doc, GFile *docfile,
55 GFile *epsfile,
56 BOOL dcs2_multi, BOOL write_all, BOOL missing_separations,
57 BOOL some_renamed);
58
59 /* A placeable Windows Metafile header is needed
60 * when the metafile is in a WMF file, but not
61 * when it is in memory.
62 */
63 typedef struct WINRECT_s {
64 WORD left;
65 WORD top;
66 WORD right;
67 WORD bottom;
68 } WINRECT;
69
70 typedef struct METAFILEHEADER_s {
71 DWORD key;
72 WORD hmf;
73 WINRECT bbox;
74 WORD inch;
75 DWORD reserved;
76 WORD checksum;
77 } METAFILEHEADER;
78
79
80 static void
81 write_doseps_header(CDSCDOSEPS *doseps, GFile *outfile)
82 {
83 unsigned char doseps_id[] = {0xc5, 0xd0, 0xd3, 0xc6};
84 gfile_write(outfile, doseps_id, 4);
85 write_dword(doseps->ps_begin, outfile);
86 write_dword(doseps->ps_length, outfile);
87 write_dword(doseps->wmf_begin, outfile);
88 write_dword(doseps->wmf_length, outfile);
89 write_dword(doseps->tiff_begin, outfile);
90 write_dword(doseps->tiff_length, outfile);
91 write_word((WORD)(doseps->checksum), outfile);
92 }
93
94 /* shift preview by offset bits to the left */
95 /* width is in bytes */
96 /* fill exposed bits with 1's */
97 static void
98 shift_preview(unsigned char *preview, int bwidth, int offset)
99 {
100 int bitoffset;
101 int byteoffset;
102 int newwidth;
103 int shifter;
104 int i;
105 if (offset == 0)
106 return;
107 byteoffset = offset / 8;
108 newwidth = bwidth - byteoffset;
109 /* first remove byte offset */
110 memmove(preview, preview+byteoffset, newwidth);
111 memset(preview+newwidth, 0xff, bwidth-newwidth);
112 /* next remove bit offset */
113 bitoffset = offset - byteoffset*8;
114 if (bitoffset==0)
115 return;
116 bitoffset = 8 - bitoffset;
117 for (i=0; i<newwidth; i++) {
118 shifter = preview[i] << 8;
119 if (i==newwidth-1)
120 shifter += 0xff; /* can't access preview[bwidth] */
121 else
122 shifter += preview[i+1];
123 preview[i] = (unsigned char)(shifter>>bitoffset);
124 }
125 }
126
127
128 static void
129 validate_devbbox(IMAGE *img, CDSCBBOX *devbbox)
130 {
131 /* make sure the pixel coordinates are valid */
132 if ((devbbox->llx < 0) || (devbbox->llx >= (int)img->width))
133 devbbox->llx = 0;
134 if ((devbbox->urx < 0) || (devbbox->urx >= (int)img->width))
135 devbbox->urx = img->width;
136 if ((devbbox->lly < 0) || (devbbox->lly >= (int)img->height))
137 devbbox->lly = 0;
138 if ((devbbox->ury < 0) || (devbbox->ury >= (int)img->height))
139 devbbox->ury = img->height;
140
141 if ((devbbox->llx >= devbbox->urx) || (devbbox->lly >= devbbox->ury)) {
142 devbbox->llx = devbbox->lly = 0;
143 devbbox->urx = img->width;
144 devbbox->ury = img->height;
145 }
146 }
147
148 /* Write bitmap info.
149 * This works even if LPBITMAP2 is not packed.
150 */
151 static void
152 write_bitmap_info(IMAGE *img, LPBITMAP2 pbmi, GFile *f)
153 {
154 int i;
155 unsigned char r, g, b;
156 unsigned char quad[4];
157 int palcount = 0;
158
159 /* write bitmap info */
160 write_dword(BITMAP2_LENGTH, f);
161 write_dword(pbmi->biWidth, f);
162 write_dword(pbmi->biHeight, f);
163 write_word(pbmi->biPlanes, f);
164 write_word(pbmi->biBitCount, f);
165 write_dword(pbmi->biCompression, f);
166 write_dword(pbmi->biSizeImage, f);
167 write_dword(pbmi->biXPelsPerMeter, f);
168 write_dword(pbmi->biYPelsPerMeter, f);
169 write_dword(pbmi->biClrUsed, f);
170 write_dword(pbmi->biClrImportant, f);
171
172 if (pbmi->biBitCount <= 8)
173 palcount = 1 << pbmi->biBitCount;
174 for (i=0; i<palcount; i++) {
175 image_colour(img->format, i, &r, &g, &b);
176 quad[0] = b;
177 quad[1] = g;
178 quad[2] = r;
179 quad[3] = '\0';
180 gfile_write(f, quad, 4);
181 }
182 }
183
184 /* Make a BMP header from an IMAGE.
185 * WARNING: The pbmi structure might not be packed, so it
186 * should only be used by write_bitmap_info(), and not written
187 * out directly.
188 */
189 static void
190 make_bmp_info(LPBITMAP2 pbmi, IMAGE *img, float xdpi, float ydpi)
191 {
192 int palcount = 0;
193 int depth = image_depth(img);
194 if (depth <= 8)
195 palcount = 1 << depth;
196
197 pbmi->biSize = sizeof(BITMAP2); /* WARNING - MAY NOT BE PACKED */
198 pbmi->biWidth = img->width;
199 pbmi->biHeight = img->width;
200 pbmi->biPlanes = 1;
201 pbmi->biBitCount = (WORD)image_depth(img);
202 pbmi->biCompression = 0;
203 pbmi->biSizeImage = 0;
204 pbmi->biXPelsPerMeter = (long)(1000 * xdpi / 25.4);
205 pbmi->biYPelsPerMeter = (long)(1000 * ydpi / 25.4);
206 pbmi->biClrUsed = palcount;
207 pbmi->biClrImportant = palcount;
208 }
209
210 /*********************************************************/
211
212 /* extract EPS or TIFF or WMF file from DOS EPS file */
213 int
214 extract_doseps(Doc *doc, LPCTSTR outname, BOOL preview)
215 {
216 unsigned long pos;
217 unsigned long len;
218 unsigned int count;
219 char *buffer;
220 GFile* epsfile;
221 BOOL is_meta = TRUE;
222 GFile *outfile;
223 CDSC *dsc = doc->dsc;
224
225 if ((dsc == (CDSC *)NULL) || (dsc->doseps == (CDSCDOSEPS *)NULL)) {
226 app_csmsgf(doc->app,
227 TEXT("Document \042%s\042 is not a DOS EPS file\n"),
228 doc->name);
229 return -1;
230 }
231
232 epsfile = gfile_open(doc_name(doc), gfile_modeRead);
233 pos = dsc->doseps->ps_begin;
234 len = dsc->doseps->ps_length;
235 if (preview) {
236 pos = dsc->doseps->wmf_begin;
237 len = dsc->doseps->wmf_length;
238 if (pos == 0L) {
239 pos = dsc->doseps->tiff_begin;
240 len = dsc->doseps->tiff_length;
241 is_meta = FALSE;
242 }
243 }
244 if (pos == 0L) {
245 gfile_close(epsfile);
246 app_csmsgf(doc->app,
247 TEXT("Document \042%s\042 does not have a %s section\n"),
248 doc->name, preview ? TEXT("preview") : TEXT("PostScript"));
249 return -1;
250 }
251 gfile_seek(epsfile, pos, gfile_begin); /* seek to section to extract */
252
253 outfile = gfile_open(outname, gfile_modeWrite | gfile_modeCreate);
254 if (outfile == (GFile *)NULL) {
255 app_csmsgf(doc->app,
256 TEXT("Failed to open output file \042%s\042\n"), outname);
257 gfile_close(epsfile);
258 return -1;
259 }
260
261 /* create buffer for file copy */
262 buffer = (char *)malloc(COPY_BUF_SIZE);
263 if (buffer == (char *)NULL) {
264 app_csmsgf(doc->app, TEXT("Out of memory in extract_doseps\n"));
265 gfile_close(epsfile);
266 if (*outname!='\0')
267 gfile_close(outfile);
268 return -1;
269 }
270
271 if (preview && is_meta) {
272 /* check if metafile already contains header */
273 DWORD key;
274 char keybuf[4];
275 DWORD wmf_key = 0x9ac6cdd7UL;
276 gfile_read(epsfile, keybuf, 4);
277 key = (unsigned int)(keybuf[0]) +
278 ((unsigned int)(keybuf[1])<<8) +
279 ((unsigned int)(keybuf[2])<<16) +
280 ((unsigned int)(keybuf[3])<<24);
281 gfile_seek(epsfile, pos, gfile_begin); /* seek to section to extract */
282 if ( key != wmf_key ) {
283 /* write placeable Windows Metafile header */
284 METAFILEHEADER mfh;
285 int i, temp;
286 unsigned short *pw;
287 mfh.key = wmf_key;
288 mfh.hmf = 0;
289 /* guess the location - this might be wrong */
290 mfh.bbox.left = 0;
291 mfh.bbox.top = 0;
292 if (dsc->bbox != (CDSCBBOX *)NULL) {
293 temp = (dsc->bbox->urx - dsc->bbox->llx);
294 /* double transfer to avoid GCC Solaris bug */
295 mfh.bbox.right = (WORD)temp;
296 mfh.bbox.bottom = (WORD)(dsc->bbox->ury - dsc->bbox->lly);
297 temp = (dsc->bbox->ury - dsc->bbox->lly);
298 mfh.bbox.bottom = (WORD)temp;
299 }
300 else {
301 /* bbox missing, assume A4 */
302 mfh.bbox.right = 595;
303 mfh.bbox.bottom = 842;
304 }
305 mfh.inch = 72; /* PostScript points */
306 mfh.reserved = 0L;
307 mfh.checksum = 0;
308 pw = (WORD *)&mfh;
309 temp = 0;
310 for (i=0; i<10; i++) {
311 temp ^= *pw++;
312 }
313 mfh.checksum = (WORD)temp;
314 write_dword(mfh.key, outfile);
315 write_word(mfh.hmf, outfile);
316 write_word(mfh.bbox.left, outfile);
317 write_word(mfh.bbox.top, outfile);
318 write_word(mfh.bbox.right, outfile);
319 write_word(mfh.bbox.bottom, outfile);
320 write_word(mfh.inch, outfile);
321 write_dword(mfh.reserved, outfile);
322 write_word(mfh.checksum, outfile);
323 }
324 }
325
326 while ( (count = (unsigned int)min(len,COPY_BUF_SIZE)) != 0 ) {
327 count = (int)gfile_read(epsfile, buffer, count);
328 gfile_write(outfile, buffer, count);
329 if (count == 0)
330 len = 0;
331 else
332 len -= count;
333 }
334 free(buffer);
335 gfile_close(epsfile);
336 gfile_close(outfile);
337
338 return 0;
339 }
340
341 /* extract EPS or PICT file from Macintosh EPSF file */
342 int
343 extract_macbin(Doc *doc, LPCTSTR outname, BOOL preview)
344 {
345 unsigned long pos;
346 unsigned long len;
347 unsigned int count;
348 char *buffer;
349 GFile* epsfile;
350 GFile *outfile;
351 CDSC *dsc = doc->dsc;
352
353 CMACFILE *mac;
354
355 if ((dsc == (CDSC *)NULL) || (dsc->macbin == (CDSCMACBIN *)NULL)) {
356 app_csmsgf(doc->app,
357 TEXT("Document \042%s\042 is not a Macintosh EPSF file with preview\n"),
358 doc->name);
359 return -1;
360 }
361
362 epsfile = gfile_open(doc_name(doc), gfile_modeRead);
363 if (epsfile == NULL) {
364 app_csmsgf(doc->app,
365 TEXT("Failed to open \042%s\042\n"), doc_name(doc));
366 return -1;
367 }
368
369 if (preview) {
370 int code = 0;
371 mac = get_mactype(epsfile);
372 if (mac == NULL) {
373 app_csmsgf(doc->app, TEXT("Not a Mac file with resource fork\n"));
374 code = -1;
375 }
376 if (code == 0) {
377 code = get_pict(epsfile, mac, FALSE);
378 if (code)
379 app_csmsgf(doc->app,
380 TEXT("Resource fork didn't contain PICT preview\n"));
381 }
382 if (code == 0) {
383 code = extract_mac_pict(epsfile, mac, outname);
384 if (code)
385 app_csmsgf(doc->app,
386 TEXT("Failed to find PICT preview or write file\n"));
387 }
388 gfile_close(epsfile);
389 return code;
390 }
391
392 pos = dsc->macbin->data_begin;
393 len = dsc->macbin->data_length;
394 if (len == 0) {
395 app_csmsgf(doc->app,
396 TEXT("File has not data section for EPSF\n"));
397 gfile_close(epsfile);
398 return -1;
399 }
400 gfile_seek(epsfile, pos, gfile_begin); /* seek to section to extract */
401
402 outfile = gfile_open(outname, gfile_modeWrite | gfile_modeCreate);
403 if (outfile == (GFile *)NULL) {
404 app_csmsgf(doc->app,
405 TEXT("Failed to open output file \042%s\042\n"), outname);
406 gfile_close(epsfile);
407 return -1;
408 }
409
410 /* create buffer for file copy */
411 buffer = (char *)malloc(COPY_BUF_SIZE);
412 if (buffer == (char *)NULL) {
413 app_csmsgf(doc->app, TEXT("Out of memory in extract_doseps\n"));
414 gfile_close(epsfile);
415 if (*outname!='\0')
416 gfile_close(outfile);
417 return -1;
418 }
419
420 while ( (count = (unsigned int)min(len,COPY_BUF_SIZE)) != 0 ) {
421 count = (int)gfile_read(epsfile, buffer, count);
422 gfile_write(outfile, buffer, count);
423 if (count == 0)
424 len = 0;
425 else
426 len -= count;
427 }
428 free(buffer);
429 gfile_close(epsfile);
430 gfile_close(outfile);
431
432 return 0;
433 }
434
435 /*********************************************************/
436
437 /* FIX: instead of devbbox, perhaps we should use CDSCFBBOX in points,
438 or simply grab this from doc. */
439
440 /* make a PC EPS file with a TIFF Preview */
441 /* from a PS file and a bitmap */
442 int
443 make_eps_tiff(Doc *doc, IMAGE *img, CDSCBBOX devbbox,
444 CDSCBBOX *bbox, CDSCFBBOX *hires_bbox,
445 float xdpi, float ydpi, BOOL tiff4, BOOL use_packbits, BOOL reverse,
446 LPCTSTR epsname)
447 {
448 GFile *epsfile;
449 GFile *tiff_file;
450 TCHAR tiffname[MAXSTR];
451 CDSCDOSEPS doseps;
452 int code;
453 GFile *tpsfile;
454 TCHAR tpsname[MAXSTR];
455 char *buffer;
456 unsigned int count;
457 CDSC *dsc = doc->dsc;
458
459 if (dsc == NULL)
460 return -1;
461
462 validate_devbbox(img, &devbbox);
463
464 /* Create TIFF file */
465 if ((tiff_file = app_temp_gfile(doc->app, tiffname,
466 sizeof(tiffname)/sizeof(TCHAR))) == (GFile *)NULL) {
467 app_csmsgf(doc->app,
468 TEXT("Can't open temporary TIFF file \042%s\042\n"),
469 tiffname);
470 return -1;
471 }
472 code = image_to_tiff(tiff_file, img,
473 devbbox.llx, devbbox.lly, devbbox.urx, devbbox.ury,
474 xdpi, ydpi, tiff4, use_packbits);
475 gfile_close(tiff_file);
476 if (code) {
477 app_csmsgf(doc->app,
478 TEXT("Failed to write temporary TIFF file \042%s\042\n"),
479 tiffname);
480 if (!(debug & DEBUG_GENERAL))
481 csunlink(tiffname);
482 return code;
483 }
484
485 /* Create temporary EPS file with updated headers */
486 tpsfile = NULL;
487 memset(tpsname, 0, sizeof(tpsname));
488 if ((tpsfile = app_temp_gfile(doc->app, tpsname,
489 sizeof(tpsname)/sizeof(TCHAR))) == (GFile *)NULL) {
490 app_csmsgf(doc->app,
491 TEXT("Can't create temporary EPS file \042%s\042\n"),
492 tpsname);
493 csunlink(tiffname);
494 return -1;
495 }
496 gfile_close(tpsfile);
497
498 code = copy_eps(doc, tpsname, bbox, hires_bbox,
499 DOSEPS_HEADER_SIZE, FALSE);
500 if (code) {
501 if (!(debug & DEBUG_GENERAL))
502 csunlink(tiffname);
503 return -1;
504 }
505
506
507 if ( (tpsfile = gfile_open(tpsname, gfile_modeRead)) == (GFile *)NULL) {
508 app_csmsgf(doc->app,
509 TEXT("Can't open temporary EPS file \042%s\042\n"),
510 tpsname);
511 if (!(debug & DEBUG_GENERAL))
512 csunlink(tiffname);
513 return -1;
514 }
515
516 /* Create DOS EPS output file */
517 epsfile = gfile_open(epsname, gfile_modeWrite | gfile_modeCreate);
518 if (epsfile == (GFile *)NULL) {
519 app_csmsgf(doc->app,
520 TEXT("Can't open output EPS file \042%s\042\n"),
521 epsname);
522 if (!(debug & DEBUG_GENERAL))
523 csunlink(tiffname);
524 gfile_close(tpsfile);
525 if (!(debug & DEBUG_GENERAL))
526 csunlink(tpsname);
527 return -1;
528 }
529
530 buffer = (char *)malloc(COPY_BUF_SIZE);
531 if (buffer == (char *)NULL) {
532 if (epsname[0]) {
533 gfile_close(epsfile);
534 if (!(debug & DEBUG_GENERAL))
535 csunlink(epsname);
536 }
537 if (!(debug & DEBUG_GENERAL))
538 csunlink(tiffname);
539 gfile_close(tpsfile);
540 if (!(debug & DEBUG_GENERAL))
541 csunlink(tpsname);
542 return -1;
543 }
544
545 if ((tiff_file = gfile_open(tiffname, gfile_modeRead)) == (GFile *)NULL) {
546 app_csmsgf(doc->app,
547 TEXT("Can't open temporary TIFF file \042%s\042\n"),
548 tiffname);
549 free(buffer);
550 if (!(debug & DEBUG_GENERAL))
551 csunlink(tiffname);
552 gfile_close(tpsfile);
553 if (!(debug & DEBUG_GENERAL))
554 csunlink(tpsname);
555 if (epsname[0]) {
556 gfile_close(epsfile);
557 if (!(debug & DEBUG_GENERAL))
558 csunlink(epsname);
559 }
560 return -1;
561 }
562 doseps.ps_length = (GSDWORD)gfile_get_length(tpsfile);
563 doseps.wmf_begin = 0;
564 doseps.wmf_length = 0;
565 doseps.tiff_length = (GSDWORD)gfile_get_length(tiff_file);
566 if (reverse) {
567 doseps.tiff_begin = DOSEPS_HEADER_SIZE;
568 doseps.ps_begin = doseps.tiff_begin + doseps.tiff_length;
569 }
570 else {
571 doseps.ps_begin = DOSEPS_HEADER_SIZE;
572 doseps.tiff_begin = doseps.ps_begin + doseps.ps_length;
573 }
574 doseps.checksum = 0xffff;
575 write_doseps_header(&doseps, epsfile);
576
577 gfile_seek(tpsfile, 0, gfile_begin);
578 if (!reverse) {
579 /* copy EPS file */
580 while ((count = (int)gfile_read(tpsfile, buffer, COPY_BUF_SIZE)) != 0)
581 gfile_write(epsfile, buffer, count);
582 }
583
584 /* copy tiff file */
585 gfile_seek(tiff_file, 0, gfile_begin);
586 while ((count = (int)gfile_read(tiff_file, buffer, COPY_BUF_SIZE)) != 0)
587 gfile_write(epsfile, buffer, count);
588
589 if (reverse) {
590 /* copy EPS file */
591 while ((count = (int)gfile_read(tpsfile, buffer, COPY_BUF_SIZE)) != 0)
592 gfile_write(epsfile, buffer, count);
593 }
594
595 free(buffer);
596 gfile_close(tiff_file);
597 if (!(debug & DEBUG_GENERAL))
598 csunlink(tiffname);
599 gfile_close(tpsfile);
600 if (!(debug & DEBUG_GENERAL))
601 csunlink(tpsname);
602 gfile_close(epsfile);
603 return 0;
604 }
605
606 /*********************************************************/
607
608 static char hex[17] = "0123456789ABCDEF";
609
610 #define MAXHEXWIDTH 70
611
612 /* Write interchange preview to file f */
613 /* Does not copy the file itself */
614 int
615 write_interchange(GFile *f, IMAGE *img, CDSCBBOX devbbox)
616 {
617 int i, j;
618 unsigned char *preview;
619 char buf[MAXSTR];
620 const char *eol_str = EOLSTR;
621 const char *endpreview_str = "%%EndPreview";
622 BYTE *line;
623 int preview_width, bwidth;
624 int lines_per_scan;
625 int topfirst = ((img->format & DISPLAY_FIRSTROW_MASK) == DISPLAY_TOPFIRST);
626 char hexline[MAXHEXWIDTH+6];
627 int hexcount = 0;
628 unsigned int value;
629 unsigned int depth = 8;
630
631 validate_devbbox(img, &devbbox);
632
633 switch (img->format & DISPLAY_COLORS_MASK) {
634 case DISPLAY_COLORS_NATIVE:
635 case DISPLAY_COLORS_GRAY:
636 if ((img->format & DISPLAY_DEPTH_MASK) == DISPLAY_DEPTH_1)
637 depth = 1;
638 }
639
640 switch (depth) {
641 case 1:
642 /* byte width of interchange preview with 1 bit/pixel */
643 bwidth = (((devbbox.urx-devbbox.llx) + 7) & ~7) >> 3;
644 /* byte width of intermediate preview with 1 bit/pixel */
645 preview_width = ((img->width + 7) & ~7) >> 3;
646 break;
647 case 8:
648 bwidth = devbbox.urx-devbbox.llx;
649 preview_width = img->width;
650 break;
651 default:
652 return -1;
653 }
654
655 preview = (unsigned char *) malloc(preview_width);
656
657 lines_per_scan = (bwidth + (MAXHEXWIDTH/2) - 1) / (MAXHEXWIDTH/2);
658 buf[sizeof(buf)-1] = '\0';
659 snprintf(buf, MAXSTR-1, "%%%%BeginPreview: %u %u %u %u%s",
660 (devbbox.urx-devbbox.llx), (devbbox.ury-devbbox.lly), depth,
661 (devbbox.ury-devbbox.lly)*lines_per_scan, eol_str);
662 gfile_puts(f, buf);
663
664 if (topfirst)
665 line = img->image + img->raster * (img->height - devbbox.ury);
666 else
667 line = img->image + img->raster * (devbbox.ury-1);
668
669 /* process each line of bitmap */
670 for (i = 0; i < (devbbox.ury-devbbox.lly); i++) {
671 memset(preview,0xff,preview_width);
672 if (depth == 1) {
673 image_to_mono(img, preview, line);
674 if (devbbox.llx)
675 shift_preview(preview, preview_width, devbbox.llx);
676 }
677 else {
678 image_to_grey(img, preview, line);
679 if (devbbox.llx)
680 memmove(preview, preview+devbbox.llx, preview_width);
681 }
682 hexcount = 0;
683 hexline[hexcount++] = '%';
684 hexline[hexcount++] = ' ';
685 for (j=0; j<bwidth; j++) {
686 if (hexcount >= 2 + MAXHEXWIDTH) {
687 if (strlen(eol_str) <= sizeof(hexline)-hexcount) {
688 memcpy(hexline+hexcount, eol_str, strlen(eol_str));
689 hexcount += (int)strlen(eol_str);
690 }
691 gfile_write(f, hexline, hexcount);
692 hexcount = 0;
693 hexline[hexcount++] = '%';
694 hexline[hexcount++] = ' ';
695 }
696 value = preview[j];
697 if (depth == 8)
698 value = 255 - value;
699 hexline[hexcount++] = hex[(value>>4)&15];
700 hexline[hexcount++] = hex[value&15];
701 }
702 if (hexcount && (strlen(eol_str) <= sizeof(hexline)-hexcount)) {
703 memcpy(hexline+hexcount, eol_str, strlen(eol_str));
704 hexcount += (int)strlen(eol_str);
705 }
706 if (hexcount)
707 gfile_write(f, hexline, hexcount);
708
709 if (topfirst)
710 line += img->raster;
711 else
712 line -= img->raster;
713
714 }
715
716
717 gfile_puts(f, endpreview_str);
718 gfile_puts(f, eol_str);
719 free(preview);
720
721 return 0;
722 }
723
724 /*********************************************************/
725
726 typedef enum PREVIEW_TYPE_e {
727 PREVIEW_UNKNOWN = 0,
728 PREVIEW_TIFF = 1,
729 PREVIEW_WMF = 2
730 } PREVIEW_TYPE;
731
732 /* Make a DOS EPS file from a PS file and a user supplied preview.
733 * Preview may be WMF or TIFF.
734 * Returns 0 on success.
735 */
736 int
737 make_eps_user(Doc *doc, LPCTSTR preview_name, BOOL reverse, LPCTSTR epsname)
738 {
739 GFile *epsfile;
740 GFile *preview_file;
741 unsigned long preview_length;
742 unsigned char id[4];
743 PREVIEW_TYPE type = PREVIEW_UNKNOWN;
744 CDSCDOSEPS doseps;
745 char *buffer;
746 unsigned int count;
747 GFile *tpsfile;
748 TCHAR tpsname[MAXSTR];
749
750 if ((preview_name == NULL) || preview_name[0] == '\0')
751 return -1;
752 if (doc->dsc == NULL)
753 return -1;
754
755 /* open preview, determine length and type */
756 preview_file = gfile_open(preview_name, gfile_modeRead);
757 if (preview_file == (GFile *)NULL) {
758 app_csmsgf(doc->app, TEXT("Can't open preview file \042%s\042\n"),
759 preview_name);
760 return -1;
761 }
762
763 /* Determine type of preview */
764 gfile_read(preview_file, id, 4);
765 preview_length = (GSDWORD)gfile_get_length(preview_file);
766 gfile_seek(preview_file, 0, gfile_begin);
767
768 if ((id[0] == 'I') && (id[1] == 'I'))
769 type = PREVIEW_TIFF;
770 if ((id[0] == 'M') && (id[1] == 'M'))
771 type = PREVIEW_TIFF;
772 if ((id[0] == 0x01) && (id[1] == 0x00) &&
773 (id[2] == 0x09) && (id[3] == 0x00))
774 type = PREVIEW_WMF;
775 if ((id[0] == 0xd7) && (id[1] == 0xcd) &&
776 (id[2] == 0xc6) && (id[3] == 0x9a)) {
777 type = PREVIEW_WMF;
778 preview_length -= 22; /* skip over placeable metafile header */
779 gfile_seek(preview_file, 22, gfile_begin);
780 }
781
782 if (type == PREVIEW_UNKNOWN) {
783 app_csmsgf(doc->app,
784 TEXT("Preview file \042%s\042 is not TIFF or Windows Metafile\n"),
785 preview_name);
786 gfile_close(preview_file);
787 return -1;
788 }
789
790 /* Create temporary EPS file containing all that is needed
791 * including updated header and trailer.
792 */
793 tpsfile = NULL;
794 memset(tpsname, 0, sizeof(tpsname));
795 if ((tpsfile = app_temp_gfile(doc->app, tpsname,
796 sizeof(tpsname)/sizeof(TCHAR))) == (GFile *)NULL) {
797 app_csmsgf(doc->app,
798 TEXT("Can't create temporary EPS file \042%s\042\n"),
799 tpsname);
800 gfile_close(preview_file);
801 return -1;
802 }
803 gfile_close(tpsfile);
804
805 if (copy_eps(doc, tpsname, doc->dsc->bbox, doc->dsc->hires_bbox,
806 DOSEPS_HEADER_SIZE, FALSE) < 0)
807 return -1;
808
809
810 if ( (tpsfile = gfile_open(tpsname, gfile_modeRead)) == (GFile *)NULL) {
811 app_csmsgf(doc->app,
812 TEXT("Can't open temporary EPS file \042%s\042\n"),
813 tpsname);
814 gfile_close(preview_file);
815 return -1;
816 }
817
818
819 /* Create EPS output file */
820 epsfile = gfile_open(epsname, gfile_modeWrite | gfile_modeCreate);
821
822 if (epsfile == (GFile *)NULL) {
823 app_csmsgf(doc->app,
824 TEXT("Can't open EPS output file \042%s\042\n"),
825 epsname);
826 gfile_close(preview_file);
827 gfile_close(tpsfile);
828 if (!(debug & DEBUG_GENERAL))
829 csunlink(tpsname);
830 return -1;
831 }
832
833 /* write DOS EPS binary header */
834 doseps.ps_length = (GSDWORD)gfile_get_length(tpsfile);
835 if (type == PREVIEW_WMF) {
836 doseps.wmf_length = preview_length;
837 doseps.tiff_begin = 0;
838 doseps.tiff_length = 0;
839 if (reverse) {
840 doseps.wmf_begin = DOSEPS_HEADER_SIZE;
841 doseps.ps_begin = doseps.wmf_begin + doseps.wmf_length;
842 }
843 else {
844 doseps.ps_begin = DOSEPS_HEADER_SIZE;
845 doseps.wmf_begin = doseps.ps_begin + doseps.ps_length;
846 }
847 }
848 else {
849 doseps.wmf_begin = 0;
850 doseps.wmf_length = 0;
851 doseps.tiff_length = preview_length;
852 if (reverse) {
853 doseps.tiff_begin = DOSEPS_HEADER_SIZE;
854 doseps.ps_begin = doseps.tiff_begin + doseps.tiff_length;
855 }
856 else {
857 doseps.ps_begin = DOSEPS_HEADER_SIZE;
858 doseps.tiff_begin = doseps.ps_begin + doseps.ps_length;
859 }
860 }
861 doseps.checksum = 0xffff;
862 write_doseps_header(&doseps, epsfile);
863
864 buffer = (char *)malloc(COPY_BUF_SIZE);
865 if (buffer == (char *)NULL) {
866 app_csmsgf(doc->app, TEXT("Out of memory in make_eps_user\n"));
867 if (epsname[0]) {
868 gfile_close(epsfile);
869 if (!(debug & DEBUG_GENERAL))
870 csunlink(epsname);
871 }
872 gfile_close(preview_file);
873 gfile_close(tpsfile);
874 if (!(debug & DEBUG_GENERAL))
875 csunlink(tpsname);
876 return -1;
877 }
878
879 gfile_seek(tpsfile, 0, gfile_begin);
880 if (!reverse) {
881 /* copy EPS file */
882 while ((count = (int)gfile_read(tpsfile, buffer, COPY_BUF_SIZE)) != 0)
883 gfile_write(epsfile, buffer, count);
884 }
885
886 /* copy preview file */
887 while ((count = (int)gfile_read(preview_file, buffer, COPY_BUF_SIZE)) != 0)
888 gfile_write(epsfile, buffer, count);
889
890 if (reverse) {
891 /* copy EPS file */
892 while ((count = (int)gfile_read(tpsfile, buffer, COPY_BUF_SIZE)) != 0)
893 gfile_write(epsfile, buffer, count);
894 }
895
896 free(buffer);
897 gfile_close(tpsfile);
898 if (!(debug & DEBUG_GENERAL))
899 csunlink(tpsname);
900 gfile_close(preview_file);
901 gfile_close(epsfile);
902 return 0; /* success */
903 }
904
905
906 /*********************************************************/
907
908 typedef struct tagMFH {
909 WORD type;
910 WORD headersize;
911 WORD version;
912 DWORD size;
913 WORD nobj;
914 DWORD maxrec;
915 WORD noparam;
916 } MFH;
917
918 int write_metafile(GFile *f, IMAGE *img, CDSCBBOX devbbox,
919 float xdpi, float ydpi, MFH *mf);
920 static int metafile_init(IMAGE *img, CDSCBBOX *pdevbbox, MFH* mf);
921
922 /* A metafile object must not be larger than 64k */
923 /* Metafile bitmap object contains metafile header, */
924 /* bitmap header, palette and bitmap bits */
925 #define MAX_METAFILE_BITMAP 64000L /* max size of bitmap bits */
926
927 static int
928 metafile_init(IMAGE *img, CDSCBBOX *pdevbbox, MFH* mf)
929 {
930 int wx, wy;
931 int ny, nylast;
932 int complete, partial;
933 int bytewidth;
934 int palcount;
935 unsigned long size;
936 int depth = image_depth(img);
937
938 switch (depth) {
939 case 1:
940 case 4:
941 case 8:
942 case 24:
943 break;
944 default:
945 /* unsupported format */
946 return -1;
947 }
948
949 validate_devbbox(img, pdevbbox);
950
951 wx = pdevbbox->urx - pdevbbox->llx;
952 wy = pdevbbox->ury - pdevbbox->lly;
953 bytewidth = (( wx * depth + 31) & ~31) >> 3;
954 ny = (int)(MAX_METAFILE_BITMAP / bytewidth);
955 if (depth == 24)
956 palcount = 0;
957 else
958 palcount = 1<<depth;
959
960 complete = wy / ny;
961 nylast = wy % ny;
962 partial = nylast ? 1 : 0;
963
964 mf->type = 1; /* metafile in file */
965 mf->headersize = 9; /* 9 WORDs */
966 mf->version = 0x300; /* Windows 3.0 */
967 mf->size = /* sizes in WORDs */
968 9UL + /* header */
969 5 + /* SetWindowOrg */
970 5; /* SetWindowExt */
971 /* complete StretchDIBits */
972 mf->size += 14*complete;
973 size = (40L + palcount*4L + (unsigned long)ny*(unsigned long)bytewidth)/2L;
974 mf->size += size * (unsigned long)complete;
975 /* partial StretchDIBits */
976 mf->size += 14*partial;
977 size = (40L + palcount*4L + (unsigned long)nylast*(unsigned long)bytewidth)/2L;
978 mf->size += size * (unsigned long)partial;
979 mf->size += 3; /* end marker */
980
981 mf->nobj = 0;
982 size = complete ?
983 (40L + palcount*4L + (unsigned long)ny*(unsigned long)bytewidth)/2L
984 : (40L + palcount*4L + (unsigned long)nylast*(unsigned long)bytewidth)/2L;
985 mf->maxrec = 14L + size;
986 mf->noparam = 0;
987 return 0;
988 }
989
990
991
992 /* convert the display bitmap to a metafile picture */
993 int
994 write_metafile(GFile *f, IMAGE *img, CDSCBBOX devbbox,
995 float xdpi, float ydpi, MFH *mf)
996 {
997 int i;
998 int wx;
999 int ny, sy, dy, wy;
1000 BYTE *line;
1001 BYTE *line2;
1002 LPBITMAP2 pbmi;
1003 int bsize;
1004 int bitoffset;
1005 int bytewidth, activewidth;
1006 int palcount;
1007 unsigned long size;
1008 int depth = image_depth(img);
1009 int topfirst = ((img->format & DISPLAY_FIRSTROW_MASK) == DISPLAY_TOPFIRST);
1010
1011 dy = 0;
1012 wx = devbbox.urx - devbbox.llx;
1013 sy = devbbox.lly;
1014 wy = devbbox.ury - devbbox.lly;
1015 bitoffset = (devbbox.llx * depth);
1016 bytewidth = (( wx * depth + 31) & ~31) >> 3;
1017 activewidth = (( wx * depth + 7) & ~7) >> 3;
1018 ny = (int)(MAX_METAFILE_BITMAP / bytewidth);
1019 if (depth == 24)
1020 palcount = 0;
1021 else
1022 palcount = 1<<depth;
1023
1024 /* create and initialize a BITMAPINFO for the <64k bitmap */
1025 bsize = sizeof(BITMAP2) + palcount * RGB4_LENGTH;
1026 pbmi = (LPBITMAP2)malloc(bsize);
1027 if (pbmi == NULL) {
1028 return -1;
1029 }
1030 memset((char *)pbmi, 0, bsize);
1031 make_bmp_info(pbmi, img, xdpi, ydpi);
1032 pbmi->biClrUsed = 0; /* write out full palette */
1033 pbmi->biClrImportant = 0;
1034
1035 line2 = (BYTE *)malloc(img->raster);
1036 if (line2 == (BYTE *)NULL)
1037 return -1;
1038 pbmi->biWidth = wx;
1039
1040 if (topfirst)
1041 line = img->image + img->raster * (img->height - devbbox.lly - 1);
1042 else
1043 line = img->image + img->raster * devbbox.lly;
1044
1045 /* write metafile header */
1046 write_word(mf->type, f);
1047 write_word(mf->headersize, f);
1048 write_word(mf->version, f);
1049 write_dword(mf->size, f);
1050 write_word(mf->nobj, f);
1051 write_dword(mf->maxrec, f);
1052 write_word(mf->noparam, f);
1053
1054 /* write SetWindowOrg */
1055 write_dword(5, f);
1056 write_word(0x20b, f);
1057 write_word(0, f);
1058 write_word(0, f);
1059
1060 /* write SetWindowExt */
1061 write_dword(5, f);
1062 write_word(0x20c, f);
1063 write_word((WORD)wy, f);
1064 write_word((WORD)wx, f);
1065
1066 /* copy in chunks < 64k */
1067 for ( ; wy > ny; dy += ny, wy -= ny, sy += ny ) {
1068 pbmi->biHeight = ny;
1069
1070 size = BITMAP2_LENGTH + (palcount * RGB4_LENGTH)
1071 + (unsigned long)bytewidth * (unsigned long)ny;
1072 /* write StretchDIBits header */
1073 write_dword(14 + size/2L, f);
1074 write_word(0x0f43, f);
1075 write_dword(0x00cc0020L, f); /* SRC_COPY */
1076 write_word(0, f); /* DIB_RGB_COLORS */
1077 write_word((WORD)ny, f); /* Source cy */
1078 write_word((WORD)wx, f); /* Source cx */
1079 write_word(0, f); /* Source y */
1080 write_word(0, f); /* Source x */
1081 write_word((WORD)ny, f); /* Dest cy */
1082 write_word((WORD)wx, f); /* Dest cx */
1083 write_word((WORD)(devbbox.ury - devbbox.lly - ny - dy), f);
1084 /* Dest y */
1085 write_word(0, f); /* Dest x */
1086
1087 /* write bitmap header */
1088 write_bitmap_info(img, pbmi, f);
1089
1090 /* write bitmap rows */
1091 for (i=0; i<ny; i++) {
1092 if (depth == 24)
1093 image_to_24BGR(img, line2, line);
1094 else
1095 memmove(line2, line, img->raster);
1096 shift_preview(line2, img->raster, bitoffset);
1097 if (activewidth < bytewidth)
1098 memset(line2+activewidth, 0xff, bytewidth-activewidth);
1099 gfile_write(f, line2, bytewidth);
1100 if (topfirst)
1101 line -= img->raster;
1102 else
1103 line += img->raster;
1104 }
1105
1106 }
1107
1108 /* write StretchDIBits header */
1109 pbmi->biHeight = wy;
1110 size = BITMAP2_LENGTH + (palcount * RGB4_LENGTH) +
1111 (unsigned long)bytewidth * (unsigned long)wy;
1112 write_dword(14 + size/2L, f);
1113 write_word(0x0f43, f);
1114 write_dword(0x00cc0020L, f); /* SRC_COPY */
1115 write_word(0, f); /* DIB_RGB_COLORS */
1116 write_word((WORD)wy, f); /* Source cy */
1117 write_word((WORD)wx, f); /* Source cx */
1118 write_word(0, f); /* Source y */
1119 write_word(0, f); /* Source x */
1120 write_word((WORD)wy, f); /* Dest cy */
1121 write_word((WORD)wx, f); /* Dest cx */
1122 write_word((WORD)(devbbox.ury - devbbox.lly - wy - dy), f); /* Dest y */
1123 write_word(0, f); /* Dest x */
1124
1125 /* write bitmap header */
1126 write_bitmap_info(img, pbmi, f);
1127
1128 /* copy last chunk */
1129 for (i=0; i<wy; i++) {
1130 if (depth == 24)
1131 image_to_24BGR(img, line2, line);
1132 else
1133 memmove(line2, line, img->raster);
1134 shift_preview(line2, img->raster, bitoffset);
1135 if (activewidth < bytewidth)
1136 memset(line2+activewidth, 0xff, bytewidth-activewidth);
1137 gfile_write(f, line2, bytewidth);
1138 if (topfirst)
1139 line -= img->raster;
1140 else
1141 line += img->raster;
1142 }
1143
1144 /* write end marker */
1145 write_dword(3, f);
1146 write_word(0, f);
1147
1148 free((char *)pbmi);
1149 free(line2);
1150
1151 return 0;
1152 }
1153
1154
1155 /*********************************************************/
1156
1157 /* Copy a DSC section, removing existing bounding boxes */
1158 void
1159 copy_nobbox(GFile *outfile, GFile *infile,
1160 FILE_POS begin, FILE_POS end)
1161 {
1162 const char bbox_str[] = "%%BoundingBox:";
1163 const char hiresbbox_str[] = "%%HiResBoundingBox:";
1164 char buf[DSC_LINE_LENGTH+1];
1165 int len;
1166 gfile_seek(infile, begin, gfile_begin);
1167 begin = gfile_get_position(infile);
1168 while (begin < end) {
1169 len = ps_fgets(buf, min(sizeof(buf)-1, end-begin), infile);
1170 begin = gfile_get_position(infile);
1171 if (len == 0) {
1172 return; /* EOF on input file */
1173 }
1174 else if (strncmp(buf, bbox_str, strlen(bbox_str)) == 0) {
1175 /* skip it */
1176 }
1177 else if (strncmp(buf, hiresbbox_str, strlen(hiresbbox_str)) == 0) {
1178 /* skip it */
1179 }
1180 else
1181 gfile_write(outfile, buf, len);
1182 }
1183 }
1184
1185 /* Copy a DSC header, removing existing bounding boxes
1186 * and adding new ones.
1187 */
1188 void
1189 copy_bbox_header(GFile *outfile,
1190 GFile *infile, FILE_POS begin, FILE_POS end,
1191 CDSCBBOX *bbox, CDSCFBBOX *hiresbbox)
1192 {
1193 char buf[DSC_LINE_LENGTH+1];
1194 int len;
1195
1196 memset(buf, 0, sizeof(buf)-1);
1197 gfile_seek(infile, begin, gfile_begin);
1198 len = ps_fgets(buf, min(sizeof(buf)-1, end-begin), infile);
1199 if (len)
1200 gfile_write(outfile, buf, len); /* copy version line */
1201 /* Add bounding box lines */
1202 if (bbox) {
1203 snprintf(buf, sizeof(buf)-1, "%%%%BoundingBox: %d %d %d %d\n",
1204 bbox->llx, bbox->lly, bbox->urx, bbox->ury);
1205 gfile_puts(outfile, buf);
1206 }
1207 if (hiresbbox) {
1208 snprintf(buf, sizeof(buf)-1, "%%%%HiResBoundingBox: %.3f %.3f %.3f %.3f\n",
1209 hiresbbox->fllx, hiresbbox->flly,
1210 hiresbbox->furx, hiresbbox->fury);
1211 gfile_puts(outfile, buf);
1212 }
1213
1214 begin = gfile_get_position(infile);
1215 copy_nobbox(outfile, infile, begin, end);
1216 }
1217
1218 /* return the length of the line less the EOL characters */
1219 static int
1220 without_eol(const char *str, int length)
1221 {
1222 int j;
1223 for (j=length-1; j>=0; j--) {
1224 if (!((str[j] == '\r') || (str[j] == '\n'))) {
1225 j++;
1226 break;
1227 }
1228 }
1229 if (j < 0)
1230 j = 0;
1231 return j;
1232 }
1233
1234 static BOOL is_process_colour(const char *name)
1235 {
1236 return (
1237 (dsc_stricmp(name, "Cyan")==0) ||
1238 (dsc_stricmp(name, "Magenta")==0) ||
1239 (dsc_stricmp(name, "Yellow")==0) ||
1240 (dsc_stricmp(name, "Black")==0)
1241 );
1242 }
1243
1244 static const char process_str[] = "%%DocumentProcessColors:";
1245 static const char custom_str[] = "%%DocumentCustomColors:";
1246 static const char cmyk_custom_str[] = "%%CMYKCustomColor:";
1247 static const char rgb_custom_str[] = "%%RGBCustomColor:";
1248 static const char eol_str[] = EOLSTR;
1249
1250 static const char *
1251 separation_name(RENAME_SEPARATION *rs, const char *name)
1252 {
1253 RENAME_SEPARATION *s;
1254 const char *newname = name;
1255 for (s=rs; s; s=s->next) {
1256 if (strcmp(s->oldname, name) == 0) {
1257 newname = s->newname;
1258 break;
1259 }
1260 }
1261 return newname;
1262 }
1263
1264 /*
1265 * Set renamed to the names of the renamed separations.
1266 * renamed[] must be as long as dsc->page_count.
1267 * Return 0 on success, or -1 if a separation name appears twice.
1268 */
1269 int
1270 rename_separations(CDSC *dsc, RENAME_SEPARATION *rs, const char *renamed[])
1271 {
1272 int duplicated = 0;
1273 int i, j;
1274 const char *sepname;
1275 renamed[0] = dsc->page[0].label;
1276 for (i=1; i<(int)dsc->page_count; i++) {
1277 sepname = separation_name(rs, dsc->page[i].label);
1278 /* Check if this is a duplicate separation, in which case
1279 * we don't want to rename it twice.
1280 */
1281 for (j=1; j<i; j++)
1282 if (strcmp(dsc->page[j].label, dsc->page[i].label) == 0) {
1283 sepname = NULL; /* don't do it */
1284 duplicated = 1;
1285 }
1286 /* If the separation name already exists in the renamed
1287 * list, don't rename it */
1288 if (sepname) {
1289 for (j=1; j<i; j++) {
1290 if (strcmp(renamed[j], sepname) == 0) {
1291 sepname = NULL; /* don't do it */
1292 duplicated = 1;
1293 break;
1294 }
1295 }
1296 }
1297 if (sepname == NULL)
1298 sepname = dsc->page[i].label;
1299 renamed[i] = sepname;
1300 }
1301 if (duplicated)
1302 return -1; /* clash in separation names */
1303 return 0;
1304 }
1305
1306 /* Find separation begin and end */
1307 static int
1308 dcs2_separation(CDSC *dsc, int pagenum,
1309 const char **fname, FILE_POS *pbegin, FILE_POS *pend)
1310 {
1311 GFile *f;
1312 TCHAR wfname[MAXSTR];
1313 *fname = dsc_find_platefile(dsc, pagenum);
1314 if (*fname) {
1315 narrow_to_cs(wfname, (int)sizeof(wfname), *fname,
1316 (int)strlen(*fname)+1);
1317 if ((f = gfile_open(wfname, gfile_modeRead)) != (GFile *)NULL) {
1318 *pbegin = 0;
1319 *pend = gfile_get_length(f);
1320 gfile_close(f);
1321 }
1322 else {
1323 /* Separation file didn't exist */
1324 *pbegin = *pend = 0;
1325 return 1;
1326 }
1327 }
1328 else {
1329 *pbegin = dsc->page[pagenum].begin;
1330 *pend = dsc->page[pagenum].end;
1331 }
1332 return 0;
1333 }
1334
1335
1336 static int
1337 fix_custom(Doc *doc, char *buf, int buflen, const char *renamed[])
1338 {
1339 /* Create a new %%DocumentCustomColors:
1340 * containing only those separations that exist
1341 */
1342 CDSC *dsc = doc->dsc;
1343 int i;
1344 int missing;
1345 int n = 0;
1346 FILE_POS begin, end;
1347 const char *fname;
1348 int count = min((int)strlen(buf), buflen);
1349 if ((dsc == NULL) || !dsc->dcs2)
1350 return 0;
1351 for (i=1; i<(int)dsc->page_count; i++) {
1352 const char *sepname = renamed[i];
1353 missing = dcs2_separation(dsc, i, &fname, &begin, &end);
1354 if (!missing && !is_process_colour(sepname)) {
1355 n++;
1356 strncpy(buf+count, " (", buflen-count-1);
1357 count = (int)strlen(buf);
1358 strncpy(buf+count, sepname, buflen-count-1);
1359 count = (int)strlen(buf);
1360 strncpy(buf+count, ")", buflen-count-1);
1361 count = (int)strlen(buf);
1362 }
1363 }
1364 return n;
1365 }
1366
1367 static int
1368 fix_process(Doc *doc, char *buf, int buflen, const char *renamed[])
1369 {
1370 /* Create a new %%DocumentProcessColors:
1371 * containing only those separations that exist
1372 */
1373 CDSC *dsc = doc->dsc;
1374 int i;
1375 int n = 0;
1376 int missing;
1377 FILE_POS begin, end;
1378 const char *fname;
1379 int count = min((int)strlen(buf), buflen);
1380 if ((dsc == NULL) || !dsc->dcs2)
1381 return 0;
1382 for (i=1; i<(int)dsc->page_count; i++) {
1383 const char *sepname = renamed[i];
1384 missing = dcs2_separation(dsc, i, &fname, &begin, &end);
1385 if (!missing && is_process_colour(sepname)) {
1386 n++;
1387 strncpy(buf+count, " ", buflen-count-1);
1388 count++;
1389 strncpy(buf+count, sepname, buflen-count-1);
1390 count = (int)strlen(buf);
1391 }
1392 }
1393 return n;
1394 }
1395
1396 /* Write out %%CMYKCustomColor line and extensions.
1397 * count is the number of lines already written.
1398 */
1399 static int
1400 write_cmyk_custom(GFile *gf, Doc *doc, const char *renamed[], int count)
1401 {
1402 /* Create a new %%CMYKCustomColor:
1403 * containing only those colours that exist
1404 */
1405 CDSC *dsc = doc->dsc;
1406 CDSCCOLOUR *colour;
1407 int i;
1408 int missing;
1409 int n = count;
1410 FILE_POS begin, end;
1411 const char *fname;
1412 char buf[MAXSTR];
1413 if ((dsc == NULL) || !dsc->dcs2)
1414 return 0;
1415 buf[sizeof(buf)-1] = '\0';
1416 for (i=1; i<(int)dsc->page_count; i++) {
1417 const char *sepname = renamed[i];
1418 missing = dcs2_separation(dsc, i, &fname, &begin, &end);
1419 if (!missing && !is_process_colour(sepname)) {
1420 /* find colour values */
1421 for (colour=dsc->colours; colour; colour=colour->next) {
1422 if (strcmp(colour->name, dsc->page[i].label)==0)
1423 break;
1424 }
1425 if ((colour != NULL) &&
1426 (colour->custom == CDSC_CUSTOM_COLOUR_CMYK)) {
1427 if (n == 0)
1428 strncpy(buf, cmyk_custom_str, sizeof(buf)-1);
1429 else
1430 strncpy(buf, "%%+", sizeof(buf)-1);
1431 snprintf(buf+strlen(buf), sizeof(buf)-1-strlen(buf),
1432 " %g %g %g %g (%s)",
1433 colour->cyan, colour->magenta, colour->yellow,
1434 colour->black, sepname);
1435 gfile_puts(gf, buf);
1436 gfile_puts(gf, eol_str);
1437 n++;
1438 }
1439 }
1440 }
1441 return n;
1442 }
1443
1444 /* Write out %%RGBCustomColor line and extensions.
1445 * count is the number of lines already written.
1446 */
1447 static int
1448 write_rgb_custom(GFile *gf, Doc *doc, const char *renamed[], int count)
1449 {
1450 /* Create a new %%RGBCustomColor:
1451 * containing only those colours that exist
1452 */
1453 CDSC *dsc = doc->dsc;
1454 CDSCCOLOUR *colour;
1455 int i;
1456 int missing;
1457 int n = count;
1458 FILE_POS begin, end;
1459 const char *fname;
1460 char buf[MAXSTR];
1461 if ((dsc == NULL) || !dsc->dcs2)
1462 return 0;
1463 buf[sizeof(buf)-1] = '\0';
1464 for (i=1; i<(int)dsc->page_count; i++) {
1465 const char *sepname = renamed[i];
1466 missing = dcs2_separation(dsc, i, &fname, &begin, &end);
1467 if (!missing && !is_process_colour(sepname)) {
1468 /* find colour values */
1469 for (colour=dsc->colours; colour; colour=colour->next) {
1470 if (strcmp(colour->name, dsc->page[i].label)==0)
1471 break;
1472 }
1473 if ((colour != NULL) &&
1474 (colour->custom == CDSC_CUSTOM_COLOUR_RGB)) {
1475 if (n == 0)
1476 strncpy(buf, cmyk_custom_str, sizeof(buf)-1);
1477 else
1478 strncpy(buf, "%%+", sizeof(buf)-1);
1479 snprintf(buf+strlen(buf), sizeof(buf)-1-strlen(buf),
1480 " %g %g %g (%s)",
1481 colour->red, colour->green, colour->blue,
1482 sepname);
1483 gfile_puts(gf, buf);
1484 gfile_puts(gf, eol_str);
1485 n++;
1486 }
1487 }
1488 }
1489 return n;
1490 }
1491
1492 /* Write out DCS2 platefile comments, and any multiple file separations */
1493 static FILE_POS
1494 write_platefile_comments(Doc *doc, GFile *docfile,
1495 GFile *epsfile, LPCTSTR epsname,
1496 int offset, FILE_POS file_offset,
1497 BOOL dcs2_multi, BOOL write_all, BOOL missing_separations,
1498 const char *renamed[], BOOL some_renamed)
1499 {
1500 int i;
1501 CDSC *dsc = doc->dsc;
1502 FILE_POS begin, end;
1503 FILE_POS len;
1504 char platename[MAXSTR];
1505 char outbuf[MAXSTR];
1506 GFile *f;
1507 FILE_POS offset2 = 0;
1508
1509 /* Now write the platefile comments */
1510 for (i=1; i<(int)dsc->page_count; i++) {
1511 /* First find length of separation */
1512 int missing;
1513 const char *fname = NULL;
1514 const char *sepname = renamed[i];
1515 missing = dcs2_separation(dsc, i, &fname, &begin, &end);
1516 len = end - begin;
1517 /* Now write out platefile */
1518 if (missing && (missing_separations || some_renamed)) {
1519 if (debug & DEBUG_GENERAL)
1520 app_msgf(doc->app,
1521 "Skipping missing separation page %d \042%s\042\n",
1522 i, dsc->page[i].label);
1523 }
1524 else if (dcs2_multi) {
1525 int j;
1526 int duplicate = 0;
1527 memset(platename, 0, sizeof(platename));
1528 cs_to_narrow(platename, sizeof(platename)-1, epsname,
1529 (int)cslen(epsname)+1);
1530 strncat(platename, ".", sizeof(platename) - strlen(platename));
1531 strncat(platename, sepname, sizeof(platename) - strlen(platename));
1532 for (j=1; j<i; j++) {
1533 /* Check if separation name is a duplicate */
1534 if (strcmp(sepname, renamed[j]) == 0)
1535 duplicate = 1;
1536 }
1537 if (duplicate) /* append page number to make the filename unique */
1538 snprintf(platename+strlen(platename),
1539 sizeof(platename) - strlen(platename),
1540 ".%d", i);
1541 snprintf(outbuf, sizeof(outbuf)-1,
1542 "%%%%PlateFile: (%s) EPS Local %s",
1543 sepname, platename);
1544 gfile_puts(epsfile, outbuf);
1545 gfile_puts(epsfile, eol_str); /* change EOL */
1546 if (write_all) {
1547 /* Write out multi file separations */
1548 TCHAR wfname[MAXSTR];
1549 GFile *pf;
1550 narrow_to_cs(wfname, (int)sizeof(wfname), platename,
1551 (int)strlen(platename)+1);
1552 pf = gfile_open(wfname, gfile_modeWrite | gfile_modeCreate);
1553 if (pf != (GFile *)NULL) {
1554 const char *fname = dsc_find_platefile(dsc, i);
1555 if (fname) {
1556 narrow_to_cs(wfname, (int)sizeof(wfname),
1557 fname, (int)strlen(fname)+1);
1558 if ((f = gfile_open(wfname, gfile_modeRead))
1559 != (GFile *)NULL) {
1560 ps_copy(pf, f, begin, end);
1561 gfile_close(f);
1562 }
1563 }
1564 else {
1565 ps_copy(pf, docfile, begin, end);
1566 }
1567 gfile_close(pf);
1568 }
1569 else {
1570 return (FILE_POS)-1; /* error */
1571 }
1572 }
1573 }
1574 else {
1575 char fmtbuf[MAXSTR];
1576 snprintf(fmtbuf, sizeof(fmtbuf)-1,
1577 "%%%%%%%%PlateFile: (%%s) EPS #%%010%s %%010%s",
1578 DSC_OFFSET_FORMAT, DSC_OFFSET_FORMAT);
1579 snprintf(outbuf, sizeof(outbuf)-1, fmtbuf,
1580 sepname, offset+file_offset+offset2, len);
1581 gfile_puts(epsfile, outbuf);
1582 gfile_puts(epsfile, eol_str); /* change EOL */
1583 offset2 += len;
1584 }
1585 }
1586 return offset2;
1587 }
1588
1589 /* Write out DCS2 single file separations */
1590 static FILE_POS
1591 write_singlefile_separations(Doc *doc, GFile *docfile,
1592 GFile *epsfile,
1593 BOOL dcs2_multi, BOOL write_all, BOOL missing_separations,
1594 BOOL some_renamed)
1595 {
1596 int i;
1597 CDSC *dsc = doc->dsc;
1598 FILE_POS begin, end;
1599 FILE_POS len;
1600 GFile *f;
1601 if (write_all && !dcs2_multi) {
1602 for (i=1; i<(int)dsc->page_count; i++) {
1603 int missing;
1604 const char *fname = NULL;
1605 missing = dcs2_separation(dsc, i, &fname, &begin, &end);
1606 len = end - begin;
1607 if (missing && (missing_separations || some_renamed)) {
1608 if (debug & DEBUG_GENERAL)
1609 app_msgf(doc->app,
1610 "Skipping missing separation page %d \042%s\042\n",
1611 i, dsc->page[i].label);
1612 }
1613 else if (fname) {
1614 TCHAR wfname[MAXSTR];
1615 narrow_to_cs(wfname, (int)sizeof(wfname), fname,
1616 (int)strlen(fname)+1);
1617 if ((f = gfile_open(wfname, gfile_modeRead)) != (GFile *)NULL) {
1618 begin = 0;
1619 end = gfile_get_length(f);
1620 if (debug & DEBUG_GENERAL)
1621 app_msgf(doc->app,
1622 "Copying page %d from \042%s\042 %ld %ld\n",
1623 i, fname, begin, end);
1624 ps_copy(epsfile, f, begin, end);
1625 gfile_close(f);
1626 }
1627 }
1628 else {
1629 begin = dsc->page[i].begin;
1630 end = dsc->page[i].end;
1631 if (debug & DEBUG_GENERAL)
1632 app_msgf(doc->app,
1633 "Copying page %d %ld %ld\n",
1634 i, fname, begin, end);
1635 ps_copy(epsfile, docfile, begin, end);
1636 }
1637 }
1638 }
1639 return 0;
1640 }
1641
1642 /* Check that two DCS2 files can be combined */
1643 static int
1644 check_dcs2_combine(Doc *doc1, Doc *doc2,
1645 const char **renamed1, const char **renamed2, int tolerance)
1646 {
1647 CDSC *dsc1;
1648 CDSC *dsc2;
1649 const char *sepname1;
1650 const char *sepname2;
1651 int i, j;
1652
1653 if (doc1 == NULL)
1654 return -1;
1655 if (doc2 == NULL)
1656 return -1;
1657 dsc1 = doc1->dsc;
1658 dsc2 = doc2->dsc;
1659 if (!dsc1->dcs2)
1660 return -1;
1661 if (!dsc2->dcs2)
1662 return -1;
1663 if (dsc1->bbox == NULL)
1664 return -1;
1665 if (dsc2->bbox == NULL)
1666 return -1;
1667 /* Check that bounding boxes match */
1668 if ((dsc1->bbox->llx > dsc2->bbox->llx + tolerance) ||
1669 (dsc1->bbox->llx < dsc2->bbox->llx - tolerance) ||
1670 (dsc1->bbox->lly > dsc2->bbox->lly + tolerance) ||
1671 (dsc1->bbox->lly < dsc2->bbox->lly - tolerance) ||
1672 (dsc1->bbox->urx > dsc2->bbox->urx + tolerance) ||
1673 (dsc1->bbox->urx < dsc2->bbox->urx - tolerance) ||
1674 (dsc1->bbox->ury > dsc2->bbox->ury + tolerance) ||
1675 (dsc1->bbox->ury < dsc2->bbox->ury - tolerance)) {
1676 app_msgf(doc1->app, "Bounding Boxes don't match\n");
1677 return -1;
1678 }
1679 /* Check that separations don't conflict */
1680 for (i=1; i<(int)dsc1->page_count; i++) {
1681 sepname1 = renamed1[i];
1682 for (j=1; i<(int)dsc2->page_count; i++) {
1683 sepname2 = renamed2[j];
1684 if (strcmp(sepname1, sepname2) == 0) {
1685 app_msgf(doc1->app,
1686 "Separation \042%s\042 appears in both files\n",
1687 sepname1);
1688 return -1;
1689 }
1690 }
1691 }
1692 return 0;
1693 }
1694
1695 /* Copy a DCS 2.0 file.
1696 * DSC 2.0 as single file looks like concatenated EPS files.
1697 * DSC parser treats these as separate pages and the
1698 * entire first EPS file is contained in the first page.
1699 * That is, there is no header, prolog or trailer.
1700 * Don't update the bounding box.
1701 * Do update the %%PlateFile comments.
1702 * If missing_separations is true, remove the names of missing
1703 * separations from the DSC comments.
1704 * The length of the composite page is returned in complen.
1705 * If composite is not NULL, use this file as the new composite page
1706 * with the existing header.
1707 * If rs is not NULL, rename some separations.
1708 * If doc2 is not NULL, add its separations. It is an error if
1709 * separations are duplicated or the bounding box differs by more
1710 * than tolerance points.
1711 */
1712 int
1713 copy_dcs2(Doc *doc, GFile *docfile,
1714 Doc *doc2, GFile *docfile2,
1715 GFile *epsfile, LPCTSTR epsname,
1716 int offset, BOOL dcs2_multi, BOOL write_all, BOOL missing_separations,
1717 FILE_POS *complen, GFile *composite, RENAME_SEPARATION *rs,
1718 int tolerance)
1719 {
1720 const char platefile_str[] = "%%PlateFile:";
1721 const char cyanplate_str[] = "%%CyanPlate:";
1722 const char magentaplate_str[] = "%%MagentaPlate:";
1723 const char yellowplate_str[] = "%%YellowPlate:";
1724 const char blackplate_str[] = "%%BlackPlate:";
1725 const char endcomments_str[] = "%%EndComments";
1726 char buf[DSC_LINE_LENGTH+1];
1727 char outbuf[MAXSTR];
1728 CDSC *dsc = doc->dsc;
1729 FILE_POS len;
1730 FILE_POS file_offset = *complen;
1731 FILE_POS begin, end;
1732 FILE_POS header_position;
1733 BOOL found_endheader = FALSE;
1734 BOOL ignore_continuation = FALSE;
1735 int count;
1736 const char **renamed1 = NULL;
1737 const char **renamed2 = NULL;
1738
1739 if (dsc->page_count == 0)
1740 return -1;
1741
1742 /* Get renamed separations */
1743 renamed1 = (const char **)malloc(sizeof(const char *) * dsc->page_count);
1744 if (renamed1 == NULL)
1745 return -1;
1746 if (rename_separations(dsc, rs, renamed1) != 0) {
1747 free((void *)renamed1);
1748 return -1;
1749 }
1750 if (doc2) {
1751 renamed2 = (const char **)
1752 malloc(sizeof(const char *) * doc2->dsc->page_count);
1753 if (renamed2 == NULL) {
1754 free((void *)renamed1);
1755 return -1;
1756 }
1757 if (rename_separations(doc2->dsc, rs, renamed2) != 0) {
1758 free((void *)renamed1);
1759 free((void *)renamed2);
1760 return -1;
1761 }
1762 }
1763
1764 if (doc2 && check_dcs2_combine(doc, doc2, renamed1, renamed2, tolerance)) {
1765 free((void *)renamed1);
1766 free((void *)renamed2);
1767 return -1;
1768 }
1769
1770 gfile_seek(docfile, dsc->page[0].begin, gfile_begin);
1771 memset(buf, 0, sizeof(buf)-1);
1772 count = ps_fgets(buf,
1773 min(sizeof(buf)-1, dsc->page[0].end - dsc->page[0].begin), docfile);
1774 header_position = gfile_get_position(docfile);
1775 if (count) {
1776 /* copy version line */
1777 gfile_write(epsfile, buf, without_eol(buf, count));
1778 gfile_puts(epsfile, eol_str); /* change EOL */
1779 }
1780 while ((count = ps_fgets(buf,
1781 min(sizeof(buf)-1, dsc->page[0].end - header_position),
1782 docfile)) != 0) {
1783 header_position = gfile_get_position(docfile);
1784 /* check if end of header */
1785 if (count < 2)
1786 found_endheader = TRUE;
1787 if (buf[0] != '%')
1788 found_endheader = TRUE;
1789 if ((buf[0] == '%') && ((buf[1] == ' ') ||
1790 (buf[1] == '\t') || (buf[1] == '\r') || (buf[1] == '\n')))
1791 found_endheader = TRUE;
1792 if (strncmp(buf, endcomments_str, strlen(endcomments_str)) == 0)
1793 found_endheader = TRUE;
1794 if (strncmp(buf, "%%Begin", 7) == 0)
1795 found_endheader = TRUE;
1796 if (found_endheader)
1797 break; /* write out count characters from buf later */
1798 if ((buf[0] == '%') && (buf[1] == '%') && (buf[2] == '+') &&
1799 ignore_continuation)
1800 continue;
1801 else
1802 ignore_continuation = FALSE;
1803 if ((strncmp(buf, platefile_str, strlen(platefile_str)) != 0) &&
1804 (strncmp(buf, cyanplate_str, strlen(cyanplate_str)) != 0) &&
1805 (strncmp(buf, magentaplate_str, strlen(magentaplate_str)) != 0) &&
1806 (strncmp(buf, yellowplate_str, strlen(yellowplate_str)) != 0) &&
1807 (strncmp(buf, blackplate_str, strlen(blackplate_str)) != 0)) {
1808 /* Write all header lines except for DCS plate lines */
1809 if ((rs != NULL) || missing_separations || doc2) {
1810 /* but don't write custom/process colour lines */
1811 if (strncmp(buf, custom_str, strlen(custom_str)) == 0) {
1812 count = 0;
1813 ignore_continuation = TRUE;
1814 }
1815 else if (strncmp(buf, process_str, strlen(process_str)) == 0) {
1816 count = 0;
1817 ignore_continuation = TRUE;
1818 }
1819 else if (strncmp(buf, cmyk_custom_str,
1820 strlen(cmyk_custom_str)) == 0) {
1821 count = 0;
1822 ignore_continuation = TRUE;
1823 }
1824 else if (strncmp(buf, rgb_custom_str,
1825 strlen(rgb_custom_str)) == 0) {
1826 count = 0;
1827 ignore_continuation = TRUE;
1828 }
1829 }
1830 if (count == 0)
1831 continue;
1832 gfile_write(epsfile, buf, without_eol(buf, count));
1833 gfile_puts(epsfile, eol_str); /* change EOL */
1834 }
1835 }
1836
1837 /* Now write DocumentProcessColors, DocumentCustomColors,
1838 * CMYKCustomColor and RGBCustomColor
1839 */
1840 if ((rs!=NULL) || missing_separations || doc2) {
1841 int n; /* number of entries written */
1842 strncpy(outbuf, process_str, sizeof(outbuf));
1843 n = fix_process(doc, outbuf, sizeof(outbuf), renamed1);
1844 if (doc2)
1845 n += fix_process(doc2, outbuf, sizeof(outbuf), renamed2);
1846 if (n) {
1847 gfile_write(epsfile, outbuf,
1848 without_eol(outbuf, (int)strlen(outbuf)));
1849 gfile_puts(epsfile, eol_str); /* change EOL */
1850 }
1851 strncpy(outbuf, custom_str, sizeof(outbuf));
1852 n = fix_custom(doc, outbuf, sizeof(outbuf), renamed1);
1853 if (doc2)
1854 n += fix_custom(doc2, outbuf, sizeof(outbuf), renamed2);
1855 if (n) {
1856 gfile_write(epsfile, outbuf,
1857 without_eol(outbuf, (int)strlen(outbuf)));
1858 gfile_puts(epsfile, eol_str); /* change EOL */
1859 }
1860 n = write_cmyk_custom(epsfile, doc, renamed1, 0);
1861 if (doc2)
1862 write_cmyk_custom(epsfile, doc2, renamed2, n);
1863 n = write_rgb_custom(epsfile, doc, renamed1, 0);
1864 if (doc2)
1865 write_rgb_custom(epsfile, doc2, renamed2, n);
1866 }
1867
1868
1869 /* Write out the platefile comments and any multiple file separations */
1870 len = write_platefile_comments(doc, docfile, epsfile, epsname,
1871 offset, file_offset,
1872 dcs2_multi, write_all, missing_separations, renamed1, (rs != NULL));
1873 if (len == (FILE_POS)-1) {
1874 free((void *)renamed1);
1875 if (renamed2)
1876 free((void *)renamed2);
1877 return -1;
1878 }
1879 file_offset += len;
1880 if (doc2) {
1881 len = write_platefile_comments(doc2, docfile2, epsfile, epsname,
1882 offset, file_offset,
1883 dcs2_multi, write_all, missing_separations, renamed2, (rs != NULL));
1884 if (len == (FILE_POS)-1) {
1885 free((void *)renamed1);
1886 if (renamed2)
1887 free((void *)renamed2);
1888 return -1;
1889 }
1890 file_offset += len;
1891 }
1892
1893 /* Copy last line of header */
1894 if (found_endheader) {
1895 gfile_write(epsfile, buf, without_eol(buf, count));
1896 gfile_puts(epsfile, eol_str); /* change EOL */
1897 }
1898 /* copy rest of composite */
1899 if (composite) {
1900 if (dsc->page_pages == 1) {
1901 gfile_puts(epsfile, "%%Page: 1 1");
1902 gfile_puts(epsfile, eol_str); /* change EOL */
1903 }
1904 end = gfile_get_length(composite);
1905 gfile_seek(composite, 0, gfile_begin);
1906 snprintf(outbuf, sizeof(outbuf)-1, "%%BeginDocument: composite");
1907 gfile_puts(epsfile, "%%BeginDocument: composite");
1908 gfile_puts(epsfile, eol_str); /* change EOL */
1909 ps_copy(epsfile, composite, 0, end);
1910 gfile_puts(epsfile, "%%EndDocument");
1911 gfile_puts(epsfile, eol_str); /* change EOL */
1912 gfile_puts(epsfile, "%%Trailer");
1913 gfile_puts(epsfile, eol_str); /* change EOL */
1914 }
1915 else {
1916 begin = header_position;
1917 end = dsc->page[0].end;
1918 ps_copy(epsfile, docfile, begin, end);
1919 }
1920
1921 file_offset = gfile_get_position(epsfile);
1922 *complen = file_offset;
1923
1924 /* Write out single file separations */
1925 write_singlefile_separations(doc, docfile, epsfile,
1926 dcs2_multi, write_all, missing_separations, (rs != NULL));
1927 if (doc2)
1928 write_singlefile_separations(doc2, docfile2, epsfile,
1929 dcs2_multi, write_all, missing_separations, (rs != NULL));
1930 free((void *)renamed1);
1931 if (renamed2)
1932 free((void *)renamed2);
1933 return 0;
1934 }
1935
1936
1937
1938 /* Copy an EPS file.
1939 * %%BoundingBox and %%HiResBoundingBox will be brought to
1940 * the start of the header.
1941 * The new EPS file will have a prolog of "offset" bytes,
1942 * so update DCS 2.0 offsets accordingly.
1943 */
1944 int
1945 copy_eps(Doc *doc, LPCTSTR epsname, CDSCBBOX *bbox, CDSCFBBOX *hires_bbox,
1946 int offset, BOOL dcs2_multi)
1947 {
1948 GFile *docfile;
1949 GFile *f = NULL;
1950 CDSC *dsc = doc->dsc;
1951 int code = 0;
1952
1953 docfile = gfile_open(doc_name(doc), gfile_modeRead);
1954 if (docfile == (GFile *)NULL) {
1955 app_csmsgf(doc->app,
1956 TEXT("Can't open document file \042%s\042\n"), doc_name(doc));
1957 return -1;
1958 }
1959
1960 f = gfile_open(epsname, gfile_modeWrite | gfile_modeCreate);
1961 if (f == (GFile *)NULL) {
1962 app_csmsgf(doc->app,
1963 TEXT("Can't open EPS file \042%s\042\n"), epsname);
1964 gfile_close(docfile);
1965 return -1;
1966 }
1967
1968 if (dsc->dcs2) {
1969 /* Write DCS 2.0, updating the %%PlateFile, but don't update
1970 * %%BoundingBox.
1971 */
1972 FILE_POS complen = 0; /* length of composite page */
1973 /* Write once to calculate the offsets */
1974 code = copy_dcs2(doc, docfile, NULL, NULL, f, epsname,
1975 offset, dcs2_multi, FALSE, FALSE, &complen, NULL, NULL, 0);
1976 gfile_seek(docfile, 0, gfile_begin);
1977 gfile_close(f);
1978 f = NULL;
1979 if (code == 0) {
1980 f = gfile_open(epsname, gfile_modeWrite | gfile_modeCreate);
1981 if (f == (GFile *)NULL) {
1982 app_csmsgf(doc->app,
1983 TEXT("Can't open EPS file \042%s\042\n"), epsname);
1984 gfile_close(docfile);
1985 return -1;
1986 }
1987 }
1988 if (code == 0) {
1989 /* Then again with the correct offsets */
1990 gfile_seek(f, 0, gfile_begin);
1991 code = copy_dcs2(doc, docfile, NULL, NULL, f, epsname,
1992 offset, dcs2_multi, TRUE, FALSE, &complen, NULL, NULL, 0);
1993 }
1994 }
1995 else {
1996 /* Update the bounding box in the header and remove it from
1997 * the trailer
1998 */
1999 copy_bbox_header(f, docfile,
2000 dsc->begincomments, dsc->endcomments,
2001 bbox, hires_bbox);
2002 ps_copy(f, docfile, dsc->begindefaults, dsc->enddefaults);
2003 ps_copy(f, docfile, dsc->beginprolog, dsc->endprolog);
2004 ps_copy(f, docfile, dsc->beginsetup, dsc->endsetup);
2005 if (dsc->page_count)
2006 ps_copy(f, docfile, dsc->page[0].begin, dsc->page[0].end);
2007 copy_nobbox(f, docfile, dsc->begintrailer, dsc->endtrailer);
2008 }
2009 if (f)
2010 gfile_close(f);
2011 gfile_close(docfile);
2012 return code;
2013 }
2014
2015
2016
2017 /*********************************************************/
2018
2019 /* make an EPSI file with an Interchange Preview */
2020 /* from a PS file and a bitmap */
2021 int
2022 make_eps_interchange(Doc *doc, IMAGE *img, CDSCBBOX devbbox,
2023 CDSCBBOX *bbox, CDSCFBBOX *hires_bbox, LPCTSTR epsname)
2024 {
2025 GFile *epsfile;
2026 GFile *docfile;
2027 int code;
2028 CDSC *dsc = doc->dsc;
2029
2030 if (dsc == NULL)
2031 return -1;
2032
2033 if ((docfile = gfile_open(doc_name(doc), gfile_modeRead))
2034 == (GFile *)NULL) {
2035 app_csmsgf(doc->app,
2036 TEXT("Can't open EPS file \042%s\042\n"),
2037 doc_name(doc));
2038 return -1;
2039 }
2040
2041 epsfile = gfile_open(epsname, gfile_modeWrite | gfile_modeCreate);
2042
2043 if (epsfile == (GFile *)NULL) {
2044 app_csmsgf(doc->app,
2045 TEXT("Can't open output EPS file \042%s\042\n"),
2046 epsname);
2047 gfile_close(docfile);
2048 return -1;
2049 }
2050
2051 /* adjust %%BoundingBox: and %%HiResBoundingBox: comments */
2052 copy_bbox_header(epsfile, docfile, dsc->begincomments, dsc->endcomments,
2053 bbox, hires_bbox);
2054
2055 code = write_interchange(epsfile, img, devbbox);
2056
2057 ps_copy(epsfile, docfile, dsc->begindefaults, dsc->enddefaults);
2058 ps_copy(epsfile, docfile, dsc->beginprolog, dsc->endprolog);
2059 ps_copy(epsfile, docfile, dsc->beginsetup, dsc->endsetup);
2060 if (dsc->page_count)
2061 ps_copy(epsfile, docfile, dsc->page[0].begin, dsc->page[0].end);
2062 copy_nobbox(epsfile, docfile, dsc->begintrailer, dsc->endtrailer);
2063 gfile_close(docfile);
2064 if (*epsname!='\0') {
2065 gfile_close(epsfile);
2066 if (code && (!(debug & DEBUG_GENERAL)))
2067 csunlink(epsname);
2068 }
2069 return code;
2070 }
2071
2072
2073 /*********************************************************/
2074
2075
2076 /* make a PC EPS file with a Windows Metafile Preview */
2077 /* from a PS file and a bitmap */
2078 int
2079 make_eps_metafile(Doc *doc, IMAGE *img, CDSCBBOX devbbox, CDSCBBOX *bbox,
2080 CDSCFBBOX *hires_bbox, float xdpi, float ydpi, BOOL reverse,
2081 LPCTSTR epsname)
2082 {
2083 MFH mf;
2084 GFile *epsfile;
2085 GFile *tpsfile;
2086 TCHAR tpsname[MAXSTR];
2087 int code;
2088 int count;
2089 char *buffer;
2090 CDSCDOSEPS doseps;
2091
2092 /* prepare metafile header and calculate length */
2093 code = metafile_init(img, &devbbox, &mf);
2094
2095 /* Create temporary EPS file with updated headers */
2096 tpsfile = NULL;
2097 memset(tpsname, 0, sizeof(tpsname));
2098 if ((tpsfile = app_temp_gfile(doc->app, tpsname,
2099 sizeof(tpsname)/sizeof(TCHAR))) == (GFile *)NULL) {
2100 app_csmsgf(doc->app,
2101 TEXT("Can't create temporary EPS file \042%s\042\n"),
2102 tpsname);
2103 return -1;
2104 }
2105 gfile_close(tpsfile);
2106
2107 code = copy_eps(doc, tpsname, bbox, hires_bbox, DOSEPS_HEADER_SIZE, FALSE);
2108 if (code)
2109 return -1;
2110
2111 if ( (tpsfile = gfile_open(tpsname, gfile_modeRead)) == (GFile *)NULL) {
2112 app_csmsgf(doc->app,
2113 TEXT("Can't open temporary EPS file \042%s\042\n"),
2114 tpsname);
2115 return -1;
2116 }
2117
2118 /* Create DOS EPS output file */
2119 epsfile = gfile_open(epsname, gfile_modeWrite | gfile_modeCreate);
2120 if (epsfile == (GFile *)NULL) {
2121 app_csmsgf(doc->app,
2122 TEXT("Can't open output EPS file \042%s\042\n"),
2123 epsname);
2124 gfile_close(tpsfile);
2125 if (!(debug & DEBUG_GENERAL))
2126 csunlink(tpsname);
2127 return -1;
2128 }
2129
2130 doseps.ps_length = (GSDWORD)gfile_get_length(tpsfile);
2131 doseps.wmf_length = mf.size * 2;
2132 doseps.tiff_begin = 0;
2133 doseps.tiff_length = 0;
2134 doseps.checksum = 0xffff;
2135 if (reverse) {
2136 doseps.wmf_begin = DOSEPS_HEADER_SIZE;
2137 doseps.ps_begin = doseps.wmf_begin + doseps.wmf_length;
2138 }
2139 else {
2140 doseps.ps_begin = DOSEPS_HEADER_SIZE;
2141 doseps.wmf_begin = doseps.ps_begin + doseps.ps_length;
2142 }
2143 write_doseps_header(&doseps, epsfile);
2144
2145 buffer = (char *)malloc(COPY_BUF_SIZE);
2146 if (buffer == (char *)NULL) {
2147 if (epsname[0]) {
2148 gfile_close(epsfile);
2149 if (!(debug & DEBUG_GENERAL))
2150 csunlink(epsname);
2151 }
2152 gfile_close(tpsfile);
2153 if (!(debug & DEBUG_GENERAL))
2154 csunlink(tpsname);
2155 return -1;
2156 }
2157
2158 gfile_seek(tpsfile, 0, gfile_begin);
2159 if (!reverse) {
2160 /* copy EPS file */
2161 while ((count = (int)gfile_read(tpsfile, buffer, COPY_BUF_SIZE)) != 0)
2162 gfile_write(epsfile, buffer, count);
2163 }
2164
2165 /* copy metafile */
2166 code = write_metafile(epsfile, img, devbbox, xdpi, ydpi, &mf);
2167
2168 if (reverse) {
2169 /* copy EPS file */
2170 while ((count = (int)gfile_read(tpsfile, buffer, COPY_BUF_SIZE)) != 0)
2171 gfile_write(epsfile, buffer, count);
2172 }
2173
2174 free(buffer);
2175 gfile_close(tpsfile);
2176 if (!(debug & DEBUG_GENERAL))
2177 csunlink(tpsname);
2178 if (epsname[0])
2179 gfile_close(epsfile);
2180 return 0;
2181 }
2182
2183 /*********************************************************/
2184 /* Create a Macintosh file with PICT preview */
2185 /* from a PS file and a bitmap */
2186
2187 int
2188 make_eps_pict(Doc *doc, IMAGE *img, CDSCBBOX *bbox,
2189 CDSCFBBOX *hires_bbox, float xdpi, float ydpi, CMAC_TYPE mac_type,
2190 LPCTSTR epsname)
2191 {
2192 GFile *epsfile;
2193 GFile *tpsfile;
2194 TCHAR tpsname[MAXSTR];
2195 GFile *tpictfile;
2196 TCHAR tpictname[MAXSTR];
2197 char filename[MAXSTR];
2198 int code = 0;
2199 int len;
2200 CMAC_TYPE type = mac_type;
2201 const TCHAR *tp, *tq;
2202
2203 len = (int)cslen(epsname);
2204 if (mac_type != CMAC_TYPE_NONE)
2205 type = mac_type;
2206 else if (epsname[0] == '.')
2207 type = CMAC_TYPE_DOUBLE;
2208 else if ((len > 3) &&
2209 (epsname[len-3] == '.') &&
2210 ((epsname[len-2] == 'a') || (epsname[len-2] == 'A')) &&
2211 ((epsname[len-1] == 's') || (epsname[len-1] == 'S')) )
2212 type = CMAC_TYPE_SINGLE;
2213 else if ((len > 5) &&
2214 ((epsname[len-5] == '.') || (epsname[len-5] == '/')) &&
2215 ((epsname[len-4] == 'r') || (epsname[len-4] == 'R')) &&
2216 ((epsname[len-3] == 's') || (epsname[len-3] == 'S')) &&
2217 ((epsname[len-2] == 'r') || (epsname[len-2] == 'R')) &&
2218 ((epsname[len-1] == 'c') || (epsname[len-1] == 'C')) )
2219 type = CMAC_TYPE_RSRC;
2220 else
2221 type = CMAC_TYPE_MACBIN;
2222
2223 /* Create temporary EPS file with updated headers */
2224 tpsfile = NULL;
2225 memset(tpsname, 0, sizeof(tpsname));
2226 if ((tpsfile = app_temp_gfile(doc->app, tpsname,
2227 sizeof(tpsname)/sizeof(TCHAR))) == (GFile *)NULL) {
2228 app_csmsgf(doc->app,
2229 TEXT("Can't create temporary EPS file \042%s\042\n"),
2230 tpsname);
2231 return -1;
2232 }
2233 gfile_close(tpsfile);
2234
2235 code = copy_eps(doc, tpsname, bbox, hires_bbox, 0, FALSE);
2236 if (code)
2237 return -1;
2238
2239 if ( (tpsfile = gfile_open(tpsname, gfile_modeRead)) == (GFile *)NULL) {
2240 app_csmsgf(doc->app,
2241 TEXT("Can't open temporary EPS file \042%s\042\n"),
2242 tpsname);
2243 return -1;
2244 }
2245 gfile_close(tpsfile);
2246
2247 /* Create temporary PICT file */
2248 tpictfile = NULL;
2249 memset(tpictname, 0, sizeof(tpictname));
2250 if ((tpictfile = app_temp_gfile(doc->app, tpictname,
2251 sizeof(tpictname)/sizeof(TCHAR))) == (GFile *)NULL) {
2252 app_csmsgf(doc->app,
2253 TEXT("Can't create temporary PICT file \042%s\042\n"),
2254 tpictname);
2255 return -1;
2256 }
2257 gfile_close(tpictfile);
2258 code = image_to_pictfile(img, tpictname, xdpi, ydpi);
2259
2260 /* Create Mac output file */
2261 epsfile = gfile_open(epsname, gfile_modeWrite | gfile_modeCreate);
2262 if (epsfile == (GFile *)NULL) {
2263 app_csmsgf(doc->app,
2264 TEXT("Can't open output EPS file \042%s\042\n"),
2265 epsname);
2266 gfile_close(tpsfile);
2267 if (!(debug & DEBUG_GENERAL))
2268 csunlink(tpsname);
2269 return -1;
2270 }
2271
2272 switch (type) {
2273 case CMAC_TYPE_SINGLE:
2274 code = write_applesingle(epsfile, tpsname, tpictname);
2275 break;
2276 case CMAC_TYPE_DOUBLE:
2277 code = write_appledouble(epsfile, tpictname);
2278 break;
2279 case CMAC_TYPE_MACBIN:
2280 memset(filename, 0, sizeof(filename));
2281 /* Remove path information */
2282 tp = tq = epsname;
2283 while (*tp != '\0') {
2284 if ((*tp == '\\') || (*tp == '/') || (*tp == ':'))
2285 tq = CHARNEXT(tp);
2286 tp = CHARNEXT(tp);
2287 }
2288 cs_to_narrow(filename, (int)sizeof(filename)-1,
2289 tq, (int)cslen(tq)+1);
2290 len = (int)strlen(filename);
2291 /* Remove trailing .bin */
2292 if ((len > 4) &&
2293 (filename[len-4] == '.') &&
2294 ((filename[len-3] == 'b') || (filename[len-3] == 'B')) &&
2295 ((filename[len-2] == 'i') || (filename[len-2] == 'I')) &&
2296 ((filename[len-1] == 'n') || (filename[len-1] == 'N')) )
2297 filename[len-4] = '\0'; /* remove ".bin" inside MacBinary */
2298 code = write_macbin(epsfile, filename, tpsname, tpictname);
2299 break;
2300 case CMAC_TYPE_RSRC:
2301 /* Just copy the resources */
2302 code = (write_resource_pict(epsfile, tpictname) < 0);
2303 break;
2304 default:
2305 code = -1;
2306 }
2307
2308 if (!(debug & DEBUG_GENERAL))
2309 csunlink(tpsname);
2310 if (!(debug & DEBUG_GENERAL))
2311 csunlink(tpictname);
2312 if (epsname[0]) {
2313 gfile_close(epsfile);
2314 if ((code<0) && (!(debug & DEBUG_GENERAL)))
2315 csunlink(epsname);
2316 }
2317 return code;
2318 }
2319
2320 /*********************************************************/
2321 /* Copy one page to a file.
2322 * This will be used for feeding directly to Ghostscript,
2323 * so don't bother updating header comments.
2324 * Add code to force one and one only showpage.
2325 */
2326 int
2327 copy_page_temp(Doc *doc, GFile *f, int page)
2328 {
2329 const char save_str[] =
2330 "%!\nsave /GSview_save exch def\n/showpage {} def\n";
2331 const char restore_str[] =
2332 "\nclear cleardictstack GSview_save restore\nshowpage\n";
2333 int code;
2334 gfile_puts(f, save_str);
2335 code = copy_page_nosave(doc, f, page);
2336 gfile_puts(f, restore_str);
2337 return code;
2338 }
2339
2340 int
2341 copy_page_nosave(Doc *doc, GFile *f, int page)
2342 {
2343 CDSC *dsc = doc->dsc;
2344 GFile *docfile;
2345 const char *fname;
2346 if (dsc == NULL)
2347 return -1;
2348
2349 fname = dsc_find_platefile(dsc, page);
2350 if (fname) {
2351 /* A separation in a separate file */
2352 FILE_POS end;
2353 TCHAR wfname[MAXSTR];
2354 narrow_to_cs(wfname, (int)sizeof(wfname), fname, (int)strlen(fname)+1);
2355 if ((docfile = gfile_open(wfname, gfile_modeRead)) != (GFile *)NULL) {
2356 end = gfile_get_length(docfile);
2357 ps_copy(f, docfile, 0, end);
2358 gfile_close(docfile);
2359 }
2360 /* else separation is missing, don't flag an error */
2361 }
2362 else {
2363 /* ordinary file */
2364 if ((docfile = gfile_open(doc_name(doc), gfile_modeRead))
2365 == (GFile *)NULL) {
2366 app_csmsgf(doc->app,
2367 TEXT("Can't open document file \042%s\042\n"),
2368 doc_name(doc));
2369 return -1;
2370 }
2371 ps_copy(f, docfile, dsc->begincomments, dsc->endcomments);
2372 ps_copy(f, docfile, dsc->begindefaults, dsc->enddefaults);
2373 ps_copy(f, docfile, dsc->beginprolog, dsc->endprolog);
2374 ps_copy(f, docfile, dsc->beginsetup, dsc->endsetup);
2375 if (dsc->page_count && (page >= 0) && (page < (int)dsc->page_count))
2376 ps_copy(f, docfile, dsc->page[page].begin, dsc->page[page].end);
2377 ps_copy(f, docfile, dsc->begintrailer, dsc->endtrailer);
2378 gfile_close(docfile);
2379 }
2380
2381 return 0;
2382 }
2383
2384
2385 /*********************************************************/