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