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