]> git.ipfire.org Git - thirdparty/cups.git/commitdiff
Add application/vnd.cups-banner MIME type and filter.
authormike <mike@7a7537e8-13f0-0310-91df-b6672ffda945>
Wed, 1 Oct 2008 04:48:33 +0000 (04:48 +0000)
committermike <mike@7a7537e8-13f0-0310-91df-b6672ffda945>
Wed, 1 Oct 2008 04:48:33 +0000 (04:48 +0000)
Add new common PostScript text code.

Banner filter needs common.o and pstext.o.

Need to use _cupsLangPrintf for localized messages.

git-svn-id: svn+ssh://src.apple.com/svn/cups/cups.org/trunk@7995 7a7537e8-13f0-0310-91df-b6672ffda945

conf/mime.convs.in
conf/mime.types
cups/transcode.c
filter/Makefile
filter/bannertops.c
filter/pstext.c [new file with mode: 0644]
filter/pstext.h [new file with mode: 0644]
filter/textcommon.c

index aea1df45812931555ca1f29457b2cd732df7edcc..8c98e9e4bb81941f9271b10e33748c895390bbaa 100644 (file)
@@ -7,7 +7,7 @@
 #
 #   MIME converts file for the Common UNIX Printing System (CUPS).
 #
-#   Copyright 2007 by Apple Inc.
+#   Copyright 2007-2008 by Apple Inc.
 #   Copyright 1997-2007 by Easy Software Products.
 #
 #   These coded instructions, statements, and computer programs are the
 # PostScript filters
 #
 
-application/pdf                application/postscript  33      pdftops
-application/postscript application/vnd.cups-postscript 66      pstops
-application/vnd.hp-HPGL        application/postscript  66      hpgltops
-application/x-cshell   application/postscript  33      texttops
-application/x-csource  application/postscript  33      texttops
-application/x-perl     application/postscript  33      texttops
-application/x-shell    application/postscript  33      texttops
-text/plain             application/postscript  33      texttops
-text/html              application/postscript  33      texttops
-image/gif              application/vnd.cups-postscript 66      imagetops
-image/png              application/vnd.cups-postscript 66      imagetops
-image/jpeg             application/vnd.cups-postscript 66      imagetops
-image/tiff             application/vnd.cups-postscript 66      imagetops
-image/x-bitmap         application/vnd.cups-postscript 66      imagetops
-image/x-photocd                application/vnd.cups-postscript 66      imagetops
-image/x-portable-anymap        application/vnd.cups-postscript 66      imagetops
-image/x-portable-bitmap        application/vnd.cups-postscript 66      imagetops
-image/x-portable-graymap application/vnd.cups-postscript       66      imagetops
-image/x-portable-pixmap        application/vnd.cups-postscript 66      imagetops
-image/x-sgi-rgb                application/vnd.cups-postscript 66      imagetops
-image/x-xbitmap                application/vnd.cups-postscript 66      imagetops
-image/x-xpixmap                application/vnd.cups-postscript 66      imagetops
-#image/x-xwindowdump   application/vnd.cups-postscript 66      imagetops
-image/x-sun-raster     application/vnd.cups-postscript 66      imagetops
-
-
-########################################################################
-#
-# Form filter...
-#
-# This filter does not currently exist, but the file format is defined
-# in the IDD and registered with the IANA for future use...
-#
-
-#application/vnd.cups-form application/vnd.cups-postscript 33 formtops
+application/pdf                        application/postscript          33      pdftops
+application/postscript         application/vnd.cups-postscript 66      pstops
+application/vnd.hp-HPGL                application/postscript          66      hpgltops
+application/x-cshell           application/postscript          33      texttops
+application/x-csource          application/postscript          33      texttops
+application/x-perl             application/postscript          33      texttops
+application/x-shell            application/postscript          33      texttops
+text/plain                     application/postscript          33      texttops
+text/html                      application/postscript          33      texttops
+image/gif                      application/vnd.cups-postscript 66      imagetops
+image/png                      application/vnd.cups-postscript 66      imagetops
+image/jpeg                     application/vnd.cups-postscript 66      imagetops
+image/tiff                     application/vnd.cups-postscript 66      imagetops
+image/x-bitmap                 application/vnd.cups-postscript 66      imagetops
+image/x-photocd                        application/vnd.cups-postscript 66      imagetops
+image/x-portable-anymap                application/vnd.cups-postscript 66      imagetops
+image/x-portable-bitmap                application/vnd.cups-postscript 66      imagetops
+image/x-portable-graymap       application/vnd.cups-postscript 66      imagetops
+image/x-portable-pixmap                application/vnd.cups-postscript 66      imagetops
+image/x-sgi-rgb                        application/vnd.cups-postscript 66      imagetops
+image/x-xbitmap                        application/vnd.cups-postscript 66      imagetops
+image/x-xpixmap                        application/vnd.cups-postscript 66      imagetops
+#image/x-xwindowdump           application/vnd.cups-postscript 66      imagetops
+image/x-sun-raster             application/vnd.cups-postscript 66      imagetops
+application/vnd.cups-banner    application/vnd.cups-postscript 33      bannertops
 
 ########################################################################
 #
 # Raster filters...
 #
 
