24 #include "wx/window.h"
27 #include "wx/dialog.h"
29 #include "wx/bitmap.h"
30 #include "wx/dcmemory.h"
33 #include "wx/dcprint.h"
34 #include "wx/module.h"
41 #include "wx/graphics.h"
42 #include "wx/rawbmp.h"
45 #include "wx/msw/dcclient.h"
46 #include "wx/msw/dcmemory.h"
47 #include "wx/msw/dcscreen.h"
51 #include "wx/gtk/dc.h"
52 #elif defined __WXGTK20__
53 #include "wx/gtk/dcclient.h"
54 #elif defined(__WXGTK__)
55 #include "wx/gtk1/dcclient.h"
56 #include "wx/gtk1/dcmemory.h"
57 #include "wx/gtk1/dcscreen.h"
61 #include "wx/osx/dcclient.h"
62 #include "wx/osx/dcmemory.h"
63 #include "wx/osx/dcscreen.h"
67 #include "wx/os2/dcclient.h"
68 #include "wx/os2/dcmemory.h"
69 #include "wx/os2/dcscreen.h"
73 #include "wx/cocoa/dcclient.h"
74 #include "wx/cocoa/dcmemory.h"
75 #include "wx/cocoa/dcscreen.h"
79 #include "wx/motif/dcclient.h"
80 #include "wx/motif/dcmemory.h"
81 #include "wx/motif/dcscreen.h"
85 #include "wx/x11/dcclient.h"
86 #include "wx/x11/dcmemory.h"
87 #include "wx/x11/dcscreen.h"
91 #include "wx/dfb/dcclient.h"
92 #include "wx/dfb/dcmemory.h"
93 #include "wx/dfb/dcscreen.h"
96 #if defined(__WXMSW__)
97 #include <wx/msw/private.h>
98 #elif defined(__WXGTK__)
102 #if wxART2D_USE_FREETYPE
103 #include <ft2build.h>
107 #include <freetype/freetype.h>
108 #include <freetype/ftoutln.h>
111 #include FT_FREETYPE_H
112 #include FT_OUTLINE_H
116 #if wxART2D_USE_GRAPHICS_CONTEXT
126 const double RAD2DEG = 180.0 / M_PI;
132 static inline double dmin(
double a,
double b )
134 return a < b ? a : b;
136 static inline double dmax(
double a,
double b )
138 return a > b ? a : b;
141 static inline double DegToRad(
double deg )
143 return ( deg * M_PI ) / 180.0;
145 static inline double RadToDeg(
double deg )
147 return ( deg * 180.0 ) / M_PI;
158 #define max(a,b) (((a) > (b)) ? (a) : (b))
162 #define min(a,b) (((a) < (b)) ? (a) : (b))
170 a2dStrokeData::~a2dStrokeData()
174 void a2dStrokeData::Init()
178 a2dStrokeData::a2dStrokeData( wxGraphicsRenderer* renderer,
const wxPen& pen )
179 : wxGraphicsObjectRefData( renderer )
185 a2dStrokeData::a2dStrokeData( wxGraphicsRenderer* renderer,
const a2dStroke& stroke )
186 : wxGraphicsObjectRefData( renderer )
192 void a2dStrokeData::Apply( wxGraphicsContext* context )
194 a2dContext* ctext = ( a2dContext* ) context->GetNativeContext();
195 ctext->SetStroke( m_stroke );
202 a2dFillData::a2dFillData( wxGraphicsRenderer* renderer )
203 : wxGraphicsObjectRefData( renderer )
208 a2dFillData::a2dFillData( wxGraphicsRenderer* renderer,
const wxBrush& brush )
209 : wxGraphicsObjectRefData( renderer )
215 a2dFillData::a2dFillData( wxGraphicsRenderer* renderer,
const a2dFill& fill )
216 : wxGraphicsObjectRefData( renderer )
222 a2dFillData::~a2dFillData ()
226 void a2dFillData::Apply( wxGraphicsContext* context )
228 a2dContext* ctext = ( a2dContext* ) context->GetNativeContext();
229 ctext->SetFill( m_fill );
232 #if wxCHECK_VERSION(2, 9, 1)
233 void a2dFillData::CreateLinearGradientBrush( wxDouble x1, wxDouble y1, wxDouble x2, wxDouble y2,
234 const wxGraphicsGradientStops& stops )
240 void a2dFillData::CreateRadialGradientBrush( wxDouble xo, wxDouble yo, wxDouble xc, wxDouble yc, wxDouble radius,
241 const wxGraphicsGradientStops& stops )
247 void a2dFillData::CreateLinearGradientBrush( wxDouble x1, wxDouble y1, wxDouble x2, wxDouble y2,
248 const wxColour& c1,
const wxColour& c2 )
254 void a2dFillData::CreateRadialGradientBrush( wxDouble xo, wxDouble yo, wxDouble xc, wxDouble yc, wxDouble radius,
255 const wxColour& oColor,
const wxColour& cColor )
263 void a2dFillData::Init()
271 a2dFontData::a2dFontData( wxGraphicsRenderer* renderer,
const wxFont& font,
272 const wxColour& col ) : wxGraphicsObjectRefData( renderer )
274 m_font =
a2dFont( font, font.GetPointSize() );
277 a2dFontData::a2dFontData( wxGraphicsRenderer* renderer,
const a2dFont& font )
278 : wxGraphicsObjectRefData( renderer )
283 a2dFontData::~a2dFontData()
287 void a2dFontData::Apply( wxGraphicsContext* context )
289 a2dContext* ctext = ( a2dContext* ) context->GetNativeContext();
290 ctext->SetFont( m_font );
297 a2dPathData::a2dPathData( wxGraphicsRenderer* renderer,
a2dVpath* path )
298 : wxGraphicsPathData( renderer )
307 a2dPathData::~a2dPathData()
311 wxGraphicsObjectRefData* a2dPathData::Clone()
const
314 return new a2dPathData( GetRenderer() , p );
318 void* a2dPathData::GetNativePath()
const
320 return (
void* ) &m_path;
323 void a2dPathData::UnGetNativePath(
void* p )
const
331 void a2dPathData::MoveToPoint( wxDouble x , wxDouble y )
333 m_path.MoveTo( x, y );
336 void a2dPathData::AddLineToPoint( wxDouble x , wxDouble y )
338 m_path.LineTo( x, y );
341 void a2dPathData::AddPath(
const wxGraphicsPathData* path )
347 void a2dPathData::CloseSubpath()
352 void a2dPathData::AddCurveToPoint( wxDouble cx1, wxDouble cy1, wxDouble cx2, wxDouble cy2, wxDouble x, wxDouble y )
354 m_path.
CBCurveTo( cx1, cy1, cx2, cy2, x, y );
358 void a2dPathData::GetCurrentPoint( wxDouble* x, wxDouble* y )
const
370 void a2dPathData::AddArc( wxDouble xc, wxDouble yc, wxDouble radius,
double startAngle,
double endAngle,
bool clockwise )
372 if ( ( endAngle - startAngle ) >= 2 * M_PI )
374 double x1 = xc + radius;
376 double x2 = xc + radius;
378 double xm = xc - radius;
380 m_path.ArcTo( xc, yc, x2 , y2, xm, ym );
382 else if ( clockwise || ( endAngle - startAngle ) >= 2 * M_PI )
384 double x1 = xc + radius * cos( startAngle );
385 double y1 = yc + radius * sin( startAngle );
386 double x2 = xc + radius * cos( endAngle );
387 double y2 = yc + radius * sin( endAngle );
394 er = endAngle - startAngle;
396 if ( er <= 0 ) er += 2.0 * M_PI;
397 if ( er >= 2.0 * M_PI ) er -= 2.0 * M_PI;
400 midrad = er / 2.0 + startAngle;
402 double xm = xc + radius * cos( midrad );
403 double ym = yc + radius * sin( midrad );
406 m_path.ArcTo( xc, yc, x2 , y2, xm, ym );
410 double x1 = xc + radius * cos( startAngle );
411 double y1 = yc + radius * sin( startAngle );
412 double x2 = xc + radius * cos( endAngle );
413 double y2 = yc + radius * sin( endAngle );
420 er = endAngle - startAngle;
422 if ( er <= 0 ) er += 2.0 * M_PI;
423 if ( er >= 2.0 * M_PI ) er -= 2.0 * M_PI;
426 midrad = ( 2.0 * M_PI - er / 2.0 );
428 double xm = xc + radius * cos( midrad );
429 double ym = yc + radius * sin( midrad );
432 m_path.ArcTo( xc, yc, x2 , y2, xm, ym );
437 void a2dPathData::Transform(
const wxGraphicsMatrixData* matrix )
442 m_path.Transform( m );
446 void a2dPathData::GetBox( wxDouble* x, wxDouble* y, wxDouble* w, wxDouble* h )
const
448 double x1, y1, x2, y2;
479 bool a2dPathData::Contains( wxDouble x, wxDouble y, wxPolygonFillMode fillStyle )
const
488 a2dMatrixData::a2dMatrixData( wxGraphicsRenderer* renderer,
const a2dAffineMatrix* matrix )
489 : wxGraphicsMatrixData( renderer )
495 a2dMatrixData::~a2dMatrixData()
500 wxGraphicsObjectRefData* a2dMatrixData::Clone()
const
502 return new a2dMatrixData( GetRenderer(), &m_matrix );
506 void a2dMatrixData::Concat(
const wxGraphicsMatrixData* t )
512 void a2dMatrixData::Set( wxDouble a, wxDouble b, wxDouble c, wxDouble d,
513 wxDouble tx, wxDouble ty )
519 void a2dMatrixData::Get( wxDouble* a, wxDouble* b, wxDouble* c,
520 wxDouble* d, wxDouble* tx, wxDouble* ty )
const
522 if ( a ) *a = m_matrix( 0, 0 );
523 if ( b ) *b = m_matrix( 0, 1 );
524 if ( c ) *c = m_matrix( 1, 0 );
525 if ( d ) *d = m_matrix( 1, 1 );
526 if ( tx ) *tx = m_matrix( 2, 0 );
527 if ( ty ) *ty = m_matrix( 2, 1 );
531 void a2dMatrixData::Invert()
537 bool a2dMatrixData::IsEqual(
const wxGraphicsMatrixData* t )
const
543 bool a2dMatrixData::IsIdentity()
const
545 return m_matrix.IsIdentity();
553 void a2dMatrixData::Translate( wxDouble dx , wxDouble dy )
555 m_matrix.Translate( dx, dy ) ;
559 void a2dMatrixData::Scale( wxDouble xScale , wxDouble yScale )
561 m_matrix.Scale( xScale, yScale, m_matrix( 2, 0 ), m_matrix( 2, 0 ) ) ;
565 void a2dMatrixData::Rotate( wxDouble angle )
567 m_matrix.Rotate( angle ) ;
575 void a2dMatrixData::TransformPoint( wxDouble* x, wxDouble* y )
const
577 double lx = *x, ly = *y ;
578 m_matrix.TransformPoint( lx, ly );
584 void a2dMatrixData::TransformDistance( wxDouble* dx, wxDouble* dy )
const
586 double lx = *dx, ly = *dy ;
588 m_matrix.TransformDistance( lx, ly );
594 void* a2dMatrixData::GetNativeMatrix()
const
596 return (
void* ) &m_matrix;
603 a2dBitmapData::a2dBitmapData( wxGraphicsRenderer* renderer,
const wxBitmap& bmp ) : wxGraphicsObjectRefData( renderer )
605 wxCHECK_RET( bmp.IsOk(), wxT(
"Invalid bitmap in a2dBitmapData" ) );
607 m_width = bmp.GetWidth();
608 m_height = bmp.GetHeight();
609 m_image = bmp.ConvertToImage();
612 a2dBitmapData::a2dBitmapData( wxGraphicsRenderer* renderer,
const wxImage& image ) : wxGraphicsObjectRefData( renderer )
614 wxCHECK_RET( image.IsOk(), wxT(
"Invalid image in a2dBitmapData" ) );
616 m_width = image.GetWidth();
617 m_height = image.GetHeight();
621 a2dBitmapData::a2dBitmapData( wxGraphicsRenderer* renderer,
const wxGraphicsBitmap& a2dbitmap ) : wxGraphicsObjectRefData( renderer )
623 a2dBitmapData* data = ( a2dBitmapData* ) a2dbitmap.GetRefData();
625 m_width = data->GetSize().GetWidth();
626 m_height = data->GetSize().GetHeight();
627 m_image = data->GetImage();
630 a2dBitmapData::~a2dBitmapData()
638 a2dContext::a2dContext( wxGraphicsRenderer* renderer, a2dContext* context )
640 m_width( context->m_width ),
641 m_height( context->m_height ),
643 wxGraphicsContext( renderer )
648 a2dContext::a2dContext( wxGraphicsRenderer* renderer,
int width,
int height )
653 wxGraphicsContext( renderer )
658 a2dContext::a2dContext( wxGraphicsRenderer* renderer )
663 wxGraphicsContext( renderer )
668 void a2dContext::Init()
673 m_OpacityFactor = 255;
674 m_displayaberration = 0.5;
697 a2dContext::~a2dContext()
703 void a2dContext::SetYaxis(
bool up )
708 void a2dContext::SetPen(
const wxGraphicsPen& pen )
710 wxGraphicsContext::SetPen( pen );
713 ( ( a2dStrokeData* )pen.GetRefData() )->Apply(
this );
718 void a2dContext::SetBrush(
const wxGraphicsBrush& brush )
720 wxGraphicsContext::SetBrush( brush );
722 if ( !brush.IsNull() )
723 ( ( a2dFillData* )brush.GetRefData() )->Apply(
this );
728 void a2dContext::SetFont(
const wxGraphicsFont& font )
730 wxGraphicsContext::SetFont( font );
731 ( ( a2dFontData* ) font.GetRefData() )->Apply(
this );
734 void a2dContext::SetStroke(
const a2dStroke& stroke )
736 switch( m_drawstyle )
741 m_activestroke = stroke;
747 m_activestroke = stroke;
757 m_colour1redStroke = m_activestroke.GetColour().Red();
758 m_colour1greenStroke = m_activestroke.GetColour().Green();
759 m_colour1blueStroke = m_activestroke.GetColour().Blue();
763 m_StrokeOpacityCol1 = 0;
764 m_StrokeOpacityCol2 = 0;
768 m_StrokeOpacityCol1 = m_activestroke.GetColour().Alpha() * m_OpacityFactor / 255 ;
769 m_StrokeOpacityCol2 = m_activestroke.GetColour().Alpha() * m_OpacityFactor / 255 ;
774 void a2dContext::SetFill(
const a2dFill& fill )
776 switch( m_drawstyle )
794 m_colour1redFill = m_activefill.GetColour().Red();
795 m_colour1greenFill = m_activefill.GetColour().Green();
796 m_colour1blueFill = m_activefill.GetColour().Blue();
797 m_colour2redFill = m_activefill.GetColour2().Red();
798 m_colour2greenFill = m_activefill.GetColour2().Green();
799 m_colour2blueFill = m_activefill.GetColour2().Blue();
801 if ( !m_activefill.GetFilling() )
803 m_FillOpacityCol1 = 0;
804 m_FillOpacityCol2 = 0;
808 m_FillOpacityCol1 = 0;
809 m_FillOpacityCol2 = 0;
811 else if ( m_activefill.IsNoFill() )
813 m_FillOpacityCol1 = 0;
814 m_FillOpacityCol2 = 0;
818 m_FillOpacityCol1 = m_activefill.GetColour().Alpha() * m_OpacityFactor / 255;
819 m_FillOpacityCol2 = m_activefill.GetColour2().Alpha() * m_OpacityFactor / 255;
825 void a2dContext::SetFont(
const a2dFont& font )
830 void a2dContext::Clip(
const wxRegion& region )
833 wxGraphicsPath path = GetRenderer()->CreatePath();
834 wxRegionIterator ri( region );
837 path.AddRectangle( ri.GetX(), ri.GetY(), ri.GetW(), ri.GetH() );
844 void a2dContext::Clip( wxDouble x, wxDouble y, wxDouble w, wxDouble h )
851 m_usertodevice.TransformPoint( x, y, dx, dy );
852 trpoints[0] = wxPoint( dx, dy );
853 m_usertodevice.TransformPoint( x, y + h, dx, dy );
854 trpoints[1] = wxPoint( dx, dy );
855 m_usertodevice.TransformPoint( x + w, y + h, dx, dy );
856 trpoints[2] = wxPoint( dx, dy );
857 m_usertodevice.TransformPoint( x + w, y, dx, dy );
858 trpoints[3] = wxPoint( dx, dy );
860 double xmin = trpoints[0].x;
861 double ymin = trpoints[0].y;
862 double xmax = trpoints[0].x;
863 double ymax = trpoints[0].y;
864 for (
int i = 1; i < 4; i ++ )
866 xmin = wxMin( xmin, trpoints[i].x );
867 xmax = wxMax( xmin, trpoints[i].x );
868 ymin = wxMin( ymin, trpoints[i].y );
869 ymax = wxMax( ymin, trpoints[i].y );
871 wxRect cliprect = wxRect( xmin, ymin, xmax - xmin, ymax - ymin );
872 m_clipboxdev = cliprect;
875 void a2dContext::ResetClip()
877 m_clipboxdev = wxRect( 0, 0, m_width, m_height );
880 void a2dContext::DrawPath(
const wxGraphicsPath& path, wxPolygonFillMode fillStyle )
882 if ( !m_pen.IsNull() || !m_brush.IsNull() )
899 void a2dContext::StrokePath(
const wxGraphicsPath& path )
901 if ( !m_pen.IsNull() )
906 a2dFill curfill = m_activefill;
913 void a2dContext::FillPath(
const wxGraphicsPath& path , wxPolygonFillMode fillStyle )
915 if ( !m_brush.IsNull() )
923 m_activestroke = curstroke;
927 void a2dContext::Rotate( wxDouble angle )
929 m_usertodevice.Rotate( angle ) ;
932 void a2dContext::Translate( wxDouble dx , wxDouble dy )
934 m_usertodevice.Translate( dx, dy ) ;
937 void a2dContext::Scale( wxDouble xScale , wxDouble yScale )
939 m_usertodevice.Scale( xScale, yScale, 0, 0 ) ;
943 void a2dContext::ConcatTransform(
const wxGraphicsMatrix& matrix )
946 m_usertodevice *= *m;
950 void a2dContext::SetTransform(
const wxGraphicsMatrix& matrix )
957 wxGraphicsMatrix a2dContext::GetTransform()
const
959 wxGraphicsMatrix matrix = CreateMatrix();
965 void a2dContext::PushState()
969 void a2dContext::PopState()
973 #if wxCHECK_VERSION(2,9,0)
974 void a2dContext::DrawBitmap(
const wxGraphicsBitmap& bmp, wxDouble x, wxDouble y, wxDouble w, wxDouble h )
976 void a2dContext::DrawGraphicsBitmap(
const wxGraphicsBitmap& bmp, wxDouble x, wxDouble y, wxDouble w, wxDouble h )
979 a2dBitmapData* data =
static_cast<a2dBitmapData*
>( bmp.GetRefData() );
980 wxImage image = data->GetImage();
983 void a2dContext::DrawBitmap(
const wxBitmap& bmp, wxDouble x, wxDouble y, wxDouble w, wxDouble h )
985 wxGraphicsBitmap bitmap = GetRenderer()->CreateBitmap( bmp );
986 #if wxCHECK_VERSION(2,9,0)
987 DrawBitmap( bitmap, x, y, w, h );
989 DrawGraphicsBitmap( bitmap, x, y, w, h );
993 void a2dContext::DrawIcon(
const wxIcon& icon, wxDouble x, wxDouble y, wxDouble w, wxDouble h )
998 #if wxCHECK_VERSION(2,9,0)
999 void a2dContext::DoDrawText(
const wxString& str, wxDouble x, wxDouble y )
1001 void a2dContext::DrawText(
const wxString& str, wxDouble x, wxDouble y )
1011 a2dBoundingBox bbox = m_a2dfont.GetTextExtent( str, wxMINX | wxMINY,
false );
1020 double dx, dy, size;
1021 dx = m_usertodevice.GetValue( 1, 0 );
1022 dy = m_usertodevice.GetValue( 1, 1 );
1023 size = m_a2dfont.GetSize() * sqrt( dx * dx + dy * dy );
1027 worldbbox.MapBbox( m_usertodevice );
1028 wxRect devb = wxRect( worldbbox.GetMinX(), worldbbox.GetMinY(), worldbbox.GetWidth(), worldbbox.GetHeight() );
1031 if ( m_clipboxdev.Intersects( devb ) )
1037 if ( size > m_drawingthreshold )
1040 switch ( m_a2dfont.GetType() )
1042 case a2dFONT_STROKED:
1043 DrawTextStroke( str, x, y );
1045 case a2dFONT_FREETYPE:
1046 DrawTextFreetype( str, x, y );
1049 DrawTextDc( str, x, y );
1052 DrawTextUnknown( str, x, y );
1057 DrawTextUnknown( str, x, y,
true );
1062 void a2dContext::GetTextExtent(
const wxString& str, wxDouble* width, wxDouble* height,
1063 wxDouble* descent, wxDouble* externalLeading )
const
1070 const wxWX2MBbuf buf( str.mb_str( wxConvUTF8 ) );
1073 if ( height || descent || externalLeading )
1078 void a2dContext::GetPartialTextExtents(
const wxString& text, wxArrayDouble& widths )
const
1081 widths.Add( 0, text.length() );
1089 void* a2dContext::GetNativeContext()
1099 unsigned int segments = 0;
1102 for ( i = 0; i < points->size(); i++ )
1106 if ( seg->GetArc() )
1110 double radius, center_x, center_y, beginrad, midrad, endrad, phit;
1112 if ( cseg->
CalcR( *( points->operator[]( i ? i - 1 : 0 ) ), radius, center_x, center_y, beginrad, midrad, endrad, phit ) )
1115 unsigned int circlesegments;
1116 double radiusDev = m_usertodevice.TransformDistance( radius );
1117 Aberration( m_displayaberration, phit, radiusDev , dphi, circlesegments );
1118 segments += circlesegments + 1;
1128 m_cpointsDouble.resize( segments * 2 );
1130 unsigned int count = 0;
1131 double x, y, lastx, lasty;
1132 for ( i = 0; i < points->size(); i++ )
1136 if ( !seg->GetArc() )
1138 m_usertodevice.TransformPoint( seg->
m_x, seg->
m_y, x, y );
1141 if( !count || fabs( x - lastx ) > 0.001 || fabs( y - lasty ) > 0.001 )
1143 m_cpointsDouble[count].x = x;
1144 m_cpointsDouble[count].y = y;
1155 double radius, center_x, center_y, beginrad, midrad, endrad, phit;
1157 if ( cseg->
CalcR( *( points->operator[]( i ? i - 1 : 0 ) ), radius, center_x, center_y, beginrad, midrad, endrad, phit ) )
1160 unsigned int segments;
1161 double radiusDev = m_usertodevice.TransformDistance( radius );
1162 Aberration( m_displayaberration, phit, radiusDev , dphi, segments );
1164 double theta = beginrad;
1168 for ( step = 0; step < segments + 1; step++ )
1170 m_usertodevice.TransformPoint( center_x + radius * cos ( theta ), center_y + radius * sin ( theta ), x, y );
1173 if( !count || fabs( x - lastx ) > 0.001 || fabs( y - lasty ) > 0.001 )
1175 m_cpointsDouble[count].x = x;
1176 m_cpointsDouble[count].y = y;
1182 theta = theta + dphi;
1188 m_usertodevice.TransformPoint( cseg->
m_x, cseg->
m_y, x, y );
1191 if( !count || fabs( x - lastx ) > 0.001 || fabs( y - lasty ) > 0.001 )
1193 m_cpointsDouble[count].x = x;
1194 m_cpointsDouble[count].y = y;
1209 unsigned int segments = 0;
1211 if ( list->empty() )
1214 a2dVertexList::const_iterator iterprev = list->end();
1215 if ( iterprev != list->begin() )
1217 a2dVertexList::const_iterator iter = list->begin();
1218 while ( iter != list->end() )
1222 if ( seg->GetArc() )
1226 double radius, center_x, center_y, beginrad, midrad, endrad, phit;
1228 if ( cseg->
CalcR( *( *iterprev ), radius, center_x, center_y, beginrad, midrad, endrad, phit ) )
1231 unsigned int circlesegments;
1232 double radiusDev = m_usertodevice.TransformDistance( radius );
1233 Aberration( m_displayaberration, phit, radiusDev , dphi, circlesegments );
1234 segments += circlesegments + 1;
1246 m_cpointsDouble.resize( segments * 2 );
1248 unsigned int count = 0;
1249 double x, y, lastx, lasty;
1250 iterprev = list->end();
1251 if ( iterprev != list->begin() )
1253 iter = list->begin();
1254 while ( iter != list->end() )
1258 if ( !seg->GetArc() )
1260 m_usertodevice.TransformPoint( seg->
m_x, seg->
m_y, x, y );
1263 if( !count || fabs( x - lastx ) > 0.001 || fabs( y - lasty ) > 0.001 )
1265 m_cpointsDouble[count].x = x;
1266 m_cpointsDouble[count].y = y;
1277 double radius, center_x, center_y, beginrad, midrad, endrad, phit;
1279 if ( cseg->
CalcR( *( *iterprev ), radius, center_x, center_y, beginrad, midrad, endrad, phit ) )
1282 unsigned int segments;
1283 double radiusDev = m_usertodevice.TransformDistance( radius );
1284 Aberration( m_displayaberration, phit, radiusDev , dphi, segments );
1286 double theta = beginrad;
1290 for ( step = 0; step < segments + 1; step++ )
1292 m_usertodevice.TransformPoint( center_x + radius * cos ( theta ), center_y + radius * sin ( theta ), x, y );
1295 if( !count || fabs( x - lastx ) > 0.001 || fabs( y - lasty ) > 0.001 )
1297 m_cpointsDouble[count].x = x;
1298 m_cpointsDouble[count].y = y;
1304 theta = theta + dphi;
1310 m_usertodevice.TransformPoint( cseg->
m_x, cseg->
m_y, x, y );
1313 if( !count || fabs( x - lastx ) > 0.001 || fabs( y - lasty ) > 0.001 )
1315 m_cpointsDouble[count].x = x;
1316 m_cpointsDouble[count].y = y;
1331 void a2dContext::DrawVpath(
const a2dVpath* path )
1339 bool nostrokeparts =
false;
1342 for ( i = 0; i < path->size(); i++ )
1345 switch ( seg->GetType() )
1367 nostrokeparts =
true;
1371 nostrokeparts =
true;
1376 double xwl = path->operator[]( i ? i - 1 : 0 )->m_x1;
1377 double ywl = path->operator[]( i ? i - 1 : 0 )->m_y1;
1384 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 );
1385 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 );
1394 nostrokeparts =
true;
1399 double xwl = path->operator[]( i ? i - 1 : 0 )->m_x1;
1400 double ywl = path->operator[]( i ? i - 1 : 0 )->m_y1;
1407 xw = xwl * pow( 1 - t, 2 ) + cseg->
m_x2 * ( 1 - t ) * t * 2 + cseg->
m_x1 * pow( t, 2 );
1408 yw = ywl * pow( 1 - t, 2 ) + cseg->
m_y2 * ( 1 - t ) * t * 2 + cseg->
m_y1 * pow( t, 2 );
1417 nostrokeparts =
true;
1422 double radius, center_x, center_y, beginrad, midrad, endrad, phit;
1424 if ( cseg->
CalcR( path->operator[]( i ? i - 1 : 0 ), radius, center_x, center_y, beginrad, midrad, endrad, phit ) )
1427 unsigned int segments;
1428 double radiusDev = m_usertodevice.TransformDistance( radius );
1429 Aberration( m_displayaberration, phit, radiusDev , dphi, segments );
1431 double theta = beginrad;
1434 for ( step = 0; step < segments + 1; step++ )
1436 points.push_back(
new a2dLineSegment( center_x + radius * cos ( theta ), center_y + radius * sin ( theta ) ) );
1438 theta = theta + dphi;
1454 DrawLines( &points );
1465 DrawPolygon( &points, wxODDEVEN_RULE );
1466 m_activestroke = stroke;
1467 nostrokeparts =
true;
1471 DrawPolygon( &points, wxODDEVEN_RULE );
1478 else if ( i == path->size() - 1 )
1480 DrawLines( &points );
1484 if ( nostrokeparts )
1489 nostrokeparts =
false;
1491 double lastmovex = 0;
1492 double lastmovey = 0;
1494 for ( i = 0; i < path->size(); i++ )
1497 switch ( seg->GetType() )
1503 lastmovex = seg->m_x1;
1504 lastmovey = seg->m_y1;
1531 nostrokeparts =
true;
1539 double xwl = path->operator[]( i ? i - 1 : 0 )->m_x1;
1540 double ywl = path->operator[]( i ? i - 1 : 0 )->m_y1;
1547 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 );
1548 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 );
1560 double xwl = path->operator[]( i ? i - 1 : 0 )->m_x1;
1561 double ywl = path->operator[]( i ? i - 1 : 0 )->m_y1;
1568 xw = xwl * pow( 1 - t, 2 ) + cseg.
m_x2 * ( 1 - t ) * t * 2 + cseg.
m_x1 * pow( t, 2 );
1569 yw = ywl * pow( 1 - t, 2 ) + cseg.
m_y2 * ( 1 - t ) * t * 2 + cseg.
m_y1 * pow( t, 2 );
1581 double radius, center_x, center_y, beginrad, midrad, endrad, phit;
1583 if ( cseg->
CalcR( path->operator[]( i ? i - 1 : 0 ), radius, center_x, center_y, beginrad, midrad, endrad, phit ) )
1586 unsigned int segments;
1587 double radiusDev = m_usertodevice.TransformDistance( radius );
1588 Aberration( m_displayaberration, phit, radiusDev , dphi, segments );
1590 double theta = beginrad;
1593 for ( step = 0; step < segments + 1; step++ )
1595 points.push_back(
new a2dLineSegment( center_x + radius * cos ( theta ), center_y + radius * sin ( theta ) ) );
1597 theta = theta + dphi;
1612 if ( move || nostrokeparts )
1614 DrawLines( &points );
1616 nostrokeparts =
false;
1627 DrawLines( &points );
1628 nostrokeparts =
false;
1633 else if ( i == path->size() )
1635 DrawLines( &points );
1642 void a2dContext::DrawCharUnknown( wxChar c )
1646 a2dStroke stroke =
a2dStroke( m_activestroke.GetColour(), m_a2dfont.GetSize() / 20.0 );
1647 m_activestroke = stroke;
1649 if ( c != wxChar(
' ' ) )
1651 double desc = m_a2dfont.GetDescent();
1652 double size = m_a2dfont.GetSize();
1653 double width = m_a2dfont.
GetWidth( c );
1654 DrawLine( 0.1 * width, desc, 0.9 * width, desc + size );
1655 DrawLine( 0.9 * width, desc, 0.1 * width, desc + size );
1659 m_activestroke = oldstroke;
1662 void a2dContext::DrawTextUnknown(
const wxString& text,
double x,
double y,
bool words )
1664 if ( words && m_a2dfont.Ok() )
1668 a2dBoundingBox linebbox = m_a2dfont.GetTextExtent( text, m_yaxis );
1673 DrawRoundedRectangle( x + linebbox.
GetMinX(), y + linebbox.
GetMinY(),
1675 m_activestroke = oldstroke;
1680 m_activestroke = strokew;
1686 for (
size_t i = 0; i < text.Length(); i++ )
1689 w = m_a2dfont.GetWidth( c );
1690 if ( c == wxChar(
' ' ) )
1693 DrawLine( start, y + h / 2, x, y + h / 2 );
1699 DrawLine( start, y + h / 2, x, y + h / 2 );
1702 m_activestroke = oldstroke;
1706 a2dBoundingBox linebbox = m_a2dfont.GetTextExtent( text, m_yaxis );
1708 DrawRoundedRectangle( x + linebbox.
GetMinX(), y + linebbox.
GetMinY(),
1716 void a2dContext::DrawCharStroke( wxChar c )
1722 stroke.
SetWidth( m_a2dfont.GetStrokeWidth() );
1723 m_activestroke = stroke;
1729 affine.
Scale( m_a2dfont.GetSize() );
1730 m_usertodevice = affine;
1742 m_usertodevice = affineold;
1743 m_activestroke = strokeold;
1746 void a2dContext::DrawTextGeneric(
const wxString& text,
double x,
double y,
void ( a2dContext::*drawchar )( wxChar ) )
1749 const double h = m_a2dfont.GetLineHeight();
1754 affine.
Mirror(
true,
false );
1762 m_usertodevice = m_usertodevice;
1764 bool textwasvisible =
false;
1768 const size_t n = text.Length();
1769 for (
size_t i = 0; i < n; i++ )
1771 const wxChar oldc = c;
1777 m_usertodevice = affineold * textm;
1779 w = m_a2dfont.GetWidth( c );
1783 bbox.
MapBbox( m_usertodevice );
1787 if ( m_clipboxdev.Intersects( devb ) )
1789 ( this->*drawchar )( c );
1790 textwasvisible =
true;
1792 else if ( textwasvisible )
1801 m_usertodevice = affineold;
1808 bool a2dContext::MoveUp(
int n, wxRealPoint points[] ,
double horline,
int& index,
int direction )
1810 int walk = ( index + direction + n ) % n;
1811 while ( points[walk].y < horline )
1813 if ( points[walk].y < points[index].y )
1819 walk = ( index + direction + n ) % n;
1827 void a2dContext::DetectCriticalPoints(
int n, wxRealPoint points[] )
1832 bool candidate =
false;
1835 for ( i = 0; i < n; i++ )
1841 if ( points[i].y > points[j].y )
1844 else if ( ( points[i].y < points[j].y ) && candidate )
1847 bool inserted =
false;
1848 a2dCriticalPointList::compatibility_iterator node = m_CRlist.GetFirst();
1852 int* ind = node->GetData();
1853 if ( points[*ind].y > points[i].y )
1855 m_CRlist.Insert( node,
new int( i ) );
1859 node = node->GetNext();
1862 m_CRlist.Append(
new int( i ) );
1868 for ( i = 0; i < n; i++ )
1874 if ( points[i].y > points[j].y )
1877 else if ( ( points[i].y < points[j].y ) && candidate )
1880 bool inserted =
false;
1881 a2dCriticalPointList::compatibility_iterator node = m_CRlist.GetFirst();
1885 int* ind = node->GetData();
1886 if ( points[*ind].y > points[i].y )
1888 m_CRlist.Insert( node,
new int( i ) );
1892 node = node->GetNext();
1895 m_CRlist.Append(
new int( i ) );
1903 static int SortonXs(
const a2dAET** first,
const a2dAET** second )
1905 if ( ( *first )->m_xs < ( *second )->m_xs )
1907 else if ( ( *first )->m_xs > ( *second )->m_xs )
1913 void a2dContext::ColourXYLinear(
int x1,
int x2,
int y )
1915 int dred = m_colour2redFill - m_colour1redFill;
1916 int dgreen = m_colour2greenFill - m_colour1greenFill;
1917 int dblue = m_colour2blueFill - m_colour1blueFill;
1919 if ( m_dx1 == m_dx2 )
1923 double stepcol = m_max_y - m_min_y;
1925 double curcol = y - m_min_y;
1928 wxColour gradcol( (
unsigned char ) ( m_colour1redFill + dred * curcol / stepcol ),
1929 (
unsigned char ) ( m_colour1greenFill + dgreen * curcol / stepcol ),
1930 (
unsigned char ) ( m_colour1blueFill + dblue * curcol / stepcol ) );
1932 m_activestroke = gradientstroke;
1933 DeviceDrawHorizontalLine( x1, y, x2,
true );
1934 m_activestroke = current;
1939 for ( j = x1; j <= x2; j++ )
1941 a2dLine perstroke( j, y, j + m_dy2 - m_dy1, y + m_dx2 - m_dx1 );
1943 perstroke.CalculateLineParameters();
1944 perstroke.Intersect( m_line, crossing );
1946 double length = sqrt( (
double ) ( crossing.m_x - m_dx1 ) * ( crossing.m_x - m_dx1 ) + ( crossing.m_y - m_dy1 ) * ( crossing.m_y - m_dy1 ) );
1948 if ( length > m_length )
1951 DeviceDrawPixel( j, y, m_colour1redFill + dred *
int( length / m_length ),
1952 m_colour1greenFill + dgreen *
int( length / m_length ),
1953 m_colour1blueFill + dblue *
int( length / m_length ) );
1958 void a2dContext::ColourXYRadial(
int x1,
int x2,
int y )
1960 int dred = m_colour2redFill - m_colour1redFill;
1961 int dgreen = m_colour2greenFill - m_colour1greenFill;
1962 int dblue = m_colour2blueFill - m_colour1blueFill;
1965 for ( j = x1; j <= x2; j++ )
1967 double cradius = sqrt( (
double ) ( j - m_dx1 ) * ( j - m_dx1 ) + ( y - m_dy1 ) * ( y - m_dy1 ) );
1970 if ( m_radiusd == 0 )
1972 else if ( cradius > m_radiusd )
1975 delta = cradius / m_radiusd;
1977 DeviceDrawPixel( j, y, (
unsigned char ) ( m_colour1redFill + dred * delta ),
1978 (
unsigned char ) ( m_colour1greenFill + dgreen * delta ),
1979 (
unsigned char ) ( m_colour1blueFill + dblue * delta ) );
1983 void a2dContext::FillPolygon(
int n, wxRealPoint points[] )
1986 clip.x = m_clipboxdev.x;
1987 clip.y = m_clipboxdev.y;
1988 clip.width = m_clipboxdev.width;
1989 clip.height = m_clipboxdev.height;
1991 m_min_y = points[0].y;
1992 m_max_y = points[0].y;
1993 m_min_x = points[0].x;
1994 m_max_x = points[0].x;
1995 double centroidx = 0;
1996 double centroidy = 0;
1998 for ( i = 0; i < n; i++ )
2000 m_min_y = wxMin( m_min_y, points[i].y );
2001 m_max_y = wxMax( m_max_y, points[i].y );
2002 m_min_x = wxMin( m_min_x, points[i].x );
2003 m_max_x = wxMax( m_max_x, points[i].x );
2004 centroidx += points[i].x;
2005 centroidy += points[i].y;
2008 centroidx /= double( n );
2009 centroidy /= double( n );
2015 double x1 = m_activefill.GetStart().m_x;
2016 double y1 = m_activefill.GetStart().m_y;
2017 double x2 = m_activefill.GetStop().m_x;
2018 double y2 = m_activefill.GetStop().m_y;
2019 m_usertodevice.TransformPoint( x1, y1, m_dx1, m_dy1 );
2020 m_usertodevice.TransformPoint( x2, y2, m_dx2, m_dy2 );
2021 if ( m_dx1 == m_dx2 && m_dy1 == m_dy2 )
2028 if ( m_dx1 == m_dx2 && m_dy1 == m_dy2 )
2029 m_dx2 = m_dx2 + 100;
2031 m_length = sqrt ( ( m_dx1 - m_dx2 ) * ( m_dx1 - m_dx2 ) + ( m_dy1 - m_dy2 ) * ( m_dy1 - m_dy2 ) );
2032 m_line =
a2dLine( m_dx1, m_dy1, m_dx2, m_dy2 );
2033 m_line.CalculateLineParameters();
2037 double xfc = m_activefill.GetFocal().m_x;
2038 double yfc = m_activefill.GetFocal().m_y;
2039 double xe = m_activefill.GetCenter().m_x;
2040 double ye = m_activefill.GetCenter().m_y;
2041 m_usertodevice.TransformPoint( xfc, yfc, m_dx1, m_dy1 );
2042 m_usertodevice.TransformPoint( xe, ye, m_dx2, m_dy2 );
2043 if ( m_dx1 == m_dx2 && m_dy1 == m_dy2 )
2051 if ( m_dx1 == m_dx2 && m_dy1 == m_dy2 )
2055 m_usertodevice.TransformPoint( xe, ye + m_activefill.GetRadius(), dx3, dy3 );
2056 m_radiusd = sqrt ( ( dx3 - m_dx2 ) * ( dx3 - m_dx2 ) + ( dy3 - m_dy2 ) * ( dy3 - m_dy2 ) );
2059 DetectCriticalPoints( n, points );
2061 int min = ( int ) wxMax ( m_min_y, clip.y );
2062 int max = ( int ) wxMin ( m_max_y, clip.y + clip.height );
2064 for ( i = min; i < max; i++ )
2066 a2dAETList::compatibility_iterator node = m_AETlist.GetFirst();
2067 int count = m_AETlist.size();
2070 a2dAET* ele = node->GetData();
2071 index = ele->m_index;
2072 int direction = ele->m_direction;
2073 if ( !MoveUp( n, points, i, index, direction ) )
2075 a2dAETList::compatibility_iterator h = node;
2077 node = node->GetNext();
2078 delete h->GetData();
2079 m_AETlist.DeleteNode( h );
2083 if ( ele->m_index != index )
2085 ele->m_index = index;
2086 int h = ( index + direction + n ) % n;
2087 ele->CalculateLineParameters( points[h], points[index] );
2089 if ( ele->m_horizontal )
2090 ele->m_xs = ( int ) points[index].x;
2092 ele->CalculateXs( i );
2093 node = node->GetNext();
2098 a2dCriticalPointList::compatibility_iterator nodec = m_CRlist.GetFirst();
2099 while ( m_CRlist.size() && points[*nodec->GetData()].y <= i )
2102 for ( DI = -1; DI <= 1 ; DI += 2 )
2104 index = *nodec->GetData();
2105 if ( MoveUp( n, points, i, index, DI ) )
2108 ele->m_index = index;
2109 ele->m_direction = DI;
2110 int h = ( index + DI + n ) % n;
2111 ele->CalculateLineParameters( points[h], points[index] );
2112 if ( ele->m_horizontal )
2113 ele->m_xs = ( int ) points[index].x;
2115 ele->CalculateXs( i );
2118 bool inserted =
false;
2119 node = m_AETlist.GetFirst();
2123 if ( ele->m_xs < ( node->GetData() )->m_xs )
2125 m_AETlist.Insert( node, ele );
2130 node = node->GetNext();
2133 m_AETlist.Append( ele );
2137 a2dCriticalPointList::compatibility_iterator h = nodec;
2138 nodec = nodec->GetNext();
2139 delete h->GetData();
2140 m_CRlist.DeleteNode( h );
2145 if ( m_AETlist.GetCount() > 1 )
2147 if ( m_AETlist.GetCount() > 2 )
2148 m_AETlist.Sort( SortonXs );
2149 else if ( m_AETlist.GetFirst()->GetData()->m_xs > m_AETlist.GetLast()->GetData()->m_xs )
2151 a2dAET* f = m_AETlist.GetFirst()->GetData();
2152 m_AETlist.GetFirst()->SetData( m_AETlist.GetLast()->GetData() );
2153 m_AETlist.GetLast()->SetData( f );
2160 node = m_AETlist.GetFirst();
2163 a2dAET* ele = node->GetData();
2164 out += ele->m_direction;
2168 int x1 = ( int ) ele->m_xs;
2169 node = node->GetNext();
2172 ele = node->GetData();
2173 int x2 = ( int ) ele->m_xs;
2175 if ( x1 < clip.x ) x1 = clip.x;
2176 if ( x2 > clip.x + clip.width ) x2 = clip.x + clip.width;
2177 if ( i >= clip.y && i <= clip.y + clip.height && ( x1 != x2 ) )
2180 ColourXYLinear( x1, x2, i );
2182 ColourXYRadial( x1, x2, i );
2184 DeviceDrawHorizontalLine( x1, i, x2,
false );
2190 node = node->GetNext();
2194 a2dAETList::compatibility_iterator node = m_AETlist.GetFirst();
2197 a2dAETList::compatibility_iterator h = node;
2198 delete h->GetData();
2199 m_AETlist.DeleteNode( h );
2200 node = m_AETlist.GetFirst();
2203 a2dCriticalPointList::compatibility_iterator nodec = m_CRlist.GetFirst();
2206 a2dCriticalPointList::compatibility_iterator h = nodec;
2207 delete h->GetData();
2208 m_CRlist.DeleteNode( h );
2209 nodec = m_CRlist.GetFirst();
2214 void a2dContext::DrawPolygon(
const a2dVertexList* list, wxPolygonFillMode fillStyle )
2217 bool smallPoly =
false;
2218 int segments = ToDeviceLines( list, devbox, smallPoly );
2220 if ( segments == 0 )
2223 DeviceDrawPolygon( segments,
false, fillStyle );
2229 bool smallPoly =
false;
2230 int segments = ToDeviceLines( list, devbox, smallPoly );
2233 DeviceDrawLines( segments,
false );
2236 void a2dContext::DrawLine(
double x1,
double y1,
double x2,
double y2 )
2241 DrawLines( &points );
2244 void a2dContext::DeviceDrawPolygon(
unsigned int n,
bool spline , wxPolygonFillMode fillStyle )
2246 wxFAIL_MSG( wxT(
"if used, must be implemented in derived class" ) );
2249 void a2dContext::DeviceDrawLines(
unsigned int n,
bool spline )
2251 wxFAIL_MSG( wxT(
"if used, must be implemented in derived class" ) );
2254 void a2dContext::DeviceDrawLine(
double x1,
double y1,
double x2,
double y2 )
2256 wxFAIL_MSG( wxT(
"if used, must be implemented in derived class" ) );
2259 void a2dContext::DeviceDrawHorizontalLine(
int x1,
int y1,
int x2,
bool WXUNUSED( use_pen ) )
2261 wxFAIL_MSG( wxT(
"if used, must be implemented in derived class" ) );
2264 void a2dContext::DeviceDrawVerticalLine(
int x1,
int y1,
int y2,
bool WXUNUSED( use_pen ) )
2266 wxFAIL_MSG( wxT(
"if used, must be implemented in derived class" ) );
2269 void a2dContext::DeviceDrawPixel(
int x1,
int y1,
unsigned char r,
unsigned char g,
unsigned char b,
unsigned char a )
2271 wxFAIL_MSG( wxT(
"if used, must be implemented in derived class" ) );
2274 wxPoint* a2dContext::_convertToIntPointCache(
int n, wxRealPoint* pts )
2276 m_cpointsInt.resize( n );
2278 for (
int i = 0; i < n; i++ )
2280 m_cpointsInt[i].x =
Round( pts[i].x );
2281 m_cpointsInt[i].y =
Round( pts[i].y );
2283 return &m_cpointsInt[0];
2293 a2dDcContext::a2dDcContext( wxGraphicsRenderer* renderer, wxMemoryDC* dc, wxBitmap* drawable )
2295 a2dContext( renderer, dc->GetSize().GetWidth(), dc->GetSize().GetHeight() )
2297 m_buffer = drawable;
2301 a2dDcContext::a2dDcContext( wxGraphicsRenderer* renderer, wxBitmap* drawable )
2303 a2dContext( renderer, drawable->GetWidth(), drawable->GetHeight() )
2305 m_buffer = drawable;
2306 m_renderDC =
new wxMemoryDC( *drawable );
2309 a2dDcContext::~a2dDcContext()
2313 void a2dDcContext::DoSetActiveStroke()
2319 m_renderDC->SetPen( *wxTRANSPARENT_PEN );
2323 m_renderDC->SetPen( *wxTRANSPARENT_PEN );
2329 m_renderDC->SetPen( *wxBLACK_PEN );
2334 switch( m_activestroke.GetStyle() )
2369 wxPen dcpen( m_activestroke.
GetColour(), 0, style );
2370 m_renderDC->SetPen( dcpen );
2371 m_renderDC->SetTextForeground( m_activestroke.
GetColour() );
2375 wxPen dcpen( m_activestroke.
GetColour(), ( int ) m_activestroke.
GetWidth(), style );
2376 dcpen.SetJoin( m_activestroke.GetJoin() );
2377 dcpen.SetCap( m_activestroke.GetCap() );
2380 double w = m_usertodevice.TransformDistance( m_activestroke.
GetWidth() );
2381 dcpen.SetWidth( (
int ) w );
2383 m_renderDC->SetPen( dcpen );
2384 m_renderDC->SetTextForeground( m_activestroke.
GetColour() );
2393 dcpen = wxPen( m_activestroke.
GetColour(), 0, wxBRUSHSTYLE_SOLID );
2396 int width = ( int ) m_activestroke.
GetWidth();
2403 dcpen = wxPen( m_activestroke.
GetColour(), width, wxBRUSHSTYLE_SOLID );
2404 dcpen.SetJoin( m_activestroke.GetJoin() );
2405 dcpen.SetCap( m_activestroke.GetCap() );
2408 #if defined(__WXMSW__)
2410 switch( m_activestroke.GetStyle() )
2413 style = wxBRUSHSTYLE_STIPPLE;
2414 dcpen.SetStyle( style );
2415 dcpen.SetStipple( m_activestroke.GetStipple() );
2421 wxBitmap noMask = m_activestroke.GetStipple();
2422 noMask.SetMask( NULL );
2423 style = wxBRUSHSTYLE_STIPPLE;
2424 dcpen.SetStyle( style );
2425 dcpen.SetStipple( noMask );
2429 style = wxBRUSHSTYLE_STIPPLE_MASK_OPAQUE;
2430 dcpen.SetStyle( style );
2431 dcpen.SetStipple( m_activestroke.GetStipple() );
2434 default: style = wxBRUSHSTYLE_SOLID;
2435 dcpen.SetStyle( style );
2439 m_renderDC->SetPen( dcpen );
2440 m_renderDC->SetTextBackground( *wxBLACK );
2441 m_renderDC->SetTextForeground( m_activestroke.
GetColour() );
2447 void a2dDcContext::DoSetActiveFill()
2451 if ( !m_activefill.GetFilling() )
2453 m_renderDC->SetBrush( *wxTRANSPARENT_BRUSH );
2454 m_renderDC->SetTextBackground( *wxBLACK );
2458 m_renderDC->SetBrush( *wxTRANSPARENT_BRUSH );
2459 m_renderDC->SetTextBackground( *wxBLACK );
2461 else if ( m_activefill.IsNoFill() )
2463 m_renderDC->SetBrush( *wxTRANSPARENT_BRUSH );
2465 m_renderDC->SetTextBackground( *wxBLACK );
2471 switch( m_activefill.GetStyle() )
2474 style = wxBRUSHSTYLE_TRANSPARENT;
2475 dcbrush.SetColour( m_activefill.GetColour() );
2476 dcbrush.SetStyle( style );
2479 dcbrush.SetColour( m_activefill.GetColour() );
2480 dcbrush.SetStyle( style );
2483 style = wxBRUSHSTYLE_BDIAGONAL_HATCH;
2484 dcbrush.SetColour( m_activefill.GetColour() );
2485 dcbrush.SetStyle( style );
2488 style = wxBRUSHSTYLE_CROSSDIAG_HATCH;
2489 dcbrush.SetColour( m_activefill.GetColour() );
2490 dcbrush.SetStyle( style );
2493 style = wxBRUSHSTYLE_FDIAGONAL_HATCH;
2494 dcbrush.SetColour( m_activefill.GetColour() );
2495 dcbrush.SetStyle( style );
2498 style = wxBRUSHSTYLE_CROSS_HATCH;
2499 dcbrush.SetColour( m_activefill.GetColour() );
2500 dcbrush.SetStyle( style );
2503 style = wxBRUSHSTYLE_HORIZONTAL_HATCH;
2504 dcbrush.SetColour( m_activefill.GetColour() );
2505 dcbrush.SetStyle( style );
2508 style = wxBRUSHSTYLE_VERTICAL_HATCH;
2509 dcbrush.SetColour( m_activefill.GetColour() );
2510 dcbrush.SetStyle( style );
2512 default: style = wxBRUSHSTYLE_SOLID;
2513 dcbrush.SetColour( m_activefill.GetColour() );
2514 dcbrush.SetStyle( style );
2517 m_renderDC->SetBrush( dcbrush );
2518 m_renderDC->SetTextBackground( m_activefill.GetColour() );
2524 switch( m_activefill.GetStyle() )
2527 style = wxBRUSHSTYLE_TRANSPARENT;
2528 dcbrush.SetColour( m_activefill.GetColour() );
2529 dcbrush.SetStyle( style );
2532 style = wxBRUSHSTYLE_BDIAGONAL_HATCH;
2533 dcbrush.SetColour( m_activefill.GetColour() );
2534 dcbrush.SetStyle( style );
2537 style = wxBRUSHSTYLE_CROSSDIAG_HATCH;
2538 dcbrush.SetColour( m_activefill.GetColour() );
2539 dcbrush.SetStyle( style );
2542 style = wxBRUSHSTYLE_FDIAGONAL_HATCH;
2543 dcbrush.SetColour( m_activefill.GetColour() );
2544 dcbrush.SetStyle( style );
2547 style = wxBRUSHSTYLE_CROSS_HATCH;
2548 dcbrush.SetColour( m_activefill.GetColour() );
2549 dcbrush.SetStyle( style );
2552 style = wxBRUSHSTYLE_HORIZONTAL_HATCH;
2553 dcbrush.SetColour( m_activefill.GetColour() );
2554 dcbrush.SetStyle( style );
2557 style = wxBRUSHSTYLE_VERTICAL_HATCH;
2558 dcbrush.SetColour( m_activefill.GetColour() );
2559 dcbrush.SetStyle( style );
2562 style = wxBRUSHSTYLE_SOLID;
2563 dcbrush.SetColour( m_activefill.GetColour() );
2564 dcbrush.SetStyle( style );
2567 m_renderDC->SetBrush( dcbrush );
2568 m_renderDC->SetTextBackground( m_activefill.GetColour() );
2574 switch( m_activefill.GetStyle() )
2577 style = wxBRUSHSTYLE_STIPPLE;
2578 dcbrush.SetColour( m_activefill.GetColour() );
2579 dcbrush.SetStipple( m_activefill.GetStipple() );
2580 dcbrush.SetStyle( style );
2586 wxBitmap noMask = m_activefill.GetStipple();
2587 noMask.SetMask( NULL );
2588 style = wxBRUSHSTYLE_STIPPLE;
2589 dcbrush.SetColour( m_activefill.GetColour() );
2590 dcbrush.SetStipple( noMask );
2594 style = wxBRUSHSTYLE_STIPPLE_MASK_OPAQUE;
2595 dcbrush.SetColour( m_activefill.GetColour() );
2596 dcbrush.SetStipple( m_activefill.GetStipple() );
2598 dcbrush.SetStyle( style );
2600 default: style = wxBRUSHSTYLE_SOLID;
2601 dcbrush.SetColour( m_activefill.GetColour() );
2602 dcbrush.SetStyle( style );
2605 m_renderDC->SetBrush( dcbrush );
2606 m_renderDC->SetTextBackground( m_activefill.GetColour() );
2611 bool a2dDcContext::SetLogicalFunction( wxRasterOperationMode
function )
2625 m_renderDC->SetLogicalFunction(
function );
2629 void a2dDcContext::SetDrawStyle(
a2dDrawStyle drawstyle )
2631 m_drawstyle = drawstyle;
2639 m_renderDC->SetLogicalFunction( wxINVERT );
2646 m_renderDC->SetLogicalFunction( wxCOPY );
2653 m_renderDC->SetLogicalFunction( wxCOPY );
2660 m_renderDC->SetLogicalFunction( wxINVERT );
2665 m_renderDC->SetLogicalFunction( wxCOPY );
2674 void a2dDcContext::Clip( wxDouble x, wxDouble y, wxDouble w, wxDouble h )
2678 wxPoint trpoints[4];
2681 m_usertodevice.TransformPoint( x, y, dx, dy );
2682 trpoints[0] = wxPoint( dx, dy );
2683 m_usertodevice.TransformPoint( x, y + h, dx, dy );
2684 trpoints[1] = wxPoint( dx, dy );
2685 m_usertodevice.TransformPoint( x + w, y + h, dx, dy );
2686 trpoints[2] = wxPoint( dx, dy );
2687 m_usertodevice.TransformPoint( x + w, y, dx, dy );
2688 trpoints[3] = wxPoint( dx, dy );
2690 double xmin = trpoints[0].x;
2691 double ymin = trpoints[0].y;
2692 double xmax = trpoints[0].x;
2693 double ymax = trpoints[0].y;
2694 for (
int i = 1; i < 4; i ++ )
2696 xmin = wxMin( xmin, trpoints[i].x );
2697 xmax = wxMax( xmax, trpoints[i].x );
2698 ymin = wxMin( ymin, trpoints[i].y );
2699 ymax = wxMax( ymax, trpoints[i].y );
2701 wxRect cliprect = wxRect( xmin, ymin, xmax - xmin, ymax - ymin );
2702 m_clipboxdev = cliprect;
2703 wxRegion clip( cliprect );
2704 m_renderDC->DestroyClippingRegion();
2705 #if wxCHECK_VERSION(2,9,0)
2706 m_renderDC->SetDeviceClippingRegion( clip );
2708 m_renderDC->SetClippingRegion( clip );
2712 void a2dDcContext::ResetClip()
2715 m_renderDC->DestroyClippingRegion();
2716 m_clipboxdev = wxRect( 0, 0, m_width, m_height );
2719 #if wxCHECK_VERSION(2,9,0)
2720 void a2dDcContext::DrawBitmap(
const wxGraphicsBitmap& bmp, wxDouble x, wxDouble y, wxDouble w, wxDouble h )
2722 void a2dDcContext::DrawGraphicsBitmap(
const wxGraphicsBitmap& bmp, wxDouble x, wxDouble y, wxDouble w, wxDouble h )
2725 a2dBitmapData* data =
static_cast<a2dBitmapData*
>( bmp.GetRefData() );
2726 wxImage image = data->GetImage();
2728 if ( w == 0 || h == 0 )
2731 wxASSERT_MSG( m_renderDC, wxT(
"no renderDc set" ) );
2733 wxPoint centr( (
int ) w / 2, (
int ) h / 2 );
2736 double angle = m_usertodevice.GetRotation();
2738 if ( fabs( angle ) > 0.5 )
2740 image.SetMask(
true );
2742 image = image.Rotate( angle / 180.0 *
wxPI, centr,
true, NULL );
2744 image = image.Rotate( -angle / 180.0 *
wxPI, centr,
true, NULL );
2747 int devicew, deviceh;
2749 devicew = m_usertodevice.TransformDistance( w );
2750 deviceh = fabs( m_usertodevice.TransformDistance( h ) );
2753 m_usertodevice.TransformPoint( x, y, hx, hy );
2754 int devicex = ( int ) ( hx - devicew / 2.0 );
2755 int devicey = ( int ) ( hy - deviceh / 2.0 );
2758 bool imgHasMask = image.HasMask();
2760 if ( devicew == 0 || deviceh == 0 )
2763 double sx = image.GetWidth() / ( double ) devicew;
2764 double sy = image.GetHeight() / ( double ) deviceh;
2767 wxRect clipped = m_clipboxdev;
2768 clipped.Intersect( wxRect( devicex, devicey, devicew, deviceh ) );
2769 double deviceClipX = clipped.GetX();
2770 double deviceClipY = clipped.GetY();
2771 double deviceClipW = clipped.GetWidth();
2772 double deviceClipH = clipped.GetHeight();
2774 clipped.SetX( ( clipped.GetX() - devicex ) * sx );
2775 clipped.SetY( ( clipped.GetY() - devicey ) * sy );
2776 clipped.SetWidth( clipped.GetWidth() * sx );
2777 clipped.SetHeight( clipped.GetHeight() * sy );
2780 if ( clipped.GetWidth() < 1 || clipped.GetHeight() < 1 )
2782 m_renderDC->DrawRectangle( devicex, devicey, devicew, deviceh );
2786 if ( deviceClipW != devicew || deviceClipH != deviceh )
2787 image = image.GetSubImage( clipped );
2791 image.Rescale( deviceClipW, deviceClipH );
2794 wxBitmap Bitmap( image );
2798 wxMemoryDC MemoryDc;
2799 MemoryDc.SelectObject( Bitmap );
2801 m_renderDC->Blit( deviceClipX, deviceClipY, deviceClipW, deviceClipH, &MemoryDc, 0, 0, wxCOPY, imgHasMask );
2805 m_renderDC->DrawRectangle( devicex, devicey, devicew, deviceh );
2809 void a2dDcContext::DrawVpath(
const a2dVpath* path )
2811 unsigned int segments = 0;
2815 for ( i = 0; i < path->size(); i++ )
2818 switch ( seg->GetType() )
2835 double radius, center_x, center_y, beginrad, midrad, endrad, phit;
2837 if ( cseg->
CalcR( path->operator[]( i ? i - 1 : 0 ), radius, center_x, center_y, beginrad, midrad, endrad, phit ) )
2840 unsigned int circlesegments;
2841 double radiusDev = m_usertodevice.TransformDistance( radius );
2842 Aberration( m_displayaberration, phit, radiusDev , dphi, circlesegments );
2843 segments += circlesegments + 1;
2856 m_cpointsDouble.resize( segments * 2 );
2861 bool nostrokeparts =
false;
2864 for ( i = 0; i < path->size(); i++ )
2867 switch ( seg->GetType() )
2872 m_usertodevice.TransformPoint( seg->m_x1, seg->m_y1, x, y );
2873 m_cpointsDouble[count].x = x;
2874 m_cpointsDouble[count].y = y;
2885 m_usertodevice.TransformPoint( seg->m_x1, seg->m_y1, x, y );
2886 m_cpointsDouble[count].x = x;
2887 m_cpointsDouble[count].y = y;
2891 m_usertodevice.TransformPoint( seg->m_x1, seg->m_y1, x, y );
2892 m_cpointsDouble[count].x = x;
2893 m_cpointsDouble[count].y = y;
2895 nostrokeparts =
true;
2899 nostrokeparts =
true;
2904 double xwl = path->operator[]( i ? i - 1 : 0 )->m_x1;
2905 double ywl = path->operator[]( i ? i - 1 : 0 )->m_y1;
2912 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 );
2913 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 );
2914 m_usertodevice.TransformPoint( xw, yw, x, y );
2915 m_cpointsDouble[count].x = x;
2916 m_cpointsDouble[count].y = y;
2924 nostrokeparts =
true;
2929 double xwl = path->operator[]( i ? i - 1 : 0 )->m_x1;
2930 double ywl = path->operator[]( i ? i - 1 : 0 )->m_y1;
2937 xw = xwl * pow( 1 - t, 2 ) + cseg.
m_x2 * ( 1 - t ) * t * 2 + cseg.
m_x1 * pow( t, 2 );
2938 yw = ywl * pow( 1 - t, 2 ) + cseg.
m_y2 * ( 1 - t ) * t * 2 + cseg.
m_y1 * pow( t, 2 );
2939 m_usertodevice.TransformPoint( xw, yw, x, y );
2940 m_cpointsDouble[count].x = x;
2941 m_cpointsDouble[count].y = y;
2949 nostrokeparts =
true;
2954 double radius, center_x, center_y, beginrad, midrad, endrad, phit;
2956 if ( cseg->
CalcR( path->operator[]( i ? i - 1 : 0 ), radius, center_x, center_y, beginrad, midrad, endrad, phit ) )
2959 unsigned int segments;
2960 double radiusDev = m_usertodevice.TransformDistance( radius );
2961 Aberration( m_displayaberration, phit, radiusDev , dphi, segments );
2963 double theta = beginrad;
2967 for ( step = 0; step < segments + 1; step++ )
2969 m_usertodevice.TransformPoint( center_x + radius * cos ( theta ), center_y + radius * sin ( theta ), x, y );
2970 m_cpointsDouble[count].x = x;
2971 m_cpointsDouble[count].y = y;
2973 theta = theta + dphi;
2979 m_usertodevice.TransformPoint( cseg->
m_x1, cseg->
m_y1, x, y );
2980 m_cpointsDouble[count].x = x;
2981 m_cpointsDouble[count].y = y;
2992 DeviceDrawLines( count,
false );
3002 DeviceDrawPolygon( count,
false, wxODDEVEN_RULE );
3003 m_activestroke = stroke;
3004 nostrokeparts =
true;
3008 DeviceDrawPolygon( count,
false, wxODDEVEN_RULE );
3014 else if ( i == path->size() - 1 )
3016 DeviceDrawLines( count,
false );
3020 if ( nostrokeparts )
3024 nostrokeparts =
false;
3026 double lastmovex = 0;
3027 double lastmovey = 0;
3029 for ( i = 0; i < path->size(); i++ )
3032 switch ( seg->GetType() )
3037 m_usertodevice.TransformPoint( seg->m_x1, seg->m_y1, x, y );
3038 m_cpointsDouble[count].x = x;
3039 m_cpointsDouble[count].y = y;
3040 lastmovex = m_cpointsDouble[count].x;
3041 lastmovey = m_cpointsDouble[count].y;
3052 m_usertodevice.TransformPoint( seg->m_x1, seg->m_y1, x, y );
3053 m_cpointsDouble[count].x = x;
3054 m_cpointsDouble[count].y = y;
3064 m_usertodevice.TransformPoint( seg->m_x1, seg->m_y1, x, y );
3065 m_cpointsDouble[count].x = x;
3066 m_cpointsDouble[count].y = y;
3072 nostrokeparts =
true;
3080 double xwl = path->operator[]( i ? i - 1 : 0 )->m_x1;
3081 double ywl = path->operator[]( i ? i - 1 : 0 )->m_y1;
3088 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 );
3089 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 );
3090 m_usertodevice.TransformPoint( xw, yw, x, y );
3091 m_cpointsDouble[count].x = x;
3092 m_cpointsDouble[count].y = y;
3103 double xwl = path->operator[]( i ? i - 1 : 0 )->m_x1;
3104 double ywl = path->operator[]( i ? i - 1 : 0 )->m_y1;
3111 xw = xwl * pow( 1 - t, 2 ) + cseg.
m_x2 * ( 1 - t ) * t * 2 + cseg.
m_x1 * pow( t, 2 );
3112 yw = ywl * pow( 1 - t, 2 ) + cseg.
m_y2 * ( 1 - t ) * t * 2 + cseg.
m_y1 * pow( t, 2 );
3113 m_usertodevice.TransformPoint( xw, yw, x, y );
3114 m_cpointsDouble[count].x = x;
3115 m_cpointsDouble[count].y = y;
3126 double radius, center_x, center_y, beginrad, midrad, endrad, phit;
3128 if ( cseg->
CalcR( path->operator[]( i ? i - 1 : 0 ), radius, center_x, center_y, beginrad, midrad, endrad, phit ) )
3131 unsigned int segments;
3132 double radiusDev = m_usertodevice.TransformDistance( radius );
3133 Aberration( m_displayaberration, phit, radiusDev , dphi, segments );
3135 double theta = beginrad;
3139 for ( step = 0; step < segments + 1; step++ )
3141 m_usertodevice.TransformPoint( center_x + radius * cos ( theta ), center_y + radius * sin ( theta ), x, y );
3142 m_cpointsDouble[count].x = x;
3143 m_cpointsDouble[count].y = y;
3145 theta = theta + dphi;
3151 m_usertodevice.TransformPoint( cseg->
m_x1, cseg->
m_y1, x, y );
3152 m_cpointsDouble[count].x = x;
3153 m_cpointsDouble[count].y = y;
3163 if ( move || nostrokeparts )
3165 DeviceDrawLines( count,
false );
3167 nostrokeparts =
false;
3174 m_cpointsDouble[count].x = lastmovex;
3175 m_cpointsDouble[count].y = lastmovey;
3178 DeviceDrawLines( count,
false );
3179 nostrokeparts =
false;
3183 else if ( i == path->size() )
3185 DeviceDrawLines( count,
false );
3193 void a2dDcContext::DeviceDrawPolygon(
unsigned int n,
bool spline, wxPolygonFillMode fillStyle )
3195 wxASSERT_MSG( m_renderDC, wxT(
"no renderDc set" ) );
3197 wxPoint* int_cpts = _convertToIntPointCache( n, &m_cpointsDouble[0] );
3200 if ( IsStrokeOnly() )
3205 m_renderDC->DrawLines( n, int_cpts );
3208 m_renderDC->DrawLine( int_cpts[0].x, int_cpts[0].y, int_cpts[n - 1].x, int_cpts[n - 1].y );
3214 #if defined(__WXMSW__)
3215 #if wxCHECK_VERSION(2,9,0)
3216 wxMSWDCImpl* dcimpl =
wxStaticCast( m_renderDC->GetImpl(), wxMSWDCImpl );
3217 WXHDC hdc = dcimpl->GetHDC();
3219 WXHDC hdc = m_renderDC->GetHDC();
3221 SetPolyFillMode( (
struct HDC__* ) hdc, fillStyle == wxODDEVEN_RULE ? ALTERNATE : WINDING );
3224 ( void )Polygon( (
struct HDC__* ) hdc, ( POINT* )int_cpts, n );
3227 m_renderDC->DrawPolygon( n, int_cpts, 0, 0, fillStyle );
3234 FillPolygon( n, &m_cpointsDouble[0] );
3238 m_renderDC->DrawLines( n, int_cpts );
3239 m_renderDC->DrawLine( int_cpts[0].x, int_cpts[0].y, int_cpts[n - 1].x, int_cpts[n - 1].y );
3244 #if defined(__WXMSW__)
3245 m_renderDC->SetTextForeground( *wxBLACK );
3246 m_renderDC->SetTextBackground( *wxWHITE );
3247 m_renderDC->SetLogicalFunction( wxAND_INVERT );
3250 COLORREF colFgOld, colBgOld;
3252 #if wxCHECK_VERSION(2,9,0)
3253 wxMSWDCImpl* dcimpl =
wxStaticCast( m_renderDC->GetImpl(), wxMSWDCImpl );
3254 WXHDC hdc = dcimpl->GetHDC();
3256 WXHDC hdc = m_renderDC->GetHDC();
3259 colBgOld = ::GetBkColor( (
struct HDC__* ) hdc );
3260 colFgOld = ::GetTextColor( (
struct HDC__* ) hdc );
3264 ::SetBkColor( (
struct HDC__* ) hdc, m_renderDC->GetTextForeground().GetPixel() );
3267 ::SetTextColor( (
struct HDC__* ) hdc, m_renderDC->GetTextBackground().GetPixel() );
3269 int prev = SetPolyFillMode( (
struct HDC__* ) hdc, WINDING );
3270 ( void )Polygon( (
struct HDC__* ) hdc, ( POINT* )int_cpts, n );
3275 m_renderDC->SetTextForeground( *wxBLACK );
3277 m_renderDC->SetTextBackground( m_activefill.GetColour() );
3278 m_renderDC->SetLogicalFunction( wxOR );
3282 ::SetBkColor( (
struct HDC__* ) hdc, m_renderDC->GetTextForeground().GetPixel() );
3285 ::SetTextColor( (
struct HDC__* ) hdc, m_renderDC->GetTextBackground().GetPixel() );
3286 ( void )Polygon( (
struct HDC__* ) hdc, ( POINT* )int_cpts, n );
3287 SetPolyFillMode( ( struct HDC__* ) hdc, prev );
3290 ::SetBkMode( ( struct HDC__* ) hdc, TRANSPARENT );
3291 ::SetTextColor( ( struct HDC__* ) hdc, colFgOld );
3292 ::SetBkColor( ( struct HDC__* ) hdc, colBgOld );
3294 m_renderDC->SetLogicalFunction( wxCOPY );
3295 m_renderDC->SetTextForeground( m_activestroke.GetColour() );
3296 m_renderDC->SetTextBackground( m_activefill.GetColour() );
3301 m_renderDC->DrawLines( n, int_cpts );
3302 m_renderDC->DrawLine( int_cpts[0].x, int_cpts[0].y, int_cpts[n - 1].x, int_cpts[n - 1].y );
3307 wxPen dcpen( m_activestroke.
GetColour(), ( int ) m_activestroke.
GetWidth(), wxSOLID );
3310 m_renderDC->SetPen( dcpen );
3312 m_renderDC->SetTextForeground( *wxBLACK );
3313 m_renderDC->SetTextBackground( *wxWHITE );
3314 m_renderDC->SetLogicalFunction( wxAND_INVERT );
3316 m_renderDC->DrawPolygon( n, int_cpts, 0, 0, fillStyle );
3320 m_renderDC->SetTextForeground( *wxBLACK );
3322 m_renderDC->SetTextBackground( m_activefill.GetColour() );
3323 m_renderDC->SetLogicalFunction( wxOR );
3325 SetStroke( m_activestroke );
3326 m_renderDC->DrawPolygon( n, int_cpts, 0, 0, fillStyle );
3327 m_renderDC->SetLogicalFunction( wxCOPY );
3328 m_renderDC->SetTextForeground( m_activestroke.
GetColour() );
3329 m_renderDC->SetTextBackground( m_activefill.GetColour() );
3334 m_renderDC->DrawLines( n, int_cpts );
3335 m_renderDC->DrawLine( int_cpts[0].x, int_cpts[0].y, int_cpts[n - 1].x, int_cpts[n - 1].y );
3344 m_renderDC->SetTextForeground( m_activefill.GetColour() );
3345 m_renderDC->SetTextBackground( m_activefill.GetColour2() );
3346 m_renderDC->DrawPolygon( n, int_cpts, 0, 0, fillStyle );
3347 m_renderDC->SetTextForeground( m_activestroke.
GetColour() );
3348 m_renderDC->SetTextBackground( m_activefill.GetColour() );
3352 wxBrush dcbrush( m_activefill.GetColour2() );
3353 wxBrush cur_dcbrush = m_renderDC->GetBrush();
3354 m_renderDC->SetBrush( dcbrush );
3355 m_renderDC->DrawPolygon( n, int_cpts, 0, 0, fillStyle );
3356 m_renderDC->SetBrush( cur_dcbrush );
3357 m_renderDC->DrawPolygon( n, int_cpts, 0, 0, fillStyle );
3361 #if defined(__WXMSW__)
3367 m_renderDC->DrawPolygon( n, int_cpts, 0, 0, fillStyle );
3370 m_renderDC->DrawPolygon( n, int_cpts, 0, 0, fillStyle );
3374 if ( IsStroked() && m_activestroke.GetType() == a2dSTROKE_OBJECT )
3379 wxRealPoint* copy =
new wxRealPoint[n + 1];
3380 memcpy( copy, &m_cpointsDouble[0], n *
sizeof( wxRealPoint ) );
3381 copy[n].x = m_cpointsDouble[0].x;
3382 copy[n].y = m_cpointsDouble[0].y;
3389 void a2dDcContext::DeviceDrawLines(
unsigned int n,
bool spline )
3391 wxASSERT_MSG( m_renderDC, wxT(
"no renderDc set" ) );
3393 wxPoint* int_cpts = _convertToIntPointCache( n, &m_cpointsDouble[0] );
3396 m_renderDC->DrawCircle( int_cpts[0].x, int_cpts[0].y, 2 );
3400 m_renderDC->DrawLines( n, int_cpts );
3401 #if defined(__WXMSW__)
3404 if ( n > 1 && m_renderDC->GetPen().GetWidth() == 1 )
3405 m_renderDC->DrawPoint( int_cpts[n - 1].x, int_cpts[n - 1].y );
3410 void a2dDcContext::DeviceDrawLine(
double x1,
double y1,
double x2,
double y2 )
3412 wxASSERT_MSG( m_renderDC, wxT(
"no renderDc set" ) );
3417 void a2dDcContext::DeviceDrawHorizontalLine(
int x1,
int y1,
int x2,
bool use_stroke_color )
3419 wxASSERT_MSG( m_renderDC, wxT(
"no renderDc set" ) );
3422 if ( use_stroke_color )
3424 wxPen pen = m_renderDC->GetPen();
3425 color = wxColour( m_colour1redStroke, m_colour1greenStroke, m_colour1blueStroke, m_StrokeOpacityCol1 );
3426 m_renderDC->SetPen( wxPen( color ) );
3428 m_renderDC->SetPen( pen );
3436 void a2dDcContext::DeviceDrawVerticalLine(
int x1,
int y1,
int y2,
bool use_stroke_color )
3438 wxASSERT_MSG( m_renderDC, wxT(
"no renderDc set" ) );
3441 if ( use_stroke_color )
3443 wxPen pen = m_renderDC->GetPen();
3444 color = wxColour( m_colour1redStroke, m_colour1greenStroke, m_colour1blueStroke, m_StrokeOpacityCol1 );
3445 m_renderDC->SetPen( wxPen( color ) );
3447 m_renderDC->SetPen( pen );
3455 void a2dDcContext::DeviceDrawPixel(
int x1,
int y1,
unsigned char r,
unsigned char g,
unsigned char b ,
unsigned char a )
3457 #if defined(__WXMSW__)
3458 #if wxCHECK_VERSION(2,9,0)
3459 wxMSWDCImpl* dcimpl =
wxStaticCast( m_renderDC->GetImpl(), wxMSWDCImpl );
3460 WXHDC hdc = dcimpl->GetHDC();
3462 WXHDC hdc = m_renderDC->GetHDC();
3464 ::SetPixelV( (
struct HDC__* )hdc, x1, y1, RGB( r, g, b ) );
3467 #if wxCHECK_VERSION(2,9,1)
3468 wxWindowDCImpl* dcimpl =
wxStaticCast( m_renderDC->GetImpl(), wxWindowDCImpl );
3469 GdkWindow* gtkwin = dcimpl->GetGDKWindow();
3471 gdk_draw_point( gtkwin, dcimpl->m_penGC, x1, y1 );
3473 wxColour col( r, g, b );
3474 col.CalcPixel( ( ( wxWindowDC* )m_renderDC )->m_cmap );
3475 gdk_gc_set_foreground( ( ( wxWindowDC* )m_renderDC )->m_penGC, col.GetColor() );
3476 gdk_draw_point( ( ( wxWindowDC* ) m_renderDC )->m_window, ( ( wxWindowDC* )m_renderDC )->m_penGC, x1, y1 );
3484 void a2dDcContext::DeviceDrawBitmap(
const wxBitmap& bmp,
double x,
double y,
bool useMask )
3486 wxASSERT_MSG( m_renderDC, wxT(
"no renderDc set" ) );
3489 m_renderDC->DrawRectangle(
Round( x ),
Round( y ), bmp.GetWidth(), bmp.GetHeight() );
3492 m_renderDC->DrawBitmap( bmp,
Round( x ),
Round( y ), useMask );
3495 void a2dDcContext::DrawCharDc( wxChar c )
3500 double angle = m_usertodevice.GetRotation();
3501 m_usertodevice.TransformPoint( x, y + m_a2dfont.GetLineHeight(), dx, dy );
3502 m_renderDC->DrawRotatedText( wxString( c ), (
int ) dx, (
int ) dy, -angle );
3505 void a2dDcContext::DrawTextDc(
const wxString& text,
double x,
double y )
3507 wxASSERT_MSG( m_renderDC, wxT(
"no renderDc set" ) );
3510 unsigned int fontsize;
3511 double dx = m_usertodevice.GetValue( 1, 0 );
3512 double dy = m_usertodevice.GetValue( 1, 1 );
3513 fontsize = (
unsigned int ) fabs( m_a2dfont.GetSize() * sqrt( dx * dx + dy * dy ) );
3516 m_a2dfont.GetFont().SetPointSize( fontsize );
3518 m_renderDC->SetFont( m_a2dfont.GetFont() );
3519 m_renderDC->SetBackgroundMode( wxTRANSPARENT );
3520 m_renderDC->SetTextForeground( m_activestroke.
GetColour() );
3522 DrawTextGeneric( text, x, y, (
void ( a2dContext::* )( wxChar ) ) & a2dDcContext::DrawCharDc );
3525 #if wxART2D_USE_FREETYPE
3526 extern FT_Library g_freetypeLibrary;
3539 static void a2dSpanFuncGray(
int y,
int count, FT_Span* spans,
a2dSpanData* user )
3541 unsigned int alpha, invalpha, len;
3543 unsigned int r, g, b, rpm, gpm, bpm;
3544 r = user->colour.Red();
3545 g = user->colour.Green();
3546 b = user->colour.Blue();
3548 unsigned char* buf, *buf2;
3549 buf = user->buf + ( user->ymax - y ) * user->stride - user->xmin * 3;
3552 buf2 = buf + spans->x * 3;
3554 alpha = spans->coverage;
3579 invalpha = 255 - alpha;
3585 buf2[0] = ( buf2[0] * invalpha + rpm ) / 255;
3586 buf2[1] = ( buf2[1] * invalpha + gpm ) / 255;
3587 buf2[2] = ( buf2[2] * invalpha + bpm ) / 255;
3589 buf2[0] = ( buf2[0] * invalpha + bpm ) / 255;
3590 buf2[1] = ( buf2[1] * invalpha + gpm ) / 255;
3591 buf2[2] = ( buf2[2] * invalpha + rpm ) / 255;
3603 void a2dDcContext::DrawCharFreetype( wxChar c )
3605 #if wxART2D_USE_FREETYPE
3608 m_usertodevice.TransformPoint( 0.0, m_a2dfont.GetDescent(), dx, dy );
3611 const a2dGlyph* a2dglyph = m_a2dfont.GetGlyphFreetype( c );
3615 if ( FT_Glyph_Copy( a2dglyph->m_glyph, &image ) != 0 )
3624 FT_Matrix trans_matrix;
3625 trans_matrix.xx = ( FT_Fixed ) ( glyphToDevice.
GetValue( 0, 0 ) * 0x10000 );
3626 trans_matrix.xy = ( FT_Fixed ) ( glyphToDevice.
GetValue( 1, 0 ) * 0x10000 );
3627 trans_matrix.yx = ( FT_Fixed ) ( -glyphToDevice.
GetValue( 0, 1 ) * 0x10000 );
3628 trans_matrix.yy = ( FT_Fixed ) ( -glyphToDevice.
GetValue( 1, 1 ) * 0x10000 );
3630 vec.x = ( int ) ( ( dx - (
int ) dx ) * 64.0 );
3631 vec.y = ( int ) ( ( dy - (
int ) dy ) * -64.0 );
3632 if ( FT_Glyph_Transform( image, &trans_matrix, &vec ) != 0 )
3634 wxFAIL_MSG( _(
"glyph transform wrong" ) );
3635 FT_Done_Glyph( image );
3641 FT_Glyph_Get_CBox( image, ft_glyph_bbox_pixels, &bbox );
3644 if ( m_clipboxdev.GetLeft() > ( int ) dx + bbox.xMin )
3645 bbox.xMin = m_clipboxdev.GetLeft() - ( int ) dx;
3646 if ( m_clipboxdev.GetRight() < ( int ) dx + bbox.xMax )
3647 bbox.xMax = m_clipboxdev.GetRight() - ( int ) dx;
3649 if ( m_clipboxdev.GetTop() >= ( int ) dy - bbox.yMax )
3650 bbox.yMax = ( int ) dy - m_clipboxdev.GetTop();
3651 if ( m_clipboxdev.GetBottom() < ( int ) dy - bbox.yMin )
3652 bbox.yMin = ( int ) dy - m_clipboxdev.GetBottom();
3655 if ( bbox.xMax - bbox.xMin <= 0 || bbox.yMax - bbox.yMin <= 0 )
3657 FT_Done_Glyph( image );
3661 int px = ( int ) dx + bbox.xMin;
3662 int py = (
int ) dy - bbox.yMax;
3663 int w = bbox.xMax - bbox.xMin + 1;
3664 int h = bbox.yMax - bbox.yMin + 1;
3667 wxRect absarea2( px, py, w, h );
3668 wxBitmap sub_bitmap = m_buffer->GetSubBitmap( absarea2 );
3670 #if defined(__WXMSW__)
3672 bi.bmiHeader.biSize =
sizeof( bi.bmiHeader );
3673 bi.bmiHeader.biWidth = w;
3674 bi.bmiHeader.biHeight = -h;
3675 bi.bmiHeader.biPlanes = 1;
3676 bi.bmiHeader.biBitCount = 24;
3677 bi.bmiHeader.biCompression = BI_RGB;
3678 bi.bmiHeader.biSizeImage = 0;
3679 bi.bmiHeader.biClrUsed = 0;
3680 bi.bmiHeader.biClrImportant = 0;
3682 HBITMAP hbitmap = ( HBITMAP ) sub_bitmap.GetHBITMAP();
3683 HDC hdc = ::GetDC( NULL );
3684 HDC memdc = ::CreateCompatibleDC( hdc );
3685 unsigned char* buf = (
unsigned char* ) malloc( ( 3 * w +
sizeof( DWORD ) - 1 ) /
sizeof( DWORD ) *
sizeof( DWORD ) * h );
3686 ::GetDIBits( memdc, hbitmap, 0, h, buf, &bi, DIB_RGB_COLORS );
3687 #else // defined( __WXMSW__ )
3688 wxImage wximage( sub_bitmap.ConvertToImage() );
3689 #endif // defined( __WXMSW__ )
3692 if ( image->format == FT_GLYPH_FORMAT_OUTLINE )
3695 spandata.colour = m_activestroke.
GetColour();
3696 spandata.xmin = bbox.xMin;
3697 spandata.ymax = bbox.yMax;
3698 spandata.stride = w * 3;
3699 #if defined(__WXMSW__)
3701 spandata.stride = ( spandata.stride +
sizeof( DWORD ) - 1 ) /
sizeof( DWORD ) *
sizeof( DWORD );
3703 #else // defined( __WXMSW__ )
3704 spandata.buf = wximage.GetData();
3705 #endif // defined( __WXMSW__ )
3706 wxASSERT( spandata.buf != NULL );
3708 FT_Raster_Params params;
3709 params.target = NULL;
3710 params.flags = FT_RASTER_FLAG_AA | FT_RASTER_FLAG_DIRECT | FT_RASTER_FLAG_CLIP;
3711 params.gray_spans = ( FT_SpanFunc ) & a2dSpanFuncGray;
3712 params.black_spans = NULL;
3713 params.bit_test = ( FT_Raster_BitTest_Func ) NULL;
3714 params.bit_set = ( FT_Raster_BitSet_Func ) NULL;
3715 params.user = &spandata;
3716 params.clip_box = bbox;
3718 FT_Outline& outline = ( ( FT_OutlineGlyph ) image )->outline;
3719 if ( FT_Outline_Render( g_freetypeLibrary, &outline, ¶ms ) == 0 )
3721 #if defined( __WXMSW__ )
3722 ::SetDIBits( memdc, hbitmap, 0, h, buf, &bi, DIB_RGB_COLORS );
3723 #else // defined( __WXMSW__ )
3724 wxBitmap sub_bitmap( wximage );
3725 #endif // defined( __WXMSW__ )
3726 DeviceDrawBitmap( sub_bitmap, px, py,
false );
3730 wxFAIL_MSG( _(
"Non vector fonts are not supported" ) );
3732 #if defined(__WXMSW__)
3734 ::DeleteDC( memdc );
3735 ::ReleaseDC( NULL, hdc );
3736 #endif // defined( __WXMSW__ )
3738 FT_Done_Glyph( image );
3739 #else // wxART2D_USE_FREETYPE
3740 DrawCharUnknown( c );
3741 #endif // wxART2D_USE_FREETYPE
3758 IMPLEMENT_DYNAMIC_CLASS( a2dRenderer, wxGraphicsRenderer )
3761 wxGraphicsContext* a2dRenderer::CreateContext( const wxWindowDC& dc )
3763 wxFAIL_MSG( wxT(
"only drawable buffers for a2dContext" ) );
3767 wxGraphicsContext* a2dRenderer::CreateContext(
const wxMemoryDC& dc )
3770 wxFAIL_MSG( wxT(
"only drawable buffers for a2dContext" ) );
3774 wxGraphicsContext* a2dRenderer::CreateContext( wxMemoryDC* dc, wxBitmap* drawable )
3776 return new a2dDcContext(
this, dc, drawable );
3779 wxGraphicsContext* a2dRenderer::CreateContextFromNativeContext(
void* context )
3781 wxFAIL_MSG( wxT(
"only drawable buffers for a2dContext" ) );
3785 #if wxCHECK_VERSION(2, 9, 0)
3786 #if wxUSE_PRINTING_ARCHITECTURE
3787 wxGraphicsContext* a2dRenderer::CreateContext(
const wxPrinterDC& dc )
3789 wxFAIL_MSG( wxT(
"only drawable buffers for a2dContext" ) );
3793 wxGraphicsContext* a2dRenderer::CreateContext(
const wxEnhMetaFileDC& dc )
3795 wxFAIL_MSG( wxT(
"only drawable buffers for a2dContext" ) );
3800 #endif //wxCHECK_VERSION(2, 9, 0)
3802 wxGraphicsContext* a2dRenderer::CreateContextFromNativeWindow(
void* window )
3804 wxFAIL_MSG( wxT(
"only drawable buffers for a2dContext" ) );
3808 wxGraphicsContext* a2dRenderer::CreateMeasuringContext()
3814 wxGraphicsContext* a2dRenderer::CreateContext( wxWindow* window )
3816 wxFAIL_MSG( wxT(
"only drawable buffers for a2dContext" ) );
3822 wxGraphicsPath a2dRenderer::CreatePath()
3824 wxGraphicsPath path;
3825 path.SetRefData(
new a2dPathData(
this ) );
3832 wxGraphicsMatrix a2dRenderer::CreateMatrix( wxDouble a, wxDouble b, wxDouble c, wxDouble d,
3833 wxDouble tx, wxDouble ty )
3837 a2dMatrixData* data =
new a2dMatrixData(
this );
3838 data->Set( a, b, c, d, tx, ty ) ;
3839 m.SetRefData( data );
3843 wxGraphicsPen a2dRenderer::CreatePen(
const wxPen& pen )
3845 if ( !pen.Ok() || pen.GetStyle() == wxTRANSPARENT )
3846 return wxNullGraphicsPen;
3850 p.SetRefData(
new a2dStrokeData(
this, pen ) );
3855 wxGraphicsBrush a2dRenderer::CreateBrush(
const wxBrush& brush )
3857 if ( !brush.Ok() || brush.GetStyle() == wxTRANSPARENT )
3858 return wxNullGraphicsBrush;
3862 p.SetRefData(
new a2dFillData(
this, brush ) );
3867 wxGraphicsPen a2dRenderer::CreateStroke(
const a2dStroke& stroke )
3874 p.SetRefData(
new a2dStrokeData(
this, stroke ) );
3879 wxGraphicsBrush a2dRenderer::CreateFill(
const a2dFill& fill )
3886 p.SetRefData(
new a2dFillData(
this, fill ) );
3891 #if wxCHECK_VERSION(2, 9, 1)
3892 wxGraphicsBrush a2dRenderer::CreateLinearGradientBrush( wxDouble x1, wxDouble y1,
3893 wxDouble x2, wxDouble y2,
3894 const wxGraphicsGradientStops& stops )
3897 a2dFillData* d =
new a2dFillData(
this );
3898 d->CreateLinearGradientBrush( x1, y1, x2, y2, stops );
3903 wxGraphicsBrush a2dRenderer::CreateRadialGradientBrush( wxDouble xo, wxDouble yo,
3904 wxDouble xc, wxDouble yc,
3906 const wxGraphicsGradientStops& stops )
3909 a2dFillData* d =
new a2dFillData(
this );
3910 d->CreateRadialGradientBrush( xo, yo, xc, yc, radius, stops );
3915 #else //wxCHECK_VERSION(2, 9, 1)
3918 wxGraphicsBrush a2dRenderer::CreateLinearGradientBrush( wxDouble x1, wxDouble y1, wxDouble x2, wxDouble y2,
3919 const wxColour& c1,
const wxColour& c2 )
3922 a2dFillData* d =
new a2dFillData(
this );
3923 d->CreateLinearGradientBrush( x1, y1, x2, y2, c1, c2 );
3930 wxGraphicsBrush a2dRenderer::CreateRadialGradientBrush( wxDouble xo, wxDouble yo, wxDouble xc, wxDouble yc, wxDouble radius,
3931 const wxColour& oColor,
const wxColour& cColor )
3934 a2dFillData* d =
new a2dFillData(
this );
3935 d->CreateRadialGradientBrush( xo, yo, xc, yc, radius, oColor, cColor );
3939 #endif //wxCHECK_VERSION(2, 9, 1)
3942 wxGraphicsFont a2dRenderer::CreateFont(
const wxFont& font ,
const wxColour& col )
3947 p.SetRefData(
new a2dFontData(
this , font, col ) );
3951 return wxNullGraphicsFont;
3954 wxGraphicsFont a2dRenderer::CreateFont(
const a2dFont& font )
3957 p.SetRefData(
new a2dFontData(
this, font ) );
3961 wxGraphicsBitmap a2dRenderer::CreateBitmap(
const wxBitmap& bmp )
3966 p.SetRefData(
new a2dBitmapData(
this , bmp ) );
3970 return wxNullGraphicsBitmap;
3973 #if wxCHECK_VERSION(2, 9, 1)
3974 wxGraphicsBitmap a2dRenderer::CreateBitmapFromNativeBitmap(
void* bitmap )
3977 p.SetRefData(
new a2dBitmapData(
this , (
const wxBitmap& ) bitmap ) );
3980 #endif //wxCHECK_VERSION(2, 9, 1)
3982 wxGraphicsBitmap a2dRenderer::CreateBitmap(
const wxImage& bmp )
3987 p.SetRefData(
new a2dBitmapData(
this , bmp ) );
3991 return wxNullGraphicsBitmap;
3994 wxGraphicsBitmap a2dRenderer::CreateSubBitmap(
const wxGraphicsBitmap& bitmap, wxDouble x, wxDouble y, wxDouble w, wxDouble h )
3997 p.SetRefData(
new a2dBitmapData(
this , bitmap ) );
4002 #endif // wxART2D_USE_GRAPHICS_CONTEXT
wxPoint2DDouble a2dPoint2D
this to define if coordinate numbers are integer or doubles
a2dAffineMatrix & Mirror(bool y=true, bool x=false)
mirror a matrix in x, y
double GetHeight() const
returns height of the boundingbox
Base class for all types of strokes, understood by a2dDrawer2D classes.
static wxUint16 GetPrimitiveThreshold()
get drawing threshold
const a2dStroke * a2dBLACK_STROKE
global a2dStroke stock object for BLACK stroking
const int SPLINE_STEP
number of steps when converting a spline to lines.
const a2dFill * a2dBLACK_FILL
global a2dFill stock object for BLACK filling
void CBCurveTo(double x1, double y1, double x2, double y2, double x3, double y3, bool withStroke=true)
add a quadratic bezier segment to the path
double m_y3
control point 2
Defines a font to be set to a2dDrawer2D or stored in a2dCanvsObject etc.
double m_x3
control point 2
bool GetPixelStroke() const
if the width is pixels or not.
double GetValue(int col, int row) const
get the value in the matrix at col,row
a2dGlobal * a2dGlobals
global a2dCanvasGlobal to have easy access to global settings
Arc Segment in a2dVertexList.
vertex array of line and arc segments.
wxColour GetColour() const
return colour 1
double m_y2
control point 1
vertex list of line and arc segments.
double TransformDistance(double distance) const
Transform a distance.
#define NORMFONT
Normalization font size used for bigger size drawing of text.
a2dDrawStyle
Define the manner in which a2dCanvasView draws to the device.
void SetWidth(float width)
Set width of stroke in world coordinates.
bool CalcR(const a2dLineSegment &prev, double &radius, double ¢er_x, double ¢er_y, double &beginrad, double &midrad, double &endrad, double &phit) const
Calculation of center for the Arc.
void Expand(const a2dPoint2D &, const a2dPoint2D &)
expand boundingbox width two points
const a2dBoundingBox & Translate(a2dPoint2D &)
translate with given vector
double GetMinX() const
get minimum X of the boundingbox
const a2dFont * a2dNullFONT
global a2dFont stock object for NO font
#define wxStaticCast(obj, className)
The wxWindows 2.4.2 wxStaticCast is buggy. It evaluates its argument twice.
Normal straight line segment in a2dVertexList and a2dVertexArray.
bool CalcR(a2dVpathSegmentPtr prev, double &radius, double ¢er_x, double ¢er_y, double &beginrad, double &midrad, double &endrad, double &phit)
Calculation of center for the Arc.
the wxGraphicContext based drawing context
double m_x2
control point 1
A 2x3 affine matrix class for 2D transformations.
double GetMaxX() const
get maximum X of the boundingbox
holes one glyph from a freetype font.
double m_x
x endpoint of line
void MapBbox(const a2dAffineMatrix &matrix)
used in freetype rendering
double m_y
y endpoint of line
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 ...
double m_y1
y endpoint of line
double GetMaxY() const
get maximum Y of the boundingbox
double GetWidth() const
returns width of the boundingbox
bool Scale(double scale)
Scale by scale (isotropic scaling i.e. the same in x and y):
bool Translate(double x, double y)
Translate by dx, dy:
const a2dStroke * a2dTRANSPARENT_STROKE
global a2dStroke stock object for TRANSPARENT stroking
The a2dBoundingBox class stores one a2dBoundingBox of a a2dCanvasObject.
bool Invert(void)
Invert matrix.
double GetMinY() const
get minimum Y of the boundingbox
double m_x1
x endpoint of line
#define Round(x)
round to integer such that e.g 2.5 < x < 3.5 becomes 3
A pointer class, that automatically calls SmrtPtrOwn/SmrtPtrRelease.
const double wxPI
defines PI
const a2dFill * a2dTRANSPARENT_FILL
global a2dFill stock object for TRANSPARENT filling
Used internal for scanned ( gradient etc. ) polygon filling.