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"
22 #include <include/inteng.h>
25 #include <win32k/debug1.h>
27 static GDIDEVICE PrimarySurface;
28 static BOOL PrimarySurfaceCreated = FALSE;
30 /* FIXME: DCs should probably be thread safe */
33 * DC device-independent Get/SetXXX functions
34 * (RJJ) swiped from WINE
37 #define DC_GET_VAL( func_type, func_name, dc_field ) \
38 func_type STDCALL func_name( HDC hdc ) \
41 PDC dc = DC_HandleToPtr( hdc ); \
47 DC_ReleasePtr( hdc ); \
51 /* DC_GET_VAL_EX is used to define functions returning a POINT or a SIZE. It is
52 * important that the function has the right signature, for the implementation
53 * we can do whatever we want.
55 #define DC_GET_VAL_EX( func_name, ret_x, ret_y, type ) \
56 BOOL STDCALL func_name( HDC hdc, LP##type pt ) \
58 PDC dc = DC_HandleToPtr( hdc ); \
63 ((LPPOINT)pt)->x = dc->ret_x; \
64 ((LPPOINT)pt)->y = dc->ret_y; \
65 DC_ReleasePtr( hdc ); \
69 #define DC_SET_MODE( func_name, dc_field, min_val, max_val ) \
70 INT STDCALL func_name( HDC hdc, INT mode ) \
73 PDC dc = DC_HandleToPtr( hdc ); \
78 if ((mode < min_val) || (mode > max_val)) \
82 prevMode = dc->dc_field; \
83 dc->dc_field = mode; \
84 DC_ReleasePtr( hdc ); \
89 // --------------------------------------------------------- File Statics
91 static void W32kSetDCState16(HDC hDC, HDC hDCSave);
93 // ----------------------------------------------------- Public Functions
95 BOOL STDCALL W32kCancelDC(HDC hDC)
100 HDC STDCALL W32kCreateCompatableDC(HDC hDC)
102 PDC NewDC, OrigDC = NULL;
106 OrigDC = DC_HandleToPtr(hDC);
109 hNewDC = DC_AllocDC(L"DISPLAY");
111 NewDC = DC_HandleToPtr( hNewDC );
114 /* Allocate a new DC based on the original DC's device */
115 hNewDC = DC_AllocDC(OrigDC->DriverName);
117 NewDC = DC_HandleToPtr( hNewDC );
125 /* Copy information from original DC to new DC */
126 NewDC->hSelf = NewDC;
128 /* FIXME: Should this DC request its own PDEV? */
131 NewDC->PDev = OrigDC->PDev;
132 NewDC->DMW = OrigDC->DMW;
133 memcpy(NewDC->FillPatternSurfaces,
134 OrigDC->FillPatternSurfaces,
135 sizeof OrigDC->FillPatternSurfaces);
136 NewDC->GDIInfo = OrigDC->GDIInfo;
137 NewDC->DevInfo = OrigDC->DevInfo;
140 /* DriverName is copied in the AllocDC routine */
142 NewDC->DeviceDriver = DRIVER_FindMPDriver(NewDC->DriverName);
144 NewDC->DeviceDriver = OrigDC->DeviceDriver;
145 NewDC->wndOrgX = OrigDC->wndOrgX;
146 NewDC->wndOrgY = OrigDC->wndOrgY;
147 NewDC->wndExtX = OrigDC->wndExtX;
148 NewDC->wndExtY = OrigDC->wndExtY;
149 NewDC->vportOrgX = OrigDC->vportOrgX;
150 NewDC->vportOrgY = OrigDC->vportOrgY;
151 NewDC->vportExtX = OrigDC->vportExtX;
152 NewDC->vportExtY = OrigDC->vportExtY;
155 /* Create default bitmap */
156 if (!(hBitmap = W32kCreateBitmap( 1, 1, 1, 1, NULL )))
158 DC_ReleasePtr( hNewDC );
162 NewDC->w.flags = DC_MEMORY;
163 NewDC->w.bitsPerPixel = 1;
164 NewDC->w.hBitmap = hBitmap;
165 NewDC->w.hFirstBitmap = hBitmap;
166 NewDC->Surface = BitmapToSurf(BITMAPOBJ_HandleToPtr(hBitmap));
170 NewDC->w.hPalette = OrigDC->w.hPalette;
171 NewDC->w.textColor = OrigDC->w.textColor;
172 NewDC->w.textAlign = OrigDC->w.textAlign;
174 DC_ReleasePtr( hDC );
175 DC_ReleasePtr( hNewDC );
181 static BOOL STDCALL FindDriverFileNames(PUNICODE_STRING DriverFileNames)
183 RTL_QUERY_REGISTRY_TABLE QueryTable[2];
184 UNICODE_STRING RegistryPath;
187 RtlInitUnicodeString(&RegistryPath, NULL);
188 RtlZeroMemory(QueryTable, sizeof(QueryTable));
189 QueryTable[0].Flags = RTL_QUERY_REGISTRY_REQUIRED | RTL_QUERY_REGISTRY_DIRECT;
190 QueryTable[0].Name = L"\\Device\\Video0";
191 QueryTable[0].EntryContext = &RegistryPath;
193 Status = RtlQueryRegistryValues(RTL_REGISTRY_DEVICEMAP,
198 if (! NT_SUCCESS(Status))
200 DPRINT1("No \\Device\\Video0 value in DEVICEMAP\\VIDEO found\n");
204 DPRINT("RegistryPath %S\n", RegistryPath.Buffer);
206 QueryTable[0].Name = L"InstalledDisplayDrivers";
207 QueryTable[0].EntryContext = DriverFileNames;
209 Status = RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE,
214 RtlFreeUnicodeString(&RegistryPath);
215 if (! NT_SUCCESS(Status))
217 DPRINT1("No InstalledDisplayDrivers value in service entry found\n");
221 DPRINT("DriverFileNames %S\n", DriverFileNames->Buffer);
226 BOOL STDCALL W32kCreatePrimarySurface(LPCWSTR Driver,
229 PGD_ENABLEDRIVER GDEnableDriver;
233 UNICODE_STRING DriverFileNames;
237 /* Open the miniport driver */
238 if ((DeviceDriver = DRIVER_FindMPDriver(Driver)) == NULL)
240 DPRINT("FindMPDriver failed\n");
244 /* Retrieve DDI driver names from registry */
245 RtlInitUnicodeString(&DriverFileNames, NULL);
246 if (! FindDriverFileNames(&DriverFileNames))
248 DPRINT("FindDriverFileNames failed\n");
252 /* DriverFileNames may be a list of drivers in REG_SZ_MULTI format, scan all of
253 them until a good one found */
254 CurrentName = DriverFileNames.Buffer;
256 while (! GotDriver && CurrentName < DriverFileNames.Buffer + DriverFileNames.Length)
258 /* Get the DDI driver's entry point */
259 GDEnableDriver = DRIVER_FindDDIDriver(CurrentName);
260 if (NULL == GDEnableDriver)
262 DPRINT("FindDDIDriver failed for %S\n", CurrentName);
266 /* Call DDI driver's EnableDriver function */
267 RtlZeroMemory(&DED, sizeof(DED));
269 if (!GDEnableDriver(DDI_DRIVER_VERSION, sizeof(DED), &DED))
271 DPRINT("DrvEnableDriver failed for %S\n", CurrentName);
281 /* Skip to the next name but never get past the Unicode string */
282 while (L'\0' != *CurrentName &&
283 CurrentName < DriverFileNames.Buffer + DriverFileNames.Length)
287 if (CurrentName < DriverFileNames.Buffer + DriverFileNames.Length)
293 RtlFreeUnicodeString(&DriverFileNames);
296 DPRINT("No suitable driver found\n");
300 DPRINT("Display driver %S loaded\n", DriverName);
302 DPRINT("Building DDI Functions\n");
304 /* Construct DDI driver function dispatch table */
305 if (!DRIVER_BuildDDIFunctions(&DED, &PrimarySurface.DriverFunctions))
307 DPRINT("BuildDDIFunctions failed\n");
311 /* Allocate a phyical device handle from the driver */
314 DPRINT("Device in u: %u\n", Device);
315 // wcsncpy(NewDC->DMW.dmDeviceName, Device, DMMAXDEVICENAME); FIXME: this crashes everything?
318 DPRINT("Enabling PDev\n");
320 PrimarySurface.PDev =
321 PrimarySurface.DriverFunctions.EnablePDev(&PrimarySurface.DMW,
324 PrimarySurface.FillPatterns,
325 sizeof(PrimarySurface.GDIInfo),
326 (ULONG *) &PrimarySurface.GDIInfo,
327 sizeof(PrimarySurface.DevInfo),
328 &PrimarySurface.DevInfo,
332 if (PrimarySurface.PDev == NULL)
334 DPRINT("DrvEnablePDEV failed\n");
338 DPRINT("calling completePDev\n");
340 /* Complete initialization of the physical device */
341 PrimarySurface.DriverFunctions.CompletePDev(PrimarySurface.PDev,
344 DPRINT("calling DRIVER_ReferenceDriver\n");
346 DRIVER_ReferenceDriver (Driver);
348 DPRINT("calling EnableSurface\n");
350 /* Enable the drawing surface */
351 PrimarySurface.Handle =
352 PrimarySurface.DriverFunctions.EnableSurface(PrimarySurface.PDev);
354 SurfObj = (PSURFOBJ)AccessUserObject((ULONG) PrimarySurface.Handle);
355 SurfObj->dhpdev = PrimarySurface.PDev;
360 HDC STDCALL W32kCreateDC(LPCWSTR Driver,
363 CONST PDEVMODEW InitData)
370 /* Check for existing DC object */
371 if ((hNewDC = DC_FindOpenDC(Driver)) != NULL)
374 return W32kCreateCompatableDC(hDC);
377 DPRINT("NAME: %S\n", Driver); // FIXME: Should not crash if NULL
379 /* Allocate a DC object */
380 if ((hNewDC = DC_AllocDC(Driver)) == NULL)
385 NewDC = DC_HandleToPtr( hNewDC );
388 if (!PrimarySurfaceCreated)
390 if (!W32kCreatePrimarySurface(Driver, Device))
392 DC_ReleasePtr( hNewDC );
397 PrimarySurfaceCreated = TRUE;
398 NewDC->DMW = PrimarySurface.DMW;
399 NewDC->DevInfo = PrimarySurface.DevInfo;
400 NewDC->GDIInfo = PrimarySurface.GDIInfo;
401 memcpy(NewDC->FillPatternSurfaces, PrimarySurface.FillPatterns,
402 sizeof(NewDC->FillPatternSurfaces));
403 NewDC->PDev = PrimarySurface.PDev;
404 NewDC->Surface = PrimarySurface.Handle;
405 NewDC->DriverFunctions = PrimarySurface.DriverFunctions;
407 NewDC->DMW.dmSize = sizeof(NewDC->DMW);
408 NewDC->DMW.dmFields = 0x000fc000;
410 /* FIXME: get mode selection information from somewhere */
412 NewDC->DMW.dmLogPixels = 96;
413 SurfGDI = (PSURFGDI)AccessInternalObject((ULONG) PrimarySurface.Handle);
414 NewDC->DMW.dmBitsPerPel = SurfGDI->BitsPerPixel;
415 NewDC->DMW.dmPelsWidth = SurfGDI->SurfObj.sizlBitmap.cx;
416 NewDC->DMW.dmPelsHeight = SurfGDI->SurfObj.sizlBitmap.cy;
417 NewDC->DMW.dmDisplayFlags = 0;
418 NewDC->DMW.dmDisplayFrequency = 0;
420 NewDC->w.bitsPerPixel = SurfGDI->BitsPerPixel; // FIXME: set this here??
422 NewDC->w.hPalette = NewDC->DevInfo.hpalDefault;
424 DPRINT("Bits per pel: %u\n", NewDC->w.bitsPerPixel);
426 NewDC->w.hVisRgn = W32kCreateRectRgn(0, 0, SurfGDI->SurfObj.sizlBitmap.cx,
427 SurfGDI->SurfObj.sizlBitmap.cy);
428 DC_ReleasePtr( hNewDC );
430 /* Initialize the DC state */
432 W32kSetTextColor(hNewDC, RGB(0, 0, 0));
433 W32kSetTextAlign(hNewDC, TA_TOP);
438 HDC STDCALL W32kCreateIC(LPCWSTR Driver,
441 CONST PDEVMODEW DevMode)
443 /* FIXME: this should probably do something else... */
444 return W32kCreateDC(Driver, Device, Output, DevMode);
447 BOOL STDCALL W32kDeleteDC(HDC DCHandle)
451 DCToDelete = DC_HandleToPtr(DCHandle);
452 if (DCToDelete == NULL)
456 DPRINT( "Deleting DC\n" );
457 if ((!(DCToDelete->w.flags & DC_MEMORY))) // Don't reset the display if its a memory DC
459 if (!DRIVER_UnreferenceDriver (DCToDelete->DriverName))
461 DPRINT( "No more references to driver, reseting display\n" );
462 DCToDelete->DriverFunctions.DisableSurface(DCToDelete->PDev);
464 DCToDelete->DriverFunctions.AssertMode( DCToDelete->PDev, FALSE );
466 DCToDelete->DriverFunctions.DisablePDev(DCToDelete->PDev);
467 PrimarySurfaceCreated = FALSE;
471 /* First delete all saved DCs */
472 while (DCToDelete->saveLevel)
477 savedHDC = DC_GetNextDC (DCToDelete);
478 savedDC = DC_HandleToPtr (savedHDC);
483 DC_SetNextDC (DCToDelete, DC_GetNextDC (savedDC));
484 DCToDelete->saveLevel--;
485 DC_ReleasePtr( savedHDC );
486 W32kDeleteDC (savedHDC);
489 /* Free GDI resources allocated to this DC */
490 if (!(DCToDelete->w.flags & DC_SAVED))
493 W32kSelectObject (DCHandle, STOCK_BLACK_PEN);
494 W32kSelectObject (DCHandle, STOCK_WHITE_BRUSH);
495 W32kSelectObject (DCHandle, STOCK_SYSTEM_FONT);
496 DC_LockDC (DCHandle); W32kSelectObject does not recognize stock objects yet */
497 BITMAPOBJ_ReleasePtr(DCToDelete->w.hBitmap);
498 if (DCToDelete->w.flags & DC_MEMORY)
500 EngDeleteSurface (DCToDelete->Surface);
501 W32kDeleteObject (DCToDelete->w.hFirstBitmap);
504 if (DCToDelete->w.hClipRgn)
506 W32kDeleteObject (DCToDelete->w.hClipRgn);
508 if (DCToDelete->w.hVisRgn)
510 W32kDeleteObject (DCToDelete->w.hVisRgn);
512 if (DCToDelete->w.hGCClipRgn)
514 W32kDeleteObject (DCToDelete->w.hGCClipRgn);
517 PATH_DestroyGdiPath (&DCToDelete->w.path);
519 DC_ReleasePtr( DCToDelete );
520 DC_FreeDC (DCToDelete);
525 INT STDCALL W32kDrawEscape(HDC hDC,
533 INT STDCALL W32kEnumObjects(HDC hDC,
535 GOBJENUMPROC ObjectFunc,
541 DC_GET_VAL( COLORREF, W32kGetBkColor, w.backgroundColor )
542 DC_GET_VAL( INT, W32kGetBkMode, w.backgroundMode )
543 DC_GET_VAL_EX( W32kGetBrushOrgEx, w.brushOrgX, w.brushOrgY, POINT )
544 DC_GET_VAL( HRGN, W32kGetClipRgn, w.hClipRgn )
546 HGDIOBJ STDCALL W32kGetCurrentObject(HDC hDC,
552 DC_GET_VAL_EX( W32kGetCurrentPositionEx, w.CursPosX, w.CursPosY, POINT )
554 BOOL STDCALL W32kGetDCOrgEx(HDC hDC,
563 dc = DC_HandleToPtr(hDC);
569 Point->x = Point->y = 0;
571 Point->x += dc->w.DCOrgX;
572 Point->y += dc->w.DCOrgY;
573 DC_ReleasePtr( hDC );
577 HDC STDCALL W32kGetDCState16(HDC hDC)
582 dc = DC_HandleToPtr(hDC);
588 hnewdc = DC_AllocDC(NULL);
591 DC_ReleasePtr( hDC );
594 newdc = DC_HandleToPtr( hnewdc );
597 newdc->w.flags = dc->w.flags | DC_SAVED;
599 newdc->w.devCaps = dc->w.devCaps;
601 newdc->w.hPen = dc->w.hPen;
602 newdc->w.hBrush = dc->w.hBrush;
603 newdc->w.hFont = dc->w.hFont;
604 newdc->w.hBitmap = dc->w.hBitmap;
605 newdc->w.hFirstBitmap = dc->w.hFirstBitmap;
607 newdc->w.hDevice = dc->w.hDevice;
608 newdc->w.hPalette = dc->w.hPalette;
610 newdc->w.totalExtent = dc->w.totalExtent;
611 newdc->w.bitsPerPixel = dc->w.bitsPerPixel;
612 newdc->w.ROPmode = dc->w.ROPmode;
613 newdc->w.polyFillMode = dc->w.polyFillMode;
614 newdc->w.stretchBltMode = dc->w.stretchBltMode;
615 newdc->w.relAbsMode = dc->w.relAbsMode;
616 newdc->w.backgroundMode = dc->w.backgroundMode;
617 newdc->w.backgroundColor = dc->w.backgroundColor;
618 newdc->w.textColor = dc->w.textColor;
619 newdc->w.brushOrgX = dc->w.brushOrgX;
620 newdc->w.brushOrgY = dc->w.brushOrgY;
621 newdc->w.textAlign = dc->w.textAlign;
622 newdc->w.charExtra = dc->w.charExtra;
623 newdc->w.breakTotalExtra = dc->w.breakTotalExtra;
624 newdc->w.breakCount = dc->w.breakCount;
625 newdc->w.breakExtra = dc->w.breakExtra;
626 newdc->w.breakRem = dc->w.breakRem;
627 newdc->w.MapMode = dc->w.MapMode;
628 newdc->w.GraphicsMode = dc->w.GraphicsMode;
630 /* Apparently, the DC origin is not changed by [GS]etDCState */
631 newdc->w.DCOrgX = dc->w.DCOrgX;
632 newdc->w.DCOrgY = dc->w.DCOrgY;
634 newdc->w.CursPosX = dc->w.CursPosX;
635 newdc->w.CursPosY = dc->w.CursPosY;
636 newdc->w.ArcDirection = dc->w.ArcDirection;
638 newdc->w.xformWorld2Wnd = dc->w.xformWorld2Wnd;
639 newdc->w.xformWorld2Vport = dc->w.xformWorld2Vport;
640 newdc->w.xformVport2World = dc->w.xformVport2World;
641 newdc->w.vport2WorldValid = dc->w.vport2WorldValid;
643 newdc->wndOrgX = dc->wndOrgX;
644 newdc->wndOrgY = dc->wndOrgY;
645 newdc->wndExtX = dc->wndExtX;
646 newdc->wndExtY = dc->wndExtY;
647 newdc->vportOrgX = dc->vportOrgX;
648 newdc->vportOrgY = dc->vportOrgY;
649 newdc->vportExtX = dc->vportExtX;
650 newdc->vportExtY = dc->vportExtY;
652 newdc->hSelf = hnewdc;
653 newdc->saveLevel = 0;
656 PATH_InitGdiPath( &newdc->w.path );
659 /* Get/SetDCState() don't change hVisRgn field ("Undoc. Windows" p.559). */
662 newdc->w.hGCClipRgn = newdc->w.hVisRgn = 0;
666 newdc->w.hClipRgn = W32kCreateRectRgn( 0, 0, 0, 0 );
667 W32kCombineRgn( newdc->w.hClipRgn, dc->w.hClipRgn, 0, RGN_COPY );
671 newdc->w.hClipRgn = 0;
673 DC_ReleasePtr( hnewdc );
677 INT STDCALL W32kGetDeviceCaps(HDC hDC,
684 dc = DC_HandleToPtr(hDC);
690 /* Device capabilities for the printer */
694 if(W32kEscape(hDC, GETPHYSPAGESIZE, 0, NULL, (LPVOID)&pt) > 0)
701 if(W32kEscape(hDC, GETPHYSPAGESIZE, 0, NULL, (LPVOID)&pt) > 0)
707 case PHYSICALOFFSETX:
708 if(W32kEscape(hDC, GETPRINTINGOFFSET, 0, NULL, (LPVOID)&pt) > 0)
714 case PHYSICALOFFSETY:
715 if(W32kEscape(hDC, GETPRINTINGOFFSET, 0, NULL, (LPVOID)&pt) > 0)
722 if(W32kEscape(hDC, GETSCALINGFACTOR, 0, NULL, (LPVOID)&pt) > 0)
729 if(W32kEscape(hDC, GETSCALINGFACTOR, 0, NULL, (LPVOID)&pt) > 0)
736 if ((Index < 0) || (Index > sizeof(DEVICECAPS) - sizeof(WORD)))
741 DPRINT("(%04x,%d): returning %d\n",
742 hDC, Index, *(WORD *)(((char *)dc->w.devCaps) + Index));
743 ret = *(WORD *)(((char *)dc->w.devCaps) + Index);
745 DC_ReleasePtr( hDC );
749 DC_GET_VAL( INT, W32kGetMapMode, w.MapMode )
750 DC_GET_VAL( INT, W32kGetPolyFillMode, w.polyFillMode )
752 INT STDCALL W32kGetObjectA(HANDLE handle, INT count, LPVOID buffer)
760 gdiObject = GDIOBJ_LockObj (handle, GO_MAGIC_DONTCARE);
764 magic = GDIOBJ_GetHandleMagic (handle);
767 /* case GO_PEN_MAGIC:
768 result = PEN_GetObject((PENOBJ *)gdiObject, count, buffer);
771 result = BRUSH_GetObject((BRUSHOBJ *)gdiObject, count, buffer);
773 case GO_BITMAP_MAGIC:
774 result = BITMAP_GetObject((BITMAPOBJ *)gdiObject, count, buffer);
776 /* case GO_FONT_MAGIC:
777 result = FONT_GetObjectA((FONTOBJ *)gdiObject, count, buffer);
779 // FIXME: Fix the LOGFONT structure for the stock fonts
781 if ( (handle >= FIRST_STOCK_HANDLE) && (handle <= LAST_STOCK_HANDLE) )
782 FixStockFontSizeA(handle, count, buffer);
784 case GO_PALETTE_MAGIC:
785 result = PALETTE_GetObject((PALETTEOBJ *)gdiObject, count, buffer);
788 case GO_REGION_MAGIC:
790 case GO_DISABLED_DC_MAGIC:
791 case GO_META_DC_MAGIC:
792 case GO_METAFILE_MAGIC:
793 case GO_METAFILE_DC_MAGIC:
794 case GO_ENHMETAFILE_MAGIC:
795 case GO_ENHMETAFILE_DC_MAGIC:
796 // FIXME("Magic %04x not implemented\n", magic);
800 DbgPrint("Invalid GDI Magic %04x\n", magic);
803 GDIOBJ_UnlockObj (handle, GO_MAGIC_DONTCARE);
807 INT STDCALL W32kGetObjectW(HANDLE handle, INT count, LPVOID buffer)
809 PGDIOBJHDR gdiObject;
815 gdiObject = GDIOBJ_LockObj(handle, GO_MAGIC_DONTCARE);
819 magic = GDIOBJ_GetHandleMagic (handle);
822 /* case GO_PEN_MAGIC:
823 result = PEN_GetObject((PENOBJ *)gdiObject, count, buffer);
826 result = BRUSH_GetObject((BRUSHOBJ *)gdiObject, count, buffer);
828 case GO_BITMAP_MAGIC:
829 result = BITMAP_GetObject((BITMAPOBJ *)gdiObject, count, buffer);
831 /* case GO_FONT_MAGIC:
832 result = FONT_GetObjectW((FONTOBJ *)gdiObject, count, buffer);
834 // Fix the LOGFONT structure for the stock fonts
836 if ( (handle >= FIRST_STOCK_HANDLE) && (handle <= LAST_STOCK_HANDLE) )
837 FixStockFontSizeW(handle, count, buffer);
839 case GO_PALETTE_MAGIC:
840 result = PALETTE_GetObject((PALETTEOBJ *)gdiObject, count, buffer);
843 // FIXME("Magic %04x not implemented\n", gdiObject->magic);
846 GDIOBJ_UnlockObj(handle, GO_MAGIC_DONTCARE);
850 INT STDCALL W32kGetObject(HANDLE handle, INT count, LPVOID buffer)
852 return W32kGetObjectW(handle, count, buffer);
855 DWORD STDCALL W32kGetObjectType(HANDLE handle)
861 ptr = GDIOBJ_LockObj(handle, GO_MAGIC_DONTCARE);
865 magic = GDIOBJ_GetHandleMagic (handle);
874 case GO_BITMAP_MAGIC:
880 case GO_PALETTE_MAGIC:
883 case GO_REGION_MAGIC:
889 case GO_META_DC_MAGIC:
892 case GO_METAFILE_MAGIC:
893 result = OBJ_METAFILE;
895 case GO_METAFILE_DC_MAGIC:
898 case GO_ENHMETAFILE_MAGIC:
899 result = OBJ_ENHMETAFILE;
901 case GO_ENHMETAFILE_DC_MAGIC:
902 result = OBJ_ENHMETADC;
905 // FIXME("Magic %04x not implemented\n", magic);
908 GDIOBJ_UnlockObj(handle, GO_MAGIC_DONTCARE);
912 DC_GET_VAL( INT, W32kGetRelAbs, w.relAbsMode )
913 DC_GET_VAL( INT, W32kGetROP2, w.ROPmode )
914 DC_GET_VAL( INT, W32kGetStretchBltMode, w.stretchBltMode )
915 DC_GET_VAL( UINT, W32kGetTextAlign, w.textAlign )
916 DC_GET_VAL( COLORREF, W32kGetTextColor, w.textColor )
917 DC_GET_VAL_EX( W32kGetViewportExtEx, vportExtX, vportExtY, SIZE )
918 DC_GET_VAL_EX( W32kGetViewportOrgEx, vportOrgX, vportOrgY, POINT )
919 DC_GET_VAL_EX( W32kGetWindowExtEx, wndExtX, wndExtY, SIZE )
920 DC_GET_VAL_EX( W32kGetWindowOrgEx, wndOrgX, wndOrgY, POINT )
922 HDC STDCALL W32kResetDC(HDC hDC, CONST DEVMODEW *InitData)
927 BOOL STDCALL W32kRestoreDC(HDC hDC, INT SaveLevel)
932 dc = DC_HandleToPtr(hDC);
940 SaveLevel = dc->saveLevel;
943 if ((SaveLevel < 1) || (SaveLevel > dc->saveLevel))
949 while (dc->saveLevel >= SaveLevel)
951 HDC hdcs = DC_GetNextDC (dc);
953 dcs = DC_HandleToPtr (hdcs);
958 DC_SetNextDC (dcs, DC_GetNextDC (dcs));
959 if (--dc->saveLevel < SaveLevel)
961 W32kSetDCState16 (hDC, hdcs);
963 if (!PATH_AssignGdiPath( &dc->w.path, &dcs->w.path ))
965 /* FIXME: This might not be quite right, since we're
966 * returning FALSE but still destroying the saved DC state */
971 DC_ReleasePtr( hdcs );
974 DC_ReleasePtr( hDC );
978 INT STDCALL W32kSaveDC(HDC hDC)
984 dc = DC_HandleToPtr (hDC);
990 if (!(hdcs = W32kGetDCState16 (hDC)))
994 dcs = DC_HandleToPtr (hdcs);
997 /* Copy path. The reason why path saving / restoring is in SaveDC/
998 * RestoreDC and not in GetDCState/SetDCState is that the ...DCState
999 * functions are only in Win16 (which doesn't have paths) and that
1000 * SetDCState doesn't allow us to signal an error (which can happen
1001 * when copying paths).
1003 if (!PATH_AssignGdiPath (&dcs->w.path, &dc->w.path))
1005 W32kDeleteDC (hdcs);
1010 DC_SetNextDC (dcs, DC_GetNextDC (dc));
1011 DC_SetNextDC (dc, hdcs);
1012 ret = ++dc->saveLevel;
1013 DC_ReleasePtr( hdcs );
1014 DC_ReleasePtr( hDC );
1019 HGDIOBJ STDCALL W32kSelectObject(HDC hDC, HGDIOBJ hGDIObj)
1030 ULONG NumColors, Index;
1032 if(!hDC || !hGDIObj) return NULL;
1034 dc = DC_HandleToPtr(hDC);
1035 objectMagic = GDIOBJ_GetHandleMagic (hGDIObj);
1036 // GdiObjHdr = hGDIObj;
1038 // FIXME: Get object handle from GDIObj and use it instead of GDIObj below?
1040 switch(objectMagic) {
1042 objOrg = (HGDIOBJ)dc->w.hPen;
1043 dc->w.hPen = hGDIObj;
1045 // Convert the color of the pen to the format of the DC
1046 PalGDI = (PPALGDI)AccessInternalObject((ULONG) dc->w.hPalette);
1048 XlateObj = (PXLATEOBJ)IntEngCreateXlate(PalGDI->Mode, PAL_RGB, dc->w.hPalette, NULL);
1049 pen = GDIOBJ_LockObj(dc->w.hPen, GO_PEN_MAGIC);
1051 pen->logpen.lopnColor = XLATEOBJ_iXlate(XlateObj, pen->logpen.lopnColor);
1053 GDIOBJ_UnlockObj( dc->w.hPen, GO_PEN_MAGIC);
1054 EngDeleteXlate(XlateObj);
1058 case GO_BRUSH_MAGIC:
1059 objOrg = (HGDIOBJ)dc->w.hBrush;
1060 dc->w.hBrush = (HBRUSH) hGDIObj;
1062 // Convert the color of the brush to the format of the DC
1063 PalGDI = (PPALGDI)AccessInternalObject((ULONG) dc->w.hPalette);
1065 XlateObj = (PXLATEOBJ)IntEngCreateXlate(PalGDI->Mode, PAL_RGB, dc->w.hPalette, NULL);
1066 brush = GDIOBJ_LockObj(dc->w.hBrush, GO_BRUSH_MAGIC);
1068 brush->iSolidColor = XLATEOBJ_iXlate(XlateObj, brush->logbrush.lbColor);
1070 GDIOBJ_UnlockObj( dc->w.hBrush, GO_BRUSH_MAGIC);
1071 EngDeleteXlate(XlateObj);
1076 objOrg = (HGDIOBJ)dc->w.hFont;
1077 dc->w.hFont = (HFONT) hGDIObj;
1078 TextIntRealizeFont(dc->w.hFont);
1081 case GO_BITMAP_MAGIC:
1082 // must be memory dc to select bitmap
1083 if (!(dc->w.flags & DC_MEMORY)) return NULL;
1084 objOrg = (HGDIOBJ)dc->w.hBitmap;
1086 /* Release the old bitmap, lock the new one and convert it to a SURF */
1087 EngDeleteSurface(dc->Surface);
1088 BITMAPOBJ_ReleasePtr(objOrg);
1089 dc->w.hBitmap = hGDIObj;
1090 pb = BITMAPOBJ_HandleToPtr(hGDIObj);
1091 dc->Surface = BitmapToSurf(pb);
1093 // if we're working with a DIB, get the palette [fixme: only create if the selected palette is null]
1096 dc->w.bitsPerPixel = pb->dib->dsBmih.biBitCount;
1098 if(pb->dib->dsBmih.biBitCount <= 8)
1100 if(pb->dib->dsBmih.biBitCount == 1) { NumColors = 2; } else
1101 if(pb->dib->dsBmih.biBitCount == 4) { NumColors = 16; } else
1102 if(pb->dib->dsBmih.biBitCount == 8) { NumColors = 256; }
1104 ColorMap = ExAllocatePool(PagedPool, sizeof(COLORREF) * NumColors);
1105 for (Index = 0; Index < NumColors; Index++)
1107 ColorMap[Index] = RGB(pb->ColorMap[Index].rgbRed,
1108 pb->ColorMap[Index].rgbGreen,
1109 pb->ColorMap[Index].rgbBlue);
1111 dc->w.hPalette = EngCreatePalette(PAL_INDEXED, NumColors, (ULONG *) ColorMap, 0, 0, 0);
1112 ExFreePool(ColorMap);
1114 if(16 == pb->dib->dsBmih.biBitCount)
1116 dc->w.hPalette = EngCreatePalette(PAL_BITFIELDS, pb->dib->dsBmih.biClrUsed, NULL, 0x7c00, 0x03e0, 0x001f);
1118 if(pb->dib->dsBmih.biBitCount >= 24)
1120 dc->w.hPalette = EngCreatePalette(PAL_RGB, pb->dib->dsBmih.biClrUsed, NULL, 0, 0, 0);
1123 dc->w.bitsPerPixel = pb->bitmap.bmBitsPixel;
1128 case GO_REGION_MAGIC:
1129 /* objOrg = (HGDIOBJ)hDC->region; */
1130 objOrg = NULL; /* FIXME? hDC->region is destroyed below */
1131 SelectClipRgn(hDC, (HRGN)hGDIObj);
1137 DC_ReleasePtr( hDC );
1141 DC_SET_MODE( W32kSetBkMode, w.backgroundMode, TRANSPARENT, OPAQUE )
1142 DC_SET_MODE( W32kSetPolyFillMode, w.polyFillMode, ALTERNATE, WINDING )
1143 // DC_SET_MODE( W32kSetRelAbs, w.relAbsMode, ABSOLUTE, RELATIVE )
1144 DC_SET_MODE( W32kSetROP2, w.ROPmode, R2_BLACK, R2_WHITE )
1145 DC_SET_MODE( W32kSetStretchBltMode, w.stretchBltMode, BLACKONWHITE, HALFTONE )
1147 COLORREF STDCALL W32kSetBkColor(HDC hDC, COLORREF color)
1150 PDC dc = DC_HandleToPtr(hDC);
1157 oldColor = dc->w.backgroundColor;
1158 dc->w.backgroundColor = color;
1159 DC_ReleasePtr( hDC );
1163 static void W32kSetDCState16(HDC hDC, HDC hDCSave)
1167 dc = DC_HandleToPtr(hDC);
1173 dcs = DC_HandleToPtr(hDCSave);
1176 DC_ReleasePtr( hDC );
1179 if (!dcs->w.flags & DC_SAVED)
1184 dc->w.flags = dcs->w.flags & ~DC_SAVED;
1187 dc->w.devCaps = dcs->w.devCaps;
1190 dc->w.hFirstBitmap = dcs->w.hFirstBitmap;
1193 dc->w.hDevice = dcs->w.hDevice;
1196 dc->w.totalExtent = dcs->w.totalExtent;
1197 dc->w.ROPmode = dcs->w.ROPmode;
1198 dc->w.polyFillMode = dcs->w.polyFillMode;
1199 dc->w.stretchBltMode = dcs->w.stretchBltMode;
1200 dc->w.relAbsMode = dcs->w.relAbsMode;
1201 dc->w.backgroundMode = dcs->w.backgroundMode;
1202 dc->w.backgroundColor = dcs->w.backgroundColor;
1203 dc->w.textColor = dcs->w.textColor;
1204 dc->w.brushOrgX = dcs->w.brushOrgX;
1205 dc->w.brushOrgY = dcs->w.brushOrgY;
1206 dc->w.textAlign = dcs->w.textAlign;
1207 dc->w.charExtra = dcs->w.charExtra;
1208 dc->w.breakTotalExtra = dcs->w.breakTotalExtra;
1209 dc->w.breakCount = dcs->w.breakCount;
1210 dc->w.breakExtra = dcs->w.breakExtra;
1211 dc->w.breakRem = dcs->w.breakRem;
1212 dc->w.MapMode = dcs->w.MapMode;
1213 dc->w.GraphicsMode = dcs->w.GraphicsMode;
1215 /* Apparently, the DC origin is not changed by [GS]etDCState */
1216 dc->w.DCOrgX = dcs->w.DCOrgX;
1217 dc->w.DCOrgY = dcs->w.DCOrgY;
1219 dc->w.CursPosX = dcs->w.CursPosX;
1220 dc->w.CursPosY = dcs->w.CursPosY;
1221 dc->w.ArcDirection = dcs->w.ArcDirection;
1224 dc->w.xformWorld2Wnd = dcs->w.xformWorld2Wnd;
1225 dc->w.xformWorld2Vport = dcs->w.xformWorld2Vport;
1226 dc->w.xformVport2World = dcs->w.xformVport2World;
1227 dc->w.vport2WorldValid = dcs->w.vport2WorldValid;
1230 dc->wndOrgX = dcs->wndOrgX;
1231 dc->wndOrgY = dcs->wndOrgY;
1232 dc->wndExtX = dcs->wndExtX;
1233 dc->wndExtY = dcs->wndExtY;
1234 dc->vportOrgX = dcs->vportOrgX;
1235 dc->vportOrgY = dcs->vportOrgY;
1236 dc->vportExtX = dcs->vportExtX;
1237 dc->vportExtY = dcs->vportExtY;
1239 if (!(dc->w.flags & DC_MEMORY))
1241 dc->w.bitsPerPixel = dcs->w.bitsPerPixel;
1245 if (dcs->w.hClipRgn)
1247 if (!dc->w.hClipRgn)
1249 dc->w.hClipRgn = W32kCreateRectRgn( 0, 0, 0, 0 );
1251 W32kCombineRgn( dc->w.hClipRgn, dcs->w.hClipRgn, 0, RGN_COPY );
1257 W32kDeleteObject( dc->w.hClipRgn );
1262 CLIPPING_UpdateGCRegion( dc );
1265 W32kSelectObject( hDC, dcs->w.hBitmap );
1266 W32kSelectObject( hDC, dcs->w.hBrush );
1267 W32kSelectObject( hDC, dcs->w.hFont );
1268 W32kSelectObject( hDC, dcs->w.hPen );
1269 W32kSetBkColor( hDC, dcs->w.backgroundColor);
1270 W32kSetTextColor( hDC, dcs->w.textColor);
1273 GDISelectPalette16( hDC, dcs->w.hPalette, FALSE );
1276 DC_ReleasePtr( hDCSave );
1277 DC_ReleasePtr( hDC );
1280 // ---------------------------------------------------- Private Interface
1282 HDC DC_AllocDC(LPCWSTR Driver)
1287 hDC = (HDC) GDIOBJ_AllocObj(sizeof(DC), GO_DC_MAGIC);
1293 NewDC = (PDC) GDIOBJ_LockObj( hDC, GO_DC_MAGIC );
1297 NewDC->DriverName = ExAllocatePool(PagedPool, (wcslen(Driver) + 1) * sizeof(WCHAR));
1298 wcscpy(NewDC->DriverName, Driver);
1301 NewDC->w.xformWorld2Wnd.eM11 = 1.0f;
1302 NewDC->w.xformWorld2Wnd.eM12 = 0.0f;
1303 NewDC->w.xformWorld2Wnd.eM21 = 0.0f;
1304 NewDC->w.xformWorld2Wnd.eM22 = 1.0f;
1305 NewDC->w.xformWorld2Wnd.eDx = 0.0f;
1306 NewDC->w.xformWorld2Wnd.eDy = 0.0f;
1307 NewDC->w.xformWorld2Vport = NewDC->w.xformWorld2Wnd;
1308 NewDC->w.xformVport2World = NewDC->w.xformWorld2Wnd;
1309 NewDC->w.vport2WorldValid = TRUE;
1311 NewDC->w.hFont = W32kGetStockObject(SYSTEM_FONT);
1313 GDIOBJ_UnlockObj( hDC, GO_DC_MAGIC );
1317 HDC DC_FindOpenDC(LPCWSTR Driver)
1323 * Initialize some common fields in the Device Context structure.
1325 void DC_InitDC(HDC DCHandle)
1327 // W32kRealizeDefaultPalette(DCHandle);
1329 W32kSelectObject(DCHandle, W32kGetStockObject( WHITE_BRUSH ));
1330 W32kSelectObject(DCHandle, W32kGetStockObject( BLACK_PEN ));
1331 //W32kSelectObject(DCHandle, hFont);
1333 // CLIPPING_UpdateGCRegion(DCToInit);
1337 void DC_FreeDC(HDC DCToFree)
1339 if (!GDIOBJ_FreeObj(DCToFree, GO_DC_MAGIC, GDIOBJFLAG_DEFAULT))
1341 DPRINT("DC_FreeDC failed\n");
1345 BOOL DC_InternalDeleteDC( PDC DCToDelete )
1347 if( DCToDelete->DriverName )
1348 ExFreePool(DCToDelete->DriverName);
1352 HDC DC_GetNextDC (PDC pDC)
1357 void DC_SetNextDC (PDC pDC, HDC hNextDC)
1359 pDC->hNext = hNextDC;
1363 DC_UpdateXforms(PDC dc)
1365 XFORM xformWnd2Vport;
1366 FLOAT scaleX, scaleY;
1368 /* Construct a transformation to do the window-to-viewport conversion */
1369 scaleX = (FLOAT)dc->vportExtX / (FLOAT)dc->wndExtX;
1370 scaleY = (FLOAT)dc->vportExtY / (FLOAT)dc->wndExtY;
1371 xformWnd2Vport.eM11 = scaleX;
1372 xformWnd2Vport.eM12 = 0.0;
1373 xformWnd2Vport.eM21 = 0.0;
1374 xformWnd2Vport.eM22 = scaleY;
1375 xformWnd2Vport.eDx = (FLOAT)dc->vportOrgX - scaleX * (FLOAT)dc->wndOrgX;
1376 xformWnd2Vport.eDy = (FLOAT)dc->vportOrgY - scaleY * (FLOAT)dc->wndOrgY;
1378 /* Combine with the world transformation */
1379 W32kCombineTransform(&dc->w.xformWorld2Vport, &dc->w.xformWorld2Wnd, &xformWnd2Vport);
1381 /* Create inverse of world-to-viewport transformation */
1382 dc->w.vport2WorldValid = DC_InvertXform(&dc->w.xformWorld2Vport, &dc->w.xformVport2World);
1386 DC_InvertXform(const XFORM *xformSrc,
1391 determinant = xformSrc->eM11*xformSrc->eM22 - xformSrc->eM12*xformSrc->eM21;
1392 if (determinant > -1e-12 && determinant < 1e-12)
1397 xformDest->eM11 = xformSrc->eM22 / determinant;
1398 xformDest->eM12 = -xformSrc->eM12 / determinant;
1399 xformDest->eM21 = -xformSrc->eM21 / determinant;
1400 xformDest->eM22 = xformSrc->eM11 / determinant;
1401 xformDest->eDx = -xformSrc->eDx * xformDest->eM11 - xformSrc->eDy * xformDest->eM21;
1402 xformDest->eDy = -xformSrc->eDx * xformDest->eM12 - xformSrc->eDy * xformDest->eM22;