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

Subversion Repositories or1k

[/] [or1k/] [tags/] [start/] [insight/] [tk/] [win/] [tkWinDraw.c] - Blame information for rev 1780

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

Line No. Rev Author Line
1 578 markom
/*
2
 * tkWinDraw.c --
3
 *
4
 *      This file contains the Xlib emulation functions pertaining to
5
 *      actually drawing objects on a window.
6
 *
7
 * Copyright (c) 1995 Sun Microsystems, Inc.
8
 * Copyright (c) 1994 Software Research Associates, Inc.
9
 *
10
 * See the file "license.terms" for information on usage and redistribution
11
 * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
12
 *
13
 * RCS: @(#) $Id: tkWinDraw.c,v 1.1.1.1 2002-01-16 10:26:02 markom Exp $
14
 */
15
 
16
#include "tkWinInt.h"
17
 
18
/*
19
 * These macros convert between X's bizarre angle units to radians.
20
 */
21
 
22
#define PI 3.14159265358979
23
#define XAngleToRadians(a) ((double)(a) / 64 * PI / 180);
24
 
25
/*
26
 * Translation table between X gc functions and Win32 raster op modes.
27
 */
28
 
29
int tkpWinRopModes[] = {
30
    R2_BLACK,                   /* GXclear */
31
    R2_MASKPEN,                 /* GXand */
32
    R2_MASKPENNOT,              /* GXandReverse */
33
    R2_COPYPEN,                 /* GXcopy */
34
    R2_MASKNOTPEN,              /* GXandInverted */
35
    R2_NOT,                     /* GXnoop */
36
    R2_XORPEN,                  /* GXxor */
37
    R2_MERGEPEN,                /* GXor */
38
    R2_NOTMERGEPEN,             /* GXnor */
39
    R2_NOTXORPEN,               /* GXequiv */
40
    R2_NOT,                     /* GXinvert */
41
    R2_MERGEPENNOT,             /* GXorReverse */
42
    R2_NOTCOPYPEN,              /* GXcopyInverted */
43
    R2_MERGENOTPEN,             /* GXorInverted */
44
    R2_NOTMASKPEN,              /* GXnand */
45
    R2_WHITE                    /* GXset */
46
};
47
 
48
/*
49
 * Translation table between X gc functions and Win32 BitBlt op modes.  Some
50
 * of the operations defined in X don't have names, so we have to construct
51
 * new opcodes for those functions.  This is arcane and probably not all that
52
 * useful, but at least it's accurate.
53
 */
54
 
55
#define NOTSRCAND       (DWORD)0x00220326 /* dest = (NOT source) AND dest */
56
#define NOTSRCINVERT    (DWORD)0x00990066 /* dest = (NOT source) XOR dest */
57
#define SRCORREVERSE    (DWORD)0x00DD0228 /* dest = source OR (NOT dest) */
58
#define SRCNAND         (DWORD)0x007700E6 /* dest = NOT (source AND dest) */
59
 
60
static int bltModes[] = {
61
    BLACKNESS,                  /* GXclear */
62
    SRCAND,                     /* GXand */
63
    SRCERASE,                   /* GXandReverse */
64
    SRCCOPY,                    /* GXcopy */
65
    NOTSRCAND,                  /* GXandInverted */
66
    PATCOPY,                    /* GXnoop */
67
    SRCINVERT,                  /* GXxor */
68
    SRCPAINT,                   /* GXor */
69
    NOTSRCERASE,                /* GXnor */
70
    NOTSRCINVERT,               /* GXequiv */
71
    DSTINVERT,                  /* GXinvert */
72
    SRCORREVERSE,               /* GXorReverse */
73
    NOTSRCCOPY,                 /* GXcopyInverted */
74
    MERGEPAINT,                 /* GXorInverted */
75
    SRCNAND,                    /* GXnand */
76
    WHITENESS                   /* GXset */
77
};
78
 
79
/*
80
 * The following raster op uses the source bitmap as a mask for the
81
 * pattern.  This is used to draw in a foreground color but leave the
82
 * background color transparent.
83
 */
84
 
85
#define MASKPAT         0x00E20746 /* dest = (src & pat) | (!src & dst) */
86
 
87
/*
88
 * The following two raster ops are used to copy the foreground and background
89
 * bits of a source pattern as defined by a stipple used as the pattern.
90
 */
91
 
92
#define COPYFG          0x00CA0749 /* dest = (pat & src) | (!pat & dst) */
93
#define COPYBG          0x00AC0744 /* dest = (!pat & src) | (pat & dst) */
94
 
95
/*
96
 * Macros used later in the file.
97
 */
98
 
99
#define MIN(a,b)        ((a>b) ? b : a)
100
#define MAX(a,b)        ((a<b) ? b : a)
101
 
102
/*
103
 * The followng typedef is used to pass Windows GDI drawing functions.
104
 */
105
 
106
typedef BOOL (CALLBACK *WinDrawFunc) _ANSI_ARGS_((HDC dc,
107
                            CONST POINT* points, int npoints));
108
 
109
/*
110
 * Forward declarations for procedures defined in this file:
111
 */
112
 
113
static POINT *          ConvertPoints _ANSI_ARGS_((XPoint *points, int npoints,
114
                            int mode, RECT *bbox));
115
static void             DrawOrFillArc _ANSI_ARGS_((Display *display,
116
                            Drawable d, GC gc, int x, int y,
117
                            unsigned int width, unsigned int height,
118
                            int start, int extent, int fill));
119
static void             RenderObject _ANSI_ARGS_((HDC dc, GC gc,
120
                            XPoint* points, int npoints, int mode, HPEN pen,
121
                            WinDrawFunc func));
122
 
123
/*
124
 *----------------------------------------------------------------------
125
 *
126
 * TkWinGetDrawableDC --
127
 *
128
 *      Retrieve the DC from a drawable.
129
 *
130
 * Results:
131
 *      Returns the window DC for windows.  Returns a new memory DC
132
 *      for pixmaps.
133
 *
134
 * Side effects:
135
 *      Sets up the palette for the device context, and saves the old
136
 *      device context state in the passed in TkWinDCState structure.
137
 *
138
 *----------------------------------------------------------------------
139
 */
