From: mike Date: Wed, 1 Oct 2008 04:48:33 +0000 (+0000) Subject: Add application/vnd.cups-banner MIME type and filter. X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=feeebb42ec6c74643212dccee5019dc8476dd5cf;p=thirdparty%2Fcups.git Add application/vnd.cups-banner MIME type and filter. 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 --- diff --git a/conf/mime.convs.in b/conf/mime.convs.in index aea1df4581..8c98e9e4bb 100644 --- a/conf/mime.convs.in +++ b/conf/mime.convs.in @@ -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 @@ -38,62 +38,52 @@ # 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 diff --git a/conf/mime.types b/conf/mime.types index 56a0642f4e..6c47eff364 100644 --- a/conf/mime.types +++ b/conf/mime.types @@ -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,"") 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) + \ diff --git a/cups/transcode.c b/cups/transcode.c index 796af97fea..40382f57ee 100644 --- a/cups/transcode.c +++ b/cups/transcode.c @@ -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++; diff --git a/filter/Makefile b/filter/Makefile index 76934da009..43fbf4cd86 100644 --- a/filter/Makefile +++ b/filter/Makefile @@ -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) # diff --git a/filter/bannertops.c b/filter/bannertops.c index b4af85090b..47df8c8582 100644 --- a/filter/bannertops.c +++ b/filter/bannertops.c @@ -21,7 +21,7 @@ * Include necessary headers... */ -#include "common.h" +#include "pstext.h" #include "image.h" #include @@ -30,58 +30,85 @@ * 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 index 0000000000..4f418aad51 --- /dev/null +++ b/filter/pstext.c @@ -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 + + +/* + * 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 index 0000000000..fea5b0a753 --- /dev/null +++ b/filter/pstext.h @@ -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 + + +/* + * 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$". + */ diff --git a/filter/textcommon.c b/filter/textcommon.c index 75b9832bac..afcec062cd 100644 --- a/filter/textcommon.c +++ b/filter/textcommon.c @@ -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); }