79cca3ecbdb1f05a77e8026c2c3831a9bd0e04f2
[reactos.git] / reactos / subsys / win32k / objects / dc.c
1 /* $Id: dc.c,v 1.13 2000/03/17 21:02:59 jfilby Exp $
2 *
3 * DC.C - Device context functions
4 *
5 */
6
7 #undef WIN32_LEAN_AND_MEAN
8 #include <windows.h>
9 #include <ddk/ntddk.h>
10 #include <win32k/bitmaps.h>
11 #include <win32k/coord.h>
12 #include <win32k/driver.h>
13 #include <win32k/dc.h>
14 #include <win32k/print.h>
15 #include <win32k/region.h>
16 #include <win32k/gdiobj.h>
17
18 // #define NDEBUG
19 #include <internal/debug.h>
20
21 /* FIXME: DCs should probably be thread safe */
22
23 /*
24 * DC device-independent Get/SetXXX functions
25 * (RJJ) swiped from WINE
26 */
27
28 #define DC_GET_VAL( func_type, func_name, dc_field ) \
29 func_type STDCALL func_name( HDC hdc ) \
30 { \
31 func_type ft; \
32 PDC dc = DC_HandleToPtr( hdc ); \
33 if (!dc) \
34 { \
35 return 0; \
36 } \
37 ft = dc->dc_field; \
38 DC_UnlockDC(dc); \
39 return ft; \
40 }
41
42 /* DC_GET_VAL_EX is used to define functions returning a POINT or a SIZE. It is
43 * important that the function has the right signature, for the implementation
44 * we can do whatever we want.
45 */
46 #define DC_GET_VAL_EX( func_name, ret_x, ret_y, type ) \
47 BOOL STDCALL func_name( HDC hdc, LP##type pt ) \
48 { \
49 PDC dc = DC_HandleToPtr( hdc ); \
50 if (!dc) \
51 { \
52 return FALSE; \
53 } \
54 ((LPPOINT)pt)->x = dc->ret_x; \
55 ((LPPOINT)pt)->y = dc->ret_y; \
56 DC_UnlockDC(dc); \
57 return TRUE; \
58 }
59
60 #define DC_SET_MODE( func_name, dc_field, min_val, max_val ) \
61 INT STDCALL func_name( HDC hdc, INT mode ) \
62 { \
63 INT prevMode; \
64 PDC dc = DC_HandleToPtr( hdc ); \
65 if(!dc) \
66 { \
67 return 0; \
68 } \
69 if ((mode < min_val) || (mode > max_val)) \
70 { \
71 return 0; \
72 } \
73 prevMode = dc->dc_field; \
74 dc->dc_field = mode; \
75 DC_UnlockDC(hdc); \
76 return prevMode; \
77 }
78
79 // --------------------------------------------------------- File Statics
80
81 static void W32kSetDCState16(HDC hDC, HDC hDCSave);
82
83 // ----------------------------------------------------- Public Functions
84
85 BOOL STDCALL W32kCancelDC(HDC hDC)
86 {
87 UNIMPLEMENTED;
88 }
89
90 HDC STDCALL W32kCreateCompatableDC(HDC hDC)
91 {
92 PDC NewDC, OrigDC;
93 HBITMAP hBitmap;
94
95 OrigDC = DC_HandleToPtr(hDC);
96 if (OrigDC == NULL)
97 {
98 return 0;
99 }
100
101 /* Allocate a new DC based on the original DC's device */
102 NewDC = DC_AllocDC(OrigDC->DriverName);
103 if (NewDC == NULL)
104 {
105 DC_UnlockDC(OrigDC);
106
107 return NULL;
108 }
109 DRIVER_ReferenceDriver (NewDC->DriverName);
110
111 /* Copy information from original DC to new DC */
112 NewDC->hSelf = NewDC;
113
114 /* FIXME: Should this DC request its own PDEV? */
115 NewDC->PDev = OrigDC->PDev;
116
117 NewDC->DMW = OrigDC->DMW;
118 memcpy(NewDC->FillPatternSurfaces,
119 OrigDC->FillPatternSurfaces,
120 sizeof OrigDC->FillPatternSurfaces);
121 NewDC->GDIInfo = OrigDC->GDIInfo;
122 NewDC->DevInfo = OrigDC->DevInfo;
123
124 /* FIXME: Should this DC request its own surface? */
125 NewDC->Surface = OrigDC->Surface;
126
127 NewDC->DriverFunctions = OrigDC->DriverFunctions;
128 /* DriverName is copied in the AllocDC routine */
129 NewDC->DeviceDriver = OrigDC->DeviceDriver;
130 NewDC->wndOrgX = OrigDC->wndOrgX;
131 NewDC->wndOrgY = OrigDC->wndOrgY;
132 NewDC->wndExtX = OrigDC->wndExtX;
133 NewDC->wndExtY = OrigDC->wndExtY;
134 NewDC->vportOrgX = OrigDC->vportOrgX;
135 NewDC->vportOrgY = OrigDC->vportOrgY;
136 NewDC->vportExtX = OrigDC->vportExtX;
137 NewDC->vportExtY = OrigDC->vportExtY;
138
139 DC_InitDC(NewDC);
140
141 /* Create default bitmap */
142 if (!(hBitmap = W32kCreateBitmap( 1, 1, 1, 1, NULL )))
143 {
144 DC_FreeDC(NewDC);
145 DC_UnlockDC(OrigDC);
146
147 return NULL;
148 }
149 NewDC->w.flags = DC_MEMORY;
150 NewDC->w.bitsPerPixel = 1;
151 NewDC->w.hBitmap = hBitmap;
152 NewDC->w.hFirstBitmap = hBitmap;
153
154 DC_UnlockDC(NewDC);
155 DC_UnlockDC(OrigDC);
156
157 return DC_PtrToHandle(NewDC);
158 }
159
160 HDC STDCALL W32kCreateDC(LPCWSTR Driver,
161 LPCWSTR Device,
162 LPCWSTR Output,
163 CONST PDEVMODEW InitData)
164 {
165 PGD_ENABLEDRIVER GDEnableDriver;
166 PDC NewDC;
167 HDC hDC = NULL;
168 DRVENABLEDATA DED;
169
170 /* Check for existing DC object */
171 if ((NewDC = DC_FindOpenDC(Driver)) != NULL)
172 {
173 hDC = DC_PtrToHandle(NewDC);
174 return W32kCreateCompatableDC(hDC);
175 }
176
177 /* Allocate a DC object */
178 if ((NewDC = DC_AllocDC(Driver)) == NULL)
179 {
180 return NULL;
181 }
182
183 /* Open the miniport driver */
184 if ((NewDC->DeviceDriver = DRIVER_FindMPDriver(Driver)) == NULL)
185 {
186 DbgPrint("FindMPDriver failed\n");
187 goto Failure;
188 }
189
190 /* Get the DDI driver's entry point */
191 /* FIXME: Retrieve DDI driver name from registry */
192 if ((GDEnableDriver = DRIVER_FindDDIDriver(L"\\??\\C:\\reactos\\system32\\drivers\\vgaddi.dll")) == NULL)
193 {
194 DbgPrint("FindDDIDriver failed\n");
195 goto Failure;
196 }
197
198 /* Call DDI driver's EnableDriver function */
199 RtlZeroMemory(&DED, sizeof(DED));
200
201 if (!GDEnableDriver(DDI_DRIVER_VERSION, sizeof(DED), &DED))
202 {
203 DbgPrint("DrvEnableDriver failed\n");
204 goto Failure;
205 }
206
207 /* Construct DDI driver function dispatch table */
208 if (!DRIVER_BuildDDIFunctions(&DED, &NewDC->DriverFunctions))
209 {
210 DbgPrint("BuildDDIFunctions failed\n");
211 goto Failure;
212 }
213
214 /* Allocate a phyical device handle from the driver */
215 if (Device != NULL)
216 {
217 wcsncpy(NewDC->DMW.dmDeviceName, Device, DMMAXDEVICENAME);
218 }
219 NewDC->DMW.dmSize = sizeof(NewDC->DMW);
220 NewDC->DMW.dmFields = 0x000fc000;
221
222 /* FIXME: get mode selection information from somewhere */
223
224 NewDC->DMW.dmLogPixels = 96;
225 NewDC->DMW.dmBitsPerPel = 8;
226 NewDC->DMW.dmPelsWidth = 640;
227 NewDC->DMW.dmPelsHeight = 480;
228 NewDC->DMW.dmDisplayFlags = 0;
229 NewDC->DMW.dmDisplayFrequency = 0;
230
231 NewDC->PDev = NewDC->DriverFunctions.EnablePDev(&NewDC->DMW,
232 L"",
233 HS_DDI_MAX,
234 NewDC->FillPatternSurfaces,
235 sizeof(NewDC->GDIInfo),
236 (ULONG *) &NewDC->GDIInfo,
237 sizeof(NewDC->DevInfo),
238 &NewDC->DevInfo,
239 NULL,
240 L"",
241 NewDC->DeviceDriver);
242 if (NewDC->PDev == NULL)
243 {
244 DbgPrint("DrvEnablePDEV failed\n");
245 goto Failure;
246 }
247
248 /* Complete initialization of the physical device */
249 NewDC->DriverFunctions.CompletePDev(NewDC->PDev, NewDC);
250
251 DRIVER_ReferenceDriver (Driver);
252
253 /* Enable the drawing surface */
254 NewDC->Surface = NewDC->DriverFunctions.EnableSurface(NewDC->PDev);
255
256 /* Initialize the DC state */
257 DC_InitDC(NewDC);
258
259 return DC_PtrToHandle(NewDC);
260
261 Failure:
262 DC_FreeDC(NewDC);
263 return NULL;
264 }
265
266 HDC STDCALL W32kCreateIC(LPCWSTR Driver,
267 LPCWSTR Device,
268 LPCWSTR Output,
269 CONST PDEVMODEW DevMode)
270 {
271 /* FIXME: this should probably do something else... */
272 return W32kCreateDC(Driver, Device, Output, DevMode);
273 }
274
275 BOOL STDCALL W32kDeleteDC(HDC DCHandle)
276 {
277 PDC DCToDelete;
278
279 UNIMPLEMENTED;
280
281 DCToDelete = DC_HandleToPtr(DCHandle);
282 if (DCToDelete == NULL)
283 {
284 return FALSE;
285 }
286
287 if (!DRIVER_UnreferenceDriver (DCToDelete->DriverName))
288 {
289 DCToDelete->DriverFunctions.DisableSurface(DCToDelete->PDev);
290 DCToDelete->DriverFunctions.DisablePDev(DCToDelete->PDev);
291 }
292
293 /* First delete all saved DCs */
294 while (DCToDelete->saveLevel)
295 {
296 PDC savedDC;
297 HDC savedHDC;
298
299 savedHDC = GDIOBJ_GetNextObject (DCHandle, GO_DC_MAGIC);
300 savedDC = DC_HandleToPtr (savedHDC);
301 if (savedDC == NULL)
302 {
303 break;
304 }
305 GDIOBJ_SetNextObject (DCHandle, GO_DC_MAGIC, GDIOBJ_GetNextObject (savedHDC, GO_DC_MAGIC));
306 DCToDelete->saveLevel--;
307 DC_UnlockDC (savedDC);
308 W32kDeleteDC (savedHDC);
309 }
310
311 /* Free GDI resources allocated to this DC */
312 if (!(DCToDelete->w.flags & DC_SAVED))
313 {
314 DC_UnlockDC (DCToDelete);
315 SelectObject (DCHandle, STOCK_BLACK_PEN);
316 SelectObject (DCHandle, STOCK_WHITE_BRUSH);
317 SelectObject (DCHandle, STOCK_SYSTEM_FONT);
318 DC_LockDC (DCHandle);
319 if (DCToDelete->w.flags & DC_MEMORY)
320 {
321 W32kDeleteObject (DCToDelete->w.hFirstBitmap);
322 }
323 }
324 if (DCToDelete->w.hClipRgn)
325 {
326 W32kDeleteObject (DCToDelete->w.hClipRgn);
327 }
328 if (DCToDelete->w.hVisRgn)
329 {
330 W32kDeleteObject (DCToDelete->w.hVisRgn);
331 }
332 if (DCToDelete->w.hGCClipRgn)
333 {
334 W32kDeleteObject (DCToDelete->w.hGCClipRgn);
335 }
336 #if 0 /* FIXME */
337 PATH_DestroyGdiPath (&DCToDelete->w.path);
338 #endif
339
340 DC_FreeDC (DCToDelete);
341
342 return STATUS_SUCCESS;
343 }
344
345 BOOL STDCALL W32kDeleteObject(HGDIOBJ hObject)
346 {
347 UNIMPLEMENTED;
348 }
349
350 INT STDCALL W32kDrawEscape(HDC hDC,
351 INT nEscape,
352 INT cbInput,
353 LPCSTR lpszInData)
354 {
355 UNIMPLEMENTED;
356 }
357
358 INT STDCALL W32kEnumObjects(HDC hDC,
359 INT ObjectType,
360 GOBJENUMPROC ObjectFunc,
361 LPARAM lParam)
362 {
363 UNIMPLEMENTED;
364 }
365
366 DC_GET_VAL( COLORREF, W32kGetBkColor, w.backgroundColor )
367 DC_GET_VAL( INT, W32kGetBkMode, w.backgroundMode )
368 DC_GET_VAL_EX( W32kGetBrushOrgEx, w.brushOrgX, w.brushOrgY, POINT )
369 DC_GET_VAL( HRGN, W32kGetClipRgn, w.hClipRgn )
370
371 HGDIOBJ STDCALL W32kGetCurrentObject(HDC hDC,
372 UINT ObjectType)
373 {
374 UNIMPLEMENTED;
375 }
376
377 DC_GET_VAL_EX( W32kGetCurrentPositionEx, w.CursPosX, w.CursPosY, POINT )
378
379 BOOL STDCALL W32kGetDCOrgEx(HDC hDC,
380 LPPOINT Point)
381 {
382 DC * dc;
383
384 if (!Point)
385 {
386 return FALSE;
387 }
388 dc = DC_HandleToPtr(hDC);
389 if (dc == NULL)
390 {
391 return FALSE;
392 }
393
394 Point->x = Point->y = 0;
395
396 Point->x += dc->w.DCOrgX;
397 Point->y += dc->w.DCOrgY;
398 DC_UnlockDC (hDC);
399
400 return TRUE;
401 }
402
403 HDC STDCALL W32kGetDCState16(HDC hDC)
404 {
405 PDC newdc, dc;
406
407 dc = DC_HandleToPtr(hDC);
408 if (dc == NULL)
409 {
410 return 0;
411 }
412
413 newdc = DC_AllocDC(NULL);
414 if (newdc == NULL)
415 {
416 DC_UnlockDC(hDC);
417 return 0;
418 }
419
420 newdc->w.flags = dc->w.flags | DC_SAVED;
421 #if 0
422 newdc->w.devCaps = dc->w.devCaps;
423 #endif
424 newdc->w.hPen = dc->w.hPen;
425 newdc->w.hBrush = dc->w.hBrush;
426 newdc->w.hFont = dc->w.hFont;
427 newdc->w.hBitmap = dc->w.hBitmap;
428 newdc->w.hFirstBitmap = dc->w.hFirstBitmap;
429 #if 0
430 newdc->w.hDevice = dc->w.hDevice;
431 newdc->w.hPalette = dc->w.hPalette;
432 #endif
433 newdc->w.totalExtent = dc->w.totalExtent;
434 newdc->w.bitsPerPixel = dc->w.bitsPerPixel;
435 newdc->w.ROPmode = dc->w.ROPmode;
436 newdc->w.polyFillMode = dc->w.polyFillMode;
437 newdc->w.stretchBltMode = dc->w.stretchBltMode;
438 newdc->w.relAbsMode = dc->w.relAbsMode;
439 newdc->w.backgroundMode = dc->w.backgroundMode;
440 newdc->w.backgroundColor = dc->w.backgroundColor;
441 newdc->w.textColor = dc->w.textColor;
442 newdc->w.brushOrgX = dc->w.brushOrgX;
443 newdc->w.brushOrgY = dc->w.brushOrgY;
444 newdc->w.textAlign = dc->w.textAlign;
445 newdc->w.charExtra = dc->w.charExtra;
446 newdc->w.breakTotalExtra = dc->w.breakTotalExtra;
447 newdc->w.breakCount = dc->w.breakCount;
448 newdc->w.breakExtra = dc->w.breakExtra;
449 newdc->w.breakRem = dc->w.breakRem;
450 newdc->w.MapMode = dc->w.MapMode;
451 newdc->w.GraphicsMode = dc->w.GraphicsMode;
452 #if 0
453 /* Apparently, the DC origin is not changed by [GS]etDCState */
454 newdc->w.DCOrgX = dc->w.DCOrgX;
455 newdc->w.DCOrgY = dc->w.DCOrgY;
456 #endif
457 newdc->w.CursPosX = dc->w.CursPosX;
458 newdc->w.CursPosY = dc->w.CursPosY;
459 newdc->w.ArcDirection = dc->w.ArcDirection;
460 #if 0
461 newdc->w.xformWorld2Wnd = dc->w.xformWorld2Wnd;
462 newdc->w.xformWorld2Vport = dc->w.xformWorld2Vport;
463 newdc->w.xformVport2World = dc->w.xformVport2World;
464 newdc->w.vport2WorldValid = dc->w.vport2WorldValid;
465 #endif
466 newdc->wndOrgX = dc->wndOrgX;
467 newdc->wndOrgY = dc->wndOrgY;
468 newdc->wndExtX = dc->wndExtX;
469 newdc->wndExtY = dc->wndExtY;
470 newdc->vportOrgX = dc->vportOrgX;
471 newdc->vportOrgY = dc->vportOrgY;
472 newdc->vportExtX = dc->vportExtX;
473 newdc->vportExtY = dc->vportExtY;
474
475 newdc->hSelf = DC_PtrToHandle(newdc);
476 newdc->saveLevel = 0;
477
478 #if 0
479 PATH_InitGdiPath( &newdc->w.path );
480 #endif
481
482 /* Get/SetDCState() don't change hVisRgn field ("Undoc. Windows" p.559). */
483
484 #if 0
485 newdc->w.hGCClipRgn = newdc->w.hVisRgn = 0;
486 #endif
487 if (dc->w.hClipRgn)
488 {
489 newdc->w.hClipRgn = W32kCreateRectRgn( 0, 0, 0, 0 );
490 W32kCombineRgn( newdc->w.hClipRgn, dc->w.hClipRgn, 0, RGN_COPY );
491 }
492 else
493 {
494 newdc->w.hClipRgn = 0;
495 }
496 DC_UnlockDC(hDC);
497
498 return newdc->hSelf;
499 }
500
501 INT STDCALL W32kGetDeviceCaps(HDC hDC,
502 INT Index)
503 {
504 PDC dc;
505 INT ret;
506 POINT pt;
507
508 dc = DC_HandleToPtr(hDC);
509 if (dc == NULL)
510 {
511 return 0;
512 }
513
514 /* Device capabilities for the printer */
515 switch (Index)
516 {
517 case PHYSICALWIDTH:
518 if(W32kEscape(hDC, GETPHYSPAGESIZE, 0, NULL, (LPVOID)&pt) > 0)
519 {
520 return pt.x;
521 }
522 break;
523
524 case PHYSICALHEIGHT:
525 if(W32kEscape(hDC, GETPHYSPAGESIZE, 0, NULL, (LPVOID)&pt) > 0)
526 {
527 return pt.y;
528 }
529 break;
530
531 case PHYSICALOFFSETX:
532 if(W32kEscape(hDC, GETPRINTINGOFFSET, 0, NULL, (LPVOID)&pt) > 0)
533 {
534 return pt.x;
535 }
536 break;
537
538 case PHYSICALOFFSETY:
539 if(W32kEscape(hDC, GETPRINTINGOFFSET, 0, NULL, (LPVOID)&pt) > 0)
540 {
541 return pt.y;
542 }
543 break;
544
545 case SCALINGFACTORX:
546 if(W32kEscape(hDC, GETSCALINGFACTOR, 0, NULL, (LPVOID)&pt) > 0)
547 {
548 return pt.x;
549 }
550 break;
551
552 case SCALINGFACTORY:
553 if(W32kEscape(hDC, GETSCALINGFACTOR, 0, NULL, (LPVOID)&pt) > 0)
554 {
555 return pt.y;
556 }
557 break;
558 }
559
560 if ((Index < 0) || (Index > sizeof(DEVICECAPS) - sizeof(WORD)))
561 {
562 DC_UnlockDC(hDC);
563 return 0;
564 }
565
566 DPRINT("(%04x,%d): returning %d\n",
567 hDC, Index, *(WORD *)(((char *)dc->w.devCaps) + Index));
568 ret = *(WORD *)(((char *)dc->w.devCaps) + Index);
569
570 DC_UnlockDC(hDC);
571 return ret;
572 }
573
574 DC_GET_VAL( INT, W32kGetMapMode, w.MapMode )
575 DC_GET_VAL( INT, W32kGetPolyFillMode, w.polyFillMode )
576
577 INT STDCALL W32kGetObject(HGDIOBJ hGDIObj,
578 INT BufSize,
579 LPVOID Object)
580 {
581 UNIMPLEMENTED;
582 }
583
584 DWORD STDCALL W32kGetObjectType(HGDIOBJ hGDIObj)
585 {
586 UNIMPLEMENTED;
587 }
588
589 DC_GET_VAL( INT, W32kGetRelAbs, w.relAbsMode )
590 DC_GET_VAL( INT, W32kGetROP2, w.ROPmode )
591 DC_GET_VAL( INT, W32kGetStretchBltMode, w.stretchBltMode )
592
593 HGDIOBJ STDCALL W32kGetStockObject(INT Object)
594 {
595 UNIMPLEMENTED;
596 }
597
598 DC_GET_VAL( UINT, W32kGetTextAlign, w.textAlign )
599 DC_GET_VAL( COLORREF, W32kGetTextColor, w.textColor )
600 DC_GET_VAL_EX( W32kGetViewportExtEx, vportExtX, vportExtY, SIZE )
601 DC_GET_VAL_EX( W32kGetViewportOrgEx, vportOrgX, vportOrgY, POINT )
602 DC_GET_VAL_EX( W32kGetWindowExtEx, wndExtX, wndExtY, SIZE )
603 DC_GET_VAL_EX( W32kGetWindowOrgEx, wndOrgX, wndOrgY, POINT )
604
605 HDC STDCALL W32kResetDC(HDC hDC, CONST DEVMODE *InitData)
606 {
607 UNIMPLEMENTED;
608 }
609
610 BOOL STDCALL W32kRestoreDC(HDC hDC, INT SaveLevel)
611 {
612 PDC dc, dcs;
613 BOOL success;
614
615 dc = DC_HandleToPtr(hDC);
616 if(!dc)
617 {
618 return FALSE;
619 }
620
621 if (SaveLevel == -1)
622 {
623 SaveLevel = dc->saveLevel;
624 }
625
626 if ((SaveLevel < 1) || (SaveLevel > dc->saveLevel))
627 {
628 DC_UnlockDC(hDC);
629
630 return FALSE;
631 }
632
633 success = TRUE;
634 while (dc->saveLevel >= SaveLevel)
635 {
636 HDC hdcs = GDIOBJ_GetNextObject (hDC, GO_DC_MAGIC);
637
638 dcs = DC_HandleToPtr (hdcs);
639 if (dcs == NULL)
640 {
641 DC_UnlockDC (hDC);
642
643 return FALSE;
644 }
645 GDIOBJ_SetNextObject (hDC, GO_DC_MAGIC, GDIOBJ_GetNextObject (hdcs, GO_DC_MAGIC));
646 if (--dc->saveLevel < SaveLevel)
647 {
648 W32kSetDCState16 (hDC, hdcs);
649 #if 0
650 if (!PATH_AssignGdiPath( &dc->w.path, &dcs->w.path ))
651 {
652 /* FIXME: This might not be quite right, since we're
653 * returning FALSE but still destroying the saved DC state */
654 success = FALSE;
655 }
656 #endif
657 }
658 W32kDeleteDC (hdcs);
659 }
660 DC_UnlockDC (hDC);
661
662 return success;
663 }
664
665 INT STDCALL W32kSaveDC(HDC hDC)
666 {
667 HDC hdcs;
668 PDC dc, dcs;
669 INT ret;
670
671 dc = DC_HandleToPtr (hDC);
672 if (dc == NULL)
673 {
674 return 0;
675 }
676
677 if (!(hdcs = W32kGetDCState16 (hDC)))
678 {
679 DC_UnlockDC (hDC);
680
681 return 0;
682 }
683 dcs = DC_HandleToPtr (hdcs);
684
685 #if 0
686 /* Copy path. The reason why path saving / restoring is in SaveDC/
687 * RestoreDC and not in GetDCState/SetDCState is that the ...DCState
688 * functions are only in Win16 (which doesn't have paths) and that
689 * SetDCState doesn't allow us to signal an error (which can happen
690 * when copying paths).
691 */
692 if (!PATH_AssignGdiPath (&dcs->w.path, &dc->w.path))
693 {
694 DC_UnlockDC (hdc);
695 DC_UnlockDC (hdcs);
696 W32kDeleteDC (hdcs);
697 return 0;
698 }
699 #endif
700
701 GDIOBJ_SetNextObject (hdcs, GO_DC_MAGIC, GDIOBJ_GetNextObject (hDC, GO_DC_MAGIC));
702 GDIOBJ_SetNextObject (hDC, GO_DC_MAGIC, hdcs);
703 ret = ++dc->saveLevel;
704 DC_UnlockDC (hdcs);
705 DC_UnlockDC (hDC);
706
707 return ret;
708 }
709
710 HGDIOBJ STDCALL W32kSelectObject(HDC hDC, HGDIOBJ GDIObj)
711 {
712 UNIMPLEMENTED;
713 }
714
715 DC_SET_MODE( W32kSetBkMode, w.backgroundMode, TRANSPARENT, OPAQUE )
716 DC_SET_MODE( W32kSetPolyFillMode, w.polyFillMode, ALTERNATE, WINDING )
717 // DC_SET_MODE( W32kSetRelAbs, w.relAbsMode, ABSOLUTE, RELATIVE )
718 DC_SET_MODE( W32kSetROP2, w.ROPmode, R2_BLACK, R2_WHITE )
719 DC_SET_MODE( W32kSetStretchBltMode, w.stretchBltMode, BLACKONWHITE, HALFTONE )
720
721 COLORREF STDCALL W32kSetBkColor(HDC hDC, COLORREF color)
722 {
723 COLORREF oldColor;
724 PDC dc = DC_HandleToPtr(hDC);
725
726 if (!dc)
727 {
728 return 0x80000000;
729 }
730
731 oldColor = dc->w.backgroundColor;
732 dc->w.backgroundColor = color;
733 DC_UnlockDC(hDC);
734
735 return oldColor;
736 }
737
738 static void W32kSetDCState16(HDC hDC, HDC hDCSave)
739 {
740 PDC dc, dcs;
741
742 dc = DC_HandleToPtr(hDC);
743 if (dc == NULL)
744 {
745 return;
746 }
747
748 dcs = DC_HandleToPtr(hDCSave);
749 if (dcs == NULL)
750 {
751 DC_UnlockDC(hDC);
752
753 return;
754 }
755 if (!dcs->w.flags & DC_SAVED)
756 {
757 DC_UnlockDC(hDC);
758 DC_UnlockDC(hDCSave);
759
760 return;
761 }
762
763 dc->w.flags = dcs->w.flags & ~DC_SAVED;
764
765 #if 0
766 dc->w.devCaps = dcs->w.devCaps;
767 #endif
768
769 dc->w.hFirstBitmap = dcs->w.hFirstBitmap;
770
771 #if 0
772 dc->w.hDevice = dcs->w.hDevice;
773 #endif
774
775 dc->w.totalExtent = dcs->w.totalExtent;
776 dc->w.ROPmode = dcs->w.ROPmode;
777 dc->w.polyFillMode = dcs->w.polyFillMode;
778 dc->w.stretchBltMode = dcs->w.stretchBltMode;
779 dc->w.relAbsMode = dcs->w.relAbsMode;
780 dc->w.backgroundMode = dcs->w.backgroundMode;
781 dc->w.backgroundColor = dcs->w.backgroundColor;
782 dc->w.textColor = dcs->w.textColor;
783 dc->w.brushOrgX = dcs->w.brushOrgX;
784 dc->w.brushOrgY = dcs->w.brushOrgY;
785 dc->w.textAlign = dcs->w.textAlign;
786 dc->w.charExtra = dcs->w.charExtra;
787 dc->w.breakTotalExtra = dcs->w.breakTotalExtra;
788 dc->w.breakCount = dcs->w.breakCount;
789 dc->w.breakExtra = dcs->w.breakExtra;
790 dc->w.breakRem = dcs->w.breakRem;
791 dc->w.MapMode = dcs->w.MapMode;
792 dc->w.GraphicsMode = dcs->w.GraphicsMode;
793 #if 0
794 /* Apparently, the DC origin is not changed by [GS]etDCState */
795 dc->w.DCOrgX = dcs->w.DCOrgX;
796 dc->w.DCOrgY = dcs->w.DCOrgY;
797 #endif
798 dc->w.CursPosX = dcs->w.CursPosX;
799 dc->w.CursPosY = dcs->w.CursPosY;
800 dc->w.ArcDirection = dcs->w.ArcDirection;
801
802 #if 0
803 dc->w.xformWorld2Wnd = dcs->w.xformWorld2Wnd;
804 dc->w.xformWorld2Vport = dcs->w.xformWorld2Vport;
805 dc->w.xformVport2World = dcs->w.xformVport2World;
806 dc->w.vport2WorldValid = dcs->w.vport2WorldValid;
807 #endif
808
809 dc->wndOrgX = dcs->wndOrgX;
810 dc->wndOrgY = dcs->wndOrgY;
811 dc->wndExtX = dcs->wndExtX;
812 dc->wndExtY = dcs->wndExtY;
813 dc->vportOrgX = dcs->vportOrgX;
814 dc->vportOrgY = dcs->vportOrgY;
815 dc->vportExtX = dcs->vportExtX;
816 dc->vportExtY = dcs->vportExtY;
817
818 if (!(dc->w.flags & DC_MEMORY))
819 {
820 dc->w.bitsPerPixel = dcs->w.bitsPerPixel;
821 }
822
823 #if 0
824 if (dcs->w.hClipRgn)
825 {
826 if (!dc->w.hClipRgn)
827 {
828 dc->w.hClipRgn = W32kCreateRectRgn( 0, 0, 0, 0 );
829 }
830 W32kCombineRgn( dc->w.hClipRgn, dcs->w.hClipRgn, 0, RGN_COPY );
831 }
832 else
833 {
834 if (dc->w.hClipRgn)
835 {
836 W32kDeleteObject( dc->w.hClipRgn );
837 }
838
839 dc->w.hClipRgn = 0;
840 }
841 CLIPPING_UpdateGCRegion( dc );
842 #endif
843
844 W32kSelectObject( hDC, dcs->w.hBitmap );
845 W32kSelectObject( hDC, dcs->w.hBrush );
846 W32kSelectObject( hDC, dcs->w.hFont );
847 W32kSelectObject( hDC, dcs->w.hPen );
848 W32kSetBkColor( hDC, dcs->w.backgroundColor);
849 W32kSetTextColor( hDC, dcs->w.textColor);
850
851 #if 0
852 GDISelectPalette16( hDC, dcs->w.hPalette, FALSE );
853 #endif
854
855 DC_UnlockDC(hDC);
856 DC_UnlockDC(hDCSave);
857 }
858
859 // ---------------------------------------------------- Private Interface
860
861 PDC DC_AllocDC(LPCWSTR Driver)
862 {
863 PDC NewDC;
864
865 NewDC = (PDC) GDIOBJ_AllocObject(sizeof(DC), GO_DC_MAGIC);
866 if (NewDC == NULL)
867 {
868 return NULL;
869 }
870 if (Driver != NULL)
871 {
872 NewDC->DriverName = ExAllocatePool(NonPagedPool,
873 (wcslen(Driver) + 1) * sizeof(WCHAR));
874 wcscpy(NewDC->DriverName, Driver);
875 }
876
877 return NewDC;
878 }
879
880 PDC DC_FindOpenDC(LPCWSTR Driver)
881 {
882 /* FIXME */
883 return NULL;
884 }
885
886 void DC_InitDC(PDC DCToInit)
887 {
888 HDC DCHandle;
889
890 DCHandle = DC_PtrToHandle(DCToInit);
891 // W32kRealizeDefaultPalette(DCHandle);
892 W32kSetTextColor(DCHandle, DCToInit->w.textColor);
893 W32kSetBkColor(DCHandle, DCToInit->w.backgroundColor);
894 W32kSelectObject(DCHandle, DCToInit->w.hPen);
895 W32kSelectObject(DCHandle, DCToInit->w.hBrush);
896 W32kSelectObject(DCHandle, DCToInit->w.hFont);
897 // CLIPPING_UpdateGCRegion(DCToInit);
898 }
899
900 void DC_FreeDC(PDC DCToFree)
901 {
902 ExFreePool(DCToFree->DriverName);
903 if (!GDIOBJ_FreeObject((PGDIOBJ)DCToFree, GO_DC_MAGIC))
904 {
905 DbgPrint("DC_FreeDC failed\n");
906 }
907 }
908
909 void
910 DC_UpdateXforms(PDC dc)
911 {
912 XFORM xformWnd2Vport;
913 FLOAT scaleX, scaleY;
914
915 /* Construct a transformation to do the window-to-viewport conversion */
916 scaleX = (FLOAT)dc->vportExtX / (FLOAT)dc->wndExtX;
917 scaleY = (FLOAT)dc->vportExtY / (FLOAT)dc->wndExtY;
918 xformWnd2Vport.eM11 = scaleX;
919 xformWnd2Vport.eM12 = 0.0;
920 xformWnd2Vport.eM21 = 0.0;
921 xformWnd2Vport.eM22 = scaleY;
922 xformWnd2Vport.eDx = (FLOAT)dc->vportOrgX -
923 scaleX * (FLOAT)dc->wndOrgX;
924 xformWnd2Vport.eDy = (FLOAT)dc->vportOrgY -
925 scaleY * (FLOAT)dc->wndOrgY;
926
927 /* Combine with the world transformation */
928 W32kCombineTransform(&dc->w.xformWorld2Vport,
929 &dc->w.xformWorld2Wnd,
930 &xformWnd2Vport );
931
932 /* Create inverse of world-to-viewport transformation */
933 dc->w.vport2WorldValid = DC_InvertXform(&dc->w.xformWorld2Vport,
934 &dc->w.xformVport2World);
935 }
936
937 BOOL
938 DC_InvertXform(const XFORM *xformSrc,
939 XFORM *xformDest)
940 {
941 FLOAT determinant;
942
943 determinant = xformSrc->eM11*xformSrc->eM22 -
944 xformSrc->eM12*xformSrc->eM21;
945 if (determinant > -1e-12 && determinant < 1e-12)
946 {
947 return FALSE;
948 }
949
950 xformDest->eM11 = xformSrc->eM22 / determinant;
951 xformDest->eM12 = -xformSrc->eM12 / determinant;
952 xformDest->eM21 = -xformSrc->eM21 / determinant;
953 xformDest->eM22 = xformSrc->eM11 / determinant;
954 xformDest->eDx = -xformSrc->eDx * xformDest->eM11 -
955 xformSrc->eDy * xformDest->eM21;
956 xformDest->eDy = -xformSrc->eDx * xformDest->eM12 -
957 xformSrc->eDy * xformDest->eM22;
958
959 return TRUE;
960 }
961
962