xref: /haiku/headers/libs/agg/agg_trans_viewport.h (revision 95bac3fda53a4cb21880712d7b43f8c21db32a2e)
1 //----------------------------------------------------------------------------
2 // Anti-Grain Geometry - Version 2.2
3 // Copyright (C) 2002-2004 Maxim Shemanarev (http://www.antigrain.com)
4 //
5 // Permission to copy, use, modify, sell and distribute this software
6 // is granted provided this copyright notice appears in all copies.
7 // This software is provided "as is" without express or implied
8 // warranty, and with no claim as to its suitability for any purpose.
9 //
10 //----------------------------------------------------------------------------
11 // Contact: mcseem@antigrain.com
12 //          mcseemagg@yahoo.com
13 //          http://www.antigrain.com
14 //----------------------------------------------------------------------------
15 //
16 // Viewport transformer - simple orthogonal conversions from world coordinates
17 //                        to screen (device) ones.
18 //
19 //----------------------------------------------------------------------------
20 
21 #ifndef AGG_TRANS_VIEWPORT_INCLUDED
22 #define AGG_TRANS_VIEWPORT_INCLUDED
23 
24 #include <string.h>
25 #include "agg_basics.h"
26 
27 
28 namespace agg
29 {
30 
31     enum aspect_ratio_e
32     {
33         aspect_ratio_stretch,
34         aspect_ratio_meet,
35         aspect_ratio_slice
36     };
37 
38 
39     //----------------------------------------------------------trans_viewport
40     class trans_viewport
41     {
42     public:
43         //-------------------------------------------------------------------
44         trans_viewport() :
45             m_world_x1(0.0),
46             m_world_y1(0.0),
47             m_world_x2(1.0),
48             m_world_y2(1.0),
49             m_device_x1(0.0),
50             m_device_y1(0.0),
51             m_device_x2(1.0),
52             m_device_y2(1.0),
53             m_aspect(aspect_ratio_stretch),
54             m_align_x(0.5),
55             m_align_y(0.5),
56             m_wx1(0.0),
57             m_wy1(0.0),
58             m_wx2(1.0),
59             m_wy2(1.0),
60             m_dx1(0.0),
61             m_dy1(0.0),
62             m_kx(1.0),
63             m_ky(1.0)
64         {}
65 
66         //-------------------------------------------------------------------
67         void preserve_aspect_ratio(double alignx,
68                                    double aligny,
69                                    aspect_ratio_e aspect)
70         {
71             m_align_x = alignx;
72             m_align_y = aligny;
73             m_aspect  = aspect;
74             update();
75         }
76 
77         //-------------------------------------------------------------------
78         void device_viewport(double x1, double y1, double x2, double y2)
79         {
80             m_device_x1 = x1;
81             m_device_y1 = y1;
82             m_device_x2 = x2;
83             m_device_y2 = y2;
84             update();
85         }
86 
87         //-------------------------------------------------------------------
88         void world_viewport(double x1, double y1, double x2, double y2)
89         {
90             m_world_x1 = x1;
91             m_world_y1 = y1;
92             m_world_x2 = x2;
93             m_world_y2 = y2;
94             update();
95         }
96 
97         //-------------------------------------------------------------------
98         void device_viewport(double* x1, double* y1, double* x2, double* y2) const
99         {
100             *x1 = m_device_x1;
101             *y1 = m_device_y1;
102             *x2 = m_device_x2;
103             *y2 = m_device_y2;
104         }
105 
106         //-------------------------------------------------------------------
107         void world_viewport(double* x1, double* y1, double* x2, double* y2) const
108         {
109             *x1 = m_world_x1;
110             *y1 = m_world_y1;
111             *x2 = m_world_x2;
112             *y2 = m_world_y2;
113         }
114 
115         //-------------------------------------------------------------------
116         void world_viewport_actual(double* x1, double* y1,
117                                    double* x2, double* y2) const
118         {
119             *x1 = m_wx1;
120             *y1 = m_wy1;
121             *x2 = m_wx2;
122             *y2 = m_wy2;
123         }
124 
125         //-------------------------------------------------------------------
126         double align_x()              const { return m_align_x; }
127         double align_y()              const { return m_align_y; }
128         aspect_ratio_e aspect_ratio() const { return m_aspect; }
129 
130         //-------------------------------------------------------------------
131         void transform(double* x, double* y) const
132         {
133             *x = (*x - m_wx1) * m_kx + m_dx1;
134             *y = (*y - m_wy1) * m_ky + m_dy1;
135         }
136 
137         //-------------------------------------------------------------------
138         void inverse_transform(double* x, double* y) const
139         {
140             *x = (*x - m_dx1) / m_kx + m_wx1;
141             *y = (*y - m_dy1) / m_ky + m_wy1;
142         }
143 
144         //-------------------------------------------------------------------
145         double scale_x() const
146         {
147             return m_kx;
148         }
149 
150         //-------------------------------------------------------------------
151         double scale_y() const
152         {
153             return m_ky;
154         }
155 
156         //-------------------------------------------------------------------
157         double scale() const
158         {
159             return (m_kx + m_ky) * 0.5;
160         }
161 
162 
163         //-------------------------------------------------------------------
164         unsigned byte_size() const
165         {
166             return
167                 sizeof(m_world_x1) +
168                 sizeof(m_world_y1) +
169                 sizeof(m_world_x2) +
170                 sizeof(m_world_y2) +
171                 sizeof(m_device_x1) +
172                 sizeof(m_device_y1) +
173                 sizeof(m_device_x2) +
174                 sizeof(m_device_y2) +
175                 sizeof(m_aspect) +
176                 sizeof(m_align_x) +
177                 sizeof(m_align_y) +
178                 sizeof(m_wx1) +
179                 sizeof(m_wy1) +
180                 sizeof(m_wx2) +
181                 sizeof(m_wy2) +
182                 sizeof(m_dx1) +
183                 sizeof(m_dy1) +
184                 sizeof(m_kx) +
185                 sizeof(m_ky);
186         }
187 
188         void serialize(int8u* ptr) const
189         {
190             memcpy(ptr, &m_world_x1,  sizeof(m_world_x1));  ptr += sizeof(m_world_x1);
191             memcpy(ptr, &m_world_y1,  sizeof(m_world_y1));  ptr += sizeof(m_world_y1);
192             memcpy(ptr, &m_world_x2,  sizeof(m_world_x2));  ptr += sizeof(m_world_x2);
193             memcpy(ptr, &m_world_y2,  sizeof(m_world_y2));  ptr += sizeof(m_world_y2);
194             memcpy(ptr, &m_device_x1, sizeof(m_device_x1)); ptr += sizeof(m_device_x1);
195             memcpy(ptr, &m_device_y1, sizeof(m_device_y1)); ptr += sizeof(m_device_y1);
196             memcpy(ptr, &m_device_x2, sizeof(m_device_x2)); ptr += sizeof(m_device_x2);
197             memcpy(ptr, &m_device_y2, sizeof(m_device_y2)); ptr += sizeof(m_device_y2);
198             memcpy(ptr, &m_aspect,    sizeof(m_aspect));    ptr += sizeof(m_aspect);
199             memcpy(ptr, &m_align_x,   sizeof(m_align_x));   ptr += sizeof(m_align_x);
200             memcpy(ptr, &m_align_y,   sizeof(m_align_y));   ptr += sizeof(m_align_y);
201             memcpy(ptr, &m_wx1,       sizeof(m_wx1));       ptr += sizeof(m_wx1);
202             memcpy(ptr, &m_wy1,       sizeof(m_wy1));       ptr += sizeof(m_wy1);
203             memcpy(ptr, &m_wx2,       sizeof(m_wx2));       ptr += sizeof(m_wx2);
204             memcpy(ptr, &m_wy2,       sizeof(m_wy2));       ptr += sizeof(m_wy2);
205             memcpy(ptr, &m_dx1,       sizeof(m_dx1));       ptr += sizeof(m_dx1);
206             memcpy(ptr, &m_dy1,       sizeof(m_dy1));       ptr += sizeof(m_dy1);
207             memcpy(ptr, &m_kx,        sizeof(m_kx));        ptr += sizeof(m_kx);
208             memcpy(ptr, &m_ky,        sizeof(m_ky));        ptr += sizeof(m_ky);
209         }
210 
211         void deserialize(const int8u* ptr)
212         {
213             memcpy(&m_world_x1,  ptr, sizeof(m_world_x1));  ptr += sizeof(m_world_x1);
214             memcpy(&m_world_y1,  ptr, sizeof(m_world_y1));  ptr += sizeof(m_world_y1);
215             memcpy(&m_world_x2,  ptr, sizeof(m_world_x2));  ptr += sizeof(m_world_x2);
216             memcpy(&m_world_y2,  ptr, sizeof(m_world_y2));  ptr += sizeof(m_world_y2);
217             memcpy(&m_device_x1, ptr, sizeof(m_device_x1)); ptr += sizeof(m_device_x1);
218             memcpy(&m_device_y1, ptr, sizeof(m_device_y1)); ptr += sizeof(m_device_y1);
219             memcpy(&m_device_x2, ptr, sizeof(m_device_x2)); ptr += sizeof(m_device_x2);
220             memcpy(&m_device_y2, ptr, sizeof(m_device_y2)); ptr += sizeof(m_device_y2);
221             memcpy(&m_aspect,    ptr, sizeof(m_aspect));    ptr += sizeof(m_aspect);
222             memcpy(&m_align_x,   ptr, sizeof(m_align_x));   ptr += sizeof(m_align_x);
223             memcpy(&m_align_y,   ptr, sizeof(m_align_y));   ptr += sizeof(m_align_y);
224             memcpy(&m_wx1,       ptr, sizeof(m_wx1));       ptr += sizeof(m_wx1);
225             memcpy(&m_wy1,       ptr, sizeof(m_wy1));       ptr += sizeof(m_wy1);
226             memcpy(&m_wx2,       ptr, sizeof(m_wx2));       ptr += sizeof(m_wx2);
227             memcpy(&m_wy2,       ptr, sizeof(m_wy2));       ptr += sizeof(m_wy2);
228             memcpy(&m_dx1,       ptr, sizeof(m_dx1));       ptr += sizeof(m_dx1);
229             memcpy(&m_dy1,       ptr, sizeof(m_dy1));       ptr += sizeof(m_dy1);
230             memcpy(&m_kx,        ptr, sizeof(m_kx));        ptr += sizeof(m_kx);
231             memcpy(&m_ky,        ptr, sizeof(m_ky));        ptr += sizeof(m_ky);
232         }
233 
234     private:
235         void update();
236 
237         double         m_world_x1;
238         double         m_world_y1;
239         double         m_world_x2;
240         double         m_world_y2;
241         double         m_device_x1;
242         double         m_device_y1;
243         double         m_device_x2;
244         double         m_device_y2;
245         aspect_ratio_e m_aspect;
246         double         m_align_x;
247         double         m_align_y;
248         double         m_wx1;
249         double         m_wy1;
250         double         m_wx2;
251         double         m_wy2;
252         double         m_dx1;
253         double         m_dy1;
254         double         m_kx;
255         double         m_ky;
256     };
257 
258 
259 
260     //-----------------------------------------------------------------------
261     inline void trans_viewport::update()
262     {
263         double world_x1  = m_world_x1;
264         double world_y1  = m_world_y1;
265         double world_x2  = m_world_x2;
266         double world_y2  = m_world_y2;
267         double device_x1 = m_device_x1;
268         double device_y1 = m_device_y1;
269         double device_x2 = m_device_x2;
270         double device_y2 = m_device_y2;
271         if(m_aspect != aspect_ratio_stretch)
272         {
273             double d;
274             m_kx = (device_x2 - device_x1) / (world_x2 - world_x1);
275             m_ky = (device_y2 - device_y1) / (world_y2 - world_y1);
276 
277             if((m_aspect == aspect_ratio_meet) == (m_kx < m_ky))
278             {
279                 d         = (world_y2 - world_y1) * m_ky / m_kx;
280                 world_y1 += (world_y2 - world_y1 - d) * m_align_y;
281                 world_y2  =  world_y1 + d;
282             }
283             else
284             {
285                 d         = (world_x2 - world_x1) * m_kx / m_ky;
286                 world_x1 += (world_x2 - world_x1 - d) * m_align_x;
287                 world_x2  =  world_x1 + d;
288             }
289         }
290         m_wx1 = world_x1;
291         m_wy1 = world_y1;
292         m_wx2 = world_x2;
293         m_wy2 = world_y2;
294         m_dx1 = device_x1;
295         m_dy1 = device_y1;
296         m_kx  = (device_x2 - device_x1) / (world_x2 - world_x1);
297         m_ky  = (device_y2 - device_y1) / (world_y2 - world_y1);
298     }
299 
300 
301 }
302 
303 
304 #endif
305