Removed w.ArcDirection. Now we are using dclevel path flags.
[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 /* $Id$
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->w.xformVport2World.eM11 +
154 y * Dc->w.xformVport2World.eM21 + Dc->w.xformVport2World.eDx;
155 Point->y = x * Dc->w.xformVport2World.eM12 +
156 y * Dc->w.xformVport2World.eM22 + Dc->w.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->w.xformWorld2Wnd.eM11 = 1.0f;
194 pDc->w.xformWorld2Wnd.eM12 = 0.0f;
195 pDc->w.xformWorld2Wnd.eM21 = 0.0f;
196 pDc->w.xformWorld2Wnd.eM22 = 1.0f;
197 pDc->w.xformWorld2Wnd.eDx = 0.0f;
198 pDc->w.xformWorld2Wnd.eDy = 0.0f;
199 break;
200
201 case MWT_LEFTMULTIPLY:
202 IntGdiCombineTransform(&pDc->w.xformWorld2Wnd, lpXForm, &pDc->w.xformWorld2Wnd );
203 break;
204
205 case MWT_RIGHTMULTIPLY:
206 IntGdiCombineTransform(&pDc->w.xformWorld2Wnd, &pDc->w.xformWorld2Wnd, lpXForm);
207 break;
208
209 case MWT_MAX+1: // Must be MWT_SET????
210 pDc->w.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->w.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->w.xformWorld2Vport.eM11 +
279 y * Dc->w.xformWorld2Vport.eM21 + Dc->w.xformWorld2Vport.eDx;
280 Point->y = x * Dc->w.xformWorld2Vport.eM12 +
281 y * Dc->w.xformWorld2Vport.eM22 + Dc->w.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 Size)
566 {
567 UNIMPLEMENTED;
568 return FALSE;
569 }
570
571 BOOL
572 STDCALL
573 NtGdiScaleWindowExtEx(HDC hDC,
574 int Xnum,
575 int Xdenom,
576 int Ynum,
577 int Ydenom,
578 LPSIZE Size)
579 {
580 UNIMPLEMENTED;
581 return FALSE;
582 }
583
584 int
585 STDCALL
586 IntGdiSetMapMode(PDC dc,
587 int MapMode)
588 {
589 int PrevMapMode;
590 PDC_ATTR Dc_Attr = dc->pDc_Attr;
591 if(!Dc_Attr) Dc_Attr = &dc->Dc_Attr;
592
593 PrevMapMode = Dc_Attr->iMapMode;
594
595 if (MapMode != Dc_Attr->iMapMode || (MapMode != MM_ISOTROPIC && MapMode != MM_ANISOTROPIC))
596 {
597 Dc_Attr->iMapMode = MapMode;
598
599 switch (MapMode)
600 {
601 case MM_TEXT:
602 Dc_Attr->szlWindowExt.cx = 1;
603 Dc_Attr->szlWindowExt.cy = 1;
604 Dc_Attr->szlViewportExt.cx = 1;
605 Dc_Attr->szlViewportExt.cy = 1;
606 break;
607
608 case MM_LOMETRIC:
609 case MM_ISOTROPIC:
610 Dc_Attr->szlWindowExt.cx = ((PGDIDEVICE)dc->pPDev)->GDIInfo.ulHorzSize * 10;
611 Dc_Attr->szlWindowExt.cy = ((PGDIDEVICE)dc->pPDev)->GDIInfo.ulVertSize * 10;
612 Dc_Attr->szlViewportExt.cx = ((PGDIDEVICE)dc->pPDev)->GDIInfo.ulHorzRes;
613 Dc_Attr->szlViewportExt.cy = -((PGDIDEVICE)dc->pPDev)->GDIInfo.ulVertRes;
614 break;
615
616 case MM_HIMETRIC:
617 Dc_Attr->szlWindowExt.cx = ((PGDIDEVICE)dc->pPDev)->GDIInfo.ulHorzSize * 100;
618 Dc_Attr->szlWindowExt.cy = ((PGDIDEVICE)dc->pPDev)->GDIInfo.ulVertSize * 100;
619 Dc_Attr->szlViewportExt.cx = ((PGDIDEVICE)dc->pPDev)->GDIInfo.ulHorzRes;
620 Dc_Attr->szlViewportExt.cy = -((PGDIDEVICE)dc->pPDev)->GDIInfo.ulVertRes;
621 break;
622
623 case MM_LOENGLISH:
624 Dc_Attr->szlWindowExt.cx = EngMulDiv(1000, ((PGDIDEVICE)dc->pPDev)->GDIInfo.ulHorzSize, 254);
625 Dc_Attr->szlWindowExt.cy = EngMulDiv(1000, ((PGDIDEVICE)dc->pPDev)->GDIInfo.ulVertSize, 254);
626 Dc_Attr->szlViewportExt.cx = ((PGDIDEVICE)dc->pPDev)->GDIInfo.ulHorzRes;
627 Dc_Attr->szlViewportExt.cy = -((PGDIDEVICE)dc->pPDev)->GDIInfo.ulVertRes;
628 break;
629
630 case MM_HIENGLISH:
631 Dc_Attr->szlWindowExt.cx = EngMulDiv(10000, ((PGDIDEVICE)dc->pPDev)->GDIInfo.ulHorzSize, 254);
632 Dc_Attr->szlWindowExt.cy = EngMulDiv(10000, ((PGDIDEVICE)dc->pPDev)->GDIInfo.ulVertSize, 254);
633 Dc_Attr->szlViewportExt.cx = ((PGDIDEVICE)dc->pPDev)->GDIInfo.ulHorzRes;
634 Dc_Attr->szlViewportExt.cy = -((PGDIDEVICE)dc->pPDev)->GDIInfo.ulVertRes;
635 break;
636
637 case MM_TWIPS:
638 Dc_Attr->szlWindowExt.cx = EngMulDiv(14400, ((PGDIDEVICE)dc->pPDev)->GDIInfo.ulHorzSize, 254);
639 Dc_Attr->szlWindowExt.cy = EngMulDiv(14400, ((PGDIDEVICE)dc->pPDev)->GDIInfo.ulVertSize, 254);
640 Dc_Attr->szlViewportExt.cx = ((PGDIDEVICE)dc->pPDev)->GDIInfo.ulHorzRes;
641 Dc_Attr->szlViewportExt.cy = -((PGDIDEVICE)dc->pPDev)->GDIInfo.ulVertRes;
642 break;
643
644 case MM_ANISOTROPIC:
645 break;
646 }
647
648 DC_UpdateXforms(dc);
649 }
650
651 return PrevMapMode;
652 }
653
654 BOOL
655 STDCALL
656 NtGdiSetViewportExtEx(HDC hDC,
657 int XExtent,
658 int YExtent,
659 LPSIZE Size)
660 {
661 PDC dc;
662 PDC_ATTR Dc_Attr;
663
664 dc = DC_LockDc(hDC);
665 if ( !dc )
666 {
667 SetLastWin32Error(ERROR_INVALID_HANDLE);
668 return FALSE;
669 }
670 Dc_Attr = dc->pDc_Attr;
671 if(!Dc_Attr) Dc_Attr = &dc->Dc_Attr;
672
673 switch (Dc_Attr->iMapMode)
674 {
675 case MM_HIENGLISH:
676 case MM_HIMETRIC:
677 case MM_LOENGLISH:
678 case MM_LOMETRIC:
679 case MM_TEXT:
680 case MM_TWIPS:
681 DC_UnlockDc(dc);
682 return FALSE;
683
684 case MM_ISOTROPIC:
685 // Here we should (probably) check that SetWindowExtEx *really* has
686 // been called
687 break;
688 }
689
690 if (Size)
691 {
692 NTSTATUS Status = STATUS_SUCCESS;
693
694 _SEH_TRY
695 {
696 ProbeForWrite(Size,
697 sizeof(SIZE),
698 1);
699 Size->cx = Dc_Attr->szlViewportExt.cx;
700 Size->cy = Dc_Attr->szlViewportExt.cy;
701
702 Dc_Attr->szlViewportExt.cx = XExtent;
703 Dc_Attr->szlViewportExt.cy = YExtent;
704
705 if (Dc_Attr->iMapMode == MM_ISOTROPIC)
706 IntFixIsotropicMapping(dc);
707 }
708 _SEH_HANDLE
709 {
710 Status = _SEH_GetExceptionCode();
711 }
712 _SEH_END;
713
714 if(!NT_SUCCESS(Status))
715 {
716 SetLastNtError(Status);
717 DC_UnlockDc(dc);
718 return FALSE;
719 }
720 }
721
722
723 DC_UpdateXforms(dc);
724 DC_UnlockDc(dc);
725
726 return TRUE;
727 }
728
729 BOOL
730 STDCALL
731 NtGdiSetViewportOrgEx(HDC hDC,
732 int X,
733 int Y,
734 LPPOINT Point)
735 {
736 PDC dc;
737 PDC_ATTR Dc_Attr;
738
739 dc = DC_LockDc(hDC);
740 if (!dc)
741 {
742 SetLastWin32Error(ERROR_INVALID_HANDLE);
743 return FALSE;
744 }
745 Dc_Attr = dc->pDc_Attr;
746 if(!Dc_Attr) Dc_Attr = &dc->Dc_Attr;
747
748 if (Point)
749 {
750 NTSTATUS Status = STATUS_SUCCESS;
751
752 _SEH_TRY
753 {
754 ProbeForWrite(Point,
755 sizeof(POINT),
756 1);
757 Point->x = Dc_Attr->ptlViewportOrg.x;
758 Point->y = Dc_Attr->ptlViewportOrg.y;
759 }
760 _SEH_HANDLE
761 {
762 Status = _SEH_GetExceptionCode();
763 }
764 _SEH_END;
765
766 if(!NT_SUCCESS(Status))
767 {
768 SetLastNtError(Status);
769 DC_UnlockDc(dc);
770 return FALSE;
771 }
772 }
773
774 Dc_Attr->ptlViewportOrg.x = X;
775 Dc_Attr->ptlViewportOrg.y = Y;
776
777 DC_UpdateXforms(dc);
778 DC_UnlockDc(dc);
779
780 return TRUE;
781 }
782
783 BOOL
784 STDCALL
785 NtGdiSetWindowExtEx(HDC hDC,
786 int XExtent,
787 int YExtent,
788 LPSIZE Size)
789 {
790 PDC dc;
791 PDC_ATTR Dc_Attr;
792
793 dc = DC_LockDc(hDC);
794 if (!dc)
795 {
796 SetLastWin32Error(ERROR_INVALID_HANDLE);
797 return FALSE;
798 }
799 Dc_Attr = dc->pDc_Attr;
800 if(!Dc_Attr) Dc_Attr = &dc->Dc_Attr;
801
802 switch (Dc_Attr->iMapMode)
803 {
804 case MM_HIENGLISH:
805 case MM_HIMETRIC:
806 case MM_LOENGLISH:
807 case MM_LOMETRIC:
808 case MM_TEXT:
809 case MM_TWIPS:
810 DC_UnlockDc(dc);
811 return FALSE;
812 }
813
814 if (Size)
815 {
816 NTSTATUS Status = STATUS_SUCCESS;
817
818 _SEH_TRY
819 {
820 ProbeForWrite(Size,
821 sizeof(SIZE),
822 1);
823 Size->cx = Dc_Attr->szlWindowExt.cx;
824 Size->cy = Dc_Attr->szlWindowExt.cy;
825 }
826 _SEH_HANDLE
827 {
828 Status = _SEH_GetExceptionCode();
829 }
830 _SEH_END;
831
832 if(!NT_SUCCESS(Status))
833 {
834 SetLastNtError(Status);
835 DC_UnlockDc(dc);
836 return FALSE;
837 }
838 }
839
840 Dc_Attr->szlWindowExt.cx = XExtent;
841 Dc_Attr->szlWindowExt.cy = YExtent;
842
843 DC_UpdateXforms(dc);
844 DC_UnlockDc(dc);
845
846 return TRUE;
847 }
848
849 BOOL
850 STDCALL
851 NtGdiSetWindowOrgEx(HDC hDC,
852 int X,
853 int Y,
854 LPPOINT Point)
855 {
856 PDC dc;
857 PDC_ATTR Dc_Attr;
858
859 dc = DC_LockDc(hDC);
860 if (!dc)
861 {
862 SetLastWin32Error(ERROR_INVALID_HANDLE);
863 return FALSE;
864 }
865 Dc_Attr = dc->pDc_Attr;
866 if(!Dc_Attr) Dc_Attr = &dc->Dc_Attr;
867
868 if (Point)
869 {
870 NTSTATUS Status = STATUS_SUCCESS;
871
872 _SEH_TRY
873 {
874 ProbeForWrite(Point,
875 sizeof(POINT),
876 1);
877 Point->x = Dc_Attr->ptlWindowOrg.x;
878 Point->y = Dc_Attr->ptlWindowOrg.y;
879 }
880 _SEH_HANDLE
881 {
882 Status = _SEH_GetExceptionCode();
883 }
884 _SEH_END;
885
886 if(!NT_SUCCESS(Status))
887 {
888 SetLastNtError(Status);
889 DC_UnlockDc(dc);
890 return FALSE;
891 }
892 }
893
894 Dc_Attr->ptlWindowOrg.x = X;
895 Dc_Attr->ptlWindowOrg.y = Y;
896
897 DC_UpdateXforms(dc);
898 DC_UnlockDc(dc);
899
900 return TRUE;
901 }
902
903 //
904 // Mirror Window function.
905 //
906 VOID
907 FASTCALL
908 IntMirrorWindowOrg(PDC dc)
909 {
910 PDC_ATTR Dc_Attr;
911 LONG X;
912
913 Dc_Attr = dc->pDc_Attr;
914 if(!Dc_Attr) Dc_Attr = &dc->Dc_Attr;
915
916 if (!(Dc_Attr->dwLayout & LAYOUT_RTL))
917 {
918 Dc_Attr->ptlWindowOrg.x = Dc_Attr->lWindowOrgx; // Flip it back.
919 return;
920 }
921 if (!Dc_Attr->szlViewportExt.cx) return;
922 //
923 // WOrgx = wox - (Width - 1) * WExtx / VExtx
924 //
925 X = (dc->erclWindow.right - dc->erclWindow.left) - 1; // Get device width - 1
926
927 X = ( X * Dc_Attr->szlWindowExt.cx) / Dc_Attr->szlViewportExt.cx;
928
929 Dc_Attr->ptlWindowOrg.x = Dc_Attr->lWindowOrgx - X; // Now set the inverted win origion.
930
931 return;
932 }
933
934 // NtGdiSetLayout
935 //
936 // The default is left to right. This function changes it to right to left, which
937 // is the standard in Arabic and Hebrew cultures.
938 //
939 /*
940 * @implemented
941 */
942 DWORD
943 APIENTRY
944 NtGdiSetLayout(
945 IN HDC hdc,
946 IN LONG wox,
947 IN DWORD dwLayout)
948 {
949 PDC dc;
950 PDC_ATTR Dc_Attr;
951 DWORD oLayout;
952
953 dc = DC_LockDc(hdc);
954 if (!dc)
955 {
956 SetLastWin32Error(ERROR_INVALID_HANDLE);
957 return GDI_ERROR;
958 }
959 Dc_Attr = dc->pDc_Attr;
960 if(!Dc_Attr) Dc_Attr = &dc->Dc_Attr;
961
962 Dc_Attr->dwLayout = dwLayout;
963 oLayout = Dc_Attr->dwLayout;
964
965 if (!(dwLayout & LAYOUT_ORIENTATIONMASK))
966 {
967 DC_UnlockDc(dc);
968 return oLayout;
969 }
970
971 if (dwLayout & LAYOUT_RTL) Dc_Attr->iMapMode = MM_ANISOTROPIC;
972
973 Dc_Attr->szlWindowExt.cy = -Dc_Attr->szlWindowExt.cy;
974 Dc_Attr->ptlWindowOrg.x = -Dc_Attr->ptlWindowOrg.x;
975
976 if (wox == -1)
977 IntMirrorWindowOrg(dc);
978 else
979 Dc_Attr->ptlWindowOrg.x = wox - Dc_Attr->ptlWindowOrg.x;
980
981 if (!(Dc_Attr->flTextAlign & TA_CENTER)) Dc_Attr->flTextAlign |= TA_RIGHT;
982
983 if (dc->DcLevel.flPath & DCPATH_CLOCKWISE)
984 dc->DcLevel.flPath &= ~DCPATH_CLOCKWISE;
985 else
986 dc->DcLevel.flPath |= DCPATH_CLOCKWISE;
987
988 Dc_Attr->flXform |= (PAGE_EXTENTS_CHANGED|INVALIDATE_ATTRIBUTES|DEVICE_TO_WORLD_INVALID);
989
990 // DC_UpdateXforms(dc);
991 DC_UnlockDc(dc);
992 return oLayout;
993 }
994
995 /*
996 * @implemented
997 */
998 LONG
999 APIENTRY
1000 NtGdiGetDeviceWidth(
1001 IN HDC hdc)
1002 {
1003 PDC dc;
1004 LONG Ret;
1005 dc = DC_LockDc(hdc);
1006 if (!dc)
1007 {
1008 SetLastWin32Error(ERROR_INVALID_HANDLE);
1009 return 0;
1010 }
1011 Ret = dc->erclWindow.right - dc->erclWindow.left;
1012 DC_UnlockDc(dc);
1013 return Ret;
1014 }
1015
1016 /*
1017 * @implemented
1018 */
1019 BOOL
1020 APIENTRY
1021 NtGdiMirrorWindowOrg(
1022 IN HDC hdc)
1023 {
1024 PDC dc;
1025 dc = DC_LockDc(hdc);
1026 if (!dc)
1027 {
1028 SetLastWin32Error(ERROR_INVALID_HANDLE);
1029 return FALSE;
1030 }
1031 IntMirrorWindowOrg(dc);
1032 DC_UnlockDc(dc);
1033 return TRUE;
1034 }
1035
1036 /* EOF */