Move the inclusion of <debug.h> to individual files and consolidate the inclusion...
[reactos.git] / reactos / subsys / 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 BOOL FASTCALL
38 IntGdiCombineTransform(LPXFORM XFormResult,
39 LPXFORM xform1,
40 LPXFORM xform2)
41 {
42 /* Check for illegal parameters */
43 if (!XFormResult || !xform1 || !xform2)
44 {
45 return FALSE;
46 }
47
48 /* Create the result in a temporary XFORM, since xformResult may be
49 * equal to xform1 or xform2 */
50 XFormResult->eM11 = xform1->eM11 * xform2->eM11 + xform1->eM12 * xform2->eM21;
51 XFormResult->eM12 = xform1->eM11 * xform2->eM12 + xform1->eM12 * xform2->eM22;
52 XFormResult->eM21 = xform1->eM21 * xform2->eM11 + xform1->eM22 * xform2->eM21;
53 XFormResult->eM22 = xform1->eM21 * xform2->eM12 + xform1->eM22 * xform2->eM22;
54 XFormResult->eDx = xform1->eDx * xform2->eM11 + xform1->eDy * xform2->eM21 + xform2->eDx;
55 XFormResult->eDy = xform1->eDx * xform2->eM12 + xform1->eDy * xform2->eM22 + xform2->eDy;
56
57 return TRUE;
58 }
59
60 BOOL STDCALL NtGdiCombineTransform(LPXFORM UnsafeXFormResult,
61 CONST LPXFORM Unsafexform1,
62 CONST LPXFORM Unsafexform2)
63 {
64 XFORM xformTemp;
65 XFORM xform1, xform2;
66 NTSTATUS Status;
67 BOOL Ret;
68
69
70 Status = MmCopyFromCaller( &xform1, Unsafexform1, sizeof(XFORM) );
71 if(!NT_SUCCESS(Status))
72 {
73 SetLastNtError(Status);
74 return FALSE;
75 }
76 Status = MmCopyFromCaller( &xform2, Unsafexform2, sizeof(XFORM) );
77 if(!NT_SUCCESS(Status))
78 {
79 SetLastNtError(Status);
80 return FALSE;
81 }
82
83 Ret = IntGdiCombineTransform(&xformTemp, &xform1, &xform2);
84
85 /* Copy the result to xformResult */
86 Status = MmCopyToCaller( UnsafeXFormResult, &xformTemp, sizeof(XFORM) );
87 if(!NT_SUCCESS(Status))
88 {
89 SetLastNtError(Status);
90 return FALSE;
91 }
92
93 return Ret;
94 }
95
96 VOID FASTCALL
97 CoordDPtoLP(PDC Dc, LPPOINT Point)
98 {
99 FLOAT x, y;
100 x = (FLOAT)Point->x;
101 y = (FLOAT)Point->y;
102 Point->x = x * Dc->w.xformVport2World.eM11 +
103 y * Dc->w.xformVport2World.eM21 + Dc->w.xformVport2World.eDx;
104 Point->y = x * Dc->w.xformVport2World.eM12 +
105 y * Dc->w.xformVport2World.eM22 + Dc->w.xformVport2World.eDy;
106 }
107
108 VOID
109 FASTCALL
110 IntDPtoLP ( PDC dc, LPPOINT Points, INT Count )
111 {
112 INT i;
113
114 ASSERT ( Points );
115
116 for ( i = 0; i < Count; i++ )
117 CoordDPtoLP ( dc, &Points[i] );
118 }
119
120 /*!
121 * Converts points from device coordinates into logical coordinates. Conversion depends on the mapping mode,
122 * world transfrom, viewport origin settings for the given device context.
123 * \param hDC device context.
124 * \param Points an array of POINT structures (in/out).
125 * \param Count number of elements in the array of POINT structures.
126 * \return TRUE if success.
127 */
128 BOOL STDCALL
129 NtGdiDPtoLP(HDC hDC,
130 LPPOINT UnsafePoints,
131 int Count)
132 {
133 PDC dc;
134 NTSTATUS Status;
135 LPPOINT Points;
136 ULONG Size;
137
138 dc = DC_LockDc(hDC);
139 if (!dc)
140 {
141 SetLastWin32Error(ERROR_INVALID_HANDLE);
142 return FALSE;
143 }
144
145 if (!UnsafePoints || Count <= 0)
146 {
147 DC_UnlockDc(dc);
148 SetLastWin32Error(ERROR_INVALID_PARAMETER);
149 return FALSE;
150 }
151
152 Size = Count * sizeof(POINT);
153
154 Points = (LPPOINT)ExAllocatePoolWithTag(PagedPool, Size, TAG_COORD);
155 if(!Points)
156 {
157 DC_UnlockDc(dc);
158 SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY);
159 return FALSE;
160 }
161
162 Status = MmCopyFromCaller(Points, UnsafePoints, Size);
163 if(!NT_SUCCESS(Status))
164 {
165 DC_UnlockDc(dc);
166 ExFreePool(Points);
167 SetLastNtError(Status);
168 return FALSE;
169 }
170
171 IntDPtoLP(dc, Points, Count);
172
173 Status = MmCopyToCaller(UnsafePoints, Points, Size);
174 if(!NT_SUCCESS(Status))
175 {
176 DC_UnlockDc(dc);
177 ExFreePool(Points);
178 SetLastNtError(Status);
179 return FALSE;
180 }
181
182 DC_UnlockDc(dc);
183 ExFreePool(Points);
184 return TRUE;
185 }
186
187 int
188 FASTCALL
189 IntGetGraphicsMode ( PDC dc )
190 {
191 ASSERT ( dc );
192 return dc->w.GraphicsMode;
193 }
194
195 int
196 STDCALL
197 NtGdiGetGraphicsMode ( HDC hDC )
198 {
199 PDC dc;
200 int GraphicsMode; // default to failure
201
202 dc = DC_LockDc ( hDC );
203 if (!dc)
204 {
205 SetLastWin32Error(ERROR_INVALID_HANDLE);
206 return 0;
207 }
208
209 GraphicsMode = dc->w.GraphicsMode;
210
211 DC_UnlockDc(dc);
212 return GraphicsMode;
213 }
214
215 BOOL
216 STDCALL
217 NtGdiGetWorldTransform(HDC hDC,
218 LPXFORM XForm)
219 {
220 PDC dc;
221 NTSTATUS Status;
222
223 dc = DC_LockDc ( hDC );
224 if (!dc)
225 {
226 SetLastWin32Error(ERROR_INVALID_HANDLE);
227 return FALSE;
228 }
229 if (!XForm)
230 {
231 DC_UnlockDc(dc);
232 SetLastWin32Error(ERROR_INVALID_PARAMETER);
233 return FALSE;
234 }
235
236 Status = MmCopyToCaller(XForm, &dc->w.xformWorld2Wnd, sizeof(XFORM));
237
238 DC_UnlockDc(dc);
239 return NT_SUCCESS(Status);
240 }
241
242 VOID
243 FASTCALL
244 CoordLPtoDP ( PDC Dc, LPPOINT Point )
245 {
246 FLOAT x, y;
247
248 ASSERT ( Dc );
249 ASSERT ( Point );
250
251 x = (FLOAT)Point->x;
252 y = (FLOAT)Point->y;
253 Point->x = x * Dc->w.xformWorld2Vport.eM11 +
254 y * Dc->w.xformWorld2Vport.eM21 + Dc->w.xformWorld2Vport.eDx;
255 Point->y = x * Dc->w.xformWorld2Vport.eM12 +
256 y * Dc->w.xformWorld2Vport.eM22 + Dc->w.xformWorld2Vport.eDy;
257 }
258
259 VOID
260 FASTCALL
261 IntLPtoDP ( PDC dc, LPPOINT Points, INT Count )
262 {
263 INT i;
264
265 ASSERT ( Points );
266
267 for ( i = 0; i < Count; i++ )
268 CoordLPtoDP ( dc, &Points[i] );
269 }
270
271 /*!
272 * Converts points from logical coordinates into device coordinates. Conversion depends on the mapping mode,
273 * world transfrom, viewport origin settings for the given device context.
274 * \param hDC device context.
275 * \param Points an array of POINT structures (in/out).
276 * \param Count number of elements in the array of POINT structures.
277 * \return TRUE if success.
278 */
279 BOOL STDCALL
280 NtGdiLPtoDP ( HDC hDC, LPPOINT UnsafePoints, INT Count )
281 {
282 PDC dc;
283 NTSTATUS Status;
284 LPPOINT Points;
285 ULONG Size;
286
287 dc = DC_LockDc(hDC);
288 if (!dc)
289 {
290 SetLastWin32Error(ERROR_INVALID_HANDLE);
291 return FALSE;
292 }
293
294 if (!UnsafePoints || Count <= 0)
295 {
296 DC_UnlockDc(dc);
297 SetLastWin32Error(ERROR_INVALID_PARAMETER);
298 return FALSE;
299 }
300
301 Size = Count * sizeof(POINT);
302
303 Points = (LPPOINT)ExAllocatePoolWithTag(PagedPool, Size, TAG_COORD);
304 if(!Points)
305 {
306 DC_UnlockDc(dc);
307 SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY);
308 return FALSE;
309 }
310
311 Status = MmCopyFromCaller(Points, UnsafePoints, Size);
312 if(!NT_SUCCESS(Status))
313 {
314 DC_UnlockDc(dc);
315 ExFreePool(Points);
316 SetLastNtError(Status);
317 return FALSE;
318 }
319
320 IntLPtoDP(dc, Points, Count);
321
322 Status = MmCopyToCaller(UnsafePoints, Points, Size);
323 if(!NT_SUCCESS(Status))
324 {
325 DC_UnlockDc(dc);
326 ExFreePool(Points);
327 SetLastNtError(Status);
328 return FALSE;
329 }
330
331 DC_UnlockDc(dc);
332 ExFreePool(Points);
333 return TRUE;
334 }
335
336 BOOL
337 STDCALL
338 NtGdiModifyWorldTransform(HDC hDC,
339 CONST LPXFORM UnsafeXForm,
340 DWORD Mode)
341 {
342 PDC dc;
343 XFORM SafeXForm;
344 NTSTATUS Status;
345
346 dc = DC_LockDc(hDC);
347 if (!dc)
348 {
349 SetLastWin32Error(ERROR_INVALID_HANDLE);
350 return FALSE;
351 }
352
353 if (!UnsafeXForm)
354 {
355 DC_UnlockDc(dc);
356 SetLastWin32Error(ERROR_INVALID_PARAMETER);
357 return FALSE;
358 }
359
360 Status = MmCopyFromCaller(&SafeXForm, UnsafeXForm, sizeof(XFORM));
361 if(!NT_SUCCESS(Status))
362 {
363 DC_UnlockDc(dc);
364 SetLastNtError(Status);
365 return FALSE;
366 }
367
368 switch(Mode)
369 {
370 case MWT_IDENTITY:
371 dc->w.xformWorld2Wnd.eM11 = 1.0f;
372 dc->w.xformWorld2Wnd.eM12 = 0.0f;
373 dc->w.xformWorld2Wnd.eM21 = 0.0f;
374 dc->w.xformWorld2Wnd.eM22 = 1.0f;
375 dc->w.xformWorld2Wnd.eDx = 0.0f;
376 dc->w.xformWorld2Wnd.eDy = 0.0f;
377 break;
378
379 case MWT_LEFTMULTIPLY:
380 IntGdiCombineTransform(&dc->w.xformWorld2Wnd, &SafeXForm, &dc->w.xformWorld2Wnd );
381 break;
382
383 case MWT_RIGHTMULTIPLY:
384 IntGdiCombineTransform(&dc->w.xformWorld2Wnd, &dc->w.xformWorld2Wnd, &SafeXForm);
385 break;
386
387 default:
388 DC_UnlockDc(dc);
389 SetLastWin32Error(ERROR_INVALID_PARAMETER);
390 return FALSE;
391 }
392
393 DC_UpdateXforms(dc);
394 DC_UnlockDc(dc);
395 return TRUE;
396 }
397
398 BOOL
399 STDCALL
400 NtGdiOffsetViewportOrgEx(HDC hDC,
401 int XOffset,
402 int YOffset,
403 LPPOINT UnsafePoint)
404 {
405 PDC dc;
406 POINT Point;
407 NTSTATUS Status;
408
409 dc = DC_LockDc ( hDC );
410 if(!dc)
411 {
412 SetLastWin32Error(ERROR_INVALID_HANDLE);
413 return FALSE;
414 }
415
416 if (UnsafePoint)
417 {
418 Point.x = dc->vportOrgX;
419 Point.y = dc->vportOrgY;
420 Status = MmCopyToCaller(UnsafePoint, &Point, sizeof(POINT));
421 if ( !NT_SUCCESS(Status) )
422 {
423 SetLastNtError(Status);
424 DC_UnlockDc(dc);
425 return FALSE;
426 }
427 }
428
429 dc->vportOrgX += XOffset;
430 dc->vportOrgY += YOffset;
431 DC_UpdateXforms(dc);
432
433 DC_UnlockDc(dc);
434 return TRUE;
435 }
436
437 BOOL
438 STDCALL
439 NtGdiOffsetWindowOrgEx(HDC hDC,
440 int XOffset,
441 int YOffset,
442 LPPOINT Point)
443 {
444 PDC dc;
445
446 dc = DC_LockDc(hDC);
447 if (!dc)
448 {
449 SetLastWin32Error(ERROR_INVALID_HANDLE);
450 return FALSE;
451 }
452
453 if (Point)
454 {
455 POINT SafePoint;
456 NTSTATUS Status;
457
458 SafePoint.x = dc->wndOrgX;
459 SafePoint.y = dc->wndOrgY;
460
461 Status = MmCopyToCaller(Point, &SafePoint, sizeof(POINT));
462 if(!NT_SUCCESS(Status))
463 {
464 SetLastNtError(Status);
465 DC_UnlockDc(dc);
466 return FALSE;
467 }
468 }
469
470 dc->wndOrgX += XOffset;
471 dc->wndOrgY += YOffset;
472
473 DC_UpdateXforms(dc);
474 DC_UnlockDc(dc);
475
476 return TRUE;
477 }
478
479 BOOL
480 STDCALL
481 NtGdiScaleViewportExtEx(HDC hDC,
482 int Xnum,
483 int Xdenom,
484 int Ynum,
485 int Ydenom,
486 LPSIZE Size)
487 {
488 UNIMPLEMENTED;
489 return FALSE;
490 }
491
492 BOOL
493 STDCALL
494 NtGdiScaleWindowExtEx(HDC hDC,
495 int Xnum,
496 int Xdenom,
497 int Ynum,
498 int Ydenom,
499 LPSIZE Size)
500 {
501 UNIMPLEMENTED;
502 return FALSE;
503 }
504
505 int
506 STDCALL
507 NtGdiSetGraphicsMode(HDC hDC,
508 int Mode)
509 {
510 INT ret;
511 PDC dc;
512
513 dc = DC_LockDc (hDC);
514 if (!dc)
515 {
516 SetLastWin32Error(ERROR_INVALID_HANDLE);
517 return 0;
518 }
519
520 /* One would think that setting the graphics mode to GM_COMPATIBLE
521 * would also reset the world transformation matrix to the unity
522 * matrix. However, in Windows, this is not the case. This doesn't
523 * make a lot of sense to me, but that's the way it is.
524 */
525
526 if ((Mode != GM_COMPATIBLE) && (Mode != GM_ADVANCED))
527 {
528 DC_UnlockDc(dc);
529 SetLastWin32Error(ERROR_INVALID_PARAMETER);
530 return 0;
531 }
532
533 ret = dc->w.GraphicsMode;
534 dc->w.GraphicsMode = Mode;
535 DC_UnlockDc(dc);
536 return ret;
537 }
538
539 int
540 STDCALL
541 NtGdiSetMapMode(HDC hDC,
542 int MapMode)
543 {
544 int PrevMapMode;
545 PDC dc;
546
547 dc = DC_LockDc(hDC);
548 if (!dc)
549 {
550 SetLastWin32Error(ERROR_INVALID_HANDLE);
551 return 0;
552 }
553
554 PrevMapMode = dc->w.MapMode;
555 dc->w.MapMode = MapMode;
556
557 DC_UnlockDc(dc);
558
559 return PrevMapMode;
560 }
561
562 BOOL
563 STDCALL
564 NtGdiSetViewportExtEx(HDC hDC,
565 int XExtent,
566 int YExtent,
567 LPSIZE Size)
568 {
569 PDC dc;
570
571 dc = DC_LockDc(hDC);
572 if ( !dc )
573 {
574 SetLastWin32Error(ERROR_INVALID_HANDLE);
575 return FALSE;
576 }
577
578 switch (dc->w.MapMode)
579 {
580 case MM_HIENGLISH:
581 case MM_HIMETRIC:
582 case MM_LOENGLISH:
583 case MM_LOMETRIC:
584 case MM_TEXT:
585 case MM_TWIPS:
586 DC_UnlockDc(dc);
587 return FALSE;
588
589 case MM_ISOTROPIC:
590 // Here we should (probably) check that SetWindowExtEx *really* has
591 // been called
592 break;
593 }
594
595 if (Size)
596 {
597 SIZE SafeSize;
598 NTSTATUS Status;
599
600 SafeSize.cx = dc->vportExtX;
601 SafeSize.cy = dc->vportExtY;
602
603 Status = MmCopyToCaller(Size, &SafeSize, sizeof(SIZE));
604 if(!NT_SUCCESS(Status))
605 {
606 SetLastNtError(Status);
607 DC_UnlockDc(dc);
608 return FALSE;
609 }
610 }
611
612 dc->vportExtX = XExtent;
613 dc->vportExtY = YExtent;
614
615 DC_UpdateXforms(dc);
616 DC_UnlockDc(dc);
617
618 return TRUE;
619 }
620
621 BOOL
622 STDCALL
623 NtGdiSetViewportOrgEx(HDC hDC,
624 int X,
625 int Y,
626 LPPOINT Point)
627 {
628 PDC dc;
629
630 dc = DC_LockDc(hDC);
631 if (!dc)
632 {
633 SetLastWin32Error(ERROR_INVALID_HANDLE);
634 return FALSE;
635 }
636
637 if (Point)
638 {
639 POINT SafePoint;
640 NTSTATUS Status;
641
642 SafePoint.x = dc->vportOrgX;
643 SafePoint.y = dc->vportOrgY;
644
645 Status = MmCopyToCaller(Point, &SafePoint, sizeof(POINT));
646 if(!NT_SUCCESS(Status))
647 {
648 SetLastNtError(Status);
649 DC_UnlockDc(dc);
650 return FALSE;
651 }
652 }
653
654 dc->vportOrgX = X;
655 dc->vportOrgY = Y;
656
657 DC_UpdateXforms(dc);
658 DC_UnlockDc(dc);
659
660 return TRUE;
661 }
662
663 BOOL
664 STDCALL
665 NtGdiSetWindowExtEx(HDC hDC,
666 int XExtent,
667 int YExtent,
668 LPSIZE Size)
669 {
670 PDC dc;
671
672 dc = DC_LockDc(hDC);
673 if (!dc)
674 {
675 SetLastWin32Error(ERROR_INVALID_HANDLE);
676 return FALSE;
677 }
678
679 switch (dc->w.MapMode)
680 {
681 case MM_HIENGLISH:
682 case MM_HIMETRIC:
683 case MM_LOENGLISH:
684 case MM_LOMETRIC:
685 case MM_TEXT:
686 case MM_TWIPS:
687 DC_UnlockDc(dc);
688 return FALSE;
689 }
690
691 if (Size)
692 {
693 SIZE SafeSize;
694 NTSTATUS Status;
695
696 SafeSize.cx = dc->wndExtX;
697 SafeSize.cy = dc->wndExtY;
698
699 Status = MmCopyToCaller(Size, &SafeSize, sizeof(SIZE));
700 if(!NT_SUCCESS(Status))
701 {
702 SetLastNtError(Status);
703 DC_UnlockDc(dc);
704 return FALSE;
705 }
706 }
707
708 dc->wndExtX = XExtent;
709 dc->wndExtY = YExtent;
710
711 DC_UpdateXforms(dc);
712 DC_UnlockDc(dc);
713
714 return TRUE;
715 }
716
717 BOOL
718 STDCALL
719 NtGdiSetWindowOrgEx(HDC hDC,
720 int X,
721 int Y,
722 LPPOINT Point)
723 {
724 PDC dc;
725
726 dc = DC_LockDc(hDC);
727 if (!dc)
728 {
729 SetLastWin32Error(ERROR_INVALID_HANDLE);
730 return FALSE;
731 }
732
733 if (Point)
734 {
735 POINT SafePoint;
736 NTSTATUS Status;
737
738 SafePoint.x = dc->wndOrgX;
739 SafePoint.y = dc->wndOrgY;
740
741 Status = MmCopyToCaller(Point, &SafePoint, sizeof(POINT));
742 if(!NT_SUCCESS(Status))
743 {
744 SetLastNtError(Status);
745 DC_UnlockDc(dc);
746 return FALSE;
747 }
748 }
749
750 dc->wndOrgX = X;
751 dc->wndOrgY = Y;
752
753 DC_UpdateXforms(dc);
754 DC_UnlockDc(dc);
755
756 return TRUE;
757 }
758
759 BOOL
760 STDCALL
761 NtGdiSetWorldTransform(HDC hDC,
762 CONST LPXFORM XForm)
763 {
764 PDC dc;
765 NTSTATUS Status;
766
767 dc = DC_LockDc (hDC);
768 if ( !dc )
769 {
770 SetLastWin32Error(ERROR_INVALID_HANDLE);
771 return FALSE;
772 }
773
774 if (!XForm)
775 {
776 DC_UnlockDc(dc);
777 /* Win doesn't set LastError */
778 return FALSE;
779 }
780
781 /* Check that graphics mode is GM_ADVANCED */
782 if ( dc->w.GraphicsMode != GM_ADVANCED )
783 {
784 DC_UnlockDc(dc);
785 return FALSE;
786 }
787
788 Status = MmCopyFromCaller(&dc->w.xformWorld2Wnd, XForm, sizeof(XFORM));
789 if(!NT_SUCCESS(Status))
790 {
791 DC_UnlockDc(dc);
792 return FALSE;
793 }
794
795 DC_UpdateXforms(dc);
796 DC_UnlockDc(dc);
797 return TRUE;
798 }
799
800 /* EOF */