Release 960611
[wine/multimedia.git] / objects / dc.c
blob63495609af217bd1ebd2558cf86605fce1a59629
1 /*
2 * GDI Device Context functions
4 * Copyright 1993 Alexandre Julliard
6 */
8 #include <stdlib.h>
9 #include <string.h>
10 #include "gdi.h"
11 #include "bitmap.h"
12 #include "metafile.h"
13 #include "stddebug.h"
14 #include "color.h"
15 #include "debug.h"
16 #include "font.h"
17 #include "callback.h"
18 #include "xmalloc.h"
20 static DeviceCaps * displayDevCaps = NULL;
22 extern void CLIPPING_UpdateGCRegion( DC * dc ); /* objects/clipping.c */
23 extern BOOL DCHook( HDC, WORD, DWORD, DWORD ); /* windows/dce.c */
25 /* Default DC values */
26 static const WIN_DC_INFO DC_defaultValues =
28 0, /* flags */
29 NULL, /* devCaps */
30 0, /* hMetaFile */
31 0, /* hClipRgn */
32 0, /* hVisRgn */
33 0, /* hGCClipRgn */
34 STOCK_BLACK_PEN, /* hPen */
35 STOCK_WHITE_BRUSH, /* hBrush */
36 STOCK_SYSTEM_FONT, /* hFont */
37 0, /* hBitmap */
38 0, /* hFirstBitmap */
39 0, /* hDevice */
40 STOCK_DEFAULT_PALETTE, /* hPalette */
41 R2_COPYPEN, /* ROPmode */
42 ALTERNATE, /* polyFillMode */
43 BLACKONWHITE, /* stretchBltMode */
44 ABSOLUTE, /* relAbsMode */
45 OPAQUE, /* backgroundMode */
46 RGB( 255, 255, 255 ), /* backgroundColor */
47 RGB( 0, 0, 0 ), /* textColor */
48 0, /* backgroundPixel */
49 0, /* textPixel */
50 0, /* brushOrgX */
51 0, /* brushOrgY */
52 TA_LEFT | TA_TOP | TA_NOUPDATECP, /* textAlign */
53 0, /* charExtra */
54 0, /* breakTotalExtra */
55 0, /* breakCount */
56 0, /* breakExtra */
57 0, /* breakRem */
58 1, /* bitsPerPixel */
59 MM_TEXT, /* MapMode */
60 0, /* DCOrgX */
61 0, /* DCOrgY */
62 0, /* CursPosX */
63 0, /* CursPosY */
64 0, /* WndOrgX */
65 0, /* WndOrgY */
66 1, /* WndExtX */
67 1, /* WndExtY */
68 0, /* VportOrgX */
69 0, /* VportOrgY */
70 1, /* VportExtX */
71 1 /* VportExtY */
74 /* ROP code to GC function conversion */
75 const int DC_XROPfunction[16] =
77 GXclear, /* R2_BLACK */
78 GXnor, /* R2_NOTMERGEPEN */
79 GXandInverted, /* R2_MASKNOTPEN */
80 GXcopyInverted, /* R2_NOTCOPYPEN */
81 GXandReverse, /* R2_MASKPENNOT */
82 GXinvert, /* R2_NOT */
83 GXxor, /* R2_XORPEN */
84 GXnand, /* R2_NOTMASKPEN */
85 GXand, /* R2_MASKPEN */
86 GXequiv, /* R2_NOTXORPEN */
87 GXnoop, /* R2_NOP */
88 GXorInverted, /* R2_MERGENOTPEN */
89 GXcopy, /* R2_COPYPEN */
90 GXorReverse, /* R2_MERGEPENNOT */
91 GXor, /* R2_MERGEPEN */
92 GXset /* R2_WHITE */
96 /***********************************************************************
97 * DC_FillDevCaps
99 * Fill the device caps structure.
101 void DC_FillDevCaps( DeviceCaps * caps )
103 caps->version = 0x300;
104 caps->technology = DT_RASDISPLAY;
105 caps->horzSize = WidthMMOfScreen(screen) * screenWidth / WidthOfScreen(screen);
106 caps->vertSize = HeightMMOfScreen(screen) * screenHeight / HeightOfScreen(screen);
107 caps->horzRes = screenWidth;
108 caps->vertRes = screenHeight;
109 caps->bitsPixel = screenDepth;
110 caps->planes = 1;
111 caps->numBrushes = 16+6; /* 16 solid + 6 hatched brushes */
112 caps->numPens = 16; /* 16 solid pens */
113 caps->numMarkers = 0;
114 caps->numFonts = 0;
115 caps->numColors = 1 << caps->bitsPixel;
116 caps->pdeviceSize = 0;
117 caps->curveCaps = CC_CIRCLES | CC_PIE | CC_CHORD | CC_ELLIPSES |
118 CC_WIDE | CC_STYLED | CC_WIDESTYLED |
119 CC_INTERIORS | CC_ROUNDRECT;
120 caps->lineCaps = LC_POLYLINE | LC_MARKER | LC_POLYMARKER | LC_WIDE |
121 LC_STYLED | LC_WIDESTYLED | LC_INTERIORS;
122 caps->polygonalCaps = PC_POLYGON | PC_RECTANGLE | PC_WINDPOLYGON |
123 PC_SCANLINE | PC_WIDE | PC_STYLED |
124 PC_WIDESTYLED | PC_INTERIORS;
125 caps->textCaps = TC_OP_CHARACTER | TC_OP_STROKE | TC_CP_STROKE |
126 TC_IA_ABLE | TC_UA_ABLE | TC_SO_ABLE | TC_RA_ABLE;
127 caps->clipCaps = CP_REGION;
128 caps->rasterCaps = RC_BITBLT | RC_BANDING | RC_SCALING | RC_BITMAP64 |
129 RC_DI_BITMAP | RC_PALETTE | RC_DIBTODEV | RC_BIGFONT|
130 RC_STRETCHBLT | RC_STRETCHDIB | RC_DEVBITS;
131 caps->aspectX = 36; /* ?? */
132 caps->aspectY = 36; /* ?? */
133 caps->aspectXY = 51;
134 caps->logPixelsX = (int)(caps->horzRes * 25.4 / caps->horzSize);
135 caps->logPixelsY = (int)(caps->vertRes * 25.4 / caps->vertSize);
136 caps->sizePalette = DefaultVisual(display,DefaultScreen(display))->map_entries;
137 caps->numReserved = 0;
138 caps->colorRes = 0;
142 /***********************************************************************
143 * DC_InitDC
145 * Setup device-specific DC values for a newly created DC.
147 void DC_InitDC( DC* dc )
149 RealizeDefaultPalette( dc->hSelf );
150 SetTextColor( dc->hSelf, dc->w.textColor );
151 SetBkColor( dc->hSelf, dc->w.backgroundColor );
152 SelectObject( dc->hSelf, dc->w.hPen );
153 SelectObject( dc->hSelf, dc->w.hBrush );
154 SelectObject( dc->hSelf, dc->w.hFont );
155 XSetGraphicsExposures( display, dc->u.x.gc, False );
156 XSetSubwindowMode( display, dc->u.x.gc, IncludeInferiors );
157 CLIPPING_UpdateGCRegion( dc );
161 /***********************************************************************
162 * DC_SetupGCForPatBlt
164 * Setup the GC for a PatBlt operation using current brush.
165 * If fMapColors is TRUE, X pixels are mapped to Windows colors.
166 * Return FALSE if brush is BS_NULL, TRUE otherwise.
168 BOOL DC_SetupGCForPatBlt( DC * dc, GC gc, BOOL fMapColors )
170 XGCValues val;
171 unsigned long mask;
172 Pixmap pixmap = 0;
174 if (dc->u.x.brush.style == BS_NULL) return FALSE;
175 if (dc->u.x.brush.pixel == -1)
177 /* Special case used for monochrome pattern brushes.
178 * We need to swap foreground and background because
179 * Windows does it the wrong way...
181 val.foreground = dc->w.backgroundPixel;
182 val.background = dc->w.textPixel;
184 else
186 val.foreground = dc->u.x.brush.pixel;
187 val.background = dc->w.backgroundPixel;
189 if (fMapColors && COLOR_PixelToPalette)
191 val.foreground = COLOR_PixelToPalette[val.foreground];
192 val.background = COLOR_PixelToPalette[val.background];
195 if (dc->w.flags & DC_DIRTY) CLIPPING_UpdateGCRegion(dc);
197 val.function = DC_XROPfunction[dc->w.ROPmode-1];
198 val.fill_style = dc->u.x.brush.fillStyle;
199 switch(val.fill_style)
201 case FillStippled:
202 case FillOpaqueStippled:
203 if (dc->w.backgroundMode==OPAQUE) val.fill_style = FillOpaqueStippled;
204 val.stipple = dc->u.x.brush.pixmap;
205 mask = GCStipple;
206 break;
208 case FillTiled:
209 if (fMapColors && COLOR_PixelToPalette)
211 register int x, y;
212 XImage *image;
213 pixmap = XCreatePixmap( display, rootWindow, 8, 8, screenDepth );
214 image = XGetImage( display, dc->u.x.brush.pixmap, 0, 0, 8, 8,
215 AllPlanes, ZPixmap );
216 for (y = 0; y < 8; y++)
217 for (x = 0; x < 8; x++)
218 XPutPixel( image, x, y,
219 COLOR_PixelToPalette[XGetPixel( image, x, y)] );
220 XPutImage( display, pixmap, gc, image, 0, 0, 0, 0, 8, 8 );
221 XDestroyImage( image );
222 val.tile = pixmap;
224 else val.tile = dc->u.x.brush.pixmap;
225 mask = GCTile;
226 break;
228 default:
229 mask = 0;
230 break;
232 val.ts_x_origin = dc->w.DCOrgX + dc->w.brushOrgX;
233 val.ts_y_origin = dc->w.DCOrgY + dc->w.brushOrgY;
234 val.fill_rule = (dc->w.polyFillMode==WINDING) ? WindingRule : EvenOddRule;
235 XChangeGC( display, gc,
236 GCFunction | GCForeground | GCBackground | GCFillStyle |
237 GCFillRule | GCTileStipXOrigin | GCTileStipYOrigin | mask,
238 &val );
239 if (pixmap) XFreePixmap( display, pixmap );
240 return TRUE;
244 /***********************************************************************
245 * DC_SetupGCForBrush
247 * Setup dc->u.x.gc for drawing operations using current brush.
248 * Return FALSE if brush is BS_NULL, TRUE otherwise.
250 BOOL DC_SetupGCForBrush( DC * dc )
252 return DC_SetupGCForPatBlt( dc, dc->u.x.gc, FALSE );
256 /***********************************************************************
257 * DC_SetupGCForPen
259 * Setup dc->u.x.gc for drawing operations using current pen.
260 * Return FALSE if pen is PS_NULL, TRUE otherwise.
262 BOOL DC_SetupGCForPen( DC * dc )
264 XGCValues val;
266 if (dc->u.x.pen.style == PS_NULL) return FALSE;
268 if (dc->w.flags & DC_DIRTY) CLIPPING_UpdateGCRegion(dc);
270 if ((screenDepth <= 8) && /* FIXME: Should check for palette instead */
271 ((dc->w.ROPmode == R2_BLACK) || (dc->w.ROPmode == R2_WHITE)))
273 val.function = GXcopy;
274 val.foreground = COLOR_ToPhysical( NULL, (dc->w.ROPmode == R2_BLACK) ?
275 RGB(0,0,0) : RGB(255,255,255) );
277 else
279 val.function = DC_XROPfunction[dc->w.ROPmode-1];
280 val.foreground = dc->u.x.pen.pixel;
282 val.background = dc->w.backgroundPixel;
283 val.fill_style = FillSolid;
284 if ((dc->u.x.pen.style!=PS_SOLID) && (dc->u.x.pen.style!=PS_INSIDEFRAME))
286 XSetDashes( display, dc->u.x.gc, 0,
287 dc->u.x.pen.dashes, dc->u.x.pen.dash_len );
288 val.line_style = (dc->w.backgroundMode == OPAQUE) ?
289 LineDoubleDash : LineOnOffDash;
291 else val.line_style = LineSolid;
292 val.line_width = dc->u.x.pen.width;
293 val.cap_style = CapRound;
294 val.join_style = JoinBevel;
295 XChangeGC( display, dc->u.x.gc,
296 GCFunction | GCForeground | GCBackground | GCLineWidth |
297 GCLineStyle | GCCapStyle | GCJoinStyle | GCFillStyle, &val );
298 return TRUE;
302 /***********************************************************************
303 * DC_SetupGCForText
305 * Setup dc->u.x.gc for text drawing operations.
306 * Return FALSE if the font is null, TRUE otherwise.
308 BOOL DC_SetupGCForText( DC * dc )
310 XGCValues val;
312 if (!dc->u.x.font.fstruct)
314 fprintf( stderr, "DC_SetupGCForText: fstruct is NULL. Please report this\n" );
315 return FALSE;
318 if (dc->w.flags & DC_DIRTY) CLIPPING_UpdateGCRegion(dc);
320 val.function = GXcopy; /* Text is always GXcopy */
321 val.foreground = dc->w.textPixel;
322 val.background = dc->w.backgroundPixel;
323 val.fill_style = FillSolid;
324 val.font = dc->u.x.font.fstruct->fid;
325 XChangeGC( display, dc->u.x.gc,
326 GCFunction | GCForeground | GCBackground | GCFillStyle |
327 GCFont, &val );
328 return TRUE;
332 /***********************************************************************
333 * DC_CallHookProc
335 BOOL DC_CallHookProc(DC* dc, WORD code, LPARAM lParam)
337 BOOL bRet = 0;
338 FARPROC ptr = GDI_GetDefDCHook();
340 dprintf_dc(stddeb,"CallDCHook: code %04x\n", code);
342 /* if 16-bit callback is, in fact, a thunk to DCHook simply call DCHook */
344 if( dc->hookProc && !(dc->w.flags & (DC_SAVED | DC_MEMORY)) )
345 bRet = (dc->hookProc == ptr) ?
346 DCHook(dc->hSelf, code, dc->dwHookData, lParam):
347 CallDCHookProc(dc->hookProc, dc->hSelf, code, dc->dwHookData, lParam);
349 return bRet;
352 /***********************************************************************
353 * GetDCState (GDI.179)
355 HDC GetDCState( HDC hdc )
357 DC * newdc, * dc;
358 HANDLE handle;
360 if (!(dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC ))) return 0;
361 if (!(handle = GDI_AllocObject( sizeof(DC), DC_MAGIC ))) return 0;
362 newdc = (DC *) GDI_HEAP_LIN_ADDR( handle );
364 dprintf_dc(stddeb, "GetDCState(%04x): returning %04x\n", hdc, handle );
366 memset( &newdc->u.x, 0, sizeof(newdc->u.x) );
367 memcpy( &newdc->w, &dc->w, sizeof(dc->w) );
368 memcpy( &newdc->u.x.pen, &dc->u.x.pen, sizeof(dc->u.x.pen) );
370 newdc->hSelf = (HDC)handle;
371 newdc->saveLevel = 0;
372 newdc->w.flags |= DC_SAVED;
374 newdc->w.hGCClipRgn = 0;
375 newdc->w.hVisRgn = CreateRectRgn( 0, 0, 0, 0 );
376 CombineRgn( newdc->w.hVisRgn, dc->w.hVisRgn, 0, RGN_COPY );
377 if (dc->w.hClipRgn)
379 newdc->w.hClipRgn = CreateRectRgn( 0, 0, 0, 0 );
380 CombineRgn( newdc->w.hClipRgn, dc->w.hClipRgn, 0, RGN_COPY );
382 COLOR_SetMapping( newdc, dc->u.x.pal.hMapping,
383 dc->u.x.pal.hRevMapping, dc->u.x.pal.mappingSize );
384 return handle;
388 /***********************************************************************
389 * SetDCState (GDI.180)
391 void SetDCState( HDC hdc, HDC hdcs )
393 DC * dc, * dcs;
394 HRGN hVisRgn, hClipRgn, hGCClipRgn;
395 HFONT hfont;
396 HBRUSH hbrush;
398 if (!(dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC ))) return;
399 if (!(dcs = (DC *) GDI_GetObjPtr( hdcs, DC_MAGIC ))) return;
400 if (!dcs->w.flags & DC_SAVED) return;
401 dprintf_dc(stddeb, "SetDCState: %04x %04x\n", hdc, hdcs );
403 /* Save the regions, font & brush before overwriting everything */
404 hVisRgn = dc->w.hVisRgn;
405 hClipRgn = dc->w.hClipRgn;
406 hGCClipRgn = dc->w.hGCClipRgn;
407 hfont = dc->w.hFont;
408 hbrush = dc->w.hBrush;
409 memcpy( &dc->w, &dcs->w, sizeof(dc->w) );
410 memcpy( &dc->u.x.pen, &dcs->u.x.pen, sizeof(dc->u.x.pen) );
411 dc->w.flags &= ~DC_SAVED;
413 /* Restore the regions */
414 dc->w.hVisRgn = hVisRgn;
415 dc->w.hClipRgn = hClipRgn;
416 dc->w.hGCClipRgn = hGCClipRgn;
417 dc->w.hFont = hfont;
418 dc->w.hBrush = hbrush;
419 CombineRgn( dc->w.hVisRgn, dcs->w.hVisRgn, 0, RGN_COPY );
420 SelectClipRgn( hdc, dcs->w.hClipRgn );
422 SelectObject( hdc, dcs->w.hBrush );
423 SelectObject( hdc, dcs->w.hFont );
424 COLOR_SetMapping( dc, dcs->u.x.pal.hMapping,
425 dcs->u.x.pal.hRevMapping, dcs->u.x.pal.mappingSize );
429 /***********************************************************************
430 * SaveDC (GDI.30)
432 int SaveDC( HDC hdc )
434 HDC hdcs;
435 DC * dc, * dcs;
437 dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
438 if (!dc)
440 dc = (DC *)GDI_GetObjPtr(hdc, METAFILE_DC_MAGIC);
441 if (!dc) return 0;
442 MF_MetaParam0(dc, META_SAVEDC);
443 return 1; /* ?? */
445 if (!(hdcs = GetDCState( hdc ))) return 0;
446 dcs = (DC *) GDI_HEAP_LIN_ADDR( hdcs );
447 dcs->header.hNext = dc->header.hNext;
448 dc->header.hNext = hdcs;
449 dprintf_dc(stddeb, "SaveDC(%04x): returning %d\n", hdc, dc->saveLevel+1 );
450 return ++dc->saveLevel;
454 /***********************************************************************
455 * RestoreDC (GDI.39)
457 BOOL RestoreDC( HDC hdc, short level )
459 DC * dc, * dcs;
461 dprintf_dc(stddeb, "RestoreDC: %04x %d\n", hdc, level );
462 dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
463 if (!dc)
465 dc = (DC *)GDI_GetObjPtr(hdc, METAFILE_DC_MAGIC);
466 if (!dc) return FALSE;
467 if (level != -1) return FALSE;
468 MF_MetaParam1(dc, META_RESTOREDC, level);
469 return TRUE;
471 if (level == -1) level = dc->saveLevel;
472 if ((level < 1) || (level > (short)dc->saveLevel)) return FALSE;
474 while ((short)dc->saveLevel >= level)
476 HDC hdcs = dc->header.hNext;
477 if (!(dcs = (DC *) GDI_GetObjPtr( hdcs, DC_MAGIC ))) return FALSE;
478 dc->header.hNext = dcs->header.hNext;
479 if ((short)--dc->saveLevel < level) SetDCState( hdc, hdcs );
480 DeleteDC( hdcs );
482 return TRUE;
486 /***********************************************************************
487 * CreateDC (GDI.53)
489 HDC CreateDC( LPCSTR driver, LPCSTR device, LPCSTR output, const DEVMODE* initData )
491 DC * dc;
492 HANDLE handle;
494 handle = GDI_AllocObject( sizeof(DC), DC_MAGIC );
495 if (!handle) return 0;
496 dc = (DC *) GDI_HEAP_LIN_ADDR( handle );
498 dprintf_dc(stddeb, "CreateDC(%s %s %s): returning %04x\n",
499 driver, device, output, handle );
501 if (!displayDevCaps)
503 displayDevCaps = (DeviceCaps *) xmalloc( sizeof(DeviceCaps) );
504 DC_FillDevCaps( displayDevCaps );
507 dc->hSelf = (HDC)handle;
508 dc->saveLevel = 0;
509 dc->dwHookData = 0L;
510 dc->hookProc = (SEGPTR)NULL;
512 memcpy( &dc->w, &DC_defaultValues, sizeof(DC_defaultValues) );
513 memset( &dc->u.x, 0, sizeof(dc->u.x) );
515 dc->u.x.drawable = rootWindow;
516 dc->u.x.gc = XCreateGC( display, dc->u.x.drawable, 0, NULL );
517 dc->w.flags = 0;
518 dc->w.devCaps = displayDevCaps;
519 dc->w.bitsPerPixel = displayDevCaps->bitsPixel;
520 dc->w.hVisRgn = CreateRectRgn( 0, 0, displayDevCaps->horzRes,
521 displayDevCaps->vertRes );
522 if (!dc->w.hVisRgn)
524 GDI_HEAP_FREE( handle );
525 return 0;
528 DC_InitDC( dc );
530 return handle;
534 /***********************************************************************
535 * CreateIC (GDI.153)
537 HDC CreateIC( LPCSTR driver, LPCSTR device, LPCSTR output, const DEVMODE* initData )
539 /* Nothing special yet for ICs */
540 return CreateDC( driver, device, output, initData );
544 /***********************************************************************
545 * CreateCompatibleDC (GDI.52)
547 HDC CreateCompatibleDC( HDC hdc )
549 DC * dc;
550 HANDLE handle;
551 HBITMAP hbitmap;
552 BITMAPOBJ *bmp;
554 handle = GDI_AllocObject( sizeof(DC), DC_MAGIC );
555 if (!handle) return 0;
556 dc = (DC *) GDI_HEAP_LIN_ADDR( handle );
558 dprintf_dc(stddeb, "CreateCompatibleDC(%04x): returning %04x\n", hdc, handle );
560 /* Create default bitmap */
561 if (!(hbitmap = CreateBitmap( 1, 1, 1, 1, NULL )))
563 GDI_HEAP_FREE( handle );
564 return 0;
566 bmp = (BITMAPOBJ *) GDI_GetObjPtr( hbitmap, BITMAP_MAGIC );
568 dc->hSelf = (HDC)handle;
569 dc->saveLevel = 0;
570 dc->dwHookData = 0L;
571 dc->hookProc = (SEGPTR)NULL;
573 memcpy( &dc->w, &DC_defaultValues, sizeof(DC_defaultValues) );
574 memset( &dc->u.x, 0, sizeof(dc->u.x) );
576 dc->u.x.drawable = bmp->pixmap;
577 dc->u.x.gc = XCreateGC( display, dc->u.x.drawable, 0, NULL );
578 dc->w.flags = DC_MEMORY;
579 dc->w.bitsPerPixel = 1;
580 dc->w.devCaps = displayDevCaps;
581 dc->w.hBitmap = hbitmap;
582 dc->w.hFirstBitmap = hbitmap;
583 dc->w.hVisRgn = CreateRectRgn( 0, 0, 1, 1 );
585 if (!dc->w.hVisRgn)
587 DeleteObject( hbitmap );
588 GDI_HEAP_FREE( handle );
589 return 0;
592 DC_InitDC( dc );
594 return handle;
598 /***********************************************************************
599 * DeleteDC (GDI.68)
601 BOOL DeleteDC( HDC hdc )
603 DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
604 if (!dc) return FALSE;
606 dprintf_dc(stddeb, "DeleteDC: %04x\n", hdc );
608 while (dc->saveLevel)
610 DC * dcs;
611 HDC hdcs = dc->header.hNext;
612 if (!(dcs = (DC *) GDI_GetObjPtr( hdcs, DC_MAGIC ))) break;
613 dc->header.hNext = dcs->header.hNext;
614 dc->saveLevel--;
615 DeleteDC( hdcs );
618 if (!(dc->w.flags & DC_SAVED))
620 SelectObject( hdc, STOCK_BLACK_PEN );
621 SelectObject( hdc, STOCK_WHITE_BRUSH );
622 SelectObject( hdc, STOCK_SYSTEM_FONT );
623 XFreeGC( display, dc->u.x.gc );
626 if (dc->w.flags & DC_MEMORY) DeleteObject( dc->w.hFirstBitmap );
627 if (dc->w.hClipRgn) DeleteObject( dc->w.hClipRgn );
628 if (dc->w.hVisRgn) DeleteObject( dc->w.hVisRgn );
629 if (dc->w.hGCClipRgn) DeleteObject( dc->w.hGCClipRgn );
631 return GDI_FreeObject( hdc );
635 /***********************************************************************
636 * ResetDC (GDI.376)
638 HDC ResetDC( HDC hdc, /* DEVMODE */ void *devmode )
640 fprintf( stderr, "ResetDC: empty stub!\n" );
641 return hdc;
645 /***********************************************************************
646 * GetDeviceCaps (GDI.80)
648 int GetDeviceCaps( HDC hdc, WORD cap )
650 DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
651 if (!dc) return 0;
653 if (cap > sizeof(DeviceCaps)-sizeof(WORD)) return 0;
655 dprintf_dc(stddeb, "GetDeviceCaps(%04x,%d): returning %d\n",
656 hdc, cap, *(WORD *)(((char *)dc->w.devCaps) + cap) );
657 return *(WORD *)(((char *)dc->w.devCaps) + cap);
661 /***********************************************************************
662 * SetBkColor (GDI.1)
664 COLORREF SetBkColor( HDC hdc, COLORREF color )
666 COLORREF oldColor;
667 DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
668 if (!dc)
670 dc = (DC *)GDI_GetObjPtr(hdc, METAFILE_DC_MAGIC);
671 if (!dc) return 0x80000000;
672 MF_MetaParam2(dc, META_SETBKCOLOR, HIWORD(color), LOWORD(color));
673 return 0; /* ?? */
676 oldColor = dc->w.backgroundColor;
677 dc->w.backgroundColor = color;
678 dc->w.backgroundPixel = COLOR_ToPhysical( dc, color );
679 return oldColor;
683 /***********************************************************************
684 * SetTextColor (GDI.9)
686 COLORREF SetTextColor( HDC hdc, COLORREF color )
688 COLORREF oldColor;
689 DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
690 if (!dc)
692 dc = (DC *)GDI_GetObjPtr(hdc, METAFILE_DC_MAGIC);
693 if (!dc) return 0x80000000;
694 MF_MetaParam2(dc, META_SETTEXTCOLOR, HIWORD(color), LOWORD(color));
695 return 0; /* ?? */
698 oldColor = dc->w.textColor;
699 dc->w.textColor = color;
700 dc->w.textPixel = COLOR_ToPhysical( dc, color );
701 return oldColor;
705 /***********************************************************************
706 * SetTextAlign (GDI.346)
708 WORD SetTextAlign( HDC hdc, WORD textAlign )
710 WORD prevAlign;
711 DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
712 if (!dc)
714 if (!(dc = (DC *)GDI_GetObjPtr( hdc, METAFILE_DC_MAGIC ))) return 0;
715 MF_MetaParam1( dc, META_SETTEXTALIGN, textAlign );
716 return 1;
718 prevAlign = dc->w.textAlign;
719 dc->w.textAlign = textAlign;
720 return prevAlign;
724 /***********************************************************************
725 * GetDCOrg (GDI.79)
727 DWORD GetDCOrg( HDC hdc )
729 Window root;
730 int x, y, w, h, border, depth;
732 DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
733 if (!dc) return 0;
734 if (dc->w.flags & DC_MEMORY) return 0;
735 XGetGeometry( display, dc->u.x.drawable, &root,
736 &x, &y, &w, &h, &border, &depth );
737 return MAKELONG( dc->w.DCOrgX + (WORD)x, dc->w.DCOrgY + (WORD)y );
741 /***********************************************************************
742 * SetDCOrg (GDI.117)
744 DWORD SetDCOrg( HDC hdc, short x, short y )
746 DWORD prevOrg;
747 DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
748 if (!dc) return 0;
749 prevOrg = dc->w.DCOrgX | (dc->w.DCOrgY << 16);
750 dc->w.DCOrgX = x;
751 dc->w.DCOrgY = y;
752 return prevOrg;
756 /***********************************************************************
757 * SetDCHook (GDI.190)
759 BOOL SetDCHook( HDC hDC, FARPROC16 hookProc, DWORD dwHookData )
761 DC *dc = (DC *)GDI_GetObjPtr( hDC, DC_MAGIC );
763 dprintf_dc( stddeb, "SetDCHook: hookProc %08x, default is %08x\n",
764 (unsigned)hookProc,(unsigned)GDI_GetDefDCHook() );
766 if (!dc) return FALSE;
767 dc->hookProc = hookProc;
768 dc->dwHookData = dwHookData;
769 return TRUE;
773 /***********************************************************************
774 * GetDCHook (GDI.191)
776 DWORD GetDCHook( HDC hDC, FARPROC16 *phookProc )
778 DC *dc = (DC *)GDI_GetObjPtr( hDC, DC_MAGIC );
779 if (!dc) return 0;
780 *phookProc = dc->hookProc;
781 return dc->dwHookData;
785 /***********************************************************************
786 * SetHookFlags (GDI.192)
788 WORD SetHookFlags(HDC hDC, WORD flags)
790 DC* dc = (DC*)GDI_GetObjPtr( hDC, DC_MAGIC );
792 if( dc )
794 WORD wRet = dc->w.flags & DC_DIRTY;
796 /* "Undocumented Windows" info is slightly
797 * confusing
800 dprintf_dc(stddeb,"SetHookFlags: hDC %04x, flags %04x\n",hDC,flags);
802 if( flags & DCHF_INVALIDATEVISRGN )
803 dc->w.flags |= DC_DIRTY;
804 else if( flags & DCHF_VALIDATEVISRGN || !flags )
805 dc->w.flags &= ~DC_DIRTY;
806 return wRet;
808 return 0;