OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

[/] [or1k/] [tags/] [start/] [insight/] [tk/] [unix/] [tkUnix3d.c] - Blame information for rev 579

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 578 markom
/*
2
 * tkUnix3d.c --
3
 *
4
 *      This file contains the platform specific routines for
5
 *      drawing 3d borders in the Motif style.
6
 *
7
 * Copyright (c) 1996 by Sun Microsystems, Inc.
8
 *
9
 * See the file "license.terms" for information on usage and redistribution
10
 * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
11
 *
12
 * RCS: @(#) $Id: tkUnix3d.c,v 1.1.1.1 2002-01-16 10:26:01 markom Exp $
13
 */
14
 
15
#include <tk3d.h>
16
 
17
/*
18
 * This structure is used to keep track of the extra colors used
19
 * by Unix 3d borders.
20
 */
21
 
22
typedef struct {
23
    TkBorder info;
24
    GC solidGC;         /* Used to draw solid relief. */
25
} UnixBorder;
26
 
27
/*
28
 *----------------------------------------------------------------------
29
 *
30
 * TkpGetBorder --
31
 *
32
 *      This function allocates a new TkBorder structure.
33
 *
34
 * Results:
35
 *      Returns a newly allocated TkBorder.
36
 *
37
 * Side effects:
38
 *      None.
39
 *
40
 *----------------------------------------------------------------------
41
 */
42
 
43
TkBorder *
44
TkpGetBorder()
45
{
46
    UnixBorder *borderPtr = (UnixBorder *) ckalloc(sizeof(UnixBorder));
47
    borderPtr->solidGC = None;
48
    return (TkBorder *) borderPtr;
49
}
50
 
51
 
52
/*
53
 *----------------------------------------------------------------------
54
 *
55
 * TkpFreeBorder --
56
 *
57
 *      This function frees any colors allocated by the platform
58
 *      specific part of this module.
59
 *
60
 * Results:
61
 *      None.
62
 *
63
 * Side effects:
64
 *      May deallocate some colors.
65
 *
66
 *----------------------------------------------------------------------
67
 */
68
 
69
void
70
TkpFreeBorder(borderPtr)
71
    TkBorder *borderPtr;
72
{
73
    UnixBorder *unixBorderPtr = (UnixBorder *) borderPtr;
74
    Display *display = DisplayOfScreen(borderPtr->screen);
75
 
76
    if (unixBorderPtr->solidGC != None) {
77
        Tk_FreeGC(display, unixBorderPtr->solidGC);
78
    }
79
}
80
/*
81
 *--------------------------------------------------------------
82
 *
83
 * Tk_3DVerticalBevel --
84
 *
85
 *      This procedure draws a vertical bevel along one side of
86
 *      an object.  The bevel is always rectangular in shape:
87
 *                      |||
88
 *                      |||
89
 *                      |||
90
 *                      |||
91
 *                      |||
92
 *                      |||
93
 *      An appropriate shadow color is chosen for the bevel based
94
 *      on the leftBevel and relief arguments.  Normally this
95
 *      procedure is called first, then Tk_3DHorizontalBevel is
96
 *      called next to draw neat corners.
97
 *
98
 * Results:
99
 *      None.
100
 *
101
 * Side effects:
102
 *      Graphics are drawn in drawable.
103
 *
104
 *--------------------------------------------------------------
105
 */
106
 
107
void
108
Tk_3DVerticalBevel(tkwin, drawable, border, x, y, width, height,
109
        leftBevel, relief)
110
    Tk_Window tkwin;            /* Window for which border was allocated. */
111
    Drawable drawable;          /* X window or pixmap in which to draw. */
112
    Tk_3DBorder border;         /* Token for border to draw. */
113
    int x, y, width, height;    /* Area of vertical bevel. */
114
    int leftBevel;              /* Non-zero means this bevel forms the
115
                                 * left side of the object;  0 means it
116
                                 * forms the right side. */
117
    int relief;                 /* Kind of bevel to draw.  For example,
118
                                 * TK_RELIEF_RAISED means interior of
119
                                 * object should appear higher than
120
                                 * exterior. */
