]>
git.ipfire.org Git - thirdparty/cups.git/blob - filter/texttops.c
2 * "$Id: texttops.c 6420 2007-03-30 20:00:59Z mike $"
4 * Text to PostScript filter for the Common UNIX Printing System (CUPS).
6 * Copyright 1993-2007 by Easy Software Products.
8 * These coded instructions, statements, and computer programs are the
9 * property of Easy Software Products and are protected by Federal
10 * copyright law. Distribution and use rights are outlined in the file
11 * "LICENSE.txt" which should have been included with this file. If this
12 * file is missing or damaged please contact Easy Software Products
15 * Attn: CUPS Licensing Information
16 * Easy Software Products
17 * 44141 Airport View Drive, Suite 204
18 * Hollywood, Maryland 20636 USA
20 * Voice: (301) 373-9600
21 * EMail: cups-info@cups.org
22 * WWW: http://www.cups.org
24 * This file is subject to the Apple OS-Developed Software exception.
28 * main() - Main entry for text to PostScript filter.
29 * WriteEpilogue() - Write the PostScript file epilogue.
30 * WritePage() - Write a page of text.
31 * WriteProlog() - Write the PostScript file prolog with options.
32 * write_line() - Write a row of text.
33 * write_string() - Write a string of text.
37 * Include necessary headers...
40 #include "textcommon.h"
41 #include <cups/i18n.h>
48 char *Glyphs
[65536]; /* PostScript glyphs for Unicode */
49 int NumFonts
; /* Number of fonts to use */
50 char *Fonts
[256][4]; /* Fonts to use */
51 unsigned short Chars
[65536]; /* 0xffcc (ff = font, cc = char) */
52 unsigned short Codes
[65536]; /* Unicode glyph mapping to fonts */
53 int Widths
[256]; /* Widths of each font */
54 int Directions
[256];/* Text directions for each font */
61 static void write_line(int row
, lchar_t
*line
);
62 static void write_string(int col
, int row
, int len
, lchar_t
*s
);
63 static void write_text(const char *s
);
67 * 'main()' - Main entry for text to PostScript filter.
70 int /* O - Exit status */
71 main(int argc
, /* I - Number of command-line arguments */
72 char *argv
[]) /* I - Command-line arguments */
74 return (TextMain("texttops", argc
, argv
));
79 * 'WriteEpilogue()' - Write the PostScript file epilogue.
86 printf("%%%%Pages: %d\n", NumPages
);
95 * 'WritePage()' - Write a page of text.
101 int line
; /* Current line */
105 printf("%%%%Page: %d %d\n", NumPages
, NumPages
);
110 printf("%d H\n", NumPages
);
112 for (line
= 0; line
< SizeLines
; line
++)
113 write_line(line
, Page
[line
]);
118 memset(Page
[0], 0, sizeof(lchar_t
) * SizeColumns
* SizeLines
);
123 * 'WriteProlog()' - Write the PostScript file prolog with options.
127 WriteProlog(const char *title
, /* I - Title of job */
128 const char *user
, /* I - Username */
129 const char *classification
, /* I - Classification */
130 const char *label
, /* I - Page label */
131 ppd_file_t
*ppd
) /* I - PPD file info */
133 int i
, j
, k
; /* Looping vars */
134 char *charset
; /* Character set string */
135 char filename
[1024]; /* Glyph filenames */
136 FILE *fp
; /* Glyph files */
137 const char *datadir
; /* CUPS_DATADIR environment variable */
138 char line
[1024], /* Line from file */
139 *lineptr
, /* Pointer into line */
140 *valptr
; /* Pointer to value in line */
141 int ch
, unicode
; /* Character values */
142 int start
, end
; /* Start and end values for range */
143 char glyph
[64]; /* Glyph name */
144 time_t curtime
; /* Current time */
145 struct tm
*curtm
; /* Current date */
146 char curdate
[255]; /* Current date (text format) */
147 int num_fonts
; /* Number of unique fonts */
148 char *fonts
[1024]; /* Unique fonts */
149 static char *names
[] = /* Font names */
158 * Get the data directory...
161 if ((datadir
= getenv("CUPS_DATADIR")) == NULL
)
162 datadir
= CUPS_DATADIR
;
165 * Adjust margins as necessary...
168 if (classification
|| label
)
171 * Leave room for labels...
179 * Allocate memory for the page...
182 SizeColumns
= (PageRight
- PageLeft
) / 72.0 * CharsPerInch
;
183 SizeLines
= (PageTop
- PageBottom
) / 72.0 * LinesPerInch
;
185 Page
= calloc(sizeof(lchar_t
*), SizeLines
);
186 Page
[0] = calloc(sizeof(lchar_t
), SizeColumns
* SizeLines
);
187 for (i
= 1; i
< SizeLines
; i
++)
188 Page
[i
] = Page
[0] + i
* SizeColumns
;
192 ColumnGutter
= CharsPerInch
/ 2;
193 ColumnWidth
= (SizeColumns
- ColumnGutter
* (PageColumns
- 1)) /
197 ColumnWidth
= SizeColumns
;
200 * Output the DSC header...
203 curtime
= time(NULL
);
204 curtm
= localtime(&curtime
);
205 strftime(curdate
, sizeof(curdate
), "%c", curtm
);
207 puts("%!PS-Adobe-3.0");
208 printf("%%%%BoundingBox: 0 0 %.0f %.0f\n", PageWidth
, PageLength
);
209 printf("%%cupsRotation: %d\n", (Orientation
& 3) * 90);
210 puts("%%Creator: texttops/" CUPS_SVERSION
);
211 printf("%%%%CreationDate: %s\n", curdate
);
212 WriteTextComment("Title", title
);
213 WriteTextComment("For", user
);
214 puts("%%Pages: (atend)");
217 * Initialize globals...
221 memset(Fonts
, 0, sizeof(Fonts
));
222 memset(Glyphs
, 0, sizeof(Glyphs
));
223 memset(Chars
, 0, sizeof(Chars
));
224 memset(Codes
, 0, sizeof(Codes
));
227 * Load the PostScript glyph names and the corresponding character
231 snprintf(filename
, sizeof(filename
), "%s/data/psglyphs", datadir
);
233 if ((fp
= fopen(filename
, "r")) != NULL
)
235 while (fscanf(fp
, "%x%63s", &unicode
, glyph
) == 2)
236 Glyphs
[unicode
] = strdup(glyph
);
242 fprintf(stderr
, _("ERROR: Unable to open \"%s\" - %s\n"), filename
,
248 * Get the output character set...
251 charset
= getenv("CHARSET");
252 if (charset
!= NULL
&& strcmp(charset
, "us-ascii") != 0)
254 snprintf(filename
, sizeof(filename
), "%s/charsets/%s", datadir
, charset
);
256 if ((fp
= fopen(filename
, "r")) == NULL
)
259 * Can't open charset file!
262 fprintf(stderr
, _("ERROR: Unable to open %s: %s\n"), filename
,
268 * Opened charset file; now see if this is really a charset file...
271 if (fgets(line
, sizeof(line
), fp
) == NULL
)
274 * Bad/empty charset file!
278 fprintf(stderr
, _("ERROR: Bad charset file %s\n"), filename
);
282 if (strncmp(line
, "charset", 7) != 0)
285 * Bad format/not a charset file!
289 fprintf(stderr
, _("ERROR: Bad charset file %s\n"), filename
);
294 * See if this is an 8-bit or UTF-8 character set file...
297 line
[strlen(line
) - 1] = '\0'; /* Drop \n */
298 for (lineptr
= line
+ 7; isspace(*lineptr
& 255); lineptr
++); /* Skip whitespace */
300 if (strcmp(lineptr
, "8bit") == 0)
310 * Read the font description(s)...
313 while (fgets(line
, sizeof(line
), fp
) != NULL
)
316 * Skip comment and blank lines...
319 if (line
[0] == '#' || line
[0] == '\n')
323 * Read the font descriptions that should look like:
325 * first last direction width normal [bold italic bold-italic]
330 start
= strtol(lineptr
, &lineptr
, 16);
331 end
= strtol(lineptr
, &lineptr
, 16);
333 while (isspace(*lineptr
& 255))
337 break; /* Must be a font mapping */
341 while (!isspace(*lineptr
& 255) && *lineptr
)
347 * Can't have a font without all required values...
350 fprintf(stderr
, _("ERROR: Bad font description line: %s\n"), valptr
);
357 if (strcmp(valptr
, "ltor") == 0)
358 Directions
[NumFonts
] = 1;
359 else if (strcmp(valptr
, "rtol") == 0)
360 Directions
[NumFonts
] = -1;
363 fprintf(stderr
, _("ERROR: Bad text direction %s\n"), valptr
);
369 * Got the direction, now get the width...
372 while (isspace(*lineptr
& 255))
377 while (!isspace(*lineptr
& 255) && *lineptr
)
383 * Can't have a font without all required values...
386 fprintf(stderr
, _("ERROR: Bad font description line: %s\n"), valptr
);
393 if (strcmp(valptr
, "single") == 0)
394 Widths
[NumFonts
] = 1;
395 else if (strcmp(valptr
, "double") == 0)
396 Widths
[NumFonts
] = 2;
399 fprintf(stderr
, _("ERROR: Bad text width %s\n"), valptr
);
408 for (i
= 0; *lineptr
&& i
< 4; i
++)
410 while (isspace(*lineptr
& 255))
415 while (!isspace(*lineptr
& 255) && *lineptr
)
421 if (lineptr
> valptr
)
422 Fonts
[NumFonts
][i
] = strdup(valptr
);
426 * Fill in remaining fonts as needed...
429 for (j
= i
; j
< 4; j
++)
430 Fonts
[NumFonts
][j
] = strdup(Fonts
[NumFonts
][0]);
433 * Define the character mappings...
436 for (i
= start
, j
= NumFonts
* 256; i
<= end
; i
++, j
++)
443 * Read encoding lines...
449 * Skip comment and blank lines...
452 if (line
[0] == '#' || line
[0] == '\n')
456 * Grab the character and unicode glyph number.
459 if (sscanf(line
, "%x%x", &ch
, &unicode
) == 2 && ch
< 256)
460 Codes
[Chars
[ch
]] = unicode
;
462 while (fgets(line
, sizeof(line
), fp
) != NULL
);
466 else if (strcmp(lineptr
, "utf8") == 0)
469 * UTF-8 (Unicode) text...
475 * Read the font descriptions...
480 while (fgets(line
, sizeof(line
), fp
) != NULL
)
483 * Skip comment and blank lines...
486 if (line
[0] == '#' || line
[0] == '\n')
490 * Read the font descriptions that should look like:
492 * start end direction width normal [bold italic bold-italic]
497 start
= strtol(lineptr
, &lineptr
, 16);
498 end
= strtol(lineptr
, &lineptr
, 16);
500 while (isspace(*lineptr
& 255))
505 while (!isspace(*lineptr
& 255) && *lineptr
)
511 * Can't have a font without all required values...
514 fprintf(stderr
, _("ERROR: Bad font description line: %s\n"), valptr
);
521 if (strcmp(valptr
, "ltor") == 0)
522 Directions
[NumFonts
] = 1;
523 else if (strcmp(valptr
, "rtol") == 0)
524 Directions
[NumFonts
] = -1;
527 fprintf(stderr
, _("ERROR: Bad text direction %s\n"), valptr
);
533 * Got the direction, now get the width...
536 while (isspace(*lineptr
& 255))
541 while (!isspace(*lineptr
& 255) && *lineptr
)
547 * Can't have a font without all required values...
550 fprintf(stderr
, _("ERROR: Bad font description line: %s\n"), valptr
);
557 if (strcmp(valptr
, "single") == 0)
558 Widths
[NumFonts
] = 1;
559 else if (strcmp(valptr
, "double") == 0)
560 Widths
[NumFonts
] = 2;
563 fprintf(stderr
, _("ERROR: Bad text width %s\n"), valptr
);
572 for (i
= 0; *lineptr
&& i
< 4; i
++)
574 while (isspace(*lineptr
& 255))
579 while (!isspace(*lineptr
& 255) && *lineptr
)
585 if (lineptr
> valptr
)
586 Fonts
[NumFonts
][i
] = strdup(valptr
);
590 * Fill in remaining fonts as needed...
593 for (j
= i
; j
< 4; j
++)
594 Fonts
[NumFonts
][j
] = strdup(Fonts
[NumFonts
][0]);
597 * Define the character mappings...
600 for (i
= start
, j
= NumFonts
* 256; i
<= end
; i
++, j
++)
607 * Move to the next font, stopping if needed...
619 fprintf(stderr
, _("ERROR: Bad charset type %s\n"), lineptr
);
627 * Standard ASCII output just uses Courier, Courier-Bold, and
628 * possibly Courier-Oblique.
633 Fonts
[0][ATTR_NORMAL
] = strdup("Courier");
634 Fonts
[0][ATTR_BOLD
] = strdup("Courier-Bold");
635 Fonts
[0][ATTR_ITALIC
] = strdup("Courier-Oblique");
636 Fonts
[0][ATTR_BOLDITALIC
] = strdup("Courier-BoldOblique");
642 * Define US-ASCII characters...
645 for (i
= 32; i
< 127; i
++)
653 * Generate a list of unique fonts to use...
656 for (i
= 0, num_fonts
= 0; i
< NumFonts
; i
++)
657 for (j
= PrettyPrint
? 2 : 1; j
>= 0; j
--)
659 for (k
= 0; k
< num_fonts
; k
++)
660 if (strcmp(Fonts
[i
][j
], fonts
[k
]) == 0)
669 fonts
[num_fonts
] = Fonts
[i
][j
];
675 * List the fonts that will be used...
678 for (i
= 0; i
< num_fonts
; i
++)
680 printf("%%%%DocumentNeededResources: font %s\n", fonts
[i
]);
682 printf("%%%%+ font %s\n", fonts
[i
]);
684 puts("%%DocumentSuppliedResources: procset texttops 1.1 0");
686 for (i
= 0; i
< num_fonts
; i
++)
690 fprintf(stderr
, "DEBUG: ppd->num_fonts = %d\n", ppd
->num_fonts
);
692 for (j
= 0; j
< ppd
->num_fonts
; j
++)
694 fprintf(stderr
, "DEBUG: ppd->fonts[%d] = %s\n", j
, ppd
->fonts
[j
]);
696 if (strcmp(fonts
[i
], ppd
->fonts
[j
]) == 0)
703 if ((ppd
!= NULL
&& j
>= ppd
->num_fonts
) ||
704 strncmp(fonts
[i
], "Courier", 7) == 0 ||
705 strcmp(fonts
[i
], "Symbol") == 0)
708 * Need to embed this font...
711 printf("%%%%+ font %s\n", fonts
[i
]);
715 puts("%%EndComments");
717 puts("%%BeginProlog");
720 * Download any missing fonts...
723 for (i
= 0; i
< num_fonts
; i
++)
727 for (j
= 0; j
< ppd
->num_fonts
; j
++)
728 if (strcmp(fonts
[i
], ppd
->fonts
[j
]) == 0)
734 if ((ppd
!= NULL
&& j
>= ppd
->num_fonts
) ||
735 strncmp(fonts
[i
], "Courier", 7) == 0 ||
736 strcmp(fonts
[i
], "Symbol") == 0)
739 * Need to embed this font...
742 printf("%%%%BeginResource: font %s\n", fonts
[i
]);
744 /**** MRS: Need to use CUPS_FONTPATH env var! ****/
745 /**** Also look for Fontmap file or name.pfa, name.pfb... ****/
746 snprintf(filename
, sizeof(filename
), "%s/fonts/%s", datadir
, fonts
[i
]);
747 if ((fp
= fopen(filename
, "rb")) != NULL
)
749 while ((j
= fread(line
, 1, sizeof(line
), fp
)) > 0)
750 fwrite(line
, 1, j
, stdout
);
755 puts("\n%%EndResource");
760 * Write the encoding array(s)...
763 puts("% character encoding(s)");
765 for (i
= 0; i
< NumFonts
; i
++)
767 printf("/cupsEncoding%02x [\n", i
);
769 for (ch
= 0; ch
< 256; ch
++)
771 if (Glyphs
[Codes
[i
* 256 + ch
]])
772 printf("/%s", Glyphs
[Codes
[i
* 256 + ch
]]);
773 else if (Codes
[i
* 256 + ch
] > 255)
774 printf("/uni%04X", Codes
[i
* 256 + ch
]);
786 * Create the fonts...
792 * Just reencode the named fonts...
795 puts("% Reencode fonts");
797 for (i
= PrettyPrint
? 2 : 1; i
>= 0; i
--)
799 printf("/%s findfont\n", Fonts
[0][i
]);
800 puts("dup length 1 add dict begin\n"
801 " { 1 index /FID ne { def } { pop pop } ifelse } forall\n"
802 " /Encoding cupsEncoding00 def\n"
805 printf("/%s exch definefont pop\n", names
[i
]);
811 * Construct composite fonts... Start by reencoding the base fonts...
814 puts("% Reencode base fonts");
816 for (i
= PrettyPrint
? 2 : 1; i
>= 0; i
--)
817 for (j
= 0; j
< NumFonts
; j
++)
819 printf("/%s findfont\n", Fonts
[j
][i
]);
820 printf("dup length 1 add dict begin\n"
821 " { 1 index /FID ne { def } { pop pop } ifelse } forall\n"
822 " /Encoding cupsEncoding%02x def\n"
825 printf("/%s%02x exch definefont /%s%02x exch def\n", names
[i
], j
,
830 * Then merge them into composite fonts...
833 puts("% Create composite fonts...");
835 for (i
= PrettyPrint
? 2 : 1; i
>= 0; i
--)
837 puts("8 dict begin");
838 puts("/FontType 0 def/FontMatrix[1.0 0 0 1.0 0 0]def/FMapType 2 def/Encoding[");
839 for (j
= 0; j
< NumFonts
; j
++)
840 if (j
== (NumFonts
- 1))
842 else if ((j
& 15) == 15)
846 puts("]def/FDepVector[");
847 for (j
= 0; j
< NumFonts
; j
++)
848 if (j
== (NumFonts
- 1))
849 printf("%s%02x", names
[i
], j
);
850 else if ((j
& 3) == 3)
851 printf("%s%02x\n", names
[i
], j
);
853 printf("%s%02x ", names
[i
], j
);
854 puts("]def currentdict end");
855 printf("/%s exch definefont pop\n", names
[i
]);
860 * Output the texttops procset...
863 puts("%%BeginResource: procset texttops 1.1 0");
865 puts("% Define fonts");
867 printf("/FN /cupsNormal findfont [%.3f 0 0 %.3f 0 0] makefont def\n",
868 120.0 / CharsPerInch
, 68.0 / LinesPerInch
);
869 printf("/FB /cupsBold findfont [%.3f 0 0 %.3f 0 0] makefont def\n",
870 120.0 / CharsPerInch
, 68.0 / LinesPerInch
);
872 printf("/FI /cupsItalic findfont [%.3f 0 0 %.3f 0 0] makefont def\n",
873 120.0 / CharsPerInch
, 68.0 / LinesPerInch
);
875 puts("% Common procedures");
877 puts("/N { FN setfont moveto } bind def");
878 puts("/B { FB setfont moveto } bind def");
879 printf("/U { gsave 0.5 setlinewidth 0 %.3f rmoveto "
880 "0 rlineto stroke grestore } bind def\n", -6.8 / LinesPerInch
);
886 puts("/S { 0.0 setgray show } bind def");
887 puts("/r { 0.5 0.0 0.0 setrgbcolor show } bind def");
888 puts("/g { 0.0 0.5 0.0 setrgbcolor show } bind def");
889 puts("/b { 0.0 0.0 0.5 setrgbcolor show } bind def");
893 puts("/S { 0.0 setgray show } bind def");
894 puts("/r { 0.2 setgray show } bind def");
895 puts("/g { 0.2 setgray show } bind def");
896 puts("/b { 0.2 setgray show } bind def");
899 puts("/I { FI setfont moveto } bind def");
902 puts("\t20 string cvs % convert page number to string");
906 * Convert a number to double-byte chars...
909 puts("\tdup length % get length");
910 puts("\tdup 2 mul string /P exch def % P = string twice as long");
911 puts("\t0 1 2 index 1 sub { % loop through each character in the page number");
912 puts("\t\tdup 3 index exch get % get character N from the page number");
913 puts("\t\texch 2 mul dup % compute offset in P");
914 puts("\t\tP exch 0 put % font 0");
915 puts("\t\t1 add P exch 2 index put % character");
916 puts("\t\tpop % discard character");
917 puts("\t} for % do for loop");
918 puts("\tpop pop % discard string and length");
919 puts("\tP % put string on stack");
933 puts("\t0.9 setgray");
937 puts("\tdup 2 mod 0 eq {");
938 printf("\t\t%.3f %.3f translate } {\n",
939 PageWidth
- PageRight
, PageTop
+ 72.0f
/ LinesPerInch
);
940 printf("\t\t%.3f %.3f translate } ifelse\n",
941 PageLeft
, PageTop
+ 72.0f
/ LinesPerInch
);
944 printf("\t%.3f %.3f translate\n",
945 PageLeft
, PageTop
+ 72.0f
/ LinesPerInch
);
947 printf("\t0 0 %.3f %.3f rectfill\n", PageRight
- PageLeft
,
948 144.0f
/ LinesPerInch
);
950 puts("\tFB setfont");
955 puts("\tdup 2 mod 0 eq {");
956 printf("\t\tT stringwidth pop neg %.3f add %.3f } {\n",
957 PageRight
- PageLeft
- 36.0f
/ LinesPerInch
,
958 (0.5f
+ 0.157f
) * 72.0f
/ LinesPerInch
);
959 printf("\t\t%.3f %.3f } ifelse\n", 36.0f
/ LinesPerInch
,
960 (0.5f
+ 0.157f
) * 72.0f
/ LinesPerInch
);
963 printf("\t%.3f %.3f\n", 36.0f
/ LinesPerInch
,
964 (0.5f
+ 0.157f
) * 72.0f
/ LinesPerInch
);
966 puts("\tmoveto T show");
968 printf("\tD dup stringwidth pop neg 2 div %.3f add %.3f\n",
969 (PageRight
- PageLeft
) * 0.5,
970 (0.5f
+ 0.157f
) * 72.0f
/ LinesPerInch
);
971 puts("\tmoveto show");
975 puts("\tdup n exch 2 mod 0 eq {");
976 printf("\t\t%.3f %.3f } {\n", 36.0f
/ LinesPerInch
,
977 (0.5f
+ 0.157f
) * 72.0f
/ LinesPerInch
);
978 printf("\t\tdup stringwidth pop neg %.3f add %.3f } ifelse\n",
979 PageRight
- PageLeft
- 36.0f
/ LinesPerInch
,
980 (0.5f
+ 0.157f
) * 72.0f
/ LinesPerInch
);
983 printf("\tn dup stringwidth pop neg %.3f add %.3f\n",
984 PageRight
- PageLeft
- 36.0f
/ LinesPerInch
,
985 (0.5f
+ 0.157f
) * 72.0f
/ LinesPerInch
);
987 puts("\tmoveto show");
992 puts("/S { show } bind def");
994 puts("%%EndResource");
1001 * 'write_line()' - Write a row of text.
1005 write_line(int row
, /* I - Row number (0 to N) */
1006 lchar_t
*line
) /* I - Line to print */
1008 int i
; /* Looping var */
1009 int col
; /* Current column */
1010 int attr
; /* Current attribute */
1011 int font
, /* Font to use */
1012 lastfont
, /* Last font */
1013 mono
; /* Monospaced? */
1014 lchar_t
*start
; /* First character in sequence */
1017 for (col
= 0, start
= line
; col
< SizeColumns
;)
1019 while (col
< SizeColumns
&& (line
->ch
== ' ' || line
->ch
== 0))
1025 if (col
>= SizeColumns
)
1031 * All characters in a single font - assume monospaced...
1037 while (col
< SizeColumns
&& line
->ch
!= 0 && attr
== line
->attr
)
1043 write_string(col
- (line
- start
), row
, line
- start
, start
);
1048 * Multiple fonts; break up based on the font...
1053 lastfont
= Chars
[line
->ch
] / 256;
1054 mono
= strncmp(Fonts
[lastfont
][0], "Courier", 7) == 0;
1060 while (col
< SizeColumns
&& line
->ch
!= 0 && attr
== line
->attr
)
1062 font
= Chars
[line
->ch
] / 256;
1063 if (strncmp(Fonts
[font
][0], "Courier", 7) != 0 ||
1072 if (Directions
[lastfont
] > 0)
1073 write_string(col
- (line
- start
), row
, line
- start
, start
);
1077 * Do right-to-left text...
1080 while (col
< SizeColumns
&& line
->ch
!= 0 && attr
== line
->attr
)
1082 if (Directions
[Chars
[line
->ch
] / 256] > 0 &&
1083 !ispunct(line
->ch
& 255) && !isspace(line
->ch
& 255))
1090 for (i
= 1; start
< line
; i
++, start
++)
1091 if (!isspace(start
->ch
& 255))
1092 write_string(col
- i
, row
, 1, start
);
1100 * 'write_string()' - Write a string of text.
1104 write_string(int col
, /* I - Start column */
1105 int row
, /* I - Row */
1106 int len
, /* I - Number of characters */
1107 lchar_t
*s
) /* I - String to print */
1109 int ch
; /* Current character */
1110 float x
, y
; /* Position of text */
1111 unsigned attr
; /* Character attributes */
1115 * Position the text and set the font...
1118 if (Duplex
&& (NumPages
& 1) == 0)
1120 x
= PageWidth
- PageRight
;
1129 x
+= (float)col
* 72.0f
/ (float)CharsPerInch
;
1130 y
-= (float)(row
+ 0.843) * 72.0f
/ (float)LinesPerInch
;
1134 if (attr
& ATTR_RAISED
)
1135 y
+= 36.0 / (float)LinesPerInch
;
1136 else if (attr
& ATTR_LOWERED
)
1137 y
-= 36.0 / (float)LinesPerInch
;
1149 if (attr
& ATTR_BOLD
)
1151 else if (attr
& ATTR_ITALIC
)
1156 if (attr
& ATTR_UNDERLINE
)
1157 printf(" %.3f U", (float)len
* 72.0 / (float)CharsPerInch
);
1162 * Write a hex string...
1169 printf("%04x", Chars
[s
->ch
]);
1180 * Write a quoted string...
1189 if (ch
< 32 || ch
> 126)
1192 * Quote 8-bit and control characters...
1195 printf("\\%03o", ch
);
1200 * Quote the parenthesis and backslash as needed...
1203 if (ch
== '(' || ch
== ')' || ch
== '\\')
1218 if (attr
& ATTR_RED
)
1220 else if (attr
& ATTR_GREEN
)
1222 else if (attr
& ATTR_BLUE
)
1233 * 'write_text()' - Write a text string, quoting/encoding as needed.
1237 write_text(const char *s
) /* I - String to write */
1239 int ch
; /* Actual character value (UTF8) */
1240 const unsigned char *utf8
; /* UTF8 text */
1251 utf8
= (const unsigned char *)s
;
1255 if (*utf8
< 0xc0 || !UTF8
)
1257 else if ((*utf8
& 0xe0) == 0xc0)
1260 * Two byte character...
1263 ch
= ((utf8
[0] & 0x1f) << 6) | (utf8
[1] & 0x3f);
1269 * Three byte character...
1272 ch
= ((((utf8
[0] & 0x1f) << 6) | (utf8
[1] & 0x3f)) << 6) |
1277 printf("%04x", Chars
[ch
]);
1285 * Standard 8-bit encoding...
1292 if (*s
< 32 || *s
> 126)
1293 printf("\\%03o", *s
);
1296 if (*s
== '(' || *s
== ')' || *s
== '\\')
1311 * End of "$Id: texttops.c 6420 2007-03-30 20:00:59Z mike $".