epstool-3.08/0000775000076400007640000000000010252260054012537 5ustar rjlrjl00000000000000epstool-3.08/src/0000775000076400007640000000000010252260054013326 5ustar rjlrjl00000000000000epstool-3.08/src/cps.c0000644000076400007640000002776510252260054014276 0ustar rjlrjl00000000000000/* Copyright (C) 1993-2005 Ghostgum Software Pty Ltd. All rights reserved. This software is provided AS-IS with no warranty, either express or implied. This software is distributed under licence and may not be copied, modified or distributed except as expressly authorised under the terms of the licence contained in the file LICENCE in this distribution. For more information about licensing, please refer to http://www.ghostgum.com.au/ or contact Ghostsgum Software Pty Ltd, 218 Gallaghers Rd, Glen Waverley VIC 3150, AUSTRALIA, Fax +61 3 9886 6616. */ /* $Id: cps.c,v 1.7 2005/06/10 09:39:24 ghostgum Exp $ */ /* Copying PostScript files */ #include "common.h" #include "dscparse.h" #include "capp.h" #define DEFINE_CDOC #include "cdoc.h" int ps_extract(Doc *doc, LPCTSTR filename, PAGELIST *pagelist, int copies); int ps_copy(GFile *outfile, GFile *infile, FILE_OFFSET begin, FILE_OFFSET end); int ps_fgets(char *s, int n, GFile *f); static int ps_writestring(GFile *f, const char *str) { return gfile_write(f, str, (int)strlen(str)); } /* Like fgets, but allows any combination of EOL characters * and returns the count of bytes, not the string pointer. * This reads one byte at a time, so is pretty slow. * Use it for copying a header or trailer, but not for * copying the whole document. */ int ps_fgets(char *s, int n, GFile *f) { char ch = '\0'; int not_eof = 0; char *p = s; int count = 0; /* bytes written to buffer */ /* copy until first EOL character */ while ( (count < n) && ((not_eof = (int)gfile_read(f, &ch, 1)) != 0) && (ch != '\r') && (ch != '\n') ) { *p++ = (char)ch; count++; } if ((count < n) && not_eof) { /* check for extra EOL characters */ if (ch == '\r') { *p++ = (char)ch; count++; /* check if MS-DOS \r\n is being used */ if ((count < n) && ((not_eof = (int)gfile_read(f, &ch, 1)) != 0)) { if (ch == '\n') { /* Yes, MS-DOS */ *p++ = (char)ch; count++; } else { /* No, Macintosh */ gfile_seek(f, -1, gfile_current); } } } else { /* must have been '\n' */ *p++ = (char)ch; count++; } } if (count < n) *p = '\0'; if ( (!not_eof) && (p == s) ) return 0; return count; } static void ps_num_copies(GFile *f, int copies) { char buf[MAXSTR]; if (copies >= 1) { snprintf(buf, sizeof(buf)-1, "[{\n%%%%BeginFeature: *NumCopies %d\n", copies); ps_writestring(f, buf); snprintf(buf, sizeof(buf)-1, "<< /NumCopies %d >> setpagedevice\n", copies); ps_writestring(f, buf); ps_writestring(f, "%%%%EndFeature\n} stopped cleartomark\n"); } } /* Copy DSC until a particular comment is found */ /* Do not copy the comment */ /* Stop if file offset exceeds end */ /* return TRUE if comment found, FALSE if not found */ static BOOL ps_copy_find(GFile *outfile, GFile *infile, FILE_OFFSET end, char *s, int n, const char *comment) { int count; int remain; while (((remain = (FILE_POS)end - gfile_get_position(infile)) > 0) && ((count = ps_fgets(s, min(n-1, remain), infile))!=0)) { s[n-1] = '\0'; if (strncmp(s, comment, strlen(comment)) == 0) return TRUE; gfile_write(outfile, s, count); } return FALSE; } int ps_copy(GFile *outfile, GFile *infile, FILE_OFFSET begin, FILE_OFFSET end) { char *buf; int count = 0; buf = (char *)malloc(COPY_BUF_SIZE); if (buf == (char *)NULL) return -1; if (begin >= 0) gfile_seek(infile, begin, gfile_begin); /* seek to section to extract */ begin = gfile_get_position(infile); while (begin < end) { count = (int)(min(end-begin, COPY_BUF_SIZE)); if ((count = (int)gfile_read(infile, buf, count)) > 0) { gfile_write(outfile, buf, count); begin += count; } else begin = end; /* EOF or error */ } free(buf); return count; } static int ps_copy_setup(GFile *outfile, GFile *infile, FILE_OFFSET begin, FILE_OFFSET end, int copies) { char line[DSC_LINE_LENGTH+1]; BOOL found; int code = 0; if (copies > 1) { if (begin != end) { gfile_seek(infile, begin, gfile_begin); /* copy up to, but not including %%EndSetup */ found = ps_copy_find(outfile, infile, end, line, sizeof(line)-1, "%%EndSetup"); /* insert code for multiple copies */ ps_num_copies(outfile, copies); /* copy rest of setup section, including %%EndSetup */ if (found) ps_writestring(outfile, line); code = ps_copy(outfile, infile, -1, end); } else { /* setup section was missing - add our own. */ ps_writestring(outfile, "%%BeginSetup\n"); ps_num_copies(outfile, copies); ps_writestring(outfile, "%%EndSetup\n"); } } else code = ps_copy(outfile, infile, begin, end); return code; } /* Extract pages from a PostScript file */ /* The pages are in v->pagelist */ static int ps_extract_pages(Doc *doc, GFile *infile, GFile *outfile, PAGELIST *pagelist, int copies) { int i; int pages = 0; int neworder; BOOL reverse; DSC_OFFSET position; char line[DSC_LINE_LENGTH+1]; char buf[MAXSTR]; BOOL end_header; BOOL line_written; BOOL pages_written = FALSE; BOOL pageorder_written = FALSE; CDSC *dsc = doc->dsc; int page; int count; if (dsc == NULL) return_error(-1); if ((pagelist->page_count == 0) || (pagelist->select == NULL)) return_error(-1); /* can't do */ if (pagelist->page_count != (int)dsc->page_count) return_error(-1); for (i=0; ipage_count; i++) { if (pagelist->select[i]) pages++; } /* neworder = page order of the extracted document */ /* reverse = reverse the current page order */ neworder = dsc->page_order; reverse = FALSE; if (neworder == CDSC_ORDER_UNKNOWN) /* No page order so assume ASCEND */ neworder = CDSC_ASCEND; /* Don't touch SPECIAL pageorder */ if (pagelist->reverse) { /* New page order to be DESCEND */ if (neworder == CDSC_ASCEND) neworder = CDSC_DESCEND; else if (neworder == CDSC_DESCEND) { /* neworder = DESCEND;*/ /* unchanged */ reverse = FALSE; /* already reversed, don't do it again */ } } else { if (neworder == CDSC_DESCEND) { neworder = CDSC_ASCEND; reverse = TRUE; /* reverse it to become ascending */ } } /* copy header, fixing up %%Pages: and %%PageOrder: * Write a DSC 3.0 %%Pages: or %%PageOrder: in header, * even if document was DSC 2.x. */ position = gfile_seek(infile, dsc->begincomments, gfile_begin); while ( position < dsc->endcomments ) { if (ps_fgets(line, min(sizeof(line), dsc->endcomments - position), infile) == 0) return FALSE; position = gfile_get_position(infile); end_header = (strncmp(line, "%%EndComments", 13) == 0); if ((line[0] != '%') && (line[0] != ' ') && (line[0] != '+') && (line[0] != '\t') && (line[0] != '\r') && (line[0] != '\n')) end_header = TRUE; line_written = FALSE; if (end_header || strncmp(line, "%%Pages:", 8) == 0) { if (!pages_written) { snprintf(buf, sizeof(buf)-1, "%%%%Pages: %d\r\n", pages); ps_writestring(outfile, buf); pages_written = TRUE; } line_written = !end_header; } if (end_header || strncmp(line, "%%PageOrder:", 12) == 0) { if (!pageorder_written) { if (neworder == CDSC_ASCEND) ps_writestring(outfile, "%%PageOrder: Ascend\r\n"); else if (neworder == CDSC_DESCEND) ps_writestring(outfile, "%%PageOrder: Descend\r\n"); else ps_writestring(outfile, "%%PageOrder: Special\r\n"); pageorder_written = TRUE; } line_written = !end_header; } if (!line_written) ps_writestring(outfile, line); } if (dsc->begincomments != dsc->endcomments) { if (!pages_written) { snprintf(buf, sizeof(buf)-1, "%%%%Pages: %d\r\n", pages); ps_writestring(outfile, buf); /* pages_written = TRUE; */ } if (!pageorder_written) { if (neworder == CDSC_ASCEND) ps_writestring(outfile, "%%PageOrder: Ascend\r\n"); else if (neworder == CDSC_DESCEND) ps_writestring(outfile, "%%PageOrder: Descend\r\n"); else ps_writestring(outfile, "%%PageOrder: Special\r\n"); /* pageorder_written = TRUE; */ } } ps_copy(outfile, infile, dsc->beginpreview, dsc->endpreview); ps_copy(outfile, infile, dsc->begindefaults, dsc->enddefaults); ps_copy(outfile, infile, dsc->beginprolog, dsc->endprolog); ps_copy_setup(outfile, infile, dsc->beginsetup, dsc->endsetup, copies); /* Copy each page */ page = 1; i = reverse ? dsc->page_count - 1 : 0; while ( reverse ? (i >= 0) : (i < (int)dsc->page_count) ) { if (pagelist->select[doc_map_page(doc,i)]) { gfile_seek(infile, dsc->page[i].begin, gfile_begin); position = gfile_get_position(infile); /* Read original %%Page: line */ if ((count = ps_fgets(line, sizeof(line)-1, infile)) == 0) return -1; /* Write new %%Page: line with new ordinal */ if (dsc->page[i].label) snprintf(buf, sizeof(buf)-1, "%%%%Page: %s %d\r\n", dsc->page[i].label, page); else snprintf(buf, sizeof(buf)-1, "%%%%Page: %d %d\r\n", page, page); ps_writestring(outfile, buf); page++; if (strncmp(line, "%%Page:", 7) != 0) gfile_write(outfile, line, count); ps_copy(outfile, infile, -1, dsc->page[i].end); } i += reverse ? -1 : 1; } /* copy trailer, removing %%Pages: and %%PageOrder: */ gfile_seek(infile, dsc->begintrailer, gfile_begin); position = gfile_get_position(infile); while ( position < dsc->endtrailer ) { if (ps_fgets(line, min(sizeof(line), dsc->endtrailer - position), infile) == 0) return -1; position = gfile_get_position(infile); if (strncmp(line, "%%Pages:", 8) == 0) { continue; /* has already been written in header */ } else if (strncmp(line, "%%PageOrder:", 12) == 0) { continue; /* has already been written in header */ } else { ps_writestring(outfile, line); } } return 0; } /* Extract pages from a PostScript file. * If copies > 1, insert PostScript code to request printing * copies of each page. * Used for saving a page that is being displayed, * or in preparation for printing. * Returns 0 if OK, -ve if error. */ int ps_extract(Doc *doc, LPCTSTR filename, PAGELIST *pagelist, int copies) { GFile *infile, *outfile; CDSC *dsc; int code; if (doc_type(doc) == DOC_PDF) return -1; if ((infile = gfile_open(doc_name(doc), gfile_modeRead)) == (GFile *)NULL) { app_msg(doc->app, "File \042"); app_csmsg(doc->app, doc_name(doc)); app_msg(doc->app, "\042 does not exist\n"); return_error(-1); } if ( (outfile = gfile_open(filename, gfile_modeWrite | gfile_modeCreate)) == (GFile *)NULL ) { app_msg(doc->app, "File \042"); app_csmsg(doc->app, filename); app_msg(doc->app, "\042 can not be opened for writing\n"); gfile_close(infile); return_error(-1); } if (pagelist == NULL) { /* Save file without changes */ code = ps_copy(outfile, infile, 0, gfile_get_length(infile)); } else if (doc->dsc && doc->dsc->page_count && pagelist->page_count && (pagelist->select != NULL)) { /* DSC with pages */ code = ps_extract_pages(doc, infile, outfile, pagelist, copies); } else if (doc->dsc) { /* DSC without pages */ dsc = doc->dsc; code = ps_copy(outfile, infile, dsc->begincomments, dsc->endcomments); if (!code) code = ps_copy(outfile, infile, dsc->begindefaults, dsc->enddefaults); if (!code) code = ps_copy(outfile, infile, dsc->beginprolog, dsc->endprolog); if (!code) code = ps_copy_setup(outfile, infile, dsc->beginsetup, dsc->endsetup, copies); if (!code) code = ps_copy(outfile, infile, dsc->begintrailer, dsc->endtrailer); } else { /* Not DSC */ if (copies > 1) ps_num_copies(outfile, copies); code = ps_copy(outfile, infile, 0, gfile_get_length(infile)); } gfile_close(outfile); gfile_close(infile); if (code && !(debug & DEBUG_GENERAL)) csunlink(filename); return code; } epstool-3.08/src/cgssrv.h0000644000076400007640000001440510252260054015010 0ustar rjlrjl00000000000000/* Copyright (C) 2001-2002 Ghostgum Software Pty Ltd. All rights reserved. This software is provided AS-IS with no warranty, either express or implied. This software is distributed under licence and may not be copied, modified or distributed except as expressly authorised under the terms of the licence contained in the file LICENCE in this distribution. For more information about licensing, please refer to http://www.ghostgum.com.au/ or contact Ghostsgum Software Pty Ltd, 218 Gallaghers Rd, Glen Waverley VIC 3150, AUSTRALIA, Fax +61 3 9886 6616. */ /* $Id: cgssrv.h,v 1.6 2003/01/18 02:36:40 ghostgum Exp $ */ /* Ghostscript server header */ /* Public */ /* These error codes are returned where GS error codes * may be used. GS uses 0 for success, -ve for error, * and <-100 for more serious errors. * We use <-200 to avoid confusion. */ typedef enum GSREQ_ERROR_e { GSREQ_ERROR_NOERROR = 0, /* normal */ GSREQ_ERROR_PAGERANGE = -201, /* page out of range */ GSREQ_ERROR_NOMOREPAGE = -202, /* non-DSC and no more pages */ GSREQ_ERROR_GS = -203, /* Ghostscript returned an error */ GSREQ_ERROR_FILE = -204, /* Problem with reading file */ GSREQ_ERROR_SETDEVICE = -205, /* Probably due to lack of memory */ /* so reset the page size. */ GSREQ_ERROR_INTERNAL = -206, /* Probably due to lack of memory */ GSREQ_ERROR_UNKNOWN = -299 } GSREQ_ERROR; typedef enum GSREQ_ACTION_e { GSREQ_ACTION_DISPLAY = 0, /* Display a page. */ GSREQ_ACTION_CONVERT = 1, /* Convert to bitmap, PDF etc. */ GSREQ_ACTION_ABORT = 2, /* Abort GS, but don't unload GS DLL */ /* Not sure if this will be used */ GSREQ_ACTION_UNLOAD = 3, /* We about to exit, so unload GS DLL */ /* Also used if we are changing GS version */ GSREQ_ACTION_CLOSE_THREAD = 4 /* We exiting GSview */ } GSREQ_ACTION; typedef enum CONVERT_OUTPUT_e { CONVERT_FILE, /* -sOutputFile="output" */ CONVERT_PIPE, /* -sOutputFile="%pipe%output" */ CONVERT_HANDLE /* -sOutputFile="%handle%output" */ } CONVERT_OUTPUT; typedef struct GSREQ_CONVERT_s GSREQ_CONVERT; struct GSREQ_CONVERT_s { CONVERT_OUTPUT method; /* determines meaning of output */ TCHAR output[MAXSTR]; char gsdevice[MAXSTR]; PAGELIST pagelist; /* FIX: should we include page size here, or use PAGESPEC? */ }; struct GSREQ_s { GSREQ *next; GSREQ_ACTION action; PAGESPEC pagespec; /* valid if action is GSREQ_ACTION_DISPLAY */ GSREQ_CONVERT convert; /* valid if action is GSREQ_ACTION_CONVERT */ CDSC *dsc; BOOL pdf; BOOL dcs2multi; /* DCS 2.0 separation in separate file */ BOOL temp_ps; /* Temporary PostScript file created from bitmap. * This file should be deleted when the request * is removed from the queue. */ View *view; /* The view that made this request. */ /* We send notifications to this view. */ }; GSSRV * gssrv_new(GSview *app); int gssrv_ref(GSSRV *s); int gssrv_unref(GSSRV *s); GSview * gssrv_app(GSSRV *s); GSIMAGE * gssrv_img(GSSRV *s); GGTHREAD * gssrv_thread_handle(GSSRV *s); int gssrv_request(GSSRV *s, GSREQ *reqnew); void gssrv_notify_view(GSSRV *s, int message, int param); void gssrv_page_callback(GSSRV *s); unsigned int gssrv_format(DISPLAY_FORMAT df); void gssrv_run_thread(void *arg); void plsrv_run_thread(void *arg); const char *gssrv_error_message(int id); /* platform specific */ int gssrv_poll(GSSRV *s); /**********************************************/ /* Private */ #ifdef DEFINE_CGSSRV struct GSSRV_s { void *handle; /* Platform specific handle */ int refcount; /* Number of users of this object */ GSview *app; /* GSview app object */ GSIMAGE *gsimg; /* display device image */ /* A linked list of requests. */ /* The currently pending request is head. */ /* The request list is NULL if there is nothing to do. */ GSREQ *req; /* Before send a document or page to GS, we set request_removed to FALSE. * If we get a page callback, request_removed will be set to TRUE and the * request removed from the list. If we don't get a callback (e.g beyond last * page of non-DSC, or EPS without showpage), then request_removed will be * still be TRUE and we need to remove the request afterwards. */ BOOL request_removed; /* TRUE if we stopped at a page and removed the request */ /* The last request we received. * This affects whether we just advance to the next page of the * non-DSC document or whether we need to restart Ghostscript. * Once we start sending the document or page to GS this is also * the current request. */ GSREQ lastreq; BOOL close_thread; /* Set to when we wnat to exit */ /* This overides all other requests */ BOOL abort; /* Ignore errors and exit GS */ BOOL unload; /* Unload GS, because we are exiting, * or because we need to use a different * GS, or because someone else needs to * use GS DLL. */ BOOL waiting; /* Used when singlethread to determine * if we are polling or waiting. * Ignored when multithread. */ GGEVENT event; /* Semaphore for synchronising threads */ GGTHREAD thread_handle; /* GS thread */ /* PDF page count is obtained when GS opens file */ int pdf_page_first; int pdf_page_count; /* PDF media box, crop box and rotate are obtained when a page is opened */ BBOX pdf_media_box; BBOX pdf_crop_box; ORIENT pdf_orient; /* GhostPCL read from stdin, so we need to keep the file open */ GFile *gf; /* stdin for GhostPCL */ /* Buffer for storing stdout which we search for text tags * information about the PDF file. */ #define MAX_TAG_LEN 4096 char pdf_tag_line[MAX_TAG_LEN]; int pdf_page_number; PDFLINK *pdf_link_head; }; int gssrv_remove(GSSRV *s, GSREQ *req); void gssrv_request_translate(GSSRV *s); int gssrv_set_lastreq(GSSRV *s, GSREQ *req); BOOL gssrv_check_requests(GSSRV *s); BOOL gssrv_check_abort(GSSRV *s); int gssrv_event_wait(GSSRV *s); int gssrv_run_string(GSSRV *s, const char *str); int gssrv_run_formatted(GSSRV *s, const char *str, ...); /* platform specific */ int gssrv_platform_init(GSSRV *s); int gssrv_platform_finish(GSSRV *s); int gssrv_event_wait(GSSRV *s); int gssrv_event_post(GSSRV *s); #endif /* DEFINE_GSSRV */ epstool-3.08/src/cdll.h0000644000076400007640000000170510252260054014416 0ustar rjlrjl00000000000000/* Copyright (C) 2001-2002 Ghostgum Software Pty Ltd. All rights reserved. This software is provided AS-IS with no warranty, either express or implied. This software is distributed under licence and may not be copied, modified or distributed except as expressly authorised under the terms of the licence contained in the file LICENCE in this distribution. For more information about licensing, please refer to http://www.ghostgum.com.au/ or contact Ghostsgum Software Pty Ltd, 218 Gallaghers Rd, Glen Waverley VIC 3150, AUSTRALIA, Fax +61 3 9886 6616. */ /* $Id: cdll.h,v 1.2 2002/05/27 09:40:10 ghostgum Exp $ */ /* Platform dependent DLL / shared object loading */ #ifndef CDLL_INCLUDED #define CDLL_INCLUDED /* platform dependent */ typedef void * (*dll_proc)(void); int dll_open(GGMODULE *hmodule, LPCTSTR name, TCHAR *msg, int msglen); int dll_close(GGMODULE *hmodule); dll_proc dll_sym(GGMODULE *hmodule, const char *name); #endif epstool-3.08/src/capp.c0000644000076400007640000004300410252260053014413 0ustar rjlrjl00000000000000/* Copyright (C) 2001-2005 Ghostgum Software Pty Ltd. All rights reserved. This software is provided AS-IS with no warranty, either express or implied. This software is distributed under licence and may not be copied, modified or distributed except as expressly authorised under the terms of the licence contained in the file LICENCE in this distribution. For more information about licensing, please refer to http://www.ghostgum.com.au/ or contact Ghostsgum Software Pty Ltd, 218 Gallaghers Rd, Glen Waverley VIC 3150, AUSTRALIA, Fax +61 3 9886 6616. */ /* $Id: capp.c,v 1.20 2005/06/10 09:39:24 ghostgum Exp $ */ /* Application */ #include "common.h" #include "dscparse.h" #define DEFINE_COPT #include "copt.h" #define DEFINE_CAPP #include "capp.h" #include "cargs.h" #include "cdll.h" #include "cgssrv.h" #include "cimg.h" #include "cpagec.h" #include "cprofile.h" #include "cres.h" /* GLOBAL WARNING */ int debug = DEBUG_GENERAL; const char szAppName[] = "GSview"; /* GLOBAL WARNING */ static void rotate_last_files(GSview *a, int count); GSDLL ** app_dll(GSview *a) { /* Because Ghostscript only supports one instance, we store * the DLL in the app. */ return &a->gsdll; } PLDLL ** app_pldll(GSview *a) { /* Because GhostPCL only supports one instance, we store * the DLL in the app. */ return &a->pldll; } Doc ** app_docs(GSview *a) { return &a->doclist; } OPTION * app_option(GSview *a) { return &a->option; } PAGECACHE ** app_pagecache(GSview *a) { return &a->pagecache; } BOOL app_multithread(GSview *a) { return a->multithread; } int app_gssrv_request(GSview *a, GSREQ *reqnew) { if (a->gssrv) return gssrv_request(a->gssrv, reqnew); return -1; } int app_plsrv_request(GSview *a, GSREQ *reqnew) { if (a->plsrv) return gssrv_request(a->plsrv, reqnew); return -1; } /* we call this when we know that the app mutex is already locked by us */ int app_msg_len_nolock(GSview *a, const char *str, int len) { char *p; const char *s; int i, lfcount; /* if debugging, write to a log file */ if (debug & DEBUG_LOG) app_log(str, len); /* we need to add \r after each \n, so count the \n's */ lfcount = 0; s = str; for (i=0; i= TWSCROLL) return 0; /* too large */ if (len + lfcount + a->twend >= TWLENGTH-1) { /* scroll buffer */ a->twend -= TWSCROLL; memmove(a->twbuf, a->twbuf+TWSCROLL, a->twend); } p = a->twbuf+a->twend; for (i=0; itwend += (len + lfcount); *(a->twbuf+a->twend) = '\0'; return len; } /* Add string for Ghostscript message window */ int app_msg_len(GSview *a, const char *str, int len) { int n; app_lock(a); n = app_msg_len_nolock(a, str, len); app_unlock(a); return n; } int app_msg(GSview *a, const char *str) { return app_msg_len(a, str, (int)strlen(str)); } int app_msgf(GSview *a, const char *fmt, ...) { va_list args; int count; char buf[2048]; va_start(args,fmt); count = vsnprintf(buf,sizeof(buf),fmt,args); buf[sizeof(buf)-1]='\0'; if (count >= (int)sizeof(buf)-1) { debug |= DEBUG_LOG; app_msg(a, "PANIC: internal buffer overflow. Stack is corrupted\n"); } app_msg(a, buf); va_end(args); return count; } int app_csmsg_len_nolock(GSview *a, LPCTSTR wstr, int wlen) { char buf[MAXSTR]; char *nstr = NULL; int nlen = cs_to_narrow(NULL, 0, wstr, wlen); if (nlen < (int)sizeof(buf)) nstr = buf; else nstr = (char *)malloc(nlen); if (nstr) { cs_to_narrow(nstr, nlen, wstr, wlen); app_msg_len_nolock(a, nstr, nlen); if (nstr != buf) free(nstr); } return wlen; } int app_csmsg_len(GSview *a, LPCTSTR wstr, int wlen) { int n; app_lock(a); n = app_csmsg_len_nolock(a, wstr, wlen); app_unlock(a); return n; } int app_csmsg(GSview *a, LPCTSTR wstr) { return app_csmsg_len(a, wstr, (int)cslen(wstr)); } int app_csmsgf(GSview *a, LPCTSTR fmt, ...) { va_list args; int count; TCHAR buf[2048]; va_start(args,fmt); count = csvnprintf(buf,sizeof(buf)/sizeof(TCHAR),fmt,args); if (count >= (int)sizeof(buf)/(int)sizeof(TCHAR)-1) { debug |= DEBUG_LOG; app_msg(a, "PANIC: internal buffer overflow. Stack is corrupted\n"); } app_csmsg(a, buf); va_end(args); return count; } #ifdef NO_SNPRINTF /* Dangerous code here - no length checking */ int snprintf(char *buffer, size_t count, const char *fmt, ...) { va_list args; int len; va_start(args,fmt); len = vsprintf(buffer,fmt,args); buffer[count-1]='\0'; if (len >= (int)count) { debug |= DEBUG_LOG; printf("PANIC: internal buffer overflow. Stack is corrupted\n"); } va_end(args); return len; } int vsnprintf(char *buffer, size_t count, const char *fmt, va_list argptr) { int len = vsprintf(buffer, fmt, argptr); if (len >= (int)count) { debug |= DEBUG_LOG; printf("PANIC: internal buffer overflow. Stack is corrupted\n"); } return len; } #endif static void rotate_last_files(GSview *a, int count) { int i; TCHAR buf[MAXSTR]; if (count >= MAX_LAST_FILES) return; csncpy(buf, a->last_files[count], MAXSTR-1); for (i=count; i>0; i--) csncpy(a->last_files[i], a->last_files[i-1], MAXSTR-1); csncpy(a->last_files[0], buf, MAXSTR-1); } void app_update_last_files(GSview *a, LPCTSTR filename) { int i; for (i=0; ilast_files_count; i++) { if (cscmp(filename, a->last_files[i]) == 0) break; } if (i < a->last_files_count) { /* already in list */ rotate_last_files(a, i); return; } if (a->last_files_count < MAX_LAST_FILES) a->last_files_count++; rotate_last_files(a, a->last_files_count-1); csncpy(a->last_files[0], filename, MAXSTR-1); } LPCTSTR app_last_files(GSview *a, int i) { if (i < a->last_files_count) return a->last_files[i]; return NULL; } /* Read last files from INI file */ int app_read_last_files(GSview *a, LPCTSTR filename) { int i; char buf[MAXSTR]; char lastfile[MAXSTR]; const char *section = INISECTION; PROFILE *prf; prf = profile_open(filename); if (prf == NULL) return_error(-1); a->last_files_count = 0; memset(lastfile, 0, sizeof(lastfile)); for (i=0; ilast_files[i], sizeof(a->last_files[i])/sizeof(TCHAR)-1, lastfile, (int)strlen(lastfile)+1); if (a->last_files[i][0]) a->last_files_count++; } profile_close(prf); return 0; } int app_write_last_files(GSview *a, LPCTSTR filename) { int i; char buf[MAXSTR]; char lastfile[MAXSTR]; const char *section = INISECTION; PROFILE *prf; prf = profile_open(filename); if (prf == NULL) return_error(-1); a->last_files_count = 0; memset(lastfile, 0, sizeof(lastfile)); for (i=0; ilast_files[i], (int)cslen(a->last_files[i])+1); profile_write_string(prf, section, buf, lastfile); } profile_close(prf); return 0; } /* Platform independent processing of arguments, before window creation */ void app_use_args(GSview *app, GSVIEW_ARGS *args) { OPTION *opt = app_option(app); if (args->geometry) { if (args->geometry == 4) { opt->img_origin.x = args->geometry_xoffset; opt->img_origin.y = args->geometry_yoffset; } if (args->geometry >= 2) { opt->img_size.x = args->geometry_width; opt->img_size.y = args->geometry_height; } } } static int app_init(GSview *a) { app_platform_init(a); return 0; } static int app_finish(GSview *a) { pagecache_unref_all(a); zlib_free(a); bzip2_free(a); app_platform_finish(a); return 0; } GSview * app_new(void *handle, BOOL multithread) { GSview *a = (GSview *)malloc(sizeof(GSview)); if (a) { memset(a, 0, sizeof(GSview)); a->handle = handle; a->multithread = multithread; app_init(a); app_ref(a); /* caller has reference to app */ } return a; } /* Increment reference count of App */ /* A Document will increment refcount when it attaches to App */ /* Assumes we own the lock */ int app_ref(GSview *a) { int refcount = ++(a->refcount); if (debug & DEBUG_DEV) { char buf[MAXSTR]; snprintf(buf, sizeof(buf), "app refcount=%d\n", refcount); app_msg_len_nolock(a, buf, (int)strlen(buf)); } return refcount; } /* Release reference to App. */ /* When reference count reaches zero, App is freed. */ /* Assumes we own the lock */ int app_unref(GSview *a) { int refcount; if (a->refcount > 0) a->refcount--; refcount = a->refcount; if (debug & DEBUG_DEV) { char buf[MAXSTR]; snprintf(buf, sizeof(buf), "app refcount=%d\n", refcount); buf[sizeof(buf)-1]='\0'; app_msg_len_nolock(a, buf, (int)strlen(buf)); } if (refcount == 0) { app_finish(a); memset(a, 0, sizeof(GSview)); free(a); } return refcount; } int zlib_load(GSview *a) { int code = 0; TCHAR buf[1024]; ZLIB *zlib = &a->zlib; if (zlib->loaded) return 0; memset(buf, 0, sizeof(buf)); code = dll_open(&zlib->hmodule, TEXT(ZLIBNAME), buf, sizeof(buf)/sizeof(TCHAR)-1); if (code != 0) { app_csmsg(a, buf); } else { if (code == 0) zlib->gzopen = (PFN_gzopen)dll_sym(&zlib->hmodule, "gzopen"); if (zlib->gzopen == NULL) { app_msg(a, "Can't find gzopen\n"); code = -1; } if (code == 0) zlib->gzread = (PFN_gzread)dll_sym(&zlib->hmodule, "gzread"); if (zlib->gzread == NULL) { app_msg(a, "Can't find gzread\n"); code = -1; } if (code == 0) zlib->gzclose = (PFN_gzclose)dll_sym(&zlib->hmodule, "gzclose"); if (zlib->gzclose == NULL) { app_msg(a, "Can't find gzclose\n"); code = -1; } if (code == 0) zlib->loaded = TRUE; else { dll_close(&zlib->hmodule); memset(zlib, 0, sizeof(ZLIB)); zlib->loaded = FALSE; } } return code; } void zlib_free(GSview *a) { if (a->zlib.loaded == FALSE) return; dll_close(&a->zlib.hmodule); a->zlib.hmodule = (GGMODULE)0; a->zlib.gzopen = NULL; a->zlib.gzread = NULL; a->zlib.gzclose = NULL; a->zlib.loaded = FALSE; } int zlib_uncompress(GSview *app, GFile *outfile, const char *filename) { gzFile infile; char *buffer; int count; if (zlib_load(app)) return_error(-1); /* create buffer for file copy */ buffer = (char *)malloc(COPY_BUF_SIZE); if (buffer == (char *)NULL) return_error(-1); if ((infile = app->zlib.gzopen(filename, "rb")) == (gzFile)NULL) { free(buffer); return_error(-1); } while ( (count = app->zlib.gzread(infile, buffer, COPY_BUF_SIZE)) > 0 ) { gfile_write(outfile, buffer, count); } free(buffer); app->zlib.gzclose(infile); if (count < 0) return_error(-1); return 0; } int bzip2_load(GSview *a) { int code = 0; TCHAR buf[1024]; BZIP2 *bzip2 = &a->bzip2; if (bzip2->loaded) return 0; memset(buf, 0, sizeof(buf)); code = dll_open(&bzip2->hmodule, TEXT(BZIP2NAME), buf, sizeof(buf)/sizeof(TCHAR)-1); if (code != 0) { app_csmsg(a, buf); } else { if (code == 0) bzip2->bzopen = (PFN_bzopen)dll_sym(&bzip2->hmodule, "BZ2_bzopen"); if (bzip2->bzopen == NULL) { app_msg(a, "Can't find bzopen\n"); code = -1; } if (code == 0) bzip2->bzread = (PFN_bzread)dll_sym(&bzip2->hmodule, "BZ2_bzread"); if (bzip2->bzread == NULL) { app_msg(a, "Can't find bzread\n"); code = -1; } if (code == 0) bzip2->bzclose = (PFN_bzclose)dll_sym(&bzip2->hmodule, "BZ2_bzclose"); if (bzip2->bzclose == NULL) { app_msg(a, "Can't find bzclose\n"); code = -1; } if (code == 0) bzip2->loaded = TRUE; else { dll_close(&bzip2->hmodule); memset(bzip2, 0, sizeof(ZLIB)); bzip2->loaded = FALSE; } } return code; } void bzip2_free(GSview *a) { if (a->bzip2.loaded == FALSE) return; dll_close(&a->bzip2.hmodule); a->bzip2.hmodule = (GGMODULE)0; a->bzip2.bzopen = NULL; a->bzip2.bzread = NULL; a->bzip2.bzclose = NULL; a->bzip2.loaded = FALSE; } int bzip2_uncompress(GSview *app, GFile *outfile, const char *filename) { bzFile infile; char *buffer; int count; if (bzip2_load(app)) return_error(-1); /* create buffer for file copy */ buffer = (char *)malloc(COPY_BUF_SIZE); if (buffer == (char *)NULL) return_error(-1); if ((infile = app->bzip2.bzopen(filename, "rb")) == (gzFile)NULL) { free(buffer); return_error(-1); } while ( (count = app->bzip2.bzread(infile, buffer, COPY_BUF_SIZE)) > 0 ) { gfile_write(outfile, buffer, count); } free(buffer); app->bzip2.bzclose(infile); if (count < 0) return_error(-1); return 0; } GFile * app_temp_gfile(GSview *app, TCHAR *fname, int len) { TCHAR *temp; #if defined(UNIX) || defined(OS2) long fd; #endif memset(fname, 0, len*sizeof(TCHAR)); if ( (temp = csgetenv(TEXT("TEMP"))) == NULL ) #ifdef UNIX csncpy(fname, "/tmp", len-1); #else csgetcwd(fname, len-1); #endif else csncpy(fname, temp, len-1); /* Prevent X's in path from being converted by mktemp. */ #if defined(_Windows) || defined(OS2) temp = fname; while (*temp) { if (*temp == '/') *temp = '\\'; if (*temp < 'a') *temp = (char)tolower(*temp); temp = CHARNEXT(temp); } #endif if ( cslen(fname) && (fname[cslen(fname)-1] != PATHSEP[0]) ) csncat(fname, TEXT(PATHSEP), len-1-cslen(fname)); csncat(fname, TEXT("gsview"), len-1-cslen(fname)); csncat(fname, TEXT("XXXXXX"), len-1-cslen(fname)); #if defined(UNIX) || defined(OS2) fd = mkstemp(fname); if (debug & DEBUG_GENERAL) app_csmsgf(app, TEXT("Creating temporary file \042%s\042\n"), fname); return gfile_open_handle((void *)fd, gfile_modeWrite | gfile_modeCreate); #else csmktemp(fname); if (debug & DEBUG_GENERAL) app_csmsgf(app, TEXT("Creating temporary file \042%s\042\n"), fname); return gfile_open(fname, gfile_modeWrite | gfile_modeCreate); #endif } FILE * app_temp_file(GSview *app, TCHAR *fname, int len) { TCHAR *temp; #if defined(UNIX) || defined(OS2) long fd; #endif memset(fname, 0, len*sizeof(TCHAR)); if ( (temp = csgetenv(TEXT("TEMP"))) == NULL ) #ifdef UNIX csncpy(fname, "/tmp", len-1); #else csgetcwd(fname, len-1); #endif else csncpy(fname, temp, len-1); /* Prevent X's in path from being converted by mktemp. */ #if defined(_Windows) || defined(OS2) temp = fname; while (*temp) { if (*temp == '/') *temp = '\\'; if (*temp < 'a') *temp = (char)tolower(*temp); temp = CHARNEXT(temp); } #endif if ( cslen(fname) && (fname[cslen(fname)-1] != PATHSEP[0]) ) csncat(fname, TEXT(PATHSEP), len-1-cslen(fname)); csncat(fname, TEXT("gsview"), len-1-cslen(fname)); csncat(fname, TEXT("XXXXXX"), len-1-cslen(fname)); #if defined(UNIX) || defined(OS2) fd = mkstemp(fname); if (debug & DEBUG_GENERAL) app_csmsgf(app, TEXT("Creating temporary file \042%s\042\n"), fname); return fdopen(fd, "wb"); #else csmktemp(fname); if (debug & DEBUG_GENERAL) app_csmsgf(app, TEXT("Creating temporary file \042%s\042\n"), fname); return csfopen(fname, TEXT("wb")); #endif } float app_get_points(GSview *a, const TCHAR *str) { float val; TCHAR ptbuf[16]; TCHAR inchbuf[16]; TCHAR mmbuf[16]; TCHAR unitbuf[MAXSTR]; TCHAR *p = unitbuf; TCHAR *q; char fbuf[64]; int i; memset(unitbuf, 0, sizeof(unitbuf)); csncpy(unitbuf, str, sizeof(unitbuf)/sizeof(TCHAR)-1); ptbuf[0] = inchbuf[0] = mmbuf[0] = '\0'; load_string(a, IDS_UNITNAME + UNIT_PT, ptbuf, sizeof(ptbuf)); load_string(a, IDS_UNITNAME + UNIT_IN, inchbuf, sizeof(inchbuf)); load_string(a, IDS_UNITNAME + UNIT_MM, mmbuf, sizeof(mmbuf)); while (*p && (*p == ' ')) p = CHARNEXT(p); cs_to_narrow(fbuf, (int)sizeof(fbuf)-1, p, (int)cslen(p)+1); fbuf[sizeof(fbuf)-1] = '\0'; val = (float)atof(fbuf); while (*p && ( ((*p >= '0') && (*p <= '9')) || (*p == '.'))) p = CHARNEXT(p); while (*p && (*p == ' ')) p = CHARNEXT(p); q = p; while (*q && (*q >= 'A')) q = CHARNEXT(q); if (*q) q = CHARNEXT(q); i = (int)(q - p); if ((csncmp(p, ptbuf, max(i, (int)cslen(ptbuf))) == 0) || (csncmp(p, TEXT("pt"), 2) == 0)) { /* do nothing */ } else if ((csncmp(p, inchbuf, max(i, (int)cslen(inchbuf))) == 0) || (csncmp(p, TEXT("in"), 2) == 0)) val *= 72.0; else if ((csncmp(p, mmbuf, max(i, (int)cslen(mmbuf))) == 0) || (csncmp(p, TEXT("mm"), 2) == 0)) val *= (float)(72.0 / 25.4); else if (csncmp(p, TEXT("cm"), 2) == 0) val *= (float)(72.0 / 2.54); else if (csncmp(p, TEXT("m"), 1) == 0) val *= (float)(72.0 / 0.0254); else if (csncmp(p, TEXT("ft"), 2) == 0) val *= (float)(72.0 * 12.0); return val; } void app_put_points(GSview *a, UNIT unit, TCHAR *buf, int len, float n) { TCHAR ubuf[16]; float factor = 1.0; if (len < 1) return; buf[0] = '\0'; ubuf[0] = '\0'; load_string(a, IDS_UNITNAME + unit, ubuf, sizeof(ubuf)); if (len < 32 + (int)cslen(ubuf)) return; switch (unit) { case UNIT_MM: factor = (float)(25.4 / 72.0); break; case UNIT_IN: factor = (float)(1.0 / 72.0); break; case UNIT_PT: default: factor = 1.0; } csnprintf(buf, len, TEXT("%g %s"), n*factor, ubuf); buf[len-1] = '0'; } epstool-3.08/src/ceps.c0000644000076400007640000020346410252260054014433 0ustar rjlrjl00000000000000/* Copyright (C) 1993-2005 Ghostgum Software Pty Ltd. All rights reserved. This software is provided AS-IS with no warranty, either express or implied. This software is distributed under licence and may not be copied, modified or distributed except as expressly authorised under the terms of the licence contained in the file LICENCE in this distribution. For more information about licensing, please refer to http://www.ghostgum.com.au/ or contact Ghostsgum Software Pty Ltd, 218 Gallaghers Rd, Glen Waverley VIC 3150, AUSTRALIA, Fax +61 3 9886 6616. */ /* $Id: ceps.c,v 1.43 2005/06/10 08:45:36 ghostgum Exp $ */ /* EPS preview manipulation */ #include "common.h" #include #include "gdevdsp.h" #include "dscparse.h" #include "capp.h" #include "cbmp.h" #define DEFINE_CDOC #include "cdoc.h" #include "cmac.h" #include "ceps.h" #include "cimg.h" #include "cps.h" #define DOSEPS_HEADER_SIZE 30 /* Local prototypes */ static void write_doseps_header(CDSCDOSEPS *doseps, GFile *outfile); static void shift_preview(unsigned char *preview, int bwidth, int offset); static void validate_devbbox(IMAGE *img, CDSCBBOX *devbbox); int write_interchange(GFile *f, IMAGE *img, CDSCBBOX devbbox); static void write_bitmap_info(IMAGE *img, LPBITMAP2 pbmi, GFile *f); static void make_bmp_info(LPBITMAP2 pbmi, IMAGE *img, float xdpi, float ydpi); void copy_nobbox(GFile *outfile, GFile *infile, FILE_POS begin, FILE_POS end); void copy_bbox_header(GFile *outfile, GFile *infile, FILE_POS begin, FILE_POS end, CDSCBBOX *bbox, CDSCFBBOX *hiresbbox); static int without_eol(const char *str, int length); static FILE_POS write_platefile_comments(Doc *doc, GFile *docfile, GFile *epsfile, LPCTSTR epsname, int offset, FILE_POS file_offset, BOOL dcs2_multi, BOOL write_all, BOOL missing_separations, const char *renamed[], BOOL some_renamed); static FILE_POS write_singlefile_separations(Doc *doc, GFile *docfile, GFile *epsfile, BOOL dcs2_multi, BOOL write_all, BOOL missing_separations, BOOL some_renamed); /* A placeable Windows Metafile header is needed * when the metafile is in a WMF file, but not * when it is in memory. */ typedef struct WINRECT_s { WORD left; WORD top; WORD right; WORD bottom; } WINRECT; typedef struct METAFILEHEADER_s { DWORD key; WORD hmf; WINRECT bbox; WORD inch; DWORD reserved; WORD checksum; } METAFILEHEADER; static void write_doseps_header(CDSCDOSEPS *doseps, GFile *outfile) { unsigned char doseps_id[] = {0xc5, 0xd0, 0xd3, 0xc6}; gfile_write(outfile, doseps_id, 4); write_dword(doseps->ps_begin, outfile); write_dword(doseps->ps_length, outfile); write_dword(doseps->wmf_begin, outfile); write_dword(doseps->wmf_length, outfile); write_dword(doseps->tiff_begin, outfile); write_dword(doseps->tiff_length, outfile); write_word((WORD)(doseps->checksum), outfile); } /* shift preview by offset bits to the left */ /* width is in bytes */ /* fill exposed bits with 1's */ static void shift_preview(unsigned char *preview, int bwidth, int offset) { int bitoffset; int byteoffset; int newwidth; int shifter; int i; if (offset == 0) return; byteoffset = offset / 8; newwidth = bwidth - byteoffset; /* first remove byte offset */ memmove(preview, preview+byteoffset, newwidth); memset(preview+newwidth, 0xff, bwidth-newwidth); /* next remove bit offset */ bitoffset = offset - byteoffset*8; if (bitoffset==0) return; bitoffset = 8 - bitoffset; for (i=0; i>bitoffset); } } static void validate_devbbox(IMAGE *img, CDSCBBOX *devbbox) { /* make sure the pixel coordinates are valid */ if ((devbbox->llx < 0) || (devbbox->llx >= (int)img->width)) devbbox->llx = 0; if ((devbbox->urx < 0) || (devbbox->urx >= (int)img->width)) devbbox->urx = img->width; if ((devbbox->lly < 0) || (devbbox->lly >= (int)img->height)) devbbox->lly = 0; if ((devbbox->ury < 0) || (devbbox->ury >= (int)img->height)) devbbox->ury = img->height; if ((devbbox->llx >= devbbox->urx) || (devbbox->lly >= devbbox->ury)) { devbbox->llx = devbbox->lly = 0; devbbox->urx = img->width; devbbox->ury = img->height; } } /* Write bitmap info. * This works even if LPBITMAP2 is not packed. */ static void write_bitmap_info(IMAGE *img, LPBITMAP2 pbmi, GFile *f) { int i; unsigned char r, g, b; unsigned char quad[4]; int palcount = 0; /* write bitmap info */ write_dword(BITMAP2_LENGTH, f); write_dword(pbmi->biWidth, f); write_dword(pbmi->biHeight, f); write_word(pbmi->biPlanes, f); write_word(pbmi->biBitCount, f); write_dword(pbmi->biCompression, f); write_dword(pbmi->biSizeImage, f); write_dword(pbmi->biXPelsPerMeter, f); write_dword(pbmi->biYPelsPerMeter, f); write_dword(pbmi->biClrUsed, f); write_dword(pbmi->biClrImportant, f); if (pbmi->biBitCount <= 8) palcount = 1 << pbmi->biBitCount; for (i=0; iformat, i, &r, &g, &b); quad[0] = b; quad[1] = g; quad[2] = r; quad[3] = '\0'; gfile_write(f, quad, 4); } } /* Make a BMP header from an IMAGE. * WARNING: The pbmi structure might not be packed, so it * should only be used by write_bitmap_info(), and not written * out directly. */ static void make_bmp_info(LPBITMAP2 pbmi, IMAGE *img, float xdpi, float ydpi) { int palcount = 0; int depth = image_depth(img); if (depth <= 8) palcount = 1 << depth; pbmi->biSize = sizeof(BITMAP2); /* WARNING - MAY NOT BE PACKED */ pbmi->biWidth = img->width; pbmi->biHeight = img->width; pbmi->biPlanes = 1; pbmi->biBitCount = (WORD)image_depth(img); pbmi->biCompression = 0; pbmi->biSizeImage = 0; pbmi->biXPelsPerMeter = (long)(1000 * xdpi / 25.4); pbmi->biYPelsPerMeter = (long)(1000 * ydpi / 25.4); pbmi->biClrUsed = palcount; pbmi->biClrImportant = palcount; } /*********************************************************/ /* extract EPS or TIFF or WMF file from DOS EPS file */ int extract_doseps(Doc *doc, LPCTSTR outname, BOOL preview) { unsigned long pos; unsigned long len; unsigned int count; char *buffer; GFile* epsfile; BOOL is_meta = TRUE; GFile *outfile; CDSC *dsc = doc->dsc; if ((dsc == (CDSC *)NULL) || (dsc->doseps == (CDSCDOSEPS *)NULL)) { app_csmsgf(doc->app, TEXT("Document \042%s\042 is not a DOS EPS file\n"), doc->name); return -1; } epsfile = gfile_open(doc_name(doc), gfile_modeRead); pos = dsc->doseps->ps_begin; len = dsc->doseps->ps_length; if (preview) { pos = dsc->doseps->wmf_begin; len = dsc->doseps->wmf_length; if (pos == 0L) { pos = dsc->doseps->tiff_begin; len = dsc->doseps->tiff_length; is_meta = FALSE; } } if (pos == 0L) { gfile_close(epsfile); app_csmsgf(doc->app, TEXT("Document \042%s\042 does not have a %s section\n"), doc->name, preview ? TEXT("preview") : TEXT("PostScript")); return -1; } gfile_seek(epsfile, pos, gfile_begin); /* seek to section to extract */ outfile = gfile_open(outname, gfile_modeWrite | gfile_modeCreate); if (outfile == (GFile *)NULL) { app_csmsgf(doc->app, TEXT("Failed to open output file \042%s\042\n"), outname); gfile_close(epsfile); return -1; } /* create buffer for file copy */ buffer = (char *)malloc(COPY_BUF_SIZE); if (buffer == (char *)NULL) { app_csmsgf(doc->app, TEXT("Out of memory in extract_doseps\n")); gfile_close(epsfile); if (*outname!='\0') gfile_close(outfile); return -1; } if (preview && is_meta) { /* check if metafile already contains header */ DWORD key; char keybuf[4]; DWORD wmf_key = 0x9ac6cdd7UL; gfile_read(epsfile, keybuf, 4); key = (unsigned int)(keybuf[0]) + ((unsigned int)(keybuf[1])<<8) + ((unsigned int)(keybuf[2])<<16) + ((unsigned int)(keybuf[3])<<24); gfile_seek(epsfile, pos, gfile_begin); /* seek to section to extract */ if ( key != wmf_key ) { /* write placeable Windows Metafile header */ METAFILEHEADER mfh; int i, temp; unsigned short *pw; mfh.key = wmf_key; mfh.hmf = 0; /* guess the location - this might be wrong */ mfh.bbox.left = 0; mfh.bbox.top = 0; if (dsc->bbox != (CDSCBBOX *)NULL) { temp = (dsc->bbox->urx - dsc->bbox->llx); /* double transfer to avoid GCC Solaris bug */ mfh.bbox.right = (WORD)temp; mfh.bbox.bottom = (WORD)(dsc->bbox->ury - dsc->bbox->lly); temp = (dsc->bbox->ury - dsc->bbox->lly); mfh.bbox.bottom = (WORD)temp; } else { /* bbox missing, assume A4 */ mfh.bbox.right = 595; mfh.bbox.bottom = 842; } mfh.inch = 72; /* PostScript points */ mfh.reserved = 0L; mfh.checksum = 0; pw = (WORD *)&mfh; temp = 0; for (i=0; i<10; i++) { temp ^= *pw++; } mfh.checksum = (WORD)temp; write_dword(mfh.key, outfile); write_word(mfh.hmf, outfile); write_word(mfh.bbox.left, outfile); write_word(mfh.bbox.top, outfile); write_word(mfh.bbox.right, outfile); write_word(mfh.bbox.bottom, outfile); write_word(mfh.inch, outfile); write_dword(mfh.reserved, outfile); write_word(mfh.checksum, outfile); } } while ( (count = (unsigned int)min(len,COPY_BUF_SIZE)) != 0 ) { count = (int)gfile_read(epsfile, buffer, count); gfile_write(outfile, buffer, count); if (count == 0) len = 0; else len -= count; } free(buffer); gfile_close(epsfile); gfile_close(outfile); return 0; } /* extract EPS or PICT file from Macintosh EPSF file */ int extract_macbin(Doc *doc, LPCTSTR outname, BOOL preview) { unsigned long pos; unsigned long len; unsigned int count; char *buffer; GFile* epsfile; GFile *outfile; CDSC *dsc = doc->dsc; CMACFILE *mac; if ((dsc == (CDSC *)NULL) || (dsc->macbin == (CDSCMACBIN *)NULL)) { app_csmsgf(doc->app, TEXT("Document \042%s\042 is not a Macintosh EPSF file with preview\n"), doc->name); return -1; } epsfile = gfile_open(doc_name(doc), gfile_modeRead); if (epsfile == NULL) { app_csmsgf(doc->app, TEXT("Failed to open \042%s\042\n"), doc_name(doc)); return -1; } if (preview) { int code = 0; mac = get_mactype(epsfile); if (mac == NULL) { app_csmsgf(doc->app, TEXT("Not a Mac file with resource fork\n")); code = -1; } if (code == 0) { code = get_pict(epsfile, mac, FALSE); if (code) app_csmsgf(doc->app, TEXT("Resource fork didn't contain PICT preview\n")); } if (code == 0) { code = extract_mac_pict(epsfile, mac, outname); if (code) app_csmsgf(doc->app, TEXT("Failed to find PICT preview or write file\n")); } gfile_close(epsfile); return code; } pos = dsc->macbin->data_begin; len = dsc->macbin->data_length; if (len == 0) { app_csmsgf(doc->app, TEXT("File has not data section for EPSF\n")); gfile_close(epsfile); return -1; } gfile_seek(epsfile, pos, gfile_begin); /* seek to section to extract */ outfile = gfile_open(outname, gfile_modeWrite | gfile_modeCreate); if (outfile == (GFile *)NULL) { app_csmsgf(doc->app, TEXT("Failed to open output file \042%s\042\n"), outname); gfile_close(epsfile); return -1; } /* create buffer for file copy */ buffer = (char *)malloc(COPY_BUF_SIZE); if (buffer == (char *)NULL) { app_csmsgf(doc->app, TEXT("Out of memory in extract_doseps\n")); gfile_close(epsfile); if (*outname!='\0') gfile_close(outfile); return -1; } while ( (count = (unsigned int)min(len,COPY_BUF_SIZE)) != 0 ) { count = (int)gfile_read(epsfile, buffer, count); gfile_write(outfile, buffer, count); if (count == 0) len = 0; else len -= count; } free(buffer); gfile_close(epsfile); gfile_close(outfile); return 0; } /*********************************************************/ /* FIX: instead of devbbox, perhaps we should use CDSCFBBOX in points, or simply grab this from doc. */ /* make a PC EPS file with a TIFF Preview */ /* from a PS file and a bitmap */ int make_eps_tiff(Doc *doc, IMAGE *img, CDSCBBOX devbbox, CDSCBBOX *bbox, CDSCFBBOX *hires_bbox, float xdpi, float ydpi, BOOL tiff4, BOOL use_packbits, BOOL reverse, LPCTSTR epsname) { GFile *epsfile; GFile *tiff_file; TCHAR tiffname[MAXSTR]; CDSCDOSEPS doseps; int code; GFile *tpsfile; TCHAR tpsname[MAXSTR]; char *buffer; unsigned int count; CDSC *dsc = doc->dsc; if (dsc == NULL) return -1; validate_devbbox(img, &devbbox); /* Create TIFF file */ if ((tiff_file = app_temp_gfile(doc->app, tiffname, sizeof(tiffname)/sizeof(TCHAR))) == (GFile *)NULL) { app_csmsgf(doc->app, TEXT("Can't open temporary TIFF file \042%s\042\n"), tiffname); return -1; } code = image_to_tiff(tiff_file, img, devbbox.llx, devbbox.lly, devbbox.urx, devbbox.ury, xdpi, ydpi, tiff4, use_packbits); gfile_close(tiff_file); if (code) { app_csmsgf(doc->app, TEXT("Failed to write temporary TIFF file \042%s\042\n"), tiffname); if (!(debug & DEBUG_GENERAL)) csunlink(tiffname); return code; } /* Create temporary EPS file with updated headers */ tpsfile = NULL; memset(tpsname, 0, sizeof(tpsname)); if ((tpsfile = app_temp_gfile(doc->app, tpsname, sizeof(tpsname)/sizeof(TCHAR))) == (GFile *)NULL) { app_csmsgf(doc->app, TEXT("Can't create temporary EPS file \042%s\042\n"), tpsname); csunlink(tiffname); return -1; } gfile_close(tpsfile); code = copy_eps(doc, tpsname, bbox, hires_bbox, DOSEPS_HEADER_SIZE, FALSE); if (code) { if (!(debug & DEBUG_GENERAL)) csunlink(tiffname); return -1; } if ( (tpsfile = gfile_open(tpsname, gfile_modeRead)) == (GFile *)NULL) { app_csmsgf(doc->app, TEXT("Can't open temporary EPS file \042%s\042\n"), tpsname); if (!(debug & DEBUG_GENERAL)) csunlink(tiffname); return -1; } /* Create DOS EPS output file */ epsfile = gfile_open(epsname, gfile_modeWrite | gfile_modeCreate); if (epsfile == (GFile *)NULL) { app_csmsgf(doc->app, TEXT("Can't open output EPS file \042%s\042\n"), epsname); if (!(debug & DEBUG_GENERAL)) csunlink(tiffname); gfile_close(tpsfile); if (!(debug & DEBUG_GENERAL)) csunlink(tpsname); return -1; } buffer = (char *)malloc(COPY_BUF_SIZE); if (buffer == (char *)NULL) { if (epsname[0]) { gfile_close(epsfile); if (!(debug & DEBUG_GENERAL)) csunlink(epsname); } if (!(debug & DEBUG_GENERAL)) csunlink(tiffname); gfile_close(tpsfile); if (!(debug & DEBUG_GENERAL)) csunlink(tpsname); return -1; } if ((tiff_file = gfile_open(tiffname, gfile_modeRead)) == (GFile *)NULL) { app_csmsgf(doc->app, TEXT("Can't open temporary TIFF file \042%s\042\n"), tiffname); free(buffer); if (!(debug & DEBUG_GENERAL)) csunlink(tiffname); gfile_close(tpsfile); if (!(debug & DEBUG_GENERAL)) csunlink(tpsname); if (epsname[0]) { gfile_close(epsfile); if (!(debug & DEBUG_GENERAL)) csunlink(epsname); } return -1; } doseps.ps_length = (GSDWORD)gfile_get_length(tpsfile); doseps.wmf_begin = 0; doseps.wmf_length = 0; doseps.tiff_length = (GSDWORD)gfile_get_length(tiff_file); if (reverse) { doseps.tiff_begin = DOSEPS_HEADER_SIZE; doseps.ps_begin = doseps.tiff_begin + doseps.tiff_length; } else { doseps.ps_begin = DOSEPS_HEADER_SIZE; doseps.tiff_begin = doseps.ps_begin + doseps.ps_length; } doseps.checksum = 0xffff; write_doseps_header(&doseps, epsfile); gfile_seek(tpsfile, 0, gfile_begin); if (!reverse) { /* copy EPS file */ while ((count = (int)gfile_read(tpsfile, buffer, COPY_BUF_SIZE)) != 0) gfile_write(epsfile, buffer, count); } /* copy tiff file */ gfile_seek(tiff_file, 0, gfile_begin); while ((count = (int)gfile_read(tiff_file, buffer, COPY_BUF_SIZE)) != 0) gfile_write(epsfile, buffer, count); if (reverse) { /* copy EPS file */ while ((count = (int)gfile_read(tpsfile, buffer, COPY_BUF_SIZE)) != 0) gfile_write(epsfile, buffer, count); } free(buffer); gfile_close(tiff_file); if (!(debug & DEBUG_GENERAL)) csunlink(tiffname); gfile_close(tpsfile); if (!(debug & DEBUG_GENERAL)) csunlink(tpsname); gfile_close(epsfile); return 0; } /*********************************************************/ static char hex[17] = "0123456789ABCDEF"; #define MAXHEXWIDTH 70 /* Write interchange preview to file f */ /* Does not copy the file itself */ int write_interchange(GFile *f, IMAGE *img, CDSCBBOX devbbox) { int i, j; unsigned char *preview; char buf[MAXSTR]; const char *eol_str = EOLSTR; const char *endpreview_str = "%%EndPreview"; BYTE *line; int preview_width, bwidth; int lines_per_scan; int topfirst = ((img->format & DISPLAY_FIRSTROW_MASK) == DISPLAY_TOPFIRST); char hexline[MAXHEXWIDTH+6]; int hexcount = 0; unsigned int value; unsigned int depth = 8; validate_devbbox(img, &devbbox); switch (img->format & DISPLAY_COLORS_MASK) { case DISPLAY_COLORS_NATIVE: case DISPLAY_COLORS_GRAY: if ((img->format & DISPLAY_DEPTH_MASK) == DISPLAY_DEPTH_1) depth = 1; } switch (depth) { case 1: /* byte width of interchange preview with 1 bit/pixel */ bwidth = (((devbbox.urx-devbbox.llx) + 7) & ~7) >> 3; /* byte width of intermediate preview with 1 bit/pixel */ preview_width = ((img->width + 7) & ~7) >> 3; break; case 8: bwidth = devbbox.urx-devbbox.llx; preview_width = img->width; break; default: return -1; } preview = (unsigned char *) malloc(preview_width); lines_per_scan = (bwidth + (MAXHEXWIDTH/2) - 1) / (MAXHEXWIDTH/2); buf[sizeof(buf)-1] = '\0'; snprintf(buf, MAXSTR-1, "%%%%BeginPreview: %u %u %u %u%s", (devbbox.urx-devbbox.llx), (devbbox.ury-devbbox.lly), depth, (devbbox.ury-devbbox.lly)*lines_per_scan, eol_str); gfile_puts(f, buf); if (topfirst) line = img->image + img->raster * (img->height - devbbox.ury); else line = img->image + img->raster * (devbbox.ury-1); /* process each line of bitmap */ for (i = 0; i < (devbbox.ury-devbbox.lly); i++) { memset(preview,0xff,preview_width); if (depth == 1) { image_to_mono(img, preview, line); if (devbbox.llx) shift_preview(preview, preview_width, devbbox.llx); } else { image_to_grey(img, preview, line); if (devbbox.llx) memmove(preview, preview+devbbox.llx, preview_width); } hexcount = 0; hexline[hexcount++] = '%'; hexline[hexcount++] = ' '; for (j=0; j= 2 + MAXHEXWIDTH) { if (strlen(eol_str) <= sizeof(hexline)-hexcount) { memcpy(hexline+hexcount, eol_str, strlen(eol_str)); hexcount += (int)strlen(eol_str); } gfile_write(f, hexline, hexcount); hexcount = 0; hexline[hexcount++] = '%'; hexline[hexcount++] = ' '; } value = preview[j]; if (depth == 8) value = 255 - value; hexline[hexcount++] = hex[(value>>4)&15]; hexline[hexcount++] = hex[value&15]; } if (hexcount && (strlen(eol_str) <= sizeof(hexline)-hexcount)) { memcpy(hexline+hexcount, eol_str, strlen(eol_str)); hexcount += (int)strlen(eol_str); } if (hexcount) gfile_write(f, hexline, hexcount); if (topfirst) line += img->raster; else line -= img->raster; } gfile_puts(f, endpreview_str); gfile_puts(f, eol_str); free(preview); return 0; } /*********************************************************/ typedef enum PREVIEW_TYPE_e { PREVIEW_UNKNOWN = 0, PREVIEW_TIFF = 1, PREVIEW_WMF = 2 } PREVIEW_TYPE; /* Make a DOS EPS file from a PS file and a user supplied preview. * Preview may be WMF or TIFF. * Returns 0 on success. */ int make_eps_user(Doc *doc, LPCTSTR preview_name, BOOL reverse, LPCTSTR epsname) { GFile *epsfile; GFile *preview_file; unsigned long preview_length; unsigned char id[4]; PREVIEW_TYPE type = PREVIEW_UNKNOWN; CDSCDOSEPS doseps; char *buffer; unsigned int count; GFile *tpsfile; TCHAR tpsname[MAXSTR]; if ((preview_name == NULL) || preview_name[0] == '\0') return -1; if (doc->dsc == NULL) return -1; /* open preview, determine length and type */ preview_file = gfile_open(preview_name, gfile_modeRead); if (preview_file == (GFile *)NULL) { app_csmsgf(doc->app, TEXT("Can't open preview file \042%s\042\n"), preview_name); return -1; } /* Determine type of preview */ gfile_read(preview_file, id, 4); preview_length = (GSDWORD)gfile_get_length(preview_file); gfile_seek(preview_file, 0, gfile_begin); if ((id[0] == 'I') && (id[1] == 'I')) type = PREVIEW_TIFF; if ((id[0] == 'M') && (id[1] == 'M')) type = PREVIEW_TIFF; if ((id[0] == 0x01) && (id[1] == 0x00) && (id[2] == 0x09) && (id[3] == 0x00)) type = PREVIEW_WMF; if ((id[0] == 0xd7) && (id[1] == 0xcd) && (id[2] == 0xc6) && (id[3] == 0x9a)) { type = PREVIEW_WMF; preview_length -= 22; /* skip over placeable metafile header */ gfile_seek(preview_file, 22, gfile_begin); } if (type == PREVIEW_UNKNOWN) { app_csmsgf(doc->app, TEXT("Preview file \042%s\042 is not TIFF or Windows Metafile\n"), preview_name); gfile_close(preview_file); return -1; } /* Create temporary EPS file containing all that is needed * including updated header and trailer. */ tpsfile = NULL; memset(tpsname, 0, sizeof(tpsname)); if ((tpsfile = app_temp_gfile(doc->app, tpsname, sizeof(tpsname)/sizeof(TCHAR))) == (GFile *)NULL) { app_csmsgf(doc->app, TEXT("Can't create temporary EPS file \042%s\042\n"), tpsname); gfile_close(preview_file); return -1; } gfile_close(tpsfile); if (copy_eps(doc, tpsname, doc->dsc->bbox, doc->dsc->hires_bbox, DOSEPS_HEADER_SIZE, FALSE) < 0) return -1; if ( (tpsfile = gfile_open(tpsname, gfile_modeRead)) == (GFile *)NULL) { app_csmsgf(doc->app, TEXT("Can't open temporary EPS file \042%s\042\n"), tpsname); gfile_close(preview_file); return -1; } /* Create EPS output file */ epsfile = gfile_open(epsname, gfile_modeWrite | gfile_modeCreate); if (epsfile == (GFile *)NULL) { app_csmsgf(doc->app, TEXT("Can't open EPS output file \042%s\042\n"), epsname); gfile_close(preview_file); gfile_close(tpsfile); if (!(debug & DEBUG_GENERAL)) csunlink(tpsname); return -1; } /* write DOS EPS binary header */ doseps.ps_length = (GSDWORD)gfile_get_length(tpsfile); if (type == PREVIEW_WMF) { doseps.wmf_length = preview_length; doseps.tiff_begin = 0; doseps.tiff_length = 0; if (reverse) { doseps.wmf_begin = DOSEPS_HEADER_SIZE; doseps.ps_begin = doseps.wmf_begin + doseps.wmf_length; } else { doseps.ps_begin = DOSEPS_HEADER_SIZE; doseps.wmf_begin = doseps.ps_begin + doseps.ps_length; } } else { doseps.wmf_begin = 0; doseps.wmf_length = 0; doseps.tiff_length = preview_length; if (reverse) { doseps.tiff_begin = DOSEPS_HEADER_SIZE; doseps.ps_begin = doseps.tiff_begin + doseps.tiff_length; } else { doseps.ps_begin = DOSEPS_HEADER_SIZE; doseps.tiff_begin = doseps.ps_begin + doseps.ps_length; } } doseps.checksum = 0xffff; write_doseps_header(&doseps, epsfile); buffer = (char *)malloc(COPY_BUF_SIZE); if (buffer == (char *)NULL) { app_csmsgf(doc->app, TEXT("Out of memory in make_eps_user\n")); if (epsname[0]) { gfile_close(epsfile); if (!(debug & DEBUG_GENERAL)) csunlink(epsname); } gfile_close(preview_file); gfile_close(tpsfile); if (!(debug & DEBUG_GENERAL)) csunlink(tpsname); return -1; } gfile_seek(tpsfile, 0, gfile_begin); if (!reverse) { /* copy EPS file */ while ((count = (int)gfile_read(tpsfile, buffer, COPY_BUF_SIZE)) != 0) gfile_write(epsfile, buffer, count); } /* copy preview file */ while ((count = (int)gfile_read(preview_file, buffer, COPY_BUF_SIZE)) != 0) gfile_write(epsfile, buffer, count); if (reverse) { /* copy EPS file */ while ((count = (int)gfile_read(tpsfile, buffer, COPY_BUF_SIZE)) != 0) gfile_write(epsfile, buffer, count); } free(buffer); gfile_close(tpsfile); if (!(debug & DEBUG_GENERAL)) csunlink(tpsname); gfile_close(preview_file); gfile_close(epsfile); return 0; /* success */ } /*********************************************************/ typedef struct tagMFH { WORD type; WORD headersize; WORD version; DWORD size; WORD nobj; DWORD maxrec; WORD noparam; } MFH; int write_metafile(GFile *f, IMAGE *img, CDSCBBOX devbbox, float xdpi, float ydpi, MFH *mf); static int metafile_init(IMAGE *img, CDSCBBOX *pdevbbox, MFH* mf); /* A metafile object must not be larger than 64k */ /* Metafile bitmap object contains metafile header, */ /* bitmap header, palette and bitmap bits */ #define MAX_METAFILE_BITMAP 64000L /* max size of bitmap bits */ static int metafile_init(IMAGE *img, CDSCBBOX *pdevbbox, MFH* mf) { int wx, wy; int ny, nylast; int complete, partial; int bytewidth; int palcount; unsigned long size; int depth = image_depth(img); switch (depth) { case 1: case 4: case 8: case 24: break; default: /* unsupported format */ return -1; } validate_devbbox(img, pdevbbox); wx = pdevbbox->urx - pdevbbox->llx; wy = pdevbbox->ury - pdevbbox->lly; bytewidth = (( wx * depth + 31) & ~31) >> 3; ny = (int)(MAX_METAFILE_BITMAP / bytewidth); if (depth == 24) palcount = 0; else palcount = 1<type = 1; /* metafile in file */ mf->headersize = 9; /* 9 WORDs */ mf->version = 0x300; /* Windows 3.0 */ mf->size = /* sizes in WORDs */ 9UL + /* header */ 5 + /* SetWindowOrg */ 5; /* SetWindowExt */ /* complete StretchDIBits */ mf->size += 14*complete; size = (40L + palcount*4L + (unsigned long)ny*(unsigned long)bytewidth)/2L; mf->size += size * (unsigned long)complete; /* partial StretchDIBits */ mf->size += 14*partial; size = (40L + palcount*4L + (unsigned long)nylast*(unsigned long)bytewidth)/2L; mf->size += size * (unsigned long)partial; mf->size += 3; /* end marker */ mf->nobj = 0; size = complete ? (40L + palcount*4L + (unsigned long)ny*(unsigned long)bytewidth)/2L : (40L + palcount*4L + (unsigned long)nylast*(unsigned long)bytewidth)/2L; mf->maxrec = 14L + size; mf->noparam = 0; return 0; } /* convert the display bitmap to a metafile picture */ int write_metafile(GFile *f, IMAGE *img, CDSCBBOX devbbox, float xdpi, float ydpi, MFH *mf) { int i; int wx; int ny, sy, dy, wy; BYTE *line; BYTE *line2; LPBITMAP2 pbmi; int bsize; int bitoffset; int bytewidth, activewidth; int palcount; unsigned long size; int depth = image_depth(img); int topfirst = ((img->format & DISPLAY_FIRSTROW_MASK) == DISPLAY_TOPFIRST); dy = 0; wx = devbbox.urx - devbbox.llx; sy = devbbox.lly; wy = devbbox.ury - devbbox.lly; bitoffset = (devbbox.llx * depth); bytewidth = (( wx * depth + 31) & ~31) >> 3; activewidth = (( wx * depth + 7) & ~7) >> 3; ny = (int)(MAX_METAFILE_BITMAP / bytewidth); if (depth == 24) palcount = 0; else palcount = 1<biClrUsed = 0; /* write out full palette */ pbmi->biClrImportant = 0; line2 = (BYTE *)malloc(img->raster); if (line2 == (BYTE *)NULL) return -1; pbmi->biWidth = wx; if (topfirst) line = img->image + img->raster * (img->height - devbbox.lly - 1); else line = img->image + img->raster * devbbox.lly; /* write metafile header */ write_word(mf->type, f); write_word(mf->headersize, f); write_word(mf->version, f); write_dword(mf->size, f); write_word(mf->nobj, f); write_dword(mf->maxrec, f); write_word(mf->noparam, f); /* write SetWindowOrg */ write_dword(5, f); write_word(0x20b, f); write_word(0, f); write_word(0, f); /* write SetWindowExt */ write_dword(5, f); write_word(0x20c, f); write_word((WORD)wy, f); write_word((WORD)wx, f); /* copy in chunks < 64k */ for ( ; wy > ny; dy += ny, wy -= ny, sy += ny ) { pbmi->biHeight = ny; size = BITMAP2_LENGTH + (palcount * RGB4_LENGTH) + (unsigned long)bytewidth * (unsigned long)ny; /* write StretchDIBits header */ write_dword(14 + size/2L, f); write_word(0x0f43, f); write_dword(0x00cc0020L, f); /* SRC_COPY */ write_word(0, f); /* DIB_RGB_COLORS */ write_word((WORD)ny, f); /* Source cy */ write_word((WORD)wx, f); /* Source cx */ write_word(0, f); /* Source y */ write_word(0, f); /* Source x */ write_word((WORD)ny, f); /* Dest cy */ write_word((WORD)wx, f); /* Dest cx */ write_word((WORD)(devbbox.ury - devbbox.lly - ny - dy), f); /* Dest y */ write_word(0, f); /* Dest x */ /* write bitmap header */ write_bitmap_info(img, pbmi, f); /* write bitmap rows */ for (i=0; iraster); shift_preview(line2, img->raster, bitoffset); if (activewidth < bytewidth) memset(line2+activewidth, 0xff, bytewidth-activewidth); gfile_write(f, line2, bytewidth); if (topfirst) line -= img->raster; else line += img->raster; } } /* write StretchDIBits header */ pbmi->biHeight = wy; size = BITMAP2_LENGTH + (palcount * RGB4_LENGTH) + (unsigned long)bytewidth * (unsigned long)wy; write_dword(14 + size/2L, f); write_word(0x0f43, f); write_dword(0x00cc0020L, f); /* SRC_COPY */ write_word(0, f); /* DIB_RGB_COLORS */ write_word((WORD)wy, f); /* Source cy */ write_word((WORD)wx, f); /* Source cx */ write_word(0, f); /* Source y */ write_word(0, f); /* Source x */ write_word((WORD)wy, f); /* Dest cy */ write_word((WORD)wx, f); /* Dest cx */ write_word((WORD)(devbbox.ury - devbbox.lly - wy - dy), f); /* Dest y */ write_word(0, f); /* Dest x */ /* write bitmap header */ write_bitmap_info(img, pbmi, f); /* copy last chunk */ for (i=0; iraster); shift_preview(line2, img->raster, bitoffset); if (activewidth < bytewidth) memset(line2+activewidth, 0xff, bytewidth-activewidth); gfile_write(f, line2, bytewidth); if (topfirst) line -= img->raster; else line += img->raster; } /* write end marker */ write_dword(3, f); write_word(0, f); free((char *)pbmi); free(line2); return 0; } /*********************************************************/ /* Copy a DSC section, removing existing bounding boxes */ void copy_nobbox(GFile *outfile, GFile *infile, FILE_POS begin, FILE_POS end) { const char bbox_str[] = "%%BoundingBox:"; const char hiresbbox_str[] = "%%HiResBoundingBox:"; char buf[DSC_LINE_LENGTH+1]; int len; gfile_seek(infile, begin, gfile_begin); begin = gfile_get_position(infile); while (begin < end) { len = ps_fgets(buf, min(sizeof(buf)-1, end-begin), infile); begin = gfile_get_position(infile); if (len == 0) { return; /* EOF on input file */ } else if (strncmp(buf, bbox_str, strlen(bbox_str)) == 0) { /* skip it */ } else if (strncmp(buf, hiresbbox_str, strlen(hiresbbox_str)) == 0) { /* skip it */ } else gfile_write(outfile, buf, len); } } /* Copy a DSC header, removing existing bounding boxes * and adding new ones. */ void copy_bbox_header(GFile *outfile, GFile *infile, FILE_POS begin, FILE_POS end, CDSCBBOX *bbox, CDSCFBBOX *hiresbbox) { char buf[DSC_LINE_LENGTH+1]; int len; memset(buf, 0, sizeof(buf)-1); gfile_seek(infile, begin, gfile_begin); len = ps_fgets(buf, min(sizeof(buf)-1, end-begin), infile); if (len) gfile_write(outfile, buf, len); /* copy version line */ /* Add bounding box lines */ if (bbox) { snprintf(buf, sizeof(buf)-1, "%%%%BoundingBox: %d %d %d %d\n", bbox->llx, bbox->lly, bbox->urx, bbox->ury); gfile_puts(outfile, buf); } if (hiresbbox) { snprintf(buf, sizeof(buf)-1, "%%%%HiResBoundingBox: %.3f %.3f %.3f %.3f\n", hiresbbox->fllx, hiresbbox->flly, hiresbbox->furx, hiresbbox->fury); gfile_puts(outfile, buf); } begin = gfile_get_position(infile); copy_nobbox(outfile, infile, begin, end); } /* return the length of the line less the EOL characters */ static int without_eol(const char *str, int length) { int j; for (j=length-1; j>=0; j--) { if (!((str[j] == '\r') || (str[j] == '\n'))) { j++; break; } } if (j < 0) j = 0; return j; } static BOOL is_process_colour(const char *name) { return ( (dsc_stricmp(name, "Cyan")==0) || (dsc_stricmp(name, "Magenta")==0) || (dsc_stricmp(name, "Yellow")==0) || (dsc_stricmp(name, "Black")==0) ); } static const char process_str[] = "%%DocumentProcessColors:"; static const char custom_str[] = "%%DocumentCustomColors:"; static const char cmyk_custom_str[] = "%%CMYKCustomColor:"; static const char rgb_custom_str[] = "%%RGBCustomColor:"; static const char eol_str[] = EOLSTR; static const char * separation_name(RENAME_SEPARATION *rs, const char *name) { RENAME_SEPARATION *s; const char *newname = name; for (s=rs; s; s=s->next) { if (strcmp(s->oldname, name) == 0) { newname = s->newname; break; } } return newname; } /* * Set renamed to the names of the renamed separations. * renamed[] must be as long as dsc->page_count. * Return 0 on success, or -1 if a separation name appears twice. */ int rename_separations(CDSC *dsc, RENAME_SEPARATION *rs, const char *renamed[]) { int duplicated = 0; int i, j; const char *sepname; renamed[0] = dsc->page[0].label; for (i=1; i<(int)dsc->page_count; i++) { sepname = separation_name(rs, dsc->page[i].label); /* Check if this is a duplicate separation, in which case * we don't want to rename it twice. */ for (j=1; jpage[j].label, dsc->page[i].label) == 0) { sepname = NULL; /* don't do it */ duplicated = 1; } /* If the separation name already exists in the renamed * list, don't rename it */ if (sepname) { for (j=1; jpage[i].label; renamed[i] = sepname; } if (duplicated) return -1; /* clash in separation names */ return 0; } /* Find separation begin and end */ static int dcs2_separation(CDSC *dsc, int pagenum, const char **fname, FILE_POS *pbegin, FILE_POS *pend) { GFile *f; TCHAR wfname[MAXSTR]; *fname = dsc_find_platefile(dsc, pagenum); if (*fname) { narrow_to_cs(wfname, (int)sizeof(wfname), *fname, (int)strlen(*fname)+1); if ((f = gfile_open(wfname, gfile_modeRead)) != (GFile *)NULL) { *pbegin = 0; *pend = gfile_get_length(f); gfile_close(f); } else { /* Separation file didn't exist */ *pbegin = *pend = 0; return 1; } } else { *pbegin = dsc->page[pagenum].begin; *pend = dsc->page[pagenum].end; } return 0; } static int fix_custom(Doc *doc, char *buf, int buflen, const char *renamed[]) { /* Create a new %%DocumentCustomColors: * containing only those separations that exist */ CDSC *dsc = doc->dsc; int i; int missing; int n = 0; FILE_POS begin, end; const char *fname; int count = min((int)strlen(buf), buflen); if ((dsc == NULL) || !dsc->dcs2) return 0; for (i=1; i<(int)dsc->page_count; i++) { const char *sepname = renamed[i]; missing = dcs2_separation(dsc, i, &fname, &begin, &end); if (!missing && !is_process_colour(sepname)) { n++; strncpy(buf+count, " (", buflen-count-1); count = (int)strlen(buf); strncpy(buf+count, sepname, buflen-count-1); count = (int)strlen(buf); strncpy(buf+count, ")", buflen-count-1); count = (int)strlen(buf); } } return n; } static int fix_process(Doc *doc, char *buf, int buflen, const char *renamed[]) { /* Create a new %%DocumentProcessColors: * containing only those separations that exist */ CDSC *dsc = doc->dsc; int i; int n = 0; int missing; FILE_POS begin, end; const char *fname; int count = min((int)strlen(buf), buflen); if ((dsc == NULL) || !dsc->dcs2) return 0; for (i=1; i<(int)dsc->page_count; i++) { const char *sepname = renamed[i]; missing = dcs2_separation(dsc, i, &fname, &begin, &end); if (!missing && is_process_colour(sepname)) { n++; strncpy(buf+count, " ", buflen-count-1); count++; strncpy(buf+count, sepname, buflen-count-1); count = (int)strlen(buf); } } return n; } /* Write out %%CMYKCustomColor line and extensions. * count is the number of lines already written. */ static int write_cmyk_custom(GFile *gf, Doc *doc, const char *renamed[], int count) { /* Create a new %%CMYKCustomColor: * containing only those colours that exist */ CDSC *dsc = doc->dsc; CDSCCOLOUR *colour; int i; int missing; int n = count; FILE_POS begin, end; const char *fname; char buf[MAXSTR]; if ((dsc == NULL) || !dsc->dcs2) return 0; buf[sizeof(buf)-1] = '\0'; for (i=1; i<(int)dsc->page_count; i++) { const char *sepname = renamed[i]; missing = dcs2_separation(dsc, i, &fname, &begin, &end); if (!missing && !is_process_colour(sepname)) { /* find colour values */ for (colour=dsc->colours; colour; colour=colour->next) { if (strcmp(colour->name, dsc->page[i].label)==0) break; } if ((colour != NULL) && (colour->custom == CDSC_CUSTOM_COLOUR_CMYK)) { if (n == 0) strncpy(buf, cmyk_custom_str, sizeof(buf)-1); else strncpy(buf, "%%+", sizeof(buf)-1); snprintf(buf+strlen(buf), sizeof(buf)-1-strlen(buf), " %g %g %g %g (%s)", colour->cyan, colour->magenta, colour->yellow, colour->black, sepname); gfile_puts(gf, buf); gfile_puts(gf, eol_str); n++; } } } return n; } /* Write out %%RGBCustomColor line and extensions. * count is the number of lines already written. */ static int write_rgb_custom(GFile *gf, Doc *doc, const char *renamed[], int count) { /* Create a new %%RGBCustomColor: * containing only those colours that exist */ CDSC *dsc = doc->dsc; CDSCCOLOUR *colour; int i; int missing; int n = count; FILE_POS begin, end; const char *fname; char buf[MAXSTR]; if ((dsc == NULL) || !dsc->dcs2) return 0; buf[sizeof(buf)-1] = '\0'; for (i=1; i<(int)dsc->page_count; i++) { const char *sepname = renamed[i]; missing = dcs2_separation(dsc, i, &fname, &begin, &end); if (!missing && !is_process_colour(sepname)) { /* find colour values */ for (colour=dsc->colours; colour; colour=colour->next) { if (strcmp(colour->name, dsc->page[i].label)==0) break; } if ((colour != NULL) && (colour->custom == CDSC_CUSTOM_COLOUR_RGB)) { if (n == 0) strncpy(buf, cmyk_custom_str, sizeof(buf)-1); else strncpy(buf, "%%+", sizeof(buf)-1); snprintf(buf+strlen(buf), sizeof(buf)-1-strlen(buf), " %g %g %g (%s)", colour->red, colour->green, colour->blue, sepname); gfile_puts(gf, buf); gfile_puts(gf, eol_str); n++; } } } return n; } /* Write out DCS2 platefile comments, and any multiple file separations */ static FILE_POS write_platefile_comments(Doc *doc, GFile *docfile, GFile *epsfile, LPCTSTR epsname, int offset, FILE_POS file_offset, BOOL dcs2_multi, BOOL write_all, BOOL missing_separations, const char *renamed[], BOOL some_renamed) { int i; CDSC *dsc = doc->dsc; FILE_POS begin, end; FILE_POS len; char platename[MAXSTR]; char outbuf[MAXSTR]; GFile *f; FILE_POS offset2 = 0; /* Now write the platefile comments */ for (i=1; i<(int)dsc->page_count; i++) { /* First find length of separation */ int missing; const char *fname = NULL; const char *sepname = renamed[i]; missing = dcs2_separation(dsc, i, &fname, &begin, &end); len = end - begin; /* Now write out platefile */ if (missing && (missing_separations || some_renamed)) { if (debug & DEBUG_GENERAL) app_msgf(doc->app, "Skipping missing separation page %d \042%s\042\n", i, dsc->page[i].label); } else if (dcs2_multi) { int j; int duplicate = 0; memset(platename, 0, sizeof(platename)); cs_to_narrow(platename, sizeof(platename)-1, epsname, (int)cslen(epsname)+1); strncat(platename, ".", sizeof(platename) - strlen(platename)); strncat(platename, sepname, sizeof(platename) - strlen(platename)); for (j=1; jdsc; FILE_POS begin, end; FILE_POS len; GFile *f; if (write_all && !dcs2_multi) { for (i=1; i<(int)dsc->page_count; i++) { int missing; const char *fname = NULL; missing = dcs2_separation(dsc, i, &fname, &begin, &end); len = end - begin; if (missing && (missing_separations || some_renamed)) { if (debug & DEBUG_GENERAL) app_msgf(doc->app, "Skipping missing separation page %d \042%s\042\n", i, dsc->page[i].label); } else if (fname) { TCHAR wfname[MAXSTR]; narrow_to_cs(wfname, (int)sizeof(wfname), fname, (int)strlen(fname)+1); if ((f = gfile_open(wfname, gfile_modeRead)) != (GFile *)NULL) { begin = 0; end = gfile_get_length(f); if (debug & DEBUG_GENERAL) app_msgf(doc->app, "Copying page %d from \042%s\042 %ld %ld\n", i, fname, begin, end); ps_copy(epsfile, f, begin, end); gfile_close(f); } } else { begin = dsc->page[i].begin; end = dsc->page[i].end; if (debug & DEBUG_GENERAL) app_msgf(doc->app, "Copying page %d %ld %ld\n", i, fname, begin, end); ps_copy(epsfile, docfile, begin, end); } } } return 0; } /* Check that two DCS2 files can be combined */ static int check_dcs2_combine(Doc *doc1, Doc *doc2, const char **renamed1, const char **renamed2, int tolerance) { CDSC *dsc1; CDSC *dsc2; const char *sepname1; const char *sepname2; int i, j; if (doc1 == NULL) return -1; if (doc2 == NULL) return -1; dsc1 = doc1->dsc; dsc2 = doc2->dsc; if (!dsc1->dcs2) return -1; if (!dsc2->dcs2) return -1; if (dsc1->bbox == NULL) return -1; if (dsc2->bbox == NULL) return -1; /* Check that bounding boxes match */ if ((dsc1->bbox->llx > dsc2->bbox->llx + tolerance) || (dsc1->bbox->llx < dsc2->bbox->llx - tolerance) || (dsc1->bbox->lly > dsc2->bbox->lly + tolerance) || (dsc1->bbox->lly < dsc2->bbox->lly - tolerance) || (dsc1->bbox->urx > dsc2->bbox->urx + tolerance) || (dsc1->bbox->urx < dsc2->bbox->urx - tolerance) || (dsc1->bbox->ury > dsc2->bbox->ury + tolerance) || (dsc1->bbox->ury < dsc2->bbox->ury - tolerance)) { app_msgf(doc1->app, "Bounding Boxes don't match\n"); return -1; } /* Check that separations don't conflict */ for (i=1; i<(int)dsc1->page_count; i++) { sepname1 = renamed1[i]; for (j=1; i<(int)dsc2->page_count; i++) { sepname2 = renamed2[j]; if (strcmp(sepname1, sepname2) == 0) { app_msgf(doc1->app, "Separation \042%s\042 appears in both files\n", sepname1); return -1; } } } return 0; } /* Copy a DCS 2.0 file. * DSC 2.0 as single file looks like concatenated EPS files. * DSC parser treats these as separate pages and the * entire first EPS file is contained in the first page. * That is, there is no header, prolog or trailer. * Don't update the bounding box. * Do update the %%PlateFile comments. * If missing_separations is true, remove the names of missing * separations from the DSC comments. * The length of the composite page is returned in complen. * If composite is not NULL, use this file as the new composite page * with the existing header. * If rs is not NULL, rename some separations. * If doc2 is not NULL, add its separations. It is an error if * separations are duplicated or the bounding box differs by more * than tolerance points. */ int copy_dcs2(Doc *doc, GFile *docfile, Doc *doc2, GFile *docfile2, GFile *epsfile, LPCTSTR epsname, int offset, BOOL dcs2_multi, BOOL write_all, BOOL missing_separations, FILE_POS *complen, GFile *composite, RENAME_SEPARATION *rs, int tolerance) { const char platefile_str[] = "%%PlateFile:"; const char cyanplate_str[] = "%%CyanPlate:"; const char magentaplate_str[] = "%%MagentaPlate:"; const char yellowplate_str[] = "%%YellowPlate:"; const char blackplate_str[] = "%%BlackPlate:"; const char endcomments_str[] = "%%EndComments"; char buf[DSC_LINE_LENGTH+1]; char outbuf[MAXSTR]; CDSC *dsc = doc->dsc; FILE_POS len; FILE_POS file_offset = *complen; FILE_POS begin, end; FILE_POS header_position; BOOL found_endheader = FALSE; BOOL ignore_continuation = FALSE; int count; const char **renamed1 = NULL; const char **renamed2 = NULL; if (dsc->page_count == 0) return -1; /* Get renamed separations */ renamed1 = (const char **)malloc(sizeof(const char *) * dsc->page_count); if (renamed1 == NULL) return -1; if (rename_separations(dsc, rs, renamed1) != 0) { free((void *)renamed1); return -1; } if (doc2) { renamed2 = (const char **) malloc(sizeof(const char *) * doc2->dsc->page_count); if (renamed2 == NULL) { free((void *)renamed1); return -1; } if (rename_separations(doc2->dsc, rs, renamed2) != 0) { free((void *)renamed1); free((void *)renamed2); return -1; } } if (doc2 && check_dcs2_combine(doc, doc2, renamed1, renamed2, tolerance)) { free((void *)renamed1); free((void *)renamed2); return -1; } gfile_seek(docfile, dsc->page[0].begin, gfile_begin); memset(buf, 0, sizeof(buf)-1); count = ps_fgets(buf, min(sizeof(buf)-1, dsc->page[0].end - dsc->page[0].begin), docfile); header_position = gfile_get_position(docfile); if (count) { /* copy version line */ gfile_write(epsfile, buf, without_eol(buf, count)); gfile_puts(epsfile, eol_str); /* change EOL */ } while ((count = ps_fgets(buf, min(sizeof(buf)-1, dsc->page[0].end - header_position), docfile)) != 0) { header_position = gfile_get_position(docfile); /* check if end of header */ if (count < 2) found_endheader = TRUE; if (buf[0] != '%') found_endheader = TRUE; if ((buf[0] == '%') && ((buf[1] == ' ') || (buf[1] == '\t') || (buf[1] == '\r') || (buf[1] == '\n'))) found_endheader = TRUE; if (strncmp(buf, endcomments_str, strlen(endcomments_str)) == 0) found_endheader = TRUE; if (strncmp(buf, "%%Begin", 7) == 0) found_endheader = TRUE; if (found_endheader) break; /* write out count characters from buf later */ if ((buf[0] == '%') && (buf[1] == '%') && (buf[2] == '+') && ignore_continuation) continue; else ignore_continuation = FALSE; if ((strncmp(buf, platefile_str, strlen(platefile_str)) != 0) && (strncmp(buf, cyanplate_str, strlen(cyanplate_str)) != 0) && (strncmp(buf, magentaplate_str, strlen(magentaplate_str)) != 0) && (strncmp(buf, yellowplate_str, strlen(yellowplate_str)) != 0) && (strncmp(buf, blackplate_str, strlen(blackplate_str)) != 0)) { /* Write all header lines except for DCS plate lines */ if ((rs != NULL) || missing_separations || doc2) { /* but don't write custom/process colour lines */ if (strncmp(buf, custom_str, strlen(custom_str)) == 0) { count = 0; ignore_continuation = TRUE; } else if (strncmp(buf, process_str, strlen(process_str)) == 0) { count = 0; ignore_continuation = TRUE; } else if (strncmp(buf, cmyk_custom_str, strlen(cmyk_custom_str)) == 0) { count = 0; ignore_continuation = TRUE; } else if (strncmp(buf, rgb_custom_str, strlen(rgb_custom_str)) == 0) { count = 0; ignore_continuation = TRUE; } } if (count == 0) continue; gfile_write(epsfile, buf, without_eol(buf, count)); gfile_puts(epsfile, eol_str); /* change EOL */ } } /* Now write DocumentProcessColors, DocumentCustomColors, * CMYKCustomColor and RGBCustomColor */ if ((rs!=NULL) || missing_separations || doc2) { int n; /* number of entries written */ strncpy(outbuf, process_str, sizeof(outbuf)); n = fix_process(doc, outbuf, sizeof(outbuf), renamed1); if (doc2) n += fix_process(doc2, outbuf, sizeof(outbuf), renamed2); if (n) { gfile_write(epsfile, outbuf, without_eol(outbuf, (int)strlen(outbuf))); gfile_puts(epsfile, eol_str); /* change EOL */ } strncpy(outbuf, custom_str, sizeof(outbuf)); n = fix_custom(doc, outbuf, sizeof(outbuf), renamed1); if (doc2) n += fix_custom(doc2, outbuf, sizeof(outbuf), renamed2); if (n) { gfile_write(epsfile, outbuf, without_eol(outbuf, (int)strlen(outbuf))); gfile_puts(epsfile, eol_str); /* change EOL */ } n = write_cmyk_custom(epsfile, doc, renamed1, 0); if (doc2) write_cmyk_custom(epsfile, doc2, renamed2, n); n = write_rgb_custom(epsfile, doc, renamed1, 0); if (doc2) write_rgb_custom(epsfile, doc2, renamed2, n); } /* Write out the platefile comments and any multiple file separations */ len = write_platefile_comments(doc, docfile, epsfile, epsname, offset, file_offset, dcs2_multi, write_all, missing_separations, renamed1, (rs != NULL)); if (len == (FILE_POS)-1) { free((void *)renamed1); if (renamed2) free((void *)renamed2); return -1; } file_offset += len; if (doc2) { len = write_platefile_comments(doc2, docfile2, epsfile, epsname, offset, file_offset, dcs2_multi, write_all, missing_separations, renamed2, (rs != NULL)); if (len == (FILE_POS)-1) { free((void *)renamed1); if (renamed2) free((void *)renamed2); return -1; } file_offset += len; } /* Copy last line of header */ if (found_endheader) { gfile_write(epsfile, buf, without_eol(buf, count)); gfile_puts(epsfile, eol_str); /* change EOL */ } /* copy rest of composite */ if (composite) { if (dsc->page_pages == 1) { gfile_puts(epsfile, "%%Page: 1 1"); gfile_puts(epsfile, eol_str); /* change EOL */ } end = gfile_get_length(composite); gfile_seek(composite, 0, gfile_begin); snprintf(outbuf, sizeof(outbuf)-1, "%%BeginDocument: composite"); gfile_puts(epsfile, "%%BeginDocument: composite"); gfile_puts(epsfile, eol_str); /* change EOL */ ps_copy(epsfile, composite, 0, end); gfile_puts(epsfile, "%%EndDocument"); gfile_puts(epsfile, eol_str); /* change EOL */ gfile_puts(epsfile, "%%Trailer"); gfile_puts(epsfile, eol_str); /* change EOL */ } else { begin = header_position; end = dsc->page[0].end; ps_copy(epsfile, docfile, begin, end); } file_offset = gfile_get_position(epsfile); *complen = file_offset; /* Write out single file separations */ write_singlefile_separations(doc, docfile, epsfile, dcs2_multi, write_all, missing_separations, (rs != NULL)); if (doc2) write_singlefile_separations(doc2, docfile2, epsfile, dcs2_multi, write_all, missing_separations, (rs != NULL)); free((void *)renamed1); if (renamed2) free((void *)renamed2); return 0; } /* Copy an EPS file. * %%BoundingBox and %%HiResBoundingBox will be brought to * the start of the header. * The new EPS file will have a prolog of "offset" bytes, * so update DCS 2.0 offsets accordingly. */ int copy_eps(Doc *doc, LPCTSTR epsname, CDSCBBOX *bbox, CDSCFBBOX *hires_bbox, int offset, BOOL dcs2_multi) { GFile *docfile; GFile *f = NULL; CDSC *dsc = doc->dsc; int code = 0; docfile = gfile_open(doc_name(doc), gfile_modeRead); if (docfile == (GFile *)NULL) { app_csmsgf(doc->app, TEXT("Can't open document file \042%s\042\n"), doc_name(doc)); return -1; } f = gfile_open(epsname, gfile_modeWrite | gfile_modeCreate); if (f == (GFile *)NULL) { app_csmsgf(doc->app, TEXT("Can't open EPS file \042%s\042\n"), epsname); gfile_close(docfile); return -1; } if (dsc->dcs2) { /* Write DCS 2.0, updating the %%PlateFile, but don't update * %%BoundingBox. */ FILE_POS complen = 0; /* length of composite page */ /* Write once to calculate the offsets */ code = copy_dcs2(doc, docfile, NULL, NULL, f, epsname, offset, dcs2_multi, FALSE, FALSE, &complen, NULL, NULL, 0); gfile_seek(docfile, 0, gfile_begin); gfile_close(f); f = NULL; if (code == 0) { f = gfile_open(epsname, gfile_modeWrite | gfile_modeCreate); if (f == (GFile *)NULL) { app_csmsgf(doc->app, TEXT("Can't open EPS file \042%s\042\n"), epsname); gfile_close(docfile); return -1; } } if (code == 0) { /* Then again with the correct offsets */ gfile_seek(f, 0, gfile_begin); code = copy_dcs2(doc, docfile, NULL, NULL, f, epsname, offset, dcs2_multi, TRUE, FALSE, &complen, NULL, NULL, 0); } } else { /* Update the bounding box in the header and remove it from * the trailer */ copy_bbox_header(f, docfile, dsc->begincomments, dsc->endcomments, bbox, hires_bbox); ps_copy(f, docfile, dsc->begindefaults, dsc->enddefaults); ps_copy(f, docfile, dsc->beginprolog, dsc->endprolog); ps_copy(f, docfile, dsc->beginsetup, dsc->endsetup); if (dsc->page_count) ps_copy(f, docfile, dsc->page[0].begin, dsc->page[0].end); copy_nobbox(f, docfile, dsc->begintrailer, dsc->endtrailer); } if (f) gfile_close(f); gfile_close(docfile); return code; } /*********************************************************/ /* make an EPSI file with an Interchange Preview */ /* from a PS file and a bitmap */ int make_eps_interchange(Doc *doc, IMAGE *img, CDSCBBOX devbbox, CDSCBBOX *bbox, CDSCFBBOX *hires_bbox, LPCTSTR epsname) { GFile *epsfile; GFile *docfile; int code; CDSC *dsc = doc->dsc; if (dsc == NULL) return -1; if ((docfile = gfile_open(doc_name(doc), gfile_modeRead)) == (GFile *)NULL) { app_csmsgf(doc->app, TEXT("Can't open EPS file \042%s\042\n"), doc_name(doc)); return -1; } epsfile = gfile_open(epsname, gfile_modeWrite | gfile_modeCreate); if (epsfile == (GFile *)NULL) { app_csmsgf(doc->app, TEXT("Can't open output EPS file \042%s\042\n"), epsname); gfile_close(docfile); return -1; } /* adjust %%BoundingBox: and %%HiResBoundingBox: comments */ copy_bbox_header(epsfile, docfile, dsc->begincomments, dsc->endcomments, bbox, hires_bbox); code = write_interchange(epsfile, img, devbbox); ps_copy(epsfile, docfile, dsc->begindefaults, dsc->enddefaults); ps_copy(epsfile, docfile, dsc->beginprolog, dsc->endprolog); ps_copy(epsfile, docfile, dsc->beginsetup, dsc->endsetup); if (dsc->page_count) ps_copy(epsfile, docfile, dsc->page[0].begin, dsc->page[0].end); copy_nobbox(epsfile, docfile, dsc->begintrailer, dsc->endtrailer); gfile_close(docfile); if (*epsname!='\0') { gfile_close(epsfile); if (code && (!(debug & DEBUG_GENERAL))) csunlink(epsname); } return code; } /*********************************************************/ /* make a PC EPS file with a Windows Metafile Preview */ /* from a PS file and a bitmap */ int make_eps_metafile(Doc *doc, IMAGE *img, CDSCBBOX devbbox, CDSCBBOX *bbox, CDSCFBBOX *hires_bbox, float xdpi, float ydpi, BOOL reverse, LPCTSTR epsname) { MFH mf; GFile *epsfile; GFile *tpsfile; TCHAR tpsname[MAXSTR]; int code; int count; char *buffer; CDSCDOSEPS doseps; /* prepare metafile header and calculate length */ code = metafile_init(img, &devbbox, &mf); /* Create temporary EPS file with updated headers */ tpsfile = NULL; memset(tpsname, 0, sizeof(tpsname)); if ((tpsfile = app_temp_gfile(doc->app, tpsname, sizeof(tpsname)/sizeof(TCHAR))) == (GFile *)NULL) { app_csmsgf(doc->app, TEXT("Can't create temporary EPS file \042%s\042\n"), tpsname); return -1; } gfile_close(tpsfile); code = copy_eps(doc, tpsname, bbox, hires_bbox, DOSEPS_HEADER_SIZE, FALSE); if (code) return -1; if ( (tpsfile = gfile_open(tpsname, gfile_modeRead)) == (GFile *)NULL) { app_csmsgf(doc->app, TEXT("Can't open temporary EPS file \042%s\042\n"), tpsname); return -1; } /* Create DOS EPS output file */ epsfile = gfile_open(epsname, gfile_modeWrite | gfile_modeCreate); if (epsfile == (GFile *)NULL) { app_csmsgf(doc->app, TEXT("Can't open output EPS file \042%s\042\n"), epsname); gfile_close(tpsfile); if (!(debug & DEBUG_GENERAL)) csunlink(tpsname); return -1; } doseps.ps_length = (GSDWORD)gfile_get_length(tpsfile); doseps.wmf_length = mf.size * 2; doseps.tiff_begin = 0; doseps.tiff_length = 0; doseps.checksum = 0xffff; if (reverse) { doseps.wmf_begin = DOSEPS_HEADER_SIZE; doseps.ps_begin = doseps.wmf_begin + doseps.wmf_length; } else { doseps.ps_begin = DOSEPS_HEADER_SIZE; doseps.wmf_begin = doseps.ps_begin + doseps.ps_length; } write_doseps_header(&doseps, epsfile); buffer = (char *)malloc(COPY_BUF_SIZE); if (buffer == (char *)NULL) { if (epsname[0]) { gfile_close(epsfile); if (!(debug & DEBUG_GENERAL)) csunlink(epsname); } gfile_close(tpsfile); if (!(debug & DEBUG_GENERAL)) csunlink(tpsname); return -1; } gfile_seek(tpsfile, 0, gfile_begin); if (!reverse) { /* copy EPS file */ while ((count = (int)gfile_read(tpsfile, buffer, COPY_BUF_SIZE)) != 0) gfile_write(epsfile, buffer, count); } /* copy metafile */ code = write_metafile(epsfile, img, devbbox, xdpi, ydpi, &mf); if (reverse) { /* copy EPS file */ while ((count = (int)gfile_read(tpsfile, buffer, COPY_BUF_SIZE)) != 0) gfile_write(epsfile, buffer, count); } free(buffer); gfile_close(tpsfile); if (!(debug & DEBUG_GENERAL)) csunlink(tpsname); if (epsname[0]) gfile_close(epsfile); return 0; } /*********************************************************/ /* Create a Macintosh file with PICT preview */ /* from a PS file and a bitmap */ int make_eps_pict(Doc *doc, IMAGE *img, CDSCBBOX *bbox, CDSCFBBOX *hires_bbox, float xdpi, float ydpi, CMAC_TYPE mac_type, LPCTSTR epsname) { GFile *epsfile; GFile *tpsfile; TCHAR tpsname[MAXSTR]; GFile *tpictfile; TCHAR tpictname[MAXSTR]; char filename[MAXSTR]; int code = 0; int len; CMAC_TYPE type = mac_type; const TCHAR *tp, *tq; len = (int)cslen(epsname); if (mac_type != CMAC_TYPE_NONE) type = mac_type; else if (epsname[0] == '.') type = CMAC_TYPE_DOUBLE; else if ((len > 3) && (epsname[len-3] == '.') && ((epsname[len-2] == 'a') || (epsname[len-2] == 'A')) && ((epsname[len-1] == 's') || (epsname[len-1] == 'S')) ) type = CMAC_TYPE_SINGLE; else if ((len > 5) && ((epsname[len-5] == '.') || (epsname[len-5] == '/')) && ((epsname[len-4] == 'r') || (epsname[len-4] == 'R')) && ((epsname[len-3] == 's') || (epsname[len-3] == 'S')) && ((epsname[len-2] == 'r') || (epsname[len-2] == 'R')) && ((epsname[len-1] == 'c') || (epsname[len-1] == 'C')) ) type = CMAC_TYPE_RSRC; else type = CMAC_TYPE_MACBIN; /* Create temporary EPS file with updated headers */ tpsfile = NULL; memset(tpsname, 0, sizeof(tpsname)); if ((tpsfile = app_temp_gfile(doc->app, tpsname, sizeof(tpsname)/sizeof(TCHAR))) == (GFile *)NULL) { app_csmsgf(doc->app, TEXT("Can't create temporary EPS file \042%s\042\n"), tpsname); return -1; } gfile_close(tpsfile); code = copy_eps(doc, tpsname, bbox, hires_bbox, 0, FALSE); if (code) return -1; if ( (tpsfile = gfile_open(tpsname, gfile_modeRead)) == (GFile *)NULL) { app_csmsgf(doc->app, TEXT("Can't open temporary EPS file \042%s\042\n"), tpsname); return -1; } gfile_close(tpsfile); /* Create temporary PICT file */ tpictfile = NULL; memset(tpictname, 0, sizeof(tpictname)); if ((tpictfile = app_temp_gfile(doc->app, tpictname, sizeof(tpictname)/sizeof(TCHAR))) == (GFile *)NULL) { app_csmsgf(doc->app, TEXT("Can't create temporary PICT file \042%s\042\n"), tpictname); return -1; } gfile_close(tpictfile); code = image_to_pictfile(img, tpictname, xdpi, ydpi); /* Create Mac output file */ epsfile = gfile_open(epsname, gfile_modeWrite | gfile_modeCreate); if (epsfile == (GFile *)NULL) { app_csmsgf(doc->app, TEXT("Can't open output EPS file \042%s\042\n"), epsname); gfile_close(tpsfile); if (!(debug & DEBUG_GENERAL)) csunlink(tpsname); return -1; } switch (type) { case CMAC_TYPE_SINGLE: code = write_applesingle(epsfile, tpsname, tpictname); break; case CMAC_TYPE_DOUBLE: code = write_appledouble(epsfile, tpictname); break; case CMAC_TYPE_MACBIN: memset(filename, 0, sizeof(filename)); /* Remove path information */ tp = tq = epsname; while (*tp != '\0') { if ((*tp == '\\') || (*tp == '/') || (*tp == ':')) tq = CHARNEXT(tp); tp = CHARNEXT(tp); } cs_to_narrow(filename, (int)sizeof(filename)-1, tq, (int)cslen(tq)+1); len = (int)strlen(filename); /* Remove trailing .bin */ if ((len > 4) && (filename[len-4] == '.') && ((filename[len-3] == 'b') || (filename[len-3] == 'B')) && ((filename[len-2] == 'i') || (filename[len-2] == 'I')) && ((filename[len-1] == 'n') || (filename[len-1] == 'N')) ) filename[len-4] = '\0'; /* remove ".bin" inside MacBinary */ code = write_macbin(epsfile, filename, tpsname, tpictname); break; case CMAC_TYPE_RSRC: /* Just copy the resources */ code = (write_resource_pict(epsfile, tpictname) < 0); break; default: code = -1; } if (!(debug & DEBUG_GENERAL)) csunlink(tpsname); if (!(debug & DEBUG_GENERAL)) csunlink(tpictname); if (epsname[0]) { gfile_close(epsfile); if ((code<0) && (!(debug & DEBUG_GENERAL))) csunlink(epsname); } return code; } /*********************************************************/ /* Copy one page to a file. * This will be used for feeding directly to Ghostscript, * so don't bother updating header comments. * Add code to force one and one only showpage. */ int copy_page_temp(Doc *doc, GFile *f, int page) { const char save_str[] = "%!\nsave /GSview_save exch def\n/showpage {} def\n"; const char restore_str[] = "\nclear cleardictstack GSview_save restore\nshowpage\n"; int code; gfile_puts(f, save_str); code = copy_page_nosave(doc, f, page); gfile_puts(f, restore_str); return code; } int copy_page_nosave(Doc *doc, GFile *f, int page) { CDSC *dsc = doc->dsc; GFile *docfile; const char *fname; if (dsc == NULL) return -1; fname = dsc_find_platefile(dsc, page); if (fname) { /* A separation in a separate file */ FILE_POS end; TCHAR wfname[MAXSTR]; narrow_to_cs(wfname, (int)sizeof(wfname), fname, (int)strlen(fname)+1); if ((docfile = gfile_open(wfname, gfile_modeRead)) != (GFile *)NULL) { end = gfile_get_length(docfile); ps_copy(f, docfile, 0, end); gfile_close(docfile); } /* else separation is missing, don't flag an error */ } else { /* ordinary file */ if ((docfile = gfile_open(doc_name(doc), gfile_modeRead)) == (GFile *)NULL) { app_csmsgf(doc->app, TEXT("Can't open document file \042%s\042\n"), doc_name(doc)); return -1; } ps_copy(f, docfile, dsc->begincomments, dsc->endcomments); ps_copy(f, docfile, dsc->begindefaults, dsc->enddefaults); ps_copy(f, docfile, dsc->beginprolog, dsc->endprolog); ps_copy(f, docfile, dsc->beginsetup, dsc->endsetup); if (dsc->page_count && (page >= 0) && (page < (int)dsc->page_count)) ps_copy(f, docfile, dsc->page[page].begin, dsc->page[page].end); ps_copy(f, docfile, dsc->begintrailer, dsc->endtrailer); gfile_close(docfile); } return 0; } /*********************************************************/ epstool-3.08/src/ceps.h0000644000076400007640000000430110252260054014425 0ustar rjlrjl00000000000000/* Copyright (C) 1993-2005 Ghostgum Software Pty Ltd. All rights reserved. This software is provided AS-IS with no warranty, either express or implied. This software is distributed under licence and may not be copied, modified or distributed except as expressly authorised under the terms of the licence contained in the file LICENCE in this distribution. For more information about licensing, please refer to http://www.ghostgum.com.au/ or contact Ghostsgum Software Pty Ltd, 218 Gallaghers Rd, Glen Waverley VIC 3150, AUSTRALIA, Fax +61 3 9886 6616. */ /* $Id: ceps.h,v 1.13 2005/06/10 09:39:24 ghostgum Exp $ */ /* EPS preview manipulation */ int extract_doseps(Doc *doc, LPCTSTR outname, BOOL preview); int extract_macbin(Doc *doc, LPCTSTR outname, BOOL preview); int make_eps_tiff(Doc *doc, IMAGE *img, CDSCBBOX devbbox, CDSCBBOX *bbox, CDSCFBBOX *hires_bbox, float xdpi, float ydpi, BOOL tiff4, BOOL use_packbits, BOOL reverse, LPCTSTR epsname); int make_eps_user(Doc *doc, LPCTSTR preview_name, BOOL reverse, LPCTSTR epsname); int make_eps_interchange(Doc *doc, IMAGE *img, CDSCBBOX devbbox, CDSCBBOX *bbox, CDSCFBBOX *hires_bbox, LPCTSTR epsname); int make_eps_metafile(Doc *doc, IMAGE *img, CDSCBBOX devbbox, CDSCBBOX *bbox, CDSCFBBOX *hires_bbox, float xdpi, float ydpi, BOOL reverse, LPCTSTR epsname); int make_eps_pict(Doc *doc, IMAGE *img, CDSCBBOX *bbox, CDSCFBBOX *hires_bbox, float xdpi, float ydpi, CMAC_TYPE type, LPCTSTR epsname); int copy_page_temp(Doc *doc, GFile *f, int page); int copy_page_nosave(Doc *doc, GFile *f, int page); int copy_eps(Doc *doc, LPCTSTR epsname, CDSCBBOX *bbox, CDSCFBBOX *hires_bbox, int offset, BOOL dcs2_multi); typedef struct RENAME_SEPARATION_s RENAME_SEPARATION; struct RENAME_SEPARATION_s { char *oldname; char *newname; RENAME_SEPARATION *next; }; int rename_separations(CDSC *dsc, RENAME_SEPARATION *rs, const char *renamed[]); int copy_dcs2(Doc *doc, GFile *docfile, Doc *doc2, GFile *docfile2, GFile *epsfile, LPCTSTR epsname, int offset, BOOL dcs2_multi, BOOL write_all, BOOL missing_separations, FILE_POS *complen, GFile *composite, RENAME_SEPARATION *rs, int tolerance); epstool-3.08/src/epstool.spec0000644000076400007640000000443510252260054015673 0ustar rjlrjl00000000000000# # Spec file for epstool 3.08 # # 3.08 release # 2005-06-06 Russell Lang # Name: epstool Version: 3.08 Release: 1 Epoch: 0 Summary: Create or extract preview images in EPS files License: GPL Group: Applications/Graphics Source: ftp://mirror.cs.wisc.edu/pub/mirrors/ghost/ghostgum/epstool-3.08.tar.gz URL: http://www.cs.wisc.edu/~ghost/gsview/ Vendor: Ghostgum Software Pty Ltd Packager: Russell Lang Requires: ghostscript BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n) %description Epstool is a utility to create or extract preview images in EPS files. Add Interchange (EPSI), DOS EPS or PICT preview. Extract PostScript or preview from DOS EPS or Macintosh EPSF files. Create preview using ghostscript. Automatically calculate bounding box using ghostscript and update in EPS file. Handle DCS 2.0 (Desktop Color Separations). %prep rm -rf $RPM_BUILD_DIR/epstool-%{version} mkdir $RPM_BUILD_DIR/epstool-%{version} %setup -n epstool-%{version} %build cd $RPM_BUILD_DIR/epstool-%{version} make RPM_OPT_FLAGS="$RPM_OPT_FLAGS" \ EPSTOOL_BASE=%{_prefix} \ EPSTOOL_BINDIR=%{_bindir} \ EPSTOOL_MANDIR=%{_mandir} \ EPSTOOL_DOCDIR=%{_docdir} %install rm -rf $RPM_BUILD_ROOT install -d $RPM_BUILD_ROOT%{_bindir} install -d $RPM_BUILD_ROOT%{_mandir} install -d $RPM_BUILD_ROOT%{_docdir} cd $RPM_BUILD_DIR/epstool-%{version} make install \ EPSTOOL_BASE=$RPM_BUILD_ROOT%{_prefix} \ EPSTOOL_BINDIR=$RPM_BUILD_ROOT%{_bindir} \ EPSTOOL_MANDIR=$RPM_BUILD_ROOT%{_mandir} \ EPSTOOL_DOCDIR=$RPM_BUILD_ROOT%{_docdir} %clean rm -rf $RPM_BUILD_DIR/%{name}-%{version} rm -rf $RPM_BUILD_ROOT %files %defattr(-, root, root) %doc %{_docdir}/* %{_bindir}/* %{_mandir}/man*/* %changelog * Fri Jun 10 2005 Russell Lang - epstool 3.08 release * Fri Jan 07 2005 Russell Lang - epstool 3.07 release * Thu Nov 28 2004 Russell Lang - epstool 3.06 release * Thu Apr 22 2004 Russell Lang - epstool 3.05 release Initial spec file Unfortunately RPM requires that dates be written backwards. Release date should be "Thu 22 Apr 2004" or preferably 2004-04-22. epstool-3.08/src/epstool.mak0000644000076400007640000000575310252260054015515 0ustar rjlrjl00000000000000# Copyright (C) 2002-2005 Ghostgum Software Pty Ltd. All rights reserved. # # This software is provided AS-IS with no warranty, either express or # implied. # # This software is distributed under licence and may not be copied, # modified or distributed except as expressly authorised under the terms # of the licence contained in the file LICENCE in this distribution. # # For more information about licensing, please refer to # http://www.ghostgum.com.au/ or contact Ghostsgum Software Pty Ltd, # 218 Gallaghers Rd, Glen Waverley VIC 3150, AUSTRALIA, # Fax +61 3 9886 6616. # # $Id: epstool.mak,v 1.9 2005/03/25 03:37:59 ghostgum Exp $ # Make epstool for GNU/Linux BINDIR=./bin OBJDIR=./epsobj SRCDIR=./src SRCWINDIR=./srcwin XINCLUDE= PFLAGS= PLINK= GTKCFLAGS= GTKLIBS= LIBPNGINC= LIBPNGCFLAGS= LIBPNGLIBS= LONGFILEDEF= LONGFILEMOD=cfile include $(SRCDIR)/unixcom.mak EPSOBJPLAT=$(OD)xnodll$(OBJ) $(OD)$(LONGFILEMOD)$(OBJ) EPSLIB=$(LIBPNGLIBS) BEGIN=$(OD)lib.rsp TARGET=epstool include $(SRCDIR)/common.mak EPSTOOL_ROOT=/usr/local EPSTOOL_BASE=$(prefix)$(EPSTOOL_ROOT) EPSTOOL_DOCDIR=$(EPSTOOL_BASE)/share/doc/epstool-$(EPSTOOL_VERSION) EPSTOOL_MANDIR=$(EPSTOOL_BASE)/man EPSTOOL_BINDIR=$(EPSTOOL_BASE)/bin epstool: $(BD)epstool$(EXE) epstest: epstool $(BD)epstest$(EXE) $(BD)epstest$(EXE) $(OD)lib.rsp: makefile -mkdir $(BINDIR) -mkdir $(OBJDIR) echo "dummy" > $(OD)lib.rsp install: $(TARGET) -mkdir -p $(EPSTOOL_BASE) chmod a+rx $(EPSTOOL_BASE) -mkdir -p $(EPSTOOL_BINDIR) chmod a+rx $(EPSTOOL_BINDIR) $(INSTALL_EXE) $(BD)epstool$(EXE) $(EPSTOOL_BINDIR)$(DD)epstool$(EXE) -strip $(EPSTOOL_BINDIR)$(DD)epstool$(EXE) -mkdir -p $(EPSTOOL_MANDIR) chmod a+rx $(EPSTOOL_MANDIR) -mkdir -p $(EPSTOOL_MANDIR)$(DD)man1 chmod a+rx $(EPSTOOL_MANDIR)$(DD)man1 $(INSTALL) doc$(DD)epstool.1 $(EPSTOOL_MANDIR)$(DD)man1$(DD)epstool.1 -mkdir -p $(EPSTOOL_DOCDIR) chmod a+rx $(EPSTOOL_DOCDIR) $(INSTALL) doc$(DD)epstool.htm $(EPSTOOL_DOCDIR)$(DD)epstool.htm $(INSTALL) doc$(DD)gsview.css $(EPSTOOL_DOCDIR)$(DD)gsview.css $(INSTALL) LICENCE $(EPSTOOL_DOCDIR)$(DD)LICENCE CYGWIN_DISTDIR=./dist CYGWIN_PACKAGE=epstool-$(EPSTOOL_VERSION)-1 CYGWIN_DOCDIR=$(CYGWIN_DISTDIR)/usr/share/doc/Cygwin cygwin: rm -rf $(CYGWIN_DISTDIR)/* $(MAKE) -f src/epstool.mak prefix=$(CYGWIN_DISTDIR) EXE=.exe EPSTOOL_ROOT=/usr EPSTOOL_MANDIR=$(CYGWIN_DISTDIR)/usr/share/man install -mkdir -p $(CYGWIN_DOCDIR) chmod a+rx $(CYGWIN_DOCDIR) $(INSTALL) doc/cygwin.README $(CYGWIN_DOCDIR)$(DD)epstool-$(EPSTOOL_VERSION).README (cd $(CYGWIN_DISTDIR); tar -cjf ../$(CYGWIN_PACKAGE).tar.bz2 *) rm -rf $(CYGWIN_DISTDIR)/* mv $(CYGWIN_PACKAGE).tar.bz2 $(CYGWIN_DISTDIR) cp doc/cygwin.hint $(CYGWIN_DISTDIR)/setup.hint make -f src/epstool.mak EXE=.exe EPSDIST=$(CYGWIN_PACKAGE) $(EPSTAR) mv $(EPSTAR) $(CYGWIN_DISTDIR)/$(CYGWIN_PACKAGE)-src.tar bzip2 $(CYGWIN_DISTDIR)/$(CYGWIN_PACKAGE)-src.tar clean: -$(RM) $(EPSOBJS) -$(RM) $(EPSTESTOBJS) -$(RM) $(OD)lib.rsp -$(RM) $(BD)epstool$(EXE) -$(RM) $(BD)epstest$(EXE) -rmdir $(OBJDIR) epstool-3.08/src/unix.mak0000644000076400007640000000761510252260054015012 0ustar rjlrjl00000000000000# Copyright (C) 2002-2005 Ghostgum Software Pty Ltd. All rights reserved. # # This software is provided AS-IS with no warranty, either express or # implied. # # This software is distributed under licence and may not be copied, # modified or distributed except as expressly authorised under the terms # of the licence contained in the file LICENCE in this distribution. # # For more information about licensing, please refer to # http://www.ghostgum.com.au/ or contact Ghostsgum Software Pty Ltd, # 218 Gallaghers Rd, Glen Waverley VIC 3150, AUSTRALIA, # Fax +61 3 9886 6616. # # $Id: unix.mak,v 1.24 2005/06/10 09:39:24 ghostgum Exp $ # Unix makefile for GSview BINDIR=./bin OBJDIR=./obj SRCDIR=./src SRCWINDIR=./srcwin XINCLUDE= PFLAGS=-DMULTITHREAD PLINK=-lpthread -lrt GTKCFLAGS=-DGTK `pkg-config --cflags gtk+-2.0` -DGTK_DISABLE_DEPRECATED -DDEBUG_MALLOC GTKLIBS=`pkg-config --libs gtk+-2.0` LIBPNGINC=-Ilibpng -Izlib LIBPNGCFLAGS=-DHAVE_LIBPNG LIBPNGLIBS=-lpng #LONGFILEDEF=-DLARGEFILES -DFILE_OFFSET="long long" -DDSC_OFFSET="unsigned long long" -DDSC_OFFSET_FORMAT=\"llu\" -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64 #LONGFILEMOD=clfile LONGFILEDEF= LONGFILEMOD=cfile include $(SRCDIR)/unixcom.mak OBJPLAT=$(OD)xapp$(OBJ) $(OD)xdll$(OBJ) $(OD)xdlg$(OBJ) \ $(OD)xdoc$(OBJ) \ $(OD)xgsimg$(OBJ) $(OD)xgssrv$(OBJ) $(OD)ximg$(OBJ) \ $(OD)xmain$(OBJ) $(OD)xmenu$(OBJ) $(OD)xopt$(OBJ) \ $(OD)xview$(OBJ) $(OD)$(LONGFILEMOD)$(OBJ) xview_h=$(SRC)xview.h XPM=$(SRCDIR)/xpm/$(NUL) XPMBUTTONS=$(XPM)xback.xpm $(XPM)xfwd.xpm $(XPM)xgoto.xpm $(XPM)xhelp.xpm \ $(XPM)xinfo.xpm $(XPM)xmagm.xpm $(XPM)xmagp.xpm $(XPM)xnext.xpm \ $(XPM)xnexts.xpm $(XPM)xopen.xpm $(XPM)xprev.xpm $(XPM)xprevs.xpm \ $(XPM)xprint.xpm BEGIN=$(OD)lib.rsp TARGET=$(BD)gsview$(EXE) include $(SRCDIR)/common.mak $(TARGET): $(OBJS) $(LINK) $(FE)$(TARGET) $(OBJS) $(LFLAGS) $(OD)lib.rsp: makefile -mkdir $(BINDIR) -mkdir $(OBJDIR) echo "dummy" > $(OD)lib.rsp # X11/gtk+ specific $(OD)xapp$(OBJ): $(SRC)xapp.c $(common_h) $(dscparse_h) \ $(copt_h) $(capp_h) $(cres_h) $(cver_h) $(cview_h) \ en/clang.h en/clang.rc $(SRC)xlang.rc $(COMP) -Ien -I. $(FOO)xapp$(OBJ) $(CO) $(SRC)xapp.c $(OD)xdlg$(OBJ): $(SRC)xdlg.c $(common_h) $(dscparse_h) \ $(capp_h) $(cres_h) $(cview_h) $(COMP) $(FOO)xdlg$(OBJ) $(CO) $(SRC)xdlg.c $(OD)xdoc$(OBJ): $(SRC)xdoc.c $(common_h) $(dscparse_h) $(capp_h) $(cdoc_h) $(COMP) $(FOO)xdoc$(OBJ) $(CO) $(SRC)xdoc.c $(OD)xgsimg$(OBJ): $(SRC)xgsimg.c $(common_h) $(gdevdsp_h) $(errors_h) \ $(capp_h) $(cimg_h) $(cdisplay_h) $(COMP) $(FOO)xgsimg$(OBJ) $(CO) $(SRC)xgsimg.c $(OD)xgssrv$(OBJ): $(SRC)xgssrv.c $(common_h) $(gdevdsp_h) $(dscparse_h) \ $(capp_h) $(cimg_h) $(cdisplay_h) $(copt_h) $(cpdf_h) $(cgssrv_h) $(COMP) $(FOO)xgssrv$(OBJ) $(CO) $(SRC)xgssrv.c $(OD)ximg$(OBJ): $(SRC)ximg.c $(common_h) $(gdevdsp_h) $(errors_h) $(cimg_h) $(COMP) $(FOO)ximg$(OBJ) $(CO) $(SRC)ximg.c $(OD)xmain$(OBJ): $(SRC)xmain.c $(common_h) $(errors_h) $(iapi_h) \ $(dscparse_h) $(copt_h) $(capp_h) $(cargs_h) $(cdoc_h) \ $(cdll_h) $(cgsdll_h) $(cmsg_h) $(cview_h) $(cvcmd_h) $(COMP) $(FOO)xmain$(OBJ) $(CO) $(SRC)xmain.c $(OD)xmenu$(OBJ): $(SRC)xmenu.c $(common_h) $(copt_h) $(cres_h) \ $(cvcmd_h) $(cview_h) $(xview_h) $(XPMBUTTONS) $(COMP) $(FOO)xmenu$(OBJ) $(CO) $(SRC)xmenu.c $(OD)xopt$(OBJ): $(SRC)xopt.c $(common_h) $(dscparse_h) \ $(capp_h) $(cres_h) $(cview_h) $(COMP) $(FOO)xopt$(OBJ) $(CO) $(SRC)xopt.c $(OD)xview$(OBJ): $(SRC)xview.c $(common_h) \ $(errors_h) $(iapi_h) $(gdevdsp_h) \ $(dscparse_h) $(copt_h) $(capp_h) $(cimg_h) $(cdisplay_h) $(cmsg_h) \ $(dpagec_h) $(cgssrv_h) $(cvcmd_h) $(cview_h) $(xview_h) $(COMP) $(FOO)xview$(OBJ) $(CO) $(SRC)xview.c # Languages $(BD)en.txt: $(SRC)xlang.c $(cver_h) $(cres_h) $(SRC)xlang.rc \ en/clang.h en/clang.rc $(COMP) -Ien $(FEO)xlangen$(EXE) $(SRC)xlang.c $(BD)xlangen$(EXE) > $(BD)en.txt clean: -$(RM) $(OBJS) -$(RM) $(TARGET) -$(RM) $(OD)lib.rsp -rmdir $(BINDIR) $(OBJDIR) epstool-3.08/src/cfile.h0000644000076400007640000000720510252260054014563 0ustar rjlrjl00000000000000/* Copyright (C) 2000-2005 Ghostgum Software Pty Ltd. All rights reserved. This software is provided AS-IS with no warranty, either express or implied. This software is distributed under licence and may not be copied, modified or distributed except as expressly authorised under the terms of the licence contained in the file LICENCE in this distribution. For more information about licensing, please refer to http://www.ghostgum.com.au/ or contact Ghostsgum Software Pty Ltd, 218 Gallaghers Rd, Glen Waverley VIC 3150, AUSTRALIA, Fax +61 3 9886 6616. */ /* $Id: cfile.h,v 1.4 2005/06/10 09:39:24 ghostgum Exp $ */ /* GFile is similar but to MFC CFile but is implemented as C, not C++. * It may also support long files if FILE_POS is > 32-bits. * FILE_OFFSET is a signed integer used for positioning a file. * FILE_POS is an unsigned integer used for positioning a file. * * GFile should really be buffered, but it isn't a disaster * if it is unbuffered. Reading of PostScript files for parsing * or DSC comments uses 4kbyte blocks, while normal reading uses 1kbyte. * Handling of bitmap files will generally read/write headers in * 2 and 4 blocks, but read/write raster data in text line or * scan line blocks. */ #if defined(STDIO) || defined(MEMORYFILE) || !defined(_Windows) || defined(OS2) # ifndef LPCTSTR # define LPCTSTR const char * # endif # ifndef GENERIC_READ # define GENERIC_READ (0x80000000L) # endif # ifndef FILE_SHARE_READ # define FILE_SHARE_READ 0x00000001 # endif #endif #ifndef FILE_OFFSET # define FILE_OFFSET long #endif #ifndef FILE_POS # define FILE_POS unsigned FILE_OFFSET #endif typedef struct GFile_s GFile; /* for gfile_open nOpenFlags */ enum OpenFlags {gfile_modeRead = 0x0000, gfile_modeWrite = 0x0001, gfile_shareExclusive=0x0010, gfile_shareDenyWrite=0x0020, gfile_modeCreate=0x1000}; /* for gfile_seek nFrom */ enum {gfile_begin, gfile_current, gfile_end}; /* Open a file from a Windows or OS handle */ /* We use "void *" instead of "int" because Windows handles * are the same size as pointers, while int is smaller for Win64. */ GFile *gfile_open_handle(void *hFile, unsigned int nOpenFlags); /* Open a file */ GFile *gfile_open(LPCTSTR lpszFileName, unsigned int nOpenFlags); /* Close a file */ void gfile_close(GFile *gf); /* Read from a file */ unsigned int gfile_read(GFile *gf, void *lpBuf, unsigned int nCount); /* Write to a file */ unsigned int gfile_write(GFile *gf, const void *lpBuf, unsigned int nCount); /* Seek to a position in the file. */ /* Reset any file errors. */ int gfile_seek(GFile *gf, FILE_OFFSET lOff, unsigned int nFrom); /* Get the current file position */ FILE_POS gfile_get_position(GFile *gf); /* Get the file length */ FILE_POS gfile_get_length(GFile *gf); /* Get the file date and time. The actual data format * in pdt_low and pdt_high is undefined, and is only used * for comparison by gfile_changed(). * Return 0 if success, -ve for failure. */ int gfile_get_datetime(GFile *gf, unsigned long *pdt_low, unsigned long *pdt_high); /* Check if the length or datetime has changed. Use gfile_get_length * and gfile_get_datetime. * Return non-zero if changed, zero if unchanged. */ int gfile_changed(GFile *gf, FILE_POS length, unsigned long dt_low, unsigned long dt_high); /* Return non-zero if a file error occurred */ int gfile_error(GFile *gf); /* For memory mapped file, set the base address and length of the * memory block. */ void gfile_set_memory(GFile *gf, const char *base, FILE_POS len); /***********************************************************/ /* These are implementation independent */ int gfile_puts(GFile *gf, const char *str); epstool-3.08/src/cimg.c0000644000076400007640000015702210252260054014416 0ustar rjlrjl00000000000000/* Copyright (C) 2001-2005 Ghostgum Software Pty Ltd. All rights reserved. This software is provided AS-IS with no warranty, either express or implied. This software is distributed under licence and may not be copied, modified or distributed except as expressly authorised under the terms of the licence contained in the file LICENCE in this distribution. For more information about licensing, please refer to http://www.ghostgum.com.au/ or contact Ghostsgum Software Pty Ltd, 218 Gallaghers Rd, Glen Waverley VIC 3150, AUSTRALIA, Fax +61 3 9886 6616. */ /* $Id: cimg.c,v 1.21 2005/06/10 09:39:24 ghostgum Exp $ */ /* Common image format and conversion functions */ #include "common.h" #include "gdevdsp.h" #include "cimg.h" #include "clzw.h" static int a85write(char *line, unsigned char *buf, int count); /* Return a palette entry for given format and index */ void image_colour(unsigned int format, int index, unsigned char *r, unsigned char *g, unsigned char *b) { switch (format & DISPLAY_COLORS_MASK) { case DISPLAY_COLORS_NATIVE: switch (format & DISPLAY_DEPTH_MASK) { case DISPLAY_DEPTH_1: *r = *g = *b = (unsigned char)(index ? 0 : 255); break; case DISPLAY_DEPTH_4: { int one = index & 8 ? 255 : 128; *r = (unsigned char)(index & 4 ? one : 0); *g = (unsigned char)(index & 2 ? one : 0); *b = (unsigned char)(index & 1 ? one : 0); } break; case DISPLAY_DEPTH_8: /* palette of 96 colours */ /* 0->63 = 00RRGGBB, 64->95 = 010YYYYY */ if (index < 64) { int one = 255 / 3; *r = (unsigned char)(((index & 0x30) >> 4) * one); *g = (unsigned char)(((index & 0x0c) >> 2) * one); *b = (unsigned char)( (index & 0x03) * one); } else { int val = index & 0x1f; *r = *g = *b = (unsigned char)((val << 3) + (val >> 2)); } break; } break; case DISPLAY_COLORS_GRAY: switch (format & DISPLAY_DEPTH_MASK) { case DISPLAY_DEPTH_1: *r = *g = *b = (unsigned char)(index ? 255 : 0); break; case DISPLAY_DEPTH_4: *r = *g = *b = (unsigned char)((index<<4) + index); break; case DISPLAY_DEPTH_8: *r = *g = *b = (unsigned char)index; break; } break; } } unsigned char colour_to_grey(unsigned char r, unsigned char g, unsigned char b) { return (unsigned char) ((r * 77) / 255 + (g * 150) / 255 + (b * 28) / 255); } /********************************************************/ /* 24BGR */ /* convert one line of 4-bit native to 24BGR */ void image_4native_to_24BGR(int width, unsigned char *dest, unsigned char *source) { int i; int val; for (i=0; i>= 4; val &= 0x0f; image_colour(DISPLAY_COLORS_NATIVE | DISPLAY_DEPTH_4, val, dest+2, dest+1, dest); dest += 3; } } /* convert one line of 16BGR555 to 24BGR */ /* byte0=GGGBBBBB byte1=0RRRRRGG */ void image_16BGR555_to_24BGR(int width, unsigned char *dest, unsigned char *source) { int i; WORD w; unsigned char value; for (i=0; i> 2)); value = (unsigned char)((w >> 5) & 0x1f); /* green */ *dest++ = (unsigned char)((value << 3) + (value >> 2)); value = (unsigned char)((w >> 10) & 0x1f); /* red */ *dest++ = (unsigned char)((value << 3) + (value >> 2)); source += 2; } } /* convert one line of 16BGR565 to 24BGR */ /* byte0=GGGBBBBB byte1=RRRRRGGG */ void image_16BGR565_to_24BGR(int width, unsigned char *dest, unsigned char *source) { int i; WORD w; unsigned char value; for (i=0; i> 2)); value = (unsigned char)((w >> 5) & 0x3f); /* green */ *dest++ = (unsigned char)((value << 2) + (value >> 4)); value = (unsigned char)((w >> 11) & 0x1f); /* red */ *dest++ = (unsigned char)((value << 3) + (value >> 2)); source += 2; } } /* convert one line of 16RGB555 to 24BGR */ /* byte0=0RRRRRGG byte1=GGGBBBBB */ void image_16RGB555_to_24BGR(int width, unsigned char *dest, unsigned char *source) { int i; WORD w; unsigned char value; for (i=0; i> 2)); value = (unsigned char)((w >> 5) & 0x1f); /* green */ *dest++ = (unsigned char)((value << 3) + (value >> 2)); value = (unsigned char)((w >> 10) & 0x1f); /* red */ *dest++ = (unsigned char)((value << 3) + (value >> 2)); source += 2; } } /* convert one line of 16RGB565 to 24BGR */ /* byte0=RRRRRGGG byte1=GGGBBBBB */ void image_16RGB565_to_24BGR(int width, unsigned char *dest, unsigned char *source) { int i; WORD w; unsigned char value; for (i=0; i> 2)); value = (unsigned char)((w >> 5) & 0x3f); /* green */ *dest++ = (unsigned char)((value << 2) + (value >> 4)); value = (unsigned char)((w >> 11) & 0x1f); /* red */ *dest++ = (unsigned char)((value << 3) + (value >> 2)); source += 2; } } /* convert one line of 32CMYK to 24BGR */ void image_32CMYK_to_24BGR(int width, unsigned char *dest, unsigned char *source, int sep) { int i; int cyan, magenta, yellow, black; for (i=0; iwidth; unsigned int alpha = img->format & DISPLAY_ALPHA_MASK; BOOL bigendian = (img->format & DISPLAY_ENDIAN_MASK) == DISPLAY_BIGENDIAN; int code = -1; int i; switch (img->format & DISPLAY_COLORS_MASK) { case DISPLAY_COLORS_NATIVE: if ((img->format & DISPLAY_DEPTH_MASK) == DISPLAY_DEPTH_1) { image_1native_to_24RGB(width, dest, source); /* monochrome */ code = 0; } else if ((img->format & DISPLAY_DEPTH_MASK) == DISPLAY_DEPTH_4) { image_4native_to_24BGR(width, dest, source); code = 0; } else if ((img->format & DISPLAY_DEPTH_MASK) == DISPLAY_DEPTH_8) { for (i=0; iformat, *s++, d+2, d+1, d); d+= 3; } code = 0; } else if ((img->format & DISPLAY_DEPTH_MASK) == DISPLAY_DEPTH_16) { if (bigendian) { if ((img->format & DISPLAY_555_MASK) == DISPLAY_NATIVE_555) image_16RGB555_to_24BGR(img->width, dest, source); else image_16RGB565_to_24BGR(img->width, dest, source); } else { if ((img->format & DISPLAY_555_MASK) == DISPLAY_NATIVE_555) { image_16BGR555_to_24BGR(img->width, dest, source); } else image_16BGR565_to_24BGR(img->width, dest, source); } code = 0; } break; case DISPLAY_COLORS_GRAY: if ((img->format & DISPLAY_DEPTH_MASK) == DISPLAY_DEPTH_1) { image_1grey_to_24RGB(width, dest, source); code = 0; } else if ((img->format & DISPLAY_DEPTH_MASK) == DISPLAY_DEPTH_4) { image_4grey_to_24RGB(width, dest, source); code = 0; } else if ((img->format & DISPLAY_DEPTH_MASK) == DISPLAY_DEPTH_8) { image_8grey_to_24RGB(width, dest, source); code = 0; } break; case DISPLAY_COLORS_RGB: if ((img->format & DISPLAY_DEPTH_MASK) == DISPLAY_DEPTH_8) { for (i=0; iformat & DISPLAY_DEPTH_MASK) == DISPLAY_DEPTH_8) { image_32CMYK_to_24BGR(width, dest, source, SEP_CYAN | SEP_MAGENTA | SEP_YELLOW | SEP_BLACK); code = 0; } break; } return code; } /********************************************************/ /* 24RGB */ /* convert one line of 16BGR555 to 24RGB */ /* byte0=GGGBBBBB byte1=0RRRRRGG */ void image_16BGR555_to_24RGB(int width, unsigned char *dest, unsigned char *source) { int i; WORD w; unsigned char value; for (i=0; i> 10) & 0x1f); /* red */ *dest++ = (unsigned char)((value << 3) + (value >> 2)); value = (unsigned char)((w >> 5) & 0x1f); /* green */ *dest++ = (unsigned char)((value << 3) + (value >> 2)); value = (unsigned char)(w & 0x1f); /* blue */ *dest++ = (unsigned char)((value << 3) + (value >> 2)); source += 2; } } /* convert one line of 16BGR565 to 24RGB */ /* byte0=GGGBBBBB byte1=RRRRRGGG */ void image_16BGR565_to_24RGB(int width, unsigned char *dest, unsigned char *source) { int i; WORD w; unsigned char value; for (i=0; i> 11) & 0x1f); /* red */ *dest++ = (unsigned char)((value << 3) + (value >> 2)); value = (unsigned char)((w >> 5) & 0x3f); /* green */ *dest++ = (unsigned char)((value << 2) + (value >> 4)); value = (unsigned char)(w & 0x1f); /* blue */ *dest++ = (unsigned char)((value << 3) + (value >> 2)); source += 2; } } /* convert one line of 16RGB555 to 24RGB */ /* byte0=0RRRRRGG byte1=GGGBBBBB */ void image_16RGB555_to_24RGB(int width, unsigned char *dest, unsigned char *source) { int i; WORD w; unsigned char value; for (i=0; i> 10) & 0x1f); /* red */ *dest++ = (unsigned char)((value << 3) + (value >> 2)); value = (unsigned char)((w >> 5) & 0x1f); /* green */ *dest++ = (unsigned char)((value << 3) + (value >> 2)); value = (unsigned char)(w & 0x1f); /* blue */ *dest++ = (unsigned char)((value << 3) + (value >> 2)); source += 2; } } /* convert one line of 16RGB565 to 24RGB */ /* byte0=RRRRRGGG byte1=GGGBBBBB */ void image_16RGB565_to_24RGB(int width, unsigned char *dest, unsigned char *source) { int i; WORD w; unsigned char value; for (i=0; i> 11) & 0x1f); /* red */ *dest++ = (unsigned char)((value << 3) + (value >> 2)); value = (unsigned char)((w >> 5) & 0x3f); /* green */ *dest++ = (unsigned char)((value << 2) + (value >> 4)); value = (unsigned char)(w & 0x1f); /* blue */ *dest++ = (unsigned char)((value << 3) + (value >> 2)); source += 2; } } /* convert one line of 32CMYK to 24RGB */ void image_32CMYK_to_24RGB(int width, unsigned char *dest, unsigned char *source, int sep) { int i; int cyan, magenta, yellow, black; for (i=0; i> 4) & 0xf; val = val + (val << 4); dest[0] = dest[1] = dest[2] = (unsigned char)val; dest += 3; } } /* convert one line of 8-bit grey to 24RGB */ void image_8grey_to_24RGB(int width, unsigned char *dest, unsigned char *source) { int i; for (i=0; i>= 4; val &= 0x0f; image_colour(DISPLAY_COLORS_NATIVE | DISPLAY_DEPTH_4, val, dest, dest+1, dest+2); dest += 3; } } int image_to_24RGB(IMAGE *img, unsigned char *dest, unsigned char *source) { unsigned char *d = dest; unsigned char *s = source; int width = img->width; unsigned int alpha = img->format & DISPLAY_ALPHA_MASK; BOOL bigendian = (img->format & DISPLAY_ENDIAN_MASK) == DISPLAY_BIGENDIAN; int i; int code = -1; switch (img->format & DISPLAY_COLORS_MASK) { case DISPLAY_COLORS_NATIVE: if ((img->format & DISPLAY_DEPTH_MASK) == DISPLAY_DEPTH_1) { image_1native_to_24RGB(img->width, dest, source); code = 0; } if ((img->format & DISPLAY_DEPTH_MASK) == DISPLAY_DEPTH_4) { image_4native_to_24RGB(img->width, dest, source); code = 0; } if ((img->format & DISPLAY_DEPTH_MASK) == DISPLAY_DEPTH_8) { for (i=0; iformat, *s++, d, d+1, d+2); d+= 3; } code = 0; } else if ((img->format & DISPLAY_DEPTH_MASK) == DISPLAY_DEPTH_16) { if (bigendian) { if ((img->format & DISPLAY_555_MASK) == DISPLAY_NATIVE_555) image_16RGB555_to_24RGB(img->width, dest, source); else image_16RGB565_to_24RGB(img->width, dest, source); } else { if ((img->format & DISPLAY_555_MASK) == DISPLAY_NATIVE_555) { image_16BGR555_to_24RGB(img->width, dest, source); } else image_16BGR565_to_24RGB(img->width, dest, source); } code = 0; } break; case DISPLAY_COLORS_GRAY: if ((img->format & DISPLAY_DEPTH_MASK) == DISPLAY_DEPTH_1) { image_1grey_to_24RGB(width, dest, source); code = 0; } else if ((img->format & DISPLAY_DEPTH_MASK) == DISPLAY_DEPTH_4) { image_4grey_to_24RGB(width, dest, source); code = 0; } else if ((img->format & DISPLAY_DEPTH_MASK) == DISPLAY_DEPTH_8) { image_8grey_to_24RGB(width, dest, source); code = 0; } break; case DISPLAY_COLORS_RGB: if ((img->format & DISPLAY_DEPTH_MASK) == DISPLAY_DEPTH_8) { for (i=0; iformat & DISPLAY_DEPTH_MASK) == DISPLAY_DEPTH_8) { image_32CMYK_to_24RGB(width, dest, source, SEP_CYAN | SEP_MAGENTA | SEP_YELLOW | SEP_BLACK); code = 0; } break; } return code; } /********************************************************/ /* Grey */ void image_1grey_to_8grey(int width, unsigned char *dest, unsigned char *source) { int i; for (i=0; i> 4) & 0x0f; else { value = (*source) & 0x0f; source++; } *dest++ = (unsigned char)(value + (value << 4)); } } void image_1native_to_8grey(int width, unsigned char *dest, unsigned char *source) { int i; for (i=0; i> 4) & 0x0f; else { value = (*source) & 0x0f; source++; } image_colour(DISPLAY_COLORS_NATIVE | DISPLAY_DEPTH_4, value, &r, &g, &b); *dest++ = colour_to_grey(r,g,b); } } void image_8native_to_8grey(int width, unsigned char *dest, unsigned char *source) { int i; int value; unsigned char r, g, b; for (i=0; iwidth*3); int code = -1; if (row) { code = image_to_24RGB(img, row, source); image_24RGB_to_8grey(img->width, dest, row); free(row); } return code; } /* Convert any format to 8-bit grey. * Returns -ve if unsupported format. */ int image_to_grey(IMAGE *img, unsigned char *dest, unsigned char *source) { int width = img->width; int code = -1; unsigned int alpha = img->format & DISPLAY_ALPHA_MASK; switch (img->format & DISPLAY_COLORS_MASK) { case DISPLAY_COLORS_NATIVE: if ((img->format & DISPLAY_DEPTH_MASK) == DISPLAY_DEPTH_1) { image_1native_to_8grey(width, dest, source); code = 0; } else if ((img->format & DISPLAY_DEPTH_MASK) == DISPLAY_DEPTH_4) { image_4native_to_8grey(width, dest, source); code = 0; } else if ((img->format & DISPLAY_DEPTH_MASK) == DISPLAY_DEPTH_8) { image_8native_to_8grey(width, dest, source); code = 0; } else code = image_to_8grey(img, dest, source); break; case DISPLAY_COLORS_GRAY: if ((img->format & DISPLAY_DEPTH_MASK) == DISPLAY_DEPTH_1) { image_1grey_to_8grey(width, dest, source); code = 0; } else if ((img->format & DISPLAY_DEPTH_MASK) == DISPLAY_DEPTH_4) { image_4grey_to_8grey(width, dest, source); code = 0; } else if ((img->format & DISPLAY_DEPTH_MASK) == DISPLAY_DEPTH_8) { memcpy(dest, source, width); code = 0; } break; case DISPLAY_COLORS_RGB: if ((img->format & DISPLAY_DEPTH_MASK) != DISPLAY_DEPTH_8) code = -1; else if (alpha == DISPLAY_ALPHA_NONE) { if ((img->format & DISPLAY_ENDIAN_MASK) == DISPLAY_BIGENDIAN) image_24RGB_to_8grey(width, dest, source); else image_24BGR_to_8grey(width, dest, source); code = 0; } else code = image_to_8grey(img, dest, source); break; case DISPLAY_COLORS_CMYK: if ((img->format & DISPLAY_DEPTH_MASK) != DISPLAY_DEPTH_8) code = -1; else code = image_to_8grey(img, dest, source); break; } return code; } /********************************************************/ /* Convert a line of image to monochrome with 0=white, 1=black. * Returns -ve if unsupported format. */ int image_to_mono(IMAGE *img, unsigned char *dest, unsigned char *source) { int width = img->width; unsigned int alpha = img->format & DISPLAY_ALPHA_MASK; BOOL bigendian = (img->format & DISPLAY_ENDIAN_MASK) == DISPLAY_BIGENDIAN; int bwidth = ((width + 7) & ~7) >> 3; /* byte width with 1 bit/pixel */ unsigned char omask = 0x80; int oroll = 7; int black; unsigned char *s = source; unsigned char mask0 = 0; unsigned char mask1 = 0; unsigned char mask2 = 0; unsigned char mask3 = 0; int bytes_per_pixel = 0; BOOL additive = TRUE; int j; switch (img->format & DISPLAY_COLORS_MASK) { case DISPLAY_COLORS_NATIVE: if ((img->format & DISPLAY_DEPTH_MASK) == DISPLAY_DEPTH_1) { for (j = 0; j < bwidth ; j++) dest[j] = source[j]; return 0; } else if ((img->format & DISPLAY_DEPTH_MASK) == DISPLAY_DEPTH_4) { for (j = 0; j < width; j++) { if (j & 1) { black = (*s & 0x0f) != 0x0f; s++; } else black = (*s & 0xf0) != 0xf0; if (black) dest[j/8] |= omask; else dest[j/8] &= (unsigned char)(~omask); oroll--; omask >>= 1; if (oroll < 0) { omask = 0x80; oroll = 7; } } return 0; } else if ((img->format & DISPLAY_DEPTH_MASK) == DISPLAY_DEPTH_8) { for (j = 0; j < width; j++) { black = (*s != 0x3f) && (*s != 0x5f); s++; if (black) dest[j/8] |= omask; else dest[j/8] &= (unsigned char)(~omask); oroll--; omask >>= 1; if (oroll < 0) { omask = 0x80; oroll = 7; } } return 0; } else if ((img->format & DISPLAY_DEPTH_MASK) == DISPLAY_DEPTH_16) { bytes_per_pixel = 2; if (bigendian) { if ((img->format & DISPLAY_555_MASK) == DISPLAY_NATIVE_555) { mask0 = 0x7f; mask1 = 0xff; } else { mask0 = 0xff; mask1 = 0xff; } } else { if ((img->format & DISPLAY_555_MASK) == DISPLAY_NATIVE_555) { mask0 = 0xff; mask1 = 0x7f; } else { mask0 = 0xff; mask1 = 0xff; } } } break; case DISPLAY_COLORS_GRAY: if ((img->format & DISPLAY_DEPTH_MASK) == DISPLAY_DEPTH_1) { for (j = 0; j < bwidth ; j++) dest[j] = (unsigned char)~source[j]; return 0; } else if ((img->format & DISPLAY_DEPTH_MASK) == DISPLAY_DEPTH_4) { for (j = 0; j < width; j++) { if (j & 1) { black = (*s & 0x0f) != 0x0f; s++; } else black = (*s & 0xf0) != 0xf0; if (black) dest[j/8] |= omask; else dest[j/8] &= (unsigned char)(~omask); oroll--; omask >>= 1; if (oroll < 0) { omask = 0x80; oroll = 7; } } return 0; } else if ((img->format & DISPLAY_DEPTH_MASK) == DISPLAY_DEPTH_8) { bytes_per_pixel = 1; mask0 = 0xff; } else return -1; break; case DISPLAY_COLORS_RGB: if ((img->format & DISPLAY_DEPTH_MASK) != DISPLAY_DEPTH_8) return -1; if ((alpha == DISPLAY_ALPHA_FIRST) || (alpha == DISPLAY_UNUSED_FIRST)) { bytes_per_pixel = 4; mask0 = 0; mask1 = 0xff; mask2 = 0xff; mask3 = 0xff; } else { bytes_per_pixel = 3; mask0 = 0xff; mask1 = 0xff; mask2 = 0xff; mask3 = 0; } if ((alpha == DISPLAY_ALPHA_LAST) || (alpha == DISPLAY_UNUSED_LAST)) bytes_per_pixel++; break; case DISPLAY_COLORS_CMYK: if ((img->format & DISPLAY_DEPTH_MASK) != DISPLAY_DEPTH_8) return -1; additive = FALSE; bytes_per_pixel = 4; mask0 = 0xff; mask1 = 0xff; mask2 = 0xff; mask3 = 0xff; break; } /* one or more bytes per pixel */ memset(dest, 0xff, bwidth); omask = 0x80; oroll = 7; for (j = 0; j < width; j++) { if (additive) { /* RGB */ black = (s[0] & mask0) != mask0; if (bytes_per_pixel > 1) black |= (s[1] & mask1) != mask1; if (bytes_per_pixel > 2) black |= (s[2] & mask2) != mask2; if (bytes_per_pixel > 3) black |= (s[3] & mask3) != mask3; } else { /* CMYK */ black = (s[0] & mask0) != 0; black |= (s[1] & mask1) != 0; black |= (s[2] & mask2) != 0; black |= (s[3] & mask3) != 0; } s += bytes_per_pixel; if (black) dest[j/8] |= omask; else dest[j/8] &= (unsigned char)(~omask); oroll--; omask >>= 1; if (oroll < 0) { omask = 0x80; oroll = 7; } } return 0; } /* Return number of bits per pixel. * If format unknown, return -ve. */ int image_depth(IMAGE *img) { unsigned int alpha = img->format & DISPLAY_ALPHA_MASK; int bitcount = -1; switch (img->format & DISPLAY_COLORS_MASK) { case DISPLAY_COLORS_NATIVE: case DISPLAY_COLORS_GRAY: switch (img->format & DISPLAY_DEPTH_MASK) { case DISPLAY_DEPTH_1: bitcount = 1; break; case DISPLAY_DEPTH_4: bitcount = 4; break; case DISPLAY_DEPTH_8: bitcount = 8; break; case DISPLAY_DEPTH_16: bitcount = 16; break; } break; case DISPLAY_COLORS_RGB: if ((img->format & DISPLAY_DEPTH_MASK) == DISPLAY_DEPTH_8) { if ((alpha == DISPLAY_ALPHA_FIRST) || (alpha == DISPLAY_UNUSED_FIRST)) bitcount = 32; else bitcount = 24; if ((alpha == DISPLAY_ALPHA_LAST) || (alpha == DISPLAY_UNUSED_LAST)) bitcount += 8; } break; case DISPLAY_COLORS_CMYK: if ((img->format & DISPLAY_DEPTH_MASK) == DISPLAY_DEPTH_8) bitcount = 32; break; } return bitcount; } /********************************************************/ /* Copy an image, converting format if needed */ int image_copy(IMAGE *newimg, IMAGE *oldimg, unsigned int format) { int code = 0; int depth; int colour_format = (format & DISPLAY_COLORS_MASK); BOOL mono = FALSE; BOOL grey = FALSE; BOOL rgb24 = FALSE; BOOL bgr24 = FALSE; memset(newimg, 0, sizeof(IMAGE)); newimg->width = oldimg->width; newimg->height = oldimg->height; newimg->raster = oldimg->raster; /* bytes per row */ newimg->format = format; newimg->image = NULL; if (newimg->format == oldimg->format) { /* copy unmodified */ int image_size = newimg->height * newimg->raster; newimg->image = (unsigned char *)malloc(image_size); if (newimg->image == NULL) code = -1; else { memcpy(newimg->image, oldimg->image, image_size); if (image_platform_init(newimg) < 0) { free(newimg->image); newimg->image = NULL; code = -1; } } return code; } /* Need to convert the format */ /* We support 1-bit monochrome, 8-bit grey, 24-bit RGB and 24-bit BGR */ depth = image_depth(newimg); if ((depth == 1) && (colour_format == DISPLAY_COLORS_NATIVE)) mono = TRUE; else if ((depth == 8) && (colour_format == DISPLAY_COLORS_GRAY)) grey = TRUE; else if ((depth == 24) && (colour_format == DISPLAY_COLORS_RGB)) { if ((format & DISPLAY_ENDIAN_MASK) == DISPLAY_BIGENDIAN) rgb24 = TRUE; else bgr24 = TRUE; } else code = -1; if (code == 0) { newimg->raster = (((depth * newimg->width + 7) >> 3) + 3) & ~3; newimg->image = (unsigned char *) malloc(newimg->raster * newimg->height); } if ((newimg->image == NULL)) code = -1; else if (code == 0) { /* convert each row */ unsigned char *source, *dest; BOOL invert = (newimg->format & DISPLAY_FIRSTROW_MASK) != (oldimg->format & DISPLAY_FIRSTROW_MASK); int i; for (i=0; i<(int)newimg->height; i++) { source = oldimg->image + oldimg->raster * i; if (invert) dest = newimg->image + newimg->raster * (newimg->height-1-i); else dest = newimg->image + newimg->raster * i; if (mono) code = image_to_mono(oldimg, dest, source); else if (grey) code = image_to_grey(oldimg, dest, source); else if (rgb24) code = image_to_24RGB(oldimg, dest, source); else if (bgr24) code = image_to_24BGR(oldimg, dest, source); if (code) break; } } if (code == 0) code = image_platform_init(newimg); if (code) { if (newimg->image) { free(newimg->image); newimg->image = NULL; } } return code; } /********************************************************/ /* Merge a separation stored as greyscale into a CMYK composite */ int image_merge_cmyk(IMAGE *img, IMAGE *layer, float cyan, float magenta, float yellow, float black) { int x; int y; unsigned char *img_row; unsigned char *layer_row; unsigned char *p; int img_topfirst; int layer_topfirst; unsigned int val; if ((img == NULL) || (img->image == NULL)) return -1; if ((layer == NULL) || (layer->image == NULL)) return -1; if ((img->format & DISPLAY_COLORS_MASK) != DISPLAY_COLORS_CMYK) return -1; if ((img->format & DISPLAY_DEPTH_MASK) != DISPLAY_DEPTH_8) return -1; if ((img->format & DISPLAY_ENDIAN_MASK) != DISPLAY_BIGENDIAN) return -1; if ((layer->format & DISPLAY_COLORS_MASK) != DISPLAY_COLORS_GRAY) return -1; if ((layer->format & DISPLAY_DEPTH_MASK) != DISPLAY_DEPTH_8) return -1; if (img->width != layer->width) return -1; if (img->height != layer->height) return -1; img_topfirst = ((img->format & DISPLAY_FIRSTROW_MASK) == DISPLAY_TOPFIRST); layer_topfirst = ((layer->format & DISPLAY_FIRSTROW_MASK) == DISPLAY_TOPFIRST); for (y=0; y<(int)img->height; y++) { img_row = img->image + img->raster * (img_topfirst ? y : ((int)img->height - y - 1)); layer_row = layer->image + layer->raster * (layer_topfirst ? y : ((int)layer->height - y - 1)); for (x=0; x<(int)img->width; x++) { val = layer_row[x]; p = &img_row[x*4]; p[0] = (unsigned char)min(255, p[0] + (255-val) * cyan); p[1] = (unsigned char)min(255, p[1] + (255-val) * magenta); p[2] = (unsigned char)min(255, p[2] + (255-val) * yellow); p[3] = (unsigned char)min(255, p[3] + (255-val) * black); } } return 0; } /********************************************************/ typedef struct scale_pixels_s { unsigned int end; /* index of last pixel (full or partial) */ unsigned int frac; /* fraction * 16 of last pixel */ } scale_pixels_t; /* Down scale an image. * This is intended to scale a hires resolution monochrome image * to a lower resolution greyscale image. * Input can be: * 1bit/pixel native or grey * 8bit/pixel grey, * 24 or 32bit/pixel RGB * 32bit/pixel CMYK. * If the input format is grey, the output format can be one of * 8bit/pixel grey, * 24 or 32bit/pixel RGB * 32bit/pixel CMYK. * If the input format is RGB or CMYK, the output format must match. * Row order must be the same for both images. */ int image_down_scale(IMAGE *newimg, IMAGE *oldimg) { unsigned int i; unsigned int xi, xo, yi, yo; unsigned int end, last; scale_pixels_t *spx = NULL; scale_pixels_t *spy = NULL; unsigned int *sum1 = NULL; /* horizontal merge of one source row */ unsigned int *sumn = NULL; /* merge of several rows */ unsigned int frac; unsigned int val; unsigned int maxval; unsigned char *row_in; unsigned char *row_out; unsigned int mask; unsigned int byteval = 0; unsigned int width_in = oldimg->width; unsigned int height_in = oldimg->height; unsigned int width_out = newimg->width; unsigned int height_out = newimg->height; BOOL mono_wb = FALSE; BOOL mono_bw = FALSE; BOOL cmyk_in = FALSE; BOOL cmyk_out = FALSE; unsigned int ncomp_in = 0; unsigned int ncomp_out = 0; unsigned int ncomp_out_first = 0; unsigned int ncomp_out_last = 0; /* Check if input image format is supported */ switch (oldimg->format & DISPLAY_COLORS_MASK) { case DISPLAY_COLORS_NATIVE: switch (oldimg->format & DISPLAY_DEPTH_MASK) { case DISPLAY_DEPTH_1: ncomp_in = 1; mono_wb = TRUE; break; } break; case DISPLAY_COLORS_GRAY: switch (oldimg->format & DISPLAY_DEPTH_MASK) { case DISPLAY_DEPTH_1: ncomp_in = 1; mono_bw = TRUE; break; case DISPLAY_DEPTH_8: ncomp_in = 1; break; } break; case DISPLAY_COLORS_RGB: if ((oldimg->format & DISPLAY_DEPTH_MASK) == DISPLAY_DEPTH_8) { int alpha = (oldimg->format & DISPLAY_ALPHA_MASK); ncomp_in = 3; if ((alpha == DISPLAY_ALPHA_FIRST) || (alpha == DISPLAY_UNUSED_FIRST)) ncomp_in++; if ((alpha == DISPLAY_ALPHA_LAST) || (alpha == DISPLAY_UNUSED_LAST)) ncomp_in++; } break; case DISPLAY_COLORS_CMYK: if ((oldimg->format & DISPLAY_DEPTH_MASK) == DISPLAY_DEPTH_8) { ncomp_in = 4; cmyk_in = TRUE; } } if (ncomp_in == 0) return -1; /* Check if output image format is supported */ switch (newimg->format & DISPLAY_COLORS_MASK) { case DISPLAY_COLORS_GRAY: switch (newimg->format & DISPLAY_DEPTH_MASK) { case DISPLAY_DEPTH_8: ncomp_out = 1; ncomp_out_last = ncomp_out; break; } break; case DISPLAY_COLORS_RGB: if ((newimg->format & DISPLAY_DEPTH_MASK) == DISPLAY_DEPTH_8) { int alpha = (newimg->format & DISPLAY_ALPHA_MASK); ncomp_out = 3; ncomp_out_first = 0; ncomp_out_last = ncomp_out; if (alpha == DISPLAY_ALPHA_FIRST) { ncomp_out++; ncomp_out_last++; } else if (alpha == DISPLAY_UNUSED_FIRST) { ncomp_out++; ncomp_out_first++; ncomp_out_last++; } if (alpha == DISPLAY_ALPHA_LAST) { ncomp_out++; ncomp_out_last++; } else if (alpha == DISPLAY_UNUSED_LAST) { ncomp_out++; } } break; case DISPLAY_COLORS_CMYK: if ((newimg->format & DISPLAY_DEPTH_MASK) == DISPLAY_DEPTH_8) { ncomp_out = 4; cmyk_out = TRUE; } } if (ncomp_out == 0) return -1; if (ncomp_out < ncomp_in) return -1; if ((ncomp_out != ncomp_in) && (ncomp_in != 1)) return -1; if (cmyk_out != cmyk_in) return -1; if ((newimg->format && DISPLAY_FIRSTROW_MASK) != (oldimg->format && DISPLAY_FIRSTROW_MASK)) return -1; if (width_out > width_in) width_out = width_in; if (height_out > height_in) height_out = height_in; maxval = (int)(16 * width_in / width_out) * (int)(16 * height_in / height_out); spy = (scale_pixels_t *)malloc(height_out * sizeof(scale_pixels_t)); spx = (scale_pixels_t *)malloc(width_out * sizeof(scale_pixels_t)); sum1 = (unsigned int *)malloc(width_out * ncomp_in * sizeof(unsigned int)); sumn = (unsigned int *)malloc(width_out * ncomp_in * sizeof(unsigned int)); if ((spy == NULL) || (spx == NULL) || (sum1 == NULL) || (sumn == NULL)) { if (spy != NULL) free(spy); if (spx != NULL) free(spx); if (sum1 != NULL) free(sum1); if (sumn == NULL) free(sumn); return -1; } /* precalculate the integer pixel offsets and fractions */ for (xo=0; xo>4; spx[xo].frac = last - end; if (spx[xo].frac == 0) { spx[xo].end--; spx[xo].frac = 16; } } for (yo=0; yo>4; spy[yo].frac = last - end; if (spy[yo].frac == 0) { spy[yo].end--; spy[yo].frac = 16; } } yo = 0; memset(sumn, 0, width_out * ncomp_in * sizeof(unsigned int)); for (yi=0; yiimage + yi * oldimg->raster; if (mono_wb) { /* 1bit/pixel, 0 is white, 1 is black */ mask = 0; end = spx[xo].end; for (xi=0; xi>= 1) == 0) { mask = 0x80; byteval = row_in[xi>>3]; } val = (byteval & mask) ? 0 : 255; if (xi >= end) { /* last (possibly partial) pixel of group */ sum1[xo] += val * (frac = spx[xo].frac); if (++xo < width_out) sum1[xo] = val * (16 - frac); end = spx[xo].end; } else sum1[xo] += val << 4; } } else if (mono_bw) { /* 0 is black, 1 is white */ mask = 0; end = spx[xo].end; for (xi=0; xi>= 1) == 0) { mask = 0x80; byteval = row_in[xi>>3]; } val = (byteval & mask) ? 255 : 0; if (xi >= end) { /* last (possibly partial) pixel of group */ sum1[xo] += val * (frac = spx[xo].frac); if (++xo < width_out) sum1[xo] = val * (16 - frac); end = spx[xo].end; } else sum1[xo] += val << 4; } } else if (ncomp_in == 1) { /* 8bits/component grey */ for (xi=0; xi= spx[xo].end) { /* last (possibly partial) pixel of group */ sum1[xo] += val * (frac = spx[xo].frac); if (++xo < width_out) sum1[xo] = val * (16 - frac); } else sum1[xo] += val << 4; } } else if (ncomp_in >= 3) { /* 8bits/component RGB, BGR, xRGB, CMYK etc. */ for (xi=0; xi= spx[xo].end) { /* last (possibly partial) pixel of group */ frac = spx[xo].frac; sum1[xo*ncomp_in+i] += val * frac; if (xo+1 < width_out) sum1[(xo+1)*ncomp_in+i] = val * (16 - frac); } else sum1[xo*ncomp_in+i] += val << 4; } if (xi >= spx[xo].end) xo++; } } if (yi >= spy[yo].end) { frac = spy[yo].frac; /* add last partial row to sumn */ for (xo=0; xoimage + yo * newimg->raster; for (xo=0; xo < width_out*ncomp_in; xo++) { val = sumn[xo] / maxval; if (val > 255) val = 255; if (ncomp_in == ncomp_out) { row_out[xo] = (unsigned char)val; } else { /* we are converting grey to colour */ if (cmyk_out) { row_out[xo*ncomp_out+0] = row_out[xo*ncomp_out+1] = row_out[xo*ncomp_out+2] = (unsigned char)0; row_out[xo*ncomp_out+3] = (unsigned char)val; } else { /* RGB */ for (i=0; iwidth = (unsigned int)(oldimg->width * xddpi / xrdpi + 0.5); newimg->height = (unsigned int)(oldimg->height * yddpi / yrdpi + 0.5); if ((((format & DISPLAY_COLORS_MASK) == DISPLAY_COLORS_NATIVE) || ((format & DISPLAY_COLORS_MASK) == DISPLAY_COLORS_GRAY)) && (((format & DISPLAY_DEPTH_MASK) == DISPLAY_DEPTH_1))) /* need to convert up to 8bit/pixel */ newimg->format = image_platform_format( (format & ~DISPLAY_COLORS_MASK & ~DISPLAY_DEPTH_MASK) | DISPLAY_COLORS_GRAY | DISPLAY_DEPTH_8); else newimg->format = format; newimg->raster = (((image_depth(newimg) * newimg->width + 7) >> 3) + 3) & ~3; /* Try converting as is */ newimg->image = malloc(newimg->raster * newimg->height); if (newimg->image == NULL) return -1; if (image_down_scale(newimg, oldimg) != 0) { /* Conversion failed, so input format probably not OK. * Convert to RGB and try again. * Ignore requested format. */ IMAGE tempimg; free(newimg->image); newimg->image = NULL; memset(&tempimg, 0, sizeof(tempimg)); tempimg.width = oldimg->width; tempimg.height = oldimg->height; if (((((oldimg->format & DISPLAY_COLORS_MASK) == DISPLAY_COLORS_NATIVE) || ((oldimg->format & DISPLAY_COLORS_MASK) == DISPLAY_COLORS_GRAY)) && ((oldimg->format & DISPLAY_DEPTH_MASK) == DISPLAY_DEPTH_1)) || (((oldimg->format & DISPLAY_COLORS_MASK) == DISPLAY_COLORS_GRAY) && ((oldimg->format & DISPLAY_DEPTH_MASK) == DISPLAY_DEPTH_8))) tempimg.format = image_platform_format(grey_format); else tempimg.format = image_platform_format(temp_format); tempimg.raster = (((image_depth(&tempimg) * tempimg.width + 7) >> 3) + 3) & ~3; tempimg.image = malloc(tempimg.raster * tempimg.height); if (tempimg.image == NULL) { return -1; } newimg->format = tempimg.format; newimg->raster = (((image_depth(newimg) * newimg->width + 7) >> 3) + 3) & ~3; newimg->image = malloc(newimg->raster * newimg->height); if (newimg->image == NULL) { free(tempimg.image); return -1; } image_copy(&tempimg, oldimg, tempimg.format); if (image_down_scale(newimg, &tempimg) != 0) { /* nothing worked */ free(tempimg.image); free(newimg->image); newimg->image = NULL; /* fall through to copy unmodified */ } else { free(tempimg.image); image_platform_init(newimg); return 0; /* succesfully resized */ } } else { image_platform_init(newimg); return 0; /* succesfully resized */ } } /* Not resized, or failed resize, so just copy image */ return image_copy(newimg, oldimg, format); } /********************************************************/ /* ASCII85Encode to a character line. * Returns the number of characters produced, which can be * no more than count+1 */ static int a85write(char *line, unsigned char *buf, int count) { int i; unsigned long value; unsigned char abuf[5]; if (count == 0) return 0; if (count < 4) { for (i = count; i < 4; i++) buf[i] = 0; } if ((count == 4) && (buf[0] == 0) && (buf[1] == 0) && (buf[2] == 0) && (buf[3] == 0)) { line[0] = 'z'; return 1; } value = ((unsigned int)(buf[0])<<24) + ((unsigned int)(buf[1])<<16) + ((unsigned int)(buf[2])<<8) + (unsigned int)(buf[3]); abuf[0] = (unsigned char)(value / (85L*85*85*85)); value -= abuf[0] * (85L*85*85*85); abuf[1] = (unsigned char)(value / (85L*85*85)); value -= abuf[1] * (85L*85*85); abuf[2] = (unsigned char)(value / (85L*85)); value -= abuf[2] * (85L*85); abuf[3] = (unsigned char)(value / (85L)); value -= abuf[3] * (85L); abuf[4] = (unsigned char)(value); for (i=0; i= furx) || (flly >= fury)) hires_bbox_valid = 0; topfirst = ((img->format & DISPLAY_FIRSTROW_MASK) == DISPLAY_TOPFIRST); bigendian = ((img->format & DISPLAY_ENDIAN_MASK) == DISPLAY_BIGENDIAN); if ((img->format & DISPLAY_DEPTH_MASK) == DISPLAY_DEPTH_1) { depth = 1; compwidth = (img->width + 7) >> 3; } else if ((img->format & DISPLAY_DEPTH_MASK) == DISPLAY_DEPTH_4) { depth = 4; compwidth = (img->width + 1) >> 1; } else if ((img->format & DISPLAY_DEPTH_MASK) == DISPLAY_DEPTH_8) { depth = 8; compwidth = img->width; } else return -1; if ((img->format & DISPLAY_COLORS_MASK) == DISPLAY_COLORS_CMYK) ncomp = 4; else if ((img->format & DISPLAY_COLORS_MASK) == DISPLAY_COLORS_RGB) { ncomp = 3; if ((img->format & DISPLAY_ALPHA_MASK) != DISPLAY_ALPHA_NONE) { convert = TRUE; compwidth = img->width; bigendian = TRUE; /* Convert to RGB, not BGR */ } } else if ((img->format & DISPLAY_COLORS_MASK) == DISPLAY_COLORS_GRAY) ncomp = 1; else if ((img->format & DISPLAY_COLORS_MASK) == DISPLAY_COLORS_NATIVE) { if (depth == 1) { ncomp = 1; invert = TRUE; } else { ncomp = 3; compwidth = img->width; convert = TRUE; bigendian = TRUE; /* Convert to RGB, not BGR */ } } else return -1; packin = (unsigned char *)malloc(compwidth * ncomp); if (packin == NULL) return -1; packout_len = compwidth * ncomp * 5 / 4 + 4; packout = (unsigned char *)malloc(packout_len); if (packout == NULL) { free(packin); return -1; } if (convert) { convert_row = (unsigned char *)malloc(compwidth * ncomp); if (convert_row == NULL) { free(packin); free(packout); return -1; } } if (compress == IMAGE_COMPRESS_LZW) { lzw = lzw_new(); if (lzw == (lzw_state_t *)NULL) { free(packin); free(packout); if (convert_row) free(convert_row); return -1; } } gfile_puts(f, "%!PS-Adobe-3.0 EPSF-3.0\n"); snprintf(buf, sizeof(buf)-1, "%%%%BoundingBox: %d %d %d %d\n", llx, lly, urx, ury); gfile_puts(f, buf); if (hires_bbox_valid) { snprintf(buf, sizeof(buf)-1, "%%%%HiResBoundingBox: %g %g %g %g\n", fllx, flly, furx, fury); gfile_puts(f, buf); } gfile_puts(f, "%%Pages: 1\n"); gfile_puts(f, "%%EndComments\n"); gfile_puts(f, "%%Page: 1 1\n"); gfile_puts(f, "gsave\n"); if (hires_bbox_valid) { snprintf(buf, sizeof(buf)-1, "%g %g translate\n", fllx, flly); gfile_puts(f, buf); snprintf(buf, sizeof(buf)-1, "%g %g scale\n", furx-fllx, fury-flly); gfile_puts(f, buf); } else { snprintf(buf, sizeof(buf)-1, "%d %d translate\n", llx, lly); gfile_puts(f, buf); snprintf(buf, sizeof(buf)-1, "%d %d scale\n", urx - llx, ury - lly); gfile_puts(f, buf); } if (ncomp == 1) gfile_puts(f, "/DeviceGray setcolorspace\n"); else if (ncomp == 3) gfile_puts(f, "/DeviceRGB setcolorspace\n"); else if (ncomp == 4) gfile_puts(f, "/DeviceCMYK setcolorspace\n"); if ((ncomp > 1) && (compress != IMAGE_COMPRESS_NONE)) { /* Include as RRRRGGGGBBBB not RGBRGBRGBRGB * (or CCCCMMMMYYYYKKKK not CMYKCMYKCMYKCMYK) * Since this compresses with RLE better. */ separate = 1; } if (separate) { /* Include as RRGGBB not RGBRGB (or CCMMYYKK not CMYKCMYK) */ /* Since this compresses with RLE better */ if (use_a85) gfile_puts(f, "/infile currentfile /ASCII85Decode filter"); else gfile_puts(f, "/infile currentfile /ASCIIHexDecode filter"); if (compress == IMAGE_COMPRESS_LZW) gfile_puts(f, " /LZWDecode filter"); else if (compress == IMAGE_COMPRESS_RLE) gfile_puts(f, " /RunLengthDecode filter"); gfile_puts(f, " def\n"); for (i=0; iwidth); gfile_puts(f, buf); } } gfile_puts(f, "<<\n /ImageType 1\n"); snprintf(buf, sizeof(buf)-1, " /Width %d\n", img->width); gfile_puts(f, buf); snprintf(buf, sizeof(buf)-1, " /Height %d\n", img->height); gfile_puts(f, buf); snprintf(buf, sizeof(buf)-1, " /BitsPerComponent %d\n", depth); gfile_puts(f, buf); gfile_puts(f, " /Decode [ "); for (i=0; iwidth, -(int)img->height, img->height); gfile_puts(f, buf); if (separate) { gfile_puts(f, " /MultipleDataSources true\n"); gfile_puts(f, " /DataSource [\n"); for (i=0; i>\nimage\n"); count = 0; packout_count = 0; for (y=0; y<(int)img->height; y++) { row = img->image + img->raster * (topfirst != 0 ? y : ((int)img->height - y - 1)); if (convert) { image_to_24RGB(img, convert_row, row); row = convert_row; } packin_count = 0; if (separate) { if (bigendian) { for (i=0; i=0; i--) for (x=0; x=0; i--) packin[packin_count++] = row[x*ncomp+i]; } } } if (compress == IMAGE_COMPRESS_LZW) { int inlen = packin_count; int outlen = packout_len - packout_count; lzw_compress(lzw, packin, &inlen, packout+packout_count, &outlen); packout_count += outlen; if (y == (int)img->height-1) { /* This is the last row */ /* Flush and EOD */ inlen = 0; /* EOD */ outlen = packout_len - packout_count; lzw_compress(lzw, packin, &inlen, packout+packout_count, &outlen); packout_count += outlen; } } else if (compress == IMAGE_COMPRESS_RLE) { packout_count += packbits(packout+packout_count, packin, packin_count); } else { memcpy(packout+packout_count, packin, packin_count); packout_count += packin_count; } for (i=0; i>4) & 0xf]; buf[count++] = hex[packout[i] & 0xf]; } if (count >= 70) { buf[count++] = '\n'; gfile_write(f, buf, count); count = 0; } } if (packout_count-i > 0) memmove(packout, packout+i, packout_count-i); packout_count -= i; } if (use_a85) { if (packout_count) count += a85write(buf+count, packout, packout_count); buf[count++] = '~'; buf[count++] = '>'; buf[count++] = '\n'; } else { buf[count++] = '>'; buf[count++] = '\n'; } gfile_write(f, buf, count); gfile_puts(f, "grestore\n"); gfile_puts(f, "showpage\n"); gfile_puts(f, "%%Trailer\n"); gfile_puts(f, "%%EOF\n"); if (lzw) lzw_free(lzw); if (convert) free(convert_row); free(packin); free(packout); return 0; } int image_to_epsfile(IMAGE *img, LPCTSTR filename, float xdpi, float ydpi) { GFile *f; int code = 0; int width = (int)(img->width * 72.0 / xdpi); int height = (int)(img->height * 72.0 / ydpi); if ((img == NULL) || (img->image == NULL)) return -1; f = gfile_open(filename, gfile_modeWrite | gfile_modeCreate); if (f == NULL) return -1; code = image_to_eps(f, img, 0, 0, width, height, 0.0, 0.0, (float)width, (float)height, TRUE, IMAGE_COMPRESS_LZW); gfile_close(f); return code; } /********************************************************/ epstool-3.08/src/cimg.h0000644000076400007640000001305710252260054014422 0ustar rjlrjl00000000000000/* Copyright (C) 2001-2005 Ghostgum Software Pty Ltd. All rights reserved. This software is provided AS-IS with no warranty, either express or implied. This software is distributed under licence and may not be copied, modified or distributed except as expressly authorised under the terms of the licence contained in the file LICENCE in this distribution. For more information about licensing, please refer to http://www.ghostgum.com.au/ or contact Ghostsgum Software Pty Ltd, 218 Gallaghers Rd, Glen Waverley VIC 3150, AUSTRALIA, Fax +61 3 9886 6616. */ /* $Id: cimg.h,v 1.16 2005/06/10 09:39:24 ghostgum Exp $ */ /* Image information and format conversions header */ /***************************************/ /* image details */ struct IMAGE_s { unsigned int width; /* pixels */ unsigned int height; /* pixels */ unsigned int raster; /* bytes per row */ unsigned int format; /* pixel format */ unsigned char *image; #ifdef UNIX GdkRgbCmap *cmap; /* colour map = palette */ #endif #ifdef _Windows BITMAPINFOHEADER bmih; HPALETTE palette; /* Windows and OS/2 require a raster line which is a multiple * of 4 bytes. If raster is not what we expect, then we need * to lie about about how many pixels are really on the line * when doing bitmap transfers. * align_width contains our calculation of how many pixels are * needed to match raster. * If align_width != width, then bitmap transfer uses: * source width = img->align_width * destination width = img->width */ int align_width; #endif }; typedef enum SEPARATIONS_e { SEP_CYAN = 8, SEP_MAGENTA = 4, SEP_YELLOW = 2, SEP_BLACK = 1 } SEPARATIONS; /* platform specific */ /* Initialise image, creating palette if necessary * Return 0 if OK, -ve if image format not supported by platform */ int image_platform_init(IMAGE *img); /* Free any platform specific image members such as a palette */ int image_platform_finish(IMAGE *img); /* If format is supported by platform, return it that format. * Otherwise, return the preferred format into which it should * be converted. */ unsigned int image_platform_format(unsigned int format); /* platform independent */ int image_copy(IMAGE *newimg, IMAGE *oldimg, unsigned int format); int image_copy_resize(IMAGE *newimg, IMAGE *oldimg, unsigned int format, float xddpi, float yddpi, float xrdpi, float yrdpi); unsigned char colour_to_grey(unsigned char r, unsigned char g, unsigned char b); void image_colour(unsigned int format, int index, unsigned char *r, unsigned char *g, unsigned char *b); int image_depth(IMAGE *img); int image_to_mono(IMAGE *img, unsigned char *dest, unsigned char *source); int image_to_grey(IMAGE *img, unsigned char *dest, unsigned char *source); void image_1grey_to_8grey(int width, unsigned char *dest, unsigned char *source); void image_4grey_to_8grey(int width, unsigned char *dest, unsigned char *source); void image_1native_to_8grey(int width, unsigned char *dest, unsigned char *source); void image_4native_to_8grey(int width, unsigned char *dest, unsigned char *source); void image_8native_to_8grey(int width, unsigned char *dest, unsigned char *source); void image_24RGB_to_8grey(int width, unsigned char *dest, unsigned char *source); void image_24BGR_to_8grey(int width, unsigned char *dest, unsigned char *source); int image_to_24BGR(IMAGE *img, unsigned char *dest, unsigned char *source); void image_4native_to_24BGR(int width, unsigned char *dest, unsigned char *source); void image_32CMYK_to_24BGR(int width, unsigned char *dest, unsigned char *source, int sep); void image_16RGB565_to_24BGR(int width, unsigned char *dest, unsigned char *source); void image_16RGB555_to_24BGR(int width, unsigned char *dest, unsigned char *source); void image_16BGR565_to_24BGR(int width, unsigned char *dest, unsigned char *source); void image_16BGR555_to_24BGR(int width, unsigned char *dest, unsigned char *source); int image_to_24RGB(IMAGE *img, unsigned char *dest, unsigned char *source); void image_1grey_to_24RGB(int width, unsigned char *dest, unsigned char *source); void image_4grey_to_24RGB(int width, unsigned char *dest, unsigned char *source); void image_8grey_to_24RGB(int width, unsigned char *dest, unsigned char *source); void image_1native_to_24RGB(int width, unsigned char *dest, unsigned char *source); void image_4native_to_24RGB(int width, unsigned char *dest, unsigned char *source); void image_8native_to_24RGB(int width, unsigned char *dest, unsigned char *source); void image_32CMYK_to_24RGB(int width, unsigned char *dest, unsigned char *source, int sep); void image_16RGB565_to_24RGB(int width, unsigned char *dest, unsigned char *source); void image_16RGB555_to_24RGB(int width, unsigned char *dest, unsigned char *source); void image_16BGR565_to_24RGB(int width, unsigned char *dest, unsigned char *source); void image_16BGR555_to_24RGB(int width, unsigned char *dest, unsigned char *source); int image_merge_cmyk(IMAGE *img, IMAGE *layer, float cyan, float magenta, float yellow, float black); int image_down_scale(IMAGE *newimg, IMAGE *oldimg); /* use_85 parameter */ #define IMAGE_ENCODE_HEX 0 #define IMAGE_ENCODE_ASCII85 1 /* compress parameter */ #define IMAGE_COMPRESS_NONE 0 #define IMAGE_COMPRESS_RLE 1 #define IMAGE_COMPRESS_LZW 2 int image_to_eps(GFile *f, IMAGE *img, int llx, int lly, int urx, int ury, float fllx, float flly, float furx, float fury, int use_a85, int compress); int image_to_epsfile(IMAGE *img, LPCTSTR filename, float xdpi, float ydpi); int packbits(BYTE *comp, BYTE *raw, int length); epstool-3.08/src/cargs.h0000644000076400007640000000322110252260053014571 0ustar rjlrjl00000000000000/* Copyright (C) 1993-2002 Ghostgum Software Pty Ltd. All rights reserved. This software is provided AS-IS with no warranty, either express or implied. This software is distributed under licence and may not be copied, modified or distributed except as expressly authorised under the terms of the licence contained in the file LICENCE in this distribution. For more information about licensing, please refer to http://www.ghostgum.com.au/ or contact Ghostsgum Software Pty Ltd, 218 Gallaghers Rd, Glen Waverley VIC 3150, AUSTRALIA, Fax +61 3 9886 6616. */ /* $Id: cargs.h,v 1.1 2002/04/17 11:39:07 ghostgum Exp $ */ /* Argument parsing header */ #ifndef GSVIEW_ARGS_TYPEDEF #define GSVIEW_ARGS_TYPEDEF typedef struct GSVIEW_ARGS_s GSVIEW_ARGS; #endif struct GSVIEW_ARGS_s { int debug; /* /d */ int multithread; /* /t */ int help; /* -help */ int version; /* -version */ TCHAR filename[MAXSTR]; /* filename */ TCHAR queue[MAXSTR]; /* /pQUEUE or /sQUEUE */ char device[64]; /* /fDEVICE */ int print; /* /p */ int convert; /* /f */ int spool; /* /s */ #ifdef NOTUSED int existing; /* /e */ int exit_existing; /* /x */ #endif char media[64]; /* /ma4 */ int orient; /* ORIENT_AUTO etc */ /* /oportrait */ float xdpi; /* -rXDPIxYDPI */ float ydpi; int geometry; /* -geometry WIDTHxHEIGHT+XOFFSET+YOFFSET */ int geometry_width; int geometry_height; int geometry_xoffset; int geometry_yoffset; }; int parse_argv(GSVIEW_ARGS *args, int argc, TCHAR *argv[]); void app_use_args(GSview *app, GSVIEW_ARGS *args); void view_use_args(View *v, GSVIEW_ARGS *args); epstool-3.08/src/cplat.h0000644000076400007640000001371010252260054014602 0ustar rjlrjl00000000000000/* Copyright (C) 2001-2005 Ghostgum Software Pty Ltd. All rights reserved. This software is provided AS-IS with no warranty, either express or implied. This software is distributed under licence and may not be copied, modified or distributed except as expressly authorised under the terms of the licence contained in the file LICENCE in this distribution. For more information about licensing, please refer to http://www.ghostgum.com.au/ or contact Ghostsgum Software Pty Ltd, 218 Gallaghers Rd, Glen Waverley VIC 3150, AUSTRALIA, Fax +61 3 9886 6616. */ /* $Id: cplat.h,v 1.17 2005/06/10 09:39:24 ghostgum Exp $ */ /* Platform specific includes and types */ /* * ZLIBNAME is name of zlib DLL/shared library * BZIP2NAME is name of bzip2 DLL/shared library * PATHSEP is a string containing the directory path separator. * INTPTR is an unsigned integer the same size as a pointer. * INTPTR_FORMAT is the printf format specifier used for INTPTR. * GGMODULE is a DLL/shared library handle. * GGMUTEX is mutual exclusion semaphore handle. * GGEVENT is an event semaphore handle. * GGTHREAD is a thread handle for the C run time library. */ #ifndef CPLAT_INCLUDED #define CPLAT_INCLUDED #if defined(_WIN32) || defined(_WIN64) # ifndef _Windows # define _Windows # endif #endif #ifdef _WINDOWS # ifndef _Windows # define _Windows # endif #endif #ifdef _Windows # include /* must be included before stdio.h */ # include # include # include "wgsver.h" # define ZLIBNAME "zlib32.dll" # define BZIP2NAME "libbz2.dll" # define PATHSEP "\\" # define EOLSTR "\r\n" # ifdef _WIN64 # define INTPTR __int64 /* an integer that same size as a pointer */ # define INTPTR_FORMAT "%I64u" # else # define INTPTR unsigned long # define INTPTR_FORMAT "%lu" # endif /* BYTE is a predefined type in windows.h */ /* WORD is a predefined type in windows.h */ /* DWORD is a predefined type in windows.h */ /* LONG is a predefined type in windows.h */ /* TCHAR is a predefined type in windows.h */ /* LPTSTR is a predefined type in windows.h */ /* LPCTSTR is a predefined type in windows.h */ # define GGMODULE HMODULE # define GGMUTEX HANDLE # define GGEVENT HANDLE # if _MSC_VER >= 1300 # define GGTHREAD uintptr_t # else # define GGTHREAD unsigned long # endif /* WINAPI already defined in windows.h */ #define snprintf _snprintf #define vsnprintf _vsnprintf #endif #ifdef OS2 #define INCL_DOS # include # include # define PATHSEP "\\" # define EOLSTR "\r\n" # define ZLIBNAME "zlib2.dll" /* never used */ # define BZIP2NAME "bzip2.dll" /* never used */ # define INTPTR unsigned long # define INTPTR_FORMAT "%lu" # define TCHAR char # define LPTSTR TCHAR * # define LPCTSTR const TCHAR * # define GGMODULE HMODULE # define GGMUTEX HMTX # define GGEVENT HEVENT # define GGTHREAD int # define WINAPI _System # define BI_RGB (0L) # define BI_BITFIELDS (3L) typedef unsigned short WORD; /* 16-bits */ typedef unsigned long DWORD; /* 32-bits (or longer)*/ typedef struct POINT_s { int x; int y; } POINT; #endif #ifdef UNIX # ifdef GTK # include # else typedef struct _GdkRgbCmap GdkRgbCmap; # endif # include # define __USE_GNU /* we might need recursive mutex */ # include # include # define ZLIBNAME "libz.so" # define BZIP2NAME "libbz2.so" # define PATHSEP "/" # define EOLSTR "\n" # define INTPTR unsigned long # define INTPTR_FORMAT "%lu" # define TCHAR char # define LPTSTR TCHAR * # define LPCTSTR const TCHAR * # define GGMODULE void * # define GGMUTEX pthread_mutex_t # define GGEVENT sem_t # define GGTHREAD pthread_t # define WINAPI # define stricmp strcasecmp /* FIX: these shouldn't be here */ /* Windows IDs */ #define IDOK 1 #define IDCANCEL 2 #define IDYES 6 #define IDNO 7 #define MB_OK 0x0 #define MB_OKCANCEL 0x1 #define MB_YESNO 0x4 #define MB_TYPEMASK 0xf #define MB_ICONHAND 0x10 #define MB_ICONQUESTION 0x20 #define MB_ICONEXCLAMATION 0x30 #define MB_ICONASTERISK 0x40 # define CW_USEDEFAULT (-32768) # define BI_RGB (0L) # define BI_BITFIELDS (3L) typedef int BOOL; typedef unsigned char BYTE; /* 8-bits */ typedef unsigned short WORD; /* 16-bits */ typedef unsigned long DWORD; /* 32-bits (or longer)*/ typedef long LONG; /* signed 32-bits (or longer)*/ typedef struct POINT_s { int x; int y; } POINT; # ifndef FALSE # define FALSE (0) # endif # ifndef TRUE # define TRUE (!(FALSE)) # endif # ifdef NO_SNPRINTF int snprintf(char *buffer, size_t count, const char *fmt, ...); int vsnprintf(char *buffer, size_t count, const char *fmt, va_list argptr); # endif #endif /* Stuff for handling UNICODE */ #ifndef TEXT # define TEXT(s) s /* for Unicode strings */ #endif /* Functions prefixed by "cs" take a character string * as an argument that may be Unicode or narrow * depending on the platform. */ #if defined(UNICODE) && defined(_Windows) # define csncpy(s,t,n) wcsncpy(s,t,n) # define csncat(s,t,n) wcsncat(s,t,n) # define cscmp(s,t) wcscmp(s,t) # define csicmp(s,t) wcsicmp(s,t) # define csncmp(s,t,n) wcsncmp(s,t,n) # define csrchr(s,c) wcsrchr(s,c) # define cslen(s) wcslen(s) # define csnprintf _snwprintf # define csvnprintf _vsnwprintf # define cstoi _wtoi # define csfopen(s,m) _wfopen(s, m) # define csunlink(s) _wunlink(s) # define csgetcwd(s, n) _wgetcwd(s, n) # define csmktemp(s) _wmktemp(s) # define csgetenv(s) _wgetenv(s) #else # define csncpy(s,t,n) strncpy(s,t,n) # define csncat(s,t,n) strncat(s,t,n) # define cscmp(s,t) strcmp(s,t) # define csicmp(s,t) stricmp(s,t) # define csncmp(s,t,n) strncmp(s,t,n) # define csrchr(s,c) strrchr(s,c) # define cslen(s) strlen(s) # define csnprintf snprintf # define csvnprintf vsnprintf # define cstoi atoi # define csfopen(s,m) fopen(s, m) # define csunlink(s) unlink(s) # define csgetcwd(s, n) getcwd(s, n) # define csmktemp(s) mktemp(s) # define csgetenv(s) getenv(s) #endif #ifdef DO_NOT_USE_THESE #define strcpy DO_NOT_USE_strcpy #define strcat DO_NOT_USE_strcat #define sprintf DO_NOT_USE_sprintf #endif #endif /* CPLAT_INCLUDED */ epstool-3.08/src/cmac.h0000644000076400007640000000615310252260054014405 0ustar rjlrjl00000000000000/* Copyright (C) 2003-2005 Ghostgum Software Pty Ltd. All rights reserved. This software is provided AS-IS with no warranty, either express or implied. This software is distributed under licence and may not be copied, modified or distributed except as expressly authorised under the terms of the licence contained in the file LICENCE in this distribution. For more information about licensing, please refer to http://www.ghostgum.com.au/ or contact Ghostsgum Software Pty Ltd, 218 Gallaghers Rd, Glen Waverley VIC 3150, AUSTRALIA, Fax +61 3 9886 6616. */ /* $Id: cmac.h,v 1.3 2005/06/10 09:39:24 ghostgum Exp $ */ /* Macintosh AppleSingle, AppleDouble and MacBinary file formats */ typedef enum CMAC_TYPE_e { CMAC_TYPE_NONE=0, CMAC_TYPE_SINGLE=1, CMAC_TYPE_DOUBLE=2, CMAC_TYPE_MACBIN=3, CMAC_TYPE_RSRC=4 } CMAC_TYPE; /* Mac finder and fork details */ typedef struct CMACFILE_s { CMAC_TYPE type; unsigned char file_type[4]; /* usually EPSF for us */ unsigned char file_creator[4]; DWORD finder_begin; DWORD finder_length; DWORD data_begin; DWORD data_length; DWORD resource_begin; DWORD resource_length; DWORD pict_begin; /* PICT resource in EPSF file */ DWORD pict_length; } CMACFILE; DWORD get_bigendian_dword(const unsigned char *buf); WORD get_bigendian_word(const unsigned char *buf); void put_bigendian_dword(unsigned char *dw, DWORD val); void put_bigendian_word(unsigned char *w, WORD val); /* Read header and identify if MacBinary, AppleSingle or AppleDouble */ CMACFILE *get_mactype(GFile *f); /* Read resources and find location of EPSF PICT preview */ /* Return 0 on success, +ve on unsuitable file, -ve on error */ int get_pict(GFile *f, CMACFILE *mac, int debug); /* Copy PICT from resources to another file */ /* Return 0 on succes, -ve on error */ int extract_mac_pict(GFile *f, CMACFILE *mac, LPCTSTR outname); /* Extract EPSF from data fork to a file */ /* Returns 0 on success, negative on failure */ int extract_mac_epsf(GFile *f, CMACFILE *mac, LPCTSTR outname); /* Write Macintosh binary files in one of several formats. * The data fork if present contains the EPSF. * The resource fork if present contains a preview image in PICT * format with id=256. * The finder informations give type "EPSF" and creator "MSWD". */ /* Write preview to AppleDouble format */ int write_appledouble(GFile *f, LPCTSTR pictname); /* Write EPSF and preview to AppleSingle format */ int write_applesingle(GFile *f, LPCTSTR epsname, LPCTSTR pictname); /* Write EPSF and preview to MacBinary I format */ /* name is the 1-63 character filename written in the MacBinary header */ int write_macbin(GFile *f, const char *name, LPCTSTR epsname, LPCTSTR pictname); /* Write resources containing a single PICT with id=256 to file. * Return number of bytes written if OK, -ve if not OK. * If f==NULL, return number of bytes required for resources. */ int write_resource_pict(GFile *f, LPCTSTR pictname); /* Returns -1 for error, 0 for Mac and 1 for non-Mac */ /* If Macintosh format and verbose, print some details to stdout */ int dump_macfile(LPCTSTR filename, int verbose); epstool-3.08/src/dscparse.c0000644000076400007640000036311510252260054015305 0ustar rjlrjl00000000000000/* Copyright (C) 2000-2005, Ghostgum Software Pty Ltd. All rights reserved. This file is part of GSview. This program is distributed with NO WARRANTY OF ANY KIND. No author or distributor accepts any responsibility for the consequences of using it, or for whether it serves any particular purpose or works at all, unless he or she says so in writing. Refer to the GSview Licence (the "Licence") for full details. Every copy of GSview must include a copy of the Licence, normally in a plain ASCII text file named LICENCE. The Licence grants you the right to copy, modify and redistribute GSview, but only under certain conditions described in the Licence. Among other things, the Licence requires that the copyright notice and this notice be preserved on all copies. */ /* $Id: dscparse.c,v 1.36 2005/01/20 11:19:00 ghostgum Exp $ */ /* * This is a DSC parser, based on the DSC 3.0 spec, * with a few DSC 2.1 additions for page size. * * Current limitations: * %%+ may be used after any comment in the comment or trailer, * but is currently only supported by * %%DocumentMedia * * DSC 2.1 additions (discontinued in DSC 3.0): * %%DocumentPaperColors: * %%DocumentPaperForms: * %%DocumentPaperSizes: * %%DocumentPaperWeights: * %%PaperColor: (ignored) * %%PaperForm: (ignored) * %%PaperSize: * %%PaperWeight: (ignored) * * Other additions for defaults or page section % %%ViewingOrientation: xx xy yx yy */ #include /* for sprintf(), not file I/O */ #include #include #include #define MAXSTR 256 #include "dscparse.h" /* Macros for comparing string literals * For maximum speed, the length of the second macro argument is * computed at compile time. * THE SECOND MACRO ARGUMENT MUST BE A STRING LITERAL. */ #define COMPARE(p,str) (strncmp((const char *)(p), (str), sizeof(str)-1)==0) #define IS_DSC(line, str) (COMPARE((line), (str))) /* Macros for comparing the first one or two characters */ #define IS_WHITE(ch) (((ch)==' ') || ((ch)=='\t')) #define IS_EOL(ch) (((ch)=='\r') || ((ch)=='\n')) #define IS_WHITE_OR_EOL(ch) (IS_WHITE(ch) || IS_EOL(ch)) #define IS_BLANK(str) (IS_EOL(str[0])) #define NOT_DSC_LINE(str) (((str)[0]!='%') || ((str)[1]!='%')) /* Macros for document offset to start and end of line */ #define DSC_START(dsc) ((dsc)->data_offset + (dsc)->data_index - (dsc)->line_length) #define DSC_END(dsc) ((dsc)->data_offset + (dsc)->data_index) /* dsc_scan_SECTION() functions return one of * CDSC_ERROR, CDSC_OK, CDSC_NOTDSC * or one of the following */ /* The line should be passed on to the next section parser. */ #define CDSC_PROPAGATE 10 /* If document is DOS EPS and we haven't read 30 bytes, ask for more. */ #define CDSC_NEEDMORE 11 /* local prototypes */ dsc_private void * dsc_memalloc(CDSC *dsc, size_t size); dsc_private void dsc_memfree(CDSC*dsc, void *ptr); dsc_private CDSC * dsc_init2(CDSC *dsc); dsc_private void dsc_reset(CDSC *dsc); dsc_private void dsc_section_join(DSC_OFFSET begin, DSC_OFFSET *pend, DSC_OFFSET **pplast); dsc_private int dsc_read_line(CDSC *dsc); dsc_private int dsc_read_doseps(CDSC *dsc); dsc_private int dsc_read_macbin(CDSC *dsc); dsc_private int dsc_read_applesingle(CDSC *dsc); dsc_private char * dsc_alloc_string(CDSC *dsc, const char *str, int len); dsc_private char * dsc_add_line(CDSC *dsc, const char *line, unsigned int len); dsc_private char * dsc_copy_string(char *str, unsigned int slen, char *line, unsigned int len, unsigned int *offset); dsc_private GSDWORD dsc_get_dword(const unsigned char *buf); dsc_private GSWORD dsc_get_word(const unsigned char *buf); dsc_private GSDWORD dsc_get_bigendian_dword(const unsigned char *buf); dsc_private GSWORD dsc_get_bigendian_word(const unsigned char *buf); dsc_private int dsc_get_int(const char *line, unsigned int len, unsigned int *offset); dsc_private float dsc_get_real(const char *line, unsigned int len, unsigned int *offset); dsc_private void dsc_unknown(CDSC *dsc); dsc_private GSBOOL dsc_is_section(char *line); dsc_private int dsc_parse_pages(CDSC *dsc); dsc_private int dsc_parse_feature(CDSC *dsc); dsc_private int dsc_parse_bounding_box(CDSC *dsc, CDSCBBOX** pbbox, int offset); dsc_private int dsc_parse_float_bounding_box(CDSC *dsc, CDSCFBBOX** pfbbox, int offset); dsc_private int dsc_parse_orientation(CDSC *dsc, unsigned int *porientation, int offset); dsc_private int dsc_parse_order(CDSC *dsc); dsc_private int dsc_parse_media(CDSC *dsc, const CDSCMEDIA **page_media); dsc_private int dsc_parse_document_media(CDSC *dsc); dsc_private int dsc_parse_viewing_orientation(CDSC *dsc, CDSCCTM **pctm); dsc_private int dsc_parse_page(CDSC *dsc); dsc_private void dsc_save_line(CDSC *dsc); dsc_private int dsc_scan_type(CDSC *dsc); dsc_private int dsc_scan_comments(CDSC *dsc); dsc_private int dsc_scan_preview(CDSC *dsc); dsc_private int dsc_scan_defaults(CDSC *dsc); dsc_private int dsc_scan_prolog(CDSC *dsc); dsc_private int dsc_scan_setup(CDSC *dsc); dsc_private int dsc_scan_page(CDSC *dsc); dsc_private int dsc_scan_trailer(CDSC *dsc); dsc_private int dsc_error(CDSC *dsc, unsigned int explanation, char *line, unsigned int line_len); dsc_private int dsc_dcs2_fixup(CDSC *dsc); dsc_private int dsc_parse_platefile(CDSC *dsc); dsc_private int dsc_parse_dcs1plate(CDSC *dsc); dsc_private CDSCCOLOUR * dsc_find_colour(CDSC *dsc, const char *colourname); dsc_private int dsc_parse_process_colours(CDSC *dsc); dsc_private int dsc_parse_custom_colours(CDSC *dsc); dsc_private int dsc_parse_cmyk_custom_colour(CDSC *dsc); dsc_private int dsc_parse_rgb_custom_colour(CDSC *dsc); /* DSC error reporting */ dsc_private const int dsc_severity[] = { CDSC_ERROR_WARN, /* CDSC_MESSAGE_BBOX */ CDSC_ERROR_WARN, /* CDSC_MESSAGE_EARLY_TRAILER */ CDSC_ERROR_WARN, /* CDSC_MESSAGE_EARLY_EOF */ CDSC_ERROR_ERROR, /* CDSC_MESSAGE_PAGE_IN_TRAILER */ CDSC_ERROR_ERROR, /* CDSC_MESSAGE_PAGE_ORDINAL */ CDSC_ERROR_ERROR, /* CDSC_MESSAGE_PAGES_WRONG */ CDSC_ERROR_ERROR, /* CDSC_MESSAGE_EPS_NO_BBOX */ CDSC_ERROR_ERROR, /* CDSC_MESSAGE_EPS_PAGES */ CDSC_ERROR_WARN, /* CDSC_MESSAGE_NO_MEDIA */ CDSC_ERROR_WARN, /* CDSC_MESSAGE_ATEND */ CDSC_ERROR_INFORM, /* CDSC_MESSAGE_DUP_COMMENT */ CDSC_ERROR_INFORM, /* CDSC_MESSAGE_DUP_TRAILER */ CDSC_ERROR_WARN, /* CDSC_MESSAGE_BEGIN_END */ CDSC_ERROR_INFORM, /* CDSC_MESSAGE_BAD_SECTION */ CDSC_ERROR_INFORM, /* CDSC_MESSAGE_LONG_LINE */ CDSC_ERROR_WARN, /* CDSC_MESSAGE_INCORRECT_USAGE */ 0 }; #define DSC_MAX_ERROR ((sizeof(dsc_severity) / sizeof(int))-2) const CDSCMEDIA dsc_known_media[CDSC_KNOWN_MEDIA] = { /* These sizes taken from Ghostscript gs_statd.ps */ {"11x17", 792, 1224, 0, NULL, NULL, NULL}, {"A3", 842, 1190, 0, NULL, NULL, NULL}, {"A4", 595, 842, 0, NULL, NULL, NULL}, {"A5", 421, 595, 0, NULL, NULL, NULL}, {"B4", 709, 1002, 0, NULL, NULL, NULL}, /* ISO, but not Adobe standard */ {"B5", 501, 709, 0, NULL, NULL, NULL}, /* ISO, but not Adobe standard */ {"Ledger", 1224, 792, 0, NULL, NULL, NULL}, {"Legal", 612, 1008, 0, NULL, NULL, NULL}, {"Letter", 612, 792, 0, NULL, NULL, NULL}, {"Note", 612, 792, 0, NULL, NULL, NULL}, /* Other standard sizes */ {"A0", 2384, 3370, 0, NULL, NULL, NULL}, {"A1", 1684, 2384, 0, NULL, NULL, NULL}, {"A2", 1190, 1684, 0, NULL, NULL, NULL}, /* Other non-standard sizes */ {"AnsiA", 612, 792, 0, NULL, NULL, NULL}, /* 8.5 x 11" */ {"AnsiB", 792, 1224, 0, NULL, NULL, NULL}, /* 11 x 17" */ {"AnsiC", 1224, 1584, 0, NULL, NULL, NULL}, /* 17 x 22" */ {"AnsiD", 1584, 2448, 0, NULL, NULL, NULL}, /* 22 x 34" */ {"AnsiE", 2448, 3168, 0, NULL, NULL, NULL}, /* 34 x 44" */ {"ArchA", 648, 864, 0, NULL, NULL, NULL}, /* 9 x 12" */ {"ArchB", 864, 1296, 0, NULL, NULL, NULL}, /* 12 x 18" */ {"ArchC", 1296, 1728, 0, NULL, NULL, NULL}, /* 18 x 24" */ {"ArchD", 1728, 2592, 0, NULL, NULL, NULL}, /* 24 x 36" */ {"ArchE", 2592, 3456, 0, NULL, NULL, NULL}, /* 36 x 48" */ {"ArchF", 2160, 3024, 0, NULL, NULL, NULL}, /* 30 x 42" */ {NULL, 0, 0, 0, NULL, NULL, NULL} }; /* parser state */ enum CDSC_SCAN_SECTION { scan_none = 0, scan_comments = 1, scan_pre_preview = 2, scan_preview = 3, scan_pre_defaults = 4, scan_defaults = 5, scan_pre_prolog = 6, scan_prolog = 7, scan_pre_setup = 8, scan_setup = 9, scan_pre_pages = 10, scan_pages = 11, scan_pre_trailer = 12, scan_trailer = 13, scan_eof = 14 }; static const char * const dsc_scan_section_name[15] = { "Type", "Comments", "pre-Preview", "Preview", "pre-Defaults", "Defaults", "pre-Prolog", "Prolog", "pre-Setup", "Setup", "pre-Page", "Page", "pre-Trailer", "Trailer", "EOF" }; /******************************************************************/ /* Public functions */ /******************************************************************/ /* constructor */ CDSC * dsc_init(void *caller_data) { CDSC *dsc = (CDSC *)malloc(sizeof(CDSC)); if (dsc == NULL) return NULL; memset(dsc, 0, sizeof(CDSC)); dsc->caller_data = caller_data; dsc->ref_count = 0; dsc_ref(dsc); return dsc_init2(dsc); } /* constructor, with caller supplied memalloc */ CDSC * dsc_init_with_alloc( void *caller_data, void *(*memalloc)(size_t size, void *closure_data), void (*memfree)(void *ptr, void *closure_data), void *closure_data) { CDSC *dsc = (CDSC *)memalloc(sizeof(CDSC), closure_data); if (dsc == NULL) return NULL; memset(dsc, 0, sizeof(CDSC)); dsc->caller_data = caller_data; dsc->memalloc = memalloc; dsc->memfree = memfree; dsc->mem_closure_data = closure_data; dsc->ref_count = 0; dsc_ref(dsc); return dsc_init2(dsc); } /* destructor */ void dsc_free(CDSC *dsc) { if (dsc == NULL) return; dsc_reset(dsc); dsc_memfree(dsc, dsc); } CDSC * dsc_new(void *caller_data) { return dsc_init(caller_data); } int dsc_ref(CDSC *dsc) { return ++(dsc->ref_count); } int dsc_unref(CDSC *dsc) { if (dsc->ref_count <= 0) return -1; dsc->ref_count--; if (dsc->ref_count == 0) { dsc_free(dsc); return 0; } return dsc->ref_count; } /* Tell DSC parser how long document will be, to allow ignoring * of early %%Trailer and %%EOF. This is optional. */ void dsc_set_length(CDSC *dsc, DSC_OFFSET len) { dsc->file_length = len; } /* Process a buffer containing DSC comments and PostScript */ /* Return value is < 0 for error, >=0 for OK. * CDSC_ERROR * CDSC_OK * CDSC_NOTDSC (DSC will be ignored) * other values indicate the last DSC comment read */ int dsc_scan_data(CDSC *dsc, const char *data, int length) { int bytes_read; int code = 0; if (dsc == NULL) return CDSC_ERROR; if (dsc->id == CDSC_NOTDSC) return CDSC_NOTDSC; dsc->id = CDSC_OK; if (dsc->eof) return CDSC_OK; /* ignore */ if (length == 0) { /* EOF, so process what remains */ dsc->eof = TRUE; } do { if (dsc->id == CDSC_NOTDSC) break; if (length != 0) { /* move existing data if needed */ if (dsc->data_length > CDSC_DATA_LENGTH/2) { memmove(dsc->data, dsc->data + dsc->data_index, dsc->data_length - dsc->data_index); dsc->data_offset += dsc->data_index; dsc->data_length -= dsc->data_index; dsc->data_index = 0; } /* append to buffer */ bytes_read = min(length, (int)(CDSC_DATA_LENGTH - dsc->data_length)); memcpy(dsc->data + dsc->data_length, data, bytes_read); dsc->data_length += bytes_read; data += bytes_read; length -= bytes_read; } if (dsc->scan_section == scan_none) { code = dsc_scan_type(dsc); if (code == CDSC_NEEDMORE) { /* need more characters before we can identify type */ code = CDSC_OK; break; } dsc->id = code; } if (code == CDSC_NOTDSC) { dsc->id = CDSC_NOTDSC; break; } while ((code = dsc_read_line(dsc)) > 0) { if (dsc->id == CDSC_NOTDSC) break; if (dsc->file_length && (dsc->data_offset + dsc->data_index > dsc->file_length)) { /* have read past end of where we need to parse. */ return CDSC_OK; /* ignore */ } if (dsc->doseps_end && (dsc->data_offset + dsc->data_index > dsc->doseps_end)) { /* have read past end of DOS EPS or Mac Binary * PostScript section */ return CDSC_OK; /* ignore */ } if (dsc->eof) return CDSC_OK; if (dsc->skip_document) continue; /* embedded document */ if (dsc->skip_lines) continue; /* embedded lines */ if (IS_DSC(dsc->line, "%%BeginData:")) continue; if (IS_DSC(dsc->line, "%%BeginBinary:")) continue; if (IS_DSC(dsc->line, "%%EndDocument")) continue; if (IS_DSC(dsc->line, "%%EndData")) continue; if (IS_DSC(dsc->line, "%%EndBinary")) continue; do { switch (dsc->scan_section) { case scan_comments: code = dsc_scan_comments(dsc); break; case scan_pre_preview: case scan_preview: code = dsc_scan_preview(dsc); break; case scan_pre_defaults: case scan_defaults: code = dsc_scan_defaults(dsc); break; case scan_pre_prolog: case scan_prolog: code = dsc_scan_prolog(dsc); break; case scan_pre_setup: case scan_setup: code = dsc_scan_setup(dsc); break; case scan_pre_pages: case scan_pages: code = dsc_scan_page(dsc); break; case scan_pre_trailer: case scan_trailer: code = dsc_scan_trailer(dsc); break; case scan_eof: code = CDSC_OK; break; default: /* invalid state */ code = CDSC_ERROR; } /* repeat if line is start of next section */ } while (code == CDSC_PROPAGATE); /* if DOS EPS header not complete, ask for more */ if (code == CDSC_NEEDMORE) { code = CDSC_OK; break; } if (code == CDSC_NOTDSC) { dsc->id = CDSC_NOTDSC; break; } } } while (length != 0); return (code < 0) ? code : dsc->id; } /* Tidy up from incorrect DSC comments */ int dsc_fixup(CDSC *dsc) { unsigned int i; char buf[32]; DSC_OFFSET *last; if (dsc->id == CDSC_NOTDSC) return 0; /* flush last partial line */ dsc_scan_data(dsc, NULL, 0); /* Fix DSC error: EOF before end of %%BeginData */ if (dsc->eof && (dsc->skip_lines || dsc->skip_bytes || dsc->skip_document)) { switch (dsc->scan_section) { case scan_comments: dsc->endcomments = DSC_END(dsc); break; case scan_preview: dsc->endpreview = DSC_END(dsc); break; case scan_defaults: dsc->enddefaults = DSC_END(dsc); break; case scan_prolog: dsc->endprolog = DSC_END(dsc); break; case scan_setup: dsc->endsetup = DSC_END(dsc); break; case scan_pages: if (dsc->page_count) dsc->page[dsc->page_count-1].end = DSC_END(dsc); break; case scan_trailer: case scan_eof: dsc->endtrailer = DSC_END(dsc); break; } } /* Fix DSC error: code between %%EndSetup and %%Page */ if (dsc->page_count && (dsc->page[0].begin != dsc->endsetup) && (dsc->endsetup != dsc->beginsetup)) { dsc->endsetup = dsc->page[0].begin; dsc_debug_print(dsc, "Warning: code included between setup and first page\n"); } /* Last page contained a false trailer, */ /* so extend last page to start of trailer */ if (dsc->page_count && (dsc->begintrailer != 0) && (dsc->page[dsc->page_count-1].end != dsc->begintrailer)) { dsc_debug_print(dsc, "Ignoring earlier misplaced trailer\n"); dsc_debug_print(dsc, "and extending last page to start of trailer\n"); dsc->page[dsc->page_count-1].end = dsc->begintrailer; } /* * Join up all sections. * There might be extra code between them, or we might have * missed including the \n which followed \r. */ last = &dsc->endcomments; dsc_section_join(dsc->beginpreview, &dsc->endpreview, &last); dsc_section_join(dsc->begindefaults, &dsc->enddefaults, &last); dsc_section_join(dsc->beginprolog, &dsc->endprolog, &last); dsc_section_join(dsc->beginsetup, &dsc->endsetup, &last); for (i=0; ipage_count; i++) dsc_section_join(dsc->page[i].begin, &dsc->page[i].end, &last); if (dsc->begintrailer) *last = dsc->begintrailer; if ((dsc->page_pages == 0) && (dsc->page_count == 1)) { /* don't flag an error if %%Pages absent but one %%Page found */ /* adjust incorrect page count */ dsc->page_pages = dsc->page_count; } /* Warnings and Errors that we can now identify */ if ((dsc->page_count != dsc->page_pages)) { int rc = dsc_error(dsc, CDSC_MESSAGE_PAGES_WRONG, NULL, 0); switch (rc) { case CDSC_RESPONSE_OK: /* adjust incorrect page count */ dsc->page_pages = dsc->page_count; break; case CDSC_RESPONSE_CANCEL: break;; case CDSC_RESPONSE_IGNORE_ALL: return CDSC_NOTDSC; } } if (dsc->epsf && (dsc->bbox == (CDSCBBOX *)NULL)) { /* EPS files MUST include a BoundingBox */ int rc = dsc_error(dsc, CDSC_MESSAGE_EPS_NO_BBOX, NULL, 0); switch (rc) { case CDSC_RESPONSE_OK: /* Assume that it is EPS */ break; case CDSC_RESPONSE_CANCEL: /* Is NOT an EPS file */ dsc->epsf = FALSE; case CDSC_RESPONSE_IGNORE_ALL: return CDSC_NOTDSC; } } if (dsc->epsf && ((dsc->page_count > 1) || (dsc->page_pages > 1))) { int rc = dsc_error(dsc, CDSC_MESSAGE_EPS_PAGES, NULL, 0); switch (rc) { case CDSC_RESPONSE_OK: /* Is an EPS file */ break; case CDSC_RESPONSE_CANCEL: /* Is NOT an EPS file */ dsc->epsf = FALSE; break; case CDSC_RESPONSE_IGNORE_ALL: return CDSC_NOTDSC; } } /* convert single file DSC 2.0 into multiple pages */ dsc_dcs2_fixup(dsc); if ((dsc->media_count == 1) && (dsc->page_media == NULL)) { /* if one only media was specified, and default page media */ /* was not specified, assume that default is the only media. */ dsc->page_media = dsc->media[0]; } if ((dsc->media_count != 0) && (dsc->page_media == NULL)) { int rc = dsc_error(dsc, CDSC_MESSAGE_NO_MEDIA, NULL, 0); switch (rc) { case CDSC_RESPONSE_OK: /* default media is first listed */ dsc->page_media = dsc->media[0]; break; case CDSC_RESPONSE_CANCEL: /* No default media */ break; case CDSC_RESPONSE_IGNORE_ALL: return CDSC_NOTDSC; } } /* make sure all pages have a label */ for (i=0; ipage_count; i++) { if (strlen(dsc->page[i].label) == 0) { sprintf(buf, "%d", i+1); if ((dsc->page[i].label = dsc_alloc_string(dsc, buf, (int)strlen(buf))) == (char *)NULL) return CDSC_ERROR; /* no memory */ } } return CDSC_OK; } /* Install a function to be used for displaying messages about * DSC errors and warnings, and to request advice from user. * Installing an error function is optional. */ void dsc_set_error_function(CDSC *dsc, int (*fn)(void *caller_data, CDSC *dsc, unsigned int explanation, const char *line, unsigned int line_len)) { dsc->dsc_error_fn = fn; } /* Install a function for printing debug messages */ /* This is optional */ void dsc_set_debug_function(CDSC *dsc, void (*debug_fn)(void *caller_data, const char *str)) { dsc->debug_print_fn = debug_fn; } /* Doesn't need to be public for PostScript documents */ /* Made public so GSview can add pages when processing PDF files */ int dsc_add_page(CDSC *dsc, int ordinal, char *label) { dsc->page[dsc->page_count].ordinal = ordinal; dsc->page[dsc->page_count].label = dsc_alloc_string(dsc, label, (int)strlen(label)+1); dsc->page[dsc->page_count].begin = 0; dsc->page[dsc->page_count].end = 0; dsc->page[dsc->page_count].orientation = CDSC_ORIENT_UNKNOWN; dsc->page[dsc->page_count].media = NULL; dsc->page[dsc->page_count].bbox = NULL; dsc->page[dsc->page_count].viewing_orientation = NULL; dsc->page[dsc->page_count].crop_box = NULL; dsc->page_count++; if (dsc->page_count >= dsc->page_chunk_length) { CDSCPAGE *new_page = (CDSCPAGE *)dsc_memalloc(dsc, (CDSC_PAGE_CHUNK+dsc->page_count) * sizeof(CDSCPAGE)); if (new_page == NULL) return CDSC_ERROR; /* out of memory */ memcpy(new_page, dsc->page, dsc->page_count * sizeof(CDSCPAGE)); dsc_memfree(dsc, dsc->page); dsc->page= new_page; dsc->page_chunk_length = CDSC_PAGE_CHUNK+dsc->page_count; } return CDSC_OK; } /* Doesn't need to be public for PostScript documents */ /* Made public so GSview can store PDF MediaBox */ int dsc_add_media(CDSC *dsc, CDSCMEDIA *media) { CDSCMEDIA **newmedia_array; CDSCMEDIA *newmedia; /* extend media array */ newmedia_array = (CDSCMEDIA **)dsc_memalloc(dsc, (dsc->media_count + 1) * sizeof(CDSCMEDIA *)); if (newmedia_array == NULL) return CDSC_ERROR; /* out of memory */ if (dsc->media != NULL) { memcpy(newmedia_array, dsc->media, dsc->media_count * sizeof(CDSCMEDIA *)); dsc_memfree(dsc, dsc->media); } dsc->media = newmedia_array; /* allocate new media */ newmedia = dsc->media[dsc->media_count] = (CDSCMEDIA *)dsc_memalloc(dsc, sizeof(CDSCMEDIA)); if (newmedia == NULL) return CDSC_ERROR; /* out of memory */ newmedia->name = NULL; newmedia->width = 595.0; newmedia->height = 842.0; newmedia->weight = 80.0; newmedia->colour = NULL; newmedia->type = NULL; newmedia->mediabox = NULL; dsc->media_count++; if (media->name) { newmedia->name = dsc_alloc_string(dsc, media->name, (int)strlen(media->name)); if (newmedia->name == NULL) return CDSC_ERROR; /* no memory */ } newmedia->width = media->width; newmedia->height = media->height; newmedia->weight = media->weight; if (media->colour) { newmedia->colour = dsc_alloc_string(dsc, media->colour, (int)strlen(media->colour)); if (newmedia->colour == NULL) return CDSC_ERROR; /* no memory */ } if (media->type) { newmedia->type = dsc_alloc_string(dsc, media->type, (int)strlen(media->type)); if (newmedia->type == NULL) return CDSC_ERROR; /* no memory */ } newmedia->mediabox = NULL; if (media->mediabox) { newmedia->mediabox = (CDSCBBOX *)dsc_memalloc(dsc, sizeof(CDSCBBOX)); if (newmedia->mediabox == NULL) return CDSC_ERROR; /* no memory */ *newmedia->mediabox = *media->mediabox; } return CDSC_OK; } /* Doesn't need to be public for PostScript documents */ /* Made public so GSview can store PDF CropBox */ int dsc_set_page_bbox(CDSC *dsc, unsigned int page_number, int llx, int lly, int urx, int ury) { CDSCBBOX *bbox; if (page_number >= dsc->page_count) return CDSC_ERROR; bbox = dsc->page[page_number].bbox; if (bbox == NULL) dsc->page[page_number].bbox = bbox = (CDSCBBOX *)dsc_memalloc(dsc, sizeof(CDSCBBOX)); if (bbox == NULL) return CDSC_ERROR; bbox->llx = llx; bbox->lly = lly; bbox->urx = urx; bbox->ury = ury; return CDSC_OK; } /******************************************************************/ /* Private functions below here. */ /******************************************************************/ dsc_private void * dsc_memalloc(CDSC *dsc, size_t size) { if (dsc->memalloc) return dsc->memalloc(size, dsc->mem_closure_data); return malloc(size); } dsc_private void dsc_memfree(CDSC*dsc, void *ptr) { if (dsc->memfree) dsc->memfree(ptr, dsc->mem_closure_data); else free(ptr); } /* private constructor */ dsc_private CDSC * dsc_init2(CDSC *dsc) { dsc_reset(dsc); dsc->string_head = (CDSCSTRING *)dsc_memalloc(dsc, sizeof(CDSCSTRING)); if (dsc->string_head == NULL) { dsc_free(dsc); return NULL; /* no memory */ } dsc->string = dsc->string_head; dsc->string->next = NULL; dsc->string->data = (char *)dsc_memalloc(dsc, CDSC_STRING_CHUNK); if (dsc->string->data == NULL) { dsc_free(dsc); return NULL; /* no memory */ } dsc->string->index = 0; dsc->string->length = CDSC_STRING_CHUNK; dsc->page = (CDSCPAGE *)dsc_memalloc(dsc, CDSC_PAGE_CHUNK * sizeof(CDSCPAGE)); if (dsc->page == NULL) { dsc_free(dsc); return NULL; /* no memory */ } dsc->page_chunk_length = CDSC_PAGE_CHUNK; dsc->page_count = 0; dsc->line = NULL; dsc->data_length = 0; dsc->data_index = dsc->data_length; return dsc; } dsc_private void dsc_reset(CDSC *dsc) { unsigned int i; /* Clear public members */ dsc->dsc = FALSE; dsc->ctrld = FALSE; dsc->pjl = FALSE; dsc->epsf = FALSE; dsc->pdf = FALSE; dsc->epsf = FALSE; dsc->preview = CDSC_NOPREVIEW; dsc->dsc_version = NULL; /* stored in dsc->string */ dsc->language_level = 0; dsc->document_data = CDSC_DATA_UNKNOWN; dsc->begincomments = 0; dsc->endcomments = 0; dsc->beginpreview = 0; dsc->endpreview = 0; dsc->begindefaults = 0; dsc->enddefaults = 0; dsc->beginprolog = 0; dsc->endprolog = 0; dsc->beginsetup = 0; dsc->endsetup = 0; dsc->begintrailer = 0; dsc->endtrailer = 0; for (i=0; ipage_count; i++) { /* page media is pointer to an element of media or dsc_known_media */ /* do not free it. */ if (dsc->page[i].bbox) dsc_memfree(dsc, dsc->page[i].bbox); if (dsc->page[i].viewing_orientation) dsc_memfree(dsc, dsc->page[i].viewing_orientation); if (dsc->page[i].crop_box) dsc_memfree(dsc, dsc->page[i].crop_box); } if (dsc->page) dsc_memfree(dsc, dsc->page); dsc->page = NULL; dsc->page_count = 0; dsc->page_pages = 0; dsc->page_order = CDSC_ORDER_UNKNOWN; dsc->page_orientation = CDSC_ORIENT_UNKNOWN; if (dsc->viewing_orientation) dsc_memfree(dsc, dsc->viewing_orientation); dsc->viewing_orientation = NULL; if (dsc->media) { for (i=0; imedia_count; i++) { if (dsc->media[i]) { if (dsc->media[i]->mediabox) dsc_memfree(dsc, dsc->media[i]->mediabox); dsc_memfree(dsc, dsc->media[i]); } } dsc_memfree(dsc, dsc->media); } dsc->media_count = 0; dsc->media = NULL; /* page_media is pointer to an element of media or dsc_known_media */ /* do not free it. */ dsc->page_media = NULL; if (dsc->bbox) dsc_memfree(dsc, dsc->bbox); dsc->bbox = NULL; if (dsc->page_bbox) dsc_memfree(dsc, dsc->page_bbox); dsc->page_bbox = NULL; if (dsc->doseps) dsc_memfree(dsc, dsc->doseps); dsc->doseps = NULL; dsc->dsc_title = NULL; dsc->dsc_creator = NULL; dsc->dsc_date = NULL; dsc->dsc_for = NULL; dsc->max_error = DSC_MAX_ERROR; dsc->severity = dsc_severity; /* Clear private members */ /* Don't touch dsc->caller_data */ dsc->id = CDSC_OK; dsc->scan_section = scan_none; dsc->doseps_end = 0; dsc->page_chunk_length = 0; dsc->file_length = 0; dsc->skip_document = 0; dsc->skip_bytes = 0; dsc->skip_lines = 0; dsc->skip_pjl = 0; dsc->begin_font_count = 0; dsc->begin_feature_count = 0; dsc->begin_resource_count = 0; dsc->begin_procset_count = 0; dsc->data_length = 0; dsc->data_index = 0; dsc->data_offset = 0; dsc->eof = 0; dsc->line = 0; dsc->line_length = 0; dsc->eol = 0; dsc->last_cr = FALSE; dsc->line_count = 1; dsc->long_line = FALSE; memset(dsc->last_line, 0, sizeof(dsc->last_line)); dsc->string = dsc->string_head; while (dsc->string != (CDSCSTRING *)NULL) { if (dsc->string->data) dsc_memfree(dsc, dsc->string->data); dsc->string_head = dsc->string; dsc->string = dsc->string->next; dsc_memfree(dsc, dsc->string_head); } dsc->string_head = NULL; dsc->string = NULL; /* don't touch caller functions */ /* public data */ if (dsc->hires_bbox) dsc_memfree(dsc, dsc->hires_bbox); dsc->hires_bbox = NULL; if (dsc->crop_box) dsc_memfree(dsc, dsc->crop_box); dsc->crop_box = NULL; if (dsc->dcs2) { CDCS2 *this_dcs, *next_dcs; this_dcs = dsc->dcs2; while (this_dcs) { next_dcs = this_dcs->next; /* strings have already been freed */ dsc_memfree(dsc, this_dcs); this_dcs = next_dcs; } dsc->dcs2 = NULL; } if (dsc->colours) { CDSCCOLOUR *this_colour, *next_colour; this_colour = dsc->colours; while (this_colour) { next_colour = this_colour->next; /* strings have already been freed */ dsc_memfree(dsc, this_colour); this_colour = next_colour; } dsc->colours = NULL; } if (dsc->macbin) dsc_memfree(dsc, dsc->macbin); dsc->macbin = NULL; dsc->worst_error = CDSC_ERROR_NONE; } /* * Join up all sections. * There might be extra code between them, or we might have * missed including the \n which followed \r. * begin is the start of this section * pend is a pointer to the end of this section * pplast is a pointer to a pointer of the end of the previous section */ dsc_private void dsc_section_join(DSC_OFFSET begin, DSC_OFFSET *pend, DSC_OFFSET **pplast) { if (begin) **pplast = begin; if (*pend > begin) *pplast = pend; } /* return value is 0 if no line available, or length of line */ dsc_private int dsc_read_line(CDSC *dsc) { char *p, *last; dsc->line = NULL; if (dsc->eof) { /* return all that remains, even if line incomplete */ dsc->line = dsc->data + dsc->data_index; dsc->line_length = dsc->data_length - dsc->data_index; dsc->data_index = dsc->data_length; return dsc->line_length; } if (dsc->file_length && (dsc->data_offset + dsc->data_index >= dsc->file_length)) { /* Have read past where we need to parse. */ /* Ignore all that remains. */ dsc->line = dsc->data + dsc->data_index; dsc->line_length = dsc->data_length - dsc->data_index; dsc->data_index = dsc->data_length; return dsc->line_length; } if (dsc->doseps_end && (dsc->data_offset + dsc->data_index >= dsc->doseps_end)) { /* Have read past end of DOS EPS PostScript section. */ /* Ignore all that remains. */ dsc->line = dsc->data + dsc->data_index; dsc->line_length = dsc->data_length - dsc->data_index; dsc->data_index = dsc->data_length; return dsc->line_length; } /* ignore embedded bytes */ if (dsc->skip_bytes) { int cnt = min(dsc->skip_bytes, (int)(dsc->data_length - dsc->data_index)); dsc->skip_bytes -= cnt; dsc->data_index += cnt; if (dsc->skip_bytes != 0) return 0; } do { dsc->line = dsc->data + dsc->data_index; last = dsc->data + dsc->data_length; if (dsc->data_index == dsc->data_length) { dsc->line_length = 0; return 0; } if (dsc->eol) { /* if previous line was complete, increment line count */ dsc->line_count++; if (dsc->skip_lines) dsc->skip_lines--; } /* skip over \n which followed \r */ if (dsc->last_cr && dsc->line[0] == '\n') { dsc->data_index++; dsc->line++; } dsc->last_cr = FALSE; /* look for EOL */ dsc->eol = FALSE; for (p = dsc->line; p < last; p++) { if (*p == '\r') { p++; if ((plast_cr = TRUE; /* we might need to skip \n */ dsc->eol = TRUE; /* dsc->line is a complete line */ break; } if (*p == '\n') { p++; dsc->eol = TRUE; /* dsc->line is a complete line */ break; } if (*p == '\032') { /* MS-DOS Ctrl+Z */ dsc->eol = TRUE; } } if (dsc->eol == FALSE) { /* we haven't got a complete line yet */ if (dsc->data_length - dsc->data_index < sizeof(dsc->data)/2) { /* buffer is less than half full, ask for some more */ dsc->line_length = 0; return 0; } } dsc->data_index += dsc->line_length = (int)(p - dsc->line); } while (dsc->skip_lines && dsc->line_length); if (dsc->line_length == 0) return 0; if ((dsc->line[0]=='%') && (dsc->line[1]=='%')) { /* handle recursive %%BeginDocument */ if ((dsc->skip_document) && dsc->line_length && COMPARE(dsc->line, "%%EndDocument")) { dsc->skip_document--; } /* handle embedded lines or binary data */ if (COMPARE(dsc->line, "%%BeginData:")) { /* %%BeginData: [ [ ] ] * ::= (Lines or physical bytes) * ::= Hex | Binary | ASCII (Type of data) * ::= Bytes | Lines (Read in bytes or lines) */ char begindata[MAXSTR+1]; int cnt; const char *numberof, *bytesorlines; cnt = dsc->line_length; if (dsc->line_length > sizeof(begindata)-1) cnt = sizeof(begindata)-1; memcpy(begindata, dsc->line, cnt); begindata[cnt] = '\0'; numberof = strtok(begindata+12, " \r\n"); strtok(NULL, " \r\n"); /* dump type */ bytesorlines = strtok(NULL, " \r\n"); if (bytesorlines == NULL) bytesorlines = "Bytes"; if ( (numberof == NULL) || (bytesorlines == NULL) ) { /* invalid usage of %%BeginData */ /* ignore that we ever saw it */ int rc = dsc_error(dsc, CDSC_MESSAGE_INCORRECT_USAGE, dsc->line, dsc->line_length); switch (rc) { case CDSC_RESPONSE_OK: case CDSC_RESPONSE_CANCEL: break; case CDSC_RESPONSE_IGNORE_ALL: return 0; } } else { cnt = atoi(numberof); if (cnt) { if (bytesorlines && (dsc_stricmp(bytesorlines, "Lines")==0)) { /* skip cnt lines */ if (dsc->skip_lines == 0) { /* we are not already skipping lines */ dsc->skip_lines = cnt+1; } } else { /* byte count doesn't includes \n or \r\n */ /* or \r of %%BeginData: */ /* skip cnt bytes */ if (dsc->skip_bytes == 0) { /* we are not already skipping lines */ dsc->skip_bytes = cnt; } } } } } else if (COMPARE(dsc->line, "%%BeginBinary:")) { /* byte count doesn't includes \n or \r\n or \r of %%BeginBinary:*/ int cnt = dsc_get_int(dsc->line + 14, dsc->line_length - 14, NULL); if (dsc->skip_bytes == 0) { /* we are not already skipping lines */ dsc->skip_bytes = cnt; } } } if ((dsc->line[0]=='%') && (dsc->line[1]=='%') && COMPARE(dsc->line, "%%BeginDocument:") ) { /* Skip over embedded document, recursively */ dsc->skip_document++; } if (!dsc->long_line && (dsc->line_length > DSC_LINE_LENGTH)) { dsc_error(dsc, CDSC_MESSAGE_LONG_LINE, dsc->line, dsc->line_length); dsc->long_line = TRUE; } return dsc->line_length; } /* Save last DSC line, for use with %%+ */ dsc_private void dsc_save_line(CDSC *dsc) { int len = min(sizeof(dsc->last_line), dsc->line_length); memcpy(dsc->last_line, dsc->line, len); } /* display unknown DSC line */ dsc_private void dsc_unknown(CDSC *dsc) { if (dsc->debug_print_fn) { char line[DSC_LINE_LENGTH]; unsigned int length = min(DSC_LINE_LENGTH-1, dsc->line_length); sprintf(line, "Unknown in %s section at line %d:\n ", dsc_scan_section_name[dsc->scan_section], dsc->line_count); dsc_debug_print(dsc, line); strncpy(line, dsc->line, length); line[length] = '\0'; dsc_debug_print(dsc, line); dsc_debug_print(dsc, "\n"); } } dsc_private GSBOOL dsc_is_section(char *line) { if ( !((line[0]=='%') && (line[1]=='%')) ) return FALSE; if (IS_DSC(line, "%%BeginPreview")) return TRUE; if (IS_DSC(line, "%%BeginDefaults")) return TRUE; if (IS_DSC(line, "%%BeginProlog")) return TRUE; if (IS_DSC(line, "%%BeginSetup")) return TRUE; if (IS_DSC(line, "%%Page:")) return TRUE; if (IS_DSC(line, "%%Trailer")) return TRUE; if (IS_DSC(line, "%%EOF")) return TRUE; return FALSE; } /* Get little-endian DWORD, used for DOS EPS files */ dsc_private GSDWORD dsc_get_dword(const unsigned char *buf) { GSDWORD dw; dw = (GSDWORD)buf[0]; dw += ((GSDWORD)buf[1])<<8; dw += ((GSDWORD)buf[2])<<16; dw += ((GSDWORD)buf[3])<<24; return dw; } dsc_private GSWORD dsc_get_word(const unsigned char *buf) { GSWORD w; w = (GSWORD)buf[0]; w |= (GSWORD)(buf[1]<<8); return w; } /* Get big-endian DWORD, used for Mac Binary files */ dsc_private GSDWORD dsc_get_bigendian_dword(const unsigned char *buf) { GSDWORD dw; dw = (GSDWORD)buf[3]; dw += ((GSDWORD)buf[2])<<8; dw += ((GSDWORD)buf[1])<<16; dw += ((GSDWORD)buf[0])<<24; return dw; } dsc_private GSWORD dsc_get_bigendian_word(const unsigned char *buf) { GSWORD w; w = (GSWORD)buf[1]; w |= (GSWORD)(buf[0]<<8); return w; } dsc_private int dsc_read_doseps(CDSC *dsc) { unsigned char *line = (unsigned char *)dsc->line; if ((dsc->doseps = (CDSCDOSEPS *)dsc_memalloc(dsc, sizeof(CDSCDOSEPS))) == NULL) return CDSC_ERROR; /* no memory */ dsc->doseps->ps_begin = dsc_get_dword(line+4); dsc->doseps->ps_length = dsc_get_dword(line+8); dsc->doseps->wmf_begin = dsc_get_dword(line+12); dsc->doseps->wmf_length = dsc_get_dword(line+16); dsc->doseps->tiff_begin = dsc_get_dword(line+20); dsc->doseps->tiff_length = dsc_get_dword(line+24); dsc->doseps->checksum = dsc_get_word(line+28); if (dsc->file_length && (dsc->doseps->ps_begin + dsc->doseps->ps_length > dsc->file_length)) { /* Error in DOS EPS header. * Some files have been seen with a fixed large value as * the length of the PostScript section. * Correct for these erroneous files. */ dsc->doseps->ps_length = (GSDWORD)(dsc->file_length - dsc->doseps->ps_begin); } dsc->doseps_end = dsc->doseps->ps_begin + dsc->doseps->ps_length; /* move data_index backwards to byte after doseps header */ dsc->data_index -= dsc->line_length - 30; /* we haven't read a line of PostScript code yet */ dsc->line_count = 0; /* skip from current position to start of PostScript section */ dsc->skip_bytes = dsc->doseps->ps_begin - 30; if (dsc->doseps->tiff_begin) dsc->preview = CDSC_TIFF; if (dsc->doseps->wmf_begin) dsc->preview = CDSC_WMF; return CDSC_OK; } dsc_private int dsc_read_macbin(CDSC *dsc) { unsigned char *line = (unsigned char *)dsc->line; if ((dsc->macbin = (CDSCMACBIN *)dsc_memalloc(dsc, sizeof(CDSCMACBIN))) == NULL) return CDSC_ERROR; /* no memory */ dsc->macbin->data_begin = 128; dsc->macbin->data_length = dsc_get_bigendian_dword(line+83); dsc->macbin->resource_begin = (dsc->macbin->data_begin + dsc->macbin->data_length + 127 ) & ~127; dsc->macbin->resource_length = dsc_get_bigendian_dword(line+87); /* A MacBinary file has been seen that doesn't have the resource * fork padded out to 128 bytes. Just make sure that the resource * doesn't extend beyond EOF. */ if (dsc->file_length && (((dsc->macbin->resource_begin + dsc->macbin->resource_length /* + 127 */ ) /* & ~127 */ ) > dsc->file_length)) { return CDSC_ERROR; } dsc->doseps_end = dsc->macbin->data_begin + dsc->macbin->data_length; /* move data_index to byte after Mac Binary header */ dsc->data_index -= dsc->line_length - 128; /* we haven't read a line of PostScript code yet */ dsc->line_count = 0; dsc->preview = CDSC_PICT; return CDSC_OK; } dsc_private int dsc_read_applesingle(CDSC *dsc) { GSDWORD EntryID; GSDWORD Offset; GSDWORD Length; GSWORD entries; int index; int header; int i; unsigned char *line = (unsigned char *)dsc->line; if ((dsc->macbin = (CDSCMACBIN *)dsc_memalloc(dsc, sizeof(CDSCMACBIN))) == NULL) return CDSC_ERROR; /* no memory */ entries = dsc_get_bigendian_word(line+24); for (i=0; i<(int)entries; i++) { index = 26 + i * 12; EntryID = dsc_get_bigendian_dword(line+index); Offset = dsc_get_bigendian_dword(line+index+4); Length = dsc_get_bigendian_dword(line+index+8); if (EntryID == 1) { /* data fork */ dsc->macbin->data_begin = Offset; dsc->macbin->data_length = Length; } else if (EntryID == 2) { /* resource fork */ dsc->macbin->resource_begin = Offset; dsc->macbin->resource_length = Length; } } if (dsc->file_length && (dsc->macbin->resource_begin + dsc->macbin->resource_length > dsc->file_length)) { return CDSC_ERROR; } if (dsc->file_length && (dsc->macbin->data_begin + dsc->macbin->data_length > dsc->file_length)) { return CDSC_ERROR; } dsc->doseps_end = dsc->macbin->data_begin + dsc->macbin->data_length; header = 26 + entries * 12; /* move data_index to byte after AppleSingle/AppleDouble header */ dsc->data_index -= dsc->line_length - header; /* we haven't read a line of PostScript code yet */ dsc->line_count = 0; /* skip from current position to start of PostScript section */ dsc->skip_bytes = dsc->macbin->data_begin - header; dsc->preview = CDSC_PICT; return CDSC_OK; } dsc_private int dsc_parse_pages(CDSC *dsc) { int ip, io; unsigned int i; char *p; int n; if ((dsc->page_pages != 0) && (dsc->scan_section == scan_comments)) { int rc = dsc_error(dsc, CDSC_MESSAGE_DUP_COMMENT, dsc->line, dsc->line_length); switch (rc) { case CDSC_RESPONSE_OK: case CDSC_RESPONSE_CANCEL: return CDSC_OK; /* ignore duplicate comments in header */ case CDSC_RESPONSE_IGNORE_ALL: return CDSC_NOTDSC; } } if ((dsc->page_pages != 0) && (dsc->scan_section == scan_trailer)) { int rc = dsc_error(dsc, CDSC_MESSAGE_DUP_TRAILER, dsc->line, dsc->line_length); switch (rc) { case CDSC_RESPONSE_OK: case CDSC_RESPONSE_CANCEL: break; /* use duplicate comments in header */ case CDSC_RESPONSE_IGNORE_ALL: return CDSC_NOTDSC; } } n = IS_DSC(dsc->line, "%%+") ? 3 : 8; while (IS_WHITE(dsc->line[n])) n++; p = dsc->line + n; if (COMPARE(p, "atend")) { if (dsc->scan_section != scan_comments) dsc_unknown(dsc); else { int rc = dsc_error(dsc, CDSC_MESSAGE_ATEND, dsc->line, dsc->line_length); switch (rc) { case CDSC_RESPONSE_OK: /* assume (atend) */ /* we should mark it as deferred */ break; case CDSC_RESPONSE_CANCEL: /* ignore it */ break; case CDSC_RESPONSE_IGNORE_ALL: return CDSC_NOTDSC; } } } else if (COMPARE(p, "(atend)")) { if (dsc->scan_section != scan_comments) dsc_unknown(dsc); /* do nothing */ /* we should mark it as deferred */ } else { ip = dsc_get_int(dsc->line+n, dsc->line_length-n, &i); if (i) { n+=i; dsc->page_pages = ip; io = dsc_get_int(dsc->line+n, dsc->line_length-n, &i); if (i) { /* DSC 2 uses extra integer to indicate page order */ /* DSC 3 uses %%PageOrder: */ if (dsc->page_order == CDSC_ORDER_UNKNOWN) switch (io) { case -1: dsc->page_order = CDSC_DESCEND; break; case 0: dsc->page_order = CDSC_SPECIAL; break; case 1: dsc->page_order = CDSC_ASCEND; break; } } } else { int rc = dsc_error(dsc, CDSC_MESSAGE_INCORRECT_USAGE, dsc->line, dsc->line_length); switch (rc) { case CDSC_RESPONSE_OK: case CDSC_RESPONSE_CANCEL: /* ignore it */ break; case CDSC_RESPONSE_IGNORE_ALL: return CDSC_NOTDSC; } } } return CDSC_OK; } dsc_private int dsc_parse_bounding_box(CDSC *dsc, CDSCBBOX** pbbox, int offset) { unsigned int i, n; int llx, lly, urx, ury; float fllx, flly, furx, fury; char *p; /* Process first %%BoundingBox: in comments, and last in trailer */ if ((*pbbox != NULL) && (dsc->scan_section == scan_comments)) { int rc = dsc_error(dsc, CDSC_MESSAGE_DUP_COMMENT, dsc->line, dsc->line_length); switch (rc) { case CDSC_RESPONSE_OK: case CDSC_RESPONSE_CANCEL: return CDSC_OK; /* ignore duplicate comments in header */ case CDSC_RESPONSE_IGNORE_ALL: return CDSC_NOTDSC; } } if ((*pbbox != NULL) && (dsc->scan_section == scan_pages)) { int rc = dsc_error(dsc, CDSC_MESSAGE_DUP_COMMENT, dsc->line, dsc->line_length); switch (rc) { case CDSC_RESPONSE_OK: case CDSC_RESPONSE_CANCEL: return CDSC_OK; /* ignore duplicate comments in header */ case CDSC_RESPONSE_IGNORE_ALL: return CDSC_NOTDSC; } } if ((*pbbox != NULL) && (dsc->scan_section == scan_trailer)) { int rc = dsc_error(dsc, CDSC_MESSAGE_DUP_TRAILER, dsc->line, dsc->line_length); switch (rc) { case CDSC_RESPONSE_OK: case CDSC_RESPONSE_CANCEL: break; /* use duplicate comments in trailer */ case CDSC_RESPONSE_IGNORE_ALL: return CDSC_NOTDSC; } } if (*pbbox != NULL) { dsc_memfree(dsc, *pbbox); *pbbox = NULL; } /* should only process first %%BoundingBox: */ while (IS_WHITE(dsc->line[offset])) offset++; p = dsc->line + offset; if (COMPARE(p, "atend")) { if (dsc->scan_section == scan_trailer) dsc_unknown(dsc); else { int rc = dsc_error(dsc, CDSC_MESSAGE_ATEND, dsc->line, dsc->line_length); switch (rc) { case CDSC_RESPONSE_OK: /* assume (atend) */ /* we should mark it as deferred */ break; case CDSC_RESPONSE_CANCEL: /* ignore it */ break; case CDSC_RESPONSE_IGNORE_ALL: return CDSC_NOTDSC; } } } else if (COMPARE(p, "(atend)")) { if (dsc->scan_section == scan_trailer) dsc_unknown(dsc); /* do nothing */ /* we should mark it as deferred */ } else { /* llx = */ lly = urx = ury = 0; n = offset; llx = dsc_get_int(dsc->line+n, dsc->line_length-n, &i); n += i; if (i) lly = dsc_get_int(dsc->line+n, dsc->line_length-n, &i); n += i; if (i) urx = dsc_get_int(dsc->line+n, dsc->line_length-n, &i); n += i; if (i) ury = dsc_get_int(dsc->line+n, dsc->line_length-n, &i); if (i) { *pbbox = (CDSCBBOX *)dsc_memalloc(dsc, sizeof(CDSCBBOX)); if (*pbbox == NULL) return CDSC_ERROR; /* no memory */ (*pbbox)->llx = llx; (*pbbox)->lly = lly; (*pbbox)->urx = urx; (*pbbox)->ury = ury; } else { int rc = dsc_error(dsc, CDSC_MESSAGE_BBOX, dsc->line, dsc->line_length); switch (rc) { case CDSC_RESPONSE_OK: /* fllx = */ flly = furx = fury = 0.0; n = offset; n += i; fllx = dsc_get_real(dsc->line+n, dsc->line_length-n, &i); n += i; if (i) flly = dsc_get_real(dsc->line+n, dsc->line_length-n, &i); n += i; if (i) furx = dsc_get_real(dsc->line+n, dsc->line_length-n, &i); n += i; if (i) fury = dsc_get_real(dsc->line+n, dsc->line_length-n, &i); if (i) { *pbbox = (CDSCBBOX *)dsc_memalloc(dsc, sizeof(CDSCBBOX)); if (*pbbox == NULL) return CDSC_ERROR; /* no memory */ (*pbbox)->llx = (int)fllx; (*pbbox)->lly = (int)flly; (*pbbox)->urx = (int)(furx+0.999); (*pbbox)->ury = (int)(fury+0.999); } return CDSC_OK; case CDSC_RESPONSE_CANCEL: return CDSC_OK; case CDSC_RESPONSE_IGNORE_ALL: return CDSC_NOTDSC; } } } return CDSC_OK; } dsc_private int dsc_parse_float_bounding_box(CDSC *dsc, CDSCFBBOX** pbbox, int offset) { unsigned int i, n; float fllx, flly, furx, fury; char *p; /* Process first %%HiResBoundingBox: or %%CropBox: in comments, * and last in trailer. */ if ((*pbbox != NULL) && (dsc->scan_section == scan_comments)) { int rc = dsc_error(dsc, CDSC_MESSAGE_DUP_COMMENT, dsc->line, dsc->line_length); switch (rc) { case CDSC_RESPONSE_OK: case CDSC_RESPONSE_CANCEL: return CDSC_OK; /* ignore duplicate comments in header */ case CDSC_RESPONSE_IGNORE_ALL: return CDSC_NOTDSC; } } if ((*pbbox != NULL) && (dsc->scan_section == scan_pages)) { int rc = dsc_error(dsc, CDSC_MESSAGE_DUP_COMMENT, dsc->line, dsc->line_length); switch (rc) { case CDSC_RESPONSE_OK: case CDSC_RESPONSE_CANCEL: return CDSC_OK; /* ignore duplicate comments in header */ case CDSC_RESPONSE_IGNORE_ALL: return CDSC_NOTDSC; } } if ((*pbbox != NULL) && (dsc->scan_section == scan_trailer)) { int rc = dsc_error(dsc, CDSC_MESSAGE_DUP_TRAILER, dsc->line, dsc->line_length); switch (rc) { case CDSC_RESPONSE_OK: case CDSC_RESPONSE_CANCEL: break; /* use duplicate comments in trailer */ case CDSC_RESPONSE_IGNORE_ALL: return CDSC_NOTDSC; } } if (*pbbox != NULL) { dsc_memfree(dsc, *pbbox); *pbbox = NULL; } /* should only process first %%BoundingBox: */ while (IS_WHITE(dsc->line[offset])) offset++; p = dsc->line + offset; if (COMPARE(p, "atend")) { if (dsc->scan_section == scan_trailer) dsc_unknown(dsc); else { int rc = dsc_error(dsc, CDSC_MESSAGE_ATEND, dsc->line, dsc->line_length); switch (rc) { case CDSC_RESPONSE_OK: /* assume (atend) */ /* we should mark it as deferred */ break; case CDSC_RESPONSE_CANCEL: /* ignore it */ break; case CDSC_RESPONSE_IGNORE_ALL: return CDSC_NOTDSC; } } } else if (COMPARE(p, "(atend)")) { if (dsc->scan_section == scan_trailer) dsc_unknown(dsc); /* do nothing */ /* we should mark it as deferred */ } else { /* fllx = */ flly = furx = fury = 0.0; n = offset; fllx = dsc_get_real(dsc->line+n, dsc->line_length-n, &i); n += i; if (i) flly = dsc_get_real(dsc->line+n, dsc->line_length-n, &i); n += i; if (i) furx = dsc_get_real(dsc->line+n, dsc->line_length-n, &i); n += i; if (i) fury = dsc_get_real(dsc->line+n, dsc->line_length-n, &i); if (i) { *pbbox = (CDSCFBBOX *)dsc_memalloc(dsc, sizeof(CDSCFBBOX)); if (*pbbox == NULL) return CDSC_ERROR; /* no memory */ (*pbbox)->fllx = fllx; (*pbbox)->flly = flly; (*pbbox)->furx = furx; (*pbbox)->fury = fury; } } return CDSC_OK; } dsc_private int dsc_parse_orientation(CDSC *dsc, unsigned int *porientation, int offset) { char *p; if ((dsc->page_orientation != CDSC_ORIENT_UNKNOWN) && (dsc->scan_section == scan_comments)) { int rc = dsc_error(dsc, CDSC_MESSAGE_DUP_COMMENT, dsc->line, dsc->line_length); switch (rc) { case CDSC_RESPONSE_OK: case CDSC_RESPONSE_CANCEL: return CDSC_OK; /* ignore duplicate comments in header */ case CDSC_RESPONSE_IGNORE_ALL: return CDSC_NOTDSC; } } if ((dsc->page_orientation != CDSC_ORIENT_UNKNOWN) && (dsc->scan_section == scan_trailer)) { int rc = dsc_error(dsc, CDSC_MESSAGE_DUP_TRAILER, dsc->line, dsc->line_length); switch (rc) { case CDSC_RESPONSE_OK: case CDSC_RESPONSE_CANCEL: break; /* use duplicate comments in header; */ case CDSC_RESPONSE_IGNORE_ALL: return CDSC_NOTDSC; } } p = dsc->line + offset; while (IS_WHITE(*p)) p++; if (COMPARE(p, "atend")) { if (dsc->scan_section == scan_trailer) dsc_unknown(dsc); else { int rc = dsc_error(dsc, CDSC_MESSAGE_ATEND, dsc->line, dsc->line_length); switch (rc) { case CDSC_RESPONSE_OK: /* assume (atend) */ /* we should mark it as deferred */ break; case CDSC_RESPONSE_CANCEL: /* ignore it */ break; case CDSC_RESPONSE_IGNORE_ALL: return CDSC_NOTDSC; } } } else if (COMPARE(p, "(atend)")) { if (dsc->scan_section == scan_trailer) dsc_unknown(dsc); /* do nothing */ /* we should mark it as deferred */ } else if (COMPARE(p, "Portrait")) { *porientation = CDSC_PORTRAIT; } else if (COMPARE(p, "Landscape")) { *porientation = CDSC_LANDSCAPE; } else { dsc_unknown(dsc); } return CDSC_OK; } dsc_private int dsc_parse_order(CDSC *dsc) { char *p; if ((dsc->page_order != CDSC_ORDER_UNKNOWN) && (dsc->scan_section == scan_comments)) { int rc = dsc_error(dsc, CDSC_MESSAGE_DUP_COMMENT, dsc->line, dsc->line_length); switch (rc) { case CDSC_RESPONSE_OK: case CDSC_RESPONSE_CANCEL: return CDSC_OK; /* ignore duplicate comments in header */ case CDSC_RESPONSE_IGNORE_ALL: return CDSC_NOTDSC; } } if ((dsc->page_order != CDSC_ORDER_UNKNOWN) && (dsc->scan_section == scan_trailer)) { int rc = dsc_error(dsc, CDSC_MESSAGE_DUP_TRAILER, dsc->line, dsc->line_length); switch (rc) { case CDSC_RESPONSE_OK: case CDSC_RESPONSE_CANCEL: break; /* use duplicate comments in trailer */ case CDSC_RESPONSE_IGNORE_ALL: return CDSC_NOTDSC; } } p = dsc->line + (IS_DSC(dsc->line, "%%+") ? 3 : 13); while (IS_WHITE(*p)) p++; if (COMPARE(p, "atend")) { if (dsc->scan_section == scan_trailer) dsc_unknown(dsc); else { int rc = dsc_error(dsc, CDSC_MESSAGE_ATEND, dsc->line, dsc->line_length); switch (rc) { case CDSC_RESPONSE_OK: /* assume (atend) */ /* we should mark it as deferred */ break; case CDSC_RESPONSE_CANCEL: /* ignore it */ break; case CDSC_RESPONSE_IGNORE_ALL: return CDSC_NOTDSC; } } } else if (COMPARE(p, "(atend)")) { if (dsc->scan_section == scan_trailer) dsc_unknown(dsc); /* do nothing */ /* we should mark it as deferred */ } else if (COMPARE(p, "Ascend")) { dsc->page_order = CDSC_ASCEND; } else if (COMPARE(p, "Descend")) { dsc->page_order = CDSC_DESCEND; } else if (COMPARE(p, "Special")) { dsc->page_order = CDSC_SPECIAL; } else { dsc_unknown(dsc); } return CDSC_OK; } dsc_private int dsc_parse_media(CDSC *dsc, const CDSCMEDIA **page_media) { char media_name[MAXSTR]; int n = IS_DSC(dsc->line, "%%+") ? 3 : 12; /* %%PageMedia: */ unsigned int i; if (dsc_copy_string(media_name, sizeof(media_name)-1, dsc->line+n, dsc->line_length-n, NULL)) { for (i=0; imedia_count; i++) { if (dsc->media[i]->name && (dsc_stricmp(media_name, dsc->media[i]->name) == 0)) { *page_media = dsc->media[i]; return CDSC_OK; } } } dsc_unknown(dsc); return CDSC_OK; } dsc_private int dsc_parse_document_media(CDSC *dsc) { unsigned int i, n; CDSCMEDIA lmedia; GSBOOL blank_line; if (IS_DSC(dsc->line, "%%DocumentMedia:")) n = 16; else if (IS_DSC(dsc->line, "%%+")) n = 3; else return CDSC_ERROR; /* error */ /* check for blank remainder of line */ blank_line = TRUE; for (i=n; iline_length; i++) { if (!IS_WHITE_OR_EOL(dsc->line[i])) { blank_line = FALSE; break; } } if (!blank_line) { char name[MAXSTR]; char colour[MAXSTR]; char type[MAXSTR]; lmedia.name = lmedia.colour = lmedia.type = (char *)NULL; lmedia.width = lmedia.height = lmedia.weight = 0; lmedia.mediabox = (CDSCBBOX *)NULL; lmedia.name = dsc_copy_string(name, sizeof(name), dsc->line+n, dsc->line_length-n, &i); n+=i; if (i) lmedia.width = dsc_get_real(dsc->line+n, dsc->line_length-n, &i); n+=i; if (i) lmedia.height = dsc_get_real(dsc->line+n, dsc->line_length-n, &i); n+=i; if (i) lmedia.weight = dsc_get_real(dsc->line+n, dsc->line_length-n, &i); n+=i; if (i) lmedia.colour = dsc_copy_string(colour, sizeof(colour), dsc->line+n, dsc->line_length-n, &i); n+=i; if (i) lmedia.type = dsc_copy_string(type, sizeof(type), dsc->line+n, dsc->line_length-n, &i); if (i==0) dsc_unknown(dsc); /* we didn't get all fields */ else { if (dsc_add_media(dsc, &lmedia)) return CDSC_ERROR; /* out of memory */ } } return CDSC_OK; } /* viewing orientation is believed to be the first four elements of * a CTM matrix */ dsc_private int dsc_parse_viewing_orientation(CDSC *dsc, CDSCCTM **pctm) { CDSCCTM ctm; unsigned int i, n; if (*pctm != NULL) { dsc_memfree(dsc, *pctm); *pctm = NULL; } n = IS_DSC(dsc->line, "%%+") ? 3 : 21; /* %%ViewingOrientation: */ while (IS_WHITE(dsc->line[n])) n++; /* ctm.xx = */ ctm.xy = ctm.yx = ctm.yy = 0.0; ctm.xx = dsc_get_real(dsc->line+n, dsc->line_length-n, &i); n += i; if (i) ctm.xy = dsc_get_real(dsc->line+n, dsc->line_length-n, &i); n += i; if (i) ctm.yx = dsc_get_real(dsc->line+n, dsc->line_length-n, &i); n += i; if (i) ctm.yy = dsc_get_real(dsc->line+n, dsc->line_length-n, &i); if (i==0) { dsc_unknown(dsc); /* we didn't get all fields */ } else { *pctm = (CDSCCTM *)dsc_memalloc(dsc, sizeof(CDSCCTM)); if (*pctm == NULL) return CDSC_ERROR; /* no memory */ **pctm = ctm; } return CDSC_OK; } /* This is called before dsc_read_line(), since we may * need to skip a binary header which contains a new line * character */ dsc_private int dsc_scan_type(CDSC *dsc) { unsigned char *p; unsigned char *line = (unsigned char *)(dsc->data + dsc->data_index); int length = dsc->data_length - dsc->data_index; /* Types that should be known: * DSC * EPSF * PJL + any of above * ^D + any of above * DOS EPS * PDF * non-DSC */ /* First process any non PostScript headers */ /* At this stage we do not have a complete line */ if (length == 0) return CDSC_NEEDMORE; /* If we have already found a DOS EPS header, */ /* ignore all until the PostScript section */ if (dsc->skip_bytes) { int cnt = min(dsc->skip_bytes, (int)(dsc->data_length - dsc->data_index)); dsc->skip_bytes -= cnt; dsc->data_index += cnt; length -= cnt; line += cnt; if (dsc->skip_bytes != 0) return CDSC_NEEDMORE; } if (dsc->skip_pjl) { /* skip until first PostScript comment */ while (length >= 2) { while (length && !IS_EOL(line[0])) { /* skip until EOL character */ line++; dsc->data_index++; length--; } while ((length >= 2) && IS_EOL(line[0]) && IS_EOL(line[1])) { /* skip until EOL followed by non-EOL */ line++; dsc->data_index++; length--; } if (length < 2) return CDSC_NEEDMORE; if (IS_EOL(line[0]) && line[1]=='%') { line++; dsc->data_index++; length--; dsc->skip_pjl = FALSE; break; } else { line++; dsc->data_index++; length--; } } if (dsc->skip_pjl) return CDSC_NEEDMORE; } if (length == 0) return CDSC_NEEDMORE; if (line[0] == '\004') { line++; dsc->data_index++; length--; dsc->ctrld = TRUE; } if (line[0] == '\033') { /* possibly PJL */ if (length < 9) return CDSC_NEEDMORE; if (COMPARE(line, "\033%-12345X")) { dsc->skip_pjl = TRUE; /* skip until first PostScript comment */ dsc->pjl = TRUE; dsc->data_index += 9; return dsc_scan_type(dsc); } } if ((line[0]==0x0) && (length < 2)) return CDSC_NEEDMORE; /* Could be Mac Binary EPSF */ if ((line[0]==0x0) && (line[1] >= 1) && (line[1] <= 63) && (length < 128)) return CDSC_NEEDMORE; /* Could be Mac Binary EPSF */ if ((line[0]==0x0) && (line[1] == 0x5) && (length < 4)) return CDSC_NEEDMORE; /* Could be Mac AppleSingle/AppleDouble */ if ((line[0]==0xc5) && (length < 4)) return CDSC_NEEDMORE; /* Could be DOS EPS */ if ((line[0]==0xc5) && (line[1]==0xd0) && (line[2]==0xd3) && (line[3]==0xc6) ) { /* id is "EPSF" with bit 7 set */ /* read DOS EPS header, then ignore all bytes until the PS section */ if (length < 30) return CDSC_NEEDMORE; dsc->line = (char *)line; if (dsc_read_doseps(dsc)) return CDSC_ERROR; } else if ((line[0]==0x0) && (line[1]==0x05) && (line[2]==0x16) && ((line[3]==0x0) || (line[3] == 0x07))) { /* Mac AppleSingle or AppleDouble */ GSDWORD version; GSWORD entries; if (length < 26) return CDSC_NEEDMORE; version = dsc_get_bigendian_dword(line+4); entries = dsc_get_bigendian_word(line+24); if ((version == 0x00010000) || (version == 0x00020000)) { if (length < (int)(26 + entries * 12)) return CDSC_NEEDMORE; dsc->line = (char *)line; if (dsc_read_applesingle(dsc)) return CDSC_ERROR; } } else if ((line[0]==0x0) && (line[1] >= 1) && (line[1] <= 63) && (line[74]==0x0) && (line[65]=='E') && (line[66]=='P') && (line[67]=='S') && (line[68]=='F')) { /* Mac Binary EPSF */ dsc->line = (char *)line; if (dsc_read_macbin(dsc)) return CDSC_ERROR; } else { if (length < 2) return CDSC_NEEDMORE; if ((line[0] == '%') && (line[1] == 'P')) { if (length < 5) return CDSC_NEEDMORE; if (COMPARE(line, "%PDF-")) { dsc->pdf = TRUE; dsc->scan_section = scan_comments; return CDSC_OK; } } } /* Finally process PostScript headers */ if (dsc_read_line(dsc) <= 0) return CDSC_NEEDMORE; dsc->dsc_version = dsc_add_line(dsc, dsc->line, dsc->line_length); if (COMPARE(dsc->line, "%!PS-Adobe")) { dsc->dsc = TRUE; dsc->begincomments = DSC_START(dsc); if (dsc->dsc_version == NULL) return CDSC_ERROR; /* no memory */ p = (unsigned char *)dsc->line + 14; while (IS_WHITE(*p)) p++; if (COMPARE(p, "EPSF-")) dsc->epsf = TRUE; dsc->scan_section = scan_comments; return CDSC_PSADOBE; } if (COMPARE(dsc->line, "%!")) { dsc->scan_section = scan_comments; return CDSC_NOTDSC; } dsc->scan_section = scan_comments; return CDSC_NOTDSC; /* unrecognised */ } dsc_private int dsc_scan_comments(CDSC *dsc) { /* Comments section ends at */ /* %%EndComments */ /* another section */ /* line that does not start with %% */ /* Save a few important lines */ char *line = dsc->line; GSBOOL continued = FALSE; dsc->id = CDSC_OK; if (IS_DSC(line, "%%EndComments")) { dsc->id = CDSC_ENDCOMMENTS; dsc->endcomments = DSC_END(dsc); dsc->scan_section = scan_pre_preview; return CDSC_OK; } else if (IS_DSC(line, "%%BeginComments")) { /* ignore because we are in this section */ dsc->id = CDSC_BEGINCOMMENTS; } else if (dsc_is_section(line)) { dsc->endcomments = DSC_START(dsc); dsc->scan_section = scan_pre_preview; return CDSC_PROPAGATE; } else if (line[0] == '%' && IS_WHITE_OR_EOL(line[1])) { dsc->endcomments = DSC_START(dsc); dsc->scan_section = scan_pre_preview; return CDSC_PROPAGATE; } else if (line[0] != '%') { dsc->id = CDSC_OK; dsc->endcomments = DSC_START(dsc); dsc->scan_section = scan_pre_preview; return CDSC_PROPAGATE; } else if (IS_DSC(line, "%%Begin")) { dsc->endcomments = DSC_START(dsc); dsc->scan_section = scan_pre_preview; return CDSC_PROPAGATE; } /* Handle continuation lines. * To simply processing, we assume that contination lines * will only occur if repeat parameters are allowed and that * a complete set of these parameters appears on each line. * This is more restrictive than the DSC specification, but * is valid for the DSC comments understood by this parser * for all documents that we have seen. */ if (IS_DSC(line, "%%+")) { line = dsc->last_line; continued = TRUE; } else dsc_save_line(dsc); if (IS_DSC(line, "%%Pages:")) { dsc->id = CDSC_PAGES; if (dsc_parse_pages(dsc) != 0) return CDSC_ERROR; } else if (IS_DSC(line, "%%Creator:")) { dsc->id = CDSC_CREATOR; dsc->dsc_creator = dsc_add_line(dsc, dsc->line+10, dsc->line_length-10); if (dsc->dsc_creator==NULL) return CDSC_ERROR; } else if (IS_DSC(line, "%%CreationDate:")) { dsc->id = CDSC_CREATIONDATE; dsc->dsc_date = dsc_add_line(dsc, dsc->line+15, dsc->line_length-15); if (dsc->dsc_date==NULL) return CDSC_ERROR; } else if (IS_DSC(line, "%%Title:")) { dsc->id = CDSC_TITLE; dsc->dsc_title = dsc_add_line(dsc, dsc->line+8, dsc->line_length-8); if (dsc->dsc_title==NULL) return CDSC_ERROR; } else if (IS_DSC(line, "%%For:")) { dsc->id = CDSC_FOR; dsc->dsc_for = dsc_add_line(dsc, dsc->line+6, dsc->line_length-6); if (dsc->dsc_for==NULL) return CDSC_ERROR; } else if (IS_DSC(line, "%%LanguageLevel:")) { unsigned int n = continued ? 3 : 16; unsigned int i; int ll; dsc->id = CDSC_LANGUAGELEVEL; ll = dsc_get_int(dsc->line+n, dsc->line_length-n, &i); if (i) { if ( (ll==1) || (ll==2) || (ll==3) ) dsc->language_level = ll; else { dsc_unknown(dsc); } } else dsc_unknown(dsc); } else if (IS_DSC(line, "%%BoundingBox:")) { dsc->id = CDSC_BOUNDINGBOX; if (dsc_parse_bounding_box(dsc, &(dsc->bbox), continued ? 3 : 14)) return CDSC_ERROR; } else if (IS_DSC(line, "%%HiResBoundingBox:")) { dsc->id = CDSC_HIRESBOUNDINGBOX; if (dsc_parse_float_bounding_box(dsc, &(dsc->hires_bbox), continued ? 3 : 19)) return CDSC_ERROR; } else if (IS_DSC(line, "%%CropBox:")) { dsc->id = CDSC_CROPBOX; if (dsc_parse_float_bounding_box(dsc, &(dsc->crop_box), continued ? 3 : 10)) return CDSC_ERROR; } else if (IS_DSC(line, "%%Orientation:")) { dsc->id = CDSC_ORIENTATION; if (dsc_parse_orientation(dsc, &(dsc->page_orientation), continued ? 3 : 14)) return CDSC_ERROR; } else if (IS_DSC(line, "%%PageOrder:")) { dsc->id = CDSC_PAGEORDER; if (dsc_parse_order(dsc)) return CDSC_ERROR; } else if (IS_DSC(line, "%%DocumentMedia:")) { dsc->id = CDSC_DOCUMENTMEDIA; if (dsc_parse_document_media(dsc)) return CDSC_ERROR; } else if (IS_DSC(line, "%%DocumentPaperSizes:")) { /* DSC 2.1 */ unsigned int n = continued ? 3 : 21; unsigned int count = 0; unsigned int i = 1; char name[MAXSTR]; char *p; dsc->id = CDSC_DOCUMENTPAPERSIZES; while (i && (dsc->line[n]!='\r') && (dsc->line[n]!='\n')) { p = dsc_copy_string(name, sizeof(name)-1, dsc->line+n, dsc->line_length-n, &i); if (i && p) { const CDSCMEDIA *m = dsc_known_media; if (count >= dsc->media_count) { /* set some default values */ CDSCMEDIA lmedia; lmedia.name = p; lmedia.width = 595.0; lmedia.height = 842.0; lmedia.weight = 80.0; lmedia.colour = NULL; lmedia.type = NULL; lmedia.mediabox = NULL; if (dsc_add_media(dsc, &lmedia)) return CDSC_ERROR; } else dsc->media[count]->name = dsc_alloc_string(dsc, p, (int)strlen(p)); /* find in list of known media */ while (m && m->name) { if (dsc_stricmp(p, m->name)==0) { dsc->media[count]->width = m->width; dsc->media[count]->height = m->height; break; } m++; } } n+=i; count++; } } else if (IS_DSC(line, "%%DocumentPaperForms:")) { /* DSC 2.1 */ unsigned int n = continued ? 3 : 21; unsigned int count = 0; unsigned int i = 1; char type[MAXSTR]; char *p; dsc->id = CDSC_DOCUMENTPAPERFORMS; while (i && (dsc->line[n]!='\r') && (dsc->line[n]!='\n')) { p = dsc_copy_string(type, sizeof(type)-1, dsc->line+n, dsc->line_length-n, &i); if (i && p) { if (count >= dsc->media_count) { /* set some default values */ CDSCMEDIA lmedia; lmedia.name = NULL; lmedia.width = 595.0; lmedia.height = 842.0; lmedia.weight = 80.0; lmedia.colour = NULL; lmedia.type = p; lmedia.mediabox = NULL; if (dsc_add_media(dsc, &lmedia)) return CDSC_ERROR; } else dsc->media[count]->type = dsc_alloc_string(dsc, p, (int)strlen(p)); } n+=i; count++; } } else if (IS_DSC(line, "%%DocumentPaperColors:")) { /* DSC 2.1 */ unsigned int n = continued ? 3 : 22; unsigned int count = 0; unsigned int i = 1; char colour[MAXSTR]; char *p; dsc->id = CDSC_DOCUMENTPAPERCOLORS; while (i && (dsc->line[n]!='\r') && (dsc->line[n]!='\n')) { p = dsc_copy_string(colour, sizeof(colour)-1, dsc->line+n, dsc->line_length-n, &i); if (i && p) { if (count >= dsc->media_count) { /* set some default values */ CDSCMEDIA lmedia; lmedia.name = NULL; lmedia.width = 595.0; lmedia.height = 842.0; lmedia.weight = 80.0; lmedia.colour = p; lmedia.type = NULL; lmedia.mediabox = NULL; if (dsc_add_media(dsc, &lmedia)) return CDSC_ERROR; } else dsc->media[count]->colour = dsc_alloc_string(dsc, p, (int)strlen(p)); } n+=i; count++; } } else if (IS_DSC(line, "%%DocumentPaperWeights:")) { /* DSC 2.1 */ unsigned int n = continued ? 3 : 23; unsigned int count = 0; unsigned int i = 1; float w; dsc->id = CDSC_DOCUMENTPAPERWEIGHTS; while (i && (dsc->line[n]!='\r') && (dsc->line[n]!='\n')) { w = dsc_get_real(dsc->line+n, dsc->line_length-n, &i); if (i) { if (count >= dsc->media_count) { /* set some default values */ CDSCMEDIA lmedia; lmedia.name = NULL; lmedia.width = 595.0; lmedia.height = 842.0; lmedia.weight = w; lmedia.colour = NULL; lmedia.type = NULL; lmedia.mediabox = NULL; if (dsc_add_media(dsc, &lmedia)) return CDSC_ERROR; } else dsc->media[count]->weight = w; } n+=i; count++; } } else if (IS_DSC(line, "%%DocumentData:")) { unsigned int n = continued ? 3 : 15; char *p = dsc->line + n; while (IS_WHITE(*p)) p++; dsc->id = CDSC_DOCUMENTDATA; if (COMPARE(p, "Clean7Bit")) dsc->document_data = CDSC_CLEAN7BIT; else if (COMPARE(p, "Clean8Bit")) dsc->document_data = CDSC_CLEAN8BIT; else if (COMPARE(p, "Binary")) dsc->document_data = CDSC_BINARY; else dsc_unknown(dsc); } else if (IS_DSC(line, "%%Requirements:")) { dsc->id = CDSC_REQUIREMENTS; /* ignore */ } else if (IS_DSC(line, "%%DocumentNeededFonts:")) { dsc->id = CDSC_DOCUMENTNEEDEDFONTS; /* ignore */ } else if (IS_DSC(line, "%%DocumentSuppliedFonts:")) { dsc->id = CDSC_DOCUMENTSUPPLIEDFONTS; /* ignore */ } else if (IS_DSC(line, "%%PlateFile:")) { dsc->id = CDSC_PLATEFILE; if (dsc_parse_platefile(dsc) != CDSC_OK) dsc->id = CDSC_UNKNOWNDSC; } else if (IS_DSC(line, "%%CyanPlate:") || IS_DSC(line, "%%MagentaPlate:") || IS_DSC(line, "%%YellowPlate:") || IS_DSC(line, "%%BlackPlate:")) { dsc->id = CDSC_PLATEFILE; if (dsc_parse_dcs1plate(dsc) != CDSC_OK) dsc->id = CDSC_UNKNOWNDSC; } else if (IS_DSC(line, "%%DocumentProcessColors:")) { dsc->id = CDSC_DOCUMENTPROCESSCOLORS; if (dsc_parse_process_colours(dsc) != CDSC_OK) dsc->id = CDSC_UNKNOWNDSC; } else if (IS_DSC(line, "%%DocumentCustomColors:")) { dsc->id = CDSC_DOCUMENTCUSTOMCOLORS; if (dsc_parse_custom_colours(dsc) != CDSC_OK) dsc->id = CDSC_UNKNOWNDSC; } else if (IS_DSC(line, "%%CMYKCustomColor:")) { dsc->id = CDSC_CMYKCUSTOMCOLOR; if (dsc_parse_cmyk_custom_colour(dsc) != CDSC_OK) dsc->id = CDSC_UNKNOWNDSC; } else if (IS_DSC(line, "%%RGBCustomColor:")) { dsc->id = CDSC_RGBCUSTOMCOLOR; if (dsc_parse_rgb_custom_colour(dsc) != CDSC_OK) dsc->id = CDSC_UNKNOWNDSC; } else if (dsc->line[0] == '%' && IS_WHITE_OR_EOL(dsc->line[1])) { dsc->id = CDSC_OK; /* ignore */ } else { dsc->id = CDSC_UNKNOWNDSC; dsc_unknown(dsc); } dsc->endcomments = DSC_END(dsc); return CDSC_OK; } dsc_private int dsc_scan_preview(CDSC *dsc) { /* Preview section ends at */ /* %%EndPreview */ /* another section */ /* Preview section must start with %%BeginPreview */ char *line = dsc->line; dsc->id = CDSC_OK; if (dsc->scan_section == scan_pre_preview) { if (IS_BLANK(line)) return CDSC_OK; /* ignore blank lines before preview */ else if (IS_DSC(line, "%%BeginPreview")) { dsc->id = CDSC_BEGINPREVIEW; dsc->beginpreview = DSC_START(dsc); dsc->endpreview = DSC_END(dsc); dsc->scan_section = scan_preview; /* Don't mark the preview as EPSI if a DOS EPS header is present */ if (dsc->preview == CDSC_NOPREVIEW) dsc->preview = CDSC_EPSI; return CDSC_OK; } else { dsc->scan_section = scan_pre_defaults; return CDSC_PROPAGATE; } } if (IS_DSC(line, "%%BeginPreview")) { /* ignore because we are in this section */ } else if (dsc_is_section(line)) { dsc->endpreview = DSC_START(dsc); dsc->scan_section = scan_pre_defaults; return CDSC_PROPAGATE; } else if (IS_DSC(line, "%%EndPreview")) { dsc->id = CDSC_ENDPREVIEW; dsc->endpreview = DSC_END(dsc); dsc->scan_section = scan_pre_defaults; return CDSC_OK; } else if (line[0] == '%' && line[1] != '%') { /* Ordinary comments are OK */ } else { dsc->id = CDSC_UNKNOWNDSC; /* DSC comments should not occur in preview */ dsc_unknown(dsc); } dsc->endpreview = DSC_END(dsc); return CDSC_OK; } dsc_private int dsc_scan_defaults(CDSC *dsc) { /* Defaults section ends at */ /* %%EndDefaults */ /* another section */ /* Defaults section must start with %%BeginDefaults */ char *line = dsc->line; dsc->id = CDSC_OK; if (dsc->scan_section == scan_pre_defaults) { if (IS_BLANK(line)) return CDSC_OK; /* ignore blank lines before defaults */ else if (IS_DSC(line, "%%BeginDefaults")) { dsc->id = CDSC_BEGINDEFAULTS; dsc->begindefaults = DSC_START(dsc); dsc->enddefaults = DSC_END(dsc); dsc->scan_section = scan_defaults; return CDSC_OK; } else { dsc->scan_section = scan_pre_prolog; return CDSC_PROPAGATE; } } if (NOT_DSC_LINE(line)) { /* ignore */ } else if (IS_DSC(line, "%%BeginPreview")) { /* ignore because we have already processed this section */ } else if (IS_DSC(line, "%%BeginDefaults")) { /* ignore because we are in this section */ } else if (dsc_is_section(line)) { dsc->enddefaults = DSC_START(dsc); dsc->scan_section = scan_pre_prolog; return CDSC_PROPAGATE; } else if (IS_DSC(line, "%%EndDefaults")) { dsc->id = CDSC_ENDDEFAULTS; dsc->enddefaults = DSC_END(dsc); dsc->scan_section = scan_pre_prolog; return CDSC_OK; } else if (IS_DSC(line, "%%PageMedia:")) { dsc->id = CDSC_PAGEMEDIA; dsc_parse_media(dsc, &dsc->page_media); } else if (IS_DSC(line, "%%PageOrientation:")) { dsc->id = CDSC_PAGEORIENTATION; /* This can override %%Orientation: */ if (dsc_parse_orientation(dsc, &(dsc->page_orientation), 18)) return CDSC_ERROR; } else if (IS_DSC(line, "%%PageBoundingBox:")) { dsc->id = CDSC_PAGEBOUNDINGBOX; if (dsc_parse_bounding_box(dsc, &(dsc->page_bbox), 18)) return CDSC_ERROR; } else if (IS_DSC(line, "%%ViewingOrientation:")) { dsc->id = CDSC_VIEWINGORIENTATION; if (dsc_parse_viewing_orientation(dsc, &dsc->viewing_orientation)) return CDSC_ERROR; } else if (IS_DSC(line, "%%PageCropBox:")) { dsc->id = CDSC_PAGECROPBOX; if (dsc_parse_float_bounding_box(dsc, &dsc->crop_box, 14)) return CDSC_ERROR; } else { dsc->id = CDSC_UNKNOWNDSC; /* All other DSC comments are unknown, but not an error */ dsc_unknown(dsc); } dsc->enddefaults = DSC_END(dsc); return CDSC_OK; } /* CDSC_RESPONSE_OK and CDSC_RESPONSE_CANCEL mean ignore the * mismatch (default) */ dsc_private int dsc_check_match_prompt(CDSC *dsc, const char *str, int count) { if (count != 0) { char buf[MAXSTR+MAXSTR]; if (dsc->line_length < (unsigned int)(sizeof(buf)/2-1)) { strncpy(buf, dsc->line, dsc->line_length); buf[dsc->line_length] = '\0'; } sprintf(buf+strlen(buf), "\n%%%%Begin%.40s: / %%%%End%.40s\n", str, str); return dsc_error(dsc, CDSC_MESSAGE_BEGIN_END, buf, (int)strlen(buf)); } return CDSC_RESPONSE_CANCEL; } dsc_private int dsc_check_match_type(CDSC *dsc, const char *str, int count) { if (dsc_check_match_prompt(dsc, str, count) == CDSC_RESPONSE_IGNORE_ALL) return CDSC_NOTDSC; return CDSC_OK; } /* complain if Begin/End blocks didn't match */ /* return non-zero if we should ignore all DSC */ dsc_private int dsc_check_match(CDSC *dsc) { int rc = 0; const char *font = "Font"; const char *feature = "Feature"; const char *resource = "Resource"; const char *procset = "ProcSet"; if (!rc) rc = dsc_check_match_type(dsc, font, dsc->begin_font_count); if (!rc) rc = dsc_check_match_type(dsc, feature, dsc->begin_feature_count); if (!rc) rc = dsc_check_match_type(dsc, resource, dsc->begin_resource_count); if (!rc) rc = dsc_check_match_type(dsc, procset, dsc->begin_procset_count); dsc->begin_font_count = 0; dsc->begin_feature_count = 0; dsc->begin_resource_count = 0; dsc->begin_procset_count = 0; return rc; } dsc_private int dsc_scan_prolog(CDSC *dsc) { /* Prolog section ends at */ /* %%EndProlog */ /* another section */ /* Prolog section may start with %%BeginProlog or non-dsc line */ char *line = dsc->line; dsc->id = CDSC_OK; if (dsc->scan_section == scan_pre_prolog) { if (dsc_is_section(line) && (!IS_DSC(line, "%%BeginProlog"))) { dsc->scan_section = scan_pre_setup; return CDSC_PROPAGATE; } dsc->id = CDSC_BEGINPROLOG; dsc->beginprolog = DSC_START(dsc); dsc->endprolog = DSC_END(dsc); dsc->scan_section = scan_prolog; if (IS_DSC(line, "%%BeginProlog")) return CDSC_OK; } if (NOT_DSC_LINE(line)) { /* ignore */ } else if (IS_DSC(line, "%%BeginPreview")) { /* ignore because we have already processed this section */ } else if (IS_DSC(line, "%%BeginDefaults")) { /* ignore because we have already processed this section */ } else if (IS_DSC(line, "%%BeginProlog")) { /* ignore because we are in this section */ } else if (dsc_is_section(line)) { dsc->endprolog = DSC_START(dsc); dsc->scan_section = scan_pre_setup; if (dsc_check_match(dsc)) return CDSC_NOTDSC; return CDSC_PROPAGATE; } else if (IS_DSC(line, "%%EndProlog")) { dsc->id = CDSC_ENDPROLOG; dsc->endprolog = DSC_END(dsc); dsc->scan_section = scan_pre_setup; if (dsc_check_match(dsc)) return CDSC_NOTDSC; return CDSC_OK; } else if (IS_DSC(line, "%%BeginFont:")) { dsc->id = CDSC_BEGINFONT; /* ignore Begin/EndFont, apart form making sure */ /* that they are matched. */ dsc->begin_font_count++; } else if (IS_DSC(line, "%%EndFont")) { dsc->id = CDSC_ENDFONT; dsc->begin_font_count--; } else if (IS_DSC(line, "%%BeginFeature:")) { dsc->id = CDSC_BEGINFEATURE; /* ignore Begin/EndFeature, apart form making sure */ /* that they are matched. */ dsc->begin_feature_count++; } else if (IS_DSC(line, "%%EndFeature")) { dsc->id = CDSC_ENDFEATURE; dsc->begin_feature_count--; } else if (IS_DSC(line, "%%BeginResource:")) { dsc->id = CDSC_BEGINRESOURCE; /* ignore Begin/EndResource, apart form making sure */ /* that they are matched. */ dsc->begin_resource_count++; } else if (IS_DSC(line, "%%EndResource")) { dsc->id = CDSC_ENDRESOURCE; dsc->begin_resource_count--; } else if (IS_DSC(line, "%%BeginProcSet:")) { dsc->id = CDSC_BEGINPROCSET; /* ignore Begin/EndProcSet, apart form making sure */ /* that they are matched. */ dsc->begin_procset_count++; } else if (IS_DSC(line, "%%EndProcSet")) { dsc->id = CDSC_ENDPROCSET; dsc->begin_procset_count--; } else { /* All other DSC comments are unknown, but not an error */ dsc->id = CDSC_UNKNOWNDSC; dsc_unknown(dsc); } dsc->endprolog = DSC_END(dsc); return CDSC_OK; } dsc_private int dsc_scan_setup(CDSC *dsc) { /* Setup section ends at */ /* %%EndSetup */ /* another section */ /* Setup section must start with %%BeginSetup */ char *line = dsc->line; dsc->id = CDSC_OK; if (dsc->scan_section == scan_pre_setup) { if (IS_BLANK(line)) return CDSC_OK; /* ignore blank lines before setup */ else if (IS_DSC(line, "%%BeginSetup")) { dsc->id = CDSC_BEGINSETUP; dsc->beginsetup = DSC_START(dsc); dsc->endsetup = DSC_END(dsc); dsc->scan_section = scan_setup; return CDSC_OK; } else { dsc->scan_section = scan_pre_pages; return CDSC_PROPAGATE; } } if (NOT_DSC_LINE(line)) { /* ignore */ } else if (IS_DSC(line, "%%BeginPreview")) { /* ignore because we have already processed this section */ } else if (IS_DSC(line, "%%BeginDefaults")) { /* ignore because we have already processed this section */ } else if (IS_DSC(line, "%%BeginProlog")) { /* ignore because we have already processed this section */ } else if (IS_DSC(line, "%%BeginSetup")) { /* ignore because we are in this section */ } else if (dsc_is_section(line)) { dsc->endsetup = DSC_START(dsc); dsc->scan_section = scan_pre_pages; if (dsc_check_match(dsc)) return CDSC_NOTDSC; return CDSC_PROPAGATE; } else if (IS_DSC(line, "%%EndSetup")) { dsc->id = CDSC_ENDSETUP; dsc->endsetup = DSC_END(dsc); dsc->scan_section = scan_pre_pages; if (dsc_check_match(dsc)) return CDSC_NOTDSC; return CDSC_OK; } else if (IS_DSC(line, "%%BeginFeature:")) { dsc->id = CDSC_BEGINFEATURE; /* ignore Begin/EndFeature, apart form making sure */ /* that they are matched. */ dsc->begin_feature_count++; /* Look for "*PageSize name" where name is known */ if (dsc_parse_feature(dsc)) return CDSC_ERROR; } else if (IS_DSC(line, "%%EndFeature")) { dsc->id = CDSC_ENDFEATURE; dsc->begin_feature_count--; } else if (IS_DSC(line, "%%Feature:")) { dsc->id = CDSC_FEATURE; /* ignore */ } else if (IS_DSC(line, "%%BeginResource:")) { dsc->id = CDSC_BEGINRESOURCE; /* ignore Begin/EndResource, apart form making sure */ /* that they are matched. */ dsc->begin_resource_count++; } else if (IS_DSC(line, "%%EndResource")) { dsc->id = CDSC_ENDRESOURCE; dsc->begin_resource_count--; } else if (IS_DSC(line, "%%PaperColor:")) { dsc->id = CDSC_PAPERCOLOR; /* ignore */ } else if (IS_DSC(line, "%%PaperForm:")) { dsc->id = CDSC_PAPERFORM; /* ignore */ } else if (IS_DSC(line, "%%PaperWeight:")) { dsc->id = CDSC_PAPERWEIGHT; /* ignore */ } else if (IS_DSC(line, "%%PaperSize:")) { /* DSC 2.1 */ GSBOOL found_media = FALSE; int i; int n = 12; char buf[MAXSTR]; buf[0] = '\0'; dsc->id = CDSC_PAPERSIZE; dsc_copy_string(buf, sizeof(buf)-1, dsc->line+n, dsc->line_length-n, NULL); for (i=0; i<(int)dsc->media_count; i++) { if (dsc->media[i] && dsc->media[i]->name && (dsc_stricmp(buf, dsc->media[i]->name)==0)) { dsc->page_media = dsc->media[i]; found_media = TRUE; break; } } if (!found_media) { /* It didn't match %%DocumentPaperSizes: */ /* Try our known media */ const CDSCMEDIA *m = dsc_known_media; while (m->name) { if (dsc_stricmp(buf, m->name)==0) { dsc->page_media = m; break; } m++; } if (m->name == NULL) dsc_unknown(dsc); } } else { /* All other DSC comments are unknown, but not an error */ dsc->id = CDSC_UNKNOWNDSC; dsc_unknown(dsc); } dsc->endsetup = DSC_END(dsc); return CDSC_OK; } dsc_private int dsc_scan_page(CDSC *dsc) { /* Page section ends at */ /* %%Page */ /* %%Trailer */ /* %%EOF */ char *line = dsc->line; dsc->id = CDSC_OK; if (dsc->scan_section == scan_pre_pages) { if (IS_DSC(line, "%%Page:")) { dsc->scan_section = scan_pages; /* fall through */ } else { /* %%Page: didn't follow %%EndSetup * Keep reading until reach %%Page or %%Trailer * and add it to previous section. */ DSC_OFFSET *last; if (dsc->endsetup != 0) last = &dsc->endsetup; else if (dsc->endprolog != 0) last = &dsc->endprolog; else if (dsc->enddefaults != 0) last = &dsc->enddefaults; else if (dsc->endpreview != 0) last = &dsc->endpreview; else if (dsc->endcomments != 0) last = &dsc->endcomments; else last = &dsc->begincomments; *last = DSC_START(dsc); if (IS_DSC(line, "%%Trailer") || IS_DSC(line, "%%EOF")) { dsc->scan_section = scan_pre_trailer; return CDSC_PROPAGATE; } *last = DSC_END(dsc); return CDSC_OK; } } if (NOT_DSC_LINE(line)) { /* ignore */ } else if (IS_DSC(line, "%%Page:")) { int code; dsc->id = CDSC_PAGE; if (dsc->page_count) { dsc->page[dsc->page_count-1].end = DSC_START(dsc); if (dsc_check_match(dsc)) return CDSC_NOTDSC; } if ( (code = dsc_parse_page(dsc)) != CDSC_OK) return code; if (dsc->page_count == 0) dsc->scan_section = scan_pre_pages; } else if (IS_DSC(line, "%%BeginPreview")) { /* ignore because we have already processed this section */ } else if (IS_DSC(line, "%%BeginDefaults")) { /* ignore because we have already processed this section */ } else if (IS_DSC(line, "%%BeginProlog")) { /* ignore because we have already processed this section */ } else if (IS_DSC(line, "%%BeginSetup")) { /* ignore because we have already processed this section */ } else if (dsc_is_section(line)) { if (IS_DSC(line, "%%Trailer")) { if (dsc->page_count) dsc->page[dsc->page_count-1].end = DSC_START(dsc); if (dsc->file_length) { if ((!dsc->doseps_end && ((DSC_END(dsc) + 32768) < dsc->file_length)) || ((dsc->doseps_end) && ((DSC_END(dsc) + 32768) < dsc->doseps_end))) { int rc = dsc_error(dsc, CDSC_MESSAGE_EARLY_TRAILER, dsc->line, dsc->line_length); switch (rc) { case CDSC_RESPONSE_OK: /* ignore early trailer */ break; case CDSC_RESPONSE_CANCEL: /* this is the trailer */ dsc->scan_section = scan_pre_trailer; if (dsc_check_match(dsc)) return CDSC_NOTDSC; return CDSC_PROPAGATE; case CDSC_RESPONSE_IGNORE_ALL: return CDSC_NOTDSC; } } else { dsc->scan_section = scan_pre_trailer; if (dsc_check_match(dsc)) return CDSC_NOTDSC; return CDSC_PROPAGATE; } } else { dsc->scan_section = scan_pre_trailer; if (dsc_check_match(dsc)) return CDSC_NOTDSC; return CDSC_PROPAGATE; } } else if (IS_DSC(line, "%%EOF")) { if (dsc->page_count) dsc->page[dsc->page_count-1].end = DSC_START(dsc); if (dsc->file_length) { if ((!dsc->doseps_end && ((DSC_END(dsc) + 100) < dsc->file_length)) || ((dsc->doseps_end) && ((DSC_END(dsc) + 100) < dsc->doseps_end))) { int rc = dsc_error(dsc, CDSC_MESSAGE_EARLY_EOF, dsc->line, dsc->line_length); switch (rc) { case CDSC_RESPONSE_OK: /* %%EOF is wrong, ignore it */ break; case CDSC_RESPONSE_CANCEL: /* %%EOF is correct */ dsc->scan_section = scan_eof; dsc->eof = TRUE; if (dsc_check_match(dsc)) return CDSC_NOTDSC; return CDSC_PROPAGATE; case CDSC_RESPONSE_IGNORE_ALL: return CDSC_NOTDSC; } } } else { /* ignore it */ if (dsc_check_match(dsc)) return CDSC_NOTDSC; return CDSC_OK; } } else { /* Section comment, probably from a badly */ /* encapsulated EPS file. */ int rc = dsc_error(dsc, CDSC_MESSAGE_BAD_SECTION, dsc->line, dsc->line_length); if (rc == CDSC_RESPONSE_IGNORE_ALL) return CDSC_NOTDSC; } } else if (IS_DSC(line, "%%PageTrailer")) { dsc->id = CDSC_PAGETRAILER; /* ignore */ } else if (IS_DSC(line, "%%BeginPageSetup")) { dsc->id = CDSC_BEGINPAGESETUP; /* ignore */ } else if (IS_DSC(line, "%%EndPageSetup")) { dsc->id = CDSC_ENDPAGESETUP; /* ignore */ } else if (IS_DSC(line, "%%PageMedia:")) { dsc->id = CDSC_PAGEMEDIA; if (dsc->page_count) dsc_parse_media(dsc, &(dsc->page[dsc->page_count-1].media)); } else if (IS_DSC(line, "%%PaperColor:")) { dsc->id = CDSC_PAPERCOLOR; /* ignore */ } else if (IS_DSC(line, "%%PaperForm:")) { dsc->id = CDSC_PAPERFORM; /* ignore */ } else if (IS_DSC(line, "%%PaperWeight:")) { dsc->id = CDSC_PAPERWEIGHT; /* ignore */ } else if (IS_DSC(line, "%%PaperSize:")) { /* DSC 2.1 */ GSBOOL found_media = FALSE; int i; int n = 12; char buf[MAXSTR]; buf[0] = '\0'; dsc_copy_string(buf, sizeof(buf)-1, dsc->line+n, dsc->line_length-n, NULL); for (i=0; i<(int)dsc->media_count; i++) { if (dsc->media[i] && dsc->media[i]->name && (dsc_stricmp(buf, dsc->media[i]->name)==0)) { if (dsc->page_count) dsc->page[dsc->page_count-1].media = dsc->media[i]; found_media = TRUE; break; } } if (!found_media) { /* It didn't match %%DocumentPaperSizes: */ /* Try our known media */ const CDSCMEDIA *m = dsc_known_media; while (m->name) { if (dsc_stricmp(buf, m->name)==0) { if (dsc->page_count) dsc->page[dsc->page_count-1].media = m; break; } m++; } if (m->name == NULL) dsc_unknown(dsc); } } else if (IS_DSC(line, "%%PageOrientation:")) { if (dsc->page_count) { dsc->id = CDSC_PAGEORIENTATION; if (dsc_parse_orientation(dsc, &(dsc->page[dsc->page_count-1].orientation) ,18)) return CDSC_NOTDSC; } } else if (IS_DSC(line, "%%PageBoundingBox:")) { if (dsc->page_count) { dsc->id = CDSC_PAGEBOUNDINGBOX; if (dsc_parse_bounding_box(dsc, &dsc->page[dsc->page_count-1].bbox, 18)) return CDSC_NOTDSC; } } else if (IS_DSC(line, "%%ViewingOrientation:")) { if (dsc->page_count) { dsc->id = CDSC_VIEWINGORIENTATION; if (dsc_parse_viewing_orientation(dsc, &dsc->page[dsc->page_count-1].viewing_orientation)) return CDSC_ERROR; } } else if (IS_DSC(line, "%%PageCropBox:")) { if (dsc->page_count) { dsc->id = CDSC_PAGECROPBOX; if (dsc_parse_float_bounding_box(dsc, &(dsc->page[dsc->page_count-1].crop_box), 14)) return CDSC_ERROR; } } else if (IS_DSC(line, "%%BeginFont:")) { dsc->id = CDSC_BEGINFONT; /* ignore Begin/EndFont, apart form making sure */ /* that they are matched. */ dsc->begin_font_count++; } else if (IS_DSC(line, "%%EndFont")) { dsc->id = CDSC_BEGINFONT; dsc->begin_font_count--; } else if (IS_DSC(line, "%%BeginFeature:")) { dsc->id = CDSC_BEGINFEATURE; /* ignore Begin/EndFeature, apart form making sure */ /* that they are matched. */ dsc->begin_feature_count++; } else if (IS_DSC(line, "%%EndFeature")) { dsc->id = CDSC_ENDFEATURE; dsc->begin_feature_count--; } else if (IS_DSC(line, "%%BeginResource:")) { dsc->id = CDSC_BEGINRESOURCE; /* ignore Begin/EndResource, apart form making sure */ /* that they are matched. */ dsc->begin_resource_count++; } else if (IS_DSC(line, "%%EndResource")) { dsc->id = CDSC_ENDRESOURCE; dsc->begin_resource_count--; } else if (IS_DSC(line, "%%BeginProcSet:")) { dsc->id = CDSC_BEGINPROCSET; /* ignore Begin/EndProcSet, apart form making sure */ /* that they are matched. */ dsc->begin_procset_count++; } else if (IS_DSC(line, "%%EndProcSet")) { dsc->id = CDSC_ENDPROCSET; dsc->begin_procset_count--; } else if (IS_DSC(line, "%%IncludeFont:")) { dsc->id = CDSC_INCLUDEFONT; /* ignore */ } else { /* All other DSC comments are unknown, but not an error */ dsc->id = CDSC_UNKNOWNDSC; dsc_unknown(dsc); } if (dsc->page_count) dsc->page[dsc->page_count-1].end = DSC_END(dsc); return CDSC_OK; } /* Valid Trailer comments are * %%Trailer * %%EOF * or the following deferred with (atend) * %%BoundingBox: * %%DocumentCustomColors: * %%DocumentFiles: * %%DocumentFonts: * %%DocumentNeededFiles: * %%DocumentNeededFonts: * %%DocumentNeededProcSets: * %%DocumentNeededResources: * %%DocumentProcSets: * %%DocumentProcessColors: * %%DocumentSuppliedFiles: * %%DocumentSuppliedFonts: * %%DocumentSuppliedProcSets: * %%DocumentSuppliedResources: * %%Orientation: * %%Pages: * %%PageOrder: * * Our supported subset is * %%Trailer * %%EOF * %%BoundingBox: * %%CropBox: * %%HiResBoundingBox: * %%DocumentCustomColors: * %%DocumentProcessColors: * %%Orientation: * %%Pages: * %%PageOrder: * In addition to these, we support * %%DocumentMedia: * * A %%PageTrailer can have the following: * %%PageBoundingBox: * %%PageCustomColors: * %%PageFiles: * %%PageFonts: * %%PageOrientation: * %%PageProcessColors: * %%PageResources: */ dsc_private int dsc_scan_trailer(CDSC *dsc) { /* Trailer section start at */ /* %%Trailer */ /* and ends at */ /* %%EOF */ char *line = dsc->line; GSBOOL continued = FALSE; dsc->id = CDSC_OK; if (dsc->scan_section == scan_pre_trailer) { if (IS_DSC(line, "%%Trailer")) { dsc->id = CDSC_TRAILER; dsc->begintrailer = DSC_START(dsc); dsc->endtrailer = DSC_END(dsc); dsc->scan_section = scan_trailer; return CDSC_OK; } else if (IS_DSC(line, "%%EOF")) { dsc->id = CDSC_EOF; dsc->begintrailer = DSC_START(dsc); dsc->endtrailer = DSC_END(dsc); dsc->scan_section = scan_trailer; /* Continue, in case we found %%EOF in an embedded document */ return CDSC_OK; } else { /* %%Page: didn't follow %%EndSetup * Keep reading until reach %%Page or %%Trailer * and add it to setup section */ /* append to previous section */ if (dsc->beginsetup) dsc->endsetup = DSC_END(dsc); else if (dsc->beginprolog) dsc->endprolog = DSC_END(dsc); else { /* horribly confused */ } return CDSC_OK; } } /* Handle continuation lines. * See comment above about our restrictive processing of * continuation lines */ if (IS_DSC(line, "%%+")) { line = dsc->last_line; continued = TRUE; } else dsc_save_line(dsc); if (NOT_DSC_LINE(line)) { /* ignore */ } else if (IS_DSC(dsc->line, "%%EOF")) { /* Keep scanning, in case we have a false trailer */ dsc->id = CDSC_EOF; } else if (IS_DSC(dsc->line, "%%Trailer")) { /* Cope with no pages with code after setup and before trailer. */ /* Last trailer is the correct one. */ dsc->id = CDSC_TRAILER; dsc->begintrailer = DSC_START(dsc); } else if (IS_DSC(line, "%%Pages:")) { dsc->id = CDSC_PAGES; if (dsc_parse_pages(dsc) != 0) return CDSC_ERROR; } else if (IS_DSC(line, "%%BoundingBox:")) { dsc->id = CDSC_BOUNDINGBOX; if (dsc_parse_bounding_box(dsc, &(dsc->bbox), continued ? 3 : 14)) return CDSC_ERROR; } else if (IS_DSC(line, "%%HiResBoundingBox:")) { dsc->id = CDSC_HIRESBOUNDINGBOX; if (dsc_parse_float_bounding_box(dsc, &(dsc->hires_bbox), continued ? 3 : 19)) return CDSC_ERROR; } else if (IS_DSC(line, "%%CropBox:")) { dsc->id = CDSC_CROPBOX; if (dsc_parse_float_bounding_box(dsc, &(dsc->crop_box), continued ? 3 : 10)) return CDSC_ERROR; } else if (IS_DSC(line, "%%Orientation:")) { dsc->id = CDSC_ORIENTATION; if (dsc_parse_orientation(dsc, &(dsc->page_orientation), continued ? 3 : 14)) return CDSC_ERROR; } else if (IS_DSC(line, "%%PageOrder:")) { dsc->id = CDSC_PAGEORDER; if (dsc_parse_order(dsc)) return CDSC_ERROR; } else if (IS_DSC(line, "%%DocumentMedia:")) { dsc->id = CDSC_DOCUMENTMEDIA; if (dsc_parse_document_media(dsc)) return CDSC_ERROR; } else if (IS_DSC(dsc->line, "%%Page:")) { /* This should not occur in the trailer, but we might see * this if a document has been incorrectly embedded. */ int rc = dsc_error(dsc, CDSC_MESSAGE_PAGE_IN_TRAILER, dsc->line, dsc->line_length); switch (rc) { case CDSC_RESPONSE_OK: /* Assume that we are really in the previous */ /* page, not the trailer */ dsc->scan_section = scan_pre_pages; if (dsc->page_count) dsc->page[dsc->page_count-1].end = DSC_START(dsc); return CDSC_PROPAGATE; /* try again */ case CDSC_RESPONSE_CANCEL: /* ignore pages in trailer */ break; case CDSC_RESPONSE_IGNORE_ALL: return CDSC_NOTDSC; } } else if (IS_DSC(line, "%%DocumentNeededFonts:")) { dsc->id = CDSC_DOCUMENTNEEDEDFONTS; /* ignore */ } else if (IS_DSC(line, "%%DocumentSuppliedFonts:")) { dsc->id = CDSC_DOCUMENTSUPPLIEDFONTS; /* ignore */ } else if (IS_DSC(line, "%%DocumentProcessColors:")) { dsc->id = CDSC_DOCUMENTPROCESSCOLORS; if (dsc_parse_process_colours(dsc) != CDSC_OK) dsc->id = CDSC_UNKNOWNDSC; } else if (IS_DSC(line, "%%DocumentCustomColors:")) { dsc->id = CDSC_DOCUMENTCUSTOMCOLORS; if (dsc_parse_custom_colours(dsc) != CDSC_OK) dsc->id = CDSC_UNKNOWNDSC; } else { /* All other DSC comments are unknown, but not an error */ dsc->id = CDSC_UNKNOWNDSC; dsc_unknown(dsc); } dsc->endtrailer = DSC_END(dsc); return CDSC_OK; } dsc_private char * dsc_alloc_string(CDSC *dsc, const char *str, int len) { char *p; if (dsc->string_head == NULL) { dsc->string_head = (CDSCSTRING *)dsc_memalloc(dsc, sizeof(CDSCSTRING)); if (dsc->string_head == NULL) return NULL; /* no memory */ dsc->string = dsc->string_head; dsc->string->next = NULL; dsc->string->data = (char *)dsc_memalloc(dsc, CDSC_STRING_CHUNK); if (dsc->string->data == NULL) { dsc_reset(dsc); return NULL; /* no memory */ } dsc->string->index = 0; dsc->string->length = CDSC_STRING_CHUNK; } if ( dsc->string->index + len + 1 > dsc->string->length) { /* allocate another string block */ CDSCSTRING *newstring = (CDSCSTRING *)dsc_memalloc(dsc, sizeof(CDSCSTRING)); if (newstring == NULL) { dsc_debug_print(dsc, "Out of memory\n"); return NULL; } newstring->next = NULL; newstring->length = 0; newstring->index = 0; newstring->data = (char *)dsc_memalloc(dsc, CDSC_STRING_CHUNK); if (newstring->data == NULL) { dsc_memfree(dsc, newstring); dsc_debug_print(dsc, "Out of memory\n"); return NULL; /* no memory */ } newstring->length = CDSC_STRING_CHUNK; dsc->string->next = newstring; dsc->string = newstring; } if ( dsc->string->index + len + 1 > dsc->string->length) return NULL; /* failed */ p = dsc->string->data + dsc->string->index; memcpy(p, str, len); *(p+len) = '\0'; dsc->string->index += len + 1; return p; } /* store line, ignoring leading spaces */ dsc_private char * dsc_add_line(CDSC *dsc, const char *line, unsigned int len) { char *newline; unsigned int i; while (len && (IS_WHITE(*line))) { len--; line++; } newline = dsc_alloc_string(dsc, line, len); if (newline == NULL) return NULL; for (i=0; i slen) len = slen-1; while ( (i= '0') && (ch <= '9')) { /* octal coded character */ int j = 3; ch = 0; while (j && (i < len) && line[i]>='0' && line[i]<='7') { ch = (unsigned char)((ch<<3) + (line[i]-'0')); i++; j--; } str[newlength] = ch; } else if (ch == '(') { str[newlength] = ch; i++; } else if (ch == ')') { str[newlength] = ch; i++; } else if (ch == 'b') { str[newlength] = '\b'; i++; } else if (ch == 'f') { str[newlength] = '\b'; i++; } else if (ch == 'n') { str[newlength] = '\n'; i++; } else if (ch == 'r') { str[newlength] = '\r'; i++; } else if (ch == 't') { str[newlength] = '\t'; i++; } else if (ch == '\\') { str[newlength] = '\\'; i++; } } newlength++; } str[newlength] = '\0'; if (offset != (unsigned int *)NULL) *offset = i; return str; } dsc_private int dsc_get_int(const char *line, unsigned int len, unsigned int *offset) { char newline[MAXSTR]; int newlength = 0; unsigned int i = 0; unsigned char ch; len = min(len, sizeof(newline)-1); while ((iline + 7; pl = dsc_copy_string(page_label, sizeof(page_label), p, dsc->line_length-7, &i); if (pl == NULL) return CDSC_ERROR; p += i; if (dsc->line_length - 7 - i == 0) { /* Ordinal missing, or parentheses not matched in label */ /* Try to find ordinal at end of line */ while (i > 0) { if (!IS_WHITE_OR_EOL(p[-1])) break; p--; i--; } while (i > 0) { if (!isdigit((int)p[-1])) break; p--; i--; } } page_ordinal = dsc_get_int(p, dsc->line_length - 7 - i, NULL); if ( (page_ordinal == 0) || (strlen(page_label) == 0) || ((dsc->page_count == 0) && (page_ordinal != 1)) || (dsc->page_count && (page_ordinal != dsc->page[dsc->page_count-1].ordinal+1)) ) { int rc = dsc_error(dsc, CDSC_MESSAGE_PAGE_ORDINAL, dsc->line, dsc->line_length); switch (rc) { case CDSC_RESPONSE_OK: /* ignore this page */ return CDSC_OK; case CDSC_RESPONSE_CANCEL: /* accept the page */ break; case CDSC_RESPONSE_IGNORE_ALL: return CDSC_NOTDSC; } } page_number = dsc->page_count; dsc_add_page(dsc, page_ordinal, page_label); dsc->page[page_number].begin = DSC_START(dsc); dsc->page[page_number].end = DSC_START(dsc); if (dsc->page[page_number].label == NULL) return CDSC_ERROR; /* no memory */ return CDSC_OK; } dsc_private int dsc_parse_feature(CDSC *dsc) { char *p; unsigned int i; char feature_name[MAXSTR]; char feature_value[MAXSTR]; char *fn; char *fv; feature_name[0] = '\0'; feature_value[0] = '\0'; p = dsc->line + 15; /* %%BeginFeature: */ fn = dsc_copy_string(feature_name, sizeof(feature_name), p, dsc->line_length-15, &i); if (fn == NULL) return CDSC_ERROR; p += i; fv = dsc_copy_string(feature_value, sizeof(feature_value), p, dsc->line_length-15-i, &i); if ((dsc_stricmp(feature_name, "*PageSize") == 0) && (fv != NULL) && (dsc->scan_section == scan_setup)) { /* If this media was not specified in the header and the name * is known to us, add it to the media list */ int found = 0; int media_index = -1; for (i=0; imedia_count; i++) { if (dsc->media[i]->name && (dsc_stricmp(feature_value, dsc->media[i]->name) == 0)) found = 1; /* don't add it again */ } for (i=0; dsc_known_media[i].name; i++) { if (dsc_stricmp(feature_value, dsc_known_media[i].name)==0) { media_index = i; /* we know this paper size */ break; } } if (!found && (media_index >= 0)) { /* This media type was not included in the header where * it should have been. Add it to the media list now. */ CDSCMEDIA lmedia; lmedia.name = feature_value; lmedia.width = dsc_known_media[i].width; lmedia.height = dsc_known_media[i].height; lmedia.weight = 80.0; lmedia.colour = NULL; lmedia.type = NULL; lmedia.mediabox = NULL; if (dsc_add_media(dsc, &lmedia)) return CDSC_ERROR; /* out of memory */ } } return CDSC_OK; } /* DSC error reporting */ void dsc_debug_print(CDSC *dsc, const char *str) { if (dsc->debug_print_fn) dsc->debug_print_fn(dsc->caller_data, str); } /* Display a message about a problem with the DSC comments. * * explanation = an index to to a multiline explanation in dsc_message[] * line = pointer to the offending DSC line (if any) * return code = * CDSC_RESPONSE_OK DSC was wrong, make a guess about what * was really meant. * CDSC_RESPONSE_CANCEL Assume DSC was correct, ignore if it * is misplaced. * CDSC_RESPONSE_IGNORE_ALL Ignore all DSC. */ /* Silent operation. Don't display errors. */ dsc_private int dsc_error(CDSC *dsc, unsigned int explanation, char *line, unsigned int line_len) { if (explanation > DSC_MAX_ERROR) return CDSC_RESPONSE_CANCEL; if ((int)dsc->worst_error < (int)dsc_severity[explanation]) dsc->worst_error = dsc_severity[explanation]; /* if error function provided, use it */ if (dsc->dsc_error_fn) return dsc->dsc_error_fn(dsc->caller_data, dsc, explanation, line, line_len); /* treat DSC as being correct */ return CDSC_RESPONSE_CANCEL; } /* Fixup if DCS 2.0 was used */ dsc_private int dsc_dcs2_fixup(CDSC *dsc) { char composite[] = "Composite"; /* If DCS 2.0 single file format found, expose the separations * as multiple pages. Treat the initial EPS file as a single * page without comments, prolog or trailer. */ if (dsc->dcs2) { int code = CDSC_OK; int page_number; DSC_OFFSET *pbegin; DSC_OFFSET *pend; DSC_OFFSET end; CDCS2 *pdcs = dsc->dcs2; /* Now treat the initial EPS file as a single page without * headers or trailer, so page extraction will fetch the * the correct separation. */ if (dsc->page_count == 0) code = dsc_add_page(dsc, 1, composite); else if (dsc->page_count == 1) dsc->page[0].label = dsc_alloc_string(dsc, composite, (int)strlen(composite)+1); if (code != CDSC_OK) return code; page_number = dsc->page_count - 1; pbegin = &dsc->page[page_number].begin; pend = &dsc->page[page_number].end; if (*pbegin == *pend) { /* no page, so force it to conform to the following sections */ *pbegin = 999999999; *pend = 0; } if (dsc->begincomments != dsc->endcomments) { *pbegin = min(dsc->begincomments, *pbegin); dsc->begincomments = 0; *pend = max(dsc->endcomments, *pend); dsc->endcomments = 0; } if (dsc->beginpreview != dsc->endpreview) { *pbegin = min(dsc->beginpreview, *pbegin); dsc->beginpreview = 0; *pend = max(dsc->endpreview, *pend); dsc->endpreview = 0; } if (dsc->begindefaults != dsc->enddefaults) { *pbegin = min(dsc->begindefaults, *pbegin); dsc->begindefaults = 0; *pend = max(dsc->enddefaults, *pend); dsc->enddefaults = 0; } if (dsc->beginprolog != dsc->endprolog) { *pbegin = min(dsc->beginprolog, *pbegin); dsc->beginprolog = 0; *pend = max(dsc->endprolog, *pend); dsc->endprolog = 0; } if (dsc->beginsetup != dsc->endsetup) { *pbegin = min(dsc->beginsetup, *pbegin); dsc->beginsetup = 0; *pend = max(dsc->endsetup, *pend); dsc->endsetup = 0; } if (dsc->begintrailer != dsc->endtrailer) { *pbegin = min(dsc->begintrailer, *pbegin); dsc->begintrailer = 0; *pend = max(dsc->endtrailer, *pend); dsc->endtrailer = 0; } if (*pbegin == 999999999) *pbegin = *pend; end = 0; /* end of composite is start of first separation */ while (pdcs) { page_number = dsc->page_count; if ((pdcs->begin) && (pdcs->colourname != NULL)) { /* Single file DCS 2.0 */ code = dsc_add_page(dsc, page_number+1, pdcs->colourname); if (code) return code; dsc->page[page_number].begin = pdcs->begin; dsc->page[page_number].end = pdcs->end; if (end != 0) end = min(end, pdcs->begin); else end = pdcs->begin; /* first separation */ } else { /* Multiple file DCS 2.0 */ if ((pdcs->location != NULL) && (pdcs->filetype != NULL) && (pdcs->colourname != NULL) && (dsc_stricmp(pdcs->location, "Local") == 0) && ((dsc_stricmp(pdcs->filetype, "EPS") == 0) || (dsc_stricmp(pdcs->filetype, "EPSF") == 0))) { code = dsc_add_page(dsc, page_number+1, pdcs->colourname); if (code) return code; dsc->page[page_number].begin = 0; dsc->page[page_number].end = 0; } } pdcs = pdcs->next; } /* end of composite is start of first separation */ if (end != 0) *pend = end; /* According to the DCS2 specification, the size of the composite * section can be determined by the smallest #offset. * Some incorrect DCS2 files don't put the separations inside * the DOS EPS PostScript section, and have a TIFF separation * between the composite and the first separation. This * contravenes the DCS2 specification. If we see one of these * files, bring the end of the composite back to the end of * the DOS EPS PostScript section. */ if (dsc->doseps_end && (*pend > dsc->doseps_end)) *pend = dsc->doseps_end; } return 0; } dsc_private int dsc_parse_platefile(CDSC *dsc) { unsigned int i, n; CDCS2 dcs2; CDCS2 *pdcs2; char colourname[MAXSTR]; char filetype[MAXSTR]; char location[MAXSTR]; char *filename = NULL; int filename_length = 0; GSBOOL blank_line; GSBOOL single = FALSE; if (IS_DSC(dsc->line, "%%PlateFile:")) n = 12; else if (IS_DSC(dsc->line, "%%+")) n = 3; else return CDSC_ERROR; /* error */ memset(&dcs2, 0, sizeof(dcs2)); memset(&colourname, 0, sizeof(colourname)); memset(&filetype, 0, sizeof(filetype)); memset(&location, 0, sizeof(location)); memset(&filename, 0, sizeof(filename)); /* check for blank remainder of line */ blank_line = TRUE; for (i=n; iline_length; i++) { if (!IS_WHITE_OR_EOL(dsc->line[i])) { blank_line = FALSE; break; } } if (!blank_line) { dsc_copy_string(colourname, sizeof(colourname), dsc->line+n, dsc->line_length-n, &i); n+=i; if (i) dsc_copy_string(filetype, sizeof(filetype), dsc->line+n, dsc->line_length-n, &i); n+=i; while (IS_WHITE_OR_EOL(dsc->line[n])) n++; if (dsc->line[n] == '#') { /* single file DCS 2.0 */ single = TRUE; n++; if (i) dcs2.begin= dsc_get_int(dsc->line+n, dsc->line_length-n, &i); n+=i; if (i) dcs2.end= dcs2.begin + dsc_get_int(dsc->line+n, dsc->line_length-n, &i); } else { /* multiple file DCS 2.0 */ if (i) dsc_copy_string(location, sizeof(location), dsc->line+n, dsc->line_length-n, &i); n+=i; if (i) { filename = dsc->line+n; filename_length = dsc->line_length-n; if (filename[0] == '(') { /* Filename in parentheses like a PS string */ int j; for (j=0; jfile_length = min(dsc->file_length, dcs2.begin); /* Allocate it */ pdcs2 = (CDCS2 *)dsc_memalloc(dsc, sizeof(CDCS2)); if (pdcs2 == NULL) return CDSC_ERROR; /* out of memory */ memcpy(pdcs2, &dcs2, sizeof(CDCS2)); /* Then add to list of separations */ if (dsc->dcs2 == NULL) dsc->dcs2 = pdcs2; else { CDCS2 *this_dcs2 = dsc->dcs2; while (this_dcs2->next) this_dcs2 = this_dcs2->next; this_dcs2->next = pdcs2; } } } return CDSC_OK; } /* Parse a DCS 1.0 plate comment, storing like a multi file DSC 2.0 */ dsc_private int dsc_parse_dcs1plate(CDSC *dsc) { unsigned int i, n = 0; CDCS2 dcs2; CDCS2 *pdcs2; const char *colourname; char *filename = NULL; int filename_length = 0; GSBOOL blank_line; GSBOOL continued = FALSE; char *line = dsc->line; memset(&dcs2, 0, sizeof(dcs2)); memset(&filename, 0, sizeof(filename)); if (IS_DSC(line, "%%+")) { n = 3; line = dsc->last_line; continued = TRUE; } if (IS_DSC(line, "%%CyanPlate:")) { colourname = "Cyan"; if (!continued) n = 12; } else if (IS_DSC(line, "%%MagentaPlate:")) { colourname = "Magenta"; if (!continued) n = 15; } else if (IS_DSC(line, "%%YellowPlate:")) { colourname = "Yellow"; if (!continued) n = 14; } else if (IS_DSC(line, "%%BlackPlate:")) { colourname = "Black"; if (!continued) n = 13; } else return CDSC_ERROR; /* error */ /* check for blank remainder of line */ blank_line = TRUE; for (i=n; iline_length; i++) { if (!IS_WHITE_OR_EOL(dsc->line[i])) { blank_line = FALSE; break; } } if (!blank_line) { filename = dsc->line+n; filename_length = dsc->line_length - n; if ((filename_length==0) || (strlen(filename) == 0)) dsc_unknown(dsc); /* we didn't get all fields */ else { /* Allocate strings */ dcs2.colourname = dsc_alloc_string(dsc, colourname, (int)strlen(colourname)); dcs2.filetype = dsc_alloc_string(dsc, "EPS", 3); dcs2.location = dsc_alloc_string(dsc, "Local", 5); dcs2.filename = dsc_add_line(dsc, filename, filename_length); /* Allocate it */ pdcs2 = (CDCS2 *)dsc_memalloc(dsc, sizeof(CDCS2)); if (pdcs2 == NULL) return CDSC_ERROR; /* out of memory */ memcpy(pdcs2, &dcs2, sizeof(CDCS2)); /* Then add to list of separations */ if (dsc->dcs2 == NULL) dsc->dcs2 = pdcs2; else { CDCS2 *this_dcs2 = dsc->dcs2; while (this_dcs2->next) this_dcs2 = this_dcs2->next; this_dcs2->next = pdcs2; } /* We've set the DCS 2.0 data, but it really is DCS 1.0 */ dsc->dcs1 = TRUE; } } return CDSC_OK; } /* Find the filename which corresponds to this separation. * Used with multiple file DCS 2.0. * Returns NULL if there is no filename, or not DCS 2.0, * or single file DCS 2.0. * Caller will need to obtain the filesize from the file. */ const char * dsc_find_platefile(CDSC *dsc, int page) { CDCS2 *pdcs = dsc->dcs2; int i = 1; while (pdcs) { if (pdcs->begin != pdcs->end) return NULL; /* Single file DCS 2.0 */ if (pdcs->location && pdcs->filetype && pdcs->colourname && (dsc_stricmp(pdcs->location, "Local") == 0) && ((dsc_stricmp(pdcs->filetype, "EPS") == 0) || (dsc_stricmp(pdcs->filetype, "EPSF") == 0))) { if (i == page) return pdcs->filename; i++; } pdcs = pdcs->next; } return NULL; } dsc_private CDSCCOLOUR * dsc_find_colour(CDSC *dsc, const char *colourname) { CDSCCOLOUR *colour = dsc->colours; while (colour) { if (colour->name && (dsc_stricmp(colour->name, colourname)==0)) return colour; colour = colour->next; } return 0; } dsc_private int dsc_parse_process_colours(CDSC *dsc) { unsigned int i, n; CDSCCOLOUR *pcolour; char colourname[MAXSTR]; GSBOOL blank_line; if (IS_DSC(dsc->line, "%%DocumentProcessColors:")) n = 24; else if (IS_DSC(dsc->line, "%%+")) n = 3; else return CDSC_ERROR; /* error */ memset(&colourname, 0, sizeof(colourname)); /* check for blank remainder of line */ blank_line = TRUE; for (i=n; iline_length; i++) { if (!IS_WHITE_OR_EOL(dsc->line[i])) { blank_line = FALSE; break; } } while (IS_WHITE(dsc->line[n])) n++; if (COMPARE(dsc->line+n, "(atend)")) { if (dsc->scan_section == scan_comments) blank_line = TRUE; else { dsc_unknown(dsc); return CDSC_NOTDSC; } } if (!blank_line) { do { dsc_copy_string(colourname, sizeof(colourname), dsc->line+n, dsc->line_length-n, &i); n+=i; if (i && strlen(colourname)) { if ((pcolour = dsc_find_colour(dsc, colourname)) == NULL) { pcolour = (CDSCCOLOUR *) dsc_memalloc(dsc, sizeof(CDSCCOLOUR)); if (pcolour == NULL) return CDSC_ERROR; /* out of memory */ memset(pcolour, 0, sizeof(CDSCCOLOUR)); pcolour->custom = CDSC_CUSTOM_COLOUR_UNKNOWN; pcolour->name = dsc_alloc_string(dsc, colourname, (int)strlen(colourname)); if (dsc->colours == NULL) dsc->colours = pcolour; else { CDSCCOLOUR *this_colour = dsc->colours; while (this_colour->next) this_colour = this_colour->next; this_colour->next = pcolour; } } pcolour->type = CDSC_COLOUR_PROCESS; if (dsc_stricmp(colourname, "Cyan")==0) { pcolour->custom = CDSC_CUSTOM_COLOUR_CMYK; pcolour->cyan = 1.0; pcolour->magenta = pcolour->yellow = pcolour->black = 0.0; } else if (dsc_stricmp(colourname, "Magenta")==0) { pcolour->custom = CDSC_CUSTOM_COLOUR_CMYK; pcolour->magenta = 1.0; pcolour->cyan = pcolour->yellow = pcolour->black = 0.0; } else if (dsc_stricmp(colourname, "Yellow")==0) { pcolour->custom = CDSC_CUSTOM_COLOUR_CMYK; pcolour->yellow = 1.0; pcolour->cyan = pcolour->magenta = pcolour->black = 0.0; } else if (dsc_stricmp(colourname, "Black")==0) { pcolour->custom = CDSC_CUSTOM_COLOUR_CMYK; pcolour->black = 1.0; pcolour->cyan = pcolour->magenta = pcolour->yellow = 0.0; } else if (dsc_stricmp(colourname, "Red")==0) { pcolour->custom = CDSC_CUSTOM_COLOUR_RGB; pcolour->red = 1.0; pcolour->green = pcolour->blue = 0.0; } else if (dsc_stricmp(colourname, "Green")==0) { pcolour->custom = CDSC_CUSTOM_COLOUR_RGB; pcolour->green = 1.0; pcolour->red = pcolour->blue = 0.0; } else if (dsc_stricmp(colourname, "Blue")==0) { pcolour->custom = CDSC_CUSTOM_COLOUR_RGB; pcolour->blue = 1.0; pcolour->red = pcolour->green = 0.0; } } } while (i != 0); } return CDSC_OK; } dsc_private int dsc_parse_custom_colours(CDSC *dsc) { unsigned int i, n; CDSCCOLOUR *pcolour; char colourname[MAXSTR]; GSBOOL blank_line; if (IS_DSC(dsc->line, "%%DocumentCustomColors:")) n = 23; else if (IS_DSC(dsc->line, "%%+")) n = 3; else return CDSC_ERROR; /* error */ memset(&colourname, 0, sizeof(colourname)); /* check for blank remainder of line */ blank_line = TRUE; for (i=n; iline_length; i++) { if (!IS_WHITE_OR_EOL(dsc->line[i])) { blank_line = FALSE; break; } } while (IS_WHITE(dsc->line[n])) n++; if (COMPARE(dsc->line+n, "(atend)")) { if (dsc->scan_section == scan_comments) blank_line = TRUE; else { dsc_unknown(dsc); return CDSC_NOTDSC; } } if (!blank_line) { do { dsc_copy_string(colourname, sizeof(colourname), dsc->line+n, dsc->line_length-n, &i); n+=i; if (i && strlen(colourname)) { if ((pcolour = dsc_find_colour(dsc, colourname)) == NULL) { pcolour = (CDSCCOLOUR *) dsc_memalloc(dsc, sizeof(CDSCCOLOUR)); if (pcolour == NULL) return CDSC_ERROR; /* out of memory */ memset(pcolour, 0, sizeof(CDSCCOLOUR)); pcolour->name = dsc_alloc_string(dsc, colourname, (int)strlen(colourname)); pcolour->custom = CDSC_CUSTOM_COLOUR_UNKNOWN; if (dsc->colours == NULL) dsc->colours = pcolour; else { CDSCCOLOUR *this_colour = dsc->colours; while (this_colour->next) this_colour = this_colour->next; this_colour->next = pcolour; } } pcolour->type = CDSC_COLOUR_CUSTOM; } } while (i != 0); } return CDSC_OK; } dsc_private int dsc_parse_cmyk_custom_colour(CDSC *dsc) { unsigned int i, n; CDSCCOLOUR *pcolour; char colourname[MAXSTR]; float cyan, magenta, yellow, black; GSBOOL blank_line; if (IS_DSC(dsc->line, "%%CMYKCustomColor:")) n = 18; else if (IS_DSC(dsc->line, "%%+")) n = 3; else return CDSC_ERROR; /* error */ memset(&colourname, 0, sizeof(colourname)); /* check for blank remainder of line */ do { blank_line = TRUE; for (i=n; iline_length; i++) { if (!IS_WHITE_OR_EOL(dsc->line[i])) { blank_line = FALSE; break; } } if (blank_line) break; else { cyan = magenta = yellow = black = 0.0; cyan = dsc_get_real(dsc->line+n, dsc->line_length-n, &i); n += i; if (i) magenta = dsc_get_real(dsc->line+n, dsc->line_length-n, &i); n += i; if (i) yellow = dsc_get_real(dsc->line+n, dsc->line_length-n, &i); n += i; if (i) black = dsc_get_real(dsc->line+n, dsc->line_length-n, &i); n += i; if (i) dsc_copy_string(colourname, sizeof(colourname), dsc->line+n, dsc->line_length-n, &i); n+=i; if (i && strlen(colourname)) { if ((pcolour = dsc_find_colour(dsc, colourname)) == NULL) { pcolour = (CDSCCOLOUR *) dsc_memalloc(dsc, sizeof(CDSCCOLOUR)); if (pcolour == NULL) return CDSC_ERROR; /* out of memory */ memset(pcolour, 0, sizeof(CDSCCOLOUR)); pcolour->name = dsc_alloc_string(dsc, colourname, (int)strlen(colourname)); pcolour->type = CDSC_COLOUR_UNKNOWN; if (dsc->colours == NULL) dsc->colours = pcolour; else { CDSCCOLOUR *this_colour = dsc->colours; while (this_colour->next) this_colour = this_colour->next; this_colour->next = pcolour; } } pcolour->custom = CDSC_CUSTOM_COLOUR_CMYK; pcolour->cyan = cyan; pcolour->magenta = magenta; pcolour->yellow = yellow; pcolour->black = black; } } } while (i != 0); return CDSC_OK; } dsc_private int dsc_parse_rgb_custom_colour(CDSC *dsc) { unsigned int i, n; CDSCCOLOUR *pcolour; char colourname[MAXSTR]; float red, green, blue; GSBOOL blank_line; if (IS_DSC(dsc->line, "%%RGBCustomColor:")) n = 17; else if (IS_DSC(dsc->line, "%%+")) n = 3; else return CDSC_ERROR; /* error */ memset(&colourname, 0, sizeof(colourname)); /* check for blank remainder of line */ do { blank_line = TRUE; for (i=n; iline_length; i++) { if (!IS_WHITE_OR_EOL(dsc->line[i])) { blank_line = FALSE; break; } } if (blank_line) break; else { red = green = blue = 0.0; red = dsc_get_real(dsc->line+n, dsc->line_length-n, &i); n += i; if (i) green = dsc_get_real(dsc->line+n, dsc->line_length-n, &i); n += i; if (i) blue = dsc_get_real(dsc->line+n, dsc->line_length-n, &i); n += i; if (i) dsc_copy_string(colourname, sizeof(colourname), dsc->line+n, dsc->line_length-n, &i); n+=i; if (i && strlen(colourname)) { if ((pcolour = dsc_find_colour(dsc, colourname)) == NULL) { pcolour = (CDSCCOLOUR *) dsc_memalloc(dsc, sizeof(CDSCCOLOUR)); if (pcolour == NULL) return CDSC_ERROR; /* out of memory */ memset(pcolour, 0, sizeof(CDSCCOLOUR)); pcolour->name = dsc_alloc_string(dsc, colourname, (int)strlen(colourname)); pcolour->type = CDSC_COLOUR_UNKNOWN; if (dsc->colours == NULL) dsc->colours = pcolour; else { CDSCCOLOUR *this_colour = dsc->colours; while (this_colour->next) this_colour = this_colour->next; this_colour->next = pcolour; } } pcolour->custom = CDSC_CUSTOM_COLOUR_RGB; pcolour->red = red; pcolour->green = green; pcolour->blue = blue; } } } while (i != 0); return CDSC_OK; } epstool-3.08/src/os2.mak0000644000076400007640000000560510252260054014527 0ustar rjlrjl00000000000000# Copyright (C) 2005 Ghostgum Software Pty Ltd. All rights reserved. # # This software is provided AS-IS with no warranty, either express or # implied. # # This software is distributed under licence and may not be copied, # modified or distributed except as expressly authorised under the terms # of the licence contained in the file LICENCE in this distribution. # # For more information about licensing, please refer to # http://www.ghostgum.com.au/ or contact Ghostsgum Software Pty Ltd, # 218 Gallaghers Rd, Glen Waverley VIC 3150, AUSTRALIA, # Fax +61 3 9886 6616. # # $Id: os2.mak,v 1.1 2005/06/09 23:02:02 ghostgum Exp $ # Make epstool for OS/2 BINDIR=bin OBJDIR=epsobj SRCDIR=src SRCWINDIR=srcwin XINCLUDE= PFLAGS= PLINK= GTKCFLAGS= GTKLIBS= LIBPNGINC= LIBPNGCFLAGS= LIBPNGLIBS= LONGFILEDEF= LONGFILEMOD=cfile INSTALL=copy INSTALL_EXE=copy MAKE=nmake EMXOMF=-Zomf -Zmts CDEFS=-DOS2 -DNONAG $(LONGFILEDEF) GSCDEBUG= -g GSCFLAGS= $(CDEFS) $(EMXOMF) -Wall -Wstrict-prototypes -Wmissing-declarations -Wmissing-prototypes -fno-builtin -fno-common -Wcast-qual -Wwrite-strings $(CDEBUG) $(GSCDEBUG) $(RPM_OPT_FLAGS) $(XINCLUDE) $(PFLAGS) $(LIBPNGCFLAGS) $(GTKCFLAGS) CCAUX=gcc CC=gcc LFLAGS=$(PLINK) $(LIBPNGLIBS) $(GTKLIBS) CLINK=gcc $(LDFLAGS) $(EMXOMF) LINK=gcc $(LDFLAGS) $(EMXOMF) COMP=$(CC) -I$(SRCDIR) -I$(OBJDIR) $(CFLAGS) $(GSCFLAGS) NUL= DD=\$(NUL) SRC=$(SRCDIR)\$(NUL) SRCWIN=$(SRCWINDIR)\$(NUL) OD=$(OBJDIR)\$(NUL) BD=$(BINDIR)\$(NUL) OBJ=.obj #OBJ=.o EXE=.exe CO=-c FE=-o $(NUL) FO=-o $(NUL) FEO=-o $(OD) FOO=-o $(OD) CP=cp -f RM=rm -f RMDIR=rm -rf EPSOBJPLAT=$(OD)xnodll$(OBJ) $(OD)$(LONGFILEMOD)$(OBJ) EPSLIB=$(LIBPNGLIBS) BEGIN=$(OD)lib.rsp TARGET=epstool !include $(SRCDIR)/common.mak EPSTOOL_ROOT=/usr/local EPSTOOL_BASE=$(prefix)$(EPSTOOL_ROOT) EPSTOOL_DOCDIR=$(EPSTOOL_BASE)/share/doc/epstool-$(EPSTOOL_VERSION) EPSTOOL_MANDIR=$(EPSTOOL_BASE)/man EPSTOOL_BINDIR=$(EPSTOOL_BASE)/bin epstool: $(BD)epstool$(EXE) epstest: epstool $(BD)epstest$(EXE) $(BD)epstest$(EXE) $(OD)lib.rsp: makefile -mkdir $(BINDIR) -mkdir $(OBJDIR) echo "dummy" > $(OD)lib.rsp install: $(TARGET) -mkdir -p $(EPSTOOL_BASE) chmod a+rx $(EPSTOOL_BASE) -mkdir -p $(EPSTOOL_BINDIR) chmod a+rx $(EPSTOOL_BINDIR) $(INSTALL_EXE) $(BD)epstool$(EXE) $(EPSTOOL_BINDIR)$(DD)epstool$(EXE) -strip $(EPSTOOL_BINDIR)$(DD)epstool$(EXE) -mkdir -p $(EPSTOOL_MANDIR) chmod a+rx $(EPSTOOL_MANDIR) -mkdir -p $(EPSTOOL_MANDIR)$(DD)man1 chmod a+rx $(EPSTOOL_MANDIR)$(DD)man1 $(INSTALL) doc$(DD)epstool.1 $(EPSTOOL_MANDIR)$(DD)man1$(DD)epstool.1 -mkdir -p $(EPSTOOL_DOCDIR) chmod a+rx $(EPSTOOL_DOCDIR) $(INSTALL) doc$(DD)epstool.htm $(EPSTOOL_DOCDIR)$(DD)epstool.htm $(INSTALL) doc$(DD)gsview.css $(EPSTOOL_DOCDIR)$(DD)gsview.css $(INSTALL) LICENCE $(EPSTOOL_DOCDIR)$(DD)LICENCE clean: -$(RM) $(EPSOBJS) -$(RM) $(EPSTESTOBJS) -$(RM) $(OD)lib.rsp -$(RM) $(BD)epstool$(EXE) -$(RM) $(BD)epstest$(EXE) -rmdir $(OBJDIR) epstool-3.08/src/clzw.c0000644000076400007640000001656410252260054014463 0ustar rjlrjl00000000000000/* Copyright (C) 2004-2005 Ghostgum Software Pty Ltd. All rights reserved. This software is provided AS-IS with no warranty, either express or implied. This software is distributed under licence and may not be copied, modified or distributed except as expressly authorised under the terms of the licence contained in the file LICENCE in this distribution. For more information about licensing, please refer to http://www.ghostgum.com.au/ or contact Ghostsgum Software Pty Ltd, 218 Gallaghers Rd, Glen Waverley VIC 3150, AUSTRALIA, Fax +61 3 9886 6616. */ /* $Id: clzw.c,v 1.2 2005/06/10 09:39:24 ghostgum Exp $ */ /* LZW compression, compatible with PostScript LZWDecode filter */ #include #include #include "clzw.h" /* * Explanation of LZW by Mark Nelson in Dr. Dobb's Journal, October 1989. * http://www.dogma.net/markn/articles/lzw/lzw.htm * * This is an implementation of 12-bit LZW, compatible with * PostScript LZWDecode filter. */ #define LZW_HASH_SIZE 5021 #define LZW_MAX 4094 #define LZW_RESET 256 #define LZW_EOD 257 #define LZW_FIRST 258 typedef struct lzw_code_s { short code; short base_code; unsigned char ch; } lzw_code_t; struct lzw_state_s { short next_code; short lzwstr; lzw_code_t table[LZW_HASH_SIZE]; int code_bit_length; /* length of current codes, 9, 10, 11 or 12 */ short code_change; /* code at which code_bit_length increases */ int output_bits; /* bits that didn't fit in a whole byte */ /* This must be a 32-bit or larger type */ int output_bits_count; /* number of bits that didn't fit */ int bytes_in; /* for checking compression efficiency */ int bytes_out; }; /* Reset the code table */ static void lzw_reset(lzw_state_t *state) { int i; lzw_code_t *table = state->table; state->next_code = LZW_FIRST; state->code_bit_length = 9; state->code_change = (short)((1<code_bit_length)-1); state->bytes_in = 0; state->bytes_out = 0; for (i=0; inext_code = LZW_FIRST; state->code_bit_length = 9; state->output_bits = 0; state->output_bits_count = 0; state->lzwstr = -1; lzw_reset(state); } lzw_state_t * lzw_new(void) { lzw_state_t *state = (lzw_state_t *)malloc(sizeof(lzw_state_t)); if (state != (lzw_state_t *)NULL) lzw_init(state); return state; } /* Returns hash index of code/ch if found, or index of an empty location */ static int lzw_find_match(lzw_code_t *table, short code, unsigned char ch) { int i = (ch << 4) ^ code; int hash_offset = (i == 0) ? 1 : LZW_HASH_SIZE - i; while (table) { /* while (true) */ if (table[i].code == -1) break; /* not in table */ else if ((table[i].base_code == code) && (table[i].ch == ch)) break; /* found it */ else { /* search forwards from here */ i += hash_offset; if (i >= LZW_HASH_SIZE) i -= LZW_HASH_SIZE; } } return i; } void lzw_compress(lzw_state_t *state, const unsigned char *inbuf, int *inlen, unsigned char *outbuf, int *outlen) { int icount = 0; int ilen = *inlen; int ocount = 0; int olen = *outlen; unsigned char ch; int hash_index; int bits = state->output_bits; int len = state->output_bits_count; int code_len = state->code_bit_length; short lzwstr = state->lzwstr; short next_code = state->next_code; lzw_code_t *table = state->table; int do_reset = 0; int bytes_in = state->bytes_in; int bytes_out = state->bytes_out; if (lzwstr == -1) { /* get first char */ lzwstr = inbuf[icount++]; /* PostScript LZWEncode always starts with LZW_RESET */ bits = LZW_RESET; len = code_len; } /* Write out any bits we couldn't fit last time */ while ((len >= 8) && (ocount < olen)) { outbuf[ocount++] = (unsigned char)(bits >> (len-8)); len -= 8; } while ((icount < ilen) && (ocount < olen)) { ch = inbuf[icount++]; hash_index = lzw_find_match(table, lzwstr, ch); if (table[hash_index].code != -1) lzwstr = table[hash_index].code; else { /* Output this code */ bits = (bits << code_len) + lzwstr; len += code_len; while ((len >= 8) && (ocount < olen)) { outbuf[ocount++] = (unsigned char)(bits >> (len-8)); len -= 8; } if (next_code == state->code_change) { state->code_bit_length = ++code_len; state->code_change = (short)((1 << code_len) - 1); /* Monitor compression efficiency */ bytes_in = state->bytes_in + icount; bytes_out = state->bytes_out + ocount; if (bytes_out > bytes_in + bytes_in/16) { /* Data is not compressing */ /* Reset the table to avoid ratio getting worse */ do_reset = 1; } } if (do_reset || (next_code >= LZW_MAX)) { /* Table is full or poor efficiency, so start again */ bits = (bits << code_len) + LZW_RESET; len += code_len; while ((len >= 8) && (ocount < olen)) { outbuf[ocount++] = (unsigned char)(bits >> (len-8)); len -= 8; } lzw_reset(state); lzwstr = ch; next_code = state->next_code; code_len = state->code_bit_length; do_reset = 0; } else { /* Add new code to table */ table[hash_index].code = next_code++; table[hash_index].base_code = lzwstr; table[hash_index].ch = ch; lzwstr = ch; } } } if (*inlen == 0) { /* Flush and EOD */ bits = (bits << 2*code_len) + (lzwstr << code_len) + LZW_EOD; len += 2*code_len; while ((len >= 8) && (ocount < olen)) { outbuf[ocount++] = (unsigned char)(bits >> (len-8)); len -= 8; } if ((len > 0) && (ocount < olen)) outbuf[ocount++] = (unsigned char)(bits << (8-len)); } /* Save state for next time */ state->output_bits = bits; state->output_bits_count = len; state->code_bit_length = code_len; state->lzwstr = lzwstr; state->next_code = next_code; state->bytes_in += icount; state->bytes_out += ocount; *outlen = ocount; /* bytes written to output buffer */ *inlen = icount; /* input bytes used */ } void lzw_free(lzw_state_t *state) { free(state); } #ifdef STANDALONE #include int main(int argc, char *argv[]) { char outbuf[4096]; int outlen = sizeof(outbuf); int outcount; char inbuf[4096]; int inlen; int incount; int inused; lzw_state_t *lzw; FILE *infile = NULL; FILE *outfile = NULL; int inread=0, outwritten=0; if (argc != 3) return 1; infile = fopen(argv[1], "rb"); if (infile == (FILE*)NULL) return 1; outfile = fopen(argv[2], "wb"); if (outfile == (FILE*)NULL) return 1; lzw = lzw_new(); while ((incount = fread(inbuf, 1, sizeof(inbuf), infile)) != 0) { inread += incount; inused = 0; inlen = incount; while (inused < incount) { outlen = sizeof(outbuf); inlen = incount - inused; lzw_compress(lzw, inbuf+inused, &inlen, outbuf, &outlen); inused += inlen; if (outlen) fwrite(outbuf, 1, outlen, outfile); outwritten += outlen; } } inlen = 0; /* EOD */ outlen = sizeof(outbuf); lzw_compress(lzw, inbuf, &inlen, outbuf, &outlen); lzw_free(lzw); if (outlen) fwrite(outbuf, 1, outlen, outfile); outwritten += outlen; fprintf(stdout, "in=%d out=%d\n", inread, outwritten); fclose(infile); fclose(outfile); return 0; } #endif epstool-3.08/src/cpdfscan.c0000644000076400007640000012411610252260054015256 0ustar rjlrjl00000000000000/* Copyright (C) 2002-2005 Ghostgum Software Pty Ltd. All rights reserved. This software is provided AS-IS with no warranty, either express or implied. This software is distributed under licence and may not be copied, modified or distributed except as expressly authorised under the terms of the licence contained in the file LICENCE in this distribution. For more information about licensing, please refer to http://www.ghostgum.com.au/ or contact Ghostsgum Software Pty Ltd, 218 Gallaghers Rd, Glen Waverley VIC 3150, AUSTRALIA, Fax +61 3 9886 6616. */ /* $Id: cpdfscan.c,v 1.7 2005/06/10 09:39:24 ghostgum Exp $ */ /* PDF scanner */ /* This is a rudimentary PDF scanner, intended to get * the page count, and for each page the Rotate, MediaBox * and CropBox. */ #ifdef DEMO_PDFSCAN # include # include # include # include # include # ifdef _MSC_VER # define vsnprintf _vsnprintf # endif # define csfopen fopen # define cslen strlen #else # include "common.h" # include #endif #include "cpdfscan.h" /* Limitations. * * We currently load the entire xref table. To minimise memory * would could instead keep a list of xref blocks, and do random * access within those. * * Memory management is very simple. We just keep a linked * list of allocated blocks for composite objects. * We empty the stack, and free all PDF objects and composite * objects before returning to the caller. * We don't bother doing garbage collection. */ /* We keep a linked list of memory allocated for composite objects * such as name, string, array or dict. */ typedef struct PDFMEM_s PDFMEM; struct PDFMEM_s { void *ptr; int len; PDFMEM *next; }; /* The token scanner and object references understand the following types */ typedef enum rtype_e { invalidtype=0, marktype=1, nulltype=2, booltype=3, /* uses boolval */ integertype=4, /* uses intval */ realtype=5, /* uses realval */ nametype=6, /* uses nameval */ stringtype=7, /* uses strval */ arraytype=8, /* uses arrayval */ dicttype=9, /* uses dictval */ optype=10, /* uses opval */ streamtype=11, /* uses streamval */ objtype=12, /* uses objval */ commenttype=13 } rtype; const char *rtype_string[] = { "invalidtype", "marktype", "nulltype", "booltype", "integertype", "realtype", "nametype", "stringtype", "arraytype", "dicttype", "optype", "streamtype", "objtype", "commenttype" }; /* A reference contains a simple object, or a pointer to * a composite object. */ typedef struct ref_s ref; struct ref_s { rtype type; int rsize; union value_u { /* simple */ void *voidval; BOOL boolval; int intval; float realval; /* composite */ char *nameval; char *strval; ref *arrayval; ref *dictval; char *opval; /* simple */ unsigned long streamval; int objval; } value; }; /* Cross reference table entry */ typedef struct PDFXREF_s { unsigned long offset; int generation; BOOL used; } PDFXREF; struct PDFSCAN_s { void *handle; int (*print_fn)(void *handle, const char *ptr, int len); TCHAR filename[1024]; FILE *file; char *buf; int buflen; /* length of allocated buf */ int len; /* #bytes currently in buf */ int offset; /* file offset to start of buf */ int begin; /* offset in buf to start of token */ int end; /* offset in buf to end of token */ rtype token_type; /* token type */ BOOL instream; /* In a stream, looking for endstream */ unsigned long xref_offset; /* offset to xref table */ PDFXREF *xref; int xref_len; /* Object numbers obtained during pdf_scan_open() */ int root; /* root object reference */ int info; /* document info dicionary reference */ int pages; /* Pages dictionary reference */ int page_count; /* number of pages */ /* Cached page media */ int pagenum; int rotate; PDFBBOX mediabox; PDFBBOX cropbox; /* memory allocation */ PDFMEM *memory_head; PDFMEM *memory_tail; /* operand stack */ ref *ostack; int ostack_idx; /* index to top of ostack */ int ostack_len; /* Initially 512 */ int ostack_maxlen; /* maximum depth of ostack */ /* objects in memory */ /* This contains pairs of integer & reference */ ref *objs; int objs_count; /* count of loaded objects */ int objs_len; /* length of objs */ int objs_maxlen; /* maximum number entries in objs */ }; typedef enum PDFSEEK_e { PDFSEEK_CUR, PDFSEEK_END, PDFSEEK_SET } PDFSEEK; /* Prototypes */ static int pdf_scan_next_token(PDFSCAN *ps); static int pdf_scan_read_trailer(PDFSCAN *ps, unsigned long *prev); static int pdf_scan_read_xref(PDFSCAN *ps, unsigned long xref_offset); static void clear_stack(PDFSCAN *ps); static void clear_objs(PDFSCAN *ps); static void pdf_scan_freeall(PDFSCAN *ps); static void pdf_scan_cleanup(PDFSCAN *ps); static int pdf_scan_open_file(PDFSCAN *ps); /*****************************************************************/ /* text message output */ static int pdf_scan_write(PDFSCAN *ps, const char *str, int len) { if (ps != NULL) fwrite(str, 1, len, stdout); else (*ps->print_fn)(ps->handle, str, len); return len; } static int pdf_scan_msgf(PDFSCAN *ps, const char *fmt, ...) { va_list args; int count; char buf[2048]; va_start(args,fmt); count = vsnprintf(buf, sizeof(buf), fmt, args); pdf_scan_write(ps, buf, count); va_end(args); return count; } /*****************************************************************/ /* memory allocation */ static void pdf_scan_cleanup(PDFSCAN *ps) { if (ps->file) fclose(ps->file); ps->file = NULL; clear_stack(ps); clear_objs(ps); pdf_scan_freeall(ps); } static void *pdf_scan_alloc(PDFSCAN *ps, const void *ptr, int len) { void *data; PDFMEM *mem = (PDFMEM *)malloc(sizeof(PDFMEM)); if (mem == NULL) return NULL; data = malloc(len); if (data == NULL) { free(mem); return NULL; } mem->ptr = data; mem->next = NULL; mem->len = len; memcpy(data, ptr, len); if (ps->memory_tail) { ps->memory_tail->next = mem; ps->memory_tail = mem; } else ps->memory_head = ps->memory_tail = mem; return data; } /* free all name/string/array/dict memory */ static void pdf_scan_freeall(PDFSCAN *ps) { PDFMEM *memnext; PDFMEM *mem = ps->memory_head; while (mem) { memnext = mem->next; free(mem->ptr); free(mem); mem = memnext; } ps->memory_head = ps->memory_tail = NULL; } /*****************************************************************/ /* Token checks */ static BOOL is_optoken(PDFSCAN *ps, const char *str) { return (ps->token_type == optype) && (ps->end-ps->begin == (int)strlen(str)) && (memcmp(ps->buf+ps->begin, str, ps->end-ps->begin) == 0); } static int type_check(PDFSCAN *ps, rtype type) { if (ps->token_type == type) return 0; pdf_scan_msgf(ps, "Error at offset %ld. Expecting %s and found %s\n", ps->offset + ps->begin, rtype_string[(int)type], rtype_string[(int)ps->token_type]); pdf_scan_msgf(ps, "Token is \042"); pdf_scan_write(ps, ps->buf+ps->begin, ps->end-ps->begin); pdf_scan_msgf(ps, "\042\n"); return -1; } static int op_check(PDFSCAN *ps, const char *str) { int code = type_check(ps, optype); if (code) return code; if (!is_optoken(ps, str)) { pdf_scan_msgf(ps, "Error at offset %ld. Expecting \042%s\042 and found \042", ps->offset + ps->begin, str); pdf_scan_write(ps, ps->buf+ps->begin, ps->end-ps->begin); pdf_scan_msgf(ps, "\042\n"); code = -1; } return code; } /*****************************************************************/ /* stack */ const ref invalidref = {invalidtype, 0, {NULL}}; const ref markref = {marktype, 0, {NULL}}; /* Push item, return depth of stack */ /* >0 is success, <=0 is failure */ static int push_stack(PDFSCAN *ps, ref r) { int idx; if (ps->ostack_idx + 1 >= ps->ostack_len) { /* increase stack size */ ref *newstack; int newlen = ps->ostack_len + 256; if (newlen > ps->ostack_maxlen) { pdf_scan_msgf(ps, "push_stack: stack overflow\n"); return 0; } newstack = (ref *)malloc(newlen * sizeof(ref)); if (newstack == NULL) { pdf_scan_msgf(ps, "push_stack: Out of memory\n"); return 0; } memcpy(newstack, ps->ostack, ps->ostack_len * sizeof(ref)); free(ps->ostack); ps->ostack = newstack; ps->ostack_len = newlen; } idx = ++(ps->ostack_idx); ps->ostack[idx] = r; return idx; } static ref pop_stack(PDFSCAN *ps) { if (ps->ostack_idx <= 0) { pdf_scan_msgf(ps, "pop_stack: stack underflow\n"); return invalidref; } return ps->ostack[ps->ostack_idx--]; } static void clear_stack(PDFSCAN *ps) { ps->ostack_idx = 0; } static ref index_stack(PDFSCAN *ps, int n) { if (n < 0) { pdf_scan_msgf(ps, "index_stack: index must not be negative\n"); return invalidref; } if (ps->ostack_idx <= n) { pdf_scan_msgf(ps, "index_stack: stack isn't that deep\n"); return invalidref; } return ps->ostack[ps->ostack_idx-n]; } static ref top_stack(PDFSCAN *ps) { if (ps->ostack_idx <= 0) { pdf_scan_msgf(ps, "top_stack: stack is empty\n"); return invalidref; } return ps->ostack[ps->ostack_idx]; } /*****************************************************************/ /* references */ static ref make_int(int value) { ref r; r.type = integertype; r.rsize = 0; r.value.intval = value; return r; } static ref make_string(PDFSCAN *ps, const char *str, int len) { ref r; r.type = stringtype; r.rsize = len; r.value.strval = pdf_scan_alloc(ps, str, len); if (r.value.strval == NULL) return invalidref; return r; } static ref make_name(PDFSCAN *ps, const char *str, int len) { ref r; r.type = nametype; r.rsize = len; r.value.nameval = pdf_scan_alloc(ps, str, len); if (r.value.nameval == NULL) return invalidref; return r; } static BOOL nameref_equals(ref *r, const char *name) { int len = (int)strlen(name); if (r->type != nametype) return FALSE; if (r->rsize != len) return FALSE; return (memcmp(r->value.nameval, name, len) == 0); } /* Get a reference from a dictionary */ /* Return the result, but don't push it */ static ref dict_get(PDFSCAN *ps, const char *name) { int namelen = (int)strlen(name); ref dict = top_stack(ps); ref *r; int dictlen; int i; if (dict.type == invalidtype) return invalidref; dictlen = dict.rsize * 2; for (i = 0; irsize == namelen) && (r->type == nametype) && (memcmp(r->value.nameval, name, namelen) ==0)) return dict.value.dictval[i+1]; } return invalidref; } /* convert the items on the stack to an array on the stack */ static ref array_to_mark(PDFSCAN *ps) { ref r; ref *array; int n = ps->ostack_idx; int len; while ((n>0) && (ps->ostack[n].type != marktype)) n--; if (n == 0) { pdf_scan_msgf(ps, "array_to_mark: no mark on stack\n"); return invalidref; } len = ps->ostack_idx - n; r.type = arraytype; r.rsize = len; r.value.arrayval = NULL; if (len) { array = pdf_scan_alloc(ps, &ps->ostack[n+1], len * sizeof(ref)); if (array) r.value.arrayval = array; else return invalidref; } ps->ostack_idx -= len + 1; push_stack(ps, r); return r; } /* convert the items on the stack to a dictionary on the stack */ static ref dict_to_mark(PDFSCAN *ps) { ref r; ref *dict; int n = ps->ostack_idx; int len; while ((n>0) && (ps->ostack[n].type != marktype)) n--; if (n == 0) { pdf_scan_msgf(ps, "dict_to_mark: no mark on stack\n"); return invalidref; } len = ps->ostack_idx - n; if (len & 1) { pdf_scan_msgf(ps, "dict_to_mark: must have name/value pairs\n"); return invalidref; } r.type = dicttype; r.rsize = len/2; r.value.arrayval = NULL; if (len) { dict = pdf_scan_alloc(ps, &ps->ostack[n+1], len * sizeof(ref)); if (dict) r.value.arrayval = dict; else return invalidref; } ps->ostack_idx -= len + 1; push_stack(ps, r); return r; } /*****************************************************************/ /* Push reference from a token */ static ref push_token(PDFSCAN *ps) { ref r; int len = ps->end - ps->begin; const char *p = ps->buf + ps->begin; r.type = ps->token_type; r.rsize = 0; r.value.voidval = NULL; switch(r.type) { case invalidtype: break; case marktype: break; case nulltype: break; case booltype: if ((len == 4) && (memcmp(p, "true", 4)==0)) r.value.boolval = TRUE; else if ((len == 5) && (memcmp(p, "true", 5)==0)) r.value.boolval = FALSE; else r = invalidref; break; case integertype: { char buf[64]; if (len > (int)sizeof(buf)-1) r = invalidref; else { memcpy(buf, p, len); buf[len] = '\0'; r.value.intval = atoi(buf); } } break; case realtype: { char buf[64]; if (len > (int)sizeof(buf)-1) r = invalidref; else { memcpy(buf, p, len); buf[len] = '\0'; r.value.realval = (float)atof(buf); } } break; case nametype: r = make_name(ps, p+1, len-1); break; case stringtype: r = make_string(ps, p, len); break; case streamtype: case commenttype: case objtype: case optype: case arraytype: case dicttype: /* Can't push these from a token */ /* These are made by operators like stream, R, ], >> */ return invalidref; default: r.type = invalidtype; break; } push_stack(ps, r); return r; } /* Process known operators */ static int process_op(PDFSCAN *ps) { ref r; if (ps->token_type != optype) return 1; /* not an op */ if (is_optoken(ps, "R")) { /* convert "n 0 R" to an indirect reference */ ref r1 = index_stack(ps, 1); r = top_stack(ps); if ((r.type == integertype) && (r1.type == integertype)) { r.type = objtype; r.rsize = r.value.intval; r.value.intval = r1.value.intval; pop_stack(ps); pop_stack(ps); push_stack(ps, r); } } else if (is_optoken(ps, "]")) { array_to_mark(ps); } else if (is_optoken(ps, ">>")) { dict_to_mark(ps); } else if (is_optoken(ps, "null")) { r.type = nulltype; r.rsize = 0; r.value.voidval = NULL; push_stack(ps, r); } else if (is_optoken(ps, "obj")) { pdf_scan_msgf(ps, "ignoring obj token\n"); /* ignore */ } else if (is_optoken(ps, "endobj")) { pdf_scan_msgf(ps, "ignoring endobj token\n"); /* ignore */ } else if (is_optoken(ps, "stream")) { /* stream object contains offset to start of stream */ r.type = streamtype; r.rsize = 0; r.value.streamval = ps->offset + ps->end; push_stack(ps, r); /* Now skip over stream */ pdf_scan_next_token(ps); } else { pdf_scan_msgf(ps, "process_op: unrecognised operator \042"); pdf_scan_write(ps, ps->buf+ps->begin, ps->end-ps->begin); pdf_scan_msgf(ps, "\042\n"); return -1; } return 0; } /*****************************************************************/ /* Debugging and error messages */ #ifdef NOTUSED /* Print a reference, returning number of characters written */ static int print_ref(PDFSCAN *ps, ref *r) { int n = 0; switch(r->type) { case invalidtype: n = pdf_scan_msgf(ps, "--invalid--"); break; case marktype: n = pdf_scan_msgf(ps, "--mark--"); break; case nulltype: n = pdf_scan_msgf(ps, "--null--"); break; case booltype: n = pdf_scan_msgf(ps, "%s", r->value.boolval ? "true" : "false"); break; case integertype: n = pdf_scan_msgf(ps, "%d", r->value.intval); break; case realtype: n = pdf_scan_msgf(ps, "%g", r->value.realval); break; case nametype: n = pdf_scan_write(ps, "/", 1); pdf_scan_write(ps, r->value.nameval, r->rsize); break; case stringtype: n = pdf_scan_write(ps, "(", 1); n += pdf_scan_write(ps, r->value.strval, r->rsize); n += pdf_scan_write(ps, ")", 1); break; case streamtype: n = pdf_scan_msgf(ps, "--stream:%d--", r->value.streamval); break; case commenttype: n = pdf_scan_msgf(ps, "--comment--"); break; case objtype: n = pdf_scan_msgf(ps, "--obj:%d--", r->value.objval); break; case optype: n = pdf_scan_msgf(ps, "--op:"); n += pdf_scan_write(ps, r->value.opval, r->rsize); n += pdf_scan_write(ps, "--", 2); break; case arraytype: n = pdf_scan_msgf(ps, "--array:%d--", r->rsize); break; case dicttype: n = pdf_scan_msgf(ps, "--dict:%d--", r->rsize); break; default: n = pdf_scan_msgf(ps, "--unknown--"); break; } return n; } /* print a reference, expanding array and dict */ static int print_ref_expand(PDFSCAN *ps, ref *r) { int i; int n = 0;; if (r->type == arraytype) { n += pdf_scan_msgf(ps, "[ "); for (i=0; irsize; i++) { n += print_ref(ps, &r->value.arrayval[i]); n += pdf_scan_msgf(ps, " "); } n += pdf_scan_msgf(ps, "]"); } else if (r->type == dicttype) { n += pdf_scan_msgf(ps, "<< "); for (i=0; irsize; i++) { n += print_ref(ps, &r->value.dictval[i+i]); n += pdf_scan_msgf(ps, " "); n += print_ref(ps, &r->value.dictval[i+i+1]); n += pdf_scan_msgf(ps, " "); } n += pdf_scan_msgf(ps, ">>"); } else n += print_ref(ps, r); return n; } static void print_stack(PDFSCAN *ps) { int i, n=ps->ostack_idx; int col = 0; pdf_scan_msgf(ps, "Stack: "); for (i=1; i<=n; i++) { col += print_ref(ps, &ps->ostack[i]); if (col > 70) { pdf_scan_msgf(ps, "\n"); col = 0; } else col += pdf_scan_msgf(ps, " "); } pdf_scan_msgf(ps, "\n"); } static void print_stack_expand(PDFSCAN *ps) { int i, n=ps->ostack_idx; pdf_scan_msgf(ps, "Stack:\n"); for (i=1; i<=n; i++) { pdf_scan_msgf(ps, "%2d: ", i); print_ref_expand(ps, &ps->ostack[i]); pdf_scan_msgf(ps, "\n"); } } static void pdf_scan_print_allocated(PDFSCAN *ps) { int count = 0; int len = 0; PDFMEM *mem = ps->memory_head; while (mem) { len += sizeof(PDFMEM); len += mem->len; count++; mem = mem->next; } pdf_scan_msgf(ps, "Allocated memory %d bytes in %d objects\n", len, count); } #endif /*****************************************************************/ /* object reading and cache */ static int obj_add(PDFSCAN *ps, int objnum, ref objref) { if (ps->objs_count + 2 >= ps->objs_len) { /* allocate more space */ ref *newobjs; int newlen = ps->objs_len + 256; if (newlen > ps->objs_maxlen) { pdf_scan_msgf(ps, "obj_add: too many objects to cache\n"); return 0; } newobjs = (ref *)malloc(newlen * sizeof(ref)); if (newobjs == NULL) { pdf_scan_msgf(ps, "obj_add: Out of memory\n"); return 0; } memcpy(newobjs, ps->objs, ps->objs_len * sizeof(ref)); free(ps->objs); ps->objs = newobjs; ps->objs_len = newlen; } ps->objs[ps->objs_count++] = make_int(objnum); ps->objs[ps->objs_count++] = objref; return ps->objs_count; } static ref obj_find(PDFSCAN *ps, int objnum) { int i; for (i=0; iobjs_count; i+=2) { if (objnum == ps->objs[i].value.intval) return ps->objs[i+1]; } return invalidref; } static void clear_objs(PDFSCAN *ps) { ps->objs_count = 0; } /*****************************************************************/ /* token parsing */ static int is_white(char ch) { return (ch == '\0') || (ch == '\t') || (ch == '\n') || (ch == '\f') || (ch == '\r') || (ch == ' '); } static int is_delimiter(char ch) { return (ch == '(') || (ch == ')') || (ch == '<') || (ch == '>') || (ch == '[') || (ch == ']') || (ch == '{') || (ch == '}') || (ch == '/') || (ch == '%'); } /* Scan next token from buffer, returning token type and offset to begin * and end of token. * Return 0 if OK, 1 if no token or not enough data, -1 on error */ static int pdf_scan_token(const char *buf, int buflen, rtype *ttype, int *tbegin, int *tend) { int code = -1; int i = 0; rtype type; int begin, end; *ttype = type = invalidtype; *tbegin = begin = 0; *tend = end = 0; while ((i < buflen) && is_white(buf[i])) i++; if (i == buflen) return 1; begin = i; if (buf[i] == '%') { while (i < buflen) { if ((buf[i] == '\n') || (buf[i] == '\r')) { type = commenttype; end = i; code = 0; break; } i++; } if (i >= buflen) code = 1; } else if (buf[i] == '(') { /* string */ int pcount = 0; type = stringtype; i++; while (i < buflen) { if (buf[i] == '\\') i++; else if (buf[i] == '(') pcount++; else if (buf[i] == ')') { if (pcount <= 0) { end = i+1; code = 0; break; } else pcount--; } i++; } if (i >= buflen) code = 1; } else if (buf[i] == '<') { i++; if (i >= buflen) { code = 1; } else if (buf[i] == '<') { /* marktype */ end = i+1; type = marktype; code = 0; } else { /* hexadecimal string */ type = stringtype; while (i < buflen) { if (buf[i] == '>') { end = i+1; code = 0; break; } i++; } if (i >= buflen) code = 1; } } else if (buf[i] == '[') { code = 0; end = i+1; type = marktype; } else if (buf[i] == '/') { /* name */ type = nametype; i++; while (i < buflen) { if (is_white(buf[i]) || is_delimiter(buf[i])) { end = i; code = 0; break; } i++; } if (i >= buflen) code = 1; } else if (is_delimiter(buf[i])) { /* skip over delimiter */ if (buf[i] == '>') { i++; if (i < buflen) { if (buf[i] == '>') { type = optype; end = i+1; code = 0; } else code = -1; } } else { type = optype; end = i+1; code = 0; } if (i >= buflen) code = 1; } else { /* First assume that it is an op */ type = optype; while (i < buflen) { if (is_white(buf[i]) || is_delimiter(buf[i])) { end = i; code = 0; break; } i++; } if (i >= buflen) code = 1; /* try to convert it into a bool */ if ((code == 0) && (type == optype)) { if ((end - begin == 4) && (memcmp(buf+begin, "true", 4) == 0)) { type = booltype; } else if ((end - begin == 5) && (memcmp(buf+begin, "false", 5) == 0)) { type = booltype; } } /* try to convert it into an integer */ if ((code == 0) && (type == optype)) { int j; char ch; BOOL isreal = FALSE; BOOL isnum = TRUE; for (j=begin; jfile) { fclose(ps->file); ps->file = NULL; } if (ps->buf) { free(ps->buf); ps->buf = NULL; } ps->buflen = 0; if (ps->xref) { free(ps->xref); ps->xref = NULL; } ps->xref_len = 0; if (ps->ostack) { free(ps->ostack); ps->ostack = NULL; } ps->ostack_len = 0; ps->ostack_idx = 0; if (ps->objs) { free(ps->objs); ps->objs = NULL; } ps->objs_len = 0; ps->objs_count = 0; memset(ps, 0, sizeof(PDFSCAN)); } static int pdf_scan_open_file(PDFSCAN *ps) { ps->file = csfopen(ps->filename, TEXT("rb")); if (ps->file == NULL) return -1; return 0; } static int pdf_scan_init(PDFSCAN *ps, const TCHAR *name) { int len = (int)(cslen(name)+1) * sizeof(TCHAR); if (len > (int)sizeof(ps->filename)) return -1; memcpy(ps->filename, name, len); if (pdf_scan_open_file(ps) != 0) return -1; ps->buflen = 256; ps->buf = (char *)malloc(ps->buflen); if (ps->buf == NULL) { pdf_scan_finish(ps); return -2; } ps->ostack_maxlen = 4096; ps->ostack_len = 256; ps->ostack_idx = 0; /* empty */ ps->ostack = (ref *)malloc(ps->ostack_len * sizeof(ref)); if (ps->ostack == NULL) { pdf_scan_finish(ps); return -2; } /* make first item on stack invalid */ ps->ostack[0].type = invalidtype; ps->ostack[0].rsize = 0; ps->ostack[0].value.voidval = NULL; /* object cache */ ps->objs_maxlen = 1024; ps->objs_len = 256; ps->objs_count = 0; /* empty */ ps->objs = (ref *)malloc(ps->objs_len * sizeof(ref)); if (ps->objs == NULL) { pdf_scan_finish(ps); return -2; } ps->pagenum = -1; /* no cached media info yet */ return 0; } static int pdf_scan_seek(PDFSCAN *ps, long offset, PDFSEEK whence) { int code = -1; switch (whence) { case PDFSEEK_CUR: offset = ps->offset + ps->end + offset; case PDFSEEK_SET: ps->begin = ps->end = ps->len = 0; code = fseek(ps->file, offset, SEEK_SET); ps->offset = offset; break; case PDFSEEK_END: code = fseek(ps->file, 0, SEEK_END); ps->begin = ps->end = ps->len = 0; ps->offset = ftell(ps->file); break; } return code; } /* Read next token from PDF file */ /* Return 0 if OK, or -1 if EOF, -2 if error */ /* Set *token_type to token type */ static int pdf_scan_next_token(PDFSCAN *ps) { int code = 0; int count; rtype type=invalidtype; int begin=0, end=0; do { if ((code == 1) && ps->end) { /* move characters to front of buffer */ if (ps->len - ps->end) memmove(ps->buf, ps->buf+ps->end, ps->len - ps->end); ps->offset += ps->end; ps->len = ps->len - ps->end; ps->begin = 0; ps->end = 0; } if ((code == 1) && (ps->len >= ps->buflen)) { /* increase buffer size */ char *newbuf; int newbuflen = 2 * ps->buflen; newbuf = (char *)malloc(newbuflen); if (newbuf) { memcpy(newbuf, ps->buf, ps->buflen); free(ps->buf); ps->buf = newbuf; ps->buflen = newbuflen; } else { pdf_scan_msgf(ps, "Out of memory in pdf_scan_next_token\n"); pdf_scan_msgf(ps, "Tried to realloc %d to %d\n", ps->buflen, newbuflen); code = -2; break; } } if ((code == 1) || (ps->len == 0)) { count = (int)fread(ps->buf+ps->len, 1, ps->buflen-ps->len, ps->file); if (count == 0) { pdf_scan_msgf(ps, "EOF in pdf_scan_next_token\n"); code = -1; break; } ps->len += count; } while (ps->instream) { /* We are in a stream. Keep reading until we find * the endstream. This isn't robust. It can be fooled * by "endstream" occuring within a stream. */ while ((ps->end < ps->len) && (ps->buf[ps->end] != 'e')) ps->end++; /* look for endstream */ if (ps->end + 9 >= ps->len) { code = 1; /* need more */ break; } if (memcmp(ps->buf+ps->end, "endstream", 9) == 0) ps->instream = FALSE; else ps->end++; } if (!ps->instream) code = pdf_scan_token(ps->buf+ps->end, ps->len - ps->end, &type, &begin, &end); } while (code == 1); if (code == 0) { /* got a token */ ps->begin = ps->end + begin; ps->end = ps->end + end; ps->token_type = type; if ((type == optype) && (ps->end-ps->begin == 6) && (memcmp(ps->buf+ps->begin, "stream", 6) == 0)) ps->instream = TRUE; } return code; } /*****************************************************************/ /* Reading %%EOF, xref, traler */ static int previous_line(const char *str, int len) { int i = len-1; /* first skip over EOL */ while ((i > 0) && ((str[i]=='\r') || (str[i]=='\n'))) i--; while ((i > 0) && !((str[i]=='\r') || (str[i]=='\n'))) i--; if (!((str[i]=='\r') || (str[i]=='\n'))) return -1; /* didn't find a line */ return i+1; } static int pdf_scan_find_xref(PDFSCAN *ps) { char buf[4096]; int i, j; int code = -1; int count; pdf_scan_seek(ps, 0, PDFSEEK_END); count = min((int)sizeof(buf), ps->offset); pdf_scan_seek(ps, -count, PDFSEEK_CUR); count = (int)fread(buf, 1, sizeof(buf), ps->file); pdf_scan_seek(ps, 0, PDFSEEK_SET); if (count == 0) return -1; i = count - 5; while (i > 0) { /* Find %%EOF */ if (memcmp(buf+i, "%%EOF", 5) == 0) { code = 0; break; } i--; } if (i == 0) { pdf_scan_msgf(ps, "Failed to find %%EOF\n"); code = -1; } if (code == 0) { /* Look for xref table offset */ j = previous_line(buf, i); if (j >= 0) ps->xref_offset = atol(buf+j); else code = -1; i = j; if (ps->xref_offset == 0) code = -1; if (code != 0) pdf_scan_msgf(ps, "Failed to find cross reference table\n"); } if (code == 0) { /* Look for "startxref" */ j = previous_line(buf, i); if (j >= 0) { if (memcmp(buf+j, "startxref", 9) != 0) code = -1; } else { code = -1; } if (code != 0) pdf_scan_msgf(ps, "Failed to find startxref\n"); } return code; } /* Read a cross reference table */ /* This is called for each cross reference table */ static int pdf_scan_read_xref(PDFSCAN *ps, unsigned long xref_offset) { int code; int i; int first = 0; int count = 0; unsigned long prev = 0; unsigned long offset = 0; int generation = 0; BOOL used = FALSE; pdf_scan_seek(ps, xref_offset, PDFSEEK_SET); code = pdf_scan_next_token(ps); if (code == 0) code = op_check(ps, "xref"); while (code == 0) { code = pdf_scan_next_token(ps); if ((code == 0) && is_optoken(ps, "trailer")) break; /* finished this xref table */ if (code == 0) { first = atoi(ps->buf + ps->begin); code = pdf_scan_next_token(ps); } if (code == 0) { count = atoi(ps->buf + ps->begin); } if (code == 0) { /* make sure there is enough space in the table */ if (first + count > ps->xref_len) { int len = (first + count) * sizeof(PDFXREF); PDFXREF *newxref = (PDFXREF *)malloc(len); if (newxref) { memset(newxref, 0, len); memcpy(newxref, ps->xref, ps->xref_len * sizeof(PDFXREF)); free(ps->xref); ps->xref = newxref; ps->xref_len = first + count; } else { pdf_scan_msgf(ps, "pdf_scan_read_xref: out of memory\n"); code = -2; break; } } } for (i=first; ibuf+ps->begin); code = pdf_scan_next_token(ps); } if (code == 0) { generation = atoi(ps->buf+ps->begin); code = pdf_scan_next_token(ps); } if (code == 0) { if (is_optoken(ps, "n")) used = TRUE; else if (is_optoken(ps, "f")) used = FALSE; else code = -1; } /* We don't deal correctly with generation. * We assume that the first xref table that marks an * object as used is the definitive reference. */ if (code == 0) { if (!(ps->xref[i].used)) { ps->xref[i].offset = offset; ps->xref[i].generation = generation; ps->xref[i].used = used; } } } } if (code == 0) { code = pdf_scan_read_trailer(ps, &prev); if ((code == 0) && prev && prev != ps->xref_offset) { /* read older xref and trailer */ code = pdf_scan_read_xref(ps, prev); } } return code; } /* Read a trailer */ static int pdf_scan_read_trailer(PDFSCAN *ps, unsigned long *prev) { int code = 0; ref p; code = pdf_scan_next_token(ps); if ((code == 0) && (ps->token_type != marktype)) code = -1; push_token(ps); while (code == 0) { code = pdf_scan_next_token(ps); if (code != 0) break; if (is_optoken(ps, "startxref")) { if (ps->root == 0) { p = dict_get(ps, "Root"); if (p.type == objtype) ps->root = p.value.objval; else { pdf_scan_msgf(ps, "trailer /Root requires indirect reference\n"); code = -1; } } p = dict_get(ps, "Prev"); if (p.type == integertype) *prev = p.value.intval; else if (p.type != invalidtype) { code = -1; pdf_scan_msgf(ps, "trailer /Prev requires integer\n"); } break; } if (process_op(ps) != 0) push_token(ps); } if (code != 0) pdf_scan_msgf(ps, "Error reading trailer\n"); return code; } static int pdf_scan_read_object_start(PDFSCAN *ps, int objnum) { int code = 0; int value = 0; if (objnum == 0) { pdf_scan_msgf(ps, "Object 0 is always unused\n"); return -1; } if (objnum >= ps->xref_len) { pdf_scan_msgf(ps, "Object reference %d doesn't exist. There are only %d objects\n", objnum, ps->xref_len); return -1; } if (!ps->xref[objnum].used) { pdf_scan_msgf(ps, "Object %d is unused\n", objnum); return -1; } pdf_scan_seek(ps, ps->xref[objnum].offset, PDFSEEK_SET); code = pdf_scan_next_token(ps); /* object number */ if (code == 0) code = type_check(ps, integertype); if (code == 0) { value = atoi(ps->buf+ps->begin); /* object number */ code = pdf_scan_next_token(ps); /* generation */ } if (code == 0) code = type_check(ps, integertype); if (code == 0) code = pdf_scan_next_token(ps); /* obj */ if (code == 0) code = op_check(ps, "obj"); if (value != objnum) { pdf_scan_msgf(ps, "Didn't find object %d\n", objnum); return -1; } return code; } /*****************************************************************/ /* Read an object, and leave it on the stack */ static int pdf_scan_read_object(PDFSCAN *ps, int objnum) { int code; ref objref = obj_find(ps, objnum); if (objref.type != invalidtype) { /* found in cache */ push_stack(ps, objref); return 0; } code = pdf_scan_read_object_start(ps, objnum); if (code) { pdf_scan_msgf(ps, "Didn't find object %d\n", objnum); return -1; } code = pdf_scan_next_token(ps); if ((code == 0) && (ps->token_type != marktype)) code = -1; push_token(ps); while (code == 0) { code = pdf_scan_next_token(ps); if (code != 0) break; if (is_optoken(ps, "endobj")) { obj_add(ps, objnum, top_stack(ps)); break; } if (process_op(ps) != 0) push_token(ps); } return code; } /*****************************************************************/ /* find the object number for a page */ /* Return <= 0 if failure, or object number */ /* First page is 0 */ static int pdf_scan_find_page(PDFSCAN *ps, int pagenum) { int code; ref kids; ref r; int pageobj = 0; int count_base = 0; int count; ref *pref; int i; int inext; if (pagenum >= ps->page_count) { pdf_scan_msgf(ps, "Not that many pages\n"); return -1; } code = pdf_scan_read_object(ps, ps->pages); if (code) { pdf_scan_msgf(ps, "Didn't find Pages object\n"); return -1; } /* iterate through Kids, looking for the one that includes this page */ kids = dict_get(ps, "Kids"); if (kids.type != arraytype) { pdf_scan_msgf(ps, "/Pages object %d must contain /Kids array\n", ps->pages); return -1; } pop_stack(ps); /* First Pages */ for (i = 0; (i < kids.rsize) && (code == 0); i=inext) { inext = i+1; pref = &kids.value.arrayval[i]; if (pref->type == objtype) code = pdf_scan_read_object(ps, pref->value.objval); if (code == 0) { r = dict_get(ps, "Type"); if (nameref_equals(&r, "Page")) { if (count_base + i == pagenum) { /* this is it */ pageobj = pref->value.objval; pop_stack(ps); /* the wanted page */ break; } } else if (nameref_equals(&r, "Pages")) { r = dict_get(ps, "Count"); if (r.type == integertype) { count = r.value.intval; if (pagenum < count_base + count) { /* It's under this child */ inext = 0; pop_stack(ps); /* The old /Pages */ code = pdf_scan_read_object(ps, pref->value.objval); if (code == 0) { kids = dict_get(ps, "Kids"); if (kids.type != arraytype) { pdf_scan_msgf(ps, "/Pages object %d must contain /Kids array\n", pref->value.objval); code = -1; } } } else { count_base += count; } } else { pdf_scan_msgf(ps, "/Pages /Count must be integer\n"); code = -1; } } else { pdf_scan_msgf(ps, "pdf_scan_find_page: object %d isn't Pages or Page\n", pref->value.objval); code = -1; } pop_stack(ps); } } if (pageobj <= 0) { pdf_scan_msgf(ps, "Failed to find page %d\n", pagenum+1); code = -1; } if (code) return -1; /* Don't clean up, since we will use the cached objects * when extracting the page media. */ return pageobj; } static int pdf_scan_read_page_count(PDFSCAN *ps) { int code; ref p; code = pdf_scan_read_object(ps, ps->pages); if (code) { pdf_scan_msgf(ps, "Didn't find Pages object\n"); return -1; } p = dict_get(ps, "Type"); if (!nameref_equals(&p, "Pages")) { pdf_scan_msgf(ps, "Pages object didn't have /Type /Pages\n"); return -1; } p = dict_get(ps, "Count"); if (p.type != integertype) { pdf_scan_msgf(ps, "Pages object didn't integer /Count\n"); return -1; } ps->page_count = p.value.intval; return code; } static int convert_float(ref r, float *f) { if (r.type == realtype) *f = r.value.realval; else if (r.type == integertype) *f = (float)r.value.intval; else return -1; return 0; } static int pdf_scan_read_bbox(PDFBBOX *box, ref array) { int code = 0; if (array.type != arraytype) code = -1; if (array.rsize != 4) code = -1; if (code == 0) code = convert_float(array.value.arrayval[0], &box->llx); if (code == 0) code = convert_float(array.value.arrayval[1], &box->lly); if (code == 0) code = convert_float(array.value.arrayval[2], &box->urx); if (code == 0) code = convert_float(array.value.arrayval[3], &box->ury); return code; } /* Read catalog and leave on stack */ static int pdf_scan_read_catalog(PDFSCAN *ps) { int code; ref p; /* Read root object, making sure it is /Type /Catalog, * and that /Pages is an indirect reference */ code = pdf_scan_read_object(ps, ps->root); if (code) { pdf_scan_msgf(ps, "Didn't find Root object\n"); return -1; } p = dict_get(ps, "Type"); if (!nameref_equals(&p, "Catalog")) { pdf_scan_msgf(ps, "Root object didn't have /Type /Catalog\n"); return -1; } p = dict_get(ps, "Pages"); if (p.type != objtype) { pdf_scan_msgf(ps, "Root object didn't indirect reference to /Pages\n"); return -1; } ps->pages = p.value.intval; return 0; } /*****************************************************************/ /* public functions */ void pdf_scan_close(PDFSCAN *ps) { pdf_scan_cleanup(ps); pdf_scan_finish(ps); free(ps); } PDFSCAN * pdf_scan_open(const TCHAR *filename, void *handle, int (*fn)(void *handle, const char *ptr, int len)) { int code; int rotate; PDFBBOX mediabox, cropbox; PDFSCAN *ps = (PDFSCAN *)malloc(sizeof(PDFSCAN)); if (ps == NULL) return NULL; memset(ps, 0, sizeof(PDFSCAN)); ps->handle = handle; ps->print_fn = fn; code = pdf_scan_init(ps, filename); if (code == -1) pdf_scan_msgf(ps, "Couldn't open PDF file\n"); else if (code != 0) pdf_scan_msgf(ps, "Error initialising PDF scanner\n"); if (code == 0) code = pdf_scan_find_xref(ps); if (code == 0) code = pdf_scan_read_xref(ps, ps->xref_offset); if (code == 0) code = pdf_scan_read_catalog(ps); if (code == 0) code = pdf_scan_read_page_count(ps); if (code == 0) code = pdf_scan_page_media(ps, 0, &rotate, &mediabox, &cropbox); pdf_scan_cleanup(ps); if (code != 0) { pdf_scan_close(ps); ps = NULL; } return ps; } int pdf_scan_page_count(PDFSCAN *ps) { if (ps == NULL) return 0; return ps->page_count; } int pdf_scan_page_media(PDFSCAN *ps, int pagenum, int *rotate, PDFBBOX *mediabox, PDFBBOX *cropbox) { BOOL found_rotate = FALSE; BOOL found_mediabox = FALSE; BOOL found_cropbox = FALSE; BOOL has_parent = TRUE; ref p, objref; int objnum; if (ps == NULL) return -1; if (pagenum == ps->pagenum) { /* Used cached values */ *rotate = ps->rotate; *mediabox = ps->mediabox; *cropbox = ps->cropbox; return 0; } if (ps->file == NULL) { if (pdf_scan_open_file(ps) != 0) return -1; } objnum = pdf_scan_find_page(ps, pagenum); if (objnum <= 0) { pdf_scan_cleanup(ps); return -1; } if (pdf_scan_read_object(ps, objnum) < 0) { pdf_scan_cleanup(ps); return -1; } while (has_parent) { if (!found_rotate) { p = dict_get(ps, "Rotate"); if (p.type == integertype) { *rotate = p.value.intval; found_rotate = TRUE; } } if (!found_mediabox) { p = dict_get(ps, "MediaBox"); if (pdf_scan_read_bbox(mediabox, p) == 0) found_mediabox = TRUE; } if (!found_cropbox) { p = dict_get(ps, "CropBox"); if (pdf_scan_read_bbox(cropbox, p) == 0) found_cropbox = TRUE; } if (found_rotate && found_mediabox && found_cropbox) break; p = dict_get(ps, "Parent"); if (p.type == objtype) { objref = pop_stack(ps); if (pdf_scan_read_object(ps, p.value.objval) < 0) { push_stack(ps, objref); has_parent = FALSE; } } else has_parent = FALSE; } pop_stack(ps); if (!found_cropbox) { *cropbox = *mediabox; found_cropbox = TRUE; } if (!found_rotate) { *rotate = 0; found_rotate = TRUE; } pdf_scan_cleanup(ps); if (found_rotate && found_mediabox && found_cropbox) { /* cache these values */ ps->pagenum = pagenum; ps->rotate = *rotate; ps->mediabox = *mediabox; ps->cropbox = *cropbox; return 0; } return -1; } /*****************************************************************/ #ifdef DEMO_PDFSCAN int test_print_fn(void *handle, const char *ptr, int len) { fwrite(ptr, 1, len, stdout); return len; } int main(int argc, char *argv[]) { PDFSCAN *ps; int i, count; int code; PDFBBOX mediabox, cropbox; int rotate; if (argc < 2) { fprintf(stdout, "Usage: cpdfscan filename\n"); return 1; } ps = pdf_scan_open(argv[1], NULL, test_print_fn); if (ps) { count = pdf_scan_page_count(ps); pdf_scan_msgf(ps, "Page count is %d\n", count); for (i=0; i #include #include #include #include #include #ifndef __WIN32__ #include #include #endif #include "cfile.h" int _llseek(unsigned int fd, unsigned long offset_high, unsigned long offset_low, loff_t *result, unsigned int whence); _syscall5(int, _llseek, uint, fd, ulong, hi, ulong, lo, loff_t *, res, uint, wh); /* These are the private bits */ struct GFile_s { int m_fd; time_t m_filetime; /* time/date of selected file */ FILE_POS m_length; /* length of selected file */ int m_error; /* non-zero if an error */ /* error cleared by open, close or seek to 0 */ }; #ifndef ASSERT #ifdef DEBUG static void gfile_assert(const char *file, int line); #define ASSERT(f) if (!(f)) gfile_assert(__FILE__, __LINE__) #else #define ASSERT(f) #endif #endif #ifdef DEBUG void gfile_assert(const char *file, int line) { g_print("gfile_assert: file:%s line:%d\n", file, line); } #endif int gfile_error(GFile *gf) { ASSERT(gf != NULL); ASSERT(gf->m_fd != 0); return gf->m_error; } FILE_POS gfile_get_length(GFile *gf) { loff_t length = 0; loff_t result = 0; unsigned long offset_high; unsigned long offset_low; const int shift = sizeof(unsigned long) * 8; const unsigned long mask = (unsigned long)-1; /* Get the current position */ _llseek(gf->m_fd, 0, 0, &result, SEEK_CUR); if (sizeof(FILE_OFFSET) > sizeof(unsigned long)) { offset_high = (result >> shift) & mask; offset_low = result & mask; } else { offset_high = 0; offset_low = result; } /* Seek to the end to get the length */ _llseek(gf->m_fd, 0, 0, &length, SEEK_END); /* Seek back to where we were before */ _llseek(gf->m_fd, offset_high, offset_low, &result, SEEK_SET); return length; } int gfile_get_datetime(GFile *gf, unsigned long *pdt_low, unsigned long *pdt_high) { struct stat fstatus; ASSERT(gf != NULL); fstat(gf->m_fd, &fstatus); *pdt_low = fstatus.st_mtime; *pdt_high = 0; return 1; } int gfile_changed(GFile *gf, FILE_POS length, unsigned long dt_low, unsigned long dt_high) { unsigned long this_dt_low, this_dt_high; FILE_POS this_length = gfile_get_length(gf); gfile_get_datetime(gf, &this_dt_low, &this_dt_high); return ( (this_length != length) || (this_dt_low != dt_low) || (this_dt_high != dt_high)); } GFile *gfile_open_handle(int hFile, unsigned int nOpenFlags) { /* nOpenFlags ignored */ GFile *gf = (GFile *)malloc(sizeof(GFile)); if (gf == NULL) return NULL; memset(gf, 0, sizeof(GFile)); gf->m_fd = hFile; gf->m_error = 0; return gf; } GFile *gfile_open(LPCTSTR lpszFileName, unsigned int nOpenFlags) { GFile *gf; int fd; int flags = O_RDONLY; if ((nOpenFlags & 0xf) == gfile_modeWrite) flags = O_WRONLY; if ((nOpenFlags & 0xf000) == gfile_modeCreate) flags |= O_CREAT | O_TRUNC; if (lpszFileName[0] == '\0') fd = 1; /* stdout */ else fd = open(lpszFileName, flags, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH); if (fd == -1) return NULL; gf = (GFile *)malloc(sizeof(GFile)); if (gf == NULL) { close(fd); return NULL; } memset(gf, 0, sizeof(GFile)); gf->m_fd = fd; gf->m_error = 0; return gf; } void gfile_close(GFile *gf) { ASSERT(gf != NULL); ASSERT(gf->m_fd != -1); close(gf->m_fd); gf->m_fd = -1; gf->m_error = 0; free(gf); } unsigned int gfile_read(GFile *gf, void *lpBuf, unsigned int nCount) { int count; ASSERT(gf != NULL); ASSERT(gf->m_fd != -1); count = read(gf->m_fd, lpBuf, nCount); if (count == -1) gf->m_error = 1; return (unsigned int)count; } unsigned int gfile_write(GFile *gf, const void *lpBuf, unsigned int nCount) { int count; ASSERT(gf != NULL); ASSERT(gf->m_fd != -1); count = write(gf->m_fd, lpBuf, nCount); if (count == -1) gf->m_error = 1; return (unsigned int)count; } /* only works with reading */ int gfile_seek(GFile *gf, FILE_OFFSET lOff, unsigned int nFrom) { int code; unsigned int origin; loff_t result = 0; unsigned long offset_high; unsigned long offset_low; const int shift = sizeof(unsigned long) * 8; const unsigned long mask = (unsigned long)-1; ASSERT(gf != NULL); ASSERT(gf->m_fd != -1); if (sizeof(FILE_OFFSET) > sizeof(unsigned long)) { offset_high = (lOff >> shift) & mask; offset_low = lOff & mask; } else { offset_high = 0; offset_low = lOff; } switch(nFrom) { default: case gfile_begin: origin = SEEK_SET; break; case gfile_current: origin = SEEK_CUR; break; case gfile_end: origin = SEEK_END; break; } if ((origin == SEEK_SET) && (lOff == 0)) { gf->m_error = 0; } code = _llseek(gf->m_fd, offset_high, offset_low, &result, origin); return code; } FILE_POS gfile_get_position(GFile *gf) { int code; loff_t result; ASSERT(gf != NULL); ASSERT(gf->m_fd != 0); code = _llseek(gf->m_fd, 0, 0, &result, SEEK_CUR); return result; } int gfile_puts(GFile *gf, const char *str) { return gfile_write(gf, str, strlen(str)); } epstool-3.08/src/cfile.c0000644000076400007640000001026710252260054014560 0ustar rjlrjl00000000000000/* Copyright (C) 2000-2005 Ghostgum Software Pty Ltd. All rights reserved. This software is provided AS-IS with no warranty, either express or implied. This software is distributed under licence and may not be copied, modified or distributed except as expressly authorised under the terms of the licence contained in the file LICENCE in this distribution. For more information about licensing, please refer to http://www.ghostgum.com.au/ or contact Ghostsgum Software Pty Ltd, 218 Gallaghers Rd, Glen Waverley VIC 3150, AUSTRALIA, Fax +61 3 9886 6616. */ /* $Id: cfile.c,v 1.5 2005/06/10 09:39:24 ghostgum Exp $ */ /* GFile is similar but not identical to MFC CFile, but is plain C. */ /* This implementation uses C file streams */ #ifdef __WIN32__ #include #endif #include #include #include #include #include #ifndef __WIN32__ #include #endif #include "cfile.h" /* These are the private bits */ struct GFile_s { FILE *m_file; time_t m_filetime; /* time/date of selected file */ FILE_POS m_length; /* length of selected file */ }; #ifndef ASSERT #ifdef DEBUG static void gfile_assert(const char *file, int len); #define ASSERT(f) if (!(f)) gfile_assert(__FILE__, __LINE__) #else #define ASSERT(f) #endif #endif int gfile_error(GFile *gf) { ASSERT(gf != NULL); ASSERT(gf->m_file != 0); return ferror(gf->m_file); } FILE_POS gfile_get_length(GFile *gf) { struct stat fstatus; fstat(fileno(gf->m_file), &fstatus); return fstatus.st_size; } int gfile_get_datetime(GFile *gf, unsigned long *pdt_low, unsigned long *pdt_high) { struct stat fstatus; ASSERT(gf != NULL); fstat(fileno(gf->m_file), &fstatus); *pdt_low = fstatus.st_mtime; *pdt_high = 0; return 1; } int gfile_changed(GFile *gf, FILE_POS length, unsigned long dt_low, unsigned long dt_high) { unsigned long this_dt_low, this_dt_high; FILE_POS this_length = gfile_get_length(gf); gfile_get_datetime(gf, &this_dt_low, &this_dt_high); return ( (this_length != length) || (this_dt_low != dt_low) || (this_dt_high != dt_high)); } GFile *gfile_open_handle(void *hFile, unsigned int nOpenFlags) { GFile *gf; const char *access = "rb"; if ((nOpenFlags & 0xf) == gfile_modeWrite) access = "wb"; gf = (GFile *)malloc(sizeof(GFile)); if (gf == NULL) return NULL; memset(gf, 0, sizeof(GFile)); gf->m_file = fdopen((long)hFile, access); if (gf->m_file == NULL) { free(gf); gf = NULL; } return gf; } GFile *gfile_open(LPCTSTR lpszFileName, unsigned int nOpenFlags) { GFile *gf; FILE *f; const char *access = "rb"; if ((nOpenFlags & 0xf) == gfile_modeWrite) access = "wb"; if (lpszFileName[0] == '\0') f = stdout; else f = fopen(lpszFileName, access); if (f == (FILE *)NULL) return NULL; gf = (GFile *)malloc(sizeof(GFile)); if (gf == NULL) { fclose(f); return NULL; } memset(gf, 0, sizeof(GFile)); gf->m_file = f; return gf; } void gfile_close(GFile *gf) { ASSERT(gf != NULL); ASSERT(gf->m_file != 0); fclose(gf->m_file); gf->m_file = NULL; free(gf); } unsigned int gfile_read(GFile *gf, void *lpBuf, unsigned int nCount) { ASSERT(gf != NULL); ASSERT(gf->m_file != 0); return fread(lpBuf, 1, nCount, gf->m_file); } unsigned int gfile_write(GFile *gf, const void *lpBuf, unsigned int nCount) { ASSERT(gf != NULL); ASSERT(gf->m_file != 0); return fwrite(lpBuf, 1, nCount, gf->m_file); } /* only works with reading */ int gfile_seek(GFile *gf, FILE_OFFSET lOff, unsigned int nFrom) { int origin; ASSERT(gf != NULL); ASSERT(gf->m_file != 0); switch(nFrom) { default: case gfile_begin: origin = SEEK_SET; break; case gfile_current: origin = SEEK_CUR; break; case gfile_end: origin = SEEK_END; break; } if ((origin == SEEK_SET) && (lOff == 0)) rewind(gf->m_file); return fseek(gf->m_file, lOff, origin); } FILE_POS gfile_get_position(GFile *gf) { ASSERT(gf != NULL); ASSERT(gf->m_file != 0); return ftell(gf->m_file); } int gfile_puts(GFile *gf, const char *str) { return gfile_write(gf, str, strlen(str)); } epstool-3.08/src/xnodll.c0000644000076400007640000000316610252260054014776 0ustar rjlrjl00000000000000/* Copyright (C) 2004 Ghostgum Software Pty Ltd. All rights reserved. This software is provided AS-IS with no warranty, either express or implied. This software is distributed under licence and may not be copied, modified or distributed except as expressly authorised under the terms of the licence contained in the file LICENCE in this distribution. For more information about licensing, please refer to http://www.ghostgum.com.au/ or contact Ghostsgum Software Pty Ltd, 218 Gallaghers Rd, Glen Waverley VIC 3150, AUSTRALIA, Fax +61 3 9886 6616. */ /* $Id: xnodll.c,v 1.2 2004/11/29 08:09:33 ghostgum Exp $ */ /* Stubs for platforms without shared objects or DLLs */ #include #include #include "common.h" #include "cdll.h" /******************************************************************/ static int dll_msg(TCHAR *msg, LPCTSTR str, int msglen) { int len = (int)cslen(str); if (len < msglen){ csncat(msg, str, len); msglen -= len; } return msglen; } /* platform dependent */ /* Load DLL */ int dll_open(GGMODULE *hmodule, LPCTSTR name, TCHAR *msg, int msglen) { memset(msg, 0, msglen); msglen = dll_msg(msg, TEXT("Trying to load "), msglen); msglen = dll_msg(msg, name, msglen); msglen = dll_msg(msg, TEXT("\n"), msglen); msglen = dll_msg(msg, TEXT("Can't load libraries on this platform.\n"), msglen); *hmodule = NULL; return -1; } /* Unload DLL */ int dll_close(GGMODULE *hmodule) { return -1; } dll_proc dll_sym(GGMODULE *hmodule, const char *name) { return NULL; } /******************************************************************/ epstool-3.08/src/common.h0000644000076400007640000001556610252260054015002 0ustar rjlrjl00000000000000/* Copyright (C) 2001-2005 Ghostgum Software Pty Ltd. All rights reserved. This software is provided AS-IS with no warranty, either express or implied. This software is distributed under licence and may not be copied, modified or distributed except as expressly authorised under the terms of the licence contained in the file LICENCE in this distribution. For more information about licensing, please refer to http://www.ghostgum.com.au/ or contact Ghostsgum Software Pty Ltd, 218 Gallaghers Rd, Glen Waverley VIC 3150, AUSTRALIA, Fax +61 3 9886 6616. */ /* $Id: common.h,v 1.15 2005/06/10 09:39:24 ghostgum Exp $ */ /* Common header */ #include #include #include #include #include #include "cplat.h" #include "cfile.h" #define __PROTOTYPES__ #define MAXSTR 256 #define COPY_BUF_SIZE 4096 #define GS_REVISION_MIN 704 #define GS_REVISION 704 #define GS_REVISION_MAX 899 #define return_error(val) return val #ifndef min #define min(a,b) ((a) < (b) ? (a) : (b)) #endif #ifndef max #define max(a,b) ((a) > (b) ? (a) : (b)) #endif /* Opaque types */ #ifndef CDSC_TYPEDEF #define CDSC_TYPEDEF typedef struct CDSC_s CDSC; #endif #ifndef Doc_TYPEDEF #define Doc_TYPEDEF typedef struct Doc_s Doc; #endif #ifndef GSDLL_TYPEDEF #define GSDLL_TYPEDEF typedef struct GSDLL_s GSDLL; #endif #ifndef PLDLL_TYPEDEF #define PLDLL_TYPEDEF typedef struct PLDLL_s PLDLL; #endif #ifndef GSIMAGE_TYPEDEF #define GSIMAGE_TYPEDEF typedef struct GSIMAGE_s GSIMAGE; #endif #ifndef GSREQ_TYPEDEF #define GSREQ_TYPEDEF typedef struct GSREQ_s GSREQ; #endif #ifndef GSSRV_TYPEDEF #define GSSRV_TYPEDEF typedef struct GSSRV_s GSSRV; #endif #ifndef GSview_TYPEDEF #define GSview_TYPEDEF typedef struct GSview_s GSview; #endif #ifndef HISTORY_TYPEDEF #define HISTORY_TYPEDEF typedef struct HISTORY_s HISTORY; #endif #ifndef IMAGE_TYPEDEF #define IMAGE_TYPEDEF typedef struct IMAGE_s IMAGE; #endif #ifndef MEDIA_TYPEDEF #define MEDIA_TYPEDEF typedef struct MEDIA_s MEDIA; #endif #ifndef OPTION_TYPEDEF #define OPTION_TYPEDEF typedef struct OPTION_s OPTION; #endif #ifndef PAGECACHE_TYPEDEF #define PAGECACHE_TYPEDEF typedef struct PAGECACHE_s PAGECACHE; #endif #ifndef PDFLINK_TYPEDEF #define PDFLINK_TYPEDEF typedef struct PDFLINK_s PDFLINK; #endif #ifndef View_TYPEDEF #define View_TYPEDEF typedef struct View_s View; #endif /* Public functions */ /***************************************/ /* Unicode, Multiple Byte Character Set and narrow strings. */ #ifdef UNICODE #define CHARNEXT(x) ((x)+1) #else #define CHARNEXT(x) (global_codepage == CODEPAGE_SBCS ? ((x)+1) : ((x)+char_next(x))) typedef enum { CODEPAGE_SBCS = 0, /* single byte character set */ CODEPAGE_UTF8 = 1, CODEPAGE_EUC = 2, CODEPAGE_SJIS = 3 } CODEPAGE; extern CODEPAGE global_codepage; /* GLOBAL */ int char_next(const char *str); #endif /* convert between cs (wide or multibyte) and narrow strings */ int cs_to_narrow(char *nstr, int nlen, LPCTSTR wstr, int wlen); int narrow_to_cs(TCHAR *wstr, int wlen, const char *nstr, int nlen); /* Implementation that just copies the string */ int char_to_narrow(char *nstr, int nlen, LPCTSTR wstr, int wlen); int narrow_to_char(TCHAR *wstr, int wlen, const char *nstr, int nlen); /* Convert ISO-Latin1 to UTF-8 */ /* Used where unknown text is passed to gtk+ GUI */ int latin1_to_utf8(char *ustr, int ulen, const char *str, int slen); /***************************************/ /* Debugging flags */ #define DEBUG_GENERAL 0x01 #define DEBUG_GDI 0x02 /* GDI printing */ #define DEBUG_MEM 0x04 /* memory allocation */ #define DEBUG_LOG 0x08 /* write gs_addmess() to file c:\gsview.txt */ #define DEBUG_GSINPUT 0x10 /* log all input written to GS */ #define DEBUG_DEV 0x80 /* For debugging */ extern int debug; /* GLOBAL */ /***************************************/ /* Debugging malloc */ /* #define DEBUG_MALLOC */ #ifdef DEBUG_MALLOC # define malloc(x) debug_malloc(x,__FILE__,__LINE__) # define calloc debug_calloc # define realloc debug_realloc # define free debug_free void * debug_malloc(size_t size, const char *file, int line); void * debug_realloc(void *block, size_t size); void debug_free(void *block); void debug_memory_report(void); #endif /***************************************/ /* should put this in cpagelst.h */ typedef struct PAGELIST_s { int current; /* index of current selection */ BOOL multiple; /* true if multiple selection allowed */ int page_count; /* number of entries in select */ BOOL *select; /* array of selection flags */ BOOL reverse; /* reverse pages when extracting or printing */ } PAGELIST; void page_list_free(PAGELIST *page_list); void page_list_copy(PAGELIST *newlist, PAGELIST *oldlist); void page_list_init(PAGELIST *page_list, int pages); /***************************************/ typedef enum ORIENT_e { ORIENT_DEFAULT = -1, /* use PDF/DSC default */ /* following values match setpagedevice /Orientation */ ORIENT_PORTRAIT = 0, ORIENT_LANDSCAPE = 3, ORIENT_UPSIDEDOWN = 2, ORIENT_SEASCAPE = 1 } ORIENT; typedef enum DISPLAY_FORMAT_e { DISPLAY_FORMAT_AUTO = 0, DISPLAY_FORMAT_GREY_1 = 1, DISPLAY_FORMAT_GREY_8 = 2, DISPLAY_FORMAT_COLOUR_4 = 3, DISPLAY_FORMAT_COLOUR_8 = 4, DISPLAY_FORMAT_COLOUR_24 = 5, DISPLAY_FORMAT_CMYK_32 = 6, DISPLAY_FORMAT_COUNT = 7 } DISPLAY_FORMAT; /***************************************/ /* PAGESPEC is used in rendering requests, and to describe * the results of a render. */ typedef struct PAGESPEC_s PAGESPEC; typedef enum PAGESIZE_METHOD_e { PAGESIZE_GIVEN = 0, /* use llx,lly,urx,ury */ PAGESIZE_CROPBOX = 1, /* use PDF crop box */ PAGESIZE_MEDIABOX = 2, /* use PDF media box */ PAGESIZE_VARIABLE = 3 /* default is llx,lly,urx,ury, but allow */ /* user PostScript to change page size */ } PAGESIZE_METHOD; struct PAGESPEC_s { TCHAR filename[MAXSTR]; int page; /* page number */ PAGESIZE_METHOD pagesize; /* If pagesize is not PAGESIZE_GIVEN, then the following dimensions * do not need to be specified on request, but will be filled * in just before rendering. This is because we don't know th * PDF page size until we start rendering. */ float llx; /* Points */ float lly; /* Points */ float urx; /* Points */ float ury; /* Points */ float xddpi; /* display dpi */ float yddpi; /* display dpi */ float xrdpi; /* render dpi */ float yrdpi; /* render dpi */ /* On request, set both req_orient and orient to the desired orientation * After rendering, orient will be set to the actual orientation, * while orient_request may be left as ORIENT_DEFAULT. * This is needed because we don't know the actual PDF orientation * until we start rendering. */ ORIENT orient_request; ORIENT orient; unsigned int format; /* display device format */ int alpha_text; /* 1, 2 or 4 */ int alpha_graphics; /* 1, 2 or 4 */ }; epstool-3.08/src/xdll.c0000644000076400007640000000500010252260054014426 0ustar rjlrjl00000000000000/* Copyright (C) 2000-2002 Ghostgum Software Pty Ltd. All rights reserved. This software is provided AS-IS with no warranty, either express or implied. This software is distributed under licence and may not be copied, modified or distributed except as expressly authorised under the terms of the licence contained in the file LICENCE in this distribution. For more information about licensing, please refer to http://www.ghostgum.com.au/ or contact Ghostsgum Software Pty Ltd, 218 Gallaghers Rd, Glen Waverley VIC 3150, AUSTRALIA, Fax +61 3 9886 6616. */ /* $Id: xdll.c,v 1.3 2003/05/06 13:17:40 ghostgum Exp $ */ /* Unix shared object loading using dlopen */ #include #include #include #include "common.h" #include "cdll.h" /******************************************************************/ static int dll_msg(TCHAR *msg, LPCTSTR str, int msglen) { int len = (int)cslen(str); if (len < msglen){ csncat(msg, str, len); msglen -= len; } return msglen; } /* platform dependent */ /* Load Ghostscript DLL */ int dll_open(GGMODULE *hmodule, LPCTSTR name, TCHAR *msg, int msglen) { char *shortname; char *s; TCHAR buf[MAXSTR]; memset(msg, 0, msglen); msglen = dll_msg(msg, TEXT("Trying to load "), msglen); msglen = dll_msg(msg, name, msglen); msglen = dll_msg(msg, TEXT("\n"), msglen); /* Try to load DLL first with given path */ *hmodule = dlopen(name, RTLD_NOW); if (*hmodule == NULL) { /* failed */ msglen = dll_msg(msg, TEXT(" Failed, "), msglen); msglen = dll_msg(msg, dlerror(), msglen); msglen = dll_msg(msg, TEXT("\n"), msglen); /* try once more, this time on system search path */ memset(buf, 0, sizeof(buf)); strncpy(buf, name, sizeof(buf)-1); s = shortname = buf; while (*s) { if (*s == '/') shortname = s+1; s = CHARNEXT(s); } msglen = dll_msg(msg, TEXT("Trying to load "), msglen); msglen = dll_msg(msg, shortname, msglen); msglen = dll_msg(msg, TEXT("\n"), msglen); *hmodule = dlopen(shortname, RTLD_NOW); if (*hmodule == NULL) { /* failed again */ msglen = dll_msg(msg, TEXT(" Failed, "), msglen); msglen = dll_msg(msg, dlerror(), msglen); msglen = dll_msg(msg, TEXT("\n"), msglen); } } return 0; } /* Unload Ghostscript DLL */ int dll_close(GGMODULE *hmodule) { dlclose(*hmodule); return 0; } dll_proc dll_sym(GGMODULE *hmodule, const char *name) { return (dll_proc)dlsym(*hmodule, name); } /******************************************************************/ epstool-3.08/src/cdoc.c0000644000076400007640000006442210252260054014410 0ustar rjlrjl00000000000000/* Copyright (C) 2001-2005 Ghostgum Software Pty Ltd. All rights reserved. This software is provided AS-IS with no warranty, either express or implied. This software is distributed under licence and may not be copied, modified or distributed except as expressly authorised under the terms of the licence contained in the file LICENCE in this distribution. For more information about licensing, please refer to http://www.ghostgum.com.au/ or contact Ghostsgum Software Pty Ltd, 218 Gallaghers Rd, Glen Waverley VIC 3150, AUSTRALIA, Fax +61 3 9886 6616. */ /* $Id: cdoc.c,v 1.19 2005/06/10 08:45:36 ghostgum Exp $ */ /* Common routines for Doc object */ #include "common.h" #include "dscparse.h" #include "capp.h" #define DEFINE_CDOC #include "cdoc.h" #include "cres.h" typedef enum PclType_e { PCLTYPE_UNKNOWN, PCLTYPE_PCL, PCLTYPE_PXL, PCLTYPE_POSTSCRIPT } PclType; /* private */ static int doc_scan(Doc *doc); /* look for DSC comments */ static int doc_init(Doc *doc); static int doc_gunzip(Doc *doc); static int doc_bunzip2(Doc *doc); static int doc_msg_len(void *handle, const char *str, int len); static PclType doc_pl_parse(const char *str, int len, unsigned int *resolution); static int doc_pl_readline(const char *str, int len); static PclType doc_pjl_parse(const char *str, int len, unsigned int *resolution); /* prototypes */ void doc_message(void *caller_data, const char *str); int show_dsc_error(void *caller_data, CDSC *dsc, unsigned int explanation, const char *line, unsigned int line_len); /* Create a new document object */ Doc * doc_new(GSview *a) { Doc *d = (Doc *)malloc(sizeof(Doc)); if (d == NULL) { app_msg(a, "Out of memory\n"); return_error(NULL); } app_lock(a); doc_init(d); d->app = a; app_ref(a); /* doc has reference to app */ doc_ref(d); /* caller has reference to doc */ app_unlock(a); return d; } /* Add document to application list of documents */ int doc_add(Doc *d, GSview *a) { Doc *dn; app_lock(a); dn = *app_docs(a); while (dn && dn->next) dn = dn->next; if (dn == NULL) *app_docs(a) = d; else dn->next = d; doc_ref(d); /* app has reference to doc */ app_unlock(a); return 0; } /* Remove document from application list */ int doc_remove(Doc *d) { GSview *a = d->app; int code = 0; Doc *dn; app_lock(a); dn = *app_docs(a); if (dn == NULL) { /* not in list */ char str[] = "App has no Doc\n"; /* Doc has already locked app */ app_msg_len_nolock(a, str, (int)strlen(str)); code = -1; } else if (dn == d) { *app_docs(a) = d->next; doc_unref(d); /* app loses reference to doc */ } else { while (dn && dn->next != d) dn = dn->next; if (dn && dn->next == d) { dn->next = d->next; doc_unref(d); /* app loses reference to doc */ } else { char str[] = "Doc not found\n"; /* Doc has already locked app */ app_msg_len_nolock(a, str, (int)strlen(str)); code = -1; } } app_unlock(a); return code; } /* Increment reference count of Doc */ /* A View will increment refcount when it attaches to Doc */ /* Assumes we own the lock */ int doc_ref(Doc *d) { int refcount = ++(d->refcount); if (debug & DEBUG_DEV) { char buf[MAXSTR]; snprintf(buf, sizeof(buf), "doc refcount=%d\n", refcount); buf[sizeof(buf)-1]='\0'; app_msg_len_nolock(d->app, buf, (int)strlen(buf)); } return refcount; } /* Release reference to Doc. */ /* When reference count reaches zero, Doc is freed. */ /* Assumes we own the lock */ int doc_unref(Doc *d) { int refcount; GSview *a = d->app; if (d->refcount > 0) d->refcount--; refcount = d->refcount; if (debug & DEBUG_DEV) { char buf[MAXSTR]; snprintf(buf, sizeof(buf), "doc refcount=%d\n", refcount); buf[sizeof(buf)-1]='\0'; app_msg_len_nolock(d->app, buf, (int)strlen(buf)); } if (d->refcount == 0) { doc_close(d); d->app = NULL; app_unref(a); /* doc loses reference to app */ memset(d, 0, sizeof(Doc)); free(d); } return refcount; } GSview * doc_app(Doc *doc) { return doc->app; } static int doc_init(Doc *doc) { memset(doc, 0, sizeof(Doc)); doc->handle = NULL; doc->app = NULL; doc->next = NULL; doc->viewlist = NULL; doc->doctype = DOC_UNKNOWN; doc->page_count = -1; doc->ignore_dsc = FALSE; doc->dsc_warn = CDSC_ERROR_WARN; doc->verbose = TRUE; return 0; } int doc_close(Doc *doc) { #ifdef NOTUSED /* index of extracted text */ free_text_index(doc); if (doc->text_name[0]) wunlink(doc->text_name); memset(doc->text_name, 0, sizeof(doc->text_name)); #endif /* temporary uncompressed file */ if (doc->tname[0]) csunlink(doc->tname); memset(doc->name, 0, sizeof(doc->name)); memset(doc->tname, 0, sizeof(doc->tname)); doc->doctype = DOC_UNKNOWN; doc->gzip = FALSE; doc->bzip2 = FALSE; doc->page_count = 0; doc->length1 = 0; doc->length2 = 0; doc->time1 = 0; doc->time2 = 0; if (doc->dsc) dsc_unref(doc->dsc); doc->dsc = NULL; #ifdef NOTUSED doc->ignore_special = FALSE; #endif doc->ctrld = FALSE; doc->pjl = FALSE; if (doc->pdfscan) pdf_scan_close(doc->pdfscan); doc->pdfscan = NULL; return 0; } /* Open a new document. * +ve = non DSC * 0 = DSC * -ve = error */ int doc_open(Doc *doc, LPCTSTR filename) { int code; doc_close(doc); csncpy(doc->name, filename, sizeof(doc->name)/sizeof(TCHAR)-1); code = doc_scan(doc); if (code < 0) doc_close(doc); return code; } DocType doc_type(Doc *doc) { return doc->doctype; } BOOL doc_is_open(Doc *doc) { return (doc->name[0] != '\0'); } void doc_ignore_dsc(Doc *doc, BOOL flag) { doc->ignore_dsc = flag; } void doc_dsc_warn(Doc *doc, int level) { doc->dsc_warn = level; } void doc_verbose(Doc *doc, BOOL verbose) { doc->verbose = verbose; } void doc_message(void *caller_data, const char *str) { app_msg(((Doc *)caller_data)->app, str); } /* Debug for DSC comments */ void doc_dump(Doc *doc) { app_csmsgf(doc->app, TEXT("DSC dump for %.200s\n"), doc->name); dsc_display(doc->dsc, doc_message); app_csmsgf(doc->app, TEXT("End of DSC dump\n")); } int show_dsc_error(void *caller_data, CDSC *dsc, unsigned int explanation, const char *line, unsigned int line_len) { Doc *doc = (Doc *)caller_data; int response = CDSC_RESPONSE_CANCEL; int severity; char buf[MAXSTR]; int len; TCHAR title[MAXSTR]; TCHAR linefmt[MAXSTR]; int i; TCHAR *p; if (explanation > dsc->max_error) return CDSC_RESPONSE_OK; severity = dsc->severity[explanation]; /* If debug function provided, copy messages there */ /* These are always in English */ if (dsc->debug_print_fn) { switch (severity) { case CDSC_ERROR_INFORM: dsc_debug_print(dsc, "\nDSC Information"); break; case CDSC_ERROR_WARN: dsc_debug_print(dsc, "\nDSC Warning"); break; case CDSC_ERROR_ERROR: dsc_debug_print(dsc, "\nDSC Error"); break; } dsc_debug_print(dsc, "\n"); if (explanation <= dsc->max_error) { if (line && line_len) { int length = min(line_len, sizeof(buf)-1); snprintf(buf, sizeof(buf), "At line %d:\n", dsc->line_count); buf[sizeof(buf)-1]='\0'; dsc_debug_print(dsc, buf); strncpy(buf, line, length); buf[length]='\0'; dsc_debug_print(dsc, " "); dsc_debug_print(dsc, buf); } dsc_debug_print(dsc, dsc_message[explanation]); } } /* Here you could prompt user for OK, Cancel, Ignore ALL DSC */ if (severity <= doc->dsc_warn) return response; switch (severity) { case CDSC_ERROR_INFORM: i = IDS_DSC_INFO; break; case CDSC_ERROR_WARN: i = IDS_DSC_WARN; break; case CDSC_ERROR_ERROR: i = IDS_DSC_ERROR; break; default: i = -1; } if (i != -1) load_string(doc->app, i, title, sizeof(title)/sizeof(TCHAR)); else title[0] = '\0'; /* build up string */ #define MLEN 4096 p = (TCHAR *)malloc(MLEN*sizeof(TCHAR)); memset(p, 0, MLEN*sizeof(TCHAR)); if (p == (TCHAR *)NULL) return response; if (line) { int len; int wlen; load_string(doc->app, IDS_DSC_LINEFMT, linefmt, sizeof(linefmt)/sizeof(TCHAR)); csnprintf(p, MLEN, linefmt, title, dsc->line_count); csncat(p, TEXT("\n "), MLEN-1-cslen(p)); len = (int)cslen(p); if (line_len > 256) line_len = 256; /* this is the maximum DSC line length */ wlen = narrow_to_cs(NULL, 0, line, line_len); narrow_to_cs(p+len, MLEN-1-len, line, line_len); p[len+wlen] = '\0'; } else { csncpy(p, title, MLEN-1); csncat(p, TEXT("\n"), MLEN-1-cslen(p)); } len = (int)cslen(p); load_string(doc->app, CDSC_RESOURCE_BASE+(explanation*2), p+len, MLEN-len); len = (int)cslen(p); load_string(doc->app, CDSC_RESOURCE_BASE+(explanation*2)+1, p+len, MLEN-len); response = get_dsc_response(doc->app, p); free(p); if (dsc->debug_print_fn) { switch (response) { case CDSC_RESPONSE_OK: dsc_debug_print(dsc, "Response = OK\n"); break; case CDSC_RESPONSE_CANCEL: dsc_debug_print(dsc, "Response = Cancel\n"); break; case CDSC_RESPONSE_IGNORE_ALL: dsc_debug_print(dsc, "Response = Ignore All DSC\n"); break; } } return response; } LPCTSTR doc_name(Doc *doc) { /* If original file was compressed, give name of uncompressed file */ if ((doc->tname[0]!='\0') && ((doc->gzip) || doc->bzip2)) return doc->tname; /* otherwise return original file name */ return doc->name; } /* gunzip to temporary file */ static int doc_gunzip(Doc *doc) { GFile *outfile; int code; char name[MAXSTR+MAXSTR]; if ((outfile = app_temp_gfile(doc->app, doc->tname, sizeof(doc->tname)/sizeof(TCHAR)-1)) == (GFile *)NULL) { TCHAR buf[MAXSTR]; load_string(doc->app, IDS_NOTEMP, buf, sizeof(buf)/sizeof(TCHAR)); app_csmsg(doc->app, buf); return_error(-1); } cs_to_narrow(name, sizeof(name)-1, doc->name, (int)cslen(doc->name)+1); app_msg(doc->app, "Uncompressing "); app_msg(doc->app, name); app_msg(doc->app, " to "); app_csmsg(doc->app, doc->tname); app_msg(doc->app, "\n"); code = zlib_uncompress(doc->app, outfile, name); gfile_close(outfile); if (code != 0) { csunlink(doc->tname); doc->tname[0] = '\0'; return_error(-1); } return 0; } /* Uncompress bzip2 to temporary file */ static int doc_bunzip2(Doc *doc) { GFile *outfile; int code; char name[MAXSTR+MAXSTR]; if ((outfile = app_temp_gfile(doc->app, doc->tname, sizeof(doc->tname)/sizeof(TCHAR)-1)) == (GFile *)NULL) { TCHAR buf[MAXSTR]; load_string(doc->app, IDS_NOTEMP, buf, sizeof(buf)/sizeof(TCHAR)); app_csmsg(doc->app, buf); return_error(-1); } cs_to_narrow(name, sizeof(name)-1, doc->name, (int)cslen(doc->name)+1); app_msg(doc->app, "Uncompressing "); app_msg(doc->app, name); app_msg(doc->app, " to "); app_csmsg(doc->app, doc->tname); app_msg(doc->app, "\n"); code = bzip2_uncompress(doc->app, outfile, name); gfile_close(outfile); if (code != 0) { csunlink(doc->tname); doc->tname[0] = '\0'; return_error(-1); } return 0; } /* Try to recognise PCL files. * PJL starts with * ESC %-12345X * PCL commonly starts with * ESC %, ESC E, ESC *, ESC & * PCLXL commonly starts with * ) HP-PCL XL * If the resolution is not specified, set it to 0. */ static PclType doc_pl_parse(const char *str, int len, unsigned int *resolution) { PclType type; *resolution = 0; if ((len >= 9) && (memcmp(str, "\033%-12345X", 9) == 0)) type = doc_pjl_parse(str, len, resolution); else if ((len >= 11) && (memcmp(str, ") HP-PCL XL", 11) == 0)) type = PCLTYPE_PXL; else if ((len >= 2) && (str[0] == '\033') && ((str[1]=='%') || (str[1]=='E') || (str[1]=='*') || (str[1] == '&'))) type = PCLTYPE_PCL; else type = PCLTYPE_UNKNOWN; return type; } /* Get length of line in buffer. */ static int doc_pl_readline(const char *str, int len) { int i = 0; /* skip until EOL */ while ((i= 9) && (memcmp(p, "\033%-12345X", 9) == 0)) { count -= 9; p += 9; idx += 9; if (count == 0) break; } if (*p != '@') break; /* Not PJL */ if ((count >= 19) && (memcmp(p, "@PJL SET RESOLUTION", 19) == 0)) { i = 19; while ((i= 19) && (memcmp(p, "@PJL ENTER LANGUAGE", 19) == 0)) { i = 19; while ((i= 10) && (memcmp(p+i, "POSTSCRIPT", 10) == 0)) type = PCLTYPE_POSTSCRIPT; else if ((count-i >= 5) && (memcmp(p+i, "PCLXL", 5) == 0)) type = PCLTYPE_PXL; else if ((count-i >= 3) && (memcmp(p+i, "PCL", 3) == 0)) type = PCLTYPE_PCL; } } idx += count; } return type; } /* scan file for PostScript Document Structuring Conventions */ /* return -ve if error */ /* return +ve if not DSC */ /* On return, doc->dsc is non-zero if DSC */ int doc_scan(Doc *doc) { char line[4096]; FILE_POS file_length; GFile *f; CDSC *dsc; PclType pcltype = PCLTYPE_UNKNOWN; if ( (f = gfile_open(doc->name, gfile_modeRead)) == (GFile *)NULL ) { app_msg(doc->app, "File \042"); app_csmsg(doc->app, doc_name(doc)); app_msg(doc->app, "\042 does not exist\n"); return_error(-1); } if (doc->dsc) dsc_unref(doc->dsc); doc->dsc = NULL; /* get first line to look for magic numbers */ memset(line, 0, sizeof(line)); gfile_read(f, line, sizeof(line)-1); gfile_seek(f, 0, gfile_begin); /* check for gzip */ doc->gzip = FALSE; doc->bzip2 = FALSE; if ( (line[0]=='\037') && (line[1]=='\213') ) { /* 1F 8B */ doc->gzip = TRUE; gfile_close(f); if (doc_gunzip(doc) != 0) { app_msg(doc->app, "Failed to gunzip file\n"); return_error(-1); } if ((f = gfile_open(doc_name(doc), gfile_modeRead)) == (GFile *)NULL) { app_msg(doc->app, "File '"); app_csmsg(doc->app, doc_name(doc)); app_msg(doc->app, "' does not exist\n"); return_error(-1); } gfile_read(f, line, sizeof(line)-1); gfile_seek(f, 0, gfile_begin); } /* check for bzip2 */ if ( (line[0]=='B') && (line[1]=='Z') && (line[2]=='h')) { /* "BZh */ doc->bzip2 = TRUE; gfile_close(f); if (doc_bunzip2(doc) != 0) { app_msg(doc->app, "Failed to uncompress bzip2 file\n"); return_error(-1); } if ((f = gfile_open(doc_name(doc), gfile_modeRead)) == (GFile *)NULL) { app_msg(doc->app, "File '"); app_csmsg(doc->app, doc_name(doc)); app_msg(doc->app, "' does not exist\n"); return_error(-1); } gfile_read(f, line, sizeof(line)-1); gfile_seek(f, 0, gfile_begin); } file_length = gfile_get_length(f); /* save file date and length */ doc_savestat(doc); doc->doctype = DOC_UNKNOWN; doc->dpi = 0; /* check for PDF */ if ( strncmp("%PDF-", line, 5) == 0 ) { gfile_close(f); doc->doctype = DOC_PDF; doc->page_count = 0; if (doc->pdfscan) pdf_scan_close(doc->pdfscan); doc->pdfscan = NULL; doc->pdfscan = pdf_scan_open(doc_name(doc), doc->app, doc_msg_len); doc->page_count = pdf_scan_page_count(doc->pdfscan); if (debug & DEBUG_GENERAL) app_msgf(doc->app, "PDF page count %d\n", doc->page_count); return 0; } /* check for PCL */ #ifdef NOTUSED if ((line[0]=='\033') && (line[1]=='E') && (line[2]=='\033')) { TCHAR buf[MAXSTR]; doc->doctype = DOC_PCL; load_string(doc->app, IDS_PROBABLY_PCL, buf, sizeof(buf)/sizeof(TCHAR)); app_msgf(doc->app, "%s\n", buf); if (app_msg_box(doc->app, buf, MB_ICONEXCLAMATION | MB_YESNO) != IDYES) { gfile_close(f); return_error(-1); } } #else pcltype = doc_pl_parse(line, (int)strlen(line), &doc->dpi); if ((pcltype == PCLTYPE_PCL) || (pcltype == PCLTYPE_PXL)) { doc->doctype = DOC_PCL; if (debug & DEBUG_GENERAL) app_msgf(doc->app, "Document is PCL or PXL\n"); gfile_close(f); return 0; } #endif /* check for Windows BMP or NETPBM */ if ( ((line[0]=='B') && (line[1]=='M')) || ((line[0]=='P') && (line[1]>='1') && (line[1]<='6')) || (((unsigned char)line[0]==0x89) && (line[1]=='P') && (line[2]=='N') && (line[3]=='G')) ) { doc->doctype = DOC_BITMAP; doc->page_count = 1; gfile_close(f); return 0; } /* Otherwise, assume it is PostScript */ doc->doctype = DOC_PS; /* check for documents that start with Ctrl-D */ doc->ctrld = (line[0] == '\004'); /* check for HP LaserJet prologue */ doc->pjl = FALSE; if (strncmp("\033%-12345X", line, 9) == 0) doc->pjl = TRUE; if (doc->ignore_dsc) doc->dsc = (CDSC *)NULL; else { int code = 0; int count; char *d; doc->dsc = NULL; if ( (d = (char *) malloc(COPY_BUF_SIZE)) == NULL) return_error(-1); doc->dsc = dsc_new(doc); if (doc->verbose) dsc_set_debug_function(doc->dsc, doc_message); dsc_set_error_function(doc->dsc, show_dsc_error); dsc_set_length(doc->dsc, file_length); while ((count = (int)gfile_read(f, d, COPY_BUF_SIZE))!=0) { code = dsc_scan_data(doc->dsc, d, count); if ((code == CDSC_ERROR) || (code == CDSC_NOTDSC)) { /* not DSC or an error */ break; } } if ((code == CDSC_ERROR) || (code == CDSC_NOTDSC)) { dsc_unref(doc->dsc); doc->dsc = NULL; } else { dsc_fixup(doc->dsc); } free(d); } gfile_close(f); /* check for DSC comments */ dsc = doc->dsc; if (dsc == (CDSC *)NULL) return 1; /* OK, but not DSC */ if (dsc->doseps) { BOOL bad_header = FALSE; /* check for errors in header */ if (dsc->doseps->ps_begin > file_length) bad_header = TRUE; if (dsc->doseps->ps_begin + dsc->doseps->ps_length > file_length) bad_header = TRUE; if (dsc->doseps->wmf_begin > file_length) bad_header = TRUE; if (dsc->doseps->wmf_begin + dsc->doseps->wmf_length > file_length) bad_header = TRUE; if (dsc->doseps->tiff_begin > file_length) bad_header = TRUE; if (dsc->doseps->tiff_begin + dsc->doseps->tiff_length > file_length) bad_header = TRUE; if (bad_header) { TCHAR buf[MAXSTR]; load_string(doc->app, IDS_BAD_DOSEPS_HEADER, buf, sizeof(buf)/sizeof(TCHAR)); app_csmsgf(doc->app, TEXT("%s\n"), buf); app_msg_box(doc->app, buf, 0); /* Ignore the bad information */ dsc_unref(doc->dsc); doc->dsc = NULL; return_error(-1); } } if (debug & DEBUG_GENERAL) doc_dump(doc); return 0; } /* reverse zero based page number if needed */ int doc_map_page(Doc *doc, int page) { if (doc->dsc != (CDSC *)NULL) if (doc->dsc->page_order == CDSC_DESCEND) return (doc->dsc->page_count - 1) - page; return page; } int doc_page_limit(Doc *doc, int page) { if (doc == NULL) return 0; if (doc->doctype == DOC_PS) { if (doc->dsc) { if (page >= (int)doc->dsc->page_count) page = doc->dsc->page_count - 1; if (page < 0) page = 0; } else if (doc->page_count) { if (page >= (int)doc->page_count) page = doc->page_count - 1; } } else if (doc->doctype == DOC_PDF) { if (page >= (int)doc->page_count) page = doc->page_count - 1; if (page < 0) page = 0; } else if (doc->doctype == DOC_BITMAP) page = 0; return page; } View ** doc_views(Doc *doc) { return &doc->viewlist; } /* append to a string in a buffer of length len */ static TCHAR * csappend(LPTSTR dest, LPCTSTR src, int len) { return csncat(dest, src, len - (int)cslen(dest)/sizeof(TCHAR) - 1); } /* Information about a document, suitable for showing in a dialog */ void doc_info(Doc *doc, DocInfo *info) { TCHAR buf[MAXSTR]; CDSC *dsc = doc->dsc; int typelen; memset(info, 0, sizeof(DocInfo)); if (cslen(doc->name)) csncpy(info->name, doc->name, sizeof(info->name)/sizeof(TCHAR)); else load_string(doc->app, IDS_NOFILE, info->name, sizeof(info->name)/sizeof(TCHAR)); typelen = sizeof(info->type)/sizeof(TCHAR); if (doc->gzip) csappend(info->type, TEXT("gzip "), typelen); if (doc->bzip2) csappend(info->type, TEXT("bzip2 "), typelen); if (dsc) { load_string(doc->app, IDS_CTRLD, buf, sizeof(buf)/sizeof(TCHAR)); if (doc->ctrld) csappend(info->type, buf, typelen); load_string(doc->app, IDS_PJL, buf, sizeof(buf)/sizeof(TCHAR)); if (doc->pjl) csappend(info->type, buf, typelen); load_string(doc->app, IDS_DCS2, buf, sizeof(buf)/sizeof(TCHAR)); if (dsc->dcs2) csappend(info->type, buf, typelen); if (dsc->epsf) { switch(dsc->preview) { default: case CDSC_NOPREVIEW: buf[0] = '\0'; break; case CDSC_EPSI: load_string(doc->app, IDS_EPSI, buf, sizeof(buf)/sizeof(TCHAR)); break; case CDSC_TIFF: load_string(doc->app, IDS_EPST, buf, sizeof(buf)/sizeof(TCHAR)); break; case CDSC_WMF: load_string(doc->app, IDS_EPSW, buf, sizeof(buf)/sizeof(TCHAR)); break; } csappend(info->type, buf, typelen); } else { load_string(doc->app, IDS_DSC, buf, sizeof(buf)/sizeof(TCHAR)); csappend(info->type, buf, typelen); } if (dsc->dsc_title) narrow_to_cs(info->title, sizeof(info->title)/sizeof(TCHAR)-1, dsc->dsc_title, (int)strlen(dsc->dsc_title)+1); if (dsc->dsc_date) narrow_to_cs(info->date, sizeof(info->date)/sizeof(TCHAR)-1, dsc->dsc_date, (int)strlen(dsc->dsc_date)+1); if (dsc->bbox) { csnprintf(buf, sizeof(buf)/sizeof(TCHAR), TEXT("%d %d %d %d"), dsc->bbox->llx, dsc->bbox->lly, dsc->bbox->urx, dsc->bbox->ury); buf[sizeof(buf)-1]='\0'; csncpy(info->bbox, buf, sizeof(info->bbox)/sizeof(TCHAR)); } if (dsc->hires_bbox) { csnprintf(buf, sizeof(buf)/sizeof(TCHAR), TEXT("%g %g %g %g"), dsc->hires_bbox->fllx, dsc->hires_bbox->flly, dsc->hires_bbox->furx, dsc->hires_bbox->fury); buf[sizeof(buf)-1]='\0'; csncpy(info->hiresbbox, buf, sizeof(info->hiresbbox)/sizeof(TCHAR)); } switch (dsc->page_orientation) { case CDSC_PORTRAIT: load_string(doc->app, IDS_PORTRAIT, info->orientation, sizeof(info->orientation)/sizeof(TCHAR)); break; case CDSC_LANDSCAPE: load_string(doc->app, IDS_LANDSCAPE, info->orientation, sizeof(info->orientation)/sizeof(TCHAR)); break; } switch (dsc->page_order) { case CDSC_ASCEND: load_string(doc->app, IDS_ASCEND, info->pageorder, sizeof(info->pageorder)/sizeof(TCHAR)); break; case CDSC_DESCEND: load_string(doc->app, IDS_LANDSCAPE, info->pageorder, sizeof(info->pageorder)/sizeof(TCHAR)); break; case CDSC_SPECIAL: load_string(doc->app, IDS_SPECIAL, info->pageorder, sizeof(info->pageorder)/sizeof(TCHAR)); break; } if (dsc->page_media && dsc->page_media->name) { int wlen = narrow_to_cs(buf, (int)sizeof(buf)/sizeof(TCHAR), dsc->page_media->name, (int)strlen(dsc->page_media->name)+1); csnprintf(buf+wlen, sizeof(buf)/sizeof(TCHAR)-wlen, TEXT(" %g %g"), dsc->page_media->width, dsc->page_media->height); buf[sizeof(buf)-1]='\0'; } else { buf[0] = '\0'; } csncpy(info->pagemedia, buf, sizeof(info->pages)/sizeof(TCHAR)); csnprintf(buf, sizeof(buf)/sizeof(TCHAR), TEXT("%d"), dsc->page_count); buf[sizeof(buf)-1]='\0'; csncpy(info->pages, buf, sizeof(info->pages)/sizeof(TCHAR)); } else if (doc->doctype == DOC_PDF) { load_string(doc->app, IDS_PDF, buf, sizeof(buf)/sizeof(TCHAR)); csappend(info->type, buf, typelen); csnprintf(buf, sizeof(buf)/sizeof(TCHAR), TEXT("%d"), doc->page_count); buf[sizeof(buf)-1]='\0'; csncpy(info->pages, buf, sizeof(info->pages)/sizeof(TCHAR)); } } /* Generate string for page list box, as either * ordinal * ordinal "label" */ void doc_ordlabel(Doc *doc, char *buf, int buflen, int page_number) { if (doc->doctype == DOC_PDF) { snprintf(buf, buflen, "%d", page_number+1); } else if (doc->dsc) { const char *label; int ordinal; label = doc->dsc->page[doc_map_page(doc, page_number)].label; ordinal = doc->dsc->page[doc_map_page(doc, page_number)].ordinal; snprintf(buf, buflen, "%d", ordinal); if (strcmp(buf, label) != 0) { /* label and ordinal don't match, so use composite */ snprintf(buf, buflen, "%d \042%s\042", ordinal, label); } } } static int doc_msg_len(void *handle, const char *str, int len) { return app_msg_len((GSview *)handle, str, len); } /* Copy document unmodified */ int doc_copyfile(Doc *doc, LPCTSTR filename) { GFile *infile, *outfile; int code = 0; char *buf; int count = 0; buf = (char *)malloc(COPY_BUF_SIZE); if (buf == (char *)NULL) return -1; if ((infile = gfile_open(doc_name(doc), gfile_modeRead)) == (GFile *)NULL){ app_msg(doc->app, "File \042"); app_csmsg(doc->app, doc_name(doc)); app_msg(doc->app, "\042 does not exist\n"); free(buf); return_error(-1); } if ((outfile = gfile_open(filename, gfile_modeWrite | gfile_modeCreate)) == (GFile *)NULL) { app_msg(doc->app, "File \042"); app_csmsg(doc->app, filename); app_msg(doc->app, "\042 can not be opened for writing\n"); free(buf); gfile_close(infile); return_error(-1); } while (((count = (int)gfile_read(infile, buf, COPY_BUF_SIZE)) > 0)) if ((int)gfile_write(outfile, buf, count) != count) break; free(buf); if (gfile_error(infile)!=0) code = -1; if (gfile_error(outfile)!=0) code = -1; gfile_close(outfile); gfile_close(infile); if (code && !(debug & DEBUG_GENERAL)) csunlink(filename); return code; } epstool-3.08/src/common.mak0000644000076400007640000002543510252260054015317 0ustar rjlrjl00000000000000# Copyright (C) 2002-2005 Ghostgum Software Pty Ltd. All rights reserved. # # This software is provided AS-IS with no warranty, either express or # implied. # # This software is distributed under licence and may not be copied, # modified or distributed except as expressly authorised under the terms # of the licence contained in the file LICENCE in this distribution. # # For more information about licensing, please refer to # http://www.ghostgum.com.au/ or contact Ghostsgum Software Pty Ltd, # 218 Gallaghers Rd, Glen Waverley VIC 3150, AUSTRALIA, # Fax +61 3 9886 6616. # # $Id: common.mak,v 1.34 2005/06/10 09:39:24 ghostgum Exp $ # Common makefile for GSview # Used by all clients OBJCOM1=$(OD)calloc$(OBJ) $(OD)capp$(OBJ) \ $(OD)cbmp$(OBJ) $(OD)cdoc$(OBJ) $(OD)ceps$(OBJ) \ $(OD)cimg$(OBJ) $(OD)clzw$(OBJ) \ $(OD)cmac$(OBJ) $(OD)cmbcs$(OBJ) $(OD)cpdfscan$(OBJ) \ $(OD)cprofile$(OBJ) $(OD)cps$(OBJ) \ $(OD)dscparse$(OBJ) $(OD)dscutil$(OBJ) # Used by simple viewer OBJCOM2=$(OD)cdisplay$(OBJ) $(OD)cgsdll$(OBJ) \ $(OD)cgssrv$(OBJ) $(OD)chist$(OBJ) \ $(OD)copt$(OBJ) $(OD)cpagec$(OBJ) $(OD)cpdf$(OBJ) \ $(OD)cpldll$(OBJ) $(OD)cplsrv$(OBJ) \ $(OD)cview$(OBJ) # Used by complex viewer OBJCOM3=$(OD)cargs$(OBJ) $(OD)ccoord$(OBJ) $(OD)cvcmd$(OBJ) OBJS=$(OBJCOM1) $(OBJCOM2) $(OBJCOM3) $(OBJPLAT) EPSTOOL_VERSION=3.08 EPSTOOL_DATE=2005-06-10 EPSOBJS=$(EPSOBJPLAT) \ $(OD)epstool$(OBJ) \ $(OBJCOM1) EPSTESTOBJS=$(EPSOBJPLAT) \ $(OD)epstest$(OBJ) \ $(OD)cbmp$(OBJ) \ $(OD)cimg$(OBJ) $(OD)clzw$(OBJ) cplat_h=$(SRC)cplat.h cfile_h=$(SRC)cfile.h common_h=$(SRC)common.h $(cplat_h) $(cfile_h) capp_h=$(SRC)capp.h cargs_h=$(SRC)cargs.h cbmp_h=$(SRC)cbmp.h cdisplay_h=$(SRC)cdisplay.h cdll_h=$(SRC)cdll.h cdoc_h=$(SRC)cdoc.h ceps_h=$(SRC)ceps.h cmac_h=$(SRC)cmac.h cgsdll_h=$(SRC)cgsdll.h cgssrv_h=$(SRC)cgssrv.h chist_h=$(SRC)chist.h cimg_h=$(SRC)cimg.h clzw_h=$(SRC)clzw.h cmsg_h=$(SRC)cmsg.h copt_h=$(SRC)copt.h cpagec_h=$(SRC)cpagec.h cpdf_h=$(SRC)cpdf.h cpdfscan_h=$(SRC)cpdfscan.h cpldll_h=$(SRC)cpldll.h cprofile_h=$(SRC)cprofile.h cps_h=$(SRC)cps.h cres_h=$(SRC)cres.h cvcmd_h=$(SRC)cvcmd.h cver_h=$(SRC)cver.h cview_h=$(SRC)cview.h dscparse_h=$(SRC)dscparse.h errors_h=$(SRC)errors.h gdevdsp_h=$(SRC)gdevdsp.h iapi_h=$(SRC)iapi.h plapis_h=$(SRC)plapis.h all: $(BEGIN) $(TARGET) $(OD)calloc$(OBJ): $(SRC)calloc.c $(common_h) $(COMP) $(FOO)calloc$(OBJ) $(CO) $(SRC)calloc.c $(OD)capp$(OBJ): $(SRC)capp.c $(common_h) $(dscparse_h) $(copt_h) \ $(capp_h) $(cdll_h) $(cgssrv_h) $(cimg_h) $(cpagec_h) $(cprofile_h) \ $(cres_h) $(COMP) $(FOO)capp$(OBJ) $(CO) $(SRC)capp.c $(OD)cargs$(OBJ): $(SRC)cargs.c $(common_h) $(dscparse_h) $(capp_h) \ $(cargs_h) $(copt_h) $(cview_h) $(COMP) $(FOO)cargs$(OBJ) $(CO) $(SRC)cargs.c $(OD)cbmp$(OBJ): $(SRC)cbmp.c $(common_h) $(gdevdsp_h) $(cimg_h) $(COMP) $(LIBPNGINC) $(FOO)cbmp$(OBJ) $(CO) $(SRC)cbmp.c $(OD)ccoord$(OBJ): $(SRC)ccoord.c $(common_h) $(gdevdsp_h) $(cpagec_h) $(COMP) $(FOO)ccoord$(OBJ) $(CO) $(SRC)ccoord.c $(OD)cdisplay$(OBJ): $(SRC)cdisplay.c $(common_h) $(gdevdsp_h) $(errors_h) \ $(capp_h) $(cimg_h) $(cdisplay_h) $(cgssrv_h) $(cmsg_h) $(COMP) $(FOO)cdisplay$(OBJ) $(CO) $(SRC)cdisplay.c $(OD)cdoc$(OBJ): $(SRC)cdoc.c $(common_h) $(dscparse_h) $(capp_h) \ $(cdoc_h) $(cpdfscan_h) $(cres_h) $(COMP) $(FOO)cdoc$(OBJ) $(CO) $(SRC)cdoc.c $(OD)ceps$(OBJ): $(SRC)ceps.c $(common_h) $(dscparse_h) \ $(gdevdsp_h) $(capp_h) $(cbmp_h) $(cdoc_h) $(ceps_h) $(cimg_h) \ $(cmac_h) $(cpdfscan_h) $(cps_h) $(COMP) $(FOO)ceps$(OBJ) $(CO) $(SRC)ceps.c $(OD)cfile$(OBJ): $(SRC)cfile.c $(SRC)cfile.h $(COMP) $(FOO)cfile$(OBJ) $(CO) $(SRC)cfile.c $(OD)clfile$(OBJ): $(SRC)clfile.c $(SRC)cfile.h $(COMP) $(FOO)clfile$(OBJ) $(CO) $(SRC)clfile.c $(OD)cgsdll$(OBJ): $(SRC)cgsdll.c $(common_h) $(errors_h) $(iapi_h) \ $(capp_h) $(cdll_h) $(cgsdll_h) $(COMP) $(FOO)cgsdll$(OBJ) $(CO) $(SRC)cgsdll.c $(OD)cgssrv$(OBJ): $(SRC)cgssrv.c $(common_h) $(dscparse_h) \ $(errors_h) $(iapi_h) \ $(capp_h) $(cdll_h) $(cimg_h) $(copt_h) $(cdisplay_h) $(cdoc_h) \ $(cgsdll_h) $(cmsg_h) $(cpdf_h) $(cpdfscan_h) $(cview_h) $(cgssrv_h) $(COMP) $(FOO)cgssrv$(OBJ) $(CO) $(SRC)cgssrv.c $(OD)chist$(OBJ): $(SRC)chist.c $(common_h) $(chist_h) $(COMP) $(FOO)chist$(OBJ) $(CO) $(SRC)chist.c $(OD)cimg$(OBJ): $(SRC)cimg.c $(common_h) $(gdevdsp_h) $(cimg_h) $(clzw_h) $(COMP) $(FOO)cimg$(OBJ) $(CO) $(SRC)cimg.c $(OD)clzw$(OBJ): $(SRC)clzw.c $(clzw_h) $(COMP) $(FOO)clzw$(OBJ) $(CO) $(SRC)clzw.c $(OD)cmac$(OBJ): $(SRC)cmac.c $(cmac_h) $(common_h) $(COMP) $(FOO)cmac$(OBJ) $(CO) $(SRC)cmac.c $(OD)cmbcs$(OBJ): $(SRC)cmbcs.c $(common_h) $(COMP) $(FOO)cmbcs$(OBJ) $(CO) $(SRC)cmbcs.c $(OD)copt$(OBJ): $(SRC)copt.c $(common_h) $(dscparse_h) $(copt_h) $(cprofile_h) $(COMP) $(FOO)copt$(OBJ) $(CO) $(SRC)copt.c $(OD)cpagec$(OBJ): $(SRC)cpagec.c $(common_h) $(dscparse_h) \ $(capp_h) $(cgssrv_h) $(cimg_h) $(cpagec_h) $(cpdf_h) $(cview_h) $(COMP) $(FOO)cpagec$(OBJ) $(CO) $(SRC)cpagec.c $(OD)cpdf$(OBJ): $(SRC)cpdf.c $(common_h) $(dscparse_h) \ $(capp_h) $(cpdf_h) $(cgssrv_h) $(cview_h) $(COMP) $(FOO)cpdf$(OBJ) $(CO) $(SRC)cpdf.c $(OD)cpdfscan$(OBJ): $(SRC)cpdfscan.c $(common_h) $(dscparse_h) \ $(capp_h) $(cpdfscan_h) $(COMP) $(FOO)cpdfscan$(OBJ) $(CO) $(SRC)cpdfscan.c $(OD)cpldll$(OBJ): $(SRC)cpldll.c $(common_h) $(errors_h) $(iapi_h) \ $(capp_h) $(cdll_h) $(cpldll_h) $(COMP) $(FOO)cpldll$(OBJ) $(CO) $(SRC)cpldll.c $(OD)cplsrv$(OBJ): $(SRC)cplsrv.c $(common_h) $(dscparse_h) \ $(errors_h) $(iapi_h) \ $(capp_h) $(cdll_h) $(cimg_h) $(copt_h) $(cdisplay_h) $(cdoc_h) \ $(cgsdll_h) $(cmsg_h) $(cpdf_h) $(cpdfscan_h) $(cview_h) $(cgssrv_h) $(COMP) $(FOO)cplsrv$(OBJ) $(CO) $(SRC)cplsrv.c $(OD)cprofile$(OBJ): $(SRC)cprofile.c $(cplat_h) $(cprofile_h) $(COMP) $(FOO)cprofile$(OBJ) $(CO) $(SRC)cprofile.c $(OD)cps$(OBJ): $(SRC)cps.c $(common_h) $(dscparse_h) \ $(capp_h) $(cdoc_h) $(COMP) $(FOO)cps$(OBJ) $(CO) $(SRC)cps.c $(OD)cvcmd$(OBJ): $(SRC)cvcmd.c $(common_h) $(dscparse_h) \ $(copt_h) $(capp_h) $(cdoc_h) $(cgssrv_h) $(chist_h) \ $(cmsg_h) $(cpdfscan_h) $(cps_h) $(cres_h) $(cvcmd_h) $(cview_h) $(COMP) $(FOO)cvcmd$(OBJ) $(CO) $(SRC)cvcmd.c $(OD)cview$(OBJ): $(SRC)cview.c $(common_h) $(dscparse_h) \ $(capp_h) $(cdoc_h) $(cgssrv_h) $(chist_h) $(cimg_h) \ $(cmsg_h) $(copt_h) $(cpagec_h) $(cpdf_h) $(cpdfscan_h) $(cres_h) \ $(cvcmd_h) $(cview_h) $(COMP) $(FOO)cview$(OBJ) $(CO) $(SRC)cview.c $(OD)dscparse$(OBJ): $(SRC)dscparse.c $(dscparse_h) $(COMP) $(FOO)dscparse$(OBJ) $(CO) $(SRC)dscparse.c $(OD)dscutil$(OBJ): $(SRC)dscutil.c $(dscparse_h) $(COMP) $(FOO)dscutil$(OBJ) $(CO) $(SRC)dscutil.c $(BD)epstool$(EXE): $(OD)lib.rsp $(EPSOBJS) $(CLINK) $(FE)$(BD)epstool$(EXE) $(EPSOBJS) $(EPSLIB) $(OD)epstool$(OBJ): $(SRC)epstool.c $(SRC)common.mak \ $(common_h) $(copt_h) $(capp_h) $(cbmp_h) $(cdoc_h) $(cdll_h) \ $(ceps_h) $(cimg_h) $(cmac_h) $(cps_h) $(cres_h) \ $(dscparse_h) $(errors_h) $(iapi_h) $(gdevdsp_h) $(COMP) $(FOO)epstool$(OBJ) $(CO) -DEPSTOOL_VERSION="$(EPSTOOL_VERSION)" -DEPSTOOL_DATE="$(EPSTOOL_DATE)" $(SRC)epstool.c $(BD)epstest$(EXE): $(OD)lib.rsp $(EPSTESTOBJS) $(CLINK) $(FE)$(BD)epstest$(EXE) $(EPSTESTOBJS) $(EPSLIB) $(OD)epstest$(OBJ): $(SRC)epstest.c $(SRC)common.mak \ $(common_h) $(copt_h) $(capp_h) $(cbmp_h) $(cdoc_h) $(cdll_h) \ $(ceps_h) $(cimg_h) $(cmac_h) $(cps_h) $(cres_h) \ $(dscparse_h) $(errors_h) $(iapi_h) $(gdevdsp_h) $(COMP) $(FOO)epstest$(OBJ) $(CO) $(SRC)epstest.c $(BD)dscparse$(EXE): (OD)dscparse$(OBJ) $(SRC)dscutil.c $(CC) $(CFLAGS) $(GSCFLAGS) -DSTANDALONE $(FOO)dscutils$(OBJ) $(CO) $(SRC)dscutil.c $(CLINK) $(CFLAGS) $(GSCFLAGS) $(FEO)dscparse$(EXE) $(OD)dscparse$(OBJ) $(OD)dscutils$(OBJ) # X11/gtk+ specific $(OD)xdll$(OBJ): $(SRC)xdll.c $(common_h) $(cdll_h) $(COMP) $(FOO)xdll$(OBJ) $(CO) $(SRC)xdll.c $(OD)xnodll$(OBJ): $(SRC)xnodll.c $(common_h) $(cdll_h) $(COMP) $(FOO)xnodll$(OBJ) $(CO) $(SRC)xnodll.c # Build distribution files for epstool EPSDIST=epstool-$(EPSTOOL_VERSION) EPSZIP=epstool-$(EPSTOOL_VERSION).zip EPSTAR=epstool-$(EPSTOOL_VERSION).tar EPSTARGZ=$(EPSTAR).gz epssrc: -$(RMDIR) $(EPSDIST) -mkdir $(EPSDIST) -mkdir $(EPSDIST)$(DD)$(SRCDIR) -mkdir $(EPSDIST)$(DD)$(SRCWINDIR) -mkdir $(EPSDIST)$(DD)doc $(CP) $(SRC)calloc.* $(EPSDIST)$(DD)$(SRCDIR) $(CP) $(SRC)capp.* $(EPSDIST)$(DD)$(SRCDIR) $(CP) $(SRC)cargs.h $(EPSDIST)$(DD)$(SRCDIR) $(CP) $(SRC)cbmp.* $(EPSDIST)$(DD)$(SRCDIR) $(CP) $(SRC)cdll.h $(EPSDIST)$(DD)$(SRCDIR) $(CP) $(SRC)cdoc.* $(EPSDIST)$(DD)$(SRCDIR) $(CP) $(SRC)ceps.* $(EPSDIST)$(DD)$(SRCDIR) $(CP) $(SRC)cfile.* $(EPSDIST)$(DD)$(SRCDIR) $(CP) $(SRC)clfile.* $(EPSDIST)$(DD)$(SRCDIR) $(CP) $(SRC)clzw.* $(EPSDIST)$(DD)$(SRCDIR) $(CP) $(SRC)cgssrv.h $(EPSDIST)$(DD)$(SRCDIR) $(CP) $(SRC)cimg.* $(EPSDIST)$(DD)$(SRCDIR) $(CP) $(SRC)cmac.* $(EPSDIST)$(DD)$(SRCDIR) $(CP) $(SRC)cmbcs.* $(EPSDIST)$(DD)$(SRCDIR) $(CP) $(SRC)common.h $(EPSDIST)$(DD)$(SRCDIR) $(CP) $(SRC)copt.h $(EPSDIST)$(DD)$(SRCDIR) $(CP) $(SRC)cpagec.h $(EPSDIST)$(DD)$(SRCDIR) $(CP) $(SRC)cpdfscan.* $(EPSDIST)$(DD)$(SRCDIR) $(CP) $(SRC)cplat.h $(EPSDIST)$(DD)$(SRCDIR) $(CP) $(SRC)cprofile.* $(EPSDIST)$(DD)$(SRCDIR) $(CP) $(SRC)cps.* $(EPSDIST)$(DD)$(SRCDIR) $(CP) $(SRC)cres.h $(EPSDIST)$(DD)$(SRCDIR) $(CP) $(SRC)dscparse.* $(EPSDIST)$(DD)$(SRCDIR) $(CP) $(SRC)dscutil.c $(EPSDIST)$(DD)$(SRCDIR) $(CP) $(SRC)epstool.c $(EPSDIST)$(DD)$(SRCDIR) $(CP) $(SRC)epstool.mak $(EPSDIST)$(DD)$(SRCDIR) $(CP) $(SRC)errors.h $(EPSDIST)$(DD)$(SRCDIR) $(CP) $(SRC)iapi.h $(EPSDIST)$(DD)$(SRCDIR) $(CP) $(SRC)gdevdsp.h $(EPSDIST)$(DD)$(SRCDIR) $(CP) $(SRC)xdll.c $(EPSDIST)$(DD)$(SRCDIR) $(CP) $(SRC)xnodll.c $(EPSDIST)$(DD)$(SRCDIR) $(CP) $(SRC)common.mak $(EPSDIST)$(DD)$(SRCDIR) $(CP) $(SRC)os2.mak $(EPSDIST)$(DD)$(SRCDIR) $(CP) $(SRC)unix.mak $(EPSDIST)$(DD)$(SRCDIR) $(CP) $(SRC)unixcom.mak $(EPSDIST)$(DD)$(SRCDIR) $(CP) $(SRC)epstool.spec $(EPSDIST)$(DD)$(SRCDIR) $(CP) $(SRCWIN)wdll.c $(EPSDIST)$(DD)$(SRCWIN) $(CP) $(SRCWIN)wfile.c $(EPSDIST)$(DD)$(SRCWIN) $(CP) $(SRCWIN)wgsver.c $(EPSDIST)$(DD)$(SRCWIN) $(CP) $(SRCWIN)wgsver.h $(EPSDIST)$(DD)$(SRCWIN) $(CP) $(SRCWIN)windows.mak $(EPSDIST)$(DD)$(SRCWIN) $(CP) $(SRCWIN)epstool.mak $(EPSDIST)$(DD)$(SRCWIN) $(CP) doc$(DD)epstool.htm $(EPSDIST)$(DD)doc $(CP) doc$(DD)epstool.1 $(EPSDIST)$(DD)doc $(CP) doc$(DD)gsview.css $(EPSDIST)$(DD)doc $(CP) doc$(DD)cygwin.README $(EPSDIST)$(DD)doc $(CP) doc$(DD)cygwin.hint $(EPSDIST)$(DD)doc $(CP) $(SRC)epstool.mak $(EPSDIST)$(DD)makefile echo "Documentation for epstool is in doc/epstool.htm" > epstool.txt $(CP) epstool.txt $(EPSDIST)$(DD)epstool.txt $(CP) LICENCE $(EPSDIST) $(EPSZIP): epssrc $(BD)epstool$(EXE) $(CP) $(SRCWIN)epstool.mak $(EPSDIST)$(DD)makefile -$(RM) $(EPSZIP) -mkdir $(EPSDIST)$(DD)bin $(CP) $(BD)epstool$(EXE) $(EPSDIST)$(DD)bin$(DD)epstool$(EXE) zip -r -X -9 $(EPSZIP) $(EPSDIST) epszip: $(EPSZIP) $(EPSTAR): epssrc -$(RM) $(EPSTAR) tar -cvf $(EPSTAR) $(EPSDIST) $(EPSTARGZ): $(EPSTAR) -$(RM) $(EPSTARGZ) gzip $(EPSTAR) epstar: $(EPSTARGZ) epstool-3.08/src/unixcom.mak0000644000076400007640000000255710252260054015511 0ustar rjlrjl00000000000000# Copyright (C) 2002-2005 Ghostgum Software Pty Ltd. All rights reserved. # # This software is provided AS-IS with no warranty, either express or # implied. # # This software is distributed under licence and may not be copied, # modified or distributed except as expressly authorised under the terms # of the licence contained in the file LICENCE in this distribution. # # For more information about licensing, please refer to # http://www.ghostgum.com.au/ or contact Ghostsgum Software Pty Ltd, # 218 Gallaghers Rd, Glen Waverley VIC 3150, AUSTRALIA, # Fax +61 3 9886 6616. # # $Id: unixcom.mak,v 1.2 2005/01/11 11:40:19 ghostgum Exp $ # Unix common makefile INSTALL=install -m 644 INSTALL_EXE=install -m 755 MAKE=make CDEFS=-DX11 -DUNIX -DNONAG $(LONGFILEDEF) GSCDEBUG= -g GSCFLAGS= $(CDEFS) -Wall -Wstrict-prototypes -Wmissing-declarations -Wmissing-prototypes -fno-builtin -fno-common -Wcast-qual -Wwrite-strings $(CDEBUG) $(GSCDEBUG) $(RPM_OPT_FLAGS) $(XINCLUDE) $(PFLAGS) $(LIBPNGCFLAGS) $(GTKCFLAGS) CCAUX=gcc CC=gcc LFLAGS=$(PLINK) $(LIBPNGLIBS) $(GTKLIBS) CLINK=gcc $(LDFLAGS) LINK=gcc $(LDFLAGS) COMP=$(CC) -I$(SRCDIR) -I$(OBJDIR) $(CFLAGS) $(GSCFLAGS) NUL= DD=/$(NUL) SRC=$(SRCDIR)/$(NUL) SRCWIN=$(SRCWINDIR)/$(NUL) OD=$(OBJDIR)/$(NUL) BD=$(BINDIR)/$(NUL) OBJ=.o EXE= CO=-c FE=-o $(NUL) FO=-o $(NUL) FEO=-o $(OD) FOO=-o $(OD) CP=cp -f RM=rm -f RMDIR=rm -rf epstool-3.08/src/cmac.c0000644000076400007640000006737010252260054014410 0ustar rjlrjl00000000000000/* Copyright (C) 2003-2005 Ghostgum Software Pty Ltd. All rights reserved. This software is provided AS-IS with no warranty, either express or implied. This software is distributed under licence and may not be copied, modified or distributed except as expressly authorised under the terms of the licence contained in the file LICENCE in this distribution. For more information about licensing, please refer to http://www.ghostgum.com.au/ or contact Ghostsgum Software Pty Ltd, 218 Gallaghers Rd, Glen Waverley VIC 3150, AUSTRALIA, Fax +61 3 9886 6616. */ /* $Id: cmac.c,v 1.11 2005/06/10 09:39:24 ghostgum Exp $ */ /* Macintosh AppleSingle, AppleDouble and MacBinary file formats */ /* Macintosh does not use a flat file system. * Each file can have a data fork and a resource fork. * EPSF files have the PostScript in the data fork, * optionally have a PICT preview in the resource fork. * In addition, finder info gives the file type using FOURCC codes * such as "EPSF" or "PICT". * When files are copied to foreign file systems, the resource * fork may be left behind. Alternatives to retain the resource * fork are to package the finder data, data fork and resource fork * in a single MacBinary or AppleSingle file, * or to put the data fork in a flat file and the finder info * and resource fork in an AppleDouble file. */ #include "common.h" #include #include "cmac.h" static int extract_mac_data(GFile *f, LPCTSTR outname, unsigned long begin, unsigned long length, unsigned long header); DWORD get_bigendian_dword(const unsigned char *buf) { DWORD dw; dw = ((DWORD)buf[0])<<24; dw += ((DWORD)buf[1])<<16; dw += ((DWORD)buf[2])<<8; dw += (DWORD)buf[3]; return dw; } WORD get_bigendian_word(const unsigned char *buf) { WORD w; w = (WORD)(buf[0]<<8); w |= (WORD)buf[1]; return w; } /* write DWORD as DWORD */ void put_bigendian_dword(unsigned char *dw, DWORD val) { dw[0] = (unsigned char)((val>>24) & 0xff); dw[1] = (unsigned char)((val>>16) & 0xff); dw[2] = (unsigned char)((val>>8) & 0xff); dw[3] = (unsigned char)( val & 0xff); } /* write WORD as WORD */ void put_bigendian_word(unsigned char *w, WORD val) { w[0] = (unsigned char)((val>>8) & 0xff); w[1] = (unsigned char)( val & 0xff); } const unsigned char apple_single_magic[4] = {0x00, 0x05, 0x16, 0x00}; const unsigned char apple_double_magic[4] = {0x00, 0x05, 0x16, 0x07}; CMACFILE *get_mactype(GFile *f) { #define ASD_HEADER_LENGTH 26 #define MACBIN_HEADER_LENGTH 128 unsigned char data[MACBIN_HEADER_LENGTH]; CMAC_TYPE type = CMAC_TYPE_NONE; CMACFILE *mac; int i; int asd_entries = 0; DWORD version; DWORD EntryID; DWORD Offset; DWORD Length; FILE_POS file_length; int count; if (f == NULL) return NULL; file_length = gfile_get_length(f); count = gfile_read(f, data, ASD_HEADER_LENGTH); if (count >= ASD_HEADER_LENGTH) { if (memcmp(data, apple_single_magic, 4) == 0) type = CMAC_TYPE_SINGLE; else if (memcmp(data, apple_double_magic, 4) == 0) type = CMAC_TYPE_DOUBLE; if ((type == CMAC_TYPE_SINGLE || type == CMAC_TYPE_DOUBLE)) { version = get_bigendian_dword(data+4); if ((version != 0x00010000) && (version != 0x00020000)) type = CMAC_TYPE_NONE; asd_entries = get_bigendian_word(data+24); } else if (type == CMAC_TYPE_NONE) { count += gfile_read(f, data+ASD_HEADER_LENGTH, MACBIN_HEADER_LENGTH-ASD_HEADER_LENGTH); if (count >= MACBIN_HEADER_LENGTH && (data[0]==0x0) && (data[1] >= 1) && (data[1] <= 63) && (data[74]==0x0) && (data[82]==0x0) && (data[65]>=' ') && (data[65]<='z') && (data[66]>=' ') && (data[66]<='z') && (data[67]>=' ') && (data[67]<='z') && (data[68]>=' ') && (data[68]<='z') && (data[69]>=' ') && (data[69]<='z') && (data[70]>=' ') && (data[70]<='z') && (data[71]>=' ') && (data[71]<='z') && (data[72]>=' ') && (data[72]<='z')) { type = CMAC_TYPE_MACBIN; } else { /* check for bare resource fork */ DWORD data_begin = get_bigendian_dword(data); DWORD map_begin = get_bigendian_dword(data+4); DWORD data_length = get_bigendian_dword(data+8); DWORD map_length = get_bigendian_dword(data+12); if ((data_begin == 0x100) && (data_begin + data_length == map_begin) && (map_begin + map_length == file_length)) type = CMAC_TYPE_RSRC; } } } if (type == CMAC_TYPE_NONE) return NULL; mac = (CMACFILE *)malloc(sizeof(CMACFILE)); if (mac == NULL) return NULL; memset(mac, 0, sizeof(CMACFILE)); mac->type = type; /* Read Mac Binary stuff */ if (type == CMAC_TYPE_MACBIN) { memcpy(mac->file_type, data+65, 4); memcpy(mac->file_creator, data+69, 4); mac->data_begin = 128; mac->data_length = get_bigendian_dword(data+83); mac->resource_begin = (mac->data_begin + mac->data_length + 127 ) & ~127; mac->resource_length = get_bigendian_dword(data+87); } else if (type == CMAC_TYPE_RSRC) { memcpy(mac->file_type, " ", 4); memcpy(mac->file_creator, " ", 4); mac->resource_begin = 0; mac->resource_length = file_length; } else { /* AppleSingle or AppleDouble */ for (i=0; idata_begin = Offset; mac->data_length = Length; break; case 2: /* Resource fork */ mac->resource_begin = Offset; mac->resource_length = Length; break; case 9: /* Finder info */ mac->finder_begin = Offset; mac->finder_length = Length; break; } } if (mac->finder_begin != 0) { gfile_seek(f, mac->finder_begin, SEEK_SET); count = gfile_read(f, data, min(sizeof(data), mac->finder_length)); if (count >= 8) { memcpy(mac->file_type, data, 4); memcpy(mac->file_creator, data+4, 4); } } } return mac; } typedef struct CMAC_RESOURCE_HEADER_s { DWORD data_begin; DWORD map_begin; DWORD data_length; DWORD map_length; } CMAC_RESOURCE_HEADER; typedef struct CMAC_RESOURCE_MAP_s { unsigned char reshdr[16]; DWORD reshdl; WORD filerefno; WORD attributes; WORD offset_type_list; WORD offset_name_list; WORD type_count; } CMAC_RESOURCE_MAP; typedef struct CMAC_RESOURCE_TYPE_LIST_s { unsigned char type[4]; WORD count; WORD offset_ref_list; } CMAC_RESOURCE_TYPE_LIST; typedef struct CMAC_RESOURCE_REF_LIST_s { WORD id; WORD offset_name; unsigned char attributes; DWORD offset_data; /* 3 bytes only */ DWORD handle; } CMAC_RESOURCE_REF_LIST; /* Find the location of PICT in the resource fork, if present */ int get_pict(GFile *f, CMACFILE *mac, int debug) { CMAC_RESOURCE_HEADER reshdr; CMAC_RESOURCE_MAP resmap; CMAC_RESOURCE_TYPE_LIST typelist; CMAC_RESOURCE_REF_LIST reflist; DWORD res_offset; DWORD map_offset; DWORD type_offset; DWORD ref_offset; DWORD preview_offset = 0; DWORD preview_length = 0; unsigned char data[16]; char name[257]; int name_length; int count; int i, j; if (mac == NULL) return 1; if (mac->type == CMAC_TYPE_NONE) return 1; if (((mac->type != CMAC_TYPE_RSRC) && (mac->resource_begin == 0)) || (mac->resource_length == 0)) return 1; memset(&resmap, 0, sizeof(resmap)); memset(&typelist, 0, sizeof(typelist)); memset(&reflist, 0, sizeof(reflist)); res_offset = mac->resource_begin; gfile_seek(f, res_offset, SEEK_SET); count = gfile_read(f, data, 16); if (count != 16) return -1; reshdr.data_begin = get_bigendian_dword(data); reshdr.map_begin = get_bigendian_dword(data+4); reshdr.data_length = get_bigendian_dword(data+8); reshdr.map_length = get_bigendian_dword(data+12); if (debug) { fprintf(stdout, "resource data: %ld %ld\n", reshdr.data_begin, reshdr.data_length); fprintf(stdout, "resource map: %ld %ld\n", reshdr.map_begin, reshdr.map_length); } map_offset = res_offset+reshdr.map_begin; gfile_seek(f, map_offset, SEEK_SET); count = gfile_read(f, &resmap.reshdr, 16); if (count != 16) return -1; count = gfile_read(f, data, 14); if (count != 14) return -1; resmap.reshdl = get_bigendian_dword(data); resmap.filerefno = get_bigendian_word(data+4); resmap.attributes = get_bigendian_word(data+6); resmap.offset_type_list = get_bigendian_word(data+8); resmap.offset_name_list = get_bigendian_word(data+10); resmap.type_count = get_bigendian_word(data+12); if (debug) { fprintf(stdout, " resource handle %ld\n", resmap.reshdl); fprintf(stdout, " file reference number %d\n", resmap.filerefno); fprintf(stdout, " attributes 0x%x\n", resmap.attributes); fprintf(stdout, " offset type list %d\n", resmap.offset_type_list); fprintf(stdout, " offset name list %d\n", resmap.offset_name_list); fprintf(stdout, " type count %d\n", resmap.type_count); } /* Documentation says that the type list starts at * map_offset + resmap.offset_type_list, but we have * found that it is actually 2 bytes further on. * Perhaps the type count is supposed be part of the type_list */ type_offset = map_offset+resmap.offset_type_list; for (i=0; i<=resmap.type_count; i++) { gfile_seek(f, type_offset + 2 + i * 8, SEEK_SET); /* +2 KLUDGE */ count = gfile_read(f, &typelist.type, 4); if (count != 4) return -1; count = gfile_read(f, data, 4); if (count != 4) return -1; typelist.count = get_bigendian_word(data); typelist.offset_ref_list = get_bigendian_word(data+2); if (debug) fprintf(stdout, "type %d %c%c%c%c count=%d offset=%d\n", i, typelist.type[0], typelist.type[1], typelist.type[2], typelist.type[3], typelist.count, typelist.offset_ref_list); ref_offset = type_offset + typelist.offset_ref_list; for (j=0; j<=typelist.count; j++) { gfile_seek(f, ref_offset + j * 12, SEEK_SET); count = gfile_read(f, data, 12); if (count != 12) return -1; reflist.id = get_bigendian_word(data); reflist.offset_name = get_bigendian_word(data+2); reflist.attributes = data[4]; reflist.offset_data = ((DWORD)data[5])<<16; reflist.offset_data += ((DWORD)data[6])<<8; reflist.offset_data += ((DWORD)data[7]); reflist.handle = get_bigendian_dword(data+8); if (debug) { fprintf(stdout, " reflist %d id=%d name=%d attributes=0x%x data=%ld 0x%lx\n", j, reflist.id, reflist.offset_name, reflist.attributes, reflist.offset_data, reflist.offset_data); gfile_seek(f, res_offset + reshdr.data_begin + reflist.offset_data, SEEK_SET); count = gfile_read(f, data, 4); if (count != 4) return -1; fprintf(stdout, " length=%ld 0x%lx\n", get_bigendian_dword(data), get_bigendian_dword(data)); } if ((resmap.offset_name_list < reshdr.map_length) && (resmap.offset_name_list != 0xffff) && (reflist.offset_name != 0xffff)) { gfile_seek(f, map_offset + resmap.offset_name_list + reflist.offset_name, SEEK_SET); count = gfile_read(f, data, 1); if (count != 1) return -1; name_length = data[0]; if (name_length <= 256) { count = gfile_read(f, name, name_length); if (count != name_length) return -1; name[name_length] = '\0'; if (debug) fprintf(stdout, " name=%s\n", name); } } if ((memcmp(typelist.type, "PICT", 4) == 0) && (reflist.id == 256)) { /* This is the PICT preview for an EPS files */ preview_offset = res_offset + reshdr.data_begin + reflist.offset_data; } } } if (preview_offset != 0) { gfile_seek(f, preview_offset, SEEK_SET); gfile_read(f, data, 4); preview_length = get_bigendian_dword(data); if (preview_length != 0) { mac->pict_begin = preview_offset + 4; mac->pict_length = preview_length; } } return 0; } /* Extract EPSF from data resource fork to a file */ /* Returns 0 on success, negative on failure */ static int extract_mac_data(GFile *f, LPCTSTR outname, unsigned long begin, unsigned long length, unsigned long header) { unsigned long len; unsigned int count; char *buffer; GFile *outfile; int code = 0; if ((begin == 0) || (length == 0)) return -1; if (*outname == '\0') return -1; /* create buffer for file copy */ buffer = (char *)malloc(COPY_BUF_SIZE); if (buffer == (char *)NULL) return -1; outfile = gfile_open(outname, gfile_modeWrite | gfile_modeCreate); if (outfile == (GFile *)NULL) { free(buffer); return -1; } /* PICT files when stored separately start with 512 nulls */ memset(buffer, 0, COPY_BUF_SIZE); if (header && header < COPY_BUF_SIZE) gfile_write(outfile, buffer, header); gfile_seek(f, begin, gfile_begin); /* seek to EPSF or PICT */ len = length; while ( (count = (unsigned int)min(len,COPY_BUF_SIZE)) != 0 ) { count = (int)gfile_read(f, buffer, count); gfile_write(outfile, buffer, count); if (count == 0) { len = 0; code = -1; } else len -= count; } free(buffer); gfile_close(outfile); return code; } /* Extract PICT from resource fork to a file */ /* Returns 0 on success, negative on failure */ int extract_mac_pict(GFile *f, CMACFILE *mac, LPCTSTR outname) { if ((f == NULL) || (mac == NULL)) return -1; /* PICT files when stored separately start with 512 nulls */ return extract_mac_data(f, outname, mac->pict_begin, mac->pict_length, 512); } /* Extract EPSF from data fork to a file */ /* Returns 0 on success, negative on failure */ int extract_mac_epsf(GFile *f, CMACFILE *mac, LPCTSTR outname) { if ((f == NULL) || (mac == NULL)) return -1; return extract_mac_data(f, outname, mac->data_begin, mac->data_length, 0); } /* Write resources containing a single PICT with id=256 to file. * Return number of bytes written if OK, -ve if not OK. * If f==NULL, return number of bytes required for resources. */ int write_resource_pict(GFile *f, LPCTSTR pictname) { GFile *pictfile; unsigned long pict_length; unsigned char data[256]; unsigned long data_offset = 256; unsigned long map_length = 58; unsigned long pict_offset = 0; /* at start of resource data */ unsigned resource_length; unsigned long len; unsigned int count; int code = 0; pictfile = gfile_open(pictname, gfile_modeRead); if (pictfile == NULL) return -1; pict_length = gfile_get_length(pictfile) - 512; if ((long)pict_length < 0) { gfile_close(pictfile); return -1; } resource_length = data_offset + 4 + pict_length + map_length; if (f == NULL) { gfile_close(pictfile); return resource_length; } /* resource header */ memset(data, 0, sizeof(data)); put_bigendian_dword(data, data_offset); /* data offset */ put_bigendian_dword(data+4, data_offset + 4 + pict_length); /* map offset */ put_bigendian_dword(data+8, pict_length + 4); /* data length */ put_bigendian_dword(data+12, map_length); /* map length */ gfile_write(f, data, data_offset); /* pict file */ put_bigendian_dword(data, pict_length); gfile_write(f, data, 4); len = pict_length; gfile_seek(pictfile, 512, SEEK_SET); while ( (count = (unsigned int)min(len,sizeof(data))) != 0 ) { count = (int)gfile_read(pictfile, data, count); gfile_write(f, data, count); if (count == 0) { len = 0; code = -1; } else len -= count; } gfile_close(pictfile); if (code < 0) return code; /* resource map */ memset(data, 0, sizeof(data)); put_bigendian_dword(data+16, 0); /* resource handle */ put_bigendian_word(data+20, 0); /* file reference number */ put_bigendian_word(data+22, 0); /* attributes */ put_bigendian_word(data+24, 28); /* offset to type list */ put_bigendian_word(data+26, 50); /* offset to name list */ gfile_write(f, data, 28); /* type list */ memset(data, 0, sizeof(data)); put_bigendian_word(data, 0); /* number of types */ memcpy(data+2, "PICT", 4); put_bigendian_word(data+6, 0); /* type count */ put_bigendian_word(data+8, 10); /* offset to ref list */ gfile_write(f, data, 10); /* reference list */ memset(data, 0, sizeof(data)); put_bigendian_word(data, 256); /* resource id for EPSF preview */ put_bigendian_word(data+2, 0); /* offset to name */ data[4] = '\0'; /* attributes */ data[5] = (unsigned char)((pict_offset>>16) & 0xff); data[6] = (unsigned char)((pict_offset>>8) & 0xff); data[7] = (unsigned char)( pict_offset & 0xff); put_bigendian_dword(data+8, 0); /* handle */ gfile_write(f, data, 12); /* name list */ memset(data, 0, sizeof(data)); data[0] = 7; memcpy(data+1, "Preview", 7); gfile_write(f, data, 8); return resource_length; } /* Write an AppleDouble file containing a single PICT with id=256 to file. */ int write_appledouble(GFile *f, LPCTSTR pictname) { unsigned char data[256]; unsigned long resource_length; /* get length of resources */ resource_length = write_resource_pict(NULL, pictname); memset(data, 0, sizeof(data)); memcpy(data, apple_double_magic, 4); /* magic signature */ put_bigendian_dword(data+4, 0x00020000); /* version */ /* 16 bytes filler */ put_bigendian_word(data+24, 2); /* 2 entries, finder and resource */ /* finder descriptor */ put_bigendian_dword(data+26, 9); /* finder id */ put_bigendian_dword(data+30, 50); /* offset */ put_bigendian_dword(data+34, 32); /* length */ /* resource descriptor */ put_bigendian_dword(data+38, 2); /* resource fork id */ put_bigendian_dword(data+42, 82); /* offset */ put_bigendian_dword(data+46, resource_length); /* length */ /* finder info */ memcpy(data+50, "EPSF", 4); /* file type */ memcpy(data+54, "MSWD", 4); /* file creator */ data[58] = 1; /* ??? need to check finder info */ gfile_write(f, data, 82); /* Now copy the resource fork */ if (write_resource_pict(f, pictname) <= 0) return -1; return 0; } /* Write an AppleSingle file with a data fork containing EPSF * and a resource fork containing a preview as a single PICT * with id=256. */ int write_applesingle(GFile *f, LPCTSTR epsname, LPCTSTR pictname) { unsigned long resource_length; unsigned long data_length; unsigned char data[256]; unsigned char *buffer; GFile *epsfile; unsigned long len; unsigned int count; int code = 0; buffer = (unsigned char *)malloc(COPY_BUF_SIZE); if (buffer == (unsigned char *)NULL) return -1; /* get length of data and resources */ epsfile = gfile_open(epsname, gfile_modeRead); if (epsname == NULL) { free(buffer); return -1; } data_length = gfile_get_length(epsfile); resource_length = write_resource_pict(NULL, pictname); memset(data, 0, sizeof(data)); memcpy(data, apple_single_magic, 4); /* magic signature */ put_bigendian_dword(data+4, 0x00020000); /* version */ /* 16 bytes filler */ put_bigendian_word(data+24, 3); /* 3 entries, finder, data and resource */ /* finder descriptor */ put_bigendian_dword(data+26, 9); /* finder id */ put_bigendian_dword(data+30, 62); /* offset */ put_bigendian_dword(data+34, 32); /* length */ /* data descriptor */ put_bigendian_dword(data+38, 1); /* data fork id */ put_bigendian_dword(data+42, 94); /* offset */ put_bigendian_dword(data+46, data_length); /* length */ /* resource descriptor */ put_bigendian_dword(data+50, 2); /* resource fork id */ put_bigendian_dword(data+54, 94+data_length); /* offset */ put_bigendian_dword(data+58, resource_length); /* length */ /* finder info */ memcpy(data+62, "EPSF", 4); /* file type */ memcpy(data+66, "MSWD", 4); /* file creator */ data[70] = 1; /* ??? need to check finder info */ gfile_write(f, data, 94); /* Copy data fork */ len = data_length; while ( (count = (unsigned int)min(len,COPY_BUF_SIZE)) != 0 ) { count = (int)gfile_read(epsfile, buffer, count); gfile_write(f, buffer, count); if (count == 0) { len = 0; code = -1; } else len -= count; } gfile_close(epsfile); free(buffer); if (code < 0) return code; /* Now copy the resource fork */ if (write_resource_pict(f, pictname) <= 0) return -1; return 0; } /* Write a MacBinary file with a data fork containing EPSF * and a resource fork containing a preview as a single PICT * with id=256. */ int write_macbin(GFile *f, const char *name, LPCTSTR epsname, LPCTSTR pictname) { unsigned char *buffer; unsigned char data[128]; const char *macname; int macname_length; unsigned long data_length; unsigned long resource_length; unsigned long len; unsigned int count; int code = 0; GFile *epsfile; time_t now = time(NULL); now += 2082844800LU; /* convert from Unix to Mac time */ macname = name; if (name[0] == '\0') /* we are writing to stdout */ macname = "Unknown"; buffer = (unsigned char *)malloc(COPY_BUF_SIZE); if (buffer == (unsigned char *)NULL) return -1; /* get length of data and resources */ epsfile = gfile_open(epsname, gfile_modeRead); if (epsname == NULL) { free(buffer); return -1; } data_length = gfile_get_length(epsfile); resource_length = write_resource_pict(NULL, pictname); /* MacBinary I header */ memset(data, 0, sizeof(data)); data[0] = 0; /* version */ macname_length = min(63, (int)strlen(macname)); data[1] = (unsigned char)macname_length; memcpy(data+2, macname, macname_length); memcpy(data+65, "EPSF", 4); /* file type */ memcpy(data+69, "MSWD", 4); /* file creator */ data[73] = 1; /* finder flags */ put_bigendian_dword(data+83, data_length); put_bigendian_dword(data+87, resource_length); put_bigendian_dword(data+91, (DWORD)now); /* creation date */ put_bigendian_dword(data+95, (DWORD)now); /* last modified date */ gfile_write(f, data, 128); /* copy data fork */ len = data_length; while ( (count = (unsigned int)min(len,COPY_BUF_SIZE)) != 0 ) { count = (int)gfile_read(epsfile, buffer, count); gfile_write(f, buffer, count); if (count == 0) { len = 0; code = -1; } else len -= count; } gfile_close(epsfile); free(buffer); if (code < 0) return code; /* Pad to 128 byte boundary */ memset(data, 0, sizeof(data)); count = data_length & 127; if (count) gfile_write(f, data, 128-count); /* Now copy the resource fork */ if (write_resource_pict(f, pictname) <= 0) return -1; /* Pad to 128 byte boundary */ count = resource_length & 127; if (count) gfile_write(f, data, 128-count); return 0; } /* Returns -1 for error, 0 for Mac and 1 for non-Mac */ /* If Macintosh format and verbose, print some details to stdout */ int dump_macfile(LPCTSTR filename, int verbose) { CMACFILE *mac; const char *p; GFile *f = gfile_open(filename, gfile_modeRead); if (f == NULL) return -1; mac = get_mactype(f); if (mac) get_pict(f, mac, (verbose > 1)); gfile_close(f); if (mac == NULL) return 1; if (verbose) { switch (mac->type) { case CMAC_TYPE_SINGLE: p = "AppleSingle"; break; case CMAC_TYPE_DOUBLE: p = "AppleDouble"; break; case CMAC_TYPE_MACBIN: p = "MacBinary"; break; case CMAC_TYPE_RSRC: p = "Resource"; break; default: p = "Unknown"; } fprintf(stdout, "Macintosh Binary Format: %s\n", p); fprintf(stdout, " File Type: %c%c%c%c\n", mac->file_type[0], mac->file_type[1], mac->file_type[2], mac->file_type[3]); fprintf(stdout, " File Creator: %c%c%c%c\n", mac->file_creator[0], mac->file_creator[1], mac->file_creator[2], mac->file_creator[3]); fprintf(stdout, " Finder Info: %ld %ld\n", mac->finder_begin, mac->finder_length); fprintf(stdout, " Data Fork: %ld %ld\n", mac->data_begin, mac->data_length); fprintf(stdout, " Resource Fork: %ld %ld\n", mac->resource_begin, mac->resource_length); fprintf(stdout, " PICT: %ld %ld, 0x%lx 0x%lx\n", mac->pict_begin, mac->pict_length, mac->pict_begin, mac->pict_length); } free(mac); return 0; } #ifdef STANDALONE /* To compile standalone for Windows, * cl -D_Windows -D__WIN32__ -DSTANDALONE -Isrc -Isrcwin * src/cmac.c obj/wfile.obj obj/calloc.obj */ int debug; void usage(void) { fprintf(stdout, "Usage:\n\ File info: cmac -i input.eps\n\ Extract data fork: cmac -d input output\n\ Extract PICT: cmac -x input.eps output.pict\n\ Write AppleSingle: cmac -1 input.eps input.pict output.eps\n\ Write AppleDouble: cmac -2 input.pict ._output.eps\n\ Write MacBinary: cmac -b input.eps input.pict output.eps\n\ "); } int main(int argc, char *argv[]) { GFile *f; CMACFILE *mac; int code = 0; if (argc < 2) { usage(); return 1; } if (argv[1][0] != '-') { usage(); return 1; } switch (argv[1][1]) { case 'i': if (argc != 3) { usage(); return 1; } if (dump_macfile(argv[2], 2) == 1) fprintf(stdout, "Not a Macintosh Resource, MacBinary, AppleSingle or AppleDouble file"; break; case 'd': /* Extract data fork */ if (argc != 4) { usage(); return 1; } f = gfile_open(argv[2], gfile_modeRead); if (f == NULL) { fprintf(stdout, "Failed to open file \042%s\042\n", argv[1]); return -1; } mac = get_mactype(f); if (mac == NULL) { fprintf(stdout, "Not a Mac file with resource fork\n"); code = 1; } if (code == 0) { code = extract_mac_data(f, argv[3], mac->data_begin, mac->data_length, 0); if (code) fprintf(stdout, "Failed to extract data fork.\n"); else fprintf(stdout, "Success\n"); } gfile_close(f); break; case 'x': /* Extract PICT preview */ if (argc != 4) { usage(); return 1; } f = gfile_open(argv[2], gfile_modeRead); if (f == NULL) { fprintf(stdout, "Failed to open file \042%s\042\n", argv[1]); return -1; } mac = get_mactype(f); if (mac == NULL) { fprintf(stdout, "Not a Mac file with resource fork\n"); code = 1; } if (get_pict(f, mac, FALSE) == 0) { if (extract_mac_pict(f, mac, argv[3]) != 0) fprintf(stdout, "Failed to find PICT id=256 or write file\n"); else fprintf(stdout, "Success\n"); } else { fprintf(stdout, "Resource fork didn't contain PICT preview\n"); } gfile_close(f); break; case 'm': /* Create MacBinary */ if (argc != 5) { usage(); return 1; } f = gfile_open(argv[4], gfile_modeWrite | gfile_modeCreate); if (f == NULL) { fprintf(stdout, "Failed to create file \042%s\042\n", argv[3]); return -1; } code = write_macbin(f, argv[2], argv[2], argv[3]); if (code != 0) fprintf(stdout, "Failed to write MacBinary\n"); else fprintf(stdout, "Success at writing MacBinary\n"); gfile_close(f); break; case '1': /* Create AppleSingle */ if (argc != 5) { usage(); return 1; } f = gfile_open(argv[4], gfile_modeWrite | gfile_modeCreate); if (f == NULL) { fprintf(stdout, "Failed to create file \042%s\042\n", argv[3]); return -1; } code = write_applesingle(f, argv[2], argv[3]); if (code != 0) fprintf(stdout, "Failed to write AppleSingle\n"); else fprintf(stdout, "Success at writing AppleSingle\n"); gfile_close(f); break; case '2': /* Create AppleDouble */ if (argc != 4) { usage(); return 1; } f = gfile_open(argv[3], gfile_modeWrite | gfile_modeCreate); if (f == NULL) { fprintf(stdout, "Failed to create file \042%s\042\n", argv[3]); return -1; } code = write_appledouble(f, argv[2]); if (code != 0) fprintf(stdout, "Failed to write AppleDouble\n"); else fprintf(stdout, "Success at writing AppleDouble\n"); gfile_close(f); break; default: usage(); return 1; } return code; } #endif epstool-3.08/src/cbmp.c0000644000076400007640000015464310252260054014426 0ustar rjlrjl00000000000000/* Copyright (C) 2001-2005 Ghostgum Software Pty Ltd. All rights reserved. This software is provided AS-IS with no warranty, either express or implied. This software is distributed under licence and may not be copied, modified or distributed except as expressly authorised under the terms of the licence contained in the file LICENCE in this distribution. For more information about licensing, please refer to http://www.ghostgum.com.au/ or contact Ghostsgum Software Pty Ltd, 218 Gallaghers Rd, Glen Waverley VIC 3150, AUSTRALIA, Fax +61 3 9886 6616. */ /* $Id: cbmp.c,v 1.17 2005/06/10 09:39:24 ghostgum Exp $ */ /* BMP and PBM to IMAGE conversion */ /* IMAGE to BMP, PBM, TIFF, PICT conversion */ /* These functions convert between a BMP or PBM file * and an IMAGE in the format as used by the Ghostscript * display device. */ #include "common.h" #include "gdevdsp.h" #include "cbmp.h" #include "cimg.h" #include "cps.h" /* for ps_fgets */ #include #ifdef HAVE_LIBPNG #include "png.h" #endif /* local prototypes */ static int read_pbm_bits(unsigned char *pbitmap, unsigned int width, unsigned int height, GFile *f); static int read_pgnm_bytes(unsigned char *pbitmap, unsigned int length, GFile *f); static int image_bmp2init(IMAGE *img, BITMAP2 *bmp2); static void shift_bits(unsigned char *bits, int bwidth, int offset); static void write_bigendian_dword(DWORD val, GFile *f); static void write_bigendian_word(WORD val, GFile *f); static const char szGSviewName[] = "GSview"; /* read/write word and dword in a portable way */ DWORD get_dword(const unsigned char *buf) { DWORD dw; dw = (DWORD)buf[0]; dw += ((DWORD)buf[1])<<8; dw += ((DWORD)buf[2])<<16; dw += ((DWORD)buf[3])<<24; return dw; } WORD get_word(const unsigned char *buf) { WORD w; w = (WORD)buf[0]; w |= (WORD)(buf[1]<<8); return w; } /* write DWORD as DWORD */ void write_dword(DWORD val, GFile *f) { unsigned char dw[4]; dw[0] = (unsigned char)( val & 0xff); dw[1] = (unsigned char)((val>>8) & 0xff); dw[2] = (unsigned char)((val>>16) & 0xff); dw[3] = (unsigned char)((val>>24) & 0xff); gfile_write(f, &dw, 4); } /* write WORD as DWORD */ void write_word_as_dword(WORD val, GFile *f) { unsigned char dw[4]; dw[0] = (unsigned char)( val & 0xff); dw[1] = (unsigned char)((val>>8) & 0xff); dw[2] = '\0'; dw[3] = '\0'; gfile_write(f, &dw, 4); } /* write WORD as WORD */ void write_word(WORD val, GFile *f) { unsigned char w[2]; w[0] = (unsigned char)( val & 0xff); w[1] = (unsigned char)((val>>8) & 0xff); gfile_write(f, &w, 2); } /* write bigendian DWORD */ static void write_bigendian_dword(DWORD val, GFile *f) { unsigned char dw[4]; dw[3] = (unsigned char)( val & 0xff); dw[2] = (unsigned char)((val>>8) & 0xff); dw[1] = (unsigned char)((val>>16) & 0xff); dw[0] = (unsigned char)((val>>24) & 0xff); gfile_write(f, &dw, 4); } /* write bigendian WORD */ static void write_bigendian_word(WORD val, GFile *f) { unsigned char w[2]; w[1] = (unsigned char)( val & 0xff); w[0] = (unsigned char)((val>>8) & 0xff); gfile_write(f, &w, 2); } /* shift preview by offset bits to the left */ /* width is in bytes */ /* fill exposed bits with 1's */ static void shift_bits(unsigned char *bits, int bwidth, int offset) { int bitoffset; int byteoffset; int newwidth; int shifter; int i; if (offset == 0) return; byteoffset = offset / 8; newwidth = bwidth - byteoffset; /* first remove byte offset */ memmove(bits, bits+byteoffset, newwidth); memset(bits+newwidth, 0xff, bwidth-newwidth); /* next remove bit offset */ bitoffset = offset - byteoffset*8; if (bitoffset==0) return; bitoffset = 8 - bitoffset; for (i=0; i>bitoffset); } } /* Load a Windows bitmap and return an image. * Because we are forcing this into a format that * could be written by the Ghostscript "display" * device, we can't write palette images since * the palette in the display device is fixed. * We convert 4 and 8-bit palette bitmaps to * 24-bit colour. */ IMAGE * bmpfile_to_image(LPCTSTR filename) { GFile *f = gfile_open(filename, gfile_modeRead); IMAGE *img; unsigned char bmf_buf[BITMAPFILE_LENGTH]; unsigned char *pbitmap; unsigned int length; unsigned int count; BITMAPFILE bmf; if (f == (GFile *)NULL) return NULL; gfile_read(f, bmf_buf, sizeof(bmf_buf)); if ((bmf_buf[0] != 'B') || (bmf_buf[1] != 'M')) { /* Not a Windows bitmap */ gfile_close(f); return NULL; } bmf.bfType = get_word(bmf_buf); bmf.bfSize = get_dword(bmf_buf+2); bmf.bfReserved1 = get_word(bmf_buf+6); bmf.bfReserved1 = get_word(bmf_buf+8); bmf.bfOffBits = get_dword(bmf_buf+10); length = bmf.bfSize - BITMAPFILE_LENGTH; pbitmap = (unsigned char *)malloc(length); if (pbitmap == NULL) { gfile_close(f); return NULL; } count = (int)gfile_read(f, pbitmap, length); gfile_close(f); img = bmp_to_image(pbitmap, length); free(pbitmap); return img; } static const unsigned char clr555[] = { 0x1f, 0x00, 0x00, 0x00, /* blue */ 0xe0, 0x03, 0x00, 0x00, /* green */ 0x00, 0x7c, 0x00, 0x00 /* red */ }; static const unsigned char clr565[] = { 0x1f, 0x00, 0x00, 0x00, /* blue */ 0xe0, 0x07, 0x00, 0x00, /* green */ 0x00, 0xf8, 0x00, 0x00 /* red */ }; IMAGE * bmp_to_image(unsigned char *pbitmap, unsigned int length) { BITMAP2 bmp2; RGB4 colour[256]; int depth; int palcount; int pallength; int bytewidth; BOOL convert; int i; int x, y; IMAGE img; IMAGE *pimage; unsigned char *bits; unsigned char *dest; memset(&img, 0, sizeof(img)); if (length < BITMAP2_LENGTH) return NULL; /* Read the BITMAPINFOHEADER in a portable way. */ bmp2.biSize = get_dword(pbitmap); pbitmap += 4; if (bmp2.biSize < BITMAP2_LENGTH) return NULL; /* we don't read OS/2 BMP format */ bmp2.biWidth = get_dword(pbitmap); pbitmap += 4; bmp2.biHeight = get_dword(pbitmap); pbitmap += 4; bmp2.biPlanes = get_word(pbitmap); pbitmap += 2; bmp2.biBitCount = get_word(pbitmap); pbitmap += 2; bmp2.biCompression = get_dword(pbitmap); pbitmap += 4; bmp2.biSizeImage = get_dword(pbitmap); pbitmap += 4; bmp2.biXPelsPerMeter = get_dword(pbitmap); pbitmap += 4; bmp2.biYPelsPerMeter = get_dword(pbitmap); pbitmap += 4; bmp2.biClrUsed = get_dword(pbitmap); pbitmap += 4; bmp2.biClrImportant = get_dword(pbitmap); pbitmap += 4; pbitmap += bmp2.biSize - BITMAP2_LENGTH; /* Calculate the raster size, depth, palette length etc. */ depth = bmp2.biPlanes * bmp2.biBitCount; bytewidth = ((bmp2.biWidth * depth + 31) & ~31) >> 3; palcount = 0; if (depth <= 8) palcount = (bmp2.biClrUsed != 0) ? (int)bmp2.biClrUsed : (int)(1 << depth); pallength = 0; if ((depth == 16) || (depth == 32)) { if (bmp2.biCompression == BI_BITFIELDS) pallength = 12; } else pallength = palcount * RGB4_LENGTH; for (i=0; i> 3; } else if ((colour[0].rgbBlue == 0xff) && (colour[0].rgbGreen == 0xff) && (colour[0].rgbRed == 0xff) && (colour[1].rgbBlue == 0) && (colour[1].rgbGreen == 0) && (colour[1].rgbRed == 0)) { /* black and white */ img.format = DISPLAY_COLORS_NATIVE | DISPLAY_ALPHA_NONE | DISPLAY_DEPTH_1 | DISPLAY_LITTLEENDIAN | DISPLAY_BOTTOMFIRST; img.raster = (img.width + 7) >> 3; } else if ( (colour[0].rgbBlue == colour[0].rgbGreen) && (colour[0].rgbRed == colour[0].rgbGreen) && (colour[1].rgbBlue == colour[1].rgbGreen) && (colour[1].rgbRed == colour[1].rgbGreen)) { /* convert to greyscale */ img.format = DISPLAY_COLORS_GRAY | DISPLAY_ALPHA_NONE | DISPLAY_DEPTH_8 | DISPLAY_LITTLEENDIAN | DISPLAY_BOTTOMFIRST; img.raster = img.width; convert = TRUE; } else /* convert to colour */ convert = TRUE; } else if ((depth == 4) || (depth == 8)) { BOOL grey = TRUE; for (i=0; i> 3]; idx = (idx >> shift) & 1; if ((img.format & DISPLAY_COLORS_MASK) == DISPLAY_COLORS_GRAY) *dest++ = colour[idx].rgbBlue; else { /* colour */ *dest++ = colour[idx].rgbBlue; *dest++ = colour[idx].rgbGreen; *dest++ = colour[idx].rgbRed; } shift--; if (shift < 0) shift = 7; } } else if (depth == 4) { for (x=0; x> 4) & 0xf; if ((img.format & DISPLAY_COLORS_MASK) == DISPLAY_COLORS_GRAY) *dest++ = colour[idx].rgbBlue; else { /* colour */ *dest++ = colour[idx].rgbBlue; *dest++ = colour[idx].rgbGreen; *dest++ = colour[idx].rgbRed; } } } else if (depth == 8) { for (x=0; ximage = bits; return pimage; } /* read width * height "bits" from file */ static int read_pbm_bits(unsigned char *pbitmap, unsigned int width, unsigned int height, GFile *f) { int count = 0; int ch; int mask = 0x80; int x, y; char buf[MAXSTR]; int buf_count = 0; int buf_idx = 0; for (y=0; y<(int)height; y++) { mask = 0x80; for (x=0; x<(int)width; x++) { if (mask == 0) { mask = 0x80; pbitmap++; count++; } ch = 0; while ((ch != '0') && (ch != '1')) { if (buf_idx >= buf_count) { buf_count = gfile_read(f, buf, min(sizeof(buf), width-x)); if (buf_count == 0) return -1; /* premature EOF */ buf_idx = 0; } ch = buf[buf_idx++]; } *pbitmap = (unsigned char) ((ch == '1') ? (*pbitmap | mask) : (*pbitmap & (~mask))); mask >>= 1; } pbitmap++; count++; } return count; } /* read length "bytes" from file */ static int read_pgnm_bytes(unsigned char *pbitmap, unsigned int length, GFile *f) { int count = 0; int ch = 0; int val; char buf[MAXSTR]; int buf_count = 0; int buf_idx = 0; for (count=0; count < (int)length; count++) { val = 0; while (!((ch >= '0') && (ch <= '9'))) { if (buf_idx >= buf_count) { buf_count = gfile_read(f, buf, min(sizeof(buf), length-count)); if (buf_count == 0) return -1; /* premature EOF */ buf_idx = 0; } ch = buf[buf_idx++]; } while ((ch >= '0') && (ch <= '9')) { val = (val*10) + ch - '0'; if (buf_idx >= buf_count) { buf_count = gfile_read(f, buf, min(sizeof(buf), length-count)); if (buf_count == 0) return -1; /* premature EOF */ buf_idx = 0; } ch = buf[buf_idx++]; } *pbitmap++ = (unsigned char)val; } return count; } /* Load a PBMPLUS bitmap and return an image. * Supported formats are pbmraw, pgmraw and ppmraw as written * by Ghostscript. */ IMAGE * pnmfile_to_image(LPCTSTR filename) { GFile *f = gfile_open(filename, gfile_modeRead); IMAGE img; IMAGE *pimage; int code; char typeline[256]; char sizeline[256]; char maxvalline[256]; char hdrline[256]; char tupltype[256]; int width = 0; int height = 0; int maxval = 255; int depth = 0; int pam = 0; int pbm = 0; int pgm = 0; int ppm = 0; int raw = 0; int cmyk = 0; unsigned int length; unsigned char *pbitmap; int endhdr; char *t1; char *t2; unsigned int count; if (f == (GFile *)NULL) return NULL; memset(&img, 0, sizeof(img)); memset(typeline, 0, sizeof(typeline)); memset(sizeline, 0, sizeof(sizeline)); memset(maxvalline, 0, sizeof(maxvalline)); code = ps_fgets(typeline, sizeof(typeline)-1, f) == 0; if (typeline[0] != 'P') code = 1; switch (typeline[1]) { case '1': pbm = 1; raw = 0; break; case '2': pgm = 1; raw = 0; break; case '3': ppm = 1; raw = 0; break; case '4': pbm = 1; raw = 1; break; case '5': pgm = 1; raw = 1; break; case '6': ppm = 1; raw = 1; break; case '7': pam = 1; raw = 1; break; default: code = 1; } if (pam) { /* Portable Arbitrary Map */ endhdr = 0; while (!endhdr && !code) { if (!code) code = ps_fgets(hdrline, sizeof(hdrline)-1, f) == 0; while (!code && (hdrline[0] == '#')) /* skip comments */ code = ps_fgets(hdrline, sizeof(hdrline)-1, f) == 0; if (code) break; t1 = hdrline; while (*t1 && ((*t1==' ') || (*t1=='\t'))) t1++; /* skip whitespace */ t1 = strtok(t1, " \t\r\n"); if (t1 == NULL) break; t2 = strtok(NULL, " \t\r\n"); if (strcmp(t1, "ENDHDR")==0) { endhdr = 1; continue; } else if (strcmp(t1, "WIDTH")==0) { if (t2) code = sscanf(t2, "%u", &width) != 1; } else if (strcmp(t1, "HEIGHT")==0) { if (t2) code = sscanf(t2, "%u", &height) != 1; } else if (strcmp(t1, "DEPTH")==0) { if (t2) code = sscanf(t2, "%u", &depth) != 1; } else if (strcmp(t1, "MAXVAL")==0) { if (t2) code = sscanf(t2, "%u", &maxval) != 1; } else if (strcmp(t1, "TUPLTYPE")==0) { if (t2) strncpy(tupltype, t2, sizeof(tupltype)-1); } } if (!endhdr) code = 1; if ((width == 0) || (height == 0) || (depth == 0) || (maxval == 0)) code = 1; if ((strcmp(tupltype, "BLACKANDWHITE")==0) && (depth == 1) && (maxval == 1)) pbm = 1; if ((strcmp(tupltype, "GRAYSCALE")==0) && (depth == 1) && (maxval == 255)) pgm = 1; if ((strcmp(tupltype, "RGB")==0) && (depth == 3) && (maxval == 255)) ppm = 1; if ((strcmp(tupltype, "CMYK")==0) && (depth == 4) && (maxval == 255)) cmyk = 1; } else { if (!code) code = ps_fgets(sizeline, sizeof(sizeline)-1, f) == 0; while (!code && (sizeline[0] == '#')) /* skip comments */ code = ps_fgets(sizeline, sizeof(sizeline)-1, f) == 0; if (!code) code = sscanf(sizeline, "%u %u", &width, &height) != 2; if ((width == 0) || (height == 0)) code = 1; if (!code && (pgm || ppm)) { code = ps_fgets(maxvalline, sizeof(maxvalline)-1, f) == 0; while (!code && (maxvalline[0] == '#')) code = ps_fgets(maxvalline, sizeof(maxvalline)-1, f) == 0; if (!code) code = sscanf(maxvalline, "%u", &maxval) != 1; } if (maxval != 255) code = 1; } img.width = width; img.height = height; if (pbm) { img.format = DISPLAY_COLORS_NATIVE | DISPLAY_ALPHA_NONE | DISPLAY_DEPTH_1 | DISPLAY_BIGENDIAN | DISPLAY_TOPFIRST; img.raster = (img.width + 7) >> 3; } else if (pgm) { img.format = DISPLAY_COLORS_GRAY | DISPLAY_ALPHA_NONE | DISPLAY_DEPTH_8 | DISPLAY_BIGENDIAN | DISPLAY_TOPFIRST; img.raster = img.width; } else if (ppm) { img.format = DISPLAY_COLORS_RGB | DISPLAY_ALPHA_NONE | DISPLAY_DEPTH_8 | DISPLAY_BIGENDIAN | DISPLAY_TOPFIRST; img.raster = img.width * 3; } else if (cmyk) { img.format = DISPLAY_COLORS_CMYK | DISPLAY_ALPHA_NONE | DISPLAY_DEPTH_8 | DISPLAY_BIGENDIAN | DISPLAY_TOPFIRST; img.raster = img.width * 4; } else code = 1; length = img.raster * img.height; if (code) { gfile_close(f); return NULL; } pbitmap = (unsigned char *)malloc(length); if (pbitmap == NULL) { gfile_close(f); return NULL; } if (raw) count = (int)gfile_read(f, pbitmap, length); else if (pbm) count = read_pbm_bits(pbitmap, img.width, img.height, f); else count = read_pgnm_bytes(pbitmap, length, f); gfile_close(f); if (count != length) { free(pbitmap); return NULL; } pimage = (IMAGE *)malloc(sizeof(IMAGE)); if (pimage == NULL) { free(pbitmap); return NULL; } memcpy(pimage, &img, sizeof(IMAGE)); pimage->image = pbitmap; return pimage; } /* Free an image created by bmpfile_to_image or pnmfile_to_image */ void bitmap_image_free(IMAGE *img) { if (img && img->image) { free(img->image); memset(img, 0, sizeof(IMAGE)); free(img); } } static int image_bmp2init(IMAGE *img, BITMAP2 *bmp2) { /* Create a BMP header from the IMAGE */ /* If we need to convert the IMAGE before writing to a BMP file, * the BMP header will not exactly match the image. */ bmp2->biSize = BITMAP2_LENGTH; bmp2->biWidth = img->width; bmp2->biHeight = img->height; bmp2->biPlanes = 1; bmp2->biCompression = 0; switch (img->format & DISPLAY_COLORS_MASK) { case DISPLAY_COLORS_NATIVE: switch (img->format & DISPLAY_DEPTH_MASK) { case DISPLAY_DEPTH_1: bmp2->biBitCount = 1; bmp2->biClrUsed = 2; bmp2->biClrImportant = 2; break; case DISPLAY_DEPTH_4: /* Fixed color palette */ bmp2->biBitCount = 4; bmp2->biClrUsed = 16; bmp2->biClrImportant = 16; break; case DISPLAY_DEPTH_8: /* Fixed color palette */ bmp2->biBitCount = 8; bmp2->biClrUsed = 96; bmp2->biClrImportant = 96; break; case DISPLAY_DEPTH_16: /* RGB bitfields */ /* Bit fields */ if ((img->format & DISPLAY_ENDIAN_MASK) == DISPLAY_BIGENDIAN) { /* convert */ bmp2->biBitCount = 24; bmp2->biClrUsed = 0; bmp2->biClrImportant = 0; } else { bmp2->biBitCount = 16; bmp2->biCompression = BI_BITFIELDS; bmp2->biClrUsed = 0; bmp2->biClrImportant = 0; } break; default: return_error(-1); } break; case DISPLAY_COLORS_GRAY: switch (img->format & DISPLAY_DEPTH_MASK) { case DISPLAY_DEPTH_1: bmp2->biBitCount = 1; bmp2->biClrUsed = 2; bmp2->biClrImportant = 2; break; case DISPLAY_DEPTH_4: /* Fixed gray palette */ bmp2->biBitCount = 4; bmp2->biClrUsed = 16; bmp2->biClrImportant = 16; break; case DISPLAY_DEPTH_8: /* Fixed gray palette */ bmp2->biBitCount = 8; bmp2->biClrUsed = 256; bmp2->biClrImportant = 256; break; default: return_error(-1); } break; case DISPLAY_COLORS_RGB: if ((img->format & DISPLAY_DEPTH_MASK) != DISPLAY_DEPTH_8) return_error(-1); /* either native BGR, or we need to convert it */ bmp2->biBitCount = 24; bmp2->biClrUsed = 0; bmp2->biClrImportant = 0; break; case DISPLAY_COLORS_CMYK: /* convert */ bmp2->biBitCount = 24; bmp2->biClrUsed = 0; bmp2->biClrImportant = 0; break; } bmp2->biSizeImage = 0; bmp2->biXPelsPerMeter = 0; bmp2->biYPelsPerMeter = 0; return 0; } /* Write an IMAGE as a Windows BMP file */ /* This is typically used to copy the display bitmap to a file */ int image_to_bmpfile(IMAGE* img, LPCTSTR filename, float xdpi, float ydpi) { BITMAP2 bmp2; BITMAPFILE bmf; int bytewidth; int depth; int palcount; int pallength; GFile *f; unsigned char r, g, b; unsigned char quad[4]; unsigned char nulchar = '\0'; int i; unsigned char *bits; unsigned char *row; int topfirst; if ((img == NULL) || (img->image == NULL)) return -1; if (image_bmp2init(img, &bmp2) < 0) return -1; if ((xdpi > 0.0) && (ydpi > 0.0)) { bmp2.biXPelsPerMeter = (int)(xdpi * 1000.0 / 25.4 + 0.5); bmp2.biYPelsPerMeter = (int)(ydpi * 1000.0 / 25.4 + 0.5); } depth = bmp2.biPlanes * bmp2.biBitCount; bytewidth = ((bmp2.biWidth * depth + 31) & ~31) >> 3; switch (depth) { case 1: case 4: case 8: palcount = 1 << depth; pallength = palcount * RGB4_LENGTH; break; case 16: palcount = 0; pallength = 12; default: palcount = 0; pallength = 0; } bmf.bfType = get_word((const unsigned char *)"BM"); bmf.bfReserved1 = 0; bmf.bfReserved2 = 0;; bmf.bfOffBits = BITMAPFILE_LENGTH + BITMAP2_LENGTH + palcount; bmf.bfSize = bmf.bfOffBits + bytewidth * bmp2.biHeight; row = (unsigned char *)malloc(bytewidth); if (row == NULL) return -1; f = gfile_open(filename, gfile_modeWrite | gfile_modeCreate); if (f == (GFile *)NULL) { free(row); return -1; } /* Write BITMAPFILEHEADER */ write_word(bmf.bfType, f); write_dword(bmf.bfSize, f); write_word(bmf.bfReserved1, f); write_word(bmf.bfReserved2, f); write_dword(bmf.bfOffBits, f); /* Write BITMAPINFOHEADER */ write_dword(bmp2.biSize, f); write_dword(bmp2.biWidth, f); write_dword(bmp2.biHeight, f); write_word(bmp2.biPlanes, f); write_word(bmp2.biBitCount, f); write_dword(bmp2.biCompression, f); write_dword(bmp2.biSizeImage, f); write_dword(bmp2.biXPelsPerMeter, f); write_dword(bmp2.biYPelsPerMeter, f); write_dword(bmp2.biClrUsed, f); write_dword(bmp2.biClrImportant, f); /* Write palette or bitmasks */ for (i=0; iformat, i, &r, &g, &b); quad[0] = b; quad[1] = g; quad[2] = r; quad[3] = '\0'; gfile_write(f, quad, 4); } if (bmp2.biCompression == BI_BITFIELDS) { if ((img->format & DISPLAY_555_MASK) == DISPLAY_NATIVE_555) gfile_write(f, clr555, sizeof(clr555)); else gfile_write(f, clr565, sizeof(clr565)); } /* Write the bits */ topfirst = ((img->format & DISPLAY_FIRSTROW_MASK) == DISPLAY_TOPFIRST); for (i=0; iimage + img->raster * (img->height - i - 1); else bits = img->image + img->raster * i; if (depth == 24) { image_to_24BGR(img, row, bits); gfile_write(f, row, bytewidth); } else { if ((int)img->raster < bytewidth) { int j; gfile_write(f, bits, img->raster); for (j=bytewidth-img->raster; j>0; j--) gfile_write(f, &nulchar, 1); } else gfile_write(f, bits, bytewidth); } } free(row); gfile_close(f); return 0; } /*********************************************************/ #define tiff_long(val, f) write_dword(val, f) #define tiff_short(val, f) write_word_as_dword(val, f) #define tiff_word(val, f) write_word(val, f) #define TIFF_BYTE 1 #define TIFF_ASCII 2 #define TIFF_SHORT 3 #define TIFF_LONG 4 #define TIFF_RATIONAL 5 struct rational_s { DWORD numerator; DWORD denominator; }; #define TIFF_RATIONAL_SIZE 8 struct ifd_entry_s { WORD tag; WORD type; DWORD length; DWORD value; }; #define TIFF_IFD_SIZE 12 struct tiff_head_s { WORD order; WORD version; DWORD ifd_offset; }; #define TIFF_HEAD_SIZE 8 /* Write tiff file from IMAGE. * Since this will be used by a DOS EPS file, we write an Intel TIFF file. * Include the pixels specified in devbbox, which is in pixel coordinates * not points. If this is empty, the whole image will be used. * Resolution of bitmap is xdpi,ydpi. * If tiff4 is true, write a monochrome file compatible with TIFF 4, * otherwise make it compatible with TIFF 6. * If use_packbits is true and tiff4 is false, use packbits to * compress the bitmap. */ int image_to_tiff(GFile *f, IMAGE *img, int xoffset, int yoffset, int width, int height, float xdpi, float ydpi, BOOL tiff4, BOOL use_packbits) { #define IFD_MAX_ENTRY 12 WORD ifd_length; DWORD ifd_next; DWORD tiff_end, end; int i, j; unsigned char *preview; BYTE *line; const unsigned char nulchar = '\0'; int temp_bwidth, bwidth; BOOL soft_extra = FALSE; int bitoffset; WORD *comp_length=NULL; /* lengths of compressed lines */ BYTE *comp_line=NULL; /* compressed line buffer */ int rowsperstrip; int stripsperimage; int strip, is; int strip_len; int lastrow; int depth; int preview_depth; int topfirst; if (img == NULL) return -1; topfirst = ((img->format & DISPLAY_FIRSTROW_MASK) == DISPLAY_TOPFIRST); depth = image_depth(img); if (depth == 1) preview_depth = 1; else if (depth == 4) preview_depth = 4; else if (depth == 8) preview_depth = 8; else preview_depth = 24; if (tiff4) preview_depth = 1; /* byte width of source bitmap is img->raster */ /* byte width of intermediate line, after conversion * to preview_depth, but before shifting to remove * unwanted pixels. */ temp_bwidth = (img->width * preview_depth + 7) >> 3; /* byte width of preview */ bwidth = (width * preview_depth + 7) >> 3; /* Number of bits to shift intermediate line to get preview line */ bitoffset = xoffset * preview_depth; if (tiff4) rowsperstrip = 1; /* make TIFF 4 very simple */ else { /* work out RowsPerStrip, to give < 8k compressed */ /* or uncompressed data per strip */ rowsperstrip = (8192 - 256) / bwidth; if (rowsperstrip == 0) rowsperstrip = 1; /* strips are larger than 8k */ } stripsperimage = (height + rowsperstrip - 1) / rowsperstrip; if (stripsperimage == 1) rowsperstrip = height; preview = (unsigned char *) malloc(img->raster); if (preview == NULL) return -1; memset(preview,0xff,img->raster); /* compress bitmap, throwing away result, to find out compressed size */ if (use_packbits) { comp_length = (WORD *)malloc(stripsperimage * sizeof(WORD)); if (comp_length == NULL) { free(preview); return -1; } comp_line = (BYTE *)malloc(bwidth + bwidth/64 + 1); if (comp_line == NULL) { free(preview); free(comp_length); return -1; } if (topfirst) line = img->image + img->raster * (img->height - yoffset - height); else line = img->image + img->raster * (yoffset + height-1); /* process each strip */ for (strip = 0; strip < stripsperimage; strip++) { is = strip * rowsperstrip; lastrow = min( rowsperstrip, height - is); comp_length[strip] = 0; strip_len = 0; /* process each line within strip */ for (i = 0; i< lastrow; i++) { if (preview_depth == 1) { memset(preview,0xff,img->raster); image_to_mono(img, preview, line); for (j=0; jraster); if (bitoffset) shift_bits(preview, temp_bwidth, bitoffset); strip_len += packbits(comp_line, preview, bwidth); if (topfirst) line += img->raster; else line -= img->raster; } comp_length[strip] = (WORD)strip_len; } } /* write header */ tiff_end = TIFF_HEAD_SIZE; tiff_word(0x4949, f); /* Intel = little endian */ tiff_word(42, f); tiff_long(tiff_end, f); /* write count of ifd entries */ tiff_end += 2 /* sizeof(ifd_length) */; if (tiff4) ifd_length = 10; else { switch (preview_depth) { case 24: /* extras are BitsPerPixel, SamplesPerPixel */ ifd_length = 15; break; case 8: case 4: /* extras are BitsPerPixel, ColorMap */ ifd_length = 15; break; default: /* bi-level */ ifd_length = 13; } } tiff_word(ifd_length, f); tiff_end += ifd_length * TIFF_IFD_SIZE + 4 /* sizeof(ifd_next) */; ifd_next = 0; /* write each of the ifd entries */ if (tiff4) { tiff_word(0xff, f); /* SubfileType */ tiff_word(TIFF_SHORT, f); /* value type */ tiff_long(1, f); /* length */ tiff_short(0, f); /* value */ } else { tiff_word(0xfe, f); /* NewSubfileType */ tiff_word(TIFF_LONG, f); tiff_long(1, f); /* length */ tiff_long(0, f); /* value */ } tiff_word(0x100, f); /* ImageWidth */ if (tiff4) { tiff_word(TIFF_SHORT, f); tiff_long(1, f); tiff_short((short)width, f); } else { tiff_word(TIFF_LONG, f); tiff_long(1, f); tiff_long(width, f); } tiff_word(0x101, f); /* ImageHeight */ if (tiff4) { tiff_word(TIFF_SHORT, f); tiff_long(1, f); tiff_short((short)height, f); } else { tiff_word(TIFF_LONG, f); tiff_long(1, f); tiff_long(height, f); } if (!tiff4 && preview_depth>1) { tiff_word(0x102, f); /* BitsPerSample */ tiff_word(TIFF_SHORT, f); if (preview_depth == 24) { tiff_long(3, f); tiff_long(tiff_end, f); tiff_end += 6; } else { tiff_long(1, f); tiff_short((WORD)preview_depth, f); } } tiff_word(0x103, f); /* Compression */ tiff_word(TIFF_SHORT, f); tiff_long(1, f); if (use_packbits) tiff_short(32773U, f); /* packbits compression */ else tiff_short(1, f); /* no compression */ tiff_word(0x106, f); /* PhotometricInterpretation */ tiff_word(TIFF_SHORT, f); tiff_long(1, f); if (tiff4 || preview_depth==1) tiff_short(1, f); /* black is zero */ else if (preview_depth==24) tiff_short(2, f); /* RGB */ else /* preview_depth == 4 or 8 */ tiff_short(3, f); /* Palette Color */ tiff_word(0x111, f); /* StripOffsets */ tiff_word(TIFF_LONG, f); if (stripsperimage == 1) { /* This is messy and fragile */ int len = 0; tiff_long(1, f); len += TIFF_RATIONAL_SIZE * 2; /* resolutions */ if (!tiff4) { len += (((int)strlen(szGSviewName)+2)&~1) + 20; /* software and date */ if (preview_depth == 4 || preview_depth == 8) len += 2 * 3*(1< 1) { int stripwidth = bwidth * rowsperstrip; for (i=0; i 1) { for (i=0; itm_year+1900, dt->tm_mon+1, dt->tm_mday, dt->tm_hour, dt->tm_min, dt->tm_sec); gfile_write(f, now, 20); } /* Palette */ if (!tiff4 && ((preview_depth==4) || (preview_depth==8))) { int palcount = 1<format, i, &r, &g, &b); tiff_word(PALVAL(r), f); } for (i=0; iformat, i, &r, &g, &b); tiff_word(PALVAL(g), f); } for (i=0; iformat, i, &r, &g, &b); tiff_word(PALVAL(b), f); } #undef PALVAL } if (topfirst) line = img->image + img->raster * (img->height - yoffset - height); else line = img->image + img->raster * (yoffset+height-1); /* process each strip of bitmap */ for (strip = 0; strip < stripsperimage; strip++) { int len; is = strip * rowsperstrip; lastrow = min( rowsperstrip, height - is); /* process each row of strip */ for (i = 0; i < lastrow; i++) { if (preview_depth == 1) { memset(preview,0,img->raster); image_to_mono(img, preview, line); for (j=0; jraster); if (bitoffset) shift_bits(preview, temp_bwidth, bitoffset); if (use_packbits) { len = (WORD)packbits(comp_line, preview, bwidth); gfile_write(f, comp_line, len); } else gfile_write(f, preview, bwidth); if (topfirst) line += img->raster; else line -= img->raster; } } if (use_packbits) { free(comp_length); free(comp_line); } free(preview); return 0; } /* Write an IMAGE as a TIFF file */ /* This is typically used to copy the display bitmap to a file */ int image_to_tifffile(IMAGE* img, LPCTSTR filename, float xdpi, float ydpi) { GFile *f; int code = 0; BOOL tiff4 = ((img->format & DISPLAY_DEPTH_MASK) == DISPLAY_DEPTH_1); if ((img == NULL) || (img->image == NULL)) return -1; f = gfile_open(filename, gfile_modeWrite | gfile_modeCreate); if (f == (GFile *)NULL) return -1; code = image_to_tiff(f, img, 0, 0, img->width, img->height, xdpi, ydpi, tiff4, !tiff4); gfile_close(f); return 0; } /*********************************************************/ int image_to_pnmfile(IMAGE* img, LPCTSTR filename, PNM_FORMAT pnm_format) { PNM_FORMAT format = pnm_format; FILE *f; int bytewidth; unsigned char *row; unsigned char *bits; int topfirst; int i; if ((img == NULL) || (img->image == NULL)) return -1; /* check if mono, grey or colour */ if ((format != PBMRAW) && (format != PGMRAW) && (format != PPMRAW)) { switch (img->format & DISPLAY_COLORS_MASK) { case DISPLAY_COLORS_NATIVE: switch (img->format & DISPLAY_DEPTH_MASK) { case DISPLAY_DEPTH_1: format = PBMRAW; break; case DISPLAY_DEPTH_4: case DISPLAY_DEPTH_8: case DISPLAY_DEPTH_16: format = PPMRAW; break; default: return_error(-1); } break; case DISPLAY_COLORS_GRAY: switch (img->format & DISPLAY_DEPTH_MASK) { case DISPLAY_DEPTH_1: format = PBMRAW; break; case DISPLAY_DEPTH_4: case DISPLAY_DEPTH_8: /* Fixed gray palette */ format = PGMRAW; break; default: return_error(-1); } break; case DISPLAY_COLORS_RGB: if ((img->format & DISPLAY_DEPTH_MASK) != DISPLAY_DEPTH_8) return_error(-1); format = PPMRAW; break; case DISPLAY_COLORS_CMYK: /* convert */ format = PPMRAW; break; } } if (format == PPMRAW) bytewidth = img->width * 3; else if (format == PGMRAW) bytewidth = img->width; else bytewidth = (img->width + 7) >> 3; row = (unsigned char *)malloc(bytewidth); if (row == NULL) return -1; topfirst = ((img->format & DISPLAY_FIRSTROW_MASK) == DISPLAY_TOPFIRST); f = csfopen(filename, TEXT("wb")); if (f == NULL) { free(row); return -1; } fprintf(f, "P%c\n", (int)(format+'0')); fprintf(f, "# Created by GSview\n"); fprintf(f, "%d %d\n", img->width, img->height); if ((format == PGMRAW) || (format == PPMRAW)) fprintf(f, "255\n"); /* max value */ for (i=0; i<(int)img->height; i++) { if (topfirst) bits = img->image + img->raster * i; else bits = img->image + img->raster * (img->height - i - 1); if (format == PPMRAW) image_to_24RGB(img, row, bits); else if (format == PGMRAW) image_to_grey(img, row, bits); else image_to_mono(img, row, bits); fwrite(row, 1, bytewidth, f); } free(row); fclose(f); return 0; } typedef enum PICTOp_e { PICT_NOP = 0x0000, PICT_Clip = 0x0001, PICT_VersionOp = 0x0011, PICT_DirectBitsRect = 0x009A, /* use this for 24/32 bits/pixel */ PICT_OpEndPic = 0x00ff, PICT_Version = 0x02ff, PICT_HeaderOp = 0x0c00 } PICTOp; /* Write PICT PixData * Return number of bytes generated. * Return -ve on error. * If file is NULL just return the number of bytes generated * without actually writing anything. */ static int write_pict_pixdata(IMAGE *img, GFile *f) { int i, j; int count; int topfirst; unsigned char b; unsigned char *bits; unsigned char *row, *sep, *packed; unsigned char *p; int wcount = 0; int rowwidth = img->width * 3; /* For the purposes of calculating the QuickDraw row width, * we must use 32-bits/pixel. */ int qdrowwidth = img->width * 4; row = (unsigned char *)malloc(rowwidth); /* 24-bit RGB */ sep = (unsigned char *)malloc(qdrowwidth); /* xRGB or RRGGBB */ packed = (unsigned char *)malloc(rowwidth + rowwidth / 128 + 1); if ((row == NULL) || (sep == NULL) || (packed == NULL)) { if (row != NULL) free(row); if (sep != NULL) free(sep); if (packed != NULL) free(packed); return -1; } /* With packType=4 we compress each component separately, red first */ wcount = 0; topfirst = ((img->format & DISPLAY_FIRSTROW_MASK) == DISPLAY_TOPFIRST); for (i=0; i<(int)img->height; i++) { if (topfirst) bits = img->image + img->raster * i; else bits = img->image + img->raster * (img->height - i - 1); image_to_24RGB(img, row, bits); p = row; if (qdrowwidth < 8) { /* Never compress short rows */ if (f) { for (j=0; j<(int)img->width; j++) { /* Store as xRGB */ sep[4*j] = '\0'; sep[4*j+1] = *p++; sep[4*j+2] = *p++; sep[4*j+3] = *p++; } gfile_write(f, sep, qdrowwidth); } wcount += 8; } else { for (j=0; j<(int)img->width; j++) { /* separate components */ sep[j] = *p++; sep[j+img->width] = *p++; sep[j+img->width+img->width] = *p++; } count = packbits(packed, sep, rowwidth); if (qdrowwidth > 250) { if (f) write_bigendian_word((WORD)count, f); wcount += 2; } else { b = (unsigned char )count; if (f) gfile_write(f, &b, 1); wcount += 1; } if (f) gfile_write(f, packed, count); wcount += count; } } if (wcount & 1) { /* write out an even number of bytes for row data */ b = 0; if (f) gfile_write(f, &b, 1); wcount++; } return wcount; } /* Macintosh PICT */ /* Only writes 24-bit RGB */ int image_to_pictfile(IMAGE* img, LPCTSTR filename, float xdpi, float ydpi) { int i; int wcount; GFile *f = NULL; f = gfile_open(filename, gfile_modeWrite | gfile_modeCreate); if (f == (GFile *)NULL) return -1; /* Calculate compressed data length */ wcount = write_pict_pixdata(img, NULL); /* PICT starts with 512 null bytes */ for (i=0; i<128; i++) write_bigendian_dword(0, f); /* picture size - we will correct this later */ /* 10 bytes */ write_bigendian_word((WORD)(wcount+124), f); /* bounding box of rectangle */ write_bigendian_word(0, f); /* top */ write_bigendian_word(0, f); /* left */ write_bigendian_word((WORD)img->height, f); /* bottom */ write_bigendian_word((WORD)img->width, f); /* right */ /* Imaging With QuickDraw: Appendix A - Picture Opcodes */ /* 4 bytes */ write_bigendian_word(PICT_VersionOp, f); write_bigendian_word(PICT_Version, f); /* Imaging With QuickDraw: Listing A-6 "A Sample Version 2 Picture" */ /* 24 byte header + 2 byte NOP */ write_bigendian_word(PICT_HeaderOp, f); write_bigendian_word((WORD)(-2), f); /* Version 2 extended */ write_bigendian_word(0, f); /* reserved */ write_bigendian_dword((DWORD)(xdpi * 65536), f); /* best hRes */ write_bigendian_dword((DWORD)(ydpi * 65536), f); /* best vRes */ write_bigendian_word(0, f); /* top */ write_bigendian_word(0, f); /* left */ write_bigendian_word((WORD)img->height, f); /* bottom */ write_bigendian_word((WORD)img->width, f); /* right */ write_bigendian_word(0, f); /* reserved */ write_bigendian_word(PICT_NOP, f); /* 40 bytes to here */ /* Clip */ write_bigendian_word(PICT_Clip, f); write_bigendian_word(10, f); /* size */ write_bigendian_word(0, f); /* top */ write_bigendian_word(0, f); /* left */ write_bigendian_word((WORD)img->height, f); /* bottom */ write_bigendian_word((WORD)img->width, f); /* right */ /* Based on Imaging With QuickDraw Listing A-2 for PackBitsRect */ /* but modified to match DirectBitsRect output from Photoshop */ write_bigendian_word(PICT_DirectBitsRect, f); write_bigendian_dword(0xff, f); /* unknown */ /* rowBytes: flags = 0x8000 for pixmap, row width */ write_bigendian_word((WORD)(0x8000 | (img->width * 4)), f); /* rowBytes */ write_bigendian_word(0, f); /* bounds: top */ write_bigendian_word(0, f); /* bounds: left */ write_bigendian_word((WORD)img->height, f); /* bounds: bottom */ write_bigendian_word((WORD)img->width, f); /* bounds: right */ write_bigendian_word(0, f); /* pmVersion */ write_bigendian_word(4, f); /* packType: packbits by component */ write_bigendian_dword(0, f); /* packSize: always 0 */ write_bigendian_dword((DWORD)(xdpi * 65536), f); /* hRes: fixed */ write_bigendian_dword((DWORD)(ydpi * 65536), f); /* vRes: fixed */ write_bigendian_word(16, f); /* pixelType: RGBDirect */ write_bigendian_word(32, f); /* pixelSize: 24-bit RGB */ write_bigendian_word(3, f); /* cmpCount: 3 for RGB */ write_bigendian_word(8, f); /* cmpSize: 8 bits/component */ write_bigendian_dword(0, f); /* planeBytes */ write_bigendian_dword(0, f); /* pmTable */ write_bigendian_dword(0, f); /* pmReserved */ /* srcRect */ write_bigendian_word(0, f); /* srcRect: top */ write_bigendian_word(0, f); /* srcRect: left */ write_bigendian_word((WORD)img->height, f); /* srcRect: bottom */ write_bigendian_word((WORD)img->width, f); /* srcRect: right */ /* destRect */ write_bigendian_word(0, f); /* destRect: top */ write_bigendian_word(0, f); /* destRect: left */ write_bigendian_word((WORD)img->height, f); /* destRect: bottom */ write_bigendian_word((WORD)img->width, f); /* destRect: right */ /* mode */ write_bigendian_word(0x40, f); /* transfer mode */ /* PixData */ write_pict_pixdata(img, f); write_bigendian_word(PICT_OpEndPic, f); gfile_close(f); return 0; } #ifdef HAVE_LIBPNG static void image_png_flush(png_structp png_ptr) { png_FILE_p io_ptr; io_ptr = (png_FILE_p)CVT_PTR((png_ptr->io_ptr)); if (io_ptr != NULL) fflush(io_ptr); } static void image_png_write_data(png_structp png_ptr, png_bytep data, png_size_t length) { int count = fwrite(data, 1, length, (png_FILE_p)png_ptr->io_ptr); if (count != (int)length) png_error(png_ptr, "Write Error"); } static void image_png_read_data(png_structp png_ptr, png_bytep data, png_size_t length) { int count; count = fread(data, 1, length, (png_FILE_p)png_ptr->io_ptr); if (count != (int)length) png_error(png_ptr, "Read Error!"); } int image_to_pngfile(IMAGE* img, LPCTSTR filename) { FILE *f; png_structp png_ptr; png_infop info_ptr; int colour_type; int bit_depth; int num_palette = 0; png_color palette[96]; BOOL invert_mono = FALSE; BOOL topfirst; unsigned char *bits; unsigned char *row = NULL; int i; if ((img == NULL) || (img->image == NULL)) return -1; switch (img->format & DISPLAY_COLORS_MASK) { case DISPLAY_COLORS_NATIVE: switch (img->format & DISPLAY_DEPTH_MASK) { case DISPLAY_DEPTH_1: colour_type = PNG_COLOR_TYPE_GRAY; bit_depth = 1; invert_mono = TRUE; break; case DISPLAY_DEPTH_4: colour_type = PNG_COLOR_TYPE_PALETTE; bit_depth = 4; num_palette = 16; break; case DISPLAY_DEPTH_8: colour_type = PNG_COLOR_TYPE_PALETTE; num_palette = 96; bit_depth = 8; break; case DISPLAY_DEPTH_16: /* convert */ colour_type = PNG_COLOR_TYPE_RGB; bit_depth = 8; break; default: return_error(-1); } break; case DISPLAY_COLORS_GRAY: switch (img->format & DISPLAY_DEPTH_MASK) { case DISPLAY_DEPTH_1: colour_type = PNG_COLOR_TYPE_GRAY; bit_depth = 1; break; case DISPLAY_DEPTH_4: colour_type = PNG_COLOR_TYPE_GRAY; bit_depth = 4; break; case DISPLAY_DEPTH_8: colour_type = PNG_COLOR_TYPE_GRAY; bit_depth = 8; break; default: return_error(-1); } break; case DISPLAY_COLORS_RGB: if ((img->format & DISPLAY_DEPTH_MASK) != DISPLAY_DEPTH_8) return_error(-1); colour_type = PNG_COLOR_TYPE_RGB; bit_depth = 8; break; case DISPLAY_COLORS_CMYK: /* convert */ colour_type = PNG_COLOR_TYPE_RGB; bit_depth = 8; break; default: return -1; } if (num_palette > sizeof(palette)/sizeof(palette[0])) return -1; if (colour_type == PNG_COLOR_TYPE_RGB) { row = (unsigned char *)malloc(img->width * 3); if (row == NULL) return -1; } f = csfopen(filename, TEXT("wb")); if (f == NULL) { if (row) free(row); return -1; } png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, (png_voidp)NULL, NULL, NULL); if (png_ptr == NULL) { fclose(f); if (row) free(row); return -1; } info_ptr = png_create_info_struct(png_ptr); if (info_ptr == NULL) { png_destroy_write_struct(&png_ptr, (png_infopp)NULL); fclose(f); return -1; } if (setjmp(png_jmpbuf(png_ptr))) { png_destroy_write_struct(&png_ptr, &info_ptr); fclose(f); if (row) free(row); return -1; } png_set_write_fn(png_ptr, (png_voidp)f, image_png_write_data, image_png_flush); png_set_IHDR(png_ptr, info_ptr, img->width, img->height, bit_depth, colour_type, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT); if (colour_type == PNG_COLOR_TYPE_PALETTE) { for (i=0; iformat, i, &palette[i].red, &palette[i].green, &palette[i].blue); png_set_PLTE(png_ptr, info_ptr, palette, num_palette); } if (invert_mono) png_set_invert_mono(png_ptr); png_write_info(png_ptr, info_ptr); topfirst = ((img->format & DISPLAY_FIRSTROW_MASK) == DISPLAY_TOPFIRST); for (i=0; i<(int)img->height; i++) { if (topfirst) bits = img->image + img->raster * i; else bits = img->image + img->raster * (img->height - i - 1); if (colour_type == PNG_COLOR_TYPE_RGB) { image_to_24RGB(img, row, bits); bits = row; } png_write_row(png_ptr, bits); } png_write_end(png_ptr, info_ptr); png_destroy_write_struct(&png_ptr, &info_ptr); fclose(f); if (row) free(row); return 0; } IMAGE * pngfile_to_image(LPCTSTR filename) { FILE *f; png_structp png_ptr; png_infop info_ptr; png_infop end_info; unsigned char png_buf[8]; png_uint_32 width; png_uint_32 height; int bit_depth; int color_type; int interlace_type; int compression_method; int filter_method; unsigned char **rows = NULL; unsigned char *bits = NULL; int nbytes; int raster; int i; IMAGE *img = NULL; f = csfopen(filename, TEXT("rb")); if (f == (FILE *)NULL) return NULL; fread(png_buf, 1, sizeof(png_buf), f); if (png_sig_cmp(png_buf, 0, sizeof(png_buf))!=0) { /* Not a PNG file */ fclose(f); return NULL; } png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, (png_voidp)NULL, NULL, NULL); if (png_ptr == NULL) { fclose(f); return NULL; } png_set_read_fn(png_ptr, (png_voidp)f, image_png_read_data); info_ptr = png_create_info_struct(png_ptr); if (info_ptr == NULL) { png_destroy_read_struct(&png_ptr, (png_infopp)NULL, (png_infopp)NULL); fclose(f); return NULL; } end_info = png_create_info_struct(png_ptr); if (end_info == NULL) { png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp)NULL); fclose(f); return NULL; } if (setjmp(png_jmpbuf(png_ptr))) { png_destroy_read_struct(&png_ptr, &info_ptr, &end_info); fclose(f); if (rows) free(rows); if (bits) free(bits); if (img) free(img); return NULL; } png_set_sig_bytes(png_ptr, sizeof(png_buf)); png_read_info(png_ptr, info_ptr); png_get_IHDR(png_ptr, info_ptr, &width, &height, &bit_depth, &color_type, &interlace_type, &compression_method, &filter_method); if (color_type == PNG_COLOR_TYPE_PALETTE) png_set_palette_to_rgb(png_ptr); if (color_type == PNG_COLOR_TYPE_GRAY) nbytes = 1; else nbytes = 3; if ((color_type == PNG_COLOR_TYPE_GRAY) && (bit_depth < 8)) png_set_gray_1_2_4_to_8(png_ptr); if (bit_depth == 16) png_set_strip_16(png_ptr); if (color_type & PNG_COLOR_MASK_ALPHA) png_set_strip_alpha(png_ptr); /* Allocate memory, and set row pointers */ raster = (width * nbytes + 3) & ~3; rows = (unsigned char **)malloc(height * sizeof(unsigned char *)); if (rows == NULL) longjmp(png_jmpbuf(png_ptr),-1); bits = (unsigned char *)malloc(raster * height); if (bits == NULL) longjmp(png_jmpbuf(png_ptr),-1); for (i=0; i<(int)height; i++) rows[i] = bits + i * raster; png_read_rows(png_ptr, rows, NULL, height); png_read_end(png_ptr, end_info); png_destroy_read_struct(&png_ptr, &info_ptr, &end_info); fclose(f); if (rows) free(rows); img = (IMAGE *)malloc(sizeof(IMAGE)); if (img == NULL) free(bits); else { img->width = width; img->height = height; img->raster = raster; img->format = (nbytes == 1) ? (DISPLAY_COLORS_GRAY | DISPLAY_ALPHA_NONE | DISPLAY_DEPTH_8 | DISPLAY_BIGENDIAN | DISPLAY_TOPFIRST) : (DISPLAY_COLORS_RGB | DISPLAY_ALPHA_NONE | DISPLAY_DEPTH_8 | DISPLAY_BIGENDIAN | DISPLAY_TOPFIRST); img->image = bits; } return img; } #else /* HAVE_LIBPNG */ int image_to_pngfile(IMAGE* img, LPCTSTR filename) { /* not supported */ return -1; } IMAGE * pngfile_to_image(LPCTSTR filename) { /* not supported */ return NULL; } #endif /* HAVE_LIBPNG */ /*********************************************************/ epstool-3.08/src/cps.h0000644000076400007640000000154310252260054014265 0ustar rjlrjl00000000000000/* Copyright (C) 1993-2003 Ghostgum Software Pty Ltd. All rights reserved. This software is provided AS-IS with no warranty, either express or implied. This software is distributed under licence and may not be copied, modified or distributed except as expressly authorised under the terms of the licence contained in the file LICENCE in this distribution. For more information about licensing, please refer to http://www.ghostgum.com.au/ or contact Ghostsgum Software Pty Ltd, 218 Gallaghers Rd, Glen Waverley VIC 3150, AUSTRALIA, Fax +61 3 9886 6616. */ /* $Id: cps.h,v 1.2 2003/01/12 06:32:44 ghostgum Exp $ */ /* Copying PostScript files */ int ps_extract(Doc *doc, LPCTSTR filename, PAGELIST *pagelist, int copies); int ps_copy(GFile *outfile, GFile *infile, FILE_OFFSET begin, FILE_OFFSET end); int ps_fgets(char *s, int n, GFile *f); epstool-3.08/src/cdoc.h0000644000076400007640000001003010252260054014377 0ustar rjlrjl00000000000000/* Copyright (C) 1993-2005 Ghostgum Software Pty Ltd. All rights reserved. This software is provided AS-IS with no warranty, either express or implied. This software is distributed under licence and may not be copied, modified or distributed except as expressly authorised under the terms of the licence contained in the file LICENCE in this distribution. For more information about licensing, please refer to http://www.ghostgum.com.au/ or contact Ghostsgum Software Pty Ltd, 218 Gallaghers Rd, Glen Waverley VIC 3150, AUSTRALIA, Fax +61 3 9886 6616. */ /* $Id: cdoc.h,v 1.9 2005/01/14 08:15:52 ghostgum Exp $ */ /* Document header */ /* Public */ #ifndef Doc_TYPEDEF #define Doc_TYPEDEF typedef struct Doc_s Doc; #endif /* Information about a document, suitable for showing in a dialog */ typedef struct DocInfo_s DocInfo; struct DocInfo_s { TCHAR name[MAXSTR]; TCHAR type[MAXSTR]; TCHAR title[MAXSTR]; TCHAR date[MAXSTR]; TCHAR bbox[MAXSTR]; TCHAR hiresbbox[MAXSTR]; TCHAR orientation[MAXSTR]; TCHAR pageorder[MAXSTR]; TCHAR pagemedia[MAXSTR]; TCHAR pages[MAXSTR]; }; typedef enum DocType_e { DOC_UNKNOWN, DOC_PS, DOC_PDF, DOC_PCL, DOC_BITMAP } DocType; Doc * doc_new(GSview *a); int doc_add(Doc *d, GSview *a); int doc_remove(Doc *d); int doc_ref(Doc *d); int doc_unref(Doc *d); GSview * doc_app(Doc *d); View **doc_views(Doc *doc); int doc_open(Doc *doc, LPCTSTR filename); int doc_close(Doc *doc); DocType doc_type(Doc *doc); BOOL doc_is_open(Doc *doc); void doc_ignore_dsc(Doc *doc, BOOL flag); void doc_dsc_warn(Doc *doc, int level); void doc_verbose(Doc *doc, BOOL verbose); void doc_dump(Doc *doc); int doc_map_page(Doc *doc, int page); int doc_page_limit(Doc *doc, int page); LPCTSTR doc_name(Doc *doc); void doc_info(Doc *doc, DocInfo *info); void doc_ordlabel(Doc *doc, char *buf, int buflen, int page_number); int doc_copyfile(Doc *doc, LPCTSTR filename); /* platform specific */ void doc_savestat(Doc *doc); /* save file length and date/time */ BOOL doc_changed(Doc *doc); /****************************************************/ /* Private */ #ifdef DEFINE_CDOC #include "cpdfscan.h" typedef struct tagTEXTINDEX { int word; /* offset to word */ int line; /* line number on page */ CDSCBBOX bbox; } TEXTINDEX; /* If you change this, remember to update doc_begin and doc_end */ struct Doc_s { void *handle; /* Platform specific handle */ /* e.g. pointer to MFC CDocument */ GSview *app; /* GSview app object */ Doc *next; /* next document in list */ int refcount; /* number of views of this document */ /* List of views */ View *viewlist; TCHAR text_name[MAXSTR]; /* name of file containing extracted text */ #ifdef NOTUSED TEXTINDEX *text_index; unsigned int text_index_count; /* number of words in index */ char *text_words; /* storage for words */ #endif TCHAR name[MAXSTR]; /* name of selected document file */ TCHAR tname[MAXSTR]; /* name of temporary file (uncompressed) */ DocType doctype; /* DOC_PS, DOC_PDF, etc. */ BOOL gzip; /* file compressed with gzip */ BOOL bzip2; /* file compressed with bzip2 */ int page_count; DSC_OFFSET length1; /* length of selected file (uncompressed) */ DSC_OFFSET length2; /* length of selected file (uncompressed) */ unsigned long time1; /* date/time of open file */ unsigned long time2; /* date/time of open file */ unsigned int dpi; /* Resolution if available from PJL */ /* If doctype == DOC_PS, the following are used */ CDSC *dsc; /* DSC structure. NULL if not DSC */ #ifdef NOTUSED BOOL ignore_special; /* %%PageOrder: Special to be ignored */ #endif BOOL ignore_dsc; /* DSC comments to be ignored */ int dsc_warn; /* Warning level for DSC comments */ BOOL verbose; /* Enable DSC debug messages */ BOOL ctrld; /* file starts with ^D */ BOOL pjl; /* file starts with HP LaserJet PJL */ /* if doctype == DOC_PDF, the following is used */ PDFSCAN *pdfscan; }; #endif /* DEFINE_CDOC */ epstool-3.08/src/cres.h0000644000076400007640000003643710252260054014446 0ustar rjlrjl00000000000000/* Copyright (C) 2001-2002 Ghostgum Software Pty Ltd. All rights reserved. This software is provided AS-IS with no warranty, either express or implied. This software is distributed under licence and may not be copied, modified or distributed except as expressly authorised under the terms of the licence contained in the file LICENCE in this distribution. For more information about licensing, please refer to http://www.ghostgum.com.au/ or contact Ghostsgum Software Pty Ltd, 218 Gallaghers Rd, Glen Waverley VIC 3150, AUSTRALIA, Fax +61 3 9886 6616. */ /* $Id: cres.h,v 1.4 2003/01/30 09:38:01 ghostgum Exp $ */ /* Resource identifiers for menus and strings */ /* for menus and clang.rc */ #define IDS_APPNAME 10 #define IDS_GSVIEWVERSION 11 #define IDM_FILEMENU 100 #define IDM_OPEN 101 #define IDM_SELECT 102 #define IDM_SAVEAS 103 #define IDM_EXTRACT 104 #define IDM_PSTOEPS 105 #define IDM_CLOSE 106 #define IDM_CLOSE_DONE 107 #define IDM_INFO 108 #define IDM_PRINT 110 #define IDM_PRINTTOFILE 111 #define IDM_CONVERTFILE 112 #define IDM_SPOOL 113 #define IDM_GSMESS 114 #define IDM_LASTFILE1 115 #define IDM_LASTFILE2 116 #define IDM_LASTFILE3 117 #define IDM_LASTFILE4 118 #define IDM_EXIT 119 #define IDM_DROP 120 #define IDM_PSTOEDIT 121 #define IDM_ARGS 122 #define IDM_EDITMENU 150 #define IDM_COPYCLIP 151 #define IDM_PASTETO 152 #define IDM_CONVERT 153 #define IDM_ADDEPSMENU 154 #define IDM_MAKEEPSI 155 #define IDM_MAKEEPST4 156 #define IDM_MAKEEPST6U 157 #define IDM_MAKEEPST6P 158 #define IDM_MAKEEPSW 159 #define IDM_MAKEEPSU 160 #define IDM_EXTEPSMENU 161 #define IDM_EXTRACTPS 162 #define IDM_EXTRACTPRE 163 #define IDM_TEXTEXTRACT 164 #define IDM_TEXTEXTRACT_SLOW 165 #define IDM_TEXTFIND 166 #define IDM_TEXTFINDNEXT 167 #define IDM_MEASURE 168 #define IDM_OPTIONMENU 174 #define IDM_GSCOMMAND 175 #define IDM_CFG 176 #define IDM_SOUNDS 177 #define IDM_SETTINGS 178 #define IDM_SAVESETTINGS 179 #define IDM_SAFER 180 #define IDM_SAVEDIR 181 #define IDM_BUTTONSHOW 182 #define IDM_FITPAGE 183 #define IDM_AUTOREDISPLAY 185 #define IDM_EPSFCLIP 186 #define IDM_EPSFWARN 187 #define IDM_IGNOREDSC 188 #define IDM_SHOWBBOX 189 #define IDM_UNITMENU 190 #define IDM_UNITPT 191 #define IDM_UNITMM 192 #define IDM_UNITINCH 193 #define IDM_UNITCUSTOM 194 #define IDM_UNITFINE 195 #define IDM_VIEWMENU 200 #define IDM_NEXT 201 #define IDM_NEXTHOME 202 #define IDM_NEXTSKIP 203 #define IDM_PREV 204 #define IDM_PREVHOME 205 #define IDM_PREVSKIP 206 #define IDM_GOTO 207 #define IDM_GOBACK 208 #define IDM_GOFWD 209 #define IDM_REDISPLAY 210 #define IDM_SKIP 211 #define IDM_FULLSCREEN 212 #define IDM_FITWIN 213 #define IDM_OPTIONS 214 #define IDM_ORIENTMENU 220 #define IDM_PORTRAIT 221 #define IDM_LANDSCAPE 222 #define IDM_UPSIDEDOWN 223 #define IDM_SEASCAPE 224 #define IDM_SWAPLANDSCAPE 225 #define IDM_AUTOORIENT 226 #define IDM_DISPLAYSETTINGS 250 #define IDM_ZOOM 251 #define IDM_MAGPLUS 252 #define IDM_MAGMINUS 253 #define IDM_RESOLUTION 254 #define IDM_MEDIAMENU 300 #define IDM_MEDIAFIRST 301 #define IDM_11x17 301 #define IDM_A3 302 #define IDM_A4 303 #define IDM_A5 304 #define IDM_B4 305 #define IDM_B5 306 #define IDM_LEDGER 307 #define IDM_LEGAL 308 #define IDM_LETTER 309 #define IDM_NOTE 310 #define IDM_MEDIALAST 311 #define IDM_USERSIZE 312 #define IDM_USERSIZE1 313 #define IDM_USERSIZE2 314 #define IDM_USERSIZE3 315 #define IDM_USERSIZE4 316 #define IDM_USERSIZE5 317 #define IDM_USERSIZE6 318 #define IDM_USERSIZE7 319 #define IDM_USERSIZE8 320 #define IDM_USERSIZE9 321 #define IDM_USERSIZE10 322 #define IDM_USERSIZE11 323 #define IDM_USERSIZE12 324 #define IDM_USERSIZE13 325 #define MEDIA_USERDEFINED "User Defined" #define IDM_MEDIAROTATE 330 #define IDM_HELPMENU 340 #define IDM_HELPCONTENT 341 #define IDM_HELPSEARCH 342 #define IDM_HELPKEYS 343 #define IDM_ABOUT 344 #define IDM_MISC 345 #define IDM_REGISTER 346 #define IDD_LANG 350 #define IDM_LANGMENU 350 #define IDM_LANGEN 351 /* These language IDs may be reallocated in GSview */ /* but are needed by the setup program */ #define IDM_LANGDE 352 #define IDM_LANGFR 353 #define IDM_LANGIT 354 #define IDM_LANGES 355 #define IDM_LANGGR 356 #define IDM_LANGNL 357 #define IDM_LANGSE 358 #define IDM_LANGLAST 359 #define IDM_PSTOTEXTMENU 370 #define IDM_PSTOTEXTDIS 371 #define IDM_PSTOTEXTNORM 372 #define IDM_PSTOTEXTCORK 373 /* file filters */ #define FILTER_PSALL 0 #define FILTER_PS 1 #define FILTER_EPS 2 #define FILTER_EPI 3 #define FILTER_PDF 4 #define FILTER_ALL 5 #define FILTER_BMP 6 #define FILTER_TIFF 7 #define FILTER_WMF 8 #define FILTER_TXT 9 /* string constants */ #define IDS_SLANGUAGE 601 #define IDS_CODEPAGE 602 #define IDS_HELPFILE 603 #define IDS_HELPTITLE 604 #define IDS_SIGSEGV 605 #define IDS_FILENOTFOUND 606 #define IDS_LANGUAGE 608 #define IDS_ELANGUAGE 609 #define IDS_FILE 610 #define IDS_NOFILE 611 #define IDS_PAGE 612 #define IDS_NOPAGE 613 #define IDS_PAGESPECIAL 614 #define IDS_LANDSCAPE 615 #define IDS_PORTRAIT 616 #define IDS_ASCEND 617 #define IDS_DESCEND 618 #define IDS_SPECIAL 619 #define IDS_PAGEINFO 620 #define IDS_LINKPAGE 621 #define IDS_DEFAULT 622 #define IDS_NOTDEFTAG 623 #define IDS_EPSF 625 #define IDS_EPSI 626 #define IDS_EPST 627 #define IDS_EPSW 628 #define IDS_DSC 629 #define IDS_NOTDSC 630 #define IDS_PDF 631 #define IDS_IGNOREDSC 632 #define IDS_CTRLD 633 #define IDS_PJL 634 #define IDS_DCS2 635 #define IDS_OUTPUTFILE 640 #define IDS_PRINTINGALL 641 #define IDS_PRINTFILE 642 #define IDS_PRINTAGAIN 643 #define IDS_SELECTPAGE 645 #define IDS_SELECTPAGES 646 #define IDS_NOTOPEN 649 #define IDS_CANNOTRUN 650 #define IDS_TOOLONG 651 #define IDS_NOMORE 652 #define IDS_GSCOMMAND 653 #define IDS_NOZOOM 656 #define IDS_USERWIDTH 657 #define IDS_USERHEIGHT 658 #define IDS_BADEPS 659 #define IDS_NOPREVIEW 660 #define IDS_NOTDFNAME 661 #define IDS_NOTEMP 662 #define IDS_CANCELDONE 663 #define IDS_BADCLI 664 #define IDS_DUPOPT 665 #define IDS_TEXTFIND 666 #define IDS_TEXTNOTFIND 667 #define IDS_PRINTPDFPS 668 #define IDS_NOPDFQUICKTEXT 669 #define IDS_BAD_DOSEPS_HEADER 670 #define IDS_PROBABLY_PCL 671 #define IDS_BUSYPRINTING 672 /* PDF messages */ #define IDS_PDFNOPAGE 790 #define IDS_PDFEXTRACTALL 791 #define IDS_USEPDFWRITE 792 /* filter strings */ #define IDS_FILTER_BASE 800 #define IDS_FILTER_PSALL IDS_FILTER_BASE+FILTER_PSALL #define IDS_FILTER_PS IDS_FILTER_BASE+FILTER_PS #define IDS_FILTER_EPS IDS_FILTER_BASE+FILTER_EPS #define IDS_FILTER_EPI IDS_FILTER_BASE+FILTER_EPI #define IDS_FILTER_PDF IDS_FILTER_BASE+FILTER_PDF #define IDS_FILTER_ALL IDS_FILTER_BASE+FILTER_ALL #define IDS_FILTER_BMP IDS_FILTER_BASE+FILTER_BMP #define IDS_FILTER_TIFF IDS_FILTER_BASE+FILTER_TIFF #define IDS_FILTER_WMF IDS_FILTER_BASE+FILTER_WMF #define IDS_FILTER_TXT IDS_FILTER_BASE+FILTER_TXT #define IDS_LARGEMEDIA 840 #define IDS_NOTIMPLEMENTED 841 #define IDS_NOLINKTARGET 842 #define IDS_PARSEERROR 844 #define IDS_ZLIB_FAIL 845 #define IDS_BZIP2_FAIL 846 #define IDS_BETAEXPIRED 850 #define IDS_BETAWARN 851 #define IDS_NOPRINTERINI 852 #define IDS_NOINI 853 #define IDS_NEEDTEMP 854 #define IDS_GSNOTINSTALLED 857 #define IDS_GSLIBNOTINSTALLED 858 #define IDS_INVALIDREG 864 #define IDS_UNREGISTERED 865 #define IDS_INVALIDNUMBER 2022 #define IDS_CANTINVERT 2023 #define IDS_UNITNAME 2030 #define IDS_UNITPT 2030 #define IDS_UNITMM 2031 #define IDS_UNITINCH 2032 #define IDS_UNITCUSTOM 2033 #define IDS_UNITFINE 2034 #define DSC_IGNORE_ALL 2231 #define IDS_DSC_INFO 2250 #define IDS_DSC_WARN 2251 #define IDS_DSC_ERROR 2252 #define IDS_DSC_LINEFMT 2253 #define IDM_DSCMENU 2260 #define IDM_DSC_OFF 2261 #define IDM_DSC_ERROR 2262 #define IDM_DSC_WARN 2263 #define IDM_DSC_INFO 2264 /* We must define these directly, without using arithmetic */ /* because OS/2 Resource Compiler won't accept arithmetic */ #define CDSC_RESOURCE_BASE 2400 #define CDSC_RESOURCE_BBOX 2400 #define CDSC_RESOURCE_BBOX2 2401 #define CDSC_RESOURCE_BBOX3 2402 #define CDSC_RESOURCE_EARLY_TRAILER 2404 #define CDSC_RESOURCE_EARLY_TRAILER2 2405 #define CDSC_RESOURCE_EARLY_TRAILER3 2406 #define CDSC_RESOURCE_EARLY_EOF 2408 #define CDSC_RESOURCE_EARLY_EOF2 2409 #define CDSC_RESOURCE_EARLY_EOF3 2410 #define CDSC_RESOURCE_PAGE_IN_TRAILER 2412 #define CDSC_RESOURCE_PAGE_IN_TRAILER2 2413 #define CDSC_RESOURCE_PAGE_IN_TRAILER3 2414 #define CDSC_RESOURCE_PAGE_ORDINAL 2416 #define CDSC_RESOURCE_PAGE_ORDINAL2 2417 #define CDSC_RESOURCE_PAGE_ORDINAL3 2418 #define CDSC_RESOURCE_PAGES_WRONG 2420 #define CDSC_RESOURCE_PAGES_WRONG2 2421 #define CDSC_RESOURCE_PAGES_WRONG3 2422 #define CDSC_RESOURCE_EPS_NO_BBOX 2424 #define CDSC_RESOURCE_EPS_NO_BBOX2 2425 #define CDSC_RESOURCE_EPS_NO_BBOX3 2426 #define CDSC_RESOURCE_EPS_PAGES 2428 #define CDSC_RESOURCE_EPS_PAGES2 2429 #define CDSC_RESOURCE_EPS_PAGES3 2430 #define CDSC_RESOURCE_NO_MEDIA 2432 #define CDSC_RESOURCE_NO_MEDIA2 2433 #define CDSC_RESOURCE_NO_MEDIA3 2434 #define CDSC_RESOURCE_ATEND 2436 #define CDSC_RESOURCE_ATEND2 2437 #define CDSC_RESOURCE_ATEND3 2438 #define CDSC_RESOURCE_DUP_COMMENT 2440 #define CDSC_RESOURCE_DUP_COMMENT2 2441 #define CDSC_RESOURCE_DUP_COMMENT3 2442 #define CDSC_RESOURCE_DUP_TRAILER 2444 #define CDSC_RESOURCE_DUP_TRAILER2 2445 #define CDSC_RESOURCE_DUP_TRAILER3 2446 #define CDSC_RESOURCE_BEGIN_END 2448 #define CDSC_RESOURCE_BEGIN_END2 2449 #define CDSC_RESOURCE_BEGIN_END3 2450 #define CDSC_RESOURCE_BAD_SECTION 2452 #define CDSC_RESOURCE_BAD_SECTION2 2453 #define CDSC_RESOURCE_BAD_SECTION3 2454 #define CDSC_RESOURCE_LONG_LINE 2456 #define CDSC_RESOURCE_LONG_LINE2 2457 #define CDSC_RESOURCE_LONG_LINE3 2458 #define CDSC_RESOURCE_INCORRECT_USAGE 2460 #define CDSC_RESOURCE_INCORRECT_USAGE2 2461 #define CDSC_RESOURCE_INCORRECT_USAGE3 2462 /* Language changing */ #define AASELECTLANGUAGE "Select Language" /* Don't translate this */ /* for xlang.rc */ #define IDS_GSVIEW_COPYRIGHT1 4030 #define IDS_GSVIEW_COPYRIGHT2 4031 #define IDS_GSVIEW_COPYRIGHT3 4032 #define IDS_GS_COPYRIGHT1 4040 #define IDS_GS_COPYRIGHT2 4041 #define IDS_GS_COPYRIGHT3 4042 /* Buttons */ #define IDS_AAOK 4050 #define IDS_AACANCEL 4051 #define IDS_AAEDIT 4052 #define IDS_AADEFAULTS 4053 #define IDS_AAHELP 4054 #define IDS_AANEW 4055 #define IDS_AATEST 4056 #define IDS_AAYES 4057 #define IDS_AANO 4058 #define IDS_AANEXTGT 4059 #define IDS_AABACKLT 4060 #define IDS_AAFINISHGT 4061 #define IDS_AAEXIT 4062 /* About dialog box */ #define IDS_AAABOUTWIN 4070 #define IDS_AAABOUTX11 4072 #define IDS_AACOPY1 4075 #define IDS_AACOPY2 4076 #define IDS_AACOPY4 4077 #define IDS_AACOPY5 4078 #define IDS_AACOPY6 4079 #define IDS_AACOPY7 4080 #define IDS_AACOPY8 4081 #define IDS_AACOPY9 4082 #define IDS_AACOPY10 4083 #define IDS_AACOPY11 4084 #define IDS_AACOPY12 4085 #define IDS_AACOPY13 4086 #define IDS_AACOPY14 4087 #define IDS_AACOPY19 4092 #define IDS_AACOPY20 4093 #define IDS_AAINPUT 4100 /* DSC error dialog box */ #define IDS_AADSC 4110 #define IDS_AAIGNOREALLDSC 4111 /* Info dialog box */ #define IDS_AAINFO 4120 #define IDS_AAFILEC 4121 #define IDS_AATYPEC 4122 #define IDS_AATITLEC 4123 #define IDS_AADATEC 4124 #define IDS_AABOUNDINGBOXC 4125 #define IDS_AAHIRESBOUNDINGBOXC 4126 #define IDS_AAORIENTATIONC 4127 #define IDS_AADEFAULTMEDIAC 4128 #define IDS_AAPAGEORDERC 4129 #define IDS_AAPAGESC 4130 #define IDS_AAPAGEC 4131 #define IDS_AABITMAPC 4132 /* Select port, printer, page dialog boxes */ #define IDS_AASELECTPORT 4150 #define IDS_AASELECTPRINTER 4151 #define IDS_AAPRINTING 4152 #define IDS_AASELECTPAGE 4153 #define IDS_AASELECTPAGES 4154 /* Convert and Printer Setup dialog box */ #define IDS_AAPRINTERSETUP 4160 #define IDS_AADEVICEC 4161 #define IDS_AARESOLUTIONC 4162 #define IDS_AAQUEUEC 4163 #define IDS_AAPRINTTOFILE 4164 #define IDS_AAPSPRINTER 4165 #define IDS_AAOPTIONSC 4166 #define IDS_AAFIXEDMEDIA 4167 #define IDS_AACONVERT 4168 #define IDS_AAWINPRINTERSETTINGS 4169 #define IDS_AACOLOURS 4170 #define IDS_AABANDW 4171 #define IDS_AAGREY 4172 #define IDS_AAFULLCOLOUR 4173 #define IDS_AASELECTGSDEVICE 4174 #define IDS_AAODDEVEN 4180 #define IDS_AAIGNOREDSC 4181 #define IDS_AAPAGES 4182 #define IDS_AAFROMC 4183 #define IDS_AATOC 4184 #define IDS_AAADVANCED 4190 #define IDS_AAADVANCEDPSOPT 4191 #define IDS_AASENDCTRLDBEFORE 4192 #define IDS_AASENDCTRLDAFTER 4193 #define IDS_AAPROLOGFILE 4194 #define IDS_AAEPILOGFILE 4195 #define IDS_AABROWSE 4196 /* PS2EPS dialog box */ #define IDS_AAPSTOEPS 4210 #define IDS_AAPSTOEPSREAD 4211 #define IDS_AAPSTOEPSAUTO 4212 #define IDS_AAAPROPERTIES 4220 #define IDS_AAALLPAGES 4221 #define IDS_AAODDPAGES 4222 #define IDS_AAEVENPAGES 4223 #define IDS_AAALL 4224 #define IDS_AAODD 4225 #define IDS_AAEVEN 4226 #define IDS_AAREVERSE 4227 /* Properties dialog box */ #define IDS_AAPROPERTIES 4230 #define IDS_AAPROPERTYC 4231 #define IDS_AAVALUEC 4232 #define IDS_AAPAGEOFFSETPT 4233 #define IDS_AAXC 4234 #define IDS_AAYC 4235 /* Edit Properties dialog box */ #define IDS_AAEDITPROPERTIES 4240 #define IDS_AAPROPERTYTYPEC 4241 #define IDS_AANUMBER 4242 #define IDS_AASTRING 4243 #define IDS_AANAMEC 4244 #define IDS_AAVALUESC 4245 #define IDS_AADELETE 4246 #define IDS_AABOUNDINGBOX 4250 /* Advanced Configure dialog box */ #define IDS_AACONFIGUREGS 4260 #define IDS_AAGHOSTSCRIPTDLLC 4261 #define IDS_AAGHOSTSCRIPTINCC 4262 #define IDS_AAGHOSTSCRIPTOTHERC 4263 #define IDS_AAGHOSTSCRIPTSOC 4268 #define IDS_AAGHOSTSCRIPTEXEC 4269 /* Easy Configure dialog box */ #define IDS_AAEASYCONFIGURE 4270 #define IDS_AAWHICHGS 4271 /* Download Ghostscript dialog box */ #define IDS_AADOWNLOADGS 4280 #define IDS_AADOWNLOADNOW 4281 #define IDS_AAGSNOTFOUND 4282 #define IDS_AAGSMESSWIN 4290 #define IDS_AAGSMESSPM 4291 #define IDS_AAGSMESSX11 4292 #define IDS_AACOPY 4293 /* Display Settings dialog box */ #define IDS_AADISPLAYSETTINGS 4300 #define IDS_AARESOLUTION 4301 #define IDS_AAZOOMRESOLUTION 4302 #define IDS_AADEPTH 4303 #define IDS_AATEXTALPHA 4304 #define IDS_AAGRAPHICSALPHA 4305 #define IDS_AADRAWMETHOD 4306 #define IDS_AADPI 4307 #define IDS_AABPP 4308 #define IDS_AABITS 4309 /* Measure and custom units dialog box */ #define IDS_AAPT 4320 #define IDS_AAMM 4321 #define IDS_AAINCH 4322 #define IDS_AACUSTOM 4323 #define IDS_AAMEASURE 4324 #define IDS_AAUNITC 4325 #define IDS_AASTARTC 4326 #define IDS_AAFINISHC 4327 #define IDS_AADELTAC 4328 #define IDS_AALENGTHC 4329 #define IDS_AACHANGE 4330 #define IDS_AACALCXFORM 4331 #define IDS_AATRANSLATE 4332 #define IDS_AAROTATE 4333 #define IDS_AASCALE 4334 #define IDS_AAINITMATRIX 4335 #define IDS_AAINVERTMATRIX 4336 /* PS to Edit dialog box */ #define IDS_AAPSTOEDIT 4340 #define IDS_AAFORMATC 4341 #define IDS_AADRAWTASP 4342 #define IDS_AAMAPTOLATIN1 4343 #define IDS_AAFLATNESSC 4344 #define IDS_AADEFAULTFONTC 4345 #define IDS_AADRIVEROPTIONSC 4346 /* Registration */ #define IDS_AAREGTOC 4350 #define IDS_AANUMBERC 4351 #define IDS_AAGSVIEWREG 4352 #define IDS_AAREGISTERNOW 4353 #define IDS_AAONLINEREG 4354 #define IDS_AAREG1 4355 #define IDS_AAREG2 4356 #define IDS_AANAG1 4357 #define IDS_AANAG2 4358 #define IDS_AANAG3 4359 #define IDS_AANAG4 4360 #define IDS_AANAG5 4361 /* Language changing */ #define IDS_AASELECTLANGUAGE 4500 #define IDS_AAENGLISH 4501 #define IDS_AADEUTSCH 4502 #define IDS_AAFRANCAIS 4503 #define IDS_AAITALIANO 4504 #define IDS_AAESPANOL 4505 #define IDS_AAGREEK 4506 #define IDS_AANEDERLANDS 4507 #define IDS_AASVENSKA 4508 #define IDS_WINHELPFILE 4510 epstool-3.08/src/cpagec.h0000644000076400007640000000256510252260054014727 0ustar rjlrjl00000000000000/* Copyright (C) 2001-2002 Ghostgum Software Pty Ltd. All rights reserved. This software is provided AS-IS with no warranty, either express or implied. This software is distributed under licence and may not be copied, modified or distributed except as expressly authorised under the terms of the licence contained in the file LICENCE in this distribution. For more information about licensing, please refer to http://www.ghostgum.com.au/ or contact Ghostsgum Software Pty Ltd, 218 Gallaghers Rd, Glen Waverley VIC 3150, AUSTRALIA, Fax +61 3 9886 6616. */ /* $Id: cpagec.h,v 1.1 2002/04/17 11:39:07 ghostgum Exp $ */ /* Page cache header */ /* Public */ void pt_to_pixel(PAGESPEC *ps, double *x, double *y); void pixel_to_pt(PAGESPEC *ps, double *x, double *y); PAGECACHE *pagecache_new(GSview *app, GSREQ *req, IMAGE *img, PDFLINK *pdflinks); PAGECACHE * pagecache_find(GSview *app, PAGESPEC *ps); int pagecache_unref(GSview *app, PAGECACHE *page); int pagecache_unref_all(GSview *app) ; /****************************************************/ /* Private */ #ifdef DEFINE_CPAGEC /* page cache */ struct PAGECACHE_s { PAGECACHE *next; /* linked list */ int refcount; /* number of views using this image */ PAGESPEC pagespec; /* changes to img must be protected by app_lock */ IMAGE img; PDFLINK *pdflink; }; #endif /* DEFINE_CPAGEC */ epstool-3.08/src/cprofile.c0000644000076400007640000002303410252260054015275 0ustar rjlrjl00000000000000/* Copyright (C) 1993-2001, Ghostgum Software Pty Ltd. All rights reserved. This file is part of GSview. This program is distributed with NO WARRANTY OF ANY KIND. No author or distributor accepts any responsibility for the consequences of using it, or for whether it serves any particular purpose or works at all, unless he or she says so in writing. Refer to the GSview Free Public Licence (the "Licence") for full details. Every copy of GSview must include a copy of the Licence, normally in a plain ASCII text file named LICENCE. The Licence grants you the right to copy, modify and redistribute GSview, but only under certain conditions described in the Licence. Among other things, the Licence requires that the copyright notice and this notice be preserved on all copies. */ /* $Id: cprofile.c,v 1.3 2002/05/29 11:39:43 ghostgum Exp $ */ /* Common profile (INI file) routines */ /* Windows provides good Profile functions. * OS/2 provides binary profile functions which don't allow * easy editing of the INI file. * Unix doesn't have generic profile functions. * * To keep things consistent, these profile routines write * text INI files compatible with Windows. * Hand editing is easy. * * profile_open() reads the entire profile into memory. * For efficiency, try to avoid repeated opening and closing the profile. */ #include #include #include #include "cplat.h" #define DEFINE_CPROFILE #include "cprofile.h" #ifndef min #define min(a,b) ((a) < (b) ? (a) : (b)) #endif /* free keys in the section, but not the section itself */ static void profile_free_section(prfsection *section) { prfentry *pe, *ne; pe = section->entry; while (pe) { /* free this entry */ if (pe->name) free(pe->name); if (pe->value) free(pe->value); ne = pe->next; free(pe); pe = ne; } if (section->name) free(section->name); } static PROFILE * profile_cleanup(PROFILE *prf) { prfsection *ps, *ns; if (prf == (PROFILE *)NULL) return NULL; if (prf->file) fclose(prf->file); ps = prf->section; while (ps) { /* free this section */ profile_free_section(ps); ns = ps->next; free(ps); ps = ns; } if (prf->name) free(prf->name); free(prf); return NULL; } PROFILE * profile_open(LPCTSTR filename) { char line[256]; PROFILE *prf; prfsection *ps, *ns; prfentry *pe, *ne; char *p; int len; if ( (prf = (PROFILE *)malloc(sizeof(PROFILE))) == (PROFILE *)NULL ) return (PROFILE *)NULL; prf->changed = FALSE; prf->section = NULL; len = (int)cslen(filename)+1; if ( (prf->name = (TCHAR *)malloc(len*sizeof(TCHAR))) == (TCHAR *)NULL ) return profile_cleanup(prf); csncpy(prf->name, filename, len); if ( (prf->file = csfopen(filename, TEXT("r"))) == (FILE *)NULL ) return prf; /* file doesn't exist - we may be creating it */ ps = ns = NULL; pe = ne = NULL; while (fgets(line, sizeof(line), prf->file)) { if (line[0] == '[') { /* new section */ if ( (ns = (prfsection *)malloc(sizeof(prfsection))) == (prfsection *)NULL ) return profile_cleanup(prf); ns->name = NULL; ns->entry = NULL; ns->next = NULL; if (ps) ps->next = ns; else prf->section = ns; ps = ns; pe = NULL; if ( (p = strchr(line+1, ']')) != (char *)NULL ) *p = '\0'; len = (int)strlen(line); if ( (ns->name = (char *)malloc(len)) == (char *)NULL ) return profile_cleanup(prf); strncpy(ns->name, line+1, len); } else { /* new entry */ if (ns == (prfsection *)NULL) continue; if ( (p = strchr(line, '\n')) != (char *)NULL ) *p = '\0'; if (line[0] == '\0') continue; if ( (ne = (prfentry *)malloc(sizeof(prfentry))) == (prfentry *)NULL ) return profile_cleanup(prf); ne->name = NULL; ne->value = NULL; ne->next = NULL; if (pe) pe->next = ne; else ns->entry = ne; pe = ne; if (line[0] == ';') { /* comment line */ len = (int)strlen(line)+1; if ( (ne->value = (char *)malloc(len)) == (char *)NULL ) return profile_cleanup(prf); strncpy(ne->value, line, len); } else { /* a real entry */ strtok(line, "="); len = (int)strlen(line)+1; if ( (ne->name = (char *)malloc(len)) == (char *)NULL ) return profile_cleanup(prf); strncpy(ne->name, line, len); p = line + strlen(line) + 1; /* if ( (p = strtok(NULL, "=")) == (char *)NULL ) continue; */ len = (int)strlen(p)+1; if ( (ne->value = (char *)malloc(len)) == (char *)NULL ) return profile_cleanup(prf); strncpy(ne->value, p, len); } } } fclose(prf->file); prf->file = NULL; return prf; } int profile_read_string(PROFILE *prf, const char *section, const char *entry, const char *def, char *buffer, int len) { prfsection *ps; prfentry *pe; int count; int slen; char *p; if (prf == (PROFILE *)NULL) return 0; if (buffer == (char *)NULL) return 0; ps = prf->section; if (section == NULL) { /* return all section names */ count = 0; p = buffer; *p = '\0'; while (ps) { slen = (int)strlen(ps->name)+ 1; if ( ps->name && ((slen + 2 + count) < len) ) { strncpy(p, ps->name, slen); count += (int)strlen(ps->name) + 1; p = buffer + count; } ps = ps->next; } *p = '\0'; return count; } while (ps) { if (strcmp(ps->name, section) == 0) break; ps = ps->next; } if (ps == (prfsection *)NULL) { strncpy(buffer, def, len); return min((int)strlen(buffer), len); } /* found section */ pe = ps->entry; if (entry == NULL) { /* return all entry names */ count = 0; p = buffer; *p = '\0'; while (pe) { slen = (int)strlen(pe->name)+1; if ( pe->name && ((int)(count + slen + 2) < len) ) { strncpy(p, pe->name, slen); count += (int)strlen(pe->name) + 1; p = buffer + count; } pe = pe->next; } *p = '\0'; return count; } while (pe) { if (pe->name && (strcmp(pe->name, entry) == 0)) break; pe = pe->next; } if ( (pe == (prfentry *)NULL) || (pe->value == (char *)NULL) ) { strncpy(buffer, def, len); return min((int)strlen(buffer), len); } /* return value */ strncpy(buffer, pe->value, len); /* got it! */ return min((int)strlen(buffer), len); } BOOL profile_write_string(PROFILE *prf, const char *section, const char *entry, const char *value) { prfsection *ps, *ns; prfentry *pe, *ne; int slen; if (prf == (PROFILE *)NULL) return FALSE; ns = prf->section; ps = NULL; while (ns) { if (strcmp(ns->name, section) == 0) break; ps = ns; ns = ns->next; } if (entry == (char *)NULL) { /* delete section */ if (ns == (prfsection *)NULL) return TRUE; profile_free_section(ns); if (ps) ps->next = ns->next; else prf->section = ns->next; free(ns); prf->changed = TRUE; return TRUE; } if (ns == (prfsection *)NULL) { /* add section */ if ( (ns = (prfsection *)malloc(sizeof(prfsection))) == (prfsection *)NULL ) return FALSE; ns->name = NULL; ns->entry = NULL; ns->next = NULL; if (ps) ps->next = ns; else prf->section = ns; ps = ns; pe = NULL; slen = (int)strlen(section)+1; if ( (ns->name = (char *)malloc(slen)) == (char *)NULL ) return FALSE; strncpy(ns->name, section, slen); } ne = ns->entry; pe = NULL; while (ne) { if (ne->name && (strcmp(ne->name, entry) == 0)) break; pe = ne; ne = ne->next; } if (ne == (prfentry *)NULL) { /* add new entry */ if ( (ne = (prfentry *)malloc(sizeof(prfentry))) == (prfentry *)NULL ) return FALSE; ne->name = NULL; ne->value = NULL; ne->next = NULL; if (pe) pe->next = ne; else ns->entry = ne; pe = ne; slen = (int)strlen(entry)+1; if ( (ne->name = (char *)malloc(slen)) == (char *)NULL ) return FALSE; strncpy(ne->name, entry, slen); } if (ne->value != (char *)NULL) free(ne->value); /* release old value */ if (value) { /* change value */ slen = (int)strlen(value)+1; if ( (ne->value = (char *)malloc(slen)) == (char *)NULL ) return FALSE; strncpy(ne->value, value, slen); } else { /* delete entry */ free(ne->name); if (pe) pe->next = ne->next; else ns->entry = ne->next; free(ne); } prf->changed = TRUE; return TRUE; } BOOL profile_close(PROFILE *prf) { prfsection *ps; prfentry *pe; if (prf == (PROFILE *)NULL) return FALSE; if (prf->changed) { if ( (prf->file = csfopen(prf->name, TEXT("w"))) == (FILE *)NULL ) { profile_cleanup(prf); return FALSE; } ps = prf->section; while (ps) { if (ps->name) fprintf(prf->file, "[%s]\n", ps->name); pe = ps->entry; while (pe) { if (pe->name) { if (pe->value) fprintf(prf->file, "%s=%s\n", pe->name, pe->value); else fprintf(prf->file, "%s=\n", pe->name); } else { if (pe->value) fprintf(prf->file, "%s\n", pe->value); } pe = pe->next; } fprintf(prf->file, "\n"); ps = ps->next; } } profile_cleanup(prf); return TRUE; } epstool-3.08/src/clzw.h0000644000076400007640000000323310252260054014455 0ustar rjlrjl00000000000000/* Copyright (C) 2004 Ghostgum Software Pty Ltd. All rights reserved. This software is provided AS-IS with no warranty, either express or implied. This software is distributed under licence and may not be copied, modified or distributed except as expressly authorised under the terms of the licence contained in the file LICENCE in this distribution. For more information about licensing, please refer to http://www.ghostgum.com.au/ or contact Ghostsgum Software Pty Ltd, 218 Gallaghers Rd, Glen Waverley VIC 3150, AUSTRALIA, Fax +61 3 9886 6616. */ /* $Id: clzw.h,v 1.1 2004/07/08 09:14:34 ghostgum Exp $ */ /* LZW compression, compatible with PostScript LZWDecode filter */ /* Structure for holding LZW compressor state */ typedef struct lzw_state_s lzw_state_t; /* allocate and initialise an LZW compressor */ lzw_state_t *lzw_new(void); /* * Compress a buffer with LZW. * Inputs: * inbuf is input buffer * *inlen is count of bytes in the input buffer * outbuf is output buffer * *outlen is the length of the output buffer * Outputs: * *inlen is count of used input bytes * *outlen is the count of output bytes produced * If the output *inlen is not equal to the input *inlen, * then output buffer is full and lzw_compress should * be called again with the remaining input bytes * and another output buffer. * To signal EOD, call with *inlen = 0. */ void lzw_compress(lzw_state_t *state, const unsigned char *inbuf, int *inlen, unsigned char *outbuf, int *outlen); /* * Free the LZW structure * You must first have signalled EOD to lzw_compress, * otherwise you will lose data. */ void lzw_free(lzw_state_t *state); epstool-3.08/src/cmbcs.c0000644000076400007640000001070010252260054014555 0ustar rjlrjl00000000000000/* Copyright (C) 2002 Ghostgum Software Pty Ltd. All rights reserved. This software is provided AS-IS with no warranty, either express or implied. This software is distributed under licence and may not be copied, modified or distributed except as expressly authorised under the terms of the licence contained in the file LICENCE in this distribution. For more information about licensing, please refer to http://www.ghostgum.com.au/ or contact Ghostsgum Software Pty Ltd, 218 Gallaghers Rd, Glen Waverley VIC 3150, AUSTRALIA, Fax +61 3 9886 6616. */ /* $Id: cmbcs.c,v 1.6 2002/08/01 08:27:52 ghostgum Exp $ */ /* Multiple Byte Character Set */ /* * GSview uses Unicode on Windows. * On Linux it may use a multiple byte character set, * such as UTF-8, EUC, Shift-JIS. * This file provides support for stepping over multiple byte * characters. This is needed when searching for a particular * characters such as a tab, space, slash or backslash. * We assume that the null character will not occur within * a MBCS string, and use the C strlen(str)+1 to get the byte * count for allocating memory. * * For Japanese text on Unix, EUC is most commonly used, SJIS is often * used, UTF-8 and UCS-2 are rarely used. * For Japanese filenames on Unix, SJIS is most commonly used * (for compatibility with Windows), EUC and UTF-8 are sometimes used, * UCS-2 is rarely used. * GSview only searches for characters in TCHAR strings we may be able * to handle filenames in a different encoding by doing the translation * in cs_to_narrow(). * * FIX: explain TCHAR, cs, MBCS. */ #include "common.h" #ifndef UNICODE CODEPAGE global_codepage = CODEPAGE_SBCS; /* GLOBAL */ /* Return number of bytes from current character to start of * next character. */ int char_next(const char *str) { int i; const unsigned char *t = (const unsigned char *)str; switch (global_codepage) { default: case CODEPAGE_SBCS: i = 1; break; case CODEPAGE_UTF8: if (t[0] == 0) i = 0; else if ((t[0] > 0) && (t[0] <= 0x7f)) i = 1; else { /* multiple byte UTF-8 */ /* scan until we find a byte in a suitable range */ i = 0; while (t[i] && (t[i] >= 0x80) && (t[i] <= 0xbf)) i++; } break; case CODEPAGE_EUC: if (t[0] == 0x8f) { /* 3 bytes */ if (t[1] == '\0') i = 1; else if (t[2] == '\0') i = 2; else i = 3; } else if (t[0] & 0x80) { /* 2 bytes */ if (str[1] == '\0') i = 1; else i = 2; } else i = 1; case CODEPAGE_SJIS: if (t[0] == 0) { i = 0; } else if ((t[0] > 0) && (t[0] <= 0x7f)) { i = 1; } else if ((t[0] >= 0x80) && (t[0] <= 0xbf)) { if (t[1] == '\0') i = 1; else i = 2; } else if ((t[0] >= 0xa0) && (t[0] <= 0xdf)) { i = 1; } else if ((t[0] >= 0xe0) && (t[0] <= 0xef)) { if (t[1] == '\0') i = 1; else i = 2; } else i = 1; } return i; } /* This implementation is for systems that don't support wide characters */ /* Convert a cs (wide or narrow) string to a narrow string. * If the output narrow string needs to be null terminated, * the input string length needs to include the null. * Returns the number of characters written to the narrow string. * If nlen is 0, the function returns the needed buffer size for nstr. * If the function fails, it returns 0. */ int char_to_narrow(char *nstr, int nlen, LPCTSTR wstr, int wlen) { /* no translation */ if (nlen == 0) return wlen; if (nlen < wlen) return 0; memcpy(nstr, wstr, wlen); return wlen; } /* opposite of char_to_narrow */ int narrow_to_char(TCHAR *wstr, int wlen, const char *nstr, int nlen) { /* no translation */ if (wlen == 0) return nlen; if (wlen < nlen) return 0; memcpy(wstr, nstr, nlen); return nlen; } #endif /* Convert ISO-Latin1 str to UTF-8 ustr. * Return byte length of UTF-8 string. * If ustr is NULL or insufficient space don't copy. * This is needed for the gtk+ user interface. */ int latin1_to_utf8(char *ustr, int ulen, const char *str, int slen) { int i, j; const char *p = str; int len = slen; for (i=0; i> 6)); ustr[j++] = (char)(0x80 | (*p & 0x3f)); } else ustr[j++] = *p; p++; } } return len; } epstool-3.08/src/epstool.c0000644000076400007640000023516310252260054015167 0ustar rjlrjl00000000000000/* Copyright (C) 1995-2005 Ghostgum Software Pty Ltd. All rights reserved. This software is provided AS-IS with no warranty, either express or implied. This software is distributed under licence and may not be copied, modified or distributed except as expressly authorised under the terms of the licence contained in the file LICENCE in this distribution. For more information about licensing, please refer to http://www.ghostgum.com.au/ or contact Ghostsgum Software Pty Ltd, 218 Gallaghers Rd, Glen Waverley VIC 3150, AUSTRALIA, Fax +61 3 9886 6616. */ /* $Id: epstool.c,v 1.69 2005/06/10 08:45:36 ghostgum Exp $ */ #include "common.h" #include "dscparse.h" #include "errors.h" #include "iapi.h" #include "gdevdsp.h" #define DEFINE_COPT #include "copt.h" #define DEFINE_CAPP #include "capp.h" #include "cbmp.h" #define DEFINE_CDOC #include "cdoc.h" #include "cdll.h" #include "cgssrv.h" #include "cmac.h" #include "ceps.h" #include "cimg.h" #include "cpagec.h" #include "cres.h" #ifdef __WIN32__ #include "wgsver.h" #endif #if defined(UNIX) || defined(OS2) #include #include #include #endif const char *epstool_name = "epstool"; const char *epstool_version = "3.08"; /* should be EPSTOOL_VERSION */ const char *epstool_date = "2005-06-06"; /* should be EPSTOOL_DATE */ const char *copyright = "Copyright 1995-2005 Ghostgum Software Pty Ltd"; const char *cmd_help = "\ Commands (one only):\n\ --add-tiff4-preview or -t4\n\ --add-tiff6u-preview or -t6u\n\ --add-tiff6p-preview or -t6p\n\ --add-tiff-preview or -tg\n\ --add-interchange-preview or -i\n\ --add-metafile-preview or -w\n\ --add-pict-preview\n\ --add-user-preview filename\n\ --dcs2-multi\n\ --dcs2-single\n\ --dcs2-report\n\ --extract-postscript or -p\n\ --extract-preview or -v\n\ --bitmap\n\ --copy\n\ --dump\n\ --help or -h\n\ --test-eps\n\ --version\n\ "; const char *opt_help = "\ Options:\n\ --bbox or -b\n\ --combine-separations filename\n\ --combine-tolerance pts\n\ --custom-colours filename\n\ --debug or -d\n\ --device name\n\ --doseps-reverse\n\ --dpi resolution\n\ --dpi-render resolution\n\ --ignore-information\n\ --ignore-warnings\n\ --ignore-errors\n\ --gs command\n\ --gs-args arguments\n\ --mac-binary\n\ --mac-double\n\ --mac-rsrc\n\ --mac-single\n\ --missing-separations\n\ --output filename\n\ --page-number\n\ --quiet\n\ --rename-separation old_name new_name\n\ --replace-composite\n\ "; typedef enum { CMD_UNKNOWN, CMD_TIFF4, CMD_TIFF6U, CMD_TIFF6P, CMD_TIFF, CMD_INTERCHANGE, CMD_WMF, CMD_PICT, CMD_USER, CMD_DCS2_MULTI, CMD_DCS2_SINGLE, CMD_DCS2_REPORT, CMD_PREVIEW, CMD_POSTSCRIPT, CMD_BITMAP, CMD_COPY, CMD_DUMP, CMD_HELP, CMD_TEST, CMD_VERSION } CMD; typedef enum{ CUSTOM_CMYK, CUSTOM_RGB } CUSTOM_COLOUR_TYPE; typedef struct CUSTOM_COLOUR_s CUSTOM_COLOUR; struct CUSTOM_COLOUR_s { char name[MAXSTR]; CUSTOM_COLOUR_TYPE type; /* if type=CUSTOM_CMYK */ float cyan; float magenta; float yellow; float black; /* if type=CUSTOM_RGB */ float red; float green; float blue; /* Next colour */ CUSTOM_COLOUR *next; }; typedef struct OPT_s { CMD cmd; TCHAR device[64]; /* --device name for --bitmap or --add-tiff-preview */ BOOL composite; /* --replace-composite */ BOOL bbox; /* --bbox */ int dscwarn; /* --ignore-warnings etc. */ TCHAR gs[MAXSTR]; /* --gs command */ TCHAR gsargs[MAXSTR*4]; /* --gs-args arguments */ TCHAR input[MAXSTR]; /* filename */ TCHAR output[MAXSTR]; /* --output filename or (second) filename */ TCHAR user_preview[MAXSTR]; /* --add-user-preview filename */ BOOL quiet; /* --quiet */ BOOL debug; /* --debug */ BOOL doseps_reverse; /* --doseps-reverse */ float dpi; /* --dpi resolution */ float dpi_render; /* --dpi-render resolution */ BOOL help; /* --help */ TCHAR custom_colours[MAXSTR]; /* --custom-colours filename */ CUSTOM_COLOUR *colours; BOOL missing_separations; /* --missing-separations */ TCHAR combine[MAXSTR]; /* --combine-separations filename */ int tolerance; /* --combine-tolerance pts */ RENAME_SEPARATION *rename_sep; /* --rename-separation */ CMAC_TYPE mac_type; /* --mac-binary, --mac-double, --mac-single */ /* or --mac-rsrc */ int page; /* --page-number for --bitmap */ int image_compress; /* IMAGE_COMPRESS_NONE, RLE, LZW */ int image_encode; /* IMAGE_ENCODE_HEX, ASCII85 */ } OPT; #define MSGOUT stdout #ifdef UNIX const char gsexe[] = "gs"; #define COLOUR_DEVICE "ppmraw" #define GREY_DEVICE "pgmraw" #define MONO_DEVICE "pbmraw" #endif #ifdef OS2 TCHAR gsexe[MAXSTR] = TEXT("gsos2.exe"); #define COLOUR_DEVICE TEXT("bmp16m") #define GREY_DEVICE TEXT("bmpgray") #define MONO_DEVICE TEXT("bmpmono") #endif #ifdef _WIN32 TCHAR gsexe[MAXSTR] = TEXT("gswin32c.exe"); #define COLOUR_DEVICE TEXT("bmp16m") #define GREY_DEVICE TEXT("bmpgray") #define MONO_DEVICE TEXT("bmpmono") #endif static void print_help(void); static void print_version(void); static int parse_args(OPT *opt, int argc, TCHAR *argv[]); static Doc * epstool_open_document(GSview *app, OPT *opt, TCHAR *name); static int epstool_add_preview(Doc *doc, OPT *opt); static int epstool_dcs2_copy(Doc *doc, Doc *doc2, OPT *opt); static int epstool_dcs2_report(Doc *doc); static int epstool_dcs2_composite(Doc *doc, OPT *opt, GFile *compfile); static int epstool_dcs2_check_files(Doc *doc, OPT *opt); static int epstool_extract(Doc *doc, OPT *opt); static int epstool_bitmap(Doc *doc, OPT *opt); static int epstool_copy(Doc *doc, OPT *opt); static int epstool_copy_bitmap(Doc *doc, OPT *opt); static int epstool_test(Doc *doc, OPT *opt); static void epstool_dump_fn(void *caller_data, const char *str); static IMAGE *make_preview_image(Doc *doc, OPT *opt, int page, LPCTSTR device, CDSCBBOX *bbox, CDSCFBBOX *hires_bbox, int calc_bbox); static int make_preview_file(Doc *doc, OPT *opt, int page, LPCTSTR preview, LPCTSTR device, float dpi, CDSCBBOX *bbox, CDSCFBBOX *hires_bbox, int calc_bbox); static int calculate_bbox(Doc *doc, OPT *opt, LPCTSTR psname, CDSCBBOX *bbox, CDSCFBBOX *hires_bbox); static int calc_device_size(float dpi, CDSCBBOX *bbox, CDSCFBBOX *hires_bbox, int *width, int *height, float *xoffset, float *yoffset); static int exec_program(LPTSTR command, int hstdin, int hstdout, int hstderr, LPCTSTR stdin_name, LPCTSTR stdout_name, LPCTSTR stderr_name); static int custom_colours_read(OPT *opt); static CUSTOM_COLOUR *custom_colours_find(OPT *opt, const char *name); static void custom_colours_free(OPT *opt); static int colour_to_cmyk(CDSC *dsc, const char *name, float *cyan, float *magenta, float *yellow, float *black); static void print_version(void) { fprintf(MSGOUT, "%s %s %s\n", epstool_name, epstool_version, epstool_date); } static void print_help(void) { print_version(); fprintf(MSGOUT, "%s\n", copyright); fprintf(MSGOUT, "Usage: epstool command [options] inputfile outputfile\n"); fprintf(MSGOUT, "%s", cmd_help); fprintf(MSGOUT, "%s", opt_help); } /* return 0 on success, or argument index if there is a duplicated * command, a missing parameter, or an unknown argument. */ static int parse_args(OPT *opt, int argc, TCHAR *argv[]) { int arg; const TCHAR *p; memset(opt, 0, sizeof(OPT)); opt->cmd = CMD_UNKNOWN; opt->dpi = 72.0; opt->dpi_render = 0.0; opt->mac_type = CMAC_TYPE_NONE; opt->dscwarn = CDSC_ERROR_NONE; opt->image_encode = IMAGE_ENCODE_ASCII85; opt->image_compress = IMAGE_COMPRESS_LZW; csncpy(opt->gs, gsexe, sizeof(opt->gs)/sizeof(TCHAR)-1); for (arg=1; argcmd != CMD_UNKNOWN) return arg; opt->cmd = CMD_TIFF4; } else if ((cscmp(p, TEXT("--add-tiff6u-preview")) == 0) || (cscmp(p, TEXT("-t6u")) == 0)) { if (opt->cmd != CMD_UNKNOWN) return arg; opt->cmd = CMD_TIFF6U; } else if ((cscmp(p, TEXT("--add-tiff6p-preview")) == 0) || (cscmp(p, TEXT("-t6p")) == 0)) { if (opt->cmd != CMD_UNKNOWN) return arg; opt->cmd = CMD_TIFF6P; } else if ((cscmp(p, TEXT("--add-tiff-preview")) == 0) || (cscmp(p, TEXT("-tg")) == 0)) { if (opt->cmd != CMD_UNKNOWN) return arg; opt->cmd = CMD_TIFF; } else if ((cscmp(p, TEXT("--add-interchange-preview")) == 0) || (cscmp(p, TEXT("-i")) == 0)) { if (opt->cmd != CMD_UNKNOWN) return arg; opt->cmd = CMD_INTERCHANGE; } else if ((cscmp(p, TEXT("--add-metafile-preview")) == 0) || (cscmp(p, TEXT("-w")) == 0)) { if (opt->cmd != CMD_UNKNOWN) return arg; opt->cmd = CMD_WMF; } else if ((cscmp(p, TEXT("--add-pict-preview")) == 0) || (cscmp(p, TEXT("-w")) == 0)) { if (opt->cmd != CMD_UNKNOWN) return arg; opt->cmd = CMD_PICT; } else if (cscmp(p, TEXT("--add-user-preview")) == 0) { if (opt->cmd != CMD_UNKNOWN) return arg; opt->cmd = CMD_USER; arg++; if (arg == argc) return arg; csncpy(opt->user_preview, argv[arg], sizeof(opt->user_preview)/sizeof(TCHAR)-1); } else if (cscmp(p, TEXT("--dcs2-multi")) == 0) { if (opt->cmd != CMD_UNKNOWN) return arg; opt->cmd = CMD_DCS2_MULTI; } else if (cscmp(p, TEXT("--dcs2-single")) == 0) { if (opt->cmd != CMD_UNKNOWN) return arg; opt->cmd = CMD_DCS2_SINGLE; } else if (cscmp(p, TEXT("--dcs2-report")) == 0) { if (opt->cmd != CMD_UNKNOWN) return arg; opt->cmd = CMD_DCS2_REPORT; } else if (cscmp(p, TEXT("--dump")) == 0) { if (opt->cmd != CMD_UNKNOWN) return arg; opt->cmd = CMD_DUMP; } else if (cscmp(p, TEXT("--test-eps")) == 0) { if (opt->cmd != CMD_UNKNOWN) return arg; opt->cmd = CMD_TEST; } else if (cscmp(p, TEXT("--replace-composite")) == 0) { opt->composite = TRUE; } else if (cscmp(p, TEXT("--missing-separations")) == 0) { opt->missing_separations = TRUE; } else if (cscmp(p, TEXT("--combine-separations")) == 0) { arg++; if (arg == argc) return arg; csncpy(opt->combine, argv[arg], sizeof(opt->combine)/sizeof(TCHAR)-1); } else if (cscmp(p, TEXT("--combine-tolerance")) == 0) { char buf[MAXSTR]; arg++; if (arg == argc) return arg; cs_to_narrow(buf, (int)sizeof(buf)-1, argv[arg], (int)cslen(argv[arg])+1); opt->tolerance = atoi(buf); } else if (cscmp(p, TEXT("--rename-separation")) == 0) { RENAME_SEPARATION *rs = opt->rename_sep; arg++; if (arg+1 == argc) return arg; if (rs) { while (rs && (rs->next != NULL)) rs = rs->next; rs->next = (RENAME_SEPARATION *)malloc(sizeof(RENAME_SEPARATION)); rs = rs->next; } else { opt->rename_sep = rs = (RENAME_SEPARATION *)malloc(sizeof(RENAME_SEPARATION)); } if (rs) { char oldname[MAXSTR]; char newname[MAXSTR]; char *p; char *q; int len; memset(rs, 0, sizeof(RENAME_SEPARATION)); rs->next = NULL; memset(oldname, 0, sizeof(oldname)); cs_to_narrow(oldname, (int)sizeof(oldname)-1, argv[arg], (int)cslen(argv[arg])+1); len = (int)strlen(oldname)+1; p = (char *)malloc(len); if (p) { memcpy(p, oldname, len); rs->oldname = p; } arg++; memset(newname, 0, sizeof(newname)); cs_to_narrow(newname, (int)sizeof(newname)-1, argv[arg], (int)cslen(argv[arg])+1); len = (int)strlen(newname)+1; q = (char *)malloc(len); if (q) { memcpy(q, newname, len); rs->newname = q; } if ((p == NULL) || (q == NULL)) { fprintf(stderr, "Out of memory\n"); return arg; } } else { fprintf(stderr, "Out of memory\n"); return arg; } } else if (cscmp(p, TEXT("--custom-colours")) == 0) { arg++; if (arg == argc) return arg; csncpy(opt->custom_colours, argv[arg], sizeof(opt->custom_colours)/sizeof(TCHAR)-1); } else if ((cscmp(p, TEXT("--extract-preview")) == 0) || (cscmp(p, TEXT("-v")) == 0)) { if (opt->cmd != CMD_UNKNOWN) return arg; opt->cmd = CMD_PREVIEW; } else if ((cscmp(p, TEXT("--extract-postscript")) == 0) || (cscmp(p, TEXT("-p")) == 0)) { if (opt->cmd != CMD_UNKNOWN) return arg; opt->cmd = CMD_POSTSCRIPT; } else if (cscmp(p, TEXT("--bitmap")) == 0) { if (opt->cmd != CMD_UNKNOWN) return arg; opt->cmd = CMD_BITMAP; } else if (cscmp(p, TEXT("--copy")) == 0) { if (opt->cmd != CMD_UNKNOWN) return arg; opt->cmd = CMD_COPY; } else if (cscmp(p, TEXT("--device")) == 0) { arg++; if (arg == argc) return arg; csncpy(opt->device, argv[arg], sizeof(opt->device)/sizeof(TCHAR)-1); } else if (cscmp(p, TEXT("--page-number")) == 0) { char buf[MAXSTR]; arg++; if (arg == argc) return arg; cs_to_narrow(buf, (int)sizeof(buf)-1, argv[arg], (int)cslen(argv[arg])+1); opt->page = atoi(buf) - 1; if (opt->page < 0) opt->page = 0; } else if ((cscmp(p, TEXT("--bbox")) == 0) || (cscmp(p, TEXT("-b")) == 0)) { opt->bbox = TRUE; } else if (cscmp(p, TEXT("--ignore-information")) == 0) { opt->dscwarn = CDSC_ERROR_INFORM; } else if (cscmp(p, TEXT("--ignore-warnings")) == 0) { opt->dscwarn = CDSC_ERROR_WARN; } else if (cscmp(p, TEXT("--ignore-errors")) == 0) { opt->dscwarn = CDSC_ERROR_ERROR; } else if (cscmp(p, TEXT("--gs")) == 0) { arg++; if (arg == argc) return arg; csncpy(opt->gs, argv[arg], sizeof(opt->gs)/sizeof(TCHAR)-1); } else if (cscmp(p, TEXT("--gs-args")) == 0) { arg++; if (arg == argc) return arg; csncpy(opt->gsargs, argv[arg], sizeof(opt->gsargs)/sizeof(TCHAR)-1); } else if (cscmp(p, TEXT("--mac-binary")) == 0) { opt->mac_type = CMAC_TYPE_MACBIN; } else if (cscmp(p, TEXT("--mac-double")) == 0) { opt->mac_type = CMAC_TYPE_DOUBLE; } else if (cscmp(p, TEXT("--mac-rsrc")) == 0) { opt->mac_type = CMAC_TYPE_RSRC; } else if (cscmp(p, TEXT("--mac-single")) == 0) { opt->mac_type = CMAC_TYPE_SINGLE; } else if (cscmp(p, TEXT("--output")) == 0) { arg++; if (arg == argc) return arg; csncpy(opt->output, argv[arg], sizeof(opt->output)/sizeof(TCHAR)-1); } else if (cscmp(p, TEXT("--quiet")) == 0) { opt->quiet = TRUE; } else if ((cscmp(p, TEXT("--debug")) == 0) || (cscmp(p, TEXT("-d")) == 0)) { opt->debug = TRUE; } else if ((cscmp(p, TEXT("--doseps-reverse")) == 0) || (cscmp(p, TEXT("-d")) == 0)) { opt->doseps_reverse = TRUE; } else if (cscmp(p, TEXT("--dpi")) == 0) { char buf[MAXSTR]; arg++; if (arg == argc) return arg; cs_to_narrow(buf, (int)sizeof(buf)-1, argv[arg], (int)cslen(argv[arg])+1); opt->dpi = (float)atof(buf); } else if (cscmp(p, TEXT("--dpi-render")) == 0) { char buf[MAXSTR]; arg++; if (arg == argc) return arg; cs_to_narrow(buf, (int)sizeof(buf)-1, argv[arg], (int)cslen(argv[arg])+1); opt->dpi_render = (float)atof(buf); } else if (cscmp(p, TEXT("--image-encode")) == 0) { /* Not in user documentation - for debug purposes only */ char buf[MAXSTR]; arg++; if (arg == argc) return arg; cs_to_narrow(buf, (int)sizeof(buf)-1, argv[arg], (int)cslen(argv[arg])+1); opt->image_encode = atoi(buf); if ((opt->image_encode < IMAGE_ENCODE_HEX) || (opt->image_encode > IMAGE_ENCODE_ASCII85)) opt->image_encode = IMAGE_ENCODE_ASCII85; } else if (cscmp(p, TEXT("--image-compress")) == 0) { /* Not in user documentation - for debug purposes only */ char buf[MAXSTR]; arg++; if (arg == argc) return arg; cs_to_narrow(buf, (int)sizeof(buf)-1, argv[arg], (int)cslen(argv[arg])+1); opt->image_compress = atoi(buf); if ((opt->image_compress < IMAGE_COMPRESS_NONE) || (opt->image_compress > IMAGE_COMPRESS_LZW)) opt->image_compress = IMAGE_COMPRESS_LZW; } else if ((cscmp(p, TEXT("--help")) == 0) || (cscmp(p, TEXT("-h"))==0)) { opt->help = TRUE; if (opt->cmd != CMD_UNKNOWN) return arg; opt->cmd = CMD_HELP; } else if (cscmp(p, TEXT("--version")) == 0) { if (opt->cmd != CMD_UNKNOWN) return arg; opt->cmd = CMD_VERSION; } else if (*p != '-') { if (opt->input[0] == 0) csncpy(opt->input, argv[arg], sizeof(opt->input)/sizeof(TCHAR)-1); else if (opt->output[0] == 0) csncpy(opt->output, argv[arg], sizeof(opt->output)/sizeof(TCHAR)-1); else return arg; } else { return arg; } } return 0; } static Doc * epstool_open_document(GSview *app, OPT *opt, TCHAR *name) { int code; Doc *doc; int require_eps = 1; /* Create a document */ doc = doc_new(app); if (doc == NULL) { debug |= DEBUG_LOG; app_csmsgf(app, TEXT("Failed to create new Doc\n")); app_unref(app); return NULL; } /* Attach it to application */ doc_add(doc, app); doc_dsc_warn(doc, opt->dscwarn); doc_verbose(doc, opt->debug); code = doc_open(doc, name); if (code < 0) { debug |= DEBUG_LOG; app_csmsgf(app, TEXT("Error opening file \042%s\042.\n"), name); code = -1; } else if (code > 0) { debug |= DEBUG_LOG; app_csmsgf(app, TEXT( "Input file \042%s\042 didn't have DSC comments.\n"), name); code = -1; } /* Some features don't require an EPS input */ if (opt->cmd == CMD_DCS2_REPORT) require_eps = 0; if (opt->cmd == CMD_TEST) require_eps = 0; if (opt->cmd == CMD_DUMP) require_eps = 0; if ((opt->cmd == CMD_COPY) && (doc->doctype == DOC_BITMAP)) require_eps = 0; if ((code == 0) && require_eps && ((doc->dsc == NULL) || (!doc->dsc->epsf)) ) { debug |= DEBUG_LOG; app_csmsgf(app, TEXT("Input file \042%s\042 is not EPSF.\n"), name); code = -1; } if ((code == 0) && require_eps && (doc->dsc != NULL)) { if ((doc->dsc->worst_error > CDSC_ERROR_INFORM) && (doc->dsc->worst_error > opt->dscwarn)) { app_csmsgf(app, TEXT("EPS had unacceptable warnings or errors.\n")); code = -1; } } if (code) { doc_close(doc); doc_remove(doc); doc_unref(doc); doc = NULL; } return doc; } #ifdef UNICODE int wmain(int argc, TCHAR *argv[]) #else int main(int argc, char *argv[]) #endif { GSview *app; Doc *doc = NULL; Doc *doc2 = NULL; int code = 0; int i, arg; OPT opt; #ifdef __WIN32__ { /* Find latest version of Ghostscript */ char buf[MAXSTR]; if (find_gs(buf, sizeof(buf)-1, 550, FALSE)) { narrow_to_cs(gsexe, (int)(sizeof(gsexe)/sizeof(TCHAR)-1), buf, (int)strlen(buf)+1); } } #endif memset(&opt, 0, sizeof(opt)); arg = parse_args(&opt, argc, argv); debug = 0; if (opt.debug) { debug = DEBUG_LOG | DEBUG_MEM | DEBUG_GENERAL; opt.quiet = 0; } if (!opt.quiet) debug |= DEBUG_LOG; /* enable output */ if (opt.help) { print_help(); return 1; } if (opt.cmd == CMD_VERSION) { print_version(); return 1; } if (opt.dpi_render < opt.dpi) opt.dpi_render = opt.dpi; app = app_new(NULL, FALSE); if (app == NULL) { fprintf(MSGOUT, "Can't create epstool app\n"); return 1; } if (arg != 0) { debug |= DEBUG_LOG; app_csmsgf(app, TEXT("epstool: Error in command line arguments:\n ")); for (i=0; idsc->dcs2) { debug |= DEBUG_LOG; app_csmsgf(app, TEXT("Ignoring --bbox for DCS 2.0.\n")); opt.bbox = 0; } /* all others are these OK */ break; default: debug |= DEBUG_LOG; app_csmsgf(app, TEXT( "Can't use --bbox with this command. Ignoring --bbox.\n")); opt.bbox = 0; } } if (code == 0) { switch (opt.cmd) { case CMD_TIFF4: case CMD_TIFF6U: case CMD_TIFF6P: case CMD_TIFF: case CMD_INTERCHANGE: case CMD_WMF: case CMD_PICT: case CMD_USER: code = epstool_add_preview(doc, &opt); break; case CMD_DCS2_SINGLE: case CMD_DCS2_MULTI: if (doc->dsc->dcs2) code = epstool_dcs2_check_files(doc, &opt); if (code == 0) code = epstool_dcs2_copy(doc, doc2, &opt); break; case CMD_DCS2_REPORT: code = epstool_dcs2_report(doc); break; case CMD_PREVIEW: case CMD_POSTSCRIPT: code = epstool_extract(doc, &opt); break; case CMD_BITMAP: code = epstool_bitmap(doc, &opt); break; case CMD_COPY: code = epstool_copy(doc, &opt); break; case CMD_TEST: code = epstool_test(doc, &opt); break; case CMD_DUMP: if (doc && doc->dsc) dsc_display(doc->dsc, epstool_dump_fn); break; default: case CMD_UNKNOWN: case CMD_HELP: /* should reach here */ code = -1; break; } } if (doc) { doc_close(doc); doc_remove(doc); /* detach doc from app */ doc_unref(doc); } app_unref(app); #ifdef DEBUG_MALLOC debug_memory_report(); #endif debug &= ~DEBUG_MEM; while (opt.rename_sep) { RENAME_SEPARATION *rs = opt.rename_sep; if (rs->oldname) free((void *)rs->oldname); if (rs->newname) free((void *)rs->newname); opt.rename_sep = rs->next; free(rs); } if (!opt.quiet) fprintf(MSGOUT, "%s\n", code == 0 ? "OK" : "Failed"); if (code != 0) return 1; return code; } /****************************************************************/ static int epstool_add_preview(Doc *doc, OPT *opt) { int code = 0; CDSCBBOX devbbox = {0,0,595,842}; CDSCBBOX bbox = {0, 0, 0, 0}; CDSCFBBOX hires_bbox = {0.0, 0.0, 0.0, 0.0}; CDSCFBBOX *phires_bbox = NULL; const TCHAR *device = COLOUR_DEVICE; FILE *f; TCHAR preview[MAXSTR]; IMAGE *img = NULL; if (opt->device[0] != '\0') device = opt->device; else if (opt->cmd == CMD_INTERCHANGE) device = MONO_DEVICE; if (opt->cmd == CMD_TIFF4) device = MONO_DEVICE; if (doc->dsc->bbox) { bbox = *doc->dsc->bbox; } else opt->bbox = 1; if (doc->dsc->hires_bbox) { hires_bbox = *doc->dsc->hires_bbox; phires_bbox = &hires_bbox; } if (opt->cmd == CMD_USER) { /* Attempt to load BMP or PPM */ /* If these fail, assume it is TIFF or WMF */ img = bmpfile_to_image(opt->user_preview); if (img == NULL) img = pnmfile_to_image(opt->user_preview); } else if (opt->cmd == CMD_TIFF) { /* We'll use ghostscript to make the image. */ } else { img = make_preview_image(doc, opt, 0, device, &bbox, &hires_bbox, opt->bbox); if (img == NULL) { app_csmsgf(doc->app, TEXT("Couldn't make preview image\n")); return -1; } if ((hires_bbox.fllx < hires_bbox.furx) && (hires_bbox.flly < hires_bbox.fury)) phires_bbox = &hires_bbox; } if (img) { devbbox.llx = devbbox.lly = 0; devbbox.urx = img->width; devbbox.ury = img->height; } /* add preview to EPS file */ switch (opt->cmd) { case CMD_TIFF4: code = make_eps_tiff(doc, img, devbbox, &bbox, phires_bbox, opt->dpi, opt->dpi, TRUE, FALSE, opt->doseps_reverse, opt->output); break; case CMD_TIFF6U: code = make_eps_tiff(doc, img, devbbox, &bbox, phires_bbox, opt->dpi, opt->dpi, FALSE, FALSE, opt->doseps_reverse, opt->output); break; case CMD_TIFF6P: code = make_eps_tiff(doc, img, devbbox, &bbox, phires_bbox, opt->dpi, opt->dpi, FALSE, TRUE, opt->doseps_reverse, opt->output); break; case CMD_TIFF: /* create preview file */ preview[0] = '\0'; if ((f = app_temp_file(doc->app, preview, sizeof(preview)/sizeof(TCHAR))) == (FILE *)NULL) { app_csmsgf(doc->app, TEXT("Can't create temporary tiff file \042%s\042\n"), preview); code = -1; } else { fclose(f); if (code == 0) code = make_preview_file(doc, opt, 0, preview, device, opt->dpi, &bbox, &hires_bbox, opt->bbox); if (code == 0) code = make_eps_user(doc, preview, opt->doseps_reverse, opt->output); if (!(debug & DEBUG_GENERAL)) csunlink(preview); } break; case CMD_INTERCHANGE: code = make_eps_interchange(doc, img, devbbox, &bbox, phires_bbox, opt->output); break; case CMD_WMF: code = make_eps_metafile(doc, img, devbbox, &bbox, phires_bbox, opt->dpi, opt->dpi, opt->doseps_reverse, opt->output); break; case CMD_PICT: code = make_eps_pict(doc, img, &bbox, phires_bbox, opt->dpi, opt->dpi, opt->mac_type, opt->output); break; case CMD_USER: if (img) code = make_eps_tiff(doc, img, devbbox, &bbox, phires_bbox, opt->dpi, opt->dpi, FALSE, TRUE, opt->doseps_reverse, opt->output); else code = make_eps_user(doc, opt->user_preview, opt->doseps_reverse, opt->output); break; default: return 0; } if (img) bitmap_image_free(img); return code; } /****************************************************************/ static int epstool_extract(Doc *doc, OPT *opt) { int code; if ((doc->dsc != (CDSC *)NULL) && (doc->dsc->macbin != (CDSCMACBIN *)NULL)) code = extract_macbin(doc, opt->output, opt->cmd == CMD_PREVIEW); else code = extract_doseps(doc, opt->output, opt->cmd == CMD_PREVIEW); return code; } /****************************************************************/ static int epstool_bitmap(Doc *doc, OPT *opt) { int code = 0; CDSCBBOX bbox; CDSCFBBOX hires_bbox; LPCTSTR device = COLOUR_DEVICE; int page = opt->page; if (opt->device[0] != '\0') device = opt->device; if (doc->dsc->bbox) bbox = *doc->dsc->bbox; else { bbox.llx = bbox.lly = bbox.urx = bbox.ury = 0; opt->bbox = 1; } if (doc->dsc->hires_bbox) hires_bbox = *doc->dsc->hires_bbox; else { hires_bbox.fllx = (float)bbox.llx; hires_bbox.flly = (float)bbox.lly; hires_bbox.furx = (float)bbox.urx; hires_bbox.fury = (float)bbox.ury; } if (doc->dsc->page_count == 0) page = 0; else if ((opt->page < 0) || (opt->page >= (int)doc->dsc->page_count)) return -1; /* invalid page */ code = make_preview_file(doc, opt, page, opt->output, device, opt->dpi, &bbox, &hires_bbox, opt->bbox); return code; } /****************************************************************/ static int epstool_copy(Doc *doc, OPT *opt) { int code = 0; /* * "epstool --copy" can also convert a BMP, PBM or PNG to EPS * for testing the DCS 2.0 composite image writing code. * This isn't in the user documentation. */ if (doc->doctype == DOC_BITMAP) return epstool_copy_bitmap(doc, opt); /* Copy an EPS to another EPS */ if (opt->bbox) { CDSCBBOX bbox; CDSCFBBOX hires_bbox; GFile *f; TCHAR tpsname[MAXSTR]; memset(tpsname, 0, sizeof(tpsname)); memset(&bbox, 0, sizeof(bbox)); memset(&hires_bbox, 0, sizeof(hires_bbox)); if (doc->dsc->bbox) memcpy(&bbox, &doc->dsc->bbox, sizeof(bbox)); if (doc->dsc->hires_bbox) memcpy(&hires_bbox, &doc->dsc->hires_bbox, sizeof(hires_bbox)); /* Copy page to temporary file */ if ((f = app_temp_gfile(doc->app, tpsname, sizeof(tpsname)/sizeof(TCHAR))) == (GFile *)NULL) { app_csmsgf(doc->app, TEXT("Can't create temporary ps file \042%s\042\n"), tpsname); return -1; } code = copy_page_temp(doc, f, 0); gfile_close(f); if (code != 0) { if (!(debug & DEBUG_GENERAL)) csunlink(tpsname); return -1; } code = calculate_bbox(doc, opt, tpsname, &bbox, &hires_bbox); if (code == 0) code = copy_eps(doc, opt->output, &bbox, &hires_bbox, 0, FALSE); /* delete temporary ps file */ if (!(debug & DEBUG_GENERAL)) csunlink(tpsname); } else { code = copy_eps(doc, opt->output, doc->dsc->bbox, doc->dsc->hires_bbox, 0, FALSE); } return code; } /* Save a BMP, PBM or PNG as an EPS file */ static int epstool_copy_bitmap(Doc *doc, OPT *opt) { int code = 0; IMAGE *img; img = bmpfile_to_image(doc->name); if (img == NULL) img = pnmfile_to_image(doc->name); if (img == NULL) img = pngfile_to_image(doc->name); if (img == NULL) code = -1; if (code == 0) { GFile *f = NULL; double width = (img->width * 72.0 / opt->dpi); double height = (img->height * 72.0 / opt->dpi); if ((img == NULL) || (img->image == NULL)) code = -1; if (code == 0) { f = gfile_open(opt->output, gfile_modeWrite | gfile_modeCreate); if (f == NULL) { code = -1; app_msgf(doc->app, "Failed to open \042%s\042 for writing\n", opt->output); } } if (code == 0) code = image_to_eps(f, img, 0, 0, (int)(width + 0.999), (int)(height + 0.999), 0.0, 0.0, (float)width, (float)height, opt->image_encode, opt->image_compress); if (f) gfile_close(f); } return code; } /****************************************************************/ /* If multi is TRUE, write DCS 2.0 multiple file, otherwise * write the single file version. */ static int epstool_dcs2_copy(Doc *doc, Doc *doc2, OPT *opt) { GFile *infile = NULL; GFile *doc2file = NULL; GFile *outfile = NULL; DSC_OFFSET complen = 0; int code = 0; GFile *compfile = NULL; TCHAR compname[MAXSTR]; TCHAR temp_outname[MAXSTR]; if (doc->dsc->dcs2 == NULL) { app_csmsgf(doc->app, TEXT("Input file is not DCS 2.0\n")); return -1; } memset(compname, 0, sizeof(compname)); if (opt->composite) { /* Replace composite (first page) with a raster generated * from the separations. */ if ((compfile = app_temp_gfile(doc->app, compname, sizeof(compname)/sizeof(TCHAR))) == (GFile *)NULL) { app_csmsgf(doc->app, TEXT("Can't create temporary composite EPS file \042%s\042\n"), compname); return -1; } custom_colours_read(opt); code = epstool_dcs2_composite(doc, opt, compfile); custom_colours_free(opt); gfile_close(compfile); if (code == 0) { compfile = gfile_open(compname, gfile_modeRead); if (compfile == (GFile *)NULL) code = -1; } if (code) { if (!(debug & DEBUG_GENERAL) && compname[0]) csunlink(compname); return -1; } } /* Let's convert from single file to multi file */ if (code == 0) code = (infile = gfile_open(doc_name(doc), gfile_modeRead)) == (GFile *)NULL; if ((code == 0) && doc2) code = (doc2file = gfile_open(doc_name(doc2), gfile_modeRead)) == (GFile *)NULL; if (opt->cmd == CMD_DCS2_SINGLE) { if (code == 0) /* write first pass to temporary file, not opt->output */ code = (outfile = app_temp_gfile(doc->app, temp_outname, sizeof(temp_outname)/sizeof(TCHAR))) == (GFile *)NULL; if (code == 0) code = copy_dcs2(doc, infile, doc2, doc2file, outfile, temp_outname, 0 /* offset */, FALSE /* multi */, FALSE /* write all */, opt->missing_separations, &complen, compfile, opt->rename_sep, opt->tolerance); gfile_seek(infile, 0, gfile_begin); if (compfile) gfile_seek(compfile, 0, gfile_begin); gfile_close(outfile); outfile = NULL; if (!(debug & DEBUG_GENERAL) && temp_outname[0]) csunlink(temp_outname); } if (code == 0) { code = (outfile = gfile_open(opt->output, gfile_modeWrite | gfile_modeCreate)) == (GFile *)NULL; if (code) app_msgf(doc->app, "Failed to open \042%s\042 for writing\n", opt->output); } if (code == 0) code = copy_dcs2(doc, infile, doc2, doc2file, outfile, opt->output, 0 /* offset */, opt->cmd == CMD_DCS2_MULTI, TRUE /* write all */, opt->missing_separations, &complen, compfile, opt->rename_sep, opt->tolerance); if (infile != (GFile *)NULL) gfile_close(infile); if (doc2file != (GFile *)NULL) gfile_close(doc2file); if (outfile != (GFile *)NULL) gfile_close(outfile); if (compfile != (GFile *)NULL) gfile_close(compfile); if (!(debug & DEBUG_GENERAL) && compname[0]) csunlink(compname); return code; } static int epstool_dcs2_report(Doc *doc) { int i; int code = 0; CDSC *dsc = doc->dsc; const char *type = "Unknown"; const char *preview = "Unknown"; if (dsc && dsc->dcs2) { DSC_OFFSET length = 0; GFile *f; /* Check for missing composite */ if ((dsc->page_count == 0) || (dsc->page[0].begin == dsc->page[0].end)) { app_msgf(doc->app, TEXT("WARNING: Missing composite, so a separation offset is probably wrong.\n")); code = 2; } /* Check for separations that extend beyond EOF */ if ((f = gfile_open(doc_name(doc), gfile_modeRead)) != (GFile *)NULL) { length = gfile_get_length(f); gfile_close(f); } for (i=0; i<(int)dsc->page_count; i++) { if ((dsc->page[i].begin > length) || (dsc->page[i].end > length)) { app_msgf(doc->app, TEXT("WARNING: separation %s extends beyond EOF\n"), dsc->page[i].label); code = 2; } } } /* Document type */ if (dsc == NULL) { if (doc->doctype == DOC_PDF) type = "PDF"; else type = "Unknown"; } else if (dsc->dcs2) { if (dsc->dcs1) type = "DCS1.0"; else type = "DCS2.0"; } else if (dsc->epsf) type = "EPSF"; else if (dsc->pdf) type = "PDF"; else type = "DSC"; fprintf(stdout, "Type\t%s\n", type); if (dsc == NULL) return 1; /* Preview type */ switch (dsc->preview) { default: case CDSC_NOPREVIEW: preview = "None"; break; case CDSC_EPSI: preview = "Interchange"; break; case CDSC_TIFF: preview = "TIFF"; break; case CDSC_WMF: preview = "WMF"; break; case CDSC_PICT: preview = "PICT"; break; } fprintf(stdout, "Preview\t%s\n", preview); if (dsc->bbox) fprintf(stdout, "BoundingBox\t%d\t%d\t%d\t%d\n", dsc->bbox->llx, dsc->bbox->lly, dsc->bbox->urx, dsc->bbox->ury); else fprintf(stdout, "BoundingBox\n"); if (dsc->hires_bbox) fprintf(stdout, "HiBoundingBox\t%g\t%g\t%g\t%g\n", dsc->hires_bbox->fllx, dsc->hires_bbox->flly, dsc->hires_bbox->furx, dsc->hires_bbox->fury); else fprintf(stdout, "HiResBoundingBox\n"); if (!dsc->dcs2) return 1; /* Pages */ for (i=0; i<(int)dsc->page_count; i++) { int found = -1; const char *name = dsc->page[i].label; float cyan, magenta, yellow, black; cyan = magenta = yellow = black = 0.0; if (name == NULL) name = "Unknown"; if (strcmp(name, "Composite") != 0) found = colour_to_cmyk(dsc, name, &cyan, &magenta, &yellow, &black); if (found == 0) fprintf(stdout, "%s\t%lu\t%g\t%g\t%g\t%g\n", name, (unsigned long)(dsc->page[i].end - dsc->page[i].begin), cyan, magenta, yellow, black); else fprintf(stdout, "%s\t%lu\n", name, (unsigned long)(dsc->page[i].end - dsc->page[i].begin)); } return code; } /* Check that all separations actually exist */ static int epstool_dcs2_check_files(Doc *doc, OPT *opt) { int code = 0; int i; CDSC *dsc = doc->dsc; GFile *f; const char *fname; const char **renamed1 = NULL; for (i=1; (i<(int)dsc->page_count); i++) { /* First find length of separation */ fname = dsc_find_platefile(dsc, i); if (fname) { TCHAR wfname[MAXSTR]; narrow_to_cs(wfname, (int)(sizeof(wfname)/sizeof(TCHAR)-1), fname, (int)strlen(fname)+1); if ((f = gfile_open(wfname, gfile_modeRead)) != (GFile *)NULL) { gfile_close(f); } else { if (!opt->missing_separations) code = -1; if (!opt->quiet) app_msgf(doc->app, "Separation \042%s\042 is missing file \042%s\042\n", dsc->page[i].label, fname); } } else { if (dsc->page[i].end <= dsc->page[i].begin) { if (!opt->quiet) app_msgf(doc->app, "Separation \042%s\042 is empty\n", dsc->page[i].label); if (!opt->missing_separations) code = -1; } } } /* Test if duplicate separations would occur */ renamed1 = (const char **)malloc(sizeof(const char *) * dsc->page_count); if (renamed1 != NULL) { if (rename_separations(dsc, opt->rename_sep, renamed1) != 0) { code = -1; if (!opt->quiet) app_msgf(doc->app, "Duplicate separations are not permitted.\n"); } free((void *)renamed1); } return code; } /****************************************************************/ /* Read --custom-colours file etc. */ static int custom_colours_read(OPT *opt) { FILE *f; char line[MAXSTR]; CUSTOM_COLOUR colour; CUSTOM_COLOUR *pcolour; CUSTOM_COLOUR *tail = opt->colours; int i; char *s; int code = 0; if (opt->custom_colours[0]) { /* read CMYK colours from file */ f = csfopen(opt->custom_colours, TEXT("r")); if (f == NULL) return -1; while (tail && tail->next) tail = tail->next; while (fgets(line, sizeof(line), f) != NULL) { memset(&colour, 0, sizeof(colour)); i = 0; s = line; if (strncmp(line, "%%CMYKCustomColor:", 18) == 0) { s += 18; colour.type = CUSTOM_CMYK; while (*s && (*s == ' ')) s++; /* Get the colour values */ s = strtok(s, " \t\r\n"); if (s != NULL) { colour.cyan = (float)atof(s); s = strtok(NULL, " \t\r\n"); } if (s != NULL) { colour.magenta = (float)atof(s); s = strtok(NULL, " \t\r\n"); } if (s != NULL) { colour.yellow = (float)atof(s); s = strtok(NULL, " \t\r\n"); } if (s != NULL) { colour.black = (float)atof(s); s = strtok(NULL, "\t\r\n"); } } else if (strncmp(line, "%%RGBCustomColor:", 17) == 0) { s += 17; colour.type = CUSTOM_RGB; while (*s && (*s == ' ')) s++; /* Get the colour values */ s = strtok(s, " \t\r\n"); if (s != NULL) { colour.red = (float)atof(s); s = strtok(NULL, " \t\r\n"); } if (s != NULL) { colour.green = (float)atof(s); s = strtok(NULL, " \t\r\n"); } if (s != NULL) { colour.blue = (float)atof(s); s = strtok(NULL, "\t\r\n"); } } else { s = NULL; } if (s != NULL) { /* Get the colour name */ while (*s && (*s == ' ')) s++; if (*s == '(') { s++; while (*s && (*s != ')')) { if (i < (int)sizeof(colour.name)-1) colour.name[i++] = *s; s++; } if (*s == ')') s++; } else { while (*s && (*s != ' ') && (*s != '\t') && (*s != '\r') && (*s != '\n')) { if (i < (int)sizeof(colour.name)-1) colour.name[i++] = *s; s++; } } colour.name[i] = '\0'; } if (debug & DEBUG_GENERAL) { if (s == NULL) fprintf(stdout, "Unrecognised line: %s\n", line); else if (colour.type == CUSTOM_CMYK) fprintf(stdout, "CMYK Colour: %g %g %g %g (%s)\n", colour.cyan, colour.magenta, colour.yellow, colour.black, colour.name); else if (colour.type == CUSTOM_RGB) fprintf(stdout, "RGB Colour: %g %g %g (%s)\n", colour.red, colour.green, colour.blue, colour.name); else fprintf(stdout, "Unrecognised colour\n"); } if (s == NULL) { if (code == 0) code = 1; } else { pcolour = (CUSTOM_COLOUR *)malloc(sizeof(CUSTOM_COLOUR)); if (pcolour == NULL) code = -1; else { /* append to list */ memcpy(pcolour, &colour, sizeof(colour)); if (tail) { tail->next = pcolour; tail = pcolour; } else opt->colours = tail = pcolour; } } } fclose(f); } return code; } static void custom_colours_free(OPT *opt) { CUSTOM_COLOUR *pcolour; while (opt->colours) { pcolour = opt->colours; opt->colours = opt->colours->next; free(pcolour); } } static CUSTOM_COLOUR * custom_colours_find(OPT *opt, const char *name) { CUSTOM_COLOUR *pcolour = opt->colours; while (pcolour) { if (strcmp(name, pcolour->name) == 0) break; pcolour = pcolour->next; } return pcolour; } /****************************************************************/ static float round_float(float f, int n) { return (float)( ((int)(f * n + 0.5)) / (float)n ); } /* Calculate the bounding box using the ghostscript bbox device */ static int calculate_bbox(Doc *doc, OPT *opt, LPCTSTR psname, CDSCBBOX *bbox, CDSCFBBOX *hires_bbox) { FILE *bboxfile; TCHAR bboxname[MAXSTR]; TCHAR command[MAXSTR*8]; char line[MAXSTR]; int got_bbox = 0; int got_hires_bbox = 0; int code = 0; int llx, lly, urx, ury; float fllx, flly, furx, fury; const int pagesize = 9400; /* Must be < 9419 on 7.07, < 150976 on 8.x */ const int offset = 3000; if ((bboxfile = app_temp_file(doc->app, bboxname, sizeof(bboxname)/sizeof(TCHAR))) == (FILE *)NULL) { app_csmsgf(doc->app, TEXT("Can't create temporary bbox file \042%s\042\n"), bboxname); return -1; } fclose(bboxfile); csnprintf(command, sizeof(command)/sizeof(TCHAR), TEXT( "\042%s\042 %s -dNOPAUSE -dBATCH -sDEVICE=bbox %s \ -c \042<> setpagedevice\042 -f \042%s\042"), opt->gs, opt->quiet ? TEXT("-dQUIET") : TEXT(""), opt->gsargs, pagesize, pagesize, offset, offset, psname); if (!opt->quiet) app_csmsgf(doc->app, TEXT("%s\n"), command); code = exec_program(command, -1, fileno(stdout), -1, NULL, NULL, bboxname); if (code != 0) app_csmsgf(doc->app, TEXT("Ghostscript failed to obtain bounding box\n")); /* Now scan for bounding box info */ if (code == 0) { if ((bboxfile = csfopen(bboxname, TEXT("rb"))) == (FILE *)NULL) { app_csmsgf(doc->app, TEXT("Can't open temporary bbox file \042%s\042\n"), bboxname); code = -1; } } if (code == 0) { while (fgets(line, sizeof(line), bboxfile) != NULL) { if (strncmp(line, "%%BoundingBox: ", 15) == 0) { if (!opt->quiet) app_msgf(doc->app, "%s", line); if (sscanf(line+15, "%d %d %d %d", &llx, &lly, &urx, &ury) == 4) { bbox->llx = llx-offset; bbox->lly = lly-offset; bbox->urx = urx-offset; bbox->ury = ury-offset; got_bbox = 1; } } else if (strncmp(line, "%%HiResBoundingBox: ", 20) == 0) { if (!opt->quiet) app_msgf(doc->app, "%s", line); if (sscanf(line+20, "%f %f %f %f", &fllx, &flly, &furx, &fury) == 4) { hires_bbox->fllx = round_float(fllx-offset, 1000); hires_bbox->flly = round_float(flly-offset, 1000); hires_bbox->furx = round_float(furx-offset, 1000); hires_bbox->fury = round_float(fury-offset, 1000); got_hires_bbox = 1; } } if (got_bbox && got_hires_bbox) break; } } fclose(bboxfile); if (!(debug & DEBUG_GENERAL)) csunlink(bboxname); if ((code == 0) && (!got_bbox)) { app_csmsgf(doc->app, TEXT("Didn't get bounding box\n")); code = -1; } if ((code == 0) && (!got_hires_bbox)) { app_csmsgf(doc->app, TEXT("Didn't get hires bounding box\n")); code = -1; } return code; } static int calc_device_size(float dpi, CDSCBBOX *bbox, CDSCFBBOX *hires_bbox, int *width, int *height, float *xoffset, float *yoffset) { int code = 0; int hires_bbox_valid = 1; if ((bbox->llx >= bbox->urx) || (bbox->lly >= bbox->ury)) { code = -1; } if ((hires_bbox->fllx > hires_bbox->furx) || (hires_bbox->flly > hires_bbox->fury)) { hires_bbox_valid = 0; code = -1; } if ((hires_bbox->fllx == hires_bbox->furx) || (hires_bbox->flly == hires_bbox->fury)) { hires_bbox_valid = 0; /* ignore hires_bbox */ } /* Make the preview image */ if (hires_bbox_valid) { *width = (int)((hires_bbox->furx - hires_bbox->fllx)*dpi/72.0+0.5); *height = (int)((hires_bbox->fury - hires_bbox->flly)*dpi/72.0+0.5); *xoffset = -hires_bbox->fllx; *yoffset = -hires_bbox->flly; } else { *width = (int)((bbox->urx - bbox->llx)*dpi/72.0+0.5); *height = (int)((bbox->ury - bbox->lly)*dpi/72.0+0.5); *xoffset = (float)(-bbox->llx); *yoffset = (float)(-bbox->lly); } return 0; } static int make_preview_file(Doc *doc, OPT *opt, int page, LPCTSTR preview, LPCTSTR device, float dpi, CDSCBBOX *bbox, CDSCFBBOX *hires_bbox, int calc_bbox) { GFile *f; int code = 0; TCHAR tpsname[MAXSTR]; TCHAR command[MAXSTR*8]; int width, height; float xoffset, yoffset; /* Copy page to temporary file */ if ((f = app_temp_gfile(doc->app, tpsname, sizeof(tpsname)/sizeof(TCHAR))) == (GFile *)NULL) { app_csmsgf(doc->app, TEXT("Can't create temporary ps file \042%s\042\n"), tpsname); return -1; } code = copy_page_temp(doc, f, page); gfile_close(f); if (code != 0) { if (!(debug & DEBUG_GENERAL)) csunlink(tpsname); return -1; } /* Get bbox */ if ((code == 0) && calc_bbox) code = calculate_bbox(doc, opt, tpsname, bbox, hires_bbox); width = height = 0; xoffset = yoffset = 0.0; if (code == 0) code = calc_device_size(dpi, bbox, hires_bbox, &width, &height, &xoffset, &yoffset); if (code) { app_csmsgf(doc->app, TEXT("BoundingBox is invalid\n")); if (!(debug & DEBUG_GENERAL)) csunlink(tpsname); return -1; } /* Make the preview image */ csnprintf(command, sizeof(command)/sizeof(TCHAR), TEXT("\042%s\042 %s -dNOPAUSE -dBATCH -sDEVICE=%s -sOutputFile=\042%s\042 -r%g -g%dx%d %s -c %f %f translate -f \042%s\042"), opt->gs, opt->quiet ? TEXT("-dQUIET") : TEXT(""), device, (preview[0]=='\0' ? TEXT("-") : preview), dpi, width, height, opt->gsargs, xoffset, yoffset, tpsname); if (!opt->quiet) app_csmsgf(doc->app, TEXT("%s\n"), command); code = exec_program(command, -1, fileno(stdout), fileno(stderr), NULL, NULL, NULL); if (code != 0) app_csmsgf(doc->app, TEXT("Ghostscript failed to create preview image\n")); /* delete temporary ps file */ if (!(debug & DEBUG_GENERAL)) csunlink(tpsname); return code; } static IMAGE * make_preview_image(Doc *doc, OPT *opt, int page, LPCTSTR device, CDSCBBOX *bbox, CDSCFBBOX *hires_bbox, int calc_bbox) { IMAGE *img = NULL; IMAGE *newimg = NULL; TCHAR preview[MAXSTR]; GFile *f; int code = 0; /* Create a temporary file for ghostscript bitmap output */ if ((f = app_temp_gfile(doc->app, preview, sizeof(preview)/sizeof(TCHAR))) == (GFile *)NULL) { app_csmsgf(doc->app, TEXT("Can't create temporary bitmap file \042%s\042\n"), preview); code = -1; } else gfile_close(f); if (code == 0) code = make_preview_file(doc, opt, page, preview, device, opt->dpi_render, bbox, hires_bbox, calc_bbox); if (code == 0) { /* Load image */ img = bmpfile_to_image(preview); if (img == NULL) img = pnmfile_to_image(preview); } if (img && (opt->dpi_render != opt->dpi)) { /* downscale it */ newimg = (IMAGE *)malloc(sizeof(IMAGE)); if (newimg != NULL) { int ncomp; int width, height; float xoffset, yoffset; memset(newimg, 0, sizeof(newimg)); calc_device_size(opt->dpi, bbox, hires_bbox, &width, &height, &xoffset, &yoffset); newimg->width = width; newimg->height = height; newimg->format = img->format; if ((newimg->format & DISPLAY_COLORS_MASK) == DISPLAY_COLORS_CMYK) ncomp = 4; else if ((newimg->format & DISPLAY_COLORS_MASK) == DISPLAY_COLORS_RGB) ncomp = 3; else ncomp = 1; newimg->raster = newimg->width * ncomp; /* bytes per row */ newimg->image = malloc(newimg->raster * newimg->height); if (newimg->image == NULL) { free(newimg); newimg = NULL; } } if (newimg != NULL) { memset(newimg->image, 0, newimg->raster * newimg->height); if (image_down_scale(newimg, img) != 0) { bitmap_image_free(newimg); newimg = NULL; } } if (newimg != NULL) { bitmap_image_free(img); img = newimg; } } if (!(debug & DEBUG_GENERAL)) csunlink(preview); return img; } /****************************************************************/ int epstool_dcs2_composite(Doc *doc, OPT *opt, GFile *compfile) { CDSC *dsc = doc->dsc; IMAGE img; IMAGE *layer = NULL; int width, height; float xoffset, yoffset; float cyan, magenta, yellow, black; int code = 0; int i; CDSCBBOX bbox = {0, 0, 0, 0}; CDSCFBBOX hires_bbox = {0.0, 0.0, 0.0, 0.0}; int hires_bbox_valid = 0; /* Require original to be DCS 2.0 */ if (doc->dsc == NULL) return -1; if (doc->dsc->dcs2 == NULL) return -1; if (dsc->bbox) { bbox = *dsc->bbox; } else return -1; if (dsc->hires_bbox) { hires_bbox = *dsc->hires_bbox; hires_bbox_valid = 1; } /* Make a CMYK image for the composite */ code = calc_device_size(opt->dpi, &bbox, &hires_bbox, &width, &height, &xoffset, &yoffset); if (code) { app_csmsgf(doc->app, TEXT("BoundingBox is invalid\n")); return -1; } memset(&img, 0, sizeof(img)); img.width = width; img.height = height; img.raster = img.width * 4; img.format = DISPLAY_COLORS_CMYK | DISPLAY_ALPHA_NONE | DISPLAY_DEPTH_8 | DISPLAY_BIGENDIAN | DISPLAY_TOPFIRST; img.image = (unsigned char *)malloc(img.raster * img.height); if (img.image == NULL) return -1; memset(img.image, 0, img.raster * img.height); /* For each plate, make an image, then merge it into * the composite */ for (i=1; i<(int)dsc->page_count; i++) { /* find colour */ int found; CUSTOM_COLOUR *ccolour = NULL; const char *name = dsc->page[i].label; if (name == NULL) { app_msgf(doc->app, "Page %d doesn't have a label\n", i); code = -1; break; } found = colour_to_cmyk(dsc, name, &cyan, &magenta, &yellow, &black); if ((ccolour = custom_colours_find(opt, name)) != NULL) { /* Use local colour overrides from --custom-colours */ found = 0; if (ccolour->type == CUSTOM_RGB) { cyan = (float)(1.0 - ccolour->red); magenta = (float)(1.0 - ccolour->green); yellow = (float)(1.0 - ccolour->blue); black = min(cyan, min(magenta, yellow)); if (black > 0.0) { cyan -= black; magenta -= black; yellow -= black; } } else { cyan = ccolour->cyan; magenta = ccolour->magenta; yellow = ccolour->yellow; black = ccolour->black; } } if (found < 0) { app_msgf(doc->app, "Unrecognised colour (%s)\n", name); code = -1; break; } if ((cyan == 0.0) && (magenta == 0.0) && (yellow == 0.0) && (black == 0.0)) { if (!opt->quiet) app_msgf(doc->app, "Skipping blank separation %s\n", name); continue; } if (!opt->quiet) app_msgf(doc->app, "Creating image from separation %s\n", name); /* Now get the separation image */ layer = make_preview_image(doc, opt, i, GREY_DEVICE, &bbox, &hires_bbox, FALSE); if (layer == NULL) { app_msgf(doc->app, "Failed to make image for separation (%s)\n", name); code = -1; break; } else { if (!opt->quiet) app_msgf(doc->app, "Merging separation %g %g %g %g %s\n", cyan, magenta, yellow, black, name); code = image_merge_cmyk(&img, layer, cyan, magenta, yellow, black); bitmap_image_free(layer); if (code < 0) { app_msgf(doc->app, "Failed to merge separation (%s)\n", name); code = -1; break; } } } if (code == 0) { if (!opt->quiet) app_msgf(doc->app, "Writing composite as EPS\n"); code = image_to_eps(compfile, &img, bbox.llx, bbox.lly, bbox.urx, bbox.ury, hires_bbox.fllx, hires_bbox.flly, hires_bbox.furx, hires_bbox.fury, opt->image_encode, opt->image_compress); } free(img.image); return code; } /* Return 0 if CMYK set from the DSC comments, -1 if not set */ static int colour_to_cmyk(CDSC *dsc, const char *name, float *cyan, float *magenta, float *yellow, float *black) { int code = 0; CDSCCOLOUR *colour = dsc->colours; if (name == NULL) return -1; while (colour) { if (colour->name && (dsc_stricmp(colour->name, name)==0)) break; colour = colour->next; } if (colour && (colour->custom == CDSC_CUSTOM_COLOUR_CMYK)) { *cyan = colour->cyan; *magenta = colour->magenta; *yellow = colour->yellow; *black = colour->black; } else if (colour && (colour->custom == CDSC_CUSTOM_COLOUR_RGB)) { *cyan = (float)(1.0 - colour->red); *magenta = (float)(1.0 - colour->green); *yellow = (float)(1.0 - colour->blue); *black = min(*cyan, min(*magenta, *yellow)); if (*black > 0.0) { *cyan -= *black; *magenta -= *black; *yellow -= *black; } } else { if (dsc_stricmp(name, "Cyan") == 0) { *cyan = 1.0; *magenta = *yellow = *black = 0.0; } else if (dsc_stricmp(name, "Magenta") == 0) { *magenta = 1.0; *cyan = *yellow = *black = 0.0; } else if (dsc_stricmp(name, "Yellow") == 0) { *yellow = 1.0; *cyan = *magenta = *black = 0.0; } else if (dsc_stricmp(name, "Black") == 0) { *black = 1.0; *cyan = *yellow = *magenta = 0.0; } else { code = -1; } } return code; } const char *epswarn_prolog[] = { "%!\n", "% This code is wrapped around an EPS file to partly test if it complies\n", "% with the EPS specfication.\n", "\n", "/eps_warn_file (%stdout) (w) file def\n", "\n", "globaldict begin /eps_warn_ok true def end\n", "\n", "/eps_write_only { % name string -- name\n", " eps_warn_file exch writestring\n", " eps_warn_file ( /) writestring\n", " dup eps_warn_file exch 32 string cvs writestring\n", " eps_warn_file (\\n) writestring \n", " eps_warn_file flushfile\n", "} bind def\n", "\n", "/eps_write { % name string -- name\n", " eps_write_only\n", " //globaldict /eps_warn_ok false put\n", "} bind def\n", "\n", "/eps_warn { % name --\n", " (EPSWARN FAIL: EPS file must not use) \n", " eps_write\n", " //systemdict exch get exec\n", "} bind def\n", "\n", "% Prohibited operators in systemdict\n", "/banddevice {/banddevice eps_warn} def\n", "/clear {/clear eps_warn} def\n", "/cleardictstack {/cleardictstack eps_warn} def\n", "/copypage {/copypage eps_warn} def\n", "/erasepage {/erasepage eps_warn} def\n", "/exitserver {/exitserver eps_warn} def % this won't work - exitserver is in serverdict\n", "/serverdict {/serverdict eps_warn} def % so use this to provide warnings instead\n", "/statusdict {/statusdict eps_warn} def\n", "/framedevice {/framedevice eps_warn} def\n", "/grestoreall {/grestoreall eps_warn} def\n", "/initclip {/initclip eps_warn} def\n", "/initgraphics {/initgraphics eps_warn} def\n", "/initmatrix {/initmatrix eps_warn} def\n", "/renderbands {/renderbands eps_warn} def\n", "/setglobal {/setglobal eps_warn} def\n", "/setpagedevice {/setpagedevice eps_warn} def\n", "/setpageparams {/setpageparams eps_warn} def\n", "/setshared {/setshared eps_warn} def\n", "/startjob {/startjob eps_warn} def\n", "% If quit is executed, then epswarn_check will never be run.\n", "/quit {\n", " % systemdict /quit doesn't work when it has been redefined in userdict\n", " /quit (EPSWARN FAIL: EPS file must not use) eps_write\n", " //globaldict /eps_warn_ok false put\n", " //systemdict begin quit \n", "} def\n", "\n", "% These page sizes are defined in userdict, not systemdict\n", "/eps_pagesize_warn {\n", " (EPSWARN FAIL: EPS file must not set page size:)\n", " eps_write pop\n", "} def\n", "/11x17 {/11x17 eps_pagesize_warn} def\n", "/a3 {/a3 eps_pagesize_warn} def\n", "/a4 {/a4 eps_pagesize_warn} def\n", "/a4small {/a4small eps_pagesize_warn} def\n", "/a5 {/a5 eps_pagesize_warn} def\n", "/ledger {/ledger eps_pagesize_warn} def\n", "/legal {/legal eps_pagesize_warn} def\n", "/letter {/letter eps_pagesize_warn} def\n", "/lettersmall {/lettersmall eps_pagesize_warn} def\n", "/note {/note eps_pagesize_warn} def\n", "\n", "% These operators can only be used if the parameter\n", "% is saved and restored afterwards, or if setting\n", "% them takes into account their previous value.\n", "% For example 'matrix setmatrix' is not permitted,\n", "% but 'matrix current matrix setmatrix' is allowed.\n", "/eps_warntwo {\n", " (EPSWARN WARNING: EPS file should be careful using) \n", " eps_write_only\n", " //systemdict exch get exec\n", "} def\n", "/nulldevice {/nulldevice eps_warntwo} def % can't test this\n", "/setgstate {/setgstate eps_warntwo} def % can't test this\n", "/sethalftone {/sethalftone eps_warntwo} def\n", "/setmatrix {/setmatrix eps_warntwo} def\n", "/setscreen {/setscreen eps_warntwo} def\n", "/settransfer {/settransfer eps_warntwo} def\n", "/setcolortransfer {/setcolortransfer eps_warntwo} def\n", "\n", "% Take snapshot of some items\n", "count /eps_count exch def\n", "countdictstack /eps_countdictstack exch def\n", "currentpagedevice /PageCount get /eps_pagecount exch def\n", "/eps_showpage_count 0 def\n", "\n", "\n", "/epswarn_check_write { % string --\n", " eps_warn_file exch writestring\n", " eps_warn_file flushfile\n", " //globaldict /eps_warn_ok false put\n", "} def\n", "\n", "/epswarn_check {\n", " % count\n", " count eps_count ne {\n", " (EPSWARN FAIL: EPS file altered operand stack count\\n) epswarn_check_write \n", " } if\n", " //systemdict /clear get exec\n", " % countdictstack\n", " countdictstack eps_countdictstack ne {\n", " (EPSWARN FAIL: EPS file altered dictionary stack count\\n) \n", " epswarn_check_write\n", " } if\n", " countdictstack eps_countdictstack sub {end} repeat\n", " % real page count\n", " currentpagedevice /PageCount get eps_pagecount ne {\n", " (EPSWARN FAIL: EPS file forcibly output a page\\n) epswarn_check_write\n", " } if\n", " % showpage count\n", " eps_showpage_count 1 gt {\n", " (EPSWARN FAIL: EPS file used showpage more than once\\n) epswarn_check_write\n", " } if\n", "} def\n", "\n", "% EPS files are normally encapsulated inside a save/restore\n", "save /epswarn_save exch def\n", "\n", "% redefine showpage, and count how many times it is called\n", "/showpage { userdict dup /eps_showpage_count get 1 add \n", " /eps_showpage_count exch put \n", "} def\n", "\n", "% Now for something to test this\n", "\n", NULL}; const char epswarn_epilog[] = "\ %!\n\ % Check that all is well\n\ epswarn_check\n\ %epswarn_save restore\n\ //globaldict /eps_warn_ok get not \n\ {eps_warn_file (\nEPSWARN FAIL\\n) writestring} \n\ {eps_warn_file (\nEPSWARN PASS\\n) writestring} \n\ ifelse\n\ systemdict begin % so quit works...\n\ "; /* Test if an EPS file really is EPS compliant */ static int epstool_test(Doc *doc, OPT *opt) { GFile *f; int code = 0; TCHAR tpsname[MAXSTR]; TCHAR command[MAXSTR*8]; unsigned int len; FILE *testfile = NULL; TCHAR testname[MAXSTR]; CDSCBBOX bbox; CDSCFBBOX hires_bbox; BOOL found_error = FALSE; BOOL found_warning = FALSE; BOOL found_pass = FALSE; BOOL bbox_valid = FALSE; char line[256]; int i; BOOL dsc_error = FALSE; BOOL dsc_warning = FALSE; if (doc->dsc) { dsc_error = (doc->dsc->worst_error == CDSC_ERROR_ERROR); dsc_warning = (doc->dsc->worst_error == CDSC_ERROR_WARN); } /* Copy prolog, page and epilog to a temporary file */ if ((f = app_temp_gfile(doc->app, tpsname, sizeof(tpsname)/sizeof(TCHAR))) == (GFile *)NULL) { app_csmsgf(doc->app, TEXT("Can't create temporary ps file \042%s\042\n"), tpsname); return -1; } for (i=0; epswarn_prolog[i]; i++) { len = (int)strlen(epswarn_prolog[i]); if (!code && (len != gfile_write(f, epswarn_prolog[i], len))) code = -1; } code = copy_page_nosave(doc, f, 0); len = (int)strlen(epswarn_epilog); if (len != gfile_write(f, epswarn_epilog, len)) code = -1; gfile_close(f); if (code != 0) { if (!(debug & DEBUG_GENERAL)) csunlink(tpsname); return -1; } if ((testfile = app_temp_file(doc->app, testname, sizeof(testname)/sizeof(TCHAR))) == (FILE *)NULL) { app_csmsgf(doc->app, TEXT("Can't create temporary file \042%s\042\n"), testname); if (!(debug & DEBUG_GENERAL)) csunlink(tpsname); return -1; } fclose(testfile); testfile = NULL; /* Interpret the file to test it */ csnprintf(command, sizeof(command)/sizeof(TCHAR), TEXT("\042%s\042 %s -dNOEPS -dNOPAUSE -dBATCH -dNODISPLAY %s \042%s\042"), opt->gs, opt->quiet ? TEXT("-dQUIET") : TEXT(""), opt->gsargs, tpsname); if (!opt->quiet) app_csmsgf(doc->app, TEXT("%s\n"), command); code = exec_program(command, -1, -1 , fileno(stderr), NULL, testname, NULL); if (code != 0) app_csmsgf(doc->app, TEXT("Ghostscript failed to interpret file\n")); /* delete temporary ps file */ if (!(debug & DEBUG_GENERAL)) csunlink(tpsname); /* Now check testfile for reports of problems */ if (code == 0) { if ((testfile = csfopen(testname, TEXT("rb"))) == (FILE *)NULL) { app_csmsgf(doc->app, TEXT("Can't open temporary file \042%s\042\n"), testname); code = -1; } } if (code == 0) { while (fgets(line, sizeof(line), testfile) != NULL) { if (!opt->quiet) app_msgf(doc->app, "%s", line); if (strncmp(line, "EPSWARN FAIL: ", 14) == 0) found_error = TRUE; else if (strncmp(line, "EPSWARN WARNING: ", 17) == 0) found_warning = TRUE; else if (strncmp(line, "EPSWARN PASS", 12) == 0) found_pass = TRUE; } } if (testfile) fclose(testfile); if (!(debug & DEBUG_GENERAL)) csunlink(testname); if (!opt->quiet) app_csmsg(doc->app, TEXT("\n")); if ((code == 0) && (doc->dsc) && (doc->dsc->bbox)) { /* Copy page to temporary file */ if ((f = app_temp_gfile(doc->app, tpsname, sizeof(tpsname)/sizeof(TCHAR))) == (GFile *)NULL) { app_csmsgf(doc->app, TEXT("Can't create temporary ps file \042%s\042\n"), tpsname); return -1; } code = copy_page_temp(doc, f, 0); gfile_close(f); if (code != 0) { if (!(debug & DEBUG_GENERAL)) csunlink(tpsname); return -1; } code = calculate_bbox(doc, opt, tpsname, &bbox, &hires_bbox); if (!opt->quiet) app_csmsg(doc->app, TEXT("\n")); if (code == 0) { if ( (bbox.llx >= doc->dsc->bbox->llx-1) && (bbox.lly >= doc->dsc->bbox->lly-1) && (bbox.urx <= doc->dsc->bbox->urx+1) && (bbox.ury <= doc->dsc->bbox->ury+1)) { bbox_valid = TRUE; } if (!opt->quiet) { app_csmsgf(doc->app, TEXT("File has %%%%BoundingBox: %d %d %d %d\n"), doc->dsc->bbox->llx, doc->dsc->bbox->lly, doc->dsc->bbox->urx, doc->dsc->bbox->ury); app_csmsgf(doc->app, TEXT("Correct is %%%%BoundingBox: %d %d %d %d\n"), bbox.llx, bbox.lly, bbox.urx, bbox.ury); if (!bbox_valid) app_csmsgf(doc->app, TEXT("File bounding box needs to be larger\n")); } } else { if (!opt->quiet) app_csmsgf(doc->app, TEXT("Failed to calculate bounding box\n")); } /* delete temporary ps file */ if (!(debug & DEBUG_GENERAL)) csunlink(tpsname); } else { if (!opt->quiet) app_csmsgf(doc->app, TEXT("Missing %%%%BoundingBox\n")); } if (found_error || !found_pass || !bbox_valid || dsc_error || dsc_warning || !doc->dsc || !doc->dsc->epsf) code = -1; if (!opt->quiet) { if (found_warning) app_csmsgf(doc->app, TEXT("File used operators that sometimes cause problems in an EPS file.\n")); if (found_error) app_csmsgf(doc->app, TEXT("File used PostScript operators that are prohibited in an EPS file.\n")); if (found_pass) app_csmsgf(doc->app, TEXT("PostScript appears well behaved.\n")); if (doc->dsc && doc->dsc->epsf) app_csmsgf(doc->app, TEXT("File claims to be EPS.\n")); else app_csmsgf(doc->app, TEXT("File is not EPS.\n")); } if (code != 0) fprintf(MSGOUT, "FAIL: File does not comply with EPS specification.\n"); else fprintf(MSGOUT, "PASS: File appears to be well behaved EPS.\n"); return code; } static void epstool_dump_fn(void *caller_data, const char *str) { fputs(str, stdout); } /****************************************************************/ /* Functions from GSview app that we need. */ /* Some of these should be moved from capp.c to a separate file. */ #ifdef _MSC_VER # pragma warning(disable:4100) /* ignore "Unreferenced formal parameter" */ #endif int app_platform_init(GSview *a) { return 0; } int app_platform_finish(GSview *a) { return 0; } int app_lock(GSview *a) { return 0; } int app_unlock(GSview *a) { return 0; } void app_log(const char *str, int len) { fwrite(str, 1, len, MSGOUT); } int cs_to_narrow(char *nstr, int nlen, LPCTSTR wstr, int wlen) { #ifdef UNICODE return WideCharToMultiByte(CP_ACP, 0, wstr, wlen, nstr, nlen, NULL, NULL); #else return char_to_narrow(nstr, nlen, wstr, wlen); #endif } int narrow_to_cs(TCHAR *wstr, int wlen, const char *nstr, int nlen) { #ifdef UNICODE return MultiByteToWideChar(CP_ACP, 0, nstr, nlen, wstr, wlen); #else return narrow_to_char(wstr, wlen, nstr, nlen); #endif } int get_dsc_response(GSview *app, LPCTSTR str) { app_csmsgf(app, TEXT("\n%s\n"), str); return CDSC_RESPONSE_OK; } int load_string(GSview *a, int id, TCHAR *buf, int len) { char msg[MAXSTR]; const char *s = NULL; int reslen; int dscmsg = (id - CDSC_RESOURCE_BASE) / 2; if (buf && len) buf[0] = '\0'; /* CDSC_MESSAGE_INCORRECT_USAGE should be dsc->max_error */ if (a /* ignore unused parameter GSview *a */ && (dscmsg >= 0) && (dscmsg <= CDSC_MESSAGE_INCORRECT_USAGE)) { if (((id - CDSC_RESOURCE_BASE) & 1) == 0) s = dsc_message[dscmsg]; else s = ""; } else switch (id) { case IDS_DSC_LINEFMT: s = "%sAt line %d:"; break; case IDS_DSC_INFO: s = "DSC Information\n"; break; case IDS_DSC_WARN: s = "DSC Warning\n"; break; case IDS_DSC_ERROR: s = "DSC Error\n"; break; } if (s == NULL) { snprintf(msg, sizeof(msg), "String %d\n", id); s = msg; } reslen = narrow_to_cs(NULL, 0, s, (int)strlen(s)+1); if (reslen > len) return reslen; return narrow_to_cs(buf, len, s, (int)strlen(s)+1); } int app_msg_box(GSview *a, LPCTSTR str, int icon) { app_csmsgf(a, TEXT("%s\n"), str); return 0; } int gssrv_request(GSSRV *s, GSREQ *reqnew) { return -1; } int pagecache_unref_all(GSview *a) { return 0; } void doc_savestat(Doc *doc) { } int image_platform_init(IMAGE *img) { return 0; } unsigned int image_platform_format(unsigned int format) { return format; } #ifdef _MSC_VER # pragma warning(default:4100) #endif /****************************************************************/ /* platform specific code for running another program */ /* * If hstdin not -1, duplicate handle and give to program, * else if stdin_name not NULL, open filename and give to program. * Same for hstdout/stdout_name and hstderr/stderr_name. */ #ifdef __WIN32__ int exec_program(LPTSTR command, int hstdin, int hstdout, int hstderr, LPCTSTR stdin_name, LPCTSTR stdout_name, LPCTSTR stderr_name) { int code = 0; HANDLE hChildStdinRd = INVALID_HANDLE_VALUE; HANDLE hChildStdoutWr = INVALID_HANDLE_VALUE; HANDLE hChildStderrWr = INVALID_HANDLE_VALUE; HANDLE hStdin = INVALID_HANDLE_VALUE; HANDLE hStderr = INVALID_HANDLE_VALUE; HANDLE hStdout = INVALID_HANDLE_VALUE; SECURITY_ATTRIBUTES saAttr; STARTUPINFO siStartInfo; PROCESS_INFORMATION piProcInfo; DWORD exitcode = (DWORD)-1; /* Set the bInheritHandle flag so pipe handles are inherited. */ saAttr.nLength = sizeof(SECURITY_ATTRIBUTES); saAttr.bInheritHandle = TRUE; saAttr.lpSecurityDescriptor = NULL; /* if handles are provided, use them */ if ((hstdin != -1)) { INTPTR handle; handle = _get_osfhandle(hstdin); if (handle == -1) code = -1; if (code == 0) { hStdin = (HANDLE)handle; if (!DuplicateHandle(GetCurrentProcess(), hStdin, GetCurrentProcess(), &hChildStdinRd, 0, TRUE, /* inherited */ DUPLICATE_SAME_ACCESS)) code = -1; } } if ((code==0) && (hstdout != -1)) { INTPTR handle; handle = _get_osfhandle(hstdout); if (handle == -1) code = -1; if (code == 0) { hStdout = (HANDLE)handle; if (!DuplicateHandle(GetCurrentProcess(), hStdout, GetCurrentProcess(), &hChildStdoutWr, 0, TRUE, /* inherited */ DUPLICATE_SAME_ACCESS)) code = -1; } } if ((code==0) && (hstderr != -1)) { INTPTR handle; handle = _get_osfhandle(hstderr); if (handle == -1) code = -1; if (code == 0) { hStderr = (HANDLE)handle; if (!DuplicateHandle(GetCurrentProcess(), hStderr, GetCurrentProcess(), &hChildStderrWr, 0, TRUE, /* inherited */ DUPLICATE_SAME_ACCESS)) code = -1; } } /* If files are requested, create them */ if ((code==0) && stdin_name && (hChildStdinRd == INVALID_HANDLE_VALUE)) { hChildStdinRd = CreateFile(stdin_name, GENERIC_READ, 0 /* no file sharing */, &saAttr /* allow handle to be inherited */, OPEN_EXISTING, 0, NULL); if (hChildStdinRd == INVALID_HANDLE_VALUE) code = -1; } if ((code==0) && stdout_name && (hChildStdoutWr == INVALID_HANDLE_VALUE)) { hChildStdoutWr = CreateFile(stdout_name, GENERIC_WRITE, 0 /* no file sharing */, &saAttr /* allow handle to be inherited */, OPEN_ALWAYS, 0, NULL); if (hChildStdoutWr == INVALID_HANDLE_VALUE) code = -1; } if ((code==0) && stderr_name && (hChildStderrWr == INVALID_HANDLE_VALUE)) { hChildStderrWr = CreateFile(stderr_name, GENERIC_WRITE, 0 /* no file sharing */, &saAttr /* allow handle to be inherited */, OPEN_ALWAYS, 0, NULL); if (hChildStderrWr == INVALID_HANDLE_VALUE) code = -1; } /* Set up members of STARTUPINFO structure. */ siStartInfo.cb = sizeof(STARTUPINFO); siStartInfo.lpReserved = NULL; siStartInfo.lpDesktop = NULL; siStartInfo.lpTitle = NULL; /* use executable name as title */ /* next two lines ignored */ siStartInfo.dwX = siStartInfo.dwY = (DWORD)CW_USEDEFAULT; siStartInfo.dwXSize = siStartInfo.dwYSize = (DWORD)CW_USEDEFAULT; siStartInfo.dwXCountChars = 80; siStartInfo.dwYCountChars = 25; siStartInfo.dwFillAttribute = 0; /* ignored */ siStartInfo.dwFlags = STARTF_USESTDHANDLES; siStartInfo.wShowWindow = SW_SHOWNORMAL; /* ignored */ siStartInfo.cbReserved2 = 0; siStartInfo.lpReserved2 = NULL; siStartInfo.hStdInput = hChildStdinRd; siStartInfo.hStdOutput = hChildStdoutWr; siStartInfo.hStdError = hChildStderrWr; memset(&piProcInfo, 0, sizeof(piProcInfo)); if ((code == 0) && !CreateProcess(NULL, command, NULL, /* process security attributes */ NULL, /* primary thread security attributes */ TRUE, /* handles are inherited */ 0, /* creation flags */ NULL, /* environment */ NULL, /* use parent's current directory */ &siStartInfo, /* STARTUPINFO pointer */ &piProcInfo)) { /* receives PROCESS_INFORMATION */ code = -1; } /* close our copy of the handles */ if (hChildStdinRd != INVALID_HANDLE_VALUE) CloseHandle(hChildStdinRd); if (hChildStdoutWr != INVALID_HANDLE_VALUE) CloseHandle(hChildStdoutWr); if (hChildStderrWr != INVALID_HANDLE_VALUE) CloseHandle(hChildStderrWr); if (code == 0) { /* wait for process to finish */ WaitForSingleObject(piProcInfo.hProcess, 300000); GetExitCodeProcess(piProcInfo.hProcess, &exitcode); CloseHandle(piProcInfo.hProcess); CloseHandle(piProcInfo.hThread); } if (code) return code; return (int)exitcode; } #endif #if defined(UNIX) int exec_program(LPTSTR command, int hstdin, int hstdout, int hstderr, LPCTSTR stdin_name, LPCTSTR stdout_name, LPCTSTR stderr_name) { int code = 0; int hChildStdinRd = -1; int hChildStdoutWr = -1; int hChildStderrWr = -1; int handle; pid_t pid; int exitcode; #define MAXARG 64 char *argv[MAXARG+1]; int argc = 0; char *args, *d, *e, *p; /* Parse command line handling quotes. */ memset(argv, 0, sizeof(argv)); argc = 0; args = (char *)malloc(strlen(command)+1); if (args == (char *)NULL) return -1; p = command; d = args; while (*p) { /* for each argument */ if (argc >= MAXARG - 1) { fprintf(stderr, "Too many arguments\n"); free(args); return -1; } e = d; while ((*p) && (*p != ' ')) { if (*p == '\042') { /* Remove quotes, skipping over embedded spaces. */ /* Doesn't handle embedded quotes. */ p++; while ((*p) && (*p != '\042')) *d++ =*p++; } else *d++ = *p; if (*p) p++; } *d++ = '\0'; argv[argc++] = e; while ((*p) && (*p == ' ')) p++; /* Skip over trailing spaces */ } argv[argc] = NULL; pid = fork(); if (pid == (pid_t)-1) { /* fork failed */ fprintf(stderr, "Failed to fork, error=%d\n", errno); return -1; } else if (pid == 0) { /* child */ /* if handles are provided, use them */ if ((code == 0) && (hstdin != -1)) { hChildStdinRd = dup2(hstdin, 0); if (hChildStdinRd == -1) code = -1; } if ((code==0) && (hstdout != -1)) { hChildStdoutWr = dup2(hstdout, 1); if (hChildStdoutWr == -1) code = -1; } if ((code==0) && (hstderr != -1)) { hChildStderrWr = dup2(hstderr, 2); if (hChildStderrWr == -1) code = -1; } if ((code==0) && stdin_name && (hChildStdinRd == -1)) { handle = open(stdin_name, O_RDONLY); hChildStdinRd = dup2(handle, 0); if (handle != -1) close(handle); if (hChildStdinRd == -1) code = -1; } if ((code==0) && stdout_name && (hChildStdoutWr == -1)) { handle = open(stdout_name, O_WRONLY | O_CREAT); hChildStdoutWr = dup2(handle, 1); if (handle != -1) close(handle); if (hChildStdoutWr == -1) code = -1; } if ((code==0) && stderr_name && (hChildStderrWr == -1)) { handle = open(stderr_name, O_WRONLY | O_CREAT); hChildStderrWr = dup2(handle, 2); if (handle != -1) close(handle); if (hChildStderrWr == -1) code = -1; } if (code) { fprintf(stderr, "Failed to open stdin/out/err, error=%d\n", errno); if (hChildStdinRd) close(hChildStdinRd); if (hChildStdoutWr) close(hChildStdoutWr); if (hChildStderrWr) close(hChildStderrWr); exit(1); } /* Now execute it */ if (execvp(argv[0], argv) == -1) { fprintf(stderr, "Failed to execute ghostscript, error=%d\n", errno); exit(1); } } /* parent - wait for child to finish */ free(args); wait(&exitcode); return exitcode; } #endif /* * If hstdin not -1, duplicate handle and give to program, * else if stdin_name not NULL, open filename and give to program. * Same for hstdout/stdout_name and hstderr/stderr_name. */ #ifdef OS2 int exec_program(LPTSTR command, int hstdin, int hstdout, int hstderr, LPCTSTR stdin_name, LPCTSTR stdout_name, LPCTSTR stderr_name) { HFILE hStdin = 0; HFILE hStdout = 1; HFILE hStderr = 2; HFILE hOldStdin; HFILE hOldStdout; HFILE hOldStderr; HFILE hNewStdin = -1; HFILE hNewStdout = -1; HFILE hNewStderr = -1; APIRET rc = 0; ULONG action; CHAR szFailName[CCHMAXPATH]; RESULTCODES resc; PSZ cmd; PSZ args; int cmdlen; /* Copy command into format needed by DosExecPgm */ cmdlen = strlen(command)+1; cmd = (char *)malloc(cmdlen+1); if (cmd) { char *p; memset(cmd, 0, cmdlen+1); strncpy(cmd, command, cmdlen); p = args = cmd; if (*p == '"') { p++; args = p; while (*p && (*p != '"')) p++; } else { while (*p && (*p != 0)) p++; } *p = '\0'; } else return -1; /* save existing stdio handles */ hOldStdin = 0xffffffff; /* allocate new handle */ if (rc == 0) rc = DosDupHandle(hStdin, &hOldStdin); hOldStdout = 0xffffffff; /* allocate new handle */ if (rc == 0) rc = DosDupHandle(hStdout, &hOldStdout); hOldStderr = 0xffffffff; /* allocate new handle */ if (rc == 0) rc = DosDupHandle(hStderr, &hOldStderr); if (rc != 0) { free(cmd); return -1; } /* if handles or files are provided, use them */ if ((hstdin != -1)) { if (rc == 0) DosDupHandle((HFILE)hstdin, &hStdin); } else if ((rc == 0) && stdin_name) { rc = DosOpen((PCSZ)stdin_name, /* filename */ &hNewStdin, /* pointer to handle */ &action, /* pointer to result */ 0, /* initial length */ FILE_NORMAL, /* normal file */ OPEN_ACTION_FAIL_IF_NEW | OPEN_ACTION_OPEN_IF_EXISTS, OPEN_ACCESS_READONLY | OPEN_SHARE_DENYNONE, 0); if (rc == 0) rc= DosDupHandle(hNewStdin, &hStdin); } if ((hstdout != -1)) { if (rc == 0) DosDupHandle((HFILE)hstdout, &hStdout); } else if ((rc == 0) && stdout_name) { rc = DosOpen((PCSZ)stdout_name, /* filename */ &hNewStdout, /* pointer to handle */ &action, /* pointer to result */ 0, /* initial length */ FILE_NORMAL, /* normal file */ OPEN_ACTION_CREATE_IF_NEW | OPEN_ACTION_REPLACE_IF_EXISTS, OPEN_ACCESS_WRITEONLY | OPEN_SHARE_DENYREADWRITE, 0); if (rc == 0) rc= DosDupHandle(hNewStdout, &hStdout); } if ((hstderr != -1)) { if (rc == 0) DosDupHandle((HFILE)hstderr, &hStderr); } else if ((rc == 0) && stderr_name) { rc = DosOpen((PCSZ)stderr_name, /* filename */ &hNewStderr, /* pointer to handle */ &action, /* pointer to result */ 0, /* initial length */ FILE_NORMAL, /* normal file */ OPEN_ACTION_CREATE_IF_NEW | OPEN_ACTION_REPLACE_IF_EXISTS, OPEN_ACCESS_WRITEONLY | OPEN_SHARE_DENYWRITE, 0); if (rc == 0) rc= DosDupHandle(hNewStderr, &hStderr); } if (rc != 0) { free(cmd); return -1; } rc = DosExecPgm(szFailName, sizeof(szFailName), EXEC_SYNC, args, (PSZ)NULL, &resc, args); /* Put stdio back to original handles */ DosDupHandle(hOldStdin, &hStdin); DosDupHandle(hOldStdout, &hStdout); DosDupHandle(hOldStderr, &hStderr); DosClose(hOldStdin); DosClose(hOldStdout); DosClose(hOldStderr); if (hNewStdin != -1) DosClose(hNewStdin); if (hNewStdout != -1) DosClose(hNewStdout); if (hNewStderr != -1) DosClose(hNewStderr); if (rc) return -1; return (int)resc.codeResult; } #endif epstool-3.08/src/calloc.c0000644000076400007640000001123710252260053014730 0ustar rjlrjl00000000000000/* Copyright (C) 2001-2005 Ghostgum Software Pty Ltd. All rights reserved. This software is provided AS-IS with no warranty, either express or implied. This software is distributed under licence and may not be copied, modified or distributed except as expressly authorised under the terms of the licence contained in the file LICENCE in this distribution. For more information about licensing, please refer to http://www.ghostgum.com.au/ or contact Ghostsgum Software Pty Ltd, 218 Gallaghers Rd, Glen Waverley VIC 3150, AUSTRALIA, Fax +61 3 9886 6616. */ /* $Id: calloc.c,v 1.10 2005/06/10 09:39:24 ghostgum Exp $ */ /* A debugging malloc */ /* This is prettly clunky, but it allows us to check if there * are any memory leaks and to check for double free. * If you enable (debug & DEBUG_MALLOC), then you must do * so before any memory is allocated, otherwise it will * crash when it frees memory on exit. */ #include "common.h" #ifdef DEBUG_MALLOC FILE *malloc_file; #ifdef UNIX #define MALLOC_FILE "gsview.txt" #else #define MALLOC_FILE "c:\\gsview.txt" #endif /* #define DEBUG_PRINT */ #undef malloc #undef calloc #undef realloc #undef free size_t allocated_memory = 0; #define SIGNATURE 0xa55a typedef struct DMEM_s { size_t size; /* size of this chunk */ int signature; /* to make sure we aren't looking at garbage */ char notes[120]; /* description of block */ } DMEM; void * debug_malloc(size_t size, const char *file, int line) { if (debug & DEBUG_MEM) { char buf[MAXSTR]; DMEM *mem = (DMEM *)malloc(size+sizeof(DMEM)); void *p = NULL; if (mem) { memset(mem, 0, size+sizeof(DMEM)); mem->size = size; mem->signature = SIGNATURE; allocated_memory += size; snprintf(mem->notes, sizeof(mem->notes), "%s:%d %ld", file, line, (long)size); p = ((char *)mem) + sizeof(DMEM); } snprintf(buf, sizeof(buf), "%s, 0x%08lx, malloc(%ld), allocated = %ld\n", mem->notes, (long)p, (long)size, (long)allocated_memory); buf[sizeof(buf)-1]='\0'; #ifdef DEBUG_PRINT fputs(buf, stderr); #endif #ifdef DEBUG_MALLOC if (malloc_file == (FILE *)NULL) malloc_file = fopen(MALLOC_FILE, "w"); if (malloc_file != (FILE *)NULL) { fputs(buf, malloc_file); fflush(malloc_file); } #endif return p; } return malloc(size); } void * debug_realloc(void *block, size_t size) { if (debug & DEBUG_MEM) { char buf[MAXSTR]; char *p = NULL; size_t oldsize = 0; if (block == NULL) { strncpy(buf, "debug_realloc: null pointer\n", sizeof(buf)); } else { DMEM *old = (DMEM *)(((char *)block)-sizeof(DMEM)); DMEM *mem; char *p; oldsize = old->size; allocated_memory -= oldsize; mem = realloc(old, size + sizeof(DMEM)); if (mem) { memset(mem, 0, size+sizeof(DMEM)); mem->size = size; mem->signature = SIGNATURE; allocated_memory += size; p = ((char *)mem) + sizeof(DMEM); } snprintf(buf, sizeof(buf), "realloc old %ld, new %ld, allocated = %ld\n", (long)oldsize, (long)size, (long)allocated_memory); buf[sizeof(buf)-1]='\0'; } #ifdef DEBUG_PRINT fputs(buf, stderr); #endif #ifdef DEBUG_MALLOC if (malloc_file == (FILE *)NULL) malloc_file = fopen(MALLOC_FILE, "w"); if (malloc_file != (FILE *)NULL) { fputs(buf, malloc_file); fflush(malloc_file); } #endif return p; } return realloc(block, size); } void debug_free(void *block) { if (debug & DEBUG_MEM) { char buf[MAXSTR]; DMEM *mem = (DMEM *)(((char *)block)-sizeof(DMEM)); if (block == NULL) { strncpy(buf, "debug_free: null pointer\n", sizeof(buf)); } else { size_t oldsize = mem->size; allocated_memory -= oldsize; if (mem->signature != SIGNATURE) snprintf(buf, sizeof(buf), "free 0x%08lx NOT VALID\n", (long)block); else snprintf(buf, sizeof(buf), "%s, 0x%08lx, free %ld, allocated = %ld\n", mem->notes, (long)block, (long)oldsize, (long)allocated_memory); buf[sizeof(buf)-1]='\0'; memset(mem, 0, oldsize + sizeof(DMEM)); } #ifdef DEBUG_PRINT fputs(buf, stderr); #endif #ifdef DEBUG_MALLOC if (malloc_file == (FILE *)NULL) malloc_file = fopen(MALLOC_FILE, "w"); if (malloc_file != (FILE *)NULL) { fputs(buf, malloc_file); fflush(malloc_file); } #endif if (block != NULL) free((void *)mem); return; } free(block); return; } void debug_memory_report(void) { if (debug & DEBUG_MEM) { char buf[256]; snprintf(buf, sizeof(buf), "Allocated memory = %ld bytes\n", (long)allocated_memory); buf[sizeof(buf)-1]='\0'; #ifdef DEBUG_PRINT fputs(buf, stderr); #endif #ifdef DEBUG_MALLOC fputs(buf, malloc_file); fclose(malloc_file); #endif } } #endif /* DEBUG_MALLOC */ epstool-3.08/src/dscutil.c0000644000076400007640000005505710252260054015153 0ustar rjlrjl00000000000000/* Copyright (C) 2000-2002, Ghostgum Software Pty Ltd. All rights reserved. This file is part of GSview. This program is distributed with NO WARRANTY OF ANY KIND. No author or distributor accepts any responsibility for the consequences of using it, or for whether it serves any particular purpose or works at all, unless he or she says so in writing. Refer to the GSview Licence (the "Licence") for full details. Every copy of GSview must include a copy of the Licence, normally in a plain ASCII text file named LICENCE. The Licence grants you the right to copy, modify and redistribute GSview, but only under certain conditions described in the Licence. Among other things, the Licence requires that the copyright notice and this notice be preserved on all copies. */ /* dscutil.c - text messages for DSC parser and standalone test code */ #include #include #include #if defined(STANDALONE) && !defined(UNIX) #include #endif #include "dscparse.h" #define MAXSTR 256 int dsc_error_fn(void *caller_data, CDSC *dsc, unsigned int explanation, const char *line, unsigned int line_len); void dsc_display(CDSC *dsc, void (*dfn)(void *ptr, const char *str)); /* We always include the English version of this text in * an array for debug reporting. Language specific versions * are stored in resources. */ const char * const dsc_message[] = { /* CDSC_MESSAGE_BBOX */ "This line is incorrect.\n\ The bounding box must be in integer coordinates,\n\ not floating point. A floating point bounding box should\n\ be specified using %%HiResBoundingBox:\n\ A %%BoundingBox: should still be provided with integer values.\n\ \n\ 'OK' will convert the coordinates to integers,\n\ rounding them outwards.\n\ 'Cancel' will ignore this line\n", /* CDSC_MESSAGE_EARLY_TRAILER */ "The trailer is normally at the end of a document.\n\ This line was found more than 32k bytes from the end\n\ of the file. Trailers are not usually this long.\n\ It is more likely that another PostScript file has been included,\n\ without enclosing it in %%BeginDocument / %%EndDocument.\n\ \n\ 'OK' will assume this is part of an included file.\n\ 'Cancel' will assume this is the trailer\n", /* CDSC_MESSAGE_EARLY_EOF */ "This line normally occurs at the end of a document.\n\ This line was found more than 100 bytes from the end\n\ of the file.\n\ It is more likely that another PostScript file has been included,\n\ without enclosing it in %%BeginDocument / %%EndDocument.\n\ \n\ 'OK' will assume this is part of an included file.\n\ 'Cancel' will assume this is part of the trailer\n", /* CDSC_MESSAGE_PAGE_IN_TRAILER */ "This %%Page: line occurred in the trailer, which is not legal.\n\ EPS files should be encapsulated in %%BeginDocument / %%EndDocument.\n\ If is possible that an EPS file was incorrectly encapsulated,\n\ and that we have been confused by the %%Trailer in an EPS file.\n\ \n\ 'OK' will process more pages.\n\ 'Cancel' will ignore this page comment\n", /* CDSC_MESSAGE_PAGE_ORDINAL */ "This line is incorrect.\n\ The two arguments should be a label and an ordinal.\n\ The ordinal should be 1 for the first page and should\n\ increase by 1 for each following page.\n\ The page ordinal is missing or is not in sequence.\n\ \n\ It is likely that this line is part of an included file that\n\ was not enclosed in %%BeginDocument / %%EndDocument.\n\ \n\ 'OK' will ignore this page, assuming it is part of an\n\ incorrectly encapsulated EPS file.\n\ 'Cancel' will treat this as a valid page\n", /* CDSC_MESSAGE_PAGES_WRONG */ "%%Pages: doesn't match number of %%Page:\n\ \n\ 'OK' will adjust the page count to match the number of %%Page:\n\ comments found\n\ 'Cancel' will set the page count from %%Pages:\n", /* CDSC_MESSAGE_EPS_NO_BBOX */ "This EPS file is missing the required %%BoundingBox:\n\ See the GSview help for details of how to add/adjust the\n\ bounding box.\n\ \n\ 'OK' will assume this as an EPS file\n\ 'Cancel' will assume this is NOT an EPS file.\n", /* CDSC_MESSAGE_EPS_PAGES */ "EPS files may have 0 or 1 pages. This 'EPS' file has\n\ more than this and so is not an EPS file.\n\ You cannot use `Print To` `Encapsulated PostScript File` for\n\ printing multipage files. The correct method is to connect\n\ the printer to FILE: or to select 'Print to File'.\n\ \n\ 'OK' will assume this as an EPS file\n\ 'Cancel' will assume this is NOT an EPS file.\n", /* CDSC_MESSAGE_NO_MEDIA */ "Media was specified with %%DocumentMedia:, but no default\n\ media was specified with %%PageMedia:.\n\ \n\ 'OK' will set the default media to the first listed media.\n\ 'Cancel' will not set a default media.\n", /* CDSC_MESSAGE_ATEND */ "This line is incorrect\n\ To defer a value, you must use '(atend)', not 'atend'\n\ \n\ 'OK' will assume that (atend) was meant.\n\ 'Cancel' will ignore this line.\n", /* CDSC_MESSAGE_DUP_COMMENT */ "This comment is duplicated in the header, which is unnecessary.\n\ The first occurence of a header line takes precedence.\n\ \n\ 'OK' or 'Cancel' will ignore the duplicate line.\n", /* CDSC_MESSAGE_DUP_TRAILER */ "This comment is duplicated in the trailer, which is unnecessary.\n\ The last occurence of a trailer line takes precedence.\n\ \n\ 'OK' or 'Cancel' will use the duplicate line.\n", /* CDSC_MESSAGE_BEGIN_END */ "The number of Begin and End comments do not match.\n\ \n\ 'OK' or 'Cancel' will ignore this mismatch.\n", /* CDSC_MESSAGE_BAD_SECTION */ "This line is incorrect because it should not occur\n\ within a page. This probably indicates that an EPS file\n\ was incorrectly encapsulated. The line will be ignored.\n\ \n\ 'OK' or 'Cancel' will ignore this line.\n", /* CDSC_MESSAGE_LONG_LINE */ "\n\nLines in DSC documents must be shorter than 255 characters.\n", /* CDSC_MESSAGE_INCORRECT_USAGE */ "This DSC comment line is incorrect.\n\ Please refer to the DSC specification.\n\ 'OK' or 'Cancel' will ignore this mismatch.\n", NULL }; int dsc_error_fn(void *caller_data, CDSC *dsc, unsigned int explanation, const char *line, unsigned int line_len) { int response; int severity; char buf[MAXSTR]; if (explanation > dsc->max_error) return CDSC_RESPONSE_OK; if (caller_data == NULL) /* ignore unused parameter */ dsc_debug_print(dsc, ""); /* do nothing */ severity = dsc->severity[explanation]; /* If debug function provided, copy messages there */ if (dsc->debug_print_fn) { switch (severity) { case CDSC_ERROR_INFORM: dsc_debug_print(dsc, "\nDSC Information"); break; case CDSC_ERROR_WARN: dsc_debug_print(dsc, "\nDSC Warning"); break; case CDSC_ERROR_ERROR: dsc_debug_print(dsc, "\nDSC Error"); } dsc_debug_print(dsc, "\n"); if (explanation <= dsc->max_error) { if (line && line_len) { int length = min(line_len, sizeof(buf)-1); sprintf(buf, "At line %d:\n", dsc->line_count); dsc_debug_print(dsc, buf); strncpy(buf, line, length); buf[length]='\0'; dsc_debug_print(dsc, " "); dsc_debug_print(dsc, buf); } dsc_debug_print(dsc, dsc_message[explanation]); } } /* Here you could prompt user for OK, Cancel, Ignore ALL DSC */ /* In this version, we treat DSC as being correct and return Cancel */ response = CDSC_RESPONSE_CANCEL; if (dsc->debug_print_fn) { switch (response) { case CDSC_RESPONSE_OK: dsc_debug_print(dsc, "Response = OK\n"); break; case CDSC_RESPONSE_CANCEL: dsc_debug_print(dsc, "Response = Cancel\n"); break; case CDSC_RESPONSE_IGNORE_ALL: dsc_debug_print(dsc, "Response = Ignore All DSC\n"); break; } } return response; } void dsc_display(CDSC *dsc, void (*dfn)(void *ptr, const char *str)) { unsigned int i; const char *p; char buf[MAXSTR]; void *ptr = dsc->caller_data; CDCS2 *pdcs = dsc->dcs2; CDSCCOLOUR *colour = dsc->colours; char fmtbuf[MAXSTR]; const char *offset_fmt = DSC_OFFSET_FORMAT; (*dfn)(ptr, "== DSC dump ==\n"); if (dsc->dsc) (*dfn)(ptr, "DSC "); if (dsc->epsf) (*dfn)(ptr, "EPSF "); if (dsc->doseps) (*dfn)(ptr, "DOSEPS "); if (dsc->macbin) (*dfn)(ptr, "MacBinary "); if (dsc->pdf) (*dfn)(ptr, "PDF "); if (dsc->pjl) (*dfn)(ptr, "PJL "); if (dsc->ctrld) (*dfn)(ptr, "CTRLD "); if (dsc->dcs2) (*dfn)(ptr, "DCS2.0 "); (*dfn)(ptr, "\n"); if (dsc->dsc_version) { (*dfn)(ptr, "version "); (*dfn)(ptr, dsc->dsc_version); (*dfn)(ptr, "\n"); } if (dsc->dsc_title) { (*dfn)(ptr, "title "); (*dfn)(ptr, dsc->dsc_title); (*dfn)(ptr, "\n"); } if (dsc->dsc_creator) { (*dfn)(ptr, "creator "); (*dfn)(ptr, dsc->dsc_creator); (*dfn)(ptr, "\n"); } if (dsc->dsc_date) { (*dfn)(ptr, "date "); (*dfn)(ptr, dsc->dsc_date); (*dfn)(ptr, "\n"); } if (dsc->dsc_for) { (*dfn)(ptr, "for "); (*dfn)(ptr, dsc->dsc_for); (*dfn)(ptr, "\n"); } if (dsc->doseps) { sprintf(buf, "doseps: ps=%ld %ld wmf=%ld %ld tiff=%ld %ld\n", dsc->doseps->ps_begin, dsc->doseps->ps_length, dsc->doseps->wmf_begin, dsc->doseps->wmf_length, dsc->doseps->tiff_begin, dsc->doseps->tiff_length); (*dfn)(ptr, buf); } if (dsc->macbin) { sprintf(buf, "macbin ps=%ld %ld resource=%ld %ld\n", dsc->macbin->data_begin, dsc->macbin->data_length, dsc->macbin->resource_begin, dsc->macbin->resource_length); (*dfn)(ptr, buf); } if (dsc->bbox) { sprintf(buf, "boundingbox %d %d %d %d\n", dsc->bbox->llx, dsc->bbox->lly, dsc->bbox->urx, dsc->bbox->ury); (*dfn)(ptr, buf); } if (dsc->hires_bbox) { sprintf(buf, "hiresboundingbox %f %f %f %f\n", dsc->hires_bbox->fllx, dsc->hires_bbox->flly, dsc->hires_bbox->furx, dsc->hires_bbox->fury); (*dfn)(ptr, buf); } if (dsc->crop_box) { sprintf(buf, "cropbox %f %f %f %f\n", dsc->crop_box->fllx, dsc->crop_box->flly, dsc->crop_box->furx, dsc->crop_box->fury); (*dfn)(ptr, buf); } if (dsc->language_level != 0) { sprintf(buf, "language level %d\n", dsc->language_level); (*dfn)(ptr, buf); } if (dsc->preview != CDSC_NOPREVIEW) { switch (dsc->preview) { case CDSC_NOPREVIEW: p = "None"; break; case CDSC_EPSI: p = "Interchange"; break; case CDSC_TIFF: p = "TIFF"; break; case CDSC_WMF: p = "Windows MetaFile"; break; case CDSC_PICT: p = "Mac PICT"; break; default: p = "Unknown"; } sprintf(buf, "preview type %s\n", p); (*dfn)(ptr, buf); } if (dsc->document_data != CDSC_DATA_UNKNOWN) { switch (dsc->document_data) { case CDSC_CLEAN7BIT: p = "Clean7Bit"; break; case CDSC_CLEAN8BIT: p = "Clean8Bit"; break; case CDSC_BINARY: p = "Binary"; break; default: p = "Unknown"; } sprintf(buf, "document data %s\n", p); (*dfn)(ptr, buf); } if (dsc->page_order != CDSC_ORDER_UNKNOWN) { switch (dsc->page_order) { case CDSC_ASCEND: p = "Ascend"; break; case CDSC_DESCEND: p = "Descend"; break; case CDSC_SPECIAL: p = "Special"; break; default: p = "Unknown"; } sprintf(buf, "page order %s\n", p); (*dfn)(ptr, buf); } if (dsc->page_orientation != CDSC_ORIENT_UNKNOWN) { switch (dsc->page_orientation) { case CDSC_PORTRAIT: p = "Portrait"; break; case CDSC_LANDSCAPE: p = "Landscape"; break; default: p = "Unknown"; } sprintf(buf, "page orientation %s\n", p); (*dfn)(ptr, buf); } if (dsc->page_bbox) { sprintf(buf, "default page boundingbox %d %d %d %d\n", dsc->page_bbox->llx, dsc->page_bbox->lly, dsc->page_bbox->urx, dsc->page_bbox->ury); (*dfn)(ptr, buf); } for (i=0; dsc->media && (imedia_count); i++) { if (dsc->media[i]) { sprintf(buf, "media %d (%.50s) %g %g %g (%.50s) (%.50s)\n", i, dsc->media[i]->name ? dsc->media[i]->name : "", dsc->media[i]->width, dsc->media[i]->height, dsc->media[i]->weight, dsc->media[i]->colour ? dsc->media[i]->colour : "", dsc->media[i]->type ? dsc->media[i]->type : ""); (*dfn)(ptr, buf); if (dsc->media[i]->mediabox) { sprintf(buf, " mediabox %d %d %d %d\n", dsc->media[i]->mediabox->llx, dsc->media[i]->mediabox->llx, dsc->media[i]->mediabox->llx, dsc->media[i]->mediabox->llx); (*dfn)(ptr, buf); } } } if (dsc->page_media) { sprintf(buf, "default page media %.50s\n", dsc->page_media->name); (*dfn)(ptr, buf); } if (dsc->viewing_orientation) { sprintf(buf, "default viewing orientation %f %f %f %f\n", dsc->viewing_orientation->xx, dsc->viewing_orientation->xy, dsc->viewing_orientation->yx, dsc->viewing_orientation->yy); (*dfn)(ptr, buf); } sprintf(fmtbuf, "comments %%%s %%%s\n", offset_fmt, offset_fmt); sprintf(buf, fmtbuf, dsc->begincomments, dsc->endcomments); (*dfn)(ptr, buf); sprintf(fmtbuf, "preview %%%s %%%s\n", offset_fmt, offset_fmt); sprintf(buf, fmtbuf, dsc->beginpreview, dsc->endpreview); (*dfn)(ptr, buf); sprintf(fmtbuf, "defaults %%%s %%%s\n", offset_fmt, offset_fmt); sprintf(buf, fmtbuf, dsc->begindefaults, dsc->enddefaults); (*dfn)(ptr, buf); sprintf(fmtbuf, "prolog %%%s %%%s\n", offset_fmt, offset_fmt); sprintf(buf, fmtbuf, dsc->beginprolog, dsc->endprolog); (*dfn)(ptr, buf); sprintf(fmtbuf, "setup %%%s %%%s\n", offset_fmt, offset_fmt); sprintf(buf, fmtbuf, dsc->beginsetup, dsc->endsetup); (*dfn)(ptr, buf); sprintf(buf, "pages %d\n", dsc->page_pages); (*dfn)(ptr, buf); for (i=0; ipage_count; i++) { sprintf(fmtbuf, "page %%.20s %%d %%%s %%%s\n", offset_fmt, offset_fmt); sprintf(buf, fmtbuf, dsc->page[i].label, dsc->page[i].ordinal, dsc->page[i].begin, dsc->page[i].end); (*dfn)(ptr, buf); if (dsc->page[i].media) { sprintf(buf, " page media %s\n", dsc->page[i].media->name); (*dfn)(ptr, buf); } if (dsc->page[i].orientation != CDSC_ORIENT_UNKNOWN) { switch (dsc->page[i].orientation) { case CDSC_PORTRAIT: p = "Portrait"; break; case CDSC_LANDSCAPE: p = "Landscape"; break; default: p = "Unknown"; } sprintf(buf, " page orientation %s\n", p); (*dfn)(ptr, buf); } if (dsc->page[i].viewing_orientation) { sprintf(buf, " viewing orientation %f %f %f %f\n", dsc->page[i].viewing_orientation->xx, dsc->page[i].viewing_orientation->xy, dsc->page[i].viewing_orientation->yx, dsc->page[i].viewing_orientation->yy); (*dfn)(ptr, buf); } if (dsc->page[i].crop_box) { sprintf(buf, "pagecropbox %f %f %f %f\n", dsc->page[i].crop_box->fllx, dsc->page[i].crop_box->flly, dsc->page[i].crop_box->furx, dsc->page[i].crop_box->fury); (*dfn)(ptr, buf); } } sprintf(fmtbuf, "trailer %%%s %%%s\n", offset_fmt, offset_fmt); sprintf(buf, fmtbuf, dsc->begintrailer, dsc->endtrailer); (*dfn)(ptr, buf); if (pdcs) { if (dsc->dcs1) sprintf(buf, "DCS 1.0 separations\n"); else sprintf(buf, "DCS 2.0 separations\n"); (*dfn)(ptr, buf); } while (pdcs) { if (pdcs->location && (dsc_stricmp(pdcs->location, "Local") == 0)) sprintf(buf, " %s %s\n", pdcs->colourname, pdcs->filename); else { sprintf(fmtbuf, " %%s #%%%s %%%s\n", offset_fmt, offset_fmt); sprintf(buf, fmtbuf, pdcs->colourname, pdcs->begin, pdcs->end); } (*dfn)(ptr, buf); pdcs = pdcs->next; } if (colour) { sprintf(buf, "colours\n"); (*dfn)(ptr, buf); } while (colour) { const char *type; switch (colour->type) { case CDSC_COLOUR_PROCESS: type = "Process"; break; case CDSC_COLOUR_CUSTOM: type = "Custom"; break; default: type = "Unknown"; } sprintf(buf, " %s %s", colour->name, type); (*dfn)(ptr, buf); switch (colour->custom) { case CDSC_CUSTOM_COLOUR_CMYK: sprintf(buf, " CMYK %g %g %g %g\n", colour->cyan, colour->magenta, colour->yellow, colour->black); break; case CDSC_CUSTOM_COLOUR_RGB: sprintf(buf, " RGB %g %g %g\n", colour->red, colour->green, colour->blue); break; default: sprintf(buf, "\n"); } (*dfn)(ptr, buf); colour = colour->next; } for (i=0; dsc->media && (imedia_count); i++) { if (dsc->media[i]) { sprintf(buf, "media %d (%.50s) %g %g %g (%.50s) (%.50s)\n", i, dsc->media[i]->name ? dsc->media[i]->name : "", dsc->media[i]->width, dsc->media[i]->height, dsc->media[i]->weight, dsc->media[i]->colour ? dsc->media[i]->colour : "", dsc->media[i]->type ? dsc->media[i]->type : ""); (*dfn)(ptr, buf); if (dsc->media[i]->mediabox) { sprintf(buf, " mediabox %d %d %d %d\n", dsc->media[i]->mediabox->llx, dsc->media[i]->mediabox->llx, dsc->media[i]->mediabox->llx, dsc->media[i]->mediabox->llx); (*dfn)(ptr, buf); } } } (*dfn)(ptr, "== END DSC dump ==\n"); } #ifdef STANDALONE /****************************************************************/ /* TESTING CODE */ /****************************************************************/ #include void dump_fn(void *caller_data, const char *str) { fputs(str, stdout); } #define COPY_BUF_SIZE 4096 void ps_copy(FILE *outfile, FILE *infile, long begin, long end) { char *buf; int count; buf = (char *)malloc(COPY_BUF_SIZE); if (buf == (char *)NULL) return; if (begin >= 0) fseek(infile, begin, SEEK_SET); begin = ftell(infile); while (begin < end) { count = min(end-begin, COPY_BUF_SIZE); if ((count = fread(buf, 1, count, infile)) > 0) { fwrite(buf, 1, count, outfile); begin += count; } else begin = end; /* EOF or error */ } free(buf); } long mem_allocated = 0; long mem_signature = 0x5aa5f00f; FILE *mem_file = NULL; #define MEM_FILE "c:/gsview.txt" void *debug_memalloc(size_t size, void *closure_data) { void *p = malloc(size + 3 * sizeof(long)); long *pl = (long *)p; if (pl) { pl[0] = mem_signature; pl[1] = (long)closure_data; pl[2] = size; mem_allocated += size; p = (void *)(pl + 3); } if (mem_file == (FILE *)NULL) mem_file = fopen(MEM_FILE, "w"); if (mem_file != (FILE *)NULL) { fprintf(mem_file, "memalloc(%d) allocated=%ld ptr=0x%lx\n", size, mem_allocated, (long)p); fflush(mem_file); } return p; } void debug_memfree(void *ptr, void *closure_data) { long *pl = (long *)ptr; long oldsize = 0; int corrupted = 0; int closure_mismatch = 0; if (pl) { pl -= 3; oldsize = pl[2]; mem_allocated -= oldsize; if (pl[1] != (long)closure_data) closure_mismatch = 1; if (pl[0] != mem_signature) corrupted = 1; else free((void *)pl); } if (mem_file == (FILE *)NULL) mem_file = fopen(MEM_FILE, "w"); if (mem_file != (FILE *)NULL) { fprintf(mem_file, "memfree(%ld) allocated=%ld ptr=0x%lx\n", oldsize, mem_allocated, (long)ptr); if (closure_mismatch) fprintf(mem_file, "memsfree closure_data MISMATCH\n"); if (corrupted) fprintf(mem_file, "memfree HEAP IS CORRUPTED\n"); fflush(mem_file); } } int main(int argc, char *argv[]) { CDSC *dsc; FILE *infile; char buf[256]; char bigbuf[4096]; int count; int code; unsigned int i; const char *filename = NULL; if (argc >= 2) filename = argv[1]; if (filename == NULL) filename = "t.ps"; /* file must be opened in BINARY mode */ infile = fopen(filename, "rb"); if (infile == NULL) return 1; /* test 1 - write single byte at a time */ fprintf(stdout, "TEST 1 - SINGLE BYTE\n"); fseek(infile, 0, SEEK_SET); dsc = dsc_init(NULL); dsc_set_debug_function(dsc, dump_fn); dsc_set_error_function(dsc, dsc_error_fn); while ((count = fread(buf, 1, 1, infile))!=0) { dsc_scan_data(dsc, buf, count); } dsc_fixup(dsc); dsc_display(dsc, dump_fn); dsc_free(dsc); /* test 2 - write multiple bytes at a time */ fprintf(stdout, "TEST 2 - %d BYTES\n", sizeof(buf)); fseek(infile, 0, SEEK_SET); dsc = dsc_init(NULL); dsc_set_debug_function(dsc, dump_fn); dsc_set_error_function(dsc, dsc_error_fn); while ((count = fread(buf, 1, sizeof(buf), infile))!=0) { dsc_scan_data(dsc, buf, count); } dsc_fixup(dsc); dsc_display(dsc, dump_fn); dsc_free(dsc); /* test 3 - write one line at a time a time */ /* Only works if the file does not contain null characters */ fprintf(stdout, "TEST 3 - LINE\n"); fseek(infile, 0, SEEK_SET); dsc = dsc_init(NULL); dsc_set_debug_function(dsc, dump_fn); dsc_set_error_function(dsc, dsc_error_fn); memset(buf, 0, sizeof(buf)); while (fgets(buf, sizeof(buf)-1, infile) != NULL) { code = dsc_scan_data(dsc, buf, strlen(buf)); if (code != CDSC_OK) fprintf(stdout, "Line %d, DSC %d\n", dsc->line_count, code); } dsc_fixup(dsc); dsc_display(dsc, dump_fn); fflush(stdout); #ifndef UNIX setmode(fileno(stdout), O_BINARY); #endif fputs("==== COMMENTS ====\r\n", stdout); ps_copy(stdout, infile, dsc->begincomments, dsc->endcomments); fputs("==== PREVIEW ====\r\n", stdout); ps_copy(stdout, infile, dsc->beginpreview, dsc->endpreview); fputs("==== DEFAULTS ====\r\n", stdout); ps_copy(stdout, infile, dsc->begindefaults, dsc->enddefaults); fputs("==== PROLOG ====\r\n", stdout); ps_copy(stdout, infile, dsc->beginprolog, dsc->endprolog); fputs("==== SETUP ====\r\n", stdout); ps_copy(stdout, infile, dsc->beginsetup, dsc->endsetup); for (i=0; ipage_count; i++) { fprintf(stdout, "==== PAGE %d ====\r\n", i+1); ps_copy(stdout, infile, dsc->page[i].begin, dsc->page[i].end); } fputs("==== TRAILER ====\r\n", stdout); ps_copy(stdout, infile, dsc->begintrailer, dsc->endtrailer); fputs("==== EOF ====\r\n", stdout); dsc_free(dsc); /* test 4 - write multiple bytes at a time, debug memalloc */ fprintf(stdout, "TEST 4 - %d BYTES, DEBUG MALLOC\n", sizeof(buf)); fseek(infile, 0, SEEK_SET); dsc = dsc_init_with_alloc(NULL, debug_memalloc, debug_memfree, NULL); dsc_set_debug_function(dsc, dump_fn); dsc_set_error_function(dsc, dsc_error_fn); while ((count = fread(buf, 1, sizeof(buf), infile))!=0) { dsc_scan_data(dsc, buf, count); } dsc_fixup(dsc); dsc_display(dsc, dump_fn); dsc_free(dsc); if (mem_file) fclose(mem_file); /* test 5 - write multiple bytes at a time */ fprintf(stdout, "TEST 5 - %d BYTES\n", sizeof(bigbuf)); fseek(infile, 0, SEEK_SET); dsc = dsc_init(NULL); dsc_set_debug_function(dsc, dump_fn); dsc_set_error_function(dsc, dsc_error_fn); while ((count = fread(bigbuf, 1, sizeof(bigbuf), infile))!=0) { dsc_scan_data(dsc, bigbuf, count); } dsc_fixup(dsc); dsc_display(dsc, dump_fn); dsc_free(dsc); dsc = NULL; return 0; } #endif epstool-3.08/src/cbmp.h0000644000076400007640000000515010252260054014417 0ustar rjlrjl00000000000000/* Copyright (C) 2002-2003 Ghostgum Software Pty Ltd. All rights reserved. This software is provided AS-IS with no warranty, either express or implied. This software is distributed under licence and may not be copied, modified or distributed except as expressly authorised under the terms of the licence contained in the file LICENCE in this distribution. For more information about licensing, please refer to http://www.ghostgum.com.au/ or contact Ghostsgum Software Pty Ltd, 218 Gallaghers Rd, Glen Waverley VIC 3150, AUSTRALIA, Fax +61 3 9886 6616. */ /* $Id: cbmp.h,v 1.5 2003/08/08 23:58:14 ghostgum Exp $ */ /* BMP structures */ typedef struct tagBITMAP2 { DWORD biSize; LONG biWidth; LONG biHeight; WORD biPlanes; WORD biBitCount; DWORD biCompression; DWORD biSizeImage; LONG biXPelsPerMeter; LONG biYPelsPerMeter; DWORD biClrUsed; DWORD biClrImportant; } BITMAP2; typedef BITMAP2 * LPBITMAP2; #define BITMAP2_LENGTH 40 typedef struct tagBITMAPFILE { WORD bfType; DWORD bfSize; WORD bfReserved1; WORD bfReserved2; DWORD bfOffBits; } BITMAPFILE; typedef BITMAPFILE * LPBITMAPFILE; #define BITMAPFILE_LENGTH 14 typedef struct tagRGB4 { BYTE rgbBlue; BYTE rgbGreen; BYTE rgbRed; BYTE rgbReserved; } RGB4; typedef RGB4 * LPRGB4; #define RGB4_BLUE 0 #define RGB4_GREEN 1 #define RGB4_RED 2 #define RGB4_EXTRA 3 #define RGB4_LENGTH 4 typedef enum PNM_FORMAT_s { PBMRAW=4, PGMRAW=5, PPMRAW=6, PNMANY=99 /* use any */ } PNM_FORMAT; /* Prototypes */ IMAGE * bmpfile_to_image(LPCTSTR filename); IMAGE * bmp_to_image(unsigned char *pbitmap, unsigned int length); IMAGE * pnmfile_to_image(LPCTSTR filename); void bitmap_image_free(IMAGE *img); int image_to_bmpfile(IMAGE*img, LPCTSTR filename, float xdpi, float ydpi); int image_to_pnmfile(IMAGE* img, LPCTSTR filename, PNM_FORMAT pnm_format); int image_to_tifffile(IMAGE* img, LPCTSTR filename, float xdpi, float ydpi); int image_to_pngfile(IMAGE* img, LPCTSTR filename); int image_to_pictfile(IMAGE* img, LPCTSTR filename, float xdpi, float ydpi); IMAGE * pngfile_to_image(LPCTSTR filename); int image_to_tifffile(IMAGE* img, LPCTSTR filename, float xdpi, float ydpi); int image_to_tiff(GFile *f, IMAGE *img, int xoffset, int yoffset, int width, int height, float xdpi, float ydpi, BOOL tiff4, BOOL use_packbits); void write_dword(DWORD val, GFile *f); void write_word_as_dword(WORD val, GFile *f); void write_word(WORD val, GFile *f); DWORD get_dword(const unsigned char *buf); WORD get_word(const unsigned char *buf); epstool-3.08/src/dscparse.h0000644000076400007640000004521010252260054015303 0ustar rjlrjl00000000000000/* Copyright (C) 2000-2005, Ghostgum Software Pty Ltd. All rights reserved. This file is part of GSview. This program is distributed with NO WARRANTY OF ANY KIND. No author or distributor accepts any responsibility for the consequences of using it, or for whether it serves any particular purpose or works at all, unless he or she says so in writing. Refer to the GSview Licence (the "Licence") for full details. Every copy of GSview must include a copy of the Licence, normally in a plain ASCII text file named LICENCE. The Licence grants you the right to copy, modify and redistribute GSview, but only under certain conditions described in the Licence. Among other things, the Licence requires that the copyright notice and this notice be preserved on all copies. */ /* $Id: dscparse.h,v 1.18 2005/01/14 08:15:52 ghostgum Exp $ */ /* Interface for the DSC parser. */ #ifndef dscparse_INCLUDED # define dscparse_INCLUDED /* Some local types that may need modification */ typedef int GSBOOL; typedef unsigned long GSDWORD; /* must be at least 32 bits */ typedef unsigned int GSWORD; /* must be at least 16 bits */ #ifndef FALSE # define FALSE ((GSBOOL)0) # define TRUE ((GSBOOL)(!FALSE)) #endif /* DSC_OFFSET is an unsigned integer which holds the offset * from the start of a file to a particular DSC comment, * or the length of a file. * Normally it is "unsigned long" which is commonly 32 bits. * Change it if you need to handle larger files. */ #ifndef DSC_OFFSET # define DSC_OFFSET unsigned long #endif #ifndef DSC_OFFSET_FORMAT # define DSC_OFFSET_FORMAT "lu" /* for printf */ #endif #ifndef dsc_private # ifdef private # define dsc_private private # else # define dsc_private static # endif #endif #ifndef min # define min(a,b) ((a) < (b) ? (a) : (b)) #endif #ifndef max # define max(a,b) ((a) > (b) ? (a) : (b)) #endif /* maximum legal length of lines in a DSC compliant file */ #define DSC_LINE_LENGTH 255 /* memory for strings is allocated in chunks of this length */ #define CDSC_STRING_CHUNK 4096 /* page array is allocated in chunks of this many pages */ #define CDSC_PAGE_CHUNK 128 /* buffer length for storing lines passed to dsc_scan_data() */ /* must be at least 2 * DSC_LINE_LENGTH */ /* We choose 8192 as twice the length passed to us by GSview */ #define CDSC_DATA_LENGTH 8192 /* Return codes from dsc_scan_data() * < 0 = error * >=0 = OK * * -1 = error, usually insufficient memory. * 0-9 = normal * 10-99 = internal codes, should not be seen. * 100-999 = identifier of last DSC comment processed. */ typedef enum CDSC_RETURN_CODE_e { CDSC_ERROR = -1, /* Fatal error, usually insufficient memory */ CDSC_OK = 0, /* OK, no DSC comment found */ CDSC_NOTDSC = 1, /* Not DSC, or DSC is being ignored */ /* Any section */ CDSC_UNKNOWNDSC = 100, /* DSC comment not recognised */ /* Header section */ CDSC_PSADOBE = 200, /* %!PS-Adobe- */ CDSC_BEGINCOMMENTS = 201, /* %%BeginComments */ CDSC_ENDCOMMENTS = 202, /* %%EndComments */ CDSC_PAGES = 203, /* %%Pages: */ CDSC_CREATOR = 204, /* %%Creator: */ CDSC_CREATIONDATE = 205, /* %%CreationDate: */ CDSC_TITLE = 206, /* %%Title: */ CDSC_FOR = 207, /* %%For: */ CDSC_LANGUAGELEVEL = 208, /* %%LanguageLevel: */ CDSC_BOUNDINGBOX = 209, /* %%BoundingBox: */ CDSC_ORIENTATION = 210, /* %%Orientation: */ CDSC_PAGEORDER = 211, /* %%PageOrder: */ CDSC_DOCUMENTMEDIA = 212, /* %%DocumentMedia: */ CDSC_DOCUMENTPAPERSIZES = 213, /* %%DocumentPaperSizes: */ CDSC_DOCUMENTPAPERFORMS = 214, /* %%DocumentPaperForms: */ CDSC_DOCUMENTPAPERCOLORS = 215, /* %%DocumentPaperColors: */ CDSC_DOCUMENTPAPERWEIGHTS = 216, /* %%DocumentPaperWeights: */ CDSC_DOCUMENTDATA = 217, /* %%DocumentData: */ CDSC_REQUIREMENTS = 218, /* IGNORED %%Requirements: */ CDSC_DOCUMENTNEEDEDFONTS = 219, /* IGNORED %%DocumentNeededFonts: */ CDSC_DOCUMENTSUPPLIEDFONTS = 220, /* IGNORED %%DocumentSuppliedFonts: */ CDSC_HIRESBOUNDINGBOX = 221, /* %%HiResBoundingBox: */ CDSC_CROPBOX = 222, /* %%CropBox: */ CDSC_PLATEFILE = 223, /* %%PlateFile: (DCS 2.0) */ CDSC_DOCUMENTPROCESSCOLORS = 224, /* %%DocumentProcessColors: */ CDSC_DOCUMENTCUSTOMCOLORS = 225, /* %%DocumentCustomColors: */ CDSC_CMYKCUSTOMCOLOR = 226, /* %%CMYKCustomColor: */ CDSC_RGBCUSTOMCOLOR = 227, /* %%RGBCustomColor: */ /* Preview section */ CDSC_BEGINPREVIEW = 301, /* %%BeginPreview */ CDSC_ENDPREVIEW = 302, /* %%EndPreview */ /* Defaults section */ CDSC_BEGINDEFAULTS = 401, /* %%BeginDefaults */ CDSC_ENDDEFAULTS = 402, /* %%EndDefaults */ /* also %%PageMedia, %%PageOrientation, %%PageBoundingBox */ /* Prolog section */ CDSC_BEGINPROLOG = 501, /* %%BeginProlog */ CDSC_ENDPROLOG = 502, /* %%EndProlog */ CDSC_BEGINFONT = 503, /* IGNORED %%BeginFont */ CDSC_ENDFONT = 504, /* IGNORED %%EndFont */ CDSC_BEGINFEATURE = 505, /* IGNORED %%BeginFeature */ CDSC_ENDFEATURE = 506, /* IGNORED %%EndFeature */ CDSC_BEGINRESOURCE = 507, /* IGNORED %%BeginResource */ CDSC_ENDRESOURCE = 508, /* IGNORED %%EndResource */ CDSC_BEGINPROCSET = 509, /* IGNORED %%BeginProcSet */ CDSC_ENDPROCSET = 510, /* IGNORED %%EndProcSet */ /* Setup section */ CDSC_BEGINSETUP = 601, /* %%BeginSetup */ CDSC_ENDSETUP = 602, /* %%EndSetup */ CDSC_FEATURE = 603, /* IGNORED %%Feature: */ CDSC_PAPERCOLOR = 604, /* IGNORED %%PaperColor: */ CDSC_PAPERFORM = 605, /* IGNORED %%PaperForm: */ CDSC_PAPERWEIGHT = 606, /* IGNORED %%PaperWeight: */ CDSC_PAPERSIZE = 607, /* %%PaperSize: */ /* also %%Begin/EndFeature, %%Begin/EndResource */ /* Page section */ CDSC_PAGE = 700, /* %%Page: */ CDSC_PAGETRAILER = 701, /* IGNORED %%PageTrailer */ CDSC_BEGINPAGESETUP = 702, /* IGNORED %%BeginPageSetup */ CDSC_ENDPAGESETUP = 703, /* IGNORED %%EndPageSetup */ CDSC_PAGEMEDIA = 704, /* %%PageMedia: */ /* also %%PaperColor, %%PaperForm, %%PaperWeight, %%PaperSize */ CDSC_PAGEORIENTATION = 705, /* %%PageOrientation: */ CDSC_PAGEBOUNDINGBOX = 706, /* %%PageBoundingBox: */ /* also %%Begin/EndFont, %%Begin/EndFeature */ /* also %%Begin/EndResource, %%Begin/EndProcSet */ CDSC_INCLUDEFONT = 707, /* IGNORED %%IncludeFont: */ CDSC_VIEWINGORIENTATION = 708, /* %%ViewingOrientation: */ CDSC_PAGECROPBOX = 709, /* %%PageCropBox: */ /* Trailer section */ CDSC_TRAILER = 800, /* %%Trailer */ /* also %%Pages, %%BoundingBox, %%Orientation, %%PageOrder, %%DocumentMedia */ /* %%Page is recognised as an error */ /* also %%DocumentNeededFonts, %%DocumentSuppliedFonts */ /* End of File */ CDSC_EOF = 900 /* %%EOF */ } CDSC_RETURN_CODE; /* stored in dsc->preview */ typedef enum CDSC_PREVIEW_TYPE_e { CDSC_NOPREVIEW = 0, CDSC_EPSI = 1, CDSC_TIFF = 2, CDSC_WMF = 3, CDSC_PICT = 4 } CDSC_PREVIEW_TYPE; /* stored in dsc->page_order */ typedef enum CDSC_PAGE_ORDER_e { CDSC_ORDER_UNKNOWN = 0, CDSC_ASCEND = 1, CDSC_DESCEND = 2, CDSC_SPECIAL = 3 } CDSC_PAGE_ORDER; /* stored in dsc->page_orientation and dsc->page[pagenum-1].orientation */ typedef enum CDSC_ORIENTATION_ENUM_e { CDSC_ORIENT_UNKNOWN = 0, CDSC_PORTRAIT = 1, CDSC_LANDSCAPE = 2, CDSC_UPSIDEDOWN = 3, CDSC_SEASCAPE = 4 } CDSC_ORIENTATION_ENUM; /* stored in dsc->document_data */ typedef enum CDSC_DOCUMENT_DATA_e { CDSC_DATA_UNKNOWN = 0, CDSC_CLEAN7BIT = 1, CDSC_CLEAN8BIT = 2, CDSC_BINARY = 3 } CDSC_DOCUMENT_DATA ; typedef struct CDSCBBOX_S { int llx; int lly; int urx; int ury; } CDSCBBOX; typedef struct CDSCFBBOX_S { float fllx; float flly; float furx; float fury; } CDSCFBBOX; typedef struct CDSCMEDIA_S { const char *name; float width; /* PostScript points */ float height; float weight; /* GSM */ const char *colour; const char *type; CDSCBBOX *mediabox; /* Used by GSview for PDF MediaBox */ } CDSCMEDIA; #define CDSC_KNOWN_MEDIA 25 extern const CDSCMEDIA dsc_known_media[CDSC_KNOWN_MEDIA]; typedef struct CDSCCTM_S { /* used for %%ViewingOrientation */ float xx; float xy; float yx; float yy; /* float ty; */ /* float ty; */ } CDSCCTM; typedef struct CDSCPAGE_S { int ordinal; const char *label; DSC_OFFSET begin; DSC_OFFSET end; unsigned int orientation; const CDSCMEDIA *media; CDSCBBOX *bbox; /* PageBoundingBox, also used by GSview for PDF CropBox */ CDSCCTM *viewing_orientation; /* Added 2001-10-19 */ CDSCFBBOX *crop_box; /* CropBox */ } CDSCPAGE; /* binary DOS EPS header */ typedef struct CDSCDOSEPS_S { GSDWORD ps_begin; GSDWORD ps_length; GSDWORD wmf_begin; GSDWORD wmf_length; GSDWORD tiff_begin; GSDWORD tiff_length; GSWORD checksum; } CDSCDOSEPS; /* macbinary header */ typedef struct CDSCMACBIN_S { GSDWORD data_begin; /* EPS */ GSDWORD data_length; GSDWORD resource_begin; /* PICT */ GSDWORD resource_length; } CDSCMACBIN; /* rather than allocated every string with malloc, we allocate * chunks of 4k and place the (usually) short strings in these * chunks. */ typedef struct CDSCSTRING_S CDSCSTRING; struct CDSCSTRING_S { unsigned int index; unsigned int length; char *data; CDSCSTRING *next; }; /* Desktop Color Separations - DCS 2.0 */ typedef struct CDCS2_S CDCS2; struct CDCS2_S { char *colourname; char *filetype; /* Usually EPS */ /* For multiple file DCS, location and filename will be set */ char *location; /* Local or NULL */ char *filename; /* For single file DCS, begin will be not equals to end */ DSC_OFFSET begin; DSC_OFFSET end; /* We maintain the separations as a linked list */ CDCS2 *next; }; typedef enum CDSC_COLOUR_TYPE_e { CDSC_COLOUR_UNKNOWN=0, CDSC_COLOUR_PROCESS=1, /* %%DocumentProcessColors: */ CDSC_COLOUR_CUSTOM=2 /* %%DocumentCustomColors: */ } CDSC_COLOUR_TYPE; typedef enum CDSC_CUSTOM_COLOUR_e { CDSC_CUSTOM_COLOUR_UNKNOWN=0, CDSC_CUSTOM_COLOUR_RGB=1, /* %%RGBCustomColor: */ CDSC_CUSTOM_COLOUR_CMYK=2 /* %%CMYKCustomColor: */ } CDSC_CUSTOM_COLOUR; typedef struct CDSCCOLOUR_S CDSCCOLOUR; struct CDSCCOLOUR_S { char *name; CDSC_COLOUR_TYPE type; CDSC_CUSTOM_COLOUR custom; /* If custom is CDSC_CUSTOM_COLOUR_RGB, the next three are correct */ float red; float green; float blue; /* If colourtype is CDSC_CUSTOM_COLOUR_CMYK, the next four are correct */ float cyan; float magenta; float yellow; float black; /* Next colour */ CDSCCOLOUR *next; }; /* DSC error reporting */ typedef enum CDSC_MESSAGE_ERROR_e { CDSC_MESSAGE_BBOX = 0, CDSC_MESSAGE_EARLY_TRAILER = 1, CDSC_MESSAGE_EARLY_EOF = 2, CDSC_MESSAGE_PAGE_IN_TRAILER = 3, CDSC_MESSAGE_PAGE_ORDINAL = 4, CDSC_MESSAGE_PAGES_WRONG = 5, CDSC_MESSAGE_EPS_NO_BBOX = 6, CDSC_MESSAGE_EPS_PAGES = 7, CDSC_MESSAGE_NO_MEDIA = 8, CDSC_MESSAGE_ATEND = 9, CDSC_MESSAGE_DUP_COMMENT = 10, CDSC_MESSAGE_DUP_TRAILER = 11, CDSC_MESSAGE_BEGIN_END = 12, CDSC_MESSAGE_BAD_SECTION = 13, CDSC_MESSAGE_LONG_LINE = 14, CDSC_MESSAGE_INCORRECT_USAGE = 15 } CDSC_MESSAGE_ERROR; /* severity */ typedef enum CDSC_MESSAGE_SEVERITY_e { CDSC_ERROR_NONE = -1, /* Not an error */ CDSC_ERROR_INFORM = 0, /* Not an error, but a common abuse */ CDSC_ERROR_WARN = 1, /* Not a DSC error itself */ CDSC_ERROR_ERROR = 2 /* DSC error */ } CDSC_MESSAGE_SEVERITY; /* response */ typedef enum CDSC_RESPONSE_e { CDSC_RESPONSE_OK = 0, CDSC_RESPONSE_CANCEL = 1, CDSC_RESPONSE_IGNORE_ALL = 2 } CDSC_RESPONSE; extern const char * const dsc_message[]; #ifndef CDSC_TYPEDEF #define CDSC_TYPEDEF typedef struct CDSC_s CDSC; #endif struct CDSC_s { char dummy[1024]; /* public data */ GSBOOL dsc; /* TRUE if DSC comments found */ GSBOOL ctrld; /* TRUE if has CTRLD at start of stream */ GSBOOL pjl; /* TRUE if has HP PJL at start of stream */ GSBOOL epsf; /* TRUE if EPSF */ GSBOOL pdf; /* TRUE if Portable Document Format */ unsigned int preview; /* enum CDSC_PREVIEW_TYPE */ char *dsc_version; /* first line of file */ unsigned int language_level; unsigned int document_data; /* Clean7Bit, Clean8Bit, Binary */ /* enum CDSC_DOCUMENT_DATA */ /* DSC sections */ DSC_OFFSET begincomments; DSC_OFFSET endcomments; DSC_OFFSET beginpreview; DSC_OFFSET endpreview; DSC_OFFSET begindefaults; DSC_OFFSET enddefaults; DSC_OFFSET beginprolog; DSC_OFFSET endprolog; DSC_OFFSET beginsetup; DSC_OFFSET endsetup; DSC_OFFSET begintrailer; DSC_OFFSET endtrailer; CDSCPAGE *page; unsigned int page_count; /* number of %%Page: pages in document */ unsigned int page_pages; /* number of pages in document from %%Pages: */ unsigned int page_order; /* enum CDSC_PAGE_ORDER */ unsigned int page_orientation; /* the default page orientation */ /* enum CDSC_ORIENTATION */ CDSCCTM *viewing_orientation; unsigned int media_count; /* number of media items */ CDSCMEDIA **media; /* the array of media */ const CDSCMEDIA *page_media;/* the default page media */ CDSCBBOX *bbox; /* the document bounding box */ CDSCBBOX *page_bbox; /* the default page bounding box */ CDSCDOSEPS *doseps; /* DOS binary header */ char *dsc_title; char *dsc_creator; char *dsc_date; char *dsc_for; unsigned int max_error; /* highest error number that will be reported */ const int *severity; /* array of severity values, one per error */ /* private data */ void *caller_data; /* pointer to be provided when calling */ /* error and debug callbacks */ int id; /* last DSC comment found */ int scan_section; /* section currently being scanned */ /* enum CDSC_SECTION */ DSC_OFFSET doseps_end; /* ps_begin+ps_length, otherwise 0 */ unsigned int page_chunk_length; /* number of pages allocated */ DSC_OFFSET file_length; /* length of document */ /* If provided we try to recognise %%Trailer and %%EOF */ /* incorrectly embedded inside document. */ /* We will not parse DSC comments beyond this point. */ /* Can be left set to default value of 0 */ int skip_document; /* recursion level of %%BeginDocument: */ int skip_bytes; /* #bytes to ignore from BeginData: */ /* or DOSEPS preview section */ int skip_lines; /* #lines to ignore from BeginData: */ GSBOOL skip_pjl; /* TRUE if skip PJL until first PS comment */ int begin_font_count; /* recursion level of %%BeginFont */ int begin_feature_count; /* recursion level of %%BeginFeature */ int begin_resource_count; /* recursion level of %%BeginResource */ int begin_procset_count; /* recursion level of %%BeginProcSet */ /* buffer for input */ char data[CDSC_DATA_LENGTH];/* start of buffer */ unsigned int data_length; /* length of data in buffer */ unsigned int data_index; /* offset to next char in buffer */ DSC_OFFSET data_offset; /* offset from start of document */ /* to byte in data[0] */ GSBOOL eof; /* TRUE if there is no more data */ /* information about DSC line */ char *line; /* pointer to last read DSC line */ /* not null terminated */ unsigned int line_length; /* number of characters in line */ GSBOOL eol; /* TRUE if dsc_line contains EOL */ GSBOOL last_cr; /* TRUE if last line ended in \r */ /* check next time for \n */ unsigned int line_count; /* line number */ GSBOOL long_line; /* TRUE if found a line longer than 255 characters */ char last_line[256]; /* previous DSC line, used for %%+ */ /* more efficient string storage (for short strings) than malloc */ CDSCSTRING *string_head; /* linked list head */ CDSCSTRING *string; /* current list item */ /* memory allocation routines */ void *(*memalloc)(size_t size, void *closure_data); void (*memfree)(void *ptr, void *closure_data); void *mem_closure_data; /* function for printing debug messages */ void (*debug_print_fn)(void *caller_data, const char *str); /* function for reporting errors in DSC comments */ int (*dsc_error_fn)(void *caller_data, CDSC *dsc, unsigned int explanation, const char *line, unsigned int line_len); /* public data */ /* Added 2001-10-01 */ CDSCFBBOX *hires_bbox; /* the hires document bounding box */ CDSCFBBOX *crop_box; /* the size of the trimmed page */ CDCS2 *dcs2; /* Desktop Color Separations 2.0 */ CDSCCOLOUR *colours; /* Process and custom colours */ /* private data */ /* Added 2002-03-30 */ int ref_count; /* public data */ /* Added 2003-07-15 */ CDSCMACBIN *macbin; /* Mac Binary header */ /* Added 2004-04-28 */ GSBOOL dcs1; /* True if dcs2 set but really DCS 1.0 */ /* public data */ /* Added 2005-01-14 */ CDSC_MESSAGE_SEVERITY worst_error; /* CDSC_MESSAGE_SEVERITY */ }; /* Public functions */ /* Create and initialise DSC parser */ CDSC *dsc_init(void *caller_data); CDSC *dsc_init_with_alloc( void *caller_data, void *(*memalloc)(size_t size, void *closure_data), void (*memfree)(void *ptr, void *closure_data), void *closure_data); /* Free the DSC parser */ void dsc_free(CDSC *dsc); /* Reference counting for dsc structure */ /* dsc_new is the same as dsc_init */ /* dsc_ref is called by dsc_new */ /* If dsc_unref decrements to 0, dsc_free will be called */ CDSC *dsc_new(void *caller_data); int dsc_ref(CDSC *dsc); int dsc_unref(CDSC *dsc); /* Tell DSC parser how long document will be, to allow ignoring * of early %%Trailer and %%EOF. This is optional. */ void dsc_set_length(CDSC *dsc, DSC_OFFSET len); /* Process a buffer containing DSC comments and PostScript */ int dsc_scan_data(CDSC *dsc, const char *data, int len); /* All data has been processed, fixup any DSC errors */ int dsc_fixup(CDSC *dsc); /* Install error query function */ void dsc_set_error_function(CDSC *dsc, int (*dsc_error_fn)(void *caller_data, CDSC *dsc, unsigned int explanation, const char *line, unsigned int line_len)); /* Install print function for debug messages */ void dsc_set_debug_function(CDSC *dsc, void (*debug_fn)(void *caller_data, const char *str)); /* Print a message to debug output, if provided */ void dsc_debug_print(CDSC *dsc, const char *str); /* Given a page number, find the filename for multi-file DCS 2.0 */ const char * dsc_find_platefile(CDSC *dsc, int page); /* Compare two strings, case insensitive */ int dsc_stricmp(const char *s, const char *t); /* should be internal only functions, but made available to * GSview for handling PDF */ int dsc_add_page(CDSC *dsc, int ordinal, char *label); int dsc_add_media(CDSC *dsc, CDSCMEDIA *media); int dsc_set_page_bbox(CDSC *dsc, unsigned int page_number, int llx, int lly, int urx, int ury); /* in dscutil.c */ void dsc_display(CDSC *dsc, void (*dfn)(void *ptr, const char *str)); #endif /* dscparse_INCLUDED */ epstool-3.08/src/copt.h0000644000076400007640000000727510252260054014455 0ustar rjlrjl00000000000000/* Copyright (C) 2001-2002 Ghostgum Software Pty Ltd. All rights reserved. This software is provided AS-IS with no warranty, either express or implied. This software is distributed under licence and may not be copied, modified or distributed except as expressly authorised under the terms of the licence contained in the file LICENCE in this distribution. For more information about licensing, please refer to http://www.ghostgum.com.au/ or contact Ghostsgum Software Pty Ltd, 218 Gallaghers Rd, Glen Waverley VIC 3150, AUSTRALIA, Fax +61 3 9886 6616. */ /* $Id: copt.h,v 1.10 2003/01/29 06:55:17 ghostgum Exp $ */ /* Options header */ /* Public */ int opt_init(OPTION *opt); int opt_read(OPTION *opt, LPCTSTR ininame); int opt_write(OPTION *opt, LPCTSTR ininame); int opt_media(OPTION *opt, int n, const char **name, float *width, float *height); /****************************************************/ /* Private */ #ifdef DEFINE_COPT #define DEFAULT_MEDIA "a4" /* #define DEFAULT_MEDIA "letter" */ #define DEFAULT_RESOLUTION 72.0 #define DEFAULT_ZOOMRES 300.0 #define INISECTION "GSview" typedef enum UNIT_e { UNIT_PT = 0, UNIT_MM = 1, UNIT_IN = 2 } UNIT; typedef enum SAFER_e { SAFER_UNSAFE = 0, SAFER_SAFE = 1, SAFER_PARANOID = 2 } SAFER; struct MEDIA_s { char name[MAXSTR]; /* name of media */ float width; /* pts */ float height; /* pts */ ORIENT orientation; BOOL swap_landscape; /* landscape <-> seascape */ BOOL rotate; /* width and height swapped */ float xdpi; /* dpi */ float ydpi; /* dpi */ DISPLAY_FORMAT depth; int alpha_text; /* bpp */ int alpha_graphics; /* bpp */ }; #define MAX_USERMEDIA 16 typedef struct USERMEDIA_s USERMEDIA; struct USERMEDIA_s { char name[MAXSTR]; /* name of media */ float width; /* pts */ float height; /* pts */ }; /* options that are saved in INI file */ struct OPTION_s { int language; int gsversion; BOOL savesettings; POINT img_origin; POINT img_size; /* Ghostscript */ char gsdll[MAXSTR]; char gsinclude[MAXSTR]; char gsother[MAXSTR]; /* GhostPCL */ char pldll[MAXSTR]; /* Security */ SAFER safer; /* Unit */ UNIT unit; BOOL unitfine; /* Pagesize */ float custom_width; float custom_height; USERMEDIA usermedia[MAX_USERMEDIA]; BOOL variable_pagesize; MEDIA media; /* DSC */ int dsc_warn; /* level of DSC error warnings */ BOOL ignore_dsc; BOOL epsf_clip; /* PDF */ BOOL pdf_crop; /* Display */ float zoom_xdpi; float zoom_ydpi; float pcl_dpi; #ifdef NOTUSED BOOL configured; BOOL img_max; int pstotext; BOOL button_show; #endif /* FIX: are these used yet? */ BOOL epsf_warn; /* Do NOT save the following in the INI file */ /* FIX: put this in the user dictionary during gssrv_run_header for PDF */ char pdf_password[MAXSTR]; /* -sPDFPassword= */ #ifdef NOTUSED BOOL epsf_warn; BOOL redisplay; BOOL show_bbox; BOOL save_dir; /* for printing to GS device */ char printer_device[64]; /* Ghostscript device for printing */ char printer_resolution[64]; BOOL print_fixed_media; /* for converting with GS device */ char convert_device[64]; char convert_resolution[64]; /* Ghostscript device for converting */ BOOL convert_fixed_media; /* for printing to GDI device */ int print_gdi_depth; /* IDC_MONO, IDC_GREY, IDC_COLOUR */ BOOL print_gdi_fixed_media; /* general printing */ #define PRINT_GDI 0 #define PRINT_GS 1 #define PRINT_PS 2 #define PRINT_CONVERT 3 int print_method; /* GDI, GS, PS */ BOOL print_reverse; /* pages to be in reverse order */ BOOL print_to_file; char printer_queue[MAXSTR]; /* for Win32 */ int pdf2ps; BOOL auto_bbox; MATRIX ctm; MEASURE measure; #endif }; #endif /* DEFINE_COPT */ epstool-3.08/src/gdevdsp.h0000644000076400007640000001616710252260054015144 0ustar rjlrjl00000000000000/* Copyright (C) 2001, Ghostgum Software Pty Ltd. All rights reserved. This software is provided AS-IS with no warranty, either express or implied. This software is distributed under license and may not be copied, modified or distributed except as expressly authorized under the terms of the license contained in the file LICENSE in this distribution. For more information about licensing, please refer to http://www.ghostscript.com/licensing/. For information on commercial licensing, go to http://www.artifex.com/licensing/ or contact Artifex Software, Inc., 101 Lucas Valley Road #110, San Rafael, CA 94903, U.S.A., +1(415)492-9861. */ /* $Id: gdevdsp.h,v 1.2 2002/05/29 11:39:43 ghostgum Exp $ */ /* gdevdisp.h - callback structure for DLL based display device */ #ifndef gdevdisp_INCLUDED # define gdevdisp_INCLUDED /* * The callback structure must be provided by calling the * Ghostscript APIs in the following order: * gsapi_new_instance(&minst); * gsapi_set_display_callback(minst, callback); * gsapi_init_with_arg(minst, argc, argv); * * Supported parameters and default values are: * -dDisplayHandle=0 long * Caller supplied handle. * Included as first parameter of all callback functions. * * -dDisplayFormat=0 long * Color format specified using bitfields below. * Included as argument of display_size() and display_presize() * These can only be changed when the device is closed. * * The second parameter of all callback functions "void *device" * is the address of the Ghostscript display device instance. * The arguments "void *handle" and "void *device" together * uniquely identify an instance of the display device. * * A typical sequence of callbacks would be * open, presize, memalloc, size, sync, page * presize, memfree, memalloc, size, sync, page * preclose, memfree, close * The caller should not access the image buffer: * - before the first sync * - between presize and size * - after preclose * If opening the device fails, you might see the following: * open, presize, memalloc, memfree, close * */ #define DISPLAY_VERSION_MAJOR 1 #define DISPLAY_VERSION_MINOR 0 /* The display format is set by a combination of the following bitfields */ /* Define the color space alternatives */ typedef enum DISPLAY_FORMAT_COLOR_e { DISPLAY_COLORS_NATIVE = (1<<0), DISPLAY_COLORS_GRAY = (1<<1), DISPLAY_COLORS_RGB = (1<<2), DISPLAY_COLORS_CMYK = (1<<3) } DISPLAY_FORMAT_COLOR; #define DISPLAY_COLORS_MASK 0x000fL /* Define whether alpha information, or an extra unused bytes is included */ /* DISPLAY_ALPHA_FIRST and DISPLAY_ALPHA_LAST are not implemented */ typedef enum DISPLAY_FORMAT_ALPHA_e { DISPLAY_ALPHA_NONE = (0<<4), DISPLAY_ALPHA_FIRST = (1<<4), DISPLAY_ALPHA_LAST = (1<<5), DISPLAY_UNUSED_FIRST = (1<<6), /* e.g. Mac xRGB */ DISPLAY_UNUSED_LAST = (1<<7) /* e.g. Windows BGRx */ } DISPLAY_FORMAT_ALPHA; #define DISPLAY_ALPHA_MASK 0x0070L /* Define the depth per component for DISPLAY_COLORS_GRAY, * DISPLAY_COLORS_RGB and DISPLAY_COLORS_CMYK, * or the depth per pixel for DISPLAY_COLORS_NATIVE * DISPLAY_DEPTH_2 and DISPLAY_DEPTH_12 have not been tested. */ typedef enum DISPLAY_FORMAT_DEPTH_e { DISPLAY_DEPTH_1 = (1<<8), DISPLAY_DEPTH_2 = (1<<9), DISPLAY_DEPTH_4 = (1<<10), DISPLAY_DEPTH_8 = (1<<11), DISPLAY_DEPTH_12 = (1<<12), DISPLAY_DEPTH_16 = (1<<13) /* unused (1<<14) */ /* unused (1<<15) */ } DISPLAY_FORMAT_DEPTH; #define DISPLAY_DEPTH_MASK 0xff00L /* Define whether Red/Cyan should come first, * or whether Blue/Black should come first */ typedef enum DISPLAY_FORMAT_ENDIAN_e { DISPLAY_BIGENDIAN = (0<<16), /* Red/Cyan first */ DISPLAY_LITTLEENDIAN = (1<<16) /* Blue/Black first */ } DISPLAY_FORMAT_ENDIAN; #define DISPLAY_ENDIAN_MASK 0x00010000L /* Define whether the raster starts at the top or bottom of the bitmap */ typedef enum DISPLAY_FORMAT_FIRSTROW_e { DISPLAY_TOPFIRST = (0<<17), /* Unix, Mac */ DISPLAY_BOTTOMFIRST = (1<<17) /* Windows */ } DISPLAY_FORMAT_FIRSTROW; #define DISPLAY_FIRSTROW_MASK 0x00020000L /* Define whether packing RGB in 16-bits should use 555 * or 565 (extra bit for green) */ typedef enum DISPLAY_FORMAT_555_e { DISPLAY_NATIVE_555 = (0<<18), DISPLAY_NATIVE_565 = (1<<18) } DISPLAY_FORMAT_555; #define DISPLAY_555_MASK 0x00040000L #ifndef display_callback_DEFINED #define display_callback_DEFINED typedef struct display_callback_s display_callback; #endif struct display_callback_s { /* Size of this structure */ /* Used for checking if we have been handed a valid structure */ int size; /* Major version of this structure */ /* The major version number will change if this structure changes. */ int version_major; /* Minor version of this structure */ /* The minor version number will change if new features are added * without changes to this structure. For example, a new color * format. */ int version_minor; /* New device has been opened */ /* This is the first event from this device. */ int (*display_open)(void *handle, void *device); /* Device is about to be closed. */ /* Device will not be closed until this function returns. */ int (*display_preclose)(void *handle, void *device); /* Device has been closed. */ /* This is the last event from this device. */ int (*display_close)(void *handle, void *device); /* Device is about to be resized. */ /* Resize will only occur if this function returns 0. */ /* raster is byte count of a row. */ int (*display_presize)(void *handle, void *device, int width, int height, int raster, unsigned int format); /* Device has been resized. */ /* New pointer to raster returned in pimage */ int (*display_size)(void *handle, void *device, int width, int height, int raster, unsigned int format, unsigned char *pimage); /* flushpage */ int (*display_sync)(void *handle, void *device); /* showpage */ /* If you want to pause on showpage, then don't return immediately */ int (*display_page)(void *handle, void *device, int copies, int flush); /* Notify the caller whenever a portion of the raster is updated. */ /* This can be used for cooperative multitasking or for * progressive update of the display. * This function pointer may be set to NULL if not required. */ int (*display_update)(void *handle, void *device, int x, int y, int w, int h); /* Allocate memory for bitmap */ /* This is provided in case you need to create memory in a special * way, e.g. shared. If this is NULL, the Ghostscript memory device * allocates the bitmap. This will only called to allocate the * image buffer. The first row will be placed at the address * returned by display_memalloc. */ void *(*display_memalloc)(void *handle, void *device, unsigned long size); /* Free memory for bitmap */ /* If this is NULL, the Ghostscript memory device will free the bitmap */ int (*display_memfree)(void *handle, void *device, void *mem); }; #endif /* gdevdisp_INCLUDED */ epstool-3.08/src/errors.h0000644000076400007640000001132210252260054015010 0ustar rjlrjl00000000000000/* Copyright (C) 1989, 1995, 1998, 1999 Aladdin Enterprises. All rights reserved. This software is provided AS-IS with no warranty, either express or implied. This software is distributed under license and may not be copied, modified or distributed except as expressly authorized under the terms of the license contained in the file LICENSE in this distribution. For more information about licensing, please refer to http://www.ghostscript.com/licensing/. For information on commercial licensing, go to http://www.artifex.com/licensing/ or contact Artifex Software, Inc., 101 Lucas Valley Road #110, San Rafael, CA 94903, U.S.A., +1(415)492-9861. */ /*$Id: errors.h,v 1.1 2002/05/22 10:52:31 ghostgum Exp $ */ /* Definition of error codes */ #ifndef errors_INCLUDED # define errors_INCLUDED /* * A procedure that may return an error always returns * a non-negative value (zero, unless otherwise noted) for success, * or negative for failure. * We use ints rather than an enum to avoid a lot of casting. */ /* Define the error name table */ extern const char *const gs_error_names[]; /* ------ PostScript Level 1 errors ------ */ #define e_unknownerror (-1) /* unknown error */ #define e_dictfull (-2) #define e_dictstackoverflow (-3) #define e_dictstackunderflow (-4) #define e_execstackoverflow (-5) #define e_interrupt (-6) /* We also need to define gs_error_interrupt, for gpcheck.h. */ #undef gs_error_interrupt #define gs_error_interrupt e_interrupt #define e_invalidaccess (-7) #define e_invalidexit (-8) #define e_invalidfileaccess (-9) #define e_invalidfont (-10) #define e_invalidrestore (-11) #define e_ioerror (-12) #define e_limitcheck (-13) #define e_nocurrentpoint (-14) #define e_rangecheck (-15) #define e_stackoverflow (-16) #define e_stackunderflow (-17) #define e_syntaxerror (-18) #define e_timeout (-19) #define e_typecheck (-20) #define e_undefined (-21) #define e_undefinedfilename (-22) #define e_undefinedresult (-23) #define e_unmatchedmark (-24) #define e_VMerror (-25) #define LEVEL1_ERROR_NAMES\ "unknownerror", "dictfull", "dictstackoverflow", "dictstackunderflow",\ "execstackoverflow", "interrupt", "invalidaccess", "invalidexit",\ "invalidfileaccess", "invalidfont", "invalidrestore", "ioerror",\ "limitcheck", "nocurrentpoint", "rangecheck", "stackoverflow",\ "stackunderflow", "syntaxerror", "timeout", "typecheck", "undefined",\ "undefinedfilename", "undefinedresult", "unmatchedmark", "VMerror" /* ------ Additional Level 2 and DPS errors ------ */ #define e_configurationerror (-26) #define e_invalidcontext (-27) #define e_undefinedresource (-28) #define e_unregistered (-29) /* invalidid is for the NeXT DPS extension. */ #define e_invalidid (-30) #define LEVEL2_ERROR_NAMES\ "configurationerror", "invalidcontext", "undefinedresource",\ "unregistered", "invalidid" #define ERROR_NAMES LEVEL1_ERROR_NAMES, LEVEL2_ERROR_NAMES /* ------ Pseudo-errors used internally ------ */ /* * Internal code for a fatal error. * gs_interpret also returns this for a .quit with a positive exit code. */ #define e_Fatal (-100) /* * Internal code for the .quit operator. * The real quit code is an integer on the operand stack. * gs_interpret returns this only for a .quit with a zero exit code. */ #define e_Quit (-101) /* * Internal code for a normal exit from the interpreter. * Do not use outside of interp.c. */ #define e_InterpreterExit (-102) /* * Internal code that indicates that a procedure has been stored in the * remap_proc of the graphics state, and should be called before retrying * the current token. This is used for color remapping involving a call * back into the interpreter -- inelegant, but effective. */ #define e_RemapColor (-103) /* * Internal code to indicate we have underflowed the top block * of the e-stack. */ #define e_ExecStackUnderflow (-104) /* * Internal code for the vmreclaim operator with a positive operand. * We need to handle this as an error because otherwise the interpreter * won't reload enough of its state when the operator returns. */ #define e_VMreclaim (-105) /* * Internal code for requesting more input from run_string. */ #define e_NeedInput (-106) /* * Internal code for stdin callout. */ #define e_NeedStdin (-107) /* * Internal code for stdout callout. */ #define e_NeedStdout (-108) /* * Internal code for stderr callout. */ #define e_NeedStderr (-109) /* * Internal code for a normal exit when usage info is displayed. * This allows Window versions of Ghostscript to pause until * the message can be read. */ #define e_Info (-110) /* * Define which error codes require re-executing the current object. */ #define ERROR_IS_INTERRUPT(ecode)\ ((ecode) == e_interrupt || (ecode) == e_timeout) #endif /* errors_INCLUDED */ epstool-3.08/src/capp.h0000644000076400007640000001402510252260053014421 0ustar rjlrjl00000000000000/* Copyright (C) 2001-2003 Ghostgum Software Pty Ltd. All rights reserved. This software is provided AS-IS with no warranty, either express or implied. This software is distributed under licence and may not be copied, modified or distributed except as expressly authorised under the terms of the licence contained in the file LICENCE in this distribution. For more information about licensing, please refer to http://www.ghostgum.com.au/ or contact Ghostsgum Software Pty Ltd, 218 Gallaghers Rd, Glen Waverley VIC 3150, AUSTRALIA, Fax +61 3 9886 6616. */ /* $Id: capp.h,v 1.7 2003/01/18 02:36:40 ghostgum Exp $ */ /* Application header */ /* Public */ int app_platform_init(GSview *a); int app_platform_finish(GSview *a); int app_gssrv_request(GSview *a, GSREQ *reqnew); int app_plsrv_request(GSview *a, GSREQ *reqnew); GSview *app_new(void *handle, BOOL multithread); int app_free(GSview *a); int app_ref(GSview *a); int app_unref(GSview *a); GSDLL **app_dll(GSview *a); PLDLL **app_pldll(GSview *a); Doc **app_docs(GSview *a); OPTION *app_option(GSview *a); PAGECACHE **app_pagecache(GSview *a); BOOL app_multithread(GSview *a); int app_lock(GSview *a); int app_unlock(GSview *a); #define MAX_LAST_FILES 4 void app_update_last_files(GSview *a, LPCTSTR filename); LPCTSTR app_last_files(GSview *a, int i); int app_read_last_files(GSview *a, LPCTSTR filename); int app_write_last_files(GSview *a, LPCTSTR filename); int zlib_load(GSview *a); void zlib_free(GSview *a); int zlib_uncompress(GSview *app, GFile *outfile, const char *filename); #ifdef __cplusplus extern "C" { #endif /* for zlib gunzip decompression */ typedef void *gzFile ; typedef gzFile (WINAPI *PFN_gzopen)(const char *path, const char *mode); typedef int (WINAPI *PFN_gzread)(gzFile file, void *buf, unsigned len); typedef int (WINAPI *PFN_gzclose)(gzFile file); #ifdef __cplusplus } #endif int bzip2_load(GSview *a); void bzip2_free(GSview *a); int bzip2_uncompress(GSview *app, GFile *outfile, const char *filename); #ifdef __cplusplus extern "C" { #endif /* for bzip2 decompression */ typedef void *bzFile ; typedef bzFile (WINAPI *PFN_bzopen)(const char *path, const char *mode); typedef int (WINAPI *PFN_bzread)(bzFile file, void *buf, unsigned len); typedef int (WINAPI *PFN_bzclose)(bzFile file); #ifdef __cplusplus } #endif /* Write text messages to log window */ void app_log(const char *str, int len); int app_msgf(GSview *a, const char *fmt, ...); int app_msg(GSview *a, const char *str); int app_msg_len(GSview *a, const char *str, int len); int app_msg_len_nolock(GSview *a, const char *str, int len); int app_csmsgf(GSview *a, LPCTSTR fmt, ...); int app_csmsg(GSview *a, LPCTSTR wstr); int app_csmsg_len(GSview *a, LPCTSTR wstr, int wlen); int app_csmsg_len_nolock(GSview *a, LPCTSTR wstr, int wlen); int load_string(GSview *app, int i, TCHAR *buf, int len); const char *get_string(GSview *a, int id); /* Not Windows */ int get_dsc_response(GSview *app, LPCTSTR str); GFile *app_temp_gfile(GSview *app, TCHAR *fname, int len); FILE *app_temp_file(GSview *app, TCHAR *fname, int len); int app_msg_box(GSview *a, LPCTSTR str, int icon); extern const char szAppName[]; /* GLOBAL */ /****************************************************/ /* Private */ #ifdef DEFINE_CAPP typedef struct STRING_s STRING; typedef struct ZLIB_s ZLIB; struct ZLIB_s { BOOL loaded; GGMODULE hmodule; PFN_gzopen gzopen; PFN_gzread gzread; PFN_gzclose gzclose; }; typedef struct BZIP2_s BZIP2; struct BZIP2_s { BOOL loaded; GGMODULE hmodule; PFN_bzopen bzopen; PFN_bzread bzread; PFN_bzclose bzclose; }; struct GSview_s { void *handle; /* Platform specific handle */ /* e.g. pointer to MFC theApp */ int refcount; /* number of references to Application */ /* MRU files */ TCHAR last_files[MAX_LAST_FILES][MAXSTR]; /* last 4 files used */ int last_files_count; /* number of files known */ /* List of documents */ Doc *doclist; /* Ghostscript DLL */ GSDLL *gsdll; /* GhostPCL DLL */ PLDLL *pldll; /* The server thread which executes ghostscript */ /* and handles requests for rendering and printing. */ GSSRV *gssrv; /* The server thread which executes GhostPCL */ /* and handles requests for rendering and printing. */ GSSRV *plsrv; /* The list of rendered pages that we have cached */ PAGECACHE *pagecache; /* Options */ OPTION option; TCHAR option_name[MAXSTR]; /* filename for options */ /* Compression libraries */ ZLIB zlib; BZIP2 bzip2; /* TRUE if application is shutting down */ BOOL quitnow; /* When running single threaded, we need to return to main * loop to complete some commands. */ BOOL in_main; /* TRUE if in main loop */ BOOL go_main; /* TRUE if we should return to main loop */ /* We can run as either single thread, or multithread with * Ghostscript on the second thread. */ BOOL multithread; /* When running multithread, we use a mutex to protect * access to resources. */ GGMUTEX hmutex; int lock_count; /* for debugging lock */ /* Text Window for Ghostscript Messages */ /* This is maintained in narrow characters, even if the user * interface is using wide characters. This is because we * want to have a simple file for sending bug reports, * and because Ghostscript is taking all input and filenames * as narrow characters. If a wide character filename is * not translated to narrow characters correctly, this * should show up in the message log. */ #ifdef _Windows #define TWLENGTH 61440 #endif #ifdef OS2 #define TWLENGTH 16384 #endif #ifndef TWLENGTH #define TWLENGTH 61440 #endif #define TWSCROLL 1024 char twbuf[TWLENGTH]; int twend; STRING *strings; /* translation strings */ }; int free_strings(STRING *s); int init_strings(GSview *a, const char *filename); float app_get_points(GSview *a, const TCHAR *str); void app_put_points(GSview *a, UNIT unit, TCHAR *buf, int len, float n); #endif /* DEFINE_CAPP */ epstool-3.08/src/iapi.h0000644000076400007640000002347110252260054014426 0ustar rjlrjl00000000000000/* Copyright (C) 1996-2001 Ghostgum Software Pty Ltd. All rights reserved. This software is provided AS-IS with no warranty, either express or implied. This software is distributed under license and may not be copied, modified or distributed except as expressly authorized under the terms of the license contained in the file LICENSE in this distribution. For more information about licensing, please refer to http://www.ghostscript.com/licensing/. For information on commercial licensing, go to http://www.artifex.com/licensing/ or contact Artifex Software, Inc., 101 Lucas Valley Road #110, San Rafael, CA 94903, U.S.A., +1(415)492-9861. */ /* $Id: iapi.h,v 1.2 2002/06/16 22:03:21 ghostgum Exp $ */ /* * Public API for Ghostscript interpreter * for use both as DLL and for static linking. * * Should work for Windows, OS/2, Linux, Mac. * * DLL exported functions should be as similar as possible to imain.c * You will need to include "errors.h". * * Current problems: * 1. Ghostscript does not support multiple instances. * 2. Global variables in gs_main_instance_default() * and gsapi_instance_counter */ /* Exported functions may need different prefix * GSDLLEXPORT marks functions as exported * GSDLLAPI is the calling convention used on functions exported * by Ghostscript * GSDLLCALL is used on callback functions called by Ghostscript * When you include this header file in the caller, you may * need to change the definitions by defining these * before including this header file. * Make sure you get the calling convention correct, otherwise your * program will crash either during callbacks or soon after returning * due to stack corruption. */ #ifndef iapi_INCLUDED # define iapi_INCLUDED #ifdef __WINDOWS__ # define _Windows #endif #ifdef _Windows # ifndef GSDLLEXPORT # define GSDLLEXPORT __declspec(dllexport) # endif # ifndef GSDLLAPI # define GSDLLAPI __stdcall # endif # ifndef GSDLLCALL # define GSDLLCALL __stdcall # endif #endif /* _Windows */ #if defined(OS2) && defined(__IBMC__) # ifndef GSDLLAPI # define GSDLLAPI _System # endif # ifndef GSDLLCALL # define GSDLLCALL _System # endif #endif /* OS2 && __IBMC */ #ifdef __MACINTOSH__ # pragma export on #endif #ifndef GSDLLEXPORT # define GSDLLEXPORT #endif #ifndef GSDLLAPI # define GSDLLAPI #endif #ifndef GSDLLCALL # define GSDLLCALL #endif #if defined(__IBMC__) # define GSDLLAPIPTR * GSDLLAPI # define GSDLLCALLPTR * GSDLLCALL #else # define GSDLLAPIPTR GSDLLAPI * # define GSDLLCALLPTR GSDLLCALL * #endif #ifndef gs_main_instance_DEFINED # define gs_main_instance_DEFINED typedef struct gs_main_instance_s gs_main_instance; #endif #ifndef display_callback_DEFINED # define display_callback_DEFINED typedef struct display_callback_s display_callback; #endif typedef struct gsapi_revision_s { const char *product; const char *copyright; long revision; long revisiondate; } gsapi_revision_t; /* Get version numbers and strings. * This is safe to call at any time. * You should call this first to make sure that the correct version * of the Ghostscript is being used. * pr is a pointer to a revision structure. * len is the size of this structure in bytes. * Returns 0 if OK, or if len too small (additional parameters * have been added to the structure) it will return the required * size of the structure. */ GSDLLEXPORT int GSDLLAPI gsapi_revision(gsapi_revision_t *pr, int len); /* * WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING * Ghostscript supports only one instance. * The current implementation uses a global static instance * counter to make sure that only a single instance is used. * If you try to create two instances, the second attempt * will return < 0 and set pinstance to NULL. * WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING */ /* Create a new instance of Ghostscript. * This instance is passed to most other API functions. * The caller_handle will be provided to callback functions. */ GSDLLEXPORT int GSDLLAPI gsapi_new_instance(gs_main_instance **pinstance, void *caller_handle); /* * WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING * Ghostscript supports only one instance. * The current implementation uses a global static instance * counter to make sure that only a single instance is used. * WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING */ /* Destroy an instance of Ghostscript * Before you call this, Ghostscript must have finished. * If Ghostscript has been initialised, you must call gsapi_exit() * before gsapi_delete_instance. */ GSDLLEXPORT void GSDLLAPI gsapi_delete_instance(gs_main_instance *instance); /* Set the callback functions for stdio * The stdin callback function should return the number of * characters read, 0 for EOF, or -1 for error. * The stdout and stderr callback functions should return * the number of characters written. * If a callback address is NULL, the real stdio will be used. */ GSDLLEXPORT int GSDLLAPI gsapi_set_stdio(gs_main_instance *instance, int (GSDLLCALLPTR stdin_fn)(void *caller_handle, char *buf, int len), int (GSDLLCALLPTR stdout_fn)(void *caller_handle, const char *str, int len), int (GSDLLCALLPTR stderr_fn)(void *caller_handle, const char *str, int len)); /* Set the callback function for polling. * This is used for handling window events or cooperative * multitasking. This function will only be called if * Ghostscript was compiled with CHECK_INTERRUPTS * as described in gpcheck.h. */ GSDLLEXPORT int GSDLLAPI gsapi_set_poll(gs_main_instance *instance, int (GSDLLCALLPTR poll_fn)(void *caller_handle)); /* Set the display device callback structure. * If the display device is used, this must be called * after gsapi_new_instance() and before gsapi_init_with_args(). * See gdevdisp.h for more details. */ GSDLLEXPORT int GSDLLAPI gsapi_set_display_callback( gs_main_instance *instance, display_callback *callback); /* Initialise the interpreter. * This calls gs_main_init_with_args() in imainarg.c * 1. If quit or EOF occur during gsapi_init_with_args(), * the return value will be e_Quit. This is not an error. * You must call gsapi_exit() and must not call any other * gsapi_XXX functions. * 2. If usage info should be displayed, the return value will be e_Info * which is not an error. Do not call gsapi_exit(). * 3. Under normal conditions this returns 0. You would then * call one or more gsapi_run_*() functions and then finish * with gsapi_exit(). */ GSDLLEXPORT int GSDLLAPI gsapi_init_with_args(gs_main_instance *instance, int argc, char **argv); /* * The gsapi_run_* functions are like gs_main_run_* except * that the error_object is omitted. * If these functions return <= -100, either quit or a fatal * error has occured. You then call gsapi_exit() next. * The only exception is gsapi_run_string_continue() * which will return e_NeedInput if all is well. */ GSDLLEXPORT int GSDLLAPI gsapi_run_string_begin(gs_main_instance *instance, int user_errors, int *pexit_code); GSDLLEXPORT int GSDLLAPI gsapi_run_string_continue(gs_main_instance *instance, const char *str, unsigned int length, int user_errors, int *pexit_code); GSDLLEXPORT int GSDLLAPI gsapi_run_string_end(gs_main_instance *instance, int user_errors, int *pexit_code); GSDLLEXPORT int GSDLLAPI gsapi_run_string_with_length(gs_main_instance *instance, const char *str, unsigned int length, int user_errors, int *pexit_code); GSDLLEXPORT int GSDLLAPI gsapi_run_string(gs_main_instance *instance, const char *str, int user_errors, int *pexit_code); GSDLLEXPORT int GSDLLAPI gsapi_run_file(gs_main_instance *instance, const char *file_name, int user_errors, int *pexit_code); /* Exit the interpreter. * This must be called on shutdown if gsapi_init_with_args() * has been called, and just before gsapi_delete_instance(). */ GSDLLEXPORT int GSDLLAPI gsapi_exit(gs_main_instance *instance); /* function prototypes */ typedef int (GSDLLAPIPTR PFN_gsapi_revision)( gsapi_revision_t *pr, int len); typedef int (GSDLLAPIPTR PFN_gsapi_new_instance)( gs_main_instance **pinstance, void *caller_handle); typedef void (GSDLLAPIPTR PFN_gsapi_delete_instance)( gs_main_instance *instance); typedef int (GSDLLAPIPTR PFN_gsapi_set_stdio)(gs_main_instance *instance, int (GSDLLCALLPTR stdin_fn)(void *caller_handle, char *buf, int len), int (GSDLLCALLPTR stdout_fn)(void *caller_handle, const char *str, int len), int (GSDLLCALLPTR stderr_fn)(void *caller_handle, const char *str, int len)); typedef int (GSDLLAPIPTR PFN_gsapi_set_poll)(gs_main_instance *instance, int(GSDLLCALLPTR poll_fn)(void *caller_handle)); typedef int (GSDLLAPIPTR PFN_gsapi_set_display_callback)( gs_main_instance *instance, display_callback *callback); typedef int (GSDLLAPIPTR PFN_gsapi_init_with_args)( gs_main_instance *instance, int argc, char **argv); typedef int (GSDLLAPIPTR PFN_gsapi_run_string_begin)( gs_main_instance *instance, int user_errors, int *pexit_code); typedef int (GSDLLAPIPTR PFN_gsapi_run_string_continue)( gs_main_instance *instance, const char *str, unsigned int length, int user_errors, int *pexit_code); typedef int (GSDLLAPIPTR PFN_gsapi_run_string_end)( gs_main_instance *instance, int user_errors, int *pexit_code); typedef int (GSDLLAPIPTR PFN_gsapi_run_string_with_length)( gs_main_instance *instance, const char *str, unsigned int length, int user_errors, int *pexit_code); typedef int (GSDLLAPIPTR PFN_gsapi_run_string)( gs_main_instance *instance, const char *str, int user_errors, int *pexit_code); typedef int (GSDLLAPIPTR PFN_gsapi_run_file)(gs_main_instance *instance, const char *file_name, int user_errors, int *pexit_code); typedef int (GSDLLAPIPTR PFN_gsapi_exit)(gs_main_instance *instance); #ifdef __MACINTOSH__ #pragma export off #endif #endif /* iapi_INCLUDED */ epstool-3.08/src/cpdfscan.h0000644000076400007640000000326710252260054015266 0ustar rjlrjl00000000000000/* Copyright (C) 2002 Ghostgum Software Pty Ltd. All rights reserved. This software is provided AS-IS with no warranty, either express or implied. This software is distributed under licence and may not be copied, modified or distributed except as expressly authorised under the terms of the licence contained in the file LICENCE in this distribution. For more information about licensing, please refer to http://www.ghostgum.com.au/ or contact Ghostsgum Software Pty Ltd, 218 Gallaghers Rd, Glen Waverley VIC 3150, AUSTRALIA, Fax +61 3 9886 6616. */ /* $Id: cpdfscan.h,v 1.2 2002/07/26 12:09:06 ghostgum Exp $ */ /* PDF scanner header */ /* This is a rudimentary PDF scanner, intended to get * the page count, and for each page the Rotate, MediaBox * and CropBox. */ /* Opaque type for PDF scanner */ typedef struct PDFSCAN_s PDFSCAN; /* For MediaBox and CropBox */ typedef struct PDFBBOX_s PDFBBOX; struct PDFBBOX_s { float llx; float lly; float urx; float ury; }; /* Open a PDF file and read trailer, cross reference tables, * and number of pages. Returns NULL if it fails. * If print_fn is NULL, it will print error messages to stdout. * PDF file is kept open until pdf_scan_close. */ PDFSCAN * pdf_scan_open(const TCHAR *filename, void *handle, int(*print_fn)(void *handle, const char *ptr, int len)); /* Return number of pages in PDF file */ int pdf_scan_page_count(PDFSCAN *ps) ; /* Read Rotate, MediaBox and CropBox for the specified page */ /* Return 0 if OK, non-zero on error */ int pdf_scan_page_media(PDFSCAN *ps, int pagenum, int *rotate, PDFBBOX *mediabox, PDFBBOX *cropbox); /* Close PDF file and ps. */ void pdf_scan_close(PDFSCAN *ps); epstool-3.08/src/cprofile.h0000644000076400007640000000312110252260054015275 0ustar rjlrjl00000000000000/* Copyright (C) 2001-2002 Ghostgum Software Pty Ltd. All rights reserved. This software is provided AS-IS with no warranty, either express or implied. This software is distributed under licence and may not be copied, modified or distributed except as expressly authorised under the terms of the licence contained in the file LICENCE in this distribution. For more information about licensing, please refer to http://www.ghostgum.com.au/ or contact Ghostsgum Software Pty Ltd, 218 Gallaghers Rd, Glen Waverley VIC 3150, AUSTRALIA, Fax +61 3 9886 6616. */ /* $Id: cprofile.h,v 1.2 2002/05/27 09:43:38 ghostgum Exp $ */ /* Windows style INI files */ /* Public */ #ifndef PROFILE_TYPEDEF #define PROFILE_TYPEDEF typedef struct PROFILE_s PROFILE; #endif PROFILE * profile_open(LPCTSTR filename); int profile_read_string(PROFILE *prf, const char *section, const char *entry, const char *def, char *buffer, int len); BOOL profile_write_string(PROFILE *prf, const char *section, const char *entry, const char *value); BOOL profile_close(PROFILE *prf); /****************************************************/ /* Private */ #ifdef DEFINE_CPROFILE typedef struct prfentry_s prfentry; typedef struct prfsection_s prfsection; struct prfentry_s { char *name; char *value; prfentry *next; }; struct prfsection_s { char *name; prfentry *entry; prfsection *next; }; #ifdef NOTUSED typedef struct prop_item_s prop_item; struct prop_item_s { char name[MAXSTR]; char value[MAXSTR]; }; #endif struct PROFILE_s { TCHAR *name; FILE *file; BOOL changed; prfsection *section; }; #endif epstool-3.08/epstool.txt0000664000076400007640000000006010252260054014761 0ustar rjlrjl00000000000000Documentation for epstool is in doc/epstool.htm epstool-3.08/doc/0000775000076400007640000000000010252260054013304 5ustar rjlrjl00000000000000epstool-3.08/doc/gsview.css0000664000076400007640000000161210252260054015322 0ustar rjlrjl00000000000000/* This is the default GSview stylesheet, based on the Ghostscript stylesheet */ body { color: black; background-color: white; } h1,h2,h3,h4,h5,h6 { font-family: sans-serif; } /* This needs a patched html file else you have it all over the place */ /* we only want this for the "visual header" at the page top */ h1 { text-align: center; background-color: #80FF80; } /* Number the h2/h3 -- doesn't work on v4/5 browsers */ h2 { counter-increment: h2-count; counter-reset: h3-count; } h2:before { content: counter(h2-count) " "; } h3 { counter-increment: h3-count; } h3:before { content: counter(h2-count) "." counter(h3-count) " "; } tt { color: rgb(40%,24%,24%); } a > tt, a > b > tt { color: blue; } a { color: blue; } a.offsite { font-style: oblique; } a:visited { color: rgb(60%,0%,30%); } a:hover, a:active, a:focus { background: #FFFFAA; } epstool-3.08/doc/epstool.10000644000076400007640000004240010252260054015051 0ustar rjlrjl00000000000000.TH EPSTOOL 1 "2005-06-10" "Martin Pitt and Russell Lang" .SH NAME epstool \- Edit preview images and fix bounding boxes in EPS files. .SH SYNOPSIS .B epstool .I command [ .I options ] .I inputfile outputfile .SH DESCRIPTION .B epstool is a utility to create or extract preview images in EPS files. It can also calculate optimal bounding boxes. .SS "EPS (Encapsulated PostScript Format)" EPS is a specialised form of a PostScript file that complies with the Document Structuring Conventions (DSC) and is intended to be embedded inside another PostScript file. An EPS file must contain a special first line that identifies it as an EPS file (e.g. \fB%!PS\-Adobe\-3.0 EPSF\-3.0\fR) and it must contain a \fB%%BoundingBox:\fR line. The EPS file only draws within the rectangle defined by the bounding box. The PostScript code must avoid using PostScript operators that would interfere with the embedding. These include operators with global effects such as changing the page size and changing the half tone screen. .SS PREVIEWS EPS files may contain a preview to be used by programs that can't interpret the PostScript code. There are three ways to add a preview to an EPS file. .IP Interchange This preview is included within PostScript comments in a section marked %%BeginPreview: / %%EndPreview. The actual image data is stored in hexadecimal format. This format is most commonly used on Unix. .IP DOS\ EPS The preview is a TIFF or Windows Metafile. A DOS EPS file has a 30 byte binary header which gives offsets and lengths for the PostScript, TIFF and Windows Metafile sections. You can't send a DOS EPS file directly to a printer \- you have to remove the binary header and preview first. This format is most commonly used on MS\-Windows. .IP PICT The preview is in PICT format stored in the resource fork of the file. This format is most commonly used on the Macinstosh. Epstool provides limited support for this format. .SH "COMMANDS (one only):" .TP .B \-t4, \-\-add\-tiff4\-preview Add a TIFF 4 preview. The preview is monochrome and is intended for use with old programs that won't read TIFF6, such as Word Perfect 5.1 for DOS. .TP .B \-t6u, \-\-add\-tiff6u\-preview Add a TIFF 6 uncompressed preview. See .B \-\-add\-tiff6p\-preview for how to add a greyscale or monochrome preview. .TP .B \-t6p, \-\-add\-tiff6p\-preview Add a TIFF 6 preview compressed with packbits (simple run length encoding). The preview will normally be full colour, but you can make it greyscale by adding the option .B \-\-device bmpgray or .B \-\-device pgmraw, or monochrome using .B \-\-device bmpmono or .B \-\-device pbmraw\fR. .TP .B \-tg, \-\-add\-tiff\-preview Add a TIFF preview using ghostscript to generate the TIFF file. You must specify a suitable TIFF device using .B \-\-device\fR. If you want a compressed monochrome image, you might use .B \-\-device tiffg3\fR. .TP .B \-i, \-\-add\-interchange\-preview Add a monochrome interchange preview. .TP .B \-w, \-\-add\-metafile\-preview Add a Windows Metafile (WMF) preview. The metafile will contain a bitmap, not vector information. The preview will normally be full colour. See .B \-\-add\-tiff6p\-preview for how to add a greyscale or monochrome preview. .TP .B \-\-add\-pict\-preview Add a Mac PICT preview. EPSF files with PICT previews can generally be used only on Mac computers. The preview will be full colour. The AppleSingle and MacBinary formats will contain the EPSF and the preview. The AppleDouble or Resource format will contain the preview only and needs to accompany the original EPSF file. To specify the file format use \fB\-\-mac\-single\fR, \fB\-\-mac\-double\fR, \fB\-\-mac\-binary\fR or \fB\-\-mac\-rsrc\fR. .TP .B \-\-add\-user\-preview \fI filename Add a user supplied image as a preview. The image can be a Windows bitmap, a PBMPLUS file, a TIFF image or a Windows Metafile. Window bitmaps and PBMPLUS files will be converted to TIFF6 compressed with packbits. TIFF and Windows Metafile images will be added unchanged. .TP .B \-\-bitmap Create a bitmap of the area within the EPS bounding box. The bitmap type must be specified with \fB\-\-device\fR. If processing a DCS 2.0 file, the separation can be specified with \fB\-\-page\-number\fR. .TP .B \-\-copy Copy the EPS file. This is generally used with the .B \-\-bbox option to update the bounding box. .TP .B \-\-dcs2\-multi Convert DCS 2.0 separations to multiple files. See DCS 2.0. If the output name is out.eps, then the separations would be named out.eps.Cyan etc. .TP .B \-\-dcs2\-single Convert DCS 2.0 separations to a single file. See DCS 2.0. .TP .B \-\-dcs2\-report Write the separation names, lengths and CMYK values to standard output. This can be used to identify if a DCS 2.0 file is missing the composite page or preview. .TP .B \-\-dump Display some information about the file type and DSC comments. .TP .B \-p, \-\-extract\-postscript Extract the PostScript section from a DOS EPS file. .TP .B \-v, \-\-extract\-preview Extract the preview section from a DOS EPS file. .TP .B \-h, \-\-help Display a summary of the epstool commands and options. .TP .B \-\-test\-eps Partially test if a file complies with the EPSF specification. .SH OPTIONS .TP .B \-b, \-\-bbox Calculate the bounding box using the ghostscript bbox device and update in the EPS file. .TP .B \-\-combine\-separations \fI filename Combine the separations of the input DCS 2.0 file with those of this file. It is an error if the bounding boxes do not match or they contain separations with the same name. This option must be used with \fB\-\-dcs2\-multi\fR or \fB\-\-dcs2\-single\fR. The composite page may later need to be updated with \fB\-\-replace\-composite\fR. .TP .B \-\-combine\-tolerance \fI pts When using \fB\-\-combine\-separations\fR, allow the bounding boxes to vary by up to \fIpts\fR points. The default is 0 so the bounding boxes must match exactly. .TP .B \-\-custom\-colours \fI filename When using .B \-\-replace\-composite on a DCS 2.0 file, use the colours specified in this file in preference to those specified in the composite page. .TP .B \-d, \-\-debug Be more verbose about progress. Do not remove temporary files. .TP .B \-\-device\fI name Specify a ghostscript device to be used when creating the preview or bitmap. For .B \-\-add\-tiff\-preview this must be one of the ghostscript tiff devices (e.g. tiffg3, tiff24nc). For any other preview, it must be one of the bmp or pbmplus devices (e.g. bmpgray, bmp16m, pgmraw, ppmraw). For bitmap output (\fB\-\-bitmap\fR) it can be any ghostscript bitmap device. .TP .B \-\-doseps\-reverse When writing a DOS EPS file (TIFF or WMF preview), the default is to write the PostScript before the preview. Using \fB\-\-doseps\-reverse\fR puts the preview before the PostScript section, which is required by some buggy programs. Either order is correct. .TP .B \-\-dpi\fI resolution Set the resolution of the preview or bitmap. The default is 72 dpi. .TP .B \-\-dpi\-render\fI resolution Render at a higher resolution set by .B \-\-dpi\-render , then downsample to the resolution set by .B \-\-dpi\fR. This works when adding a preview image or using .B \-\-replace\-composite , but not when using .B \-\-bitmap. This improves the preview quality when the original contains a pre\-rendered image and .B \-\-dpi\-render is set to match the original target printer. .TP .B \-\-ignore\-information Ignore information messages from the DSC parser. Use at your own risk. These messages usually indicate that something is wrong with an EPS file, but that most EPS handlers probably won't care. An example is a line with more than 255 characters. .TP .B \-\-ignore\-warnings Ignore warnings from the DSC parser. Use at your own risk. These messages are usually about faults in the DSC comments that are recoverable by \fBepstool\fR, but may confuse other EPS handlers. An example is a bounding box that incorrectly uses floating point numbers instead of integer. .TP .B \-\-ignore\-errors Ignore warnings from the DSC parser. Use at your own risk. You really should fix the EPS file first. .TP .B \-\-gs command Specify the name the ghostscript program. On Unix the default is gs. On Windows, .B epstool will check the registry for installed versions of ghostscript and use the latest, otherwise it will use gswin32c.exe. .TP .B \-\-gs\-args\fI arguments Specify additional Ghostscript arguments. This might be used to select anti\-aliasing with "\-dTextAlphaBits=4 \-dGraphicsAlphaBits=4" .TP .B \-\-output\fI filename Specify the output file (instead of using the second file parameter). Using the filename \fB\-\fR causes epstool to write to standard output, which requires the use of \fB\-\-quiet\fR. .TP .B \-\-mac\-binary When adding a PICT preview, use the MacBinary I format. for the Mac .TP .B \-\-mac\-double When adding a PICT preview, use the AppleDouble format for the Mac. .TP .B \-\-mac\-rsrc When adding a PICT preview, use the Resource format for the Mac. .TP .B \-\-mac\-single When adding a PICT preview, use the AppleSingle format for the Mac. .TP .B \-\-missing\-separations When writing a DCS 2.0 file, epstool will normally fail if a separation is missing. When this option is used, it will remove references to missing separations when writing the file. .TP .B \-\-page\-number\fI page When creating a bitmap with \fB\-\-device\fR from a DCS 2.0 file, \fIpage\fR specifies the separation to be used. Page 1 is the composite and page 2 is the first separation. Use \fB\-\-dcs2\-report\fR to get the list of separations. .TP .B \-\-quiet Try to run without writing to standard output. .TP .B \-\-rename\-separation\fI oldname newname When copying a DCS 2.0 file with \fB\-\-dcs2\-multi\fR or \fB\-\-dcs2\-single\fR, rename separation with \fIoldname\fR to \fInewname\fR. This option implies \fB\-\-missing\-separations\fR. It is assumed that the new name is just an alias for the same colour and that the CMYK or RGB values for the separation are not changed. This option may be used multiple times. This must be used if the input file incorrectly has two separations of the same name. .TP .B \-\-replace\-composite Some DCS 2.0 files do not have an image in the composite page. This option replaces the composite page with a CMYK image derived from the separations. This option must be used with .B \-\-dcs2\-multi or .B \-\-dcs2\-single\fR. See also the options .B \-\-dpi and .B \-\-custom\-colours\fR. .SH MACINTOSH The Macintosh does not use a flat file system. Each file can have a data fork and a resource fork. EPSF files have the PostScript in the data fork, and optionally have a preview in the resource fork as a PICT image. In addition, file type is obtained from the finder info rather than a file extension. File types use a four character code such as "EPSF" or "PICT". When Macintosh files are copied to a foreign file system, the resource fork may be left behind. Alternatives to retain the resource fork are to package the finder data, data fork and resource fork in a single MacBinary or AppleSingle file, or to put the data fork in a flat file and the finder info and resource fork in an AppleDouble file. The Mac OSX finder will handle AppleDouble files automatically when copying files to and from a foreign file system. When copying \fItest.eps\fR to a foreign file system, the data fork would be written as \fItest.eps\fR and the finder info and resource fork to the AppleDouble file \fI._test.eps\fR or \fI.AppleDouble/test.eps\fR. Epstool can read MacBinary and AppleSingle files. It can write MacBinary I, AppleSingle, AppleDouble or Resource files. Files written by epstool will have type \fIEPSF\fR and creator \fIMSWD\fR. When adding a preview to \fItest.eps\fR, it is suggested that you create the MacBinary file \fItest.eps.bin\fR. On a Macintosh computer you then need to extract it with StuffIt Expander. Another alternative is to write the AppleDouble file to \fI._test.eps\fR then copy \fBboth files\fR to a file system accessible to a Mac computer. If the output file name starts with \fI.\fR then AppleDouble will be assumed, otherwise if it ends with \fI.as\fR then AppleSingle will be assumed, otherwise if it ends with \fI.rsrc\fR or \fI/rsrc\fR then Resource will be assumed, otherwise MacBinary will be assumed. When writing a MacBinary file, it is recommended that you end the filename in \fI.bin\fR. To force the file type, use \fB\-\-mac\-single\fR, \fB\-\-mac\-double\fR, \fB\-\-mac\-binary\fR or \fB\-\-mac\-rsrc\fR. On Mac OS X you can access a file's resource fork from command line tools by appending \fI/rsrc\fR to the original file name. The easiest way to add a preview to the file \fItest.eps\fR on Mac OS X is to let epstool write in \fB\-\-mac-rsrc\fR format to \fItest.eps/rsrc\fR (see \fBExamples\fR). .SH DESKTOP COLOR SEPARATIONS (DCS 2.0) The Desktop Color Separation (DCS) image file format contains a low resolution preview, a main file with the full resolution composite image, and colour separations with full resolution separated plates. The separations will typically contain Cyan, Magenta, Yellow, Black and possibly spot colours. There are two versions of DCS 2.0. .TP Multiple File The main file contains \fI%%PlateFile: (name) EPS Local filename\fR comments which give the filenames of the separation plates. The main file may contain a low resolution DOS EPS preview. The separation files do not contain previews. .TP Single File This is an abuse of the EPS specification. The single file contains the main file and the separations concatenated together, which makes the DSC comments incorrect. The main file specifies the byte offsets to the separations using \fI%%PlateFile: (name) EPS #offset size\fR. The single file may then be placed inside a DOS EPS file with a low resolution preview. By default, epstool writes single file DCS 2.0. .P Epstool can add previews to single and multiple file DCS 2.0. It can split single file DCS 2.0 into multiple files and vice versa. This allows a single file DCS 2.0 to be split, the composite image replaced, a new preview created, and then be recombined into a single file. Some DCS 2.0 files do not have an image in the composite page. To determine if the composite page does not contain an image, use \fB\-\-dcs2\-report\fR and look to see if the composite section is very short. Using \fB\-\-dcs2\-single \-\-replace\-composite\fR replaces the composite page with the headers of the original composite page and a body containing a CMYK image derived from the separations. Set the resolution of the CMYK image using \fB\-\-dpi\fR. When replacing the composite page with a CMYK image using \fB\-\-replace\-composite\fR, the \fB\-\-custom\-colours\fR option is useful for dealing with DCS 2.0 files that have incorrect CMYK colours, for example specifying that the varnish layer is grey. Each line of the CMYK colours file is formatted like a DSC \fI%%CMYKCustomColor:\fR or \fI%%RGBCustomColor:\fR line, as shown in the example below. .P %%CMYKCustomColor: 0.00 0.00 0.00 0.00 Varnish .P %%CMYKCustomColor: 1.00 0.68 0.00 0.12 (Dark Blue) .P %%RGBCustomColor: 0.5 0.0 0.0 (Dark Red) DCS2 files should not have two separations with the same name. Epstool will not allow a DCS2 output file to have duplicate separation names. Use \fB\-\-rename\-separation\fR to resolve this. .SH EXAMPLES .TP Add colour preview (24bit/pixel) to EPS file epstool \-t6p tiger.eps output.eps .TP Add TIFF (G3 Fax) preview to tiger.eps. epstool \-\-add\-tiff\-preview \-\-device tiffg3 tiger.eps output.eps .P Any GS TIFF device can be used, e.g. tiffg4, tiffpack .TP Extract TIFF preview from tiger.eps epstool \-v tiger.eps tiger.tif .TP Fix incorrect %%BoundingBox then add TIFF4 preview. epstool \-\-bbox \-t4 golfer.eps output.eps .TP Adjust the BoundingBox of an existing EPS file, but don't add a preview: epstool \-\-copy \-\-bbox input.eps output.eps .TP Add user supplied Windows Metafile to EPS file. epstool \-\-add\-user\-preview logo.wmf logo.eps output.eps .P Typically used when an application can export EPS and WMF separately but can't export EPS with WMF preview. .TP Add a PICT preview and write an AppleDouble file. epstool \-\-add\-pict\-preview \-\-mac\-double tiger.eps ._tiger.eps .P To be used by a Mac, both \fItiger.eps\fR and \fI._tiger.eps\fR need to be on a foreign file system accessible to the Mac. .TP Add a PICT preview, overwriting the existing resources. epstool \-\-add\-pict\-preview \-\-mac\-rsrc tiger.eps tiger.eps/rsrc .P On Mac OS X you can access a file's resource fork from command line tools by appending "/rsrc" to the file's original name. .SH NOTES When adding a WMF preview to an EPS file using \fB\-add\-user\-preview filename\fP, the placeable metafile header is removed from the metafile as it is put into the EPS file. When extracting a WMF preview from an EPS file, a placeable metafile header is created from the EPS BoundingBox information. This placeable metafile header assumes that the WMF has its origin at (0,0), which might not be correct. When epstool is creating a TIFF or WMF preview, it will convert palette colour images into 24\-bit/pixel. The environment variable TEMP should point to a writeable directory for temporary files. If not defined, /tmp will be used for Unix and the current directory will be used for other platforms. .SH AUTHOR .B epstool was written by Russell Lang .PP This man page was contributed by Martin Pitt for the Debian GNU/Linux system (but may be used by others). epstool-3.08/doc/cygwin.README0000664000076400007640000000124410252260054015464 0ustar rjlrjl00000000000000Cygwin Release: 3.08-1 Cygwin package maintainer: James R. Phillips email: antiskid56_cygwin@yahoo.com To create the binary and source distributions from packaged source: ==== tar -xjf epstool-3.08-1-src.tar.bz2 cd epstool-3.08-1 make cygwin ==== Source archive, binary archive and setup.hint will now appear in ./dist To create the binary and source distributions from upstream source: ==== tar -xzf epstool-3.08.tar.gz cd epstool-3.08 make cygwin ==== Source archive, binary archive and setup.hint will now appear in ./dist To recreate the upstream source distribution from packaged source: ===== tar -xjf epstool-3.08-1-src.tar.bz2 cd epstool-3.08-1 make epstar ====== epstool-3.08/doc/cygwin.hint0000664000076400007640000000070110252260054015466 0ustar rjlrjl00000000000000# cygwin setup.hint from epstool distribution category: Graphics requires: cygwin sdesc:"Edit preview images and fix bounding boxes in EPS files." ldesc:"Edit preview images and fix bounding boxes in EPS files. Encapsulated PostScript (EPS) files may contain a preview to be used by programs that can't interpret the PostScript code. epstool can create and extract such previews. epstool can also calculate an optimal bounding box for an EPS file." epstool-3.08/doc/epstool.htm0000644000076400007640000007754710252260054015525 0ustar rjlrjl00000000000000 epstool

epstool

EPSTOOL - Create or extract preview images in EPS files.
Release date: 2005-06-10

Table of contents

Overview

Epstool is a utility to create or extract preview images in EPS files.

Features:

  • Add Interchange (EPSI), DOS EPS or PICT preview.
  • Extract PostScript or preview from DOS EPS or Macintosh EPSF files.
  • Create preview using ghostscript.
  • Automatically calculate bounding box using ghostscript and update in EPS file.
  • Handle DCS 2.0.
  • Works under Windows 32 and 64-bit, Unix and OS/2.

Usage: epstool command [options] input_filename output_filename

Commands (one only):

  --add-tiff6p-preview       or  -t6p
  --add-tiff6u-preview       or  -t6u
  --add-tiff4-preview        or  -t4
  --add-tiff-preview         or  -tg
  --add-interchange-preview  or  -i
  --add-metafile-preview     or  -w
  --add-pict-preview
  --add-user-preview filename
  --dcs2-multi
  --dcs2-single
  --dcs2-report
  --extract-postscript       or  -p
  --extract-preview          or  -v
  --bitmap
  --copy
  --dump
  --test-eps
  --help                     or  -h
Options:
  --bbox                     or  -b
  --combine-separations filename
  --combine-tolerance pts
  --custom-colours filename
  --debug                    or  -d
  --device name
  --doseps-reverse
  --dpi resolution
  --dpi-render resolution
  --ignore-information
  --ignore-warnings
  --ignore-errors
  --gs command
  --gs-args arguments
  --mac-binary
  --mac-double
  --mac-rsrc
  --mac-single
  --missing-separations
  --page-number page
  --quiet
  --rename-separation oldname  newname
  --replace-composite

Encapsulated PostScript Format (EPS)

EPS is a specialised form of a PostScript file that complies with the Document Structuring Conventions (DSC) and is intended to be embedded inside another PostScript file. An EPS file must contain a special first line that identifies it as an EPS file (e.g. %!PS-Adobe-3.0 EPSF-3.0) and it must contain a %%BoundingBox: line. The EPS file only draws within the rectangle defined by the bounding box. The PostScript code must avoid using PostScript operators that would interfere with the embedding. These include operators with global effects such as changing the page size and changing the half tone screen.

Previews

EPS files may contain a preview to be used by programs that can't interpret the PostScript code. There are three ways to add a preview to an EPS file.
Interchange
This preview is included within PostScript comments in a section marked %%BeginPreview: / %%EndPreview. The actual image data is stored in hexadecimal format. This format is most commonly used on Unix.
DOS EPS
The preview is a TIFF or Windows Metafile. A DOS EPS file has a 30 byte binary header which gives offsets and lengths for the PostScript, TIFF and Windows Metafile sections. You can't send a DOS EPS file directly to a printer - you have to remove the binary header and preview first. This format is most commonly used on MS-Windows.
PICT
The preview is in PICT format stored in the resource fork of the file. This format is most commonly used on the Macinstosh. Epstool provides limited support for this format.

Commands

One of the following commands must be specified. Trying to use more than one command isn't helpful.

--add-tiff6p-preview or -t6p
Add a TIFF 6 preview compressed with packbits (simple run length encoding). The preview will normally be full colour, but you can make it greyscale by adding the option --device bmpgray or --device pgmraw, or monochrome using --device bmpmono or --device pbmraw.
--add-tiff6u-preview or -t6u
Add a TIFF 6 uncompressed preview. See --add-tiff6p-preview for how to add a greyscale or monochrome preview.
--add-tiff4-preview or -t4
Add a TIFF 4 preview. The preview is monochrome and is intended for use with old programs that won't read TIFF6, such as Word Perfect 5.1 for DOS.
--add-tiff-preview or -tg
Add a TIFF preview using ghostscript to generate the TIFF file. You must specify a suitable TIFF device using --device. If you want a compressed monochrome image, you might use --device tiffg3.
--add-interchange-preview or -i
Add a monochrome interchange preview
--add-metafile-preview or -w
Add a Windows Metafile (WMF) preview. The metafile will contain a bitmap, not vector information. The preview will normally be full colour. See --add-tiff6p-preview for how to add a greyscale or monochrome preview.
--add-pict-preview
Add a Mac PICT preview. EPSF files with PICT previews can generally be used only on Mac computers. The preview will be full colour. The AppleSingle and MacBinary formats will contain the EPSF and the preview. The AppleDouble or Resource format will contain the preview only and needs to accompany the original EPSF file. To specify the file format use --mac-single, --mac-double, --mac-binary or --mac-rsrc.
--add-user-preview filename
Add a user supplied image as a preview. The image can be a Windows bitmap, a PBMPLUS file, a TIFF image or a Windows Metafile. Window bitmaps and PBMPLUS files will be converted to TIFF6 compressed with packbits. TIFF and Windows Metafile images will be added unchanged.
--bitmap
Create a bitmap of the area within the EPS bounding box. The bitmap type must be specified with --device. If processing a DCS 2.0 file, the separation can be specified with --page-number.
--copy
Copy the EPS file. This is generally used with the --bbox option to update the bounding box.
--dcs2-multi
Convert DCS 2.0 separations to multiple files. See DCS 2.0. If the output name is out.eps, then the separations would be named out.eps.Cyan etc.
--dcs2-single
Convert DCS 2.0 separations to a single file. See DCS 2.0.
--dcs2-report
Write the file type, preview type, bounding boxes, separation names, lengths and CMYK values to standard output. This can be used to identify if a DCS 2.0 file is missing the composite page or preview.
--dump
Display some information about the file type and DSC comments.
--extract-postscript or -p
Extract the PostScript section from a DOS EPS or MacBinary/AppleSingle file.
--extract-preview or -v
Extract the preview section from a DOS EPS or MacBinary/AppleSingle file.
--help or -h
Display a summary of the epstool commands and options.
--test-eps
Partially test if a file complies with the EPSF specification.

Options

--bbox or -b
Calculate the bounding box using the ghostscript bbox device and update in the EPS file.
--combine-separations filename
Combine the separations of the input DCS 2.0 file with those of this file. It is an error if the bounding boxes do not match or they contain separations with the same name. This option must be used with --dcs2-multi or --dcs2-single. The composite page may later need to be updated with --replace-composite.
--combine-tolerance pts
When using --combine-separations, allow the bounding boxes to vary by up to pts points. The default is 0 so the bounding boxes must match exactly.
--custom-colours filename
When using --replace-composite on a DCS 2.0 file, use the colours specified in this file in preference to those specified in the composite page.
--debug or -d
Be more verbose about progress. Do not remove temporary files.
--doseps-reverse
When writing a DOS EPS file (TIFF or WMF preview), the default is to write the PostScript before the preview. Using --doseps-reverse puts the preview before the PostScript section, which is required by some buggy programs. Either order is correct.
--device name
Specify a ghostscript device to be used when creating the preview or bitmap. For --add-tiff-preview this must be one of the ghostscript tiff devices (e.g. tiffg3, tiff24nc). For any other preview, it must be one of the bmp or pbmplus devices (e.g. bmpgray, bmp16m, pgmraw, ppmraw). For bitmap output (--bitmap) it can be any ghostscript bitmap device.
--dpi resolution
Set the resolution of the preview or bitmap. The default is 72 dpi.
--dpi-render resolution
Render at a higher resolution set by --dpi-render, then down sample to the resolution set by --dpi. This works when adding a preview image or using --replace-composite, but not when using --bitmap. This improves the preview quality when the original contains a pre-rendered image and --dpi-render is set to match the original target printer.
--ignore-information
Ignore information messages from the DSC parser. Use at your own risk. These messages usually indicate that something is wrong with an EPS file, but that most EPS handlers probably won't care. An example is a line with more than 255 characters.
--ignore-warnings
Ignore warnings from the DSC parser. Use at your own risk. These messages are usually about faults in the DSC comments that are recoverable by epstool, but may confuse other EPS handlers. An example is a bounding box that incorrectly uses floating point numbers instead of integer.
--ignore-errors
Ignore errors from the DSC parser. Use at your own risk. You really should fix the EPS file first.
--gs command
Specify the name the ghostscript program. On Unix the default is gs. On Windows, epstool will check the registry for installed versions of ghostscript and use the latest, otherwise it will use gswin32c.exe.
--gs-args arguments
Specify additional Ghostscript arguments. This might be used to select anti-aliasing with "-dTextAlphaBits=4 -dGraphicsAlphaBits=4"
--output filename
Specify the output file (instead of using the second file parameter). Using the filename - causes epstool to write to standard output, which requires the use of --quiet.
--mac-binary
When adding a PICT preview, use the MacBinary I format for the Mac.
--mac-double
When adding a PICT preview, use the AppleDouble format for the Mac.
--mac-rsrc
When adding a PICT preview, use the Resource format for the Mac.
--mac-single
When adding a PICT preview, use the AppleSingle format for the Mac.
--missing-separations
When writing a DCS 2.0 file, epstool will normally fail if a separation is missing. When this option is used, it will remove references to missing separations when writing the file.
--page-number page
When creating a bitmap with --device from a DCS 2.0 file, page specifies the separation to be used. Page 1 is the composite and page 2 is the first separation. Use --dcs2-report to get the list of separations.
--quiet
Try to run without writing to standard output.
--rename-separation oldname newname
When copying a DCS 2.0 file with --dcs2-multi or --dcs2-single, rename separation oldname to newname. This option implies --missing-separations. It is assumed that the new name is just an alias for the same colour and that the CMYK or RGB values for the separation are not changed. This option may be used multiple times. This must be used if the input file has two separations with the same name.
--replace-composite
Some DCS 2.0 files do not have an image in the composite page. This option replaces the composite page with a CMYK image derived from the separations. This option must be used with --dcs2-multi or --dcs2-single. See also the options --dpi and --custom-colours.

Macintosh

The Macintosh does not use a flat file system. Each file can have a data fork and a resource fork. EPSF files have the PostScript in the data fork, and optionally have a preview in the resource fork as a PICT image. In addition, file type is obtained from the finder info rather than a file extension. File types use a four character code such as "EPSF" or "PICT". When Macintosh files are copied to a foreign file system, the resource fork may be left behind. Alternatives to retain the resource fork are to package the finder data, data fork and resource fork in a single MacBinary or AppleSingle file, or to put the data fork in a flat file and the finder info and resource fork in an AppleDouble file. The Mac OSX finder will handle AppleDouble files automatically when copying files to and from a foreign file system. When copying test.eps to a foreign file system, the data fork would be written as test.eps and the finder info and resource fork to the AppleDouble file ._test.eps or .AppleDouble/test.eps.

Epstool can read MacBinary and AppleSingle files. It can write MacBinary I, AppleSingle, AppleDouble or Resource files. Files written by epstool will have type EPSF and creator MSWD. When adding a preview to test.eps, it is suggested that you create the MacBinary file test.eps.bin. On a Macintosh computer you then need to extract it with StuffIt Expander. Another alternative is to write the AppleDouble file to ._test.eps then copy both files to a file system accessible to a Mac computer.

If the output file name starts with . then AppleDouble will be assumed, otherwise if it ends with .as then AppleSingle will be assumed, otherwise if it ends with .rsrc or /rsrc then Resource will be assumed, otherwise MacBinary will be assumed. When writing a MacBinary file, it is recommended that you end the filename in .bin. To force the file type, use --mac-single, --mac-double, --mac-binary or --mac-rsrc.

On Mac OS X you can access a file's resource fork from command line tools by appending /rsrc to the original file name. The easiest way to add a preview to the file test.eps on Mac OS X is to let epstool write in --mac-rsrc format to test.eps/rsrc (see Examples).

Desktop Color Separations (DCS 2.0)

The Desktop Color Separation (DCS) image file format contains a low resolution preview, a main file with the full resolution composite image, and colour separations with full resolution separated plates. The separations will typically contain Cyan, Magenta, Yellow, Black and possibly spot colours. There are two versions of DCS 2.0.

Multiple File
The main file contains %%PlateFile: (name) EPS Local filename comments which give the filenames of the separation plates. The main file may contain a low resolution DOS EPS preview. The separation files do not contain previews.
Single File
This is an abuse of the EPS specification. The single file contains the main file and the separations concatenated together, which makes the DSC comments incorrect. The main file specifies the byte offsets to the separations using %%PlateFile: (name) EPS #offset size. The single file may then be placed inside a DOS EPS file with a low resolution preview. By default, epstool writes single file DCS 2.0.

Epstool can add previews to single and multiple file DCS 2.0. It can split single file DCS 2.0 into multiple files and vice versa. This allows a single file DCS 2.0 to be split, the composite image replaced, a new preview created, and then be recombined into a single file.

Some DCS 2.0 files do not have an image in the composite page. To determine if the composite page does not contain an image, use --dcs2-report and look to see if the composite section is very short. Using --dcs2-single --replace-composite replaces the composite page with the headers of the original composite page and a body containing a CMYK image derived from the separations. Set the resolution of the CMYK image using --dpi.

When replacing the composite page with a CMYK image using --replace-composite, the --custom-colours option is useful for dealing with DCS 2.0 files that have incorrect CMYK colours, for example specifying that the varnish layer is grey. Each line of the CMYK colours file is formatted like a DSC %%CMYKCustomColor: or %%RGBCustomColor: line, as shown in the example below.

%%CMYKCustomColor: 0.00 0.00 0.00 0.00 Varnish 
%%CMYKCustomColor: 1.00 0.68 0.00 0.12 (Dark Blue)
%%RGBCustomColor: 0.5 0.0 0.0 (Dark Red)

DCS2 files should not have two separations with the same name. Epstool will not allow a DCS2 output file to have duplicate separation names. Use --rename-separation to resolve this.

Examples

Add colour preview (24bit/pixel) to EPS file
  epstool -t6p tiger.eps output.eps

Add TIFF (G3 Fax) preview to tiger.eps.
  epstool --add-tiff-preview --device tiffg3 tiger.eps output.eps
Any GS TIFF device can be used, e.g. tiffg4, tiffpack

Extract TIFF preview from tiger.eps
  epstool -v tiger.eps tiger.tif

Fix incorrect %%BoundingBox then add TIFF4 preview.
  epstool --bbox -t4 golfer.eps output.eps

Adjust the BoundingBox of an existing EPS file, but don't add a preview:
  epstool --copy --bbox input.eps output.eps

Add user supplied Windows Metafile to EPS file. Typically used when an application can export EPS and WMF separately but can't export EPS with WMF preview.
  epstool --add-user-preview logo.wmf logo.eps output.eps

Add a PICT preview and write an AppleDouble file.
  epstool --add-pict-preview --mac-double tiger.eps ._tiger.eps
To be used by a Mac, both tiger.eps and ._tiger.eps need to be on a foreign file system accessible to the Mac.

On Mac OS X you can access a file's resource fork from command line tools by appending "/rsrc" to the file's original name. Add a PICT preview, overwriting the existing resources.
  epstool --add-pict-preview --mac-rsrc tiger.eps tiger.eps/rsrc

Notes

When adding a WMF preview to an EPS file using -add-user-preview filename, the placeable metafile header is removed from the metafile as it is put into the EPS file. When extracting a WMF preview from an EPS file, a placeable metafile header is created from the EPS BoundingBox information. This placeable metafile header assumes that the WMF has its origin at (0,0), which might not be correct.

When epstool is creating a TIFF or WMF preview, it will convert palette colour images into 24-bit/pixel.

The environment variable TEMP should point to a writeable directory for temporary files. If not defined, /tmp will be used for Unix and the current directory will be used for other platforms.

Copyright

Copyright (C) 1995-2005 Ghostgum Software Pty Ltd. All rights reserved.

This software is provided AS-IS with no warranty, either express or implied.

This software is distributed under licence and may not be copied, modified or distributed except as expressly authorised under the terms of the licence contained in the file LICENCE in this distribution.

For more information about licensing, please refer to http://www.ghostgum.com.au/ or contact Ghostsgum Software Pty Ltd, 218 Gallaghers Rd, Glen Waverley VIC 3150, AUSTRALIA, Fax +61 3 9886 6616.

Author: Russell Lang, Ghostgum Software Pty Ltd
Internet: gsview at ghostgum.com.au

Compiling

To compile epstool on Unix, use
  make -f src/epstool.mak
To build an RPM
  rpmbuild -ta epstool-N.NN.tar.gz

To compile epstool on MS-Windows, use
  nmake -f srcwin/epstool.mak VCVER=71

Other tools

Other tools that can add previews to EPS files are

  • GSview (slightly older code than epstool)
  • ps2epsi, which is part of Ghostscript. This only adds Interchange previews.
  • ps2epsplus for creating Mac EPS files on a Mac.
  • ps2epsmac for creating Mac EPS files under Unix.

Revision History

3.08 2005-06-10

Fix Unix-like makefiles to work with non-GNU make.
Install CSS file gsview.css.
Added --ignore-information to ignore DSC parser information messages.
Fixed handling of --ignore-warnings and --ignore-errors so that these are now required to process files with warnings or errors.
Added makefile support for cygwin packages.
Added --test-eps making a partial test of EPS compliance.
Added --dump for displaying summary of DSC information.
Builds as Win64 for AMD64, using either Microsoft Visual Studio .NET 2003 with Windows Server 2003 DDK, or with Microsoft Visual Studio .NET 2005 beta.
Builds under OS/2 with gcc/emx.

3.07 2005-01-07

Fix portability issue for Unix-like systems without shared libraries.
Interchange preview was restricted to 1bit/pixel. Add 8bit/pixel grey which isn't commonly used.
Explicitly set the page size when calculating the bounding box, to avoid getting erroneous results when the user changes the default page size with -sPAPERSIZE=a4 or by modifying gs_init.ps to change the default page size on startup. This was a problem with some badly configured Linux distributions.

3.06 2004-11-28

Fix interchange previews which were inverted.
Fix --bitmap for EPS file without a page, which was broken when --page-number was added.
Identify DCS 1.0 as itself, not DCS 2.0.
More portable on Unix-like systems.

3.05 2004-04-22

Write duplicate DCS2 separations to unique files with --dcs2-multi.
When renaming a DCS2 separation, only rename the first occurence of the name, to allow files with duplicate separation names to be fixed.
Do not allow duplicate separations in an output file. This must be resolved with --rename-separations
Added --page-number to allow bitmaps of separations to be created.
Fix bitmap output to stdout with "--bitmap --output -".
Prevent crash when given a PDF file.
Put --gs-args near the end of the GS command line, to allow PostScript commands to be embedded.

3.04 2004-01-17

Fix bug that caused a crash with -t6p on non-Windows systems.
Allow output to stdout with filename "-".
Remove blank lines from interchange preview.
Rearrange files in the epstool distribution so that it compiles with a simple 'make' on Linux.

3.03 2003-10-18

Added Macintosh AppleDouble, AppleSingle, MacBinary and Resource formats, and the ability to add/remove PICT previews.
Added --combine-separations and --combine-tolerance. Allow spaces to occur in unquoted DCS1 separation file names.

3.02 2003-05-06

Added man page and some build updates for Debian.

3.01 2003-02-28

Added --doseps-reverse.
Added --rename-separation.
Added bounding box to --dcs2-report output.

3.0 2002-09-17

Major rewrite.
Command line changes.
Use ghostscript bbox device for calculating bounding box.
Supports multiple file DCS 2.0.
Add preview to single file DCS 2.0.
Replace composite page of DCS 2.0 with an image derived from the separations.
Down sample images to provide anti-aliasing.
Removed option to extract a page from a multipage file. The input file must now be EPS.

2.2 2002-04-30

Release with GSview 4.3.
Fixed bug in extracting a page.
Handle single file DCS 2.0.
Added '-k' to create a bitmap of the EPS.

2.1 2002-02-07

Release with GSview 4.2.

2.0 2001-11-23

Release with GSview 4.1.
Remove %%BoundingBox from trailer when adding it to header.

1.92 2001-10-20

Release with GSview 4.05 beta.
Added -aargs to separate arguments from -g. This is needed because program name is surrounded by quotes and so some shells were treating the arguments as part of the program name.

1.91 2001-10-06

Release with GSview 4.03 beta.

1.9 2001-07-27

Release with GSview 4.01 beta.
Ignore DSC warnings with -e1, ignore DSC errors with -e2.

1.8 2001-06-02

Release with GSview 4.0.

1.7 2001-03-30

Allow DSC warnings to be ignored with -e.

1.6 2000-12-28

Release with GSview 3.6.
Write correct page ordinal when extracting a page.
Correctly handle DOS EPS files again.

1.5 2000-12-16

Release with GSview 3.5.

1.32 2000-11-06

Updated DSC parser.
Release with GSview 3.41 beta.

1.4 2000-06-30

Fixed handling of files without trailers.

1.3 2000-06-25

Put quotes around Ghostscript EXE name for Windows, OS/2 and Unix. Released with GSview 3.1.

1.21 2000-06-15

Minor fixes for Linux build.

1.2 2000-06-15

Release with GSview 3.0.

1.10 2000-04-01

Fixes to DSC parser.

1.09 2000-03-11

New DSC parser.
Added #pragma pack(1) needed by MSVC++.
Modified BMP reading so it works even if byte packing not used.
, BMP reading might now work with big-endian architectures, so might be able to use BMP devices on Unix (if compiled into Ghostscript). (Untested).

1.08 2000-02-15

Fixed incorrect switch statement in psfile_extract_header()
Fixed -b -c to change the first line to EPS.
Added -sWIDTHxHEIGHT for use with -b -c and large page sizes.

1.07 1998-12-23

Cope with badly written EPS files that leave items on the stack or dictionary stack.

1.06 1998-09-13

Page calculation for descending page order was wrong.
If a multipage non-EPS file was used as input, the output didn't contain the correct single page (or copied garbage).
Added macro for SUNOS4 to use bcopy instead of memmove.

1.05 1997-12-09

When calculating the bounding box from a bitmap, round the area outwards by 0.5 pixels.

1.04 1997-11-29

Released with GSview 2.4

1.03 1997-09-22

TIFF4 preview didn't work from 24bit/pixel source bitmap.
TIFF 6 packbits didn't compress properly for some data (and consquently caused heap corruption).
Fixed TIFF 6 output when using palette (4 or 8 bit/pixel).

1.02 1997-02-15

Removed requirement for EPS file to use showpage.
Added -c to allow correction of %%BoundingBox
When calculating %%BoundingBox, render to a page of letter width and A4 height.
Avoid integer overflow on 16bit machines when calculating width and height.
If TEMP undefined, default to /tmp on Unix.

1.01 1996-11-07

Release separate from GSview. No code changes.
Includes Win32 (epstool.exe) and OS/2 (epstool2.exe) EXEs.

1.0 1996-10-13

Not a beta version. Included with GSview 2.1.

0.81 beta 1996-09-12

Added TIFF packbits compression.
Added -zdevice.
-t5 replaced by -t6u, -t6p.
-wdevice replaced by -w -zdevice
-ttiff3 replaced by -tg -ztiffg3

0.8 beta 1996-09-09

Makefile target for Win32.
Add WMF for all platforms.
Removed restriction that structures must be byte aligned under Unix.
Must still be byte aligned under DOS and OS/2.

0.7 alpha 1995-10-20

Fixed a few error messages.
Use @file to reduce Ghostscript command line length under MS-DOS and OS/2.
Added -q option to GSview and -dQUIET option to Ghostscript command line to allow EPS files to be written to stdout.

0.6 alpha 1995-10-12

Delete temporary bmp file.
Add user supplied preview to a DOS EPS file (which already had a preview) was wrong.

0.5 alpha 1995-09-27

Put stdout into binary mode.
Write placeable WMF header correctly on 32bit and big-endian machines.

0.4 alpha 1995-09-15

Remove placeable WMF header when adding to EPS file, add placeable
WMF header when extracting from EPS file.

0.3 alpha 1995-09-14

First release separate from GSview.

End of epstool documentation

epstool-3.08/makefile0000644000076400007640000000575310252260054014247 0ustar rjlrjl00000000000000# Copyright (C) 2002-2005 Ghostgum Software Pty Ltd. All rights reserved. # # This software is provided AS-IS with no warranty, either express or # implied. # # This software is distributed under licence and may not be copied, # modified or distributed except as expressly authorised under the terms # of the licence contained in the file LICENCE in this distribution. # # For more information about licensing, please refer to # http://www.ghostgum.com.au/ or contact Ghostsgum Software Pty Ltd, # 218 Gallaghers Rd, Glen Waverley VIC 3150, AUSTRALIA, # Fax +61 3 9886 6616. # # $Id: epstool.mak,v 1.9 2005/03/25 03:37:59 ghostgum Exp $ # Make epstool for GNU/Linux BINDIR=./bin OBJDIR=./epsobj SRCDIR=./src SRCWINDIR=./srcwin XINCLUDE= PFLAGS= PLINK= GTKCFLAGS= GTKLIBS= LIBPNGINC= LIBPNGCFLAGS= LIBPNGLIBS= LONGFILEDEF= LONGFILEMOD=cfile include $(SRCDIR)/unixcom.mak EPSOBJPLAT=$(OD)xnodll$(OBJ) $(OD)$(LONGFILEMOD)$(OBJ) EPSLIB=$(LIBPNGLIBS) BEGIN=$(OD)lib.rsp TARGET=epstool include $(SRCDIR)/common.mak EPSTOOL_ROOT=/usr/local EPSTOOL_BASE=$(prefix)$(EPSTOOL_ROOT) EPSTOOL_DOCDIR=$(EPSTOOL_BASE)/share/doc/epstool-$(EPSTOOL_VERSION) EPSTOOL_MANDIR=$(EPSTOOL_BASE)/man EPSTOOL_BINDIR=$(EPSTOOL_BASE)/bin epstool: $(BD)epstool$(EXE) epstest: epstool $(BD)epstest$(EXE) $(BD)epstest$(EXE) $(OD)lib.rsp: makefile -mkdir $(BINDIR) -mkdir $(OBJDIR) echo "dummy" > $(OD)lib.rsp install: $(TARGET) -mkdir -p $(EPSTOOL_BASE) chmod a+rx $(EPSTOOL_BASE) -mkdir -p $(EPSTOOL_BINDIR) chmod a+rx $(EPSTOOL_BINDIR) $(INSTALL_EXE) $(BD)epstool$(EXE) $(EPSTOOL_BINDIR)$(DD)epstool$(EXE) -strip $(EPSTOOL_BINDIR)$(DD)epstool$(EXE) -mkdir -p $(EPSTOOL_MANDIR) chmod a+rx $(EPSTOOL_MANDIR) -mkdir -p $(EPSTOOL_MANDIR)$(DD)man1 chmod a+rx $(EPSTOOL_MANDIR)$(DD)man1 $(INSTALL) doc$(DD)epstool.1 $(EPSTOOL_MANDIR)$(DD)man1$(DD)epstool.1 -mkdir -p $(EPSTOOL_DOCDIR) chmod a+rx $(EPSTOOL_DOCDIR) $(INSTALL) doc$(DD)epstool.htm $(EPSTOOL_DOCDIR)$(DD)epstool.htm $(INSTALL) doc$(DD)gsview.css $(EPSTOOL_DOCDIR)$(DD)gsview.css $(INSTALL) LICENCE $(EPSTOOL_DOCDIR)$(DD)LICENCE CYGWIN_DISTDIR=./dist CYGWIN_PACKAGE=epstool-$(EPSTOOL_VERSION)-1 CYGWIN_DOCDIR=$(CYGWIN_DISTDIR)/usr/share/doc/Cygwin cygwin: rm -rf $(CYGWIN_DISTDIR)/* $(MAKE) -f src/epstool.mak prefix=$(CYGWIN_DISTDIR) EXE=.exe EPSTOOL_ROOT=/usr EPSTOOL_MANDIR=$(CYGWIN_DISTDIR)/usr/share/man install -mkdir -p $(CYGWIN_DOCDIR) chmod a+rx $(CYGWIN_DOCDIR) $(INSTALL) doc/cygwin.README $(CYGWIN_DOCDIR)$(DD)epstool-$(EPSTOOL_VERSION).README (cd $(CYGWIN_DISTDIR); tar -cjf ../$(CYGWIN_PACKAGE).tar.bz2 *) rm -rf $(CYGWIN_DISTDIR)/* mv $(CYGWIN_PACKAGE).tar.bz2 $(CYGWIN_DISTDIR) cp doc/cygwin.hint $(CYGWIN_DISTDIR)/setup.hint make -f src/epstool.mak EXE=.exe EPSDIST=$(CYGWIN_PACKAGE) $(EPSTAR) mv $(EPSTAR) $(CYGWIN_DISTDIR)/$(CYGWIN_PACKAGE)-src.tar bzip2 $(CYGWIN_DISTDIR)/$(CYGWIN_PACKAGE)-src.tar clean: -$(RM) $(EPSOBJS) -$(RM) $(EPSTESTOBJS) -$(RM) $(OD)lib.rsp -$(RM) $(BD)epstool$(EXE) -$(RM) $(BD)epstest$(EXE) -rmdir $(OBJDIR) epstool-3.08/LICENCE0000664000076400007640000004313310252260054013530 0ustar rjlrjl00000000000000 GNU GENERAL PUBLIC LICENSE Version 2, June 1991 Copyright (C) 1989, 1991 Free Software Foundation, Inc. 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This General Public License applies to most of the Free Software Foundation's software and to any other program whose authors commit to using it. (Some other Free Software Foundation software is covered by the GNU Library General Public License instead.) You can apply it to your programs, too. When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs; and that you know you can do these things. To protect your rights, we need to make restrictions that forbid anyone to deny you these rights or to ask you to surrender the rights. These restrictions translate to certain responsibilities for you if you distribute copies of the software, or if you modify it. For example, if you distribute copies of such a program, whether gratis or for a fee, you must give the recipients all the rights that you have. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights. We protect your rights with two steps: (1) copyright the software, and (2) offer you this license which gives you legal permission to copy, distribute and/or modify the software. Also, for each author's protection and ours, we want to make certain that everyone understands that there is no warranty for this free software. If the software is modified by someone else and passed on, we want its recipients to know that what they have is not the original, so that any problems introduced by others will not reflect on the original authors' reputations. Finally, any free program is threatened constantly by software patents. We wish to avoid the danger that redistributors of a free program will individually obtain patent licenses, in effect making the program proprietary. To prevent this, we have made it clear that any patent must be licensed for everyone's free use or not licensed at all. The precise terms and conditions for copying, distribution and modification follow. GNU GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License applies to any program or other work which contains a notice placed by the copyright holder saying it may be distributed under the terms of this General Public License. The "Program", below, refers to any such program or work, and a "work based on the Program" means either the Program or any derivative work under copyright law: that is to say, a work containing the Program or a portion of it, either verbatim or with modifications and/or translated into another language. (Hereinafter, translation is included without limitation in the term "modification".) Each licensee is addressed as "you". Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running the Program is not restricted, and the output from the Program is covered only if its contents constitute a work based on the Program (independent of having been made by running the Program). Whether that is true depends on what the Program does. 1. You may copy and distribute verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and give any other recipients of the Program a copy of this License along with the Program. You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. 2. You may modify your copy or copies of the Program or any portion of it, thus forming a work based on the Program, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: a) You must cause the modified files to carry prominent notices stating that you changed the files and the date of any change. b) You must cause any work that you distribute or publish, that in whole or in part contains or is derived from the Program or any part thereof, to be licensed as a whole at no charge to all third parties under the terms of this License. c) If the modified program normally reads commands interactively when run, you must cause it, when started running for such interactive use in the most ordinary way, to print or display an announcement including an appropriate copyright notice and a notice that there is no warranty (or else, saying that you provide a warranty) and that users may redistribute the program under these conditions, and telling the user how to view a copy of this License. (Exception: if the Program itself is interactive but does not normally print such an announcement, your work based on the Program is not required to print an announcement.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Program, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Program, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Program. In addition, mere aggregation of another work not based on the Program with the Program (or with a work based on the Program) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may copy and distribute the Program (or a work based on it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you also do one of the following: a) Accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, b) Accompany it with a written offer, valid for at least three years, to give any third party, for a charge no more than your cost of physically performing source distribution, a complete machine-readable copy of the corresponding source code, to be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, c) Accompany it with the information you received as to the offer to distribute corresponding source code. (This alternative is allowed only for noncommercial distribution and only if you received the program in object code or executable form with such an offer, in accord with Subsection b above.) The source code for a work means the preferred form of the work for making modifications to it. For an executable work, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the executable. However, as a special exception, the source code distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. If distribution of executable or object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place counts as distribution of the source code, even though third parties are not compelled to copy the source along with the object code. 4. You may not copy, modify, sublicense, or distribute the Program except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense or distribute the Program is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. 5. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Program or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Program (or any work based on the Program), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Program or works based on it. 6. Each time you redistribute the Program (or any work based on the Program), the recipient automatically receives a license from the original licensor to copy, distribute or modify the Program subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties to this License. 7. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Program at all. For example, if a patent license would not permit royalty-free redistribution of the Program by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Program. If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply and the section as a whole is intended to apply in other circumstances. It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system, which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. 8. If the distribution and/or use of the Program is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Program under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. 9. The Free Software Foundation may publish revised and/or new versions of the General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Program specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of this License, you may choose any version ever published by the Free Software Foundation. 10. If you wish to incorporate parts of the Program into other free programs whose distribution conditions are different, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. NO WARRANTY 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS How to Apply These Terms to Your New Programs If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms. To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Also add information on how to contact you by electronic and paper mail. If the program is interactive, make it output a short notice like this when it starts in an interactive mode: Gnomovision version 69, Copyright (C) year name of author Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. This is free software, and you are welcome to redistribute it under certain conditions; type `show c' for details. The hypothetical commands `show w' and `show c' should show the appropriate parts of the General Public License. Of course, the commands you use may be called something other than `show w' and `show c'; they could even be mouse-clicks or menu items--whatever suits your program. You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the program, if necessary. Here is a sample; alter the names: Yoyodyne, Inc., hereby disclaims all copyright interest in the program `Gnomovision' (which makes passes at compilers) written by James Hacker. , 1 April 1989 Ty Coon, President of Vice This General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Library General Public License instead of this License. epstool-3.08/srcwin/0000775000076400007640000000000010252260054014044 5ustar rjlrjl00000000000000epstool-3.08/srcwin/wdll.c0000644000076400007640000001102210252260054015144 0ustar rjlrjl00000000000000/* Copyright (C) 2001-2005 Ghostgum Software Pty Ltd. All rights reserved. This software is provided AS-IS with no warranty, either express or implied. This software is distributed under licence and may not be copied, modified or distributed except as expressly authorised under the terms of the licence contained in the file LICENCE in this distribution. For more information about licensing, please refer to http://www.ghostgum.com.au/ or contact Ghostsgum Software Pty Ltd, 218 Gallaghers Rd, Glen Waverley VIC 3150, AUSTRALIA, Fax +61 3 9886 6616. */ /* $Id: wdll.c,v 1.1.2.6 2005/06/10 09:39:24 ghostgum Exp $ */ #include #include #include "cplat.h" #include "cdll.h" /******************************************************************/ static int dll_msg(TCHAR *msg, LPCTSTR str, int msglen) { int len = (int)cslen(str); if (len < msglen){ csncat(msg, str, len); msglen -= len; } return msglen; } #ifndef ERROR_DLL_NOT_FOUND #define ERROR_DLL_NOT_FOUND 1157L #endif /* display error message for LoadLibrary */ static int load_library_error(LPCTSTR dllname, TCHAR *msg, int msglen) { LPCTSTR text_reason; TCHAR buf[MAX_PATH+128]; int reason; LPVOID lpMessageBuffer; reason = GetLastError() & 0xffff; switch (reason) { case ERROR_FILE_NOT_FOUND: /* 2 */ text_reason = TEXT("File not found"); break; case ERROR_PATH_NOT_FOUND: /* 3 */ text_reason = TEXT("Path not found"); break; case ERROR_NOT_ENOUGH_MEMORY: /* 8 */ text_reason = TEXT("Not enough memory"); break; case ERROR_BAD_FORMAT: /* 11 */ text_reason = TEXT("Bad EXE or DLL format"); break; case ERROR_OUTOFMEMORY: /* 14 */ text_reason = TEXT("Out of memory"); break; case ERROR_DLL_NOT_FOUND: /* 1157 */ text_reason = TEXT("DLL not found"); break; default: text_reason = (TCHAR *)NULL; } if (text_reason) csnprintf(buf, sizeof(buf)/sizeof(TCHAR), TEXT("Failed to load %s, error %d = %s\n"), dllname, reason, text_reason); else csnprintf(buf, sizeof(buf)/sizeof(TCHAR), TEXT("Failed to load %s, error %d\n"), dllname, reason); msglen = dll_msg(msg, buf, msglen); FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM, NULL, reason, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), /* user default language */ (LPTSTR) &lpMessageBuffer, 0, NULL); if (lpMessageBuffer) { msglen = dll_msg(msg, (LPTSTR)lpMessageBuffer, msglen); msglen = dll_msg(msg, TEXT("\r\n"), msglen); LocalFree(LocalHandle(lpMessageBuffer)); } return msglen; } /* Load DLL. Write log of actions in msg */ int dll_open(GGMODULE *hmodule, LPCTSTR name, TCHAR *msg, int msglen) { LPCTSTR shortname; TCHAR fullname[MAX_PATH]; TCHAR *p; HINSTANCE hInstance = GetModuleHandle(NULL); memset(msg, 0, msglen); msglen = dll_msg(msg, TEXT("Trying to load "), msglen); msglen = dll_msg(msg, name, msglen); msglen = dll_msg(msg, TEXT("\n"), msglen); /* Try to load DLL first with given path */ *hmodule = LoadLibrary(name); if (*hmodule == (GGMODULE)NULL) { /* failed */ msglen = load_library_error(name, msg, msglen); /* try again, with path of EXE */ if ((shortname = csrchr(name, '\\')) == (TCHAR *)NULL) shortname = name; else shortname++; GetModuleFileName(hInstance, fullname, sizeof(fullname)); if ((p = csrchr(fullname,'\\')) != (TCHAR *)NULL) p++; else p = fullname; *p = '\0'; csncat(fullname, shortname, sizeof(fullname)-cslen(fullname)-1); msglen = dll_msg(msg, TEXT("Trying to load "), msglen); msglen = dll_msg(msg, fullname, msglen); msglen = dll_msg(msg, TEXT("\n"), msglen); *hmodule = LoadLibrary(fullname); if (*hmodule == (GGMODULE)NULL) { /* failed again */ msglen = load_library_error(fullname, msg, msglen); /* try once more, this time on system search path */ msglen = dll_msg(msg, TEXT("Trying to load "), msglen); msglen = dll_msg(msg, shortname, msglen); msglen = dll_msg(msg, TEXT("\n"), msglen); *hmodule = LoadLibrary(shortname); if (*hmodule == (GGMODULE)NULL) { /* failed again */ msglen = load_library_error(shortname, msg, msglen); } } } if (*hmodule == (GGMODULE)NULL) { *hmodule = (GGMODULE)NULL; return -1; } return 0; } int dll_close(GGMODULE *hmodule) { FreeLibrary(*hmodule); return 0; } dll_proc dll_sym(GGMODULE *hmodule, const char *name) { return (dll_proc)GetProcAddress(*hmodule, name); } /******************************************************************/ epstool-3.08/srcwin/wfile.c0000644000076400007640000001310410252260054015313 0ustar rjlrjl00000000000000/* Copyright (C) 2000-2005 Ghostgum Software Pty Ltd. All rights reserved. This software is provided AS-IS with no warranty, either express or implied. This software is distributed under licence and may not be copied, modified or distributed except as expressly authorised under the terms of the licence contained in the file LICENCE in this distribution. For more information about licensing, please refer to http://www.ghostgum.com.au/ or contact Ghostsgum Software Pty Ltd, 218 Gallaghers Rd, Glen Waverley VIC 3150, AUSTRALIA, Fax +61 3 9886 6616. */ /* $Id: wfile.c,v 1.1.2.9 2005/06/10 09:39:24 ghostgum Exp $ */ /* GFile is similar but not identical to MFC CFile. */ /* This implementation uses Windows APIs */ #define STRICT #include #include #include "cfile.h" /* These are the private bits */ struct GFile_s { #ifdef MEMORYFILE /* Read from a memory buffer */ const char *m_pBase; long m_nOffset; long m_nLen; #else #ifdef _Windows /* Windows API */ void *m_hFile; int m_error; int m_openflags; #else FILE *m_file; #endif /* !_Windows */ #endif /* !MEMORYFILE */ }; #ifndef ASSERT #ifdef DEBUG static void gfile_assert(const char *file, int len); #define ASSERT(f) if (!(f)) gfile_assert(__FILE__, __LINE__) static void gfile_assert(const char *file, int line) { printf("Assert failed in file %s at line %d\n", file, line); } #else #define ASSERT(f) #endif #endif int gfile_error(GFile *gf) { ASSERT(gf != NULL); ASSERT(gf->m_hFile != INVALID_HANDLE_VALUE); return gf->m_error; } FILE_POS gfile_get_length(GFile *gf) { BY_HANDLE_FILE_INFORMATION fi; ASSERT(gf != NULL); GetFileInformationByHandle((HANDLE)gf->m_hFile, &fi); /* FIX */ return (FILE_POS) (((unsigned __int64 )fi.nFileSizeHigh << 32) + fi.nFileSizeLow); /* return fi.nFileSizeLow; */ } BOOL gfile_get_datetime(GFile *gf, unsigned long *pdt_low, unsigned long *pdt_high) { FILETIME datetime; BOOL flag; ASSERT(gf != NULL); flag = GetFileTime((HANDLE)gf->m_hFile, NULL, NULL, &datetime); *pdt_low = datetime.dwLowDateTime; *pdt_high = datetime.dwHighDateTime; return flag; } BOOL gfile_changed(GFile *gf, FILE_POS length, unsigned long dt_low, unsigned long dt_high) { unsigned long this_dt_low, this_dt_high; FILE_POS this_length = gfile_get_length(gf); gfile_get_datetime(gf, &this_dt_low, &this_dt_high); return ( (this_length != length) || (this_dt_low != dt_low) || (this_dt_high != dt_high)); } GFile *gfile_open_handle(void *hFile, unsigned int nOpenFlags) { GFile *gf = (GFile *)malloc(sizeof(GFile)); if (gf == NULL) { CloseHandle((HANDLE)hFile); return NULL; } memset(gf, 0, sizeof(GFile)); gf->m_hFile = hFile; gf->m_error = 0; gf->m_openflags = nOpenFlags; return gf; } GFile *gfile_open(LPCTSTR lpszFileName, unsigned int nOpenFlags) { GFile *gf; DWORD dwAccess = GENERIC_READ; DWORD dwShareMode = FILE_SHARE_READ | FILE_SHARE_WRITE; DWORD dwCreate = OPEN_EXISTING; HANDLE hFile; ASSERT(nOpenFlags == GENERIC_READ); if ((nOpenFlags & 0xf) == gfile_modeRead) dwAccess = GENERIC_READ; if ((nOpenFlags & 0xf) == gfile_modeWrite) dwAccess = GENERIC_WRITE; if ((nOpenFlags & 0xf0) == gfile_shareDenyWrite) dwShareMode = FILE_SHARE_READ; if ((nOpenFlags & 0xf0) == gfile_shareExclusive) dwShareMode = 0; if ((nOpenFlags & 0xf000) == gfile_modeCreate) dwCreate = CREATE_ALWAYS; if (lpszFileName[0] == '\0') hFile = GetStdHandle(STD_OUTPUT_HANDLE); else hFile = CreateFile(lpszFileName, dwAccess, dwShareMode, NULL, dwCreate, FILE_ATTRIBUTE_NORMAL, NULL); if (hFile == INVALID_HANDLE_VALUE) return NULL; gf = (GFile *)malloc(sizeof(GFile)); if (gf == NULL) { CloseHandle(hFile); return NULL; } memset(gf, 0, sizeof(GFile)); gf->m_hFile = hFile; gf->m_error = 0; gf->m_openflags = nOpenFlags; return gf; } void gfile_close(GFile *gf) { ASSERT(gf != NULL); ASSERT(gf->m_hFile != 0); CloseHandle((HANDLE)gf->m_hFile); gf->m_hFile = 0; gf->m_error = 0; free(gf); } UINT gfile_read(GFile *gf, void *lpBuf, UINT nCount) { DWORD nBytesRead; ASSERT(gf != NULL); ASSERT(gf->m_hFile != 0); if (ReadFile((HANDLE)gf->m_hFile, lpBuf, nCount, &nBytesRead, NULL)) return nBytesRead; else gf->m_error = 1; /* file error */ return 0; } UINT gfile_write(GFile *gf, void *lpBuf, UINT nCount) { DWORD nBytesWritten; ASSERT(gf != NULL); ASSERT(gf->m_hFile != 0); if (WriteFile((HANDLE)gf->m_hFile, lpBuf, nCount, &nBytesWritten, NULL)) return nBytesWritten; else gf->m_error = 1; /* file error */ return 0; } int gfile_seek(GFile *gf, FILE_OFFSET lOff, unsigned int nFrom) { DWORD dwMoveMethod; LONG lHiOff = (LONG)((unsigned __int64)lOff >> 32); ASSERT(gf != NULL); ASSERT(gf->m_hFile != 0); switch(nFrom) { default: case gfile_begin: dwMoveMethod = FILE_BEGIN; break; case gfile_current: dwMoveMethod = FILE_CURRENT; break; case gfile_end: dwMoveMethod = FILE_END; break; } /* return value on error is 0xffffffff */ return (SetFilePointer((HANDLE)gf->m_hFile, (LONG)lOff, &lHiOff, dwMoveMethod) == 0xffffffff); } FILE_POS gfile_get_position(GFile *gf) { LONG lHiOff = 0; LONG lLoOff; ASSERT(gf != NULL); ASSERT(gf->m_hFile != 0); lLoOff = SetFilePointer((HANDLE)gf->m_hFile, 0, &lHiOff, FILE_CURRENT); return (FILE_POS)(((unsigned __int64)lHiOff << 32) + lLoOff); } int gfile_puts(GFile *gf, const char *str) { return gfile_write(gf, str, (int)strlen(str)); } epstool-3.08/srcwin/epstool.mak0000644000076400007640000000134710252260054016226 0ustar rjlrjl00000000000000# Copyright (C) 2002-2004 Ghostgum Software Pty Ltd. All rights reserved. # # This software is provided AS-IS with no warranty, either express or # implied. # # This software is distributed under licence and may not be copied, # modified or distributed except as expressly authorised under the terms # of the licence contained in the file LICENCE in this distribution. # # For more information about licensing, please refer to # http://www.ghostgum.com.au/ or contact Ghostsgum Software Pty Ltd, # 218 Gallaghers Rd, Glen Waverley VIC 3150, AUSTRALIA, # Fax +61 3 9886 6616. # # $Id: epstool.mak,v 1.1.2.1 2004/11/28 01:02:47 ghostgum Exp $ # Make epstool for MS-Windows epstool_all: epstool_make !include "srcwin/windows.mak" epstool-3.08/srcwin/wgsver.c0000664000076400007640000002103710252260054015530 0ustar rjlrjl00000000000000/* Copyright (C) 2001-2003, Ghostgum Software Pty Ltd. All rights reserved. * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation * files (the "Software"), to deal in the Software without * restriction, including without limitation the rights to use, copy, * modify, merge, publish, distribute, sublicense, and/or sell copies * of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be * included in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ /* * This file is part of GSview. The above notice applies only * to this file. It does NOT apply to any other file in GSview * unless that file includes the above copyright notice. */ /* $Id: wgsver.c,v 1.1.2.4 2003/07/14 08:03:09 ghostgum Exp $ */ /* Obtain details of copies of Ghostscript installed under Windows */ /* To compile as a demo program, define DUMP_GSVER */ /* #define DUMP_GSVER */ #include #include #include #include #include "wgsver.h" /* Ghostscript may be known in the Windows Registry by * the following names. */ #define GS_PRODUCT_AFPL "AFPL Ghostscript" #define GS_PRODUCT_ALADDIN "Aladdin Ghostscript" #define GS_PRODUCT_GPL "GPL Ghostscript" #define GS_PRODUCT_GNU "GNU Ghostscript" /* Get Ghostscript versions for given product. * Store results starting at pver + 1 + offset. * Returns total number of versions in pver. */ static int get_gs_versions_product(int *pver, int offset, const char *gs_productfamily) { HKEY hkey; DWORD cbData; HKEY hkeyroot; char key[256]; int ver; char *p; int n = 0; sprintf(key, "Software\\%s", gs_productfamily); hkeyroot = HKEY_LOCAL_MACHINE; if (RegOpenKeyExA(hkeyroot, key, 0, KEY_READ, &hkey) == ERROR_SUCCESS) { /* Now enumerate the keys */ cbData = sizeof(key) / sizeof(char); while (RegEnumKeyA(hkey, n, key, cbData) == ERROR_SUCCESS) { n++; ver = 0; p = key; while (*p && (*p!='.')) { ver = (ver * 10) + (*p - '0')*100; p++; } if (*p == '.') p++; if (*p) { ver += (*p - '0') * 10; p++; } if (*p) ver += (*p - '0'); if (n + offset < pver[0]) pver[n+offset] = ver; } } return n+offset; } /* Query registry to find which versions of Ghostscript are installed. * Return version numbers in an integer array. * On entry, the first element in the array must be the array size * in elements. * If all is well, TRUE is returned. * On exit, the first element is set to the number of Ghostscript * versions installed, and subsequent elements to the version * numbers of Ghostscript. * e.g. on entry {5, 0, 0, 0, 0}, on exit {3, 550, 600, 596, 0} * Returned version numbers may not be sorted. * * If Ghostscript is not installed at all, return FALSE * and set pver[0] to 0. * If the array is not large enough, return FALSE * and set pver[0] to the number of Ghostscript versions installed. */ BOOL get_gs_versions(int *pver) { int n; if (pver == (int *)NULL) return FALSE; n = get_gs_versions_product(pver, 0, GS_PRODUCT_AFPL); n = get_gs_versions_product(pver, n, GS_PRODUCT_ALADDIN); n = get_gs_versions_product(pver, n, GS_PRODUCT_GPL); n = get_gs_versions_product(pver, n, GS_PRODUCT_GNU); if (n >= pver[0]) { pver[0] = n; return FALSE; /* too small */ } if (n == 0) { pver[0] = 0; return FALSE; /* not installed */ } pver[0] = n; return TRUE; } /* * Get a named registry value. * Key = hkeyroot\\key, named value = name. * name, ptr, plen and return values are the same as in gp_getenv(); */ int gp_getenv_registry(HKEY hkeyroot, const char *key, const char *name, char *ptr, int *plen) { HKEY hkey; DWORD cbData, keytype; BYTE b; LONG rc; BYTE *bptr = (BYTE *)ptr; if (RegOpenKeyExA(hkeyroot, key, 0, KEY_READ, &hkey) == ERROR_SUCCESS) { keytype = REG_SZ; cbData = *plen; if (bptr == (BYTE *)NULL) bptr = &b; /* Registry API won't return ERROR_MORE_DATA */ /* if ptr is NULL */ rc = RegQueryValueExA(hkey, (char *)name, 0, &keytype, bptr, &cbData); RegCloseKey(hkey); if (rc == ERROR_SUCCESS) { *plen = cbData; return 0; /* found environment variable and copied it */ } else if (rc == ERROR_MORE_DATA) { /* buffer wasn't large enough */ *plen = cbData; return -1; } } return 1; /* not found */ } static BOOL get_gs_string_product(int gs_revision, const char *name, char *ptr, int len, const char *gs_productfamily) { /* If using Win32, look in the registry for a value with * the given name. The registry value will be under the key * HKEY_CURRENT_USER\Software\AFPL Ghostscript\N.NN * or if that fails under the key * HKEY_LOCAL_MACHINE\Software\AFPL Ghostscript\N.NN * where "AFPL Ghostscript" is actually gs_productfamily * and N.NN is obtained from gs_revision. */ int code; char key[256]; char dotversion[16]; int length; DWORD version = GetVersion(); if (((HIWORD(version) & 0x8000) != 0) && ((HIWORD(version) & 0x4000) == 0)) { /* Win32s */ return FALSE; } sprintf(dotversion, "%d.%02d", (int)(gs_revision / 100), (int)(gs_revision % 100)); sprintf(key, "Software\\%s\\%s", gs_productfamily, dotversion); length = len; code = gp_getenv_registry(HKEY_CURRENT_USER, key, name, ptr, &length); if ( code == 0 ) return TRUE; /* found it */ length = len; code = gp_getenv_registry(HKEY_LOCAL_MACHINE, key, name, ptr, &length); if ( code == 0 ) return TRUE; /* found it */ return FALSE; } BOOL get_gs_string(int gs_revision, const char *name, char *ptr, int len) { if (get_gs_string_product(gs_revision, name, ptr, len, GS_PRODUCT_AFPL)) return TRUE; if (get_gs_string_product(gs_revision, name, ptr, len, GS_PRODUCT_ALADDIN)) return TRUE; if (get_gs_string_product(gs_revision, name, ptr, len, GS_PRODUCT_GPL)) return TRUE; if (get_gs_string_product(gs_revision, name, ptr, len, GS_PRODUCT_GNU)) return TRUE; return FALSE; } /* Set the latest Ghostscript EXE or DLL from the registry */ BOOL find_gs(char *gspath, int len, int minver, BOOL bDLL) { int count; int *ver; int gsver; char buf[256]; char *p; int i; DWORD version = GetVersion(); if ( ((HIWORD(version) & 0x8000)!=0) && ((HIWORD(version) & 0x4000)==0) ) return FALSE; // win32s count = 1; get_gs_versions(&count); if (count < 1) return FALSE; ver = (int *)malloc((count+1)*sizeof(int)); if (ver == (int *)NULL) return FALSE; ver[0] = count+1; if (!get_gs_versions(ver)) { free(ver); return FALSE; } gsver = 0; for (i=1; i<=ver[0]; i++) { if (ver[i] > gsver) gsver = ver[i]; } free(ver); if (gsver < minver) // minimum version (e.g. for gsprint) return FALSE; if (!get_gs_string(gsver, "GS_DLL", buf, sizeof(buf))) return FALSE; if (bDLL) { strncpy(gspath, buf, len-1); return TRUE; } p = strrchr(buf, '\\'); if (p) { p++; *p = 0; strncpy(p, "gswin32c.exe", sizeof(buf)-1-strlen(buf)); strncpy(gspath, buf, len-1); return TRUE; } return FALSE; } #ifdef DUMP_GSVER /* This is an example of how you can use the above functions */ int main(int argc, char *argv[]) { BOOL flag; int n; int ver[10]; int i; char buf[256]; if (find_gs(buf, sizeof(buf), 550, TRUE)) printf("Latest GS DLL is %s\n", buf); if (find_gs(buf, sizeof(buf), 550, FALSE)) printf("Latest GS EXE is %s\n", buf); ver[0] = sizeof(ver) / sizeof(int); flag = get_gs_versions(ver); printf("Versions: %d\n", ver[0]); if (flag == FALSE) { printf("get_gs_versions failed, need %d\n", ver[0]); return 1; } for (i=1; i <= ver[0]; i++) { printf(" %d\n", ver[i]); if (get_gs_string(ver[i], "GS_DLL", buf, sizeof(buf))) printf(" GS_DLL=%s\n", buf); if (get_gs_string(ver[i], "GS_LIB", buf, sizeof(buf))) printf(" GS_LIB=%s\n", buf); } return 0; } #endif epstool-3.08/srcwin/wgsver.h0000664000076400007640000000315010252260054015531 0ustar rjlrjl00000000000000/* Copyright (C) 2001-2002, Ghostgum Software Pty Ltd. All rights reserved. * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation * files (the "Software"), to deal in the Software without * restriction, including without limitation the rights to use, copy, * modify, merge, publish, distribute, sublicense, and/or sell copies * of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be * included in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ /* * This file is part of GSview. The above notice applies only * to this file. It does NOT apply to any other file in GSview * unless that file includes the above copyright notice. */ /* $Id: wgsver.h,v 1.1.2.2 2002/05/27 11:18:32 ghostgum Exp $ */ /* Functions for finding Ghostscript versions */ BOOL get_gs_versions(int *pver); BOOL get_gs_string(int gs_revision, const char *name, char *ptr, int len); BOOL find_gs(char *gspath, int len, int minver, BOOL bDLL); epstool-3.08/srcwin/windows.mak0000644000076400007640000002430110252260054016226 0ustar rjlrjl00000000000000# Copyright (C) 2002-2005 Ghostgum Software Pty Ltd. All rights reserved. # # This software is provided AS-IS with no warranty, either express or # implied. # # This software is distributed under licence and may not be copied, # modified or distributed except as expressly authorised under the terms # of the licence contained in the file LICENCE in this distribution. # # For more information about licensing, please refer to # http://www.ghostgum.com.au/ or contact Ghostsgum Software Pty Ltd, # 218 Gallaghers Rd, Glen Waverley VIC 3150, AUSTRALIA, # Fax +61 3 9886 6616. # # $Id: windows.mak,v 1.1.2.25 2005/06/10 09:39:24 ghostgum Exp $ # Windows makefile for MSVC # Try to detect the compiler version !if defined(_NMAKE_VER) && !defined(VCVER) !if "$(_NMAKE_VER)" == "162" VCVER=5 !endif !if "$(_NMAKE_VER)" == "6.00.8168.0" VCVER=6 !endif !if "$(_NMAKE_VER)" == "7.00.9466" VCVER=7 !endif !if "$(_NMAKE_VER)" == "7.10.3077" VCVER=71 !endif !if "$(_NMAKE_VER)" == "8.00.40607.16" VCVER=8 !endif !endif # Edit VCVER and DEVBASE as required !ifndef VCVER VCVER=71 !endif !ifndef VCDRIVE VCDRIVE=C: !endif # Win64 requires Microsoft Visual Studio 8 (.NET 2005) # or Microsoft Visual Studio .NET 2003 with Windows Server 2003 DDK. # To compile for Win64, use "nmake WIN64=1" !ifdef WIN64 WIN32=0 WIN64=1 !else WIN32=1 WIN64=0 !endif # When compiling on Win64, x86 programs are in different place !ifndef PROGFILESX86 PROGFILESX86=Program Files #PROGFILESX86=Program Files (x86) !endif !if $(VCVER) <= 5 DEVBASE=$(VCDRIVE)\$(PROGFILESX86)\devstudio !endif !if $(VCVER) == 6 DEVBASE=$(VCDRIVE)\$(PROGFILESX86)\Microsoft Visual Studio !endif !if $(VCVER) == 7 DEVBASE=$(VCDRIVE)\$(PROGFILESX86)\Microsoft Visual Studio .NET !endif !if $(VCVER) == 71 DEVBASE=$(VCDRIVE)\$(PROGFILESX86)\Microsoft Visual Studio .NET 2003 DDKBASE=$(VCDRIVE)\winddk\3790 !endif !if $(VCVER) == 8 DEVBASE=$(VCDRIVE)\$(PROGFILESX86)\Microsoft Visual Studio 8 !endif # DEBUG=1 for Debugging options DEBUG=1 BINDIR=.\bin OBJDIR=.\obj SRCDIR=.\src SRCWINDIR=.\srcwin !ifndef LIBPNGINC LIBPNGINC=-Ilibpng -Izlib LIBPNGCFLAGS=-DHAVE_LIBPNG -DPNG_USE_DLL LIBPNGLIBS=libpng\libpng.lib zlib\zlib.lib !endif !if $(VCVER) <= 5 COMPBASE=$(DEVBASE)\vc !endif !if $(VCVER) == 6 COMPBASE=$(DEVBASE)\vc98 !endif !if ($(VCVER) == 7) || ($(VCVER) == 71) COMPBASE=$(DEVBASE)\Vc7 PLATLIBDIR=$(COMPBASE)\PlatformSDK\lib !endif !if $(VCVER) == 8 COMPBASE = $(DEVBASE)\VC PLATLIBDIR=$(COMPBASE)\PlatformSDK\lib !endif # MSVC 8 (2005) warns about deprecated common functions like fopen. !if $(VCVER) == 8 VC8WARN=/wd4996 !else VC8WARN= !endif COMPDIR=$(COMPBASE)\bin INCDIR=$(COMPBASE)\include LIBDIR=$(COMPBASE)\lib !ifndef PLATLIBDIR PLATLIBDIR=$(LIBDIR) !endif !ifdef UNICODE UNICODEDEF=-DUNICODE !endif CDEFS=-D_Windows -D__WIN32__ -I"$(INCDIR)" $(UNICODEDEF) $(LIBPNGCFLAGS) $(LARGEFILES) WINEXT=32 CFLAGS=$(CDEFS) /MT /nologo /W4 $(VC8WARN) !if $(DEBUG) DEBUGLINK=/DEBUG CDEBUG=/Zi !endif !if $(WIN32) MODEL=32 CCAUX = "$(COMPDIR)\cl" -I"$(INCDIR)" CC = "$(COMPDIR)\cl" $(CDEBUG) CLINK=$(CC) LINK = "$(COMPDIR)\link" LINKMACHINE=IX86 !else if $(WIN64) MODEL=32 CCAUX = "$(COMPDIR)\cl" -I"$(INCDIR)" !if $(VCVER) == 71 LINKMACHINE=X86 CC="$(DDKBASE)\bin\win64\x86\amd64\cl" $(CDEBUG) CLINK=$(CC) LINK="$(DDKBASE)\bin\win64\x86\amd64\link" LIBDIR=$(DDKBASE)\lib\wnet\amd64 PLATLIBDIR=$(DDKBASE)\lib\wnet\amd64 !else LINKMACHINE=X64 CC="$(COMPDIR)\x86_amd64\cl" $(CDEBUG) CLINK=$(CC) LINK="$(COMPDIR)\x86_amd64\link" LIBDIR=$(COMPBASE)\lib\amd64 PLATLIBDIR=$(COMPBASE)\PlatformSDK\Lib\AMD64 !endif !endif CLFLAG= RIFLAGS=-i"$(INCDIR)" -i"$(SRCDIR)" -i"$(SRCWINDIR)" -i"$(OBJDIR)" !if $(VCVER) <= 5 HC="$(COMPDIR)\hcw" /C /E RCOMP="$(DEVBASE)\sharedide\bin\rc" -D_MSC_VER $(CDEFS) $(RIFLAGS) !endif !if $(VCVER) == 6 HC="$(DEVBASE)\common\tools\hcw" /C /E RCOMP="$(DEVBASE)\common\msdev98\bin\rc" -D_MSC_VER $(CDEFS) $(RIFLAGS) !endif !if ($(VCVER) == 7) || ($(VCVER) == 71) HC="$(DEVBASE)\Common7\Tools\hcw" /C /E RCOMP="$(DEVBASE)\Vc7\bin\rc" -D_MSC_VER $(CDEFS) $(RIFLAGS) !endif !if $(VCVER) == 8 HC="$(DEVBASE)\VC\bin\hcw" /C /E RCOMP="$(DEVBASE)\VC\bin\rc" -D_MSC_VER $(CDEFS) $(RIFLAGS) !endif COMP=$(CC) -I$(SRCDIR) -I$(SRCWINDIR) -I$(OBJDIR) $(CFLAGS) NUL= DD=\$(NUL) SRC=$(SRCDIR)\$(NUL) SRCWIN=$(SRCWINDIR)\$(NUL) OD=$(OBJDIR)\$(NUL) BD=$(BINDIR)\$(NUL) OBJ=.obj EXE=.exe CO=-c FE=-Fe FO=-Fo FEO=-Fe$(OD) FOO=-Fo$(OD) CP=copy RM=del RMDIR=rmdir /s /q # simple viewer OBJPLAT1=$(OD)wapp$(OBJ) $(OD)wdll$(OBJ) $(OD)wdoc$(OBJ) \ $(OD)wgsimg$(OBJ) $(OD)wgssrv$(OBJ) $(OD)wgsver$(OBJ) $(OD)wimg$(OBJ) \ $(OD)wfile$(OBJ) VIEWAPIOBJ=$(OBJPLAT1) $(OBJCOM1) $(OBJCOM2) $(OD)wviewapi$(OBJ) # complex viewer OBJPLAT2=$(OD)wview$(OBJ) $(OD)wviewwin$(OBJ) $(OD)main$(OBJ) OBJPLAT=$(OBJPLAT1) $(OBJPLAT2) # another complex viewer VIEWOBJ=$(OBJPLAT1) $(OBJCOM1) $(OBJCOM2) \ $(OD)wtest2$(OBJ) $(OD)wtest3$(OBJ) $(OD)cvcmd$(OBJ) # epstool EPSOBJPLAT=$(OD)wdll$(OBJ) $(OD)wgsver$(OBJ) $(OD)wfile$(OBJ) EPSLIB="$(PLATLIBDIR)\advapi32.lib" $(LIBPNGLIBS) /link /LIBPATH:"$(LIBDIR)" HDRSPLAT=$(SRCWIN)wimg.h $(SRCWIN)wgsver.h OBJSBEGIN=$(OD)lib.rsp #TARGET=$(BD)main$(EXE) #TARGET=$(BD)epstool$(EXE) TARGET=gsview_test1 !include $(SRC)common.mak $(OD)lib.rsp: makefile -mkdir $(BINDIR) -mkdir $(OBJDIR) echo "$(PLATLIBDIR)\shell32.lib" > $(OD)lib.rsp echo "$(PLATLIBDIR)\comdlg32.lib" >> $(OD)lib.rsp echo "$(PLATLIBDIR)\gdi32.lib" >> $(OD)lib.rsp echo "$(PLATLIBDIR)\user32.lib" >> $(OD)lib.rsp echo "$(PLATLIBDIR)\winspool.lib" >> $(OD)lib.rsp echo "$(PLATLIBDIR)\advapi32.lib" >> $(OD)lib.rsp echo "$(PLATLIBDIR)\ole32.lib" >> $(OD)lib.rsp echo "$(PLATLIBDIR)\uuid.lib" >> $(OD)lib.rsp echo /NODEFAULTLIB:LIBC.lib >> $(OD)lib.rsp echo "$(LIBDIR)\libcmt.lib" >> $(OD)lib.rsp !if "$(LIBPNGLIBS)" != "" echo $(LIBPNGLIBS) >> $(OD)lib.rsp !endif # A command line program for testing GSview on Windows. $(BD)main.exe: $(OBJS) $(OD)lib.rsp echo $(OBJS) > $(OD)link.rsp $(LINK) $(DEBUGLINK) /OUT:$(BD)main.exe @$(OD)link.rsp @$(OD)lib.rsp $(OD)main.obj: $(SRCWIN)main.c $(HDRS) $(COMP) $(FOO)main$(OBJ) $(CO) $(SRCWIN)main.c # A DLL with a simplified interface to GSview. This is intended # to be used by an ActiveX control. gsview_test1: $(BD)gsview_test1.dll $(BD)wviewapi_example.exe $(BD)wtest1.exe $(BD)wtest3.exe $(BD)gsview_test1.dll: $(VIEWAPIOBJ) $(OD)lib.rsp echo $(VIEWAPIOBJ) > $(OD)link.rsp $(LINK) $(DEBUGLINK) /DLL /OUT:$(BD)gsview_test1.dll @$(OD)link.rsp @$(OD)lib.rsp $(OD)wviewapi.obj: $(SRCWIN)wviewapi.c $(HDRS) $(COMP) $(FOO)wviewapi$(OBJ) $(CO) $(SRCWIN)wviewapi.c $(BD)wviewapi_example.exe: $(SRCWIN)wviewapi_example.c $(SRCWIN)wviewapi.h $(BD)gsview_test1.dll $(COMP) $(FE)$(BD)wviewapi_example.exe $(SRCWIN)wviewapi_example.c $(BD)gsview_test1.lib $(BD)wtest1$(EXE): $(OD)wtest1$(OBJ) $(OD)wtest2$(OBJ) $(OD)wtest1.res $(SRCWIN)wviewapi.h $(BD)gsview_test1.dll $(OD)lib.rsp $(LINK) $(DEBUGLINK) /SUBSYSTEM:WINDOWS /OUT:$(BD)wtest1$(EXE) $(OD)wtest1$(OBJ) $(OD)wtest2$(OBJ) $(BD)gsview_test1.lib @$(OD)lib.rsp $(OD)wtest1.res $(BD)wtest3$(EXE): $(VIEWOBJ) $(OD)wtest1.res $(OD)lib.rsp $(LINK) $(DEBUGLINK) /SUBSYSTEM:WINDOWS /OUT:$(BD)wtest3$(EXE) $(VIEWOBJ) @$(OD)lib.rsp $(OD)wtest1.res $(OD)wtest1.res: $(SRCWIN)wtest1.h $(SRCWIN)wtest1.rc $(RCOMP) -i"srcwin" -fo$(OD)wtest1.res $(SRCWIN)wtest1 # Windows specific $(OD)wapp$(OBJ): $(SRCWIN)wapp.c $(HDRS) $(COMP) $(FOO)wapp$(OBJ) $(CO) $(SRCWIN)wapp.c $(OD)wdll$(OBJ): $(SRCWIN)wdll.c $(HDRS) $(COMP) $(FOO)wdll$(OBJ) $(CO) $(SRCWIN)wdll.c $(OD)wdoc$(OBJ): $(SRCWIN)wdoc.c $(HDRS) $(COMP) $(FOO)wdoc$(OBJ) $(CO) $(SRCWIN)wdoc.c $(OD)wfile$(OBJ): $(SRCWIN)wfile.c $(cfile_h) $(COMP) $(FOO)wfile$(OBJ) $(CO) $(SRCWIN)wfile.c $(OD)wgsimg$(OBJ): $(SRCWIN)wgsimg.c $(HDRS) $(COMP) $(FOO)wgsimg$(OBJ) $(CO) $(SRCWIN)wgsimg.c $(OD)wgssrv$(OBJ): $(SRCWIN)wgssrv.c $(HDRS) $(COMP) $(FOO)wgssrv$(OBJ) $(CO) $(SRCWIN)wgssrv.c $(OD)wgsver$(OBJ): $(SRCWIN)wgsver.c $(HDRS) $(COMP) $(FOO)wgsver$(OBJ) $(CO) $(SRCWIN)wgsver.c $(OD)wimg$(OBJ): $(SRCWIN)wimg.c $(HDRS) $(COMP) $(FOO)wimg$(OBJ) $(CO) $(SRCWIN)wimg.c $(OD)wview$(OBJ): $(SRCWIN)wview.c $(HDRS) $(COMP) $(FOO)wview$(OBJ) $(CO) $(SRCWIN)wview.c $(OD)wviewwin$(OBJ): $(SRCWIN)wviewwin.c $(HDRS) $(COMP) $(FOO)wviewwin$(OBJ) $(CO) $(SRCWIN)wviewwin.c $(OD)wtest1$(OBJ): $(SRCWIN)wtest1.c $(SRCWIN)wtest1.h $(SRCWIN)wtest2.h $(HDRS) $(COMP) $(FOO)wtest1$(OBJ) $(CO) $(SRCWIN)wtest1.c $(OD)wtest2$(OBJ): $(SRCWIN)wtest2.c $(SRCWIN)wtest1.h $(SRCWIN)wtest2.h $(HDRS) $(COMP) $(FOO)wtest2$(OBJ) $(CO) $(SRCWIN)wtest2.c $(OD)wtest3$(OBJ): $(SRCWIN)wtest3.c $(SRCWIN)wtest1.h $(SRCWIN)wtest2.h $(HDRS) $(COMP) $(FOO)wtest3$(OBJ) $(CO) $(SRCWIN)wtest3.c wtest1: $(BD)wtest1$(EXE) wtest3: $(BD)wtest3$(EXE) epstool: $(BD)epstool$(EXE) epstool_make: nmake -f $(SRCWIN)windows.mak VCVER=$(VCVER) VCDRIVE=$(VCDRIVE) LIBPNGINC= LIBPNGCFLAGS= LIBPNGLIBS= $(BD)epstool$(EXE) epstest: epstool_make nmake -f $(SRCWIN)windows.mak VCVER=$(VCVER) VCDRIVE=$(VCDRIVE) LIBPNGINC= LIBPNGCFLAGS= LIBPNGLIBS= $(BD)epstest$(EXE) $(BD)epstest$(EXE) clean: -del $(OBJS) -del $(EPSOBJS) -del $(VIEWAPIOBJ) -del $(BD)main.exe -del $(BD)main.ilk -del $(BD)main.pdb -del $(BD)epstool.exe -del $(BD)epstool.ilk -del $(BD)epstool.pdb -del $(BD)gsview_test1.dll -del $(BD)gsview_test1.exp -del $(BD)gsview_test1.lib -del $(BD)gsview_test1.ilk -del $(BD)gsview_test1.pdb -del $(BD)wviewapi_example.exe -del $(BD)wviewapi_example.ilk -del $(BD)wviewapi_example.pdb -del $(OD)wtest1.obj -del $(OD)wtest1.res -del $(BD)wtest1.exe -del $(BD)wtest1.ilk -del $(BD)wtest1.pdb -del $(OD)wtest3.obj -del $(OD)wtest3.res -del $(BD)wtest3.exe -del $(BD)wtest3.ilk -del $(BD)wtest3.pdb -del vc70.pdb vc60.pdb vc50.pdb -del $(OD)lib.rsp -del $(OD)link.rsp # simple GS interface SIMPLEOBJ=$(OD)wdll$(OBJ) $(OD)wgsver$(OBJ) \ $(OD)cgsdll$(OBJ) $(OD)cgsdll2$(OBJ) $(OD)cgsdll2$(OBJ): $(SRC)cgsdll2.c $(HDRS) $(COMP) $(FOO)cgsdll2$(OBJ) $(CO) $(SRC)cgsdll2.c $(BD)gssimple.dll: $(SIMPLEOBJ) $(OD)lib.rsp echo $(SIMPLEOBJ) > $(OD)link.rsp $(LINK) $(DEBUGLINK) /DLL /OUT:$(BD)gssimple.dll @$(OD)link.rsp @$(OD)lib.rsp $(BD)gssimple.exe: $(SIMPLEOBJ) $(OD)lib.rsp echo $(SIMPLEOBJ) > $(OD)link.rsp $(LINK) $(DEBUGLINK) /SUBSYSTEM:CONSOLE /OUT:$(BD)gssimple.exe @$(OD)link.rsp @$(OD)lib.rsp