140
 
141
HDC
142
TkWinGetDrawableDC(display, d, state)
143
    Display *display;
144
    Drawable d;
145
    TkWinDCState* state;
146
{
147
    HDC dc;
148
    TkWinDrawable *twdPtr = (TkWinDrawable *)d;
149
    Colormap cmap;
150
 
151
    if (twdPtr->type == TWD_WINDOW) {
152
        TkWindow *winPtr = twdPtr->window.winPtr;
153
 
154
        dc = GetDC(twdPtr->window.handle);
155
        if (winPtr == NULL) {
156
            cmap = DefaultColormap(display, DefaultScreen(display));
157
        } else {
158
            cmap = winPtr->atts.colormap;
159
        }
160
    } else if (twdPtr->type == TWD_WINDC) {
161
        dc = twdPtr->winDC.hdc;
162
        cmap = DefaultColormap(display, DefaultScreen(display));
163
    } else {
164
        dc = CreateCompatibleDC(NULL);
165
        SelectObject(dc, twdPtr->bitmap.handle);
166
        cmap = twdPtr->bitmap.colormap;
167
    }
168
    state->palette = TkWinSelectPalette(dc, cmap);
169
    return dc;
170
}
171
 
172
/*
173
 *----------------------------------------------------------------------
174
 *
175
 * TkWinReleaseDrawableDC --
176
 *
177
 *      Frees the resources associated with a drawable's DC.
178
 *
179
 * Results:
180
 *      None.
181
 *
182
 * Side effects:
183
 *      Restores the old bitmap handle to the memory DC for pixmaps.
184
 *
185
 *----------------------------------------------------------------------
186
 */
187
 
188
void
189
TkWinReleaseDrawableDC(d, dc, state)
190
    Drawable d;
191
    HDC dc;
192
    TkWinDCState *state;
193
{
194
    TkWinDrawable *twdPtr = (TkWinDrawable *)d;
195
    SelectPalette(dc, state->palette, TRUE);
196
    RealizePalette(dc);
197
    if (twdPtr->type == TWD_WINDOW) {
198
        ReleaseDC(TkWinGetHWND(d), dc);
199
    } else if (twdPtr->type == TWD_BITMAP) {
200
        DeleteDC(dc);
201
    }
202
}
203
 
204
/*
205
 *----------------------------------------------------------------------
206
 *
207
 * ConvertPoints --
208
 *
209
 *      Convert an array of X points to an array of Win32 points.
210
 *
211
 * Results:
212
 *      Returns the converted array of POINTs.
213
 *
214
 * Side effects:
215
 *      Allocates a block of memory that should not be freed.
216
 *
217
 *----------------------------------------------------------------------
218
 */
219
 
220
static POINT *
221
ConvertPoints(points, npoints, mode, bbox)
222
    XPoint *points;
223
    int npoints;
224
    int mode;                   /* CoordModeOrigin or CoordModePrevious. */
225
    RECT *bbox;                 /* Bounding box of points. */
226
{
227
    static POINT *winPoints = NULL; /* Array of points that is reused. */
228
    static int nWinPoints = -1;     /* Current size of point array. */
229
    int i;
230
 
231
    /*
232
     * To avoid paying the cost of a malloc on every drawing routine,
233
     * we reuse the last array if it is large enough.
234
     */
235
 
236
    if (npoints > nWinPoints) {
237
        if (winPoints != NULL) {
238
            ckfree((char *) winPoints);
239
        }
240
        winPoints = (POINT *) ckalloc(sizeof(POINT) * npoints);
241
        if (winPoints == NULL) {
242
            nWinPoints = -1;
243
            return NULL;
244
        }
245
        nWinPoints = npoints;
246
    }
247
 
248
    bbox->left = bbox->right = points[0].x;
249
    bbox->top = bbox->bottom = points[0].y;
250
 
251
    if (mode == CoordModeOrigin) {
252
        for (i = 0; i < npoints; i++) {
253
            winPoints[i].x = points[i].x;
254
            winPoints[i].y = points[i].y;
255
            bbox->left = MIN(bbox->left, winPoints[i].x);
256
            bbox->right = MAX(bbox->right, winPoints[i].x);
257
            bbox->top = MIN(bbox->top, winPoints[i].y);
258
            bbox->bottom = MAX(bbox->bottom, winPoints[i].y);
259
        }
260
    } else {
261
        winPoints[0].x = points[0].x;
262
        winPoints[0].y = points[0].y;
263
        for (i = 1; i < npoints; i++) {
264
            winPoints[i].x = winPoints[i-1].x + points[i].x;
265
            winPoints[i].y = winPoints[i-1].y + points[i].y;
266
            bbox->left = MIN(bbox->left, winPoints[i].x);
267
            bbox->right = MAX(bbox->right, winPoints[i].x);
268
            bbox->top = MIN(bbox->top, winPoints[i].y);
269
            bbox->bottom = MAX(bbox->bottom, winPoints[i].y);
270
        }
271
    }
272
    return winPoints;
273
}
274
 
275
/*
276
 *----------------------------------------------------------------------
277
 *
278
 * XCopyArea --
279
 *
280
 *      Copies data from one drawable to another using block transfer
281
 *      routines.
282
 *
283
 * Results:
284
 *      None.
285
 *
286
 * Side effects:
287
 *      Data is moved from a window or bitmap to a second window or
288
 *      bitmap.
289
 *
290
 *----------------------------------------------------------------------
291
 */
292
 
293
void
294
XCopyArea(display, src, dest, gc, src_x, src_y, width, height, dest_x, dest_y)
295
    Display* display;
296
    Drawable src;
297
    Drawable dest;
298
    GC gc;
299
    int src_x, src_y;
300
    unsigned int width, height;
301
    int dest_x, dest_y;
