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 #include <wx/wfstream.h>
00021 #include "wx/artbase/drawer2d.h"
00022 #include "wx/artbase/stylebase.h"
00023 #include "wx/artbase/dcdrawer.h"
00024
00025 #if defined(__WXMSW__)
00026 #include "wx/artbase/mswfont.h"
00027 #endif
00028 #endif
00029
00030 #if defined(__WXMSW__)
00031 #include "wx/msw/dc.h"
00032 #include <wx/msw/private.h>
00033 #elif __WXGTK__
00034 #include <gtk/gtk.h>
00035 #include <gdk/gdkrgb.h>
00036 #include <wx/dcps.h>
00037 #if wxCHECK_VERSION(2,9,0)
00038 #include "wx/gtk/dcclient.h"
00039 #else
00040 #include "wx/gtk/win_gtk.h"
00041 #endif
00042 #endif
00043
00044 #if wxART2D_USE_AGGDRAWER
00045 #include "wx/aggdrawer/aggdrawer.h"
00046 #endif
00047
00048
00049 #if wxART2D_USE_FREETYPE
00050 #include <ft2build.h>
00051 #ifdef _MSC_VER
00052
00053
00054 #include <freetype/freetype.h>
00055 #include <freetype/ftoutln.h>
00056 #else // _MSC_VER
00057
00058 #include FT_FREETYPE_H
00059 #include FT_OUTLINE_H
00060 #endif // _MSC_VER
00061 #endif
00062
00063
00064 IMPLEMENT_DYNAMIC_CLASS( a2dDcDrawer, a2dDrawer2D )
00065 IMPLEMENT_DYNAMIC_CLASS( a2dMemDcDrawer, a2dDcDrawer )
00066
00067
00068
00069
00070
00071 a2dDcDrawer::a2dDcDrawer( const wxSize& size ): a2dDrawer2D( size )
00072 {
00073 m_externalDc = false;
00074 m_renderDC = m_deviceDC = 0;
00075 m_clip.Clear();
00076 }
00077
00078 a2dDcDrawer::a2dDcDrawer( int width, int height ): a2dDrawer2D( width, height )
00079 {
00080 m_externalDc = false;
00081 m_renderDC = m_deviceDC = 0;
00082 m_clip.Clear();
00083 }
00084
00085 a2dDcDrawer::~a2dDcDrawer()
00086 {}
00087
00088 a2dDcDrawer::a2dDcDrawer( const a2dDcDrawer& other )
00089 : a2dDrawer2D( other )
00090 {
00091 m_externalDc = false;
00092 m_renderDC = m_deviceDC = 0;
00093 m_clip.Clear();
00094 }
00095
00096 a2dDcDrawer::a2dDcDrawer( const a2dDrawer2D& other )
00097 : a2dDrawer2D( other )
00098 {
00099 m_externalDc = false;
00100 m_renderDC = m_deviceDC = 0;
00101 m_clip.Clear();
00102 }
00103
00104 void a2dDcDrawer::BeginDraw()
00105 {
00106 wxASSERT_MSG( m_beginDraw_endDraw >= 0, wxT( "a2dDcDrawer, unbalanced BeginDraw EndDraw" ) );
00107
00108 if ( m_beginDraw_endDraw == 0 )
00109 {
00110 if ( m_externalDc )
00111 {
00112 wxASSERT_MSG( true == m_externalDc, wxT( "a2dDcDrawer, wxClientDc not set yet" ) );
00113 }
00114 else
00115 {
00116 wxASSERT_MSG( m_renderDC == NULL, wxT( "a2dMemDcDrawer, unbalanced BeginDraw EndDraw" ) );
00117
00118 if ( m_display )
00119 {
00120 m_deviceDC = new wxClientDC( m_display );
00121 m_display->PrepareDC( *m_deviceDC );
00122 }
00123 m_renderDC = m_deviceDC;
00124 }
00125
00126 DestroyClippingRegion();
00127 SetDrawerFill( m_currentfill );
00128 SetDrawerStroke( m_currentstroke );
00129 SetDrawStyle( m_drawstyle );
00130 m_OpacityFactor = 255;
00131 m_renderDC->SetMapMode( wxMM_TEXT );
00132 }
00133 m_beginDraw_endDraw++;
00134 }
00135
00136 void a2dDcDrawer::EndDraw()
00137 {
00138 m_beginDraw_endDraw--;
00139
00140 wxASSERT_MSG( m_beginDraw_endDraw >= 0, wxT( "a2dDcDrawer, unbalanced BeginDraw EndDraw" ) );
00141
00142 if ( m_beginDraw_endDraw == 0 )
00143 {
00144 wxASSERT_MSG( m_renderDC != NULL, wxT( "a2dDcDrawer, unbalanced BeginDraw EndDraw" ) );
00145 if ( m_externalDc )
00146 {
00147 wxASSERT_MSG( true == m_externalDc, wxT( "a2dDcDrawer, wxClientDc not set yet" ) );
00148 }
00149 else
00150 {
00151 if ( m_display )
00152 delete m_deviceDC;
00153 }
00154
00155 m_renderDC = m_deviceDC = NULL;
00156 }
00157
00158 }
00159
00160 void a2dDcDrawer::SetBufferSize( int w, int h )
00161 {
00162 m_width = w;
00163 m_height = h;
00164 }
00165
00166 wxBitmap a2dDcDrawer::GetSubBitmap( wxRect rect ) const
00167 {
00168
00169 #ifdef __WXGTK__
00170 wxFAIL_MSG( wxT( "a2dDcDrawer has no buffer" ) );
00171 #endif
00172 wxASSERT_MSG( m_renderDC, wxT( "no renderDc set" ) );
00173
00174 #ifdef __WXGTK__
00175 wxBitmap ret( rect.width, rect.height, 32 );
00176 #else
00177 wxBitmap ret( rect.width, rect.height, m_renderDC->GetDepth() );
00178 #endif
00179 wxASSERT_MSG( ret.Ok(), wxT( "GetSubImage error" ) );
00180
00181 if ( m_renderDC )
00182 {
00183
00184 wxMemoryDC dcb;
00185 dcb.SelectObject( ret );
00186 dcb.Blit( 0, 0, rect.width, rect.height, m_renderDC, rect.x, rect.y, wxCOPY, false );
00187 dcb.SelectObject( wxNullBitmap );
00188 }
00189 return ret;
00190 }
00191
00192 void a2dDcDrawer::SetRenderDC( wxDC* dc )
00193 {
00194 if ( dc == NULL )
00195 {
00196 m_externalDc = false;
00197 m_renderDC = m_deviceDC = NULL;
00198 }
00199 else
00200 {
00201 m_externalDc = true;
00202 m_renderDC = dc;
00203 }
00204 }
00205
00206 void a2dDcDrawer::SetClippingRegion( a2dVertexList* points, bool spline, wxPolygonFillMode fillStyle )
00207 {
00208 wxASSERT_MSG( m_renderDC, wxT( "no renderDc set" ) );
00209 unsigned int n = points->size();
00210
00211 m_cpointsDouble.resize( n );
00212
00213 unsigned int i = 0;
00214 double x, y;
00215 forEachIn( a2dVertexList, points )
00216 {
00217 a2dPoint2D point = ( *iter )->GetPoint();
00218
00219 GetUserToDeviceTransform().TransformPoint( point.m_x, point.m_y, x, y );
00220 m_cpointsDouble[i].x = x;
00221 m_cpointsDouble[i].y = y;
00222 i++;
00223 }
00224
00225 if ( spline )
00226 n = ConvertSplinedPolygon2( n );
00227
00228 wxPoint *intpoints = _convertToIntPointCache( n, &m_cpointsDouble[0] );
00229 m_clip = wxRegion( n, intpoints, fillStyle );
00230
00231 wxCoord originX, originY;
00232 m_renderDC->GetDeviceOrigin( &originX, &originY );
00233 m_clip.Offset( originX, originY );
00234 m_renderDC->DestroyClippingRegion();
00235 #if wxCHECK_VERSION(2,9,0)
00236 m_renderDC->SetDeviceClippingRegion( m_clip );
00237 #else
00238 m_renderDC->SetClippingRegion( m_clip );
00239 #endif
00240 m_clipboxdev = m_clip.GetBox();
00241 m_clipboxdev.Offset( -originX, -originY );
00242 m_clipboxworld = ToWorld( m_clipboxdev );
00243 }
00244
00245 void a2dDcDrawer::ExtendAndPushClippingRegion( a2dVertexList* points, bool spline, wxPolygonFillMode fillStyle, a2dBooleanClip clipoperation )
00246 {
00247
00248 wxASSERT_MSG( m_renderDC, wxT( "no renderDc set" ) );
00249
00250 wxRegion* push = new wxRegion( m_clip );
00251
00252 m_clipregionlist.Insert( push );
00253
00254 ExtendClippingRegion( points, spline, fillStyle, clipoperation );
00255 }
00256
00257 void a2dDcDrawer::ExtendClippingRegion( a2dVertexList* points, bool spline, wxPolygonFillMode WXUNUSED( fillStyle ), a2dBooleanClip clipoperation )
00258 {
00259 wxASSERT_MSG( m_renderDC, wxT( "no renderDc set" ) );
00260
00261 wxRegion totaladd;
00262 bool first = false;
00263
00264 a2dBoundingBox devbox;
00265 bool smallPoly = false;
00266 unsigned int segments = ToDeviceLines( points, devbox, smallPoly );
00267
00268 if ( segments == 0 )
00269 return;
00270
00271 if ( spline )
00272 segments = ConvertSplinedPolygon2( segments );
00273
00274 wxPoint *int_cpts = _convertToIntPointCache( segments, &m_cpointsDouble[0] );
00275 wxRegion add = wxRegion( segments, int_cpts, wxWINDING_RULE );
00276 wxCoord originX, originY;
00277 m_renderDC->GetDeviceOrigin( &originX, &originY );
00278 add.Offset( originX, originY );
00279 if ( !first )
00280 {
00281 totaladd = add;
00282 first = true;
00283 }
00284 else
00285 totaladd.Union( add );
00286
00287 if ( !m_clip.Empty() )
00288 {
00289 bool result;
00290 switch ( clipoperation )
00291 {
00292 case a2dCLIP_AND:
00293 result = m_clip.Intersect( totaladd );
00294 break ;
00295
00296 case a2dCLIP_OR:
00297 result = m_clip.Union( totaladd );
00298 break ;
00299
00300 case a2dCLIP_XOR:
00301 result = m_clip.Xor( totaladd );
00302 break ;
00303
00304 case a2dCLIP_DIFF:
00305 result = m_clip.Subtract( totaladd );
00306 break ;
00307
00308 case a2dCLIP_COPY:
00309 default:
00310 m_clip = totaladd;
00311 result = true;
00312 break ;
00313 }
00314 if ( result )
00315 {
00316 m_renderDC->DestroyClippingRegion();
00317 #if wxCHECK_VERSION(2,9,0)
00318 m_renderDC->SetDeviceClippingRegion( m_clip );
00319 #else
00320 m_renderDC->SetClippingRegion( m_clip );
00321 #endif
00322 }
00323 }
00324 else
00325 {
00326 m_clip = totaladd;
00327 m_renderDC->DestroyClippingRegion();
00328 #if wxCHECK_VERSION(2,9,0)
00329 m_renderDC->SetDeviceClippingRegion( m_clip );
00330 #else
00331 m_renderDC->SetClippingRegion( m_clip );
00332 #endif
00333 }
00334
00335 m_clipboxdev = m_clip.GetBox();
00336 m_clipboxdev.Offset( -originX, -originY );
00337 m_clipboxworld = ToWorld( m_clipboxdev );
00338 }
00339
00340 void a2dDcDrawer::PopClippingRegion()
00341 {
00342 wxASSERT_MSG( m_renderDC, wxT( "no renderDc set" ) );
00343 if ( !m_clipregionlist.GetCount() )
00344 return;
00345
00346 m_clip = *m_clipregionlist.GetFirst()->GetData();
00347 delete m_clipregionlist.GetFirst()->GetData();
00348 m_clipregionlist.DeleteNode( m_clipregionlist.GetFirst() );
00349
00350 m_renderDC->DestroyClippingRegion();
00351 #if wxCHECK_VERSION(2,9,0)
00352 m_renderDC->SetDeviceClippingRegion( m_clip );
00353 #else
00354 m_renderDC->SetClippingRegion( m_clip );
00355 #endif
00356 m_clipboxdev = m_clip.GetBox();
00357 wxCoord originX, originY;
00358 m_renderDC->GetDeviceOrigin( &originX, &originY );
00359 m_clipboxdev.Offset( -originX, -originY );
00360 m_clipboxworld = ToWorld( m_clipboxdev );
00361
00362 }
00363
00364 void a2dDcDrawer::SetClippingRegionDev( wxCoord minx, wxCoord miny, wxCoord width, wxCoord height )
00365 {
00366 wxASSERT_MSG( m_renderDC, wxT( "no renderDc set" ) );
00367 m_clip = wxRegion( minx, miny, width, height );
00368 wxCoord originX, originY;
00369 m_renderDC->GetDeviceOrigin( &originX, &originY );
00370 m_clip.Offset( originX, originY );
00371 m_renderDC->DestroyClippingRegion();
00372 #if wxCHECK_VERSION(2,9,0)
00373 m_renderDC->SetDeviceClippingRegion( m_clip );
00374 #else
00375 m_renderDC->SetClippingRegion( m_clip );
00376 #endif
00377
00378 m_clipboxdev = wxRect( minx, miny, width, height );
00379 m_clipboxworld = ToWorld( m_clipboxdev );
00380 }
00381
00382 void a2dDcDrawer::SetClippingRegion( double minx, double miny, double maxx, double maxy )
00383 {
00384 wxASSERT_MSG( m_renderDC, wxT( "no renderDc set" ) );
00385 int iminx = WorldToDeviceX( minx );
00386 int iminy = WorldToDeviceY( miny );
00387 int imaxx = WorldToDeviceX( maxx );
00388 int imaxy = WorldToDeviceY( maxy );
00389 if ( m_yaxis )
00390 {
00391 m_clip = wxRegion( iminx, imaxy, imaxx - iminx, iminy - imaxy );
00392 m_clipboxdev = wxRect( iminx, imaxy, imaxx - iminx, iminy - imaxy );
00393 }
00394 else
00395 {
00396 m_clip = wxRegion( iminx, iminy, imaxx - iminx, imaxy - iminy );
00397 m_clipboxdev = wxRect( iminx, iminy, imaxx - iminx, imaxy - iminy );
00398 }
00399
00400 m_clipboxworld = ToWorld( m_clipboxdev );
00401
00402 m_renderDC->DestroyClippingRegion();
00403 wxCoord originX, originY;
00404 m_renderDC->GetDeviceOrigin( &originX, &originY );
00405 m_clip.Offset( originX, originY );
00406 #if wxCHECK_VERSION(2,9,0)
00407 m_renderDC->SetDeviceClippingRegion( m_clip );
00408 #else
00409 m_renderDC->SetClippingRegion( m_clip );
00410 #endif
00411 }
00412
00413 void a2dDcDrawer::DestroyClippingRegion()
00414 {
00415 m_clip.Clear();
00416 if ( m_renderDC )
00417 m_renderDC->DestroyClippingRegion();
00418
00419 m_clipboxdev = wxRect( 0, 0, m_width, m_height );
00420 m_clipboxworld = ToWorld( m_clipboxdev );
00421 }
00422
00423 void a2dDcDrawer::ResetStyle()
00424 {
00425 a2dDrawer2D::ResetStyle();
00426 SetDrawerFill( *a2dBLACK_FILL );
00427 SetDrawerStroke( *a2dBLACK_STROKE );
00428 SetDrawStyle( m_drawstyle );
00429 }
00430
00431 void a2dDcDrawer::DoSetActiveStroke()
00432 {
00433 if ( m_renderDC )
00434 {
00435 if ( m_activestroke.GetStyle() == a2dSTROKE_TRANSPARENT )
00436 {
00437 m_renderDC->SetPen( *wxTRANSPARENT_PEN );
00438 }
00439 else if ( m_activestroke.IsNoStroke() )
00440 {
00441 m_renderDC->SetPen( *wxTRANSPARENT_PEN );
00442
00443
00444 }
00445 else if ( m_drawstyle == a2dWIREFRAME_INVERT_ZERO_WIDTH )
00446 {
00447 m_renderDC->SetPen( *wxBLACK_PEN );
00448 }
00449 else if ( m_activestroke.GetType() == a2dSTROKE_ONE_COLOUR )
00450 {
00451 int style;
00452 switch( m_activestroke.GetStyle() )
00453 {
00454 case a2dSTROKE_SOLID: style = wxSOLID;
00455 break;
00456 case a2dSTROKE_TRANSPARENT: style = wxTRANSPARENT;
00457 break;
00458 case a2dSTROKE_DOT: style = wxDOT;
00459 break;
00460 case a2dSTROKE_DOT_DASH: style = wxDOT_DASH;
00461 break;
00462 case a2dSTROKE_LONG_DASH: style = wxLONG_DASH;
00463 break;
00464 case a2dSTROKE_SHORT_DASH: style = wxSHORT_DASH;
00465 break;
00466 case a2dSTROKE_BDIAGONAL_HATCH: style = wxBDIAGONAL_HATCH;
00467 break;
00468 case a2dSTROKE_CROSSDIAG_HATCH: style = wxCROSSDIAG_HATCH;
00469 break;
00470 case a2dSTROKE_FDIAGONAL_HATCH: style = wxFDIAGONAL_HATCH;
00471 break;
00472 case a2dSTROKE_CROSS_HATCH: style = wxCROSS_HATCH;
00473 break;
00474 case a2dSTROKE_HORIZONTAL_HATCH: style = wxHORIZONTAL_HATCH;
00475 break;
00476 case a2dSTROKE_VERTICAL_HATCH: style = wxVERTICAL_HATCH;
00477 break;
00478 case a2dSTROKE_STIPPLE: style = wxSTIPPLE;
00479 break;
00480 case a2dSTROKE_STIPPLE_MASK_OPAQUE: style = wxSTIPPLE_MASK_OPAQUE;
00481 break;
00482 default: style = a2dSTROKE_SOLID;
00483 }
00484
00485 if ( m_drawstyle == a2dWIREFRAME_ZERO_WIDTH )
00486 {
00487 wxPen dcpen( m_activestroke.GetColour(), 0, style );
00488 m_renderDC->SetPen( dcpen );
00489 m_renderDC->SetTextForeground( m_activestroke.GetColour() );
00490 }
00491 else
00492 {
00493 wxPen dcpen( m_activestroke.GetColour(), ( int ) m_activestroke.GetWidth(), style );
00494 dcpen.SetJoin( m_activestroke.GetJoin() );
00495 dcpen.SetCap( m_activestroke.GetCap() );
00496 if ( !m_activestroke.GetPixelStroke() )
00497 {
00498 int widthDev = ( int ) WorldToDeviceXRel( m_activestroke.GetWidth() );
00499 dcpen.SetWidth( widthDev );
00500 }
00501 m_renderDC->SetPen( dcpen );
00502 m_renderDC->SetTextForeground( m_activestroke.GetColour() );
00503 }
00504
00505 }
00506 else if ( m_activestroke.GetType() == a2dSTROKE_BITMAP )
00507 {
00508 wxPen dcpen;
00509
00510 if ( m_drawstyle == a2dWIREFRAME_ZERO_WIDTH )
00511 dcpen = wxPen( m_activestroke.GetColour(), 0, wxBRUSHSTYLE_SOLID );
00512 else
00513 {
00514 int width = (int) m_activestroke.GetWidth();
00515 if ( !m_activestroke.GetPixelStroke() )
00516 width = ( int )WorldToDeviceXRel( width );
00517 dcpen = wxPen( m_activestroke.GetColour(), width, wxBRUSHSTYLE_SOLID );
00518 dcpen.SetJoin( m_activestroke.GetJoin() );
00519 dcpen.SetCap( m_activestroke.GetCap() );
00520 }
00521
00522 #if defined(__WXMSW__)
00523 wxBrushStyle style;
00524 switch( m_activestroke.GetStyle() )
00525 {
00526 case a2dSTROKE_STIPPLE:
00527 style = wxBRUSHSTYLE_STIPPLE;
00528 dcpen.SetStyle( style );
00529 dcpen.SetStipple( m_activestroke.GetStipple() );
00530 break;
00531 case a2dSTROKE_STIPPLE_MASK_OPAQUE_TRANSPARENT:
00532 case a2dSTROKE_STIPPLE_MASK_OPAQUE:
00533 if ( 0 )
00534 {
00535 wxBitmap noMask = m_activestroke.GetStipple();
00536 noMask.SetMask( NULL );
00537 style = wxBRUSHSTYLE_STIPPLE;
00538 dcpen.SetStyle( style );
00539 dcpen.SetStipple( noMask );
00540 }
00541 else
00542 {
00543 style = wxBRUSHSTYLE_STIPPLE_MASK_OPAQUE;
00544 dcpen.SetStyle( style );
00545 dcpen.SetStipple( m_activestroke.GetStipple() );
00546 }
00547 break;
00548 default: style = wxBRUSHSTYLE_SOLID;
00549 dcpen.SetStyle( style );
00550 }
00551 #endif
00552
00553 m_renderDC->SetPen( dcpen );
00554 m_renderDC->SetTextBackground( *wxBLACK );
00555 m_renderDC->SetTextForeground( m_activestroke.GetColour() );
00556 }
00557
00558 }
00559 }
00560
00561 void a2dDcDrawer::DoSetActiveFill()
00562 {
00563 if ( m_renderDC )
00564 {
00565 if ( !m_activefill.GetFilling() )
00566 {
00567 m_renderDC->SetBrush( *wxTRANSPARENT_BRUSH );
00568 m_renderDC->SetTextBackground( *wxBLACK );
00569 }
00570 else if ( m_activefill.GetStyle() == a2dFILL_TRANSPARENT )
00571 {
00572 m_renderDC->SetBrush( *wxTRANSPARENT_BRUSH );
00573 m_renderDC->SetTextBackground( *wxBLACK );
00574 }
00575 else if ( m_activefill.IsNoFill() )
00576 {
00577 m_renderDC->SetBrush( *wxTRANSPARENT_BRUSH );
00578
00579 m_renderDC->SetTextBackground( *wxBLACK );
00580 }
00581 else if ( m_activefill.GetType() == a2dFILL_ONE_COLOUR )
00582 {
00583 wxBrush dcbrush;
00584 wxBrushStyle style;
00585 switch( m_activefill.GetStyle() )
00586 {
00587 case a2dFILL_TRANSPARENT:
00588 style = wxBRUSHSTYLE_TRANSPARENT;
00589 dcbrush.SetColour( m_activefill.GetColour() );
00590 dcbrush.SetStyle( style );
00591 break;
00592 case a2dFILL_SOLID: style = wxBRUSHSTYLE_SOLID;
00593 dcbrush.SetColour( m_activefill.GetColour() );
00594 dcbrush.SetStyle( style );
00595 break;
00596 case a2dFILL_BDIAGONAL_HATCH:
00597 style = wxBRUSHSTYLE_BDIAGONAL_HATCH;
00598 dcbrush.SetColour( m_activefill.GetColour() );
00599 dcbrush.SetStyle( style );
00600 break;
00601 case a2dFILL_CROSSDIAG_HATCH:
00602 style = wxBRUSHSTYLE_CROSSDIAG_HATCH;
00603 dcbrush.SetColour( m_activefill.GetColour() );
00604 dcbrush.SetStyle( style );
00605 break;
00606 case a2dFILL_FDIAGONAL_HATCH:
00607 style = wxBRUSHSTYLE_FDIAGONAL_HATCH;
00608 dcbrush.SetColour( m_activefill.GetColour() );
00609 dcbrush.SetStyle( style );
00610 break;
00611 case a2dFILL_CROSS_HATCH:
00612 style = wxBRUSHSTYLE_CROSS_HATCH;
00613 dcbrush.SetColour( m_activefill.GetColour() );
00614 dcbrush.SetStyle( style );
00615 break;
00616 case a2dFILL_HORIZONTAL_HATCH:
00617 style = wxBRUSHSTYLE_HORIZONTAL_HATCH;
00618 dcbrush.SetColour( m_activefill.GetColour() );
00619 dcbrush.SetStyle( style );
00620 break;
00621 case a2dFILL_VERTICAL_HATCH:
00622 style = wxBRUSHSTYLE_VERTICAL_HATCH;
00623 dcbrush.SetColour( m_activefill.GetColour() );
00624 dcbrush.SetStyle( style );
00625 break;
00626 default: style = wxBRUSHSTYLE_SOLID;
00627 dcbrush.SetColour( m_activefill.GetColour() );
00628 dcbrush.SetStyle( style );
00629 }
00630
00631 m_renderDC->SetBrush( dcbrush );
00632 m_renderDC->SetTextBackground( m_activefill.GetColour() );
00633 }
00634 else if ( m_activefill.GetType() == a2dFILL_HATCH_TWO_COLOUR )
00635 {
00636 wxBrush dcbrush;
00637 wxBrushStyle style;
00638 switch( m_activefill.GetStyle() )
00639 {
00640 case a2dFILL_TRANSPARENT:
00641 style = wxBRUSHSTYLE_TRANSPARENT;
00642 dcbrush.SetColour( m_activefill.GetColour() );
00643 dcbrush.SetStyle( style );
00644 break;
00645 case a2dFILL_TWOCOL_BDIAGONAL_HATCH:
00646 style = wxBRUSHSTYLE_BDIAGONAL_HATCH;
00647 dcbrush.SetColour( m_activefill.GetColour() );
00648 dcbrush.SetStyle( style );
00649 break;
00650 case a2dFILL_TWOCOL_CROSSDIAG_HATCH:
00651 style = wxBRUSHSTYLE_CROSSDIAG_HATCH;
00652 dcbrush.SetColour( m_activefill.GetColour() );
00653 dcbrush.SetStyle( style );
00654 break;
00655 case a2dFILL_TWOCOL_FDIAGONAL_HATCH:
00656 style = wxBRUSHSTYLE_FDIAGONAL_HATCH;
00657 dcbrush.SetColour( m_activefill.GetColour() );
00658 dcbrush.SetStyle( style );
00659 break;
00660 case a2dFILL_TWOCOL_CROSS_HATCH:
00661 style = wxBRUSHSTYLE_CROSS_HATCH;
00662 dcbrush.SetColour( m_activefill.GetColour() );
00663 dcbrush.SetStyle( style );
00664 break;
00665 case a2dFILL_TWOCOL_HORIZONTAL_HATCH:
00666 style = wxBRUSHSTYLE_HORIZONTAL_HATCH;
00667 dcbrush.SetColour( m_activefill.GetColour() );
00668 dcbrush.SetStyle( style );
00669 break;
00670 case a2dFILL_TWOCOL_VERTICAL_HATCH:
00671 style = wxBRUSHSTYLE_VERTICAL_HATCH;
00672 dcbrush.SetColour( m_activefill.GetColour() );
00673 dcbrush.SetStyle( style );
00674 break;
00675 default:
00676 style = wxBRUSHSTYLE_SOLID;
00677 dcbrush.SetColour( m_activefill.GetColour() );
00678 dcbrush.SetStyle( style );
00679 }
00680
00681 m_renderDC->SetBrush( dcbrush );
00682 m_renderDC->SetTextBackground( m_activefill.GetColour() );
00683 }
00684 else if ( m_activefill.GetType() == a2dFILL_BITMAP )
00685 {
00686 wxBrush dcbrush;
00687 wxBrushStyle style;
00688 switch( m_activefill.GetStyle() )
00689 {
00690 case a2dFILL_STIPPLE:
00691 style = wxBRUSHSTYLE_STIPPLE;
00692 dcbrush.SetColour( m_activefill.GetColour() );
00693 dcbrush.SetStipple( m_activefill.GetStipple() );
00694 dcbrush.SetStyle( style );
00695 break;
00696 case a2dFILL_STIPPLE_MASK_OPAQUE_TRANSPARENT:
00697 case a2dFILL_STIPPLE_MASK_OPAQUE:
00698 if ( 0 )
00699 {
00700 wxBitmap noMask = m_activefill.GetStipple();
00701 noMask.SetMask( NULL );
00702 style = wxBRUSHSTYLE_STIPPLE;
00703 dcbrush.SetColour( m_activefill.GetColour() );
00704 dcbrush.SetStipple( noMask );
00705 }
00706 else
00707 {
00708 style = wxBRUSHSTYLE_STIPPLE_MASK_OPAQUE;
00709 dcbrush.SetColour( m_activefill.GetColour() );
00710 dcbrush.SetStipple( m_activefill.GetStipple() );
00711 }
00712 dcbrush.SetStyle( style );
00713 break;
00714 default: style = wxBRUSHSTYLE_SOLID;
00715 dcbrush.SetColour( m_activefill.GetColour() );
00716 dcbrush.SetStyle( style );
00717 }
00718
00719 m_renderDC->SetBrush( dcbrush );
00720 m_renderDC->SetTextBackground( m_activefill.GetColour() );
00721 }
00722 }
00723 }
00724
00725 void a2dDcDrawer::DoSetDrawStyle( a2dDrawStyle drawstyle )
00726 {
00727 m_drawstyle = drawstyle;
00728
00729 switch( drawstyle )
00730 {
00731 case a2dWIREFRAME_INVERT:
00732 SetActiveStroke( *a2dBLACK_STROKE );
00733 SetActiveFill( *a2dTRANSPARENT_FILL );
00734 SetLogicalFunction( wxINVERT );
00735 break;
00736
00737 case a2dWIREFRAME:
00738 SetActiveStroke( *a2dBLACK_STROKE );
00739 SetActiveFill( *a2dTRANSPARENT_FILL );
00740 SetLogicalFunction( wxCOPY );
00741 break;
00742
00743 case a2dWIREFRAME_ZERO_WIDTH:
00744 SetActiveStroke( *a2dBLACK_STROKE );
00745 SetActiveFill( *a2dTRANSPARENT_FILL );
00746 SetLogicalFunction( wxCOPY );
00747 break;
00748
00749 case a2dWIREFRAME_INVERT_ZERO_WIDTH:
00750 SetActiveStroke( *a2dBLACK_STROKE );
00751 SetActiveFill( *a2dTRANSPARENT_FILL );
00752 SetLogicalFunction( wxINVERT );
00753 break;
00754
00755 case a2dFILLED:
00756 SetActiveStroke( m_currentstroke );
00757 SetActiveFill( m_currentfill );
00758 SetLogicalFunction( wxCOPY );
00759 break;
00760
00761 case a2dFIX_STYLE:
00762
00763 m_fixStrokeRestore = m_currentstroke;
00764 m_fixFillRestore = m_currentfill;
00765 m_fixDrawstyle = m_drawstyle;
00766 SetActiveStroke( m_currentstroke );
00767 SetActiveFill( m_currentfill );
00768
00769
00770 SetLogicalFunction( wxCOPY );
00771 break;
00772
00773 case a2dFIX_STYLE_INVERT:
00774
00775 SetLogicalFunction( wxINVERT );
00776 break;
00777
00778 default:
00779 wxASSERT( 0 );
00780 }
00781 }
00782
00783
00784 void a2dDcDrawer::DrawImage( const wxImage& imagein, double x, double y, double width, double height, wxUint8 Opacity )
00785 {
00786 if ( m_disableDrawing )
00787 return;
00788
00789 wxASSERT_MSG( m_renderDC, wxT( "no renderDc set" ) );
00790
00791 wxPoint centr( ( int ) width / 2, ( int ) height / 2 );
00792
00793
00794 double angle = GetTransform().GetRotation();
00795
00796 wxImage image = imagein;
00797
00798 if ( fabs(angle) > 0.5 )
00799 {
00800 image.SetMask( true );
00801 if ( m_yaxis )
00802 image = imagein.Rotate( angle / 180.0 * wxPI, centr, true, NULL );
00803 else
00804 image = imagein.Rotate( -angle / 180.0 * wxPI, centr, true, NULL );
00805 }
00806
00807 int devicew, deviceh;
00808 devicew = WorldToDeviceXRel( GetTransform().Get_scaleX() * width );
00809 deviceh = abs( WorldToDeviceYRel( GetTransform().Get_scaleY() * height ) );
00810
00811 double hx, hy;
00812 GetUserToDeviceTransform().TransformPoint( x, y, hx, hy );
00813 int devicex = ( int ) ( hx - devicew / 2.0 );
00814 int devicey = ( int ) ( hy - deviceh / 2.0 );
00815
00816
00817 bool imgHasMask = image.HasMask();
00818
00819 if ( devicew == 0 || deviceh == 0 )
00820 return;
00821
00822 double sx = image.GetWidth() / (double) devicew;
00823 double sy = image.GetHeight() / (double) deviceh;
00824
00825
00826 wxRect clipped = m_clipboxdev;
00827 clipped.Intersect( wxRect( devicex, devicey, devicew, deviceh ) );
00828 int deviceClipX = clipped.GetX();
00829 int deviceClipY = clipped.GetY();
00830 int deviceClipW = clipped.GetWidth();
00831 int deviceClipH = clipped.GetHeight();
00832
00833 clipped.SetX( (int) ((clipped.GetX() - devicex) * sx ) );
00834 clipped.SetY( (int) ( (clipped.GetY() - devicey) * sy ) );
00835 clipped.SetWidth( (int) ( clipped.GetWidth() * sx ));
00836 clipped.SetHeight( (int) ( clipped.GetHeight() * sy ));
00837
00838
00839 if ( clipped.GetWidth() < 1 || clipped.GetHeight() < 1 )
00840 {
00841 m_renderDC->DrawRectangle( devicex, devicey, devicew, deviceh );
00842 return;
00843 }
00844
00845 if ( deviceClipW != devicew || deviceClipH != deviceh )
00846 image = image.GetSubImage( clipped );
00847
00848
00849
00850 image.Rescale( deviceClipW, deviceClipH );
00851
00852
00853 wxBitmap Bitmap( image );
00854
00855 if ( m_drawstyle == a2dFILLED )
00856 {
00857 wxMemoryDC MemoryDc;
00858 MemoryDc.SelectObject( Bitmap );
00859
00860 m_renderDC->Blit( deviceClipX, deviceClipY, deviceClipW, deviceClipH, &MemoryDc, 0, 0, wxCOPY, imgHasMask );
00861 }
00862 else
00863 {
00864 m_renderDC->DrawRectangle( devicex, devicey, devicew, deviceh );
00865 }
00866
00867
00868
00869
00870
00871
00872
00873
00874
00875
00876
00877
00878
00879
00880
00881
00882
00883
00884 }
00885
00886 void a2dDcDrawer::SetLogicalFunction( wxRasterOperationMode function )
00887 {
00888 #if __WXGTK__
00889 if ( m_renderDC && !wxDynamicCast( m_renderDC, wxPostScriptDC ) )
00890 m_renderDC->SetLogicalFunction( function );
00891 #else
00892 if ( m_renderDC )
00893 m_renderDC->SetLogicalFunction( function );
00894 #endif
00895 }
00896
00897
00898
00899
00900
00901
00902
00903
00904
00905
00906
00907
00908
00909
00910
00911
00912
00913
00914
00915
00916
00917
00918
00919
00920
00921
00922
00923
00924
00925
00926
00927
00928
00929
00930
00931
00932
00933
00934
00935
00936
00937
00938
00939
00940
00941
00942
00943
00944
00945
00946
00947
00948
00949
00950
00951
00952
00953
00954
00955
00956
00957
00958
00959
00960
00961
00962
00963
00964
00965
00966
00967
00968
00969
00970
00971
00972
00973
00974
00975
00976
00977
00978
00979
00980
00981
00982
00983
00984
00985
00986
00987
00988
00989
00990
00991
00992
00993
00994
00995
00996
00997
00998
00999
01000
01001
01002
01003
01004
01005
01006
01007
01008
01009
01010
01011
01012
01013
01014
01015
01016
01017
01018
01019
01020
01021
01022
01023
01024
01025
01026
01027
01028
01029
01030
01031
01032
01033
01034
01035
01036
01037
01038
01039
01040
01041
01042
01043
01044
01045
01046
01047
01048
01049
01050
01051
01052
01053
01054
01055
01056
01057
01058
01059
01060
01061
01062
01063
01064
01065
01066
01067 }
01068 }
01069 */
01070
01071
01072 void a2dDcDrawer::DrawImage( const a2dImageRGBA& image, double x, double y, double width, double height, wxUint8 Opacity )
01073 {
01074 if ( m_disableDrawing )
01075 return;
01076
01077 wxASSERT_MSG( m_renderDC, wxT( "no renderDc set" ) );
01078
01079 wxPoint centr( ( int ) width / 2, ( int ) height / 2 );
01080
01081
01082 int devicew, deviceh;
01083 devicew = WorldToDeviceXRel( GetTransform().Get_scaleX() * width );
01084 deviceh = abs( WorldToDeviceYRel( GetTransform().Get_scaleY() * height ) );
01085
01086 double hx, hy;
01087 GetUserToDeviceTransform().TransformPoint( x, y, hx, hy );
01088 int devicex = ( int ) ( hx - devicew / 2.0 );
01089 int devicey = ( int ) ( hy - deviceh / 2.0 );
01090
01091 int clipx;
01092 int clipy;
01093 int clipwidth;
01094 int clipheight;
01095 m_clip.GetBox( clipx, clipy, clipwidth, clipheight );
01096
01097
01098
01099 if ( devicew == 0 || deviceh == 0 )
01100 return;
01101
01102
01103
01104
01105
01106
01107
01108
01109
01110
01111
01112
01113
01114
01115
01116
01117
01118
01119
01120
01121 }
01122
01123 void a2dDcDrawer::DrawVpath( const a2dVpath* path )
01124 {
01125 if ( m_disableDrawing )
01126 return;
01127
01128 unsigned int segments = 0;
01129
01130 double tstep = 1 / ( double ) SPLINE_STEP;
01131 unsigned int i;
01132 for ( i = 0; i < path->size(); i++ )
01133 {
01134 a2dVpathSegment& seg = path->Item( i );
01135 switch ( seg.GetType() )
01136 {
01137 case a2dPATHSEG_CBCURVETO:
01138 case a2dPATHSEG_CBCURVETO_NOSTROKE:
01139 segments += SPLINE_STEP;
01140 break;
01141
01142 case a2dPATHSEG_QBCURVETO:
01143 case a2dPATHSEG_QBCURVETO_NOSTROKE:
01144 segments += SPLINE_STEP;
01145 break;
01146
01147 case a2dPATHSEG_ARCTO:
01148 case a2dPATHSEG_ARCTO_NOSTROKE:
01149 {
01150 a2dVpathArcSegment& cseg = ( a2dVpathArcSegment& ) seg;
01151
01152 double radius, center_x, center_y, beginrad, midrad, endrad, phit;
01153
01154 if ( cseg.CalcR( path->Item( i ? i - 1 : 0 ), radius, center_x, center_y, beginrad, midrad, endrad, phit ) )
01155 {
01156 double dphi;
01157 unsigned int circlesegments;
01158 double radiusDev = m_usertodevice.TransformDistance( radius );
01159 Aberration( m_displayaberration, phit, radiusDev , dphi, circlesegments );
01160 segments += circlesegments + 1;
01161 }
01162 else
01163 segments ++;
01164 }
01165 break;
01166 default:
01167 segments++;
01168
01169 }
01170 }
01171
01172
01173 m_cpointsDouble.resize( segments * 2 );
01174
01175 double x, y;
01176 bool move = false;
01177 int count = 0;
01178 bool nostrokeparts = false;
01179
01180
01181 for ( i = 0; i < path->size(); i++ )
01182 {
01183 a2dVpathSegment& seg = path->Item( i );
01184 switch ( seg.GetType() )
01185 {
01186 case a2dPATHSEG_MOVETO:
01187 if ( count == 0 )
01188 {
01189 m_usertodevice.TransformPoint( seg.m_x1, seg.m_y1, x, y );
01190 m_cpointsDouble[count].x = x;
01191 m_cpointsDouble[count].y = y;
01192 count++;
01193 }
01194 else
01195 {
01196 i--;
01197 move = true;
01198 }
01199 break;
01200
01201 case a2dPATHSEG_LINETO:
01202 m_usertodevice.TransformPoint( seg.m_x1, seg.m_y1, x, y );
01203 m_cpointsDouble[count].x = x;
01204 m_cpointsDouble[count].y = y;
01205 count++;
01206 break;
01207 case a2dPATHSEG_LINETO_NOSTROKE:
01208 m_usertodevice.TransformPoint( seg.m_x1, seg.m_y1, x, y );
01209 m_cpointsDouble[count].x = x;
01210 m_cpointsDouble[count].y = y;
01211 count++;
01212 nostrokeparts = true;
01213 break;
01214
01215 case a2dPATHSEG_CBCURVETO_NOSTROKE:
01216 nostrokeparts = true;
01217 case a2dPATHSEG_CBCURVETO:
01218 {
01219 double xw, yw;
01220
01221 double xwl = path->Item( i ? i - 1 : 0 ).m_x1;
01222 double ywl = path->Item( i ? i - 1 : 0 ).m_y1;
01223 a2dVpathCBCurveSegment& cseg = ( a2dVpathCBCurveSegment& ) seg;
01224
01225 int step;
01226 double t = 0;
01227 for ( step = 0; step <= SPLINE_STEP; step++ )
01228 {
01229 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 );
01230 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 );
01231 m_usertodevice.TransformPoint( xw, yw, x, y );
01232 m_cpointsDouble[count].x = x;
01233 m_cpointsDouble[count].y = y;
01234 count++;
01235 t = t + tstep;
01236 }
01237 }
01238 break;
01239
01240 case a2dPATHSEG_QBCURVETO_NOSTROKE:
01241 nostrokeparts = true;
01242 case a2dPATHSEG_QBCURVETO:
01243 {
01244 double xw, yw;
01245
01246 double xwl = path->Item( i ? i - 1 : 0 ).m_x1;
01247 double ywl = path->Item( i ? i - 1 : 0 ).m_y1;
01248 a2dVpathQBCurveSegment& cseg = ( a2dVpathQBCurveSegment& ) seg;
01249
01250 int step;
01251 double t = 0;
01252 for ( step = 0; step <= SPLINE_STEP; step++ )
01253 {
01254 xw = xwl * pow( 1 - t, 2 ) + cseg.m_x2 * ( 1 - t ) * t * 2 + cseg.m_x1 * pow( t, 2 );
01255 yw = ywl * pow( 1 - t, 2 ) + cseg.m_y2 * ( 1 - t ) * t * 2 + cseg.m_y1 * pow( t, 2 );
01256 m_usertodevice.TransformPoint( xw, yw, x, y );
01257 m_cpointsDouble[count].x = x;
01258 m_cpointsDouble[count].y = y;
01259 count++;
01260 t = t + tstep;
01261 }
01262 }
01263 break;
01264
01265 case a2dPATHSEG_ARCTO_NOSTROKE:
01266 nostrokeparts = true;
01267 case a2dPATHSEG_ARCTO:
01268 {
01269 a2dVpathArcSegment& cseg = ( a2dVpathArcSegment& ) seg;
01270
01271 double radius, center_x, center_y, beginrad, midrad, endrad, phit;
01272
01273 if ( cseg.CalcR( path->Item( i ? i - 1 : 0 ), radius, center_x, center_y, beginrad, midrad, endrad, phit ) )
01274 {
01275 double dphi;
01276 unsigned int segments;
01277 double radiusDev = m_usertodevice.TransformDistance( radius );
01278 Aberration( m_displayaberration, phit, radiusDev , dphi, segments );
01279
01280 double theta = beginrad;
01281 unsigned int step;
01282
01283 double x, y;
01284 for ( step = 0; step < segments + 1; step++ )
01285 {
01286 m_usertodevice.TransformPoint( center_x + radius * cos ( theta ), center_y + radius * sin ( theta ), x, y );
01287 m_cpointsDouble[count].x = x;
01288 m_cpointsDouble[count].y = y;
01289 count++;
01290 theta = theta + dphi;
01291 }
01292 }
01293 else
01294 {
01295 double x, y;
01296 m_usertodevice.TransformPoint( cseg.m_x1, cseg.m_y1, x, y );
01297 m_cpointsDouble[count].x = x;
01298 m_cpointsDouble[count].y = y;
01299 count++;
01300 }
01301 }
01302 default:
01303 break;
01304 break;
01305 }
01306
01307 if ( move )
01308 {
01309 DeviceDrawLines( count, false );
01310 move = false;
01311 count = 0;
01312 }
01313 else if ( seg.GetClose() != a2dPATHSEG_END_OPEN )
01314 {
01315 if ( nostrokeparts || seg.GetClose() == a2dPATHSEG_END_CLOSED_NOSTROKE )
01316 {
01317 a2dStroke stroke = m_activestroke;
01318 SetDrawerStroke( *a2dTRANSPARENT_STROKE );
01319 DeviceDrawPolygon( count, false, wxODDEVEN_RULE );
01320 SetDrawerStroke( stroke );
01321 nostrokeparts = true;
01322 }
01323 else
01324 {
01325 DeviceDrawPolygon( count, false, wxODDEVEN_RULE );
01326 }
01327
01328 move = false;
01329 count = 0;
01330 }
01331 else if ( i == path->GetCount() - 1 )
01332 {
01333 DeviceDrawLines( count, false );
01334 }
01335 }
01336
01337 if ( nostrokeparts )
01338 {
01339 move = false;
01340 count = 0;
01341 nostrokeparts = false;
01342
01343 double lastmovex = 0;
01344 double lastmovey = 0;
01345
01346 for ( i = 0; i < path->GetCount(); i++ )
01347 {
01348 a2dVpathSegment& seg = path->Item( i );
01349 switch ( seg.GetType() )
01350 {
01351 case a2dPATHSEG_MOVETO:
01352 if ( count == 0 )
01353 {
01354 m_usertodevice.TransformPoint( seg.m_x1, seg.m_y1, x, y );
01355 m_cpointsDouble[count].x = x;
01356 m_cpointsDouble[count].y = y;
01357 lastmovex = m_cpointsDouble[count].x;
01358 lastmovey = m_cpointsDouble[count].y;
01359 count++;
01360 }
01361 else
01362 {
01363 i--;
01364 move = true;
01365 }
01366 break;
01367
01368 case a2dPATHSEG_LINETO:
01369 m_usertodevice.TransformPoint( seg.m_x1, seg.m_y1, x, y );
01370 m_cpointsDouble[count].x = x;
01371 m_cpointsDouble[count].y = y;
01372 count++;
01373 break;
01374
01375 case a2dPATHSEG_LINETO_NOSTROKE:
01376 case a2dPATHSEG_CBCURVETO_NOSTROKE:
01377 case a2dPATHSEG_QBCURVETO_NOSTROKE:
01378 case a2dPATHSEG_ARCTO_NOSTROKE:
01379 if ( count == 0 )
01380 {
01381 m_usertodevice.TransformPoint( seg.m_x1, seg.m_y1, x, y );
01382 m_cpointsDouble[count].x = x;
01383 m_cpointsDouble[count].y = y;
01384 count++;
01385 }
01386 else
01387 {
01388 i--;
01389 nostrokeparts = true;
01390 }
01391 break;
01392
01393 case a2dPATHSEG_CBCURVETO:
01394 {
01395 double xw, yw;
01396
01397 double xwl = path->Item( i ? i - 1 : 0 ).m_x1;
01398 double ywl = path->Item( i ? i - 1 : 0 ).m_y1;
01399 a2dVpathCBCurveSegment& cseg = ( a2dVpathCBCurveSegment& ) seg;
01400
01401 int step;
01402 double t = 0;
01403 for ( step = 0; step <= SPLINE_STEP; step++ )
01404 {
01405 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 );
01406 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 );
01407 m_usertodevice.TransformPoint( xw, yw, x, y );
01408 m_cpointsDouble[count].x = x;
01409 m_cpointsDouble[count].y = y;
01410 count++;
01411 t = t + tstep;
01412 }
01413 }
01414 break;
01415
01416 case a2dPATHSEG_QBCURVETO:
01417 {
01418 double xw, yw;
01419
01420 double xwl = path->Item( i ? i - 1 : 0 ).m_x1;
01421 double ywl = path->Item( i ? i - 1 : 0 ).m_y1;
01422 a2dVpathQBCurveSegment& cseg = ( a2dVpathQBCurveSegment& ) seg;
01423
01424 int step;
01425 double t = 0;
01426 for ( step = 0; step <= SPLINE_STEP; step++ )
01427 {
01428 xw = xwl * pow( 1 - t, 2 ) + cseg.m_x2 * ( 1 - t ) * t * 2 + cseg.m_x1 * pow( t, 2 );
01429 yw = ywl * pow( 1 - t, 2 ) + cseg.m_y2 * ( 1 - t ) * t * 2 + cseg.m_y1 * pow( t, 2 );
01430 m_usertodevice.TransformPoint( xw, yw, x, y );
01431 m_cpointsDouble[count].x = x;
01432 m_cpointsDouble[count].y = y;
01433 count++;
01434 t = t + tstep;
01435 }
01436 }
01437 break;
01438
01439 case a2dPATHSEG_ARCTO:
01440 {
01441 a2dVpathArcSegment& cseg = ( a2dVpathArcSegment& ) seg;
01442
01443 double radius, center_x, center_y, beginrad, midrad, endrad, phit;
01444
01445 if ( cseg.CalcR( path->Item( i ? i - 1 : 0 ), radius, center_x, center_y, beginrad, midrad, endrad, phit ) )
01446 {
01447 double dphi;
01448 unsigned int segments;
01449 double radiusDev = m_usertodevice.TransformDistance( radius );
01450 Aberration( m_displayaberration, phit, radiusDev , dphi, segments );
01451
01452 double theta = beginrad;
01453 unsigned int step;
01454
01455 double x, y;
01456 for ( step = 0; step < segments + 1; step++ )
01457 {
01458 m_usertodevice.TransformPoint( center_x + radius * cos ( theta ), center_y + radius * sin ( theta ), x, y );
01459 m_cpointsDouble[count].x = x;
01460 m_cpointsDouble[count].y = y;
01461 count++;
01462 theta = theta + dphi;
01463 }
01464 }
01465 else
01466 {
01467 double x, y;
01468 m_usertodevice.TransformPoint( cseg.m_x1, cseg.m_y1, x, y );
01469 m_cpointsDouble[count].x = x;
01470 m_cpointsDouble[count].y = y;
01471 count++;
01472 }
01473 }
01474 default:
01475 break;
01476
01477 break;
01478 }
01479
01480 if ( move || nostrokeparts )
01481 {
01482 DeviceDrawLines( count, false );
01483 move = false;
01484 nostrokeparts = false;
01485 count = 0;
01486 }
01487 else if ( seg.GetClose() != a2dPATHSEG_END_OPEN )
01488 {
01489 if ( seg.GetClose() == a2dPATHSEG_END_CLOSED )
01490 {
01491 m_cpointsDouble[count].x = lastmovex;
01492 m_cpointsDouble[count].y = lastmovey;
01493 count++;
01494 }
01495 DeviceDrawLines( count, false );
01496 nostrokeparts = false;
01497 move = false;
01498 count = 0;
01499 }
01500 else if ( i == path->GetCount() )
01501 {
01502 DeviceDrawLines( count, false );
01503 }
01504 }
01505 }
01506
01507 }
01508
01509 void a2dDcDrawer::DrawPolyPolygon( a2dListOfa2dVertexList polylist, wxPolygonFillMode fillStyle )
01510 {
01511 if ( m_disableDrawing )
01512 return;
01513
01514 a2dBoundingBox devbox;
01515 bool smallPoly = false;
01516 int j = 0;
01517 int totalsize = 0;
01518 std::vector<int> pcount;
01519 pcount.resize( polylist.size() );
01520
01521 m_cpointsInt.clear();
01522 for( a2dListOfa2dVertexList::iterator iterp = polylist.begin(); iterp != polylist.end(); iterp++ )
01523 {
01524 int segments = ToDeviceLines( (*iterp).Get(), devbox, smallPoly );
01525 pcount[ j++ ] = segments;
01526 m_cpointsInt.resize( totalsize + segments );
01527
01528 for ( int i = 0; i < segments; i++ )
01529 {
01530 m_cpointsInt[ totalsize + i ].x = Round( m_cpointsDouble[i].x );
01531 m_cpointsInt[ totalsize + i ].y = Round( m_cpointsDouble[i].y );
01532 }
01533 totalsize += segments;
01534 }
01535
01536 if ( m_cpointsInt.size() == 0 )
01537 return;
01538
01539 m_renderDC->DrawPolyPolygon( j, &pcount[0], &m_cpointsInt[0], 0, 0, fillStyle );
01540
01541 }
01542
01543 void a2dDcDrawer::DrawCircle( double xc, double yc, double radius )
01544 {
01545 if ( m_disableDrawing )
01546 return;
01547
01548 if ( m_activefill.GetType() == a2dFILL_GRADIENT_FILL_LINEAR ||
01549 m_activefill.GetType() == a2dFILL_GRADIENT_FILL_RADIAL ||
01550 m_activefill.GetStyle() == a2dFILL_STIPPLE_MASK_OPAQUE_TRANSPARENT )
01551 {
01552 }
01553 else if ( m_usertodevice.IsIdentity() )
01554 {
01555 wxASSERT_MSG( m_renderDC, wxT("no renderDc set") );
01556 m_renderDC->DrawCircle( Round(xc), Round(yc), Round(radius) );
01557 return;
01558 }
01559
01560 if ( radius == 0 )
01561 {
01562 double x, y;
01563 m_usertodevice.TransformPoint( xc, yc, x, y );
01564 m_renderDC->DrawPoint( Round( x ), Round( y ) );
01565 return;
01566 }
01567
01568 if ( m_activefill.GetType() != a2dFILL_GRADIENT_FILL_LINEAR &&
01569 m_activefill.GetType() != a2dFILL_GRADIENT_FILL_RADIAL &&
01570 ( m_activefill.GetType() == a2dFILL_BITMAP && m_activefill.GetStyle() != a2dFILL_STIPPLE_MASK_OPAQUE_TRANSPARENT )
01571 )
01572 {
01573
01574
01575
01576
01577
01578
01579 double m00 = fabs( m_usertodevice.GetValue( 0, 0 ) );
01580 double m11 = fabs( m_usertodevice.GetValue( 1, 1 ) );
01581 double m10 = fabs( m_usertodevice.GetValue( 1, 0 ) );
01582 double m01 = fabs( m_usertodevice.GetValue( 0, 1 ) );
01583
01584
01585
01586
01587
01588 if ( m00 == m11 && m10 == m01 )
01589 {
01590
01591 double x, y;
01592 m_usertodevice.TransformPoint( xc, yc, x, y );
01593 #if defined(__WXMSW__)
01594 m_renderDC->DrawCircle( Round( x ), Round( y ), Round( _hypot( m00, m01 ) * radius ) );
01595 #else
01596 m_renderDC->DrawCircle( Round( x ), Round( y ), Round( hypot( m00, m01 ) * radius ) );
01597 #endif
01598 }
01599 else if ( ( 100.0 * m10 < m00 ) && ( 100.0 * m01 < m11 ) )
01600 {
01601
01602
01603
01604
01605 double x, y, rx, ry;
01606 m_usertodevice.TransformPoint( xc, yc, x, y );
01607 rx = m00 * radius;
01608 ry = m11 * radius;
01609 m_renderDC->DrawEllipse( Round( x - rx ), Round( y - ry ), Round( 2.0 * rx ), Round( 2.0 * ry ) );
01610 }
01611 else if ( ( 100.0 * m00 < m10 ) && ( 100.0 * m11 < m01 ) )
01612 {
01613
01614 double x, y, rx, ry;
01615 m_usertodevice.TransformPoint( xc, yc, x, y );
01616 rx = m10 * radius;
01617 ry = m01 * radius;
01618 m_renderDC->DrawEllipse( Round( x - rx ), Round( y - ry ), Round( 2.0 * rx ), Round( 2.0 * ry ) );
01619 }
01620 else
01621 {
01622
01623 DrawEllipse( xc, yc, 2.0 * radius, 2.0 * radius );
01624 }
01625 }
01626 else
01627 {
01628
01629 a2dDrawer2D::DrawEllipse( xc, yc, 2.0 * radius, 2.0 * radius );
01630 }
01631 }
01632
01633 void a2dDcDrawer::DrawEllipse( double xc, double yc, double width, double height )
01634 {
01635 if ( m_disableDrawing )
01636 return;
01637
01638 if ( m_activefill.GetType() == a2dFILL_GRADIENT_FILL_LINEAR ||
01639 m_activefill.GetType() == a2dFILL_GRADIENT_FILL_RADIAL ||
01640 m_activefill.GetStyle() == a2dFILL_STIPPLE_MASK_OPAQUE_TRANSPARENT )
01641 {
01642 a2dDrawer2D::DrawEllipse( xc, yc, width, height );
01643 }
01644 else if ( m_usertodevice.IsIdentity() )
01645 {
01646 wxASSERT_MSG( m_renderDC, wxT("no renderDc set") );
01647 m_renderDC->DrawEllipse( Round( xc - width/2.0), Round(yc - height/2.0), Round(width), Round(height) );
01648 }
01649 else
01650 a2dDrawer2D::DrawEllipse( xc, yc, width, height );
01651 }
01652
01653 void a2dDcDrawer::DrawLine( double x1, double y1, double x2, double y2 )
01654 {
01655 if ( m_disableDrawing )
01656 return;
01657
01658 if ( m_activefill.GetType() == a2dFILL_GRADIENT_FILL_LINEAR ||
01659 m_activefill.GetType() == a2dFILL_GRADIENT_FILL_RADIAL ||
01660 m_activefill.GetStyle() == a2dFILL_STIPPLE_MASK_OPAQUE_TRANSPARENT )
01661 {
01662 a2dDrawer2D::DrawLine( x1, y1, x2, y2 );
01663 }
01664 else if ( m_usertodevice.IsIdentity() )
01665 {
01666 wxASSERT_MSG( m_renderDC, wxT("no renderDc set") );
01667 m_renderDC->DrawLine( Round(x1), Round(y1), Round(x2), Round(y2));
01668 }
01669 else
01670 a2dDrawer2D::DrawLine( x1, y1, x2, y2 );
01671 }
01672
01673
01674 void a2dDcDrawer::DrawRoundedRectangle( double x, double y, double width, double height, double radius, bool pixelsize )
01675 {
01676 if ( m_disableDrawing )
01677 return;
01678
01679 if ( m_activefill.GetType() == a2dFILL_GRADIENT_FILL_LINEAR ||
01680 m_activefill.GetType() == a2dFILL_GRADIENT_FILL_RADIAL ||
01681 m_activefill.GetStyle() == a2dFILL_STIPPLE_MASK_OPAQUE_TRANSPARENT )
01682 {
01683 a2dDrawer2D::DrawRoundedRectangle( x, y, width, height, radius, pixelsize );
01684 }
01685 else if ( m_usertodevice.IsIdentity() )
01686 {
01687 if ( pixelsize )
01688 {
01689 width = DeviceToWorldXRel( width );
01690 height = DeviceToWorldYRel( height );
01691 radius = DeviceToWorldXRel( radius );
01692 if( m_yaxis )
01693 height = -height;
01694 }
01695
01696 wxASSERT_MSG( m_renderDC, wxT("no renderDc set") );
01697 m_renderDC->DrawRoundedRectangle( Round(x), Round(y), Round(width), Round(height), Round(radius) );
01698 }
01699 else
01700 a2dDrawer2D::DrawRoundedRectangle( x, y, width, height, radius, pixelsize );
01701 }
01702
01703 void a2dDcDrawer::DrawPoint( double xc, double yc )
01704 {
01705 if ( m_disableDrawing )
01706 return;
01707
01708 double xt, yt;
01709 GetUserToDeviceTransform().TransformPoint( xc, yc, xt, yt );
01710 DeviceDrawPixel( (int) xt, (int) yt, m_colour1redStroke, m_colour1greenStroke, m_colour1blueStroke, m_StrokeOpacityCol1 );
01711
01712
01713 }
01714
01715 void a2dDcDrawer::DeviceDrawPolygon( unsigned int n, bool spline, wxPolygonFillMode fillStyle )
01716 {
01717 if ( m_disableDrawing )
01718 return;
01719
01720 wxASSERT_MSG( m_renderDC, wxT( "no renderDc set" ) );
01721
01722 if ( spline )
01723 n = ConvertSplinedPolygon2( n );
01724
01725 wxPoint *int_cpts = _convertToIntPointCache( n, &m_cpointsDouble[0] );
01726
01727
01728 if ( IsStrokeOnly() )
01729 {
01730 if ( n == 2 )
01731 {
01732
01733 m_renderDC->DrawLines( n, int_cpts );
01734
01735 if ( m_drawstyle == a2dWIREFRAME || m_drawstyle == a2dWIREFRAME_ZERO_WIDTH )
01736 m_renderDC->DrawLine( int_cpts[0].x, int_cpts[0].y, int_cpts[n-1].x, int_cpts[n-1].y );
01737 }
01738 else
01739 {
01740
01741 #if defined(__WXMSW__)
01742 #if wxCHECK_VERSION(2,9,0)
01743 wxMSWDCImpl* dcimpl = wxStaticCast( m_renderDC->GetImpl(), wxMSWDCImpl );
01744 WXHDC hdc = dcimpl->GetHDC();
01745 #else
01746 WXHDC hdc = m_renderDC->GetHDC();
01747 #endif
01748 SetPolyFillMode( ( struct HDC__ * ) hdc, fillStyle == wxODDEVEN_RULE ? ALTERNATE : WINDING );
01749
01750
01751 ( void )Polygon( ( struct HDC__ * ) hdc, ( POINT* )int_cpts, n );
01752
01753 #else
01754 m_renderDC->DrawPolygon( n, int_cpts, 0, 0, fillStyle );
01755 #endif
01756
01757 }
01758 }
01759 else if ( m_activefill.GetType() == a2dFILL_GRADIENT_FILL_LINEAR || m_activefill.GetType() == a2dFILL_GRADIENT_FILL_RADIAL )
01760 {
01761 FillPolygon( n, &m_cpointsDouble[0] );
01762
01763 if ( IsStroked() )
01764 {
01765 m_renderDC->DrawLines( n, int_cpts );
01766 m_renderDC->DrawLine( int_cpts[0].x, int_cpts[0].y, int_cpts[n-1].x, int_cpts[n-1].y );
01767 }
01768 }
01769 else if ( m_activefill.GetType() == a2dFILL_BITMAP && m_activefill.GetStyle() == a2dFILL_STIPPLE_MASK_OPAQUE_TRANSPARENT )
01770 {
01771 #if defined(__WXMSW__)
01772 m_renderDC->SetTextForeground( *wxBLACK );
01773 m_renderDC->SetTextBackground( *wxWHITE );
01774 m_renderDC->SetLogicalFunction( wxAND_INVERT );
01775
01776
01777 COLORREF colFgOld, colBgOld;
01778
01779 #if wxCHECK_VERSION(2,9,0)
01780 wxMSWDCImpl* dcimpl = wxStaticCast( m_renderDC->GetImpl(), wxMSWDCImpl );
01781 WXHDC hdc = dcimpl->GetHDC();
01782 #else
01783 WXHDC hdc = m_renderDC->GetHDC();
01784 #endif
01785
01786 colBgOld = ::GetBkColor( ( struct HDC__ * ) hdc );
01787 colFgOld = ::GetTextColor( ( struct HDC__ * ) hdc );
01788
01789
01790
01791 ::SetBkColor( ( struct HDC__ * ) hdc, m_renderDC->GetTextForeground().GetPixel() );
01792
01793
01794 ::SetTextColor( ( struct HDC__ * ) hdc, m_renderDC->GetTextBackground().GetPixel() );
01795
01796 int prev = SetPolyFillMode( ( struct HDC__ * ) hdc, WINDING );
01797 ( void )Polygon( ( struct HDC__ * ) hdc, ( POINT* )int_cpts, n );
01798
01799
01800
01801
01802 m_renderDC->SetTextForeground( *wxBLACK );
01803
01804 m_renderDC->SetTextBackground( m_activefill.GetColour() );
01805 m_renderDC->SetLogicalFunction( wxOR );
01806
01807
01808
01809 ::SetBkColor( ( struct HDC__ * ) hdc, m_renderDC->GetTextForeground().GetPixel() );
01810
01811
01812 ::SetTextColor( ( struct HDC__ * ) hdc, m_renderDC->GetTextBackground().GetPixel() );
01813 ( void )Polygon( ( struct HDC__ * ) hdc, ( POINT* )int_cpts, n );
01814 SetPolyFillMode( ( struct HDC__ * ) hdc, prev );
01815
01816
01817 ::SetBkMode( ( struct HDC__ * ) hdc, TRANSPARENT );
01818 ::SetTextColor( ( struct HDC__ * ) hdc, colFgOld );
01819 ::SetBkColor( ( struct HDC__ * ) hdc, colBgOld );
01820
01821 m_renderDC->SetLogicalFunction( wxCOPY );
01822 m_renderDC->SetTextForeground( m_activestroke.GetColour() );
01823 m_renderDC->SetTextBackground( m_activefill.GetColour() );
01824
01825
01826 if ( IsStroked() )
01827 {
01828 m_renderDC->DrawLines( n, int_cpts );
01829 m_renderDC->DrawLine( int_cpts[0].x, int_cpts[0].y, int_cpts[n-1].x, int_cpts[n-1].y );
01830 }
01831
01832
01833 #else
01834
01835 if ( !wxDynamicCast( m_renderDC, wxPostScriptDC ) )
01836 {
01837 wxPen dcpen( m_activestroke.GetColour(), ( int ) m_activestroke.GetWidth(), wxSOLID );
01838 if ( !m_activestroke.GetPixelStroke() )
01839 dcpen.SetWidth( ( int )WorldToDeviceXRel( m_activestroke.GetWidth() ) );
01840 m_renderDC->SetPen( dcpen );
01841
01842 m_renderDC->SetTextForeground( *wxBLACK );
01843 m_renderDC->SetTextBackground( *wxWHITE );
01844 m_renderDC->SetLogicalFunction( wxAND_INVERT );
01845
01846 m_renderDC->DrawPolygon( n, int_cpts, 0, 0, fillStyle );
01847
01848
01849
01850 m_renderDC->SetTextForeground( *wxBLACK );
01851
01852 m_renderDC->SetTextBackground( m_activefill.GetColour() );
01853 m_renderDC->SetLogicalFunction( wxOR );
01854
01855 SetActiveStroke( m_activestroke );
01856 m_renderDC->DrawPolygon( n, int_cpts, 0, 0, fillStyle );
01857 m_renderDC->SetLogicalFunction( wxCOPY );
01858 m_renderDC->SetTextForeground( m_activestroke.GetColour() );
01859 m_renderDC->SetTextBackground( m_activefill.GetColour() );
01860 }
01861 else
01862 {
01863 wxPen dcpen( m_activestroke.GetColour(), ( int ) m_activestroke.GetWidth(), wxSOLID );
01864 if ( !m_activestroke.GetPixelStroke() )
01865 dcpen.SetWidth( ( int )WorldToDeviceXRel( m_activestroke.GetWidth() ) );
01866 m_renderDC->SetPen( dcpen );
01867
01868 m_renderDC->DrawPolygon( n, int_cpts, 0, 0, fillStyle );
01869 }
01870
01871 if ( IsStroked() )
01872 {
01873 m_renderDC->DrawLines( n, int_cpts );
01874 m_renderDC->DrawLine( int_cpts[0].x, int_cpts[0].y, int_cpts[n-1].x, int_cpts[n-1].y );
01875 }
01876 #endif
01877 }
01878 else if ( m_activefill.GetType() == a2dFILL_BITMAP &&
01879 ( m_activefill.GetStyle() == a2dFILL_STIPPLE ||
01880 m_activefill.GetStyle() == a2dFILL_STIPPLE_MASK_OPAQUE )
01881 )
01882 {
01883 m_renderDC->SetTextForeground( m_activefill.GetColour() );
01884 m_renderDC->SetTextBackground( m_activefill.GetColour2() );
01885 m_renderDC->DrawPolygon( n, int_cpts, 0, 0, fillStyle );
01886 m_renderDC->SetTextForeground( m_activestroke.GetColour() );
01887 m_renderDC->SetTextBackground( m_activefill.GetColour() );
01888 }
01889 else if ( m_activefill.GetType() == a2dFILL_HATCH_TWO_COLOUR )
01890 {
01891 wxBrush dcbrush( m_activefill.GetColour2() );
01892 wxBrush cur_dcbrush = m_renderDC->GetBrush();
01893 m_renderDC->SetBrush( dcbrush );
01894 m_renderDC->DrawPolygon( n, int_cpts, 0, 0, fillStyle );
01895 m_renderDC->SetBrush( cur_dcbrush );
01896 m_renderDC->DrawPolygon( n, int_cpts, 0, 0, fillStyle );
01897 }
01898 else
01899 {
01900 #if defined(__WXMSW__)
01901
01902
01903
01904
01905
01906 m_renderDC->DrawPolygon( n, int_cpts, 0, 0, fillStyle );
01907
01908 #else
01909 m_renderDC->DrawPolygon( n, int_cpts, 0, 0, fillStyle );
01910 #endif
01911 }
01912
01913 if ( IsStroked() && m_activestroke.GetType() == a2dSTROKE_OBJECT )
01914 {
01915
01916
01917
01918 wxRealPoint * copy = new wxRealPoint[n+1];
01919 memcpy( copy, &m_cpointsDouble[0], n * sizeof( wxRealPoint ) );
01920 copy[n].x = m_cpointsDouble[0].x;
01921 copy[n].y = m_cpointsDouble[0].y;
01922
01923
01924 delete [] copy;
01925 }
01926 }
01927
01928 void a2dDcDrawer::DeviceDrawLines( unsigned int n, bool spline )
01929 {
01930 if ( m_disableDrawing )
01931 return;
01932
01933 wxASSERT_MSG( m_renderDC, wxT( "no renderDc set" ) );
01934 if ( spline )
01935 n = ConvertSplinedPolyline2( n );
01936
01937 wxPoint *int_cpts = _convertToIntPointCache( n, &m_cpointsDouble[0] );
01938
01939 if ( n == 1 )
01940 m_renderDC->DrawCircle( int_cpts[0].x, int_cpts[0].y, 2 );
01941
01942 else
01943 {
01944 m_renderDC->DrawLines( n, int_cpts );
01945 #if defined(__WXMSW__)
01946
01947
01948 if ( n > 1 && m_renderDC->GetPen().GetWidth() == 1 )
01949 m_renderDC->DrawPoint( int_cpts[n-1].x, int_cpts[n-1].y );
01950 #endif
01951 }
01952 }
01953
01954 void a2dDcDrawer::DeviceDrawLine( double x1, double y1, double x2, double y2 )
01955 {
01956 if ( m_disableDrawing )
01957 return;
01958
01959 wxASSERT_MSG( m_renderDC, wxT( "no renderDc set" ) );
01960
01961 m_renderDC->DrawLine( Round( x1 ), Round( y1 ), Round( x2 ), Round( y2 ) );
01962 }
01963
01964 void a2dDcDrawer::DeviceDrawHorizontalLine( int x1, int y1, int x2, bool use_stroke_color)
01965 {
01966 if ( m_disableDrawing )
01967 return;
01968
01969 wxASSERT_MSG( m_renderDC, wxT( "no renderDc set" ) );
01970
01971 wxColour color;
01972 if (use_stroke_color)
01973 {
01974 wxPen pen = m_renderDC->GetPen();
01975 color = wxColour( m_colour1redStroke, m_colour1greenStroke, m_colour1blueStroke, m_StrokeOpacityCol1 );
01976 m_renderDC->SetPen( wxPen( color ) );
01977 m_renderDC->DrawLine( Round( x1 ), Round( y1 ), Round( x2 ), Round( y1 ) );
01978 m_renderDC->SetPen( pen );
01979 }
01980 else
01981 {
01982 m_renderDC->DrawLine( Round( x1 ), Round( y1 ), Round( x2 ), Round( y1 ) );
01983 }
01984 }
01985
01986 void a2dDcDrawer::DeviceDrawVerticalLine( int x1, int y1, int y2, bool use_stroke_color)
01987 {
01988 if ( m_disableDrawing )
01989 return;
01990
01991 wxASSERT_MSG( m_renderDC, wxT( "no renderDc set" ) );
01992
01993 wxColour color;
01994 if (use_stroke_color)
01995 {
01996 wxPen pen = m_renderDC->GetPen();
01997 color = wxColour( m_colour1redStroke, m_colour1greenStroke, m_colour1blueStroke, m_StrokeOpacityCol1 );
01998 m_renderDC->SetPen( wxPen( color ) );
01999 m_renderDC->DrawLine( Round( x1 ), Round( y1 ), Round( x1 ), Round( y2 ) );
02000 m_renderDC->SetPen( pen );
02001 }
02002 else
02003 {
02004 m_renderDC->DrawLine( Round( x1 ), Round( y1 ), Round( x1 ), Round( y2 ) );
02005 }
02006 }
02007
02008 void a2dDcDrawer::DeviceDrawPixel( int x1, int y1, unsigned char r, unsigned char g, unsigned char b , unsigned char a )
02009 {
02010 #if defined(__WXMSW__)
02011 #if wxCHECK_VERSION(2,9,0)
02012 wxMSWDCImpl * dcimpl = wxStaticCast( m_renderDC->GetImpl(), wxMSWDCImpl );
02013 WXHDC hdc = dcimpl->GetHDC();
02014 #else
02015 WXHDC hdc = m_renderDC->GetHDC();
02016 #endif
02017 ::SetPixelV( ( struct HDC__ * )hdc, x1, y1, RGB( r, g, b ) );
02018 #elif __WXGTK__
02019
02020 #if wxCHECK_VERSION(2,9,1)
02021 wxWindowDCImpl * dcimpl = wxStaticCast( m_renderDC->GetImpl(), wxWindowDCImpl );
02022 GdkWindow* gtkwin = dcimpl->GetGDKWindow();
02023 if ( gtkwin )
02024 gdk_draw_point( gtkwin, dcimpl->m_penGC, x1, y1 );
02025 #else
02026 wxColour col( r, g, b );
02027 col.CalcPixel( ( ( wxWindowDC* )m_renderDC )->m_cmap );
02028 gdk_gc_set_foreground( ( ( wxWindowDC* )m_renderDC )->m_penGC, col.GetColor() );
02029 gdk_draw_point( ( ( wxWindowDC* ) m_renderDC )->m_window, ( ( wxWindowDC* )m_renderDC )->m_penGC, x1, y1 );
02030 #endif
02031
02032 #else
02033
02034 #endif
02035 }
02036
02037 void a2dDcDrawer::DeviceDrawBitmap( const wxBitmap &bmp, double x, double y, bool useMask )
02038 {
02039 if ( m_disableDrawing )
02040 return;
02041
02042 wxASSERT_MSG( m_renderDC, wxT( "no renderDc set" ) );
02043 if ( m_drawstyle == a2dWIREFRAME_INVERT )
02044 {
02045 m_renderDC->DrawRectangle( Round( x ), Round( y ), bmp.GetWidth(), bmp.GetHeight() );
02046 }
02047 else
02048 m_renderDC->DrawBitmap( bmp, Round( x ), Round( y ), useMask );
02049 }
02050
02051 void a2dDcDrawer::DrawCharDc( wxChar c )
02052 {
02053 double x, y;
02054 x = y = 0.0;
02055 double dx, dy;
02056 double angle = GetUserToDeviceTransform().GetRotation();
02057 GetUserToDeviceTransform().TransformPoint( x, y + m_currentfont.GetLineHeight(), dx, dy );
02058 m_renderDC->DrawRotatedText( wxString( c ), ( int ) dx, ( int ) dy, -angle );
02059 }
02060
02061 void a2dDcDrawer::DrawTextDc( const wxString& text, double x, double y )
02062 {
02063 wxASSERT_MSG( m_renderDC, wxT( "no renderDc set" ) );
02064
02065
02066 unsigned int fontsize;
02067 double dx = GetUserToDeviceTransform().GetValue( 1, 0 );
02068 double dy = GetUserToDeviceTransform().GetValue( 1, 1 );
02069 fontsize = ( unsigned int ) fabs( m_currentfont.GetSize() * sqrt( dx * dx + dy * dy ) );
02070 if ( fontsize < 1 )
02071 fontsize = 1;
02072 m_currentfont.GetFont().SetPointSize( fontsize );
02073
02074 m_renderDC->SetFont( m_currentfont.GetFont() );
02075 m_renderDC->SetBackgroundMode( wxTRANSPARENT );
02076 m_renderDC->SetTextForeground( m_activestroke.GetColour() );
02077
02078 DrawTextGeneric( text, x, y, ( void ( a2dDrawer2D::* )( wxChar ) ) & a2dDcDrawer::DrawCharDc );
02079 }
02080
02081 #if wxART2D_USE_FREETYPE
02082 extern FT_Library g_freetypeLibrary;
02083
02084
02085 typedef struct
02086 {
02087 wxColour colour;
02088 int xmin, ymax;
02089 int stride;
02090 unsigned char* buf;
02091 }
02092 a2dSpanData;
02093
02094
02095 static void a2dSpanFuncGray( int y, int count, FT_Span* spans, a2dSpanData* user )
02096 {
02097 unsigned int alpha, invalpha, len;
02098
02099 unsigned int r, g, b, rpm, gpm, bpm;
02100 r = user->colour.Red();
02101 g = user->colour.Green();
02102 b = user->colour.Blue();
02103
02104 unsigned char *buf, *buf2;
02105 buf = user->buf + ( user->ymax - y ) * user->stride - user->xmin * 3;
02106 do
02107 {
02108 buf2 = buf + spans->x * 3;
02109 len = spans->len;
02110 alpha = spans->coverage;
02111 if ( alpha == 255 )
02112 {
02113 do
02114 {
02115
02116
02117 #ifdef __WXGTK__
02118 buf2[0] = r;
02119 buf2[1] = g;
02120 buf2[2] = b;
02121 #else
02122 buf2[0] = b;
02123 buf2[1] = g;
02124 buf2[2] = r;
02125 #endif
02126 buf2 += 3;
02127 }
02128 while( --len );
02129 }
02130 else
02131 {
02132 rpm = r * alpha;
02133 gpm = g * alpha;
02134 bpm = b * alpha;
02135 invalpha = 255 - alpha;
02136 do
02137 {
02138
02139
02140 #ifdef __WXGTK__
02141 buf2[0] = ( buf2[0] * invalpha + rpm ) / 255;
02142 buf2[1] = ( buf2[1] * invalpha + gpm ) / 255;
02143 buf2[2] = ( buf2[2] * invalpha + bpm ) / 255;
02144 #else
02145 buf2[0] = ( buf2[0] * invalpha + bpm ) / 255;
02146 buf2[1] = ( buf2[1] * invalpha + gpm ) / 255;
02147 buf2[2] = ( buf2[2] * invalpha + rpm ) / 255;
02148 #endif
02149 buf2 += 3;
02150 }
02151 while( --len );
02152 }
02153 spans++;
02154 }
02155 while ( --count );
02156 }
02157 #endif
02158
02159
02160 void a2dDcDrawer::DrawCharFreetype( wxChar c )
02161 {
02162 #if wxART2D_USE_FREETYPE
02163
02164 double dx, dy;
02165 GetUserToDeviceTransform().TransformPoint( 0.0, m_currentfont.GetDescent(), dx, dy );
02166
02167
02168 const a2dGlyph* a2dglyph = m_currentfont.GetGlyphFreetype( c );
02169 if( !a2dglyph )
02170 return;
02171 FT_Glyph image;
02172 if ( FT_Glyph_Copy( a2dglyph->m_glyph, &image ) != 0 )
02173 return;
02174
02175
02176 a2dAffineMatrix glyphPos;
02177 glyphPos.Scale( m_currentfont.GetSize() / FTNORMFONT );
02178 a2dAffineMatrix glyphToDevice = GetUserToDeviceTransform() * glyphPos;
02179
02180
02181 FT_Matrix trans_matrix;
02182 trans_matrix.xx = ( FT_Fixed ) ( glyphToDevice.GetValue( 0, 0 ) * 0x10000 );
02183 trans_matrix.xy = ( FT_Fixed ) ( glyphToDevice.GetValue( 1, 0 ) * 0x10000 );
02184 trans_matrix.yx = ( FT_Fixed ) ( -glyphToDevice.GetValue( 0, 1 ) * 0x10000 );
02185 trans_matrix.yy = ( FT_Fixed ) ( -glyphToDevice.GetValue( 1, 1 ) * 0x10000 );
02186 FT_Vector vec;
02187 vec.x = ( int ) ( ( dx - ( int ) dx ) * 64.0 );
02188 vec.y = ( int ) ( ( dy - ( int ) dy ) * -64.0 );
02189 if ( FT_Glyph_Transform( image, &trans_matrix, &vec ) != 0 )
02190 {
02191 wxFAIL_MSG( _( "glyph transform wrong" ) );
02192 FT_Done_Glyph( image );
02193 return;
02194 }
02195
02196
02197 FT_BBox bbox;
02198 FT_Glyph_Get_CBox( image, ft_glyph_bbox_pixels, &bbox );
02199
02200
02201 if ( m_clipboxdev.GetLeft() > ( int ) dx + bbox.xMin )
02202 bbox.xMin = m_clipboxdev.GetLeft() - ( int ) dx;
02203 if ( m_clipboxdev.GetRight() < ( int ) dx + bbox.xMax )
02204 bbox.xMax = m_clipboxdev.GetRight() - ( int ) dx;
02205
02206 if ( m_clipboxdev.GetTop() >= (int) dy - bbox.yMax )
02207 bbox.yMax = (int) dy - m_clipboxdev.GetTop();
02208 if ( m_clipboxdev.GetBottom() < (int) dy - bbox.yMin )
02209 bbox.yMin = (int) dy - m_clipboxdev.GetBottom();
02210
02211
02212 if ( bbox.xMax - bbox.xMin <= 0 || bbox.yMax - bbox.yMin <= 0 )
02213 {
02214 FT_Done_Glyph( image );
02215 return;
02216 }
02217
02218 int px = ( int ) dx + bbox.xMin;
02219 int py = ( int ) dy - bbox.yMax;
02220 int w = bbox.xMax - bbox.xMin + 1;
02221 int h = bbox.yMax - bbox.yMin + 1;
02222
02223
02224 wxRect absarea2( px, py, w, h );
02225 wxBitmap sub_bitmap = GetSubBitmap( absarea2 );
02226 #if defined(__WXMSW__)
02227 BITMAPINFO bi;
02228 bi.bmiHeader.biSize = sizeof( bi.bmiHeader );
02229 bi.bmiHeader.biWidth = w;
02230 bi.bmiHeader.biHeight = -h;
02231 bi.bmiHeader.biPlanes = 1;
02232 bi.bmiHeader.biBitCount = 24;
02233 bi.bmiHeader.biCompression = BI_RGB;
02234 bi.bmiHeader.biSizeImage = 0;
02235 bi.bmiHeader.biClrUsed = 0;
02236 bi.bmiHeader.biClrImportant = 0;
02237
02238 HBITMAP hbitmap = ( HBITMAP ) sub_bitmap.GetHBITMAP();
02239 HDC hdc = ::GetDC( NULL );
02240 HDC memdc = ::CreateCompatibleDC( hdc );
02241 unsigned char *buf = ( unsigned char * ) malloc( ( 3 * w + sizeof( DWORD ) - 1 ) / sizeof( DWORD ) * sizeof( DWORD ) * h );
02242 ::GetDIBits( memdc, hbitmap, 0, h, buf, &bi, DIB_RGB_COLORS );
02243 #else // defined( __WXMSW__ )
02244 wxImage wximage( sub_bitmap.ConvertToImage() );
02245 #endif // defined( __WXMSW__ )
02246
02247
02248 if ( image->format == FT_GLYPH_FORMAT_OUTLINE )
02249 {
02250 a2dSpanData spandata;
02251 spandata.colour = GetDrawerStroke().GetColour();
02252 spandata.xmin = bbox.xMin;
02253 spandata.ymax = bbox.yMax;
02254 spandata.stride = w * 3;
02255 #if defined(__WXMSW__)
02256
02257 spandata.stride = ( spandata.stride + sizeof( DWORD ) - 1 ) / sizeof( DWORD ) * sizeof( DWORD );
02258 spandata.buf = buf;
02259 #else // defined( __WXMSW__ )
02260 spandata.buf = wximage.GetData();
02261 #endif // defined( __WXMSW__ )
02262 wxASSERT( spandata.buf != NULL );
02263
02264 FT_Raster_Params params;
02265 params.target = NULL;
02266 params.flags = FT_RASTER_FLAG_AA | FT_RASTER_FLAG_DIRECT | FT_RASTER_FLAG_CLIP;
02267 params.gray_spans = ( FT_SpanFunc ) & a2dSpanFuncGray;
02268 params.black_spans = NULL;
02269 params.bit_test = ( FT_Raster_BitTest_Func ) NULL;
02270 params.bit_set = ( FT_Raster_BitSet_Func ) NULL;
02271 params.user = &spandata;
02272 params.clip_box = bbox;
02273
02274 FT_Outline& outline = ( ( FT_OutlineGlyph ) image )->outline;
02275 if ( FT_Outline_Render( g_freetypeLibrary, &outline, ¶ms ) == 0 )
02276 {
02277 #if defined( __WXMSW__ )
02278 ::SetDIBits( memdc, hbitmap, 0, h, buf, &bi, DIB_RGB_COLORS );
02279 #else // defined( __WXMSW__ )
02280 wxBitmap sub_bitmap( wximage );
02281 #endif // defined( __WXMSW__ )
02282 DeviceDrawBitmap( sub_bitmap, px, py );
02283 }
02284 }
02285 else
02286 wxFAIL_MSG( _( "Non vector fonts are not supported" ) );
02287
02288 #if defined(__WXMSW__)
02289 free( buf );
02290 ::DeleteDC( memdc );
02291 ::ReleaseDC( NULL, hdc );
02292 #endif // defined( __WXMSW__ )
02293
02294 FT_Done_Glyph( image );
02295 #else // wxART2D_USE_FREETYPE
02296 DrawCharUnknown( c );
02297 #endif // wxART2D_USE_FREETYPE
02298 }
02299
02300 void a2dDcDrawer::DeviceDrawAnnotation( const wxString& text, wxCoord x, wxCoord y, const wxFont& font )
02301 {
02302 if ( m_disableDrawing )
02303 return;
02304
02305 wxASSERT_MSG( m_renderDC, wxT( "no renderDc set" ) );
02306
02307 m_renderDC->SetFont( font );
02308 wxCoord w, h;
02309 m_renderDC->GetTextExtent( text, &w, &h );
02310 m_renderDC->SetPen( *wxBLACK_PEN );
02311 m_renderDC->SetBrush( *wxCYAN_BRUSH );
02312 m_renderDC->DrawRectangle( x - 1, y - 1, w + 2, h + 2 );
02313 m_renderDC->SetTextBackground( *wxCYAN );
02314 m_renderDC->SetTextForeground( *wxBLACK );
02315 m_renderDC->DrawText( text, x, y );
02316 }
02317
02318 void a2dDcDrawer::BlitBuffer( wxRect WXUNUSED( rect ), const wxPoint& WXUNUSED( bufferpos ) )
02319 {
02320
02321 }
02322
02323 void a2dDcDrawer::BlitBuffer( wxDC* WXUNUSED( dc ), wxRect WXUNUSED( rect ), const wxPoint& WXUNUSED( bufferpos ) )
02324 {
02325
02326 }
02327
02328
02329
02330
02331
02332 a2dMemDcDrawer::a2dMemDcDrawer( const wxSize& size ): a2dDcDrawer( size )
02333 {
02334 m_buffer = wxBitmap( m_width, m_height );
02335 }
02336
02337 a2dMemDcDrawer::a2dMemDcDrawer( int width, int height ): a2dDcDrawer( width, height )
02338 {
02339 m_buffer = wxBitmap( width, height );
02340 }
02341
02342 a2dMemDcDrawer::~a2dMemDcDrawer()
02343 {
02344 }
02345
02346 a2dMemDcDrawer::a2dMemDcDrawer( const a2dMemDcDrawer& other )
02347 : a2dDcDrawer( other )
02348 {
02349 m_buffer = other.m_buffer;
02350 }
02351
02352 void a2dMemDcDrawer::BeginDraw()
02353 {
02354 wxASSERT_MSG( m_beginDraw_endDraw >= 0, wxT( "a2dMemDcDrawer, unbalanced BeginDraw EndDraw" ) );
02355
02356 if ( m_beginDraw_endDraw == 0 )
02357 {
02358 wxASSERT_MSG( m_renderDC == NULL, wxT( "a2dMemDcDrawer, unbalanced BeginDraw EndDraw" ) );
02359 m_memdc = new wxMemoryDC();
02360 m_memdc->SelectObject( m_buffer );
02361
02362 m_renderDC = m_memdc;
02363
02364 SetDrawerFill( m_currentfill );
02365 SetDrawerStroke( m_currentstroke );
02366
02367 DestroyClippingRegion();
02368
02369 SetDrawStyle( m_drawstyle );
02370
02371 m_renderDC->SetMapMode( wxMM_TEXT );
02372
02373 if ( m_display )
02374 {
02375 m_deviceDC = new wxClientDC( m_display );
02376 m_display->PrepareDC( *m_deviceDC );
02377 }
02378 }
02379
02380 m_beginDraw_endDraw++;
02381 }
02382
02383 void a2dMemDcDrawer::EndDraw()
02384 {
02385 m_beginDraw_endDraw--;
02386
02387 wxASSERT_MSG( m_renderDC != NULL, wxT( "a2dMemDcDrawer, unbalanced BeginDraw EndDraw" ) );
02388 wxASSERT_MSG( m_beginDraw_endDraw >= 0, wxT( "a2dMemDcDrawer, unbalanced BeginDraw EndDraw" ) );
02389
02390 if ( m_beginDraw_endDraw == 0 )
02391 {
02392 m_memdc->SelectObject( wxNullBitmap );
02393 delete m_memdc;
02394 m_renderDC = NULL;
02395
02396 if ( m_display )
02397 delete m_deviceDC;
02398 }
02399 }
02400
02401 void a2dMemDcDrawer::SetBufferSize( int w, int h )
02402 {
02403 m_width = w;
02404 m_height = h;
02405 wxBitmap helpbuf = wxBitmap( w, h );
02406
02407
02408
02409 wxMemoryDC mdc;
02410 wxMemoryDC mdch;
02411 mdc.SelectObject( m_buffer );
02412 mdch.SelectObject( helpbuf );
02413 mdch.Blit( 0, 0, w, h, &mdc, 0, 0 );
02414 mdc.SelectObject( wxNullBitmap );
02415 mdch.SelectObject( wxNullBitmap );
02416
02417 m_buffer = helpbuf;
02418 }
02419
02420 void a2dMemDcDrawer::DrawPolygon( const a2dVertexList *list, bool spline, wxPolygonFillMode fillStyle )
02421 {
02422 if ( m_disableDrawing )
02423 return;
02424
02425 a2dDrawer2D::DrawPolygon( list, spline, fillStyle );
02426 }
02427
02428 void a2dMemDcDrawer::DeviceDrawPolygon( unsigned int n, bool spline, wxPolygonFillMode fillStyle )
02429 {
02430 a2dDcDrawer::DeviceDrawPolygon( n, spline, fillStyle );
02431 }
02432
02433 wxBitmap a2dMemDcDrawer::GetSubBitmap( wxRect rect ) const
02434 {
02435 wxBitmap ret( rect.width, rect.height, m_buffer.GetDepth() );
02436 wxASSERT_MSG( ret.Ok(), wxT( "GetSubImage error" ) );
02437
02438 if ( m_renderDC )
02439 {
02440
02441 wxMemoryDC dcb;
02442 dcb.SelectObject( ret );
02443 dcb.Blit( 0, 0, rect.width, rect.height, m_renderDC, rect.x, rect.y, wxCOPY, false );
02444 dcb.SelectObject( wxNullBitmap );
02445 }
02446 else
02447 {
02448 wxMemoryDC dcm;
02449 dcm.SelectObject( const_cast<wxBitmap&>( m_buffer ) );
02450
02451
02452 wxMemoryDC dcb;
02453 dcb.SelectObject( ret );
02454 dcb.Blit( 0, 0, rect.width, rect.height, &dcm, rect.x, rect.y, wxCOPY, false );
02455 dcb.SelectObject( wxNullBitmap );
02456
02457 dcm.SelectObject( wxNullBitmap );
02458 }
02459
02460 return ret;
02461 }
02462
02463 void a2dMemDcDrawer::CopyIntoBuffer( const wxBitmap& bitm )
02464 {
02465 m_buffer = bitm;
02466 }
02467
02468 void a2dMemDcDrawer::BlitBuffer( wxDC* dc, wxRect rect, const wxPoint& bufferpos )
02469 {
02470
02471 if ( rect.x < 0)
02472 {
02473 rect.width += rect.x;
02474 rect.x = 0;
02475 }
02476 if (rect.width <= 0) return;
02477
02478 if (rect.y < 0)
02479 {
02480 rect.height += rect.y;
02481 rect.y = 0;
02482 }
02483 if (rect.height <= 0) return;
02484
02485 if (rect.x+rect.width > m_width )
02486 {
02487 rect.width = m_width - rect.x;
02488 }
02489 if (rect.width <= 0) return;
02490
02491 if (rect.y+rect.height > m_height )
02492 {
02493 rect.height = m_height - rect.y;
02494 }
02495 if (rect.height <= 0) return;
02496
02497 if ( !m_renderDC )
02498 {
02499 wxMemoryDC mdc;
02500 mdc.SelectObject( m_buffer );
02501
02502 dc->Blit( rect.x - bufferpos.x, rect.y - bufferpos.y, rect.width, rect.height, &mdc, rect.x, rect.y, wxCOPY, false );
02503
02504 mdc.SelectObject( wxNullBitmap );
02505 }
02506 else
02507 {
02508 dc->Blit( rect.x - bufferpos.x, rect.y - bufferpos.y, rect.width, rect.height, m_renderDC, rect.x, rect.y, wxCOPY, false );
02509 }
02510
02511 }
02512
02513 void a2dMemDcDrawer::BlitBuffer( wxRect rect, const wxPoint& bufferpos )
02514 {
02515 BeginDraw();
02516 BlitBuffer( m_deviceDC, rect, bufferpos );
02517 EndDraw();
02518 }
02519
02520 void a2dMemDcDrawer::ShiftBuffer( int dxy, bool yshift )
02521 {
02522 int bw = GetBuffer().GetWidth();
02523 int bh = GetBuffer().GetHeight();
02524 if ( yshift )
02525 {
02526 if ( dxy > 0 && dxy < bh )
02527 {
02528 wxRect rect( 0, 0, bw, bh - dxy );
02529 wxBitmap sub_bitmap( m_buffer.GetSubBitmap( rect ) );
02530 wxMemoryDC dcm;
02531 dcm.SelectObject( m_buffer );
02532 dcm.DrawBitmap( sub_bitmap, 0, dxy, true );
02533 dcm.SelectObject( wxNullBitmap );
02534 }
02535 else if ( dxy < 0 && dxy > -bh )
02536 {
02537 wxRect rect( 0, -dxy, bw, bh + dxy );
02538 wxBitmap sub_bitmap( m_buffer.GetSubBitmap( rect ) );
02539 wxMemoryDC dcm;
02540 dcm.SelectObject( m_buffer );
02541 dcm.DrawBitmap( sub_bitmap, 0, 0, true );
02542 dcm.SelectObject( wxNullBitmap );
02543 }
02544 else
02545 wxFAIL_MSG( wxT( "you can only shift within height of buffer" ) );
02546
02547 }
02548 else
02549 {
02550 if ( dxy > 0 && dxy < bw )
02551 {
02552 wxRect rect( 0, 0, bw - dxy, bh );
02553 wxBitmap sub_bitmap( m_buffer.GetSubBitmap( rect ) );
02554 wxMemoryDC dcm;
02555 dcm.SelectObject( m_buffer );
02556 dcm.DrawBitmap( sub_bitmap, dxy, 0, true );
02557 dcm.SelectObject( wxNullBitmap );
02558 }
02559 else if ( dxy < 0 && dxy > -bw )
02560 {
02561 wxRect rect( -dxy, 0, bw + dxy, bh );
02562 wxBitmap sub_bitmap( m_buffer.GetSubBitmap( rect ) );
02563 wxMemoryDC dcm;
02564 dcm.SelectObject( m_buffer );
02565 dcm.DrawBitmap( sub_bitmap, 0, 0, true );
02566 dcm.SelectObject( wxNullBitmap );
02567 }
02568 else
02569 wxFAIL_MSG( wxT( "you can only shift within width of buffer" ) );
02570 }
02571 }
02572
02573 void a2dMemDcDrawer::DrawImage( const wxImage& image, double x, double y, double width, double height, wxUint8 Opacity )
02574 {
02575 #if wxART2D_USE_AGGDRAWER
02576 if ( m_disableDrawing )
02577 return;
02578
02579 if ( width == 0 || height == 0 )
02580 return;
02581
02582 if ( m_drawstyle == a2dFILLED )
02583 {
02584 double angle = GetTransform().GetRotation();
02585
02586
02587 if ( fabs(angle) > 0.5 || Opacity != 255 )
02588 {
02589
02590 EndDraw();
02591
02592 a2dAggDrawer aggDrawer = a2dAggDrawer( m_buffer );
02593 aggDrawer.SetYaxis( m_yaxis );
02594 aggDrawer.SetTransform( GetTransform() );
02595 aggDrawer.SetMappingMatrix( GetMappingMatrix() );
02596 aggDrawer.SetDrawerFill( m_activefill );
02597 aggDrawer.SetDrawerStroke( m_activestroke );
02598 aggDrawer.SetDrawStyle( m_drawstyle );
02599 aggDrawer.BeginDraw();
02600 aggDrawer.SetClippingRegionDev( m_clipboxdev.x, m_clipboxdev.y, m_clipboxdev.x + m_clipboxdev.width, m_clipboxdev.y + m_clipboxdev.height );
02601 aggDrawer.DrawImage( image,x ,y, width, height, Opacity );
02602 aggDrawer.EndDraw();
02603
02604 m_buffer = aggDrawer.GetBuffer();
02605
02606
02607 BeginDraw();
02608 }
02609 else
02610 a2dDcDrawer::DrawImage( image, x, y, width, height, Opacity );
02611 }
02612 else
02613 {
02614 DrawCenterRoundedRectangle( x, y, width, height, 0 );
02615 }
02616 #else
02617 a2dDcDrawer::DrawImage( image, x, y, width, height, Opacity );
02618 #endif
02619 }
02620
02621 void a2dMemDcDrawer::DrawImage( const a2dImageRGBA& image, double x, double y, double width, double height, wxUint8 Opacity )
02622 {
02623 #if wxART2D_USE_AGGDRAWER
02624 if ( m_disableDrawing )
02625 return;
02626
02627 if ( width == 0 || height == 0 )
02628 return;
02629
02630 if ( m_drawstyle == a2dFILLED )
02631 {
02632 double angle = GetTransform().GetRotation();
02633
02634
02635 if ( 1 )
02636 {
02637
02638 EndDraw();
02639
02640 a2dAggDrawer aggDrawer = a2dAggDrawer( m_buffer );
02641 aggDrawer.SetYaxis( m_yaxis );
02642 aggDrawer.SetTransform( GetTransform() );
02643 aggDrawer.SetMappingMatrix( GetMappingMatrix() );
02644 aggDrawer.SetDrawerFill( m_activefill );
02645 aggDrawer.SetDrawerStroke( m_activestroke );
02646 aggDrawer.SetDrawStyle( m_drawstyle );
02647 aggDrawer.BeginDraw();
02648 aggDrawer.SetClippingRegionDev( m_clipboxdev.x, m_clipboxdev.y, m_clipboxdev.x + m_clipboxdev.width, m_clipboxdev.y + m_clipboxdev.height );
02649 aggDrawer.DrawImage( image,x ,y, width, height );
02650 aggDrawer.EndDraw();
02651
02652 m_buffer = aggDrawer.GetBuffer();
02653
02654
02655 BeginDraw();
02656 }
02657 else
02658 a2dDcDrawer::DrawImage( image, x, y, width, height, Opacity );
02659 }
02660 else
02661 {
02662 DrawRoundedRectangle( x, y, width, height, 0 );
02663 }
02664 #else
02665 a2dDcDrawer::DrawImage( image, x, y, width, height, Opacity );
02666 #endif
02667 }
02668
02669 #if wxART2D_USE_GRAPHICS_CONTEXT
02670
02671 IMPLEMENT_DYNAMIC_CLASS( a2dGcDrawer, a2dGcBaseDrawer )
02672
02673
02674
02675
02676
02677 void a2dGcDrawer::InitContext()
02678 {
02679 m_externalDc = false;
02680 m_clip.Clear();
02681 m_buffer = wxBitmap( m_width, m_height );
02682 m_memdc.SelectObject( m_buffer );
02683 m_render = new a2dRenderer();
02684 m_context = (a2dDcContext*) (( a2dRenderer*)m_render)->CreateContext( &m_memdc, &m_buffer );
02685 }
02686
02687 a2dGcDrawer::a2dGcDrawer( const wxSize& size ): a2dGcBaseDrawer( size.GetWidth(), size.GetHeight() )
02688 {
02689 InitContext();
02690 }
02691
02692 a2dGcDrawer::a2dGcDrawer( int width, int height ): a2dGcBaseDrawer( width, height )
02693 {
02694 InitContext();
02695 }
02696
02697 a2dGcDrawer::a2dGcDrawer( const a2dGcDrawer& other )
02698 : a2dGcBaseDrawer( other )
02699 {
02700 InitContext();
02701 }
02702
02703 a2dGcDrawer::a2dGcDrawer( const a2dDrawer2D& other )
02704 : a2dGcBaseDrawer( other )
02705 {
02706 InitContext();
02707 }
02708
02709 a2dGcDrawer::~a2dGcDrawer()
02710 {
02711 delete m_context;
02712 delete m_render;
02713 m_memdc.SelectObject( wxNullBitmap );
02714 }
02715
02716 wxBitmap a2dGcDrawer::GetBuffer() const
02717 {
02718 return m_buffer;
02719 }
02720
02721 void a2dGcDrawer::SetBufferSize( int w, int h )
02722 {
02723 m_width = w;
02724 m_height = h;
02725 wxBitmap helpbuf = wxBitmap( w, h );
02726
02727
02728
02729 wxMemoryDC mdch;
02730 mdch.SelectObject( helpbuf );
02731 mdch.Blit( 0, 0, w, h, &m_memdc, 0, 0 );
02732 mdch.SelectObject( wxNullBitmap );
02733
02734 m_memdc.SelectObject( wxNullBitmap );
02735 m_buffer = helpbuf;
02736 m_memdc.SelectObject( m_buffer );
02737 delete m_context;
02738 m_context = (a2dDcContext*) (( a2dRenderer*)m_render)->CreateContext( &m_memdc, &m_buffer );
02739 }
02740
02741 wxBitmap a2dGcDrawer::GetSubBitmap( wxRect rect ) const
02742 {
02743 wxBitmap ret( rect.width, rect.height, m_buffer.GetDepth() );
02744 wxASSERT_MSG( ret.Ok(), wxT( "GetSubImage error" ) );
02745
02746
02747 wxMemoryDC dcb;
02748 dcb.SelectObject( ret );
02749 dcb.Blit( 0, 0, rect.width, rect.height, const_cast<wxMemoryDC*>( &m_memdc ), rect.x, rect.y, wxCOPY, false );
02750 dcb.SelectObject( wxNullBitmap );
02751
02752 return ret;
02753 }
02754
02755 void a2dGcDrawer::BlitBuffer( wxDC* dc, wxRect rect, const wxPoint& bufferpos )
02756 {
02757
02758 if ( rect.x < 0)
02759 {
02760 rect.width += rect.x;
02761 rect.x = 0;
02762 }
02763 if (rect.width <= 0) return;
02764
02765 if (rect.y < 0)
02766 {
02767 rect.height += rect.y;
02768 rect.y = 0;
02769 }
02770 if (rect.height <= 0) return;
02771
02772 if (rect.x+rect.width > m_width )
02773 {
02774 rect.width = m_width - rect.x;
02775 }
02776 if (rect.width <= 0) return;
02777
02778 if (rect.y+rect.height > m_height )
02779 {
02780 rect.height = m_height - rect.y;
02781 }
02782 if (rect.height <= 0) return;
02783
02784 dc->Blit( rect.x - bufferpos.x, rect.y - bufferpos.y, rect.width, rect.height, &m_memdc, rect.x, rect.y, wxCOPY, false );
02785 }
02786
02787 void a2dGcDrawer::ShiftBuffer( int dxy, bool yshift )
02788 {
02789 int bw = GetBuffer().GetWidth();
02790 int bh = GetBuffer().GetHeight();
02791 if ( yshift )
02792 {
02793 if ( dxy > 0 && dxy < bh )
02794 {
02795 wxRect rect( 0, 0, bw, bh - dxy );
02796 wxBitmap sub_bitmap( m_buffer.GetSubBitmap( rect ) );
02797 wxMemoryDC dcm;
02798 dcm.SelectObject( m_buffer );
02799 dcm.DrawBitmap( sub_bitmap, 0, dxy, true );
02800 dcm.SelectObject( wxNullBitmap );
02801 }
02802 else if ( dxy < 0 && dxy > -bh )
02803 {
02804 wxRect rect( 0, -dxy, bw, bh + dxy );
02805 wxBitmap sub_bitmap( m_buffer.GetSubBitmap( rect ) );
02806 wxMemoryDC dcm;
02807 dcm.SelectObject( m_buffer );
02808 dcm.DrawBitmap( sub_bitmap, 0, 0, true );
02809 dcm.SelectObject( wxNullBitmap );
02810 }
02811 else
02812 wxFAIL_MSG( wxT( "you can only shift within height of buffer" ) );
02813
02814 }
02815 else
02816 {
02817 if ( dxy > 0 && dxy < bw )
02818 {
02819 wxRect rect( 0, 0, bw - dxy, bh );
02820 wxBitmap sub_bitmap( m_buffer.GetSubBitmap( rect ) );
02821 wxMemoryDC dcm;
02822 dcm.SelectObject( m_buffer );
02823 dcm.DrawBitmap( sub_bitmap, dxy, 0, true );
02824 dcm.SelectObject( wxNullBitmap );
02825 }
02826 else if ( dxy < 0 && dxy > -bw )
02827 {
02828 wxRect rect( -dxy, 0, bw + dxy, bh );
02829 wxBitmap sub_bitmap( m_buffer.GetSubBitmap( rect ) );
02830 wxMemoryDC dcm;
02831 dcm.SelectObject( m_buffer );
02832 dcm.DrawBitmap( sub_bitmap, 0, 0, true );
02833 dcm.SelectObject( wxNullBitmap );
02834 }
02835 else
02836 wxFAIL_MSG( wxT( "you can only shift within width of buffer" ) );
02837 }
02838 }
02839
02840 void a2dGcDrawer::SetYaxis( bool up )
02841 {
02842 a2dDrawer2D::SetYaxis( up );
02843
02844
02845 }
02846
02847 void a2dGcDrawer::DoSetActiveFont( const a2dFont& font )
02848 {
02849 a2dContext* context = (a2dContext*) m_context;
02850 a2dRenderer* render = (a2dRenderer*) m_render;
02851 wxGraphicsFont f = render->CreateFont( font );
02852 context->SetFont( f );
02853 }
02854
02855 void a2dGcDrawer::DoSetActiveStroke()
02856 {
02857
02858
02859 a2dRenderer* render = (a2dRenderer*) m_render;
02860 a2dContext* context = (a2dContext*) m_context;
02861 wxGraphicsPen p = render->CreateStroke( m_activestroke );
02862 m_context->SetPen( p );
02863 }
02864
02865 void a2dGcDrawer::DoSetActiveFill()
02866 {
02867
02868
02869 a2dRenderer* render = (a2dRenderer*) m_render;
02870 a2dContext* context = (a2dContext*) m_context;
02871 wxGraphicsBrush b = render->CreateFill( m_activefill );
02872 m_context->SetBrush( b );
02873 }
02874
02875 void a2dGcDrawer::DrawImage( const wxImage& imagein, double x, double y, double width, double height, wxUint8 Opacity )
02876 {
02877 if ( m_disableDrawing )
02878 return;
02879
02880
02881
02882 a2dRenderer* render = (a2dRenderer*) m_render;
02883 a2dContext* context = (a2dContext*) m_context;
02884 wxGraphicsBitmap bitmap = render->CreateBitmap( imagein );
02885 #if wxCHECK_VERSION(2,9,0)
02886 context->DrawBitmap( bitmap, x, y, width, height );
02887 #else
02888 context->DrawGraphicsBitmap( bitmap, x, y, width, height );
02889 #endif
02890 }
02891
02892 void a2dGcDrawer::DrawImage( const a2dImageRGBA& image, double x, double y, double width, double height, wxUint8 Opacity )
02893 {
02894 if ( m_disableDrawing )
02895 return;
02896
02897 wxImage wximage = image.GetImage();
02898 a2dGcDrawer::DrawImage( wximage, x, y, width, height, Opacity );
02899 }
02900
02901 void a2dGcDrawer::DrawPoint( double xc, double yc )
02902 {
02903 if ( m_disableDrawing )
02904 return;
02905
02906 double xt, yt;
02907 GetUserToDeviceTransform().TransformPoint( xc, yc, xt, yt );
02908
02909 }
02910
02911
02912
02913
02914
02915
02916
02917
02918
02919
02920
02921
02922
02923
02924
02925
02926
02927
02928
02929
02930
02931
02932
02933
02934
02935
02936
02937
02938 void a2dGcDrawer::DrawCharFreetype( wxChar c )
02939 {
02940 wxGraphicsMatrix m = m_context->CreateMatrix();
02941 m.Set(
02942 m_usertodevice( 0, 0), m_usertodevice( 0, 1),
02943 m_usertodevice( 1, 0), m_usertodevice( 1, 1),
02944 m_usertodevice( 2, 0), m_usertodevice( 2, 1) );
02945 m_context->SetTransform( m );
02946 static_cast<a2dDcContext*>(m_context)->DrawCharFreetype( c );
02947 }
02948 */
02949
02950
02951
02952 #endif // wxART2D_USE_GRAPHICS_CONTEXT
02953
02954
02955
02956
02957
02958
02959
02960
02961
02962
02963
02964
02965
02966
02967
02968
02969
02970
02971