00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011 #include "a2dprec.h"
00012
00013 #ifdef __BORLANDC__
00014 #pragma hdrstop
00015 #endif
00016
00017 #ifndef WX_PRECOMP
00018 #include "wx/wx.h"
00019 #include <wx/wfstream.h>
00020 #include "wx/artbase/drawer2d.h"
00021 #include "wx/artbase/stylebase.h"
00022 #if defined(__WXMSW__)
00023 #include "wx/artbase/mswfont.h"
00024 #endif
00025 #endif
00026
00027 #if wxART2D_USE_FREETYPE
00028 #include <ft2build.h>
00029 #ifdef _MSC_VER
00030
00031
00032 #include <freetype/freetype.h>
00033 #include <freetype/ftoutln.h>
00034 #else // _MSC_VER
00035
00036 #include FT_FREETYPE_H
00037 #include FT_OUTLINE_H
00038 #endif // _MSC_VER
00039 #endif
00040
00041 #include "wx/general/comevt.h"
00042
00043 #define THRESHOLD 5
00044
00045 #define AFFINESTACKSIZE 16
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055 DEFINE_EVENT_TYPE( a2dDrawer2D::sm_changedZoom )
00056
00057
00058 a2dDrawer2D::a2dDrawer2D( const wxSize& size )
00059 #if defined(_DEBUG) && defined (SMART_POINTER_DEBUG)
00060 : m_initCurrentSmartPointerOwner( this )
00061 #endif
00062 {
00063 m_width = size.GetWidth();
00064 m_height = size.GetHeight();
00065 m_display = NULL;
00066
00067 Init();
00068 }
00069
00070 a2dDrawer2D::a2dDrawer2D( int width, int height )
00071 #if defined(_DEBUG) && defined (SMART_POINTER_DEBUG)
00072 : m_initCurrentSmartPointerOwner( this )
00073 #endif
00074 {
00075 m_width = width;
00076 m_height = height;
00077 m_display = NULL;
00078
00079 Init();
00080 }
00081
00082 a2dDrawer2D::a2dDrawer2D( const a2dDrawer2D& other )
00083 : wxObject( other )
00084 #if defined(_DEBUG) && defined (SMART_POINTER_DEBUG)
00085 , m_initCurrentSmartPointerOwner( this )
00086 #endif
00087 {
00088 m_cpointsDouble.clear();
00089 m_cpointsInt.clear();
00090
00091 m_display = other.m_display;
00092
00093 Init();
00094
00095 m_realScale = other.m_realScale;
00096 m_width = other.m_width;
00097 m_height = other.m_height;
00098
00099 m_xpp = other.m_xpp;
00100 m_ypp = other.m_ypp;
00101
00102 m_virt_minX = other.m_virt_minX;
00103 m_virt_minY = other.m_virt_minY;
00104
00105 m_worldtodevice = other.m_worldtodevice;
00106 SetTransform( other.GetTransform() );
00107
00108 m_virtualarea_set = other.m_virtualarea_set;
00109
00110 m_printingMode = other.m_printingMode;
00111 m_yaxis = other.m_yaxis ;
00112 }
00113
00114 void a2dDrawer2D::Init()
00115 {
00116 m_realScale = true;
00117 m_disableDrawing = false;
00118
00119 m_drawingthreshold = a2dGlobals->GetPrimitiveThreshold();
00120 m_polygonFillThreshold = a2dGlobals->GetPolygonFillThreshold();
00121 m_asrectangle = a2dGlobals->GetThresholdDrawRectangle();
00122
00123 m_refreshDisplay = 0;
00124
00125 m_frozen = false;
00126
00127
00128 m_xpp = 1;
00129 m_ypp = 1;
00130
00131 m_mapX = m_mapY = 0;
00132 m_mapWidth = m_width;
00133 m_mapHeight = m_height;
00134
00135 m_virt_minX = 0;
00136 m_virt_minY = 0;
00137
00138 m_worldtodevice.Identity();
00139 SetTransform( a2dIDENTITY_MATRIX );
00140
00141 m_drawstyle = a2dFILLED;
00142 m_virtualarea_set = false;
00143
00144 m_yaxis = false;
00145
00146 m_currentstroke = *a2dBLACK_STROKE;
00147 m_currentfill = *a2dBLACK_FILL;
00148 m_currentfont = *a2dNullFONT;
00149 m_activestroke = m_currentstroke;
00150 m_activefill = m_currentfill;
00151
00152 m_OpacityFactor = 255;
00153
00154 m_fixStrokeRestore = *a2dBLACK_STROKE;
00155 m_fixFillRestore = *a2dBLACK_FILL;
00156 m_fixDrawstyle = m_drawstyle;
00157
00158 m_splineaberration = 10;
00159
00160 m_displayaberration = 0.5;
00161
00162 m_beginDraw_endDraw = 0;
00163 m_printingMode = false;
00164 }
00165
00166 a2dDrawer2D::~a2dDrawer2D()
00167 {
00168 wxASSERT_MSG( m_affineStack.empty(), _( "Unbalanced Push/PopTransform" ) );
00169 }
00170
00171
00172 void a2dDrawer2D::BlitBuffer()
00173 {
00174 wxRect rect( 0, 0, m_width, m_height );
00175 BlitBuffer( rect, wxPoint( 0, 0 ) );
00176 }
00177
00178 void a2dDrawer2D::BlitBuffer( int x, int y, int width, int height, int xbuf, int ybuf )
00179 {
00180 wxRect rect( x, y, width, height );
00181 BlitBuffer( rect, wxPoint( xbuf, ybuf ) );
00182 }
00183
00184 void a2dDrawer2D::SetSplineAberration( double aber )
00185 {
00186 m_splineaberration = aber;
00187 }
00188
00189
00190
00191
00192
00193 void a2dDrawer2D::SetMappingDeviceRect( int mapx, int mapy, int mapWidth, int mapHeight, bool remap )
00194 {
00195 m_mapX = mapx;
00196 m_mapY = mapy;
00197 m_mapWidth = mapWidth;
00198 m_mapHeight = mapHeight;
00199 if ( remap )
00200 SetMappingUpp( m_mapX, m_mapY, m_mapWidth, m_mapHeight, m_virt_minX, m_virt_minY, m_xpp, m_ypp );
00201 }
00202
00203 void a2dDrawer2D::SetMinX( double x )
00204 {
00205 m_virt_minX = x;
00206 SetMappingUpp( m_mapX, m_mapY, m_mapWidth, m_mapHeight, m_virt_minX, m_virt_minY, m_xpp, m_ypp );
00207 }
00208
00209 void a2dDrawer2D::SetMinY( double y )
00210 {
00211 m_virt_minY = y;
00212 SetMappingUpp( m_mapX, m_mapY, m_mapWidth, m_mapHeight, m_virt_minX, m_virt_minY, m_xpp, m_ypp );
00213 }
00214
00215 void a2dDrawer2D::SetUppX( double x )
00216 {
00217 m_xpp = x;
00218 SetMappingUpp( m_mapX, m_mapY, m_mapWidth, m_mapHeight, m_virt_minX, m_virt_minY, m_xpp, m_ypp );
00219 }
00220
00221 void a2dDrawer2D::SetUppY( double y )
00222 {
00223 m_ypp = y;
00224 SetMappingUpp( m_mapX, m_mapY, m_mapWidth, m_mapHeight, m_virt_minX, m_virt_minY, m_xpp, m_ypp );
00225 }
00226
00227 void a2dDrawer2D::SetMappingUpp( double vx1, double vy1, double xpp, double ypp )
00228 {
00229 SetMappingUpp( m_mapX, m_mapY, m_mapWidth, m_mapHeight, vx1, vy1, xpp, ypp );
00230 }
00231
00232
00233
00234 void a2dDrawer2D::SetMappingUpp( double x, double y, double wx, double wy, double vx1, double vy1, double xpp, double ypp )
00235 {
00236 m_mapX = ( int ) x;
00237 m_mapY = ( int ) y;
00238 m_mapWidth = ( int ) wx;
00239 m_mapHeight = ( int ) wy;
00240
00241 m_virt_minX = vx1;
00242 m_virt_minY = vy1;
00243 m_xpp = xpp;
00244 m_ypp = ypp;
00245
00246
00247 double scalex, scaley, transx, transy;
00248
00249
00250
00251
00252
00253 if ( m_yaxis )
00254 {
00255 double virt_maxY = m_virt_minY + wy * m_ypp;
00256 transx = -m_virt_minX + m_mapX;
00257 transy = -virt_maxY + m_mapY;
00258 }
00259 else
00260 {
00261 transx = -m_virt_minX + m_mapX;
00262 transy = -m_virt_minY + m_mapY;
00263 }
00264
00265
00266 scalex = 1 / m_xpp;
00267 scaley = 1 / m_ypp;
00268 transx = transx * scalex;
00269 transy = transy * scaley;
00270
00271
00272
00273
00274 if ( m_yaxis )
00275 {
00276 scaley = -scaley;
00277 transy = -transy;
00278 }
00279
00280
00281 m_virtualarea_set = true;
00282
00283
00284 m_worldtodevice.SetValue( 2 , 0, transx );
00285 m_worldtodevice.SetValue( 2 , 1, transy );
00286 m_worldtodevice.SetValue( 0 , 0, scalex );
00287 m_worldtodevice.SetValue( 1 , 1, scaley );
00288
00289
00290 m_usertodevice = m_worldtodevice * m_usertoworld;
00291
00292 a2dComEvent changedZoom( this, &a2dDrawer2D::sm_changedZoom );
00293 if ( m_display && m_refreshDisplay <= 0 )
00294 {
00295 m_display->GetEventHandler()->ProcessEvent( changedZoom );
00296 m_display->Refresh();
00297 }
00298 a2dGeneralGlobals->GetEventDistributer()->ProcessEvent( changedZoom );
00299 DestroyClippingRegion();
00300 }
00301
00302 void a2dDrawer2D::SetMappingWidthHeight( double vx1, double vy1, double width, double height )
00303 {
00304 double xupp = width / m_mapWidth;
00305 double yupp = height / m_mapHeight;
00306
00307 if ( yupp == 0 || xupp == 0 )
00308 {
00309 yupp = 1; xupp = 1;
00310 }
00311
00312 if( m_realScale )
00313 {
00314 if ( yupp > xupp )
00315 {
00316 SetMappingUpp( m_mapX, m_mapY, m_mapWidth, m_mapHeight, vx1, vy1, yupp, yupp );
00317 }
00318 else
00319 {
00320 SetMappingUpp( m_mapX, m_mapY, m_mapWidth, m_mapHeight, vx1, vy1, xupp, xupp );
00321 }
00322 }
00323 else
00324 SetMappingUpp( m_mapX, m_mapY, m_mapWidth, m_mapHeight, vx1, vy1, xupp, yupp );
00325 }
00326
00327 void a2dDrawer2D::SetMappingWidthHeight( const a2dBoundingBox& box )
00328 {
00329 SetMappingWidthHeight( box.GetMinX(), box.GetMinY(), box.GetWidth(), box.GetHeight() );
00330 }
00331
00332 void a2dDrawer2D::SetMappingMatrix( const a2dAffineMatrix& mapping )
00333 {
00334 m_worldtodevice = mapping;
00335
00336 m_usertodevice = m_worldtodevice * m_usertoworld;
00337 }
00338
00339 double a2dDrawer2D::GetVisibleMinX() const
00340 {
00341 return m_virt_minX;
00342 }
00343
00344 double a2dDrawer2D::GetVisibleMinY() const
00345 {
00346 return m_virt_minY;
00347 }
00348
00349 double a2dDrawer2D::GetVisibleMaxX() const
00350 {
00351 return m_virt_minX + m_xpp * m_mapWidth;
00352 }
00353
00354 double a2dDrawer2D::GetVisibleMaxY() const
00355 {
00356 return m_virt_minY + m_ypp * m_mapHeight;
00357 }
00358
00359 double a2dDrawer2D::GetVisibleWidth() const
00360 {
00361 return m_xpp * m_mapWidth;
00362 }
00363
00364 double a2dDrawer2D::GetVisibleHeight() const
00365 {
00366 return m_ypp * m_mapHeight;
00367 }
00368
00369 a2dBoundingBox a2dDrawer2D::GetVisibleBbox() const
00370 {
00371 return a2dBoundingBox( m_virt_minX, m_virt_minY, m_virt_minX + m_xpp * m_mapWidth, m_virt_minY + m_ypp * m_mapHeight );
00372 }
00373
00374 void a2dDrawer2D::SetYaxis( bool up )
00375 {
00376 m_yaxis = up;
00377
00378
00379 SetMappingUpp( m_mapX, m_mapY, m_mapWidth, m_mapHeight, m_virt_minX, m_virt_minY, m_xpp, m_ypp );
00380 }
00381
00382 void a2dDrawer2D::SetTransform( const a2dAffineMatrix& userToWorld )
00383 {
00384 m_usertoworld = userToWorld;
00385 m_usertodevice = m_worldtodevice * m_usertoworld;
00386 }
00387
00388 void a2dDrawer2D::PushTransform()
00389 {
00390 m_affineStack.push_back( m_usertoworld );
00391 m_affineStack.push_back( m_worldtodevice );
00392 m_affineStack.push_back( m_usertodevice );
00393 }
00394
00395 void a2dDrawer2D::PushTransform( const a2dAffineMatrix& affine )
00396 {
00397 m_affineStack.push_back( m_usertoworld );
00398 m_affineStack.push_back( m_worldtodevice );
00399 m_affineStack.push_back( m_usertodevice );
00400
00401 m_usertoworld = m_usertoworld * affine;
00402 m_usertodevice = m_worldtodevice * m_usertoworld;
00403 }
00404
00405 void a2dDrawer2D::PushIdentityTransform()
00406 {
00407 m_affineStack.push_back( m_usertoworld );
00408 m_affineStack.push_back( m_worldtodevice );
00409 m_affineStack.push_back( m_usertodevice );
00410
00411 m_usertoworld = a2dIDENTITY_MATRIX;
00412 m_usertodevice = a2dIDENTITY_MATRIX;
00413 m_worldtodevice = a2dIDENTITY_MATRIX;
00414 }
00415
00416 void a2dDrawer2D::PopTransform( void )
00417 {
00418 wxASSERT_MSG( !m_affineStack.empty(), _( "Unbalanced Push/PopTransform" ) );
00419 m_usertodevice = m_affineStack.back();
00420 m_affineStack.pop_back();
00421 m_worldtodevice = m_affineStack.back();
00422 m_affineStack.pop_back();
00423 m_usertoworld = m_affineStack.back();
00424 m_affineStack.pop_back();
00425 }
00426
00427 a2dBoundingBox a2dDrawer2D::ToWorld( const wxRect& rect )
00428 {
00429 return a2dBoundingBox( DeviceToWorldX( rect.x ),
00430 DeviceToWorldY( rect.y ),
00431 DeviceToWorldX( rect.x + rect.width ),
00432 DeviceToWorldY( rect.y + rect.height ) );
00433 }
00434
00435 wxRect a2dDrawer2D::ToDevice( const a2dBoundingBox& bbox )
00436 {
00437 int xd1, yd1, xd2, yd2;
00438 xd1 = WorldToDeviceX( bbox.GetMinX() );
00439 yd1 = WorldToDeviceY( bbox.GetMinY() );
00440 xd2 = WorldToDeviceX( bbox.GetMaxX() );
00441 yd2 = WorldToDeviceY( bbox.GetMaxY() );
00442
00443 if ( xd1 > xd2 )
00444 {
00445 int tmp = xd1;
00446 xd1 = xd2;
00447 xd2 = tmp;
00448 }
00449 if ( yd1 > yd2 )
00450 {
00451 int tmp = yd1;
00452 yd1 = yd2;
00453 yd2 = tmp;
00454 }
00455
00456 wxRect tmparea;
00457 tmparea.x = xd1;
00458 tmparea.y = yd1;
00459 tmparea.width = xd2 - xd1;
00460 tmparea.height = yd2 - yd1;
00461
00462 return tmparea;
00463 }
00464
00465 wxPoint *a2dDrawer2D::_convertToIntPointCache( int n, wxRealPoint *pts )
00466 {
00467 m_cpointsInt.resize( n );
00468
00469 for ( int i = 0; i < n; i++ )
00470 {
00471 m_cpointsInt[i].x = Round( pts[i].x );
00472 m_cpointsInt[i].y = Round( pts[i].y );
00473 }
00474 return &m_cpointsInt[0];
00475 }
00476
00477
00478
00479
00480
00481 void a2dDrawer2D::ResetStyle()
00482 {
00483 m_fixedStyledOverRuled = false;
00484 }
00485
00486 void a2dDrawer2D::SetOpacityFactor( wxUint8 OpacityFactor )
00487 {
00488 m_OpacityFactor = OpacityFactor;
00489 SetActiveStroke( m_currentstroke );
00490 SetActiveFill( m_currentfill );
00491 }
00492
00493 void a2dDrawer2D::SetDrawStyle( a2dDrawStyle drawstyle )
00494 {
00495 if ( m_drawstyle != a2dFIX_STYLE && m_drawstyle != a2dFIX_STYLE_INVERT )
00496 {
00497 DoSetDrawStyle( drawstyle );
00498 }
00499 }
00500
00501 void a2dDrawer2D::SetDrawerStroke( const a2dStroke& stroke )
00502 {
00503 if ( m_drawstyle != a2dFIX_STYLE && m_drawstyle != a2dFIX_STYLE_INVERT )
00504 {
00505
00506
00507
00508 if ( !stroke.IsSameAs( m_currentstroke ) )
00509 {
00510
00511 m_currentstroke = stroke;
00512 SetActiveStroke( m_currentstroke );
00513 }
00514 }
00515 }
00516
00517 void a2dDrawer2D::SetActiveStroke( const a2dStroke& stroke )
00518 {
00519 switch( m_drawstyle )
00520 {
00521 case a2dWIREFRAME_INVERT:
00522 case a2dWIREFRAME:
00523 case a2dWIREFRAME_ZERO_WIDTH:
00524 m_activestroke = stroke;
00525 break;
00526 case a2dWIREFRAME_INVERT_ZERO_WIDTH:
00527 m_activestroke = *a2dBLACK_STROKE;
00528 break;
00529 case a2dFILLED:
00530 m_activestroke = stroke;
00531 break;
00532 case a2dFIX_STYLE:
00533 break;
00534 case a2dFIX_STYLE_INVERT:
00535 break;
00536 default:
00537 wxASSERT( 0 );
00538 }
00539
00540 m_colour1redStroke = m_activestroke.GetColour().Red();
00541 m_colour1greenStroke = m_activestroke.GetColour().Green();
00542 m_colour1blueStroke = m_activestroke.GetColour().Blue();
00543
00544 if ( m_activestroke.IsNoStroke() || m_activestroke.GetStyle() == a2dSTROKE_TRANSPARENT )
00545 {
00546 m_StrokeOpacityCol1 = 0;
00547 m_StrokeOpacityCol2 = 0;
00548 }
00549 else
00550 {
00551 m_StrokeOpacityCol1 = m_activestroke.GetColour().Alpha() * m_OpacityFactor / 255 ;
00552 m_StrokeOpacityCol2 = m_activestroke.GetColour().Alpha() * m_OpacityFactor / 255 ;
00553 }
00554 DoSetActiveStroke();
00555 }
00556
00557 void a2dDrawer2D::SetDrawerFill( const a2dFill& fill )
00558 {
00559 if ( m_drawstyle != a2dFIX_STYLE && m_drawstyle != a2dFIX_STYLE_INVERT )
00560 {
00561 if ( !fill.IsSameAs( m_currentfill ) )
00562 {
00563 m_currentfill = fill;
00564 SetActiveFill( m_currentfill );
00565 }
00566 }
00567 }
00568
00569 void a2dDrawer2D::SetActiveFill( const a2dFill& fill )
00570 {
00571 switch( m_drawstyle )
00572 {
00573 case a2dWIREFRAME_INVERT:
00574 case a2dWIREFRAME:
00575 case a2dWIREFRAME_ZERO_WIDTH:
00576 case a2dWIREFRAME_INVERT_ZERO_WIDTH:
00577 m_activefill = *a2dTRANSPARENT_FILL;
00578 break;
00579 case a2dFILLED:
00580 m_activefill = fill;
00581 break;
00582 case a2dFIX_STYLE:
00583 case a2dFIX_STYLE_INVERT:
00584 break;
00585 default:
00586 wxASSERT( 0 );
00587 }
00588
00589 m_colour1redFill = m_activefill.GetColour().Red();
00590 m_colour1greenFill = m_activefill.GetColour().Green();
00591 m_colour1blueFill = m_activefill.GetColour().Blue();
00592 m_colour2redFill = m_activefill.GetColour2().Red();
00593 m_colour2greenFill = m_activefill.GetColour2().Green();
00594 m_colour2blueFill = m_activefill.GetColour2().Blue();
00595
00596 if ( !m_activefill.GetFilling() )
00597 {
00598 m_FillOpacityCol1 = 0;
00599 m_FillOpacityCol2 = 0;
00600 }
00601 else if ( m_activefill.GetStyle() == a2dFILL_TRANSPARENT )
00602 {
00603 m_FillOpacityCol1 = 0;
00604 m_FillOpacityCol2 = 0;
00605 }
00606 else if ( m_activefill.IsNoFill() )
00607 {
00608 m_FillOpacityCol1 = 0;
00609 m_FillOpacityCol2 = 0;
00610 }
00611 else
00612 {
00613 m_FillOpacityCol1 = m_activefill.GetColour().Alpha() * m_OpacityFactor / 255;
00614 m_FillOpacityCol2 = m_activefill.GetColour2().Alpha() * m_OpacityFactor / 255;
00615 }
00616
00617 DoSetActiveFill();
00618 }
00619
00620 void a2dDrawer2D::ResetFixedStyle()
00621 {
00622 if ( m_drawstyle == a2dFIX_STYLE || m_drawstyle == a2dFIX_STYLE_INVERT )
00623 {
00624 m_drawstyle = a2dFILLED;
00625 ResetStyle();
00626 m_fixFillRestore = m_currentfill;
00627 m_fixStrokeRestore = m_currentstroke;
00628 m_fixDrawstyle = m_drawstyle;
00629 m_fixedStyledOverRuled = false;
00630 }
00631 }
00632
00633 void a2dDrawer2D::OverRuleFixedStyle()
00634 {
00635 if ( !m_fixedStyledOverRuled &&
00636 ( m_drawstyle == a2dFIX_STYLE || m_drawstyle == a2dFIX_STYLE_INVERT )
00637 )
00638 {
00639 m_fixFillRestore = m_currentfill;
00640 m_fixStrokeRestore = m_currentstroke;
00641 m_fixDrawstyle = m_drawstyle;
00642 m_drawstyle = a2dFILLED;
00643 m_fixedStyledOverRuled = true;
00644 }
00645 }
00646
00647 void a2dDrawer2D::ReStoreFixedStyle()
00648 {
00649 if ( m_fixedStyledOverRuled )
00650 {
00651 SetDrawerFill( m_fixFillRestore );
00652 SetDrawerStroke( m_fixStrokeRestore );
00653 SetDrawStyle( m_fixDrawstyle );
00654 m_fixedStyledOverRuled = false;
00655 }
00656 }
00657
00658 void a2dDrawer2D::SetFont( const a2dFont& font )
00659 {
00660 if ( !font.IsSameAs( m_currentfont ) )
00661 {
00662 m_currentfont = font;
00663 }
00664 DoSetActiveFont( m_currentfont );
00665 }
00666
00667 wxPen a2dDrawer2D::ConvertActiveToPen()
00668 {
00669 wxPen dcpen = *wxTRANSPARENT_PEN;
00670 wxColour stroke1;
00671 stroke1.Set( m_colour1redStroke, m_colour1greenStroke, m_colour1blueStroke, m_StrokeOpacityCol1 );
00672
00673 if ( m_activestroke.GetStyle() == a2dSTROKE_TRANSPARENT )
00674 {
00675 dcpen = *wxTRANSPARENT_PEN;
00676 }
00677 else if ( m_activestroke.IsNoStroke() )
00678 {
00679 dcpen = *wxTRANSPARENT_PEN;
00680 }
00681 else if ( m_drawstyle == a2dWIREFRAME_INVERT_ZERO_WIDTH )
00682 {
00683 dcpen = *wxBLACK_PEN;
00684 }
00685 else if ( m_activestroke.GetType() == a2dSTROKE_ONE_COLOUR )
00686 {
00687 int style;
00688 switch( m_activestroke.GetStyle() )
00689 {
00690 case a2dSTROKE_SOLID: style = wxSOLID;
00691 break;
00692 case a2dSTROKE_TRANSPARENT: style = wxTRANSPARENT;
00693 break;
00694 case a2dSTROKE_DOT: style = wxDOT;
00695 break;
00696 case a2dSTROKE_DOT_DASH: style = wxDOT_DASH;
00697 break;
00698 case a2dSTROKE_LONG_DASH: style = wxLONG_DASH;
00699 break;
00700 case a2dSTROKE_SHORT_DASH: style = wxSHORT_DASH;
00701 break;
00702 case a2dSTROKE_BDIAGONAL_HATCH: style = wxBDIAGONAL_HATCH;
00703 break;
00704 case a2dSTROKE_CROSSDIAG_HATCH: style = wxCROSSDIAG_HATCH;
00705 break;
00706 case a2dSTROKE_FDIAGONAL_HATCH: style = wxFDIAGONAL_HATCH;
00707 break;
00708 case a2dSTROKE_CROSS_HATCH: style = wxCROSS_HATCH;
00709 break;
00710 case a2dSTROKE_HORIZONTAL_HATCH: style = wxHORIZONTAL_HATCH;
00711 break;
00712 case a2dSTROKE_VERTICAL_HATCH: style = wxVERTICAL_HATCH;
00713 break;
00714 case a2dSTROKE_STIPPLE: style = wxSTIPPLE;
00715 break;
00716 case a2dSTROKE_STIPPLE_MASK_OPAQUE: style = wxSTIPPLE_MASK_OPAQUE;
00717 break;
00718 default: style = a2dSTROKE_SOLID;
00719 }
00720
00721 if ( m_drawstyle == a2dWIREFRAME_ZERO_WIDTH )
00722 {
00723 dcpen = wxPen( stroke1, 0, style );
00724 }
00725 else
00726 {
00727 dcpen = wxPen( stroke1, ( int ) m_activestroke.GetWidth(), style );
00728 dcpen.SetJoin( m_activestroke.GetJoin() );
00729 dcpen.SetCap( m_activestroke.GetCap() );
00730 if ( m_activestroke.GetPixelStroke() )
00731 dcpen.SetWidth( (int) DeviceToWorldXRel( m_activestroke.GetWidth() ) );
00732 }
00733 }
00734 else if ( m_activestroke.GetType() == a2dSTROKE_BITMAP )
00735 {
00736 if ( m_drawstyle == a2dWIREFRAME_ZERO_WIDTH )
00737 dcpen = wxPen( stroke1, 0, wxBRUSHSTYLE_SOLID );
00738 else
00739 {
00740 int width = (int) m_activestroke.GetWidth();
00741 if ( m_activestroke.GetPixelStroke() )
00742 width = (int) DeviceToWorldXRel( width );
00743 dcpen = wxPen( stroke1, width, wxBRUSHSTYLE_SOLID );
00744 dcpen.SetJoin( m_activestroke.GetJoin() );
00745 dcpen.SetCap( m_activestroke.GetCap() );
00746 }
00747
00748 #if defined(__WXMSW__)
00749 wxBrushStyle style;
00750 switch( m_activestroke.GetStyle() )
00751 {
00752 case a2dSTROKE_STIPPLE:
00753 style = wxBRUSHSTYLE_STIPPLE;
00754 dcpen.SetStyle( style );
00755 dcpen.SetStipple( m_activestroke.GetStipple() );
00756 break;
00757 case a2dSTROKE_STIPPLE_MASK_OPAQUE_TRANSPARENT:
00758 case a2dSTROKE_STIPPLE_MASK_OPAQUE:
00759 if ( 0 )
00760 {
00761 wxBitmap noMask = m_activestroke.GetStipple();
00762 noMask.SetMask( NULL );
00763 style = wxBRUSHSTYLE_STIPPLE;
00764 dcpen.SetStyle( style );
00765 dcpen.SetStipple( noMask );
00766 }
00767 else
00768 {
00769 style = wxBRUSHSTYLE_STIPPLE_MASK_OPAQUE;
00770 dcpen.SetStyle( style );
00771 dcpen.SetStipple( m_activestroke.GetStipple() );
00772 }
00773 break;
00774 default: style = wxBRUSHSTYLE_SOLID;
00775 dcpen.SetStyle( style );
00776 }
00777 #endif
00778
00779 }
00780 return dcpen;
00781 }
00782
00783 wxBrush a2dDrawer2D::ConvertActiveToBrush()
00784 {
00785 wxBrush dcbrush = *wxTRANSPARENT_BRUSH;
00786 wxColour textb;
00787 wxBrushStyle style;
00788 wxColour fill1;
00789 fill1.Set( m_colour1redFill, m_colour1greenFill, m_colour1blueFill, m_FillOpacityCol1 );
00790 wxColour fill2;
00791 fill2.Set( m_colour2redFill, m_colour2greenFill, m_colour2blueFill, m_FillOpacityCol2 );
00792
00793 if ( !m_activefill.GetFilling() )
00794 {
00795 dcbrush = *wxTRANSPARENT_BRUSH;
00796 textb = *wxBLACK;
00797 }
00798 else if ( m_activefill.GetStyle() == a2dFILL_TRANSPARENT )
00799 {
00800 dcbrush = *wxTRANSPARENT_BRUSH;
00801 textb = *wxBLACK;
00802 }
00803 else if ( m_activefill.IsNoFill() )
00804 {
00805 dcbrush = *wxTRANSPARENT_BRUSH;
00806 textb = *wxBLACK;
00807 }
00808 else if ( m_activefill.GetType() == a2dFILL_ONE_COLOUR )
00809 {
00810 switch( m_activefill.GetStyle() )
00811 {
00812 case a2dFILL_TRANSPARENT:
00813 style = wxBRUSHSTYLE_TRANSPARENT;
00814 dcbrush.SetColour( fill1 );
00815 dcbrush.SetStyle( style );
00816 break;
00817 case a2dFILL_SOLID: style = wxBRUSHSTYLE_SOLID;
00818 dcbrush.SetColour( fill1 );
00819 dcbrush.SetStyle( style );
00820 break;
00821 case a2dFILL_BDIAGONAL_HATCH:
00822 style = wxBRUSHSTYLE_BDIAGONAL_HATCH;
00823 dcbrush.SetColour( fill1 );
00824 dcbrush.SetStyle( style );
00825 break;
00826 case a2dFILL_CROSSDIAG_HATCH:
00827 style = wxBRUSHSTYLE_CROSSDIAG_HATCH;
00828 dcbrush.SetColour( fill1 );
00829 dcbrush.SetStyle( style );
00830 break;
00831 case a2dFILL_FDIAGONAL_HATCH:
00832 style = wxBRUSHSTYLE_FDIAGONAL_HATCH;
00833 dcbrush.SetColour( fill1 );
00834 dcbrush.SetStyle( style );
00835 break;
00836 case a2dFILL_CROSS_HATCH:
00837 style = wxBRUSHSTYLE_CROSS_HATCH;
00838 dcbrush.SetColour( fill1 );
00839 dcbrush.SetStyle( style );
00840 break;
00841 case a2dFILL_HORIZONTAL_HATCH:
00842 style = wxBRUSHSTYLE_HORIZONTAL_HATCH;
00843 dcbrush.SetColour( fill1 );
00844 dcbrush.SetStyle( style );
00845 break;
00846 case a2dFILL_VERTICAL_HATCH:
00847 style = wxBRUSHSTYLE_VERTICAL_HATCH;
00848 dcbrush.SetColour( fill1 );
00849 dcbrush.SetStyle( style );
00850 break;
00851 default: style = wxBRUSHSTYLE_SOLID;
00852 dcbrush.SetColour( fill1 );
00853 dcbrush.SetStyle( style );
00854 }
00855 }
00856 else if ( m_activefill.GetType() == a2dFILL_HATCH_TWO_COLOUR )
00857 {
00858 wxBrushStyle style;
00859 switch( m_activefill.GetStyle() )
00860 {
00861 case a2dFILL_TRANSPARENT:
00862 style = wxBRUSHSTYLE_TRANSPARENT;
00863 dcbrush.SetColour( fill1 );
00864 dcbrush.SetStyle( style );
00865 break;
00866 case a2dFILL_TWOCOL_BDIAGONAL_HATCH:
00867 style = wxBRUSHSTYLE_BDIAGONAL_HATCH;
00868 dcbrush.SetColour( fill1 );
00869 dcbrush.SetStyle( style );
00870 break;
00871 case a2dFILL_TWOCOL_CROSSDIAG_HATCH:
00872 style = wxBRUSHSTYLE_CROSSDIAG_HATCH;
00873 dcbrush.SetColour( fill1 );
00874 dcbrush.SetStyle( style );
00875 break;
00876 case a2dFILL_TWOCOL_FDIAGONAL_HATCH:
00877 style = wxBRUSHSTYLE_FDIAGONAL_HATCH;
00878 dcbrush.SetColour( fill1 );
00879 dcbrush.SetStyle( style );
00880 break;
00881 case a2dFILL_TWOCOL_CROSS_HATCH:
00882 style = wxBRUSHSTYLE_CROSS_HATCH;
00883 dcbrush.SetColour( fill1 );
00884 dcbrush.SetStyle( style );
00885 break;
00886 case a2dFILL_TWOCOL_HORIZONTAL_HATCH:
00887 style = wxBRUSHSTYLE_HORIZONTAL_HATCH;
00888 dcbrush.SetColour( fill1 );
00889 dcbrush.SetStyle( style );
00890 break;
00891 case a2dFILL_TWOCOL_VERTICAL_HATCH:
00892 style = wxBRUSHSTYLE_VERTICAL_HATCH;
00893 dcbrush.SetColour( fill1 );
00894 dcbrush.SetStyle( style );
00895 break;
00896 default:
00897 style = wxBRUSHSTYLE_SOLID;
00898 dcbrush.SetColour( fill1 );
00899 dcbrush.SetStyle( style );
00900 }
00901 }
00902 else if ( m_activefill.GetType() == a2dFILL_BITMAP )
00903 {
00904 wxBrushStyle style;
00905 switch( m_activefill.GetStyle() )
00906 {
00907 case a2dFILL_STIPPLE:
00908 style = wxBRUSHSTYLE_STIPPLE;
00909 dcbrush.SetColour( fill1 );
00910 dcbrush.SetStipple( m_activefill.GetStipple() );
00911 dcbrush.SetStyle( style );
00912 break;
00913 case a2dFILL_STIPPLE_MASK_OPAQUE_TRANSPARENT:
00914 case a2dFILL_STIPPLE_MASK_OPAQUE:
00915 if ( 0 )
00916 {
00917 wxBitmap noMask = m_activefill.GetStipple();
00918 noMask.SetMask( NULL );
00919 style = wxBRUSHSTYLE_STIPPLE;
00920 dcbrush.SetColour( fill1 );
00921 dcbrush.SetStipple( noMask );
00922 }
00923 else
00924 {
00925 style = wxBRUSHSTYLE_STIPPLE_MASK_OPAQUE;
00926 dcbrush.SetColour( fill1 );
00927 dcbrush.SetStipple( m_activefill.GetStipple() );
00928 }
00929 dcbrush.SetStyle( style );
00930 break;
00931 default: style = wxBRUSHSTYLE_SOLID;
00932 dcbrush.SetColour( fill1 );
00933 dcbrush.SetStyle( style );
00934 }
00935 }
00936 else if ( m_activefill.GetType() == a2dFILL_GRADIENT_FILL_LINEAR || m_activefill.GetType() == a2dFILL_GRADIENT_FILL_RADIAL )
00937 {
00938 wxFAIL_MSG( wxT( "can not convert gradients to wxBrush" ) );
00939 }
00940 return dcbrush;
00941 }
00942
00943 #if wxART2D_USE_GRAPHICS_CONTEXT
00944
00945 wxGraphicsPen a2dDrawer2D::ConvertActiveToGraphicsPen( wxGraphicsContext* context )
00946 {
00947 wxPen dcpen = *wxTRANSPARENT_PEN;
00948 wxColour stroke1;
00949 stroke1.Set( m_colour1redStroke, m_colour1greenStroke, m_colour1blueStroke, m_StrokeOpacityCol1 );
00950
00951 if ( m_activestroke.GetStyle() == a2dSTROKE_TRANSPARENT )
00952 {
00953 dcpen = *wxTRANSPARENT_PEN;
00954 }
00955 else if ( m_activestroke.IsNoStroke() )
00956 {
00957 dcpen = *wxTRANSPARENT_PEN;
00958 }
00959 else if ( m_drawstyle == a2dWIREFRAME_INVERT_ZERO_WIDTH )
00960 {
00961 dcpen = *wxBLACK_PEN;
00962 }
00963 else if ( m_activestroke.GetType() == a2dSTROKE_ONE_COLOUR )
00964 {
00965 int style;
00966 switch( m_activestroke.GetStyle() )
00967 {
00968 case a2dSTROKE_SOLID: style = wxSOLID;
00969 break;
00970 case a2dSTROKE_TRANSPARENT: style = wxTRANSPARENT;
00971 break;
00972 case a2dSTROKE_DOT: style = wxDOT;
00973 break;
00974 case a2dSTROKE_DOT_DASH: style = wxDOT_DASH;
00975 break;
00976 case a2dSTROKE_LONG_DASH: style = wxLONG_DASH;
00977 break;
00978 case a2dSTROKE_SHORT_DASH: style = wxSHORT_DASH;
00979 break;
00980 case a2dSTROKE_BDIAGONAL_HATCH: style = wxBDIAGONAL_HATCH;
00981 break;
00982 case a2dSTROKE_CROSSDIAG_HATCH: style = wxCROSSDIAG_HATCH;
00983 break;
00984 case a2dSTROKE_FDIAGONAL_HATCH: style = wxFDIAGONAL_HATCH;
00985 break;
00986 case a2dSTROKE_CROSS_HATCH: style = wxCROSS_HATCH;
00987 break;
00988 case a2dSTROKE_HORIZONTAL_HATCH: style = wxHORIZONTAL_HATCH;
00989 break;
00990 case a2dSTROKE_VERTICAL_HATCH: style = wxVERTICAL_HATCH;
00991 break;
00992 case a2dSTROKE_STIPPLE: style = wxSTIPPLE;
00993 break;
00994 case a2dSTROKE_STIPPLE_MASK_OPAQUE: style = wxSTIPPLE_MASK_OPAQUE;
00995 break;
00996 default: style = a2dSTROKE_SOLID;
00997 }
00998
00999 if ( m_drawstyle == a2dWIREFRAME_ZERO_WIDTH )
01000 {
01001 dcpen = wxPen( stroke1, 0, style );
01002 }
01003 else
01004 {
01005 dcpen = wxPen( stroke1, ( int ) m_activestroke.GetWidth(), style );
01006 dcpen.SetJoin( m_activestroke.GetJoin() );
01007 dcpen.SetCap( m_activestroke.GetCap() );
01008 if ( m_activestroke.GetPixelStroke() )
01009 dcpen.SetWidth( DeviceToWorldXRel( m_activestroke.GetWidth() ) );
01010 }
01011 }
01012 else if ( m_activestroke.GetType() == a2dSTROKE_BITMAP )
01013 {
01014 if ( m_drawstyle == a2dWIREFRAME_ZERO_WIDTH )
01015 dcpen = wxPen( stroke1, 0, wxBRUSHSTYLE_SOLID );
01016 else
01017 {
01018 int width = (int) m_activestroke.GetWidth();
01019 if ( m_activestroke.GetPixelStroke() )
01020 width = DeviceToWorldXRel( width );
01021 dcpen = wxPen( stroke1, width, wxBRUSHSTYLE_SOLID );
01022 dcpen.SetJoin( m_activestroke.GetJoin() );
01023 dcpen.SetCap( m_activestroke.GetCap() );
01024 }
01025
01026 #if defined(__WXMSW__)
01027 wxBrushStyle style;
01028 switch( m_activestroke.GetStyle() )
01029 {
01030 case a2dSTROKE_STIPPLE:
01031 style = wxBRUSHSTYLE_STIPPLE;
01032 dcpen.SetStyle( style );
01033 dcpen.SetStipple( m_activestroke.GetStipple() );
01034 break;
01035 case a2dSTROKE_STIPPLE_MASK_OPAQUE_TRANSPARENT:
01036 case a2dSTROKE_STIPPLE_MASK_OPAQUE:
01037 if ( 0 )
01038 {
01039 wxBitmap noMask = m_activestroke.GetStipple();
01040 noMask.SetMask( NULL );
01041 style = wxBRUSHSTYLE_STIPPLE;
01042 dcpen.SetStyle( style );
01043 dcpen.SetStipple( noMask );
01044 }
01045 else
01046 {
01047 style = wxBRUSHSTYLE_STIPPLE_MASK_OPAQUE;
01048 dcpen.SetStyle( style );
01049 dcpen.SetStipple( m_activestroke.GetStipple() );
01050 }
01051 break;
01052 default: style = wxBRUSHSTYLE_SOLID;
01053 dcpen.SetStyle( style );
01054 }
01055 #endif
01056
01057 }
01058 return context->CreatePen(dcpen);
01059 }
01060
01061 wxGraphicsBrush a2dDrawer2D::ConvertActiveToGraphicsBrush( wxGraphicsContext* context )
01062 {
01063 wxBrush dcbrush = *wxTRANSPARENT_BRUSH;
01064 wxColour textb;
01065 wxBrushStyle style;
01066 wxColour fill1;
01067 fill1.Set( m_colour1redFill, m_colour1greenFill, m_colour1blueFill, m_FillOpacityCol1 );
01068 wxColour fill2;
01069 fill2.Set( m_colour2redFill, m_colour2greenFill, m_colour2blueFill, m_FillOpacityCol2 );
01070
01071 if ( !m_activefill.GetFilling() )
01072 {
01073 dcbrush = *wxTRANSPARENT_BRUSH;
01074 textb = *wxBLACK;
01075 return context->CreateBrush(dcbrush);
01076 }
01077 else if ( m_activefill.GetStyle() == a2dFILL_TRANSPARENT )
01078 {
01079 dcbrush = *wxTRANSPARENT_BRUSH;
01080 textb = *wxBLACK;
01081 return context->CreateBrush(dcbrush);
01082 }
01083 else if ( m_activefill.IsNoFill() )
01084 {
01085 dcbrush = *wxTRANSPARENT_BRUSH;
01086 textb = *wxBLACK;
01087 return context->CreateBrush(dcbrush);
01088 }
01089 else if ( m_activefill.GetType() == a2dFILL_ONE_COLOUR )
01090 {
01091 switch( m_activefill.GetStyle() )
01092 {
01093 case a2dFILL_TRANSPARENT:
01094 style = wxBRUSHSTYLE_TRANSPARENT;
01095 dcbrush.SetColour( fill1 );
01096 dcbrush.SetStyle( style );
01097 break;
01098 case a2dFILL_SOLID: style = wxBRUSHSTYLE_SOLID;
01099 dcbrush.SetColour( fill1 );
01100 dcbrush.SetStyle( style );
01101 break;
01102 case a2dFILL_BDIAGONAL_HATCH:
01103 style = wxBRUSHSTYLE_BDIAGONAL_HATCH;
01104 dcbrush.SetColour( fill1 );
01105 dcbrush.SetStyle( style );
01106 break;
01107 case a2dFILL_CROSSDIAG_HATCH:
01108 style = wxBRUSHSTYLE_CROSSDIAG_HATCH;
01109 dcbrush.SetColour( fill1 );
01110 dcbrush.SetStyle( style );
01111 break;
01112 case a2dFILL_FDIAGONAL_HATCH:
01113 style = wxBRUSHSTYLE_FDIAGONAL_HATCH;
01114 dcbrush.SetColour( fill1 );
01115 dcbrush.SetStyle( style );
01116 break;
01117 case a2dFILL_CROSS_HATCH:
01118 style = wxBRUSHSTYLE_CROSS_HATCH;
01119 dcbrush.SetColour( fill1 );
01120 dcbrush.SetStyle( style );
01121 break;
01122 case a2dFILL_HORIZONTAL_HATCH:
01123 style = wxBRUSHSTYLE_HORIZONTAL_HATCH;
01124 dcbrush.SetColour( fill1 );
01125 dcbrush.SetStyle( style );
01126 break;
01127 case a2dFILL_VERTICAL_HATCH:
01128 style = wxBRUSHSTYLE_VERTICAL_HATCH;
01129 dcbrush.SetColour( fill1 );
01130 dcbrush.SetStyle( style );
01131 break;
01132 default: style = wxBRUSHSTYLE_SOLID;
01133 dcbrush.SetColour( fill1 );
01134 dcbrush.SetStyle( style );
01135 }
01136 return context->CreateBrush(dcbrush);
01137 }
01138 else if ( m_activefill.GetType() == a2dFILL_HATCH_TWO_COLOUR )
01139 {
01140 wxBrushStyle style;
01141 switch( m_activefill.GetStyle() )
01142 {
01143 case a2dFILL_TRANSPARENT:
01144 style = wxBRUSHSTYLE_TRANSPARENT;
01145 dcbrush.SetColour( fill1 );
01146 dcbrush.SetStyle( style );
01147 break;
01148 case a2dFILL_TWOCOL_BDIAGONAL_HATCH:
01149 style = wxBRUSHSTYLE_BDIAGONAL_HATCH;
01150 dcbrush.SetColour( fill1 );
01151 dcbrush.SetStyle( style );
01152 break;
01153 case a2dFILL_TWOCOL_CROSSDIAG_HATCH:
01154 style = wxBRUSHSTYLE_CROSSDIAG_HATCH;
01155 dcbrush.SetColour( fill1 );
01156 dcbrush.SetStyle( style );
01157 break;
01158 case a2dFILL_TWOCOL_FDIAGONAL_HATCH:
01159 style = wxBRUSHSTYLE_FDIAGONAL_HATCH;
01160 dcbrush.SetColour( fill1 );
01161 dcbrush.SetStyle( style );
01162 break;
01163 case a2dFILL_TWOCOL_CROSS_HATCH:
01164 style = wxBRUSHSTYLE_CROSS_HATCH;
01165 dcbrush.SetColour( fill1 );
01166 dcbrush.SetStyle( style );
01167 break;
01168 case a2dFILL_TWOCOL_HORIZONTAL_HATCH:
01169 style = wxBRUSHSTYLE_HORIZONTAL_HATCH;
01170 dcbrush.SetColour( fill1 );
01171 dcbrush.SetStyle( style );
01172 break;
01173 case a2dFILL_TWOCOL_VERTICAL_HATCH:
01174 style = wxBRUSHSTYLE_VERTICAL_HATCH;
01175 dcbrush.SetColour( fill1 );
01176 dcbrush.SetStyle( style );
01177 break;
01178 default:
01179 style = wxBRUSHSTYLE_SOLID;
01180 dcbrush.SetColour( fill1 );
01181 dcbrush.SetStyle( style );
01182 }
01183 return context->CreateBrush(dcbrush);
01184 }
01185 else if ( m_activefill.GetType() == a2dFILL_BITMAP )
01186 {
01187 wxBrushStyle style;
01188 switch( m_activefill.GetStyle() )
01189 {
01190 case a2dFILL_STIPPLE:
01191 style = wxBRUSHSTYLE_STIPPLE;
01192 dcbrush.SetColour( fill1 );
01193 dcbrush.SetStipple( m_activefill.GetStipple() );
01194 dcbrush.SetStyle( style );
01195 break;
01196 case a2dFILL_STIPPLE_MASK_OPAQUE_TRANSPARENT:
01197 case a2dFILL_STIPPLE_MASK_OPAQUE:
01198 if ( 0 )
01199 {
01200 wxBitmap noMask = m_activefill.GetStipple();
01201 noMask.SetMask( NULL );
01202 style = wxBRUSHSTYLE_STIPPLE;
01203 dcbrush.SetColour( fill1 );
01204 dcbrush.SetStipple( noMask );
01205 }
01206 else
01207 {
01208 style = wxBRUSHSTYLE_STIPPLE_MASK_OPAQUE;
01209 dcbrush.SetColour( fill1 );
01210 dcbrush.SetStipple( m_activefill.GetStipple() );
01211 }
01212 dcbrush.SetStyle( style );
01213 break;
01214 default: style = wxBRUSHSTYLE_SOLID;
01215 dcbrush.SetColour( fill1 );
01216 dcbrush.SetStyle( style );
01217 }
01218 return context->CreateBrush(dcbrush);
01219 }
01220
01221 if ( m_activefill.GetType() == a2dFILL_GRADIENT_FILL_LINEAR )
01222 {
01223 double x1 = m_activefill.GetStart().m_x;
01224 double y1 = m_activefill.GetStart().m_y;
01225 double x2 = m_activefill.GetStop().m_x;
01226 double y2 = m_activefill.GetStop().m_y;
01227 return context->CreateLinearGradientBrush( x1, y1, x2, y2, fill1, fill2);
01228 }
01229 if ( m_activefill.GetType() == a2dFILL_GRADIENT_FILL_RADIAL )
01230 {
01231 double xf = m_activefill.GetFocal().m_x;
01232 double yf = m_activefill.GetFocal().m_y;
01233 double xc = m_activefill.GetCenter().m_x;
01234 double yc = m_activefill.GetCenter().m_y;
01235 double r = m_activefill.GetRadius();
01236 return context->CreateRadialGradientBrush( xf, yf, xc, yc, r, fill1, fill2);
01237 }
01238 return wxNullGraphicsBrush;
01239 }
01240
01241 #endif // wxART2D_USE_GRAPHICS_CONTEXT
01242
01243
01244
01245
01246 int a2dDrawer2D::ToDeviceLines( a2dVertexArray* points, a2dBoundingBox& devbbox, bool& smallPoly, bool replaceByRectangle )
01247 {
01248 unsigned int segments = 0;
01249
01250 unsigned int i;
01251 for ( i = 0; i < points->size(); i++ )
01252 {
01253 const a2dLineSegmentPtr seg = points->Item( i );
01254
01255 if ( seg->GetArc() )
01256 {
01257 const a2dArcSegment* cseg = ( const a2dArcSegment* ) seg.Get();
01258
01259 double radius, center_x, center_y, beginrad, midrad, endrad, phit;
01260
01261 if ( cseg->CalcR( *(points->Item( i ? i - 1 : 0 )), radius, center_x, center_y, beginrad, midrad, endrad, phit ) )
01262 {
01263 double dphi;
01264 unsigned int circlesegments;
01265 double radiusDev = m_usertodevice.TransformDistance( radius );
01266 Aberration( m_displayaberration, phit, radiusDev , dphi, circlesegments );
01267 segments += circlesegments + 1;
01268 }
01269 else
01270 segments ++;
01271 }
01272 else
01273 segments++;
01274 }
01275
01276
01277 m_cpointsDouble.resize( segments * 2 );
01278
01279 unsigned int count = 0;
01280 double x, y, lastx, lasty;
01281 for ( i = 0; i < points->size(); i++ )
01282 {
01283 const a2dLineSegmentPtr seg = points->Item( i );
01284
01285 if ( !seg->GetArc() )
01286 {
01287 GetUserToDeviceTransform().TransformPoint( seg->m_x, seg->m_y, x, y );
01288
01289
01290 if( !count || fabs( x - lastx ) > 0.001 || fabs( y - lasty ) > 0.001 )
01291 {
01292 m_cpointsDouble[count].x = x;
01293 m_cpointsDouble[count].y = y;
01294 lastx = x;
01295 lasty = y;
01296 devbbox.Expand( x, y );
01297 count++;
01298 }
01299 }
01300 else
01301 {
01302 const a2dArcSegment* cseg = ( const a2dArcSegment* ) seg.Get();
01303
01304 double radius, center_x, center_y, beginrad, midrad, endrad, phit;
01305
01306 if ( cseg->CalcR( *(points->Item( i ? i - 1 : 0 )), radius, center_x, center_y, beginrad, midrad, endrad, phit ) )
01307 {
01308 double dphi;
01309 unsigned int segments;
01310 double radiusDev = m_usertodevice.TransformDistance( radius );
01311 Aberration( m_displayaberration, phit, radiusDev , dphi, segments );
01312
01313 double theta = beginrad;
01314 unsigned int step;
01315
01316 double x, y;
01317 for ( step = 0; step < segments + 1; step++ )
01318 {
01319 GetUserToDeviceTransform().TransformPoint( center_x + radius * cos ( theta ), center_y + radius * sin ( theta ), x, y );
01320
01321
01322 if( !count || fabs( x - lastx ) > 0.001 || fabs( y - lasty ) > 0.001 )
01323 {
01324 m_cpointsDouble[count].x = x;
01325 m_cpointsDouble[count].y = y;
01326 lastx = x;
01327 lasty = y;
01328 devbbox.Expand( x, y );
01329 count++;
01330 }
01331 theta = theta + dphi;
01332 }
01333 }
01334 else
01335 {
01336 double x, y;
01337 GetUserToDeviceTransform().TransformPoint( cseg->m_x, cseg->m_y, x, y );
01338
01339
01340 if( !count || fabs( x - lastx ) > 0.001 || fabs( y - lasty ) > 0.001 )
01341 {
01342 m_cpointsDouble[count].x = x;
01343 m_cpointsDouble[count].y = y;
01344 lastx = x;
01345 lasty = y;
01346 devbbox.Expand( x, y );
01347 count++;
01348 }
01349 }
01350 }
01351 }
01352
01353 if ( devbbox.GetSize() < m_polygonFillThreshold )
01354 {
01355 smallPoly = true;
01356 if ( replaceByRectangle )
01357 {
01358 m_cpointsDouble[0].x = devbbox.GetMinX(); m_cpointsDouble[0].y = devbbox.GetMinY();
01359 m_cpointsDouble[1].x = devbbox.GetMinX(); m_cpointsDouble[1].y = devbbox.GetMaxY();
01360 m_cpointsDouble[2].x = devbbox.GetMaxX(); m_cpointsDouble[2].y = devbbox.GetMaxY();
01361 m_cpointsDouble[3].x = devbbox.GetMaxX(); m_cpointsDouble[3].y = devbbox.GetMinY();
01362 return 4;
01363 }
01364 }
01365 return count;
01366 }
01367
01368 int a2dDrawer2D::ToDeviceLines( const a2dVertexList *list, a2dBoundingBox& devbbox, bool& smallPoly, bool replaceByRectangle )
01369 {
01370 unsigned int segments = 0;
01371
01372 if ( list->empty() )
01373 return 0;
01374
01375 a2dVertexList::const_iterator iterprev = list->end();
01376 if ( iterprev != list->begin() )
01377 iterprev--;
01378 a2dVertexList::const_iterator iter = list->begin();
01379 while ( iter != list->end() )
01380 {
01381 a2dLineSegment * seg = ( *iter );
01382
01383 if ( seg->GetArc() )
01384 {
01385 a2dArcSegment * cseg = ( a2dArcSegment* ) seg;
01386
01387 double radius, center_x, center_y, beginrad, midrad, endrad, phit;
01388
01389 if ( cseg->CalcR( *( *iterprev ), radius, center_x, center_y, beginrad, midrad, endrad, phit ) )
01390 {
01391 double dphi;
01392 unsigned int circlesegments;
01393 double radiusDev = m_usertodevice.TransformDistance( radius );
01394 Aberration( m_displayaberration, phit, radiusDev , dphi, circlesegments );
01395 segments += circlesegments + 1;
01396 }
01397 else
01398 segments ++;
01399 }
01400 else
01401 segments++;
01402
01403 iterprev = iter++;
01404 }
01405
01406
01407 m_cpointsDouble.resize( segments * 2 );
01408
01409 unsigned int count = 0;
01410 double x, y, lastx, lasty;
01411 iterprev = list->end();
01412 if ( iterprev != list->begin() )
01413 iterprev--;
01414 iter = list->begin();
01415 while ( iter != list->end() )
01416 {
01417 a2dLineSegment * seg = ( *iter );
01418
01419 if ( !seg->GetArc() )
01420 {
01421 GetUserToDeviceTransform().TransformPoint( seg->m_x, seg->m_y, x, y );
01422
01423
01424 if( !count || fabs( x - lastx ) > 0.001 || fabs( y - lasty ) > 0.001 )
01425 {
01426 m_cpointsDouble[count].x = x;
01427 m_cpointsDouble[count].y = y;
01428 lastx = x;
01429 lasty = y;
01430 devbbox.Expand( x, y );
01431 count++;
01432 }
01433 }
01434 else
01435 {
01436 a2dArcSegment* cseg = ( a2dArcSegment* ) seg;
01437
01438 double radius, center_x, center_y, beginrad, midrad, endrad, phit;
01439
01440 if ( cseg->CalcR( *( *iterprev ), radius, center_x, center_y, beginrad, midrad, endrad, phit ) )
01441 {
01442 double dphi;
01443 unsigned int segments;
01444 double radiusDev = m_usertodevice.TransformDistance( radius );
01445 Aberration( m_displayaberration, phit, radiusDev , dphi, segments );
01446
01447 double theta = beginrad;
01448 unsigned int step;
01449
01450 double x, y;
01451 for ( step = 0; step < segments + 1; step++ )
01452 {
01453 GetUserToDeviceTransform().TransformPoint( center_x + radius * cos ( theta ), center_y + radius * sin ( theta ), x, y );
01454
01455
01456 if( !count || fabs( x - lastx ) > 0.001 || fabs( y - lasty ) > 0.001 )
01457 {
01458 m_cpointsDouble[count].x = x;
01459 m_cpointsDouble[count].y = y;
01460 lastx = x;
01461 lasty = y;
01462 devbbox.Expand( x, y );
01463 count++;
01464 }
01465 theta = theta + dphi;
01466 }
01467 }
01468 else
01469 {
01470 double x, y;
01471 GetUserToDeviceTransform().TransformPoint( cseg->m_x, cseg->m_y, x, y );
01472
01473
01474 if( !count || fabs( x - lastx ) > 0.001 || fabs( y - lasty ) > 0.001 )
01475 {
01476 m_cpointsDouble[count].x = x;
01477 m_cpointsDouble[count].y = y;
01478 lastx = x;
01479 lasty = y;
01480 devbbox.Expand( x, y );
01481 count++;
01482 }
01483 }
01484 }
01485 iterprev = iter++;
01486 }
01487
01488 if ( devbbox.GetSize() < m_polygonFillThreshold )
01489 {
01490 smallPoly = true;
01491 if ( replaceByRectangle )
01492 {
01493 m_cpointsDouble[0].x = devbbox.GetMinX(); m_cpointsDouble[0].y = devbbox.GetMinY();
01494 m_cpointsDouble[1].x = devbbox.GetMinX(); m_cpointsDouble[1].y = devbbox.GetMaxY();
01495 m_cpointsDouble[2].x = devbbox.GetMaxX(); m_cpointsDouble[2].y = devbbox.GetMaxY();
01496 m_cpointsDouble[3].x = devbbox.GetMaxX(); m_cpointsDouble[3].y = devbbox.GetMinY();
01497 return 4;
01498 }
01499 }
01500 return count;
01501 }
01502
01503
01504 void a2dDrawer2D::DrawVpath( const a2dVpath* path )
01505 {
01506 if ( m_disableDrawing )
01507 return;
01508
01509 double tstep = 1 / ( double ) SPLINE_STEP;
01510 unsigned int i;
01511
01512 a2dVertexList points;
01513 bool move = false;
01514 int count = 0;
01515 bool nostrokeparts = false;
01516
01517
01518 for ( i = 0; i < path->size(); i++ )
01519 {
01520 a2dVpathSegment& seg = path->Item( i );
01521 switch ( seg.GetType() )
01522 {
01523 case a2dPATHSEG_MOVETO:
01524 if ( count == 0 )
01525 {
01526 points.push_back( new a2dLineSegment( seg.m_x1, seg.m_y1 ) );
01527 count++;
01528 }
01529 else
01530 {
01531 i--;
01532 move = true;
01533 }
01534 break;
01535
01536 case a2dPATHSEG_LINETO:
01537 points.push_back( new a2dLineSegment( seg.m_x1, seg.m_y1 ) );
01538 count++;
01539 break;
01540 case a2dPATHSEG_LINETO_NOSTROKE:
01541 points.push_back( new a2dLineSegment( seg.m_x1, seg.m_y1 ) );
01542 count++;
01543 nostrokeparts = true;
01544 break;
01545
01546 case a2dPATHSEG_CBCURVETO_NOSTROKE:
01547 nostrokeparts = true;
01548 case a2dPATHSEG_CBCURVETO:
01549 {
01550 double xw, yw;
01551
01552 double xwl = path->Item( i ? i - 1 : 0 ).m_x1;
01553 double ywl = path->Item( i ? i - 1 : 0 ).m_y1;
01554 a2dVpathCBCurveSegment& cseg = ( a2dVpathCBCurveSegment& ) seg;
01555
01556 int step;
01557 double t = 0;
01558 for ( step = 0; step <= SPLINE_STEP; step++ )
01559 {
01560 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 );
01561 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 );
01562 points.push_back( new a2dLineSegment( xw, yw ) );
01563 count++;
01564 t = t + tstep;
01565 }
01566 }
01567 break;
01568
01569 case a2dPATHSEG_QBCURVETO_NOSTROKE:
01570 nostrokeparts = true;
01571 case a2dPATHSEG_QBCURVETO:
01572 {
01573 double xw, yw;
01574
01575 double xwl = path->Item( i ? i - 1 : 0 ).m_x1;
01576 double ywl = path->Item( i ? i - 1 : 0 ).m_y1;
01577 a2dVpathQBCurveSegment& cseg = ( a2dVpathQBCurveSegment& ) seg;
01578
01579 int step;
01580 double t = 0;
01581 for ( step = 0; step <= SPLINE_STEP; step++ )
01582 {
01583 xw = xwl * pow( 1 - t, 2 ) + cseg.m_x2 * ( 1 - t ) * t * 2 + cseg.m_x1 * pow( t, 2 );
01584 yw = ywl * pow( 1 - t, 2 ) + cseg.m_y2 * ( 1 - t ) * t * 2 + cseg.m_y1 * pow( t, 2 );
01585 points.push_back( new a2dLineSegment( xw, yw ) );
01586 count++;
01587 t = t + tstep;
01588 }
01589 }
01590 break;
01591
01592 case a2dPATHSEG_ARCTO_NOSTROKE:
01593 nostrokeparts = true;
01594 case a2dPATHSEG_ARCTO:
01595 {
01596 a2dVpathArcSegment& cseg = ( a2dVpathArcSegment& ) seg;
01597
01598 double radius, center_x, center_y, beginrad, midrad, endrad, phit;
01599
01600 if ( cseg.CalcR( path->Item( i ? i - 1 : 0 ), radius, center_x, center_y, beginrad, midrad, endrad, phit ) )
01601 {
01602 double dphi;
01603 unsigned int segments;
01604 double radiusDev = m_usertodevice.TransformDistance( radius );
01605 Aberration( m_displayaberration, phit, radiusDev , dphi, segments );
01606
01607 double theta = beginrad;
01608 unsigned int step;
01609
01610 for ( step = 0; step < segments + 1; step++ )
01611 {
01612 points.push_back( new a2dLineSegment( center_x + radius * cos ( theta ), center_y + radius * sin ( theta ) ) );
01613 count++;
01614 theta = theta + dphi;
01615 }
01616 }
01617 else
01618 {
01619 points.push_back( new a2dLineSegment( cseg.m_x1, cseg.m_y1 ) );
01620 count++;
01621 }
01622 }
01623 default:
01624 break;
01625 break;
01626 }
01627
01628 if ( move )
01629 {
01630 DrawLines( &points, false );
01631 move = false;
01632 count = 0;
01633 points.clear();
01634 }
01635 else if ( seg.GetClose() != a2dPATHSEG_END_OPEN )
01636 {
01637 if ( nostrokeparts || seg.GetClose() == a2dPATHSEG_END_CLOSED_NOSTROKE )
01638 {
01639 a2dStroke stroke = m_activestroke;
01640 SetDrawerStroke( *a2dTRANSPARENT_STROKE );
01641 DrawPolygon( &points, false, wxODDEVEN_RULE );
01642 SetDrawerStroke( stroke );
01643 nostrokeparts = true;
01644 }
01645 else
01646 {
01647 DrawPolygon( &points, false, wxODDEVEN_RULE );
01648 }
01649
01650 move = false;
01651 count = 0;
01652 points.clear();
01653 }
01654 else if ( i == path->size() - 1 )
01655 {
01656 DrawLines( &points, false );
01657 }
01658 }
01659
01660 if ( nostrokeparts )
01661 {
01662 points.clear();
01663 move = false;
01664 count = 0;
01665 nostrokeparts = false;
01666
01667 double lastmovex = 0;
01668 double lastmovey = 0;
01669
01670 for ( i = 0; i < path->size(); i++ )
01671 {
01672 a2dVpathSegment& seg = path->Item( i );
01673 switch ( seg.GetType() )
01674 {
01675 case a2dPATHSEG_MOVETO:
01676 if ( count == 0 )
01677 {
01678 points.push_back( new a2dLineSegment( seg.m_x1, seg.m_y1 ) );
01679 lastmovex = seg.m_x1;
01680 lastmovey = seg.m_y1;
01681 count++;
01682 }
01683 else
01684 {
01685 i--;
01686 move = true;
01687 }
01688 break;
01689
01690 case a2dPATHSEG_LINETO:
01691 points.push_back( new a2dLineSegment( seg.m_x1, seg.m_y1 ) );
01692 count++;
01693 break;
01694
01695 case a2dPATHSEG_LINETO_NOSTROKE:
01696 case a2dPATHSEG_CBCURVETO_NOSTROKE:
01697 case a2dPATHSEG_QBCURVETO_NOSTROKE:
01698 case a2dPATHSEG_ARCTO_NOSTROKE:
01699 if ( count == 0 )
01700 {
01701 points.push_back( new a2dLineSegment( seg.m_x1, seg.m_y1 ) );
01702 count++;
01703 }
01704 else
01705 {
01706 i--;
01707 nostrokeparts = true;
01708 }
01709 break;
01710
01711 case a2dPATHSEG_CBCURVETO:
01712 {
01713 double xw, yw;
01714
01715 double xwl = path->Item( i ? i - 1 : 0 ).m_x1;
01716 double ywl = path->Item( i ? i - 1 : 0 ).m_y1;
01717 a2dVpathCBCurveSegment& cseg = ( a2dVpathCBCurveSegment& ) seg;
01718
01719 int step;
01720 double t = 0;
01721 for ( step = 0; step <= SPLINE_STEP; step++ )
01722 {
01723 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 );
01724 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 );
01725 points.push_back( new a2dLineSegment( xw, yw ) );
01726 count++;
01727 t = t + tstep;
01728 }
01729 }
01730 break;
01731
01732 case a2dPATHSEG_QBCURVETO:
01733 {
01734 double xw, yw;
01735
01736 double xwl = path->Item( i ? i - 1 : 0 ).m_x1;
01737 double ywl = path->Item( i ? i - 1 : 0 ).m_y1;
01738 a2dVpathQBCurveSegment& cseg = ( a2dVpathQBCurveSegment& ) seg;
01739
01740 int step;
01741 double t = 0;
01742 for ( step = 0; step <= SPLINE_STEP; step++ )
01743 {
01744 xw = xwl * pow( 1 - t, 2 ) + cseg.m_x2 * ( 1 - t ) * t * 2 + cseg.m_x1 * pow( t, 2 );
01745 yw = ywl * pow( 1 - t, 2 ) + cseg.m_y2 * ( 1 - t ) * t * 2 + cseg.m_y1 * pow( t, 2 );
01746 points.push_back( new a2dLineSegment( xw, yw ) );
01747 count++;
01748 t = t + tstep;
01749 }
01750 }
01751 break;
01752
01753 case a2dPATHSEG_ARCTO:
01754 {
01755 a2dVpathArcSegment& cseg = ( a2dVpathArcSegment& ) seg;
01756
01757 double radius, center_x, center_y, beginrad, midrad, endrad, phit;
01758
01759 if ( cseg.CalcR( path->Item( i ? i - 1 : 0 ), radius, center_x, center_y, beginrad, midrad, endrad, phit ) )
01760 {
01761 double dphi;
01762 unsigned int segments;
01763 double radiusDev = m_usertodevice.TransformDistance( radius );
01764 Aberration( m_displayaberration, phit, radiusDev , dphi, segments );
01765
01766 double theta = beginrad;
01767 unsigned int step;
01768
01769 for ( step = 0; step < segments + 1; step++ )
01770 {
01771 points.push_back( new a2dLineSegment( center_x + radius * cos ( theta ), center_y + radius * sin ( theta ) ) );
01772 count++;
01773 theta = theta + dphi;
01774 }
01775 }
01776 else
01777 {
01778 points.push_back( new a2dLineSegment( cseg.m_x1, cseg.m_y1 ) );
01779 count++;
01780 }
01781 }
01782 default:
01783 break;
01784
01785 break;
01786 }
01787
01788 if ( move || nostrokeparts )
01789 {
01790 DrawLines( &points, false );
01791 move = false;
01792 nostrokeparts = false;
01793 points.clear();
01794 count = 0;
01795 }
01796 else if ( seg.GetClose() != a2dPATHSEG_END_OPEN )
01797 {
01798 if ( seg.GetClose() == a2dPATHSEG_END_CLOSED )
01799 {
01800 points.push_back( new a2dLineSegment( lastmovex, lastmovey ) );
01801 count++;
01802 }
01803 DrawLines( &points, false );
01804 nostrokeparts = false;
01805 move = false;
01806 points.clear();
01807 count = 0;
01808 }
01809 else if ( i == path->size() )
01810 {
01811 DrawLines( &points, false );
01812 }
01813 }
01814 }
01815 }
01816
01817 void a2dDrawer2D::DrawPolyPolygon( a2dListOfa2dVertexList polylist, wxPolygonFillMode fillStyle )
01818 {
01819 if ( m_disableDrawing )
01820 return;
01821
01822
01823 }
01824
01825 void a2dDrawer2D::DrawPolygon( a2dVertexArray* points, bool spline, wxPolygonFillMode fillStyle )
01826 {
01827 if ( m_disableDrawing )
01828 return;
01829
01830 a2dBoundingBox devbox;
01831 bool smallPoly = false;
01832 int segments = ToDeviceLines( points, devbox, smallPoly );
01833
01834 if ( segments == 0 )
01835 return;
01836
01837 if ( smallPoly )
01838 {
01839 DeviceDrawLines( segments, spline );
01840 DeviceDrawLine( m_cpointsDouble[0].x, m_cpointsDouble[0].y, m_cpointsDouble[segments-1].x, m_cpointsDouble[segments-1].y );
01841 }
01842 else
01843 DeviceDrawPolygon( segments, spline, fillStyle );
01844 }
01845
01846 void a2dDrawer2D::DrawPolygon( const a2dVertexList *list, bool spline, wxPolygonFillMode fillStyle )
01847 {
01848 if ( m_disableDrawing )
01849 return;
01850
01851 a2dBoundingBox devbox;
01852 bool smallPoly = false;
01853 int segments = ToDeviceLines( list, devbox, smallPoly );
01854
01855 if ( segments == 0 )
01856 return;
01857
01858 if ( smallPoly )
01859 {
01860 DeviceDrawLines( segments, spline );
01861 DeviceDrawLine( m_cpointsDouble[0].x, m_cpointsDouble[0].y, m_cpointsDouble[segments-1].x, m_cpointsDouble[segments-1].y );
01862 }
01863 else
01864 DeviceDrawPolygon( segments, spline, fillStyle );
01865 }
01866
01867 void a2dDrawer2D::DrawLines( a2dVertexArray* points, bool spline )
01868 {
01869 if ( m_disableDrawing )
01870 return;
01871
01872 a2dBoundingBox devbox;
01873 bool smallPoly = false;
01874 int segments = ToDeviceLines( points, devbox, smallPoly );
01875
01876 if ( segments > 0 )
01877 DeviceDrawLines( segments, spline );
01878 }
01879
01880 void a2dDrawer2D::DrawLines( const a2dVertexList* list, bool spline )
01881 {
01882 if ( m_disableDrawing )
01883 return;
01884
01885 a2dBoundingBox devbox;
01886 bool smallPoly = false;
01887 int segments = ToDeviceLines( list, devbox, smallPoly );
01888
01889 if ( segments > 0 )
01890 DeviceDrawLines( segments, spline );
01891 }
01892
01893 void a2dDrawer2D::DrawArc( double x1, double y1, double x2, double y2, double xc, double yc, bool chord )
01894 {
01895 if ( m_disableDrawing )
01896 return;
01897
01898 double dx = x1 - xc;
01899 double dy = y1 - yc;
01900
01901 double start;
01902 double end;
01903 double radius = sqrt( dx * dx + dy * dy );
01904
01905 if ( x1 == x2 && y1 ==y2 )
01906 {
01907 start = 0;
01908 end = 2.0 * wxPI;
01909 }
01910 else
01911 {
01912 if ( !dx && !dy )
01913 start = 0;
01914 else
01915 start = atan2( dy, dx );
01916
01917 dx = x2 - xc;
01918 dy = y2 - yc;
01919
01920 if ( !dx && !dy )
01921 end = 0;
01922 else
01923 end = atan2( dy, dx );
01924
01925 end = end - start;
01926 if ( end <= 0 ) end += 2.0 * wxPI;
01927 if ( start < 0 ) start += 2.0 * wxPI;
01928 end = end + start;
01929 }
01930
01931 DrawEllipticArc( xc, yc, 2.0 * radius, 2.0 * radius, start * 180.0 / wxPI, end * 180.0 / wxPI, chord );
01932 }
01933
01934 void a2dDrawer2D::DrawEllipticArc( double xc, double yc, double width, double height, double sa, double ea, bool chord )
01935 {
01936 if ( m_disableDrawing )
01937 return;
01938
01939 double start, end;
01940
01941 start = wxDegToRad( sa );
01942 end = wxDegToRad( ea );
01943
01944 end = end - start;
01945 if ( end <= 0 ) end += 2.0 * wxPI;
01946
01947 if ( start < 0 ) start += 2.0 * wxPI;
01948
01949 end = end + start;
01950
01951 double dphi;
01952 unsigned int segments;
01953
01954
01955 double radiusDev = m_usertodevice.TransformDistance( wxMax( width, height ) );
01956 Aberration( m_displayaberration, end - start, radiusDev , dphi, segments );
01957
01958 a2dVertexList points;
01959 double theta = start;
01960 unsigned int i;
01961 for ( i = 0; i < segments + 1; i++ )
01962 {
01963 points.push_back( new a2dLineSegment( xc + width / 2 * cos ( theta ), yc + height / 2 * sin ( theta ) ) );
01964 theta = theta + dphi;
01965 }
01966
01967 if ( !chord )
01968 {
01969 points.push_back( new a2dLineSegment( xc, yc ) );
01970 DrawPolygon( &points );
01971 }
01972 else
01973 DrawLines( &points );
01974 }
01975
01976 void a2dDrawer2D::DrawCenterRoundedRectangle( double xc, double yc, double width, double height, double radius, bool pixelsize )
01977 {
01978 if ( m_disableDrawing )
01979 return;
01980
01981 DrawRoundedRectangle( xc -width / 2, yc - height / 2, width, height, radius, pixelsize );
01982 }
01983
01984 void a2dDrawer2D::DrawRoundedRectangle( double x, double y, double width, double height, double radius, bool pixelsize )
01985 {
01986 if ( m_disableDrawing )
01987 return;
01988
01989 if ( pixelsize )
01990 {
01991 width = DeviceToWorldXRel( width );
01992 height = DeviceToWorldYRel( height );
01993 radius = DeviceToWorldXRel( radius );
01994 if( m_yaxis )
01995 height = -height;
01996 }
01997
01998 if ( radius )
01999 {
02000 static const double sintab[9] =
02001 {
02002 1 - 0,
02003 1 - 0.19509032201612826784828486847702,
02004 1 - 0.38268343236508977172845998403040,
02005 1 - 0.55557023301960222474283081394853,
02006 1 - 0.70710678118654752440084436210485,
02007 1 - 0.83146961230254523707878837761791,
02008 1 - 0.92387953251128675612818318939679,
02009 1 - 0.98078528040323044912618223613424,
02010 1 - 1
02011 };
02012
02013 a2dVertexList points;
02014 int i;
02015 for( i = 0; i <= 8; i++ )
02016 points.push_back( new a2dLineSegment( x + radius * sintab[i], y + radius * sintab[8-i] ) );
02017 for( i = 0; i <= 8; i++ )
02018 points.push_back( new a2dLineSegment( x + radius * sintab[8-i], y + height - radius * sintab[i] ) );
02019 for( i = 0; i <= 8; i++ )
02020 points.push_back( new a2dLineSegment( x + width - radius * sintab[i], y + height - radius * sintab[8-i] ) );
02021 for( i = 0; i <= 8; i++ )
02022 points.push_back( new a2dLineSegment( x + width - radius * sintab[8-i], y + radius * sintab[i] ) );
02023 DrawPolygon( &points );
02024 }
02025 else
02026 {
02027 a2dVertexList points;
02028 points.push_back( new a2dLineSegment( x, y ) );
02029 points.push_back( new a2dLineSegment( x, y + height ) );
02030 points.push_back( new a2dLineSegment( x + width, y + height ) );
02031 points.push_back( new a2dLineSegment( x + width, y ) );
02032 DrawPolygon( &points );
02033 }
02034 }
02035
02036 void a2dDrawer2D::DrawCircle( double xc, double yc, double radius )
02037 {
02038 DrawEllipse( xc, yc, 2.0 * radius, 2.0 * radius );
02039 }
02040
02041 void a2dDrawer2D::DrawEllipse( double xc, double yc, double width, double height )
02042 {
02043 if ( m_disableDrawing )
02044 return;
02045
02046 double dphi;
02047 unsigned int segments;
02048
02049 if ( width == 0 && height == 0 )
02050 {
02051 DrawPoint( xc, yc );
02052 return;
02053 }
02054
02055
02056 double radiusDev = m_usertodevice.TransformDistance( wxMax( width, height ) );
02057 Aberration( m_displayaberration, wxPI*2, radiusDev , dphi, segments );
02058
02059
02060
02061
02062
02063
02064
02065 double m00 = m_usertodevice.GetValue( 0, 0 ) * width;
02066 double m01 = m_usertodevice.GetValue( 0, 1 ) * width;
02067 double m10 = m_usertodevice.GetValue( 1, 0 ) * height;
02068 double m11 = m_usertodevice.GetValue( 1, 1 ) * height;
02069 double n = fabs( m00 + m10 ) + fabs( m01 + m11 );
02070 if ( segments > n )
02071 {
02072 segments = ( int ) ceil( n );
02073 dphi = 2.0 * wxPI / segments;
02074 }
02075
02076 a2dVertexList points;
02077 double theta;
02078 unsigned int i;
02079 for ( i = 0; i < segments ; i++ )
02080 {
02081 theta = i * dphi;
02082 points.push_back( new a2dLineSegment( xc + width / 2 * cos ( theta ), yc - height / 2 * sin ( theta ) ) );
02083 }
02084 DrawPolygon( &points );
02085 }
02086
02087 void a2dDrawer2D::DrawLine( double x1, double y1, double x2, double y2 )
02088 {
02089 if ( m_disableDrawing )
02090 return;
02091
02092 a2dVertexList points;
02093 points.push_back( new a2dLineSegment( x1, y1 ) );
02094 points.push_back( new a2dLineSegment( x2, y2 ) );
02095 DrawLines( &points );
02096 }
02097
02098 void a2dDrawer2D::DrawCharUnknown( wxChar c )
02099 {
02100
02101 a2dStroke stroke = a2dStroke( m_activestroke.GetColour(), m_currentfont.GetSize() / 20.0 );
02102 a2dStroke oldstroke = m_activestroke;
02103 SetActiveStroke( stroke );
02104
02105 if ( c != wxChar( ' ' ) )
02106 {
02107 double desc = m_currentfont.GetDescent();
02108 double size = m_currentfont.GetSize();
02109 double width = m_currentfont.GetWidth( c );
02110 DrawLine( 0.1 * width, desc, 0.9 * width, desc + size );
02111 DrawLine( 0.9 * width, desc, 0.1 * width, desc + size );
02112 }
02113
02114
02115 SetActiveStroke( oldstroke );
02116 }
02117
02118 void a2dDrawer2D::DrawTextUnknown( const wxString& text, double x, double y, bool words )
02119 {
02120 if ( m_disableDrawing )
02121 return;
02122
02123 if ( words && m_currentfont.Ok() )
02124 {
02125
02126 a2dBoundingBox linebbox = m_currentfont.GetTextExtent( text, m_yaxis );
02127
02128 if ( !GetDrawerFill().IsNoFill() && !GetDrawerFill().GetStyle() == a2dFILL_TRANSPARENT )
02129 {
02130 a2dStroke oldstroke = GetDrawerStroke();
02131 SetDrawerStroke( *a2dTRANSPARENT_STROKE );
02132 DrawRoundedRectangle( x + linebbox.GetMinX(), y + linebbox.GetMinY(),
02133 linebbox.GetWidth(), linebbox.GetHeight(), 0 );
02134 SetDrawerStroke( oldstroke );
02135 }
02136
02137
02138 a2dStroke strokew = a2dStroke( m_activestroke.GetColour(), 1 );
02139 a2dStroke oldstroke = m_activestroke;
02140 SetActiveStroke( strokew );
02141
02142 double h = linebbox.GetHeight();
02143 double w;
02144 wxChar c;
02145 double start = x;
02146 for ( size_t i = 0; i < text.Length(); i++ )
02147 {
02148 c = text[i];
02149 w = m_currentfont.GetWidth( c );
02150 if ( c == wxChar( ' ' ) )
02151 {
02152 if ( x != start )
02153 DrawLine( start, y + h / 2, x, y + h / 2 );
02154 start = x + w;
02155 }
02156 x += w;
02157 }
02158 if ( x != start )
02159 DrawLine( start, y + h / 2, x, y + h / 2 );
02160
02161
02162 SetActiveStroke( oldstroke );
02163 }
02164 else
02165 {
02166 a2dBoundingBox linebbox = m_currentfont.GetTextExtent( text, m_yaxis );
02167
02168 DrawRoundedRectangle( x + linebbox.GetMinX(), y + linebbox.GetMinY(),
02169 linebbox.GetWidth(), linebbox.GetHeight(), 0 );
02170 DrawLine( x + linebbox.GetMinX(), y + linebbox.GetMinY(), x + linebbox.GetMaxX(), y + linebbox.GetMaxY() );
02171 DrawLine( x + linebbox.GetMinX(), y + linebbox.GetMaxY(), x + linebbox.GetMaxX(), y + linebbox.GetMinY() );
02172 }
02173 }
02174
02175
02176 void a2dDrawer2D::DrawCharStroke( wxChar c )
02177 {
02178
02179
02180 a2dStroke stroke = a2dStroke( m_activestroke.GetColour(), m_currentfont.GetStrokeWidth() );
02181
02182 a2dStroke oldstroke = m_activestroke;
02183 SetActiveStroke( stroke );
02184
02185
02186 a2dAffineMatrix affine;
02187 affine.Scale( m_currentfont.GetSize() );
02188 PushTransform( affine );
02189
02190 a2dVertexList** ptr = m_currentfont.GetGlyphStroke( c );
02191 if ( ptr )
02192 {
02193 while ( *ptr )
02194 {
02195 DrawLines( *ptr, false );
02196 ptr++;
02197 }
02198 }
02199
02200
02201 PopTransform();
02202 SetActiveStroke( oldstroke );
02203 }
02204
02205 void a2dDrawer2D::DrawTextGeneric( const wxString& text, double x, double y, void ( a2dDrawer2D::*drawchar )( wxChar ) )
02206 {
02207
02208 const double h = m_currentfont.GetLineHeight();
02209 a2dAffineMatrix affine;
02210 if ( !GetYaxis() )
02211 {
02212 affine.Translate( 0.0, -h );
02213 affine.Mirror( true, false );
02214 }
02215
02216 affine.Translate( x, y );
02217
02218
02219 PushTransform( affine );
02220
02221 bool textwasvisible = false;
02222
02223 double w = 0.0;
02224 wxChar c = 0;
02225 const size_t n = text.Length();
02226 for ( size_t i = 0; i < n; i++ )
02227 {
02228 const wxChar oldc = c;
02229 c = text[i];
02230 if ( i > 0 )
02231 {
02232 m_usertoworld *= a2dAffineMatrix( w + m_currentfont.GetKerning( oldc, c ), 0.0 );
02233 m_usertodevice = m_worldtodevice * m_usertoworld;
02234 }
02235 w = m_currentfont.GetWidth( c );
02236
02237
02238 a2dBoundingBox bbox( 0.0, 0.0, w, h );
02239 bbox.MapBbox( m_usertoworld );
02240
02241
02242 if ( m_clipboxworld.Intersect( bbox ) != _OUT )
02243 {
02244 ( this->*drawchar )( c );
02245 textwasvisible = true;
02246 }
02247 else if ( textwasvisible )
02248 {
02249
02250
02251 break;
02252 }
02253 }
02254
02255
02256 PopTransform();
02257 }
02258
02259 void a2dDrawer2D::DrawText( const wxString& text, double x, double y, int alignment, bool Background )
02260 {
02261 if ( m_disableDrawing )
02262 return;
02263
02264
02265 a2dBoundingBox bbox = m_currentfont.GetTextExtent( text, m_yaxis, alignment );
02266 bbox.Translate( x, y );
02267
02268
02269
02270 x = bbox.GetMinX();
02271 y = bbox.GetMinY();
02272
02273
02274 double dx, dy, size;
02275 dx = m_usertodevice.GetValue( 1, 0 );
02276 dy = m_usertodevice.GetValue( 1, 1 );
02277 size = m_currentfont.GetSize() * sqrt( dx * dx + dy * dy );
02278
02279
02280 a2dBoundingBox worldbbox( bbox );
02281 worldbbox.MapBbox( m_usertoworld );
02282
02283 if ( m_clipboxworld.Intersect( worldbbox ) != _OUT )
02284 {
02285
02286 if ( Background && !GetDrawerFill().IsNoFill() && !GetDrawerFill().GetStyle() == a2dFILL_TRANSPARENT )
02287 {
02288 a2dStroke oldstroke = m_activestroke;
02289 SetDrawerStroke( *a2dTRANSPARENT_STROKE );
02290 DrawRoundedRectangle( bbox.GetMinX(), bbox.GetMinY(),
02291 bbox.GetWidth(), bbox.GetHeight(), 0 );
02292 SetDrawerStroke( oldstroke );
02293 }
02294
02295
02296
02297
02298
02299
02300
02301
02302
02303
02304
02305
02306 if ( size > m_drawingthreshold )
02307 {
02308
02309 switch (m_currentfont.GetType())
02310 {
02311 case a2dFONT_STROKED:
02312 DrawTextStroke( text, x, y );
02313 break;
02314 case a2dFONT_FREETYPE:
02315 DrawTextFreetype( text, x, y );
02316 break;
02317 case a2dFONT_WXDC:
02318 DrawTextDc( text, x, y );
02319 break;
02320 default:
02321 DrawTextUnknown( text, x, y );
02322 }
02323 }
02324
02325 else
02326 DrawTextUnknown( text, x, y, true );
02327
02328
02329 }
02330 }
02331
02332
02333
02334
02335
02336 bool a2dDrawer2D::MoveUp( int n, wxRealPoint points[] , double horline, int& index, int direction )
02337 {
02338 int walk = ( index + direction + n ) % n;
02339 while ( points[walk].y < horline )
02340 {
02341 if ( points[walk].y < points[index].y )
02342 return false;
02343 else
02344 {
02345
02346 index = walk;
02347 walk = ( index + direction + n ) % n;
02348 }
02349 }
02350 return true;
02351 }
02352
02353
02354
02355 void a2dDrawer2D::DetectCriticalPoints( int n, wxRealPoint points[] )
02356 {
02357
02358
02359
02360 bool candidate = false;
02361 int i, j;
02362
02363 for ( i = 0; i < n; i++ )
02364 {
02365
02366 j = ( i + 1 ) % n;
02367
02368
02369 if ( points[i].y > points[j].y )
02370
02371 candidate = true;
02372 else if ( ( points[i].y < points[j].y ) && candidate )
02373 {
02374 bool inserted = false;
02375 a2dCriticalPointList::compatibility_iterator node = m_CRlist.GetFirst();
02376 while ( node )
02377 {
02378
02379 int * ind = node->GetData();
02380 if ( points[*ind].y > points[i].y )
02381 {
02382 m_CRlist.Insert( node, new int( i ) );
02383 inserted = true;
02384 break;
02385 }
02386 node = node->GetNext();
02387 }
02388 if ( !inserted )
02389 m_CRlist.Append( new int( i ) );
02390 candidate = false;
02391 }
02392 }
02393 if ( candidate )
02394 {
02395 for ( i = 0; i < n; i++ )
02396 {
02397
02398 j = ( i + 1 ) % n;
02399
02400
02401 if ( points[i].y > points[j].y )
02402
02403 candidate = true;
02404 else if ( ( points[i].y < points[j].y ) && candidate )
02405 {
02406 bool inserted = false;
02407 a2dCriticalPointList::compatibility_iterator node = m_CRlist.GetFirst();
02408 while ( node )
02409 {
02410
02411 int * ind = node->GetData();
02412 if ( points[*ind].y > points[i].y )
02413 {
02414 m_CRlist.Insert( node, new int( i ) );
02415 inserted = true;
02416 break;
02417 }
02418 node = node->GetNext();
02419 }
02420 if ( !inserted )
02421 m_CRlist.Append( new int( i ) );
02422 candidate = false;
02423 }
02424 }
02425 }
02426 }
02427
02428
02429 static int SortonXs( const a2dAET** first, const a2dAET** second )
02430 {
02431 if ( ( *first )->m_xs < ( *second )->m_xs )
02432 return -1;
02433 else if ( ( *first )->m_xs > ( *second )->m_xs )
02434 return 1;
02435
02436 return 0;
02437 }
02438
02439 void a2dDrawer2D::ColourXYLinear( int x1, int x2, int y )
02440 {
02441 int dred = m_colour2redFill - m_colour1redFill;
02442 int dgreen = m_colour2greenFill - m_colour1greenFill;
02443 int dblue = m_colour2blueFill - m_colour1blueFill;
02444
02445 if ( m_dx1 == m_dx2 )
02446 {
02447
02448
02449 double stepcol = m_max_y - m_min_y;
02450
02451 double curcol = y - m_min_y;
02452
02453 a2dStroke current = GetDrawerStroke();
02454 wxColour gradcol( ( unsigned char ) (m_colour1redFill + dred * curcol / stepcol),
02455 ( unsigned char ) (m_colour1greenFill + dgreen * curcol / stepcol),
02456 ( unsigned char ) (m_colour1blueFill + dblue * curcol / stepcol) );
02457 a2dStroke gradientstroke = a2dStroke( gradcol, 0 );
02458 SetDrawerStroke( gradientstroke );
02459 DeviceDrawHorizontalLine( x1, y, x2, true );
02460 SetDrawerStroke( current );
02461 }
02462 else
02463 {
02464 int j;
02465 for ( j = x1; j <= x2; j++ )
02466 {
02467 a2dLine perstroke( j, y, j + m_dy2 - m_dy1, y + m_dx2 - m_dx1 );
02468 a2dPoint2D crossing;
02469 perstroke.CalculateLineParameters();
02470 perstroke.Intersect( m_line, crossing );
02471
02472 double length = sqrt( ( double ) ( crossing.m_x - m_dx1 ) * ( crossing.m_x - m_dx1 ) + ( crossing.m_y - m_dy1 ) * ( crossing.m_y - m_dy1 ) );
02473
02474 if ( length > m_length )
02475 length = m_length;
02476
02477 DeviceDrawPixel( j, y, m_colour1redFill + dred * int( length / m_length ),
02478 m_colour1greenFill + dgreen * int( length / m_length ),
02479 m_colour1blueFill + dblue * int( length / m_length ) );
02480 }
02481 }
02482 }
02483
02484 void a2dDrawer2D::ColourXYRadial( int x1, int x2, int y )
02485 {
02486 int dred = m_colour2redFill - m_colour1redFill;
02487 int dgreen = m_colour2greenFill - m_colour1greenFill;
02488 int dblue = m_colour2blueFill - m_colour1blueFill;
02489
02490 int j;
02491 for ( j = x1; j <= x2; j++ )
02492 {
02493 double cradius = sqrt( ( double ) ( j - m_dx1 ) * ( j - m_dx1 ) + ( y - m_dy1 ) * ( y - m_dy1 ) );
02494
02495 double delta;
02496 if ( m_radiusd == 0 )
02497 delta = 0;
02498 else if ( cradius > m_radiusd )
02499 delta = 1;
02500 else
02501 delta = cradius / m_radiusd;
02502
02503 DeviceDrawPixel( j, y, ( unsigned char ) ( m_colour1redFill + dred * delta ),
02504 ( unsigned char ) ( m_colour1greenFill + dgreen * delta ),
02505 ( unsigned char ) ( m_colour1blueFill + dblue * delta ) );
02506 }
02507 }
02508
02509 void a2dDrawer2D::FillPolygon( int n, wxRealPoint points[] )
02510 {
02511 wxRect clip;
02512 GetClippingBoxDev( clip.x, clip.y, clip.width, clip.height );
02513
02514
02515 m_min_y = points[0].y;
02516 m_max_y = points[0].y;
02517 m_min_x = points[0].x;
02518 m_max_x = points[0].x;
02519 double centroidx = 0;
02520 double centroidy = 0;
02521 int i;
02522 for ( i = 0; i < n; i++ )
02523 {
02524 m_min_y = wxMin( m_min_y, points[i].y );
02525 m_max_y = wxMax( m_max_y, points[i].y );
02526 m_min_x = wxMin( m_min_x, points[i].x );
02527 m_max_x = wxMax( m_max_x, points[i].x );
02528 centroidx += points[i].x;
02529 centroidy += points[i].y;
02530 }
02531
02532 centroidx /= double( n );
02533 centroidy /= double( n );
02534
02535 int index;
02536
02537 if ( m_activefill.GetType() == a2dFILL_GRADIENT_FILL_LINEAR )
02538 {
02539 double x1 = m_activefill.GetStart().m_x;
02540 double y1 = m_activefill.GetStart().m_y;
02541 double x2 = m_activefill.GetStop().m_x;
02542 double y2 = m_activefill.GetStop().m_y;
02543 m_usertodevice.TransformPoint( x1, y1, m_dx1, m_dy1 );
02544 m_usertodevice.TransformPoint( x2, y2, m_dx2, m_dy2 );
02545 if ( m_dx1 == m_dx2 && m_dy1 == m_dy2 )
02546 {
02547 m_dx1 = centroidx;
02548 m_dy1 = m_min_y;
02549 m_dx2 = centroidx;
02550 m_dy2 = m_max_y;
02551 if ( m_dx1 == m_dx2 && m_dy1 == m_dy2 )
02552 m_dx2 = m_dx2 + 100;
02553 }
02554 m_length = sqrt ( ( m_dx1 - m_dx2 ) * ( m_dx1 - m_dx2 ) + ( m_dy1 - m_dy2 ) * ( m_dy1 - m_dy2 ) );
02555 m_line = a2dLine( m_dx1, m_dy1, m_dx2, m_dy2 );
02556 m_line.CalculateLineParameters();
02557 }
02558 else if ( m_activefill.GetType() == a2dFILL_GRADIENT_FILL_RADIAL )
02559 {
02560 double xfc = m_activefill.GetFocal().m_x;
02561 double yfc = m_activefill.GetFocal().m_y;
02562 double xe = m_activefill.GetCenter().m_x;
02563 double ye = m_activefill.GetCenter().m_y;
02564 m_usertodevice.TransformPoint( xfc, yfc, m_dx1, m_dy1 );
02565 m_usertodevice.TransformPoint( xe, ye, m_dx2, m_dy2 );
02566 if ( m_dx1 == m_dx2 && m_dy1 == m_dy2 )
02567 {
02568 m_dx1 = centroidx;
02569 m_dy1 = centroidy;
02570 m_dx2 = centroidx;
02571 m_dy2 = m_max_y;
02572
02573 if ( m_dx1 == m_dx2 && m_dy1 == m_dy2 )
02574 m_dx2 = m_dx2 + 10;
02575 }
02576 double dx3, dy3;
02577 m_usertodevice.TransformPoint( xe, ye + m_activefill.GetRadius(), dx3, dy3 );
02578 m_radiusd = sqrt ( ( dx3 - m_dx2 ) * ( dx3 - m_dx2 ) + ( dy3 - m_dy2 ) * ( dy3 - m_dy2 ) );
02579 }
02580
02581 DetectCriticalPoints( n, points );
02582
02583 int min = ( int ) wxMax ( m_min_y, clip.y );
02584 int max = ( int ) wxMin ( m_max_y, clip.y + clip.height );
02585
02586 for ( i = min; i < max; i++ )
02587 {
02588 a2dAETList::compatibility_iterator node = m_AETlist.GetFirst();
02589 int count = m_AETlist.size();
02590 while ( count > 0 )
02591 {
02592 a2dAET * ele = node->GetData();
02593 index = ele->m_index;
02594 int direction = ele->m_direction;
02595 if ( !MoveUp( n, points, i, index, direction ) )
02596 {
02597 a2dAETList::compatibility_iterator h = node;
02598
02599 node = node->GetNext();
02600 delete h->GetData();
02601 m_AETlist.DeleteNode( h );
02602 }
02603 else
02604 {
02605 if ( ele->m_index != index )
02606 {
02607 ele->m_index = index;
02608 int h = ( index + direction + n ) % n;
02609 ele->CalculateLineParameters( points[h], points[index] );
02610 }
02611 if ( ele->m_horizontal )
02612 ele->m_xs = ( int ) points[index].x;
02613 else
02614 ele->CalculateXs( i );
02615 node = node->GetNext();
02616 }
02617 count--;
02618 }
02619
02620 a2dCriticalPointList::compatibility_iterator nodec = m_CRlist.GetFirst();
02621 while ( m_CRlist.size() && points[*nodec->GetData()].y <= i )
02622 {
02623 int DI;
02624 for ( DI = -1; DI <= 1 ; DI += 2 )
02625 {
02626 index = *nodec->GetData();
02627 if ( MoveUp( n, points, i, index, DI ) )
02628 {
02629 a2dAET * ele = new a2dAET();
02630 ele->m_index = index;
02631 ele->m_direction = DI;
02632 int h = ( index + DI + n ) % n;
02633 ele->CalculateLineParameters( points[h], points[index] );
02634 if ( ele->m_horizontal )
02635 ele->m_xs = ( int ) points[index].x;
02636 else
02637 ele->CalculateXs( i );
02638
02639
02640 bool inserted = false;
02641 node = m_AETlist.GetFirst();
02642 while ( node )
02643 {
02644
02645 if ( ele->m_xs < ( node->GetData() )->m_xs )
02646 {
02647 m_AETlist.Insert( node, ele );
02648 inserted = true;
02649 break;
02650 }
02651
02652 node = node->GetNext();
02653 }
02654 if ( !inserted )
02655 m_AETlist.Append( ele );
02656 }
02657 }
02658
02659 a2dCriticalPointList::compatibility_iterator h = nodec;
02660 nodec = nodec->GetNext();
02661 delete h->GetData();
02662 m_CRlist.DeleteNode( h );
02663 }
02664
02665
02666
02667 if ( m_AETlist.GetCount() > 1 )
02668 {
02669 if ( m_AETlist.GetCount() > 2 )
02670 m_AETlist.Sort( SortonXs );
02671 else if ( m_AETlist.GetFirst()->GetData()->m_xs > m_AETlist.GetLast()->GetData()->m_xs )
02672 {
02673 a2dAET * f = m_AETlist.GetFirst()->GetData();
02674 m_AETlist.GetFirst()->SetData( m_AETlist.GetLast()->GetData() );
02675 m_AETlist.GetLast()->SetData( f );
02676 }
02677 }
02678
02679
02680
02681 int out = 0;
02682 node = m_AETlist.GetFirst();
02683 while ( node )
02684 {
02685 a2dAET * ele = node->GetData();
02686 out += ele->m_direction;
02687
02688 if ( out != 0 )
02689 {
02690 int x1 = ( int ) ele->m_xs;
02691 node = node->GetNext();
02692 if ( node )
02693 {
02694 ele = node->GetData();
02695 int x2 = ( int ) ele->m_xs;
02696
02697 if ( x1 < clip.x ) x1 = clip.x;
02698 if ( x2 > clip.x + clip.width ) x2 = clip.x + clip.width;
02699 if ( i >= clip.y && i <= clip.y + clip.height && ( x1 != x2 ) )
02700 {
02701 if ( m_activefill.GetType() == a2dFILL_GRADIENT_FILL_LINEAR )
02702 ColourXYLinear( x1, x2, i );
02703 else if ( m_activefill.GetType() == a2dFILL_GRADIENT_FILL_RADIAL )
02704 ColourXYRadial( x1, x2, i );
02705 else
02706 DeviceDrawHorizontalLine( x1, i, x2, false );
02707 }
02708 }
02709
02710 }
02711 else
02712 node = node->GetNext();
02713 }
02714 }
02715
02716 a2dAETList::compatibility_iterator node = m_AETlist.GetFirst();
02717 while ( node )
02718 {
02719 a2dAETList::compatibility_iterator h = node;
02720 delete h->GetData();
02721 m_AETlist.DeleteNode( h );
02722 node = m_AETlist.GetFirst();
02723 }
02724
02725 a2dCriticalPointList::compatibility_iterator nodec = m_CRlist.GetFirst();
02726 while ( nodec )
02727 {
02728 a2dCriticalPointList::compatibility_iterator h = nodec;
02729 delete h->GetData();
02730 m_CRlist.DeleteNode( h );
02731 nodec = m_CRlist.GetFirst();
02732 }
02733
02734 }
02735
02736
02737
02738
02739
02740
02741
02742
02743
02744 int a2dDrawer2D::GetClipCode( double x, double y )
02745 {
02746
02747
02748
02749
02750
02751
02752
02753
02754
02755
02756 int p = 0;
02757
02758 if ( x < m_clipboxworld.GetMinX() )
02759 p |= 0x0001;
02760 else if ( x > m_clipboxworld.GetMaxX() )
02761 p |= 0x0002;
02762 if ( y < m_clipboxworld.GetMinY() )
02763 p |= 0x0004;
02764 else if ( y > m_clipboxworld.GetMaxY() )
02765 p |= 0x0008;
02766
02767 return p;
02768 }
02769
02770
02771 bool a2dDrawer2D::Clipping( double &x1, double &y1, double &x2, double &y2 )
02772 {
02773 int clipcode1, clipcode2;
02774 int nr_of_intersections = 0;
02775
02776
02777 double intersectionpoint1[2];
02778 double intersectionpoint2[2];
02779 double A, B, temppoint;
02780 double RC = 0;
02781 double T = 0;
02782
02783
02784 clipcode1 = GetClipCode( x1, y1 );
02785 clipcode2 = GetClipCode( x2, y2 );
02786
02787
02788 if ( !clipcode1 && !clipcode2 ) return true;
02789
02790
02791
02792 if ( !clipcode1 )
02793 {
02794 intersectionpoint1[0] = x1;
02795 intersectionpoint2[0] = y1;
02796
02797 nr_of_intersections = 1;
02798 }
02799
02800
02801 if ( !clipcode2 )
02802 {
02803 intersectionpoint1[0] = x2;
02804 intersectionpoint2[0] = y2;
02805
02806 nr_of_intersections = 1;
02807 }
02808
02809 clipcode1 ^= clipcode2;
02810
02811
02812
02813
02814 A = y2 - y1;
02815 B = x2 - x1;
02816
02817 if ( B )
02818 {
02819 RC = A / B;
02820 T = y1 - x1 * RC;
02821 }
02822
02823 if ( clipcode1 & 0x0004 )
02824 {
02825
02826 if ( B ) temppoint = ( m_clipboxworld.GetMinY() - T ) / RC;
02827 else temppoint = x1;
02828
02829
02830 if ( temppoint >= m_clipboxworld.GetMinX() && temppoint <= m_clipboxworld.GetMaxX() )
02831 {
02832 intersectionpoint1[nr_of_intersections] = temppoint;
02833 intersectionpoint2[nr_of_intersections++] = m_clipboxworld.GetMinY();
02834 }
02835 }
02836
02837 if ( clipcode1 & 0x0008 )
02838 {
02839
02840 if ( B ) temppoint = ( m_clipboxworld.GetMaxY() - T ) / RC;
02841 else temppoint = x1;
02842
02843 if ( temppoint >= m_clipboxworld.GetMinX() && temppoint <= m_clipboxworld.GetMaxX() )
02844 {
02845 intersectionpoint1[nr_of_intersections] = temppoint;
02846 intersectionpoint2[nr_of_intersections++] = m_clipboxworld.GetMaxY();
02847 }
02848 }
02849
02850 if ( clipcode1 & 0x0001 )
02851 {
02852
02853 temppoint = RC * m_clipboxworld.GetMinX() + T;
02854 if ( temppoint > m_clipboxworld.GetMinY() && temppoint < m_clipboxworld.GetMaxY() )
02855 {
02856 intersectionpoint2[nr_of_intersections] = temppoint;
02857 intersectionpoint1[nr_of_intersections++] = m_clipboxworld.GetMinX();
02858 }
02859 }
02860
02861 if ( clipcode1 & 0x0002 )
02862 {
02863
02864 temppoint = RC * m_clipboxworld.GetMaxX() + T;
02865 if ( temppoint > m_clipboxworld.GetMinY() && temppoint < m_clipboxworld.GetMaxY() )
02866 {
02867 intersectionpoint2[nr_of_intersections] = temppoint;
02868 intersectionpoint1[nr_of_intersections++] = m_clipboxworld.GetMaxX();
02869 }
02870 }
02871
02872 if ( nr_of_intersections != 2 ) return false;
02873
02874
02875 x1 = intersectionpoint1[0];
02876 y1 = intersectionpoint2[0];
02877 x2 = intersectionpoint1[1];
02878 y2 = intersectionpoint2[1];
02879
02880 return true;
02881 }
02882
02883 void a2dDrawer2D::GetClippingBoxDev( int& x, int& y, int& w, int& h ) const
02884 {
02885 x = m_clipboxdev.x;
02886 y = m_clipboxdev.y;
02887 w = m_clipboxdev.width;
02888 h = m_clipboxdev.height;
02889 }
02890
02891 void a2dDrawer2D::GetClippingMinMax( double& xmin, double& ymin, double& xmax, double& ymax ) const
02892 {
02893 xmin = m_clipboxworld.GetMinX();
02894 ymin = m_clipboxworld.GetMinY();
02895 xmax = m_clipboxworld.GetMaxX();
02896 ymax = m_clipboxworld.GetMaxY();
02897 }
02898
02899 void a2dDrawer2D::GetClippingBox( double& x, double& y, double& w, double& h ) const
02900 {
02901 x = m_clipboxworld.GetMinX();
02902 y = m_clipboxworld.GetMinY();
02903 w = m_clipboxworld.GetWidth();
02904 h = m_clipboxworld.GetHeight();
02905 }
02906
02907 unsigned int a2dDrawer2D::ConvertSplinedPolygon2( unsigned int n )
02908 {
02909 a2dVertexList h;
02910 unsigned int i;
02911 for ( i = 0; i < n; i++ )
02912 {
02913 h.push_back( new a2dLineSegment( m_cpointsDouble[i].x, m_cpointsDouble[i].y ) );
02914 }
02915
02916 double deviceaber = WorldToDeviceXRel( m_splineaberration );
02917 if ( deviceaber < 5 )
02918 deviceaber = THRESHOLD;
02919
02920
02921 h.ConvertIntoSplinedPolygon( deviceaber );
02922
02923 n = h.size();
02924
02925 m_cpointsDouble.resize( n );
02926
02927 a2dVertexList::iterator iter = h.begin();
02928 for ( i = 0; i < n; i++ )
02929 {
02930 m_cpointsDouble[i].x = ( *iter )->m_x;
02931 m_cpointsDouble[i].y = ( *iter )->m_y;
02932 iter++;
02933 }
02934 h.clear();
02935
02936 return n;
02937 }
02938
02939 unsigned int a2dDrawer2D::ConvertSplinedPolyline2( unsigned int n )
02940 {
02941 a2dVertexList h;
02942 unsigned int i;
02943 for ( i = 0; i < n; i++ )
02944 {
02945 h.push_back( new a2dLineSegment( m_cpointsDouble[i].x, m_cpointsDouble[i].y ) );
02946 }
02947
02948 double deviceaber = WorldToDeviceXRel( m_splineaberration );
02949 if ( deviceaber < 5 )
02950 deviceaber = THRESHOLD;
02951
02952
02953 h.ConvertIntoSplinedPolyline( deviceaber );
02954
02955 n = h.size();
02956 m_cpointsDouble.resize( n );
02957
02958 a2dVertexList::iterator iter = h.begin();
02959 for ( i = 0; i < n; i++ )
02960 {
02961 m_cpointsDouble[i].x = ( *iter )->m_x;
02962 m_cpointsDouble[i].y = ( *iter )->m_y;
02963 iter = h.erase( iter );
02964 }
02965 return n;
02966 }
02967
02968 void a2dDrawer2D::DeviceDrawPolygon( unsigned int n, bool spline , wxPolygonFillMode fillStyle )
02969 {
02970 wxFAIL_MSG( wxT( "if used, must be implemented in derived class" ) );
02971 }
02972
02973 void a2dDrawer2D::DeviceDrawLines( unsigned int n, bool spline )
02974 {
02975 wxFAIL_MSG( wxT( "if used, must be implemented in derived class" ) );
02976 }
02977
02978 void a2dDrawer2D::DeviceDrawLine( double x1, double y1, double x2, double y2 )
02979 {
02980 wxFAIL_MSG( wxT( "if used, must be implemented in derived class" ) );
02981 }
02982
02983 void a2dDrawer2D::DeviceDrawHorizontalLine( int x1, int y1, int x2, bool WXUNUSED( use_pen ) )
02984 {
02985 wxFAIL_MSG( wxT( "if used, must be implemented in derived class" ) );
02986 }
02987
02988 void a2dDrawer2D::DeviceDrawVerticalLine( int x1, int y1, int y2, bool WXUNUSED( use_pen ) )
02989 {
02990 wxFAIL_MSG( wxT( "if used, must be implemented in derived class" ) );
02991 }
02992
02993 void a2dDrawer2D::DeviceDrawPixel( int x1, int y1, unsigned char r, unsigned char g, unsigned char b, unsigned char a )
02994 {
02995 wxFAIL_MSG( wxT( "if used, must be implemented in derived class" ) );
02996 }
02997
02998 IMPLEMENT_CLASS( a2dDrawer2D, wxObject )
02999 IMPLEMENT_DYNAMIC_CLASS( a2dBlindDrawer2D, a2dDrawer2D )
03000
03001
03002
03003
03004
03005 a2dBlindDrawer2D::a2dBlindDrawer2D( const wxSize& size ): a2dDrawer2D( size )
03006 {}
03007
03008 a2dBlindDrawer2D::a2dBlindDrawer2D( int w, int h ): a2dDrawer2D( w, h )
03009 {}
03010
03011 a2dBlindDrawer2D::~a2dBlindDrawer2D()
03012 {}
03013
03014 a2dBlindDrawer2D::a2dBlindDrawer2D( const a2dBlindDrawer2D& other )
03015 : a2dDrawer2D( other )
03016 {}
03017
03018 a2dBlindDrawer2D::a2dBlindDrawer2D( const a2dDrawer2D& other )
03019 : a2dDrawer2D( other )
03020 {}
03021
03022 void a2dBlindDrawer2D::BeginDraw()
03023 {
03024 wxASSERT_MSG( m_beginDraw_endDraw >= 0, wxT( "a2dBlindDrawer2D, unbalanced BeginDraw EndDraw" ) );
03025 m_beginDraw_endDraw++;
03026 }
03027
03028 void a2dBlindDrawer2D::EndDraw()
03029 {
03030 m_beginDraw_endDraw--;
03031 wxASSERT_MSG( m_beginDraw_endDraw >= 0, wxT( "a2dBlindDrawer2D, unbalanced BeginDraw EndDraw" ) );
03032 }
03033
03034 void a2dBlindDrawer2D::SetBufferSize( int w, int h )
03035 {
03036 m_width = w;
03037 m_height = h;
03038 }
03039
03040 wxBitmap a2dBlindDrawer2D::GetSubBitmap( wxRect WXUNUSED( rect ) ) const
03041 {
03042 wxFAIL_MSG( wxT( "a2dBlindDrawer2D has no buffer" ) );
03043 return wxBitmap( m_width, m_height );
03044 }
03045
03046 void a2dBlindDrawer2D::SetClippingRegion( a2dVertexList* WXUNUSED( points ), bool WXUNUSED( spline ), wxPolygonFillMode WXUNUSED( fillStyle ) )
03047 {}
03048
03049 void a2dBlindDrawer2D::ExtendAndPushClippingRegion( a2dVertexList* WXUNUSED( points ), bool WXUNUSED( spline ), wxPolygonFillMode WXUNUSED( fillStyle ), a2dBooleanClip WXUNUSED( clipoperation ) )
03050 {}
03051
03052 void a2dBlindDrawer2D::ExtendClippingRegion( a2dVertexList* WXUNUSED( points ), bool WXUNUSED( spline ), wxPolygonFillMode WXUNUSED( fillStyle ), a2dBooleanClip WXUNUSED( clipoperation ) )
03053 {}
03054
03055 void a2dBlindDrawer2D::PopClippingRegion()
03056 {}
03057
03058 void a2dBlindDrawer2D::SetClippingRegionDev( wxCoord WXUNUSED( minx ), wxCoord WXUNUSED( miny ), wxCoord WXUNUSED( width ), wxCoord WXUNUSED( height ) )
03059 {}
03060
03061 void a2dBlindDrawer2D::SetClippingRegion( double WXUNUSED( minx ), double WXUNUSED( miny ), double WXUNUSED( maxx ), double WXUNUSED( maxy ) )
03062 {}
03063
03064 void a2dBlindDrawer2D::DestroyClippingRegion()
03065 {}
03066
03067 void a2dBlindDrawer2D::ResetStyle()
03068 {
03069 a2dDrawer2D::ResetStyle();
03070 }
03071
03072 void a2dBlindDrawer2D::DoSetActiveStroke()
03073 {}
03074
03075 void a2dBlindDrawer2D::DoSetActiveFill()
03076 {}
03077
03078 void a2dBlindDrawer2D::DoSetDrawStyle( a2dDrawStyle WXUNUSED( drawstyle ) )
03079 {}
03080
03081 void a2dBlindDrawer2D::DrawImage( const wxImage& WXUNUSED( imagein ), double WXUNUSED( x ), double WXUNUSED( y ), double WXUNUSED( width ), double WXUNUSED( height ), wxUint8 WXUNUSED( Opacity ) )
03082 {}
03083
03084 void a2dBlindDrawer2D::DrawImage( const a2dImageRGBA& image, double x, double y, double width, double height, wxUint8 Opacity )
03085 {}
03086
03087 void a2dBlindDrawer2D::DrawVpath( const a2dVpath* WXUNUSED( path ) )
03088 {}
03089
03090 void a2dBlindDrawer2D::DrawPoint( double xc, double yc )
03091 {}
03092
03093 void a2dBlindDrawer2D::DrawPolygon( a2dVertexArray* points, bool spline, wxPolygonFillMode fillStyle )
03094 {
03095 }
03096
03097 void a2dBlindDrawer2D::DrawPolygon( const a2dVertexList *list, bool spline, wxPolygonFillMode fillStyle )
03098 {
03099 }
03100
03101 void a2dBlindDrawer2D::DrawLines( a2dVertexArray* points, bool spline )
03102 {
03103 }
03104
03105 void a2dBlindDrawer2D::DrawLines( const a2dVertexList* list, bool spline )
03106 {
03107 }
03108
03109 void a2dBlindDrawer2D::DrawArc( double x1, double y1, double x2, double y2, double xc, double yc, bool chord )
03110 {
03111 }
03112
03113 void a2dBlindDrawer2D::DrawEllipticArc( double xc, double yc, double width, double height, double sa, double ea, bool chord )
03114 {
03115 }
03116
03117 void a2dBlindDrawer2D::DrawCenterRoundedRectangle( double xc, double yc, double width, double height, double radius, bool pixelsize )
03118 {
03119 }
03120
03121 void a2dBlindDrawer2D::DrawRoundedRectangle( double x, double y, double width, double height, double radius, bool pixelsize )
03122 {
03123 }
03124
03125 void a2dBlindDrawer2D::DrawCircle( double xc, double yc, double radius )
03126 {
03127 }
03128
03129 void a2dBlindDrawer2D::DrawEllipse( double xc, double yc, double width, double height )
03130 {
03131 }
03132
03133 void a2dBlindDrawer2D::DrawLine( double x1, double y1, double x2, double y2 )
03134 {
03135 }
03136
03137 void a2dBlindDrawer2D::DeviceDrawAnnotation( const wxString& WXUNUSED( text ), wxCoord WXUNUSED( x ), wxCoord WXUNUSED( y ), const wxFont& WXUNUSED( font ) )
03138 {}
03139
03140 void a2dBlindDrawer2D::BlitBuffer( wxRect WXUNUSED( rect ), const wxPoint& WXUNUSED( bufferpos ) )
03141 {
03142 wxFAIL_MSG( wxT( "not useful here" ) );
03143 }
03144
03145 void a2dBlindDrawer2D::BlitBuffer( wxDC* WXUNUSED( dc ), wxRect WXUNUSED( rect ), const wxPoint& WXUNUSED( bufferpos ) )
03146 {
03147 wxFAIL_MSG( wxT( "not useful here" ) );
03148 }
03149
03150
03151
03152
03153 #if wxART2D_USE_GRAPHICS_CONTEXT
03154
03155 IMPLEMENT_CLASS( a2dGcBaseDrawer, a2dDrawer2D )
03156
03157
03158
03159
03160
03161 a2dGcBaseDrawer::a2dGcBaseDrawer( int width, int height, wxGraphicsRenderer* render, wxGraphicsContext* context ): a2dDrawer2D( width, height )
03162 {
03163 m_render = render;
03164 m_context = context;
03165 }
03166
03167 a2dGcBaseDrawer::a2dGcBaseDrawer( const a2dGcBaseDrawer& other )
03168 : a2dDrawer2D( other )
03169 {
03170 m_render = other.m_render;
03171 m_context = other.m_context;
03172 }
03173
03174 a2dGcBaseDrawer::a2dGcBaseDrawer( const a2dDrawer2D& other )
03175 : a2dDrawer2D( other )
03176 {
03177 m_render = NULL;
03178 m_context = NULL;
03179 }
03180
03181 a2dGcBaseDrawer::~a2dGcBaseDrawer()
03182 {
03183 }
03184
03185 void a2dGcBaseDrawer::SetTransform( const a2dAffineMatrix& userToWorld )
03186 {
03187 a2dDrawer2D::SetTransform( userToWorld );
03188
03189 wxGraphicsMatrix m = m_context->CreateMatrix(
03190 m_usertodevice( 0, 0), m_usertodevice( 0, 1),
03191 m_usertodevice( 1, 0), m_usertodevice( 1, 1),
03192 m_usertodevice( 2, 0), m_usertodevice( 2, 1) );
03193 m_context->SetTransform( m );
03194 }
03195
03196 void a2dGcBaseDrawer::PushTransform()
03197 {
03198 a2dDrawer2D::PushTransform();
03199
03200 wxGraphicsMatrix m = m_context->CreateMatrix();
03201 m.Set(
03202 m_usertodevice( 0, 0), m_usertodevice( 0, 1),
03203 m_usertodevice( 1, 0), m_usertodevice( 1, 1),
03204 m_usertodevice( 2, 0), m_usertodevice( 2, 1) );
03205 m_context->SetTransform( m );
03206 }
03207
03208 void a2dGcBaseDrawer::PushTransform( const a2dAffineMatrix& affine )
03209 {
03210 a2dDrawer2D::PushTransform( affine );
03211
03212 wxGraphicsMatrix m = m_context->CreateMatrix();
03213 m.Set(
03214 m_usertodevice( 0, 0), m_usertodevice( 0, 1),
03215 m_usertodevice( 1, 0), m_usertodevice( 1, 1),
03216 m_usertodevice( 2, 0), m_usertodevice( 2, 1) );
03217 m_context->SetTransform( m );
03218 }
03219
03220 void a2dGcBaseDrawer::PushIdentityTransform()
03221 {
03222 a2dDrawer2D::PushIdentityTransform( );
03223
03224 wxGraphicsMatrix m = m_context->CreateMatrix();
03225 m.Set(
03226 m_usertodevice( 0, 0), m_usertodevice( 0, 1),
03227 m_usertodevice( 1, 0), m_usertodevice( 1, 1),
03228 m_usertodevice( 2, 0), m_usertodevice( 2, 1) );
03229 m_context->SetTransform( m );
03230 }
03231
03232 void a2dGcBaseDrawer::PopTransform( void )
03233 {
03234 a2dDrawer2D::PopTransform();
03235
03236 wxGraphicsMatrix m = m_context->CreateMatrix();
03237 m.Set(
03238 m_usertodevice( 0, 0), m_usertodevice( 0, 1),
03239 m_usertodevice( 1, 0), m_usertodevice( 1, 1),
03240 m_usertodevice( 2, 0), m_usertodevice( 2, 1) );
03241 m_context->SetTransform( m );
03242 }
03243
03244 void a2dGcBaseDrawer::BeginDraw()
03245 {
03246 wxASSERT_MSG( m_beginDraw_endDraw >= 0, wxT( "a2dMemDcDrawer, unbalanced BeginDraw EndDraw" ) );
03247
03248 if ( m_beginDraw_endDraw == 0 )
03249 {
03250 SetDrawerFill( m_currentfill );
03251 SetDrawerStroke( m_currentstroke );
03252 DestroyClippingRegion();
03253 SetDrawStyle( m_drawstyle );
03254
03255 }
03256
03257 m_beginDraw_endDraw++;
03258 }
03259
03260 void a2dGcBaseDrawer::EndDraw()
03261 {
03262 m_beginDraw_endDraw--;
03263
03264 wxASSERT_MSG( m_beginDraw_endDraw >= 0, wxT( "a2dMemDcDrawer, unbalanced BeginDraw EndDraw" ) );
03265
03266 if ( m_beginDraw_endDraw == 0 )
03267 {
03268 }
03269 }
03270
03271 void a2dGcBaseDrawer::BlitBuffer( wxRect rect, const wxPoint& bufferpos )
03272 {
03273 BeginDraw();
03274 if ( m_display )
03275 {
03276 wxClientDC deviceDC( m_display );
03277 m_display->PrepareDC( deviceDC );
03278 BlitBuffer( &deviceDC, rect, bufferpos );
03279 }
03280 EndDraw();
03281 }
03282
03283 void a2dGcBaseDrawer::SetClippingRegion( a2dVertexList* points, bool spline, wxPolygonFillMode fillStyle )
03284 {
03285 unsigned int n = points->size();
03286
03287 m_cpointsDouble.resize( n );
03288
03289 unsigned int i = 0;
03290 double x, y;
03291 forEachIn( a2dVertexList, points )
03292 {
03293 a2dPoint2D point = ( *iter )->GetPoint();
03294
03295 GetUserToDeviceTransform().TransformPoint( point.m_x, point.m_y, x, y );
03296 m_cpointsDouble[i].x = x;
03297 m_cpointsDouble[i].y = y;
03298 i++;
03299 }
03300
03301 if ( spline )
03302 n = ConvertSplinedPolygon2( n );
03303
03304 wxPoint *intpoints = _convertToIntPointCache( n, &m_cpointsDouble[0] );
03305 m_clip = wxRegion( n, intpoints, fillStyle );
03306
03307 m_clipboxdev = m_clip.GetBox();
03308 m_clipboxworld = ToWorld( m_clipboxdev );
03309 }
03310
03311 void a2dGcBaseDrawer::ExtendAndPushClippingRegion( a2dVertexList* points, bool spline, wxPolygonFillMode fillStyle, a2dBooleanClip clipoperation )
03312 {
03313 wxRegion* push = new wxRegion( m_clip );
03314
03315 m_clipregionlist.Insert( push );
03316
03317 ExtendClippingRegion( points, spline, fillStyle, clipoperation );
03318 }
03319
03320 void a2dGcBaseDrawer::ExtendClippingRegion( a2dVertexList* points, bool spline, wxPolygonFillMode WXUNUSED( fillStyle ), a2dBooleanClip clipoperation )
03321 {
03322 wxRegion totaladd;
03323 bool first = false;
03324
03325 a2dBoundingBox devbox;
03326 bool smallPoly = false;
03327 unsigned int segments = ToDeviceLines( points, devbox, smallPoly );
03328
03329 if ( segments == 0 )
03330 return;
03331
03332 if ( spline )
03333 segments = ConvertSplinedPolygon2( segments );
03334
03335 wxPoint *int_cpts = _convertToIntPointCache( segments, &m_cpointsDouble[0] );
03336 wxRegion add = wxRegion( segments, int_cpts, wxWINDING_RULE );
03337 if ( !first )
03338 {
03339 totaladd = add;
03340 first = true;
03341 }
03342 else
03343 totaladd.Union( add );
03344
03345 if ( !m_clip.Empty() )
03346 {
03347 bool result;
03348 switch ( clipoperation )
03349 {
03350 case a2dCLIP_AND:
03351 result = m_clip.Intersect( totaladd );
03352 break ;
03353
03354 case a2dCLIP_OR:
03355 result = m_clip.Union( totaladd );
03356 break ;
03357
03358 case a2dCLIP_XOR:
03359 result = m_clip.Xor( totaladd );
03360 break ;
03361
03362 case a2dCLIP_DIFF:
03363 result = m_clip.Subtract( totaladd );
03364 break ;
03365
03366 case a2dCLIP_COPY:
03367 default:
03368 m_clip = totaladd;
03369 result = true;
03370 break ;
03371 }
03372 if ( result )
03373 {
03374 m_context->ResetClip();
03375 }
03376 }
03377 else
03378 {
03379 m_clip = totaladd;
03380 m_context->ResetClip();
03381 }
03382
03383 m_clipboxdev = m_clip.GetBox();
03384 m_clipboxworld = ToWorld( m_clipboxdev );
03385 m_context->Clip( m_clipboxworld.GetMinX(), m_clipboxworld.GetMinY(),
03386 m_clipboxworld.GetWidth(), m_clipboxworld.GetHeight() );
03387 }
03388
03389 void a2dGcBaseDrawer::PopClippingRegion()
03390 {
03391 if ( !m_clipregionlist.GetCount() )
03392 return;
03393
03394 m_clip = *m_clipregionlist.GetFirst()->GetData();
03395 delete m_clipregionlist.GetFirst()->GetData();
03396 m_clipregionlist.DeleteNode( m_clipregionlist.GetFirst() );
03397
03398 m_clipboxdev = m_clip.GetBox();
03399 m_clipboxworld = ToWorld( m_clipboxdev );
03400 m_context->Clip( m_clipboxworld.GetMinX(), m_clipboxworld.GetMinY(),
03401 m_clipboxworld.GetWidth(), m_clipboxworld.GetHeight() );
03402 }
03403
03404 void a2dGcBaseDrawer::SetClippingRegionDev( wxCoord minx, wxCoord miny, wxCoord width, wxCoord height )
03405 {
03406 m_clip = wxRegion( minx, miny, width, height );
03407 m_clipboxdev = wxRect( minx, miny, width, height );
03408 m_clipboxworld = ToWorld( m_clipboxdev );
03409
03410
03411
03412 PushIdentityTransform();
03413 m_context->ResetClip();
03414 m_context->Clip( m_clipboxdev.x, m_clipboxdev.y,
03415 m_clipboxdev.GetWidth(), m_clipboxdev.GetHeight() );
03416
03417 PopTransform();
03418 }
03419
03420 void a2dGcBaseDrawer::SetClippingRegion( double minx, double miny, double maxx, double maxy )
03421 {
03422 int iminx = WorldToDeviceX( minx );
03423 int iminy = WorldToDeviceY( miny );
03424 int imaxx = WorldToDeviceX( maxx );
03425 int imaxy = WorldToDeviceY( maxy );
03426 if ( m_yaxis )
03427 {
03428 m_clip = wxRegion( iminx, imaxy, imaxx - iminx, iminy - imaxy );
03429 m_clipboxdev = wxRect( iminx, imaxy, imaxx - iminx, iminy - imaxy );
03430 }
03431 else
03432 {
03433 m_clip = wxRegion( iminx, iminy, imaxx - iminx, imaxy - iminy );
03434 m_clipboxdev = wxRect( iminx, iminy, imaxx - iminx, imaxy - iminy );
03435 }
03436
03437 m_context->ResetClip();
03438
03439
03440 PushIdentityTransform();
03441 m_context->Clip( m_clipboxdev.x, m_clipboxdev.y,
03442 m_clipboxdev.GetWidth(), m_clipboxdev.GetHeight() );
03443
03444 PopTransform();
03445 }
03446
03447 void a2dGcBaseDrawer::DestroyClippingRegion()
03448 {
03449 m_clip.Clear();
03450 m_clipboxdev = wxRect( 0, 0, m_width, m_height );
03451 m_clipboxworld = ToWorld( m_clipboxdev );
03452
03453 m_context->ResetClip();
03454 }
03455
03456 void a2dGcBaseDrawer::ResetStyle()
03457 {
03458 a2dDrawer2D::ResetStyle();
03459 SetDrawerFill( *a2dBLACK_FILL );
03460 SetDrawerStroke( *a2dBLACK_STROKE );
03461 SetDrawStyle( m_drawstyle );
03462 }
03463
03464 void a2dGcBaseDrawer::DoSetActiveFont( const a2dFont& font )
03465 {
03466
03467 unsigned int fontsize;
03468 fontsize = m_currentfont.GetSize();
03469 if ( fontsize < 1 )
03470 fontsize = 1;
03471 switch ( m_currentfont.GetType() )
03472 {
03473 case a2dFONT_WXDC:
03474 {
03475 m_currentfont.GetFont().SetPointSize( fontsize );
03476 wxGraphicsFont f = m_render->CreateFont( m_currentfont.GetFont() );
03477 m_context->SetFont( f );
03478 break;
03479 }
03480 default:
03481 wxFont wxfont = *wxNORMAL_FONT;
03482 wxfont.SetPointSize( fontsize );
03483 wxGraphicsFont f = m_render->CreateFont( wxfont );
03484 m_context->SetFont( f );
03485 }
03486 }
03487
03488 void a2dGcBaseDrawer::DoSetActiveStroke()
03489 {
03490 wxGraphicsPen graphpen = ConvertActiveToGraphicsPen( m_context );
03491 m_context->SetPen( graphpen );
03492
03493
03494 }
03495
03496 void a2dGcBaseDrawer::DoSetActiveFill()
03497 {
03498 wxGraphicsBrush graphbrush = ConvertActiveToGraphicsBrush( m_context );
03499 m_context->SetBrush( graphbrush );
03500
03501
03502 }
03503
03504 void a2dGcBaseDrawer::DoSetDrawStyle( a2dDrawStyle drawstyle )
03505 {
03506 if ( m_drawstyle == a2dFIX_STYLE && m_drawstyle == a2dFIX_STYLE_INVERT )
03507 return;
03508
03509 m_drawstyle = drawstyle;
03510
03511 switch( drawstyle )
03512 {
03513 case a2dWIREFRAME_INVERT:
03514 SetActiveStroke( *a2dBLACK_STROKE );
03515 SetActiveFill( *a2dTRANSPARENT_FILL );
03516 #if wxCHECK_VERSION(2,9,0)
03517 #else
03518 m_context->SetLogicalFunction( wxINVERT );
03519 #endif
03520 break;
03521
03522 case a2dWIREFRAME:
03523 SetActiveStroke( *a2dBLACK_STROKE );
03524 SetActiveFill( *a2dTRANSPARENT_FILL );
03525 #if wxCHECK_VERSION(2,9,0)
03526 #if wxCHECK_VERSION(2,9,0)
03527 #else
03528 m_context->SetLogicalFunction( wxCOPY );
03529 #endif
03530 #else
03531 #endif
03532 break;
03533
03534 case a2dWIREFRAME_ZERO_WIDTH:
03535 SetActiveStroke( *a2dBLACK_STROKE );
03536 SetActiveFill( *a2dTRANSPARENT_FILL );
03537 #if wxCHECK_VERSION(2,9,0)
03538 #else
03539 m_context->SetLogicalFunction( wxCOPY );
03540 #endif
03541 break;
03542
03543 case a2dWIREFRAME_INVERT_ZERO_WIDTH:
03544 SetActiveStroke( *a2dBLACK_STROKE );
03545 SetActiveFill( *a2dTRANSPARENT_FILL );
03546 #if wxCHECK_VERSION(2,9,0)
03547 #else
03548 m_context->SetLogicalFunction( wxINVERT );
03549 #endif
03550 break;
03551
03552 case a2dFILLED:
03553 SetActiveStroke( m_currentstroke );
03554 SetActiveFill( m_currentfill );
03555 #if wxCHECK_VERSION(2,9,0)
03556 #else
03557 m_context->SetLogicalFunction( wxCOPY );
03558 #endif
03559 break;
03560
03561 case a2dFIX_STYLE:
03562
03563 m_fixStrokeRestore = m_currentstroke;
03564 m_fixFillRestore = m_currentfill;
03565 m_fixDrawstyle = m_drawstyle;
03566 SetActiveStroke( m_currentstroke );
03567 SetActiveFill( m_currentfill );
03568
03569
03570 #if wxCHECK_VERSION(2,9,0)
03571 #else
03572 m_context->SetLogicalFunction( wxCOPY );
03573 #endif
03574 break;
03575
03576 case a2dFIX_STYLE_INVERT:
03577
03578 #if wxCHECK_VERSION(2,9,0)
03579 #else
03580 m_context->SetLogicalFunction( wxINVERT );
03581 #endif
03582 break;
03583
03584 default:
03585 wxASSERT( 0 );
03586 }
03587
03588
03589
03590 }
03591
03592
03593 void a2dGcBaseDrawer::DrawImage( const wxImage& imagein, double x, double y, double width, double height, wxUint8 Opacity )
03594 {
03595 if ( m_disableDrawing )
03596 return;
03597
03598 a2dAffineMatrix affine;
03599 if ( GetYaxis() )
03600 {
03601 affine.Translate( 0.0, -(y) );
03602 affine.Mirror( true, false );
03603 affine.Translate( 0.0, y );
03604 }
03605 PushTransform( affine );
03606
03607 wxGraphicsBitmap bitmap = m_render->CreateBitmap( imagein );
03608 #if wxCHECK_VERSION(2,9,0)
03609 m_context->DrawBitmap( bitmap, x - width/2.0, y - height/2.0, width, height );
03610 #else
03611 m_context->DrawGraphicsBitmap( bitmap, x - width/2.0, y - height/2.0, width, height );
03612 #endif
03613
03614 PopTransform();
03615 }
03616
03617 void a2dGcBaseDrawer::DrawImage( const a2dImageRGBA& image, double x, double y, double width, double height, wxUint8 Opacity )
03618 {
03619 if ( m_disableDrawing )
03620 return;
03621
03622 wxImage wximage = image.GetImage();
03623 wxGraphicsBitmap bitmap = m_render->CreateBitmap( wximage );
03624 #if wxCHECK_VERSION(2,9,0)
03625 m_context->DrawBitmap( bitmap, x - width/2.0, y - height/2.0, width, height );
03626 #else
03627 m_context->DrawGraphicsBitmap( bitmap, x - width/2.0, y - height/2.0, width, height );
03628 #endif
03629 }
03630
03631 void a2dGcBaseDrawer::DrawLines( const a2dVertexList* list, bool spline )
03632 {
03633 if ( m_disableDrawing )
03634 return;
03635
03636 wxGraphicsPath path = m_context->CreatePath();
03637
03638 a2dVertexList::const_iterator iter = list->begin();
03639 int i = 0;
03640 while ( iter != list->end() )
03641 {
03642 a2dLineSegment * seg = ( *iter );
03643 if ( i == 0 )
03644 path.MoveToPoint( seg->m_x, seg->m_y );
03645 else
03646 path.AddLineToPoint( seg->m_x, seg->m_y );
03647 i++;
03648 iter++;
03649 }
03650
03651 m_context->StrokePath( path );
03652 }
03653
03654 void a2dGcBaseDrawer::DrawLines( a2dVertexArray* points, bool spline )
03655 {
03656 if ( m_disableDrawing )
03657 return;
03658
03659 wxGraphicsPath path = m_context->CreatePath();
03660
03661 int i;
03662 for ( i = 0; i < points->size(); i++ )
03663 {
03664 const a2dLineSegmentPtr seg = points->Item( i );
03665 if ( i == 0 )
03666 path.MoveToPoint( seg->m_x, seg->m_y );
03667 else
03668 path.AddLineToPoint( seg->m_x, seg->m_y );
03669 }
03670
03671 m_context->StrokePath( path );
03672 }
03673
03674 void a2dGcBaseDrawer::DrawPolygon( a2dVertexArray* points, bool spline, wxPolygonFillMode fillStyle )
03675 {
03676 if ( m_disableDrawing )
03677 return;
03678
03679 wxGraphicsPath path = m_context->CreatePath();
03680
03681 int i;
03682 for ( i = 0; i < points->size(); i++ )
03683 {
03684 const a2dLineSegmentPtr seg = points->Item( i );
03685 if ( i == 0 )
03686 path.MoveToPoint( seg->m_x, seg->m_y );
03687 else
03688 path.AddLineToPoint( seg->m_x, seg->m_y );
03689 }
03690 path.CloseSubpath();
03691
03692 m_context->DrawPath( path , fillStyle);
03693 }
03694
03695 void a2dGcBaseDrawer::DrawPolygon( const a2dVertexList *list, bool spline, wxPolygonFillMode fillStyle )
03696 {
03697 if ( m_disableDrawing )
03698 return;
03699
03700 wxGraphicsPath path = m_context->CreatePath();
03701
03702 a2dVertexList::const_iterator iter = list->begin();
03703 int i = 0;
03704 while ( iter != list->end() )
03705 {
03706 a2dLineSegment * seg = ( *iter );
03707 if ( i == 0 )
03708 path.MoveToPoint( seg->m_x, seg->m_y );
03709 else
03710 path.AddLineToPoint( seg->m_x, seg->m_y );
03711 iter++;
03712 i++;
03713 }
03714 path.CloseSubpath();
03715
03716 m_context->DrawPath( path , fillStyle);
03717 }
03718
03719 void a2dGcBaseDrawer::DrawCircle( double xc, double yc, double radius )
03720 {
03721 if ( m_disableDrawing )
03722 return;
03723
03724 m_context->DrawEllipse( xc - radius, yc - radius, 2.0 * radius, 2.0 * radius );
03725 }
03726
03727 void a2dGcBaseDrawer::DrawEllipse( double xc, double yc, double width, double height )
03728 {
03729 if ( m_disableDrawing )
03730 return;
03731
03732 m_context->DrawEllipse( xc - width/2.0, yc - height/2.0, width, height );
03733 }
03734
03735 void a2dGcBaseDrawer::DrawLine( double x1, double y1, double x2, double y2 )
03736 {
03737 if ( m_disableDrawing )
03738 return;
03739
03740 m_context->StrokeLine( x1, y1, x2, y2 );
03741 }
03742
03743
03744 void a2dGcBaseDrawer::DrawRoundedRectangle( double x, double y, double width, double height, double radius, bool pixelsize )
03745 {
03746 if ( m_disableDrawing )
03747 return;
03748
03749 if ( height < 0 )
03750 {
03751 y += height;
03752 height = -height;
03753 }
03754 if ( width < 0 )
03755 {
03756 x += width;
03757 width = -width;
03758 }
03759 m_context->DrawRoundedRectangle( x, y, width, height, radius);
03760 }
03761
03762 void a2dGcBaseDrawer::DrawPoint( double xc, double yc )
03763 {
03764 if ( m_disableDrawing )
03765 return;
03766
03767 double xt, yt;
03768 GetUserToDeviceTransform().TransformPoint( xc, yc, xt, yt );
03769
03770 }
03771
03772 void a2dGcBaseDrawer::DrawText( const wxString& text, double x, double y, int alignment, bool Background )
03773 {
03774 if ( m_disableDrawing )
03775 return;
03776
03777
03778 a2dBoundingBox bbox = m_currentfont.GetTextExtent( text, m_yaxis, alignment );
03779 bbox.Translate( x, y );
03780
03781
03782
03783 x = bbox.GetMinX();
03784 y = bbox.GetMinY();
03785
03786
03787 double dx, dy, size;
03788 dx = m_usertodevice.GetValue( 1, 0 );
03789 dy = m_usertodevice.GetValue( 1, 1 );
03790 size = m_currentfont.GetSize() * sqrt( dx * dx + dy * dy );
03791
03792
03793 a2dBoundingBox worldbbox( bbox );
03794 worldbbox.MapBbox( m_usertoworld );
03795
03796 if ( m_clipboxworld.Intersect( worldbbox ) != _OUT )
03797 {
03798
03799 if ( Background && !GetDrawerFill().IsNoFill() && !GetDrawerFill().GetStyle() == a2dFILL_TRANSPARENT )
03800 {
03801 a2dStroke oldstroke = m_activestroke;
03802 SetDrawerStroke( *a2dTRANSPARENT_STROKE );
03803 DrawRoundedRectangle( bbox.GetMinX(), bbox.GetMinY(),
03804 bbox.GetWidth(), bbox.GetHeight(), 0 );
03805 SetDrawerStroke( oldstroke );
03806 }
03807
03808 const double h = m_currentfont.GetLineHeight();
03809 a2dAffineMatrix affine;
03810 if ( GetYaxis() )
03811 {
03812 affine.Translate( 0.0, -(y+h) );
03813 affine.Mirror( true, false );
03814 affine.Translate( 0.0, y );
03815 }
03816 PushTransform( affine );
03817
03818
03819
03820
03821
03822 if ( size > m_drawingthreshold )
03823 m_context->DrawText( text, x, y );
03824
03825 else
03826 DrawTextUnknown( text, x, y, true );
03827
03828 PopTransform();
03829 }
03830
03831 }
03832
03833
03834 IMPLEMENT_DYNAMIC_CLASS( a2dNativeGcDrawer, a2dGcBaseDrawer )
03835
03836
03837
03838
03839
03840 void a2dNativeGcDrawer::InitContext()
03841 {
03842 m_clip.Clear();
03843 m_buffer = wxBitmap( m_width, m_height );
03844 m_memdc.SelectObject( m_buffer );
03845 m_render = wxGraphicsRenderer::GetDefaultRenderer();
03846 m_context = m_render->CreateContext( m_memdc );
03847 }
03848
03849 a2dNativeGcDrawer::a2dNativeGcDrawer( const wxSize& size ): a2dGcBaseDrawer( size.GetWidth(), size.GetHeight() )
03850 {
03851 InitContext();
03852 }
03853
03854 a2dNativeGcDrawer::a2dNativeGcDrawer( int width, int height ): a2dGcBaseDrawer( width, height )
03855 {
03856 InitContext();
03857 }
03858
03859 a2dNativeGcDrawer::a2dNativeGcDrawer( const a2dNativeGcDrawer& other )
03860 : a2dGcBaseDrawer( other )
03861 {
03862 InitContext();
03863 }
03864
03865 a2dNativeGcDrawer::a2dNativeGcDrawer( const a2dDrawer2D& other )
03866 : a2dGcBaseDrawer( other )
03867 {
03868 InitContext();
03869 }
03870
03871 a2dNativeGcDrawer::~a2dNativeGcDrawer()
03872 {
03873 m_memdc.SelectObject( wxNullBitmap );
03874 }
03875
03876 wxBitmap a2dNativeGcDrawer::GetBuffer() const
03877 {
03878 return m_buffer;
03879 }
03880
03881 void a2dNativeGcDrawer::SetBufferSize( int w, int h )
03882 {
03883 m_width = w;
03884 m_height = h;
03885 wxBitmap helpbuf = wxBitmap( w, h );
03886
03887
03888
03889 wxMemoryDC mdch;
03890 mdch.SelectObject( helpbuf );
03891 mdch.Blit( 0, 0, w, h, &m_memdc, 0, 0 );
03892 mdch.SelectObject( wxNullBitmap );
03893
03894 m_memdc.SelectObject( wxNullBitmap );
03895 m_buffer = helpbuf;
03896 m_memdc.SelectObject( m_buffer );
03897 delete m_context;
03898 m_context = m_render->CreateContext( m_memdc );
03899 }
03900
03901 wxBitmap a2dNativeGcDrawer::GetSubBitmap( wxRect rect ) const
03902 {
03903 wxBitmap ret( rect.width, rect.height, m_buffer.GetDepth() );
03904 wxASSERT_MSG( ret.Ok(), wxT( "GetSubImage error" ) );
03905
03906
03907 wxMemoryDC dcb;
03908 dcb.SelectObject( ret );
03909 dcb.Blit( 0, 0, rect.width, rect.height, const_cast< wxMemoryDC* >( &m_memdc ), rect.x, rect.y, wxCOPY, false );
03910 dcb.SelectObject( wxNullBitmap );
03911
03912 return ret;
03913 }
03914
03915 void a2dNativeGcDrawer::CopyIntoBuffer( const wxBitmap& bitm )
03916 {
03917 m_memdc.SelectObject( wxNullBitmap );
03918 m_buffer = bitm;
03919 m_memdc.SelectObject( m_buffer );
03920 }
03921
03922 void a2dNativeGcDrawer::BlitBuffer( wxDC* dc, wxRect rect, const wxPoint& bufferpos )
03923 {
03924
03925 if ( rect.x < 0)
03926 {
03927 rect.width += rect.x;
03928 rect.x = 0;
03929 }
03930 if (rect.width <= 0) return;
03931
03932 if (rect.y < 0)
03933 {
03934 rect.height += rect.y;
03935 rect.y = 0;
03936 }
03937 if (rect.height <= 0) return;
03938
03939 if (rect.x+rect.width > m_width )
03940 {
03941 rect.width = m_width - rect.x;
03942 }
03943 if (rect.width <= 0) return;
03944
03945 if (rect.y+rect.height > m_height )
03946 {
03947 rect.height = m_height - rect.y;
03948 }
03949 if (rect.height <= 0) return;
03950
03951 dc->Blit( rect.x - bufferpos.x, rect.y - bufferpos.y, rect.width, rect.height, &m_memdc, rect.x, rect.y, wxCOPY, false );
03952 }
03953
03954 void a2dNativeGcDrawer::ShiftBuffer( int dxy, bool yshift )
03955 {
03956 int bw = GetBuffer().GetWidth();
03957 int bh = GetBuffer().GetHeight();
03958 if ( yshift )
03959 {
03960 if ( dxy > 0 && dxy < bh )
03961 {
03962 wxRect rect( 0, 0, bw, bh - dxy );
03963 wxBitmap sub_bitmap( m_buffer.GetSubBitmap( rect ) );
03964 wxMemoryDC dcm;
03965 dcm.SelectObject( m_buffer );
03966 dcm.DrawBitmap( sub_bitmap, 0, dxy, true );
03967 dcm.SelectObject( wxNullBitmap );
03968 }
03969 else if ( dxy < 0 && dxy > -bh )
03970 {
03971 wxRect rect( 0, -dxy, bw, bh + dxy );
03972 wxBitmap sub_bitmap( m_buffer.GetSubBitmap( rect ) );
03973 wxMemoryDC dcm;
03974 dcm.SelectObject( m_buffer );
03975 dcm.DrawBitmap( sub_bitmap, 0, 0, true );
03976 dcm.SelectObject( wxNullBitmap );
03977 }
03978 else
03979 wxFAIL_MSG( wxT( "you can only shift within height of buffer" ) );
03980
03981 }
03982 else
03983 {
03984 if ( dxy > 0 && dxy < bw )
03985 {
03986 wxRect rect( 0, 0, bw - dxy, bh );
03987 wxBitmap sub_bitmap( m_buffer.GetSubBitmap( rect ) );
03988 wxMemoryDC dcm;
03989 dcm.SelectObject( m_buffer );
03990 dcm.DrawBitmap( sub_bitmap, dxy, 0, true );
03991 dcm.SelectObject( wxNullBitmap );
03992 }
03993 else if ( dxy < 0 && dxy > -bw )
03994 {
03995 wxRect rect( -dxy, 0, bw + dxy, bh );
03996 wxBitmap sub_bitmap( m_buffer.GetSubBitmap( rect ) );
03997 wxMemoryDC dcm;
03998 dcm.SelectObject( m_buffer );
03999 dcm.DrawBitmap( sub_bitmap, 0, 0, true );
04000 dcm.SelectObject( wxNullBitmap );
04001 }
04002 else
04003 wxFAIL_MSG( wxT( "you can only shift within width of buffer" ) );
04004 }
04005 }
04006
04007 void a2dNativeGcDrawer::DrawPoint( double xc, double yc )
04008 {
04009 if ( m_disableDrawing )
04010 return;
04011
04012 double xt, yt;
04013 GetUserToDeviceTransform().TransformPoint( xc, yc, xt, yt );
04014
04015 }
04016
04017 #endif // wxART2D_USE_GRAPHICS_CONTEXT
04018
04019
04020
04021