302
{
303
    HDC srcDC, destDC;
304
    TkWinDCState srcState, destState;
305
    TkpClipMask *clipPtr = (TkpClipMask*)gc->clip_mask;
306
 
307
    srcDC = TkWinGetDrawableDC(display, src, &srcState);
308
 
309
    if (src != dest) {
310
        destDC = TkWinGetDrawableDC(display, dest, &destState);
311
    } else {
312
        destDC = srcDC;
313
    }
314
 
315
    if (clipPtr && clipPtr->type == TKP_CLIP_REGION) {
316
        SelectClipRgn(destDC, (HRGN) clipPtr->value.region);
317
        OffsetClipRgn(destDC, gc->clip_x_origin, gc->clip_y_origin);
318
    }
319
 
320
    BitBlt(destDC, dest_x, dest_y, width, height, srcDC, src_x, src_y,
321
            bltModes[gc->function]);
322
 
323
    SelectClipRgn(destDC, NULL);
324
 
325
    if (src != dest) {
326
        TkWinReleaseDrawableDC(dest, destDC, &destState);
327
    }
328
    TkWinReleaseDrawableDC(src, srcDC, &srcState);
329
}
330
 
331
/*
332
 *----------------------------------------------------------------------
333
 *
334
 * XCopyPlane --
335
 *
336
 *      Copies a bitmap from a source drawable to a destination
337
 *      drawable.  The plane argument specifies which bit plane of
338
 *      the source contains the bitmap.  Note that this implementation
339
 *      ignores the gc->function.
340
 *
341
 * Results:
342
 *      None.
343
 *
344
 * Side effects:
345
 *      Changes the destination drawable.
346
 *
347
 *----------------------------------------------------------------------
348
 */
349
 
350
void
351
XCopyPlane(display, src, dest, gc, src_x, src_y, width, height, dest_x,
352
        dest_y, plane)
353
    Display* display;
354
    Drawable src;
355
    Drawable dest;
356
    GC gc;
357
    int src_x, src_y;
358
    unsigned int width, height;
359
    int dest_x, dest_y;
360
    unsigned long plane;
361
{
362
    HDC srcDC, destDC;
363
    TkWinDCState srcState, destState;
364
    HBRUSH bgBrush, fgBrush, oldBrush;
365
    TkpClipMask *clipPtr = (TkpClipMask*)gc->clip_mask;
366
 
367
    display->request++;
368
 
369
    if (plane != 1) {
370
        panic("Unexpected plane specified for XCopyPlane");
371
    }
372
 
373
    srcDC = TkWinGetDrawableDC(display, src, &srcState);
374
 
375
    if (src != dest) {
376
        destDC = TkWinGetDrawableDC(display, dest, &destState);
377
    } else {
378
        destDC = srcDC;
379
    }
380
 
381
    if (clipPtr == NULL || clipPtr->type == TKP_CLIP_REGION) {
382
 
383
        /*
384
         * Case 1: opaque bitmaps.  Windows handles the conversion
385
         * from one bit to multiple bits by setting 0 to the
386
         * foreground color, and 1 to the background color (seems
387
         * backwards, but there you are).
388
         */
389
 
390
        if (clipPtr && clipPtr->type == TKP_CLIP_REGION) {
391
            SelectClipRgn(destDC, (HRGN) clipPtr->value.region);
392
            OffsetClipRgn(destDC, gc->clip_x_origin, gc->clip_y_origin);
393
        }
394
 
395
        SetBkMode(destDC, OPAQUE);
396
        SetBkColor(destDC, gc->foreground);
397
        SetTextColor(destDC, gc->background);
398
        BitBlt(destDC, dest_x, dest_y, width, height, srcDC, src_x, src_y,
399
                SRCCOPY);
400
 
401
        SelectClipRgn(destDC, NULL);
402
    } else if (clipPtr->type == TKP_CLIP_PIXMAP) {
403
        if (clipPtr->value.pixmap == src) {
404
 
405
            /*
406
             * Case 2: transparent bitmaps are handled by setting the
407
             * destination to the foreground color whenever the source
408
             * pixel is set.
409
             */
410
 
411
            fgBrush = CreateSolidBrush(gc->foreground);
412
            oldBrush = SelectObject(destDC, fgBrush);
413
            BitBlt(destDC, dest_x, dest_y, width, height, srcDC, src_x, src_y,
414
                    MASKPAT);
415
            SelectObject(destDC, oldBrush);
416
            DeleteObject(fgBrush);
417
        } else {
418
 
419
            /*
420
             * Case 3: two arbitrary bitmaps.  Copy the source rectangle
421
             * into a color pixmap.  Use the result as a brush when
422
             * copying the clip mask into the destination.
423
             */
424
 
425
            HDC memDC, maskDC;
426
            HBITMAP bitmap;
427
            TkWinDCState maskState;
428
 
429
            fgBrush = CreateSolidBrush(gc->foreground);
430
            bgBrush = CreateSolidBrush(gc->background);
431
            maskDC = TkWinGetDrawableDC(display, clipPtr->value.pixmap,
432
                    &maskState);
433
            memDC = CreateCompatibleDC(destDC);
434
            bitmap = CreateBitmap(width, height, 1, 1, NULL);
435
            SelectObject(memDC, bitmap);
436
 
437
            /*
438
             * Set foreground bits.  We create a new bitmap containing
439
             * (source AND mask), then use it to set the foreground color
440
             * into the destination.
441
             */
442
 
443
            BitBlt(memDC, 0, 0, width, height, srcDC, src_x, src_y, SRCCOPY);
444
            BitBlt(memDC, 0, 0, width, height, maskDC,
445
                    dest_x - gc->clip_x_origin, dest_y - gc->clip_y_origin,
446
                    SRCAND);
447
            oldBrush = SelectObject(destDC, fgBrush);
448
            BitBlt(destDC, dest_x, dest_y, width, height, memDC, 0, 0,
449
                    MASKPAT);
450
 
451
            /*
452
             * Set background bits.  Same as foreground, except we use
453
             * ((NOT source) AND mask) and the background brush.
454
             */
455
 
456
            BitBlt(memDC, 0, 0, width, height, srcDC, src_x, src_y,
457
                    NOTSRCCOPY);
458
            BitBlt(memDC, 0, 0, width, height, maskDC,
459
                    dest_x - gc->clip_x_origin, dest_y - gc->clip_y_origin,
460
                    SRCAND);
461
            SelectObject(destDC, bgBrush);
462
            BitBlt(destDC, dest_x, dest_y, width, height, memDC, 0, 0,
463
                    MASKPAT);
464
 
465
            TkWinReleaseDrawableDC(clipPtr->value.pixmap, maskDC, &maskState);
466
            SelectObject(destDC, oldBrush);
467
            DeleteDC(memDC);
468
            DeleteObject(bitmap);
469
            DeleteObject(fgBrush);
470
            DeleteObject(bgBrush);
471
        }
472
    }
473
    if (src != dest) {
474
        TkWinReleaseDrawableDC(dest, destDC, &destState);
475
    }
476
    TkWinReleaseDrawableDC(src, srcDC, &srcState);
477
}
478
 
