Synchronize up to trunk's revision r57756.
[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 BOOL _Success_(return != FALSE)
359 APIENTRY
360 NtGdiGetAndSetDCDword(
361 _In_ HDC hdc,
362 _In_ UINT u,
363 _In_ DWORD dwIn,
364 _Out_ DWORD *pdwResult)
365 {
366 BOOL Ret = TRUE;
367 PDC pdc;
368 PDC_ATTR pdcattr;
369
370 DWORD SafeResult = 0;
371 NTSTATUS Status = STATUS_SUCCESS;
372
373 if (!pdwResult)
374 {
375 EngSetLastError(ERROR_INVALID_PARAMETER);
376 return FALSE;
377 }
378
379 pdc = DC_LockDc(hdc);
380 if (!pdc)
381 {
382 EngSetLastError(ERROR_INVALID_HANDLE);
383 return FALSE;
384 }
385 pdcattr = pdc->pdcattr;
386
387 switch (u)
388 {
389 case GdiGetSetCopyCount:
390 SafeResult = pdc->ulCopyCount;
391 pdc->ulCopyCount = dwIn;
392 break;
393
394 case GdiGetSetTextAlign:
395 SafeResult = pdcattr->lTextAlign;
396 pdcattr->lTextAlign = dwIn;
397 // pdcattr->flTextAlign = dwIn; // Flags!
398 break;
399
400 case GdiGetSetRelAbs:
401 SafeResult = pdcattr->lRelAbs;
402 pdcattr->lRelAbs = dwIn;
403 break;
404
405 case GdiGetSetTextCharExtra:
406 SafeResult = pdcattr->lTextExtra;
407 pdcattr->lTextExtra = dwIn;
408 break;
409
410 case GdiGetSetSelectFont:
411 break;
412
413 case GdiGetSetMapperFlagsInternal:
414 if (dwIn & ~1)
415 {
416 EngSetLastError(ERROR_INVALID_PARAMETER);
417 Ret = FALSE;
418 break;
419 }
420 SafeResult = pdcattr->flFontMapper;
421 pdcattr->flFontMapper = dwIn;
422 break;
423
424 case GdiGetSetMapMode:
425 SafeResult = IntGdiSetMapMode(pdc, dwIn);
426 break;
427
428 case GdiGetSetArcDirection:
429 if (dwIn != AD_COUNTERCLOCKWISE && dwIn != AD_CLOCKWISE)
430 {
431 EngSetLastError(ERROR_INVALID_PARAMETER);
432 Ret = FALSE;
433 break;
434 }
435 if (pdcattr->dwLayout & LAYOUT_RTL) // Right to Left
436 {
437 SafeResult = AD_CLOCKWISE - ((pdc->dclevel.flPath & DCPATH_CLOCKWISE) != 0);
438 if (dwIn == AD_CLOCKWISE)
439 {
440 pdc->dclevel.flPath &= ~DCPATH_CLOCKWISE;
441 break;
442 }
443 pdc->dclevel.flPath |= DCPATH_CLOCKWISE;
444 }
445 else // Left to Right
446 {
447 SafeResult = ((pdc->dclevel.flPath & DCPATH_CLOCKWISE) != 0) +
448 AD_COUNTERCLOCKWISE;
449 if (dwIn == AD_COUNTERCLOCKWISE)
450 {
451 pdc->dclevel.flPath &= ~DCPATH_CLOCKWISE;
452 break;
453 }
454 pdc->dclevel.flPath |= DCPATH_CLOCKWISE;
455 }
456 break;
457
458 default:
459 EngSetLastError(ERROR_INVALID_PARAMETER);
460 Ret = FALSE;
461 break;
462 }
463
464 if (Ret)
465 {
466 _SEH2_TRY
467 {
468 ProbeForWrite(pdwResult, sizeof(DWORD), 1);
469 *pdwResult = SafeResult;
470 }
471 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
472 {
473 Status = _SEH2_GetExceptionCode();
474 }
475 _SEH2_END;
476
477 if (!NT_SUCCESS(Status))
478 {
479 SetLastNtError(Status);
480 Ret = FALSE;
481 }
482 }
483
484 DC_UnlockDc(pdc);
485 return Ret;
486 }
487
488 DWORD
489 APIENTRY
490 NtGdiGetBoundsRect(
491 IN HDC hdc,
492 OUT LPRECT prc,
493 IN DWORD flags)
494 {
495 DWORD ret;
496 PDC pdc;
497
498 /* Lock the DC */
499 if (!(pdc = DC_LockDc(hdc))) return 0;
500
501 /* Get the return value */
502 ret = pdc->fs & DC_ACCUM_APP ? DCB_ENABLE : DCB_DISABLE;
503 ret |= RECTL_bIsEmptyRect(&pdc->erclBoundsApp) ? DCB_RESET : DCB_SET;
504
505 /* Copy the rect to the caller */
506 _SEH2_TRY
507 {
508 ProbeForWrite(prc, sizeof(RECT), 1);
509 *prc = pdc->erclBoundsApp;
510 }
511 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
512 {
513 ret = 0;
514 }
515 _SEH2_END;
516
517 if (flags & DCB_RESET)
518 {
519 RECTL_vSetEmptyRect(&pdc->erclBoundsApp);
520 }
521
522 DC_UnlockDc(pdc);
523 return ret;
524 }
525
526
527 DWORD
528 APIENTRY
529 NtGdiSetBoundsRect(
530 IN HDC hdc,
531 IN LPRECT prc,
532 IN DWORD flags)
533 {
534 DWORD ret;
535 PDC pdc;
536 RECTL rcl;
537
538 /* Verify arguments */
539 if ((flags & DCB_ENABLE) && (flags & DCB_DISABLE)) return 0;
540
541 /* Lock the DC */
542 if (!(pdc = DC_LockDc(hdc))) return 0;
543
544 /* Get the return value */
545 ret = pdc->fs & DC_ACCUM_APP ? DCB_ENABLE : DCB_DISABLE;
546 ret |= RECTL_bIsEmptyRect(&pdc->erclBoundsApp) ? DCB_RESET : DCB_SET;
547
548 if (flags & DCB_RESET)
549 {
550 RECTL_vSetEmptyRect(&pdc->erclBoundsApp);
551 }
552
553 if (flags & DCB_ACCUMULATE)
554 {
555 /* Capture the rect */
556 _SEH2_TRY
557 {
558 ProbeForRead(prc, sizeof(RECT), 1);
559 rcl = *prc;
560 }
561 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
562 {
563 DC_UnlockDc(pdc);
564 _SEH2_YIELD(return 0;)
565 }
566 _SEH2_END;
567
568 RECTL_vMakeWellOrdered(&rcl);
569 RECTL_bUnionRect(&pdc->erclBoundsApp, &pdc->erclBoundsApp, &rcl);
570 }
571
572 if (flags & DCB_ENABLE) pdc->fs |= DC_ACCUM_APP;
573 if (flags & DCB_DISABLE) pdc->fs &= ~DC_ACCUM_APP;
574 DC_UnlockDc(pdc);
575 return ret;
576 }
577
578 /* Translates a COLORREF to the right color in the specified DC color space */
579 ULONG
580 TranslateCOLORREF(PDC pdc, COLORREF crColor)
581 {
582 PSURFACE psurfDC;
583 PPALETTE ppalDC;
584 ULONG index, ulColor, iBitmapFormat;
585 EXLATEOBJ exlo;
586
587 /* Get the DC surface */
588 psurfDC = pdc->dclevel.pSurface;
589
590 /* If no surface is selected, use the default bitmap */
591 if (!psurfDC)
592 psurfDC = psurfDefaultBitmap;
593
594 /* Check what color type this is */
595 switch (crColor >> 24)
596 {
597 case 0x00: /* RGB color */
598 break;
599
600 case 0x01: /* PALETTEINDEX */
601 index = crColor & 0xFFFFFF;
602 ppalDC = pdc->dclevel.ppal;
603 if (index >= ppalDC->NumColors) index = 0;
604
605 /* Get the RGB value */
606 crColor = PALETTE_ulGetRGBColorFromIndex(ppalDC, index);
607 break;
608
609 case 0x02: /* PALETTERGB */
610
611 if (pdc->dclevel.hpal != StockObjects[DEFAULT_PALETTE])
612 {
613 /* First find the nearest index in the dc palette */
614 ppalDC = pdc->dclevel.ppal;
615 index = PALETTE_ulGetNearestIndex(ppalDC, crColor & 0xFFFFFF);
616
617 /* Get the RGB value */
618 crColor = PALETTE_ulGetRGBColorFromIndex(ppalDC, index);
619 }
620 else
621 {
622 /* Use the pure color */
623 crColor = crColor & 0x00FFFFFF;
624 }
625 break;
626
627 case 0x10: /* DIBINDEX */
628 /* Mask the value to match the target bpp */
629 iBitmapFormat = psurfDC->SurfObj.iBitmapFormat;
630 if (iBitmapFormat == BMF_1BPP) index = crColor & 0x1;
631 else if (iBitmapFormat == BMF_4BPP) index = crColor & 0xf;
632 else if (iBitmapFormat == BMF_8BPP) index = crColor & 0xFF;
633 else if (iBitmapFormat == BMF_16BPP) index = crColor & 0xFFFF;
634 else index = crColor & 0xFFFFFF;
635 return index;
636
637 default:
638 DPRINT("Unsupported color type %u passed\n", crColor >> 24);
639 crColor &= 0xFFFFFF;
640 }
641
642 /* Initialize an XLATEOBJ from RGB to the target surface */
643 EXLATEOBJ_vInitialize(&exlo, &gpalRGB, psurfDC->ppal, 0xFFFFFF, 0, 0);
644
645 /* Translate the color to the target format */
646 ulColor = XLATEOBJ_iXlate(&exlo.xlo, crColor);
647
648 /* Cleanup the XLATEOBJ */
649 EXLATEOBJ_vCleanup(&exlo);
650
651 return ulColor;
652 }
653
654