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

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

Parent Directory Parent Directory | Revision Log Revision Log


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

dashley@gmail.com
ViewVC Help
Powered by ViewVC 1.1.25