source: trunk/kitgen/8.x/blt/generic/bltPs.c@ 199

Last change on this file since 199 was 175, checked in by demin, 12 years ago

initial commit

File size: 41.3 KB
Line 
1
2/*
3 * bltPs.c --
4 *
5 * This module implements general PostScript conversion routines.
6 *
7 * Copyright 1991-1998 Lucent Technologies, Inc.
8 *
9 * Permission to use, copy, modify, and distribute this software and
10 * its documentation for any purpose and without fee is hereby
11 * granted, provided that the above copyright notice appear in all
12 * copies and that both that the copyright notice and warranty
13 * disclaimer appear in supporting documentation, and that the names
14 * of Lucent Technologies any of their entities not be used in
15 * advertising or publicity pertaining to distribution of the software
16 * without specific, written prior permission.
17 *
18 * Lucent Technologies disclaims all warranties with regard to this
19 * software, including all implied warranties of merchantability and
20 * fitness. In no event shall Lucent Technologies be liable for any
21 * special, indirect or consequential damages or any damages
22 * whatsoever resulting from loss of use, data or profits, whether in
23 * an action of contract, negligence or other tortuous action, arising
24 * out of or in connection with the use or performance of this
25 * software.
26 */
27
28#include "bltInt.h"
29#include "bltPs.h"
30
31#include <X11/Xutil.h>
32#include <X11/Xatom.h>
33#if defined(__STDC__)
34#include <stdarg.h>
35#else
36#include <varargs.h>
37#endif
38
39#define PS_MAXPATH 1500 /* Maximum number of components in a PostScript
40 * (level 1) path. */
41
42PsToken
43Blt_GetPsToken(interp, tkwin)
44 Tcl_Interp *interp;
45 Tk_Window tkwin;
46{
47 struct PsTokenStruct *tokenPtr;
48
49 tokenPtr = Blt_Malloc(sizeof(struct PsTokenStruct));
50 assert(tokenPtr);
51
52 tokenPtr->fontVarName = tokenPtr->colorVarName = NULL;
53 tokenPtr->interp = interp;
54 tokenPtr->tkwin = tkwin;
55 tokenPtr->colorMode = PS_MODE_COLOR;
56 Tcl_DStringInit(&(tokenPtr->dString));
57 return tokenPtr;
58}
59
60void
61Blt_ReleasePsToken(tokenPtr)
62 struct PsTokenStruct *tokenPtr;
63{
64 Tcl_DStringFree(&(tokenPtr->dString));
65 Blt_Free(tokenPtr);
66}
67
68char *
69Blt_PostScriptFromToken(tokenPtr)
70 struct PsTokenStruct *tokenPtr;
71{
72 return Tcl_DStringValue(&(tokenPtr->dString));
73}
74
75char *
76Blt_ScratchBufferFromToken(tokenPtr)
77 struct PsTokenStruct *tokenPtr;
78{
79 return tokenPtr->scratchArr;
80}
81
82void
83Blt_AppendToPostScript
84TCL_VARARGS_DEF(PsToken, arg1)
85{
86 va_list argList;
87 struct PsTokenStruct *tokenPtr;
88 char *string;
89
90 tokenPtr = TCL_VARARGS_START(struct PsTokenStruct, arg1, argList);
91 for (;;) {
92 string = va_arg(argList, char *);
93 if (string == NULL) {
94 break;
95 }
96 Tcl_DStringAppend(&(tokenPtr->dString), string, -1);
97 }
98}
99
100void
101Blt_FormatToPostScript
102TCL_VARARGS_DEF(PsToken, arg1)
103{
104 va_list argList;
105 struct PsTokenStruct *tokenPtr;
106 char *fmt;
107
108 tokenPtr = TCL_VARARGS_START(struct PsTokenStruct, arg1, argList);
109 fmt = va_arg(argList, char *);
110 vsprintf(tokenPtr->scratchArr, fmt, argList);
111 va_end(argList);
112 Tcl_DStringAppend(&(tokenPtr->dString), tokenPtr->scratchArr, -1);
113}
114
115int
116Blt_FileToPostScript(tokenPtr, fileName)
117 struct PsTokenStruct *tokenPtr;
118 char *fileName;
119{
120 Tcl_Channel channel;
121 Tcl_DString dString;
122 Tcl_Interp *interp;
123 char *buf;
124 char *libDir;
125 int nBytes;
126
127 interp = tokenPtr->interp;
128 buf = tokenPtr->scratchArr;
129
130 /*
131 * Read in a standard prolog file from file and append it to the
132 * PostScript output stored in the Tcl_DString in tokenPtr.
133 */
134
135 libDir = (char *)Tcl_GetVar(interp, "blt_library", TCL_GLOBAL_ONLY);
136 if (libDir == NULL) {
137 Tcl_AppendResult(interp, "couldn't find BLT script library:",
138 "global variable \"blt_library\" doesn't exist", (char *)NULL);
139 return TCL_ERROR;
140 }
141 Tcl_DStringInit(&dString);
142 Tcl_DStringAppend(&dString, libDir, -1);
143 Tcl_DStringAppend(&dString, "/", -1);
144 Tcl_DStringAppend(&dString, fileName, -1);
145 fileName = Tcl_DStringValue(&dString);
146 Blt_AppendToPostScript(tokenPtr, "\n% including file \"", fileName,
147 "\"\n\n", (char *)NULL);
148 channel = Tcl_OpenFileChannel(interp, fileName, "r", 0);
149 if (channel == NULL) {
150 Tcl_AppendResult(interp, "couldn't open prologue file \"", fileName,
151 "\": ", Tcl_PosixError(interp), (char *)NULL);
152 return TCL_ERROR;
153 }
154 for(;;) {
155 nBytes = Tcl_Read(channel, buf, PSTOKEN_BUFSIZ);
156 if (nBytes < 0) {
157 Tcl_AppendResult(interp, "error reading prologue file \"",
158 fileName, "\": ", Tcl_PosixError(interp),
159 (char *)NULL);
160 Tcl_Close(interp, channel);
161 Tcl_DStringFree(&dString);
162 return TCL_ERROR;
163 }
164 if (nBytes == 0) {
165 break;
166 }
167 buf[nBytes] = '\0';
168 Blt_AppendToPostScript(tokenPtr, buf, (char *)NULL);
169 }
170 Tcl_DStringFree(&dString);
171 Tcl_Close(interp, channel);
172 return TCL_OK;
173}
174/*
175 *----------------------------------------------------------------------
176 *
177 * XColorToPostScript --
178 *
179 * Convert the a XColor (from its RGB values) to a PostScript
180 * command. If a Tk color map variable exists, it will be
181 * consulted for a PostScript translation based upon the color
182 * name.
183 *
184 * Maps an X color intensity (0 to 2^16-1) to a floating point
185 * value [0..1]. Many versions of Tk don't properly handle the
186 * the lower 8 bits of the color intensity, so we can only
187 * consider the upper 8 bits.
188 *
189 * Results:
190 * The string representing the color mode is returned.
191 *
192 *----------------------------------------------------------------------
193 */
194static void
195XColorToPostScript(tokenPtr, colorPtr)
196 struct PsTokenStruct *tokenPtr;
197 XColor *colorPtr; /* Color value to be converted */
198{
199 /*
200 * Shift off the lower byte before dividing because some versions
201 * of Tk don't fill the lower byte correctly.
202 */
203 Blt_FormatToPostScript(tokenPtr, "%g %g %g",
204 ((double)(colorPtr->red >> 8) / 255.0),
205 ((double)(colorPtr->green >> 8) / 255.0),
206 ((double)(colorPtr->blue >> 8) / 255.0));
207}
208
209void
210Blt_BackgroundToPostScript(tokenPtr, colorPtr)
211 struct PsTokenStruct *tokenPtr;
212 XColor *colorPtr;
213{
214 /* If the color name exists in Tcl array variable, use that translation */
215 if (tokenPtr->colorVarName != NULL) {
216 CONST char *psColor;
217
218 psColor = Tcl_GetVar2(tokenPtr->interp, tokenPtr->colorVarName,
219 Tk_NameOfColor(colorPtr), 0);
220 if (psColor != NULL) {
221 Blt_AppendToPostScript(tokenPtr, " ", psColor, "\n", (char *)NULL);
222 return;
223 }
224 }
225 XColorToPostScript(tokenPtr, colorPtr);
226 Blt_AppendToPostScript(tokenPtr, " SetBgColor\n", (char *)NULL);
227}
228
229void
230Blt_ForegroundToPostScript(tokenPtr, colorPtr)
231 struct PsTokenStruct *tokenPtr;
232 XColor *colorPtr;
233{
234 /* If the color name exists in Tcl array variable, use that translation */
235 if (tokenPtr->colorVarName != NULL) {
236 CONST char *psColor;
237
238 psColor = Tcl_GetVar2(tokenPtr->interp, tokenPtr->colorVarName,
239 Tk_NameOfColor(colorPtr), 0);
240 if (psColor != NULL) {
241 Blt_AppendToPostScript(tokenPtr, " ", psColor, "\n", (char *)NULL);
242 return;
243 }
244 }
245 XColorToPostScript(tokenPtr, colorPtr);
246 Blt_AppendToPostScript(tokenPtr, " SetFgColor\n", (char *)NULL);
247}
248
249/*
250 *----------------------------------------------------------------------
251 *
252 * ReverseBits --
253 *
254 * Convert a byte from a X image into PostScript image order.
255 * This requires not only the nybbles to be reversed but also
256 * their bit values.
257 *
258 * Results:
259 * The converted byte is returned.
260 *
261 *----------------------------------------------------------------------
262 */
263INLINE static unsigned char
264ReverseBits(byte)
265 register unsigned char byte;
266{
267 byte = ((byte >> 1) & 0x55) | ((byte << 1) & 0xaa);
268 byte = ((byte >> 2) & 0x33) | ((byte << 2) & 0xcc);
269 byte = ((byte >> 4) & 0x0f) | ((byte << 4) & 0xf0);
270 return byte;
271}
272
273/*
274 *----------------------------------------------------------------------
275 *
276 * ByteToHex --
277 *
278 * Convert a byte to its ASCII hexidecimal equivalent.
279 *
280 * Results:
281 * The converted 2 ASCII character string is returned.
282 *
283 *----------------------------------------------------------------------
284 */
285INLINE static void
286ByteToHex(byte, string)
287 register unsigned char byte;
288 char *string;
289{
290 static char hexDigits[] = "0123456789ABCDEF";
291
292 string[0] = hexDigits[byte >> 4];
293 string[1] = hexDigits[byte & 0x0F];
294}
295
296#ifdef WIN32
297/*
298 * -------------------------------------------------------------------------
299 *
300 * Blt_BitmapDataToPostScript --
301 *
302 * Output a PostScript image string of the given bitmap image.
303 * It is assumed the image is one bit deep and a zero value
304 * indicates an off-pixel. To convert to PostScript, the bits
305 * need to be reversed from the X11 image order.
306 *
307 * Results:
308 * None.
309 *
310 * Side Effects:
311 * The PostScript image string is appended.
312 *
313 * -------------------------------------------------------------------------
314 */
315void
316Blt_BitmapDataToPostScript(
317 struct PsTokenStruct *tokenPtr,
318 Display *display,
319 Pixmap bitmap,
320 int width, int height)
321{
322 register unsigned char byte;
323 register int x, y, bitPos;
324 unsigned long pixel;
325 int byteCount;
326 char string[10];
327 unsigned char *srcBits, *srcPtr;
328 int bytesPerRow;
329
330 srcBits = Blt_GetBitmapData(display, bitmap, width, height, &bytesPerRow);
331 if (srcBits == NULL) {
332 OutputDebugString("Can't get bitmap data");
333 return;
334 }
335 Blt_AppendToPostScript(tokenPtr, "\t<", (char *)NULL);
336 byteCount = bitPos = 0; /* Suppress compiler warning */
337 for (y = height - 1; y >= 0; y--) {
338 srcPtr = srcBits + (bytesPerRow * y);
339 byte = 0;
340 for (x = 0; x < width; x++) {
341 bitPos = x % 8;
342 pixel = (*srcPtr & (0x80 >> bitPos));
343 if (pixel) {
344 byte |= (unsigned char)(1 << bitPos);
345 }
346 if (bitPos == 7) {
347 byte = ReverseBits(byte);
348 ByteToHex(byte, string);
349 string[2] = '\0';
350 byteCount++;
351 srcPtr++;
352 byte = 0;
353 if (byteCount >= 30) {
354 string[2] = '\n';
355 string[3] = '\t';
356 string[4] = '\0';
357 byteCount = 0;
358 }
359 Blt_AppendToPostScript(tokenPtr, string, (char *)NULL);
360 }
361 } /* x */
362 if (bitPos != 7) {
363 byte = ReverseBits(byte);
364 ByteToHex(byte, string);
365 string[2] = '\0';
366 Blt_AppendToPostScript(tokenPtr, string, (char *)NULL);
367 byteCount++;
368 }
369 } /* y */
370 Blt_Free(srcBits);
371 Blt_AppendToPostScript(tokenPtr, ">\n", (char *)NULL);
372}
373
374#else
375
376/*
377 * -------------------------------------------------------------------------
378 *
379 * Blt_BitmapDataToPostScript --
380 *
381 * Output a PostScript image string of the given bitmap image.
382 * It is assumed the image is one bit deep and a zero value
383 * indicates an off-pixel. To convert to PostScript, the bits
384 * need to be reversed from the X11 image order.
385 *
386 * Results:
387 * None.
388 *
389 * Side Effects:
390 * The PostScript image string is appended to interp->result.
391 *
392 * -------------------------------------------------------------------------
393 */
394void
395Blt_BitmapDataToPostScript(tokenPtr, display, bitmap, width, height)
396 struct PsTokenStruct *tokenPtr;
397 Display *display;
398 Pixmap bitmap;
399 int width, height;
400{
401 register unsigned char byte = 0;
402 register int x, y, bitPos;
403 unsigned long pixel;
404 XImage *imagePtr;
405 int byteCount;
406 char string[10];
407
408 imagePtr = XGetImage(display, bitmap, 0, 0, width, height, 1, ZPixmap);
409 Blt_AppendToPostScript(tokenPtr, "\t<", (char *)NULL);
410 byteCount = bitPos = 0; /* Suppress compiler warning */
411 for (y = 0; y < height; y++) {
412 byte = 0;
413 for (x = 0; x < width; x++) {
414 pixel = XGetPixel(imagePtr, x, y);
415 bitPos = x % 8;
416 byte |= (unsigned char)(pixel << bitPos);
417 if (bitPos == 7) {
418 byte = ReverseBits(byte);
419 ByteToHex(byte, string);
420 string[2] = '\0';
421 byteCount++;
422 byte = 0;
423 if (byteCount >= 30) {
424 string[2] = '\n';
425 string[3] = '\t';
426 string[4] = '\0';
427 byteCount = 0;
428 }
429 Blt_AppendToPostScript(tokenPtr, string, (char *)NULL);
430 }
431 } /* x */
432 if (bitPos != 7) {
433 byte = ReverseBits(byte);
434 ByteToHex(byte, string);
435 string[2] = '\0';
436 Blt_AppendToPostScript(tokenPtr, string, (char *)NULL);
437 byteCount++;
438 }
439 } /* y */
440 Blt_AppendToPostScript(tokenPtr, ">\n", (char *)NULL);
441 XDestroyImage(imagePtr);
442}
443
444#endif /* WIN32 */
445
446/*
447 *----------------------------------------------------------------------
448 *
449 * Blt_ColorImageToPsData --
450 *
451 * Converts a color image to PostScript RGB (3 components)
452 * or Greyscale (1 component) output. With 3 components, we
453 * assume the "colorimage" operator is available.
454 *
455 * Note that the image converted from bottom to top, to conform
456 * to the PostScript coordinate system.
457 *
458 * Results:
459 * The PostScript data comprising the color image is written
460 * into the dynamic string.
461 *
462 *----------------------------------------------------------------------
463 */
464int
465Blt_ColorImageToPsData(image, nComponents, resultPtr, prefix)
466 Blt_ColorImage image;
467 int nComponents;
468 Tcl_DString *resultPtr;
469 char *prefix;
470{
471 char string[10];
472 register int count;
473 register int x, y;
474 register Pix32 *pixelPtr;
475 unsigned char byte;
476 int width, height;
477 int offset;
478 int nLines;
479 width = Blt_ColorImageWidth(image);
480 height = Blt_ColorImageHeight(image);
481
482 nLines = 0;
483 count = 0;
484 offset = (height - 1) * width;
485 if (nComponents == 3) {
486 for (y = (height - 1); y >= 0; y--) {
487 pixelPtr = Blt_ColorImageBits(image) + offset;
488 for (x = 0; x < width; x++, pixelPtr++) {
489 if (count == 0) {
490 Tcl_DStringAppend(resultPtr, prefix, -1);
491 Tcl_DStringAppend(resultPtr, " ", -1);
492 }
493 count += 6;
494 ByteToHex(pixelPtr->Red, string);
495 ByteToHex(pixelPtr->Green, string + 2);
496 ByteToHex(pixelPtr->Blue, string + 4);
497 string[6] = '\0';
498 if (count >= 60) {
499 string[6] = '\n';
500 string[7] = '\0';
501 count = 0;
502 nLines++;
503 }
504 Tcl_DStringAppend(resultPtr, string, -1);
505 }
506 offset -= width;
507 }
508 } else if (nComponents == 1) {
509 for (y = (height - 1); y >= 0; y--) {
510 pixelPtr = Blt_ColorImageBits(image) + offset;
511 for (x = 0; x < width; x++, pixelPtr++) {
512 if (count == 0) {
513 Tcl_DStringAppend(resultPtr, prefix, -1);
514 Tcl_DStringAppend(resultPtr, " ", -1);
515 }
516 count += 2;
517 byte = ~(pixelPtr->Red);
518 ByteToHex(byte, string);
519 string[2] = '\0';
520 if (count >= 60) {
521 string[2] = '\n';
522 string[3] = '\0';
523 count = 0;
524 nLines++;
525 }
526 Tcl_DStringAppend(resultPtr, string, -1);
527 }
528 offset -= width;
529 }
530 }
531 if (count != 0) {
532 Tcl_DStringAppend(resultPtr, "\n", -1);
533 nLines++;
534 }
535 return nLines;
536}
537
538/*
539 *----------------------------------------------------------------------
540 *
541 * NameOfAtom --
542 *
543 * Wrapper routine for Tk_GetAtomName. Returns NULL instead of
544 * "?bad atom?" if the atom can't be found.
545 *
546 * Results:
547 * The name of the atom is returned if found. Otherwise NULL.
548 *
549 *----------------------------------------------------------------------
550 */
551static char *
552NameOfAtom(tkwin, atom)
553 Tk_Window tkwin;
554 Atom atom;
555{
556 char *result;
557
558 result = Tk_GetAtomName(tkwin, atom);
559 if ((result[0] == '?') && (strcmp(result, "?bad atom?") == 0)) {
560 return NULL;
561 }
562 return result;
563}
564
565
566typedef struct {
567 char *alias;
568 char *fontName;
569} FontMap;
570
571static FontMap psFontMap[] =
572{
573 {"Arial", "Helvetica",},
574 {"AvantGarde", "AvantGarde",},
575 {"Courier New", "Courier",},
576 {"Courier", "Courier",},
577 {"Geneva", "Helvetica",},
578 {"Helvetica", "Helvetica",},
579 {"Monaco", "Courier",},
580 {"New Century Schoolbook", "NewCenturySchlbk",},
581 {"New York", "Times",},
582 {"Palatino", "Palatino",},
583 {"Symbol", "Symbol",},
584 {"Times New Roman", "Times",},
585 {"Times Roman", "Times",},
586 {"Times", "Times",},
587 {"Utopia", "Utopia",},
588 {"ZapfChancery", "ZapfChancery",},
589 {"ZapfDingbats", "ZapfDingbats",},
590};
591
592static int nFontNames = (sizeof(psFontMap) / sizeof(FontMap));
593
594#ifndef WIN32
595/*
596 * -----------------------------------------------------------------
597 *
598 * XFontStructToPostScript --
599 *
600 * Map X11 font to a PostScript font. Currently, only fonts whose
601 * FOUNDRY property are "Adobe" are converted. Simply gets the
602 * XA_FULL_NAME and XA_FAMILY properties and pieces together a
603 * PostScript fontname.
604 *
605 * Results:
606 * Returns the mapped PostScript font name if one is possible.
607 * Otherwise returns NULL.
608 *
609 * -----------------------------------------------------------------
610 */
611static char *
612XFontStructToPostScript(tkwin, fontPtr)
613 Tk_Window tkwin; /* Window to query for atoms */
614 XFontStruct *fontPtr; /* Font structure to map to name */
615{
616 Atom atom;
617 char *fullName, *family, *foundry;
618 register char *src, *dest;
619 int familyLen;
620 char *start;
621 static char string[200]; /* What size? */
622
623 if (XGetFontProperty(fontPtr, XA_FULL_NAME, &atom) == False) {
624 return NULL;
625 }
626 fullName = NameOfAtom(tkwin, atom);
627 if (fullName == NULL) {
628 return NULL;
629 }
630 family = foundry = NULL;
631 if (XGetFontProperty(fontPtr, Tk_InternAtom(tkwin, "FOUNDRY"), &atom)) {
632 foundry = NameOfAtom(tkwin, atom);
633 }
634 if (XGetFontProperty(fontPtr, XA_FAMILY_NAME, &atom)) {
635 family = NameOfAtom(tkwin, atom);
636 }
637 /*
638 * Try to map the font only if the foundry is Adobe
639 */
640 if ((foundry == NULL) || (family == NULL)) {
641 return NULL;
642 }
643 src = NULL;
644 familyLen = strlen(family);
645 if (strncasecmp(fullName, family, familyLen) == 0) {
646 src = fullName + familyLen;
647 }
648 if (strcmp(foundry, "Adobe") != 0) {
649 register int i;
650
651 if (strncasecmp(family, "itc ", 4) == 0) {
652 family += 4; /* Throw out the "itc" prefix */
653 }
654 for (i = 0; i < nFontNames; i++) {
655 if (strcasecmp(family, psFontMap[i].alias) == 0) {
656 family = psFontMap[i].fontName;
657 }
658 }
659 if (i == nFontNames) {
660 family = "Helvetica"; /* Default to a known font */
661 }
662 }
663 /*
664 * PostScript font name is in the form <family>-<type face>
665 */
666 sprintf(string, "%s-", family);
667 dest = start = string + strlen(string);
668
669 /*
670 * Append the type face (part of the full name trailing the family name)
671 * to the the PostScript font name, removing any spaces or dashes
672 *
673 * ex. " Bold Italic" ==> "BoldItalic"
674 */
675 if (src != NULL) {
676 while (*src != '\0') {
677 if ((*src != ' ') && (*src != '-')) {
678 *dest++ = *src;
679 }
680 src++;
681 }
682 }
683 if (dest == start) {
684 --dest; /* Remove '-' to leave just the family name */
685 }
686 *dest = '\0'; /* Make a valid string */
687 return string;
688}
689
690#endif /* !WIN32 */
691
692
693
694/*
695 * -------------------------------------------------------------------
696 * Routines to convert X drawing functions to PostScript commands.
697 * -------------------------------------------------------------------
698 */
699void
700Blt_ClearBackgroundToPostScript(tokenPtr)
701 struct PsTokenStruct *tokenPtr;
702{
703 Blt_AppendToPostScript(tokenPtr,
704 " 1.0 1.0 1.0 SetBgColor\n",
705 (char *)NULL);
706}
707
708void
709Blt_CapStyleToPostScript(tokenPtr, capStyle)
710 struct PsTokenStruct *tokenPtr;
711 int capStyle;
712{
713 /*
714 * X11:not last = 0, butt = 1, round = 2, projecting = 3
715 * PS: butt = 0, round = 1, projecting = 2
716 */
717 if (capStyle > 0) {
718 capStyle--;
719 }
720 Blt_FormatToPostScript(tokenPtr,
721 "%d setlinecap\n",
722 capStyle);
723}
724
725void
726Blt_JoinStyleToPostScript(tokenPtr, joinStyle)
727 struct PsTokenStruct *tokenPtr;
728 int joinStyle;
729{
730 /*
731 * miter = 0, round = 1, bevel = 2
732 */
733 Blt_FormatToPostScript(tokenPtr,
734 "%d setlinejoin\n",
735 joinStyle);
736}
737
738void
739Blt_LineWidthToPostScript(tokenPtr, lineWidth)
740 struct PsTokenStruct *tokenPtr;
741 int lineWidth;
742{
743 if (lineWidth < 1) {
744 lineWidth = 1;
745 }
746 Blt_FormatToPostScript(tokenPtr,
747 "%d setlinewidth\n",
748 lineWidth);
749}
750
751void
752Blt_LineDashesToPostScript(tokenPtr, dashesPtr)
753 struct PsTokenStruct *tokenPtr;
754 Blt_Dashes *dashesPtr;
755{
756
757 Blt_AppendToPostScript(tokenPtr, "[ ", (char *)NULL);
758 if (dashesPtr != NULL) {
759 unsigned char *p;
760
761 for (p = dashesPtr->values; *p != 0; p++) {
762 Blt_FormatToPostScript(tokenPtr, " %d", *p);
763 }
764 }
765 Blt_AppendToPostScript(tokenPtr, "] 0 setdash\n", (char *)NULL);
766}
767
768void
769Blt_LineAttributesToPostScript(tokenPtr, colorPtr, lineWidth, dashesPtr,
770 capStyle, joinStyle)
771 struct PsTokenStruct *tokenPtr;
772 XColor *colorPtr;
773 int lineWidth;
774 Blt_Dashes *dashesPtr;
775 int capStyle, joinStyle;
776{
777 Blt_JoinStyleToPostScript(tokenPtr, joinStyle);
778 Blt_CapStyleToPostScript(tokenPtr, capStyle);
779 Blt_ForegroundToPostScript(tokenPtr, colorPtr);
780 Blt_LineWidthToPostScript(tokenPtr, lineWidth);
781 Blt_LineDashesToPostScript(tokenPtr, dashesPtr);
782 Blt_AppendToPostScript(tokenPtr, "/DashesProc {} def\n", (char *)NULL);
783}
784
785void
786Blt_RectangleToPostScript(tokenPtr, x, y, width, height)
787 struct PsTokenStruct *tokenPtr;
788 double x, y;
789 int width, height;
790{
791 Blt_FormatToPostScript(tokenPtr,
792 "%g %g %d %d Box fill\n\n",
793 x, y, width, height);
794}
795
796void
797Blt_RegionToPostScript(tokenPtr, x, y, width, height)
798 struct PsTokenStruct *tokenPtr;
799 double x, y;
800 int width, height;
801{
802 Blt_FormatToPostScript(tokenPtr, "%g %g %d %d Box\n\n",
803 x, y, width, height);
804}
805
806void
807Blt_PathToPostScript(tokenPtr, screenPts, nScreenPts)
808 struct PsTokenStruct *tokenPtr;
809 register Point2D *screenPts;
810 int nScreenPts;
811{
812 register Point2D *pointPtr, *endPtr;
813
814 pointPtr = screenPts;
815 Blt_FormatToPostScript(tokenPtr, "newpath %g %g moveto\n",
816 pointPtr->x, pointPtr->y);
817 pointPtr++;
818 endPtr = screenPts + nScreenPts;
819 while (pointPtr < endPtr) {
820 Blt_FormatToPostScript(tokenPtr, "%g %g lineto\n",
821 pointPtr->x, pointPtr->y);
822 pointPtr++;
823 }
824}
825
826void
827Blt_PolygonToPostScript(tokenPtr, screenPts, nScreenPts)
828 struct PsTokenStruct *tokenPtr;
829 Point2D *screenPts;
830 int nScreenPts;
831{
832 Blt_PathToPostScript(tokenPtr, screenPts, nScreenPts);
833 Blt_FormatToPostScript(tokenPtr, "%g %g ", screenPts[0].x, screenPts[0].y);
834 Blt_AppendToPostScript(tokenPtr, " lineto closepath Fill\n", (char *)NULL);
835}
836
837void
838Blt_SegmentsToPostScript(tokenPtr, segPtr, nSegments)
839 struct PsTokenStruct *tokenPtr;
840 register XSegment *segPtr;
841 int nSegments;
842{
843 register int i;
844
845 for (i = 0; i < nSegments; i++, segPtr++) {
846 Blt_FormatToPostScript(tokenPtr, "%d %d moveto\n",
847 segPtr->x1, segPtr->y1);
848 Blt_FormatToPostScript(tokenPtr, " %d %d lineto\n",
849 segPtr->x2, segPtr->y2);
850 Blt_AppendToPostScript(tokenPtr, "DashesProc stroke\n", (char *)NULL);
851 }
852}
853
854
855void
856Blt_RectanglesToPostScript(tokenPtr, rectArr, nRects)
857 struct PsTokenStruct *tokenPtr;
858 XRectangle rectArr[];
859 int nRects;
860{
861 register int i;
862
863 for (i = 0; i < nRects; i++) {
864 Blt_RectangleToPostScript(tokenPtr,
865 (double)rectArr[i].x, (double)rectArr[i].y,
866 (int)rectArr[i].width, (int)rectArr[i].height);
867 }
868}
869
870#ifndef TK_RELIEF_SOLID
871#define TK_RELIEF_SOLID -1 /* Set the an impossible value. */
872#endif /* TK_RELIEF_SOLID */
873
874void
875Blt_Draw3DRectangleToPostScript(tokenPtr, border, x, y, width, height,
876 borderWidth, relief)
877 struct PsTokenStruct *tokenPtr;
878 Tk_3DBorder border; /* Token for border to draw. */
879 double x, y; /* Coordinates of rectangle */
880 int width, height; /* Region to be drawn. */
881 int borderWidth; /* Desired width for border, in pixels. */
882 int relief; /* Should be either TK_RELIEF_RAISED or
883 * TK_RELIEF_SUNKEN; indicates position of
884 * interior of window relative to exterior. */
885{
886 TkBorder *borderPtr = (TkBorder *) border;
887 XColor lightColor, darkColor;
888 XColor *lightColorPtr, *darkColorPtr;
889 XColor *topColor, *bottomColor;
890 Point2D points[7];
891 int twiceWidth = (borderWidth * 2);
892
893 if ((width < twiceWidth) || (height < twiceWidth)) {
894 return;
895 }
896 if ((relief == TK_RELIEF_SOLID) ||
897 (borderPtr->lightColor == NULL) || (borderPtr->darkColor == NULL)) {
898 if (relief == TK_RELIEF_SOLID) {
899 darkColor.red = darkColor.blue = darkColor.green = 0x00;
900 lightColor.red = lightColor.blue = lightColor.green = 0x00;
901 relief = TK_RELIEF_SUNKEN;
902 } else {
903 Screen *screenPtr;
904
905 lightColor = *borderPtr->bgColor;
906 screenPtr = Tk_Screen(tokenPtr->tkwin);
907 if (lightColor.pixel == WhitePixelOfScreen(screenPtr)) {
908 darkColor.red = darkColor.blue = darkColor.green = 0x00;
909 } else {
910 darkColor.red = darkColor.blue = darkColor.green = 0xFF;
911 }
912 }
913 lightColorPtr = &lightColor;
914 darkColorPtr = &darkColor;
915 } else {
916 lightColorPtr = borderPtr->lightColor;
917 darkColorPtr = borderPtr->darkColor;
918 }
919
920
921 /*
922 * Handle grooves and ridges with recursive calls.
923 */
924
925 if ((relief == TK_RELIEF_GROOVE) || (relief == TK_RELIEF_RIDGE)) {
926 int halfWidth, insideOffset;
927
928 halfWidth = borderWidth / 2;
929 insideOffset = borderWidth - halfWidth;
930 Blt_Draw3DRectangleToPostScript(tokenPtr, border, (double)x, (double)y,
931 width, height, halfWidth,
932 (relief == TK_RELIEF_GROOVE) ? TK_RELIEF_SUNKEN : TK_RELIEF_RAISED);
933 Blt_Draw3DRectangleToPostScript(tokenPtr, border,
934 (double)(x + insideOffset), (double)(y + insideOffset),
935 width - insideOffset * 2, height - insideOffset * 2, halfWidth,
936 (relief == TK_RELIEF_GROOVE) ? TK_RELIEF_RAISED : TK_RELIEF_SUNKEN);
937 return;
938 }
939 if (relief == TK_RELIEF_RAISED) {
940 topColor = lightColorPtr;
941 bottomColor = darkColorPtr;
942 } else if (relief == TK_RELIEF_SUNKEN) {
943 topColor = darkColorPtr;
944 bottomColor = lightColorPtr;
945 } else {
946 topColor = bottomColor = borderPtr->bgColor;
947 }
948 Blt_BackgroundToPostScript(tokenPtr, bottomColor);
949 Blt_RectangleToPostScript(tokenPtr, x, y + height - borderWidth, width,
950 borderWidth);
951 Blt_RectangleToPostScript(tokenPtr, x + width - borderWidth, y,
952 borderWidth, height);
953 points[0].x = points[1].x = points[6].x = x;
954 points[0].y = points[6].y = y + height;
955 points[1].y = points[2].y = y;
956 points[2].x = x + width;
957 points[3].x = x + width - borderWidth;
958 points[3].y = points[4].y = y + borderWidth;
959 points[4].x = points[5].x = x + borderWidth;
960 points[5].y = y + height - borderWidth;
961 if (relief != TK_RELIEF_FLAT) {
962 Blt_BackgroundToPostScript(tokenPtr, topColor);
963 }
964 Blt_PolygonToPostScript(tokenPtr, points, 7);
965}
966
967void
968Blt_Fill3DRectangleToPostScript(tokenPtr, border, x, y, width, height,
969 borderWidth, relief)
970 struct PsTokenStruct *tokenPtr;
971 Tk_3DBorder border; /* Token for border to draw. */
972 double x, y; /* Coordinates of top-left of border area */
973 int width, height; /* Dimension of border to be drawn. */
974 int borderWidth; /* Desired width for border, in pixels. */
975 int relief; /* Should be either TK_RELIEF_RAISED or
976 * TK_RELIEF_SUNKEN; indicates position of
977 * interior of window relative to exterior. */
978{
979 TkBorder *borderPtr = (TkBorder *) border;
980
981 /*
982 * I'm assuming that the rectangle is to be drawn as a background.
983 * Setting the pen color as foreground or background only affects
984 * the plot when the colormode option is "monochrome".
985 */
986 Blt_BackgroundToPostScript(tokenPtr, borderPtr->bgColor);
987 Blt_RectangleToPostScript(tokenPtr, x, y, width, height);
988 Blt_Draw3DRectangleToPostScript(tokenPtr, border, x, y, width, height,
989 borderWidth, relief);
990}
991
992void
993Blt_StippleToPostScript(tokenPtr, display, bitmap)
994 struct PsTokenStruct *tokenPtr;
995 Display *display;
996 Pixmap bitmap;
997{
998 int width, height;
999
1000 Tk_SizeOfBitmap(display, bitmap, &width, &height);
1001 Blt_FormatToPostScript(tokenPtr,
1002 "gsave\n clip\n %d %d\n",
1003 width, height);
1004 Blt_BitmapDataToPostScript(tokenPtr, display, bitmap, width, height);
1005 Blt_AppendToPostScript(tokenPtr,
1006 " StippleFill\ngrestore\n",
1007 (char *)NULL);
1008}
1009
1010/*
1011 *----------------------------------------------------------------------
1012 *
1013 * Blt_ColorImageToPostScript --
1014 *
1015 * Translates a color image into 3 component RGB PostScript output.
1016 * Uses PS Language Level 2 operator "colorimage".
1017 *
1018 * Results:
1019 * The dynamic string will contain the PostScript output.
1020 *
1021 *----------------------------------------------------------------------
1022 */
1023void
1024Blt_ColorImageToPostScript(tokenPtr, image, x, y)
1025 struct PsTokenStruct *tokenPtr;
1026 Blt_ColorImage image;
1027 double x, y;
1028{
1029 int width, height;
1030 int tmpSize;
1031
1032 width = Blt_ColorImageWidth(image);
1033 height = Blt_ColorImageHeight(image);
1034
1035 tmpSize = width;
1036 if (tokenPtr->colorMode == PS_MODE_COLOR) {
1037 tmpSize *= 3;
1038 }
1039 Blt_FormatToPostScript(tokenPtr, "\n/tmpStr %d string def\n", tmpSize);
1040 Blt_AppendToPostScript(tokenPtr, "gsave\n", (char *)NULL);
1041 Blt_FormatToPostScript(tokenPtr, " %g %g translate\n", x, y);
1042 Blt_FormatToPostScript(tokenPtr, " %d %d scale\n", width, height);
1043 Blt_FormatToPostScript(tokenPtr, " %d %d 8\n", width, height);
1044 Blt_FormatToPostScript(tokenPtr, " [%d 0 0 %d 0 %d] ", width, -height,
1045 height);
1046 Blt_AppendToPostScript(tokenPtr,
1047 "{\n currentfile tmpStr readhexstring pop\n } ",
1048 (char *)NULL);
1049 if (tokenPtr->colorMode != PS_MODE_COLOR) {
1050 Blt_AppendToPostScript(tokenPtr, "image\n", (char *)NULL);
1051 Blt_ColorImageToGreyscale(image);
1052 Blt_ColorImageToPsData(image, 1, &(tokenPtr->dString), " ");
1053 } else {
1054 Blt_AppendToPostScript(tokenPtr,
1055 "false 3 colorimage\n",
1056 (char *)NULL);
1057 Blt_ColorImageToPsData(image, 3, &(tokenPtr->dString), " ");
1058 }
1059 Blt_AppendToPostScript(tokenPtr,
1060 "\ngrestore\n\n",
1061 (char *)NULL);
1062}
1063
1064/*
1065 *----------------------------------------------------------------------
1066 *
1067 * Blt_WindowToPostScript --
1068 *
1069 * Converts a Tk window to PostScript. If the window could not
1070 * be "snapped", then a grey rectangle is drawn in its place.
1071 *
1072 * Results:
1073 * None.
1074 *
1075 *----------------------------------------------------------------------
1076 */
1077void
1078Blt_WindowToPostScript(tokenPtr, tkwin, x, y)
1079 struct PsTokenStruct *tokenPtr;
1080 Tk_Window tkwin;
1081 double x, y;
1082{
1083 Blt_ColorImage image;
1084 int width, height;
1085
1086 width = Tk_Width(tkwin);
1087 height = Tk_Height(tkwin);
1088 image = Blt_DrawableToColorImage(tkwin, Tk_WindowId(tkwin), 0, 0, width,
1089 height, GAMMA);
1090 if (image == NULL) {
1091 /* Can't grab window image so paint the window area grey */
1092 Blt_AppendToPostScript(tokenPtr, "% Can't grab window \"",
1093 Tk_PathName(tkwin), "\"\n", (char *)NULL);
1094 Blt_AppendToPostScript(tokenPtr, "0.5 0.5 0.5 SetBgColor\n",
1095 (char *)NULL);
1096 Blt_RectangleToPostScript(tokenPtr, x, y, width, height);
1097 return;
1098 }
1099 Blt_ColorImageToPostScript(tokenPtr, image, x, y);
1100 Blt_FreeColorImage(image);
1101}
1102
1103/*
1104 * -------------------------------------------------------------------------
1105 *
1106 * Blt_PhotoToPostScript --
1107 *
1108 * Output a PostScript image string of the given photo image.
1109 * The photo is first converted into a color image and then
1110 * translated into PostScript.
1111 *
1112 * Results:
1113 * None.
1114 *
1115 * Side Effects:
1116 * The PostScript output representing the photo is appended to
1117 * the tokenPtr's dynamic string.
1118 *
1119 * -------------------------------------------------------------------------
1120 */
1121void
1122Blt_PhotoToPostScript(tokenPtr, photo, x, y)
1123 struct PsTokenStruct *tokenPtr;
1124 Tk_PhotoHandle photo;
1125 double x, y; /* Origin of photo image */
1126{
1127 Blt_ColorImage image;
1128
1129 image = Blt_PhotoToColorImage(photo);
1130 Blt_ColorImageToPostScript(tokenPtr, image, x, y);
1131 Blt_FreeColorImage(image);
1132}
1133
1134/*
1135 * -----------------------------------------------------------------
1136 *
1137 * Blt_FontToPostScript --
1138 *
1139 * Map the Tk font to a PostScript font and point size.
1140 *
1141 * If a Tcl array variable was specified, each element should be
1142 * indexed by the X11 font name and contain a list of 1-2
1143 * elements; the PostScript font name and the desired point size.
1144 * The point size may be omitted and the X font point size will
1145 * be used.
1146 *
1147 * Otherwise, if the foundry is "Adobe", we try to do a plausible
1148 * mapping looking at the full name of the font and building a
1149 * string in the form of "Family-TypeFace".
1150 *
1151 * Returns:
1152 * None.
1153 *
1154 * Side Effects:
1155 * PostScript commands are output to change the type and the
1156 * point size of the current font.
1157 *
1158 * -----------------------------------------------------------------
1159 */
1160
1161void
1162Blt_FontToPostScript(tokenPtr, font)
1163 struct PsTokenStruct *tokenPtr;
1164 Tk_Font font; /* Tk font to query about */
1165{
1166 XFontStruct *fontPtr = (XFontStruct *)font;
1167 Tcl_Interp *interp = tokenPtr->interp;
1168 char *fontName;
1169 double pointSize;
1170#if (TK_MAJOR_VERSION > 4)
1171 Tk_Uid family;
1172 register int i;
1173#endif /* TK_MAJOR_VERSION > 4 */
1174
1175 fontName = Tk_NameOfFont(font);
1176 pointSize = 12.0;
1177 /*
1178 * Use the font variable information if it exists.
1179 */
1180 if (tokenPtr->fontVarName != NULL) {
1181 char *fontInfo;
1182
1183 fontInfo = (char *)Tcl_GetVar2(interp, tokenPtr->fontVarName, fontName,
1184 0);
1185 if (fontInfo != NULL) {
1186 int nProps;
1187 char **propArr = NULL;
1188
1189 if (Tcl_SplitList(interp, fontInfo, &nProps, &propArr) == TCL_OK) {
1190 int newSize;
1191
1192 fontName = propArr[0];
1193 if ((nProps == 2) &&
1194 (Tcl_GetInt(interp, propArr[1], &newSize) == TCL_OK)) {
1195 pointSize = (double)newSize;
1196 }
1197 }
1198 Blt_FormatToPostScript(tokenPtr,
1199 "%g /%s SetFont\n",
1200 pointSize, fontName);
1201 if (propArr != (char **)NULL) {
1202 Blt_Free(propArr);
1203 }
1204 return;
1205 }
1206 }
1207#if (TK_MAJOR_VERSION > 4)
1208
1209 /*
1210 * Otherwise do a quick test to see if it's a PostScript font.
1211 * Tk_PostScriptFontName will silently generate a bogus PostScript
1212 * font description, so we have to check to see if this is really a
1213 * PostScript font.
1214 */
1215 family = ((TkFont *) fontPtr)->fa.family;
1216 for (i = 0; i < nFontNames; i++) {
1217 if (strncasecmp(psFontMap[i].alias, family, strlen(psFontMap[i].alias))
1218 == 0) {
1219 Tcl_DString dString;
1220
1221 Tcl_DStringInit(&dString);
1222 pointSize = (double)Tk_PostscriptFontName(font, &dString);
1223 fontName = Tcl_DStringValue(&dString);
1224 Blt_FormatToPostScript(tokenPtr, "%g /%s SetFont\n", pointSize,
1225 fontName);
1226 Tcl_DStringFree(&dString);
1227 return;
1228 }
1229 }
1230
1231#endif /* TK_MAJOR_VERSION > 4 */
1232
1233 /*
1234 * Can't find it. Try to use the current point size.
1235 */
1236 fontName = NULL;
1237 pointSize = 12.0;
1238
1239#ifndef WIN32
1240#if (TK_MAJOR_VERSION > 4)
1241 /* Can you believe what I have to go through to get an XFontStruct? */
1242 fontPtr = XLoadQueryFont(Tk_Display(tokenPtr->tkwin), Tk_NameOfFont(font));
1243#endif
1244 if (fontPtr != NULL) {
1245 unsigned long fontProp;
1246
1247 if (XGetFontProperty(fontPtr, XA_POINT_SIZE, &fontProp) != False) {
1248 pointSize = (double)fontProp / 10.0;
1249 }
1250 fontName = XFontStructToPostScript(tokenPtr->tkwin, fontPtr);
1251#if (TK_MAJOR_VERSION > 4)
1252 XFreeFont(Tk_Display(tokenPtr->tkwin), fontPtr);
1253#endif /* TK_MAJOR_VERSION > 4 */
1254 }
1255#endif /* !WIN32 */
1256 if ((fontName == NULL) || (fontName[0] == '\0')) {
1257 fontName = "Helvetica-Bold"; /* Defaulting to a known PS font */
1258 }
1259 Blt_FormatToPostScript(tokenPtr, "%g /%s SetFont\n", pointSize, fontName);
1260}
1261
1262static void
1263TextLayoutToPostScript(tokenPtr, x, y, textPtr)
1264 struct PsTokenStruct *tokenPtr;
1265 int x, y;
1266 TextLayout *textPtr;
1267{
1268 char *src, *dst, *end;
1269 int count; /* Counts the # of bytes written to
1270 * the intermediate scratch buffer. */
1271 TextFragment *fragPtr;
1272 int i;
1273 unsigned char c;
1274#if HAVE_UTF
1275 Tcl_UniChar ch;
1276#endif
1277 int limit;
1278
1279 limit = PSTOKEN_BUFSIZ - 4; /* High water mark for the scratch
1280 * buffer. */
1281 fragPtr = textPtr->fragArr;
1282 for (i = 0; i < textPtr->nFrags; i++, fragPtr++) {
1283 if (fragPtr->count < 1) {
1284 continue;
1285 }
1286 Blt_AppendToPostScript(tokenPtr, "(", (char *)NULL);
1287 count = 0;
1288 dst = tokenPtr->scratchArr;
1289 src = fragPtr->text;
1290 end = fragPtr->text + fragPtr->count;
1291 while (src < end) {
1292 if (count > limit) {
1293 /* Don't let the scatch buffer overflow */
1294 dst = tokenPtr->scratchArr;
1295 dst[count] = '\0';
1296 Blt_AppendToPostScript(tokenPtr, dst, (char *)NULL);
1297 count = 0;
1298 }
1299#if HAVE_UTF
1300 /*
1301 * INTL: For now we just treat the characters as binary
1302 * data and display the lower byte. Eventually this should
1303 * be revised to handle international postscript fonts.
1304 */
1305 src += Tcl_UtfToUniChar(src, &ch);
1306 c = (unsigned char)(ch & 0xff);
1307#else
1308 c = *src++;
1309#endif
1310
1311 if ((c == '\\') || (c == '(') || (c == ')')) {
1312 /*
1313 * If special PostScript characters characters "\", "(",
1314 * and ")" are contained in the text string, prepend
1315 * backslashes to them.
1316 */
1317 *dst++ = '\\';
1318 *dst++ = c;
1319 count += 2;
1320 } else if ((c < ' ') || (c > '~')) {
1321 /*
1322 * Present non-printable characters in their octal
1323 * representation.
1324 */
1325 sprintf(dst, "\\%03o", c);
1326 dst += 4;
1327 count += 4;
1328 } else {
1329 *dst++ = c;
1330 count++;
1331 }
1332 }
1333 tokenPtr->scratchArr[count] = '\0';
1334 Blt_AppendToPostScript(tokenPtr, tokenPtr->scratchArr, (char *)NULL);
1335 Blt_FormatToPostScript(tokenPtr, ") %d %d %d DrawAdjText\n",
1336 fragPtr->width, x + fragPtr->x, y + fragPtr->y);
1337 }
1338}
1339
1340/*
1341 * -----------------------------------------------------------------
1342 *
1343 * Blt_TextToPostScript --
1344 *
1345 * Output PostScript commands to print a text string. The string
1346 * may be rotated at any arbitrary angle, and placed according
1347 * the anchor type given. The anchor indicates how to interpret
1348 * the window coordinates as an anchor for the text bounding box.
1349 *
1350 * Results:
1351 * None.
1352 *
1353 * Side Effects:
1354 * Text string is drawn using the given font and GC on the graph
1355 * window at the given coordinates, anchor, and rotation
1356 *
1357 * -----------------------------------------------------------------
1358 */
1359void
1360Blt_TextToPostScript(tokenPtr, string, tsPtr, x, y)
1361 struct PsTokenStruct *tokenPtr;
1362 char *string; /* String to convert to PostScript */
1363 TextStyle *tsPtr; /* Text attribute information */
1364 double x, y; /* Window coordinates where to print text */
1365{
1366 double theta;
1367 double rotWidth, rotHeight;
1368 TextLayout *textPtr;
1369 Point2D anchorPos;
1370
1371 if ((string == NULL) || (*string == '\0')) { /* Empty string, do nothing */
1372 return;
1373 }
1374 theta = FMOD(tsPtr->theta, (double)360.0);
1375 textPtr = Blt_GetTextLayout(string, tsPtr);
1376 Blt_GetBoundingBox(textPtr->width, textPtr->height, theta, &rotWidth,
1377 &rotHeight, (Point2D *)NULL);
1378 /*
1379 * Find the center of the bounding box
1380 */
1381 anchorPos.x = x, anchorPos.y = y;
1382 anchorPos = Blt_TranslatePoint(&anchorPos, ROUND(rotWidth),
1383 ROUND(rotHeight), tsPtr->anchor);
1384 anchorPos.x += (rotWidth * 0.5);
1385 anchorPos.y += (rotHeight * 0.5);
1386
1387 /* Initialize text (sets translation and rotation) */
1388 Blt_FormatToPostScript(tokenPtr, "%d %d %g %g %g BeginText\n",
1389 textPtr->width, textPtr->height, tsPtr->theta, anchorPos.x,
1390 anchorPos.y);
1391
1392 Blt_FontToPostScript(tokenPtr, tsPtr->font);
1393
1394 /* All coordinates are now relative to what was set by BeginText */
1395 if ((tsPtr->shadow.offset > 0) && (tsPtr->shadow.color != NULL)) {
1396 Blt_ForegroundToPostScript(tokenPtr, tsPtr->shadow.color);
1397 TextLayoutToPostScript(tokenPtr, tsPtr->shadow.offset,
1398 tsPtr->shadow.offset, textPtr);
1399 }
1400 Blt_ForegroundToPostScript(tokenPtr, (tsPtr->state & STATE_ACTIVE)
1401 ? tsPtr->activeColor : tsPtr->color);
1402 TextLayoutToPostScript(tokenPtr, 0, 0, textPtr);
1403 Blt_Free(textPtr);
1404 Blt_AppendToPostScript(tokenPtr, "EndText\n", (char *)NULL);
1405}
1406
1407/*
1408 * -----------------------------------------------------------------
1409 *
1410 * Blt_LineToPostScript --
1411 *
1412 * Outputs PostScript commands to print a multi-segmented line.
1413 * It assumes a procedure DashesProc was previously defined.
1414 *
1415 * Results:
1416 * None.
1417 *
1418 * Side Effects:
1419 * Segmented line is printed.
1420 *
1421 * -----------------------------------------------------------------
1422 */
1423void
1424Blt_LineToPostScript(tokenPtr, pointPtr, nPoints)
1425 struct PsTokenStruct *tokenPtr;
1426 register XPoint *pointPtr;
1427 int nPoints;
1428{
1429 register int i;
1430
1431 if (nPoints <= 0) {
1432 return;
1433 }
1434 Blt_FormatToPostScript(tokenPtr, " newpath %d %d moveto\n",
1435 pointPtr->x, pointPtr->y);
1436 pointPtr++;
1437 for (i = 1; i < (nPoints - 1); i++, pointPtr++) {
1438 Blt_FormatToPostScript(tokenPtr, " %d %d lineto\n",
1439 pointPtr->x, pointPtr->y);
1440 if ((i % PS_MAXPATH) == 0) {
1441 Blt_FormatToPostScript(tokenPtr,
1442 "DashesProc stroke\n newpath %d %d moveto\n",
1443 pointPtr->x, pointPtr->y);
1444 }
1445 }
1446 Blt_FormatToPostScript(tokenPtr, " %d %d lineto\n",
1447 pointPtr->x, pointPtr->y);
1448 Blt_AppendToPostScript(tokenPtr, "DashesProc stroke\n", (char *)NULL);
1449}
1450
1451void
1452Blt_BitmapToPostScript(tokenPtr, display, bitmap, scaleX, scaleY)
1453 struct PsTokenStruct *tokenPtr;
1454 Display *display;
1455 Pixmap bitmap; /* Bitmap to be converted to PostScript */
1456 double scaleX, scaleY;
1457{
1458 int width, height;
1459 double scaledWidth, scaledHeight;
1460
1461 Tk_SizeOfBitmap(display, bitmap, &width, &height);
1462 scaledWidth = (double)width * scaleX;
1463 scaledHeight = (double)height * scaleY;
1464 Blt_AppendToPostScript(tokenPtr, " gsave\n", (char *)NULL);
1465 Blt_FormatToPostScript(tokenPtr, " %g %g translate\n",
1466 scaledWidth * -0.5, scaledHeight * 0.5);
1467 Blt_FormatToPostScript(tokenPtr, " %g %g scale\n",
1468 scaledWidth, -scaledHeight);
1469 Blt_FormatToPostScript(tokenPtr, " %d %d true [%d 0 0 %d 0 %d] {",
1470 width, height, width, -height, height);
1471 Blt_BitmapDataToPostScript(tokenPtr, display, bitmap, width, height);
1472 Blt_AppendToPostScript(tokenPtr, " } imagemask\n grestore\n",
1473 (char *)NULL);
1474}
1475
1476void
1477Blt_2DSegmentsToPostScript(psToken, segPtr, nSegments)
1478 PsToken psToken;
1479 register Segment2D *segPtr;
1480 int nSegments;
1481{
1482 register Segment2D *endPtr;
1483
1484 for (endPtr = segPtr + nSegments; segPtr < endPtr; segPtr++) {
1485 Blt_FormatToPostScript(psToken, "%g %g moveto\n",
1486 segPtr->p.x, segPtr->p.y);
1487 Blt_FormatToPostScript(psToken, " %g %g lineto\n",
1488 segPtr->q.x, segPtr->q.y);
1489 Blt_AppendToPostScript(psToken, "DashesProc stroke\n", (char *)NULL);
1490 }
1491}
Note: See TracBrowser for help on using the repository browser.