-CHANGES.txt - 03/29/2001
+CHANGES.txt - 05/07/2001
------------------------
+CHANGES IN CUPS V1.1.8
+
+ - Updated spec file to generate separate cups-pstoraster
+ package for pstoraster.
+ - The spec file wasn't setting LOGDIR in the install.
+ - The scheduler might restart a stopped printer after
+ stopping a print job. Thanks to Florent
+ Guiliani for finding this bug!
+ - The init script showed run level 0 for the Red Hat
+ chkconfig program. This is incorrect because Red Hat
+ doesn't use run level 0 for shutdown scripts.
+ - The IPP backend did not handle the
+ client-error-not-found error when checking the status
+ of the job that was sent. This caused remote queues
+ to stop on client machines when the server had job
+ history disabled.
+ - Added httpConnectEncrypt() function to avoid
+ performance penalty for setting up encrypted
+ connections initially.
+ - Use httpConnectEncrypt() in all client apps and in the
+ CUPS API to ensure consistent usage of encryption
+ throughout.
+ - Jobs weren't queued to remote classes (fix from
+ Richard Begg.)
+ - AIX changes from Richard Begg.
+ - Fixed the pstops fix for GNOME output - no longer use
+ the page numbers in the %%Page: comment since GNOME
+ puts a filename instead (!?@!#?!). There is still an
+ issue with N-up printing since GNOME defines its fonts
+ in the first page instead of the document setup section
+ (pages must be independent according to the DSC spec)
+ People with GNOME printing problems should consult bug
+ #54489...
+ - The imagetops filter produced PAGE: messages when
+ generating PostScript for a non-PostScript printer
+ (only affects page-label and Classification
+ options.)
+ - The updated pdftops filter was looking for an options
+ file called xpdf.conf instead of pdftops.conf.
+
+
CHANGES IN CUPS V1.1.7
- Configuration script changes, including new
- All scheduler configuration files are now case
insensitive to match Apache.
- Added support for Apache ListenBackLog, LogFormat,
- PassEnv, SetEnv, UnsetEnv, Require, UseCanonicalName,
- Satisfy, <Limit>, <LimitExcept>, LimitRequestSize, and
- Options directives.
+ Require, UseCanonicalName, Satisfy, <Limit>,
+ <LimitExcept>, LimitRequestSize, and Options
+ directives.
- Added support for all Apache log levels...
- Added support for "double" HostNameLookups.
- Added new "RunAsUser" directive to support non-root
clients or start print jobs as the load allows.
- Fixed a bug in the Set-Job-Attributes code that could
crash the scheduler (patch from Martin Zielinski)
- - cupsSetDests() did not quote option values with embedded
- spaces.
+ - cupsSetDests() did not quote option values with
+ embedded spaces.
+ - Added support for the Enable-Printer and
+ Disable-Printer extension operations (same as
+ CUPS-Accept-Jobs and CUPS-Reject-Jobs.)
+ - The AppSocket and IPP backends now wait for the print
+ job to be finished before exiting; this should prevent
+ the loss of print jobs with older JetDirect firmware
+ and make consecutive print jobs print faster.
+ - The BMP loading code did not handle resolution values
+ of 0. This is a problem with BMP image files produced
+ by the GIMP.
+ - The HTTP Upgrade code (upgrade to TLS encryption)
+ bypassed the authentication checks.
+ - The HTTP Upgrade code did not send a 426 status code
+ to the client and end the current request. This caused
+ a race condition between the client and server for the
+ upgrade to TLS.
+ - Fixed a bug in the EOF and Trailer detection code in
+ the pstops filter.
+ - The imagetoraster filter did not add the margins to
+ the custom page size in the raster header.
+ - The imagetops filter did not adjust the custom page
+ size to the size of the printed image.
+ - The imagetops filter did not include DSC comments
+ which are required by some printers.
+ - The imagetops filter did not insert newlines in
+ Base85 encoded output, causing files to contain
+ lines longer than 255 characters (violation of the
+ DSC).
+ - Added support for the DeskJet 900 series duplexer
+ and CRET color modes in the HP driver.
+ - Added support for PPD-defined margins in the HP
+ driver.
+ - Fixed the debugging output from pstoraster - the
+ font list was not terminated by a newline.
+ - Some versions of the HP-UX pam_unix authentication
+ module apparently do not pass the appdata_ptr argument
+ to the conversation function, preventing the scheduler
+ from authenticating users using PAM under HP-UX. A
+ workaround using a static variable has been added to
+ address this problem.
+ - Fixed a bug in the scheduler SortPrinters() function
+ that could cause printers to disappear or the
+ scheduler to crash when adding a printer.
+ - Changed the pstops filter to not do per-page filtering
+ if the file does not conform to at least version 3.0
+ of the document structuring conventions. This seems
+ to "fix" printing with broken apps.
+ - The image filters did not handle older TIFF files that
+ lacked the samples-per-pixel and bits-per-pixel tags.
+ - Added new cupsGetJobs() and cupsFreeJobs() functions
+ to manage print jobs.
+ - cupsEncodeOptions() would encode names of 0 length and
+ cupsAddOption() and cupsParseOptions() would add names
+ of 0 length.
+ - The scheduler might block waiting for status messages
+ after starting a new print job. Thanks to Florent
+ Guiliani for finding this bug!
CHANGES IN CUPS V1.1.6-3
-INSTALL - CUPS v1.1.6 - 01/23/2001
+INSTALL - CUPS v1.1.7 - 05/01/2001
----------------------------------
This file describes how to compile and install CUPS from source
#
-# "$Id: Makedefs.in,v 1.36 2001/03/01 18:10:40 mike Exp $"
+# "$Id: Makedefs.in,v 1.36.2.1 2001/05/13 18:37:58 mike Exp $"
#
# Common makefile definitions for the Common UNIX Printing System (CUPS).
#
#
# Program options...
#
-# GSOPTIM defines the common compiler optimization/debugging options for
-# pstoraster (Ghostscript).
# OPTIM defines the common compiler optimization/debugging options.
# OPTIONS defines other compile-time options (currently only -dDEBUG for
# extra debug info)
CXXFLAGS = @CXXFLAGS@ -I.. $(OPTIONS)
DSOFLAGS = @DSOFLAGS@
DSOLIBS = @DSOLIBS@
-GSOPTIM = @GSOPTIM@
IMGLIBS = @IMGLIBS@ -lm
LDFLAGS = @LDFLAGS@ $(OPTIM)
LINKCUPS = @LINKCUPS@
$(MV) t.z $@
#
-# End of "$Id: Makedefs.in,v 1.36 2001/03/01 18:10:40 mike Exp $"
+# End of "$Id: Makedefs.in,v 1.36.2.1 2001/05/13 18:37:58 mike Exp $"
#
#
-# "$Id: Makefile,v 1.31 2001/03/01 20:40:14 mike Exp $"
+# "$Id: Makefile,v 1.31.2.1 2001/05/13 18:37:58 mike Exp $"
#
# Top-level Makefile for the Common UNIX Printing System (CUPS).
#
#
EPMFLAGS = -v \
+ AMANDIR=$(AMANDIR) \
BINDIR=$(BINDIR) DATADIR=$(DATADIR) \
DOCDIR=$(DOCDIR) INCLUDEDIR=$(INCLUDEDIR) \
LIBDIR=$(LIBDIR) LOCALEDIR=$(LOCALEDIR) \
epm $(EPMFLAGS) -f tardist cups
#
-# End of "$Id: Makefile,v 1.31 2001/03/01 20:40:14 mike Exp $".
+# End of "$Id: Makefile,v 1.31.2.1 2001/05/13 18:37:58 mike Exp $".
#
-README - CUPS v1.1.6 - 01/23/2001
+README - CUPS v1.1.7 - 05/01/2001
---------------------------------
Looking for compile instructions? Read the file "INSTALL.txt"
/*
- * "$Id: ipp.c,v 1.38 2001/02/14 13:59:45 mike Exp $"
+ * "$Id: ipp.c,v 1.38.2.1 2001/05/13 18:37:59 mike Exp $"
*
* IPP backend for the Common UNIX Printing System (CUPS).
*
*
* Contents:
*
- * main() - Send a file to the printer or server.
+ * main() - Send a file to the printer or server.
+ * password_cb() - Disable the password prompt for cupsDoFileRequest().
*/
/*
#include <signal.h>
+/*
+ * Local functions...
+ */
+
+const char *password_cb(const char *);
+
+
+/*
+ * Local globals...
+ */
+
+char *password = NULL;
+
+
/*
* 'main()' - Send a file to the printer or server.
*
resource[1024], /* Resource info (printer name) */
filename[1024]; /* File to print */
int port; /* Port number (not used) */
- char password[255], /* Password info */
- uri[HTTP_MAX_URI];/* Updated URI without user/pass */
- http_status_t status; /* Status of HTTP job */
+ char uri[HTTP_MAX_URI];/* Updated URI without user/pass */
ipp_status_t ipp_status; /* Status of IPP request */
- FILE *fp; /* File to print */
http_t *http; /* HTTP connection */
ipp_t *request, /* IPP request */
*response, /* IPP response */
*supported; /* get-printer-attributes response */
- ipp_attribute_t *job_id; /* job-id attribute */
+ ipp_attribute_t *job_id_attr; /* job-id attribute */
+ int job_id; /* job-id value */
+ ipp_attribute_t *job_state; /* job-state attribute */
ipp_attribute_t *copies_sup; /* copies-supported attribute */
ipp_attribute_t *charset_sup; /* charset-supported attribute */
ipp_attribute_t *format_sup; /* document-format-supported attribute */
const char *charset; /* Character set to use */
cups_lang_t *language; /* Default language */
- struct stat fileinfo; /* File statistics */
- size_t nbytes, /* Number of bytes written */
- tbytes; /* Total bytes written */
- char buffer[8192]; /* Output buffer */
int copies; /* Number of copies remaining */
const char *content_type; /* CONTENT_TYPE environment variable */
#if defined(HAVE_SIGACTION) && !defined(HAVE_SIGSET)
}
/*
- * Open the print file...
+ * Extract the hostname and printer name from the URI...
*/
- if ((fp = fopen(filename, "rb")) == NULL)
- {
- perror("ERROR: Unable to open print file");
- return (1);
- }
- else
- stat(filename, &fileinfo);
+ httpSeparate(argv[0], method, username, hostname, &port, resource);
/*
- * Extract the hostname and printer name from the URI...
+ * Set the authentication info, if any...
*/
- httpSeparate(argv[0], method, username, hostname, &port, resource);
+ cupsSetPasswordCB(password_cb);
+
+ if (username[0])
+ {
+ if ((password = strchr(username, ':')) != NULL)
+ *password++ = '\0';
+
+ cupsSetUser(username);
+ }
/*
* Try connecting to the remote server...
ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri",
NULL, uri);
- /*
- * Now fill in the HTTP request stuff...
- */
-
- httpClearFields(http);
- httpSetField(http, HTTP_FIELD_CONTENT_TYPE, "application/ipp");
- if (username[0])
- {
- httpEncode64(password, username);
- httpSetField(http, HTTP_FIELD_AUTHORIZATION, password);
- }
-
- sprintf(buffer, "%u", ippLength(request));
- httpSetField(http, HTTP_FIELD_CONTENT_LENGTH, buffer);
-
/*
* Do the request...
*/
- for (response = NULL, ipp_status = IPP_BAD_REQUEST;;)
+ if ((supported = cupsDoRequest(http, request, resource)) == NULL)
+ ipp_status = cupsLastError();
+ else
+ ipp_status = supported->request.status.status_code;
+
+ if (ipp_status > IPP_OK_CONFLICT)
{
- /*
- * POST the request, retrying as needed...
- */
+ if (supported)
+ ippDelete(supported);
- if (httpPost(http, resource))
+ if (ipp_status == IPP_PRINTER_BUSY ||
+ ipp_status == IPP_SERVICE_UNAVAILABLE)
{
- fputs("INFO: Unable to POST get-printer-attributes request; retrying...\n", stderr);
+ fputs("INFO: Printer busy; will retry in 10 seconds...\n", stderr);
sleep(10);
- httpReconnect(http);
- continue;
- }
-
- fputs("INFO: POST successful, sending IPP request...\n", stderr);
-
- /*
- * Send the IPP request...
- */
-
- request->state = IPP_IDLE;
-
- if (ippWrite(http, request) == IPP_ERROR)
- {
- fputs("ERROR: Unable to send IPP request!\n", stderr);
- status = HTTP_ERROR;
- break;
}
-
- fputs("INFO: IPP request sent, getting status...\n", stderr);
-
- /*
- * Finally, check the status from the HTTP server...
- */
-
- while ((status = httpUpdate(http)) == HTTP_CONTINUE);
-
- if (supported)
- ippDelete(supported);
-
- if (status == HTTP_OK)
+ else if ((ipp_status == IPP_BAD_REQUEST ||
+ ipp_status == IPP_VERSION_NOT_SUPPORTED) && version == 1)
{
- supported = ippNew();
- ippRead(http, supported);
+ /*
+ * Switch to IPP/1.0...
+ */
- ipp_status = supported->request.status.status_code;
-
- if (ipp_status > IPP_OK_CONFLICT)
- {
- if (ipp_status == IPP_PRINTER_BUSY ||
- ipp_status == IPP_SERVICE_UNAVAILABLE)
- {
- fputs("INFO: Printer busy; will retry in 10 seconds...\n", stderr);
- sleep(10);
- }
- else if ((ipp_status == IPP_BAD_REQUEST ||
- ipp_status == IPP_VERSION_NOT_SUPPORTED) && version == 1)
- {
- /*
- * Switch to IPP/1.0...
- */
-
- fputs("INFO: Printer does not support IPP/1.1, trying IPP/1.0...\n", stderr);
- version = 0;
- }
- else
- {
- fprintf(stderr, "ERROR: Printer will not accept print file (%x)!\n",
- ipp_status);
- fprintf(stderr, "ERROR: %s\n", ippErrorString(ipp_status));
- status = HTTP_ERROR;
- }
- }
- else if ((copies_sup = ippFindAttribute(supported, "copies-supported",
- IPP_TAG_RANGE)) != NULL)
- {
- /*
- * Has the "copies-supported" attribute - does it have an upper
- * bound > 1?
- */
-
- if (copies_sup->values[0].range.upper <= 1)
- copies_sup = NULL; /* No */
- }
-
- charset_sup = ippFindAttribute(supported, "charset-supported",
- IPP_TAG_CHARSET);
- format_sup = ippFindAttribute(supported, "document-format-supported",
- IPP_TAG_MIMETYPE);
-
- if (format_sup)
- {
- fprintf(stderr, "DEBUG: document-format-supported (%d values)\n",
- format_sup->num_values);
- for (i = 0; i < format_sup->num_values; i ++)
- fprintf(stderr, "DEBUG: [%d] = \"%s\"\n", i,
- format_sup->values[i].string.text);
- }
+ fputs("INFO: Printer does not support IPP/1.1, trying IPP/1.0...\n", stderr);
+ version = 0;
}
else
- {
- supported = NULL;
-
- if (status == HTTP_ERROR)
- {
- fprintf(stderr, "WARNING: Did not receive the IPP supported (%d)\n",
- errno);
- status = HTTP_OK;
- ipp_status = IPP_PRINTER_BUSY;
- }
- else
- {
- fprintf(stderr, "ERROR: Validate request was not accepted (%d)!\n",
- status);
- ipp_status = IPP_FORBIDDEN;
- }
- }
-
- httpFlush(http);
-
- break;
+ fprintf(stderr, "ERROR: Printer will not accept print file (%s)!\n",
+ ippErrorString(ipp_status));
}
-
- if (status != HTTP_OK)
+ else if ((copies_sup = ippFindAttribute(supported, "copies-supported",
+ IPP_TAG_RANGE)) != NULL)
{
- if (fp != stdin)
- fclose(fp);
+ /*
+ * Has the "copies-supported" attribute - does it have an upper
+ * bound > 1?
+ */
- httpClose(http);
+ if (copies_sup->values[0].range.upper <= 1)
+ copies_sup = NULL; /* No */
+ }
- return (1);
+ charset_sup = ippFindAttribute(supported, "charset-supported",
+ IPP_TAG_CHARSET);
+ format_sup = ippFindAttribute(supported, "document-format-supported",
+ IPP_TAG_MIMETYPE);
+
+ if (format_sup)
+ {
+ fprintf(stderr, "DEBUG: document-format-supported (%d values)\n",
+ format_sup->num_values);
+ for (i = 0; i < format_sup->num_values; i ++)
+ fprintf(stderr, "DEBUG: [%d] = \"%s\"\n", i,
+ format_sup->values[i].string.text);
}
- else if (ipp_status > IPP_OK_CONFLICT)
- httpReconnect(http);
}
while (ipp_status > IPP_OK_CONFLICT);
ippAddInteger(request, IPP_TAG_JOB, IPP_TAG_INTEGER, "copies", atoi(argv[4]));
/*
- * Now fill in the HTTP request stuff...
+ * Do the request...
*/
- httpClearFields(http);
- httpSetField(http, HTTP_FIELD_CONTENT_TYPE, "application/ipp");
- if (username[0])
+ if ((response = cupsDoFileRequest(http, request, resource, filename)) == NULL)
+ ipp_status = cupsLastError();
+ else
+ ipp_status = response->request.status.status_code;
+
+ if (ipp_status > IPP_OK_CONFLICT)
+ {
+ if (ipp_status == IPP_SERVICE_UNAVAILABLE ||
+ ipp_status == IPP_PRINTER_BUSY)
+ {
+ fputs("INFO: Printer is busy; retrying print job...\n", stderr);
+ sleep(10);
+ }
+ else
+ fprintf(stderr, "ERROR: Print file was not accepted (%s)!\n",
+ ippErrorString(ipp_status));
+ }
+ else if ((job_id_attr = ippFindAttribute(response, "job-id",
+ IPP_TAG_INTEGER)) == NULL)
{
- httpEncode64(password, username);
- httpSetField(http, HTTP_FIELD_AUTHORIZATION, password);
+ fputs("INFO: Print file accepted - job ID unknown.\n", stderr);
+ job_id = 0;
+ }
+ else
+ {
+ job_id = job_id_attr->values[0].integer;
+ fprintf(stderr, "INFO: Print file accepted - job ID %d.\n", job_id);
}
- sprintf(buffer, "%u", ippLength(request) + (size_t)fileinfo.st_size);
- httpSetField(http, HTTP_FIELD_CONTENT_LENGTH, buffer);
+ if (response)
+ ippDelete(response);
+
+ if (ipp_status <= IPP_OK_CONFLICT)
+ {
+ fprintf(stderr, "PAGE: 1 %d\n", copies_sup ? atoi(argv[4]) : 1);
+ copies --;
+ }
+ else if (ipp_status != IPP_SERVICE_UNAVAILABLE &&
+ ipp_status != IPP_PRINTER_BUSY)
+ break;
/*
- * Do the request...
+ * Wait for the job to complete...
*/
+ if (!job_id)
+ continue;
+
+ fputs("INFO: Waiting for job to complete...\n", stderr);
+
for (;;)
{
/*
- * POST the request, retrying as needed...
+ * Build an IPP_GET_JOB_ATTRIBUTES request...
*/
- httpReconnect(http);
-
- if (httpPost(http, resource))
- {
- fputs("INFO: Unable to POST print request; retrying...\n", stderr);
- sleep(10);
- continue;
- }
+ request = ippNew();
+ request->request.op.version[1] = version;
+ request->request.op.operation_id = IPP_GET_JOB_ATTRIBUTES;
+ request->request.op.request_id = 1;
- fputs("INFO: POST successful, sending IPP request...\n", stderr);
+ ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_CHARSET,
+ "attributes-charset", NULL, charset);
- /*
- * Send the IPP request...
- */
+ ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_LANGUAGE,
+ "attributes-natural-language", NULL,
+ language != NULL ? language->language : "en");
- request->state = IPP_IDLE;
+ ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri",
+ NULL, uri);
- if (ippWrite(http, request) == IPP_ERROR)
- {
- fputs("ERROR: Unable to send IPP request!\n", stderr);
- status = HTTP_ERROR;
- break;
- }
+ ippAddInteger(request, IPP_TAG_OPERATION, IPP_TAG_INTEGER, "job-id",
+ job_id);
- fputs("INFO: IPP request sent, sending print file...\n", stderr);
+ ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_KEYWORD,
+ "requested-attributes", NULL, "job-state");
/*
- * Then send the file...
+ * Do the request...
*/
- rewind(fp);
+ if ((response = cupsDoRequest(http, request, resource)) == NULL)
+ ipp_status = cupsLastError();
+ else
+ ipp_status = response->request.status.status_code;
- tbytes = 0;
- while ((nbytes = fread(buffer, 1, sizeof(buffer), fp)) > 0)
+ if (ipp_status == IPP_NOT_FOUND)
{
- tbytes += nbytes;
- fprintf(stderr, "INFO: Sending print file, %uk...\n", tbytes / 1024);
+ /*
+ * Job has gone away and the server has no job history...
+ */
- if (httpWrite(http, buffer, nbytes) < nbytes)
- {
- perror("ERROR: Unable to send print file to printer");
- status = HTTP_ERROR;
- break;
- }
+ ippDelete(response);
+ break;
}
- fputs("INFO: Print file sent; checking status...\n", stderr);
-
- /*
- * Finally, check the status from the HTTP server...
- */
-
- while ((status = httpUpdate(http)) == HTTP_CONTINUE);
-
- if (status == HTTP_OK)
+ if (ipp_status > IPP_OK_CONFLICT)
{
- response = ippNew();
- ippRead(http, response);
-
- if ((ipp_status = response->request.status.status_code) > IPP_OK_CONFLICT)
+ if (ipp_status != IPP_SERVICE_UNAVAILABLE &&
+ ipp_status != IPP_PRINTER_BUSY)
{
- if (ipp_status == IPP_SERVICE_UNAVAILABLE ||
- ipp_status == IPP_PRINTER_BUSY)
- {
- fputs("INFO: Printer is busy; retrying print job...\n", stderr);
- sleep(10);
- }
- else
- {
- fprintf(stderr, "ERROR: Print file was not accepted (%04x)!\n",
- response->request.status.status_code);
- fprintf(stderr, "ERROR: %s\n", ippErrorString(ipp_status));
- }
+ if (response)
+ ippDelete(response);
+
+ fprintf(stderr, "ERROR: Unable to get job %d attributes (%s)!\n",
+ job_id, ippErrorString(ipp_status));
+ break;
}
- else if ((job_id = ippFindAttribute(response, "job-id", IPP_TAG_INTEGER)) == NULL)
- fputs("INFO: Print file accepted - job ID unknown.\n", stderr);
- else
- fprintf(stderr, "INFO: Print file accepted - job ID %d.\n",
- job_id->values[0].integer);
}
- else
+ else if ((job_state = ippFindAttribute(response, "job-state", IPP_TAG_ENUM)) != NULL)
{
- response = NULL;
- ipp_status = IPP_PRINTER_BUSY;
+ /*
+ * Stop polling if the job is finished...
+ */
- if (status == HTTP_ERROR)
+ if (job_state->values[0].integer > IPP_JOB_PROCESSING)
{
- fprintf(stderr, "WARNING: Did not receive the IPP response (%d)\n",
- errno);
- status = HTTP_OK;
+ ippDelete(response);
+ break;
}
- else
- fprintf(stderr, "ERROR: Print request was not accepted (%d)!\n", status);
}
- httpFlush(http);
-
- break;
- }
+ /*
+ * Wait 10 seconds before polling again...
+ */
- if (request != NULL)
- ippDelete(request);
- if (response != NULL)
- ippDelete(response);
+ if (response)
+ ippDelete(response);
- if (ipp_status <= IPP_OK_CONFLICT)
- {
- fprintf(stderr, "PAGE: 1 %d\n", copies_sup ? atoi(argv[4]) : 1);
- copies --;
+ sleep(10);
}
- else if (ipp_status != IPP_SERVICE_UNAVAILABLE &&
- ipp_status != IPP_PRINTER_BUSY)
- break;
}
/*
* Close and remove the temporary file if necessary...
*/
- fclose(fp);
-
if (argc < 7)
unlink(filename);
* Return the queue status...
*/
- return (status != HTTP_OK);
+ if (ipp_status <= IPP_OK_CONFLICT)
+ fputs("INFO: " CUPS_SVERSION " is ready to print.\n", stderr);
+
+ return (ipp_status > IPP_OK_CONFLICT);
+}
+
+
+/*
+ * 'password_cb()' - Disable the password prompt for cupsDoFileRequest().
+ */
+
+const char * /* O - Password */
+password_cb(const char *prompt) /* I - Prompt (not used) */
+{
+ (void)prompt;
+
+ return (password);
}
/*
- * End of "$Id: ipp.c,v 1.38 2001/02/14 13:59:45 mike Exp $".
+ * End of "$Id: ipp.c,v 1.38.2.1 2001/05/13 18:37:59 mike Exp $".
*/
/*
- * "$Id: socket.c,v 1.17 2001/01/24 17:14:01 mike Exp $"
+ * "$Id: socket.c,v 1.17.2.1 2001/05/13 18:37:59 mike Exp $"
*
* AppSocket backend for the Common UNIX Printing System (CUPS).
*
* Check for possible data coming back from the printer...
*/
- timeout.tv_sec = 0;
+ timeout.tv_sec = 0;
timeout.tv_usec = 0;
+
FD_ZERO(&input);
FD_SET(fd, &input);
+#ifdef __hpux
+ if (select(fd + 1, (int *)&input, NULL, NULL, &timeout) > 0)
+#else
if (select(fd + 1, &input, NULL, NULL, &timeout) > 0)
+#endif /* __hpux */
{
/*
* Grab the data coming back and spit it out to stderr...
fprintf(stderr, "INFO: Sending print file, %u bytes...\n", tbytes);
}
+ /*
+ * Shutdown the socket and wait for the other end to finish...
+ */
+
+ fputs("INFO: Print file sent, waiting for printer to finish...\n", stderr);
+
+ shutdown(fd, 1);
+
+ for (;;)
+ {
+ /*
+ * Wait a maximum of 90 seconds for backchannel data or a closed
+ * connection...
+ */
+
+ timeout.tv_sec = 90;
+ timeout.tv_usec = 0;
+
+ FD_ZERO(&input);
+ FD_SET(fd, &input);
+
+#ifdef __hpux
+ if (select(fd + 1, (int *)&input, NULL, NULL, &timeout) > 0)
+#else
+ if (select(fd + 1, &input, NULL, NULL, &timeout) > 0)
+#endif /* __hpux */
+ {
+ /*
+ * Grab the data coming back and spit it out to stderr...
+ */
+
+ if ((nbytes = recv(fd, buffer, sizeof(buffer), 0)) > 0)
+ fprintf(stderr, "INFO: Received %u bytes of back-channel data!\n",
+ nbytes);
+ else
+ break;
+ }
+ else
+ break;
+ }
+
/*
* Close the socket connection...
*/
if (fp != stdin)
fclose(fp);
+ fputs("INFO: " CUPS_SVERSION " is ready to print.\n", stderr);
+
return (0);
}
/*
- * End of "$Id: socket.c,v 1.17 2001/01/24 17:14:01 mike Exp $".
+ * End of "$Id: socket.c,v 1.17.2.1 2001/05/13 18:37:59 mike Exp $".
*/
/*
- * "$Id: lpc.c,v 1.11 2001/02/13 20:37:42 mike Exp $"
+ * "$Id: lpc.c,v 1.11.2.1 2001/05/13 18:37:59 mike Exp $"
*
* "lpc" command for the Common UNIX Printing System (CUPS).
*
* Connect to the scheduler...
*/
- http = httpConnect(cupsServer(), ippPort());
+ http = httpConnectEncrypt(cupsServer(), ippPort(), cupsEncryption());
if (argc > 1)
{
/*
- * End of "$Id: lpc.c,v 1.11 2001/02/13 20:37:42 mike Exp $".
+ * End of "$Id: lpc.c,v 1.11.2.1 2001/05/13 18:37:59 mike Exp $".
*/
/*
- * "$Id: lpq.c,v 1.17 2001/02/13 20:37:42 mike Exp $"
+ * "$Id: lpq.c,v 1.17.2.1 2001/05/13 18:38:00 mike Exp $"
*
* "lpq" command for the Common UNIX Printing System (CUPS).
*
* Connect to the scheduler...
*/
- if ((http = httpConnect(cupsServer(), ippPort())) == NULL)
+ if ((http = httpConnectEncrypt(cupsServer(), ippPort(),
+ cupsEncryption())) == NULL)
{
fputs("lpq: Unable to contact server!\n", stderr);
return (1);
/*
- * End of "$Id: lpq.c,v 1.17 2001/02/13 20:37:42 mike Exp $".
+ * End of "$Id: lpq.c,v 1.17.2.1 2001/05/13 18:38:00 mike Exp $".
*/
/*
- * "$Id: lpr.c,v 1.20 2001/02/13 20:37:43 mike Exp $"
+ * "$Id: lpr.c,v 1.20.2.1 2001/05/13 18:38:00 mike Exp $"
*
* "lpr" command for the Common UNIX Printing System (CUPS).
*
int deletefile; /* Delete file after print? */
char buffer[8192]; /* Copy buffer */
int temp; /* Temporary file descriptor */
-#ifdef HAVE_SIGACTION
+#if defined(HAVE_SIGACTION) && !defined(HAVE_SIGSET)
struct sigaction action; /* Signal action */
-#endif /* HAVE_SIGACTION */
+#endif /* HAVE_SIGACTION && !HAVE_SIGSET */
deletefile = 0;
/*
- * End of "$Id: lpr.c,v 1.20 2001/02/13 20:37:43 mike Exp $".
+ * End of "$Id: lpr.c,v 1.20.2.1 2001/05/13 18:38:00 mike Exp $".
*/
/*
- * "$Id: lprm.c,v 1.15 2001/03/02 17:35:03 mike Exp $"
+ * "$Id: lprm.c,v 1.15.2.1 2001/05/13 18:38:00 mike Exp $"
*
* "lprm" command for the Common UNIX Printing System (CUPS).
*
* Open a connection to the server...
*/
- if ((http = httpConnect(cupsServer(), ippPort())) == NULL)
+ if ((http = httpConnectEncrypt(cupsServer(), ippPort(), encryption)) == NULL)
{
fputs("lprm: Unable to contact server!\n", stderr);
cupsFreeDests(num_dests, dests);
return (1);
}
- httpEncryption(http, encryption);
-
/*
* Process command-line arguments...
*/
/*
- * End of "$Id: lprm.c,v 1.15 2001/03/02 17:35:03 mike Exp $".
+ * End of "$Id: lprm.c,v 1.15.2.1 2001/05/13 18:38:00 mike Exp $".
*/
/*
- * "$Id: admin.c,v 1.22 2001/03/05 21:37:33 mike Exp $"
+ * "$Id: admin.c,v 1.22.2.1 2001/05/13 18:38:01 mike Exp $"
*
* Administration CGI for the Common UNIX Printing System (CUPS).
*
* Connect to the HTTP server...
*/
- http = httpConnect("localhost", ippPort());
+ http = httpConnectEncrypt("localhost", ippPort(), cupsEncryption());
/*
* Do the operation...
/*
- * End of "$Id: admin.c,v 1.22 2001/03/05 21:37:33 mike Exp $".
+ * End of "$Id: admin.c,v 1.22.2.1 2001/05/13 18:38:01 mike Exp $".
*/
/*
- * "$Id: classes.c,v 1.18 2001/01/22 15:03:22 mike Exp $"
+ * "$Id: classes.c,v 1.18.2.1 2001/05/13 18:38:01 mike Exp $"
*
* Class status CGI for the Common UNIX Printing System (CUPS).
*
* Connect to the HTTP server...
*/
- http = httpConnect("localhost", ippPort());
+ http = httpConnectEncrypt("localhost", ippPort(), cupsEncryption());
/*
* Tell the client to expect HTML...
/*
- * End of "$Id: classes.c,v 1.18 2001/01/22 15:03:22 mike Exp $".
+ * End of "$Id: classes.c,v 1.18.2.1 2001/05/13 18:38:01 mike Exp $".
*/
/*
- * "$Id: jobs.c,v 1.15 2001/01/22 15:03:22 mike Exp $"
+ * "$Id: jobs.c,v 1.15.2.1 2001/05/13 18:38:01 mike Exp $"
*
* Job status CGI for the Common UNIX Printing System (CUPS).
*
* Connect to the HTTP server...
*/
- http = httpConnect("localhost", ippPort());
+ http = httpConnectEncrypt("localhost", ippPort(), cupsEncryption());
/*
* Tell the client to expect HTML...
/*
- * End of "$Id: jobs.c,v 1.15 2001/01/22 15:03:22 mike Exp $".
+ * End of "$Id: jobs.c,v 1.15.2.1 2001/05/13 18:38:01 mike Exp $".
*/
/*
- * "$Id: printers.c,v 1.21 2001/01/22 15:03:22 mike Exp $"
+ * "$Id: printers.c,v 1.21.2.1 2001/05/13 18:38:01 mike Exp $"
*
* Printer status CGI for the Common UNIX Printing System (CUPS).
*
* Connect to the HTTP server...
*/
- http = httpConnect("localhost", ippPort());
+ http = httpConnectEncrypt("localhost", ippPort(), cupsEncryption());
/*
* Tell the client to expect HTML...
/*
- * End of "$Id: printers.c,v 1.21 2001/01/22 15:03:22 mike Exp $".
+ * End of "$Id: printers.c,v 1.21.2.1 2001/05/13 18:38:01 mike Exp $".
*/
#
-# "$Id: mime.types,v 1.17 2001/03/05 21:37:33 mike Exp $"
+# "$Id: mime.types,v 1.17.2.1 2001/05/13 18:38:02 mike Exp $"
#
# MIME types file for the Common UNIX Printing System (CUPS).
#
application/vnd.hp-HPGL hpgl string(0,<1B>&)\
string(0,<1B>E<1B>%0B) string(0,<201B>)\
string(0,BP;) string(0,IN;) string(0,DF;) \
+ string(0,BPINPS;) \
(string(0,<1B>%-12345X) + \
(contains(9,512,"LANGUAGE=HPGL") \
contains(9,512,"LANGUAGE = HPGL")))
#application/octet-stream
#
-# End of "$Id: mime.types,v 1.17 2001/03/05 21:37:33 mike Exp $".
+# End of "$Id: mime.types,v 1.17.2.1 2001/05/13 18:38:02 mike Exp $".
#
/*
- * "$Id: config.h.in,v 1.39.2.1 2001/04/02 19:51:40 mike Exp $"
+ * "$Id: config.h.in,v 1.39.2.2 2001/05/13 18:37:58 mike Exp $"
*
* Configuration file for the Common UNIX Printing System (CUPS).
*
#undef HAVE_CRYPT_H
+/*
+ * Use <string.h>, <strings.h>, or both?
+ */
+
+#undef HAVE_STRING_H
+#undef HAVE_STRINGS_H
+
/*
* Do we have the strXXX() functions?
*/
#undef HAVE_SYS_IOCTL_H
/*
- * End of "$Id: config.h.in,v 1.39.2.1 2001/04/02 19:51:40 mike Exp $".
+ * End of "$Id: config.h.in,v 1.39.2.2 2001/05/13 18:37:58 mike Exp $".
*/
dnl
-dnl "$Id: configure.in,v 1.83.2.1 2001/04/02 19:51:41 mike Exp $"
+dnl "$Id: configure.in,v 1.83.2.2 2001/05/13 18:37:58 mike Exp $"
dnl
dnl Configuration script for the Common UNIX Printing System (CUPS).
dnl
OPTIM=""
AC_SUBST(OPTIM)
-GSOPTIM=""
-AC_SUBST(GSOPTIM)
PICFLAG=1
CFLAGS="${CFLAGS:=}"
CXXFLAGS="${CXXFLAGS:=}"
AC_ARG_ENABLE(debug, [ --enable-debug turn on debugging [default=no]],[if eval "test x$enable_debug = xyes"; then
OPTIM="-g"
- GSOPTIM="-g"
fi])
AC_ARG_ENABLE(shared, [ --enable-shared turn on shared libraries [default=yes]])
AC_ARG_ENABLE(ssl, [ --enable-ssl turn on SSL/TLS support [default=yes]])
DSO="\$(CC)"
DSOFLAGS="$DSOFLAGS -soname \$@ -shared \$(OPTIM)"
;;
+ AIX*)
+ AC_MSG_WARN(Shared library support for AIX not available yet - defaulting to static)
+ enable_shared=no
+ PICFLAG=0
+ LIBCUPS="libcups.a"
+ LIBCUPSIMAGE="libcupsimage.a"
+ DSO=":"
+ ;;
*)
echo "Warning: shared libraries may not be supported. Trying -shared"
echo " option with compiler."
AC_ARG_ENABLE(pam, [ --enable-pam turn on PAM support [default=yes]])
-AC_ARG_WITH(fontpath, [ --with-fontpath set font path for pstoraster],fontpath="$withval",fontpath="")
+# Don't use PAM with AIX...
+if test $uname = AIX; then
+ enable_pam=no
+fi
+AC_ARG_WITH(fontpath, [ --with-fontpath set font path for pstoraster],fontpath="$withval",fontpath="")
AC_ARG_WITH(docdir, [ --with-docdir set path for documentation],docdir="$withval",docdir="")
+AC_ARG_WITH(logdir, [ --with-logdir set path for log files],logdir="$withval",logdir="")
dnl Checks for programs...
AC_PROG_AWK
AC_CHECK_HEADER(shadow.h,AC_DEFINE(HAVE_SHADOW_H))
AC_CHECK_HEADER(stddef.h,AC_DEFINE(HAVE_STDDEF_H))
AC_CHECK_HEADER(stdlib.h,AC_DEFINE(HAVE_STDLIB_H))
+AC_CHECK_HEADER(string.h,AC_DEFINE(HAVE_STRING_H))
+AC_CHECK_HEADER(strings.h,AC_DEFINE(HAVE_STRINGS_H))
+AC_CHECK_HEADER(usersec.h,AC_DEFINE(HAVE_USERSEC_H))
AC_CHECK_HEADER(sys/ioctl.h,AC_DEFINE(HAVE_SYS_IOCTL_H))
dnl Checks for string functions.
dnl Update compiler options...
if test -n "$GCC"; then
- GXX="gcc"
+ CXX="$CC"
if test -z "$OPTIM"; then
OPTIM="-O2"
- GSOPTIM="-O1"
fi
if test $PICFLAG = 1; then
OPTIM="-fPIC $OPTIM"
- GSOPTIM="-fPIC $GSOPTIM"
fi
OPTIM="-Wall $OPTIM"
- GSOPTIM="-Wall $GSOPTIM"
else
case $uname in
- IRIX*)
+ AIX*)
if test -z "$OPTIM"; then
- OPTIM="-O2"
- GSOPTIM="-O1"
+ OPTIM="-O2 -qmaxmem=6000"
fi
- if test $uversion -ge 62; then
- OPTIM="$OPTIM -n32 -mips3"
- GSOPTIM="$GSOPTIM -n32 -mips3"
- fi
- OPTIM="-fullwarn $OPTIM"
- GSOPTIM="-fullwarn $GSOPTIM"
;;
HP-UX*)
if test -z "$OPTIM"; then
OPTIM="+O2"
- GSOPTIM="+O1"
fi
- OPTIM="-Ae +DAportable $OPTIM"
- GSOPTIM="-Ae +DAportable $GSOPTIM"
+ CFLAGS="-Ae $CFLAGS"
+ OPTIM="+DAportable $OPTIM"
if test $PICFLAG = 1; then
OPTIM="+z $OPTIM"
- GSOPTIM="+z $GSOPTIM"
fi
;;
+ IRIX*)
+ if test -z "$OPTIM"; then
+ OPTIM="-O2"
+ fi
+ if test $uversion -ge 62; then
+ OPTIM="$OPTIM -n32 -mips3"
+ fi
+ OPTIM="-fullwarn $OPTIM"
+ ;;
SunOS*)
# Solaris
if test -z "$OPTIM"; then
OPTIM="-xO4"
- GSOPTIM="-xO2"
fi
OPTIM="$OPTIM -xarch=generic"
- GSOPTIM="$GSOPTIM -xarch=generic"
if test $PICFLAG = 1; then
OPTIM="-KPIC $OPTIM"
- GSOPTIM="-KPIC $GSOPTIM"
fi
;;
*)
dnl Fix "mandir" variable...
if test "$mandir" = "\${prefix}/man" -a "$prefix" = "/"; then
case "$uname" in
- FreeBSD* | NetBSD* | OpenBSD*)
- # *BSD
+ FreeBSD* | NetBSD* | OpenBSD* | AIX*)
+ # *BSD + AIX
mandir="/usr/share/man"
AMANDIR="/usr/share/man"
;;
INITDDIR="../init.d"
;;
+ AIX*)
+ INITDIR="/etc/rc.d"
+ INITDDIR=".."
+ ;;
+
*)
INITDIR="/etc"
INITDDIR="../init.d"
dnl Setup default locations...
CUPS_SERVERROOT='${sysconfdir}/cups'
-CUPS_LOGDIR='${localstatedir}/log/cups'
CUPS_REQUESTS='${localstatedir}/spool/cups'
AC_DEFINE_UNQUOTED(CUPS_SERVERROOT, "$sysconfdir/cups")
-AC_DEFINE_UNQUOTED(CUPS_LOGDIR, "$localstatedir/log/cups")
AC_DEFINE_UNQUOTED(CUPS_REQUESTS, "$localstatedir/spool/cups")
+if test x$logdir = x; then
+ CUPS_LOGDIR='${localstatedir}/log/cups'
+ AC_DEFINE_UNQUOTED(CUPS_LOGDIR, "$localstatedir/log/cups")
+else
+ CUPS_LOGDIR="$logdir"
+ AC_DEFINE_UNQUOTED(CUPS_LOGDIR, "$logdir")
+fi
+
dnl See what directory to put server executables...
case "$uname" in
FreeBSD* | NetBSD* | OpenBSD*)
AC_DEFINE_UNQUOTED(CUPS_LOCALEDIR, "$datadir/locale")
;;
- OSF1*)
+ OSF1* | AIX*)
CUPS_LOCALEDIR='${exec_prefix}/lib/nls/msg'
AC_DEFINE_UNQUOTED(CUPS_LOCALEDIR, "$exec_prefix/lib/nls/msg")
;;
dnl Set the CUPS_DOCROOT directory...
if test x$docdir = x; then
CUPS_DOCROOT='${datadir}/doc/cups'
- docdir='$datadir/doc/cups'
+ docdir="$datadir/doc/cups"
else
CUPS_DOCROOT="$docdir"
fi
AC_OUTPUT(Makedefs cups.sh)
dnl
-dnl End of "$Id: configure.in,v 1.83.2.1 2001/04/02 19:51:41 mike Exp $".
+dnl End of "$Id: configure.in,v 1.83.2.2 2001/05/13 18:37:58 mike Exp $".
dnl
#
-# "$Id: cups.list,v 1.85 2001/02/21 17:01:15 mike Exp $"
+# "$Id: cups.list,v 1.85.2.1 2001/05/13 18:37:58 mike Exp $"
#
# ESP Package Manager (EPM) file list for the Common UNIX Printing
# System (CUPS).
# Man pages
%system irix
-d 0555 root sys $MANDIR/a_man -
-d 0555 root sys $MANDIR/a_man/cat1 -
-d 0555 root sys $MANDIR/u_man -
-d 0555 root sys $MANDIR/u_man/cat1 -
-d 0555 root sys $MANDIR/u_man/cat5 -
+d 0555 root sys $AMANDIR -
+d 0555 root sys $AMANDIR/cat1 -
+d 0555 root sys $MANDIR -
+d 0555 root sys $MANDIR/cat1 -
+d 0555 root sys $MANDIR/cat5 -
-f 0444 root sys $MANDIR/a_man/cat1/accept.z man/accept.z
-l 0444 root sys $MANDIR/a_man/cat1/reject.z accept.z
-f 0444 root sys $MANDIR/u_man/cat1/backend.z man/backend.z
-f 0444 root sys $MANDIR/u_man/cat5/classes.conf.z man/classes.conf.z
-f 0444 root sys $MANDIR/a_man/cat1/cups-lpd.z man/cups-lpd.z
-f 0444 root sys $MANDIR/a_man/cat1/cups-polld.z man/cups-polld.z
-f 0444 root sys $MANDIR/u_man/cat5/cupsd.conf.z man/cupsd.conf.z
-f 0444 root sys $MANDIR/a_man/cat1/cupsd.z man/cupsd.z
-f 0444 root sys $MANDIR/a_man/cat1/enable.z man/enable.z
-l 0444 root sys $MANDIR/a_man/cat1/disable.z enable.z
-f 0444 root sys $MANDIR/u_man/cat1/filter.z man/filter.z
-f 0444 root sys $MANDIR/a_man/cat1/lpadmin.z man/lpadmin.z
-f 0444 root sys $MANDIR/a_man/cat1/lpc.z man/lpc.z
-f 0444 root sys $MANDIR/a_man/cat1/lpinfo.z man/lpinfo.z
-f 0444 root sys $MANDIR/a_man/cat1/lpmove.z man/lpmove.z
-f 0444 root sys $MANDIR/u_man/cat1/lpoptions.z man/lpoptions.z
-f 0444 root sys $MANDIR/u_man/cat1/lpq.z man/lpq.z
-f 0444 root sys $MANDIR/u_man/cat1/lprm.z man/lprm.z
-f 0444 root sys $MANDIR/u_man/cat1/lpr.z man/lpr.z
-f 0444 root sys $MANDIR/u_man/cat1/lpstat.z man/lpstat.z
-f 0444 root sys $MANDIR/u_man/cat1/lp.z man/lp.z
-l 0444 root sys $MANDIR/u_man/cat1/cancel.z lp.z
-f 0444 root sys $MANDIR/u_man/cat5/mime.convs.z man/mime.convs.z
-f 0444 root sys $MANDIR/u_man/cat5/mime.types.z man/mime.types.z
-f 0444 root sys $MANDIR/u_man/cat5/printers.conf.z man/printers.conf.z
+f 0444 root sys $AMANDIR/cat1/accept.z man/accept.z
+l 0444 root sys $AMANDIR/cat1/reject.z accept.z
+f 0444 root sys $MANDIR/cat1/backend.z man/backend.z
+f 0444 root sys $MANDIR/cat5/classes.conf.z man/classes.conf.z
+f 0444 root sys $AMANDIR/cat1/cups-lpd.z man/cups-lpd.z
+f 0444 root sys $AMANDIR/cat1/cups-polld.z man/cups-polld.z
+f 0444 root sys $MANDIR/cat5/cupsd.conf.z man/cupsd.conf.z
+f 0444 root sys $AMANDIR/cat1/cupsd.z man/cupsd.z
+f 0444 root sys $AMANDIR/cat1/enable.z man/enable.z
+l 0444 root sys $AMANDIR/cat1/disable.z enable.z
+f 0444 root sys $MANDIR/cat1/filter.z man/filter.z
+f 0444 root sys $AMANDIR/cat1/lpadmin.z man/lpadmin.z
+f 0444 root sys $AMANDIR/cat1/lpc.z man/lpc.z
+f 0444 root sys $AMANDIR/cat1/lpinfo.z man/lpinfo.z
+f 0444 root sys $AMANDIR/cat1/lpmove.z man/lpmove.z
+f 0444 root sys $MANDIR/cat1/lpoptions.z man/lpoptions.z
+f 0444 root sys $MANDIR/cat1/lpq.z man/lpq.z
+f 0444 root sys $MANDIR/cat1/lprm.z man/lprm.z
+f 0444 root sys $MANDIR/cat1/lpr.z man/lpr.z
+f 0444 root sys $MANDIR/cat1/lpstat.z man/lpstat.z
+f 0444 root sys $MANDIR/cat1/lp.z man/lp.z
+l 0444 root sys $MANDIR/cat1/cancel.z lp.z
+f 0444 root sys $MANDIR/cat5/mime.convs.z man/mime.convs.z
+f 0444 root sys $MANDIR/cat5/mime.types.z man/mime.types.z
+f 0444 root sys $MANDIR/cat5/printers.conf.z man/printers.conf.z
%system solaris hpux
d 0555 root sys $MANDIR/man1 -
i 0555 root sys cups cups.sh
#
-# End of "$Id: cups.list,v 1.85 2001/02/21 17:01:15 mike Exp $".
+# End of "$Id: cups.list,v 1.85.2.1 2001/05/13 18:37:58 mike Exp $".
#
#!/bin/sh
#
-# "$Id: cups.sh.in,v 1.9 2001/03/14 22:02:17 mike Exp $"
+# "$Id: cups.sh.in,v 1.9.2.1 2001/05/13 18:37:58 mike Exp $"
#
# Startup/shutdown script for the Common UNIX Printing System (CUPS).
#
#
# Linux chkconfig stuff:
#
-# chkconfig: 0235 99 00
+# chkconfig: 235 99 00
# description: Startup/shutdown script for the Common UNIX \
# Printing System (CUPS).
#
#
case "`uname`" in
- IRIX* | HP-UX* | SunOS*)
+ IRIX* | HP-UX* | SunOS* | AIX*)
pid=`ps -e | awk '{print $1,$4}' | grep cupsd | awk '{print $1}'`
;;
OSF1*)
#
-# End of "$Id: cups.sh.in,v 1.9 2001/03/14 22:02:17 mike Exp $".
+# End of "$Id: cups.sh.in,v 1.9.2.1 2001/05/13 18:37:58 mike Exp $".
#
#
-# "$Id: cups.spec,v 1.30 2001/03/06 18:37:49 mike Exp $"
+# "$Id: cups.spec,v 1.30.2.1 2001/05/13 18:37:58 mike Exp $"
#
# RPM "spec" file for the Common UNIX Printing System (CUPS).
#
Summary: Common Unix Printing System
Name: cups
Version: 1.1.7
-Release: 0
+Release: 1
Copyright: GPL
Group: System Environment/Daemons
Source: ftp://ftp.easysw.com/pub/cups/%{version}/cups-%{version}-source.tar.gz
# use buildroot so as not to disturb the version already installed
BuildRoot: /var/tmp/%{name}-root
Conflicts: lpr, LPRng
+Provides: libcups.so.2
+Provides: libcupsimage.so.2
+Provides: cupsd
%package devel
Summary: Common Unix Printing System - development environment
Group: Development/Libraries
+%package pstoraster
+Summary: Common Unix Printing System - PostScript RIP
+Group: System Environment/Daemons
+Provides: pstoraster
+
%description
The Common UNIX Printing System provides a portable printing layer for
UNIX® operating systems. It has been developed by Easy Software Products
UNIX® operating systems. This is the development package for creating
additional printer drivers, and other CUPS services.
+%description devel
+The Common UNIX Printing System provides a portable printing layer for
+UNIX® operating systems. This is the PostScript RIP package for
+supporting non-PostScript printer drivers.
+
%prep
%setup
make
%install
-# these lines just make sure the directory structure in the
-# RPM_BUILD_ROOT exists
+# Make sure the RPM_BUILD_ROOT directory exists.
rm -rf $RPM_BUILD_ROOT
-mkdir -p $RPM_BUILD_ROOT/etc/rc.d/init.d
-mkdir -p $RPM_BUILD_ROOT/etc/rc.d/rc0.d
-mkdir -p $RPM_BUILD_ROOT/etc/rc.d/rc3.d
-mkdir -p $RPM_BUILD_ROOT/etc/rc.d/rc5.d
make prefix=$RPM_BUILD_ROOT \
exec_prefix=$RPM_BUILD_ROOT/usr \
DOCDIR=$RPM_BUILD_ROOT/usr/share/doc/cups \
INCLUDEDIR=$RPM_BUILD_ROOT/usr/include \
LIBDIR=$RPM_BUILD_ROOT/usr/lib \
+ LOGDIR=$RPM_BUILD_ROOT/var/log/cups \
LOCALEDIR=$RPM_BUILD_ROOT/usr/share/locale \
MANDIR=$RPM_BUILD_ROOT/usr/man \
PAMDIR=$RPM_BUILD_ROOT/etc/pam.d \
/usr/bin/*
/usr/lib/*.so*
%dir /usr/lib/cups
-/usr/lib/cups/*
+%dir /usr/lib/cups/backend
+/usr/lib/cups/backend/*
+%dir /usr/lib/cups/cgi-bin
+/usr/lib/cups/cgi-bin/*
+%dir /usr/lib/cups/filter
+/usr/lib/cups/filter/hpgltops
+/usr/lib/cups/filter/imagetops
+/usr/lib/cups/filter/imagetoraster
+/usr/lib/cups/filter/pdftops
+/usr/lib/cups/filter/pstops
+/usr/lib/cups/filter/rastertoepson
+/usr/lib/cups/filter/rastertohp
+/usr/lib/cups/filter/texttops
/usr/man/*
/usr/sbin/*
%dir /usr/share/cups
-/usr/share/cups/*
+%dir /usr/share/cups/banners
+/usr/share/cups/banners/*
+%dir /usr/share/cups/charsets
+/usr/share/cups/charsets/*
+%dir /usr/share/cups/data
+/usr/share/cups/data/*
+%dir /usr/share/cups/model
+/usr/share/cups/model/*
+%dir /usr/share/cups/templates
+/usr/share/cups/templates/*
%dir /usr/share/doc/cups
/usr/share/doc/cups/*
%dir /usr/share/locale
/usr/include/cups/*
/usr/lib/*.a
+%files pstoraster
+%dir /usr/lib/cups/filter
+/usr/lib/cups/filter/pstoraster
+%dir /usr/share/cups/fonts
+/usr/share/cups/fonts/*
+%dir /usr/share/cups/pstoraster
+/usr/share/cups/pstoraster/*
+
#
-# End of "$Id: cups.spec,v 1.30 2001/03/06 18:37:49 mike Exp $".
+# End of "$Id: cups.spec,v 1.30.2.1 2001/05/13 18:37:58 mike Exp $".
#
/*
- * "$Id: cups.h,v 1.32 2001/02/06 23:40:07 mike Exp $"
+ * "$Id: cups.h,v 1.32.2.1 2001/05/13 18:38:02 mike Exp $"
*
* API definitions for the Common UNIX Printing System (CUPS).
*
cups_option_t *options; /* Options */
} cups_dest_t;
-
+typedef struct /**** Job ****/
+{
+ int id; /* The job ID */
+ char *dest, /* Printer or class name */
+ *title, /* Title/job name */
+ *user, /* User the submitted the job */
+ *format; /* Document format */
+ ipp_jstate_t state; /* Job state */
+ int size, /* Size in kilobytes */
+ priority; /* Priority (1-100) */
+ time_t completed_time, /* Time the job was completed */
+ creation_time, /* Time the job was created */
+ processing_time; /* Time the job was processed */
+} cups_job_t;
+
+
/*
* Functions...
*/
extern ipp_t *cupsDoFileRequest(http_t *http, ipp_t *request,
const char *resource, const char *filename);
extern http_encryption_t cupsEncryption(void);
+extern void cupsFreeJobs(int num_jobs, cups_job_t *jobs);
extern int cupsGetClasses(char ***classes);
extern const char *cupsGetDefault(void);
+extern int cupsGetJobs(cups_job_t **jobs, const char *dest,
+ int myjobs, int completed);
extern const char *cupsGetPPD(const char *printer);
extern int cupsGetPrinters(char ***printers);
extern ipp_status_t cupsLastError(void);
#endif /* !_CUPS_CUPS_H_ */
/*
- * End of "$Id: cups.h,v 1.32 2001/02/06 23:40:07 mike Exp $".
+ * End of "$Id: cups.h,v 1.32.2.1 2001/05/13 18:38:02 mike Exp $".
*/
/*
- * "$Id: encode.c,v 1.1 2001/03/09 20:06:06 mike Exp $"
+ * "$Id: encode.c,v 1.1.2.1 2001/05/13 18:38:02 mike Exp $"
*
* Option encoding routines for the Common UNIX Printing System (CUPS).
*
*/
if (strcasecmp(options[i].name, "raw") == 0 ||
- strcasecmp(options[i].name, "document-format") == 0)
+ strcasecmp(options[i].name, "document-format") == 0 ||
+ !options[i].name[0])
continue;
/*
/*
- * End of "$Id: encode.c,v 1.1 2001/03/09 20:06:06 mike Exp $".
+ * End of "$Id: encode.c,v 1.1.2.1 2001/05/13 18:38:02 mike Exp $".
*/
/*
- * "$Id: http.c,v 1.82.2.1 2001/04/02 19:51:43 mike Exp $"
+ * "$Id: http.c,v 1.82.2.2 2001/05/13 18:38:03 mike Exp $"
*
* HTTP routines for the Common UNIX Printing System (CUPS).
*
*
* Contents:
*
- * httpInitialize() - Initialize the HTTP interface library and set the
- * default HTTP proxy (if any).
- * httpCheck() - Check to see if there is a pending response from
- * the server.
- * httpClose() - Close an HTTP connection...
- * httpConnect() - Connect to a HTTP server.
- * httpEncryption() - Set the required encryption on the link.
- * httpReconnect() - Reconnect to a HTTP server...
- * httpSeparate() - Separate a Universal Resource Identifier into its
- * components.
- * httpSetField() - Set the value of an HTTP header.
- * httpDelete() - Send a DELETE request to the server.
- * httpGet() - Send a GET request to the server.
- * httpHead() - Send a HEAD request to the server.
- * httpOptions() - Send an OPTIONS request to the server.
- * httpPost() - Send a POST request to the server.
- * httpPut() - Send a PUT request to the server.
- * httpTrace() - Send an TRACE request to the server.
- * httpFlush() - Flush data from a HTTP connection.
- * httpRead() - Read data from a HTTP connection.
- * httpWrite() - Write data to a HTTP connection.
- * httpGets() - Get a line of text from a HTTP connection.
- * httpPrintf() - Print a formatted string to a HTTP connection.
- * httpStatus() - Return a short string describing a HTTP status code.
- * httpGetDateString() - Get a formatted date/time string from a time value.
- * httpGetDateTime() - Get a time value from a formatted date/time string.
- * httpUpdate() - Update the current HTTP state for incoming data.
- * httpDecode64() - Base64-decode a string.
- * httpEncode64() - Base64-encode a string.
- * httpGetLength() - Get the amount of data remaining from the
- * content-length or transfer-encoding fields.
- * http_field() - Return the field index for a field name.
- * http_send() - Send a request with all fields and the trailing
- * blank line.
- * http_upgrade() - Force upgrade to TLS encryption.
+ * httpInitialize() - Initialize the HTTP interface library and set the
+ * default HTTP proxy (if any).
+ * httpCheck() - Check to see if there is a pending response from
+ * the server.
+ * httpClose() - Close an HTTP connection...
+ * httpConnect() - Connect to a HTTP server.
+ * httpConnectEncrypt() - Connect to a HTTP server using encryption.
+ * httpEncryption() - Set the required encryption on the link.
+ * httpReconnect() - Reconnect to a HTTP server...
+ * httpSeparate() - Separate a Universal Resource Identifier into its
+ * components.
+ * httpSetField() - Set the value of an HTTP header.
+ * httpDelete() - Send a DELETE request to the server.
+ * httpGet() - Send a GET request to the server.
+ * httpHead() - Send a HEAD request to the server.
+ * httpOptions() - Send an OPTIONS request to the server.
+ * httpPost() - Send a POST request to the server.
+ * httpPut() - Send a PUT request to the server.
+ * httpTrace() - Send an TRACE request to the server.
+ * httpFlush() - Flush data from a HTTP connection.
+ * httpRead() - Read data from a HTTP connection.
+ * httpWrite() - Write data to a HTTP connection.
+ * httpGets() - Get a line of text from a HTTP connection.
+ * httpPrintf() - Print a formatted string to a HTTP connection.
+ * httpStatus() - Return a short string describing a HTTP status code.
+ * httpGetDateString() - Get a formatted date/time string from a time value.
+ * httpGetDateTime() - Get a time value from a formatted date/time string.
+ * httpUpdate() - Update the current HTTP state for incoming data.
+ * httpDecode64() - Base64-decode a string.
+ * httpEncode64() - Base64-encode a string.
+ * httpGetLength() - Get the amount of data remaining from the
+ * content-length or transfer-encoding fields.
+ * http_field() - Return the field index for a field name.
+ * http_send() - Send a request with all fields and the trailing
+ * blank line.
+ * http_upgrade() - Force upgrade to TLS encryption.
*/
/*
http_t * /* O - New HTTP connection */
httpConnect(const char *host, /* I - Host to connect to */
int port) /* I - Port number */
+{
+ http_encryption_t encrypt;/* Type of encryption to use */
+
+
+ /*
+ * Set the default encryption status...
+ */
+
+ if (port == 443)
+ encrypt = HTTP_ENCRYPT_ALWAYS;
+ else
+ encrypt = HTTP_ENCRYPT_IF_REQUESTED;
+
+ return (httpConnectEncrypt(host, port, encrypt));
+}
+
+
+/*
+ * 'httpConnectEncrypt()' - Connect to a HTTP server using encryption.
+ */
+
+http_t * /* O - New HTTP connection */
+httpConnectEncrypt(const char *host, /* I - Host to connect to */
+ int port, /* I - Port number */
+ http_encryption_t encrypt)
+ /* I - Type of encryption to use */
{
int i; /* Looping var */
http_t *http; /* New HTTP connection */
http->encryption = HTTP_ENCRYPT_ALWAYS;
}
+ /*
+ * Set the encryption status...
+ */
+
+ http->encryption = encrypt;
+
/*
* Loop through the addresses we have until one of them connects...
*/
/*
- * End of "$Id: http.c,v 1.82.2.1 2001/04/02 19:51:43 mike Exp $".
+ * End of "$Id: http.c,v 1.82.2.2 2001/05/13 18:38:03 mike Exp $".
*/
/*
- * "$Id: http.h,v 1.33.2.1 2001/04/02 19:51:43 mike Exp $"
+ * "$Id: http.h,v 1.33.2.2 2001/05/13 18:38:03 mike Exp $"
*
* Hyper-Text Transport Protocol definitions for the Common UNIX Printing
* System (CUPS).
httpSetField((http), HTTP_FIELD_HOST, (http)->hostname)
extern void httpClose(http_t *http);
extern http_t *httpConnect(const char *host, int port);
+extern http_t *httpConnectEncrypt(const char *host, int port,
+ http_encryption_t encrypt);
extern int httpDelete(http_t *http, const char *uri);
extern int httpEncryption(http_t *http, http_encryption_t e);
# define httpError(http) ((http)->error)
#endif /* !_CUPS_HTTP_H_ */
/*
- * End of "$Id: http.h,v 1.33.2.1 2001/04/02 19:51:43 mike Exp $".
+ * End of "$Id: http.h,v 1.33.2.2 2001/05/13 18:38:03 mike Exp $".
*/
/*
- * "$Id: ipp.c,v 1.55.2.1 2001/04/02 19:51:44 mike Exp $"
+ * "$Id: ipp.c,v 1.55.2.2 2001/05/13 18:38:03 mike Exp $"
*
* Internet Printing Protocol support functions for the Common UNIX
* Printing System (CUPS).
DEBUG_printf(("ippFindAttribute: attr = %p, name = \'%s\'\n", attr,
attr->name));
- value_tag = attr->value_tag & ~IPP_TAG_COPY;
+ value_tag = (ipp_tag_t)(attr->value_tag & IPP_TAG_MASK);
if (attr->name != NULL && strcasecmp(attr->name, name) == 0 &&
(value_tag == type || type == IPP_TAG_ZERO ||
/*
- * End of "$Id: ipp.c,v 1.55.2.1 2001/04/02 19:51:44 mike Exp $".
+ * End of "$Id: ipp.c,v 1.55.2.2 2001/05/13 18:38:03 mike Exp $".
*/
/*
- * "$Id: ipp.h,v 1.36.2.1 2001/04/02 19:51:44 mike Exp $"
+ * "$Id: ipp.h,v 1.36.2.2 2001/05/13 18:38:04 mike Exp $"
*
* Internet Printing Protocol definitions for the Common UNIX Printing
* System (CUPS).
IPP_TAG_LANGUAGE,
IPP_TAG_MIMETYPE,
IPP_TAG_MEMBERNAME,
- IPP_TAG_COPY = 0x80000000 /* Bitflag for copied attribute values */
+ IPP_TAG_MASK = 0x3fffffff, /* Mask for copied attribute values */
+ IPP_TAG_COPY = 0x40000000 /* Bitflag for copied attribute values */
} ipp_tag_t;
typedef enum /**** Resolution units... ****/
#endif /* !_CUPS_IPP_H_ */
/*
- * End of "$Id: ipp.h,v 1.36.2.1 2001/04/02 19:51:44 mike Exp $".
+ * End of "$Id: ipp.h,v 1.36.2.2 2001/05/13 18:38:04 mike Exp $".
*/
/*
- * "$Id: options.c,v 1.21 2001/03/09 20:06:07 mike Exp $"
+ * "$Id: options.c,v 1.21.2.1 2001/05/13 18:38:04 mike Exp $"
*
* Option routines for the Common UNIX Printing System (CUPS).
*
cups_option_t *temp; /* Pointer to new option */
- if (name == NULL || value == NULL || options == NULL || num_options < 0)
- return (0);
+ if (name == NULL || !name[0] || value == NULL ||
+ options == NULL || num_options < 0)
+ return (num_options);
/*
* Look for an existing option with the same name...
while (!isspace(*ptr) && *ptr != '=' && *ptr != '\0')
ptr ++;
+ /*
+ * Avoid an empty name...
+ */
+
+ if (ptr == name)
+ break;
+
/*
* Skip trailing spaces...
*/
/*
- * End of "$Id: options.c,v 1.21 2001/03/09 20:06:07 mike Exp $".
+ * End of "$Id: options.c,v 1.21.2.1 2001/05/13 18:38:04 mike Exp $".
*/
/*
- * "$Id: ppd.c,v 1.51.2.1 2001/04/11 00:24:11 mike Exp $"
+ * "$Id: ppd.c,v 1.51.2.2 2001/05/13 18:38:04 mike Exp $"
*
* PPD file routines for the Common UNIX Printing System (CUPS).
*
* 'compare_strings()' - Compare two strings.
*/
-int /* O - Result of comparison */
+static int /* O - Result of comparison */
compare_strings(char *s, /* I - First string */
char *t) /* I - Second string */
{
/*
- * End of "$Id: ppd.c,v 1.51.2.1 2001/04/11 00:24:11 mike Exp $".
+ * End of "$Id: ppd.c,v 1.51.2.2 2001/05/13 18:38:04 mike Exp $".
*/
/*
- * "$Id: string.h,v 1.7 2001/01/22 15:03:31 mike Exp $"
+ * "$Id: string.h,v 1.7.2.1 2001/05/13 18:38:05 mike Exp $"
*
* String definitions for the Common UNIX Printing System (CUPS).
*
# include <stdio.h>
# include <stdarg.h>
# include <config.h>
-# include <string.h>
+
+# ifdef HAVE_STRING_H
+# include <string.h>
+# endif /* HAVE_STRING_H */
+
+# ifdef HAVE_STRINGS_H
+# include <strings.h>
+# endif /* HAVE_STRINGS_H */
/*
#endif /* !_CUPS_STRING_H_ */
/*
- * End of "$Id: string.h,v 1.7 2001/01/22 15:03:31 mike Exp $".
+ * End of "$Id: string.h,v 1.7.2.1 2001/05/13 18:38:05 mike Exp $".
*/
/*
- * "$Id: util.c,v 1.81.2.1 2001/04/02 19:51:44 mike Exp $"
+ * "$Id: util.c,v 1.81.2.2 2001/05/13 18:38:05 mike Exp $"
*
* Printing utilities for the Common UNIX Printing System (CUPS).
*
*
* cupsCancelJob() - Cancel a print job.
* cupsDoFileRequest() - Do an IPP request...
+ * cupsFreeJobs() - Free memory used by job data.
* cupsGetClasses() - Get a list of printer classes.
* cupsGetDefault() - Get the default printer or class.
+ * cupsGetJobs() - Get the jobs from the server.
* cupsGetPPD() - Get the PPD file for a printer.
* cupsGetPrinters() - Get a list of printers.
* cupsLastError() - Return the last IPP error that occurred.
else
break;
}
+#ifdef HAVE_LIBSSL
+ else if (status == HTTP_UPGRADE_REQUIRED)
+ {
+ /*
+ * Flush any error message...
+ */
+
+ httpFlush(http);
+
+ /*
+ * Try again, this time with encryption enabled...
+ */
+
+ continue;
+ }
+#endif /* HAVE_LIBSSL */
else if (status != HTTP_OK)
{
DEBUG_printf(("cupsDoFileRequest: error %d...\n", status));
}
+/*
+ * 'cupsFreeJobs()' - Free memory used by job data.
+ */
+
+void
+cupsFreeJobs(int num_jobs,/* I - Number of jobs */
+ cups_job_t *jobs) /* I - Jobs */
+{
+ int i; /* Looping var */
+
+
+ if (num_jobs <= 0 || jobs == NULL)
+ return;
+
+ for (i = 0; i < num_jobs; i ++)
+ {
+ free(jobs[i].dest);
+ free(jobs[i].user);
+ free(jobs[i].format);
+ free(jobs[i].title);
+ }
+
+ free(jobs);
+}
+
+
/*
* 'cupsGetClasses()' - Get a list of printer classes.
*/
}
+/*
+ * 'cupsGetJobs()' - Get the jobs from the server.
+ */
+
+int /* O - Number of jobs */
+cupsGetJobs(cups_job_t **jobs, /* O - Job data */
+ const char *mydest, /* I - Only show jobs for dest? */
+ int myjobs, /* I - Only show my jobs? */
+ int completed) /* I - Only show completed jobs? */
+{
+ int n; /* Number of jobs */
+ ipp_t *request, /* IPP Request */
+ *response; /* IPP Response */
+ ipp_attribute_t *attr; /* Current attribute */
+ cups_lang_t *language; /* Default language */
+ cups_job_t *temp; /* Temporary pointer */
+ int id, /* job-id */
+ priority, /* job-priority */
+ size; /* job-k-octets */
+ ipp_jstate_t state; /* job-state */
+ time_t completed_time, /* time-at-completed */
+ creation_time, /* time-at-creation */
+ processing_time; /* time-at-processing */
+ const char *dest, /* job-printer-uri */
+ *format, /* document-format */
+ *title, /* job-name */
+ *user; /* job-originating-user-name */
+ char uri[HTTP_MAX_URI]; /* URI for jobs */
+ static const char *attrs[] = /* Requested attributes */
+ {
+ "job-id",
+ "job-priority",
+ "job-k-octets",
+ "job-state",
+ "time-at-completed",
+ "time-at-creation",
+ "time-at-processing",
+ "job-printer-uri",
+ "document-format",
+ "job-name",
+ "job-originating-user-name"
+ };
+
+
+ if (jobs == NULL)
+ {
+ last_error = IPP_INTERNAL_ERROR;
+ return (0);
+ }
+
+ /*
+ * Try to connect to the server...
+ */
+
+ if (!cups_connect("default", NULL, NULL))
+ {
+ last_error = IPP_SERVICE_UNAVAILABLE;
+ return (0);
+ }
+
+ /*
+ * Build an IPP_GET_JOBS request, which requires the following
+ * attributes:
+ *
+ * attributes-charset
+ * attributes-natural-language
+ * printer-uri
+ * requesting-user-name
+ * which-jobs
+ * my-jobs
+ * requested-attributes
+ */
+
+ request = ippNew();
+
+ request->request.op.operation_id = IPP_GET_JOBS;
+ request->request.op.request_id = 1;
+
+ language = cupsLangDefault();
+
+ ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_CHARSET,
+ "attributes-charset", NULL, cupsLangEncoding(language));
+
+ ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_LANGUAGE,
+ "attributes-natural-language", NULL, language->language);
+
+ if (mydest)
+ snprintf(uri, sizeof(uri), "ipp://localhost/printers/%s", mydest);
+ else
+ strcpy(uri, "ipp://localhost/jobs");
+
+ ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI,
+ "printer-uri", NULL, uri);
+
+ ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME,
+ "requesting-user-name", NULL, cupsUser());
+
+ if (myjobs)
+ ippAddBoolean(request, IPP_TAG_OPERATION, "my-jobs", 1);
+
+ if (completed)
+ ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_KEYWORD,
+ "which-jobs", NULL, "completed");
+
+ ippAddStrings(request, IPP_TAG_OPERATION, IPP_TAG_KEYWORD,
+ "requested-attributes", sizeof(attrs) / sizeof(attrs[0]),
+ NULL, attrs);
+
+ /*
+ * Do the request and get back a response...
+ */
+
+ n = 0;
+ *jobs = NULL;
+
+ if ((response = cupsDoRequest(cups_server, request, "/")) != NULL)
+ {
+ last_error = response->request.status.status_code;
+
+ for (attr = response->attrs; attr != NULL; attr = attr->next)
+ {
+ /*
+ * Skip leading attributes until we hit a job...
+ */
+
+ while (attr != NULL && attr->group_tag != IPP_TAG_JOB)
+ attr = attr->next;
+
+ if (attr == NULL)
+ break;
+
+ /*
+ * Pull the needed attributes from this job...
+ */
+
+ id = 0;
+ size = 0;
+ priority = 50;
+ state = IPP_JOB_PENDING;
+ user = NULL;
+ dest = NULL;
+ format = NULL;
+ title = NULL;
+ creation_time = 0;
+ completed_time = 0;
+ processing_time = 0;
+
+ while (attr != NULL && attr->group_tag == IPP_TAG_JOB)
+ {
+ if (strcmp(attr->name, "job-id") == 0 &&
+ attr->value_tag == IPP_TAG_INTEGER)
+ id = attr->values[0].integer;
+ else if (strcmp(attr->name, "job-state") == 0 &&
+ attr->value_tag == IPP_TAG_ENUM)
+ state = (ipp_jstate_t)attr->values[0].integer;
+ else if (strcmp(attr->name, "job-priority") == 0 &&
+ attr->value_tag == IPP_TAG_INTEGER)
+ priority = attr->values[0].integer;
+ else if (strcmp(attr->name, "job-k-octets") == 0 &&
+ attr->value_tag == IPP_TAG_INTEGER)
+ size = attr->values[0].integer;
+ else if (strcmp(attr->name, "time-at-completed") == 0 &&
+ attr->value_tag == IPP_TAG_INTEGER)
+ completed_time = attr->values[0].integer;
+ else if (strcmp(attr->name, "time-at-creation") == 0 &&
+ attr->value_tag == IPP_TAG_INTEGER)
+ creation_time = attr->values[0].integer;
+ else if (strcmp(attr->name, "time-at-processing") == 0 &&
+ attr->value_tag == IPP_TAG_INTEGER)
+ processing_time = attr->values[0].integer;
+ else if (strcmp(attr->name, "job-printer-uri") == 0 &&
+ attr->value_tag == IPP_TAG_URI)
+ {
+ if ((dest = strrchr(attr->values[0].string.text, '/')) != NULL)
+ dest ++;
+ }
+ else if (strcmp(attr->name, "job-originating-user-name") == 0 &&
+ attr->value_tag == IPP_TAG_NAME)
+ user = attr->values[0].string.text;
+ else if (strcmp(attr->name, "document-format") == 0 &&
+ attr->value_tag == IPP_TAG_MIMETYPE)
+ format = attr->values[0].string.text;
+ else if (strcmp(attr->name, "job-name") == 0 &&
+ attr->value_tag == IPP_TAG_TEXT)
+ title = attr->values[0].string.text;
+
+ attr = attr->next;
+ }
+
+ /*
+ * See if we have everything needed...
+ */
+
+ if (dest == NULL || format == NULL || title == NULL || user == NULL ||
+ id == 0)
+ {
+ if (attr == NULL)
+ break;
+ else
+ continue;
+ }
+
+ /*
+ * Allocate memory for the job...
+ */
+
+ if (n == 0)
+ temp = malloc(sizeof(cups_job_t));
+ else
+ temp = realloc(*jobs, sizeof(cups_job_t) * (n + 1));
+
+ if (temp == NULL)
+ {
+ /*
+ * Ran out of memory!
+ */
+
+ cupsFreeJobs(n, *jobs);
+ *jobs = NULL;
+
+ ippDelete(response);
+ return (0);
+ }
+
+ *jobs = temp;
+ temp += n;
+ n ++;
+
+ /*
+ * Copy the data over...
+ */
+
+ temp->dest = strdup(dest);
+ temp->user = strdup(user);
+ temp->format = strdup(format);
+ temp->title = strdup(title);
+ temp->id = id;
+ temp->priority = priority;
+ temp->state = state;
+ temp->size = size;
+ temp->completed_time = completed_time;
+ temp->creation_time = creation_time;
+ temp->processing_time = processing_time;
+ }
+
+ ippDelete(response);
+ }
+ else
+ last_error = IPP_BAD_REQUEST;
+
+ return (n);
+}
+
+
/*
* 'cupsGetPPD()' - Get the PPD file for a printer.
*/
{
httpClose(cups_server);
- if ((cups_server = httpConnect(hostname, ippPort())) == NULL)
+ if ((cups_server = httpConnectEncrypt(hostname, ippPort(),
+ cupsEncryption())) == NULL)
{
last_error = IPP_SERVICE_UNAVAILABLE;
return (NULL);
break;
}
}
- while (status == HTTP_UNAUTHORIZED);
+ while (status == HTTP_UNAUTHORIZED || status == HTTP_UPGRADE_REQUIRED);
/*
* See if we actually got the file or an error...
/* Name of printer or class */
+ DEBUG_printf(("cups_connect(\"%s\", %p, %p)\n", name, printer, hostname));
+
if (name == NULL)
{
last_error = IPP_BAD_REQUEST;
httpClose(cups_server);
}
- if ((cups_server = httpConnect(hostname, ippPort())) == NULL)
+ DEBUG_printf(("connecting to %s on port %d...\n", hostname, ippPort()));
+
+ if ((cups_server = httpConnectEncrypt(hostname, ippPort(),
+ cupsEncryption())) == NULL)
{
last_error = IPP_SERVICE_UNAVAILABLE;
return (NULL);
}
else
- {
- httpEncryption(cups_server, cupsEncryption());
return (printer);
- }
}
/*
- * End of "$Id: util.c,v 1.81.2.1 2001/04/02 19:51:44 mike Exp $".
+ * End of "$Id: util.c,v 1.81.2.2 2001/05/13 18:38:05 mike Exp $".
*/
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" "http://www.w3.org/TR/REC-html40/loose.dtd">
<HTML>
<HEAD>
-<TITLE> CUPS Software Administrators Manual</TITLE>
+<TITLE>CUPS Software Administrators Manual</TITLE>
<META NAME="author" CONTENT="Easy Software Products">
<META NAME="copyright" CONTENT="Copyright 1997-2001, All Rights Reserved">
<META NAME="docnumber" CONTENT="CUPS-SAM-1.1.7">
<META HTTP-EQUIV="Content-Type" CONTENT="text/html; CHARSET=iso-8859-1">
<STYLE TYPE="text/css"><!--
-BODY { font-family: serif; font-size: 11.0pt }
-H1 { font-family: sans-serif; font-size: 20.0pt }
-H2 { font-family: sans-serif; font-size: 17.0pt }
-H3 { font-family: sans-serif; font-size: 14.0pt }
-H4 { font-family: sans-serif; font-size: 11.0pt }
-H5 { font-family: sans-serif; font-size: 9.0pt }
-H6 { font-family: sans-serif; font-size: 8.0pt }
-SUB { font-size: 8.0pt }
-SUP { font-size: 8.0pt }
-PRE { font-size: 9.0pt }
+BODY { font-family: serif }
+H1 { font-family: sans-serif }
+H2 { font-family: sans-serif }
+H3 { font-family: sans-serif }
+H4 { font-family: sans-serif }
+H5 { font-family: sans-serif }
+H6 { font-family: sans-serif }
+SUB { font-size: smaller }
+SUP { font-size: smaller }
+PRE { font-family: monospace }
--></STYLE>
</HEAD>
<BODY BGCOLOR="#ffffff">
-<CENTER><A HREF="#CONTENTS"><IMG SRC="images/cups-large.gif" BORDER="0" WIDTH="100%"><BR>
-<H1> CUPS Software Administrators Manual</H1></A><BR>
+<CENTER><A HREF="#CONTENTS"><IMG SRC="images/cups-large.gif" BORDER="0" WIDTH="431" HEIGHT="511"><BR>
+<H1>CUPS Software Administrators Manual</H1></A><BR>
CUPS-SAM-1.1.7<BR>
Easy Software Products<BR>
Copyright 1997-2001, All Rights Reserved<BR>
<LI><A HREF="#BrowseShortNames">BrowseShortNames</A></LI>
<LI><A HREF="#BrowseTimeout">BrowseTimeout</A></LI>
<LI><A HREF="#Browsing">Browsing</A></LI>
+<LI><A HREF="#Classification">Classification</A></LI>
<LI><A HREF="#DataDir">DataDir</A></LI>
<LI><A HREF="#DefaultCharset">DefaultCharset</A></LI>
<LI><A HREF="#DefaultLanguage">DefaultLanguage</A></LI>
<LI><A HREF="#LogLevel">LogLevel</A></LI>
<LI><A HREF="#MaxClients">MaxClients</A></LI>
<LI><A HREF="#MaxJobs">MaxJobs</A></LI>
+<LI><A HREF="#MaxJobsPerPrinter">MaxJobsPerPrinter</A></LI>
+<LI><A HREF="#MaxJobsPerUser">MaxJobsPerUser</A></LI>
<LI><A HREF="#MaxLogSize">MaxLogSize</A></LI>
<LI><A HREF="#MaxRequestSize">MaxRequestSize</A></LI>
<LI><A HREF="#Order">Order</A></LI>
EPSON printers are included that use these filters. </P>
<!-- NEED 3in -->
-
<H2><A NAME="1_2">Document Overview</A></H2>
<P>This software administrators manual is organized into the following
sections:</P>
</UL>
<!-- NEED 4in -->
-
<H2><A NAME="BINARY">Installing a Binary Distribution</A></H2>
<P>CUPS comes in a variety of binary distribution formats. Easy
Software Products provides binaries in TAR format with installation and
<LI><A HREF="#BrowseShortNames"><CODE>BrowseShortNames</CODE></A></LI>
<LI><A HREF="#BrowseTimeout"><CODE>BrowseTimeout</CODE></A></LI>
<LI><A HREF="#Browsing"><CODE>Browsing</CODE></A></LI>
+<LI><A HREF="#Classification"><CODE>Classification</CODE></A></LI>
<LI><A HREF="#DataDir"><CODE>DataDir</CODE></A></LI>
<LI><A HREF="#DefaultCharset"><CODE>DefaultCharset</CODE></A></LI>
<LI><A HREF="#DefaultLanguage"><CODE>DefaultLanguage</CODE></A></LI>
<LI><A HREF="#LogLevel"><CODE>LogLevel</CODE></A></LI>
<LI><A HREF="#MaxClients"><CODE>MaxClients</CODE></A></LI>
<LI><A HREF="#MaxJobs"><CODE>MaxJobs</CODE></A></LI>
+<LI><A HREF="#MaxJobsPerPrinter"><CODE>MaxJobsPerPrinter</CODE></A></LI>
+<LI><A HREF="#MaxJobsPerUser"><CODE>MaxJobsPerUser</CODE></A></LI>
<LI><A HREF="#MaxLogSize"><CODE>MaxLogSize</CODE></A></LI>
<LI><A HREF="#MaxRequestSize"><CODE>MaxRequestSize</CODE></A></LI>
<LI><A HREF="#Order"><CODE>Order</CODE></A></LI>
<LI><A HREF="#PageLog"><CODE>PageLog</CODE></A></LI>
-<LI><A HREF="#Port"><CODE>Port</CODE></A></LI>
</TD><TD VALIGN="TOP"> </TD><TD VALIGN="TOP">
+<LI><A HREF="#Port"><CODE>Port</CODE></A></LI>
<LI><A HREF="#PreserveJobFiles"><CODE>PreserveJobFiles</CODE></A></LI>
<LI><A HREF="#PreserveJobHistory"><CODE>PreserveJobHistory</CODE></A></LI>
<LI><A HREF="#Printcap"><CODE>Printcap</CODE></A></LI>
</UL>
<!-- NEED 3in -->
-
<H3><A NAME="AccessLog">AccessLog</A></H3>
<HR>
<H4>Examples</H4>
to the system log instead of a plain file. </P>
<P>The default access log file is <VAR>/var/log/cups/access_log</VAR>.
<!-- NEED 6in -->
-
</P>
<H3><A NAME="Allow">Allow</A></H3>
<HR>
</UL>
<!-- NEED 3in -->
-
<H3><A NAME="BrowseInterval">BrowseInterval</A></H3>
<HR>
<H4>Examples</H4>
</TABLE>
</CENTER>
+<!-- NEED 3in -->
+</P>
+<H3><A NAME="Classification">Classification</A></H3>
+<HR>
+<H4>Examples</H4>
+<UL>
+<PRE>
+Classification
+Classification classified
+Classification confidential
+Classification secret
+Classification topsecret
+Classification unclassified
+</PRE>
+</UL>
+<H4>Description</H4>
+<P>The <CODE>Classification</CODE> directive sets the classification
+level on the server. When this option is set, at least one of the
+banner pages is forced to the classification level, and the
+classification is placed on each page of output. The default is no
+classification level.
<!-- NEED 3in -->
</P>
<H3><A NAME="DataDir">DataDir</A></H3>
utf-8</CODE> but is overridden by the character set for the language
specified by the client or the <CODE>DefaultLanguage</CODE> directive.
<!-- NEED 3in -->
-
</P>
<H3><A NAME="DefaultLanguage">DefaultLanguage</A></H3>
<HR>
filter and CGI programs run as. The default group is <CODE>sys</CODE>, <CODE>
system</CODE>, or <CODE>root</CODE> depending on the operating system.
<!-- NEED 3in -->
-
</P>
<H3><A NAME="HostNameLookups">HostNameLookups</A></H3>
<HR>
</UL>
<!-- NEED 3in -->
-
<H3><A NAME="MaxClients">MaxClients</A></H3>
<HR>
<H4>Examples</H4>
limit, the oldest completed job is automatically purged from the system
to make room for the new one. If all of the known jobs are still
pending or active then the new job will be rejected. </P>
-<P>Setting the maximum size to 0 disables this functionality. The
-default setting is 0.
+<P>Setting the maximum to 0 disables this functionality. The default
+setting is 0.
+<!-- NEED 3in -->
+</P>
+<H3><A NAME="MaxJobsPerPrinter">MaxJobsPerPrinter</A></H3>
+<HR>
+<H4>Examples</H4>
+<UL>
+<PRE>
+MaxJobsPerPrinter 100
+MaxJobsPerPrinter 9999
+MaxJobsPerPrinter 0
+</PRE>
+</UL>
+<H4>Description</H4>
+<P>The <CODE>MaxJobsPerPrinter</CODE> directive controls the maximum
+number of active jobs that are allowed for each printer or class. Once
+a printer or class reaches the limit, new jobs will be rejected until
+one of the active jobs is completed, stopped, aborted, or cancelled. </P>
+<P>Setting the maximum to 0 disables this functionality. The default
+setting is 0.
+<!-- NEED 3in -->
+</P>
+<H3><A NAME="MaxJobsPerUser">MaxJobsPerUser</A></H3>
+<HR>
+<H4>Examples</H4>
+<UL>
+<PRE>
+MaxJobsPerUser 100
+MaxJobsPerUser 9999
+MaxJobsPerUser 0
+</PRE>
+</UL>
+<H4>Description</H4>
+<P>The <CODE>MaxJobsPerUser</CODE> directive controls the maximum
+number of active jobs that are allowed for each user. Once a user
+reaches the limit, new jobs will be rejected until one of the active
+jobs is completed, stopped, aborted, or cancelled. </P>
+<P>Setting the maximum to 0 disables this functionality. The default
+setting is 0.
<!-- NEED 3in -->
</P>
<H3><A NAME="MaxLogSize">MaxLogSize</A></H3>
<P>The <CODE>PrintcapFormat</CODE> directive controls the output format
of the printcap file. The default is to generate a BSD printcap file.
<!-- NEED 3in -->
-
</P>
<H3><A NAME="RemoteRoot">RemoteRoot</A></H3>
<HR>
</UL>
<!-- NEED 3in -->
-
<H3><A NAME="Timeout">Timeout</A></H3>
<HR>
<H4>Examples</H4>
</UL>
<!-- NEED 7in -->
-
<H3><A NAME="7_5_3">Using Digest Authentication</A></H3>
<P>Digest authentication uses users and passwords defined in the <VAR>
/etc/cups/passwd.md5</VAR> file to authenticate access to resources
</UL>
<!-- NEED 2in -->
-
<P>Once added, a user can change his/her password by typing: </P>
<UL>
<PRE>
</UL>
<!-- NEED 1in -->
-
<P>To remove a user from the password file, type: </P>
<UL>
<PRE>
</UL>
<!-- NEW PAGE -->
-
<H2><A NAME="PRINTER_ACCOUNTING">Printer Accounting</A></H2>
<P>ESP Print Pro maintains a log of all accesses, errors, and pages
that are printed. The log files are normally stored in the <VAR>
<P>where <CODE>Name</CODE> is the name you want to use when sharing the
printer, and <CODE>printer</CODE> is the name of the CUPS print queue.
<!-- NEED 3in -->
-
</P>
<H3><A NAME="8_4_2">XINET KA/Spool</A></H3>
<P>To use your system as a print server for Mac OS clients, configure
</UL>
<!-- NEED 2in -->
-
<H2><A NAME="8_5">Printing to Mac OS Servers</A></H2>
<P>CUPS currently does not provide a backend to communicate with a Mac
OS server. However, you can write and install a short shell script in
</UL>
<!-- NEED 2in -->
-
<H2><A NAME="8_6">Printing from Windows Clients</A></H2>
<P>While CUPS does not provide Windows support directly, the free SAMBA
software package does. SAMBA version 2.0.6 is the first release of
</UL>
<!-- NEW PAGE -->
-
<H2><A NAME="9_2">GNU GENERAL PUBLIC LICENSE</A></H2>
<P>Version 2, June 1991 </P>
<PRE>
<H4>END OF TERMS AND CONDITIONS</H4>
<!-- NEW PAGE -->
-
<H2><A NAME="9_3">GNU LIBRARY GENERAL PUBLIC LICENSE</A></H2>
<P>Version 2, June 1991 </P>
<PRE>
</UL>
<!-- NEED 1in -->
-
<P>Newer versions of <CODE>bootpd</CODE> use a different format: </P>
<UL>
<PRE>
address</I>/PASSTHRU</TD></TR>
<!-- NEED 1in -->
-
<TR ALIGN="LEFT" VALIGN="TOP"><TD>Axis w/o IPP
<BR><A HREF="#AXIS"> (see directions)</A></TD><TD>socket://<I>address</I>
:9100
<BR> socket://<I>address</I>:9102</TD></TR>
<!-- NEED 1in -->
-
<TR ALIGN="LEFT" VALIGN="TOP"><TD>Axis w/IPP</TD><TD>ipp://<I>address</I>
/LPT1
<BR> ipp://<I>address</I>/LPT2
<BR> ipp://<I>address</I>/COM1</TD></TR>
<!-- NEED 1in -->
-
<TR ALIGN="LEFT" VALIGN="TOP"><TD>Castelle LANpress<SUP>TM</SUP></TD><TD>
lpd://<I>address</I>/pr1
<BR> lpd://<I>address</I>/pr2
<BR> lpd://<I>address</I>/pr3</TD></TR>
<!-- NEED 1in -->
-
<TR ALIGN="LEFT" VALIGN="TOP"><TD>DPI NETPrint</TD><TD>lpd://<I>address</I>
/pr1
<BR> lpd://<I>address</I>/pr2
Interface Board</TD><TD>socket://<I>address</I></TD></TR>
<!-- NEED 1in -->
-
<TR ALIGN="LEFT" VALIGN="TOP"><TD>Extended System ExtendNET</TD><TD>
lpd://<I>address</I>/pr1
<BR> lpd://<I>address</I>/pr2
<BR> lpd://<I>address</I>/pr3</TD></TR>
<!-- NEED 1in -->
-
<TR ALIGN="LEFT" VALIGN="TOP"><TD>Hewlett Packard JetDirect w/o IPP</TD><TD>
socket://<I>address</I>:9100
<BR> socket://<I>address</I>:9101
<BR> socket://<I>address</I>:9102</TD></TR>
<!-- NEED 1in -->
-
<TR ALIGN="LEFT" VALIGN="TOP"><TD>Hewlett Packard JetDirect w/IPP</TD><TD>
ipp://<I>address</I>/ipp
<BR> ipp://<I>address</I>/ipp/port1
<BR> ipp://<I>address</I>/ipp/port3</TD></TR>
<!-- NEED 1in -->
-
<TR ALIGN="LEFT" VALIGN="TOP"><TD>Intel® NetportExpress XL, PRO/100</TD><TD>
lpd://<I>address</I>/LPT1_PASSTHRU
<BR> lpd://<I>address</I>/LPT2_PASSTHRU
lpd://<I>address</I>/ps</TD></TR>
<!-- NEED 1in -->
-
<TR ALIGN="LEFT" VALIGN="TOP"><TD>Linksys EtherFast®
<BR><A HREF="#LINKSYS"> (see directions)</A></TD><TD>socket://<I>address</I>
:4010
</UL>
<!-- NEED 2in -->
-
<P>Next, edit the file with your favorite text editor and locate the
lines beginning with: </P>
<UL>
</UL>
<!-- NEED 2in -->
-
<P>This disables the Reverse TELNET protocol and enables the standard
TELNET protocol on the print server. Next, assign a port number for
each parallel and serial port on the server as follows: </P>
</UL>
<!-- NEED 4in -->
-
<P>This essentially makes the Axis print server look like a Hewlett
Packard JetDirect EX print server. Save the file and then upload the
new <VAR>config</VAR> file using the <CODE>ftp</CODE> command: </P>
</UL>
<!-- NEED 2in -->
-
<P>Next, edit the file with your favorite text editor and locate the
lines beginning with: </P>
<UL>
</UL>
<!-- NEED 4in -->
-
<P>This maps each virtual printer with a physical port. Save the file
and then upload the new <VAR>CONFIG</VAR> file using the <CODE>ftp</CODE>
command: </P>
</CENTER>
<!-- NEED 4in -->
-
<H2><A NAME="13_4">I Can't Do Administration Tasks from My Web Browser!</A>
</H2>
<P>This problem is usually caused by: </P>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" "http://www.w3.org/TR/REC-html40/loose.dtd">
<HTML>
<HEAD>
-<TITLE> CUPS Software Users Manual</TITLE>
+<TITLE>CUPS Software Users Manual</TITLE>
<META NAME="author" CONTENT="Easy Software Products">
<META NAME="copyright" CONTENT="Copyright 1997-2001, All Rights Reserved">
-<META NAME="docnumber" CONTENT="CUPS-SUM-1.1.6">
+<META NAME="docnumber" CONTENT="CUPS-SUM-1.1.7">
<META HTTP-EQUIV="Content-Type" CONTENT="text/html; CHARSET=iso-8859-1">
<STYLE TYPE="text/css"><!--
-BODY { font-family: serif; font-size: 11.0pt }
-H1 { font-family: sans-serif; font-size: 20.0pt }
-H2 { font-family: sans-serif; font-size: 17.0pt }
-H3 { font-family: sans-serif; font-size: 14.0pt }
-H4 { font-family: sans-serif; font-size: 11.0pt }
-H5 { font-family: sans-serif; font-size: 9.0pt }
-H6 { font-family: sans-serif; font-size: 8.0pt }
-SUB { font-size: 8.0pt }
-SUP { font-size: 8.0pt }
-PRE { font-size: 9.0pt }
+BODY { font-family: serif }
+H1 { font-family: sans-serif }
+H2 { font-family: sans-serif }
+H3 { font-family: sans-serif }
+H4 { font-family: sans-serif }
+H5 { font-family: sans-serif }
+H6 { font-family: sans-serif }
+SUB { font-size: smaller }
+SUP { font-size: smaller }
+PRE { font-family: monospace }
--></STYLE>
</HEAD>
<BODY BGCOLOR="#ffffff">
-<CENTER><A HREF="#CONTENTS"><IMG SRC="images/cups-large.gif" BORDER="0" WIDTH="100%"><BR>
-<H1> CUPS Software Users Manual</H1></A><BR>
-CUPS-SUM-1.1.6<BR>
+<CENTER><A HREF="#CONTENTS"><IMG SRC="images/cups-large.gif" BORDER="0" WIDTH="431" HEIGHT="511"><BR>
+<H1>CUPS Software Users Manual</H1></A><BR>
+CUPS-SUM-1.1.7<BR>
Easy Software Products<BR>
Copyright 1997-2001, All Rights Reserved<BR>
</CENTER>
<HR>
<H1 ALIGN="RIGHT"><A NAME="1">Preface</A></H1>
<P>This software users manual describes how to use the Common UNIX
-Printing System<SUP>TM</SUP> ("CUPS<SUP>TM</SUP>") Version 1.1.6. </P>
+Printing System<SUP>TM</SUP> ("CUPS<SUP>TM</SUP>") Version 1.1.7. </P>
<H2><A NAME="1_1">System Overview</A></H2>
<P>CUPS provides a portable printing layer for UNIX®-based operating
systems. It has been developed by <A HREF="http://www.easysw.com">Easy
<HEAD>
<META NAME="Description" CONTENT="Common UNIX Printing System Software Users Manual">
<META NAME="COPYRIGHT" CONTENT="Copyright 1997-2001, All Rights Reserved">
- <META NAME="DOCNUMBER" CONTENT="CUPS-SUM-1.1.6">
+ <META NAME="DOCNUMBER" CONTENT="CUPS-SUM-1.1.7">
<META NAME="Author" CONTENT="Easy Software Products">
<TITLE>CUPS Software Users Manual</TITLE>
</HEAD>
<H1 ALIGN="RIGHT">Preface</H1>
<P>This software users manual describes how to use the Common UNIX Printing
-System<SUP>TM</SUP> ("CUPS<SUP>TM</SUP>") Version 1.1.6.
+System<SUP>TM</SUP> ("CUPS<SUP>TM</SUP>") Version 1.1.7.
<EMBED SRC="system-overview.shtml">
/*
- * "$Id: common.c,v 1.15 2001/03/27 20:54:15 mike Exp $"
+ * "$Id: common.c,v 1.15.2.1 2001/05/13 18:38:18 mike Exp $"
*
* Common filter routines for the Common UNIX Printing System (CUPS).
*
*
* Contents:
*
- * SetCommonOptions() - Set common filter options for media size, etc.
+ * SetCommonOptions() - Set common filter options for media size,
+ * etc.
+ * UpdatePageVars() - Update the page variables for the
+ * orientation.
+ * WriteClassificationProlog() - Write the prolog with the classification
+ * and page label.
*/
/*
cups_option_t *options, /* I - Options */
int change_size) /* I - Change page size? */
{
- float temp; /* Swapping variable */
ppd_file_t *ppd; /* PPD file */
ppd_size_t *pagesize; /* Current page size */
const char *val; /* Option value */
}
if (change_size)
- switch (Orientation)
- {
- case 0 : /* Portait */
- break;
-
- case 1 : /* Landscape */
- temp = PageLeft;
- PageLeft = PageBottom;
- PageBottom = temp;
-
- temp = PageRight;
- PageRight = PageTop;
- PageTop = temp;
-
- temp = PageWidth;
- PageWidth = PageLength;
- PageLength = temp;
- break;
-
- case 2 : /* Reverse Portrait */
- temp = PageWidth - PageLeft;
- PageLeft = PageWidth - PageRight;
- PageRight = temp;
-
- temp = PageLength - PageBottom;
- PageBottom = PageLength - PageTop;
- PageTop = temp;
- break;
-
- case 3 : /* Reverse Landscape */
- temp = PageWidth - PageLeft;
- PageLeft = PageWidth - PageRight;
- PageRight = temp;
-
- temp = PageLength - PageBottom;
- PageBottom = PageLength - PageTop;
- PageTop = temp;
-
- temp = PageLeft;
- PageLeft = PageBottom;
- PageBottom = temp;
-
- temp = PageRight;
- PageRight = PageTop;
- PageTop = temp;
-
- temp = PageWidth;
- PageWidth = PageLength;
- PageLength = temp;
- break;
- }
+ UpdatePageVars();
if ((val = cupsGetOption("sides", num_options, options)) != NULL &&
strncasecmp(val, "two-", 4) == 0)
}
+/*
+ * 'UpdatePageVars()' - Update the page variables for the orientation.
+ */
+
+void
+UpdatePageVars(void)
+{
+ float temp; /* Swapping variable */
+
+
+ switch (Orientation)
+ {
+ case 0 : /* Portait */
+ break;
+
+ case 1 : /* Landscape */
+ temp = PageLeft;
+ PageLeft = PageBottom;
+ PageBottom = temp;
+
+ temp = PageRight;
+ PageRight = PageTop;
+ PageTop = temp;
+
+ temp = PageWidth;
+ PageWidth = PageLength;
+ PageLength = temp;
+ break;
+
+ case 2 : /* Reverse Portrait */
+ temp = PageWidth - PageLeft;
+ PageLeft = PageWidth - PageRight;
+ PageRight = temp;
+
+ temp = PageLength - PageBottom;
+ PageBottom = PageLength - PageTop;
+ PageTop = temp;
+ break;
+
+ case 3 : /* Reverse Landscape */
+ temp = PageWidth - PageLeft;
+ PageLeft = PageWidth - PageRight;
+ PageRight = temp;
+
+ temp = PageLength - PageBottom;
+ PageBottom = PageLength - PageTop;
+ PageTop = temp;
+
+ temp = PageLeft;
+ PageLeft = PageBottom;
+ PageBottom = temp;
+
+ temp = PageRight;
+ PageRight = PageTop;
+ PageTop = temp;
+
+ temp = PageWidth;
+ PageWidth = PageLength;
+ PageLength = temp;
+ break;
+ }
+}
+
+
/*
* 'WriteClassificationProlog()' - Write the prolog with the classification
* and page label.
/*
- * End of "$Id: common.c,v 1.15 2001/03/27 20:54:15 mike Exp $".
+ * End of "$Id: common.c,v 1.15.2.1 2001/05/13 18:38:18 mike Exp $".
*/
/*
- * "$Id: common.h,v 1.6 2001/03/14 13:45:33 mike Exp $"
+ * "$Id: common.h,v 1.6.2.1 2001/05/13 18:38:18 mike Exp $"
*
* Common filter definitions for the Common UNIX Printing System (CUPS).
*
extern ppd_file_t *SetCommonOptions(int num_options, cups_option_t *options,
int change_size);
+extern void UpdatePageVars(void);
extern void WriteLabelProlog(const char *label);
#define WriteLabels() puts("espWL");
/*
- * End of "$Id: common.h,v 1.6 2001/03/14 13:45:33 mike Exp $".
+ * End of "$Id: common.h,v 1.6.2.1 2001/05/13 18:38:18 mike Exp $".
*/
/*
- * "$Id: image-bmp.c,v 1.3 2001/01/22 15:03:38 mike Exp $"
+ * "$Id: image-bmp.c,v 1.3.2.1 2001/05/13 18:38:18 mike Exp $"
*
* BMP image routines for the Common UNIX Printing System (CUPS).
*
ib_t colormap[256][4]; /* Colormap */
+ (void)secondary;
+
/*
* Get the header...
*/
colors_used = read_dword(fp);
colors_important = read_dword(fp);
+ /*
+ * Make sure the resolution info is valid...
+ */
+
+ if (img->xppi == 0)
+ img->xppi = 128;
+ if (img->yppi == 0)
+ img->yppi = 128;
+
fprintf(stderr, "info_size = %d, xsize = %d, ysize = %d, planes = %d, depth = %d\n",
info_size, img->xsize, img->ysize, planes, depth);
fprintf(stderr, "compression = %d, image_size = %d, xppi = %d, yppi = %d\n",
/*
- * End of "$Id: image-bmp.c,v 1.3 2001/01/22 15:03:38 mike Exp $".
+ * End of "$Id: image-bmp.c,v 1.3.2.1 2001/05/13 18:38:18 mike Exp $".
*/
/*
- * "$Id: image-tiff.c,v 1.17 2001/01/22 15:03:39 mike Exp $"
+ * "$Id: image-tiff.c,v 1.17.2.1 2001/05/13 18:38:18 mike Exp $"
*
* TIFF file routines for the Common UNIX Printing System (CUPS).
*
if ((tif = TIFFFdOpen(fileno(fp), "", "r")) == NULL)
{
+ fputs("ERROR: TIFFFdOpen() failed!\n", stderr);
fclose(fp);
return (-1);
}
- if (!TIFFGetField(tif, TIFFTAG_IMAGEWIDTH, &width) ||
- !TIFFGetField(tif, TIFFTAG_IMAGELENGTH, &height) ||
- !TIFFGetField(tif, TIFFTAG_PHOTOMETRIC, &photometric) ||
- !TIFFGetField(tif, TIFFTAG_COMPRESSION, &compression) ||
- !TIFFGetField(tif, TIFFTAG_SAMPLESPERPIXEL, &samples) ||
- !TIFFGetField(tif, TIFFTAG_BITSPERSAMPLE, &bits))
+ if (!TIFFGetField(tif, TIFFTAG_IMAGEWIDTH, &width))
{
+ fputs("ERROR: No image width tag in the file!\n", stderr);
TIFFClose(tif);
fclose(fp);
return (-1);
}
+ if (!TIFFGetField(tif, TIFFTAG_IMAGELENGTH, &height))
+ {
+ fputs("ERROR: No image height tag in the file!\n", stderr);
+ TIFFClose(tif);
+ fclose(fp);
+ return (-1);
+ }
+
+ if (!TIFFGetField(tif, TIFFTAG_PHOTOMETRIC, &photometric))
+ {
+ fputs("ERROR: No photometric tag in the file!\n", stderr);
+ TIFFClose(tif);
+ fclose(fp);
+ return (-1);
+ }
+
+ if (!TIFFGetField(tif, TIFFTAG_COMPRESSION, &compression))
+ {
+ fputs("ERROR: No compression tag in the file!\n", stderr);
+ TIFFClose(tif);
+ fclose(fp);
+ return (-1);
+ }
+
+ if (!TIFFGetField(tif, TIFFTAG_SAMPLESPERPIXEL, &samples))
+ samples = 1;
+
+ if (!TIFFGetField(tif, TIFFTAG_BITSPERSAMPLE, &bits))
+ bits = 1;
+
/*
* Get the image orientation...
*/
/*
- * End of "$Id: image-tiff.c,v 1.17 2001/01/22 15:03:39 mike Exp $".
+ * End of "$Id: image-tiff.c,v 1.17.2.1 2001/05/13 18:38:18 mike Exp $".
*/
/*
- * "$Id: imagetops.c,v 1.36 2001/03/14 13:45:33 mike Exp $"
+ * "$Id: imagetops.c,v 1.36.2.1 2001/05/13 18:38:18 mike Exp $"
*
* Image file to PostScript filter for the Common UNIX Printing System (CUPS).
*
* Local functions...
*/
-static void ps_hex(ib_t *, int);
+static void ps_hex(ib_t *, int, int);
static void ps_ascii85(ib_t *, int, int);
int out_offset, /* Offset into output buffer */
out_length; /* Length of output buffer */
ppd_file_t *ppd; /* PPD file */
+ ppd_choice_t *choice; /* PPD option choice */
int num_options; /* Number of print options */
cups_option_t *options; /* Print options */
const char *val; /* Option value */
int realcopies; /* Real copies being printed */
float left, top; /* Left and top of image */
char filename[1024]; /* Name of file to print */
+ time_t curtime; /* Current time */
+ struct tm *curtm; /* Current date */
+ char curdate[255]; /* Current date string */
/*
}
}
+ /*
+ * Compute the number of pages to print and the size of the image on each
+ * page...
+ */
+
xpages = ceil(xinches / xprint);
ypages = ceil(yinches / yprint);
+ xprint = xinches / xpages;
+ yprint = yinches / ypages;
+
+ /*
+ * Update the page size for custom sizes...
+ */
+
+ if ((choice = ppdFindMarkedChoice(ppd, "PageSize")) != NULL &&
+ strcasecmp(choice->choice, "Custom") == 0)
+ {
+ float width, /* New width in points */
+ length; /* New length in points */
+ char s[255]; /* New custom page size... */
+
+
+ if (Orientation & 1)
+ {
+ width = yprint * 72.0;
+ length = xprint * 72.0;
+ }
+ else
+ {
+ width = xprint * 72.0;
+ length = yprint * 72.0;
+ }
+
+ /*
+ * Add margins to page size...
+ */
+
+ width += ppd->custom_margins[0] + ppd->custom_margins[2];
+ length += ppd->custom_margins[1] + ppd->custom_margins[3];
+
+ /*
+ * Enforce minimums...
+ */
+
+ if (width < ppd->custom_min[0])
+ width = ppd->custom_min[0];
+
+ if (length < ppd->custom_min[1])
+ length = ppd->custom_min[1];
+
+ /*
+ * Set the new custom size...
+ */
+
+ sprintf(s, "Custom.%.0fx%.0f", width, length);
+ ppdMarkOption(ppd, "PageSize", s);
+
+ /*
+ * Update page variables...
+ */
+
+ PageWidth = width;
+ PageLength = length;
+ PageLeft = ppd->custom_margins[0];
+ PageRight = width - ppd->custom_margins[2];
+ PageBottom = ppd->custom_margins[1];
+ PageTop = length - ppd->custom_margins[3];
+
+ UpdatePageVars();
+ }
+
/*
* See if we need to collate, and if so how we need to do it...
*/
slowcollate = Collate && ppdFindOption(ppd, "Collate") == NULL;
+ if (Copies > 1 && !slowcollate)
+ {
+ realcopies = Copies;
+ Copies = 1;
+ }
+ else
+ realcopies = 1;
+
/*
* Write any "exit server" options that have been selected...
*/
* Start sending the document with any commands needed...
*/
- puts("%!");
+ curtime = time(NULL);
+ curtm = localtime(&curtime);
+
+ puts("%!PS-Adobe-3.0");
+ printf("%%%%BoundingBox: %.0f %.0f %.0f %.0f\n", PageLeft, PageBottom,
+ PageRight, PageTop);
+ printf("%%%%LanguageLevel: %d\n", LanguageLevel);
+ printf("%%%%Pages: %d\n", xpages * ypages * Copies);
+ puts("%%DocumentData: Clean7Bit");
+ puts("%%DocumentNeededResources: font Helvetica-Bold");
+ puts("%%Creator: imagetops/" CUPS_SVERSION);
+ strftime(curdate, sizeof(curdate), CUPS_STRFTIME_FORMAT, curtm);
+ printf("%%%%CreationDate: %s\n", curdate);
+ printf("%%%%Title: %s\n", argv[3]);
+ printf("%%%%For: %s\n", argv[2]);
+ if (Orientation & 1)
+ puts("%%Orientation: Landscape");
+ puts("%%EndComments");
+ puts("%%BeginProlog");
if (ppd != NULL && ppd->patches != NULL)
puts(ppd->patches);
WriteLabelProlog(cupsGetOption("page-label", num_options, options));
- if (Copies > 1 && !slowcollate)
+ if (realcopies > 1)
{
if (ppd == NULL || ppd->language_level == 1)
- printf("/#copies %d def\n", Copies);
+ printf("/#copies %d def\n", realcopies);
else
- printf("<</NumCopies %d>>setpagedevice\n", Copies);
-
- realcopies = Copies;
- Copies = 1;
+ printf("<</NumCopies %d>>setpagedevice\n", realcopies);
}
- else
- realcopies = 1;
+
+ puts("%%EndProlog");
/*
* Output the pages...
*/
- xprint = xinches / xpages;
- yprint = yinches / ypages;
- row = malloc(img->xsize * abs(colorspace) + 3);
+ row = malloc(img->xsize * abs(colorspace) + 3);
for (page = 1; Copies > 0; Copies --)
for (xpage = 0; xpage < xpages; xpage ++)
for (ypage = 0; ypage < ypages; ypage ++, page ++)
{
- fprintf(stderr, "PAGE: %d %d\n", page, realcopies);
- fprintf(stderr, "INFO: Printing page %d...\n", page);
+ if (ppd && ppd->num_filters == 0)
+ fprintf(stderr, "PAGE: %d %d\n", page, realcopies);
+
+ fprintf(stderr, "INFO: Printing page %d...\n", page);
+
+ printf("%%%%Page: %d %d\n", page, page);
ppdEmit(ppd, stdout, PPD_ORDER_PAGE);
for (y = y0; y <= y1; y ++)
{
ImageGetRow(img, x0, y, x1 - x0 + 1, row);
- ps_hex(row, (x1 - x0 + 1) * abs(colorspace));
+ ps_hex(row, (x1 - x0 + 1) * abs(colorspace), y == y1);
}
}
else
puts("showpage");
}
+ puts("%%EOF");
+
/*
* End the job with the appropriate JCL command or CTRL-D otherwise.
*/
*/
static void
-ps_hex(ib_t *data, /* I - Data to print */
- int length) /* I - Number of bytes to print */
+ps_hex(ib_t *data, /* I - Data to print */
+ int length, /* I - Number of bytes to print */
+ int last_line) /* I - Last line of raster data? */
{
- int col;
+ static int col = 0; /* Current column */
static char *hex = "0123456789ABCDEF";
+ /* Hex digits */
- col = 0;
-
while (length > 0)
{
/*
data ++;
length --;
- col = (col + 1) & 31;
- if (col == 0 && length > 0)
+ col += 2;
+ if (col > 78)
+ {
putchar('\n');
+ col = 0;
+ }
}
- putchar('\n');
+ if (last_line && col)
+ {
+ putchar('\n');
+ col = 0;
+ }
}
{
unsigned b; /* Binary data word */
unsigned char c[5]; /* ASCII85 encoded chars */
+ static int col = 0; /* Current column */
while (length > 3)
b = (((((data[0] << 8) | data[1]) << 8) | data[2]) << 8) | data[3];
if (b == 0)
+ {
putchar('z');
+ col ++;
+ }
else
{
c[4] = (b % 85) + '!';
c[0] = b + '!';
fwrite(c, 5, 1, stdout);
+ col += 5;
}
data += 4;
length -= 4;
+
+ if (col >= 75)
+ {
+ putchar('\n');
+ col = 0;
+ }
}
if (last_line)
}
puts("~>");
+ col = 0;
}
}
/*
- * End of "$Id: imagetops.c,v 1.36 2001/03/14 13:45:33 mike Exp $".
+ * End of "$Id: imagetops.c,v 1.36.2.1 2001/05/13 18:38:18 mike Exp $".
*/
/*
- * "$Id: imagetoraster.c,v 1.56 2001/03/15 17:48:07 mike Exp $"
+ * "$Id: imagetoraster.c,v 1.56.2.1 2001/05/13 18:38:19 mike Exp $"
*
* Image file to raster filter for the Common UNIX Printing System (CUPS).
*
if ((choice = ppdFindMarkedChoice(ppd, "PageSize")) != NULL &&
strcasecmp(choice->choice, "Custom") == 0)
{
+ float width, /* New width in points */
+ length; /* New length in points */
+
+
if (Orientation & 1)
{
- header.cupsWidth = yprint * header.HWResolution[0];
- header.cupsHeight = xprint * header.HWResolution[1];
- header.PageSize[0] = yprint * 72.0;
- header.PageSize[1] = xprint * 72.0;
+ width = yprint * 72.0;
+ length = xprint * 72.0;
}
else
{
- header.cupsWidth = xprint * header.HWResolution[0];
- header.cupsHeight = yprint * header.HWResolution[1];
- header.PageSize[0] = xprint * 72.0;
- header.PageSize[1] = yprint * 72.0;
+ width = xprint * 72.0;
+ length = yprint * 72.0;
}
+
+ /*
+ * Add margins to page size...
+ */
+
+ width += ppd->custom_margins[0] + ppd->custom_margins[2];
+ length += ppd->custom_margins[1] + ppd->custom_margins[3];
+
+ /*
+ * Enforce minimums...
+ */
+
+ if (width < ppd->custom_min[0])
+ width = ppd->custom_min[0];
+
+ if (length < ppd->custom_min[1])
+ length = ppd->custom_min[1];
+
+ /*
+ * Set the new custom size...
+ */
+
+ header.PageSize[0] = width + 0.5;
+ header.PageSize[1] = length + 0.5;
+
+ /*
+ * Update page variables...
+ */
+
+ PageWidth = width;
+ PageLength = length;
+ PageLeft = ppd->custom_margins[0];
+ PageRight = width - ppd->custom_margins[2];
+ PageBottom = ppd->custom_margins[1];
+ PageTop = length - ppd->custom_margins[3];
+
+ /*
+ * Remove margins from page size...
+ */
+
+ width -= ppd->custom_margins[0] + ppd->custom_margins[2];
+ length -= ppd->custom_margins[1] + ppd->custom_margins[3];
+
+ /*
+ * Set the bitmap size...
+ */
+
+ header.cupsWidth = width * header.HWResolution[0] / 72.0;
+ header.cupsHeight = length * header.HWResolution[1] / 72.0;
}
else
{
*dither; /* Pointer into dither array */
+ (void)z;
+
switch (XPosition)
{
case -1 :
*dither; /* Pointer into dither array */
+ (void)z;
+
switch (XPosition)
{
case -1 :
/*
- * End of "$Id: imagetoraster.c,v 1.56 2001/03/15 17:48:07 mike Exp $".
+ * End of "$Id: imagetoraster.c,v 1.56.2.1 2001/05/13 18:38:19 mike Exp $".
*/
/*
- * "$Id: pstops.c,v 1.54 2001/03/29 15:14:47 mike Exp $"
+ * "$Id: pstops.c,v 1.54.2.1 2001/05/13 18:38:20 mike Exp $"
*
* PostScript filter for the Common UNIX Printing System (CUPS).
*
Flip = 0, /* Flip/mirror pages */
NUp = 1, /* Number of pages on each sheet (1, 2, 4) */
Collate = 0, /* Collate copies? */
- Copies = 1; /* Number of copies */
+ Copies = 1, /* Number of copies */
+ UseESPsp = 0; /* Use ESPshowpage? */
/*
ppdEmit(ppd, stdout, PPD_ORDER_ANY);
ppdEmit(ppd, stdout, PPD_ORDER_PROLOG);
- puts("userdict begin\n"
- "/ESPshowpage /showpage load def\n"
- "/showpage { } def\n"
- "end");
-
if (g != 1.0 || b != 1.0)
printf("{ neg 1 add dup 0 lt { pop 1 } { %.3f exp neg 1 add } "
"ifelse %.3f mul } bind settransfer\n", g, b);
- WriteLabelProlog(cupsGetOption("page-label", num_options, options));
+ /*
+ * Figure out if we should use ESPshowpage or not...
+ */
+
+ val = cupsGetOption("page-label", num_options, options);
+
+ if (val != NULL || getenv("CLASSIFICATION") != NULL || NUp > 1)
+ {
+ /*
+ * Yes, use ESPshowpage...
+ */
+
+ UseESPsp = 1;
+
+ WriteLabelProlog(val);
+
+ puts("userdict begin\n"
+ "/ESPshowpage /showpage load def\n"
+ "/showpage { } def\n"
+ "end");
+ }
if (Copies > 1 && (!Collate || !slowcollate))
{
- if (ppd == NULL || ppd->language_level == 1)
+ if (Collate)
+ printf("%%%%Requirements: numcopies(%d) collate\n", Copies);
+ else
+ printf("%%%%Requirements: numcopies(%d)\n", Copies);
+
+ if (LanguageLevel == 1)
printf("/#copies %d def\n", Copies);
else
printf("<</NumCopies %d>>setpagedevice\n", Copies);
}
- if (strncmp(line, "%!PS-Adobe-", 11) == 0)
+ if (strncmp(line, "%!PS-Adobe-", 11) == 0 && atof(line + 11) >= 3.0)
{
/*
* OK, we have DSC comments; read until we find a %%Page comment...
if (strncmp(line, "%%BeginDocument:", 16) == 0 ||
strncmp(line, "%%BeginDocument ", 16) == 0) /* Adobe Acrobat BUG */
level ++;
- else if (strcmp(line, "%%EndDocument") == 0 && level > 0)
+ else if (strncmp(line, "%%EndDocument", 13) == 0 && level > 0)
level --;
else if (strncmp(line, "%%Page:", 7) == 0 && level == 0)
break;
if (strncmp(line, "%%BeginDocument:", 16) == 0 ||
strncmp(line, "%%BeginDocument ", 16) == 0) /* Adobe Acrobat BUG */
level ++;
- else if (strcmp(line, "%%EndDocument") == 0 && level > 0)
+ else if (strncmp(line, "%%EndDocument", 13) == 0 && level > 0)
level --;
- else if (strcmp(line, "%%EOF") == 0 && level == 0)
+ else if (strcmp(line, "\004") == 0)
+ continue;
+ else if (strncmp(line, "%%EOF", 5) == 0 && level == 0)
+ {
+ fputs("DEBUG: Saw EOF!\n", stderr);
saweof = 1;
+ break;
+ }
else if (strncmp(line, "%%Page:", 7) == 0 && level == 0)
{
- if (sscanf(line, "%*s%*s%d", &number) == 1)
+ if (!check_range(NumPages + 1))
{
- if (!check_range(number))
- {
- while (psgets(line, sizeof(line), fp) != NULL)
- if (strncmp(line, "%%BeginDocument:", 16) == 0 ||
- strncmp(line, "%%BeginDocument ", 16) == 0) /* Adobe Acrobat BUG */
- level ++;
- else if (strcmp(line, "%%EndDocument") == 0 && level > 0)
- level --;
- else if (strncmp(line, "%%Page:", 7) == 0 && level == 0)
- break;
-
- continue;
- }
+ while (psgets(line, sizeof(line), fp) != NULL)
+ if (strncmp(line, "%%BeginDocument:", 16) == 0 ||
+ strncmp(line, "%%BeginDocument ", 16) == 0) /* Adobe Acrobat BUG */
+ level ++;
+ else if (strcmp(line, "%%EndDocument") == 0 && level > 0)
+ level --;
+ else if (strncmp(line, "%%Page:", 7) == 0 && level == 0)
+ break;
+
+ continue;
+ }
- if (!sloworder && NumPages > 0)
- end_nup(NumPages - 1);
+ if (!sloworder && NumPages > 0)
+ end_nup(NumPages - 1);
- if (slowcollate || sloworder)
- Pages[NumPages] = ftell(temp);
+ if (slowcollate || sloworder)
+ Pages[NumPages] = ftell(temp);
- if (!sloworder)
+ if (!sloworder)
+ {
+ if ((NumPages & (NUp - 1)) == 0)
{
- if ((NumPages & (NUp - 1)) == 0)
- {
- if (ppd == NULL || ppd->num_filters == 0)
- fprintf(stderr, "PAGE: %d %d\n", page, Copies);
-
- printf("%%%%Page: %d %d\n", page, page);
- page ++;
- ppdEmit(ppd, stdout, PPD_ORDER_PAGE);
- }
+ if (ppd == NULL || ppd->num_filters == 0)
+ fprintf(stderr, "PAGE: %d %d\n", page, Copies);
- start_nup(NumPages);
+ printf("%%%%Page: %d %d\n", page, page);
+ page ++;
+ ppdEmit(ppd, stdout, PPD_ORDER_PAGE);
}
- NumPages ++;
+ start_nup(NumPages);
}
+
+ NumPages ++;
}
else if (strncmp(line, "%%BeginBinary:", 14) == 0 ||
(strncmp(line, "%%BeginData:", 12) == 0 &&
tbytes -= nbytes;
}
}
- else if (strcmp(line, "%%Trailer") == 0 && level == 0)
+ else if (strncmp(line, "%%Trailer", 9) == 0 && level == 0)
+ {
+ fputs("DEBUG: Saw Trailer!\n", stderr);
break;
+ }
else
{
if (!sloworder)
* Copy the trailer, if any...
*/
- while ((nbytes = fread(line, 1, sizeof(line), fp)) > 0)
- fwrite(line, 1, nbytes, stdout);
+ while (psgets(line, sizeof(line), fp) != NULL)
+ {
+ if (strcmp(line, "\004") != 0)
+ fputs(line, stdout);
+
+ if (strncmp(line, "%%EOF", 5) == 0)
+ {
+ fputs("DEBUG: Saw EOF!\n", stderr);
+ saweof = 1;
+ break;
+ }
+ }
}
else
{
fputs(line, temp);
}
- puts("ESPshowpage");
+ if (UseESPsp)
+ puts("ESPshowpage");
if (slowcollate)
{
copy_bytes(temp, 0);
Copies --;
- puts("ESPshowpage");
+ if (UseESPsp)
+ puts("ESPshowpage");
}
}
}
if (ppd != NULL && ppd->jcl_end)
fputs(ppd->jcl_end, stdout);
- else if (ppd->num_filters == 0)
+ else if (ppd != NULL && ppd->num_filters == 0)
putchar(0x04);
/*
switch (NUp)
{
case 1 :
- WriteLabels();
- puts("ESPshowpage");
+ if (UseESPsp)
+ {
+ WriteLabels();
+ puts("ESPshowpage");
+ }
break;
case 2 :
- if ((number & 1) == 1)
+ if ((number & 1) == 1 && UseESPsp)
{
WriteLabels();
puts("ESPshowpage");
break;
case 4 :
- if ((number & 3) == 3)
+ if ((number & 3) == 3 && UseESPsp)
{
WriteLabels();
puts("ESPshowpage");
/*
- * End of "$Id: pstops.c,v 1.54 2001/03/29 15:14:47 mike Exp $".
+ * End of "$Id: pstops.c,v 1.54.2.1 2001/05/13 18:38:20 mike Exp $".
*/
/*
- * "$Id: rastertoepson.c,v 1.10 2001/03/05 22:09:18 mike Exp $"
+ * "$Id: rastertoepson.c,v 1.10.2.1 2001/05/13 18:38:20 mike Exp $"
*
* EPSON ESC/P and ESC/P2 filter for the Common UNIX Printing System
* (CUPS).
if (page == 0)
fputs("ERROR: No pages found!\n", stderr);
else
- fputs("INFO: Ready to print.\n", stderr);
+ fputs("INFO: " CUPS_SVERSION " is ready to print.\n", stderr);
return (page == 0);
}
/*
- * End of "$Id: rastertoepson.c,v 1.10 2001/03/05 22:09:18 mike Exp $".
+ * End of "$Id: rastertoepson.c,v 1.10.2.1 2001/05/13 18:38:20 mike Exp $".
*/
/*
- * "$Id: rastertohp.c,v 1.15 2001/03/02 14:30:15 mike Exp $"
+ * "$Id: rastertohp.c,v 1.15.2.1 2001/05/13 18:38:21 mike Exp $"
*
* Hewlett-Packard Page Control Language filter for the Common UNIX
* Printing System (CUPS).
*/
unsigned char *Planes[4], /* Output buffers */
- *CompBuffer; /* Compression buffer */
+ *CompBuffer, /* Compression buffer */
+ *BitBuffer; /* Buffer for output bits */
int NumPlanes, /* Number of color planes */
+ ColorBits, /* Number of bits per color */
Feed, /* Number of lines to skip */
Duplex, /* Current duplex mode */
Page; /* Current page number */
*/
void Setup(void);
-void StartPage(cups_page_header_t *header);
+void StartPage(ppd_file_t *ppd, cups_page_header_t *header);
void EndPage(void);
void Shutdown(void);
*/
void
-StartPage(cups_page_header_t *header) /* I - Page header */
+StartPage(ppd_file_t *ppd, /* I - PPD file */
+ cups_page_header_t *header) /* I - Page header */
{
int plane; /* Looping var */
#if defined(HAVE_SIGACTION) && !defined(HAVE_SIGSET)
* Setup printer/job attributes...
*/
- Duplex = header->Duplex;
+ Duplex = header->Duplex;
+ ColorBits = header->cupsBitsPerColor;
if (!Duplex || (Page & 1))
{
*/
printf("\033&l6D\033&k12H"); /* Set 6 LPI, 10 CPI */
+ printf("\033&l0O"); /* Set portrait orientation */
switch (header->PageSize[1])
{
header->Duplex + header->Tumble);
printf("\033&l0L"); /* Turn off perforation skip */
+
+ if (ppd && ppd->model_number == 2)
+ printf("\033&l-2H"); /* Load media */
}
else
printf("\033&a2G"); /* Set back side */
*/
printf("\033*t%dR", header->HWResolution[0]); /* Set resolution */
- printf("\033*r%dS", header->cupsWidth); /* Set width */
- printf("\033*r%dT", header->cupsHeight); /* Set height */
- if (header->cupsColorSpace == CUPS_CSPACE_KCMY)
+ if (ppd->model_number == 2)
{
- NumPlanes = 4;
- printf("\033*r-4U"); /* Set KCMY graphics */
+ /*
+ * Figure out the number of color planes...
+ */
+
+ if (header->cupsColorSpace == CUPS_CSPACE_KCMY)
+ NumPlanes = 4;
+ else
+ NumPlanes = 1;
+
+ /*
+ * Send 26-byte configure image data command with horizontal and
+ * vertical resolutions as well as a color count...
+ */
+
+ printf("\033*g26W");
+ putchar(2); /* Format 2 */
+ putchar(NumPlanes); /* Output planes */
+
+ putchar(header->HWResolution[0] >> 8); /* Black resolution */
+ putchar(header->HWResolution[0]);
+ putchar(header->HWResolution[1] >> 8);
+ putchar(header->HWResolution[1]);
+ putchar(0);
+ putchar(1 << ColorBits); /* # of black levels */
+
+ putchar(header->HWResolution[0] >> 8); /* Cyan resolution */
+ putchar(header->HWResolution[0]);
+ putchar(header->HWResolution[1] >> 8);
+ putchar(header->HWResolution[1]);
+ putchar(0);
+ putchar(1 << ColorBits); /* # of cyan levels */
+
+ putchar(header->HWResolution[0] >> 8); /* Magenta resolution */
+ putchar(header->HWResolution[0]);
+ putchar(header->HWResolution[1] >> 8);
+ putchar(header->HWResolution[1]);
+ putchar(0);
+ putchar(1 << ColorBits); /* # of magenta levels */
+
+ putchar(header->HWResolution[0] >> 8); /* Yellow resolution */
+ putchar(header->HWResolution[0]);
+ putchar(header->HWResolution[1] >> 8);
+ putchar(header->HWResolution[1]);
+ putchar(0);
+ putchar(1 << ColorBits); /* # of yellow levels */
}
- else if (header->cupsColorSpace == CUPS_CSPACE_CMY)
+ else
{
- NumPlanes = 3;
- printf("\033*r-3U"); /* Set CMY graphics */
+ if (header->cupsColorSpace == CUPS_CSPACE_KCMY)
+ {
+ NumPlanes = 4;
+ printf("\033*r-4U"); /* Set KCMY graphics */
+ }
+ else if (header->cupsColorSpace == CUPS_CSPACE_CMY)
+ {
+ NumPlanes = 3;
+ printf("\033*r-3U"); /* Set CMY graphics */
+ }
+ else
+ NumPlanes = 1; /* Black&white graphics */
}
+
+ /*
+ * Set size and position of graphics...
+ */
+
+ printf("\033*r%dS", header->cupsWidth); /* Set width */
+ printf("\033*r%dT", header->cupsHeight); /* Set height */
+
+ printf("\033&a0H"); /* Set horizontal position */
+
+ if (ppd)
+ printf("\033&a%.0fV", /* Set vertical position */
+ 10.0 * (ppd->sizes[0].length - ppd->sizes[0].top));
else
- NumPlanes = 1; /* Black&white graphics */
+ printf("\033&a0V"); /* Set top-of-page */
- printf("\033&a0H\033&a330V"); /* Set top-of-page */
printf("\033*r1A"); /* Start graphics */
if (header->cupsCompression)
for (plane = 1; plane < NumPlanes; plane ++)
Planes[plane] = Planes[0] + plane * header->cupsBytesPerLine / NumPlanes;
+ if (ColorBits > 1)
+ BitBuffer = malloc(ColorBits * ((header->cupsWidth + 7) / 8));
+ else
+ BitBuffer = NULL;
+
if (header->cupsCompression)
CompBuffer = malloc(header->cupsBytesPerLine * 2);
else
if (NumPlanes > 1)
{
printf("\033*rC"); /* End color GFX */
- printf("\033&l0H"); /* Eject current page */
+
+ if (!(Duplex && (Page & 1)))
+ printf("\033&l0H"); /* Eject current page */
}
else
{
free(Planes[0]);
+ if (BitBuffer)
+ free(BitBuffer);
+
if (CompBuffer)
free(CompBuffer);
}
void
OutputLine(cups_page_header_t *header) /* I - Page header */
{
- int plane; /* Current plane */
+ int plane, /* Current plane */
+ bytes, /* Bytes to write */
+ count; /* Bytes to convert */
+ unsigned char bit, /* Current plane data */
+ bit0, /* Current low bit data */
+ bit1, /* Current high bit data */
+ *plane_ptr, /* Pointer into Planes */
+ *bit_ptr; /* Pointer into BitBuffer */
/*
* Write bitmap data as needed...
*/
+ bytes = (header->cupsWidth + 7) / 8;
+
for (plane = 0; plane < NumPlanes; plane ++)
- CompressData(Planes[plane], header->cupsBytesPerLine / NumPlanes,
- plane < (NumPlanes - 1) ? 'V' : 'W',
- header->cupsCompression);
+ if (ColorBits == 1)
+ {
+ /*
+ * Send bits as-is...
+ */
+
+ CompressData(Planes[plane], bytes, plane < (NumPlanes - 1) ? 'V' : 'W',
+ header->cupsCompression);
+ }
+ else
+ {
+ /*
+ * Separate low and high bit data into separate buffers.
+ */
+
+ for (count = header->cupsBytesPerLine / NumPlanes,
+ plane_ptr = Planes[plane], bit_ptr = BitBuffer;
+ count > 0;
+ count -= 2, plane_ptr += 2, bit_ptr ++)
+ {
+ bit = plane_ptr[0];
+
+ bit0 = ((bit & 64) << 1) | ((bit & 16) << 2) | ((bit & 4) << 3) | ((bit & 1) << 4);
+ bit1 = (bit & 128) | ((bit & 32) << 1) | ((bit & 8) << 2) | ((bit & 2) << 3);
+
+ if (count > 1)
+ {
+ bit = plane_ptr[1];
+
+ bit0 |= (bit & 1) | ((bit & 4) >> 1) | ((bit & 16) >> 2) | ((bit & 64) >> 3);
+ bit1 |= ((bit & 2) >> 1) | ((bit & 8) >> 2) | ((bit & 32) >> 3) | ((bit & 128) >> 4);
+ }
+
+ bit_ptr[0] = bit0;
+ bit_ptr[bytes] = bit1;
+ }
+
+ /*
+ * Send low and high bits...
+ */
+
+ CompressData(BitBuffer, bytes, 'V', header->cupsCompression);
+ CompressData(BitBuffer + bytes, bytes, plane < (NumPlanes - 1) ? 'V' : 'W',
+ header->cupsCompression);
+ }
fflush(stdout);
}
cups_raster_t *ras; /* Raster stream for printing */
cups_page_header_t header; /* Page header from file */
int y; /* Current line */
+ ppd_file_t *ppd; /* PPD file */
/*
* Initialize the print device...
*/
+ ppd = ppdOpenFile(getenv("PPD"));
+
Setup();
/*
* Start the page...
*/
- StartPage(&header);
+ StartPage(ppd, &header);
/*
* Loop for each line on the page...
Shutdown();
+ if (ppd)
+ ppdClose(ppd);
+
/*
* Close the raster stream...
*/
if (Page == 0)
fputs("ERROR: No pages found!\n", stderr);
else
- fputs("INFO: Ready to print.\n", stderr);
+ fputs("INFO: " CUPS_SVERSION " is ready to print.\n", stderr);
return (Page == 0);
}
/*
- * End of "$Id: rastertohp.c,v 1.15 2001/03/02 14:30:15 mike Exp $".
+ * End of "$Id: rastertohp.c,v 1.15.2.1 2001/05/13 18:38:21 mike Exp $".
*/
/*
- * "$Id: textcommon.c,v 1.16 2001/01/24 17:18:59 mike Exp $"
+ * "$Id: textcommon.c,v 1.16.2.1 2001/05/13 18:38:21 mike Exp $"
*
* Common text filter routines for the Common UNIX Printing System (CUPS).
*
*/
int /* O - Exit status */
-TextMain(char *name, /* I - Name of filter */
- int argc, /* I - Number of command-line arguments */
- char *argv[]) /* I - Command-line arguments */
+TextMain(const char *name, /* I - Name of filter */
+ int argc, /* I - Number of command-line arguments */
+ char *argv[]) /* I - Command-line arguments */
{
FILE *fp; /* Print file */
ppd_file_t *ppd; /* PPD file */
Copies = atoi(argv[4]);
- WriteProlog(argv[3], argv[2], ppd);
+ WriteProlog(argv[3], argv[2], getenv("CLASSIFICATION"),
+ cupsGetOption("page-label", num_options, options), ppd);
/*
* Read text from the specified source and print it...
/*
- * End of "$Id: textcommon.c,v 1.16 2001/01/24 17:18:59 mike Exp $".
+ * End of "$Id: textcommon.c,v 1.16.2.1 2001/05/13 18:38:21 mike Exp $".
*/
/*
- * "$Id: textcommon.h,v 1.6 2001/01/22 15:03:42 mike Exp $"
+ * "$Id: textcommon.h,v 1.6.2.1 2001/05/13 18:38:21 mike Exp $"
*
* Common text filter definitions for the Common UNIX Printing System (CUPS).
*
* Required functions...
*/
-extern int TextMain(char *name, int argc, char *argv[]);
+extern int TextMain(const char *name, int argc, char *argv[]);
extern void WriteEpilogue(void);
extern void WritePage(void);
-extern void WriteProlog(char *title, char *user, ppd_file_t *ppd);
+extern void WriteProlog(const char *title, const char *user,
+ const char *classification, const char *label,
+ ppd_file_t *ppd);
/*
- * End of "$Id: textcommon.h,v 1.6 2001/01/22 15:03:42 mike Exp $".
+ * End of "$Id: textcommon.h,v 1.6.2.1 2001/05/13 18:38:21 mike Exp $".
*/
/*
- * "$Id: texttops.c,v 1.34 2001/03/02 14:30:15 mike Exp $"
+ * "$Id: texttops.c,v 1.34.2.1 2001/05/13 18:38:21 mike Exp $"
*
* Text to PostScript filter for the Common UNIX Printing System (CUPS).
*
static void write_line(int row, lchar_t *line);
static void write_string(int col, int row, int len, lchar_t *s);
-static void write_text(char *s);
+static void write_text(const char *s);
/*
*/
void
-WriteProlog(char *title, /* I - Title of job */
- char *user, /* I - Username */
- ppd_file_t *ppd) /* I - PPD file info */
+WriteProlog(const char *title, /* I - Title of job */
+ const char *user, /* I - Username */
+ const char *classification, /* I - Classification */
+ const char *label, /* I - Page label */
+ ppd_file_t *ppd) /* I - PPD file info */
{
int i, j, k; /* Looping vars */
char *charset; /* Character set string */
if ((datadir = getenv("CUPS_DATADIR")) == NULL)
datadir = CUPS_DATADIR;
+ /*
+ * Adjust margins as necessary...
+ */
+
+ if (classification || label)
+ {
+ /*
+ * Leave room for labels...
+ */
+
+ PageBottom += 36;
+ PageTop -= 36;
+ }
+
/*
* Allocate memory for the page...
*/
*/
static void
-write_text(char *s) /* I - String to write */
+write_text(const char *s) /* I - String to write */
{
- int ch; /* Actual character value (UTF8) */
- unsigned char *utf8; /* UTF8 text */
+ int ch; /* Actual character value (UTF8) */
+ const unsigned char *utf8; /* UTF8 text */
if (NumFonts > 1)
putchar('<');
- utf8 = (unsigned char *)s;
+ utf8 = (const unsigned char *)s;
while (*utf8)
{
/*
- * End of "$Id: texttops.c,v 1.34 2001/03/02 14:30:15 mike Exp $".
+ * End of "$Id: texttops.c,v 1.34.2.1 2001/05/13 18:38:21 mike Exp $".
*/
#ifndef COMPACTFONTINFO_H
#define COMPACTFONTINFO_H
-static char *type1CStdStrings[391] = {
+static const char *type1CStdStrings[391] = {
".notdef",
"space",
"exclam",
int i;
for (i = 0; i < length; ++i) {
- gfree(entries[i].key);
+ gfree((void *)entries[i].key);
entries[i].val.free();
}
gfree(entries);
}
-void Dict::add(char *key, Object *val) {
+void Dict::add(const char *key, Object *val) {
if (length + 1 > size) {
size += 8;
entries = (DictEntry *)grealloc(entries, size * sizeof(DictEntry));
++length;
}
-inline DictEntry *Dict::find(char *key) {
+inline DictEntry *Dict::find(const char *key) {
int i;
for (i = 0; i < length; ++i) {
return NULL;
}
-GBool Dict::is(char *type) {
+GBool Dict::is(const char *type) {
DictEntry *e;
return (e = find("Type")) && e->val.isName(type);
}
-Object *Dict::lookup(char *key, Object *obj) {
+Object *Dict::lookup(const char *key, Object *obj) {
DictEntry *e;
return (e = find(key)) ? e->val.fetch(obj) : obj->initNull();
}
-Object *Dict::lookupNF(char *key, Object *obj) {
+Object *Dict::lookupNF(const char *key, Object *obj) {
DictEntry *e;
return (e = find(key)) ? e->val.copy(obj) : obj->initNull();
}
-char *Dict::getKey(int i) {
+const char *Dict::getKey(int i) {
return entries[i].key;
}
//------------------------------------------------------------------------
struct DictEntry {
- char *key;
+ const char *key;
Object val;
};
int getLength() { return length; }
// Add an entry. NB: does not copy key.
- void add(char *key, Object *val);
+ void add(const char *key, Object *val);
// Check if dictionary is of specified type.
- GBool is(char *type);
+ GBool is(const char *type);
// Look up an entry and return the value. Returns a null object
// if <key> is not in the dictionary.
- Object *lookup(char *key, Object *obj);
- Object *lookupNF(char *key, Object *obj);
+ Object *lookup(const char *key, Object *obj);
+ Object *lookupNF(const char *key, Object *obj);
// Iterative accessors.
- char *getKey(int i);
+ const char *getKey(int i);
Object *getVal(int i, Object *obj);
Object *getValNF(int i, Object *obj);
int length; // number of entries in dictionary
int ref; // reference count
- DictEntry *find(char *key);
+ DictEntry *find(const char *key);
};
#endif
GBool errQuiet;
void errorInit() {
- errFile = stderr;
+ if (errQuiet) {
+ errFile = NULL;
+ } else {
+ errFile = stderr;
+ }
}
-void CDECL error(int pos, char *msg, ...) {
+void CDECL error(int pos, const char *msg, ...) {
va_list args;
if (errQuiet) {
extern void errorInit();
-extern void CDECL error(int pos, char *msg, ...);
+extern void CDECL error(int pos, const char *msg, ...);
#endif
// FontEncoding
//------------------------------------------------------------------------
-inline int FontEncoding::hash(char *name) {
+inline int FontEncoding::hash(const char *name) {
Guint h;
h = (Guint)name[0] & 0xff;
FontEncoding::FontEncoding() {
int i;
- encoding = (char **)gmalloc(256 * sizeof(char *));
+ encoding = (const char **)gmalloc(256 * sizeof(const char *));
size = 256;
freeEnc = gTrue;
for (i = 0; i < 256; ++i)
hashTab[i] = -1;
}
-FontEncoding::FontEncoding(char **encoding, int size) {
+FontEncoding::FontEncoding(const char **nencoding, int nsize) {
int i;
- this->encoding = encoding;
- this->size = size;
+ encoding = nencoding;
+ size = nsize;
freeEnc = gFalse;
for (i = 0; i < fontEncHashSize; ++i)
hashTab[i] = -1;
for (i = 0; i < size; ++i) {
- if (encoding[i])
- addChar1(i, encoding[i]);
+ if (nencoding[i])
+ addChar1(i, nencoding[i]);
}
}
FontEncoding::FontEncoding(FontEncoding *fontEnc) {
int i;
- encoding = (char **)gmalloc(fontEnc->size * sizeof(char *));
+ encoding = (const char **)gmalloc(fontEnc->size * sizeof(const char *));
size = fontEnc->size;
freeEnc = gTrue;
for (i = 0; i < size; ++i) {
encoding[i] =
- fontEnc->encoding[i] ? copyString(fontEnc->encoding[i]) : NULL;
+ fontEnc->encoding[i] ? copyString(fontEnc->encoding[i]) : (char *)NULL;
}
memcpy(hashTab, fontEnc->hashTab, fontEncHashSize * sizeof(short));
}
-void FontEncoding::addChar(int code, char *name) {
+void FontEncoding::addChar(int code, const char *name) {
int h, i;
// replace character associated with code
if (++h == fontEncHashSize)
h = 0;
}
- gfree(encoding[code]);
+ gfree((void *)encoding[code]);
}
// associate name with code
addChar1(code, name);
}
-void FontEncoding::addChar1(int code, char *name) {
+void FontEncoding::addChar1(int code, const char *name) {
int h, i, code2;
// insert name in hash table
if (freeEnc) {
for (i = 0; i < size; ++i) {
if (encoding[i])
- gfree(encoding[i]);
+ gfree((void *)encoding[i]);
}
- gfree(encoding);
+ gfree((void *)encoding);
}
}
-int FontEncoding::getCharCode(char *name) {
+int FontEncoding::getCharCode(const char *name) {
int h, i, code;
h = hash(name);
FontEncoding();
// Construct an encoding from an array of char names.
- FontEncoding(char **encoding, int size);
+ FontEncoding(const char **encoding, int size);
// Destructor.
~FontEncoding();
int getSize() { return size; }
// Add a char to the encoding.
- void addChar(int code, char *name);
+ void addChar(int code, const char *name);
// Return the character name associated with <code>.
- char *getCharName(int code) { return encoding[code]; }
+ const char *getCharName(int code) { return encoding[code]; }
// Return the code associated with <name>.
- int getCharCode(char *name);
+ int getCharCode(const char *name);
private:
FontEncoding(FontEncoding *fontEnc);
- int hash(char *name);
- void addChar1(int code, char *name);
+ int hash(const char *name);
+ void addChar1(int code, const char *name);
- char **encoding; // code --> name mapping
+ const char **encoding; // code --> name mapping
int size; // number of codes
GBool freeEnc; // should we free the encoding array?
short // name --> code hash table
//------------------------------------------------------------------------
-static inline char *nextLine(char *line, char *end) {
+static inline const char *nextLine(const char *line, const char *end) {
while (line < end && *line != '\n' && *line != '\r')
++line;
while (line < end && *line == '\n' || *line == '\r')
// Type1FontFile
//------------------------------------------------------------------------
-Type1FontFile::Type1FontFile(char *file, int len) {
- char *line, *line1, *p;
+Type1FontFile::Type1FontFile(const char *file, int len) {
+ const char *line, *line1;
+ char *p, *p2;
char buf[256];
+ char c;
int n, code, i;
name = NULL;
n = 255;
strncpy(buf, line, n);
buf[n] = '\0';
- p = strtok(buf, " \t");
- if (p && !strcmp(p, "dup")) {
- if ((p = strtok(NULL, " \t"))) {
+ for (p = buf; *p == ' ' || *p == '\t'; ++p) ;
+ if (!strncmp(p, "dup", 3)) {
+ for (p += 3; *p == ' ' || *p == '\t'; ++p) ;
+ for (p2 = p; *p2 >= '0' && *p2 <= '9'; ++p2) ;
+ if (*p2) {
+ c = *p2;
+ *p2 = '\0';
if ((code = atoi(p)) < 256) {
- if ((p = strtok(NULL, " \t"))) {
- if (p[0] == '/') {
- encoding->addChar(code, copyString(p+1));
- }
+ *p2 = c;
+ for (p = p2; *p == ' ' || *p == '\t'; ++p) ;
+ if (*p == '/') {
+ ++p;
+ for (p2 = p; *p2 && *p2 != ' ' && *p2 != '\t'; ++p2) ;
+ *p2 = '\0';
+ encoding->addChar(code, copyString(p));
}
}
}
} else {
- if ((p = strtok(NULL, " \t\n\r")) && !strcmp(p, "def")) {
+ if (strtok(buf, " \t") &&
+ (p = strtok(NULL, " \t\n\r")) && !strcmp(p, "def")) {
break;
}
}
Type1FontFile::~Type1FontFile() {
if (name)
- gfree(name);
+ gfree((void *)name);
if (encoding && freeEnc)
delete encoding;
}
// Type1CFontFile
//------------------------------------------------------------------------
-Type1CFontFile::Type1CFontFile(char *file, int len) {
+Type1CFontFile::Type1CFontFile(const char *file, int len) {
char buf[256];
Guchar *topPtr, *idxStartPtr, *idxPtr0, *idxPtr1;
Guchar *stringIdxPtr, *stringStartPtr;
- int topOffSize, idxOffSize, stringOffSize;
+ int idxOffSize, stringOffSize;
int nFonts, nStrings, nGlyphs;
int nCodes, nRanges, nLeft, nSups;
Gushort *glyphNames;
int key;
int i, j, n;
+ (void)len;
+
name = NULL;
encoding = NULL;
freeEnc = gTrue;
// read header
topPtr = (Guchar *)file + (file[2] & 0xff);
- topOffSize = file[3] & 0xff;
// read name index (first font only)
nFonts = getWord(topPtr, 2);
idxPtr1 = idxStartPtr + getWord(topPtr + idxOffSize, idxOffSize);
if ((n = idxPtr1 - idxPtr0) > 255)
n = 255;
- strncpy(buf, (char *)idxPtr0, n);
+ strncpy(buf, (const char *)idxPtr0, n);
buf[n] = '\0';
name = copyString(buf);
topPtr = idxStartPtr + getWord(topPtr + nFonts * idxOffSize, idxOffSize);
Type1CFontFile::~Type1CFontFile() {
if (name)
- gfree(name);
+ gfree((void *)name);
if (encoding && freeEnc)
delete encoding;
}
stringOffSize);
if ((len = idxPtr1 - idxPtr0) > 255)
len = 255;
- strncpy(buf, (char *)idxPtr0, len);
+ strncpy(buf, (const char *)idxPtr0, len);
buf[len] = '\0';
}
return buf;
// Type1CFontConverter
//------------------------------------------------------------------------
-Type1CFontConverter::Type1CFontConverter(char *file, int len, FILE *out) {
- this->file = file;
- this->len = len;
- this->out = out;
+Type1CFontConverter::Type1CFontConverter(const char *nfile, int nlen, FILE *nout) {
+ file = nfile;
+ len = nlen;
+ out = nout;
r1 = 55665;
line = 0;
}
}
void Type1CFontConverter::convert() {
- char *fontName;
+ const char *fontName;
struct {
int version;
int notice;
char buf[256], eBuf[256];
Guchar *topPtr, *idxStartPtr, *idxPtr0, *idxPtr1;
Guchar *stringIdxPtr, *stringStartPtr;
- int topOffSize, idxOffSize, stringOffSize;
+ int idxOffSize, stringOffSize;
int nFonts, nStrings, nGlyphs;
int nCodes, nRanges, nLeft, nSups;
Gushort *glyphNames;
// read header
topPtr = (Guchar *)file + (file[2] & 0xff);
- topOffSize = file[3] & 0xff;
// read name (first font only)
nFonts = getWord(topPtr, 2);
idxPtr1 = idxStartPtr + getWord(topPtr + idxOffSize, idxOffSize);
if ((n = idxPtr1 - idxPtr0) > 255)
n = 255;
- strncpy(buf, (char *)idxPtr0, n);
+ strncpy(buf, (const char *)idxPtr0, n);
buf[n] = '\0';
fontName = copyString(buf);
topPtr = idxStartPtr + getWord(topPtr + nFonts * idxOffSize, idxOffSize);
topPtr = stringStartPtr + getWord(topPtr + nStrings * stringOffSize,
stringOffSize);
-#if 1 //~
- // get global subrs
- int nGSubrs;
- int gSubrOffSize;
-
- nGSubrs = getWord(topPtr, 2);
- gSubrOffSize = topPtr[2];
+ // skip global subrs
topPtr += 3;
-#endif
// write header and font dictionary, up to encoding
fprintf(out, "%%!FontType1-1.0: %s", fontName);
// clean up
if (dict.charset > 2)
- gfree(glyphNames);
- gfree(fontName);
+ gfree((void *)glyphNames);
+ gfree((void *)fontName);
}
-void Type1CFontConverter::eexecWrite(char *s) {
+void Type1CFontConverter::eexecWrite(const char *s) {
Guchar *p;
Guchar x;
}
}
-void Type1CFontConverter::cvtGlyph(char *name, Guchar *s, int n) {
+void Type1CFontConverter::cvtGlyph(const char *name, Guchar *s, int n) {
int nHints;
int x;
GBool first = gTrue;
eexecDumpOp1(13);
}
-void Type1CFontConverter::eexecDumpNum(double x, GBool fp) {
+void Type1CFontConverter::eexecDumpNum(double x, GBool nfp) {
Guchar buf[12];
int y, n;
n = 0;
- if (fp) {
+ if (nfp) {
if (x >= -32768 && x < 32768) {
y = (int)(x * 256.0);
buf[0] = 255;
n = 5;
}
}
- charBuf->append((char *)buf, n);
+ charBuf->append((const char *)buf, n);
}
-void Type1CFontConverter::eexecDumpOp1(int op) {
- charBuf->append((char)op);
+void Type1CFontConverter::eexecDumpOp1(int nop) {
+ charBuf->append((char)nop);
}
-void Type1CFontConverter::eexecDumpOp2(int op) {
+void Type1CFontConverter::eexecDumpOp2(int nop) {
charBuf->append((char)12);
- charBuf->append((char)op);
+ charBuf->append((char)nop);
}
void Type1CFontConverter::eexecWriteCharstring(Guchar *s, int n) {
}
}
-void Type1CFontConverter::getDeltaInt(char *buf, char *name, double *op,
+void Type1CFontConverter::getDeltaInt(char *buf, const char *name, double *nop,
int n) {
int x, i;
buf += strlen(buf);
x = 0;
for (i = 0; i < n; ++i) {
- x += (int)op[i];
+ x += (int)nop[i];
sprintf(buf, "%s%d", i > 0 ? " " : "", x);
buf += strlen(buf);
}
sprintf(buf, "] def\n");
}
-void Type1CFontConverter::getDeltaReal(char *buf, char *name, double *op,
+void Type1CFontConverter::getDeltaReal(char *buf, const char *name, double *nop,
int n) {
double x;
int i;
buf += strlen(buf);
x = 0;
for (i = 0; i < n; ++i) {
- x += op[i];
+ x += nop[i];
sprintf(buf, "%s%g", i > 0 ? " " : "", x);
buf += strlen(buf);
}
// Returns the font name, as specified internally by the font file.
// Returns NULL if no name is available.
- virtual char *getName() = 0;
+ virtual const char *getName() = 0;
// Returns the custom font encoding, or NULL if the encoding is
// not available. If <taken> is set, the caller of this function
class Type1FontFile: public FontFile {
public:
- Type1FontFile(char *file, int len);
+ Type1FontFile(const char *file, int len);
virtual ~Type1FontFile();
- virtual char *getName() { return name; }
+ virtual const char *getName() { return name; }
virtual FontEncoding *getEncoding(GBool taken);
private:
- char *name;
+ const char *name;
FontEncoding *encoding;
GBool freeEnc;
};
class Type1CFontFile: public FontFile {
public:
- Type1CFontFile(char *file, int len);
+ Type1CFontFile(const char *file, int len);
virtual ~Type1CFontFile();
- virtual char *getName() { return name; }
+ virtual const char *getName() { return name; }
virtual FontEncoding *getEncoding(GBool taken);
private:
- char *name;
+ const char *name;
FontEncoding *encoding;
GBool freeEnc;
};
class Type1CFontConverter {
public:
- Type1CFontConverter(char *file, int len, FILE *out);
+ Type1CFontConverter(const char *file, int len, FILE *out);
~Type1CFontConverter();
void convert();
private:
- void eexecWrite(char *s);
- void cvtGlyph(char *name, Guchar *s, int n);
+ void eexecWrite(const char *s);
+ void cvtGlyph(const char *name, Guchar *s, int n);
void cvtGlyphWidth(GBool useOp);
void eexecDumpNum(double x, GBool fp);
void eexecDumpOp1(int op);
void eexecDumpOp2(int op);
void eexecWriteCharstring(Guchar *s, int n);
- void getDeltaInt(char *buf, char *name, double *op, int n);
- void getDeltaReal(char *buf, char *name, double *op, int n);
+ void getDeltaInt(char *buf, const char *name, double *op, int n);
+ void getDeltaReal(char *buf, const char *name, double *op, int n);
- char *file;
+ const char *file;
int len;
FILE *out;
double op[48]; // operands
//------------------------------------------------------------------------
#define standardEncodingSize 335
-static char *standardEncodingNames[standardEncodingSize] = {
+static const char *standardEncodingNames[standardEncodingSize] = {
NULL,
NULL,
NULL,
standardEncodingSize);
#define symbolEncodingSize 257
-static char *symbolEncodingNames[symbolEncodingSize] = {
+static const char *symbolEncodingNames[symbolEncodingSize] = {
NULL,
NULL,
NULL,
symbolEncodingSize);
#define zapfDingbatsEncodingSize 270
-static char *zapfDingbatsEncodingNames[zapfDingbatsEncodingSize] = {
+static const char *zapfDingbatsEncodingNames[zapfDingbatsEncodingSize] = {
NULL,
NULL,
NULL,
zapfDingbatsEncodingSize);
#define macRomanEncodingSize 256
-static char *macRomanEncodingNames[macRomanEncodingSize] = {
+static const char *macRomanEncodingNames[macRomanEncodingSize] = {
NULL,
NULL,
NULL,
macRomanEncodingSize);
#define winAnsiEncodingSize 256
-static char *winAnsiEncodingNames[winAnsiEncodingSize] = {
+static const char *winAnsiEncodingNames[winAnsiEncodingSize] = {
NULL,
NULL,
NULL,
//------------------------------------------------------------------------
struct BuiltinFont {
- char *name;
+ const char *name;
Gushort *widths;
FontEncoding *encoding;
};
FormWidget::FormWidget(Dict *dict) {
Object obj1, obj2;
+ double t;
ok = gFalse;
obj1.arrayGet(3, &obj2);
yMax = obj2.getNum();
obj2.free();
+ if (xMin > xMax) {
+ t = xMin; xMin = xMax; xMax = t;
+ }
+ if (yMin > yMax) {
+ t = yMin; yMin = yMax; yMax = t;
+ }
+ } else {
+ //~ this should return an error
+ xMin = yMin = 0;
+ xMax = yMax = 1;
}
obj1.free();
}
Object obj;
if (appearance.fetch(&obj)->isStream()) {
- gfx->doWidgetForm(&obj, xMin, yMin);
+ gfx->doWidgetForm(&obj, xMin, yMin, xMax, yMax);
}
obj.free();
}
if (annots->isArray()) {
for (i = 0; i < annots->arrayGetLength(); ++i) {
if (annots->arrayGet(i, &obj1)->isDict()) {
- if (obj1.dictLookup("Subtype", &obj2)->isName("Widget")) {
+ obj1.dictLookup("Subtype", &obj2);
+ if (obj2.isName("Widget") ||
+ obj2.isName("Stamp")) {
widget = new FormWidget(obj1.getDict());
if (widget->isOk()) {
if (nWidgets >= size) {
#include <stdio.h>
#include <stddef.h>
#include <string.h>
+#include <math.h>
#include "gmem.h"
#include "Object.h"
#include "Array.h"
GBool printCommands = gFalse;
//------------------------------------------------------------------------
-// Gfx
+// GfxResources
//------------------------------------------------------------------------
-Gfx::Gfx(OutputDev *out1, int pageNum, Dict *resDict,
- int dpi, double x1, double y1, double x2, double y2, GBool crop,
- double cropX1, double cropY1, double cropX2, double cropY2,
- int rotate) {
+GfxResources::GfxResources(Dict *resDict, GfxResources *next) {
Object obj1;
- // start the resource stack
- res = new GfxResources(NULL);
-
- // build font dictionary
- res->fonts = NULL;
if (resDict) {
+
+ // build font dictionary
+ fonts = NULL;
resDict->lookup("Font", &obj1);
- if (obj1.isDict())
- res->fonts = new GfxFontDict(obj1.getDict());
+ if (obj1.isDict()) {
+ fonts = new GfxFontDict(obj1.getDict());
+ }
obj1.free();
+
+ // get XObject dictionary
+ resDict->lookup("XObject", &xObjDict);
+
+ // get color space dictionary
+ resDict->lookup("ColorSpace", &colorSpaceDict);
+
+ // get pattern dictionary
+ resDict->lookup("Pattern", &patternDict);
+
+ // get graphics state parameter dictionary
+ resDict->lookup("ExtGState", &gStateDict);
+
+ } else {
+ fonts = NULL;
+ xObjDict.initNull();
+ colorSpaceDict.initNull();
+ patternDict.initNull();
+ gStateDict.initNull();
+ }
+
+ this->next = next;
+}
+
+GfxResources::~GfxResources() {
+ if (fonts) {
+ delete fonts;
+ }
+ xObjDict.free();
+ colorSpaceDict.free();
+ patternDict.free();
+ gStateDict.free();
+}
+
+GfxFont *GfxResources::lookupFont(const char *name) {
+ GfxFont *font;
+ GfxResources *resPtr;
+
+ for (resPtr = this; resPtr; resPtr = resPtr->next) {
+ if (resPtr->fonts) {
+ if ((font = resPtr->fonts->lookup(name)))
+ return font;
+ }
+ }
+ error(-1, "Unknown font tag '%s'", name);
+ return NULL;
+}
+
+GBool GfxResources::lookupXObject(const char *name, Object *obj) {
+ GfxResources *resPtr;
+
+ for (resPtr = this; resPtr; resPtr = resPtr->next) {
+ if (resPtr->xObjDict.isDict()) {
+ if (!resPtr->xObjDict.dictLookup(name, obj)->isNull())
+ return gTrue;
+ obj->free();
+ }
}
+ error(-1, "XObject '%s' is unknown", name);
+ return gFalse;
+}
+
+GBool GfxResources::lookupXObjectNF(const char *name, Object *obj) {
+ GfxResources *resPtr;
+
+ for (resPtr = this; resPtr; resPtr = resPtr->next) {
+ if (resPtr->xObjDict.isDict()) {
+ if (!resPtr->xObjDict.dictLookupNF(name, obj)->isNull())
+ return gTrue;
+ obj->free();
+ }
+ }
+ error(-1, "XObject '%s' is unknown", name);
+ return gFalse;
+}
+
+void GfxResources::lookupColorSpace(const char *name, Object *obj) {
+ GfxResources *resPtr;
+
+ for (resPtr = this; resPtr; resPtr = resPtr->next) {
+ if (resPtr->colorSpaceDict.isDict()) {
+ if (!resPtr->colorSpaceDict.dictLookup(name, obj)->isNull()) {
+ return;
+ }
+ obj->free();
+ }
+ }
+ obj->initNull();
+}
+
+GfxPattern *GfxResources::lookupPattern(const char *name) {
+ GfxResources *resPtr;
+ GfxPattern *pattern;
+ Object obj;
+
+ for (resPtr = this; resPtr; resPtr = resPtr->next) {
+ if (resPtr->patternDict.isDict()) {
+ if (!resPtr->patternDict.dictLookup(name, &obj)->isNull()) {
+ pattern = GfxPattern::parse(&obj);
+ obj.free();
+ return pattern;
+ }
+ obj.free();
+ }
+ }
+ error(-1, "Unknown pattern '%s'", name);
+ return NULL;
+}
+
+GBool GfxResources::lookupGState(const char *name, Object *obj) {
+ GfxResources *resPtr;
+
+ for (resPtr = this; resPtr; resPtr = resPtr->next) {
+ if (resPtr->gStateDict.isDict()) {
+ if (!resPtr->gStateDict.dictLookup(name, obj)->isNull()) {
+ return gTrue;
+ }
+ obj->free();
+ }
+ }
+ error(-1, "ExtGState '%s' is unknown", name);
+ return gFalse;
+}
+
+//------------------------------------------------------------------------
+// Gfx
+//------------------------------------------------------------------------
- // get XObject dictionary
- if (resDict)
- resDict->lookup("XObject", &res->xObjDict);
- else
- res->xObjDict.initNull();
+Gfx::Gfx(OutputDev *out1, int pageNum, Dict *resDict,
+ double dpi, double x1, double y1, double x2, double y2, GBool crop,
+ double cropX1, double cropY1, double cropX2, double cropY2,
+ int rotate) {
+ int i;
- // get colorspace dictionary
- if (resDict)
- resDict->lookup("ColorSpace", &res->colorSpaceDict);
- else
- res->colorSpaceDict.initNull();
+ // start the resource stack
+ res = new GfxResources(resDict, NULL);
// initialize
out = out1;
out->startPage(pageNum, state);
out->setDefaultCTM(state->getCTM());
out->updateAll(state);
+ for (i = 0; i < 6; ++i) {
+ baseMatrix[i] = state->getCTM()[i];
+ }
// set crop box
if (crop) {
}
out->endPage();
while (res) {
- resPtr = res->next;
+ resPtr = res->getNext();
delete res;
res = resPtr;
}
delete state;
}
-GfxResources::~GfxResources() {
- if (fonts)
- delete fonts;
- xObjDict.free();
- colorSpaceDict.free();
-}
-
-void Gfx::display(Object *obj) {
+void Gfx::display(Object *obj, GBool topLevel) {
Object obj2;
int i;
return;
}
parser = new Parser(new Lexer(obj));
- go();
+ go(topLevel);
delete parser;
parser = NULL;
}
-void Gfx::go() {
+void Gfx::go(GBool topLevel) {
Object obj;
Object args[maxArgs];
int numCmds, numArgs;
}
// update display
- if (numCmds > 0)
+ if (topLevel && numCmds > 0) {
out->dump();
+ }
// clean up
- if (printCommands)
+ if (printCommands) {
fflush(stdout);
+ }
}
void Gfx::execOp(Object *cmd, Object args[], int numArgs) {
Operator *op;
- char *name;
+ const char *name;
int i;
// find operator
(this->*op->func)(args, numArgs);
}
-Operator *Gfx::findOp(char *name) {
+Operator *Gfx::findOp(const char *name) {
int a, b, m, cmp;
a = -1;
return parser ? parser->getPos() : -1;
}
-GfxFont *Gfx::lookupFont(char *name) {
- GfxFont *font;
- GfxResources *resPtr;
-
- for (resPtr = res; resPtr; resPtr = resPtr->next) {
- if (resPtr->fonts) {
- if ((font = resPtr->fonts->lookup(name)))
- return font;
- }
- }
- error(getPos(), "unknown font tag '%s'", name);
- return NULL;
-}
-
-GBool Gfx::lookupXObject(char *name, Object *obj) {
- GfxResources *resPtr;
-
- for (resPtr = res; resPtr; resPtr = resPtr->next) {
- if (resPtr->xObjDict.isDict()) {
- if (!resPtr->xObjDict.dictLookup(name, obj)->isNull())
- return gTrue;
- obj->free();
- }
- }
- error(getPos(), "XObject '%s' is unknown", name);
- return gFalse;
-}
-
-void Gfx::lookupColorSpace(char *name, Object *obj) {
- GfxResources *resPtr;
-
- for (resPtr = res; resPtr; resPtr = resPtr->next) {
- if (resPtr->colorSpaceDict.isDict()) {
- if (!resPtr->colorSpaceDict.dictLookup(name, obj)->isNull())
- return;
- obj->free();
- }
- }
- obj->initNull();
-}
-
//------------------------------------------------------------------------
// graphics state operators
//------------------------------------------------------------------------
void Gfx::opSave(Object args[], int numArgs) {
+ (void)args;
+ (void)numArgs;
+
out->saveState(state);
state = state->save();
}
void Gfx::opRestore(Object args[], int numArgs) {
+ (void)args;
+ (void)numArgs;
+
state = state->restore();
out->restoreState(state);
}
void Gfx::opConcat(Object args[], int numArgs) {
+ (void)numArgs;
+
state->concatCTM(args[0].getNum(), args[1].getNum(),
args[2].getNum(), args[3].getNum(),
args[4].getNum(), args[5].getNum());
double *dash;
int i;
+ (void)numArgs;
+
a = args[0].getArray();
length = a->getLength();
if (length == 0) {
}
void Gfx::opSetExtGState(Object args[], int numArgs) {
+ Object obj1, obj2;
+
+ if (!res->lookupGState(args[0].getName(), &obj1)) {
+ return;
+ }
+ if (!obj1.isDict()) {
+ error(getPos(), "ExtGState '%s' is wrong type", args[0].getName());
+ obj1.free();
+ return;
+ }
+ if (obj1.dictLookup("ca", &obj2)->isNum()) {
+ state->setFillOpacity(obj2.getNum());
+ out->updateFillOpacity(state);
+ }
+ obj2.free();
+ if (obj1.dictLookup("CA", &obj2)->isNum()) {
+ state->setStrokeOpacity(obj2.getNum());
+ out->updateStrokeOpacity(state);
+ }
+ obj2.free();
+ obj1.free();
}
void Gfx::opSetRenderingIntent(Object args[], int numArgs) {
//------------------------------------------------------------------------
void Gfx::opSetFillGray(Object args[], int numArgs) {
- state->setFillColorSpace(new GfxColorSpace(colorGray));
- state->setFillGray(args[0].getNum());
+ GfxColor color;
+
+ state->setFillPattern(NULL);
+ state->setFillColorSpace(new GfxDeviceGrayColorSpace());
+ color.c[0] = args[0].getNum();
+ state->setFillColor(&color);
out->updateFillColor(state);
}
void Gfx::opSetStrokeGray(Object args[], int numArgs) {
- state->setStrokeColorSpace(new GfxColorSpace(colorGray));
- state->setStrokeGray(args[0].getNum());
+ GfxColor color;
+
+ state->setStrokePattern(NULL);
+ state->setStrokeColorSpace(new GfxDeviceGrayColorSpace());
+ color.c[0] = args[0].getNum();
+ state->setStrokeColor(&color);
out->updateStrokeColor(state);
}
void Gfx::opSetFillCMYKColor(Object args[], int numArgs) {
- state->setFillColorSpace(new GfxColorSpace(colorCMYK));
- state->setFillCMYK(args[0].getNum(), args[1].getNum(),
- args[2].getNum(), args[3].getNum());
+ GfxColor color;
+ int i;
+
+ state->setFillPattern(NULL);
+ state->setFillColorSpace(new GfxDeviceCMYKColorSpace());
+ for (i = 0; i < 4; ++i) {
+ color.c[i] = args[i].getNum();
+ }
+ state->setFillColor(&color);
out->updateFillColor(state);
}
void Gfx::opSetStrokeCMYKColor(Object args[], int numArgs) {
- state->setStrokeColorSpace(new GfxColorSpace(colorCMYK));
- state->setStrokeCMYK(args[0].getNum(), args[1].getNum(),
- args[2].getNum(), args[3].getNum());
+ GfxColor color;
+ int i;
+
+ state->setStrokePattern(NULL);
+ state->setStrokeColorSpace(new GfxDeviceCMYKColorSpace());
+ for (i = 0; i < 4; ++i) {
+ color.c[i] = args[i].getNum();
+ }
+ state->setStrokeColor(&color);
out->updateStrokeColor(state);
}
void Gfx::opSetFillRGBColor(Object args[], int numArgs) {
- state->setFillColorSpace(new GfxColorSpace(colorRGB));
- state->setFillRGB(args[0].getNum(), args[1].getNum(), args[2].getNum());
+ GfxColor color;
+ int i;
+
+ state->setFillPattern(NULL);
+ state->setFillColorSpace(new GfxDeviceRGBColorSpace());
+ for (i = 0; i < 3; ++i) {
+ color.c[i] = args[i].getNum();
+ }
+ state->setFillColor(&color);
out->updateFillColor(state);
}
void Gfx::opSetStrokeRGBColor(Object args[], int numArgs) {
- state->setStrokeColorSpace(new GfxColorSpace(colorRGB));
- state->setStrokeRGB(args[0].getNum(), args[1].getNum(), args[2].getNum());
+ GfxColor color;
+ int i;
+
+ state->setStrokePattern(NULL);
+ state->setStrokeColorSpace(new GfxDeviceRGBColorSpace());
+ for (i = 0; i < 3; ++i) {
+ color.c[i] = args[i].getNum();
+ }
+ state->setStrokeColor(&color);
out->updateStrokeColor(state);
}
void Gfx::opSetFillColorSpace(Object args[], int numArgs) {
Object obj;
GfxColorSpace *colorSpace;
- double x[4];
+ GfxColor color;
+ int i;
- lookupColorSpace(args[0].getName(), &obj);
- if (obj.isNull())
- colorSpace = new GfxColorSpace(&args[0]);
- else
- colorSpace = new GfxColorSpace(&obj);
+ state->setFillPattern(NULL);
+ res->lookupColorSpace(args[0].getName(), &obj);
+ if (obj.isNull()) {
+ colorSpace = GfxColorSpace::parse(&args[0]);
+ } else {
+ colorSpace = GfxColorSpace::parse(&obj);
+ }
obj.free();
- if (colorSpace->isOk()) {
+ if (colorSpace) {
state->setFillColorSpace(colorSpace);
} else {
- delete colorSpace;
- error(getPos(), "Bad colorspace");
+ error(getPos(), "Bad color space");
+ }
+ for (i = 0; i < gfxColorMaxComps; ++i) {
+ color.c[i] = 0;
}
- x[0] = x[1] = x[2] = x[3] = 0;
- state->setFillColor(x);
+ state->setFillColor(&color);
out->updateFillColor(state);
}
void Gfx::opSetStrokeColorSpace(Object args[], int numArgs) {
Object obj;
GfxColorSpace *colorSpace;
- double x[4];
+ GfxColor color;
+ int i;
- lookupColorSpace(args[0].getName(), &obj);
- if (obj.isNull())
- colorSpace = new GfxColorSpace(&args[0]);
- else
- colorSpace = new GfxColorSpace(&obj);
+ state->setStrokePattern(NULL);
+ res->lookupColorSpace(args[0].getName(), &obj);
+ if (obj.isNull()) {
+ colorSpace = GfxColorSpace::parse(&args[0]);
+ } else {
+ colorSpace = GfxColorSpace::parse(&obj);
+ }
obj.free();
- if (colorSpace->isOk()) {
+ if (colorSpace) {
state->setStrokeColorSpace(colorSpace);
} else {
- delete colorSpace;
- error(getPos(), "Bad colorspace");
+ error(getPos(), "Bad color space");
}
- x[0] = x[1] = x[2] = x[3] = 0;
- state->setStrokeColor(x);
+ for (i = 0; i < gfxColorMaxComps; ++i) {
+ color.c[i] = 0;
+ }
+ state->setStrokeColor(&color);
out->updateStrokeColor(state);
}
void Gfx::opSetFillColor(Object args[], int numArgs) {
- double x[4];
+ GfxColor color;
int i;
- x[0] = x[1] = x[2] = x[3] = 0;
- for (i = 0; i < numArgs; ++i)
- x[i] = args[i].getNum();
- state->setFillColor(x);
+ state->setFillPattern(NULL);
+ for (i = 0; i < numArgs; ++i) {
+ color.c[i] = args[i].getNum();
+ }
+ state->setFillColor(&color);
out->updateFillColor(state);
}
void Gfx::opSetStrokeColor(Object args[], int numArgs) {
- double x[4];
+ GfxColor color;
int i;
- x[0] = x[1] = x[2] = x[3] = 0;
- for (i = 0; i < numArgs; ++i)
- x[i] = args[i].getNum();
- state->setStrokeColor(x);
+ state->setStrokePattern(NULL);
+ for (i = 0; i < numArgs; ++i) {
+ color.c[i] = args[i].getNum();
+ }
+ state->setStrokeColor(&color);
out->updateStrokeColor(state);
}
void Gfx::opSetFillColorN(Object args[], int numArgs) {
- double x[4];
+ GfxColor color;
+ GfxPattern *pattern;
int i;
- x[0] = x[1] = x[2] = x[3] = 0;
- for (i = 0; i < numArgs && i < 4; ++i) {
- if (args[i].isNum())
- x[i] = args[i].getNum();
- else
- break;
+ if (state->getFillColorSpace()->getMode() == csPattern) {
+ if (numArgs > 1) {
+ for (i = 0; i < numArgs && i < 4; ++i) {
+ if (args[i].isNum()) {
+ color.c[i] = args[i].getNum();
+ }
+ }
+ state->setFillColor(&color);
+ out->updateFillColor(state);
+ }
+ if (args[numArgs-1].isName() &&
+ (pattern = res->lookupPattern(args[numArgs-1].getName()))) {
+ state->setFillPattern(pattern);
+ }
+
+ } else {
+ state->setFillPattern(NULL);
+ for (i = 0; i < numArgs && i < 4; ++i) {
+ if (args[i].isNum()) {
+ color.c[i] = args[i].getNum();
+ }
+ }
+ state->setFillColor(&color);
+ out->updateFillColor(state);
}
- state->setFillColor(x);
- out->updateFillColor(state);
}
void Gfx::opSetStrokeColorN(Object args[], int numArgs) {
- double x[4];
+ GfxColor color;
+ GfxPattern *pattern;
int i;
- x[0] = x[1] = x[2] = x[3] = 0;
- for (i = 0; i < numArgs && i < 4; ++i) {
- if (args[i].isNum())
- x[i] = args[i].getNum();
- else
- break;
+ if (state->getStrokeColorSpace()->getMode() == csPattern) {
+ if (numArgs > 1) {
+ for (i = 0; i < numArgs && i < 4; ++i) {
+ if (args[i].isNum()) {
+ color.c[i] = args[i].getNum();
+ }
+ }
+ state->setStrokeColor(&color);
+ out->updateStrokeColor(state);
+ }
+ if (args[numArgs-1].isName() &&
+ (pattern = res->lookupPattern(args[numArgs-1].getName()))) {
+ state->setStrokePattern(pattern);
+ }
+
+ } else {
+ state->setStrokePattern(NULL);
+ for (i = 0; i < numArgs && i < 4; ++i) {
+ if (args[i].isNum()) {
+ color.c[i] = args[i].getNum();
+ }
+ }
+ state->setStrokeColor(&color);
+ out->updateStrokeColor(state);
}
- state->setStrokeColor(x);
- out->updateStrokeColor(state);
}
//------------------------------------------------------------------------
//------------------------------------------------------------------------
void Gfx::opMoveTo(Object args[], int numArgs) {
+ (void)numArgs;
+
state->moveTo(args[0].getNum(), args[1].getNum());
}
void Gfx::opLineTo(Object args[], int numArgs) {
+ (void)numArgs;
+
if (!state->isCurPt()) {
error(getPos(), "No current point in lineto");
return;
void Gfx::opCurveTo(Object args[], int numArgs) {
double x1, y1, x2, y2, x3, y3;
+ (void)numArgs;
+
if (!state->isCurPt()) {
error(getPos(), "No current point in curveto");
return;
void Gfx::opCurveTo1(Object args[], int numArgs) {
double x1, y1, x2, y2, x3, y3;
+ (void)numArgs;
+
if (!state->isCurPt()) {
error(getPos(), "No current point in curveto1");
return;
void Gfx::opCurveTo2(Object args[], int numArgs) {
double x1, y1, x2, y2, x3, y3;
+ (void)numArgs;
+
if (!state->isCurPt()) {
error(getPos(), "No current point in curveto2");
return;
void Gfx::opRectangle(Object args[], int numArgs) {
double x, y, w, h;
+ (void)numArgs;
+
x = args[0].getNum();
y = args[1].getNum();
w = args[2].getNum();
}
void Gfx::opClosePath(Object args[], int numArgs) {
+ (void)args;
+ (void)numArgs;
+
if (!state->isPath()) {
error(getPos(), "No current point in closepath");
return;
//------------------------------------------------------------------------
void Gfx::opEndPath(Object args[], int numArgs) {
+ (void)args;
+ (void)numArgs;
+
doEndPath();
}
void Gfx::opStroke(Object args[], int numArgs) {
+ (void)args;
+ (void)numArgs;
+
if (!state->isCurPt()) {
//error(getPos(), "No path in stroke");
return;
}
void Gfx::opCloseStroke(Object args[], int numArgs) {
+ (void)args;
+ (void)numArgs;
+
if (!state->isCurPt()) {
//error(getPos(), "No path in closepath/stroke");
return;
}
void Gfx::opFill(Object args[], int numArgs) {
+ (void)args;
+ (void)numArgs;
+
if (!state->isCurPt()) {
//error(getPos(), "No path in fill");
return;
}
- if (state->isPath())
- out->fill(state);
+ if (state->isPath()) {
+ if (state->getFillColorSpace()->getMode() == csPattern) {
+ doPatternFill(gFalse);
+ } else {
+ out->fill(state);
+ }
+ }
doEndPath();
}
void Gfx::opEOFill(Object args[], int numArgs) {
+ (void)args;
+ (void)numArgs;
+
if (!state->isCurPt()) {
//error(getPos(), "No path in eofill");
return;
}
- if (state->isPath())
- out->eoFill(state);
+ if (state->isPath()) {
+ if (state->getFillColorSpace()->getMode() == csPattern) {
+ doPatternFill(gTrue);
+ } else {
+ out->eoFill(state);
+ }
+ }
doEndPath();
}
void Gfx::opFillStroke(Object args[], int numArgs) {
+ (void)args;
+ (void)numArgs;
+
if (!state->isCurPt()) {
//error(getPos(), "No path in fill/stroke");
return;
}
if (state->isPath()) {
- out->fill(state);
+ if (state->getFillColorSpace()->getMode() == csPattern) {
+ doPatternFill(gFalse);
+ } else {
+ out->fill(state);
+ }
out->stroke(state);
}
doEndPath();
}
void Gfx::opCloseFillStroke(Object args[], int numArgs) {
+ (void)args;
+ (void)numArgs;
+
if (!state->isCurPt()) {
//error(getPos(), "No path in closepath/fill/stroke");
return;
}
if (state->isPath()) {
state->closePath();
- out->fill(state);
+ if (state->getFillColorSpace()->getMode() == csPattern) {
+ doPatternFill(gFalse);
+ } else {
+ out->fill(state);
+ }
out->stroke(state);
}
doEndPath();
}
void Gfx::opEOFillStroke(Object args[], int numArgs) {
+ (void)args;
+ (void)numArgs;
+
if (!state->isCurPt()) {
//error(getPos(), "No path in eofill/stroke");
return;
}
if (state->isPath()) {
- out->eoFill(state);
+ if (state->getFillColorSpace()->getMode() == csPattern) {
+ doPatternFill(gTrue);
+ } else {
+ out->eoFill(state);
+ }
out->stroke(state);
}
doEndPath();
}
void Gfx::opCloseEOFillStroke(Object args[], int numArgs) {
+ (void)args;
+ (void)numArgs;
+
if (!state->isCurPt()) {
//error(getPos(), "No path in closepath/eofill/stroke");
return;
}
if (state->isPath()) {
state->closePath();
- out->eoFill(state);
+ if (state->getFillColorSpace()->getMode() == csPattern) {
+ doPatternFill(gTrue);
+ } else {
+ out->eoFill(state);
+ }
out->stroke(state);
}
doEndPath();
}
void Gfx::opShFill(Object args[], int numArgs) {
+ (void)args;
+ (void)numArgs;
+}
+
+void Gfx::doPatternFill(GBool eoFill) {
+ GfxPatternColorSpace *patCS;
+ GfxPattern *pattern;
+ GfxTilingPattern *tPat;
+ GfxColorSpace *cs;
+ GfxPath *path;
+ GfxSubpath *subpath;
+ double xMin, yMin, xMax, yMax, x, y, x1, y1;
+ int xi0, yi0, xi1, yi1, xi, yi;
+ double *ctm, *btm, *ptm;
+ double m[6], ictm[6], m1[6], im[6];
+ double det;
+ double xstep, ystep;
+ int i, j;
+
+ // get color space
+ patCS = (GfxPatternColorSpace *)state->getFillColorSpace();
+
+ // get pattern
+ if (!(pattern = state->getFillPattern())) {
+ return;
+ }
+ if (pattern->getType() != 1) {
+ return;
+ }
+ tPat = (GfxTilingPattern *)pattern;
+
+ // construct a (pattern space) -> (current space) transform matrix
+ ctm = state->getCTM();
+ btm = baseMatrix;
+ ptm = tPat->getMatrix();
+ // iCTM = invert CTM
+ det = 1 / (ctm[0] * ctm[3] - ctm[1] * ctm[2]);
+ ictm[0] = ctm[3] * det;
+ ictm[1] = -ctm[1] * det;
+ ictm[2] = -ctm[2] * det;
+ ictm[3] = ctm[0] * det;
+ ictm[4] = (ctm[2] * ctm[5] - ctm[3] * ctm[4]) * det;
+ ictm[5] = (ctm[1] * ctm[4] - ctm[0] * ctm[5]) * det;
+ // m1 = PTM * BTM = PTM * base transform matrix
+ m1[0] = ptm[0] * btm[0] + ptm[1] * btm[2];
+ m1[1] = ptm[0] * btm[1] + ptm[1] * btm[3];
+ m1[2] = ptm[2] * btm[0] + ptm[3] * btm[2];
+ m1[3] = ptm[2] * btm[1] + ptm[3] * btm[3];
+ m1[4] = ptm[4] * btm[0] + ptm[5] * btm[2] + btm[4];
+ m1[5] = ptm[4] * btm[1] + ptm[5] * btm[3] + btm[5];
+ // m = m1 * iCTM = (PTM * BTM) * (iCTM)
+ m[0] = m1[0] * ictm[0] + m1[1] * ictm[2];
+ m[1] = m1[0] * ictm[1] + m1[1] * ictm[3];
+ m[2] = m1[2] * ictm[0] + m1[3] * ictm[2];
+ m[3] = m1[2] * ictm[1] + m1[3] * ictm[3];
+ m[4] = m1[4] * ictm[0] + m1[5] * ictm[2] + ictm[4];
+ m[5] = m1[4] * ictm[1] + m1[5] * ictm[3] + ictm[5];
+
+ // construct a (current space) -> (pattern space) transform matrix
+ det = 1 / (m[0] * m[3] - m[1] * m[2]);
+ im[0] = m[3] * det;
+ im[1] = -m[1] * det;
+ im[2] = -m[2] * det;
+ im[3] = m[0] * det;
+ im[4] = (m[2] * m[5] - m[3] * m[4]) * det;
+ im[5] = (m[1] * m[4] - m[0] * m[5]) * det;
+
+ // compute bounding box of current path, in pattern space
+ xMin = xMax = yMin = yMax = 0; // make gcc happy
+ path = state->getPath();
+ for (i = 0; i < path->getNumSubpaths(); ++i) {
+ subpath = path->getSubpath(i);
+ for (j = 0; j < subpath->getNumPoints(); ++j) {
+ x = subpath->getX(j);
+ y = subpath->getY(j);
+ x1 = x * im[0] + y * im[2] + im[4];
+ y1 = x * im[1] + y * im[3] + im[5];
+ if (i == 0 && j == 0) {
+ xMin = xMax = x1;
+ yMin = yMax = y1;
+ } else {
+ if (x1 < xMin) {
+ xMin = x1;
+ } else if (x1 > xMax) {
+ xMax = x1;
+ }
+ if (y1 < yMin) {
+ yMin = y1;
+ } else if (y1 > yMax) {
+ yMax = y1;
+ }
+ }
+ }
+ }
+
+ // save current graphics state
+ out->saveState(state);
+ state = state->save();
+
+ // set underlying color space (for uncolored tiling patterns)
+ if (tPat->getPaintType() == 2 && (cs = patCS->getUnder())) {
+ state->setFillColorSpace(cs->copy());
+ } else {
+ state->setFillColorSpace(new GfxDeviceGrayColorSpace());
+ }
+ state->setFillPattern(NULL);
+ out->updateFillColor(state);
+
+ // clip to current path
+ if (eoFill) {
+ out->eoClip(state);
+ } else {
+ out->clip(state);
+ }
+ state->clearPath();
+
+ // draw the pattern
+ //~ this should treat negative steps differently -- start at right/top
+ //~ edge instead of left/bottom (?)
+ xstep = fabs(tPat->getXStep());
+ ystep = fabs(tPat->getYStep());
+ xi0 = (int)floor(xMin / xstep);
+ xi1 = (int)ceil(xMax / xstep);
+ yi0 = (int)floor(yMin / ystep);
+ yi1 = (int)ceil(yMax / ystep);
+ for (i = 0; i < 4; ++i) {
+ m1[i] = m[i];
+ }
+ for (yi = yi0; yi < yi1; ++yi) {
+ for (xi = xi0; xi < xi1; ++xi) {
+ x = xi * xstep;
+ y = yi * ystep;
+ m1[4] = x * m[0] + y * m[2] + m[4];
+ m1[5] = x * m[1] + y * m[3] + m[5];
+ doForm1(tPat->getContentStream(), tPat->getResDict(),
+ m1, tPat->getBBox());
+ }
+ }
+
+ // restore graphics state
+ state = state->restore();
+ out->restoreState(state);
}
void Gfx::doEndPath() {
//------------------------------------------------------------------------
void Gfx::opClip(Object args[], int numArgs) {
+ (void)args;
+ (void)numArgs;
+
clip = clipNormal;
}
void Gfx::opEOClip(Object args[], int numArgs) {
+ (void)args;
+ (void)numArgs;
+
clip = clipEO;
}
//------------------------------------------------------------------------
void Gfx::opBeginText(Object args[], int numArgs) {
+ (void)args;
+ (void)numArgs;
+
state->setTextMat(1, 0, 0, 1, 0, 0);
state->textMoveTo(0, 0);
out->updateTextMat(state);
}
void Gfx::opEndText(Object args[], int numArgs) {
+ (void)args;
+ (void)numArgs;
}
//------------------------------------------------------------------------
//------------------------------------------------------------------------
void Gfx::opSetCharSpacing(Object args[], int numArgs) {
+ (void)args;
+ (void)numArgs;
+
state->setCharSpace(args[0].getNum());
out->updateCharSpace(state);
}
void Gfx::opSetFont(Object args[], int numArgs) {
GfxFont *font;
- if (!(font = lookupFont(args[0].getName())))
+ if (!(font = res->lookupFont(args[0].getName()))) {
return;
+ }
if (printCommands) {
printf(" font: '%s' %g\n",
font->getName() ? font->getName()->getCString() : "???",
}
void Gfx::opSetTextLeading(Object args[], int numArgs) {
+ (void)numArgs;
+
state->setLeading(args[0].getNum());
}
void Gfx::opSetTextRender(Object args[], int numArgs) {
+ (void)numArgs;
+
state->setRender(args[0].getInt());
out->updateRender(state);
}
void Gfx::opSetTextRise(Object args[], int numArgs) {
+ (void)numArgs;
+
state->setRise(args[0].getNum());
out->updateRise(state);
}
void Gfx::opSetWordSpacing(Object args[], int numArgs) {
+ (void)numArgs;
+
state->setWordSpace(args[0].getNum());
out->updateWordSpace(state);
}
void Gfx::opSetHorizScaling(Object args[], int numArgs) {
+ (void)numArgs;
+
state->setHorizScaling(args[0].getNum());
out->updateHorizScaling(state);
}
void Gfx::opTextMove(Object args[], int numArgs) {
double tx, ty;
+ (void)numArgs;
+
tx = state->getLineX() + args[0].getNum();
ty = state->getLineY() + args[1].getNum();
state->textMoveTo(tx, ty);
void Gfx::opTextMoveSet(Object args[], int numArgs) {
double tx, ty;
+ (void)numArgs;
+
tx = state->getLineX() + args[0].getNum();
ty = args[1].getNum();
state->setLeading(-ty);
}
void Gfx::opSetTextMatrix(Object args[], int numArgs) {
+ (void)numArgs;
+
state->setTextMat(args[0].getNum(), args[1].getNum(),
args[2].getNum(), args[3].getNum(),
args[4].getNum(), args[5].getNum());
void Gfx::opTextNextLine(Object args[], int numArgs) {
double tx, ty;
+ (void)args;
+ (void)numArgs;
+
tx = state->getLineX();
ty = state->getLineY() - state->getLeading();
state->textMoveTo(tx, ty);
//------------------------------------------------------------------------
void Gfx::opShowText(Object args[], int numArgs) {
+ (void)numArgs;
+
if (!state->getFont()) {
error(getPos(), "No font in show");
return;
void Gfx::opMoveShowText(Object args[], int numArgs) {
double tx, ty;
+ (void)numArgs;
+
if (!state->getFont()) {
error(getPos(), "No font in move/show");
return;
void Gfx::opMoveSetShowText(Object args[], int numArgs) {
double tx, ty;
+ (void)numArgs;
+
if (!state->getFont()) {
error(getPos(), "No font in move/set/show");
return;
Object obj;
int i;
+ (void)numArgs;
+
if (!state->getFont()) {
error(getPos(), "No font in show/space");
return;
state->setCTM(newCTM[0], newCTM[1], newCTM[2], newCTM[3], x, y);
//~ out->updateCTM(???)
if (charProc.isStream()) {
- display(&charProc);
+ display(&charProc, gFalse);
} else {
error(getPos(), "Missing or bad Type3 CharProc entry");
}
//------------------------------------------------------------------------
void Gfx::opXObject(Object args[], int numArgs) {
- Object obj1, obj2;
+ Object obj1, obj2, refObj;
#if OPI_SUPPORT
Object opiDict;
#endif
- if (!lookupXObject(args[0].getName(), &obj1))
+ if (!res->lookupXObject(args[0].getName(), &obj1)) {
return;
+ }
if (!obj1.isStream()) {
error(getPos(), "XObject '%s' is wrong type", args[0].getName());
obj1.free();
}
#endif
obj1.streamGetDict()->lookup("Subtype", &obj2);
- if (obj2.isName("Image"))
- doImage(obj1.getStream(), gFalse);
- else if (obj2.isName("Form"))
+ if (obj2.isName("Image")) {
+ res->lookupXObjectNF(args[0].getName(), &refObj);
+ doImage(&refObj, obj1.getStream(), gFalse);
+ refObj.free();
+ } else if (obj2.isName("Form")) {
doForm(&obj1);
- else if (obj2.isName())
+ } else if (obj2.isName()) {
error(getPos(), "Unknown XObject subtype '%s'", obj2.getName());
- else
+ } else {
error(getPos(), "XObject subtype is missing or wrong type");
+ }
obj2.free();
#if OPI_SUPPORT
if (opiDict.isDict()) {
obj1.free();
}
-void Gfx::doImage(Stream *str, GBool inlineImg) {
+void Gfx::doImage(Object *ref, Stream *str, GBool inlineImg) {
Dict *dict;
Object obj1, obj2;
int width, height;
obj1.free();
// draw it
- out->drawImageMask(state, str, width, height, invert, inlineImg);
+ out->drawImageMask(state, ref, str, width, height, invert, inlineImg);
} else {
dict->lookup("CS", &obj1);
}
if (obj1.isName()) {
- lookupColorSpace(obj1.getName(), &obj2);
+ res->lookupColorSpace(obj1.getName(), &obj2);
if (!obj2.isNull()) {
obj1.free();
obj1 = obj2;
obj2.free();
}
}
- colorSpace = new GfxColorSpace(&obj1);
+ colorSpace = GfxColorSpace::parse(&obj1);
obj1.free();
- if (!colorSpace->isOk()) {
- delete colorSpace;
+ if (!colorSpace) {
goto err1;
}
dict->lookup("Decode", &obj1);
colorMap = new GfxImageColorMap(bits, &obj1, colorSpace);
obj1.free();
if (!colorMap->isOk()) {
- delete colorSpace;
+ delete colorMap;
goto err1;
}
// draw it
- out->drawImage(state, str, width, height, colorMap, inlineImg);
+ out->drawImage(state, ref, str, width, height, colorMap, inlineImg);
delete colorMap;
+ str->close();
}
return;
void Gfx::doForm(Object *str) {
Dict *dict;
Object matrixObj, bboxObj;
+ double m[6], bbox[6];
+ Object resObj;
+ Dict *resDict;
Object obj1;
+ int i;
// get stream dict
dict = str->streamGetDict();
}
obj1.free();
- // get matrix and bounding box
- dict->lookup("Matrix", &matrixObj);
- if (!matrixObj.isArray()) {
- matrixObj.free();
- error(getPos(), "Bad form matrix");
- return;
- }
+ // get bounding box
dict->lookup("BBox", &bboxObj);
if (!bboxObj.isArray()) {
matrixObj.free();
error(getPos(), "Bad form bounding box");
return;
}
+ for (i = 0; i < 4; ++i) {
+ bboxObj.arrayGet(i, &obj1);
+ bbox[i] = obj1.getNum();
+ obj1.free();
+ }
+ bboxObj.free();
- doForm1(str, dict, &matrixObj, &bboxObj);
-
+ // get matrix
+ dict->lookup("Matrix", &matrixObj);
+ if (matrixObj.isArray()) {
+ for (i = 0; i < 6; ++i) {
+ matrixObj.arrayGet(i, &obj1);
+ m[i] = obj1.getNum();
+ obj1.free();
+ }
+ } else {
+ m[0] = 1; m[1] = 0;
+ m[2] = 0; m[3] = 1;
+ m[4] = 0; m[5] = 0;
+ }
matrixObj.free();
- bboxObj.free();
+
+ // get resources
+ dict->lookup("Resources", &resObj);
+ resDict = resObj.isDict() ? resObj.getDict() : NULL;
+
+ // draw it
+ doForm1(str, resDict, m, bbox);
+
+ resObj.free();
}
-void Gfx::doWidgetForm(Object *str, double x, double y) {
- Dict *dict;
- Object matrixObj, bboxObj;
+void Gfx::doWidgetForm(Object *str, double xMin, double yMin,
+ double xMax, double yMax) {
+ Dict *dict, *resDict;
+ Object matrixObj, bboxObj, resObj;
Object obj1;
+ double m[6], bbox[6];
+ double sx, sy;
+ int i;
// get stream dict
dict = str->streamGetDict();
error(getPos(), "Bad form bounding box");
return;
}
+ for (i = 0; i < 4; ++i) {
+ bboxObj.arrayGet(i, &obj1);
+ bbox[i] = obj1.getNum();
+ obj1.free();
+ }
+ bboxObj.free();
- // construct matrix
- matrixObj.initArray();
- obj1.initReal(1);
- matrixObj.arrayAdd(&obj1);
- obj1.initReal(0);
- matrixObj.arrayAdd(&obj1);
- obj1.initReal(0);
- matrixObj.arrayAdd(&obj1);
- obj1.initReal(1);
- matrixObj.arrayAdd(&obj1);
- obj1.initReal(x);
- matrixObj.arrayAdd(&obj1);
- obj1.initReal(y);
- matrixObj.arrayAdd(&obj1);
+ // get matrix
+ dict->lookup("Matrix", &matrixObj);
+ if (matrixObj.isArray()) {
+ for (i = 0; i < 6; ++i) {
+ matrixObj.arrayGet(i, &obj1);
+ m[i] = obj1.getNum();
+ obj1.free();
+ }
+ } else {
+ m[0] = 1; m[1] = 0;
+ m[2] = 0; m[3] = 1;
+ m[4] = 0; m[5] = 0;
+ }
+ matrixObj.free();
- doForm1(str, dict, &matrixObj, &bboxObj);
+ // scale form bbox to widget rectangle
+ sx = fabs((xMax - xMin) / (bbox[2] - bbox[0]));
+ sy = fabs((yMax - yMin) / (bbox[3] - bbox[1]));
+ m[0] *= sx; m[1] *= sy;
+ m[2] *= sx; m[3] *= sy;
+ m[4] *= sx; m[5] *= sy;
- matrixObj.free();
+ // translate to widget rectangle
+ m[4] += xMin;
+ m[5] += yMin;
+
+ // get resources
+ dict->lookup("Resources", &resObj);
+ resDict = resObj.isDict() ? resObj.getDict() : NULL;
+
+ // draw it
+ doForm1(str, resDict, m, bbox);
+
+ resObj.free();
bboxObj.free();
}
-void Gfx::doForm1(Object *str, Dict *dict,
- Object *matrixObj, Object *bboxObj) {
+void Gfx::doForm1(Object *str, Dict *resDict, double *matrix, double *bbox) {
Parser *oldParser;
+ double oldBaseMatrix[6];
GfxResources *resPtr;
- Dict *resDict;
- double m[6];
- Object obj1, obj2;
int i;
// push new resources on stack
- res = new GfxResources(res);
- dict->lookup("Resources", &obj1);
- if (obj1.isDict()) {
- resDict = obj1.getDict();
- res->fonts = NULL;
- resDict->lookup("Font", &obj2);
- if (obj2.isDict())
- res->fonts = new GfxFontDict(obj2.getDict());
- obj2.free();
- resDict->lookup("XObject", &res->xObjDict);
- resDict->lookup("ColorSpace", &res->colorSpaceDict);
- obj1.free();
- }
+ res = new GfxResources(resDict, res);
// save current graphics state
out->saveState(state);
oldParser = parser;
// set form transformation matrix
+ state->concatCTM(matrix[0], matrix[1], matrix[2],
+ matrix[3], matrix[4], matrix[5]);
+ out->updateCTM(state, matrix[0], matrix[1], matrix[2],
+ matrix[3], matrix[4], matrix[5]);
+
+ // set new base matrix
for (i = 0; i < 6; ++i) {
- matrixObj->arrayGet(i, &obj1);
- m[i] = obj1.getNum();
- obj1.free();
+ oldBaseMatrix[i] = baseMatrix[i];
+ baseMatrix[i] = state->getCTM()[i];
}
- state->concatCTM(m[0], m[1], m[2], m[3], m[4], m[5]);
- out->updateCTM(state, m[0], m[1], m[2], m[3], m[4], m[5]);
// set form bounding box
- for (i = 0; i < 4; ++i) {
- bboxObj->arrayGet(i, &obj1);
- m[i] = obj1.getNum();
- obj1.free();
- }
- state->moveTo(m[0], m[1]);
- state->lineTo(m[2], m[1]);
- state->lineTo(m[2], m[3]);
- state->lineTo(m[0], m[3]);
+ state->moveTo(bbox[0], bbox[1]);
+ state->lineTo(bbox[2], bbox[1]);
+ state->lineTo(bbox[2], bbox[3]);
+ state->lineTo(bbox[0], bbox[3]);
state->closePath();
out->clip(state);
state->clearPath();
// draw the form
- display(str);
+ display(str, gFalse);
+
+ // restore base matrix
+ for (i = 0; i < 6; ++i) {
+ baseMatrix[i] = oldBaseMatrix[i];
+ }
// restore parser
parser = oldParser;
out->restoreState(state);
// pop resource stack
- resPtr = res->next;
+ resPtr = res->getNext();
delete res;
res = resPtr;
Stream *str;
int c1, c2;
+ (void)args;
+ (void)numArgs;
+
// build dict/stream
str = buildImageStream();
// display the image
if (str) {
- doImage(str, gTrue);
+ doImage(NULL, str, gTrue);
// skip 'EI' tag
c1 = str->getBaseStream()->getChar();
Stream *Gfx::buildImageStream() {
Object dict;
Object obj;
- char *key;
+ const char *key;
Stream *str;
// build dictionary
}
void Gfx::opImageData(Object args[], int numArgs) {
+ (void)args;
+ (void)numArgs;
+
error(getPos(), "Internal: got 'ID' operator");
}
void Gfx::opEndImage(Object args[], int numArgs) {
+ (void)args;
+ (void)numArgs;
+
error(getPos(), "Internal: got 'EI' operator");
}
//------------------------------------------------------------------------
void Gfx::opSetCharWidth(Object args[], int numArgs) {
+ (void)args;
+ (void)numArgs;
+
error(getPos(), "Encountered 'd0' operator in content stream");
}
void Gfx::opSetCacheDevice(Object args[], int numArgs) {
+ (void)args;
+ (void)numArgs;
+
error(getPos(), "Encountered 'd1' operator in content stream");
}
//------------------------------------------------------------------------
void Gfx::opBeginIgnoreUndef(Object args[], int numArgs) {
+ (void)args;
+ (void)numArgs;
+
++ignoreUndef;
}
void Gfx::opEndIgnoreUndef(Object args[], int numArgs) {
+ (void)args;
+ (void)numArgs;
+
if (ignoreUndef > 0)
--ignoreUndef;
}
//------------------------------------------------------------------------
void Gfx::opBeginMarkedContent(Object args[], int numArgs) {
+ (void)numArgs;
+
if (printCommands) {
printf(" marked content: %s ", args[0].getName());
if (numArgs == 2)
}
void Gfx::opEndMarkedContent(Object args[], int numArgs) {
+ (void)args;
+ (void)numArgs;
}
void Gfx::opMarkPoint(Object args[], int numArgs) {
+ (void)numArgs;
+
if (printCommands) {
printf(" mark point: %s ", args[0].getName());
if (numArgs == 2)
class GfxFontDict;
class GfxFont;
struct GfxFontEncoding16;
+class GfxPattern;
class GfxState;
class Gfx;
class GfxResources {
public:
- GfxResources(GfxResources *next1) { fonts = NULL; next = next1; }
+ GfxResources(Dict *resDict, GfxResources *next);
~GfxResources();
+ GfxFont *lookupFont(const char *name);
+ GBool lookupXObject(const char *name, Object *obj);
+ GBool lookupXObjectNF(const char *name, Object *obj);
+ void lookupColorSpace(const char *name, Object *obj);
+ GfxPattern *lookupPattern(const char *name);
+ GBool lookupGState(const char *name, Object *obj);
+
+ GfxResources *getNext() { return next; }
+
+private:
+
GfxFontDict *fonts;
Object xObjDict;
Object colorSpaceDict;
+ Object patternDict;
+ Object gStateDict;
GfxResources *next;
};
// Constructor for regular output.
Gfx(OutputDev *out1, int pageNum, Dict *resDict,
- int dpi, double x1, double y1, double x2, double y2, GBool crop,
+ double dpi, double x1, double y1, double x2, double y2, GBool crop,
double cropX1, double cropY1, double cropX2, double cropY2,
int rotate);
~Gfx();
// Interpret a stream or array of streams.
- void display(Object *obj);
+ void display(Object *obj, GBool topLevel = gTrue);
- void doWidgetForm(Object *str, double x, double y);
+ void doWidgetForm(Object *str, double xMin, double yMin,
+ double xMax, double yMax);
private:
GBool fontChanged; // set if font or text matrix has changed
GfxClipType clip; // do a clip?
int ignoreUndef; // current BX/EX nesting level
+ double baseMatrix[6]; // default matrix for most recent
+ // page/form/pattern
Parser *parser; // parser for page content stream(s)
static Operator opTab[]; // table of operators
- void go();
+ void go(GBool topLevel);
void execOp(Object *cmd, Object args[], int numArgs);
- Operator *findOp(char *name);
+ Operator *findOp(const char *name);
GBool checkArg(Object *arg, TchkType type);
int getPos();
- GfxFont *lookupFont(char *name);
- GBool lookupXObject(char *name, Object *obj);
- void lookupColorSpace(char *name, Object *obj);
// graphics state operators
void opSave(Object args[], int numArgs);
void opEOFillStroke(Object args[], int numArgs);
void opCloseEOFillStroke(Object args[], int numArgs);
void opShFill(Object args[], int numArgs);
+ void doPatternFill(GBool eoFill);
void doEndPath();
// path clipping operators
// XObject operators
void opXObject(Object args[], int numArgs);
- void doImage(Stream *str, GBool inlineImg);
+ void doImage(Object *ref, Stream *str, GBool inlineImg);
void doForm(Object *str);
- void doForm1(Object *str, Dict *dict,
- Object *matrixObj, Object *bboxObj);
+ void doForm1(Object *str, Dict *resDict, double *matrix, double *bbox);
// in-line image operators
void opBeginImage(Object args[], int numArgs);
#if JAPANESE_SUPPORT
#include "Japan12CMapInfo.h"
#endif
-#if CHINESE_SUPPORT
+#if CHINESE_GB_SUPPORT
#include "GB12CMapInfo.h"
#endif
+#if CHINESE_CNS_SUPPORT
+#include "CNS13CMapInfo.h"
+#endif
//------------------------------------------------------------------------
-static int CDECL cmpWidthExcep(const void *w1, const void *w2);
-static int CDECL cmpWidthExcepV(const void *w1, const void *w2);
+#if defined(JAPANESE_SUPPORT) || defined(CHINESE_GB_SUPPORT) || defined(CHINESE_CNS_SUPPORT)
+extern "C" {
+static int cmpWidthExcep(const void *w1, const void *w2);
+static int cmpWidthExcepV(const void *w1, const void *w2);
+}
+#endif /* JAPANESE_SUPPORT || CHINESE_GB_SUPPORT || CHINESE_CNS_SUPPORT */
//------------------------------------------------------------------------
// GfxFont
//------------------------------------------------------------------------
-GfxFont::GfxFont(char *tag1, Ref id1, Dict *fontDict) {
+GfxFont::GfxFont(const char *tag1, Ref id1, Dict *fontDict) {
BuiltinFont *builtinFont;
Object obj1, obj2, obj3, obj4;
int missingWidth;
- char *name2, *p;
+ const char *name2, *p;
int i;
// get font tag and ID
tag = new GString(tag1);
id = id1;
- // get base font name
- name = NULL;
- fontDict->lookup("BaseFont", &obj1);
- if (obj1.isName())
- name = new GString(obj1.getName());
- obj1.free();
-
- // is it a built-in font?
- builtinFont = NULL;
- if (name) {
- for (i = 0; i < numBuiltinFonts; ++i) {
- if (!strcmp(builtinFonts[i].name, name->getCString())) {
- builtinFont = &builtinFonts[i];
- break;
- }
- }
- }
-
// get font type
type = fontUnknownType;
fontDict->lookup("Subtype", &obj1);
obj1.free();
is16 = gFalse;
- // assume Times-Roman by default (for substitution purposes)
- flags = fontSerif;
+ // get base font name
+ name = NULL;
+ fontDict->lookup("BaseFont", &obj1);
+ if (obj1.isName())
+ name = new GString(obj1.getName());
+ obj1.free();
// Newer Adobe tools are using Base14-compatible TrueType fonts
// without embedding them, so munge the names into the equivalent
if (!strncmp(p, "Arial", 5)) {
if (!strcmp(p+5, ",Bold")) {
name2 = "Helvetica-Bold";
- } else if (!strcmp(p+5, "Italic")) {
+ } else if (!strcmp(p+5, ",Italic")) {
name2 = "Helvetica-Oblique";
- } else if (!strcmp(p+5, "BoldItalic")) {
+ } else if (!strcmp(p+5, ",BoldItalic")) {
name2 = "Helvetica-BoldOblique";
} else {
name2 = "Helvetica";
}
} else if (!strncmp(p, "TimesNewRoman", 13)) {
- if (!strcmp(p+5, ",Bold")) {
+ if (!strcmp(p+13, ",Bold")) {
name2 = "Times-Bold";
- } else if (!strcmp(p+5, "Italic")) {
+ } else if (!strcmp(p+13, ",Italic")) {
name2 = "Times-Italic";
- } else if (!strcmp(p+5, "BoldItalic")) {
+ } else if (!strcmp(p+13, ",BoldItalic")) {
name2 = "Times-BoldItalic";
} else {
name2 = "Times-Roman";
}
} else if (!strncmp(p, "CourierNew", 10)) {
- if (!strcmp(p+5, ",Bold")) {
+ if (!strcmp(p+10, ",Bold")) {
name2 = "Courier-Bold";
- } else if (!strcmp(p+5, "Italic")) {
+ } else if (!strcmp(p+10, ",Italic")) {
name2 = "Courier-Oblique";
- } else if (!strcmp(p+5, "BoldItalic")) {
+ } else if (!strcmp(p+10, ",BoldItalic")) {
name2 = "Courier-BoldOblique";
} else {
name2 = "Courier";
}
}
+ // is it a built-in font?
+ builtinFont = NULL;
+ if (name) {
+ for (i = 0; i < numBuiltinFonts; ++i) {
+ if (!strcmp(builtinFonts[i].name, name->getCString())) {
+ builtinFont = &builtinFonts[i];
+ break;
+ }
+ }
+ }
+
+ // assume Times-Roman by default (for substitution purposes)
+ flags = fontSerif;
+
// get info from font descriptor
embFontName = NULL;
embFontID.num = -1;
void GfxFont::getEncAndWidths(Dict *fontDict, BuiltinFont *builtinFont,
int missingWidth) {
Object obj1, obj2, obj3;
- char *buf;
+ const char *buf;
int len;
FontFile *fontFile;
int code, i;
if (!encoding)
encoding = fontFile->getEncoding(gTrue);
delete fontFile;
- gfree(buf);
+ gfree((void *)buf);
}
}
}
void GfxFont::findExtFontFile() {
- char **path;
+ const char **path;
FILE *f;
for (path = fontPath; *path; ++path) {
}
}
-char *GfxFont::readExtFontFile(int *len) {
+const char *GfxFont::readExtFontFile(int *len) {
FILE *f;
char *buf;
return buf;
}
-char *GfxFont::readEmbFontFile(int *len) {
+const char *GfxFont::readEmbFontFile(int *len) {
char *buf;
Object obj1, obj2;
Stream *str;
buf[i++] = c;
}
*len = i;
+ str->close();
obj2.free();
obj1.free();
Object obj1, obj2;
int firstChar, lastChar;
int code, code2;
- char *charName;
+ const char *charName;
Gushort *defWidths;
int index;
double mult;
void GfxFont::getType0EncAndWidths(Dict *fontDict) {
Object obj1, obj2, obj3, obj4, obj5, obj6, obj7, obj8;
+#if defined(JAPANESE_SUPPORT) || defined(CHINESE_GB_SUPPORT) || defined(CHINESE_CNS_SUPPORT)
int excepsSize;
int i, j, k, n;
+#endif /* JAPANESE_SUPPORT || CHINESE_GB_SUPPORT || CHINESE_CNS_SUPPORT */
widths16.exceps = NULL;
widths16.excepsV = NULL;
#endif
} else if (obj4.getString()->cmp("Adobe") == 0 &&
obj5.getString()->cmp("GB1") == 0) {
-#if CHINESE_SUPPORT
+#if CHINESE_GB_SUPPORT
is16 = gTrue;
enc16.charSet = font16AdobeGB12;
#else
- error(-1, "Xpdf was compiled without Chinese font support");
+ error(-1, "Xpdf was compiled without Chinese GB font support");
+ goto err4;
+#endif
+ } else if (obj4.getString()->cmp("Adobe") == 0 &&
+ obj5.getString()->cmp("CNS1") == 0) {
+#if CHINESE_CNS_SUPPORT
+ is16 = gTrue;
+ enc16.charSet = font16AdobeCNS13;
+#else
+ error(-1, "Xpdf was compiled without Chinese CNS font support");
goto err4;
#endif
} else {
error(-1, "Unknown Type 0 character set");
goto err4;
}
+
+#if defined(JAPANESE_SUPPORT) || defined(CHINESE_GB_SUPPORT) || defined(CHINESE_CNS_SUPPORT)
obj5.free();
obj4.free();
obj3.free();
error(-1, "Bad encoding for Type 0 font");
goto err1;
}
-#if JAPANESE_SUPPORT
+# if JAPANESE_SUPPORT
if (enc16.charSet == font16AdobeJapan12) {
for (i = 0; gfxJapan12Tab[i].name; ++i) {
if (!strcmp(obj1.getName(), gfxJapan12Tab[i].name))
}
enc16.enc = gfxJapan12Tab[i].enc;
}
-#endif
-#if CHINESE_SUPPORT
+# endif
+# if CHINESE_GB_SUPPORT
if (enc16.charSet == font16AdobeGB12) {
for (i = 0; gfxGB12Tab[i].name; ++i) {
if (!strcmp(obj1.getName(), gfxGB12Tab[i].name))
}
enc16.enc = gfxGB12Tab[i].enc;
}
-#endif
+# endif
+# if CHINESE_CNS_SUPPORT
+ if (enc16.charSet == font16AdobeCNS13) {
+ for (i = 0; gfxCNS13Tab[i].name; ++i) {
+ if (!strcmp(obj1.getName(), gfxCNS13Tab[i].name))
+ break;
+ }
+ if (!gfxCNS13Tab[i].name) {
+ error(-1, "Unknown encoding '%s' for Adobe-CNS1-3 font",
+ obj1.getName());
+ goto err1;
+ }
+ enc16.enc = gfxCNS13Tab[i].enc;
+ }
+# endif
obj1.free();
return;
+#endif /* JAPANESE_SUPPORT || CHINESE_GB_SUPPORT || CHINESE_CNS_SUPPORT */
err4:
obj5.free();
makeWidths(fontDict, NULL, NULL, 0);
}
-static int CDECL cmpWidthExcep(const void *w1, const void *w2) {
+#if defined(JAPANESE_SUPPORT) || defined(CHINESE_GB_SUPPORT) || defined(CHINESE_CNS_SUPPORT)
+static int cmpWidthExcep(const void *w1, const void *w2) {
return ((GfxFontWidthExcep *)w1)->first - ((GfxFontWidthExcep *)w2)->first;
}
-static int CDECL cmpWidthExcepV(const void *w1, const void *w2) {
+static int cmpWidthExcepV(const void *w1, const void *w2) {
return ((GfxFontWidthExcepV *)w1)->first - ((GfxFontWidthExcepV *)w2)->first;
}
+#endif /* JAPANESE_SUPPORT || CHINESE_GB_SUPPORT || CHINESE_CNS_SUPPORT */
//------------------------------------------------------------------------
// GfxFontDict
gfree(fonts);
}
-GfxFont *GfxFontDict::lookup(char *tag) {
+GfxFont *GfxFontDict::lookup(const char *tag) {
int i;
for (i = 0; i < numFonts; ++i) {
enum GfxFontCharSet16 {
font16AdobeJapan12, // Adobe-Japan1-2
- font16AdobeGB12 // Adobe-GB1-2 (Chinese)
+ font16AdobeGB12, // Adobe-GB1-2 (Chinese)
+ font16AdobeCNS13 // Adobe-CNS1-3 (Chinese)
};
//------------------------------------------------------------------------
public:
// Constructor.
- GfxFont(char *tag1, Ref id1, Dict *fontDict);
+ GfxFont(const char *tag1, Ref id1, Dict *fontDict);
// Destructor.
~GfxFont();
Ref getID() { return id; }
// Does this font match the tag?
- GBool matches(char *tag1) { return !tag->cmp(tag1); }
+ GBool matches(const char *tag1) { return !tag->cmp(tag1); }
// Get base font name.
GString *getName() { return name; }
// Get the PostScript font name for the embedded font. Returns
// NULL if there is no embedded font.
- char *getEmbeddedFontName()
- { return embFontName ? embFontName->getCString() : (char *)NULL; }
+ const char *getEmbeddedFontName()
+ { return embFontName ? embFontName->getCString() : (const char *)NULL; }
// Get the name of the external font file. Returns NULL if there
// is no external font file.
FontEncoding *getEncoding() { return encoding; }
// Return the character name associated with <code>.
- char *getCharName(int code) { return encoding->getCharName(code); }
+ const char *getCharName(int code) { return encoding->getCharName(code); }
// Return the code associated with <name>.
- int getCharCode(char *charName) { return encoding->getCharCode(charName); }
+ int getCharCode(const char *charName) { return encoding->getCharCode(charName); }
// Return the Type 3 CharProc for the character associated with <code>.
Object *getCharProc(int code, Object *proc);
double *getFontMatrix() { return fontMat; }
// Read an external or embedded font file into a buffer.
- char *readExtFontFile(int *len);
- char *readEmbFontFile(int *len);
+ const char *readExtFontFile(int *len);
+ const char *readEmbFontFile(int *len);
private:
~GfxFontDict();
// Get the specified font.
- GfxFont *lookup(char *tag);
+ GfxFont *lookup(const char *tag);
// Iterative access.
int getNumFonts() { return numFonts; }
#include "gmem.h"
#include "Error.h"
#include "Object.h"
+#include "Array.h"
#include "GfxState.h"
//------------------------------------------------------------------------
-// GfxColor
+
+static inline double clip01(double x) {
+ return (x < 0) ? 0 : ((x > 1) ? 1 : x);
+}
+
//------------------------------------------------------------------------
+// GfxColorSpace
+//------------------------------------------------------------------------
+
+GfxColorSpace::GfxColorSpace() {
+}
-void GfxColor::setGray(double gray) {
- if (gray < 0) {
- r = g = b = 0;
- } else if (gray > 1) {
- r = g = b = 1;
+GfxColorSpace::~GfxColorSpace() {
+}
+
+GfxColorSpace *GfxColorSpace::parse(Object *csObj) {
+ GfxColorSpace *cs;
+ Object obj1;
+
+ cs = NULL;
+ if (csObj->isName()) {
+ if (csObj->isName("DeviceGray") || csObj->isName("G")) {
+ cs = new GfxDeviceGrayColorSpace();
+ } else if (csObj->isName("DeviceRGB") || csObj->isName("RGB")) {
+ cs = new GfxDeviceRGBColorSpace();
+ } else if (csObj->isName("DeviceCMYK") || csObj->isName("CMYK")) {
+ cs = new GfxDeviceCMYKColorSpace();
+ } else if (csObj->isName("Pattern")) {
+ cs = new GfxPatternColorSpace(NULL);
+ } else {
+ error(-1, "Bad color space '%s'", csObj->getName());
+ }
+ } else if (csObj->isArray()) {
+ csObj->arrayGet(0, &obj1);
+ if (obj1.isName("DeviceGray") || obj1.isName("G")) {
+ cs = new GfxDeviceGrayColorSpace();
+ } else if (obj1.isName("DeviceRGB") || obj1.isName("RGB")) {
+ cs = new GfxDeviceRGBColorSpace();
+ } else if (obj1.isName("DeviceCMYK") || obj1.isName("CMYK")) {
+ cs = new GfxDeviceCMYKColorSpace();
+ } else if (obj1.isName("CalGray")) {
+ cs = GfxCalGrayColorSpace::parse(csObj->getArray());
+ } else if (obj1.isName("CalRGB")) {
+ cs = GfxCalRGBColorSpace::parse(csObj->getArray());
+ } else if (obj1.isName("Lab")) {
+ cs = GfxLabColorSpace::parse(csObj->getArray());
+ } else if (obj1.isName("ICCBased")) {
+ cs = GfxICCBasedColorSpace::parse(csObj->getArray());
+ } else if (obj1.isName("Indexed") || obj1.isName("I")) {
+ cs = GfxIndexedColorSpace::parse(csObj->getArray());
+ } else if (obj1.isName("Separation")) {
+ cs = GfxSeparationColorSpace::parse(csObj->getArray());
+ } else if (obj1.isName("DeviceN")) {
+ cs = GfxDeviceNColorSpace::parse(csObj->getArray());
+ } else if (obj1.isName("Pattern")) {
+ cs = GfxPatternColorSpace::parse(csObj->getArray());
+ } else {
+ error(-1, "Bad color space '%s'", csObj->getName());
+ }
+ obj1.free();
} else {
- r = g = b = gray;
+ error(-1, "Bad color space - expected name or array");
+ }
+ return cs;
+}
+
+void GfxColorSpace::getDefaultRanges(double *decodeLow, double *decodeRange,
+ int maxImgPixel) {
+ int i;
+
+ for (i = 0; i < getNComps(); ++i) {
+ decodeLow[i] = 0;
+ decodeRange[i] = 1;
+ }
+}
+
+//------------------------------------------------------------------------
+// GfxDeviceGrayColorSpace
+//------------------------------------------------------------------------
+
+GfxDeviceGrayColorSpace::GfxDeviceGrayColorSpace() {
+}
+
+GfxDeviceGrayColorSpace::~GfxDeviceGrayColorSpace() {
+}
+
+GfxColorSpace *GfxDeviceGrayColorSpace::copy() {
+ return new GfxDeviceGrayColorSpace();
+}
+
+void GfxDeviceGrayColorSpace::getGray(GfxColor *color, double *gray) {
+ *gray = clip01(color->c[0]);
+}
+
+void GfxDeviceGrayColorSpace::getRGB(GfxColor *color, GfxRGB *rgb) {
+ rgb->r = rgb->g = rgb->b = clip01(color->c[0]);
+}
+
+void GfxDeviceGrayColorSpace::getCMYK(GfxColor *color, GfxCMYK *cmyk) {
+ cmyk->c = cmyk->m = cmyk->y = 0;
+ cmyk->k = clip01(1 - color->c[0]);
+}
+
+//------------------------------------------------------------------------
+// GfxCalGrayColorSpace
+//------------------------------------------------------------------------
+
+GfxCalGrayColorSpace::GfxCalGrayColorSpace() {
+ whiteX = whiteY = whiteZ = 1;
+ blackX = blackY = blackZ = 0;
+ gamma = 1;
+}
+
+GfxCalGrayColorSpace::~GfxCalGrayColorSpace() {
+}
+
+GfxColorSpace *GfxCalGrayColorSpace::copy() {
+ GfxCalGrayColorSpace *cs;
+
+ cs = new GfxCalGrayColorSpace();
+ cs->whiteX = whiteX;
+ cs->whiteY = whiteY;
+ cs->whiteZ = whiteZ;
+ cs->blackX = blackX;
+ cs->blackY = blackY;
+ cs->blackZ = blackZ;
+ cs->gamma = gamma;
+ return cs;
+}
+
+GfxColorSpace *GfxCalGrayColorSpace::parse(Array *arr) {
+ GfxCalGrayColorSpace *cs;
+ Object obj1, obj2, obj3;
+
+ arr->get(1, &obj1);
+ if (!obj1.isDict()) {
+ error(-1, "Bad CalGray color space");
+ obj1.free();
+ return NULL;
}
+ cs = new GfxCalGrayColorSpace();
+ if (obj1.dictLookup("WhitePoint", &obj2)->isArray() &&
+ obj2.arrayGetLength() == 3) {
+ obj2.arrayGet(0, &obj3);
+ cs->whiteX = obj3.getNum();
+ obj3.free();
+ obj2.arrayGet(1, &obj3);
+ cs->whiteY = obj3.getNum();
+ obj3.free();
+ obj2.arrayGet(2, &obj3);
+ cs->whiteZ = obj3.getNum();
+ obj3.free();
+ }
+ obj2.free();
+ if (obj1.dictLookup("BlackPoint", &obj2)->isArray() &&
+ obj2.arrayGetLength() == 3) {
+ obj2.arrayGet(0, &obj3);
+ cs->blackX = obj3.getNum();
+ obj3.free();
+ obj2.arrayGet(1, &obj3);
+ cs->blackY = obj3.getNum();
+ obj3.free();
+ obj2.arrayGet(2, &obj3);
+ cs->blackZ = obj3.getNum();
+ obj3.free();
+ }
+ obj2.free();
+ if (obj1.dictLookup("Gamma", &obj2)->isNum()) {
+ cs->gamma = obj2.getNum();
+ }
+ obj2.free();
+ obj1.free();
+ return cs;
+}
+
+void GfxCalGrayColorSpace::getGray(GfxColor *color, double *gray) {
+ *gray = clip01(color->c[0]);
+}
+
+void GfxCalGrayColorSpace::getRGB(GfxColor *color, GfxRGB *rgb) {
+ rgb->r = rgb->g = rgb->b = clip01(color->c[0]);
+}
+
+void GfxCalGrayColorSpace::getCMYK(GfxColor *color, GfxCMYK *cmyk) {
+ cmyk->c = cmyk->m = cmyk->y = 0;
+ cmyk->k = clip01(1 - color->c[0]);
+}
+
+//------------------------------------------------------------------------
+// GfxDeviceRGBColorSpace
+//------------------------------------------------------------------------
+
+GfxDeviceRGBColorSpace::GfxDeviceRGBColorSpace() {
+}
+
+GfxDeviceRGBColorSpace::~GfxDeviceRGBColorSpace() {
+}
+
+GfxColorSpace *GfxDeviceRGBColorSpace::copy() {
+ return new GfxDeviceRGBColorSpace();
+}
+
+void GfxDeviceRGBColorSpace::getGray(GfxColor *color, double *gray) {
+ *gray = clip01(0.299 * color->c[0] +
+ 0.587 * color->c[1] +
+ 0.114 * color->c[2]);
+}
+
+void GfxDeviceRGBColorSpace::getRGB(GfxColor *color, GfxRGB *rgb) {
+ rgb->r = clip01(color->c[0]);
+ rgb->g = clip01(color->c[1]);
+ rgb->b = clip01(color->c[2]);
}
-void GfxColor::setCMYK(double c, double m, double y, double k) {
- if ((r = 1 - (c + k)) < 0) {
- r = 0;
- } else if (r > 1) {
- r = 1;
+void GfxDeviceRGBColorSpace::getCMYK(GfxColor *color, GfxCMYK *cmyk) {
+ double c, m, y, k;
+
+ c = clip01(1 - color->c[0]);
+ m = clip01(1 - color->c[1]);
+ y = clip01(1 - color->c[2]);
+ k = c;
+ if (m < k) {
+ k = m;
}
- if ((g = 1 - (m + k)) < 0) {
- g = 0;
- } else if (g > 1) {
- g = 1;
+ if (y < k) {
+ k = y;
}
- if ((b = 1 - (y + k)) < 0) {
- b = 0;
- } else if (b > 1) {
- b = 1;
+ cmyk->c = c - k;
+ cmyk->m = m - k;
+ cmyk->y = y - k;
+ cmyk->k = k;
+}
+
+//------------------------------------------------------------------------
+// GfxCalRGBColorSpace
+//------------------------------------------------------------------------
+
+GfxCalRGBColorSpace::GfxCalRGBColorSpace() {
+ whiteX = whiteY = whiteZ = 1;
+ blackX = blackY = blackZ = 0;
+ gammaR = gammaG = gammaB = 1;
+ m[0] = 1; m[1] = 0; m[2] = 0;
+ m[3] = 0; m[4] = 1; m[5] = 0;
+ m[6] = 0; m[7] = 0; m[8] = 1;
+}
+
+GfxCalRGBColorSpace::~GfxCalRGBColorSpace() {
+}
+
+GfxColorSpace *GfxCalRGBColorSpace::copy() {
+ GfxCalRGBColorSpace *cs;
+ int i;
+
+ cs = new GfxCalRGBColorSpace();
+ cs->whiteX = whiteX;
+ cs->whiteY = whiteY;
+ cs->whiteZ = whiteZ;
+ cs->blackX = blackX;
+ cs->blackY = blackY;
+ cs->blackZ = blackZ;
+ cs->gammaR = gammaR;
+ cs->gammaG = gammaG;
+ cs->gammaB = gammaB;
+ for (i = 0; i < 9; ++i) {
+ cs->m[i] = m[i];
}
+ return cs;
}
-void GfxColor::setRGB(double r1, double g1, double b1) {
- if (r1 < 0) {
- r = 0;
- } else if (r1 > 1) {
- r = 1;
- } else {
- r = r1;
+GfxColorSpace *GfxCalRGBColorSpace::parse(Array *arr) {
+ GfxCalRGBColorSpace *cs;
+ Object obj1, obj2, obj3;
+ int i;
+
+ arr->get(1, &obj1);
+ if (!obj1.isDict()) {
+ error(-1, "Bad CalRGB color space");
+ obj1.free();
+ return NULL;
}
- if (g1 < 0) {
- g = 0;
- } else if (g1 > 1) {
- g = 1;
- } else {
- g = g1;
+ cs = new GfxCalRGBColorSpace();
+ if (obj1.dictLookup("WhitePoint", &obj2)->isArray() &&
+ obj2.arrayGetLength() == 3) {
+ obj2.arrayGet(0, &obj3);
+ cs->whiteX = obj3.getNum();
+ obj3.free();
+ obj2.arrayGet(1, &obj3);
+ cs->whiteY = obj3.getNum();
+ obj3.free();
+ obj2.arrayGet(2, &obj3);
+ cs->whiteZ = obj3.getNum();
+ obj3.free();
}
- if (b1 < 0) {
- b = 0;
- } else if (b1 > 1) {
- b = 1;
- } else {
- b = b1;
+ obj2.free();
+ if (obj1.dictLookup("BlackPoint", &obj2)->isArray() &&
+ obj2.arrayGetLength() == 3) {
+ obj2.arrayGet(0, &obj3);
+ cs->blackX = obj3.getNum();
+ obj3.free();
+ obj2.arrayGet(1, &obj3);
+ cs->blackY = obj3.getNum();
+ obj3.free();
+ obj2.arrayGet(2, &obj3);
+ cs->blackZ = obj3.getNum();
+ obj3.free();
+ }
+ obj2.free();
+ if (obj1.dictLookup("Gamma", &obj2)->isArray() &&
+ obj2.arrayGetLength() == 3) {
+ obj2.arrayGet(0, &obj3);
+ cs->gammaR = obj3.getNum();
+ obj3.free();
+ obj2.arrayGet(1, &obj3);
+ cs->gammaG = obj3.getNum();
+ obj3.free();
+ obj2.arrayGet(2, &obj3);
+ cs->gammaB = obj3.getNum();
+ obj3.free();
+ }
+ obj2.free();
+ if (obj1.dictLookup("Matrix", &obj2)->isArray() &&
+ obj2.arrayGetLength() == 9) {
+ for (i = 0; i < 9; ++i) {
+ obj2.arrayGet(i, &obj3);
+ cs->m[i] = obj3.getNum();
+ obj3.free();
+ }
+ }
+ obj2.free();
+ obj1.free();
+ return cs;
+}
+
+void GfxCalRGBColorSpace::getGray(GfxColor *color, double *gray) {
+ *gray = clip01(0.299 * color->c[0] +
+ 0.587 * color->c[1] +
+ 0.114 * color->c[2]);
+}
+
+void GfxCalRGBColorSpace::getRGB(GfxColor *color, GfxRGB *rgb) {
+ rgb->r = clip01(color->c[0]);
+ rgb->g = clip01(color->c[1]);
+ rgb->b = clip01(color->c[2]);
+}
+
+void GfxCalRGBColorSpace::getCMYK(GfxColor *color, GfxCMYK *cmyk) {
+ double c, m, y, k;
+
+ c = clip01(1 - color->c[0]);
+ m = clip01(1 - color->c[1]);
+ y = clip01(1 - color->c[2]);
+ k = c;
+ if (m < k) {
+ k = m;
+ }
+ if (y < k) {
+ k = y;
+ }
+ cmyk->c = c - k;
+ cmyk->m = m - k;
+ cmyk->y = y - k;
+ cmyk->k = k;
+}
+
+//------------------------------------------------------------------------
+// GfxDeviceCMYKColorSpace
+//------------------------------------------------------------------------
+
+GfxDeviceCMYKColorSpace::GfxDeviceCMYKColorSpace() {
+}
+
+GfxDeviceCMYKColorSpace::~GfxDeviceCMYKColorSpace() {
+}
+
+GfxColorSpace *GfxDeviceCMYKColorSpace::copy() {
+ return new GfxDeviceCMYKColorSpace();
+}
+
+void GfxDeviceCMYKColorSpace::getGray(GfxColor *color, double *gray) {
+ *gray = clip01(1 - color->c[3]
+ - 0.299 * color->c[0]
+ - 0.587 * color->c[1]
+ - 0.114 * color->c[2]);
+}
+
+void GfxDeviceCMYKColorSpace::getRGB(GfxColor *color, GfxRGB *rgb) {
+ rgb->r = clip01(1 - (color->c[0] + color->c[3]));
+ rgb->g = clip01(1 - (color->c[1] + color->c[3]));
+ rgb->b = clip01(1 - (color->c[2] + color->c[3]));
+}
+
+void GfxDeviceCMYKColorSpace::getCMYK(GfxColor *color, GfxCMYK *cmyk) {
+ cmyk->c = clip01(color->c[0]);
+ cmyk->m = clip01(color->c[1]);
+ cmyk->y = clip01(color->c[2]);
+ cmyk->k = clip01(color->c[3]);
+}
+
+//------------------------------------------------------------------------
+// GfxLabColorSpace
+//------------------------------------------------------------------------
+
+// This is the inverse of MatrixLMN in Example 4.10 from the PostScript
+// Language Reference, Third Edition.
+static double xyzrgb[3][3] = {
+ { 3.240449, -1.537136, -0.498531 },
+ { -0.969265, 1.876011, 0.041556 },
+ { 0.055643, -0.204026, 1.057229 }
+};
+
+GfxLabColorSpace::GfxLabColorSpace() {
+ whiteX = whiteY = whiteZ = 1;
+ blackX = blackY = blackZ = 0;
+ aMin = bMin = -100;
+ aMax = bMax = 100;
+}
+
+GfxLabColorSpace::~GfxLabColorSpace() {
+}
+
+GfxColorSpace *GfxLabColorSpace::copy() {
+ GfxLabColorSpace *cs;
+
+ cs = new GfxLabColorSpace();
+ cs->whiteX = whiteX;
+ cs->whiteY = whiteY;
+ cs->whiteZ = whiteZ;
+ cs->blackX = blackX;
+ cs->blackY = blackY;
+ cs->blackZ = blackZ;
+ cs->aMin = aMin;
+ cs->aMax = aMax;
+ cs->bMin = bMin;
+ cs->bMax = bMax;
+ cs->kr = kr;
+ cs->kg = kg;
+ cs->kb = kb;
+ return cs;
+}
+
+GfxColorSpace *GfxLabColorSpace::parse(Array *arr) {
+ GfxLabColorSpace *cs;
+ Object obj1, obj2, obj3;
+
+ arr->get(1, &obj1);
+ if (!obj1.isDict()) {
+ error(-1, "Bad Lab color space");
+ obj1.free();
+ return NULL;
+ }
+ cs = new GfxLabColorSpace();
+ if (obj1.dictLookup("WhitePoint", &obj2)->isArray() &&
+ obj2.arrayGetLength() == 3) {
+ obj2.arrayGet(0, &obj3);
+ cs->whiteX = obj3.getNum();
+ obj3.free();
+ obj2.arrayGet(1, &obj3);
+ cs->whiteY = obj3.getNum();
+ obj3.free();
+ obj2.arrayGet(2, &obj3);
+ cs->whiteZ = obj3.getNum();
+ obj3.free();
}
+ obj2.free();
+ if (obj1.dictLookup("BlackPoint", &obj2)->isArray() &&
+ obj2.arrayGetLength() == 3) {
+ obj2.arrayGet(0, &obj3);
+ cs->blackX = obj3.getNum();
+ obj3.free();
+ obj2.arrayGet(1, &obj3);
+ cs->blackY = obj3.getNum();
+ obj3.free();
+ obj2.arrayGet(2, &obj3);
+ cs->blackZ = obj3.getNum();
+ obj3.free();
+ }
+ obj2.free();
+ if (obj1.dictLookup("Range", &obj2)->isArray() &&
+ obj2.arrayGetLength() == 4) {
+ obj2.arrayGet(0, &obj3);
+ cs->aMin = obj3.getNum();
+ obj3.free();
+ obj2.arrayGet(1, &obj3);
+ cs->aMax = obj3.getNum();
+ obj3.free();
+ obj2.arrayGet(2, &obj3);
+ cs->bMin = obj3.getNum();
+ obj3.free();
+ obj2.arrayGet(3, &obj3);
+ cs->bMax = obj3.getNum();
+ obj3.free();
+ }
+ obj2.free();
+ obj1.free();
+
+ cs->kr = 1 / (xyzrgb[0][0] * cs->whiteX +
+ xyzrgb[0][1] * cs->whiteY +
+ xyzrgb[0][2] * cs->whiteZ);
+ cs->kg = 1 / (xyzrgb[1][0] * cs->whiteX +
+ xyzrgb[1][1] * cs->whiteY +
+ xyzrgb[1][2] * cs->whiteZ);
+ cs->kb = 1 / (xyzrgb[2][0] * cs->whiteX +
+ xyzrgb[2][1] * cs->whiteY +
+ xyzrgb[2][2] * cs->whiteZ);
+
+ return cs;
}
-// Handle colors in the L*a*b* color space.
-void GfxColor::setLab(double L, double a, double bb, LabParams *params) {
+void GfxLabColorSpace::getGray(GfxColor *color, double *gray) {
+ GfxRGB rgb;
+
+ getRGB(color, &rgb);
+ *gray = clip01(0.299 * rgb.r +
+ 0.587 * rgb.g +
+ 0.114 * rgb.b);
+}
+
+void GfxLabColorSpace::getRGB(GfxColor *color, GfxRGB *rgb) {
double X, Y, Z;
double t1, t2;
+ double r, g, b;
// convert L*a*b* to CIE 1931 XYZ color space
- // (This ignores the white point parameter, because I don't
- // understand exactly how it should work.)
- t1 = (L + 16) / 116;
- t2 = t1 + a / 500;
+ t1 = (color->c[0] + 16) / 116;
+ t2 = t1 + color->c[1] / 500;
if (t2 >= (6.0 / 29.0)) {
X = t2 * t2 * t2;
} else {
X = (108.0 / 841.0) * (t2 - (4.0 / 29.0));
}
-#if 0 //~
- X *= params->whiteX;
-#endif
+ X *= whiteX;
if (t1 >= (6.0 / 29.0)) {
Y = t1 * t1 * t1;
} else {
Y = (108.0 / 841.0) * (t1 - (4.0 / 29.0));
}
-#if 0 //~
- Y *= params->whiteY;
-#endif
- t2 = t1 - bb / 200;
+ Y *= whiteY;
+ t2 = t1 - color->c[2] / 200;
if (t2 >= (6.0 / 29.0)) {
Z = t2 * t2 * t2;
} else {
Z = (108.0 / 841.0) * (t2 - (4.0 / 29.0));
}
-#if 0 //~
- Z *= params->whiteZ;
-#endif
+ Z *= whiteZ;
+
+ // convert XYZ to RGB, including gamut mapping and gamma correction
+ r = xyzrgb[0][0] * X + xyzrgb[0][1] * Y + xyzrgb[0][2] * Z;
+ g = xyzrgb[1][0] * X + xyzrgb[1][1] * Y + xyzrgb[1][2] * Z;
+ b = xyzrgb[2][0] * X + xyzrgb[2][1] * Y + xyzrgb[2][2] * Z;
+ rgb->r = pow(clip01(r * kr), 0.5);
+ rgb->g = pow(clip01(g * kg), 0.5);
+ rgb->b = pow(clip01(b * kb), 0.5);
+}
- // convert XYZ to RGB
-#if 0 //~
- X *= 0.9505;
- Z *= 1.0890;
-#endif
- r = 3.240479 * X - 1.537150 * Y - 0.498535 * Z;
- g = -0.969256 * X + 1.875992 * Y + 0.041556 * Z;
- b = 0.055648 * X - 0.204043 * Y + 1.057311 * Z;
+void GfxLabColorSpace::getCMYK(GfxColor *color, GfxCMYK *cmyk) {
+ GfxRGB rgb;
+ double c, m, y, k;
+
+ getRGB(color, &rgb);
+ c = clip01(1 - rgb.r);
+ m = clip01(1 - rgb.g);
+ y = clip01(1 - rgb.b);
+ k = c;
+ if (m < k) {
+ k = m;
+ }
+ if (y < k) {
+ k = y;
+ }
+ cmyk->c = c - k;
+ cmyk->m = m - k;
+ cmyk->y = y - k;
+ cmyk->k = k;
+}
+
+void GfxLabColorSpace::getDefaultRanges(double *decodeLow, double *decodeRange,
+ int maxImgPixel) {
+ decodeLow[0] = 0;
+ decodeRange[0] = 100;
+ decodeLow[1] = aMin;
+ decodeRange[1] = aMax - aMin;
+ decodeLow[2] = bMin;
+ decodeRange[2] = bMax - bMin;
+}
+
+//------------------------------------------------------------------------
+// GfxICCBasedColorSpace
+//------------------------------------------------------------------------
+
+GfxICCBasedColorSpace::GfxICCBasedColorSpace(int nComps, GfxColorSpace *alt,
+ Ref *iccProfileStream) {
+ this->nComps = nComps;
+ this->alt = alt;
+ this->iccProfileStream = *iccProfileStream;
+ rangeMin[0] = rangeMin[1] = rangeMin[2] = rangeMin[3] = 0;
+ rangeMax[0] = rangeMax[1] = rangeMax[2] = rangeMax[3] = 1;
+}
+
+GfxICCBasedColorSpace::~GfxICCBasedColorSpace() {
+ delete alt;
+}
+
+GfxColorSpace *GfxICCBasedColorSpace::copy() {
+ GfxICCBasedColorSpace *cs;
+ int i;
+
+ cs = new GfxICCBasedColorSpace(nComps, alt->copy(), &iccProfileStream);
+ for (i = 0; i < 4; ++i) {
+ cs->rangeMin[i] = rangeMin[i];
+ cs->rangeMax[i] = rangeMax[i];
+ }
+ return cs;
+}
+
+GfxColorSpace *GfxICCBasedColorSpace::parse(Array *arr) {
+ GfxICCBasedColorSpace *cs;
+ Ref iccProfileStream;
+ int nComps;
+ GfxColorSpace *alt;
+ Dict *dict;
+ Object obj1, obj2, obj3;
+ int i;
- // clip RGB
- if (r < 0) {
- r = 0;
- } else if (r > 1) {
- r = 1;
+ arr->getNF(1, &obj1);
+ if (obj1.isRef()) {
+ iccProfileStream = obj1.getRef();
+ } else {
+ iccProfileStream.num = 0;
+ iccProfileStream.gen = 0;
+ }
+ obj1.free();
+ arr->get(1, &obj1);
+ if (!obj1.isStream()) {
+ error(-1, "Bad ICCBased color space (stream)");
+ obj1.free();
+ return NULL;
+ }
+ dict = obj1.streamGetDict();
+ if (!dict->lookup("N", &obj2)->isInt()) {
+ error(-1, "Bad ICCBased color space (N)");
+ obj2.free();
+ obj1.free();
+ return NULL;
+ }
+ nComps = obj2.getInt();
+ obj2.free();
+ if (dict->lookup("Alternate", &obj2)->isNull() ||
+ !(alt = GfxColorSpace::parse(&obj2))) {
+ switch (nComps) {
+ case 1:
+ alt = new GfxDeviceGrayColorSpace();
+ break;
+ case 3:
+ alt = new GfxDeviceRGBColorSpace();
+ break;
+ case 4:
+ alt = new GfxDeviceCMYKColorSpace();
+ break;
+ default:
+ error(-1, "Bad ICCBased color space - invalid N");
+ obj2.free();
+ obj1.free();
+ return NULL;
+ }
}
- if (g < 0) {
- g = 0;
- } else if (g > 1) {
- g = 1;
+ obj2.free();
+ cs = new GfxICCBasedColorSpace(nComps, alt, &iccProfileStream);
+ if (dict->lookup("Range", &obj2)->isArray() &&
+ obj2.arrayGetLength() == 2 * nComps) {
+ for (i = 0; i < nComps; ++i) {
+ obj2.arrayGet(2*i, &obj3);
+ cs->rangeMin[i] = obj3.getNum();
+ obj3.free();
+ obj2.arrayGet(2*i+1, &obj3);
+ cs->rangeMax[i] = obj3.getNum();
+ obj3.free();
+ }
}
- if (b < 0) {
- b = 0;
- } else if (b > 1) {
- b = 1;
+ obj2.free();
+ obj1.free();
+ return cs;
+}
+
+void GfxICCBasedColorSpace::getGray(GfxColor *color, double *gray) {
+ alt->getGray(color, gray);
+}
+
+void GfxICCBasedColorSpace::getRGB(GfxColor *color, GfxRGB *rgb) {
+ alt->getRGB(color, rgb);
+}
+
+void GfxICCBasedColorSpace::getCMYK(GfxColor *color, GfxCMYK *cmyk) {
+ alt->getCMYK(color, cmyk);
+}
+
+void GfxICCBasedColorSpace::getDefaultRanges(double *decodeLow,
+ double *decodeRange,
+ int maxImgPixel) {
+ int i;
+
+ for (i = 0; i < nComps; ++i) {
+ decodeLow[i] = rangeMin[i];
+ decodeRange[i] = rangeMax[i] - rangeMin[i];
}
}
//------------------------------------------------------------------------
-// GfxColorSpace
+// GfxIndexedColorSpace
//------------------------------------------------------------------------
-GfxColorSpace::GfxColorSpace(Object *colorSpace) {
- Object csObj;
- Object obj, obj2, obj3;
- Dict *dict;
- char *s;
+GfxIndexedColorSpace::GfxIndexedColorSpace(GfxColorSpace *base,
+ int indexHigh) {
+ this->base = base;
+ this->indexHigh = indexHigh;
+ this->lookup = (Guchar *)gmalloc((indexHigh + 1) * base->getNComps() *
+ sizeof(Guchar));
+}
+
+GfxIndexedColorSpace::~GfxIndexedColorSpace() {
+ delete base;
+ gfree(lookup);
+}
+
+GfxColorSpace *GfxIndexedColorSpace::copy() {
+ GfxIndexedColorSpace *cs;
+
+ cs = new GfxIndexedColorSpace(base->copy(), indexHigh);
+ memcpy(cs->lookup, lookup,
+ (indexHigh + 1) * base->getNComps() * sizeof(Guchar));
+ return cs;
+}
+
+GfxColorSpace *GfxIndexedColorSpace::parse(Array *arr) {
+ GfxIndexedColorSpace *cs;
+ GfxColorSpace *base;
+ int indexHigh;
+ Object obj1;
int x;
- int i, j;
+ char *s;
+ int n, i, j;
- ok = gTrue;
- lookup = NULL;
-
- // check for Separation, DeviceN, ICCBased, and Pattern colorspaces
- colorSpace->copy(&csObj);
- sepFunc = NULL;
- if (colorSpace->isArray()) {
- colorSpace->arrayGet(0, &obj);
- if (obj.isName("Separation") || obj.isName("DeviceN")) {
- csObj.free();
- colorSpace->arrayGet(2, &csObj);
- sepFunc = new Function(colorSpace->arrayGet(3, &obj2));
- obj2.free();
- if (!sepFunc->isOk()) {
- delete sepFunc;
- sepFunc = NULL;
- }
- } else if (obj.isName("ICCBased")) {
- colorSpace->arrayGet(1, &obj2);
- if (obj2.isStream()) {
- if ((dict = obj2.streamGetDict())) {
- dict->lookup("Alternate", &obj3);
- if (!obj3.isNull()) {
- csObj.free();
- csObj = obj3;
- } else {
- obj3.free();
- dict->lookup("N", &obj3);
- if (!obj3.isNull()) {
- csObj.free();
- if (obj3.getInt() == 4) {
- csObj.initName("DeviceCMYK");
- } else if (obj3.getInt() == 3) {
- csObj.initName("DeviceRGB");
- } else {
- csObj.initName("DeviceGray");
- }
- }
- obj3.free();
- }
+ if (arr->getLength() != 4) {
+ error(-1, "Bad Indexed color space");
+ goto err1;
+ }
+ arr->get(1, &obj1);
+ if (!(base = GfxColorSpace::parse(&obj1))) {
+ error(-1, "Bad Indexed color space (base color space)");
+ goto err2;
+ }
+ obj1.free();
+ if (!arr->get(2, &obj1)->isInt()) {
+ error(-1, "Bad Indexed color space (hival)");
+ goto err2;
+ }
+ indexHigh = obj1.getInt();
+ obj1.free();
+ cs = new GfxIndexedColorSpace(base, indexHigh);
+ arr->get(3, &obj1);
+ n = base->getNComps();
+ if (obj1.isStream()) {
+ obj1.streamReset();
+ for (i = 0; i <= indexHigh; ++i) {
+ for (j = 0; j < n; ++j) {
+ if ((x = obj1.streamGetChar()) == EOF) {
+ error(-1, "Bad Indexed color space (lookup table stream too short)");
+ goto err3;
}
+ cs->lookup[i*n + j] = (Guchar)x;
}
- obj2.free();
- } else if (obj.isName("Pattern")) {
- csObj.free();
- colorSpace->arrayGet(1, &csObj);
}
- obj.free();
- }
-
- // get mode
- indexed = gFalse;
- if (csObj.isName()) {
- setMode(&csObj);
- } else if (csObj.isArray()) {
- csObj.arrayGet(0, &obj);
- if (obj.isName("Indexed") || obj.isName("I")) {
- indexed = gTrue;
- setMode(csObj.arrayGet(1, &obj2));
- obj2.free();
- } else {
- setMode(&csObj);
+ obj1.streamClose();
+ } else if (obj1.isString()) {
+ if (obj1.getString()->getLength() < (indexHigh + 1) * n) {
+ error(-1, "Bad Indexed color space (lookup table string too short)");
+ goto err3;
+ }
+ s = obj1.getString()->getCString();
+ for (i = 0; i <= indexHigh; ++i) {
+ for (j = 0; j < n; ++j) {
+ cs->lookup[i*n + j] = (Guchar)*s++;
+ }
}
- obj.free();
} else {
- goto err1;
+ error(-1, "Bad Indexed color space (lookup table)");
+ goto err3;
+ }
+ obj1.free();
+ return cs;
+
+ err3:
+ delete cs;
+ err2:
+ obj1.free();
+ err1:
+ return NULL;
+}
+
+void GfxIndexedColorSpace::getGray(GfxColor *color, double *gray) {
+ Guchar *p;
+ GfxColor color2;
+ int n, i;
+
+ n = base->getNComps();
+ p = &lookup[(int)(color->c[0] + 0.5) * n];
+ for (i = 0; i < n; ++i) {
+ color2.c[i] = p[i] / 255.0;
+ }
+ base->getGray(&color2, gray);
+}
+
+void GfxIndexedColorSpace::getRGB(GfxColor *color, GfxRGB *rgb) {
+ Guchar *p;
+ GfxColor color2;
+ int n, i;
+
+ n = base->getNComps();
+ p = &lookup[(int)(color->c[0] + 0.5) * n];
+ for (i = 0; i < n; ++i) {
+ color2.c[i] = p[i] / 255.0;
+ }
+ base->getRGB(&color2, rgb);
+}
+
+void GfxIndexedColorSpace::getCMYK(GfxColor *color, GfxCMYK *cmyk) {
+ Guchar *p;
+ GfxColor color2;
+ int n, i;
+
+ n = base->getNComps();
+ p = &lookup[(int)(color->c[0] + 0.5) * n];
+ for (i = 0; i < n; ++i) {
+ color2.c[i] = p[i] / 255.0;
}
- if (!ok) {
+ base->getCMYK(&color2, cmyk);
+}
+
+void GfxIndexedColorSpace::getDefaultRanges(double *decodeLow,
+ double *decodeRange,
+ int maxImgPixel) {
+ decodeLow[0] = 0;
+ decodeRange[0] = maxImgPixel;
+}
+
+//------------------------------------------------------------------------
+// GfxSeparationColorSpace
+//------------------------------------------------------------------------
+
+GfxSeparationColorSpace::GfxSeparationColorSpace(GString *name,
+ GfxColorSpace *alt,
+ Function *func) {
+ this->name = name;
+ this->alt = alt;
+ this->func = func;
+}
+
+GfxSeparationColorSpace::~GfxSeparationColorSpace() {
+ delete name;
+ delete alt;
+ delete func;
+}
+
+GfxColorSpace *GfxSeparationColorSpace::copy() {
+ return new GfxSeparationColorSpace(name->copy(), alt->copy(), func->copy());
+}
+
+//~ handle the 'All' and 'None' colorants
+GfxColorSpace *GfxSeparationColorSpace::parse(Array *arr) {
+ GfxSeparationColorSpace *cs;
+ GString *name;
+ GfxColorSpace *alt;
+ Function *func;
+ Object obj1;
+
+ if (arr->getLength() != 4) {
+ error(-1, "Bad Separation color space");
goto err1;
}
+ if (!arr->get(1, &obj1)->isName()) {
+ error(-1, "Bad Separation color space (name)");
+ goto err2;
+ }
+ name = new GString(obj1.getName());
+ obj1.free();
+ arr->get(2, &obj1);
+ if (!(alt = GfxColorSpace::parse(&obj1))) {
+ error(-1, "Bad Separation color space (alternate color space)");
+ goto err3;
+ }
+ obj1.free();
+ func = Function::parse(arr->get(3, &obj1));
+ obj1.free();
+ if (!func->isOk()) {
+ goto err4;
+ }
+ cs = new GfxSeparationColorSpace(name, alt, func);
+ return cs;
- // get lookup table for indexed colorspace
- if (indexed) {
- csObj.arrayGet(2, &obj);
- if (!obj.isInt())
- goto err2;
- indexHigh = obj.getInt();
- obj.free();
- lookup = (Guchar (*)[4])gmalloc((indexHigh + 1) * 4 * sizeof(Guchar));
- csObj.arrayGet(3, &obj);
- if (obj.isStream()) {
- obj.streamReset();
- for (i = 0; i <= indexHigh; ++i) {
- for (j = 0; j < numComps; ++j) {
- if ((x = obj.streamGetChar()) == EOF)
- goto err2;
- lookup[i][j] = (Guchar)x;
- }
- }
- } else if (obj.isString()) {
- s = obj.getString()->getCString();
- for (i = 0; i <= indexHigh; ++i)
- for (j = 0; j < numComps; ++j)
- lookup[i][j] = (Guchar)*s++;
- } else {
+ err4:
+ delete func;
+ delete alt;
+ err3:
+ delete name;
+ err2:
+ obj1.free();
+ err1:
+ return NULL;
+}
+
+void GfxSeparationColorSpace::getGray(GfxColor *color, double *gray) {
+ GfxColor color2;
+
+ func->transform(color->c, color2.c);
+ alt->getGray(&color2, gray);
+}
+
+void GfxSeparationColorSpace::getRGB(GfxColor *color, GfxRGB *rgb) {
+ GfxColor color2;
+
+ func->transform(color->c, color2.c);
+ alt->getRGB(&color2, rgb);
+}
+
+void GfxSeparationColorSpace::getCMYK(GfxColor *color, GfxCMYK *cmyk) {
+ GfxColor color2;
+
+ func->transform(color->c, color2.c);
+ alt->getCMYK(&color2, cmyk);
+}
+
+//------------------------------------------------------------------------
+// GfxDeviceNColorSpace
+//------------------------------------------------------------------------
+
+GfxDeviceNColorSpace::GfxDeviceNColorSpace(int nComps,
+ GfxColorSpace *alt,
+ Function *func) {
+ this->nComps = nComps;
+ this->alt = alt;
+ this->func = func;
+}
+
+GfxDeviceNColorSpace::~GfxDeviceNColorSpace() {
+ int i;
+
+ for (i = 0; i < nComps; ++i) {
+ delete names[i];
+ }
+ delete alt;
+ delete func;
+}
+
+GfxColorSpace *GfxDeviceNColorSpace::copy() {
+ GfxDeviceNColorSpace *cs;
+ int i;
+
+ cs = new GfxDeviceNColorSpace(nComps, alt->copy(), func->copy());
+ for (i = 0; i < nComps; ++i) {
+ cs->names[i] = names[i]->copy();
+ }
+ return cs;
+}
+
+//~ handle the 'None' colorant
+GfxColorSpace *GfxDeviceNColorSpace::parse(Array *arr) {
+ GfxDeviceNColorSpace *cs;
+ int nComps;
+ GString *names[gfxColorMaxComps];
+ GfxColorSpace *alt;
+ Function *func;
+ Object obj1, obj2;
+ int i;
+
+ if (arr->getLength() != 4 && arr->getLength() != 5) {
+ error(-1, "Bad DeviceN color space");
+ goto err1;
+ }
+ if (!arr->get(1, &obj1)->isArray()) {
+ error(-1, "Bad DeviceN color space (names)");
+ goto err2;
+ }
+ nComps = obj1.arrayGetLength();
+ for (i = 0; i < nComps; ++i) {
+ if (!obj1.arrayGet(i, &obj2)->isName()) {
+ error(-1, "Bad DeviceN color space (names)");
+ obj2.free();
goto err2;
}
- obj.free();
+ names[i] = new GString(obj2.getName());
+ obj2.free();
}
+ obj1.free();
+ arr->get(2, &obj1);
+ if (!(alt = GfxColorSpace::parse(&obj1))) {
+ error(-1, "Bad DeviceN color space (alternate color space)");
+ goto err3;
+ }
+ obj1.free();
+ func = Function::parse(arr->get(3, &obj1));
+ obj1.free();
+ if (!func->isOk()) {
+ goto err4;
+ }
+ cs = new GfxDeviceNColorSpace(nComps, alt, func);
+ for (i = 0; i < nComps; ++i) {
+ cs->names[i] = names[i];
+ }
+ return cs;
- csObj.free();
- return;
-
+ err4:
+ delete func;
+ delete alt;
+ err3:
+ for (i = 0; i < nComps; ++i) {
+ delete names[i];
+ }
err2:
- obj.free();
+ obj1.free();
err1:
- csObj.free();
- ok = gFalse;
+ return NULL;
+}
+
+void GfxDeviceNColorSpace::getGray(GfxColor *color, double *gray) {
+ GfxColor color2;
+
+ func->transform(color->c, color2.c);
+ alt->getGray(&color2, gray);
+}
+
+void GfxDeviceNColorSpace::getRGB(GfxColor *color, GfxRGB *rgb) {
+ GfxColor color2;
+
+ func->transform(color->c, color2.c);
+ alt->getRGB(&color2, rgb);
+}
+
+void GfxDeviceNColorSpace::getCMYK(GfxColor *color, GfxCMYK *cmyk) {
+ GfxColor color2;
+
+ func->transform(color->c, color2.c);
+ alt->getCMYK(&color2, cmyk);
}
-GfxColorSpace::GfxColorSpace(GfxColorMode mode1) {
- sepFunc = NULL;
- mode = mode1;
- indexed = gFalse;
- switch (mode) {
- case colorGray: numComps = 1; break;
- case colorCMYK: numComps = 4; break;
- case colorRGB: numComps = 3; break;
- case colorLab: numComps = 3; break;
+//------------------------------------------------------------------------
+// GfxPatternColorSpace
+//------------------------------------------------------------------------
+
+GfxPatternColorSpace::GfxPatternColorSpace(GfxColorSpace *under) {
+ this->under = under;
+}
+
+GfxPatternColorSpace::~GfxPatternColorSpace() {
+ if (under) {
+ delete under;
}
- lookup = NULL;
- ok = gTrue;
}
-GfxColorSpace::~GfxColorSpace() {
- if (sepFunc)
- delete sepFunc;
- gfree(lookup);
+GfxColorSpace *GfxPatternColorSpace::copy() {
+ return new GfxPatternColorSpace(under ? under->copy() :
+ (GfxColorSpace *)NULL);
}
-GfxColorSpace::GfxColorSpace(GfxColorSpace *colorSpace) {
- int size;
-
- if (colorSpace->sepFunc)
- sepFunc = colorSpace->sepFunc->copy();
- else
- sepFunc = NULL;
- mode = colorSpace->mode;
- indexed = colorSpace->indexed;
- numComps = colorSpace->numComps;
- indexHigh = colorSpace->indexHigh;
- if (indexed) {
- size = (indexHigh + 1) * 4 * sizeof(Guchar);
- lookup = (Guchar (*)[4])gmalloc(size);
- memcpy(lookup, colorSpace->lookup, size);
- } else {
- lookup = NULL;
+GfxColorSpace *GfxPatternColorSpace::parse(Array *arr) {
+ GfxPatternColorSpace *cs;
+ GfxColorSpace *under;
+ Object obj1;
+
+ if (arr->getLength() != 1 && arr->getLength() != 2) {
+ error(-1, "Bad Pattern color space");
+ return NULL;
}
- ok = gTrue;
+ under = NULL;
+ if (arr->getLength() == 2) {
+ arr->get(1, &obj1);
+ if (!(under = GfxColorSpace::parse(&obj1))) {
+ error(-1, "Bad Pattern color space (underlying color space)");
+ obj1.free();
+ return NULL;
+ }
+ obj1.free();
+ }
+ cs = new GfxPatternColorSpace(under);
+ return cs;
}
-void GfxColorSpace::setMode(Object *colorSpace) {
- Object obj1, obj2, obj3, obj4;
-
- if (colorSpace->isName("DeviceGray") || colorSpace->isName("G")) {
- mode = colorGray;
- numComps = 1;
- } else if (colorSpace->isName("DeviceRGB") || colorSpace->isName("RGB")) {
- mode = colorRGB;
- numComps = 3;
- } else if (colorSpace->isName("DeviceCMYK") || colorSpace->isName("CMYK")) {
- mode = colorCMYK;
- numComps = 4;
- } else if (colorSpace->isArray()) {
- colorSpace->arrayGet(0, &obj1);
- if (obj1.isName("CalGray")) {
- mode = colorGray;
- numComps = 1;
- } else if (obj1.isName("CalRGB")) {
- mode = colorRGB;
- numComps = 3;
- } else if (obj1.isName("CalCMYK")) {
- mode = colorCMYK;
- numComps = 4;
- } else if (obj1.isName("Lab")) {
- mode = colorLab;
- numComps = 3;
- labParams.whiteX = 0.9505;
- labParams.whiteY = 1;
- labParams.whiteZ = 1.0890;
- labParams.aMin = -100;
- labParams.aMax = 100;
- labParams.bMin = -100;
- labParams.bMax = 100;
- colorSpace->arrayGet(1, &obj2);
- if (obj2.isDict()) {
- obj2.dictLookup("WhitePoint", &obj3);
- if (obj3.isArray() && obj3.arrayGetLength() == 3) {
- obj3.arrayGet(0, &obj4);
- if (obj4.isNum()) {
- labParams.whiteX = obj4.getNum();
- }
- obj4.free();
- obj3.arrayGet(1, &obj4);
- if (obj4.isNum()) {
- labParams.whiteY = obj4.getNum();
- }
- obj4.free();
- obj3.arrayGet(2, &obj4);
- if (obj4.isNum()) {
- labParams.whiteZ = obj4.getNum();
- }
- obj4.free();
- }
- obj3.free();
- obj2.dictLookup("Range", &obj3);
- if (obj3.isArray() && obj3.arrayGetLength() == 4) {
- obj3.arrayGet(0, &obj4);
- if (obj4.isNum()) {
- labParams.aMin = obj4.getNum();
- }
- obj4.free();
- obj3.arrayGet(1, &obj4);
- if (obj4.isNum()) {
- labParams.aMax = obj4.getNum();
- }
- obj4.free();
- obj3.arrayGet(2, &obj4);
- if (obj4.isNum()) {
- labParams.bMin = obj4.getNum();
- }
- obj4.free();
- obj3.arrayGet(3, &obj4);
- if (obj4.isNum()) {
- labParams.bMax = obj4.getNum();
- }
- obj4.free();
- }
- obj3.free();
- }
- obj2.free();
- } else {
- ok = gFalse;
+void GfxPatternColorSpace::getGray(GfxColor *color, double *gray) {
+ *gray = 0;
+}
+
+void GfxPatternColorSpace::getRGB(GfxColor *color, GfxRGB *rgb) {
+ rgb->r = rgb->g = rgb->b = 0;
+}
+
+void GfxPatternColorSpace::getCMYK(GfxColor *color, GfxCMYK *cmyk) {
+ cmyk->c = cmyk->m = cmyk->y = 0;
+ cmyk->k = 1;
+}
+
+//------------------------------------------------------------------------
+// Pattern
+//------------------------------------------------------------------------
+
+GfxPattern::GfxPattern(int type) {
+ this->type = type;
+}
+
+GfxPattern::~GfxPattern() {
+}
+
+GfxPattern *GfxPattern::parse(Object *obj) {
+ GfxPattern *pattern;
+ Dict *dict;
+ Object obj1;
+
+ pattern = NULL;
+ if (obj->isStream()) {
+ dict = obj->streamGetDict();
+ dict->lookup("PatternType", &obj1);
+ if (obj1.isInt() && obj1.getInt() == 1) {
+ pattern = new GfxTilingPattern(dict, obj);
}
obj1.free();
- } else {
- ok = gFalse;
}
+ return pattern;
}
-void GfxColorSpace::getDefaultRanges(double *decodeLow, double *decodeRange,
- int maxPixel) {
+//------------------------------------------------------------------------
+// GfxTilingPattern
+//------------------------------------------------------------------------
+
+GfxTilingPattern::GfxTilingPattern(Dict *streamDict, Object *stream):
+ GfxPattern(1)
+{
+ Object obj1, obj2;
int i;
- if (indexed) {
- decodeLow[0] = 0;
- decodeRange[0] = maxPixel;
- } else if (mode == colorLab) {
- decodeLow[0] = 0;
- decodeRange[0] = 100;
- decodeLow[1] = labParams.aMin;
- decodeRange[1] = labParams.aMax - labParams.aMin;
- decodeLow[2] = labParams.bMin;
- decodeRange[2] = labParams.bMax - labParams.bMin;
+ if (streamDict->lookup("PaintType", &obj1)->isInt()) {
+ paintType = obj1.getInt();
+ } else {
+ paintType = 1;
+ error(-1, "Invalid or missing PaintType in pattern");
+ }
+ obj1.free();
+ if (streamDict->lookup("TilingType", &obj1)->isInt()) {
+ tilingType = obj1.getInt();
+ } else {
+ tilingType = 1;
+ error(-1, "Invalid or missing TilingType in pattern");
+ }
+ obj1.free();
+ bbox[0] = bbox[1] = 0;
+ bbox[2] = bbox[3] = 1;
+ if (streamDict->lookup("BBox", &obj1)->isArray() &&
+ obj1.arrayGetLength() == 4) {
+ for (i = 0; i < 4; ++i) {
+ if (obj1.arrayGet(i, &obj2)->isNum()) {
+ bbox[i] = obj2.getNum();
+ }
+ obj2.free();
+ }
+ } else {
+ error(-1, "Invalid or missing BBox in pattern");
+ }
+ obj1.free();
+ if (streamDict->lookup("XStep", &obj1)->isNum()) {
+ xStep = obj1.getNum();
} else {
- for (i = 0; i < numComps; ++i) {
- decodeLow[i] = 0;
- decodeRange[i] = 1;
+ xStep = 1;
+ error(-1, "Invalid or missing XStep in pattern");
+ }
+ obj1.free();
+ if (streamDict->lookup("YStep", &obj1)->isNum()) {
+ yStep = obj1.getNum();
+ } else {
+ yStep = 1;
+ error(-1, "Invalid or missing YStep in pattern");
+ }
+ obj1.free();
+ if (!streamDict->lookup("Resources", &resDict)->isDict()) {
+ resDict.free();
+ resDict.initNull();
+ error(-1, "Invalid or missing Resources in pattern");
+ }
+ matrix[0] = 1; matrix[1] = 0;
+ matrix[2] = 0; matrix[3] = 1;
+ matrix[4] = 0; matrix[5] = 0;
+ if (streamDict->lookup("Matrix", &obj1)->isArray() &&
+ obj1.arrayGetLength() == 6) {
+ for (i = 0; i < 6; ++i) {
+ if (obj1.arrayGet(i, &obj2)->isNum()) {
+ matrix[i] = obj2.getNum();
+ }
+ obj2.free();
}
}
+ obj1.free();
+ stream->copy(&contentStream);
+}
+
+GfxTilingPattern::~GfxTilingPattern() {
+ resDict.free();
+ contentStream.free();
}
-void GfxColorSpace::getColor(double x[4], GfxColor *color) {
- double y[4];
- Guchar *p;
+GfxPattern *GfxTilingPattern::copy() {
+ return new GfxTilingPattern(this);
+}
- if (sepFunc) {
- sepFunc->transform(x, y);
- } else {
- y[0] = x[0];
- y[1] = x[1];
- y[2] = x[2];
- y[3] = x[3];
- }
- if (indexed) {
- p = lookup[(int)(y[0] + 0.5)];
- switch (mode) {
- case colorGray:
- color->setGray(p[0] / 255.0);
- break;
- case colorCMYK:
- color->setCMYK(p[0] / 255.0, p[1] / 255.0, p[2] / 255.0, p[3] / 255.0);
- break;
- case colorRGB:
- color->setRGB(p[0] / 255.0, p[1] / 255.0, p[2] / 255.0);
- break;
- case colorLab:
- color->setLab(p[0] / 255.0, p[1] / 255.0, p[2] / 255.0, &labParams);
- break;
- }
- } else {
- switch (mode) {
- case colorGray:
- color->setGray(y[0]);
- break;
- case colorCMYK:
- color->setCMYK(y[0], y[1], y[2], y[3]);
- break;
- case colorRGB:
- color->setRGB(y[0], y[1], y[2]);
- break;
- case colorLab:
- color->setLab(y[0], y[1], y[2], &labParams);
- break;
- }
- }
+GfxTilingPattern::GfxTilingPattern(GfxTilingPattern *pat):
+ GfxPattern(1)
+{
+ memcpy(this, pat, sizeof(GfxTilingPattern));
+ pat->resDict.copy(&resDict);
+ pat->contentStream.copy(&contentStream);
}
//------------------------------------------------------------------------
// Function
//------------------------------------------------------------------------
-Function::Function(Object *funcObj) {
- Stream *str;
- Dict *dict;
- int nSamples, sampleBits;
- double sampleMul;
- Object obj1, obj2;
- Guint buf, bitMask;
- int bits;
- int s;
- int i;
+Function::Function() {
+}
- ok = gFalse;
- samples = NULL;
+Function::~Function() {
+}
- if (!funcObj->isStream()) {
- error(-1, "Expected function dictionary");
- goto err3;
+Function *Function::parse(Object *funcObj) {
+ Function *func;
+ Dict *dict;
+ int funcType;
+ Object obj1;
+
+ if (funcObj->isStream()) {
+ dict = funcObj->streamGetDict();
+ } else if (funcObj->isDict()) {
+ dict = funcObj->getDict();
+ } else {
+ error(-1, "Expected function dictionary or stream");
+ return NULL;
}
- str = funcObj->getStream();
- dict = str->getDict();
- //----- FunctionType
- if (!dict->lookup("FunctionType", &obj1)->isInt() ||
- obj1.getInt() != 0) {
- error(-1, "Unknown function type");
- goto err2;
+ if (!dict->lookup("FunctionType", &obj1)->isInt()) {
+ error(-1, "Function type is missing or wrong type");
+ obj1.free();
+ return NULL;
}
+ funcType = obj1.getInt();
obj1.free();
+ if (funcType == 0) {
+ func = new SampledFunction(funcObj, dict);
+ } else if (funcType == 2) {
+ func = new ExponentialFunction(funcObj, dict);
+ } else {
+ error(-1, "Unimplemented function type");
+ return NULL;
+ }
+ if (!func->isOk()) {
+ delete func;
+ return NULL;
+ }
+
+ return func;
+}
+
+GBool Function::init(Dict *dict) {
+ Object obj1, obj2;
+ int i;
+
//----- Domain
if (!dict->lookup("Domain", &obj1)->isArray()) {
error(-1, "Function is missing domain");
goto err2;
}
m = obj1.arrayGetLength() / 2;
- if (m > 1) {
- error(-1, "Functions with more than 1 input are unsupported");
+ if (m > funcMaxInputs) {
+ error(-1, "Functions with more than %d inputs are unsupported",
+ funcMaxInputs);
goto err2;
}
for (i = 0; i < m; ++i) {
obj1.free();
//----- Range
- if (!dict->lookup("Range", &obj1)->isArray()) {
- error(-1, "Function is missing range");
- goto err2;
- }
- n = obj1.arrayGetLength() / 2;
- if (n > 4) {
- error(-1, "Functions with more than 4 outputs are unsupported");
- goto err2;
- }
- for (i = 0; i < n; ++i) {
- obj1.arrayGet(2*i, &obj2);
- if (!obj2.isNum()) {
- error(-1, "Illegal value in function range array");
- goto err1;
+ hasRange = gFalse;
+ n = 0;
+ if (dict->lookup("Range", &obj1)->isArray()) {
+ hasRange = gTrue;
+ n = obj1.arrayGetLength() / 2;
+ if (n > funcMaxOutputs) {
+ error(-1, "Functions with more than %d outputs are unsupported",
+ funcMaxOutputs);
+ goto err2;
}
- range[i][0] = obj2.getNum();
- obj2.free();
- obj1.arrayGet(2*i+1, &obj2);
- if (!obj2.isNum()) {
- error(-1, "Illegal value in function range array");
- goto err1;
+ for (i = 0; i < n; ++i) {
+ obj1.arrayGet(2*i, &obj2);
+ if (!obj2.isNum()) {
+ error(-1, "Illegal value in function range array");
+ goto err1;
+ }
+ range[i][0] = obj2.getNum();
+ obj2.free();
+ obj1.arrayGet(2*i+1, &obj2);
+ if (!obj2.isNum()) {
+ error(-1, "Illegal value in function range array");
+ goto err1;
+ }
+ range[i][1] = obj2.getNum();
+ obj2.free();
}
- range[i][1] = obj2.getNum();
- obj2.free();
+ obj1.free();
}
+
+ return gTrue;
+
+ err1:
+ obj2.free();
+ err2:
obj1.free();
+ return gFalse;
+}
+
+//------------------------------------------------------------------------
+// SampledFunction
+//------------------------------------------------------------------------
+
+SampledFunction::SampledFunction(Object *funcObj, Dict *dict) {
+ Stream *str;
+ int nSamples, sampleBits;
+ double sampleMul;
+ Object obj1, obj2;
+ Guint buf, bitMask;
+ int bits;
+ int s;
+ int i;
+
+ samples = NULL;
+ ok = gFalse;
+
+ //----- initialize the generic stuff
+ if (!init(dict)) {
+ goto err1;
+ }
+ if (!hasRange) {
+ error(-1, "Type 0 function is missing range");
+ goto err1;
+ }
+
+ //----- get the stream
+ if (!funcObj->isStream()) {
+ error(-1, "Type 0 function isn't a stream");
+ goto err1;
+ }
+ str = funcObj->getStream();
//----- Size
if (!dict->lookup("Size", &obj1)->isArray() ||
obj1.arrayGet(i, &obj2);
if (!obj2.isInt()) {
error(-1, "Illegal value in function size array");
- goto err1;
+ goto err3;
}
sampleSize[i] = obj2.getInt();
obj2.free();
obj1.arrayGet(2*i, &obj2);
if (!obj2.isNum()) {
error(-1, "Illegal value in function encode array");
- goto err1;
+ goto err3;
}
encode[i][0] = obj2.getNum();
obj2.free();
obj1.arrayGet(2*i+1, &obj2);
if (!obj2.isNum()) {
error(-1, "Illegal value in function encode array");
- goto err1;
+ goto err3;
}
encode[i][1] = obj2.getNum();
obj2.free();
obj1.arrayGet(2*i, &obj2);
if (!obj2.isNum()) {
error(-1, "Illegal value in function decode array");
- goto err1;
+ goto err3;
}
decode[i][0] = obj2.getNum();
obj2.free();
obj1.arrayGet(2*i+1, &obj2);
if (!obj2.isNum()) {
error(-1, "Illegal value in function decode array");
- goto err1;
+ goto err3;
}
decode[i][1] = obj2.getNum();
obj2.free();
}
samples[i] = (double)s * sampleMul;
}
+ str->close();
ok = gTrue;
return;
- err1:
+ err3:
obj2.free();
err2:
obj1.free();
- err3:
+ err1:
return;
}
-Function::Function(Function *func) {
+SampledFunction::~SampledFunction() {
+ if (samples) {
+ gfree(samples);
+ }
+}
+
+SampledFunction::SampledFunction(SampledFunction *func) {
int nSamples, i;
- m = func->m;
- n = func->n;
- memcpy(domain, func->domain, sizeof(domain));
- memcpy(range, func->range, sizeof(range));
- memcpy(sampleSize, func->sampleSize, sizeof(sampleSize));
- memcpy(encode, func->encode, sizeof(encode));
- memcpy(decode, func->decode, sizeof(decode));
+ memcpy(this, func, sizeof(SampledFunction));
nSamples = n;
- for (i = 0; i < m; ++i)
+ for (i = 0; i < m; ++i) {
nSamples *= sampleSize[i];
+ }
samples = (double *)gmalloc(nSamples * sizeof(double));
memcpy(samples, func->samples, nSamples * sizeof(double));
-
- ok = gTrue;
-}
-
-Function::~Function() {
- if (samples)
- gfree(samples);
}
-void Function::transform(double *in, double *out) {
+void SampledFunction::transform(double *in, double *out) {
double e[4];
double s;
double x0, x1;
for (i = 0; i < m; ++i) {
e[i] = ((in[i] - domain[i][0]) / (domain[i][1] - domain[i][0])) *
(encode[i][1] - encode[i][0]) + encode[i][0];
- if (e[i] < 0)
+ if (e[i] < 0) {
e[i] = 0;
- else if (e[i] > sampleSize[i] - 1)
+ } else if (e[i] > sampleSize[i] - 1) {
e[i] = sampleSize[i] - 1;
+ }
}
for (i = 0; i < n; ++i) {
// map output values to range
out[i] = s * (decode[i][1] - decode[i][0]) + decode[i][0];
- if (out[i] < range[i][0])
+ if (out[i] < range[i][0]) {
out[i] = range[i][0];
- else if (out[i] > range[i][1])
+ } else if (out[i] > range[i][1]) {
out[i] = range[i][1];
+ }
}
}
+//------------------------------------------------------------------------
+// ExponentialFunction
+//------------------------------------------------------------------------
+
+ExponentialFunction::ExponentialFunction(Object *funcObj, Dict *dict) {
+ Object obj1, obj2;
+ GBool hasN;
+ int i;
+
+ ok = gFalse;
+ hasN = gFalse;
+
+ //----- initialize the generic stuff
+ if (!init(dict)) {
+ goto err1;
+ }
+ if (m != 1) {
+ error(-1, "Exponential function with more than one input");
+ goto err1;
+ }
+
+ //----- default values
+ for (i = 0; i < funcMaxOutputs; ++i) {
+ c0[i] = 0;
+ c1[i] = 1;
+ }
+
+ //----- C0
+ if (dict->lookup("C0", &obj1)->isArray()) {
+ if (!hasN) {
+ n = obj1.arrayGetLength();
+ } else if (obj1.arrayGetLength() != n) {
+ error(-1, "Function's C0 array is wrong length");
+ goto err2;
+ }
+ for (i = 0; i < n; ++i) {
+ obj1.arrayGet(i, &obj2);
+ if (!obj2.isNum()) {
+ error(-1, "Illegal value in function C0 array");
+ goto err3;
+ }
+ c0[i] = obj2.getNum();
+ obj2.free();
+ }
+ obj1.free();
+ }
+
+ //----- C1
+ if (dict->lookup("C1", &obj1)->isArray()) {
+ if (!hasN) {
+ n = obj1.arrayGetLength();
+ } else if (obj1.arrayGetLength() != n) {
+ error(-1, "Function's C1 array is wrong length");
+ goto err2;
+ }
+ for (i = 0; i < n; ++i) {
+ obj1.arrayGet(i, &obj2);
+ if (!obj2.isNum()) {
+ error(-1, "Illegal value in function C1 array");
+ goto err3;
+ }
+ c1[i] = obj2.getNum();
+ obj2.free();
+ }
+ obj1.free();
+ }
+
+ //----- N (exponent)
+ if (!dict->lookup("N", &obj1)->isNum()) {
+ error(-1, "Function has missing or invalid N");
+ goto err2;
+ }
+ e = obj1.getNum();
+ obj1.free();
+
+ ok = gTrue;
+ return;
+
+ err3:
+ obj2.free();
+ err2:
+ obj1.free();
+ err1:
+ return;
+}
+
+ExponentialFunction::~ExponentialFunction() {
+}
+
+ExponentialFunction::ExponentialFunction(ExponentialFunction *func) {
+ memcpy(this, func, sizeof(ExponentialFunction));
+}
+
+void ExponentialFunction::transform(double *in, double *out) {
+ double x;
+ int i;
+
+ if (in[0] < domain[0][0]) {
+ x = domain[0][0];
+ } else if (in[0] > domain[0][1]) {
+ x = domain[0][1];
+ } else {
+ x = in[0];
+ }
+ for (i = 0; i < n; ++i) {
+ out[i] = c0[i] + pow(x, e) * (c1[i] - c0[i]);
+ if (hasRange) {
+ if (out[i] < range[i][0]) {
+ out[i] = range[i][0];
+ } else if (out[i] > range[i][1]) {
+ out[i] = range[i][1];
+ }
+ }
+ }
+ return;
+}
+
//------------------------------------------------------------------------
// GfxImageColorMap
//------------------------------------------------------------------------
-GfxImageColorMap::GfxImageColorMap(int bits1, Object *decode,
- GfxColorSpace *colorSpace1) {
- GfxColor color;
- double x[4];
- int maxPixel;
+GfxImageColorMap::GfxImageColorMap(int bits, Object *decode,
+ GfxColorSpace *colorSpace) {
+ GfxIndexedColorSpace *indexedCS;
+ GfxSeparationColorSpace *sepCS;
+ int maxPixel, indexHigh;
+ Guchar *lookup2;
+ Function *sepFunc;
Object obj;
- int i, j;
+ double x;
+ double y[gfxColorMaxComps];
+ int i, j, k;
ok = gTrue;
- // bits per component and colorspace
- bits = bits1;
+ // bits per component and color space
+ this->bits = bits;
maxPixel = (1 << bits) - 1;
- colorSpace = colorSpace1;
- mode = colorSpace->getMode();
+ this->colorSpace = colorSpace;
// get decode map
- indexed = colorSpace->isIndexed();
- sep = colorSpace->isSeparation();
if (decode->isNull()) {
- numComps = colorSpace->getNumPixelComps();
+ nComps = colorSpace->getNComps();
colorSpace->getDefaultRanges(decodeLow, decodeRange, maxPixel);
} else if (decode->isArray()) {
- numComps = decode->arrayGetLength() / 2;
- if (numComps != colorSpace->getNumPixelComps())
+ nComps = decode->arrayGetLength() / 2;
+ if (nComps != colorSpace->getNComps()) {
goto err1;
- indexed = colorSpace->isIndexed();
- for (i = 0; i < numComps; ++i) {
+ }
+ for (i = 0; i < nComps; ++i) {
decode->arrayGet(2*i, &obj);
- if (!obj.isNum())
+ if (!obj.isNum()) {
goto err2;
+ }
decodeLow[i] = obj.getNum();
obj.free();
decode->arrayGet(2*i+1, &obj);
- if (!obj.isNum())
+ if (!obj.isNum()) {
goto err2;
+ }
decodeRange[i] = obj.getNum() - decodeLow[i];
obj.free();
}
goto err1;
}
+#if 0 //~
// handle the case where fewer than 2^n palette entries of an n-bit
// indexed color space are populated (this happens, e.g., in files
// optimized by Distiller)
- if (colorSpace->isIndexed() && maxPixel > colorSpace->getIndexHigh()) {
- maxPixel = colorSpace->getIndexHigh();
- }
-
- // handle the case where fewer than 2^n palette entries of an n-bit
- // indexed color space are populated (this happens, e.g., in files
- // optimized by Distiller)
- if (indexed && maxPixel > colorSpace->getIndexHigh()) {
- maxPixel = colorSpace->getIndexHigh();
+ if (colorSpace->getMode() == csIndexed) {
+ i = ((GfxIndexedColorSpace *)colorSpace)->getIndexHigh();
+ if (i < maxPixel) {
+ maxPixel = i;
+ }
}
+#endif
- // construct lookup table
- lookup = (double (*)[4])gmalloc((maxPixel + 1) * 4 * sizeof(double));
- if (sep) {
- for (i = 0; i <= maxPixel; ++i) {
- x[0] = (double)i / (double)maxPixel;
- colorSpace->getColor(x, &color);
- lookup[i][0] = color.getR();
- lookup[i][1] = color.getG();
- lookup[i][2] = color.getB();
+ // Construct a lookup table -- this stores pre-computed decoded
+ // values for each component, i.e., the result of applying the
+ // decode mapping to each possible image pixel component value.
+ //
+ // Optimization: for Indexed and Separation color spaces (which have
+ // only one component), we store color values in the lookup table
+ // rather than component values.
+ colorSpace2 = NULL;
+ nComps2 = 0;
+ if (colorSpace->getMode() == csIndexed) {
+ // Note that indexHigh may not be the same as maxPixel --
+ // Distiller will remove unused palette entries, resulting in
+ // indexHigh < maxPixel.
+ indexedCS = (GfxIndexedColorSpace *)colorSpace;
+ colorSpace2 = indexedCS->getBase();
+ indexHigh = indexedCS->getIndexHigh();
+ nComps2 = colorSpace2->getNComps();
+ lookup = (double *)gmalloc((indexHigh + 1) * nComps2 * sizeof(double));
+ lookup2 = indexedCS->getLookup();
+ for (i = 0; i <= indexHigh; ++i) {
+ j = (int)(decodeLow[0] +(i * decodeRange[0]) / maxPixel + 0.5);
+ for (k = 0; k < nComps2; ++k) {
+ lookup[i*nComps2 + k] = lookup2[i*nComps2 + k] / 255.0;
+ }
}
- } else if (indexed) {
+ } else if (colorSpace->getMode() == csSeparation) {
+ sepCS = (GfxSeparationColorSpace *)colorSpace;
+ colorSpace2 = sepCS->getAlt();
+ nComps2 = colorSpace2->getNComps();
+ lookup = (double *)gmalloc((maxPixel + 1) * nComps2 * sizeof(double));
+ sepFunc = sepCS->getFunc();
for (i = 0; i <= maxPixel; ++i) {
- x[0] = (double)i;
- colorSpace->getColor(x, &color);
- lookup[i][0] = color.getR();
- lookup[i][1] = color.getG();
- lookup[i][2] = color.getB();
+ x = decodeLow[0] + (i * decodeRange[0]) / maxPixel;
+ sepFunc->transform(&x, y);
+ for (k = 0; k < nComps2; ++k) {
+ lookup[i*nComps2 + k] = y[k];
+ }
}
} else {
- for (i = 0; i <= maxPixel; ++i)
- for (j = 0; j < numComps; ++j)
- lookup[i][j] = decodeLow[j] + (i * decodeRange[j]) / maxPixel;
+ lookup = (double *)gmalloc((maxPixel + 1) * nComps * sizeof(double));
+ for (i = 0; i <= maxPixel; ++i) {
+ for (k = 0; k < nComps; ++k) {
+ lookup[i*nComps + k] = decodeLow[k] +
+ (i * decodeRange[k]) / maxPixel;
+ }
+ }
}
return;
gfree(lookup);
}
-void GfxImageColorMap::getColor(Guchar x[4], GfxColor *color) {
+void GfxImageColorMap::getGray(Guchar *x, double *gray) {
+ GfxColor color;
double *p;
+ int i;
- if (sep || indexed) {
- p = lookup[x[0]];
- color->setRGB(p[0], p[1], p[2]);
+ if (colorSpace2) {
+ p = &lookup[x[0] * nComps2];
+ for (i = 0; i < nComps2; ++i) {
+ color.c[i] = *p++;
+ }
+ colorSpace2->getGray(&color, gray);
} else {
- switch (mode) {
- case colorGray:
- color->setGray(lookup[x[0]][0]);
- break;
- case colorCMYK:
- color->setCMYK(lookup[x[0]][0], lookup[x[1]][1],
- lookup[x[2]][2], lookup[x[3]][3]);
- break;
- case colorRGB:
- color->setRGB(lookup[x[0]][0], lookup[x[1]][1], lookup[x[2]][2]);
- break;
- case colorLab:
- color->setLab(lookup[x[0]][0], lookup[x[1]][1], lookup[x[2]][2],
- colorSpace->getLabParams());
- break;
+ for (i = 0; i < nComps; ++i) {
+ color.c[i] = lookup[x[i] * nComps + i];
+ }
+ colorSpace->getGray(&color, gray);
+ }
+}
+
+void GfxImageColorMap::getRGB(Guchar *x, GfxRGB *rgb) {
+ GfxColor color;
+ double *p;
+ int i;
+
+ if (colorSpace2) {
+ p = &lookup[x[0] * nComps2];
+ for (i = 0; i < nComps2; ++i) {
+ color.c[i] = *p++;
+ }
+ colorSpace2->getRGB(&color, rgb);
+ } else {
+ for (i = 0; i < nComps; ++i) {
+ color.c[i] = lookup[x[i] * nComps + i];
+ }
+ colorSpace->getRGB(&color, rgb);
+ }
+}
+
+void GfxImageColorMap::getCMYK(Guchar *x, GfxCMYK *cmyk) {
+ GfxColor color;
+ double *p;
+ int i;
+
+ if (colorSpace2) {
+ p = &lookup[x[0] * nComps2];
+ for (i = 0; i < nComps2; ++i) {
+ color.c[i] = *p++;
}
+ colorSpace2->getCMYK(&color, cmyk);
+ } else {
+ for (i = 0; i < nComps; ++i) {
+ color.c[i] = lookup[x[i] * nComps + i];
+ }
+ colorSpace->getCMYK(&color, cmyk);
}
}
// GfxState
//------------------------------------------------------------------------
-GfxState::GfxState(int dpi, double px1a, double py1a, double px2a, double py2a,
- int rotate, GBool upsideDown) {
+GfxState::GfxState(double dpi, double px1a, double py1a,
+ double px2a, double py2a, int rotate, GBool upsideDown) {
double k;
px1 = px1a;
py1 = py1a;
px2 = px2a;
py2 = py2a;
- k = (double)dpi / 72.0;
+ k = dpi / 72.0;
if (rotate == 90) {
ctm[0] = 0;
ctm[1] = upsideDown ? k : -k;
pageHeight = k * (py2 - py1);
}
- fillColorSpace = new GfxColorSpace(colorGray);
- strokeColorSpace = new GfxColorSpace(colorGray);
- fillColor.setGray(0);
- strokeColor.setGray(0);
+ fillColorSpace = new GfxDeviceGrayColorSpace();
+ strokeColorSpace = new GfxDeviceGrayColorSpace();
+ fillColor.c[0] = 0;
+ strokeColor.c[0] = 0;
+ fillPattern = NULL;
+ strokePattern = NULL;
+ fillOpacity = 1;
+ strokeOpacity = 1;
lineWidth = 1;
lineDash = NULL;
}
GfxState::~GfxState() {
- if (fillColorSpace)
+ if (fillColorSpace) {
delete fillColorSpace;
- if (strokeColorSpace)
+ }
+ if (strokeColorSpace) {
delete strokeColorSpace;
+ }
+ if (fillPattern) {
+ delete fillPattern;
+ }
+ if (strokePattern) {
+ delete strokePattern;
+ }
gfree(lineDash);
delete path;
- if (saved)
+ if (saved) {
delete saved;
+ }
}
// Used for copy();
GfxState::GfxState(GfxState *state) {
memcpy(this, state, sizeof(GfxState));
- if (fillColorSpace)
+ if (fillColorSpace) {
fillColorSpace = state->fillColorSpace->copy();
- if (strokeColorSpace)
+ }
+ if (strokeColorSpace) {
strokeColorSpace = state->strokeColorSpace->copy();
+ }
+ if (fillPattern) {
+ fillPattern = state->fillPattern->copy();
+ }
+ if (strokePattern) {
+ strokePattern = state->strokePattern->copy();
+ }
if (lineDashLength > 0) {
lineDash = (double *)gmalloc(lineDashLength * sizeof(double));
memcpy(lineDash, state->lineDash, lineDashLength * sizeof(double));
}
void GfxState::setFillColorSpace(GfxColorSpace *colorSpace) {
- if (fillColorSpace)
+ if (fillColorSpace) {
delete fillColorSpace;
+ }
fillColorSpace = colorSpace;
}
void GfxState::setStrokeColorSpace(GfxColorSpace *colorSpace) {
- if (strokeColorSpace)
+ if (strokeColorSpace) {
delete strokeColorSpace;
+ }
strokeColorSpace = colorSpace;
}
+void GfxState::setFillPattern(GfxPattern *pattern) {
+ if (fillPattern) {
+ delete fillPattern;
+ }
+ fillPattern = pattern;
+}
+
+void GfxState::setStrokePattern(GfxPattern *pattern) {
+ if (strokePattern) {
+ delete strokePattern;
+ }
+ strokePattern = pattern;
+}
+
void GfxState::setLineDash(double *dash, int length, double start) {
if (lineDash)
gfree(lineDash);
#endif
#include "gtypes.h"
+#include "Object.h"
-class Object;
+class Array;
class Function;
class GfxFont;
//------------------------------------------------------------------------
-// LabParams
+// GfxColor
//------------------------------------------------------------------------
-// Parameters for L*a*b* color spaces.
-struct LabParams {
- double whiteX, whiteY, whiteZ;
- double aMin, aMax, bMin, bMax;
+#define gfxColorMaxComps 8
+
+struct GfxColor {
+ double c[gfxColorMaxComps];
};
//------------------------------------------------------------------------
-// GfxColor
+// GfxRGB
+//------------------------------------------------------------------------
+
+struct GfxRGB {
+ double r, g, b;
+};
+
+//------------------------------------------------------------------------
+// GfxCMYK
+//------------------------------------------------------------------------
+
+struct GfxCMYK {
+ double c, m, y, k;
+};
+
//------------------------------------------------------------------------
+// GfxColorSpace
+//------------------------------------------------------------------------
+
+enum GfxColorSpaceMode {
+ csDeviceGray,
+ csCalGray,
+ csDeviceRGB,
+ csCalRGB,
+ csDeviceCMYK,
+ csLab,
+ csICCBased,
+ csIndexed,
+ csSeparation,
+ csDeviceN,
+ csPattern
+};
-class GfxColor {
+class GfxColorSpace {
public:
- GfxColor(): r(0), g(0), b(0) {}
+ GfxColorSpace();
+ virtual ~GfxColorSpace();
+ virtual GfxColorSpace *copy() = 0;
+ virtual GfxColorSpaceMode getMode() = 0;
- // Set color.
- void setGray(double gray);
- void setCMYK(double c, double m, double y, double k);
- void setRGB(double r1, double g1, double b1);
- void setLab(double L, double a, double bb, LabParams *params);
+ // Construct a color space. Returns NULL if unsuccessful.
+ static GfxColorSpace *parse(Object *csObj);
- // Accessors.
- double getR() { return r; }
- double getG() { return g; }
- double getB() { return b; }
- double getGray() { return 0.299 * r + 0.587 * g + 0.114 * b; }
+ // Convert to gray, RGB, or CMYK.
+ virtual void getGray(GfxColor *color, double *gray) = 0;
+ virtual void getRGB(GfxColor *color, GfxRGB *rgb) = 0;
+ virtual void getCMYK(GfxColor *color, GfxCMYK *cmyk) = 0;
+
+ // Return the number of color components.
+ virtual int getNComps() = 0;
+
+ // Return the default ranges for each component, assuming an image
+ // with a max pixel value of <maxImgPixel>.
+ virtual void getDefaultRanges(double *decodeLow, double *decodeRange,
+ int maxImgPixel);
private:
+};
- double r, g, b;
+//------------------------------------------------------------------------
+// GfxDeviceGrayColorSpace
+//------------------------------------------------------------------------
+
+class GfxDeviceGrayColorSpace: public GfxColorSpace {
+public:
+
+ GfxDeviceGrayColorSpace();
+ virtual ~GfxDeviceGrayColorSpace();
+ virtual GfxColorSpace *copy();
+ virtual GfxColorSpaceMode getMode() { return csDeviceGray; }
+
+ virtual void getGray(GfxColor *color, double *gray);
+ virtual void getRGB(GfxColor *color, GfxRGB *rgb);
+ virtual void getCMYK(GfxColor *color, GfxCMYK *cmyk);
+
+ virtual int getNComps() { return 1; }
+
+private:
};
//------------------------------------------------------------------------
-// GfxColorSpace
+// GfxCalGrayColorSpace
//------------------------------------------------------------------------
-enum GfxColorMode {
- colorGray, colorCMYK, colorRGB, colorLab
+class GfxCalGrayColorSpace: public GfxColorSpace {
+public:
+
+ GfxCalGrayColorSpace();
+ virtual ~GfxCalGrayColorSpace();
+ virtual GfxColorSpace *copy();
+ virtual GfxColorSpaceMode getMode() { return csCalGray; }
+
+ // Construct a CalGray color space. Returns NULL if unsuccessful.
+ static GfxColorSpace *parse(Array *arr);
+
+ virtual void getGray(GfxColor *color, double *gray);
+ virtual void getRGB(GfxColor *color, GfxRGB *rgb);
+ virtual void getCMYK(GfxColor *color, GfxCMYK *cmyk);
+
+ virtual int getNComps() { return 1; }
+
+ // CalGray-specific access.
+ double getWhiteX() { return whiteX; }
+ double getWhiteY() { return whiteY; }
+ double getWhiteZ() { return whiteZ; }
+ double getBlackX() { return blackX; }
+ double getBlackY() { return blackY; }
+ double getBlackZ() { return blackZ; }
+ double getGamma() { return gamma; }
+
+private:
+
+ double whiteX, whiteY, whiteZ; // white point
+ double blackX, blackY, blackZ; // black point
+ double gamma; // gamma value
};
-class GfxColorSpace {
+//------------------------------------------------------------------------
+// GfxDeviceRGBColorSpace
+//------------------------------------------------------------------------
+
+class GfxDeviceRGBColorSpace: public GfxColorSpace {
public:
- // Construct a colorspace.
- GfxColorSpace(Object *colorSpace);
+ GfxDeviceRGBColorSpace();
+ virtual ~GfxDeviceRGBColorSpace();
+ virtual GfxColorSpace *copy();
+ virtual GfxColorSpaceMode getMode() { return csDeviceRGB; }
- // Construct a simple colorspace: DeviceGray, DeviceCMYK, or
- // DeviceRGB.
- GfxColorSpace(GfxColorMode mode1);
+ virtual void getGray(GfxColor *color, double *gray);
+ virtual void getRGB(GfxColor *color, GfxRGB *rgb);
+ virtual void getCMYK(GfxColor *color, GfxCMYK *cmyk);
- // Destructor.
- ~GfxColorSpace();
+ virtual int getNComps() { return 3; }
- // Copy.
- GfxColorSpace *copy() { return new GfxColorSpace(this); }
+private:
+};
- // Is color space valid?
- GBool isOk() { return ok; }
+//------------------------------------------------------------------------
+// GfxCalRGBColorSpace
+//------------------------------------------------------------------------
+
+class GfxCalRGBColorSpace: public GfxColorSpace {
+public:
+
+ GfxCalRGBColorSpace();
+ virtual ~GfxCalRGBColorSpace();
+ virtual GfxColorSpace *copy();
+ virtual GfxColorSpaceMode getMode() { return csCalRGB; }
+
+ // Construct a CalRGB color space. Returns NULL if unsuccessful.
+ static GfxColorSpace *parse(Array *arr);
+
+ virtual void getGray(GfxColor *color, double *gray);
+ virtual void getRGB(GfxColor *color, GfxRGB *rgb);
+ virtual void getCMYK(GfxColor *color, GfxCMYK *cmyk);
+
+ virtual int getNComps() { return 3; }
+
+ // CalRGB-specific access.
+ double getWhiteX() { return whiteX; }
+ double getWhiteY() { return whiteY; }
+ double getWhiteZ() { return whiteZ; }
+ double getBlackX() { return blackX; }
+ double getBlackY() { return blackY; }
+ double getBlackZ() { return blackZ; }
+ double getGammaR() { return gammaR; }
+ double getGammaG() { return gammaG; }
+ double getGammaB() { return gammaB; }
+ double *getMatrix() { return m; }
+
+private:
+
+ double whiteX, whiteY, whiteZ; // white point
+ double blackX, blackY, blackZ; // black point
+ double gammaR, gammaG, gammaB; // gamma values
+ double m[9]; // ABC -> XYZ transform matrix
+};
+
+//------------------------------------------------------------------------
+// GfxDeviceCMYKColorSpace
+//------------------------------------------------------------------------
+
+class GfxDeviceCMYKColorSpace: public GfxColorSpace {
+public:
- // Get the color mode.
- GfxColorMode getMode() { return mode; }
+ GfxDeviceCMYKColorSpace();
+ virtual ~GfxDeviceCMYKColorSpace();
+ virtual GfxColorSpace *copy();
+ virtual GfxColorSpaceMode getMode() { return csDeviceCMYK; }
- // Get number of components in pixels of this colorspace.
- int getNumPixelComps() { return (sepFunc || indexed) ? 1 : numComps; }
+ virtual void getGray(GfxColor *color, double *gray);
+ virtual void getRGB(GfxColor *color, GfxRGB *rgb);
+ virtual void getCMYK(GfxColor *color, GfxCMYK *cmyk);
+
+ virtual int getNComps() { return 4; }
+
+private:
+};
+
+//------------------------------------------------------------------------
+// GfxLabColorSpace
+//------------------------------------------------------------------------
+
+class GfxLabColorSpace: public GfxColorSpace {
+public:
- // Get number of components in colors of this colorspace.
- int getNumColorComps() { return numComps; }
+ GfxLabColorSpace();
+ virtual ~GfxLabColorSpace();
+ virtual GfxColorSpace *copy();
+ virtual GfxColorSpaceMode getMode() { return csLab; }
- // Return true if colorspace is indexed.
- GBool isIndexed() { return indexed; }
+ // Construct a Lab color space. Returns NULL if unsuccessful.
+ static GfxColorSpace *parse(Array *arr);
- // Return true for a separation colorspace.
- GBool isSeparation() { return sepFunc ? gTrue : gFalse; }
+ virtual void getGray(GfxColor *color, double *gray);
+ virtual void getRGB(GfxColor *color, GfxRGB *rgb);
+ virtual void getCMYK(GfxColor *color, GfxCMYK *cmyk);
- // Get default ranges for the components.
- void getDefaultRanges(double *decodeLow, double *decodeRange, int maxPixel);
+ virtual int getNComps() { return 3; }
- // Get lookup table (only for indexed colorspaces).
+ virtual void getDefaultRanges(double *decodeLow, double *decodeRange,
+ int maxImgPixel);
+
+ // Lab-specific access.
+ double getWhiteX() { return whiteX; }
+ double getWhiteY() { return whiteY; }
+ double getWhiteZ() { return whiteZ; }
+ double getBlackX() { return blackX; }
+ double getBlackY() { return blackY; }
+ double getBlackZ() { return blackZ; }
+ double getAMin() { return aMin; }
+ double getAMax() { return aMax; }
+ double getBMin() { return bMin; }
+ double getBMax() { return bMax; }
+
+private:
+
+ double whiteX, whiteY, whiteZ; // white point
+ double blackX, blackY, blackZ; // black point
+ double aMin, aMax, bMin, bMax; // range for the a and b components
+ double kr, kg, kb; // gamut mapping mulitpliers
+};
+
+//------------------------------------------------------------------------
+// GfxICCBasedColorSpace
+//------------------------------------------------------------------------
+
+class GfxICCBasedColorSpace: public GfxColorSpace {
+public:
+
+ GfxICCBasedColorSpace(int nComps, GfxColorSpace *alt,
+ Ref *iccProfileStream);
+ virtual ~GfxICCBasedColorSpace();
+ virtual GfxColorSpace *copy();
+ virtual GfxColorSpaceMode getMode() { return csICCBased; }
+
+ // Construct an ICCBased color space. Returns NULL if unsuccessful.
+ static GfxColorSpace *parse(Array *arr);
+
+ virtual void getGray(GfxColor *color, double *gray);
+ virtual void getRGB(GfxColor *color, GfxRGB *rgb);
+ virtual void getCMYK(GfxColor *color, GfxCMYK *cmyk);
+
+ virtual int getNComps() { return nComps; }
+
+ virtual void getDefaultRanges(double *decodeLow, double *decodeRange,
+ int maxImgPixel);
+
+ // ICCBased-specific access.
+ GfxColorSpace *getAlt() { return alt; }
+
+private:
+
+ int nComps; // number of color components (1, 3, or 4)
+ GfxColorSpace *alt; // alternate color space
+ double rangeMin[4]; // min values for each component
+ double rangeMax[4]; // max values for each component
+ Ref iccProfileStream; // the ICC profile
+};
+
+//------------------------------------------------------------------------
+// GfxIndexedColorSpace
+//------------------------------------------------------------------------
+
+class GfxIndexedColorSpace: public GfxColorSpace {
+public:
+
+ GfxIndexedColorSpace(GfxColorSpace *base, int indexHigh);
+ virtual ~GfxIndexedColorSpace();
+ virtual GfxColorSpace *copy();
+ virtual GfxColorSpaceMode getMode() { return csIndexed; }
+
+ // Construct a Lab color space. Returns NULL if unsuccessful.
+ static GfxColorSpace *parse(Array *arr);
+
+ virtual void getGray(GfxColor *color, double *gray);
+ virtual void getRGB(GfxColor *color, GfxRGB *rgb);
+ virtual void getCMYK(GfxColor *color, GfxCMYK *cmyk);
+
+ virtual int getNComps() { return 1; }
+
+ virtual void getDefaultRanges(double *decodeLow, double *decodeRange,
+ int maxImgPixel);
+
+ // Indexed-specific access.
+ GfxColorSpace *getBase() { return base; }
int getIndexHigh() { return indexHigh; }
- Guchar *getLookupVal(int i) { return lookup[i]; }
+ Guchar *getLookup() { return lookup; }
+
+private:
+
+ GfxColorSpace *base; // base color space
+ int indexHigh; // max pixel value
+ Guchar *lookup; // lookup table
+};
+
+//------------------------------------------------------------------------
+// GfxSeparationColorSpace
+//------------------------------------------------------------------------
+
+class GfxSeparationColorSpace: public GfxColorSpace {
+public:
+
+ GfxSeparationColorSpace(GString *name, GfxColorSpace *alt,
+ Function *func);
+ virtual ~GfxSeparationColorSpace();
+ virtual GfxColorSpace *copy();
+ virtual GfxColorSpaceMode getMode() { return csSeparation; }
+
+ // Construct a Separation color space. Returns NULL if unsuccessful.
+ static GfxColorSpace *parse(Array *arr);
+
+ virtual void getGray(GfxColor *color, double *gray);
+ virtual void getRGB(GfxColor *color, GfxRGB *rgb);
+ virtual void getCMYK(GfxColor *color, GfxCMYK *cmyk);
+
+ virtual int getNComps() { return 1; }
+
+ // Separation-specific access.
+ GString *getName() { return name; }
+ GfxColorSpace *getAlt() { return alt; }
+ Function *getFunc() { return func; }
+
+private:
+
+ GString *name; // colorant name
+ GfxColorSpace *alt; // alternate color space
+ Function *func; // tint transform (into alternate color space)
+};
+
+//------------------------------------------------------------------------
+// GfxDeviceNColorSpace
+//------------------------------------------------------------------------
+
+class GfxDeviceNColorSpace: public GfxColorSpace {
+public:
+
+ GfxDeviceNColorSpace(int nComps, GfxColorSpace *alt, Function *func);
+ virtual ~GfxDeviceNColorSpace();
+ virtual GfxColorSpace *copy();
+ virtual GfxColorSpaceMode getMode() { return csDeviceN; }
+
+ // Construct a DeviceN color space. Returns NULL if unsuccessful.
+ static GfxColorSpace *parse(Array *arr);
+
+ virtual void getGray(GfxColor *color, double *gray);
+ virtual void getRGB(GfxColor *color, GfxRGB *rgb);
+ virtual void getCMYK(GfxColor *color, GfxCMYK *cmyk);
+
+ virtual int getNComps() { return nComps; }
+
+ // DeviceN-specific access.
+ GfxColorSpace *getAlt() { return alt; }
+
+private:
+
+ int nComps; // number of components
+ GString // colorant names
+ *names[gfxColorMaxComps];
+ GfxColorSpace *alt; // alternate color space
+ Function *func; // tint transform (into alternate color space)
+
+};
+
+//------------------------------------------------------------------------
+// GfxPatternColorSpace
+//------------------------------------------------------------------------
+
+class GfxPatternColorSpace: public GfxColorSpace {
+public:
+
+ GfxPatternColorSpace(GfxColorSpace *under);
+ virtual ~GfxPatternColorSpace();
+ virtual GfxColorSpace *copy();
+ virtual GfxColorSpaceMode getMode() { return csPattern; }
+
+ // Construct a Pattern color space. Returns NULL if unsuccessful.
+ static GfxColorSpace *parse(Array *arr);
+
+ virtual void getGray(GfxColor *color, double *gray);
+ virtual void getRGB(GfxColor *color, GfxRGB *rgb);
+ virtual void getCMYK(GfxColor *color, GfxCMYK *cmyk);
+
+ virtual int getNComps() { return 0; }
+
+ // Pattern-specific access.
+ GfxColorSpace *getUnder() { return under; }
+
+private:
- // Convert a pixel to a color.
- void getColor(double x[4], GfxColor *color);
+ GfxColorSpace *under; // underlying color space (for uncolored
+ // patterns)
+};
+
+//------------------------------------------------------------------------
+// GfxPattern
+//------------------------------------------------------------------------
+
+class GfxPattern {
+public:
+
+ GfxPattern(int type);
+ virtual ~GfxPattern();
+
+ static GfxPattern *parse(Object *obj);
+
+ virtual GfxPattern *copy() = 0;
+
+ int getType() { return type; }
+
+private:
+
+ int type;
+};
+
+//------------------------------------------------------------------------
+// GfxTilingPattern
+//------------------------------------------------------------------------
+
+class GfxTilingPattern: public GfxPattern {
+public:
+
+ GfxTilingPattern(Dict *streamDict, Object *stream);
+ virtual ~GfxTilingPattern();
- // Get the L*a*b* color space parameters.
- LabParams *getLabParams() { return &labParams; }
+ virtual GfxPattern *copy();
+
+ int getPaintType() { return paintType; }
+ int getTilingType() { return tilingType; }
+ double *getBBox() { return bbox; }
+ double getXStep() { return xStep; }
+ double getYStep() { return yStep; }
+ Dict *getResDict()
+ { return resDict.isDict() ? resDict.getDict() : (Dict *)NULL; }
+ double *getMatrix() { return matrix; }
+ Object *getContentStream() { return &contentStream; }
private:
- Function *sepFunc; // separation tint transform function
- GfxColorMode mode; // color mode
- GBool indexed; // set for indexed colorspaces
- int numComps; // number of components in colors
- int indexHigh; // max pixel for indexed colorspace
- Guchar (*lookup)[4]; // lookup table (only for indexed
- // colorspaces)
- LabParams labParams; // parameters for L*a*b* color space
- GBool ok; // is color space valid?
-
- GfxColorSpace(GfxColorSpace *colorSpace);
- void setMode(Object *colorSpace);
+ GfxTilingPattern(GfxTilingPattern *pat);
+
+ int paintType;
+ int tilingType;
+ double bbox[4];
+ double xStep, yStep;
+ Object resDict;
+ double matrix[6];
+ Object contentStream;
};
//------------------------------------------------------------------------
// Function
//------------------------------------------------------------------------
+#define funcMaxInputs 1
+#define funcMaxOutputs 8
+
class Function {
public:
- // Create a PDF function object.
- Function(Object *funcObj);
+ Function();
- ~Function();
-
- Function *copy() { return new Function(this); }
+ virtual ~Function();
- GBool isOk() { return ok; }
+ // Construct a function. Returns NULL if unsuccessful.
+ static Function *parse(Object *funcObj);
+
+ // Initialize the entries common to all function types.
+ GBool init(Dict *dict);
+
+ virtual Function *copy() = 0;
// Return size of input and output tuples.
int getInputSize() { return m; }
int getOutputSize() { return n; }
// Transform an input tuple into an output tuple.
- void transform(double *in, double *out);
+ virtual void transform(double *in, double *out) = 0;
-private:
+ virtual GBool isOk() = 0;
- Function(Function *func);
+protected:
int m, n; // size of input and output tuples
- double domain[1][2]; // min and max values for function domain
- double range[4][2]; // min and max values for function range
- int sampleSize[1]; // number of samples for each domain element
- double encode[1][2]; // min and max values for domain encoder
- double decode[4][2]; // min and max values for range decoder
+ double // min and max values for function domain
+ domain[funcMaxInputs][2];
+ double // min and max values for function range
+ range[funcMaxOutputs][2];
+ GBool hasRange; // set if range is defined
+};
+
+//------------------------------------------------------------------------
+// SampledFunction
+//------------------------------------------------------------------------
+
+class SampledFunction: public Function {
+public:
+
+ SampledFunction(Object *funcObj, Dict *dict);
+ virtual ~SampledFunction();
+ virtual Function *copy() { return new SampledFunction(this); }
+ virtual void transform(double *in, double *out);
+ virtual GBool isOk() { return ok; }
+
+private:
+
+ SampledFunction(SampledFunction *func);
+
+ int // number of samples for each domain element
+ sampleSize[funcMaxInputs];
+ double // min and max values for domain encoder
+ encode[funcMaxInputs][2];
+ double // min and max values for range decoder
+ decode[funcMaxOutputs][2];
double *samples; // the samples
GBool ok;
};
+//------------------------------------------------------------------------
+// ExponentialFunction
+//------------------------------------------------------------------------
+
+class ExponentialFunction: public Function {
+public:
+
+ ExponentialFunction(Object *funcObj, Dict *dict);
+ virtual ~ExponentialFunction();
+ virtual Function *copy() { return new ExponentialFunction(this); }
+ virtual void transform(double *in, double *out);
+ virtual GBool isOk() { return ok; }
+
+private:
+
+ ExponentialFunction(ExponentialFunction *func);
+
+ double c0[funcMaxOutputs];
+ double c1[funcMaxOutputs];
+ double e;
+ GBool ok;
+};
+
//------------------------------------------------------------------------
// GfxImageColorMap
//------------------------------------------------------------------------
public:
// Constructor.
- GfxImageColorMap(int bits1, Object *decode, GfxColorSpace *colorSpace1);
+ GfxImageColorMap(int bits, Object *decode, GfxColorSpace *colorSpace);
// Destructor.
~GfxImageColorMap();
GfxColorSpace *getColorSpace() { return colorSpace; }
// Get stream decoding info.
- int getNumPixelComps() { return numComps; }
+ int getNumPixelComps() { return nComps; }
int getBits() { return bits; }
// Get decode table.
double getDecodeLow(int i) { return decodeLow[i]; }
double getDecodeHigh(int i) { return decodeLow[i] + decodeRange[i]; }
- // Convert a pixel to a color.
- void getColor(Guchar x[4], GfxColor *color);
+ // Convert an image pixel to a color.
+ void getGray(Guchar *x, double *gray);
+ void getRGB(Guchar *x, GfxRGB *rgb);
+ void getCMYK(Guchar *x, GfxCMYK *cmyk);
private:
- GfxColorSpace *colorSpace; // the image colorspace
+ GfxColorSpace *colorSpace; // the image color space
int bits; // bits per component
- int numComps; // number of components in a pixel
- GBool indexed; // set for indexed color space
- GBool sep; // set for separation colorspaces
- GfxColorMode mode; // color mode
- double (*lookup)[4]; // lookup table
- double decodeLow[4]; // minimum values for each component
- double decodeRange[4]; // max - min value for each component
+ int nComps; // number of components in a pixel
+ GfxColorSpace *colorSpace2; // secondary color space
+ int nComps2; // number of components in colorSpace2
+ double *lookup; // lookup table
+ double // minimum values for each component
+ decodeLow[gfxColorMaxComps];
+ double // max - min value for each component
+ decodeRange[gfxColorMaxComps];
GBool ok;
};
// Construct a default GfxState, for a device with resolution <dpi>,
// page box (<x1>,<y1>)-(<x2>,<y2>), page rotation <rotate>, and
// coordinate system specified by <upsideDown>.
- GfxState(int dpi, double px1a, double py1a, double px2a, double py2a,
- int rotate, GBool upsideDown);
+ GfxState(double dpi, double px1a, double py1a,
+ double px2a, double py2a, int rotate, GBool upsideDown);
// Destructor.
~GfxState();
double getPageHeight() { return pageHeight; }
GfxColor *getFillColor() { return &fillColor; }
GfxColor *getStrokeColor() { return &strokeColor; }
+ void getFillRGB(GfxRGB *rgb)
+ { fillColorSpace->getRGB(&fillColor, rgb); }
+ void getStrokeRGB(GfxRGB *rgb)
+ { strokeColorSpace->getRGB(&strokeColor, rgb); }
+ void getFillCMYK(GfxCMYK *cmyk)
+ { fillColorSpace->getCMYK(&fillColor, cmyk); }
+ void getStrokeCMYK(GfxCMYK *cmyk)
+ { strokeColorSpace->getCMYK(&strokeColor, cmyk); }
+ GfxColorSpace *getFillColorSpace() { return fillColorSpace; }
+ GfxColorSpace *getStrokeColorSpace() { return strokeColorSpace; }
+ GfxPattern *getFillPattern() { return fillPattern; }
+ GfxPattern *getStrokePattern() { return strokePattern; }
+ double getFillOpacity() { return fillOpacity; }
+ double getStrokeOpacity() { return strokeOpacity; }
double getLineWidth() { return lineWidth; }
void getLineDash(double **dash, int *length, double *start)
{ *dash = lineDash; *length = lineDashLength; *start = lineDashStart; }
double d, double e, double f);
void concatCTM(double a, double b, double c,
double d, double e, double f);
- void setFillGray(double gray)
- { fillColor.setGray(gray); }
- void setFillCMYK(double c, double m, double y, double k)
- { fillColor.setCMYK(c, m, y, k); }
- void setFillRGB(double r, double g, double b)
- { fillColor.setRGB(r, g, b); }
- void setStrokeGray(double gray)
- { strokeColor.setGray(gray); }
- void setStrokeCMYK(double c, double m, double y, double k)
- { strokeColor.setCMYK(c, m, y, k); }
- void setStrokeRGB(double r, double g, double b)
- { strokeColor.setRGB(r, g, b); }
void setFillColorSpace(GfxColorSpace *colorSpace);
void setStrokeColorSpace(GfxColorSpace *colorSpace);
- void setFillColor(double x[4])
- { fillColorSpace->getColor(x, &fillColor); }
- void setStrokeColor(double x[4])
- { strokeColorSpace->getColor(x, &strokeColor); }
- void setLineWidth(double width)
- { lineWidth = width; }
+ void setFillColor(GfxColor *color) { fillColor = *color; }
+ void setStrokeColor(GfxColor *color) { strokeColor = *color; }
+ void setFillPattern(GfxPattern *pattern);
+ void setStrokePattern(GfxPattern *pattern);
+ void setFillOpacity(double opac) { fillOpacity = opac; }
+ void setStrokeOpacity(double opac) { strokeOpacity = opac; }
+ void setLineWidth(double width) { lineWidth = width; }
void setLineDash(double *dash, int length, double start);
void setFlatness(int flatness1) { flatness = flatness1; }
void setLineJoin(int lineJoin1) { lineJoin = lineJoin1; }
GfxColorSpace *strokeColorSpace; // stroke color space
GfxColor fillColor; // fill color
GfxColor strokeColor; // stroke color
+ GfxPattern *fillPattern; // fill pattern
+ GfxPattern *strokePattern; // stroke pattern
+ double fillOpacity; // fill opacity
+ double strokeOpacity; // stroke opacity
double lineWidth; // line width
double *lineDash; // line dash
+++ /dev/null
-//========================================================================
-//
-// ImageOutputDev.cc
-//
-// Copyright 1998 Derek B. Noonburg
-//
-//========================================================================
-
-#ifdef __GNUC__
-#pragma implementation
-#endif
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <stddef.h>
-#include <ctype.h>
-#include "gmem.h"
-#include "config.h"
-#include "Error.h"
-#include "GfxState.h"
-#include "Object.h"
-#include "Stream.h"
-#include "ImageOutputDev.h"
-
-ImageOutputDev::ImageOutputDev(char *fileRoot1, GBool dumpJPEG1) {
- fileRoot = copyString(fileRoot1);
- fileName = (char *)gmalloc(strlen(fileRoot) + 20);
- dumpJPEG = dumpJPEG1;
- imgNum = 0;
- ok = gTrue;
-}
-
-ImageOutputDev::~ImageOutputDev() {
- gfree(fileName);
- gfree(fileRoot);
-}
-
-void ImageOutputDev::drawImageMask(GfxState *state, Stream *str,
- int width, int height, GBool invert,
- GBool inlineImg) {
- FILE *f;
- int c;
-
- // dump JPEG file
- if (dumpJPEG && str->getKind() == strDCT) {
-
- // open the image file
- sprintf(fileName, "%s-%03d.jpg", fileRoot, imgNum);
- ++imgNum;
- if (!(f = fopen(fileName, "wb"))) {
- error(-1, "Couldn't open image file '%s'", fileName);
- return;
- }
-
- // initialize stream
- str = ((DCTStream *)str)->getRawStream();
- str->reset();
-
- // copy the stream
- while ((c = str->getChar()) != EOF)
- fputc(c, f);
-
- fclose(f);
-
- // dump PBM file
- } else {
-
- // open the image file and write the PBM header
- sprintf(fileName, "%s-%03d.pbm", fileRoot, imgNum);
- ++imgNum;
- if (!(f = fopen(fileName, "wb"))) {
- error(-1, "Couldn't open image file '%s'", fileName);
- return;
- }
- fprintf(f, "P4\n");
- fprintf(f, "%d %d\n", width, height);
-
- // initialize stream
- str->reset();
-
- // copy the stream
- while ((c = str->getChar()) != EOF)
- fputc(c, f);
-
- fclose(f);
- }
-}
-
-void ImageOutputDev::drawImage(GfxState *state, Stream *str, int width,
- int height, GfxImageColorMap *colorMap,
- GBool inlineImg) {
- FILE *f;
- ImageStream *imgStr;
- Guchar pixBuf[4];
- GfxColor color;
- int x, y;
- int c;
-
- // dump JPEG file
- if (dumpJPEG && str->getKind() == strDCT) {
-
- // open the image file
- sprintf(fileName, "%s-%03d.jpg", fileRoot, imgNum);
- ++imgNum;
- if (!(f = fopen(fileName, "wb"))) {
- error(-1, "Couldn't open image file '%s'", fileName);
- return;
- }
-
- // initialize stream
- str = ((DCTStream *)str)->getRawStream();
- str->reset();
-
- // copy the stream
- while ((c = str->getChar()) != EOF)
- fputc(c, f);
-
- fclose(f);
-
- // dump PPM file
- } else {
-
- // open the image file and write the PPM header
- sprintf(fileName, "%s-%03d.ppm", fileRoot, imgNum);
- ++imgNum;
- if (!(f = fopen(fileName, "wb"))) {
- error(-1, "Couldn't open image file '%s'", fileName);
- return;
- }
- fprintf(f, "P6\n");
- fprintf(f, "%d %d\n", width, height);
- fprintf(f, "255\n");
-
- // initialize stream
- imgStr = new ImageStream(str, width, colorMap->getNumPixelComps(),
- colorMap->getBits());
- imgStr->reset();
-
- // for each line...
- for (y = 0; y < height; ++y) {
-
- // write the line
- for (x = 0; x < width; ++x) {
- imgStr->getPixel(pixBuf);
- colorMap->getColor(pixBuf, &color);
- fputc((int)(color.getR() * 255 + 0.5), f);
- fputc((int)(color.getG() * 255 + 0.5), f);
- fputc((int)(color.getB() * 255 + 0.5), f);
- }
- }
- delete imgStr;
-
- fclose(f);
- }
-}
+++ /dev/null
-//========================================================================
-//
-// ImageOutputDev.h
-//
-// Copyright 1998 Derek B. Noonburg
-//
-//========================================================================
-
-#ifndef IMAGEOUTPUTDEV_H
-#define IMAGEOUTPUTDEV_H
-
-#ifdef __GNUC__
-#pragma interface
-#endif
-
-#include <stdio.h>
-#include "gtypes.h"
-#include "OutputDev.h"
-
-class GfxState;
-
-//------------------------------------------------------------------------
-// ImageOutputDev
-//------------------------------------------------------------------------
-
-class ImageOutputDev: public OutputDev {
-public:
-
- // Create an OutputDev which will write images to files named
- // <fileRoot>-NNN.<type>. Normally, all images are written as PBM
- // (.pbm) or PPM (.ppm) files. If <dumpJPEG> is set, JPEG images are
- // written as JPEG (.jpg) files.
- ImageOutputDev(char *fileRoot1, GBool dumpJPEG1);
-
- // Destructor.
- virtual ~ImageOutputDev();
-
- // Check if file was successfully created.
- virtual GBool isOk() { return ok; }
-
- //---- get info about output device
-
- // Does this device use upside-down coordinates?
- // (Upside-down means (0,0) is the top left corner of the page.)
- virtual GBool upsideDown() { return gTrue; }
-
- // Does this device use drawChar() or drawString()?
- virtual GBool useDrawChar() { return gFalse; }
-
- //----- image drawing
- virtual void drawImageMask(GfxState *state, Stream *str,
- int width, int height, GBool invert,
- GBool inlineImg);
- virtual void drawImage(GfxState *state, Stream *str, int width,
- int height, GfxImageColorMap *colorMap,
- GBool inlineImg);
-
-private:
-
- char *fileRoot; // root of output file names
- char *fileName; // buffer for output file names
- GBool dumpJPEG; // set to dump native JPEG files
- int imgNum; // current image number
- GBool ok; // set up ok?
-};
-
-#endif
//------------------------------------------------------------------------
-// A '1' in this array means the corresponding character ends a name
-// or command.
-static char endOfNameChars[128] = {
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 0, 0, // 0x
+// A '1' in this array means the character is white space. A '1' or
+// '2' means the character ends a name or command.
+static char specialChars[256] = {
+ 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 1, 1, 0, 0, // 0x
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 1x
- 1, 0, 0, 0, 0, 1, 0, 0, 1, 1, 0, 0, 0, 0, 0, 1, // 2x
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, // 3x
+ 1, 0, 0, 0, 0, 2, 0, 0, 2, 2, 0, 0, 0, 0, 0, 2, // 2x
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 2, 0, // 3x
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 4x
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, // 5x
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 2, 0, 0, // 5x
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 6x
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0 // 7x
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 2, 0, 0, // 7x
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 8x
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 9x
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // ax
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // bx
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // cx
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // dx
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // ex
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 // fx
};
//------------------------------------------------------------------------
}
Lexer::~Lexer() {
- if (!curStr.isNone())
+ if (!curStr.isNone()) {
+ curStr.streamClose();
curStr.free();
- if (freeArray)
+ }
+ if (freeArray) {
delete streams;
+ }
}
int Lexer::getChar() {
c = EOF;
while (!curStr.isNone() && (c = curStr.streamGetChar()) == EOF) {
+ curStr.streamClose();
curStr.free();
++strPtr;
if (strPtr < streams->getLength()) {
}
int Lexer::lookChar() {
- int c;
-
- c = EOF;
- while (!curStr.isNone() && (c = curStr.streamLookChar()) == EOF) {
- curStr.free();
- ++strPtr;
- if (strPtr < streams->getLength()) {
- streams->get(strPtr, &curStr);
- curStr.streamReset();
- }
+ if (curStr.isNone()) {
+ return EOF;
}
- return c;
+ return curStr.streamLookChar();
}
Object *Lexer::getObj(Object *obj) {
// skip whitespace and comments
comment = gFalse;
while (1) {
- if ((c = getChar()) == EOF)
+ if ((c = getChar()) == EOF) {
return obj->initEOF();
+ }
if (comment) {
if (c == '\r' || c == '\n')
comment = gFalse;
} else if (c == '%') {
comment = gTrue;
- } else if (!isspace(c)) {
+ } else if (specialChars[c] != 1) {
break;
}
}
scale = 0.1;
while (1) {
c = lookChar();
- if (!isdigit(c))
+ if (!isdigit(c)) {
break;
+ }
getChar();
xf = xf + scale * (c - '0');
scale *= 0.1;
switch (c = getChar()) {
case EOF:
+#if 0
+ // This breaks some PDF files, e.g., ones from Photoshop.
case '\r':
case '\n':
+#endif
error(getPos(), "Unterminated string");
done = gTrue;
break;
break;
case '\r':
c = lookChar();
- if (c == '\n')
+ if (c == '\n') {
getChar();
+ }
break;
case '\n':
break;
case '/':
p = tokBuf;
n = 0;
- while ((c = lookChar()) != EOF && !(c < 128 && endOfNameChars[c])) {
+ while ((c = lookChar()) != EOF && !specialChars[c]) {
getChar();
if (c == '#') {
c2 = lookChar();
- if (c2 >= '0' && c2 <= '9')
+ if (c2 >= '0' && c2 <= '9') {
c = c2 - '0';
- else if (c2 >= 'A' && c2 <= 'F')
+ } else if (c2 >= 'A' && c2 <= 'F') {
c = c2 - 'A' + 10;
- else if (c2 >= 'a' && c2 <= 'f')
+ } else if (c2 >= 'a' && c2 <= 'f') {
c = c2 - 'a' + 10;
- else
+ } else {
goto notEscChar;
+ }
getChar();
c <<= 4;
c2 = getChar();
- if (c2 >= '0' && c2 <= '9')
+ if (c2 >= '0' && c2 <= '9') {
c += c2 - '0';
- else if (c2 >= 'A' && c2 <= 'F')
+ } else if (c2 >= 'A' && c2 <= 'F') {
c += c2 - 'A' + 10;
- else if (c2 >= 'a' && c2 <= 'f')
+ } else if (c2 >= 'a' && c2 <= 'f') {
c += c2 - 'a' + 10;
- else
+ } else {
error(getPos(), "Illegal digit in hex char in name");
+ }
}
notEscChar:
if (++n == tokBufSize) {
} else if (c == EOF) {
error(getPos(), "Unterminated hex string");
break;
- } else if (!isspace(c)) {
+ } else if (specialChars[c] != 1) {
c2 = c2 << 4;
if (c >= '0' && c <= '9')
c2 += c - '0';
p = tokBuf;
*p++ = c;
n = 1;
- while ((c = lookChar()) != EOF && !(c < 128 && endOfNameChars[c])) {
+ while ((c = lookChar()) != EOF && !specialChars[c]) {
getChar();
if (++n == tokBufSize) {
error(getPos(), "Command token too long");
*p++ = c;
}
*p = '\0';
- if (tokBuf[0] == 't' && !strcmp(tokBuf, "true"))
+ if (tokBuf[0] == 't' && !strcmp(tokBuf, "true")) {
obj->initBool(gTrue);
- else if (tokBuf[0] == 'f' && !strcmp(tokBuf, "false"))
+ } else if (tokBuf[0] == 'f' && !strcmp(tokBuf, "false")) {
obj->initBool(gFalse);
- else if (tokBuf[0] == 'n' && !strcmp(tokBuf, "null"))
+ } else if (tokBuf[0] == 'n' && !strcmp(tokBuf, "null")) {
obj->initNull();
- else
+ } else {
obj->initCmd(tokBuf);
+ }
break;
}
while (1) {
c = getChar();
- if (c == EOF || c == '\n')
+ if (c == EOF || c == '\n') {
return;
+ }
if (c == '\r') {
- if ((c = lookChar()) == '\n')
+ if ((c = lookChar()) == '\n') {
getChar();
+ }
return;
}
}
delete uri;
}
+//------------------------------------------------------------------------
+// LinkNamed
+//------------------------------------------------------------------------
+
+LinkNamed::LinkNamed(Object *nameObj) {
+ name = NULL;
+ if (nameObj->isName()) {
+ name = new GString(nameObj->getName());
+ }
+}
+
+LinkNamed::~LinkNamed() {
+ if (name) {
+ delete name;
+ }
+}
+
//------------------------------------------------------------------------
// LinkUnknown
//------------------------------------------------------------------------
-LinkUnknown::LinkUnknown(char *action1) {
+LinkUnknown::LinkUnknown(const char *action1) {
action = new GString(action1);
}
action = new LinkURI(&obj3, baseURI);
obj3.free();
+ // Named action
+ } else if (obj2.isName("Named")) {
+ obj1.dictLookup("N", &obj3);
+ action = new LinkNamed(&obj3);
+ obj3.free();
+
// unknown action
} else if (obj2.isName()) {
action = new LinkUnknown(obj2.getName());
actionGoToR, // go to destination in new file
actionLaunch, // launch app (or open document)
actionURI, // URI
+ actionNamed, // named action
actionUnknown // anything else
};
GString *uri; // the URI
};
+//------------------------------------------------------------------------
+// LinkNamed
+//------------------------------------------------------------------------
+
+class LinkNamed: public LinkAction {
+public:
+
+ // Build a LinkNamed given the action name.
+ LinkNamed(Object *nameObj);
+
+ virtual ~LinkNamed();
+
+ virtual GBool isOk() { return name != NULL; }
+
+ virtual LinkActionKind getKind() { return actionNamed; }
+ GString *getName() { return name; }
+
+private:
+
+ GString *name;
+};
+
//------------------------------------------------------------------------
// LinkUnknown
//------------------------------------------------------------------------
public:
// Build a LinkUnknown with the specified action type.
- LinkUnknown(char *action1);
+ LinkUnknown(const char *action1);
// Destructor.
virtual ~LinkUnknown();
// Object
//------------------------------------------------------------------------
-char *objTypeNames[numObjTypes] = {
+const char *objTypeNames[numObjTypes] = {
"boolean",
"integer",
"real",
delete string;
break;
case objName:
- gfree(name);
+ gfree((void *)name);
break;
case objArray:
if (!array->decRef()) {
}
break;
case objCmd:
- gfree(cmd);
+ gfree((void *)cmd);
break;
default:
break;
type = objNone;
}
-char *Object::getTypeName() {
+const char *Object::getTypeName() {
return objTypeNames[type];
}
fprintf(f, " %-20s: %6d\n", objTypeNames[i], numAlloc[i]);
}
}
+#else
+ (void)f;
#endif
}
{ initObj(objReal); real = real1; return this; }
Object *initString(GString *string1)
{ initObj(objString); string = string1; return this; }
- Object *initName(char *name1)
+ Object *initName(const char *name1)
{ initObj(objName); name = copyString(name1); return this; }
Object *initNull()
{ initObj(objNull); return this; }
Object *initStream(Stream *stream1);
Object *initRef(int num1, int gen1)
{ initObj(objRef); ref.num = num1; ref.gen = gen1; return this; }
- Object *initCmd(char *cmd1)
+ Object *initCmd(const char *cmd1)
{ initObj(objCmd); cmd = copyString(cmd1); return this; }
Object *initError()
{ initObj(objError); return this; }
GBool isNone() { return type == objNone; }
// Special type checking.
- GBool isName(char *name1)
+ GBool isName(const char *name1)
{ return type == objName && !strcmp(name, name1); }
- GBool isDict(char *dictType);
- GBool isStream(char *dictType);
- GBool isCmd(char *cmd1)
+ GBool isDict(const char *dictType);
+ GBool isStream(const char *dictType);
+ GBool isCmd(const char *cmd1)
{ return type == objCmd && !strcmp(cmd, cmd1); }
// Accessors. NB: these assume object is of correct type.
double getReal() { return real; }
double getNum() { return type == objInt ? (double)intg : real; }
GString *getString() { return string; }
- char *getName() { return name; }
+ const char *getName() { return name; }
Array *getArray() { return array; }
Dict *getDict() { return dict; }
Stream *getStream() { return stream; }
// Dict accessors.
int dictGetLength();
- void dictAdd(char *key, Object *val);
- GBool dictIs(char *dictType);
- Object *dictLookup(char *key, Object *obj);
- Object *dictLookupNF(char *key, Object *obj);
- char *dictGetKey(int i);
+ void dictAdd(const char *key, Object *val);
+ GBool dictIs(const char *dictType);
+ Object *dictLookup(const char *key, Object *obj);
+ Object *dictLookupNF(const char *key, Object *obj);
+ const char *dictGetKey(int i);
Object *dictGetVal(int i, Object *obj);
Object *dictGetValNF(int i, Object *obj);
// Stream accessors.
- GBool streamIs(char *dictType);
+ GBool streamIs(const char *dictType);
void streamReset();
+ void streamClose();
int streamGetChar();
int streamLookChar();
char *streamGetLine(char *buf, int size);
Dict *streamGetDict();
// Output.
- char *getTypeName();
+ const char *getTypeName();
void print(FILE *f = stdout);
// Memory testing.
int intg; // integer
double real; // real
GString *string; // string
- char *name; // name
+ const char *name; // name
Array *array; // array
Dict *dict; // dictionary
Stream *stream; // stream
Ref ref; // indirect reference
- char *cmd; // command
+ const char *cmd; // command
};
#ifdef DEBUG_MEM
inline int Object::dictGetLength()
{ return dict->getLength(); }
-inline void Object::dictAdd(char *key, Object *val)
+inline void Object::dictAdd(const char *key, Object *val)
{ dict->add(key, val); }
-inline GBool Object::dictIs(char *dictType)
+inline GBool Object::dictIs(const char *dictType)
{ return dict->is(dictType); }
-inline GBool Object::isDict(char *dictType)
+inline GBool Object::isDict(const char *dictType)
{ return type == objDict && dictIs(dictType); }
-inline Object *Object::dictLookup(char *key, Object *obj)
+inline Object *Object::dictLookup(const char *key, Object *obj)
{ return dict->lookup(key, obj); }
-inline Object *Object::dictLookupNF(char *key, Object *obj)
+inline Object *Object::dictLookupNF(const char *key, Object *obj)
{ return dict->lookupNF(key, obj); }
-inline char *Object::dictGetKey(int i)
+inline const char *Object::dictGetKey(int i)
{ return dict->getKey(i); }
inline Object *Object::dictGetVal(int i, Object *obj)
#include "Stream.h"
-inline GBool Object::streamIs(char *dictType)
+inline GBool Object::streamIs(const char *dictType)
{ return stream->getDict()->is(dictType); }
-inline GBool Object::isStream(char *dictType)
+inline GBool Object::isStream(const char *dictType)
{ return type == objStream && streamIs(dictType); }
inline void Object::streamReset()
{ stream->reset(); }
+inline void Object::streamClose()
+ { stream->close(); }
+
inline int Object::streamGetChar()
{ return stream->getChar(); }
updateFont(state);
}
-void OutputDev::drawImageMask(GfxState *state, Stream *str,
+void OutputDev::drawImageMask(GfxState *state, Object *ref, Stream *str,
int width, int height, GBool invert,
GBool inlineImg) {
int i, j;
+ (void)state;
+ (void)invert;
+
if (inlineImg) {
str->reset();
j = height * ((width + 7) / 8);
}
}
-void OutputDev::drawImage(GfxState *state, Stream *str, int width,
- int height, GfxImageColorMap *colorMap,
+void OutputDev::drawImage(GfxState *state, Object *ref, Stream *str,
+ int width, int height, GfxImageColorMap *colorMap,
GBool inlineImg) {
int i, j;
+ (void)state;
+
if (inlineImg) {
str->reset();
j = height * ((width * colorMap->getNumPixelComps() *
virtual void setDefaultCTM(double *ctm1);
// Start a page.
- virtual void startPage(int pageNum, GfxState *state) {}
+ virtual void startPage(int, GfxState *) {}
// End a page.
virtual void endPage() {}
virtual void cvtUserToDev(double ux, double uy, int *dx, int *dy);
//----- link borders
- virtual void drawLink(Link *link, Catalog *catalog) {}
+ virtual void drawLink(Link *, Catalog *) {}
//----- save/restore graphics state
- virtual void saveState(GfxState *state) {}
- virtual void restoreState(GfxState *state) {}
+ virtual void saveState(GfxState *) {}
+ virtual void restoreState(GfxState *) {}
//----- update graphics state
virtual void updateAll(GfxState *state);
- virtual void updateCTM(GfxState *state, double m11, double m12,
- double m21, double m22, double m31, double m32) {}
- virtual void updateLineDash(GfxState *state) {}
- virtual void updateFlatness(GfxState *state) {}
- virtual void updateLineJoin(GfxState *state) {}
- virtual void updateLineCap(GfxState *state) {}
- virtual void updateMiterLimit(GfxState *state) {}
- virtual void updateLineWidth(GfxState *state) {}
- virtual void updateFillColor(GfxState *state) {}
- virtual void updateStrokeColor(GfxState *state) {}
-
- //----- update text state
- virtual void updateFont(GfxState *state) {}
- virtual void updateTextMat(GfxState *state) {}
- virtual void updateCharSpace(GfxState *state) {}
- virtual void updateRender(GfxState *state) {}
- virtual void updateRise(GfxState *state) {}
- virtual void updateWordSpace(GfxState *state) {}
- virtual void updateHorizScaling(GfxState *state) {}
- virtual void updateTextPos(GfxState *state) {}
- virtual void updateTextShift(GfxState *state, double shift) {}
+ virtual void updateCTM(GfxState *, double, double,
+ double, double, double, double) {}
+ virtual void updateLineDash(GfxState *) {}
+ virtual void updateFlatness(GfxState *) {}
+ virtual void updateLineJoin(GfxState *) {}
+ virtual void updateLineCap(GfxState *) {}
+ virtual void updateMiterLimit(GfxState *) {}
+ virtual void updateLineWidth(GfxState *) {}
+ virtual void updateFillColor(GfxState *) {}
+ virtual void updateStrokeColor(GfxState *) {}
+ virtual void updateFillOpacity(GfxState *) {}
+ virtual void updateStrokeOpacity(GfxState *) {}
+
+ //----- update text
+ virtual void updateFont(GfxState *) {}
+ virtual void updateTextMat(GfxState *) {}
+ virtual void updateCharSpace(GfxState *) {}
+ virtual void updateRender(GfxState *) {}
+ virtual void updateRise(GfxState *) {}
+ virtual void updateWordSpace(GfxState *) {}
+ virtual void updateHorizScaling(GfxState *) {}
+ virtual void updateTextPos(GfxState *) {}
+ virtual void updateTextShift(GfxState *, double) {}
//----- path painting
- virtual void stroke(GfxState *state) {}
- virtual void fill(GfxState *state) {}
- virtual void eoFill(GfxState *state) {}
+ virtual void stroke(GfxState *) {}
+ virtual void fill(GfxState *) {}
+ virtual void eoFill(GfxState *) {}
//----- path clipping
- virtual void clip(GfxState *state) {}
- virtual void eoClip(GfxState *state) {}
+ virtual void clip(GfxState *) {}
+ virtual void eoClip(GfxState *) {}
//----- text drawing
- virtual void beginString(GfxState *state, GString *s) {}
- virtual void endString(GfxState *state) {}
- virtual void drawChar(GfxState *state, double x, double y,
- double dx, double dy, Guchar c) {}
- virtual void drawChar16(GfxState *state, double x, double y,
- double dx, double dy, int c) {}
- virtual void drawString(GfxState *state, GString *s) {}
- virtual void drawString16(GfxState *state, GString *s) {}
+ virtual void beginString(GfxState *, GString *) {}
+ virtual void endString(GfxState *) {}
+ virtual void drawChar(GfxState *, double, double,
+ double, double, Guchar) {}
+ virtual void drawChar16(GfxState *, double, double,
+ double, double, int) {}
+ virtual void drawString(GfxState *, GString *) {}
+ virtual void drawString16(GfxState *, GString *) {}
//----- image drawing
- virtual void drawImageMask(GfxState *state, Stream *str,
+ virtual void drawImageMask(GfxState *state, Object *ref, Stream *str,
int width, int height, GBool invert,
GBool inlineImg);
- virtual void drawImage(GfxState *state, Stream *str, int width,
- int height, GfxImageColorMap *colorMap,
+ virtual void drawImage(GfxState *state, Object *ref, Stream *str,
+ int width, int height, GfxImageColorMap *colorMap,
GBool inlineImg);
#if OPI_SUPPORT
ok = setup(userPassword);
}
-PDFDoc::PDFDoc(BaseStream *str, GString *userPassword) {
+PDFDoc::PDFDoc(BaseStream *nstr, GString *userPassword) {
ok = gFalse;
fileName = NULL;
file = NULL;
- this->str = str;
+ str = nstr;
xref = NULL;
catalog = NULL;
links = NULL;
}
}
-void PDFDoc::displayPage(OutputDev *out, int page, int zoom, int rotate,
- GBool doLinks) {
+void PDFDoc::displayPage(OutputDev *out, int page, double zoom,
+ int rotate, GBool doLinks) {
Page *p;
if (printCommands) {
while ((c = str->getChar()) != EOF) {
fputc(c, f);
}
+ str->close();
fclose(f);
return gTrue;
}
int getNumPages() { return catalog->getNumPages(); }
// Display a page.
- void displayPage(OutputDev *out, int page, int zoom, int rotate,
- GBool doLinks);
+ void displayPage(OutputDev *out, int page, double zoom,
+ int rotate, GBool doLinks);
// Display a range of pages.
void displayPages(OutputDev *out, int firstPage, int lastPage,
#endif
#include <stdio.h>
+#include <stdlib.h>
#include <stddef.h>
#include <stdarg.h>
#include <signal.h>
// Generate Level 1 PostScript?
GBool psOutLevel1 = gFalse;
+// Generate Level 1 separable PostScript?
+GBool psOutLevel1Sep = gFalse;
+
// Generate Encapsulated PostScript?
GBool psOutEPS = gFalse;
GBool psOutOPI = gFalse;
#endif
-int paperWidth = 612;
-int paperHeight = 792;
+int paperWidth = defPaperWidth;
+int paperHeight = defPaperHeight;
//------------------------------------------------------------------------
// PostScript prolog and setup
//------------------------------------------------------------------------
-static char *prolog[] = {
+static const char *prolog[] = {
"/xpdf 75 dict def xpdf begin",
"% PDF special state",
"/pdfDictSize 14 def",
-#if 0 // Not used for CUPS - the pstops filter handles this...
"/pdfSetup {",
" 2 array astore",
" /setpagedevice where {",
" pop",
" } ifelse",
"} def",
-#endif // 0
"/pdfStartPage {",
" pdfDictSize dict begin",
" /pdfFill [0] def",
" /pdfHorizScaling 1 def",
"} def",
"/pdfEndPage { end } def",
- "/sCol { pdfLastStroke not {",
- " pdfStroke aload length",
- " 1 eq { setgray } { setrgbcolor} ifelse",
- " /pdfLastStroke true def /pdfLastFill false def",
- " } if } def",
- "/fCol { pdfLastFill not {",
- " pdfFill aload length",
- " 1 eq { setgray } { setrgbcolor } ifelse",
- " /pdfLastFill true def /pdfLastStroke false def",
- " } if } def",
+ "/sCol {",
+ " pdfLastStroke not {",
+ " pdfStroke aload length",
+ " dup 1 eq { pop setgray }",
+ " { 3 eq { setrgbcolor } { setcmykcolor } ifelse } ifelse",
+ " /pdfLastStroke true def /pdfLastFill false def",
+ " } if",
+ "} def",
+ "/fCol {",
+ " pdfLastFill not {",
+ " pdfFill aload length",
+ " dup 1 eq { pop setgray }",
+ " { 3 eq { setrgbcolor } { setcmykcolor } ifelse } ifelse",
+ " /pdfLastFill true def /pdfLastStroke false def",
+ " } if",
+ "} def",
"% build a font",
"/pdfMakeFont {",
" 4 3 roll findfont",
"/w { setlinewidth } def",
"% color operators",
"/g { dup 1 array astore /pdfFill exch def setgray",
- " /pdfLastFill true def /pdfLastStroke false def } def",
+ " /pdfLastFill true def /pdfLastStroke false def } def",
"/G { dup 1 array astore /pdfStroke exch def setgray",
" /pdfLastStroke true def /pdfLastFill false def } def",
"/rg { 3 copy 3 array astore /pdfFill exch def setrgbcolor",
- " /pdfLastFill true def /pdfLastStroke false def } def",
+ " /pdfLastFill true def /pdfLastStroke false def } def",
"/RG { 3 copy 3 array astore /pdfStroke exch def setrgbcolor",
+ " /pdfLastStroke true def /pdfLastFill false def } def",
+ "/k { 4 copy 4 array astore /pdfFill exch def setcmykcolor",
+ " /pdfLastFill true def /pdfLastStroke false def } def",
+ "/K { 4 copy 4 array astore /pdfStroke exch def setcmykcolor",
" /pdfLastStroke true def /pdfLastFill false def } def",
"% path segment operators",
"/m { moveto } def",
" sub 1 index length dup 0 ne { div } { pop pop 0 } ifelse",
" pdfWordSpacing 0 pdfTextMat dtransform 32",
" 4 3 roll pdfCharSpacing add 0 pdfTextMat dtransform",
+#if 0 /* temporary fix until we can figure out why the width is wrong */
" 6 5 roll awidthshow",
+#else
+ " 6 5 roll show pop pop pop pop pop",
+#endif /* 0 */
" 0 pdfTextRise neg pdfTextMat dtransform rmoveto } def",
"/TJm { pdfFontSize 0.001 mul mul neg 0",
" pdfTextMat dtransform rmoveto } def",
" /pdfImBuf1 4 index string def",
" { currentfile pdfImBuf1 readhexstring pop } image",
"} def",
+ "/pdfIm1Sep {",
+ " /pdfImBuf1 4 index string def",
+ " /pdfImBuf2 4 index string def",
+ " /pdfImBuf3 4 index string def",
+ " /pdfImBuf4 4 index string def",
+ " { currentfile pdfImBuf1 readhexstring pop }",
+ " { currentfile pdfImBuf2 readhexstring pop }",
+ " { currentfile pdfImBuf3 readhexstring pop }",
+ " { currentfile pdfImBuf4 readhexstring pop }",
+ " true 4 colorimage",
+ "} def",
"/pdfImM1 {",
" /pdfImBuf1 4 index 7 add 8 idiv string def",
" { currentfile pdfImBuf1 readhexstring pop } imagemask",
//------------------------------------------------------------------------
struct PSFont {
- char *name; // PDF name
- char *psName; // PostScript name
+ const char *name; // PDF name
+ const char *psName; // PostScript name
};
struct PSSubstFont {
- char *psName; // PostScript name
+ const char *psName; // PostScript name
double mWidth; // width of 'm' character
};
// PSOutputDev
//------------------------------------------------------------------------
-PSOutputDev::PSOutputDev(char *fileName, Catalog *catalog,
+PSOutputDev::PSOutputDev(const char *fileName, Catalog *catalog,
int firstPage, int lastPage,
GBool embedType11, GBool doForm1) {
Page *page;
Dict *resDict;
FormWidgets *formWidgets;
- char **p;
+ const char **p;
int pg;
Object obj1, obj2;
int i;
fileType = psPipe;
#ifdef HAVE_POPEN
#ifndef WIN32
- signal(SIGPIPE, (void (*)(int))SIG_IGN);
+ signal(SIGPIPE, SIG_IGN);
#endif
if (!(f = popen(fileName + 1, "w"))) {
error(-1, "Couldn't run print command '%s'", fileName);
if (doForm) {
writePS("%%!PS-Adobe-3.0 Resource-Form\n");
writePS("%%%%Creator: xpdf/pdftops %s\n", xpdfVersion);
- writePS("%%%%LanguageLevel: %d\n", psOutLevel1 ? 1 : 2);
+ writePS("%%%%LanguageLevel: %d\n",
+ (psOutLevel1 || psOutLevel1Sep) ? 1 : 2);
+ if (psOutLevel1Sep) {
+ writePS("%%%%DocumentProcessColors: Cyan Magenta Yellow Black\n");
+ }
writePS("%%%%EndComments\n");
+ page = catalog->getPage(firstPage);
+ writePS("32 dict dup begin\n");
+ writePS("/BBox [%d %d %d %d] def\n",
+ (int)page->getX1(), (int)page->getY1(),
+ (int)page->getX2(), (int)page->getY2());
+ writePS("/FormType 1 def\n");
+ writePS("/Matrix [1 0 0 1 0 0] def\n");
} else if (psOutEPS) {
writePS("%%!PS-Adobe-3.0 EPSF-3.0\n");
writePS("%%%%Creator: xpdf/pdftops %s\n", xpdfVersion);
- writePS("%%%%LanguageLevel: %d\n", psOutLevel1 ? 1 : 2);
+ writePS("%%%%LanguageLevel: %d\n",
+ (psOutLevel1 || psOutLevel1Sep) ? 1 : 2);
+ if (psOutLevel1Sep) {
+ writePS("%%%%DocumentProcessColors: Cyan Magenta Yellow Black\n");
+ }
page = catalog->getPage(firstPage);
writePS("%%%%BoundingBox: %d %d %d %d\n",
(int)floor(page->getX1()), (int)floor(page->getY1()),
page->getX1(), page->getY1(),
page->getX2(), page->getY2());
}
- writePS("%%%%DocumentSuppliedResources:\n");
- writePS("%%%%+ font: (atend)\n");
+ writePS("%%%%DocumentSuppliedResources: (atend)\n");
writePS("%%%%EndComments\n");
} else {
writePS("%%!PS-Adobe-3.0\n");
writePS("%%%%Creator: xpdf/pdftops %s\n", xpdfVersion);
- writePS("%%%%LanguageLevel: %d\n", psOutLevel1 ? 1 : 2);
+ writePS("%%%%LanguageLevel: %d\n",
+ (psOutLevel1 || psOutLevel1Sep) ? 1 : 2);
+ if (psOutLevel1Sep) {
+ writePS("%%%%DocumentProcessColors: Cyan Magenta Yellow Black\n");
+ }
writePS("%%%%DocumentMedia: plain %d %d 0 () ()\n",
paperWidth, paperHeight);
writePS("%%%%Pages: %d\n", lastPage - firstPage + 1);
}
// write prolog
- if (!doForm)
+ if (!doForm) {
writePS("%%%%BeginProlog\n");
- writePS("%%%%BeginResource: xpdf %s\n", xpdfVersion);
- for (p = prolog; *p; ++p)
+ }
+ writePS("%%%%BeginResource: procset xpdf %s 0\n", xpdfVersion);
+ for (p = prolog; *p; ++p) {
writePS("%s\n", *p);
+ }
writePS("%%%%EndResource\n");
- if (!doForm)
+ if (!doForm) {
writePS("%%%%EndProlog\n");
+ }
- // set up fonts
- if (!doForm)
+ // set up fonts and images
+ type3Warning = gFalse;
+ if (doForm) {
+ // swap the form and xpdf dicts
+ writePS("xpdf end begin dup begin\n");
+ } else {
writePS("%%%%BeginSetup\n");
- writePS("xpdf begin\n");
+ writePS("xpdf begin\n");
+ }
for (pg = firstPage; pg <= lastPage; ++pg) {
page = catalog->getPage(pg);
if ((resDict = page->getResourceDict())) {
- setupFonts(resDict);
+ setupResources(resDict);
}
formWidgets = new FormWidgets(page->getAnnots(&obj1));
obj1.free();
if (formWidgets->getWidget(i)->getAppearance(&obj1)->isStream()) {
obj1.streamGetDict()->lookup("Resources", &obj2);
if (obj2.isDict()) {
- setupFonts(obj2.getDict());
+ setupResources(obj2.getDict());
}
obj2.free();
}
}
delete formWidgets;
}
- if (doForm) {
- writePS("end\n");
- } else {
+ if (!doForm) {
#if OPI_SUPPORT
if (psOutOPI) {
writePS("/opiMatrix matrix currentmatrix def\n");
}
#endif
if (!psOutEPS) {
-// pdfSetup not used for CUPS filter...
-// writePS("%d %d pdfSetup\n", paperWidth, paperHeight);
+ if (!getenv("PPD") || !getenv("SOFTWARE")) {
+ // pdfSetup not used for CUPS filter...
+ writePS("%d %d pdfSetup\n", paperWidth, paperHeight);
+ }
}
writePS("%%%%EndSetup\n");
}
- // write form header
- if (doForm) {
- page = catalog->getPage(firstPage);
- writePS("4 dict dup begin\n");
- writePS("/BBox [%d %d %d %d] def\n",
- (int)page->getX1(), (int)page->getY1(),
- (int)page->getX2(), (int)page->getY2());
- writePS("/FormType 1 def\n");
- writePS("/Matrix [1 0 0 1 0 0] def\n");
- }
-
// initialize sequential page number
seqPage = 1;
if (f) {
if (doForm) {
- writePS("end\n");
writePS("/Foo exch /Form defineresource pop\n");
} else if (psOutEPS) {
writePS("%%%%Trailer\n");
else if (fileType == psPipe) {
pclose(f);
#ifndef WIN32
- signal(SIGPIPE, (void (*)(int))SIG_DFL);
+ signal(SIGPIPE, SIG_DFL);
#endif
}
#endif
}
}
-void PSOutputDev::setupFonts(Dict *resDict) {
- Object fontDict, xObjDict, xObj, resObj;
- GfxFontDict *gfxFontDict;
- GfxFont *font;
+void PSOutputDev::setupResources(Dict *resDict) {
+ Object xObjDict, xObj, resObj;
int i;
- resDict->lookup("Font", &fontDict);
- if (fontDict.isDict()) {
- gfxFontDict = new GfxFontDict(fontDict.getDict());
- for (i = 0; i < gfxFontDict->getNumFonts(); ++i) {
- font = gfxFontDict->getFont(i);
- setupFont(font);
- }
- delete gfxFontDict;
- }
- fontDict.free();
+ setupFonts(resDict);
+ setupImages(resDict);
resDict->lookup("XObject", &xObjDict);
if (xObjDict.isDict()) {
xObjDict.dictGetVal(i, &xObj);
if (xObj.isStream()) {
xObj.streamGetDict()->lookup("Resources", &resObj);
- if (resObj.isDict())
- setupFonts(resObj.getDict());
+ if (resObj.isDict()) {
+ setupResources(resObj.getDict());
+ }
resObj.free();
}
xObj.free();
xObjDict.free();
}
+void PSOutputDev::setupFonts(Dict *resDict) {
+ Object fontDict;
+ GfxFontDict *gfxFontDict;
+ GfxFont *font;
+ int i;
+
+ resDict->lookup("Font", &fontDict);
+ if (fontDict.isDict()) {
+ gfxFontDict = new GfxFontDict(fontDict.getDict());
+ for (i = 0; i < gfxFontDict->getNumFonts(); ++i) {
+ font = gfxFontDict->getFont(i);
+ setupFont(font);
+ }
+ delete gfxFontDict;
+ }
+ fontDict.free();
+}
+
void PSOutputDev::setupFont(GfxFont *font) {
Ref fontFileID;
GString *name;
- char *psName;
- char *charName;
+ const char *psName;
+ const char *charName;
double xs, ys;
GBool do16Bit;
int code;
// do font substitution
} else {
+ if (!type3Warning && font->getType() == fontType3) {
+ error(-1, "This document uses Type 3 fonts - some text may not be correctly printed");
+ type3Warning = gTrue;
+ }
name = font->getName();
psName = NULL;
if (name) {
}
}
-void PSOutputDev::setupEmbeddedType1Font(Ref *id, char *psName) {
+void PSOutputDev::setupEmbeddedType1Font(Ref *id, const char *psName) {
static char hexChar[17] = "0123456789abcdef";
Object refObj, strObj, obj1, obj2;
Dict *dict;
}
err1:
+ strObj.streamClose();
strObj.free();
}
//~ This doesn't handle .pfb files or binary eexec data (which only
//~ happens in pfb files?).
-void PSOutputDev::setupEmbeddedType1Font(GString *fileName, char *psName) {
+void PSOutputDev::setupEmbeddedType1Font(GString *fileName, const char *psName) {
FILE *fontFile;
int c;
int i;
}
void PSOutputDev::setupEmbeddedType1CFont(GfxFont *font, Ref *id,
- char *psName) {
- char *fontBuf;
+ const char *psName) {
+ const char *fontBuf;
int fontLen;
Type1CFontConverter *cvt;
int i;
cvt = new Type1CFontConverter(fontBuf, fontLen, f);
cvt->convert();
delete cvt;
- gfree(fontBuf);
+ gfree((void *)fontBuf);
// ending comment
if (psOutEPS) {
}
}
+void PSOutputDev::setupImages(Dict *resDict) {
+ Object xObjDict, xObj, xObjRef, subtypeObj;
+ int i;
+
+ if (!doForm) {
+ return;
+ }
+
+ resDict->lookup("XObject", &xObjDict);
+ if (xObjDict.isDict()) {
+ for (i = 0; i < xObjDict.dictGetLength(); ++i) {
+ xObjDict.dictGetValNF(i, &xObjRef);
+ xObjDict.dictGetVal(i, &xObj);
+ if (xObj.isStream()) {
+ xObj.streamGetDict()->lookup("Subtype", &subtypeObj);
+ if (subtypeObj.isName("Image")) {
+ if (xObjRef.isRef()) {
+ setupImage(xObjRef.getRef(), xObj.getStream());
+ } else {
+ error(-1, "Image in resource dict is not an indirect reference");
+ }
+ }
+ subtypeObj.free();
+ }
+ xObj.free();
+ xObjRef.free();
+ }
+ }
+ xObjDict.free();
+}
+
+void PSOutputDev::setupImage(Ref id, Stream *str) {
+ int c;
+ int size, line, col, i;
+
+ // construct an encoder stream
+ str = new ASCII85Encoder(str);
+
+ // compute image data size
+ str->reset();
+ col = size = 0;
+ do {
+ do {
+ c = str->getChar();
+ } while (c == '\n' || c == '\r');
+ if (c == '~' || c == EOF) {
+ break;
+ }
+ if (c == 'z') {
+ ++col;
+ } else {
+ ++col;
+ for (i = 1; i <= 4; ++i) {
+ do {
+ c = str->getChar();
+ } while (c == '\n' || c == '\r');
+ if (c == '~' || c == EOF) {
+ break;
+ }
+ ++col;
+ }
+ }
+ if (col > 225) {
+ ++size;
+ col = 0;
+ }
+ } while (c != '~' && c != EOF);
+ ++size;
+ writePS("%d array dup /ImData_%d_%d exch def\n", size, id.num, id.gen);
+
+ // write the data into the array
+ str->reset();
+ line = col = 0;
+ writePS("dup 0 <~");
+ do {
+ do {
+ c = str->getChar();
+ } while (c == '\n' || c == '\r');
+ if (c == '~' || c == EOF) {
+ break;
+ }
+ if (c == 'z') {
+ fputc(c, f);
+ ++col;
+ } else {
+ fputc(c, f);
+ ++col;
+ for (i = 1; i <= 4; ++i) {
+ do {
+ c = str->getChar();
+ } while (c == '\n' || c == '\r');
+ if (c == '~' || c == EOF) {
+ break;
+ }
+ fputc(c, f);
+ ++col;
+ }
+ }
+ // each line is: "dup nnnnn <~...data...~> put<eol>"
+ // so max data length = 255 - 20 = 235
+ // chunks are 1 or 4 bytes each, so we have to stop at 232
+ // but make it 225 just to be safe
+ if (col > 225) {
+ writePS("~> put\n");
+ ++line;
+ writePS("dup %d <~", line);
+ col = 0;
+ }
+ } while (c != '~' && c != EOF);
+ writePS("~> put\n");
+ writePS("pop\n");
+
+ delete str;
+}
+
void PSOutputDev::startPage(int pageNum, GfxState *state) {
int x1, y1, x2, y2, width, height, t;
writePS("pdfEndPage\n");
writePS("end end\n");
writePS("} def\n");
+ writePS("end end\n");
} else {
writePS("showpage\n");
writePS("%%%%PageTrailer\n");
}
void PSOutputDev::saveState(GfxState *state) {
+ (void)state;
+
writePS("q\n");
}
void PSOutputDev::restoreState(GfxState *state) {
+ (void)state;
+
writePS("Q\n");
}
void PSOutputDev::updateCTM(GfxState *state, double m11, double m12,
double m21, double m22, double m31, double m32) {
+ (void)state;
+
writePS("[%g %g %g %g %g %g] cm\n", m11, m12, m21, m22, m31, m32);
}
}
void PSOutputDev::updateFillColor(GfxState *state) {
- GfxColor *color;
- double r, g, b;
-
- color = state->getFillColor();
- r = color->getR();
- g = color->getG();
- b = color->getB();
- if (r == g && g == b)
- writePS("%g g\n", r);
- else
- writePS("%g %g %g rg\n", r, g, b);
+ GfxRGB rgb;
+ GfxCMYK cmyk;
+
+ if (psOutLevel1Sep) {
+ state->getFillCMYK(&cmyk);
+ writePS("%g %g %g %g k\n", cmyk.c, cmyk.m, cmyk.y, cmyk.k);
+ } else {
+ state->getFillRGB(&rgb);
+ if (rgb.r == rgb.g && rgb.g == rgb.b) {
+ writePS("%g g\n", rgb.r);
+ } else {
+ writePS("%g %g %g rg\n", rgb.r, rgb.g, rgb.b);
+ }
+ }
}
void PSOutputDev::updateStrokeColor(GfxState *state) {
- GfxColor *color;
- double r, g, b;
-
- color = state->getStrokeColor();
- r = color->getR();
- g = color->getG();
- b = color->getB();
- if (r == g && g == b)
- writePS("%g G\n", r);
- else
- writePS("%g %g %g RG\n", r, g, b);
+ GfxRGB rgb;
+ GfxCMYK cmyk;
+
+ if (psOutLevel1Sep) {
+ state->getStrokeCMYK(&cmyk);
+ writePS("%g %g %g %g K\n", cmyk.c, cmyk.m, cmyk.y, cmyk.k);
+ } else {
+ state->getStrokeRGB(&rgb);
+ if (rgb.r == rgb.g && rgb.g == rgb.b) {
+ writePS("%g G\n", rgb.r);
+ } else {
+ writePS("%g %g %g RG\n", rgb.r, rgb.g, rgb.b);
+ }
+ }
}
void PSOutputDev::updateFont(GfxState *state) {
}
void PSOutputDev::updateTextShift(GfxState *state, double shift) {
+ (void)state;
+
writePS("%g TJm\n", shift);
}
}
void PSOutputDev::drawString16(GfxState *state, GString *s) {
+#if defined(JAPANESE_SUPPORT) || defined(CHINESE_SUPPORT)
int c1, c2;
double w;
int i;
+#else
+ (void)s;
+#endif /* JAPANESE_SUPPORT || CHINESE_SUPPORT */
// check for invisible text -- this is used by Acrobat Capture
if ((state->getRender() & 3) == 3)
case font16AdobeGB12:
break;
+
+ case font16AdobeCNS13:
+ break;
}
}
-void PSOutputDev::drawImageMask(GfxState *state, Stream *str,
+void PSOutputDev::drawImageMask(GfxState *state, Object *ref, Stream *str,
int width, int height, GBool invert,
GBool inlineImg) {
int len;
+ (void)state;
+
len = height * ((width + 7) / 8);
- if (psOutLevel1)
+ if (psOutLevel1 || psOutLevel1Sep) {
doImageL1(NULL, invert, inlineImg, str, width, height, len);
- else
- doImage(NULL, invert, inlineImg, str, width, height, len);
+ } else {
+ doImageL2(ref, NULL, invert, inlineImg, str, width, height, len);
+ }
}
-void PSOutputDev::drawImage(GfxState *state, Stream *str, int width,
- int height, GfxImageColorMap *colorMap,
+void PSOutputDev::drawImage(GfxState *state, Object *ref, Stream *str,
+ int width, int height, GfxImageColorMap *colorMap,
GBool inlineImg) {
int len;
+ (void)state;
+
len = height * ((width * colorMap->getNumPixelComps() *
colorMap->getBits() + 7) / 8);
- if (psOutLevel1)
+ if (psOutLevel1) {
doImageL1(colorMap, gFalse, inlineImg, str, width, height, len);
- else
- doImage(colorMap, gFalse, inlineImg, str, width, height, len);
+ } else if (psOutLevel1Sep) {
+ //~ handle indexed, separation, ... color spaces
+ doImageL1Sep(colorMap, gFalse, inlineImg, str, width, height, len);
+ } else {
+ doImageL2(ref, colorMap, gFalse, inlineImg, str, width, height, len);
+ }
}
void PSOutputDev::doImageL1(GfxImageColorMap *colorMap,
GBool invert, GBool inlineImg,
Stream *str, int width, int height, int len) {
ImageStream *imgStr;
- Guchar pixBuf[4];
- GfxColor color;
+ Guchar pixBuf[gfxColorMaxComps];
+ double gray;
int x, y, i;
+ (void)inlineImg;
+ (void)len;
+
// width, height, matrix, bits per component
if (colorMap) {
writePS("%d %d 8 [%d 0 0 %d 0 %d] pdfIm1\n",
// write the line
for (x = 0; x < width; ++x) {
imgStr->getPixel(pixBuf);
- colorMap->getColor(pixBuf, &color);
- fprintf(f, "%02x", (int)(color.getGray() * 255 + 0.5));
+ colorMap->getGray(pixBuf, &gray);
+ fprintf(f, "%02x", (int)(gray * 255 + 0.5));
if (++i == 32) {
fputc('\n', f);
i = 0;
}
}
-void PSOutputDev::doImage(GfxImageColorMap *colorMap,
- GBool invert, GBool inlineImg,
- Stream *str, int width, int height, int len) {
- GfxColorSpace *colorSpace;
- LabParams *labParams;
+void PSOutputDev::doImageL1Sep(GfxImageColorMap *colorMap,
+ GBool invert, GBool inlineImg,
+ Stream *str, int width, int height, int len) {
+ ImageStream *imgStr;
+ Guchar *lineBuf;
+ Guchar pixBuf[gfxColorMaxComps];
+ GfxCMYK cmyk;
+ int x, y, i, comp;
+
+ // width, height, matrix, bits per component
+ writePS("%d %d 8 [%d 0 0 %d 0 %d] pdfIm1Sep\n",
+ width, height,
+ width, -height, height);
+
+ // allocate a line buffer
+ lineBuf = (Guchar *)gmalloc(4 * width);
+
+ // set up to process the data stream
+ imgStr = new ImageStream(str, width, colorMap->getNumPixelComps(),
+ colorMap->getBits());
+ imgStr->reset();
+
+ // process the data stream
+ i = 0;
+ for (y = 0; y < height; ++y) {
+
+ // read the line
+ for (x = 0; x < width; ++x) {
+ imgStr->getPixel(pixBuf);
+ colorMap->getCMYK(pixBuf, &cmyk);
+ lineBuf[4*x+0] = (int)(255 * cmyk.c + 0.5);
+ lineBuf[4*x+1] = (int)(255 * cmyk.m + 0.5);
+ lineBuf[4*x+2] = (int)(255 * cmyk.y + 0.5);
+ lineBuf[4*x+3] = (int)(255 * cmyk.k + 0.5);
+ }
+
+ // write one line of each color component
+ for (comp = 0; comp < 4; ++comp) {
+ for (x = 0; x < width; ++x) {
+ fprintf(f, "%02x", lineBuf[4*x + comp]);
+ if (++i == 32) {
+ fputc('\n', f);
+ i = 0;
+ }
+ }
+ }
+ }
+
+ if (i != 0) {
+ fputc('\n', f);
+ }
+
+ delete imgStr;
+ gfree(lineBuf);
+}
+
+void PSOutputDev::doImageL2(Object *ref, GfxImageColorMap *colorMap,
+ GBool invert, GBool inlineImg,
+ Stream *str, int width, int height, int len) {
GString *s;
int n, numComps;
- Guchar *color;
- Guchar x[4];
- GfxColor rgb;
GBool useRLE, useA85;
int c;
- int i, j, k;
+ int i;
// color space
if (colorMap) {
- colorSpace = colorMap->getColorSpace();
- if (colorSpace->isSeparation()) {
- //~ this is a kludge -- the correct thing would be to output
- //~ a separation color space
- n = (1 << colorMap->getBits()) - 1;
- writePS("[/Indexed /DeviceRGB %d <", n);
- for (i = 0; i <= n; i += 8) {
- writePS(" ");
- for (j = i; j < i+8 && j <= n; ++j) {
- x[0] = j;
- colorMap->getColor(x, &rgb);
- writePS("%02x%02x%02x",
- (int)(255 * rgb.getR() + 0.5),
- (int)(255 * rgb.getG() + 0.5),
- (int)(255 * rgb.getB() + 0.5));
- }
- writePS("\n");
- }
- writePS("> ] setcolorspace\n");
- } else {
- if (colorSpace->isIndexed()) {
- writePS("[/Indexed ");
- }
- switch (colorSpace->getMode()) {
- case colorGray:
- writePS("/DeviceGray ");
- break;
- case colorCMYK:
- writePS("/DeviceCMYK ");
- break;
- case colorRGB:
- writePS("/DeviceRGB ");
- break;
- case colorLab:
- labParams = colorSpace->getLabParams();
- writePS("[/CIEBasedABC <<\n");
- writePS(" /RangeABC [0 100 %g %g %g %g]\n",
- labParams->aMin, labParams->aMax,
- labParams->bMin, labParams->bMax);
- writePS(" /DecodeABC [{16 add 116 div} bind {500 div} bind {200 div} bind]\n");
- writePS(" /MatrixABC [1 1 1 1 0 0 0 0 -1]\n");
- writePS(" /DecodeLMN\n");
- writePS(" [{dup 6 29 div ge {dup dup mul mul}\n");
- writePS(" {4 29 div sub 108 841 div mul } ifelse %g mul} bind\n",
- labParams->whiteX);
- writePS(" {dup 6 29 div ge {dup dup mul mul}\n");
- writePS(" {4 29 div sub 108 841 div mul } ifelse %g mul} bind\n",
- labParams->whiteY);
- writePS(" {dup 6 29 div ge {dup dup mul mul}\n");
- writePS(" {4 29 div sub 108 841 div mul } ifelse %g mul} bind]\n",
- labParams->whiteZ);
- writePS(" /WhitePoint [%g %g %g]\n",
- labParams->whiteX, labParams->whiteY, labParams->whiteZ);
- writePS(">>] ");
- break;
- }
- if (colorSpace->isIndexed()) {
- n = colorSpace->getIndexHigh();
- numComps = colorSpace->getNumColorComps();
- writePS("%d <\n", n);
- for (i = 0; i <= n; i += 8) {
- writePS(" ");
- for (j = i; j < i+8 && j <= n; ++j) {
- color = colorSpace->getLookupVal(j);
- for (k = 0; k < numComps; ++k) {
- writePS("%02x", color[k]);
- }
- }
- writePS("\n");
- }
- writePS("> ] setcolorspace\n");
- } else {
- writePS("setcolorspace\n");
- }
- }
+ dumpColorSpaceL2(colorMap->getColorSpace());
+ writePS(" setcolorspace\n");
+ }
+
+ // set up to use the array created by setupImages()
+ if (doForm && !inlineImg) {
+ writePS("ImData_%d_%d 0\n", ref->getRefNum(), ref->getRefGen());
}
// image dictionary
// decode
if (colorMap) {
writePS(" /Decode [");
- if (colorMap->getColorSpace()->isSeparation()) {
- //~ this is a kludge -- the correct thing would be to output
- //~ a separation color space
+ if (colorMap->getColorSpace()->getMode() == csSeparation) {
+ //~ this is a kludge -- see comment in dumpColorSpaceL2
n = (1 << colorMap->getBits()) - 1;
writePS("%g %g", colorMap->getDecodeLow(0) * n,
colorMap->getDecodeHigh(0) * n);
if (doForm) {
- // data source
- writePS(" /DataSource <~\n");
-
- // write image data stream, using ASCII85 encode filter
if (inlineImg) {
+
+ // data source
+ writePS(" /DataSource <~\n");
+
+ // write image data stream, using ASCII85 encode filter
str = new FixedLengthEncoder(str, len);
+ str = new ASCII85Encoder(str);
+ str->reset();
+ while ((c = str->getChar()) != EOF) {
+ fputc(c, f);
+ }
+ fputc('\n', f);
+ delete str;
+
+ } else {
+ writePS(" /DataSource { 2 copy get exch 1 add exch }\n");
}
- str = new ASCII85Encoder(str);
- str->reset();
- while ((c = str->getChar()) != EOF)
- fputc(c, f);
- fputc('\n', f);
- delete str;
// end of image dictionary
writePS(">>\n%s\n", colorMap ? "image" : "imagemask");
+ // get rid of the array and index
+ if (!inlineImg) {
+ writePS("pop pop\n");
+ }
+
} else {
// data source
}
}
+void PSOutputDev::dumpColorSpaceL2(GfxColorSpace *colorSpace) {
+ GfxCalGrayColorSpace *calGrayCS;
+ GfxCalRGBColorSpace *calRGBCS;
+ GfxLabColorSpace *labCS;
+ GfxIndexedColorSpace *indexedCS;
+ GfxSeparationColorSpace *separationCS;
+ Guchar *lookup;
+ double x[1], y[gfxColorMaxComps];
+ int n, numComps;
+ int i, j, k;
+
+ switch (colorSpace->getMode()) {
+
+ case csDeviceGray:
+ writePS("/DeviceGray");
+ break;
+
+ case csCalGray:
+ calGrayCS = (GfxCalGrayColorSpace *)colorSpace;
+ writePS("[/CIEBasedA <<\n");
+ writePS(" /DecodeA {%g exp} bind\n", calGrayCS->getGamma());
+ writePS(" /MatrixA [%g %g %g]\n",
+ calGrayCS->getWhiteX(), calGrayCS->getWhiteY(),
+ calGrayCS->getWhiteZ());
+ writePS(" /WhitePoint [%g %g %g]\n",
+ calGrayCS->getWhiteX(), calGrayCS->getWhiteY(),
+ calGrayCS->getWhiteZ());
+ writePS(" /BlackPoint [%g %g %g]\n",
+ calGrayCS->getBlackX(), calGrayCS->getBlackY(),
+ calGrayCS->getBlackZ());
+ writePS(">>]");
+ break;
+
+ case csDeviceRGB:
+ writePS("/DeviceRGB");
+ break;
+
+ case csCalRGB:
+ calRGBCS = (GfxCalRGBColorSpace *)colorSpace;
+ writePS("[/CIEBasedABC <<\n");
+ writePS(" /DecodeABC [{%g exp} bind {%g exp} bind {%g exp} bind]\n",
+ calRGBCS->getGammaR(), calRGBCS->getGammaG(),
+ calRGBCS->getGammaB());
+ writePS(" /MatrixABC [%g %g %g %g %g %g %g %g %g]\n",
+ calRGBCS->getMatrix()[0], calRGBCS->getMatrix()[1],
+ calRGBCS->getMatrix()[2], calRGBCS->getMatrix()[3],
+ calRGBCS->getMatrix()[4], calRGBCS->getMatrix()[5],
+ calRGBCS->getMatrix()[6], calRGBCS->getMatrix()[7],
+ calRGBCS->getMatrix()[8]);
+ writePS(" /WhitePoint [%g %g %g]\n",
+ calRGBCS->getWhiteX(), calRGBCS->getWhiteY(),
+ calRGBCS->getWhiteZ());
+ writePS(" /BlackPoint [%g %g %g]\n",
+ calRGBCS->getBlackX(), calRGBCS->getBlackY(),
+ calRGBCS->getBlackZ());
+ writePS(">>]");
+ break;
+
+ case csDeviceCMYK:
+ writePS("/DeviceCMYK");
+ break;
+
+ case csLab:
+ labCS = (GfxLabColorSpace *)colorSpace;
+ writePS("[/CIEBasedABC <<\n");
+ writePS(" /RangeABC [0 100 %g %g %g %g]\n",
+ labCS->getAMin(), labCS->getAMax(),
+ labCS->getBMin(), labCS->getBMax());
+ writePS(" /DecodeABC [{16 add 116 div} bind {500 div} bind {200 div} bind]\n");
+ writePS(" /MatrixABC [1 1 1 1 0 0 0 0 -1]\n");
+ writePS(" /DecodeLMN\n");
+ writePS(" [{dup 6 29 div ge {dup dup mul mul}\n");
+ writePS(" {4 29 div sub 108 841 div mul } ifelse %g mul} bind\n",
+ labCS->getWhiteX());
+ writePS(" {dup 6 29 div ge {dup dup mul mul}\n");
+ writePS(" {4 29 div sub 108 841 div mul } ifelse %g mul} bind\n",
+ labCS->getWhiteY());
+ writePS(" {dup 6 29 div ge {dup dup mul mul}\n");
+ writePS(" {4 29 div sub 108 841 div mul } ifelse %g mul} bind]\n",
+ labCS->getWhiteZ());
+ writePS(" /WhitePoint [%g %g %g]\n",
+ labCS->getWhiteX(), labCS->getWhiteY(), labCS->getWhiteZ());
+ writePS(" /BlackPoint [%g %g %g]\n",
+ labCS->getBlackX(), labCS->getBlackY(), labCS->getBlackZ());
+ writePS(">>]");
+ break;
+
+ case csICCBased:
+ dumpColorSpaceL2(((GfxICCBasedColorSpace *)colorSpace)->getAlt());
+ break;
+
+ case csIndexed:
+ indexedCS = (GfxIndexedColorSpace *)colorSpace;
+ writePS("[/Indexed ");
+ dumpColorSpaceL2(indexedCS->getBase());
+ n = indexedCS->getIndexHigh();
+ numComps = indexedCS->getBase()->getNComps();
+ lookup = indexedCS->getLookup();
+ writePS(" %d <\n", n);
+ for (i = 0; i <= n; i += 8) {
+ writePS(" ");
+ for (j = i; j < i+8 && j <= n; ++j) {
+ for (k = 0; k < numComps; ++k) {
+ writePS("%02x", lookup[j * numComps + k]);
+ }
+ }
+ writePS("\n");
+ }
+ writePS(">]");
+ break;
+
+ case csSeparation:
+ //~ this is a kludge -- the correct thing would to ouput a
+ //~ separation color space, with the specified alternate color
+ //~ space and tint transform
+ separationCS = (GfxSeparationColorSpace *)colorSpace;
+ writePS(" [/Indexed ");
+ dumpColorSpaceL2(separationCS->getAlt());
+ writePS(" 255 <\n");
+ numComps = separationCS->getAlt()->getNComps();
+ for (i = 0; i <= 255; i += 8) {
+ writePS(" ");
+ for (j = i; j < i+8 && j <= 255; ++j) {
+ x[0] = (double)j / 255.0;
+ separationCS->getFunc()->transform(x, y);
+ for (k = 0; k < numComps; ++k) {
+ writePS("%02x", (int)(255 * y[k] + 0.5));
+ }
+ }
+ writePS("\n");
+ }
+ writePS(">]");
+ break;
+
+ case csDeviceN:
+ // DeviceN color spaces are a Level 3 PostScript feature.
+ dumpColorSpaceL2(((GfxDeviceNColorSpace *)colorSpace)->getAlt());
+ break;
+
+ case csPattern:
+ //~ unimplemented
+ break;
+
+ }
+}
+
#if OPI_SUPPORT
void PSOutputDev::opiBegin(GfxState *state, Dict *opiDict) {
Object dict;
obj1.arrayGet(1, &obj2);
height = obj2.getInt();
obj2.free();
- writePS("%%ALDImageSize: %d %d\n", width, height);
+ writePS("%%ALDImageDimensions: %d %d\n", width, height);
}
obj1.free();
class GfxPath;
class GfxFont;
+class GfxColorSpace;
//------------------------------------------------------------------------
// Parameters
// Generate Level 1 PostScript?
extern GBool psOutLevel1;
+// Generate Level 1 separable PostScript?
+extern GBool psOutLevel1Sep;
+
// Generate Encapsulated PostScript?
extern GBool psOutEPS;
public:
// Open a PostScript output file, and write the prolog.
- PSOutputDev(char *fileName, Catalog *catalog,
+ PSOutputDev(const char *fileName, Catalog *catalog,
int firstPage, int lastPage,
GBool embedType11, GBool doForm1);
virtual void drawString16(GfxState *state, GString *s);
//----- image drawing
- virtual void drawImageMask(GfxState *state, Stream *str,
+ virtual void drawImageMask(GfxState *state, Object *ref, Stream *str,
int width, int height, GBool invert,
GBool inlineImg);
- virtual void drawImage(GfxState *state, Stream *str, int width,
- int height, GfxImageColorMap *colorMap,
+ virtual void drawImage(GfxState *state, Object *ref, Stream *str,
+ int width, int height, GfxImageColorMap *colorMap,
GBool inlineImg);
#if OPI_SUPPORT
private:
+ void setupResources(Dict *resDict);
void setupFonts(Dict *resDict);
void setupFont(GfxFont *font);
- void setupEmbeddedType1Font(Ref *id, char *psName);
- void setupEmbeddedType1Font(GString *fileName, char *psName);
- void setupEmbeddedType1CFont(GfxFont *font, Ref *id, char *psName);
+ void setupEmbeddedType1Font(Ref *id, const char *psName);
+ void setupEmbeddedType1Font(GString *fileName, const char *psName);
+ void setupEmbeddedType1CFont(GfxFont *font, Ref *id, const char *psName);
+ void setupImages(Dict *resDict);
+ void setupImage(Ref id, Stream *str);
void doPath(GfxPath *path);
void doImageL1(GfxImageColorMap *colorMap,
GBool invert, GBool inlineImg,
Stream *str, int width, int height, int len);
- void doImage(GfxImageColorMap *colorMap,
- GBool invert, GBool inlineImg,
- Stream *str, int width, int height, int len);
+ void doImageL1Sep(GfxImageColorMap *colorMap,
+ GBool invert, GBool inlineImg,
+ Stream *str, int width, int height, int len);
+ void doImageL2(Object *ref, GfxImageColorMap *colorMap,
+ GBool invert, GBool inlineImg,
+ Stream *str, int width, int height, int len);
+ void dumpColorSpaceL2(GfxColorSpace *colorSpace);
void opiBegin20(GfxState *state, Dict *dict);
void opiBegin13(GfxState *state, Dict *dict);
void opiTransform(GfxState *state, double x0, double y0,
int opi20Nest; // nesting level of OPI 2.0 objects
#endif
+ GBool type3Warning; // only show the Type 3 font warning once
+
GBool ok; // set up ok?
};
contents.free();
}
-void Page::display(OutputDev *out, int dpi, int rotate,
+void Page::display(OutputDev *out, double dpi, int rotate,
Links *links, Catalog *catalog) {
#ifndef PDF_PARSER_ONLY
Gfx *gfx;
for (i = 0; i < formWidgets->getNumWidgets(); ++i) {
formWidgets->getWidget(i)->draw(gfx);
}
+ if (formWidgets->getNumWidgets() > 0) {
+ out->dump();
+ }
delete formWidgets;
delete gfx;
Object *getContents(Object *obj) { return contents.fetch(obj); }
// Display a page.
- void display(OutputDev *out, int dpi, int rotate,
+ void display(OutputDev *out, double dpi, int rotate,
Links *links, Catalog *catalog);
private:
#include "gfile.h"
#include "Params.h"
-char **fontPath = NULL;
+const char **fontPath = NULL;
static int fontPathLen, fontPathSize;
DevFontMapEntry *devFontMap = NULL;
static int devFontMapLen, devFontMapSize;
-void initParams(char *configFile) {
+void initParams(const char *configFile) {
GString *fileName;
FILE *f;
char buf[256];
char *p, *q;
// initialize font path and font map
- fontPath = (char **)gmalloc((fontPathSize = 8) * sizeof(char *));
+ fontPath = (const char **)gmalloc((fontPathSize = 8) * sizeof(const char *));
fontPath[fontPathLen = 0] = NULL;
devFontMap = (DevFontMapEntry *)gmalloc((devFontMapSize = 8) *
sizeof(DevFontMapEntry));
p = strtok(buf, " \t\n\r");
if (p && !strcmp(p, "fontpath")) {
if (fontPathLen+1 >= fontPathSize)
- fontPath = (char **)
- grealloc(fontPath, (fontPathSize += 8) * sizeof(char *));
+ fontPath = (const char **)
+ grealloc(fontPath, (fontPathSize += 8) * sizeof(const char *));
p = strtok(NULL, " \t\n\r");
fontPath[fontPathLen++] = copyString(p);
} else if (p && !strcmp(p, "fontmap")) {
if (fontPath) {
for (i = 0; i < fontPathLen; ++i)
- gfree(fontPath[i]);
- gfree(fontPath);
+ gfree((void *)fontPath[i]);
+ gfree((void *)fontPath);
}
if (devFontMap) {
for (i = 0; i < devFontMapLen; ++i) {
- gfree(devFontMap[i].pdfFont);
- gfree(devFontMap[i].devFont);
+ gfree((void *)devFontMap[i].pdfFont);
+ gfree((void *)devFontMap[i].devFont);
}
- gfree(devFontMap);
+ gfree((void *)devFontMap);
}
}
extern GBool errQuiet;
// Font search path.
-extern char **fontPath;
+extern const char **fontPath;
// Mapping from PDF font name to device font name.
struct DevFontMapEntry {
- char *pdfFont;
- char *devFont;
+ const char *pdfFont;
+ const char *devFont;
};
extern DevFontMapEntry *devFontMap;
// Initialize font path and font map, and read configuration file,
// if present.
-extern void initParams(char *configFile);
+extern void initParams(const char *configFile);
// Free memory used for font path and font map.
extern void freeParams();
#include "Array.h"
#include "Dict.h"
#include "Parser.h"
+#include "XRef.h"
#include "Error.h"
#ifndef NO_DECRYPTION
#include "Decrypt.h"
Stream *Parser::makeStream(Object *dict) {
Object obj;
Stream *str;
- int pos, length;
+ int pos, endPos, length;
// get stream start position
lexer->skipToNextLine();
return NULL;
}
+ // check for length in damaged file
+ if ((endPos = xref->getStreamEnd(pos)) >= 0) {
+ length = endPos - pos;
+ }
+
// make base stream
str = lexer->getStream()->getBaseStream()->makeSubStream(pos, length, dict);
//------------------------------------------------------------------------
#define type1StdEncodingSize 256
-static char *type1StdEncodingNames[type1StdEncodingSize] = {
+static const char *type1StdEncodingNames[type1StdEncodingSize] = {
NULL,
NULL,
NULL,
//------------------------------------------------------------------------
#define type1ExpertEncodingSize 256
-static char *type1ExpertEncodingNames[type1ExpertEncodingSize] = {
+static const char *type1ExpertEncodingNames[type1ExpertEncodingSize] = {
NULL,
NULL,
NULL,
Stream::~Stream() {
}
+void Stream::close() {
+}
+
int Stream::getRawChar() {
error(-1, "Internal: called getRawChar() on non-predictor stream");
return EOF;
return buf;
}
-GString *Stream::getPSFilter(char *indent) {
+GString *Stream::getPSFilter(const char *indent) {
+ (void)indent;
+
return new GString();
}
return str;
}
-Stream *Stream::makeFilter(char *name, Stream *str, Object *params) {
+Stream *Stream::makeFilter(const char *name, Stream *str, Object *params) {
int pred; // parameters
int colors;
int bits;
// BaseStream
//------------------------------------------------------------------------
-BaseStream::BaseStream(Object *dict) {
- this->dict = *dict;
+BaseStream::BaseStream(Object *ndict) {
+ dict = *ndict;
#ifndef NO_DECRYPTION
decrypt = NULL;
#endif
// FilterStream
//------------------------------------------------------------------------
-FilterStream::FilterStream(Stream *str) {
- this->str = str;
+FilterStream::FilterStream(Stream *nstr) {
+ str = nstr;
}
FilterStream::~FilterStream() {
}
+void FilterStream::close() {
+ str->close();
+}
+
void FilterStream::setPos(int pos) {
+ (void)pos;
+
error(-1, "Internal: called setPos() on FilterStream");
}
// ImageStream
//------------------------------------------------------------------------
-ImageStream::ImageStream(Stream *str, int width, int nComps, int nBits) {
+ImageStream::ImageStream(Stream *nstr, int nwidth, int nnComps, int nnBits) {
int imgLineSize;
- this->str = str;
- this->width = width;
- this->nComps = nComps;
- this->nBits = nBits;
+ str = nstr;
+ width = nwidth;
+ nComps = nnComps;
+ nBits = nnBits;
nVals = width * nComps;
if (nBits == 1) {
// StreamPredictor
//------------------------------------------------------------------------
-StreamPredictor::StreamPredictor(Stream *str, int predictor,
- int width, int nComps, int nBits) {
- this->str = str;
- this->predictor = predictor;
- this->width = width;
- this->nComps = nComps;
- this->nBits = nBits;
+StreamPredictor::StreamPredictor(Stream *nstr, int npredictor,
+ int nwidth, int nnComps, int nnBits) {
+ str = nstr;
+ predictor = npredictor;
+ width = nwidth;
+ nComps = nnComps;
+ nBits = nnBits;
nVals = width * nComps;
pixBytes = (nComps * nBits + 7) >> 3;
// FileStream
//------------------------------------------------------------------------
-FileStream::FileStream(FILE *f, int start, int length, Object *dict):
+FileStream::FileStream(FILE *nf, int nstart, int nlength, Object *dict):
BaseStream(dict) {
- this->f = f;
- this->start = start;
- this->length = length;
+ f = nf;
+ start = nstart;
+ length = nlength;
bufPtr = bufEnd = buf;
bufPos = start;
savePos = -1;
}
FileStream::~FileStream() {
- if (savePos >= 0) {
- fseek(f, savePos, SEEK_SET);
- }
+ close();
}
-Stream *FileStream::makeSubStream(int start, int length, Object *dict) {
- return new FileStream(f, start, length, dict);
+Stream *FileStream::makeSubStream(int nstart, int nlength, Object *ndict) {
+ return new FileStream(f, nstart, nlength, ndict);
}
void FileStream::reset() {
#endif
}
+void FileStream::close() {
+ if (savePos >= 0) {
+ fseek(f, savePos, SEEK_SET);
+ savePos = -1;
+ }
+}
+
GBool FileStream::fillBuf() {
int n;
#ifndef NO_DECRYPTION
bufPos += bufEnd - buf;
bufPtr = bufEnd = buf;
- if (length >= 0 && bufPos >= start + length)
+ if (length >= 0 && bufPos >= start + length) {
return gFalse;
- if (length >= 0 && bufPos + 256 > start + length)
+ }
+ if (length >= 0 && bufPos + fileStreamBufSize > start + length) {
n = start + length - bufPos;
- else
- n = 256;
+ } else {
+ n = fileStreamBufSize;
+ }
n = fread(buf, 1, n, f);
bufEnd = buf + n;
- if (bufPtr >= bufEnd)
+ if (bufPtr >= bufEnd) {
return gFalse;
+ }
#ifndef NO_DECRYPTION
if (decrypt) {
- for (p = buf; p < bufEnd; ++p)
+ for (p = buf; p < bufEnd; ++p) {
*p = (char)decrypt->decryptByte((Guchar)*p);
+ }
}
#endif
return gTrue;
// EmbedStream
//------------------------------------------------------------------------
-EmbedStream::EmbedStream(Stream *str, Object *dict):
- BaseStream(dict) {
- this->str = str;
+EmbedStream::EmbedStream(Stream *nstr, Object *ndict):
+ BaseStream(ndict) {
+ str = nstr;
}
EmbedStream::~EmbedStream() {
}
-Stream *EmbedStream::makeSubStream(int start, int length, Object *dict) {
+Stream *EmbedStream::makeSubStream(int start, int length, Object *ndict) {
+ (void)start;
+ (void)length;
+ (void)ndict;
+
error(-1, "Internal: called makeSubStream() on EmbedStream");
return NULL;
}
void EmbedStream::setPos(int pos) {
+ (void)pos;
+
error(-1, "Internal: called setPos() on EmbedStream");
}
}
void EmbedStream::moveStart(int start) {
+ (void)start;
+
error(-1, "Internal: called moveStart() on EmbedStream");
}
return buf;
}
-GString *ASCIIHexStream::getPSFilter(char *indent) {
+GString *ASCIIHexStream::getPSFilter(const char *indent) {
GString *s;
s = str->getPSFilter(indent);
}
GBool ASCIIHexStream::isBinary(GBool last) {
+ (void)last;
+
return str->isBinary(gFalse);
}
return b[index];
}
-GString *ASCII85Stream::getPSFilter(char *indent) {
+GString *ASCII85Stream::getPSFilter(const char *indent) {
GString *s;
s = str->getPSFilter(indent);
}
GBool ASCII85Stream::isBinary(GBool last) {
+ (void)last;
+
return str->isBinary(gFalse);
}
return n > 0;
}
-GString *LZWStream::getPSFilter(char *indent) {
+GString *LZWStream::getPSFilter(const char *indent) {
GString *s;
if (pred) {
}
GBool LZWStream::isBinary(GBool last) {
+ (void)last;
+
return str->isBinary(gTrue);
}
eof = gFalse;
}
-GString *RunLengthStream::getPSFilter(char *indent) {
+GString *RunLengthStream::getPSFilter(const char *indent) {
GString *s;
s = str->getPSFilter(indent);
}
GBool RunLengthStream::isBinary(GBool last) {
+ (void)last;
+
return str->isBinary(gTrue);
}
// CCITTFaxStream
//------------------------------------------------------------------------
-CCITTFaxStream::CCITTFaxStream(Stream *str, int encoding, GBool endOfLine,
- GBool byteAlign, int columns, int rows,
- GBool endOfBlock, GBool black):
+CCITTFaxStream::CCITTFaxStream(Stream *str, int nencoding, GBool nendOfLine,
+ GBool nbyteAlign, int ncolumns, int nrows,
+ GBool nendOfBlock, GBool nblack):
FilterStream(str) {
- this->encoding = encoding;
- this->endOfLine = endOfLine;
- this->byteAlign = byteAlign;
- this->columns = columns;
- this->rows = rows;
- this->endOfBlock = endOfBlock;
- this->black = black;
+ encoding = nencoding;
+ endOfLine = nendOfLine;
+ byteAlign = nbyteAlign;
+ columns = ncolumns;
+ rows = nrows;
+ endOfBlock = nendOfBlock;
+ black = nblack;
refLine = (short *)gmalloc((columns + 3) * sizeof(short));
codingLine = (short *)gmalloc((columns + 2) * sizeof(short));
#if 0 //~
GBool err;
#endif
+ GBool gotEOL;
int ret;
- int bits, i, n;
+ int bits, i;
// if at eof just return EOF
if (eof && codingLine[a0] >= columns) {
inputBits &= ~7;
}
- // check for end-of-line marker, end-of-block marker, and
- // 2D encoding tag
- if (endOfBlock) {
+ // check for end-of-line marker, skipping over any extra zero bits
+ gotEOL = gFalse;
+ if (!endOfBlock && row == rows - 1) {
+ eof = gTrue;
+ } else {
code1 = lookBits(12);
- if (code1 == EOF) {
+ while (code1 == 0) {
+ eatBits(1);
+ code1 = lookBits(12);
+ }
+ if (code1 == 0x001) {
+ eatBits(12);
+ gotEOL = gTrue;
+ } else if (code1 == EOF) {
eof = gTrue;
- } else if (code1 == 0x001) {
+ }
+ }
+
+ // get 2D encoding tag
+ if (!eof && encoding > 0) {
+ nextLine2D = !lookBits(1);
+ eatBits(1);
+ }
+
+ // check for end-of-block marker
+ if (endOfBlock && gotEOL) {
+ code1 = lookBits(12);
+ if (code1 == 0x001) {
eatBits(12);
if (encoding > 0) {
- nextLine2D = !lookBits(1);
+ lookBits(1);
eatBits(1);
}
- code1 = lookBits(12);
- if (code1 == 0x001) {
- eatBits(12);
- if (encoding > 0) {
- lookBits(1);
- eatBits(1);
- }
- if (encoding >= 0) {
- for (i = 0; i < 4; ++i) {
- code1 = lookBits(12);
- if (code1 != 0x001) {
- error(getPos(), "Bad RTC code in CCITTFax stream");
- }
- eatBits(12);
- if (encoding > 0) {
- lookBits(1);
- eatBits(1);
- }
+ if (encoding >= 0) {
+ for (i = 0; i < 4; ++i) {
+ code1 = lookBits(12);
+ if (code1 != 0x001) {
+ error(getPos(), "Bad RTC code in CCITTFax stream");
+ }
+ eatBits(12);
+ if (encoding > 0) {
+ lookBits(1);
+ eatBits(1);
}
}
- eof = gTrue;
- }
- } else {
- if (encoding > 0) {
- nextLine2D = !lookBits(1);
- eatBits(1);
}
- }
- } else {
- if (row == rows - 1) {
eof = gTrue;
- } else {
- for (n = 0; n < 11 && lookBits(n) == 0; ++n) ;
- if (n == 11 && lookBits(12) == 0x001) {
- eatBits(12);
- }
- if (encoding > 0) {
- nextLine2D = !lookBits(1);
- eatBits(1);
- }
}
}
code = 0; // make gcc happy
if (endOfBlock) {
code = lookBits(12);
- if ((code >> 5) == 0)
+ if ((code >> 5) == 0) {
p = &whiteTab1[code];
- else
+ } else {
p = &whiteTab2[code >> 3];
+ }
if (p->bits > 0) {
eatBits(p->bits);
return p->n;
}
}
error(getPos(), "Bad white code (%04x) in CCITTFax stream", code);
- return EOF;
+ // eat a bit and return a positive number so that the caller doesn't
+ // go into an infinite loop
+ eatBits(1);
+ return 1;
}
short CCITTFaxStream::getBlackCode() {
code = 0; // make gcc happy
if (endOfBlock) {
code = lookBits(13);
- if ((code >> 7) == 0)
+ if ((code >> 7) == 0) {
p = &blackTab1[code];
- else if ((code >> 9) == 0)
+ } else if ((code >> 9) == 0) {
p = &blackTab2[(code >> 1) - 64];
- else
+ } else {
p = &blackTab3[code >> 7];
+ }
if (p->bits > 0) {
eatBits(p->bits);
return p->n;
}
}
error(getPos(), "Bad black code (%04x) in CCITTFax stream", code);
- return EOF;
+ // eat a bit and return a positive number so that the caller doesn't
+ // go into an infinite loop
+ eatBits(1);
+ return 1;
}
short CCITTFaxStream::lookBits(int n) {
while (inputBits < n) {
if ((c = str->getChar()) == EOF) {
- if (inputBits == 0)
+ if (inputBits == 0) {
return EOF;
- c = 0;
+ }
+ // near the end of the stream, the caller may ask for more bits
+ // than are available, but there may still be a valid code in
+ // however many bits are available -- we need to return correct
+ // data in this case
+ return (inputBuf << (n - inputBits)) & (0xffff >> (16 - n));
}
inputBuf = (inputBuf << 8) + c;
inputBits += 8;
return (inputBuf >> (inputBits - n)) & (0xffff >> (16 - n));
}
-GString *CCITTFaxStream::getPSFilter(char *indent) {
+GString *CCITTFaxStream::getPSFilter(const char *indent) {
GString *s;
char s1[50];
}
GBool CCITTFaxStream::isBinary(GBool last) {
+ (void)last;
+
return str->isBinary(gTrue);
}
return (c1 << 8) + c2;
}
-GString *DCTStream::getPSFilter(char *indent) {
+GString *DCTStream::getPSFilter(const char *indent) {
GString *s;
s = str->getPSFilter(indent);
}
GBool DCTStream::isBinary(GBool last) {
+ (void)last;
+
return str->isBinary(gTrue);
}
void FlateStream::reset() {
int cmf, flg;
+ index = 0;
+ remain = 0;
+ codeBuf = 0;
+ codeSize = 0;
+ compressedBlock = gFalse;
+ endOfBlock = gTrue;
+ eof = gTrue;
+
str->reset();
// read header
return;
}
- // initialize
- index = 0;
- remain = 0;
- codeBuf = 0;
- codeSize = 0;
- compressedBlock = gFalse;
- endOfBlock = gTrue;
eof = gFalse;
}
return c;
}
-GString *FlateStream::getPSFilter(char *indent) {
+GString *FlateStream::getPSFilter(const char *indent) {
+ (void)indent;
+
return NULL;
}
GBool FlateStream::isBinary(GBool last) {
+ (void)last;
+
return str->isBinary(gTrue);
}
count = 0;
}
+void FixedLengthEncoder::close() {
+}
+
int FixedLengthEncoder::getChar() {
if (length >= 0 && count >= length)
return EOF;
eof = gFalse;
}
+void ASCII85Encoder::close() {
+}
+
GBool ASCII85Encoder::fillBuf() {
Gulong t;
char buf1[5];
eof = gFalse;
}
+void RunLengthEncoder::close() {
+}
+
//
// When fillBuf finishes, buf[] looks like this:
// +-----+--------------+-----------------+--
// Reset stream to beginning.
virtual void reset() = 0;
+ // Close down the stream.
+ virtual void close();
+
// Get next char from stream.
virtual int getChar() = 0;
virtual void setPos(int pos1) = 0;
// Get PostScript command for the filter(s).
- virtual GString *getPSFilter(char *indent);
+ virtual GString *getPSFilter(const char *indent);
// Does this stream type potentially contain non-printable chars?
virtual GBool isBinary(GBool last = gTrue) = 0;
private:
- Stream *makeFilter(char *name, Stream *str, Object *params);
+ Stream *makeFilter(const char *name, Stream *str, Object *params);
int ref; // reference count
};
FilterStream(Stream *str);
virtual ~FilterStream();
+ virtual void close();
virtual int getPos() { return str->getPos(); }
virtual void setPos(int pos);
virtual BaseStream *getBaseStream() { return str->getBaseStream(); }
// FileStream
//------------------------------------------------------------------------
+#define fileStreamBufSize 256
+
class FileStream: public BaseStream {
public:
virtual Stream *makeSubStream(int start, int length, Object *dict);
virtual StreamKind getKind() { return strFile; }
virtual void reset();
+ virtual void close();
virtual int getChar()
{ return (bufPtr >= bufEnd && !fillBuf()) ? EOF : (*bufPtr++ & 0xff); }
virtual int lookChar()
FILE *f;
int start;
int length;
- char buf[256];
+ char buf[fileStreamBufSize];
char *bufPtr;
char *bufEnd;
int bufPos;
virtual int getChar()
{ int c = lookChar(); buf = EOF; return c; }
virtual int lookChar();
- virtual GString *getPSFilter(char *indent);
+ virtual GString *getPSFilter(const char *indent);
virtual GBool isBinary(GBool last = gTrue);
private:
virtual int getChar()
{ int ch = lookChar(); ++index; return ch; }
virtual int lookChar();
- virtual GString *getPSFilter(char *indent);
+ virtual GString *getPSFilter(const char *indent);
virtual GBool isBinary(GBool last = gTrue);
private:
virtual int getChar();
virtual int lookChar();
virtual int getRawChar();
- virtual GString *getPSFilter(char *indent);
+ virtual GString *getPSFilter(const char *indent);
virtual GBool isBinary(GBool last = gTrue);
private:
{ return (bufPtr >= bufEnd && !fillBuf()) ? EOF : (*bufPtr++ & 0xff); }
virtual int lookChar()
{ return (bufPtr >= bufEnd && !fillBuf()) ? EOF : (*bufPtr & 0xff); }
- virtual GString *getPSFilter(char *indent);
+ virtual GString *getPSFilter(const char *indent);
virtual GBool isBinary(GBool last = gTrue);
private:
virtual int getChar()
{ int c = lookChar(); buf = EOF; return c; }
virtual int lookChar();
- virtual GString *getPSFilter(char *indent);
+ virtual GString *getPSFilter(const char *indent);
virtual GBool isBinary(GBool last = gTrue);
private:
virtual void reset();
virtual int getChar();
virtual int lookChar();
- virtual GString *getPSFilter(char *indent);
+ virtual GString *getPSFilter(const char *indent);
virtual GBool isBinary(GBool last = gTrue);
Stream *getRawStream() { return str; }
virtual int getChar();
virtual int lookChar();
virtual int getRawChar();
- virtual GString *getPSFilter(char *indent);
+ virtual GString *getPSFilter(const char *indent);
virtual GBool isBinary(GBool last = gTrue);
private:
virtual void reset() {}
virtual int getChar() { return EOF; }
virtual int lookChar() { return EOF; }
- virtual GString *getPSFilter(char *indent) { return NULL; }
- virtual GBool isBinary(GBool last = gTrue) { return gFalse; }
+ virtual GString *getPSFilter(const char *indent) { (void)indent; return NULL; }
+ virtual GBool isBinary(GBool last = gTrue) { (void)last; return gFalse; }
};
//------------------------------------------------------------------------
~FixedLengthEncoder();
virtual StreamKind getKind() { return strWeird; }
virtual void reset();
+ virtual void close();
virtual int getChar();
virtual int lookChar();
- virtual GString *getPSFilter(char *indent) { return NULL; }
- virtual GBool isBinary(GBool last = gTrue) { return gFalse; }
+ virtual GString *getPSFilter(const char *indent) { (void)indent; return NULL; }
+ virtual GBool isBinary(GBool last = gTrue) { (void)last; return gFalse; }
virtual GBool isEncoder() { return gTrue; }
private:
virtual ~ASCII85Encoder();
virtual StreamKind getKind() { return strWeird; }
virtual void reset();
+ virtual void close();
virtual int getChar()
{ return (bufPtr >= bufEnd && !fillBuf()) ? EOF : (*bufPtr++ & 0xff); }
virtual int lookChar()
{ return (bufPtr >= bufEnd && !fillBuf()) ? EOF : (*bufPtr & 0xff); }
- virtual GString *getPSFilter(char *indent) { return NULL; }
- virtual GBool isBinary(GBool last = gTrue) { return gFalse; }
+ virtual GString *getPSFilter(const char *indent) { (void)indent; return NULL; }
+ virtual GBool isBinary(GBool last = gTrue) { (void)last; return gFalse; }
virtual GBool isEncoder() { return gTrue; }
private:
virtual ~RunLengthEncoder();
virtual StreamKind getKind() { return strWeird; }
virtual void reset();
+ virtual void close();
virtual int getChar()
{ return (bufPtr >= bufEnd && !fillBuf()) ? EOF : (*bufPtr++ & 0xff); }
virtual int lookChar()
{ return (bufPtr >= bufEnd && !fillBuf()) ? EOF : (*bufPtr & 0xff); }
- virtual GString *getPSFilter(char *indent) { return NULL; }
- virtual GBool isBinary(GBool last = gTrue) { return gFalse; }
+ virtual GString *getPSFilter(const char *indent) { (void)indent; return NULL; }
+ virtual GBool isBinary(GBool last = gTrue) { (void)last; return gFalse; }
virtual GBool isEncoder() { return gTrue; }
private:
ok = gTrue;
size = 0;
entries = NULL;
+ streamEnds = NULL;
+ streamEndsLen = 0;
// get rid of old xref (otherwise it will try to fetch the Root object
// in the new document, using the old xref)
XRef::~XRef() {
gfree(entries);
trailerDict.free();
+ if (streamEnds) {
+ gfree(streamEnds);
+ }
}
// Read startxref position, xref table size, and root. Returns
int pos;
int num, gen;
int newSize;
+ int streamEndsSize;
char *p;
int i;
GBool gotRoot;
error(0, "PDF file is damaged - attempting to reconstruct xref table...");
gotRoot = gFalse;
+ streamEndsLen = streamEndsSize = 0;
str->reset();
while (1) {
pos = str->getPos();
- if (!str->getLine(buf, 256))
+ if (!str->getLine(buf, 256)) {
break;
+ }
p = buf;
// got trailer dictionary
if (!strncmp(p, "trailer", 7)) {
obj.initNull();
parser = new Parser(new Lexer(
- str->makeSubStream(start + pos + 8, -1, &obj)));
+ str->makeSubStream(start + pos + 7, -1, &obj)));
if (!trailerDict.isNone())
trailerDict.free();
parser->getObj(&trailerDict);
}
}
}
+
+ } else if (!strncmp(p, "endstream", 9)) {
+ if (streamEndsLen == streamEndsSize) {
+ streamEndsSize += 64;
+ streamEnds = (int *)grealloc(streamEnds, streamEndsSize * sizeof(int));
+ }
+ streamEnds[streamEndsLen++] = pos;
}
}
Object *XRef::getDocInfo(Object *obj) {
return trailerDict.dictLookup("Info", obj);
}
+
+int XRef::getStreamEnd(int start) {
+ int a, b, m;
+
+ if (streamEndsLen == 0 ||
+ start > streamEnds[streamEndsLen - 1]) {
+ return -1;
+ }
+
+ a = -1;
+ b = streamEndsLen - 1;
+ // invariant: streamEnds[a] < start <= streamEnds[b]
+ while (b - a > 1) {
+ m = (a + b) / 2;
+ if (start <= streamEnds[m]) {
+ b = m;
+ } else {
+ a = m;
+ }
+ }
+ return streamEnds[b];
+}
int getRootNum() { return rootNum; }
int getRootGen() { return rootGen; }
+ // Get end position for a stream in a damaged file.
+ // Returns -1 if unknown or file is not damaged.
+ int getStreamEnd(int start);
+
private:
BaseStream *str; // input stream
GBool ok; // true if xref table is valid
Object trailerDict; // trailer dictionary
int lastXRefPos; // offset of last xref table
+ int *streamEnds; // 'endstream' positions - only used in
+ // damaged files
+ int streamEndsLen; // number of valid entries in streamEnds
#ifndef NO_DECRYPTION
GBool encrypted; // true if file is encrypted
int permFlags; // permission bits
#ifndef CONFIG_H
#define CONFIG_H
+#include <config.h>
+#define HAVE_LIBCUPS
+
//------------------------------------------------------------------------
// general constants
//------------------------------------------------------------------------
// xpdf version
-#define xpdfVersion "0.91"
+#define xpdfVersion "0.92"
// supported PDF version
#define supportedPDFVersionStr "1.3"
#define supportedPDFVersionNum 1.3
-
+
// copyright notice
-#define xpdfCopyright "Copyright 1996-2001 Derek B. Noonburg"
+#define xpdfCopyright "Copyright 1996-2000 Derek B. Noonburg"
+
+// default paper size (in points) for PostScript output
+#ifdef A4_PAPER
+#define defPaperWidth 595 // ISO A4 (210x297 mm)
+#define defPaperHeight 842
+#else
+#define defPaperWidth 612 // American letter (8.5x11")
+#define defPaperHeight 792
+#endif
+
+// config file name
+#if defined(VMS)
+#define xpdfConfigFile "xpdfrc"
+#else
+#define xpdfConfigFile ".xpdfrc"
+#endif
//------------------------------------------------------------------------
-// uncompress program
+// X-related constants
//------------------------------------------------------------------------
-#define HAVE_POPEN
-#define uncompressCmd "uncompress -c"
+// default maximum size of color cube to allocate
+#define defaultRGBCube 5
+
+// number of X server fonts to cache
+#define serverFontCacheSize 16
+
+// number of Type 1 (t1lib) fonts to cache
+#define t1FontCacheSize 32
// number of TrueType (FreeType) fonts to cache
#define ttFontCacheSize 32
#define POPEN_READ_MODE "r"
#endif
+//------------------------------------------------------------------------
+// uncompress program
+//------------------------------------------------------------------------
+
+#ifdef HAVE_POPEN
+
+// command to uncompress to stdout
+# ifdef USE_GZIP
+# define uncompressCmd "gzip -d -c -q"
+# else
+# ifdef __EMX__
+# define uncompressCmd "compress -d -c"
+# else
+# define uncompressCmd "uncompress -c"
+# endif // __EMX__
+# endif // USE_GZIP
+
+#else // HAVE_POPEN
+
+// command to uncompress a file
+# ifdef USE_GZIP
+# define uncompressCmd "gzip -d -q"
+# else
+# define uncompressCmd "uncompress"
+# endif // USE_GZIP
+
+#endif // HAVE_POPEN
+
//------------------------------------------------------------------------
// Win32 stuff
//------------------------------------------------------------------------
#endif // WIN32
#include "GString.h"
#include "gfile.h"
-#include <cups/cups.h>
+
+#ifdef HAVE_LIBCUPS
+# include <cups/cups.h>
+#endif // HAVE_LIBCUPS
// Some systems don't define this, so just make it something reasonably
// large.
if ((s = getenv("HOME"))) {
ret = new GString(s);
+# ifdef HAVE_LIBCUPS
+ } else if ((s = getenv("CUPS_SERVERROOT"))) {
+ ret = new GString(s);
+# endif // HAVE_LIBCUPS
} else {
if ((s = getenv("USER")))
pw = getpwnam(s);
return new GString();
}
-GString *appendToPath(GString *path, char *fileName) {
+GString *appendToPath(GString *path, const char *fileName) {
#if defined(VMS)
//---------- VMS ----------
//~ this should handle everything necessary for file
#endif
}
-GString *grabPath(char *fileName) {
+GString *grabPath(const char *fileName) {
#ifdef VMS
//---------- VMS ----------
- char *p;
+ const char *p;
if ((p = strrchr(fileName, ']')))
return new GString(fileName, p + 1 - fileName);
#elif defined(__EMX__) || defined(WIN32)
//---------- OS/2+EMX and Win32 ----------
- char *p;
+ const char *p;
if ((p = strrchr(fileName, '/')))
return new GString(fileName, p - fileName);
#elif defined(ACORN)
//---------- RISCOS ----------
- char *p;
+ const char *p;
if ((p = strrchr(fileName, '.')))
return new GString(fileName, p - fileName);
#elif defined(MACOS)
//---------- MacOS ----------
- char *p;
+ const char *p;
if ((p = strrchr(fileName, ':')))
return new GString(fileName, p - fileName);
#else
//---------- Unix ----------
- char *p;
+ const char *p;
if ((p = strrchr(fileName, '/')))
return new GString(fileName, p - fileName);
#endif
}
-GBool isAbsolutePath(char *path) {
+GBool isAbsolutePath(const char *path) {
#ifdef VMS
//---------- VMS ----------
return strchr(path, ':') ||
#endif
}
-time_t getModTime(char *fileName) {
+time_t getModTime(const char *fileName) {
#ifdef WIN32
//~ should implement this, but it's (currently) only used in xpdf
return 0;
#endif
}
-GBool openTempFile(GString **name, FILE **f, char *mode, char *ext) {
+GBool openTempFile(GString **name, FILE **f, const char *mode, const char *ext) {
+#ifdef HAVE_LIBCUPS
char filename[1024]; // Name of temporary file...
int fd; // File descriptor...
+ (void)ext;
+
// Use the CUPS temporary file function on all platforms...
if ((fd = cupsTempFd(filename, sizeof(filename))) < 0)
return (gFalse);
*name = new GString(filename);
return (gTrue);
+#elif defined(VMS) || defined(__EMX__) || defined(WIN32) || defined(ACORN) || defined(MACOS)
+ //---------- non-Unix ----------
+ char *s;
+
+ // There is a security hole here: an attacker can create a symlink
+ // with this file name after the tmpnam call and before the fopen
+ // call. I will happily accept fixes to this function for non-Unix
+ // OSs.
+ if (!(s = tmpnam(NULL))) {
+ return gFalse;
+ }
+ *name = new GString(s);
+ if (ext) {
+ (*name)->append(ext);
+ }
+ if (!(*f = fopen((*name)->getCString(), mode))) {
+ delete (*name);
+ return gFalse;
+ }
+ return gTrue;
+#else
+ //---------- Unix ----------
+ char *s, *p;
+ int fd;
+
+ if (ext) {
+ if (!(s = tmpnam(NULL))) {
+ return gFalse;
+ }
+ *name = new GString(s);
+ s = (*name)->getCString();
+ if ((p = strrchr(s, '.'))) {
+ (*name)->del(p - s, (*name)->getLength() - (p - s));
+ }
+ (*name)->append(ext);
+ fd = open((*name)->getCString(), O_WRONLY | O_CREAT | O_EXCL, 0600);
+ } else {
+# if HAVE_MKSTEMP
+ if ((s = getenv("TMPDIR"))) {
+ *name = new GString(s);
+ } else {
+ *name = new GString("/tmp");
+ }
+ (*name)->append("/XXXXXX");
+ fd = mkstemp((*name)->getCString());
+# else // HAVE_MKSTEMP
+ if (!(s = tmpnam(NULL))) {
+ return gFalse;
+ }
+ *name = new GString(s);
+ fd = open((*name)->getCString(), O_WRONLY | O_CREAT | O_EXCL, 0600);
+# endif // HAVE_MKSTEMP
+ }
+ if (fd < 0 || !(*f = fdopen(fd, mode))) {
+ delete *name;
+ return gFalse;
+ }
+ return gTrue;
+#endif
}
//------------------------------------------------------------------------
// GDir and GDirEntry
//------------------------------------------------------------------------
-GDirEntry::GDirEntry(char *dirPath, char *name1, GBool doStat) {
+GDirEntry::GDirEntry(const char *dirPath, const char *name1, GBool doStat) {
#ifdef VMS
char *p;
#elif defined(WIN32)
delete name;
}
-GDir::GDir(char *name, GBool doStat1) {
+GDir::GDir(const char *name, GBool doStat1) {
path = new GString(name);
doStat = doStat1;
#if defined(WIN32)
# endif
#elif defined(ACORN)
#elif defined(MACOS)
+# include <ctime.h>
#else
# include <unistd.h>
# include <sys/types.h>
// Append a file name to a path string. <path> may be an empty
// string, denoting the current directory). Returns <path>.
-extern GString *appendToPath(GString *path, char *fileName);
+extern GString *appendToPath(GString *path, const char *fileName);
// Grab the path from the front of the file name. If there is no
// directory component in <fileName>, returns an empty string.
-extern GString *grabPath(char *fileName);
+extern GString *grabPath(const char *fileName);
// Is this an absolute path or file name?
-extern GBool isAbsolutePath(char *path);
+extern GBool isAbsolutePath(const char *path);
// Make this path absolute by prepending current directory (if path is
// relative) or prepending user's directory (if path starts with '~').
// Get the modification time for <fileName>. Returns 0 if there is an
// error.
-time_t getModTime(char *fileName);
+time_t getModTime(const char *fileName);
// Create a temporary file and open it for writing. If <ext> is not
// NULL, it will be used as the file name extension. Returns both the
// should be done to the returned file pointer; the file may be
// reopened later for reading, but not for writing. The <mode> string
// should be "w" or "wb". Returns true on success.
-GBool openTempFile(GString **name, FILE **f, char *mode, char *ext);
+GBool openTempFile(GString **name, FILE **f, const char *mode, const char *ext);
//------------------------------------------------------------------------
// GDir and GDirEntry
class GDirEntry {
public:
- GDirEntry(char *dirPath, char *name1, GBool doStat);
+ GDirEntry(const char *dirPath, const char *name1, GBool doStat);
~GDirEntry();
GString *getName() { return name; }
GBool isDir() { return dir; }
class GDir {
public:
- GDir(char *name, GBool doStat1 = gTrue);
+ GDir(const char *name, GBool doStat1 = gTrue);
~GDir();
GDirEntry *getNextEntry();
void rewind();
}
#endif
-char *copyString(char *s) {
+char *copyString(const char *s) {
char *s1;
s1 = (char *)gmalloc(strlen(s) + 1);
/*
* Allocate memory and copy a string into it.
*/
-extern char *copyString(char *s);
+extern char *copyString(const char *s);
#ifdef __cplusplus
}
#ifndef GTYPES_H
#define GTYPES_H
+#define HAVE_LIBCUPS
+
/*
* These have stupid names to avoid conflicts with some (but not all)
* C++ compilers which define them.
#include <stdlib.h>
#include <stddef.h>
#include <string.h>
-#include <config.h>
#include "parseargs.h"
#include "GString.h"
#include "gmem.h"
#include "Params.h"
#include "Error.h"
#include "config.h"
-#include <cups/cups.h>
+#ifdef HAVE_LIBCUPS
+# include <cups/cups.h>
+#endif /* HAVE_LIBCUPS */
+
+static int firstPage = 1;
+static int lastPage = 0;
+static GBool noEmbedFonts = gFalse;
+static GBool doForm = gFalse;
+static char userPassword[33] = "";
+static GBool printVersion = gFalse;
+static GBool printHelp = gFalse;
+
+static ArgDesc argDesc[] = {
+ {"-f", argInt, &firstPage, 0,
+ "first page to print"},
+ {"-l", argInt, &lastPage, 0,
+ "last page to print"},
+ {"-paperw", argInt, &paperWidth, 0,
+ "paper width, in points"},
+ {"-paperh", argInt, &paperHeight, 0,
+ "paper height, in points"},
+ {"-level1", argFlag, &psOutLevel1, 0,
+ "generate Level 1 PostScript"},
+ {"-level1sep", argFlag, &psOutLevel1Sep, 0,
+ "generate Level 1 separable PostScript"},
+ {"-eps", argFlag, &psOutEPS, 0,
+ "generate Encapsulated PostScript (EPS)"},
+#if OPI_SUPPORT
+ {"-opi", argFlag, &psOutOPI, 0,
+ "generate OPI comments"},
+#endif
+ {"-noemb", argFlag, &noEmbedFonts, 0,
+ "don't embed Type 1 fonts"},
+ {"-form", argFlag, &doForm, 0,
+ "generate a PostScript form"},
+ {"-upw", argString, userPassword, sizeof(userPassword),
+ "user password (for encrypted files)"},
+ {"-q", argFlag, &errQuiet, 0,
+ "don't print any messages or errors"},
+ {"-v", argFlag, &printVersion, 0,
+ "print copyright and version info"},
+ {"-h", argFlag, &printHelp, 0,
+ "print usage information"},
+ {"-help", argFlag, &printHelp, 0,
+ "print usage information"},
+ {NULL}
+};
int main(int argc, char *argv[]) {
- PDFDoc *doc;
- GString *fileName;
- PSOutputDev *psOut;
+ PDFDoc *doc;
+ GString *fileName;
+ GString *psFileName;
+ GString *userPW;
+ PSOutputDev *psOut;
+ GBool ok;
+ char *p;
+#ifdef HAVE_LIBCUPS
int num_options;
cups_option_t *options;
ppd_file_t *ppd;
ppd_size_t *size;
FILE *fp;
+ const char *server_root;
char tempfile[1024];
char buffer[8192];
int bytes;
- // Make sure status messages are not buffered...
- setbuf(stderr, NULL);
+ // See if we are being run as a filter...
+ if (getenv("PPD") && getenv("SOFTWARE")) {
+ // Yes, make sure status messages are not buffered...
+ setbuf(stderr, NULL);
- // Make sure we have the right number of arguments for CUPS!
- if (argc < 6 || argc > 7)
- {
- fputs("Usage: pdftops job user title copies options [filename]\n", stderr);
- return (1);
- }
+ // Send all error messages...
+ errQuiet = 0;
- // Copy stdin if needed...
- if (argc == 6)
- {
- if ((fp = fopen(cupsTempFile(tempfile, sizeof(tempfile)), "w")) == NULL)
- {
- perror("ERROR: Unable to copy PDF file");
+ // Make sure we have the right number of arguments for CUPS!
+ if (argc < 6 || argc > 7) {
+ fputs("Usage: pdftops job user title copies options [filename]\n", stderr);
return (1);
}
- fprintf(stderr, "DEBUG: pdftops - copying to temp print file \"%s\"\n",
- tempfile);
+ // Copy stdin if needed...
+ if (argc == 6) {
+ if ((fp = fopen(cupsTempFile(tempfile, sizeof(tempfile)), "w")) == NULL) {
+ perror("ERROR: Unable to copy PDF file");
+ return (1);
+ }
- while ((bytes = fread(buffer, 1, sizeof(buffer), stdin)) > 0)
- fwrite(buffer, 1, bytes, fp);
- fclose(fp);
+ fprintf(stderr, "DEBUG: pdftops - copying to temp print file \"%s\"\n",
+ tempfile);
- fileName = new GString(tempfile);
- }
- else
- {
- fileName = new GString(argv[6]);
+ while ((bytes = fread(buffer, 1, sizeof(buffer), stdin)) > 0)
+ fwrite(buffer, 1, bytes, fp);
+ fclose(fp);
+
+ fileName = new GString(tempfile);
+ } else {
+ fileName = new GString(argv[6]);
+ tempfile[0] = '\0';
+ }
+ } else {
tempfile[0] = '\0';
+#endif // HAVE_LIBCUPS
+ // parse args
+ ok = parseArgs(argDesc, &argc, argv);
+ if (!ok || argc < 2 || argc > 3 || printVersion || printHelp) {
+ fprintf(stderr, "pdftops version %s\n", xpdfVersion);
+ fprintf(stderr, "%s\n", xpdfCopyright);
+ if (!printVersion) {
+ printUsage("pdftops", "<PDF-file> [<PS-file>]", argDesc);
+ }
+ exit(1);
+ }
+ if (psOutLevel1 && psOutLevel1Sep) {
+ fprintf(stderr, "Error: use -level1 or -level1sep, not both.\n");
+ exit(1);
+ }
+ if (doForm && (psOutLevel1 || psOutLevel1Sep)) {
+ fprintf(stderr, "Error: forms are only available with Level 2 output.\n");
+ exit(1);
+ }
+ fileName = new GString(argv[1]);
+#ifdef HAVE_LIBCUPS
}
// Get PPD and initialize options as needed...
- if ((ppd = ppdOpenFile(getenv("PPD"))) != NULL)
- {
+ if ((ppd = ppdOpenFile(getenv("PPD"))) != NULL) {
fprintf(stderr, "DEBUG: pdftops - opened PPD file \"%s\"...\n", getenv("PPD"));
ppdMarkDefaults(ppd);
cupsMarkOptions(ppd, num_options, options);
cupsFreeOptions(num_options, options);
- if ((size = ppdPageSize(ppd, NULL)) != NULL)
- {
+ if ((size = ppdPageSize(ppd, NULL)) != NULL) {
paperWidth = (int)size->width;
paperHeight = (int)size->length;
}
ppdClose(ppd);
}
+#endif // HAVE_LIBCUPS
// init error file
errorInit();
// read config file
- initParams(CUPS_SERVERROOT "/xpdf.conf");
+#ifdef HAVE_LIBCUPS
+ if ((server_root = getenv("CUPS_SERVERROOT")) != NULL) {
+ sprintf(tempfile, "%s/pdftops.conf", server_root);
+ initParams(tempfile);
+ } else
+#endif /* HAVE_LIBCUPS */
+ initParams(xpdfConfigFile);
// open PDF file
xref = NULL;
- doc = new PDFDoc(fileName, NULL);
+ if (userPassword[0]) {
+ userPW = new GString(userPassword);
+ } else {
+ userPW = NULL;
+ }
+ doc = new PDFDoc(fileName, userPW);
+ if (userPW) {
+ delete userPW;
+ }
if (!doc->isOk()) {
goto err1;
}
goto err1;
}
+#ifdef HAVE_LIBCUPS
+ if (getenv("PPD") && getenv("SOFTWARE")) {
+ // CUPS always needs every page and writes to stdout...
+ psFileName = new GString("-");
+ firstPage = 1;
+ lastPage = doc->getNumPages();
+ } else {
+#endif // HAVE_LIBCUPS
+
+ // construct PostScript file name
+ if (argc == 3) {
+ psFileName = new GString(argv[2]);
+ } else {
+ p = fileName->getCString() + fileName->getLength() - 4;
+ if (!strcmp(p, ".pdf") || !strcmp(p, ".PDF"))
+ psFileName = new GString(fileName->getCString(),
+ fileName->getLength() - 4);
+ else
+ psFileName = fileName->copy();
+ psFileName->append(psOutEPS ? ".eps" : ".ps");
+ }
+
+ // get page range
+ if (firstPage < 1)
+ firstPage = 1;
+ if (lastPage < 1 || lastPage > doc->getNumPages())
+ lastPage = doc->getNumPages();
+ if (doForm)
+ lastPage = firstPage;
+
+ // check for multi-page EPS
+ if (psOutEPS && firstPage != lastPage) {
+ error(-1, "EPS files can only contain one page.");
+ goto err2;
+ }
+#ifdef HAVE_LIBCUPS
+ }
+#endif // HAVE_LIBCUPS
+
// write PostScript file
- psOut = new PSOutputDev("-", doc->getCatalog(), 1, doc->getNumPages(), 1, 0);
+ psOut = new PSOutputDev(psFileName->getCString(), doc->getCatalog(),
+ firstPage, lastPage, !noEmbedFonts, doForm);
if (psOut->isOk())
- doc->displayPages(psOut, 1, doc->getNumPages(), 72, 0, gFalse);
-
+ doc->displayPages(psOut, firstPage, lastPage, 72, 0, gFalse);
delete psOut;
// clean up
- delete doc;
+ err2:
+ delete psFileName;
err1:
+ delete doc;
freeParams();
// check for memory leaks
Object::memCheck(stderr);
gMemReport(stderr);
+#ifdef HAVE_LIBCUPS
// Remove temp file if needed...
if (tempfile[0])
unlink(tempfile);
+#endif /* HAVE_LIBCUPS */
return 0;
}
#
-# "$Id: Makefile,v 1.8 2001/01/22 15:03:53 mike Exp $"
+# "$Id: Makefile,v 1.8.2.1 2001/05/13 18:38:30 mike Exp $"
#
# PPD file makefile for the Common UNIX Printing System (CUPS).
#
# PPD files...
#
-FILES = deskjet.ppd epson9.ppd epson24.ppd laserjet.ppd \
+FILES = deskjet.ppd deskjet2.ppd epson9.ppd epson24.ppd laserjet.ppd \
okidata9.ppd okidat24.ppd stcolor.ppd stphoto.ppd
+
#
# Make everything...
#
all:
+
#
# Clean all config and object files...
#
clean:
+
#
# Install files...
#
$(CHMOD) ugo+rx $(DATADIR)/model
$(INSTALL_DATA) $(FILES) $(DATADIR)/model
+
#
-# End of "$Id: Makefile,v 1.8 2001/01/22 15:03:53 mike Exp $".
+# End of "$Id: Makefile,v 1.8.2.1 2001/05/13 18:38:30 mike Exp $".
#
*PPD-Adobe: "4.3"
*%
-*% "$Id: deskjet.ppd,v 1.9 2001/02/22 16:48:12 mike Exp $"
+*% "$Id: deskjet.ppd,v 1.9.2.1 2001/05/13 18:38:30 mike Exp $"
*%
*% Sample HP DeskJet driver PPD file for the Common UNIX Printing
*% System (CUPS).
*cupsVersion: 1.1
*cupsManualCopies: True
*cupsFilter: "application/vnd.cups-raster 0 rastertohp"
+*cupsModelNumber: 1
*ModelName: "HP DeskJet Series"
*ShortNickName: "HP DeskJet Series"
*NickName: "HP DeskJet Series CUPS v1.1"
*Font ZapfChancery-MediumItalic: Standard "(001.007S)" Standard ROM
*Font ZapfDingbats: Special "(001.004S)" Standard ROM
*%
-*% End of "$Id: deskjet.ppd,v 1.9 2001/02/22 16:48:12 mike Exp $".
+*% End of "$Id: deskjet.ppd,v 1.9.2.1 2001/05/13 18:38:30 mike Exp $".
*%
*PPD-Adobe: "4.3"
*%
-*% "$Id: deskjet2.ppd,v 1.1 2001/04/23 19:52:31 mike Exp $"
+*% "$Id: deskjet2.ppd,v 1.1.2.1 2001/05/13 18:38:30 mike Exp $"
*%
*% Second sample HP DeskJet driver PPD file for the Common UNIX Printing
*% System (CUPS).
*Font ZapfChancery-MediumItalic: Standard "(001.007S)" Standard ROM
*Font ZapfDingbats: Special "(001.004S)" Standard ROM
*%
-*% End of "$Id: deskjet2.ppd,v 1.1 2001/04/23 19:52:31 mike Exp $".
+*% End of "$Id: deskjet2.ppd,v 1.1.2.1 2001/05/13 18:38:30 mike Exp $".
*%
*PPD-Adobe: "4.3"
*%
-*% "$Id: laserjet.ppd,v 1.7 2001/02/22 16:48:12 mike Exp $"
+*% "$Id: laserjet.ppd,v 1.7.2.1 2001/05/13 18:38:30 mike Exp $"
*%
*% Sample HP LaserJet driver PPD file for the Common UNIX Printing
*% System (CUPS).
*cupsVersion: 1.1
*cupsManualCopies: False
*cupsFilter: "application/vnd.cups-raster 0 rastertohp"
+*cupsModelNumber: 0
*ModelName: "HP LaserJet Series"
*ShortNickName: "HP LaserJet Series"
*NickName: "HP LaserJet Series CUPS v1.1"
*Font ZapfChancery-MediumItalic: Standard "(001.007S)" Standard ROM
*Font ZapfDingbats: Special "(001.004S)" Standard ROM
*%
-*% End of "$Id: laserjet.ppd,v 1.7 2001/02/22 16:48:12 mike Exp $".
+*% End of "$Id: laserjet.ppd,v 1.7.2.1 2001/05/13 18:38:30 mike Exp $".
*%
#
-# "$Id: Makefile,v 1.31 2001/02/02 16:37:45 mike Exp $"
+# "$Id: Makefile,v 1.31.2.1 2001/05/13 18:38:31 mike Exp $"
#
# GNU Ghostscript makefile for the Common UNIX Printing System (CUPS).
#
include ../Makedefs
-#
-# Updated rules for Ghostscript, which can't use the same level of
-# optimization on many platforms...
-#
-
-.c.o:
- echo Compiling $<...
- $(CC) $(GSOPTIM) $(CFLAGS) -c $<
-
-
#
# Object files...
#
$(AR) $(ARFLAGS) $@ $(LIBOBJS)
$(RANLIB) $@
-gdevcups.o: ../filter/raster.h
-$(LIBOBJS): arch.h ../config.h ../Makedefs
-
#
# pstoraster - PostScript RIP filter.
echo Linking $@...
$(CC) $(LDFLAGS) -o pstoraster pstoraster.o libgs.a \
$(LINKCUPSIMAGE) $(IMGLIBS) $(DSOLIBS) $(LIBS) -lm
-pstoraster.o: arch.h ../config.h ../Makedefs
#
-# End of "$Id: Makefile,v 1.31 2001/02/02 16:37:45 mike Exp $".
+# Generate dependencies for Ghostscript source files...
+#
+
+depend:
+ rm -f Dependencies
+ touch Dependencies
+ for file in $(OBJS:.o=.c); do \
+ echo $$file; \
+ makedepend -a -fDependencies -I.. -Y $$file >/dev/null 2>&1; \
+ done
+
+
+#
+# Dependencies...
+#
+
+$(OBJS): ../Makedefs
+
+include Dependencies
+
+
+#
+# End of "$Id: Makefile,v 1.31.2.1 2001/05/13 18:38:31 mike Exp $".
#
GNU software to build or run it.
*/
-/*$Id: gdevm1.c,v 1.2 2000/03/08 23:14:23 mike Exp $ */
+/*$Id: gdevm1.c,v 1.2.2.1 2001/05/13 18:38:31 mike Exp $ */
/* Monobit "memory" (stored bitmap) device */
#include "memory_.h"
#include "gx.h"
* The indexing is (transparent, 0, 1, unused). */
private const copy_mode copy_modes[16] =
{
- {~0, COPY_FUNNY}, /* NN */
- {~0, COPY_AND}, /* N0 */
+ {~0UL, COPY_FUNNY}, /* NN */
+ {~0UL, COPY_AND}, /* N0 */
{0, COPY_OR}, /* N1 */
{0, 0}, /* unused */
{0, COPY_AND}, /* 0N */
{0, COPY_FUNNY}, /* 00 */
{0, COPY_STORE}, /* 01 */
{0, 0}, /* unused */
- {~0, COPY_OR}, /* 1N */
- {~0, COPY_STORE}, /* 10 */
+ {~0UL, COPY_OR}, /* 1N */
+ {~0UL, COPY_STORE}, /* 10 */
{0, COPY_FUNNY}, /* 11 */
{0, 0}, /* unused */
{0, 0}, /* unused */
% Ghostscript, as distributed by Aladdin Enterprises, does not require any
% GNU software to build or run it.
-% $Id: gs_fonts.ps,v 1.2 2000/03/08 23:14:29 mike Exp $
+% $Id: gs_fonts.ps,v 1.2.2.1 2001/05/13 18:38:31 mike Exp $
% Font initialization and management code.
% Define the default font.
{ pop pop
}
{ exch copystring exch
- DEBUG { ( ) print dup =only flush } if
+ DEBUG { dup =only (\n) print flush } if
1 index .definefontmap
.splitfilename pop true .scanfontdict 3 1 roll .growput
% Increment fontcount.
-/* Copyright (C) 1996, 1997, 1998 Aladdin Enterprises. All rights reserved.
+/*
+ Copyright 2001 by Easy Software Products
+ Copyright 1996, 1997, 1998 Aladdin Enterprises. All rights reserved.
This file is part of GNU Ghostscript.
GNU software to build or run it.
*/
-/*$Id: gstype2.c,v 1.1 2000/03/08 23:14:49 mike Exp $ */
+/*$Id: gstype2.c,v 1.1.2.1 2001/05/13 18:38:31 mike Exp $ */
/* Adobe Type 2 charstring interpreter */
#include "math_.h"
#include "memory_.h"
goto vstem;
case cx_vmoveto:
check_first_operator(csp > cstack);
- accum_y(*csp);
+ /*** MRS: This is the first of many macro invocations;
+ *** Since these are encased in {} (previously an
+ *** empty do while(0) loop), we don't need the
+ *** trailing semicolon...
+ ***/
+ accum_y(*csp)
move:if ((pcis->hint_next != 0 || path_is_drawing(sppath)))
apply_path_hints(pcis, true);
code = gx_path_add_point(sppath, ptx, pty);
vertical = true;
hvl:for (ap = cstack; ap <= csp; vertical = !vertical, ++ap) {
if (vertical)
- accum_y(*ap);
+ accum_y(*ap)
else
- accum_x(*ap);
+ accum_x(*ap)
code = gx_path_add_line(sppath, ptx, pty);
if (code < 0)
return code;
goto move;
case cx_hmoveto:
check_first_operator(csp > cstack);
- accum_x(*csp);
+ accum_x(*csp)
goto move;
case cx_vhcurveto:
vertical = true;
fixed ay0 = sppath->position.y - pty;
if (vertical)
- accum_y(ap[0]);
+ accum_y(ap[0])
else
- accum_x(ap[0]);
+ accum_x(ap[0])
pt1.x = ptx + ax0, pt1.y = pty + ay0;
accum_xy(ap[1], ap[2]);
pt2.x = ptx, pt2.y = pty;
if (ap + 4 == csp)
accum_xy(ap[3], ap[4]);
else
- accum_x(ap[3]);
+ accum_x(ap[3])
} else {
if (ap + 4 == csp)
accum_xy(ap[4], ap[3]);
else
- accum_y(ap[3]);
+ accum_y(ap[3])
}
code = gx_path_add_curve(sppath, pt1.x, pt1.y,
pt2.x, pt2.y, ptx, pty);
-/* Copyright (C) 1998 Aladdin Enterprises. All rights reserved.
+/*
+ Copyright 2001 by Easy Software Products.
+ Copyright 1998 Aladdin Enterprises. All rights reserved.
This file is part of GNU Ghostscript.
GNU software to build or run it.
*/
-/*$Id: gxclrast.c,v 1.1 2000/03/08 23:14:54 mike Exp $ */
+/*$Id: gxclrast.c,v 1.1.2.1 2001/05/13 18:38:32 mike Exp $ */
/* Command list interpreter/rasterizer */
#include "memory_.h"
#include "gx.h"
break;
case cmd_set_misc_data_x >> 6:
if (cb & 0x20)
- cmd_getw(data_x, cbp);
+ cmd_getw(data_x, cbp) /* MRS: No trailing ; */
else
data_x = 0;
data_x = (data_x << 5) + (cb & 0x1f);
bits->height = rep_height;
}
if (bd & 0x80)
- cmd_getw(bits->rep_shift, cbp);
+ cmd_getw(bits->rep_shift, cbp) /* MRS: No trailing ; */
else
bits->rep_shift = 0;
if_debug6('L', " depth=%d size=(%d,%d), rep_size=(%d,%d), rep_shift=%d\n",
GNU software to build or run it.
*/
-/*$Id: iparam.c,v 1.2 2000/03/08 23:15:14 mike Exp $ */
+/*$Id: iparam.c,v 1.2.2.1 2001/05/13 18:38:32 mike Exp $ */
/* Interpreter implementations of parameter dictionaries */
#include "memory_.h"
#include "string_.h"
case gs_param_type_array:
return ref_param_begin_write_collection(plist, pkey,
&pvalue->value.d,
- pvalue->type - gs_param_type_dict);
+ (gs_param_collection_type_t)(pvalue->type - gs_param_type_dict));
default:
return_error(e_typecheck);
}
-/* Copyright (C) 1993, 1994, 1996, 1997, 1998 Aladdin Enterprises. All rights reserved.
+/*
+ Copyright 2001 by Easy Software Products.
+ Copyright 1993, 1994, 1996, 1997, 1998 Aladdin Enterprises. All rights reserved.
This file is part of GNU Ghostscript.
GNU software to build or run it.
*/
-/*$Id: stdpre.h,v 1.2 2000/03/08 23:15:29 mike Exp $ */
+/*$Id: stdpre.h,v 1.2.2.1 2001/05/13 18:38:32 mike Exp $ */
/* Standard definitions for Aladdin Enterprises code not needing arch.h */
#ifndef stdpre_INCLUDED
* ...statements...
* END
*/
-#define BEGIN do {
-#define END } while (0)
+/*** MRS: If you didn't treat C like a macro language, maybe this wouldn't
+ *** be a problem; changed to { and } (which do work) to avoid
+ *** needless compiler warnings...
+ ***/
+#define BEGIN {
+#define END }
/*
* Define a handy macro for a statement that does nothing.
* We can't just use an empty statement, since this upsets some compilers.
*/
+/*** MRS: Fix DO_NOTHING to use a void statement. Again, not using
+ *** macros makes life easier...
+ ***/
#ifndef DO_NOTHING
-# define DO_NOTHING BEGIN END
+# define DO_NOTHING (void)stdout
#endif
/*
-/* Copyright (C) 1997, 1998 Aladdin Enterprises. All rights reserved.
+/*
+ Copyright 2001 by Easy Software Products.
+ Copyright 1997, 1998 Aladdin Enterprises. All rights reserved.
This file is part of GNU Ghostscript.
GNU software to build or run it.
*/
-/*$Id: zfunc.c,v 1.1 2000/03/08 23:15:38 mike Exp $ */
+/*$Id: zfunc.c,v 1.1.2.1 2001/05/13 18:38:33 mike Exp $ */
/* Generic PostScript language interface to Functions */
#include "memory_.h"
#include "ghost.h"
DO_NOTHING;
else {
if (diff > 0)
- push(diff); /* can't fail */
+ push(diff) /* can't fail */ /* MRS: No trailing ; */
else if (diff < 0) {
pop(-diff);
op = osp;
/*
- * "$Id: auth.c,v 1.41.2.1 2001/04/02 19:51:46 mike Exp $"
+ * "$Id: auth.c,v 1.41.2.2 2001/05/13 18:38:33 mike Exp $"
*
* Authorization routines for the Common UNIX Printing System (CUPS).
*
#if HAVE_LIBPAM
# include <security/pam_appl.h>
#endif /* HAVE_LIBPAM */
+#ifdef HAVE_USERSEC_H
+# include <usersec.h>
+#endif /* HAVE_USERSEC_H */
/*
#endif /* HAVE_LIBPAM */
+/*
+ * Local globals...
+ */
+
+#ifdef __hpux
+static client_t *auth_client; /* Current client being authenticated */
+#endif /* __hpux */
+
+
/*
* 'AddLocation()' - Add a location for authorization.
*/
for (i = NumLocations, loc = Locations; i > 0; i --, loc ++)
{
- DEBUG_printf(("Location %s Limit %x\n", loc->location, loc->limit));
+ LogMessage(L_DEBUG2, "FindBest: Location %s Limit %x",
+ loc->location, loc->limit);
if (loc->length > bestlen &&
strncmp(con->uri, loc->location, loc->length) == 0 &&
* Return the match, if any...
*/
+ LogMessage(L_DEBUG2, "FindBest: best = %s", best ? best->location : "NONE");
+
return (best);
}
pam_handle_t *pamh; /* PAM authentication handle */
int pamerr; /* PAM error code */
struct pam_conv pamdata; /* PAM conversation data */
+#elif defined(HAVE_USERSEC_H)
+ char *authmsg; /* Authentication message */
+ char *loginmsg; /* Login message */
+ int reenter; /* ??? */
#else
char *pass; /* Encrypted password */
# ifdef HAVE_SHADOW_H
};
+ LogMessage(L_DEBUG2, "IsAuthorized: URI = %s", con->uri);
+
/*
* Find a matching location; if there is no match then access is
* not authorized...
*/
if ((best = FindBest(con)) == NULL)
- {
- DEBUG_printf(("FindBest(%s, %s) failed!\n", states[con->http.state],
- con->uri));
-
return (HTTP_FORBIDDEN);
- }
/*
* Check host/ip-based accesses...
}
}
+ LogMessage(L_DEBUG2, "IsAuthorized: auth = %d, satisfy=%d...",
+ auth, best->satisfy);
+
if (auth == AUTH_DENY && best->satisfy == AUTH_SATISFY_ALL)
return (HTTP_FORBIDDEN);
*/
if (best->encryption >= HTTP_ENCRYPT_REQUIRED && !con->http.tls)
+ {
+ LogMessage(L_DEBUG2, "IsAuthorized: Need upgrade to TLS...");
return (HTTP_UPGRADE_REQUIRED);
+ }
#endif /* HAVE_LIBSSL */
/*
if (best->level == AUTH_ANON) /* Anonymous access - allow it */
return (HTTP_OK);
+ LogMessage(L_DEBUG2, "IsAuthorized: username = \"%s\" password = %d chars",
+ con->username, strlen(con->password));
DEBUG_printf(("IsAuthorized: username = \"%s\", password = \"%s\"\n",
con->username, con->password));
return (HTTP_UNAUTHORIZED);
}
- DEBUG_printf(("IsAuthorized: Checking \"%s\", address = %08x, hostname = \"%s\"\n",
- con->username, address, con->http.hostname));
+ LogMessage(L_DEBUG2, "IsAuthorized: Checking \"%s\", address = %08x, hostname = \"%s\"",
+ con->username, address, con->http.hostname);
if (strcasecmp(con->http.hostname, "localhost") != 0 ||
strncmp(con->http.fields[HTTP_FIELD_AUTHORIZATION], "Local", 5) != 0)
pamdata.conv = pam_func;
pamdata.appdata_ptr = con;
+# ifdef __hpux
+ /*
+ * Workaround for HP-UX bug in pam_unix; see pam_conv() below for
+ * more info...
+ */
+
+ auth_client = con;
+# endif /* __hpux */
+
+ DEBUG_printf(("IsAuthorized: Setting appdata_ptr = %p\n", con));
+
pamerr = pam_start("cups", con->username, &pamdata, &pamh);
if (pamerr != PAM_SUCCESS)
{
}
pam_end(pamh, PAM_SUCCESS);
+#elif defined(HAVE_USERSEC_H)
+ /*
+ * Use AIX authentication interface...
+ */
+
+ LogMessage(L_DEBUG, "IsAuthorized: AIX authenticate of username \"%s\"",
+ con->username);
+
+ reenter = 1;
+ if (authenticate(con->username, con->password, &reenter, &authmsg) != 0)
+ {
+ LogMessage(L_DEBUG, "IsAuthorized: Unable to authenticate username \"%s\": %s",
+ con->username, strerror(errno));
+ return (HTTP_UNAUTHORIZED);
+ }
#else
# ifdef HAVE_SHADOW_H
spw = getspnam(con->username);
* OK, the password isn't blank, so compare with what came from the client...
*/
- DEBUG_printf(("IsAuthorized: pw_passwd = %s, crypt = %s\n",
- pw->pw_passwd, crypt(con->password, pw->pw_passwd)));
+ LogMessage(L_DEBUG2, "IsAuthorized: pw_passwd = %s, crypt = %s",
+ pw->pw_passwd, crypt(con->password, pw->pw_passwd));
pass = crypt(con->password, pw->pw_passwd);
# ifdef HAVE_SHADOW_H
if (spw != NULL)
{
- DEBUG_printf(("IsAuthorized: sp_pwdp = %s, crypt = %s\n",
- spw->sp_pwdp, crypt(con->password, spw->sp_pwdp)));
+ LogMessage(L_DEBUG2, "IsAuthorized: sp_pwdp = %s, crypt = %s",
+ spw->sp_pwdp, crypt(con->password, spw->sp_pwdp));
pass = crypt(con->password, spw->sp_pwdp);
* any valid user is OK...
*/
+ LogMessage(L_DEBUG2, "IsAuthorized: Checking user membership...");
+
if (best->num_names == 0)
return (HTTP_OK);
* Check to see if this user is in any of the named groups...
*/
+ LogMessage(L_DEBUG2, "IsAuthorized: Checking group membership...");
+
for (i = 0; i < best->num_names; i ++)
{
grp = getgrnam(best->names[i]);
* The user isn't part of the specified group, so deny access...
*/
- DEBUG_puts("IsAuthorized: user not in group!");
+ LogMessage(L_DEBUG2, "IsAuthorized: user not in group!");
return (HTTP_UNAUTHORIZED);
}
* Answer all of the messages...
*/
+ DEBUG_printf(("pam_func: appdata_ptr = %p\n", appdata_ptr));
+
+#ifdef __hpux
+ /*
+ * Apparently some versions of HP-UX 11 have a broken pam_unix security
+ * module. This is a workaround...
+ */
+
+ client = auth_client;
+ (void)appdata_ptr;
+#else
client = (client_t *)appdata_ptr;
+#endif /* __hpux */
for (i = 0; i < num_msg; i ++)
+ {
+ DEBUG_printf(("pam_func: Message = \"%s\"\n", msg[i]->msg));
+
switch (msg[i]->msg_style)
{
case PAM_PROMPT_ECHO_ON:
+ DEBUG_printf(("pam_func: PAM_PROMPT_ECHO_ON, returning \"%s\"...\n",
+ client->username));
replies[i].resp_retcode = PAM_SUCCESS;
replies[i].resp = strdup(client->username);
break;
case PAM_PROMPT_ECHO_OFF:
+ DEBUG_printf(("pam_func: PAM_PROMPT_ECHO_OFF, returning \"%s\"...\n",
+ client->password));
replies[i].resp_retcode = PAM_SUCCESS;
replies[i].resp = strdup(client->password);
break;
case PAM_TEXT_INFO:
+ DEBUG_puts("pam_func: PAM_TEXT_INFO...");
+ replies[i].resp_retcode = PAM_SUCCESS;
+ replies[i].resp = NULL;
+ break;
+
case PAM_ERROR_MSG:
+ DEBUG_puts("pam_func: PAM_ERROR_MSG...");
replies[i].resp_retcode = PAM_SUCCESS;
replies[i].resp = NULL;
break;
default:
+ DEBUG_printf(("pam_func: Unknown PAM message %d...\n",
+ msg[i]->msg_style));
free(replies);
return (PAM_CONV_ERR);
}
+ }
/*
* Return the responses back to PAM...
/*
- * End of "$Id: auth.c,v 1.41.2.1 2001/04/02 19:51:46 mike Exp $".
+ * End of "$Id: auth.c,v 1.41.2.2 2001/05/13 18:38:33 mike Exp $".
*/
/*
- * "$Id: cert.c,v 1.7 2001/03/06 14:23:15 mike Exp $"
+ * "$Id: cert.c,v 1.7.2.1 2001/05/13 18:38:34 mike Exp $"
*
* Authentication certificate routines for the Common UNIX
* Printing System (CUPS).
fchmod(fileno(fp), 0440);
if ((grp = getgrnam(SystemGroup)) == NULL)
- fchown(fileno(fp), 0, 0);
+ fchown(fileno(fp), getuid(), 0);
else
- fchown(fileno(fp), 0, grp->gr_gid);
+ fchown(fileno(fp), getuid(), grp->gr_gid);
endgrent();
/*
- * End of "$Id: cert.c,v 1.7 2001/03/06 14:23:15 mike Exp $".
+ * End of "$Id: cert.c,v 1.7.2.1 2001/05/13 18:38:34 mike Exp $".
*/
/*
- * "$Id: client.c,v 1.91.2.1 2001/04/02 19:51:47 mike Exp $"
+ * "$Id: client.c,v 1.91.2.2 2001/05/13 18:38:34 mike Exp $"
*
* Client routines for the Common UNIX Printing System (CUPS) scheduler.
*
}
}
- if ((strcasecmp(con->http.fields[HTTP_FIELD_CONNECTION], "Upgrade") == 0 ||
- (best != NULL && best->encryption == HTTP_ENCRYPT_ALWAYS)) &&
+ if (strcasecmp(con->http.fields[HTTP_FIELD_CONNECTION], "Upgrade") == 0 &&
con->http.tls == NULL)
{
#ifdef HAVE_LIBSSL
}
httpPrintf(HTTP(con), "Connection: Upgrade\r\n");
- httpPrintf(HTTP(con), "Upgrade: TLS/1.0,SSL/2.0,SSL/3.0\r\n");
+ httpPrintf(HTTP(con), "Upgrade: TLS/1.0,HTTP/1.1\r\n");
httpPrintf(HTTP(con), "Content-Length: 0\r\n");
httpPrintf(HTTP(con), "\r\n");
}
else
{
- if ((status = IsAuthorized(con)) == HTTP_UPGRADE_REQUIRED)
+ if (strcasecmp(con->http.fields[HTTP_FIELD_CONNECTION], "Upgrade") == 0 &&
+ con->http.tls == NULL)
{
#ifdef HAVE_LIBSSL
/*
}
httpPrintf(HTTP(con), "Connection: Upgrade\r\n");
- httpPrintf(HTTP(con), "Upgrade: TLS/1.0,SSL/2.0,SSL/3.0\r\n");
+ httpPrintf(HTTP(con), "Upgrade: TLS/1.0,HTTP/1.1\r\n");
httpPrintf(HTTP(con), "Content-Length: 0\r\n");
httpPrintf(HTTP(con), "\r\n");
}
#endif /* HAVE_LIBSSL */
}
- else if (status != HTTP_OK)
+
+ if ((status = IsAuthorized(con)) != HTTP_OK)
{
SendError(con, status);
CloseClient(con);
close(fd);
- LogMessage(L_DEBUG, "SendCommand() %d command=\"%s\" file=%d pipe_pid=%d",
- con->http.fd, command, con->file, con->pipe_pid);
+ LogMessage(L_INFO, "Started \"%s\" (pid=%d)", command, con->pipe_pid);
+
+ LogMessage(L_DEBUG, "SendCommand() %d file=%d", con->http.fd, con->file);
if (con->pipe_pid == 0)
return (0);
#ifdef HAVE_LIBSSL
if (code == HTTP_UPGRADE_REQUIRED)
- {
if (httpPrintf(HTTP(con), "Connection: Upgrade\r\n") < 0)
return (0);
- if (httpPrintf(HTTP(con), "Upgrade: TLS/1.0,SSL/2.0,SSL/3.0\r\n") < 0)
- return (0);
- }
+ if (httpPrintf(HTTP(con), "Upgrade: TLS/1.0,HTTP/1.1\r\n") < 0)
+ return (0);
#endif /* HAVE_LIBSSL */
if (con->http.version >= HTTP_1_1 && !con->http.keep_alive)
/*
- * End of "$Id: client.c,v 1.91.2.1 2001/04/02 19:51:47 mike Exp $".
+ * End of "$Id: client.c,v 1.91.2.2 2001/05/13 18:38:34 mike Exp $".
*/
/*
- * "$Id: cups-lpd.c,v 1.24.2.1 2001/04/02 19:51:48 mike Exp $"
+ * "$Id: cups-lpd.c,v 1.24.2.2 2001/05/13 18:38:34 mike Exp $"
*
* Line Printer Daemon interface for the Common UNIX Printing System (CUPS).
*
* Setup a connection and request data...
*/
- if ((http = httpConnect(cupsServer(), ippPort())) == NULL)
+ if ((http = httpConnectEncrypt(cupsServer(), ippPort(),
+ cupsEncryption())) == NULL)
{
syslog(LOG_ERR, "Unable to connect to server: %s", strerror(errno));
return (0);
* Try connecting to the local server...
*/
- if ((http = httpConnect(cupsServer(), ippPort())) == NULL)
+ if ((http = httpConnectEncrypt(cupsServer(), ippPort(),
+ cupsEncryption())) == NULL)
return (1);
language = cupsLangDefault();
* Try connecting to the local server...
*/
- if ((http = httpConnect(cupsServer(), ippPort())) == NULL)
+ if ((http = httpConnectEncrypt(cupsServer(), ippPort(),
+ cupsEncryption())) == NULL)
return (1);
/*
/*
- * End of "$Id: cups-lpd.c,v 1.24.2.1 2001/04/02 19:51:48 mike Exp $".
+ * End of "$Id: cups-lpd.c,v 1.24.2.2 2001/05/13 18:38:34 mike Exp $".
*/
/*
- * "$Id: cups-polld.c,v 1.5 2001/01/22 15:03:59 mike Exp $"
+ * "$Id: cups-polld.c,v 1.5.2.1 2001/05/13 18:38:35 mike Exp $"
*
* Polling daemon for the Common UNIX Printing System (CUPS).
*
* Open a connection to the server...
*/
- if ((http = httpConnect(argv[1], atoi(argv[2]))) == NULL)
+ if ((http = httpConnectEncrypt(argv[1], atoi(argv[2]),
+ cupsEncryption())) == NULL)
{
perror("cups-polld");
return (1);
/*
- * End of "$Id: cups-polld.c,v 1.5 2001/01/22 15:03:59 mike Exp $".
+ * End of "$Id: cups-polld.c,v 1.5.2.1 2001/05/13 18:38:35 mike Exp $".
*/
/*
- * "$Id: dirsvc.c,v 1.73.2.1 2001/04/02 19:51:48 mike Exp $"
+ * "$Id: dirsvc.c,v 1.73.2.2 2001/05/13 18:38:35 mike Exp $"
*
* Directory services routines for the Common UNIX Printing System (CUPS).
*
*sptr; /* Pointer into ServerName */
printer_t *p, /* Printer information */
*pclass, /* Printer class */
- *first; /* First printer in class */
+ *first, /* First printer in class */
+ *next; /* Next printer in list */
/*
for (p = Printers, len = 0, offset = 0, first = NULL;
p != NULL;
- p = p->next)
+ p = next)
{
+ /*
+ * Get next printer in list...
+ */
+
+ next = p->next;
+
/*
* Skip classes...
*/
/*
- * End of "$Id: dirsvc.c,v 1.73.2.1 2001/04/02 19:51:48 mike Exp $".
+ * End of "$Id: dirsvc.c,v 1.73.2.2 2001/05/13 18:38:35 mike Exp $".
*/
/*
- * "$Id: ipp.c,v 1.127.2.1 2001/04/02 19:51:48 mike Exp $"
+ * "$Id: ipp.c,v 1.127.2.2 2001/05/13 18:38:35 mike Exp $"
*
* IPP routines for the Common UNIX Printing System (CUPS) scheduler.
*
break;
case CUPS_ACCEPT_JOBS :
+ case IPP_ENABLE_PRINTER :
accept_jobs(con, uri);
break;
case CUPS_REJECT_JOBS :
+ case IPP_DISABLE_PRINTER :
reject_jobs(con, uri);
break;
add_queued_job_count(client_t *con, /* I - Client connection */
printer_t *p) /* I - Printer or class */
{
- cups_ptype_t dtype; /* Destination type */
int count; /* Number of jobs on destination */
LogMessage(L_DEBUG2, "add_queued_job_count(%d, %s)\n", con->http.fd,
p->name);
- dtype = p->type & CUPS_PRINTER_CLASS;
-
count = GetPrinterJobCount(p->name);
ippAddInteger(con->response, IPP_TAG_PRINTER, IPP_TAG_INTEGER,
ipp_attribute_t *toattr; /* Destination attribute */
- LogMessage(L_DEBUG2, "copy_attribute(%p, %s)\n", to, attr->name);
+ LogMessage(L_DEBUG2, "copy_attribute(%p, %s)\n", to,
+ attr->name ? attr->name : "(null)");
switch (attr->value_tag)
{
case IPP_TAG_LANGUAGE :
case IPP_TAG_MIMETYPE :
toattr = ippAddStrings(to, attr->group_tag,
- attr->value_tag | IPP_TAG_COPY,
+ (ipp_tag_t)(attr->value_tag | IPP_TAG_COPY),
attr->name, attr->num_values, NULL,
NULL);
case IPP_TAG_TEXTLANG :
case IPP_TAG_NAMELANG :
toattr = ippAddStrings(to, attr->group_tag,
- attr->value_tag | IPP_TAG_COPY,
+ (ipp_tag_t)(attr->value_tag | IPP_TAG_COPY),
attr->name, attr->num_values, NULL, NULL);
for (i = 0; i < attr->num_values; i ++)
attr->values[1].string.text = strdup(printer->job_sheets[1]);
}
+ job->job_sheets = attr;
+
/*
* Enforce classification level if set...
*/
attr->values[1].string.text = strdup(printer->job_sheets[1]);
}
+ job->job_sheets = attr;
+
/*
* Enforce classification level if set...
*/
/*
- * End of "$Id: ipp.c,v 1.127.2.1 2001/04/02 19:51:48 mike Exp $".
+ * End of "$Id: ipp.c,v 1.127.2.2 2001/05/13 18:38:35 mike Exp $".
*/
/*
- * "$Id: job.c,v 1.124.2.1 2001/04/02 19:51:49 mike Exp $"
+ * "$Id: job.c,v 1.124.2.2 2001/05/13 18:38:36 mike Exp $"
*
* Job management routines for the Common UNIX Printing System (CUPS).
*
if (current->state->values[0].integer == IPP_JOB_PENDING)
{
if ((pclass = FindClass(current->dest)) != NULL)
- printer = FindAvailablePrinter(current->dest);
+ {
+ /*
+ * If the class is remote, just pass it to the remote server...
+ */
+
+ if (pclass->type & CUPS_PRINTER_REMOTE)
+ printer = pclass;
+ else
+ printer = FindAvailablePrinter(current->dest);
+ }
else
printer = FindPrinter(current->dest);
*optptr; /* Pointer to options */
ipp_attribute_t *attr; /* Current attribute */
int pid; /* Process ID of new filter process */
+ int banner_page; /* 1 if banner page, 0 otherwise */
int statusfds[2], /* Pipes used between the filters and scheduler */
filterfds[2][2];/* Pipes used between the filters */
char *argv[8], /* Filter command-line arguments */
if (current == NULL)
return;
- LogMessage(L_DEBUG, "StartJob() id = %d, file = %d", id,
- current->current_file);
+ LogMessage(L_DEBUG, "StartJob() id = %d, file = %d/%d", id,
+ current->current_file, current->num_files);
if (current->num_files == 0)
{
if (current->current_file == 0)
set_time(current, "time-at-processing");
+ /*
+ * Determine if we are printing a banner page or not...
+ */
+
+ if (current->job_sheets == NULL)
+ LogMessage(L_DEBUG, "No job-sheets attribute.");
+ else if (current->job_sheets->num_values == 1)
+ LogMessage(L_DEBUG, "job-sheets=%s",
+ current->job_sheets->values[0].string.text);
+ else
+ LogMessage(L_DEBUG, "job-sheets=%s,%s",
+ current->job_sheets->values[0].string.text,
+ current->job_sheets->values[1].string.text);
+
+ if (printer->type & CUPS_PRINTER_REMOTE)
+ banner_page = 0;
+ else if (current->job_sheets == NULL)
+ banner_page = 0;
+ else if (strcasecmp(current->job_sheets->values[0].string.text, "none") != 0 &&
+ current->current_file == 0)
+ banner_page = 1;
+ else if (current->job_sheets->num_values > 1 &&
+ strcasecmp(current->job_sheets->values[1].string.text, "none") != 0 &&
+ current->current_file == (current->num_files - 1))
+ banner_page = 1;
+ else
+ banner_page = 0;
+
+ LogMessage(L_DEBUG, "banner_page = %d", banner_page);
+
/*
* Building the options string is harder than it needs to be, but
* for the moment we need to pass strings for command-line args and
* Don't use the # copies attribute if we are printing the job sheets...
*/
- if ((printer->type & CUPS_PRINTER_REMOTE) ||
- current->job_sheets == NULL ||
- ((strcasecmp(current->job_sheets->values[0].string.text, "none") == 0 ||
- current->current_file != 0) &&
- (current->job_sheets->num_values == 1 ||
- strcasecmp(current->job_sheets->values[1].string.text, "none") == 0 ||
- current->current_file != (current->num_files - 1))))
+ if (!banner_page)
sprintf(copies, "%d", attr->values[0].integer);
}
else if (strcmp(attr->name, "job-name") == 0 &&
strcmp(attr->name, "job-priority") != 0)
continue;
+ if (strcmp(attr->name, "page-label") == 0 &&
+ banner_page)
+ continue;
+
/*
* Otherwise add them to the list...
*/
snprintf(tmpdir, sizeof(tmpdir), "TMPDIR=%s", TempDir);
snprintf(datadir, sizeof(datadir), "CUPS_DATADIR=%s", DataDir);
snprintf(fontpath, sizeof(fontpath), "CUPS_FONTPATH=%s", FontPath);
- if (Classification[0])
+ if (Classification[0] && !banner_page)
snprintf(classification, sizeof(classification), "CLASSIFICATION=%s",
Classification);
else
if (current->status < 0)
SetPrinterState(current->printer, IPP_PRINTER_STOPPED);
- else
+ else if (current->printer->state != IPP_PRINTER_STOPPED)
SetPrinterState(current->printer, IPP_PRINTER_IDLE);
LogMessage(L_DEBUG, "StopJob: printer state is %d", current->printer->state);
* Figure out the logging level...
*/
- if (strncmp(buffer, "ERROR:", 6) == 0)
- {
- loglevel = L_ERROR;
- message = buffer + 6;
- }
if (strncmp(buffer, "EMERG:", 6) == 0)
{
loglevel = L_EMERG;
message = buffer + 6;
}
- if (strncmp(buffer, "ALERT:", 6) == 0)
+ else if (strncmp(buffer, "ALERT:", 6) == 0)
{
loglevel = L_ALERT;
message = buffer + 6;
}
- if (strncmp(buffer, "CRIT:", 5) == 0)
+ else if (strncmp(buffer, "CRIT:", 5) == 0)
{
loglevel = L_CRIT;
message = buffer + 5;
}
- if (strncmp(buffer, "ERROR:", 6) == 0)
+ else if (strncmp(buffer, "ERROR:", 6) == 0)
{
loglevel = L_ERROR;
message = buffer + 6;
loglevel = L_WARN;
message = buffer + 8;
}
- if (strncmp(buffer, "NOTICE:", 6) == 0)
+ else if (strncmp(buffer, "NOTICE:", 6) == 0)
{
loglevel = L_NOTICE;
message = buffer + 6;
/*
- * End of "$Id: job.c,v 1.124.2.1 2001/04/02 19:51:49 mike Exp $".
+ * End of "$Id: job.c,v 1.124.2.2 2001/05/13 18:38:36 mike Exp $".
*/
/*
- * "$Id: main.c,v 1.57 2001/03/14 22:02:18 mike Exp $"
+ * "$Id: main.c,v 1.57.2.1 2001/05/13 18:38:37 mike Exp $"
*
* Scheduler main loop for the Common UNIX Printing System (CUPS).
*
* Log all sorts of debug info to help track down the problem.
*/
- LogMessage(L_ERROR, "select() failed - %s!", strerror(errno));
+ LogMessage(L_EMERG, "select() failed - %s!", strerror(errno));
strcpy(s, "InputSet =");
slen = 9;
if (FD_ISSET(i, &InputSet))
snprintf(sptr, sizeof(s) - slen, " %d", i);
- LogMessage(L_ERROR, s);
+ LogMessage(L_EMERG, s);
strcpy(s, "OutputSet =");
slen = 10;
if (FD_ISSET(i, &OutputSet))
snprintf(sptr, sizeof(s) - slen, " %d", i);
- LogMessage(L_ERROR, s);
+ LogMessage(L_EMERG, s);
for (i = 0, con = Clients; i < NumClients; i ++, con ++)
- LogMessage(L_ERROR, "Clients[%d] = %d, file = %d, state = %d",
+ LogMessage(L_EMERG, "Clients[%d] = %d, file = %d, state = %d",
i, con->http.fd, con->file, con->http.state);
for (i = 0, lis = Listeners; i < NumListeners; i ++, lis ++)
- LogMessage(L_ERROR, "Listeners[%d] = %d", i, lis->fd);
+ LogMessage(L_EMERG, "Listeners[%d] = %d", i, lis->fd);
- LogMessage(L_ERROR, "BrowseSocket = %d", BrowseSocket);
+ LogMessage(L_EMERG, "BrowseSocket = %d", BrowseSocket);
for (job = Jobs; job != NULL; job = job->next)
- LogMessage(L_ERROR, "Jobs[%d] = %d", job->id, job->pipe);
+ LogMessage(L_EMERG, "Jobs[%d] = %d", job->id, job->pipe);
break;
}
next = job->next;
if (job->pipe && FD_ISSET(job->pipe, &input))
+ {
+ /*
+ * Clear the input bit to avoid updating the next job
+ * using the same status pipe file descriptor...
+ */
+
+ FD_CLR(job->pipe, &input);
+
+ /*
+ * Read any status messages from the filters...
+ */
+
UpdateJob(job);
+ }
}
/*
/*
- * End of "$Id: main.c,v 1.57 2001/03/14 22:02:18 mike Exp $".
+ * End of "$Id: main.c,v 1.57.2.1 2001/05/13 18:38:37 mike Exp $".
*/
/*
- * "$Id: ppds.c,v 1.14 2001/01/22 15:04:01 mike Exp $"
+ * "$Id: ppds.c,v 1.14.2.1 2001/05/13 18:38:38 mike Exp $"
*
* PPD scanning routines for the Common UNIX Printing System (CUPS).
*
*ptr = '\0';
else if (strncasecmp(manufacturer, "agfa", 4) == 0)
strcpy(manufacturer, "AGFA");
- else if (strncasecmp(manufacturer, "ps-ipu", 6) == 0)
- strcpy(manufacturer, "Canon");
else if (strncasecmp(manufacturer, "herk", 4) == 0)
strcpy(manufacturer, "Linotype");
else
strcpy(manufacturer, "Seiko");
else if (strcasecmp(manufacturer, "fiery") == 0)
strcpy(manufacturer, "EFI");
+ else if (strcasecmp(manufacturer, "ps") == 0 ||
+ strcasecmp(manufacturer, "colorpass") == 0)
+ strcpy(manufacturer, "Canon");
else if (strncasecmp(manufacturer, "primera", 7) == 0)
strcpy(manufacturer, "Fargo");
+ else if (strcasecmp(manufacturer, "designjet") == 0)
+ strcpy(manufacturer, "HP");
}
/*
/*
- * End of "$Id: ppds.c,v 1.14 2001/01/22 15:04:01 mike Exp $".
+ * End of "$Id: ppds.c,v 1.14.2.1 2001/05/13 18:38:38 mike Exp $".
*/
/*
- * "$Id: printers.c,v 1.93.2.2 2001/04/11 00:24:14 mike Exp $"
+ * "$Id: printers.c,v 1.93.2.3 2001/05/13 18:38:38 mike Exp $"
*
* Printer routines for the Common UNIX Printing System (CUPS).
*
IPP_RESUME_PRINTER,
IPP_PURGE_JOBS,
IPP_SET_JOB_ATTRIBUTES,
+ IPP_ENABLE_PRINTER,
+ IPP_DISABLE_PRINTER,
CUPS_GET_DEFAULT,
CUPS_GET_PRINTERS,
CUPS_ADD_PRINTER,
next = current->next;
current->next = next->next;
next->next = current;
+ prev = next;
}
else
+ {
+ prev = current;
current = current->next;
+ }
}
while (did_swap);
}
/*
- * End of "$Id: printers.c,v 1.93.2.2 2001/04/11 00:24:14 mike Exp $".
+ * End of "$Id: printers.c,v 1.93.2.3 2001/05/13 18:38:38 mike Exp $".
*/
/*
- * "$Id: accept.c,v 1.11 2001/01/23 17:36:22 mike Exp $"
+ * "$Id: accept.c,v 1.11.2.1 2001/05/13 18:38:40 mike Exp $"
*
* "accept", "disable", "enable", and "reject" commands for the Common
* UNIX Printing System (CUPS).
httpClose(http);
if (argv[i][2] != '\0')
- http = httpConnect(argv[i] + 2, ippPort());
+ http = httpConnectEncrypt(argv[i] + 2, ippPort(), encryption);
else
{
i ++;
return (1);
}
- http = httpConnect(argv[i], ippPort());
+ http = httpConnectEncrypt(argv[i], ippPort(), encryption);
}
if (http == NULL)
}
if (http == NULL)
- http = httpConnect(hostname, ippPort());
+ http = httpConnectEncrypt(hostname, ippPort(), encryption);
if (http == NULL)
{
* Do the request and get back a response...
*/
- httpEncryption(http, encryption);
-
if ((response = cupsDoRequest(http, request, "/admin/")) != NULL)
{
if (response->request.status.status_code > IPP_OK_CONFLICT)
/*
- * End of "$Id: accept.c,v 1.11 2001/01/23 17:36:22 mike Exp $".
+ * End of "$Id: accept.c,v 1.11.2.1 2001/05/13 18:38:40 mike Exp $".
*/
/*
- * "$Id: cancel.c,v 1.19 2001/03/02 17:35:04 mike Exp $"
+ * "$Id: cancel.c,v 1.19.2.1 2001/05/13 18:38:40 mike Exp $"
*
* "cancel" command for the Common UNIX Printing System (CUPS).
*
httpClose(http);
if (argv[i][2] != '\0')
- http = httpConnect(argv[i] + 2, ippPort());
+ http = httpConnectEncrypt(argv[i] + 2, ippPort(), encryption);
else
{
i ++;
return (1);
}
else
- http = httpConnect(argv[i], ippPort());
+ http = httpConnectEncrypt(argv[i], ippPort(), encryption);
}
if (http == NULL)
*host++ = '\0';
- if ((http = httpConnect(host, ippPort())) == NULL)
+ if ((http = httpConnectEncrypt(host, ippPort(), encryption)) == NULL)
{
perror("cancel: Unable to connect to server");
return (1);
*/
if (http == NULL)
- if ((http = httpConnect(cupsServer(), ippPort())) == NULL)
+ if ((http = httpConnectEncrypt(cupsServer(), ippPort(),
+ encryption)) == NULL)
{
fputs("cancel: Unable to contact server!\n", stderr);
return (1);
* Do the request and get back a response...
*/
- httpEncryption(http, encryption);
-
if (op == IPP_PURGE_JOBS)
response = cupsDoRequest(http, request, "/admin/");
else
/*
- * End of "$Id: cancel.c,v 1.19 2001/03/02 17:35:04 mike Exp $".
+ * End of "$Id: cancel.c,v 1.19.2.1 2001/05/13 18:38:40 mike Exp $".
*/
/*
- * "$Id: lp.c,v 1.29 2001/03/09 14:26:54 mike Exp $"
+ * "$Id: lp.c,v 1.29.2.1 2001/05/13 18:38:40 mike Exp $"
*
* "lp" command for the Common UNIX Printing System (CUPS).
*
char uri[HTTP_MAX_URI]; /* URI for job */
- http = httpConnect(cupsServer(), ippPort());
+ http = httpConnectEncrypt(cupsServer(), ippPort(), cupsEncryption());
language = cupsLangDefault();
/*
- * End of "$Id: lp.c,v 1.29 2001/03/09 14:26:54 mike Exp $".
+ * End of "$Id: lp.c,v 1.29.2.1 2001/05/13 18:38:40 mike Exp $".
*/
/*
- * "$Id: lpadmin.c,v 1.22 2001/02/07 00:33:55 mike Exp $"
+ * "$Id: lpadmin.c,v 1.22.2.1 2001/05/13 18:38:41 mike Exp $"
*
* "lpadmin" command for the Common UNIX Printing System (CUPS).
*
case 'c' : /* Add printer to class */
if (!http)
{
- http = httpConnect(cupsServer(), ippPort());
+ http = httpConnectEncrypt(cupsServer(), ippPort(), encryption);
if (http == NULL)
{
perror("lpadmin: Unable to connect to server");
return (1);
}
-
- httpEncryption(http, encryption);
}
if (printer == NULL)
case 'd' : /* Set as default destination */
if (!http)
{
- http = httpConnect(cupsServer(), ippPort());
+ http = httpConnectEncrypt(cupsServer(), ippPort(), encryption);
if (http == NULL)
{
perror("lpadmin: Unable to connect to server");
return (1);
}
-
- httpEncryption(http, encryption);
}
if (argv[i][2])
httpClose(http);
if (argv[i][2] != '\0')
- http = httpConnect(argv[i] + 2, ippPort());
+ http = httpConnectEncrypt(argv[i] + 2, ippPort(), encryption);
else
{
i ++;
return (1);
}
else
- http = httpConnect(argv[i], ippPort());
+ http = httpConnectEncrypt(argv[i], ippPort(), encryption);
}
if (http == NULL)
return (1);
}
else
- {
- httpEncryption(http, encryption);
cupsSetServer(http->hostname);
- }
break;
case 'i' : /* Use the specified interface script */
if (!http)
{
- http = httpConnect(cupsServer(), ippPort());
+ http = httpConnectEncrypt(cupsServer(), ippPort(), encryption);
if (http == NULL)
{
perror("lpadmin: Unable to connect to server");
return (1);
}
-
- httpEncryption(http, encryption);
}
if (printer == NULL)
if (!http)
{
- http = httpConnect(cupsServer(), ippPort());
+ http = httpConnectEncrypt(cupsServer(), ippPort(), encryption);
if (http == NULL)
{
perror("lpadmin: Unable to connect to server");
return (1);
}
-
- httpEncryption(http, encryption);
}
enable_printer(http, printer);
case 'm' : /* Use the specified standard script/PPD file */
if (!http)
{
- http = httpConnect(cupsServer(), ippPort());
+ http = httpConnectEncrypt(cupsServer(), ippPort(), encryption);
if (http == NULL)
{
perror("lpadmin: Unable to connect to server");
return (1);
}
-
- httpEncryption(http, encryption);
}
if (printer == NULL)
case 'p' : /* Add/modify a printer */
if (!http)
{
- http = httpConnect(cupsServer(), ippPort());
+ http = httpConnectEncrypt(cupsServer(), ippPort(), encryption);
if (http == NULL)
{
perror("lpadmin: Unable to connect to server");
return (1);
}
-
- httpEncryption(http, encryption);
}
if (argv[i][2])
httpClose(http);
*host++ = '\0';
- if ((http = httpConnect(host, ippPort())) == NULL)
+ if ((http = httpConnectEncrypt(host, ippPort(), encryption)) == NULL)
{
perror("lpadmin: Unable to connect to server");
return (1);
}
-
- httpEncryption(http, encryption);
}
break;
case 'r' : /* Remove printer from class */
if (!http)
{
- http = httpConnect(cupsServer(), ippPort());
+ http = httpConnectEncrypt(cupsServer(), ippPort(), encryption);
if (http == NULL)
{
perror("lpadmin: Unable to connect to server");
return (1);
}
-
- httpEncryption(http, encryption);
}
if (printer == NULL)
case 'v' : /* Set the device-uri attribute */
if (!http)
{
- http = httpConnect(cupsServer(), ippPort());
+ http = httpConnectEncrypt(cupsServer(), ippPort(), encryption);
if (http == NULL)
{
perror("lpadmin: Unable to connect to server");
return (1);
}
-
- httpEncryption(http, encryption);
}
if (printer == NULL)
case 'x' : /* Delete a printer */
if (!http)
{
- http = httpConnect(cupsServer(), ippPort());
+ http = httpConnectEncrypt(cupsServer(), ippPort(), encryption);
if (http == NULL)
{
perror("lpadmin: Unable to connect to server");
return (1);
}
-
- httpEncryption(http, encryption);
}
if (argv[i][2])
httpClose(http);
*host++ = '\0';
- if ((http = httpConnect(host, ippPort())) == NULL)
+ if ((http = httpConnectEncrypt(host, ippPort(), encryption)) == NULL)
{
perror("lpadmin: Unable to connect to server");
return (1);
case 'D' : /* Set the printer-info attribute */
if (!http)
{
- http = httpConnect(cupsServer(), ippPort());
+ http = httpConnectEncrypt(cupsServer(), ippPort(), encryption);
if (http == NULL)
{
perror("lpadmin: Unable to connect to server");
return (1);
}
-
- httpEncryption(http, encryption);
}
if (printer == NULL)
case 'L' : /* Set the printer-location attribute */
if (!http)
{
- http = httpConnect(cupsServer(), ippPort());
+ http = httpConnectEncrypt(cupsServer(), ippPort(), encryption);
if (http == NULL)
{
perror("lpadmin: Unable to connect to server");
return (1);
}
-
- httpEncryption(http, encryption);
}
if (printer == NULL)
case 'P' : /* Use the specified PPD file */
if (!http)
{
- http = httpConnect(cupsServer(), ippPort());
+ http = httpConnectEncrypt(cupsServer(), ippPort(), encryption);
if (http == NULL)
{
perror("lpadmin: Unable to connect to server");
return (1);
}
-
- httpEncryption(http, encryption);
}
if (printer == NULL)
{
if (!http)
{
- http = httpConnect(cupsServer(), ippPort());
+ http = httpConnectEncrypt(cupsServer(), ippPort(), encryption);
if (http == NULL)
{
perror("lpadmin: Unable to connect to server");
return (1);
}
-
- httpEncryption(http, encryption);
}
if (printer == NULL)
/*
- * End of "$Id: lpadmin.c,v 1.22 2001/02/07 00:33:55 mike Exp $".
+ * End of "$Id: lpadmin.c,v 1.22.2.1 2001/05/13 18:38:41 mike Exp $".
*/
/*
- * "$Id: lpinfo.c,v 1.3 2001/01/23 17:36:23 mike Exp $"
+ * "$Id: lpinfo.c,v 1.3.2.1 2001/05/13 18:38:41 mike Exp $"
*
* "lpinfo" command for the Common UNIX Printing System (CUPS).
*
case 'm' : /* Show models */
if (!http)
{
- http = httpConnect(cupsServer(), ippPort());
+ http = httpConnectEncrypt(cupsServer(), ippPort(), encryption);
if (http == NULL)
{
perror("lpinfo: Unable to connect to server");
return (1);
}
-
- httpEncryption(http, encryption);
}
show_models(http, long_status);
case 'v' : /* Show available devices */
if (!http)
{
- http = httpConnect(cupsServer(), ippPort());
+ http = httpConnectEncrypt(cupsServer(), ippPort(), encryption);
if (http == NULL)
{
perror("lpinfo: Unable to connect to server");
return (1);
}
-
- httpEncryption(http, encryption);
}
show_devices(http, long_status);
httpClose(http);
if (argv[i][2] != '\0')
- http = httpConnect(argv[i] + 2, ippPort());
+ http = httpConnectEncrypt(argv[i] + 2, ippPort(), encryption);
else
{
i ++;
return (1);
}
- http = httpConnect(argv[i], ippPort());
+ http = httpConnectEncrypt(argv[i], ippPort(), encryption);
}
if (http == NULL)
perror("lpinfo: Unable to connect to server");
return (1);
}
-
- httpEncryption(http, encryption);
break;
default :
/*
- * End of "$Id: lpinfo.c,v 1.3 2001/01/23 17:36:23 mike Exp $".
+ * End of "$Id: lpinfo.c,v 1.3.2.1 2001/05/13 18:38:41 mike Exp $".
*/
/*
- * "$Id: lpmove.c,v 1.5 2001/01/23 17:36:24 mike Exp $"
+ * "$Id: lpmove.c,v 1.5.2.1 2001/05/13 18:38:41 mike Exp $"
*
* "lpmove" command for the Common UNIX Printing System (CUPS).
*
httpClose(http);
if (argv[i][2] != '\0')
- http = httpConnect(argv[i] + 2, ippPort());
+ http = httpConnectEncrypt(argv[i] + 2, ippPort(), encryption);
else
{
i ++;
return (1);
}
- http = httpConnect(argv[i], ippPort());
+ http = httpConnectEncrypt(argv[i], ippPort(), encryption);
}
if (http == NULL)
perror("lpmove: Unable to connect to server");
return (1);
}
-
- httpEncryption(http, encryption);
break;
default :
if (!http)
{
- http = httpConnect(cupsServer(), ippPort());
+ http = httpConnectEncrypt(cupsServer(), ippPort(), encryption);
if (http == NULL)
{
perror("lpmove: Unable to connect to server");
return (1);
}
-
- httpEncryption(http, encryption);
}
move_job(http, atoi(job), dest);
/*
- * End of "$Id: lpmove.c,v 1.5 2001/01/23 17:36:24 mike Exp $".
+ * End of "$Id: lpmove.c,v 1.5.2.1 2001/05/13 18:38:41 mike Exp $".
*/
/*
- * "$Id: lpstat.c,v 1.37 2001/01/26 15:29:59 mike Exp $"
+ * "$Id: lpstat.c,v 1.37.2.1 2001/05/13 18:38:41 mike Exp $"
*
* "lpstat" command for the Common UNIX Printing System (CUPS).
*
{
int i; /* Looping var */
http_t *http; /* Connection to server */
- char server[1024]; /* CUPS_SERVER environment variable */
int num_dests; /* Number of user destinations */
cups_dest_t *dests; /* User destinations */
int long_status; /* Long status report? */
case 'a' : /* Show acceptance status */
if (!http)
{
- http = httpConnect(cupsServer(), ippPort());
+ http = httpConnectEncrypt(cupsServer(), ippPort(), encryption);
if (http == NULL)
{
perror("lpstat: Unable to connect to server");
return (1);
}
-
- httpEncryption(http, encryption);
}
if (num_dests == 0)
case 'c' : /* Show classes and members */
if (!http)
{
- http = httpConnect(cupsServer(), ippPort());
+ http = httpConnectEncrypt(cupsServer(), ippPort(), encryption);
if (http == NULL)
{
perror("lpstat: Unable to connect to server");
return (1);
}
-
- httpEncryption(http, encryption);
}
if (argv[i][2] != '\0')
if (argv[i][2] != '\0')
{
- http = httpConnect(argv[i] + 2, ippPort());
- snprintf(server, sizeof(server), "CUPS_SERVER=%s", argv[i] + 2);
+ http = httpConnectEncrypt(argv[i] + 2, ippPort(), encryption);
+ cupsSetServer(argv[i] + 2);
}
else
{
return (1);
}
- http = httpConnect(argv[i], ippPort());
- snprintf(server, sizeof(server), "CUPS_SERVER=%s", argv[i] + 2);
+ http = httpConnectEncrypt(argv[i], ippPort(), encryption);
+ cupsSetServer(argv[i]);
}
- putenv(server);
if (http == NULL)
{
perror("lpstat: Unable to connect to server");
return (1);
}
-
- httpEncryption(http, encryption);
break;
case 'l' : /* Long status */
case 'o' : /* Show jobs by destination */
if (!http)
{
- http = httpConnect(cupsServer(), ippPort());
+ http = httpConnectEncrypt(cupsServer(), ippPort(), encryption);
if (http == NULL)
{
perror("lpstat: Unable to connect to server");
return (1);
}
-
- httpEncryption(http, encryption);
}
if (argv[i][2] != '\0')
case 'p' : /* Show printers */
if (!http)
{
- http = httpConnect(cupsServer(), ippPort());
+ http = httpConnectEncrypt(cupsServer(), ippPort(), encryption);
if (http == NULL)
{
perror("lpstat: Unable to connect to server");
return (1);
}
-
- httpEncryption(http, encryption);
}
if (num_dests == 0)
case 'r' : /* Show scheduler status */
if (!http)
{
- http = httpConnect(cupsServer(), ippPort());
+ http = httpConnectEncrypt(cupsServer(), ippPort(), encryption);
if (http == NULL)
{
perror("lpstat: Unable to connect to server");
return (1);
}
-
- httpEncryption(http, encryption);
}
show_scheduler(http);
case 's' : /* Show summary */
if (!http)
{
- http = httpConnect(cupsServer(), ippPort());
+ http = httpConnectEncrypt(cupsServer(), ippPort(), encryption);
if (http == NULL)
{
perror("lpstat: Unable to connect to server");
return (1);
}
-
- httpEncryption(http, encryption);
}
if (num_dests == 0)
case 't' : /* Show all info */
if (!http)
{
- http = httpConnect(cupsServer(), ippPort());
+ http = httpConnectEncrypt(cupsServer(), ippPort(), encryption);
if (http == NULL)
{
perror("lpstat: Unable to connect to server");
return (1);
}
-
- httpEncryption(http, encryption);
}
if (num_dests == 0)
case 'u' : /* Show jobs by user */
if (!http)
{
- http = httpConnect(cupsServer(), ippPort());
+ http = httpConnectEncrypt(cupsServer(), ippPort(), encryption);
if (http == NULL)
{
perror("lpstat: Unable to connect to server");
return (1);
}
-
- httpEncryption(http, encryption);
}
if (argv[i][2] != '\0')
case 'v' : /* Show printer devices */
if (!http)
{
- http = httpConnect(cupsServer(), ippPort());
+ http = httpConnectEncrypt(cupsServer(), ippPort(), encryption);
if (http == NULL)
{
perror("lpstat: Unable to connect to server");
return (1);
}
-
- httpEncryption(http, encryption);
}
if (num_dests == 0)
{
if (!http)
{
- http = httpConnect(cupsServer(), ippPort());
+ http = httpConnectEncrypt(cupsServer(), ippPort(), encryption);
if (http == NULL)
{
perror("lpstat: Unable to connect to server");
return (1);
}
-
- httpEncryption(http, encryption);
}
show_jobs(http, argv[i], NULL, long_status, ranking);
{
if (!http)
{
- http = httpConnect(cupsServer(), ippPort());
+ http = httpConnectEncrypt(cupsServer(), ippPort(), encryption);
if (http == NULL)
{
perror("lpstat: Unable to connect to server");
return (1);
}
-
- httpEncryption(http, encryption);
}
show_jobs(http, NULL, cupsUser(), long_status, ranking);
{
httpSeparate(printer_uri, method, username, server, &port, resource);
- if ((http2 = httpConnect(server, port)) != NULL)
+ if ((http2 = httpConnectEncrypt(server, port, cupsEncryption())) != NULL)
{
/*
* Build an IPP_GET_PRINTER_ATTRIBUTES request, which requires the
/*
- * End of "$Id: lpstat.c,v 1.37 2001/01/26 15:29:59 mike Exp $".
+ * End of "$Id: lpstat.c,v 1.37.2.1 2001/05/13 18:38:41 mike Exp $".
*/
ATTR uri job-uri $uri
# What statuses are OK?
- STATUS ok
- STATUS ok-subst
+ #STATUS ok
+ #STATUS ok-subst
# What attributes do we expect?
EXPECT job-uri
EXPECT job-state
+ EXPECT bogus-attribute
}