- Force a recompute when setting map modes.
[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 ULONG xdim;
41 ULONG ydim;
42 PDC_ATTR Dc_Attr = dc->pDc_Attr;
43 if(!Dc_Attr) Dc_Attr = &dc->Dc_Attr;
44
45 xdim = EngMulDiv(Dc_Attr->szlViewportExt.cx,
46 ((PGDIDEVICE)dc->pPDev)->GDIInfo.ulHorzSize,
47 ((PGDIDEVICE)dc->pPDev)->GDIInfo.ulHorzRes) /
48 Dc_Attr->szlWindowExt.cx;
49 ydim = EngMulDiv(Dc_Attr->szlViewportExt.cy,
50 ((PGDIDEVICE)dc->pPDev)->GDIInfo.ulVertSize,
51 ((PGDIDEVICE)dc->pPDev)->GDIInfo.ulVertRes) /
52 Dc_Attr->szlWindowExt.cy;
53
54 if (xdim > ydim)
55 {
56 Dc_Attr->szlViewportExt.cx = Dc_Attr->szlViewportExt.cx * abs(ydim / xdim);
57 if (!Dc_Attr->szlViewportExt.cx) Dc_Attr->szlViewportExt.cx = 1;
58 }
59 else
60 {
61 Dc_Attr->szlViewportExt.cy = Dc_Attr->szlViewportExt.cy * abs(xdim / ydim);
62 if (!Dc_Attr->szlViewportExt.cy) Dc_Attr->szlViewportExt.cy = 1;
63 }
64 }
65
66 BOOL FASTCALL
67 IntGdiCombineTransform(LPXFORM XFormResult,
68 LPXFORM xform1,
69 LPXFORM xform2)
70 {
71 XFORM xformTemp;
72 /* Check for illegal parameters */
73 if (!XFormResult || !xform1 || !xform2)
74 {
75 return FALSE;
76 }
77
78 /* Create the result in a temporary XFORM, since xformResult may be
79 * equal to xform1 or xform2 */
80 xformTemp.eM11 = xform1->eM11 * xform2->eM11 + xform1->eM12 * xform2->eM21;
81 xformTemp.eM12 = xform1->eM11 * xform2->eM12 + xform1->eM12 * xform2->eM22;
82 xformTemp.eM21 = xform1->eM21 * xform2->eM11 + xform1->eM22 * xform2->eM21;
83 xformTemp.eM22 = xform1->eM21 * xform2->eM12 + xform1->eM22 * xform2->eM22;
84 xformTemp.eDx = xform1->eDx * xform2->eM11 + xform1->eDy * xform2->eM21 + xform2->eDx;
85 xformTemp.eDy = xform1->eDx * xform2->eM12 + xform1->eDy * xform2->eM22 + xform2->eDy;
86 *XFormResult = xformTemp;
87
88 return TRUE;
89 }
90
91 BOOL STDCALL NtGdiCombineTransform(LPXFORM UnsafeXFormResult,
92 LPXFORM Unsafexform1,
93 LPXFORM Unsafexform2)
94 {
95 BOOL Ret;
96
97 _SEH_TRY
98 {
99 ProbeForWrite(UnsafeXFormResult,
100 sizeof(XFORM),
101 1);
102 ProbeForRead(Unsafexform1,
103 sizeof(XFORM),
104 1);
105 ProbeForRead(Unsafexform2,
106 sizeof(XFORM),
107 1);
108 Ret = IntGdiCombineTransform(UnsafeXFormResult, Unsafexform1, Unsafexform2);
109 }
110 _SEH_HANDLE
111 {
112 Ret = FALSE;
113 }
114 _SEH_END;
115
116 return Ret;
117 }
118
119
120 int
121 FASTCALL
122 IntGetGraphicsMode ( PDC dc )
123 {
124 PDC_ATTR Dc_Attr;
125 ASSERT ( dc );
126 Dc_Attr = dc->pDc_Attr;
127 if(!Dc_Attr) Dc_Attr = &dc->Dc_Attr;
128 return Dc_Attr->iGraphicsMode;
129 }
130
131 BOOL
132 FASTCALL
133 IntGdiModifyWorldTransform(PDC pDc,
134 CONST LPXFORM lpXForm,
135 DWORD Mode)
136 {
137 ASSERT(pDc);
138 XFORM xformWorld2Wnd;
139
140 switch(Mode)
141 {
142 case MWT_IDENTITY:
143 xformWorld2Wnd.eM11 = 1.0f;
144 xformWorld2Wnd.eM12 = 0.0f;
145 xformWorld2Wnd.eM21 = 0.0f;
146 xformWorld2Wnd.eM22 = 1.0f;
147 xformWorld2Wnd.eDx = 0.0f;
148 xformWorld2Wnd.eDy = 0.0f;
149 XForm2MatrixS(&pDc->DcLevel.mxWorldToPage, &xformWorld2Wnd);
150 break;
151
152 case MWT_LEFTMULTIPLY:
153 MatrixS2XForm(&xformWorld2Wnd, &pDc->DcLevel.mxWorldToPage);
154 IntGdiCombineTransform(&xformWorld2Wnd, lpXForm, &xformWorld2Wnd);
155 XForm2MatrixS(&pDc->DcLevel.mxWorldToPage, &xformWorld2Wnd);
156 break;
157
158 case MWT_RIGHTMULTIPLY:
159 MatrixS2XForm(&xformWorld2Wnd, &pDc->DcLevel.mxWorldToPage);
160 IntGdiCombineTransform(&xformWorld2Wnd, &xformWorld2Wnd, lpXForm);
161 XForm2MatrixS(&pDc->DcLevel.mxWorldToPage, &xformWorld2Wnd);
162 break;
163
164 case MWT_MAX+1: // Must be MWT_SET????
165 XForm2MatrixS(&pDc->DcLevel.mxWorldToPage, lpXForm); // Do it like Wine.
166 break;
167
168 default:
169 return FALSE;
170 }
171 DC_UpdateXforms(pDc);
172 return TRUE;
173 }
174
175 BOOL
176 STDCALL
177 NtGdiGetTransform(HDC hDC,
178 DWORD iXform,
179 LPXFORM XForm)
180 {
181 PDC dc;
182 NTSTATUS Status = STATUS_SUCCESS;
183
184 dc = DC_LockDc ( hDC );
185 if (!dc)
186 {
187 SetLastWin32Error(ERROR_INVALID_HANDLE);
188 return FALSE;
189 }
190 if (!XForm)
191 {
192 DC_UnlockDc(dc);
193 SetLastWin32Error(ERROR_INVALID_PARAMETER);
194 return FALSE;
195 }
196
197 _SEH_TRY
198 {
199 ProbeForWrite(XForm,
200 sizeof(XFORM),
201 1);
202 switch(iXform)
203 {
204 case GdiWorldSpaceToPageSpace:
205 MatrixS2XForm(XForm, &dc->DcLevel.mxWorldToPage);
206 break;
207 default:
208 break;
209 }
210 }
211 _SEH_HANDLE
212 {
213 Status = _SEH_GetExceptionCode();
214 }
215 _SEH_END;
216
217 DC_UnlockDc(dc);
218 return NT_SUCCESS(Status);
219 }
220
221
222 /*!
223 * Converts points from logical coordinates into device coordinates. Conversion depends on the mapping mode,
224 * world transfrom, viewport origin settings for the given device context.
225 * \param hDC device context.
226 * \param Points an array of POINT structures (in/out).
227 * \param Count number of elements in the array of POINT structures.
228 * \return TRUE if success.
229 */
230 BOOL
231 APIENTRY
232 NtGdiTransformPoints( HDC hDC,
233 PPOINT UnsafePtsIn,
234 PPOINT UnsafePtOut,
235 INT Count,
236 INT iMode )
237 {
238 PDC dc;
239 NTSTATUS Status = STATUS_SUCCESS;
240 LPPOINT Points;
241 ULONG Size;
242
243 dc = DC_LockDc(hDC);
244 if (!dc)
245 {
246 SetLastWin32Error(ERROR_INVALID_HANDLE);
247 return FALSE;
248 }
249
250 if (!UnsafePtsIn || !UnsafePtOut || Count <= 0)
251 {
252 DC_UnlockDc(dc);
253 SetLastWin32Error(ERROR_INVALID_PARAMETER);
254 return FALSE;
255 }
256
257 Size = Count * sizeof(POINT);
258
259 Points = (LPPOINT)ExAllocatePoolWithTag(PagedPool, Size, TAG_COORD);
260 if(!Points)
261 {
262 DC_UnlockDc(dc);
263 SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY);
264 return FALSE;
265 }
266
267 _SEH_TRY
268 {
269 ProbeForWrite(UnsafePtOut,
270 Size,
271 1);
272 ProbeForRead(UnsafePtsIn,
273 Size,
274 1);
275 RtlCopyMemory(Points,
276 UnsafePtsIn,
277 Size);
278 }
279 _SEH_HANDLE
280 {
281 Status = _SEH_GetExceptionCode();
282 }
283 _SEH_END;
284
285 if(!NT_SUCCESS(Status))
286 {
287 DC_UnlockDc(dc);
288 ExFreePool(Points);
289 SetLastNtError(Status);
290 return FALSE;
291 }
292
293 switch (iMode)
294 {
295 case GdiDpToLp:
296 IntDPtoLP(dc, Points, Count);
297 break;
298 case GdiLpToDp:
299 IntLPtoDP(dc, Points, Count);
300 break;
301 case 2: // Not supported yet. Need testing.
302 default:
303 {
304 DC_UnlockDc(dc);
305 ExFreePool(Points);
306 SetLastWin32Error(ERROR_INVALID_PARAMETER);
307 return FALSE;
308 }
309 }
310
311 _SEH_TRY
312 {
313 /* pointer was already probed! */
314 RtlCopyMemory(UnsafePtOut,
315 Points,
316 Size);
317 }
318 _SEH_HANDLE
319 {
320 Status = _SEH_GetExceptionCode();
321 }
322 _SEH_END;
323
324 if(!NT_SUCCESS(Status))
325 {
326 DC_UnlockDc(dc);
327 ExFreePool(Points);
328 SetLastNtError(Status);
329 return FALSE;
330 }
331 //
332 // If we are getting called that means User XForms is a mess!
333 //
334 DC_UnlockDc(dc);
335 ExFreePool(Points);
336 return TRUE;
337 }
338
339 BOOL
340 STDCALL
341 NtGdiModifyWorldTransform(HDC hDC,
342 LPXFORM UnsafeXForm,
343 DWORD Mode)
344 {
345 PDC dc;
346 XFORM SafeXForm;
347 BOOL Ret = TRUE;
348
349 dc = DC_LockDc(hDC);
350 if (!dc)
351 {
352 SetLastWin32Error(ERROR_INVALID_HANDLE);
353 return FALSE;
354 }
355
356 // The xform is permitted to be NULL for MWT_IDENTITY.
357 // However, if it is not NULL, then it must be valid even though it is not used.
358 if (UnsafeXForm != NULL || Mode != MWT_IDENTITY)
359 {
360 _SEH_TRY
361 {
362 ProbeForRead(UnsafeXForm, sizeof(XFORM), 1);
363 RtlCopyMemory(&SafeXForm, UnsafeXForm, sizeof(XFORM));
364 }
365 _SEH_HANDLE
366 {
367 Ret = FALSE;
368 }
369 _SEH_END;
370 }
371
372 // Safe to handle kernel mode data.
373 if (Ret) Ret = IntGdiModifyWorldTransform(dc, &SafeXForm, Mode);
374 DC_UnlockDc(dc);
375 return Ret;
376 }
377
378 BOOL
379 STDCALL
380 NtGdiOffsetViewportOrgEx(HDC hDC,
381 int XOffset,
382 int YOffset,
383 LPPOINT UnsafePoint)
384 {
385 PDC dc;
386 PDC_ATTR Dc_Attr;
387 NTSTATUS Status = STATUS_SUCCESS;
388
389 dc = DC_LockDc ( hDC );
390 if(!dc)
391 {
392 SetLastWin32Error(ERROR_INVALID_HANDLE);
393 return FALSE;
394 }
395 Dc_Attr = dc->pDc_Attr;
396 if(!Dc_Attr) Dc_Attr = &dc->Dc_Attr;
397
398 if (UnsafePoint)
399 {
400 _SEH_TRY
401 {
402 ProbeForWrite(UnsafePoint,
403 sizeof(POINT),
404 1);
405 UnsafePoint->x = Dc_Attr->ptlViewportOrg.x;
406 UnsafePoint->y = Dc_Attr->ptlViewportOrg.y;
407 }
408 _SEH_HANDLE
409 {
410 Status = _SEH_GetExceptionCode();
411 }
412 _SEH_END;
413
414 if ( !NT_SUCCESS(Status) )
415 {
416 SetLastNtError(Status);
417 DC_UnlockDc(dc);
418 return FALSE;
419 }
420 }
421
422 Dc_Attr->ptlViewportOrg.x += XOffset;
423 Dc_Attr->ptlViewportOrg.y += YOffset;
424 DC_UpdateXforms(dc);
425 DC_UnlockDc(dc);
426 return TRUE;
427 }
428
429 BOOL
430 STDCALL
431 NtGdiOffsetWindowOrgEx(HDC hDC,
432 int XOffset,
433 int YOffset,
434 LPPOINT Point)
435 {
436 PDC dc;
437 PDC_ATTR Dc_Attr;
438
439 dc = DC_LockDc(hDC);
440 if (!dc)
441 {
442 SetLastWin32Error(ERROR_INVALID_HANDLE);
443 return FALSE;
444 }
445 Dc_Attr = dc->pDc_Attr;
446 if(!Dc_Attr) Dc_Attr = &dc->Dc_Attr;
447
448 if (Point)
449 {
450 NTSTATUS Status = STATUS_SUCCESS;
451
452 _SEH_TRY
453 {
454 ProbeForWrite(Point,
455 sizeof(POINT),
456 1);
457 Point->x = Dc_Attr->ptlWindowOrg.x;
458 Point->y = Dc_Attr->ptlWindowOrg.y;
459 }
460 _SEH_HANDLE
461 {
462 Status = _SEH_GetExceptionCode();
463 }
464 _SEH_END;
465
466 if(!NT_SUCCESS(Status))
467 {
468 SetLastNtError(Status);
469 DC_UnlockDc(dc);
470 return FALSE;
471 }
472 }
473
474 Dc_Attr->ptlWindowOrg.x += XOffset;
475 Dc_Attr->ptlWindowOrg.y += YOffset;
476
477 DC_UpdateXforms(dc);
478 DC_UnlockDc(dc);
479
480 return TRUE;
481 }
482
483 BOOL
484 STDCALL
485 NtGdiScaleViewportExtEx(HDC hDC,
486 int Xnum,
487 int Xdenom,
488 int Ynum,
489 int Ydenom,
490 LPSIZE pSize)
491 {
492 PDC pDC;
493 PDC_ATTR pDc_Attr;
494 BOOL Ret = FALSE;
495 LONG X, Y;
496
497 pDC = DC_LockDc(hDC);
498 if (!pDC)
499 {
500 SetLastWin32Error(ERROR_INVALID_HANDLE);
501 return FALSE;
502 }
503 pDc_Attr = pDC->pDc_Attr;
504 if(!pDc_Attr) pDc_Attr = &pDC->Dc_Attr;
505
506 if ( pSize )
507 {
508 NTSTATUS Status = STATUS_SUCCESS;
509
510 _SEH_TRY
511 {
512 ProbeForWrite(pSize,
513 sizeof(LPSIZE),
514 1);
515
516 pSize->cx = pDc_Attr->szlViewportExt.cx;
517 pSize->cy = pDc_Attr->szlViewportExt.cy;
518 }
519 _SEH_HANDLE
520 {
521 Status = _SEH_GetExceptionCode();
522 }
523 _SEH_END;
524
525 if(!NT_SUCCESS(Status))
526 {
527 SetLastNtError(Status);
528 DC_UnlockDc(pDC);
529 return FALSE;
530 }
531 }
532
533 if (pDc_Attr->iMapMode > MM_TWIPS)
534 {
535 if ( ( Xdenom ) && ( Ydenom ) )
536 {
537 X = Xnum * pDc_Attr->szlViewportExt.cx / Xdenom;
538 if ( X )
539 {
540 Y = Ynum * pDc_Attr->szlViewportExt.cy / Ydenom;
541 if ( Y )
542 {
543 pDc_Attr->szlViewportExt.cx = X;
544 pDc_Attr->szlViewportExt.cy = Y;
545
546 IntMirrorWindowOrg(pDC);
547
548 pDc_Attr->flXform |= (PAGE_EXTENTS_CHANGED|INVALIDATE_ATTRIBUTES|DEVICE_TO_WORLD_INVALID);
549
550 if (pDc_Attr->iMapMode == MM_ISOTROPIC) IntFixIsotropicMapping(pDC);
551 DC_UpdateXforms(pDC);
552
553 Ret = TRUE;
554 }
555 }
556 }
557 }
558 else
559 Ret = TRUE;
560
561 DC_UnlockDc(pDC);
562 return Ret;
563 }
564
565 BOOL
566 STDCALL
567 NtGdiScaleWindowExtEx(HDC hDC,
568 int Xnum,
569 int Xdenom,
570 int Ynum,
571 int Ydenom,
572 LPSIZE pSize)
573 {
574 PDC pDC;
575 PDC_ATTR pDc_Attr;
576 BOOL Ret = FALSE;
577 LONG X, Y;
578
579 pDC = DC_LockDc(hDC);
580 if (!pDC)
581 {
582 SetLastWin32Error(ERROR_INVALID_HANDLE);
583 return FALSE;
584 }
585 pDc_Attr = pDC->pDc_Attr;
586 if(!pDc_Attr) pDc_Attr = &pDC->Dc_Attr;
587
588 if ( pSize )
589 {
590 NTSTATUS Status = STATUS_SUCCESS;
591
592 _SEH_TRY
593 {
594 ProbeForWrite(pSize,
595 sizeof(LPSIZE),
596 1);
597
598 X = pDc_Attr->szlWindowExt.cx;
599 if (pDc_Attr->dwLayout & LAYOUT_RTL) X = -X;
600 pSize->cx = X;
601 pSize->cy = pDc_Attr->szlWindowExt.cy;
602 }
603 _SEH_HANDLE
604 {
605 Status = _SEH_GetExceptionCode();
606 }
607 _SEH_END;
608
609 if(!NT_SUCCESS(Status))
610 {
611 SetLastNtError(Status);
612 DC_UnlockDc(pDC);
613 return FALSE;
614 }
615 }
616
617 if (pDc_Attr->iMapMode > MM_TWIPS)
618 {
619 if (( Xdenom ) && ( Ydenom ))
620 {
621 X = Xnum * pDc_Attr->szlWindowExt.cx / Xdenom;
622 if ( X )
623 {
624 Y = Ynum * pDc_Attr->szlWindowExt.cy / Ydenom;
625 if ( Y )
626 {
627 pDc_Attr->szlWindowExt.cx = X;
628 pDc_Attr->szlWindowExt.cy = Y;
629
630 IntMirrorWindowOrg(pDC);
631
632 pDc_Attr->flXform |= (PAGE_EXTENTS_CHANGED|INVALIDATE_ATTRIBUTES|DEVICE_TO_WORLD_INVALID);
633
634 if (pDc_Attr->iMapMode == MM_ISOTROPIC) IntFixIsotropicMapping(pDC);
635 DC_UpdateXforms(pDC);
636
637 Ret = TRUE;
638 }
639 }
640 }
641 }
642 else
643 Ret = TRUE;
644
645 DC_UnlockDc(pDC);
646 return Ret;
647 }
648
649 int
650 STDCALL
651 IntGdiSetMapMode(PDC dc,
652 int MapMode)
653 {
654 int PrevMapMode;
655 PDC_ATTR Dc_Attr = dc->pDc_Attr;
656 if(!Dc_Attr) Dc_Attr = &dc->Dc_Attr;
657
658 PrevMapMode = Dc_Attr->iMapMode;
659
660 Dc_Attr->iMapMode = MapMode;
661
662 switch (MapMode)
663 {
664 case MM_TEXT:
665 Dc_Attr->szlWindowExt.cx = 1;
666 Dc_Attr->szlWindowExt.cy = 1;
667 Dc_Attr->szlViewportExt.cx = 1;
668 Dc_Attr->szlViewportExt.cy = 1;
669 Dc_Attr->flXform &= ~(ISO_OR_ANISO_MAP_MODE|PTOD_EFM22_NEGATIVE|
670 PTOD_EFM11_NEGATIVE|POSITIVE_Y_IS_UP);
671 Dc_Attr->flXform |= (PAGE_XLATE_CHANGED|PAGE_TO_DEVICE_SCALE_IDENTITY|
672 INVALIDATE_ATTRIBUTES|DEVICE_TO_WORLD_INVALID);
673 break;
674
675 case MM_LOMETRIC:
676 case MM_ISOTROPIC:
677 Dc_Attr->szlWindowExt.cx = ((PGDIDEVICE)dc->pPDev)->GDIInfo.ulHorzSize * 10;
678 Dc_Attr->szlWindowExt.cy = ((PGDIDEVICE)dc->pPDev)->GDIInfo.ulVertSize * 10;
679 Dc_Attr->szlViewportExt.cx = ((PGDIDEVICE)dc->pPDev)->GDIInfo.ulHorzRes;
680 Dc_Attr->szlViewportExt.cy = -((PGDIDEVICE)dc->pPDev)->GDIInfo.ulVertRes;
681 break;
682
683 case MM_HIMETRIC:
684 Dc_Attr->szlWindowExt.cx = ((PGDIDEVICE)dc->pPDev)->GDIInfo.ulHorzSize * 100;
685 Dc_Attr->szlWindowExt.cy = ((PGDIDEVICE)dc->pPDev)->GDIInfo.ulVertSize * 100;
686 Dc_Attr->szlViewportExt.cx = ((PGDIDEVICE)dc->pPDev)->GDIInfo.ulHorzRes;
687 Dc_Attr->szlViewportExt.cy = -((PGDIDEVICE)dc->pPDev)->GDIInfo.ulVertRes;
688 break;
689
690 case MM_LOENGLISH:
691 Dc_Attr->szlWindowExt.cx = EngMulDiv(1000, ((PGDIDEVICE)dc->pPDev)->GDIInfo.ulHorzSize, 254);
692 Dc_Attr->szlWindowExt.cy = EngMulDiv(1000, ((PGDIDEVICE)dc->pPDev)->GDIInfo.ulVertSize, 254);
693 Dc_Attr->szlViewportExt.cx = ((PGDIDEVICE)dc->pPDev)->GDIInfo.ulHorzRes;
694 Dc_Attr->szlViewportExt.cy = -((PGDIDEVICE)dc->pPDev)->GDIInfo.ulVertRes;
695 break;
696
697 case MM_HIENGLISH:
698 Dc_Attr->szlWindowExt.cx = EngMulDiv(10000, ((PGDIDEVICE)dc->pPDev)->GDIInfo.ulHorzSize, 254);
699 Dc_Attr->szlWindowExt.cy = EngMulDiv(10000, ((PGDIDEVICE)dc->pPDev)->GDIInfo.ulVertSize, 254);
700 Dc_Attr->szlViewportExt.cx = ((PGDIDEVICE)dc->pPDev)->GDIInfo.ulHorzRes;
701 Dc_Attr->szlViewportExt.cy = -((PGDIDEVICE)dc->pPDev)->GDIInfo.ulVertRes;
702 break;
703
704 case MM_TWIPS:
705 Dc_Attr->szlWindowExt.cx = EngMulDiv(14400, ((PGDIDEVICE)dc->pPDev)->GDIInfo.ulHorzSize, 254);
706 Dc_Attr->szlWindowExt.cy = EngMulDiv(14400, ((PGDIDEVICE)dc->pPDev)->GDIInfo.ulVertSize, 254);
707 Dc_Attr->szlViewportExt.cx = ((PGDIDEVICE)dc->pPDev)->GDIInfo.ulHorzRes;
708 Dc_Attr->szlViewportExt.cy = -((PGDIDEVICE)dc->pPDev)->GDIInfo.ulVertRes;
709 break;
710
711 case MM_ANISOTROPIC:
712 Dc_Attr->flXform &= ~(PAGE_TO_DEVICE_IDENTITY|POSITIVE_Y_IS_UP);
713 Dc_Attr->flXform |= ISO_OR_ANISO_MAP_MODE;
714 break;
715 default:
716 Dc_Attr->iMapMode = PrevMapMode;
717 PrevMapMode = 0;
718
719 DC_UpdateXforms(dc);
720 }
721
722 return PrevMapMode;
723 }
724
725 BOOL
726 STDCALL
727 NtGdiSetViewportExtEx(HDC hDC,
728 int XExtent,
729 int YExtent,
730 LPSIZE Size)
731 {
732 PDC dc;
733 PDC_ATTR Dc_Attr;
734
735 dc = DC_LockDc(hDC);
736 if ( !dc )
737 {
738 SetLastWin32Error(ERROR_INVALID_HANDLE);
739 return FALSE;
740 }
741 Dc_Attr = dc->pDc_Attr;
742 if(!Dc_Attr) Dc_Attr = &dc->Dc_Attr;
743
744 switch (Dc_Attr->iMapMode)
745 {
746 case MM_HIENGLISH:
747 case MM_HIMETRIC:
748 case MM_LOENGLISH:
749 case MM_LOMETRIC:
750 case MM_TEXT:
751 case MM_TWIPS:
752 DC_UnlockDc(dc);
753 return FALSE;
754
755 case MM_ISOTROPIC:
756 // Here we should (probably) check that SetWindowExtEx *really* has
757 // been called
758 break;
759 }
760
761 if (Size)
762 {
763 NTSTATUS Status = STATUS_SUCCESS;
764
765 _SEH_TRY
766 {
767 ProbeForWrite(Size,
768 sizeof(SIZE),
769 1);
770 Size->cx = Dc_Attr->szlViewportExt.cx;
771 Size->cy = Dc_Attr->szlViewportExt.cy;
772
773 Dc_Attr->szlViewportExt.cx = XExtent;
774 Dc_Attr->szlViewportExt.cy = YExtent;
775
776 if (Dc_Attr->iMapMode == MM_ISOTROPIC)
777 IntFixIsotropicMapping(dc);
778 }
779 _SEH_HANDLE
780 {
781 Status = _SEH_GetExceptionCode();
782 }
783 _SEH_END;
784
785 if(!NT_SUCCESS(Status))
786 {
787 SetLastNtError(Status);
788 DC_UnlockDc(dc);
789 return FALSE;
790 }
791 }
792
793
794 DC_UpdateXforms(dc);
795 DC_UnlockDc(dc);
796
797 return TRUE;
798 }
799
800 BOOL
801 STDCALL
802 NtGdiSetViewportOrgEx(HDC hDC,
803 int X,
804 int Y,
805 LPPOINT Point)
806 {
807 PDC dc;
808 PDC_ATTR Dc_Attr;
809
810 dc = DC_LockDc(hDC);
811 if (!dc)
812 {
813 SetLastWin32Error(ERROR_INVALID_HANDLE);
814 return FALSE;
815 }
816 Dc_Attr = dc->pDc_Attr;
817 if(!Dc_Attr) Dc_Attr = &dc->Dc_Attr;
818
819 if (Point)
820 {
821 NTSTATUS Status = STATUS_SUCCESS;
822
823 _SEH_TRY
824 {
825 ProbeForWrite(Point,
826 sizeof(POINT),
827 1);
828 Point->x = Dc_Attr->ptlViewportOrg.x;
829 Point->y = Dc_Attr->ptlViewportOrg.y;
830 }
831 _SEH_HANDLE
832 {
833 Status = _SEH_GetExceptionCode();
834 }
835 _SEH_END;
836
837 if(!NT_SUCCESS(Status))
838 {
839 SetLastNtError(Status);
840 DC_UnlockDc(dc);
841 return FALSE;
842 }
843 }
844
845 Dc_Attr->ptlViewportOrg.x = X;
846 Dc_Attr->ptlViewportOrg.y = Y;
847
848 DC_UpdateXforms(dc);
849 DC_UnlockDc(dc);
850
851 return TRUE;
852 }
853
854 BOOL
855 STDCALL
856 NtGdiSetWindowExtEx(HDC hDC,
857 int XExtent,
858 int YExtent,
859 LPSIZE Size)
860 {
861 PDC dc;
862 PDC_ATTR Dc_Attr;
863
864 dc = DC_LockDc(hDC);
865 if (!dc)
866 {
867 SetLastWin32Error(ERROR_INVALID_HANDLE);
868 return FALSE;
869 }
870 Dc_Attr = dc->pDc_Attr;
871 if(!Dc_Attr) Dc_Attr = &dc->Dc_Attr;
872
873 switch (Dc_Attr->iMapMode)
874 {
875 case MM_HIENGLISH:
876 case MM_HIMETRIC:
877 case MM_LOENGLISH:
878 case MM_LOMETRIC:
879 case MM_TEXT:
880 case MM_TWIPS:
881 DC_UnlockDc(dc);
882 return FALSE;
883 }
884
885 if (Size)
886 {
887 NTSTATUS Status = STATUS_SUCCESS;
888
889 _SEH_TRY
890 {
891 ProbeForWrite(Size,
892 sizeof(SIZE),
893 1);
894 Size->cx = Dc_Attr->szlWindowExt.cx;
895 Size->cy = Dc_Attr->szlWindowExt.cy;
896 }
897 _SEH_HANDLE
898 {
899 Status = _SEH_GetExceptionCode();
900 }
901 _SEH_END;
902
903 if(!NT_SUCCESS(Status))
904 {
905 SetLastNtError(Status);
906 DC_UnlockDc(dc);
907 return FALSE;
908 }
909 }
910
911 Dc_Attr->szlWindowExt.cx = XExtent;
912 Dc_Attr->szlWindowExt.cy = YExtent;
913
914 DC_UpdateXforms(dc);
915 DC_UnlockDc(dc);
916
917 return TRUE;
918 }
919
920 BOOL
921 STDCALL
922 NtGdiSetWindowOrgEx(HDC hDC,
923 int X,
924 int Y,
925 LPPOINT Point)
926 {
927 PDC dc;
928 PDC_ATTR Dc_Attr;
929
930 dc = DC_LockDc(hDC);
931 if (!dc)
932 {
933 SetLastWin32Error(ERROR_INVALID_HANDLE);
934 return FALSE;
935 }
936 Dc_Attr = dc->pDc_Attr;
937 if(!Dc_Attr) Dc_Attr = &dc->Dc_Attr;
938
939 if (Point)
940 {
941 NTSTATUS Status = STATUS_SUCCESS;
942
943 _SEH_TRY
944 {
945 ProbeForWrite(Point,
946 sizeof(POINT),
947 1);
948 Point->x = Dc_Attr->ptlWindowOrg.x;
949 Point->y = Dc_Attr->ptlWindowOrg.y;
950 }
951 _SEH_HANDLE
952 {
953 Status = _SEH_GetExceptionCode();
954 }
955 _SEH_END;
956
957 if(!NT_SUCCESS(Status))
958 {
959 SetLastNtError(Status);
960 DC_UnlockDc(dc);
961 return FALSE;
962 }
963 }
964
965 Dc_Attr->ptlWindowOrg.x = X;
966 Dc_Attr->ptlWindowOrg.y = Y;
967
968 DC_UpdateXforms(dc);
969 DC_UnlockDc(dc);
970
971 return TRUE;
972 }
973
974 //
975 // Mirror Window function.
976 //
977 VOID
978 FASTCALL
979 IntMirrorWindowOrg(PDC dc)
980 {
981 PDC_ATTR Dc_Attr;
982 LONG X;
983
984 Dc_Attr = dc->pDc_Attr;
985 if(!Dc_Attr) Dc_Attr = &dc->Dc_Attr;
986
987 if (!(Dc_Attr->dwLayout & LAYOUT_RTL))
988 {
989 Dc_Attr->ptlWindowOrg.x = Dc_Attr->lWindowOrgx; // Flip it back.
990 return;
991 }
992 if (!Dc_Attr->szlViewportExt.cx) return;
993 //
994 // WOrgx = wox - (Width - 1) * WExtx / VExtx
995 //
996 X = (dc->erclWindow.right - dc->erclWindow.left) - 1; // Get device width - 1
997
998 X = ( X * Dc_Attr->szlWindowExt.cx) / Dc_Attr->szlViewportExt.cx;
999
1000 Dc_Attr->ptlWindowOrg.x = Dc_Attr->lWindowOrgx - X; // Now set the inverted win origion.
1001
1002 return;
1003 }
1004
1005 // NtGdiSetLayout
1006 //
1007 // The default is left to right. This function changes it to right to left, which
1008 // is the standard in Arabic and Hebrew cultures.
1009 //
1010 /*
1011 * @implemented
1012 */
1013 DWORD
1014 APIENTRY
1015 NtGdiSetLayout(
1016 IN HDC hdc,
1017 IN LONG wox,
1018 IN DWORD dwLayout)
1019 {
1020 PDC dc;
1021 PDC_ATTR Dc_Attr;
1022 DWORD oLayout;
1023
1024 dc = DC_LockDc(hdc);
1025 if (!dc)
1026 {
1027 SetLastWin32Error(ERROR_INVALID_HANDLE);
1028 return GDI_ERROR;
1029 }
1030 Dc_Attr = dc->pDc_Attr;
1031 if(!Dc_Attr) Dc_Attr = &dc->Dc_Attr;
1032
1033 Dc_Attr->dwLayout = dwLayout;
1034 oLayout = Dc_Attr->dwLayout;
1035
1036 if (!(dwLayout & LAYOUT_ORIENTATIONMASK))
1037 {
1038 DC_UnlockDc(dc);
1039 return oLayout;
1040 }
1041
1042 if (dwLayout & LAYOUT_RTL) Dc_Attr->iMapMode = MM_ANISOTROPIC;
1043
1044 Dc_Attr->szlWindowExt.cy = -Dc_Attr->szlWindowExt.cy;
1045 Dc_Attr->ptlWindowOrg.x = -Dc_Attr->ptlWindowOrg.x;
1046
1047 if (wox == -1)
1048 IntMirrorWindowOrg(dc);
1049 else
1050 Dc_Attr->ptlWindowOrg.x = wox - Dc_Attr->ptlWindowOrg.x;
1051
1052 if (!(Dc_Attr->flTextAlign & TA_CENTER)) Dc_Attr->flTextAlign |= TA_RIGHT;
1053
1054 if (dc->DcLevel.flPath & DCPATH_CLOCKWISE)
1055 dc->DcLevel.flPath &= ~DCPATH_CLOCKWISE;
1056 else
1057 dc->DcLevel.flPath |= DCPATH_CLOCKWISE;
1058
1059 Dc_Attr->flXform |= (PAGE_EXTENTS_CHANGED|INVALIDATE_ATTRIBUTES|DEVICE_TO_WORLD_INVALID);
1060
1061 // DC_UpdateXforms(dc);
1062 DC_UnlockDc(dc);
1063 return oLayout;
1064 }
1065
1066 /*
1067 * @implemented
1068 */
1069 LONG
1070 APIENTRY
1071 NtGdiGetDeviceWidth(
1072 IN HDC hdc)
1073 {
1074 PDC dc;
1075 LONG Ret;
1076 dc = DC_LockDc(hdc);
1077 if (!dc)
1078 {
1079 SetLastWin32Error(ERROR_INVALID_HANDLE);
1080 return 0;
1081 }
1082 Ret = dc->erclWindow.right - dc->erclWindow.left;
1083 DC_UnlockDc(dc);
1084 return Ret;
1085 }
1086
1087 /*
1088 * @implemented
1089 */
1090 BOOL
1091 APIENTRY
1092 NtGdiMirrorWindowOrg(
1093 IN HDC hdc)
1094 {
1095 PDC dc;
1096 dc = DC_LockDc(hdc);
1097 if (!dc)
1098 {
1099 SetLastWin32Error(ERROR_INVALID_HANDLE);
1100 return FALSE;
1101 }
1102 IntMirrorWindowOrg(dc);
1103 DC_UnlockDc(dc);
1104 return TRUE;
1105 }
1106
1107 /*
1108 * @implemented
1109 */
1110 BOOL
1111 APIENTRY
1112 NtGdiSetSizeDevice(
1113 IN HDC hdc,
1114 IN INT cxVirtualDevice,
1115 IN INT cyVirtualDevice)
1116 {
1117 PDC dc;
1118 PDC_ATTR pDc_Attr;
1119
1120 if (!cxVirtualDevice ||
1121 !cyVirtualDevice ) return FALSE;
1122
1123 dc = DC_LockDc(hdc);
1124 if (!dc) return FALSE;
1125
1126 pDc_Attr = dc->pDc_Attr;
1127 if(!pDc_Attr) pDc_Attr = &dc->Dc_Attr;
1128
1129 pDc_Attr->szlVirtualDeviceSize.cx = cxVirtualDevice;
1130 pDc_Attr->szlVirtualDeviceSize.cy = cyVirtualDevice;
1131
1132 // DC_UpdateXforms(dc);
1133 DC_UnlockDc(dc);
1134
1135 return TRUE;
1136 }
1137
1138 /*
1139 * @implemented
1140 */
1141 BOOL
1142 APIENTRY
1143 NtGdiSetVirtualResolution(
1144 IN HDC hdc,
1145 IN INT cxVirtualDevicePixel,
1146 IN INT cyVirtualDevicePixel,
1147 IN INT cxVirtualDeviceMm,
1148 IN INT cyVirtualDeviceMm)
1149 {
1150 PDC dc;
1151 PDC_ATTR pDc_Attr;
1152
1153 // Need test types for zeros and non zeros
1154
1155 dc = DC_LockDc(hdc);
1156 if (!dc) return FALSE;
1157
1158 pDc_Attr = dc->pDc_Attr;
1159 if(!pDc_Attr) pDc_Attr = &dc->Dc_Attr;
1160
1161 pDc_Attr->szlVirtualDevicePixel.cx = cxVirtualDevicePixel;
1162 pDc_Attr->szlVirtualDevicePixel.cy = cyVirtualDevicePixel;
1163 pDc_Attr->szlVirtualDeviceMm.cx = cxVirtualDeviceMm;
1164 pDc_Attr->szlVirtualDeviceMm.cy = cyVirtualDeviceMm;
1165
1166 // DC_UpdateXforms(dc);
1167 DC_UnlockDc(dc);
1168 return TRUE;
1169 }
1170
1171 /* EOF */