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

Subversion Repositories or1k

[/] [or1k/] [trunk/] [insight/] [tk/] [win/] [tkWin3d.c] - Blame information for rev 1765

Details | Compare with Previous | View Log

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

powered by: WebSVN 2.1.0

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