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