• Main Page
  • Namespaces
  • Classes
  • Files
  • File List
  • File Members

wxwidgets_gc.cpp

Go to the documentation of this file.
00001 // $Id: wxwidgets_gc.cpp 11935 2011-09-25 16:09:38Z airwin $
00002 //
00003 // Copyright (C) 2008  Werner Smekal
00004 //
00005 // This file is part of PLplot.
00006 //
00007 // PLplot is free software; you can redistribute it and/or modify
00008 // it under the terms of the GNU Library General Public License as published
00009 // by the Free Software Foundation; either version 2 of the License, or
00010 // (at your option) any later version.
00011 //
00012 // PLplot is distributed in the hope that it will be useful,
00013 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00014 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015 // GNU Library General Public License for more details.
00016 //
00017 // You should have received a copy of the GNU Library General Public License
00018 // along with PLplot; if not, write to the Free Software
00019 // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
00020 //
00021 
00022 
00023 // TODO:
00024 // - text clipping
00025 // - implement AddToClipRegion for text correctly
00026 //
00027 
00028 // wxwidgets headers
00029 #include <wx/wx.h>
00030 
00031 #include "plDevs.h"
00032 
00033 // plplot headers
00034 #include "plplotP.h"
00035 
00036 // std and driver headers
00037 #include "wxwidgets.h"
00038 
00039 // only compile code if wxGraphicsContext available
00040 #if wxUSE_GRAPHICS_CONTEXT
00041 
00042 wxPLDevGC::wxPLDevGC( void ) : wxPLDevBase( wxBACKEND_GC )
00043 {
00044     // Log_Verbose( "%s", __FUNCTION__ );
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     // Log_Verbose( "%s", __FUNCTION__ );
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     // Log_Verbose( "%s", __FUNCTION__ );
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     // Log_Verbose( "%s", __FUNCTION__ );
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     // Log_Verbose( "%s", __FUNCTION__ );
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     // Log_Verbose( "%s", __FUNCTION__ );
00147 
00148     bool isRect = false;
00149     short* x    = pls->dev_x;
00150     short* y    = pls->dev_y;
00151 
00152     if ( pls->dev_npts == 4 )     // Check if it's a rectangle. If so, it can be made faster to display
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 )    //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     // Log_Verbose( "%s", __FUNCTION__ );
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     // Log_Verbose( "%s", __FUNCTION__ );
00235 
00236     if ( ownGUI )
00237     {
00238         if ( !m_dc )
00239             m_dc = new wxMemoryDC();
00240 
00241         ( (wxMemoryDC *) m_dc )->SelectObject( wxNullBitmap ); // deselect bitmap
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 ); // select new 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     // Log_Verbose( "%s", __FUNCTION__ );
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     // Log_Verbose( "%s", __FUNCTION__ );
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     // Log_Verbose( "%s", __FUNCTION__ );
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 //  void wx_set_dc( PLStream* pls, wxDC* dc )
00306 //
00307 //  Adds a dc to the stream. The associated device is attached to the canvas
00308 //  as the property "dev".
00309 //--------------------------------------------------------------------------
00310 void wxPLDevGC::SetExternalBuffer( void* dc )
00311 {
00312     // Log_Verbose( "%s", __FUNCTION__ );
00313 
00314     m_dc      = (wxDC *) dc; // Add the dc to the device
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     // Log_Verbose( "%s", __FUNCTION__ );
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     //m_context->DrawPoint( x, y );
00331     AddtoClipRegion( x, y, x, y );
00332     m_context->SetPen( oldpen );
00333 }
00334 
00335 void wxPLDevGC::PutPixel( short x, short y )
00336 {
00337     // Log_Verbose( "%s", __FUNCTION__ );
00338 
00339     //m_dc->DrawPoint( x, y );
00340     AddtoClipRegion( x, y, x, y );
00341 }
00342 
00343 PLINT wxPLDevGC::GetPixel( short x, short y )
00344 {
00345     // Log_Verbose( "%s", __FUNCTION__ );
00346 
00347   #ifdef __WXGTK__
00348     // The GetPixel method is incredible slow for wxGTK. Therefore we set the colour
00349     // always to the background color, since this is the case anyway 99% of the time.
00350     PLINT bgr, bgg, bgb;           // red, green, blue
00351     plgcolbg( &bgr, &bgg, &bgb );  // get background color information
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     // Log_Verbose( "%s", __FUNCTION__ );
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     // Log_Verbose( "%s", __FUNCTION__ );
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     // Log_Verbose( "%s", __FUNCTION__ );
00407 
00408     // Check that we got unicode, warning message and return if not
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     // Check that unicode string isn't longer then the max we allow
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     // Calculate the font size (in pixels)
00423     fontSize = pls->chrht * VIRTUAL_PIXELS_PER_MM / scaley * 1.3;
00424 
00425     // Use PLplot core routine to get the corners of the clipping rectangle
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     // m_context->Clip( wxRegion( topLeft, bottomRight) );  // this wxRegion constructor doesn't work in wxWidgets 2.9.2/Cocoa
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     // text color
00452     textRed   = pls->cmap0[pls->icol0].r;
00453     textGreen = pls->cmap0[pls->icol0].g;
00454     textBlue  = pls->cmap0[pls->icol0].b;
00455 
00456     // calculate rotation of text
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     // determine extend of text
00465     PSDrawText( args->unicode_array, args->unicode_array_len, false );
00466 
00467     // actually draw text
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

Generated on Wed Oct 12 2011 20:42:23 for PLplot by  doxygen 1.7.1