479
/*
480
 *----------------------------------------------------------------------
481
 *
482
 * TkPutImage --
483
 *
484
 *      Copies a subimage from an in-memory image to a rectangle of
485
 *      of the specified drawable.
486
 *
487
 * Results:
488
 *      None.
489
 *
490
 * Side effects:
491
 *      Draws the image on the specified drawable.
492
 *
493
 *----------------------------------------------------------------------
494
 */
495
 
496
void
497
TkPutImage(colors, ncolors, display, d, gc, image, src_x, src_y, dest_x,
498
        dest_y, width, height)
499
    unsigned long *colors;              /* Array of pixel values used by this
500
                                         * image.  May be NULL. */
501
    int ncolors;                        /* Number of colors used, or 0. */
502
    Display* display;
503
    Drawable d;                         /* Destination drawable. */
504
    GC gc;
505
    XImage* image;                      /* Source image. */
506
    int src_x, src_y;                   /* Offset of subimage. */
507
    int dest_x, dest_y;                 /* Position of subimage origin in
508
                                         * drawable.  */
509
    unsigned int width, height;         /* Dimensions of subimage. */
510
{
511
    HDC dc, dcMem;
512
    TkWinDCState state;
513
    BITMAPINFO *infoPtr;
514
    HBITMAP bitmap;
515
    char *data;
516
 
517
    display->request++;
518
 
519
    dc = TkWinGetDrawableDC(display, d, &state);
520
    SetROP2(dc, tkpWinRopModes[gc->function]);
521
    dcMem = CreateCompatibleDC(dc);
522
 
523
    if (image->bits_per_pixel == 1) {
524
        /*
525
         * If the image isn't in the right format, we have to copy
526
         * it into a new buffer in MSBFirst and word-aligned format.
527
         */
528
 
529
        if ((image->bitmap_bit_order != MSBFirst)
530
                || (image->bitmap_pad != sizeof(WORD))) {
531
            data = TkAlignImageData(image, sizeof(WORD), MSBFirst);
532
            bitmap = CreateBitmap(image->width, image->height, 1, 1, data);
533
            ckfree(data);
534
        } else {
535
            bitmap = CreateBitmap(image->width, image->height, 1, 1,
536
                    image->data);
537
        }
538
        SetTextColor(dc, gc->foreground);
539
        SetBkColor(dc, gc->background);
540
    } else {
541
        int i, usePalette;
542
 
543
        /*
544
         * Do not use a palette for TrueColor images.
545
         */
546
 
547
        usePalette = (image->bits_per_pixel < 16);
548
 
549
        if (usePalette) {
550
            infoPtr = (BITMAPINFO*) ckalloc(sizeof(BITMAPINFOHEADER)
551
                    + sizeof(RGBQUAD)*ncolors);
552
        } else {
553
            infoPtr = (BITMAPINFO*) ckalloc(sizeof(BITMAPINFOHEADER));
554
        }
555
 
556
        infoPtr->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
557
        infoPtr->bmiHeader.biWidth = image->width;
558
 
559
        /*
560
         * The following code works around a bug in Win32s.  CreateDIBitmap
561
         * fails under Win32s for top-down images.  So we have to reverse the
562
         * order of the scanlines.  If we are not running under Win32s, we can
563
         * just declare the image to be top-down.
564
         */
565
 
566
        if (tkpIsWin32s) {
567
            int y;
568
            char *srcPtr, *dstPtr, *temp;
569
 
570
            temp = ckalloc((unsigned) image->bytes_per_line);
571
            srcPtr = image->data;
572
            dstPtr = image->data+(image->bytes_per_line * (image->height - 1));
573
            for (y = 0; y < (image->height/2); y++) {
574
                memcpy(temp, srcPtr, image->bytes_per_line);
575
                memcpy(srcPtr, dstPtr, image->bytes_per_line);
576
                memcpy(dstPtr, temp, image->bytes_per_line);
577
                srcPtr += image->bytes_per_line;
578
                dstPtr -= image->bytes_per_line;
579
            }
580
            ckfree(temp);
581
            infoPtr->bmiHeader.biHeight = image->height; /* Bottom-up order */
582
        } else {
583
            infoPtr->bmiHeader.biHeight = -image->height; /* Top-down order */
584
        }
585
        infoPtr->bmiHeader.biPlanes = 1;
586
        infoPtr->bmiHeader.biBitCount = image->bits_per_pixel;
587
        infoPtr->bmiHeader.biCompression = BI_RGB;
588
        infoPtr->bmiHeader.biSizeImage = 0;
589
        infoPtr->bmiHeader.biXPelsPerMeter = 0;
590
        infoPtr->bmiHeader.biYPelsPerMeter = 0;
591
        infoPtr->bmiHeader.biClrImportant = 0;
592
 
593
        if (usePalette) {
594
            infoPtr->bmiHeader.biClrUsed = ncolors;
595
            for (i = 0; i < ncolors; i++) {
596
                infoPtr->bmiColors[i].rgbBlue = GetBValue(colors[i]);
597
                infoPtr->bmiColors[i].rgbGreen = GetGValue(colors[i]);
598
                infoPtr->bmiColors[i].rgbRed = GetRValue(colors[i]);
599
                infoPtr->bmiColors[i].rgbReserved = 0;
600
            }
601
        } else {
602
            infoPtr->bmiHeader.biClrUsed = 0;
603
        }
604
        bitmap = CreateDIBitmap(dc, &infoPtr->bmiHeader, CBM_INIT,
605
                image->data, infoPtr, DIB_RGB_COLORS);
606
        ckfree((char *) infoPtr);
607
    }
608
    bitmap = SelectObject(dcMem, bitmap);
609
    BitBlt(dc, dest_x, dest_y, width, height, dcMem, src_x, src_y, SRCCOPY);
610
    DeleteObject(SelectObject(dcMem, bitmap));
611
    DeleteDC(dcMem);
612
    TkWinReleaseDrawableDC(d, dc, &state);
613
}
614
 
