/[dtapublic]/projs/trunk/shared_source/c_tk_base_7_5_w_mods/tkwin3d.c
ViewVC logotype

Contents of /projs/trunk/shared_source/c_tk_base_7_5_w_mods/tkwin3d.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 69 - (show annotations) (download)
Sat Nov 5 10:54:17 2016 UTC (8 years, 1 month ago) by dashley
File MIME type: text/plain
File size: 17371 byte(s)
License and property (keyword) changes.
1 /* $Header$ */
2
3 /*
4 * tkWin3d.c --
5 *
6 * This file contains the platform specific routines for
7 * drawing 3d borders in the Windows 95 style.
8 *
9 * Copyright (c) 1996 by Sun Microsystems, Inc.
10 *
11 * See the file "license.terms" for information on usage and redistribution
12 * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
13 *
14 * RCS: @(#) $Id: tkwin3d.c,v 1.1.1.1 2001/06/13 05:11:49 dtashley Exp $
15 */
16
17 #include "tkWinInt.h"
18 #include "tk3d.h"
19
20 /*
21 * This structure is used to keep track of the extra colors used by
22 * Windows 3d borders.
23 */
24
25 typedef struct {
26 TkBorder info;
27 XColor *light2ColorPtr; /* System3dLight */
28 XColor *dark2ColorPtr; /* System3dDarkShadow */
29 } WinBorder;
30
31
32 /*
33 *----------------------------------------------------------------------
34 *
35 * TkpGetBorder --
36 *
37 * This function allocates a new TkBorder structure.
38 *
39 * Results:
40 * Returns a newly allocated TkBorder.
41 *
42 * Side effects:
43 * None.
44 *
45 *----------------------------------------------------------------------
46 */
47
48 TkBorder *
49 TkpGetBorder()
50 {
51 WinBorder *borderPtr = (WinBorder *) ckalloc(sizeof(WinBorder));
52 borderPtr->light2ColorPtr = NULL;
53 borderPtr->dark2ColorPtr = NULL;
54 return (TkBorder *) borderPtr;
55 }
56
57 /*
58 *----------------------------------------------------------------------
59 *
60 * TkpFreeBorder --
61 *
62 * This function frees any colors allocated by the platform
63 * specific part of this module.
64 *
65 * Results:
66 * None.
67 *
68 * Side effects:
69 * May deallocate some colors.
70 *
71 *----------------------------------------------------------------------
72 */
73
74 void
75 TkpFreeBorder(borderPtr)
76 TkBorder *borderPtr;
77 {
78 WinBorder *winBorderPtr = (WinBorder *) borderPtr;
79 if (winBorderPtr->light2ColorPtr) {
80 Tk_FreeColor(winBorderPtr->light2ColorPtr);
81 }
82 if (winBorderPtr->dark2ColorPtr) {
83 Tk_FreeColor(winBorderPtr->dark2ColorPtr);
84 }
85 }
86
87 /*
88 *--------------------------------------------------------------
89 *
90 * Tk_3DVerticalBevel --
91 *
92 * This procedure draws a vertical bevel along one side of
93 * an object. The bevel is always rectangular in shape:
94 * |||
95 * |||
96 * |||
97 * |||
98 * |||
99 * |||
100 * An appropriate shadow color is chosen for the bevel based
101 * on the leftBevel and relief arguments. Normally this
102 * procedure is called first, then Tk_3DHorizontalBevel is
103 * called next to draw neat corners.
104 *
105 * Results:
106 * None.
107 *
108 * Side effects:
109 * Graphics are drawn in drawable.
110 *
111 *--------------------------------------------------------------
112 */
113
114 void
115 Tk_3DVerticalBevel(tkwin, drawable, border, x, y, width, height,
116 leftBevel, relief)
117 Tk_Window tkwin; /* Window for which border was allocated. */
118 Drawable drawable; /* X window or pixmap in which to draw. */
119 Tk_3DBorder border; /* Token for border to draw. */
120 int x, y, width, height; /* Area of vertical bevel. */
121 int leftBevel; /* Non-zero means this bevel forms the
122 * left side of the object; 0 means it
123 * forms the right side. */
124 int relief; /* Kind of bevel to draw. For example,
125 * TK_RELIEF_RAISED means interior of
126 * object should appear higher than
127 * exterior. */
128 {
129 TkBorder *borderPtr = (TkBorder *) border;
130 int left, right;
131 Display *display = Tk_Display(tkwin);
132 TkWinDCState state;
133 HDC dc = TkWinGetDrawableDC(display, drawable, &state);
134 int half;
135
136 if ((borderPtr->lightGC == None) && (relief != TK_RELIEF_FLAT)) {
137 TkpGetShadows(borderPtr, tkwin);
138 }
139
140 switch (relief) {
141 case TK_RELIEF_RAISED:
142 left = (leftBevel)
143 ? borderPtr->lightGC->foreground
144 : borderPtr->darkGC->foreground;
145 right = (leftBevel)
146 ? ((WinBorder *)borderPtr)->light2ColorPtr->pixel
147 : ((WinBorder *)borderPtr)->dark2ColorPtr->pixel;
148 break;
149 case TK_RELIEF_SUNKEN:
150 left = (leftBevel)
151 ? ((WinBorder *)borderPtr)->dark2ColorPtr->pixel
152 : ((WinBorder *)borderPtr)->light2ColorPtr->pixel;
153 right = (leftBevel)
154 ? borderPtr->darkGC->foreground
155 : borderPtr->lightGC->foreground;
156 break;
157 case TK_RELIEF_RIDGE:
158 left = borderPtr->lightGC->foreground;
159 right = borderPtr->darkGC->foreground;
160 break;
161 case TK_RELIEF_GROOVE:
162 left = borderPtr->darkGC->foreground;
163 right = borderPtr->lightGC->foreground;
164 break;
165 case TK_RELIEF_FLAT:
166 left = right = borderPtr->bgGC->foreground;
167 break;
168 case TK_RELIEF_SOLID:
169 left = right = RGB(0,0,0);
170 break;
171 }
172 half = width/2;
173 if (leftBevel && (width & 1)) {
174 half++;
175 }
176 TkWinFillRect(dc, x, y, half, height, left);
177 TkWinFillRect(dc, x+half, y, width-half, height, right);
178 TkWinReleaseDrawableDC(drawable, dc, &state);
179 }
180
181 /*
182 *--------------------------------------------------------------
183 *
184 * Tk_3DHorizontalBevel --
185 *
186 * This procedure draws a horizontal bevel along one side of
187 * an object. The bevel has mitered corners (depending on
188 * leftIn and rightIn arguments).
189 *
190 * Results:
191 * None.
192 *
193 * Side effects:
194 * None.
195 *
196 *--------------------------------------------------------------
197 */
198
199 void
200 Tk_3DHorizontalBevel(tkwin, drawable, border, x, y, width, height,
201 leftIn, rightIn, topBevel, relief)
202 Tk_Window tkwin; /* Window for which border was allocated. */
203 Drawable drawable; /* X window or pixmap in which to draw. */
204 Tk_3DBorder border; /* Token for border to draw. */
205 int x, y, width, height; /* Bounding box of area of bevel. Height
206 * gives width of border. */
207 int leftIn, rightIn; /* Describes whether the left and right
208 * edges of the bevel angle in or out as
209 * they go down. For example, if "leftIn"
210 * is true, the left side of the bevel
211 * looks like this:
212 * ___________
213 * __________
214 * _________
215 * ________
216 */
217 int topBevel; /* Non-zero means this bevel forms the
218 * top side of the object; 0 means it
219 * forms the bottom side. */
220 int relief; /* Kind of bevel to draw. For example,
221 * TK_RELIEF_RAISED means interior of
222 * object should appear higher than
223 * exterior. */
224 {
225 TkBorder *borderPtr = (TkBorder *) border;
226 Display *display = Tk_Display(tkwin);
227 int bottom, halfway, x1, x2, x1Delta, x2Delta;
228 TkWinDCState state;
229 HDC dc = TkWinGetDrawableDC(display, drawable, &state);
230 int topColor, bottomColor;
231
232 if ((borderPtr->lightGC == None) && (relief != TK_RELIEF_FLAT)) {
233 TkpGetShadows(borderPtr, tkwin);
234 }
235
236 /*
237 * Compute a GC for the top half of the bevel and a GC for the
238 * bottom half (they're the same in many cases).
239 */
240
241 switch (relief) {
242 case TK_RELIEF_RAISED:
243 topColor = (topBevel)
244 ? borderPtr->lightGC->foreground
245 : borderPtr->darkGC->foreground;
246 bottomColor = (topBevel)
247 ? ((WinBorder *)borderPtr)->light2ColorPtr->pixel
248 : ((WinBorder *)borderPtr)->dark2ColorPtr->pixel;
249 break;
250 case TK_RELIEF_SUNKEN:
251 topColor = (topBevel)
252 ? ((WinBorder *)borderPtr)->dark2ColorPtr->pixel
253 : ((WinBorder *)borderPtr)->light2ColorPtr->pixel;
254 bottomColor = (topBevel)
255 ? borderPtr->darkGC->foreground
256 : borderPtr->lightGC->foreground;
257 break;
258 case TK_RELIEF_RIDGE:
259 topColor = borderPtr->lightGC->foreground;
260 bottomColor = borderPtr->darkGC->foreground;
261 break;
262 case TK_RELIEF_GROOVE:
263 topColor = borderPtr->darkGC->foreground;
264 bottomColor = borderPtr->lightGC->foreground;
265 break;
266 case TK_RELIEF_FLAT:
267 topColor = bottomColor = borderPtr->bgGC->foreground;
268 break;
269 case TK_RELIEF_SOLID:
270 topColor = bottomColor = RGB(0,0,0);
271 }
272
273 /*
274 * Compute various other geometry-related stuff.
275 */
276
277 if (leftIn) {
278 x1 = x+1;
279 } else {
280 x1 = x+height-1;
281 }
282 x2 = x+width;
283 if (rightIn) {
284 x2--;
285 } else {
286 x2 -= height;
287 }
288 x1Delta = (leftIn) ? 1 : -1;
289 x2Delta = (rightIn) ? -1 : 1;
290 halfway = y + height/2;
291 if (topBevel && (height & 1)) {
292 halfway++;
293 }
294 bottom = y + height;
295
296 /*
297 * Draw one line for each y-coordinate covered by the bevel.
298 */
299
300 for ( ; y < bottom; y++) {
301 /*
302 * In some weird cases (such as large border widths for skinny
303 * rectangles) x1 can be >= x2. Don't draw the lines
304 * in these cases.
305 */
306
307 if (x1 < x2) {
308 TkWinFillRect(dc, x1, y, x2-x1, 1,
309 (y < halfway) ? topColor : bottomColor);
310 }
311 x1 += x1Delta;
312 x2 += x2Delta;
313 }
314 TkWinReleaseDrawableDC(drawable, dc, &state);
315 }
316
317 /*
318 *----------------------------------------------------------------------
319 *
320 * TkpGetShadows --
321 *
322 * This procedure computes the shadow colors for a 3-D border
323 * and fills in the corresponding fields of the Border structure.
324 * It's called lazily, so that the colors aren't allocated until
325 * something is actually drawn with them. That way, if a border
326 * is only used for flat backgrounds the shadow colors will
327 * never be allocated.
328 *
329 * Results:
330 * None.
331 *
332 * Side effects:
333 * The lightGC and darkGC fields in borderPtr get filled in,
334 * if they weren't already.
335 *
336 *----------------------------------------------------------------------
337 */
338
339 void
340 TkpGetShadows(borderPtr, tkwin)
341 TkBorder *borderPtr; /* Information about border. */
342 Tk_Window tkwin; /* Window where border will be used for
343 * drawing. */
344 {
345 XColor lightColor, darkColor;
346 int tmp1, tmp2;
347 int r, g, b;
348 XGCValues gcValues;
349
350 if (borderPtr->lightGC != None) {
351 return;
352 }
353
354 /*
355 * Handle the special case of the default system colors.
356 */
357
358 if ((TkWinIndexOfColor(borderPtr->bgColorPtr) == COLOR_3DFACE)
359 || (TkWinIndexOfColor(borderPtr->bgColorPtr) == COLOR_WINDOW)) {
360 borderPtr->darkColorPtr = Tk_GetColor(NULL, tkwin,
361 Tk_GetUid("SystemButtonShadow"));
362 gcValues.foreground = borderPtr->darkColorPtr->pixel;
363 borderPtr->darkGC = Tk_GetGC(tkwin, GCForeground, &gcValues);
364 borderPtr->lightColorPtr = Tk_GetColor(NULL, tkwin,
365 Tk_GetUid("SystemButtonHighlight"));
366 gcValues.foreground = borderPtr->lightColorPtr->pixel;
367 borderPtr->lightGC = Tk_GetGC(tkwin, GCForeground, &gcValues);
368 ((WinBorder*)borderPtr)->dark2ColorPtr = Tk_GetColor(NULL, tkwin,
369 Tk_GetUid("System3dDarkShadow"));
370 ((WinBorder*)borderPtr)->light2ColorPtr = Tk_GetColor(NULL, tkwin,
371 Tk_GetUid("System3dLight"));
372 return;
373 } else {
374 darkColor.red = 0;
375 darkColor.green = 0;
376 darkColor.blue = 0;
377 ((WinBorder*)borderPtr)->dark2ColorPtr = Tk_GetColorByValue(tkwin,
378 &darkColor);
379 lightColor = *(borderPtr->bgColorPtr);
380 ((WinBorder*)borderPtr)->light2ColorPtr = Tk_GetColorByValue(tkwin,
381 &lightColor);
382 }
383
384 /*
385 * First, handle the case of a color display with lots of colors.
386 * The shadow colors get computed using whichever formula results
387 * in the greatest change in color:
388 * 1. Lighter shadow is half-way to white, darker shadow is half
389 * way to dark.
390 * 2. Lighter shadow is 40% brighter than background, darker shadow
391 * is 40% darker than background.
392 */
393
394 if (Tk_Depth(tkwin) >= 6) {
395 /*
396 * This is a color display with lots of colors. For the dark
397 * shadow, cut 40% from each of the background color components.
398 * But if the background is already very dark, make the
399 * dark color a little lighter than the background by increasing
400 * each color component 1/4th of the way to MAX_INTENSITY.
401 *
402 * For the light shadow, boost each component by 40% or half-way
403 * to white, whichever is greater (the first approach works
404 * better for unsaturated colors, the second for saturated ones).
405 * But if the background is already very bright, instead choose a
406 * slightly darker color for the light shadow by reducing each
407 * color component by 10%.
408 *
409 * Compute the colors using integers, not using lightColor.red
410 * etc.: these are shorts and may have problems with integer
411 * overflow.
412 */
413
414 /*
415 * Compute the dark shadow color
416 */
417
418 r = (int) borderPtr->bgColorPtr->red;
419 g = (int) borderPtr->bgColorPtr->green;
420 b = (int) borderPtr->bgColorPtr->blue;
421
422 if (r*0.5*r + g*1.0*g + b*0.28*b < MAX_INTENSITY*0.05*MAX_INTENSITY) {
423 darkColor.red = (MAX_INTENSITY + 3*r)/4;
424 darkColor.green = (MAX_INTENSITY + 3*g)/4;
425 darkColor.blue = (MAX_INTENSITY + 3*b)/4;
426 } else {
427 darkColor.red = (60 * r)/100;
428 darkColor.green = (60 * g)/100;
429 darkColor.blue = (60 * b)/100;
430 }
431
432 /*
433 * Allocate the dark shadow color and its GC
434 */
435
436 borderPtr->darkColorPtr = Tk_GetColorByValue(tkwin, &darkColor);
437 gcValues.foreground = borderPtr->darkColorPtr->pixel;
438 borderPtr->darkGC = Tk_GetGC(tkwin, GCForeground, &gcValues);
439
440 /*
441 * Compute the light shadow color
442 */
443
444 if (g > MAX_INTENSITY*0.95) {
445 lightColor.red = (90 * r)/100;
446 lightColor.green = (90 * g)/100;
447 lightColor.blue = (90 * b)/100;
448 } else {
449 tmp1 = (14 * r)/10;
450 if (tmp1 > MAX_INTENSITY) {
451 tmp1 = MAX_INTENSITY;
452 }
453 tmp2 = (MAX_INTENSITY + r)/2;
454 lightColor.red = (tmp1 > tmp2) ? tmp1 : tmp2;
455 tmp1 = (14 * g)/10;
456 if (tmp1 > MAX_INTENSITY) {
457 tmp1 = MAX_INTENSITY;
458 }
459 tmp2 = (MAX_INTENSITY + g)/2;
460 lightColor.green = (tmp1 > tmp2) ? tmp1 : tmp2;
461 tmp1 = (14 * b)/10;
462 if (tmp1 > MAX_INTENSITY) {
463 tmp1 = MAX_INTENSITY;
464 }
465 tmp2 = (MAX_INTENSITY + b)/2;
466 lightColor.blue = (tmp1 > tmp2) ? tmp1 : tmp2;
467 }
468
469 /*
470 * Allocate the light shadow color and its GC
471 */
472
473 borderPtr->lightColorPtr = Tk_GetColorByValue(tkwin, &lightColor);
474 gcValues.foreground = borderPtr->lightColorPtr->pixel;
475 borderPtr->lightGC = Tk_GetGC(tkwin, GCForeground, &gcValues);
476 return;
477 }
478
479 if (borderPtr->shadow == None) {
480 borderPtr->shadow = Tk_GetBitmap((Tcl_Interp *) NULL, tkwin,
481 Tk_GetUid("gray50"));
482 if (borderPtr->shadow == None) {
483 panic("TkpGetShadows couldn't allocate bitmap for border");
484 }
485 }
486 if (borderPtr->visual->map_entries > 2) {
487 /*
488 * This isn't a monochrome display, but the colormap either
489 * ran out of entries or didn't have very many to begin with.
490 * Generate the light shadows with a white stipple and the
491 * dark shadows with a black stipple.
492 */
493
494 gcValues.foreground = borderPtr->bgColorPtr->pixel;
495 gcValues.background = BlackPixelOfScreen(borderPtr->screen);
496 gcValues.stipple = borderPtr->shadow;
497 gcValues.fill_style = FillOpaqueStippled;
498 borderPtr->darkGC = Tk_GetGC(tkwin,
499 GCForeground|GCBackground|GCStipple|GCFillStyle, &gcValues);
500 gcValues.foreground = WhitePixelOfScreen(borderPtr->screen);
501 gcValues.background = borderPtr->bgColorPtr->pixel;
502 borderPtr->lightGC = Tk_GetGC(tkwin,
503 GCForeground|GCBackground|GCStipple|GCFillStyle, &gcValues);
504 return;
505 }
506
507 /*
508 * This is just a measly monochrome display, hardly even worth its
509 * existence on this earth. Make one shadow a 50% stipple and the
510 * other the opposite of the background.
511 */
512
513 gcValues.foreground = WhitePixelOfScreen(borderPtr->screen);
514 gcValues.background = BlackPixelOfScreen(borderPtr->screen);
515 gcValues.stipple = borderPtr->shadow;
516 gcValues.fill_style = FillOpaqueStippled;
517 borderPtr->lightGC = Tk_GetGC(tkwin,
518 GCForeground|GCBackground|GCStipple|GCFillStyle, &gcValues);
519 if (borderPtr->bgColorPtr->pixel
520 == WhitePixelOfScreen(borderPtr->screen)) {
521 gcValues.foreground = BlackPixelOfScreen(borderPtr->screen);
522 borderPtr->darkGC = Tk_GetGC(tkwin, GCForeground, &gcValues);
523 } else {
524 borderPtr->darkGC = borderPtr->lightGC;
525 borderPtr->lightGC = Tk_GetGC(tkwin, GCForeground, &gcValues);
526 }
527 }
528
529 /*
530 *----------------------------------------------------------------------
531 *
532 * TkWinGetBorderPixels --
533 *
534 * This routine returns the 5 COLORREFs used to draw a given
535 * 3d border.
536 *
537 * Results:
538 * Returns the colors in the specified array.
539 *
540 * Side effects:
541 * May cause the remaining colors to be allocated.
542 *
543 *----------------------------------------------------------------------
544 */
545
546 COLORREF
547 TkWinGetBorderPixels(tkwin, border, which)
548 Tk_Window tkwin;
549 Tk_3DBorder border;
550 int which; /* One of TK_3D_FLAT_GC, TK_3D_LIGHT_GC,
551 * TK_3D_DARK_GC, TK_3D_LIGHT2, TK_3D_DARK2 */
552 {
553 WinBorder *borderPtr = (WinBorder *) border;
554
555 if (borderPtr->info.lightGC == None) {
556 TkpGetShadows(&borderPtr->info, tkwin);
557 }
558 switch (which) {
559 case TK_3D_FLAT_GC:
560 return borderPtr->info.bgColorPtr->pixel;
561 case TK_3D_LIGHT_GC:
562 if (borderPtr->info.lightColorPtr == NULL) {
563 return WhitePixelOfScreen(borderPtr->info.screen);
564 }
565 return borderPtr->info.lightColorPtr->pixel;
566 case TK_3D_DARK_GC:
567 if (borderPtr->info.darkColorPtr == NULL) {
568 return BlackPixelOfScreen(borderPtr->info.screen);
569 }
570 return borderPtr->info.darkColorPtr->pixel;
571 case TK_3D_LIGHT2:
572 return borderPtr->light2ColorPtr->pixel;
573 case TK_3D_DARK2:
574 return borderPtr->dark2ColorPtr->pixel;
575 }
576 return 0;
577 }
578
579 /* End of tkwin3d.c */

Properties

Name Value
svn:keywords Header

dashley@gmail.com
ViewVC Help
Powered by ViewVC 1.1.25