1 /* $Id: dc.c,v 1.45 2003/01/25 23:09:40 ei Exp $
3 * DC.C - Device context functions
7 #undef WIN32_LEAN_AND_MEAN
10 #include <ddk/ntddvid.h>
12 #include <win32k/bitmaps.h>
13 #include <win32k/coord.h>
14 #include <win32k/driver.h>
15 #include <win32k/dc.h>
16 #include <win32k/print.h>
17 #include <win32k/region.h>
18 #include <win32k/gdiobj.h>
19 #include <win32k/pen.h>
20 #include <win32k/text.h>
21 #include "../eng/handle.h"
24 #include <win32k/debug1.h>
26 static GDIDEVICE PrimarySurface
;
27 static BOOL PrimarySurfaceCreated
= FALSE
;
29 /* FIXME: DCs should probably be thread safe */
32 * DC device-independent Get/SetXXX functions
33 * (RJJ) swiped from WINE
36 #define DC_GET_VAL( func_type, func_name, dc_field ) \
37 func_type STDCALL func_name( HDC hdc ) \
40 PDC dc = DC_HandleToPtr( hdc ); \
46 DC_ReleasePtr( hdc ); \
50 /* DC_GET_VAL_EX is used to define functions returning a POINT or a SIZE. It is
51 * important that the function has the right signature, for the implementation
52 * we can do whatever we want.
54 #define DC_GET_VAL_EX( func_name, ret_x, ret_y, type ) \
55 BOOL STDCALL func_name( HDC hdc, LP##type pt ) \
57 PDC dc = DC_HandleToPtr( hdc ); \
62 ((LPPOINT)pt)->x = dc->ret_x; \
63 ((LPPOINT)pt)->y = dc->ret_y; \
64 DC_ReleasePtr( hdc ); \
68 #define DC_SET_MODE( func_name, dc_field, min_val, max_val ) \
69 INT STDCALL func_name( HDC hdc, INT mode ) \
72 PDC dc = DC_HandleToPtr( hdc ); \
77 if ((mode < min_val) || (mode > max_val)) \
81 prevMode = dc->dc_field; \
82 dc->dc_field = mode; \
83 DC_ReleasePtr( hdc ); \
88 VOID
BitmapToSurf(HDC hdc
, PSURFGDI SurfGDI
, PSURFOBJ SurfObj
, PBITMAPOBJ Bitmap
);
90 // --------------------------------------------------------- File Statics
92 static void W32kSetDCState16(HDC hDC
, HDC hDCSave
);
94 // ----------------------------------------------------- Public Functions
96 BOOL STDCALL
W32kCancelDC(HDC hDC
)
101 HDC STDCALL
W32kCreateCompatableDC(HDC hDC
)
103 PDC NewDC
, OrigDC
= NULL
;
108 OrigDC
= DC_HandleToPtr(hDC
);
111 hNewDC
= DC_AllocDC(L
"DISPLAY");
113 NewDC
= DC_HandleToPtr( hNewDC
);
116 /* Allocate a new DC based on the original DC's device */
117 hNewDC
= DC_AllocDC(OrigDC
->DriverName
);
119 NewDC
= DC_HandleToPtr( hNewDC
);
127 /* Copy information from original DC to new DC */
128 NewDC
->hSelf
= NewDC
;
130 /* FIXME: Should this DC request its own PDEV? */
133 NewDC
->PDev
= OrigDC
->PDev
;
134 NewDC
->DMW
= OrigDC
->DMW
;
135 memcpy(NewDC
->FillPatternSurfaces
,
136 OrigDC
->FillPatternSurfaces
,
137 sizeof OrigDC
->FillPatternSurfaces
);
138 NewDC
->GDIInfo
= OrigDC
->GDIInfo
;
139 NewDC
->DevInfo
= OrigDC
->DevInfo
;
142 // Create a 1x1 monochrome bitmap surface
145 NewDC
->Surface
= EngCreateBitmap(onebyone
, 1, BMF_1BPP
, 0, NULL
);
147 /* DriverName is copied in the AllocDC routine */
149 NewDC
->DeviceDriver
= DRIVER_FindMPDriver(NewDC
->DriverName
);
151 NewDC
->DeviceDriver
= OrigDC
->DeviceDriver
;
152 NewDC
->wndOrgX
= OrigDC
->wndOrgX
;
153 NewDC
->wndOrgY
= OrigDC
->wndOrgY
;
154 NewDC
->wndExtX
= OrigDC
->wndExtX
;
155 NewDC
->wndExtY
= OrigDC
->wndExtY
;
156 NewDC
->vportOrgX
= OrigDC
->vportOrgX
;
157 NewDC
->vportOrgY
= OrigDC
->vportOrgY
;
158 NewDC
->vportExtX
= OrigDC
->vportExtX
;
159 NewDC
->vportExtY
= OrigDC
->vportExtY
;
162 /* Create default bitmap */
163 if (!(hBitmap
= W32kCreateBitmap( 1, 1, 1, 1, NULL
)))
165 DC_ReleasePtr( hNewDC
);
169 NewDC
->w
.flags
= DC_MEMORY
;
170 NewDC
->w
.bitsPerPixel
= 1;
171 NewDC
->w
.hBitmap
= hBitmap
;
172 NewDC
->w
.hFirstBitmap
= hBitmap
;
176 NewDC
->w
.hPalette
= OrigDC
->w
.hPalette
;
177 NewDC
->w
.textColor
= OrigDC
->w
.textColor
;
178 NewDC
->w
.textAlign
= OrigDC
->w
.textAlign
;
180 DC_ReleasePtr( hDC
);
181 DC_ReleasePtr( hNewDC
);
187 BOOL STDCALL
W32kCreatePrimarySurface(LPCWSTR Driver
,
190 PGD_ENABLEDRIVER GDEnableDriver
;
195 /* Open the miniport driver */
196 if ((DeviceDriver
= DRIVER_FindMPDriver(Driver
)) == NULL
)
198 DPRINT("FindMPDriver failed\n");
202 /* Get the DDI driver's entry point */
203 /* FIXME: Retrieve DDI driver name from registry */
204 if ((GDEnableDriver
= DRIVER_FindDDIDriver(L
"\\SystemRoot\\system32\\drivers\\vgaddi.dll")) == NULL
)
206 DPRINT("FindDDIDriver failed\n");
210 /* Call DDI driver's EnableDriver function */
211 RtlZeroMemory(&DED
, sizeof(DED
));
213 if (!GDEnableDriver(DDI_DRIVER_VERSION
, sizeof(DED
), &DED
))
215 DPRINT("DrvEnableDriver failed\n");
218 DPRINT("Building DDI Functions\n");
220 /* Construct DDI driver function dispatch table */
221 if (!DRIVER_BuildDDIFunctions(&DED
, &PrimarySurface
.DriverFunctions
))
223 DPRINT("BuildDDIFunctions failed\n");
227 /* Allocate a phyical device handle from the driver */
230 DPRINT("Device in u: %u\n", Device
);
231 // wcsncpy(NewDC->DMW.dmDeviceName, Device, DMMAXDEVICENAME); FIXME: this crashes everything?
234 DPRINT("Enabling PDev\n");
236 PrimarySurface
.PDev
=
237 PrimarySurface
.DriverFunctions
.EnablePDev(&PrimarySurface
.DMW
,
240 PrimarySurface
.FillPatterns
,
241 sizeof(PrimarySurface
.GDIInfo
),
242 (ULONG
*) &PrimarySurface
.GDIInfo
,
243 sizeof(PrimarySurface
.DevInfo
),
244 &PrimarySurface
.DevInfo
,
248 if (PrimarySurface
.PDev
== NULL
)
250 DPRINT("DrvEnablePDEV failed\n");
254 DPRINT("calling completePDev\n");
256 /* Complete initialization of the physical device */
257 PrimarySurface
.DriverFunctions
.CompletePDev(PrimarySurface
.PDev
,
260 DPRINT("calling DRIVER_ReferenceDriver\n");
262 DRIVER_ReferenceDriver (Driver
);
264 DPRINT("calling EnableSurface\n");
266 /* Enable the drawing surface */
267 PrimarySurface
.Handle
=
268 PrimarySurface
.DriverFunctions
.EnableSurface(PrimarySurface
.PDev
);
270 SurfObj
= (PSURFOBJ
)AccessUserObject(PrimarySurface
.Handle
);
271 SurfObj
->dhpdev
= PrimarySurface
.PDev
;
274 HDC STDCALL
W32kCreateDC(LPCWSTR Driver
,
277 CONST PDEVMODEW InitData
)
283 /* Check for existing DC object */
284 if ((hNewDC
= DC_FindOpenDC(Driver
)) != NULL
)
287 return W32kCreateCompatableDC(hDC
);
290 DPRINT("NAME: %S\n", Driver
); // FIXME: Should not crash if NULL
292 /* Allocate a DC object */
293 if ((hNewDC
= DC_AllocDC(Driver
)) == NULL
)
298 NewDC
= DC_HandleToPtr( hNewDC
);
301 if (!PrimarySurfaceCreated
)
303 if (!W32kCreatePrimarySurface(Driver
, Device
))
305 DC_ReleasePtr( hNewDC
);
310 PrimarySurfaceCreated
= TRUE
;
311 NewDC
->DMW
= PrimarySurface
.DMW
;
312 NewDC
->DevInfo
= PrimarySurface
.DevInfo
;
313 NewDC
->GDIInfo
= PrimarySurface
.GDIInfo
;
314 memcpy(NewDC
->FillPatternSurfaces
, PrimarySurface
.FillPatterns
,
315 sizeof(NewDC
->FillPatternSurfaces
));
316 NewDC
->PDev
= PrimarySurface
.PDev
;
317 NewDC
->Surface
= PrimarySurface
.Handle
;
318 NewDC
->DriverFunctions
= PrimarySurface
.DriverFunctions
;
320 NewDC
->DMW
.dmSize
= sizeof(NewDC
->DMW
);
321 NewDC
->DMW
.dmFields
= 0x000fc000;
323 /* FIXME: get mode selection information from somewhere */
325 NewDC
->DMW
.dmLogPixels
= 96;
326 NewDC
->DMW
.dmBitsPerPel
= 4;
327 NewDC
->DMW
.dmPelsWidth
= 640;
328 NewDC
->DMW
.dmPelsHeight
= 480;
329 NewDC
->DMW
.dmDisplayFlags
= 0;
330 NewDC
->DMW
.dmDisplayFrequency
= 0;
332 NewDC
->w
.bitsPerPixel
= 4; // FIXME: set this here??
334 NewDC
->w
.hPalette
= NewDC
->DevInfo
.hpalDefault
;
336 DPRINT("Bits per pel: %u\n", NewDC
->w
.bitsPerPixel
);
338 NewDC
->w
.hVisRgn
= W32kCreateRectRgn(0, 0, 640, 480);
339 DC_ReleasePtr( hNewDC
);
341 /* Initialize the DC state */
343 W32kSetTextColor(hNewDC
, RGB(0, 0, 0));
344 W32kSetTextAlign(hNewDC
, TA_TOP
);
349 HDC STDCALL
W32kCreateIC(LPCWSTR Driver
,
352 CONST PDEVMODEW DevMode
)
354 /* FIXME: this should probably do something else... */
355 return W32kCreateDC(Driver
, Device
, Output
, DevMode
);
358 BOOL STDCALL
W32kDeleteDC(HDC DCHandle
)
362 DCToDelete
= DC_HandleToPtr(DCHandle
);
363 if (DCToDelete
== NULL
)
367 DPRINT( "Deleting DC\n" );
368 if ((!(DCToDelete
->w
.flags
& DC_MEMORY
))) // Don't reset the display if its a memory DC
370 if (!DRIVER_UnreferenceDriver (DCToDelete
->DriverName
))
372 DPRINT( "No more references to driver, reseting display\n" );
373 DCToDelete
->DriverFunctions
.DisableSurface(DCToDelete
->PDev
);
375 DCToDelete
->DriverFunctions
.AssertMode( DCToDelete
->PDev
, FALSE
);
377 DCToDelete
->DriverFunctions
.DisablePDev(DCToDelete
->PDev
);
378 PrimarySurfaceCreated
= FALSE
;
382 /* First delete all saved DCs */
383 while (DCToDelete
->saveLevel
)
388 savedHDC
= DC_GetNextDC (DCToDelete
);
389 savedDC
= DC_HandleToPtr (savedHDC
);
394 DC_SetNextDC (DCToDelete
, DC_GetNextDC (savedDC
));
395 DCToDelete
->saveLevel
--;
396 DC_ReleasePtr( savedHDC
);
397 W32kDeleteDC (savedHDC
);
400 /* Free GDI resources allocated to this DC */
401 if (!(DCToDelete
->w
.flags
& DC_SAVED
))
404 W32kSelectObject (DCHandle, STOCK_BLACK_PEN);
405 W32kSelectObject (DCHandle, STOCK_WHITE_BRUSH);
406 W32kSelectObject (DCHandle, STOCK_SYSTEM_FONT);
407 DC_LockDC (DCHandle); W32kSelectObject does not recognize stock objects yet */
408 if (DCToDelete
->w
.flags
& DC_MEMORY
)
410 W32kDeleteObject (DCToDelete
->w
.hFirstBitmap
);
413 if (DCToDelete
->w
.hClipRgn
)
415 W32kDeleteObject (DCToDelete
->w
.hClipRgn
);
417 if (DCToDelete
->w
.hVisRgn
)
419 W32kDeleteObject (DCToDelete
->w
.hVisRgn
);
421 if (DCToDelete
->w
.hGCClipRgn
)
423 W32kDeleteObject (DCToDelete
->w
.hGCClipRgn
);
426 PATH_DestroyGdiPath (&DCToDelete
->w
.path
);
428 DC_ReleasePtr( DCToDelete
);
429 DC_FreeDC (DCToDelete
);
434 INT STDCALL
W32kDrawEscape(HDC hDC
,
442 INT STDCALL
W32kEnumObjects(HDC hDC
,
444 GOBJENUMPROC ObjectFunc
,
450 DC_GET_VAL( COLORREF
, W32kGetBkColor
, w
.backgroundColor
)
451 DC_GET_VAL( INT
, W32kGetBkMode
, w
.backgroundMode
)
452 DC_GET_VAL_EX( W32kGetBrushOrgEx
, w
.brushOrgX
, w
.brushOrgY
, POINT
)
453 DC_GET_VAL( HRGN
, W32kGetClipRgn
, w
.hClipRgn
)
455 HGDIOBJ STDCALL
W32kGetCurrentObject(HDC hDC
,
461 DC_GET_VAL_EX( W32kGetCurrentPositionEx
, w
.CursPosX
, w
.CursPosY
, POINT
)
463 BOOL STDCALL
W32kGetDCOrgEx(HDC hDC
,
472 dc
= DC_HandleToPtr(hDC
);
478 Point
->x
= Point
->y
= 0;
480 Point
->x
+= dc
->w
.DCOrgX
;
481 Point
->y
+= dc
->w
.DCOrgY
;
482 DC_ReleasePtr( hDC
);
486 HDC STDCALL
W32kGetDCState16(HDC hDC
)
491 dc
= DC_HandleToPtr(hDC
);
497 hnewdc
= DC_AllocDC(NULL
);
500 DC_ReleasePtr( hDC
);
503 newdc
= DC_HandleToPtr( hnewdc
);
506 newdc
->w
.flags
= dc
->w
.flags
| DC_SAVED
;
508 newdc
->w
.devCaps
= dc
->w
.devCaps
;
510 newdc
->w
.hPen
= dc
->w
.hPen
;
511 newdc
->w
.hBrush
= dc
->w
.hBrush
;
512 newdc
->w
.hFont
= dc
->w
.hFont
;
513 newdc
->w
.hBitmap
= dc
->w
.hBitmap
;
514 newdc
->w
.hFirstBitmap
= dc
->w
.hFirstBitmap
;
516 newdc
->w
.hDevice
= dc
->w
.hDevice
;
517 newdc
->w
.hPalette
= dc
->w
.hPalette
;
519 newdc
->w
.totalExtent
= dc
->w
.totalExtent
;
520 newdc
->w
.bitsPerPixel
= dc
->w
.bitsPerPixel
;
521 newdc
->w
.ROPmode
= dc
->w
.ROPmode
;
522 newdc
->w
.polyFillMode
= dc
->w
.polyFillMode
;
523 newdc
->w
.stretchBltMode
= dc
->w
.stretchBltMode
;
524 newdc
->w
.relAbsMode
= dc
->w
.relAbsMode
;
525 newdc
->w
.backgroundMode
= dc
->w
.backgroundMode
;
526 newdc
->w
.backgroundColor
= dc
->w
.backgroundColor
;
527 newdc
->w
.textColor
= dc
->w
.textColor
;
528 newdc
->w
.brushOrgX
= dc
->w
.brushOrgX
;
529 newdc
->w
.brushOrgY
= dc
->w
.brushOrgY
;
530 newdc
->w
.textAlign
= dc
->w
.textAlign
;
531 newdc
->w
.charExtra
= dc
->w
.charExtra
;
532 newdc
->w
.breakTotalExtra
= dc
->w
.breakTotalExtra
;
533 newdc
->w
.breakCount
= dc
->w
.breakCount
;
534 newdc
->w
.breakExtra
= dc
->w
.breakExtra
;
535 newdc
->w
.breakRem
= dc
->w
.breakRem
;
536 newdc
->w
.MapMode
= dc
->w
.MapMode
;
537 newdc
->w
.GraphicsMode
= dc
->w
.GraphicsMode
;
539 /* Apparently, the DC origin is not changed by [GS]etDCState */
540 newdc
->w
.DCOrgX
= dc
->w
.DCOrgX
;
541 newdc
->w
.DCOrgY
= dc
->w
.DCOrgY
;
543 newdc
->w
.CursPosX
= dc
->w
.CursPosX
;
544 newdc
->w
.CursPosY
= dc
->w
.CursPosY
;
545 newdc
->w
.ArcDirection
= dc
->w
.ArcDirection
;
547 newdc
->w
.xformWorld2Wnd
= dc
->w
.xformWorld2Wnd
;
548 newdc
->w
.xformWorld2Vport
= dc
->w
.xformWorld2Vport
;
549 newdc
->w
.xformVport2World
= dc
->w
.xformVport2World
;
550 newdc
->w
.vport2WorldValid
= dc
->w
.vport2WorldValid
;
552 newdc
->wndOrgX
= dc
->wndOrgX
;
553 newdc
->wndOrgY
= dc
->wndOrgY
;
554 newdc
->wndExtX
= dc
->wndExtX
;
555 newdc
->wndExtY
= dc
->wndExtY
;
556 newdc
->vportOrgX
= dc
->vportOrgX
;
557 newdc
->vportOrgY
= dc
->vportOrgY
;
558 newdc
->vportExtX
= dc
->vportExtX
;
559 newdc
->vportExtY
= dc
->vportExtY
;
561 newdc
->hSelf
= hnewdc
;
562 newdc
->saveLevel
= 0;
565 PATH_InitGdiPath( &newdc
->w
.path
);
568 /* Get/SetDCState() don't change hVisRgn field ("Undoc. Windows" p.559). */
571 newdc
->w
.hGCClipRgn
= newdc
->w
.hVisRgn
= 0;
575 newdc
->w
.hClipRgn
= W32kCreateRectRgn( 0, 0, 0, 0 );
576 W32kCombineRgn( newdc
->w
.hClipRgn
, dc
->w
.hClipRgn
, 0, RGN_COPY
);
580 newdc
->w
.hClipRgn
= 0;
582 DC_ReleasePtr( hnewdc
);
586 INT STDCALL
W32kGetDeviceCaps(HDC hDC
,
593 dc
= DC_HandleToPtr(hDC
);
599 /* Device capabilities for the printer */
603 if(W32kEscape(hDC
, GETPHYSPAGESIZE
, 0, NULL
, (LPVOID
)&pt
) > 0)
610 if(W32kEscape(hDC
, GETPHYSPAGESIZE
, 0, NULL
, (LPVOID
)&pt
) > 0)
616 case PHYSICALOFFSETX
:
617 if(W32kEscape(hDC
, GETPRINTINGOFFSET
, 0, NULL
, (LPVOID
)&pt
) > 0)
623 case PHYSICALOFFSETY
:
624 if(W32kEscape(hDC
, GETPRINTINGOFFSET
, 0, NULL
, (LPVOID
)&pt
) > 0)
631 if(W32kEscape(hDC
, GETSCALINGFACTOR
, 0, NULL
, (LPVOID
)&pt
) > 0)
638 if(W32kEscape(hDC
, GETSCALINGFACTOR
, 0, NULL
, (LPVOID
)&pt
) > 0)
645 if ((Index
< 0) || (Index
> sizeof(DEVICECAPS
) - sizeof(WORD
)))
650 DPRINT("(%04x,%d): returning %d\n",
651 hDC
, Index
, *(WORD
*)(((char *)dc
->w
.devCaps
) + Index
));
652 ret
= *(WORD
*)(((char *)dc
->w
.devCaps
) + Index
);
654 DC_ReleasePtr( hDC
);
658 DC_GET_VAL( INT
, W32kGetMapMode
, w
.MapMode
)
659 DC_GET_VAL( INT
, W32kGetPolyFillMode
, w
.polyFillMode
)
661 INT STDCALL
W32kGetObjectA(HANDLE handle
, INT count
, LPVOID buffer
)
669 gdiObject
= GDIOBJ_LockObj (handle
, GO_MAGIC_DONTCARE
);
673 magic
= GDIOBJ_GetHandleMagic (handle
);
676 /* case GO_PEN_MAGIC:
677 result = PEN_GetObject((PENOBJ *)gdiObject, count, buffer);
680 result = BRUSH_GetObject((BRUSHOBJ *)gdiObject, count, buffer);
682 case GO_BITMAP_MAGIC
:
683 result
= BITMAP_GetObject((BITMAPOBJ
*)gdiObject
, count
, buffer
);
685 /* case GO_FONT_MAGIC:
686 result = FONT_GetObjectA((FONTOBJ *)gdiObject, count, buffer);
688 // FIXME: Fix the LOGFONT structure for the stock fonts
690 if ( (handle >= FIRST_STOCK_HANDLE) && (handle <= LAST_STOCK_HANDLE) )
691 FixStockFontSizeA(handle, count, buffer);
693 case GO_PALETTE_MAGIC:
694 result = PALETTE_GetObject((PALETTEOBJ *)gdiObject, count, buffer);
697 case GO_REGION_MAGIC
:
699 case GO_DISABLED_DC_MAGIC
:
700 case GO_META_DC_MAGIC
:
701 case GO_METAFILE_MAGIC
:
702 case GO_METAFILE_DC_MAGIC
:
703 case GO_ENHMETAFILE_MAGIC
:
704 case GO_ENHMETAFILE_DC_MAGIC
:
705 // FIXME("Magic %04x not implemented\n", magic);
709 DbgPrint("Invalid GDI Magic %04x\n", magic
);
712 GDIOBJ_UnlockObj (handle
, GO_MAGIC_DONTCARE
);
716 INT STDCALL
W32kGetObjectW(HANDLE handle
, INT count
, LPVOID buffer
)
718 PGDIOBJHDR gdiObject
;
724 gdiObject
= GDIOBJ_LockObj(handle
, GO_MAGIC_DONTCARE
);
728 magic
= GDIOBJ_GetHandleMagic (handle
);
731 /* case GO_PEN_MAGIC:
732 result = PEN_GetObject((PENOBJ *)gdiObject, count, buffer);
735 result = BRUSH_GetObject((BRUSHOBJ *)gdiObject, count, buffer);
737 case GO_BITMAP_MAGIC
:
738 result
= BITMAP_GetObject((BITMAPOBJ
*)gdiObject
, count
, buffer
);
740 /* case GO_FONT_MAGIC:
741 result = FONT_GetObjectW((FONTOBJ *)gdiObject, count, buffer);
743 // Fix the LOGFONT structure for the stock fonts
745 if ( (handle >= FIRST_STOCK_HANDLE) && (handle <= LAST_STOCK_HANDLE) )
746 FixStockFontSizeW(handle, count, buffer);
748 case GO_PALETTE_MAGIC:
749 result = PALETTE_GetObject((PALETTEOBJ *)gdiObject, count, buffer);
752 // FIXME("Magic %04x not implemented\n", gdiObject->magic);
755 GDIOBJ_UnlockObj(handle
, GO_MAGIC_DONTCARE
);
759 INT STDCALL
W32kGetObject(HANDLE handle
, INT count
, LPVOID buffer
)
761 return W32kGetObjectW(handle
, count
, buffer
);
764 DWORD STDCALL
W32kGetObjectType(HANDLE handle
)
770 ptr
= GDIOBJ_LockObj(handle
, GO_MAGIC_DONTCARE
);
774 magic
= GDIOBJ_GetHandleMagic (handle
);
783 case GO_BITMAP_MAGIC
:
789 case GO_PALETTE_MAGIC
:
792 case GO_REGION_MAGIC
:
798 case GO_META_DC_MAGIC
:
801 case GO_METAFILE_MAGIC
:
802 result
= OBJ_METAFILE
;
804 case GO_METAFILE_DC_MAGIC
:
807 case GO_ENHMETAFILE_MAGIC
:
808 result
= OBJ_ENHMETAFILE
;
810 case GO_ENHMETAFILE_DC_MAGIC
:
811 result
= OBJ_ENHMETADC
;
814 // FIXME("Magic %04x not implemented\n", magic);
817 GDIOBJ_UnlockObj(handle
, GO_MAGIC_DONTCARE
);
821 DC_GET_VAL( INT
, W32kGetRelAbs
, w
.relAbsMode
)
822 DC_GET_VAL( INT
, W32kGetROP2
, w
.ROPmode
)
823 DC_GET_VAL( INT
, W32kGetStretchBltMode
, w
.stretchBltMode
)
824 DC_GET_VAL( UINT
, W32kGetTextAlign
, w
.textAlign
)
825 DC_GET_VAL( COLORREF
, W32kGetTextColor
, w
.textColor
)
826 DC_GET_VAL_EX( W32kGetViewportExtEx
, vportExtX
, vportExtY
, SIZE
)
827 DC_GET_VAL_EX( W32kGetViewportOrgEx
, vportOrgX
, vportOrgY
, POINT
)
828 DC_GET_VAL_EX( W32kGetWindowExtEx
, wndExtX
, wndExtY
, SIZE
)
829 DC_GET_VAL_EX( W32kGetWindowOrgEx
, wndOrgX
, wndOrgY
, POINT
)
831 HDC STDCALL
W32kResetDC(HDC hDC
, CONST DEVMODEW
*InitData
)
836 BOOL STDCALL
W32kRestoreDC(HDC hDC
, INT SaveLevel
)
841 dc
= DC_HandleToPtr(hDC
);
849 SaveLevel
= dc
->saveLevel
;
852 if ((SaveLevel
< 1) || (SaveLevel
> dc
->saveLevel
))
858 while (dc
->saveLevel
>= SaveLevel
)
860 HDC hdcs
= DC_GetNextDC (dc
);
862 dcs
= DC_HandleToPtr (hdcs
);
867 DC_SetNextDC (dcs
, DC_GetNextDC (dcs
));
868 if (--dc
->saveLevel
< SaveLevel
)
870 W32kSetDCState16 (hDC
, hdcs
);
872 if (!PATH_AssignGdiPath( &dc
->w
.path
, &dcs
->w
.path
))
874 /* FIXME: This might not be quite right, since we're
875 * returning FALSE but still destroying the saved DC state */
880 DC_ReleasePtr( hdcs
);
883 DC_ReleasePtr( hDC
);
887 INT STDCALL
W32kSaveDC(HDC hDC
)
893 dc
= DC_HandleToPtr (hDC
);
899 if (!(hdcs
= W32kGetDCState16 (hDC
)))
903 dcs
= DC_HandleToPtr (hdcs
);
906 /* Copy path. The reason why path saving / restoring is in SaveDC/
907 * RestoreDC and not in GetDCState/SetDCState is that the ...DCState
908 * functions are only in Win16 (which doesn't have paths) and that
909 * SetDCState doesn't allow us to signal an error (which can happen
910 * when copying paths).
912 if (!PATH_AssignGdiPath (&dcs
->w
.path
, &dc
->w
.path
))
919 DC_SetNextDC (dcs
, DC_GetNextDC (dc
));
920 DC_SetNextDC (dc
, hdcs
);
921 ret
= ++dc
->saveLevel
;
922 DC_ReleasePtr( hdcs
);
923 DC_ReleasePtr( hDC
);
928 HGDIOBJ STDCALL
W32kSelectObject(HDC hDC
, HGDIOBJ hGDIObj
)
942 if(!hDC
|| !hGDIObj
) return NULL
;
944 dc
= DC_HandleToPtr(hDC
);
945 objectMagic
= GDIOBJ_GetHandleMagic (hGDIObj
);
946 // GdiObjHdr = hGDIObj;
948 // FIXME: Get object handle from GDIObj and use it instead of GDIObj below?
950 switch(objectMagic
) {
952 objOrg
= (HGDIOBJ
)dc
->w
.hPen
;
953 dc
->w
.hPen
= hGDIObj
;
955 // Convert the color of the pen to the format of the DC
956 PalGDI
= (PPALGDI
)AccessInternalObject(dc
->w
.hPalette
);
958 XlateObj
= (PXLATEOBJ
)EngCreateXlate(PalGDI
->Mode
, PAL_RGB
, dc
->w
.hPalette
, NULL
);
959 pen
= GDIOBJ_LockObj(dc
->w
.hPen
, GO_PEN_MAGIC
);
961 pen
->logpen
.lopnColor
= XLATEOBJ_iXlate(XlateObj
, pen
->logpen
.lopnColor
);
963 GDIOBJ_UnlockObj( dc
->w
.hPen
, GO_PEN_MAGIC
);
967 objOrg
= (HGDIOBJ
)dc
->w
.hBrush
;
968 dc
->w
.hBrush
= (HBRUSH
) hGDIObj
;
970 // Convert the color of the brush to the format of the DC
971 PalGDI
= (PPALGDI
)AccessInternalObject(dc
->w
.hPalette
);
973 XlateObj
= (PXLATEOBJ
)EngCreateXlate(PalGDI
->Mode
, PAL_RGB
, dc
->w
.hPalette
, NULL
);
974 brush
= GDIOBJ_LockObj(dc
->w
.hBrush
, GO_BRUSH_MAGIC
);
976 brush
->iSolidColor
= XLATEOBJ_iXlate(XlateObj
, brush
->logbrush
.lbColor
);
978 GDIOBJ_UnlockObj( dc
->w
.hBrush
, GO_BRUSH_MAGIC
);
982 objOrg
= (HGDIOBJ
)dc
->w
.hFont
;
983 dc
->w
.hFont
= (HFONT
) hGDIObj
;
985 case GO_BITMAP_MAGIC
:
986 // must be memory dc to select bitmap
987 if (!(dc
->w
.flags
& DC_MEMORY
)) return NULL
;
988 objOrg
= (HGDIOBJ
)dc
->w
.hBitmap
;
990 // setup mem dc for drawing into bitmap
991 pb
= BITMAPOBJ_HandleToPtr (hGDIObj
);
992 dc
->w
.hBitmap
= CreateGDIHandle(sizeof( SURFGDI
), sizeof( SURFOBJ
)); // Assign the DC's bitmap
994 surfobj
= (PSURFOBJ
) AccessUserObject( dc
->w
.hBitmap
);
995 surfgdi
= (PSURFGDI
) AccessInternalObject( dc
->w
.hBitmap
);
996 BitmapToSurf(hDC
, surfgdi
, surfobj
, pb
); // Put the bitmap in a surface
998 dc
->Surface
= dc
->w
.hBitmap
;
1000 // if we're working with a DIB, get the palette [fixme: only create if the selected palette is null]
1003 dc
->w
.bitsPerPixel
= pb
->dib
->dsBmih
.biBitCount
;
1005 if(pb
->dib
->dsBmih
.biBitCount
<= 8)
1007 if(pb
->dib
->dsBmih
.biBitCount
== 1) { NumColors
= 2; } else
1008 if(pb
->dib
->dsBmih
.biBitCount
== 4) { NumColors
= 16; } else
1009 if(pb
->dib
->dsBmih
.biBitCount
== 8) { NumColors
= 256; }
1011 dc
->w
.hPalette
= EngCreatePalette(PAL_INDEXED
, NumColors
, pb
->ColorMap
, 0, 0, 0);
1013 if((pb
->dib
->dsBmih
.biBitCount
> 8) && (pb
->dib
->dsBmih
.biBitCount
< 24))
1015 dc
->w
.hPalette
= EngCreatePalette(PAL_BITFIELDS
, pb
->dib
->dsBmih
.biClrUsed
, NULL
, 0, 0, 0);
1017 if(pb
->dib
->dsBmih
.biBitCount
>= 24)
1019 dc
->w
.hPalette
= EngCreatePalette(PAL_RGB
, pb
->dib
->dsBmih
.biClrUsed
, NULL
, 0, 0, 0);
1022 dc
->w
.bitsPerPixel
= pb
->bitmap
.bmBitsPixel
;
1026 case GO_REGION_MAGIC
:
1027 /* objOrg = (HGDIOBJ)hDC->region; */
1028 objOrg
= NULL
; /* FIXME? hDC->region is destroyed below */
1029 SelectClipRgn(hDC
, (HRGN
)hGDIObj
);
1035 DC_ReleasePtr( hDC
);
1039 DC_SET_MODE( W32kSetBkMode
, w
.backgroundMode
, TRANSPARENT
, OPAQUE
)
1040 DC_SET_MODE( W32kSetPolyFillMode
, w
.polyFillMode
, ALTERNATE
, WINDING
)
1041 // DC_SET_MODE( W32kSetRelAbs, w.relAbsMode, ABSOLUTE, RELATIVE )
1042 DC_SET_MODE( W32kSetROP2
, w
.ROPmode
, R2_BLACK
, R2_WHITE
)
1043 DC_SET_MODE( W32kSetStretchBltMode
, w
.stretchBltMode
, BLACKONWHITE
, HALFTONE
)
1045 COLORREF STDCALL
W32kSetBkColor(HDC hDC
, COLORREF color
)
1048 PDC dc
= DC_HandleToPtr(hDC
);
1055 oldColor
= dc
->w
.backgroundColor
;
1056 dc
->w
.backgroundColor
= color
;
1057 DC_ReleasePtr( hDC
);
1061 static void W32kSetDCState16(HDC hDC
, HDC hDCSave
)
1065 dc
= DC_HandleToPtr(hDC
);
1071 dcs
= DC_HandleToPtr(hDCSave
);
1074 DC_ReleasePtr( hDC
);
1077 if (!dcs
->w
.flags
& DC_SAVED
)
1082 dc
->w
.flags
= dcs
->w
.flags
& ~DC_SAVED
;
1085 dc
->w
.devCaps
= dcs
->w
.devCaps
;
1088 dc
->w
.hFirstBitmap
= dcs
->w
.hFirstBitmap
;
1091 dc
->w
.hDevice
= dcs
->w
.hDevice
;
1094 dc
->w
.totalExtent
= dcs
->w
.totalExtent
;
1095 dc
->w
.ROPmode
= dcs
->w
.ROPmode
;
1096 dc
->w
.polyFillMode
= dcs
->w
.polyFillMode
;
1097 dc
->w
.stretchBltMode
= dcs
->w
.stretchBltMode
;
1098 dc
->w
.relAbsMode
= dcs
->w
.relAbsMode
;
1099 dc
->w
.backgroundMode
= dcs
->w
.backgroundMode
;
1100 dc
->w
.backgroundColor
= dcs
->w
.backgroundColor
;
1101 dc
->w
.textColor
= dcs
->w
.textColor
;
1102 dc
->w
.brushOrgX
= dcs
->w
.brushOrgX
;
1103 dc
->w
.brushOrgY
= dcs
->w
.brushOrgY
;
1104 dc
->w
.textAlign
= dcs
->w
.textAlign
;
1105 dc
->w
.charExtra
= dcs
->w
.charExtra
;
1106 dc
->w
.breakTotalExtra
= dcs
->w
.breakTotalExtra
;
1107 dc
->w
.breakCount
= dcs
->w
.breakCount
;
1108 dc
->w
.breakExtra
= dcs
->w
.breakExtra
;
1109 dc
->w
.breakRem
= dcs
->w
.breakRem
;
1110 dc
->w
.MapMode
= dcs
->w
.MapMode
;
1111 dc
->w
.GraphicsMode
= dcs
->w
.GraphicsMode
;
1113 /* Apparently, the DC origin is not changed by [GS]etDCState */
1114 dc
->w
.DCOrgX
= dcs
->w
.DCOrgX
;
1115 dc
->w
.DCOrgY
= dcs
->w
.DCOrgY
;
1117 dc
->w
.CursPosX
= dcs
->w
.CursPosX
;
1118 dc
->w
.CursPosY
= dcs
->w
.CursPosY
;
1119 dc
->w
.ArcDirection
= dcs
->w
.ArcDirection
;
1122 dc
->w
.xformWorld2Wnd
= dcs
->w
.xformWorld2Wnd
;
1123 dc
->w
.xformWorld2Vport
= dcs
->w
.xformWorld2Vport
;
1124 dc
->w
.xformVport2World
= dcs
->w
.xformVport2World
;
1125 dc
->w
.vport2WorldValid
= dcs
->w
.vport2WorldValid
;
1128 dc
->wndOrgX
= dcs
->wndOrgX
;
1129 dc
->wndOrgY
= dcs
->wndOrgY
;
1130 dc
->wndExtX
= dcs
->wndExtX
;
1131 dc
->wndExtY
= dcs
->wndExtY
;
1132 dc
->vportOrgX
= dcs
->vportOrgX
;
1133 dc
->vportOrgY
= dcs
->vportOrgY
;
1134 dc
->vportExtX
= dcs
->vportExtX
;
1135 dc
->vportExtY
= dcs
->vportExtY
;
1137 if (!(dc
->w
.flags
& DC_MEMORY
))
1139 dc
->w
.bitsPerPixel
= dcs
->w
.bitsPerPixel
;
1143 if (dcs
->w
.hClipRgn
)
1145 if (!dc
->w
.hClipRgn
)
1147 dc
->w
.hClipRgn
= W32kCreateRectRgn( 0, 0, 0, 0 );
1149 W32kCombineRgn( dc
->w
.hClipRgn
, dcs
->w
.hClipRgn
, 0, RGN_COPY
);
1155 W32kDeleteObject( dc
->w
.hClipRgn
);
1160 CLIPPING_UpdateGCRegion( dc
);
1163 W32kSelectObject( hDC
, dcs
->w
.hBitmap
);
1164 W32kSelectObject( hDC
, dcs
->w
.hBrush
);
1165 W32kSelectObject( hDC
, dcs
->w
.hFont
);
1166 W32kSelectObject( hDC
, dcs
->w
.hPen
);
1167 W32kSetBkColor( hDC
, dcs
->w
.backgroundColor
);
1168 W32kSetTextColor( hDC
, dcs
->w
.textColor
);
1171 GDISelectPalette16( hDC
, dcs
->w
.hPalette
, FALSE
);
1174 DC_ReleasePtr( hDCSave
);
1175 DC_ReleasePtr( hDC
);
1178 // ---------------------------------------------------- Private Interface
1180 HDC
DC_AllocDC(LPCWSTR Driver
)
1185 hDC
= (HDC
) GDIOBJ_AllocObj(sizeof(DC
), GO_DC_MAGIC
);
1191 NewDC
= (PDC
) GDIOBJ_LockObj( hDC
, GO_DC_MAGIC
);
1195 NewDC
->DriverName
= ExAllocatePool(PagedPool
, (wcslen(Driver
) + 1) * sizeof(WCHAR
));
1196 wcscpy(NewDC
->DriverName
, Driver
);
1199 NewDC
->w
.xformWorld2Wnd
.eM11
= 1.0f
;
1200 NewDC
->w
.xformWorld2Wnd
.eM12
= 0.0f
;
1201 NewDC
->w
.xformWorld2Wnd
.eM21
= 0.0f
;
1202 NewDC
->w
.xformWorld2Wnd
.eM22
= 1.0f
;
1203 NewDC
->w
.xformWorld2Wnd
.eDx
= 0.0f
;
1204 NewDC
->w
.xformWorld2Wnd
.eDy
= 0.0f
;
1205 NewDC
->w
.xformWorld2Vport
= NewDC
->w
.xformWorld2Wnd
;
1206 NewDC
->w
.xformVport2World
= NewDC
->w
.xformWorld2Wnd
;
1207 NewDC
->w
.vport2WorldValid
= TRUE
;
1209 NewDC
->w
.hFont
= W32kGetStockObject(SYSTEM_FONT
);
1211 GDIOBJ_UnlockObj( hDC
, GO_DC_MAGIC
);
1215 HDC
DC_FindOpenDC(LPCWSTR Driver
)
1221 * Initialize some common fields in the Device Context structure.
1223 void DC_InitDC(HDC DCHandle
)
1225 // W32kRealizeDefaultPalette(DCHandle);
1227 W32kSelectObject(DCHandle
, W32kGetStockObject( WHITE_BRUSH
));
1228 //W32kSelectObject(DCHandle, hPen);
1229 //W32kSelectObject(DCHandle, hFont);
1231 // CLIPPING_UpdateGCRegion(DCToInit);
1235 void DC_FreeDC(HDC DCToFree
)
1237 if (!GDIOBJ_FreeObj(DCToFree
, GO_DC_MAGIC
, GDIOBJFLAG_DEFAULT
))
1239 DPRINT("DC_FreeDC failed\n");
1243 BOOL
DC_InternalDeleteDC( PDC DCToDelete
)
1245 if( DCToDelete
->DriverName
)
1246 ExFreePool(DCToDelete
->DriverName
);
1250 HDC
DC_GetNextDC (PDC pDC
)
1255 void DC_SetNextDC (PDC pDC
, HDC hNextDC
)
1257 pDC
->hNext
= hNextDC
;
1261 DC_UpdateXforms(PDC dc
)
1263 XFORM xformWnd2Vport
;
1264 FLOAT scaleX
, scaleY
;
1266 /* Construct a transformation to do the window-to-viewport conversion */
1267 scaleX
= (FLOAT
)dc
->vportExtX
/ (FLOAT
)dc
->wndExtX
;
1268 scaleY
= (FLOAT
)dc
->vportExtY
/ (FLOAT
)dc
->wndExtY
;
1269 xformWnd2Vport
.eM11
= scaleX
;
1270 xformWnd2Vport
.eM12
= 0.0;
1271 xformWnd2Vport
.eM21
= 0.0;
1272 xformWnd2Vport
.eM22
= scaleY
;
1273 xformWnd2Vport
.eDx
= (FLOAT
)dc
->vportOrgX
- scaleX
* (FLOAT
)dc
->wndOrgX
;
1274 xformWnd2Vport
.eDy
= (FLOAT
)dc
->vportOrgY
- scaleY
* (FLOAT
)dc
->wndOrgY
;
1276 /* Combine with the world transformation */
1277 W32kCombineTransform(&dc
->w
.xformWorld2Vport
, &dc
->w
.xformWorld2Wnd
, &xformWnd2Vport
);
1279 /* Create inverse of world-to-viewport transformation */
1280 dc
->w
.vport2WorldValid
= DC_InvertXform(&dc
->w
.xformWorld2Vport
, &dc
->w
.xformVport2World
);
1284 DC_InvertXform(const XFORM
*xformSrc
,
1289 determinant
= xformSrc
->eM11
*xformSrc
->eM22
- xformSrc
->eM12
*xformSrc
->eM21
;
1290 if (determinant
> -1e-12 && determinant
< 1e-12)
1295 xformDest
->eM11
= xformSrc
->eM22
/ determinant
;
1296 xformDest
->eM12
= -xformSrc
->eM12
/ determinant
;
1297 xformDest
->eM21
= -xformSrc
->eM21
/ determinant
;
1298 xformDest
->eM22
= xformSrc
->eM11
/ determinant
;
1299 xformDest
->eDx
= -xformSrc
->eDx
* xformDest
->eM11
- xformSrc
->eDy
* xformDest
->eM21
;
1300 xformDest
->eDy
= -xformSrc
->eDx
* xformDest
->eM12
- xformSrc
->eDy
* xformDest
->eM22
;