615
/*
616
 *----------------------------------------------------------------------
617
 *
618
 * XFillRectangles --
619
 *
620
 *      Fill multiple rectangular areas in the given drawable.
621
 *
622
 * Results:
623
 *      None.
624
 *
625
 * Side effects:
626
 *      Draws onto the specified drawable.
627
 *
628
 *----------------------------------------------------------------------
629
 */
630
 
631
void
632
XFillRectangles(display, d, gc, rectangles, nrectangles)
633
    Display* display;
634
    Drawable d;
635
    GC gc;
636
    XRectangle* rectangles;
637
    int nrectangles;
638
{
639
    HDC dc;
640
    int i;
641
    RECT rect;
642
    TkWinDCState state;
643
    HBRUSH brush;
644
 
645
    if (d == None) {
646
        return;
647
    }
648
 
649
    dc = TkWinGetDrawableDC(display, d, &state);
650
    SetROP2(dc, tkpWinRopModes[gc->function]);
651
    brush = CreateSolidBrush(gc->foreground);
652
 
653
    if ((gc->fill_style == FillStippled
654
            || gc->fill_style == FillOpaqueStippled)
655
            && gc->stipple != None) {
656
        TkWinDrawable *twdPtr = (TkWinDrawable *)gc->stipple;
657
        HBRUSH oldBrush, stipple;
658
        HBITMAP oldBitmap, bitmap;
659
        HDC dcMem;
660
        HBRUSH bgBrush = CreateSolidBrush(gc->background);
661
 
662
        if (twdPtr->type != TWD_BITMAP) {
663
            panic("unexpected drawable type in stipple");
664
        }
665
 
666
        /*
667
         * Select stipple pattern into destination dc.
668
         */
669
 
670
        stipple = CreatePatternBrush(twdPtr->bitmap.handle);
671
        SetBrushOrgEx(dc, gc->ts_x_origin, gc->ts_y_origin, NULL);
672
        oldBrush = SelectObject(dc, stipple);
673
        dcMem = CreateCompatibleDC(dc);
674
 
675
        /*
676
         * For each rectangle, create a drawing surface which is the size of
677
         * the rectangle and fill it with the background color.  Then merge the
678
         * result with the stipple pattern.
679
         */
680
 
681
        for (i = 0; i < nrectangles; i++) {
682
            bitmap = CreateCompatibleBitmap(dc, rectangles[i].width,
683
                    rectangles[i].height);
684
            oldBitmap = SelectObject(dcMem, bitmap);
685
            rect.left = 0;
686
            rect.top = 0;
687
            rect.right = rectangles[i].width;
688
            rect.bottom = rectangles[i].height;
689
            FillRect(dcMem, &rect, brush);
690
            BitBlt(dc, rectangles[i].x, rectangles[i].y, rectangles[i].width,
691
                    rectangles[i].height, dcMem, 0, 0, COPYFG);
692
            if (gc->fill_style == FillOpaqueStippled) {
693
                FillRect(dcMem, &rect, bgBrush);
694
                BitBlt(dc, rectangles[i].x, rectangles[i].y,
695
                        rectangles[i].width, rectangles[i].height, dcMem,
696
                        0, 0, COPYBG);
697
            }
698
            SelectObject(dcMem, oldBitmap);
699
            DeleteObject(bitmap);
700
        }
701
 
702
        DeleteDC(dcMem);
703
        SelectObject(dc, oldBrush);
704
        DeleteObject(stipple);
705
        DeleteObject(bgBrush);
706
    } else {
707
        for (i = 0; i < nrectangles; i++) {
708
            TkWinFillRect(dc, rectangles[i].x, rectangles[i].y,
709
                    rectangles[i].width, rectangles[i].height, gc->foreground);
710
        }
711
    }
712
    DeleteObject(brush);
713
    TkWinReleaseDrawableDC(d, dc, &state);
714
}
715
 
716
/*
717
 *----------------------------------------------------------------------
718
 *
719
 * RenderObject --
720
 *
721
 *      This function draws a shape using a list of points, a
722
 *      stipple pattern, and the specified drawing function.
723
 *
724
 * Results:
725
 *      None.
726
 *
727
 * Side effects:
728
 *      None.
729
 *
730
 *----------------------------------------------------------------------
731
 */
732
 
733
static void
734
RenderObject(dc, gc, points, npoints, mode, pen, func)
735
    HDC dc;
736
    GC gc;
737
    XPoint* points;
738
    int npoints;
739
    int mode;
740
    HPEN pen;
741
    WinDrawFunc func;
