wxArt2D
aggdrawer.cpp
Go to the documentation of this file.
1 /*! \file aggdrawer/src/aggdrawer.cpp
2  \brief a2dAggDrawerRgba - Drawer using the antigrain library
3  \author Klaas Holwerda
4 
5  Copyright: 2001-2004 (C) Klaas Holwerda
6 
7  Licence: wxWidgets licence
8 
9  RCS-ID: $Id: aggdrawer.cpp,v 1.107 2009/10/01 19:22:34 titato Exp $
10 */
11 
12 #include "a2dprec.h"
13 
14 #ifdef __BORLANDC__
15 #pragma hdrstop
16 #endif
17 
18 #ifndef WX_PRECOMP
19 #include "wx/wx.h"
20 #endif
21 
22 #include "wx/wfstream.h"
23 #include "wx/intl.h"
24 #include "wx/log.h"
25 #include "wx/strconv.h"
26 #include <wx/tokenzr.h>
27 
28 #include <stdio.h>
29 #include <string.h>
30 #include <math.h>
31 
32 
33 #if wxART2D_USE_AGGDRAWER
34 
35 //AGG_RGB24
36 //#include "pixel_formats.h"
37 
38 /*
39 //! the pixel format used for MSW a2dAggDrawer
40 #define pix_format agg::pix_format_rgb24
41 //! the pixel format used for MSW a2dAggDrawer
42 typedef agg::pixfmt_rgb24 pixfmt;
43 //! the pixel format used for MSW a2dAggDrawer
44 typedef agg::pixfmt_rgb24_pre pixfmt_pre;
45 
46 //! the pixel format used for MSW a2dAggDrawer
47 #define pixfmt_gamma agg::pixfmt_rgb24_gamma
48 //! the pixel format used for MSW a2dAggDrawer
49 typedef agg::order_rgb component_order;
50 */
51 
52 #include "agg_basics.h"
53 
54 #include "wx/artbase/stylebase.h"
55 #include "wx/aggdrawer/aggdrawer.h"
56 
57 #else
58 #error This source file should not be compiled !
59 #endif
60 
61 
62 a2dAggDrawerBase::a2dAggDrawerBase( int width, int height )
63  :
64  m_rasterizer(),
65  m_path(),
66  m_fillGradient(),
67  m_lineGradient(),
68  m_fillGradientMatrix(),
69  m_lineGradientMatrix(),
70  m_fillGradientD1( 0.0 ),
71  m_lineGradientD1( 0.0 ),
72  m_fillGradientD2( 100.0 ),
73  m_lineGradientD2( 100.0 ),
74  m_fillGradientInterpolator( m_fillGradientMatrix ),
75  m_lineGradientInterpolator( m_lineGradientMatrix ),
76  m_linearGradientFunction(),
77  m_radialGradientFunction(),
78  a2dDrawer2D( width, height )
79 {
80  m_ownsBuffer = true;
81  m_preStroke = true;
82 }
83 
84 a2dAggDrawerBase::a2dAggDrawerBase( const wxSize& size )
85  :
86  m_rasterizer(),
87  m_path(),
88  m_fillGradient(),
89  m_lineGradient(),
90  m_fillGradientMatrix(),
91  m_lineGradientMatrix(),
92  m_fillGradientD1( 0.0 ),
93  m_lineGradientD1( 0.0 ),
94  m_fillGradientD2( 100.0 ),
95  m_lineGradientD2( 100.0 ),
96  m_fillGradientInterpolator( m_fillGradientMatrix ),
97  m_lineGradientInterpolator( m_lineGradientMatrix ),
98  m_linearGradientFunction(),
99  m_radialGradientFunction(),
100  a2dDrawer2D( size )
101 {
102  m_ownsBuffer = true;
103  m_preStroke = true;
104 }
105 
106 a2dAggDrawerBase::a2dAggDrawerBase( const wxBitmap& bitmap )
107  :
108  m_rasterizer(),
109  m_path(),
110  m_fillGradient(),
111  m_lineGradient(),
112  m_fillGradientMatrix(),
113  m_lineGradientMatrix(),
114  m_fillGradientD1( 0.0 ),
115  m_lineGradientD1( 0.0 ),
116  m_fillGradientD2( 100.0 ),
117  m_lineGradientD2( 100.0 ),
118  m_fillGradientInterpolator( m_fillGradientMatrix ),
119  m_lineGradientInterpolator( m_lineGradientMatrix ),
120  m_linearGradientFunction(),
121  m_radialGradientFunction(),
122  a2dDrawer2D( bitmap.GetWidth(), bitmap.GetHeight() )
123 {
124  m_ownsBuffer = true;
125  m_preStroke = true;
126 }
127 
128 a2dAggDrawerBase::a2dAggDrawerBase( const a2dAggDrawerBase& other )
129  :
130  m_rasterizer(),
131  m_path(),
132  m_fillGradient(),
133  m_lineGradient(),
134  m_fillGradientMatrix(),
135  m_lineGradientMatrix(),
136  m_fillGradientD1( 0.0 ),
137  m_lineGradientD1( 0.0 ),
138  m_fillGradientD2( 100.0 ),
139  m_lineGradientD2( 100.0 ),
140  m_fillGradientInterpolator( m_fillGradientMatrix ),
141  m_lineGradientInterpolator( m_lineGradientMatrix ),
142  m_linearGradientFunction(),
143  m_radialGradientFunction(),
144  a2dDrawer2D( other )
145 {
146  m_ownsBuffer = false;
147  m_preStroke = other.m_preStroke;
148 }
149 
151 {
152  SetDrawerFill( *a2dBLACK_FILL ); //set to a sure state
155 }
156 
157 agg::trans_affine a2dAggDrawerBase::_get_agg_user_to_device_transform() const
158 {
160  return agg::trans_affine(
161  rmtx( 0, 0 ), rmtx( 0, 1 ),
162  rmtx( 1, 0 ), rmtx( 1, 1 ),
163  rmtx( 2, 0 ), rmtx( 2, 1 ) );
164 }
165 
166 void a2dAggDrawerBase::BlitBuffer( wxRect rect, const wxPoint& bufferpos )
167 {
168  BeginDraw();
169  BlitBuffer( m_deviceDC, rect, bufferpos );
170  EndDraw();
171 }
172 
174 {
175  wxASSERT_MSG( m_beginDraw_endDraw >= 0, wxT( "a2dDcDrawer, unbalanced BeginDraw EndDraw" ) );
176 
177  if ( m_display && m_beginDraw_endDraw == 0 )
178  {
179  m_deviceDC = new wxClientDC( m_display );
180  m_display->PrepareDC( *m_deviceDC );
185  m_OpacityFactor = 255;
186  }
188 }
189 
190 
192 {
194 
195  wxASSERT_MSG( m_beginDraw_endDraw >= 0, wxT( "a2dDcDrawer, unbalanced BeginDraw EndDraw" ) );
196 
197  if ( m_display && m_beginDraw_endDraw == 0 )
198  {
199  delete m_deviceDC;
200  m_deviceDC = NULL;
201  }
202 
203 }
204 
205 void a2dAggDrawerBase::DoSetDrawStyle( a2dDrawStyle drawstyle )
206 {
207  m_drawstyle = drawstyle;
208 
209  switch( drawstyle )
210  {
211  case a2dWIREFRAME_INVERT:
212  //SetActiveStroke( *a2dBLACK_STROKE );
213  //SetActiveFill( *a2dTRANSPARENT_FILL );
214  m_blendMode = agg::comp_op_invert;
215  break;
216 
217  case a2dWIREFRAME:
220  m_blendMode = agg::end_of_comp_op_e;
221  break;
222 
226  m_blendMode = agg::end_of_comp_op_e;
227  break;
228 
232  m_blendMode = agg::comp_op_invert;
233  break;
234 
235  case a2dFILLED:
238  m_blendMode = agg::end_of_comp_op_e;
239  break;
240 
241  case a2dFIX_STYLE:
242  //preserve this
248 
249  m_blendMode = agg::end_of_comp_op_e;
250  break;
251 
252  case a2dFIX_STYLE_INVERT:
253  // don't adjust style
254  m_blendMode = agg::comp_op_invert;
255  break;
256 
257  default:
258  wxASSERT( 0 );
259  }
260 }
261 
263 {
265  {
266  m_strokewidth = 0;
267  m_strokewidthDev = 1;
268  }
269  else if ( m_activestroke.GetType() == a2dSTROKE_ONE_COLOUR )
270  {
271  switch( m_activestroke.GetStyle() )
272  {
273  case a2dSTROKE_SOLID:
275  case a2dSTROKE_DOT:
276  case a2dSTROKE_DOT_DASH:
277  case a2dSTROKE_LONG_DASH:
279  m_style = m_activestroke.GetStyle();
280  break;
281  /*
282  // These aren't supported yet
283  case a2dSTROKE_USER_DASH:
284  break;
285  case a2dSTROKE_BDIAGONAL_HATCH:
286  break;
287  case a2dSTROKE_CROSSDIAG_HATCH
288  break;
289  case a2dSTROKE_FDIAGONAL_HATCH:
290  break;
291  case a2dSTROKE_CROSS_HATCH:
292  break;
293  case a2dSTROKE_HORIZONTAL_HATCH:
294  break;
295  case a2dSTROKE_VERTICAL_HATCH:
296  break;
297  case a2dSTROKE_STIPPLE:
298  break;
299  case a2dSTROKE_STIPPLE_MASK_OPAQUE:
300  break;
301  */
302  default: m_style=a2dSTROKE_SOLID;
303  }
304 
305  m_strokewidth = m_activestroke.GetWidth();
307  {
309  invert.Invert();
310  m_strokewidthDev = 1;
311  m_strokewidth = invert.TransformDistance( m_strokewidthDev );
312  m_join = agg::round_join;
313  m_cap = agg::round_cap;
314  }
315  else
316  {
317  switch ( m_activestroke.GetJoin() )
318  {
319  case wxJOIN_MITER: m_join = agg::miter_join;
320  break;
321  case wxJOIN_ROUND: m_join = agg::round_join;
322  break;
323  case wxJOIN_BEVEL: m_join = agg::bevel_join;
324  break;
325  default: m_join = agg::round_join;
326  }
327  switch ( m_activestroke.GetCap() )
328  {
329  case wxCAP_BUTT: m_cap = agg::butt_cap;
330  break;
331  case wxCAP_ROUND: m_cap = agg::round_cap;
332  break;
333  case wxCAP_PROJECTING: m_cap = agg::square_cap;
334  break;
335  default: m_cap = agg::round_cap;
336  }
337 
339  {
341  invert.Invert();
342  m_strokewidthDev = m_activestroke.GetWidth();
343  m_strokewidthDev = !m_strokewidthDev ? 1 : m_strokewidthDev;
344  m_strokewidth = invert.TransformDistance( m_strokewidthDev );
345  }
346  else
347  {
348  m_strokewidth = m_activestroke.GetWidth();
349  m_strokewidthDev = m_worldtodevice.TransformDistance( m_strokewidth );
350  if ( !m_strokewidthDev )
351  {
352  m_strokewidthDev = 1;
354  invert.Invert();
355  m_strokewidth = invert.TransformDistance( m_strokewidthDev );
356  }
357  }
358  }
359  }
360 }
361 
362 
364 {
365  if ( m_activefill.GetType() == a2dFILL_ONE_COLOUR )
366  {
367  switch( m_activefill.GetStyle() )
368  {
369  case a2dFILL_TRANSPARENT:
370  break;
371  case a2dFILL_SOLID:
372  break;
374  m_pattern = wxImage( BDIAGONAL_HATCH_XPM );
375  break;
377  m_pattern = wxImage( CROSSDIAG_HATCH_XPM );
378  break;
380  m_pattern = wxImage( FDIAGONAL_HATCH_XPM );
381  break;
382  case a2dFILL_CROSS_HATCH:
383  m_pattern = wxImage( CROSS_HATCH_XPM );
384  break;
386  m_pattern = wxImage( HORIZONTAL_HATCH_XPM );
387  break;
389  m_pattern = wxImage( VERTICAL_HATCH_XPM );
390  break;
391  default: ;
392  }
393  if ( m_activefill.GetStyle() >= a2dFIRST_HATCH && m_activefill.GetStyle() <= a2dLAST_HATCH )
394  {
395  m_pattern.Replace( 0, 0, 0,
399 
400  m_pattern_rbuf.attach( m_pattern.GetData(), m_pattern.GetWidth(), m_pattern.GetHeight(), m_pattern.GetWidth() * 3 );
401  }
402  }
403  else if ( m_activefill.GetType() == a2dFILL_HATCH_TWO_COLOUR )
404  {
405  bool nohatch = false;
406  switch( m_activefill.GetStyle() )
407  {
409  m_pattern = wxImage( BDIAGONAL_HATCH_XPM );
410  break;
412  m_pattern = wxImage( CROSSDIAG_HATCH_XPM );
413  break;
415  m_pattern = wxImage( FDIAGONAL_HATCH_XPM );
416  break;
418  m_pattern = wxImage( CROSS_HATCH_XPM );
419  break;
421  m_pattern = wxImage( HORIZONTAL_HATCH_XPM );
422  break;
424  m_pattern = wxImage( VERTICAL_HATCH_XPM );
425  break;
426  default:
427  nohatch = true;
428  break;
429  }
430  m_pattern.Replace( 255, 255, 255,
434 
435  m_pattern.Replace( 0, 0, 0,
439 
440  m_pattern_rbuf.attach( m_pattern.GetData(), m_pattern.GetWidth(), m_pattern.GetHeight(), m_pattern.GetWidth() * 3 );
441  }
442  else if ( m_activefill.GetType() == a2dFILL_BITMAP )
443  {
444  wxBrush dcbrush;
445  //wxBrushStyle style;
446  switch( m_activefill.GetStyle() )
447  {
448  case a2dFILL_STIPPLE:
451  {
452  static const int MASK_RED = 1;
453  static const int MASK_GREEN = 2;
454  static const int MASK_BLUE = 3;
455 
456  m_pattern = m_activefill.GetStipple().ConvertToImage();
457  m_pattern.Replace( MASK_RED, MASK_GREEN, MASK_BLUE,
461 
462  m_pattern_rbuf.attach( m_pattern.GetData(), m_pattern.GetWidth(), m_pattern.GetHeight(), m_pattern.GetWidth() * 3 );
463 
464  //test to see what effect it has
465  //PixFormat pixf(m_pattern_rbuf);
466  //agg::renderer_base<pixfmt> rb(pixf);
467  //rb.clear(agg::rgba(0.4, 0.5, 0.1, 1.0)); // Pattern background color
468  //rb.clear(agg::rgba8(0,250,80));
469  }
470  break;
471  default:
472  break;
473  }
474  }
475  else if ( m_activefill.GetType() == a2dFILL_GRADIENT_FILL_LINEAR )
476  {
477  double profile = 1.0;
478  int i;
479  double x1 = m_activefill.GetStart().m_x;
480  double y1 = m_activefill.GetStart().m_y;
481  double x2 = m_activefill.GetStop().m_x;
482  double y2 = m_activefill.GetStop().m_y;
485  int startGradient = 128 - int( profile * 128.0 );
486  int endGradient = 128 + int( profile * 128.0 );
487  if ( endGradient <= startGradient ) endGradient = startGradient + 1;
488  double k = 1.0 / double( endGradient - startGradient );
489  for ( i = 0; i < startGradient; i++ )
490  {
491  m_fillGradient[i] = c1;
492  }
493  for ( ; i < endGradient; i++ )
494  {
495  m_fillGradient[i] = c1.gradient( c2, double( i - startGradient ) * k );
496  }
497  for ( ; i < 256; i++ )
498  {
499  m_fillGradient[i] = c2;
500  }
501  double angle = atan2( y2 - y1, x2 - x1 );
502  m_fillGradientMatrix.reset();
503  m_fillGradientMatrix *= agg::trans_affine_rotation( angle );
504  m_fillGradientMatrix *= agg::trans_affine_translation( x1, y1 );
505  m_fillGradientMatrix *= _get_agg_user_to_device_transform();
506  m_fillGradientMatrix.invert();
507  m_fillGradientD1 = 0;
508  m_fillGradientD2 = sqrt( ( x2 - x1 ) * ( x2 - x1 ) + ( y2 - y1 ) * ( y2 - y1 ) );
509  }
510  else if ( m_activefill.GetType() == a2dFILL_GRADIENT_FILL_RADIAL )
511  {
512  double profile = 1.0;
513  int i;
514  double xf = m_activefill.GetFocal().m_x;
515  double yf = m_activefill.GetFocal().m_y;
516  double x = m_activefill.GetCenter().m_x;
517  double y = m_activefill.GetCenter().m_y;
518  double r = m_activefill.GetRadius();
519 
522  int startGradient = 128 - int( profile * 127.0 );
523  int endGradient = 128 + int( profile * 127.0 );
524  if ( endGradient <= startGradient ) endGradient = startGradient + 1;
525  double k = 1.0 / double( endGradient - startGradient );
526  for ( i = 0; i < startGradient; i++ )
527  {
528  m_fillGradient[i] = c1;
529  }
530  for ( ; i < endGradient; i++ )
531  {
532  m_fillGradient[i] = c1.gradient( c2, double( i - startGradient ) * k );
533  }
534  for ( ; i < 256; i++ )
535  {
536  m_fillGradient[i] = c2;
537  }
538  m_fillGradientD2 = m_usertodevice.TransformDistance( r );
539  m_usertodevice.TransformPoint( x, y, x, y );
540  m_fillGradientMatrix.reset();
541  m_fillGradientMatrix *= agg::trans_affine_translation( x, y );
542  m_fillGradientMatrix.invert();
543  m_fillGradientD1 = 0;
544  }
545 }
546 
547 void a2dAggDrawerBase::SetClippingRegion( a2dVertexList* points, bool spline, wxPolygonFillMode fillStyle )
548 {
549  unsigned int n = points->size();
550  m_cpointsDouble.resize( n );
551 
552  unsigned int i = 0;
553  double x, y;
554  forEachIn( a2dVertexList, points )
555  {
556  a2dPoint2D point = ( *iter )->GetPoint();
557  //transform to device
558  GetUserToDeviceTransform().TransformPoint( point.m_x, point.m_y, x, y );
559  m_cpointsDouble[i].x = x;
560  m_cpointsDouble[i].y = y;
561  i++;
562  }
563 
564  if ( spline )
565  n = ConvertSplinedPolygon2( n );
566 
567  wxPoint* intCPoints = new wxPoint[n];
568 
569  for ( i = 0; i < n; i++ )
570  {
571  intCPoints[i].x = Round( m_cpointsDouble[i].x );
572  intCPoints[i].y = Round( m_cpointsDouble[i].y );
573  }
574 
575  m_clip = wxRegion( n, intCPoints, fillStyle );
576 
577  delete[] intCPoints;
578 }
579 
580 void a2dAggDrawerBase::ExtendAndPushClippingRegion( a2dVertexList* points, bool spline, wxPolygonFillMode fillStyle, a2dBooleanClip clipoperation )
581 {
582 
583  wxRegion* push = new wxRegion( m_clip );
584 
585  m_clipregionlist.Insert( push );
586 
587  ExtendClippingRegion( points, spline, fillStyle, clipoperation );
588 }
589 
590 void a2dAggDrawerBase::ExtendClippingRegion( a2dVertexList* points, bool spline, wxPolygonFillMode fillStyle, a2dBooleanClip clipoperation )
591 {
592  wxRegion totaladd;
593  bool first = false;
594 
595  unsigned int n = points->size();
596  m_cpointsDouble.resize( n );
597 
598  unsigned int i = 0;
599  double x, y;
600  forEachIn( a2dVertexList, points )
601  {
602  a2dPoint2D point = ( *iter )->GetPoint();
603  //transform to device
604  GetUserToDeviceTransform().TransformPoint( point.m_x, point.m_y, x, y );
605  m_cpointsDouble[i].x = x;
606  m_cpointsDouble[i].y = y;
607  i++;
608  }
609 
610  if ( spline )
611  n = ConvertSplinedPolygon2( n );
612 
613  wxPoint* intCPoints = new wxPoint[n];
614 
615  for ( i = 0; i < n; i++ )
616  {
617  intCPoints[i].x = Round( m_cpointsDouble[i].x );
618  intCPoints[i].y = Round( m_cpointsDouble[i].y );
619  }
620 
621  wxRegion add = wxRegion( n, intCPoints, fillStyle );
622 
623  delete[] intCPoints;
624 
625  if ( !first )
626  {
627  totaladd = add;
628  first = true;
629  }
630  else
631  totaladd.Union( add );
632 
633  if ( !m_clip.Empty() )
634  {
635  bool result;
636  switch ( clipoperation )
637  {
638  case a2dCLIP_AND:
639  result = m_clip.Intersect( totaladd );
640  break ;
641 
642  case a2dCLIP_OR:
643  result = m_clip.Union( totaladd );
644  break ;
645 
646  case a2dCLIP_XOR:
647  result = m_clip.Xor( totaladd );
648  break ;
649 
650  case a2dCLIP_DIFF:
651  result = m_clip.Subtract( totaladd );
652  break ;
653 
654  case a2dCLIP_COPY:
655  default:
656  m_clip = totaladd;
657  result = true;
658  break ;
659 
660  }
661  if ( result )
662  {
663  //DestroyClippingRegion();
664  //SetClippingRegion( m_clip );
665  }
666  }
667  else
668  {
669  m_clip = totaladd;
670  //DestroyClippingRegion();
671  //SetClippingRegion( m_clip );
672  }
673 
674  m_clipboxdev = m_clip.GetBox();
676 }
677 
679 {
680  if ( !m_clipregionlist.GetCount() )
681  return;
682 
683  m_clip = *m_clipregionlist.GetFirst()->GetData();
684  delete m_clipregionlist.GetFirst()->GetData();
685  m_clipregionlist.DeleteNode( m_clipregionlist.GetFirst() );
686  //DestroyClippingRegion();
687  //SetClippingRegion( m_clip );
688 
689 }
690 
691 void a2dAggDrawerBase::SetClippingRegionDev( wxCoord minx, wxCoord miny, wxCoord width, wxCoord height )
692 {
693  m_clip = wxRegion( minx, miny, width, height );
694 
695  m_clipboxdev = wxRect( minx, miny, width, height );
696  RenderSetClip();
697  // why not the next, does not work??
698  //m_rasterizer.clip_box( minx, miny, width, height );
700 }
701 
702 void a2dAggDrawerBase::SetClippingRegion( double minx, double miny, double maxx, double maxy )
703 {
704  int iminx = WorldToDeviceX( minx );
705  int iminy = WorldToDeviceY( miny );
706  int imaxx = WorldToDeviceX( maxx );
707  int imaxy = WorldToDeviceY( maxy );
708  if ( m_yaxis )
709  {
710  m_clip = wxRegion( iminx, imaxy, imaxx - iminx, iminy - imaxy );
711  m_clipboxdev = wxRect( iminx, imaxy, imaxx - iminx, iminy - imaxy );
712  }
713  else
714  {
715  m_clip = wxRegion( iminx, iminy, imaxx - iminx, imaxy - iminy );
716  m_clipboxdev = wxRect( iminx, iminy, imaxx - iminx, imaxy - iminy );
717  }
718  RenderSetClip();
719  // why not the next, does not work??
720  //m_rasterizer.clip_box( m_clipboxdev.x, m_clipboxdev.y, m_clipboxdev.x + m_clipboxdev.width, m_clipboxdev.y + m_clipboxdev.height);
721 
723 }
724 
726 {
727  m_clip.Clear();
728 
729  m_clipboxdev = wxRect( 0, 0, m_width, m_height );
731  RenderSetClip();
732 }
733 
734 int a2dAggDrawerBase::ToAggPath( a2dVertexArray* points, bool transform )
735 {
736  unsigned int segments = 0;
737 
738  m_path.remove_all();
739 
740  unsigned int count = 0;
741  double x, y, lastx, lasty;
742  int i;
743  for ( i = 0; i < points->size(); i++ )
744  {
745  const a2dLineSegmentPtr seg = points->Item( i );
746 
747  if ( !seg->GetArc() )
748  {
749  if ( transform )
750  m_usertodevice.TransformPoint( seg->m_x, seg->m_y, x, y );
751  else
752  {
753  x = seg->m_x;
754  y = seg->m_y;
755  }
756 
757  //to reduce the points count for lines or a polygon on the screen
758  if( !count || fabs( x - lastx ) > 0.001 || fabs( y - lasty ) > 0.001 )
759  {
760  if ( count == 0 )
761  m_path.move_to( x, y );
762  else
763  m_path.line_to( x, y );
764  lastx = x;
765  lasty = y;
766  count++;
767  }
768  }
769  else
770  {
771  const a2dArcSegment* cseg = ( const a2dArcSegment* ) seg.Get();
772 
773  double radius, center_x, center_y, beginrad, midrad, endrad, phit;
774 
775  if ( cseg->CalcR( *( points->Item( i ? i - 1 : 0 ) ), radius, center_x, center_y, beginrad, midrad, endrad, phit ) )
776  {
777  double dphi;
778  unsigned int segments;
779  double radiusDev = m_usertodevice.TransformDistance( radius );
780  Aberration( m_displayaberration, phit, radiusDev , dphi, segments );
781 
782  double theta = beginrad;
783  unsigned int step;
784 
785  double x, y;
786  for ( step = 0; step < segments + 1; step++ )
787  {
788  if ( transform )
789  m_usertodevice.TransformPoint( center_x + radius * cos ( theta ), center_y + radius * sin ( theta ), x, y );
790  else
791  {
792  x = center_x + radius * cos ( theta );
793  y = center_y + radius * sin ( theta );
794  }
795  //to reduce the points count for lines or a polygon on the screen
796  if( !count || fabs( x - lastx ) > 0.001 || fabs( y - lasty ) > 0.001 )
797  {
798  if ( count == 0 )
799  m_path.move_to( x, y );
800  else
801  m_path.line_to( x, y );
802 
803  lastx = x;
804  lasty = y;
805  count++;
806  }
807  theta = theta + dphi;
808  }
809  }
810  else
811  {
812  double x, y;
813  if ( transform )
814  m_usertodevice.TransformPoint( cseg->m_x, cseg->m_y, x, y );
815  else
816  {
817  x = cseg->m_x;
818  y = cseg->m_y;
819  }
820 
821  //to reduce the points count for lines or a polygon on the screen
822  if( !count || fabs( x - lastx ) > 0.001 || fabs( y - lasty ) > 0.001 )
823  {
824  if ( count == 0 )
825  m_path.move_to( x, y );
826  else
827  m_path.line_to( x, y );
828  lastx = x;
829  lasty = y;
830  count++;
831  }
832  }
833  }
834  }
835 
836  return count;
837 }
838 
839 int a2dAggDrawerBase::ToAggPath( const a2dVertexList* list, bool transform )
840 {
841  unsigned int segments = 0;
842 
843  if ( list->empty() )
844  return 0;
845 
846  m_path.remove_all();
847 
848  a2dVertexList::const_iterator iterprev = list->end();
849 
850  unsigned int count = 0;
851  double x, y, lastx, lasty;
852  iterprev = list->end();
853  if ( iterprev != list->begin() )
854  iterprev--;
855  a2dVertexList::const_iterator iter = list->begin();
856  iter = list->begin();
857  while ( iter != list->end() )
858  {
859  a2dLineSegment* seg = ( *iter );
860 
861  if ( !seg->GetArc() )
862  {
863  if ( transform )
864  m_usertodevice.TransformPoint( seg->m_x, seg->m_y, x, y );
865  else
866  {
867  x = seg->m_x;
868  y = seg->m_y;
869  }
870 
871  //to reduce the points count for lines or a polygon on the screen
872  if( !count || fabs( x - lastx ) > 0.001 || fabs( y - lasty ) > 0.001 )
873  {
874  if ( count == 0 )
875  m_path.move_to( x, y );
876  else
877  m_path.line_to( x, y );
878  lastx = x;
879  lasty = y;
880  count++;
881  }
882  }
883  else
884  {
885  a2dArcSegment* cseg = ( a2dArcSegment* ) seg;
886 
887  double radius, center_x, center_y, beginrad, midrad, endrad, phit;
888 
889  if ( cseg->CalcR( *( *iterprev ), radius, center_x, center_y, beginrad, midrad, endrad, phit ) )
890  {
891  double dphi;
892  unsigned int segments;
893  double radiusDev = m_usertodevice.TransformDistance( radius );
894  Aberration( m_displayaberration, phit, radiusDev , dphi, segments );
895 
896  double theta = beginrad;
897  unsigned int step;
898 
899  double x, y;
900  for ( step = 0; step < segments + 1; step++ )
901  {
902  if ( transform )
903  m_usertodevice.TransformPoint( center_x + radius * cos ( theta ), center_y + radius * sin ( theta ), x, y );
904  else
905  {
906  x = center_x + radius * cos ( theta );
907  y = center_y + radius * sin ( theta );
908  }
909 
910  //to reduce the points count for lines or a polygon on the screen
911  if( !count || fabs( x - lastx ) > 0.001 || fabs( y - lasty ) > 0.001 )
912  {
913  if ( count == 0 )
914  m_path.move_to( x, y );
915  else
916  m_path.line_to( x, y );
917  lastx = x;
918  lasty = y;
919  count++;
920  }
921  theta = theta + dphi;
922  }
923  }
924  else
925  {
926  double x, y;
927  if ( transform )
928  m_usertodevice.TransformPoint( cseg->m_x, cseg->m_y, x, y );
929  else
930  {
931  x = cseg->m_x;
932  y = cseg->m_y;
933  }
934 
935  //to reduce the points count for lines or a polygon on the screen
936  if( !count || fabs( x - lastx ) > 0.001 || fabs( y - lasty ) > 0.001 )
937  {
938  if ( count == 0 )
939  m_path.move_to( x, y );
940  else
941  m_path.line_to( x, y );
942  lastx = x;
943  lasty = y;
944  count++;
945  }
946  }
947  }
948  iterprev = iter++;
949  }
950 
951  return count;
952 }
953 
954 void a2dAggDrawerBase::ShiftBufferInternal( int dxy, bool yshift, int bytesPerPixel )
955 {
956  if ( yshift )
957  {
958  int pixelwidth = m_width * bytesPerPixel;
959  //pixel coordinates so ( 0,0 ) upper left
960  if ( dxy > 0 && dxy < m_height )
961  {
962  unsigned char* highline = m_pdata + ( m_height - dxy ) * pixelwidth ;
963  unsigned char* lowline = m_pdata + m_height * pixelwidth ;
964 
965  for ( int yp = 0; yp < m_height - dxy; yp++ )
966  {
967  highline -= pixelwidth;
968  lowline -= pixelwidth;
969  memcpy( lowline, highline, pixelwidth );
970  }
971  }
972  else if ( dxy < 0 && dxy > -m_height )
973  {
974  dxy = -dxy;
975  unsigned char* highline = m_pdata;
976  unsigned char* lowline = m_pdata + dxy * pixelwidth ;
977 
978  for ( int yp = 0; yp < m_height - dxy ; yp++ )
979  {
980  memcpy( highline, lowline, pixelwidth );
981  highline += pixelwidth;
982  lowline += pixelwidth;
983  }
984  }
985  else
986  wxFAIL_MSG( wxT( "you can only shift within height of buffer" ) );
987  }
988  else
989  {
990  int pixelwidth = m_width * bytesPerPixel;
991  if ( dxy > 0 && dxy < m_width )
992  {
993  int subwidth = ( m_width - dxy ) * bytesPerPixel;
994  unsigned char* low = m_pdata;
995  unsigned char* high = m_pdata + dxy * bytesPerPixel;
996 
997  for ( int yp = 0; yp < m_height ; yp++ )
998  {
999  memmove( high, low, subwidth );
1000  high += pixelwidth;
1001  low += pixelwidth;
1002  }
1003  }
1004  else if ( dxy < 0 && dxy > -m_width )
1005  {
1006  dxy = -dxy;
1007  int subwidth = ( m_width - dxy ) * bytesPerPixel;
1008  unsigned char* low = m_pdata;
1009  unsigned char* high = m_pdata + dxy * bytesPerPixel ;
1010 
1011  for ( int yp = 0; yp < m_height ; yp++ )
1012  {
1013  memmove( low, high, subwidth );
1014  high += pixelwidth;
1015  low += pixelwidth;
1016  }
1017  }
1018  else
1019  wxFAIL_MSG( wxT( "you can only shift within width of buffer" ) );
1020  }
1021 }
1022 
1023 template< class PathT >
1024 void a2dAggDrawerBase::_ras_add_stroked_path_xform( PathT& path, const
1025  agg::trans_affine& mtx )
1026 {
1027  // This does the job of constructing all stroke rendering pipelines
1028  // based on the current stroke parameters.
1029  // Transformation is always part of the pipeline, but sometimes its
1030  // a no-op transformer (noop_conv_transform).
1031 
1032  if ( m_style == a2dSTROKE_SOLID )
1033  {
1034  if ( m_preStroke )
1035  {
1036  typedef agg::conv_stroke< PathT > path_stroke_t;
1037  typedef agg::conv_transform< path_stroke_t > path_stroke_trans_t;
1038 
1039  path_stroke_t stroke( path );
1040  path_stroke_trans_t trans_path( stroke, mtx );
1041  stroke.line_join( m_join );
1042  stroke.line_cap( m_cap );
1044  stroke.width( m_strokewidthDev );
1045  else
1046  stroke.width( m_strokewidth );
1047  m_rasterizer.reset();
1048  m_rasterizer.add_path( trans_path );
1049  }
1050  else
1051  {
1052  typedef agg::conv_transform<PathT> trans_t;
1053  typedef agg::conv_stroke< trans_t > path_stroke_t;
1054 
1055  trans_t trans_path( path, mtx );
1056  path_stroke_t stroke( trans_path );
1057  //stroke.miter_limit();
1058  stroke.line_join( m_join );
1059  stroke.line_cap( m_cap );
1060  stroke.width( m_strokewidthDev );
1061  m_rasterizer.reset();
1062  m_rasterizer.add_path( stroke );
1063  }
1064  }
1065  else
1066  {
1067  if ( m_preStroke )
1068  {
1069  typedef agg::conv_dash< PathT > path_dash_t;
1070  typedef agg::conv_stroke< path_dash_t > path_dashstroked_t;
1071  typedef agg::conv_transform< path_dashstroked_t > path_transdash_t;
1072 
1073  path_dash_t dash_path( path );
1074  path_dashstroked_t stroke( dash_path );
1075  path_transdash_t trans_path( stroke, mtx );
1076 
1077  double scale = m_strokewidth;
1078  if ( scale < 1.0 ) scale = 1.0;
1079  //scale = 1.0;
1080  switch( m_style )
1081  {
1082  case a2dSTROKE_DOT:
1083  dash_path.add_dash( 0.25 * scale, 1.5 * scale );
1084  break;
1085  case a2dSTROKE_DOT_DASH:
1086  dash_path.add_dash( 0.25 * scale, 1.5 * scale );
1087  dash_path.add_dash( 2.0 * scale, 2.0 * scale );
1088  break;
1089  case a2dSTROKE_LONG_DASH:
1090  dash_path.add_dash( 2.0 * scale, 2.0 * scale );
1091  break;
1092  case a2dSTROKE_SHORT_DASH:
1093  dash_path.add_dash( 2.0 * scale, 2.0 * scale );
1094  break;
1095  //case a2dSTROKE_USER_DASH:
1096  // break;
1097  }
1098  //dash_path.dash_start(m_dash_offset);
1099  stroke.line_join( m_join );
1100  stroke.line_cap( m_cap );
1101  //stroke.miter_limit();
1103  stroke.width( m_strokewidth );
1104  else
1105  stroke.width( m_strokewidthDev );
1106  m_rasterizer.reset();
1107  m_rasterizer.add_path( trans_path );
1108  }
1109  else
1110  {
1111  typedef agg::conv_transform<PathT> trans_t;
1112  typedef agg::conv_dash< trans_t > path_transdash_t;
1113  typedef agg::conv_stroke< path_transdash_t > path_dashstroked_t;
1114 
1115  trans_t trans_path( path, mtx );
1116  path_transdash_t dash_path( trans_path );
1117  path_dashstroked_t stroke( dash_path );
1118 
1119  double scale = m_strokewidthDev;
1120  if ( scale < 1.0 ) scale = 1.0;
1121  //scale = 1.0;
1122  switch( m_style )
1123  {
1124  case a2dSTROKE_DOT:
1125  dash_path.add_dash( 0.25 * scale, 1.5 * scale );
1126  break;
1127  case a2dSTROKE_DOT_DASH:
1128  dash_path.add_dash( 0.25 * scale, 1.5 * scale );
1129  dash_path.add_dash( 2.0 * scale, 2.0 * scale );
1130  break;
1131  case a2dSTROKE_LONG_DASH:
1132  dash_path.add_dash( 2.0 * scale, 2.0 * scale );
1133  break;
1134  case a2dSTROKE_SHORT_DASH:
1135  dash_path.add_dash( 2.0 * scale, 2.0 * scale );
1136  break;
1137  //case a2dSTROKE_USER_DASH:
1138  // break;
1139  }
1140  //dash_path.dash_start(m_dash_offset);
1141  stroke.line_join( m_join );
1142  stroke.line_cap( m_cap );
1143  //stroke.miter_limit();
1144  stroke.width( m_strokewidthDev );
1145  m_rasterizer.reset();
1146  m_rasterizer.add_path( stroke );
1147  }
1148 
1149  }
1150 }
1151 
1152 void a2dAggDrawerBase::DrawCircle( double x, double y, double radius )
1153 {
1154  if ( m_disableDrawing )
1155  return;
1156 
1157  DrawEllipse( x, y, radius * 2, radius * 2 );
1158 }
1159 
1160 void a2dAggDrawerBase::DrawPoint( double xc, double yc )
1161 {
1162  if ( m_disableDrawing )
1163  return;
1164 
1165  m_usertodevice.TransformPoint( xc, yc, xc, yc );
1167 }
1168 
1170 {
1171 #if wxART2D_USE_FREETYPE && defined(__USE_WINAPI__)
1172  if ( m_currentfont.GetType() == a2dFONT_WXDC && m_currentfont.GetFreetypeFont().Ok() )
1173  {
1174  a2dFont oldfont = m_currentfont;
1175  m_currentfont = m_currentfont.GetFreetypeFont();
1176  DrawCharFreetype( c );
1177  m_currentfont = oldfont;
1178  }
1179  else
1181 #else // wxART2D_USE_FREETYPE && defined(__USE_WINAPI__)
1183 #endif // wxART2D_USE_FREETYPE && defined(__USE_WINAPI__)
1184 }
1185 
1186 void a2dAggDrawerBase::DrawRoundedRectangle( double x, double y, double width, double height, double radius, bool pixelsize )
1187 {
1188  if ( m_disableDrawing )
1189  return;
1190 
1191  if ( width == 0 || height == 0 )
1192  return;
1193 
1194  if ( pixelsize )
1195  {
1196  width = DeviceToWorldXRel( width );
1197  height = DeviceToWorldYRel( height );
1198  radius = DeviceToWorldXRel( radius );
1199  if( m_yaxis )
1200  height = -height;
1201  }
1202 
1203  if ( !IsStrokeOnly() )
1204  {
1205  agg::trans_affine mtx = _get_agg_user_to_device_transform();
1206 
1207  if ( fabs( radius ) <= 0.00000001 )
1208  {
1209  plain_rect r( x, y, x + width, y + height );
1210  agg::conv_transform<plain_rect> tr( r, mtx );
1211  m_rasterizer.reset();
1212  m_rasterizer.add_path( tr );
1213  }
1214  else
1215  {
1216  agg::rounded_rect r( x, y, x + width, y + height, radius );
1217  r.normalize_radius();
1218  agg::conv_transform<agg::rounded_rect> tr( r, mtx );
1219  m_rasterizer.reset();
1220  m_rasterizer.add_path( tr );
1221  }
1222 
1223  if ( m_activefill.GetType() == a2dFILL_GRADIENT_FILL_LINEAR )
1224  {
1225  RenderGradient( false );
1226  }
1227  else if ( m_activefill.GetType() == a2dFILL_GRADIENT_FILL_RADIAL )
1228  {
1229  RenderGradient( true );
1230  }
1231  else if ( m_activefill.GetType() == a2dFILL_BITMAP ||
1232  ( m_activefill.GetStyle() >= a2dFIRST_HATCH && m_activefill.GetStyle() <= a2dLAST_HATCH ) ||
1233  ( m_activefill.GetStyle() >= a2dFIRST_TWOCOL_HATCH && m_activefill.GetStyle() <= a2dLAST_TWOCOL_HATCH ) )
1234  {
1235  RenderBitmapFill();
1236  }
1237  else
1238  {
1239  Render( true );
1240  }
1241  }
1242 
1243  if ( IsStroked() )
1244  {
1245  if ( fabs( radius ) <= 0.00000001 )
1246  {
1247  plain_rect r( x, y, x + width, y + height );
1248  agg::trans_affine mtx = _get_agg_user_to_device_transform();
1249  m_rasterizer.reset();
1250  _ras_add_stroked_path_xform( r, mtx );
1251  }
1252  else
1253  {
1254  m_rasterizer.reset();
1255  agg::rounded_rect r( x, y, x + width, y + height, radius );
1256  r.normalize_radius();
1257  agg::trans_affine mtx = _get_agg_user_to_device_transform();
1258  _ras_add_stroked_path_xform( r, mtx );
1259  }
1260  Render( false );
1261  }
1262 }
1263 
1264 void a2dAggDrawerBase::DrawEllipse( double xc, double yc, double width, double height )
1265 {
1266  if ( m_disableDrawing )
1267  return;
1268 
1269  double dphi;
1270  unsigned int segments;
1271 
1272  //circular approximation of radius.
1273  double radiusDev = m_usertodevice.TransformDistance( wxMax( width, height ) );
1274  Aberration( m_displayaberration, wxPI * 2, radiusDev , dphi, segments );
1275 
1276  agg::trans_affine mtx = _get_agg_user_to_device_transform();
1277 
1278  agg::ellipse ellipse( xc, yc, width / 2.0, height / 2.0, segments );
1279 
1280  agg::conv_transform<agg::ellipse> tr( ellipse, mtx );
1281 
1282  if ( !IsStrokeOnly() )
1283  {
1284  m_path.remove_all();
1285  m_path.concat_path( tr, 0 );
1286 
1287  m_rasterizer.reset();
1288  m_rasterizer.add_path( m_path );
1289 
1290  if ( m_activefill.GetType() == a2dFILL_GRADIENT_FILL_LINEAR )
1291  {
1292  RenderGradient( false );
1293  }
1294  else if ( m_activefill.GetType() == a2dFILL_GRADIENT_FILL_RADIAL )
1295  {
1296  RenderGradient( true );
1297  }
1298  else if ( m_activefill.GetType() == a2dFILL_BITMAP ||
1299  ( m_activefill.GetStyle() >= a2dFIRST_HATCH && m_activefill.GetStyle() <= a2dLAST_HATCH ) ||
1300  ( m_activefill.GetStyle() >= a2dFIRST_TWOCOL_HATCH && m_activefill.GetStyle() <= a2dLAST_TWOCOL_HATCH ) )
1301  {
1302  RenderBitmapFill();
1303  }
1304  else
1305  Render( true );
1306  }
1307  if ( IsStroked() )
1308  {
1309  m_rasterizer.reset();
1310  _ras_add_stroked_path_xform( ellipse, mtx );
1311  Render( false );
1312  }
1313 }
1314 
1315 void a2dAggDrawerBase::DrawPolygon( a2dVertexArray* array, bool spline, wxPolygonFillMode fillStyle )
1316 {
1317  if ( m_disableDrawing )
1318  return;
1319 
1320  int segments;
1321  if ( spline )
1322  {
1323  a2dVertexArray* splinedlist = array->ConvertSplinedPolyline( m_splineaberration );
1324  segments = ToAggPath( splinedlist, false );
1325  delete splinedlist;
1326  }
1327  else
1328  segments = ToAggPath( array, false );
1329 
1330  if ( segments == 0 )
1331  return;
1332 
1333  agg::trans_affine mtx = _get_agg_user_to_device_transform();
1334  if ( IsStrokeOnly() )
1335  {
1336  }
1337  else if ( m_activefill.GetType() == a2dFILL_GRADIENT_FILL_LINEAR )
1338  {
1339  m_path.close_polygon();
1340  agg::conv_transform<agg::path_storage> tr( m_path, mtx );
1341  m_rasterizer.reset();
1342  m_rasterizer.add_path( tr );
1343 
1344  RenderGradient( false );
1345  }
1346  else if ( m_activefill.GetType() == a2dFILL_GRADIENT_FILL_RADIAL )
1347  {
1348  m_path.close_polygon();
1349  agg::conv_transform<agg::path_storage> tr( m_path, mtx );
1350  m_rasterizer.reset();
1351  m_rasterizer.add_path( tr );
1352 
1353  RenderGradient( true );
1354  }
1355  else if ( m_activefill.GetType() == a2dFILL_BITMAP ||
1356  ( m_activefill.GetStyle() >= a2dFIRST_HATCH && m_activefill.GetStyle() <= a2dLAST_HATCH ) ||
1357  ( m_activefill.GetStyle() >= a2dFIRST_TWOCOL_HATCH && m_activefill.GetStyle() <= a2dLAST_TWOCOL_HATCH ) )
1358  {
1359  m_path.close_polygon();
1360  agg::conv_transform<agg::path_storage> tr( m_path, mtx );
1361  m_rasterizer.reset();
1362  m_rasterizer.add_path( tr );
1363 
1364  RenderBitmapFill();
1365  }
1366  else //normal solid case
1367  {
1368  m_path.close_polygon();
1369  agg::conv_transform<agg::path_storage> tr( m_path, mtx );
1370  m_rasterizer.reset();
1371  m_rasterizer.add_path( tr );
1372 
1373  Render( true );
1374  }
1375 
1376  if ( IsStroked() )
1377  {
1378  m_rasterizer.reset();
1379  m_path.close_polygon();
1380  _ras_add_stroked_path_xform( m_path, mtx );
1381 
1382  Render( false );
1383  }
1384 }
1385 
1386 void a2dAggDrawerBase::DrawPolygon( const a2dVertexList* list, bool spline, wxPolygonFillMode fillStyle )
1387 {
1388  if ( m_disableDrawing )
1389  return;
1390 
1391  int segments;
1392  if ( spline )
1393  {
1394  a2dVertexList* splinedlist = list->ConvertSplinedPolygon( m_splineaberration );
1395  segments = ToAggPath( splinedlist, false );
1396  delete splinedlist;
1397  }
1398  else
1399  segments = ToAggPath( list, false );
1400 
1401  if ( segments == 0 )
1402  return;
1403 
1404  agg::trans_affine mtx = _get_agg_user_to_device_transform();
1405  if ( IsStrokeOnly() )
1406  {
1407  }
1408  else if ( m_activefill.GetType() == a2dFILL_GRADIENT_FILL_LINEAR )
1409  {
1410  m_path.close_polygon();
1411  agg::conv_transform<agg::path_storage> tr( m_path, mtx );
1412  m_rasterizer.reset();
1413  m_rasterizer.add_path( tr );
1414 
1415  RenderGradient( false );
1416  }
1417  else if ( m_activefill.GetType() == a2dFILL_GRADIENT_FILL_RADIAL )
1418  {
1419  m_path.close_polygon();
1420  agg::conv_transform<agg::path_storage> tr( m_path, mtx );
1421  m_rasterizer.reset();
1422  m_rasterizer.add_path( tr );
1423 
1424  RenderGradient( true );
1425  }
1426  else if ( m_activefill.GetType() == a2dFILL_BITMAP ||
1427  ( m_activefill.GetStyle() >= a2dFIRST_HATCH && m_activefill.GetStyle() <= a2dLAST_HATCH ) ||
1428  ( m_activefill.GetStyle() >= a2dFIRST_TWOCOL_HATCH && m_activefill.GetStyle() <= a2dLAST_TWOCOL_HATCH ) )
1429  {
1430  m_path.close_polygon();
1431 
1432  agg::conv_transform<agg::path_storage> tr( m_path, mtx );
1433  m_rasterizer.reset();
1434  m_rasterizer.add_path( tr );
1435 
1436  RenderBitmapFill();
1437  }
1438  else //normal solid case
1439  {
1440  m_path.close_polygon();
1441 
1442  agg::conv_transform<agg::path_storage> tr( m_path, mtx );
1443  m_rasterizer.reset();
1444  m_rasterizer.add_path( tr );
1445 
1446  Render( true );
1447  }
1448 
1449  if ( IsStroked() )
1450  {
1451  m_rasterizer.reset();
1452  m_path.close_polygon();
1453  _ras_add_stroked_path_xform( m_path, mtx );
1454  Render( false );
1455  }
1456 }
1457 
1458 void a2dAggDrawerBase::DrawPolyPolygon( a2dListOfa2dVertexList polylist, wxPolygonFillMode fillStyle )
1459 {
1460  if ( m_disableDrawing )
1461  return;
1462 
1463  for( a2dListOfa2dVertexList::iterator iterp = polylist.begin(); iterp != polylist.end(); iterp++ )
1464  {
1465  DrawPolygon( *iterp, false, fillStyle );
1466  }
1467 }
1468 
1469 void a2dAggDrawerBase::DrawLines( const a2dVertexList* list, bool spline )
1470 {
1471  if ( m_disableDrawing )
1472  return;
1473 
1474  int segments;
1475  if ( spline )
1476  {
1478  segments = ToAggPath( splinedlist, false );
1479  delete splinedlist;
1480  }
1481  else
1482  segments = ToAggPath( list, false );
1483 
1484  if ( segments == 0 )
1485  return;
1486 
1487  agg::trans_affine mtx = _get_agg_user_to_device_transform();
1488  m_rasterizer.reset();
1489  _ras_add_stroked_path_xform( m_path, mtx );
1490  Render( false );
1491 }
1492 
1493 void a2dAggDrawerBase::DrawLines( a2dVertexArray* array, bool spline )
1494 {
1495  if ( m_disableDrawing )
1496  return;
1497 
1498  int segments;
1499  if ( spline )
1500  {
1501  a2dVertexArray* splinedlist = array->ConvertSplinedPolyline( m_splineaberration );
1502  segments = ToAggPath( splinedlist, false );
1503  delete splinedlist;
1504  }
1505  else
1506  segments = ToAggPath( array, false );
1507 
1508  if ( segments == 0 )
1509  return;
1510 
1511  agg::trans_affine mtx = _get_agg_user_to_device_transform();
1512  m_rasterizer.reset();
1513  _ras_add_stroked_path_xform( m_path, mtx );
1514  Render( false );
1515 }
1516 
1518 {
1519  double x, y;
1520  x = y = 0.0;
1521 
1522  if ( m_disableDrawing )
1523  return;
1524 
1525 #if wxART2D_USE_FREETYPE
1526  y += m_currentfont.GetDescent();
1527 
1528  agg::path_storage path;
1529  double scale = m_currentfont.GetSize() / ( 64 * m_currentfont.GetDeviceHeight() );
1530 
1531  FT_Glyph glyph = m_currentfont.GetGlyphFreetype( c )->m_glyph;
1532  if ( glyph->format != FT_GLYPH_FORMAT_OUTLINE )
1533  return;
1534  FT_Outline& outline = ( ( FT_OutlineGlyph ) glyph )->outline;
1535 
1536  FT_Vector v_last;
1537  FT_Vector v_control;
1538  FT_Vector v_start;
1539 
1540  FT_Vector* point;
1541  FT_Vector* limit;
1542  char* tags;
1543 
1544  int n; // index of contour in outline
1545  int first; // index of first point in contour
1546  char tag; // current point's state
1547 
1548  first = 0;
1549 
1550  for( n = 0; n < outline.n_contours; n++ )
1551  {
1552  int last; // index of last point in contour
1553 
1554  last = outline.contours[n];
1555  limit = outline.points + last;
1556 
1557  v_start = outline.points[first];
1558  v_last = outline.points[last];
1559 
1560  v_control = v_start;
1561 
1562  point = outline.points + first;
1563  tags = outline.tags + first;
1564  tag = FT_CURVE_TAG( tags[0] );
1565 
1566  // A contour cannot start with a cubic control point!
1567  if( tag == FT_CURVE_TAG_CUBIC ) return;
1568 
1569  // check first point to determine origin
1570  if( tag == FT_CURVE_TAG_CONIC )
1571  {
1572  // first point is conic control. Yes, this happens.
1573  if( FT_CURVE_TAG( outline.tags[last] ) == FT_CURVE_TAG_ON )
1574  {
1575  // start at last point if it is on the curve
1576  v_start = v_last;
1577  limit--;
1578  }
1579  else
1580  {
1581  // if both first and last points are conic,
1582  // start at their middle and record its position
1583  // for closure
1584  v_start.x = ( v_start.x + v_last.x ) / 2;
1585  v_start.y = ( v_start.y + v_last.y ) / 2;
1586 
1587  v_last = v_start;
1588  }
1589  point--;
1590  tags--;
1591  }
1592 
1593  path.move_to( v_start.x, v_start.y );
1594 
1595  while( point < limit )
1596  {
1597  point++;
1598  tags++;
1599 
1600  tag = FT_CURVE_TAG( tags[0] );
1601  switch( tag )
1602  {
1603  case FT_CURVE_TAG_ON: // emit a single line_to
1604  {
1605  path.line_to( point->x, point->y );
1606  continue;
1607  }
1608 
1609  case FT_CURVE_TAG_CONIC: // consume conic arcs
1610  {
1611  v_control.x = point->x;
1612  v_control.y = point->y;
1613 
1614 Do_Conic:
1615  if( point < limit )
1616  {
1617  FT_Vector vec;
1618  FT_Vector v_middle;
1619 
1620  point++;
1621  tags++;
1622  tag = FT_CURVE_TAG( tags[0] );
1623 
1624  vec.x = point->x;
1625  vec.y = point->y;
1626 
1627  if( tag == FT_CURVE_TAG_ON )
1628  {
1629  path.curve3( v_control.x, v_control.y, vec.x, vec.y );
1630  continue;
1631  }
1632 
1633  if( tag != FT_CURVE_TAG_CONIC ) return;
1634 
1635  v_middle.x = ( v_control.x + vec.x ) / 2;
1636  v_middle.y = ( v_control.y + vec.y ) / 2;
1637 
1638  path.curve3( v_control.x, v_control.y, v_middle.x, v_middle.y );
1639 
1640  v_control = vec;
1641  goto Do_Conic;
1642  }
1643  path.curve3( v_control.x, v_control.y, v_start.x, v_start.y );
1644  goto Close;
1645  }
1646 
1647  default: // FT_CURVE_TAG_CUBIC
1648  {
1649  FT_Vector vec1, vec2;
1650 
1651  if( point + 1 > limit || FT_CURVE_TAG( tags[1] ) != FT_CURVE_TAG_CUBIC )
1652  {
1653  return;
1654  }
1655 
1656  vec1.x = point[0].x;
1657  vec1.y = point[0].y;
1658  vec2.x = point[1].x;
1659  vec2.y = point[1].y;
1660 
1661  point += 2;
1662  tags += 2;
1663 
1664  if( point <= limit )
1665  {
1666  FT_Vector vec;
1667 
1668  vec.x = point->x;
1669  vec.y = point->y;
1670 
1671  path.curve4( vec1.x, vec1.y, vec2.x, vec2.y, vec.x, vec.y );
1672  continue;
1673  }
1674 
1675  path.curve4( vec1.x, vec1.y, vec2.x, vec2.y, v_start.x, v_start.y );
1676  goto Close;
1677  }
1678  }
1679  }
1680 
1681  path.close_polygon();
1682 
1683 Close:
1684  first = last + 1;
1685  }
1686 
1687  // scale font to size
1688  a2dAffineMatrix affine;
1689  affine.Scale( scale );
1690  affine.Translate( x, y );
1691  affine = GetUserToDeviceTransform() * affine;
1692 
1693  agg::trans_affine mtx( affine.GetValue( 0, 0 ), affine.GetValue( 0, 1 ),
1694  affine.GetValue( 1, 0 ), affine.GetValue( 1, 1 ),
1695  affine.GetValue( 2, 0 ), affine.GetValue( 2, 1 ) );
1696  agg::conv_transform< agg::path_storage > tr( path, mtx );
1697  agg::conv_curve< agg::conv_transform< agg::path_storage > > stroke( tr );
1698 
1699  m_rasterizer.reset();
1700  m_rasterizer.add_path( stroke );
1701 
1702  Render( false );
1703 #else // wxART2D_USE_FREETYPE
1705 #endif // wxART2D_USE_FREETYPE
1706 }
1707 
1709 {
1710  agg::path_storage path;
1711  double size = m_currentfont.GetSize();
1713  if ( ptr )
1714  {
1715  while ( *ptr )
1716  {
1717  a2dVertexList::iterator iter = ( *ptr )->begin();
1718  if ( ( *ptr )->size() )
1719  {
1720  a2dPoint2D point = ( *iter )->GetPoint();
1721  path.move_to( point.m_x * size, point.m_y * size );
1722  iter++;
1723  }
1724  while ( iter != ( *ptr )->end() )
1725  {
1726  a2dPoint2D point = ( *iter )->GetPoint();
1727  path.line_to( point.m_x * size, point.m_y * size );
1728  iter++;
1729  }
1730  ptr++;
1731  }
1732  }
1733 
1734  // apply affine matrix
1735  agg::trans_affine mtx( GetUserToDeviceTransform().GetValue( 0, 0 ), GetUserToDeviceTransform().GetValue( 0, 1 ),
1736  GetUserToDeviceTransform().GetValue( 1, 0 ), GetUserToDeviceTransform().GetValue( 1, 1 ),
1737  GetUserToDeviceTransform().GetValue( 2, 0 ), GetUserToDeviceTransform().GetValue( 2, 1 ) );
1738  agg::conv_transform< agg::path_storage > tr( path, mtx );
1739  agg::conv_stroke< agg::conv_transform< agg::path_storage > > stroke( tr );
1740 
1741  stroke.line_join( m_join );
1742  stroke.line_cap( m_cap );
1743  stroke.width( m_currentfont.GetStrokeWidth() * GetMappingMatrix()( 0, 0 ) );
1744  m_rasterizer.reset();
1745  m_rasterizer.add_path( stroke );
1746 
1747  Render( true );
1748 }
1749 
1750 
1751 
1752 /*******************************************************************
1753 a2dAggDrawerRgba
1754 ********************************************************************/
1755 
1756 IMPLEMENT_DYNAMIC_CLASS( a2dAggDrawerRgba, a2dAggDrawerBase )
1757 
1758 void a2dAggDrawerRgba::DeviceDrawPixel( int x1, int y1, unsigned char r, unsigned char g, unsigned char b , unsigned char a )
1759 {
1760  agg::rgba8 colorfill( m_colour1redStroke, m_colour1greenStroke, m_colour1blueStroke, m_StrokeOpacityCol1 );
1761  m_renBase.blend_pixel( x1, y1, colorfill, 255 );
1762 }
1763 
1764 void a2dAggDrawerRgba::Render( bool fillColor )
1765 {
1766  if ( fillColor )
1767  {
1769  m_renderer.color( colorfill );
1770  m_renSolidComp.color( colorfill );
1771  }
1772  else
1773  {
1775  m_renderer.color( colorstroke );
1776  m_renSolidComp.color( colorstroke );
1777  }
1778 
1779  if( m_blendMode == agg::end_of_comp_op_e )
1780  agg::render_scanlines( m_rasterizer, m_sl, m_renderer );
1781  else
1782  agg::render_scanlines( m_rasterizer, m_sl, m_renSolidComp );
1783 }
1784 
1785 void a2dAggDrawerRgba::RenderGradient( bool radial )
1786 {
1787  if ( !radial )
1788  {
1789  span_allocator_type aggallocator;
1790  LinearGradientSpan span( /*gr.m_allocator, */
1791  m_fillGradientInterpolator,
1792  m_linearGradientFunction,
1793  m_fillGradient,
1794  m_fillGradientD1,
1795  m_fillGradientD2 );
1796  RendererLinearGradientA ren( m_renBase, aggallocator, span );
1797  RendererLinearGradientComp renComp( m_renBaseComp, aggallocator, span );
1798 
1799  if( m_blendMode == agg::end_of_comp_op_e )
1800  agg::render_scanlines( m_rasterizer, m_sl, ren );
1801  else
1802  agg::render_scanlines( m_rasterizer, m_sl, renComp );
1803  }
1804  else
1805  {
1806  span_allocator_type aggallocator;
1807  RadialGradientSpan span( /*gr.m_allocator, */
1808  m_fillGradientInterpolator,
1809  m_radialGradientFunction,
1810  m_fillGradient,
1811  m_fillGradientD1,
1812  m_fillGradientD2 );
1813  RendererRadialGradientA ren( m_renBase, aggallocator, span );
1814  RendererRadialGradientComp renComp( m_renBaseComp, aggallocator, span );
1815 
1816  if( m_blendMode == agg::end_of_comp_op_e )
1817  agg::render_scanlines( m_rasterizer, m_sl, ren );
1818  else
1819  agg::render_scanlines( m_rasterizer, m_sl, renComp );
1820 
1821  }
1822 }
1823 
1824 void a2dAggDrawerRgba::RenderBitmapFill()
1825 {
1826  unsigned offset_x = 0;
1827  unsigned offset_y = 0;
1828 
1829  //typedef agg::wrap_mode_reflect_auto_pow2 wrap_x_type;
1830  //typedef agg::wrap_mode_reflect_auto_pow2 wrap_y_type;
1831  typedef agg::wrap_mode_repeat wrap_x_type;
1832  typedef agg::wrap_mode_repeat wrap_y_type;
1833 
1834  typedef agg::image_accessor_wrap<PixFormat, wrap_x_type, wrap_y_type> img_source_type;
1835  typedef agg::span_pattern_a2d<img_source_type> span_gen_type;
1836  typedef agg::span_allocator<color_type> span_alloc_type;
1837 
1838  typedef agg::renderer_scanline_aa<RendererBaseA, span_alloc_type, span_gen_type> renderer_type;
1839 
1840  PixFormat img_pixf( m_pattern_rbuf );
1841  img_source_type img_src( img_pixf );
1842  span_gen_type sg( img_src, offset_x, offset_y );
1843 
1844  sg.alpha( span_gen_type::value_type( m_FillOpacityCol1 ) );
1845 
1846  span_alloc_type sa;
1847  renderer_type rp( m_renBase, sa, sg );
1848 
1849  agg::render_scanlines( m_rasterizer, m_sl, rp );
1850 }
1851 
1852 void a2dAggDrawerRgba::RenderSetClip()
1853 {
1854  m_renBase.clip_box( m_clipboxdev.x, m_clipboxdev.y, m_clipboxdev.x + m_clipboxdev.width, m_clipboxdev.y + m_clipboxdev.height );
1855  m_renBaseComp.clip_box( m_clipboxdev.x, m_clipboxdev.y, m_clipboxdev.x + m_clipboxdev.width, m_clipboxdev.y + m_clipboxdev.height );
1856  m_rasterizer.clip_box( 0, 0, m_width, m_height );
1857 }
1858 
1860  m_rendering_buffer(),
1861  m_pixFormat( m_rendering_buffer ),
1862  m_pixFormatComp( m_rendering_buffer ),
1863  m_renBase( m_pixFormat ),
1864  m_renBaseComp( m_pixFormatComp ),
1865  m_renderer( m_renBase ),
1866  m_renSolidComp( m_renBaseComp ),
1867 
1868  a2dAggDrawerBase( size )
1869 {
1870  m_buffer = a2dImageRGBA( m_width, m_height );
1871  m_ownsBuffer = true;
1872  m_preStroke = false;//true;
1873 
1874  m_pdata = m_buffer.GetData();
1875  m_rendering_buffer.attach( m_pdata, m_width, m_height, m_width * 4 );
1877 }
1878 
1879 a2dAggDrawerRgba::a2dAggDrawerRgba( int width, int height ):
1880  m_rendering_buffer(),
1881  m_pixFormat( m_rendering_buffer ),
1882  m_pixFormatComp( m_rendering_buffer ),
1883  m_renBase( m_pixFormat ),
1884  m_renBaseComp( m_pixFormatComp ),
1885  m_renderer( m_renBase ),
1886  m_renSolidComp( m_renBaseComp ),
1887 
1888  a2dAggDrawerBase( width, height )
1889 {
1890  if ( width == 0 || height == 0 )
1891  m_buffer = a2dImageRGBA( 100, 100 );
1892  else
1893  m_buffer = a2dImageRGBA( width, height );
1894  m_ownsBuffer = true;
1895  m_pdata = m_buffer.GetData();
1896  m_rendering_buffer.attach( m_pdata, m_width, m_height, m_width * 4 );
1897  m_pixFormatComp.premultiply();
1899  m_preStroke = false;//true;
1900 }
1901 
1902 
1904  m_rendering_buffer(),
1905  m_pixFormat( m_rendering_buffer ),
1906  m_pixFormatComp( m_rendering_buffer ),
1907  m_renBase( m_pixFormat ),
1908  m_renBaseComp( m_pixFormatComp ),
1909  m_renderer( m_renBase ),
1910  m_renSolidComp( m_renBaseComp ),
1911 
1912  a2dAggDrawerBase( other )
1913 {
1914  m_ownsBuffer = false;
1915  m_width = other.m_width;
1916  m_height = other.m_height;
1917  m_buffer = other.m_buffer;
1918  m_preStroke = other.m_preStroke;
1919 }
1920 
1921 
1922 a2dAggDrawerRgba::a2dAggDrawerRgba( const wxBitmap& bitmap ):
1923  m_rendering_buffer(),
1924  m_pixFormat( m_rendering_buffer ),
1925  m_pixFormatComp( m_rendering_buffer ),
1926  m_renBase( m_pixFormat ),
1927  m_renBaseComp( m_pixFormatComp ),
1928  m_renderer( m_renBase ),
1929  m_renSolidComp( m_renBaseComp ),
1930 
1931  a2dAggDrawerBase( bitmap.GetWidth(), bitmap.GetHeight() )
1932 {
1933  wxImage image = bitmap.ConvertToImage();
1934  m_buffer = a2dImageRGBA( image );
1935  m_ownsBuffer = true;
1936  m_pdata = m_buffer.GetData();
1937  m_rendering_buffer.attach( m_pdata, m_width, m_height, m_width * 4 );
1939  m_preStroke = false;//true;
1940 }
1941 
1942 
1943 a2dAggDrawerRgba::~a2dAggDrawerRgba()
1944 {
1945 }
1946 
1948 {
1949  wxImage image = m_buffer.GetImage();
1950  return image;
1951 }
1952 
1954 {
1955  a2dImageRGBA newbuf( w, h );
1956 
1957  int old_pixelwidth = m_width * 4;
1958  int new_pixelwidth = w * 4;
1959  int pixelwidth = wxMin( w, m_width ) * 4;
1960  int minheight = wxMin( h, m_height );
1961 
1962  //pixel coordinates so ( 0,0 ) upper left
1963  unsigned char* oldpdata = m_pdata;
1964  unsigned char* newpdata = newbuf.GetData();
1965 
1966  for ( int yp = 0; yp < minheight; yp++ )
1967  {
1968  memcpy( newpdata, oldpdata, pixelwidth );
1969  oldpdata += old_pixelwidth;
1970  newpdata += new_pixelwidth;
1971  }
1972 
1973  m_width = w;
1974  m_height = h;
1975  m_buffer = newbuf;
1976 
1977  m_pdata = m_buffer.GetData();
1978  m_rendering_buffer.attach( m_pdata, m_width, m_height, m_width * 4 );
1979  m_pixFormatComp.premultiply();
1981 }
1982 
1984 {
1985  return wxBitmap( m_buffer.GetImage() );
1986 }
1987 
1988 wxBitmap a2dAggDrawerRgba::GetSubBitmap( wxRect rect ) const
1989 {
1990  return wxBitmap( m_buffer.GetImage().GetSubImage( rect ) );
1991 }
1992 
1993 void a2dAggDrawerRgba::CopyIntoBuffer( const wxBitmap& bitm )
1994 {
1995  m_buffer = a2dImageRGBA( bitm.ConvertToImage() );
1996 }
1997 
1998 void a2dAggDrawerRgba::DoSetDrawStyle( a2dDrawStyle drawstyle )
1999 {
2000  a2dAggDrawerBase::DoSetDrawStyle( drawstyle );
2001  m_pixFormatComp.comp_op( m_blendMode );
2002 }
2003 
2004 void a2dAggDrawerRgba::DrawImage( const wxImage& image, double x, double y, double width, double height, wxUint8 Opacity )
2005 {
2006  if ( m_disableDrawing )
2007  return;
2008  int imagew = image.GetWidth();
2009  int imageh = image.GetHeight();
2010 
2011  agg::trans_affine mtxi;
2012  mtxi *= agg::trans_affine_scaling( width / imagew, height / imageh );
2013  mtxi *= agg::trans_affine_translation( x - width / 2, y - height / 2 );
2014  // pictures always upwards
2015  //if ( m_yaxis )
2016  // mtxi *= agg::trans_affine_reflection_unit( 1, 0 );
2017 
2019  agg::trans_affine mtx(
2020  r2d.GetValue( 0, 0 ), r2d.GetValue( 0, 1 ),
2021  r2d.GetValue( 1, 0 ), r2d.GetValue( 1, 1 ),
2022  r2d.GetValue( 2, 0 ), r2d.GetValue( 2, 1 )
2023  );
2024  mtxi *= mtx;
2025  mtxi.invert();
2026 
2027  typedef agg::span_allocator<agg::rgba8> span_alloc_type;
2028 
2029  span_alloc_type sa;
2030  typedef agg::image_accessor_clip<PixFormat> img_source_type;
2031  typedef agg::span_interpolator_linear<> interpolator_type;
2032  interpolator_type interpolator( mtxi );
2033 
2034  typedef agg::span_image_filter_rgb_bilinear<img_source_type, interpolator_type> span_gen_type;
2035  //typedef agg::span_image_filter_rgb_nn<img_source_type, interpolator_type> span_gen_type;
2036 
2037  typedef agg::span_converter<span_gen_type, span_conv_const_alpha_rgba8> span_conv;
2038 
2039  agg::rendering_buffer image_buffer;
2040  image_buffer.attach( image.GetData(), imagew, imageh, ( m_yaxis ) ? -imagew * 3 : imagew * 3 );
2041  PixFormat img_pixf( image_buffer );
2042  img_source_type img_src( img_pixf, agg::rgba( 1, 1, 1, 0 ) );
2043 
2044  span_gen_type sg( img_src, interpolator );
2045 
2046  //now add the path to render, which should be the image bounding polygon/rotate rectangle.
2047  //But you could even make cuts from the image using ellipse etc.
2048  /*
2049  agg::rounded_rect er(0,0,m_width,m_height, 0);
2050  er.normalize_radius();
2051  m_rasterizer.add_path(er);
2052 
2053  agg::ellipse ellipse( x, y, width/2, height/2);
2054  agg::conv_transform<agg::ellipse> tr(ellipse, mtx);
2055  m_rasterizer.add_path( tr );
2056 
2057  agg::rounded_rect er(x-width/2, y-height/2 ,x+width/2, y+height/2, 0);
2058  er.normalize_radius();
2059  agg::conv_transform<agg::rounded_rect> tr(er, mtx);
2060  m_rasterizer.add_path(tr);
2061  */
2062  agg::rounded_rect er( x - width / 2, y - height / 2 , x + width / 2, y + height / 2, 0 );
2063  er.normalize_radius();
2064  agg::conv_transform<agg::rounded_rect> tr( er, mtx );
2065  m_rasterizer.reset();
2066  m_rasterizer.add_path( tr );
2067 
2068  wxUint8 OpacityFactor = ( m_OpacityFactor * Opacity ) / 255;
2069 
2070  //NOT m_FillOpacityCol1 since for images fill does not influence the picture.
2071  if ( 1 ) //OpacityFactor != 255 )
2072  {
2073  span_conv_const_alpha_rgba8 color_alpha( OpacityFactor );
2074  span_conv sc( sg, color_alpha );
2075  typedef agg::renderer_scanline_aa<RendererBaseA, span_alloc_type, span_conv> renderer_type_alpha;
2076  renderer_type_alpha ri( m_renBase, sa, sc );
2077 
2078  agg::render_scanlines( m_rasterizer, m_sl, ri );
2079  }
2080  else
2081  {
2082  typedef agg::renderer_scanline_bin<RendererBaseA, span_alloc_type, span_gen_type> renderer_type_normal;
2083  renderer_type_normal ri( m_renBase, sa, sg );
2084  agg::render_scanlines( m_rasterizer, m_sl, ri );
2085  }
2086 }
2087 
2088 void a2dAggDrawerRgba::DrawImage( const a2dImageRGBA& image, double x, double y, double width, double height, wxUint8 Opacity )
2089 {
2090  if ( m_disableDrawing )
2091  return;
2092 
2093  int imagew = image.GetWidth();
2094  int imageh = image.GetHeight();
2095 
2096  agg::trans_affine mtxi;
2097  mtxi *= agg::trans_affine_scaling( width / imagew, height / imageh );
2098  mtxi *= agg::trans_affine_translation( x, y );
2099 
2101  agg::trans_affine mtx(
2102  r2d.GetValue( 0, 0 ), r2d.GetValue( 0, 1 ),
2103  r2d.GetValue( 1, 0 ), r2d.GetValue( 1, 1 ),
2104  r2d.GetValue( 2, 0 ), r2d.GetValue( 2, 1 )
2105  );
2106  mtxi *= mtx;
2107  mtxi.invert();
2108 
2109  typedef agg::span_allocator<agg::rgba8> span_alloc_type;
2110  span_alloc_type sa;
2111  typedef agg::image_accessor_clip<agg::pixfmt_rgba32> img_source_type;
2112  typedef agg::span_interpolator_linear<> interpolator_type;
2113  interpolator_type interpolator( mtxi );
2114 
2115  typedef agg::span_image_filter_rgba_nn<img_source_type, interpolator_type> span_gen_type;
2116 
2117  typedef agg::span_converter<span_gen_type, span_conv_const_alpha_rgba8> span_conv;
2118 
2119  agg::rendering_buffer image_buffer;
2120  image_buffer.attach( image.GetData(), imagew, imageh, imagew * 4 );
2121  agg::pixfmt_rgba32 img_pixf( image_buffer );
2122  img_source_type img_src( img_pixf, agg::rgba( 0, 0, 0, 0 ) );
2123 
2124  span_gen_type sg( img_src, interpolator );
2125 
2126 
2127  agg::rounded_rect er( x, y , x + width, y + height, 1 );
2128  er.normalize_radius();
2129  agg::conv_transform<agg::rounded_rect> tr( er, mtx );
2130  m_rasterizer.reset();
2131  m_rasterizer.add_path( tr );
2132 
2133  wxUint8 OpacityFactor = ( m_OpacityFactor * Opacity ) / 255;
2134 
2135  //NOT m_FillOpacityCol1 since for images fill does not influence the picture.
2136  if ( OpacityFactor != 255 )
2137  {
2138  span_conv_const_alpha_rgba8 color_alpha( OpacityFactor );
2139  span_conv sc( sg, color_alpha );
2140  typedef agg::renderer_scanline_aa<RendererBaseA, span_alloc_type, span_conv> renderer_type_alpha;
2141  renderer_type_alpha ri( m_renBase, sa, sc );
2142 
2143  agg::render_scanlines( m_rasterizer, m_sl, ri );
2144  }
2145  else
2146  {
2147  typedef agg::renderer_scanline_bin<RendererBaseA, span_alloc_type, span_gen_type> renderer_type_normal;
2148  renderer_type_normal ri( m_renBase, sa, sg );
2149  agg::render_scanlines( m_rasterizer, m_sl, ri );
2150  }
2151 }
2152 
2153 void a2dAggDrawerRgba::BlitBuffer( wxDC* dc, wxRect rect, const wxPoint& bufferpos )
2154 {
2155  // clip to buffer
2156  if ( rect.x < 0 )
2157  {
2158  rect.width += rect.x;
2159  rect.x = 0;
2160  }
2161  if ( rect.width <= 0 ) return;
2162 
2163  if ( rect.y < 0 )
2164  {
2165  rect.height += rect.y;
2166  rect.y = 0;
2167  }
2168  if ( rect.height <= 0 ) return;
2169 
2170  if ( rect.x + rect.width >= m_width )
2171  rect.width = m_width - rect.x;
2172 
2173  if ( rect.width <= 0 ) return;
2174 
2175  if ( rect.y + rect.height >= m_height )
2176  rect.height = m_height - rect.y;
2177 
2178  if ( rect.height <= 0 ) return;
2179 
2180  int xmax = rect.x + rect.width;
2181  int ymax = rect.y + rect.height;
2182 
2183  a2dImageRGBA* subImage = m_buffer.GetSubImage( rect );
2184  wxBitmap subbitmap = subImage->CreateBitmap();
2185  delete subImage;
2186 
2187  wxMemoryDC mdc;
2188  mdc.SelectObject( subbitmap );
2189 
2190  dc->Blit( rect.x - bufferpos.x, rect.y - bufferpos.y, xmax - rect.x, ymax - rect.y, &mdc, 0, 0, wxCOPY, false );
2191 
2192  mdc.SelectObject( wxNullBitmap );
2193 }
2194 
2195 void a2dAggDrawerRgba::ShiftBuffer( int dxy, bool yshift )
2196 {
2197  ShiftBufferInternal( dxy, yshift, 4 );
2198 }
2199 
2200 /*******************************************************************
2201 a2dAggDrawer
2202 ********************************************************************/
2203 
2204 void a2dAggDrawer::DeviceDrawPixel( int x1, int y1, unsigned char r, unsigned char g, unsigned char b , unsigned char a )
2205 {
2207  m_renBase.blend_pixel( x1, y1, colorfill, 255 );
2208 }
2209 
2210 void a2dAggDrawer::Render( bool fillColor )
2211 {
2212  if ( fillColor )
2213  {
2215  m_renderer.color( colorfill );
2216  }
2217  else
2218  {
2220  m_renderer.color( colorstroke );
2221  }
2222  agg::render_scanlines( m_rasterizer, m_sl, m_renderer );
2223 }
2224 
2225 void a2dAggDrawer::RenderGradient( bool radial )
2226 {
2227  if ( !radial )
2228  {
2229  span_allocator_type aggallocator;
2230  LinearGradientSpan span( /*gr.m_allocator, */
2231  m_fillGradientInterpolator,
2232  m_linearGradientFunction,
2233  m_fillGradient,
2234  m_fillGradientD1,
2235  m_fillGradientD2 );
2236  RendererLinearGradient ren( m_renBase, aggallocator, span );
2237  agg::render_scanlines( m_rasterizer, m_sl, ren );
2238  }
2239  else
2240  {
2241  span_allocator_type aggallocator;
2242  RadialGradientSpan span( /*gr.m_allocator, */
2243  m_fillGradientInterpolator,
2244  m_radialGradientFunction,
2245  m_fillGradient,
2246  m_fillGradientD1,
2247  m_fillGradientD2 );
2248  RendererRadialGradient ren( m_renBase, aggallocator, span );
2249  agg::render_scanlines( m_rasterizer, m_sl, ren );
2250  }
2251 }
2252 
2253 void a2dAggDrawer::RenderBitmapFill()
2254 {
2255  unsigned offset_x = 0;
2256  unsigned offset_y = 0;
2257 
2258  //typedef agg::wrap_mode_reflect_auto_pow2 wrap_x_type;
2259  //typedef agg::wrap_mode_reflect_auto_pow2 wrap_y_type;
2260  typedef agg::wrap_mode_repeat wrap_x_type;
2261  typedef agg::wrap_mode_repeat wrap_y_type;
2262 
2263  typedef agg::image_accessor_wrap<PixFormat, wrap_x_type, wrap_y_type> img_source_type;
2264  typedef agg::span_pattern_a2d<img_source_type> span_gen_type;
2265  typedef agg::span_allocator<color_type> span_alloc_type;
2266 
2267  typedef agg::renderer_scanline_aa<RendererBase, span_alloc_type, span_gen_type> renderer_type;
2268 
2269  PixFormat img_pixf( m_pattern_rbuf );
2270  img_source_type img_src( img_pixf );
2271  span_gen_type sg( img_src, offset_x, offset_y );
2272 
2273  sg.alpha( span_gen_type::value_type( m_FillOpacityCol1 ) );
2274 
2275  span_alloc_type sa;
2276  renderer_type rp( m_renBase, sa, sg );
2277 
2278  agg::render_scanlines( m_rasterizer, m_sl, rp );
2279 }
2280 
2281 void a2dAggDrawer::RenderSetClip()
2282 {
2283  m_renBase.clip_box( m_clipboxdev.x, m_clipboxdev.y, m_clipboxdev.x + m_clipboxdev.width, m_clipboxdev.y + m_clipboxdev.height );
2284  m_rasterizer.clip_box( 0, 0, m_width, m_height );
2285 }
2286 
2287 IMPLEMENT_DYNAMIC_CLASS( a2dAggDrawer, a2dAggDrawerBase )
2288 
2289 a2dAggDrawer::a2dAggDrawer( const wxSize& size ):
2290  m_rendering_buffer(),
2291  m_pixFormat( m_rendering_buffer ),
2292  m_renBase( m_pixFormat ),
2293  m_renderer( m_renBase ),
2294 
2295  a2dAggDrawerBase( size )
2296 {
2297  m_buffer = wxImage( m_width, m_height );
2298 
2299  m_pdata = m_buffer.GetData();
2300  m_rendering_buffer.attach( m_pdata, m_width, m_height, m_width * 3 );
2301  DestroyClippingRegion();
2302  m_preStroke = false;//true;
2303 }
2304 
2305 a2dAggDrawer::a2dAggDrawer( int width, int height ):
2306  m_rendering_buffer(),
2307  m_pixFormat( m_rendering_buffer ),
2308  m_renBase( m_pixFormat ),
2309  m_renderer( m_renBase ),
2310 
2311  a2dAggDrawerBase( width, height )
2312 {
2313  if ( width == 0 || height == 0 )
2314  m_buffer = wxImage( 100, 100 );
2315  else
2316  m_buffer = wxImage( width, height );
2317 
2318  m_pdata = m_buffer.GetData();
2319  m_rendering_buffer.attach( m_pdata, m_width, m_height, m_width * 3 );
2321  m_preStroke = false;//true;
2322 }
2323 
2325  m_rendering_buffer(),
2326  m_pixFormat( m_rendering_buffer ),
2327  m_renBase( m_pixFormat ),
2328  m_renderer( m_renBase ),
2329 
2330  a2dAggDrawerBase( other )
2331 {
2332  m_width = other.m_width;
2333  m_height = other.m_height;
2334  m_buffer = other.m_buffer;
2335  m_preStroke = other.m_preStroke;
2336 }
2337 
2338 a2dAggDrawer::a2dAggDrawer( const wxBitmap& bitmap ):
2339  m_rendering_buffer(),
2340  m_pixFormat( m_rendering_buffer ),
2341  m_renBase( m_pixFormat ),
2342  m_renderer( m_renBase ),
2343 
2344  a2dAggDrawerBase( bitmap.GetWidth(), bitmap.GetHeight() )
2345 {
2346  m_buffer = bitmap.ConvertToImage();
2347  m_pdata = m_buffer.GetData();
2348  m_rendering_buffer.attach( m_pdata, m_width, m_height, m_width * 3 );
2350  m_preStroke = false;//true;
2351 }
2352 
2353 a2dAggDrawer::~a2dAggDrawer()
2354 {
2355 }
2356 
2357 void a2dAggDrawer::SetBufferSize( int w, int h )
2358 {
2359  wxImage newbuf = wxImage( w, h );
2360 
2361  int old_pixelwidth = m_width * 3;
2362  int new_pixelwidth = w * 3;
2363  int pixelwidth = wxMin( w, m_width ) * 3;
2364  int minheight = wxMin( h, m_height );
2365 
2366  //pixel coordinates so ( 0,0 ) upper left
2367  unsigned char* oldpdata = m_pdata;
2368  unsigned char* newpdata = newbuf.GetData();
2369 
2370  for ( int yp = 0; yp < minheight; yp++ )
2371  {
2372  memcpy( newpdata, oldpdata, pixelwidth );
2373  oldpdata += old_pixelwidth;
2374  newpdata += new_pixelwidth;
2375  }
2376 
2377  m_width = w;
2378  m_height = h;
2379  m_buffer = newbuf;
2380 
2381  m_pdata = m_buffer.GetData();
2382  m_rendering_buffer.attach( m_pdata, m_width, m_height, m_width * 3 );
2383  /*
2384  agg::renderer_rgb24_util utl( *m_rendering_buffer );
2385 
2386  unsigned char colour1red = m_backgroundfill->GetColour().Red();
2387  unsigned char colour1green = m_backgroundfill->GetColour().Green();
2388  unsigned char colour1blue = m_backgroundfill->GetColour().Blue();
2389 
2390  agg::rgba8 color( colour1red, colour1green, colour1blue, m_backgroundfill->m_FillOpacityCol1 );
2391  utl.clear( color );
2392  */
2393 }
2394 
2395 wxBitmap a2dAggDrawer::GetBuffer() const
2396 {
2397  return wxBitmap( m_buffer );
2398 }
2399 
2400 wxBitmap a2dAggDrawer::GetSubBitmap( wxRect rect ) const
2401 {
2402  return wxBitmap( m_buffer.GetSubImage( rect ) );
2403 }
2404 
2405 void a2dAggDrawer::CopyIntoBuffer( const wxBitmap& bitm )
2406 {
2407  m_buffer = bitm.ConvertToImage();
2408  m_pdata = m_buffer.GetData();
2409  m_rendering_buffer.attach( m_pdata, m_width, m_height, m_width * 3 );
2411 }
2412 
2413 void a2dAggDrawer::DrawImage( const wxImage& image, double x, double y, double width, double height, wxUint8 Opacity )
2414 {
2415  if ( m_disableDrawing )
2416  return;
2417  int imagew = image.GetWidth();
2418  int imageh = image.GetHeight();
2419 
2420  agg::trans_affine mtxi;
2421  mtxi *= agg::trans_affine_scaling( width / imagew, height / imageh );
2422  mtxi *= agg::trans_affine_translation( x - width / 2, y - height / 2 );
2423  // pictures always upwards
2424  //if ( m_yaxis )
2425  // mtxi *= agg::trans_affine_reflection_unit( 1, 0 );
2426 
2428  agg::trans_affine mtx(
2429  r2d.GetValue( 0, 0 ), r2d.GetValue( 0, 1 ),
2430  r2d.GetValue( 1, 0 ), r2d.GetValue( 1, 1 ),
2431  r2d.GetValue( 2, 0 ), r2d.GetValue( 2, 1 )
2432  );
2433  mtxi *= mtx;
2434  mtxi.invert();
2435 
2436  typedef agg::span_allocator<agg::rgba8> span_alloc_type;
2437 
2438  span_alloc_type sa;
2439  typedef agg::image_accessor_clip<PixFormat> img_source_type;
2440  typedef agg::span_interpolator_linear<> interpolator_type;
2441  interpolator_type interpolator( mtxi );
2442 
2443  typedef agg::span_image_filter_rgb_bilinear<img_source_type, interpolator_type> span_gen_type;
2444  //typedef agg::span_image_filter_rgb_nn<img_source_type, interpolator_type> span_gen_type;
2445 
2446  typedef agg::span_converter<span_gen_type, span_conv_const_alpha_rgba8> span_conv;
2447 
2448  typedef agg::renderer_scanline_aa<RendererBase, span_alloc_type, span_conv> renderer_type_alpha;
2449 
2450  typedef agg::renderer_scanline_bin<RendererBase, span_alloc_type, span_gen_type> renderer_type_normal;
2451 
2452  agg::rendering_buffer image_buffer;
2453  image_buffer.attach( image.GetData(), imagew, imageh, ( m_yaxis ) ? -imagew * 3 : imagew * 3 );
2454  PixFormat img_pixf( image_buffer );
2455  img_source_type img_src( img_pixf, agg::rgba( 1, 1, 1, 0 ) );
2456 
2457  span_gen_type sg( img_src, interpolator );
2458 
2459  //now add the path to render, which should be the image bounding polygon/rotate rectangle.
2460  //But you could even make cuts from the image using ellipse etc.
2461  /*
2462  agg::rounded_rect er(0,0,m_width,m_height, 0);
2463  er.normalize_radius();
2464  m_rasterizer.add_path(er);
2465 
2466  agg::ellipse ellipse( x, y, width/2, height/2);
2467  agg::conv_transform<agg::ellipse> tr(ellipse, mtx);
2468  m_rasterizer.add_path( tr );
2469 
2470  agg::rounded_rect er(x-width/2, y-height/2 ,x+width/2, y+height/2, 0);
2471  er.normalize_radius();
2472  agg::conv_transform<agg::rounded_rect> tr(er, mtx);
2473  m_rasterizer.add_path(tr);
2474  */
2475  agg::rounded_rect er( x - width / 2, y - height / 2 , x + width / 2, y + height / 2, 0 );
2476  er.normalize_radius();
2477  agg::conv_transform<agg::rounded_rect> tr( er, mtx );
2478  m_rasterizer.reset();
2479  m_rasterizer.add_path( tr );
2480 
2481  wxUint8 OpacityFactor = ( m_OpacityFactor * Opacity ) / 255;
2482 
2483  //NOT m_FillOpacityCol1 since for images fill does not influence the picture.
2484  if ( image.HasAlpha() || OpacityFactor != 255 )
2485  {
2486  span_conv_const_alpha_rgba8 color_alpha( OpacityFactor );
2487  //span_conv_array_alpha_rgba8 color_alpha_array( image, OpacityFactor );
2488  span_conv sc( sg, color_alpha );
2489  renderer_type_alpha ri( m_renBase, sa, sc );
2490 
2491  agg::render_scanlines( m_rasterizer, m_sl, ri );
2492  }
2493  else
2494  {
2495  renderer_type_normal ri( m_renBase, sa, sg );
2496  agg::render_scanlines( m_rasterizer, m_sl, ri );
2497  }
2498 }
2499 
2500 void a2dAggDrawer::DrawImage( const a2dImageRGBA& image, double x, double y, double width, double height, wxUint8 Opacity )
2501 {
2502  if ( m_disableDrawing )
2503  return;
2504 
2505  int imagew = image.GetWidth();
2506  int imageh = image.GetHeight();
2507 
2508  agg::trans_affine mtxi;
2509  mtxi *= agg::trans_affine_scaling( width / imagew, height / imageh );
2510  mtxi *= agg::trans_affine_translation( x, y );
2511 
2513  agg::trans_affine mtx(
2514  r2d.GetValue( 0, 0 ), r2d.GetValue( 0, 1 ),
2515  r2d.GetValue( 1, 0 ), r2d.GetValue( 1, 1 ),
2516  r2d.GetValue( 2, 0 ), r2d.GetValue( 2, 1 )
2517  );
2518  mtxi *= mtx;
2519  mtxi.invert();
2520 
2521  typedef agg::span_allocator<agg::rgba8> span_alloc_type;
2522  span_alloc_type sa;
2523  typedef agg::image_accessor_clip<agg::pixfmt_rgba32> img_source_type;
2524  typedef agg::span_interpolator_linear<> interpolator_type;
2525  interpolator_type interpolator( mtxi );
2526 
2527  typedef agg::span_image_filter_rgba_nn<img_source_type, interpolator_type> span_gen_type;
2528 
2529  typedef agg::span_converter<span_gen_type, span_conv_const_alpha_rgba8> span_conv;
2530 
2531  typedef agg::renderer_scanline_aa<RendererBase, span_alloc_type, span_conv> renderer_type_alpha;
2532 
2533  typedef agg::renderer_scanline_bin<RendererBase, span_alloc_type, span_gen_type> renderer_type_normal;
2534 
2535  agg::rendering_buffer image_buffer;
2536  image_buffer.attach( image.GetData(), imagew, imageh, imagew * 4 );
2537  agg::pixfmt_rgba32 img_pixf( image_buffer );
2538  img_source_type img_src( img_pixf, agg::rgba( 0, 0, 0, 0 ) );
2539 
2540  span_gen_type sg( img_src, interpolator );
2541 
2542 
2543  agg::rounded_rect er( x, y , x + width, y + height, 1 );
2544  er.normalize_radius();
2545  agg::conv_transform<agg::rounded_rect> tr( er, mtx );
2546  m_rasterizer.reset();
2547  m_rasterizer.add_path( tr );
2548 
2549  wxUint8 OpacityFactor = ( m_OpacityFactor * Opacity ) / 255;
2550 
2551  //NOT m_FillOpacityCol1 since for images fill does not influence the picture.
2552  if ( OpacityFactor != 255 )
2553  {
2554  span_conv_const_alpha_rgba8 color_alpha( OpacityFactor );
2555  span_conv sc( sg, color_alpha );
2556  renderer_type_alpha ri( m_renBase, sa, sc );
2557 
2558  agg::render_scanlines( m_rasterizer, m_sl, ri );
2559  }
2560  else
2561  {
2562  renderer_type_normal ri( m_renBase, sa, sg );
2563  agg::render_scanlines( m_rasterizer, m_sl, ri );
2564  }
2565 }
2566 
2567 void a2dAggDrawer::BlitBuffer( wxDC* dc, wxRect rect, const wxPoint& bufferpos )
2568 {
2569  // clip to buffer
2570  if ( rect.x < 0 )
2571  {
2572  rect.width += rect.x;
2573  rect.x = 0;
2574  }
2575  if ( rect.width <= 0 ) return;
2576 
2577  if ( rect.y < 0 )
2578  {
2579  rect.height += rect.y;
2580  rect.y = 0;
2581  }
2582  if ( rect.height <= 0 ) return;
2583 
2584  if ( rect.x + rect.width >= m_width )
2585  rect.width = m_width - rect.x;
2586 
2587  if ( rect.width <= 0 ) return;
2588 
2589  if ( rect.y + rect.height >= m_height )
2590  rect.height = m_height - rect.y;
2591 
2592  if ( rect.height <= 0 ) return;
2593 
2594  int xmax = rect.x + rect.width;
2595  int ymax = rect.y + rect.height;
2596 
2597  wxBitmap subbitmap = m_buffer.GetSubImage( rect );
2598  wxMemoryDC mdc;
2599  mdc.SelectObject( subbitmap );
2600 
2601  dc->Blit( rect.x - bufferpos.x, rect.y - bufferpos.y, xmax - rect.x, ymax - rect.y, &mdc, 0, 0, wxCOPY, false );
2602 
2603  mdc.SelectObject( wxNullBitmap );
2604 }
2605 
2606 void a2dAggDrawer::ShiftBuffer( int dxy, bool yshift )
2607 {
2608  ShiftBufferInternal( dxy, yshift, 3 );
2609 }
2610 
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
a2dDrawStyle m_drawstyle
drawstyle (like invert mode)
Definition: drawer2d.h:1015
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
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
wxImage GetImageBuffer() const
return wxImage which is used as buffer here
Definition: aggdrawer.cpp:1947
void ShiftBuffer(int dxy, bool yshift)
quick scroll over small distance
Definition: aggdrawer.cpp:2195
a2dFill m_activefill
used while rendering
Definition: drawer2d.h:1009
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
virtual void DrawPolygon(a2dVertexArray *points, bool spline=false, wxPolygonFillMode fillStyle=wxODDEVEN_RULE)
Draw polygon in world coordinates using pointarray.
Definition: aggdrawer.cpp:1315
const a2dStroke * a2dBLACK_STROKE
global a2dStroke stock object for BLACK stroking
Stroke and fill base classes.
a2dPoint2D GetStop() const
Get stop for gradient fill colour change.
Definition: stylebase.cpp:4733
unsigned char m_colour2blueFill
active fill colours
Definition: drawer2d.h:1128
a2dStroke m_currentstroke
used while rendering
Definition: drawer2d.h:1000
a2dDrawStyle m_fixDrawstyle
used to restore an overruled fix style
Definition: drawer2d.h:1024
const a2dFill * a2dBLACK_FILL
global a2dFill stock object for BLACK filling
bool IsStrokeOnly()
wxART2D_USE_GRAPHICS_CONTEXT
Definition: drawer2d.h:847
std::vector< wxRealPoint > m_cpointsDouble
cached array for containing transformed device coordinates (double)
Definition: drawer2d.h:1175
double DeviceToWorldYRel(double y) const
convert y relative from device to world coordinates
Definition: drawer2d.h:449
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 GetRadius() const
Get stop for gradient fill colour change.
Definition: stylebase.cpp:4765
bool GetPixelStroke() const
if the width is pixels or not.
Definition: stylebase.cpp:6335
virtual void DrawCharDc(wxChar c)
Draw a dc character.
Definition: aggdrawer.cpp:1169
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
void ShiftBuffer(int dxy, bool yshift)
quick scroll over small distance
Definition: aggdrawer.cpp:2606
a2dFont m_currentfont
current font set
Definition: drawer2d.h:1012
a2dBoundingBox m_clipboxworld
current clipping area in world coordinates
Definition: drawer2d.h:1196
virtual void DrawCharFreetype(wxChar c)
Draw a freetype character.
Definition: aggdrawer.cpp:1517
void DeviceDrawPixel(int x1, int y1, unsigned char r, unsigned char g, unsigned char b, unsigned char a)
draw a single, unstroked pixel in device coordinates with the given color
Definition: aggdrawer.cpp:2204
a2dVertexList * ConvertSplinedPolyline(double Aber) const
Spline conversion for polyline.
Definition: polyver.cpp:2858
Arc Segment in a2dVertexList.
Definition: polyver.h:371
vertex array of line and arc segments.
Definition: polyver.h:494
unsigned char m_colour1blueStroke
active stroke colours
Definition: drawer2d.h:1114
virtual void BeginDraw()
start to draw on this context (used to initialize a specific drawer)
Definition: aggdrawer.cpp:173
unsigned char m_colour2redFill
active fill colours
Definition: drawer2d.h:1124
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
a2dStrokeGlyph GetGlyphStroke(wxChar c) const
Get the glyph of a single character.
Definition: stylebase.cpp:2944
virtual void EndDraw()
end drawing on this context (used to reset a specific drawer)
Definition: aggdrawer.cpp:191
double TransformDistance(double distance) const
Transform a distance.
Definition: afmatrix.cpp:616
virtual void SetActiveFill(const a2dFill &fill)
sync with actual API graphical context
Definition: drawer2d.cpp:633
wxBitmap GetBuffer() const
get buffer as bitmap pointer
Definition: aggdrawer.cpp:1983
a2dVertexList * ConvertSplinedPolygon(double Aber) const
Spline conversion for polygon.
Definition: polyver.cpp:2846
a2dDrawStyle
Define the manner in which a2dCanvasView draws to the device.
Definition: artglob.h:280
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 SetBufferSize(int w, int h)
set buffer size to w pixel wide and h pixels heigh
Definition: aggdrawer.cpp:2357
a2dVertexArray * ConvertSplinedPolyline(double Aber) const
Spline conversion for polyline.
Definition: polyver.cpp:1221
a2dClipRegionList m_clipregionlist
pushed clipping regions
Definition: drawer2d.h:1181
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
virtual void DrawRoundedRectangle(double x, double y, double width, double height, double radius, bool pixelsize=false)
Draw RoundedRectangle in world coordinates.
Definition: aggdrawer.cpp:1186
a2dAffineMatrix m_worldtodevice
world to device coordinate mapping
Definition: drawer2d.h:1133
double m_displayaberration
accuracy of arc segment calculation etc. in device coordinates
Definition: drawer2d.h:1184
#define forEachIn(listtype, list)
easy iteration for a2dlist
Definition: a2dlist.h:111
virtual void DrawCharDc(wxChar c)
Draw a dc character.
Definition: drawer2d.h:981
the antigrain based drawing context derived from a2dDrawer2D
unsigned char m_colour1greenStroke
active stroke colours
Definition: drawer2d.h:1112
void DrawImage(const wxImage &image, double x, double y, double width, double height, wxUint8 Opacity=255)
Draw wxImage in world coordinates.
Definition: aggdrawer.cpp:2004
void SetBufferSize(int w, int h)
set buffer size to w pixel wide and h pixels heigh
Definition: aggdrawer.cpp:1953
wxBitmap GetBuffer() const
get buffer as bitmap pointer
Definition: aggdrawer.cpp:2395
a2dPoint2D GetStart() const
Get start for gradient fill colour change.
Definition: stylebase.cpp:4727
a2dPoint2D GetCenter() const
Get start for gradient fill colour change.
Definition: stylebase.cpp:4753
bool IsStroked()
Definition: drawer2d.h:860
the antigrain based drawing context derived from a2dDrawer2D
Definition: aggdrawer.h:674
Drawing context abstraction.
Definition: drawer2d.h:177
Normal straight line segment in a2dVertexList and a2dVertexArray.
Definition: polyver.h:163
unsigned char m_colour2greenFill
active fill colours
Definition: drawer2d.h:1126
int WorldToDeviceX(double x) const
convert x from world to device coordinates
Definition: drawer2d.h:453
virtual void DrawLines(a2dVertexArray *points, bool spline=false)
Draw polyline in world coordinates using pointarray.
Definition: aggdrawer.cpp:1493
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: aggdrawer.cpp:590
void DoSetActiveStroke()
per drawer implementation
Definition: aggdrawer.cpp:262
virtual void DrawPolyPolygon(a2dListOfa2dVertexList polylist, wxPolygonFillMode fillStyle=wxODDEVEN_RULE)
draw a list of polygons ( contour clockwise becomes hole )
Definition: aggdrawer.cpp:1458
a2dPoint2D GetFocal() const
Get start for gradient fill colour change.
Definition: stylebase.cpp:4759
bool m_yaxis
up or down
Definition: drawer2d.h:1027
void SetClippingRegion(a2dVertexList *points, bool spline=false, wxPolygonFillMode fillStyle=wxODDEVEN_RULE)
set clipping region from polygon to which everything drawn will be clipped.
Definition: aggdrawer.cpp:547
the antigrain based drawing context derived from a2dDrawer2D
Definition: aggdrawer.h:601
void SetClippingRegionDev(wxCoord minx, wxCoord miny, wxCoord width, wxCoord height)
set clipping region using x y values in device coordinates
Definition: aggdrawer.cpp:691
A 2x3 affine matrix class for 2D transformations.
Definition: afmatrix.h:53
agg::rgba8 color_type
color format in a2dAggDrawer
Definition: aggdrawer.h:112
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
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
a2dAggDrawerRgba(int width=0, int height=0)
Drawer having a buffer of w pixel wide and h pixels heigh.
Definition: aggdrawer.cpp:1879
void DrawImage(const wxImage &image, double x, double y, double width, double height, wxUint8 Opacity=255)
Draw wxImage in world coordinates.
Definition: aggdrawer.cpp:2413
double m_x
x endpoint of line
Definition: polyver.h:232
void DestroyClippingRegion()
set clipping region off
Definition: aggdrawer.cpp:725
a2dAggDrawer(int width=0, int height=0)
Drawer having a buffer of w pixel wide and h pixels heigh.
Definition: aggdrawer.cpp:2305
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
virtual void DrawCharFreetype(wxChar c)
Draw a freetype character.
Definition: drawer2d.h:966
double m_y
y endpoint of line
Definition: polyver.h:235
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
int m_beginDraw_endDraw
counter for BeginDraw EndDraw calls
Definition: drawer2d.h:1202
wxBitmap GetSubBitmap(wxRect sub_rect) const
get part of the buffer given a rect
Definition: aggdrawer.cpp:1988
int m_width
device size width
Definition: drawer2d.h:1148
void DrawPoint(double xc, double yc)
draw a single point
Definition: aggdrawer.cpp:1160
unsigned char m_colour1greenFill
active fill colours
Definition: drawer2d.h:1119
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: aggdrawer.cpp:580
void DoSetActiveFill()
per drawer implementation
Definition: aggdrawer.cpp:363
unsigned char m_colour1redStroke
active stroke colours
Definition: drawer2d.h:1110
void BlitBuffer()
blit whole buffer to device
Definition: drawer2d.cpp:183
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
wxWindow * m_display
view its window.
Definition: drawer2d.h:1205
wxUint8 m_FillOpacityCol1
active fill alpha
Definition: drawer2d.h:1105
bool Invert(void)
Invert matrix.
Definition: afmatrix.cpp:197
void PopClippingRegion()
pop a previously pushed clipping region
Definition: aggdrawer.cpp:678
float GetWidth() const
Definition: stylebase.cpp:6281
#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: aggdrawer.cpp:1152
virtual void DrawEllipse(double x, double y, double width, double height)
Draw Ellipse in world coordinates.
Definition: aggdrawer.cpp:1264
virtual void DrawCharStroke(wxChar c)
Draw a stroke character.
Definition: aggdrawer.cpp:1708
void ResetStyle()
set a pre-defined style reseting cashed values.
Definition: aggdrawer.cpp:150
a2dFill m_currentfill
used while rendering
Definition: drawer2d.h:1003
const a2dAffineMatrix & GetMappingMatrix()
get the world-to-device (aka mapping) matrix
Definition: drawer2d.h:478
wxUint8 m_OpacityFactor
opacity will be the one set, derived by this
Definition: drawer2d.h:1211
wxBitmap GetSubBitmap(wxRect sub_rect) const
get part of the buffer given a rect
Definition: aggdrawer.cpp:2400
double DeviceToWorldXRel(double x) const
convert x relative from device to world coordinates
Definition: drawer2d.h:444
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
const double wxPI
defines PI
Definition: artglob.cpp:28
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
aggdrawer.cpp Source File -- Sun Oct 12 2014 17:04:12 -- Sun Oct 12 2014 -- 1.8.5 -- wxArt2D -- . -- Main Page Reference Documentation