PLplot  5.10.0
wxwidgets_agg.cpp
Go to the documentation of this file.
00001 // Copyright (C) 2008  Werner Smekal
00002 //
00003 // This file is part of PLplot.
00004 //
00005 // PLplot is free software; you can redistribute it and/or modify
00006 // it under the terms of the GNU Library General Public License as published
00007 // by the Free Software Foundation; either version 2 of the License, or
00008 // (at your option) any later version.
00009 //
00010 // PLplot is distributed in the hope that it will be useful,
00011 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00012 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00013 // GNU Library General Public License for more details.
00014 //
00015 // You should have received a copy of the GNU Library General Public License
00016 // along with PLplot; if not, write to the Free Software
00017 // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
00018 //
00019 
00020 // TODO:
00021 // - let the AGG library process the text. In the moment most of the relevant code
00022 //   is commented out, since there are problems with the affine transformation
00023 //
00024 
00025 // wxwidgets headers
00026 #include <wx/wx.h>
00027 #include <wx/strconv.h>
00028 
00029 #include "plDevs.h"
00030 
00031 // plplot headers
00032 #include "plplotP.h"
00033 #include "plfci-truetype.h"
00034 
00035 // std and driver headers
00036 #include "wxwidgets.h"
00037 #include <wchar.h>
00038 
00039 // helper functions
00040 #if !defined ( WIN32 ) || defined ( __GNUC__ )
00041   #include <unistd.h>
00042 #else
00043   #define F_OK    1
00044   #include <stdio.h>
00045 int access( char *filename, int flag )
00046 {
00047     FILE *infile;
00048     infile = fopen( filename, "r" );
00049     if ( infile != NULL )
00050     {
00051         fclose( infile );
00052         return 0;
00053     }
00054     else
00055         return 1;
00056 }
00057 #endif
00058 
00059 #define makeunixslash( b )    do { char *I; for ( I = b; *I != 0; *I++ ) if ( *I == '\\' ) *I = '/';} while ( 0 )
00060 
00061 //--------------------------------------------------------------------------
00062 //  wxPLDevAGG::wxPLDevAGG()
00063 //
00064 //  Constructor of the AGG wxWidgets device based on the wxPLDevBase
00065 //  class. Initialisations of variables and objects are done.
00066 //--------------------------------------------------------------------------
00067 wxPLDevAGG::wxPLDevAGG() :
00068     wxPLDevBase( wxBACKEND_AGG ),
00069     mRenderingBuffer(),
00070     mPixFormat( mRenderingBuffer ),
00071     mRendererBase( mPixFormat ),
00072     mRendererSolid( mRendererBase ),
00073 
00074     mPath(),
00075     mTransform(),
00076     mConvCurve( mPath ),
00077     mConvStroke( mConvCurve ),
00078     mPathTransform( mConvCurve, mTransform ),
00079     mStrokeTransform( mConvStroke, mTransform ),
00080 
00081     mFontEngine(),
00082     mFontManager( mFontEngine ),
00083     mCurves( mFontManager.path_adaptor() ),
00084     mContour( mCurves ),
00085 
00086     mBuffer( NULL ),
00087     mStrokeWidth( 1.0 ),
00088     mStrokeOpacity( 255 ),
00089     mColorRedStroke( 255 ),
00090     mColorGreenStroke( 255 ),
00091     mColorBlueStroke( 255 ),
00092     mColorRedFill( 0 ),
00093     mColorGreenFill( 0 ),
00094     mColorBlueFill( 0 )
00095 {
00096     mCurves.approximation_scale( 2.0 );
00097     mContour.auto_detect_orientation( false );
00098     mConvStroke.line_join( agg::round_join );
00099     mConvStroke.line_cap( agg::round_cap );
00100 
00101     // determine font directory
00102 #if defined ( WIN32 )
00103     //static char *default_font_names[]={"arial.ttf","times.ttf","timesi.ttf","arial.ttf",
00104     //                                 "symbol.ttf"};
00105     // char WINDIR_PATH[255];
00106     // char *b;
00107     // b=getenv("WINDIR");
00108     // strncpy(WINDIR_PATH,b,255);
00109 
00110 //
00111 // Work out if we have Win95+ or Win3.?... sort of.
00112 // Actually, this just tries to find the place where the fonts live by looking
00113 // for arial, which should be on all windows machines.
00114 // At present, it only looks in two places, on one drive. I might change this
00115 // soon.
00116 //
00117     //if (WINDIR_PATH==NULL)
00118     // {
00119     //  if (access("c:\\windows\\fonts\\arial.ttf", F_OK)==0) {
00120     //      strcpy(font_dir,"c:/windows/fonts/");
00121     //  }
00122     //  else if ( access("c:\\windows\\system\\arial.ttf", F_OK)==0) {
00123     //      strcpy(font_dir,"c:/windows/system/");
00124     //  }
00125     //  else
00126     //  plwarn("Could not find font path; I sure hope you have defined fonts manually !");
00127     // }
00128     // else
00129     // {
00130     // strncat(WINDIR_PATH,"\\fonts\\arial.ttf",255);
00131     // if (access(WINDIR_PATH, F_OK)==0)
00132     //  {
00133     //    b=strrchr(WINDIR_PATH,'\\');
00134     //    b++;
00135     //b=0;
00136     //    makeunixslash(WINDIR_PATH);
00137     //    strcpy(font_dir,WINDIR_PATH);
00138     //  }
00139     // else
00140     //  plwarn("Could not find font path; I sure hope you have defined fonts manually !");
00141     // }
00142     //
00143     // if (pls->debug) fprintf( stderr, "%s\n", font_dir ) ;
00144 #else
00145     //  For Unix systems, we will set the font path up a little differently in
00146     //  that the configured PL_FREETYPE_FONT_DIR has been set as the default path,
00147     //  but the user can override this by setting the environmental variable
00148     //  "PLPLOT_FREETYPE_FONT_DIR" to something else.
00149     //  NOTE WELL - the trailing slash must be added for now !
00150     //
00151     // const char *str;
00152     //
00153     // fontdir.Clear();
00154     // if( (str=getenv("PLPLOT_FREETYPE_FONT_DIR"))!=NULL )
00155     //      fontdir.Append( wxString(str, wxConvFile) );
00156     // else
00157     //      fontdir.Append( wxT(PL_FREETYPE_FONT_DIR) );
00158     //
00159     // //printf("fontdir=%s, len=%d\n", fontdir.c_str(), fontdir.Length() );
00160 #endif
00161 }
00162 
00163 
00164 //--------------------------------------------------------------------------
00165 //  wxPLDevAGG::~wxPLDevAGG()
00166 //
00167 //  Deconstructor frees allocated buffer.
00168 //--------------------------------------------------------------------------
00169 wxPLDevAGG::~wxPLDevAGG()
00170 {
00171     if ( ownGUI )
00172         if ( mBuffer )
00173             delete mBuffer;
00174 }
00175 
00176 
00177 //--------------------------------------------------------------------------
00178 //  void wxPLDevAGG::drawPath( drawPathFlag flag )
00179 //
00180 //  Common function which either draws a stroke along a path or a filled
00181 //  polygon surrounded by a stroke depending on flag.
00182 //--------------------------------------------------------------------------
00183 void wxPLDevAGG::drawPath( drawPathFlag flag )
00184 {
00185     mRasterizer.reset();
00186 
00187     switch ( flag )
00188     {
00189     case Stroke:
00190         if ( mStrokeOpacity && mStrokeWidth > 0.0 )
00191         {
00192             mConvStroke.width( mStrokeWidth );
00193             mRasterizer.add_path( mStrokeTransform );
00194             mRendererSolid.color( agg::rgba8( mColorRedStroke, mColorGreenStroke, mColorBlueStroke, mStrokeOpacity ) );
00195             agg::render_scanlines( mRasterizer, mScanLine, mRendererSolid );
00196         }
00197         break;
00198     case FillAndStroke:
00199         if ( mStrokeOpacity )
00200         {
00201             mRasterizer.add_path( mPathTransform );
00202             mRendererSolid.color( agg::rgba8( mColorRedStroke, mColorGreenStroke, mColorBlueStroke, mStrokeOpacity ) );
00203             agg::render_scanlines( mRasterizer, mScanLine, mRendererSolid );
00204         }
00205 
00206         if ( mStrokeOpacity && mStrokeWidth > 0.0 )
00207         {
00208             mConvStroke.width( mStrokeWidth );
00209             mRasterizer.add_path( mStrokeTransform );
00210             mRendererSolid.color( agg::rgba8( mColorRedStroke, mColorGreenStroke, mColorBlueStroke, mStrokeOpacity ) );
00211             agg::render_scanlines( mRasterizer, mScanLine, mRendererSolid );
00212         }
00213         break;
00214     }
00215 }
00216 
00217 
00218 //--------------------------------------------------------------------------
00219 //  void wxPLDevAGG::DrawLine( short x1a, short y1a, short x2a, short y2a )
00220 //
00221 //  Draw a line from (x1a, y1a) to (x2a, y2a).
00222 //--------------------------------------------------------------------------
00223 void wxPLDevAGG::DrawLine( short x1a, short y1a, short x2a, short y2a )
00224 {
00225     mPath.remove_all();
00226     mPath.move_to( x1a, y1a );
00227     mPath.line_to( x2a, y2a );
00228 
00229     if ( !resizing && ownGUI )
00230         AGGAddtoClipRegion( x1a, y1a, x2a, y2a );
00231 
00232     drawPath( Stroke );
00233 }
00234 
00235 
00236 //--------------------------------------------------------------------------
00237 //  void wxPLDevAGG::DrawPolyline( short *xa, short *ya, PLINT npts )
00238 //
00239 //  Draw a poly line - coordinates are in the xa and ya arrays.
00240 //--------------------------------------------------------------------------
00241 void wxPLDevAGG::DrawPolyline( short *xa, short *ya, PLINT npts )
00242 {
00243     mPath.remove_all();
00244     mPath.move_to( xa[0], ya[0] );
00245     for ( PLINT i = 1; i < npts; i++ )
00246     {
00247         mPath.line_to( xa[i], ya[i] );
00248         if ( !resizing && ownGUI )
00249             AGGAddtoClipRegion( xa[i - 1], ya[i - 1], xa[i], ya[i] );
00250     }
00251 
00252     drawPath( Stroke );
00253 }
00254 
00255 
00256 //--------------------------------------------------------------------------
00257 //  void wxPLDevAGG::ClearBackground( PLINT bgr, PLINT bgg, PLINT bgb,
00258 //                                    PLINT x1, PLINT y1, PLINT x2, PLINT y2 )
00259 //
00260 //  Clear parts ((x1,y1) to (x2,y2)) of the background in color (bgr,bgg,bgb).
00261 //--------------------------------------------------------------------------
00262 void wxPLDevAGG::ClearBackground( PLINT bgr, PLINT bgg, PLINT bgb, PLINT x1, PLINT y1, PLINT x2, PLINT y2 )
00263 {
00264     if ( x1 < 0 && y1 < 0 && x2 < 0 && y2 < 0 )
00265     {
00266         mRendererBase.clear( agg::rgba8( bgr, bgg, bgb ) );
00267         if ( !resizing && ownGUI )
00268             AddtoClipRegion( 0, 0, width, height );
00269     }
00270     else
00271     {
00272         mPath.remove_all();
00273         mPath.move_to( x1, y1 );
00274         mPath.line_to( x2, y1 );
00275         mPath.line_to( x2, y2 );
00276         mPath.line_to( x1, y2 );
00277         mPath.close_polygon();
00278 
00279         mRasterizer.reset();
00280         mRasterizer.add_path( mPathTransform );
00281         mRendererSolid.color( agg::rgba8( bgr, bgg, bgb, 255 ) );
00282         agg::render_scanlines( mRasterizer, mScanLine, mRendererSolid );
00283 
00284         mConvStroke.width( 1.0 );
00285         mRasterizer.add_path( mStrokeTransform );
00286         mRendererSolid.color( agg::rgba8( bgr, bgg, bgb, 255 ) );
00287         agg::render_scanlines( mRasterizer, mScanLine, mRendererSolid );
00288 
00289         if ( !resizing && ownGUI )
00290             AGGAddtoClipRegion( x1, y1, x2, y2 );
00291     }
00292 }
00293 
00294 
00295 //--------------------------------------------------------------------------
00296 //  void wxPLDevAGG::AGGAddtoClipRegion( short x1, short y1,
00297 //                                       short x2, short y2 )
00298 //
00299 //  Adds the region (x1,y1)-(x2,y2) to the regions which needs to be
00300 //  updated/redrawn.
00301 //--------------------------------------------------------------------------
00302 void wxPLDevAGG::AGGAddtoClipRegion( short x1, short y1, short x2, short y2 )
00303 {
00304     double x1d = x1, x2d = x2, y1d = y1, y2d = y2;
00305 
00306     mTransform.transform( &x1d, &y1d );
00307     mTransform.transform( &x2d, &y2d );
00308     AddtoClipRegion( (int) floor( x1d ), (int) floor( y1d ), (int) ceil( x2d ), (int) ceil( y2d ) );
00309 }
00310 
00311 
00312 //--------------------------------------------------------------------------
00313 //  void wxPLDevAGG::FillPolygon( PLStream *pls )
00314 //
00315 //  Draw a filled polygon.
00316 //--------------------------------------------------------------------------
00317 void wxPLDevAGG::FillPolygon( PLStream *pls )
00318 {
00319     short *xa = pls->dev_x;
00320     short *ya = pls->dev_y;
00321 
00322     mPath.remove_all();
00323     mPath.move_to( xa[0], ya[0] );
00324     for ( PLINT i = 1; i < pls->dev_npts; i++ )
00325     {
00326         mPath.line_to( xa[i], ya[i] );
00327         if ( !resizing && ownGUI )
00328             AGGAddtoClipRegion( xa[i - 1], ya[i - 1], xa[i], ya[i] );
00329     }
00330     mPath.line_to( xa[0], ya[0] );
00331     mPath.close_polygon();
00332 
00333     drawPath( FillAndStroke );
00334 }
00335 
00336 
00337 //--------------------------------------------------------------------------
00338 //  void wxPLDevAGG::BlitRectangle( wxDC* dc, int vX, int vY,
00339 //                                  int vW, int vH )
00340 //
00341 //  Copy/Blit a rectangle ((vX,vY) to (vX+vW,vY+vH)) into given dc.
00342 //--------------------------------------------------------------------------
00343 void wxPLDevAGG::BlitRectangle( wxDC* dc, int vX, int vY, int vW, int vH )
00344 {
00345     if ( mBuffer )
00346     {
00347         wxMemoryDC MemoryDC;
00348         wxBitmap   bitmap( mBuffer->GetSubImage( wxRect( vX, vY, vW, vH ) ), -1 );
00349         MemoryDC.SelectObject( bitmap );
00350         dc->Blit( vX, vY, vW, vH, &MemoryDC, 0, 0 );
00351         MemoryDC.SelectObject( wxNullBitmap );
00352     }
00353 }
00354 
00355 
00356 //--------------------------------------------------------------------------
00357 //  void wxPLDevAGG::CreateCanvas( void )
00358 //
00359 //  Create canvas (bitmap and dc) if the driver provides the GUI.
00360 //--------------------------------------------------------------------------
00361 void wxPLDevAGG::CreateCanvas()
00362 {
00363     if ( ownGUI )
00364     {
00365         // get a new wxImage (image buffer)
00366         if ( mBuffer )
00367             delete mBuffer;
00368         mBuffer = new wxImage( bm_width, bm_height );
00369         mRenderingBuffer.attach( mBuffer->GetData(), bm_width, bm_height, bm_width * 3 );
00370     }
00371     else
00372         mRenderingBuffer.attach( mBuffer->GetData(), width, height, width * 3 );
00373 
00374     mRendererBase.reset_clipping( true );
00375     mTransform.reset();
00376     mTransform.premultiply( agg::trans_affine_translation( 0.0, height ) );
00377     mTransform.premultiply( agg::trans_affine_scaling( 1.0 / scalex, -1.0 / scaley ) );
00378     mStrokeWidth = ( scalex + scaley ) / 2.0;
00379 }
00380 
00381 
00382 //--------------------------------------------------------------------------
00383 //  void wxPLDevAGG::SetWidth( PLStream *pls )
00384 //
00385 //  Set the width of the drawing pen.
00386 //--------------------------------------------------------------------------
00387 void wxPLDevAGG::SetWidth( PLStream *pls )
00388 {
00389     mStrokeWidth = ( scalex + scaley ) / 2.0 * ( pls->width > 0 ? pls->width : 1 ); // TODO: why and when ist width 0???
00390 }
00391 
00392 
00393 //--------------------------------------------------------------------------
00394 //  void wxPLDevAGG::SetColor0( PLStream *pls )
00395 //
00396 //  Set color from colormap 0.
00397 //--------------------------------------------------------------------------
00398 void wxPLDevAGG::SetColor0( PLStream *pls )
00399 {
00400     mColorRedStroke   = pls->curcolor.r;
00401     mColorGreenStroke = pls->curcolor.g;
00402     mColorBlueStroke  = pls->curcolor.b;
00403     mStrokeOpacity    = (wxUint8) ( pls->curcolor.a * 255 );
00404 }
00405 
00406 
00407 //--------------------------------------------------------------------------
00408 //  void wxPLDevAGG::SetColor1( PLStream *pls )
00409 //
00410 //  Set color from colormap 1.
00411 //--------------------------------------------------------------------------
00412 void wxPLDevAGG::SetColor1( PLStream *pls )
00413 {
00414     mColorRedStroke   = pls->curcolor.r;
00415     mColorGreenStroke = pls->curcolor.g;
00416     mColorBlueStroke  = pls->curcolor.b;
00417     mStrokeOpacity    = (wxUint8) ( pls->curcolor.a * 255 );
00418 }
00419 
00420 
00421 //--------------------------------------------------------------------------
00422 //  void wxPLDevAGG::SetExternalBuffer( void* dc )
00423 //
00424 //  Adds a dc to the device. In that case, the drivers doesn't provide
00425 //  a GUI. A new buffer (image) will be created and set up.
00426 //--------------------------------------------------------------------------
00427 void wxPLDevAGG::SetExternalBuffer( void* image )
00428 {
00429     mBuffer = (wxImage *) image; // Add the image to the device
00430     mRenderingBuffer.attach( mBuffer->GetData(), width, height, width * 3 );
00431 
00432     mRendererBase.reset_clipping( true );
00433     mTransform.reset();
00434     mTransform.premultiply( agg::trans_affine_translation( 0.0, height ) );
00435     mTransform.premultiply( agg::trans_affine_scaling( 1.0 / scalex, -1.0 / scaley ) );
00436     mStrokeWidth = ( scalex + scaley ) / 2.0;
00437 
00438     ready  = true;
00439     ownGUI = false;
00440 }
00441 
00442 
00443 #ifdef PL_HAVE_FREETYPE
00444 
00445 //--------------------------------------------------------------------------
00446 //  void wxPLDevAGG::PutPixel( short x, short y, PLINT color )
00447 //
00448 //  Draw a pixel in color color @ (x,y).
00449 //--------------------------------------------------------------------------
00450 void wxPLDevAGG::PutPixel( short x, short y, PLINT color )
00451 {
00452     mBuffer->SetRGB( x, y, GetRValue( color ), GetGValue( color ), GetBValue( color ) );
00453     AddtoClipRegion( x, y, x, y );
00454 }
00455 
00456 
00457 //--------------------------------------------------------------------------
00458 //  void wxPLDevAGG::PutPixel( short x, short y )
00459 //
00460 //  Draw a pixel in current color @ (x,y).
00461 //--------------------------------------------------------------------------
00462 void wxPLDevAGG::PutPixel( short x, short y )
00463 {
00464     mBuffer->SetRGB( x, y, mColorRedStroke, mColorGreenStroke, mColorBlueStroke );
00465     AddtoClipRegion( x, y, x, y );
00466 }
00467 
00468 
00469 //--------------------------------------------------------------------------
00470 //  PLINT wxPLDevAGG::GetPixel( short x, short y )
00471 //
00472 //  Get color information from pixel @ (x,y).
00473 //--------------------------------------------------------------------------
00474 PLINT wxPLDevAGG::GetPixel( short x, short y )
00475 {
00476     return RGB( mBuffer->GetRed( x, y ), mBuffer->GetGreen( x, y ), mBuffer->GetBlue( x, y ) );
00477 }
00478 
00479 #endif // PL_HAVE_FREETYPE
00480 
00481 
00482 void wxPLDevAGG::PSDrawTextToDC( char* utf8_string, bool drawText )
00483 {
00484     // Log_Verbose( "%s", __FUNCTION__ );
00485     printf( "utf8_string=%s\n", utf8_string );
00486 
00487     double start_x = 0.0;
00488     double start_y = 0.0;
00489 
00490     //wchar_t str[512];
00491     //size_t len=wxConvUTF8.ToWChar( str, 512, utf8_string );
00492     size_t len   = strlen( utf8_string );
00493     char   * str = utf8_string;
00494     printf( "len=%lu\n", (unsigned long) len );
00495 
00496     const agg::glyph_cache* glyph;
00497     if ( !drawText )
00498     {
00499         double x         = 0;
00500         double y         = 0;
00501         bool   first     = true;
00502         char   * saveStr = str;
00503         while ( *str && len )
00504         {
00505             glyph = mFontManager.glyph( *str );
00506             if ( glyph )
00507             {
00508                 if ( !first )
00509                     mFontManager.add_kerning( &x, &y );
00510                 x    += glyph->advance_x;
00511                 y    += glyph->advance_y;
00512                 first = false;
00513             }
00514             textHeight = textHeight > ( glyph->bounds.y2 - glyph->bounds.y1 + yOffset ) ?
00515                          textHeight : ( glyph->bounds.y2 - glyph->bounds.y1 + yOffset );
00516             ++str; --len;
00517         }
00518         textWidth = x;
00519         printf( "str: %s, textWidth=%lf\n", saveStr, textWidth );
00520     }
00521     else
00522     {
00523         for ( size_t i = 0; i < len && str[i]; i++ )
00524         {
00525             glyph = mFontManager.glyph( str[i] );
00526             if ( glyph )
00527             {
00528                 printf( "before: start_x=%f, start_y=%f\n", start_x, start_y );
00529                 if ( i )
00530                     mFontManager.add_kerning( &start_x, &start_y );
00531                 printf( "after: start_x=%f, start_y=%f\n", start_x, start_y );
00532                 mFontManager.init_embedded_adaptors( glyph, start_x, start_y );
00533 
00534                 mRendererSolid.color( agg::rgba8( mColorRedStroke, mColorGreenStroke, mColorBlueStroke, mStrokeOpacity ) );
00535                 agg::render_scanlines( mFontManager.gray8_adaptor(), mFontManager.gray8_scanline(), mRendererSolid );
00536 
00537                 start_x += glyph->advance_x / scalex;
00538                 //start_y += glyph->advance_y/scaley;
00539             }
00540         }
00541     }
00542 
00543     memset( utf8_string, '\0', max_string_length );
00544 }
00545 
00546 
00547 void wxPLDevAGG::PSSetFont( PLUNICODE fci )
00548 {
00549     // convert the fci to Base14/Type1 font information
00550     wxString fontname = fontdir + wxString( plP_FCI2FontName( fci, TrueTypeLookup, N_TrueTypeLookup ), *wxConvCurrent );
00551 
00552     if ( !mFontEngine.load_font( "/usr/share/fonts/truetype/freefont/FreeSans.ttf", 0, agg::glyph_ren_agg_gray8 ) )
00553         plabort( "Font could not be loaded" );
00554     //mFontEngine.load_font( "c:\\windows\\fonts\\arial.ttf", 0, agg::glyph_ren_agg_gray8 );
00555     mFontEngine.height( fontSize * fontScale );
00556     mFontEngine.width( fontSize * fontScale );
00557     mFontEngine.hinting( true );
00558     mFontEngine.flip_y( false );
00559     mContour.width( fontSize * fontScale * 0.2 );
00560 }
00561 
00562 
00563 void wxPLDevAGG::ProcessString( PLStream* pls, EscText* args )
00564 {
00565     plabort( "The AGG backend can't process the text yet own its own!" );
00566 
00567     // Check that we got unicode, warning message and return if not
00568     if ( args->unicode_array_len == 0 )
00569     {
00570         printf( "Non unicode string passed to a wxWidgets driver, ignoring\n" );
00571         return;
00572     }
00573 
00574     // Check that unicode string isn't longer then the max we allow
00575     if ( args->unicode_array_len >= 500 )
00576     {
00577         printf( "Sorry, the wxWidgets drivers only handles strings of length < %d\n", 500 );
00578         return;
00579     }
00580 
00581     // Calculate the font size (in pixels)
00582     fontSize = pls->chrht * DEVICE_PIXELS_PER_MM * 1.2 * scaley;
00583 
00584     // calculate rotation of text
00585     plRotationShear( args->xform, &rotation, &shear, &stride );
00586     rotation -= pls->diorot * M_PI / 2.0;
00587     cos_shear = cos( shear );
00588     sin_shear = sin( shear );
00589 
00590     PSDrawText( args->unicode_array, args->unicode_array_len, false );
00591     printf( "textWidth=%f, textHeight=%f\n", textWidth, textHeight );
00592 
00593     agg::trans_affine mtx;
00594     mtx.reset();
00595     mtx *= agg::trans_affine_translation( args->x, args->y );
00596     //mtx *= agg::trans_affine_rotation( rotation );
00597     //mtx *= agg::trans_affine_skewing( shear, shear );
00598     mtx *= mTransform;
00599     mtx *= agg::trans_affine_translation( -args->just * textWidth / scalex, -0.5 * textHeight );
00600     mtx *= agg::trans_affine_translation( -args->just * textWidth / scalex, -0.5 * textHeight );
00601     mFontEngine.transform( mtx );
00602 
00603     PSDrawText( args->unicode_array, args->unicode_array_len, true );
00604 
00605     AddtoClipRegion( 0, 0, width, height );
00606 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Defines