[NtGDI] Use flag for text align mode.
[reactos.git] / win32ss / gdi / ntgdi / dcutil.c
1 #include <win32k.h>
2
3 #define NDEBUG
4 #include <debug.h>
5
6 BOOL FASTCALL
7 GreDPtoLP(HDC hdc, LPPOINT lpPoints, INT nCount)
8 {
9 PDC dc;
10 if (!(dc = DC_LockDc(hdc)))
11 {
12 EngSetLastError(ERROR_INVALID_HANDLE);
13 return FALSE;
14 }
15 IntDPtoLP(dc, lpPoints, nCount);
16 DC_UnlockDc(dc);
17 return TRUE;
18 }
19
20 BOOL FASTCALL
21 GreLPtoDP(HDC hdc, LPPOINT lpPoints, INT nCount)
22 {
23 PDC dc;
24 if (!(dc = DC_LockDc(hdc)))
25 {
26 EngSetLastError(ERROR_INVALID_HANDLE);
27 return FALSE;
28 }
29 IntLPtoDP(dc, lpPoints, nCount);
30 DC_UnlockDc(dc);
31 return TRUE;
32 }
33
34 int FASTCALL
35 GreGetBkMode(HDC hdc)
36 {
37 PDC dc;
38 LONG lBkMode;
39 if (!(dc = DC_LockDc(hdc)))
40 {
41 EngSetLastError(ERROR_INVALID_HANDLE);
42 return CLR_INVALID;
43 }
44 lBkMode = dc->pdcattr->lBkMode;
45 DC_UnlockDc(dc);
46 return lBkMode;
47 }
48
49 COLORREF FASTCALL
50 GreGetBkColor(HDC hdc)
51 {
52 PDC dc;
53 COLORREF crBk;
54 if (!(dc = DC_LockDc(hdc)))
55 {
56 EngSetLastError(ERROR_INVALID_HANDLE);
57 return CLR_INVALID;
58 }
59 crBk = dc->pdcattr->ulBackgroundClr;
60 DC_UnlockDc(dc);
61 return crBk;
62 }
63
64 int FASTCALL
65 GreGetMapMode(HDC hdc)
66 {
67 PDC dc;
68 INT iMapMode;
69 if (!(dc = DC_LockDc(hdc)))
70 {
71 EngSetLastError(ERROR_INVALID_HANDLE);
72 return CLR_INVALID;
73 }
74 iMapMode = dc->pdcattr->iMapMode;
75 DC_UnlockDc(dc);
76 return iMapMode;
77 }
78
79 COLORREF FASTCALL
80 GreGetTextColor(HDC hdc)
81 {
82 PDC dc;
83 ULONG ulForegroundClr;
84 if (!(dc = DC_LockDc(hdc)))
85 {
86 EngSetLastError(ERROR_INVALID_HANDLE);
87 return CLR_INVALID;
88 }
89 ulForegroundClr = dc->pdcattr->ulForegroundClr;
90 DC_UnlockDc(dc);
91 return ulForegroundClr;
92 }
93
94 COLORREF FASTCALL
95 IntGdiSetBkColor(HDC hDC, COLORREF color)
96 {
97 COLORREF oldColor;
98 PDC dc;
99 PDC_ATTR pdcattr;
100 HBRUSH hBrush;
101
102 if (!(dc = DC_LockDc(hDC)))
103 {
104 EngSetLastError(ERROR_INVALID_HANDLE);
105 return CLR_INVALID;
106 }
107 pdcattr = dc->pdcattr;
108
109 oldColor = pdcattr->ulBackgroundClr;
110 pdcattr->ulBackgroundClr = color;
111
112 if (pdcattr->crBackgroundClr != color)
113 {
114 pdcattr->ulDirty_ |= (DIRTY_BACKGROUND|DIRTY_LINE|DIRTY_FILL); // Clear Flag if set.
115 pdcattr->crBackgroundClr = color;
116 }
117 hBrush = pdcattr->hbrush;
118 DC_UnlockDc(dc);
119 NtGdiSelectBrush(hDC, hBrush);
120 return oldColor;
121 }
122
123 INT FASTCALL
124 IntGdiSetBkMode(HDC hDC, INT Mode)
125 {
126 COLORREF oldMode;
127 PDC dc;
128 PDC_ATTR pdcattr;
129
130 if (!(dc = DC_LockDc(hDC)))
131 {
132 EngSetLastError(ERROR_INVALID_HANDLE);
133 return CLR_INVALID;
134 }
135 pdcattr = dc->pdcattr;
136 oldMode = pdcattr->lBkMode;
137 pdcattr->jBkMode = Mode;
138 pdcattr->lBkMode = Mode;
139 DC_UnlockDc(dc);
140 return oldMode;
141 }
142
143 UINT
144 FASTCALL
145 IntGdiSetTextAlign(HDC hDC,
146 UINT Mode)
147 {
148 UINT prevAlign;
149 DC *dc;
150 PDC_ATTR pdcattr;
151
152 dc = DC_LockDc(hDC);
153 if (!dc)
154 {
155 EngSetLastError(ERROR_INVALID_HANDLE);
156 return GDI_ERROR;
157 }
158 pdcattr = dc->pdcattr;
159 prevAlign = pdcattr->lTextAlign;
160 pdcattr->lTextAlign = Mode;
161 if (pdcattr->dwLayout & LAYOUT_RTL)
162 {
163 if ((Mode & TA_CENTER) != TA_CENTER) Mode ^= TA_RIGHT;
164 }
165 pdcattr->flTextAlign = Mode & TA_MASK;
166 DC_UnlockDc(dc);
167 return prevAlign;
168 }
169
170 COLORREF
171 FASTCALL
172 IntGdiSetTextColor(HDC hDC,
173 COLORREF color)
174 {
175 COLORREF crOldColor;
176 PDC pdc;
177 PDC_ATTR pdcattr;
178
179 pdc = DC_LockDc(hDC);
180 if (!pdc)
181 {
182 EngSetLastError(ERROR_INVALID_HANDLE);
183 return CLR_INVALID;
184 }
185 pdcattr = pdc->pdcattr;
186
187 crOldColor = (COLORREF) pdcattr->ulForegroundClr;
188 pdcattr->ulForegroundClr = (ULONG)color;
189
190 if (pdcattr->crForegroundClr != color)
191 {
192 pdcattr->ulDirty_ |= (DIRTY_TEXT|DIRTY_LINE|DIRTY_FILL);
193 pdcattr->crForegroundClr = color;
194 }
195
196 DC_vUpdateTextBrush(pdc);
197 DC_vUpdateLineBrush(pdc);
198 DC_vUpdateFillBrush(pdc);
199
200 DC_UnlockDc(pdc);
201
202 return crOldColor;
203 }
204
205 COLORREF FASTCALL
206 IntSetDCBrushColor(HDC hdc, COLORREF crColor)
207 {
208 COLORREF OldColor = CLR_INVALID;
209 PDC dc;
210 if (!(dc = DC_LockDc(hdc)))
211 {
212 EngSetLastError(ERROR_INVALID_HANDLE);
213 return CLR_INVALID;
214 }
215 else
216 {
217 OldColor = (COLORREF) dc->pdcattr->ulBrushClr;
218 dc->pdcattr->ulBrushClr = (ULONG) crColor;
219
220 if ( dc->pdcattr->crBrushClr != crColor )
221 {
222 dc->pdcattr->ulDirty_ |= DIRTY_FILL;
223 dc->pdcattr->crBrushClr = crColor;
224 }
225 }
226 DC_UnlockDc(dc);
227 return OldColor;
228 }
229
230 BOOL FASTCALL
231 GreSetBrushOrg(
232 HDC hdc,
233 INT x,
234 INT y,
235 LPPOINT pptOut)
236 {
237 PDC pdc = DC_LockDc(hdc);
238 if (pdc == NULL)
239 {
240 EngSetLastError(ERROR_INVALID_HANDLE);
241 return FALSE;
242 }
243
244 if (pptOut != NULL)
245 {
246 *pptOut = pdc->pdcattr->ptlBrushOrigin;
247 }
248
249 pdc->pdcattr->ptlBrushOrigin.x = x;
250 pdc->pdcattr->ptlBrushOrigin.y = y;
251
252 DC_vSetBrushOrigin(pdc, x, y);
253
254 DC_UnlockDc(pdc);
255 return TRUE;
256 }
257
258 COLORREF FASTCALL
259 IntSetDCPenColor(HDC hdc, COLORREF crColor)
260 {
261 COLORREF OldColor;
262 PDC dc;
263 if (!(dc = DC_LockDc(hdc)))
264 {
265 EngSetLastError(ERROR_INVALID_PARAMETER);
266 return CLR_INVALID;
267 }
268
269 OldColor = (COLORREF)dc->pdcattr->ulPenClr;
270 dc->pdcattr->ulPenClr = (ULONG)crColor;
271
272 if (dc->pdcattr->crPenClr != crColor)
273 {
274 dc->pdcattr->ulDirty_ |= DIRTY_LINE;
275 dc->pdcattr->crPenClr = crColor;
276 }
277 DC_UnlockDc(dc);
278 return OldColor;
279 }
280
281 int
282 FASTCALL
283 GreSetStretchBltMode(HDC hDC, int iStretchMode)
284 {
285 PDC pdc;
286 PDC_ATTR pdcattr;
287 INT oSMode = 0;
288
289 pdc = DC_LockDc(hDC);
290 if (pdc)
291 {
292 pdcattr = pdc->pdcattr;
293 oSMode = pdcattr->lStretchBltMode;
294 pdcattr->lStretchBltMode = iStretchMode;
295
296 // Wine returns an error here. We set the default.
297 if ((iStretchMode <= 0) || (iStretchMode > MAXSTRETCHBLTMODE)) iStretchMode = WHITEONBLACK;
298
299 pdcattr->jStretchBltMode = iStretchMode;
300 DC_UnlockDc(pdc);
301 }
302 return oSMode;
303 }
304
305 int FASTCALL
306 GreGetGraphicsMode(HDC hdc)
307 {
308 PDC dc;
309 int GraphicsMode;
310 if (!(dc = DC_LockDc(hdc)))
311 {
312 EngSetLastError(ERROR_INVALID_HANDLE);
313 return CLR_INVALID;
314 }
315 GraphicsMode = dc->pdcattr->iGraphicsMode;
316 DC_UnlockDc(dc);
317 return GraphicsMode;
318 }
319
320 VOID
321 FASTCALL
322 DCU_SetDcUndeletable(HDC hDC)
323 {
324 PDC dc = DC_LockDc(hDC);
325 if (!dc)
326 {
327 EngSetLastError(ERROR_INVALID_HANDLE);
328 return;
329 }
330
331 dc->fs |= DC_FLAG_PERMANENT;
332 DC_UnlockDc(dc);
333 return;
334 }
335
336 #if 0
337 BOOL FASTCALL
338 IntIsPrimarySurface(SURFOBJ *SurfObj)
339 {
340 if (PrimarySurface.pSurface == NULL)
341 {
342 return FALSE;
343 }
344 return SurfObj->hsurf == PrimarySurface.pSurface; // <- FIXME: WTF?
345 }
346 #endif
347
348 BOOL
349 FASTCALL
350 IntSetDefaultRegion(PDC pdc)
351 {
352 PSURFACE pSurface;
353 PREGION prgn;
354 RECTL rclWnd, rclClip;
355
356 IntGdiReleaseRaoRgn(pdc);
357
358 rclWnd.left = 0;
359 rclWnd.top = 0;
360 rclWnd.right = pdc->dclevel.sizl.cx;
361 rclWnd.bottom = pdc->dclevel.sizl.cy;
362 rclClip = rclWnd;
363
364 //EngAcquireSemaphoreShared(pdc->ppdev->hsemDevLock);
365 if (pdc->ppdev->flFlags & PDEV_META_DEVICE)
366 {
367 pSurface = pdc->dclevel.pSurface;
368 if (pSurface && pSurface->flags & PDEV_SURFACE)
369 {
370 rclClip.left += pdc->ppdev->ptlOrigion.x;
371 rclClip.top += pdc->ppdev->ptlOrigion.y;
372 rclClip.right += pdc->ppdev->ptlOrigion.x;
373 rclClip.bottom += pdc->ppdev->ptlOrigion.y;
374 }
375 }
376 //EngReleaseSemaphore(pdc->ppdev->hsemDevLock);
377
378 prgn = pdc->prgnVis;
379
380 if (prgn && prgn != prgnDefault)
381 {
382 REGION_SetRectRgn( prgn,
383 rclClip.left,
384 rclClip.top,
385 rclClip.right ,
386 rclClip.bottom );
387 }
388 else
389 {
390 prgn = IntSysCreateRectpRgn( rclClip.left,
391 rclClip.top,
392 rclClip.right ,
393 rclClip.bottom );
394 pdc->prgnVis = prgn;
395 }
396
397 if (prgn)
398 {
399 pdc->ptlDCOrig.x = 0;
400 pdc->ptlDCOrig.y = 0;
401 pdc->erclWindow = rclWnd;
402 pdc->erclClip = rclClip;
403 /* Might be an InitDC or DCE... */
404 pdc->ptlFillOrigin.x = pdc->dcattr.ptlBrushOrigin.x;
405 pdc->ptlFillOrigin.y = pdc->dcattr.ptlBrushOrigin.y;
406 return TRUE;
407 }
408
409 pdc->prgnVis = prgnDefault;
410 return FALSE;
411 }
412
413
414 BOOL APIENTRY
415 NtGdiCancelDC(HDC hDC)
416 {
417 UNIMPLEMENTED;
418 return FALSE;
419 }
420
421
422 WORD APIENTRY
423 IntGdiSetHookFlags(HDC hDC, WORD Flags)
424 {
425 WORD wRet;
426 DC *dc = DC_LockDc(hDC);
427
428 if (NULL == dc)
429 {
430 EngSetLastError(ERROR_INVALID_HANDLE);
431 return 0;
432 }
433
434 wRet = dc->fs & DC_FLAG_DIRTY_RAO; // FIXME: Wrong flag!
435
436 /* Info in "Undocumented Windows" is slightly confusing. */
437 DPRINT("DC %p, Flags %04x\n", hDC, Flags);
438
439 if (Flags & DCHF_INVALIDATEVISRGN)
440 {
441 /* hVisRgn has to be updated */
442 dc->fs |= DC_FLAG_DIRTY_RAO;
443 }
444 else if (Flags & DCHF_VALIDATEVISRGN || 0 == Flags)
445 {
446 //dc->fs &= ~DC_FLAG_DIRTY_RAO;
447 }
448
449 DC_UnlockDc(dc);
450
451 return wRet;
452 }
453
454
455 BOOL
456 APIENTRY
457 NtGdiGetDCDword(
458 HDC hDC,
459 UINT u,
460 DWORD *Result)
461 {
462 BOOL Ret = TRUE;
463 PDC pdc;
464 PDC_ATTR pdcattr;
465
466 DWORD SafeResult = 0;
467 NTSTATUS Status = STATUS_SUCCESS;
468
469 if (!Result)
470 {
471 EngSetLastError(ERROR_INVALID_PARAMETER);
472 return FALSE;
473 }
474
475 pdc = DC_LockDc(hDC);
476 if (!pdc)
477 {
478 EngSetLastError(ERROR_INVALID_HANDLE);
479 return FALSE;
480 }
481 pdcattr = pdc->pdcattr;
482
483 switch (u)
484 {
485 case GdiGetJournal:
486 break;
487
488 case GdiGetRelAbs:
489 SafeResult = pdcattr->lRelAbs;
490 break;
491
492 case GdiGetBreakExtra:
493 SafeResult = pdcattr->lBreakExtra;
494 break;
495
496 case GdiGerCharBreak:
497 SafeResult = pdcattr->cBreak;
498 break;
499
500 case GdiGetArcDirection:
501 if (pdcattr->dwLayout & LAYOUT_RTL)
502 SafeResult = AD_CLOCKWISE - ((pdc->dclevel.flPath & DCPATH_CLOCKWISE) != 0);
503 else
504 SafeResult = ((pdc->dclevel.flPath & DCPATH_CLOCKWISE) != 0) + AD_COUNTERCLOCKWISE;
505 break;
506
507 case GdiGetEMFRestorDc:
508 SafeResult = pdc->dclevel.lSaveDepth;
509 break;
510
511 case GdiGetFontLanguageInfo:
512 SafeResult = IntGetFontLanguageInfo(pdc);
513 break;
514
515 case GdiGetIsMemDc:
516 SafeResult = pdc->dctype;
517 break;
518
519 case GdiGetMapMode:
520 SafeResult = pdcattr->iMapMode;
521 break;
522
523 case GdiGetTextCharExtra:
524 SafeResult = pdcattr->lTextExtra;
525 break;
526
527 default:
528 EngSetLastError(ERROR_INVALID_PARAMETER);
529 Ret = FALSE;
530 break;
531 }
532
533 if (Ret)
534 {
535 _SEH2_TRY
536 {
537 ProbeForWrite(Result, sizeof(DWORD), 1);
538 *Result = SafeResult;
539 }
540 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
541 {
542 Status = _SEH2_GetExceptionCode();
543 }
544 _SEH2_END;
545
546 if (!NT_SUCCESS(Status))
547 {
548 SetLastNtError(Status);
549 Ret = FALSE;
550 }
551 }
552
553 DC_UnlockDc(pdc);
554 return Ret;
555 }
556
557 _Success_(return != FALSE)
558 BOOL
559 APIENTRY
560 NtGdiGetAndSetDCDword(
561 _In_ HDC hdc,
562 _In_ UINT u,
563 _In_ DWORD dwIn,
564 _Out_ DWORD *pdwResult)
565 {
566 BOOL Ret = TRUE;
567 PDC pdc;
568 PDC_ATTR pdcattr;
569
570 DWORD SafeResult = 0;
571 NTSTATUS Status = STATUS_SUCCESS;
572
573 if (!pdwResult)
574 {
575 EngSetLastError(ERROR_INVALID_PARAMETER);
576 return FALSE;
577 }
578
579 pdc = DC_LockDc(hdc);
580 if (!pdc)
581 {
582 EngSetLastError(ERROR_INVALID_HANDLE);
583 return FALSE;
584 }
585 pdcattr = pdc->pdcattr;
586
587 switch (u)
588 {
589 case GdiGetSetCopyCount:
590 SafeResult = pdc->ulCopyCount;
591 pdc->ulCopyCount = dwIn;
592 break;
593
594 case GdiGetSetTextAlign:
595 SafeResult = pdcattr->lTextAlign;
596 pdcattr->lTextAlign = dwIn;
597 // pdcattr->flTextAlign = dwIn; // Flags!
598 break;
599
600 case GdiGetSetRelAbs:
601 SafeResult = pdcattr->lRelAbs;
602 pdcattr->lRelAbs = dwIn;
603 break;
604
605 case GdiGetSetTextCharExtra:
606 SafeResult = pdcattr->lTextExtra;
607 pdcattr->lTextExtra = dwIn;
608 break;
609
610 case GdiGetSetSelectFont:
611 break;
612
613 case GdiGetSetMapperFlagsInternal:
614 if (dwIn & ~1)
615 {
616 EngSetLastError(ERROR_INVALID_PARAMETER);
617 Ret = FALSE;
618 break;
619 }
620 SafeResult = pdcattr->flFontMapper;
621 pdcattr->flFontMapper = dwIn;
622 break;
623
624 case GdiGetSetMapMode:
625 SafeResult = IntGdiSetMapMode(pdc, dwIn);
626 break;
627
628 case GdiGetSetArcDirection:
629 if (dwIn != AD_COUNTERCLOCKWISE && dwIn != AD_CLOCKWISE)
630 {
631 EngSetLastError(ERROR_INVALID_PARAMETER);
632 Ret = FALSE;
633 break;
634 }
635 if (pdcattr->dwLayout & LAYOUT_RTL) // Right to Left
636 {
637 SafeResult = AD_CLOCKWISE - ((pdc->dclevel.flPath & DCPATH_CLOCKWISE) != 0);
638 if (dwIn == AD_CLOCKWISE)
639 {
640 pdc->dclevel.flPath &= ~DCPATH_CLOCKWISE;
641 break;
642 }
643 pdc->dclevel.flPath |= DCPATH_CLOCKWISE;
644 }
645 else // Left to Right
646 {
647 SafeResult = ((pdc->dclevel.flPath & DCPATH_CLOCKWISE) != 0) +
648 AD_COUNTERCLOCKWISE;
649 if (dwIn == AD_COUNTERCLOCKWISE)
650 {
651 pdc->dclevel.flPath &= ~DCPATH_CLOCKWISE;
652 break;
653 }
654 pdc->dclevel.flPath |= DCPATH_CLOCKWISE;
655 }
656 break;
657
658 default:
659 EngSetLastError(ERROR_INVALID_PARAMETER);
660 Ret = FALSE;
661 break;
662 }
663
664 if (Ret)
665 {
666 _SEH2_TRY
667 {
668 ProbeForWrite(pdwResult, sizeof(DWORD), 1);
669 *pdwResult = SafeResult;
670 }
671 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
672 {
673 Status = _SEH2_GetExceptionCode();
674 }
675 _SEH2_END;
676
677 if (!NT_SUCCESS(Status))
678 {
679 SetLastNtError(Status);
680 Ret = FALSE;
681 }
682 }
683
684 DC_UnlockDc(pdc);
685 return Ret;
686 }
687
688 VOID
689 FASTCALL
690 IntUpdateBoundsRect(PDC pdc, PRECTL pRect)
691 {
692 if (pdc->fs & DC_ACCUM_APP)
693 {
694 RECTL_bUnionRect(&pdc->erclBoundsApp, &pdc->erclBoundsApp, pRect);
695 }
696 if (pdc->fs & DC_ACCUM_WMGR)
697 {
698 RECTL_bUnionRect(&pdc->erclBounds, &pdc->erclBounds, pRect);
699 }
700 }
701
702 DWORD
703 APIENTRY
704 NtGdiGetBoundsRect(
705 IN HDC hdc,
706 OUT LPRECT prc,
707 IN DWORD flags)
708 {
709 DWORD ret;
710 PDC pdc;
711 RECT rc;
712
713 /* Lock the DC */
714 if (!(pdc = DC_LockDc(hdc))) return 0;
715
716 if (!(flags & DCB_WINDOWMGR))
717 {
718 rc = pdc->erclBoundsApp;
719
720 if (RECTL_bIsEmptyRect(&rc))
721 {
722 rc.left = rc.top = rc.right = rc.bottom = 0;
723 ret = DCB_RESET;
724 }
725 else
726 {
727 RECTL rcRgn;
728 if (pdc->fs & DC_FLAG_DIRTY_RAO) CLIPPING_UpdateGCRegion(pdc);
729 if(!REGION_GetRgnBox(pdc->prgnRao, &rcRgn))
730 {
731 REGION_GetRgnBox(pdc->prgnVis, &rcRgn);
732 }
733 rc.left = max( rc.left, 0 );
734 rc.top = max( rc.top, 0 );
735 rc.right = min( rc.right, rcRgn.right - rcRgn.left );
736 rc.bottom = min( rc.bottom, rcRgn.bottom - rcRgn.top );
737 DPRINT("Rao dc %p r %d b %d\n",pdc,rcRgn.right - rcRgn.left, rcRgn.bottom - rcRgn.top);
738 DPRINT("rc l %d t %d\n",rc.left,rc.top);
739 DPRINT(" r %d b %d\n",rc.right,rc.bottom);
740 ret = DCB_SET;
741 }
742 IntDPtoLP( pdc, &rc, 2 );
743 DPRINT("rc1 l %d t %d\n",rc.left,rc.top);
744 DPRINT(" r %d b %d\n",rc.right,rc.bottom);
745 }
746 else
747 {
748 rc = pdc->erclBounds;
749 ret = DCB_SET;
750 }
751
752 /* Copy the rect to the caller */
753 _SEH2_TRY
754 {
755 ProbeForWrite(prc, sizeof(RECT), 1);
756 *prc = rc;
757 }
758 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
759 {
760 ret = 0;
761 }
762 _SEH2_END;
763
764 if (flags & DCB_RESET)
765 {
766 if (!(flags & DCB_WINDOWMGR))
767 {
768 pdc->erclBoundsApp.left = pdc->erclBoundsApp.top = INT_MAX;
769 pdc->erclBoundsApp.right = pdc->erclBoundsApp.bottom = INT_MIN;
770 }
771 else
772 {
773 pdc->erclBounds.left = pdc->erclBounds.top = INT_MAX;
774 pdc->erclBounds.right = pdc->erclBounds.bottom = INT_MIN;
775 }
776 }
777
778 DC_UnlockDc(pdc);
779 return ret;
780 }
781
782 DWORD
783 APIENTRY
784 NtGdiSetBoundsRect(
785 IN HDC hdc,
786 IN LPRECT prc,
787 IN DWORD flags)
788 {
789 DWORD ret;
790 PDC pdc;
791 RECTL rcl;
792
793 /* Verify arguments */
794 if ((flags & DCB_ENABLE) && (flags & DCB_DISABLE)) return 0;
795
796 /* Lock the DC */
797 if (!(pdc = DC_LockDc(hdc))) return 0;
798
799 /* Get the return value */
800 ret = DCB_RESET; /* we don't have device-specific bounds */
801 ret = (pdc->fs & (DC_ACCUM_APP|DC_ACCUM_WMGR) ? DCB_ENABLE : DCB_DISABLE) |
802 (RECTL_bIsEmptyRect(&pdc->erclBoundsApp) ? ret & DCB_SET : DCB_SET );
803 ret |= (flags & DCB_WINDOWMGR);
804
805 if (flags & DCB_RESET)
806 {
807 if (!(flags & DCB_WINDOWMGR))
808 {
809 pdc->erclBoundsApp.left = pdc->erclBoundsApp.top = INT_MAX;
810 pdc->erclBoundsApp.right = pdc->erclBoundsApp.bottom = INT_MIN;
811 }
812 else
813 {
814 pdc->erclBounds.left = pdc->erclBounds.top = INT_MAX;
815 pdc->erclBounds.right = pdc->erclBounds.bottom = INT_MIN;
816 }
817 }
818
819 if (flags & DCB_ACCUMULATE && prc != NULL)
820 {
821 /* Capture the rect */
822 _SEH2_TRY
823 {
824 ProbeForRead(prc, sizeof(RECT), 1);
825 rcl = *prc;
826 }
827 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
828 {
829 DC_UnlockDc(pdc);
830 _SEH2_YIELD(return 0;)
831 }
832 _SEH2_END;
833
834 RECTL_vMakeWellOrdered(&rcl);
835
836 if (!(flags & DCB_WINDOWMGR))
837 {
838 IntLPtoDP( pdc, (POINT *)&rcl, 2 );
839 RECTL_bUnionRect(&pdc->erclBoundsApp, &pdc->erclBoundsApp, &rcl);
840 }
841 else
842 RECTL_bUnionRect(&pdc->erclBounds, &pdc->erclBounds, &rcl);
843 }
844
845 if (flags & DCB_ENABLE)
846 {
847 if (!(flags & DCB_WINDOWMGR))
848 pdc->fs |= DC_ACCUM_APP;
849 else
850 pdc->fs |= DC_ACCUM_WMGR;
851 }
852 if (flags & DCB_DISABLE)
853 {
854 if (!(flags & DCB_WINDOWMGR))
855 pdc->fs &= ~DC_ACCUM_APP;
856 else
857 pdc->fs &= ~DC_ACCUM_WMGR;
858 }
859 DC_UnlockDc(pdc);
860 return ret;
861 }
862
863 /* Translates a COLORREF to the right color in the specified DC color space */
864 ULONG
865 TranslateCOLORREF(PDC pdc, COLORREF crColor)
866 {
867 PSURFACE psurfDC;
868 PPALETTE ppalDC;
869 ULONG index, ulColor, iBitmapFormat;
870 EXLATEOBJ exlo;
871
872 /* Get the DC surface */
873 psurfDC = pdc->dclevel.pSurface;
874
875 /* If no surface is selected, use the default bitmap */
876 if (!psurfDC)
877 psurfDC = psurfDefaultBitmap;
878
879 /* Check what color type this is */
880 switch (crColor >> 24)
881 {
882 case 0x00: /* RGB color */
883 break;
884
885 case 0x01: /* PALETTEINDEX */
886 index = crColor & 0xFFFFFF;
887 ppalDC = pdc->dclevel.ppal;
888 if (index >= ppalDC->NumColors) index = 0;
889
890 /* Get the RGB value */
891 crColor = PALETTE_ulGetRGBColorFromIndex(ppalDC, index);
892 break;
893
894 case 0x02: /* PALETTERGB */
895
896 if (pdc->dclevel.hpal != StockObjects[DEFAULT_PALETTE])
897 {
898 /* First find the nearest index in the dc palette */
899 ppalDC = pdc->dclevel.ppal;
900 index = PALETTE_ulGetNearestIndex(ppalDC, crColor & 0xFFFFFF);
901
902 /* Get the RGB value */
903 crColor = PALETTE_ulGetRGBColorFromIndex(ppalDC, index);
904 }
905 else
906 {
907 /* Use the pure color */
908 crColor = crColor & 0x00FFFFFF;
909 }
910 break;
911
912 case 0x10: /* DIBINDEX */
913 /* Mask the value to match the target bpp */
914 iBitmapFormat = psurfDC->SurfObj.iBitmapFormat;
915 if (iBitmapFormat == BMF_1BPP) index = crColor & 0x1;
916 else if (iBitmapFormat == BMF_4BPP) index = crColor & 0xf;
917 else if (iBitmapFormat == BMF_8BPP) index = crColor & 0xFF;
918 else if (iBitmapFormat == BMF_16BPP) index = crColor & 0xFFFF;
919 else index = crColor & 0xFFFFFF;
920 return index;
921
922 default:
923 DPRINT("Unsupported color type %u passed\n", crColor >> 24);
924 crColor &= 0xFFFFFF;
925 }
926
927 /* Initialize an XLATEOBJ from RGB to the target surface */
928 EXLATEOBJ_vInitialize(&exlo, &gpalRGB, psurfDC->ppal, 0xFFFFFF, 0, 0);
929
930 /* Translate the color to the target format */
931 ulColor = XLATEOBJ_iXlate(&exlo.xlo, crColor);
932
933 /* Cleanup the XLATEOBJ */
934 EXLATEOBJ_vCleanup(&exlo);
935
936 return ulColor;
937 }
938
939