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
00029 #include <wx/wx.h>
00030
00031 #include "plDevs.h"
00032
00033
00034 #include "plplotP.h"
00035
00036
00037 #include "wxwidgets.h"
00038
00039
00040 #if wxUSE_GRAPHICS_CONTEXT
00041
00042 wxPLDevGC::wxPLDevGC( void ) : wxPLDevBase( wxBACKEND_GC )
00043 {
00044
00045
00046 m_dc = NULL;
00047 m_bitmap = NULL;
00048 m_context = NULL;
00049 m_font = NULL;
00050 underlined = false;
00051 }
00052
00053
00054 wxPLDevGC::~wxPLDevGC()
00055 {
00056
00057
00058 if ( ownGUI )
00059 {
00060 if ( m_dc )
00061 {
00062 ( (wxMemoryDC *) m_dc )->SelectObject( wxNullBitmap );
00063 delete m_dc;
00064 }
00065 if ( m_bitmap )
00066 delete m_bitmap;
00067 }
00068
00069 delete m_font;
00070 delete m_context;
00071 }
00072
00073
00074 void wxPLDevGC::DrawLine( short x1a, short y1a, short x2a, short y2a )
00075 {
00076
00077
00078 wxDouble x1 = x1a / scalex;
00079 wxDouble y1 = height - y1a / scaley;
00080 wxDouble x2 = x2a / scalex;
00081 wxDouble y2 = height - y2a / scaley;
00082
00083 wxGraphicsPath path = m_context->CreatePath();
00084 path.MoveToPoint( x1, y1 );
00085 path.AddLineToPoint( x2, y2 );
00086 m_context->StrokePath( path );
00087
00088 AddtoClipRegion( (int) x1, (int) y1, (int) x2, (int) y2 );
00089 }
00090
00091
00092 void wxPLDevGC::DrawPolyline( short *xa, short *ya, PLINT npts )
00093 {
00094
00095
00096 wxGraphicsPath path = m_context->CreatePath();
00097 path.MoveToPoint( xa[0] / scalex, height - ya[0] / scaley );
00098 for ( PLINT i = 1; i < npts; i++ )
00099 path.AddLineToPoint( xa[i] / scalex, height - ya[i] / scaley );
00100 m_context->StrokePath( path );
00101
00102 wxDouble x, y, w, h;
00103 path.GetBox( &x, &y, &w, &h );
00104 AddtoClipRegion( (int) x, (int) y, (int) ( x + w ), (int) ( y + h ) );
00105 }
00106
00107
00108 void wxPLDevGC::ClearBackground( PLINT bgr, PLINT bgg, PLINT bgb, PLINT x1, PLINT y1, PLINT x2, PLINT y2 )
00109 {
00110
00111
00112 wxDouble x1a, y1a, x2a, y2a;
00113
00114 if ( x1 < 0 )
00115 x1a = 0;
00116 else
00117 x1a = x1 / scalex;
00118 if ( y1 < 0 )
00119 y1a = 0;
00120 else
00121 y1a = height - y1 / scaley;
00122 if ( x2 < 0 )
00123 x2a = width;
00124 else
00125 x2a = x2 / scalex;
00126 if ( y2 < 0 )
00127 y2a = height;
00128 else
00129 y2a = height - y2 / scaley;
00130
00131 m_context->SetPen( *( wxThePenList->FindOrCreatePen( wxColour( bgr, bgg, bgb ), 1, wxSOLID ) ) );
00132 m_context->SetBrush( wxBrush( wxColour( bgr, bgg, bgb ) ) );
00133 m_context->DrawRectangle( x1a, y1a, x2a - x1a, y2a - y1a );
00134
00135 m_context->SetPen( *( wxThePenList->FindOrCreatePen( wxColour( mColorRedStroke, mColorGreenStroke,
00136 mColorBlueStroke, mStrokeOpacity ),
00137 1, wxSOLID ) ) );
00138 m_context->SetBrush( wxBrush( wxColour( mColorRedFill, mColorGreenFill, mColorBlueFill, mStrokeOpacity ) ) );
00139
00140 AddtoClipRegion( (int) x1a, (int) y1a, (int) x2a, (int) y2a );
00141 }
00142
00143
00144 void wxPLDevGC::FillPolygon( PLStream *pls )
00145 {
00146
00147
00148 bool isRect = false;
00149 short* x = pls->dev_x;
00150 short* y = pls->dev_y;
00151
00152 if ( pls->dev_npts == 4 )
00153 {
00154 if ( x[0] == x[1] && x[2] == x[3] && y[0] == y[3] && y[1] == y[2] )
00155 isRect = true;
00156 else if ( x[0] == x[3] && x[1] == x[2] && y[0] == y[1] && y[2] == y[3] )
00157 isRect = true;
00158 }
00159 if ( pls->dev_npts == 5 )
00160 {
00161 if ( x[0] == x[4] && y[0] == y[4] )
00162 {
00163 if ( x[0] == x[1] && x[2] == x[3] && y[0] == y[3] && y[1] == y[2] )
00164 isRect = true;
00165 else if ( x[0] == x[3] && x[1] == x[2] && y[0] == y[1] && y[2] == y[3] )
00166 isRect = true;
00167 }
00168 }
00169
00170 if ( isRect )
00171 {
00172 double x1, y1, x2, y2, x0, y0, w, h;
00173
00174 x1 = x[0] / scalex;
00175 x2 = x[2] / scalex;
00176 y1 = height - y[0] / scaley;
00177 y2 = height - y[2] / scaley;
00178
00179 if ( x1 < x2 )
00180 {
00181 x0 = x1;
00182 w = x2 - x1;
00183 }
00184 else
00185 {
00186 x0 = x2;
00187 w = x1 - x2;
00188 }
00189 if ( y1 < y2 )
00190 {
00191 y0 = y1;
00192 h = y2 - y1;
00193 }
00194 else
00195 {
00196 y0 = y2;
00197 h = y1 - y2;
00198 }
00199 m_context->DrawRectangle( x0, y0, w, h );
00200 AddtoClipRegion( (int) x0, (int) y0, (int) w, (int) h );
00201 }
00202 else
00203 {
00204 wxGraphicsPath path = m_context->CreatePath();
00205 path.MoveToPoint( x[0] / scalex, height - y[0] / scaley );
00206 for ( int i = 1; i < pls->dev_npts; i++ )
00207 path.AddLineToPoint( x[i] / scalex, height - y[i] / scaley );
00208 path.CloseSubpath();
00209
00210 if ( pls->dev_eofill )
00211 m_context->DrawPath( path, wxODDEVEN_RULE );
00212 else
00213 m_context->DrawPath( path, wxWINDING_RULE );
00214
00215 wxDouble x, y, w, h;
00216 path.GetBox( &x, &y, &w, &h );
00217
00218 AddtoClipRegion( (int) x, (int) y, (int) ( x + w ), (int) ( y + h ) );
00219 }
00220 }
00221
00222
00223 void wxPLDevGC::BlitRectangle( wxDC* dc, int vX, int vY, int vW, int vH )
00224 {
00225
00226
00227 if ( m_dc )
00228 dc->Blit( vX, vY, vW, vH, m_dc, vX, vY );
00229 }
00230
00231
00232 void wxPLDevGC::CreateCanvas()
00233 {
00234
00235
00236 if ( ownGUI )
00237 {
00238 if ( !m_dc )
00239 m_dc = new wxMemoryDC();
00240
00241 ( (wxMemoryDC *) m_dc )->SelectObject( wxNullBitmap );
00242 if ( m_bitmap )
00243 delete m_bitmap;
00244 m_bitmap = new wxBitmap( bm_width, bm_height, 32 );
00245 ( (wxMemoryDC *) m_dc )->SelectObject( *m_bitmap );
00246 }
00247
00248 if ( m_dc )
00249 {
00250 delete m_context;
00251 m_context = wxGraphicsContext::Create( *( (wxMemoryDC *) m_dc ) );
00252 }
00253 }
00254
00255
00256 void wxPLDevGC::SetWidth( PLStream *pls )
00257 {
00258
00259
00260 m_context->SetPen( *( wxThePenList->FindOrCreatePen( wxColour( mColorRedStroke, mColorGreenStroke,
00261 mColorBlueStroke, mStrokeOpacity ),
00262 pls->width > 0 ? pls->width : 1, wxSOLID ) ) );
00263 }
00264
00265
00266 void wxPLDevGC::SetColor0( PLStream *pls )
00267 {
00268
00269
00270 mColorRedStroke = pls->cmap0[pls->icol0].r;
00271 mColorGreenStroke = pls->cmap0[pls->icol0].g;
00272 mColorBlueStroke = pls->cmap0[pls->icol0].b;
00273 mColorRedFill = pls->cmap0[pls->icol0].r;
00274 mColorGreenFill = pls->cmap0[pls->icol0].g;
00275 mColorBlueFill = pls->cmap0[pls->icol0].b;
00276 mStrokeOpacity = (unsigned char) ( pls->cmap0[pls->icol0].a * 255 );
00277
00278 m_context->SetPen( *( wxThePenList->FindOrCreatePen( wxColour( mColorRedStroke, mColorGreenStroke,
00279 mColorBlueStroke, mStrokeOpacity ),
00280 pls->width > 0 ? pls->width : 1, wxSOLID ) ) );
00281 m_context->SetBrush( wxBrush( wxColour( mColorRedFill, mColorGreenFill, mColorBlueFill, mStrokeOpacity ) ) );
00282 }
00283
00284
00285 void wxPLDevGC::SetColor1( PLStream *pls )
00286 {
00287
00288
00289 mColorRedStroke = pls->curcolor.r;
00290 mColorGreenStroke = pls->curcolor.g;
00291 mColorBlueStroke = pls->curcolor.b;
00292 mColorRedFill = pls->curcolor.r;
00293 mColorGreenFill = pls->curcolor.g;
00294 mColorBlueFill = pls->curcolor.b;
00295 mStrokeOpacity = (unsigned char) ( pls->curcolor.a * 255 );
00296
00297 m_context->SetPen( *( wxThePenList->FindOrCreatePen( wxColour( mColorRedStroke, mColorGreenStroke,
00298 mColorBlueStroke, mStrokeOpacity ),
00299 pls->width > 0 ? pls->width : 1, wxSOLID ) ) );
00300 m_context->SetBrush( wxBrush( wxColour( mColorRedFill, mColorGreenFill, mColorBlueFill, mStrokeOpacity ) ) );
00301 }
00302
00303
00304
00305
00306
00307
00308
00309
00310 void wxPLDevGC::SetExternalBuffer( void* dc )
00311 {
00312
00313
00314 m_dc = (wxDC *) dc;
00315 m_context = wxGraphicsContext::Create( *( (wxMemoryDC *) m_dc ) );
00316 ready = true;
00317 ownGUI = false;
00318 }
00319
00320
00321 #ifdef HAVE_FREETYPE
00322
00323 void wxPLDevGC::PutPixel( short x, short y, PLINT color )
00324 {
00325
00326
00327 const wxPen oldpen = m_dc->GetPen();
00328 m_context->SetPen( *( wxThePenList->FindOrCreatePen( wxColour( GetRValue( color ), GetGValue( color ), GetBValue( color ) ),
00329 1, wxSOLID ) ) );
00330
00331 AddtoClipRegion( x, y, x, y );
00332 m_context->SetPen( oldpen );
00333 }
00334
00335 void wxPLDevGC::PutPixel( short x, short y )
00336 {
00337
00338
00339
00340 AddtoClipRegion( x, y, x, y );
00341 }
00342
00343 PLINT wxPLDevGC::GetPixel( short x, short y )
00344 {
00345
00346
00347 #ifdef __WXGTK__
00348
00349
00350 PLINT bgr, bgg, bgb;
00351 plgcolbg( &bgr, &bgg, &bgb );
00352 return RGB( bgr, bgg, bgb );
00353 #else
00354 wxColour col;
00355 m_dc->GetPixel( x, y, &col );
00356 return RGB( col.Red(), col.Green(), col.Blue() );
00357 #endif
00358 }
00359
00360 #endif // HAVE_FREETYPE
00361
00362
00363 void wxPLDevGC::PSDrawTextToDC( char* utf8_string, bool drawText )
00364 {
00365
00366
00367 wxDouble w, h, d, l;
00368
00369 wxString str( wxConvUTF8.cMB2WC( utf8_string ), *wxConvCurrent );
00370 m_context->GetTextExtent( str, &w, &h, &d, &l );
00371 if ( drawText )
00372 {
00373 m_context->DrawText( str, 0, -yOffset / scaley );
00374 m_context->Translate( w, 0 );
00375 }
00376
00377 textWidth += static_cast<int>( w );
00378 textHeight = textHeight > ( h + yOffset / scaley )
00379 ? textHeight
00380 : static_cast<int>( ( h + yOffset / scaley ) );
00381 memset( utf8_string, '\0', max_string_length );
00382 }
00383
00384
00385 void wxPLDevGC::PSSetFont( PLUNICODE fci )
00386 {
00387
00388
00389 unsigned char fontFamily, fontStyle, fontWeight;
00390
00391 plP_fci2hex( fci, &fontFamily, PL_FCI_FAMILY );
00392 plP_fci2hex( fci, &fontStyle, PL_FCI_STYLE );
00393 plP_fci2hex( fci, &fontWeight, PL_FCI_WEIGHT );
00394 if ( m_font )
00395 delete m_font;
00396 m_font = wxFont::New( static_cast<int>( fontSize * fontScale ),
00397 fontFamilyLookup[fontFamily],
00398 fontStyleLookup[fontStyle] & fontWeightLookup[fontWeight] );
00399 m_font->SetUnderlined( underlined );
00400 m_context->SetFont( *m_font, wxColour( textRed, textGreen, textBlue ) );
00401 }
00402
00403
00404 void wxPLDevGC::ProcessString( PLStream* pls, EscText* args )
00405 {
00406
00407
00408
00409 if ( args->unicode_array_len == 0 )
00410 {
00411 printf( "Non unicode string passed to a cairo driver, ignoring\n" );
00412 return;
00413 }
00414
00415
00416 if ( args->unicode_array_len >= 500 )
00417 {
00418 printf( "Sorry, the wxWidgets drivers only handles strings of length < %d\n", 500 );
00419 return;
00420 }
00421
00422
00423 fontSize = pls->chrht * VIRTUAL_PIXELS_PER_MM / scaley * 1.3;
00424
00425
00426 PLINT rcx[4], rcy[4];
00427 difilt_clip( rcx, rcy );
00428
00429 #ifdef __WXOSX_COCOA__
00430 wxPoint topLeft( width, height ), bottomRight( -1, -1 );
00431 for ( int i = 0; i < 4; i++ )
00432 {
00433 topLeft.x = topLeft.x > ( rcx[i] / scalex ) ? ( rcx[i] / scalex ) : topLeft.x;
00434 topLeft.y = topLeft.y > ( height - rcy[i] / scaley ) ? ( height - rcy[i] / scaley ) : topLeft.y;
00435 bottomRight.x = bottomRight.x < ( rcx[i] / scalex ) ? ( rcx[i] / scalex ) : bottomRight.x;
00436 bottomRight.y = bottomRight.y < ( height - rcy[i] / scaley ) ? ( height - rcy[i] / scaley ) : bottomRight.y;
00437 }
00438
00439 m_context->Clip( wxRegion( topLeft.x, topLeft.y, bottomRight.x - topLeft.x, bottomRight.y - topLeft.y ) );
00440
00441 #else
00442 wxPoint cpoints[4];
00443 for ( int i = 0; i < 4; i++ )
00444 {
00445 cpoints[i].x = rcx[i] / scalex;
00446 cpoints[i].y = height - rcy[i] / scaley;
00447 }
00448 m_context->Clip( wxRegion( 4, cpoints ) );
00449 #endif
00450
00451
00452 textRed = pls->cmap0[pls->icol0].r;
00453 textGreen = pls->cmap0[pls->icol0].g;
00454 textBlue = pls->cmap0[pls->icol0].b;
00455
00456
00457 plRotationShear( args->xform, &rotation, &shear, &stride );
00458 rotation -= pls->diorot * M_PI / 2.0;
00459 cos_rot = cos( rotation );
00460 sin_rot = sin( rotation );
00461 cos_shear = cos( shear );
00462 sin_shear = sin( shear );
00463
00464
00465 PSDrawText( args->unicode_array, args->unicode_array_len, false );
00466
00467
00468 m_context->PushState();
00469 m_context->Translate( args->x / scalex, height - args->y / scaley );
00470 wxGraphicsMatrix matrix = m_context->CreateMatrix(
00471 cos_rot * stride, -sin_rot * stride,
00472 cos_rot * sin_shear + sin_rot * cos_shear,
00473 -sin_rot * sin_shear + cos_rot * cos_shear,
00474 0.0, 0.0 );
00475 m_context->ConcatTransform( matrix );
00476 m_context->Translate( -args->just * textWidth, -0.5 * textHeight );
00477 PSDrawText( args->unicode_array, args->unicode_array_len, true );
00478 m_context->PopState();
00479
00480 AddtoClipRegion( 0, 0, width, height );
00481
00482 m_context->ResetClip();
00483 }
00484
00485 #endif