00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012 #include "a2dprec.h"
00013
00014 #ifdef __BORLANDC__
00015 #pragma hdrstop
00016 #endif
00017
00018 #ifndef WX_PRECOMP
00019 #include "wx/wx.h"
00020 #endif
00021
00022 #include "wx/txtstrm.h"
00023 #include "wx/wfstream.h"
00024 #include "wx/intl.h"
00025 #include "wx/log.h"
00026 #include "wx/strconv.h"
00027 #include <wx/tokenzr.h>
00028
00029 #include <stdio.h>
00030 #include <string.h>
00031 #include <math.h>
00032
00033
00034 #if wxART2D_USE_AGGDRAWER
00035
00036
00037
00038
00039
00040
00041 #define pix_format agg::pix_format_rgb24
00042
00043 typedef agg::pixfmt_rgb24 pixfmt;
00044
00045 typedef agg::pixfmt_rgb24_pre pixfmt_pre;
00046
00047
00048 #define pixfmt_gamma agg::pixfmt_rgb24_gamma
00049
00050 typedef agg::order_rgb component_order;
00051 */
00052
00053 #include "agg_basics.h"
00054
00055 #include "wx/artbase/stylebase.h"
00056 #include "wx/aggdrawer/aggdrawer.h"
00057
00058 #else
00059 #error This source file should not be compiled !
00060 #endif
00061
00062
00063 a2dAggDrawerBase::a2dAggDrawerBase( int width, int height )
00064 :
00065 m_rasterizer(),
00066 m_path(),
00067 m_fillGradient(),
00068 m_lineGradient(),
00069 m_fillGradientMatrix(),
00070 m_lineGradientMatrix(),
00071 m_fillGradientD1(0.0),
00072 m_lineGradientD1(0.0),
00073 m_fillGradientD2(100.0),
00074 m_lineGradientD2(100.0),
00075 m_fillGradientInterpolator(m_fillGradientMatrix),
00076 m_lineGradientInterpolator(m_lineGradientMatrix),
00077 m_linearGradientFunction(),
00078 m_radialGradientFunction(),
00079 a2dDrawer2D( width, height )
00080 {
00081 m_ownsBuffer = true;
00082 m_preStroke = true;
00083 }
00084
00085 a2dAggDrawerBase::a2dAggDrawerBase( const wxSize& size )
00086 :
00087 m_rasterizer(),
00088 m_path(),
00089 m_fillGradient(),
00090 m_lineGradient(),
00091 m_fillGradientMatrix(),
00092 m_lineGradientMatrix(),
00093 m_fillGradientD1(0.0),
00094 m_lineGradientD1(0.0),
00095 m_fillGradientD2(100.0),
00096 m_lineGradientD2(100.0),
00097 m_fillGradientInterpolator(m_fillGradientMatrix),
00098 m_lineGradientInterpolator(m_lineGradientMatrix),
00099 m_linearGradientFunction(),
00100 m_radialGradientFunction(),
00101 a2dDrawer2D( size )
00102 {
00103 m_ownsBuffer = true;
00104 m_preStroke = true;
00105 }
00106
00107 a2dAggDrawerBase::a2dAggDrawerBase( const wxBitmap& bitmap )
00108 :
00109 m_rasterizer(),
00110 m_path(),
00111 m_fillGradient(),
00112 m_lineGradient(),
00113 m_fillGradientMatrix(),
00114 m_lineGradientMatrix(),
00115 m_fillGradientD1(0.0),
00116 m_lineGradientD1(0.0),
00117 m_fillGradientD2(100.0),
00118 m_lineGradientD2(100.0),
00119 m_fillGradientInterpolator(m_fillGradientMatrix),
00120 m_lineGradientInterpolator(m_lineGradientMatrix),
00121 m_linearGradientFunction(),
00122 m_radialGradientFunction(),
00123 a2dDrawer2D( bitmap.GetWidth(), bitmap.GetHeight() )
00124 {
00125 m_ownsBuffer = true;
00126 m_preStroke = true;
00127 }
00128
00129 a2dAggDrawerBase::a2dAggDrawerBase( const a2dAggDrawerBase& other )
00130 :
00131 m_rasterizer(),
00132 m_path(),
00133 m_fillGradient(),
00134 m_lineGradient(),
00135 m_fillGradientMatrix(),
00136 m_lineGradientMatrix(),
00137 m_fillGradientD1(0.0),
00138 m_lineGradientD1(0.0),
00139 m_fillGradientD2(100.0),
00140 m_lineGradientD2(100.0),
00141 m_fillGradientInterpolator(m_fillGradientMatrix),
00142 m_lineGradientInterpolator(m_lineGradientMatrix),
00143 m_linearGradientFunction(),
00144 m_radialGradientFunction(),
00145 a2dDrawer2D( other )
00146 {
00147 m_ownsBuffer = false;
00148 m_preStroke = other.m_preStroke;
00149 }
00150
00151 void a2dAggDrawerBase::ResetStyle()
00152 {
00153 SetDrawerFill( *a2dBLACK_FILL );
00154 SetDrawerStroke( *a2dBLACK_STROKE );
00155 SetDrawStyle( m_drawstyle );
00156 }
00157
00158 agg::trans_affine a2dAggDrawerBase::_get_agg_user_to_device_transform() const
00159 {
00160 const a2dAffineMatrix &rmtx = GetUserToDeviceTransform();
00161 return agg::trans_affine(
00162 rmtx(0,0),rmtx(0,1),
00163 rmtx(1,0),rmtx(1,1),
00164 rmtx(2,0),rmtx(2,1));
00165 }
00166
00167 void a2dAggDrawerBase::BlitBuffer( wxRect rect, const wxPoint& bufferpos )
00168 {
00169 BeginDraw();
00170 BlitBuffer( m_deviceDC, rect, bufferpos );
00171 EndDraw();
00172 }
00173
00174 void a2dAggDrawerBase::BeginDraw()
00175 {
00176 wxASSERT_MSG( m_beginDraw_endDraw >= 0, wxT("a2dDcDrawer, unbalanced BeginDraw EndDraw") );
00177
00178 if ( m_display && m_beginDraw_endDraw == 0 )
00179 {
00180 m_deviceDC = new wxClientDC( m_display );
00181 m_display->PrepareDC( *m_deviceDC );
00182 DestroyClippingRegion();
00183 SetDrawStyle( m_drawstyle );
00184 SetActiveStroke( m_currentstroke );
00185 SetActiveFill( m_currentfill );
00186 m_OpacityFactor = 255;
00187 }
00188 m_beginDraw_endDraw++;
00189 }
00190
00191
00192 void a2dAggDrawerBase::EndDraw()
00193 {
00194 m_beginDraw_endDraw--;
00195
00196 wxASSERT_MSG( m_beginDraw_endDraw >= 0, wxT("a2dDcDrawer, unbalanced BeginDraw EndDraw") );
00197
00198 if ( m_display && m_beginDraw_endDraw == 0 )
00199 {
00200 delete m_deviceDC;
00201 m_deviceDC = NULL;
00202 }
00203
00204 }
00205
00206 void a2dAggDrawerBase::DoSetDrawStyle( a2dDrawStyle drawstyle )
00207 {
00208 m_drawstyle = drawstyle;
00209
00210 switch( drawstyle )
00211 {
00212 case a2dWIREFRAME_INVERT:
00213
00214
00215 m_blendMode = agg::comp_op_invert;
00216 break;
00217
00218 case a2dWIREFRAME:
00219 SetActiveStroke( *a2dBLACK_STROKE );
00220 SetActiveFill( *a2dTRANSPARENT_FILL );
00221 m_blendMode = agg::end_of_comp_op_e;
00222 break;
00223
00224 case a2dWIREFRAME_ZERO_WIDTH:
00225 SetActiveStroke( *a2dBLACK_STROKE );
00226 SetActiveFill( *a2dTRANSPARENT_FILL );
00227 m_blendMode = agg::end_of_comp_op_e;
00228 break;
00229
00230 case a2dWIREFRAME_INVERT_ZERO_WIDTH:
00231 SetActiveStroke( *a2dBLACK_STROKE );
00232 SetActiveFill( *a2dTRANSPARENT_FILL );
00233 m_blendMode = agg::comp_op_invert;
00234 break;
00235
00236 case a2dFILLED:
00237 SetActiveStroke( m_currentstroke );
00238 SetActiveFill( m_currentfill );
00239 m_blendMode = agg::end_of_comp_op_e;
00240 break;
00241
00242 case a2dFIX_STYLE:
00243
00244 m_fixStrokeRestore = m_currentstroke;
00245 m_fixFillRestore = m_currentfill;
00246 m_fixDrawstyle = m_drawstyle;
00247 SetActiveStroke( m_currentstroke );
00248 SetActiveFill( m_currentfill );
00249
00250 m_blendMode = agg::end_of_comp_op_e;
00251 break;
00252
00253 case a2dFIX_STYLE_INVERT:
00254
00255 m_blendMode = agg::comp_op_invert;
00256 break;
00257
00258 default:
00259 wxASSERT( 0 );
00260 }
00261 }
00262
00263 void a2dAggDrawerBase::DoSetActiveStroke()
00264 {
00265 if ( m_drawstyle == a2dWIREFRAME_INVERT_ZERO_WIDTH )
00266 {
00267 m_strokewidth = 0;
00268 m_strokewidthDev = 1;
00269 }
00270 else if ( m_activestroke.GetType() == a2dSTROKE_ONE_COLOUR )
00271 {
00272 switch( m_activestroke.GetStyle() )
00273 {
00274 case a2dSTROKE_SOLID:
00275 case a2dSTROKE_TRANSPARENT:
00276 case a2dSTROKE_DOT:
00277 case a2dSTROKE_DOT_DASH:
00278 case a2dSTROKE_LONG_DASH:
00279 case a2dSTROKE_SHORT_DASH:
00280 m_style = m_activestroke.GetStyle();
00281 break;
00282
00283
00284
00285
00286
00287
00288
00289
00290
00291
00292
00293
00294
00295
00296
00297
00298
00299
00300
00301
00302
00303 default: m_style=a2dSTROKE_SOLID;
00304 }
00305
00306 m_strokewidth = m_activestroke.GetWidth();
00307 if ( m_drawstyle == a2dWIREFRAME_ZERO_WIDTH )
00308 {
00309 a2dAffineMatrix invert = m_worldtodevice;
00310 invert.Invert();
00311 m_strokewidthDev = 1;
00312 m_strokewidth = invert.TransformDistance( m_strokewidthDev );
00313 m_join = agg::round_join;
00314 m_cap = agg::round_cap;
00315 }
00316 else
00317 {
00318 switch ( m_activestroke.GetJoin() )
00319 {
00320 case wxJOIN_MITER: m_join = agg::miter_join;
00321 break;
00322 case wxJOIN_ROUND: m_join = agg::round_join;
00323 break;
00324 case wxJOIN_BEVEL: m_join = agg::bevel_join;
00325 break;
00326 default: m_join = agg::round_join;
00327 }
00328 switch ( m_activestroke.GetCap() )
00329 {
00330 case wxCAP_BUTT: m_cap = agg::butt_cap;
00331 break;
00332 case wxCAP_ROUND: m_cap = agg::round_cap;
00333 break;
00334 case wxCAP_PROJECTING: m_cap = agg::square_cap;
00335 break;
00336 default: m_cap = agg::round_cap;
00337 }
00338
00339 if ( m_activestroke.GetPixelStroke() )
00340 {
00341 a2dAffineMatrix invert = m_worldtodevice;
00342 invert.Invert();
00343 m_strokewidthDev = m_activestroke.GetWidth();
00344 m_strokewidthDev = !m_strokewidthDev ? 1: m_strokewidthDev;
00345 m_strokewidth = invert.TransformDistance( m_strokewidthDev );
00346 }
00347 else
00348 {
00349 m_strokewidth = m_activestroke.GetWidth();
00350 m_strokewidthDev = m_worldtodevice.TransformDistance( m_strokewidth );
00351 if ( !m_strokewidthDev )
00352 {
00353 m_strokewidthDev = 1;
00354 a2dAffineMatrix invert = m_worldtodevice;
00355 invert.Invert();
00356 m_strokewidth = invert.TransformDistance( m_strokewidthDev );
00357 }
00358 }
00359 }
00360 }
00361 }
00362
00363
00364 void a2dAggDrawerBase::DoSetActiveFill()
00365 {
00366 if ( m_activefill.GetType() == a2dFILL_ONE_COLOUR )
00367 {
00368 switch( m_activefill.GetStyle() )
00369 {
00370 case a2dFILL_TRANSPARENT:
00371 break;
00372 case a2dFILL_SOLID:
00373 break;
00374 case a2dFILL_BDIAGONAL_HATCH:
00375 m_pattern = wxImage( BDIAGONAL_HATCH_XPM );
00376 break;
00377 case a2dFILL_CROSSDIAG_HATCH:
00378 m_pattern = wxImage( CROSSDIAG_HATCH_XPM );
00379 break;
00380 case a2dFILL_FDIAGONAL_HATCH:
00381 m_pattern = wxImage( FDIAGONAL_HATCH_XPM );
00382 break;
00383 case a2dFILL_CROSS_HATCH:
00384 m_pattern = wxImage( CROSS_HATCH_XPM );
00385 break;
00386 case a2dFILL_HORIZONTAL_HATCH:
00387 m_pattern = wxImage( HORIZONTAL_HATCH_XPM );
00388 break;
00389 case a2dFILL_VERTICAL_HATCH:
00390 m_pattern = wxImage( VERTICAL_HATCH_XPM );
00391 break;
00392 default: ;
00393 }
00394 if ( m_activefill.GetStyle() >= a2dFIRST_HATCH && m_activefill.GetStyle() <= a2dLAST_HATCH )
00395 {
00396 m_pattern.Replace( 0, 0, 0,
00397 m_colour1redFill,
00398 m_colour1greenFill,
00399 m_colour1blueFill );
00400
00401 m_pattern_rbuf.attach(m_pattern.GetData(), m_pattern.GetWidth(), m_pattern.GetHeight(), m_pattern.GetWidth()*3);
00402 }
00403 }
00404 else if ( m_activefill.GetType() == a2dFILL_HATCH_TWO_COLOUR )
00405 {
00406 bool nohatch = false;
00407 switch( m_activefill.GetStyle() )
00408 {
00409 case a2dFILL_TWOCOL_BDIAGONAL_HATCH:
00410 m_pattern = wxImage( BDIAGONAL_HATCH_XPM );
00411 break;
00412 case a2dFILL_TWOCOL_CROSSDIAG_HATCH:
00413 m_pattern = wxImage( CROSSDIAG_HATCH_XPM );
00414 break;
00415 case a2dFILL_TWOCOL_FDIAGONAL_HATCH:
00416 m_pattern = wxImage( FDIAGONAL_HATCH_XPM );
00417 break;
00418 case a2dFILL_TWOCOL_CROSS_HATCH:
00419 m_pattern = wxImage( CROSS_HATCH_XPM );
00420 break;
00421 case a2dFILL_TWOCOL_HORIZONTAL_HATCH:
00422 m_pattern = wxImage( HORIZONTAL_HATCH_XPM );
00423 break;
00424 case a2dFILL_TWOCOL_VERTICAL_HATCH:
00425 m_pattern = wxImage( VERTICAL_HATCH_XPM );
00426 break;
00427 default:
00428 nohatch = true;
00429 break;
00430 }
00431 m_pattern.Replace( 255, 255, 255,
00432 m_colour2redFill,
00433 m_colour2greenFill,
00434 m_colour2blueFill );
00435
00436 m_pattern.Replace( 0, 0, 0,
00437 m_colour1redFill,
00438 m_colour1greenFill,
00439 m_colour1blueFill );
00440
00441 m_pattern_rbuf.attach(m_pattern.GetData(), m_pattern.GetWidth(), m_pattern.GetHeight(), m_pattern.GetWidth()*3);
00442 }
00443 else if ( m_activefill.GetType() == a2dFILL_BITMAP )
00444 {
00445 wxBrush dcbrush;
00446
00447 switch( m_activefill.GetStyle() )
00448 {
00449 case a2dFILL_STIPPLE:
00450 case a2dFILL_STIPPLE_MASK_OPAQUE_TRANSPARENT:
00451 case a2dFILL_STIPPLE_MASK_OPAQUE:
00452 {
00453 static const int MASK_RED = 1;
00454 static const int MASK_GREEN = 2;
00455 static const int MASK_BLUE = 3;
00456
00457 m_pattern = m_activefill.GetStipple().ConvertToImage();
00458 m_pattern.Replace( MASK_RED, MASK_GREEN, MASK_BLUE,
00459 m_colour1redFill,
00460 m_colour1greenFill,
00461 m_colour1blueFill );
00462
00463 m_pattern_rbuf.attach(m_pattern.GetData(), m_pattern.GetWidth(), m_pattern.GetHeight(), m_pattern.GetWidth()*3);
00464
00465
00466
00467
00468
00469
00470 }
00471 break;
00472 default:
00473 break;
00474 }
00475 }
00476 else if ( m_activefill.GetType() == a2dFILL_GRADIENT_FILL_LINEAR )
00477 {
00478 double profile=1.0;
00479 int i;
00480 double x1 = m_activefill.GetStart().m_x;
00481 double y1 = m_activefill.GetStart().m_y;
00482 double x2 = m_activefill.GetStop().m_x;
00483 double y2 = m_activefill.GetStop().m_y;
00484 color_type c1( m_colour1redFill, m_colour1greenFill, m_colour1blueFill, m_FillOpacityCol1 );
00485 color_type c2( m_colour2redFill, m_colour2greenFill, m_colour2blueFill, m_FillOpacityCol2 );
00486 int startGradient = 128 - int(profile * 128.0);
00487 int endGradient = 128 + int(profile * 128.0);
00488 if (endGradient <= startGradient) endGradient = startGradient + 1;
00489 double k = 1.0 / double(endGradient - startGradient);
00490 for (i = 0; i < startGradient; i++)
00491 {
00492 m_fillGradient[i] = c1;
00493 }
00494 for (; i < endGradient; i++)
00495 {
00496 m_fillGradient[i] = c1.gradient(c2, double(i - startGradient) * k);
00497 }
00498 for (; i < 256; i++)
00499 {
00500 m_fillGradient[i] = c2;
00501 }
00502 double angle = atan2(y2-y1, x2-x1);
00503 m_fillGradientMatrix.reset();
00504 m_fillGradientMatrix *= agg::trans_affine_rotation(angle);
00505 m_fillGradientMatrix *= agg::trans_affine_translation(x1, y1);
00506 m_fillGradientMatrix *= _get_agg_user_to_device_transform();
00507 m_fillGradientMatrix.invert();
00508 m_fillGradientD1 = 0;
00509 m_fillGradientD2 = sqrt((x2-x1) * (x2-x1) + (y2-y1) * (y2-y1));
00510 }
00511 else if ( m_activefill.GetType() == a2dFILL_GRADIENT_FILL_RADIAL )
00512 {
00513 double profile=1.0;
00514 int i;
00515 double xf = m_activefill.GetFocal().m_x;
00516 double yf = m_activefill.GetFocal().m_y;
00517 double x = m_activefill.GetCenter().m_x;
00518 double y = m_activefill.GetCenter().m_y;
00519 double r = m_activefill.GetRadius();
00520
00521 color_type c1( m_colour1redFill, m_colour1greenFill, m_colour1blueFill, m_FillOpacityCol1 );
00522 color_type c2( m_colour2redFill, m_colour2greenFill, m_colour2blueFill, m_FillOpacityCol2 );
00523 int startGradient = 128 - int(profile * 127.0);
00524 int endGradient = 128 + int(profile * 127.0);
00525 if (endGradient <= startGradient) endGradient = startGradient + 1;
00526 double k = 1.0 / double(endGradient - startGradient);
00527 for (i = 0; i < startGradient; i++)
00528 {
00529 m_fillGradient[i] = c1;
00530 }
00531 for (; i < endGradient; i++)
00532 {
00533 m_fillGradient[i] = c1.gradient(c2, double(i - startGradient) * k);
00534 }
00535 for (; i < 256; i++)
00536 {
00537 m_fillGradient[i] = c2;
00538 }
00539 m_fillGradientD2 = m_usertodevice.TransformDistance( r );
00540 m_usertodevice.TransformPoint( x, y, x, y );
00541 m_fillGradientMatrix.reset();
00542 m_fillGradientMatrix *= agg::trans_affine_translation(x, y);
00543 m_fillGradientMatrix.invert();
00544 m_fillGradientD1 = 0;
00545 }
00546 }
00547
00548 void a2dAggDrawerBase::SetClippingRegion( a2dVertexList* points, bool spline, wxPolygonFillMode fillStyle )
00549 {
00550 unsigned int n = points->size();
00551 m_cpointsDouble.resize(n);
00552
00553 unsigned int i = 0;
00554 double x,y;
00555 forEachIn( a2dVertexList, points )
00556 {
00557 a2dPoint2D point = (*iter)->GetPoint();
00558
00559 GetUserToDeviceTransform().TransformPoint( point.m_x, point.m_y, x, y );
00560 m_cpointsDouble[i].x = x;
00561 m_cpointsDouble[i].y = y;
00562 i++;
00563 }
00564
00565 if ( spline )
00566 n = ConvertSplinedPolygon2(n);
00567
00568 wxPoint* intCPoints = new wxPoint[n];
00569
00570 for ( i = 0; i < n; i++)
00571 {
00572 intCPoints[i].x = Round(m_cpointsDouble[i].x);
00573 intCPoints[i].y = Round(m_cpointsDouble[i].y);
00574 }
00575
00576 m_clip = wxRegion( n, intCPoints, fillStyle );
00577
00578 delete[] intCPoints;
00579 }
00580
00581 void a2dAggDrawerBase::ExtendAndPushClippingRegion( a2dVertexList* points, bool spline, wxPolygonFillMode fillStyle, a2dBooleanClip clipoperation )
00582 {
00583
00584 wxRegion* push = new wxRegion( m_clip );
00585
00586 m_clipregionlist.Insert( push );
00587
00588 ExtendClippingRegion( points, spline, fillStyle, clipoperation );
00589 }
00590
00591 void a2dAggDrawerBase::ExtendClippingRegion( a2dVertexList* points, bool spline, wxPolygonFillMode fillStyle, a2dBooleanClip clipoperation )
00592 {
00593 wxRegion totaladd;
00594 bool first=false;
00595
00596 unsigned int n = points->size();
00597 m_cpointsDouble.resize(n);
00598
00599 unsigned int i = 0;
00600 double x,y;
00601 forEachIn( a2dVertexList, points )
00602 {
00603 a2dPoint2D point = (*iter)->GetPoint();
00604
00605 GetUserToDeviceTransform().TransformPoint( point.m_x, point.m_y, x, y );
00606 m_cpointsDouble[i].x = x;
00607 m_cpointsDouble[i].y = y;
00608 i++;
00609 }
00610
00611 if ( spline )
00612 n = ConvertSplinedPolygon2(n);
00613
00614 wxPoint* intCPoints = new wxPoint[n];
00615
00616 for ( i = 0; i < n; i++)
00617 {
00618 intCPoints[i].x = Round(m_cpointsDouble[i].x);
00619 intCPoints[i].y = Round(m_cpointsDouble[i].y);
00620 }
00621
00622 wxRegion add = wxRegion( n, intCPoints, fillStyle );
00623
00624 delete[] intCPoints;
00625
00626 if (!first)
00627 {
00628 totaladd = add;
00629 first = true;
00630 }
00631 else
00632 totaladd.Union( add );
00633
00634 if (!m_clip.Empty())
00635 {
00636 bool result;
00637 switch (clipoperation)
00638 {
00639 case a2dCLIP_AND:
00640 result = m_clip.Intersect( totaladd );
00641 break ;
00642
00643 case a2dCLIP_OR:
00644 result = m_clip.Union( totaladd );
00645 break ;
00646
00647 case a2dCLIP_XOR:
00648 result = m_clip.Xor( totaladd );
00649 break ;
00650
00651 case a2dCLIP_DIFF:
00652 result = m_clip.Subtract( totaladd );
00653 break ;
00654
00655 case a2dCLIP_COPY:
00656 default:
00657 m_clip = totaladd;
00658 result = true;
00659 break ;
00660
00661 }
00662 if ( result )
00663 {
00664
00665
00666 }
00667 }
00668 else
00669 {
00670 m_clip = totaladd;
00671
00672
00673 }
00674
00675 m_clipboxdev = m_clip.GetBox();
00676 m_clipboxworld = ToWorld( m_clipboxdev );
00677 }
00678
00679 void a2dAggDrawerBase::PopClippingRegion()
00680 {
00681 if (!m_clipregionlist.GetCount())
00682 return;
00683
00684 m_clip = *m_clipregionlist.GetFirst()->GetData();
00685 delete m_clipregionlist.GetFirst()->GetData();
00686 m_clipregionlist.DeleteNode(m_clipregionlist.GetFirst());
00687
00688
00689
00690 }
00691
00692 void a2dAggDrawerBase::SetClippingRegionDev(wxCoord minx, wxCoord miny, wxCoord width, wxCoord height)
00693 {
00694 m_clip = wxRegion( minx, miny, width, height );
00695
00696 m_clipboxdev = wxRect( minx, miny, width, height );
00697 RenderSetClip();
00698
00699
00700 m_clipboxworld = ToWorld( m_clipboxdev );
00701 }
00702
00703 void a2dAggDrawerBase::SetClippingRegion(double minx, double miny, double maxx, double maxy)
00704 {
00705 int iminx = WorldToDeviceX(minx);
00706 int iminy = WorldToDeviceY(miny);
00707 int imaxx = WorldToDeviceX(maxx);
00708 int imaxy = WorldToDeviceY(maxy);
00709 if ( m_yaxis )
00710 {
00711 m_clip = wxRegion( iminx, imaxy, imaxx - iminx, iminy - imaxy );
00712 m_clipboxdev = wxRect( iminx, imaxy, imaxx - iminx, iminy - imaxy );
00713 }
00714 else
00715 {
00716 m_clip = wxRegion( iminx, iminy, imaxx - iminx, imaxy - iminy );
00717 m_clipboxdev = wxRect( iminx, iminy, imaxx - iminx, imaxy - iminy );
00718 }
00719 RenderSetClip();
00720
00721
00722
00723 m_clipboxworld = ToWorld( m_clipboxdev );
00724 }
00725
00726 void a2dAggDrawerBase::DestroyClippingRegion()
00727 {
00728 m_clip.Clear();
00729
00730 m_clipboxdev = wxRect( 0, 0, m_width, m_height );
00731 m_clipboxworld = ToWorld( m_clipboxdev );
00732 RenderSetClip();
00733 }
00734
00735 int a2dAggDrawerBase::ToAggPath( a2dVertexArray* points, bool transform )
00736 {
00737 unsigned int segments = 0;
00738
00739 m_path.remove_all();
00740
00741 unsigned int count = 0;
00742 double x, y, lastx, lasty;
00743 int i;
00744 for ( i = 0; i < points->size(); i++ )
00745 {
00746 const a2dLineSegmentPtr seg = points->Item( i );
00747
00748 if ( !seg->GetArc() )
00749 {
00750 if ( transform )
00751 m_usertodevice.TransformPoint( seg->m_x, seg->m_y, x, y );
00752 else
00753 {
00754 x = seg->m_x;
00755 y = seg->m_y;
00756 }
00757
00758
00759 if( !count || fabs( x - lastx ) > 0.001 || fabs( y - lasty ) > 0.001 )
00760 {
00761 if ( count == 0 )
00762 m_path.move_to( x, y );
00763 else
00764 m_path.line_to( x, y );
00765 lastx = x;
00766 lasty = y;
00767 count++;
00768 }
00769 }
00770 else
00771 {
00772 const a2dArcSegment* cseg = ( const a2dArcSegment* ) seg.Get();
00773
00774 double radius, center_x, center_y, beginrad, midrad, endrad, phit;
00775
00776 if ( cseg->CalcR( *(points->Item( i ? i - 1 : 0 )), radius, center_x, center_y, beginrad, midrad, endrad, phit ) )
00777 {
00778 double dphi;
00779 unsigned int segments;
00780 double radiusDev = m_usertodevice.TransformDistance( radius );
00781 Aberration( m_displayaberration, phit, radiusDev , dphi, segments );
00782
00783 double theta = beginrad;
00784 unsigned int step;
00785
00786 double x, y;
00787 for ( step = 0; step < segments + 1; step++ )
00788 {
00789 if ( transform )
00790 m_usertodevice.TransformPoint( center_x + radius * cos ( theta ), center_y + radius * sin ( theta ), x, y );
00791 else
00792 {
00793 x = center_x + radius * cos ( theta );
00794 y = center_y + radius * sin ( theta );
00795 }
00796
00797 if( !count || fabs( x - lastx ) > 0.001 || fabs( y - lasty ) > 0.001 )
00798 {
00799 if ( count == 0 )
00800 m_path.move_to( x, y );
00801 else
00802 m_path.line_to( x, y );
00803
00804 lastx = x;
00805 lasty = y;
00806 count++;
00807 }
00808 theta = theta + dphi;
00809 }
00810 }
00811 else
00812 {
00813 double x, y;
00814 if ( transform )
00815 m_usertodevice.TransformPoint( cseg->m_x, cseg->m_y, x, y );
00816 else
00817 {
00818 x = cseg->m_x;
00819 y = cseg->m_y;
00820 }
00821
00822
00823 if( !count || fabs( x - lastx ) > 0.001 || fabs( y - lasty ) > 0.001 )
00824 {
00825 if ( count == 0 )
00826 m_path.move_to( x, y );
00827 else
00828 m_path.line_to( x, y );
00829 lastx = x;
00830 lasty = y;
00831 count++;
00832 }
00833 }
00834 }
00835 }
00836
00837 return count;
00838 }
00839
00840 int a2dAggDrawerBase::ToAggPath( const a2dVertexList *list, bool transform )
00841 {
00842 unsigned int segments = 0;
00843
00844 if ( list->empty() )
00845 return 0;
00846
00847 m_path.remove_all();
00848
00849 a2dVertexList::const_iterator iterprev = list->end();
00850
00851 unsigned int count = 0;
00852 double x, y, lastx, lasty;
00853 iterprev = list->end();
00854 if ( iterprev != list->begin() )
00855 iterprev--;
00856 a2dVertexList::const_iterator iter = list->begin();
00857 iter = list->begin();
00858 while ( iter != list->end() )
00859 {
00860 a2dLineSegment * seg = ( *iter );
00861
00862 if ( !seg->GetArc() )
00863 {
00864 if ( transform )
00865 m_usertodevice.TransformPoint( seg->m_x, seg->m_y, x, y );
00866 else
00867 {
00868 x = seg->m_x;
00869 y = seg->m_y;
00870 }
00871
00872
00873 if( !count || fabs( x - lastx ) > 0.001 || fabs( y - lasty ) > 0.001 )
00874 {
00875 if ( count == 0 )
00876 m_path.move_to( x, y );
00877 else
00878 m_path.line_to( x, y );
00879 lastx = x;
00880 lasty = y;
00881 count++;
00882 }
00883 }
00884 else
00885 {
00886 a2dArcSegment* cseg = ( a2dArcSegment* ) seg;
00887
00888 double radius, center_x, center_y, beginrad, midrad, endrad, phit;
00889
00890 if ( cseg->CalcR( *( *iterprev ), radius, center_x, center_y, beginrad, midrad, endrad, phit ) )
00891 {
00892 double dphi;
00893 unsigned int segments;
00894 double radiusDev = m_usertodevice.TransformDistance( radius );
00895 Aberration( m_displayaberration, phit, radiusDev , dphi, segments );
00896
00897 double theta = beginrad;
00898 unsigned int step;
00899
00900 double x, y;
00901 for ( step = 0; step < segments + 1; step++ )
00902 {
00903 if ( transform )
00904 m_usertodevice.TransformPoint( center_x + radius * cos ( theta ), center_y + radius * sin ( theta ), x, y );
00905 else
00906 {
00907 x = center_x + radius * cos ( theta );
00908 y = center_y + radius * sin ( theta );
00909 }
00910
00911
00912 if( !count || fabs( x - lastx ) > 0.001 || fabs( y - lasty ) > 0.001 )
00913 {
00914 if ( count == 0 )
00915 m_path.move_to( x, y );
00916 else
00917 m_path.line_to( x, y );
00918 lastx = x;
00919 lasty = y;
00920 count++;
00921 }
00922 theta = theta + dphi;
00923 }
00924 }
00925 else
00926 {
00927 double x, y;
00928 if ( transform )
00929 m_usertodevice.TransformPoint( cseg->m_x, cseg->m_y, x, y );
00930 else
00931 {
00932 x = cseg->m_x;
00933 y = cseg->m_y;
00934 }
00935
00936
00937 if( !count || fabs( x - lastx ) > 0.001 || fabs( y - lasty ) > 0.001 )
00938 {
00939 if ( count == 0 )
00940 m_path.move_to( x, y );
00941 else
00942 m_path.line_to( x, y );
00943 lastx = x;
00944 lasty = y;
00945 count++;
00946 }
00947 }
00948 }
00949 iterprev = iter++;
00950 }
00951
00952 return count;
00953 }
00954
00955 void a2dAggDrawerBase::ShiftBufferInternal( int dxy, bool yshift, int bytesPerPixel )
00956 {
00957 if (yshift)
00958 {
00959 int pixelwidth = m_width*bytesPerPixel;
00960
00961 if (dxy > 0 && dxy < m_height )
00962 {
00963 unsigned char* highline = m_pdata + (m_height-dxy)*pixelwidth ;
00964 unsigned char* lowline = m_pdata + m_height*pixelwidth ;
00965
00966 for (int yp = 0; yp < m_height-dxy; yp++)
00967 {
00968 highline -= pixelwidth;
00969 lowline -= pixelwidth;
00970 memcpy( lowline, highline, pixelwidth);
00971 }
00972 }
00973 else if (dxy < 0 && dxy > -m_height)
00974 {
00975 dxy = -dxy;
00976 unsigned char* highline = m_pdata;
00977 unsigned char* lowline = m_pdata + dxy*pixelwidth ;
00978
00979 for (int yp = 0; yp < m_height-dxy ; yp++)
00980 {
00981 memcpy( highline, lowline, pixelwidth);
00982 highline += pixelwidth;
00983 lowline += pixelwidth;
00984 }
00985 }
00986 else
00987 wxFAIL_MSG( wxT("you can only shift within height of buffer") );
00988 }
00989 else
00990 {
00991 int pixelwidth = m_width*bytesPerPixel;
00992 if (dxy > 0 && dxy < m_width)
00993 {
00994 int subwidth = (m_width - dxy)*bytesPerPixel;
00995 unsigned char* low = m_pdata;
00996 unsigned char* high = m_pdata + dxy*bytesPerPixel;
00997
00998 for (int yp = 0; yp < m_height ; yp++)
00999 {
01000 memcpy( high, low, subwidth);
01001 high += pixelwidth;
01002 low += pixelwidth;
01003 }
01004 }
01005 else if (dxy < 0 && dxy > -m_width )
01006 {
01007 dxy = -dxy;
01008 int subwidth = (m_width - dxy)*bytesPerPixel;
01009 unsigned char* low = m_pdata;
01010 unsigned char* high = m_pdata + dxy*bytesPerPixel ;
01011
01012 for (int yp = 0; yp < m_height ; yp++)
01013 {
01014 memcpy( low, high, subwidth );
01015 high += pixelwidth;
01016 low += pixelwidth;
01017 }
01018 }
01019 else
01020 wxFAIL_MSG( wxT("you can only shift within width of buffer") );
01021 }
01022 }
01023
01024 template< class PathT >
01025 void a2dAggDrawerBase::_ras_add_stroked_path_xform(PathT &path, const
01026 agg::trans_affine& mtx)
01027 {
01028
01029
01030
01031
01032
01033 if (m_style == a2dSTROKE_SOLID)
01034 {
01035 if ( m_preStroke )
01036 {
01037 typedef agg::conv_stroke< PathT > path_stroke_t;
01038 typedef agg::conv_transform< path_stroke_t > path_stroke_trans_t;
01039
01040 path_stroke_t stroke(path);
01041 path_stroke_trans_t trans_path( stroke, mtx );
01042 stroke.line_join(m_join);
01043 stroke.line_cap(m_cap);
01044 if ( m_activestroke.GetPixelStroke() )
01045 stroke.width( m_strokewidthDev );
01046 else
01047 stroke.width( m_strokewidth );
01048 m_rasterizer.reset();
01049 m_rasterizer.add_path( trans_path );
01050 }
01051 else
01052 {
01053 typedef agg::conv_transform<PathT> trans_t;
01054 typedef agg::conv_stroke< trans_t > path_stroke_t;
01055
01056 trans_t trans_path(path,mtx);
01057 path_stroke_t stroke(trans_path);
01058
01059 stroke.line_join(m_join);
01060 stroke.line_cap(m_cap);
01061 stroke.width( m_strokewidthDev );
01062 m_rasterizer.reset();
01063 m_rasterizer.add_path( stroke );
01064 }
01065 }
01066 else
01067 {
01068 if ( m_preStroke )
01069 {
01070 typedef agg::conv_dash< PathT > path_dash_t;
01071 typedef agg::conv_stroke< path_dash_t > path_dashstroked_t;
01072 typedef agg::conv_transform< path_dashstroked_t > path_transdash_t;
01073
01074 path_dash_t dash_path(path);
01075 path_dashstroked_t stroke(dash_path);
01076 path_transdash_t trans_path( stroke, mtx);
01077
01078 double scale = m_strokewidth;
01079 if (scale < 1.0) scale = 1.0;
01080
01081 switch(m_style)
01082 {
01083 case a2dSTROKE_DOT:
01084 dash_path.add_dash( 0.25*scale, 1.5*scale);
01085 break;
01086 case a2dSTROKE_DOT_DASH:
01087 dash_path.add_dash( 0.25*scale, 1.5*scale);
01088 dash_path.add_dash(2.0*scale, 2.0*scale);
01089 break;
01090 case a2dSTROKE_LONG_DASH:
01091 dash_path.add_dash( 2.0*scale, 2.0*scale);
01092 break;
01093 case a2dSTROKE_SHORT_DASH:
01094 dash_path.add_dash( 2.0*scale, 2.0*scale);
01095 break;
01096
01097
01098 }
01099
01100 stroke.line_join(m_join);
01101 stroke.line_cap(m_cap);
01102
01103 if ( m_activestroke.GetPixelStroke() )
01104 stroke.width( m_strokewidth );
01105 else
01106 stroke.width( m_strokewidthDev );
01107 m_rasterizer.reset();
01108 m_rasterizer.add_path(trans_path);
01109 }
01110 else
01111 {
01112 typedef agg::conv_transform<PathT> trans_t;
01113 typedef agg::conv_dash< trans_t > path_transdash_t;
01114 typedef agg::conv_stroke< path_transdash_t > path_dashstroked_t;
01115
01116 trans_t trans_path(path, mtx);
01117 path_transdash_t dash_path(trans_path);
01118 path_dashstroked_t stroke(dash_path);
01119
01120 double scale = m_strokewidthDev;
01121 if (scale < 1.0) scale = 1.0;
01122
01123 switch(m_style)
01124 {
01125 case a2dSTROKE_DOT:
01126 dash_path.add_dash( 0.25*scale, 1.5*scale);
01127 break;
01128 case a2dSTROKE_DOT_DASH:
01129 dash_path.add_dash( 0.25*scale, 1.5*scale);
01130 dash_path.add_dash(2.0*scale, 2.0*scale);
01131 break;
01132 case a2dSTROKE_LONG_DASH:
01133 dash_path.add_dash(2.0*scale, 2.0*scale);
01134 break;
01135 case a2dSTROKE_SHORT_DASH:
01136 dash_path.add_dash( 2.0*scale, 2.0*scale);
01137 break;
01138
01139
01140 }
01141
01142 stroke.line_join(m_join);
01143 stroke.line_cap(m_cap);
01144
01145 stroke.width( m_strokewidthDev );
01146 m_rasterizer.reset();
01147 m_rasterizer.add_path(stroke);
01148 }
01149
01150 }
01151 }
01152
01153 void a2dAggDrawerBase::DrawCircle( double x, double y, double radius )
01154 {
01155 if ( m_disableDrawing )
01156 return;
01157
01158 DrawEllipse( x, y, radius*2, radius*2 );
01159 }
01160
01161 void a2dAggDrawerBase::DrawPoint( double xc, double yc )
01162 {
01163 if ( m_disableDrawing )
01164 return;
01165
01166 m_usertodevice.TransformPoint( xc, yc, xc, yc );
01167 DeviceDrawPixel( (int) xc, (int) yc, m_colour1redStroke, m_colour1greenStroke, m_colour1blueStroke, m_StrokeOpacityCol1 );
01168 }
01169
01170 void a2dAggDrawerBase::DrawCharDc( wxChar c )
01171 {
01172 #if wxART2D_USE_FREETYPE && defined(__USE_WINAPI__)
01173 if ( m_currentfont.GetType() == a2dFONT_WXDC && m_currentfont.GetFreetypeFont().Ok() )
01174 {
01175 a2dFont oldfont = m_currentfont;
01176 m_currentfont = m_currentfont.GetFreetypeFont();
01177 DrawCharFreetype( c );
01178 m_currentfont = oldfont;
01179 }
01180 else
01181 a2dDrawer2D::DrawCharDc( c );
01182 #else // wxART2D_USE_FREETYPE && defined(__USE_WINAPI__)
01183 a2dDrawer2D::DrawCharDc( c );
01184 #endif // wxART2D_USE_FREETYPE && defined(__USE_WINAPI__)
01185 }
01186
01187 void a2dAggDrawerBase::DrawRoundedRectangle( double x, double y, double width, double height, double radius, bool pixelsize )
01188 {
01189 if ( m_disableDrawing )
01190 return;
01191
01192 if ( width == 0 || height == 0 )
01193 return;
01194
01195 if ( pixelsize )
01196 {
01197 width = DeviceToWorldXRel(width);
01198 height = DeviceToWorldYRel(height);
01199 radius = DeviceToWorldXRel(radius);
01200 if(m_yaxis)
01201 height = -height;
01202 }
01203
01204 if ( !IsStrokeOnly() )
01205 {
01206 agg::trans_affine mtx = _get_agg_user_to_device_transform();
01207
01208 if ( fabs(radius) <= 0.00000001 )
01209 {
01210 plain_rect r( x, y, x+width, y+height );
01211 agg::conv_transform<plain_rect> tr(r, mtx);
01212 m_rasterizer.reset();
01213 m_rasterizer.add_path( tr );
01214 }
01215 else
01216 {
01217 agg::rounded_rect r( x, y, x+width, y+height, radius );
01218 r.normalize_radius();
01219 agg::conv_transform<agg::rounded_rect> tr(r, mtx);
01220 m_rasterizer.reset();
01221 m_rasterizer.add_path( tr );
01222 }
01223
01224 if ( m_activefill.GetType() == a2dFILL_GRADIENT_FILL_LINEAR )
01225 {
01226 RenderGradient( false );
01227 }
01228 else if ( m_activefill.GetType() == a2dFILL_GRADIENT_FILL_RADIAL )
01229 {
01230 RenderGradient( true );
01231 }
01232 else if ( m_activefill.GetType() == a2dFILL_BITMAP ||
01233 (m_activefill.GetStyle() >= a2dFIRST_HATCH && m_activefill.GetStyle() <= a2dLAST_HATCH ) ||
01234 (m_activefill.GetStyle() >= a2dFIRST_TWOCOL_HATCH && m_activefill.GetStyle() <= a2dLAST_TWOCOL_HATCH ) )
01235 {
01236 RenderBitmapFill();
01237 }
01238 else
01239 {
01240 Render( true );
01241 }
01242 }
01243
01244 if ( IsStroked() )
01245 {
01246 if ( fabs(radius) <= 0.00000001 )
01247 {
01248 plain_rect r( x, y, x+width, y+height );
01249 agg::trans_affine mtx = _get_agg_user_to_device_transform();
01250 m_rasterizer.reset();
01251 _ras_add_stroked_path_xform( r, mtx );
01252 }
01253 else
01254 {
01255 m_rasterizer.reset();
01256 agg::rounded_rect r( x, y, x+width, y+height, radius );
01257 r.normalize_radius();
01258 agg::trans_affine mtx = _get_agg_user_to_device_transform();
01259 _ras_add_stroked_path_xform( r, mtx );
01260 }
01261 Render(false);
01262 }
01263 }
01264
01265 void a2dAggDrawerBase::DrawEllipse( double xc, double yc, double width, double height )
01266 {
01267 if ( m_disableDrawing )
01268 return;
01269
01270 double dphi;
01271 unsigned int segments;
01272
01273
01274 double radiusDev = m_usertodevice.TransformDistance( wxMax( width, height ) );
01275 Aberration( m_displayaberration, wxPI*2, radiusDev , dphi, segments );
01276
01277 agg::trans_affine mtx = _get_agg_user_to_device_transform();
01278
01279 agg::ellipse ellipse( xc, yc, width/2.0, height/2.0, segments );
01280
01281 agg::conv_transform<agg::ellipse> tr(ellipse, mtx);
01282
01283 if ( !IsStrokeOnly() )
01284 {
01285 m_path.remove_all();
01286 m_path.concat_path(tr,0);
01287
01288 m_rasterizer.reset();
01289 m_rasterizer.add_path( m_path );
01290
01291 if ( m_activefill.GetType() == a2dFILL_GRADIENT_FILL_LINEAR )
01292 {
01293 RenderGradient( false );
01294 }
01295 else if ( m_activefill.GetType() == a2dFILL_GRADIENT_FILL_RADIAL )
01296 {
01297 RenderGradient( true );
01298 }
01299 else if ( m_activefill.GetType() == a2dFILL_BITMAP ||
01300 (m_activefill.GetStyle() >= a2dFIRST_HATCH && m_activefill.GetStyle() <= a2dLAST_HATCH ) ||
01301 (m_activefill.GetStyle() >= a2dFIRST_TWOCOL_HATCH && m_activefill.GetStyle() <= a2dLAST_TWOCOL_HATCH ) )
01302 {
01303 RenderBitmapFill();
01304 }
01305 else
01306 Render( true );
01307 }
01308 if ( IsStroked() )
01309 {
01310 m_rasterizer.reset();
01311 _ras_add_stroked_path_xform( ellipse, mtx );
01312 Render( false );
01313 }
01314 }
01315
01316 void a2dAggDrawerBase::DrawPolygon( a2dVertexArray *array, bool spline, wxPolygonFillMode fillStyle )
01317 {
01318 if ( m_disableDrawing )
01319 return;
01320
01321 int segments;
01322 if ( spline )
01323 {
01324 a2dVertexArray* splinedlist = array->ConvertSplinedPolyline( m_splineaberration );
01325 segments = ToAggPath( splinedlist, false );
01326 delete splinedlist;
01327 }
01328 else
01329 segments = ToAggPath( array, false );
01330
01331 if ( segments == 0 )
01332 return;
01333
01334 agg::trans_affine mtx = _get_agg_user_to_device_transform();
01335 if ( IsStrokeOnly() )
01336 {
01337 }
01338 else if ( m_activefill.GetType() == a2dFILL_GRADIENT_FILL_LINEAR )
01339 {
01340 m_path.close_polygon();
01341 agg::conv_transform<agg::path_storage> tr( m_path, mtx );
01342 m_rasterizer.reset();
01343 m_rasterizer.add_path( tr );
01344
01345 RenderGradient( false );
01346 }
01347 else if ( m_activefill.GetType() == a2dFILL_GRADIENT_FILL_RADIAL )
01348 {
01349 m_path.close_polygon();
01350 agg::conv_transform<agg::path_storage> tr( m_path, mtx );
01351 m_rasterizer.reset();
01352 m_rasterizer.add_path( tr );
01353
01354 RenderGradient( true );
01355 }
01356 else if ( m_activefill.GetType() == a2dFILL_BITMAP ||
01357 (m_activefill.GetStyle() >= a2dFIRST_HATCH && m_activefill.GetStyle() <= a2dLAST_HATCH ) ||
01358 (m_activefill.GetStyle() >= a2dFIRST_TWOCOL_HATCH && m_activefill.GetStyle() <= a2dLAST_TWOCOL_HATCH ) )
01359 {
01360 m_path.close_polygon();
01361 agg::conv_transform<agg::path_storage> tr( m_path, mtx );
01362 m_rasterizer.reset();
01363 m_rasterizer.add_path( tr );
01364
01365 RenderBitmapFill();
01366 }
01367 else
01368 {
01369 m_path.close_polygon();
01370 agg::conv_transform<agg::path_storage> tr( m_path, mtx );
01371 m_rasterizer.reset();
01372 m_rasterizer.add_path( tr );
01373
01374 Render( true );
01375 }
01376
01377 if ( IsStroked() )
01378 {
01379 m_rasterizer.reset();
01380 m_path.close_polygon();
01381 _ras_add_stroked_path_xform( m_path, mtx );
01382
01383 Render( false );
01384 }
01385 }
01386
01387 void a2dAggDrawerBase::DrawPolygon( const a2dVertexList *list, bool spline, wxPolygonFillMode fillStyle )
01388 {
01389 if ( m_disableDrawing )
01390 return;
01391
01392 int segments;
01393 if ( spline )
01394 {
01395 a2dVertexList* splinedlist = list->ConvertSplinedPolygon( m_splineaberration );
01396 segments = ToAggPath( splinedlist, false );
01397 delete splinedlist;
01398 }
01399 else
01400 segments = ToAggPath( list, false );
01401
01402 if ( segments == 0 )
01403 return;
01404
01405 agg::trans_affine mtx = _get_agg_user_to_device_transform();
01406 if ( IsStrokeOnly() )
01407 {
01408 }
01409 else if ( m_activefill.GetType() == a2dFILL_GRADIENT_FILL_LINEAR )
01410 {
01411 m_path.close_polygon();
01412 agg::conv_transform<agg::path_storage> tr( m_path, mtx );
01413 m_rasterizer.reset();
01414 m_rasterizer.add_path( tr );
01415
01416 RenderGradient( false );
01417 }
01418 else if ( m_activefill.GetType() == a2dFILL_GRADIENT_FILL_RADIAL )
01419 {
01420 m_path.close_polygon();
01421 agg::conv_transform<agg::path_storage> tr( m_path, mtx );
01422 m_rasterizer.reset();
01423 m_rasterizer.add_path( tr );
01424
01425 RenderGradient( true );
01426 }
01427 else if ( m_activefill.GetType() == a2dFILL_BITMAP ||
01428 (m_activefill.GetStyle() >= a2dFIRST_HATCH && m_activefill.GetStyle() <= a2dLAST_HATCH ) ||
01429 (m_activefill.GetStyle() >= a2dFIRST_TWOCOL_HATCH && m_activefill.GetStyle() <= a2dLAST_TWOCOL_HATCH ) )
01430 {
01431 m_path.close_polygon();
01432
01433 agg::conv_transform<agg::path_storage> tr( m_path, mtx );
01434 m_rasterizer.reset();
01435 m_rasterizer.add_path( tr );
01436
01437 RenderBitmapFill();
01438 }
01439 else
01440 {
01441 m_path.close_polygon();
01442
01443 agg::conv_transform<agg::path_storage> tr( m_path, mtx );
01444 m_rasterizer.reset();
01445 m_rasterizer.add_path( tr );
01446
01447 Render( true );
01448 }
01449
01450 if ( IsStroked() )
01451 {
01452 m_rasterizer.reset();
01453 m_path.close_polygon();
01454 _ras_add_stroked_path_xform( m_path, mtx );
01455 Render( false );
01456 }
01457 }
01458
01459 void a2dAggDrawerBase::DrawPolyPolygon( a2dListOfa2dVertexList polylist, wxPolygonFillMode fillStyle )
01460 {
01461 if ( m_disableDrawing )
01462 return;
01463
01464 for( a2dListOfa2dVertexList::iterator iterp = polylist.begin(); iterp != polylist.end(); iterp++ )
01465 {
01466 DrawPolygon( *iterp, false, fillStyle );
01467 }
01468 }
01469
01470 void a2dAggDrawerBase::DrawLines( const a2dVertexList* list, bool spline )
01471 {
01472 if ( m_disableDrawing )
01473 return;
01474
01475 int segments;
01476 if ( spline )
01477 {
01478 a2dVertexList* splinedlist = list->ConvertSplinedPolyline( m_splineaberration );
01479 segments = ToAggPath( splinedlist, false );
01480 delete splinedlist;
01481 }
01482 else
01483 segments = ToAggPath( list, false );
01484
01485 if ( segments == 0 )
01486 return;
01487
01488 agg::trans_affine mtx = _get_agg_user_to_device_transform();
01489 m_rasterizer.reset();
01490 _ras_add_stroked_path_xform( m_path, mtx );
01491 Render( false );
01492 }
01493
01494 void a2dAggDrawerBase::DrawLines( a2dVertexArray* array, bool spline )
01495 {
01496 if ( m_disableDrawing )
01497 return;
01498
01499 int segments;
01500 if ( spline )
01501 {
01502 a2dVertexArray* splinedlist = array->ConvertSplinedPolyline( m_splineaberration );
01503 segments = ToAggPath( splinedlist, false );
01504 delete splinedlist;
01505 }
01506 else
01507 segments = ToAggPath( array, false );
01508
01509 if ( segments == 0 )
01510 return;
01511
01512 agg::trans_affine mtx = _get_agg_user_to_device_transform();
01513 m_rasterizer.reset();
01514 _ras_add_stroked_path_xform( m_path, mtx );
01515 Render( false );
01516 }
01517
01518 void a2dAggDrawerBase::DrawCharFreetype( wxChar c )
01519 {
01520 double x, y;
01521 x = y = 0.0;
01522
01523 if ( m_disableDrawing )
01524 return;
01525
01526 #if wxART2D_USE_FREETYPE
01527 y += m_currentfont.GetDescent();
01528
01529 agg::path_storage path;
01530 double scale = m_currentfont.GetSize() / (64 * FTNORMFONT);
01531
01532 FT_Glyph glyph = m_currentfont.GetGlyphFreetype( c )->m_glyph;
01533 if (glyph->format != FT_GLYPH_FORMAT_OUTLINE)
01534 return;
01535 FT_Outline& outline = ((FT_OutlineGlyph) glyph)->outline;
01536
01537 FT_Vector v_last;
01538 FT_Vector v_control;
01539 FT_Vector v_start;
01540
01541 FT_Vector* point;
01542 FT_Vector* limit;
01543 char* tags;
01544
01545 int n;
01546 int first;
01547 char tag;
01548
01549 first = 0;
01550
01551 for(n = 0; n < outline.n_contours; n++)
01552 {
01553 int last;
01554
01555 last = outline.contours[n];
01556 limit = outline.points + last;
01557
01558 v_start = outline.points[first];
01559 v_last = outline.points[last];
01560
01561 v_control = v_start;
01562
01563 point = outline.points + first;
01564 tags = outline.tags + first;
01565 tag = FT_CURVE_TAG(tags[0]);
01566
01567
01568 if(tag == FT_CURVE_TAG_CUBIC) return;
01569
01570
01571 if( tag == FT_CURVE_TAG_CONIC)
01572 {
01573
01574 if(FT_CURVE_TAG(outline.tags[last]) == FT_CURVE_TAG_ON)
01575 {
01576
01577 v_start = v_last;
01578 limit--;
01579 }
01580 else
01581 {
01582
01583
01584
01585 v_start.x = (v_start.x + v_last.x) / 2;
01586 v_start.y = (v_start.y + v_last.y) / 2;
01587
01588 v_last = v_start;
01589 }
01590 point--;
01591 tags--;
01592 }
01593
01594 path.move_to( v_start.x, v_start.y);
01595
01596 while(point < limit)
01597 {
01598 point++;
01599 tags++;
01600
01601 tag = FT_CURVE_TAG(tags[0]);
01602 switch(tag)
01603 {
01604 case FT_CURVE_TAG_ON:
01605 {
01606 path.line_to( point->x, point->y );
01607 continue;
01608 }
01609
01610 case FT_CURVE_TAG_CONIC:
01611 {
01612 v_control.x = point->x;
01613 v_control.y = point->y;
01614
01615 Do_Conic:
01616 if(point < limit)
01617 {
01618 FT_Vector vec;
01619 FT_Vector v_middle;
01620
01621 point++;
01622 tags++;
01623 tag = FT_CURVE_TAG(tags[0]);
01624
01625 vec.x = point->x;
01626 vec.y = point->y;
01627
01628 if(tag == FT_CURVE_TAG_ON)
01629 {
01630 path.curve3( v_control.x, v_control.y, vec.x, vec.y );
01631 continue;
01632 }
01633
01634 if(tag != FT_CURVE_TAG_CONIC) return;
01635
01636 v_middle.x = (v_control.x + vec.x) / 2;
01637 v_middle.y = (v_control.y + vec.y) / 2;
01638
01639 path.curve3( v_control.x, v_control.y, v_middle.x, v_middle.y );
01640
01641 v_control = vec;
01642 goto Do_Conic;
01643 }
01644 path.curve3( v_control.x, v_control.y, v_start.x, v_start.y );
01645 goto Close;
01646 }
01647
01648 default:
01649 {
01650 FT_Vector vec1, vec2;
01651
01652 if(point + 1 > limit || FT_CURVE_TAG(tags[1]) != FT_CURVE_TAG_CUBIC)
01653 {
01654 return;
01655 }
01656
01657 vec1.x = point[0].x;
01658 vec1.y = point[0].y;
01659 vec2.x = point[1].x;
01660 vec2.y = point[1].y;
01661
01662 point += 2;
01663 tags += 2;
01664
01665 if(point <= limit)
01666 {
01667 FT_Vector vec;
01668
01669 vec.x = point->x;
01670 vec.y = point->y;
01671
01672 path.curve4( vec1.x, vec1.y, vec2.x, vec2.y, vec.x, vec.y );
01673 continue;
01674 }
01675
01676 path.curve4( vec1.x, vec1.y, vec2.x, vec2.y, v_start.x, v_start.y );
01677 goto Close;
01678 }
01679 }
01680 }
01681
01682 path.close_polygon();
01683
01684 Close:
01685 first = last + 1;
01686 }
01687
01688
01689 a2dAffineMatrix affine;
01690 affine.Scale( scale );
01691 affine.Translate( x, y );
01692 affine = GetUserToDeviceTransform() * affine;
01693
01694 agg::trans_affine mtx(affine.GetValue(0,0), affine.GetValue(0,1),
01695 affine.GetValue(1,0), affine.GetValue(1,1),
01696 affine.GetValue(2,0), affine.GetValue(2,1) );
01697 agg::conv_transform< agg::path_storage > tr( path, mtx );
01698 agg::conv_curve< agg::conv_transform< agg::path_storage > > stroke( tr );
01699
01700 m_rasterizer.reset();
01701 m_rasterizer.add_path( stroke );
01702
01703 Render( false );
01704 #else // wxART2D_USE_FREETYPE
01705 a2dDrawer2D::DrawCharFreetype( c );
01706 #endif // wxART2D_USE_FREETYPE
01707 }
01708
01709 void a2dAggDrawerBase::DrawCharStroke( wxChar c )
01710 {
01711 agg::path_storage path;
01712 double size = m_currentfont.GetSize();
01713 a2dVertexList** ptr = m_currentfont.GetGlyphStroke(c);
01714 if (ptr)
01715 {
01716 while (*ptr)
01717 {
01718 a2dVertexList::iterator iter = (*ptr)->begin();
01719 if ( (*ptr)->size() )
01720 {
01721 a2dPoint2D point = (*iter)->GetPoint();
01722 path.move_to( point.m_x * size, point.m_y * size );
01723 iter++;
01724 }
01725 while ( iter != (*ptr)->end() )
01726 {
01727 a2dPoint2D point = (*iter)->GetPoint();
01728 path.line_to( point.m_x * size, point.m_y * size );
01729 iter++;
01730 }
01731 ptr++;
01732 }
01733 }
01734
01735
01736 agg::trans_affine mtx(GetUserToDeviceTransform().GetValue(0,0), GetUserToDeviceTransform().GetValue(0,1),
01737 GetUserToDeviceTransform().GetValue(1,0), GetUserToDeviceTransform().GetValue(1,1),
01738 GetUserToDeviceTransform().GetValue(2,0), GetUserToDeviceTransform().GetValue(2,1) );
01739 agg::conv_transform< agg::path_storage > tr( path, mtx );
01740 agg::conv_stroke< agg::conv_transform< agg::path_storage > > stroke( tr );
01741
01742 stroke.line_join( m_join );
01743 stroke.line_cap( m_cap );
01744 stroke.width( m_currentfont.GetStrokeWidth() * GetMappingMatrix()( 0, 0 ) );
01745 m_rasterizer.reset();
01746 m_rasterizer.add_path( stroke );
01747
01748 Render( true );
01749 }
01750
01751
01752
01753
01754
01755
01756
01757 IMPLEMENT_DYNAMIC_CLASS(a2dAggDrawerRgba, a2dAggDrawerBase)
01758
01759 void a2dAggDrawerRgba::Render( bool fillColor )
01760 {
01761 if ( fillColor )
01762 {
01763 agg::rgba8 colorfill( m_colour1redFill, m_colour1greenFill, m_colour1blueFill, m_FillOpacityCol1 );
01764 m_renderer.color( colorfill );
01765 m_renSolidComp.color( colorfill );
01766 }
01767 else
01768 {
01769 agg::rgba8 colorstroke( m_colour1redStroke, m_colour1greenStroke, m_colour1blueStroke, m_StrokeOpacityCol1 );
01770 m_renderer.color( colorstroke );
01771 m_renSolidComp.color( colorstroke );
01772 }
01773
01774 if(m_blendMode == agg::end_of_comp_op_e)
01775 agg::render_scanlines(m_rasterizer, m_sl, m_renderer);
01776 else
01777 agg::render_scanlines(m_rasterizer, m_sl, m_renSolidComp);
01778 }
01779
01780 void a2dAggDrawerRgba::RenderGradient( bool radial )
01781 {
01782 if ( !radial )
01783 {
01784 span_allocator_type aggallocator;
01785 LinearGradientSpan span(
01786 m_fillGradientInterpolator,
01787 m_linearGradientFunction,
01788 m_fillGradient,
01789 m_fillGradientD1,
01790 m_fillGradientD2);
01791 RendererLinearGradientA ren( m_renBase, aggallocator, span );
01792 RendererLinearGradientComp renComp( m_renBaseComp, aggallocator, span );
01793
01794 if(m_blendMode == agg::end_of_comp_op_e)
01795 agg::render_scanlines(m_rasterizer, m_sl, ren );
01796 else
01797 agg::render_scanlines(m_rasterizer, m_sl, renComp );
01798 }
01799 else
01800 {
01801 span_allocator_type aggallocator;
01802 RadialGradientSpan span(
01803 m_fillGradientInterpolator,
01804 m_radialGradientFunction,
01805 m_fillGradient,
01806 m_fillGradientD1,
01807 m_fillGradientD2);
01808 RendererRadialGradientA ren( m_renBase, aggallocator, span );
01809 RendererRadialGradientComp renComp( m_renBaseComp, aggallocator, span );
01810
01811 if(m_blendMode == agg::end_of_comp_op_e)
01812 agg::render_scanlines(m_rasterizer, m_sl, ren );
01813 else
01814 agg::render_scanlines(m_rasterizer, m_sl, renComp );
01815
01816 }
01817 }
01818
01819 void a2dAggDrawerRgba::RenderBitmapFill()
01820 {
01821 unsigned offset_x = 0;
01822 unsigned offset_y = 0;
01823
01824
01825
01826 typedef agg::wrap_mode_repeat wrap_x_type;
01827 typedef agg::wrap_mode_repeat wrap_y_type;
01828
01829 typedef agg::image_accessor_wrap<PixFormat, wrap_x_type, wrap_y_type> img_source_type;
01830 typedef agg::span_pattern_a2d<img_source_type> span_gen_type;
01831 typedef agg::span_allocator<color_type> span_alloc_type;
01832
01833 typedef agg::renderer_scanline_aa<RendererBaseA, span_alloc_type, span_gen_type> renderer_type;
01834
01835 PixFormat img_pixf( m_pattern_rbuf );
01836 img_source_type img_src(img_pixf);
01837 span_gen_type sg(img_src, offset_x, offset_y);
01838
01839 sg.alpha(span_gen_type::value_type( m_FillOpacityCol1 ));
01840
01841 span_alloc_type sa;
01842 renderer_type rp( m_renBase, sa, sg);
01843
01844 agg::render_scanlines(m_rasterizer, m_sl, rp);
01845 }
01846
01847 void a2dAggDrawerRgba::RenderSetClip()
01848 {
01849 m_renBase.clip_box( m_clipboxdev.x, m_clipboxdev.y, m_clipboxdev.x + m_clipboxdev.width, m_clipboxdev.y + m_clipboxdev.height);
01850 m_renBaseComp.clip_box( m_clipboxdev.x, m_clipboxdev.y, m_clipboxdev.x + m_clipboxdev.width, m_clipboxdev.y + m_clipboxdev.height);
01851 m_rasterizer.clip_box( 0, 0, m_width, m_height );
01852 }
01853
01854 a2dAggDrawerRgba::a2dAggDrawerRgba( const wxSize& size ):
01855 m_rendering_buffer(),
01856 m_pixFormat(m_rendering_buffer),
01857 m_pixFormatComp(m_rendering_buffer),
01858 m_renBase(m_pixFormat),
01859 m_renBaseComp(m_pixFormatComp),
01860 m_renderer(m_renBase),
01861 m_renSolidComp(m_renBaseComp),
01862
01863 a2dAggDrawerBase( size )
01864 {
01865 m_buffer = a2dImageRGBA( m_width,m_height );
01866 m_ownsBuffer = true;
01867 m_preStroke = false;
01868
01869 m_pdata = m_buffer.GetData();
01870 m_rendering_buffer.attach(m_pdata, m_width, m_height, m_width*4);
01871 DestroyClippingRegion();
01872 }
01873
01874 a2dAggDrawerRgba::a2dAggDrawerRgba( int width, int height ):
01875 m_rendering_buffer(),
01876 m_pixFormat(m_rendering_buffer),
01877 m_pixFormatComp(m_rendering_buffer),
01878 m_renBase(m_pixFormat),
01879 m_renBaseComp(m_pixFormatComp),
01880 m_renderer(m_renBase),
01881 m_renSolidComp(m_renBaseComp),
01882
01883 a2dAggDrawerBase( width, height )
01884 {
01885 if ( width == 0 || height == 0 )
01886 m_buffer = a2dImageRGBA( 100, 100 );
01887 else
01888 m_buffer = a2dImageRGBA( width, height );
01889 m_ownsBuffer = true;
01890 m_pdata = m_buffer.GetData();
01891 m_rendering_buffer.attach(m_pdata, m_width, m_height, m_width*4);
01892 m_pixFormatComp.premultiply();
01893 DestroyClippingRegion();
01894 m_preStroke = false;
01895 }
01896
01897
01898 a2dAggDrawerRgba::a2dAggDrawerRgba( const a2dAggDrawerRgba& other):
01899 m_rendering_buffer(),
01900 m_pixFormat(m_rendering_buffer),
01901 m_pixFormatComp(m_rendering_buffer),
01902 m_renBase(m_pixFormat),
01903 m_renBaseComp(m_pixFormatComp),
01904 m_renderer(m_renBase),
01905 m_renSolidComp(m_renBaseComp),
01906
01907 a2dAggDrawerBase( other )
01908 {
01909 m_ownsBuffer = false;
01910 m_width = other.m_width;
01911 m_height = other.m_height;
01912 m_buffer = other.m_buffer;
01913 m_preStroke = other.m_preStroke;
01914 }
01915
01916
01917 a2dAggDrawerRgba::a2dAggDrawerRgba( const wxBitmap& bitmap ):
01918 m_rendering_buffer(),
01919 m_pixFormat(m_rendering_buffer),
01920 m_pixFormatComp(m_rendering_buffer),
01921 m_renBase(m_pixFormat),
01922 m_renBaseComp(m_pixFormatComp),
01923 m_renderer(m_renBase),
01924 m_renSolidComp(m_renBaseComp),
01925
01926 a2dAggDrawerBase( bitmap.GetWidth(), bitmap.GetHeight() )
01927 {
01928 wxImage image = bitmap.ConvertToImage();
01929 m_buffer = a2dImageRGBA( image );
01930 m_ownsBuffer = true;
01931 m_pdata = m_buffer.GetData();
01932 m_rendering_buffer.attach(m_pdata, m_width, m_height, m_width*4);
01933 DestroyClippingRegion();
01934 m_preStroke = false;
01935 }
01936
01937
01938 a2dAggDrawerRgba::~a2dAggDrawerRgba()
01939 {
01940 }
01941
01942 wxImage a2dAggDrawerRgba::GetImageBuffer() const
01943 {
01944 wxImage image = m_buffer.GetImage();
01945 return image;
01946 }
01947
01948 void a2dAggDrawerRgba::SetBufferSize( int w, int h )
01949 {
01950 a2dImageRGBA newbuf( w, h );
01951
01952 int old_pixelwidth = m_width * 4;
01953 int new_pixelwidth = w * 4;
01954 int pixelwidth = wxMin( w, m_width) *4;
01955 int minheight = wxMin( h, m_height);
01956
01957
01958 unsigned char* oldpdata = m_pdata;
01959 unsigned char* newpdata = newbuf.GetData();
01960
01961 for (int yp = 0; yp < minheight; yp++)
01962 {
01963 memcpy( newpdata, oldpdata, pixelwidth);
01964 oldpdata += old_pixelwidth;
01965 newpdata += new_pixelwidth;
01966 }
01967
01968 m_width = w;
01969 m_height = h;
01970 m_buffer = newbuf;
01971
01972 m_pdata = m_buffer.GetData();
01973 m_rendering_buffer.attach(m_pdata, m_width, m_height, m_width*4);
01974 m_pixFormatComp.premultiply();
01975 DestroyClippingRegion();
01976 }
01977
01978 wxBitmap a2dAggDrawerRgba::GetBuffer() const
01979 {
01980 return wxBitmap( m_buffer.GetImage() );
01981 }
01982
01983 wxBitmap a2dAggDrawerRgba::GetSubBitmap( wxRect rect ) const
01984 {
01985 return wxBitmap( m_buffer.GetImage().GetSubImage(rect) );
01986 }
01987
01988 void a2dAggDrawerRgba::CopyIntoBuffer( const wxBitmap& bitm )
01989 {
01990 m_buffer = a2dImageRGBA( bitm.ConvertToImage() );
01991 }
01992
01993 void a2dAggDrawerRgba::DoSetDrawStyle( a2dDrawStyle drawstyle )
01994 {
01995 a2dAggDrawerBase::DoSetDrawStyle( drawstyle );
01996 m_pixFormatComp.comp_op( m_blendMode );
01997 }
01998
01999 void a2dAggDrawerRgba::DrawImage( const wxImage& image, double x, double y, double width, double height, wxUint8 Opacity )
02000 {
02001 if ( m_disableDrawing )
02002 return;
02003 int imagew=image.GetWidth();
02004 int imageh=image.GetHeight();
02005
02006 agg::trans_affine mtxi;
02007 mtxi *= agg::trans_affine_scaling( width/imagew, height/imageh );
02008 mtxi *= agg::trans_affine_translation( x-width/2, y-height/2 );
02009
02010
02011
02012
02013 const a2dAffineMatrix &r2d = GetUserToDeviceTransform();
02014 agg::trans_affine mtx(
02015 r2d.GetValue(0,0), r2d.GetValue(0,1),
02016 r2d.GetValue(1,0), r2d.GetValue(1,1),
02017 r2d.GetValue(2,0), r2d.GetValue(2,1)
02018 );
02019 mtxi *= mtx;
02020 mtxi.invert();
02021
02022 typedef agg::span_allocator<agg::rgba8> span_alloc_type;
02023
02024 span_alloc_type sa;
02025 typedef agg::image_accessor_clip<PixFormat> img_source_type;
02026 typedef agg::span_interpolator_linear<> interpolator_type;
02027 interpolator_type interpolator(mtxi);
02028
02029 typedef agg::span_image_filter_rgb_bilinear<img_source_type, interpolator_type> span_gen_type;
02030
02031
02032 typedef agg::span_converter<span_gen_type, span_conv_const_alpha_rgba8> span_conv;
02033
02034 agg::rendering_buffer image_buffer;
02035 image_buffer.attach( image.GetData(), imagew, imageh, ( m_yaxis ) ? -imagew*3: imagew*3 );
02036 PixFormat img_pixf(image_buffer);
02037 img_source_type img_src(img_pixf, agg::rgba(1,1,1,0));
02038
02039 span_gen_type sg(img_src, interpolator);
02040
02041
02042
02043
02044
02045
02046
02047
02048
02049
02050
02051
02052
02053
02054
02055
02056
02057 agg::rounded_rect er(x-width/2, y-height/2 ,x+width/2, y+height/2, 0);
02058 er.normalize_radius();
02059 agg::conv_transform<agg::rounded_rect> tr(er, mtx);
02060 m_rasterizer.reset();
02061 m_rasterizer.add_path(tr);
02062
02063 wxUint8 OpacityFactor = (m_OpacityFactor * Opacity)/255;
02064
02065
02066 if ( 1 )
02067 {
02068 span_conv_const_alpha_rgba8 color_alpha( OpacityFactor );
02069 span_conv sc(sg, color_alpha);
02070 typedef agg::renderer_scanline_aa<RendererBaseA, span_alloc_type, span_conv> renderer_type_alpha;
02071 renderer_type_alpha ri(m_renBase, sa, sc);
02072
02073 agg::render_scanlines(m_rasterizer, m_sl, ri);
02074 }
02075 else
02076 {
02077 typedef agg::renderer_scanline_bin<RendererBaseA, span_alloc_type, span_gen_type> renderer_type_normal;
02078 renderer_type_normal ri(m_renBase, sa, sg);
02079 agg::render_scanlines(m_rasterizer, m_sl, ri);
02080 }
02081 }
02082
02083 void a2dAggDrawerRgba::DrawImage( const a2dImageRGBA& image, double x, double y, double width, double height, wxUint8 Opacity )
02084 {
02085 if ( m_disableDrawing )
02086 return;
02087
02088 int imagew = image.GetWidth();
02089 int imageh = image.GetHeight();
02090
02091 agg::trans_affine mtxi;
02092 mtxi *= agg::trans_affine_scaling( width/imagew, height/imageh );
02093 mtxi *= agg::trans_affine_translation( x, y );
02094
02095 const a2dAffineMatrix &r2d = GetUserToDeviceTransform();
02096 agg::trans_affine mtx(
02097 r2d.GetValue(0,0), r2d.GetValue(0,1),
02098 r2d.GetValue(1,0), r2d.GetValue(1,1),
02099 r2d.GetValue(2,0), r2d.GetValue(2,1)
02100 );
02101 mtxi *= mtx;
02102 mtxi.invert();
02103
02104 typedef agg::span_allocator<agg::rgba8> span_alloc_type;
02105 span_alloc_type sa;
02106 typedef agg::image_accessor_clip<agg::pixfmt_rgba32> img_source_type;
02107 typedef agg::span_interpolator_linear<> interpolator_type;
02108 interpolator_type interpolator(mtxi);
02109
02110 typedef agg::span_image_filter_rgba_nn<img_source_type, interpolator_type> span_gen_type;
02111
02112 typedef agg::span_converter<span_gen_type, span_conv_const_alpha_rgba8> span_conv;
02113
02114 agg::rendering_buffer image_buffer;
02115 image_buffer.attach( image.GetData(), imagew, imageh, imagew*4 );
02116 agg::pixfmt_rgba32 img_pixf(image_buffer);
02117 img_source_type img_src(img_pixf, agg::rgba(0,0,0,0));
02118
02119 span_gen_type sg(img_src, interpolator);
02120
02121
02122 agg::rounded_rect er(x, y ,x+width, y+height, 1);
02123 er.normalize_radius();
02124 agg::conv_transform<agg::rounded_rect> tr(er, mtx);
02125 m_rasterizer.reset();
02126 m_rasterizer.add_path(tr);
02127
02128 wxUint8 OpacityFactor = (m_OpacityFactor * Opacity)/255;
02129
02130
02131 if ( OpacityFactor != 255 )
02132 {
02133 span_conv_const_alpha_rgba8 color_alpha( OpacityFactor );
02134 span_conv sc(sg, color_alpha);
02135 typedef agg::renderer_scanline_aa<RendererBaseA, span_alloc_type, span_conv> renderer_type_alpha;
02136 renderer_type_alpha ri(m_renBase, sa, sc);
02137
02138 agg::render_scanlines(m_rasterizer, m_sl, ri);
02139 }
02140 else
02141 {
02142 typedef agg::renderer_scanline_bin<RendererBaseA, span_alloc_type, span_gen_type> renderer_type_normal;
02143 renderer_type_normal ri(m_renBase, sa, sg);
02144 agg::render_scanlines(m_rasterizer, m_sl, ri);
02145 }
02146 }
02147
02148 void a2dAggDrawerRgba::BlitBuffer( wxDC* dc, wxRect rect, const wxPoint& bufferpos )
02149 {
02150
02151 if (rect.x < 0)
02152 {
02153 rect.width += rect.x;
02154 rect.x = 0;
02155 }
02156 if (rect.width <= 0) return;
02157
02158 if (rect.y < 0)
02159 {
02160 rect.height += rect.y;
02161 rect.y = 0;
02162 }
02163 if (rect.height <= 0) return;
02164
02165 if (rect.x+rect.width >= m_width)
02166 rect.width = m_width - rect.x;
02167
02168 if (rect.width <= 0) return;
02169
02170 if (rect.y+rect.height >= m_height)
02171 rect.height = m_height - rect.y;
02172
02173 if (rect.height <= 0) return;
02174
02175 int xmax = rect.x + rect.width;
02176 int ymax = rect.y + rect.height;
02177
02178 a2dImageRGBA* subImage = m_buffer.GetSubImage(rect);
02179 wxBitmap subbitmap = subImage->CreateBitmap();
02180 delete subImage;
02181
02182 wxMemoryDC mdc;
02183 mdc.SelectObject( subbitmap );
02184
02185 dc->Blit( rect.x - bufferpos.x, rect.y - bufferpos.y, xmax-rect.x, ymax-rect.y, &mdc, 0, 0, wxCOPY, false );
02186
02187 mdc.SelectObject( wxNullBitmap );
02188 }
02189
02190 void a2dAggDrawerRgba::ShiftBuffer( int dxy, bool yshift )
02191 {
02192 ShiftBufferInternal( dxy, yshift, 4 );
02193 }
02194
02195
02196
02197
02198
02199 void a2dAggDrawer::Render( bool fillColor )
02200 {
02201 if ( fillColor )
02202 {
02203 agg::rgba8 colorfill( m_colour1redFill, m_colour1greenFill, m_colour1blueFill, m_FillOpacityCol1 );
02204 m_renderer.color( colorfill );
02205 }
02206 else
02207 {
02208 agg::rgba8 colorstroke( m_colour1redStroke, m_colour1greenStroke, m_colour1blueStroke, m_StrokeOpacityCol1 );
02209 m_renderer.color( colorstroke );
02210 }
02211 agg::render_scanlines(m_rasterizer, m_sl, m_renderer);
02212 }
02213
02214 void a2dAggDrawer::RenderGradient( bool radial )
02215 {
02216 if ( !radial )
02217 {
02218 span_allocator_type aggallocator;
02219 LinearGradientSpan span(
02220 m_fillGradientInterpolator,
02221 m_linearGradientFunction,
02222 m_fillGradient,
02223 m_fillGradientD1,
02224 m_fillGradientD2);
02225 RendererLinearGradient ren( m_renBase, aggallocator, span );
02226 agg::render_scanlines(m_rasterizer, m_sl, ren );
02227 }
02228 else
02229 {
02230 span_allocator_type aggallocator;
02231 RadialGradientSpan span(
02232 m_fillGradientInterpolator,
02233 m_radialGradientFunction,
02234 m_fillGradient,
02235 m_fillGradientD1,
02236 m_fillGradientD2);
02237 RendererRadialGradient ren( m_renBase, aggallocator, span );
02238 agg::render_scanlines(m_rasterizer, m_sl, ren );
02239 }
02240 }
02241
02242 void a2dAggDrawer::RenderBitmapFill()
02243 {
02244 unsigned offset_x = 0;
02245 unsigned offset_y = 0;
02246
02247
02248
02249 typedef agg::wrap_mode_repeat wrap_x_type;
02250 typedef agg::wrap_mode_repeat wrap_y_type;
02251
02252 typedef agg::image_accessor_wrap<PixFormat, wrap_x_type, wrap_y_type> img_source_type;
02253 typedef agg::span_pattern_a2d<img_source_type> span_gen_type;
02254 typedef agg::span_allocator<color_type> span_alloc_type;
02255
02256 typedef agg::renderer_scanline_aa<RendererBase, span_alloc_type, span_gen_type> renderer_type;
02257
02258 PixFormat img_pixf( m_pattern_rbuf );
02259 img_source_type img_src(img_pixf);
02260 span_gen_type sg(img_src, offset_x, offset_y);
02261
02262 sg.alpha(span_gen_type::value_type( m_FillOpacityCol1 ));
02263
02264 span_alloc_type sa;
02265 renderer_type rp( m_renBase, sa, sg);
02266
02267 agg::render_scanlines(m_rasterizer, m_sl, rp);
02268 }
02269
02270 void a2dAggDrawer::RenderSetClip()
02271 {
02272 m_renBase.clip_box( m_clipboxdev.x, m_clipboxdev.y, m_clipboxdev.x + m_clipboxdev.width, m_clipboxdev.y + m_clipboxdev.height);
02273 m_rasterizer.clip_box( 0, 0, m_width, m_height );
02274 }
02275
02276 IMPLEMENT_DYNAMIC_CLASS(a2dAggDrawer, a2dAggDrawerBase)
02277
02278 a2dAggDrawer::a2dAggDrawer( const wxSize& size ):
02279 m_rendering_buffer(),
02280 m_pixFormat(m_rendering_buffer),
02281 m_renBase(m_pixFormat),
02282 m_renderer(m_renBase),
02283
02284 a2dAggDrawerBase( size )
02285 {
02286 m_buffer = wxImage( m_width,m_height );
02287
02288 m_pdata = m_buffer.GetData();
02289 m_rendering_buffer.attach(m_pdata, m_width, m_height, m_width*3);
02290 DestroyClippingRegion();
02291 m_preStroke = false;
02292 }
02293
02294 a2dAggDrawer::a2dAggDrawer( int width, int height ):
02295 m_rendering_buffer(),
02296 m_pixFormat(m_rendering_buffer),
02297 m_renBase(m_pixFormat),
02298 m_renderer(m_renBase),
02299
02300 a2dAggDrawerBase( width, height )
02301 {
02302 if ( width == 0 || height == 0 )
02303 m_buffer = wxImage( 100, 100 );
02304 else
02305 m_buffer = wxImage( width, height );
02306
02307 m_pdata = m_buffer.GetData();
02308 m_rendering_buffer.attach(m_pdata, m_width, m_height, m_width*3);
02309 DestroyClippingRegion();
02310 m_preStroke = false;
02311 }
02312
02313 a2dAggDrawer::a2dAggDrawer( const a2dAggDrawer& other):
02314 m_rendering_buffer(),
02315 m_pixFormat(m_rendering_buffer),
02316 m_renBase(m_pixFormat),
02317 m_renderer(m_renBase),
02318
02319 a2dAggDrawerBase( other )
02320 {
02321 m_width = other.m_width;
02322 m_height = other.m_height;
02323 m_buffer = other.m_buffer;
02324 m_preStroke = other.m_preStroke;
02325 }
02326
02327 a2dAggDrawer::a2dAggDrawer( const wxBitmap& bitmap ):
02328 m_rendering_buffer(),
02329 m_pixFormat(m_rendering_buffer),
02330 m_renBase(m_pixFormat),
02331 m_renderer(m_renBase),
02332
02333 a2dAggDrawerBase( bitmap.GetWidth(), bitmap.GetHeight() )
02334 {
02335 m_buffer = bitmap.ConvertToImage();
02336 m_pdata = m_buffer.GetData();
02337 m_rendering_buffer.attach(m_pdata, m_width, m_height, m_width*3);
02338 DestroyClippingRegion();
02339 m_preStroke = false;
02340 }
02341
02342 a2dAggDrawer::~a2dAggDrawer()
02343 {
02344 }
02345
02346 void a2dAggDrawer::SetBufferSize( int w, int h )
02347 {
02348 wxImage newbuf = wxImage( w, h );
02349
02350 int old_pixelwidth = m_width * 3;
02351 int new_pixelwidth = w * 3;
02352 int pixelwidth = wxMin( w, m_width) * 3;
02353 int minheight = wxMin( h, m_height);
02354
02355
02356 unsigned char* oldpdata = m_pdata;
02357 unsigned char* newpdata = newbuf.GetData();
02358
02359 for (int yp = 0; yp < minheight; yp++)
02360 {
02361 memcpy( newpdata, oldpdata, pixelwidth);
02362 oldpdata += old_pixelwidth;
02363 newpdata += new_pixelwidth;
02364 }
02365
02366 m_width = w;
02367 m_height = h;
02368 m_buffer = newbuf;
02369
02370 m_pdata = m_buffer.GetData();
02371 m_rendering_buffer.attach(m_pdata, m_width, m_height, m_width*3);
02372
02373
02374
02375
02376
02377
02378
02379
02380
02381
02382 }
02383
02384 wxBitmap a2dAggDrawer::GetBuffer() const
02385 {
02386 return wxBitmap( m_buffer );
02387 }
02388
02389 wxBitmap a2dAggDrawer::GetSubBitmap( wxRect rect ) const
02390 {
02391 return wxBitmap( m_buffer.GetSubImage(rect) );
02392 }
02393
02394 void a2dAggDrawer::CopyIntoBuffer( const wxBitmap& bitm )
02395 {
02396 m_buffer = bitm.ConvertToImage();
02397 m_pdata = m_buffer.GetData();
02398 m_rendering_buffer.attach(m_pdata, m_width, m_height, m_width*3);
02399 DestroyClippingRegion();
02400 }
02401
02402 void a2dAggDrawer::DrawImage( const wxImage& image, double x, double y, double width, double height, wxUint8 Opacity )
02403 {
02404 if ( m_disableDrawing )
02405 return;
02406 int imagew=image.GetWidth();
02407 int imageh=image.GetHeight();
02408
02409 agg::trans_affine mtxi;
02410 mtxi *= agg::trans_affine_scaling( width/imagew, height/imageh );
02411 mtxi *= agg::trans_affine_translation( x-width/2, y-height/2 );
02412
02413
02414
02415
02416 const a2dAffineMatrix &r2d = GetUserToDeviceTransform();
02417 agg::trans_affine mtx(
02418 r2d.GetValue(0,0), r2d.GetValue(0,1),
02419 r2d.GetValue(1,0), r2d.GetValue(1,1),
02420 r2d.GetValue(2,0), r2d.GetValue(2,1)
02421 );
02422 mtxi *= mtx;
02423 mtxi.invert();
02424
02425 typedef agg::span_allocator<agg::rgba8> span_alloc_type;
02426
02427 span_alloc_type sa;
02428 typedef agg::image_accessor_clip<PixFormat> img_source_type;
02429 typedef agg::span_interpolator_linear<> interpolator_type;
02430 interpolator_type interpolator(mtxi);
02431
02432 typedef agg::span_image_filter_rgb_bilinear<img_source_type, interpolator_type> span_gen_type;
02433
02434
02435 typedef agg::span_converter<span_gen_type, span_conv_const_alpha_rgba8> span_conv;
02436
02437 typedef agg::renderer_scanline_aa<RendererBase, span_alloc_type, span_conv> renderer_type_alpha;
02438
02439 typedef agg::renderer_scanline_bin<RendererBase, span_alloc_type, span_gen_type> renderer_type_normal;
02440
02441 agg::rendering_buffer image_buffer;
02442 image_buffer.attach( image.GetData(), imagew, imageh, ( m_yaxis ) ? -imagew*3: imagew*3 );
02443 PixFormat img_pixf(image_buffer);
02444 img_source_type img_src(img_pixf, agg::rgba(1,1,1,0));
02445
02446 span_gen_type sg(img_src, interpolator);
02447
02448
02449
02450
02451
02452
02453
02454
02455
02456
02457
02458
02459
02460
02461
02462
02463
02464 agg::rounded_rect er(x-width/2, y-height/2 ,x+width/2, y+height/2, 0);
02465 er.normalize_radius();
02466 agg::conv_transform<agg::rounded_rect> tr(er, mtx);
02467 m_rasterizer.reset();
02468 m_rasterizer.add_path(tr);
02469
02470 wxUint8 OpacityFactor = (m_OpacityFactor * Opacity)/255;
02471
02472
02473 if ( image.HasAlpha() || OpacityFactor != 255 )
02474 {
02475 span_conv_const_alpha_rgba8 color_alpha( OpacityFactor );
02476
02477 span_conv sc(sg, color_alpha);
02478 renderer_type_alpha ri(m_renBase, sa, sc);
02479
02480 agg::render_scanlines(m_rasterizer, m_sl, ri);
02481 }
02482 else
02483 {
02484 renderer_type_normal ri(m_renBase, sa, sg);
02485 agg::render_scanlines(m_rasterizer, m_sl, ri);
02486 }
02487 }
02488
02489 void a2dAggDrawer::DrawImage( const a2dImageRGBA& image, double x, double y, double width, double height, wxUint8 Opacity )
02490 {
02491 if ( m_disableDrawing )
02492 return;
02493
02494 int imagew = image.GetWidth();
02495 int imageh = image.GetHeight();
02496
02497 agg::trans_affine mtxi;
02498 mtxi *= agg::trans_affine_scaling( width/imagew, height/imageh );
02499 mtxi *= agg::trans_affine_translation( x, y );
02500
02501 const a2dAffineMatrix &r2d = GetUserToDeviceTransform();
02502 agg::trans_affine mtx(
02503 r2d.GetValue(0,0), r2d.GetValue(0,1),
02504 r2d.GetValue(1,0), r2d.GetValue(1,1),
02505 r2d.GetValue(2,0), r2d.GetValue(2,1)
02506 );
02507 mtxi *= mtx;
02508 mtxi.invert();
02509
02510 typedef agg::span_allocator<agg::rgba8> span_alloc_type;
02511 span_alloc_type sa;
02512 typedef agg::image_accessor_clip<agg::pixfmt_rgba32> img_source_type;
02513 typedef agg::span_interpolator_linear<> interpolator_type;
02514 interpolator_type interpolator(mtxi);
02515
02516 typedef agg::span_image_filter_rgba_nn<img_source_type, interpolator_type> span_gen_type;
02517
02518 typedef agg::span_converter<span_gen_type, span_conv_const_alpha_rgba8> span_conv;
02519
02520 typedef agg::renderer_scanline_aa<RendererBase, span_alloc_type, span_conv> renderer_type_alpha;
02521
02522 typedef agg::renderer_scanline_bin<RendererBase, span_alloc_type, span_gen_type> renderer_type_normal;
02523
02524 agg::rendering_buffer image_buffer;
02525 image_buffer.attach( image.GetData(), imagew, imageh, imagew*4 );
02526 agg::pixfmt_rgba32 img_pixf(image_buffer);
02527 img_source_type img_src(img_pixf, agg::rgba(0,0,0,0));
02528
02529 span_gen_type sg(img_src, interpolator);
02530
02531
02532 agg::rounded_rect er(x, y ,x+width, y+height, 1);
02533 er.normalize_radius();
02534 agg::conv_transform<agg::rounded_rect> tr(er, mtx);
02535 m_rasterizer.reset();
02536 m_rasterizer.add_path(tr);
02537
02538 wxUint8 OpacityFactor = (m_OpacityFactor * Opacity)/255;
02539
02540
02541 if ( OpacityFactor != 255 )
02542 {
02543 span_conv_const_alpha_rgba8 color_alpha( OpacityFactor );
02544 span_conv sc(sg, color_alpha);
02545 renderer_type_alpha ri(m_renBase, sa, sc);
02546
02547 agg::render_scanlines(m_rasterizer, m_sl, ri);
02548 }
02549 else
02550 {
02551 renderer_type_normal ri(m_renBase, sa, sg);
02552 agg::render_scanlines(m_rasterizer, m_sl, ri);
02553 }
02554 }
02555
02556 void a2dAggDrawer::BlitBuffer( wxDC* dc, wxRect rect, const wxPoint& bufferpos )
02557 {
02558
02559 if (rect.x < 0)
02560 {
02561 rect.width += rect.x;
02562 rect.x = 0;
02563 }
02564 if (rect.width <= 0) return;
02565
02566 if (rect.y < 0)
02567 {
02568 rect.height += rect.y;
02569 rect.y = 0;
02570 }
02571 if (rect.height <= 0) return;
02572
02573 if (rect.x+rect.width >= m_width)
02574 rect.width = m_width - rect.x;
02575
02576 if (rect.width <= 0) return;
02577
02578 if (rect.y+rect.height >= m_height)
02579 rect.height = m_height - rect.y;
02580
02581 if (rect.height <= 0) return;
02582
02583 int xmax = rect.x + rect.width;
02584 int ymax = rect.y + rect.height;
02585
02586 wxBitmap subbitmap = m_buffer.GetSubImage(rect);
02587 wxMemoryDC mdc;
02588 mdc.SelectObject( subbitmap );
02589
02590 dc->Blit( rect.x - bufferpos.x, rect.y - bufferpos.y, xmax-rect.x, ymax-rect.y, &mdc, 0, 0, wxCOPY, false );
02591
02592 mdc.SelectObject( wxNullBitmap );
02593 }
02594
02595 void a2dAggDrawer::ShiftBuffer( int dxy, bool yshift )
02596 {
02597 ShiftBufferInternal( dxy, yshift, 3 );
02598 }
02599