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

Annotation of /projs/trunk/shared_source/tk_base/tkwin3d.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 29 - (hide annotations) (download)
Sat Oct 8 07:08:47 2016 UTC (7 years, 7 months ago) by dashley
Original Path: to_be_filed/sf_code/esrgpcpj/shared/tk_base/tkwin3d.c
File MIME type: text/plain
File size: 17691 byte(s)
Directories relocated.
1 dashley 25 /* $Header: /cvsroot/esrg/sfesrg/esrgpcpj/shared/tk_base/tkwin3d.c,v 1.1.1.1 2001/06/13 05:11:49 dtashley Exp $ */
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    
580     /* $History: tkWin3d.c $
581     *
582     * ***************** Version 1 *****************
583     * User: Dtashley Date: 1/02/01 Time: 3:11a
584     * Created in $/IjuScripter, IjuConsole/Source/Tk Base
585     * Initial check-in.
586     */
587    
588     /* End of TKWIN3D.C */

dashley@gmail.com
ViewVC Help
Powered by ViewVC 1.1.25