742
{
743
    RECT rect;
744
    HPEN oldPen;
745
    HBRUSH oldBrush;
746
    POINT *winPoints = ConvertPoints(points, npoints, mode, &rect);
747
 
748
    if ((gc->fill_style == FillStippled
749
            || gc->fill_style == FillOpaqueStippled)
750
            && gc->stipple != None) {
751
 
752
        TkWinDrawable *twdPtr = (TkWinDrawable *)gc->stipple;
753
        HDC dcMem;
754
        LONG width, height;
755
        HBITMAP oldBitmap;
756
        int i;
757
        HBRUSH oldMemBrush;
758
 
759
        if (twdPtr->type != TWD_BITMAP) {
760
            panic("unexpected drawable type in stipple");
761
        }
762
 
763
        /*
764
         * Grow the bounding box enough to account for wide lines.
765
         */
766
 
767
        if (gc->line_width > 1) {
768
            rect.left -= gc->line_width;
769
            rect.top -= gc->line_width;
770
            rect.right += gc->line_width;
771
            rect.bottom += gc->line_width;
772
        }
773
 
774
        width = rect.right - rect.left;
775
        height = rect.bottom - rect.top;
776
 
777
        /*
778
         * Select stipple pattern into destination dc.
779
         */
780
 
781
        SetBrushOrgEx(dc, gc->ts_x_origin, gc->ts_y_origin, NULL);
782
        oldBrush = SelectObject(dc, CreatePatternBrush(twdPtr->bitmap.handle));
783
 
784
        /*
785
         * Create temporary drawing surface containing a copy of the
786
         * destination equal in size to the bounding box of the object.
787
         */
788
 
789
        dcMem = CreateCompatibleDC(dc);
790
        oldBitmap = SelectObject(dcMem, CreateCompatibleBitmap(dc, width,
791
                height));
792
        oldPen = SelectObject(dcMem, pen);
793
        BitBlt(dcMem, 0, 0, width, height, dc, rect.left, rect.top, SRCCOPY);
794
 
795
        /*
796
         * Translate the object for rendering in the temporary drawing
797
         * surface.
798
         */
799
 
800
        for (i = 0; i < npoints; i++) {
801
            winPoints[i].x -= rect.left;
802
            winPoints[i].y -= rect.top;
803
        }
804
 
805
        /*
806
         * Draw the object in the foreground color and copy it to the
807
         * destination wherever the pattern is set.
808
         */
809
 
810
        SetPolyFillMode(dcMem, (gc->fill_rule == EvenOddRule) ? ALTERNATE
811
                : WINDING);
812
        oldMemBrush = SelectObject(dcMem, CreateSolidBrush(gc->foreground));
813
        (*func)(dcMem, winPoints, npoints);
814
        BitBlt(dc, rect.left, rect.top, width, height, dcMem, 0, 0, COPYFG);
815
 
816
        /*
817
         * If we are rendering an opaque stipple, then draw the polygon in the
818
         * background color and copy it to the destination wherever the pattern
819
         * is clear.
820
         */
821
 
822
        if (gc->fill_style == FillOpaqueStippled) {
823
            DeleteObject(SelectObject(dcMem,
824
                    CreateSolidBrush(gc->background)));
825
            (*func)(dcMem, winPoints, npoints);
826
            BitBlt(dc, rect.left, rect.top, width, height, dcMem, 0, 0,
827
                    COPYBG);
828
        }
829
 
830
        SelectObject(dcMem, oldPen);
831
        DeleteObject(SelectObject(dcMem, oldMemBrush));
832
        DeleteObject(SelectObject(dcMem, oldBitmap));
833
        DeleteDC(dcMem);
834
    } else {
835
        oldPen = SelectObject(dc, pen);
836
        oldBrush = SelectObject(dc, CreateSolidBrush(gc->foreground));
837
        SetROP2(dc, tkpWinRopModes[gc->function]);
838
 
839
        SetPolyFillMode(dc, (gc->fill_rule == EvenOddRule) ? ALTERNATE
840
                : WINDING);
841
 
842
        (*func)(dc, winPoints, npoints);
843
 
844
        SelectObject(dc, oldPen);
845
    }
846
    DeleteObject(SelectObject(dc, oldBrush));
847
}
848
 
849
/*
850
 *----------------------------------------------------------------------
851
 *
852
 * XDrawLines --
853
 *
854
 *      Draw connected lines.
855
 *
856
 * Results:
857
 *      None.
858
 *
859
 * Side effects:
860
 *      Renders a series of connected lines.
861
 *
862
 *----------------------------------------------------------------------
863
 */
864
 
865
void
866
XDrawLines(display, d, gc, points, npoints, mode)
867
    Display* display;
868
    Drawable d;
869
    GC gc;
870
    XPoint* points;
871
    int npoints;
872
    int mode;
873
{
874
    HPEN pen;
875
    TkWinDCState state;
876
    HDC dc;
877
 
878
    if (d == None) {
879
        return;
880
    }
881
 
882
    dc = TkWinGetDrawableDC(display, d, &state);
883
 
884
    if (!tkpIsWin32s && (gc->line_width > 1)) {
885
        LOGBRUSH lb;
886
        DWORD style;
887
 
888
        lb.lbStyle = BS_SOLID;
889
        lb.lbColor = gc->foreground;
890
        lb.lbHatch = 0;
891
 
892
        style = PS_GEOMETRIC|PS_COSMETIC;
893
        switch (gc->cap_style) {
894
            case CapNotLast:
895
            case CapButt:
896
                style |= PS_ENDCAP_FLAT;
897
                break;
898
            case CapRound:
899
                style |= PS_ENDCAP_ROUND;
900
                break;
901
            default:
902
                style |= PS_ENDCAP_SQUARE;
903
                break;
904
        }
905
        switch (gc->join_style) {
906
            case JoinMiter:
907
                style |= PS_JOIN_MITER;
908
                break;
909
            case JoinRound:
910
                style |= PS_JOIN_ROUND;
911
                break;
912
            default:
913
                style |= PS_JOIN_BEVEL;
914
                break;
915
        }
916
        pen = ExtCreatePen(style, gc->line_width, &lb, 0, NULL);
917
    } else {
918
        pen = CreatePen(PS_SOLID, gc->line_width, gc->foreground);
919
    }
920
    RenderObject(dc, gc, points, npoints, mode, pen, Polyline);
921
    DeleteObject(pen);
922
 
923
    TkWinReleaseDrawableDC(d, dc, &state);
924
}
925
 
