1 /*
2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS Win32k subsystem
4 * PURPOSE: Functions for creation and destruction of DCs
5 * FILE: win32ss/gdi/ntgdi/dcobjs.c
6 * PROGRAMER: Timo Kreuzer (timo.kreuzer@rectos.org)
7 */
8
9 #include <win32k.h>
10
11 #define NDEBUG
12 #include <debug.h>
13
14 VOID
15 FASTCALL
DC_vUpdateFillBrush(PDC pdc)16 DC_vUpdateFillBrush(PDC pdc)
17 {
18 PDC_ATTR pdcattr = pdc->pdcattr;
19 PBRUSH pbrFill;
20
21 /* Check if the brush handle has changed */
22 if (pdcattr->hbrush != pdc->dclevel.pbrFill->BaseObject.hHmgr)
23 {
24 /* Try to lock the new brush */
25 pbrFill = BRUSH_ShareLockBrush(pdcattr->hbrush);
26 if (pbrFill)
27 {
28 /* Unlock old brush, set new brush */
29 BRUSH_ShareUnlockBrush(pdc->dclevel.pbrFill);
30 pdc->dclevel.pbrFill = pbrFill;
31
32 /* Mark eboFill as dirty */
33 pdcattr->ulDirty_ |= DIRTY_FILL;
34 }
35 else
36 {
37 /* Invalid brush handle, restore old one */
38 pdcattr->hbrush = pdc->dclevel.pbrFill->BaseObject.hHmgr;
39 }
40 }
41
42 /* Check if the EBRUSHOBJ needs update */
43 if (pdcattr->ulDirty_ & DIRTY_FILL)
44 {
45 /* Update eboFill */
46 EBRUSHOBJ_vUpdateFromDC(&pdc->eboFill, pdc->dclevel.pbrFill, pdc);
47 }
48
49 /* Check for DC brush */
50 if (pdcattr->hbrush == StockObjects[DC_BRUSH])
51 {
52 /* Update the eboFill's solid color */
53 EBRUSHOBJ_vSetSolidRGBColor(&pdc->eboFill, pdcattr->crBrushClr);
54 }
55
56 /* Clear flags */
57 pdcattr->ulDirty_ &= ~(DIRTY_FILL | DC_BRUSH_DIRTY);
58 }
59
60 VOID
61 FASTCALL
DC_vUpdateLineBrush(PDC pdc)62 DC_vUpdateLineBrush(PDC pdc)
63 {
64 PDC_ATTR pdcattr = pdc->pdcattr;
65 PBRUSH pbrLine;
66
67 /* Check if the pen handle has changed */
68 if (pdcattr->hpen != pdc->dclevel.pbrLine->BaseObject.hHmgr)
69 {
70 /* Try to lock the new pen */
71 pbrLine = PEN_ShareLockPen(pdcattr->hpen);
72 if (pbrLine)
73 {
74 /* Unlock old brush, set new brush */
75 BRUSH_ShareUnlockBrush(pdc->dclevel.pbrLine);
76 pdc->dclevel.pbrLine = pbrLine;
77
78 /* Mark eboLine as dirty */
79 pdcattr->ulDirty_ |= DIRTY_LINE;
80 }
81 else
82 {
83 /* Invalid pen handle, restore old one */
84 pdcattr->hpen = pdc->dclevel.pbrLine->BaseObject.hHmgr;
85 }
86 }
87
88 /* Check if the EBRUSHOBJ needs update */
89 if (pdcattr->ulDirty_ & DIRTY_LINE)
90 {
91 /* Update eboLine */
92 EBRUSHOBJ_vUpdateFromDC(&pdc->eboLine, pdc->dclevel.pbrLine, pdc);
93 }
94
95 /* Check for DC pen */
96 if (pdcattr->hpen == StockObjects[DC_PEN])
97 {
98 /* Update the eboLine's solid color */
99 EBRUSHOBJ_vSetSolidRGBColor(&pdc->eboLine, pdcattr->crPenClr);
100 }
101
102 /* Clear flags */
103 pdcattr->ulDirty_ &= ~(DIRTY_LINE | DC_PEN_DIRTY);
104 }
105
106 VOID
107 FASTCALL
DC_vUpdateTextBrush(PDC pdc)108 DC_vUpdateTextBrush(PDC pdc)
109 {
110 PDC_ATTR pdcattr = pdc->pdcattr;
111
112 /* Timo : The text brush should never be changed.
113 * Jérôme : Yeah, but its palette must be updated anyway! */
114 if(pdcattr->ulDirty_ & DIRTY_TEXT)
115 EBRUSHOBJ_vUpdateFromDC(&pdc->eboText, pbrDefaultBrush, pdc);
116
117 /* Update the eboText's solid color */
118 EBRUSHOBJ_vSetSolidRGBColor(&pdc->eboText, pdcattr->crForegroundClr);
119
120 /* Clear flag */
121 pdcattr->ulDirty_ &= ~DIRTY_TEXT;
122 }
123
124 VOID
125 FASTCALL
DC_vUpdateBackgroundBrush(PDC pdc)126 DC_vUpdateBackgroundBrush(PDC pdc)
127 {
128 PDC_ATTR pdcattr = pdc->pdcattr;
129
130 if(pdcattr->ulDirty_ & DIRTY_BACKGROUND)
131 EBRUSHOBJ_vUpdateFromDC(&pdc->eboBackground, pbrDefaultBrush, pdc);
132
133 /* Update the eboBackground's solid color */
134 EBRUSHOBJ_vSetSolidRGBColor(&pdc->eboBackground, pdcattr->crBackgroundClr);
135
136 /* Clear flag */
137 pdcattr->ulDirty_ &= ~DIRTY_BACKGROUND;
138 }
139
140 VOID
141 NTAPI
DC_vSetBrushOrigin(PDC pdc,LONG x,LONG y)142 DC_vSetBrushOrigin(PDC pdc, LONG x, LONG y)
143 {
144 /* Set the brush origin */
145 pdc->dclevel.ptlBrushOrigin.x = x;
146 pdc->dclevel.ptlBrushOrigin.y = y;
147
148 /* Set the fill origin */
149 pdc->ptlFillOrigin.x = x + pdc->ptlDCOrig.x;
150 pdc->ptlFillOrigin.y = y + pdc->ptlDCOrig.y;
151 }
152
153 /**
154 * \name NtGdiSetBrushOrg
155 *
156 * \brief Sets the brush origin that GDI uses when drawing with pattern
157 * brushes. The brush origin is relative to the DC origin.
158 *
159 * @implemented
160 */
161 _Success_(return!=FALSE)
162 __kernel_entry
163 BOOL
164 APIENTRY
NtGdiSetBrushOrg(_In_ HDC hdc,_In_ INT x,_In_ INT y,_Out_opt_ LPPOINT pptOut)165 NtGdiSetBrushOrg(
166 _In_ HDC hdc,
167 _In_ INT x,
168 _In_ INT y,
169 _Out_opt_ LPPOINT pptOut)
170 {
171
172 POINT ptOut;
173 /* Call the internal function */
174 BOOL Ret = GreSetBrushOrg( hdc, x, y, &ptOut);
175 if (Ret)
176 {
177 /* Check if the old origin was requested */
178 if (pptOut != NULL)
179 {
180 /* Enter SEH for buffer transfer */
181 _SEH2_TRY
182 {
183 /* Probe and copy the old origin */
184 ProbeForWrite(pptOut, sizeof(POINT), 1);
185 *pptOut = ptOut;
186 }
187 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
188 {
189 _SEH2_YIELD(return FALSE);
190 }
191 _SEH2_END;
192 }
193 }
194 return Ret;
195 }
196
197 HPALETTE
198 NTAPI
GdiSelectPalette(HDC hDC,HPALETTE hpal,BOOL ForceBackground)199 GdiSelectPalette(
200 HDC hDC,
201 HPALETTE hpal,
202 BOOL ForceBackground)
203 {
204 PDC pdc;
205 HPALETTE oldPal = NULL;
206 PPALETTE ppal;
207
208 // FIXME: Mark the palette as a [fore\back]ground pal
209 pdc = DC_LockDc(hDC);
210 if (!pdc)
211 {
212 return NULL;
213 }
214
215 /* Check if this is a valid palette handle */
216 ppal = PALETTE_ShareLockPalette(hpal);
217 if (!ppal)
218 {
219 DC_UnlockDc(pdc);
220 return NULL;
221 }
222
223 /// FIXME: we shouldn't dereference pSurface when the PDEV is not locked
224 /* Is this a valid palette for this depth? */
225 if ((!pdc->dclevel.pSurface) ||
226 (BitsPerFormat(pdc->dclevel.pSurface->SurfObj.iBitmapFormat) <= 8
227 && (ppal->flFlags & PAL_INDEXED)) ||
228 (BitsPerFormat(pdc->dclevel.pSurface->SurfObj.iBitmapFormat) > 8))
229 {
230 /* Get old palette, set new one */
231 oldPal = pdc->dclevel.hpal;
232 pdc->dclevel.hpal = hpal;
233 DC_vSelectPalette(pdc, ppal);
234
235 /* Mark the brushes invalid */
236 pdc->pdcattr->ulDirty_ |= DIRTY_FILL | DIRTY_LINE |
237 DIRTY_BACKGROUND | DIRTY_TEXT;
238 }
239
240 if(pdc->dctype == DCTYPE_MEMORY)
241 {
242 // This didn't work anyway
243 //IntGdiRealizePalette(hDC);
244 }
245
246 PALETTE_ShareUnlockPalette(ppal);
247 DC_UnlockDc(pdc);
248
249 return oldPal;
250 }
251
252 /*
253 * @implemented
254 */
255 HBRUSH
256 APIENTRY
NtGdiSelectBrush(IN HDC hDC,IN HBRUSH hBrush)257 NtGdiSelectBrush(
258 IN HDC hDC,
259 IN HBRUSH hBrush)
260 {
261 PDC pDC;
262 HBRUSH hOrgBrush;
263
264 if (hDC == NULL || hBrush == NULL) return NULL;
265
266 pDC = DC_LockDc(hDC);
267 if (!pDC)
268 {
269 return NULL;
270 }
271
272 /* Simply return the user mode value, without checking */
273 hOrgBrush = pDC->pdcattr->hbrush;
274 pDC->pdcattr->hbrush = hBrush;
275 DC_vUpdateFillBrush(pDC);
276
277 DC_UnlockDc(pDC);
278
279 return hOrgBrush;
280 }
281
282 /*
283 * @implemented
284 */
285 HPEN
286 APIENTRY
NtGdiSelectPen(IN HDC hDC,IN HPEN hPen)287 NtGdiSelectPen(
288 IN HDC hDC,
289 IN HPEN hPen)
290 {
291 PDC pDC;
292 HPEN hOrgPen;
293
294 if (hDC == NULL || hPen == NULL) return NULL;
295
296 pDC = DC_LockDc(hDC);
297 if (!pDC)
298 {
299 return NULL;
300 }
301
302 /* Simply return the user mode value, without checking */
303 hOrgPen = pDC->pdcattr->hpen;
304 pDC->pdcattr->hpen = hPen;
305 DC_vUpdateLineBrush(pDC);
306
307 DC_UnlockDc(pDC);
308
309 return hOrgPen;
310 }
311
312 BOOL
313 NTAPI
DC_bIsBitmapCompatible(PDC pdc,PSURFACE psurf)314 DC_bIsBitmapCompatible(PDC pdc, PSURFACE psurf)
315 {
316 ULONG cBitsPixel;
317
318 /* Must be an API bitmap */
319 if (!(psurf->flags & API_BITMAP)) return FALSE;
320
321 /* DIB sections are always compatible */
322 if (psurf->hSecure != NULL) return TRUE;
323
324 /* See if this is the same PDEV */
325 if (psurf->SurfObj.hdev == (HDEV)pdc->ppdev)
326 return TRUE;
327
328 /* Get the bit depth of the bitmap */
329 cBitsPixel = gajBitsPerFormat[psurf->SurfObj.iBitmapFormat];
330
331 /* 1 BPP is compatible */
332 if ((cBitsPixel == 1) || (cBitsPixel == pdc->ppdev->gdiinfo.cBitsPixel))
333 return TRUE;
334
335 return FALSE;
336 }
337
338 /*
339 * @implemented
340 */
341 HBITMAP
342 APIENTRY
NtGdiSelectBitmap(IN HDC hdc,IN HBITMAP hbmp)343 NtGdiSelectBitmap(
344 IN HDC hdc,
345 IN HBITMAP hbmp)
346 {
347 PDC pdc;
348 HBITMAP hbmpOld;
349 PSURFACE psurfNew, psurfOld;
350 HDC hdcOld;
351 ASSERT_NOGDILOCKS();
352
353 /* Verify parameters */
354 if (hdc == NULL || hbmp == NULL) return NULL;
355
356 /* First lock the DC */
357 pdc = DC_LockDc(hdc);
358 if (!pdc)
359 {
360 return NULL;
361 }
362
363 /* Must be a memory dc to select a bitmap */
364 if (pdc->dctype != DCTYPE_MEMORY)
365 {
366 DC_UnlockDc(pdc);
367 return NULL;
368 }
369
370 /* Save the old bitmap */
371 psurfOld = pdc->dclevel.pSurface;
372
373 /* Check if there is a bitmap selected */
374 if (psurfOld)
375 {
376 /* Get the old bitmap's handle */
377 hbmpOld = psurfOld->BaseObject.hHmgr;
378 }
379 else
380 {
381 /* Use the default bitmap */
382 hbmpOld = StockObjects[DEFAULT_BITMAP];
383 }
384
385 /* Check if the new bitmap is already selected */
386 if (hbmp == hbmpOld)
387 {
388 /* Unlock the DC and return the old bitmap */
389 DC_UnlockDc(pdc);
390 return hbmpOld;
391 }
392
393 /* Check if the default bitmap was passed */
394 if (hbmp == StockObjects[DEFAULT_BITMAP])
395 {
396 psurfNew = NULL;
397
398 /* Default bitmap is 1x1 pixel */
399 pdc->dclevel.sizl.cx = 1;
400 pdc->dclevel.sizl.cy = 1;
401 }
402 else
403 {
404 /* Reference the new bitmap and check if it's valid */
405 psurfNew = SURFACE_ShareLockSurface(hbmp);
406 if (!psurfNew)
407 {
408 DC_UnlockDc(pdc);
409 return NULL;
410 }
411
412 /* Check if the bitmap is compatible with the dc */
413 if (!DC_bIsBitmapCompatible(pdc, psurfNew))
414 {
415 /* Dereference the bitmap, unlock the DC and fail. */
416 SURFACE_ShareUnlockSurface(psurfNew);
417 DC_UnlockDc(pdc);
418 return NULL;
419 }
420
421 /* Set the bitmap's hdc and check if it was set before */
422 hdcOld = InterlockedCompareExchangePointer((PVOID*)&psurfNew->hdc, hdc, 0);
423 if (hdcOld != NULL)
424 {
425 /* The bitmap is already selected into a different DC */
426 ASSERT(hdcOld != hdc);
427
428 /* Dereference the bitmap, unlock the DC and fail. */
429 SURFACE_ShareUnlockSurface(psurfNew);
430 DC_UnlockDc(pdc);
431 return NULL;
432 }
433
434 /* Copy the bitmap size */
435 pdc->dclevel.sizl = psurfNew->SurfObj.sizlBitmap;
436
437 /* Check if the bitmap is a dibsection */
438 if (psurfNew->hSecure)
439 {
440 /* Set DIBSECTION attribute */
441 pdc->pdcattr->ulDirty_ |= DC_DIBSECTION;
442 }
443 else
444 {
445 /* Remove DIBSECTION attribute */
446 pdc->pdcattr->ulDirty_ &= ~DC_DIBSECTION;
447 }
448 }
449
450 /* Select the new bitmap */
451 pdc->dclevel.pSurface = psurfNew;
452
453 /* Check if there was a bitmap selected before */
454 if (psurfOld)
455 {
456 /* Reset hdc of the old bitmap, it isn't selected anymore */
457 psurfOld->hdc = NULL;
458
459 /* Dereference the old bitmap */
460 SURFACE_ShareUnlockSurface(psurfOld);
461 }
462
463 /* Mark the DC brushes and the RAO region invalid */
464 pdc->pdcattr->ulDirty_ |= DIRTY_FILL | DIRTY_LINE;
465 pdc->fs |= DC_DIRTY_RAO;
466
467 /* Update the system region */
468 REGION_SetRectRgn(pdc->prgnVis,
469 0,
470 0,
471 pdc->dclevel.sizl.cx,
472 pdc->dclevel.sizl.cy);
473
474 /* Unlock the DC */
475 DC_UnlockDc(pdc);
476
477 /* Return the old bitmap handle */
478 return hbmpOld;
479 }
480
481
482 BOOL
483 APIENTRY
NtGdiSelectClipPath(HDC hDC,int Mode)484 NtGdiSelectClipPath(
485 HDC hDC,
486 int Mode)
487 {
488 PREGION RgnPath;
489 PPATH pPath, pNewPath;
490 BOOL success = FALSE;
491 PDC_ATTR pdcattr;
492 PDC pdc;
493
494 pdc = DC_LockDc(hDC);
495 if (!pdc)
496 {
497 EngSetLastError(ERROR_INVALID_PARAMETER);
498 return FALSE;
499 }
500 pdcattr = pdc->pdcattr;
501
502 pPath = PATH_LockPath(pdc->dclevel.hPath);
503 if (!pPath)
504 {
505 DC_UnlockDc(pdc);
506 return FALSE;
507 }
508
509 /* Check that path is closed */
510 if (pPath->state != PATH_Closed)
511 {
512 EngSetLastError(ERROR_CAN_NOT_COMPLETE);
513 success = FALSE;
514 goto Exit;
515 }
516
517 /* Construct a region from the path */
518 RgnPath = IntSysCreateRectpRgn(0, 0, 0, 0);
519 if (!RgnPath)
520 {
521 EngSetLastError(ERROR_NOT_ENOUGH_MEMORY);
522 DC_UnlockDc(pdc);
523 return FALSE;
524 }
525
526 pNewPath = PATH_FlattenPath(pPath);
527
528 success = PATH_PathToRegion(pNewPath, pdcattr->jFillMode, RgnPath);
529
530 PATH_UnlockPath(pNewPath);
531 PATH_Delete(pNewPath->BaseObject.hHmgr);
532
533 if (success) success = IntGdiExtSelectClipRgn(pdc, RgnPath, Mode) != ERROR;
534
535 REGION_Delete(RgnPath);
536
537 Exit:
538 PATH_UnlockPath(pPath);
539 PATH_Delete(pdc->dclevel.hPath);
540 pdc->dclevel.flPath &= ~DCPATH_ACTIVE;
541 pdc->dclevel.hPath = NULL;
542
543 DC_UnlockDc(pdc);
544
545 return success;
546 }
547
548 HFONT
549 NTAPI
DC_hSelectFont(_In_ PDC pdc,_In_ HFONT hlfntNew)550 DC_hSelectFont(
551 _In_ PDC pdc,
552 _In_ HFONT hlfntNew)
553 {
554 PLFONT plfntNew;
555 HFONT hlfntOld;
556
557 // Legacy crap that will die with font engine rewrite
558 if (!NT_SUCCESS(TextIntRealizeFont(hlfntNew, NULL)))
559 {
560 return NULL;
561 }
562
563 /* Get the current selected font */
564 hlfntOld = pdc->dclevel.plfnt->BaseObject.hHmgr;
565
566 /* Check if a new font should be selected */
567 if (hlfntNew != hlfntOld)
568 {
569 /* Lock the new font */
570 plfntNew = LFONT_ShareLockFont(hlfntNew);
571 if (plfntNew)
572 {
573 /* Success, dereference the old font */
574 LFONT_ShareUnlockFont(pdc->dclevel.plfnt);
575
576 /* Select the new font */
577 pdc->dclevel.plfnt = plfntNew;
578 pdc->pdcattr->hlfntNew = hlfntNew;
579
580 /* Update dirty flags */
581 pdc->pdcattr->ulDirty_ |= DIRTY_CHARSET;
582 pdc->pdcattr->ulDirty_ &= ~SLOW_WIDTHS;
583 }
584 else
585 {
586 /* Failed, restore old, return NULL */
587 pdc->pdcattr->hlfntNew = hlfntOld;
588 hlfntOld = NULL;
589 }
590 }
591
592 return hlfntOld;
593 }
594
595 HFONT
596 APIENTRY
NtGdiSelectFont(_In_ HDC hdc,_In_ HFONT hfont)597 NtGdiSelectFont(
598 _In_ HDC hdc,
599 _In_ HFONT hfont)
600 {
601 HFONT hfontOld;
602 PDC pdc;
603
604 /* Check parameters */
605 if ((hdc == NULL) || (hfont == NULL))
606 {
607 return NULL;
608 }
609
610 /* Lock the DC */
611 pdc = DC_LockDc(hdc);
612 if (!pdc)
613 {
614 return NULL;
615 }
616
617 /* Call the internal function */
618 hfontOld = DC_hSelectFont(pdc, hfont);
619
620 /* Unlock the DC */
621 DC_UnlockDc(pdc);
622
623 /* Return the previously selected font */
624 return hfontOld;
625 }
626
627 HANDLE
628 APIENTRY
NtGdiGetDCObject(HDC hDC,INT ObjectType)629 NtGdiGetDCObject(HDC hDC, INT ObjectType)
630 {
631 HGDIOBJ SelObject;
632 DC *pdc;
633 PDC_ATTR pdcattr;
634
635 /* From Wine: GetCurrentObject does not SetLastError() on a null object */
636 if(!hDC) return NULL;
637
638 if(!(pdc = DC_LockDc(hDC)))
639 {
640 return NULL;
641 }
642 pdcattr = pdc->pdcattr;
643
644 if (pdcattr->ulDirty_ & (DIRTY_FILL | DC_BRUSH_DIRTY))
645 DC_vUpdateFillBrush(pdc);
646
647 if (pdcattr->ulDirty_ & (DIRTY_LINE | DC_PEN_DIRTY))
648 DC_vUpdateLineBrush(pdc);
649
650 switch(ObjectType)
651 {
652 case GDI_OBJECT_TYPE_EXTPEN:
653 case GDI_OBJECT_TYPE_PEN:
654 SelObject = pdcattr->hpen;
655 break;
656
657 case GDI_OBJECT_TYPE_BRUSH:
658 SelObject = pdcattr->hbrush;
659 break;
660
661 case GDI_OBJECT_TYPE_PALETTE:
662 SelObject = pdc->dclevel.hpal;
663 break;
664
665 case GDI_OBJECT_TYPE_FONT:
666 SelObject = pdcattr->hlfntNew;
667 break;
668
669 case GDI_OBJECT_TYPE_BITMAP:
670 {
671 SURFACE *psurf = pdc->dclevel.pSurface;
672 SelObject = psurf ? psurf->BaseObject.hHmgr : StockObjects[DEFAULT_BITMAP];
673 break;
674 }
675
676 case GDI_OBJECT_TYPE_COLORSPACE:
677 DPRINT1("FIXME: NtGdiGetCurrentObject() ObjectType OBJ_COLORSPACE not supported yet!\n");
678 // SelObject = dc->dclevel.pColorSpace.BaseObject.hHmgr; ?
679 SelObject = NULL;
680 break;
681
682 default:
683 SelObject = NULL;
684 EngSetLastError(ERROR_INVALID_PARAMETER);
685 break;
686 }
687
688 DC_UnlockDc(pdc);
689 return SelObject;
690 }
691
692 /* See WINE, MSDN, OSR and Feng Yuan - Windows Graphics Programming Win32 GDI and DirectDraw
693 *
694 * 1st: http://www.codeproject.com/gdi/cliprgnguide.asp is wrong!
695 *
696 * The intersection of the clip with the meta region is not Rao it's API!
697 * Go back and read 7.2 Clipping pages 418-19:
698 * Rao = API & Vis:
699 * 1) The Rao region is the intersection of the API region and the system region,
700 * named after the Microsoft engineer who initially proposed it.
701 * 2) The Rao region can be calculated from the API region and the system region.
702 *
703 * API:
704 * API region is the intersection of the meta region and the clipping region,
705 * clearly named after the fact that it is controlled by GDI API calls.
706 */
707 INT
708 APIENTRY
NtGdiGetRandomRgn(HDC hdc,HRGN hrgnDest,INT iCode)709 NtGdiGetRandomRgn(
710 HDC hdc,
711 HRGN hrgnDest,
712 INT iCode)
713 {
714 INT ret = 0;
715 PDC pdc;
716 PREGION prgnSrc = NULL;
717
718 pdc = DC_LockDc(hdc);
719 if (!pdc)
720 {
721 EngSetLastError(ERROR_INVALID_HANDLE);
722 return -1;
723 }
724
725 switch (iCode)
726 {
727 case CLIPRGN:
728 prgnSrc = pdc->dclevel.prgnClip;
729 break;
730
731 case METARGN:
732 prgnSrc = pdc->dclevel.prgnMeta;
733 break;
734
735 case APIRGN:
736 if (pdc->fs & DC_DIRTY_RAO)
737 CLIPPING_UpdateGCRegion(pdc);
738 if (pdc->prgnAPI)
739 {
740 prgnSrc = pdc->prgnAPI;
741 }
742 else if (pdc->dclevel.prgnClip)
743 {
744 prgnSrc = pdc->dclevel.prgnClip;
745 }
746 else if (pdc->dclevel.prgnMeta)
747 {
748 prgnSrc = pdc->dclevel.prgnMeta;
749 }
750 break;
751
752 case SYSRGN:
753 prgnSrc = pdc->prgnVis;
754 break;
755
756 default:
757 break;
758 }
759
760 if (prgnSrc)
761 {
762 PREGION prgnDest = REGION_LockRgn(hrgnDest);
763 if (prgnDest)
764 {
765 ret = IntGdiCombineRgn(prgnDest, prgnSrc, 0, RGN_COPY) == ERROR ? -1 : 1;
766 if ((ret == 1) && (iCode == SYSRGN))
767 {
768 /// \todo FIXME This is not really correct, since we already modified the region
769 ret = REGION_bOffsetRgn(prgnDest, pdc->ptlDCOrig.x, pdc->ptlDCOrig.y);
770 }
771 REGION_UnlockRgn(prgnDest);
772 }
773 else
774 ret = -1;
775 }
776
777 DC_UnlockDc(pdc);
778
779 return ret;
780 }
781
782 ULONG
783 APIENTRY
NtGdiEnumObjects(IN HDC hdc,IN INT iObjectType,IN ULONG cjBuf,OUT OPTIONAL PVOID pvBuf)784 NtGdiEnumObjects(
785 IN HDC hdc,
786 IN INT iObjectType,
787 IN ULONG cjBuf,
788 OUT OPTIONAL PVOID pvBuf)
789 {
790 UNIMPLEMENTED;
791 return 0;
792 }
793
794 /* EOF */
795