+++ /dev/null
-<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
-<html>
-<!-- SECTION: Specifications -->
-<head>
- <title>Generating PostScript for CUPS</title>
- <meta name='keywords' content='Programming, PostScript, Document Structuring Conventions'>
- <link rel='stylesheet' type='text/css' href='../cups-printable.css'>
-</head>
-<body>
-<!--
- CUPS PostScript file specification for CUPS.
-
- Copyright © 2007-2012 by Apple Inc.
- Copyright © 2006 by Easy Software Products.
-
- Licensed under Apache License v2.0. See the file "LICENSE" for more
- information.
--->
-
-<H1 CLASS="title">Generating PostScript for CUPS</H1>
-
-<h2 class='title'><a name='INTRODUCTION'>Introduction</a></h2>
-
-<p>This document describes how to generate PostScript output for
-CUPS and is largely based on the <a
-href="http://partners.adobe.com/public/developer/en/ps/5001.DSC_Spec.pdf">
-Adobe TechNote #5001: PostScript Language Document Structuring
-Conventions Specification Version 3.0</a>. While CUPS can
-generally print any PostScript file, following the rules in the
-Adobe TechNote and this document will ensure that your PostScript
-output will work reliably.</p>
-
-<blockquote><b>Note:</b> While PostScript is currently the
-de-facto standard print job file format/language for UNIX-based
-applications, it is slowly being phased out in favor of Adobe's
-Portable Document Format ("PDF") which offers many advantages
-over PostScript. macOS uses PDF as the primary print job file
-format and Linux is making the transition. Both PostScript and
-PDF are complex formats, and we highly recommend using high-level
-toolkits whenever possible to create your print jobs.</blockquote>
-
-<h3>Anatomy of a PostScript File</h3>
-
-<p>PostScript files are ASCII text files starting with a header
-line (<tt>%!PS-Adobe-3.0</tt>) followed by a combination of
-comment lines starting with the percent sign (<tt>%</tt>) and
-PostScript code lines. The lines themselves should not exceed 255
-characters to conform to the DSC. The following short PostScript
-file produces a box with a smiley face in it:</p>
-
-<pre class="command">
-%!PS-Adobe-3.0
-%%BoundingBox: 36 36 576 756
-%%Pages: 1
-%%LanguageLevel: 2
-%%EndComments
-%%BeginSetup
-% this is where fonts would be embedded
-%%EndSetup
-%%Page: (1) 1
-%%BeginPageSetup
-% this is where page-specific features would be specified
-%%EndPageSetup
-% Draw a black box around the page
-0 setgray
-1 setlinewidth
-36 36 540 720 rectstroke
-
-% Draw a two inch blue circle in the middle of the page
-0 0 1 setrgbcolor
-306 396 144 0 360 arc closepath fill
-
-% Draw two half inch yellow circles for eyes
-1 1 0 setrgbcolor
-252 432 36 0 360 arc closepath fill
-360 432 36 0 360 arc closepath fill
-
-% Draw the smile
-1 setlinecap
-18 setlinewidth
-306 396 99 200 340 arc stroke
-
-% Print it!
-showpage
-%%EOF
-</pre>
-
-<div class="figure"><table summary="Sample PostScript File Output">
-<caption>Figure 1: <a name="FIGURE_1">Sample PostScript File Output</a></caption>
-<tr><td align="center"><img src="../images/smiley.jpg"
-width="445" height="570" alt="Sample PostScript File Output"></td></tr>
-</table></div>
-
-
-<h2><a name='OPTIONS'>Embedding Printer Options</a></h2>
-
-<p>There are two main strategies for embedding printer options in PostScript
-files. The first is to list CUPS options using the <code>%cupsJobTicket</code>
-comment:</p>
-
-<pre>
-%!PS-Adobe-3.0
-%cupsJobTicket: media=A4 sides=two-sided-long-edge
-%cupsJobTicket: PrinterOption=foo PrinterOption2=bar
-...
-%%EndComments
-</pre>
-
-<p>CUPS options apply to the entire job. To apply options to individual pages,
-use the <code>%%IncludeFeature</code> comment instead:</p>
-
-<pre>
-%%Page: label 123
-%%BeginPageSetup
-%%IncludeFeature: *PageSize A4
-%%IncludeFeature: *PrinterOption Foo
-%%IncludeFeature: *PrinterOption2 Bar
-%%EndPageSetup
-...
-</pre>
-
-
-<h2><a name='FONTS'>Embedding Fonts and Text</a></h2>
-
-<p>Always embed the fonts used by your print job, and for best performance
-embed the fonts and character encodings in the setup section of the PostScript
-file. Type 1 and Type 3 fonts are supported by all PostScript printers, while
-Type 42 (TrueType) and CID fonts are supported by most level 2 and all level 3
-PostScript printers. Binary font files should always be converted to the
-corresponding ASCII (hex) encoding to avoid problems when printing over
-interfaces that do not support binary PostScript.</p>
-
-
-<h2><a name='IMAGES'>Embedding Images</a></h2>
-
-<p>The <code>image</code> operator should be used to embed images in PostScript
-files. Always use ASCII hex or Base-85 encoding for the image data to avoid
-problems when printing over interfaces that do not support binary PostScript.
-In most cases, the Base-85 encoding and compression filters can be used to
-embed images with very little, if any, increase in data size.</p>
-
-</body>
-</html>
+++ /dev/null
-/*
- * DSC test program for CUPS.
- *
- * Copyright 2007-2010 by Apple Inc.
- * Copyright 2006 by Easy Software Products, all rights reserved.
- *
- * Licensed under Apache License v2.0. See the file "LICENSE" for more information.
- *
- * PostScript is a trademark of Adobe Systems, Inc.
- */
-
-/*
- * Include necessary headers...
- */
-
-#include <cups/cups-private.h>
-
-
-/*
- * Local functions...
- */
-
-static int check_file(const char *filename);
-static void usage(void) _CUPS_NORETURN;
-
-
-/*
- * 'main()' - Main entry for test program.
- */
-
-int /* O - Exit status */
-main(int argc, /* I - Number of command-line args */
- char *argv[]) /* I - Command-line arguments */
-{
- int i; /* Looping var */
- int status; /* Status of tests */
- int num_files; /* Number of files tested */
-
-
- _cupsSetLocale(argv);
-
- /*
- * Collect command-line arguments...
- */
-
- for (i = 1, num_files = 0, status = 0; i < argc; i ++)
- if (argv[i][0] == '-')
- {
- if (argv[i][1])
- {
- /*
- * Currently the only supported option is "-h" (help)...
- */
-
- usage();
- }
- else
- {
- num_files ++;
- status += check_file("(stdin)");
- }
- }
- else
- {
- num_files ++;
- status += check_file(argv[i]);
- }
-
- if (!num_files)
- usage();
-
- return (status);
-}
-
-
-/*
- * 'check()' - Check a file for conformance.
- */
-
-static int /* O - 0 on success, 1 on failure */
-check_file(const char *filename) /* I - File to read from */
-{
- int i; /* Looping var */
- cups_file_t *fp; /* File */
- char line[1024]; /* Line from file */
- int ch; /* Current character */
- size_t bytes; /* Length of line */
- int status; /* Status of test */
- int linenum; /* Line number */
- int binary; /* File contains binary data? */
- float version; /* DSC version */
- int lbrt[4]; /* Bounding box */
- char page_label[256]; /* Page label string */
- int page_number; /* Page number */
- int last_page_number; /* Last page number seen */
- int level; /* Embedded document level */
- int saw_bounding_box, /* %%BoundingBox seen? */
- saw_pages, /* %%Pages seen? */
- saw_end_comments, /* %%EndComments seen? */
- saw_begin_prolog, /* %%BeginProlog seen? */
- saw_end_prolog, /* %%EndProlog seen? */
- saw_begin_setup, /* %%BeginSetup seen? */
- saw_end_setup, /* %%EndSetup seen? */
- saw_page, /* %%Page seen? */
- saw_trailer, /* %%Trailer seen? */
- saw_long_line; /* Saw long lines? */
-
-
- /*
- * Open the file...
- */
-
- if (!strcmp(filename, "(stdin)"))
- fp = cupsFileStdin();
- else
- fp = cupsFileOpen(filename, "r");
-
- if (!fp)
- {
- perror(filename);
- return (1);
- }
-
- /*
- * Scan the file...
- */
-
- binary = 0;
- last_page_number = 0;
- level = 0;
- linenum = 0;
- saw_begin_prolog = 0;
- saw_begin_setup = 0;
- saw_bounding_box = 0;
- saw_end_comments = 0;
- saw_end_prolog = 0;
- saw_end_setup = 0;
- saw_long_line = 0;
- saw_page = 0;
- saw_pages = 0;
- saw_trailer = 0;
- status = 0;
- version = 0.0f;
-
- /* TODO: Fixme */
- printf("%s: ", filename);
- fflush(stdout);
-
- while ((bytes = cupsFileGetLine(fp, line, sizeof(line))) > 0)
- {
- linenum ++;
-
- if (bytes > 255)
- {
- if (!saw_long_line)
- {
- if (!status)
- _cupsLangPuts(stdout, _("FAIL"));
-
- status ++;
- _cupsLangPrintf(stdout,
- _(" Line %d is longer than 255 characters (%d).\n"
- " REF: Page 25, Line Length"),
- linenum, (int)bytes);
- }
-
- saw_long_line ++;
- }
-
- if (linenum == 1)
- {
- if (strncmp(line, "%!PS-Adobe-", 11))
- {
- if (!status)
- _cupsLangPuts(stdout, _("FAIL"));
-
- _cupsLangPuts(stdout,
- _(" Missing %!PS-Adobe-3.0 on first line.\n"
- " REF: Page 17, 3.1 Conforming Documents"));
- cupsFileClose(fp);
- return (1);
- }
- else
- version = (float)atof(line + 11);
- }
- else if (level > 0)
- {
- if (!strncmp(line, "%%BeginDocument:", 16))
- level ++;
- else if (!strncmp(line, "%%EndDocument", 13))
- level --;
- }
- else if (saw_trailer)
- {
- if (!strncmp(line, "%%Pages:", 8))
- {
- if (atoi(line + 8) <= 0)
- {
- if (!status)
- _cupsLangPuts(stdout, _("FAIL"));
-
- status ++;
- _cupsLangPrintf(stdout,
- _(" Bad %%%%Pages: on line %d.\n"
- " REF: Page 43, %%%%Pages:"),
- linenum);
- }
- else
- saw_pages = 1;
- }
- else if (!strncmp(line, "%%BoundingBox:", 14))
- {
- if (sscanf(line + 14, "%d%d%d%d", lbrt + 0, lbrt + 1, lbrt + 2,
- lbrt + 3) != 4)
- {
- if (!status)
- _cupsLangPuts(stdout, _("FAIL"));
-
- status ++;
- _cupsLangPrintf(stdout, _(" Bad %%%%BoundingBox: on line %d.\n"
- " REF: Page 39, %%%%BoundingBox:"),
- linenum);
- }
- else
- saw_bounding_box = 1;
- }
- }
- else if (!saw_end_comments)
- {
- if (!strncmp(line, "%%EndComments", 13))
- saw_end_comments = 1;
- else if (line[0] != '%')
- saw_end_comments = -1;
- else if (!strncmp(line, "%%Pages:", 8))
- {
- if (strstr(line + 8, "(atend)"))
- saw_pages = -1;
- else if (atoi(line + 8) <= 0)
- {
- if (!status)
- _cupsLangPuts(stdout, _("FAIL"));
-
- status ++;
- _cupsLangPrintf(stdout, _(" Bad %%%%Pages: on line %d.\n"
- " REF: Page 43, %%%%Pages:"),
- linenum);
- }
- else
- saw_pages = 1;
- }
- else if (!strncmp(line, "%%BoundingBox:", 14))
- {
- if (strstr(line, "(atend)"))
- saw_bounding_box = -1;
- else if (sscanf(line + 14, "%d%d%d%d", lbrt + 0, lbrt + 1, lbrt + 2,
- lbrt + 3) != 4)
- {
- if (!status)
- _cupsLangPuts(stdout, _("FAIL"));
-
- status ++;
- _cupsLangPrintf(stdout, _(" Bad %%%%BoundingBox: on line %d.\n"
- " REF: Page 39, %%%%BoundingBox:"),
- linenum);
- }
- else
- saw_bounding_box = 1;
- }
- }
- else if (saw_begin_prolog && !saw_end_prolog)
- {
- if (!strncmp(line, "%%EndProlog", 11))
- saw_end_prolog = 1;
- }
- else if (saw_begin_setup && !saw_end_setup)
- {
- if (!strncmp(line, "%%EndSetup", 10))
- saw_end_setup = 1;
- }
- else if (saw_end_comments)
- {
- if (!strncmp(line, "%%Page:", 7))
- {
- if (sscanf(line + 7, "%255s%d", page_label, &page_number) != 2 ||
- page_number != (last_page_number + 1) || page_number < 1)
- {
- if (!status)
- _cupsLangPuts(stdout, _("FAIL"));
-
- status ++;
- _cupsLangPrintf(stdout, _(" Bad %%%%Page: on line %d.\n"
- " REF: Page 53, %%%%Page:"),
- linenum);
- }
- else
- {
- last_page_number = page_number;
- saw_page = 1;
- }
- }
- else if (!strncmp(line, "%%BeginProlog", 13))
- saw_begin_prolog = 1;
- else if (!strncmp(line, "%%BeginSetup", 12))
- saw_begin_setup = 1;
- else if (!strncmp(line, "%%BeginDocument:", 16))
- level ++;
- else if (!strncmp(line, "%%EndDocument", 13))
- level --;
- else if (!strncmp(line, "%%Trailer", 9))
- saw_trailer = 1;
- }
-
- for (i = 0; !binary && i < (int)bytes; i ++)
- {
- ch = line[i];
-
- if ((ch < ' ' || (ch & 0x80)) && ch != '\n' && ch != '\r' && ch != '\t')
- binary = 1;
- }
- }
-
- if (saw_bounding_box <= 0)
- {
- if (!status)
- _cupsLangPuts(stdout, _("FAIL"));
-
- status ++;
- _cupsLangPuts(stdout, _(" Missing or bad %%BoundingBox: comment.\n"
- " REF: Page 39, %%BoundingBox:"));
- }
-
- if (saw_pages <= 0)
- {
- if (!status)
- _cupsLangPuts(stdout, _("FAIL"));
-
- status ++;
- _cupsLangPuts(stdout, _(" Missing or bad %%Pages: comment.\n"
- " REF: Page 43, %%Pages:"));
- }
-
- if (!saw_end_comments)
- {
- if (!status)
- _cupsLangPuts(stdout, _("FAIL"));
-
- status ++;
- _cupsLangPuts(stdout, _(" Missing %%EndComments comment."
- " REF: Page 41, %%EndComments"));
- }
-
- if (!saw_page)
- {
- if (!status)
- _cupsLangPuts(stdout, _("FAIL"));
-
- status ++;
- _cupsLangPuts(stdout, _(" Missing or bad %%Page: comments.\n"
- " REF: Page 53, %%Page:"));
- }
-
- if (level < 0)
- {
- if (!status)
- _cupsLangPuts(stdout, _("FAIL"));
-
- status ++;
- _cupsLangPuts(stdout, _(" Too many %%EndDocument comments."));
- }
- else if (level > 0)
- {
- if (!status)
- _cupsLangPuts(stdout, _("FAIL"));
-
- status ++;
- _cupsLangPuts(stdout, _(" Too many %%BeginDocument comments."));
- }
-
- if (saw_long_line > 1)
- _cupsLangPrintf(stderr,
- _(" Saw %d lines that exceeded 255 characters."),
- saw_long_line);
-
- if (!status)
- _cupsLangPuts(stdout, _("PASS"));
-
- if (binary)
- _cupsLangPuts(stdout, _(" Warning: file contains binary data."));
-
- if (version < 3.0f)
- _cupsLangPrintf(stdout,
- _(" Warning: obsolete DSC version %.1f in file."),
- version);
-
- if (saw_end_comments < 0)
- _cupsLangPuts(stdout, _(" Warning: no %%EndComments comment in file."));
-
- cupsFileClose(fp);
-
- return (status);
-}
-
-
-/*
- * 'usage()' - Show program usage.
- */
-
-static void
-usage(void)
-{
- _cupsLangPuts(stdout, _("Usage: cupstestdsc [options] filename.ps [... "
- "filename.ps]"));
- _cupsLangPuts(stdout, _(" cupstestdsc [options] -"));
- _cupsLangPuts(stdout, "");
- _cupsLangPuts(stdout, _("Options:"));
- _cupsLangPuts(stdout, "");
- _cupsLangPuts(stdout, _(" -h Show program usage"));
- _cupsLangPuts(stdout, "");
- _cupsLangPuts(stdout, _("Note: this program only validates the DSC comments, "
- "not the PostScript itself."));
-
- exit(1);
-}