121
{
122
    TkBorder *borderPtr = (TkBorder *) border;
123
    GC left, right;
124
    Display *display = Tk_Display(tkwin);
125
 
126
    if ((borderPtr->lightGC == None) && (relief != TK_RELIEF_FLAT)) {
127
        TkpGetShadows(borderPtr, tkwin);
128
    }
129
 
130
    if (relief == TK_RELIEF_RAISED) {
131
        XFillRectangle(display, drawable,
132
                (leftBevel) ? borderPtr->lightGC : borderPtr->darkGC,
133
                x, y, (unsigned) width, (unsigned) height);
134
    } else if (relief == TK_RELIEF_SUNKEN) {
135
        XFillRectangle(display, drawable,
136
                (leftBevel) ? borderPtr->darkGC : borderPtr->lightGC,
137
                x, y, (unsigned) width, (unsigned) height);
138
    } else if (relief == TK_RELIEF_RIDGE) {
139
        int half;
140
 
141
        left = borderPtr->lightGC;
142
        right = borderPtr->darkGC;
143
        ridgeGroove:
144
        half = width/2;
145
        if (!leftBevel && (width & 1)) {
146
            half++;
147
        }
148
        XFillRectangle(display, drawable, left, x, y, (unsigned) half,
149
                (unsigned) height);
150
        XFillRectangle(display, drawable, right, x+half, y,
151
                (unsigned) (width-half), (unsigned) height);
152
    } else if (relief == TK_RELIEF_GROOVE) {
153
        left = borderPtr->darkGC;
154
        right = borderPtr->lightGC;
155
        goto ridgeGroove;
156
    } else if (relief == TK_RELIEF_FLAT) {
157
        XFillRectangle(display, drawable, borderPtr->bgGC, x, y,
158
                (unsigned) width, (unsigned) height);
159
    } else if (relief == TK_RELIEF_SOLID) {
160
        UnixBorder *unixBorderPtr = (UnixBorder *) borderPtr;
161
        if (unixBorderPtr->solidGC == None) {
162
            XGCValues gcValues;
163
 
164
            gcValues.foreground = BlackPixelOfScreen(borderPtr->screen);
165
            unixBorderPtr->solidGC = Tk_GetGC(tkwin, GCForeground, &gcValues);
166
        }
167
        XFillRectangle(display, drawable, unixBorderPtr->solidGC, x, y,
168
                (unsigned) width, (unsigned) height);
169
    }
170
}
171
 
172
/*
173
 *--------------------------------------------------------------
174
 *
175
 * Tk_3DHorizontalBevel --
176
 *
177
 *      This procedure draws a horizontal bevel along one side of
178
 *      an object.  The bevel has mitered corners (depending on
179
 *      leftIn and rightIn arguments).
180
 *
181
 * Results:
182
 *      None.
183
 *
184
 * Side effects:
185
 *      None.
186
 *
187
 *--------------------------------------------------------------
188
 */
189
 
190
void
191
Tk_3DHorizontalBevel(tkwin, drawable, border, x, y, width, height,
192
        leftIn, rightIn, topBevel, relief)
193
    Tk_Window tkwin;            /* Window for which border was allocated. */
194
    Drawable drawable;          /* X window or pixmap in which to draw. */
195
    Tk_3DBorder border;         /* Token for border to draw. */
196
    int x, y, width, height;    /* Bounding box of area of bevel.  Height
197
                                 * gives width of border. */
198
    int leftIn, rightIn;        /* Describes whether the left and right
199
                                 * edges of the bevel angle in or out as
200
                                 * they go down.  For example, if "leftIn"
201
                                 * is true, the left side of the bevel
202
                                 * looks like this:
203
                                 *      ___________
204
                                 *       __________
205
                                 *        _________
206
                                 *         ________
207
                                 */
208
    int topBevel;               /* Non-zero means this bevel forms the
209
                                 * top side of the object;  0 means it
210
                                 * forms the bottom side. */
211
    int relief;                 /* Kind of bevel to draw.  For example,
212
                                 * TK_RELIEF_RAISED means interior of
213
                                 * object should appear higher than
214
                                 * exterior. */