-image/gif              application/vnd.cups-raster     100     imagetoraster
-image/png              application/vnd.cups-raster     100     imagetoraster
-image/jpeg             application/vnd.cups-raster     100     imagetoraster
-image/tiff             application/vnd.cups-raster     100     imagetoraster
-image/x-bitmap         application/vnd.cups-raster     100     imagetoraster
-image/x-photocd                application/vnd.cups-raster     100     imagetoraster
-image/x-portable-anymap        application/vnd.cups-raster     100     imagetoraster
-image/x-portable-bitmap        application/vnd.cups-raster     100     imagetoraster
-image/x-portable-graymap application/vnd.cups-raster   100     imagetoraster
-image/x-portable-pixmap        application/vnd.cups-raster     100     imagetoraster
-image/x-sgi-rgb                application/vnd.cups-raster     100     imagetoraster
-image/x-xbitmap                application/vnd.cups-raster     100     imagetoraster
-image/x-xpixmap                application/vnd.cups-raster     100     imagetoraster
-#image/x-xwindowdump   application/vnd.cups-raster     100     imagetoraster
-image/x-sun-raster     application/vnd.cups-raster     100     imagetoraster
+image/gif                      application/vnd.cups-raster     100     imagetoraster
+image/png                      application/vnd.cups-raster     100     imagetoraster
+image/jpeg                     application/vnd.cups-raster     100     imagetoraster
+image/tiff                     application/vnd.cups-raster     100     imagetoraster
+image/x-bitmap                 application/vnd.cups-raster     100     imagetoraster
+image/x-photocd                        application/vnd.cups-raster     100     imagetoraster
+image/x-portable-anymap                application/vnd.cups-raster     100     imagetoraster
+image/x-portable-bitmap                application/vnd.cups-raster     100     imagetoraster
+image/x-portable-graymap       application/vnd.cups-raster     100     imagetoraster
+image/x-portable-pixmap                application/vnd.cups-raster     100     imagetoraster
+image/x-sgi-rgb                        application/vnd.cups-raster     100     imagetoraster
+image/x-xbitmap                        application/vnd.cups-raster     100     imagetoraster
+image/x-xpixmap                        application/vnd.cups-raster     100     imagetoraster
+#image/x-xwindowdump           application/vnd.cups-raster     100     imagetoraster
+image/x-sun-raster             application/vnd.cups-raster     100     imagetoraster
 
 # pstoraster is part of GPL Ghostscript...
 application/vnd.cups-postscript        application/vnd.cups-raster     100     pstoraster
index 56a0642f4ed17048a919f26e762e4b6dc73445c2..6c47eff3640f125bf92262a9b2f12405555ff835 100644 (file)
@@ -151,12 +151,14 @@ application/rss+xml               rss
 # CUPS-specific types...
 #
 
+application/vnd.cups-banner    string(0,'#CUPS-BANNER')
 application/vnd.cups-command   string(0,'#CUPS-COMMAND')
-application/vnd.cups-form      string(0,"<CUPSFORM>")
 application/vnd.cups-pdf
 application/vnd.cups-postscript
 application/vnd.cups-ppd       ppd string(0,"*PPD-Adobe:")
