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