source: trunk/kitgen/8.x/blt/generic/bltText.c@ 191

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

initial commit

File size: 25.2 KB
RevLine 
[175]1
2/*
3 * bltText.c --
4 *
5 * This module implements multi-line, rotate-able text for the BLT toolkit.
6 *
7 * Copyright 1993-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 <X11/Xutil.h>
30#include "bltImage.h"
31
32#define WINDEBUG 0
33
34static Blt_HashTable bitmapGCTable;
35static int initialized;
36
37static void
38DrawTextLayout(display, drawable, gc, font, x, y, textPtr)
39 Display *display;
40 Drawable drawable;
41 GC gc;
42 Tk_Font font;
43 register int x, y; /* Origin of text */
44 TextLayout *textPtr;
45{
46 register TextFragment *fragPtr;
47 register int i;
48
49 fragPtr = textPtr->fragArr;
50 for (i = 0; i < textPtr->nFrags; i++, fragPtr++) {
51#if HAVE_UTF
52 Tk_DrawChars(display, drawable, gc, font, fragPtr->text,
53 fragPtr->count, x + fragPtr->x, y + fragPtr->y);
54#else
55 XDrawString(display, drawable, gc, x + fragPtr->x, y + fragPtr->y,
56 fragPtr->text, fragPtr->count);
57#endif /*HAVE_UTF*/
58 }
59}
60
61/*
62 * -----------------------------------------------------------------
63 *
64 * Blt_GetTextLayout --
65 *
66 * Get the extents of a possibly multiple-lined text string.
67 *
68 * Results:
69 * Returns via *widthPtr* and *heightPtr* the dimensions of
70 * the text string.
71 *
72 * -----------------------------------------------------------------
73 */
74TextLayout *
75Blt_GetTextLayout(string, tsPtr)
76 char string[];
77 TextStyle *tsPtr;
78{
79 int maxHeight, maxWidth;
80 int count; /* Count # of characters on each line */
81 int nFrags;
82 int width; /* Running dimensions of the text */
83 TextFragment *fragPtr;
84 TextLayout *textPtr;
85 int lineHeight;
86 int size;
87 register char *p;
88 register int i;
89 Tk_FontMetrics fontMetrics;
90
91 Tk_GetFontMetrics(tsPtr->font, &fontMetrics);
92 lineHeight = fontMetrics.linespace +
93 tsPtr->leader + tsPtr->shadow.offset;
94 nFrags = 0;
95 for (p = string; *p != '\0'; p++) {
96 if (*p == '\n') {
97 nFrags++;
98 }
99 }
100 if ((p != string) && (*(p - 1) != '\n')) {
101 nFrags++;
102 }
103 size = sizeof(TextLayout) + (sizeof(TextFragment) * (nFrags - 1));
104 textPtr = Blt_Calloc(1, size);
105 textPtr->nFrags = nFrags;
106 nFrags = count = 0;
107 width = maxWidth = 0;
108 maxHeight = tsPtr->padTop;
109 fragPtr = textPtr->fragArr;
110 for (p = string; *p != '\0'; p++) {
111 if (*p == '\n') {
112 if (count > 0) {
113 width = Tk_TextWidth(tsPtr->font, string, count) +
114 tsPtr->shadow.offset;
115 if (width > maxWidth) {
116 maxWidth = width;
117 }
118 }
119 fragPtr->width = width;
120 fragPtr->count = count;
121 fragPtr->y = maxHeight + fontMetrics.ascent;
122 fragPtr->text = string;
123 fragPtr++;
124 nFrags++;
125 maxHeight += lineHeight;
126 string = p + 1; /* Start the string on the next line */
127 count = 0; /* Reset to indicate the start of a new line */
128 continue;
129 }
130 count++;
131 }
132 if (nFrags < textPtr->nFrags) {
133 width = Tk_TextWidth(tsPtr->font, string, count) + tsPtr->shadow.offset;
134 if (width > maxWidth) {
135 maxWidth = width;
136 }
137 fragPtr->width = width;
138 fragPtr->count = count;
139 fragPtr->y = maxHeight + fontMetrics.ascent;
140 fragPtr->text = string;
141 maxHeight += lineHeight;
142 nFrags++;
143 }
144 maxHeight += tsPtr->padBottom;
145 maxWidth += PADDING(tsPtr->padX);
146 fragPtr = textPtr->fragArr;
147 for (i = 0; i < nFrags; i++, fragPtr++) {
148 switch (tsPtr->justify) {
149 default:
150 case TK_JUSTIFY_LEFT:
151 /* No offset for left justified text strings */
152 fragPtr->x = tsPtr->padLeft;
153 break;
154 case TK_JUSTIFY_RIGHT:
155 fragPtr->x = (maxWidth - fragPtr->width) - tsPtr->padRight;
156 break;
157 case TK_JUSTIFY_CENTER:
158 fragPtr->x = (maxWidth - fragPtr->width) / 2;
159 break;
160 }
161 }
162 textPtr->width = maxWidth;
163 textPtr->height = maxHeight - tsPtr->leader;
164 return textPtr;
165}
166
167/*
168 * -----------------------------------------------------------------
169 *
170 * Blt_GetTextExtents --
171 *
172 * Get the extents of a possibly multiple-lined text string.
173 *
174 * Results:
175 * Returns via *widthPtr* and *heightPtr* the dimensions of
176 * the text string.
177 *
178 * -----------------------------------------------------------------
179 */
180void
181Blt_GetTextExtents(tsPtr, string, widthPtr, heightPtr)
182 TextStyle *tsPtr;
183 char *string;
184 int *widthPtr, *heightPtr;
185{
186 int count; /* Count # of characters on each line */
187 int width, height;
188 int w, lineHeight;
189 register char *p;
190 Tk_FontMetrics fontMetrics;
191
192 if (string == NULL) {
193 return; /* NULL string? */
194 }
195 Tk_GetFontMetrics(tsPtr->font, &fontMetrics);
196 lineHeight = fontMetrics.linespace + tsPtr->leader + tsPtr->shadow.offset;
197 count = 0;
198 width = height = 0;
199 for (p = string; *p != '\0'; p++) {
200 if (*p == '\n') {
201 if (count > 0) {
202 w = Tk_TextWidth(tsPtr->font, string, count) +
203 tsPtr->shadow.offset;
204 if (w > width) {
205 width = w;
206 }
207 }
208 height += lineHeight;
209 string = p + 1; /* Start the string on the next line */
210 count = 0; /* Reset to indicate the start of a new line */
211 continue;
212 }
213 count++;
214 }
215 if ((count > 0) && (*(p - 1) != '\n')) {
216 height += lineHeight;
217 w = Tk_TextWidth(tsPtr->font, string, count) + tsPtr->shadow.offset;
218 if (w > width) {
219 width = w;
220 }
221 }
222 *widthPtr = width + PADDING(tsPtr->padX);
223 *heightPtr = height + PADDING(tsPtr->padY);
224}
225
226/*
227 * -----------------------------------------------------------------
228 *
229 * Blt_GetBoundingBox
230 *
231 * Computes the dimensions of the bounding box surrounding a
232 * rectangle rotated about its center. If pointArr isn't NULL,
233 * the coordinates of the rotated rectangle are also returned.
234 *
235 * The dimensions are determined by rotating the rectangle, and
236 * doubling the maximum x-coordinate and y-coordinate.
237 *
238 * w = 2 * maxX, h = 2 * maxY
239 *
240 * Since the rectangle is centered at 0,0, the coordinates of
241 * the bounding box are (-w/2,-h/2 w/2,-h/2, w/2,h/2 -w/2,h/2).
242 *
243 * 0 ------- 1
244 * | |
245 * | x |
246 * | |
247 * 3 ------- 2
248 *
249 * Results:
250 * The width and height of the bounding box containing the
251 * rotated rectangle are returned.
252 *
253 * -----------------------------------------------------------------
254 */
255void
256Blt_GetBoundingBox(width, height, theta, rotWidthPtr, rotHeightPtr, bbox)
257 int width, height; /* Unrotated region */
258 double theta; /* Rotation of box */
259 double *rotWidthPtr, *rotHeightPtr; /* (out) Bounding box region */
260 Point2D *bbox; /* (out) Points of the rotated box */
261{
262 register int i;
263 double sinTheta, cosTheta;
264 double xMax, yMax;
265 register double x, y;
266 Point2D corner[4];
267
268 theta = FMOD(theta, 360.0);
269 if (FMOD(theta, (double)90.0) == 0.0) {
270 int ll, ur, ul, lr;
271 double rotWidth, rotHeight;
272 int quadrant;
273
274 /* Handle right-angle rotations specifically */
275
276 quadrant = (int)(theta / 90.0);
277 switch (quadrant) {
278 case ROTATE_270: /* 270 degrees */
279 ul = 3, ur = 0, lr = 1, ll = 2;
280 rotWidth = (double)height;
281 rotHeight = (double)width;
282 break;
283 case ROTATE_90: /* 90 degrees */
284 ul = 1, ur = 2, lr = 3, ll = 0;
285 rotWidth = (double)height;
286 rotHeight = (double)width;
287 break;
288 case ROTATE_180: /* 180 degrees */
289 ul = 2, ur = 3, lr = 0, ll = 1;
290 rotWidth = (double)width;
291 rotHeight = (double)height;
292 break;
293 default:
294 case ROTATE_0: /* 0 degrees */
295 ul = 0, ur = 1, lr = 2, ll = 3;
296 rotWidth = (double)width;
297 rotHeight = (double)height;
298 break;
299 }
300 if (bbox != NULL) {
301 x = rotWidth * 0.5;
302 y = rotHeight * 0.5;
303 bbox[ll].x = bbox[ul].x = -x;
304 bbox[ur].y = bbox[ul].y = -y;
305 bbox[lr].x = bbox[ur].x = x;
306 bbox[ll].y = bbox[lr].y = y;
307 }
308 *rotWidthPtr = rotWidth;
309 *rotHeightPtr = rotHeight;
310 return;
311 }
312 /* Set the four corners of the rectangle whose center is the origin */
313
314 corner[1].x = corner[2].x = (double)width *0.5;
315 corner[0].x = corner[3].x = -corner[1].x;
316 corner[2].y = corner[3].y = (double)height *0.5;
317 corner[0].y = corner[1].y = -corner[2].y;
318
319 theta = (-theta / 180.0) * M_PI;
320 sinTheta = sin(theta), cosTheta = cos(theta);
321 xMax = yMax = 0.0;
322
323 /* Rotate the four corners and find the maximum X and Y coordinates */
324
325 for (i = 0; i < 4; i++) {
326 x = (corner[i].x * cosTheta) - (corner[i].y * sinTheta);
327 y = (corner[i].x * sinTheta) + (corner[i].y * cosTheta);
328 if (x > xMax) {
329 xMax = x;
330 }
331 if (y > yMax) {
332 yMax = y;
333 }
334 if (bbox != NULL) {
335 bbox[i].x = x;
336 bbox[i].y = y;
337 }
338 }
339
340 /*
341 * By symmetry, the width and height of the bounding box are
342 * twice the maximum x and y coordinates.
343 */
344 *rotWidthPtr = xMax + xMax;
345 *rotHeightPtr = yMax + yMax;
346}
347
348/*
349 * -----------------------------------------------------------------
350 *
351 * Blt_TranslateAnchor --
352 *
353 * Translate the coordinates of a given bounding box based
354 * upon the anchor specified. The anchor indicates where
355 * the given xy position is in relation to the bounding box.
356 *
357 * nw --- n --- ne
358 * | |
359 * w center e
360 * | |
361 * sw --- s --- se
362 *
363 * The coordinates returned are translated to the origin of the
364 * bounding box (suitable for giving to XCopyArea, XCopyPlane, etc.)
365 *
366 * Results:
367 * The translated coordinates of the bounding box are returned.
368 *
369 * -----------------------------------------------------------------
370 */
371void
372Blt_TranslateAnchor(x, y, width, height, anchor, transXPtr, transYPtr)
373 int x, y; /* Window coordinates of anchor */
374 int width, height; /* Extents of the bounding box */
375 Tk_Anchor anchor; /* Direction of the anchor */
376 int *transXPtr, *transYPtr;
377{
378 switch (anchor) {
379 case TK_ANCHOR_NW: /* Upper left corner */
380 break;
381 case TK_ANCHOR_W: /* Left center */
382 y -= (height / 2);
383 break;
384 case TK_ANCHOR_SW: /* Lower left corner */
385 y -= height;
386 break;
387 case TK_ANCHOR_N: /* Top center */
388 x -= (width / 2);
389 break;
390 case TK_ANCHOR_CENTER: /* Center */
391 x -= (width / 2);
392 y -= (height / 2);
393 break;
394 case TK_ANCHOR_S: /* Bottom center */
395 x -= (width / 2);
396 y -= height;
397 break;
398 case TK_ANCHOR_NE: /* Upper right corner */
399 x -= width;
400 break;
401 case TK_ANCHOR_E: /* Right center */
402 x -= width;
403 y -= (height / 2);
404 break;
405 case TK_ANCHOR_SE: /* Lower right corner */
406 x -= width;
407 y -= height;
408 break;
409 }
410 *transXPtr = x;
411 *transYPtr = y;
412}
413
414/*
415 * -----------------------------------------------------------------
416 *
417 * Blt_TranslatePoint --
418 *
419 * Translate the coordinates of a given bounding box based
420 * upon the anchor specified. The anchor indicates where
421 * the given xy position is in relation to the bounding box.
422 *
423 * nw --- n --- ne
424 * | |
425 * w center e
426 * | |
427 * sw --- s --- se
428 *
429 * The coordinates returned are translated to the origin of the
430 * bounding box (suitable for giving to XCopyArea, XCopyPlane, etc.)
431 *
432 * Results:
433 * The translated coordinates of the bounding box are returned.
434 *
435 * -----------------------------------------------------------------
436 */
437Point2D
438Blt_TranslatePoint(pointPtr, width, height, anchor)
439 Point2D *pointPtr; /* Window coordinates of anchor */
440 int width, height; /* Extents of the bounding box */
441 Tk_Anchor anchor; /* Direction of the anchor */
442{
443 Point2D trans;
444
445 trans = *pointPtr;
446 switch (anchor) {
447 case TK_ANCHOR_NW: /* Upper left corner */
448 break;
449 case TK_ANCHOR_W: /* Left center */
450 trans.y -= (height * 0.5);
451 break;
452 case TK_ANCHOR_SW: /* Lower left corner */
453 trans.y -= height;
454 break;
455 case TK_ANCHOR_N: /* Top center */
456 trans.x -= (width * 0.5);
457 break;
458 case TK_ANCHOR_CENTER: /* Center */
459 trans.x -= (width * 0.5);
460 trans.y -= (height * 0.5);
461 break;
462 case TK_ANCHOR_S: /* Bottom center */
463 trans.x -= (width * 0.5);
464 trans.y -= height;
465 break;
466 case TK_ANCHOR_NE: /* Upper right corner */
467 trans.x -= width;
468 break;
469 case TK_ANCHOR_E: /* Right center */
470 trans.x -= width;
471 trans.y -= (height * 0.5);
472 break;
473 case TK_ANCHOR_SE: /* Lower right corner */
474 trans.x -= width;
475 trans.y -= height;
476 break;
477 }
478 return trans;
479}
480
481/*
482 * -----------------------------------------------------------------
483 *
484 * Blt_CreateTextBitmap --
485 *
486 * Draw a bitmap, using the the given window coordinates
487 * as an anchor for the text bounding box.
488 *
489 * Results:
490 * Returns the bitmap representing the text string.
491 *
492 * Side Effects:
493 * Bitmap is drawn using the given font and GC in the
494 * drawable at the given coordinates, anchor, and rotation.
495 *
496 * -----------------------------------------------------------------
497 */
498Pixmap
499Blt_CreateTextBitmap(tkwin, textPtr, tsPtr, bmWidthPtr, bmHeightPtr)
500 Tk_Window tkwin;
501 TextLayout *textPtr; /* Text string to draw */
502 TextStyle *tsPtr; /* Text attributes: rotation, color, font,
503 * linespacing, justification, etc. */
504 int *bmWidthPtr;
505 int *bmHeightPtr; /* Extents of rotated text string */
506{
507 int width, height;
508 Pixmap bitmap;
509 Display *display;
510 Window root;
511 GC gc;
512#ifdef WIN32
513 HDC hDC;
514 TkWinDCState state;
515#endif
516 display = Tk_Display(tkwin);
517
518 width = textPtr->width;
519 height = textPtr->height;
520
521 /* Create a temporary bitmap to contain the text string */
522 root = RootWindow(display, Tk_ScreenNumber(tkwin));
523 bitmap = Tk_GetPixmap(display, root, width, height, 1);
524 assert(bitmap != None);
525 if (bitmap == None) {
526 return None; /* Can't allocate pixmap. */
527 }
528 /* Clear the pixmap and draw the text string into it */
529 gc = Blt_GetBitmapGC(tkwin);
530#ifdef WIN32
531 hDC = TkWinGetDrawableDC(display, bitmap, &state);
532 PatBlt(hDC, 0, 0, width, height, WHITENESS);
533 TkWinReleaseDrawableDC(bitmap, hDC, &state);
534#else
535 XSetForeground(display, gc, 0);
536 XFillRectangle(display, bitmap, gc, 0, 0, width, height);
537#endif /* WIN32 */
538
539 XSetFont(display, gc, Tk_FontId(tsPtr->font));
540 XSetForeground(display, gc, 1);
541 DrawTextLayout(display, bitmap, gc, tsPtr->font, 0, 0, textPtr);
542
543#ifdef WIN32
544 /*
545 * Under Win32 when drawing into a bitmap, the bits are
546 * reversed. Which is why we are inverting the bitmap here.
547 */
548 hDC = TkWinGetDrawableDC(display, bitmap, &state);
549 PatBlt(hDC, 0, 0, width, height, DSTINVERT);
550 TkWinReleaseDrawableDC(bitmap, hDC, &state);
551#endif
552 if (tsPtr->theta != 0.0) {
553 Pixmap rotBitmap;
554
555 /* Replace the text pixmap with a rotated one */
556
557 rotBitmap = Blt_RotateBitmap(tkwin, bitmap, width, height,
558 tsPtr->theta, bmWidthPtr, bmHeightPtr);
559 assert(rotBitmap);
560 if (rotBitmap != None) {
561 Tk_FreePixmap(display, bitmap);
562 return rotBitmap;
563 }
564 }
565 *bmWidthPtr = textPtr->width, *bmHeightPtr = textPtr->height;
566 return bitmap;
567}
568
569/*LINTLIBRARY*/
570void
571Blt_InitTextStyle(tsPtr)
572 TextStyle *tsPtr;
573{
574 /* Initialize these attributes to zero */
575 tsPtr->activeColor = (XColor *)NULL;
576 tsPtr->anchor = TK_ANCHOR_CENTER;
577 tsPtr->color = (XColor *)NULL;
578 tsPtr->font = NULL;
579 tsPtr->justify = TK_JUSTIFY_CENTER;
580 tsPtr->leader = 0;
581 tsPtr->padLeft = tsPtr->padRight = 0;
582 tsPtr->padTop = tsPtr->padBottom = 0;
583 tsPtr->shadow.color = (XColor *)NULL;
584 tsPtr->shadow.offset = 0;
585 tsPtr->state = 0;
586 tsPtr->theta = 0.0;
587}
588
589void
590Blt_SetDrawTextStyle(tsPtr, font, gc, normalColor, activeColor, shadowColor,
591 theta, anchor, justify, leader, shadowOffset)
592 TextStyle *tsPtr;
593 Tk_Font font;
594 GC gc;
595 XColor *normalColor, *activeColor, *shadowColor;
596 double theta;
597 Tk_Anchor anchor;
598 Tk_Justify justify;
599 int leader, shadowOffset;
600{
601 Blt_InitTextStyle(tsPtr);
602 tsPtr->activeColor = activeColor;
603 tsPtr->anchor = anchor;
604 tsPtr->color = normalColor;
605 tsPtr->font = font;
606 tsPtr->gc = gc;
607 tsPtr->justify = justify;
608 tsPtr->leader = leader;
609 tsPtr->shadow.color = shadowColor;
610 tsPtr->shadow.offset = shadowOffset;
611 tsPtr->theta = theta;
612}
613
614void
615Blt_SetPrintTextStyle(tsPtr, font, fgColor, activeColor, shadowColor, theta,
616 anchor, justify, leader, shadowOffset)
617 TextStyle *tsPtr;
618 Tk_Font font;
619 XColor *fgColor, *activeColor, *shadowColor;
620 double theta;
621 Tk_Anchor anchor;
622 Tk_Justify justify;
623 int leader, shadowOffset;
624{
625 Blt_InitTextStyle(tsPtr);
626 tsPtr->color = fgColor;
627 tsPtr->activeColor = activeColor;
628 tsPtr->shadow.color = shadowColor;
629 tsPtr->font = font;
630 tsPtr->theta = theta;
631 tsPtr->anchor = anchor;
632 tsPtr->justify = justify;
633 tsPtr->leader = leader;
634 tsPtr->shadow.offset = shadowOffset;
635}
636
637/*
638 * -----------------------------------------------------------------
639 *
640 * Blt_DrawTextLayout --
641 *
642 * Draw a text string, possibly rotated, using the the given
643 * window coordinates as an anchor for the text bounding box.
644 * If the text is not rotated, simply use the X text drawing
645 * routines. Otherwise, generate a bitmap of the rotated text.
646 *
647 * Results:
648 * Returns the x-coordinate to the right of the text.
649 *
650 * Side Effects:
651 * Text string is drawn using the given font and GC at the
652 * the given window coordinates.
653 *
654 * The Stipple, FillStyle, and TSOrigin fields of the GC are
655 * modified for rotated text. This assumes the GC is private,
656 * *not* shared (via Tk_GetGC)
657 *
658 * -----------------------------------------------------------------
659 */
660void
661Blt_DrawTextLayout(tkwin, drawable, textPtr, tsPtr, x, y)
662 Tk_Window tkwin;
663 Drawable drawable;
664 TextLayout *textPtr;
665 TextStyle *tsPtr; /* Text attribute information */
666 int x, y; /* Window coordinates to draw text */
667{
668 int width, height;
669 double theta;
670 Display *display;
671 Pixmap bitmap;
672 int active;
673
674 if (!textPtr)
675 return;
676
677 display = Tk_Display(tkwin);
678 theta = FMOD(tsPtr->theta, (double)360.0);
679 if (theta < 0.0) {
680 theta += 360.0;
681 }
682 active = tsPtr->state & STATE_ACTIVE;
683 if (theta == 0.0) {
684
685 /*
686 * This is the easy case of no rotation. Simply draw the text
687 * using the standard drawing routines. Handle offset printing
688 * for engraved (disabled) and shadowed text.
689 */
690 width = textPtr->width, height = textPtr->height;
691 Blt_TranslateAnchor(x, y, width, height, tsPtr->anchor, &x, &y);
692 if (tsPtr->state & (STATE_DISABLED | STATE_EMPHASIS)) {
693 TkBorder *borderPtr = (TkBorder *) tsPtr->border;
694 XColor *color1, *color2;
695
696 color1 = borderPtr->lightColor, color2 = borderPtr->darkColor;
697 if (tsPtr->state & STATE_EMPHASIS) {
698 XColor *hold;
699
700 hold = color1, color1 = color2, color2 = hold;
701 }
702 if (color1 != NULL) {
703 XSetForeground(display, tsPtr->gc, color1->pixel);
704 }
705 DrawTextLayout(display, drawable, tsPtr->gc, tsPtr->font, x + 1,
706 y + 1, textPtr);
707 if (color2 != NULL) {
708 XSetForeground(display, tsPtr->gc, color2->pixel);
709 }
710 DrawTextLayout(display, drawable, tsPtr->gc, tsPtr->font, x, y,
711 textPtr);
712
713 /* Reset the foreground color back to its original setting,
714 * so not to invalidate the GC cache. */
715 XSetForeground(display, tsPtr->gc, tsPtr->color->pixel);
716
717 return; /* Done */
718 }
719 if ((tsPtr->shadow.offset > 0) && (tsPtr->shadow.color != NULL)) {
720 XSetForeground(display, tsPtr->gc, tsPtr->shadow.color->pixel);
721 DrawTextLayout(display, drawable, tsPtr->gc, tsPtr->font,
722 x + tsPtr->shadow.offset, y + tsPtr->shadow.offset, textPtr);
723 XSetForeground(display, tsPtr->gc, tsPtr->color->pixel);
724 }
725 if (active) {
726 XSetForeground(display, tsPtr->gc, tsPtr->activeColor->pixel);
727 }
728 DrawTextLayout(display, drawable, tsPtr->gc, tsPtr->font, x, y,
729 textPtr);
730 if (active) {
731 XSetForeground(display, tsPtr->gc, tsPtr->color->pixel);
732 }
733 return; /* Done */
734 }
735#ifdef WIN32
736 if (Blt_DrawRotatedText(display, drawable, x, y, theta, tsPtr, textPtr)) {
737 return;
738 }
739#endif
740 /*
741 * Rotate the text by writing the text into a bitmap and rotating
742 * the bitmap. Set the clip mask and origin in the GC first. And
743 * make sure we restore the GC because it may be shared.
744 */
745 tsPtr->theta = theta;
746 bitmap = Blt_CreateTextBitmap(tkwin, textPtr, tsPtr, &width, &height);
747 if (bitmap == None) {
748 return;
749 }
750 Blt_TranslateAnchor(x, y, width, height, tsPtr->anchor, &x, &y);
751#ifdef notdef
752 theta = FMOD(theta, (double)90.0);
753#endif
754 XSetClipMask(display, tsPtr->gc, bitmap);
755
756 if (tsPtr->state & (STATE_DISABLED | STATE_EMPHASIS)) {
757 TkBorder *borderPtr = (TkBorder *) tsPtr->border;
758 XColor *color1, *color2;
759
760 color1 = borderPtr->lightColor, color2 = borderPtr->darkColor;
761 if (tsPtr->state & STATE_EMPHASIS) {
762 XColor *hold;
763
764 hold = color1, color1 = color2, color2 = hold;
765 }
766 if (color1 != NULL) {
767 XSetForeground(display, tsPtr->gc, color1->pixel);
768 }
769 XSetClipOrigin(display, tsPtr->gc, x + 1, y + 1);
770 XCopyPlane(display, bitmap, drawable, tsPtr->gc, 0, 0, width,
771 height, x + 1, y + 1, 1);
772 if (color2 != NULL) {
773 XSetForeground(display, tsPtr->gc, color2->pixel);
774 }
775 XSetClipOrigin(display, tsPtr->gc, x, y);
776 XCopyPlane(display, bitmap, drawable, tsPtr->gc, 0, 0, width,
777 height, x, y, 1);
778 XSetForeground(display, tsPtr->gc, tsPtr->color->pixel);
779 } else {
780 if ((tsPtr->shadow.offset > 0) && (tsPtr->shadow.color != NULL)) {
781 XSetClipOrigin(display, tsPtr->gc, x + tsPtr->shadow.offset,
782 y + tsPtr->shadow.offset);
783 XSetForeground(display, tsPtr->gc, tsPtr->shadow.color->pixel);
784 XCopyPlane(display, bitmap, drawable, tsPtr->gc, 0, 0, width,
785 height, x + tsPtr->shadow.offset, y + tsPtr->shadow.offset, 1);
786 XSetForeground(display, tsPtr->gc, tsPtr->color->pixel);
787 }
788 if (active) {
789 XSetForeground(display, tsPtr->gc, tsPtr->activeColor->pixel);
790 }
791 XSetClipOrigin(display, tsPtr->gc, x, y);
792 XCopyPlane(display, bitmap, drawable, tsPtr->gc, 0, 0, width, height,
793 x, y, 1);
794 if (active) {
795 XSetForeground(display, tsPtr->gc, tsPtr->color->pixel);
796 }
797 }
798 XSetClipMask(display, tsPtr->gc, None);
799 Tk_FreePixmap(display, bitmap);
800}
801
802void
803Blt_DrawText2(tkwin, drawable, string, tsPtr, x, y, areaPtr)
804 Tk_Window tkwin;
805 Drawable drawable;
806 char string[];
807 TextStyle *tsPtr; /* Text attribute information */
808 int x, y; /* Window coordinates to draw text */
809 Dim2D *areaPtr;
810{
811 TextLayout *textPtr;
812 int width, height;
813 double theta;
814
815 if ((string == NULL) || (*string == '\0')) {
816 return; /* Empty string, do nothing */
817 }
818 textPtr = Blt_GetTextLayout(string, tsPtr);
819 Blt_DrawTextLayout(tkwin, drawable, textPtr, tsPtr, x, y);
820 theta = FMOD(tsPtr->theta, (double)360.0);
821 if (theta < 0.0) {
822 theta += 360.0;
823 }
824 width = textPtr->width;
825 height = textPtr->height;
826 if (theta != 0.0) {
827 double rotWidth, rotHeight;
828
829 Blt_GetBoundingBox(width, height, theta, &rotWidth, &rotHeight,
830 (Point2D *)NULL);
831 width = ROUND(rotWidth);
832 height = ROUND(rotHeight);
833 }
834 areaPtr->width = width;
835 areaPtr->height = height;
836 Blt_Free(textPtr);
837}
838
839void
840Blt_DrawText(tkwin, drawable, string, tsPtr, x, y)
841 Tk_Window tkwin;
842 Drawable drawable;
843 char string[];
844 TextStyle *tsPtr; /* Text attribute information */
845 int x, y; /* Window coordinates to draw text */
846{
847 TextLayout *textPtr;
848
849 if ((string == NULL) || (*string == '\0')) {
850 return; /* Empty string, do nothing */
851 }
852 textPtr = Blt_GetTextLayout(string, tsPtr);
853 Blt_DrawTextLayout(tkwin, drawable, textPtr, tsPtr, x, y);
854 Blt_Free(textPtr);
855}
856
857GC
858Blt_GetBitmapGC(tkwin)
859 Tk_Window tkwin;
860{
861 int isNew;
862 GC gc;
863 Display *display;
864 Blt_HashEntry *hPtr;
865
866 if (!initialized) {
867 Blt_InitHashTable(&bitmapGCTable, BLT_ONE_WORD_KEYS);
868 initialized = TRUE;
869 }
870 display = Tk_Display(tkwin);
871 hPtr = Blt_CreateHashEntry(&bitmapGCTable, (char *)display, &isNew);
872 if (isNew) {
873 Pixmap bitmap;
874 XGCValues gcValues;
875 unsigned long gcMask;
876 Window root;
877
878 root = RootWindow(display, Tk_ScreenNumber(tkwin));
879 bitmap = Tk_GetPixmap(display, root, 1, 1, 1);
880 gcValues.foreground = gcValues.background = 0;
881 gcMask = (GCForeground | GCBackground);
882 gc = Blt_GetPrivateGCFromDrawable(display, bitmap, gcMask, &gcValues);
883 Tk_FreePixmap(display, bitmap);
884 Blt_SetHashValue(hPtr, gc);
885 } else {
886 gc = (GC)Blt_GetHashValue(hPtr);
887 }
888 return gc;
889}
890
891void
892Blt_ResetTextStyle(tkwin, tsPtr)
893 Tk_Window tkwin;
894 TextStyle *tsPtr;
895{
896 GC newGC;
897 XGCValues gcValues;
898 unsigned long gcMask;
899
900 gcMask = GCFont;
901 gcValues.font = Tk_FontId(tsPtr->font);
902 if (tsPtr->color != NULL) {
903 gcMask |= GCForeground;
904 gcValues.foreground = tsPtr->color->pixel;
905 }
906 newGC = Tk_GetGC(tkwin, gcMask, &gcValues);
907 if (tsPtr->gc != NULL) {
908 Tk_FreeGC(Tk_Display(tkwin), tsPtr->gc);
909 }
910 tsPtr->gc = newGC;
911}
912
913void
914Blt_FreeTextStyle(display, tsPtr)
915 Display *display;
916 TextStyle *tsPtr;
917{
918 if (tsPtr->gc != NULL) {
919 Tk_FreeGC(display, tsPtr->gc);
920 }
921}
Note: See TracBrowser for help on using the repository browser.