00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012 #include "a2dprec.h"
00013
00014 #ifdef __BORLANDC__
00015 #pragma hdrstop
00016 #endif
00017
00018 #ifndef WX_PRECOMP
00019 #include "wx/wx.h"
00020 #endif
00021
00022 #include <gdiplus.h>
00023
00024 #include <stdio.h>
00025 #include <string.h>
00026 #include <math.h>
00027
00028 #include "wx/msw/dc.h"
00029 #include "wx/artbase/stylebase.h"
00030 #include "wx/gdiplusdrawer/gdiplusdrawer.h"
00031
00032
00033 #if wxART2D_USE_GDIPLUSDRAWER
00034
00035 WX_DEFINE_LIST( RegionList );
00036
00037 a2dGDIPlusDrawer::a2dGDIPlusDrawer( int width, int height ) : a2dDrawer2D( width, height )
00038 {
00039 Init();
00040 }
00041
00042 a2dGDIPlusDrawer::a2dGDIPlusDrawer( const wxSize &size ) : a2dDrawer2D( size )
00043 {
00044 Init();
00045 }
00046
00047 void a2dGDIPlusDrawer::Init()
00048 {
00049 GdiplusStartupInput input;
00050 GdiplusStartupOutput output;
00051 GdiplusStartup(&m_gdiplus_token,&input,&output);
00052
00053 m_buffer = wxBitmap( m_width, m_height );
00054 m_dc = new wxMemoryDC( );
00055 m_dc->SelectObject( m_buffer );
00056
00057 #if wxCHECK_VERSION(2, 9, 0)
00058 const wxMSWDCImpl *impl;
00059 impl = wxDynamicCast (m_dc->GetImpl(), wxMSWDCImpl);
00060 m_context = new Graphics( (HDC) impl->GetHDC( ) );
00061 #else
00062 m_context = new Graphics( (HDC) m_dc->GetHDC( ) );
00063 #endif
00064 m_context->SetSmoothingMode( SmoothingModeHighQuality );
00065 m_context->SetSmoothingMode( SmoothingModeAntiAlias );
00066
00067 m_current_pen = new Pen( Color( 0, 0, 0 ), 1 );
00068 m_current_brush = new SolidBrush( Color( 0, 0, 0 ) );
00069 m_matrix = Matrix().Clone();
00070 m_penImage = NULL;
00071 m_penBrush = NULL;
00072 m_brushImage = NULL;
00073 m_brushPath= NULL;
00074
00075 m_externalDc = false;
00076 m_deviceDC = 0;
00077 m_clip.Clear();
00078 m_OpacityFactor = 255;
00079 }
00080
00081 a2dGDIPlusDrawer::a2dGDIPlusDrawer( const a2dGDIPlusDrawer& other ) : a2dDrawer2D( other )
00082 {
00083 m_externalDc = false;
00084 m_deviceDC = 0;
00085 m_clip.Clear();
00086
00087 m_buffer = other.m_buffer;
00088 }
00089
00090 a2dGDIPlusDrawer::~a2dGDIPlusDrawer( )
00091 {
00092 if ( m_matrix )
00093 delete m_matrix;
00094 delete m_context;
00095 delete m_current_pen;
00096 delete m_current_brush;
00097 delete m_penImage;
00098 delete m_penBrush;
00099 delete m_brushImage;
00100 delete m_brushPath;
00101 delete m_dc;
00102 GdiplusShutdown( m_gdiplus_token );
00103 }
00104
00105 Matrix* a2dGDIPlusDrawer::_get_gdiplus_user_to_device_transform()
00106 {
00107 if ( m_matrix )
00108 delete m_matrix;
00109 const a2dAffineMatrix &rmtx = GetUserToDeviceTransform();
00110 Matrix mat(
00111 (REAL)rmtx(0,0),(REAL)rmtx(0,1),
00112 (REAL)rmtx(1,0),(REAL)rmtx(1,1),
00113 (REAL)rmtx(2,0),(REAL)rmtx(2,1) );
00114
00115 m_matrix = mat.Clone();
00116 return m_matrix;
00117 }
00118
00119 void a2dGDIPlusDrawer::SetBufferSize( int w, int h )
00120 {
00121 m_width = w;
00122 m_height = h;
00123
00124 delete m_context;
00125
00126 wxBitmap helpbuf = wxBitmap( w, h );
00127 m_dc->SelectObject( wxNullBitmap );
00128
00129
00130
00131 wxMemoryDC mdc;
00132
00133 m_dc->SelectObject( m_buffer );
00134 mdc.SelectObject( helpbuf );
00135 m_dc->Blit( 0, 0, w, h, &mdc, 0, 0 );
00136 mdc.SelectObject( wxNullBitmap );
00137 m_dc->SelectObject( wxNullBitmap );
00138
00139 m_buffer = helpbuf;
00140 m_dc->SelectObject( m_buffer );
00141 #if wxCHECK_VERSION(2, 9, 0)
00142 const wxMSWDCImpl *m_impl;
00143 m_impl = wxDynamicCast (m_dc->GetImpl(), wxMSWDCImpl);
00144 m_context = new Graphics( (HDC) m_impl->GetHDC( ) );
00145 #else
00146 m_context = new Graphics( (HDC) m_dc->GetHDC( ) );
00147 #endif
00148 m_current_pen = new Pen( Color( 0, 0, 0 ), 1 );
00149 m_current_brush = new SolidBrush( Color( 0, 0, 0 ) );
00150 }
00151
00152 wxBitmap a2dGDIPlusDrawer::GetSubBitmap( wxRect rect ) const
00153 {
00154 wxBitmap ret( rect.width, rect.height, m_buffer.GetDepth() );
00155 wxASSERT_MSG( ret.Ok(), wxT( "GetSubImage error" ) );
00156
00157 wxMemoryDC dcm;
00158 dcm.SelectObject( const_cast<wxBitmap&>(m_buffer) );
00159
00160
00161 wxMemoryDC dcb;
00162 dcb.SelectObject( ret );
00163 dcb.Blit( 0, 0, rect.width, rect.height, const_cast<wxMemoryDC*>( &dcm ), rect.x, rect.y, wxCOPY, false );
00164 dcb.SelectObject( wxNullBitmap );
00165
00166 dcm.SelectObject( wxNullBitmap );
00167 return ret;
00168 }
00169
00170 void a2dGDIPlusDrawer::CopyIntoBuffer( const wxBitmap& bitm )
00171 {
00172 delete m_context;
00173
00174 m_dc->SelectObject( wxNullBitmap );
00175 m_buffer = bitm;
00176 m_dc->SelectObject( m_buffer );
00177 #if wxCHECK_VERSION(2, 9, 0)
00178 const wxMSWDCImpl *m_impl;
00179 m_impl = wxDynamicCast (m_dc->GetImpl(), wxMSWDCImpl);
00180 m_context = new Graphics( (HDC) m_impl->GetHDC( ) );
00181 #else
00182 m_context = new Graphics( (HDC) m_dc->GetHDC( ) );
00183 #endif
00184 }
00185
00186 void a2dGDIPlusDrawer::SetTransform( const a2dAffineMatrix& userToWorld )
00187 {
00188 a2dDrawer2D::SetTransform( userToWorld );
00189
00190 Matrix m(
00191 m_usertodevice( 0, 0), m_usertodevice( 0, 1),
00192 m_usertodevice( 1, 0), m_usertodevice( 1, 1),
00193 m_usertodevice( 2, 0), m_usertodevice( 2, 1) );
00194 m_context->SetTransform( &m );
00195 }
00196
00197 void a2dGDIPlusDrawer::PushTransform()
00198 {
00199 a2dDrawer2D::PushTransform();
00200
00201 m_context->SetTransform( _get_gdiplus_user_to_device_transform() );
00202 }
00203
00204 void a2dGDIPlusDrawer::PushTransform( const a2dAffineMatrix& affine )
00205 {
00206 a2dDrawer2D::PushTransform( affine );
00207
00208 m_context->SetTransform( _get_gdiplus_user_to_device_transform() );
00209 }
00210
00211 void a2dGDIPlusDrawer::PushIdentityTransform()
00212 {
00213 a2dDrawer2D::PushIdentityTransform( );
00214
00215 m_context->SetTransform( _get_gdiplus_user_to_device_transform() );
00216 }
00217
00218 void a2dGDIPlusDrawer::PopTransform( void )
00219 {
00220 a2dDrawer2D::PopTransform();
00221
00222 m_context->SetTransform( _get_gdiplus_user_to_device_transform() );
00223 }
00224
00225 void a2dGDIPlusDrawer::BeginDraw( )
00226 {
00227 wxASSERT_MSG( m_beginDraw_endDraw >= 0, wxT("a2dGDIPlusDrawer, unbalanced BeginDraw EndDraw") );
00228
00229 if ( m_display && m_beginDraw_endDraw == 0 )
00230 {
00231 DestroyClippingRegion();
00232
00233 SetDrawStyle( m_drawstyle );
00234 SetActiveStroke( m_currentstroke );
00235 SetActiveFill( m_currentfill );
00236
00237 m_deviceDC = new wxClientDC( m_display );
00238 m_display->PrepareDC( *m_deviceDC );
00239 }
00240
00241 m_beginDraw_endDraw++;
00242 }
00243
00244 void a2dGDIPlusDrawer::EndDraw( )
00245 {
00246 m_beginDraw_endDraw--;
00247
00248 wxASSERT_MSG( m_beginDraw_endDraw >= 0, wxT("a2dDcDrawer, unbalanced BeginDraw EndDraw") );
00249
00250 if ( m_display && m_beginDraw_endDraw == 0 )
00251 {
00252 delete m_deviceDC;
00253 m_deviceDC = NULL;
00254 }
00255 }
00256
00257 void a2dGDIPlusDrawer::SetClippingRegion( a2dVertexList* points, bool spline, wxPolygonFillMode fillStyle )
00258 {
00259
00260
00261
00262
00263
00264
00265
00266
00267
00268
00269
00270
00271
00272
00273
00274
00275
00276
00277
00278
00279
00280
00281
00282
00283
00284
00285
00286
00287
00288
00289
00290 GraphicsPath *path = createGraphicsPath( points, spline );
00291 m_context->SetClip( path, CombineModeReplace );
00292 }
00293
00294 void a2dGDIPlusDrawer::ExtendAndPushClippingRegion( a2dVertexList* points, bool spline, wxPolygonFillMode fillStyle, a2dBooleanClip clipoperation )
00295 {
00296 Region *push = new Region( );
00297 m_context->GetClip( push );
00298 m_clipping_region_stack.Insert( push );
00299
00300 ExtendClippingRegion( points, spline, fillStyle, clipoperation );
00301 return;
00302 }
00303
00304 void a2dGDIPlusDrawer::ExtendClippingRegion( a2dVertexList* points, bool spline, wxPolygonFillMode fillStyle, a2dBooleanClip clipoperation )
00305 {
00306 GraphicsPath *path = createGraphicsPath( points, spline, fillStyle );
00307
00308 if( !m_context->IsClipEmpty( ) )
00309 {
00310 switch( clipoperation )
00311 {
00312 case a2dCLIP_AND:
00313 m_context->SetClip( path, CombineModeIntersect );
00314 break ;
00315
00316 case a2dCLIP_OR:
00317 m_context->SetClip( path, CombineModeUnion );
00318 break ;
00319
00320 case a2dCLIP_XOR:
00321 m_context->SetClip( path, CombineModeXor );
00322 break ;
00323
00324 case a2dCLIP_DIFF:
00325 m_context->SetClip( path, CombineModeExclude );
00326 break ;
00327
00328 case a2dCLIP_COPY:
00329 default:
00330 m_context->SetClip( path, CombineModeReplace );
00331 break ;
00332 }
00333 }
00334 else
00335 {
00336 m_context->SetClip( path, CombineModeReplace );
00337 }
00338 }
00339
00340 void a2dGDIPlusDrawer::PopClippingRegion( )
00341 {
00342 wxASSERT( m_clipping_region_stack.GetCount( ) > 0 );
00343
00344 Region *region = m_clipping_region_stack.GetFirst()->GetData( );
00345
00346 m_clipping_region_stack.DeleteNode( m_clipping_region_stack.GetLast( ) );
00347 m_context->SetClip( region, CombineModeReplace );
00348 }
00349
00350 void a2dGDIPlusDrawer::SetClippingRegionDev( wxCoord minx, wxCoord miny, wxCoord width, wxCoord height )
00351 {
00352 m_clip = wxRegion( minx, miny, width, height );
00353 m_clipboxdev = wxRect( minx, miny, width, height );
00354 m_clipboxworld = ToWorld( m_clipboxdev );
00355
00356
00357
00358 PushIdentityTransform();
00359 m_context->ResetClip();
00360 Rect clip_box( m_clipboxdev.x, m_clipboxdev.y, m_clipboxdev.GetWidth(), m_clipboxdev.GetHeight() );
00361 m_context->SetClip( clip_box, CombineModeReplace );
00362 PopTransform();
00363 }
00364
00365 void a2dGDIPlusDrawer::SetClippingRegion(double minx, double miny, double maxx, double maxy)
00366 {
00367 int iminx = WorldToDeviceX( minx );
00368 int iminy = WorldToDeviceY( miny );
00369 int imaxx = WorldToDeviceX( maxx );
00370 int imaxy = WorldToDeviceY( maxy );
00371 if ( m_yaxis )
00372 {
00373 m_clip = wxRegion( iminx, imaxy, imaxx - iminx, iminy - imaxy );
00374 m_clipboxdev = wxRect( iminx, imaxy, imaxx - iminx, iminy - imaxy );
00375 }
00376 else
00377 {
00378 m_clip = wxRegion( iminx, iminy, imaxx - iminx, imaxy - iminy );
00379 m_clipboxdev = wxRect( iminx, iminy, imaxx - iminx, imaxy - iminy );
00380 }
00381
00382 m_context->ResetClip();
00383
00384
00385 PushIdentityTransform();
00386 Rect clip_box( m_clipboxdev.x, m_clipboxdev.y, m_clipboxdev.GetWidth(), m_clipboxdev.GetHeight() );
00387 m_context->SetClip( clip_box, CombineModeReplace );
00388
00389 PopTransform();
00390 }
00391
00392 void a2dGDIPlusDrawer::DestroyClippingRegion()
00393 {
00394 m_context->ResetClip( );
00395 m_clipboxdev = wxRect( 0, 0, m_width, m_height );
00396 m_clipboxworld = ToWorld( m_clipboxdev );
00397 }
00398
00399 void a2dGDIPlusDrawer::ResetStyle()
00400 {
00401 a2dDrawer2D::ResetStyle();
00402 SetDrawerFill( *a2dBLACK_FILL );
00403 SetDrawerStroke( *a2dBLACK_STROKE );
00404 SetDrawStyle( m_drawstyle );
00405 }
00406
00407 void a2dGDIPlusDrawer::DoSetActiveStroke()
00408 {
00409 if ( m_activestroke.IsNoStroke() || m_activestroke.GetStyle() == a2dSTROKE_TRANSPARENT )
00410 {
00411 wxColour color = m_activestroke.GetColour( );
00412 m_current_pen = new Pen( Color( m_StrokeOpacityCol1, color.Red( ), color.Green( ), color.Blue( ) ), 1 );
00413 }
00414 else if ( m_drawstyle == a2dWIREFRAME_INVERT_ZERO_WIDTH )
00415 {
00416 wxColour color = m_activestroke.GetColour( );
00417 m_current_pen = new Pen( Color( m_StrokeOpacityCol1, color.Red( ), color.Green( ), color.Blue( ) ), 1 );
00418 }
00419 else if ( m_activestroke.GetType() == a2dSTROKE_ONE_COLOUR )
00420 {
00421 wxColour color = m_activestroke.GetColour( );
00422 m_current_pen = new Pen( Color( m_StrokeOpacityCol1, color.Red( ), color.Green( ), color.Blue( ) ) );
00423 DashStyle dashStyle = DashStyleSolid;
00424 switch( m_activestroke.GetStyle() )
00425 {
00426 case a2dSTROKE_SOLID:
00427 break;
00428 case a2dSTROKE_DOT:
00429 dashStyle = DashStyleDot;
00430 break;
00431 case a2dSTROKE_DOT_DASH:
00432 dashStyle = DashStyleDashDot;
00433 break;
00434 case a2dSTROKE_LONG_DASH:
00435 dashStyle = DashStyleDash;
00436 break;
00437 case a2dSTROKE_SHORT_DASH:
00438 dashStyle = DashStyleDash;
00439 break;
00440 case a2dSTROKE_TRANSPARENT:
00441 dashStyle = DashStyleDash;
00442 break;
00443 case a2dSTROKE_STIPPLE:
00444 case a2dSTROKE_STIPPLE_MASK_OPAQUE:
00445 {
00446 wxBitmap bmp = m_activestroke.GetStipple();
00447 if ( bmp.Ok() )
00448 {
00449 m_penImage = Bitmap::FromHBITMAP((HBITMAP)bmp.GetHBITMAP(),(HPALETTE)bmp.GetPalette()->GetHPALETTE());
00450 m_penBrush = new TextureBrush(m_penImage);
00451 m_current_pen->SetBrush( m_penBrush );
00452 }
00453
00454 }
00455 default :
00456
00457 {
00458 HatchStyle style = HatchStyleHorizontal;
00459 switch( m_activestroke.GetStyle() )
00460 {
00461 case a2dSTROKE_BDIAGONAL_HATCH:
00462 style = HatchStyleBackwardDiagonal;
00463 break;
00464 case a2dSTROKE_CROSSDIAG_HATCH:
00465 style = HatchStyleDiagonalCross;
00466 break;
00467 case a2dSTROKE_FDIAGONAL_HATCH:
00468 style = HatchStyleForwardDiagonal;
00469 break;
00470 case a2dSTROKE_CROSS_HATCH:
00471 style = HatchStyleCross;
00472 break;
00473 case a2dSTROKE_HORIZONTAL_HATCH:
00474 style = HatchStyleHorizontal;
00475 break;
00476 case a2dSTROKE_VERTICAL_HATCH:
00477 style = HatchStyleVertical;
00478 break;
00479 }
00480 m_penBrush = new HatchBrush(style,Color( m_StrokeOpacityCol1, m_activestroke.GetColour().Red() ,
00481 m_activestroke.GetColour().Green() , m_activestroke.GetColour().Blue() ), Color::Transparent );
00482 m_current_pen->SetBrush( m_penBrush );
00483 }
00484 break;
00485 }
00486 if ( dashStyle != DashStyleSolid )
00487 m_current_pen->SetDashStyle(dashStyle);
00488
00489
00490 double strokewidth;
00491
00492 strokewidth = m_activestroke.GetWidth();
00493 if ( m_drawstyle == a2dWIREFRAME_ZERO_WIDTH )
00494 {
00495 m_current_pen->SetLineJoin( LineJoinRound );
00496 m_current_pen->SetLineCap( LineCapRound, LineCapRound, DashCapFlat);
00497 m_current_pen->SetWidth( 1 );
00498 strokewidth = DeviceToWorldXRel( 1 );
00499 }
00500 else
00501 {
00502 LineJoin join;
00503 switch( m_activestroke.GetJoin( ) )
00504 {
00505 case wxJOIN_MITER:
00506 join = LineJoinMiter;
00507 break;
00508 case wxJOIN_ROUND:
00509 join = LineJoinRound;
00510 break;
00511 case wxJOIN_BEVEL:
00512 join = LineJoinBevel;
00513 break;
00514 default:
00515 join = LineJoinRound;
00516 break;
00517 }
00518 m_current_pen->SetLineJoin( join );
00519
00520 LineCap cap;
00521 switch( m_activestroke.GetCap( ) )
00522 {
00523 case wxCAP_BUTT:
00524 cap = LineCapFlat;
00525 break;
00526 case wxCAP_ROUND:
00527 cap = LineCapRound;
00528 break;
00529
00530 case wxCAP_PROJECTING:
00531 cap = LineCapSquare;
00532 break;
00533 default:
00534 cap = LineCapFlat;
00535 break;
00536 }
00537 m_current_pen->SetLineCap(cap,cap, DashCapFlat);
00538
00539 if ( !m_activestroke.GetPixelStroke() )
00540 {
00541 strokewidth = WorldToDeviceXRel( m_activestroke.GetWidth() );
00542 }
00543
00544
00545 }
00546
00547 strokewidth = !strokewidth ? 1: strokewidth;
00548 m_current_pen->SetWidth( strokewidth );
00549 }
00550 }
00551
00552 void a2dGDIPlusDrawer::DoSetActiveFill()
00553 {
00554 wxColour color1 = m_activefill.GetColour();
00555 wxColour color2 = m_activefill.GetColour2();
00556
00557 if ( !m_activefill.GetFilling() )
00558 {
00559 Color gdicolor1( m_FillOpacityCol1, color1.Red( ), color1.Green( ), color1.Blue( ) );
00560 m_current_brush = new SolidBrush( gdicolor1 );
00561 return;
00562 }
00563 else if ( m_activefill.GetStyle() == a2dFILL_TRANSPARENT )
00564 {
00565 Color gdicolor1( m_FillOpacityCol1, color1.Red( ), color1.Green( ), color1.Blue( ) );
00566 m_current_brush = new SolidBrush( gdicolor1 );
00567 return;
00568 }
00569 else if ( m_activefill.IsNoFill() )
00570 {
00571 Color gdicolor1( m_FillOpacityCol1, color1.Red( ), color1.Green( ), color1.Blue( ) );
00572 m_current_brush = new SolidBrush( gdicolor1 );
00573 return;
00574 }
00575
00576 if ( m_activefill.GetType() == a2dFILL_ONE_COLOUR )
00577 {
00578 Color gdicolor1( m_FillOpacityCol1, color1.Red( ), color1.Green( ), color1.Blue( ) );
00579 Color gdicolor2( m_FillOpacityCol2, color2.Red( ), color2.Green( ), color2.Blue( ) );
00580
00581 bool nohatch = false;
00582 HatchStyle style = HatchStyleHorizontal;
00583 switch( m_activefill.GetStyle() )
00584 {
00585 case a2dFILL_TRANSPARENT:
00586 nohatch = true;
00587 break;
00588 case a2dFILL_SOLID:
00589 nohatch = true;
00590 break;
00591 case a2dFILL_BDIAGONAL_HATCH:
00592 style = HatchStyleBackwardDiagonal;
00593 break;
00594 case a2dFILL_CROSSDIAG_HATCH:
00595 style = HatchStyleDiagonalCross;
00596 break;
00597 case a2dFILL_FDIAGONAL_HATCH:
00598 style = HatchStyleForwardDiagonal;
00599 break;
00600 case a2dFILL_CROSS_HATCH:
00601 style = HatchStyleCross;
00602 break;
00603 case a2dFILL_HORIZONTAL_HATCH:
00604 style = HatchStyleHorizontal;
00605 break;
00606 case a2dFILL_VERTICAL_HATCH:
00607 style = HatchStyleVertical;
00608 break;
00609 default:
00610 nohatch = true;
00611 break;
00612 }
00613 if (nohatch)
00614 m_current_brush = new SolidBrush( gdicolor1 );
00615 else
00616 m_current_brush = new HatchBrush(style,gdicolor1, gdicolor2 );
00617 }
00618 else if ( m_activefill.GetType() == a2dFILL_HATCH_TWO_COLOUR )
00619 {
00620 Color gdicolor1( m_FillOpacityCol1, color1.Red( ), color1.Green( ), color1.Blue( ) );
00621 Color gdicolor2( m_FillOpacityCol2, color2.Red( ), color2.Green( ), color2.Blue( ) );
00622
00623 bool nohatch = false;
00624 HatchStyle style = HatchStyleHorizontal;
00625 switch( m_activefill.GetStyle() )
00626 {
00627 case a2dFILL_TWOCOL_BDIAGONAL_HATCH:
00628 style = HatchStyleBackwardDiagonal;
00629 break;
00630 case a2dFILL_TWOCOL_CROSSDIAG_HATCH:
00631 style = HatchStyleDiagonalCross;
00632 break;
00633 case a2dFILL_TWOCOL_FDIAGONAL_HATCH:
00634 style = HatchStyleForwardDiagonal;
00635 break;
00636 case a2dFILL_TWOCOL_CROSS_HATCH:
00637 style = HatchStyleCross;
00638 break;
00639 case a2dFILL_TWOCOL_HORIZONTAL_HATCH:
00640 style = HatchStyleHorizontal;
00641 break;
00642 case a2dFILL_TWOCOL_VERTICAL_HATCH:
00643 style = HatchStyleVertical;
00644 break;
00645 default:
00646 nohatch = true;
00647 break;
00648 }
00649 if (nohatch)
00650 m_current_brush = new SolidBrush( gdicolor1 );
00651 else
00652 m_current_brush = new HatchBrush( style, gdicolor1, gdicolor2 );
00653 }
00654 else if ( m_activefill.GetType() == a2dFILL_BITMAP )
00655 {
00656 wxBrush dcbrush;
00657
00658 switch( m_activefill.GetStyle() )
00659 {
00660 case a2dFILL_STIPPLE:
00661 case a2dFILL_STIPPLE_MASK_OPAQUE_TRANSPARENT:
00662 case a2dFILL_STIPPLE_MASK_OPAQUE:
00663 {
00664 wxBitmap bmp = m_activefill.GetStipple();
00665 if ( bmp.Ok() )
00666 {
00667 wxDELETE( m_brushImage );
00668 m_brushImage = Bitmap::FromHBITMAP((HBITMAP)bmp.GetHBITMAP(),(HPALETTE)bmp.GetPalette()->GetHPALETTE());
00669 m_current_brush = new TextureBrush(m_brushImage);
00670 }
00671 }
00672 break;
00673 default:
00674 break;
00675 }
00676 }
00677 else if ( m_activefill.GetType() == a2dFILL_GRADIENT_FILL_LINEAR )
00678 {
00679 a2dPoint2D p1 = m_activefill.GetStart();
00680 a2dPoint2D p2 = m_activefill.GetStop();
00681 Color gdicolor1( m_FillOpacityCol1, color1.Red( ), color1.Green( ), color1.Blue( ) );
00682 Color gdicolor2( m_FillOpacityCol2, color2.Red( ), color2.Green( ), color2.Blue( ) );
00683 m_current_brush = new LinearGradientBrush( PointF( p1.m_x,p1.m_y) , PointF( p2.m_x,p2.m_x), gdicolor1, gdicolor2 );
00684 }
00685 else if ( m_activefill.GetType() == a2dFILL_GRADIENT_FILL_RADIAL )
00686 {
00687 Color gdicolor1( m_FillOpacityCol1, color1.Red( ), color1.Green( ), color1.Blue( ) );
00688 Color gdicolor2( m_FillOpacityCol2, color2.Red( ), color2.Green( ), color2.Blue( ) );
00689 double xc = m_activefill.GetCenter().m_x;
00690 double yc = m_activefill.GetCenter().m_y;
00691 double xo = m_activefill.GetFocal().m_x;
00692 double yo = m_activefill.GetFocal().m_y;
00693 double radius = m_activefill.GetRadius();
00694
00695
00696 m_brushPath = new GraphicsPath();
00697 m_brushPath->AddEllipse( (REAL)(xc-radius), (REAL)(yc-radius), (REAL)(2*radius), (REAL)(2*radius));
00698
00699 PathGradientBrush* b = new PathGradientBrush(m_brushPath);
00700 m_current_brush = b;
00701 b->SetCenterPoint( PointF(xo,yo));
00702 b->SetCenterColor(gdicolor1);
00703
00704 Color colors[] = {gdicolor2};
00705 int count = 1;
00706 b->SetSurroundColors(colors, &count);
00707 }
00708
00709 }
00710
00711
00712
00713 void a2dGDIPlusDrawer::DoSetDrawStyle( a2dDrawStyle drawstyle )
00714 {
00715 m_drawstyle = drawstyle;
00716 }
00717
00718 void a2dGDIPlusDrawer::DrawRoundedRectangle( double x, double y, double width, double height, double radius, bool pixelsize )
00719 {
00720 if ( m_disableDrawing )
00721 return;
00722
00723 if ( !width || !height )
00724 return;
00725
00726 if ( pixelsize )
00727 {
00728 width = DeviceToWorldXRel(width);
00729 height = DeviceToWorldYRel(height);
00730 radius = DeviceToWorldXRel(radius);
00731 if(m_yaxis)
00732 height = -height;
00733 }
00734 if ( width < 0 )
00735 {
00736 x += width; width = -width;
00737 }
00738 if ( height < 0 )
00739 {
00740 y += height;
00741 height = -height;
00742 }
00743
00744 if ( fabs(radius) <= 0.00000001 )
00745 {
00746 m_context->SetTransform( _get_gdiplus_user_to_device_transform() );
00747 m_context->FillRectangle(m_current_brush, (REAL) x, (REAL) y, (REAL) width, (REAL) height );
00748 if ( !m_currentstroke.IsNoStroke() && !m_currentstroke.GetStyle() == a2dSTROKE_TRANSPARENT )
00749 m_context->DrawRectangle(m_current_pen, (REAL) x, (REAL) y, (REAL) width, (REAL)height );
00750 return;
00751 }
00752
00753 m_context->SetTransform( _get_gdiplus_user_to_device_transform() );
00754 m_context->FillRectangle(m_current_brush, (REAL) x, (REAL) y, (REAL) width, (REAL) height);
00755 if ( !m_currentstroke.IsNoStroke() && !m_currentstroke.GetStyle() == a2dSTROKE_TRANSPARENT )
00756 m_context->DrawRectangle(m_current_pen, (REAL) x, (REAL) y, (REAL) width, (REAL) height);
00757 }
00758
00759 void a2dGDIPlusDrawer::DrawCircle( double x, double y, double radius )
00760 {
00761 DrawEllipse( x, y, radius*2, radius*2 );
00762 }
00763
00764 void a2dGDIPlusDrawer::DrawPoint( double xc, double yc )
00765 {
00766 m_usertodevice.TransformPoint( xc, yc, xc, yc );
00767 DeviceDrawPixel( xc, yc, m_colour1redStroke, m_colour1greenStroke, m_colour1blueStroke, m_StrokeOpacityCol1 );
00768 }
00769
00770 void a2dGDIPlusDrawer::DrawEllipse( double xc, double yc, double width, double height )
00771 {
00772 if ( m_disableDrawing )
00773 return;
00774
00775 m_context->SetTransform( _get_gdiplus_user_to_device_transform() );
00776 m_context->FillEllipse( m_current_brush, (REAL) xc - width/2, (REAL) yc - height/2, (REAL) width, (REAL) height );
00777
00778 if ( !m_currentstroke.IsNoStroke() && !m_currentstroke.GetStyle() == a2dSTROKE_TRANSPARENT )
00779 m_context->DrawEllipse( m_current_pen, (REAL) xc - width/2, (REAL) yc - height/2, (REAL) width, (REAL) height );
00780 }
00781
00782 void a2dGDIPlusDrawer::DrawImage( const wxImage& image, double xc, double yc, double width, double height, wxUint8 Opacity )
00783 {
00784 if ( m_disableDrawing )
00785 return;
00786
00787
00788
00789
00790 bool hasAlpha = image.HasAlpha();
00791 size_t w = image.GetWidth();
00792 size_t h = image.GetHeight();
00793 Bitmap* bitmap = new Bitmap(w, h, PixelFormat32bppPARGB );
00794 Rect bounds(0,0,w,h);
00795 BitmapData data ;
00796
00797 bitmap->LockBits(&bounds, ImageLockModeWrite,
00798 bitmap->GetPixelFormat(),&data);
00799
00800
00801
00802 UINT* pixels = (UINT*)data.Scan0;
00803
00804 const int srcBytesPerLine = w * 3;
00805 const int dstBytesPerLine = w * 4;
00806 const unsigned char *src = image.GetData() + ((h - 1) * srcBytesPerLine);
00807 const unsigned char *alpha = hasAlpha ? image.GetAlpha() + (h - 1)*w
00808 : NULL;
00809 unsigned char *dstLineStart = (unsigned char *)pixels;
00810 for ( int y = 0; y < h; y++ )
00811 {
00812
00813 unsigned char *dst = dstLineStart;
00814 if ( alpha )
00815 {
00816 for ( int x = 0; x < w; x++ )
00817 {
00818
00819
00820 const unsigned char a = *alpha++;
00821 *dst++ = (unsigned char)((src[2] * a + 127) / 255);
00822 *dst++ = (unsigned char)((src[1] * a + 127) / 255);
00823 *dst++ = (unsigned char)((src[0] * a + 127) / 255);
00824 *dst++ = a;
00825 src += 3;
00826 }
00827 }
00828 else
00829 {
00830 for ( int x = 0; x < w; x++ )
00831 {
00832
00833 *dst++ = (unsigned char)((src[2] * m_OpacityFactor + 127) / 255);
00834 *dst++ = (unsigned char)((src[1] * m_OpacityFactor + 127) / 255);
00835 *dst++ = (unsigned char)((src[0] * m_OpacityFactor + 127) / 255);
00836 *dst++ = m_OpacityFactor;
00837 src += 3;
00838 }
00839 }
00840
00841
00842 src -= 2*srcBytesPerLine;
00843 if ( alpha )
00844 alpha -= 2*w;
00845
00846
00847 dstLineStart += dstBytesPerLine;
00848 }
00849 bitmap->UnlockBits(&data);
00850
00851 if ( bitmap )
00852 m_context->DrawImage(bitmap,(REAL) xc - width/2.0,(REAL) yc - height/2.0,(REAL) width,(REAL) height) ;
00853 delete bitmap;
00854 }
00855
00856 void a2dGDIPlusDrawer::DrawImage( const a2dImageRGBA& image, double x, double y, double width, double height, wxUint8 Opacity )
00857 {
00858 if ( m_disableDrawing )
00859 return;
00860
00861
00862 }
00863
00864 #include "Gdipluspixelformats.h"
00865
00866 void a2dGDIPlusDrawer::DeviceDrawPolygon( unsigned int n, bool spline, wxPolygonFillMode fillStyle )
00867 {
00868 if ( spline)
00869 n = ConvertSplinedPolygon2(n);
00870
00871 Matrix ident;
00872 m_context->SetTransform( &ident );
00873
00874
00875 if (m_drawstyle == a2dWIREFRAME_INVERT || n == 2)
00876 {
00877 GraphicsPath path;
00878 unsigned int i;
00879 for (i = 0; i < n; i++)
00880 {
00881 if ( i == 0 )
00882 path.StartFigure();
00883 else
00884 path.AddLine( (REAL) m_cpointsDouble[i-1].x, (REAL) m_cpointsDouble[i-1].y, (REAL) m_cpointsDouble[i].x, (REAL) m_cpointsDouble[i].y );
00885 }
00886 path.CloseFigure();
00887 m_context->DrawPath( m_current_pen, &path);
00888 }
00889 else if ( m_currentfill.GetType() == a2dFILL_GRADIENT_FILL_LINEAR || m_currentfill.GetType() == a2dFILL_GRADIENT_FILL_RADIAL )
00890 {
00891 GraphicsPath path;
00892 unsigned int i;
00893 for (i = 0; i < n; i++)
00894 {
00895 if ( i == 0 )
00896 path.StartFigure();
00897 else
00898 path.AddLine( (REAL) m_cpointsDouble[i-1].x, (REAL) m_cpointsDouble[i-1].y, (REAL) m_cpointsDouble[i].x, (REAL) m_cpointsDouble[i].y );
00899 }
00900 path.CloseFigure();
00901 m_context->FillPath( m_current_brush, &path);
00902
00903 if ( !m_currentstroke.IsNoStroke() && !m_currentstroke.GetStyle() == a2dSTROKE_TRANSPARENT )
00904 m_context->DrawPath( m_current_pen, &path);
00905 }
00906 else if ( m_currentfill.GetType() == a2dFILL_BITMAP )
00907 {
00908 GraphicsPath path;
00909 unsigned int i;
00910 for (i = 0; i < n; i++)
00911 {
00912 if ( i == 0 )
00913 path.StartFigure();
00914 else
00915 path.AddLine( (REAL) m_cpointsDouble[i-1].x, (REAL) m_cpointsDouble[i-1].y, (REAL) m_cpointsDouble[i].x, (REAL) m_cpointsDouble[i].y );
00916 }
00917 path.CloseFigure();
00918 m_context->FillPath( m_current_brush, &path);
00919
00920 if ( !m_currentstroke.IsNoStroke() && !m_currentstroke.GetStyle() == a2dSTROKE_TRANSPARENT )
00921 m_context->DrawPath( m_current_pen, &path);
00922 }
00923 else
00924 {
00925 GraphicsPath path;
00926 unsigned int i;
00927 for (i = 0; i < n; i++)
00928 {
00929 if ( i == 0 )
00930 path.StartFigure();
00931 else
00932 path.AddLine( (REAL) m_cpointsDouble[i-1].x, (REAL) m_cpointsDouble[i-1].y, (REAL) m_cpointsDouble[i].x, (REAL) m_cpointsDouble[i].y );
00933 }
00934 path.CloseFigure();
00935 m_context->FillPath( m_current_brush, &path);
00936
00937 if ( !m_currentstroke.IsNoStroke() && !m_currentstroke.GetStyle() == a2dSTROKE_TRANSPARENT )
00938 m_context->DrawPath( m_current_pen, &path);
00939 }
00940
00941 if ( !m_currentstroke.IsSameAs( *a2dTRANSPARENT_STROKE ) && m_currentstroke.GetType() == a2dSTROKE_OBJECT)
00942 {
00943
00944
00945
00946 wxRealPoint* copy = new wxRealPoint[n+1];
00947 memcpy( copy, &m_cpointsDouble[0], n*sizeof( wxRealPoint) );
00948 copy[n].x = m_cpointsDouble[0].x;
00949 copy[n].y = m_cpointsDouble[0].y;
00950
00951
00952 delete [] copy;
00953 }
00954
00955 }
00956
00957 void a2dGDIPlusDrawer::DeviceDrawLines( unsigned int n, bool spline )
00958 {
00959 if ( spline )
00960 n = ConvertSplinedPolyline2(n);
00961
00962 Matrix ident;
00963 m_context->SetTransform( &ident );
00964
00965 GraphicsPath path;
00966 unsigned int i;
00967 for (i = 0; i < n; i++)
00968 {
00969 if ( i == 0 )
00970 path.StartFigure();
00971 else
00972 path.AddLine( (REAL) m_cpointsDouble[i-1].x, (REAL) m_cpointsDouble[i-1].y, (REAL) m_cpointsDouble[i].x, (REAL) m_cpointsDouble[i].y );
00973 }
00974 m_context->DrawPath( m_current_pen, &path);
00975 }
00976
00977 void a2dGDIPlusDrawer::DeviceDrawLine( double x1, double y1, double x2, double y2)
00978 {
00979 Matrix ident;
00980 m_context->SetTransform( &ident );
00981 if ( !m_currentstroke.IsNoStroke() && !m_currentstroke.GetStyle() == a2dSTROKE_TRANSPARENT )
00982 m_context->DrawLine(m_current_pen, (REAL) x1, (REAL) y1, (REAL) x2, (REAL) y2);
00983 }
00984
00985 void a2dGDIPlusDrawer::DeviceDrawHorizontalLine( int x1, int y1, int x2, bool use_stroke_color)
00986 {
00987 if (x1 > x2)
00988 {
00989 int tmp = x1;
00990 x1 = x2;
00991 x2 = tmp;
00992 }
00993
00994
00995 if ( x2 < m_clipboxdev.x)
00996 return;
00997
00998 if ( x1 >= m_clipboxdev.x + m_clipboxdev.width)
00999 return;
01000
01001 if (x1 < m_clipboxdev.x) x1 = m_clipboxdev.x;
01002 if (x2 >= m_clipboxdev.x + m_clipboxdev.width) x2 = m_clipboxdev.x + m_clipboxdev.width -1;
01003 if (y1 >= m_clipboxdev.y && y1 < m_clipboxdev.y + m_clipboxdev.height )
01004 {
01005
01006 Matrix ident;
01007 m_context->SetTransform( &ident );
01008 m_context->DrawLine(m_current_pen, (REAL) x1, (REAL) y1, (REAL) x2, (REAL) y1);
01009 }
01010 }
01011
01012 void a2dGDIPlusDrawer::DeviceDrawVerticalLine( int x1, int y1, int y2, bool use_stroke_color)
01013 {
01014 if (y1 > y2)
01015 {
01016 int tmp = y1;
01017 y1 = y2;
01018 y2 = tmp;
01019 }
01020
01021
01022 if ( y2 < m_clipboxdev.y)
01023 return;
01024
01025 if ( y1 >= m_clipboxdev.y + m_clipboxdev.height)
01026 return;
01027
01028 if (y1 < m_clipboxdev.y) y1 = m_clipboxdev.y;
01029 if (y2 >= m_clipboxdev.y + m_clipboxdev.height) y2 = m_clipboxdev.y + m_clipboxdev.height -1;
01030 if (x1 >= m_clipboxdev.x && x1 < m_clipboxdev.x + m_clipboxdev.width )
01031 {
01032 }
01033 }
01034
01035 void a2dGDIPlusDrawer::DeviceDrawPixel( int x1, int y1, unsigned char r, unsigned char g, unsigned char b, unsigned char a )
01036 {
01037 Matrix ident;
01038 m_context->SetTransform( &ident );
01039 Pen tmp( Color( a, r, g, b ), 1 );
01040 m_context->DrawLine( &tmp, x1, y1, x1, y1 );
01041 }
01042
01043
01044 GraphicsPath *a2dGDIPlusDrawer::createGraphicsPath( a2dVertexList *list, bool spline, wxPolygonFillMode fillStyle )
01045 {
01046 unsigned int n = list->size();
01047 unsigned int i = 0;
01048
01049 GraphicsPath ret;
01050
01051 switch( fillStyle )
01052 {
01053 case wxODDEVEN_RULE:
01054 ret.SetFillMode( FillModeAlternate );
01055 break;
01056 default:
01057 ret.SetFillMode( FillModeWinding );
01058 break;
01059 }
01060
01061 #ifdef wxUSE_INTPOINT
01062 Point *points = new Point[ n ];
01063 #else
01064 PointF *points = new PointF[ n ];
01065 #endif
01066
01067 forEachIn( a2dVertexList, list )
01068 {
01069 a2dPoint2D point = (*iter)->GetPoint();
01070 #ifdef wxUSE_INTPOINT
01071 points[ i ] = Point( point.m_x, point.m_y );
01072 #else
01073 points[ i ] = PointF( point.m_x, point.m_y );
01074 #endif
01075 i++;
01076 }
01077
01078 if( spline == true )
01079 ret.AddCurve( points, n );
01080 else
01081 ret.AddLines( points, n );
01082
01083 delete [ ] points;
01084 return ret.Clone( );
01085 }
01086
01087 void a2dGDIPlusDrawer::BlitBuffer( wxDC* dc, wxRect rect, const wxPoint& bufferpos )
01088 {
01089 if ( rect.x + rect.width > m_buffer.GetWidth() )
01090 rect.width = m_buffer.GetWidth() - rect.x;
01091 if ( rect.y + rect.height > m_buffer.GetHeight() )
01092 rect.height = m_buffer.GetHeight() - rect.y;
01093
01094 if ( ( rect.width > 0 ) && ( rect.height > 0 ) )
01095 {
01096 dc->Blit( rect.x - bufferpos.x, rect.y - bufferpos.y, rect.width, rect.height, m_dc, rect.x, rect.y, wxCOPY, false );
01097 }
01098 }
01099
01100 void a2dGDIPlusDrawer::BlitBuffer( wxRect rect, const wxPoint& bufferpos )
01101 {
01102 BeginDraw();
01103 BlitBuffer( m_deviceDC, rect, bufferpos );
01104 EndDraw();
01105 }
01106
01107 void a2dGDIPlusDrawer::ShiftBuffer( int dxy, bool yshift )
01108 {
01109 int bw = GetBuffer().GetWidth();
01110 int bh = GetBuffer().GetHeight();
01111 if ( yshift )
01112 {
01113 if ( dxy > 0 && dxy < bh )
01114 {
01115 wxRect rect( 0, 0, bw, bh - dxy );
01116 wxBitmap sub_bitmap( m_buffer.GetSubBitmap( rect ) );
01117 wxMemoryDC dcm;
01118 dcm.SelectObject( m_buffer );
01119 dcm.DrawBitmap( sub_bitmap, 0, dxy, true );
01120 dcm.SelectObject( wxNullBitmap );
01121 }
01122 else if ( dxy < 0 && dxy > -bh )
01123 {
01124 wxRect rect( 0, -dxy, bw, bh + dxy );
01125 wxBitmap sub_bitmap( m_buffer.GetSubBitmap( rect ) );
01126 wxMemoryDC dcm;
01127 dcm.SelectObject( m_buffer );
01128 dcm.DrawBitmap( sub_bitmap, 0, 0, true );
01129 dcm.SelectObject( wxNullBitmap );
01130 }
01131 else
01132 wxFAIL_MSG( wxT( "you can only shift within height of buffer" ) );
01133
01134 }
01135 else
01136 {
01137 if ( dxy > 0 && dxy < bw )
01138 {
01139 wxRect rect( 0, 0, bw - dxy, bh );
01140 wxBitmap sub_bitmap( m_buffer.GetSubBitmap( rect ) );
01141 wxMemoryDC dcm;
01142 dcm.SelectObject( m_buffer );
01143 dcm.DrawBitmap( sub_bitmap, dxy, 0, true );
01144 dcm.SelectObject( wxNullBitmap );
01145 }
01146 else if ( dxy < 0 && dxy > -bw )
01147 {
01148 wxRect rect( -dxy, 0, bw + dxy, bh );
01149 wxBitmap sub_bitmap( m_buffer.GetSubBitmap( rect ) );
01150 wxMemoryDC dcm;
01151 dcm.SelectObject( m_buffer );
01152 dcm.DrawBitmap( sub_bitmap, 0, 0, true );
01153 dcm.SelectObject( wxNullBitmap );
01154 }
01155 else
01156 wxFAIL_MSG( wxT( "you can only shift within width of buffer" ) );
01157 }
01158 }
01159
01160 void a2dGDIPlusDrawer::DrawCharStroke( wxChar c )
01161 {
01162 a2dDrawer2D::DrawCharStroke( c );
01163 return;
01164
01165
01166
01167
01168 a2dStroke stroke = a2dStroke( m_activestroke.GetColour(), m_currentfont.GetStrokeWidth() );
01169 a2dStroke oldstroke = m_activestroke;
01170 SetActiveStroke( stroke );
01171
01172
01173 a2dAffineMatrix affine;
01174 affine.Scale( m_currentfont.GetSize() );
01175 PushTransform( affine );
01176
01177 GraphicsPath path;
01178 a2dVertexList** ptr = m_currentfont.GetGlyphStroke(c);
01179 if (ptr)
01180 {
01181 while (*ptr)
01182 {
01183 a2dVertexList::iterator iter = (*ptr)->begin();
01184 if ( (*ptr)->size() )
01185 {
01186 path.StartFigure();
01187 }
01188 while ( iter != (*ptr)->end() )
01189 {
01190 a2dPoint2D point = (*iter)->GetPoint();
01191 path.AddLine( (REAL) point.m_x, (REAL) point.m_y, (REAL) point.m_x, (REAL) point.m_y );
01192 iter++;
01193 }
01194 ptr++;
01195 }
01196 }
01197
01198 m_context->DrawPath( m_current_pen, &path);
01199
01200
01201 PopTransform();
01202 SetActiveStroke( oldstroke );
01203 }
01204
01205
01206 void a2dGDIPlusDrawer::DrawCharFreetype( wxChar c )
01207 {
01208 double x, y;
01209 x = y = 0.0;
01210
01211 if ( m_disableDrawing )
01212 return;
01213
01214 #if wxART2D_USE_FREETYPE
01215 y += m_currentfont.GetDescent();
01216
01217 double scale = m_currentfont.GetSize() / (64 * FTNORMFONT);
01218
01219 FT_Glyph glyph = m_currentfont.GetGlyphFreetype( c )->m_glyph;
01220 if (glyph->format != FT_GLYPH_FORMAT_OUTLINE)
01221 return;
01222 FT_Outline& outline = ((FT_OutlineGlyph) glyph)->outline;
01223
01224 FT_Vector v_last;
01225 FT_Vector v_control;
01226 FT_Vector v_start;
01227
01228 FT_Vector* point;
01229 FT_Vector* limit;
01230 char* tags;
01231
01232 int n;
01233 int first;
01234 char tag;
01235
01236 first = 0;
01237
01238 GraphicsPath path;
01239 a2dPoint2D pointprev;
01240 for(n = 0; n < outline.n_contours; n++)
01241 {
01242 int last;
01243
01244 last = outline.contours[n];
01245 limit = outline.points + last;
01246
01247 v_start = outline.points[first];
01248 v_last = outline.points[last];
01249
01250 v_control = v_start;
01251
01252 point = outline.points + first;
01253 tags = outline.tags + first;
01254 tag = FT_CURVE_TAG(tags[0]);
01255
01256
01257 if(tag == FT_CURVE_TAG_CUBIC) return;
01258
01259
01260 if( tag == FT_CURVE_TAG_CONIC)
01261 {
01262
01263 if(FT_CURVE_TAG(outline.tags[last]) == FT_CURVE_TAG_ON)
01264 {
01265
01266 v_start = v_last;
01267 limit--;
01268 }
01269 else
01270 {
01271
01272
01273
01274 v_start.x = (v_start.x + v_last.x) / 2;
01275 v_start.y = (v_start.y + v_last.y) / 2;
01276
01277 v_last = v_start;
01278 }
01279 point--;
01280 tags--;
01281 }
01282
01283 path.StartFigure();
01284 pointprev = a2dPoint2D( v_start.x, v_start.y);
01285 path.AddLine( (REAL) v_start.x, (REAL) v_start.y, (REAL) v_start.x, (REAL) v_start.y );
01286
01287 while(point < limit)
01288 {
01289 point++;
01290 tags++;
01291
01292 tag = FT_CURVE_TAG(tags[0]);
01293 switch(tag)
01294 {
01295 case FT_CURVE_TAG_ON:
01296 {
01297 path.AddLine( (REAL) point->x, (REAL) point->y, (REAL) point->x, (REAL) point->y );
01298 continue;
01299 }
01300
01301 case FT_CURVE_TAG_CONIC:
01302 {
01303 v_control.x = point->x;
01304 v_control.y = point->y;
01305
01306 Do_Conic:
01307 if(point < limit)
01308 {
01309 FT_Vector vec;
01310 FT_Vector v_middle;
01311
01312 point++;
01313 tags++;
01314 tag = FT_CURVE_TAG(tags[0]);
01315
01316 vec.x = point->x;
01317 vec.y = point->y;
01318
01319 if(tag == FT_CURVE_TAG_ON)
01320 {
01321 PointF c1(v_control.x, v_control.y);
01322 PointF c2(v_control.x, v_control.y);
01323 PointF end(vec.x, vec.y);
01324 PointF start;
01325 path.GetLastPoint(&start);
01326 path.AddBezier(start,c1,c2,end);
01327 continue;
01328 }
01329
01330 if(tag != FT_CURVE_TAG_CONIC) return;
01331
01332 v_middle.x = (v_control.x + vec.x) / 2;
01333 v_middle.y = (v_control.y + vec.y) / 2;
01334
01335 PointF c1(v_control.x, v_control.y);
01336 PointF c2(v_control.x, v_control.y);
01337 PointF end(v_middle.x, v_middle.y);
01338 PointF start;
01339 path.GetLastPoint(&start);
01340 path.AddBezier(start,c1,c2,end);
01341
01342 v_control = vec;
01343 goto Do_Conic;
01344 }
01345 PointF c1(v_control.x, v_control.y);
01346 PointF c2(v_control.x, v_control.y);
01347 PointF end(v_start.x, v_start.y);
01348 PointF start;
01349 path.GetLastPoint(&start);
01350 path.AddBezier(start,c1,c2,end);
01351 goto Close;
01352 }
01353
01354 default:
01355 {
01356 FT_Vector vec1, vec2;
01357
01358 if(point + 1 > limit || FT_CURVE_TAG(tags[1]) != FT_CURVE_TAG_CUBIC)
01359 {
01360 return;
01361 }
01362
01363 vec1.x = point[0].x;
01364 vec1.y = point[0].y;
01365 vec2.x = point[1].x;
01366 vec2.y = point[1].y;
01367
01368 point += 2;
01369 tags += 2;
01370
01371 if(point <= limit)
01372 {
01373 FT_Vector vec;
01374
01375 vec.x = point->x;
01376 vec.y = point->y;
01377
01378 PointF c1(vec1.x, vec1.y);
01379 PointF c2(vec2.x, vec2.y);
01380 PointF end(vec.x, vec.y);
01381 PointF start;
01382 path.GetLastPoint(&start);
01383 path.AddBezier(start,c1,c2,end);
01384
01385 continue;
01386 }
01387
01388 PointF c1(vec1.x, vec1.y);
01389 PointF c2(vec2.x, vec2.y);
01390 PointF end(v_start.x, v_start.y);
01391 PointF start;
01392 path.GetLastPoint(&start);
01393 path.AddBezier(start,c1,c2,end);
01394
01395 goto Close;
01396 }
01397 }
01398 }
01399
01400 path.CloseFigure();
01401
01402 Close:
01403 first = last + 1;
01404 }
01405
01406
01407 a2dAffineMatrix affine;
01408 affine.Scale( scale );
01409 affine.Translate( x, y );
01410 affine = GetUserToDeviceTransform() * affine;
01411
01412 Matrix charTransform(
01413 (REAL)affine(0,0),(REAL)affine(0,1),
01414 (REAL)affine(1,0),(REAL)affine(1,1),
01415 (REAL)affine(2,0),(REAL)affine(2,1) );
01416
01417 m_context->SetTransform( &charTransform );
01418
01419 wxColour color1 = m_currentstroke.GetColour();
01420 Color gdicolor1( m_StrokeOpacityCol1, color1.Red( ), color1.Green( ), color1.Blue( ) );
01421 SolidBrush* text_brush = new SolidBrush( gdicolor1 );
01422 m_context->FillPath( text_brush, &path);
01423 #else // wxART2D_USE_FREETYPE
01424 a2dDrawer2D::DrawCharFreetype( c );
01425 #endif // wxART2D_USE_FREETYPE
01426 }
01427
01428 void a2dGDIPlusDrawer::DrawCharDc( wxChar c )
01429 {
01430 #if wxART2D_USE_FREETYPE && defined(__USE_WINAPI__)
01431 if ( m_currentfont.GetType() == a2dFONT_WXDC && m_currentfont.GetFreetypeFont().Ok())
01432 {
01433 a2dFont oldfont = m_currentfont;
01434 m_currentfont = m_currentfont.GetFreetypeFont();
01435 DrawCharFreetype( c );
01436 m_currentfont = oldfont;
01437 }
01438 else
01439 a2dDrawer2D::DrawCharDc( c );
01440 #else // wxART2D_USE_FREETYPE && defined(__USE_WINAPI__)
01441 a2dDrawer2D::DrawCharDc( c );
01442 #endif // wxART2D_USE_FREETYPE && defined(__USE_WINAPI__)
01443 }
01444
01445 void a2dGDIPlusDrawer::DrawTextDc( const wxString& text, double x, double y )
01446 {
01447 a2dDrawer2D::DrawTextDc( text, x, y );
01448 return;
01449
01450
01451
01452
01453
01454
01455
01456
01457
01458
01459
01460
01461
01462
01463
01464
01465
01466
01467
01468
01469
01470 }
01471
01472 #endif // wxART2D_USE_GDIPLUS_DRAWER