Synchronize with trunk revision 59636 (just before Alex's CreateProcess revamp).
[reactos.git] / win32ss / gdi / ntgdi / dcutil.c
1 #include <win32k.h>
2
3 #define NDEBUG
4 #include <debug.h>
5
6 COLORREF FASTCALL
7 IntGdiSetBkColor(HDC hDC, COLORREF color)
8 {
9 COLORREF oldColor;
10 PDC dc;
11 PDC_ATTR pdcattr;
12 HBRUSH hBrush;
13
14 if (!(dc = DC_LockDc(hDC)))
15 {
16 EngSetLastError(ERROR_INVALID_HANDLE);
17 return CLR_INVALID;
18 }
19 pdcattr = dc->pdcattr;
20 oldColor = pdcattr->crBackgroundClr;
21 pdcattr->crBackgroundClr = color;
22 pdcattr->ulBackgroundClr = (ULONG)color;
23 pdcattr->ulDirty_ |= DIRTY_BACKGROUND|DIRTY_LINE|DIRTY_FILL; // Clear Flag if set.
24 hBrush = pdcattr->hbrush;
25 DC_UnlockDc(dc);
26 NtGdiSelectBrush(hDC, hBrush);
27 return oldColor;
28 }
29
30 INT FASTCALL
31 IntGdiSetBkMode(HDC hDC, INT Mode)
32 {
33 COLORREF oldMode;
34 PDC dc;
35 PDC_ATTR pdcattr;
36
37 if (!(dc = DC_LockDc(hDC)))
38 {
39 EngSetLastError(ERROR_INVALID_HANDLE);
40 return CLR_INVALID;
41 }
42 pdcattr = dc->pdcattr;
43 oldMode = pdcattr->lBkMode;
44 pdcattr->jBkMode = Mode;
45 pdcattr->lBkMode = Mode;
46 DC_UnlockDc(dc);
47 return oldMode;
48 }
49
50 UINT
51 FASTCALL
52 IntGdiSetTextAlign(HDC hDC,
53 UINT Mode)
54 {
55 UINT prevAlign;
56 DC *dc;
57 PDC_ATTR pdcattr;
58
59 dc = DC_LockDc(hDC);
60 if (!dc)
61 {
62 EngSetLastError(ERROR_INVALID_HANDLE);
63 return GDI_ERROR;
64 }
65 pdcattr = dc->pdcattr;
66 prevAlign = pdcattr->lTextAlign;
67 pdcattr->lTextAlign = Mode;
68 DC_UnlockDc(dc);
69 return prevAlign;
70 }
71
72 COLORREF
73 FASTCALL
74 IntGdiSetTextColor(HDC hDC,
75 COLORREF color)
76 {
77 COLORREF crOldColor;
78 PDC pdc;
79 PDC_ATTR pdcattr;
80
81 pdc = DC_LockDc(hDC);
82 if (!pdc)
83 {
84 EngSetLastError(ERROR_INVALID_HANDLE);
85 return CLR_INVALID;
86 }
87 pdcattr = pdc->pdcattr;
88
89 // What about ulForegroundClr, like in gdi32?
90 crOldColor = pdcattr->crForegroundClr;
91 pdcattr->crForegroundClr = color;
92 DC_vUpdateTextBrush(pdc);
93
94 DC_UnlockDc(pdc);
95
96 return crOldColor;
97 }
98
99 int
100 FASTCALL
101 GreSetStretchBltMode(HDC hDC, int iStretchMode)
102 {
103 PDC pdc;
104 PDC_ATTR pdcattr;
105 INT oSMode = 0;
106
107 pdc = DC_LockDc(hDC);
108 if (pdc)
109 {
110 pdcattr = pdc->pdcattr;
111 oSMode = pdcattr->lStretchBltMode;
112 pdcattr->lStretchBltMode = iStretchMode;
113
114 // Wine returns an error here. We set the default.
115 if ((iStretchMode <= 0) || (iStretchMode > MAXSTRETCHBLTMODE)) iStretchMode = WHITEONBLACK;
116
117 pdcattr->jStretchBltMode = iStretchMode;
118 }
119 return oSMode;
120 }
121
122 VOID
123 FASTCALL
124 DCU_SetDcUndeletable(HDC hDC)
125 {
126 PDC dc = DC_LockDc(hDC);
127 if (!dc)
128 {
129 EngSetLastError(ERROR_INVALID_HANDLE);
130 return;
131 }
132
133 dc->fs |= DC_FLAG_PERMANENT;
134 DC_UnlockDc(dc);
135 return;
136 }
137
138 #if 0
139 BOOL FASTCALL
140 IntIsPrimarySurface(SURFOBJ *SurfObj)
141 {
142 if (PrimarySurface.pSurface == NULL)
143 {
144 return FALSE;
145 }
146 return SurfObj->hsurf == PrimarySurface.pSurface; // <- FIXME: WTF?
147 }
148 #endif
149
150 BOOL
151 FASTCALL
152 IntSetDefaultRegion(PDC pdc)
153 {
154 PSURFACE pSurface;
155 PROSRGNDATA prgn;
156 RECTL rclWnd, rclClip;
157
158 IntGdiReleaseRaoRgn(pdc);
159
160 rclWnd.left = 0;
161 rclWnd.top = 0;
162 rclWnd.right = pdc->dclevel.sizl.cx;
163 rclWnd.bottom = pdc->dclevel.sizl.cy;
164 rclClip = rclWnd;
165
166 //EngAcquireSemaphoreShared(pdc->ppdev->hsemDevLock);
167 if (pdc->ppdev->flFlags & PDEV_META_DEVICE)
168 {
169 pSurface = pdc->dclevel.pSurface;
170 if (pSurface && pSurface->flags & PDEV_SURFACE)
171 {
172 rclClip.left += pdc->ppdev->ptlOrigion.x;
173 rclClip.top += pdc->ppdev->ptlOrigion.y;
174 rclClip.right += pdc->ppdev->ptlOrigion.x;
175 rclClip.bottom += pdc->ppdev->ptlOrigion.y;
176 }
177 }
178 //EngReleaseSemaphore(pdc->ppdev->hsemDevLock);
179
180 prgn = pdc->prgnVis;
181
182 if (prgn && prgn != prgnDefault)
183 {
184 REGION_SetRectRgn( prgn,
185 rclClip.left,
186 rclClip.top,
187 rclClip.right ,
188 rclClip.bottom );
189 }
190 else
191 {
192 prgn = IntSysCreateRectpRgn( rclClip.left,
193 rclClip.top,
194 rclClip.right ,
195 rclClip.bottom );
196 pdc->prgnVis = prgn;
197 }
198
199 if (prgn)
200 {
201 pdc->ptlDCOrig.x = 0;
202 pdc->ptlDCOrig.y = 0;
203 pdc->erclWindow = rclWnd;
204 pdc->erclClip = rclClip;
205 /* Might be an InitDC or DCE... */
206 pdc->ptlFillOrigin.x = pdc->dcattr.VisRectRegion.Rect.right;
207 pdc->ptlFillOrigin.y = pdc->dcattr.VisRectRegion.Rect.bottom;
208 return TRUE;
209 }
210
211 pdc->prgnVis = prgnDefault;
212 return FALSE;
213 }
214
215
216 BOOL APIENTRY
217 NtGdiCancelDC(HDC hDC)
218 {
219 UNIMPLEMENTED;
220 return FALSE;
221 }
222
223
224 WORD APIENTRY
225 IntGdiSetHookFlags(HDC hDC, WORD Flags)
226 {
227 WORD wRet;
228 DC *dc = DC_LockDc(hDC);
229
230 if (NULL == dc)
231 {
232 EngSetLastError(ERROR_INVALID_HANDLE);
233 return 0;
234 }
235
236 wRet = dc->fs & DC_FLAG_DIRTY_RAO; // FIXME: Wrong flag!
237
238 /* Info in "Undocumented Windows" is slightly confusing. */
239 DPRINT("DC %p, Flags %04x\n", hDC, Flags);
240
241 if (Flags & DCHF_INVALIDATEVISRGN)
242 {
243 /* hVisRgn has to be updated */
244 dc->fs |= DC_FLAG_DIRTY_RAO;
245 }
246 else if (Flags & DCHF_VALIDATEVISRGN || 0 == Flags)
247 {
248 dc->fs &= ~DC_FLAG_DIRTY_RAO;
249 }
250
251 DC_UnlockDc(dc);
252
253 return wRet;
254 }
255
256
257 BOOL
258 APIENTRY
259 NtGdiGetDCDword(
260 HDC hDC,
261 UINT u,
262 DWORD *Result)
263 {
264 BOOL Ret = TRUE;
265 PDC pdc;
266 PDC_ATTR pdcattr;
267
268 DWORD SafeResult = 0;
269 NTSTATUS Status = STATUS_SUCCESS;
270
271 if (!Result)
272 {
273 EngSetLastError(ERROR_INVALID_PARAMETER);
274 return FALSE;
275 }
276
277 pdc = DC_LockDc(hDC);
278 if (!pdc)
279 {
280 EngSetLastError(ERROR_INVALID_HANDLE);
281 return FALSE;
282 }
283 pdcattr = pdc->pdcattr;
284
285 switch (u)
286 {
287 case GdiGetJournal:
288 break;
289
290 case GdiGetRelAbs:
291 SafeResult = pdcattr->lRelAbs;
292 break;
293
294 case GdiGetBreakExtra:
295 SafeResult = pdcattr->lBreakExtra;
296 break;
297
298 case GdiGerCharBreak:
299 SafeResult = pdcattr->cBreak;
300 break;
301
302 case GdiGetArcDirection:
303 if (pdcattr->dwLayout & LAYOUT_RTL)
304 SafeResult = AD_CLOCKWISE - ((pdc->dclevel.flPath & DCPATH_CLOCKWISE) != 0);
305 else
306 SafeResult = ((pdc->dclevel.flPath & DCPATH_CLOCKWISE) != 0) + AD_COUNTERCLOCKWISE;
307 break;
308
309 case GdiGetEMFRestorDc:
310 break;
311
312 case GdiGetFontLanguageInfo:
313 SafeResult = IntGetFontLanguageInfo(pdc);
314 break;
315
316 case GdiGetIsMemDc:
317 SafeResult = pdc->dctype;
318 break;
319
320 case GdiGetMapMode:
321 SafeResult = pdcattr->iMapMode;
322 break;
323
324 case GdiGetTextCharExtra:
325 SafeResult = pdcattr->lTextExtra;
326 break;
327
328 default:
329 EngSetLastError(ERROR_INVALID_PARAMETER);
330 Ret = FALSE;
331 break;
332 }
333
334 if (Ret)
335 {
336 _SEH2_TRY
337 {
338 ProbeForWrite(Result, sizeof(DWORD), 1);
339 *Result = SafeResult;
340 }
341 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
342 {
343 Status = _SEH2_GetExceptionCode();
344 }
345 _SEH2_END;
346
347 if (!NT_SUCCESS(Status))
348 {
349 SetLastNtError(Status);
350 Ret = FALSE;
351 }
352 }
353
354 DC_UnlockDc(pdc);
355 return Ret;
356 }
357
358 _Success_(return != FALSE)
359 BOOL
360 APIENTRY
361 NtGdiGetAndSetDCDword(
362 _In_ HDC hdc,
363 _In_ UINT u,
364 _In_ DWORD dwIn,
365 _Out_ DWORD *pdwResult)
366 {
367 BOOL Ret = TRUE;
368 PDC pdc;
369 PDC_ATTR pdcattr;
370
371 DWORD SafeResult = 0;
372 NTSTATUS Status = STATUS_SUCCESS;
373
374 if (!pdwResult)
375 {
376 EngSetLastError(ERROR_INVALID_PARAMETER);
377 return FALSE;
378 }
379
380 pdc = DC_LockDc(hdc);
381 if (!pdc)
382 {
383 EngSetLastError(ERROR_INVALID_HANDLE);
384 return FALSE;
385 }
386 pdcattr = pdc->pdcattr;
387
388 switch (u)
389 {
390 case GdiGetSetCopyCount:
391 SafeResult = pdc->ulCopyCount;
392 pdc->ulCopyCount = dwIn;
393 break;
394
395 case GdiGetSetTextAlign:
396 SafeResult = pdcattr->lTextAlign;
397 pdcattr->lTextAlign = dwIn;
398 // pdcattr->flTextAlign = dwIn; // Flags!
399 break;
400
401 case GdiGetSetRelAbs:
402 SafeResult = pdcattr->lRelAbs;
403 pdcattr->lRelAbs = dwIn;
404 break;
405
406 case GdiGetSetTextCharExtra:
407 SafeResult = pdcattr->lTextExtra;
408 pdcattr->lTextExtra = dwIn;
409 break;
410
411 case GdiGetSetSelectFont:
412 break;
413
414 case GdiGetSetMapperFlagsInternal:
415 if (dwIn & ~1)
416 {
417 EngSetLastError(ERROR_INVALID_PARAMETER);
418 Ret = FALSE;
419 break;
420 }
421 SafeResult = pdcattr->flFontMapper;
422 pdcattr->flFontMapper = dwIn;
423 break;
424
425 case GdiGetSetMapMode:
426 SafeResult = IntGdiSetMapMode(pdc, dwIn);
427 break;
428
429 case GdiGetSetArcDirection:
430 if (dwIn != AD_COUNTERCLOCKWISE && dwIn != AD_CLOCKWISE)
431 {
432 EngSetLastError(ERROR_INVALID_PARAMETER);
433 Ret = FALSE;
434 break;
435 }
436 if (pdcattr->dwLayout & LAYOUT_RTL) // Right to Left
437 {
438 SafeResult = AD_CLOCKWISE - ((pdc->dclevel.flPath & DCPATH_CLOCKWISE) != 0);
439 if (dwIn == AD_CLOCKWISE)
440 {
441 pdc->dclevel.flPath &= ~DCPATH_CLOCKWISE;
442 break;
443 }
444 pdc->dclevel.flPath |= DCPATH_CLOCKWISE;
445 }
446 else // Left to Right
447 {
448 SafeResult = ((pdc->dclevel.flPath & DCPATH_CLOCKWISE) != 0) +
449 AD_COUNTERCLOCKWISE;
450 if (dwIn == AD_COUNTERCLOCKWISE)
451 {
452 pdc->dclevel.flPath &= ~DCPATH_CLOCKWISE;
453 break;
454 }
455 pdc->dclevel.flPath |= DCPATH_CLOCKWISE;
456 }
457 break;
458
459 default:
460 EngSetLastError(ERROR_INVALID_PARAMETER);
461 Ret = FALSE;
462 break;
463 }
464
465 if (Ret)
466 {
467 _SEH2_TRY
468 {
469 ProbeForWrite(pdwResult, sizeof(DWORD), 1);
470 *pdwResult = SafeResult;
471 }
472 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
473 {
474 Status = _SEH2_GetExceptionCode();
475 }
476 _SEH2_END;
477
478 if (!NT_SUCCESS(Status))
479 {
480 SetLastNtError(Status);
481 Ret = FALSE;
482 }
483 }
484
485 DC_UnlockDc(pdc);
486 return Ret;
487 }
488
489 DWORD
490 APIENTRY
491 NtGdiGetBoundsRect(
492 IN HDC hdc,
493 OUT LPRECT prc,
494 IN DWORD flags)
495 {
496 DWORD ret;
497 PDC pdc;
498
499 /* Lock the DC */
500 if (!(pdc = DC_LockDc(hdc))) return 0;
501
502 /* Get the return value */
503 ret = pdc->fs & DC_ACCUM_APP ? DCB_ENABLE : DCB_DISABLE;
504 ret |= RECTL_bIsEmptyRect(&pdc->erclBoundsApp) ? DCB_RESET : DCB_SET;
505
506 /* Copy the rect to the caller */
507 _SEH2_TRY
508 {
509 ProbeForWrite(prc, sizeof(RECT), 1);
510 *prc = pdc->erclBoundsApp;
511 }
512 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
513 {
514 ret = 0;
515 }
516 _SEH2_END;
517
518 if (flags & DCB_RESET)
519 {
520 RECTL_vSetEmptyRect(&pdc->erclBoundsApp);
521 }
522
523 DC_UnlockDc(pdc);
524 return ret;
525 }
526
527
528 DWORD
529 APIENTRY
530 NtGdiSetBoundsRect(
531 IN HDC hdc,
532 IN LPRECT prc,
533 IN DWORD flags)
534 {
535 DWORD ret;
536 PDC pdc;
537 RECTL rcl;
538
539 /* Verify arguments */
540 if ((flags & DCB_ENABLE) && (flags & DCB_DISABLE)) return 0;
541
542 /* Lock the DC */
543 if (!(pdc = DC_LockDc(hdc))) return 0;
544
545 /* Get the return value */
546 ret = pdc->fs & DC_ACCUM_APP ? DCB_ENABLE : DCB_DISABLE;
547 ret |= RECTL_bIsEmptyRect(&pdc->erclBoundsApp) ? DCB_RESET : DCB_SET;
548
549 if (flags & DCB_RESET)
550 {
551 RECTL_vSetEmptyRect(&pdc->erclBoundsApp);
552 }
553
554 if (flags & DCB_ACCUMULATE)
555 {
556 /* Capture the rect */
557 _SEH2_TRY
558 {
559 ProbeForRead(prc, sizeof(RECT), 1);
560 rcl = *prc;
561 }
562 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
563 {
564 DC_UnlockDc(pdc);
565 _SEH2_YIELD(return 0;)
566 }
567 _SEH2_END;
568
569 RECTL_vMakeWellOrdered(&rcl);
570 RECTL_bUnionRect(&pdc->erclBoundsApp, &pdc->erclBoundsApp, &rcl);
571 }
572
573 if (flags & DCB_ENABLE) pdc->fs |= DC_ACCUM_APP;
574 if (flags & DCB_DISABLE) pdc->fs &= ~DC_ACCUM_APP;
575 DC_UnlockDc(pdc);
576 return ret;
577 }
578
579 /* Translates a COLORREF to the right color in the specified DC color space */
580 ULONG
581 TranslateCOLORREF(PDC pdc, COLORREF crColor)
582 {
583 PSURFACE psurfDC;
584 PPALETTE ppalDC;
585 ULONG index, ulColor, iBitmapFormat;
586 EXLATEOBJ exlo;
587
588 /* Get the DC surface */
589 psurfDC = pdc->dclevel.pSurface;
590
591 /* If no surface is selected, use the default bitmap */
592 if (!psurfDC)
593 psurfDC = psurfDefaultBitmap;
594
595 /* Check what color type this is */
596 switch (crColor >> 24)
597 {
598 case 0x00: /* RGB color */
599 break;
600
601 case 0x01: /* PALETTEINDEX */
602 index = crColor & 0xFFFFFF;
603 ppalDC = pdc->dclevel.ppal;
604 if (index >= ppalDC->NumColors) index = 0;
605
606 /* Get the RGB value */
607 crColor = PALETTE_ulGetRGBColorFromIndex(ppalDC, index);
608 break;
609
610 case 0x02: /* PALETTERGB */
611
612 if (pdc->dclevel.hpal != StockObjects[DEFAULT_PALETTE])
613 {
614 /* First find the nearest index in the dc palette */
615 ppalDC = pdc->dclevel.ppal;
616 index = PALETTE_ulGetNearestIndex(ppalDC, crColor & 0xFFFFFF);
617
618 /* Get the RGB value */
619 crColor = PALETTE_ulGetRGBColorFromIndex(ppalDC, index);
620 }
621 else
622 {
623 /* Use the pure color */
624 crColor = crColor & 0x00FFFFFF;
625 }
626 break;
627
628 case 0x10: /* DIBINDEX */
629 /* Mask the value to match the target bpp */
630 iBitmapFormat = psurfDC->SurfObj.iBitmapFormat;
631 if (iBitmapFormat == BMF_1BPP) index = crColor & 0x1;
632 else if (iBitmapFormat == BMF_4BPP) index = crColor & 0xf;
633 else if (iBitmapFormat == BMF_8BPP) index = crColor & 0xFF;
634 else if (iBitmapFormat == BMF_16BPP) index = crColor & 0xFFFF;
635 else index = crColor & 0xFFFFFF;
636 return index;
637
638 default:
639 DPRINT("Unsupported color type %u passed\n", crColor >> 24);
640 crColor &= 0xFFFFFF;
641 }
642
643 /* Initialize an XLATEOBJ from RGB to the target surface */
644 EXLATEOBJ_vInitialize(&exlo, &gpalRGB, psurfDC->ppal, 0xFFFFFF, 0, 0);
645
646 /* Translate the color to the target format */
647 ulColor = XLATEOBJ_iXlate(&exlo.xlo, crColor);
648
649 /* Cleanup the XLATEOBJ */
650 EXLATEOBJ_vCleanup(&exlo);
651
652 return ulColor;
653 }
654
655