rename DC.Dc_attr to dcattr, DC.DcLevel to dclevel, just like in gdikdx. Some naming...
[reactos.git] / reactos / subsystems / win32 / win32k / objects / coord.c
1 /*
2 * ReactOS W32 Subsystem
3 * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003 ReactOS Team
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18 */
19 /*
20 *
21 * COPYRIGHT: See COPYING in the top level directory
22 * PROJECT: ReactOS kernel
23 * PURPOSE: Coordinate systems
24 * FILE: subsys/win32k/objects/coord.c
25 * PROGRAMER: Unknown
26 */
27
28 /* INCLUDES ******************************************************************/
29
30 #include <w32k.h>
31
32 #define NDEBUG
33 #include <debug.h>
34
35 /* FUNCTIONS *****************************************************************/
36
37 void FASTCALL
38 IntFixIsotropicMapping(PDC dc)
39 {
40 PDC_ATTR pdcattr;
41 LONG fx, fy, s;
42
43 /* Get a pointer to the DC_ATTR */
44 pdcattr = dc->pdcattr;
45
46 /* Check if all values are valid */
47 if (pdcattr->szlWindowExt.cx == 0 || pdcattr->szlWindowExt.cy == 0 ||
48 pdcattr->szlViewportExt.cx == 0 || pdcattr->szlViewportExt.cy == 0)
49 {
50 /* Don't recalculate */
51 return;
52 }
53
54 fx = abs(pdcattr->szlWindowExt.cx * pdcattr->szlViewportExt.cy);
55 fy = abs(pdcattr->szlWindowExt.cy * pdcattr->szlViewportExt.cx);
56
57 if (fy > fx)
58 {
59 s = pdcattr->szlWindowExt.cy * pdcattr->szlViewportExt.cx > 0 ? 1 : -1;
60 pdcattr->szlViewportExt.cx = s * fx / pdcattr->szlWindowExt.cy;
61 }
62 else if (fx > fy)
63 {
64 s = pdcattr->szlWindowExt.cx * pdcattr->szlViewportExt.cy > 0 ? 1 : -1;
65 pdcattr->szlViewportExt.cy = s * fy / pdcattr->szlWindowExt.cx;
66 }
67 }
68
69 BOOL FASTCALL
70 IntGdiCombineTransform(LPXFORM XFormResult,
71 LPXFORM xform1,
72 LPXFORM xform2)
73 {
74 XFORM xformTemp;
75 /* Check for illegal parameters */
76 if (!XFormResult || !xform1 || !xform2)
77 {
78 return FALSE;
79 }
80
81 /* Create the result in a temporary XFORM, since xformResult may be
82 * equal to xform1 or xform2 */
83 xformTemp.eM11 = xform1->eM11 * xform2->eM11 + xform1->eM12 * xform2->eM21;
84 xformTemp.eM12 = xform1->eM11 * xform2->eM12 + xform1->eM12 * xform2->eM22;
85 xformTemp.eM21 = xform1->eM21 * xform2->eM11 + xform1->eM22 * xform2->eM21;
86 xformTemp.eM22 = xform1->eM21 * xform2->eM12 + xform1->eM22 * xform2->eM22;
87 xformTemp.eDx = xform1->eDx * xform2->eM11 + xform1->eDy * xform2->eM21 + xform2->eDx;
88 xformTemp.eDy = xform1->eDx * xform2->eM12 + xform1->eDy * xform2->eM22 + xform2->eDy;
89 *XFormResult = xformTemp;
90
91 return TRUE;
92 }
93
94 BOOL APIENTRY NtGdiCombineTransform(LPXFORM UnsafeXFormResult,
95 LPXFORM Unsafexform1,
96 LPXFORM Unsafexform2)
97 {
98 BOOL Ret;
99
100 _SEH2_TRY
101 {
102 ProbeForWrite(UnsafeXFormResult, sizeof(XFORM), 1);
103 ProbeForRead(Unsafexform1, sizeof(XFORM), 1);
104 ProbeForRead(Unsafexform2, sizeof(XFORM), 1);
105 Ret = IntGdiCombineTransform(UnsafeXFormResult,
106 Unsafexform1,
107 Unsafexform2);
108 }
109 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
110 {
111 Ret = FALSE;
112 }
113 _SEH2_END;
114
115 return Ret;
116 }
117
118
119 int
120 FASTCALL
121 IntGetGraphicsMode(PDC dc)
122 {
123 PDC_ATTR pdcattr;
124 ASSERT(dc);
125 pdcattr = dc->pdcattr;
126 return pdcattr->iGraphicsMode;
127 }
128
129 BOOL
130 FASTCALL
131 IntGdiModifyWorldTransform(PDC pDc,
132 CONST LPXFORM lpXForm,
133 DWORD Mode)
134 {
135 ASSERT(pDc);
136 XFORM xformWorld2Wnd;
137
138 switch (Mode)
139 {
140 case MWT_IDENTITY:
141 xformWorld2Wnd.eM11 = 1.0f;
142 xformWorld2Wnd.eM12 = 0.0f;
143 xformWorld2Wnd.eM21 = 0.0f;
144 xformWorld2Wnd.eM22 = 1.0f;
145 xformWorld2Wnd.eDx = 0.0f;
146 xformWorld2Wnd.eDy = 0.0f;
147 XForm2MatrixS(&pDc->dclevel.mxWorldToPage, &xformWorld2Wnd);
148 break;
149
150 case MWT_LEFTMULTIPLY:
151 MatrixS2XForm(&xformWorld2Wnd, &pDc->dclevel.mxWorldToPage);
152 IntGdiCombineTransform(&xformWorld2Wnd, lpXForm, &xformWorld2Wnd);
153 XForm2MatrixS(&pDc->dclevel.mxWorldToPage, &xformWorld2Wnd);
154 break;
155
156 case MWT_RIGHTMULTIPLY:
157 MatrixS2XForm(&xformWorld2Wnd, &pDc->dclevel.mxWorldToPage);
158 IntGdiCombineTransform(&xformWorld2Wnd, &xformWorld2Wnd, lpXForm);
159 XForm2MatrixS(&pDc->dclevel.mxWorldToPage, &xformWorld2Wnd);
160 break;
161
162 case MWT_MAX+1: // Must be MWT_SET????
163 XForm2MatrixS(&pDc->dclevel.mxWorldToPage, lpXForm); // Do it like Wine.
164 break;
165
166 default:
167 return FALSE;
168 }
169 DC_UpdateXforms(pDc);
170 return TRUE;
171 }
172
173 BOOL
174 APIENTRY
175 NtGdiGetTransform(HDC hDC,
176 DWORD iXform,
177 LPXFORM XForm)
178 {
179 PDC dc;
180 NTSTATUS Status = STATUS_SUCCESS;
181
182 dc = DC_LockDc(hDC);
183 if (!dc)
184 {
185 SetLastWin32Error(ERROR_INVALID_HANDLE);
186 return FALSE;
187 }
188 if (!XForm)
189 {
190 DC_UnlockDc(dc);
191 SetLastWin32Error(ERROR_INVALID_PARAMETER);
192 return FALSE;
193 }
194
195 _SEH2_TRY
196 {
197 ProbeForWrite(XForm, sizeof(XFORM), 1);
198 switch (iXform)
199 {
200 case GdiWorldSpaceToPageSpace:
201 MatrixS2XForm(XForm, &dc->dclevel.mxWorldToPage);
202 break;
203 default:
204 break;
205 }
206 }
207 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
208 {
209 Status = _SEH2_GetExceptionCode();
210 }
211 _SEH2_END;
212
213 DC_UnlockDc(dc);
214 return NT_SUCCESS(Status);
215 }
216
217
218 /*!
219 * Converts points from logical coordinates into device coordinates. Conversion depends on the mapping mode,
220 * world transfrom, viewport origin settings for the given device context.
221 * \param hDC device context.
222 * \param Points an array of POINT structures (in/out).
223 * \param Count number of elements in the array of POINT structures.
224 * \return TRUE if success.
225 */
226 BOOL
227 APIENTRY
228 NtGdiTransformPoints(HDC hDC,
229 PPOINT UnsafePtsIn,
230 PPOINT UnsafePtOut,
231 INT Count,
232 INT iMode)
233 {
234 PDC dc;
235 NTSTATUS Status = STATUS_SUCCESS;
236 LPPOINT Points;
237 ULONG Size;
238
239 dc = DC_LockDc(hDC);
240 if (!dc)
241 {
242 SetLastWin32Error(ERROR_INVALID_HANDLE);
243 return FALSE;
244 }
245
246 if (!UnsafePtsIn || !UnsafePtOut || Count <= 0)
247 {
248 DC_UnlockDc(dc);
249 SetLastWin32Error(ERROR_INVALID_PARAMETER);
250 return FALSE;
251 }
252
253 Size = Count * sizeof(POINT);
254
255 Points = (LPPOINT)ExAllocatePoolWithTag(PagedPool, Size, TAG_COORD);
256 if (!Points)
257 {
258 DC_UnlockDc(dc);
259 SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY);
260 return FALSE;
261 }
262
263 _SEH2_TRY
264 {
265 ProbeForWrite(UnsafePtOut, Size, 1);
266 ProbeForRead(UnsafePtsIn, Size, 1);
267 RtlCopyMemory(Points, UnsafePtsIn, Size);
268 }
269 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
270 {
271 Status = _SEH2_GetExceptionCode();
272 }
273 _SEH2_END;
274
275 if (!NT_SUCCESS(Status))
276 {
277 DC_UnlockDc(dc);
278 ExFreePoolWithTag(Points, TAG_COORD);
279 SetLastNtError(Status);
280 return FALSE;
281 }
282
283 switch (iMode)
284 {
285 case GdiDpToLp:
286 IntDPtoLP(dc, Points, Count);
287 break;
288 case GdiLpToDp:
289 IntLPtoDP(dc, Points, Count);
290 break;
291 case 2: // Not supported yet. Need testing.
292 default:
293 {
294 DC_UnlockDc(dc);
295 ExFreePoolWithTag(Points, TAG_COORD);
296 SetLastWin32Error(ERROR_INVALID_PARAMETER);
297 return FALSE;
298 }
299 }
300
301 _SEH2_TRY
302 {
303 /* pointer was already probed! */
304 RtlCopyMemory(UnsafePtOut, Points, Size);
305 }
306 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
307 {
308 Status = _SEH2_GetExceptionCode();
309 }
310 _SEH2_END;
311
312 if (!NT_SUCCESS(Status))
313 {
314 DC_UnlockDc(dc);
315 ExFreePoolWithTag(Points, TAG_COORD);
316 SetLastNtError(Status);
317 return FALSE;
318 }
319 //
320 // If we are getting called that means User XForms is a mess!
321 //
322 DC_UnlockDc(dc);
323 ExFreePoolWithTag(Points, TAG_COORD);
324 return TRUE;
325 }
326
327 BOOL
328 APIENTRY
329 NtGdiModifyWorldTransform(HDC hDC,
330 LPXFORM UnsafeXForm,
331 DWORD Mode)
332 {
333 PDC dc;
334 XFORM SafeXForm;
335 BOOL Ret = TRUE;
336
337 dc = DC_LockDc(hDC);
338 if (!dc)
339 {
340 SetLastWin32Error(ERROR_INVALID_HANDLE);
341 return FALSE;
342 }
343
344 // The xform is permitted to be NULL for MWT_IDENTITY.
345 // However, if it is not NULL, then it must be valid even though it is not used.
346 if (UnsafeXForm != NULL || Mode != MWT_IDENTITY)
347 {
348 _SEH2_TRY
349 {
350 ProbeForRead(UnsafeXForm, sizeof(XFORM), 1);
351 RtlCopyMemory(&SafeXForm, UnsafeXForm, sizeof(XFORM));
352 }
353 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
354 {
355 Ret = FALSE;
356 }
357 _SEH2_END;
358 }
359
360 // Safe to handle kernel mode data.
361 if (Ret) Ret = IntGdiModifyWorldTransform(dc, &SafeXForm, Mode);
362 DC_UnlockDc(dc);
363 return Ret;
364 }
365
366 BOOL
367 APIENTRY
368 NtGdiOffsetViewportOrgEx(HDC hDC,
369 int XOffset,
370 int YOffset,
371 LPPOINT UnsafePoint)
372 {
373 PDC dc;
374 PDC_ATTR pdcattr;
375 NTSTATUS Status = STATUS_SUCCESS;
376
377 dc = DC_LockDc(hDC);
378 if (!dc)
379 {
380 SetLastWin32Error(ERROR_INVALID_HANDLE);
381 return FALSE;
382 }
383 pdcattr = dc->pdcattr;
384
385 if (UnsafePoint)
386 {
387 _SEH2_TRY
388 {
389 ProbeForWrite(UnsafePoint, sizeof(POINT), 1);
390 UnsafePoint->x = pdcattr->ptlViewportOrg.x;
391 UnsafePoint->y = pdcattr->ptlViewportOrg.y;
392 if (pdcattr->dwLayout & LAYOUT_RTL)
393 {
394 UnsafePoint->x = -UnsafePoint->x;
395 }
396 }
397 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
398 {
399 Status = _SEH2_GetExceptionCode();
400 }
401 _SEH2_END;
402
403 if (!NT_SUCCESS(Status))
404 {
405 SetLastNtError(Status);
406 DC_UnlockDc(dc);
407 return FALSE;
408 }
409 }
410
411 if (pdcattr->dwLayout & LAYOUT_RTL)
412 {
413 XOffset = -XOffset;
414 }
415 pdcattr->ptlViewportOrg.x += XOffset;
416 pdcattr->ptlViewportOrg.y += YOffset;
417 DC_UpdateXforms(dc);
418 DC_UnlockDc(dc);
419
420 return TRUE;
421 }
422
423 BOOL
424 APIENTRY
425 NtGdiOffsetWindowOrgEx(HDC hDC,
426 int XOffset,
427 int YOffset,
428 LPPOINT Point)
429 {
430 PDC dc;
431 PDC_ATTR pdcattr;
432
433 dc = DC_LockDc(hDC);
434 if (!dc)
435 {
436 SetLastWin32Error(ERROR_INVALID_HANDLE);
437 return FALSE;
438 }
439 pdcattr = dc->pdcattr;
440
441 if (Point)
442 {
443 NTSTATUS Status = STATUS_SUCCESS;
444
445 _SEH2_TRY
446 {
447 ProbeForWrite(Point, sizeof(POINT), 1);
448 Point->x = pdcattr->ptlWindowOrg.x;
449 Point->y = pdcattr->ptlWindowOrg.y;
450 }
451 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
452 {
453 Status = _SEH2_GetExceptionCode();
454 }
455 _SEH2_END;
456
457 if (!NT_SUCCESS(Status))
458 {
459 SetLastNtError(Status);
460 DC_UnlockDc(dc);
461 return FALSE;
462 }
463 }
464
465 pdcattr->ptlWindowOrg.x += XOffset;
466 pdcattr->ptlWindowOrg.y += YOffset;
467
468 DC_UpdateXforms(dc);
469 DC_UnlockDc(dc);
470
471 return TRUE;
472 }
473
474 BOOL
475 APIENTRY
476 NtGdiScaleViewportExtEx(HDC hDC,
477 int Xnum,
478 int Xdenom,
479 int Ynum,
480 int Ydenom,
481 LPSIZE pSize)
482 {
483 PDC pDC;
484 PDC_ATTR pdcattr;
485 BOOL Ret = FALSE;
486 LONG X, Y;
487
488 pDC = DC_LockDc(hDC);
489 if (!pDC)
490 {
491 SetLastWin32Error(ERROR_INVALID_HANDLE);
492 return FALSE;
493 }
494 pdcattr = pDC->pdcattr;
495
496 if (pSize)
497 {
498 NTSTATUS Status = STATUS_SUCCESS;
499
500 _SEH2_TRY
501 {
502 ProbeForWrite(pSize, sizeof(LPSIZE), 1);
503
504 pSize->cx = pdcattr->szlViewportExt.cx;
505 pSize->cy = pdcattr->szlViewportExt.cy;
506 }
507 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
508 {
509 Status = _SEH2_GetExceptionCode();
510 }
511 _SEH2_END;
512
513 if (!NT_SUCCESS(Status))
514 {
515 SetLastNtError(Status);
516 DC_UnlockDc(pDC);
517 return FALSE;
518 }
519 }
520
521 if (pdcattr->iMapMode > MM_TWIPS)
522 {
523 if (Xdenom && Ydenom)
524 {
525 X = Xnum * pdcattr->szlViewportExt.cx / Xdenom;
526 if (X)
527 {
528 Y = Ynum * pdcattr->szlViewportExt.cy / Ydenom;
529 if (Y)
530 {
531 pdcattr->szlViewportExt.cx = X;
532 pdcattr->szlViewportExt.cy = Y;
533
534 IntMirrorWindowOrg(pDC);
535
536 pdcattr->flXform |= (PAGE_EXTENTS_CHANGED |
537 INVALIDATE_ATTRIBUTES |
538 DEVICE_TO_WORLD_INVALID);
539
540 if (pdcattr->iMapMode == MM_ISOTROPIC)
541 {
542 IntFixIsotropicMapping(pDC);
543 }
544 DC_UpdateXforms(pDC);
545
546 Ret = TRUE;
547 }
548 }
549 }
550 }
551 else
552 Ret = TRUE;
553
554 DC_UnlockDc(pDC);
555 return Ret;
556 }
557
558 BOOL
559 APIENTRY
560 NtGdiScaleWindowExtEx(HDC hDC,
561 int Xnum,
562 int Xdenom,
563 int Ynum,
564 int Ydenom,
565 LPSIZE pSize)
566 {
567 PDC pDC;
568 PDC_ATTR pdcattr;
569 BOOL Ret = FALSE;
570 LONG X, Y;
571
572 pDC = DC_LockDc(hDC);
573 if (!pDC)
574 {
575 SetLastWin32Error(ERROR_INVALID_HANDLE);
576 return FALSE;
577 }
578 pdcattr = pDC->pdcattr;
579
580 if (pSize)
581 {
582 NTSTATUS Status = STATUS_SUCCESS;
583
584 _SEH2_TRY
585 {
586 ProbeForWrite(pSize, sizeof(LPSIZE), 1);
587
588 X = pdcattr->szlWindowExt.cx;
589 if (pdcattr->dwLayout & LAYOUT_RTL) X = -X;
590 pSize->cx = X;
591 pSize->cy = pdcattr->szlWindowExt.cy;
592 }
593 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
594 {
595 Status = _SEH2_GetExceptionCode();
596 }
597 _SEH2_END;
598
599 if (!NT_SUCCESS(Status))
600 {
601 SetLastNtError(Status);
602 DC_UnlockDc(pDC);
603 return FALSE;
604 }
605 }
606
607 if (pdcattr->iMapMode > MM_TWIPS)
608 {
609 if (Xdenom && Ydenom)
610 {
611 X = Xnum * pdcattr->szlWindowExt.cx / Xdenom;
612 if (X)
613 {
614 Y = Ynum * pdcattr->szlWindowExt.cy / Ydenom;
615 if (Y)
616 {
617 pdcattr->szlWindowExt.cx = X;
618 pdcattr->szlWindowExt.cy = Y;
619
620 IntMirrorWindowOrg(pDC);
621
622 pdcattr->flXform |= (PAGE_EXTENTS_CHANGED|INVALIDATE_ATTRIBUTES|DEVICE_TO_WORLD_INVALID);
623
624 if (pdcattr->iMapMode == MM_ISOTROPIC) IntFixIsotropicMapping(pDC);
625 DC_UpdateXforms(pDC);
626
627 Ret = TRUE;
628 }
629 }
630 }
631 }
632 else
633 Ret = TRUE;
634
635 DC_UnlockDc(pDC);
636 return Ret;
637 }
638
639 int
640 APIENTRY
641 IntGdiSetMapMode(PDC dc,
642 int MapMode)
643 {
644 int PrevMapMode;
645 PDC_ATTR pdcattr = dc->pdcattr;
646
647 PrevMapMode = pdcattr->iMapMode;
648
649 pdcattr->iMapMode = MapMode;
650
651 switch (MapMode)
652 {
653 case MM_TEXT:
654 pdcattr->szlWindowExt.cx = 1;
655 pdcattr->szlWindowExt.cy = 1;
656 pdcattr->szlViewportExt.cx = 1;
657 pdcattr->szlViewportExt.cy = 1;
658 pdcattr->flXform &= ~(ISO_OR_ANISO_MAP_MODE|PTOD_EFM22_NEGATIVE|
659 PTOD_EFM11_NEGATIVE|POSITIVE_Y_IS_UP);
660 pdcattr->flXform |= (PAGE_XLATE_CHANGED|PAGE_TO_DEVICE_SCALE_IDENTITY|
661 INVALIDATE_ATTRIBUTES|DEVICE_TO_WORLD_INVALID);
662 break;
663
664 case MM_ISOTROPIC:
665 pdcattr->flXform |= ISO_OR_ANISO_MAP_MODE;
666 /* Fall through */
667
668 case MM_LOMETRIC:
669 pdcattr->szlWindowExt.cx = 3600;
670 pdcattr->szlWindowExt.cy = 2700;
671 pdcattr->szlViewportExt.cx = ((PGDIDEVICE)dc->ppdev)->GDIInfo.ulHorzRes;
672 pdcattr->szlViewportExt.cy = -((PGDIDEVICE)dc->ppdev)->GDIInfo.ulVertRes;
673 break;
674
675 case MM_HIMETRIC:
676 pdcattr->szlWindowExt.cx = 36000;
677 pdcattr->szlWindowExt.cy = 27000;
678 pdcattr->szlViewportExt.cx = ((PGDIDEVICE)dc->ppdev)->GDIInfo.ulHorzRes;
679 pdcattr->szlViewportExt.cy = -((PGDIDEVICE)dc->ppdev)->GDIInfo.ulVertRes;
680 break;
681
682 case MM_LOENGLISH:
683 pdcattr->szlWindowExt.cx = 1417;
684 pdcattr->szlWindowExt.cy = 1063;
685 pdcattr->szlViewportExt.cx = ((PGDIDEVICE)dc->ppdev)->GDIInfo.ulHorzRes;
686 pdcattr->szlViewportExt.cy = -((PGDIDEVICE)dc->ppdev)->GDIInfo.ulVertRes;
687 break;
688
689 case MM_HIENGLISH:
690 pdcattr->szlWindowExt.cx = 14173;
691 pdcattr->szlWindowExt.cy = 10630;
692 pdcattr->szlViewportExt.cx = ((PGDIDEVICE)dc->ppdev)->GDIInfo.ulHorzRes;
693 pdcattr->szlViewportExt.cy = -((PGDIDEVICE)dc->ppdev)->GDIInfo.ulVertRes;
694 break;
695
696 case MM_TWIPS:
697 pdcattr->szlWindowExt.cx = 20409;
698 pdcattr->szlWindowExt.cy = 15307;
699 pdcattr->szlViewportExt.cx = ((PGDIDEVICE)dc->ppdev)->GDIInfo.ulHorzRes;
700 pdcattr->szlViewportExt.cy = -((PGDIDEVICE)dc->ppdev)->GDIInfo.ulVertRes;
701 break;
702
703 case MM_ANISOTROPIC:
704 pdcattr->flXform &= ~(PAGE_TO_DEVICE_IDENTITY|POSITIVE_Y_IS_UP);
705 pdcattr->flXform |= ISO_OR_ANISO_MAP_MODE;
706 break;
707 default:
708 pdcattr->iMapMode = PrevMapMode;
709 PrevMapMode = 0;
710 }
711 DC_UpdateXforms(dc);
712
713 return PrevMapMode;
714 }
715
716
717 BOOL
718 APIENTRY
719 NtGdiSetViewportOrgEx(HDC hDC,
720 int X,
721 int Y,
722 LPPOINT Point)
723 {
724 PDC dc;
725 PDC_ATTR pdcattr;
726
727 dc = DC_LockDc(hDC);
728 if (!dc)
729 {
730 SetLastWin32Error(ERROR_INVALID_HANDLE);
731 return FALSE;
732 }
733 pdcattr = dc->pdcattr;
734
735 if (Point)
736 {
737 NTSTATUS Status = STATUS_SUCCESS;
738
739 _SEH2_TRY
740 {
741 ProbeForWrite(Point, sizeof(POINT), 1);
742 Point->x = pdcattr->ptlViewportOrg.x;
743 Point->y = pdcattr->ptlViewportOrg.y;
744 }
745 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
746 {
747 Status = _SEH2_GetExceptionCode();
748 }
749 _SEH2_END;
750
751 if (!NT_SUCCESS(Status))
752 {
753 SetLastNtError(Status);
754 DC_UnlockDc(dc);
755 return FALSE;
756 }
757 }
758
759 pdcattr->ptlViewportOrg.x = X;
760 pdcattr->ptlViewportOrg.y = Y;
761
762 DC_UpdateXforms(dc);
763 DC_UnlockDc(dc);
764
765 return TRUE;
766 }
767
768 BOOL
769 APIENTRY
770 NtGdiSetWindowOrgEx(HDC hDC,
771 int X,
772 int Y,
773 LPPOINT Point)
774 {
775 PDC dc;
776 PDC_ATTR pdcattr;
777
778 dc = DC_LockDc(hDC);
779 if (!dc)
780 {
781 SetLastWin32Error(ERROR_INVALID_HANDLE);
782 return FALSE;
783 }
784 pdcattr = dc->pdcattr;
785
786 if (Point)
787 {
788 NTSTATUS Status = STATUS_SUCCESS;
789
790 _SEH2_TRY
791 {
792 ProbeForWrite(Point, sizeof(POINT), 1);
793 Point->x = pdcattr->ptlWindowOrg.x;
794 Point->y = pdcattr->ptlWindowOrg.y;
795 }
796 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
797 {
798 Status = _SEH2_GetExceptionCode();
799 }
800 _SEH2_END;
801
802 if (!NT_SUCCESS(Status))
803 {
804 SetLastNtError(Status);
805 DC_UnlockDc(dc);
806 return FALSE;
807 }
808 }
809
810 pdcattr->ptlWindowOrg.x = X;
811 pdcattr->ptlWindowOrg.y = Y;
812
813 DC_UpdateXforms(dc);
814 DC_UnlockDc(dc);
815
816 return TRUE;
817 }
818
819 //
820 // Mirror Window function.
821 //
822 VOID
823 FASTCALL
824 IntMirrorWindowOrg(PDC dc)
825 {
826 PDC_ATTR pdcattr;
827 LONG X;
828
829 pdcattr = dc->pdcattr;
830
831 if (!(pdcattr->dwLayout & LAYOUT_RTL))
832 {
833 pdcattr->ptlWindowOrg.x = pdcattr->lWindowOrgx; // Flip it back.
834 return;
835 }
836 if (!pdcattr->szlViewportExt.cx) return;
837 //
838 // WOrgx = wox - (Width - 1) * WExtx / VExtx
839 //
840 X = (dc->erclWindow.right - dc->erclWindow.left) - 1; // Get device width - 1
841
842 X = (X * pdcattr->szlWindowExt.cx) / pdcattr->szlViewportExt.cx;
843
844 pdcattr->ptlWindowOrg.x = pdcattr->lWindowOrgx - X; // Now set the inverted win origion.
845
846 return;
847 }
848
849 // NtGdiSetLayout
850 //
851 // The default is left to right. This function changes it to right to left, which
852 // is the standard in Arabic and Hebrew cultures.
853 //
854 /*
855 * @implemented
856 */
857 DWORD
858 APIENTRY
859 NtGdiSetLayout(
860 IN HDC hdc,
861 IN LONG wox,
862 IN DWORD dwLayout)
863 {
864 PDC dc;
865 PDC_ATTR pdcattr;
866 DWORD oLayout;
867
868 dc = DC_LockDc(hdc);
869 if (!dc)
870 {
871 SetLastWin32Error(ERROR_INVALID_HANDLE);
872 return GDI_ERROR;
873 }
874 pdcattr = dc->pdcattr;
875
876 pdcattr->dwLayout = dwLayout;
877 oLayout = pdcattr->dwLayout;
878
879 if (!(dwLayout & LAYOUT_ORIENTATIONMASK))
880 {
881 DC_UnlockDc(dc);
882 return oLayout;
883 }
884
885 if (dwLayout & LAYOUT_RTL)
886 {
887 pdcattr->iMapMode = MM_ANISOTROPIC;
888 }
889
890 pdcattr->szlWindowExt.cy = -pdcattr->szlWindowExt.cy;
891 pdcattr->ptlWindowOrg.x = -pdcattr->ptlWindowOrg.x;
892
893 if (wox == -1)
894 IntMirrorWindowOrg(dc);
895 else
896 pdcattr->ptlWindowOrg.x = wox - pdcattr->ptlWindowOrg.x;
897
898 if (!(pdcattr->flTextAlign & TA_CENTER)) pdcattr->flTextAlign |= TA_RIGHT;
899
900 if (dc->dclevel.flPath & DCPATH_CLOCKWISE)
901 dc->dclevel.flPath &= ~DCPATH_CLOCKWISE;
902 else
903 dc->dclevel.flPath |= DCPATH_CLOCKWISE;
904
905 pdcattr->flXform |= (PAGE_EXTENTS_CHANGED |
906 INVALIDATE_ATTRIBUTES |
907 DEVICE_TO_WORLD_INVALID);
908
909 // DC_UpdateXforms(dc);
910 DC_UnlockDc(dc);
911 return oLayout;
912 }
913
914 /*
915 * @implemented
916 */
917 LONG
918 APIENTRY
919 NtGdiGetDeviceWidth(
920 IN HDC hdc)
921 {
922 PDC dc;
923 LONG Ret;
924 dc = DC_LockDc(hdc);
925 if (!dc)
926 {
927 SetLastWin32Error(ERROR_INVALID_HANDLE);
928 return 0;
929 }
930 Ret = dc->erclWindow.right - dc->erclWindow.left;
931 DC_UnlockDc(dc);
932 return Ret;
933 }
934
935 /*
936 * @implemented
937 */
938 BOOL
939 APIENTRY
940 NtGdiMirrorWindowOrg(
941 IN HDC hdc)
942 {
943 PDC dc;
944 dc = DC_LockDc(hdc);
945 if (!dc)
946 {
947 SetLastWin32Error(ERROR_INVALID_HANDLE);
948 return FALSE;
949 }
950 IntMirrorWindowOrg(dc);
951 DC_UnlockDc(dc);
952 return TRUE;
953 }
954
955 /*
956 * @implemented
957 */
958 BOOL
959 APIENTRY
960 NtGdiSetSizeDevice(
961 IN HDC hdc,
962 IN INT cxVirtualDevice,
963 IN INT cyVirtualDevice)
964 {
965 PDC dc;
966 PDC_ATTR pdcattr;
967
968 if (!cxVirtualDevice || !cyVirtualDevice)
969 {
970 return FALSE;
971 }
972
973 dc = DC_LockDc(hdc);
974 if (!dc) return FALSE;
975
976 pdcattr = dc->pdcattr;
977
978 pdcattr->szlVirtualDeviceSize.cx = cxVirtualDevice;
979 pdcattr->szlVirtualDeviceSize.cy = cyVirtualDevice;
980
981 // DC_UpdateXforms(dc);
982 DC_UnlockDc(dc);
983
984 return TRUE;
985 }
986
987 /*
988 * @implemented
989 */
990 BOOL
991 APIENTRY
992 NtGdiSetVirtualResolution(
993 IN HDC hdc,
994 IN INT cxVirtualDevicePixel,
995 IN INT cyVirtualDevicePixel,
996 IN INT cxVirtualDeviceMm,
997 IN INT cyVirtualDeviceMm)
998 {
999 PDC dc;
1000 PDC_ATTR pdcattr;
1001
1002 // Need test types for zeros and non zeros
1003
1004 dc = DC_LockDc(hdc);
1005 if (!dc) return FALSE;
1006
1007 pdcattr = dc->pdcattr;
1008
1009 pdcattr->szlVirtualDevicePixel.cx = cxVirtualDevicePixel;
1010 pdcattr->szlVirtualDevicePixel.cy = cyVirtualDevicePixel;
1011 pdcattr->szlVirtualDeviceMm.cx = cxVirtualDeviceMm;
1012 pdcattr->szlVirtualDeviceMm.cy = cyVirtualDeviceMm;
1013
1014 // DC_UpdateXforms(dc);
1015 DC_UnlockDc(dc);
1016 return TRUE;
1017 }
1018
1019 /* EOF */