update for HEAD-2003091401
[reactos.git] / 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 <windows.h>
31 #include <ddk/ntddk.h>
32 #include <internal/safe.h>
33 #include <win32k/coord.h>
34 #include <win32k/dc.h>
35 #include <include/error.h>
36 #define NDEBUG
37 #include <win32k/debug1.h>
38
39 /* FUNCTIONS *****************************************************************/
40
41 BOOL STDCALL NtGdiCombineTransform(LPXFORM  UnsafeXFormResult,
42                            CONST LPXFORM  Unsafexform1,
43                            CONST LPXFORM  Unsafexform2)
44 {
45   XFORM  xformTemp;
46   XFORM  xform1, xform2;
47
48   /* Check for illegal parameters */
49   if (!UnsafeXFormResult || !Unsafexform1 || !Unsafexform2)
50   {
51     return  FALSE;
52   }
53
54   MmCopyFromCaller( &xform1, Unsafexform1, sizeof(XFORM) );
55   MmCopyFromCaller( &xform2, Unsafexform2, sizeof(XFORM) );
56
57   /* Create the result in a temporary XFORM, since xformResult may be
58    * equal to xform1 or xform2 */
59   xformTemp.eM11 = xform1.eM11 * xform2.eM11 + xform1.eM12 * xform2.eM21;
60   xformTemp.eM12 = xform1.eM11 * xform2.eM12 + xform1.eM12 * xform2.eM22;
61   xformTemp.eM21 = xform1.eM21 * xform2.eM11 + xform1.eM22 * xform2.eM21;
62   xformTemp.eM22 = xform1.eM21 * xform2.eM12 + xform1.eM22 * xform2.eM22;
63   xformTemp.eDx  = xform1.eDx  * xform2.eM11 + xform1.eDy  * xform2.eM21 + xform2.eDx;
64   xformTemp.eDy  = xform1.eDx  * xform2.eM12 + xform1.eDy  * xform2.eM22 + xform2.eDy;
65
66   /* Copy the result to xformResult */
67   MmCopyToCaller(  UnsafeXFormResult, &xformTemp, sizeof(XFORM) );
68
69   return  TRUE;
70 }
71
72 VOID STATIC FASTCALL
73 CoordDPtoLP(PDC Dc, LPPOINT Point)
74 {
75 FLOAT x, y;
76   x = (FLOAT)Point->x;
77   y = (FLOAT)Point->y;
78   Point->x = x * Dc->w.xformVport2World.eM11 +
79     y * Dc->w.xformVport2World.eM21 + Dc->w.xformVport2World.eDx;
80   Point->y = x * Dc->w.xformVport2World.eM12 +
81     y * Dc->w.xformVport2World.eM22 + Dc->w.xformVport2World.eDy;
82 }
83
84 /*!
85  * Converts points from device coordinates into logical coordinates. Conversion depends on the mapping mode,
86  * world transfrom, viewport origin settings for the given device context.
87  * \param       hDC             device context.
88  * \param       Points  an array of POINT structures (in/out).
89  * \param       Count   number of elements in the array of POINT structures.
90  * \return  TRUE        if success.
91 */
92 BOOL STDCALL
93 NtGdiDPtoLP(HDC  hDC,
94            LPPOINT  UnsafePoints,
95            int  Count)
96 {
97   PDC dc;
98   INT i;
99   LPPOINT Points = (LPPOINT) ExAllocatePool( PagedPool, Count*sizeof(POINT));
100   BOOL ret = FALSE; // default to failure
101
102   ASSERT(Points);
103   if ( !Points )
104     return ret;
105
106   MmCopyFromCaller( Points, UnsafePoints, Count*sizeof(POINT) );
107
108   dc = DC_LockDc (hDC);
109   if ( dc )
110   {
111     ret = TRUE;
112     if ( dc->w.vport2WorldValid )
113     {
114       for (i = 0; i < Count; i++)
115         {
116           CoordDPtoLP ( dc, &Points[i] );
117         }
118     }
119
120     DC_UnlockDc( hDC );
121
122     MmCopyToCaller(  UnsafePoints, Points, Count*sizeof(POINT) );
123
124   }
125
126   ExFreePool ( Points );
127
128   return(TRUE);
129 }
130
131 int
132 FASTCALL
133 IntGetGraphicsMode ( PDC dc )
134 {
135   ASSERT ( dc );
136   return dc->w.GraphicsMode;
137 }
138
139 int
140 STDCALL
141 NtGdiGetGraphicsMode ( HDC hDC )
142 {
143   PDC dc = DC_LockDc ( hDC );
144   int GraphicsMode = 0; // default to failure
145
146   if ( dc )
147   {
148     GraphicsMode = dc->w.GraphicsMode;
149     DC_UnlockDc ( hDC );
150   }
151
152   return GraphicsMode;
153 }
154
155 BOOL
156 STDCALL
157 NtGdiGetWorldTransform(HDC  hDC,
158                       LPXFORM  XForm)
159 {
160   PDC  dc;
161
162   if (!XForm)
163     return FALSE;
164
165   dc = DC_LockDc (hDC);
166   if (!dc)
167     return FALSE;
168
169   *XForm = dc->w.xformWorld2Wnd;
170
171   DC_UnlockDc ( hDC );
172
173   return  TRUE;
174 }
175
176 VOID
177 FASTCALL
178 CoordLPtoDP ( PDC Dc, LPPOINT Point )
179 {
180   FLOAT x, y;
181
182   ASSERT ( Dc );
183   ASSERT ( Point );
184
185   x = (FLOAT)Point->x;
186   y = (FLOAT)Point->y;
187   Point->x = x * Dc->w.xformWorld2Vport.eM11 +
188     y * Dc->w.xformWorld2Vport.eM21 + Dc->w.xformWorld2Vport.eDx;
189   Point->y = x * Dc->w.xformWorld2Vport.eM12 +
190     y * Dc->w.xformWorld2Vport.eM22 + Dc->w.xformWorld2Vport.eDy;
191 }
192
193 VOID
194 FASTCALL
195 IntLPtoDP ( PDC dc, LPPOINT Points, INT Count )
196 {
197   INT i;
198
199   ASSERT ( Points );
200
201   for ( i = 0; i < Count; i++ )
202     CoordLPtoDP ( dc, &Points[i] );
203 }
204
205 /*!
206  * Converts points from logical coordinates into device coordinates. Conversion depends on the mapping mode,
207  * world transfrom, viewport origin settings for the given device context.
208  * \param       hDC             device context.
209  * \param       Points  an array of POINT structures (in/out).
210  * \param       Count   number of elements in the array of POINT structures.
211  * \return  TRUE        if success.
212 */
213 BOOL STDCALL
214 NtGdiLPtoDP ( HDC hDC, LPPOINT UnsafePoints, INT Count )
215 {
216   PDC dc;
217   LPPOINT Points = (LPPOINT)ExAllocatePool ( PagedPool, Count*sizeof(POINT) );
218   BOOL    ret = FALSE; // default to failure
219
220   ASSERT(Points);
221   if ( !Points )
222     return FALSE;
223
224   dc = DC_LockDc ( hDC );
225
226   if ( dc )
227   {
228     ret = TRUE;
229
230     MmCopyFromCaller( Points, UnsafePoints, Count*sizeof(POINT) );
231
232     IntLPtoDP ( dc, Points, Count );
233
234     MmCopyToCaller ( UnsafePoints, Points, Count*sizeof(POINT) );
235
236     DC_UnlockDc ( hDC );
237   }
238
239   ExFreePool ( Points );
240
241   return ret;
242 }
243
244 BOOL
245 STDCALL
246 NtGdiModifyWorldTransform(HDC            hDC,
247                           CONST LPXFORM  UnsafeXForm,
248                           DWORD          Mode)
249 {
250   PDC  dc;
251   LPXFORM XForm = (LPXFORM) ExAllocatePool( PagedPool, sizeof( XFORM ) );
252   BOOL ret = FALSE; // default to failure
253
254   ASSERT( XForm );
255   if (!XForm)
256     return FALSE;
257
258   MmCopyFromCaller( XForm, UnsafeXForm, sizeof( XFORM ) );
259
260   dc = DC_LockDc (hDC);
261   if ( dc )
262   {
263     /* Check that graphics mode is GM_ADVANCED */
264     if ( dc->w.GraphicsMode == GM_ADVANCED )
265     {
266       ret = TRUE; // switch to a default of success
267       switch (Mode)
268       {
269         case MWT_IDENTITY:
270           dc->w.xformWorld2Wnd.eM11 = 1.0f;
271           dc->w.xformWorld2Wnd.eM12 = 0.0f;
272           dc->w.xformWorld2Wnd.eM21 = 0.0f;
273           dc->w.xformWorld2Wnd.eM22 = 1.0f;
274           dc->w.xformWorld2Wnd.eDx  = 0.0f;
275           dc->w.xformWorld2Wnd.eDy  = 0.0f;
276           break;
277
278         case MWT_LEFTMULTIPLY:
279           NtGdiCombineTransform(&dc->w.xformWorld2Wnd, XForm, &dc->w.xformWorld2Wnd );
280           break;
281
282         case MWT_RIGHTMULTIPLY:
283           NtGdiCombineTransform(&dc->w.xformWorld2Wnd, &dc->w.xformWorld2Wnd, XForm);
284           break;
285
286         default:
287           ret = FALSE;
288           break;
289       }
290       if ( ret )
291         DC_UpdateXforms ( dc );
292     }
293     DC_UnlockDc ( hDC );
294   }
295   ExFreePool ( XForm );
296   return ret;
297 }
298
299 BOOL
300 STDCALL
301 NtGdiOffsetViewportOrgEx(HDC hDC,
302                         int XOffset,
303                         int YOffset,
304                         LPPOINT UnsafePoint)
305 {
306   PDC      dc;
307   POINT    Point;
308   NTSTATUS Status;
309   BOOL     ret = FALSE; // default to failure
310
311   dc = DC_LockDc ( hDC );
312   if ( dc )
313   {
314     ret = TRUE;
315     if (NULL != UnsafePoint)
316       {
317         Point.x = dc->vportOrgX;
318         Point.y = dc->vportOrgY;
319         Status = MmCopyToCaller(UnsafePoint, &Point, sizeof(POINT));
320         if ( !NT_SUCCESS(Status) )
321           {
322             SetLastNtError(Status);
323             ret = FALSE;
324           }
325       }
326
327     if ( ret )
328     {
329       dc->vportOrgX += XOffset;
330       dc->vportOrgY += YOffset;
331       DC_UpdateXforms(dc);
332
333       dc->w.DCOrgX += XOffset;
334       dc->w.DCOrgY += YOffset;
335     }
336
337     DC_UnlockDc ( hDC );
338   }
339   return TRUE;
340 }
341
342 BOOL
343 STDCALL
344 NtGdiOffsetWindowOrgEx(HDC  hDC,
345                       int  XOffset,
346                       int  YOffset,
347                       LPPOINT  Point)
348 {
349   PDC dc;
350
351   dc = DC_LockDc(hDC);
352   if (!dc)
353     {
354       return FALSE;
355     }
356
357   if (Point)
358     {
359       Point->x = dc->wndOrgX;
360       Point->y = dc->wndOrgY;
361     }
362
363   dc->wndOrgX += XOffset;
364   dc->wndOrgY += YOffset;
365
366   DC_UnlockDc(hDC);
367
368   return TRUE;
369 }
370
371 BOOL
372 STDCALL
373 NtGdiScaleViewportExtEx(HDC  hDC,
374                              int  Xnum,
375                              int  Xdenom,
376                              int  Ynum,
377                              int  Ydenom,
378                              LPSIZE  Size)
379 {
380   UNIMPLEMENTED;
381 }
382
383 BOOL
384 STDCALL
385 NtGdiScaleWindowExtEx(HDC  hDC,
386                            int  Xnum,
387                            int  Xdenom,
388                            int  Ynum,
389                            int  Ydenom,
390                            LPSIZE  Size)
391 {
392   UNIMPLEMENTED;
393 }
394
395 int
396 STDCALL
397 NtGdiSetGraphicsMode(HDC  hDC,
398                     int  Mode)
399 {
400   INT ret;
401   PDC dc;
402
403   dc = DC_LockDc (hDC);
404   if (!dc)
405   {
406     return 0;
407   }
408
409   /* One would think that setting the graphics mode to GM_COMPATIBLE
410    * would also reset the world transformation matrix to the unity
411    * matrix. However, in Windows, this is not the case. This doesn't
412    * make a lot of sense to me, but that's the way it is.
413    */
414
415   if ((Mode != GM_COMPATIBLE) && (Mode != GM_ADVANCED))
416     {
417       DC_UnlockDc( hDC );
418       return 0;
419     }
420
421   ret = dc->w.GraphicsMode;
422   dc->w.GraphicsMode = Mode;
423   DC_UnlockDc( hDC );
424   return  ret;
425 }
426
427 int
428 STDCALL
429 NtGdiSetMapMode(HDC  hDC,
430                 int  MapMode)
431 {
432   int PrevMapMode;
433   PDC dc;
434
435   dc = DC_LockDc(hDC);
436   if (!dc)
437     return 0;
438
439   PrevMapMode = dc->w.MapMode;
440   dc->w.MapMode = MapMode;
441
442   DC_UnlockDc ( hDC );
443
444   return PrevMapMode;
445 }
446
447 BOOL
448 STDCALL
449 NtGdiSetViewportExtEx(HDC  hDC,
450                       int  XExtent,
451                       int  YExtent,
452                       LPSIZE  Size)
453 {
454   PDC dc;
455
456   dc = DC_LockDc(hDC);
457   if ( !dc )
458     return FALSE;
459
460   switch (dc->w.MapMode)
461     {
462       case MM_HIENGLISH:
463       case MM_HIMETRIC:
464       case MM_LOENGLISH:
465       case MM_LOMETRIC:
466       case MM_TEXT:
467       case MM_TWIPS:
468         DC_UnlockDc(hDC);
469         return FALSE;
470
471       case MM_ISOTROPIC:
472         // Here we should (probably) check that SetWindowExtEx *really* has
473         // been called
474         break;
475     }
476
477   if (Size)
478     {
479       Size->cx = dc->vportExtX;
480       Size->cy = dc->vportExtY;
481     }
482
483   dc->vportExtX = XExtent;
484   dc->vportExtY = YExtent;
485
486   DC_UnlockDc(hDC);
487
488   return TRUE;
489 }
490
491 BOOL
492 STDCALL
493 NtGdiSetViewportOrgEx(HDC  hDC,
494                      int  X,
495                      int  Y,
496                      LPPOINT  Point)
497 {
498   PDC dc;
499
500   dc = DC_LockDc(hDC);
501   if (!dc)
502     {
503       return FALSE;
504     }
505
506   if (Point)
507     {
508       Point->x = dc->vportOrgX;
509       Point->y = dc->vportOrgY;
510     }
511
512   dc->vportOrgX = X;
513   dc->vportOrgY = Y;
514
515   DC_UnlockDc(hDC);
516
517   return TRUE;
518 }
519
520 BOOL
521 STDCALL
522 NtGdiSetWindowExtEx(HDC  hDC,
523                    int  XExtent,
524                    int  YExtent,
525                    LPSIZE  Size)
526 {
527   PDC dc;
528
529   dc = DC_LockDc(hDC);
530   if (!dc)
531     {
532       return FALSE;
533     }
534
535   switch (dc->w.MapMode)
536     {
537       case MM_HIENGLISH:
538       case MM_HIMETRIC:
539       case MM_LOENGLISH:
540       case MM_LOMETRIC:
541       case MM_TEXT:
542       case MM_TWIPS:
543         DC_UnlockDc(hDC);
544         return FALSE;
545     }
546
547   if (Size)
548     {
549       Size->cx = dc->wndExtX;
550       Size->cy = dc->wndExtY;
551     }
552
553   dc->wndExtX = XExtent;
554   dc->wndExtY = YExtent;
555
556   DC_UnlockDc(hDC);
557
558   return TRUE;
559 }
560
561 BOOL
562 STDCALL
563 NtGdiSetWindowOrgEx(HDC  hDC,
564                    int  X,
565                    int  Y,
566                    LPPOINT  Point)
567 {
568   PDC dc;
569
570   dc = DC_LockDc(hDC);
571   if (!dc)
572     {
573       return FALSE;
574     }
575
576   if (Point)
577     {
578       Point->x = dc->wndOrgX;
579       Point->y = dc->wndOrgY;
580     }
581
582   dc->wndOrgX = X;
583   dc->wndOrgY = Y;
584
585   DC_UnlockDc(hDC);
586
587   return TRUE;
588 }
589
590 BOOL
591 STDCALL
592 NtGdiSetWorldTransform(HDC  hDC,
593                       CONST LPXFORM  XForm)
594 {
595   PDC  dc;
596
597   if (!XForm)
598     return  FALSE;
599
600   dc = DC_LockDc (hDC);
601   if ( !dc )
602   {
603     return  FALSE;
604   }
605
606   /* Check that graphics mode is GM_ADVANCED */
607   if ( dc->w.GraphicsMode != GM_ADVANCED )
608   {
609     DC_UnlockDc( hDC );
610     return  FALSE;
611   }
612   dc->w.xformWorld2Wnd = *XForm;
613   DC_UpdateXforms (dc);
614   DC_UnlockDc( hDC );
615   return  TRUE;
616 }
617
618 /* EOF */