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