2 * ReactOS W32 Subsystem
3 * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003 ReactOS Team
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21 * DC.C - Device context functions
25 #undef WIN32_LEAN_AND_MEAN
27 #include <ddk/ntddk.h>
28 #include <ddk/ntddvid.h>
30 #include <win32k/bitmaps.h>
31 #include <win32k/brush.h>
32 #include <win32k/cliprgn.h>
33 #include <win32k/coord.h>
34 #include <win32k/driver.h>
35 #include <win32k/dc.h>
36 #include <win32k/misc.h>
37 #include <win32k/print.h>
38 #include <win32k/region.h>
39 #include <win32k/gdiobj.h>
40 #include <win32k/paint.h>
41 #include <win32k/pen.h>
42 #include <win32k/text.h>
43 #include "../eng/clip.h"
44 #include "../eng/handle.h"
45 #include <include/inteng.h>
46 #include <include/eng.h>
47 #include <include/palette.h>
50 #include <win32k/debug1.h>
52 static GDIDEVICE PrimarySurface;
53 static BOOL PrimarySurfaceCreated = FALSE;
55 /* FIXME: DCs should probably be thread safe */
58 * DC device-independent Get/SetXXX functions
59 * (RJJ) swiped from WINE
62 #define DC_GET_VAL( func_type, func_name, dc_field ) \
63 func_type STDCALL func_name( HDC hdc ) \
66 PDC dc = DC_LockDc( hdc ); \
76 /* DC_GET_VAL_EX is used to define functions returning a POINT or a SIZE. It is
77 * important that the function has the right signature, for the implementation
78 * we can do whatever we want.
80 #define DC_GET_VAL_EX( NtGdiFuncName, IntFuncName, ret_x, ret_y, type ) \
81 VOID FASTCALL IntFuncName ( PDC dc, LP##type pt ) \
85 ((LPPOINT)pt)->x = dc->ret_x; \
86 ((LPPOINT)pt)->y = dc->ret_y; \
88 BOOL STDCALL NtGdiFuncName ( HDC hdc, LP##type pt ) \
90 PDC dc = DC_LockDc ( hdc ); \
93 IntFuncName ( dc, pt ); \
94 DC_UnlockDc ( hdc ); \
98 #define DC_SET_MODE( func_name, dc_field, min_val, max_val ) \
99 INT STDCALL func_name( HDC hdc, INT mode ) \
103 if ((mode < min_val) || (mode > max_val)) \
105 dc = DC_LockDc ( hdc ); \
108 prevMode = dc->dc_field; \
109 dc->dc_field = mode; \
110 DC_UnlockDc ( hdc ); \
115 // --------------------------------------------------------- File Statics
117 // ----------------------------------------------------- Public Functions
120 NtGdiCancelDC(HDC hDC)
126 NtGdiCreateCompatableDC(HDC hDC)
137 hNewDC = DC_AllocDC(L"DISPLAY");
141 /* Allocate a new DC based on the original DC's device */
142 OrigDC = DC_LockDc(hDC);
147 hNewDC = DC_AllocDC(OrigDC->DriverName);
154 NewDC = DC_LockDc( hNewDC );
156 /* Copy information from original DC to new DC */
157 NewDC->hSelf = NewDC;
159 /* FIXME: Should this DC request its own PDEV? */
162 NewDC->PDev = PrimarySurface.PDev;
163 memcpy(NewDC->FillPatternSurfaces, PrimarySurface.FillPatterns,
164 sizeof(NewDC->FillPatternSurfaces));
165 NewDC->GDIInfo = &PrimarySurface.GDIInfo;
166 NewDC->DevInfo = &PrimarySurface.DevInfo;
170 NewDC->PDev = OrigDC->PDev;
171 NewDC->DMW = OrigDC->DMW;
172 memcpy(NewDC->FillPatternSurfaces,
173 OrigDC->FillPatternSurfaces,
174 sizeof OrigDC->FillPatternSurfaces);
175 NewDC->GDIInfo = OrigDC->GDIInfo;
176 NewDC->DevInfo = OrigDC->DevInfo;
179 /* DriverName is copied in the AllocDC routine */
182 NewDC->DeviceDriver = DRIVER_FindMPDriver(NewDC->DriverName);
186 NewDC->DeviceDriver = OrigDC->DeviceDriver;
187 NewDC->wndOrgX = OrigDC->wndOrgX;
188 NewDC->wndOrgY = OrigDC->wndOrgY;
189 NewDC->wndExtX = OrigDC->wndExtX;
190 NewDC->wndExtY = OrigDC->wndExtY;
191 NewDC->vportOrgX = OrigDC->vportOrgX;
192 NewDC->vportOrgY = OrigDC->vportOrgY;
193 NewDC->vportExtX = OrigDC->vportExtX;
194 NewDC->vportExtY = OrigDC->vportExtY;
197 /* Create default bitmap */
198 if (!(hBitmap = NtGdiCreateBitmap( 1, 1, 1, 1, NULL )))
201 DC_UnlockDc( hNewDC );
205 NewDC->w.flags = DC_MEMORY;
206 NewDC->w.bitsPerPixel = 1;
207 NewDC->w.hBitmap = hBitmap;
208 NewDC->w.hFirstBitmap = hBitmap;
209 pb = BITMAPOBJ_LockBitmap(hBitmap);
210 NewDC->Surface = BitmapToSurf(pb);
211 BITMAPOBJ_UnlockBitmap(hBitmap);
215 NewDC->w.hPalette = NewDC->DevInfo->hpalDefault;
219 NewDC->w.hPalette = OrigDC->w.hPalette;
220 NewDC->w.textColor = OrigDC->w.textColor;
221 NewDC->w.textAlign = OrigDC->w.textAlign;
222 NewDC->w.backgroundColor = OrigDC->w.backgroundColor;
223 NewDC->w.backgroundMode = OrigDC->w.backgroundMode;
229 DC_UnlockDc( hNewDC );
231 hVisRgn = NtGdiCreateRectRgn(0, 0, 1, 1);
232 NtGdiSelectVisRgn(hNewDC, hVisRgn);
233 NtGdiDeleteObject(hVisRgn);
241 FindDriverFileNames(PUNICODE_STRING DriverFileNames)
243 RTL_QUERY_REGISTRY_TABLE QueryTable[2];
244 UNICODE_STRING RegistryPath;
247 RtlInitUnicodeString(&RegistryPath, NULL);
248 RtlZeroMemory(QueryTable, sizeof(QueryTable));
249 QueryTable[0].Flags = RTL_QUERY_REGISTRY_REQUIRED | RTL_QUERY_REGISTRY_DIRECT;
250 QueryTable[0].Name = L"\\Device\\Video0";
251 QueryTable[0].EntryContext = &RegistryPath;
253 Status = RtlQueryRegistryValues(RTL_REGISTRY_DEVICEMAP,
258 if (! NT_SUCCESS(Status))
260 DPRINT1("No \\Device\\Video0 value in DEVICEMAP\\VIDEO found\n");
264 DPRINT("RegistryPath %S\n", RegistryPath.Buffer);
266 QueryTable[0].Name = L"InstalledDisplayDrivers";
267 QueryTable[0].EntryContext = DriverFileNames;
269 Status = RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE,
274 RtlFreeUnicodeString(&RegistryPath);
275 if (! NT_SUCCESS(Status))
277 DPRINT1("No InstalledDisplayDrivers value in service entry found\n");
281 DPRINT("DriverFileNames %S\n", DriverFileNames->Buffer);
288 NtGdiCreatePrimarySurface(LPCWSTR Driver,
291 PGD_ENABLEDRIVER GDEnableDriver;
295 UNICODE_STRING DriverFileNames;
298 extern void FASTCALL IntInitDesktopWindow(ULONG Width, ULONG Height);
300 /* Open the miniport driver */
301 if ((PrimarySurface.DisplayDevice = DRIVER_FindMPDriver(Driver)) == NULL)
303 DPRINT("FindMPDriver failed\n");
307 /* Retrieve DDI driver names from registry */
308 RtlInitUnicodeString(&DriverFileNames, NULL);
309 if (! FindDriverFileNames(&DriverFileNames))
311 DPRINT("FindDriverFileNames failed\n");
315 /* DriverFileNames may be a list of drivers in REG_SZ_MULTI format, scan all of
316 them until a good one found */
317 CurrentName = DriverFileNames.Buffer;
319 while (! GotDriver && CurrentName < DriverFileNames.Buffer + DriverFileNames.Length)
321 /* Get the DDI driver's entry point */
322 GDEnableDriver = DRIVER_FindDDIDriver(CurrentName);
323 if (NULL == GDEnableDriver)
325 DPRINT("FindDDIDriver failed for %S\n", CurrentName);
329 /* Call DDI driver's EnableDriver function */
330 RtlZeroMemory(&DED, sizeof(DED));
332 if (!GDEnableDriver(DDI_DRIVER_VERSION, sizeof(DED), &DED))
334 DPRINT("DrvEnableDriver failed for %S\n", CurrentName);
344 /* Skip to the next name but never get past the Unicode string */
345 while (L'\0' != *CurrentName &&
346 CurrentName < DriverFileNames.Buffer + DriverFileNames.Length)
350 if (CurrentName < DriverFileNames.Buffer + DriverFileNames.Length)
356 RtlFreeUnicodeString(&DriverFileNames);
359 DPRINT("No suitable driver found\n");
363 DPRINT("Display driver %S loaded\n", CurrentName);
365 DPRINT("Building DDI Functions\n");
367 /* Construct DDI driver function dispatch table */
368 if (!DRIVER_BuildDDIFunctions(&DED, &PrimarySurface.DriverFunctions))
370 DPRINT("BuildDDIFunctions failed\n");
374 /* Allocate a phyical device handle from the driver */
377 DPRINT("Device in u: %u\n", Device);
378 // wcsncpy(NewDC->DMW.dmDeviceName, Device, DMMAXDEVICENAME); FIXME: this crashes everything?
381 DPRINT("Enabling PDev\n");
383 PrimarySurface.PDev =
384 PrimarySurface.DriverFunctions.EnablePDev(&PrimarySurface.DMW,
387 PrimarySurface.FillPatterns,
388 sizeof(PrimarySurface.GDIInfo),
389 (ULONG *) &PrimarySurface.GDIInfo,
390 sizeof(PrimarySurface.DevInfo),
391 &PrimarySurface.DevInfo,
394 PrimarySurface.DisplayDevice);
395 if (PrimarySurface.PDev == NULL)
397 DPRINT("DrvEnablePDEV failed\n");
401 DPRINT("calling completePDev\n");
403 /* Complete initialization of the physical device */
404 PrimarySurface.DriverFunctions.CompletePDev(PrimarySurface.PDev,
407 DPRINT("calling DRIVER_ReferenceDriver\n");
409 DRIVER_ReferenceDriver (Driver);
411 DPRINT("calling EnableSurface\n");
413 /* Enable the drawing surface */
414 PrimarySurface.Handle =
415 PrimarySurface.DriverFunctions.EnableSurface(PrimarySurface.PDev);
417 SurfObj = (PSURFOBJ)AccessUserObject((ULONG) PrimarySurface.Handle);
418 SurfObj->dhpdev = PrimarySurface.PDev;
419 SurfGDI = (PSURFGDI)AccessInternalObject((ULONG) PrimarySurface.Handle);
420 IntInitDesktopWindow(SurfGDI->SurfObj.sizlBitmap.cx, SurfGDI->SurfObj.sizlBitmap.cy);
426 NtGdiCreateDC(LPCWSTR Driver,
429 CONST PDEVMODEW InitData)
437 /* Check for existing DC object */
438 if ((hNewDC = DC_FindOpenDC(Driver)) != NULL)
441 return NtGdiCreateCompatableDC(hDC);
444 DPRINT("NAME: %S\n", Driver); // FIXME: Should not crash if NULL
446 /* Allocate a DC object */
447 if ((hNewDC = DC_AllocDC(Driver)) == NULL)
452 NewDC = DC_LockDc( hNewDC );
455 if (! PrimarySurfaceCreated)
457 PrimarySurfaceCreated = TRUE;
458 if (!NtGdiCreatePrimarySurface(Driver, Device))
460 PrimarySurfaceCreated = FALSE;
461 DC_UnlockDc( hNewDC );
466 NewDC->DMW = PrimarySurface.DMW;
467 NewDC->DevInfo = &PrimarySurface.DevInfo;
468 NewDC->GDIInfo = &PrimarySurface.GDIInfo;
469 memcpy(NewDC->FillPatternSurfaces, PrimarySurface.FillPatterns,
470 sizeof(NewDC->FillPatternSurfaces));
471 NewDC->PDev = PrimarySurface.PDev;
472 NewDC->Surface = PrimarySurface.Handle;
473 NewDC->DriverFunctions = PrimarySurface.DriverFunctions;
475 NewDC->DMW.dmSize = sizeof(NewDC->DMW);
476 NewDC->DMW.dmFields = 0x000fc000;
478 /* FIXME: get mode selection information from somewhere */
480 NewDC->DMW.dmLogPixels = 96;
481 SurfGDI = (PSURFGDI)AccessInternalObject((ULONG) PrimarySurface.Handle);
482 NewDC->DMW.dmBitsPerPel = SurfGDI->BitsPerPixel;
483 NewDC->DMW.dmPelsWidth = SurfGDI->SurfObj.sizlBitmap.cx;
484 NewDC->DMW.dmPelsHeight = SurfGDI->SurfObj.sizlBitmap.cy;
485 NewDC->DMW.dmDisplayFlags = 0;
486 NewDC->DMW.dmDisplayFrequency = 0;
488 NewDC->w.bitsPerPixel = SurfGDI->BitsPerPixel; // FIXME: set this here??
490 NewDC->w.hPalette = NewDC->DevInfo->hpalDefault;
492 DPRINT("Bits per pel: %u\n", NewDC->w.bitsPerPixel);
494 DC_UnlockDc( hNewDC );
496 hVisRgn = NtGdiCreateRectRgn(0, 0, SurfGDI->SurfObj.sizlBitmap.cx,
497 SurfGDI->SurfObj.sizlBitmap.cy);
498 NtGdiSelectVisRgn(hNewDC, hVisRgn);
499 NtGdiDeleteObject(hVisRgn);
501 /* Initialize the DC state */
503 NtGdiSetTextColor(hNewDC, RGB(0, 0, 0));
504 NtGdiSetTextAlign(hNewDC, TA_TOP);
505 NtGdiSetBkColor(hNewDC, RGB(255, 255, 255));
506 NtGdiSetBkMode(hNewDC, OPAQUE);
512 NtGdiCreateIC(LPCWSTR Driver,
515 CONST PDEVMODEW DevMode)
517 /* FIXME: this should probably do something else... */
518 return NtGdiCreateDC(Driver, Device, Output, DevMode);
522 NtGdiDeleteDC(HDC DCHandle)
526 DCToDelete = DC_LockDc(DCHandle);
527 if (DCToDelete == NULL)
531 DPRINT( "Deleting DC\n" );
532 if ((!(DCToDelete->w.flags & DC_MEMORY))) // Don't reset the display if its a memory DC
534 if (!DRIVER_UnreferenceDriver (DCToDelete->DriverName))
536 PEPROCESS CurrentProcess;
537 DPRINT( "No more references to driver, reseting display\n" );
538 DCToDelete->DriverFunctions.AssertMode( DCToDelete->PDev, FALSE );
540 DCToDelete->DriverFunctions.DisableSurface(DCToDelete->PDev);
542 DCToDelete->DriverFunctions.DisablePDev(DCToDelete->PDev);
544 CurrentProcess = PsGetCurrentProcess();
545 if (CurrentProcess != Win32kDeviceProcess)
547 KeAttachProcess(Win32kDeviceProcess);
549 ZwClose(PrimarySurface.DisplayDevice);
550 if (CurrentProcess != Win32kDeviceProcess)
555 PrimarySurfaceCreated = FALSE;
559 /* First delete all saved DCs */
560 while (DCToDelete->saveLevel)
565 savedHDC = DC_GetNextDC (DCToDelete);
566 savedDC = DC_LockDc (savedHDC);
571 DC_SetNextDC (DCToDelete, DC_GetNextDC (savedDC));
572 DCToDelete->saveLevel--;
573 DC_UnlockDc( savedHDC );
574 NtGdiDeleteDC (savedHDC);
577 /* Free GDI resources allocated to this DC */
578 if (!(DCToDelete->w.flags & DC_SAVED))
581 NtGdiSelectObject (DCHandle, STOCK_BLACK_PEN);
582 NtGdiSelectObject (DCHandle, STOCK_WHITE_BRUSH);
583 NtGdiSelectObject (DCHandle, STOCK_SYSTEM_FONT);
584 DC_LockDC (DCHandle); NtGdiSelectObject does not recognize stock objects yet */
585 if (DCToDelete->w.flags & DC_MEMORY)
587 EngDeleteSurface (DCToDelete->Surface);
588 NtGdiDeleteObject (DCToDelete->w.hFirstBitmap);
591 if (DCToDelete->w.hClipRgn)
593 NtGdiDeleteObject (DCToDelete->w.hClipRgn);
595 if (DCToDelete->w.hVisRgn)
597 NtGdiDeleteObject (DCToDelete->w.hVisRgn);
599 if (NULL != DCToDelete->CombinedClip)
601 IntEngDeleteClipRegion(DCToDelete->CombinedClip);
603 if (DCToDelete->w.hGCClipRgn)
605 NtGdiDeleteObject (DCToDelete->w.hGCClipRgn);
608 PATH_DestroyGdiPath (&DCToDelete->w.path);
610 DC_UnlockDc( DCHandle );
611 DC_FreeDC ( DCHandle );
617 NtGdiDrawEscape(HDC hDC,
626 NtGdiEnumObjects(HDC hDC,
628 GOBJENUMPROC ObjectFunc,
634 DC_GET_VAL( COLORREF, NtGdiGetBkColor, w.backgroundColor )
635 DC_GET_VAL( INT, NtGdiGetBkMode, w.backgroundMode )
636 DC_GET_VAL_EX( NtGdiGetBrushOrgEx, IntGetBrushOrgEx, w.brushOrgX, w.brushOrgY, POINT )
637 DC_GET_VAL( HRGN, NtGdiGetClipRgn, w.hClipRgn )
640 NtGdiGetCurrentObject(HDC hDC, UINT ObjectType)
645 DC_GET_VAL_EX ( NtGdiGetCurrentPositionEx, IntGetCurrentPositionEx, w.CursPosX, w.CursPosY, POINT )
648 NtGdiGetDCOrgEx(HDC hDC, LPPOINT Point)
662 Point->x = Point->y = 0;
664 Point->x += dc->w.DCOrgX;
665 Point->y += dc->w.DCOrgY;
671 NtGdiSetBkColor(HDC hDC, COLORREF color)
674 PDC dc = DC_LockDc(hDC);
679 oldColor = dc->w.backgroundColor;
680 dc->w.backgroundColor = color;
686 NtGdiGetDCState(HDC hDC)
697 hnewdc = DC_AllocDC(NULL);
703 newdc = DC_LockDc( hnewdc );
706 newdc->w.flags = dc->w.flags | DC_SAVED;
707 newdc->w.hPen = dc->w.hPen;
708 newdc->w.hBrush = dc->w.hBrush;
709 newdc->w.hFont = dc->w.hFont;
710 newdc->w.hBitmap = dc->w.hBitmap;
711 newdc->w.hFirstBitmap = dc->w.hFirstBitmap;
713 newdc->w.hDevice = dc->w.hDevice;
714 newdc->w.hPalette = dc->w.hPalette;
716 newdc->w.totalExtent = dc->w.totalExtent;
717 newdc->w.bitsPerPixel = dc->w.bitsPerPixel;
718 newdc->w.ROPmode = dc->w.ROPmode;
719 newdc->w.polyFillMode = dc->w.polyFillMode;
720 newdc->w.stretchBltMode = dc->w.stretchBltMode;
721 newdc->w.relAbsMode = dc->w.relAbsMode;
722 newdc->w.backgroundMode = dc->w.backgroundMode;
723 newdc->w.backgroundColor = dc->w.backgroundColor;
724 newdc->w.textColor = dc->w.textColor;
725 newdc->w.brushOrgX = dc->w.brushOrgX;
726 newdc->w.brushOrgY = dc->w.brushOrgY;
727 newdc->w.textAlign = dc->w.textAlign;
728 newdc->w.charExtra = dc->w.charExtra;
729 newdc->w.breakTotalExtra = dc->w.breakTotalExtra;
730 newdc->w.breakCount = dc->w.breakCount;
731 newdc->w.breakExtra = dc->w.breakExtra;
732 newdc->w.breakRem = dc->w.breakRem;
733 newdc->w.MapMode = dc->w.MapMode;
734 newdc->w.GraphicsMode = dc->w.GraphicsMode;
736 /* Apparently, the DC origin is not changed by [GS]etDCState */
737 newdc->w.DCOrgX = dc->w.DCOrgX;
738 newdc->w.DCOrgY = dc->w.DCOrgY;
740 newdc->w.CursPosX = dc->w.CursPosX;
741 newdc->w.CursPosY = dc->w.CursPosY;
742 newdc->w.ArcDirection = dc->w.ArcDirection;
744 newdc->w.xformWorld2Wnd = dc->w.xformWorld2Wnd;
745 newdc->w.xformWorld2Vport = dc->w.xformWorld2Vport;
746 newdc->w.xformVport2World = dc->w.xformVport2World;
747 newdc->w.vport2WorldValid = dc->w.vport2WorldValid;
749 newdc->wndOrgX = dc->wndOrgX;
750 newdc->wndOrgY = dc->wndOrgY;
751 newdc->wndExtX = dc->wndExtX;
752 newdc->wndExtY = dc->wndExtY;
753 newdc->vportOrgX = dc->vportOrgX;
754 newdc->vportOrgY = dc->vportOrgY;
755 newdc->vportExtX = dc->vportExtX;
756 newdc->vportExtY = dc->vportExtY;
758 newdc->hSelf = hnewdc;
759 newdc->saveLevel = 0;
762 PATH_InitGdiPath( &newdc->w.path );
765 /* Get/SetDCState() don't change hVisRgn field ("Undoc. Windows" p.559). */
768 newdc->w.hGCClipRgn = newdc->w.hVisRgn = 0;
772 newdc->w.hClipRgn = NtGdiCreateRectRgn( 0, 0, 0, 0 );
773 NtGdiCombineRgn( newdc->w.hClipRgn, dc->w.hClipRgn, 0, RGN_COPY );
777 newdc->w.hClipRgn = 0;
779 DC_UnlockDc( hnewdc );
787 NtGdiSetDCState ( HDC hDC, HDC hDCSave )
791 dc = DC_LockDc ( hDC );
794 dcs = DC_LockDc ( hDCSave );
797 if ( dcs->w.flags & DC_SAVED )
799 dc->w.flags = dcs->w.flags & ~DC_SAVED;
801 dc->w.hFirstBitmap = dcs->w.hFirstBitmap;
804 dc->w.hDevice = dcs->w.hDevice;
807 dc->w.totalExtent = dcs->w.totalExtent;
808 dc->w.ROPmode = dcs->w.ROPmode;
809 dc->w.polyFillMode = dcs->w.polyFillMode;
810 dc->w.stretchBltMode = dcs->w.stretchBltMode;
811 dc->w.relAbsMode = dcs->w.relAbsMode;
812 dc->w.backgroundMode = dcs->w.backgroundMode;
813 dc->w.backgroundColor = dcs->w.backgroundColor;
814 dc->w.textColor = dcs->w.textColor;
815 dc->w.brushOrgX = dcs->w.brushOrgX;
816 dc->w.brushOrgY = dcs->w.brushOrgY;
817 dc->w.textAlign = dcs->w.textAlign;
818 dc->w.charExtra = dcs->w.charExtra;
819 dc->w.breakTotalExtra = dcs->w.breakTotalExtra;
820 dc->w.breakCount = dcs->w.breakCount;
821 dc->w.breakExtra = dcs->w.breakExtra;
822 dc->w.breakRem = dcs->w.breakRem;
823 dc->w.MapMode = dcs->w.MapMode;
824 dc->w.GraphicsMode = dcs->w.GraphicsMode;
826 /* Apparently, the DC origin is not changed by [GS]etDCState */
827 dc->w.DCOrgX = dcs->w.DCOrgX;
828 dc->w.DCOrgY = dcs->w.DCOrgY;
830 dc->w.CursPosX = dcs->w.CursPosX;
831 dc->w.CursPosY = dcs->w.CursPosY;
832 dc->w.ArcDirection = dcs->w.ArcDirection;
835 dc->w.xformWorld2Wnd = dcs->w.xformWorld2Wnd;
836 dc->w.xformWorld2Vport = dcs->w.xformWorld2Vport;
837 dc->w.xformVport2World = dcs->w.xformVport2World;
838 dc->w.vport2WorldValid = dcs->w.vport2WorldValid;
841 dc->wndOrgX = dcs->wndOrgX;
842 dc->wndOrgY = dcs->wndOrgY;
843 dc->wndExtX = dcs->wndExtX;
844 dc->wndExtY = dcs->wndExtY;
845 dc->vportOrgX = dcs->vportOrgX;
846 dc->vportOrgY = dcs->vportOrgY;
847 dc->vportExtX = dcs->vportExtX;
848 dc->vportExtY = dcs->vportExtY;
850 if (!(dc->w.flags & DC_MEMORY))
852 dc->w.bitsPerPixel = dcs->w.bitsPerPixel;
860 dc->w.hClipRgn = NtGdiCreateRectRgn( 0, 0, 0, 0 );
862 NtGdiCombineRgn( dc->w.hClipRgn, dcs->w.hClipRgn, 0, RGN_COPY );
868 NtGdiDeleteObject( dc->w.hClipRgn );
873 CLIPPING_UpdateGCRegion( dc );
876 NtGdiSelectObject( hDC, dcs->w.hBitmap );
877 NtGdiSelectObject( hDC, dcs->w.hBrush );
878 NtGdiSelectObject( hDC, dcs->w.hFont );
879 NtGdiSelectObject( hDC, dcs->w.hPen );
880 NtGdiSetBkColor( hDC, dcs->w.backgroundColor);
881 NtGdiSetTextColor( hDC, dcs->w.textColor);
884 GDISelectPalette16( hDC, dcs->w.hPalette, FALSE );
888 DC_UnlockDc ( hDCSave );
895 NtGdiGetDeviceCaps(HDC hDC,
908 /* Retrieve capability */
912 ret = dc->GDIInfo->ulVersion;
916 ret = dc->GDIInfo->ulTechnology;
920 ret = dc->GDIInfo->ulHorzSize;
924 ret = dc->GDIInfo->ulVertSize;
928 ret = dc->GDIInfo->ulHorzRes;
932 ret = dc->GDIInfo->ulVertRes;
936 ret = dc->GDIInfo->ulLogPixelsX;
940 ret = dc->GDIInfo->ulLogPixelsY;
944 ret = dc->GDIInfo->cBitsPixel;
948 ret = dc->GDIInfo->cPlanes;
952 UNIMPLEMENTED; /* FIXME */
956 UNIMPLEMENTED; /* FIXME */
960 UNIMPLEMENTED; /* FIXME */
964 ret = dc->GDIInfo->ulNumColors;
968 ret = dc->GDIInfo->ulAspectX;
972 ret = dc->GDIInfo->ulAspectY;
976 ret = dc->GDIInfo->ulAspectXY;
980 UNIMPLEMENTED; /* FIXME */
984 UNIMPLEMENTED; /* FIXME */
988 ret = dc->GDIInfo->ulNumPalReg; /* FIXME not sure */
992 UNIMPLEMENTED; /* FIXME */
996 UNIMPLEMENTED; /* FIXME */
1000 if(NtGdiEscape(hDC, GETPHYSPAGESIZE, 0, NULL, (LPVOID)&pt) > 0)
1010 case PHYSICALHEIGHT:
1011 if(NtGdiEscape(hDC, GETPHYSPAGESIZE, 0, NULL, (LPVOID)&pt) > 0)
1021 case PHYSICALOFFSETX:
1022 if(NtGdiEscape(hDC, GETPRINTINGOFFSET, 0, NULL, (LPVOID)&pt) > 0)
1032 case PHYSICALOFFSETY:
1033 if(NtGdiEscape(hDC, GETPRINTINGOFFSET, 0, NULL, (LPVOID)&pt) > 0)
1044 UNIMPLEMENTED; /* FIXME */
1047 case SCALINGFACTORX:
1048 if(NtGdiEscape(hDC, GETSCALINGFACTOR, 0, NULL, (LPVOID)&pt) > 0)
1058 case SCALINGFACTORY:
1059 if(NtGdiEscape(hDC, GETSCALINGFACTOR, 0, NULL, (LPVOID)&pt) > 0)
1070 UNIMPLEMENTED; /* FIXME */
1074 UNIMPLEMENTED; /* FIXME */
1078 UNIMPLEMENTED; /* FIXME */
1082 UNIMPLEMENTED; /* FIXME */
1086 ret = dc->GDIInfo->flTextCaps;
1094 DPRINT("(%04x,%d): returning %d\n", hDC, Index, ret);
1100 DC_GET_VAL( INT, NtGdiGetMapMode, w.MapMode )
1101 DC_GET_VAL( INT, NtGdiGetPolyFillMode, w.polyFillMode )
1104 NtGdiGetObjectA(HANDLE handle, INT count, LPVOID buffer)
1112 gdiObject = GDIOBJ_LockObj (handle, GDI_OBJECT_TYPE_DONTCARE);
1116 objectType = GDIOBJ_GetObjectType(handle);
1119 /* case GDI_OBJECT_TYPE_PEN:
1120 result = PEN_GetObject((PENOBJ *)gdiObject, count, buffer);
1122 case GDI_OBJECT_TYPE_BRUSH:
1123 result = BRUSH_GetObject((BRUSHOBJ *)gdiObject, count, buffer);
1125 case GDI_OBJECT_TYPE_BITMAP:
1126 result = BITMAP_GetObject((BITMAPOBJ *)gdiObject, count, buffer);
1128 /* case GDI_OBJECT_TYPE_FONT:
1129 result = FONT_GetObjectA((FONTOBJ *)gdiObject, count, buffer);
1131 // FIXME: Fix the LOGFONT structure for the stock fonts
1133 if ( (handle >= FIRST_STOCK_HANDLE) && (handle <= LAST_STOCK_HANDLE) )
1134 FixStockFontSizeA(handle, count, buffer);
1136 case GDI_OBJECT_TYPE_PALETTE:
1137 result = PALETTE_GetObject((PALETTEOBJ *)gdiObject, count, buffer);
1140 case GDI_OBJECT_TYPE_REGION:
1141 case GDI_OBJECT_TYPE_DC:
1142 case GDI_OBJECT_TYPE_METADC:
1143 case GDI_OBJECT_TYPE_METAFILE:
1144 case GDI_OBJECT_TYPE_ENHMETADC:
1145 case GDI_OBJECT_TYPE_EMF:
1146 DPRINT1("GDI object type 0x%08x not implemented\n", objectType);
1150 DPRINT1("Invalid GDI object type 0x%08x\n", objectType);
1153 GDIOBJ_UnlockObj(handle, GDI_OBJECT_TYPE_DONTCARE);
1159 NtGdiGetObjectW(HANDLE handle, INT count, LPVOID buffer)
1161 PGDIOBJHDR gdiObject;
1167 gdiObject = GDIOBJ_LockObj(handle, GDI_OBJECT_TYPE_DONTCARE);
1171 objectType = GDIOBJ_GetObjectType(handle);
1174 /* case GDI_OBJECT_TYPE_PEN:
1175 result = PEN_GetObject((PENOBJ *)gdiObject, count, buffer);
1177 case GDI_OBJECT_TYPE_BRUSH:
1178 result = BRUSH_GetObject((BRUSHOBJ *)gdiObject, count, buffer);
1180 case GDI_OBJECT_TYPE_BITMAP:
1181 result = BITMAP_GetObject((BITMAPOBJ *)gdiObject, count, buffer);
1183 /* case GDI_OBJECT_TYPE_FONT:
1184 result = FONT_GetObjectW((FONTOBJ *)gdiObject, count, buffer);
1186 // Fix the LOGFONT structure for the stock fonts
1188 if ( (handle >= FIRST_STOCK_HANDLE) && (handle <= LAST_STOCK_HANDLE) )
1189 FixStockFontSizeW(handle, count, buffer);
1191 case GDI_OBJECT_TYPE_PALETTE:
1192 result = PALETTE_GetObject((PALETTEOBJ *)gdiObject, count, buffer);
1195 DPRINT1("GDI object type 0x%08x not implemented\n", objectType);
1199 GDIOBJ_UnlockObj(handle, GDI_OBJECT_TYPE_DONTCARE);
1205 NtGdiGetObject(HANDLE handle, INT count, LPVOID buffer)
1207 return NtGdiGetObjectW(handle, count, buffer);
1211 NtGdiGetObjectType(HANDLE handle)
1217 ptr = GDIOBJ_LockObj(handle, GDI_OBJECT_TYPE_DONTCARE);
1221 objectType = GDIOBJ_GetObjectType(handle);
1224 case GDI_OBJECT_TYPE_PEN:
1227 case GDI_OBJECT_TYPE_BRUSH:
1230 case GDI_OBJECT_TYPE_BITMAP:
1231 result = OBJ_BITMAP;
1233 case GDI_OBJECT_TYPE_FONT:
1236 case GDI_OBJECT_TYPE_PALETTE:
1239 case GDI_OBJECT_TYPE_REGION:
1240 result = OBJ_REGION;
1242 case GDI_OBJECT_TYPE_DC:
1245 case GDI_OBJECT_TYPE_METADC:
1246 result = OBJ_METADC;
1248 case GDI_OBJECT_TYPE_METAFILE:
1249 result = OBJ_METAFILE;
1251 case GDI_OBJECT_TYPE_ENHMETAFILE:
1252 result = OBJ_ENHMETAFILE;
1254 case GDI_OBJECT_TYPE_ENHMETADC:
1255 result = OBJ_ENHMETADC;
1257 case GDI_OBJECT_TYPE_EXTPEN:
1258 result = OBJ_EXTPEN;
1260 case GDI_OBJECT_TYPE_MEMDC:
1264 DPRINT1("Magic 0x%08x not implemented\n", objectType);
1267 GDIOBJ_UnlockObj(handle, GDI_OBJECT_TYPE_DONTCARE);
1271 DC_GET_VAL( INT, NtGdiGetRelAbs, w.relAbsMode )
1272 DC_GET_VAL( INT, NtGdiGetROP2, w.ROPmode )
1273 DC_GET_VAL( INT, NtGdiGetStretchBltMode, w.stretchBltMode )
1274 DC_GET_VAL( UINT, NtGdiGetTextAlign, w.textAlign )
1275 DC_GET_VAL( COLORREF, NtGdiGetTextColor, w.textColor )
1276 DC_GET_VAL_EX( NtGdiGetViewportExtEx, IntGetViewportExtEx, vportExtX, vportExtY, SIZE )
1277 DC_GET_VAL_EX( NtGdiGetViewportOrgEx, IntGetViewportOrgEx, vportOrgX, vportOrgY, POINT )
1278 DC_GET_VAL_EX( NtGdiGetWindowExtEx, IntGetWindowExtEx, wndExtX, wndExtY, SIZE )
1279 DC_GET_VAL_EX( NtGdiGetWindowOrgEx, IntGetWindowOrgEx, wndOrgX, wndOrgY, POINT )
1282 NtGdiResetDC(HDC hDC, CONST DEVMODEW *InitData)
1288 NtGdiRestoreDC(HDC hDC, INT SaveLevel)
1293 dc = DC_LockDc(hDC);
1299 if (SaveLevel == -1)
1301 SaveLevel = dc->saveLevel;
1304 if ((SaveLevel < 1) || (SaveLevel > dc->saveLevel))
1310 while (dc->saveLevel >= SaveLevel)
1312 HDC hdcs = DC_GetNextDC (dc);
1314 dcs = DC_LockDc (hdcs);
1319 DC_SetNextDC (dcs, DC_GetNextDC (dcs));
1320 if (--dc->saveLevel < SaveLevel)
1323 DC_UnlockDc( hdcs );
1324 NtGdiSetDCState(hDC, hdcs);
1326 if (!PATH_AssignGdiPath( &dc->w.path, &dcs->w.path ))
1328 /* FIXME: This might not be quite right, since we're
1329 * returning FALSE but still destroying the saved DC state */
1333 dc = DC_LockDc(hDC);
1341 DC_UnlockDc( hdcs );
1343 NtGdiDeleteDC (hdcs);
1350 NtGdiSaveDC(HDC hDC)
1356 if (!(hdcs = NtGdiGetDCState(hDC)))
1361 dcs = DC_LockDc (hdcs);
1366 dc = DC_LockDc (hDC);
1374 /* Copy path. The reason why path saving / restoring is in SaveDC/
1375 * RestoreDC and not in GetDCState/SetDCState is that the ...DCState
1376 * functions are only in Win16 (which doesn't have paths) and that
1377 * SetDCState doesn't allow us to signal an error (which can happen
1378 * when copying paths).
1380 if (!PATH_AssignGdiPath (&dcs->w.path, &dc->w.path))
1382 NtGdiDeleteDC (hdcs);
1387 DC_SetNextDC (dcs, DC_GetNextDC (dc));
1388 DC_SetNextDC (dc, hdcs);
1389 ret = ++dc->saveLevel;
1390 DC_UnlockDc( hdcs );
1398 NtGdiSelectObject(HDC hDC, HGDIOBJ hGDIObj)
1400 HGDIOBJ objOrg = NULL; // default to failure
1409 ULONG NumColors, Index;
1413 if(!hDC || !hGDIObj) return NULL;
1415 dc = DC_LockDc(hDC);
1418 objectType = GDIOBJ_GetObjectType(hGDIObj);
1419 // GdiObjHdr = hGDIObj;
1421 // FIXME: Get object handle from GDIObj and use it instead of GDIObj below?
1425 case GDI_OBJECT_TYPE_PEN:
1426 objOrg = (HGDIOBJ)dc->w.hPen;
1427 dc->w.hPen = hGDIObj;
1429 /* Convert the color of the pen to the format of the DC */
1430 PalGDI = PALETTE_LockPalette(dc->w.hPalette);
1433 Mode = PalGDI->Mode;
1434 PALETTE_UnlockPalette(dc->w.hPalette);
1435 XlateObj = (PXLATEOBJ)IntEngCreateXlate(Mode, PAL_RGB, dc->w.hPalette, NULL);
1436 ASSERT ( XlateObj );
1437 pen = PENOBJ_LockPen(dc->w.hPen);
1440 pen->logpen.lopnColor = XLATEOBJ_iXlate(XlateObj, pen->logpen.lopnColor);
1441 PENOBJ_UnlockPen(dc->w.hPen);
1443 EngDeleteXlate(XlateObj);
1447 case GDI_OBJECT_TYPE_BRUSH:
1448 objOrg = (HGDIOBJ)dc->w.hBrush;
1449 dc->w.hBrush = (HBRUSH) hGDIObj;
1451 /* Convert the color of the brush to the format of the DC */
1452 PalGDI = PALETTE_LockPalette(dc->w.hPalette);
1455 Mode = PalGDI->Mode;
1456 PALETTE_UnlockPalette(dc->w.hPalette);
1457 XlateObj = (PXLATEOBJ)IntEngCreateXlate(Mode, PAL_RGB, dc->w.hPalette, NULL);
1459 brush = BRUSHOBJ_LockBrush(dc->w.hBrush);
1462 brush->iSolidColor = XLATEOBJ_iXlate(XlateObj, brush->logbrush.lbColor);
1464 BRUSHOBJ_UnlockBrush(dc->w.hBrush);
1465 EngDeleteXlate(XlateObj);
1469 case GDI_OBJECT_TYPE_FONT:
1470 objOrg = (HGDIOBJ)dc->w.hFont;
1471 dc->w.hFont = (HFONT) hGDIObj;
1472 TextIntRealizeFont(dc->w.hFont);
1475 case GDI_OBJECT_TYPE_BITMAP:
1476 // must be memory dc to select bitmap
1477 if (!(dc->w.flags & DC_MEMORY)) return NULL;
1478 objOrg = (HGDIOBJ)dc->w.hBitmap;
1480 /* Release the old bitmap, lock the new one and convert it to a SURF */
1481 EngDeleteSurface(dc->Surface);
1482 dc->w.hBitmap = hGDIObj;
1483 pb = BITMAPOBJ_LockBitmap(hGDIObj);
1485 dc->Surface = BitmapToSurf(pb);
1487 // if we're working with a DIB, get the palette [fixme: only create if the selected palette is null]
1490 dc->w.bitsPerPixel = pb->dib->dsBmih.biBitCount;
1492 if(pb->dib->dsBmih.biBitCount <= 8)
1494 if(pb->dib->dsBmih.biBitCount == 1) { NumColors = 2; } else
1495 if(pb->dib->dsBmih.biBitCount == 4) { NumColors = 16; } else
1496 if(pb->dib->dsBmih.biBitCount == 8) { NumColors = 256; }
1498 ColorMap = ExAllocatePool(PagedPool, sizeof(COLORREF) * NumColors);
1500 for (Index = 0; Index < NumColors; Index++)
1502 ColorMap[Index] = RGB(pb->ColorMap[Index].rgbRed,
1503 pb->ColorMap[Index].rgbGreen,
1504 pb->ColorMap[Index].rgbBlue);
1506 dc->w.hPalette = PALETTE_AllocPalette(PAL_INDEXED, NumColors, (ULONG *) ColorMap, 0, 0, 0);
1507 ExFreePool(ColorMap);
1509 else if ( 16 == pb->dib->dsBmih.biBitCount )
1511 dc->w.hPalette = PALETTE_AllocPalette(PAL_BITFIELDS, pb->dib->dsBmih.biClrUsed, NULL, 0x7c00, 0x03e0, 0x001f);
1513 else if(pb->dib->dsBmih.biBitCount >= 24)
1515 dc->w.hPalette = PALETTE_AllocPalette(PAL_RGB, pb->dib->dsBmih.biClrUsed, NULL, 0, 0, 0);
1520 dc->w.bitsPerPixel = pb->bitmap.bmBitsPixel;
1523 DC_UnlockDc ( hDC );
1524 hVisRgn = NtGdiCreateRectRgn ( 0, 0, pb->size.cx, pb->size.cy );
1525 NtGdiSelectVisRgn ( hDC, hVisRgn );
1526 NtGdiDeleteObject ( hVisRgn );
1527 BITMAPOBJ_UnlockBitmap(hGDIObj);
1532 case GDI_OBJECT_TYPE_REGION:
1533 DC_UnlockDc ( hDC );
1534 SelectClipRgn(hDC, (HRGN)hGDIObj);
1544 DC_SET_MODE( NtGdiSetBkMode, w.backgroundMode, TRANSPARENT, OPAQUE )
1545 DC_SET_MODE( NtGdiSetPolyFillMode, w.polyFillMode, ALTERNATE, WINDING )
1546 // DC_SET_MODE( NtGdiSetRelAbs, w.relAbsMode, ABSOLUTE, RELATIVE )
1547 DC_SET_MODE( NtGdiSetROP2, w.ROPmode, R2_BLACK, R2_WHITE )
1548 DC_SET_MODE( NtGdiSetStretchBltMode, w.stretchBltMode, BLACKONWHITE, HALFTONE )
1550 // ---------------------------------------------------- Private Interface
1553 DC_AllocDC(LPCWSTR Driver)
1558 hDC = (HDC) GDIOBJ_AllocObj(sizeof(DC), GDI_OBJECT_TYPE_DC, (GDICLEANUPPROC) DC_InternalDeleteDC);
1564 NewDC = DC_LockDc(hDC);
1568 NewDC->DriverName = ExAllocatePool(PagedPool, (wcslen(Driver) + 1) * sizeof(WCHAR));
1569 wcscpy(NewDC->DriverName, Driver);
1572 NewDC->w.xformWorld2Wnd.eM11 = 1.0f;
1573 NewDC->w.xformWorld2Wnd.eM12 = 0.0f;
1574 NewDC->w.xformWorld2Wnd.eM21 = 0.0f;
1575 NewDC->w.xformWorld2Wnd.eM22 = 1.0f;
1576 NewDC->w.xformWorld2Wnd.eDx = 0.0f;
1577 NewDC->w.xformWorld2Wnd.eDy = 0.0f;
1578 NewDC->w.xformWorld2Vport = NewDC->w.xformWorld2Wnd;
1579 NewDC->w.xformVport2World = NewDC->w.xformWorld2Wnd;
1580 NewDC->w.vport2WorldValid = TRUE;
1582 NewDC->w.hFont = NtGdiGetStockObject(SYSTEM_FONT);
1583 TextIntRealizeFont(NewDC->w.hFont);
1591 DC_FindOpenDC(LPCWSTR Driver)
1597 * Initialize some common fields in the Device Context structure.
1600 DC_InitDC(HDC DCHandle)
1602 // NtGdiRealizeDefaultPalette(DCHandle);
1604 NtGdiSelectObject(DCHandle, NtGdiGetStockObject( WHITE_BRUSH ));
1605 NtGdiSelectObject(DCHandle, NtGdiGetStockObject( BLACK_PEN ));
1606 //NtGdiSelectObject(DCHandle, hFont);
1608 // CLIPPING_UpdateGCRegion(DCToInit);
1613 DC_FreeDC(HDC DCToFree)
1615 if (!GDIOBJ_FreeObj(DCToFree, GDI_OBJECT_TYPE_DC, GDIOBJFLAG_DEFAULT))
1617 DPRINT("DC_FreeDC failed\n");
1622 DC_InternalDeleteDC( PDC DCToDelete )
1624 if( DCToDelete->DriverName )
1626 ExFreePool(DCToDelete->DriverName);
1633 DC_GetNextDC (PDC pDC)
1639 DC_SetNextDC (PDC pDC, HDC hNextDC)
1641 pDC->hNext = hNextDC;
1645 DC_UpdateXforms(PDC dc)
1647 XFORM xformWnd2Vport;
1648 FLOAT scaleX, scaleY;
1650 /* Construct a transformation to do the window-to-viewport conversion */
1651 scaleX = (FLOAT)dc->vportExtX / (FLOAT)dc->wndExtX;
1652 scaleY = (FLOAT)dc->vportExtY / (FLOAT)dc->wndExtY;
1653 xformWnd2Vport.eM11 = scaleX;
1654 xformWnd2Vport.eM12 = 0.0;
1655 xformWnd2Vport.eM21 = 0.0;
1656 xformWnd2Vport.eM22 = scaleY;
1657 xformWnd2Vport.eDx = (FLOAT)dc->vportOrgX - scaleX * (FLOAT)dc->wndOrgX;
1658 xformWnd2Vport.eDy = (FLOAT)dc->vportOrgY - scaleY * (FLOAT)dc->wndOrgY;
1660 /* Combine with the world transformation */
1661 NtGdiCombineTransform(&dc->w.xformWorld2Vport, &dc->w.xformWorld2Wnd, &xformWnd2Vport);
1663 /* Create inverse of world-to-viewport transformation */
1664 dc->w.vport2WorldValid = DC_InvertXform(&dc->w.xformWorld2Vport, &dc->w.xformVport2World);
1668 DC_InvertXform(const XFORM *xformSrc,
1673 determinant = xformSrc->eM11*xformSrc->eM22 - xformSrc->eM12*xformSrc->eM21;
1674 if (determinant > -1e-12 && determinant < 1e-12)
1679 xformDest->eM11 = xformSrc->eM22 / determinant;
1680 xformDest->eM12 = -xformSrc->eM12 / determinant;
1681 xformDest->eM21 = -xformSrc->eM21 / determinant;
1682 xformDest->eM22 = xformSrc->eM11 / determinant;
1683 xformDest->eDx = -xformSrc->eDx * xformDest->eM11 - xformSrc->eDy * xformDest->eM21;
1684 xformDest->eDy = -xformSrc->eDx * xformDest->eM12 - xformSrc->eDy * xformDest->eM22;