PLplot  5.10.0
wxwidgets_dc.cpp
Go to the documentation of this file.
00001 // Copyright (C) 2005  Werner Smekal, Sjaak Verdoold
00002 // Copyright (C) 2005  Germain Carrera Corraleche
00003 // Copyright (C) 1999  Frank Huebner
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 // TODO:
00023 // - text clipping
00024 // - implement AddToClipRegion for text correctly
00025 //
00026 
00027 // wxwidgets headers
00028 #include <wx/wx.h>
00029 
00030 #include "plDevs.h"
00031 
00032 // plplot headers
00033 #include "plplotP.h"
00034 
00035 // std and driver headers
00036 #include <cmath>
00037 #include "wxwidgets.h"
00038 
00039 
00040 //--------------------------------------------------------------------------
00041 //  wxPLDevDC::wxPLDevDC( void )
00042 //
00043 //  Constructor of the standard wxWidgets device based on the wxPLDevBase
00044 //  class. Only some initialisations are done.
00045 //--------------------------------------------------------------------------
00046 wxPLDevDC::wxPLDevDC( void ) : wxPLDevBase( wxBACKEND_DC )
00047 {
00048     m_dc       = NULL;
00049     m_bitmap   = NULL;
00050     m_font     = NULL;
00051     underlined = false;
00052 }
00053 
00054 
00055 //--------------------------------------------------------------------------
00056 //  wxPLDevDC::~wxPLDevDC( void )
00057 //
00058 //  The deconstructor frees memory allocated by the device.
00059 //--------------------------------------------------------------------------
00060 wxPLDevDC::~wxPLDevDC()
00061 {
00062     if ( ownGUI )
00063     {
00064         if ( m_dc )
00065         {
00066             ( (wxMemoryDC *) m_dc )->SelectObject( wxNullBitmap );
00067             delete m_dc;
00068         }
00069         if ( m_bitmap )
00070             delete m_bitmap;
00071     }
00072 
00073     if ( m_font )
00074         delete m_font;
00075 }
00076 
00077 
00078 //--------------------------------------------------------------------------
00079 //  void wxPLDevDC::DrawLine( short x1a, short y1a, short x2a, short y2a )
00080 //
00081 //  Draw a line from (x1a, y1a) to (x2a, y2a).
00082 //--------------------------------------------------------------------------
00083 void wxPLDevDC::DrawLine( short x1a, short y1a, short x2a, short y2a )
00084 {
00085     x1a = (short) ( x1a / scalex ); y1a = (short) ( height - y1a / scaley );
00086     x2a = (short) ( x2a / scalex );        y2a = (short) ( height - y2a / scaley );
00087 
00088     m_dc->DrawLine( (wxCoord) x1a, (wxCoord) y1a, (wxCoord) x2a, (wxCoord) y2a );
00089 
00090     AddtoClipRegion( (int) x1a, (int) y1a, (int) x2a, (int) y2a );
00091 }
00092 
00093 
00094 //--------------------------------------------------------------------------
00095 //  void wxPLDevDC::DrawPolyline( short *xa, short *ya, PLINT npts )
00096 //
00097 //  Draw a poly line - coordinates are in the xa and ya arrays.
00098 //--------------------------------------------------------------------------
00099 void wxPLDevDC::DrawPolyline( short *xa, short *ya, PLINT npts )
00100 {
00101     wxCoord x1a, y1a, x2a, y2a;
00102 
00103     x2a = (wxCoord) ( xa[0] / scalex );
00104     y2a = (wxCoord) ( height - ya[0] / scaley );
00105     for ( PLINT i = 1; i < npts; i++ )
00106     {
00107         x1a = x2a; y1a = y2a;
00108         x2a = (wxCoord) ( xa[i] / scalex );
00109         y2a = (wxCoord) ( height - ya[i] / scaley );
00110 
00111         m_dc->DrawLine( x1a, y1a, x2a, y2a );
00112 
00113         AddtoClipRegion( (int) x1a, (int) y1a, (int) x2a, (int) y2a );
00114     }
00115 }
00116 
00117 
00118 //--------------------------------------------------------------------------
00119 //  void wxPLDevDC::ClearBackground( PLINT bgr, PLINT bgg, PLINT bgb,
00120 //                                   PLINT x1, PLINT y1, PLINT x2, PLINT y2 )
00121 //
00122 //  Clear parts ((x1,y1) to (x2,y2)) of the background in color (bgr,bgg,bgb).
00123 //--------------------------------------------------------------------------
00124 void wxPLDevDC::ClearBackground( PLINT bgr, PLINT bgg, PLINT bgb,
00125                                  PLINT x1, PLINT y1, PLINT x2, PLINT y2 )
00126 {
00127     if ( x1 < 0 )
00128         x1 = 0;
00129     else
00130         x1 = (PLINT) ( x1 / scalex );
00131     if ( y1 < 0 )
00132         y1 = 0;
00133     else
00134         y1 = (PLINT) ( height - y1 / scaley );
00135     if ( x2 < 0 )
00136         x2 = width;
00137     else
00138         x2 = (PLINT) ( x2 / scalex );
00139     if ( y2 < 0 )
00140         y2 = height;
00141     else
00142         y2 = (PLINT) ( height - y2 / scaley );
00143 
00144     const wxPen   oldPen   = m_dc->GetPen();
00145     const wxBrush oldBrush = m_dc->GetBrush();
00146 
00147     m_dc->SetPen( *( wxThePenList->FindOrCreatePen( wxColour( bgr, bgg, bgb ), 1, wxSOLID ) ) );
00148     m_dc->SetBrush( wxBrush( wxColour( bgr, bgg, bgb ) ) );
00149     m_dc->DrawRectangle( x1, y1, x2 - x1, y2 - y1 );
00150 
00151     m_dc->SetPen( oldPen );
00152     m_dc->SetBrush( oldBrush );
00153 
00154     AddtoClipRegion( x1, y1, x2, y2 );
00155 }
00156 
00157 
00158 //--------------------------------------------------------------------------
00159 //  void wxPLDevDC::FillPolygon( PLStream *pls )
00160 //
00161 //  Draw a filled polygon.
00162 //--------------------------------------------------------------------------
00163 void wxPLDevDC::FillPolygon( PLStream *pls )
00164 {
00165     wxPoint *points = new wxPoint[pls->dev_npts];
00166     wxCoord xoffset = 0;
00167     wxCoord yoffset = 0;
00168 
00169     for ( int i = 0; i < pls->dev_npts; i++ )
00170     {
00171         points[i].x = (int) ( pls->dev_x[i] / scalex );
00172         points[i].y = (int) ( height - pls->dev_y[i] / scaley );
00173         if ( i > 0 )
00174             AddtoClipRegion( points[i - 1].x, points[i - 1].y, points[i].x, points[i].y );
00175     }
00176 
00177     if ( pls->dev_eofill )
00178     {
00179         m_dc->DrawPolygon( pls->dev_npts, points, xoffset, yoffset, wxODDEVEN_RULE );
00180     }
00181     else
00182     {
00183         m_dc->DrawPolygon( pls->dev_npts, points, xoffset, yoffset, wxWINDING_RULE );
00184     }
00185     delete[] points;
00186 }
00187 
00188 
00189 //--------------------------------------------------------------------------
00190 //  void wxPLDevDC::BlitRectangle( wxDC* dc, int vX, int vY,
00191 //                                 int vW, int vH )
00192 //
00193 //  Copy/Blit a rectangle ((vX,vY) to (vX+vW,vY+vH)) into given dc.
00194 //--------------------------------------------------------------------------
00195 void wxPLDevDC::BlitRectangle( wxDC* dc, int vX, int vY, int vW, int vH )
00196 {
00197     if ( m_dc )
00198         dc->Blit( vX, vY, vW, vH, m_dc, vX, vY );
00199 }
00200 
00201 
00202 //--------------------------------------------------------------------------
00203 //  void wxPLDevDC::CreateCanvas( void )
00204 //
00205 //  Create canvas (bitmap and dc) if the driver provides the GUI.
00206 //--------------------------------------------------------------------------
00207 void wxPLDevDC::CreateCanvas()
00208 {
00209     if ( ownGUI )
00210     {
00211         if ( !m_dc )
00212             m_dc = new wxMemoryDC();
00213 
00214         ( (wxMemoryDC *) m_dc )->SelectObject( wxNullBitmap ); // deselect bitmap
00215         if ( m_bitmap )
00216             delete m_bitmap;
00217         m_bitmap = new wxBitmap( bm_width, bm_height, 32 );
00218         ( (wxMemoryDC *) m_dc )->SelectObject( *m_bitmap ); // select new bitmap
00219     }
00220 }
00221 
00222 
00223 //--------------------------------------------------------------------------
00224 //  void wxPLDevDC::SetWidth( PLStream *pls )
00225 //
00226 //  Set the width of the drawing pen.
00227 //--------------------------------------------------------------------------
00228 void wxPLDevDC::SetWidth( PLStream *pls )
00229 {
00230     m_dc->SetPen( *( wxThePenList->FindOrCreatePen( wxColour( pls->curcolor.r, pls->curcolor.g, pls->curcolor.b ),
00231                          pls->width > 0 ? pls->width : 1, wxSOLID ) ) );
00232 }
00233 
00234 
00235 //--------------------------------------------------------------------------
00236 //  void wxPLDevDC::SetColor0( PLStream *pls )
00237 //
00238 //  Set color from colormap 0.
00239 //--------------------------------------------------------------------------
00240 void wxPLDevDC::SetColor0( PLStream *pls )
00241 {
00242     m_dc->SetPen( *( wxThePenList->FindOrCreatePen( wxColour( pls->curcolor.r, pls->curcolor.g, pls->curcolor.b, pls->curcolor.a ),
00243                          pls->width > 0 ? pls->width : 1, wxSOLID ) ) );
00244     m_dc->SetBrush( wxBrush( wxColour( pls->curcolor.r, pls->curcolor.g, pls->curcolor.b, pls->curcolor.a ) ) );
00245 }
00246 
00247 
00248 //--------------------------------------------------------------------------
00249 //  void wxPLDevDC::SetColor1( PLStream *pls )
00250 //
00251 //  Set color from colormap 1.
00252 //--------------------------------------------------------------------------
00253 void wxPLDevDC::SetColor1( PLStream *pls )
00254 {
00255     m_dc->SetPen( *( wxThePenList->FindOrCreatePen( wxColour( pls->curcolor.r, pls->curcolor.g, pls->curcolor.b, pls->curcolor.a ),
00256                          pls->width > 0 ? pls->width : 1, wxSOLID ) ) );
00257     m_dc->SetBrush( wxBrush( wxColour( pls->curcolor.r, pls->curcolor.g, pls->curcolor.b, pls->curcolor.a ) ) );
00258 }
00259 
00260 
00261 //--------------------------------------------------------------------------
00262 //  void wxPLDevDC::SetExternalBuffer( void* dc )
00263 //
00264 //  Adds a dc to the device. In that case, the drivers doesn't provide
00265 //  a GUI.
00266 //--------------------------------------------------------------------------
00267 void wxPLDevDC::SetExternalBuffer( void* dc )
00268 {
00269     m_dc   = (wxDC *) dc; // Add the dc to the device
00270     ready  = true;
00271     ownGUI = false;
00272 }
00273 
00274 
00275 #ifdef PL_HAVE_FREETYPE
00276 
00277 //--------------------------------------------------------------------------
00278 //  void wxPLDevDC::PutPixel( short x, short y, PLINT color )
00279 //
00280 //  Draw a pixel in color color @ (x,y).
00281 //--------------------------------------------------------------------------
00282 void wxPLDevDC::PutPixel( short x, short y, PLINT color )
00283 {
00284     const wxPen oldpen = m_dc->GetPen();
00285     m_dc->SetPen( *( wxThePenList->FindOrCreatePen( wxColour( GetRValue( color ), GetGValue( color ), GetBValue( color ) ),
00286                          1, wxSOLID ) ) );
00287     m_dc->DrawPoint( x, y );
00288     AddtoClipRegion( x, y, x, y );
00289     m_dc->SetPen( oldpen );
00290 }
00291 
00292 
00293 //--------------------------------------------------------------------------
00294 //  void wxPLDevDC::PutPixel( short x, short y )
00295 //
00296 //  Draw a pixel in current color @ (x,y).
00297 //--------------------------------------------------------------------------
00298 void wxPLDevDC::PutPixel( short x, short y )
00299 {
00300     m_dc->DrawPoint( x, y );
00301     AddtoClipRegion( x, y, x, y );
00302 }
00303 
00304 
00305 //--------------------------------------------------------------------------
00306 //  PLINT wxPLDevDC::GetPixel( short x, short y )
00307 //
00308 //  Get color information from pixel @ (x,y).
00309 //--------------------------------------------------------------------------
00310 PLINT wxPLDevDC::GetPixel( short x, short y )
00311 {
00312 #ifdef __WXGTK__
00313     // The GetPixel method is incredible slow for wxGTK. Therefore we set the colour
00314     // always to the background color, since this is the case anyway 99% of the time.
00315     PLINT bgr, bgg, bgb;           // red, green, blue
00316     (void) x;  (void) y;           // Cast to void to silence compiler warnings about unused parameters
00317     plgcolbg( &bgr, &bgg, &bgb );  // get background color information
00318     return RGB( bgr, bgg, bgb );
00319 #else
00320     wxColour col;
00321     m_dc->GetPixel( x, y, &col );
00322     return RGB( col.Red(), col.Green(), col.Blue() );
00323 #endif
00324 }
00325 
00326 #endif // PL_HAVE_FREETYPE
00327 
00328 
00329 //--------------------------------------------------------------------------
00330 //  void wxPLDevDC::PSDrawTextToDC( char* utf8_string, bool drawText )
00331 //
00332 //  Draw utf8 text to screen if drawText==true. Otherwise determine
00333 //  width and height of text.
00334 //--------------------------------------------------------------------------
00335 void wxPLDevDC::PSDrawTextToDC( char* utf8_string, bool drawText )
00336 {
00337     wxCoord  w, h, d, l;
00338 
00339     wxString str( wxConvUTF8.cMB2WC( utf8_string ), *wxConvCurrent );
00340 
00341     m_dc->GetTextExtent( str, &w, &h, &d, &l );
00342 
00343     if ( drawText )
00344     {
00345         m_dc->DrawRotatedText( str, (wxCoord) ( posX - yOffset / scaley * sin_rot ),
00346             (wxCoord) ( height - (wxCoord) ( posY + yOffset * cos_rot / scaley ) ),
00347             rotation * 180.0 / M_PI );
00348         posX += (PLINT) ( w * cos_rot );
00349         posY += (PLINT) ( w * sin_rot );
00350     }
00351 
00352     textWidth += w;
00353 
00354     //keep track of the height of superscript text, the depth of subscript
00355     //text and the height of regular text
00356     if ( yOffset > 0.0001 )
00357     {
00358         //determine the height the text would have if it were full size
00359         double currentOffset = yOffset;
00360         double currentHeight = h;
00361         while ( currentOffset > 0.0001 )
00362         {
00363             currentOffset -= scaley * fontSize * fontScale / 2.;
00364             currentHeight *= 1.25;
00365         }
00366         textHeight = (wxCoord) textHeight > ( currentHeight )
00367                      ? textHeight
00368                      : currentHeight;
00369         //work out the height including superscript
00370         superscriptHeight = superscriptHeight > ( currentHeight + yOffset / scaley )
00371                             ? superscriptHeight
00372                             : static_cast<int>( ( currentHeight + yOffset / scaley ) );
00373     }
00374     else if ( yOffset < -0.0001 )
00375     {
00376         //determine the height the text would have if it were full size
00377         double currentOffset = yOffset;
00378         double currentHeight = h;
00379         double currentDepth  = d;
00380         while ( currentOffset < -0.0001 )
00381         {
00382             currentOffset += scaley * fontSize * fontScale * 1.25 / 2.;
00383             currentHeight *= 1.25;
00384             currentDepth  *= 1.25;
00385         }
00386         textHeight = (wxCoord) textHeight > currentHeight ? textHeight : currentHeight;
00387         //work out the additional depth for subscript note an assumption has been made
00388         //that the font size of (non-superscript and non-subscript) text is the same
00389         //along a line. Currently there is no escape to change font size mid string
00390         //so this should be fine
00391         subscriptDepth = (wxCoord) subscriptDepth > ( ( -yOffset / scaley + h + d ) - ( currentDepth + textHeight ) )
00392                          ? subscriptDepth
00393                          : ( ( -yOffset / scaley + h + d ) - ( currentDepth + textHeight ) );
00394         subscriptDepth = subscriptDepth > 0 ? subscriptDepth : 0;
00395     }
00396     else
00397         textHeight = (wxCoord) textHeight > ( h ) ? textHeight : h;
00398 
00399     memset( utf8_string, '\0', max_string_length );
00400 }
00401 
00402 
00403 //--------------------------------------------------------------------------
00404 //  void wxPLDevDC::PSSetFont( PLUNICODE fci )
00405 //
00406 //  Set font defined by fci.
00407 //--------------------------------------------------------------------------
00408 void wxPLDevDC::PSSetFont( PLUNICODE fci )
00409 {
00410     unsigned char fontFamily, fontStyle, fontWeight;
00411 
00412     plP_fci2hex( fci, &fontFamily, PL_FCI_FAMILY );
00413     plP_fci2hex( fci, &fontStyle, PL_FCI_STYLE );
00414     plP_fci2hex( fci, &fontWeight, PL_FCI_WEIGHT );
00415 
00416     if ( m_font )
00417         delete m_font;
00418 
00419     m_font = wxFont::New( (int) ( fontSize * fontScale < 4 ? 4 : fontSize * fontScale ),
00420         fontFamilyLookup[fontFamily],
00421         fontStyleLookup[fontStyle] | fontWeightLookup[fontWeight] );
00422     m_font->SetUnderlined( underlined );
00423     m_dc->SetFont( *m_font );
00424 }
00425 
00426 
00427 //--------------------------------------------------------------------------
00428 //  void wxPLDevDC::ProcessString( PLStream* pls, EscText* args )
00429 //
00430 //  This is the main function which processes the unicode text strings.
00431 //  Font size, rotation and color are set, width and height of the
00432 //  text string is determined and then the string is drawn to the canvas.
00433 //--------------------------------------------------------------------------
00434 void wxPLDevDC::ProcessString( PLStream* pls, EscText* args )
00435 {
00436     // Check that we got unicode, warning message and return if not
00437     if ( args->unicode_array_len == 0 )
00438     {
00439         printf( "Non unicode string passed to the wxWidgets driver, ignoring\n" );
00440         return;
00441     }
00442 
00443     // Check that unicode string isn't longer then the max we allow
00444     if ( args->unicode_array_len >= 500 )
00445     {
00446         printf( "Sorry, the wxWidgets drivers only handles strings of length < %d\n", 500 );
00447         return;
00448     }
00449 
00450     // Calculate the font size (in pixels)
00451     fontSize = pls->chrht * VIRTUAL_PIXELS_PER_MM / scaley * 1.3;
00452 
00453     // Use PLplot core routine to get the corners of the clipping rectangle
00454     PLINT rcx[4], rcy[4];
00455     difilt_clip( rcx, rcy );
00456 
00457     wxPoint cpoints[4];
00458     for ( int i = 0; i < 4; i++ )
00459     {
00460         cpoints[i].x = rcx[i] / scalex;
00461         cpoints[i].y = height - rcy[i] / scaley;
00462     }
00463     wxDCClipper clip( *m_dc, wxRegion( 4, cpoints ) );
00464 
00465     // calculate rotation of text
00466     plRotationShear( args->xform, &rotation, &shear, &stride );
00467     rotation -= pls->diorot * M_PI / 2.0;
00468     cos_rot   = cos( rotation );
00469     sin_rot   = sin( rotation );
00470 
00471     // Set font color
00472     m_dc->SetTextForeground( wxColour( pls->curcolor.r, pls->curcolor.g, pls->curcolor.b ) );
00473     m_dc->SetTextBackground( wxColour( pls->curcolor.r, pls->curcolor.g, pls->curcolor.b ) );
00474 
00475     PLUNICODE *lineStart     = args->unicode_array;
00476     int       lineLen        = 0;
00477     bool      lineFeed       = false;
00478     bool      carriageReturn = false;
00479     wxCoord   paraHeight     = 0;
00480     // Get the curent font
00481     fontScale = 1.0;
00482     yOffset   = 0.0;
00483     plgfci( &fci );
00484     PSSetFont( fci );
00485     while ( lineStart != args->unicode_array + args->unicode_array_len )
00486     {
00487         while ( lineStart + lineLen != args->unicode_array + args->unicode_array_len
00488                 && *( lineStart + lineLen ) != (PLUNICODE) '\n' )
00489         {
00490             lineLen++;
00491         }
00492         //set line feed for the beginning of this line and
00493         //carriage return for the end
00494         lineFeed       = carriageReturn;
00495         carriageReturn = lineStart + lineLen != args->unicode_array + args->unicode_array_len
00496                          && *( lineStart + lineLen ) == (PLUNICODE) ( '\n' );
00497         if ( lineFeed )
00498             paraHeight += textHeight + subscriptDepth;
00499 
00500         //remember the text parameters so they can be restored
00501         double    startingFontScale = fontScale;
00502         double    startingYOffset   = yOffset;
00503         PLUNICODE startingFci       = fci;
00504 
00505         // determine extent of text
00506         posX = args->x / scalex;
00507         posY = args->y / scaley;
00508 
00509         PSDrawText( lineStart, lineLen, false );
00510 
00511         if ( lineFeed && superscriptHeight > textHeight )
00512             paraHeight += superscriptHeight - textHeight;
00513 
00514         // actually draw text, resetting the font first
00515         fontScale = startingFontScale;
00516         yOffset   = startingYOffset;
00517         fci       = startingFci;
00518         PSSetFont( fci );
00519         posX = (PLINT) ( args->x / scalex - ( args->just * textWidth ) * cos_rot - ( 0.5 * textHeight - paraHeight * lineSpacing ) * sin_rot ); //move to set alignment
00520         posY = (PLINT) ( args->y / scaley - ( args->just * textWidth ) * sin_rot + ( 0.5 * textHeight - paraHeight * lineSpacing ) * cos_rot );
00521         PSDrawText( lineStart, lineLen, true );                                                                                                 //draw text
00522 
00523         lineStart += lineLen;
00524         if ( carriageReturn )
00525             lineStart++;
00526         lineLen = 0;
00527     }
00528     //posX = args->x;
00529     //posY = args->y;
00530     //PSDrawText( args->unicode_array, args->unicode_array_len, false );
00531 
00532     //posX = (PLINT) ( args->x - ( ( args->just * textWidth ) * cos_rot + ( 0.5 * textHeight ) * sin_rot ) * scalex );
00533     //posY = (PLINT) ( args->y - ( ( args->just * textWidth ) * sin_rot - ( 0.5 * textHeight ) * cos_rot ) * scaley );
00534     //PSDrawText( args->unicode_array, args->unicode_array_len, true );
00535 
00536     AddtoClipRegion( 0, 0, width, height );
00537 }
00538 
00539 
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Defines