* Include necessary headers...
*/
-#include "common.h"
+#include "pstext.h"
#include "image.h"
#include <cups/i18n.h>
* Globals...
*/
-char *Glyphs[65536]; /* PostScript glyphs for Unicode */
-int NumFonts; /* Number of fonts to use */
-char *Fonts[256][4]; /* Fonts to use */
-unsigned short Chars[65536]; /* 0xffcc (ff = font, cc = char) */
-unsigned short Codes[65536]; /* Unicode glyph mapping to fonts */
-int Widths[256]; /* Widths of each font */
-int Directions[256];/* Text directions for each font */
-
-
/*
* Local functions...
*/
-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(const char *s);
+static void write_epilogue(int num_pages);
+ps_text_t *write_prolog(const char *title, const char *user);
/*
* 'main()' - Generate PostScript cover pages.
*/
-int /* O - Exit status */
-main(int argc, /* I - Number of command-line arguments */
- char *argv[]) /* I - Command-line arguments */
+int /* O - Exit status */
+main(int argc, /* I - Number of command-line args */
+ char *argv[]) /* I - Command-line arguments */
{
-}
+ int num_options; /* Number of print options */
+ cups_option_t *options; /* Print options */
+ ppd_file_t *ppd; /* PPD file */
+ ps_text_t *fonts; /* Fonts for output */
+ cups_lang_t *language; /* Default language */
+ cups_file_t *fp; /* Print file */
+ char line[2048], /* Line from file */
+ *ptr; /* Pointer into line */
+ float fontsize; /* Font size to use */
-/*
- * 'WriteEpilogue()' - Write the PostScript file epilogue.
- */
+ /*
+ * Make sure status messages are not buffered...
+ */
-void
-WriteEpilogue(void)
-{
- puts("%%Trailer");
- printf("%%%%Pages: %d\n", NumPages);
- puts("%%EOF");
+ setbuf(stderr, NULL);
- free(Page[0]);
- free(Page);
-}
+ /*
+ * Check command-line...
+ */
+ if (argc < 6 || argc > 7)
+ {
+ _cupsLangPrintf(stderr,
+ _("Usage: %s job-id user title copies options [file]\n"),
+ "bannertops");
+ return (1);
+ }
-/*
- * 'WritePage()' - Write a page of text.
- */
+ /*
+ * Get standard options and the PPD file for this printer...
+ */
-void
-WritePage(void)
-{
+ options = NULL;
+ num_options = cupsParseOptions(argv[5], 0, &options);
+ ppd = SetCommonOptions(num_options, options, 1);
+ fonts = write_prolog(argv[3], argv[2]);
+ language = cupsLangDefault();
+
+ /*
+ * Write the page...
+ */
+
+ puts("%%Page: 1 1");
+ puts("0 setgray");
+
+ puts("306 144 moveto");
+ psTextUTF8(fonts, 12.0, PS_BOLD, PS_RIGHT,
+ _cupsLangString(language, _("Job ID: ")));
+ snprintf(line, sizeof(line), "%s-%s", getenv("PRINTER"), argv[1]);
+ psTextUTF8(fonts, 12.0, PS_NORMAL, PS_LEFT, line);
+
+ puts("306 130 moveto");
+ psTextUTF8(fonts, 12.0, PS_BOLD, PS_RIGHT,
+ _cupsLangString(language, _("Title: ")));
+ psTextUTF8(fonts, 12.0, PS_NORMAL, PS_LEFT, argv[3]);
+
+ puts("showpage");
+ write_epilogue(1);
+
+ return (0);
+
+#if 0
int line; /* Current line */
puts("showpage");
memset(Page[0], 0, sizeof(lchar_t) * SizeColumns * SizeLines);
+#endif /* 0 */
}
/*
- * 'WriteProlog()' - Write the PostScript file prolog with options.
+ * 'write_epilogue()' - Write the PostScript file epilogue.
*/
-void
-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 */
+static void
+write_epilogue(int num_pages) /* I - Number of pages */
{
- int i, j, k; /* Looping vars */
- char *charset; /* Character set string */
- char filename[1024]; /* Glyph filenames */
- FILE *fp; /* Glyph files */
- const char *datadir; /* CUPS_DATADIR environment variable */
- char line[1024], /* Line from file */
- *lineptr, /* Pointer into line */
- *valptr; /* Pointer to value in line */
- int ch, unicode; /* Character values */
- int start, end; /* Start and end values for range */
- char glyph[64]; /* Glyph name */
- time_t curtime; /* Current time */
- struct tm *curtm; /* Current date */
- char curdate[255]; /* Current date (text format) */
- int num_fonts; /* Number of unique fonts */
- char *fonts[1024]; /* Unique fonts */
- static char *names[] = /* Font names */
- {
- "cupsNormal",
- "cupsBold",
- "cupsItalic"
- };
-
-
- /*
- * Get the data directory...
- */
+ puts("%%Trailer");
+ printf("%%%%Pages: %d\n", num_pages);
+ puts("%%EOF");
+}
- if ((datadir = getenv("CUPS_DATADIR")) == NULL)
- datadir = CUPS_DATADIR;
- /*
- * Adjust margins as necessary...
- */
+/*
+ * 'write_prolog()' - Write the PostScript file prolog with options.
+ */
- if (classification || label)
- {
- /*
- * Leave room for labels...
- */
+ps_text_t * /* O - Fonts */
+write_prolog(const char *title, /* I - Title of job */
+ const char *user) /* I - Username */
+{
+ time_t curtime; /* Current time */
+ struct tm *curtm; /* Current date */
+ char curdate[255]; /* Current date (text format) */
+ ps_text_t *fonts; /* Fonts */
- PageBottom += 36;
- PageTop -= 36;
- }
/*
- * Allocate memory for the page...
+ * Get the fonts we'll need...
*/
- SizeColumns = (PageRight - PageLeft) / 72.0 * CharsPerInch;
- SizeLines = (PageTop - PageBottom) / 72.0 * LinesPerInch;
-
- Page = calloc(sizeof(lchar_t *), SizeLines);
- Page[0] = calloc(sizeof(lchar_t), SizeColumns * SizeLines);
- for (i = 1; i < SizeLines; i ++)
- Page[i] = Page[0] + i * SizeColumns;
-
- if (PageColumns > 1)
- {
- ColumnGutter = CharsPerInch / 2;
- ColumnWidth = (SizeColumns - ColumnGutter * (PageColumns - 1)) /
- PageColumns;
- }
- else
- ColumnWidth = SizeColumns;
+ fonts = psTextInitialize();
/*
* Output the DSC header...
strftime(curdate, sizeof(curdate), "%c", curtm);
puts("%!PS-Adobe-3.0");
- printf("%%%%BoundingBox: 0 0 %.0f %.0f\n", PageWidth, PageLength);
+ printf("%%%%BoundingBox: %.0f %.0f %.0f %.0f\n", PageLeft, PageBottom,
+ PageRight, PageTop);
printf("%%cupsRotation: %d\n", (Orientation & 3) * 90);
- puts("%%Creator: texttops/" CUPS_SVERSION);
+ puts("%%Creator: bannertops/" CUPS_SVERSION);
printf("%%%%CreationDate: %s\n", curdate);
WriteTextComment("Title", title);
WriteTextComment("For", user);
- puts("%%Pages: (atend)");
-
- /*
- * Initialize globals...
- */
-
- NumFonts = 0;
- memset(Fonts, 0, sizeof(Fonts));
- memset(Glyphs, 0, sizeof(Glyphs));
- memset(Chars, 0, sizeof(Chars));
- memset(Codes, 0, sizeof(Codes));
-
- /*
- * Load the PostScript glyph names and the corresponding character
- * set definition...
- */
-
- snprintf(filename, sizeof(filename), "%s/data/psglyphs", datadir);
-
- if ((fp = fopen(filename, "r")) != NULL)
- {
- while (fscanf(fp, "%x%63s", &unicode, glyph) == 2)
- Glyphs[unicode] = strdup(glyph);
-
- fclose(fp);
- }
- else
- {
- fprintf(stderr, _("ERROR: Unable to open \"%s\" - %s\n"), filename,
- strerror(errno));
- exit(1);
- }
-
- /*
- * Get the output character set...
- */
-
- charset = getenv("CHARSET");
- if (charset != NULL && strcmp(charset, "us-ascii") != 0)
- {
- snprintf(filename, sizeof(filename), "%s/charsets/%s", datadir, charset);
-
- if ((fp = fopen(filename, "r")) == NULL)
- {
- /*
- * Can't open charset file!
- */
-
- fprintf(stderr, _("ERROR: Unable to open %s: %s\n"), filename,
- strerror(errno));
- exit(1);
- }
-
- /*
- * Opened charset file; now see if this is really a charset file...
- */
-
- if (fgets(line, sizeof(line), fp) == NULL)
- {
- /*
- * Bad/empty charset file!
- */
-
- fclose(fp);
- fprintf(stderr, _("ERROR: Bad charset file %s\n"), filename);
- exit(1);
- }
-
- if (strncmp(line, "charset", 7) != 0)
- {
- /*
- * Bad format/not a charset file!
- */
-
- fclose(fp);
- fprintf(stderr, _("ERROR: Bad charset file %s\n"), filename);
- exit(1);
- }
-
- /*
- * See if this is an 8-bit or UTF-8 character set file...
- */
-
- line[strlen(line) - 1] = '\0'; /* Drop \n */
- for (lineptr = line + 7; isspace(*lineptr & 255); lineptr ++); /* Skip whitespace */
-
- if (strcmp(lineptr, "8bit") == 0)
- {
- /*
- * 8-bit text...
- */
-
- UTF8 = 0;
- NumFonts = 0;
-
- /*
- * Read the font description(s)...
- */
-
- while (fgets(line, sizeof(line), fp) != NULL)
- {
- /*
- * Skip comment and blank lines...
- */
-
- if (line[0] == '#' || line[0] == '\n')
- continue;
-
- /*
- * Read the font descriptions that should look like:
- *
- * first last direction width normal [bold italic bold-italic]
- */
-
- lineptr = line;
-
- start = strtol(lineptr, &lineptr, 16);
- end = strtol(lineptr, &lineptr, 16);
-
- while (isspace(*lineptr & 255))
- lineptr ++;
-
- if (!*lineptr)
- break; /* Must be a font mapping */
-
- valptr = lineptr;
-
- while (!isspace(*lineptr & 255) && *lineptr)
- lineptr ++;
-
- if (!*lineptr)
- {
- /*
- * Can't have a font without all required values...
- */
-
- fprintf(stderr, _("ERROR: Bad font description line: %s\n"), valptr);
- fclose(fp);
- exit(1);
- }
-
- *lineptr++ = '\0';
-
- if (strcmp(valptr, "ltor") == 0)
- Directions[NumFonts] = 1;
- else if (strcmp(valptr, "rtol") == 0)
- Directions[NumFonts] = -1;
- else
- {
- fprintf(stderr, _("ERROR: Bad text direction %s\n"), valptr);
- fclose(fp);
- exit(1);
- }
-
- /*
- * Got the direction, now get the width...
- */
-
- while (isspace(*lineptr & 255))
- lineptr ++;
-
- valptr = lineptr;
-
- while (!isspace(*lineptr & 255) && *lineptr)
- lineptr ++;
-
- if (!*lineptr)
- {
- /*
- * Can't have a font without all required values...
- */
-
- fprintf(stderr, _("ERROR: Bad font description line: %s\n"), valptr);
- fclose(fp);
- exit(1);
- }
-
- *lineptr++ = '\0';
-
- if (strcmp(valptr, "single") == 0)
- Widths[NumFonts] = 1;
- else if (strcmp(valptr, "double") == 0)
- Widths[NumFonts] = 2;
- else
- {
- fprintf(stderr, _("ERROR: Bad text width %s\n"), valptr);
- fclose(fp);
- exit(1);
- }
-
- /*
- * Get the fonts...
- */
-
- for (i = 0; *lineptr && i < 4; i ++)
- {
- while (isspace(*lineptr & 255))
- lineptr ++;
-
- valptr = lineptr;
-
- while (!isspace(*lineptr & 255) && *lineptr)
- lineptr ++;
-
- if (*lineptr)
- *lineptr++ = '\0';
-
- if (lineptr > valptr)
- Fonts[NumFonts][i] = strdup(valptr);
- }
-
- /*
- * Fill in remaining fonts as needed...
- */
-
- for (j = i; j < 4; j ++)
- Fonts[NumFonts][j] = strdup(Fonts[NumFonts][0]);
-
- /*
- * Define the character mappings...
- */
-
- for (i = start, j = NumFonts * 256; i <= end; i ++, j ++)
- Chars[i] = j;
-
- NumFonts ++;
- }
-
- /*
- * Read encoding lines...
- */
-
- do
- {
- /*
- * Skip comment and blank lines...
- */
-
- if (line[0] == '#' || line[0] == '\n')
- continue;
-
- /*
- * Grab the character and unicode glyph number.
- */
-
- if (sscanf(line, "%x%x", &ch, &unicode) == 2 && ch < 256)
- Codes[Chars[ch]] = unicode;
- }
- while (fgets(line, sizeof(line), fp) != NULL);
-
- fclose(fp);
- }
- else if (strcmp(lineptr, "utf8") == 0)
- {
- /*
- * UTF-8 (Unicode) text...
- */
-
- UTF8 = 1;
-
- /*
- * Read the font descriptions...
- */
-
- NumFonts = 0;
-
- while (fgets(line, sizeof(line), fp) != NULL)
- {
- /*
- * Skip comment and blank lines...
- */
-
- if (line[0] == '#' || line[0] == '\n')
- continue;
-
- /*
- * Read the font descriptions that should look like:
- *
- * start end direction width normal [bold italic bold-italic]
- */
-
- lineptr = line;
-
- start = strtol(lineptr, &lineptr, 16);
- end = strtol(lineptr, &lineptr, 16);
-
- while (isspace(*lineptr & 255))
- lineptr ++;
-
- valptr = lineptr;
-
- while (!isspace(*lineptr & 255) && *lineptr)
- lineptr ++;
-
- if (!*lineptr)
- {
- /*
- * Can't have a font without all required values...
- */
-
- fprintf(stderr, _("ERROR: Bad font description line: %s\n"), valptr);
- fclose(fp);
- exit(1);
- }
-
- *lineptr++ = '\0';
-
- if (strcmp(valptr, "ltor") == 0)
- Directions[NumFonts] = 1;
- else if (strcmp(valptr, "rtol") == 0)
- Directions[NumFonts] = -1;
- else
- {
- fprintf(stderr, _("ERROR: Bad text direction %s\n"), valptr);
- fclose(fp);
- exit(1);
- }
-
- /*
- * Got the direction, now get the width...
- */
-
- while (isspace(*lineptr & 255))
- lineptr ++;
-
- valptr = lineptr;
-
- while (!isspace(*lineptr & 255) && *lineptr)
- lineptr ++;
-
- if (!*lineptr)
- {
- /*
- * Can't have a font without all required values...
- */
-
- fprintf(stderr, _("ERROR: Bad font description line: %s\n"), valptr);
- fclose(fp);
- exit(1);
- }
-
- *lineptr++ = '\0';
-
- if (strcmp(valptr, "single") == 0)
- Widths[NumFonts] = 1;
- else if (strcmp(valptr, "double") == 0)
- Widths[NumFonts] = 2;
- else
- {
- fprintf(stderr, _("ERROR: Bad text width %s\n"), valptr);
- fclose(fp);
- exit(1);
- }
-
- /*
- * Get the fonts...
- */
-
- for (i = 0; *lineptr && i < 4; i ++)
- {
- while (isspace(*lineptr & 255))
- lineptr ++;
-
- valptr = lineptr;
-
- while (!isspace(*lineptr & 255) && *lineptr)
- lineptr ++;
-
- if (*lineptr)
- *lineptr++ = '\0';
-
- if (lineptr > valptr)
- Fonts[NumFonts][i] = strdup(valptr);
- }
-
- /*
- * Fill in remaining fonts as needed...
- */
-
- for (j = i; j < 4; j ++)
- Fonts[NumFonts][j] = strdup(Fonts[NumFonts][0]);
-
- /*
- * Define the character mappings...
- */
-
- for (i = start, j = NumFonts * 256; i <= end; i ++, j ++)
- {
- Chars[i] = j;
- Codes[j] = i;
- }
-
- /*
- * Move to the next font, stopping if needed...
- */
-
- NumFonts ++;
- if (NumFonts >= 256)
- break;
- }
-
- fclose(fp);
- }
- else
- {
- fprintf(stderr, _("ERROR: Bad charset type %s\n"), lineptr);
- fclose(fp);
- exit(1);
- }
- }
- else
- {
- /*
- * Standard ASCII output just uses Courier, Courier-Bold, and
- * possibly Courier-Oblique.
- */
-
- NumFonts = 1;
-
- Fonts[0][ATTR_NORMAL] = strdup("Courier");
- Fonts[0][ATTR_BOLD] = strdup("Courier-Bold");
- Fonts[0][ATTR_ITALIC] = strdup("Courier-Oblique");
- Fonts[0][ATTR_BOLDITALIC] = strdup("Courier-BoldOblique");
-
- Widths[0] = 1;
- Directions[0] = 1;
-
- /*
- * Define US-ASCII characters...
- */
-
- for (i = 32; i < 127; i ++)
- {
- Chars[i] = i;
- Codes[i] = i;
- }
- }
-
- /*
- * Generate a list of unique fonts to use...
- */
-
- for (i = 0, num_fonts = 0; i < NumFonts; i ++)
- for (j = PrettyPrint ? 2 : 1; j >= 0; j --)
- {
- for (k = 0; k < num_fonts; k ++)
- if (strcmp(Fonts[i][j], fonts[k]) == 0)
- break;
-
- if (k >= num_fonts)
- {
- /*
- * Add new font...
- */
-
- fonts[num_fonts] = Fonts[i][j];
- num_fonts ++;
- }
- }
-
- /*
- * List the fonts that will be used...
- */
-
- for (i = 0; i < num_fonts; i ++)
- if (i == 0)
- printf("%%%%DocumentNeededResources: font %s\n", fonts[i]);
- else
- printf("%%%%+ font %s\n", fonts[i]);
-
- puts("%%DocumentSuppliedResources: procset texttops 1.1 0");
-
- for (i = 0; i < num_fonts; i ++)
- {
- if (ppd != NULL)
- {
- fprintf(stderr, "DEBUG: ppd->num_fonts = %d\n", ppd->num_fonts);
-
- for (j = 0; j < ppd->num_fonts; j ++)
- {
- fprintf(stderr, "DEBUG: ppd->fonts[%d] = %s\n", j, ppd->fonts[j]);
-
- if (strcmp(fonts[i], ppd->fonts[j]) == 0)
- break;
- }
- }
- else
- j = 0;
-
- if ((ppd != NULL && j >= ppd->num_fonts) ||
- strncmp(fonts[i], "Courier", 7) == 0 ||
- strcmp(fonts[i], "Symbol") == 0)
- {
- /*
- * Need to embed this font...
- */
-
- printf("%%%%+ font %s\n", fonts[i]);
- }
- }
-
+ printf("%%%%Pages: %d\n", Duplex ? 2 : 1);
+ psTextListFonts(fonts);
puts("%%EndComments");
-
puts("%%BeginProlog");
-
- /*
- * Download any missing fonts...
- */
-
- for (i = 0; i < num_fonts; i ++)
- {
- if (ppd != NULL)
- {
- for (j = 0; j < ppd->num_fonts; j ++)
- if (strcmp(fonts[i], ppd->fonts[j]) == 0)
- break;
- }
- else
- j = 0;
-
- if ((ppd != NULL && j >= ppd->num_fonts) ||
- strncmp(fonts[i], "Courier", 7) == 0 ||
- strcmp(fonts[i], "Symbol") == 0)
- {
- /*
- * Need to embed this font...
- */
-
- printf("%%%%BeginResource: font %s\n", fonts[i]);
-
- /**** MRS: Need to use CUPS_FONTPATH env var! ****/
- /**** Also look for Fontmap file or name.pfa, name.pfb... ****/
- snprintf(filename, sizeof(filename), "%s/fonts/%s", datadir, fonts[i]);
- if ((fp = fopen(filename, "rb")) != NULL)
- {
- while ((j = fread(line, 1, sizeof(line), fp)) > 0)
- fwrite(line, 1, j, stdout);
-
- fclose(fp);
- }
-
- puts("\n%%EndResource");
- }
- }
-
- /*
- * Write the encoding array(s)...
- */
-
- puts("% character encoding(s)");
-
- for (i = 0; i < NumFonts; i ++)
- {
- printf("/cupsEncoding%02x [\n", i);
-
- for (ch = 0; ch < 256; ch ++)
- {
- if (Glyphs[Codes[i * 256 + ch]])
- printf("/%s", Glyphs[Codes[i * 256 + ch]]);
- else if (Codes[i * 256 + ch] > 255)
- printf("/uni%04X", Codes[i * 256 + ch]);
- else
- printf("/.notdef");
-
- if ((ch & 7) == 7)
- putchar('\n');
- }
-
- puts("] def");
- }
-
- /*
- * Create the fonts...
- */
-
- if (NumFonts == 1)
- {
- /*
- * Just reencode the named fonts...
- */
-
- puts("% Reencode fonts");
-
- for (i = PrettyPrint ? 2 : 1; i >= 0; i --)
- {
- printf("/%s findfont\n", Fonts[0][i]);
- puts("dup length 1 add dict begin\n"
- " { 1 index /FID ne { def } { pop pop } ifelse } forall\n"
- " /Encoding cupsEncoding00 def\n"
- " currentdict\n"
- "end");
- printf("/%s exch definefont pop\n", names[i]);
- }
- }
- else
- {
- /*
- * Construct composite fonts... Start by reencoding the base fonts...
- */
-
- puts("% Reencode base fonts");
-
- for (i = PrettyPrint ? 2 : 1; i >= 0; i --)
- for (j = 0; j < NumFonts; j ++)
- {
- printf("/%s findfont\n", Fonts[j][i]);
- printf("dup length 1 add dict begin\n"
- " { 1 index /FID ne { def } { pop pop } ifelse } forall\n"
- " /Encoding cupsEncoding%02x def\n"
- " currentdict\n"
- "end\n", j);
- printf("/%s%02x exch definefont /%s%02x exch def\n", names[i], j,
- names[i], j);
- }
-
- /*
- * Then merge them into composite fonts...
- */
-
- puts("% Create composite fonts...");
-
- for (i = PrettyPrint ? 2 : 1; i >= 0; i --)
- {
- puts("8 dict begin");
- puts("/FontType 0 def/FontMatrix[1.0 0 0 1.0 0 0]def/FMapType 2 def/Encoding[");
- for (j = 0; j < NumFonts; j ++)
- if (j == (NumFonts - 1))
- printf("%d", j);
- else if ((j & 15) == 15)
- printf("%d\n", j);
- else
- printf("%d ", j);
- puts("]def/FDepVector[");
- for (j = 0; j < NumFonts; j ++)
- if (j == (NumFonts - 1))
- printf("%s%02x", names[i], j);
- else if ((j & 3) == 3)
- printf("%s%02x\n", names[i], j);
- else
- printf("%s%02x ", names[i], j);
- puts("]def currentdict end");
- printf("/%s exch definefont pop\n", names[i]);
- }
- }
-
- /*
- * Output the texttops procset...
- */
-
- puts("%%BeginResource: procset texttops 1.1 0");
-
- puts("% Define fonts");
-
- printf("/FN /cupsNormal findfont [%.3f 0 0 %.3f 0 0] makefont def\n",
- 120.0 / CharsPerInch, 68.0 / LinesPerInch);
- printf("/FB /cupsBold findfont [%.3f 0 0 %.3f 0 0] makefont def\n",
- 120.0 / CharsPerInch, 68.0 / LinesPerInch);
- if (PrettyPrint)
- printf("/FI /cupsItalic findfont [%.3f 0 0 %.3f 0 0] makefont def\n",
- 120.0 / CharsPerInch, 68.0 / LinesPerInch);
-
- puts("% Common procedures");
-
- puts("/N { FN setfont moveto } bind def");
- puts("/B { FB setfont moveto } bind def");
- printf("/U { gsave 0.5 setlinewidth 0 %.3f rmoveto "
- "0 rlineto stroke grestore } bind def\n", -6.8 / LinesPerInch);
-
- if (PrettyPrint)
- {
- if (ColorDevice)
- {
- puts("/S { 0.0 setgray show } bind def");
- puts("/r { 0.5 0.0 0.0 setrgbcolor show } bind def");
- puts("/g { 0.0 0.5 0.0 setrgbcolor show } bind def");
- puts("/b { 0.0 0.0 0.5 setrgbcolor show } bind def");
- }
- else
- {
- puts("/S { 0.0 setgray show } bind def");
- puts("/r { 0.2 setgray show } bind def");
- puts("/g { 0.2 setgray show } bind def");
- puts("/b { 0.2 setgray show } bind def");
- }
-
- puts("/I { FI setfont moveto } bind def");
-
- puts("/n {");
- puts("\t20 string cvs % convert page number to string");
- if (NumFonts > 1)
- {
- /*
- * Convert a number to double-byte chars...
- */
-
- puts("\tdup length % get length");
- puts("\tdup 2 mul string /P exch def % P = string twice as long");
- puts("\t0 1 2 index 1 sub { % loop through each character in the page number");
- puts("\t\tdup 3 index exch get % get character N from the page number");
- puts("\t\texch 2 mul dup % compute offset in P");
- puts("\t\tP exch 0 put % font 0");
- puts("\t\t1 add P exch 2 index put % character");
- puts("\t\tpop % discard character");
- puts("\t} for % do for loop");
- puts("\tpop pop % discard string and length");
- puts("\tP % put string on stack");
- }
- puts("} bind def");
-
- printf("/T");
- write_text(title);
- puts("def");
-
- printf("/D");
- write_text(curdate);
- puts("def");
-
- puts("/H {");
- puts("\tgsave");
- puts("\t0.9 setgray");
-
- if (Duplex)
- {
- puts("\tdup 2 mod 0 eq {");
- printf("\t\t%.3f %.3f translate } {\n",
- PageWidth - PageRight, PageTop + 72.0f / LinesPerInch);
- printf("\t\t%.3f %.3f translate } ifelse\n",
- PageLeft, PageTop + 72.0f / LinesPerInch);
- }
- else
- printf("\t%.3f %.3f translate\n",
- PageLeft, PageTop + 72.0f / LinesPerInch);
-
- printf("\t0 0 %.3f %.3f rectfill\n", PageRight - PageLeft,
- 144.0f / LinesPerInch);
-
- puts("\tFB setfont");
- puts("\t0 setgray");
-
- if (Duplex)
- {
- puts("\tdup 2 mod 0 eq {");
- printf("\t\tT stringwidth pop neg %.3f add %.3f } {\n",
- PageRight - PageLeft - 36.0f / LinesPerInch,
- (0.5f + 0.157f) * 72.0f / LinesPerInch);
- printf("\t\t%.3f %.3f } ifelse\n", 36.0f / LinesPerInch,
- (0.5f + 0.157f) * 72.0f / LinesPerInch);
- }
- else
- printf("\t%.3f %.3f\n", 36.0f / LinesPerInch,
- (0.5f + 0.157f) * 72.0f / LinesPerInch);
-
- puts("\tmoveto T show");
-
- printf("\tD dup stringwidth pop neg 2 div %.3f add %.3f\n",
- (PageRight - PageLeft) * 0.5,
- (0.5f + 0.157f) * 72.0f / LinesPerInch);
- puts("\tmoveto show");
-
- if (Duplex)
- {
- puts("\tdup n exch 2 mod 0 eq {");
- printf("\t\t%.3f %.3f } {\n", 36.0f / LinesPerInch,
- (0.5f + 0.157f) * 72.0f / LinesPerInch);
- printf("\t\tdup stringwidth pop neg %.3f add %.3f } ifelse\n",
- PageRight - PageLeft - 36.0f / LinesPerInch,
- (0.5f + 0.157f) * 72.0f / LinesPerInch);
- }
- else
- printf("\tn dup stringwidth pop neg %.3f add %.3f\n",
- PageRight - PageLeft - 36.0f / LinesPerInch,
- (0.5f + 0.157f) * 72.0f / LinesPerInch);
-
- puts("\tmoveto show");
- puts("\tgrestore");
- puts("} bind def");
- }
- else
- puts("/S { show } bind def");
-
- puts("%%EndResource");
-
+ psTextEmbedFonts(fonts);
puts("%%EndProlog");
-}
-
-
-/*
- * 'write_line()' - Write a row of text.
- */
-
-static void
-write_line(int row, /* I - Row number (0 to N) */
- lchar_t *line) /* I - Line to print */
-{
- int i; /* Looping var */
- int col; /* Current column */
- int attr; /* Current attribute */
- int font, /* Font to use */
- lastfont, /* Last font */
- mono; /* Monospaced? */
- lchar_t *start; /* First character in sequence */
-
- for (col = 0; col < SizeColumns;)
- {
- while (col < SizeColumns && (line->ch == ' ' || line->ch == 0))
- {
- col ++;
- line ++;
- }
-
- if (col >= SizeColumns)
- break;
-
- if (NumFonts == 1)
- {
- /*
- * All characters in a single font - assume monospaced...
- */
-
- attr = line->attr;
- start = line;
-
- while (col < SizeColumns && line->ch != 0 && attr == line->attr)
- {
- col ++;
- line ++;
- }
-
- write_string(col - (line - start), row, line - start, start);
- }
- else
- {
- /*
- * Multiple fonts; break up based on the font...
- */
-
- attr = line->attr;
- start = line;
- lastfont = Chars[line->ch] / 256;
- mono = strncmp(Fonts[lastfont][0], "Courier", 7) == 0;
- col ++;
- line ++;
-
- if (mono)
- {
- while (col < SizeColumns && line->ch != 0 && attr == line->attr)
- {
- font = Chars[line->ch] / 256;
- if (strncmp(Fonts[font][0], "Courier", 7) != 0 ||
- font != lastfont)
- break;
-
- col ++;
- line ++;
- }
- }
-
- if (Directions[lastfont] > 0)
- write_string(col - (line - start), row, line - start, start);
- else
- {
- /*
- * Do right-to-left text...
- */
-
- while (col < SizeColumns && line->ch != 0 && attr == line->attr)
- {
- if (Directions[Chars[line->ch] / 256] > 0 &&
- !ispunct(line->ch & 255) && !isspace(line->ch & 255))
- break;
-
- col ++;
- line ++;
- }
-
- for (i = 1; start < line; i ++, start ++)
- if (!isspace(start->ch & 255))
- write_string(col - i, row, 1, start);
- }
- }
- }
-}
-
-
-/*
- * 'write_string()' - Write a string of text.
- */
-
-static void
-write_string(int col, /* I - Start column */
- int row, /* I - Row */
- int len, /* I - Number of characters */
- lchar_t *s) /* I - String to print */
-{
- int ch; /* Current character */
- float x, y; /* Position of text */
- unsigned attr; /* Character attributes */
-
-
- /*
- * Position the text and set the font...
- */
-
- if (Duplex && (NumPages & 1) == 0)
- {
- x = PageWidth - PageRight;
- y = PageTop;
- }
- else
- {
- x = PageLeft;
- y = PageTop;
- }
-
- x += (float)col * 72.0f / (float)CharsPerInch;
- y -= (float)(row + 0.843) * 72.0f / (float)LinesPerInch;
-
- attr = s->attr;
-
- if (attr & ATTR_RAISED)
- y += 36.0 / (float)LinesPerInch;
- else if (attr & ATTR_LOWERED)
- y -= 36.0 / (float)LinesPerInch;
-
- if (x == (int)x)
- printf("%.0f ", x);
- else
- printf("%.3f ", x);
-
- if (y == (int)y)
- printf("%.0f ", y);
- else
- printf("%.3f ", y);
-
- if (attr & ATTR_BOLD)
- putchar('B');
- else if (attr & ATTR_ITALIC)
- putchar('I');
- else
- putchar('N');
-
- if (attr & ATTR_UNDERLINE)
- printf(" %.3f U", (float)len * 72.0 / (float)CharsPerInch);
-
- if (NumFonts > 1)
- {
- /*
- * Write a hex string...
- */
-
- putchar('<');
-
- while (len > 0)
- {
- printf("%04x", Chars[s->ch]);
-
- len --;
- s ++;
- }
-
- putchar('>');
- }
- else
- {
- /*
- * Write a quoted string...
- */
-
- putchar('(');
-
- while (len > 0)
- {
- ch = Chars[s->ch];
-
- if (ch < 32 || ch > 126)
- {
- /*
- * Quote 8-bit and control characters...
- */
-
- printf("\\%03o", ch);
- }
- else
- {
- /*
- * Quote the parenthesis and backslash as needed...
- */
-
- if (ch == '(' || ch == ')' || ch == '\\')
- putchar('\\');
-
- putchar(ch);
- }
-
- len --;
- s ++;
- }
-
- putchar(')');
- }
-
- if (PrettyPrint)
- {
- if (attr & ATTR_RED)
- puts("r");
- else if (attr & ATTR_GREEN)
- puts("g");
- else if (attr & ATTR_BLUE)
- puts("b");
- else
- puts("S");
- }
- else
- puts("S");
-}
-
-
-/*
- * 'write_text()' - Write a text string, quoting/encoding as needed.
- */
-
-static void
-write_text(const char *s) /* I - String to write */
-{
- int ch; /* Actual character value (UTF8) */
- const unsigned char *utf8; /* UTF8 text */
-
-
- if (NumFonts > 1)
- {
- /*
- * 8/8 encoding...
- */
-
- putchar('<');
-
- utf8 = (const unsigned char *)s;
-
- while (*utf8)
- {
- if (*utf8 < 0xc0 || !UTF8)
- ch = *utf8 ++;
- else if ((*utf8 & 0xe0) == 0xc0)
- {
- /*
- * Two byte character...
- */
-
- ch = ((utf8[0] & 0x1f) << 6) | (utf8[1] & 0x3f);
- utf8 += 2;
- }
- else
- {
- /*
- * Three byte character...
- */
-
- ch = ((((utf8[0] & 0x1f) << 6) | (utf8[1] & 0x3f)) << 6) |
- (utf8[2] & 0x3f);
- utf8 += 3;
- }
-
- printf("%04x", Chars[ch]);
- }
-
- putchar('>');
- }
- else
- {
- /*
- * Standard 8-bit encoding...
- */
-
- putchar('(');
-
- while (*s)
- {
- if (*s < 32 || *s > 126)
- printf("\\%03o", *s);
- else
- {
- if (*s == '(' || *s == ')' || *s == '\\')
- putchar('\\');
-
- putchar(*s);
- }
-
- s ++;
- }
-
- putchar(')');
- }
+ return (fonts);
}
--- /dev/null
+/*
+ * "$Id$"
+ *
+ * Common PostScript text code for the Common UNIX Printing System (CUPS).
+ *
+ * Copyright 2008 by Apple Inc.
+ *
+ * These coded instructions, statements, and computer programs are the
+ * property of Apple Inc. and are protected by Federal copyright
+ * law. Distribution and use rights are outlined in the file "LICENSE.txt"
+ * which should have been included with this file. If this file is
+ * file is missing or damaged, see the license at "http://www.cups.org/".
+ *
+ * This file is subject to the Apple OS-Developed Software exception.
+ *
+ * Contents:
+ *
+ */
+
+/*
+ * Include necessary headers...
+ */
+
+#include "pstext.h"
+#include <cups/i18n.h>
+
+
+/*
+ * Composite font names...
+ */
+
+static const char * const ps_font_names[] =
+{
+ "cupsNormal",
+ "cupsBold",
+ "cupsItalic",
+ "cupsBoldItalic"
+};
+
+
+/*
+ * 'psTextEmbedFonts()'- Embed PostScript fonts.
+ */
+
+void
+psTextEmbedFonts(ps_text_t *fonts) /* I - Font data */
+{
+ int i, j; /* Looping vars */
+ const char *cups_datadir; /* CUPS_DATADIR environment variable */
+ char *font; /* Current font */
+ char filename[1024]; /* Current filename */
+ FILE *fp; /* Current file */
+ char line[1024]; /* Line from file */
+ int ch; /* Character value */
+
+
+ /*
+ * Get the data directory...
+ */
+
+ if ((cups_datadir = getenv("CUPS_DATADIR")) == NULL)
+ cups_datadir = CUPS_DATADIR;
+
+ /*
+ * Embed each font...
+ */
+
+ for (font = (char *)cupsArrayFirst(fonts->unique);
+ font;
+ font = (char *)cupsArrayNext(fonts->unique))
+ {
+ printf("%%%%BeginResource: font %s\n", font);
+
+ snprintf(filename, sizeof(filename), "%s/fonts/%s", cups_datadir, font);
+ if ((fp = fopen(filename, "rb")) != NULL)
+ {
+ while ((j = fread(line, 1, sizeof(line), fp)) > 0)
+ fwrite(line, 1, j, stdout);
+
+ fclose(fp);
+ }
+
+ puts("\n%%EndResource");
+ }
+
+ /*
+ * Write the encoding arrays...
+ */
+
+ puts("% Character encodings");
+
+ for (i = 0; i < fonts->num_fonts; i ++)
+ {
+ printf("/cupsEncoding%02x [\n", i);
+
+ for (ch = 0; ch < 256; ch ++)
+ {
+ if (fonts->glyphs[fonts->codes[i * 256 + ch]])
+ printf("/%s", fonts->glyphs[fonts->codes[i * 256 + ch]]);
+ else if (fonts->codes[i * 256 + ch] > 255)
+ printf("/uni%04X", fonts->codes[i * 256 + ch]);
+ else
+ printf("/.notdef");
+
+ if ((ch & 7) == 7)
+ putchar('\n');
+ }
+
+ puts("] def");
+ }
+
+ /*
+ * Construct composite fonts... Start by reencoding the base fonts...
+ */
+
+ puts("% Reencode base fonts");
+
+ for (i = 0; i < 4; i ++)
+ for (j = 0; j < fonts->num_fonts; j ++)
+ {
+ printf("/%s findfont\n", fonts->fonts[j][i]);
+ printf("dup length 1 add dict begin\n"
+ " { 1 index /FID ne { def } { pop pop } ifelse } forall\n"
+ " /Encoding cupsEncoding%02x def\n"
+ " currentdict\n"
+ "end\n", j);
+ printf("/%s%02x exch definefont /%s%02x exch def\n", ps_font_names[i], j,
+ ps_font_names[i], j);
+ }
+
+ /*
+ * Then merge them into composite fonts...
+ */
+
+ puts("% Create composite fonts");
+
+ for (i = 0; i < 4; i ++)
+ {
+ puts("8 dict begin");
+ puts("/FontType 0 def/FontMatrix[1.0 0 0 1.0 0 0]def/FMapType 2 def"
+ "/Encoding[");
+ for (j = 0; j < fonts->num_fonts; j ++)
+ if (j == (fonts->num_fonts - 1))
+ printf("%d", j);
+ else if ((j & 15) == 15)
+ printf("%d\n", j);
+ else
+ printf("%d ", j);
+ puts("]def/FDepVector[");
+ for (j = 0; j < fonts->num_fonts; j ++)
+ if (j == (fonts->num_fonts - 1))
+ printf("%s%02x", ps_font_names[i], j);
+ else if ((j & 3) == 3)
+ printf("%s%02x\n", ps_font_names[i], j);
+ else
+ printf("%s%02x ", ps_font_names[i], j);
+ puts("]def currentdict end");
+ printf("/%s exch definefont pop\n", ps_font_names[i]);
+ }
+
+ /*
+ * Procedures...
+ */
+
+ puts("% Procedures to justify text...\n"
+ "/showcenter{dup stringwidth pop -0.5 mul 0 rmoveto show}bind def\n"
+ "/showleft{show}bind def\n"
+ "/showright{dup stringwidth pop neg 0 rmoveto show}bind def");
+}
+
+
+/*
+ * 'psTextListFonts()' - List PostScript fonts.
+ */
+
+void
+psTextListFonts(ps_text_t *fonts) /* I - Font data */
+{
+ char *font; /* Current font */
+
+
+ font = (char *)cupsArrayFirst(fonts->unique);
+ printf("%%%%DocumentSuppliedResources: font %s\n", font);
+ while ((font = (char *)cupsArrayNext(fonts->unique)) != NULL)
+ printf("%%%%+ font %s\n", font);
+}
+
+
+/*
+ * 'psTextInitialize()' - Load and embed font data for UTF-8 text.
+ */
+
+ps_text_t * /* O - Font data */
+psTextInitialize(void)
+{
+ ps_text_t *fonts; /* Font data */
+ int i, j; /* Looping vars */
+ char filename[1024]; /* Current filename */
+ FILE *fp; /* Current file */
+ const char *cups_datadir; /* CUPS_DATADIR environment variable */
+ char line[1024], /* Line from file */
+ *lineptr, /* Pointer into line */
+ *valptr; /* Pointer to value in line */
+ int unicode; /* Character value */
+ int start, end; /* Start and end values for range */
+ char glyph[64]; /* Glyph name */
+
+
+ /*
+ * Get the data directory...
+ */
+
+ if ((cups_datadir = getenv("CUPS_DATADIR")) == NULL)
+ cups_datadir = CUPS_DATADIR;
+
+ /*
+ * Initialize the PostScript text data...
+ */
+
+ fonts = (ps_text_t *)calloc(1, sizeof(ps_text_t));
+ fonts->size = -1.0;
+ fonts->style = -1;
+
+ /*
+ * Load the PostScript glyph names...
+ */
+
+ snprintf(filename, sizeof(filename), "%s/data/psglyphs", cups_datadir);
+
+ if ((fp = fopen(filename, "r")) != NULL)
+ {
+ while (fscanf(fp, "%x%63s", &unicode, glyph) == 2)
+ fonts->glyphs[unicode] = _cupsStrAlloc(glyph);
+
+ fclose(fp);
+ }
+ else
+ {
+ _cupsLangPrintf(stderr, _("ERROR: Unable to open \"%s\" - %s\n"), filename,
+ strerror(errno));
+ exit(1);
+ }
+
+ /*
+ * Open the UTF-8 character set definition...
+ */
+
+ snprintf(filename, sizeof(filename), "%s/charsets/utf-8", cups_datadir);
+
+ if ((fp = fopen(filename, "r")) == NULL)
+ {
+ /*
+ * Can't open charset file!
+ */
+
+ _cupsLangPrintf(stderr, _("ERROR: Unable to open %s: %s\n"), filename,
+ strerror(errno));
+ exit(1);
+ }
+
+ if (!fgets(line, sizeof(line), fp) || strncmp(line, "charset utf8", 12))
+ {
+ /*
+ * Bad/empty charset file!
+ */
+
+ fclose(fp);
+ _cupsLangPrintf(stderr, _("ERROR: Bad charset file %s\n"), filename);
+ exit(1);
+ }
+
+ /*
+ * Read the font descriptions...
+ */
+
+ fonts->unique = cupsArrayNew((cups_array_func_t)strcmp, NULL);
+
+ while (fgets(line, sizeof(line), fp) != NULL)
+ {
+ /*
+ * Skip comment and blank lines...
+ */
+
+ if (line[0] == '#' || line[0] == '\n')
+ continue;
+
+ /*
+ * Read the font descriptions that should look like:
+ *
+ * start end direction width normal [bold italic bold-italic]
+ */
+
+ lineptr = line;
+
+ start = strtol(lineptr, &lineptr, 16);
+ end = strtol(lineptr, &lineptr, 16);
+
+ while (isspace(*lineptr & 255))
+ lineptr ++;
+
+ valptr = lineptr;
+
+ while (!isspace(*lineptr & 255) && *lineptr)
+ lineptr ++;
+
+ if (!*lineptr)
+ {
+ /*
+ * Can't have a font without all required values...
+ */
+
+ _cupsLangPrintf(stderr, _("ERROR: Bad font description line: %s\n"),
+ valptr);
+ fclose(fp);
+ exit(1);
+ }
+
+ *lineptr++ = '\0';
+
+ if (!strcmp(valptr, "ltor"))
+ fonts->directions[fonts->num_fonts] = 1;
+ else if (!strcmp(valptr, "rtol"))
+ fonts->directions[fonts->num_fonts] = -1;
+ else
+ {
+ _cupsLangPrintf(stderr, _("ERROR: Bad text direction %s\n"), valptr);
+ fclose(fp);
+ exit(1);
+ }
+
+ /*
+ * Got the direction, now get the width...
+ */
+
+ while (isspace(*lineptr & 255))
+ lineptr ++;
+
+ valptr = lineptr;
+
+ while (!isspace(*lineptr & 255) && *lineptr)
+ lineptr ++;
+
+ if (!*lineptr)
+ {
+ /*
+ * Can't have a font without all required values...
+ */
+
+ _cupsLangPrintf(stderr, _("ERROR: Bad font description line: %s\n"),
+ valptr);
+ fclose(fp);
+ exit(1);
+ }
+
+ *lineptr++ = '\0';
+
+ if (!strcmp(valptr, "single"))
+ fonts->widths[fonts->num_fonts] = 1;
+ else if (!strcmp(valptr, "double"))
+ fonts->widths[fonts->num_fonts] = 2;
+ else
+ {
+ _cupsLangPrintf(stderr, _("ERROR: Bad text width %s\n"), valptr);
+ fclose(fp);
+ exit(1);
+ }
+
+ /*
+ * Get the fonts...
+ */
+
+ for (i = 0; *lineptr && i < 4; i ++)
+ {
+ while (isspace(*lineptr & 255))
+ lineptr ++;
+
+ valptr = lineptr;
+
+ while (!isspace(*lineptr & 255) && *lineptr)
+ lineptr ++;
+
+ if (*lineptr)
+ *lineptr++ = '\0';
+
+ if (lineptr > valptr)
+ {
+ if (!cupsArrayFind(fonts->unique, valptr))
+ cupsArrayAdd(fonts->unique, _cupsStrAlloc(valptr));
+
+ fonts->fonts[fonts->num_fonts][i] = _cupsStrAlloc(valptr);
+ }
+ }
+
+ /*
+ * Fill in remaining fonts as needed...
+ */
+
+ for (j = i; j < 4; j ++)
+ fonts->fonts[fonts->num_fonts][j] =
+ _cupsStrAlloc(fonts->fonts[fonts->num_fonts][0]);
+
+ /*
+ * Define the character mappings...
+ */
+
+ for (i = start, j = fonts->num_fonts * 256; i <= end; i ++, j ++)
+ {
+ fonts->chars[i] = j;
+ fonts->codes[j] = i;
+ }
+
+ /*
+ * Move to the next font, stopping if needed...
+ */
+
+ fonts->num_fonts ++;
+ if (fonts->num_fonts >= 256)
+ break;
+ }
+
+ fclose(fp);
+
+ if (cupsArrayCount(fonts->unique) == 0)
+ {
+ _cupsLangPrintf(stderr, _("ERROR: No fonts in charset file %s\n"), filename);
+ exit(1);
+ }
+
+ return (fonts);
+}
+
+
+/*
+ * 'psTextUTF8()' - Output UTF-8 text at the current position.
+ */
+
+void
+psTextUTF8(ps_text_t *fonts, /* I - Font data */
+ float size, /* I - Size in points */
+ int style, /* I - Style */
+ int align, /* I - Alignment */
+ const char *text) /* I - UTF-8 text */
+{
+ cups_utf32_t utf32[2048]; /* Temporary buffer */
+ int utf32len; /* Number of characters */
+
+
+ if ((utf32len = cupsUTF8ToUTF32(utf32, (cups_utf8_t *)text,
+ (int)(sizeof(utf32) / sizeof(utf32[0])))) > 0)
+ psTextUTF32(fonts, size, style, align, utf32, utf32len);
+}
+
+
+/*
+ * 'psTextUTF32()' - Output UTF-32 text at the current position.
+ */
+
+void
+psTextUTF32(ps_text_t *fonts, /* I - Font data */
+ float size, /* I - Size in points */
+ int style, /* I - Font style */
+ int align, /* I - Alignment */
+ const cups_utf32_t *text, /* I - UTF-32 text */
+ int textlen) /* I - Length of text */
+{
+ if (size != fonts->size || style != fonts->style)
+ {
+ printf("/%s findfont %g scalefont setfont\n", ps_font_names[style], size);
+ fonts->size = size;
+ fonts->style = style;
+ }
+
+ putchar('<');
+ while (textlen > 0)
+ {
+ printf("%04x", fonts->chars[*text]);
+ text ++;
+ textlen --;
+ }
+
+ if (align == PS_CENTER)
+ puts(">showcenter");
+ else if (align == PS_RIGHT)
+ puts(">showright");
+ else
+ puts(">showleft");
+
+}
+
+
+/*
+ * End of "$Id$".
+ */