00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028 #include <wx/wx.h>
00029 #include <wx/strconv.h>
00030
00031 #include "plDevs.h"
00032
00033
00034 #include "plplotP.h"
00035 #include "plfci-truetype.h"
00036
00037
00038 #include "wxwidgets.h"
00039 #include <wchar.h>
00040
00041
00042 #if !defined ( WIN32 ) || defined ( __GNUC__ )
00043 #include <unistd.h>
00044 #else
00045 #define F_OK 1
00046 #include <stdio.h>
00047 int access( char *filename, int flag )
00048 {
00049 FILE *infile;
00050 infile = fopen( filename, "r" );
00051 if ( infile != NULL )
00052 {
00053 fclose( infile );
00054 return 0;
00055 }
00056 else
00057 return 1;
00058 }
00059 #endif
00060
00061 #define makeunixslash( b ) do { char *I; for ( I = b; *I != 0; *I++ ) if ( *I == '\\' ) *I = '/';} while ( 0 )
00062
00063
00064
00065
00066
00067
00068
00069 wxPLDevAGG::wxPLDevAGG() :
00070 wxPLDevBase( wxBACKEND_AGG ),
00071 mRenderingBuffer(),
00072 mPixFormat( mRenderingBuffer ),
00073 mRendererBase( mPixFormat ),
00074 mRendererSolid( mRendererBase ),
00075
00076 mPath(),
00077 mTransform(),
00078 mConvCurve( mPath ),
00079 mConvStroke( mConvCurve ),
00080 mPathTransform( mConvCurve, mTransform ),
00081 mStrokeTransform( mConvStroke, mTransform ),
00082
00083 mFontEngine(),
00084 mFontManager( mFontEngine ),
00085 mCurves( mFontManager.path_adaptor() ),
00086 mContour( mCurves ),
00087
00088 mBuffer( NULL ),
00089 mStrokeWidth( 1.0 ),
00090 mStrokeOpacity( 255 ),
00091 mColorRedStroke( 255 ),
00092 mColorGreenStroke( 255 ),
00093 mColorBlueStroke( 255 ),
00094 mColorRedFill( 0 ),
00095 mColorGreenFill( 0 ),
00096 mColorBlueFill( 0 )
00097 {
00098 mCurves.approximation_scale( 2.0 );
00099 mContour.auto_detect_orientation( false );
00100 mConvStroke.line_join( agg::round_join );
00101 mConvStroke.line_cap( agg::round_cap );
00102
00103
00104 #if defined ( WIN32 )
00105
00106
00107
00108
00109
00110
00111
00112
00113
00114
00115
00116
00117
00118
00119
00120
00121
00122
00123
00124
00125
00126
00127
00128
00129
00130
00131
00132
00133
00134
00135
00136
00137
00138
00139
00140
00141
00142
00143
00144
00145
00146 #else
00147
00148
00149
00150
00151
00152
00153
00154
00155
00156
00157
00158
00159
00160
00161
00162 #endif
00163 }
00164
00165
00166
00167
00168
00169
00170
00171 wxPLDevAGG::~wxPLDevAGG()
00172 {
00173 if ( ownGUI )
00174 if ( mBuffer )
00175 delete mBuffer;
00176 }
00177
00178
00179
00180
00181
00182
00183
00184
00185 void wxPLDevAGG::drawPath( drawPathFlag flag )
00186 {
00187 mRasterizer.reset();
00188
00189 switch ( flag )
00190 {
00191 case Stroke:
00192 if ( mStrokeOpacity && mStrokeWidth > 0.0 )
00193 {
00194 mConvStroke.width( mStrokeWidth );
00195 mRasterizer.add_path( mStrokeTransform );
00196 mRendererSolid.color( agg::rgba8( mColorRedStroke, mColorGreenStroke, mColorBlueStroke, mStrokeOpacity ) );
00197 agg::render_scanlines( mRasterizer, mScanLine, mRendererSolid );
00198 }
00199 break;
00200 case FillAndStroke:
00201 if ( mStrokeOpacity )
00202 {
00203 mRasterizer.add_path( mPathTransform );
00204 mRendererSolid.color( agg::rgba8( mColorRedStroke, mColorGreenStroke, mColorBlueStroke, mStrokeOpacity ) );
00205 agg::render_scanlines( mRasterizer, mScanLine, mRendererSolid );
00206 }
00207
00208 if ( mStrokeOpacity && mStrokeWidth > 0.0 )
00209 {
00210 mConvStroke.width( mStrokeWidth );
00211 mRasterizer.add_path( mStrokeTransform );
00212 mRendererSolid.color( agg::rgba8( mColorRedStroke, mColorGreenStroke, mColorBlueStroke, mStrokeOpacity ) );
00213 agg::render_scanlines( mRasterizer, mScanLine, mRendererSolid );
00214 }
00215 break;
00216 }
00217 }
00218
00219
00220
00221
00222
00223
00224
00225 void wxPLDevAGG::DrawLine( short x1a, short y1a, short x2a, short y2a )
00226 {
00227 mPath.remove_all();
00228 mPath.move_to( x1a, y1a );
00229 mPath.line_to( x2a, y2a );
00230
00231 if ( !resizing && ownGUI )
00232 AGGAddtoClipRegion( x1a, y1a, x2a, y2a );
00233
00234 drawPath( Stroke );
00235 }
00236
00237
00238
00239
00240
00241
00242
00243 void wxPLDevAGG::DrawPolyline( short *xa, short *ya, PLINT npts )
00244 {
00245 mPath.remove_all();
00246 mPath.move_to( xa[0], ya[0] );
00247 for ( PLINT i = 1; i < npts; i++ )
00248 {
00249 mPath.line_to( xa[i], ya[i] );
00250 if ( !resizing && ownGUI )
00251 AGGAddtoClipRegion( xa[i - 1], ya[i - 1], xa[i], ya[i] );
00252 }
00253
00254 drawPath( Stroke );
00255 }
00256
00257
00258
00259
00260
00261
00262
00263
00264 void wxPLDevAGG::ClearBackground( PLINT bgr, PLINT bgg, PLINT bgb, PLINT x1, PLINT y1, PLINT x2, PLINT y2 )
00265 {
00266 if ( x1 < 0 && y1 < 0 && x2 < 0 && y2 < 0 )
00267 {
00268 mRendererBase.clear( agg::rgba8( bgr, bgg, bgb ) );
00269 if ( !resizing && ownGUI )
00270 AddtoClipRegion( 0, 0, width, height );
00271 }
00272 else
00273 {
00274 mPath.remove_all();
00275 mPath.move_to( x1, y1 );
00276 mPath.line_to( x2, y1 );
00277 mPath.line_to( x2, y2 );
00278 mPath.line_to( x1, y2 );
00279 mPath.close_polygon();
00280
00281 mRasterizer.reset();
00282 mRasterizer.add_path( mPathTransform );
00283 mRendererSolid.color( agg::rgba8( bgr, bgg, bgb, 255 ) );
00284 agg::render_scanlines( mRasterizer, mScanLine, mRendererSolid );
00285
00286 mConvStroke.width( 1.0 );
00287 mRasterizer.add_path( mStrokeTransform );
00288 mRendererSolid.color( agg::rgba8( bgr, bgg, bgb, 255 ) );
00289 agg::render_scanlines( mRasterizer, mScanLine, mRendererSolid );
00290
00291 if ( !resizing && ownGUI )
00292 AGGAddtoClipRegion( x1, y1, x2, y2 );
00293 }
00294 }
00295
00296
00297
00298
00299
00300
00301
00302
00303
00304 void wxPLDevAGG::AGGAddtoClipRegion( short x1, short y1, short x2, short y2 )
00305 {
00306 double x1d = x1, x2d = x2, y1d = y1, y2d = y2;
00307
00308 mTransform.transform( &x1d, &y1d );
00309 mTransform.transform( &x2d, &y2d );
00310 AddtoClipRegion( (int) floor( x1d ), (int) floor( y1d ), (int) ceil( x2d ), (int) ceil( y2d ) );
00311 }
00312
00313
00314
00315
00316
00317
00318
00319 void wxPLDevAGG::FillPolygon( PLStream *pls )
00320 {
00321 short *xa = pls->dev_x;
00322 short *ya = pls->dev_y;
00323
00324 mPath.remove_all();
00325 mPath.move_to( xa[0], ya[0] );
00326 for ( PLINT i = 1; i < pls->dev_npts; i++ )
00327 {
00328 mPath.line_to( xa[i], ya[i] );
00329 if ( !resizing && ownGUI )
00330 AGGAddtoClipRegion( xa[i - 1], ya[i - 1], xa[i], ya[i] );
00331 }
00332 mPath.line_to( xa[0], ya[0] );
00333 mPath.close_polygon();
00334
00335 drawPath( FillAndStroke );
00336 }
00337
00338
00339
00340
00341
00342
00343
00344
00345 void wxPLDevAGG::BlitRectangle( wxDC* dc, int vX, int vY, int vW, int vH )
00346 {
00347 if ( mBuffer )
00348 {
00349 wxMemoryDC MemoryDC;
00350 wxBitmap bitmap( mBuffer->GetSubImage( wxRect( vX, vY, vW, vH ) ), -1 );
00351 MemoryDC.SelectObject( bitmap );
00352 dc->Blit( vX, vY, vW, vH, &MemoryDC, 0, 0 );
00353 MemoryDC.SelectObject( wxNullBitmap );
00354 }
00355 }
00356
00357
00358
00359
00360
00361
00362
00363 void wxPLDevAGG::CreateCanvas()
00364 {
00365 if ( ownGUI )
00366 {
00367
00368 if ( mBuffer )
00369 delete mBuffer;
00370 mBuffer = new wxImage( bm_width, bm_height );
00371 mRenderingBuffer.attach( mBuffer->GetData(), bm_width, bm_height, bm_width * 3 );
00372 }
00373 else
00374 mRenderingBuffer.attach( mBuffer->GetData(), width, height, width * 3 );
00375
00376 mRendererBase.reset_clipping( true );
00377 mTransform.reset();
00378 mTransform.premultiply( agg::trans_affine_translation( 0.0, height ) );
00379 mTransform.premultiply( agg::trans_affine_scaling( 1.0 / scalex, -1.0 / scaley ) );
00380 mStrokeWidth = ( scalex + scaley ) / 2.0;
00381 }
00382
00383
00384
00385
00386
00387
00388
00389 void wxPLDevAGG::SetWidth( PLStream *pls )
00390 {
00391 mStrokeWidth = ( scalex + scaley ) / 2.0 * ( pls->width > 0 ? pls->width : 1 );
00392 }
00393
00394
00395
00396
00397
00398
00399
00400 void wxPLDevAGG::SetColor0( PLStream *pls )
00401 {
00402 mColorRedStroke = pls->cmap0[pls->icol0].r;
00403 mColorGreenStroke = pls->cmap0[pls->icol0].g;
00404 mColorBlueStroke = pls->cmap0[pls->icol0].b;
00405 mStrokeOpacity = (wxUint8) ( pls->cmap0[pls->icol0].a * 255 );
00406 }
00407
00408
00409
00410
00411
00412
00413
00414 void wxPLDevAGG::SetColor1( PLStream *pls )
00415 {
00416 mColorRedStroke = pls->curcolor.r;
00417 mColorGreenStroke = pls->curcolor.g;
00418 mColorBlueStroke = pls->curcolor.b;
00419 mStrokeOpacity = (wxUint8) ( pls->curcolor.a * 255 );
00420 }
00421
00422
00423
00424
00425
00426
00427
00428
00429 void wxPLDevAGG::SetExternalBuffer( void* image )
00430 {
00431 mBuffer = (wxImage *) image;
00432 mRenderingBuffer.attach( mBuffer->GetData(), width, height, width * 3 );
00433
00434 mRendererBase.reset_clipping( true );
00435 mTransform.reset();
00436 mTransform.premultiply( agg::trans_affine_translation( 0.0, height ) );
00437 mTransform.premultiply( agg::trans_affine_scaling( 1.0 / scalex, -1.0 / scaley ) );
00438 mStrokeWidth = ( scalex + scaley ) / 2.0;
00439
00440 ready = true;
00441 ownGUI = false;
00442 }
00443
00444
00445 #ifdef HAVE_FREETYPE
00446
00447
00448
00449
00450
00451
00452 void wxPLDevAGG::PutPixel( short x, short y, PLINT color )
00453 {
00454 mBuffer->SetRGB( x, y, GetRValue( color ), GetGValue( color ), GetBValue( color ) );
00455 AddtoClipRegion( x, y, x, y );
00456 }
00457
00458
00459
00460
00461
00462
00463
00464 void wxPLDevAGG::PutPixel( short x, short y )
00465 {
00466 mBuffer->SetRGB( x, y, mColorRedStroke, mColorGreenStroke, mColorBlueStroke );
00467 AddtoClipRegion( x, y, x, y );
00468 }
00469
00470
00471
00472
00473
00474
00475
00476 PLINT wxPLDevAGG::GetPixel( short x, short y )
00477 {
00478 return RGB( mBuffer->GetRed( x, y ), mBuffer->GetGreen( x, y ), mBuffer->GetBlue( x, y ) );
00479 }
00480
00481 #endif // HAVE_FREETYPE
00482
00483
00484 void wxPLDevAGG::PSDrawTextToDC( char* utf8_string, bool drawText )
00485 {
00486
00487 printf( "utf8_string=%s\n", utf8_string );
00488
00489 double start_x = 0.0;
00490 double start_y = 0.0;
00491
00492
00493
00494 size_t len = strlen( utf8_string );
00495 char * str = utf8_string;
00496 printf( "len=%d\n", len );
00497
00498 const agg::glyph_cache* glyph;
00499 if ( !drawText )
00500 {
00501 double x = 0;
00502 double y = 0;
00503 bool first = true;
00504 char * saveStr = str;
00505 while ( *str && len )
00506 {
00507 glyph = mFontManager.glyph( *str );
00508 if ( glyph )
00509 {
00510 if ( !first )
00511 mFontManager.add_kerning( &x, &y );
00512 x += glyph->advance_x;
00513 y += glyph->advance_y;
00514 first = false;
00515 }
00516 textHeight = textHeight > ( glyph->bounds.y2 - glyph->bounds.y1 + yOffset ) ?
00517 textHeight : ( glyph->bounds.y2 - glyph->bounds.y1 + yOffset );
00518 ++str; --len;
00519 }
00520 textWidth = x;
00521 printf( "str: %s, textWidth=%lf\n", saveStr, textWidth );
00522 }
00523 else
00524 {
00525 for ( size_t i = 0; i < len && str[i]; i++ )
00526 {
00527 glyph = mFontManager.glyph( str[i] );
00528 if ( glyph )
00529 {
00530 printf( "before: start_x=%f, start_y=%f\n", start_x, start_y );
00531 if ( i )
00532 mFontManager.add_kerning( &start_x, &start_y );
00533 printf( "after: start_x=%f, start_y=%f\n", start_x, start_y );
00534 mFontManager.init_embedded_adaptors( glyph, start_x, start_y );
00535
00536 mRendererSolid.color( agg::rgba8( mColorRedStroke, mColorGreenStroke, mColorBlueStroke, mStrokeOpacity ) );
00537 agg::render_scanlines( mFontManager.gray8_adaptor(), mFontManager.gray8_scanline(), mRendererSolid );
00538
00539 start_x += glyph->advance_x / scalex;
00540
00541 }
00542 }
00543 }
00544
00545 memset( utf8_string, '\0', max_string_length );
00546 }
00547
00548
00549 void wxPLDevAGG::PSSetFont( PLUNICODE fci )
00550 {
00551
00552 wxString fontname = fontdir + wxString( plP_FCI2FontName( fci, TrueTypeLookup, N_TrueTypeLookup ), *wxConvCurrent );
00553
00554 if ( !mFontEngine.load_font( "/usr/share/fonts/truetype/freefont/FreeSans.ttf", 0, agg::glyph_ren_agg_gray8 ) )
00555 plabort( "Font could not be loaded" );
00556
00557 mFontEngine.height( fontSize * fontScale );
00558 mFontEngine.width( fontSize * fontScale );
00559 mFontEngine.hinting( true );
00560 mFontEngine.flip_y( false );
00561 mContour.width( fontSize * fontScale * 0.2 );
00562 }
00563
00564
00565 void wxPLDevAGG::ProcessString( PLStream* pls, EscText* args )
00566 {
00567 plabort( "The AGG backend can't process the text yet own its own!" );
00568
00569
00570 if ( args->unicode_array_len == 0 )
00571 {
00572 printf( "Non unicode string passed to a wxWidgets driver, ignoring\n" );
00573 return;
00574 }
00575
00576
00577 if ( args->unicode_array_len >= 500 )
00578 {
00579 printf( "Sorry, the wxWidgets drivers only handles strings of length < %d\n", 500 );
00580 return;
00581 }
00582
00583
00584 fontSize = pls->chrht * DEVICE_PIXELS_PER_MM * 1.2 * scaley;
00585
00586
00587 plRotationShear( args->xform, &rotation, &shear, &stride );
00588 rotation -= pls->diorot * M_PI / 2.0;
00589 cos_shear = cos( shear );
00590 sin_shear = sin( shear );
00591
00592 PSDrawText( args->unicode_array, args->unicode_array_len, false );
00593 printf( "textWidth=%f, textHeight=%f\n", textWidth, textHeight );
00594
00595 agg::trans_affine mtx;
00596 mtx.reset();
00597 mtx *= agg::trans_affine_translation( args->x, args->y );
00598
00599
00600 mtx *= mTransform;
00601 mtx *= agg::trans_affine_translation( -args->just * textWidth / scalex, -0.5 * textHeight );
00602 mtx *= agg::trans_affine_translation( -args->just * textWidth / scalex, -0.5 * textHeight );
00603 mFontEngine.transform( mtx );
00604
00605 PSDrawText( args->unicode_array, args->unicode_array_len, true );
00606
00607 AddtoClipRegion( 0, 0, width, height );
00608 }