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