215
{
216
    TkBorder *borderPtr = (TkBorder *) border;
217
    Display *display = Tk_Display(tkwin);
218
    int bottom, halfway, x1, x2, x1Delta, x2Delta;
219
    UnixBorder *unixBorderPtr = (UnixBorder *) borderPtr;
220
    GC topGC = None, bottomGC = None;
221
                                /* Initializations needed only to prevent
222
                                 * compiler warnings. */
223
 
224
    if ((borderPtr->lightGC == None) && (relief != TK_RELIEF_FLAT) &&
225
            (relief != TK_RELIEF_SOLID)) {
226
        TkpGetShadows(borderPtr, tkwin);
227
    }
228
 
229
    /*
230
     * Compute a GC for the top half of the bevel and a GC for the
231
     * bottom half (they're the same in many cases).
232
     */
233
 
234
    switch (relief) {
235
        case TK_RELIEF_FLAT:
236
            topGC = bottomGC = borderPtr->bgGC;
237
            break;
238
        case TK_RELIEF_GROOVE:
239
            topGC = borderPtr->darkGC;
240
            bottomGC = borderPtr->lightGC;
241
            break;
242
        case TK_RELIEF_RAISED:
243
            topGC = bottomGC =
244
                    (topBevel) ? borderPtr->lightGC : borderPtr->darkGC;
245
            break;
246
        case TK_RELIEF_RIDGE:
247
            topGC = borderPtr->lightGC;
248
            bottomGC = borderPtr->darkGC;
249
            break;
250
        case TK_RELIEF_SOLID:
251
            if (unixBorderPtr->solidGC == None) {
252
                XGCValues gcValues;
253
 
254
                gcValues.foreground = BlackPixelOfScreen(borderPtr->screen);
255
                unixBorderPtr->solidGC = Tk_GetGC(tkwin, GCForeground,
256
                        &gcValues);
257
            }
258
            XFillRectangle(display, drawable, unixBorderPtr->solidGC, x, y,
259
                (unsigned) width, (unsigned) height);
260
            return;
261
        case TK_RELIEF_SUNKEN:
262
            topGC = bottomGC =
263
                    (topBevel) ? borderPtr->darkGC : borderPtr->lightGC;
264
            break;
265
    }
266
 
267
    /*
268
     * Compute various other geometry-related stuff.
269
     */
270
 
271
    x1 = x;
272
    if (!leftIn) {
273
        x1 += height;
274
    }
275
    x2 = x+width;
276
    if (!rightIn) {
277
        x2 -= height;
278
    }
279
    x1Delta = (leftIn) ? 1 : -1;
280
    x2Delta = (rightIn) ? -1 : 1;
281
    halfway = y + height/2;
282
    if (!topBevel && (height & 1)) {
283
        halfway++;
284
    }
285
    bottom = y + height;
286
 
287
    /*
288
     * Draw one line for each y-coordinate covered by the bevel.
289
     */
290
 
291
    for ( ; y < bottom; y++) {
292
        /*
293
         * In some weird cases (such as large border widths for skinny
294
         * rectangles) x1 can be >= x2.  Don't draw the lines
295
         * in these cases.
296
         */
297
 
298
        if (x1 < x2) {
299
            XFillRectangle(display, drawable,
300
                (y < halfway) ? topGC : bottomGC, x1, y,
301
                (unsigned) (x2-x1), (unsigned) 1);
302
        }
303
        x1 += x1Delta;
304
        x2 += x2Delta;
305
    }
306
}
307
 
308
/*
309
 *----------------------------------------------------------------------
310
 *
311
 * TkpGetShadows --
312
 *
313
 *      This procedure computes the shadow colors for a 3-D border
314
 *      and fills in the corresponding fields of the Border structure.
315
 *      It's called lazily, so that the colors aren't allocated until
316
 *      something is actually drawn with them.  That way, if a border
317
 *      is only used for flat backgrounds the shadow colors will
318
 *      never be allocated.
319
 *
320
 * Results:
321
 *      None.
322
 *
323
 * Side effects:
324
 *      The lightGC and darkGC fields in borderPtr get filled in,
325
 *      if they weren't already.
326
 *
327
 *----------------------------------------------------------------------
328
 */
329
 
330
void
331
TkpGetShadows(borderPtr, tkwin)
332
    TkBorder *borderPtr;                /* Information about border. */
333
    Tk_Window tkwin;            /* Window where border will be used for
334
                                 * drawing. */