-application/vnd.cups-raster    string(0,"RaSt") string(0,"tSaR")
+application/vnd.cups-raster    string(0,"RaSt") string(0,"tSaR") \
+                               string(0,"RaS2") string(0,"2SaR") \
+                               string(0,"RaS3") string(0,"3SaR")
 application/vnd.cups-raw       (string(0,<1B>E) + !string(2,<1B>%0B)) \
                                string(0,<1B>@) \
                                (contains(0,128,<1B>%-12345X) + \
index 796af97fea88bcfe60b42f9650ce073a17060126..40382f57eed8b2b0891af71925c29e3304ccdd54 100644 (file)
@@ -487,11 +487,9 @@ cupsUTF8ToUTF32(
   }
 
  /*
-  * Convert input UTF-8 to output UTF-32 (and insert BOM)...
+  * Convert input UTF-8 to output UTF-32...
   */
 
-  *dest++ = 0xfeff;
-
   for (i = maxout - 1; *src && i > 0; i --)
   {
     ch = *src++;
index 76934da009829e9aca10140b62e3fa46fff78d80..43fbf4cd868e1653554d82a68d71a1460be6116a 100644 (file)
@@ -53,7 +53,7 @@ IMAGE64OBJS = $(IMAGEOBJS:.o=.64.o)
 FORMOBJS =     form-attr.o form-main.o form-ps.o form-text.o form-tree.o
 OBJS   =       $(HPGLOBJS) $(IMAGEOBJS) $(FORMOBJS) \
                bannertops.o commandtops.o gziptoany.o imagetops.o \
-               imagetoraster.o common.o pdftops.o pstops.o \
+               imagetoraster.o common.o pdftops.o pstext.o pstops.o \
                rasterbench.o rastertoepson.o rastertohp.o rastertolabel.o \
                testimage.o testraster.o textcommon.o texttops.o
 
@@ -236,9 +236,9 @@ framedhelp:
 # bannertops
 #
 
-bannertops:    bannertops.o ../cups/$(LIBCUPS) $(LIBCUPSIMAGE)
+bannertops:    bannertops.o pstext.o common.o ../cups/$(LIBCUPS) $(LIBCUPSIMAGE)
        echo Linking $@...
-       $(CC) $(LDFLAGS) -o $@ bannertops.o $(LIBS)
+       $(CC) $(LDFLAGS) -o $@ bannertops.o pstext.o common.o $(LIBS)
 
 
 #
index b4af85090bebee893000862f073de2b74cffd0fb..47df8c8582d2aab3da08e28485eee5d8a0be0be6 100644 (file)
@@ -21,7 +21,7 @@
  * 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 */
 
 
@@ -100,85 +127,42 @@ WritePage(void)
   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...
@@ -189,1105 +173,21 @@ WriteProlog(const char *title,          /* I - Title of job */
   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);
 }
 
 
diff --git a/filter/pstext.c b/filter/pstext.c
new file mode 100644 (file)
index 0000000..4f418aa
--- /dev/null
@@ -0,0 +1,493 @@
+/*
+ * "$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$".
+ */
diff --git a/filter/pstext.h b/filter/pstext.h
new file mode 100644 (file)
index 0000000..fea5b0a
--- /dev/null
@@ -0,0 +1,75 @@
+/*
+ * "$Id$"
+ *
+ *   Common PostScript text definitions 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.
+ */
+
+/*
+ * Include necessary headers...
+ */
+
+#include "common.h"
+#include <cups/transcode.h>
+
+
+/*
+ * Constants...
+ */
+
+#define PS_NORMAL      0       /* Normal text */
+#define PS_BOLD                1       /* Bold text */
+#define PS_ITALIC      2       /* Italic text */
+#define PS_BOLDITALIC  3       /* Bold italic text */
+
+#define PS_LEFT                1       /* Left-justified text */
+#define PS_CENTER      0       /* Center-justified text */
+#define PS_RIGHT       -1      /* Right-justified text */
+
+
+/*
+ * Structures...
+ */
+
+typedef struct ps_text_s       /**** PostScript font data ****/
+{
+  char         *glyphs[65536]; /* PostScript glyphs for Unicode */
+  int          num_fonts;      /* Number of fonts to use */
+  char         *fonts[256][4]; /* Fonts to use */
+  cups_array_t *unique;        /* Unique fonts */
+  unsigned short chars[65536], /* 0xffcc (ff = font, cc = char) */
+               codes[65536];   /* Unicode glyph mapping to fonts */
+  int          widths[256],    /* Widths of each font */
+               directions[256];/* Text directions for each font */
+  float                size;           /* Current text size */
+  int          style;          /* Current text style */
+} ps_text_t;
+
+
+/*
+ * Functions...
+ */
+
+extern void            psTextEmbedFonts(ps_text_t *fonts);
+extern void            psTextListFonts(ps_text_t *fonts);
+extern ps_text_t       *psTextInitialize(void);
+extern void            psTextUTF8(ps_text_t *fonts, float size, int style,
+                                  int align, const char *text);
+extern void            psTextUTF32(ps_text_t *fonts, float size, int style,
+                                   int align, const cups_utf32_t *text,
+                                   int textlen);
+
+
+/*
+ * End of "$Id$".
+ */
index 75b9832bac1070814c87e7fbb3ca58acc70dcbae..afcec062cdd9d70f80b7b933b479ecd99928db08 100644 (file)
@@ -515,8 +515,9 @@ TextMain(const char *name,  /* I - Name of filter */
 
   if (argc < 6 || argc > 7)
   {
-    fprintf(stderr, _("Usage: %s job-id user title copies options [file]\n"),
-            name);
+    _cupsLangPrintf(stderr,
+                    _("Usage: %s job-id user title copies options [file]\n"),
+                    name);
     return (1);
   }