926
/*
927
 *----------------------------------------------------------------------
928
 *
929
 * XFillPolygon --
930
 *
931
 *      Draws a filled polygon.
932
 *
933
 * Results:
934
 *      None.
935
 *
936
 * Side effects:
937
 *      Draws a filled polygon on the specified drawable.
938
 *
939
 *----------------------------------------------------------------------
940
 */
941
 
942
void
943
XFillPolygon(display, d, gc, points, npoints, shape, mode)
944
    Display* display;
945
    Drawable d;
946
    GC gc;
947
    XPoint* points;
948
    int npoints;
949
    int shape;
950
    int mode;
951
{
952
    HPEN pen;
953
    TkWinDCState state;
954
    HDC dc;
955
 
956
    if (d == None) {
957
        return;
958
    }
959
 
960
    dc = TkWinGetDrawableDC(display, d, &state);
961
 
962
    pen = GetStockObject(NULL_PEN);
963
    RenderObject(dc, gc, points, npoints, mode, pen, Polygon);
964
 
965
    TkWinReleaseDrawableDC(d, dc, &state);
966
}
967
 
968
/*
969
 *----------------------------------------------------------------------
970
 *
971
 * XDrawRectangle --
972
 *
973
 *      Draws a rectangle.
974
 *
975
 * Results:
976
 *      None.
977
 *
978
 * Side effects:
979
 *      Draws a rectangle on the specified drawable.
980
 *
981
 *----------------------------------------------------------------------
982
 */
983
 
984
void
985
XDrawRectangle(display, d, gc, x, y, width, height)
986
    Display* display;
987
    Drawable d;
988
    GC gc;
989
    int x;
990
    int y;
991
    unsigned int width;
992
    unsigned int height;
993
{
994
    HPEN pen, oldPen;
995
    TkWinDCState state;
996
    HBRUSH oldBrush;
997
    HDC dc;
998
 
999
    if (d == None) {
1000
        return;
1001
    }
1002
 
1003
    dc = TkWinGetDrawableDC(display, d, &state);
1004
 
1005
    pen = CreatePen(PS_SOLID, gc->line_width, gc->foreground);
1006
    oldPen = SelectObject(dc, pen);
1007
    oldBrush = SelectObject(dc, GetStockObject(NULL_BRUSH));
1008
    SetROP2(dc, tkpWinRopModes[gc->function]);
1009
 
1010
    Rectangle(dc, x, y, x+width+1, y+height+1);
1011
 
1012
    DeleteObject(SelectObject(dc, oldPen));
1013
    SelectObject(dc, oldBrush);
1014
    TkWinReleaseDrawableDC(d, dc, &state);
1015
}
1016
 
1017
/*
1018
 *----------------------------------------------------------------------
1019
 *
1020
 * XDrawArc --
1021
 *
1022
 *      Draw an arc.
1023
 *
1024
 * Results:
1025
 *      None.
1026
 *
1027
 * Side effects:
1028
 *      Draws an arc on the specified drawable.
1029
 *
1030
 *----------------------------------------------------------------------
1031
 */
1032
 
1033
void
1034
XDrawArc(display, d, gc, x, y, width, height, start, extent)
1035
    Display* display;
1036
    Drawable d;
1037
    GC gc;
1038
    int x;
1039
    int y;
1040
    unsigned int width;
1041
    unsigned int height;
1042
    int start;
1043
    int extent;
1044
{
1045
    display->request++;
1046
 
1047
    DrawOrFillArc(display, d, gc, x, y, width, height, start, extent, 0);
1048
}
1049
 
1050
/*
1051
 *----------------------------------------------------------------------
1052
 *
1053
 * XFillArc --
1054
 *
1055
 *      Draw a filled arc.
1056
 *
1057
 * Results:
1058
 *      None.
1059
 *
1060
 * Side effects:
1061
 *      Draws a filled arc on the specified drawable.
1062
 *
1063
 *----------------------------------------------------------------------
1064
 */
1065
 
1066
void
1067
XFillArc(display, d, gc, x, y, width, height, start, extent)
1068
    Display* display;
1069
    Drawable d;
1070
    GC gc;
1071
    int x;
1072
    int y;
1073
    unsigned int width;
1074
    unsigned int height;
1075
    int start;
1076
    int extent;
1077
{
1078
    display->request++;
1079
 
1080
    DrawOrFillArc(display, d, gc, x, y, width, height, start, extent, 1);
1081
}
1082
 
1083
/*
1084
 *----------------------------------------------------------------------
1085
 *
1086
 * DrawOrFillArc --
1087
 *
1088
 *      This procedure handles the rendering of drawn or filled
1089
 *      arcs and chords.
1090
 *
1091
 * Results:
1092
 *      None.
1093
 *
1094
 * Side effects:
1095
 *      Renders the requested arc.
1096
 *
1097
 *----------------------------------------------------------------------
1098
 */
1099
 
1100
static void
1101
DrawOrFillArc(display, d, gc, x, y, width, height, start, extent, fill)
1102
    Display *display;
1103
    Drawable d;
1104
    GC gc;
1105
    int x, y;                   /* left top */
1106
    unsigned int width, height;
1107
    int start;                  /* start: three-o'clock (deg*64) */
1108
    int extent;                 /* extent: relative (deg*64) */
1109
    int fill;                   /* ==0 draw, !=0 fill */
