3 * DC.C - Device context functions
7 #undef WIN32_LEAN_AND_MEAN
11 #include <win32k/bitmaps.h>
12 #include <win32k/coord.h>
13 #include <win32k/driver.h>
14 #include <win32k/dc.h>
15 #include <win32k/print.h>
16 #include <win32k/region.h>
17 #include <win32k/gdiobj.h>
18 #include <win32k/pen.h>
19 #include <win32k/text.h>
20 #include "../eng/handle.h"
23 #include <win32k/debug1.h>
26 /* FIXME: DCs should probably be thread safe */
29 * DC device-independent Get/SetXXX functions
30 * (RJJ) swiped from WINE
33 #define DC_GET_VAL( func_type, func_name, dc_field ) \
34 func_type STDCALL func_name( HDC hdc ) \
37 PDC dc = DC_HandleToPtr( hdc ); \
43 DC_ReleasePtr( hdc ); \
47 /* DC_GET_VAL_EX is used to define functions returning a POINT or a SIZE. It is
48 * important that the function has the right signature, for the implementation
49 * we can do whatever we want.
51 #define DC_GET_VAL_EX( func_name, ret_x, ret_y, type ) \
52 BOOL STDCALL func_name( HDC hdc, LP##type pt ) \
54 PDC dc = DC_HandleToPtr( hdc ); \
59 ((LPPOINT)pt)->x = dc->ret_x; \
60 ((LPPOINT)pt)->y = dc->ret_y; \
61 DC_ReleasePtr( hdc ); \
65 #define DC_SET_MODE( func_name, dc_field, min_val, max_val ) \
66 INT STDCALL func_name( HDC hdc, INT mode ) \
69 PDC dc = DC_HandleToPtr( hdc ); \
74 if ((mode < min_val) || (mode > max_val)) \
78 prevMode = dc->dc_field; \
79 dc->dc_field = mode; \
80 DC_ReleasePtr( hdc ); \
85 VOID BitmapToSurf(HDC hdc, PSURFGDI SurfGDI, PSURFOBJ SurfObj, PBITMAPOBJ Bitmap);
87 // --------------------------------------------------------- File Statics
89 static void W32kSetDCState16(HDC hDC, HDC hDCSave);
91 // ----------------------------------------------------- Public Functions
93 BOOL STDCALL W32kCancelDC(HDC hDC)
98 HDC STDCALL W32kCreateCompatableDC(HDC hDC)
100 PDC NewDC, OrigDC = NULL;
105 OrigDC = DC_HandleToPtr(hDC);
108 hNewDC = DC_AllocDC(L"DISPLAY");
110 NewDC = DC_HandleToPtr( hNewDC );
113 /* Allocate a new DC based on the original DC's device */
114 hNewDC = DC_AllocDC(OrigDC->DriverName);
116 NewDC = DC_HandleToPtr( hNewDC );
124 /* Copy information from original DC to new DC */
125 NewDC->hSelf = NewDC;
127 /* FIXME: Should this DC request its own PDEV? */
130 NewDC->PDev = OrigDC->PDev;
131 NewDC->DMW = OrigDC->DMW;
132 memcpy(NewDC->FillPatternSurfaces,
133 OrigDC->FillPatternSurfaces,
134 sizeof OrigDC->FillPatternSurfaces);
135 NewDC->GDIInfo = OrigDC->GDIInfo;
136 NewDC->DevInfo = OrigDC->DevInfo;
139 // Create a 1x1 monochrome bitmap surface
142 NewDC->Surface = EngCreateBitmap(onebyone, 1, BMF_1BPP, 0, NULL);
144 /* DriverName is copied in the AllocDC routine */
146 NewDC->DeviceDriver = DRIVER_FindMPDriver(NewDC->DriverName);
148 NewDC->DeviceDriver = OrigDC->DeviceDriver;
149 NewDC->wndOrgX = OrigDC->wndOrgX;
150 NewDC->wndOrgY = OrigDC->wndOrgY;
151 NewDC->wndExtX = OrigDC->wndExtX;
152 NewDC->wndExtY = OrigDC->wndExtY;
153 NewDC->vportOrgX = OrigDC->vportOrgX;
154 NewDC->vportOrgY = OrigDC->vportOrgY;
155 NewDC->vportExtX = OrigDC->vportExtX;
156 NewDC->vportExtY = OrigDC->vportExtY;
161 /* Create default bitmap */
162 if (!(hBitmap = W32kCreateBitmap( 1, 1, 1, 1, NULL )))
164 DC_ReleasePtr( hNewDC );
168 NewDC->w.flags = DC_MEMORY;
169 NewDC->w.bitsPerPixel = 1;
170 NewDC->w.hBitmap = hBitmap;
171 NewDC->w.hFirstBitmap = hBitmap;
175 NewDC->w.hPalette = OrigDC->w.hPalette;
176 NewDC->w.textColor = OrigDC->w.textColor;
177 NewDC->w.textAlign = OrigDC->w.textAlign;
179 DC_ReleasePtr( hDC );
180 DC_ReleasePtr( hNewDC );
185 #include <ddk/ntddvid.h>
187 static GDIDEVICE PrimarySurface;
188 static BOOL PrimarySurfaceCreated = FALSE;
190 BOOL STDCALL W32kCreatePrimarySurface(LPCWSTR Driver,
193 PGD_ENABLEDRIVER GDEnableDriver;
198 /* Open the miniport driver */
199 if ((DeviceDriver = DRIVER_FindMPDriver(Driver)) == NULL)
201 DPRINT("FindMPDriver failed\n");
205 /* Get the DDI driver's entry point */
206 /* FIXME: Retrieve DDI driver name from registry */
207 if ((GDEnableDriver = DRIVER_FindDDIDriver(L"\\SystemRoot\\system32\\drivers\\vgaddi.dll")) == NULL)
209 DPRINT("FindDDIDriver failed\n");
213 /* Call DDI driver's EnableDriver function */
214 RtlZeroMemory(&DED, sizeof(DED));
216 if (!GDEnableDriver(DDI_DRIVER_VERSION, sizeof(DED), &DED))
218 DPRINT("DrvEnableDriver failed\n");
221 DPRINT("Building DDI Functions\n");
223 /* Construct DDI driver function dispatch table */
224 if (!DRIVER_BuildDDIFunctions(&DED, &PrimarySurface.DriverFunctions))
226 DPRINT("BuildDDIFunctions failed\n");
230 /* Allocate a phyical device handle from the driver */
233 DPRINT("Device in u: %u\n", Device);
234 // wcsncpy(NewDC->DMW.dmDeviceName, Device, DMMAXDEVICENAME); FIXME: this crashes everything?
237 DPRINT("Enabling PDev\n");
239 PrimarySurface.PDev =
240 PrimarySurface.DriverFunctions.EnablePDev(&PrimarySurface.DMW,
243 PrimarySurface.FillPatterns,
244 sizeof(PrimarySurface.GDIInfo),
245 (ULONG *) &PrimarySurface.GDIInfo,
246 sizeof(PrimarySurface.DevInfo),
247 &PrimarySurface.DevInfo,
251 if (PrimarySurface.PDev == NULL)
253 DPRINT("DrvEnablePDEV failed\n");
257 DPRINT("calling completePDev\n");
259 /* Complete initialization of the physical device */
260 PrimarySurface.DriverFunctions.CompletePDev(PrimarySurface.PDev,
263 DPRINT("calling DRIVER_ReferenceDriver\n");
265 DRIVER_ReferenceDriver (Driver);
267 DPRINT("calling EnableSurface\n");
269 /* Enable the drawing surface */
270 PrimarySurface.Handle =
271 PrimarySurface.DriverFunctions.EnableSurface(PrimarySurface.PDev);
273 SurfObj = (PSURFOBJ)AccessUserObject(PrimarySurface.Handle);
274 SurfObj->dhpdev = PrimarySurface.PDev;
277 HDC STDCALL W32kCreateDC(LPCWSTR Driver,
280 CONST PDEVMODEW InitData)
286 /* Check for existing DC object */
287 if ((hNewDC = DC_FindOpenDC(Driver)) != NULL)
290 return W32kCreateCompatableDC(hDC);
293 DPRINT("NAME: %S\n", Driver); // FIXME: Should not crash if NULL
295 /* Allocate a DC object */
296 if ((hNewDC = DC_AllocDC(Driver)) == NULL)
301 NewDC = DC_HandleToPtr( hNewDC );
304 if (!PrimarySurfaceCreated)
306 if (!W32kCreatePrimarySurface(Driver, Device))
308 DC_ReleasePtr( hNewDC );
313 PrimarySurfaceCreated = TRUE;
314 NewDC->DMW = PrimarySurface.DMW;
315 NewDC->DevInfo = PrimarySurface.DevInfo;
316 NewDC->GDIInfo = PrimarySurface.GDIInfo;
317 memcpy(NewDC->FillPatternSurfaces, PrimarySurface.FillPatterns,
318 sizeof(NewDC->FillPatternSurfaces));
319 NewDC->PDev = PrimarySurface.PDev;
320 NewDC->Surface = PrimarySurface.Handle;
321 NewDC->DriverFunctions = PrimarySurface.DriverFunctions;
323 NewDC->DMW.dmSize = sizeof(NewDC->DMW);
324 NewDC->DMW.dmFields = 0x000fc000;
326 /* FIXME: get mode selection information from somewhere */
328 NewDC->DMW.dmLogPixels = 96;
329 NewDC->DMW.dmBitsPerPel = 4;
330 NewDC->DMW.dmPelsWidth = 640;
331 NewDC->DMW.dmPelsHeight = 480;
332 NewDC->DMW.dmDisplayFlags = 0;
333 NewDC->DMW.dmDisplayFrequency = 0;
335 NewDC->w.bitsPerPixel = 4; // FIXME: set this here??
337 NewDC->w.hPalette = NewDC->DevInfo.hpalDefault;
339 DPRINT("Bits per pel: %u\n", NewDC->w.bitsPerPixel);
341 /* Initialize the DC state */
344 NewDC->w.hVisRgn = W32kCreateRectRgn(0, 0, 640, 480);
345 W32kSetTextColor(hNewDC, RGB(0, 0, 0));
346 W32kSetTextAlign(hNewDC, TA_TOP);
347 DC_ReleasePtr( hNewDC );
352 HDC STDCALL W32kCreateIC(LPCWSTR Driver,
355 CONST PDEVMODEW DevMode)
357 /* FIXME: this should probably do something else... */
358 return W32kCreateDC(Driver, Device, Output, DevMode);
361 BOOL STDCALL W32kDeleteDC(HDC DCHandle)
365 DCToDelete = DC_HandleToPtr(DCHandle);
366 if (DCToDelete == NULL)
370 DPRINT( "Deleting DC\n" );
371 if ((!(DCToDelete->w.flags & DC_MEMORY))) // Don't reset the display if its a memory DC
373 if (!DRIVER_UnreferenceDriver (DCToDelete->DriverName))
375 DPRINT( "No more references to driver, reseting display\n" );
376 DCToDelete->DriverFunctions.DisableSurface(DCToDelete->PDev);
378 DCToDelete->DriverFunctions.AssertMode( DCToDelete->PDev, FALSE );
380 DCToDelete->DriverFunctions.DisablePDev(DCToDelete->PDev);
381 PrimarySurfaceCreated = FALSE;
385 /* First delete all saved DCs */
386 while (DCToDelete->saveLevel)
391 savedHDC = DC_GetNextDC (DCToDelete);
392 savedDC = DC_HandleToPtr (savedHDC);
397 DC_SetNextDC (DCToDelete, DC_GetNextDC (savedDC));
398 DCToDelete->saveLevel--;
399 DC_ReleasePtr( savedHDC );
400 W32kDeleteDC (savedHDC);
403 /* Free GDI resources allocated to this DC */
404 if (!(DCToDelete->w.flags & DC_SAVED))
407 W32kSelectObject (DCHandle, STOCK_BLACK_PEN);
408 W32kSelectObject (DCHandle, STOCK_WHITE_BRUSH);
409 W32kSelectObject (DCHandle, STOCK_SYSTEM_FONT);
410 DC_LockDC (DCHandle); W32kSelectObject does not recognize stock objects yet */
411 if (DCToDelete->w.flags & DC_MEMORY)
413 W32kDeleteObject (DCToDelete->w.hFirstBitmap);
416 if (DCToDelete->w.hClipRgn)
418 W32kDeleteObject (DCToDelete->w.hClipRgn);
420 if (DCToDelete->w.hVisRgn)
422 W32kDeleteObject (DCToDelete->w.hVisRgn);
424 if (DCToDelete->w.hGCClipRgn)
426 W32kDeleteObject (DCToDelete->w.hGCClipRgn);
429 PATH_DestroyGdiPath (&DCToDelete->w.path);
431 DC_ReleasePtr( DCToDelete );
432 DC_FreeDC (DCToDelete);
437 INT STDCALL W32kDrawEscape(HDC hDC,
445 INT STDCALL W32kEnumObjects(HDC hDC,
447 GOBJENUMPROC ObjectFunc,
453 DC_GET_VAL( COLORREF, W32kGetBkColor, w.backgroundColor )
454 DC_GET_VAL( INT, W32kGetBkMode, w.backgroundMode )
455 DC_GET_VAL_EX( W32kGetBrushOrgEx, w.brushOrgX, w.brushOrgY, POINT )
456 DC_GET_VAL( HRGN, W32kGetClipRgn, w.hClipRgn )
458 HGDIOBJ STDCALL W32kGetCurrentObject(HDC hDC,
464 DC_GET_VAL_EX( W32kGetCurrentPositionEx, w.CursPosX, w.CursPosY, POINT )
466 BOOL STDCALL W32kGetDCOrgEx(HDC hDC,
475 dc = DC_HandleToPtr(hDC);
481 Point->x = Point->y = 0;
483 Point->x += dc->w.DCOrgX;
484 Point->y += dc->w.DCOrgY;
485 DC_ReleasePtr( hDC );
489 HDC STDCALL W32kGetDCState16(HDC hDC)
494 dc = DC_HandleToPtr(hDC);
500 hnewdc = DC_AllocDC(NULL);
503 DC_ReleasePtr( hDC );
506 newdc = DC_HandleToPtr( hnewdc );
509 newdc->w.flags = dc->w.flags | DC_SAVED;
511 newdc->w.devCaps = dc->w.devCaps;
513 newdc->w.hPen = dc->w.hPen;
514 newdc->w.hBrush = dc->w.hBrush;
515 newdc->w.hFont = dc->w.hFont;
516 newdc->w.hBitmap = dc->w.hBitmap;
517 newdc->w.hFirstBitmap = dc->w.hFirstBitmap;
519 newdc->w.hDevice = dc->w.hDevice;
520 newdc->w.hPalette = dc->w.hPalette;
522 newdc->w.totalExtent = dc->w.totalExtent;
523 newdc->w.bitsPerPixel = dc->w.bitsPerPixel;
524 newdc->w.ROPmode = dc->w.ROPmode;
525 newdc->w.polyFillMode = dc->w.polyFillMode;
526 newdc->w.stretchBltMode = dc->w.stretchBltMode;
527 newdc->w.relAbsMode = dc->w.relAbsMode;
528 newdc->w.backgroundMode = dc->w.backgroundMode;
529 newdc->w.backgroundColor = dc->w.backgroundColor;
530 newdc->w.textColor = dc->w.textColor;
531 newdc->w.brushOrgX = dc->w.brushOrgX;
532 newdc->w.brushOrgY = dc->w.brushOrgY;
533 newdc->w.textAlign = dc->w.textAlign;
534 newdc->w.charExtra = dc->w.charExtra;
535 newdc->w.breakTotalExtra = dc->w.breakTotalExtra;
536 newdc->w.breakCount = dc->w.breakCount;
537 newdc->w.breakExtra = dc->w.breakExtra;
538 newdc->w.breakRem = dc->w.breakRem;
539 newdc->w.MapMode = dc->w.MapMode;
540 newdc->w.GraphicsMode = dc->w.GraphicsMode;
542 /* Apparently, the DC origin is not changed by [GS]etDCState */
543 newdc->w.DCOrgX = dc->w.DCOrgX;
544 newdc->w.DCOrgY = dc->w.DCOrgY;
546 newdc->w.CursPosX = dc->w.CursPosX;
547 newdc->w.CursPosY = dc->w.CursPosY;
548 newdc->w.ArcDirection = dc->w.ArcDirection;
550 newdc->w.xformWorld2Wnd = dc->w.xformWorld2Wnd;
551 newdc->w.xformWorld2Vport = dc->w.xformWorld2Vport;
552 newdc->w.xformVport2World = dc->w.xformVport2World;
553 newdc->w.vport2WorldValid = dc->w.vport2WorldValid;
555 newdc->wndOrgX = dc->wndOrgX;
556 newdc->wndOrgY = dc->wndOrgY;
557 newdc->wndExtX = dc->wndExtX;
558 newdc->wndExtY = dc->wndExtY;
559 newdc->vportOrgX = dc->vportOrgX;
560 newdc->vportOrgY = dc->vportOrgY;
561 newdc->vportExtX = dc->vportExtX;
562 newdc->vportExtY = dc->vportExtY;
564 newdc->hSelf = hnewdc;
565 newdc->saveLevel = 0;
568 PATH_InitGdiPath( &newdc->w.path );
571 /* Get/SetDCState() don't change hVisRgn field ("Undoc. Windows" p.559). */
574 newdc->w.hGCClipRgn = newdc->w.hVisRgn = 0;
578 newdc->w.hClipRgn = W32kCreateRectRgn( 0, 0, 0, 0 );
579 W32kCombineRgn( newdc->w.hClipRgn, dc->w.hClipRgn, 0, RGN_COPY );
583 newdc->w.hClipRgn = 0;
585 DC_ReleasePtr( hnewdc );
589 INT STDCALL W32kGetDeviceCaps(HDC hDC,
596 dc = DC_HandleToPtr(hDC);
602 /* Device capabilities for the printer */
606 if(W32kEscape(hDC, GETPHYSPAGESIZE, 0, NULL, (LPVOID)&pt) > 0)
613 if(W32kEscape(hDC, GETPHYSPAGESIZE, 0, NULL, (LPVOID)&pt) > 0)
619 case PHYSICALOFFSETX:
620 if(W32kEscape(hDC, GETPRINTINGOFFSET, 0, NULL, (LPVOID)&pt) > 0)
626 case PHYSICALOFFSETY:
627 if(W32kEscape(hDC, GETPRINTINGOFFSET, 0, NULL, (LPVOID)&pt) > 0)
634 if(W32kEscape(hDC, GETSCALINGFACTOR, 0, NULL, (LPVOID)&pt) > 0)
641 if(W32kEscape(hDC, GETSCALINGFACTOR, 0, NULL, (LPVOID)&pt) > 0)
648 if ((Index < 0) || (Index > sizeof(DEVICECAPS) - sizeof(WORD)))
653 DPRINT("(%04x,%d): returning %d\n",
654 hDC, Index, *(WORD *)(((char *)dc->w.devCaps) + Index));
655 ret = *(WORD *)(((char *)dc->w.devCaps) + Index);
657 DC_ReleasePtr( hDC );
661 DC_GET_VAL( INT, W32kGetMapMode, w.MapMode )
662 DC_GET_VAL( INT, W32kGetPolyFillMode, w.polyFillMode )
664 INT STDCALL W32kGetObjectA(HANDLE handle, INT count, LPVOID buffer)
672 gdiObject = GDIOBJ_LockObj (handle, GO_MAGIC_DONTCARE);
676 magic = GDIOBJ_GetHandleMagic (handle);
679 /* case GO_PEN_MAGIC:
680 result = PEN_GetObject((PENOBJ *)gdiObject, count, buffer);
683 result = BRUSH_GetObject((BRUSHOBJ *)gdiObject, count, buffer);
685 case GO_BITMAP_MAGIC:
686 result = BITMAP_GetObject((BITMAPOBJ *)gdiObject, count, buffer);
688 /* case GO_FONT_MAGIC:
689 result = FONT_GetObjectA((FONTOBJ *)gdiObject, count, buffer);
691 // FIXME: Fix the LOGFONT structure for the stock fonts
693 if ( (handle >= FIRST_STOCK_HANDLE) && (handle <= LAST_STOCK_HANDLE) )
694 FixStockFontSizeA(handle, count, buffer);
696 case GO_PALETTE_MAGIC:
697 result = PALETTE_GetObject((PALETTEOBJ *)gdiObject, count, buffer);
700 case GO_REGION_MAGIC:
702 case GO_DISABLED_DC_MAGIC:
703 case GO_META_DC_MAGIC:
704 case GO_METAFILE_MAGIC:
705 case GO_METAFILE_DC_MAGIC:
706 case GO_ENHMETAFILE_MAGIC:
707 case GO_ENHMETAFILE_DC_MAGIC:
708 // FIXME("Magic %04x not implemented\n", magic);
712 DbgPrint("Invalid GDI Magic %04x\n", magic);
715 GDIOBJ_UnlockObj (handle, GO_MAGIC_DONTCARE);
719 INT STDCALL W32kGetObjectW(HANDLE handle, INT count, LPVOID buffer)
721 PGDIOBJHDR gdiObject;
727 gdiObject = GDIOBJ_LockObj(handle, GO_MAGIC_DONTCARE);
731 magic = GDIOBJ_GetHandleMagic (handle);
734 /* case GO_PEN_MAGIC:
735 result = PEN_GetObject((PENOBJ *)gdiObject, count, buffer);
738 result = BRUSH_GetObject((BRUSHOBJ *)gdiObject, count, buffer);
740 case GO_BITMAP_MAGIC:
741 result = BITMAP_GetObject((BITMAPOBJ *)gdiObject, count, buffer);
743 /* case GO_FONT_MAGIC:
744 result = FONT_GetObjectW((FONTOBJ *)gdiObject, count, buffer);
746 // Fix the LOGFONT structure for the stock fonts
748 if ( (handle >= FIRST_STOCK_HANDLE) && (handle <= LAST_STOCK_HANDLE) )
749 FixStockFontSizeW(handle, count, buffer);
751 case GO_PALETTE_MAGIC:
752 result = PALETTE_GetObject((PALETTEOBJ *)gdiObject, count, buffer);
755 // FIXME("Magic %04x not implemented\n", gdiObject->magic);
758 GDIOBJ_UnlockObj(handle, GO_MAGIC_DONTCARE);
762 INT STDCALL W32kGetObject(HANDLE handle, INT count, LPVOID buffer)
764 return W32kGetObjectW(handle, count, buffer);
767 DWORD STDCALL W32kGetObjectType(HANDLE handle)
773 ptr = GDIOBJ_LockObj(handle, GO_MAGIC_DONTCARE);
777 magic = GDIOBJ_GetHandleMagic (handle);
786 case GO_BITMAP_MAGIC:
792 case GO_PALETTE_MAGIC:
795 case GO_REGION_MAGIC:
801 case GO_META_DC_MAGIC:
804 case GO_METAFILE_MAGIC:
805 result = OBJ_METAFILE;
807 case GO_METAFILE_DC_MAGIC:
810 case GO_ENHMETAFILE_MAGIC:
811 result = OBJ_ENHMETAFILE;
813 case GO_ENHMETAFILE_DC_MAGIC:
814 result = OBJ_ENHMETADC;
817 // FIXME("Magic %04x not implemented\n", magic);
820 GDIOBJ_UnlockObj(handle, GO_MAGIC_DONTCARE);
824 DC_GET_VAL( INT, W32kGetRelAbs, w.relAbsMode )
825 DC_GET_VAL( INT, W32kGetROP2, w.ROPmode )
826 DC_GET_VAL( INT, W32kGetStretchBltMode, w.stretchBltMode )
827 DC_GET_VAL( UINT, W32kGetTextAlign, w.textAlign )
828 DC_GET_VAL( COLORREF, W32kGetTextColor, w.textColor )
829 DC_GET_VAL_EX( W32kGetViewportExtEx, vportExtX, vportExtY, SIZE )
830 DC_GET_VAL_EX( W32kGetViewportOrgEx, vportOrgX, vportOrgY, POINT )
831 DC_GET_VAL_EX( W32kGetWindowExtEx, wndExtX, wndExtY, SIZE )
832 DC_GET_VAL_EX( W32kGetWindowOrgEx, wndOrgX, wndOrgY, POINT )
834 HDC STDCALL W32kResetDC(HDC hDC, CONST DEVMODEW *InitData)
839 BOOL STDCALL W32kRestoreDC(HDC hDC, INT SaveLevel)
844 dc = DC_HandleToPtr(hDC);
852 SaveLevel = dc->saveLevel;
855 if ((SaveLevel < 1) || (SaveLevel > dc->saveLevel))
861 while (dc->saveLevel >= SaveLevel)
863 HDC hdcs = DC_GetNextDC (dc);
865 dcs = DC_HandleToPtr (hdcs);
870 DC_SetNextDC (dcs, DC_GetNextDC (dcs));
871 if (--dc->saveLevel < SaveLevel)
873 W32kSetDCState16 (hDC, hdcs);
875 if (!PATH_AssignGdiPath( &dc->w.path, &dcs->w.path ))
877 /* FIXME: This might not be quite right, since we're
878 * returning FALSE but still destroying the saved DC state */
883 DC_ReleasePtr( hdcs );
886 DC_ReleasePtr( hDC );
890 INT STDCALL W32kSaveDC(HDC hDC)
896 dc = DC_HandleToPtr (hDC);
902 if (!(hdcs = W32kGetDCState16 (hDC)))
906 dcs = DC_HandleToPtr (hdcs);
909 /* Copy path. The reason why path saving / restoring is in SaveDC/
910 * RestoreDC and not in GetDCState/SetDCState is that the ...DCState
911 * functions are only in Win16 (which doesn't have paths) and that
912 * SetDCState doesn't allow us to signal an error (which can happen
913 * when copying paths).
915 if (!PATH_AssignGdiPath (&dcs->w.path, &dc->w.path))
922 DC_SetNextDC (dcs, DC_GetNextDC (dc));
923 DC_SetNextDC (dc, hdcs);
924 ret = ++dc->saveLevel;
925 DC_ReleasePtr( hdcs );
926 DC_ReleasePtr( hDC );
931 HGDIOBJ STDCALL W32kSelectObject(HDC hDC, HGDIOBJ hGDIObj)
945 if(!hDC || !hGDIObj) return NULL;
947 dc = DC_HandleToPtr(hDC);
948 objectMagic = GDIOBJ_GetHandleMagic (hGDIObj);
949 // GdiObjHdr = hGDIObj;
951 // FIXME: Get object handle from GDIObj and use it instead of GDIObj below?
953 switch(objectMagic) {
955 objOrg = (HGDIOBJ)dc->w.hPen;
956 dc->w.hPen = hGDIObj;
958 // Convert the color of the pen to the format of the DC
959 PalGDI = (PPALGDI)AccessInternalObject(dc->w.hPalette);
961 XlateObj = (PXLATEOBJ)EngCreateXlate(PalGDI->Mode, PAL_RGB, dc->w.hPalette, NULL);
962 pen = GDIOBJ_LockObj(dc->w.hPen, GO_PEN_MAGIC);
963 pen->logpen.lopnColor = XLATEOBJ_iXlate(XlateObj, pen->logpen.lopnColor);
964 GDIOBJ_UnlockObj( dc->w.hPen, GO_PEN_MAGIC);
968 objOrg = (HGDIOBJ)dc->w.hBrush;
969 dc->w.hBrush = (HBRUSH) hGDIObj;
971 // Convert the color of the brush to the format of the DC
972 PalGDI = (PPALGDI)AccessInternalObject(dc->w.hPalette);
974 XlateObj = (PXLATEOBJ)EngCreateXlate(PalGDI->Mode, PAL_RGB, dc->w.hPalette, NULL);
975 brush = GDIOBJ_LockObj(dc->w.hBrush, GO_BRUSH_MAGIC);
976 brush->iSolidColor = XLATEOBJ_iXlate(XlateObj,
977 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)
1220 void DC_InitDC(HDC DCHandle)
1222 // W32kRealizeDefaultPalette(DCHandle);
1224 if( (DCToInit = DC_HandleToPtr( DCHandle ) ) ){
1225 W32kSetTextColor(DCHandle, DCToInit->w.textColor);
1226 W32kSetBkColor(DCHandle, DCToInit->w.backgroundColor);
1227 W32kSelectObject(DCHandle, DCToInit->w.hPen);
1228 W32kSelectObject(DCHandle, W32kGetStockObject( GRAY_BRUSH )); //FIXME: default should be WHITE_BRUSH
1229 W32kSelectObject(DCHandle, DCToInit->w.hFont);
1232 DPRINT("DC_InitDC: can't get dc for handle %d\n", DCHandle );
1233 // CLIPPING_UpdateGCRegion(DCToInit);
1236 void DC_FreeDC(HDC DCToFree)
1238 if (!GDIOBJ_FreeObj(DCToFree, GO_DC_MAGIC, GDIOBJFLAG_DEFAULT))
1240 DPRINT("DC_FreeDC failed\n");
1244 BOOL DC_InternalDeleteDC( PDC DCToDelete )
1246 if( DCToDelete->DriverName )
1247 ExFreePool(DCToDelete->DriverName);
1251 HDC DC_GetNextDC (PDC pDC)
1256 void DC_SetNextDC (PDC pDC, HDC hNextDC)
1258 pDC->hNext = hNextDC;
1262 DC_UpdateXforms(PDC dc)
1264 XFORM xformWnd2Vport;
1265 FLOAT scaleX, scaleY;
1267 /* Construct a transformation to do the window-to-viewport conversion */
1268 scaleX = (FLOAT)dc->vportExtX / (FLOAT)dc->wndExtX;
1269 scaleY = (FLOAT)dc->vportExtY / (FLOAT)dc->wndExtY;
1270 xformWnd2Vport.eM11 = scaleX;
1271 xformWnd2Vport.eM12 = 0.0;
1272 xformWnd2Vport.eM21 = 0.0;
1273 xformWnd2Vport.eM22 = scaleY;
1274 xformWnd2Vport.eDx = (FLOAT)dc->vportOrgX - scaleX * (FLOAT)dc->wndOrgX;
1275 xformWnd2Vport.eDy = (FLOAT)dc->vportOrgY - scaleY * (FLOAT)dc->wndOrgY;
1277 /* Combine with the world transformation */
1278 W32kCombineTransform(&dc->w.xformWorld2Vport, &dc->w.xformWorld2Wnd, &xformWnd2Vport);
1280 /* Create inverse of world-to-viewport transformation */
1281 dc->w.vport2WorldValid = DC_InvertXform(&dc->w.xformWorld2Vport, &dc->w.xformVport2World);
1285 DC_InvertXform(const XFORM *xformSrc,
1290 determinant = xformSrc->eM11*xformSrc->eM22 - xformSrc->eM12*xformSrc->eM21;
1291 if (determinant > -1e-12 && determinant < 1e-12)
1296 xformDest->eM11 = xformSrc->eM22 / determinant;
1297 xformDest->eM12 = -xformSrc->eM12 / determinant;
1298 xformDest->eM21 = -xformSrc->eM21 / determinant;
1299 xformDest->eM22 = xformSrc->eM11 / determinant;
1300 xformDest->eDx = -xformSrc->eDx * xformDest->eM11 - xformSrc->eDy * xformDest->eM21;
1301 xformDest->eDy = -xformSrc->eDx * xformDest->eM12 - xformSrc->eDy * xformDest->eM22;