1 | /*
|
---|
2 | * bltWinDraw.c --
|
---|
3 | *
|
---|
4 | * This module contains WIN32 routines not included in the Tcl/Tk
|
---|
5 | * libraries.
|
---|
6 | *
|
---|
7 | * Copyright 1998 by Bell Labs Innovations for Lucent Technologies.
|
---|
8 | *
|
---|
9 | * Permission to use, copy, modify, and distribute this software and
|
---|
10 | * its documentation for any purpose and without fee is hereby
|
---|
11 | * granted, provided that the above copyright notice appear in all
|
---|
12 | * copies and that both that the copyright notice and warranty
|
---|
13 | * disclaimer appear in supporting documentation, and that the names
|
---|
14 | * of Lucent Technologies any of their entities not be used in
|
---|
15 | * advertising or publicity pertaining to distribution of the software
|
---|
16 | * without specific, written prior permission.
|
---|
17 | *
|
---|
18 | * Lucent Technologies disclaims all warranties with regard to this
|
---|
19 | * software, including all implied warranties of merchantability and
|
---|
20 | * fitness. In no event shall Lucent Technologies be liable for any
|
---|
21 | * special, indirect or consequential damages or any damages
|
---|
22 | * whatsoever resulting from loss of use, data or profits, whether in
|
---|
23 | * an action of contract, negligence or other tortuous action, arising
|
---|
24 | * out of or in connection with the use or performance of this
|
---|
25 | * software.
|
---|
26 | */
|
---|
27 |
|
---|
28 | #include "bltInt.h"
|
---|
29 | #include <X11/Xutil.h>
|
---|
30 | #include <X11/Xlib.h>
|
---|
31 |
|
---|
32 | #define WINDEBUG 0
|
---|
33 |
|
---|
34 | /*
|
---|
35 | * Data structure for setting graphics context.
|
---|
36 | */
|
---|
37 | typedef struct {
|
---|
38 | int function; /* logical operation */
|
---|
39 | unsigned long plane_mask; /* plane mask */
|
---|
40 | unsigned long foreground; /* foreground pixel */
|
---|
41 | unsigned long background; /* background pixel */
|
---|
42 | int line_width; /* line width */
|
---|
43 | int line_style; /* LineSolid, LineOnOffDash, LineDoubleDash */
|
---|
44 | int cap_style; /* CapNotLast, CapButt,
|
---|
45 | CapRound, CapProjecting */
|
---|
46 | int join_style; /* JoinMiter, JoinRound, JoinBevel */
|
---|
47 | int fill_style; /* FillSolid, FillTiled,
|
---|
48 | FillStippled, FillOpaeueStippled */
|
---|
49 | int fill_rule; /* EvenOddRule, WindingRule */
|
---|
50 | int arc_mode; /* ArcChord, ArcPieSlice */
|
---|
51 | Pixmap tile; /* tile pixmap for tiling operations */
|
---|
52 | Pixmap stipple; /* stipple 1 plane pixmap for stipping */
|
---|
53 | int ts_x_origin; /* offset for tile or stipple operations */
|
---|
54 | int ts_y_origin;
|
---|
55 | Font font; /* default text font for text operations */
|
---|
56 | int subwindow_mode; /* ClipByChildren, IncludeInferiors */
|
---|
57 | Bool graphics_exposures; /* boolean, should exposures be generated */
|
---|
58 | int clip_x_origin; /* origin for clipping */
|
---|
59 | int clip_y_origin;
|
---|
60 | Pixmap clip_mask; /* bitmap clipping; other calls for rects */
|
---|
61 | int dash_offset; /* patterned/dashed line information */
|
---|
62 | char dashes; /* If -1, indicates that the extended
|
---|
63 | * information below is available. */
|
---|
64 | int nDashValues;
|
---|
65 | char dashValues[12];
|
---|
66 | } XGCValuesEx;
|
---|
67 |
|
---|
68 | static int tkpWinRopModes[] =
|
---|
69 | {
|
---|
70 | R2_BLACK, /* GXclear */
|
---|
71 | R2_MASKPEN, /* GXand */
|
---|
72 | R2_MASKPENNOT, /* GXandReverse */
|
---|
73 | R2_COPYPEN, /* GXcopy */
|
---|
74 | R2_MASKNOTPEN, /* GXandInverted */
|
---|
75 | R2_NOT, /* GXnoop */
|
---|
76 | R2_XORPEN, /* GXxor */
|
---|
77 | R2_MERGEPEN, /* GXor */
|
---|
78 | R2_NOTMERGEPEN, /* GXnor */
|
---|
79 | R2_NOTXORPEN, /* GXequiv */
|
---|
80 | R2_NOT, /* GXinvert */
|
---|
81 | R2_MERGEPENNOT, /* GXorReverse */
|
---|
82 | R2_NOTCOPYPEN, /* GXcopyInverted */
|
---|
83 | R2_MERGENOTPEN, /* GXorInverted */
|
---|
84 | R2_NOTMASKPEN, /* GXnand */
|
---|
85 | R2_WHITE /* GXset */
|
---|
86 | };
|
---|
87 |
|
---|
88 | #define MASKPAT 0x00E20746 /* dest = (src & pat) | (!src & dst) */
|
---|
89 | #define COPYFG 0x00CA0749 /* dest = (pat & src) | (!pat & dst) */
|
---|
90 | #define COPYBG 0x00AC0744 /* dest = (!pat & src) | (pat & dst) */
|
---|
91 | /*
|
---|
92 | * Translation table between X gc functions and Win32 BitBlt op modes. Some
|
---|
93 | * of the operations defined in X don't have names, so we have to construct
|
---|
94 | * new opcodes for those functions. This is arcane and probably not all that
|
---|
95 | * useful, but at least it's accurate.
|
---|
96 | */
|
---|
97 |
|
---|
98 | #define NOTSRCAND (DWORD)0x00220326 /* dest = (NOT src) AND dest */
|
---|
99 | #define NOTSRCINVERT (DWORD)0x00990066 /* dest = (NOT src) XOR dest */
|
---|
100 | #define SRCORREVERSE (DWORD)0x00DD0228 /* dest = src OR (NOT dest) */
|
---|
101 | #define SRCNAND (DWORD)0x007700E6 /* dest = NOT (src AND dest) */
|
---|
102 |
|
---|
103 | static int bltModes[] =
|
---|
104 | {
|
---|
105 | BLACKNESS, /* GXclear */
|
---|
106 | SRCAND, /* GXand */
|
---|
107 | SRCERASE, /* GXandReverse */
|
---|
108 | SRCCOPY, /* GXcopy */
|
---|
109 | NOTSRCAND, /* GXandInverted */
|
---|
110 | PATCOPY, /* GXnoop */
|
---|
111 | SRCINVERT, /* GXxor */
|
---|
112 | SRCPAINT, /* GXor */
|
---|
113 | NOTSRCERASE, /* GXnor */
|
---|
114 | NOTSRCINVERT, /* GXequiv */
|
---|
115 | DSTINVERT, /* GXinvert */
|
---|
116 | SRCORREVERSE, /* GXorReverse */
|
---|
117 | NOTSRCCOPY, /* GXcopyInverted */
|
---|
118 | MERGEPAINT, /* GXorInverted */
|
---|
119 | SRCNAND, /* GXnand */
|
---|
120 | WHITENESS /* GXset */
|
---|
121 | };
|
---|
122 |
|
---|
123 | #if (TCL_VERSION_NUMBER < _VERSION(8,1,0))
|
---|
124 | typedef void *Tcl_Encoding; /* Make up dummy type for encoding. */
|
---|
125 | #else
|
---|
126 | static Tcl_Encoding systemEncoding = NULL;
|
---|
127 | #endif
|
---|
128 |
|
---|
129 | HPALETTE
|
---|
130 | Blt_GetSystemPalette(void)
|
---|
131 | {
|
---|
132 | HDC hDC;
|
---|
133 | HPALETTE hPalette;
|
---|
134 | DWORD flags;
|
---|
135 |
|
---|
136 | hPalette = NULL;
|
---|
137 | hDC = GetDC(NULL); /* Get the desktop device context */
|
---|
138 | flags = GetDeviceCaps(hDC, RASTERCAPS);
|
---|
139 | if (flags & RC_PALETTE) {
|
---|
140 | LOGPALETTE *palettePtr;
|
---|
141 |
|
---|
142 | palettePtr = (LOGPALETTE *)
|
---|
143 | GlobalAlloc(GPTR, sizeof(LOGPALETTE) + 256 * sizeof(PALETTEENTRY));
|
---|
144 | palettePtr->palVersion = 0x300;
|
---|
145 | palettePtr->palNumEntries = 256;
|
---|
146 | GetSystemPaletteEntries(hDC, 0, 256, palettePtr->palPalEntry);
|
---|
147 | hPalette = CreatePalette(palettePtr);
|
---|
148 | GlobalFree(palettePtr);
|
---|
149 | }
|
---|
150 | ReleaseDC(NULL, hDC);
|
---|
151 | return hPalette;
|
---|
152 | }
|
---|
153 |
|
---|
154 | /*
|
---|
155 | *----------------------------------------------------------------------
|
---|
156 | *
|
---|
157 | * CreateRotatedFont --
|
---|
158 | *
|
---|
159 | * Creates a rotated copy of the given font. This only works
|
---|
160 | * for TrueType fonts.
|
---|
161 | *
|
---|
162 | * Results:
|
---|
163 | * Returns the newly create font or NULL if the font could not
|
---|
164 | * be created.
|
---|
165 | *
|
---|
166 | *----------------------------------------------------------------------
|
---|
167 | */
|
---|
168 | HFONT
|
---|
169 | CreateRotatedFont(
|
---|
170 | unsigned long fontId, /* Font identifier (actually a Tk_Font) */
|
---|
171 | double theta)
|
---|
172 | { /* Number of degrees to rotate font */
|
---|
173 | TkFontAttributes *faPtr; /* Set of attributes to match. */
|
---|
174 | TkFont *fontPtr;
|
---|
175 | HFONT hFont;
|
---|
176 | LOGFONTW lf;
|
---|
177 |
|
---|
178 | fontPtr = (TkFont *) fontId;
|
---|
179 | faPtr = &fontPtr->fa;
|
---|
180 | ZeroMemory(&lf, sizeof(LOGFONT));
|
---|
181 | lf.lfHeight = -faPtr->pointsize;
|
---|
182 | if (lf.lfHeight < 0) {
|
---|
183 | HDC dc;
|
---|
184 |
|
---|
185 | dc = GetDC(NULL);
|
---|
186 | lf.lfHeight = -MulDiv(faPtr->pointsize,
|
---|
187 | GetDeviceCaps(dc, LOGPIXELSY), 72);
|
---|
188 | ReleaseDC(NULL, dc);
|
---|
189 | }
|
---|
190 | lf.lfWidth = 0;
|
---|
191 | lf.lfEscapement = lf.lfOrientation = ROUND(theta * 10.0);
|
---|
192 | #define TK_FW_NORMAL 0
|
---|
193 | lf.lfWeight = (faPtr->weight == TK_FW_NORMAL) ? FW_NORMAL : FW_BOLD;
|
---|
194 | lf.lfItalic = faPtr->slant;
|
---|
195 | lf.lfUnderline = faPtr->underline;
|
---|
196 | lf.lfStrikeOut = faPtr->overstrike;
|
---|
197 | lf.lfCharSet = DEFAULT_CHARSET;
|
---|
198 | lf.lfOutPrecision = OUT_TT_ONLY_PRECIS;
|
---|
199 | lf.lfClipPrecision = CLIP_DEFAULT_PRECIS;
|
---|
200 | lf.lfQuality = DEFAULT_QUALITY;
|
---|
201 | lf.lfPitchAndFamily = DEFAULT_PITCH | FF_DONTCARE;
|
---|
202 |
|
---|
203 | hFont = NULL;
|
---|
204 | if (faPtr->family == NULL) {
|
---|
205 | lf.lfFaceName[0] = '\0';
|
---|
206 | } else {
|
---|
207 | #if (TCL_VERSION_NUMBER >= _VERSION(8,1,0))
|
---|
208 | Tcl_DString dString;
|
---|
209 |
|
---|
210 | Tcl_UtfToExternalDString(systemEncoding, faPtr->family, -1, &dString);
|
---|
211 |
|
---|
212 | if (Blt_GetPlatformId() == VER_PLATFORM_WIN32_NT) {
|
---|
213 | Tcl_UniChar *src, *dst;
|
---|
214 |
|
---|
215 | /*
|
---|
216 | * We can only store up to LF_FACESIZE wide characters
|
---|
217 | */
|
---|
218 | if (Tcl_DStringLength(&dString) >= (LF_FACESIZE * sizeof(WCHAR))) {
|
---|
219 | Tcl_DStringSetLength(&dString, LF_FACESIZE);
|
---|
220 | }
|
---|
221 | src = (Tcl_UniChar *)Tcl_DStringValue(&dString);
|
---|
222 | dst = (Tcl_UniChar *)lf.lfFaceName;
|
---|
223 | while (*src != '\0') {
|
---|
224 | *dst++ = *src++;
|
---|
225 | }
|
---|
226 | *dst = '\0';
|
---|
227 | hFont = CreateFontIndirectW((LOGFONTW *)&lf);
|
---|
228 | } else {
|
---|
229 | /*
|
---|
230 | * We can only store up to LF_FACESIZE characters
|
---|
231 | */
|
---|
232 | if (Tcl_DStringLength(&dString) >= LF_FACESIZE) {
|
---|
233 | Tcl_DStringSetLength(&dString, LF_FACESIZE);
|
---|
234 | }
|
---|
235 | strcpy((char *)lf.lfFaceName, Tcl_DStringValue(&dString));
|
---|
236 | hFont = CreateFontIndirectA((LOGFONTA *)&lf);
|
---|
237 | }
|
---|
238 | Tcl_DStringFree(&dString);
|
---|
239 | #else
|
---|
240 | strncpy((char *)lf.lfFaceName, faPtr->family, LF_FACESIZE - 1);
|
---|
241 | lf.lfFaceName[LF_FACESIZE] = '\0';
|
---|
242 | #endif /* TCL_VERSION_NUMBER >= 8.1.0 */
|
---|
243 | }
|
---|
244 |
|
---|
245 | if (hFont == NULL) {
|
---|
246 | #if WINDEBUG
|
---|
247 | PurifyPrintf("can't create font: %s\n", Blt_LastError());
|
---|
248 | #endif
|
---|
249 | } else {
|
---|
250 | HFONT oldFont;
|
---|
251 | TEXTMETRIC tm;
|
---|
252 | HDC hRefDC;
|
---|
253 | int result;
|
---|
254 |
|
---|
255 | /* Check if the rotated font is really a TrueType font. */
|
---|
256 |
|
---|
257 | hRefDC = GetDC(NULL); /* Get the desktop device context */
|
---|
258 | oldFont = SelectFont(hRefDC, hFont);
|
---|
259 | result = ((GetTextMetrics(hRefDC, &tm)) &&
|
---|
260 | (tm.tmPitchAndFamily & TMPF_TRUETYPE));
|
---|
261 | SelectFont(hRefDC, oldFont);
|
---|
262 | ReleaseDC(NULL, hRefDC);
|
---|
263 | if (!result) {
|
---|
264 | #if WINDEBUG
|
---|
265 | PurifyPrintf("not a true type font\n");
|
---|
266 | #endif
|
---|
267 | DeleteFont(hFont);
|
---|
268 | return NULL;
|
---|
269 | }
|
---|
270 | }
|
---|
271 | return hFont;
|
---|
272 | }
|
---|
273 |
|
---|
274 | /*
|
---|
275 | *----------------------------------------------------------------------
|
---|
276 | *
|
---|
277 | * Blt_GetBitmapData --
|
---|
278 | *
|
---|
279 | * Returns the DIB bits from a bitmap.
|
---|
280 | *
|
---|
281 | * Results:
|
---|
282 | * Returns a byte array of bitmap data or NULL if an error
|
---|
283 | * occurred. The parameter pitchPtr returns the number
|
---|
284 | * of bytes per row.
|
---|
285 | *
|
---|
286 | *----------------------------------------------------------------------
|
---|
287 | */
|
---|
288 | unsigned char *
|
---|
289 | Blt_GetBitmapData(
|
---|
290 | Display *display, /* Display of bitmap */
|
---|
291 | Pixmap bitmap, /* Bitmap to query */
|
---|
292 | int width, /* Width of bitmap */
|
---|
293 | int height, /* Height of bitmap */
|
---|
294 | int *pitchPtr) /* (out) Number of bytes per row */
|
---|
295 | {
|
---|
296 | TkWinDCState state;
|
---|
297 | HDC dc;
|
---|
298 | int result;
|
---|
299 | unsigned char *bits;
|
---|
300 | unsigned int size;
|
---|
301 | HBITMAP hBitmap;
|
---|
302 | BITMAPINFOHEADER *bmiPtr;
|
---|
303 | HANDLE hMem, hMem2;
|
---|
304 | int bytesPerRow, imageSize;
|
---|
305 |
|
---|
306 | size = sizeof(BITMAPINFOHEADER) + 2 * sizeof(RGBQUAD);
|
---|
307 | hMem = GlobalAlloc(GHND, size);
|
---|
308 | bmiPtr = (BITMAPINFOHEADER *)GlobalLock(hMem);
|
---|
309 | bmiPtr->biSize = sizeof(BITMAPINFOHEADER);
|
---|
310 | bmiPtr->biPlanes = 1;
|
---|
311 | bmiPtr->biBitCount = 1;
|
---|
312 | bmiPtr->biCompression = BI_RGB;
|
---|
313 | bmiPtr->biWidth = width;
|
---|
314 | bmiPtr->biHeight = height;
|
---|
315 |
|
---|
316 | hBitmap = ((TkWinDrawable *)bitmap)->bitmap.handle;
|
---|
317 | dc = TkWinGetDrawableDC(display, bitmap, &state);
|
---|
318 | result = GetDIBits(dc, hBitmap, 0, height, (LPVOID)NULL,
|
---|
319 | (BITMAPINFO *)bmiPtr, DIB_RGB_COLORS);
|
---|
320 | TkWinReleaseDrawableDC(bitmap, dc, &state);
|
---|
321 | if (!result) {
|
---|
322 | GlobalUnlock(hMem);
|
---|
323 | GlobalFree(hMem);
|
---|
324 | return NULL;
|
---|
325 | }
|
---|
326 | imageSize = bmiPtr->biSizeImage;
|
---|
327 | GlobalUnlock(hMem);
|
---|
328 | bytesPerRow = ((width + 31) & ~31) / 8;
|
---|
329 | if (imageSize == 0) {
|
---|
330 | imageSize = bytesPerRow * height;
|
---|
331 | }
|
---|
332 | hMem2 = GlobalReAlloc(hMem, size + imageSize, 0);
|
---|
333 | if (hMem2 == NULL) {
|
---|
334 | GlobalFree(hMem);
|
---|
335 | return NULL;
|
---|
336 | }
|
---|
337 | hMem = hMem2;
|
---|
338 | bmiPtr = (LPBITMAPINFOHEADER)GlobalLock(hMem);
|
---|
339 | dc = TkWinGetDrawableDC(display, bitmap, &state);
|
---|
340 | result = GetDIBits(dc, hBitmap, 0, height, (unsigned char *)bmiPtr + size,
|
---|
341 | (BITMAPINFO *)bmiPtr, DIB_RGB_COLORS);
|
---|
342 | TkWinReleaseDrawableDC(bitmap, dc, &state);
|
---|
343 | bits = NULL;
|
---|
344 | if (!result) {
|
---|
345 | OutputDebugString("GetDIBits failed\n");
|
---|
346 | } else {
|
---|
347 | bits = Blt_Malloc(imageSize);
|
---|
348 | if (bits != NULL) {
|
---|
349 | memcpy (bits, (unsigned char *)bmiPtr + size, imageSize);
|
---|
350 | }
|
---|
351 | }
|
---|
352 | *pitchPtr = bytesPerRow;
|
---|
353 | GlobalUnlock(hMem);
|
---|
354 | GlobalFree(hMem);
|
---|
355 | return bits;
|
---|
356 | }
|
---|
357 |
|
---|
358 | /*
|
---|
359 | *----------------------------------------------------------------------
|
---|
360 | *
|
---|
361 | * XFree --
|
---|
362 | *
|
---|
363 | *----------------------------------------------------------------------
|
---|
364 | */
|
---|
365 | void
|
---|
366 | Blt_EmulateXFree(void *ptr)
|
---|
367 | {
|
---|
368 | Blt_Free(ptr);
|
---|
369 | }
|
---|
370 |
|
---|
371 | /*
|
---|
372 | *----------------------------------------------------------------------
|
---|
373 | *
|
---|
374 | * XMaxRequestSize --
|
---|
375 | *
|
---|
376 | *----------------------------------------------------------------------
|
---|
377 | */
|
---|
378 | long
|
---|
379 | Blt_EmulateXMaxRequestSize(Display *display)
|
---|
380 | {
|
---|
381 | return (SHRT_MAX / 4);
|
---|
382 | }
|
---|
383 |
|
---|
384 | /*
|
---|
385 | *----------------------------------------------------------------------
|
---|
386 | *
|
---|
387 | * XLowerWindow --
|
---|
388 | *
|
---|
389 | *----------------------------------------------------------------------
|
---|
390 | */
|
---|
391 | void
|
---|
392 | Blt_EmulateXLowerWindow(
|
---|
393 | Display *display,
|
---|
394 | Window window)
|
---|
395 | {
|
---|
396 | HWND hWnd;
|
---|
397 |
|
---|
398 | hWnd = Tk_GetHWND(window);
|
---|
399 | display->request++;
|
---|
400 | SetWindowPos(hWnd, HWND_BOTTOM, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE);
|
---|
401 | }
|
---|
402 |
|
---|
403 | /*
|
---|
404 | *----------------------------------------------------------------------
|
---|
405 | *
|
---|
406 | * XRaiseWindow --
|
---|
407 | *
|
---|
408 | *----------------------------------------------------------------------
|
---|
409 | */
|
---|
410 | void
|
---|
411 | Blt_EmulateXRaiseWindow(
|
---|
412 | Display *display,
|
---|
413 | Window window)
|
---|
414 | {
|
---|
415 | HWND hWnd;
|
---|
416 |
|
---|
417 | hWnd = Tk_GetHWND(window);
|
---|
418 | display->request++;
|
---|
419 | SetWindowPos(hWnd, HWND_TOP, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE);
|
---|
420 | }
|
---|
421 |
|
---|
422 | /*
|
---|
423 | *----------------------------------------------------------------------
|
---|
424 | *
|
---|
425 | * XUnmapWindow --
|
---|
426 | *
|
---|
427 | *----------------------------------------------------------------------
|
---|
428 | */
|
---|
429 | void
|
---|
430 | Blt_EmulateXUnmapWindow(
|
---|
431 | Display *display,
|
---|
432 | Window window)
|
---|
433 | {
|
---|
434 | HWND hWnd;
|
---|
435 |
|
---|
436 | hWnd = Tk_GetHWND(window);
|
---|
437 | display->request++;
|
---|
438 | ShowWindow(hWnd, SW_HIDE);
|
---|
439 | /* SetWindowPos(hWnd, HWND_TOP, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE); */
|
---|
440 | }
|
---|
441 |
|
---|
442 | /*
|
---|
443 | *----------------------------------------------------------------------
|
---|
444 | *
|
---|
445 | * XWarpPointer --
|
---|
446 | *
|
---|
447 | * If destWindow is None, moves the pointer by the offsets (destX,
|
---|
448 | * destY) relative to the current position of the pointer.
|
---|
449 | * If destWindow is a window, moves the pointer to the offsets
|
---|
450 | * (destX, destY) relative to the origin of destWindow. However,
|
---|
451 | * if srcWindow is a window, the move only takes place if the window
|
---|
452 | * srcWindow contains the pointer and if the specified rectangle of
|
---|
453 | * srcWindow contains the pointer.
|
---|
454 | *
|
---|
455 | * The srcX and srcY coordinates are relative to the origin of
|
---|
456 | * srcWindow. If srcHeight is zero, it is replaced with the current
|
---|
457 | * height of srcWindow minus srcY. If srcWidth is zero, it is
|
---|
458 | * replaced with the current width of srcWindow minus srcX.
|
---|
459 | *
|
---|
460 | *----------------------------------------------------------------------
|
---|
461 | */
|
---|
462 | void
|
---|
463 | Blt_EmulateXWarpPointer(
|
---|
464 | Display *display,
|
---|
465 | Window srcWindow,
|
---|
466 | Window destWindow,
|
---|
467 | int srcX,
|
---|
468 | int srcY,
|
---|
469 | unsigned int srcWidth,
|
---|
470 | unsigned int srcHeight,
|
---|
471 | int destX,
|
---|
472 | int destY)
|
---|
473 | {
|
---|
474 | HWND hWnd;
|
---|
475 | POINT point;
|
---|
476 |
|
---|
477 | hWnd = Tk_GetHWND(destWindow);
|
---|
478 | point.x = destX, point.y = destY;
|
---|
479 | if (ClientToScreen(hWnd, &point)) {
|
---|
480 | SetCursorPos(point.x, point.y);
|
---|
481 | }
|
---|
482 | }
|
---|
483 |
|
---|
484 | #ifdef notdef
|
---|
485 | static Blt_HashTable gcTable;
|
---|
486 | static int gcInitialized = FALSE;
|
---|
487 | #endif
|
---|
488 |
|
---|
489 | typedef struct {
|
---|
490 | HDC dc;
|
---|
491 | int count;
|
---|
492 | COLORREF color;
|
---|
493 | int offset, nBits;
|
---|
494 | } DashInfo;
|
---|
495 |
|
---|
496 | void
|
---|
497 | Blt_SetDashes(Display *display, GC gc, Blt_Dashes *dashesPtr)
|
---|
498 | {
|
---|
499 | XGCValuesEx *gcPtr = (XGCValuesEx *)gc;
|
---|
500 |
|
---|
501 | /* This must be used only with a privately created GC */
|
---|
502 | assert((int)gcPtr->dashes == -1);
|
---|
503 | gcPtr->nDashValues = strlen(dashesPtr->values);
|
---|
504 | gcPtr->dash_offset = dashesPtr->offset;
|
---|
505 | strcpy(gcPtr->dashValues, dashesPtr->values);
|
---|
506 | }
|
---|
507 |
|
---|
508 | static int
|
---|
509 | GetDashInfo(
|
---|
510 | HDC dc,
|
---|
511 | GC gc,
|
---|
512 | DashInfo *infoPtr)
|
---|
513 | {
|
---|
514 | int dashOffset, dashValue;
|
---|
515 |
|
---|
516 | dashValue = 0;
|
---|
517 | dashOffset = gc->dash_offset;
|
---|
518 | if ((int)gc->dashes == -1) {
|
---|
519 | XGCValuesEx *gcPtr = (XGCValuesEx *)gc;
|
---|
520 |
|
---|
521 | if (gcPtr->nDashValues == 1) {
|
---|
522 | dashValue = gcPtr->dashValues[0];
|
---|
523 | }
|
---|
524 | } else if (gc->dashes > 0) {
|
---|
525 | dashValue = (int)gc->dashes;
|
---|
526 | }
|
---|
527 | if (dashValue == 0) {
|
---|
528 | return FALSE;
|
---|
529 | }
|
---|
530 | infoPtr->dc = dc;
|
---|
531 | infoPtr->nBits = dashValue;
|
---|
532 | infoPtr->offset = dashOffset;
|
---|
533 | infoPtr->count = 0;
|
---|
534 | infoPtr->color = gc->foreground;
|
---|
535 | return TRUE;
|
---|
536 | }
|
---|
537 |
|
---|
538 | void
|
---|
539 | Blt_SetROP2(HDC dc, int function)
|
---|
540 | {
|
---|
541 | SetROP2(dc, tkpWinRopModes[function]);
|
---|
542 | }
|
---|
543 |
|
---|
544 | static XGCValuesEx *
|
---|
545 | CreateGC()
|
---|
546 | {
|
---|
547 | XGCValuesEx *gcPtr;
|
---|
548 |
|
---|
549 | gcPtr = Blt_Malloc(sizeof(XGCValuesEx));
|
---|
550 | if (gcPtr == NULL) {
|
---|
551 | return NULL;
|
---|
552 | }
|
---|
553 | gcPtr->arc_mode = ArcPieSlice;
|
---|
554 | gcPtr->background = 0xffffff;
|
---|
555 | gcPtr->cap_style = CapNotLast;
|
---|
556 | gcPtr->clip_mask = None;
|
---|
557 | gcPtr->clip_x_origin = gcPtr->clip_y_origin = 0;
|
---|
558 | gcPtr->dash_offset = 0;
|
---|
559 | gcPtr->fill_rule = WindingRule;
|
---|
560 | gcPtr->fill_style = FillSolid;
|
---|
561 | gcPtr->font = None;
|
---|
562 | gcPtr->foreground = 0;
|
---|
563 | gcPtr->function = GXcopy;
|
---|
564 | gcPtr->graphics_exposures = True;
|
---|
565 | gcPtr->join_style = JoinMiter;
|
---|
566 | gcPtr->line_style = LineSolid;
|
---|
567 | gcPtr->line_width = 0;
|
---|
568 | gcPtr->plane_mask = ~0;
|
---|
569 | gcPtr->stipple = None;
|
---|
570 | gcPtr->subwindow_mode = ClipByChildren;
|
---|
571 | gcPtr->tile = None;
|
---|
572 | gcPtr->ts_x_origin = gcPtr->ts_y_origin = 0;
|
---|
573 |
|
---|
574 | gcPtr->dashes = -1; /* Mark that this an extended GC */
|
---|
575 | gcPtr->nDashValues = 0;
|
---|
576 |
|
---|
577 | return gcPtr;
|
---|
578 | }
|
---|
579 |
|
---|
580 | /*
|
---|
581 | *----------------------------------------------------------------------
|
---|
582 | *
|
---|
583 | * Blt_EmulateXCreateGC --
|
---|
584 | *
|
---|
585 | * Allocate a new extended GC, and initialize the specified fields.
|
---|
586 | *
|
---|
587 | * Results:
|
---|
588 | * Returns a newly allocated GC.
|
---|
589 | *
|
---|
590 | * Side effects:
|
---|
591 | * None.
|
---|
592 | *
|
---|
593 | *----------------------------------------------------------------------
|
---|
594 | */
|
---|
595 | GC
|
---|
596 | Blt_EmulateXCreateGC(
|
---|
597 | Display *display,
|
---|
598 | Drawable drawable,
|
---|
599 | unsigned long mask,
|
---|
600 | XGCValues *srcPtr)
|
---|
601 | {
|
---|
602 | XGCValuesEx *destPtr;
|
---|
603 |
|
---|
604 | destPtr = CreateGC();
|
---|
605 | if (destPtr == NULL) {
|
---|
606 | return None;
|
---|
607 | }
|
---|
608 | if (mask & GCFunction) {
|
---|
609 | destPtr->function = srcPtr->function;
|
---|
610 | }
|
---|
611 | if (mask & GCPlaneMask) {
|
---|
612 | destPtr->plane_mask = srcPtr->plane_mask;
|
---|
613 | }
|
---|
614 | if (mask & GCForeground) {
|
---|
615 | destPtr->foreground = srcPtr->foreground;
|
---|
616 | }
|
---|
617 | if (mask & GCBackground) {
|
---|
618 | destPtr->background = srcPtr->background;
|
---|
619 | }
|
---|
620 | if (mask & GCLineWidth) {
|
---|
621 | destPtr->line_width = srcPtr->line_width;
|
---|
622 | }
|
---|
623 | if (mask & GCLineStyle) {
|
---|
624 | destPtr->line_style = srcPtr->line_style;
|
---|
625 | }
|
---|
626 | if (mask & GCCapStyle) {
|
---|
627 | destPtr->cap_style = srcPtr->cap_style;
|
---|
628 | }
|
---|
629 | if (mask & GCJoinStyle) {
|
---|
630 | destPtr->join_style = srcPtr->join_style;
|
---|
631 | }
|
---|
632 | if (mask & GCFillStyle) {
|
---|
633 | destPtr->fill_style = srcPtr->fill_style;
|
---|
634 | }
|
---|
635 | if (mask & GCFillRule) {
|
---|
636 | destPtr->fill_rule = srcPtr->fill_rule;
|
---|
637 | }
|
---|
638 | if (mask & GCArcMode) {
|
---|
639 | destPtr->arc_mode = srcPtr->arc_mode;
|
---|
640 | }
|
---|
641 | if (mask & GCTile) {
|
---|
642 | destPtr->tile = srcPtr->tile;
|
---|
643 | }
|
---|
644 | if (mask & GCStipple) {
|
---|
645 | destPtr->stipple = srcPtr->stipple;
|
---|
646 | }
|
---|
647 | if (mask & GCTileStipXOrigin) {
|
---|
648 | destPtr->ts_x_origin = srcPtr->ts_x_origin;
|
---|
649 | }
|
---|
650 | if (mask & GCTileStipXOrigin) {
|
---|
651 | destPtr->ts_y_origin = srcPtr->ts_y_origin;
|
---|
652 | }
|
---|
653 | if (mask & GCFont) {
|
---|
654 | destPtr->font = srcPtr->font;
|
---|
655 | }
|
---|
656 | if (mask & GCSubwindowMode) {
|
---|
657 | destPtr->subwindow_mode = srcPtr->subwindow_mode;
|
---|
658 | }
|
---|
659 | if (mask & GCGraphicsExposures) {
|
---|
660 | destPtr->graphics_exposures = srcPtr->graphics_exposures;
|
---|
661 | }
|
---|
662 | if (mask & GCClipXOrigin) {
|
---|
663 | destPtr->clip_x_origin = srcPtr->clip_x_origin;
|
---|
664 | }
|
---|
665 | if (mask & GCClipYOrigin) {
|
---|
666 | destPtr->clip_y_origin = srcPtr->clip_y_origin;
|
---|
667 | }
|
---|
668 | if (mask & GCDashOffset) {
|
---|
669 | destPtr->dash_offset = srcPtr->dash_offset;
|
---|
670 | }
|
---|
671 | if (mask & GCDashList) {
|
---|
672 | destPtr->dashes = srcPtr->dashes;
|
---|
673 | }
|
---|
674 | if (mask & GCClipMask) {
|
---|
675 | struct ClipMask {
|
---|
676 | int type; /* TKP_CLIP_PIXMAP or TKP_CLIP_REGION */
|
---|
677 | Pixmap pixmap;
|
---|
678 | } *clipPtr;
|
---|
679 |
|
---|
680 | clipPtr = Blt_Malloc(sizeof(struct ClipMask));
|
---|
681 | #define TKP_CLIP_PIXMAP 0
|
---|
682 | clipPtr->type = TKP_CLIP_PIXMAP;
|
---|
683 | clipPtr->pixmap = srcPtr->clip_mask;
|
---|
684 | destPtr->clip_mask = (Pixmap) clipPtr;
|
---|
685 | }
|
---|
686 | return (GC)destPtr;
|
---|
687 | }
|
---|
688 |
|
---|
689 | /*
|
---|
690 | *----------------------------------------------------------------------
|
---|
691 | *
|
---|
692 | * Blt_GCToPen --
|
---|
693 | *
|
---|
694 | * Set up the graphics port from the given GC.
|
---|
695 | *
|
---|
696 | * Geometric and cosmetic pens available under both 95 and NT.
|
---|
697 | * Geometric pens differ from cosmetic pens in that they can
|
---|
698 | * 1. Draw in world units (can have thick lines: line width > 1).
|
---|
699 | * 2. Under NT, allow arbitrary line style.
|
---|
700 | * 3. Can have caps and join (needed for thick lines).
|
---|
701 | * 4. Draw very, very slowly.
|
---|
702 | *
|
---|
703 | * Cosmetic pens are single line width only.
|
---|
704 | *
|
---|
705 | * 95 98 NT
|
---|
706 | * PS_SOLID c,g c,g c,g
|
---|
707 | * PS_DASH c,g c,g c,g
|
---|
708 | * PS_DOT c c c,g
|
---|
709 | * PS_DASHDOT c - c,g
|
---|
710 | * PS_DASHDOTDOT c - c,g
|
---|
711 | * PS_USERSTYLE - - c,g
|
---|
712 | * PS_ALTERNATE - - c
|
---|
713 | *
|
---|
714 | * Geometric only for 95/98
|
---|
715 | *
|
---|
716 | * PS_ENDCAP_ROUND
|
---|
717 | * PS_ENDCAP_SQUARE
|
---|
718 | * PS_ENDCAP_FLAT
|
---|
719 | * PS_JOIN_BEVEL
|
---|
720 | * PS_JOIN_ROUND
|
---|
721 | * PS_JOIN_MITER
|
---|
722 | *
|
---|
723 | * Results:
|
---|
724 | * None.
|
---|
725 | *
|
---|
726 | * Side effects:
|
---|
727 | * The current port is adjusted.
|
---|
728 | *
|
---|
729 | *----------------------------------------------------------------------
|
---|
730 | */
|
---|
731 | HPEN
|
---|
732 | Blt_GCToPen(HDC dc, GC gc)
|
---|
733 | {
|
---|
734 | DWORD lineAttrs, lineStyle;
|
---|
735 | DWORD dashArr[12];
|
---|
736 | DWORD *dashPtr;
|
---|
737 | int nValues, lineWidth;
|
---|
738 | LOGBRUSH lBrush;
|
---|
739 | HPEN pen;
|
---|
740 |
|
---|
741 | nValues = 0;
|
---|
742 | lineWidth = (gc->line_width < 1) ? 1 : gc->line_width;
|
---|
743 | if ((gc->line_style == LineOnOffDash) ||
|
---|
744 | (gc->line_style == LineDoubleDash)) {
|
---|
745 | XGCValuesEx *gcPtr = (XGCValuesEx *)gc;
|
---|
746 |
|
---|
747 | if ((int)gc->dashes == -1) {
|
---|
748 | register int i;
|
---|
749 |
|
---|
750 | nValues = strlen(gcPtr->dashValues);
|
---|
751 | for (i = 0; i < nValues; i++) {
|
---|
752 | dashArr[i] = (DWORD)gcPtr->dashValues[i];
|
---|
753 | }
|
---|
754 | if (nValues == 1) {
|
---|
755 | dashArr[1] = dashArr[0];
|
---|
756 | nValues = 2;
|
---|
757 | }
|
---|
758 | } else {
|
---|
759 | dashArr[1] = dashArr[0] = (DWORD) gc->dashes;
|
---|
760 | nValues = 2;
|
---|
761 | gc->dashes = -1;
|
---|
762 | }
|
---|
763 | }
|
---|
764 |
|
---|
765 | switch (nValues) {
|
---|
766 | case 0:
|
---|
767 | lineStyle = PS_SOLID;
|
---|
768 | break;
|
---|
769 | case 3:
|
---|
770 | lineStyle = PS_DASHDOT;
|
---|
771 | break;
|
---|
772 | case 4:
|
---|
773 | lineStyle = PS_DASHDOTDOT;
|
---|
774 | break;
|
---|
775 | case 2:
|
---|
776 | default:
|
---|
777 | /* PS_DASH style dash length is too long. */
|
---|
778 | lineStyle = PS_DOT;
|
---|
779 | break;
|
---|
780 | }
|
---|
781 |
|
---|
782 | lBrush.lbStyle = BS_SOLID;
|
---|
783 | lBrush.lbColor = gc->foreground;
|
---|
784 | lBrush.lbHatch = 0; /* Value is ignored when style is BS_SOLID. */
|
---|
785 |
|
---|
786 | lineAttrs = 0;
|
---|
787 | switch (gc->cap_style) {
|
---|
788 | case CapNotLast:
|
---|
789 | case CapButt:
|
---|
790 | lineAttrs |= PS_ENDCAP_FLAT;
|
---|
791 | break;
|
---|
792 | case CapRound:
|
---|
793 | lineAttrs |= PS_ENDCAP_ROUND;
|
---|
794 | break;
|
---|
795 | default:
|
---|
796 | lineAttrs |= PS_ENDCAP_SQUARE;
|
---|
797 | break;
|
---|
798 | }
|
---|
799 | switch (gc->join_style) {
|
---|
800 | case JoinMiter:
|
---|
801 | lineAttrs |= PS_JOIN_MITER;
|
---|
802 | break;
|
---|
803 | case JoinBevel:
|
---|
804 | lineAttrs |= PS_JOIN_BEVEL;
|
---|
805 | break;
|
---|
806 | case JoinRound:
|
---|
807 | default:
|
---|
808 | lineAttrs |= PS_JOIN_ROUND;
|
---|
809 | break;
|
---|
810 | }
|
---|
811 | SetBkMode(dc, TRANSPARENT);
|
---|
812 |
|
---|
813 | if (Blt_GetPlatformId() == VER_PLATFORM_WIN32_NT) {
|
---|
814 | /* Windows NT/2000/XP. */
|
---|
815 | if (nValues > 0) {
|
---|
816 | lineStyle = PS_USERSTYLE;
|
---|
817 | dashPtr = dashArr;
|
---|
818 | } else {
|
---|
819 | dashPtr = NULL;
|
---|
820 | }
|
---|
821 | if (lineWidth > 1) {
|
---|
822 | /* Limit the use of geometric pens to thick lines. */
|
---|
823 | pen = ExtCreatePen(PS_GEOMETRIC | lineAttrs | lineStyle, lineWidth,
|
---|
824 | &lBrush, nValues, dashPtr);
|
---|
825 | } else {
|
---|
826 | /* Cosmetic pens are much faster. */
|
---|
827 | pen = ExtCreatePen(PS_COSMETIC | lineAttrs | lineStyle, 1, &lBrush,
|
---|
828 | nValues, dashPtr);
|
---|
829 | }
|
---|
830 | } else {
|
---|
831 | /* Windows 95/98. */
|
---|
832 | if ((lineStyle == PS_SOLID) && (lineWidth > 1)) {
|
---|
833 | /* Use geometric pens with solid, thick lines only. */
|
---|
834 | pen = ExtCreatePen(PS_GEOMETRIC | lineAttrs | lineStyle, lineWidth,
|
---|
835 | &lBrush, 0, NULL);
|
---|
836 | } else {
|
---|
837 | /* Otherwise sacrifice thick lines for dashes. */
|
---|
838 | pen = ExtCreatePen(PS_COSMETIC | lineStyle, 1, &lBrush, 0, NULL);
|
---|
839 | }
|
---|
840 | }
|
---|
841 | assert(pen != NULL);
|
---|
842 | return pen;
|
---|
843 | }
|
---|
844 |
|
---|
845 | /*
|
---|
846 | *----------------------------------------------------------------------
|
---|
847 | *
|
---|
848 | * XDrawRectangles --
|
---|
849 | *
|
---|
850 | * Draws the outlines of the specified rectangles as if a
|
---|
851 | * five-point PolyLine protocol request were specified for each
|
---|
852 | * rectangle:
|
---|
853 | *
|
---|
854 | * [x,y] [x+width,y] [x+width,y+height] [x,y+height]
|
---|
855 | * [x,y]
|
---|
856 | *
|
---|
857 | * For the specified rectangles, these functions do not draw a
|
---|
858 | * pixel more than once. XDrawRectangles draws the rectangles in
|
---|
859 | * the order listed in the array. If rectangles intersect, the
|
---|
860 | * intersecting pixels are drawn multiple times. Draws a
|
---|
861 | * rectangle.
|
---|
862 | *
|
---|
863 | * Results:
|
---|
864 | * None.
|
---|
865 | *
|
---|
866 | * Side effects:
|
---|
867 | * Draws rectangles on the specified drawable.
|
---|
868 | *
|
---|
869 | *----------------------------------------------------------------------
|
---|
870 | */
|
---|
871 | void
|
---|
872 | Blt_EmulateXDrawRectangles(
|
---|
873 | Display *display,
|
---|
874 | Drawable drawable,
|
---|
875 | GC gc,
|
---|
876 | XRectangle *rectArr,
|
---|
877 | int nRects)
|
---|
878 | {
|
---|
879 | HPEN pen, oldPen;
|
---|
880 | TkWinDCState state;
|
---|
881 | HBRUSH brush, oldBrush;
|
---|
882 | HDC dc;
|
---|
883 | register XRectangle *rectPtr;
|
---|
884 | register int i;
|
---|
885 |
|
---|
886 | if (drawable == None) {
|
---|
887 | return;
|
---|
888 | }
|
---|
889 | dc = TkWinGetDrawableDC(display, drawable, &state);
|
---|
890 | pen = Blt_GCToPen(dc, gc);
|
---|
891 | brush = GetStockObject(NULL_BRUSH);
|
---|
892 | oldPen = SelectPen(dc, pen);
|
---|
893 | oldBrush = SelectBrush(dc, brush);
|
---|
894 | SetROP2(dc, tkpWinRopModes[gc->function]);
|
---|
895 | rectPtr = rectArr;
|
---|
896 | for (i = 0; i < nRects; i++, rectPtr++) {
|
---|
897 | Rectangle(dc, (int)rectPtr->x, (int)rectPtr->y,
|
---|
898 | (int)(rectPtr->x + rectPtr->width + 1),
|
---|
899 | (int)(rectPtr->y + rectPtr->height + 1));
|
---|
900 | }
|
---|
901 | DeletePen(SelectPen(dc, oldPen));
|
---|
902 | DeleteBrush(SelectBrush(dc, oldBrush));
|
---|
903 | TkWinReleaseDrawableDC(drawable, dc, &state);
|
---|
904 | }
|
---|
905 |
|
---|
906 | #ifdef notdef
|
---|
907 | /*
|
---|
908 | * Implements the "pixeling" of small arcs, because GDI-performance
|
---|
909 | * for this is awful
|
---|
910 | * was made especially for BLT, graph4 demo now runs 4x faster
|
---|
911 | *
|
---|
912 | */
|
---|
913 | /* O-outer , I-inner, B-both */
|
---|
914 | #define NEITHER_ 0
|
---|
915 | #define OUTLINE 1
|
---|
916 | #define FILL 2
|
---|
917 | #define BOTH (OUTLINE|FILL)
|
---|
918 | #define MINIARCS 5
|
---|
919 | static int arcus0[1] =
|
---|
920 | {
|
---|
921 | BOTH
|
---|
922 | };
|
---|
923 | static int arcus1[4] =
|
---|
924 | {
|
---|
925 | BOTH, BOTH,
|
---|
926 | BOTH, BOTH
|
---|
927 | };
|
---|
928 |
|
---|
929 | static int arcus2[9] =
|
---|
930 | {
|
---|
931 | NEITHER, OUTLINE, NEITHER,
|
---|
932 | OUTLINE, FILL, OUTLINE,
|
---|
933 | NEITHER, OUTLINE, NEITHER
|
---|
934 | };
|
---|
935 |
|
---|
936 | static int arcus3[16] =
|
---|
937 | {
|
---|
938 | NEITHER, OUTLINE, OUTLINE, NEITHER,
|
---|
939 | OUTLINE, FILL, FILL, OUTLINE,
|
---|
940 | OUTLINE, FILL, FILL, OUTLINE,
|
---|
941 | NEITHER, OUTLINE, OUTLINE, NEITHER
|
---|
942 | };
|
---|
943 |
|
---|
944 | static int arcus4[25] =
|
---|
945 | {
|
---|
946 | NEITHER, OUTLINE, OUTLINE, OUTLINE, NEITHER,
|
---|
947 | OUTLINE, FILL, FILL, FILL, OUTLINE,
|
---|
948 | OUTLINE, FILL, FILL, FILL, OUTLINE,
|
---|
949 | OUTLINE, FILL, FILL, FILL, OUTLINE,
|
---|
950 | NEITHER, OUTLINE, OUTLINE, OUTLINE, NEITHER
|
---|
951 | };
|
---|
952 |
|
---|
953 | static int *arcis[MINIARCS] =
|
---|
954 | {
|
---|
955 | arcus0, arcus1, arcus2, arcus3, arcus4
|
---|
956 | };
|
---|
957 |
|
---|
958 | static void
|
---|
959 | DrawMiniArc(
|
---|
960 | HDC dc,
|
---|
961 | int width,
|
---|
962 | int x,
|
---|
963 | int y,
|
---|
964 | int mask,
|
---|
965 | COLORREF inner,
|
---|
966 | COLORREF outer)
|
---|
967 | {
|
---|
968 | int *arc;
|
---|
969 | int i, j;
|
---|
970 |
|
---|
971 | if (width > MINIARCS) {
|
---|
972 | return;
|
---|
973 | }
|
---|
974 | arc = arcis[width];
|
---|
975 | for (i = 0; i <= width; i++) {
|
---|
976 | for (j = 0; j <= width; j++) {
|
---|
977 | bit = (mask & *arc);
|
---|
978 | if (bit & OUTLINE) {
|
---|
979 | SetPixelV(dc, x + i, y + j, outer);
|
---|
980 | } else if (bit & FILL) {
|
---|
981 | SetPixelV(dc, x + i, y + j, inner);
|
---|
982 | }
|
---|
983 | arc++;
|
---|
984 | }
|
---|
985 | }
|
---|
986 | }
|
---|
987 |
|
---|
988 | #endif
|
---|
989 |
|
---|
990 | /*
|
---|
991 | *----------------------------------------------------------------------
|
---|
992 | *
|
---|
993 | * DrawArc --
|
---|
994 | *
|
---|
995 | * This procedure handles the rendering of drawn or filled
|
---|
996 | * arcs and chords.
|
---|
997 | *
|
---|
998 | * Results:
|
---|
999 | * None.
|
---|
1000 | *
|
---|
1001 | * Side effects:
|
---|
1002 | * Renders the requested arcs.
|
---|
1003 | *
|
---|
1004 | *----------------------------------------------------------------------
|
---|
1005 | */
|
---|
1006 | static void
|
---|
1007 | DrawArc(
|
---|
1008 | HDC dc,
|
---|
1009 | int arcMode, /* Mode: either ArcChord or ArcPieSlice */
|
---|
1010 | XArc *arcPtr,
|
---|
1011 | HPEN pen,
|
---|
1012 | HBRUSH brush)
|
---|
1013 | {
|
---|
1014 | int start, extent, clockwise;
|
---|
1015 | int xstart, ystart, xend, yend;
|
---|
1016 | double radian_start, radian_end, xr, yr;
|
---|
1017 | double dx, dy;
|
---|
1018 |
|
---|
1019 | if ((arcPtr->angle1 == 0) && (arcPtr->angle2 == 23040)) {
|
---|
1020 | /* Handle special case of circle or ellipse */
|
---|
1021 | Ellipse(dc, arcPtr->x, arcPtr->y, arcPtr->x + arcPtr->width + 1,
|
---|
1022 | arcPtr->y + arcPtr->height + 1);
|
---|
1023 | return;
|
---|
1024 | }
|
---|
1025 | start = arcPtr->angle1, extent = arcPtr->angle2;
|
---|
1026 | clockwise = (extent < 0); /* Non-zero if clockwise */
|
---|
1027 |
|
---|
1028 | /*
|
---|
1029 | * Compute the absolute starting and ending angles in normalized radians.
|
---|
1030 | * Swap the start and end if drawing clockwise.
|
---|
1031 | */
|
---|
1032 | start = start % (64 * 360);
|
---|
1033 | if (start < 0) {
|
---|
1034 | start += (64 * 360);
|
---|
1035 | }
|
---|
1036 | extent = (start + extent) % (64 * 360);
|
---|
1037 | if (extent < 0) {
|
---|
1038 | extent += (64 * 360);
|
---|
1039 | }
|
---|
1040 | if (clockwise) {
|
---|
1041 | int tmp = start;
|
---|
1042 | start = extent;
|
---|
1043 | extent = tmp;
|
---|
1044 | }
|
---|
1045 | #define XAngleToRadians(a) ((double)(a) / 64 * M_PI / 180);
|
---|
1046 | radian_start = XAngleToRadians(start);
|
---|
1047 | radian_end = XAngleToRadians(extent);
|
---|
1048 |
|
---|
1049 | /*
|
---|
1050 | * Now compute points on the radial lines that define the starting and
|
---|
1051 | * ending angles. Be sure to take into account that the y-coordinate
|
---|
1052 | * system is inverted.
|
---|
1053 | */
|
---|
1054 | dx = arcPtr->width * 0.5;
|
---|
1055 | dy = arcPtr->height * 0.5;
|
---|
1056 |
|
---|
1057 | xr = arcPtr->x + dx;
|
---|
1058 | yr = arcPtr->y + dy;
|
---|
1059 | xstart = (int)((xr + cos(radian_start) * dx) + 0.5);
|
---|
1060 | ystart = (int)((yr + sin(-radian_start) * dy) + 0.5);
|
---|
1061 | xend = (int)((xr + cos(radian_end) * dx) + 0.5);
|
---|
1062 | yend = (int)((yr + sin(-radian_end) * dy) + 0.5);
|
---|
1063 |
|
---|
1064 | /*
|
---|
1065 | * Now draw a filled or open figure. Note that we have to
|
---|
1066 | * increase the size of the bounding box by one to account for the
|
---|
1067 | * difference in pixel definitions between X and Windows.
|
---|
1068 | */
|
---|
1069 |
|
---|
1070 | if (brush == 0) {
|
---|
1071 | /*
|
---|
1072 | * Note that this call will leave a gap of one pixel at the
|
---|
1073 | * end of the arc for thin arcs. We can't use ArcTo because
|
---|
1074 | * it's only supported under Windows NT.
|
---|
1075 | */
|
---|
1076 | Arc(dc, arcPtr->x, arcPtr->y, arcPtr->x + arcPtr->width + 1,
|
---|
1077 | arcPtr->y + arcPtr->height + 1, xstart, ystart, xend, yend);
|
---|
1078 | /* FIXME: */
|
---|
1079 | } else {
|
---|
1080 | if (arcMode == ArcChord) {
|
---|
1081 | Chord(dc, arcPtr->x, arcPtr->y, arcPtr->x + arcPtr->width + 1,
|
---|
1082 | arcPtr->y + arcPtr->height + 1, xstart, ystart, xend, yend);
|
---|
1083 | } else if (arcMode == ArcPieSlice) {
|
---|
1084 | Pie(dc, arcPtr->x, arcPtr->y, arcPtr->x + arcPtr->width + 1,
|
---|
1085 | arcPtr->y + arcPtr->height + 1, xstart, ystart, xend, yend);
|
---|
1086 | }
|
---|
1087 | }
|
---|
1088 | }
|
---|
1089 |
|
---|
1090 | /*
|
---|
1091 | *----------------------------------------------------------------------
|
---|
1092 | *
|
---|
1093 | * XDrawArcs --
|
---|
1094 | *
|
---|
1095 | * Draws multiple circular or elliptical arcs. Each arc is
|
---|
1096 | * specified by a rectangle and two angles. The center of the
|
---|
1097 | * circle or ellipse is the center of the rect- angle, and the
|
---|
1098 | * major and minor axes are specified by the width and height.
|
---|
1099 | * Positive angles indicate counterclock- wise motion, and
|
---|
1100 | * negative angles indicate clockwise motion. If the magnitude
|
---|
1101 | * of angle2 is greater than 360 degrees, XDrawArcs truncates it
|
---|
1102 | * to 360 degrees.
|
---|
1103 | *
|
---|
1104 | * Results:
|
---|
1105 | * None.
|
---|
1106 | *
|
---|
1107 | * Side effects:
|
---|
1108 | * Draws an arc for each array element on the specified drawable.
|
---|
1109 | *
|
---|
1110 | *----------------------------------------------------------------------
|
---|
1111 | */
|
---|
1112 | void
|
---|
1113 | Blt_EmulateXDrawArcs(
|
---|
1114 | Display *display,
|
---|
1115 | Drawable drawable,
|
---|
1116 | GC gc,
|
---|
1117 | XArc *arcArr,
|
---|
1118 | int nArcs)
|
---|
1119 | {
|
---|
1120 | HPEN pen, oldPen;
|
---|
1121 | HBRUSH brush, oldBrush;
|
---|
1122 | HDC dc;
|
---|
1123 | TkWinDCState state;
|
---|
1124 | register XArc *arcPtr, *endPtr;
|
---|
1125 |
|
---|
1126 | display->request++;
|
---|
1127 | if (drawable == None) {
|
---|
1128 | return;
|
---|
1129 | }
|
---|
1130 | dc = TkWinGetDrawableDC(display, drawable, &state);
|
---|
1131 | SetROP2(dc, tkpWinRopModes[gc->function]);
|
---|
1132 | pen = Blt_GCToPen(dc, gc);
|
---|
1133 | oldPen = SelectPen(dc, pen);
|
---|
1134 | brush = GetStockBrush(NULL_BRUSH);
|
---|
1135 | oldBrush = SelectBrush(dc, brush);
|
---|
1136 | endPtr = arcArr + nArcs;
|
---|
1137 | for (arcPtr = arcArr; arcPtr < endPtr; arcPtr++) {
|
---|
1138 | DrawArc(dc, gc->arc_mode, arcPtr, pen, 0);
|
---|
1139 | }
|
---|
1140 | DeleteBrush(SelectBrush(dc, oldBrush));
|
---|
1141 | DeletePen(SelectPen(dc, oldPen));
|
---|
1142 | TkWinReleaseDrawableDC(drawable, dc, &state);
|
---|
1143 | }
|
---|
1144 |
|
---|
1145 | /*
|
---|
1146 | *----------------------------------------------------------------------
|
---|
1147 | *
|
---|
1148 | * XFillArcs --
|
---|
1149 | *
|
---|
1150 | * Draw a filled arc.
|
---|
1151 | *
|
---|
1152 | * Results:
|
---|
1153 | * None.
|
---|
1154 | *
|
---|
1155 | * Side effects:
|
---|
1156 | * Draws a filled arc for each array element on the specified drawable.
|
---|
1157 | *
|
---|
1158 | *----------------------------------------------------------------------
|
---|
1159 | */
|
---|
1160 | void
|
---|
1161 | Blt_EmulateXFillArcs(
|
---|
1162 | Display *display,
|
---|
1163 | Drawable drawable,
|
---|
1164 | GC gc,
|
---|
1165 | XArc *arcArr,
|
---|
1166 | int nArcs)
|
---|
1167 | {
|
---|
1168 | HBRUSH brush, oldBrush;
|
---|
1169 | HPEN pen, oldPen;
|
---|
1170 | HDC dc;
|
---|
1171 | register XArc *arcPtr, *endPtr;
|
---|
1172 | TkWinDCState state;
|
---|
1173 |
|
---|
1174 | display->request++;
|
---|
1175 | if (drawable == None) {
|
---|
1176 | return;
|
---|
1177 | }
|
---|
1178 | dc = TkWinGetDrawableDC(display, drawable, &state);
|
---|
1179 | SetROP2(dc, tkpWinRopModes[gc->function]);
|
---|
1180 | pen = Blt_GCToPen(dc, gc);
|
---|
1181 | oldPen = SelectPen(dc, pen);
|
---|
1182 | brush = CreateSolidBrush(gc->foreground);
|
---|
1183 | oldBrush = SelectBrush(dc, brush);
|
---|
1184 | endPtr = arcArr + nArcs;
|
---|
1185 | for (arcPtr = arcArr; arcPtr < endPtr; arcPtr++) {
|
---|
1186 | DrawArc(dc, gc->arc_mode, arcPtr, pen, brush);
|
---|
1187 | }
|
---|
1188 | DeleteBrush(SelectBrush(dc, oldBrush));
|
---|
1189 | DeletePen(SelectPen(dc, oldPen));
|
---|
1190 | TkWinReleaseDrawableDC(drawable, dc, &state);
|
---|
1191 | }
|
---|
1192 | |
---|
1193 |
|
---|
1194 | /*
|
---|
1195 | *----------------------------------------------------------------------
|
---|
1196 | *
|
---|
1197 | * XDrawLines --
|
---|
1198 | *
|
---|
1199 | * Draw connected lines.
|
---|
1200 | *
|
---|
1201 | * Results:
|
---|
1202 | * None.
|
---|
1203 | *
|
---|
1204 | * Side effects:
|
---|
1205 | * Renders a series of connected lines.
|
---|
1206 | *
|
---|
1207 | *----------------------------------------------------------------------
|
---|
1208 | */
|
---|
1209 |
|
---|
1210 | static void CALLBACK
|
---|
1211 | DrawDot(
|
---|
1212 | int x, int y, /* Coordinates of point */
|
---|
1213 | LPARAM clientData)
|
---|
1214 | { /* Line information */
|
---|
1215 | DashInfo *infoPtr = (DashInfo *) clientData;
|
---|
1216 | int count;
|
---|
1217 |
|
---|
1218 | infoPtr->count++;
|
---|
1219 | count = (infoPtr->count + infoPtr->offset) / infoPtr->nBits;
|
---|
1220 | if (count & 0x1) {
|
---|
1221 | SetPixelV(infoPtr->dc, x, y, infoPtr->color);
|
---|
1222 | }
|
---|
1223 | }
|
---|
1224 |
|
---|
1225 |
|
---|
1226 | void
|
---|
1227 | Blt_EmulateXDrawLine(
|
---|
1228 | Display *display,
|
---|
1229 | Drawable drawable,
|
---|
1230 | GC gc,
|
---|
1231 | int x1, int y1,
|
---|
1232 | int x2, int y2)
|
---|
1233 | {
|
---|
1234 | TkWinDCState state;
|
---|
1235 | HDC dc;
|
---|
1236 |
|
---|
1237 | if (drawable == None) {
|
---|
1238 | return;
|
---|
1239 | }
|
---|
1240 | dc = TkWinGetDrawableDC(display, drawable, &state);
|
---|
1241 | SetROP2(dc, tkpWinRopModes[gc->function]);
|
---|
1242 | if (gc->line_style != LineSolid) {
|
---|
1243 | /* Handle dotted lines specially */
|
---|
1244 | DashInfo info;
|
---|
1245 |
|
---|
1246 | if (!GetDashInfo(dc, gc, &info)) {
|
---|
1247 | goto solidLine;
|
---|
1248 | }
|
---|
1249 | LineDDA(x1, y1, x2, y2, DrawDot, (LPARAM)&info);
|
---|
1250 | } else {
|
---|
1251 | HPEN pen, oldPen;
|
---|
1252 | HBRUSH brush, oldBrush;
|
---|
1253 |
|
---|
1254 | solidLine:
|
---|
1255 | pen = Blt_GCToPen(dc, gc);
|
---|
1256 | oldPen = SelectPen(dc, pen);
|
---|
1257 | brush = CreateSolidBrush(gc->foreground);
|
---|
1258 | oldBrush = SelectBrush(dc, brush);
|
---|
1259 | MoveToEx(dc, x1, y1, (LPPOINT)NULL);
|
---|
1260 | LineTo(dc, x2, y2);
|
---|
1261 | DeletePen(SelectPen(dc, oldPen));
|
---|
1262 | DeleteBrush(SelectBrush(dc, oldBrush));
|
---|
1263 | }
|
---|
1264 | TkWinReleaseDrawableDC(drawable, dc, &state);
|
---|
1265 | }
|
---|
1266 |
|
---|
1267 | static void
|
---|
1268 | DrawLine(
|
---|
1269 | Display *display,
|
---|
1270 | Drawable drawable,
|
---|
1271 | GC gc,
|
---|
1272 | POINT *points,
|
---|
1273 | int nPoints)
|
---|
1274 | {
|
---|
1275 | TkWinDCState state;
|
---|
1276 | HDC dc;
|
---|
1277 | register int i, n;
|
---|
1278 | int start, extra, size;
|
---|
1279 | HPEN pen, oldPen;
|
---|
1280 | HBRUSH brush, oldBrush;
|
---|
1281 |
|
---|
1282 | if (drawable == None) {
|
---|
1283 | return;
|
---|
1284 | }
|
---|
1285 | dc = TkWinGetDrawableDC(display, drawable, &state);
|
---|
1286 | pen = Blt_GCToPen(dc, gc);
|
---|
1287 | oldPen = SelectPen(dc, pen);
|
---|
1288 | brush = CreateSolidBrush(gc->foreground);
|
---|
1289 | oldBrush = SelectBrush(dc, brush);
|
---|
1290 | SetROP2(dc, tkpWinRopModes[gc->function]);
|
---|
1291 |
|
---|
1292 | start = extra = 0;
|
---|
1293 | /*
|
---|
1294 | * Depending if the line is wide (> 1 pixel), arbitrarily break
|
---|
1295 | * the line in sections of 100 points. This bit of weirdness has
|
---|
1296 | * to do with wide geometric pens. The longer the polyline, the
|
---|
1297 | * slower it draws. The trade off is that we lose dash and
|
---|
1298 | * cap uniformity for unbearably slow polyline draws.
|
---|
1299 | */
|
---|
1300 | if (gc->line_width > 1) {
|
---|
1301 | size = 100;
|
---|
1302 | } else {
|
---|
1303 | size = nPoints;
|
---|
1304 | }
|
---|
1305 | for (i = nPoints; i > 0; i -= size) {
|
---|
1306 | n = MIN(i, size);
|
---|
1307 | Polyline(dc, points + start, n + extra);
|
---|
1308 | start += (n - 1);
|
---|
1309 | extra = 1;
|
---|
1310 | }
|
---|
1311 | DeletePen(SelectPen(dc, oldPen));
|
---|
1312 | DeleteBrush(SelectBrush(dc, oldBrush));
|
---|
1313 | TkWinReleaseDrawableDC(drawable, dc, &state);
|
---|
1314 | }
|
---|
1315 |
|
---|
1316 | void
|
---|
1317 | Blt_EmulateXDrawLines(
|
---|
1318 | Display *display,
|
---|
1319 | Drawable drawable,
|
---|
1320 | GC gc,
|
---|
1321 | XPoint *pointArr,
|
---|
1322 | int nPoints,
|
---|
1323 | int mode)
|
---|
1324 | {
|
---|
1325 | if (drawable == None) {
|
---|
1326 | return;
|
---|
1327 | }
|
---|
1328 | if (gc->line_style != LineSolid) { /* Handle dotted lines specially */
|
---|
1329 | DashInfo info;
|
---|
1330 | TkWinDCState state;
|
---|
1331 | HDC dc;
|
---|
1332 | int result;
|
---|
1333 |
|
---|
1334 | dc = TkWinGetDrawableDC(display, drawable, &state);
|
---|
1335 | SetROP2(dc, tkpWinRopModes[gc->function]);
|
---|
1336 | result = GetDashInfo(dc, gc, &info);
|
---|
1337 | if (result) {
|
---|
1338 | register XPoint *p1, *p2;
|
---|
1339 | register int i;
|
---|
1340 |
|
---|
1341 | p1 = pointArr;
|
---|
1342 | p2 = p1 + 1;
|
---|
1343 | for (i = 1; i < nPoints; i++, p1++, p2++) {
|
---|
1344 | LineDDA(p1->x, p1->y, p2->x, p2->y, DrawDot, (LPARAM)&info);
|
---|
1345 | }
|
---|
1346 | result = TCL_OK;
|
---|
1347 | }
|
---|
1348 | TkWinReleaseDrawableDC(drawable, dc, &state);
|
---|
1349 | if (result) {
|
---|
1350 | return;
|
---|
1351 | }
|
---|
1352 | } else {
|
---|
1353 | POINT *points, *destPtr;
|
---|
1354 | XPoint *srcPtr, *endPtr;
|
---|
1355 |
|
---|
1356 | points = Blt_Malloc(sizeof(POINT) * nPoints);
|
---|
1357 | if (points == NULL) {
|
---|
1358 | return;
|
---|
1359 | }
|
---|
1360 | endPtr = pointArr + nPoints;
|
---|
1361 | if (mode == CoordModeOrigin) {
|
---|
1362 | destPtr = points;
|
---|
1363 | for (srcPtr = pointArr; srcPtr < endPtr; srcPtr++) {
|
---|
1364 | destPtr->x = (int)srcPtr->x;
|
---|
1365 | destPtr->y = (int)srcPtr->y;
|
---|
1366 | destPtr++;
|
---|
1367 | }
|
---|
1368 | } else {
|
---|
1369 | POINT *lastPtr;
|
---|
1370 |
|
---|
1371 | srcPtr = pointArr;
|
---|
1372 | destPtr = points;
|
---|
1373 | destPtr->x = (int)srcPtr->x;
|
---|
1374 | destPtr->y = (int)srcPtr->y;
|
---|
1375 | lastPtr = destPtr;
|
---|
1376 | srcPtr++, destPtr++;
|
---|
1377 | for (/*empty*/; srcPtr < endPtr; srcPtr++) {
|
---|
1378 | destPtr->x = lastPtr->x + (int)srcPtr->x;
|
---|
1379 | destPtr->y = lastPtr->y + (int)srcPtr->y;
|
---|
1380 | lastPtr = destPtr;
|
---|
1381 | destPtr++;
|
---|
1382 | }
|
---|
1383 | }
|
---|
1384 | DrawLine(display, drawable, gc, points, nPoints);
|
---|
1385 | Blt_Free(points);
|
---|
1386 | }
|
---|
1387 | }
|
---|
1388 |
|
---|
1389 |
|
---|
1390 |
|
---|
1391 | /*
|
---|
1392 | *----------------------------------------------------------------------
|
---|
1393 | *
|
---|
1394 | * Blt_EmultateXDrawSegments --
|
---|
1395 | *
|
---|
1396 | * Draws multiple, unconnected lines. For each segment, draws a
|
---|
1397 | * line between (x1, y1) and (x2, y2). It draws the lines in the
|
---|
1398 | * order listed in the array of XSegment structures and does not
|
---|
1399 | * perform joining at coincident endpoints. For any given line,
|
---|
1400 | * does not draw a pixel more than once. If lines intersect, the
|
---|
1401 | * intersecting pixels are drawn multiple times.
|
---|
1402 | *
|
---|
1403 | * Results:
|
---|
1404 | * None.
|
---|
1405 | *
|
---|
1406 | * Side effects:
|
---|
1407 | * Draws unconnected line segments on the specified drawable.
|
---|
1408 | *
|
---|
1409 | *----------------------------------------------------------------------
|
---|
1410 | */
|
---|
1411 | void
|
---|
1412 | Blt_EmulateXDrawSegments(
|
---|
1413 | Display *display,
|
---|
1414 | Drawable drawable,
|
---|
1415 | GC gc,
|
---|
1416 | XSegment *segArr,
|
---|
1417 | int nSegments)
|
---|
1418 | {
|
---|
1419 | HDC dc;
|
---|
1420 | register XSegment *segPtr, *endPtr;
|
---|
1421 | TkWinDCState state;
|
---|
1422 |
|
---|
1423 | display->request++;
|
---|
1424 | if (drawable == None) {
|
---|
1425 | return;
|
---|
1426 | }
|
---|
1427 | dc = TkWinGetDrawableDC(display, drawable, &state);
|
---|
1428 | SetROP2(dc, tkpWinRopModes[gc->function]);
|
---|
1429 | if (gc->line_style != LineSolid) {
|
---|
1430 | /* Handle dotted lines specially */
|
---|
1431 | DashInfo info;
|
---|
1432 |
|
---|
1433 | if (!GetDashInfo(dc, gc, &info)) {
|
---|
1434 | goto solidLine;
|
---|
1435 | }
|
---|
1436 | endPtr = segArr + nSegments;
|
---|
1437 | for (segPtr = segArr; segPtr < endPtr; segPtr++) {
|
---|
1438 | info.count = 0; /* Reset dash counter after every segment. */
|
---|
1439 | LineDDA(segPtr->x1, segPtr->y1, segPtr->x2, segPtr->y2, DrawDot,
|
---|
1440 | (LPARAM)&info);
|
---|
1441 | }
|
---|
1442 | } else {
|
---|
1443 | HPEN pen, oldPen;
|
---|
1444 |
|
---|
1445 | solidLine:
|
---|
1446 | pen = Blt_GCToPen(dc, gc);
|
---|
1447 | oldPen = SelectPen(dc, pen);
|
---|
1448 | endPtr = segArr + nSegments;
|
---|
1449 | for (segPtr = segArr; segPtr < endPtr; segPtr++) {
|
---|
1450 | MoveToEx(dc, segPtr->x1, segPtr->y1, (LPPOINT)NULL);
|
---|
1451 | LineTo(dc, segPtr->x2, segPtr->y2);
|
---|
1452 | }
|
---|
1453 | DeletePen(SelectPen(dc, oldPen));
|
---|
1454 | }
|
---|
1455 | TkWinReleaseDrawableDC(drawable, dc, &state);
|
---|
1456 | }
|
---|
1457 |
|
---|
1458 | /*
|
---|
1459 | *----------------------------------------------------------------------
|
---|
1460 | *
|
---|
1461 | * Blt_EmultateXDrawRectangle --
|
---|
1462 | *
|
---|
1463 | * Draws the outlines of the specified rectangle as if a
|
---|
1464 | * five-point PolyLine protocol request were specified for each
|
---|
1465 | * rectangle:
|
---|
1466 | *
|
---|
1467 | * [x,y] [x+width,y] [x+width,y+height] [x,y+height]
|
---|
1468 | * [x,y]
|
---|
1469 | *
|
---|
1470 | * Results:
|
---|
1471 | * None.
|
---|
1472 | *
|
---|
1473 | * Side effects:
|
---|
1474 | * Draws a rectangle on the specified drawable.
|
---|
1475 | *
|
---|
1476 | *----------------------------------------------------------------------
|
---|
1477 | */
|
---|
1478 | void
|
---|
1479 | Blt_EmulateXDrawRectangle(
|
---|
1480 | Display *display,
|
---|
1481 | Drawable drawable,
|
---|
1482 | GC gc,
|
---|
1483 | int x, int y,
|
---|
1484 | unsigned int width,
|
---|
1485 | unsigned int height)
|
---|
1486 | {
|
---|
1487 | TkWinDCState state;
|
---|
1488 | HPEN pen, oldPen;
|
---|
1489 | HBRUSH brush, oldBrush;
|
---|
1490 | HDC dc;
|
---|
1491 |
|
---|
1492 | if (drawable == None) {
|
---|
1493 | return;
|
---|
1494 | }
|
---|
1495 | dc = TkWinGetDrawableDC(display, drawable, &state);
|
---|
1496 | pen = Blt_GCToPen(dc, gc);
|
---|
1497 | brush = GetStockObject(NULL_BRUSH);
|
---|
1498 | oldPen = SelectPen(dc, pen);
|
---|
1499 | oldBrush = SelectBrush(dc, brush);
|
---|
1500 | SetROP2(dc, tkpWinRopModes[gc->function]);
|
---|
1501 | if (gc->line_style != LineSolid) {
|
---|
1502 | /* Handle dotted lines specially */
|
---|
1503 | register int x2, y2;
|
---|
1504 | DashInfo info;
|
---|
1505 |
|
---|
1506 | if (!GetDashInfo(dc, gc, &info)) {
|
---|
1507 | goto solidLine;
|
---|
1508 | }
|
---|
1509 | x2 = x + width;
|
---|
1510 | y2 = y + height;
|
---|
1511 | LineDDA(x, y, x2, y, DrawDot, (LPARAM)&info);
|
---|
1512 | LineDDA(x2, y, x2, y2, DrawDot, (LPARAM)&info);
|
---|
1513 | LineDDA(x2, y2, x, y2, DrawDot, (LPARAM)&info);
|
---|
1514 | LineDDA(x, y2, x, y, DrawDot, (LPARAM)&info);
|
---|
1515 | } else {
|
---|
1516 | solidLine:
|
---|
1517 | Rectangle(dc, x, y, x + width + 1, y + height + 1);
|
---|
1518 | }
|
---|
1519 | DeletePen(SelectPen(dc, oldPen));
|
---|
1520 | DeleteBrush(SelectBrush(dc, oldBrush));
|
---|
1521 | TkWinReleaseDrawableDC(drawable, dc, &state);
|
---|
1522 | }
|
---|
1523 |
|
---|
1524 | /*
|
---|
1525 | *----------------------------------------------------------------------
|
---|
1526 | *
|
---|
1527 | * Blt_EmulateXDrawPoints --
|
---|
1528 | *
|
---|
1529 | * Uses the foreground pixel and function components of the GC to
|
---|
1530 | * draw a multiple points into the specified drawable.
|
---|
1531 | * CoordModeOrigin treats all coordinates as relative to the
|
---|
1532 | * origin, and CoordModePrevious treats all coordinates after
|
---|
1533 | * the first as relative to the previous point.
|
---|
1534 | *
|
---|
1535 | * Results:
|
---|
1536 | * None.
|
---|
1537 | *
|
---|
1538 | * Side effects:
|
---|
1539 | * Draws points on the specified drawable.
|
---|
1540 | *
|
---|
1541 | *----------------------------------------------------------------------
|
---|
1542 | */
|
---|
1543 | void
|
---|
1544 | Blt_EmulateXDrawPoints(
|
---|
1545 | Display *display,
|
---|
1546 | Drawable drawable,
|
---|
1547 | GC gc,
|
---|
1548 | XPoint *pointArr,
|
---|
1549 | int nPoints,
|
---|
1550 | int mode)
|
---|
1551 | { /* Ignored. CoordModeOrigin is assumed. */
|
---|
1552 | HDC dc;
|
---|
1553 | register XPoint *pointPtr, *endPtr;
|
---|
1554 | TkWinDCState state;
|
---|
1555 |
|
---|
1556 | display->request++;
|
---|
1557 | if (drawable == None) {
|
---|
1558 | return;
|
---|
1559 | }
|
---|
1560 | dc = TkWinGetDrawableDC(display, drawable, &state);
|
---|
1561 | SetROP2(dc, tkpWinRopModes[gc->function]);
|
---|
1562 | endPtr = pointArr + nPoints;
|
---|
1563 | for (pointPtr = pointArr; pointPtr < endPtr; pointPtr++) {
|
---|
1564 | SetPixelV(dc, pointPtr->x, pointPtr->y, gc->foreground);
|
---|
1565 | }
|
---|
1566 | TkWinReleaseDrawableDC(drawable, dc, &state);
|
---|
1567 | }
|
---|
1568 |
|
---|
1569 | /*
|
---|
1570 | *----------------------------------------------------------------------
|
---|
1571 | *
|
---|
1572 | * Blt_EmultateXReparentWindow --
|
---|
1573 | *
|
---|
1574 | * If the specified window is mapped, automatically performs an
|
---|
1575 | * UnmapWindow request on it, removes it from its current
|
---|
1576 | * position in the hierarchy, and inserts it as the child of the
|
---|
1577 | * specified parent. The window is placed in the stacking order
|
---|
1578 | * on top with respect to sibling windows.
|
---|
1579 | *
|
---|
1580 | * Note: In WIN32 you can't reparent to/from another application.
|
---|
1581 | *
|
---|
1582 | * Results:
|
---|
1583 | * None.
|
---|
1584 | *
|
---|
1585 | * Side effects:
|
---|
1586 | * Reparents the specified window.
|
---|
1587 | *
|
---|
1588 | *----------------------------------------------------------------------
|
---|
1589 | */
|
---|
1590 | void
|
---|
1591 | Blt_EmulateXReparentWindow(
|
---|
1592 | Display *display,
|
---|
1593 | Window window,
|
---|
1594 | Window parent,
|
---|
1595 | int x,
|
---|
1596 | int y)
|
---|
1597 | {
|
---|
1598 | HWND child, newParent;
|
---|
1599 |
|
---|
1600 | child = Tk_GetHWND(window);
|
---|
1601 | newParent = Tk_GetHWND(parent);
|
---|
1602 | SetParent(child, newParent);
|
---|
1603 | SetWindowLong(child, GWL_STYLE, WS_CHILD | WS_CLIPCHILDREN |
|
---|
1604 | WS_CLIPSIBLINGS);
|
---|
1605 |
|
---|
1606 | XMoveWindow(display, window, x, y);
|
---|
1607 | XRaiseWindow(display, window);
|
---|
1608 | XMapWindow(display, window);
|
---|
1609 | }
|
---|
1610 |
|
---|
1611 | void
|
---|
1612 | Blt_EmulateXSetDashes(
|
---|
1613 | Display *display,
|
---|
1614 | GC gc,
|
---|
1615 | int dashOffset,
|
---|
1616 | _Xconst char *dashList,
|
---|
1617 | int n)
|
---|
1618 | {
|
---|
1619 | gc->dashes = (unsigned char)strlen(dashList);
|
---|
1620 | gc->dash_offset = (int)dashList;
|
---|
1621 | }
|
---|
1622 |
|
---|
1623 | /*
|
---|
1624 | *----------------------------------------------------------------------
|
---|
1625 | *
|
---|
1626 | * Blt_EmultateXDrawString --
|
---|
1627 | *
|
---|
1628 | * Draw a single string in the current font.
|
---|
1629 | *
|
---|
1630 | * Results:
|
---|
1631 | * None.
|
---|
1632 | *
|
---|
1633 | * Side effects:
|
---|
1634 | * Renders the specified string in the drawable.
|
---|
1635 | *
|
---|
1636 | *----------------------------------------------------------------------
|
---|
1637 | */
|
---|
1638 | void
|
---|
1639 | Blt_EmulateXDrawString(
|
---|
1640 | Display *display,
|
---|
1641 | Drawable drawable,
|
---|
1642 | GC gc,
|
---|
1643 | int x,
|
---|
1644 | int y,
|
---|
1645 | _Xconst char *string,
|
---|
1646 | int length)
|
---|
1647 | {
|
---|
1648 | if (drawable == None) {
|
---|
1649 | return;
|
---|
1650 | }
|
---|
1651 | Tk_DrawChars(display, drawable, gc, (Tk_Font)gc->font, string, length,
|
---|
1652 | x, y);
|
---|
1653 | }
|
---|
1654 |
|
---|
1655 | static void
|
---|
1656 | TileArea(destDC, srcDC, tileOriginX, tileOriginY, tileWidth, tileHeight,
|
---|
1657 | x, y, width, height)
|
---|
1658 | HDC destDC, srcDC;
|
---|
1659 | int tileOriginX, tileOriginY, tileWidth, tileHeight;
|
---|
1660 | int x, y, width, height;
|
---|
1661 | {
|
---|
1662 | int destX, destY;
|
---|
1663 | int destWidth, destHeight;
|
---|
1664 | int srcX, srcY;
|
---|
1665 | int xOrigin, yOrigin;
|
---|
1666 | int delta;
|
---|
1667 | int left, top, right, bottom;
|
---|
1668 |
|
---|
1669 | xOrigin = x, yOrigin = y;
|
---|
1670 | if (x < tileOriginX) {
|
---|
1671 | delta = (tileOriginX - x) % tileWidth;
|
---|
1672 | if (delta > 0) {
|
---|
1673 | xOrigin -= (tileWidth - delta);
|
---|
1674 | }
|
---|
1675 | } else if (x > tileOriginX) {
|
---|
1676 | delta = (x - tileOriginX) % tileWidth;
|
---|
1677 | if (delta > 0) {
|
---|
1678 | xOrigin -= delta;
|
---|
1679 | }
|
---|
1680 | }
|
---|
1681 | if (y < tileOriginY) {
|
---|
1682 | delta = (tileOriginY - y) % tileHeight;
|
---|
1683 | if (delta > 0) {
|
---|
1684 | yOrigin -= (tileHeight - delta);
|
---|
1685 | }
|
---|
1686 | } else if (y >= tileOriginY) {
|
---|
1687 | delta = (y - tileOriginY) % tileHeight;
|
---|
1688 | if (delta > 0) {
|
---|
1689 | yOrigin -= delta;
|
---|
1690 | }
|
---|
1691 | }
|
---|
1692 | #ifdef notdef
|
---|
1693 | PurifyPrintf("tile is (%d,%d,%d,%d)\n", tileOriginX, tileOriginY,
|
---|
1694 | tileWidth, tileHeight);
|
---|
1695 | PurifyPrintf("region is (%d,%d,%d,%d)\n", x, y, width, height);
|
---|
1696 | PurifyPrintf("starting at %d,%d\n", xOrigin, yOrigin);
|
---|
1697 | #endif
|
---|
1698 | left = x;
|
---|
1699 | right = x + width;
|
---|
1700 | top = y;
|
---|
1701 | bottom = y + height;
|
---|
1702 | for (y = yOrigin; y < bottom; y += tileHeight) {
|
---|
1703 | srcY = 0;
|
---|
1704 | destY = y;
|
---|
1705 | destHeight = tileHeight;
|
---|
1706 | if (y < top) {
|
---|
1707 | srcY = (top - y);
|
---|
1708 | destHeight = tileHeight - srcY;
|
---|
1709 | destY = top;
|
---|
1710 | }
|
---|
1711 | if ((destY + destHeight) > bottom) {
|
---|
1712 | destHeight = (bottom - destY);
|
---|
1713 | }
|
---|
1714 | for (x = xOrigin; x < right; x += tileWidth) {
|
---|
1715 | srcX = 0;
|
---|
1716 | destX = x;
|
---|
1717 | destWidth = tileWidth;
|
---|
1718 | if (x < left) {
|
---|
1719 | srcX = (left - x);
|
---|
1720 | destWidth = tileWidth - srcX;
|
---|
1721 | destX = left;
|
---|
1722 | }
|
---|
1723 | if ((destX + destWidth) > right) {
|
---|
1724 | destWidth = (right - destX);
|
---|
1725 | }
|
---|
1726 | #ifdef notdef
|
---|
1727 | PurifyPrintf("drawing pattern (%d,%d,%d,%d) at %d,%d\n",
|
---|
1728 | srcX , srcY, destWidth, destHeight, destX, destY);
|
---|
1729 | #endif
|
---|
1730 | BitBlt(destDC, destX, destY, destWidth, destHeight,
|
---|
1731 | srcDC, srcX, srcY, SRCCOPY);
|
---|
1732 | }
|
---|
1733 | }
|
---|
1734 | }
|
---|
1735 |
|
---|
1736 | /*
|
---|
1737 | *----------------------------------------------------------------------
|
---|
1738 | *
|
---|
1739 | * Blt_EmultateXFillRectangles --
|
---|
1740 | *
|
---|
1741 | * Fill multiple rectangular areas in the given drawable.
|
---|
1742 | * Handles tiling.
|
---|
1743 | *
|
---|
1744 | * Results:
|
---|
1745 | * None.
|
---|
1746 | *
|
---|
1747 | * Side effects:
|
---|
1748 | * Draws onto the specified drawable.
|
---|
1749 | *
|
---|
1750 | *----------------------------------------------------------------------
|
---|
1751 | */
|
---|
1752 |
|
---|
1753 | void
|
---|
1754 | Blt_EmulateXFillRectangles(
|
---|
1755 | Display *display,
|
---|
1756 | Drawable drawable,
|
---|
1757 | GC gc,
|
---|
1758 | XRectangle *rectArr,
|
---|
1759 | int nRectangles)
|
---|
1760 | {
|
---|
1761 | BITMAP bm;
|
---|
1762 | HBITMAP oldBitmap, hBitmap;
|
---|
1763 | HBRUSH oldBrush, hFgBrush, hBgBrush, hBrush;
|
---|
1764 | HDC hDC;
|
---|
1765 | HDC memDC;
|
---|
1766 | RECT rect;
|
---|
1767 | TkWinDCState state;
|
---|
1768 | TkWinDrawable *twdPtr;
|
---|
1769 | register XRectangle *rectPtr, *endPtr;
|
---|
1770 |
|
---|
1771 | if (drawable == None) {
|
---|
1772 | return;
|
---|
1773 | }
|
---|
1774 | hDC = TkWinGetDrawableDC(display, drawable, &state);
|
---|
1775 | SetROP2(hDC, tkpWinRopModes[gc->function]);
|
---|
1776 |
|
---|
1777 | switch(gc->fill_style) {
|
---|
1778 | case FillTiled:
|
---|
1779 | if (gc->tile == None) {
|
---|
1780 | goto fillSolid;
|
---|
1781 | }
|
---|
1782 | #ifdef notdef
|
---|
1783 | if ((GetDeviceCaps(hDC, RASTERCAPS) & RC_BITBLT) == 0) {
|
---|
1784 | goto fillSolid;
|
---|
1785 | }
|
---|
1786 | #endif
|
---|
1787 | twdPtr = (TkWinDrawable *)gc->tile;
|
---|
1788 | GetObject(twdPtr->bitmap.handle, sizeof(BITMAP), &bm);
|
---|
1789 | memDC = CreateCompatibleDC(hDC);
|
---|
1790 | oldBitmap = SelectBitmap(memDC, twdPtr->bitmap.handle);
|
---|
1791 | endPtr = rectArr + nRectangles;
|
---|
1792 | for (rectPtr = rectArr; rectPtr < endPtr; rectPtr++) {
|
---|
1793 | TileArea(hDC, memDC, gc->ts_x_origin, gc->ts_y_origin, bm.bmWidth,
|
---|
1794 | bm.bmHeight, (int)rectPtr->x, (int)rectPtr->y,
|
---|
1795 | (int)rectPtr->width, (int)rectPtr->height);
|
---|
1796 | }
|
---|
1797 | SelectBitmap(memDC, oldBitmap);
|
---|
1798 | DeleteDC(memDC);
|
---|
1799 | break;
|
---|
1800 |
|
---|
1801 | case FillOpaqueStippled:
|
---|
1802 | case FillStippled:
|
---|
1803 | if (gc->stipple == None) {
|
---|
1804 | goto fillSolid;
|
---|
1805 | }
|
---|
1806 | twdPtr = (TkWinDrawable *)gc->stipple;
|
---|
1807 | if (twdPtr->type != TWD_BITMAP) {
|
---|
1808 | panic("unexpected drawable type in stipple");
|
---|
1809 | }
|
---|
1810 | hBrush = CreatePatternBrush(twdPtr->bitmap.handle);
|
---|
1811 | SetBrushOrgEx(hDC, gc->ts_x_origin, gc->ts_y_origin, NULL);
|
---|
1812 | oldBrush = SelectBrush(hDC, hBrush);
|
---|
1813 | memDC = CreateCompatibleDC(hDC);
|
---|
1814 |
|
---|
1815 | /*
|
---|
1816 | * For each rectangle, create a drawing surface which is the size of
|
---|
1817 | * the rectangle and fill it with the background color. Then merge the
|
---|
1818 | * result with the stipple pattern.
|
---|
1819 | */
|
---|
1820 | hFgBrush = CreateSolidBrush(gc->foreground);
|
---|
1821 | hBgBrush = CreateSolidBrush(gc->background);
|
---|
1822 | endPtr = rectArr + nRectangles;
|
---|
1823 | for (rectPtr = rectArr; rectPtr < endPtr; rectPtr++) {
|
---|
1824 | hBitmap = CreateCompatibleBitmap(hDC, rectPtr->width,
|
---|
1825 | rectPtr->height);
|
---|
1826 | oldBitmap = SelectObject(memDC, hBitmap);
|
---|
1827 | rect.left = rect.top = 0;
|
---|
1828 | rect.right = rectPtr->width;
|
---|
1829 | rect.bottom = rectPtr->height;
|
---|
1830 | FillRect(memDC, &rect, hFgBrush);
|
---|
1831 | BitBlt(hDC, rectPtr->x, rectPtr->y, rectPtr->width, rectPtr->height,
|
---|
1832 | memDC, 0, 0, COPYBG);
|
---|
1833 | if (gc->fill_style == FillOpaqueStippled) {
|
---|
1834 | FillRect(memDC, &rect, hBgBrush);
|
---|
1835 | BitBlt(hDC, rectPtr->x, rectPtr->y, rectPtr->width,
|
---|
1836 | rectPtr->height, memDC, 0, 0, COPYFG);
|
---|
1837 | }
|
---|
1838 | SelectObject(memDC, oldBitmap);
|
---|
1839 | DeleteObject(hBitmap);
|
---|
1840 | }
|
---|
1841 | DeleteBrush(hFgBrush);
|
---|
1842 | DeleteBrush(hBgBrush);
|
---|
1843 | DeleteDC(memDC);
|
---|
1844 | SelectBrush(hDC, oldBrush);
|
---|
1845 | DeleteBrush(hBrush);
|
---|
1846 | break;
|
---|
1847 |
|
---|
1848 | case FillSolid:
|
---|
1849 | fillSolid:
|
---|
1850 | memDC = CreateCompatibleDC(hDC);
|
---|
1851 | hFgBrush = CreateSolidBrush(gc->foreground);
|
---|
1852 | endPtr = rectArr + nRectangles;
|
---|
1853 | for (rectPtr = rectArr; rectPtr < endPtr; rectPtr++) {
|
---|
1854 | hBitmap = CreateCompatibleBitmap(hDC, rectPtr->width,
|
---|
1855 | rectPtr->height);
|
---|
1856 | oldBitmap = SelectObject(memDC, hBitmap);
|
---|
1857 | rect.left = rect.top = 0;
|
---|
1858 | rect.right = rectPtr->width;
|
---|
1859 | rect.bottom = rectPtr->height;
|
---|
1860 | FillRect(memDC, &rect, hFgBrush);
|
---|
1861 | BitBlt(hDC, rectPtr->x, rectPtr->y, rectPtr->width, rectPtr->height,
|
---|
1862 | memDC, 0, 0, SRCCOPY);
|
---|
1863 | SelectObject(memDC, oldBitmap);
|
---|
1864 | DeleteObject(hBitmap);
|
---|
1865 | }
|
---|
1866 | DeleteBrush(hFgBrush);
|
---|
1867 | DeleteDC(memDC);
|
---|
1868 | break;
|
---|
1869 | }
|
---|
1870 | TkWinReleaseDrawableDC(drawable, hDC, &state);
|
---|
1871 | }
|
---|
1872 |
|
---|
1873 | void
|
---|
1874 | Blt_EmulateXFillRectangle(
|
---|
1875 | Display *display,
|
---|
1876 | Drawable drawable,
|
---|
1877 | GC gc,
|
---|
1878 | int x,
|
---|
1879 | int y,
|
---|
1880 | unsigned int width,
|
---|
1881 | unsigned int height)
|
---|
1882 | {
|
---|
1883 | HDC hDC;
|
---|
1884 | RECT rect;
|
---|
1885 | TkWinDCState state;
|
---|
1886 |
|
---|
1887 | if (drawable == None) {
|
---|
1888 | return;
|
---|
1889 | }
|
---|
1890 | hDC = TkWinGetDrawableDC(display, drawable, &state);
|
---|
1891 | SetROP2(hDC, tkpWinRopModes[gc->function]);
|
---|
1892 | rect.left = rect.top = 0;
|
---|
1893 | rect.right = width;
|
---|
1894 | rect.bottom = height;
|
---|
1895 |
|
---|
1896 | switch(gc->fill_style) {
|
---|
1897 | case FillTiled:
|
---|
1898 | {
|
---|
1899 | TkWinDrawable *twdPtr;
|
---|
1900 | HBITMAP oldBitmap;
|
---|
1901 | HDC memDC;
|
---|
1902 | BITMAP bm;
|
---|
1903 |
|
---|
1904 | if (gc->tile == None) {
|
---|
1905 | goto fillSolid;
|
---|
1906 | }
|
---|
1907 | #ifdef notdef
|
---|
1908 | if ((GetDeviceCaps(hDC, RASTERCAPS) & RC_BITBLT) == 0) {
|
---|
1909 | goto fillSolid;
|
---|
1910 | }
|
---|
1911 | #endif
|
---|
1912 | twdPtr = (TkWinDrawable *)gc->tile;
|
---|
1913 | /* The tiling routine needs to know the size of the bitmap */
|
---|
1914 | GetObject(twdPtr->bitmap.handle, sizeof(BITMAP), &bm);
|
---|
1915 |
|
---|
1916 | memDC = CreateCompatibleDC(hDC);
|
---|
1917 | oldBitmap = SelectBitmap(memDC, twdPtr->bitmap.handle);
|
---|
1918 | TileArea(hDC, memDC, gc->ts_x_origin, gc->ts_y_origin, bm.bmWidth,
|
---|
1919 | bm.bmHeight, x, y, width, height);
|
---|
1920 | SelectBitmap(memDC, oldBitmap);
|
---|
1921 | DeleteDC(memDC);
|
---|
1922 | }
|
---|
1923 | break;
|
---|
1924 |
|
---|
1925 | case FillOpaqueStippled:
|
---|
1926 | case FillStippled:
|
---|
1927 | {
|
---|
1928 | TkWinDrawable *twdPtr;
|
---|
1929 | HBRUSH oldBrush, hBrush;
|
---|
1930 | HBRUSH hBrushFg, hBrushBg;
|
---|
1931 | HBITMAP oldBitmap, hBitmap;
|
---|
1932 | HDC memDC;
|
---|
1933 |
|
---|
1934 | if (gc->stipple == None) {
|
---|
1935 | goto fillSolid;
|
---|
1936 | }
|
---|
1937 | twdPtr = (TkWinDrawable *)gc->stipple;
|
---|
1938 | if (twdPtr->type != TWD_BITMAP) {
|
---|
1939 | panic("unexpected drawable type in stipple");
|
---|
1940 | }
|
---|
1941 | hBrush = CreatePatternBrush(twdPtr->bitmap.handle);
|
---|
1942 | SetBrushOrgEx(hDC, gc->ts_x_origin, gc->ts_y_origin, NULL);
|
---|
1943 | oldBrush = SelectBrush(hDC, hBrush);
|
---|
1944 | memDC = CreateCompatibleDC(hDC);
|
---|
1945 |
|
---|
1946 | hBrushFg = CreateSolidBrush(gc->foreground);
|
---|
1947 | hBrushBg = CreateSolidBrush(gc->background);
|
---|
1948 | hBitmap = CreateCompatibleBitmap(hDC, width, height);
|
---|
1949 | oldBitmap = SelectObject(memDC, hBitmap);
|
---|
1950 | FillRect(memDC, &rect, hBrushFg);
|
---|
1951 | SetBkMode(hDC, TRANSPARENT);
|
---|
1952 | BitBlt(hDC, x, y, width, height, memDC, 0, 0, COPYFG);
|
---|
1953 | if (gc->fill_style == FillOpaqueStippled) {
|
---|
1954 | FillRect(memDC, &rect, hBrushBg);
|
---|
1955 | BitBlt(hDC, x, y, width, height, memDC, 0, 0, COPYBG);
|
---|
1956 | }
|
---|
1957 | SelectBrush(hDC, oldBrush);
|
---|
1958 | SelectBitmap(memDC, oldBitmap);
|
---|
1959 | DeleteBrush(hBrushFg);
|
---|
1960 | DeleteBrush(hBrushBg);
|
---|
1961 | DeleteBrush(hBrush);
|
---|
1962 | DeleteBitmap(hBitmap);
|
---|
1963 | DeleteDC(memDC);
|
---|
1964 | }
|
---|
1965 | break;
|
---|
1966 |
|
---|
1967 | case FillSolid:
|
---|
1968 | {
|
---|
1969 | HBRUSH hBrush;
|
---|
1970 | HBITMAP oldBitmap, hBitmap;
|
---|
1971 | HDC memDC;
|
---|
1972 |
|
---|
1973 | fillSolid:
|
---|
1974 | /* TkWinFillRect(hDC, x, y, width, height, gc->foreground); */
|
---|
1975 | memDC = CreateCompatibleDC(hDC);
|
---|
1976 | hBrush = CreateSolidBrush(gc->foreground);
|
---|
1977 | hBitmap = CreateCompatibleBitmap(hDC, width, height);
|
---|
1978 | oldBitmap = SelectBitmap(memDC, hBitmap);
|
---|
1979 | rect.left = rect.top = 0;
|
---|
1980 | rect.right = width;
|
---|
1981 | rect.bottom = height;
|
---|
1982 | FillRect(memDC, &rect, hBrush);
|
---|
1983 | BitBlt(hDC, x, y, width, height, memDC, 0, 0, SRCCOPY);
|
---|
1984 | SelectObject(memDC, oldBitmap);
|
---|
1985 | DeleteBitmap(hBitmap);
|
---|
1986 | DeleteBrush(hBrush);
|
---|
1987 | DeleteDC(memDC);
|
---|
1988 | }
|
---|
1989 | break;
|
---|
1990 | }
|
---|
1991 | TkWinReleaseDrawableDC(drawable, hDC, &state);
|
---|
1992 | }
|
---|
1993 |
|
---|
1994 | static BOOL
|
---|
1995 | DrawChars(HDC dc, int x, int y, char *string, int length)
|
---|
1996 | {
|
---|
1997 | BOOL result;
|
---|
1998 |
|
---|
1999 | #if (TCL_VERSION_NUMBER >= _VERSION(8,1,0))
|
---|
2000 | if (systemEncoding == NULL) {
|
---|
2001 | result = TextOutA(dc, x, y, string, length);
|
---|
2002 | } else {
|
---|
2003 | const unsigned short *wstring;
|
---|
2004 | Tcl_DString dString;
|
---|
2005 |
|
---|
2006 | Tcl_DStringInit(&dString);
|
---|
2007 | Tcl_UtfToExternalDString(systemEncoding, string, length, &dString);
|
---|
2008 | length = Tcl_NumUtfChars(string, -1);
|
---|
2009 | wstring = (const unsigned short *)Tcl_DStringValue(&dString);
|
---|
2010 | result = TextOutW(dc, x, y, wstring, length);
|
---|
2011 | Tcl_DStringFree(&dString);
|
---|
2012 | }
|
---|
2013 | #else
|
---|
2014 | result = TextOutA(dc, x, y, string, length);
|
---|
2015 | #endif /* TCL_VERSION_NUMBER >= 8.1.0 */
|
---|
2016 | return result;
|
---|
2017 | }
|
---|
2018 |
|
---|
2019 | int
|
---|
2020 | Blt_DrawRotatedText(
|
---|
2021 | Display *display,
|
---|
2022 | Drawable drawable,
|
---|
2023 | int x, int y,
|
---|
2024 | double theta,
|
---|
2025 | TextStyle *tsPtr,
|
---|
2026 | TextLayout *textPtr)
|
---|
2027 | {
|
---|
2028 | HFONT hFont, oldFont;
|
---|
2029 | TkWinDCState state;
|
---|
2030 | HDC hDC;
|
---|
2031 | int isActive;
|
---|
2032 | int bbWidth, bbHeight;
|
---|
2033 | double rotWidth, rotHeight;
|
---|
2034 | double sinTheta, cosTheta;
|
---|
2035 | Point2D p, q, center;
|
---|
2036 | register TextFragment *fragPtr, *endPtr;
|
---|
2037 | #if (TCL_VERSION_NUMBER >= _VERSION(8,1,0))
|
---|
2038 | static int initialized = 0;
|
---|
2039 |
|
---|
2040 | if (!initialized) {
|
---|
2041 | if (Blt_GetPlatformId() == VER_PLATFORM_WIN32_NT) {
|
---|
2042 | /*
|
---|
2043 | * If running NT, then we will be calling some Unicode functions
|
---|
2044 | * explictly. So, even if the Tcl system encoding isn't Unicode,
|
---|
2045 | * make sure we convert to/from the Unicode char set.
|
---|
2046 | */
|
---|
2047 | systemEncoding = Tcl_GetEncoding(NULL, "unicode");
|
---|
2048 | }
|
---|
2049 | initialized = 1;
|
---|
2050 | }
|
---|
2051 | #endif
|
---|
2052 | hFont = CreateRotatedFont(tsPtr->gc->font, theta);
|
---|
2053 | if (hFont == NULL) {
|
---|
2054 | return FALSE;
|
---|
2055 | }
|
---|
2056 | isActive = (tsPtr->state & STATE_ACTIVE);
|
---|
2057 | hDC = TkWinGetDrawableDC(display, drawable, &state);
|
---|
2058 | SetROP2(hDC, tsPtr->gc->function);
|
---|
2059 | oldFont = SelectFont(hDC, hFont);
|
---|
2060 |
|
---|
2061 | Blt_GetBoundingBox(textPtr->width, textPtr->height, theta, &rotWidth,
|
---|
2062 | &rotHeight, (Point2D *)NULL);
|
---|
2063 | bbWidth = ROUND(rotWidth);
|
---|
2064 | bbHeight = ROUND(rotHeight);
|
---|
2065 | Blt_TranslateAnchor(x, y, bbWidth, bbHeight, tsPtr->anchor, &x, &y);
|
---|
2066 | center.x = (double)textPtr->width * -0.5;
|
---|
2067 | center.y = (double)textPtr->height * -0.5;
|
---|
2068 | theta = (-theta / 180.0) * M_PI;
|
---|
2069 | sinTheta = sin(theta), cosTheta = cos(theta);
|
---|
2070 |
|
---|
2071 | endPtr = textPtr->fragArr + textPtr->nFrags;
|
---|
2072 |
|
---|
2073 | for (fragPtr = textPtr->fragArr; fragPtr < endPtr; fragPtr++) {
|
---|
2074 | p.x = center.x + (double)fragPtr->x;
|
---|
2075 | p.y = center.y + (double)fragPtr->y;
|
---|
2076 | q.x = x + (p.x * cosTheta) - (p.y * sinTheta) + (bbWidth * 0.5);
|
---|
2077 | q.y = y + (p.x * sinTheta) + (p.y * cosTheta) + (bbHeight * 0.5);
|
---|
2078 | fragPtr->sx = ROUND(q.x);
|
---|
2079 | fragPtr->sy = ROUND(q.y);
|
---|
2080 | }
|
---|
2081 | SetBkMode(hDC, TRANSPARENT);
|
---|
2082 | SetTextAlign(hDC, TA_LEFT | TA_BASELINE);
|
---|
2083 |
|
---|
2084 | if (tsPtr->state & (STATE_DISABLED | STATE_EMPHASIS)) {
|
---|
2085 | TkBorder *borderPtr = (TkBorder *) tsPtr->border;
|
---|
2086 | XColor *color1, *color2;
|
---|
2087 |
|
---|
2088 | color1 = borderPtr->lightColor, color2 = borderPtr->darkColor;
|
---|
2089 | if (tsPtr->state & STATE_EMPHASIS) {
|
---|
2090 | XColor *hold;
|
---|
2091 |
|
---|
2092 | hold = color1, color1 = color2, color2 = hold;
|
---|
2093 | }
|
---|
2094 | if (color1 != NULL) {
|
---|
2095 | SetTextColor(hDC, color1->pixel);
|
---|
2096 | for (fragPtr = textPtr->fragArr; fragPtr < endPtr; fragPtr++) {
|
---|
2097 | DrawChars(hDC, fragPtr->sx, fragPtr->sy, fragPtr->text,
|
---|
2098 | fragPtr->count);
|
---|
2099 | }
|
---|
2100 | }
|
---|
2101 | if (color2 != NULL) {
|
---|
2102 | SetTextColor(hDC, color2->pixel);
|
---|
2103 | for (fragPtr = textPtr->fragArr; fragPtr < endPtr; fragPtr++) {
|
---|
2104 | DrawChars(hDC, fragPtr->sx + 1, fragPtr->sy + 1, fragPtr->text,
|
---|
2105 | fragPtr->count);
|
---|
2106 | }
|
---|
2107 | }
|
---|
2108 | goto done; /* Done */
|
---|
2109 | }
|
---|
2110 | SetBkMode(hDC, TRANSPARENT);
|
---|
2111 | if ((tsPtr->shadow.offset > 0) && (tsPtr->shadow.color != NULL)) {
|
---|
2112 | SetTextColor(hDC, tsPtr->shadow.color->pixel);
|
---|
2113 | for (fragPtr = textPtr->fragArr; fragPtr < endPtr; fragPtr++) {
|
---|
2114 | DrawChars(hDC, fragPtr->sx + tsPtr->shadow.offset,
|
---|
2115 | fragPtr->sy + tsPtr->shadow.offset, fragPtr->text,
|
---|
2116 | fragPtr->count);
|
---|
2117 | }
|
---|
2118 | }
|
---|
2119 | if (isActive) {
|
---|
2120 | SetTextColor(hDC, tsPtr->activeColor->pixel);
|
---|
2121 | } else {
|
---|
2122 | SetTextColor(hDC, tsPtr->color->pixel);
|
---|
2123 | }
|
---|
2124 |
|
---|
2125 | for (fragPtr = textPtr->fragArr; fragPtr < endPtr; fragPtr++) {
|
---|
2126 | DrawChars(hDC, fragPtr->sx, fragPtr->sy, fragPtr->text,
|
---|
2127 | fragPtr->count);
|
---|
2128 | }
|
---|
2129 |
|
---|
2130 | if (isActive) {
|
---|
2131 | SetTextColor(hDC, tsPtr->color->pixel);
|
---|
2132 | }
|
---|
2133 | done:
|
---|
2134 | SelectFont(hDC, oldFont);
|
---|
2135 | DeleteFont(hFont);
|
---|
2136 | TkWinReleaseDrawableDC(drawable, hDC, &state);
|
---|
2137 | return TRUE;
|
---|
2138 | }
|
---|
2139 |
|
---|
2140 | static void
|
---|
2141 | DrawPixel(
|
---|
2142 | HDC hDC,
|
---|
2143 | int x,
|
---|
2144 | int y,
|
---|
2145 | COLORREF color)
|
---|
2146 | {
|
---|
2147 | HDC memDC;
|
---|
2148 | HBRUSH hBrushFg;
|
---|
2149 | HBITMAP oldBitmap, hBitmap;
|
---|
2150 | RECT rect;
|
---|
2151 | int size;
|
---|
2152 |
|
---|
2153 | size = 1;
|
---|
2154 | memDC = CreateCompatibleDC(hDC);
|
---|
2155 | hBrushFg = CreateSolidBrush(color);
|
---|
2156 | hBitmap = CreateCompatibleBitmap(hDC, size, size);
|
---|
2157 | oldBitmap = SelectObject(memDC, hBitmap);
|
---|
2158 | rect.left = rect.top = 0;
|
---|
2159 | rect.right = rect.bottom = size;
|
---|
2160 | FillRect(memDC, &rect, hBrushFg);
|
---|
2161 | BitBlt(hDC, x, y, size, size, memDC, 0, 0, SRCCOPY);
|
---|
2162 | SelectObject(memDC, oldBitmap);
|
---|
2163 | DeleteObject(hBitmap);
|
---|
2164 | DeleteBrush(hBrushFg);
|
---|
2165 | DeleteDC(memDC);
|
---|
2166 | }
|
---|
2167 |
|
---|
2168 | /*
|
---|
2169 | *----------------------------------------------------------------------
|
---|
2170 | *
|
---|
2171 | * PixelateBitmap --
|
---|
2172 | *
|
---|
2173 | * Draws a masked bitmap in given device (should be printer)
|
---|
2174 | * context. Bit operations on print devices usually fail because
|
---|
2175 | * there's no way to read back from the device surface to get the
|
---|
2176 | * previous pixel values, rendering BitBlt useless. The bandaid
|
---|
2177 | * solution here is to draw 1x1 pixel rectangles at each
|
---|
2178 | * coordinate as directed by the the mask and source bitmaps.
|
---|
2179 | *
|
---|
2180 | * Results:
|
---|
2181 | * None.
|
---|
2182 | *
|
---|
2183 | * Side effects:
|
---|
2184 | * Draws onto the specified drawable.
|
---|
2185 | *
|
---|
2186 | *----------------------------------------------------------------------
|
---|
2187 | */
|
---|
2188 | static void
|
---|
2189 | PixelateBitmap(
|
---|
2190 | Display *display,
|
---|
2191 | Drawable drawable,
|
---|
2192 | Pixmap srcBitmap,
|
---|
2193 | Pixmap maskBitmap,
|
---|
2194 | int width,
|
---|
2195 | int height,
|
---|
2196 | GC gc,
|
---|
2197 | int destX,
|
---|
2198 | int destY)
|
---|
2199 | {
|
---|
2200 | register int x, y;
|
---|
2201 | register int dx, dy;
|
---|
2202 | int pixel;
|
---|
2203 | unsigned char *srcBits;
|
---|
2204 | register unsigned char *srcPtr;
|
---|
2205 | int bitPos, bytesPerRow;
|
---|
2206 | HDC hDC;
|
---|
2207 | TkWinDCState state;
|
---|
2208 |
|
---|
2209 | srcBits = Blt_GetBitmapData(display, srcBitmap, width, height,
|
---|
2210 | &bytesPerRow);
|
---|
2211 | if (srcBits == NULL) {
|
---|
2212 | return;
|
---|
2213 | }
|
---|
2214 | hDC = TkWinGetDrawableDC(display, drawable, &state);
|
---|
2215 | if (maskBitmap != None) {
|
---|
2216 | register unsigned char *maskPtr;
|
---|
2217 | unsigned char *maskBits;
|
---|
2218 | maskBits = Blt_GetBitmapData(display, maskBitmap, width, height,
|
---|
2219 | &bytesPerRow);
|
---|
2220 | bytesPerRow = ((width + 31) & ~31) / 8;
|
---|
2221 | for (dy = destY, y = height - 1; y >= 0; y--, dy++) {
|
---|
2222 | maskPtr = maskBits + (bytesPerRow * y);
|
---|
2223 | srcPtr = srcBits + (bytesPerRow * y);
|
---|
2224 | for (dx = destX, x = 0; x < width; x++, dx++) {
|
---|
2225 | bitPos = x % 8;
|
---|
2226 | pixel = (*maskPtr & (0x80 >> bitPos));
|
---|
2227 | if (pixel) {
|
---|
2228 | pixel = (*srcPtr & (0x80 >> bitPos));
|
---|
2229 | DrawPixel(hDC, dx, dy,
|
---|
2230 | (pixel) ? gc->foreground : gc->background);
|
---|
2231 | }
|
---|
2232 | if (bitPos == 7) {
|
---|
2233 | srcPtr++, maskPtr++;
|
---|
2234 | }
|
---|
2235 | } /* x */
|
---|
2236 | }
|
---|
2237 | Blt_Free(maskBits);
|
---|
2238 | } else {
|
---|
2239 | bytesPerRow = ((width + 31) & ~31) / 8;
|
---|
2240 | for (dy = destY, y = height - 1; y >= 0; y--, dy++) {
|
---|
2241 | srcPtr = srcBits + (bytesPerRow * y);
|
---|
2242 | for (dx = destX, x = 0; x < width; x++, dx++) {
|
---|
2243 | bitPos = x % 8;
|
---|
2244 | pixel = (*srcPtr & (0x80 >> bitPos));
|
---|
2245 | DrawPixel(hDC, dx, dy,
|
---|
2246 | (pixel) ? gc->foreground : gc->background);
|
---|
2247 | if (bitPos == 7) {
|
---|
2248 | srcPtr++;
|
---|
2249 | }
|
---|
2250 | }
|
---|
2251 | }
|
---|
2252 | }
|
---|
2253 | TkWinReleaseDrawableDC(drawable, hDC, &state);
|
---|
2254 | Blt_Free(srcBits);
|
---|
2255 | }
|
---|
2256 |
|
---|
2257 | /*
|
---|
2258 | *----------------------------------------------------------------------
|
---|
2259 | *
|
---|
2260 | * Blt_EmulateXCopyPlane --
|
---|
2261 | *
|
---|
2262 | * Simplified version of XCopyPlane. Right now it ignores
|
---|
2263 | * function,
|
---|
2264 | * clip_x_origin,
|
---|
2265 | * clip_y_origin
|
---|
2266 | *
|
---|
2267 | * The plane argument must always be 1.
|
---|
2268 | *
|
---|
2269 | * This routine differs from the Tk version in how it handles
|
---|
2270 | * transparency. It uses a different method of drawing transparent
|
---|
2271 | * bitmaps that doesn't copy the background or use brushes. The
|
---|
2272 | * second change is to call a special routine when the destDC is
|
---|
2273 | * a printer. Stippling is done by a very slow brute-force
|
---|
2274 | * method of drawing 1x1 rectangles for each pixel (bleech).
|
---|
2275 | *
|
---|
2276 | * Results:
|
---|
2277 | * None.
|
---|
2278 | *
|
---|
2279 | * Side effects:
|
---|
2280 | * Changes the destination drawable.
|
---|
2281 | *
|
---|
2282 | *----------------------------------------------------------------------
|
---|
2283 | */
|
---|
2284 | void
|
---|
2285 | Blt_EmulateXCopyPlane(
|
---|
2286 | Display *display,
|
---|
2287 | Drawable src,
|
---|
2288 | Drawable dest,
|
---|
2289 | GC gc,
|
---|
2290 | int srcX,
|
---|
2291 | int srcY,
|
---|
2292 | unsigned int width,
|
---|
2293 | unsigned int height,
|
---|
2294 | int destX,
|
---|
2295 | int destY,
|
---|
2296 | unsigned long plane)
|
---|
2297 | {
|
---|
2298 | HDC srcDC, destDC;
|
---|
2299 | TkWinDCState srcState, destState;
|
---|
2300 | TkpClipMask *clipPtr = (TkpClipMask *) gc->clip_mask;
|
---|
2301 |
|
---|
2302 | display->request++;
|
---|
2303 |
|
---|
2304 | if (plane != 1) {
|
---|
2305 | panic("Unexpected plane specified for XCopyPlane");
|
---|
2306 | }
|
---|
2307 | srcDC = TkWinGetDrawableDC(display, src, &srcState);
|
---|
2308 |
|
---|
2309 | if (src != dest) {
|
---|
2310 | destDC = TkWinGetDrawableDC(display, dest, &destState);
|
---|
2311 | } else {
|
---|
2312 | destDC = srcDC;
|
---|
2313 | }
|
---|
2314 | if ((clipPtr == NULL) || (clipPtr->type == TKP_CLIP_REGION)) {
|
---|
2315 | /*
|
---|
2316 | * Case 1: opaque bitmaps. Windows handles the conversion
|
---|
2317 | * from one bit to multiple bits by setting 0 to the
|
---|
2318 | * foreground color, and 1 to the background color (seems
|
---|
2319 | * backwards, but there you are).
|
---|
2320 | */
|
---|
2321 | if ((clipPtr != NULL) && (clipPtr->type == TKP_CLIP_REGION)) {
|
---|
2322 | SelectClipRgn(destDC, (HRGN) clipPtr->value.region);
|
---|
2323 | OffsetClipRgn(destDC, gc->clip_x_origin, gc->clip_y_origin);
|
---|
2324 | }
|
---|
2325 | SetBkMode(destDC, OPAQUE);
|
---|
2326 | SetBkColor(destDC, gc->foreground);
|
---|
2327 | SetTextColor(destDC, gc->background);
|
---|
2328 | BitBlt(destDC, destX, destY, width, height, srcDC, srcX, srcY,
|
---|
2329 | SRCCOPY);
|
---|
2330 |
|
---|
2331 | SelectClipRgn(destDC, NULL);
|
---|
2332 |
|
---|
2333 | } else if (clipPtr->type == TKP_CLIP_PIXMAP) {
|
---|
2334 | Drawable mask;
|
---|
2335 | /*
|
---|
2336 | * Case 2: transparent bitmaps are handled by setting the
|
---|
2337 | * destination to the foreground color whenever the source
|
---|
2338 | * pixel is set.
|
---|
2339 | */
|
---|
2340 | /*
|
---|
2341 | * Case 3: two arbitrary bitmaps. Copy the source rectangle
|
---|
2342 | * into a color pixmap. Use the result as a brush when
|
---|
2343 | * copying the clip mask into the destination.
|
---|
2344 | */
|
---|
2345 | mask = clipPtr->value.pixmap;
|
---|
2346 |
|
---|
2347 | #if WINDEBUG
|
---|
2348 | PurifyPrintf("mask %s src\n", (mask == src) ? "==" : "!=");
|
---|
2349 | PurifyPrintf("GetDeviceCaps=%x\n",
|
---|
2350 | GetDeviceCaps(destDC, TECHNOLOGY) & DT_RASDISPLAY);
|
---|
2351 | #endif
|
---|
2352 | {
|
---|
2353 | HDC maskDC;
|
---|
2354 | TkWinDCState maskState;
|
---|
2355 |
|
---|
2356 | if (mask != src) {
|
---|
2357 | maskDC = TkWinGetDrawableDC(display, mask, &maskState);
|
---|
2358 | } else {
|
---|
2359 | maskDC = srcDC;
|
---|
2360 | }
|
---|
2361 | SetBkMode(destDC, OPAQUE);
|
---|
2362 | SetTextColor(destDC, gc->background);
|
---|
2363 | SetBkColor(destDC, gc->foreground);
|
---|
2364 | BitBlt(destDC, destX, destY, width, height, srcDC, srcX, srcY,
|
---|
2365 | SRCINVERT);
|
---|
2366 | /*
|
---|
2367 | * Make sure we treat the mask as a monochrome bitmap.
|
---|
2368 | * We can get alpha-blending with non-black/white fg/bg
|
---|
2369 | * color selections.
|
---|
2370 | */
|
---|
2371 | SetTextColor(destDC, RGB(255,255,255));
|
---|
2372 | SetBkColor(destDC, RGB(0,0,0));
|
---|
2373 |
|
---|
2374 | /* FIXME: Handle gc->clip_?_origin's */
|
---|
2375 | BitBlt(destDC, destX, destY, width, height, maskDC, 0, 0, SRCAND);
|
---|
2376 |
|
---|
2377 | SetTextColor(destDC, gc->background);
|
---|
2378 | SetBkColor(destDC, gc->foreground);
|
---|
2379 | BitBlt(destDC, destX, destY, width, height, srcDC, srcX, srcY,
|
---|
2380 | SRCINVERT);
|
---|
2381 | if (mask != src) {
|
---|
2382 | TkWinReleaseDrawableDC(mask, maskDC, &maskState);
|
---|
2383 | }
|
---|
2384 | }
|
---|
2385 | }
|
---|
2386 | if (src != dest) {
|
---|
2387 | TkWinReleaseDrawableDC(dest, destDC, &destState);
|
---|
2388 | }
|
---|
2389 | TkWinReleaseDrawableDC(src, srcDC, &srcState);
|
---|
2390 | }
|
---|
2391 |
|
---|
2392 | /*
|
---|
2393 | *----------------------------------------------------------------------
|
---|
2394 | *
|
---|
2395 | * Blt_EmulateXCopyArea --
|
---|
2396 | *
|
---|
2397 | * Copies data from one drawable to another using block transfer
|
---|
2398 | * routines. The small enhancement over the version in Tk is
|
---|
2399 | * that it doesn't assume that the source and destination devices
|
---|
2400 | * have the same resolution. This isn't true when the destination
|
---|
2401 | * device is a printer.
|
---|
2402 | *
|
---|
2403 | * FIXME: not true anymore. delete this routine.
|
---|
2404 | *
|
---|
2405 | * Results:
|
---|
2406 | * None.
|
---|
2407 | *
|
---|
2408 | * Side effects:
|
---|
2409 | * Data is moved from a window or bitmap to a second window,
|
---|
2410 | * bitmap, or printer.
|
---|
2411 | *
|
---|
2412 | *----------------------------------------------------------------------
|
---|
2413 | */
|
---|
2414 | void
|
---|
2415 | Blt_EmulateXCopyArea(
|
---|
2416 | Display *display,
|
---|
2417 | Drawable src,
|
---|
2418 | Drawable dest,
|
---|
2419 | GC gc,
|
---|
2420 | int srcX, /* Source X-coordinate */
|
---|
2421 | int srcY, /* Source Y-coordinate. */
|
---|
2422 | unsigned int width, /* Width of area. */
|
---|
2423 | unsigned int height, /* Height of area. */
|
---|
2424 | int destX, /* Destination X-coordinate (in screen
|
---|
2425 | * coordinates). */
|
---|
2426 | int destY) /* Destination Y-coordinate (in screen
|
---|
2427 | * coordinates). */
|
---|
2428 | {
|
---|
2429 | HDC srcDC, destDC;
|
---|
2430 | TkWinDCState srcState, destState;
|
---|
2431 | TkpClipMask *clipPtr;
|
---|
2432 |
|
---|
2433 | srcDC = TkWinGetDrawableDC(display, src, &srcState);
|
---|
2434 | if (src != dest) {
|
---|
2435 | destDC = TkWinGetDrawableDC(display, dest, &destState);
|
---|
2436 | } else {
|
---|
2437 | destDC = srcDC;
|
---|
2438 | }
|
---|
2439 | clipPtr = (TkpClipMask *)gc->clip_mask;
|
---|
2440 | if ((clipPtr != NULL) && (clipPtr->type == TKP_CLIP_REGION)) {
|
---|
2441 | SelectClipRgn(destDC, (HRGN)clipPtr->value.region);
|
---|
2442 | OffsetClipRgn(destDC, gc->clip_x_origin, gc->clip_y_origin);
|
---|
2443 | }
|
---|
2444 |
|
---|
2445 | BitBlt(destDC, destX, destY, width, height, srcDC, srcX, srcY,
|
---|
2446 | bltModes[gc->function]);
|
---|
2447 | SelectClipRgn(destDC, NULL);
|
---|
2448 |
|
---|
2449 | if (src != dest) {
|
---|
2450 | TkWinReleaseDrawableDC(dest, destDC, &destState);
|
---|
2451 | }
|
---|
2452 | TkWinReleaseDrawableDC(src, srcDC, &srcState);
|
---|
2453 | }
|
---|
2454 |
|
---|
2455 | static void
|
---|
2456 | StippleRegion(
|
---|
2457 | Display *display,
|
---|
2458 | HDC hDC, /* Device context: For polygons, clip
|
---|
2459 | * region will be installed. */
|
---|
2460 | GC gc,
|
---|
2461 | int x, int y,
|
---|
2462 | int width, int height)
|
---|
2463 | {
|
---|
2464 | BITMAP bm;
|
---|
2465 | HBITMAP oldBitmap;
|
---|
2466 | HDC maskDC, memDC;
|
---|
2467 | Pixmap mask;
|
---|
2468 | TkWinDCState maskState;
|
---|
2469 | TkWinDrawable *twdPtr;
|
---|
2470 | int destX, destY, destWidth, destHeight;
|
---|
2471 | int dx, dy;
|
---|
2472 | int left, top, right, bottom;
|
---|
2473 | int srcX, srcY;
|
---|
2474 | int startX, startY; /* Starting upper left corner of region. */
|
---|
2475 |
|
---|
2476 | twdPtr = (TkWinDrawable *)gc->stipple;
|
---|
2477 | GetObject(twdPtr->bitmap.handle, sizeof(BITMAP), &bm);
|
---|
2478 |
|
---|
2479 | startX = x;
|
---|
2480 | if (x < gc->ts_x_origin) {
|
---|
2481 | dx = (gc->ts_x_origin - x) % bm.bmWidth;
|
---|
2482 | if (dx > 0) {
|
---|
2483 | startX -= (bm.bmWidth - dx);
|
---|
2484 | }
|
---|
2485 | } else if (x > gc->ts_x_origin) {
|
---|
2486 | dx = (x - gc->ts_x_origin) % bm.bmWidth;
|
---|
2487 | if (dx > 0) {
|
---|
2488 | startX -= dx;
|
---|
2489 | }
|
---|
2490 | }
|
---|
2491 | startY = y;
|
---|
2492 | if (y < gc->ts_y_origin) {
|
---|
2493 | dy = (gc->ts_y_origin - y) % bm.bmHeight;
|
---|
2494 | if (dy > 0) {
|
---|
2495 | startY -= (bm.bmHeight - dy);
|
---|
2496 | }
|
---|
2497 | } else if (y >= gc->ts_y_origin) {
|
---|
2498 | dy = (y - gc->ts_y_origin) % bm.bmHeight;
|
---|
2499 | if (dy > 0) {
|
---|
2500 | startY -= dy;
|
---|
2501 | }
|
---|
2502 | }
|
---|
2503 | #ifdef notdef
|
---|
2504 | PurifyPrintf("tile is (%d,%d,%d,%d)\n", gc->ts_x_origin, gc->ts_y_origin,
|
---|
2505 | bm.bmWidth, bm.bmHeight);
|
---|
2506 | PurifyPrintf("region is (%d,%d,%d,%d)\n", x, y, width, height);
|
---|
2507 | PurifyPrintf("starting at %d,%d\n", startX, startY);
|
---|
2508 | #endif
|
---|
2509 | left = x;
|
---|
2510 | right = x + width;
|
---|
2511 | top = y;
|
---|
2512 | bottom = y + height;
|
---|
2513 |
|
---|
2514 | maskDC = memDC = CreateCompatibleDC(hDC);
|
---|
2515 | oldBitmap = SelectBitmap(memDC, twdPtr->bitmap.handle);
|
---|
2516 | mask = gc->stipple;
|
---|
2517 | if (gc->fill_style == FillStippled) { /* With transparency. */
|
---|
2518 | if (gc->clip_mask != None) {
|
---|
2519 | TkpClipMask *clipPtr;
|
---|
2520 |
|
---|
2521 | mask = gc->stipple;
|
---|
2522 | clipPtr = (TkpClipMask *)gc->clip_mask;
|
---|
2523 | if (clipPtr->type == TKP_CLIP_PIXMAP) {
|
---|
2524 | mask = clipPtr->value.pixmap;
|
---|
2525 | }
|
---|
2526 | }
|
---|
2527 | if (mask != gc->stipple) {
|
---|
2528 | maskDC = TkWinGetDrawableDC(display, mask, &maskState);
|
---|
2529 | }
|
---|
2530 | }
|
---|
2531 |
|
---|
2532 | for (y = startY; y < bottom; y += bm.bmHeight) {
|
---|
2533 | srcY = 0;
|
---|
2534 | destY = y;
|
---|
2535 | destHeight = bm.bmHeight;
|
---|
2536 | if (y < top) {
|
---|
2537 | srcY = (top - y);
|
---|
2538 | destHeight = bm.bmHeight - srcY;
|
---|
2539 | destY = top;
|
---|
2540 | }
|
---|
2541 | if ((destY + destHeight) > bottom) {
|
---|
2542 | destHeight = (bottom - destY);
|
---|
2543 | }
|
---|
2544 | for (x = startX; x < right; x += bm.bmWidth) {
|
---|
2545 | srcX = 0;
|
---|
2546 | destX = x;
|
---|
2547 | destWidth = bm.bmWidth;
|
---|
2548 | if (x < left) {
|
---|
2549 | srcX = (left - x);
|
---|
2550 | destWidth = bm.bmWidth - srcX;
|
---|
2551 | destX = left;
|
---|
2552 | }
|
---|
2553 | if ((destX + destWidth) > right) {
|
---|
2554 | destWidth = (right - destX);
|
---|
2555 | }
|
---|
2556 | #ifdef notdef
|
---|
2557 | PurifyPrintf("drawing pattern (%d,%d,%d,%d) at %d,%d\n",
|
---|
2558 | srcX , srcY, destWidth, destHeight, destX, destY);
|
---|
2559 | #endif
|
---|
2560 | if (gc->fill_style == FillStippled) { /* With transparency. */
|
---|
2561 | SetBkMode(hDC, OPAQUE);
|
---|
2562 | SetTextColor(hDC, gc->background);
|
---|
2563 | SetBkColor(hDC, gc->foreground);
|
---|
2564 | BitBlt(hDC, destX, destY, destWidth, destHeight, memDC,
|
---|
2565 | srcX, srcY, SRCINVERT);
|
---|
2566 | SetTextColor(hDC, RGB(255,255,255));
|
---|
2567 | SetBkColor(hDC, RGB(0,0,0));
|
---|
2568 | BitBlt(hDC, destX, destY, destWidth, destHeight, maskDC,
|
---|
2569 | srcX, srcY, SRCAND);
|
---|
2570 | SetTextColor(hDC, gc->background);
|
---|
2571 | SetBkColor(hDC, gc->foreground);
|
---|
2572 | BitBlt(hDC, destX, destY, destWidth, destHeight, memDC,
|
---|
2573 | srcX, srcY, SRCINVERT);
|
---|
2574 | } else if (gc->fill_style == FillOpaqueStippled) { /* Opaque. */
|
---|
2575 | SetBkColor(hDC, gc->foreground);
|
---|
2576 | SetTextColor(hDC, gc->background);
|
---|
2577 | BitBlt(hDC, destX, destY, destWidth, destHeight, memDC,
|
---|
2578 | srcX, srcY, SRCCOPY);
|
---|
2579 | }
|
---|
2580 | }
|
---|
2581 | }
|
---|
2582 | SelectBitmap(memDC, oldBitmap);
|
---|
2583 | if (maskDC != memDC) {
|
---|
2584 | TkWinReleaseDrawableDC(mask, maskDC, &maskState);
|
---|
2585 | }
|
---|
2586 | DeleteDC(memDC);
|
---|
2587 | }
|
---|
2588 |
|
---|
2589 | /*
|
---|
2590 | *----------------------------------------------------------------------
|
---|
2591 | *
|
---|
2592 | * Blt_EmulateXFillPolygon --
|
---|
2593 | *
|
---|
2594 | * This differs from Tk's XFillPolygon in that it works around
|
---|
2595 | * deficencies in Windows 95/98:
|
---|
2596 | * 1. Stippling bitmap is limited to 8x8.
|
---|
2597 | * 2. No tiling (with or without mask).
|
---|
2598 | * Results:
|
---|
2599 | * None.
|
---|
2600 | *
|
---|
2601 | *----------------------------------------------------------------------
|
---|
2602 | */
|
---|
2603 | void
|
---|
2604 | Blt_EmulateXFillPolygon(
|
---|
2605 | Display *display,
|
---|
2606 | Drawable drawable,
|
---|
2607 | GC gc,
|
---|
2608 | XPoint *pointPtr,
|
---|
2609 | int nPoints,
|
---|
2610 | int shape,
|
---|
2611 | int mode)
|
---|
2612 | {
|
---|
2613 | HDC hDC;
|
---|
2614 | HRGN hRgn;
|
---|
2615 | POINT *p, *winPts, *endPtr;
|
---|
2616 | Region2D bbox;
|
---|
2617 | TkWinDCState state;
|
---|
2618 | int fillMode;
|
---|
2619 |
|
---|
2620 | if (drawable == None) {
|
---|
2621 | return;
|
---|
2622 | }
|
---|
2623 |
|
---|
2624 | /* Determine the bounding box of the polygon. */
|
---|
2625 | bbox.left = bbox.right = pointPtr->x;
|
---|
2626 | bbox.top = bbox.bottom = pointPtr->y;
|
---|
2627 |
|
---|
2628 | hDC = TkWinGetDrawableDC(display, drawable, &state);
|
---|
2629 |
|
---|
2630 | /* Allocate array of POINTS to create the polygon's path. */
|
---|
2631 | winPts = Blt_Malloc(sizeof(POINT) * nPoints);
|
---|
2632 | endPtr = winPts + nPoints;
|
---|
2633 | for (p = winPts; p < endPtr; p++) {
|
---|
2634 | if (pointPtr->x < bbox.left) {
|
---|
2635 | bbox.left = pointPtr->x;
|
---|
2636 | }
|
---|
2637 | if (pointPtr->x > bbox.right) {
|
---|
2638 | bbox.right = pointPtr->x;
|
---|
2639 | }
|
---|
2640 | if (pointPtr->y < bbox.top) {
|
---|
2641 | bbox.top = pointPtr->y;
|
---|
2642 | }
|
---|
2643 | if (pointPtr->y > bbox.bottom) {
|
---|
2644 | bbox.bottom = pointPtr->y;
|
---|
2645 | }
|
---|
2646 | p->x = pointPtr->x;
|
---|
2647 | p->y = pointPtr->y;
|
---|
2648 | pointPtr++;
|
---|
2649 | }
|
---|
2650 |
|
---|
2651 | SetROP2(hDC, tkpWinRopModes[gc->function]);
|
---|
2652 | fillMode = (gc->fill_rule == EvenOddRule) ? ALTERNATE : WINDING;
|
---|
2653 |
|
---|
2654 | if ((gc->fill_style == FillStippled) ||
|
---|
2655 | (gc->fill_style == FillOpaqueStippled)) {
|
---|
2656 | int width, height;
|
---|
2657 |
|
---|
2658 | /* Points are offsets within the bounding box. */
|
---|
2659 | for (p = winPts; p < endPtr; p++) {
|
---|
2660 | p->x -= bbox.left;
|
---|
2661 | p->y -= bbox.top;
|
---|
2662 | }
|
---|
2663 | /* Use the polygon as a clip path. */
|
---|
2664 | LPtoDP(hDC, winPts, nPoints);
|
---|
2665 | hRgn = CreatePolygonRgn(winPts, nPoints, fillMode);
|
---|
2666 | SelectClipRgn(hDC, hRgn);
|
---|
2667 | OffsetClipRgn(hDC, bbox.left, bbox.top);
|
---|
2668 |
|
---|
2669 | /* Tile the bounding box. */
|
---|
2670 | width = bbox.right - bbox.left + 1;
|
---|
2671 | height = bbox.bottom - bbox.top + 1;
|
---|
2672 | StippleRegion(display, hDC, gc, bbox.left, bbox.top, width, height);
|
---|
2673 |
|
---|
2674 | SelectClipRgn(hDC, NULL);
|
---|
2675 | DeleteRgn(hRgn);
|
---|
2676 | } else {
|
---|
2677 | HPEN oldPen;
|
---|
2678 | HBRUSH oldBrush;
|
---|
2679 |
|
---|
2680 | /*
|
---|
2681 | * FIXME: Right now, we're assuming that it's solid or
|
---|
2682 | * stippled and ignoring tiling. I'll merge the bits from
|
---|
2683 | * Blt_TilePolygon later.
|
---|
2684 | */
|
---|
2685 | oldPen = SelectPen(hDC, GetStockObject(NULL_PEN));
|
---|
2686 | oldBrush = SelectBrush(hDC, CreateSolidBrush(gc->foreground));
|
---|
2687 | SetPolyFillMode(hDC, fillMode);
|
---|
2688 | Polygon(hDC, winPts, nPoints);
|
---|
2689 | SelectPen(hDC, oldPen);
|
---|
2690 | DeleteBrush(SelectBrush(hDC, oldBrush));
|
---|
2691 | }
|
---|
2692 | Blt_Free(winPts);
|
---|
2693 | TkWinReleaseDrawableDC(drawable, hDC, &state);
|
---|
2694 | }
|
---|