PLplot
5.10.0
|
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 }