1110
{
1111
    HDC dc;
1112
    HBRUSH brush, oldBrush;
1113
    HPEN pen, oldPen;
1114
    TkWinDCState state;
1115
    int clockwise = (extent < 0); /* non-zero if clockwise */
1116
    int xstart, ystart, xend, yend;
1117
    double radian_start, radian_end, xr, yr;
1118
 
1119
    if (d == None) {
1120
        return;
1121
    }
1122
 
1123
    dc = TkWinGetDrawableDC(display, d, &state);
1124
 
1125
    SetROP2(dc, tkpWinRopModes[gc->function]);
1126
 
1127
    /*
1128
     * Compute the absolute starting and ending angles in normalized radians.
1129
     * Swap the start and end if drawing clockwise.
1130
     */
1131
 
1132
    start = start % (64*360);
1133
    if (start < 0) {
1134
        start += (64*360);
1135
    }
1136
    extent = (start+extent) % (64*360);
1137
    if (extent < 0) {
1138
        extent += (64*360);
1139
    }
1140
    if (clockwise) {
1141
        int tmp = start;
1142
        start = extent;
1143
        extent = tmp;
1144
    }
1145
    radian_start = XAngleToRadians(start);
1146
    radian_end = XAngleToRadians(extent);
1147
 
1148
    /*
1149
     * Now compute points on the radial lines that define the starting and
1150
     * ending angles.  Be sure to take into account that the y-coordinate
1151
     * system is inverted.
1152
     */
1153
 
1154
    xr = x + width / 2.0;
1155
    yr = y + height / 2.0;
1156
    xstart = (int)((xr + cos(radian_start)*width/2.0) + 0.5);
1157
    ystart = (int)((yr + sin(-radian_start)*height/2.0) + 0.5);
1158
    xend = (int)((xr + cos(radian_end)*width/2.0) + 0.5);
1159
    yend = (int)((yr + sin(-radian_end)*height/2.0) + 0.5);
1160
 
1161
    /*
1162
     * Now draw a filled or open figure.  Note that we have to
1163
     * increase the size of the bounding box by one to account for the
1164
     * difference in pixel definitions between X and Windows.
1165
     */
1166
 
1167
    pen = CreatePen(PS_SOLID, gc->line_width, gc->foreground);
1168
    oldPen = SelectObject(dc, pen);
1169
    if (!fill) {
1170
        /*
1171
         * Note that this call will leave a gap of one pixel at the
1172
         * end of the arc for thin arcs.  We can't use ArcTo because
1173
         * it's only supported under Windows NT.
1174
         */
1175
 
1176
        Arc(dc, x, y, x+width+1, y+height+1, xstart, ystart, xend, yend);
1177
    } else {
1178
        brush = CreateSolidBrush(gc->foreground);
1179
        oldBrush = SelectObject(dc, brush);
1180
        if (gc->arc_mode == ArcChord) {
1181
            Chord(dc, x, y, x+width+1, y+height+1, xstart, ystart, xend, yend);
1182
        } else if ( gc->arc_mode == ArcPieSlice ) {
1183
            Pie(dc, x, y, x+width+1, y+height+1, xstart, ystart, xend, yend);
1184
        }
1185
        DeleteObject(SelectObject(dc, oldBrush));
1186
    }
1187
    DeleteObject(SelectObject(dc, oldPen));
1188
    TkWinReleaseDrawableDC(d, dc, &state);
1189
}
1190
 
1191
/*
1192
 *----------------------------------------------------------------------
1193
 *
1194
 * TkScrollWindow --
1195
 *
1196
 *      Scroll a rectangle of the specified window and accumulate
1197
 *      a damage region.
1198
 *
1199
 * Results:
1200
 *      Returns 0 if the scroll genereated no additional damage.
1201
 *      Otherwise, sets the region that needs to be repainted after
1202
 *      scrolling and returns 1.
1203
 *
1204
 * Side effects:
1205
 *      Scrolls the bits in the window.
1206
 *
1207
 *----------------------------------------------------------------------
1208
 */
1209
 
1210
int
1211
TkScrollWindow(tkwin, gc, x, y, width, height, dx, dy, damageRgn)
1212
    Tk_Window tkwin;            /* The window to be scrolled. */
1213
    GC gc;                      /* GC for window to be scrolled. */
1214
    int x, y, width, height;    /* Position rectangle to be scrolled. */
1215
    int dx, dy;                 /* Distance rectangle should be moved. */
1216
    TkRegion damageRgn;         /* Region to accumulate damage in. */
1217
{
1218
    HWND hwnd = TkWinGetHWND(Tk_WindowId(tkwin));
1219
    RECT scrollRect;
1220
 
1221
    scrollRect.left = x;
1222
    scrollRect.top = y;
1223
    scrollRect.right = x + width;
1224
    scrollRect.bottom = y + height;
1225
    return (ScrollWindowEx(hwnd, dx, dy, &scrollRect, NULL, (HRGN) damageRgn,
1226
            NULL, 0) == NULLREGION) ? 0 : 1;
1227
}
1228
 
1229
/*
1230
 *----------------------------------------------------------------------
1231
 *
1232
 * TkWinFillRect --
1233
 *
1234
 *      This routine fills a rectangle with the foreground color
1235
 *      from the specified GC ignoring all other GC values.  This
1236
 *      is the fastest way to fill a drawable with a solid color.
1237
 *
1238
 * Results:
1239
 *      None.
1240
 *
1241
 * Side effects:
1242
 *      Modifies the contents of the DC drawing surface.
1243
 *
1244
 *----------------------------------------------------------------------
1245
 */
1246
 
1247
void
1248
TkWinFillRect(dc, x, y, width, height, pixel)
1249
    HDC dc;
1250
    int x, y, width, height;
1251
    int pixel;
1252
{
1253
    RECT rect;
1254
    COLORREF oldColor;
1255
 
1256
    rect.left = x;
1257
    rect.top = y;
1258
    rect.right = x + width;
1259
    rect.bottom = y + height;
1260
    oldColor = SetBkColor(dc, (COLORREF)pixel);
1261
    SetBkMode(dc, OPAQUE);
1262
    ExtTextOut(dc, 0, 0, ETO_OPAQUE, &rect, NULL, 0, NULL);
1263
    SetBkColor(dc, oldColor);
1264
}

powered by: WebSVN 2.1.0

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