Changes for multiple window support
[reactos.git] / reactos / subsys / win32k / objects / dc.c
1 /*
2 * ReactOS W32 Subsystem
3 * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003 ReactOS Team
4 *
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.
9 *
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.
14 *
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.
18 */
19 /* $Id: dc.c,v 1.64 2003/07/17 07:49:15 gvg Exp $
20 *
21 * DC.C - Device context functions
22 *
23 */
24
25 #undef WIN32_LEAN_AND_MEAN
26 #include <windows.h>
27 #include <ddk/ntddk.h>
28 #include <ddk/ntddvid.h>
29
30 #include <win32k/bitmaps.h>
31 #include <win32k/cliprgn.h>
32 #include <win32k/coord.h>
33 #include <win32k/driver.h>
34 #include <win32k/dc.h>
35 #include <win32k/misc.h>
36 #include <win32k/print.h>
37 #include <win32k/region.h>
38 #include <win32k/gdiobj.h>
39 #include <win32k/pen.h>
40 #include <win32k/text.h>
41 #include "../eng/clip.h"
42 #include "../eng/handle.h"
43 #include <include/inteng.h>
44 #include <include/eng.h>
45
46 #define NDEBUG
47 #include <win32k/debug1.h>
48
49 static GDIDEVICE PrimarySurface;
50 static BOOL PrimarySurfaceCreated = FALSE;
51
52 /* FIXME: DCs should probably be thread safe */
53
54 /*
55 * DC device-independent Get/SetXXX functions
56 * (RJJ) swiped from WINE
57 */
58
59 #define DC_GET_VAL( func_type, func_name, dc_field ) \
60 func_type STDCALL func_name( HDC hdc ) \
61 { \
62 func_type ft; \
63 PDC dc = DC_HandleToPtr( hdc ); \
64 if (!dc) \
65 { \
66 return 0; \
67 } \
68 ft = dc->dc_field; \
69 DC_ReleasePtr( hdc ); \
70 return ft; \
71 }
72
73 /* DC_GET_VAL_EX is used to define functions returning a POINT or a SIZE. It is
74 * important that the function has the right signature, for the implementation
75 * we can do whatever we want.
76 */
77 #define DC_GET_VAL_EX( func_name, ret_x, ret_y, type ) \
78 BOOL STDCALL func_name( HDC hdc, LP##type pt ) \
79 { \
80 PDC dc = DC_HandleToPtr( hdc ); \
81 if (!dc) \
82 { \
83 return FALSE; \
84 } \
85 ((LPPOINT)pt)->x = dc->ret_x; \
86 ((LPPOINT)pt)->y = dc->ret_y; \
87 DC_ReleasePtr( hdc ); \
88 return TRUE; \
89 }
90
91 #define DC_SET_MODE( func_name, dc_field, min_val, max_val ) \
92 INT STDCALL func_name( HDC hdc, INT mode ) \
93 { \
94 INT prevMode; \
95 PDC dc = DC_HandleToPtr( hdc ); \
96 if(!dc) \
97 { \
98 return 0; \
99 } \
100 if ((mode < min_val) || (mode > max_val)) \
101 { \
102 return 0; \
103 } \
104 prevMode = dc->dc_field; \
105 dc->dc_field = mode; \
106 DC_ReleasePtr( hdc ); \
107 return prevMode; \
108 }
109
110
111 // --------------------------------------------------------- File Statics
112
113 static VOID FASTCALL W32kSetDCState16(HDC hDC, HDC hDCSave);
114
115 // ----------------------------------------------------- Public Functions
116
117 BOOL STDCALL W32kCancelDC(HDC hDC)
118 {
119 UNIMPLEMENTED;
120 }
121
122 HDC STDCALL W32kCreateCompatableDC(HDC hDC)
123 {
124 PDC NewDC, OrigDC = NULL;
125 HBITMAP hBitmap;
126 HDC hNewDC;
127 HRGN hVisRgn;
128
129 OrigDC = DC_HandleToPtr(hDC);
130 if (OrigDC == NULL)
131 {
132 hNewDC = DC_AllocDC(L"DISPLAY");
133 if( hNewDC )
134 NewDC = DC_HandleToPtr( hNewDC );
135 }
136 else {
137 /* Allocate a new DC based on the original DC's device */
138 hNewDC = DC_AllocDC(OrigDC->DriverName);
139 if( hNewDC )
140 NewDC = DC_HandleToPtr( hNewDC );
141 }
142
143 if (NewDC == NULL)
144 {
145 return NULL;
146 }
147
148 /* Copy information from original DC to new DC */
149 NewDC->hSelf = NewDC;
150
151 /* FIXME: Should this DC request its own PDEV? */
152 if(OrigDC == NULL) {
153 } else {
154 NewDC->PDev = OrigDC->PDev;
155 NewDC->DMW = OrigDC->DMW;
156 memcpy(NewDC->FillPatternSurfaces,
157 OrigDC->FillPatternSurfaces,
158 sizeof OrigDC->FillPatternSurfaces);
159 NewDC->GDIInfo = OrigDC->GDIInfo;
160 NewDC->DevInfo = OrigDC->DevInfo;
161 }
162
163 /* DriverName is copied in the AllocDC routine */
164 if(OrigDC == NULL) {
165 NewDC->DeviceDriver = DRIVER_FindMPDriver(NewDC->DriverName);
166 } else {
167 NewDC->DeviceDriver = OrigDC->DeviceDriver;
168 NewDC->wndOrgX = OrigDC->wndOrgX;
169 NewDC->wndOrgY = OrigDC->wndOrgY;
170 NewDC->wndExtX = OrigDC->wndExtX;
171 NewDC->wndExtY = OrigDC->wndExtY;
172 NewDC->vportOrgX = OrigDC->vportOrgX;
173 NewDC->vportOrgY = OrigDC->vportOrgY;
174 NewDC->vportExtX = OrigDC->vportExtX;
175 NewDC->vportExtY = OrigDC->vportExtY;
176 }
177
178 /* Create default bitmap */
179 if (!(hBitmap = W32kCreateBitmap( 1, 1, 1, 1, NULL )))
180 {
181 DC_ReleasePtr( hNewDC );
182 DC_FreeDC( hNewDC );
183 return NULL;
184 }
185 NewDC->w.flags = DC_MEMORY;
186 NewDC->w.bitsPerPixel = 1;
187 NewDC->w.hBitmap = hBitmap;
188 NewDC->w.hFirstBitmap = hBitmap;
189 NewDC->Surface = BitmapToSurf(BITMAPOBJ_HandleToPtr(hBitmap));
190
191 if(OrigDC != NULL)
192 {
193 NewDC->w.hPalette = OrigDC->w.hPalette;
194 NewDC->w.textColor = OrigDC->w.textColor;
195 NewDC->w.textAlign = OrigDC->w.textAlign;
196 }
197 DC_ReleasePtr( hDC );
198 DC_ReleasePtr( hNewDC );
199
200 hVisRgn = W32kCreateRectRgn(0, 0, 1, 1);
201 W32kSelectVisRgn(hNewDC, hVisRgn);
202 W32kDeleteObject(hVisRgn);
203
204 DC_InitDC(hNewDC);
205
206 return hNewDC;
207 }
208
209 static BOOL STDCALL FindDriverFileNames(PUNICODE_STRING DriverFileNames)
210 {
211 RTL_QUERY_REGISTRY_TABLE QueryTable[2];
212 UNICODE_STRING RegistryPath;
213 NTSTATUS Status;
214
215 RtlInitUnicodeString(&RegistryPath, NULL);
216 RtlZeroMemory(QueryTable, sizeof(QueryTable));
217 QueryTable[0].Flags = RTL_QUERY_REGISTRY_REQUIRED | RTL_QUERY_REGISTRY_DIRECT;
218 QueryTable[0].Name = L"\\Device\\Video0";
219 QueryTable[0].EntryContext = &RegistryPath;
220
221 Status = RtlQueryRegistryValues(RTL_REGISTRY_DEVICEMAP,
222 L"VIDEO",
223 QueryTable,
224 NULL,
225 NULL);
226 if (! NT_SUCCESS(Status))
227 {
228 DPRINT1("No \\Device\\Video0 value in DEVICEMAP\\VIDEO found\n");
229 return FALSE;
230 }
231
232 DPRINT("RegistryPath %S\n", RegistryPath.Buffer);
233
234 QueryTable[0].Name = L"InstalledDisplayDrivers";
235 QueryTable[0].EntryContext = DriverFileNames;
236
237 Status = RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE,
238 RegistryPath.Buffer,
239 QueryTable,
240 NULL,
241 NULL);
242 RtlFreeUnicodeString(&RegistryPath);
243 if (! NT_SUCCESS(Status))
244 {
245 DPRINT1("No InstalledDisplayDrivers value in service entry found\n");
246 return FALSE;
247 }
248
249 DPRINT("DriverFileNames %S\n", DriverFileNames->Buffer);
250
251 return TRUE;
252 }
253
254
255 BOOL STDCALL W32kCreatePrimarySurface(LPCWSTR Driver,
256 LPCWSTR Device)
257 {
258 PGD_ENABLEDRIVER GDEnableDriver;
259 DRVENABLEDATA DED;
260 PSURFOBJ SurfObj;
261 PSURFGDI SurfGDI;
262 UNICODE_STRING DriverFileNames;
263 PWSTR CurrentName;
264 BOOL GotDriver;
265 extern void FASTCALL W32kInitDesktopWindow(ULONG Width, ULONG Height);
266
267 /* Open the miniport driver */
268 if ((PrimarySurface.DisplayDevice = DRIVER_FindMPDriver(Driver)) == NULL)
269 {
270 DPRINT("FindMPDriver failed\n");
271 return(FALSE);
272 }
273
274 /* Retrieve DDI driver names from registry */
275 RtlInitUnicodeString(&DriverFileNames, NULL);
276 if (! FindDriverFileNames(&DriverFileNames))
277 {
278 DPRINT("FindDriverFileNames failed\n");
279 return(FALSE);
280 }
281
282 /* DriverFileNames may be a list of drivers in REG_SZ_MULTI format, scan all of
283 them until a good one found */
284 CurrentName = DriverFileNames.Buffer;
285 GotDriver = FALSE;
286 while (! GotDriver && CurrentName < DriverFileNames.Buffer + DriverFileNames.Length)
287 {
288 /* Get the DDI driver's entry point */
289 GDEnableDriver = DRIVER_FindDDIDriver(CurrentName);
290 if (NULL == GDEnableDriver)
291 {
292 DPRINT("FindDDIDriver failed for %S\n", CurrentName);
293 }
294 else
295 {
296 /* Call DDI driver's EnableDriver function */
297 RtlZeroMemory(&DED, sizeof(DED));
298
299 if (!GDEnableDriver(DDI_DRIVER_VERSION, sizeof(DED), &DED))
300 {
301 DPRINT("DrvEnableDriver failed for %S\n", CurrentName);
302 }
303 else
304 {
305 GotDriver = TRUE;
306 }
307 }
308
309 if (! GotDriver)
310 {
311 /* Skip to the next name but never get past the Unicode string */
312 while (L'\0' != *CurrentName &&
313 CurrentName < DriverFileNames.Buffer + DriverFileNames.Length)
314 {
315 CurrentName++;
316 }
317 if (CurrentName < DriverFileNames.Buffer + DriverFileNames.Length)
318 {
319 CurrentName++;
320 }
321 }
322 }
323 RtlFreeUnicodeString(&DriverFileNames);
324 if (! GotDriver)
325 {
326 DPRINT("No suitable driver found\n");
327 return FALSE;
328 }
329
330 DPRINT("Display driver %S loaded\n", DriverName);
331
332 DPRINT("Building DDI Functions\n");
333
334 /* Construct DDI driver function dispatch table */
335 if (!DRIVER_BuildDDIFunctions(&DED, &PrimarySurface.DriverFunctions))
336 {
337 DPRINT("BuildDDIFunctions failed\n");
338 return(FALSE);
339 }
340
341 /* Allocate a phyical device handle from the driver */
342 if (Device != NULL)
343 {
344 DPRINT("Device in u: %u\n", Device);
345 // wcsncpy(NewDC->DMW.dmDeviceName, Device, DMMAXDEVICENAME); FIXME: this crashes everything?
346 }
347
348 DPRINT("Enabling PDev\n");
349
350 PrimarySurface.PDev =
351 PrimarySurface.DriverFunctions.EnablePDev(&PrimarySurface.DMW,
352 L"",
353 HS_DDI_MAX,
354 PrimarySurface.FillPatterns,
355 sizeof(PrimarySurface.GDIInfo),
356 (ULONG *) &PrimarySurface.GDIInfo,
357 sizeof(PrimarySurface.DevInfo),
358 &PrimarySurface.DevInfo,
359 NULL,
360 L"",
361 PrimarySurface.DisplayDevice);
362 if (PrimarySurface.PDev == NULL)
363 {
364 DPRINT("DrvEnablePDEV failed\n");
365 return(FALSE);
366 }
367
368 DPRINT("calling completePDev\n");
369
370 /* Complete initialization of the physical device */
371 PrimarySurface.DriverFunctions.CompletePDev(PrimarySurface.PDev,
372 &PrimarySurface);
373
374 DPRINT("calling DRIVER_ReferenceDriver\n");
375
376 DRIVER_ReferenceDriver (Driver);
377
378 DPRINT("calling EnableSurface\n");
379
380 /* Enable the drawing surface */
381 PrimarySurface.Handle =
382 PrimarySurface.DriverFunctions.EnableSurface(PrimarySurface.PDev);
383
384 SurfObj = (PSURFOBJ)AccessUserObject((ULONG) PrimarySurface.Handle);
385 SurfObj->dhpdev = PrimarySurface.PDev;
386 SurfGDI = (PSURFGDI)AccessInternalObject((ULONG) PrimarySurface.Handle);
387 W32kInitDesktopWindow(SurfGDI->SurfObj.sizlBitmap.cx, SurfGDI->SurfObj.sizlBitmap.cy);
388
389 return TRUE;
390 }
391
392 HDC STDCALL W32kCreateDC(LPCWSTR Driver,
393 LPCWSTR Device,
394 LPCWSTR Output,
395 CONST PDEVMODEW InitData)
396 {
397 HDC hNewDC;
398 PDC NewDC;
399 HDC hDC = NULL;
400 PSURFGDI SurfGDI;
401 HRGN hVisRgn;
402
403 /* Check for existing DC object */
404 if ((hNewDC = DC_FindOpenDC(Driver)) != NULL)
405 {
406 hDC = hNewDC;
407 return W32kCreateCompatableDC(hDC);
408 }
409
410 DPRINT("NAME: %S\n", Driver); // FIXME: Should not crash if NULL
411
412 /* Allocate a DC object */
413 if ((hNewDC = DC_AllocDC(Driver)) == NULL)
414 {
415 return NULL;
416 }
417
418 NewDC = DC_HandleToPtr( hNewDC );
419 ASSERT( NewDC );
420
421 if (! PrimarySurfaceCreated)
422 {
423 PrimarySurfaceCreated = TRUE;
424 if (!W32kCreatePrimarySurface(Driver, Device))
425 {
426 PrimarySurfaceCreated = FALSE;
427 DC_ReleasePtr( hNewDC );
428 DC_FreeDC(hNewDC);
429 return NULL;
430 }
431 }
432 NewDC->DMW = PrimarySurface.DMW;
433 NewDC->DevInfo = &PrimarySurface.DevInfo;
434 NewDC->GDIInfo = &PrimarySurface.GDIInfo;
435 memcpy(NewDC->FillPatternSurfaces, PrimarySurface.FillPatterns,
436 sizeof(NewDC->FillPatternSurfaces));
437 NewDC->PDev = PrimarySurface.PDev;
438 NewDC->Surface = PrimarySurface.Handle;
439 NewDC->DriverFunctions = PrimarySurface.DriverFunctions;
440
441 NewDC->DMW.dmSize = sizeof(NewDC->DMW);
442 NewDC->DMW.dmFields = 0x000fc000;
443
444 /* FIXME: get mode selection information from somewhere */
445
446 NewDC->DMW.dmLogPixels = 96;
447 SurfGDI = (PSURFGDI)AccessInternalObject((ULONG) PrimarySurface.Handle);
448 NewDC->DMW.dmBitsPerPel = SurfGDI->BitsPerPixel;
449 NewDC->DMW.dmPelsWidth = SurfGDI->SurfObj.sizlBitmap.cx;
450 NewDC->DMW.dmPelsHeight = SurfGDI->SurfObj.sizlBitmap.cy;
451 NewDC->DMW.dmDisplayFlags = 0;
452 NewDC->DMW.dmDisplayFrequency = 0;
453
454 NewDC->w.bitsPerPixel = SurfGDI->BitsPerPixel; // FIXME: set this here??
455
456 NewDC->w.hPalette = NewDC->DevInfo->hpalDefault;
457
458 DPRINT("Bits per pel: %u\n", NewDC->w.bitsPerPixel);
459
460 DC_ReleasePtr( hNewDC );
461
462 hVisRgn = W32kCreateRectRgn(0, 0, SurfGDI->SurfObj.sizlBitmap.cx,
463 SurfGDI->SurfObj.sizlBitmap.cy);
464 W32kSelectVisRgn(hNewDC, hVisRgn);
465 W32kDeleteObject(hVisRgn);
466
467 /* Initialize the DC state */
468 DC_InitDC(hNewDC);
469 W32kSetTextColor(hNewDC, RGB(0, 0, 0));
470 W32kSetTextAlign(hNewDC, TA_TOP);
471
472 return hNewDC;
473 }
474
475 HDC STDCALL W32kCreateIC(LPCWSTR Driver,
476 LPCWSTR Device,
477 LPCWSTR Output,
478 CONST PDEVMODEW DevMode)
479 {
480 /* FIXME: this should probably do something else... */
481 return W32kCreateDC(Driver, Device, Output, DevMode);
482 }
483
484 BOOL STDCALL W32kDeleteDC(HDC DCHandle)
485 {
486 PDC DCToDelete;
487
488 DCToDelete = DC_HandleToPtr(DCHandle);
489 if (DCToDelete == NULL)
490 {
491 return FALSE;
492 }
493 DPRINT( "Deleting DC\n" );
494 if ((!(DCToDelete->w.flags & DC_MEMORY))) // Don't reset the display if its a memory DC
495 {
496 if (!DRIVER_UnreferenceDriver (DCToDelete->DriverName))
497 {
498 DPRINT( "No more references to driver, reseting display\n" );
499 DCToDelete->DriverFunctions.AssertMode( DCToDelete->PDev, FALSE );
500 CHECKPOINT;
501 DCToDelete->DriverFunctions.DisableSurface(DCToDelete->PDev);
502 CHECKPOINT;
503 DCToDelete->DriverFunctions.DisablePDev(DCToDelete->PDev);
504
505 KeAttachProcess(W32kDeviceProcess);
506 ZwClose(PrimarySurface.DisplayDevice);
507 KeDetachProcess();
508
509 PrimarySurfaceCreated = FALSE;
510 }
511 }
512 CHECKPOINT;
513 /* First delete all saved DCs */
514 while (DCToDelete->saveLevel)
515 {
516 PDC savedDC;
517 HDC savedHDC;
518
519 savedHDC = DC_GetNextDC (DCToDelete);
520 savedDC = DC_HandleToPtr (savedHDC);
521 if (savedDC == NULL)
522 {
523 break;
524 }
525 DC_SetNextDC (DCToDelete, DC_GetNextDC (savedDC));
526 DCToDelete->saveLevel--;
527 DC_ReleasePtr( savedHDC );
528 W32kDeleteDC (savedHDC);
529 }
530
531 /* Free GDI resources allocated to this DC */
532 if (!(DCToDelete->w.flags & DC_SAVED))
533 {
534 /*
535 W32kSelectObject (DCHandle, STOCK_BLACK_PEN);
536 W32kSelectObject (DCHandle, STOCK_WHITE_BRUSH);
537 W32kSelectObject (DCHandle, STOCK_SYSTEM_FONT);
538 DC_LockDC (DCHandle); W32kSelectObject does not recognize stock objects yet */
539 BITMAPOBJ_ReleasePtr(DCToDelete->w.hBitmap);
540 if (DCToDelete->w.flags & DC_MEMORY)
541 {
542 EngDeleteSurface (DCToDelete->Surface);
543 W32kDeleteObject (DCToDelete->w.hFirstBitmap);
544 }
545 }
546 if (DCToDelete->w.hClipRgn)
547 {
548 W32kDeleteObject (DCToDelete->w.hClipRgn);
549 }
550 if (DCToDelete->w.hVisRgn)
551 {
552 W32kDeleteObject (DCToDelete->w.hVisRgn);
553 }
554 if (NULL != DCToDelete->CombinedClip)
555 {
556 IntEngDeleteClipRegion(DCToDelete->CombinedClip);
557 }
558 if (DCToDelete->w.hGCClipRgn)
559 {
560 W32kDeleteObject (DCToDelete->w.hGCClipRgn);
561 }
562 #if 0 /* FIXME */
563 PATH_DestroyGdiPath (&DCToDelete->w.path);
564 #endif
565 DC_ReleasePtr( DCToDelete );
566 DC_FreeDC (DCToDelete);
567
568 return TRUE;
569 }
570
571 INT STDCALL W32kDrawEscape(HDC hDC,
572 INT nEscape,
573 INT cbInput,
574 LPCSTR lpszInData)
575 {
576 UNIMPLEMENTED;
577 }
578
579 INT STDCALL W32kEnumObjects(HDC hDC,
580 INT ObjectType,
581 GOBJENUMPROC ObjectFunc,
582 LPARAM lParam)
583 {
584 UNIMPLEMENTED;
585 }
586
587 DC_GET_VAL( COLORREF, W32kGetBkColor, w.backgroundColor )
588 DC_GET_VAL( INT, W32kGetBkMode, w.backgroundMode )
589 DC_GET_VAL_EX( W32kGetBrushOrgEx, w.brushOrgX, w.brushOrgY, POINT )
590 DC_GET_VAL( HRGN, W32kGetClipRgn, w.hClipRgn )
591
592 HGDIOBJ STDCALL W32kGetCurrentObject(HDC hDC,
593 UINT ObjectType)
594 {
595 UNIMPLEMENTED;
596 }
597
598 DC_GET_VAL_EX( W32kGetCurrentPositionEx, w.CursPosX, w.CursPosY, POINT )
599
600 BOOL STDCALL W32kGetDCOrgEx(HDC hDC,
601 LPPOINT Point)
602 {
603 PDC dc;
604
605 if (!Point)
606 {
607 return FALSE;
608 }
609 dc = DC_HandleToPtr(hDC);
610 if (dc == NULL)
611 {
612 return FALSE;
613 }
614
615 Point->x = Point->y = 0;
616
617 Point->x += dc->w.DCOrgX;
618 Point->y += dc->w.DCOrgY;
619 DC_ReleasePtr( hDC );
620 return TRUE;
621 }
622
623 HDC STDCALL W32kGetDCState16(HDC hDC)
624 {
625 PDC newdc, dc;
626 HDC hnewdc;
627
628 dc = DC_HandleToPtr(hDC);
629 if (dc == NULL)
630 {
631 return 0;
632 }
633
634 hnewdc = DC_AllocDC(NULL);
635 if (hnewdc == NULL)
636 {
637 DC_ReleasePtr( hDC );
638 return 0;
639 }
640 newdc = DC_HandleToPtr( hnewdc );
641 ASSERT( newdc );
642
643 newdc->w.flags = dc->w.flags | DC_SAVED;
644 newdc->w.hPen = dc->w.hPen;
645 newdc->w.hBrush = dc->w.hBrush;
646 newdc->w.hFont = dc->w.hFont;
647 newdc->w.hBitmap = dc->w.hBitmap;
648 newdc->w.hFirstBitmap = dc->w.hFirstBitmap;
649 #if 0
650 newdc->w.hDevice = dc->w.hDevice;
651 newdc->w.hPalette = dc->w.hPalette;
652 #endif
653 newdc->w.totalExtent = dc->w.totalExtent;
654 newdc->w.bitsPerPixel = dc->w.bitsPerPixel;
655 newdc->w.ROPmode = dc->w.ROPmode;
656 newdc->w.polyFillMode = dc->w.polyFillMode;
657 newdc->w.stretchBltMode = dc->w.stretchBltMode;
658 newdc->w.relAbsMode = dc->w.relAbsMode;
659 newdc->w.backgroundMode = dc->w.backgroundMode;
660 newdc->w.backgroundColor = dc->w.backgroundColor;
661 newdc->w.textColor = dc->w.textColor;
662 newdc->w.brushOrgX = dc->w.brushOrgX;
663 newdc->w.brushOrgY = dc->w.brushOrgY;
664 newdc->w.textAlign = dc->w.textAlign;
665 newdc->w.charExtra = dc->w.charExtra;
666 newdc->w.breakTotalExtra = dc->w.breakTotalExtra;
667 newdc->w.breakCount = dc->w.breakCount;
668 newdc->w.breakExtra = dc->w.breakExtra;
669 newdc->w.breakRem = dc->w.breakRem;
670 newdc->w.MapMode = dc->w.MapMode;
671 newdc->w.GraphicsMode = dc->w.GraphicsMode;
672 #if 0
673 /* Apparently, the DC origin is not changed by [GS]etDCState */
674 newdc->w.DCOrgX = dc->w.DCOrgX;
675 newdc->w.DCOrgY = dc->w.DCOrgY;
676 #endif
677 newdc->w.CursPosX = dc->w.CursPosX;
678 newdc->w.CursPosY = dc->w.CursPosY;
679 newdc->w.ArcDirection = dc->w.ArcDirection;
680 #if 0
681 newdc->w.xformWorld2Wnd = dc->w.xformWorld2Wnd;
682 newdc->w.xformWorld2Vport = dc->w.xformWorld2Vport;
683 newdc->w.xformVport2World = dc->w.xformVport2World;
684 newdc->w.vport2WorldValid = dc->w.vport2WorldValid;
685 #endif
686 newdc->wndOrgX = dc->wndOrgX;
687 newdc->wndOrgY = dc->wndOrgY;
688 newdc->wndExtX = dc->wndExtX;
689 newdc->wndExtY = dc->wndExtY;
690 newdc->vportOrgX = dc->vportOrgX;
691 newdc->vportOrgY = dc->vportOrgY;
692 newdc->vportExtX = dc->vportExtX;
693 newdc->vportExtY = dc->vportExtY;
694
695 newdc->hSelf = hnewdc;
696 newdc->saveLevel = 0;
697
698 #if 0
699 PATH_InitGdiPath( &newdc->w.path );
700 #endif
701
702 /* Get/SetDCState() don't change hVisRgn field ("Undoc. Windows" p.559). */
703
704 #if 0
705 newdc->w.hGCClipRgn = newdc->w.hVisRgn = 0;
706 #endif
707 if (dc->w.hClipRgn)
708 {
709 newdc->w.hClipRgn = W32kCreateRectRgn( 0, 0, 0, 0 );
710 W32kCombineRgn( newdc->w.hClipRgn, dc->w.hClipRgn, 0, RGN_COPY );
711 }
712 else
713 {
714 newdc->w.hClipRgn = 0;
715 }
716 DC_ReleasePtr( hnewdc );
717 return hnewdc;
718 }
719
720 INT STDCALL W32kGetDeviceCaps(HDC hDC,
721 INT Index)
722 {
723 PDC dc;
724 INT ret;
725 POINT pt;
726
727 dc = DC_HandleToPtr(hDC);
728 if (dc == NULL)
729 {
730 return 0;
731 }
732
733 /* Retrieve capability */
734 switch (Index)
735 {
736 case DRIVERVERSION:
737 ret = dc->GDIInfo->ulVersion;
738 break;
739
740 case TECHNOLOGY:
741 ret = dc->GDIInfo->ulTechnology;
742 break;
743
744 case HORZSIZE:
745 ret = dc->GDIInfo->ulHorzSize;
746 break;
747
748 case VERTSIZE:
749 ret = dc->GDIInfo->ulVertSize;
750 break;
751
752 case HORZRES:
753 ret = dc->GDIInfo->ulHorzRes;
754 break;
755
756 case VERTRES:
757 ret = dc->GDIInfo->ulVertRes;
758 break;
759
760 case LOGPIXELSX:
761 ret = dc->GDIInfo->ulLogPixelsX;
762 break;
763
764 case LOGPIXELSY:
765 ret = dc->GDIInfo->ulLogPixelsY;
766 break;
767
768 case BITSPIXEL:
769 ret = dc->GDIInfo->cBitsPixel;
770 break;
771
772 case PLANES:
773 ret = dc->GDIInfo->cPlanes;
774 break;
775
776 case NUMBRUSHES:
777 UNIMPLEMENTED; /* FIXME */
778 break;
779
780 case NUMPENS:
781 UNIMPLEMENTED; /* FIXME */
782 break;
783
784 case NUMFONTS:
785 UNIMPLEMENTED; /* FIXME */
786 break;
787
788 case NUMCOLORS:
789 ret = dc->GDIInfo->ulNumColors;
790 break;
791
792 case ASPECTX:
793 ret = dc->GDIInfo->ulAspectX;
794 break;
795
796 case ASPECTY:
797 ret = dc->GDIInfo->ulAspectY;
798 break;
799
800 case ASPECTXY:
801 ret = dc->GDIInfo->ulAspectXY;
802 break;
803
804 case PDEVICESIZE:
805 UNIMPLEMENTED; /* FIXME */
806 break;
807
808 case CLIPCAPS:
809 UNIMPLEMENTED; /* FIXME */
810 break;
811
812 case SIZEPALETTE:
813 ret = dc->GDIInfo->ulNumPalReg; /* FIXME not sure */
814 break;
815
816 case NUMRESERVED:
817 UNIMPLEMENTED; /* FIXME */
818 break;
819
820 case COLORRES:
821 UNIMPLEMENTED; /* FIXME */
822 break;
823
824 case PHYSICALWIDTH:
825 if(W32kEscape(hDC, GETPHYSPAGESIZE, 0, NULL, (LPVOID)&pt) > 0)
826 {
827 ret = pt.x;
828 }
829 else
830 {
831 ret = 0;
832 }
833 break;
834
835 case PHYSICALHEIGHT:
836 if(W32kEscape(hDC, GETPHYSPAGESIZE, 0, NULL, (LPVOID)&pt) > 0)
837 {
838 ret = pt.y;
839 }
840 else
841 {
842 ret = 0;
843 }
844 break;
845
846 case PHYSICALOFFSETX:
847 if(W32kEscape(hDC, GETPRINTINGOFFSET, 0, NULL, (LPVOID)&pt) > 0)
848 {
849 ret = pt.x;
850 }
851 else
852 {
853 ret = 0;
854 }
855 break;
856
857 case PHYSICALOFFSETY:
858 if(W32kEscape(hDC, GETPRINTINGOFFSET, 0, NULL, (LPVOID)&pt) > 0)
859 {
860 ret = pt.y;
861 }
862 else
863 {
864 ret = 0;
865 }
866 break;
867
868 case VREFRESH:
869 UNIMPLEMENTED; /* FIXME */
870 break;
871
872 case SCALINGFACTORX:
873 if(W32kEscape(hDC, GETSCALINGFACTOR, 0, NULL, (LPVOID)&pt) > 0)
874 {
875 ret = pt.x;
876 }
877 else
878 {
879 ret = 0;
880 }
881 break;
882
883 case SCALINGFACTORY:
884 if(W32kEscape(hDC, GETSCALINGFACTOR, 0, NULL, (LPVOID)&pt) > 0)
885 {
886 ret = pt.y;
887 }
888 else
889 {
890 ret = 0;
891 }
892 break;
893
894 case RASTERCAPS:
895 UNIMPLEMENTED; /* FIXME */
896 break;
897
898 case CURVECAPS:
899 UNIMPLEMENTED; /* FIXME */
900 break;
901
902 case LINECAPS:
903 UNIMPLEMENTED; /* FIXME */
904 break;
905
906 case POLYGONALCAPS:
907 UNIMPLEMENTED; /* FIXME */
908 break;
909
910 case TEXTCAPS:
911 ret = dc->GDIInfo->flTextCaps;
912 break;
913
914 default:
915 ret = 0;
916 break;
917 }
918
919 DPRINT("(%04x,%d): returning %d\n", hDC, Index, ret);
920
921 DC_ReleasePtr( hDC );
922 return ret;
923 }
924
925 DC_GET_VAL( INT, W32kGetMapMode, w.MapMode )
926 DC_GET_VAL( INT, W32kGetPolyFillMode, w.polyFillMode )
927
928 INT STDCALL W32kGetObjectA(HANDLE handle, INT count, LPVOID buffer)
929 {
930 PGDIOBJ gdiObject;
931 INT result = 0;
932 WORD magic;
933
934 if (!count)
935 return 0;
936 gdiObject = GDIOBJ_LockObj (handle, GO_MAGIC_DONTCARE);
937 if (gdiObject == 0)
938 return 0;
939
940 magic = GDIOBJ_GetHandleMagic (handle);
941 switch(magic)
942 {
943 /* case GO_PEN_MAGIC:
944 result = PEN_GetObject((PENOBJ *)gdiObject, count, buffer);
945 break;
946 case GO_BRUSH_MAGIC:
947 result = BRUSH_GetObject((BRUSHOBJ *)gdiObject, count, buffer);
948 break; */
949 case GO_BITMAP_MAGIC:
950 result = BITMAP_GetObject((BITMAPOBJ *)gdiObject, count, buffer);
951 break;
952 /* case GO_FONT_MAGIC:
953 result = FONT_GetObjectA((FONTOBJ *)gdiObject, count, buffer);
954
955 // FIXME: Fix the LOGFONT structure for the stock fonts
956
957 if ( (handle >= FIRST_STOCK_HANDLE) && (handle <= LAST_STOCK_HANDLE) )
958 FixStockFontSizeA(handle, count, buffer);
959 break;
960 case GO_PALETTE_MAGIC:
961 result = PALETTE_GetObject((PALETTEOBJ *)gdiObject, count, buffer);
962 break; */
963
964 case GO_REGION_MAGIC:
965 case GO_DC_MAGIC:
966 case GO_DISABLED_DC_MAGIC:
967 case GO_META_DC_MAGIC:
968 case GO_METAFILE_MAGIC:
969 case GO_METAFILE_DC_MAGIC:
970 case GO_ENHMETAFILE_MAGIC:
971 case GO_ENHMETAFILE_DC_MAGIC:
972 // FIXME("Magic %04x not implemented\n", magic);
973 break;
974
975 default:
976 DbgPrint("Invalid GDI Magic %04x\n", magic);
977 break;
978 }
979 GDIOBJ_UnlockObj (handle, GO_MAGIC_DONTCARE);
980 return result;
981 }
982
983 INT STDCALL W32kGetObjectW(HANDLE handle, INT count, LPVOID buffer)
984 {
985 PGDIOBJHDR gdiObject;
986 INT result = 0;
987 WORD magic;
988
989 if (!count)
990 return 0;
991 gdiObject = GDIOBJ_LockObj(handle, GO_MAGIC_DONTCARE);
992 if (gdiObject == 0)
993 return 0;
994
995 magic = GDIOBJ_GetHandleMagic (handle);
996 switch(magic)
997 {
998 /* case GO_PEN_MAGIC:
999 result = PEN_GetObject((PENOBJ *)gdiObject, count, buffer);
1000 break;
1001 case GO_BRUSH_MAGIC:
1002 result = BRUSH_GetObject((BRUSHOBJ *)gdiObject, count, buffer);
1003 break; */
1004 case GO_BITMAP_MAGIC:
1005 result = BITMAP_GetObject((BITMAPOBJ *)gdiObject, count, buffer);
1006 break;
1007 /* case GO_FONT_MAGIC:
1008 result = FONT_GetObjectW((FONTOBJ *)gdiObject, count, buffer);
1009
1010 // Fix the LOGFONT structure for the stock fonts
1011
1012 if ( (handle >= FIRST_STOCK_HANDLE) && (handle <= LAST_STOCK_HANDLE) )
1013 FixStockFontSizeW(handle, count, buffer);
1014 break;
1015 case GO_PALETTE_MAGIC:
1016 result = PALETTE_GetObject((PALETTEOBJ *)gdiObject, count, buffer);
1017 break; */
1018 default:
1019 // FIXME("Magic %04x not implemented\n", gdiObject->magic);
1020 break;
1021 }
1022 GDIOBJ_UnlockObj(handle, GO_MAGIC_DONTCARE);
1023 return result;
1024 }
1025
1026 INT STDCALL W32kGetObject(HANDLE handle, INT count, LPVOID buffer)
1027 {
1028 return W32kGetObjectW(handle, count, buffer);
1029 }
1030
1031 DWORD STDCALL W32kGetObjectType(HANDLE handle)
1032 {
1033 GDIOBJHDR * ptr;
1034 INT result = 0;
1035 WORD magic;
1036
1037 ptr = GDIOBJ_LockObj(handle, GO_MAGIC_DONTCARE);
1038 if (ptr == 0)
1039 return 0;
1040
1041 magic = GDIOBJ_GetHandleMagic (handle);
1042 switch(magic)
1043 {
1044 case GO_PEN_MAGIC:
1045 result = OBJ_PEN;
1046 break;
1047 case GO_BRUSH_MAGIC:
1048 result = OBJ_BRUSH;
1049 break;
1050 case GO_BITMAP_MAGIC:
1051 result = OBJ_BITMAP;
1052 break;
1053 case GO_FONT_MAGIC:
1054 result = OBJ_FONT;
1055 break;
1056 case GO_PALETTE_MAGIC:
1057 result = OBJ_PAL;
1058 break;
1059 case GO_REGION_MAGIC:
1060 result = OBJ_REGION;
1061 break;
1062 case GO_DC_MAGIC:
1063 result = OBJ_DC;
1064 break;
1065 case GO_META_DC_MAGIC:
1066 result = OBJ_METADC;
1067 break;
1068 case GO_METAFILE_MAGIC:
1069 result = OBJ_METAFILE;
1070 break;
1071 case GO_METAFILE_DC_MAGIC:
1072 result = OBJ_METADC;
1073 break;
1074 case GO_ENHMETAFILE_MAGIC:
1075 result = OBJ_ENHMETAFILE;
1076 break;
1077 case GO_ENHMETAFILE_DC_MAGIC:
1078 result = OBJ_ENHMETADC;
1079 break;
1080 default:
1081 // FIXME("Magic %04x not implemented\n", magic);
1082 break;
1083 }
1084 GDIOBJ_UnlockObj(handle, GO_MAGIC_DONTCARE);
1085 return result;
1086 }
1087
1088 DC_GET_VAL( INT, W32kGetRelAbs, w.relAbsMode )
1089 DC_GET_VAL( INT, W32kGetROP2, w.ROPmode )
1090 DC_GET_VAL( INT, W32kGetStretchBltMode, w.stretchBltMode )
1091 DC_GET_VAL( UINT, W32kGetTextAlign, w.textAlign )
1092 DC_GET_VAL( COLORREF, W32kGetTextColor, w.textColor )
1093 DC_GET_VAL_EX( W32kGetViewportExtEx, vportExtX, vportExtY, SIZE )
1094 DC_GET_VAL_EX( W32kGetViewportOrgEx, vportOrgX, vportOrgY, POINT )
1095 DC_GET_VAL_EX( W32kGetWindowExtEx, wndExtX, wndExtY, SIZE )
1096 DC_GET_VAL_EX( W32kGetWindowOrgEx, wndOrgX, wndOrgY, POINT )
1097
1098 HDC STDCALL W32kResetDC(HDC hDC, CONST DEVMODEW *InitData)
1099 {
1100 UNIMPLEMENTED;
1101 }
1102
1103 BOOL STDCALL W32kRestoreDC(HDC hDC, INT SaveLevel)
1104 {
1105 PDC dc, dcs;
1106 BOOL success;
1107
1108 dc = DC_HandleToPtr(hDC);
1109 if(!dc)
1110 {
1111 return FALSE;
1112 }
1113
1114 if (SaveLevel == -1)
1115 {
1116 SaveLevel = dc->saveLevel;
1117 }
1118
1119 if ((SaveLevel < 1) || (SaveLevel > dc->saveLevel))
1120 {
1121 return FALSE;
1122 }
1123
1124 success = TRUE;
1125 while (dc->saveLevel >= SaveLevel)
1126 {
1127 HDC hdcs = DC_GetNextDC (dc);
1128
1129 dcs = DC_HandleToPtr (hdcs);
1130 if (dcs == NULL)
1131 {
1132 return FALSE;
1133 }
1134 DC_SetNextDC (dcs, DC_GetNextDC (dcs));
1135 if (--dc->saveLevel < SaveLevel)
1136 {
1137 W32kSetDCState16 (hDC, hdcs);
1138 #if 0
1139 if (!PATH_AssignGdiPath( &dc->w.path, &dcs->w.path ))
1140 {
1141 /* FIXME: This might not be quite right, since we're
1142 * returning FALSE but still destroying the saved DC state */
1143 success = FALSE;
1144 }
1145 #endif
1146 }
1147 DC_ReleasePtr( hdcs );
1148 W32kDeleteDC (hdcs);
1149 }
1150 DC_ReleasePtr( hDC );
1151 return success;
1152 }
1153
1154 INT STDCALL W32kSaveDC(HDC hDC)
1155 {
1156 HDC hdcs;
1157 PDC dc, dcs;
1158 INT ret;
1159
1160 dc = DC_HandleToPtr (hDC);
1161 if (dc == NULL)
1162 {
1163 return 0;
1164 }
1165
1166 if (!(hdcs = W32kGetDCState16 (hDC)))
1167 {
1168 return 0;
1169 }
1170 dcs = DC_HandleToPtr (hdcs);
1171
1172 #if 0
1173 /* Copy path. The reason why path saving / restoring is in SaveDC/
1174 * RestoreDC and not in GetDCState/SetDCState is that the ...DCState
1175 * functions are only in Win16 (which doesn't have paths) and that
1176 * SetDCState doesn't allow us to signal an error (which can happen
1177 * when copying paths).
1178 */
1179 if (!PATH_AssignGdiPath (&dcs->w.path, &dc->w.path))
1180 {
1181 W32kDeleteDC (hdcs);
1182 return 0;
1183 }
1184 #endif
1185
1186 DC_SetNextDC (dcs, DC_GetNextDC (dc));
1187 DC_SetNextDC (dc, hdcs);
1188 ret = ++dc->saveLevel;
1189 DC_ReleasePtr( hdcs );
1190 DC_ReleasePtr( hDC );
1191
1192 return ret;
1193 }
1194
1195 HGDIOBJ STDCALL W32kSelectObject(HDC hDC, HGDIOBJ hGDIObj)
1196 {
1197 HGDIOBJ objOrg;
1198 BITMAPOBJ *pb;
1199 PDC dc;
1200 PPENOBJ pen;
1201 PBRUSHOBJ brush;
1202 PXLATEOBJ XlateObj;
1203 PPALGDI PalGDI;
1204 WORD objectMagic;
1205 COLORREF *ColorMap;
1206 ULONG NumColors, Index;
1207 HRGN hVisRgn;
1208
1209 if(!hDC || !hGDIObj) return NULL;
1210
1211 dc = DC_HandleToPtr(hDC);
1212 objectMagic = GDIOBJ_GetHandleMagic (hGDIObj);
1213 // GdiObjHdr = hGDIObj;
1214
1215 // FIXME: Get object handle from GDIObj and use it instead of GDIObj below?
1216
1217 switch(objectMagic) {
1218 case GO_PEN_MAGIC:
1219 objOrg = (HGDIOBJ)dc->w.hPen;
1220 dc->w.hPen = hGDIObj;
1221
1222 // Convert the color of the pen to the format of the DC
1223 PalGDI = (PPALGDI)AccessInternalObject((ULONG) dc->w.hPalette);
1224 if( PalGDI ){
1225 XlateObj = (PXLATEOBJ)IntEngCreateXlate(PalGDI->Mode, PAL_RGB, dc->w.hPalette, NULL);
1226 pen = GDIOBJ_LockObj(dc->w.hPen, GO_PEN_MAGIC);
1227 if( pen ){
1228 pen->logpen.lopnColor = XLATEOBJ_iXlate(XlateObj, pen->logpen.lopnColor);
1229 }
1230 GDIOBJ_UnlockObj( dc->w.hPen, GO_PEN_MAGIC);
1231 EngDeleteXlate(XlateObj);
1232 }
1233 break;
1234
1235 case GO_BRUSH_MAGIC:
1236 objOrg = (HGDIOBJ)dc->w.hBrush;
1237 dc->w.hBrush = (HBRUSH) hGDIObj;
1238
1239 // Convert the color of the brush to the format of the DC
1240 PalGDI = (PPALGDI)AccessInternalObject((ULONG) dc->w.hPalette);
1241 if( PalGDI ){
1242 XlateObj = (PXLATEOBJ)IntEngCreateXlate(PalGDI->Mode, PAL_RGB, dc->w.hPalette, NULL);
1243 brush = GDIOBJ_LockObj(dc->w.hBrush, GO_BRUSH_MAGIC);
1244 if( brush ){
1245 brush->iSolidColor = XLATEOBJ_iXlate(XlateObj, brush->logbrush.lbColor);
1246 }
1247 GDIOBJ_UnlockObj( dc->w.hBrush, GO_BRUSH_MAGIC);
1248 EngDeleteXlate(XlateObj);
1249 }
1250 break;
1251
1252 case GO_FONT_MAGIC:
1253 objOrg = (HGDIOBJ)dc->w.hFont;
1254 dc->w.hFont = (HFONT) hGDIObj;
1255 TextIntRealizeFont(dc->w.hFont);
1256 break;
1257
1258 case GO_BITMAP_MAGIC:
1259 // must be memory dc to select bitmap
1260 if (!(dc->w.flags & DC_MEMORY)) return NULL;
1261 objOrg = (HGDIOBJ)dc->w.hBitmap;
1262
1263 /* Release the old bitmap, lock the new one and convert it to a SURF */
1264 EngDeleteSurface(dc->Surface);
1265 BITMAPOBJ_ReleasePtr(objOrg);
1266 dc->w.hBitmap = hGDIObj;
1267 pb = BITMAPOBJ_HandleToPtr(hGDIObj);
1268 dc->Surface = BitmapToSurf(pb);
1269
1270 // if we're working with a DIB, get the palette [fixme: only create if the selected palette is null]
1271 if(pb->dib)
1272 {
1273 dc->w.bitsPerPixel = pb->dib->dsBmih.biBitCount;
1274
1275 if(pb->dib->dsBmih.biBitCount <= 8)
1276 {
1277 if(pb->dib->dsBmih.biBitCount == 1) { NumColors = 2; } else
1278 if(pb->dib->dsBmih.biBitCount == 4) { NumColors = 16; } else
1279 if(pb->dib->dsBmih.biBitCount == 8) { NumColors = 256; }
1280
1281 ColorMap = ExAllocatePool(PagedPool, sizeof(COLORREF) * NumColors);
1282 for (Index = 0; Index < NumColors; Index++)
1283 {
1284 ColorMap[Index] = RGB(pb->ColorMap[Index].rgbRed,
1285 pb->ColorMap[Index].rgbGreen,
1286 pb->ColorMap[Index].rgbBlue);
1287 }
1288 dc->w.hPalette = EngCreatePalette(PAL_INDEXED, NumColors, (ULONG *) ColorMap, 0, 0, 0);
1289 ExFreePool(ColorMap);
1290 } else
1291 if(16 == pb->dib->dsBmih.biBitCount)
1292 {
1293 dc->w.hPalette = EngCreatePalette(PAL_BITFIELDS, pb->dib->dsBmih.biClrUsed, NULL, 0x7c00, 0x03e0, 0x001f);
1294 } else
1295 if(pb->dib->dsBmih.biBitCount >= 24)
1296 {
1297 dc->w.hPalette = EngCreatePalette(PAL_RGB, pb->dib->dsBmih.biClrUsed, NULL, 0, 0, 0);
1298 }
1299 } else {
1300 dc->w.bitsPerPixel = pb->bitmap.bmBitsPixel;
1301 }
1302
1303 hVisRgn = W32kCreateRectRgn(0, 0, pb->size.cx, pb->size.cy);
1304 W32kSelectVisRgn(hDC, hVisRgn);
1305 W32kDeleteObject(hVisRgn);
1306
1307 break;
1308
1309 #if UPDATEREGIONS
1310 case GO_REGION_MAGIC:
1311 /* objOrg = (HGDIOBJ)hDC->region; */
1312 objOrg = NULL; /* FIXME? hDC->region is destroyed below */
1313 SelectClipRgn(hDC, (HRGN)hGDIObj);
1314 break;
1315 #endif
1316 default:
1317 return NULL;
1318 }
1319 DC_ReleasePtr( hDC );
1320 return objOrg;
1321 }
1322
1323 DC_SET_MODE( W32kSetBkMode, w.backgroundMode, TRANSPARENT, OPAQUE )
1324 DC_SET_MODE( W32kSetPolyFillMode, w.polyFillMode, ALTERNATE, WINDING )
1325 // DC_SET_MODE( W32kSetRelAbs, w.relAbsMode, ABSOLUTE, RELATIVE )
1326 DC_SET_MODE( W32kSetROP2, w.ROPmode, R2_BLACK, R2_WHITE )
1327 DC_SET_MODE( W32kSetStretchBltMode, w.stretchBltMode, BLACKONWHITE, HALFTONE )
1328
1329 COLORREF STDCALL W32kSetBkColor(HDC hDC, COLORREF color)
1330 {
1331 COLORREF oldColor;
1332 PDC dc = DC_HandleToPtr(hDC);
1333
1334 if (!dc)
1335 {
1336 return 0x80000000;
1337 }
1338
1339 oldColor = dc->w.backgroundColor;
1340 dc->w.backgroundColor = color;
1341 DC_ReleasePtr( hDC );
1342 return oldColor;
1343 }
1344
1345 STATIC VOID FASTCALL W32kSetDCState16(HDC hDC, HDC hDCSave)
1346 {
1347 PDC dc, dcs;
1348
1349 dc = DC_HandleToPtr(hDC);
1350 if (dc == NULL)
1351 {
1352 return;
1353 }
1354
1355 dcs = DC_HandleToPtr(hDCSave);
1356 if (dcs == NULL)
1357 {
1358 DC_ReleasePtr( hDC );
1359 return;
1360 }
1361 if (!dcs->w.flags & DC_SAVED)
1362 {
1363 return;
1364 }
1365
1366 dc->w.flags = dcs->w.flags & ~DC_SAVED;
1367
1368 dc->w.hFirstBitmap = dcs->w.hFirstBitmap;
1369
1370 #if 0
1371 dc->w.hDevice = dcs->w.hDevice;
1372 #endif
1373
1374 dc->w.totalExtent = dcs->w.totalExtent;
1375 dc->w.ROPmode = dcs->w.ROPmode;
1376 dc->w.polyFillMode = dcs->w.polyFillMode;
1377 dc->w.stretchBltMode = dcs->w.stretchBltMode;
1378 dc->w.relAbsMode = dcs->w.relAbsMode;
1379 dc->w.backgroundMode = dcs->w.backgroundMode;
1380 dc->w.backgroundColor = dcs->w.backgroundColor;
1381 dc->w.textColor = dcs->w.textColor;
1382 dc->w.brushOrgX = dcs->w.brushOrgX;
1383 dc->w.brushOrgY = dcs->w.brushOrgY;
1384 dc->w.textAlign = dcs->w.textAlign;
1385 dc->w.charExtra = dcs->w.charExtra;
1386 dc->w.breakTotalExtra = dcs->w.breakTotalExtra;
1387 dc->w.breakCount = dcs->w.breakCount;
1388 dc->w.breakExtra = dcs->w.breakExtra;
1389 dc->w.breakRem = dcs->w.breakRem;
1390 dc->w.MapMode = dcs->w.MapMode;
1391 dc->w.GraphicsMode = dcs->w.GraphicsMode;
1392 #if 0
1393 /* Apparently, the DC origin is not changed by [GS]etDCState */
1394 dc->w.DCOrgX = dcs->w.DCOrgX;
1395 dc->w.DCOrgY = dcs->w.DCOrgY;
1396 #endif
1397 dc->w.CursPosX = dcs->w.CursPosX;
1398 dc->w.CursPosY = dcs->w.CursPosY;
1399 dc->w.ArcDirection = dcs->w.ArcDirection;
1400
1401 #if 0
1402 dc->w.xformWorld2Wnd = dcs->w.xformWorld2Wnd;
1403 dc->w.xformWorld2Vport = dcs->w.xformWorld2Vport;
1404 dc->w.xformVport2World = dcs->w.xformVport2World;
1405 dc->w.vport2WorldValid = dcs->w.vport2WorldValid;
1406 #endif
1407
1408 dc->wndOrgX = dcs->wndOrgX;
1409 dc->wndOrgY = dcs->wndOrgY;
1410 dc->wndExtX = dcs->wndExtX;
1411 dc->wndExtY = dcs->wndExtY;
1412 dc->vportOrgX = dcs->vportOrgX;
1413 dc->vportOrgY = dcs->vportOrgY;
1414 dc->vportExtX = dcs->vportExtX;
1415 dc->vportExtY = dcs->vportExtY;
1416
1417 if (!(dc->w.flags & DC_MEMORY))
1418 {
1419 dc->w.bitsPerPixel = dcs->w.bitsPerPixel;
1420 }
1421
1422 #if 0
1423 if (dcs->w.hClipRgn)
1424 {
1425 if (!dc->w.hClipRgn)
1426 {
1427 dc->w.hClipRgn = W32kCreateRectRgn( 0, 0, 0, 0 );
1428 }
1429 W32kCombineRgn( dc->w.hClipRgn, dcs->w.hClipRgn, 0, RGN_COPY );
1430 }
1431 else
1432 {
1433 if (dc->w.hClipRgn)
1434 {
1435 W32kDeleteObject( dc->w.hClipRgn );
1436 }
1437
1438 dc->w.hClipRgn = 0;
1439 }
1440 CLIPPING_UpdateGCRegion( dc );
1441 #endif
1442
1443 W32kSelectObject( hDC, dcs->w.hBitmap );
1444 W32kSelectObject( hDC, dcs->w.hBrush );
1445 W32kSelectObject( hDC, dcs->w.hFont );
1446 W32kSelectObject( hDC, dcs->w.hPen );
1447 W32kSetBkColor( hDC, dcs->w.backgroundColor);
1448 W32kSetTextColor( hDC, dcs->w.textColor);
1449
1450 #if 0
1451 GDISelectPalette16( hDC, dcs->w.hPalette, FALSE );
1452 #endif
1453
1454 DC_ReleasePtr( hDCSave );
1455 DC_ReleasePtr( hDC );
1456 }
1457
1458 // ---------------------------------------------------- Private Interface
1459
1460 HDC FASTCALL DC_AllocDC(LPCWSTR Driver)
1461 {
1462 PDC NewDC;
1463 HDC hDC;
1464
1465 hDC = (HDC) GDIOBJ_AllocObj(sizeof(DC), GO_DC_MAGIC);
1466 if (hDC == NULL)
1467 {
1468 return NULL;
1469 }
1470
1471 NewDC = (PDC) GDIOBJ_LockObj( hDC, GO_DC_MAGIC );
1472
1473 if (Driver != NULL)
1474 {
1475 NewDC->DriverName = ExAllocatePool(PagedPool, (wcslen(Driver) + 1) * sizeof(WCHAR));
1476 wcscpy(NewDC->DriverName, Driver);
1477 }
1478
1479 NewDC->w.xformWorld2Wnd.eM11 = 1.0f;
1480 NewDC->w.xformWorld2Wnd.eM12 = 0.0f;
1481 NewDC->w.xformWorld2Wnd.eM21 = 0.0f;
1482 NewDC->w.xformWorld2Wnd.eM22 = 1.0f;
1483 NewDC->w.xformWorld2Wnd.eDx = 0.0f;
1484 NewDC->w.xformWorld2Wnd.eDy = 0.0f;
1485 NewDC->w.xformWorld2Vport = NewDC->w.xformWorld2Wnd;
1486 NewDC->w.xformVport2World = NewDC->w.xformWorld2Wnd;
1487 NewDC->w.vport2WorldValid = TRUE;
1488
1489 NewDC->w.hFont = W32kGetStockObject(SYSTEM_FONT);
1490
1491 GDIOBJ_UnlockObj( hDC, GO_DC_MAGIC );
1492 return hDC;
1493 }
1494
1495 HDC FASTCALL DC_FindOpenDC(LPCWSTR Driver)
1496 {
1497 return NULL;
1498 }
1499
1500 /*!
1501 * Initialize some common fields in the Device Context structure.
1502 */
1503 VOID FASTCALL DC_InitDC(HDC DCHandle)
1504 {
1505 // W32kRealizeDefaultPalette(DCHandle);
1506
1507 W32kSelectObject(DCHandle, W32kGetStockObject( WHITE_BRUSH ));
1508 W32kSelectObject(DCHandle, W32kGetStockObject( BLACK_PEN ));
1509 //W32kSelectObject(DCHandle, hFont);
1510
1511 // CLIPPING_UpdateGCRegion(DCToInit);
1512
1513 }
1514
1515 VOID FASTCALL DC_FreeDC(HDC DCToFree)
1516 {
1517 if (!GDIOBJ_FreeObj(DCToFree, GO_DC_MAGIC, GDIOBJFLAG_DEFAULT))
1518 {
1519 DPRINT("DC_FreeDC failed\n");
1520 }
1521 }
1522
1523 BOOL FASTCALL DC_InternalDeleteDC( PDC DCToDelete )
1524 {
1525 if( DCToDelete->DriverName )
1526 ExFreePool(DCToDelete->DriverName);
1527 return TRUE;
1528 }
1529
1530 HDC FASTCALL DC_GetNextDC (PDC pDC)
1531 {
1532 return pDC->hNext;
1533 }
1534
1535 VOID FASTCALL DC_SetNextDC (PDC pDC, HDC hNextDC)
1536 {
1537 pDC->hNext = hNextDC;
1538 }
1539
1540 VOID FASTCALL
1541 DC_UpdateXforms(PDC dc)
1542 {
1543 XFORM xformWnd2Vport;
1544 FLOAT scaleX, scaleY;
1545
1546 /* Construct a transformation to do the window-to-viewport conversion */
1547 scaleX = (FLOAT)dc->vportExtX / (FLOAT)dc->wndExtX;
1548 scaleY = (FLOAT)dc->vportExtY / (FLOAT)dc->wndExtY;
1549 xformWnd2Vport.eM11 = scaleX;
1550 xformWnd2Vport.eM12 = 0.0;
1551 xformWnd2Vport.eM21 = 0.0;
1552 xformWnd2Vport.eM22 = scaleY;
1553 xformWnd2Vport.eDx = (FLOAT)dc->vportOrgX - scaleX * (FLOAT)dc->wndOrgX;
1554 xformWnd2Vport.eDy = (FLOAT)dc->vportOrgY - scaleY * (FLOAT)dc->wndOrgY;
1555
1556 /* Combine with the world transformation */
1557 W32kCombineTransform(&dc->w.xformWorld2Vport, &dc->w.xformWorld2Wnd, &xformWnd2Vport);
1558
1559 /* Create inverse of world-to-viewport transformation */
1560 dc->w.vport2WorldValid = DC_InvertXform(&dc->w.xformWorld2Vport, &dc->w.xformVport2World);
1561 }
1562
1563 BOOL FASTCALL
1564 DC_InvertXform(const XFORM *xformSrc,
1565 XFORM *xformDest)
1566 {
1567 FLOAT determinant;
1568
1569 determinant = xformSrc->eM11*xformSrc->eM22 - xformSrc->eM12*xformSrc->eM21;
1570 if (determinant > -1e-12 && determinant < 1e-12)
1571 {
1572 return FALSE;
1573 }
1574
1575 xformDest->eM11 = xformSrc->eM22 / determinant;
1576 xformDest->eM12 = -xformSrc->eM12 / determinant;
1577 xformDest->eM21 = -xformSrc->eM21 / determinant;
1578 xformDest->eM22 = xformSrc->eM11 / determinant;
1579 xformDest->eDx = -xformSrc->eDx * xformDest->eM11 - xformSrc->eDy * xformDest->eM21;
1580 xformDest->eDy = -xformSrc->eDx * xformDest->eM12 - xformSrc->eDy * xformDest->eM22;
1581
1582 return TRUE;
1583 }
1584 /* EOF */