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