wxArt2D
drawer2d.cpp
Go to the documentation of this file.
1 /*! \file artbase/src/drawer2d.cpp
2  \author Klaas Holwerda
3 
4  Copyright: 2000-2004 (c) Klaas Holwerda
5 
6  Licence: wxWidgets Licence
7 
8  RCS-ID: $Id: drawer2d.cpp,v 1.159 2009/10/06 18:40:31 titato Exp $
9 */
10 
11 #include "a2dprec.h"
12 
13 #ifdef __BORLANDC__
14 #pragma hdrstop
15 #endif
16 
17 #ifndef WX_PRECOMP
18 #include "wx/wx.h"
19 #include "wx/artbase/drawer2d.h"
20 #include "wx/artbase/stylebase.h"
21 #if defined(__WXMSW__)
22 #include "wx/artbase/mswfont.h"
23 #endif
24 #endif
25 
26 #if wxUSE_STD_IOSTREAM
27 #include <wx/ioswrap.h>
28 #else
29 #include <wx/wfstream.h>
30 #include <wx/sstream.h>
31 #endif
32 
33 #if wxART2D_USE_FREETYPE
34 #include <ft2build.h>
35 #ifdef _MSC_VER
36 // Do not use the define include for MSVC, because of a bug with precompiled
37 // headers. See (freetype)/doc/INSTALL.ANY for (some) more information
38 #include <freetype/freetype.h>
39 #include <freetype/ftoutln.h>
40 #else // _MSC_VER
41 // This is the way it should be included.
42 #include FT_FREETYPE_H
43 #include FT_OUTLINE_H
44 #endif // _MSC_VER
45 #endif
46 
47 #include "wx/general/comevt.h"
48 
49 #define THRESHOLD 5
50 // 16 hierarchy levels should be more then sufficient in general.
51 #define AFFINESTACKSIZE 16
52 #define TEXT_MAXSIZE_INPIXELS 3000 //related to screen size in pixels
53 
54 //----------------------------------------------------------------------------
55 // globals
56 //----------------------------------------------------------------------------
57 
58 //----------------------------------------------------------------------------
59 // a2dDrawer2D
60 //----------------------------------------------------------------------------
61 
62 const a2dSignal a2dDrawer2D::sig_changedZoom = wxNewId();
63 
64 
65 a2dDrawer2D::a2dDrawer2D( const wxSize& size )
66 #if defined(_DEBUG) && defined (SMART_POINTER_DEBUG)
67  : m_initCurrentSmartPointerOwner( this )
68 #endif
69 {
70  m_width = size.GetWidth();
71  m_height = size.GetHeight();
72  m_display = NULL;
73 
74  Init();
75 }
76 
77 a2dDrawer2D::a2dDrawer2D( int width, int height )
78 #if defined(_DEBUG) && defined (SMART_POINTER_DEBUG)
79  : m_initCurrentSmartPointerOwner( this )
80 #endif
81 {
82  m_width = width;
83  m_height = height;
84  m_display = NULL;
85 
86  Init();
87 }
88 
90  : wxObject( other )
91 #if defined(_DEBUG) && defined (SMART_POINTER_DEBUG)
92  , m_initCurrentSmartPointerOwner( this )
93 #endif
94 {
95  m_cpointsDouble.clear();
96  m_cpointsInt.clear();
97 
98  m_display = other.m_display;
99 
100  Init();
101 
102  m_realScale = other.m_realScale;
103  m_width = other.m_width;
104  m_height = other.m_height;
105 
106  m_xpp = other.m_xpp;
107  m_ypp = other.m_ypp;
108 
109  m_virt_minX = other.m_virt_minX;
110  m_virt_minY = other.m_virt_minY;
111 
113  SetTransform( other.GetTransform() );
114 
116 
118  m_yaxis = other.m_yaxis ;
119 
120 }
121 
123 {
124  m_realScale = true;
125  m_disableDrawing = false;
126  m_forceNormalizedFont = false;
127  m_smallTextThreshold = SMALLTEXTTHRESHOLD;
128 
132 
133  m_refreshDisplay = 0;
134 
135  m_frozen = false;
136 
137  //set one to one mapping as default
138  m_xpp = 1;
139  m_ypp = 1;
140 
141  m_mapX = m_mapY = 0;
144 
145  m_virt_minX = 0;
146  m_virt_minY = 0;
147 
150 
152  m_virtualarea_set = false;
153 
154  m_yaxis = false;
155 
161 
162  m_OpacityFactor = 255;
163 
167 
168  m_splineaberration = 10;
169 
170  m_displayaberration = 0.5;
171 
173  m_printingMode = false;
174  m_pendingSig_changedZoom = false;
175 }
176 
178 {
179  wxASSERT_MSG( m_affineStack.empty(), _( "Unbalanced Push/PopTransform" ) );
180 }
181 
182 
184 {
185  wxRect rect( 0, 0, m_width, m_height );
186  BlitBuffer( rect, wxPoint( 0, 0 ) );
187 }
188 
189 void a2dDrawer2D::BlitBuffer( int x, int y, int width, int height, int xbuf, int ybuf )
190 {
191  wxRect rect( x, y, width, height );
192  BlitBuffer( rect, wxPoint( xbuf, ybuf ) );
193 }
194 
196 {
197  m_splineaberration = aber;
198 }
199 
200 //------------------------------------------------------------------------
201 // mapping of device to world and visa versa
202 //------------------------------------------------------------------------
203 
205 {
206  m_refreshDisplay--;
207  a2dComEvent changedZoom( this, a2dDrawer2D::sig_changedZoom );
209  {
210  m_pendingSig_changedZoom = false;
211  if ( m_display )
212  m_display->GetEventHandler()->ProcessEvent( changedZoom );
213  }
214 }
215 
216 void a2dDrawer2D::SetMappingDeviceRect( int mapx, int mapy, int mapWidth, int mapHeight, bool remap )
217 {
218  m_mapX = mapx;
219  m_mapY = mapy;
220  m_mapWidth = mapWidth;
221  m_mapHeight = mapHeight;
222  if ( remap )
224 }
225 
226 void a2dDrawer2D::SetMinX( double x )
227 {
228  m_virt_minX = x;
230 }
231 
232 void a2dDrawer2D::SetMinY( double y )
233 {
234  m_virt_minY = y;
236 }
237 
238 void a2dDrawer2D::SetUppX( double x )
239 {
240  m_xpp = x;
242 }
243 
244 void a2dDrawer2D::SetUppY( double y )
245 {
246  m_ypp = y;
248 }
249 
250 void a2dDrawer2D::SetMappingUpp( double vx1, double vy1, double xpp, double ypp )
251 {
252  SetMappingUpp( m_mapX, m_mapY, m_mapWidth, m_mapHeight, vx1, vy1, xpp, ypp );
253 }
254 
255 // maps the virtual window (Real drawing to the window coordinates
256 // also used for zooming
257 void a2dDrawer2D::SetMappingUpp( double x, double y, double wx, double wy, double vx1, double vy1, double xpp, double ypp )
258 {
259 // static bool recur = false;
260 // if ( recur )
261 // return;
262 // recur = true;
263 
264  m_mapX = ( int ) x;
265  m_mapY = ( int ) y;
266  m_mapWidth = ( int ) wx;
267  m_mapHeight = ( int ) wy;
268 
269  m_virt_minX = vx1;
270  m_virt_minY = vy1;
271  m_xpp = xpp;
272  m_ypp = ypp;
273 
274  //!transformation from world to device coordinates
275  double scalex, scaley, transx, transy;
276 
277  // initialize the mapping used for mapping the
278  // virtual window to the pixel window
279 
280  // translate the drawing to 0,0
281  if ( m_yaxis )
282  {
283  double virt_maxY = m_virt_minY + wy * m_ypp;
284  transx = -m_virt_minX + m_mapX * m_xpp;
285  transy = -virt_maxY + m_mapY * m_ypp;
286  }
287  else
288  {
289  transx = -m_virt_minX + m_mapX * m_xpp;
290  transy = -m_virt_minY + m_mapY * m_ypp;
291  }
292 
293  // scale the drawing so that one pixel is the right number of units
294  scalex = 1 / m_xpp;
295  scaley = 1 / m_ypp;
296  transx = transx * scalex;
297  transy = transy * scaley;
298 
299  // because of coordinates origin change, mirror over X.
300  // Like 0,0 in graphic computerscreens: upperleft corner.
301  // While 0,0 in cartesian: lowerleft corner
302  if ( m_yaxis )
303  {
304  scaley = -scaley;
305  transy = -transy;
306  }
307 
308  //now we have a valid virtual area that is visible
309  m_virtualarea_set = true;
310 
311  //setup the transform to reflect the mapping.
312  m_worldtodevice.SetValue( 2 , 0, transx );
313  m_worldtodevice.SetValue( 2 , 1, transy );
314  m_worldtodevice.SetValue( 0 , 0, scalex );
315  m_worldtodevice.SetValue( 1 , 1, scaley );
316 
317  // for speed matrix we have a matrix for going directly from user to device space.
319 
320  a2dComEvent changedZoom( this, a2dDrawer2D::sig_changedZoom );
321  if ( m_display && m_refreshDisplay <= 0 )
322  {
323  m_display->GetEventHandler()->ProcessEvent( changedZoom );
324  m_display->Refresh();
325  }
326  else
329 
330 // recur = false;
331 }
332 
333 void a2dDrawer2D::SetMappingWidthHeight( double vx1, double vy1, double width, double height )
334 {
335  double xupp = width / m_mapWidth;
336  double yupp = height / m_mapHeight;
337 
338  if ( yupp == 0 || xupp == 0 ) //no drawing at all
339  {
340  yupp = 1; xupp = 1; //some value
341  }
342 
343  if( m_realScale )
344  {
345  if ( yupp > xupp )
346  {
347  SetMappingUpp( m_mapX, m_mapY, m_mapWidth, m_mapHeight, vx1, vy1, yupp, yupp );
348  }
349  else
350  {
351  SetMappingUpp( m_mapX, m_mapY, m_mapWidth, m_mapHeight, vx1, vy1, xupp, xupp );
352  }
353  }
354  else
355  SetMappingUpp( m_mapX, m_mapY, m_mapWidth, m_mapHeight, vx1, vy1, xupp, yupp );
356 }
357 
359 {
360  double vx1, vy1, width, height;
361  vx1 = box.GetMinX();
362  vy1 = box.GetMinY();
363  width = box.GetWidth();
364  height = box.GetHeight();
365 
366  double xupp = width / m_mapWidth;
367  double yupp = height / m_mapHeight;
368 
369  if ( yupp == 0 || xupp == 0 ) //no drawing at all
370  {
371  yupp = 1; xupp = 1; //some value
372  }
373 
374  double xc = vx1 + width/2.0;
375  double yc = vy1 + height/2.0;
376 
377  if( m_realScale )
378  {
379  if ( yupp > xupp )
380  {
381  vx1 = xc - yupp* m_mapWidth/2.0;
382  vy1 = yc - yupp* m_mapHeight/2.0;
383  SetMappingUpp( m_mapX, m_mapY, m_mapWidth, m_mapHeight, vx1, vy1, yupp, yupp );
384  }
385  else
386  {
387  vx1 = xc - xupp* m_mapWidth/2.0;
388  vy1 = yc - xupp* m_mapHeight/2.0;
389  SetMappingUpp( m_mapX, m_mapY, m_mapWidth, m_mapHeight, vx1, vy1, xupp, xupp );
390  }
391  }
392  else
393  SetMappingUpp( m_mapX, m_mapY, m_mapWidth, m_mapHeight, vx1, vy1, xupp, yupp );
394 }
395 
397 {
398  m_worldtodevice = mapping;
399  // for speed matrix we have a matrix for going directly from user to device space.
401 }
402 
404 {
405  return m_virt_minX;
406 }
407 
409 {
410  return m_virt_minY;
411 }
412 
414 {
415  return m_virt_minX + m_xpp * m_mapWidth;
416 }
417 
419 {
420  return m_virt_minY + m_ypp * m_mapHeight;
421 }
422 
424 {
425  return m_xpp * m_mapWidth;
426 }
427 
429 {
430  return m_ypp * m_mapHeight;
431 }
432 
434 {
436 }
437 
438 void a2dDrawer2D::SetYaxis( bool up )
439 {
440  m_yaxis = up;
441 
442  //TODO i prefer to mirror around the middle of the visible area, but this needs thinking :-(
444 }
445 
446 void a2dDrawer2D::SetTransform( const a2dAffineMatrix& userToWorld )
447 {
448  m_usertoworld = userToWorld;
450 }
451 
453 {
454  m_affineStack.push_back( m_usertoworld );
455  m_affineStack.push_back( m_worldtodevice );
456  m_affineStack.push_back( m_usertodevice );
457 }
458 
460 {
461  m_affineStack.push_back( m_usertoworld );
462  m_affineStack.push_back( m_worldtodevice );
463  m_affineStack.push_back( m_usertodevice );
464 
465  m_usertoworld = m_usertoworld * affine;
467 }
468 
470 {
471  m_affineStack.push_back( m_usertoworld );
472  m_affineStack.push_back( m_worldtodevice );
473  m_affineStack.push_back( m_usertodevice );
474 
478 }
479 
481 {
482  wxASSERT_MSG( !m_affineStack.empty(), _( "Unbalanced Push/PopTransform" ) );
483  m_usertodevice = m_affineStack.back();
484  m_affineStack.pop_back();
486  m_affineStack.pop_back();
487  m_usertoworld = m_affineStack.back();
488  m_affineStack.pop_back();
489 }
490 
492 {
493  return a2dBoundingBox( DeviceToWorldX( rect.x ),
494  DeviceToWorldY( rect.y ),
495  DeviceToWorldX( rect.x + rect.width ),
496  DeviceToWorldY( rect.y + rect.height ) );
497 }
498 
500 {
501  int xd1, yd1, xd2, yd2;
502  xd1 = WorldToDeviceX( bbox.GetMinX() );
503  yd1 = WorldToDeviceY( bbox.GetMinY() );
504  xd2 = WorldToDeviceX( bbox.GetMaxX() );
505  yd2 = WorldToDeviceY( bbox.GetMaxY() );
506 
507  if ( xd1 > xd2 )
508  {
509  int tmp = xd1;
510  xd1 = xd2;
511  xd2 = tmp;
512  }
513  if ( yd1 > yd2 )
514  {
515  int tmp = yd1;
516  yd1 = yd2;
517  yd2 = tmp;
518  }
519 
520  wxRect tmparea;
521  tmparea.x = xd1;
522  tmparea.y = yd1;
523  tmparea.width = xd2 - xd1;
524  tmparea.height = yd2 - yd1;
525 
526  return tmparea;
527 }
528 
529 wxPoint* a2dDrawer2D::_convertToIntPointCache( int n, wxRealPoint* pts )
530 {
531  m_cpointsInt.resize( n );
532  // Convert to integer coords by rounding
533  for ( int i = 0; i < n; i++ )
534  {
535  m_cpointsInt[i].x = Round( pts[i].x );
536  m_cpointsInt[i].y = Round( pts[i].y );
537  }
538  return &m_cpointsInt[0];
539 }
540 
541 //------------------------------------------------------------------------
542 // platform indepent style settings
543 //------------------------------------------------------------------------
544 
546 {
547  m_fixedStyledOverRuled = false;
548 }
549 
550 void a2dDrawer2D::SetOpacityFactor( wxUint8 OpacityFactor )
551 {
552  m_OpacityFactor = OpacityFactor;
555 }
556 
558 {
560  {
561  DoSetDrawStyle( drawstyle );
562  }
563 }
564 
566 {
568  {
569  //I prefer to see penwidth changing,
570  //therefore not ignore ( m_drawstyle == a2dWIREFRAME_INVERT )
571 
572  if ( !stroke.IsSameAs( m_currentstroke ) )
573  {
574  //DEPENDING on the current drawstyle, make the wxDC in sync or not.
575  m_currentstroke = stroke;
577  }
578  }
579 }
580 
582 {
583  switch( m_drawstyle )
584  {
585  case a2dWIREFRAME_INVERT:
586  case a2dWIREFRAME:
588  m_activestroke = stroke;
589  break;
592  break;
593  case a2dFILLED:
594  m_activestroke = stroke;
595  break;
596  case a2dFIX_STYLE:
597  break;
598  case a2dFIX_STYLE_INVERT:
599  break;
600  default:
601  wxASSERT( 0 );
602  }
603 
607 
609  {
612  }
613  else
614  {
617  }
619 }
620 
622 {
624  {
625  if ( !fill.IsSameAs( m_currentfill ) )
626  {
627  m_currentfill = fill;
629  }
630  }
631 }
632 
634 {
635  switch( m_drawstyle )
636  {
637  case a2dWIREFRAME_INVERT:
638  case a2dWIREFRAME:
642  break;
643  case a2dFILLED:
644  m_activefill = fill;
645  break;
646  case a2dFIX_STYLE:
647  case a2dFIX_STYLE_INVERT:
648  break;
649  default:
650  wxASSERT( 0 );
651  }
652 
659 
660  if ( !m_activefill.GetFilling() )
661  {
662  m_FillOpacityCol1 = 0;
663  m_FillOpacityCol2 = 0;
664  }
665  else if ( m_activefill.GetStyle() == a2dFILL_TRANSPARENT )
666  {
667  m_FillOpacityCol1 = 0;
668  m_FillOpacityCol2 = 0;
669  }
670  else if ( m_activefill.IsNoFill() )
671  {
672  m_FillOpacityCol1 = 0;
673  m_FillOpacityCol2 = 0;
674  }
675  else
676  {
679  }
680 
681  DoSetActiveFill();
682 }
683 
685 {
687  {
689  ResetStyle();
693  m_fixedStyledOverRuled = false;
694  }
695 }
696 
698 {
699  if ( !m_fixedStyledOverRuled &&
701  )
702  {
707  m_fixedStyledOverRuled = true;
708  }
709 }
710 
712 {
714  {
718  m_fixedStyledOverRuled = false;
719  }
720 }
721 
722 void a2dDrawer2D::SetFont( const a2dFont& font )
723 {
724  if ( !font.IsSameAs( m_currentfont ) )
725  {
726  m_currentfont = font;
727  }
728  DoSetActiveFont( m_currentfont );
729 }
730 
732 {
733  wxPen dcpen = *wxTRANSPARENT_PEN;
734  wxColour stroke1;
736 
737  if ( m_activestroke.GetStyle() == a2dSTROKE_TRANSPARENT )
738  {
739  dcpen = *wxTRANSPARENT_PEN;
740  }
741  else if ( m_activestroke.IsNoStroke() )
742  {
743  dcpen = *wxTRANSPARENT_PEN;
744  }
746  {
747  dcpen = *wxBLACK_PEN;
748  }
749  else if ( m_activestroke.GetType() == a2dSTROKE_ONE_COLOUR )
750  {
751  int style;
752  switch( m_activestroke.GetStyle() )
753  {
754  case a2dSTROKE_SOLID: style = wxSOLID;
755  break;
756  case a2dSTROKE_TRANSPARENT: style = wxTRANSPARENT;
757  break;
758  case a2dSTROKE_DOT: style = wxDOT;
759  break;
760  case a2dSTROKE_DOT_DASH: style = wxDOT_DASH;
761  break;
762  case a2dSTROKE_LONG_DASH: style = wxLONG_DASH;
763  break;
764  case a2dSTROKE_SHORT_DASH: style = wxSHORT_DASH;
765  break;
766  case a2dSTROKE_BDIAGONAL_HATCH: style = wxBDIAGONAL_HATCH;
767  break;
768  case a2dSTROKE_CROSSDIAG_HATCH: style = wxCROSSDIAG_HATCH;
769  break;
770  case a2dSTROKE_FDIAGONAL_HATCH: style = wxFDIAGONAL_HATCH;
771  break;
772  case a2dSTROKE_CROSS_HATCH: style = wxCROSS_HATCH;
773  break;
774  case a2dSTROKE_HORIZONTAL_HATCH: style = wxHORIZONTAL_HATCH;
775  break;
776  case a2dSTROKE_VERTICAL_HATCH: style = wxVERTICAL_HATCH;
777  break;
778  case a2dSTROKE_STIPPLE: style = wxSTIPPLE;
779  break;
780  case a2dSTROKE_STIPPLE_MASK_OPAQUE: style = wxSTIPPLE_MASK_OPAQUE;
781  break;
782  default: style = a2dSTROKE_SOLID;
783  }
784 
786  {
787  dcpen = wxPen( stroke1, 0, style );
788  }
789  else
790  {
791  dcpen = wxPen( stroke1, ( int ) m_activestroke.GetWidth(), style );
792  dcpen.SetJoin( m_activestroke.GetJoin() );
793  dcpen.SetCap( m_activestroke.GetCap() );
795  dcpen.SetWidth( ( int ) DeviceToWorldXRel( m_activestroke.GetWidth() ) );
796  }
797  }
798  else if ( m_activestroke.GetType() == a2dSTROKE_BITMAP )
799  {
801  dcpen = wxPen( stroke1, 0, wxBRUSHSTYLE_SOLID );
802  else
803  {
804  int width = ( int ) m_activestroke.GetWidth();
806  width = ( int ) DeviceToWorldXRel( width );
807  dcpen = wxPen( stroke1, width, wxBRUSHSTYLE_SOLID );
808  dcpen.SetJoin( m_activestroke.GetJoin() );
809  dcpen.SetCap( m_activestroke.GetCap() );
810  }
811 
812 #if defined(__WXMSW__)
813  wxBrushStyle style;
814  switch( m_activestroke.GetStyle() )
815  {
816  case a2dSTROKE_STIPPLE:
817  style = wxBRUSHSTYLE_STIPPLE;
818  dcpen.SetStyle( style );
819  dcpen.SetStipple( m_activestroke.GetStipple() );
820  break;
823  if ( 0 ) //m_printingMode )
824  {
825  wxBitmap noMask = m_activestroke.GetStipple();
826  noMask.SetMask( NULL );
827  style = wxBRUSHSTYLE_STIPPLE;
828  dcpen.SetStyle( style );
829  dcpen.SetStipple( noMask );
830  }
831  else
832  {
833  style = wxBRUSHSTYLE_STIPPLE_MASK_OPAQUE;
834  dcpen.SetStyle( style );
835  dcpen.SetStipple( m_activestroke.GetStipple() );
836  }
837  break;
838  default: style = wxBRUSHSTYLE_SOLID;
839  dcpen.SetStyle( style );
840  }
841 #endif
842 
843  }
844  return dcpen;
845 }
846 
848 {
849  wxBrush dcbrush = *wxTRANSPARENT_BRUSH;
850  wxColour textb;
851  wxBrushStyle style;
852  wxColour fill1;
854  wxColour fill2;
856 
857  if ( !m_activefill.GetFilling() )
858  {
859  dcbrush = *wxTRANSPARENT_BRUSH;
860  textb = *wxBLACK;
861  }
862  else if ( m_activefill.GetStyle() == a2dFILL_TRANSPARENT )
863  {
864  dcbrush = *wxTRANSPARENT_BRUSH;
865  textb = *wxBLACK;
866  }
867  else if ( m_activefill.IsNoFill() )
868  {
869  dcbrush = *wxTRANSPARENT_BRUSH;
870  textb = *wxBLACK;
871  }
872  else if ( m_activefill.GetType() == a2dFILL_ONE_COLOUR )
873  {
874  switch( m_activefill.GetStyle() )
875  {
876  case a2dFILL_TRANSPARENT:
877  style = wxBRUSHSTYLE_TRANSPARENT;
878  dcbrush.SetColour( fill1 );
879  dcbrush.SetStyle( style );
880  break;
881  case a2dFILL_SOLID: style = wxBRUSHSTYLE_SOLID;
882  dcbrush.SetColour( fill1 );
883  dcbrush.SetStyle( style );
884  break;
886  style = wxBRUSHSTYLE_BDIAGONAL_HATCH;
887  dcbrush.SetColour( fill1 );
888  dcbrush.SetStyle( style );
889  break;
891  style = wxBRUSHSTYLE_CROSSDIAG_HATCH;
892  dcbrush.SetColour( fill1 );
893  dcbrush.SetStyle( style );
894  break;
896  style = wxBRUSHSTYLE_FDIAGONAL_HATCH;
897  dcbrush.SetColour( fill1 );
898  dcbrush.SetStyle( style );
899  break;
900  case a2dFILL_CROSS_HATCH:
901  style = wxBRUSHSTYLE_CROSS_HATCH;
902  dcbrush.SetColour( fill1 );
903  dcbrush.SetStyle( style );
904  break;
906  style = wxBRUSHSTYLE_HORIZONTAL_HATCH;
907  dcbrush.SetColour( fill1 );
908  dcbrush.SetStyle( style );
909  break;
911  style = wxBRUSHSTYLE_VERTICAL_HATCH;
912  dcbrush.SetColour( fill1 );
913  dcbrush.SetStyle( style );
914  break;
915  default: style = wxBRUSHSTYLE_SOLID;
916  dcbrush.SetColour( fill1 );
917  dcbrush.SetStyle( style );
918  }
919  }
920  else if ( m_activefill.GetType() == a2dFILL_HATCH_TWO_COLOUR )
921  {
922  wxBrushStyle style;
923  switch( m_activefill.GetStyle() )
924  {
925  case a2dFILL_TRANSPARENT:
926  style = wxBRUSHSTYLE_TRANSPARENT;
927  dcbrush.SetColour( fill1 );
928  dcbrush.SetStyle( style );
929  break;
931  style = wxBRUSHSTYLE_BDIAGONAL_HATCH;
932  dcbrush.SetColour( fill1 );
933  dcbrush.SetStyle( style );
934  break;
936  style = wxBRUSHSTYLE_CROSSDIAG_HATCH;
937  dcbrush.SetColour( fill1 );
938  dcbrush.SetStyle( style );
939  break;
941  style = wxBRUSHSTYLE_FDIAGONAL_HATCH;
942  dcbrush.SetColour( fill1 );
943  dcbrush.SetStyle( style );
944  break;
946  style = wxBRUSHSTYLE_CROSS_HATCH;
947  dcbrush.SetColour( fill1 );
948  dcbrush.SetStyle( style );
949  break;
951  style = wxBRUSHSTYLE_HORIZONTAL_HATCH;
952  dcbrush.SetColour( fill1 );
953  dcbrush.SetStyle( style );
954  break;
956  style = wxBRUSHSTYLE_VERTICAL_HATCH;
957  dcbrush.SetColour( fill1 );
958  dcbrush.SetStyle( style );
959  break;
960  default:
961  style = wxBRUSHSTYLE_SOLID;
962  dcbrush.SetColour( fill1 );
963  dcbrush.SetStyle( style );
964  }
965  }
966  else if ( m_activefill.GetType() == a2dFILL_BITMAP )
967  {
968  wxBrushStyle style;
969  switch( m_activefill.GetStyle() )
970  {
971  case a2dFILL_STIPPLE:
972  style = wxBRUSHSTYLE_STIPPLE;
973  dcbrush.SetColour( fill1 );
974  dcbrush.SetStipple( m_activefill.GetStipple() );
975  dcbrush.SetStyle( style );
976  break;
979  if ( 0 ) //m_printingMode )
980  {
981  wxBitmap noMask = m_activefill.GetStipple();
982  noMask.SetMask( NULL );
983  style = wxBRUSHSTYLE_STIPPLE;
984  dcbrush.SetColour( fill1 );
985  dcbrush.SetStipple( noMask );
986  }
987  else
988  {
989  style = wxBRUSHSTYLE_STIPPLE_MASK_OPAQUE;
990  dcbrush.SetColour( fill1 );
991  dcbrush.SetStipple( m_activefill.GetStipple() );
992  }
993  dcbrush.SetStyle( style );
994  break;
995  default: style = wxBRUSHSTYLE_SOLID;
996  dcbrush.SetColour( fill1 );
997  dcbrush.SetStyle( style );
998  }
999  }
1001  {
1002  wxFAIL_MSG( wxT( "can not convert gradients to wxBrush" ) );
1003  }
1004  return dcbrush;
1005 }
1006 
1007 #if wxART2D_USE_GRAPHICS_CONTEXT
1008 
1009 wxGraphicsPen a2dDrawer2D::ConvertActiveToGraphicsPen( wxGraphicsContext* context )
1010 {
1011  wxPen dcpen = *wxTRANSPARENT_PEN;
1012  wxColour stroke1;
1014 
1015  if ( m_activestroke.GetStyle() == a2dSTROKE_TRANSPARENT )
1016  {
1017  dcpen = *wxTRANSPARENT_PEN;
1018  }
1019  else if ( m_activestroke.IsNoStroke() )
1020  {
1021  dcpen = *wxTRANSPARENT_PEN;
1022  }
1024  {
1025  dcpen = *wxBLACK_PEN;
1026  }
1027  else if ( m_activestroke.GetType() == a2dSTROKE_ONE_COLOUR )
1028  {
1029  int style;
1030  switch( m_activestroke.GetStyle() )
1031  {
1032  case a2dSTROKE_SOLID: style = wxSOLID;
1033  break;
1034  case a2dSTROKE_TRANSPARENT: style = wxTRANSPARENT;
1035  break;
1036  case a2dSTROKE_DOT: style = wxDOT;
1037  break;
1038  case a2dSTROKE_DOT_DASH: style = wxDOT_DASH;
1039  break;
1040  case a2dSTROKE_LONG_DASH: style = wxLONG_DASH;
1041  break;
1042  case a2dSTROKE_SHORT_DASH: style = wxSHORT_DASH;
1043  break;
1044  case a2dSTROKE_BDIAGONAL_HATCH: style = wxBDIAGONAL_HATCH;
1045  break;
1046  case a2dSTROKE_CROSSDIAG_HATCH: style = wxCROSSDIAG_HATCH;
1047  break;
1048  case a2dSTROKE_FDIAGONAL_HATCH: style = wxFDIAGONAL_HATCH;
1049  break;
1050  case a2dSTROKE_CROSS_HATCH: style = wxCROSS_HATCH;
1051  break;
1052  case a2dSTROKE_HORIZONTAL_HATCH: style = wxHORIZONTAL_HATCH;
1053  break;
1054  case a2dSTROKE_VERTICAL_HATCH: style = wxVERTICAL_HATCH;
1055  break;
1056  case a2dSTROKE_STIPPLE: style = wxSTIPPLE;
1057  break;
1058  case a2dSTROKE_STIPPLE_MASK_OPAQUE: style = wxSTIPPLE_MASK_OPAQUE;
1059  break;
1060  default: style = a2dSTROKE_SOLID;
1061  }
1062 
1064  {
1065  dcpen = wxPen( stroke1, 0, style );
1066  }
1067  else
1068  {
1069  dcpen = wxPen( stroke1, ( int ) m_activestroke.GetWidth(), style );
1070  dcpen.SetJoin( m_activestroke.GetJoin() );
1071  dcpen.SetCap( m_activestroke.GetCap() );
1073  dcpen.SetWidth( DeviceToWorldXRel( m_activestroke.GetWidth() ) );
1074  }
1075  }
1076  else if ( m_activestroke.GetType() == a2dSTROKE_BITMAP )
1077  {
1079  dcpen = wxPen( stroke1, 0, wxBRUSHSTYLE_SOLID );
1080  else
1081  {
1082  int width = ( int ) m_activestroke.GetWidth();
1084  width = DeviceToWorldXRel( width );
1085  dcpen = wxPen( stroke1, width, wxBRUSHSTYLE_SOLID );
1086  dcpen.SetJoin( m_activestroke.GetJoin() );
1087  dcpen.SetCap( m_activestroke.GetCap() );
1088  }
1089 
1090 #if defined(__WXMSW__)
1091  wxBrushStyle style;
1092  switch( m_activestroke.GetStyle() )
1093  {
1094  case a2dSTROKE_STIPPLE:
1095  style = wxBRUSHSTYLE_STIPPLE;
1096  dcpen.SetStyle( style );
1097  dcpen.SetStipple( m_activestroke.GetStipple() );
1098  break;
1101  if ( 0 ) //m_printingMode )
1102  {
1103  wxBitmap noMask = m_activestroke.GetStipple();
1104  noMask.SetMask( NULL );
1105  style = wxBRUSHSTYLE_STIPPLE;
1106  dcpen.SetStyle( style );
1107  dcpen.SetStipple( noMask );
1108  }
1109  else
1110  {
1111  style = wxBRUSHSTYLE_STIPPLE_MASK_OPAQUE;
1112  dcpen.SetStyle( style );
1113  dcpen.SetStipple( m_activestroke.GetStipple() );
1114  }
1115  break;
1116  default: style = wxBRUSHSTYLE_SOLID;
1117  dcpen.SetStyle( style );
1118  }
1119 #endif
1120 
1121  }
1122  return context->CreatePen( dcpen );
1123 }
1124 
1125 wxGraphicsBrush a2dDrawer2D::ConvertActiveToGraphicsBrush( wxGraphicsContext* context )
1126 {
1127  wxBrush dcbrush = *wxTRANSPARENT_BRUSH;
1128  wxColour textb;
1129  wxBrushStyle style;
1130  wxColour fill1;
1132  wxColour fill2;
1134 
1135  if ( !m_activefill.GetFilling() )
1136  {
1137  dcbrush = *wxTRANSPARENT_BRUSH;
1138  textb = *wxBLACK;
1139  return context->CreateBrush( dcbrush );
1140  }
1141  else if ( m_activefill.GetStyle() == a2dFILL_TRANSPARENT )
1142  {
1143  dcbrush = *wxTRANSPARENT_BRUSH;
1144  textb = *wxBLACK;
1145  return context->CreateBrush( dcbrush );
1146  }
1147  else if ( m_activefill.IsNoFill() )
1148  {
1149  dcbrush = *wxTRANSPARENT_BRUSH;
1150  textb = *wxBLACK;
1151  return context->CreateBrush( dcbrush );
1152  }
1153  else if ( m_activefill.GetType() == a2dFILL_ONE_COLOUR )
1154  {
1155  switch( m_activefill.GetStyle() )
1156  {
1157  case a2dFILL_TRANSPARENT:
1158  style = wxBRUSHSTYLE_TRANSPARENT;
1159  dcbrush.SetColour( fill1 );
1160  dcbrush.SetStyle( style );
1161  break;
1162  case a2dFILL_SOLID: style = wxBRUSHSTYLE_SOLID;
1163  dcbrush.SetColour( fill1 );
1164  dcbrush.SetStyle( style );
1165  break;
1167  style = wxBRUSHSTYLE_BDIAGONAL_HATCH;
1168  dcbrush.SetColour( fill1 );
1169  dcbrush.SetStyle( style );
1170  break;
1172  style = wxBRUSHSTYLE_CROSSDIAG_HATCH;
1173  dcbrush.SetColour( fill1 );
1174  dcbrush.SetStyle( style );
1175  break;
1177  style = wxBRUSHSTYLE_FDIAGONAL_HATCH;
1178  dcbrush.SetColour( fill1 );
1179  dcbrush.SetStyle( style );
1180  break;
1181  case a2dFILL_CROSS_HATCH:
1182  style = wxBRUSHSTYLE_CROSS_HATCH;
1183  dcbrush.SetColour( fill1 );
1184  dcbrush.SetStyle( style );
1185  break;
1187  style = wxBRUSHSTYLE_HORIZONTAL_HATCH;
1188  dcbrush.SetColour( fill1 );
1189  dcbrush.SetStyle( style );
1190  break;
1192  style = wxBRUSHSTYLE_VERTICAL_HATCH;
1193  dcbrush.SetColour( fill1 );
1194  dcbrush.SetStyle( style );
1195  break;
1196  default: style = wxBRUSHSTYLE_SOLID;
1197  dcbrush.SetColour( fill1 );
1198  dcbrush.SetStyle( style );
1199  }
1200  return context->CreateBrush( dcbrush );
1201  }
1202  else if ( m_activefill.GetType() == a2dFILL_HATCH_TWO_COLOUR )
1203  {
1204  wxBrushStyle style;
1205  switch( m_activefill.GetStyle() )
1206  {
1207  case a2dFILL_TRANSPARENT:
1208  style = wxBRUSHSTYLE_TRANSPARENT;
1209  dcbrush.SetColour( fill1 );
1210  dcbrush.SetStyle( style );
1211  break;
1213  style = wxBRUSHSTYLE_BDIAGONAL_HATCH;
1214  dcbrush.SetColour( fill1 );
1215  dcbrush.SetStyle( style );
1216  break;
1218  style = wxBRUSHSTYLE_CROSSDIAG_HATCH;
1219  dcbrush.SetColour( fill1 );
1220  dcbrush.SetStyle( style );
1221  break;
1223  style = wxBRUSHSTYLE_FDIAGONAL_HATCH;
1224  dcbrush.SetColour( fill1 );
1225  dcbrush.SetStyle( style );
1226  break;
1228  style = wxBRUSHSTYLE_CROSS_HATCH;
1229  dcbrush.SetColour( fill1 );
1230  dcbrush.SetStyle( style );
1231  break;
1233  style = wxBRUSHSTYLE_HORIZONTAL_HATCH;
1234  dcbrush.SetColour( fill1 );
1235  dcbrush.SetStyle( style );
1236  break;
1238  style = wxBRUSHSTYLE_VERTICAL_HATCH;
1239  dcbrush.SetColour( fill1 );
1240  dcbrush.SetStyle( style );
1241  break;
1242  default:
1243  style = wxBRUSHSTYLE_SOLID;
1244  dcbrush.SetColour( fill1 );
1245  dcbrush.SetStyle( style );
1246  }
1247  return context->CreateBrush( dcbrush );
1248  }
1249  else if ( m_activefill.GetType() == a2dFILL_BITMAP )
1250  {
1251  wxBrushStyle style;
1252  switch( m_activefill.GetStyle() )
1253  {
1254  case a2dFILL_STIPPLE:
1255  style = wxBRUSHSTYLE_STIPPLE;
1256  dcbrush.SetColour( fill1 );
1257  dcbrush.SetStipple( m_activefill.GetStipple() );
1258  dcbrush.SetStyle( style );
1259  break;
1262  if ( 0 ) //m_printingMode )
1263  {
1264  wxBitmap noMask = m_activefill.GetStipple();
1265  noMask.SetMask( NULL );
1266  style = wxBRUSHSTYLE_STIPPLE;
1267  dcbrush.SetColour( fill1 );
1268  dcbrush.SetStipple( noMask );
1269  }
1270  else
1271  {
1272  style = wxBRUSHSTYLE_STIPPLE_MASK_OPAQUE;
1273  dcbrush.SetColour( fill1 );
1274  dcbrush.SetStipple( m_activefill.GetStipple() );
1275  }
1276  dcbrush.SetStyle( style );
1277  break;
1278  default: style = wxBRUSHSTYLE_SOLID;
1279  dcbrush.SetColour( fill1 );
1280  dcbrush.SetStyle( style );
1281  }
1282  return context->CreateBrush( dcbrush );
1283  }
1284 
1285  if ( m_activefill.GetType() == a2dFILL_GRADIENT_FILL_LINEAR )
1286  {
1287  double x1 = m_activefill.GetStart().m_x;
1288  double y1 = m_activefill.GetStart().m_y;
1289  double x2 = m_activefill.GetStop().m_x;
1290  double y2 = m_activefill.GetStop().m_y;
1291  return context->CreateLinearGradientBrush( x1, y1, x2, y2, fill1, fill2 );
1292  }
1293  if ( m_activefill.GetType() == a2dFILL_GRADIENT_FILL_RADIAL )
1294  {
1295  double xf = m_activefill.GetFocal().m_x;
1296  double yf = m_activefill.GetFocal().m_y;
1297  double xc = m_activefill.GetCenter().m_x;
1298  double yc = m_activefill.GetCenter().m_y;
1299  double r = m_activefill.GetRadius();
1300  return context->CreateRadialGradientBrush( xf, yf, xc, yc, r, fill1, fill2 );
1301  }
1302  return wxNullGraphicsBrush;
1303 }
1304 
1305 #endif // wxART2D_USE_GRAPHICS_CONTEXT
1306 
1307 //------------------------------------------------------------------------
1308 // basic platform independent drawing of primitives
1309 //------------------------------------------------------------------------
1310 int a2dDrawer2D::ToDeviceLines( a2dVertexArray* points, a2dBoundingBox& devbbox, bool& smallPoly, bool replaceByRectangle )
1311 {
1312  unsigned int segments = 0;
1313 
1314  unsigned int i;
1315  for ( i = 0; i < points->size(); i++ )
1316  {
1317  const a2dLineSegmentPtr seg = points->Item( i );
1318 
1319  if ( seg->GetArc() )
1320  {
1321  const a2dArcSegment* cseg = ( const a2dArcSegment* ) seg.Get();
1322 
1323  double radius, center_x, center_y, beginrad, midrad, endrad, phit;
1324 
1325  if ( cseg->CalcR( *( points->Item( i ? i - 1 : 0 ) ), radius, center_x, center_y, beginrad, midrad, endrad, phit ) )
1326  {
1327  double dphi;
1328  unsigned int circlesegments;
1329  double radiusDev = m_usertodevice.TransformDistance( radius );
1330  Aberration( m_displayaberration, phit, radiusDev , dphi, circlesegments );
1331  segments += circlesegments + 1;
1332  }
1333  else
1334  segments ++;
1335  }
1336  else
1337  segments++;
1338  }
1339 
1340  //TODO memory error because of wrong calculation of segments?? for the moment *2 to be save
1341  m_cpointsDouble.resize( segments * 2 );
1342 
1343  unsigned int count = 0;
1344  double x, y, lastx, lasty;
1345  for ( i = 0; i < points->size(); i++ )
1346  {
1347  const a2dLineSegmentPtr seg = points->Item( i );
1348 
1349  if ( !seg->GetArc() )
1350  {
1351  GetUserToDeviceTransform().TransformPoint( seg->m_x, seg->m_y, x, y );
1352 
1353  //to reduce the points count for lines or a polygon on the screen
1354  if( !count || fabs( x - lastx ) > 0.001 || fabs( y - lasty ) > 0.001 )
1355  {
1356  m_cpointsDouble[count].x = x;
1357  m_cpointsDouble[count].y = y;
1358  lastx = x;
1359  lasty = y;
1360  devbbox.Expand( x, y );
1361  count++;
1362  }
1363  }
1364  else
1365  {
1366  const a2dArcSegment* cseg = ( const a2dArcSegment* ) seg.Get();
1367 
1368  double radius, center_x, center_y, beginrad, midrad, endrad, phit;
1369 
1370  if ( cseg->CalcR( *( points->Item( i ? i - 1 : 0 ) ), radius, center_x, center_y, beginrad, midrad, endrad, phit ) )
1371  {
1372  double dphi;
1373  unsigned int segments;
1374  double radiusDev = m_usertodevice.TransformDistance( radius );
1375  Aberration( m_displayaberration, phit, radiusDev , dphi, segments );
1376 
1377  double theta = beginrad;
1378  unsigned int step;
1379 
1380  double x, y;
1381  for ( step = 0; step < segments + 1; step++ )
1382  {
1383  GetUserToDeviceTransform().TransformPoint( center_x + radius * cos ( theta ), center_y + radius * sin ( theta ), x, y );
1384 
1385  //to reduce the points count for lines or a polygon on the screen
1386  if( !count || fabs( x - lastx ) > 0.001 || fabs( y - lasty ) > 0.001 )
1387  {
1388  m_cpointsDouble[count].x = x;
1389  m_cpointsDouble[count].y = y;
1390  lastx = x;
1391  lasty = y;
1392  devbbox.Expand( x, y );
1393  count++;
1394  }
1395  theta = theta + dphi;
1396  }
1397  }
1398  else
1399  {
1400  double x, y;
1401  GetUserToDeviceTransform().TransformPoint( cseg->m_x, cseg->m_y, x, y );
1402 
1403  //to reduce the points count for lines or a polygon on the screen
1404  if( !count || fabs( x - lastx ) > 0.001 || fabs( y - lasty ) > 0.001 )
1405  {
1406  m_cpointsDouble[count].x = x;
1407  m_cpointsDouble[count].y = y;
1408  lastx = x;
1409  lasty = y;
1410  devbbox.Expand( x, y );
1411  count++;
1412  }
1413  }
1414  }
1415  }
1416 
1417  if ( devbbox.GetSize() < m_polygonFillThreshold )
1418  {
1419  smallPoly = true;
1420  if ( replaceByRectangle )
1421  {
1422  m_cpointsDouble[0].x = devbbox.GetMinX(); m_cpointsDouble[0].y = devbbox.GetMinY();
1423  m_cpointsDouble[1].x = devbbox.GetMinX(); m_cpointsDouble[1].y = devbbox.GetMaxY();
1424  m_cpointsDouble[2].x = devbbox.GetMaxX(); m_cpointsDouble[2].y = devbbox.GetMaxY();
1425  m_cpointsDouble[3].x = devbbox.GetMaxX(); m_cpointsDouble[3].y = devbbox.GetMinY();
1426  return 4;
1427  }
1428  }
1429  return count;
1430 }
1431 
1432 int a2dDrawer2D::ToDeviceLines( const a2dVertexList* list, a2dBoundingBox& devbbox, bool& smallPoly, bool replaceByRectangle )
1433 {
1434  unsigned int segments = 0;
1435 
1436  if ( list->empty() )
1437  return 0;
1438 
1439  a2dVertexList::const_iterator iterprev = list->end();
1440  if ( iterprev != list->begin() )
1441  iterprev--;
1442  a2dVertexList::const_iterator iter = list->begin();
1443  while ( iter != list->end() )
1444  {
1445  a2dLineSegment* seg = ( *iter );
1446 
1447  if ( seg->GetArc() )
1448  {
1449  a2dArcSegment* cseg = ( a2dArcSegment* ) seg;
1450 
1451  double radius, center_x, center_y, beginrad, midrad, endrad, phit;
1452 
1453  if ( cseg->CalcR( *( *iterprev ), radius, center_x, center_y, beginrad, midrad, endrad, phit ) )
1454  {
1455  double dphi;
1456  unsigned int circlesegments;
1457  double radiusDev = m_usertodevice.TransformDistance( radius );
1458  Aberration( m_displayaberration, phit, radiusDev , dphi, circlesegments );
1459  segments += circlesegments + 1;
1460  }
1461  else
1462  segments ++;
1463  }
1464  else
1465  segments++;
1466 
1467  iterprev = iter++;
1468  }
1469 
1470  //TODO memory error because of wrong calculation of segments?? for the moment *2 to be save
1471  m_cpointsDouble.resize( segments * 2 );
1472 
1473  unsigned int count = 0;
1474  double x, y, lastx, lasty;
1475  iterprev = list->end();
1476  if ( iterprev != list->begin() )
1477  iterprev--;
1478  iter = list->begin();
1479  while ( iter != list->end() )
1480  {
1481  a2dLineSegment* seg = ( *iter );
1482 
1483  if ( !seg->GetArc() )
1484  {
1485  GetUserToDeviceTransform().TransformPoint( seg->m_x, seg->m_y, x, y );
1486 
1487  //to reduce the points count for lines or a polygon on the screen
1488  if( !count || fabs( x - lastx ) > 0.001 || fabs( y - lasty ) > 0.001 )
1489  {
1490  m_cpointsDouble[count].x = x;
1491  m_cpointsDouble[count].y = y;
1492  lastx = x;
1493  lasty = y;
1494  devbbox.Expand( x, y );
1495  count++;
1496  }
1497  }
1498  else
1499  {
1500  a2dArcSegment* cseg = ( a2dArcSegment* ) seg;
1501 
1502  double radius, center_x, center_y, beginrad, midrad, endrad, phit;
1503 
1504  if ( cseg->CalcR( *( *iterprev ), radius, center_x, center_y, beginrad, midrad, endrad, phit ) )
1505  {
1506  double dphi;
1507  unsigned int segments;
1508  double radiusDev = m_usertodevice.TransformDistance( radius );
1509  Aberration( m_displayaberration, phit, radiusDev , dphi, segments );
1510 
1511  double theta = beginrad;
1512  unsigned int step;
1513 
1514  double x, y;
1515  for ( step = 0; step < segments + 1; step++ )
1516  {
1517  GetUserToDeviceTransform().TransformPoint( center_x + radius * cos ( theta ), center_y + radius * sin ( theta ), x, y );
1518 
1519  //to reduce the points count for lines or a polygon on the screen
1520  if( !count || fabs( x - lastx ) > 0.001 || fabs( y - lasty ) > 0.001 )
1521  {
1522  m_cpointsDouble[count].x = x;
1523  m_cpointsDouble[count].y = y;
1524  lastx = x;
1525  lasty = y;
1526  devbbox.Expand( x, y );
1527  count++;
1528  }
1529  theta = theta + dphi;
1530  }
1531  }
1532  else
1533  {
1534  double x, y;
1535  GetUserToDeviceTransform().TransformPoint( cseg->m_x, cseg->m_y, x, y );
1536 
1537  //to reduce the points count for lines or a polygon on the screen
1538  if( !count || fabs( x - lastx ) > 0.001 || fabs( y - lasty ) > 0.001 )
1539  {
1540  m_cpointsDouble[count].x = x;
1541  m_cpointsDouble[count].y = y;
1542  lastx = x;
1543  lasty = y;
1544  devbbox.Expand( x, y );
1545  count++;
1546  }
1547  }
1548  }
1549  iterprev = iter++;
1550  }
1551 
1552  if ( devbbox.GetSize() < m_polygonFillThreshold )
1553  {
1554  smallPoly = true;
1555  if ( replaceByRectangle )
1556  {
1557  m_cpointsDouble[0].x = devbbox.GetMinX(); m_cpointsDouble[0].y = devbbox.GetMinY();
1558  m_cpointsDouble[1].x = devbbox.GetMinX(); m_cpointsDouble[1].y = devbbox.GetMaxY();
1559  m_cpointsDouble[2].x = devbbox.GetMaxX(); m_cpointsDouble[2].y = devbbox.GetMaxY();
1560  m_cpointsDouble[3].x = devbbox.GetMaxX(); m_cpointsDouble[3].y = devbbox.GetMinY();
1561  return 4;
1562  }
1563  }
1564  return count;
1565 }
1566 
1567 
1569 {
1570  if ( m_disableDrawing )
1571  return;
1572 
1573  double tstep = 1 / ( double ) SPLINE_STEP;
1574  unsigned int i;
1575 
1576  m_tempPoints.clear();
1577  bool move = false;
1578  int count = 0;
1579  bool nostrokeparts = false;
1580 
1581  //first draw as much as possible ( nostroke parts may stop this first round )
1582  for ( i = 0; i < path->size(); i++ )
1583  {
1584  a2dVpathSegmentPtr seg = path->operator[]( i );
1585  switch ( seg->GetType() )
1586  {
1587  case a2dPATHSEG_MOVETO:
1588  if ( count == 0 )
1589  {
1590  m_tempPoints.push_back( new a2dLineSegment( seg->m_x1, seg->m_y1 ) );
1591  count++;
1592  }
1593  else
1594  {
1595  i--;
1596  move = true;
1597  }
1598  break;
1599 
1600  case a2dPATHSEG_LINETO:
1601  m_tempPoints.push_back( new a2dLineSegment( seg->m_x1, seg->m_y1 ) );
1602  count++;
1603  break;
1605  m_tempPoints.push_back( new a2dLineSegment( seg->m_x1, seg->m_y1 ) );
1606  count++;
1607  nostrokeparts = true;
1608  break;
1609 
1611  nostrokeparts = true;
1612  case a2dPATHSEG_CBCURVETO:
1613  {
1614  double xw, yw;
1615 
1616  double xwl = path->operator[]( i ? i - 1 : 0 )->m_x1;
1617  double ywl = path->operator[]( i ? i - 1 : 0 )->m_y1;
1618  a2dVpathCBCurveSegment* cseg = ( a2dVpathCBCurveSegment* ) seg.Get();
1619 
1620  int step;
1621  double t = 0;
1622  for ( step = 0; step <= SPLINE_STEP; step++ )
1623  {
1624  xw = xwl * pow( 1 - t, 3 ) + cseg->m_x2 * pow( 1 - t, 2 ) * t * 3 + cseg->m_x3 * ( 1 - t ) * t * t * 3 + cseg->m_x1 * pow( t, 3 );
1625  yw = ywl * pow( 1 - t, 3 ) + cseg->m_y2 * pow( 1 - t, 2 ) * t * 3 + cseg->m_y3 * ( 1 - t ) * t * t * 3 + cseg->m_y1 * pow( t, 3 );
1626  m_tempPoints.push_back( new a2dLineSegment( xw, yw ) );
1627  count++;
1628  t = t + tstep;
1629  }
1630  }
1631  break;
1632 
1634  nostrokeparts = true;
1635  case a2dPATHSEG_QBCURVETO:
1636  {
1637  double xw, yw;
1638 
1639  double xwl = path->operator[]( i ? i - 1 : 0 )->m_x1;
1640  double ywl = path->operator[]( i ? i - 1 : 0 )->m_y1;
1641  a2dVpathQBCurveSegment* cseg = ( a2dVpathQBCurveSegment* ) seg.Get();
1642 
1643  int step;
1644  double t = 0;
1645  for ( step = 0; step <= SPLINE_STEP; step++ )
1646  {
1647  xw = xwl * pow( 1 - t, 2 ) + cseg->m_x2 * ( 1 - t ) * t * 2 + cseg->m_x1 * pow( t, 2 );
1648  yw = ywl * pow( 1 - t, 2 ) + cseg->m_y2 * ( 1 - t ) * t * 2 + cseg->m_y1 * pow( t, 2 );
1649  m_tempPoints.push_back( new a2dLineSegment( xw, yw ) );
1650  count++;
1651  t = t + tstep;
1652  }
1653  }
1654  break;
1655 
1657  nostrokeparts = true;
1658  case a2dPATHSEG_ARCTO:
1659  {
1660  a2dVpathArcSegment* cseg = ( a2dVpathArcSegment* ) seg.Get();
1661 
1662  double radius, center_x, center_y, beginrad, midrad, endrad, phit;
1663 
1664  if ( cseg->CalcR( path->operator[]( i ? i - 1 : 0 ), radius, center_x, center_y, beginrad, midrad, endrad, phit ) )
1665  {
1666  double dphi;
1667  unsigned int segments;
1668  double radiusDev = m_usertodevice.TransformDistance( radius );
1669  Aberration( m_displayaberration, phit, radiusDev , dphi, segments );
1670 
1671  double theta = beginrad;
1672  unsigned int step;
1673 
1674  for ( step = 0; step < segments + 1; step++ )
1675  {
1676  m_tempPoints.push_back( new a2dLineSegment( center_x + radius * cos ( theta ), center_y + radius * sin ( theta ) ) );
1677  count++;
1678  theta = theta + dphi;
1679  }
1680  }
1681  else
1682  {
1683  m_tempPoints.push_back( new a2dLineSegment( cseg->m_x1, cseg->m_y1 ) );
1684  count++;
1685  }
1686  }
1687  default:
1688  break;
1689  break;
1690  }
1691 
1692  if ( move )
1693  {
1694  DrawLines( &m_tempPoints, false );
1695  move = false;
1696  count = 0;
1697  m_tempPoints.clear();
1698  }
1699  else if ( seg->GetClose() != a2dPATHSEG_END_OPEN )
1700  {
1701  if ( nostrokeparts || seg->GetClose() == a2dPATHSEG_END_CLOSED_NOSTROKE )
1702  {
1703  a2dStroke stroke = m_activestroke;
1705  DrawPolygon( &m_tempPoints, false, wxODDEVEN_RULE );
1706  SetDrawerStroke( stroke );
1707  nostrokeparts = true;
1708  }
1709  else
1710  {
1711  DrawPolygon( &m_tempPoints, false, wxODDEVEN_RULE );
1712  }
1713 
1714  move = false;
1715  count = 0;
1716  m_tempPoints.clear();
1717  }
1718  else if ( i == path->size() - 1 ) //last segment?
1719  {
1720  DrawLines( &m_tempPoints, false );
1721  }
1722  }
1723 
1724  if ( nostrokeparts )
1725  {
1726  m_tempPoints.clear();
1727  move = false;
1728  count = 0;
1729  nostrokeparts = false;
1730 
1731  double lastmovex = 0;
1732  double lastmovey = 0;
1733 
1734  for ( i = 0; i < path->size(); i++ )
1735  {
1736  a2dVpathSegmentPtr seg = path->operator[]( i );
1737  switch ( seg->GetType() )
1738  {
1739  case a2dPATHSEG_MOVETO:
1740  if ( count == 0 )
1741  {
1742  m_tempPoints.push_back( new a2dLineSegment( seg->m_x1, seg->m_y1 ) );
1743  lastmovex = seg->m_x1;
1744  lastmovey = seg->m_y1;
1745  count++;
1746  }
1747  else
1748  {
1749  i--;
1750  move = true;
1751  }
1752  break;
1753 
1754  case a2dPATHSEG_LINETO:
1755  m_tempPoints.push_back( new a2dLineSegment( seg->m_x1, seg->m_y1 ) );
1756  count++;
1757  break;
1758 
1763  if ( count == 0 )
1764  {
1765  m_tempPoints.push_back( new a2dLineSegment( seg->m_x1, seg->m_y1 ) );
1766  count++;
1767  }
1768  else
1769  {
1770  i--;
1771  nostrokeparts = true;
1772  }
1773  break;
1774 
1775  case a2dPATHSEG_CBCURVETO:
1776  {
1777  double xw, yw;
1778 
1779  double xwl = path->operator[]( i ? i - 1 : 0 )->m_x1;
1780  double ywl = path->operator[]( i ? i - 1 : 0 )->m_y1;
1781  a2dVpathCBCurveSegment* cseg = ( a2dVpathCBCurveSegment* ) seg.Get();
1782 
1783  int step;
1784  double t = 0;
1785  for ( step = 0; step <= SPLINE_STEP; step++ )
1786  {
1787  xw = xwl * pow( 1 - t, 3 ) + cseg->m_x2 * pow( 1 - t, 2 ) * t * 3 + cseg->m_x3 * ( 1 - t ) * t * t * 3 + cseg->m_x1 * pow( t, 3 );
1788  yw = ywl * pow( 1 - t, 3 ) + cseg->m_y2 * pow( 1 - t, 2 ) * t * 3 + cseg->m_y3 * ( 1 - t ) * t * t * 3 + cseg->m_y1 * pow( t, 3 );
1789  m_tempPoints.push_back( new a2dLineSegment( xw, yw ) );
1790  count++;
1791  t = t + tstep;
1792  }
1793  }
1794  break;
1795 
1796  case a2dPATHSEG_QBCURVETO:
1797  {
1798  double xw, yw;
1799 
1800  double xwl = path->operator[]( i ? i - 1 : 0 )->m_x1;
1801  double ywl = path->operator[]( i ? i - 1 : 0 )->m_y1;
1802  a2dVpathQBCurveSegment* cseg = ( a2dVpathQBCurveSegment* ) seg.Get();
1803 
1804  int step;
1805  double t = 0;
1806  for ( step = 0; step <= SPLINE_STEP; step++ )
1807  {
1808  xw = xwl * pow( 1 - t, 2 ) + cseg->m_x2 * ( 1 - t ) * t * 2 + cseg->m_x1 * pow( t, 2 );
1809  yw = ywl * pow( 1 - t, 2 ) + cseg->m_y2 * ( 1 - t ) * t * 2 + cseg->m_y1 * pow( t, 2 );
1810  m_tempPoints.push_back( new a2dLineSegment( xw, yw ) );
1811  count++;
1812  t = t + tstep;
1813  }
1814  }
1815  break;
1816 
1817  case a2dPATHSEG_ARCTO:
1818  {
1819  a2dVpathArcSegment* cseg = ( a2dVpathArcSegment* ) seg.Get();
1820 
1821  double radius, center_x, center_y, beginrad, midrad, endrad, phit;
1822 
1823  if ( cseg->CalcR( path->operator[]( i ? i - 1 : 0 ), radius, center_x, center_y, beginrad, midrad, endrad, phit ) )
1824  {
1825  double dphi;
1826  unsigned int segments;
1827  double radiusDev = m_usertodevice.TransformDistance( radius );
1828  Aberration( m_displayaberration, phit, radiusDev , dphi, segments );
1829 
1830  double theta = beginrad;
1831  unsigned int step;
1832 
1833  for ( step = 0; step < segments + 1; step++ )
1834  {
1835  m_tempPoints.push_back( new a2dLineSegment( center_x + radius * cos ( theta ), center_y + radius * sin ( theta ) ) );
1836  count++;
1837  theta = theta + dphi;
1838  }
1839  }
1840  else
1841  {
1842  m_tempPoints.push_back( new a2dLineSegment( cseg->m_x1, cseg->m_y1 ) );
1843  count++;
1844  }
1845  }
1846  default:
1847  break;
1848 
1849  break;
1850  }
1851 
1852  if ( move || nostrokeparts )
1853  {
1854  DrawLines( &m_tempPoints, false );
1855  move = false;
1856  nostrokeparts = false;
1857  m_tempPoints.clear();
1858  count = 0;
1859  }
1860  else if ( seg->GetClose() != a2dPATHSEG_END_OPEN )
1861  {
1862  if ( seg->GetClose() == a2dPATHSEG_END_CLOSED )
1863  {
1864  m_tempPoints.push_back( new a2dLineSegment( lastmovex, lastmovey ) );
1865  count++;
1866  }
1867  DrawLines( &m_tempPoints, false );
1868  nostrokeparts = false;
1869  move = false;
1870  m_tempPoints.clear();
1871  count = 0;
1872  }
1873  else if ( i == path->size() )
1874  {
1875  DrawLines( &m_tempPoints, false );
1876  }
1877  }
1878  }
1879 }
1880 
1881 void a2dDrawer2D::DrawPolyPolygon( a2dListOfa2dVertexList polylist, wxPolygonFillMode fillStyle )
1882 {
1883  if ( m_disableDrawing )
1884  return;
1885 
1886 
1887 }
1888 
1889 void a2dDrawer2D::DrawPolygon( a2dVertexArray* points, bool spline, wxPolygonFillMode fillStyle )
1890 {
1891  if ( m_disableDrawing )
1892  return;
1893 
1894  a2dBoundingBox devbox;
1895  bool smallPoly = false;
1896  int segments = ToDeviceLines( points, devbox, smallPoly );
1897 
1898  if ( segments == 0 )
1899  return;
1900 
1901  if ( smallPoly )
1902  {
1903  DeviceDrawLines( segments, spline );
1904  DeviceDrawLine( m_cpointsDouble[0].x, m_cpointsDouble[0].y, m_cpointsDouble[segments - 1].x, m_cpointsDouble[segments - 1].y );
1905  }
1906  else
1907  DeviceDrawPolygon( segments, spline, fillStyle );
1908 }
1909 
1910 void a2dDrawer2D::DrawPolygon( const a2dVertexList* list, bool spline, wxPolygonFillMode fillStyle )
1911 {
1912  if ( m_disableDrawing )
1913  return;
1914 
1915  a2dBoundingBox devbox;
1916  bool smallPoly = false;
1917  int segments = ToDeviceLines( list, devbox, smallPoly );
1918 
1919  if ( segments == 0 )
1920  return;
1921 
1922  if ( smallPoly )
1923  {
1924  DeviceDrawLines( segments, spline );
1925  DeviceDrawLine( m_cpointsDouble[0].x, m_cpointsDouble[0].y, m_cpointsDouble[segments - 1].x, m_cpointsDouble[segments - 1].y );
1926  }
1927  else
1928  DeviceDrawPolygon( segments, spline, fillStyle );
1929 }
1930 
1931 void a2dDrawer2D::DrawLines( a2dVertexArray* points, bool spline )
1932 {
1933  if ( m_disableDrawing )
1934  return;
1935 
1936  a2dBoundingBox devbox;
1937  bool smallPoly = false;
1938  int segments = ToDeviceLines( points, devbox, smallPoly );
1939 
1940  if ( segments > 0 )
1941  DeviceDrawLines( segments, spline );
1942 }
1943 
1944 void a2dDrawer2D::DrawLines( const a2dVertexList* list, bool spline )
1945 {
1946  if ( m_disableDrawing )
1947  return;
1948 
1949  a2dBoundingBox devbox;
1950  bool smallPoly = false;
1951  int segments = ToDeviceLines( list, devbox, smallPoly );
1952 
1953  if ( segments > 0 )
1954  DeviceDrawLines( segments, spline );
1955 }
1956 
1957 void a2dDrawer2D::DrawArc( double x1, double y1, double x2, double y2, double xc, double yc, bool chord )
1958 {
1959  if ( m_disableDrawing )
1960  return;
1961 
1962  double dx = x1 - xc;
1963  double dy = y1 - yc;
1964 
1965  double start;
1966  double end;
1967  double radius = sqrt( dx * dx + dy * dy );
1968 
1969  if ( x1 == x2 && y1 == y2 )
1970  {
1971  start = 0;
1972  end = 2.0 * wxPI;
1973  }
1974  else
1975  {
1976  if ( !dx && !dy )
1977  start = 0;
1978  else
1979  start = atan2( dy, dx );
1980 
1981  dx = x2 - xc;
1982  dy = y2 - yc;
1983 
1984  if ( !dx && !dy )
1985  end = 0;
1986  else
1987  end = atan2( dy, dx );
1988 
1989  end = end - start;
1990  if ( end <= 0 ) end += 2.0 * wxPI;
1991  if ( start < 0 ) start += 2.0 * wxPI;
1992  end = end + start;
1993  }
1994 
1995  DrawEllipticArc( xc, yc, 2.0 * radius, 2.0 * radius, start * 180.0 / wxPI, end * 180.0 / wxPI, chord );
1996 }
1997 
1998 void a2dDrawer2D::DrawEllipticArc( double xc, double yc, double width, double height, double sa, double ea, bool chord )
1999 {
2000  if ( m_disableDrawing )
2001  return;
2002 
2003  double start, end;
2004 
2005  start = wxDegToRad( sa );
2006  end = wxDegToRad( ea );
2007 
2008  end = end - start;
2009  if ( end <= 0 ) end += 2.0 * wxPI;
2010 
2011  if ( start < 0 ) start += 2.0 * wxPI;
2012 
2013  end = end + start;
2014 
2015  double dphi;
2016  unsigned int segments;
2017 
2018  //circular approximation of radius.
2019  double radiusDev = m_usertodevice.TransformDistance( wxMax( width, height ) );
2020  Aberration( m_displayaberration, end - start, radiusDev , dphi, segments );
2021 
2022  m_tempPoints.clear();
2023  double theta = start;
2024  unsigned int i;
2025  for ( i = 0; i < segments + 1; i++ )
2026  {
2027  m_tempPoints.push_back( new a2dLineSegment( xc + width / 2 * cos ( theta ), yc + height / 2 * sin ( theta ) ) );
2028  theta = theta + dphi;
2029  }
2030 
2031  if ( !chord )
2032  {
2033  m_tempPoints.push_back( new a2dLineSegment( xc, yc ) );
2035  }
2036  else
2037  DrawLines( &m_tempPoints );
2038 }
2039 
2040 void a2dDrawer2D::DrawCenterRoundedRectangle( double xc, double yc, double width, double height, double radius, bool pixelsize )
2041 {
2042  if ( m_disableDrawing )
2043  return;
2044 
2045  DrawRoundedRectangle( xc - width / 2, yc - height / 2, width, height, radius, pixelsize );
2046 }
2047 
2048 void a2dDrawer2D::DrawRoundedRectangle( double x, double y, double width, double height, double radius, bool pixelsize )
2049 {
2050  if ( m_disableDrawing )
2051  return;
2052 
2053  if ( pixelsize )
2054  {
2055  width = DeviceToWorldXRel( width );
2056  height = DeviceToWorldYRel( height );
2057  radius = DeviceToWorldXRel( radius );
2058  if( m_yaxis )
2059  height = -height;
2060  }
2061 
2062  if ( radius )
2063  {
2064  static const double sintab[9] =
2065  {
2066  1 - 0,
2067  1 - 0.19509032201612826784828486847702,
2068  1 - 0.38268343236508977172845998403040,
2069  1 - 0.55557023301960222474283081394853,
2070  1 - 0.70710678118654752440084436210485,
2071  1 - 0.83146961230254523707878837761791,
2072  1 - 0.92387953251128675612818318939679,
2073  1 - 0.98078528040323044912618223613424,
2074  1 - 1
2075  };
2076 
2077  m_tempPoints.clear();
2078  int i;
2079  if ( height > 0 )
2080  {
2081  for( i = 0; i <= 8; i++ )
2082  m_tempPoints.push_back( new a2dLineSegment( x + radius * sintab[i], y + radius * sintab[8 - i] ) );
2083  for( i = 0; i <= 8; i++ )
2084  m_tempPoints.push_back( new a2dLineSegment( x + radius * sintab[8 - i], y + height - radius * sintab[i] ) );
2085  for( i = 0; i <= 8; i++ )
2086  m_tempPoints.push_back( new a2dLineSegment( x + width - radius * sintab[i], y + height - radius * sintab[8 - i] ) );
2087  for( i = 0; i <= 8; i++ )
2088  m_tempPoints.push_back( new a2dLineSegment( x + width - radius * sintab[8 - i], y + radius * sintab[i] ) );
2089  }
2090  else
2091  {
2092  for( i = 0; i <= 8; i++ )
2093  m_tempPoints.push_back( new a2dLineSegment( x + radius * sintab[8-i], y - radius * sintab[i] ) );
2094  for( i = 0; i <= 8; i++ )
2095  m_tempPoints.push_back( new a2dLineSegment( x + width - radius * sintab[i], y - radius * sintab[8-i] ) );
2096  for( i = 0; i <= 8; i++ )
2097  m_tempPoints.push_back( new a2dLineSegment( x + width - radius * sintab[8-i], y + height + radius * sintab[i] ) );
2098  for( i = 0; i <= 8; i++ )
2099  m_tempPoints.push_back( new a2dLineSegment( x + radius * sintab[i], y + height + radius * sintab[8-i] ) );
2100  }
2102 
2103  }
2104  else
2105  {
2106  //in a rectangle of say 5 by 5, the last pixel is 4,4 but that should be handle at device level i think, not here in world coordinates
2107  m_tempPoints.clear();
2108  m_tempPoints.push_back( new a2dLineSegment( x, y ) );
2109  m_tempPoints.push_back( new a2dLineSegment( x, y + height ) );
2110  m_tempPoints.push_back( new a2dLineSegment( x + width, y + height ) );
2111  m_tempPoints.push_back( new a2dLineSegment( x + width, y ) );
2113  }
2114 }
2115 
2116 void a2dDrawer2D::DrawCircle( double xc, double yc, double radius )
2117 {
2118  DrawEllipse( xc, yc, 2.0 * radius, 2.0 * radius );
2119 }
2120 
2121 void a2dDrawer2D::DrawEllipse( double xc, double yc, double width, double height )
2122 {
2123  if ( m_disableDrawing )
2124  return;
2125 
2126  double dphi;
2127  unsigned int segments;
2128 
2129  if ( width == 0 && height == 0 )
2130  {
2131  DrawPoint( xc, yc );
2132  return;
2133  }
2134 
2135  //circular approximation of radius.
2136  double radiusDev = m_usertodevice.TransformDistance( wxMax( width, height ) );
2137  Aberration( m_displayaberration, wxPI * 2, radiusDev , dphi, segments );
2138 
2139  /* limit the number of segments on a circle
2140  if the circle is small only a few segments need to be drawn.
2141  ie for a circle of 4x4 pixels, roughly 8 segments are needed
2142  The number of segments could be tuned with a fiddle factor (now 1.0).
2143  n = (width_pixels + height_pixels) * fiddle_factor;
2144  */
2145  double m00 = m_usertodevice.GetValue( 0, 0 ) * width;
2146  double m01 = m_usertodevice.GetValue( 0, 1 ) * width;
2147  double m10 = m_usertodevice.GetValue( 1, 0 ) * height;
2148  double m11 = m_usertodevice.GetValue( 1, 1 ) * height;
2149  double n = fabs( m00 + m10 ) + fabs( m01 + m11 ); // * fiddle_factor
2150  if ( segments > n )
2151  {
2152  segments = ( int ) ceil( n );
2153  dphi = 2.0 * wxPI / segments;
2154  }
2155 
2156  m_tempPoints.clear();
2157  double theta;
2158  unsigned int i;
2159  for ( i = 0; i < segments ; i++ )
2160  {
2161  theta = i * dphi;
2162  m_tempPoints.push_back( new a2dLineSegment( xc + width / 2 * cos ( theta ), yc - height / 2 * sin ( theta ) ) );
2163  }
2165 }
2166 
2167 void a2dDrawer2D::DrawLine( double x1, double y1, double x2, double y2 )
2168 {
2169  if ( m_disableDrawing )
2170  return;
2171 
2172  m_tempPoints.clear();
2173  m_tempPoints.push_back( new a2dLineSegment( x1, y1 ) );
2174  m_tempPoints.push_back( new a2dLineSegment( x2, y2 ) );
2175  DrawLines( &m_tempPoints );
2176 }
2177 
2179 {
2180  // set text linestroke.
2182  a2dStroke oldstroke = m_activestroke;
2183  SetActiveStroke( stroke );
2184 
2185  if ( c != wxChar( ' ' ) )
2186  {
2187  double desc = m_currentfont.GetDescent();
2188  double size = m_currentfont.GetSize();
2189  double width = m_currentfont.GetWidth( c );
2190  DrawLine( 0.1 * width, desc, 0.9 * width, desc + size );
2191  DrawLine( 0.9 * width, desc, 0.1 * width, desc + size );
2192  }
2193 
2194  // restore context
2195  SetActiveStroke( oldstroke );
2196 }
2197 
2198 void a2dDrawer2D::DrawTextUnknown( const wxString& text, double x, double y, bool words )
2199 {
2200  if ( m_disableDrawing )
2201  return;
2202 
2203  const double h = m_currentfont.GetLineHeight();
2204  x = y = 0;
2205  if ( words && m_currentfont.Ok() )
2206  {
2207  // Draw a piece of line for each word.
2208  // set text linestroke.
2209  a2dStroke strokew = a2dStroke( m_activestroke.GetColour(), 1 );
2210  a2dStroke oldstroke = m_activestroke;
2211  SetActiveStroke( strokew );
2212 
2213  double w;
2214  wxChar c;
2215  double start = x;
2216  for ( size_t i = 0; i < text.Length(); i++ )
2217  {
2218  c = text[i];
2219  w = m_currentfont.GetWidth( c );
2220  if ( c == wxChar( ' ' ) )
2221  {
2222  if ( x != start )
2223  DrawLine( start, h / 2.0, x, h / 2.0 );
2224  start = x + w;
2225  }
2226  x += w;
2227  }
2228  if ( x != start )
2229  DrawLine( start, h / 2.0, x, h / 2.0 );
2230 
2231  // restore context
2232  SetActiveStroke( oldstroke );
2233  }
2234  else
2235  {
2236  a2dBoundingBox linebbox = m_currentfont.GetTextExtent( text, m_yaxis );
2237 
2238  DrawRoundedRectangle( linebbox.GetMinX(), linebbox.GetMinY(),
2239  linebbox.GetWidth(), linebbox.GetHeight(), 0 );
2240  DrawLine( linebbox.GetMinX(), linebbox.GetMinY(), linebbox.GetMaxX(), linebbox.GetMaxY() );
2241  DrawLine( linebbox.GetMinX(), linebbox.GetMaxY(), linebbox.GetMaxX(), linebbox.GetMinY() );
2242  }
2243 }
2244 
2245 void a2dDrawer2D::DrawTextStroke( const wxString& text, double x, double y )
2246 {
2247  // set text linestroke.
2248  //!todo what about the style (pixel or not of stroke font )
2249  a2dStroke oldstroke = m_activestroke;
2250 
2251  double width = m_currentfont.GetStrokeWidth();
2252  double widthdevice = m_usertodevice.TransformDistance( width );
2253  if ( widthdevice < 1 )//width
2254  {
2255  a2dStroke stroke = a2dStroke( m_activestroke.GetColour(), 0 );
2256  SetDrawerStroke( stroke );
2257  //SetActiveStroke( stroke );
2258  }
2259  else
2260  {
2261  a2dStroke stroke = a2dStroke( m_activestroke.GetColour(), width );
2262  a2dStroke oldstroke = m_activestroke;
2263  SetDrawerStroke( stroke );
2264  //SetActiveStroke( stroke );
2265  }
2267  SetActiveStroke( oldstroke );
2268 }
2269 
2271 {
2272  // scale character to size
2273  a2dAffineMatrix affine;
2274  affine.Scale( m_currentfont.GetSize() );
2275  PushTransform( affine );
2276 
2278  if ( ptr )
2279  {
2280  while ( *ptr )
2281  {
2282  DrawLines( *ptr, false );
2283  ptr++;
2284  }
2285  }
2286 
2287  // restore context
2288  PopTransform();
2289 }
2290 
2291 void a2dDrawer2D::DrawTextGeneric( const wxString& text, double x, double y, void ( a2dDrawer2D::*drawchar )( wxChar ) )
2292 {
2293  const double h = m_currentfont.GetLineHeight();
2294  bool textwasvisible = false;
2295 
2296  double w = 0.0;
2297  wxChar c = 0;
2298  const size_t n = text.Length();
2299  for ( size_t i = 0; i < n; i++ )
2300  {
2301  const wxChar oldc = c;
2302  c = text[i];
2303  if ( i > 0 )
2304  {
2305  m_usertoworld *= a2dAffineMatrix( w + m_currentfont.GetKerning( oldc, c ), 0.0 );
2307  }
2308  w = m_currentfont.GetWidth( c );
2309 
2310  // get absolute character bounding box
2311  a2dBoundingBox bbox( 0.0, 0.0, w, h );
2312  bbox.MapBbox( m_usertoworld );
2313 
2314  // if character is not outside clipping box, draw it.
2315  if ( m_clipboxworld.Intersect( bbox ) != _OUT )
2316  {
2317  ( this->*drawchar )( c );
2318  textwasvisible = true;
2319  }
2320  else if ( textwasvisible )
2321  {
2322  // If characters of a string had been visible, and this character is not
2323  // visible, then so will all succeeding. i.o.w. we can stop drawing.
2324  break;
2325  }
2326  }
2327 }
2328 
2329 void a2dDrawer2D::DrawText( const wxString& text, double x, double y, int alignment, bool Background )
2330 {
2331  if ( m_disableDrawing )
2332  return;
2333 
2334  // Get font size in device units, also takes stretching into account
2335  double dx, dy, size;
2336  dx = m_usertodevice.GetValue( 1, 0 );
2337  dy = m_usertodevice.GetValue( 1, 1 );
2338  size = m_currentfont.GetSize() * sqrt( dx * dx + dy * dy );
2339  //size = m_usertodevice.TransformDistance( m_a2dfont.GetSize() );
2340 
2341  if ( size > TEXT_MAXSIZE_INPIXELS )
2342  return;
2343 
2344  bool oldforce = m_forceNormalizedFont;
2345  if ( m_forceNormalizedFont || size > m_smallTextThreshold )
2346  {
2347  m_currentfont.SetDeviceHeight( NORMFONT );
2348  //m_currentfont.SetDeviceHeight( size );
2349  m_forceNormalizedFont = true;
2350  }
2351  else
2352  m_currentfont.SetDeviceHeight( size );
2353 
2354  // Get the bounding box, including alignment displacement.
2355  a2dBoundingBox bbox = m_currentfont.GetTextExtent( text, alignment );
2356  bbox.Translate( x, y );
2357 
2358  // Get unaligned coordinates for DrawTextXXX functions. By default these functions
2359  // use the lowerleft corner of the boundingbox, hence GetMinX() and GetMinY().
2360  x = bbox.GetMinX();
2361  y = bbox.GetMinY();
2362 
2363  // Transform user bbox to world bbox.
2364  a2dBoundingBox worldbbox( bbox );
2365  worldbbox.MapBbox( m_usertoworld );
2366  // If bbox not outside clipping area, draw the text
2367  if ( m_clipboxworld.Intersect( worldbbox ) != _OUT )
2368  {
2369  // Draw background fill
2370  if ( size > m_drawingthreshold &&
2371  Background && !GetDrawerFill().IsNoFill() && !GetDrawerFill().GetStyle() == a2dFILL_TRANSPARENT )
2372  {
2373  a2dStroke oldstroke = m_activestroke;
2375  DrawRoundedRectangle( bbox.GetMinX(), bbox.GetMinY(),
2376  bbox.GetWidth(), bbox.GetHeight(), 0 );
2377  SetDrawerStroke( oldstroke );
2378  }
2379 
2380  /* DEBUG text boundingbox
2381  a2dStroke oldstroke = m_activestroke;
2382  SetDrawerStroke( *a2dBLACK_STROKE );
2383  DrawRoundedRectangle( bbox.GetMinX(), bbox.GetMinY(),
2384  bbox.GetWidth(), bbox.GetHeight(), 0 );
2385  SetDrawerStroke( oldstroke );
2386  */
2387 
2388 
2389 
2390  // mirror text, depending on y-axis orientation
2391  const double h = m_currentfont.GetLineHeight();
2392  a2dAffineMatrix affine;
2393  if ( !GetYaxis() )
2394  {
2395  affine.Translate( 0.0, -h );
2396  affine.Mirror( true, false );
2397  }
2398  // position text
2399  affine.Translate( x, y );
2400  PushTransform( affine );
2401 
2402  // If text > threshold, draw text
2403  if ( size > m_drawingthreshold )
2404  {
2405  // Try to find the appropriate drawing function.
2406  switch ( m_currentfont.GetType() )
2407  {
2408  case a2dFONT_STROKED:
2409  DrawTextStroke( text, x, y );
2410  break;
2411  case a2dFONT_FREETYPE:
2412  DrawTextFreetype( text, x, y );
2413  break;
2414  case a2dFONT_WXDC:
2415  DrawTextDc( text, x, y );
2416  break;
2417  default:
2418  DrawTextUnknown( text, x, y );
2419  }
2420  }
2421  // If text < threshold, draw a simple version.
2422  else
2423  DrawTextUnknown( text, x, y, true );
2424 
2425  PopTransform();
2426  }
2427 
2428  m_forceNormalizedFont = oldforce;
2429  //m_currentfont.SetDeviceHeight( NORMFONT );
2430 
2431 }
2432 
2433 //use by polygon filling
2434 //moves the scanline up
2435 //index is the index of the point where the search begins
2436 //direction is +1 or -1 and indicates if the segment ascends or decends
2437 bool a2dDrawer2D::MoveUp( int n, wxRealPoint points[] , double horline, int& index, int direction )
2438 {
2439  int walk = ( index + direction + n ) % n;
2440  while ( points[walk].y < horline )
2441  {
2442  if ( points[walk].y < points[index].y )
2443  return false;
2444  else
2445  {
2446  //modify index
2447  index = walk;
2448  walk = ( index + direction + n ) % n;
2449  }
2450  }
2451  return true;
2452 }
2453 
2454 //a crictical point is a point between a decending and a ascending segment
2455 //collect those points for filling later
2456 void a2dDrawer2D::DetectCriticalPoints( int n, wxRealPoint points[] )
2457 {
2458  //candidate for critical point
2459  //true if Y is getting lower, unchanged i Y is unchanged
2460  //and if Y becomes higher and candidate was true: it is a critical point
2461  bool candidate = false;
2462  int i, j;
2463 
2464  for ( i = 0; i < n; i++ )
2465  {
2466  //j next point
2467  j = ( i + 1 ) % n;
2468 
2469  //check if Y is smaller
2470  if ( points[i].y > points[j].y )
2471  //we have a candidate
2472  candidate = true;
2473  else if ( ( points[i].y < points[j].y ) && candidate )
2474  {
2475  //this is a critical point put in list
2476  bool inserted = false;
2477  a2dCriticalPointList::compatibility_iterator node = m_CRlist.GetFirst();
2478  while ( node )
2479  {
2480  //sorted on smallest Y value
2481  int* ind = node->GetData();
2482  if ( points[*ind].y > points[i].y )
2483  {
2484  m_CRlist.Insert( node, new int( i ) );
2485  inserted = true;
2486  break;
2487  }
2488  node = node->GetNext();
2489  }
2490  if ( !inserted )
2491  m_CRlist.Append( new int( i ) );
2492  candidate = false;
2493  }
2494  }
2495  if ( candidate )
2496  {
2497  for ( i = 0; i < n; i++ )
2498  {
2499  //j next point
2500  j = ( i + 1 ) % n;
2501 
2502  //check if Y is smaller
2503  if ( points[i].y > points[j].y )
2504  //we have a candidate
2505  candidate = true;
2506  else if ( ( points[i].y < points[j].y ) && candidate )
2507  {
2508  //this is a critical point put in list
2509  bool inserted = false;
2510  a2dCriticalPointList::compatibility_iterator node = m_CRlist.GetFirst();
2511  while ( node )
2512  {
2513  //sorted on smallest Y value
2514  int* ind = node->GetData();
2515  if ( points[*ind].y > points[i].y )
2516  {
2517  m_CRlist.Insert( node, new int( i ) );
2518  inserted = true;
2519  break;
2520  }
2521  node = node->GetNext();
2522  }
2523  if ( !inserted )
2524  m_CRlist.Append( new int( i ) );
2525  candidate = false;
2526  }
2527  }
2528  }
2529 }
2530 
2531 static int SortonXs( const void* f, const void* s )
2532 {
2533  const a2dAET** first =(const a2dAET **)f;
2534  const a2dAET** second =(const a2dAET **)s;
2535 
2536  if ( ( *first )->m_xs < ( *second )->m_xs )
2537  return -1;
2538  else if ( ( *first )->m_xs > ( *second )->m_xs )
2539  return 1;
2540 
2541  return 0;
2542 }
2543 
2544 void a2dDrawer2D::ColourXYLinear( int x1, int x2, int y )
2545 {
2546  int dred = m_colour2redFill - m_colour1redFill;
2547  int dgreen = m_colour2greenFill - m_colour1greenFill;
2548  int dblue = m_colour2blueFill - m_colour1blueFill;
2549 
2550  if ( m_dx1 == m_dx2 )
2551  {
2552  //total number of lines to go from m_textbg to m_textfg
2553  //gives the following number of steps for the gradient color
2554  double stepcol = m_max_y - m_min_y;
2555 
2556  double curcol = y - m_min_y;
2557 
2558  a2dStroke current = GetDrawerStroke();
2559  wxColour gradcol( ( unsigned char ) ( m_colour1redFill + dred * curcol / stepcol ),
2560  ( unsigned char ) ( m_colour1greenFill + dgreen * curcol / stepcol ),
2561  ( unsigned char ) ( m_colour1blueFill + dblue * curcol / stepcol ) );
2562  a2dStroke gradientstroke = a2dStroke( gradcol, 0 );
2563  SetDrawerStroke( gradientstroke );
2564  DeviceDrawHorizontalLine( x1, y, x2, true );
2565  SetDrawerStroke( current );
2566  }
2567  else
2568  {
2569  int j;
2570  for ( j = x1; j <= x2; j++ )
2571  {
2572  a2dLine perstroke( j, y, j + m_dy2 - m_dy1, y + m_dx2 - m_dx1 );
2573  a2dPoint2D crossing;
2574  perstroke.CalculateLineParameters();
2575  perstroke.Intersect( m_line, crossing );
2576 
2577  double length = sqrt( ( double ) ( crossing.m_x - m_dx1 ) * ( crossing.m_x - m_dx1 ) + ( crossing.m_y - m_dy1 ) * ( crossing.m_y - m_dy1 ) );
2578 
2579  if ( length > m_length )
2580  length = m_length;
2581 
2582  DeviceDrawPixel( j, y, m_colour1redFill + dred * int( length / m_length ),
2583  m_colour1greenFill + dgreen * int( length / m_length ),
2584  m_colour1blueFill + dblue * int( length / m_length ) );
2585  }
2586  }
2587 }
2588 
2589 void a2dDrawer2D::ColourXYRadial( int x1, int x2, int y )
2590 {
2591  int dred = m_colour2redFill - m_colour1redFill;
2592  int dgreen = m_colour2greenFill - m_colour1greenFill;
2593  int dblue = m_colour2blueFill - m_colour1blueFill;
2594 
2595  int j;
2596  for ( j = x1; j <= x2; j++ )
2597  {
2598  double cradius = sqrt( ( double ) ( j - m_dx1 ) * ( j - m_dx1 ) + ( y - m_dy1 ) * ( y - m_dy1 ) );
2599 
2600  double delta;
2601  if ( m_radiusd == 0 )
2602  delta = 0;
2603  else if ( cradius > m_radiusd )
2604  delta = 1;
2605  else
2606  delta = cradius / m_radiusd;
2607 
2608  DeviceDrawPixel( j, y, ( unsigned char ) ( m_colour1redFill + dred * delta ),
2609  ( unsigned char ) ( m_colour1greenFill + dgreen * delta ),
2610  ( unsigned char ) ( m_colour1blueFill + dblue * delta ) );
2611  }
2612 }
2613 
2614 void a2dDrawer2D::FillPolygon( int n, wxRealPoint points[] )
2615 {
2616  wxRect clip;
2617  GetClippingBoxDev( clip.x, clip.y, clip.width, clip.height );
2618 
2619 
2620  m_min_y = points[0].y;
2621  m_max_y = points[0].y;
2622  m_min_x = points[0].x;
2623  m_max_x = points[0].x;
2624  double centroidx = 0;
2625  double centroidy = 0;
2626  int i;
2627  for ( i = 0; i < n; i++ )
2628  {
2629  m_min_y = wxMin( m_min_y, points[i].y );
2630  m_max_y = wxMax( m_max_y, points[i].y );
2631  m_min_x = wxMin( m_min_x, points[i].x );
2632  m_max_x = wxMax( m_max_x, points[i].x );
2633  centroidx += points[i].x;
2634  centroidy += points[i].y;
2635  }
2636 
2637  centroidx /= double( n );
2638  centroidy /= double( n );
2639 
2640  int index;
2641 
2642  if ( m_activefill.GetType() == a2dFILL_GRADIENT_FILL_LINEAR )
2643  {
2644  double x1 = m_activefill.GetStart().m_x;
2645  double y1 = m_activefill.GetStart().m_y;
2646  double x2 = m_activefill.GetStop().m_x;
2647  double y2 = m_activefill.GetStop().m_y;
2648  m_usertodevice.TransformPoint( x1, y1, m_dx1, m_dy1 );
2649  m_usertodevice.TransformPoint( x2, y2, m_dx2, m_dy2 );
2650  if ( m_dx1 == m_dx2 && m_dy1 == m_dy2 )
2651  {
2652  //do a linear fill vertical
2653  m_dx1 = centroidx;
2654  m_dy1 = m_min_y;
2655  m_dx2 = centroidx;
2656  m_dy2 = m_max_y;
2657  if ( m_dx1 == m_dx2 && m_dy1 == m_dy2 )
2658  m_dx2 = m_dx2 + 100;
2659  }
2660  m_length = sqrt ( ( m_dx1 - m_dx2 ) * ( m_dx1 - m_dx2 ) + ( m_dy1 - m_dy2 ) * ( m_dy1 - m_dy2 ) );
2661  m_line = a2dLine( m_dx1, m_dy1, m_dx2, m_dy2 );
2662  m_line.CalculateLineParameters();
2663  }
2664  else if ( m_activefill.GetType() == a2dFILL_GRADIENT_FILL_RADIAL )
2665  {
2666  double xfc = m_activefill.GetFocal().m_x;
2667  double yfc = m_activefill.GetFocal().m_y;
2668  double xe = m_activefill.GetCenter().m_x;
2669  double ye = m_activefill.GetCenter().m_y;
2670  m_usertodevice.TransformPoint( xfc, yfc, m_dx1, m_dy1 );
2671  m_usertodevice.TransformPoint( xe, ye, m_dx2, m_dy2 );
2672  if ( m_dx1 == m_dx2 && m_dy1 == m_dy2 )
2673  {
2674  //no start stop given
2675  m_dx1 = centroidx;
2676  m_dy1 = centroidy;
2677  m_dx2 = centroidx;
2678  m_dy2 = m_max_y;
2679 
2680  if ( m_dx1 == m_dx2 && m_dy1 == m_dy2 )
2681  m_dx2 = m_dx2 + 10;
2682  }
2683  double dx3, dy3;
2684  m_usertodevice.TransformPoint( xe, ye + m_activefill.GetRadius(), dx3, dy3 );
2685  m_radiusd = sqrt ( ( dx3 - m_dx2 ) * ( dx3 - m_dx2 ) + ( dy3 - m_dy2 ) * ( dy3 - m_dy2 ) );
2686  }
2687 
2688  DetectCriticalPoints( n, points );
2689 
2690  int min = ( int ) wxMax ( m_min_y, clip.y );
2691  int max = ( int ) wxMin ( m_max_y, clip.y + clip.height );
2692 
2693  for ( i = min; i < max; i++ )
2694  {
2695  a2dAETList::compatibility_iterator node = m_AETlist.GetFirst();
2696  int count = m_AETlist.size();
2697  while ( count > 0 )
2698  {
2699  a2dAET* ele = node->GetData();
2700  index = ele->m_index;
2701  int direction = ele->m_direction;
2702  if ( !MoveUp( n, points, i, index, direction ) )
2703  {
2704  a2dAETList::compatibility_iterator h = node;
2705  //remove this node
2706  node = node->GetNext();
2707  delete h->GetData();
2708  m_AETlist.DeleteNode( h );
2709  }
2710  else
2711  {
2712  if ( ele->m_index != index )
2713  {
2714  ele->m_index = index;
2715  int h = ( index + direction + n ) % n;
2716  ele->CalculateLineParameters( points[h], points[index] );
2717  }
2718  if ( ele->m_horizontal )
2719  ele->m_xs = ( int ) points[index].x;
2720  else
2721  ele->CalculateXs( i );
2722  node = node->GetNext();
2723  }
2724  count--;
2725  }
2726 
2727  a2dCriticalPointList::compatibility_iterator nodec = m_CRlist.GetFirst();
2728  while ( m_CRlist.size() && points[*nodec->GetData()].y <= i )
2729  {
2730  int DI;
2731  for ( DI = -1; DI <= 1 ; DI += 2 )
2732  {
2733  index = *nodec->GetData();
2734  if ( MoveUp( n, points, i, index, DI ) )
2735  {
2736  a2dAET* ele = new a2dAET();
2737  ele->m_index = index;
2738  ele->m_direction = DI;
2739  int h = ( index + DI + n ) % n;
2740  ele->CalculateLineParameters( points[h], points[index] );
2741  if ( ele->m_horizontal )
2742  ele->m_xs = ( int ) points[index].x;
2743  else
2744  ele->CalculateXs( i );
2745 
2746  //insert in sorted order of m_xs
2747  bool inserted = false;
2748  node = m_AETlist.GetFirst();
2749  while ( node )
2750  {
2751  //sorted on smallest xs value
2752  if ( ele->m_xs < ( node->GetData() )->m_xs )
2753  {
2754  m_AETlist.Insert( node, ele );
2755  inserted = true;
2756  break;
2757  }
2758 // TODO to make sorting work (is eqaul in xs the sorting can be wrong
2759  node = node->GetNext();
2760  }
2761  if ( !inserted )
2762  m_AETlist.Append( ele );
2763  }
2764  }
2765 
2766  a2dCriticalPointList::compatibility_iterator h = nodec;
2767  nodec = nodec->GetNext();
2768  delete h->GetData();
2769  m_CRlist.DeleteNode( h );
2770  }
2771 
2772  //and since i am not smart enough to insert sorted when xs is equal
2773  //sort again and again :-((
2774  if ( m_AETlist.GetCount() > 1 )
2775  {
2776  if ( m_AETlist.GetCount() > 2 )
2777  m_AETlist.Sort( SortonXs );
2778  else if ( m_AETlist.GetFirst()->GetData()->m_xs > m_AETlist.GetLast()->GetData()->m_xs )
2779  {
2780  a2dAET* f = m_AETlist.GetFirst()->GetData();
2781  m_AETlist.GetFirst()->SetData( m_AETlist.GetLast()->GetData() );
2782  m_AETlist.GetLast()->SetData( f );
2783  }
2784  }
2785 
2786  //m_AETlist must be sorted in m_xs at this moment
2787  //now draw all the line parts on one horizontal scanline (Winding Rule)
2788  int out = 0;
2789  node = m_AETlist.GetFirst();
2790  while ( node )
2791  {
2792  a2dAET* ele = node->GetData();
2793  out += ele->m_direction;
2794 
2795  if ( out != 0 )
2796  {
2797  int x1 = ( int ) ele->m_xs;
2798  node = node->GetNext();
2799  if ( node )
2800  {
2801  ele = node->GetData();
2802  int x2 = ( int ) ele->m_xs;
2803 
2804  if ( x1 < clip.x ) x1 = clip.x;
2805  if ( x2 > clip.x + clip.width ) x2 = clip.x + clip.width;
2806  if ( i >= clip.y && i <= clip.y + clip.height && ( x1 != x2 ) )
2807  {
2808  if ( m_activefill.GetType() == a2dFILL_GRADIENT_FILL_LINEAR )
2809  ColourXYLinear( x1, x2, i );
2810  else if ( m_activefill.GetType() == a2dFILL_GRADIENT_FILL_RADIAL )
2811  ColourXYRadial( x1, x2, i );
2812  else
2813  DeviceDrawHorizontalLine( x1, i, x2, false );
2814  }
2815  }
2816  //something is wrong if we arrive here.
2817  }
2818  else
2819  node = node->GetNext();
2820  }
2821  }
2822 
2823  a2dAETList::compatibility_iterator node = m_AETlist.GetFirst();
2824  while ( node )
2825  {
2826  a2dAETList::compatibility_iterator h = node;
2827  delete h->GetData();
2828  m_AETlist.DeleteNode( h );
2829  node = m_AETlist.GetFirst();
2830  }
2831 
2832  a2dCriticalPointList::compatibility_iterator nodec = m_CRlist.GetFirst();
2833  while ( nodec )
2834  {
2835  a2dCriticalPointList::compatibility_iterator h = nodec;
2836  delete h->GetData();
2837  m_CRlist.DeleteNode( h );
2838  nodec = m_CRlist.GetFirst();
2839  }
2840 
2841 }
2842 
2843 //-----------------------------------------------------------------------------------
2844 // Clipping region
2845 //-----------------------------------------------------------------------------------
2846 
2847 // Clipping of line in world coordinates
2848 // Function return a value of where the point is in the space.
2849 // The screen is the one with the double lines below (in the middle)
2850 // If the given point is on the right of this window -> 2 is returned
2851 int a2dDrawer2D::GetClipCode( double x, double y )
2852 {
2853  // 9 | 8 | 10
2854  // | |
2855  // ------============--------- Y-max
2856  // 1 || 0 || 2
2857  // || ||
2858  // ------============--------- Y-min
2859  // 5 | 4 | 6
2860  // | |
2861  // X-min X-max
2862  //
2863  int p = 0;
2864 
2865  if ( x < m_clipboxworld.GetMinX() )
2866  p |= 0x0001;
2867  else if ( x > m_clipboxworld.GetMaxX() )
2868  p |= 0x0002;
2869  if ( y < m_clipboxworld.GetMinY() )
2870  p |= 0x0004;
2871  else if ( y > m_clipboxworld.GetMaxY() )
2872  p |= 0x0008;
2873 
2874  return p;
2875 }
2876 
2877 // return true if the line is inside the window
2878 bool a2dDrawer2D::Clipping( double& x1, double& y1, double& x2, double& y2 )
2879 {
2880  int clipcode1, clipcode2;
2881  int nr_of_intersections = 0;
2882 
2883  // intersection points are used if the line falls from the screen
2884  double intersectionpoint1[2];
2885  double intersectionpoint2[2];
2886  double A, B, temppoint;
2887  double RC = 0;
2888  double T = 0;
2889 
2890  // call clipcode from each point from the line
2891  clipcode1 = GetClipCode( x1, y1 );
2892  clipcode2 = GetClipCode( x2, y2 );
2893 
2894  // are both points within the window?
2895  if ( !clipcode1 && !clipcode2 ) return true;
2896  // then draw the line
2897 
2898  // is point (x1,y1) inside the window?
2899  if ( !clipcode1 )
2900  {
2901  intersectionpoint1[0] = x1;
2902  intersectionpoint2[0] = y1;
2903 
2904  nr_of_intersections = 1;
2905  }
2906 
2907  // is point (x2,y2) inside the window?
2908  if ( !clipcode2 )
2909  {
2910  intersectionpoint1[0] = x2;
2911  intersectionpoint2[0] = y2;
2912 
2913  nr_of_intersections = 1;
2914  }
2915 
2916  clipcode1 ^= clipcode2;
2917 
2918  // We can make the following linefunction:
2919  // y = (A/B)x + C
2920  // calculate the slope of the line
2921  A = y2 - y1;
2922  B = x2 - x1;
2923 
2924  if ( B )
2925  {
2926  RC = A / B; // RC is slope
2927  T = y1 - x1 * RC;
2928  }
2929 
2930  if ( clipcode1 & 0x0004 )
2931  {
2932  // intersect lowerbound with the line
2933  if ( B ) temppoint = ( m_clipboxworld.GetMinY() - T ) / RC;
2934  else temppoint = x1; // perpendicular line
2935 
2936  // calculate intersection points
2937  if ( temppoint >= m_clipboxworld.GetMinX() && temppoint <= m_clipboxworld.GetMaxX() )
2938  {
2939  intersectionpoint1[nr_of_intersections] = temppoint;
2940  intersectionpoint2[nr_of_intersections++] = m_clipboxworld.GetMinY();
2941  }
2942  }
2943 
2944  if ( clipcode1 & 0x0008 )
2945  {
2946  // intersect upperbound with the line
2947  if ( B ) temppoint = ( m_clipboxworld.GetMaxY() - T ) / RC;
2948  else temppoint = x1; // loodrechte lijn
2949 
2950  if ( temppoint >= m_clipboxworld.GetMinX() && temppoint <= m_clipboxworld.GetMaxX() )
2951  {
2952  intersectionpoint1[nr_of_intersections] = temppoint;
2953  intersectionpoint2[nr_of_intersections++] = m_clipboxworld.GetMaxY();
2954  }
2955  }
2956 
2957  if ( clipcode1 & 0x0001 )
2958  {
2959  // intersect leftbound with the line
2960  temppoint = RC * m_clipboxworld.GetMinX() + T;
2961  if ( temppoint > m_clipboxworld.GetMinY() && temppoint < m_clipboxworld.GetMaxY() )
2962  {
2963  intersectionpoint2[nr_of_intersections] = temppoint;
2964  intersectionpoint1[nr_of_intersections++] = m_clipboxworld.GetMinX();
2965  }
2966  }
2967 
2968  if ( clipcode1 & 0x0002 )
2969  {
2970  // intersect rightbound with the line
2971  temppoint = RC * m_clipboxworld.GetMaxX() + T;
2972  if ( temppoint > m_clipboxworld.GetMinY() && temppoint < m_clipboxworld.GetMaxY() )
2973  {
2974  intersectionpoint2[nr_of_intersections] = temppoint;
2975  intersectionpoint1[nr_of_intersections++] = m_clipboxworld.GetMaxX();
2976  }
2977  }
2978 
2979  if ( nr_of_intersections != 2 ) return false;
2980 
2981  // set the new values in the parameters (these are references)
2982  x1 = intersectionpoint1[0];
2983  y1 = intersectionpoint2[0];
2984  x2 = intersectionpoint1[1];
2985  y2 = intersectionpoint2[1];
2986 
2987  return true;
2988 }
2989 
2990 void a2dDrawer2D::GetClippingBoxDev( int& x, int& y, int& w, int& h ) const
2991 {
2992  x = m_clipboxdev.x;
2993  y = m_clipboxdev.y;
2994  w = m_clipboxdev.width;
2995  h = m_clipboxdev.height;
2996 }
2997 
2998 void a2dDrawer2D::GetClippingMinMax( double& xmin, double& ymin, double& xmax, double& ymax ) const
2999 {
3000  xmin = m_clipboxworld.GetMinX();
3001  ymin = m_clipboxworld.GetMinY();
3002  xmax = m_clipboxworld.GetMaxX();
3003  ymax = m_clipboxworld.GetMaxY();
3004 }
3005 
3006 void a2dDrawer2D::GetClippingBox( double& x, double& y, double& w, double& h ) const
3007 {
3008  x = m_clipboxworld.GetMinX();
3009  y = m_clipboxworld.GetMinY();
3010  w = m_clipboxworld.GetWidth();
3011  h = m_clipboxworld.GetHeight();
3012 }
3013 
3014 unsigned int a2dDrawer2D::ConvertSplinedPolygon2( unsigned int n )
3015 {
3016  a2dVertexList h;
3017  unsigned int i;
3018  for ( i = 0; i < n; i++ )
3019  {
3020  h.push_back( new a2dLineSegment( m_cpointsDouble[i].x, m_cpointsDouble[i].y ) );
3021  }
3022 
3023  double deviceaber = WorldToDeviceXRel( m_splineaberration );
3024  if ( deviceaber < 5 )
3025  deviceaber = THRESHOLD;
3026 
3027  //TODO need an array version for speed
3028  h.ConvertIntoSplinedPolygon( deviceaber );
3029 
3030  n = h.size();
3031 
3032  m_cpointsDouble.resize( n );
3033 
3034  a2dVertexList::iterator iter = h.begin();
3035  for ( i = 0; i < n; i++ )
3036  {
3037  m_cpointsDouble[i].x = ( *iter )->m_x;
3038  m_cpointsDouble[i].y = ( *iter )->m_y;
3039  iter++;
3040  }
3041  h.clear();
3042 
3043  return n;
3044 }
3045 
3046 unsigned int a2dDrawer2D::ConvertSplinedPolyline2( unsigned int n )
3047 {
3048  a2dVertexList h;
3049  unsigned int i;
3050  for ( i = 0; i < n; i++ )
3051  {
3052  h.push_back( new a2dLineSegment( m_cpointsDouble[i].x, m_cpointsDouble[i].y ) );
3053  }
3054 
3055  double deviceaber = WorldToDeviceXRel( m_splineaberration );
3056  if ( deviceaber < 5 )
3057  deviceaber = THRESHOLD;
3058 
3059  //TODO need an array version for speed
3060  h.ConvertIntoSplinedPolyline( deviceaber );
3061 
3062  n = h.size();
3063  m_cpointsDouble.resize( n );
3064 
3065  a2dVertexList::iterator iter = h.begin();
3066  for ( i = 0; i < n; i++ )
3067  {
3068  m_cpointsDouble[i].x = ( *iter )->m_x;
3069  m_cpointsDouble[i].y = ( *iter )->m_y;
3070  iter = h.erase( iter );
3071  }
3072  return n;
3073 }
3074 
3075 void a2dDrawer2D::DeviceDrawPolygon( unsigned int n, bool spline , wxPolygonFillMode fillStyle )
3076 {
3077  wxFAIL_MSG( wxT( "if used, must be implemented in derived class" ) );
3078 }
3079 
3080 void a2dDrawer2D::DeviceDrawLines( unsigned int n, bool spline )
3081 {
3082  wxFAIL_MSG( wxT( "if used, must be implemented in derived class" ) );
3083 }
3084 
3085 void a2dDrawer2D::DeviceDrawLine( double x1, double y1, double x2, double y2 )
3086 {
3087  wxFAIL_MSG( wxT( "if used, must be implemented in derived class" ) );
3088 }
3089 
3090 void a2dDrawer2D::DeviceDrawHorizontalLine( int x1, int y1, int x2, bool WXUNUSED( use_pen ) )
3091 {
3092  wxFAIL_MSG( wxT( "if used, must be implemented in derived class" ) );
3093 }
3094 
3095 void a2dDrawer2D::DeviceDrawVerticalLine( int x1, int y1, int y2, bool WXUNUSED( use_pen ) )
3096 {
3097  wxFAIL_MSG( wxT( "if used, must be implemented in derived class" ) );
3098 }
3099 
3100 void a2dDrawer2D::DeviceDrawPixel( int x1, int y1, unsigned char r, unsigned char g, unsigned char b, unsigned char a )
3101 {
3102  wxFAIL_MSG( wxT( "if used, must be implemented in derived class" ) );
3103 }
3104 
3105 IMPLEMENT_CLASS( a2dDrawer2D, wxObject )
3106 IMPLEMENT_DYNAMIC_CLASS( a2dBlindDrawer2D, a2dDrawer2D )
3107 
3108 /*******************************************************************
3109 a2dBlindDrawer2D
3110 ********************************************************************/
3111 
3112 a2dBlindDrawer2D::a2dBlindDrawer2D( const wxSize& size ): a2dDrawer2D( size )
3113 {}
3114 
3116 {}
3117 
3119 {}
3120 
3122  : a2dDrawer2D( other )
3123 {}
3124 
3126  : a2dDrawer2D( other )
3127 {}
3128 
3130 {
3131  wxASSERT_MSG( m_beginDraw_endDraw >= 0, wxT( "a2dBlindDrawer2D, unbalanced BeginDraw EndDraw" ) );
3133 }
3134 
3136 {
3138  wxASSERT_MSG( m_beginDraw_endDraw >= 0, wxT( "a2dBlindDrawer2D, unbalanced BeginDraw EndDraw" ) );
3139 }
3140 
3142 {
3143  m_width = w;
3144  m_height = h;
3145 }
3146 
3147 wxBitmap a2dBlindDrawer2D::GetSubBitmap( wxRect WXUNUSED( rect ) ) const
3148 {
3149  wxFAIL_MSG( wxT( "a2dBlindDrawer2D has no buffer" ) );
3150  return wxBitmap( m_width, m_height );
3151 }
3152 
3153 void a2dBlindDrawer2D::SetClippingRegion( a2dVertexList* WXUNUSED( points ), bool WXUNUSED( spline ), wxPolygonFillMode WXUNUSED( fillStyle ) )
3154 {}
3155 
3156 void a2dBlindDrawer2D::ExtendAndPushClippingRegion( a2dVertexList* WXUNUSED( points ), bool WXUNUSED( spline ), wxPolygonFillMode WXUNUSED( fillStyle ), a2dBooleanClip WXUNUSED( clipoperation ) )
3157 {}
3158 
3159 void a2dBlindDrawer2D::ExtendClippingRegion( a2dVertexList* WXUNUSED( points ), bool WXUNUSED( spline ), wxPolygonFillMode WXUNUSED( fillStyle ), a2dBooleanClip WXUNUSED( clipoperation ) )
3160 {}
3161 
3163 {}
3164 
3165 void a2dBlindDrawer2D::SetClippingRegionDev( wxCoord WXUNUSED( minx ), wxCoord WXUNUSED( miny ), wxCoord WXUNUSED( width ), wxCoord WXUNUSED( height ) )
3166 {}
3167 
3168 void a2dBlindDrawer2D::SetClippingRegion( double WXUNUSED( minx ), double WXUNUSED( miny ), double WXUNUSED( maxx ), double WXUNUSED( maxy ) )
3169 {}
3170 
3172 {}
3173 
3175 {
3177 }
3178 
3180 {}
3181 
3183 {}
3184 
3185 void a2dBlindDrawer2D::DoSetDrawStyle( a2dDrawStyle WXUNUSED( drawstyle ) )
3186 {}
3187 
3188 void a2dBlindDrawer2D::DrawImage( const wxImage& WXUNUSED( imagein ), double WXUNUSED( x ), double WXUNUSED( y ), double WXUNUSED( width ), double WXUNUSED( height ), wxUint8 WXUNUSED( Opacity ) )
3189 {}
3190 
3191 void a2dBlindDrawer2D::DrawImage( const a2dImageRGBA& image, double x, double y, double width, double height, wxUint8 Opacity )
3192 {}
3193 
3194 void a2dBlindDrawer2D::DrawVpath( const a2dVpath* WXUNUSED( path ) )
3195 {}
3196 
3197 void a2dBlindDrawer2D::DrawPoint( double xc, double yc )
3198 {}
3199 
3200 void a2dBlindDrawer2D::DrawPolygon( a2dVertexArray* points, bool spline, wxPolygonFillMode fillStyle )
3201 {
3202 }
3203 
3204 void a2dBlindDrawer2D::DrawPolygon( const a2dVertexList* list, bool spline, wxPolygonFillMode fillStyle )
3205 {
3206 }
3207 
3208 void a2dBlindDrawer2D::DrawLines( a2dVertexArray* points, bool spline )
3209 {
3210 }
3211 
3212 void a2dBlindDrawer2D::DrawLines( const a2dVertexList* list, bool spline )
3213 {
3214 }
3215 
3216 void a2dBlindDrawer2D::DrawArc( double x1, double y1, double x2, double y2, double xc, double yc, bool chord )
3217 {
3218 }
3219 
3220 void a2dBlindDrawer2D::DrawEllipticArc( double xc, double yc, double width, double height, double sa, double ea, bool chord )
3221 {
3222 }
3223 
3224 void a2dBlindDrawer2D::DrawCenterRoundedRectangle( double xc, double yc, double width, double height, double radius, bool pixelsize )
3225 {
3226 }
3227 
3228 void a2dBlindDrawer2D::DrawRoundedRectangle( double x, double y, double width, double height, double radius, bool pixelsize )
3229 {
3230 }
3231 
3232 void a2dBlindDrawer2D::DrawCircle( double xc, double yc, double radius )
3233 {
3234 }
3235 
3236 void a2dBlindDrawer2D::DrawEllipse( double xc, double yc, double width, double height )
3237 {
3238 }
3239 
3240 void a2dBlindDrawer2D::DrawLine( double x1, double y1, double x2, double y2 )
3241 {
3242 }
3243 
3244 void a2dBlindDrawer2D::DeviceDrawAnnotation( const wxString& WXUNUSED( text ), wxCoord WXUNUSED( x ), wxCoord WXUNUSED( y ), const wxFont& WXUNUSED( font ) )
3245 {}
3246 
3247 void a2dBlindDrawer2D::BlitBuffer( wxRect WXUNUSED( rect ), const wxPoint& WXUNUSED( bufferpos ) )
3248 {
3249  wxFAIL_MSG( wxT( "not useful here" ) );
3250 }
3251 
3252 void a2dBlindDrawer2D::BlitBuffer( wxDC* WXUNUSED( dc ), wxRect WXUNUSED( rect ), const wxPoint& WXUNUSED( bufferpos ) )
3253 {
3254  wxFAIL_MSG( wxT( "not useful here" ) );
3255 }
3256 
3257 
3258 
3259 
3260 #if wxART2D_USE_GRAPHICS_CONTEXT
3261 
3262 IMPLEMENT_CLASS( a2dGcBaseDrawer, a2dDrawer2D )
3263 
3264 /*******************************************************************
3265 a2dGcBaseDrawer
3266 ********************************************************************/
3267 
3268 a2dGcBaseDrawer::a2dGcBaseDrawer( int width, int height, wxGraphicsRenderer* render, wxGraphicsContext* context ): a2dDrawer2D( width, height )
3269 {
3270  m_render = render;
3271  m_context = context;
3272 }
3273 
3274 a2dGcBaseDrawer::a2dGcBaseDrawer( const a2dGcBaseDrawer& other )
3275  : a2dDrawer2D( other )
3276 {
3277  m_render = other.m_render;
3278  m_context = other.m_context;
3279 }
3280 
3281 a2dGcBaseDrawer::a2dGcBaseDrawer( const a2dDrawer2D& other )
3282  : a2dDrawer2D( other )
3283 {
3284  m_render = NULL;
3285  m_context = NULL;
3286 }
3287 
3288 a2dGcBaseDrawer::~a2dGcBaseDrawer()
3289 {
3290 }
3291 
3292 void a2dGcBaseDrawer::SetTransform( const a2dAffineMatrix& userToWorld )
3293 {
3294  a2dDrawer2D::SetTransform( userToWorld );
3295 
3296  wxGraphicsMatrix m = m_context->CreateMatrix(
3297  m_usertodevice( 0, 0 ), m_usertodevice( 0, 1 ),
3298  m_usertodevice( 1, 0 ), m_usertodevice( 1, 1 ),
3299  m_usertodevice( 2, 0 ), m_usertodevice( 2, 1 ) );
3300  m_context->SetTransform( m );
3301 }
3302 
3303 void a2dGcBaseDrawer::PushTransform()
3304 {
3306 
3307  wxGraphicsMatrix m = m_context->CreateMatrix();
3308  m.Set(
3309  m_usertodevice( 0, 0 ), m_usertodevice( 0, 1 ),
3310  m_usertodevice( 1, 0 ), m_usertodevice( 1, 1 ),
3311  m_usertodevice( 2, 0 ), m_usertodevice( 2, 1 ) );
3312  m_context->SetTransform( m );
3313 }
3314 
3315 void a2dGcBaseDrawer::PushTransform( const a2dAffineMatrix& affine )
3316 {
3317  a2dDrawer2D::PushTransform( affine );
3318 
3319  wxGraphicsMatrix m = m_context->CreateMatrix();
3320  m.Set(
3321  m_usertodevice( 0, 0 ), m_usertodevice( 0, 1 ),
3322  m_usertodevice( 1, 0 ), m_usertodevice( 1, 1 ),
3323  m_usertodevice( 2, 0 ), m_usertodevice( 2, 1 ) );
3324  m_context->SetTransform( m );
3325 }
3326 
3327 void a2dGcBaseDrawer::PushIdentityTransform()
3328 {
3330 
3331  wxGraphicsMatrix m = m_context->CreateMatrix();
3332  m.Set(
3333  m_usertodevice( 0, 0 ), m_usertodevice( 0, 1 ),
3334  m_usertodevice( 1, 0 ), m_usertodevice( 1, 1 ),
3335  m_usertodevice( 2, 0 ), m_usertodevice( 2, 1 ) );
3336  m_context->SetTransform( m );
3337 }
3338 
3339 void a2dGcBaseDrawer::PopTransform( void )
3340 {
3342 
3343  wxGraphicsMatrix m = m_context->CreateMatrix();
3344  m.Set(
3345  m_usertodevice( 0, 0 ), m_usertodevice( 0, 1 ),
3346  m_usertodevice( 1, 0 ), m_usertodevice( 1, 1 ),
3347  m_usertodevice( 2, 0 ), m_usertodevice( 2, 1 ) );
3348  m_context->SetTransform( m );
3349 }
3350 
3351 void a2dGcBaseDrawer::BeginDraw()
3352 {
3353  wxASSERT_MSG( m_beginDraw_endDraw >= 0, wxT( "a2dMemDcDrawer, unbalanced BeginDraw EndDraw" ) );
3354 
3355  if ( m_beginDraw_endDraw == 0 )
3356  {
3357  SetDrawerFill( m_currentfill );
3358  SetDrawerStroke( m_currentstroke );
3359  DestroyClippingRegion();
3360  SetDrawStyle( m_drawstyle );
3361 
3362  }
3363 
3364  m_beginDraw_endDraw++;
3365 }
3366 
3367 void a2dGcBaseDrawer::EndDraw()
3368 {
3369  m_beginDraw_endDraw--;
3370 
3371  wxASSERT_MSG( m_beginDraw_endDraw >= 0, wxT( "a2dMemDcDrawer, unbalanced BeginDraw EndDraw" ) );
3372 
3373  if ( m_beginDraw_endDraw == 0 )
3374  {
3375  }
3376 }
3377 
3378 void a2dGcBaseDrawer::BlitBuffer( wxRect rect, const wxPoint& bufferpos )
3379 {
3380  BeginDraw();
3381  if ( m_display )
3382  {
3383  wxClientDC deviceDC( m_display );
3384  m_display->PrepareDC( deviceDC );
3385  BlitBuffer( &deviceDC, rect, bufferpos );
3386  }
3387  EndDraw();
3388 }
3389 
3390 void a2dGcBaseDrawer::SetClippingRegion( a2dVertexList* points, bool spline, wxPolygonFillMode fillStyle )
3391 {
3392  unsigned int n = points->size();
3393 
3394  m_cpointsDouble.resize( n );
3395 
3396  unsigned int i = 0;
3397  double x, y;
3398  forEachIn( a2dVertexList, points )
3399  {
3400  a2dPoint2D point = ( *iter )->GetPoint();
3401  //transform to device
3402  GetUserToDeviceTransform().TransformPoint( point.m_x, point.m_y, x, y );
3403  m_cpointsDouble[i].x = x;
3404  m_cpointsDouble[i].y = y;
3405  i++;
3406  }
3407 
3408  if ( spline )
3409  n = ConvertSplinedPolygon2( n );
3410 
3411  wxPoint* intpoints = _convertToIntPointCache( n, &m_cpointsDouble[0] );
3412  m_clip = wxRegion( n, intpoints, fillStyle );
3413 
3414  m_clipboxdev = m_clip.GetBox();
3415  m_clipboxworld = ToWorld( m_clipboxdev );
3416 }
3417 
3418 void a2dGcBaseDrawer::ExtendAndPushClippingRegion( a2dVertexList* points, bool spline, wxPolygonFillMode fillStyle, a2dBooleanClip clipoperation )
3419 {
3420  wxRegion* push = new wxRegion( m_clip );
3421 
3422  m_clipregionlist.Insert( push );
3423 
3424  ExtendClippingRegion( points, spline, fillStyle, clipoperation );
3425 }
3426 
3427 void a2dGcBaseDrawer::ExtendClippingRegion( a2dVertexList* points, bool spline, wxPolygonFillMode WXUNUSED( fillStyle ), a2dBooleanClip clipoperation )
3428 {
3429  wxRegion totaladd;
3430  bool first = false;
3431 
3432  a2dBoundingBox devbox;
3433  bool smallPoly = false;
3434  unsigned int segments = ToDeviceLines( points, devbox, smallPoly );
3435 
3436  if ( segments == 0 )
3437  return;
3438 
3439  if ( spline )
3440  segments = ConvertSplinedPolygon2( segments );
3441 
3442  wxPoint* int_cpts = _convertToIntPointCache( segments, &m_cpointsDouble[0] );
3443  wxRegion add = wxRegion( segments, int_cpts, wxWINDING_RULE );
3444  if ( !first )
3445  {
3446  totaladd = add;
3447  first = true;
3448  }
3449  else
3450  totaladd.Union( add );
3451 
3452  if ( !m_clip.Empty() )
3453  {
3454  bool result;
3455  switch ( clipoperation )
3456  {
3457  case a2dCLIP_AND:
3458  result = m_clip.Intersect( totaladd );
3459  break ;
3460 
3461  case a2dCLIP_OR:
3462  result = m_clip.Union( totaladd );
3463  break ;
3464 
3465  case a2dCLIP_XOR:
3466  result = m_clip.Xor( totaladd );
3467  break ;
3468 
3469  case a2dCLIP_DIFF:
3470  result = m_clip.Subtract( totaladd );
3471  break ;
3472 
3473  case a2dCLIP_COPY:
3474  default:
3475  m_clip = totaladd;
3476  result = true;
3477  break ;
3478  }
3479  if ( result )
3480  {
3481  m_context->ResetClip();
3482  }
3483  }
3484  else
3485  {
3486  m_clip = totaladd;
3487  m_context->ResetClip();
3488  }
3489 
3490  m_clipboxdev = m_clip.GetBox();
3491  m_clipboxworld = ToWorld( m_clipboxdev );
3492  m_context->Clip( m_clipboxworld.GetMinX(), m_clipboxworld.GetMinY(),
3493  m_clipboxworld.GetWidth(), m_clipboxworld.GetHeight() );
3494 }
3495 
3496 void a2dGcBaseDrawer::PopClippingRegion()
3497 {
3498  if ( !m_clipregionlist.GetCount() )
3499  return;
3500 
3501  m_clip = *m_clipregionlist.GetFirst()->GetData();
3502  delete m_clipregionlist.GetFirst()->GetData();
3503  m_clipregionlist.DeleteNode( m_clipregionlist.GetFirst() );
3504 
3505  m_clipboxdev = m_clip.GetBox();
3506  m_clipboxworld = ToWorld( m_clipboxdev );
3507  m_context->Clip( m_clipboxworld.GetMinX(), m_clipboxworld.GetMinY(),
3508  m_clipboxworld.GetWidth(), m_clipboxworld.GetHeight() );
3509 }
3510 
3511 void a2dGcBaseDrawer::SetClippingRegionDev( wxCoord minx, wxCoord miny, wxCoord width, wxCoord height )
3512 {
3513  m_clip = wxRegion( minx, miny, width, height );
3514  m_clipboxdev = wxRect( minx, miny, width, height );
3515  m_clipboxworld = ToWorld( m_clipboxdev );
3516 
3517  //we don't know which part of the transform set in m_context is to go from world to device.
3518  //remove all first.
3519  PushIdentityTransform();
3520  m_context->ResetClip();
3521  m_context->Clip( m_clipboxdev.x, m_clipboxdev.y,
3522  m_clipboxdev.GetWidth(), m_clipboxdev.GetHeight() );
3523 
3524  PopTransform();
3525 }
3526 
3527 void a2dGcBaseDrawer::SetClippingRegion( double minx, double miny, double maxx, double maxy )
3528 {
3529  int iminx = WorldToDeviceX( minx );
3530  int iminy = WorldToDeviceY( miny );
3531  int imaxx = WorldToDeviceX( maxx );
3532  int imaxy = WorldToDeviceY( maxy );
3533  if ( m_yaxis )
3534  {
3535  m_clip = wxRegion( iminx, imaxy, imaxx - iminx, iminy - imaxy );
3536  m_clipboxdev = wxRect( iminx, imaxy, imaxx - iminx, iminy - imaxy );
3537  }
3538  else
3539  {
3540  m_clip = wxRegion( iminx, iminy, imaxx - iminx, imaxy - iminy );
3541  m_clipboxdev = wxRect( iminx, iminy, imaxx - iminx, imaxy - iminy );
3542  }
3543 
3544  m_context->ResetClip();
3545  //we don't know which part of the transform set in m_context is to go from world to device.
3546  //remove all first.
3547  PushIdentityTransform();
3548  m_context->Clip( m_clipboxdev.x, m_clipboxdev.y,
3549  m_clipboxdev.GetWidth(), m_clipboxdev.GetHeight() );
3550 
3551  PopTransform();
3552 }
3553 
3554 void a2dGcBaseDrawer::DestroyClippingRegion()
3555 {
3556  m_clip.Clear();
3557  m_clipboxdev = wxRect( 0, 0, m_width, m_height );
3558  m_clipboxworld = ToWorld( m_clipboxdev );
3559 
3560  m_context->ResetClip();
3561 }
3562 
3563 void a2dGcBaseDrawer::ResetStyle()
3564 {
3566  SetDrawerFill( *a2dBLACK_FILL ); //set to a sure state
3567  SetDrawerStroke( *a2dBLACK_STROKE );
3568  SetDrawStyle( m_drawstyle );
3569 }
3570 
3571 void a2dGcBaseDrawer::DoSetActiveFont( const a2dFont& font )
3572 {
3573  // Get font size in device units
3574  unsigned int fontsize;
3575  fontsize = m_currentfont.GetSize();
3576  if ( fontsize < 1 )
3577  fontsize = 1;
3578  switch ( m_currentfont.GetType() )
3579  {
3580  case a2dFONT_WXDC:
3581  {
3582  m_currentfont.GetFont().SetPointSize( fontsize );
3583  wxGraphicsFont f = m_render->CreateFont( m_currentfont.GetFont() );
3584  m_context->SetFont( f );
3585  break;
3586  }
3587  default:
3588  wxFont wxfont = *wxNORMAL_FONT;
3589  wxfont.SetPointSize( fontsize );
3590  wxGraphicsFont f = m_render->CreateFont( wxfont );
3591  m_context->SetFont( f );
3592  }
3593 }
3594 
3595 void a2dGcBaseDrawer::DoSetActiveStroke()
3596 {
3597  wxGraphicsPen graphpen = ConvertActiveToGraphicsPen( m_context );
3598  m_context->SetPen( graphpen );
3599  //wxPen dcpen = ConvertActiveToPen();
3600  //m_context->SetPen( dcpen );
3601 }
3602 
3603 void a2dGcBaseDrawer::DoSetActiveFill()
3604 {
3605  wxGraphicsBrush graphbrush = ConvertActiveToGraphicsBrush( m_context );
3606  m_context->SetBrush( graphbrush );
3607  //wxBrush dcbrush = ConvertActiveToBrush();
3608  //m_context->SetBrush( dcbrush );
3609 }
3610 
3611 void a2dGcBaseDrawer::DoSetDrawStyle( a2dDrawStyle drawstyle )
3612 {
3613  if ( m_drawstyle == a2dFIX_STYLE && m_drawstyle == a2dFIX_STYLE_INVERT )
3614  return;
3615 
3616  m_drawstyle = drawstyle;
3617 
3618  switch( drawstyle )
3619  {
3620  case a2dWIREFRAME_INVERT:
3621  SetActiveStroke( *a2dBLACK_STROKE );
3622  SetActiveFill( *a2dTRANSPARENT_FILL );
3623 #if wxCHECK_VERSION(2,9,0)
3624 #else
3625  m_context->SetLogicalFunction( wxINVERT );
3626 #endif
3627  break;
3628 
3629  case a2dWIREFRAME:
3630  SetActiveStroke( *a2dBLACK_STROKE );
3631  SetActiveFill( *a2dTRANSPARENT_FILL );
3632 #if wxCHECK_VERSION(2,9,0)
3633 #if wxCHECK_VERSION(2,9,0)
3634 #else
3635  m_context->SetLogicalFunction( wxCOPY );
3636 #endif
3637 #else
3638 #endif
3639  break;
3640 
3642  SetActiveStroke( *a2dBLACK_STROKE );
3643  SetActiveFill( *a2dTRANSPARENT_FILL );
3644 #if wxCHECK_VERSION(2,9,0)
3645 #else
3646  m_context->SetLogicalFunction( wxCOPY );
3647 #endif
3648  break;
3649 
3651  SetActiveStroke( *a2dBLACK_STROKE );
3652  SetActiveFill( *a2dTRANSPARENT_FILL );
3653 #if wxCHECK_VERSION(2,9,0)
3654 #else
3655  m_context->SetLogicalFunction( wxINVERT );
3656 #endif
3657  break;
3658 
3659  case a2dFILLED:
3660  SetActiveStroke( m_currentstroke );
3661  SetActiveFill( m_currentfill );
3662 #if wxCHECK_VERSION(2,9,0)
3663 #else
3664  m_context->SetLogicalFunction( wxCOPY );
3665 #endif
3666  break;
3667 
3668  case a2dFIX_STYLE:
3669  //preserve this
3670  m_fixStrokeRestore = m_currentstroke;
3671  m_fixFillRestore = m_currentfill;
3672  m_fixDrawstyle = m_drawstyle;
3673  SetActiveStroke( m_currentstroke );
3674  SetActiveFill( m_currentfill );
3675 
3676  // don't adjust style
3677 #if wxCHECK_VERSION(2,9,0)
3678 #else
3679  m_context->SetLogicalFunction( wxCOPY );
3680 #endif
3681  break;
3682 
3683  case a2dFIX_STYLE_INVERT:
3684  // don't adjust style
3685 #if wxCHECK_VERSION(2,9,0)
3686 #else
3687  m_context->SetLogicalFunction( wxINVERT );
3688 #endif
3689  break;
3690 
3691  default:
3692  wxASSERT( 0 );
3693  }
3694 
3695  //a2dContext* context = (a2dContext*) m_context;
3696  //context->SetDrawStyle( m_drawstyle );
3697 }
3698 
3699 
3700 void a2dGcBaseDrawer::DrawImage( const wxImage& imagein, double x, double y, double width, double height, wxUint8 Opacity )
3701 {
3702  if ( m_disableDrawing )
3703  return;
3704 
3705  a2dAffineMatrix affine;
3706  if ( GetYaxis() )
3707  {
3708  affine.Translate( 0.0, -( y ) );
3709  affine.Mirror( true, false );
3710  affine.Translate( 0.0, y );
3711  }
3712  PushTransform( affine );
3713 
3714  wxGraphicsBitmap bitmap = m_render->CreateBitmap( imagein );
3715 #if wxCHECK_VERSION(2,9,0)
3716  m_context->DrawBitmap( bitmap, x - width / 2.0, y - height / 2.0, width, height );
3717 #else
3718  m_context->DrawGraphicsBitmap( bitmap, x - width / 2.0, y - height / 2.0, width, height );
3719 #endif
3720 
3721  PopTransform();
3722 }
3723 
3724 void a2dGcBaseDrawer::DrawImage( const a2dImageRGBA& image, double x, double y, double width, double height, wxUint8 Opacity )
3725 {
3726  if ( m_disableDrawing )
3727  return;
3728 
3729  wxImage wximage = image.GetImage();
3730  wxGraphicsBitmap bitmap = m_render->CreateBitmap( wximage );
3731 #if wxCHECK_VERSION(2,9,0)
3732  m_context->DrawBitmap( bitmap, x - width / 2.0, y - height / 2.0, width, height );
3733 #else
3734  m_context->DrawGraphicsBitmap( bitmap, x - width / 2.0, y - height / 2.0, width, height );
3735 #endif
3736 }
3737 
3738 void a2dGcBaseDrawer::DrawLines( const a2dVertexList* list, bool spline )
3739 {
3740  if ( m_disableDrawing )
3741  return;
3742 
3743  wxGraphicsPath path = m_context->CreatePath();
3744 
3745  a2dVertexList::const_iterator iter = list->begin();
3746  int i = 0;
3747  while ( iter != list->end() )
3748  {
3749  a2dLineSegment* seg = ( *iter );
3750  if ( i == 0 )
3751  path.MoveToPoint( seg->m_x, seg->m_y );
3752  else
3753  path.AddLineToPoint( seg->m_x, seg->m_y );
3754  i++;
3755  iter++;
3756  }
3757 
3758  m_context->StrokePath( path );
3759 }
3760 
3761 void a2dGcBaseDrawer::DrawLines( a2dVertexArray* points, bool spline )
3762 {
3763  if ( m_disableDrawing )
3764  return;
3765 
3766  wxGraphicsPath path = m_context->CreatePath();
3767 
3768  int i;
3769  for ( i = 0; i < points->size(); i++ )
3770  {
3771  const a2dLineSegmentPtr seg = points->Item( i );
3772  if ( i == 0 )
3773  path.MoveToPoint( seg->m_x, seg->m_y );
3774  else
3775  path.AddLineToPoint( seg->m_x, seg->m_y );
3776  }
3777 
3778  m_context->StrokePath( path );
3779 }
3780 
3781 void a2dGcBaseDrawer::DrawPolygon( a2dVertexArray* points, bool spline, wxPolygonFillMode fillStyle )
3782 {
3783  if ( m_disableDrawing )
3784  return;
3785 
3786  wxGraphicsPath path = m_context->CreatePath();
3787 
3788  int i;
3789  for ( i = 0; i < points->size(); i++ )
3790  {
3791  const a2dLineSegmentPtr seg = points->Item( i );
3792  if ( i == 0 )
3793  path.MoveToPoint( seg->m_x, seg->m_y );
3794  else
3795  path.AddLineToPoint( seg->m_x, seg->m_y );
3796  }
3797  path.CloseSubpath();
3798 
3799  m_context->DrawPath( path , fillStyle );
3800 }
3801 
3802 void a2dGcBaseDrawer::DrawPolygon( const a2dVertexList* list, bool spline, wxPolygonFillMode fillStyle )
3803 {
3804  if ( m_disableDrawing )
3805  return;
3806 
3807  wxGraphicsPath path = m_context->CreatePath();
3808 
3809  a2dVertexList::const_iterator iter = list->begin();
3810  int i = 0;
3811  while ( iter != list->end() )
3812  {
3813  a2dLineSegment* seg = ( *iter );
3814  if ( i == 0 )
3815  path.MoveToPoint( seg->m_x, seg->m_y );
3816  else
3817  path.AddLineToPoint( seg->m_x, seg->m_y );
3818  iter++;
3819  i++;
3820  }
3821  path.CloseSubpath();
3822 
3823  m_context->DrawPath( path , fillStyle );
3824 }
3825 
3826 void a2dGcBaseDrawer::DrawCircle( double xc, double yc, double radius )
3827 {
3828  if ( m_disableDrawing )
3829  return;
3830 
3831  m_context->DrawEllipse( xc - radius, yc - radius, 2.0 * radius, 2.0 * radius );
3832 }
3833 
3834 void a2dGcBaseDrawer::DrawEllipse( double xc, double yc, double width, double height )
3835 {
3836  if ( m_disableDrawing )
3837  return;
3838 
3839  m_context->DrawEllipse( xc - width / 2.0, yc - height / 2.0, width, height );
3840 }
3841 
3842 void a2dGcBaseDrawer::DrawLine( double x1, double y1, double x2, double y2 )
3843 {
3844  if ( m_disableDrawing )
3845  return;
3846 
3847  m_context->StrokeLine( x1, y1, x2, y2 );
3848 }
3849 
3850 
3851 void a2dGcBaseDrawer::DrawRoundedRectangle( double x, double y, double width, double height, double radius, bool pixelsize )
3852 {
3853  if ( m_disableDrawing )
3854  return;
3855 
3856  if ( height < 0 )
3857  {
3858  y += height;
3859  height = -height;
3860  }
3861  if ( width < 0 )
3862  {
3863  x += width;
3864  width = -width;
3865  }
3866  m_context->DrawRoundedRectangle( x, y, width, height, radius );
3867 }
3868 
3869 void a2dGcBaseDrawer::DrawPoint( double xc, double yc )
3870 {
3871  if ( m_disableDrawing )
3872  return;
3873 
3874  double xt, yt;
3875  GetUserToDeviceTransform().TransformPoint( xc, yc, xt, yt );
3876  //DeviceDrawPixel( xt, yt, m_colour1redStroke, m_colour1greenStroke, m_colour1blueStroke, m_StrokeOpacityCol1 );
3877 }
3878 
3879 void a2dGcBaseDrawer::DrawText( const wxString& text, double x, double y, int alignment, bool Background )
3880 {
3881  if ( m_disableDrawing )
3882  return;
3883 
3884  // Get the bounding box, including alignment displacement.
3885  a2dBoundingBox bbox = m_currentfont.GetTextExtent( text, alignment );
3886  bbox.Translate( x, y );
3887 
3888  // Get unaligned coordinates for DrawTextXXX functions. By default these functions
3889  // use the lowerleft corner of the boundingbox, hence GetMinX() and GetMinY().
3890  x = bbox.GetMinX();
3891  y = bbox.GetMinY();
3892 
3893  // Get font size in device units, also takes stretching into account
3894  double dx, dy, size;
3895  dx = m_usertodevice.GetValue( 1, 0 );
3896  dy = m_usertodevice.GetValue( 1, 1 );
3897  size = m_currentfont.GetSize() * sqrt( dx * dx + dy * dy );
3898 
3899  // Transform user bbox to world bbox.
3900  a2dBoundingBox worldbbox( bbox );
3901  worldbbox.MapBbox( m_usertoworld );
3902  // If bbox not outside clipping area, draw the text
3903  if ( m_clipboxworld.Intersect( worldbbox ) != _OUT )
3904  {
3905  // Draw background fill
3906  if ( Background && !GetDrawerFill().IsNoFill() && !GetDrawerFill().GetStyle() == a2dFILL_TRANSPARENT )
3907  {
3908  a2dStroke oldstroke = m_activestroke;
3909  SetDrawerStroke( *a2dTRANSPARENT_STROKE );
3910  DrawRoundedRectangle( bbox.GetMinX(), bbox.GetMinY(),
3911  bbox.GetWidth(), bbox.GetHeight(), 0 );
3912  SetDrawerStroke( oldstroke );
3913  }
3914 
3915  const double h = m_currentfont.GetLineHeight();
3916  a2dAffineMatrix affine;
3917  if ( GetYaxis() )
3918  {
3919  affine.Translate( 0.0, -( y + h ) );
3920  affine.Mirror( true, false );
3921  affine.Translate( 0.0, y );
3922  }
3923  PushTransform( affine );
3924 
3925  //a2dFill oldfill = m_activefill;
3926  //SetDrawerFill( a2dFill( m_activestroke.GetColour() ) );
3927 
3928  // If text > threshold, draw text
3929  if ( size > m_drawingthreshold )
3930  m_context->DrawText( text, x, y );
3931  // If text < threshold, draw a simple version.
3932  else
3933  DrawTextUnknown( text, x, y, true );
3934  //SetDrawerFill( oldfill );
3935  PopTransform();
3936  }
3937 
3938 }
3939 
3940 
3941 IMPLEMENT_DYNAMIC_CLASS( a2dNativeGcDrawer, a2dGcBaseDrawer )
3942 
3943 /*******************************************************************
3944 a2dNativeGcDrawer
3945 ********************************************************************/
3946 
3947 void a2dNativeGcDrawer::InitContext()
3948 {
3949  m_clip.Clear();
3950  m_buffer = wxBitmap( m_width, m_height );
3951  m_memdc.SelectObject( m_buffer );
3952  if ( !m_render )
3953  m_render = wxGraphicsRenderer::GetDefaultRenderer();
3954  if ( !m_context )
3955  m_context = m_render->CreateContext( m_memdc );
3956 }
3957 
3958 a2dNativeGcDrawer::a2dNativeGcDrawer( const wxSize& size ): a2dGcBaseDrawer( size.GetWidth(), size.GetHeight() )
3959 {
3960  InitContext();
3961 }
3962 
3963 a2dNativeGcDrawer::a2dNativeGcDrawer( int width, int height, wxGraphicsRenderer* render, wxGraphicsContext* context )
3964  : a2dGcBaseDrawer( width, height )
3965 {
3966  m_render = render;
3967  m_context = context;
3968  InitContext();
3969 }
3970 
3971 a2dNativeGcDrawer::a2dNativeGcDrawer( const a2dNativeGcDrawer& other )
3972  : a2dGcBaseDrawer( other )
3973 {
3974  m_render = NULL;
3975  m_context = NULL;
3976  InitContext();
3977 }
3978 
3979 a2dNativeGcDrawer::a2dNativeGcDrawer( const a2dDrawer2D& other )
3980  : a2dGcBaseDrawer( other )
3981 {
3982  InitContext();
3983 }
3984 
3985 a2dNativeGcDrawer::~a2dNativeGcDrawer()
3986 {
3987  m_memdc.SelectObject( wxNullBitmap );
3988 }
3989 
3990 wxBitmap a2dNativeGcDrawer::GetBuffer() const
3991 {
3992  return m_buffer;
3993 }
3994 
3995 void a2dNativeGcDrawer::SetBufferSize( int w, int h )
3996 {
3997  m_width = w;
3998  m_height = h;
3999  wxBitmap helpbuf = wxBitmap( w, h );
4000 
4001  //make sure to preserve what was in the old buffer bitmap,
4002  //to prevent the need for total redraws
4003  wxMemoryDC mdch;
4004  mdch.SelectObject( helpbuf );
4005  mdch.Blit( 0, 0, w, h, &m_memdc, 0, 0 );
4006  mdch.SelectObject( wxNullBitmap );
4007 
4008  m_memdc.SelectObject( wxNullBitmap );
4009  m_buffer = helpbuf;
4010  m_memdc.SelectObject( m_buffer );
4011  delete m_context;
4012  m_context = m_render->CreateContext( m_memdc );
4013 }
4014 
4015 wxBitmap a2dNativeGcDrawer::GetSubBitmap( wxRect rect ) const
4016 {
4017  wxBitmap ret( rect.width, rect.height, m_buffer.GetDepth() );
4018  wxASSERT_MSG( ret.Ok(), wxT( "GetSubImage error" ) );
4019 
4020  //do NOT use getsubbitmap, renderDc is already set for the buffer therefor will not work properly
4021  wxMemoryDC dcb;
4022  dcb.SelectObject( ret );
4023  dcb.Blit( 0, 0, rect.width, rect.height, const_cast< wxMemoryDC* >( &m_memdc ), rect.x, rect.y, wxCOPY, false );
4024  dcb.SelectObject( wxNullBitmap );
4025 
4026  return ret;
4027 }
4028 
4029 void a2dNativeGcDrawer::CopyIntoBuffer( const wxBitmap& bitm )
4030 {
4031  m_memdc.SelectObject( wxNullBitmap );
4032  m_buffer = bitm;
4033  m_memdc.SelectObject( m_buffer );
4034 }
4035 
4036 void a2dNativeGcDrawer::BlitBuffer( wxDC* dc, wxRect rect, const wxPoint& bufferpos )
4037 {
4038  // clip to buffer
4039  if ( rect.x < 0 )
4040  {
4041  rect.width += rect.x;
4042  rect.x = 0;
4043  }
4044  if ( rect.width <= 0 ) return;
4045 
4046  if ( rect.y < 0 )
4047  {
4048  rect.height += rect.y;
4049  rect.y = 0;
4050  }
4051  if ( rect.height <= 0 ) return;
4052 
4053  if ( rect.x + rect.width > m_width )
4054  {
4055  rect.width = m_width - rect.x;
4056  }
4057  if ( rect.width <= 0 ) return;
4058 
4059  if ( rect.y + rect.height > m_height )
4060  {
4061  rect.height = m_height - rect.y;
4062  }
4063  if ( rect.height <= 0 ) return;
4064 
4065  dc->Blit( rect.x - bufferpos.x, rect.y - bufferpos.y, rect.width, rect.height, &m_memdc, rect.x, rect.y, wxCOPY, false );
4066 }
4067 
4068 void a2dNativeGcDrawer::ShiftBuffer( int dxy, bool yshift )
4069 {
4070  int bw = GetBuffer().GetWidth();
4071  int bh = GetBuffer().GetHeight();
4072  if ( yshift )
4073  {
4074  if ( dxy > 0 && dxy < bh )
4075  {
4076  wxRect rect( 0, 0, bw, bh - dxy );
4077  wxBitmap sub_bitmap( m_buffer.GetSubBitmap( rect ) );
4078  wxMemoryDC dcm;
4079  dcm.SelectObject( m_buffer );
4080  dcm.DrawBitmap( sub_bitmap, 0, dxy, true );
4081  dcm.SelectObject( wxNullBitmap );
4082  }
4083  else if ( dxy < 0 && dxy > -bh )
4084  {
4085  wxRect rect( 0, -dxy, bw, bh + dxy );
4086  wxBitmap sub_bitmap( m_buffer.GetSubBitmap( rect ) );
4087  wxMemoryDC dcm;
4088  dcm.SelectObject( m_buffer );
4089  dcm.DrawBitmap( sub_bitmap, 0, 0, true );
4090  dcm.SelectObject( wxNullBitmap );
4091  }
4092  else
4093  wxFAIL_MSG( wxT( "you can only shift within height of buffer" ) );
4094 
4095  }
4096  else
4097  {
4098  if ( dxy > 0 && dxy < bw )
4099  {
4100  wxRect rect( 0, 0, bw - dxy, bh );
4101  wxBitmap sub_bitmap( m_buffer.GetSubBitmap( rect ) );
4102  wxMemoryDC dcm;
4103  dcm.SelectObject( m_buffer );
4104  dcm.DrawBitmap( sub_bitmap, dxy, 0, true );
4105  dcm.SelectObject( wxNullBitmap );
4106  }
4107  else if ( dxy < 0 && dxy > -bw )
4108  {
4109  wxRect rect( -dxy, 0, bw + dxy, bh );
4110  wxBitmap sub_bitmap( m_buffer.GetSubBitmap( rect ) );
4111  wxMemoryDC dcm;
4112  dcm.SelectObject( m_buffer );
4113  dcm.DrawBitmap( sub_bitmap, 0, 0, true );
4114  dcm.SelectObject( wxNullBitmap );
4115  }
4116  else
4117  wxFAIL_MSG( wxT( "you can only shift within width of buffer" ) );
4118  }
4119 }
4120 
4121 void a2dNativeGcDrawer::DrawPoint( double xc, double yc )
4122 {
4123  if ( m_disableDrawing )
4124  return;
4125 
4126  double xt, yt;
4127  GetUserToDeviceTransform().TransformPoint( xc, yc, xt, yt );
4128  //DeviceDrawPixel( xt, yt, m_colour1redStroke, m_colour1greenStroke, m_colour1blueStroke, m_StrokeOpacityCol1 );
4129 }
4130 
4131 #endif // wxART2D_USE_GRAPHICS_CONTEXT
4132 
4133 
4134 
4135 
void SetMappingUpp(double vx1, double vy1, double xpp, double ypp)
Give the virtual size to be displayed, the mapping matrix will be calculated.
Definition: drawer2d.cpp:250
virtual void SetYaxis(bool up)
set if the Yaxis goes up or down
Definition: drawer2d.cpp:438
a2dBoundingBox GetVisibleBbox() const
get visible area as a boundingbox in world coordinates
Definition: drawer2d.cpp:433
int WorldToDeviceXRel(double x) const
convert x relative from world to device coordinates
Definition: drawer2d.h:460
a2dAffineMatrix m_usertodevice
pointer to current user-to-device transform matrix ( so includes mapping matrix ) ...
Definition: drawer2d.h:1139
a2dStroke m_activestroke
used while rendering
Definition: drawer2d.h:1006
wxPoint2DDouble a2dPoint2D
this to define if coordinate numbers are integer or doubles
Definition: artglob.h:47
virtual double GetVisibleMaxX() const
get Maximum X of the visible part in world coordinates
Definition: drawer2d.cpp:413
a2dBoundingBox & GetClippingBox()
what is the current clipping region in world coordinates
Definition: drawer2d.h:753
a2dDrawStyle m_drawstyle
drawstyle (like invert mode)
Definition: drawer2d.h:1015
a2dAffineMatrix & Mirror(bool y=true, bool x=false)
mirror a matrix in x, y
Definition: afmatrix.cpp:396
double GetHeight() const
returns height of the boundingbox
Definition: bbox.cpp:334
double m_xpp
user units per pixel in x
Definition: drawer2d.h:1036
wxUint8 m_StrokeOpacityCol2
active stroke alpha
Definition: drawer2d.h:1103
bool m_asrectangle
underneath the threshold draw rectangles if true else nothing
Definition: drawer2d.h:1193
double GetSize() const
Get the font size.
Definition: stylebase.cpp:2917
double GetStrokeWidth() const
Get stroke width.
Definition: stylebase.cpp:2931
wxUint8 m_StrokeOpacityCol1
active stroke alpha
Definition: drawer2d.h:1101
Base class for all types of strokes, understood by a2dDrawer2D classes.
Definition: stylebase.h:378
void EndRefreshDisplayDisable()
see StartRefreshDisplayDisable()
Definition: drawer2d.cpp:204
virtual void SetTransform(const a2dAffineMatrix &userToWorld)
set user-to-world transform matrix.
Definition: drawer2d.cpp:446
virtual void DeviceDrawPixel(int x1, int y1, unsigned char r, unsigned char g, unsigned char b, unsigned char a=255)
draw a single, unstroked pixel in device coordinates with the given color
Definition: drawer2d.cpp:3100
a2dStroke m_fixStrokeRestore
used to restore an overruled fix style
Definition: drawer2d.h:1018
bool IsNoStroke() const
Definition: stylebase.h:510
void DrawVpath(const a2dVpath *path)
Draw vector path in world coordinates.
Definition: drawer2d.cpp:3194
a2dVertexList m_tempPoints
used internally in some methods to avoid constructor, new, ...
Definition: drawer2d.h:1053
a2dFill m_activefill
used while rendering
Definition: drawer2d.h:1009
Quadratic Bezier curve.
Definition: polyver.h:984
virtual void DrawArc(double x1, double y1, double x2, double y2, double xc, double yc, bool chord)
Draw Arc in world coordinates.
Definition: drawer2d.cpp:1957
unsigned int ConvertSplinedPolyline2(unsigned int n)
converts internal device points array to spline. Returns new number of points.
Definition: drawer2d.cpp:3046
void SetDrawStyle(a2dDrawStyle drawstyle)
set drawstyle to use for drawing,
Definition: drawer2d.cpp:557
int WorldToDeviceY(double y) const
convert y from world to device coordinates
Definition: drawer2d.h:455
void DestroyClippingRegion()
set clipping region off
Definition: drawer2d.cpp:3171
double m_x2
control point
Definition: polyver.h:1025
static wxUint16 GetPrimitiveThreshold()
get drawing threshold
Definition: artglob.h:143
const a2dStroke * a2dBLACK_STROKE
global a2dStroke stock object for BLACK stroking
Stroke and fill base classes.
void SetBufferSize(int w, int h)
set buffer size to w pixel wide and h pixels heigh
Definition: drawer2d.cpp:3141
virtual void PopTransform(void)
Recall the previously saved user-to-world transform off the matrix stack.
Definition: drawer2d.cpp:480
bool m_realScale
If true use real scale else different scale by x and y.
Definition: drawer2d.h:1221
std::vector< a2dAffineMatrix > m_affineStack
Affine transform stack.
Definition: drawer2d.h:1218
void DrawRoundedRectangle(double x, double y, double width, double height, double radius, bool pixelsize=false)
Draw RoundedRectangle in world coordinates.
Definition: drawer2d.cpp:3228
a2dPoint2D GetStop() const
Get stop for gradient fill colour change.
Definition: stylebase.cpp:4733
double GetVisibleMinX() const
get Minimal X of the visible part in world coordinates
Definition: drawer2d.cpp:403
unsigned char m_colour2blueFill
active fill colours
Definition: drawer2d.h:1128
wxColour GetColour2() const
return colour 2
Definition: stylebase.cpp:4969
const int SPLINE_STEP
number of steps when converting a spline to lines.
Definition: artglob.h:334
a2dStroke m_currentstroke
used while rendering
Definition: drawer2d.h:1000
a2dDrawStyle m_fixDrawstyle
used to restore an overruled fix style
Definition: drawer2d.h:1024
OVERLAP Intersect(const a2dBoundingBox &, double Marge=0) const
Definition: bbox.cpp:205
Cubic Bezier curve.
Definition: polyver.h:1045
wxPen ConvertActiveToPen()
get active stroke as wxPen
Definition: drawer2d.cpp:731
const a2dFill * a2dBLACK_FILL
global a2dFill stock object for BLACK filling
int m_refreshDisplay
see SetRefreshDisplay()
Definition: drawer2d.h:1145
void DrawEllipticArc(double xc, double yc, double width, double height, double sa, double ea, bool chord)
Draw Elliptic Arc in world coordinates.
Definition: drawer2d.cpp:3220
void PopClippingRegion()
pop a previously pushed clipping region
Definition: drawer2d.cpp:3162
virtual void DrawVpath(const a2dVpath *path)
Draw vector path in world coordinates.
Definition: drawer2d.cpp:1568
a2dBlindDrawer2D(int w=100, int h=100)
Drawer having a buffer of w pixel wide and h pixels heigh.
Definition: drawer2d.cpp:3115
double wxDegToRad(double deg)
conversion from degrees to radians
Definition: artglob.cpp:30
virtual void DestroyClippingRegion()=0
set clipping region off
void SetMappingDeviceRect(int mapx, int mapy, int mapWidth, int mapHeight, bool remap=false)
to change the default mapping (to the complete buffer).
Definition: drawer2d.cpp:216
std::vector< wxRealPoint > m_cpointsDouble
cached array for containing transformed device coordinates (double)
Definition: drawer2d.h:1175
double m_y2
control point
Definition: polyver.h:1027
double DeviceToWorldYRel(double y) const
convert y relative from device to world coordinates
Definition: drawer2d.h:449
double m_y3
control point 2
Definition: polyver.h:1100
Arc Segment.
Definition: polyver.h:1112
wxUint16 m_polygonFillThreshold
polygon smaller than this value will be rendered non filled.
Definition: drawer2d.h:1190
double GetDescent() const
Get descent.
Definition: stylebase.cpp:3101
void SetDrawerStroke(const a2dStroke &stroke)
Used to set the current stroke.
Definition: drawer2d.cpp:565
Defines a font to be set to a2dDrawer2D or stored in a2dCanvsObject etc.
Definition: stylebase.h:779
double m_x3
control point 2
Definition: polyver.h:1098
double GetRadius() const
Get stop for gradient fill colour change.
Definition: stylebase.cpp:4765
virtual void DrawPolygon(a2dVertexArray *points, bool spline=false, wxPolygonFillMode fillStyle=wxODDEVEN_RULE)
Draw polygon in world coordinates using pointarray.
Definition: drawer2d.cpp:1889
bool GetPixelStroke() const
if the width is pixels or not.
Definition: stylebase.cpp:6335
double GetValue(int col, int row) const
get the value in the matrix at col,row
Definition: afmatrix.cpp:106
unsigned char m_colour1redFill
active fill colours
Definition: drawer2d.h:1117
bool IsNoFill() const
Definition: stylebase.h:273
bool GetYaxis() const
get y axis orientation
Definition: drawer2d.h:280
void SetClippingRegion(a2dVertexList *points, bool spline=false, wxPolygonFillMode fillStyle=wxODDEVEN_RULE)
set clipping region from polygon to which everything drawn will be clipped.
Definition: drawer2d.cpp:3153
a2dGlobal * a2dGlobals
global a2dCanvasGlobal to have easy access to global settings
Definition: artglob.cpp:34
a2dFont m_currentfont
current font set
Definition: drawer2d.h:1012
a2dBoundingBox m_clipboxworld
current clipping area in world coordinates
Definition: drawer2d.h:1196
double GetVisibleMinY() const
get Minimal X of the visible part in world coordinates
Definition: drawer2d.cpp:408
a2dDrawer2D(int width=0, int height=0)
constructor
Definition: drawer2d.cpp:77
wxUint16 GetPolygonFillThreshold()
get threshold at which polygon is drawn filled or only outline
Definition: artglob.h:140
a2dAffineMatrix m_usertoworld
pointer to current user-to-world transform matrix
Definition: drawer2d.h:1136
virtual ~a2dBlindDrawer2D()
destructor
Definition: drawer2d.cpp:3118
void SetFont(const a2dFont &font)
set font to use for drawing text
Definition: drawer2d.cpp:722
wxRect ToDevice(const a2dBoundingBox &bbox)
convert the bounding box in world coordinates to device coordinates and return that rectangle...
Definition: drawer2d.cpp:499
Arc Segment in a2dVertexList.
Definition: polyver.h:371
void ReStoreFixedStyle()
when fixed drawing style is set, it can be overruled.
Definition: drawer2d.cpp:711
vertex array of line and arc segments.
Definition: polyver.h:494
int m_mapHeight
height for mapping in device coordinates
Definition: drawer2d.h:1163
bool m_fixedStyledOverRuled
keep track of this
Definition: drawer2d.h:1042
wxColour GetColour() const
return colour 1
Definition: stylebase.cpp:6131
unsigned char m_colour1blueStroke
active stroke colours
Definition: drawer2d.h:1114
a2dAffineMatrix a2dIDENTITY_MATRIX
global a2dAffineMatrix to set/pass the identity matrix.
Definition: afmatrix.cpp:51
double m_y2
control point 1
Definition: polyver.h:1095
bool Clipping(double &x1, double &y1, double &x2, double &y2)
clip lines
Definition: drawer2d.cpp:2878
virtual void EndDraw()
end drawing on this context (used to reset a specific drawer)
Definition: drawer2d.cpp:3135
unsigned char m_colour2redFill
active fill colours
Definition: drawer2d.h:1124
double m_virt_minY
virtual coordinates box its miminum Y
Definition: drawer2d.h:1033
std::vector< wxPoint > m_cpointsInt
cached array for containing transformed device coordinates (integer)
Definition: drawer2d.h:1172
vertex list of line and arc segments.
Definition: polyver.h:600
unsigned char m_colour1blueFill
active fill colours
Definition: drawer2d.h:1121
void TransformPoint(double x, double y, double &tx, double &ty) const
Transform a point.
Definition: afmatrix.cpp:559
virtual void DeviceDrawVerticalLine(int x1, int y1, int y2, bool use_stroke_color)
Draw a pixel-width, unstroked vertical line in device (pixel) coordinates.
Definition: drawer2d.cpp:3095
void DoSetActiveStroke()
per drawer implementation
Definition: drawer2d.cpp:3179
virtual void DrawCenterRoundedRectangle(double xc, double yc, double width, double height, double radius, bool pixelsize=false)
Draw CenterRoundedRectangle in world coordinates.
Definition: drawer2d.cpp:2040
a2dStrokeGlyph GetGlyphStroke(wxChar c) const
Get the glyph of a single character.
Definition: stylebase.cpp:2944
double TransformDistance(double distance) const
Transform a distance.
Definition: afmatrix.cpp:616
virtual void ExtendAndPushClippingRegion(a2dVertexList *points, bool spline=false, wxPolygonFillMode fillStyle=wxODDEVEN_RULE, a2dBooleanClip clipoperation=a2dCLIP_AND)
push on stack the current clipping region and extend clipping region
Definition: drawer2d.cpp:3156
virtual void DrawCharStroke(wxChar c)
Draw a stroke character.
Definition: drawer2d.cpp:2270
void DrawTextGeneric(const wxString &text, double x, double y, void(a2dDrawer2D::*drawchar)(wxChar))
Definition: drawer2d.cpp:2291
#define NORMFONT
Normalization font size used for bigger size drawing of text.
Definition: stylebase.h:68
a2dBoundingBox GetTextExtent(const wxString &string, int alignment=wxMINX|wxMINY, double *w=NULL, double *h=NULL, double *descent=NULL, double *externalLeading=NULL) const
Get the dimensions in world coordinates of the string.
Definition: stylebase.cpp:3044
virtual void SetActiveFill(const a2dFill &fill)
sync with actual API graphical context
Definition: drawer2d.cpp:633
virtual double GetVisibleHeight() const
get Height of visible part in world coordinates
Definition: drawer2d.cpp:428
a2dDrawStyle
Define the manner in which a2dCanvasView draws to the device.
Definition: artglob.h:280
void DrawLines(a2dVertexArray *points, bool spline=false)
Draw polyline in world coordinates using pointarray.
Definition: drawer2d.cpp:3208
void SetDrawerFill(const a2dFill &fill)
Used to set the current fill.
Definition: drawer2d.cpp:621
bool Ok() const
Check font validity.
Definition: stylebase.cpp:2894
void DrawLine(double x1, double y1, double x2, double y2)
Draw line in world coordinates.
Definition: drawer2d.cpp:3240
virtual void PushTransform()
Save the current user-to-world transform on the affine stack.
Definition: drawer2d.cpp:452
double GetWidth(wxChar c)
Get width of a single character.
Definition: stylebase.cpp:3106
double DeviceToWorldY(double y) const
convert y from device to world coordinates
Definition: drawer2d.h:439
bool CalcR(const a2dLineSegment &prev, double &radius, double &center_x, double &center_y, double &beginrad, double &midrad, double &endrad, double &phit) const
Calculation of center for the Arc.
Definition: polyver.cpp:411
void Expand(const a2dPoint2D &, const a2dPoint2D &)
expand boundingbox width two points
Definition: bbox.cpp:155
const a2dBoundingBox & Translate(a2dPoint2D &)
translate with given vector
Definition: bbox.cpp:370
double GetMinX() const
get minimum X of the boundingbox
Definition: bbox.cpp:304
virtual void DrawRoundedRectangle(double x, double y, double width, double height, double radius, bool pixelsize=false)
Draw RoundedRectangle in world coordinates.
Definition: drawer2d.cpp:2048
void DrawArc(double x1, double y1, double x2, double y2, double xc, double yc, bool chord)
Draw Arc in world coordinates.
Definition: drawer2d.cpp:3216
a2dAffineMatrix m_worldtodevice
world to device coordinate mapping
Definition: drawer2d.h:1133
double GetLineHeight() const
Get the line height.
Definition: stylebase.cpp:3096
void Init()
Initialize a drawer.
Definition: drawer2d.cpp:122
double m_displayaberration
accuracy of arc segment calculation etc. in device coordinates
Definition: drawer2d.h:1184
virtual void ResetStyle()
set a pre-defined style reseting cashed values.
Definition: drawer2d.cpp:545
#define forEachIn(listtype, list)
easy iteration for a2dlist
Definition: a2dlist.h:111
class draws nothing, still can be used as a drawing context.
Definition: drawer2d.h:1245
virtual void DrawPoint(double xc, double yc)=0
draw a single point
unsigned char m_colour1greenStroke
active stroke colours
Definition: drawer2d.h:1112
const a2dFont * a2dNullFONT
global a2dFont stock object for NO font
void SetUppX(double x)
set world units per pixel in X
Definition: drawer2d.cpp:238
void DetectCriticalPoints(int n, wxRealPoint points[])
Used for filling with Gradient fill style.
Definition: drawer2d.cpp:2456
wxUint16 m_drawingthreshold
object smaller than this value will not be rendered
Definition: drawer2d.h:1187
double m_ypp
user units per pixel in y
Definition: drawer2d.h:1039
void GetClippingMinMax(double &xmin, double &ymin, double &xmax, double &ymax) const
what is the current clipping region in world coordinates
Definition: drawer2d.cpp:2998
virtual void DrawPolyPolygon(a2dListOfa2dVertexList polylist, wxPolygonFillMode fillStyle=wxODDEVEN_RULE)
draw a list of polygons ( contour clockwise becomes hole )
Definition: drawer2d.cpp:1881
a2dPoint2D GetStart() const
Get start for gradient fill colour change.
Definition: stylebase.cpp:4727
virtual double GetVisibleWidth() const
get Width of visible part in world coordinates
Definition: drawer2d.cpp:423
a2dPoint2D GetCenter() const
Get start for gradient fill colour change.
Definition: stylebase.cpp:4753
Drawing context abstraction.
Definition: drawer2d.h:177
Normal straight line segment in a2dVertexList and a2dVertexArray.
Definition: polyver.h:163
bool CalcR(a2dVpathSegmentPtr prev, double &radius, double &center_x, double &center_y, double &beginrad, double &midrad, double &endrad, double &phit)
Calculation of center for the Arc.
Definition: polyver.cpp:3820
void CalculateLineParameters()
Calculate the parameters if invalid.
Definition: liner.cpp:355
void SetUppY(double y)
set world units per pixel in Y
Definition: drawer2d.cpp:244
virtual void DrawTextFreetype(const wxString &text, double x, double y)
Draw text in world coordinates, based on a freetype font .
Definition: drawer2d.h:972
virtual void DoSetActiveStroke()=0
per drawer implementation
unsigned char m_colour2greenFill
active fill colours
Definition: drawer2d.h:1126
void DrawImage(const wxImage &image, double x, double y, double width, double height, wxUint8 Opacity=255)
Draw wxImage in world coordinates.
Definition: drawer2d.cpp:3188
int WorldToDeviceX(double x) const
convert x from world to device coordinates
Definition: drawer2d.h:453
int m_mapX
X mapping position in device coordinates.
Definition: drawer2d.h:1154
virtual void DrawLine(double x1, double y1, double x2, double y2)
Draw line in world coordinates.
Definition: drawer2d.cpp:2167
virtual void DrawTextUnknown(const wxString &text, double x, double y, bool words=false)
Draw a cross, indicating an unsupported font type for this drawer.
Definition: drawer2d.cpp:2198
a2dAETList m_AETlist
scanline list of intersections with polygon
Definition: drawer2d.h:1169
virtual void DoSetActiveFill()=0
per drawer implementation
a2dPoint2D GetFocal() const
Get start for gradient fill colour change.
Definition: stylebase.cpp:4759
virtual void DeviceDrawLine(double x1, double y1, double x2, double y2)
draw in pixels
Definition: drawer2d.cpp:3085
wxBrush ConvertActiveToBrush()
get active fill as wxBrush
Definition: drawer2d.cpp:847
int GetClipCode(double x, double y)
clip code of a point
Definition: drawer2d.cpp:2851
void DrawPoint(double xc, double yc)
draw a single point
Definition: drawer2d.cpp:3197
void ResetFixedStyle()
only way to reset style after SetDrawStyle( a2dFIXED*** );
Definition: drawer2d.cpp:684
bool Identity(void)
Make into identity matrix.
Definition: afmatrix.cpp:256
bool m_yaxis
up or down
Definition: drawer2d.h:1027
virtual void DrawTextDc(const wxString &text, double x, double y)
Draw text in user coordinates, based on a dc font .
Definition: drawer2d.h:987
double m_x2
control point 1
Definition: polyver.h:1093
virtual void DrawText(const wxString &text, double x, double y, int alignment=wxMINX|wxMINY, bool Background=true)
Draw text in user coordinates.
Definition: drawer2d.cpp:2329
A 2x3 affine matrix class for 2D transformations.
Definition: afmatrix.h:53
void DrawCenterRoundedRectangle(double xc, double yc, double width, double height, double radius, bool pixelsize=false)
Draw CenterRoundedRectangle in world coordinates.
Definition: drawer2d.cpp:3224
a2dStroke GetDrawerStroke() const
get the current stroke
Definition: drawer2d.h:548
virtual void SetActiveStroke(const a2dStroke &stroke)
sync with actual API graphical context
Definition: drawer2d.cpp:581
a2dBoundingBox ToWorld(const wxRect &rect)
convert the rect in device coordinates to a bounding box in world coordinates and return that boundin...
Definition: drawer2d.cpp:491
double GetMaxX() const
get maximum X of the boundingbox
Definition: bbox.cpp:316
void DrawCharStrokeCb(wxChar c)
Wrapper for DrawCharStroke.
Definition: drawer2d.h:796
void SetMappingMatrix(const a2dAffineMatrix &mapping)
Definition: drawer2d.cpp:396
int m_height
device size height
Definition: drawer2d.h:1151
bool m_disableDrawing
all drawing is disabled when this is true
Definition: drawer2d.h:1208
bool GetFilling() const
if true, filling is on else filling is transparent.
Definition: stylebase.cpp:5069
void ConvertIntoSplinedPolygon(double Aber)
Definition: polyver.cpp:2869
static const a2dSignal sig_changedZoom
Definition: drawer2d.h:1232
Contains graphical drawing context specific classes. a2dDrawer2D and derived classes are used for dra...
wxPoint * _convertToIntPointCache(int n, wxRealPoint *pts)
Convert double points to integer coords in the point cache and return pointer.
Definition: drawer2d.cpp:529
double m_x
x endpoint of line
Definition: polyver.h:232
virtual void DrawEllipticArc(double xc, double yc, double width, double height, double sa, double ea, bool chord)
Draw Elliptic Arc in world coordinates.
Definition: drawer2d.cpp:1998
virtual ~a2dDrawer2D()
destructor
Definition: drawer2d.cpp:177
void DrawCircle(double x, double y, double radius)
Draw Circle in world coordinates.
Definition: drawer2d.cpp:3232
void MapBbox(const a2dAffineMatrix &matrix)
Definition: bbox.cpp:445
Definition: bbox.h:28
a2dBooleanClip
Used for defining how a ClippingRegion defined as a polygon is combined with.
Definition: drawer2d.h:54
wxRect m_clipboxdev
current clipping area in device coordinates
Definition: drawer2d.h:1199
double m_y
y endpoint of line
Definition: polyver.h:235
void FillPolygon(int n, wxRealPoint points[])
Used for filling with Gradient fill style.
Definition: drawer2d.cpp:2614
a2dCriticalPointList m_CRlist
critical point list for polygon
Definition: drawer2d.h:1166
void Aberration(double aber, double angle, double radius, double &dphi, unsigned int &segments)
calculate number of segments in an arc such that a certain accuracy is maintained ...
Definition: artglob.cpp:67
Line calculations.
Definition: liner.h:36
bool m_printingMode
can be used to modify drawing features when used as context for printing
Definition: drawer2d.h:1224
virtual void DrawTextStroke(const wxString &text, double x, double y)
Draw text in user coordinates, based on a stroke font.
Definition: drawer2d.cpp:2245
void SetMinX(double x)
Set Minimal X of the visible part in world coordinates.
Definition: drawer2d.cpp:226
void SetClippingRegionDev(wxCoord minx, wxCoord miny, wxCoord width, wxCoord height)
set clipping region using x y values in device coordinates
Definition: drawer2d.cpp:3165
bool m_virtualarea_set
is the virtual area set already (used during startup)
Definition: drawer2d.h:1142
int m_beginDraw_endDraw
counter for BeginDraw EndDraw calls
Definition: drawer2d.h:1202
double m_virt_minX
virtual coordinates box its miminum X
Definition: drawer2d.h:1030
virtual void ExtendClippingRegion(a2dVertexList *points, bool spline=false, wxPolygonFillMode fillStyle=wxODDEVEN_RULE, a2dBooleanClip clipoperation=a2dCLIP_AND)
extend clipping region with a polygon to which everything drawn will be clipped.
Definition: drawer2d.cpp:3159
int m_width
device size width
Definition: drawer2d.h:1148
void DoSetActiveFill()
per drawer implementation
Definition: drawer2d.cpp:3182
virtual void DrawCharUnknown(wxChar c)
Draw a cross instead of a character.
Definition: drawer2d.cpp:2178
double DeviceToWorldX(double x) const
convert x from device to world coordinates
Definition: drawer2d.h:437
double m_y1
y endpoint of line
Definition: polyver.h:922
unsigned char m_colour1greenFill
active fill colours
Definition: drawer2d.h:1119
double GetMaxY() const
get maximum Y of the boundingbox
Definition: bbox.cpp:322
double GetWidth() const
returns width of the boundingbox
Definition: bbox.cpp:328
bool m_pendingSig_changedZoom
When display refresh is on hold, this triggers a delayed zoom signal, when released.
Definition: drawer2d.h:1050
virtual void DeviceDrawPolygon(unsigned int n, bool spline, wxPolygonFillMode fillStyle)
draw an internal polygon in device coordinates
Definition: drawer2d.cpp:3075
bool MoveUp(int n, wxRealPoint points[], double horline, int &index, int direction)
Used for filling with Gradient fill style.
Definition: drawer2d.cpp:2437
unsigned char m_colour1redStroke
active stroke colours
Definition: drawer2d.h:1110
void BlitBuffer()
blit whole buffer to device
Definition: drawer2d.cpp:183
wxColour GetColour() const
return colour
Definition: stylebase.cpp:5012
bool Scale(double scale)
Scale by scale (isotropic scaling i.e. the same in x and y):
Definition: afmatrix.cpp:270
bool Translate(double x, double y)
Translate by dx, dy:
Definition: afmatrix.cpp:420
double GetKerning(wxChar c1, wxChar c2) const
Get kerning space between two characters.
Definition: stylebase.cpp:2924
static bool GetThresholdDrawRectangle()
underneath the threshold draw rectangles instead of the real object.
Definition: artglob.h:146
void DeviceDrawAnnotation(const wxString &text, wxCoord x, wxCoord y, const wxFont &font)
text drawn in device coordinates
Definition: drawer2d.cpp:3244
int m_mapWidth
width for mapping in device coordinates
Definition: drawer2d.h:1160
const a2dStroke * a2dTRANSPARENT_STROKE
global a2dStroke stock object for TRANSPARENT stroking
wxWindow * m_display
view its window.
Definition: drawer2d.h:1205
command processor and intializing and event handling classes specific for wxDocview.
a2dFill GetDrawerFill() const
get the current fill
Definition: drawer2d.h:557
see a2dComEvent
Definition: gen.h:371
wxUint8 m_FillOpacityCol1
active fill alpha
Definition: drawer2d.h:1105
bool m_forceNormalizedFont
up or down
Definition: drawer2d.h:1045
void SetMinY(double y)
Set Minimal Y of the visible part in world coordinates.
Definition: drawer2d.cpp:232
int ToDeviceLines(a2dVertexArray *points, a2dBoundingBox &devbbox, bool &smallPoly, bool replaceByRectangle=false)
convert vertex array containing line and arc segments in user coordinates to device coordinate lines...
Definition: drawer2d.cpp:1310
The a2dBoundingBox class stores one a2dBoundingBox of a a2dCanvasObject.
Definition: bbox.h:39
virtual void BeginDraw()
start to draw on this context (used to initialize a specific drawer)
Definition: drawer2d.cpp:3129
const a2dAffineMatrix & GetTransform() const
get the user-to-world transform matrix.
Definition: drawer2d.h:500
void SetValue(int col, int row, double value)
set the value in the matrix at col,row
Definition: afmatrix.cpp:114
double GetMinY() const
get minimum Y of the boundingbox
Definition: bbox.cpp:310
float GetWidth() const
Definition: stylebase.cpp:6281
virtual double GetVisibleMaxY() const
get Maximum Y of the visible part in world coordinates
Definition: drawer2d.cpp:418
double m_x1
x endpoint of line
Definition: polyver.h:919
virtual void DrawEllipse(double x, double y, double width, double height)
Draw Ellipse in world coordinates.
Definition: drawer2d.cpp:2121
void DrawEllipse(double x, double y, double width, double height)
Draw Ellipse in world coordinates.
Definition: drawer2d.cpp:3236
wxRect & GetClippingBoxDev()
what is the current clipping region in device coordinates
Definition: drawer2d.h:759
#define Round(x)
round to integer such that e.g 2.5 &lt; x &lt; 3.5 becomes 3
Definition: artglob.h:60
virtual void DrawCircle(double x, double y, double radius)
Draw Circle in world coordinates.
Definition: drawer2d.cpp:2116
Vector Path.
Definition: polyver.h:1211
void SetSplineAberration(double aber)
Set the detail level for spline drawing.
Definition: drawer2d.cpp:195
virtual void DrawLines(a2dVertexArray *points, bool spline=false)
Draw polyline in world coordinates using pointarray.
Definition: drawer2d.cpp:1931
int m_mapY
Y mapping position in device coordinates.
Definition: drawer2d.h:1157
void ResetStyle()
set a pre-defined style reseting cashed values.
Definition: drawer2d.cpp:3174
virtual void DeviceDrawHorizontalLine(int x1, int y1, int x2, bool use_stroke_color)
Draw a pixel-width, unstroked horizontal line in device (pixel) coordinates.
Definition: drawer2d.cpp:3090
a2dFill m_currentfill
used while rendering
Definition: drawer2d.h:1003
bool m_frozen
buffer updating activity possible or not
Definition: drawer2d.h:994
void SetOpacityFactor(wxUint8 OpacityFactor)
when enabling m_useOpacityFactor, this is how transparent
Definition: drawer2d.cpp:550
void DrawPolygon(a2dVertexArray *points, bool spline=false, wxPolygonFillMode fillStyle=wxODDEVEN_RULE)
Draw polygon in world coordinates using pointarray.
Definition: drawer2d.cpp:3200
wxUint8 m_OpacityFactor
opacity will be the one set, derived by this
Definition: drawer2d.h:1211
double DeviceToWorldXRel(double x) const
convert x relative from device to world coordinates
Definition: drawer2d.h:444
virtual void SetMappingWidthHeight(double vx1, double vy1, double width, double height)
Give the virtual size to be displayed, the mapping matrix will be calculated.
Definition: drawer2d.cpp:333
const a2dAffineMatrix & GetUserToDeviceTransform() const
get matrix which transforms directly from user coordinates to device
Definition: drawer2d.h:503
wxUint8 m_FillOpacityCol2
active fill alpha
Definition: drawer2d.h:1107
double m_splineaberration
accuracy of spline
Definition: drawer2d.h:1178
virtual void DeviceDrawLines(unsigned int n, bool spline)
draw an internal polyline in device coordinates
Definition: drawer2d.cpp:3080
wxBitmap GetSubBitmap(wxRect sub_rect) const
get part of the buffer given a rect
Definition: drawer2d.cpp:3147
const double wxPI
defines PI
Definition: artglob.cpp:28
virtual void PushIdentityTransform()
push no transform, to draw directly in device coordinates
Definition: drawer2d.cpp:469
unsigned int ConvertSplinedPolygon2(unsigned int n)
converts internal device points array to spline. Returns new number of points.
Definition: drawer2d.cpp:3014
const a2dFill * a2dTRANSPARENT_FILL
global a2dFill stock object for TRANSPARENT filling
a2dFill m_fixFillRestore
used to restore an overruled fix style
Definition: drawer2d.h:1021
Used internal for scanned ( gradient etc. ) polygon filling.
Definition: artglob.h:306
void OverRuleFixedStyle()
id style is FIXED, saves current style and sets style to a2dFILLED
Definition: drawer2d.cpp:697
drawer2d.cpp Source File -- Sun Oct 12 2014 17:04:16 -- Sun Oct 12 2014 -- 1.8.5 -- wxArt2D -- . -- Main Page Reference Documentation