bb8df5221a178510c69a359119e45bf14e84cd6f
[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.91 2003/10/25 10:59:19 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/brush.h>
32 #include <win32k/cliprgn.h>
33 #include <win32k/coord.h>
34 #include <win32k/driver.h>
35 #include <win32k/dc.h>
36 #include <win32k/misc.h>
37 #include <win32k/print.h>
38 #include <win32k/region.h>
39 #include <win32k/gdiobj.h>
40 #include <win32k/paint.h>
41 #include <win32k/pen.h>
42 #include <win32k/text.h>
43 #include "../eng/clip.h"
44 #include "../eng/handle.h"
45 #include <include/dce.h>
46 #include <include/error.h>
47 #include <include/inteng.h>
48 #include <include/eng.h>
49 #include <include/palette.h>
50
51 #define NDEBUG
52 #include <win32k/debug1.h>
53
54 #define TAG_DC TAG('D', 'C', 'D', 'C')
55
56 static GDIDEVICE PrimarySurface;
57 static BOOL PrimarySurfaceCreated = FALSE;
58
59 /* FIXME: DCs should probably be thread safe */
60
61 /*
62 * DC device-independent Get/SetXXX functions
63 * (RJJ) swiped from WINE
64 */
65
66 #define DC_GET_VAL( func_type, func_name, dc_field ) \
67 func_type STDCALL func_name( HDC hdc ) \
68 { \
69 func_type ft; \
70 PDC dc = DC_LockDc( hdc ); \
71 if (!dc) \
72 { \
73 return 0; \
74 } \
75 ft = dc->dc_field; \
76 DC_UnlockDc( hdc ); \
77 return ft; \
78 }
79
80 /* DC_GET_VAL_EX is used to define functions returning a POINT or a SIZE. It is
81 * important that the function has the right signature, for the implementation
82 * we can do whatever we want.
83 */
84 #define DC_GET_VAL_EX( NtGdiFuncName, IntFuncName, ret_x, ret_y, type ) \
85 VOID FASTCALL IntFuncName ( PDC dc, LP##type pt ) \
86 { \
87 ASSERT ( dc ); \
88 ASSERT ( pt ); \
89 ((LPPOINT)pt)->x = dc->ret_x; \
90 ((LPPOINT)pt)->y = dc->ret_y; \
91 } \
92 BOOL STDCALL NtGdiFuncName ( HDC hdc, LP##type pt ) \
93 { \
94 PDC dc = DC_LockDc ( hdc ); \
95 if ( !dc ) \
96 return FALSE; \
97 IntFuncName ( dc, pt ); \
98 DC_UnlockDc ( hdc ); \
99 return TRUE; \
100 }
101
102 #define DC_SET_MODE( func_name, dc_field, min_val, max_val ) \
103 INT STDCALL func_name( HDC hdc, INT mode ) \
104 { \
105 INT prevMode; \
106 PDC dc; \
107 if ((mode < min_val) || (mode > max_val)) \
108 return 0; \
109 dc = DC_LockDc ( hdc ); \
110 if ( !dc ) \
111 return 0; \
112 prevMode = dc->dc_field; \
113 dc->dc_field = mode; \
114 DC_UnlockDc ( hdc ); \
115 return prevMode; \
116 }
117
118
119 // --------------------------------------------------------- File Statics
120
121 // ----------------------------------------------------- Public Functions
122
123 BOOL STDCALL
124 NtGdiCancelDC(HDC hDC)
125 {
126 UNIMPLEMENTED;
127 }
128
129 HDC STDCALL
130 NtGdiCreateCompatableDC(HDC hDC)
131 {
132 PDC NewDC, OrigDC;
133 HBITMAP hBitmap;
134 HDC hNewDC;
135 HRGN hVisRgn;
136 BITMAPOBJ *pb;
137 PSURFGDI SurfGDI;
138
139 if (hDC == NULL)
140 {
141 if (! PrimarySurfaceCreated)
142 {
143 DPRINT1("Can't create compatible DC because initialization of primary surface failed\n");
144 return NULL;
145 }
146 OrigDC = NULL;
147 hNewDC = DC_AllocDC(L"DISPLAY");
148 }
149 else
150 {
151 /* Allocate a new DC based on the original DC's device */
152 OrigDC = DC_LockDc(hDC);
153 if (NULL == OrigDC)
154 {
155 return NULL;
156 }
157 hNewDC = DC_AllocDC(OrigDC->DriverName);
158 }
159
160 if (NULL == hNewDC)
161 {
162 return NULL;
163 }
164 NewDC = DC_LockDc( hNewDC );
165
166 /* Copy information from original DC to new DC */
167 NewDC->hSelf = NewDC;
168
169 /* FIXME: Should this DC request its own PDEV? */
170 if(OrigDC == NULL)
171 {
172 NewDC->PDev = PrimarySurface.PDev;
173 memcpy(NewDC->FillPatternSurfaces, PrimarySurface.FillPatterns,
174 sizeof(NewDC->FillPatternSurfaces));
175 NewDC->GDIInfo = &PrimarySurface.GDIInfo;
176 NewDC->DevInfo = &PrimarySurface.DevInfo;
177 SurfGDI = (PSURFGDI)AccessInternalObject((ULONG) PrimarySurface.Handle);
178 NewDC->w.bitsPerPixel = SurfGDI->BitsPerPixel;
179 }
180 else
181 {
182 NewDC->PDev = OrigDC->PDev;
183 NewDC->DMW = OrigDC->DMW;
184 memcpy(NewDC->FillPatternSurfaces,
185 OrigDC->FillPatternSurfaces,
186 sizeof OrigDC->FillPatternSurfaces);
187 NewDC->GDIInfo = OrigDC->GDIInfo;
188 NewDC->DevInfo = OrigDC->DevInfo;
189 NewDC->w.bitsPerPixel = OrigDC->w.bitsPerPixel;
190 }
191
192 /* DriverName is copied in the AllocDC routine */
193 if(OrigDC == NULL)
194 {
195 NewDC->DeviceDriver = DRIVER_FindMPDriver(NewDC->DriverName);
196 }
197 else
198 {
199 NewDC->DeviceDriver = OrigDC->DeviceDriver;
200 NewDC->wndOrgX = OrigDC->wndOrgX;
201 NewDC->wndOrgY = OrigDC->wndOrgY;
202 NewDC->wndExtX = OrigDC->wndExtX;
203 NewDC->wndExtY = OrigDC->wndExtY;
204 NewDC->vportOrgX = OrigDC->vportOrgX;
205 NewDC->vportOrgY = OrigDC->vportOrgY;
206 NewDC->vportExtX = OrigDC->vportExtX;
207 NewDC->vportExtY = OrigDC->vportExtY;
208 }
209
210 /* Create default bitmap */
211 if (!(hBitmap = NtGdiCreateBitmap( 1, 1, 1, NewDC->w.bitsPerPixel, NULL )))
212 {
213 DC_UnlockDc( hDC );
214 DC_UnlockDc( hNewDC );
215 DC_FreeDC( hNewDC );
216 return NULL;
217 }
218 NewDC->w.flags = DC_MEMORY;
219 NewDC->w.hBitmap = hBitmap;
220 NewDC->w.hFirstBitmap = hBitmap;
221 pb = BITMAPOBJ_LockBitmap(hBitmap);
222 NewDC->Surface = BitmapToSurf(pb);
223 BITMAPOBJ_UnlockBitmap(hBitmap);
224
225 if(OrigDC == NULL)
226 {
227 NewDC->w.hPalette = NewDC->DevInfo->hpalDefault;
228 }
229 else
230 {
231 NewDC->w.hPalette = OrigDC->w.hPalette;
232 NewDC->w.textColor = OrigDC->w.textColor;
233 NewDC->w.textAlign = OrigDC->w.textAlign;
234 NewDC->w.backgroundColor = OrigDC->w.backgroundColor;
235 NewDC->w.backgroundMode = OrigDC->w.backgroundMode;
236 }
237 if (NULL != hDC)
238 {
239 DC_UnlockDc( hDC );
240 }
241 DC_UnlockDc( hNewDC );
242
243 hVisRgn = NtGdiCreateRectRgn(0, 0, 1, 1);
244 NtGdiSelectVisRgn(hNewDC, hVisRgn);
245 NtGdiDeleteObject(hVisRgn);
246
247 DC_InitDC(hNewDC);
248
249 return hNewDC;
250 }
251
252 static BOOL FASTCALL
253 GetRegistryPath(PUNICODE_STRING RegistryPath)
254 {
255 RTL_QUERY_REGISTRY_TABLE QueryTable[2];
256 NTSTATUS Status;
257
258 RtlInitUnicodeString(RegistryPath, NULL);
259 RtlZeroMemory(QueryTable, sizeof(QueryTable));
260 QueryTable[0].Flags = RTL_QUERY_REGISTRY_REQUIRED | RTL_QUERY_REGISTRY_DIRECT;
261 QueryTable[0].Name = L"\\Device\\Video0";
262 QueryTable[0].EntryContext = RegistryPath;
263
264 Status = RtlQueryRegistryValues(RTL_REGISTRY_DEVICEMAP,
265 L"VIDEO",
266 QueryTable,
267 NULL,
268 NULL);
269 if (! NT_SUCCESS(Status))
270 {
271 DPRINT1("No \\Device\\Video0 value in DEVICEMAP\\VIDEO found\n");
272 return FALSE;
273 }
274
275 DPRINT("RegistryPath %S\n", RegistryPath.Buffer);
276
277 return TRUE;
278 }
279
280 static BOOL FASTCALL
281 FindDriverFileNames(PUNICODE_STRING DriverFileNames)
282 {
283 RTL_QUERY_REGISTRY_TABLE QueryTable[2];
284 UNICODE_STRING RegistryPath;
285 NTSTATUS Status;
286
287 if (! GetRegistryPath(&RegistryPath))
288 {
289 DPRINT("GetRegistryPath failed\n");
290 return FALSE;
291 }
292
293 RtlZeroMemory(QueryTable, sizeof(QueryTable));
294 QueryTable[0].Flags = RTL_QUERY_REGISTRY_REQUIRED | RTL_QUERY_REGISTRY_DIRECT;
295 QueryTable[0].Name = L"InstalledDisplayDrivers";
296 QueryTable[0].EntryContext = DriverFileNames;
297
298 Status = RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE,
299 RegistryPath.Buffer,
300 QueryTable,
301 NULL,
302 NULL);
303 RtlFreeUnicodeString(&RegistryPath);
304 if (! NT_SUCCESS(Status))
305 {
306 DPRINT1("No InstalledDisplayDrivers value in service entry found\n");
307 return FALSE;
308 }
309
310 DPRINT("DriverFileNames %S\n", DriverFileNames->Buffer);
311
312 return TRUE;
313 }
314
315 static void FASTCALL
316 CloseMiniport()
317 {
318 PEPROCESS CurrentProcess;
319
320 CurrentProcess = PsGetCurrentProcess();
321 if (CurrentProcess != Win32kDeviceProcess)
322 {
323 KeAttachProcess(Win32kDeviceProcess);
324 }
325 ZwClose(PrimarySurface.DisplayDevice);
326 if (CurrentProcess != Win32kDeviceProcess)
327 {
328 KeDetachProcess();
329 }
330 }
331
332 static NTSTATUS STDCALL
333 DevModeCallback(IN PWSTR ValueName,
334 IN ULONG ValueType,
335 IN PVOID ValueData,
336 IN ULONG ValueLength,
337 IN PVOID Context,
338 IN PVOID EntryContext)
339 {
340 PDEVMODEW DevMode = (PDEVMODEW) Context;
341
342 DPRINT("Found registry value for name %S: type %d, length %d\n",
343 ValueName, ValueType, ValueLength);
344
345 if (REG_DWORD == ValueType && sizeof(DWORD) == ValueLength)
346 {
347 if (0 == _wcsicmp(ValueName, L"DefaultSettings.BitsPerPel"))
348 {
349 DevMode->dmBitsPerPel = *((DWORD *) ValueData);
350 }
351 else if (0 == _wcsicmp(ValueName, L"DefaultSettings.Flags"))
352 {
353 DevMode->dmDisplayFlags = *((DWORD *) ValueData);
354 }
355 else if (0 == _wcsicmp(ValueName, L"DefaultSettings.VRefresh"))
356 {
357 DevMode->dmDisplayFrequency = *((DWORD *) ValueData);
358 }
359 else if (0 == _wcsicmp(ValueName, L"DefaultSettings.XPanning"))
360 {
361 DevMode->dmPanningWidth = *((DWORD *) ValueData);
362 }
363 else if (0 == _wcsicmp(ValueName, L"DefaultSettings.XResolution"))
364 {
365 DevMode->dmPelsWidth = *((DWORD *) ValueData);
366 }
367 else if (0 == _wcsicmp(ValueName, L"DefaultSettings.YPanning"))
368 {
369 DevMode->dmPanningHeight = *((DWORD *) ValueData);
370 }
371 else if (0 == _wcsicmp(ValueName, L"DefaultSettings.YResolution"))
372 {
373 DevMode->dmPelsHeight = *((DWORD *) ValueData);
374 }
375 }
376
377 return STATUS_SUCCESS;
378 }
379
380 static BOOL FASTCALL
381 SetupDevMode(PDEVMODEW DevMode)
382 {
383 static WCHAR RegistryMachineSystem[] = L"\\REGISTRY\\MACHINE\\SYSTEM\\";
384 static WCHAR CurrentControlSet[] = L"CURRENTCONTROLSET\\";
385 static WCHAR ControlSet[] = L"CONTROLSET";
386 static WCHAR Insert[] = L"Hardware Profiles\\Current\\System\\CurrentControlSet\\";
387 UNICODE_STRING RegistryPath;
388 BOOL Valid;
389 PWCHAR AfterControlSet;
390 PWCHAR ProfilePath;
391 RTL_QUERY_REGISTRY_TABLE QueryTable[2];
392 NTSTATUS Status;
393
394 if (! GetRegistryPath(&RegistryPath))
395 {
396 DPRINT("GetRegistryPath failed\n");
397 return FALSE;
398 }
399
400 Valid = (0 == _wcsnicmp(RegistryPath.Buffer, RegistryMachineSystem,
401 wcslen(RegistryMachineSystem)));
402 if (Valid)
403 {
404 AfterControlSet = RegistryPath.Buffer + wcslen(RegistryMachineSystem);
405 if (0 == _wcsnicmp(AfterControlSet, CurrentControlSet, wcslen(CurrentControlSet)))
406 {
407 AfterControlSet += wcslen(CurrentControlSet);
408 }
409 else if (0 == _wcsnicmp(AfterControlSet, ControlSet, wcslen(ControlSet)))
410 {
411 AfterControlSet += wcslen(ControlSet);
412 while (L'0' <= *AfterControlSet && L'9' <= *AfterControlSet)
413 {
414 AfterControlSet++;
415 }
416 Valid = (L'\\' == *AfterControlSet);
417 AfterControlSet++;
418 }
419 else
420 {
421 Valid = FALSE;
422 }
423 }
424
425 if (Valid)
426 {
427 ProfilePath = ExAllocatePoolWithTag(PagedPool,
428 (wcslen(RegistryPath.Buffer) +
429 wcslen(Insert) + 1) * sizeof(WCHAR),
430 TAG_DC);
431 if (NULL != ProfilePath)
432 {
433 wcsncpy(ProfilePath, RegistryPath.Buffer, AfterControlSet - RegistryPath.Buffer);
434 wcscpy(ProfilePath + (AfterControlSet - RegistryPath.Buffer), Insert);
435 wcscat(ProfilePath, AfterControlSet);
436
437 RtlZeroMemory(QueryTable, sizeof(QueryTable));
438 QueryTable[0].QueryRoutine = DevModeCallback;
439 QueryTable[0].Flags = 0;
440 QueryTable[0].Name = NULL;
441 QueryTable[0].EntryContext = NULL;
442 QueryTable[0].DefaultType = REG_NONE;
443 QueryTable[0].DefaultData = NULL;
444 QueryTable[0].DefaultLength = 0;
445
446 Status = RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE,
447 ProfilePath,
448 QueryTable,
449 DevMode,
450 NULL);
451 if (! NT_SUCCESS(Status))
452 {
453 DPRINT1("RtlQueryRegistryValues for %S failed with status 0x%08x\n",
454 ProfilePath, Status);
455 Valid = FALSE;
456 }
457 else
458 {
459 DPRINT("dmBitsPerPel %d dmDisplayFrequency %d dmPelsWidth %d dmPelsHeight %d\n",
460 DevMode->dmBitsPerPel, DevMode->dmDisplayFrequency,
461 DevMode->dmPelsWidth, DevMode->dmPelsHeight);
462 if (0 == DevMode->dmBitsPerPel || 0 == DevMode->dmDisplayFrequency
463 || 0 == DevMode->dmPelsWidth || 0 == DevMode->dmPelsHeight)
464 {
465 DPRINT("Not all required devmode members are set\n");
466 Valid = FALSE;
467 }
468 }
469
470 ExFreePool(ProfilePath);
471 }
472 else
473 {
474 Valid = FALSE;
475 }
476 }
477 else
478 {
479 DPRINT1("Unparsable registry path %S in DEVICEMAP\\VIDEO0", RegistryPath.Buffer);
480 }
481
482 RtlFreeUnicodeString(&RegistryPath);
483
484 if (! Valid)
485 {
486 RtlZeroMemory(DevMode, sizeof(DEVMODEW));
487 }
488
489 return Valid;
490 }
491
492 BOOL STDCALL
493 NtGdiCreatePrimarySurface(LPCWSTR Driver,
494 LPCWSTR Device)
495 {
496 PGD_ENABLEDRIVER GDEnableDriver;
497 DRVENABLEDATA DED;
498 PSURFOBJ SurfObj;
499 PSURFGDI SurfGDI;
500 UNICODE_STRING DriverFileNames;
501 PWSTR CurrentName;
502 BOOL GotDriver;
503 BOOL DoDefault;
504 extern void FASTCALL IntInitDesktopWindow(ULONG Width, ULONG Height);
505
506 /* Open the miniport driver */
507 if ((PrimarySurface.DisplayDevice = DRIVER_FindMPDriver(Driver)) == NULL)
508 {
509 DPRINT1("FindMPDriver failed\n");
510 return(FALSE);
511 }
512
513 /* Retrieve DDI driver names from registry */
514 RtlInitUnicodeString(&DriverFileNames, NULL);
515 if (! FindDriverFileNames(&DriverFileNames))
516 {
517 DPRINT1("FindDriverFileNames failed\n");
518 return(FALSE);
519 }
520
521 /* DriverFileNames may be a list of drivers in REG_SZ_MULTI format, scan all of
522 them until a good one found */
523 CurrentName = DriverFileNames.Buffer;
524 GotDriver = FALSE;
525 while (! GotDriver && CurrentName < DriverFileNames.Buffer + DriverFileNames.Length)
526 {
527 /* Get the DDI driver's entry point */
528 GDEnableDriver = DRIVER_FindDDIDriver(CurrentName);
529 if (NULL == GDEnableDriver)
530 {
531 DPRINT("FindDDIDriver failed for %S\n", CurrentName);
532 }
533 else
534 {
535 /* Call DDI driver's EnableDriver function */
536 RtlZeroMemory(&DED, sizeof(DED));
537
538 if (!GDEnableDriver(DDI_DRIVER_VERSION, sizeof(DED), &DED))
539 {
540 DPRINT("DrvEnableDriver failed for %S\n", CurrentName);
541 }
542 else
543 {
544 GotDriver = TRUE;
545 }
546 }
547
548 if (! GotDriver)
549 {
550 /* Skip to the next name but never get past the Unicode string */
551 while (L'\0' != *CurrentName &&
552 CurrentName < DriverFileNames.Buffer + DriverFileNames.Length)
553 {
554 CurrentName++;
555 }
556 if (CurrentName < DriverFileNames.Buffer + DriverFileNames.Length)
557 {
558 CurrentName++;
559 }
560 }
561 }
562 RtlFreeUnicodeString(&DriverFileNames);
563 if (! GotDriver)
564 {
565 CloseMiniport();
566 DPRINT1("No suitable DDI driver found\n");
567 return FALSE;
568 }
569
570 DPRINT("Display driver %S loaded\n", CurrentName);
571
572 DPRINT("Building DDI Functions\n");
573
574 /* Construct DDI driver function dispatch table */
575 if (!DRIVER_BuildDDIFunctions(&DED, &PrimarySurface.DriverFunctions))
576 {
577 CloseMiniport();
578 DPRINT1("BuildDDIFunctions failed\n");
579 return(FALSE);
580 }
581
582 /* Allocate a phyical device handle from the driver */
583 if (SetupDevMode(&PrimarySurface.DMW))
584 {
585 PrimarySurface.PDev =
586 PrimarySurface.DriverFunctions.EnablePDev(&PrimarySurface.DMW,
587 L"",
588 HS_DDI_MAX,
589 PrimarySurface.FillPatterns,
590 sizeof(PrimarySurface.GDIInfo),
591 (ULONG *) &PrimarySurface.GDIInfo,
592 sizeof(PrimarySurface.DevInfo),
593 &PrimarySurface.DevInfo,
594 NULL,
595 L"",
596 PrimarySurface.DisplayDevice);
597 DoDefault = (NULL == PrimarySurface.PDev);
598 if (DoDefault)
599 {
600 DPRINT1("DrvEnablePDev with registry parameters failed\n");
601 }
602 }
603 else
604 {
605 DoDefault = TRUE;
606 }
607
608 if (DoDefault)
609 {
610 RtlZeroMemory(&(PrimarySurface.DMW), sizeof(DEVMODEW));
611 PrimarySurface.PDev =
612 PrimarySurface.DriverFunctions.EnablePDev(&PrimarySurface.DMW,
613 L"",
614 HS_DDI_MAX,
615 PrimarySurface.FillPatterns,
616 sizeof(PrimarySurface.GDIInfo),
617 (ULONG *) &PrimarySurface.GDIInfo,
618 sizeof(PrimarySurface.DevInfo),
619 &PrimarySurface.DevInfo,
620 NULL,
621 L"",
622 PrimarySurface.DisplayDevice);
623
624 if (NULL == PrimarySurface.PDev)
625 {
626 CloseMiniport();
627 DPRINT1("DrvEnablePDEV with default parameters failed\n");
628 DPRINT1("Perhaps DDI driver doesn't match miniport driver?\n");
629 return FALSE;
630 }
631 }
632
633 if (0 == PrimarySurface.GDIInfo.ulLogPixelsX)
634 {
635 DPRINT("Adjusting GDIInfo.ulLogPixelsX\n");
636 PrimarySurface.GDIInfo.ulLogPixelsX = 96;
637 }
638 if (0 == PrimarySurface.GDIInfo.ulLogPixelsY)
639 {
640 DPRINT("Adjusting GDIInfo.ulLogPixelsY\n");
641 PrimarySurface.GDIInfo.ulLogPixelsY = 96;
642 }
643 GDIOBJ_MarkObjectGlobal(PrimarySurface.DevInfo.hpalDefault);
644
645 DPRINT("calling completePDev\n");
646
647 /* Complete initialization of the physical device */
648 PrimarySurface.DriverFunctions.CompletePDev(PrimarySurface.PDev,
649 &PrimarySurface);
650
651 DPRINT("calling DRIVER_ReferenceDriver\n");
652
653 DRIVER_ReferenceDriver (Driver);
654
655 DPRINT("calling EnableSurface\n");
656
657 /* Enable the drawing surface */
658 PrimarySurface.Handle =
659 PrimarySurface.DriverFunctions.EnableSurface(PrimarySurface.PDev);
660 if (NULL == PrimarySurface.Handle)
661 {
662 CloseMiniport();
663 DPRINT1("DrvEnableSurface failed\n");
664 return FALSE;
665 }
666
667 SurfObj = (PSURFOBJ)AccessUserObject((ULONG) PrimarySurface.Handle);
668 SurfObj->dhpdev = PrimarySurface.PDev;
669 SurfGDI = (PSURFGDI)AccessInternalObject((ULONG) PrimarySurface.Handle);
670 IntInitDesktopWindow(SurfGDI->SurfObj.sizlBitmap.cx, SurfGDI->SurfObj.sizlBitmap.cy);
671
672 return TRUE;
673 }
674
675 HDC STDCALL
676 NtGdiCreateDC(LPCWSTR Driver,
677 LPCWSTR Device,
678 LPCWSTR Output,
679 CONST PDEVMODEW InitData)
680 {
681 HDC hNewDC;
682 PDC NewDC;
683 HDC hDC = NULL;
684 PSURFGDI SurfGDI;
685 HRGN hVisRgn;
686
687 /* Check for existing DC object */
688 if ((hNewDC = DC_FindOpenDC(Driver)) != NULL)
689 {
690 hDC = hNewDC;
691 return NtGdiCreateCompatableDC(hDC);
692 }
693
694 DPRINT("NAME: %S\n", Driver); // FIXME: Should not crash if NULL
695
696 /* Allocate a DC object */
697 if ((hNewDC = DC_AllocDC(Driver)) == NULL)
698 {
699 return NULL;
700 }
701
702 NewDC = DC_LockDc( hNewDC );
703 ASSERT( NewDC );
704
705 if (! PrimarySurfaceCreated)
706 {
707 PrimarySurfaceCreated = TRUE;
708 if (!NtGdiCreatePrimarySurface(Driver, Device))
709 {
710 PrimarySurfaceCreated = FALSE;
711 DC_UnlockDc( hNewDC );
712 DC_FreeDC(hNewDC);
713 return NULL;
714 }
715 }
716 NewDC->DMW = PrimarySurface.DMW;
717 NewDC->DevInfo = &PrimarySurface.DevInfo;
718 NewDC->GDIInfo = &PrimarySurface.GDIInfo;
719 memcpy(NewDC->FillPatternSurfaces, PrimarySurface.FillPatterns,
720 sizeof(NewDC->FillPatternSurfaces));
721 NewDC->PDev = PrimarySurface.PDev;
722 NewDC->Surface = PrimarySurface.Handle;
723 NewDC->DriverFunctions = PrimarySurface.DriverFunctions;
724
725 NewDC->DMW.dmSize = sizeof(NewDC->DMW);
726 NewDC->DMW.dmFields = 0x000fc000;
727
728 /* FIXME: get mode selection information from somewhere */
729
730 NewDC->DMW.dmLogPixels = 96;
731 SurfGDI = (PSURFGDI)AccessInternalObject((ULONG) PrimarySurface.Handle);
732 NewDC->DMW.dmBitsPerPel = SurfGDI->BitsPerPixel;
733 NewDC->DMW.dmPelsWidth = SurfGDI->SurfObj.sizlBitmap.cx;
734 NewDC->DMW.dmPelsHeight = SurfGDI->SurfObj.sizlBitmap.cy;
735 NewDC->DMW.dmDisplayFlags = 0;
736 NewDC->DMW.dmDisplayFrequency = 0;
737
738 NewDC->w.bitsPerPixel = SurfGDI->BitsPerPixel; // FIXME: set this here??
739
740 NewDC->w.hPalette = NewDC->DevInfo->hpalDefault;
741
742 DPRINT("Bits per pel: %u\n", NewDC->w.bitsPerPixel);
743
744 DC_UnlockDc( hNewDC );
745
746 hVisRgn = NtGdiCreateRectRgn(0, 0, SurfGDI->SurfObj.sizlBitmap.cx,
747 SurfGDI->SurfObj.sizlBitmap.cy);
748 NtGdiSelectVisRgn(hNewDC, hVisRgn);
749 NtGdiDeleteObject(hVisRgn);
750
751 /* Initialize the DC state */
752 DC_InitDC(hNewDC);
753 NtGdiSetTextColor(hNewDC, RGB(0, 0, 0));
754 NtGdiSetTextAlign(hNewDC, TA_TOP);
755 NtGdiSetBkColor(hNewDC, RGB(255, 255, 255));
756 NtGdiSetBkMode(hNewDC, OPAQUE);
757
758 return hNewDC;
759 }
760
761 HDC STDCALL
762 NtGdiCreateIC(LPCWSTR Driver,
763 LPCWSTR Device,
764 LPCWSTR Output,
765 CONST PDEVMODEW DevMode)
766 {
767 /* FIXME: this should probably do something else... */
768 return NtGdiCreateDC(Driver, Device, Output, DevMode);
769 }
770
771 BOOL STDCALL
772 NtGdiDeleteDC(HDC DCHandle)
773 {
774 PDC DCToDelete;
775
776 DCToDelete = DC_LockDc(DCHandle);
777 if (DCToDelete == NULL)
778 {
779 return FALSE;
780 }
781 DPRINT( "Deleting DC\n" );
782 if (! (DCToDelete->w.flags & DC_MEMORY) /* Don't reset the display if its a memory DC */
783 && NULL != DCToDelete->DriverName)
784 {
785 if (!DRIVER_UnreferenceDriver (DCToDelete->DriverName))
786 {
787 DPRINT( "No more references to driver, reseting display\n" );
788 DCToDelete->DriverFunctions.AssertMode( DCToDelete->PDev, FALSE );
789 CHECKPOINT;
790 DCToDelete->DriverFunctions.DisableSurface(DCToDelete->PDev);
791 CHECKPOINT;
792 DCToDelete->DriverFunctions.DisablePDev(DCToDelete->PDev);
793
794 CloseMiniport();
795
796 PrimarySurfaceCreated = FALSE;
797 }
798 }
799 CHECKPOINT;
800 /* First delete all saved DCs */
801 while (DCToDelete->saveLevel)
802 {
803 PDC savedDC;
804 HDC savedHDC;
805
806 savedHDC = DC_GetNextDC (DCToDelete);
807 savedDC = DC_LockDc (savedHDC);
808 if (savedDC == NULL)
809 {
810 break;
811 }
812 DC_SetNextDC (DCToDelete, DC_GetNextDC (savedDC));
813 DCToDelete->saveLevel--;
814 DC_UnlockDc( savedHDC );
815 NtGdiDeleteDC (savedHDC);
816 }
817
818 /* Free GDI resources allocated to this DC */
819 if (!(DCToDelete->w.flags & DC_SAVED))
820 {
821 /*
822 NtGdiSelectObject (DCHandle, STOCK_BLACK_PEN);
823 NtGdiSelectObject (DCHandle, STOCK_WHITE_BRUSH);
824 NtGdiSelectObject (DCHandle, STOCK_SYSTEM_FONT);
825 DC_LockDC (DCHandle); NtGdiSelectObject does not recognize stock objects yet */
826 if (DCToDelete->w.flags & DC_MEMORY)
827 {
828 EngDeleteSurface (DCToDelete->Surface);
829 NtGdiDeleteObject (DCToDelete->w.hFirstBitmap);
830 }
831 }
832 if (DCToDelete->w.hClipRgn)
833 {
834 NtGdiDeleteObject (DCToDelete->w.hClipRgn);
835 }
836 if (DCToDelete->w.hVisRgn)
837 {
838 NtGdiDeleteObject (DCToDelete->w.hVisRgn);
839 }
840 if (NULL != DCToDelete->CombinedClip)
841 {
842 IntEngDeleteClipRegion(DCToDelete->CombinedClip);
843 }
844 if (DCToDelete->w.hGCClipRgn)
845 {
846 NtGdiDeleteObject (DCToDelete->w.hGCClipRgn);
847 }
848 #if 0 /* FIXME */
849 PATH_DestroyGdiPath (&DCToDelete->w.path);
850 #endif
851 DC_UnlockDc( DCHandle );
852 DC_FreeDC ( DCHandle );
853
854 return TRUE;
855 }
856
857 INT STDCALL
858 NtGdiDrawEscape(HDC hDC,
859 INT nEscape,
860 INT cbInput,
861 LPCSTR lpszInData)
862 {
863 UNIMPLEMENTED;
864 }
865
866 INT STDCALL
867 NtGdiEnumObjects(HDC hDC,
868 INT ObjectType,
869 GOBJENUMPROC ObjectFunc,
870 LPARAM lParam)
871 {
872 UNIMPLEMENTED;
873 }
874
875 DC_GET_VAL( COLORREF, NtGdiGetBkColor, w.backgroundColor )
876 DC_GET_VAL( INT, NtGdiGetBkMode, w.backgroundMode )
877 DC_GET_VAL_EX( NtGdiGetBrushOrgEx, IntGetBrushOrgEx, w.brushOrgX, w.brushOrgY, POINT )
878 DC_GET_VAL( HRGN, NtGdiGetClipRgn, w.hClipRgn )
879
880 HGDIOBJ STDCALL
881 NtGdiGetCurrentObject(HDC hDC, UINT ObjectType)
882 {
883 UNIMPLEMENTED;
884 }
885
886 DC_GET_VAL_EX ( NtGdiGetCurrentPositionEx, IntGetCurrentPositionEx, w.CursPosX, w.CursPosY, POINT )
887
888 BOOL STDCALL
889 NtGdiGetDCOrgEx(HDC hDC, LPPOINT Point)
890 {
891 PDC dc;
892
893 if (!Point)
894 {
895 return FALSE;
896 }
897 dc = DC_LockDc(hDC);
898 if (dc == NULL)
899 {
900 return FALSE;
901 }
902
903 Point->x = Point->y = 0;
904
905 Point->x += dc->w.DCOrgX;
906 Point->y += dc->w.DCOrgY;
907 DC_UnlockDc( hDC );
908 return TRUE;
909 }
910
911 COLORREF STDCALL
912 NtGdiSetBkColor(HDC hDC, COLORREF color)
913 {
914 COLORREF oldColor;
915 PDC dc = DC_LockDc(hDC);
916
917 if ( !dc )
918 return 0x80000000;
919
920 oldColor = dc->w.backgroundColor;
921 dc->w.backgroundColor = color;
922 DC_UnlockDc ( hDC );
923 return oldColor;
924 }
925
926 HDC STDCALL
927 NtGdiGetDCState(HDC hDC)
928 {
929 PDC newdc, dc;
930 HDC hnewdc;
931
932 dc = DC_LockDc(hDC);
933 if (dc == NULL)
934 {
935 return 0;
936 }
937
938 hnewdc = DC_AllocDC(NULL);
939 if (hnewdc == NULL)
940 {
941 DC_UnlockDc( hDC );
942 return 0;
943 }
944 newdc = DC_LockDc( hnewdc );
945 ASSERT( newdc );
946
947 newdc->w.flags = dc->w.flags | DC_SAVED;
948 newdc->w.hPen = dc->w.hPen;
949 newdc->w.hBrush = dc->w.hBrush;
950 newdc->w.hFont = dc->w.hFont;
951 newdc->w.hBitmap = dc->w.hBitmap;
952 newdc->w.hFirstBitmap = dc->w.hFirstBitmap;
953 #if 0
954 newdc->w.hDevice = dc->w.hDevice;
955 newdc->w.hPalette = dc->w.hPalette;
956 #endif
957 newdc->w.totalExtent = dc->w.totalExtent;
958 newdc->w.bitsPerPixel = dc->w.bitsPerPixel;
959 newdc->w.ROPmode = dc->w.ROPmode;
960 newdc->w.polyFillMode = dc->w.polyFillMode;
961 newdc->w.stretchBltMode = dc->w.stretchBltMode;
962 newdc->w.relAbsMode = dc->w.relAbsMode;
963 newdc->w.backgroundMode = dc->w.backgroundMode;
964 newdc->w.backgroundColor = dc->w.backgroundColor;
965 newdc->w.textColor = dc->w.textColor;
966 newdc->w.brushOrgX = dc->w.brushOrgX;
967 newdc->w.brushOrgY = dc->w.brushOrgY;
968 newdc->w.textAlign = dc->w.textAlign;
969 newdc->w.charExtra = dc->w.charExtra;
970 newdc->w.breakTotalExtra = dc->w.breakTotalExtra;
971 newdc->w.breakCount = dc->w.breakCount;
972 newdc->w.breakExtra = dc->w.breakExtra;
973 newdc->w.breakRem = dc->w.breakRem;
974 newdc->w.MapMode = dc->w.MapMode;
975 newdc->w.GraphicsMode = dc->w.GraphicsMode;
976 #if 0
977 /* Apparently, the DC origin is not changed by [GS]etDCState */
978 newdc->w.DCOrgX = dc->w.DCOrgX;
979 newdc->w.DCOrgY = dc->w.DCOrgY;
980 #endif
981 newdc->w.CursPosX = dc->w.CursPosX;
982 newdc->w.CursPosY = dc->w.CursPosY;
983 newdc->w.ArcDirection = dc->w.ArcDirection;
984 #if 0
985 newdc->w.xformWorld2Wnd = dc->w.xformWorld2Wnd;
986 newdc->w.xformWorld2Vport = dc->w.xformWorld2Vport;
987 newdc->w.xformVport2World = dc->w.xformVport2World;
988 newdc->w.vport2WorldValid = dc->w.vport2WorldValid;
989 #endif
990 newdc->wndOrgX = dc->wndOrgX;
991 newdc->wndOrgY = dc->wndOrgY;
992 newdc->wndExtX = dc->wndExtX;
993 newdc->wndExtY = dc->wndExtY;
994 newdc->vportOrgX = dc->vportOrgX;
995 newdc->vportOrgY = dc->vportOrgY;
996 newdc->vportExtX = dc->vportExtX;
997 newdc->vportExtY = dc->vportExtY;
998
999 newdc->hSelf = hnewdc;
1000 newdc->saveLevel = 0;
1001
1002 #if 0
1003 PATH_InitGdiPath( &newdc->w.path );
1004 #endif
1005
1006 /* Get/SetDCState() don't change hVisRgn field ("Undoc. Windows" p.559). */
1007
1008 #if 0
1009 newdc->w.hGCClipRgn = newdc->w.hVisRgn = 0;
1010 #endif
1011 if (dc->w.hClipRgn)
1012 {
1013 newdc->w.hClipRgn = NtGdiCreateRectRgn( 0, 0, 0, 0 );
1014 NtGdiCombineRgn( newdc->w.hClipRgn, dc->w.hClipRgn, 0, RGN_COPY );
1015 }
1016 else
1017 {
1018 newdc->w.hClipRgn = 0;
1019 }
1020 DC_UnlockDc( hnewdc );
1021 DC_UnlockDc( hDC );
1022 return hnewdc;
1023 }
1024
1025
1026 VOID
1027 STDCALL
1028 NtGdiSetDCState ( HDC hDC, HDC hDCSave )
1029 {
1030 PDC dc, dcs;
1031
1032 dc = DC_LockDc ( hDC );
1033 if ( dc )
1034 {
1035 dcs = DC_LockDc ( hDCSave );
1036 if ( dcs )
1037 {
1038 if ( dcs->w.flags & DC_SAVED )
1039 {
1040 dc->w.flags = dcs->w.flags & ~DC_SAVED;
1041
1042 dc->w.hFirstBitmap = dcs->w.hFirstBitmap;
1043
1044 #if 0
1045 dc->w.hDevice = dcs->w.hDevice;
1046 #endif
1047
1048 dc->w.totalExtent = dcs->w.totalExtent;
1049 dc->w.ROPmode = dcs->w.ROPmode;
1050 dc->w.polyFillMode = dcs->w.polyFillMode;
1051 dc->w.stretchBltMode = dcs->w.stretchBltMode;
1052 dc->w.relAbsMode = dcs->w.relAbsMode;
1053 dc->w.backgroundMode = dcs->w.backgroundMode;
1054 dc->w.backgroundColor = dcs->w.backgroundColor;
1055 dc->w.textColor = dcs->w.textColor;
1056 dc->w.brushOrgX = dcs->w.brushOrgX;
1057 dc->w.brushOrgY = dcs->w.brushOrgY;
1058 dc->w.textAlign = dcs->w.textAlign;
1059 dc->w.charExtra = dcs->w.charExtra;
1060 dc->w.breakTotalExtra = dcs->w.breakTotalExtra;
1061 dc->w.breakCount = dcs->w.breakCount;
1062 dc->w.breakExtra = dcs->w.breakExtra;
1063 dc->w.breakRem = dcs->w.breakRem;
1064 dc->w.MapMode = dcs->w.MapMode;
1065 dc->w.GraphicsMode = dcs->w.GraphicsMode;
1066 #if 0
1067 /* Apparently, the DC origin is not changed by [GS]etDCState */
1068 dc->w.DCOrgX = dcs->w.DCOrgX;
1069 dc->w.DCOrgY = dcs->w.DCOrgY;
1070 #endif
1071 dc->w.CursPosX = dcs->w.CursPosX;
1072 dc->w.CursPosY = dcs->w.CursPosY;
1073 dc->w.ArcDirection = dcs->w.ArcDirection;
1074
1075 #if 0
1076 dc->w.xformWorld2Wnd = dcs->w.xformWorld2Wnd;
1077 dc->w.xformWorld2Vport = dcs->w.xformWorld2Vport;
1078 dc->w.xformVport2World = dcs->w.xformVport2World;
1079 dc->w.vport2WorldValid = dcs->w.vport2WorldValid;
1080 #endif
1081
1082 dc->wndOrgX = dcs->wndOrgX;
1083 dc->wndOrgY = dcs->wndOrgY;
1084 dc->wndExtX = dcs->wndExtX;
1085 dc->wndExtY = dcs->wndExtY;
1086 dc->vportOrgX = dcs->vportOrgX;
1087 dc->vportOrgY = dcs->vportOrgY;
1088 dc->vportExtX = dcs->vportExtX;
1089 dc->vportExtY = dcs->vportExtY;
1090
1091 if (!(dc->w.flags & DC_MEMORY))
1092 {
1093 dc->w.bitsPerPixel = dcs->w.bitsPerPixel;
1094 }
1095
1096 #if 0
1097 if (dcs->w.hClipRgn)
1098 {
1099 if (!dc->w.hClipRgn)
1100 {
1101 dc->w.hClipRgn = NtGdiCreateRectRgn( 0, 0, 0, 0 );
1102 }
1103 NtGdiCombineRgn( dc->w.hClipRgn, dcs->w.hClipRgn, 0, RGN_COPY );
1104 }
1105 else
1106 {
1107 if (dc->w.hClipRgn)
1108 {
1109 NtGdiDeleteObject( dc->w.hClipRgn );
1110 }
1111
1112 dc->w.hClipRgn = 0;
1113 }
1114 CLIPPING_UpdateGCRegion( dc );
1115 DC_UnlockDc ( hDC );
1116 #else
1117 DC_UnlockDc ( hDC );
1118 NtGdiSelectClipRgn(hDC, dcs->w.hClipRgn);
1119 #endif
1120
1121 NtGdiSelectObject( hDC, dcs->w.hBitmap );
1122 NtGdiSelectObject( hDC, dcs->w.hBrush );
1123 NtGdiSelectObject( hDC, dcs->w.hFont );
1124 NtGdiSelectObject( hDC, dcs->w.hPen );
1125 NtGdiSetBkColor( hDC, dcs->w.backgroundColor);
1126 NtGdiSetTextColor( hDC, dcs->w.textColor);
1127
1128 #if 0
1129 GDISelectPalette16( hDC, dcs->w.hPalette, FALSE );
1130 #endif
1131 } else {
1132 DC_UnlockDc(hDC);
1133 }
1134 DC_UnlockDc ( hDCSave );
1135 } else {
1136 DC_UnlockDc ( hDC );
1137 }
1138 }
1139 }
1140
1141 INT STDCALL
1142 NtGdiGetDeviceCaps(HDC hDC,
1143 INT Index)
1144 {
1145 PDC dc;
1146 INT ret;
1147 POINT pt;
1148
1149 dc = DC_LockDc(hDC);
1150 if (dc == NULL)
1151 {
1152 return 0;
1153 }
1154
1155 /* Retrieve capability */
1156 switch (Index)
1157 {
1158 case DRIVERVERSION:
1159 ret = dc->GDIInfo->ulVersion;
1160 break;
1161
1162 case TECHNOLOGY:
1163 ret = dc->GDIInfo->ulTechnology;
1164 break;
1165
1166 case HORZSIZE:
1167 ret = dc->GDIInfo->ulHorzSize;
1168 break;
1169
1170 case VERTSIZE:
1171 ret = dc->GDIInfo->ulVertSize;
1172 break;
1173
1174 case HORZRES:
1175 ret = dc->GDIInfo->ulHorzRes;
1176 break;
1177
1178 case VERTRES:
1179 ret = dc->GDIInfo->ulVertRes;
1180 break;
1181
1182 case LOGPIXELSX:
1183 ret = dc->GDIInfo->ulLogPixelsX;
1184 break;
1185
1186 case LOGPIXELSY:
1187 ret = dc->GDIInfo->ulLogPixelsY;
1188 break;
1189
1190 case BITSPIXEL:
1191 ret = dc->GDIInfo->cBitsPixel;
1192 break;
1193
1194 case PLANES:
1195 ret = dc->GDIInfo->cPlanes;
1196 break;
1197
1198 case NUMBRUSHES:
1199 UNIMPLEMENTED; /* FIXME */
1200 break;
1201
1202 case NUMPENS:
1203 UNIMPLEMENTED; /* FIXME */
1204 break;
1205
1206 case NUMFONTS:
1207 UNIMPLEMENTED; /* FIXME */
1208 break;
1209
1210 case NUMCOLORS:
1211 ret = dc->GDIInfo->ulNumColors;
1212 break;
1213
1214 case ASPECTX:
1215 ret = dc->GDIInfo->ulAspectX;
1216 break;
1217
1218 case ASPECTY:
1219 ret = dc->GDIInfo->ulAspectY;
1220 break;
1221
1222 case ASPECTXY:
1223 ret = dc->GDIInfo->ulAspectXY;
1224 break;
1225
1226 case PDEVICESIZE:
1227 UNIMPLEMENTED; /* FIXME */
1228 break;
1229
1230 case CLIPCAPS:
1231 UNIMPLEMENTED; /* FIXME */
1232 break;
1233
1234 case SIZEPALETTE:
1235 ret = dc->GDIInfo->ulNumPalReg; /* FIXME not sure */
1236 break;
1237
1238 case NUMRESERVED:
1239 UNIMPLEMENTED; /* FIXME */
1240 break;
1241
1242 case COLORRES:
1243 UNIMPLEMENTED; /* FIXME */
1244 break;
1245
1246 case PHYSICALWIDTH:
1247 if(NtGdiEscape(hDC, GETPHYSPAGESIZE, 0, NULL, (LPVOID)&pt) > 0)
1248 {
1249 ret = pt.x;
1250 }
1251 else
1252 {
1253 ret = 0;
1254 }
1255 break;
1256
1257 case PHYSICALHEIGHT:
1258 if(NtGdiEscape(hDC, GETPHYSPAGESIZE, 0, NULL, (LPVOID)&pt) > 0)
1259 {
1260 ret = pt.y;
1261 }
1262 else
1263 {
1264 ret = 0;
1265 }
1266 break;
1267
1268 case PHYSICALOFFSETX:
1269 if(NtGdiEscape(hDC, GETPRINTINGOFFSET, 0, NULL, (LPVOID)&pt) > 0)
1270 {
1271 ret = pt.x;
1272 }
1273 else
1274 {
1275 ret = 0;
1276 }
1277 break;
1278
1279 case PHYSICALOFFSETY:
1280 if(NtGdiEscape(hDC, GETPRINTINGOFFSET, 0, NULL, (LPVOID)&pt) > 0)
1281 {
1282 ret = pt.y;
1283 }
1284 else
1285 {
1286 ret = 0;
1287 }
1288 break;
1289
1290 case VREFRESH:
1291 UNIMPLEMENTED; /* FIXME */
1292 break;
1293
1294 case SCALINGFACTORX:
1295 if(NtGdiEscape(hDC, GETSCALINGFACTOR, 0, NULL, (LPVOID)&pt) > 0)
1296 {
1297 ret = pt.x;
1298 }
1299 else
1300 {
1301 ret = 0;
1302 }
1303 break;
1304
1305 case SCALINGFACTORY:
1306 if(NtGdiEscape(hDC, GETSCALINGFACTOR, 0, NULL, (LPVOID)&pt) > 0)
1307 {
1308 ret = pt.y;
1309 }
1310 else
1311 {
1312 ret = 0;
1313 }
1314 break;
1315
1316 case RASTERCAPS:
1317 UNIMPLEMENTED; /* FIXME */
1318 break;
1319
1320 case CURVECAPS:
1321 UNIMPLEMENTED; /* FIXME */
1322 break;
1323
1324 case LINECAPS:
1325 UNIMPLEMENTED; /* FIXME */
1326 break;
1327
1328 case POLYGONALCAPS:
1329 UNIMPLEMENTED; /* FIXME */
1330 break;
1331
1332 case TEXTCAPS:
1333 ret = dc->GDIInfo->flTextCaps;
1334 break;
1335
1336 default:
1337 ret = 0;
1338 break;
1339 }
1340
1341 DPRINT("(%04x,%d): returning %d\n", hDC, Index, ret);
1342
1343 DC_UnlockDc( hDC );
1344 return ret;
1345 }
1346
1347 DC_GET_VAL( INT, NtGdiGetMapMode, w.MapMode )
1348 DC_GET_VAL( INT, NtGdiGetPolyFillMode, w.polyFillMode )
1349
1350 INT STDCALL
1351 NtGdiGetObjectA(HANDLE handle, INT count, LPVOID buffer)
1352 {
1353 PGDIOBJ gdiObject;
1354 INT result = 0;
1355 DWORD objectType;
1356
1357 if (!count)
1358 return 0;
1359 gdiObject = GDIOBJ_LockObj (handle, GDI_OBJECT_TYPE_DONTCARE);
1360 if (gdiObject == 0)
1361 return 0;
1362
1363 objectType = GDIOBJ_GetObjectType(handle);
1364 switch(objectType)
1365 {
1366 /* case GDI_OBJECT_TYPE_PEN:
1367 result = PEN_GetObject((PENOBJ *)gdiObject, count, buffer);
1368 break;
1369 case GDI_OBJECT_TYPE_BRUSH:
1370 result = BRUSH_GetObject((BRUSHOBJ *)gdiObject, count, buffer);
1371 break; */
1372 case GDI_OBJECT_TYPE_BITMAP:
1373 result = BITMAP_GetObject((BITMAPOBJ *)gdiObject, count, buffer);
1374 break;
1375 /* case GDI_OBJECT_TYPE_FONT:
1376 result = FONT_GetObjectA((FONTOBJ *)gdiObject, count, buffer);
1377
1378 // FIXME: Fix the LOGFONT structure for the stock fonts
1379
1380 if ( (handle >= FIRST_STOCK_HANDLE) && (handle <= LAST_STOCK_HANDLE) )
1381 FixStockFontSizeA(handle, count, buffer);
1382 break;
1383 case GDI_OBJECT_TYPE_PALETTE:
1384 result = PALETTE_GetObject((PALETTEOBJ *)gdiObject, count, buffer);
1385 break; */
1386
1387 case GDI_OBJECT_TYPE_REGION:
1388 case GDI_OBJECT_TYPE_DC:
1389 case GDI_OBJECT_TYPE_METADC:
1390 case GDI_OBJECT_TYPE_METAFILE:
1391 case GDI_OBJECT_TYPE_ENHMETADC:
1392 case GDI_OBJECT_TYPE_EMF:
1393 DPRINT1("GDI object type 0x%08x not implemented\n", objectType);
1394 break;
1395
1396 default:
1397 DPRINT1("Invalid GDI object type 0x%08x\n", objectType);
1398 break;
1399 }
1400 GDIOBJ_UnlockObj(handle, GDI_OBJECT_TYPE_DONTCARE);
1401
1402 return result;
1403 }
1404
1405 INT STDCALL
1406 NtGdiGetObjectW(HANDLE handle, INT count, LPVOID buffer)
1407 {
1408 PGDIOBJHDR gdiObject;
1409 INT result = 0;
1410 DWORD objectType;
1411
1412 if (!count)
1413 return 0;
1414 gdiObject = GDIOBJ_LockObj(handle, GDI_OBJECT_TYPE_DONTCARE);
1415 if (gdiObject == 0)
1416 return 0;
1417
1418 objectType = GDIOBJ_GetObjectType(handle);
1419 switch(objectType)
1420 {
1421 /* case GDI_OBJECT_TYPE_PEN:
1422 result = PEN_GetObject((PENOBJ *)gdiObject, count, buffer);
1423 break;
1424 case GDI_OBJECT_TYPE_BRUSH:
1425 result = BRUSH_GetObject((BRUSHOBJ *)gdiObject, count, buffer);
1426 break; */
1427 case GDI_OBJECT_TYPE_BITMAP:
1428 result = BITMAP_GetObject((BITMAPOBJ *)gdiObject, count, buffer);
1429 break;
1430 /* case GDI_OBJECT_TYPE_FONT:
1431 result = FONT_GetObjectW((FONTOBJ *)gdiObject, count, buffer);
1432
1433 // Fix the LOGFONT structure for the stock fonts
1434
1435 if ( (handle >= FIRST_STOCK_HANDLE) && (handle <= LAST_STOCK_HANDLE) )
1436 FixStockFontSizeW(handle, count, buffer);
1437 break;
1438 case GDI_OBJECT_TYPE_PALETTE:
1439 result = PALETTE_GetObject((PALETTEOBJ *)gdiObject, count, buffer);
1440 break; */
1441 default:
1442 DPRINT1("GDI object type 0x%08x not implemented\n", objectType);
1443 break;
1444 }
1445
1446 GDIOBJ_UnlockObj(handle, GDI_OBJECT_TYPE_DONTCARE);
1447
1448 return result;
1449 }
1450
1451 INT STDCALL
1452 NtGdiGetObject(HANDLE handle, INT count, LPVOID buffer)
1453 {
1454 return NtGdiGetObjectW(handle, count, buffer);
1455 }
1456
1457 DWORD STDCALL
1458 NtGdiGetObjectType(HANDLE handle)
1459 {
1460 GDIOBJHDR * ptr;
1461 INT result = 0;
1462 DWORD objectType;
1463
1464 ptr = GDIOBJ_LockObj(handle, GDI_OBJECT_TYPE_DONTCARE);
1465 if (ptr == 0)
1466 return 0;
1467
1468 objectType = GDIOBJ_GetObjectType(handle);
1469 switch(objectType)
1470 {
1471 case GDI_OBJECT_TYPE_PEN:
1472 result = OBJ_PEN;
1473 break;
1474 case GDI_OBJECT_TYPE_BRUSH:
1475 result = OBJ_BRUSH;
1476 break;
1477 case GDI_OBJECT_TYPE_BITMAP:
1478 result = OBJ_BITMAP;
1479 break;
1480 case GDI_OBJECT_TYPE_FONT:
1481 result = OBJ_FONT;
1482 break;
1483 case GDI_OBJECT_TYPE_PALETTE:
1484 result = OBJ_PAL;
1485 break;
1486 case GDI_OBJECT_TYPE_REGION:
1487 result = OBJ_REGION;
1488 break;
1489 case GDI_OBJECT_TYPE_DC:
1490 result = OBJ_DC;
1491 break;
1492 case GDI_OBJECT_TYPE_METADC:
1493 result = OBJ_METADC;
1494 break;
1495 case GDI_OBJECT_TYPE_METAFILE:
1496 result = OBJ_METAFILE;
1497 break;
1498 case GDI_OBJECT_TYPE_ENHMETAFILE:
1499 result = OBJ_ENHMETAFILE;
1500 break;
1501 case GDI_OBJECT_TYPE_ENHMETADC:
1502 result = OBJ_ENHMETADC;
1503 break;
1504 case GDI_OBJECT_TYPE_EXTPEN:
1505 result = OBJ_EXTPEN;
1506 break;
1507 case GDI_OBJECT_TYPE_MEMDC:
1508 result = OBJ_MEMDC;
1509 break;
1510 default:
1511 DPRINT1("Magic 0x%08x not implemented\n", objectType);
1512 break;
1513 }
1514 GDIOBJ_UnlockObj(handle, GDI_OBJECT_TYPE_DONTCARE);
1515 return result;
1516 }
1517
1518 DC_GET_VAL( INT, NtGdiGetRelAbs, w.relAbsMode )
1519 DC_GET_VAL( INT, NtGdiGetROP2, w.ROPmode )
1520 DC_GET_VAL( INT, NtGdiGetStretchBltMode, w.stretchBltMode )
1521 DC_GET_VAL( UINT, NtGdiGetTextAlign, w.textAlign )
1522 DC_GET_VAL( COLORREF, NtGdiGetTextColor, w.textColor )
1523 DC_GET_VAL_EX( NtGdiGetViewportExtEx, IntGetViewportExtEx, vportExtX, vportExtY, SIZE )
1524 DC_GET_VAL_EX( NtGdiGetViewportOrgEx, IntGetViewportOrgEx, vportOrgX, vportOrgY, POINT )
1525 DC_GET_VAL_EX( NtGdiGetWindowExtEx, IntGetWindowExtEx, wndExtX, wndExtY, SIZE )
1526 DC_GET_VAL_EX( NtGdiGetWindowOrgEx, IntGetWindowOrgEx, wndOrgX, wndOrgY, POINT )
1527
1528 HDC STDCALL
1529 NtGdiResetDC(HDC hDC, CONST DEVMODEW *InitData)
1530 {
1531 UNIMPLEMENTED;
1532 }
1533
1534 BOOL STDCALL
1535 NtGdiRestoreDC(HDC hDC, INT SaveLevel)
1536 {
1537 PDC dc, dcs;
1538 BOOL success;
1539
1540 dc = DC_LockDc(hDC);
1541 if(!dc)
1542 {
1543 return FALSE;
1544 }
1545
1546 if (SaveLevel == -1)
1547 {
1548 SaveLevel = dc->saveLevel;
1549 }
1550
1551 if ((SaveLevel < 1) || (SaveLevel > dc->saveLevel))
1552 {
1553 return FALSE;
1554 }
1555
1556 success = TRUE;
1557 while (dc->saveLevel >= SaveLevel)
1558 {
1559 HDC hdcs = DC_GetNextDC (dc);
1560
1561 dcs = DC_LockDc (hdcs);
1562 if (dcs == NULL)
1563 {
1564 return FALSE;
1565 }
1566 DC_SetNextDC (dcs, DC_GetNextDC (dcs));
1567 if (--dc->saveLevel < SaveLevel)
1568 {
1569 DC_UnlockDc( hDC );
1570 DC_UnlockDc( hdcs );
1571 NtGdiSetDCState(hDC, hdcs);
1572 #if 0
1573 if (!PATH_AssignGdiPath( &dc->w.path, &dcs->w.path ))
1574 {
1575 /* FIXME: This might not be quite right, since we're
1576 * returning FALSE but still destroying the saved DC state */
1577 success = FALSE;
1578 }
1579 #endif
1580 dc = DC_LockDc(hDC);
1581 if(!dc)
1582 {
1583 return FALSE;
1584 }
1585 }
1586 else
1587 {
1588 DC_UnlockDc( hdcs );
1589 }
1590 NtGdiDeleteDC (hdcs);
1591 }
1592 DC_UnlockDc( hDC );
1593 return success;
1594 }
1595
1596 INT STDCALL
1597 NtGdiSaveDC(HDC hDC)
1598 {
1599 HDC hdcs;
1600 PDC dc, dcs;
1601 INT ret;
1602
1603 if (!(hdcs = NtGdiGetDCState(hDC)))
1604 {
1605 return 0;
1606 }
1607
1608 dcs = DC_LockDc (hdcs);
1609 if (dcs == NULL)
1610 {
1611 return 0;
1612 }
1613 dc = DC_LockDc (hDC);
1614 if (dc == NULL)
1615 {
1616 DC_UnlockDc(dc);
1617 return 0;
1618 }
1619
1620 #if 0
1621 /* Copy path. The reason why path saving / restoring is in SaveDC/
1622 * RestoreDC and not in GetDCState/SetDCState is that the ...DCState
1623 * functions are only in Win16 (which doesn't have paths) and that
1624 * SetDCState doesn't allow us to signal an error (which can happen
1625 * when copying paths).
1626 */
1627 if (!PATH_AssignGdiPath (&dcs->w.path, &dc->w.path))
1628 {
1629 NtGdiDeleteDC (hdcs);
1630 return 0;
1631 }
1632 #endif
1633
1634 DC_SetNextDC (dcs, DC_GetNextDC (dc));
1635 DC_SetNextDC (dc, hdcs);
1636 ret = ++dc->saveLevel;
1637 DC_UnlockDc( hdcs );
1638 DC_UnlockDc( hDC );
1639
1640 return ret;
1641 }
1642
1643 HGDIOBJ
1644 STDCALL
1645 NtGdiSelectObject(HDC hDC, HGDIOBJ hGDIObj)
1646 {
1647 HGDIOBJ objOrg = NULL; // default to failure
1648 BITMAPOBJ *pb;
1649 PDC dc;
1650 PPENOBJ pen;
1651 PBRUSHOBJ brush;
1652 PXLATEOBJ XlateObj;
1653 PPALGDI PalGDI;
1654 DWORD objectType;
1655 COLORREF *ColorMap;
1656 ULONG NumColors, Index;
1657 HRGN hVisRgn;
1658 USHORT Mode;
1659
1660 if(!hDC || !hGDIObj) return NULL;
1661
1662 dc = DC_LockDc(hDC);
1663 if (NULL == dc)
1664 {
1665 SetLastWin32Error(ERROR_INVALID_HANDLE);
1666 return NULL;
1667 }
1668
1669 objectType = GDIOBJ_GetObjectType(hGDIObj);
1670
1671 switch (objectType)
1672 {
1673 case GDI_OBJECT_TYPE_PEN:
1674 objOrg = NULL;
1675 /* Convert the color of the pen to the format of the DC */
1676 PalGDI = PALETTE_LockPalette(dc->w.hPalette);
1677 if (NULL != PalGDI)
1678 {
1679 Mode = PalGDI->Mode;
1680 PALETTE_UnlockPalette(dc->w.hPalette);
1681 XlateObj = (PXLATEOBJ)IntEngCreateXlate(Mode, PAL_RGB, dc->w.hPalette, NULL);
1682 if (NULL != XlateObj)
1683 {
1684 pen = PENOBJ_LockPen((HPEN) hGDIObj);
1685 if (NULL != pen)
1686 {
1687 pen->iSolidColor = XLATEOBJ_iXlate(XlateObj, pen->logpen.lopnColor);
1688 PENOBJ_UnlockPen((HPEN) hGDIObj);
1689 objOrg = (HGDIOBJ)dc->w.hPen;
1690 dc->w.hPen = hGDIObj;
1691 }
1692 else
1693 {
1694 SetLastWin32Error(ERROR_INVALID_HANDLE);
1695 }
1696 EngDeleteXlate(XlateObj);
1697 }
1698 else
1699 {
1700 SetLastWin32Error(ERROR_NO_SYSTEM_RESOURCES);
1701 }
1702 }
1703 else
1704 {
1705 SetLastWin32Error(ERROR_INVALID_HANDLE);
1706 }
1707 break;
1708
1709 case GDI_OBJECT_TYPE_BRUSH:
1710 objOrg = NULL;
1711 /* Convert the color of the brush to the format of the DC */
1712 PalGDI = PALETTE_LockPalette(dc->w.hPalette);
1713 if (NULL != PalGDI)
1714 {
1715 Mode = PalGDI->Mode;
1716 PALETTE_UnlockPalette(dc->w.hPalette);
1717 XlateObj = (PXLATEOBJ)IntEngCreateXlate(Mode, PAL_RGB, dc->w.hPalette, NULL);
1718 if (NULL != XlateObj)
1719 {
1720 brush = BRUSHOBJ_LockBrush((HBRUSH) hGDIObj);
1721 if (NULL != brush)
1722 {
1723 brush->iSolidColor = XLATEOBJ_iXlate(XlateObj, brush->logbrush.lbColor);
1724 BRUSHOBJ_UnlockBrush((HBRUSH) hGDIObj);
1725 objOrg = (HGDIOBJ)dc->w.hBrush;
1726 dc->w.hBrush = (HBRUSH) hGDIObj;
1727 }
1728 else
1729 {
1730 SetLastWin32Error(ERROR_INVALID_HANDLE);
1731 }
1732 EngDeleteXlate(XlateObj);
1733 }
1734 else
1735 {
1736 SetLastWin32Error(ERROR_NO_SYSTEM_RESOURCES);
1737 }
1738 }
1739 else
1740 {
1741 SetLastWin32Error(ERROR_INVALID_HANDLE);
1742 }
1743 break;
1744
1745 case GDI_OBJECT_TYPE_FONT:
1746 objOrg = (HGDIOBJ)dc->w.hFont;
1747 dc->w.hFont = (HFONT) hGDIObj;
1748 TextIntRealizeFont(dc->w.hFont);
1749 break;
1750
1751 case GDI_OBJECT_TYPE_BITMAP:
1752 // must be memory dc to select bitmap
1753 if (!(dc->w.flags & DC_MEMORY))
1754 {
1755 DC_UnlockDc(hDC);
1756 return NULL;
1757 }
1758 pb = BITMAPOBJ_LockBitmap(hGDIObj);
1759 if (NULL == pb)
1760 {
1761 SetLastWin32Error(ERROR_INVALID_HANDLE);
1762 DC_UnlockDc(hDC);
1763 return NULL;
1764 }
1765 objOrg = (HGDIOBJ)dc->w.hBitmap;
1766
1767 /* Release the old bitmap, lock the new one and convert it to a SURF */
1768 EngDeleteSurface(dc->Surface);
1769 dc->w.hBitmap = hGDIObj;
1770 dc->Surface = BitmapToSurf(pb);
1771
1772 // if we're working with a DIB, get the palette [fixme: only create if the selected palette is null]
1773 if(pb->dib)
1774 {
1775 dc->w.bitsPerPixel = pb->dib->dsBmih.biBitCount;
1776
1777 if(pb->dib->dsBmih.biBitCount <= 8)
1778 {
1779 if(pb->dib->dsBmih.biBitCount == 1) { NumColors = 2; } else
1780 if(pb->dib->dsBmih.biBitCount == 4) { NumColors = 16; } else
1781 if(pb->dib->dsBmih.biBitCount == 8) { NumColors = 256; }
1782
1783 ColorMap = ExAllocatePoolWithTag(PagedPool, sizeof(COLORREF) * NumColors, TAG_DC);
1784 ASSERT(ColorMap);
1785 for (Index = 0; Index < NumColors; Index++)
1786 {
1787 ColorMap[Index] = RGB(pb->ColorMap[Index].rgbRed,
1788 pb->ColorMap[Index].rgbGreen,
1789 pb->ColorMap[Index].rgbBlue);
1790 }
1791 dc->w.hPalette = PALETTE_AllocPalette(PAL_INDEXED, NumColors, (ULONG *) ColorMap, 0, 0, 0);
1792 ExFreePool(ColorMap);
1793 }
1794 else if ( 16 == pb->dib->dsBmih.biBitCount )
1795 {
1796 dc->w.hPalette = PALETTE_AllocPalette(PAL_BITFIELDS, pb->dib->dsBmih.biClrUsed, NULL, 0x7c00, 0x03e0, 0x001f);
1797 }
1798 else if(pb->dib->dsBmih.biBitCount >= 24)
1799 {
1800 dc->w.hPalette = PALETTE_AllocPalette(PAL_RGB, pb->dib->dsBmih.biClrUsed, NULL, 0, 0, 0);
1801 }
1802 }
1803 else
1804 {
1805 dc->w.bitsPerPixel = pb->bitmap.bmBitsPixel;
1806 }
1807
1808 DC_UnlockDc ( hDC );
1809 hVisRgn = NtGdiCreateRectRgn ( 0, 0, pb->size.cx, pb->size.cy );
1810 NtGdiSelectVisRgn ( hDC, hVisRgn );
1811 NtGdiDeleteObject ( hVisRgn );
1812 BITMAPOBJ_UnlockBitmap(hGDIObj);
1813
1814 return objOrg;
1815
1816 #if UPDATEREGIONS
1817 case GDI_OBJECT_TYPE_REGION:
1818 DC_UnlockDc ( hDC );
1819 SelectClipRgn(hDC, (HRGN)hGDIObj);
1820 return NULL;
1821 #endif
1822 default:
1823 break;
1824 }
1825 DC_UnlockDc( hDC );
1826 return objOrg;
1827 }
1828
1829 WORD STDCALL
1830 NtGdiSetHookFlags(HDC hDC, WORD Flags)
1831 {
1832 WORD wRet;
1833 DC *dc = DC_LockDc(hDC);
1834
1835 if (NULL == dc)
1836 {
1837 return 0;
1838 }
1839
1840 wRet = dc->w.flags & DC_DIRTY;
1841
1842 /* "Undocumented Windows" info is slightly confusing.
1843 */
1844
1845 DPRINT("DC %p, Flags %04x\n", hDC, Flags);
1846
1847 if (Flags & DCHF_INVALIDATEVISRGN)
1848 {
1849 dc->w.flags |= DC_DIRTY;
1850 }
1851 else if (Flags & DCHF_VALIDATEVISRGN || 0 == Flags)
1852 {
1853 dc->w.flags &= ~DC_DIRTY;
1854 }
1855
1856 DC_UnlockDc(hDC);
1857
1858 return wRet;
1859 }
1860
1861 DC_SET_MODE( NtGdiSetBkMode, w.backgroundMode, TRANSPARENT, OPAQUE )
1862 DC_SET_MODE( NtGdiSetPolyFillMode, w.polyFillMode, ALTERNATE, WINDING )
1863 // DC_SET_MODE( NtGdiSetRelAbs, w.relAbsMode, ABSOLUTE, RELATIVE )
1864 DC_SET_MODE( NtGdiSetROP2, w.ROPmode, R2_BLACK, R2_WHITE )
1865 DC_SET_MODE( NtGdiSetStretchBltMode, w.stretchBltMode, BLACKONWHITE, HALFTONE )
1866
1867 // ---------------------------------------------------- Private Interface
1868
1869 HDC FASTCALL
1870 DC_AllocDC(LPCWSTR Driver)
1871 {
1872 PDC NewDC;
1873 HDC hDC;
1874
1875 hDC = (HDC) GDIOBJ_AllocObj(sizeof(DC), GDI_OBJECT_TYPE_DC, (GDICLEANUPPROC) DC_InternalDeleteDC);
1876 if (hDC == NULL)
1877 {
1878 return NULL;
1879 }
1880
1881 NewDC = DC_LockDc(hDC);
1882
1883 if (Driver != NULL)
1884 {
1885 NewDC->DriverName = ExAllocatePoolWithTag(PagedPool, (wcslen(Driver) + 1) * sizeof(WCHAR), TAG_DC);
1886 wcscpy(NewDC->DriverName, Driver);
1887 }
1888
1889 NewDC->w.xformWorld2Wnd.eM11 = 1.0f;
1890 NewDC->w.xformWorld2Wnd.eM12 = 0.0f;
1891 NewDC->w.xformWorld2Wnd.eM21 = 0.0f;
1892 NewDC->w.xformWorld2Wnd.eM22 = 1.0f;
1893 NewDC->w.xformWorld2Wnd.eDx = 0.0f;
1894 NewDC->w.xformWorld2Wnd.eDy = 0.0f;
1895 NewDC->w.xformWorld2Vport = NewDC->w.xformWorld2Wnd;
1896 NewDC->w.xformVport2World = NewDC->w.xformWorld2Wnd;
1897 NewDC->w.vport2WorldValid = TRUE;
1898
1899 NewDC->w.hFont = NtGdiGetStockObject(SYSTEM_FONT);
1900 TextIntRealizeFont(NewDC->w.hFont);
1901
1902 DC_UnlockDc(hDC);
1903
1904 return hDC;
1905 }
1906
1907 HDC FASTCALL
1908 DC_FindOpenDC(LPCWSTR Driver)
1909 {
1910 return NULL;
1911 }
1912
1913 /*!
1914 * Initialize some common fields in the Device Context structure.
1915 */
1916 VOID FASTCALL
1917 DC_InitDC(HDC DCHandle)
1918 {
1919 // NtGdiRealizeDefaultPalette(DCHandle);
1920
1921 NtGdiSelectObject(DCHandle, NtGdiGetStockObject( WHITE_BRUSH ));
1922 NtGdiSelectObject(DCHandle, NtGdiGetStockObject( BLACK_PEN ));
1923 //NtGdiSelectObject(DCHandle, hFont);
1924
1925 // CLIPPING_UpdateGCRegion(DCToInit);
1926
1927 }
1928
1929 VOID FASTCALL
1930 DC_FreeDC(HDC DCToFree)
1931 {
1932 if (!GDIOBJ_FreeObj(DCToFree, GDI_OBJECT_TYPE_DC, GDIOBJFLAG_DEFAULT))
1933 {
1934 DPRINT("DC_FreeDC failed\n");
1935 }
1936 }
1937
1938 BOOL FASTCALL
1939 DC_InternalDeleteDC( PDC DCToDelete )
1940 {
1941 if( DCToDelete->DriverName )
1942 {
1943 ExFreePool(DCToDelete->DriverName);
1944 }
1945
1946 return TRUE;
1947 }
1948
1949 HDC FASTCALL
1950 DC_GetNextDC (PDC pDC)
1951 {
1952 return pDC->hNext;
1953 }
1954
1955 VOID FASTCALL
1956 DC_SetNextDC (PDC pDC, HDC hNextDC)
1957 {
1958 pDC->hNext = hNextDC;
1959 }
1960
1961 VOID FASTCALL
1962 DC_UpdateXforms(PDC dc)
1963 {
1964 XFORM xformWnd2Vport;
1965 FLOAT scaleX, scaleY;
1966
1967 /* Construct a transformation to do the window-to-viewport conversion */
1968 scaleX = (FLOAT)dc->vportExtX / (FLOAT)dc->wndExtX;
1969 scaleY = (FLOAT)dc->vportExtY / (FLOAT)dc->wndExtY;
1970 xformWnd2Vport.eM11 = scaleX;
1971 xformWnd2Vport.eM12 = 0.0;
1972 xformWnd2Vport.eM21 = 0.0;
1973 xformWnd2Vport.eM22 = scaleY;
1974 xformWnd2Vport.eDx = (FLOAT)dc->vportOrgX - scaleX * (FLOAT)dc->wndOrgX;
1975 xformWnd2Vport.eDy = (FLOAT)dc->vportOrgY - scaleY * (FLOAT)dc->wndOrgY;
1976
1977 /* Combine with the world transformation */
1978 NtGdiCombineTransform(&dc->w.xformWorld2Vport, &dc->w.xformWorld2Wnd, &xformWnd2Vport);
1979
1980 /* Create inverse of world-to-viewport transformation */
1981 dc->w.vport2WorldValid = DC_InvertXform(&dc->w.xformWorld2Vport, &dc->w.xformVport2World);
1982 }
1983
1984 BOOL FASTCALL
1985 DC_InvertXform(const XFORM *xformSrc,
1986 XFORM *xformDest)
1987 {
1988 FLOAT determinant;
1989
1990 determinant = xformSrc->eM11*xformSrc->eM22 - xformSrc->eM12*xformSrc->eM21;
1991 if (determinant > -1e-12 && determinant < 1e-12)
1992 {
1993 return FALSE;
1994 }
1995
1996 xformDest->eM11 = xformSrc->eM22 / determinant;
1997 xformDest->eM12 = -xformSrc->eM12 / determinant;
1998 xformDest->eM21 = -xformSrc->eM21 / determinant;
1999 xformDest->eM22 = xformSrc->eM11 / determinant;
2000 xformDest->eDx = -xformSrc->eDx * xformDest->eM11 - xformSrc->eDy * xformDest->eM21;
2001 xformDest->eDy = -xformSrc->eDx * xformDest->eM12 - xformSrc->eDy * xformDest->eM22;
2002
2003 return TRUE;
2004 }
2005 /* EOF */