| 1 | ///////////////////////////////////////////////////////////////////////////// |
| 2 | // Name: dc.cpp |
| 3 | // Purpose: wxDC class |
| 4 | // Author: AUTHOR |
| 5 | // Modified by: |
| 6 | // Created: 01/02/97 |
| 7 | // RCS-ID: $Id$ |
| 8 | // Copyright: (c) AUTHOR |
| 9 | // Licence: wxWindows licence |
| 10 | ///////////////////////////////////////////////////////////////////////////// |
| 11 | |
| 12 | #ifdef __GNUG__ |
| 13 | #pragma implementation "dc.h" |
| 14 | #endif |
| 15 | |
| 16 | #include "wx/dc.h" |
| 17 | |
| 18 | IMPLEMENT_ABSTRACT_CLASS(wxDC, wxObject) |
| 19 | |
| 20 | //----------------------------------------------------------------------------- |
| 21 | // constants |
| 22 | //----------------------------------------------------------------------------- |
| 23 | |
| 24 | #define mm2inches 0.0393700787402 |
| 25 | #define inches2mm 25.4 |
| 26 | #define mm2twips 56.6929133859 |
| 27 | #define twips2mm 0.0176388888889 |
| 28 | #define mm2pt 2.83464566929 |
| 29 | #define pt2mm 0.352777777778 |
| 30 | |
| 31 | //----------------------------------------------------------------------------- |
| 32 | // wxDC |
| 33 | //----------------------------------------------------------------------------- |
| 34 | |
| 35 | IMPLEMENT_ABSTRACT_CLASS(wxDC,wxObject) |
| 36 | |
| 37 | wxDC::wxDC(void) |
| 38 | { |
| 39 | m_ok = FALSE; |
| 40 | m_optimize = FALSE; |
| 41 | m_autoSetting = FALSE; |
| 42 | m_colour = TRUE; |
| 43 | m_clipping = FALSE; |
| 44 | |
| 45 | m_mm_to_pix_x = 1.0; |
| 46 | m_mm_to_pix_y = 1.0; |
| 47 | |
| 48 | m_logicalOriginX = 0; |
| 49 | m_logicalOriginY = 0; |
| 50 | m_deviceOriginX = 0; |
| 51 | m_deviceOriginY = 0; |
| 52 | m_internalDeviceOriginX = 0; |
| 53 | m_internalDeviceOriginY = 0; |
| 54 | m_externalDeviceOriginX = 0; |
| 55 | m_externalDeviceOriginY = 0; |
| 56 | |
| 57 | m_logicalScaleX = 1.0; |
| 58 | m_logicalScaleY = 1.0; |
| 59 | m_userScaleX = 1.0; |
| 60 | m_userScaleY = 1.0; |
| 61 | m_scaleX = 1.0; |
| 62 | m_scaleY = 1.0; |
| 63 | |
| 64 | m_mappingMode = wxMM_TEXT; |
| 65 | m_needComputeScaleX = FALSE; |
| 66 | m_needComputeScaleY = FALSE; |
| 67 | |
| 68 | m_signX = 1; // default x-axis left to right |
| 69 | m_signY = 1; // default y-axis top down |
| 70 | |
| 71 | m_maxX = m_maxY = -100000; |
| 72 | m_minY = m_minY = 100000; |
| 73 | |
| 74 | m_logicalFunction = wxCOPY; |
| 75 | // m_textAlignment = wxALIGN_TOP_LEFT; |
| 76 | m_backgroundMode = wxTRANSPARENT; |
| 77 | |
| 78 | m_textForegroundColour = *wxBLACK; |
| 79 | m_textBackgroundColour = *wxWHITE; |
| 80 | m_pen = *wxBLACK_PEN; |
| 81 | m_font = *wxNORMAL_FONT; |
| 82 | m_brush = *wxTRANSPARENT_BRUSH; |
| 83 | m_backgroundBrush = *wxWHITE_BRUSH; |
| 84 | |
| 85 | // m_palette = wxAPP_COLOURMAP; |
| 86 | }; |
| 87 | |
| 88 | wxDC::~wxDC(void) |
| 89 | { |
| 90 | }; |
| 91 | |
| 92 | void wxDC::DrawIcon( const wxIcon &WXUNUSED(icon), long WXUNUSED(x), long WXUNUSED(y), bool WXUNUSED(useMask) ) |
| 93 | { |
| 94 | }; |
| 95 | |
| 96 | void wxDC::DrawPoint( wxPoint& point ) |
| 97 | { |
| 98 | DrawPoint( point.x, point.y ); |
| 99 | }; |
| 100 | |
| 101 | void wxDC::DrawPolygon( wxList *list, long xoffset, long yoffset, int fillStyle ) |
| 102 | { |
| 103 | int n = list->Number(); |
| 104 | wxPoint *points = new wxPoint[n]; |
| 105 | |
| 106 | int i = 0; |
| 107 | for( wxNode *node = list->First(); node; node = node->Next() ) |
| 108 | { |
| 109 | wxPoint *point = (wxPoint *)node->Data(); |
| 110 | points[i].x = point->x; |
| 111 | points[i++].y = point->y; |
| 112 | }; |
| 113 | DrawPolygon( n, points, xoffset, yoffset, fillStyle ); |
| 114 | delete[] points; |
| 115 | }; |
| 116 | |
| 117 | void wxDC::DrawLines( wxList *list, long xoffset, long yoffset ) |
| 118 | { |
| 119 | int n = list->Number(); |
| 120 | wxPoint *points = new wxPoint[n]; |
| 121 | |
| 122 | int i = 0; |
| 123 | for( wxNode *node = list->First(); node; node = node->Next() ) |
| 124 | { |
| 125 | wxPoint *point = (wxPoint *)node->Data(); |
| 126 | points[i].x = point->x; |
| 127 | points[i++].y = point->y; |
| 128 | }; |
| 129 | DrawLines( n, points, xoffset, yoffset ); |
| 130 | delete []points; |
| 131 | }; |
| 132 | |
| 133 | void wxDC::DrawSpline( long x1, long y1, long x2, long y2, long x3, long y3 ) |
| 134 | { |
| 135 | wxList list; |
| 136 | list.Append( (wxObject*)new wxPoint(x1, y1) ); |
| 137 | list.Append( (wxObject*)new wxPoint(x2, y2) ); |
| 138 | list.Append( (wxObject*)new wxPoint(x3, y3) ); |
| 139 | DrawSpline(&list); |
| 140 | wxNode *node = list.First(); |
| 141 | while (node) |
| 142 | { |
| 143 | wxPoint *p = (wxPoint*)node->Data(); |
| 144 | delete p; |
| 145 | node = node->Next(); |
| 146 | }; |
| 147 | }; |
| 148 | |
| 149 | void wxDC::DrawSpline( wxList *points ) |
| 150 | { |
| 151 | DrawOpenSpline( points ); |
| 152 | }; |
| 153 | |
| 154 | void wxDC::DrawSpline( int n, wxPoint points[] ) |
| 155 | { |
| 156 | wxList list; |
| 157 | for (int i = 0; i < n; i++) list.Append( (wxObject*)&points[i] ); |
| 158 | DrawSpline( &list ); |
| 159 | }; |
| 160 | |
| 161 | void wxDC::SetClippingRegion( long x, long y, long width, long height ) |
| 162 | { |
| 163 | m_clipping = TRUE; |
| 164 | m_clipX1 = x; |
| 165 | m_clipY1 = y; |
| 166 | m_clipX2 = x + width; |
| 167 | m_clipY2 = y + height; |
| 168 | }; |
| 169 | |
| 170 | void wxDC::DestroyClippingRegion(void) |
| 171 | { |
| 172 | m_clipping = FALSE; |
| 173 | }; |
| 174 | |
| 175 | void wxDC::GetClippingBox( long *x, long *y, long *width, long *height ) const |
| 176 | { |
| 177 | if (m_clipping) |
| 178 | { |
| 179 | if (x) *x = m_clipX1; |
| 180 | if (y) *y = m_clipY1; |
| 181 | if (width) *width = (m_clipX2 - m_clipX1); |
| 182 | if (height) *height = (m_clipY2 - m_clipY1); |
| 183 | } |
| 184 | else |
| 185 | *x = *y = *width = *height = 0; |
| 186 | }; |
| 187 | |
| 188 | void wxDC::GetSize( int* width, int* height ) const |
| 189 | { |
| 190 | *width = m_maxX-m_minX; |
| 191 | *height = m_maxY-m_minY; |
| 192 | }; |
| 193 | |
| 194 | void wxDC::GetSizeMM( long* width, long* height ) const |
| 195 | { |
| 196 | int w = 0; |
| 197 | int h = 0; |
| 198 | GetSize( &w, &h ); |
| 199 | *width = long( double(w) / (m_scaleX*m_mm_to_pix_x) ); |
| 200 | *height = long( double(h) / (m_scaleY*m_mm_to_pix_y) ); |
| 201 | }; |
| 202 | |
| 203 | void wxDC::SetTextForeground( const wxColour &col ) |
| 204 | { |
| 205 | if (!Ok()) return; |
| 206 | m_textForegroundColour = col; |
| 207 | }; |
| 208 | |
| 209 | void wxDC::SetTextBackground( const wxColour &col ) |
| 210 | { |
| 211 | if (!Ok()) return; |
| 212 | m_textBackgroundColour = col; |
| 213 | }; |
| 214 | |
| 215 | void wxDC::SetMapMode( int mode ) |
| 216 | { |
| 217 | switch (mode) |
| 218 | { |
| 219 | case wxMM_TWIPS: |
| 220 | SetLogicalScale( twips2mm*m_mm_to_pix_x, twips2mm*m_mm_to_pix_y ); |
| 221 | break; |
| 222 | case wxMM_POINTS: |
| 223 | SetLogicalScale( pt2mm*m_mm_to_pix_x, pt2mm*m_mm_to_pix_y ); |
| 224 | break; |
| 225 | case wxMM_METRIC: |
| 226 | SetLogicalScale( m_mm_to_pix_x, m_mm_to_pix_y ); |
| 227 | break; |
| 228 | case wxMM_LOMETRIC: |
| 229 | SetLogicalScale( m_mm_to_pix_x/10.0, m_mm_to_pix_y/10.0 ); |
| 230 | break; |
| 231 | default: |
| 232 | case wxMM_TEXT: |
| 233 | SetLogicalScale( 1.0, 1.0 ); |
| 234 | break; |
| 235 | }; |
| 236 | if (mode != wxMM_TEXT) |
| 237 | { |
| 238 | m_needComputeScaleX = TRUE; |
| 239 | m_needComputeScaleY = TRUE; |
| 240 | }; |
| 241 | }; |
| 242 | |
| 243 | void wxDC::SetUserScale( double x, double y ) |
| 244 | { |
| 245 | // allow negative ? -> no |
| 246 | m_userScaleX = x; |
| 247 | m_userScaleY = y; |
| 248 | ComputeScaleAndOrigin(); |
| 249 | }; |
| 250 | |
| 251 | void wxDC::GetUserScale( double *x, double *y ) |
| 252 | { |
| 253 | if (x) *x = m_userScaleX; |
| 254 | if (y) *y = m_userScaleY; |
| 255 | }; |
| 256 | |
| 257 | void wxDC::SetLogicalScale( double x, double y ) |
| 258 | { |
| 259 | // allow negative ? |
| 260 | m_logicalScaleX = x; |
| 261 | m_logicalScaleY = y; |
| 262 | ComputeScaleAndOrigin(); |
| 263 | }; |
| 264 | |
| 265 | void wxDC::GetLogicalScale( double *x, double *y ) |
| 266 | { |
| 267 | if (x) *x = m_logicalScaleX; |
| 268 | if (y) *y = m_logicalScaleY; |
| 269 | }; |
| 270 | |
| 271 | void wxDC::SetLogicalOrigin( long x, long y ) |
| 272 | { |
| 273 | m_logicalOriginX = x * m_signX; // is this still correct ? |
| 274 | m_logicalOriginY = y * m_signY; |
| 275 | ComputeScaleAndOrigin(); |
| 276 | }; |
| 277 | |
| 278 | void wxDC::GetLogicalOrigin( long *x, long *y ) |
| 279 | { |
| 280 | if (x) *x = m_logicalOriginX; |
| 281 | if (y) *y = m_logicalOriginY; |
| 282 | }; |
| 283 | |
| 284 | void wxDC::SetDeviceOrigin( long x, long y ) |
| 285 | { |
| 286 | m_externalDeviceOriginX = x; |
| 287 | m_externalDeviceOriginY = y; |
| 288 | ComputeScaleAndOrigin(); |
| 289 | }; |
| 290 | |
| 291 | void wxDC::GetDeviceOrigin( long *x, long *y ) |
| 292 | { |
| 293 | // if (x) *x = m_externalDeviceOriginX; |
| 294 | // if (y) *y = m_externalDeviceOriginY; |
| 295 | if (x) *x = m_deviceOriginX; |
| 296 | if (y) *y = m_deviceOriginY; |
| 297 | }; |
| 298 | |
| 299 | void wxDC::SetInternalDeviceOrigin( long x, long y ) |
| 300 | { |
| 301 | m_internalDeviceOriginX = x; |
| 302 | m_internalDeviceOriginY = y; |
| 303 | ComputeScaleAndOrigin(); |
| 304 | }; |
| 305 | |
| 306 | void wxDC::GetInternalDeviceOrigin( long *x, long *y ) |
| 307 | { |
| 308 | if (x) *x = m_internalDeviceOriginX; |
| 309 | if (y) *y = m_internalDeviceOriginY; |
| 310 | }; |
| 311 | |
| 312 | void wxDC::SetAxisOrientation( bool xLeftRight, bool yBottomUp ) |
| 313 | { |
| 314 | m_signX = (xLeftRight ? 1 : -1); |
| 315 | m_signY = (yBottomUp ? -1 : 1); |
| 316 | ComputeScaleAndOrigin(); |
| 317 | }; |
| 318 | |
| 319 | long wxDC::DeviceToLogicalX(long x) const |
| 320 | { |
| 321 | return XDEV2LOG(x); |
| 322 | }; |
| 323 | |
| 324 | long wxDC::DeviceToLogicalY(long y) const |
| 325 | { |
| 326 | return YDEV2LOG(y); |
| 327 | }; |
| 328 | |
| 329 | long wxDC::DeviceToLogicalXRel(long x) const |
| 330 | { |
| 331 | return XDEV2LOGREL(x); |
| 332 | }; |
| 333 | |
| 334 | long wxDC::DeviceToLogicalYRel(long y) const |
| 335 | { |
| 336 | return YDEV2LOGREL(y); |
| 337 | }; |
| 338 | |
| 339 | long wxDC::LogicalToDeviceX(long x) const |
| 340 | { |
| 341 | return XLOG2DEV(x); |
| 342 | }; |
| 343 | |
| 344 | long wxDC::LogicalToDeviceY(long y) const |
| 345 | { |
| 346 | return YLOG2DEV(y); |
| 347 | }; |
| 348 | |
| 349 | long wxDC::LogicalToDeviceXRel(long x) const |
| 350 | { |
| 351 | return XLOG2DEVREL(x); |
| 352 | }; |
| 353 | |
| 354 | long wxDC::LogicalToDeviceYRel(long y) const |
| 355 | { |
| 356 | return YLOG2DEVREL(y); |
| 357 | }; |
| 358 | |
| 359 | void wxDC::CalcBoundingBox( long x, long y ) |
| 360 | { |
| 361 | if (x < m_minX) m_minX = x; |
| 362 | if (y < m_minY) m_minY = y; |
| 363 | if (x > m_maxX) m_maxX = x; |
| 364 | if (y > m_maxY) m_maxY = y; |
| 365 | }; |
| 366 | |
| 367 | void wxDC::ComputeScaleAndOrigin(void) |
| 368 | { |
| 369 | // CMB: copy scale to see if it changes |
| 370 | double origScaleX = m_scaleX; |
| 371 | double origScaleY = m_scaleY; |
| 372 | |
| 373 | m_scaleX = m_logicalScaleX * m_userScaleX; |
| 374 | m_scaleY = m_logicalScaleY * m_userScaleY; |
| 375 | |
| 376 | m_deviceOriginX = m_internalDeviceOriginX + m_externalDeviceOriginX; |
| 377 | m_deviceOriginY = m_internalDeviceOriginY + m_externalDeviceOriginY; |
| 378 | |
| 379 | // CMB: if scale has changed call SetPen to recalulate the line width |
| 380 | if (m_scaleX != origScaleX || m_scaleY != origScaleY) |
| 381 | { |
| 382 | // this is a bit artificial, but we need to force wxDC to think |
| 383 | // the pen has changed |
| 384 | wxPen* pen = GetPen(); |
| 385 | wxPen tempPen; |
| 386 | m_pen = tempPen; |
| 387 | SetPen(pen); |
| 388 | } |
| 389 | }; |
| 390 | |