28 #include "wx/msw/dc.h"
30 #include "wx/gdiplusdrawer/gdiplusdrawer.h"
33 #if wxART2D_USE_GDIPLUSDRAWER
35 WX_DEFINE_LIST( RegionList );
37 a2dGDIPlusDrawer::a2dGDIPlusDrawer(
int width,
int height ) :
a2dDrawer2D( width, height )
42 a2dGDIPlusDrawer::a2dGDIPlusDrawer(
const wxSize& size ) :
a2dDrawer2D( size )
47 void a2dGDIPlusDrawer::Init()
49 GdiplusStartupInput input;
50 GdiplusStartupOutput output;
51 GdiplusStartup( &m_gdiplus_token, &input, &output );
53 m_buffer = wxBitmap( m_width, m_height );
54 m_dc =
new wxMemoryDC( );
55 m_dc->SelectObject( m_buffer );
57 #if wxCHECK_VERSION(2, 9, 0)
58 const wxMSWDCImpl* impl;
60 m_context =
new Graphics( ( HDC ) impl->GetHDC( ) );
62 m_context =
new Graphics( ( HDC ) m_dc->GetHDC( ) );
64 m_context->SetSmoothingMode( SmoothingModeHighQuality );
65 m_context->SetSmoothingMode( SmoothingModeAntiAlias );
67 m_current_pen =
new Pen( Color( 0, 0, 0 ), 1 );
68 m_current_brush =
new SolidBrush( Color( 0, 0, 0 ) );
69 m_matrix = Matrix().Clone();
78 m_OpacityFactor = 255;
81 a2dGDIPlusDrawer::a2dGDIPlusDrawer(
const a2dGDIPlusDrawer& other ) :
a2dDrawer2D( other )
87 m_buffer = other.m_buffer;
90 a2dGDIPlusDrawer::~a2dGDIPlusDrawer( )
96 delete m_current_brush;
102 GdiplusShutdown( m_gdiplus_token );
105 Matrix* a2dGDIPlusDrawer::_get_gdiplus_user_to_device_transform()
111 ( REAL )rmtx( 0, 0 ), ( REAL )rmtx( 0, 1 ),
112 ( REAL )rmtx( 1, 0 ), ( REAL )rmtx( 1, 1 ),
113 ( REAL )rmtx( 2, 0 ), ( REAL )rmtx( 2, 1 ) );
115 m_matrix = mat.Clone();
119 void a2dGDIPlusDrawer::SetBufferSize(
int w,
int h )
126 wxBitmap helpbuf = wxBitmap( w, h );
127 m_dc->SelectObject( wxNullBitmap );
133 m_dc->SelectObject( m_buffer );
134 mdc.SelectObject( helpbuf );
135 m_dc->Blit( 0, 0, w, h, &mdc, 0, 0 );
136 mdc.SelectObject( wxNullBitmap );
137 m_dc->SelectObject( wxNullBitmap );
140 m_dc->SelectObject( m_buffer );
141 #if wxCHECK_VERSION(2, 9, 0)
142 const wxMSWDCImpl* m_impl;
144 m_context =
new Graphics( ( HDC ) m_impl->GetHDC( ) );
146 m_context =
new Graphics( ( HDC ) m_dc->GetHDC( ) );
148 m_current_pen =
new Pen( Color( 0, 0, 0 ), 1 );
149 m_current_brush =
new SolidBrush( Color( 0, 0, 0 ) );
152 wxBitmap a2dGDIPlusDrawer::GetSubBitmap( wxRect rect )
const
154 wxBitmap ret( rect.width, rect.height, m_buffer.GetDepth() );
155 wxASSERT_MSG( ret.Ok(), wxT(
"GetSubImage error" ) );
158 dcm.SelectObject( const_cast<wxBitmap&>( m_buffer ) );
162 dcb.SelectObject( ret );
163 dcb.Blit( 0, 0, rect.width, rect.height, const_cast<wxMemoryDC*>( &dcm ), rect.x, rect.y, wxCOPY,
false );
164 dcb.SelectObject( wxNullBitmap );
166 dcm.SelectObject( wxNullBitmap );
170 void a2dGDIPlusDrawer::CopyIntoBuffer(
const wxBitmap& bitm )
174 m_dc->SelectObject( wxNullBitmap );
176 m_dc->SelectObject( m_buffer );
177 #if wxCHECK_VERSION(2, 9, 0)
178 const wxMSWDCImpl* m_impl;
180 m_context =
new Graphics( ( HDC ) m_impl->GetHDC( ) );
182 m_context =
new Graphics( ( HDC ) m_dc->GetHDC( ) );
186 void a2dGDIPlusDrawer::SetTransform(
const a2dAffineMatrix& userToWorld )
191 m_usertodevice( 0, 0 ), m_usertodevice( 0, 1 ),
192 m_usertodevice( 1, 0 ), m_usertodevice( 1, 1 ),
193 m_usertodevice( 2, 0 ), m_usertodevice( 2, 1 ) );
194 m_context->SetTransform( &m );
197 void a2dGDIPlusDrawer::PushTransform()
201 m_context->SetTransform( _get_gdiplus_user_to_device_transform() );
208 m_context->SetTransform( _get_gdiplus_user_to_device_transform() );
211 void a2dGDIPlusDrawer::PushIdentityTransform()
215 m_context->SetTransform( _get_gdiplus_user_to_device_transform() );
218 void a2dGDIPlusDrawer::PopTransform(
void )
222 m_context->SetTransform( _get_gdiplus_user_to_device_transform() );
225 void a2dGDIPlusDrawer::BeginDraw( )
227 wxASSERT_MSG( m_beginDraw_endDraw >= 0, wxT(
"a2dGDIPlusDrawer, unbalanced BeginDraw EndDraw" ) );
229 if ( m_display && m_beginDraw_endDraw == 0 )
231 DestroyClippingRegion();
233 SetDrawStyle( m_drawstyle );
234 SetActiveStroke( m_currentstroke );
235 SetActiveFill( m_currentfill );
237 m_deviceDC =
new wxClientDC( m_display );
238 m_display->PrepareDC( *m_deviceDC );
241 m_beginDraw_endDraw++;
244 void a2dGDIPlusDrawer::EndDraw( )
246 m_beginDraw_endDraw--;
248 wxASSERT_MSG( m_beginDraw_endDraw >= 0, wxT(
"a2dDcDrawer, unbalanced BeginDraw EndDraw" ) );
250 if ( m_display && m_beginDraw_endDraw == 0 )
257 void a2dGDIPlusDrawer::SetClippingRegion(
a2dVertexList* points,
bool spline, wxPolygonFillMode fillStyle )
290 GraphicsPath* path = createGraphicsPath( points, spline );
291 m_context->SetClip( path, CombineModeReplace );
294 void a2dGDIPlusDrawer::ExtendAndPushClippingRegion(
a2dVertexList* points,
bool spline, wxPolygonFillMode fillStyle,
a2dBooleanClip clipoperation )
296 Region* push =
new Region( );
297 m_context->GetClip( push );
298 m_clipping_region_stack.Insert( push );
300 ExtendClippingRegion( points, spline, fillStyle, clipoperation );
304 void a2dGDIPlusDrawer::ExtendClippingRegion(
a2dVertexList* points,
bool spline, wxPolygonFillMode fillStyle,
a2dBooleanClip clipoperation )
306 GraphicsPath* path = createGraphicsPath( points, spline, fillStyle );
308 if( !m_context->IsClipEmpty( ) )
310 switch( clipoperation )
313 m_context->SetClip( path, CombineModeIntersect );
317 m_context->SetClip( path, CombineModeUnion );
321 m_context->SetClip( path, CombineModeXor );
325 m_context->SetClip( path, CombineModeExclude );
330 m_context->SetClip( path, CombineModeReplace );
336 m_context->SetClip( path, CombineModeReplace );
340 void a2dGDIPlusDrawer::PopClippingRegion( )
342 wxASSERT( m_clipping_region_stack.GetCount( ) > 0 );
344 Region* region = m_clipping_region_stack.GetFirst()->GetData( );
346 m_clipping_region_stack.DeleteNode( m_clipping_region_stack.GetLast( ) );
347 m_context->SetClip( region, CombineModeReplace );
350 void a2dGDIPlusDrawer::SetClippingRegionDev( wxCoord minx, wxCoord miny, wxCoord width, wxCoord height )
352 m_clip = wxRegion( minx, miny, width, height );
353 m_clipboxdev = wxRect( minx, miny, width, height );
354 m_clipboxworld = ToWorld( m_clipboxdev );
358 PushIdentityTransform();
359 m_context->ResetClip();
360 Rect clip_box( m_clipboxdev.x, m_clipboxdev.y, m_clipboxdev.GetWidth(), m_clipboxdev.GetHeight() );
361 m_context->SetClip( clip_box, CombineModeReplace );
365 void a2dGDIPlusDrawer::SetClippingRegion(
double minx,
double miny,
double maxx,
double maxy )
367 int iminx = WorldToDeviceX( minx );
368 int iminy = WorldToDeviceY( miny );
369 int imaxx = WorldToDeviceX( maxx );
370 int imaxy = WorldToDeviceY( maxy );
373 m_clip = wxRegion( iminx, imaxy, imaxx - iminx, iminy - imaxy );
374 m_clipboxdev = wxRect( iminx, imaxy, imaxx - iminx, iminy - imaxy );
378 m_clip = wxRegion( iminx, iminy, imaxx - iminx, imaxy - iminy );
379 m_clipboxdev = wxRect( iminx, iminy, imaxx - iminx, imaxy - iminy );
382 m_context->ResetClip();
385 PushIdentityTransform();
386 Rect clip_box( m_clipboxdev.x, m_clipboxdev.y, m_clipboxdev.GetWidth(), m_clipboxdev.GetHeight() );
387 m_context->SetClip( clip_box, CombineModeReplace );
392 void a2dGDIPlusDrawer::DestroyClippingRegion()
394 m_context->ResetClip( );
395 m_clipboxdev = wxRect( 0, 0, m_width, m_height );
396 m_clipboxworld = ToWorld( m_clipboxdev );
399 void a2dGDIPlusDrawer::ResetStyle()
404 SetDrawStyle( m_drawstyle );
407 void a2dGDIPlusDrawer::DoSetActiveStroke()
411 wxColour color = m_activestroke.GetColour( );
412 m_current_pen =
new Pen( Color( m_StrokeOpacityCol1, color.Red( ), color.Green( ), color.Blue( ) ), 1 );
416 wxColour color = m_activestroke.GetColour( );
417 m_current_pen =
new Pen( Color( m_StrokeOpacityCol1, color.Red( ), color.Green( ), color.Blue( ) ), 1 );
421 wxColour color = m_activestroke.GetColour( );
422 m_current_pen =
new Pen( Color( m_StrokeOpacityCol1, color.Red( ), color.Green( ), color.Blue( ) ) );
423 DashStyle dashStyle = DashStyleSolid;
424 switch( m_activestroke.GetStyle() )
429 dashStyle = DashStyleDot;
432 dashStyle = DashStyleDashDot;
435 dashStyle = DashStyleDash;
438 dashStyle = DashStyleDash;
441 dashStyle = DashStyleDash;
446 wxBitmap bmp = m_activestroke.GetStipple();
449 m_penImage = Bitmap::FromHBITMAP( ( HBITMAP )bmp.GetHBITMAP(), ( HPALETTE )bmp.GetPalette()->GetHPALETTE() );
450 m_penBrush =
new TextureBrush( m_penImage );
451 m_current_pen->SetBrush( m_penBrush );
458 HatchStyle style = HatchStyleHorizontal;
459 switch( m_activestroke.GetStyle() )
462 style = HatchStyleBackwardDiagonal;
465 style = HatchStyleDiagonalCross;
468 style = HatchStyleForwardDiagonal;
471 style = HatchStyleCross;
474 style = HatchStyleHorizontal;
477 style = HatchStyleVertical;
480 m_penBrush =
new HatchBrush( style, Color( m_StrokeOpacityCol1, m_activestroke.GetColour().Red() ,
481 m_activestroke.GetColour().Green() , m_activestroke.GetColour().Blue() ), Color::Transparent );
482 m_current_pen->SetBrush( m_penBrush );
486 if ( dashStyle != DashStyleSolid )
487 m_current_pen->SetDashStyle( dashStyle );
492 strokewidth = m_activestroke.GetWidth();
495 m_current_pen->SetLineJoin( LineJoinRound );
496 m_current_pen->SetLineCap( LineCapRound, LineCapRound, DashCapFlat );
497 m_current_pen->SetWidth( 1 );
498 strokewidth = DeviceToWorldXRel( 1 );
503 switch( m_activestroke.GetJoin( ) )
506 join = LineJoinMiter;
509 join = LineJoinRound;
512 join = LineJoinBevel;
515 join = LineJoinRound;
518 m_current_pen->SetLineJoin( join );
521 switch( m_activestroke.GetCap( ) )
530 case wxCAP_PROJECTING:
537 m_current_pen->SetLineCap( cap, cap, DashCapFlat );
539 if ( !m_activestroke.GetPixelStroke() )
541 strokewidth = WorldToDeviceXRel( m_activestroke.GetWidth() );
547 strokewidth = !strokewidth ? 1 : strokewidth;
548 m_current_pen->SetWidth( strokewidth );
552 void a2dGDIPlusDrawer::DoSetActiveFill()
554 wxColour color1 = m_activefill.GetColour();
555 wxColour color2 = m_activefill.GetColour2();
557 if ( !m_activefill.GetFilling() )
559 Color gdicolor1( m_FillOpacityCol1, color1.Red( ), color1.Green( ), color1.Blue( ) );
560 m_current_brush =
new SolidBrush( gdicolor1 );
565 Color gdicolor1( m_FillOpacityCol1, color1.Red( ), color1.Green( ), color1.Blue( ) );
566 m_current_brush =
new SolidBrush( gdicolor1 );
569 else if ( m_activefill.IsNoFill() )
571 Color gdicolor1( m_FillOpacityCol1, color1.Red( ), color1.Green( ), color1.Blue( ) );
572 m_current_brush =
new SolidBrush( gdicolor1 );
578 Color gdicolor1( m_FillOpacityCol1, color1.Red( ), color1.Green( ), color1.Blue( ) );
579 Color gdicolor2( m_FillOpacityCol2, color2.Red( ), color2.Green( ), color2.Blue( ) );
581 bool nohatch =
false;
582 HatchStyle style = HatchStyleHorizontal;
583 switch( m_activefill.GetStyle() )
592 style = HatchStyleBackwardDiagonal;
595 style = HatchStyleDiagonalCross;
598 style = HatchStyleForwardDiagonal;
601 style = HatchStyleCross;
604 style = HatchStyleHorizontal;
607 style = HatchStyleVertical;
614 m_current_brush =
new SolidBrush( gdicolor1 );
616 m_current_brush =
new HatchBrush( style, gdicolor1, gdicolor2 );
620 Color gdicolor1( m_FillOpacityCol1, color1.Red( ), color1.Green( ), color1.Blue( ) );
621 Color gdicolor2( m_FillOpacityCol2, color2.Red( ), color2.Green( ), color2.Blue( ) );
623 bool nohatch =
false;
624 HatchStyle style = HatchStyleHorizontal;
625 switch( m_activefill.GetStyle() )
628 style = HatchStyleBackwardDiagonal;
631 style = HatchStyleDiagonalCross;
634 style = HatchStyleForwardDiagonal;
637 style = HatchStyleCross;
640 style = HatchStyleHorizontal;
643 style = HatchStyleVertical;
650 m_current_brush =
new SolidBrush( gdicolor1 );
652 m_current_brush =
new HatchBrush( style, gdicolor1, gdicolor2 );
658 switch( m_activefill.GetStyle() )
664 wxBitmap bmp = m_activefill.GetStipple();
667 wxDELETE( m_brushImage );
668 m_brushImage = Bitmap::FromHBITMAP( ( HBITMAP )bmp.GetHBITMAP(), ( HPALETTE )bmp.GetPalette()->GetHPALETTE() );
669 m_current_brush =
new TextureBrush( m_brushImage );
681 Color gdicolor1( m_FillOpacityCol1, color1.Red( ), color1.Green( ), color1.Blue( ) );
682 Color gdicolor2( m_FillOpacityCol2, color2.Red( ), color2.Green( ), color2.Blue( ) );
683 m_current_brush =
new LinearGradientBrush( PointF( p1.m_x, p1.m_y ) , PointF( p2.m_x, p2.m_x ), gdicolor1, gdicolor2 );
687 Color gdicolor1( m_FillOpacityCol1, color1.Red( ), color1.Green( ), color1.Blue( ) );
688 Color gdicolor2( m_FillOpacityCol2, color2.Red( ), color2.Green( ), color2.Blue( ) );
689 double xc = m_activefill.GetCenter().m_x;
690 double yc = m_activefill.GetCenter().m_y;
691 double xo = m_activefill.GetFocal().m_x;
692 double yo = m_activefill.GetFocal().m_y;
693 double radius = m_activefill.GetRadius();
696 m_brushPath =
new GraphicsPath();
697 m_brushPath->AddEllipse( ( REAL )( xc - radius ), ( REAL )( yc - radius ), ( REAL )( 2 * radius ), ( REAL )( 2 * radius ) );
699 PathGradientBrush* b =
new PathGradientBrush( m_brushPath );
701 b->SetCenterPoint( PointF( xo, yo ) );
702 b->SetCenterColor( gdicolor1 );
704 Color colors[] = {gdicolor2};
706 b->SetSurroundColors( colors, &count );
713 void a2dGDIPlusDrawer::DoSetDrawStyle(
a2dDrawStyle drawstyle )
715 m_drawstyle = drawstyle;
718 void a2dGDIPlusDrawer::DrawRoundedRectangle(
double x,
double y,
double width,
double height,
double radius,
bool pixelsize )
720 if ( m_disableDrawing )
723 if ( !width || !height )
728 width = DeviceToWorldXRel( width );
729 height = DeviceToWorldYRel( height );
730 radius = DeviceToWorldXRel( radius );
736 x += width; width = -width;
744 if ( fabs( radius ) <= 0.00000001 )
746 m_context->SetTransform( _get_gdiplus_user_to_device_transform() );
747 m_context->FillRectangle( m_current_brush, ( REAL ) x, ( REAL ) y, ( REAL ) width, ( REAL ) height );
749 m_context->DrawRectangle( m_current_pen, ( REAL ) x, ( REAL ) y, ( REAL ) width, ( REAL )height );
753 m_context->SetTransform( _get_gdiplus_user_to_device_transform() );
754 m_context->FillRectangle( m_current_brush, ( REAL ) x, ( REAL ) y, ( REAL ) width, ( REAL ) height );
756 m_context->DrawRectangle( m_current_pen, ( REAL ) x, ( REAL ) y, ( REAL ) width, ( REAL ) height );
759 void a2dGDIPlusDrawer::DrawCircle(
double x,
double y,
double radius )
761 DrawEllipse( x, y, radius * 2, radius * 2 );
764 void a2dGDIPlusDrawer::DrawPoint(
double xc,
double yc )
766 m_usertodevice.TransformPoint( xc, yc, xc, yc );
767 DeviceDrawPixel( xc, yc, m_colour1redStroke, m_colour1greenStroke, m_colour1blueStroke, m_StrokeOpacityCol1 );
770 void a2dGDIPlusDrawer::DrawEllipse(
double xc,
double yc,
double width,
double height )
772 if ( m_disableDrawing )
775 m_context->SetTransform( _get_gdiplus_user_to_device_transform() );
776 m_context->FillEllipse( m_current_brush, ( REAL ) xc - width / 2, ( REAL ) yc - height / 2, ( REAL ) width, ( REAL ) height );
779 m_context->DrawEllipse( m_current_pen, ( REAL ) xc - width / 2, ( REAL ) yc - height / 2, ( REAL ) width, ( REAL ) height );
782 void a2dGDIPlusDrawer::DrawImage(
const wxImage& image,
double xc,
double yc,
double width,
double height, wxUint8 Opacity )
784 if ( m_disableDrawing )
790 bool hasAlpha = image.HasAlpha();
791 size_t w = image.GetWidth();
792 size_t h = image.GetHeight();
793 Bitmap* bitmap =
new Bitmap( w, h, PixelFormat32bppPARGB );
794 Rect bounds( 0, 0, w, h );
797 bitmap->LockBits( &bounds, ImageLockModeWrite,
798 bitmap->GetPixelFormat(), &data );
802 UINT* pixels = ( UINT* )data.Scan0;
804 const int srcBytesPerLine = w * 3;
805 const int dstBytesPerLine = w * 4;
806 const unsigned char* src = image.GetData() + ( ( h - 1 ) * srcBytesPerLine );
807 const unsigned char* alpha = hasAlpha ? image.GetAlpha() + ( h - 1 ) * w
809 unsigned char* dstLineStart = (
unsigned char* )pixels;
810 for (
int y = 0; y < h; y++ )
813 unsigned char* dst = dstLineStart;
816 for (
int x = 0; x < w; x++ )
820 const unsigned char a = *alpha++;
821 *dst++ = (
unsigned char )( ( src[2] * a + 127 ) / 255 );
822 *dst++ = (
unsigned char )( ( src[1] * a + 127 ) / 255 );
823 *dst++ = (
unsigned char )( ( src[0] * a + 127 ) / 255 );
830 for (
int x = 0; x < w; x++ )
833 *dst++ = (
unsigned char )( ( src[2] * m_OpacityFactor + 127 ) / 255 );
834 *dst++ = (
unsigned char )( ( src[1] * m_OpacityFactor + 127 ) / 255 );
835 *dst++ = (
unsigned char )( ( src[0] * m_OpacityFactor + 127 ) / 255 );
836 *dst++ = m_OpacityFactor;
842 src -= 2 * srcBytesPerLine;
847 dstLineStart += dstBytesPerLine;
849 bitmap->UnlockBits( &data );
852 m_context->DrawImage( bitmap, ( REAL ) xc - width / 2.0, ( REAL ) yc - height / 2.0, ( REAL ) width, ( REAL ) height ) ;
856 void a2dGDIPlusDrawer::DrawImage(
const a2dImageRGBA& image,
double x,
double y,
double width,
double height, wxUint8 Opacity )
858 if ( m_disableDrawing )
864 #include "Gdipluspixelformats.h"
866 void a2dGDIPlusDrawer::DeviceDrawPolygon(
unsigned int n,
bool spline, wxPolygonFillMode fillStyle )
869 n = ConvertSplinedPolygon2( n );
872 m_context->SetTransform( &ident );
879 for ( i = 0; i < n; i++ )
884 path.AddLine( ( REAL ) m_cpointsDouble[i - 1].x, ( REAL ) m_cpointsDouble[i - 1].y, ( REAL ) m_cpointsDouble[i].x, ( REAL ) m_cpointsDouble[i].y );
887 m_context->DrawPath( m_current_pen, &path );
893 for ( i = 0; i < n; i++ )
898 path.AddLine( ( REAL ) m_cpointsDouble[i - 1].x, ( REAL ) m_cpointsDouble[i - 1].y, ( REAL ) m_cpointsDouble[i].x, ( REAL ) m_cpointsDouble[i].y );
901 m_context->FillPath( m_current_brush, &path );
904 m_context->DrawPath( m_current_pen, &path );
910 for ( i = 0; i < n; i++ )
915 path.AddLine( ( REAL ) m_cpointsDouble[i - 1].x, ( REAL ) m_cpointsDouble[i - 1].y, ( REAL ) m_cpointsDouble[i].x, ( REAL ) m_cpointsDouble[i].y );
918 m_context->FillPath( m_current_brush, &path );
921 m_context->DrawPath( m_current_pen, &path );
927 for ( i = 0; i < n; i++ )
932 path.AddLine( ( REAL ) m_cpointsDouble[i - 1].x, ( REAL ) m_cpointsDouble[i - 1].y, ( REAL ) m_cpointsDouble[i].x, ( REAL ) m_cpointsDouble[i].y );
935 m_context->FillPath( m_current_brush, &path );
938 m_context->DrawPath( m_current_pen, &path );
941 if ( !m_currentstroke.IsSameAs( *
a2dTRANSPARENT_STROKE ) && m_currentstroke.GetType() == a2dSTROKE_OBJECT )
946 wxRealPoint* copy =
new wxRealPoint[n + 1];
947 memcpy( copy, &m_cpointsDouble[0], n *
sizeof( wxRealPoint ) );
948 copy[n].x = m_cpointsDouble[0].x;
949 copy[n].y = m_cpointsDouble[0].y;
957 void a2dGDIPlusDrawer::DeviceDrawLines(
unsigned int n,
bool spline )
960 n = ConvertSplinedPolyline2( n );
963 m_context->SetTransform( &ident );
967 for ( i = 0; i < n; i++ )
972 path.AddLine( ( REAL ) m_cpointsDouble[i - 1].x, ( REAL ) m_cpointsDouble[i - 1].y, ( REAL ) m_cpointsDouble[i].x, ( REAL ) m_cpointsDouble[i].y );
974 m_context->DrawPath( m_current_pen, &path );
977 void a2dGDIPlusDrawer::DeviceDrawLine(
double x1,
double y1,
double x2,
double y2 )
980 m_context->SetTransform( &ident );
982 m_context->DrawLine( m_current_pen, ( REAL ) x1, ( REAL ) y1, ( REAL ) x2, ( REAL ) y2 );
985 void a2dGDIPlusDrawer::DeviceDrawHorizontalLine(
int x1,
int y1,
int x2,
bool use_stroke_color )
995 if ( x2 < m_clipboxdev.x )
998 if ( x1 >= m_clipboxdev.x + m_clipboxdev.width )
1001 if ( x1 < m_clipboxdev.x ) x1 = m_clipboxdev.x;
1002 if ( x2 >= m_clipboxdev.x + m_clipboxdev.width ) x2 = m_clipboxdev.x + m_clipboxdev.width - 1;
1003 if ( y1 >= m_clipboxdev.y && y1 < m_clipboxdev.y + m_clipboxdev.height )
1007 m_context->SetTransform( &ident );
1008 m_context->DrawLine( m_current_pen, ( REAL ) x1, ( REAL ) y1, ( REAL ) x2, ( REAL ) y1 );
1012 void a2dGDIPlusDrawer::DeviceDrawVerticalLine(
int x1,
int y1,
int y2,
bool use_stroke_color )
1022 if ( y2 < m_clipboxdev.y )
1025 if ( y1 >= m_clipboxdev.y + m_clipboxdev.height )
1028 if ( y1 < m_clipboxdev.y ) y1 = m_clipboxdev.y;
1029 if ( y2 >= m_clipboxdev.y + m_clipboxdev.height ) y2 = m_clipboxdev.y + m_clipboxdev.height - 1;
1030 if ( x1 >= m_clipboxdev.x && x1 < m_clipboxdev.x + m_clipboxdev.width )
1035 void a2dGDIPlusDrawer::DeviceDrawPixel(
int x1,
int y1,
unsigned char r,
unsigned char g,
unsigned char b,
unsigned char a )
1038 m_context->SetTransform( &ident );
1039 Pen tmp( Color( a, r, g, b ), 1 );
1040 m_context->DrawLine( &tmp, x1, y1, x1, y1 );
1044 GraphicsPath* a2dGDIPlusDrawer::createGraphicsPath(
a2dVertexList* list,
bool spline, wxPolygonFillMode fillStyle )
1046 unsigned int n = list->size();
1053 case wxODDEVEN_RULE:
1054 ret.SetFillMode( FillModeAlternate );
1057 ret.SetFillMode( FillModeWinding );
1061 #ifdef wxUSE_INTPOINT
1062 Point* points =
new Point[ n ];
1064 PointF* points =
new PointF[ n ];
1070 #ifdef wxUSE_INTPOINT
1071 points[ i ] = Point( point.m_x, point.m_y );
1073 points[ i ] = PointF( point.m_x, point.m_y );
1078 if( spline ==
true )
1079 ret.AddCurve( points, n );
1081 ret.AddLines( points, n );
1084 return ret.Clone( );
1087 void a2dGDIPlusDrawer::BlitBuffer( wxDC* dc, wxRect rect,
const wxPoint& bufferpos )
1089 if ( rect.x + rect.width > m_buffer.GetWidth() )
1090 rect.width = m_buffer.GetWidth() - rect.x;
1091 if ( rect.y + rect.height > m_buffer.GetHeight() )
1092 rect.height = m_buffer.GetHeight() - rect.y;
1094 if ( ( rect.width > 0 ) && ( rect.height > 0 ) )
1096 dc->Blit( rect.x - bufferpos.x, rect.y - bufferpos.y, rect.width, rect.height, m_dc, rect.x, rect.y, wxCOPY,
false );
1100 void a2dGDIPlusDrawer::BlitBuffer( wxRect rect,
const wxPoint& bufferpos )
1103 BlitBuffer( m_deviceDC, rect, bufferpos );
1107 void a2dGDIPlusDrawer::ShiftBuffer(
int dxy,
bool yshift )
1109 int bw = GetBuffer().GetWidth();
1110 int bh = GetBuffer().GetHeight();
1113 if ( dxy > 0 && dxy < bh )
1115 wxRect rect( 0, 0, bw, bh - dxy );
1116 wxBitmap sub_bitmap( m_buffer.GetSubBitmap( rect ) );
1118 dcm.SelectObject( m_buffer );
1119 dcm.DrawBitmap( sub_bitmap, 0, dxy,
true );
1120 dcm.SelectObject( wxNullBitmap );
1122 else if ( dxy < 0 && dxy > -bh )
1124 wxRect rect( 0, -dxy, bw, bh + dxy );
1125 wxBitmap sub_bitmap( m_buffer.GetSubBitmap( rect ) );
1127 dcm.SelectObject( m_buffer );
1128 dcm.DrawBitmap( sub_bitmap, 0, 0,
true );
1129 dcm.SelectObject( wxNullBitmap );
1132 wxFAIL_MSG( wxT(
"you can only shift within height of buffer" ) );
1137 if ( dxy > 0 && dxy < bw )
1139 wxRect rect( 0, 0, bw - dxy, bh );
1140 wxBitmap sub_bitmap( m_buffer.GetSubBitmap( rect ) );
1142 dcm.SelectObject( m_buffer );
1143 dcm.DrawBitmap( sub_bitmap, dxy, 0,
true );
1144 dcm.SelectObject( wxNullBitmap );
1146 else if ( dxy < 0 && dxy > -bw )
1148 wxRect rect( -dxy, 0, bw + dxy, bh );
1149 wxBitmap sub_bitmap( m_buffer.GetSubBitmap( rect ) );
1151 dcm.SelectObject( m_buffer );
1152 dcm.DrawBitmap( sub_bitmap, 0, 0,
true );
1153 dcm.SelectObject( wxNullBitmap );
1156 wxFAIL_MSG( wxT(
"you can only shift within width of buffer" ) );
1160 void a2dGDIPlusDrawer::DrawCharStroke( wxChar c )
1168 a2dStroke stroke =
a2dStroke( m_activestroke.GetColour(), m_currentfont.GetStrokeWidth() );
1170 SetActiveStroke( stroke );
1174 affine.
Scale( m_currentfont.GetSize() );
1175 PushTransform( affine );
1183 a2dVertexList::iterator iter = ( *ptr )->begin();
1184 if ( ( *ptr )->size() )
1188 while ( iter != ( *ptr )->end() )
1191 path.AddLine( ( REAL ) point.m_x, ( REAL ) point.m_y, ( REAL ) point.m_x, ( REAL ) point.m_y );
1198 m_context->DrawPath( m_current_pen, &path );
1202 SetActiveStroke( oldstroke );
1206 void a2dGDIPlusDrawer::DrawCharFreetype( wxChar c )
1211 if ( m_disableDrawing )
1214 double scale = m_currentfont.GetSize() / ( 64 * m_currentfont.GetDeviceHeight() );
1216 #if wxART2D_USE_FREETYPE
1217 y += m_currentfont.GetDescent();
1219 FT_Glyph glyph = m_currentfont.GetGlyphFreetype( c )->m_glyph;
1220 if ( glyph->format != FT_GLYPH_FORMAT_OUTLINE )
1222 FT_Outline& outline = ( ( FT_OutlineGlyph ) glyph )->outline;
1225 FT_Vector v_control;
1240 for( n = 0; n < outline.n_contours; n++ )
1244 last = outline.contours[n];
1245 limit = outline.points + last;
1247 v_start = outline.points[first];
1248 v_last = outline.points[last];
1250 v_control = v_start;
1252 point = outline.points + first;
1253 tags = outline.tags + first;
1254 tag = FT_CURVE_TAG( tags[0] );
1257 if( tag == FT_CURVE_TAG_CUBIC )
return;
1260 if( tag == FT_CURVE_TAG_CONIC )
1263 if( FT_CURVE_TAG( outline.tags[last] ) == FT_CURVE_TAG_ON )
1274 v_start.x = ( v_start.x + v_last.x ) / 2;
1275 v_start.y = ( v_start.y + v_last.y ) / 2;
1284 pointprev =
a2dPoint2D( v_start.x, v_start.y );
1285 path.AddLine( ( REAL ) v_start.x, ( REAL ) v_start.y, ( REAL ) v_start.x, ( REAL ) v_start.y );
1287 while( point < limit )
1292 tag = FT_CURVE_TAG( tags[0] );
1295 case FT_CURVE_TAG_ON:
1297 path.AddLine( ( REAL ) point->x, ( REAL ) point->y, ( REAL ) point->x, ( REAL ) point->y );
1301 case FT_CURVE_TAG_CONIC:
1303 v_control.x = point->x;
1304 v_control.y = point->y;
1314 tag = FT_CURVE_TAG( tags[0] );
1319 if( tag == FT_CURVE_TAG_ON )
1321 PointF c1( v_control.x, v_control.y );
1322 PointF c2( v_control.x, v_control.y );
1323 PointF end( vec.x, vec.y );
1325 path.GetLastPoint( &start );
1326 path.AddBezier( start, c1, c2, end );
1330 if( tag != FT_CURVE_TAG_CONIC )
return;
1332 v_middle.x = ( v_control.x + vec.x ) / 2;
1333 v_middle.y = ( v_control.y + vec.y ) / 2;
1335 PointF c1( v_control.x, v_control.y );
1336 PointF c2( v_control.x, v_control.y );
1337 PointF end( v_middle.x, v_middle.y );
1339 path.GetLastPoint( &start );
1340 path.AddBezier( start, c1, c2, end );
1345 PointF c1( v_control.x, v_control.y );
1346 PointF c2( v_control.x, v_control.y );
1347 PointF end( v_start.x, v_start.y );
1349 path.GetLastPoint( &start );
1350 path.AddBezier( start, c1, c2, end );
1356 FT_Vector vec1, vec2;
1358 if( point + 1 > limit || FT_CURVE_TAG( tags[1] ) != FT_CURVE_TAG_CUBIC )
1363 vec1.x = point[0].x;
1364 vec1.y = point[0].y;
1365 vec2.x = point[1].x;
1366 vec2.y = point[1].y;
1371 if( point <= limit )
1378 PointF c1( vec1.x, vec1.y );
1379 PointF c2( vec2.x, vec2.y );
1380 PointF end( vec.x, vec.y );
1382 path.GetLastPoint( &start );
1383 path.AddBezier( start, c1, c2, end );
1388 PointF c1( vec1.x, vec1.y );
1389 PointF c2( vec2.x, vec2.y );
1390 PointF end( v_start.x, v_start.y );
1392 path.GetLastPoint( &start );
1393 path.AddBezier( start, c1, c2, end );
1408 affine.
Scale( scale );
1410 affine = GetUserToDeviceTransform() * affine;
1412 Matrix charTransform(
1413 ( REAL )affine( 0, 0 ), ( REAL )affine( 0, 1 ),
1414 ( REAL )affine( 1, 0 ), ( REAL )affine( 1, 1 ),
1415 ( REAL )affine( 2, 0 ), ( REAL )affine( 2, 1 ) );
1417 m_context->SetTransform( &charTransform );
1419 wxColour color1 = m_currentstroke.GetColour();
1420 Color gdicolor1( m_StrokeOpacityCol1, color1.Red( ), color1.Green( ), color1.Blue( ) );
1421 SolidBrush* text_brush =
new SolidBrush( gdicolor1 );
1422 m_context->FillPath( text_brush, &path );
1423 #else // wxART2D_USE_FREETYPE
1425 #endif // wxART2D_USE_FREETYPE
1428 void a2dGDIPlusDrawer::DrawCharDc( wxChar c )
1430 #if wxART2D_USE_FREETYPE && defined(__USE_WINAPI__)
1431 if ( m_currentfont.GetType() == a2dFONT_WXDC && m_currentfont.GetFreetypeFont().Ok() )
1433 a2dFont oldfont = m_currentfont;
1434 m_currentfont = m_currentfont.GetFreetypeFont();
1435 DrawCharFreetype( c );
1436 m_currentfont = oldfont;
1440 #else // wxART2D_USE_FREETYPE && defined(__USE_WINAPI__)
1442 #endif // wxART2D_USE_FREETYPE && defined(__USE_WINAPI__)
1445 void a2dGDIPlusDrawer::DrawTextDc(
const wxString& text,
double x,
double y )
1472 #endif // wxART2D_USE_GDIPLUS_DRAWER
wxPoint2DDouble a2dPoint2D
this to define if coordinate numbers are integer or doubles
#define wxDynamicCast(obj, className)
Define wxDynamicCast so that it will give a compiler error for unrelated types.
Base class for all types of strokes, understood by a2dDrawer2D classes.
virtual void SetTransform(const a2dAffineMatrix &userToWorld)
set user-to-world transform matrix.
const a2dStroke * a2dBLACK_STROKE
global a2dStroke stock object for BLACK stroking
Stroke and fill base classes.
virtual void PopTransform(void)
Recall the previously saved user-to-world transform off the matrix stack.
const a2dFill * a2dBLACK_FILL
global a2dFill stock object for BLACK filling
Defines a font to be set to a2dDrawer2D or stored in a2dCanvsObject etc.
vertex list of line and arc segments.
virtual void DrawCharStroke(wxChar c)
Draw a stroke character.
a2dDrawStyle
Define the manner in which a2dCanvasView draws to the device.
virtual void PushTransform()
Save the current user-to-world transform on the affine stack.
virtual void ResetStyle()
set a pre-defined style reseting cashed values.
#define forEachIn(listtype, list)
easy iteration for a2dlist
virtual void DrawCharDc(wxChar c)
Draw a dc character.
Drawing context abstraction.
virtual void DrawTextDc(const wxString &text, double x, double y)
Draw text in user coordinates, based on a dc font .
A 2x3 affine matrix class for 2D transformations.
a2dBooleanClip
Used for defining how a ClippingRegion defined as a polygon is combined with.
virtual void DrawCharFreetype(wxChar c)
Draw a freetype character.
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
virtual void PushIdentityTransform()
push no transform, to draw directly in device coordinates