335
{
336
    XColor lightColor, darkColor;
337
    int stressed, tmp1, tmp2;
338
    XGCValues gcValues;
339
 
340
    if (borderPtr->lightGC != None) {
341
        return;
342
    }
343
    stressed = TkpCmapStressed(tkwin, borderPtr->colormap);
344
 
345
    /*
346
     * First, handle the case of a color display with lots of colors.
347
     * The shadow colors get computed using whichever formula results
348
     * in the greatest change in color:
349
     * 1. Lighter shadow is half-way to white, darker shadow is half
350
     *    way to dark.
351
     * 2. Lighter shadow is 40% brighter than background, darker shadow
352
     *    is 40% darker than background.
353
     */
354
 
355
    if (!stressed && (Tk_Depth(tkwin) >= 6)) {
356
        /*
357
         * This is a color display with lots of colors.  For the dark
358
         * shadow, cut 40% from each of the background color components.
359
         * For the light shadow, boost each component by 40% or half-way
360
         * to white, whichever is greater (the first approach works
361
         * better for unsaturated colors, the second for saturated ones).
362
         */
363
 
364
        darkColor.red = (60 * (int) borderPtr->bgColorPtr->red)/100;
365
        darkColor.green = (60 * (int) borderPtr->bgColorPtr->green)/100;
366
        darkColor.blue = (60 * (int) borderPtr->bgColorPtr->blue)/100;
367
        borderPtr->darkColorPtr = Tk_GetColorByValue(tkwin, &darkColor);
368
        gcValues.foreground = borderPtr->darkColorPtr->pixel;
369
        borderPtr->darkGC = Tk_GetGC(tkwin, GCForeground, &gcValues);
370
 
371
        /*
372
         * Compute the colors using integers, not using lightColor.red
373
         * etc.: these are shorts and may have problems with integer
374
         * overflow.
375
         */
376
 
377
        tmp1 = (14 * (int) borderPtr->bgColorPtr->red)/10;
378
        if (tmp1 > MAX_INTENSITY) {
379
            tmp1 = MAX_INTENSITY;
380
        }
381
        tmp2 = (MAX_INTENSITY + (int) borderPtr->bgColorPtr->red)/2;
382
        lightColor.red = (tmp1 > tmp2) ? tmp1 : tmp2;
383
        tmp1 = (14 * (int) borderPtr->bgColorPtr->green)/10;
384
        if (tmp1 > MAX_INTENSITY) {
385
            tmp1 = MAX_INTENSITY;
386
        }
387
        tmp2 = (MAX_INTENSITY + (int) borderPtr->bgColorPtr->green)/2;
388
        lightColor.green = (tmp1 > tmp2) ? tmp1 : tmp2;
389
        tmp1 = (14 * (int) borderPtr->bgColorPtr->blue)/10;
390
        if (tmp1 > MAX_INTENSITY) {
391
            tmp1 = MAX_INTENSITY;
392
        }
393
        tmp2 = (MAX_INTENSITY + (int) borderPtr->bgColorPtr->blue)/2;
394
        lightColor.blue = (tmp1 > tmp2) ? tmp1 : tmp2;
395
        borderPtr->lightColorPtr = Tk_GetColorByValue(tkwin, &lightColor);
396
        gcValues.foreground = borderPtr->lightColorPtr->pixel;
397
        borderPtr->lightGC = Tk_GetGC(tkwin, GCForeground, &gcValues);
398
        return;
399
    }
400
 
401
    if (borderPtr->shadow == None) {
402
        borderPtr->shadow = Tk_GetBitmap((Tcl_Interp *) NULL, tkwin,
403
                Tk_GetUid("gray50"));
404
        if (borderPtr->shadow == None) {
405
            panic("TkpGetShadows couldn't allocate bitmap for border");
406
        }
407
    }
408
    if (borderPtr->visual->map_entries > 2) {
409
        /*
410
         * This isn't a monochrome display, but the colormap either
411
         * ran out of entries or didn't have very many to begin with.
412
         * Generate the light shadows with a white stipple and the
413
         * dark shadows with a black stipple.
414
         */
415
 
416
        gcValues.foreground = borderPtr->bgColorPtr->pixel;
417
        gcValues.background = BlackPixelOfScreen(borderPtr->screen);
418
        gcValues.stipple = borderPtr->shadow;
419
        gcValues.fill_style = FillOpaqueStippled;
420
        borderPtr->darkGC = Tk_GetGC(tkwin,
421
                GCForeground|GCBackground|GCStipple|GCFillStyle, &gcValues);
422
        gcValues.background = WhitePixelOfScreen(borderPtr->screen);
423
        borderPtr->lightGC = Tk_GetGC(tkwin,
424
                GCForeground|GCBackground|GCStipple|GCFillStyle, &gcValues);
425
        return;
426
    }
427
 
428
    /*
429
     * This is just a measly monochrome display, hardly even worth its
430
     * existence on this earth.  Make one shadow a 50% stipple and the
431
     * other the opposite of the background.
432
     */
433
 
434
    gcValues.foreground = WhitePixelOfScreen(borderPtr->screen);
435
    gcValues.background = BlackPixelOfScreen(borderPtr->screen);
436
    gcValues.stipple = borderPtr->shadow;
437
    gcValues.fill_style = FillOpaqueStippled;
438
    borderPtr->lightGC = Tk_GetGC(tkwin,
439
            GCForeground|GCBackground|GCStipple|GCFillStyle, &gcValues);
440
    if (borderPtr->bgColorPtr->pixel
441
            == WhitePixelOfScreen(borderPtr->screen)) {
442
        gcValues.foreground = BlackPixelOfScreen(borderPtr->screen);
443
        borderPtr->darkGC = Tk_GetGC(tkwin, GCForeground, &gcValues);
444
    } else {
445
        borderPtr->darkGC = borderPtr->lightGC;
446
        borderPtr->lightGC = Tk_GetGC(tkwin, GCForeground, &gcValues);
447
    }
448
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.