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