From: <sm...@us...> - 2008-10-22 15:01:10
|
Revision: 8954 http://plplot.svn.sourceforge.net/plplot/?rev=8954&view=rev Author: smekal Date: 2008-10-22 15:01:00 +0000 (Wed, 22 Oct 2008) Log Message: ----------- Simplifying the use of the AGG library based on agg2d.cpp/agg2d.h found at http://www.koders.com. Basically the driver works as before, but the AGG library is more "professionally" used and code is easier to read. Also added support of the internal freetype based font routines in the AGG library to process text. Text is printed to the screen, but positioning doesn't work well (or at all). Turn off the buggy font processing by setting the driver option text=0. Modified Paths: -------------- trunk/drivers/wxwidgets.cpp trunk/drivers/wxwidgets.h trunk/drivers/wxwidgets_agg.cpp Modified: trunk/drivers/wxwidgets.cpp =================================================================== --- trunk/drivers/wxwidgets.cpp 2008-10-22 04:25:30 UTC (rev 8953) +++ trunk/drivers/wxwidgets.cpp 2008-10-22 15:01:00 UTC (rev 8954) @@ -325,7 +325,6 @@ #ifdef HAVE_AGG case 1: dev = new wxPLDevAGG; - text = 0; // agg backend is not able to draw text in the moment break; #endif default: Modified: trunk/drivers/wxwidgets.h =================================================================== --- trunk/drivers/wxwidgets.h 2008-10-22 04:25:30 UTC (rev 8953) +++ trunk/drivers/wxwidgets.h 2008-10-22 15:01:00 UTC (rev 8954) @@ -213,14 +213,23 @@ #include "agg2/agg_conv_contour.h" #include "agg2/agg_font_freetype.h" -typedef agg::pixfmt_rgb24 pixfmt; -typedef agg::renderer_base<pixfmt> ren_base; -typedef agg::renderer_scanline_aa_solid<ren_base> renderer; -typedef agg::font_engine_freetype_int32 font_engine_type; -typedef agg::font_cache_manager<font_engine_type> font_manager_type; - class wxPLDevAGG : public wxPLDevBase { + /* type definitions and enums */ + typedef agg::pixfmt_rgb24 pixFormat; + typedef agg::renderer_base<pixFormat> rendererBase; + typedef agg::renderer_scanline_aa_solid<rendererBase> rendererSolid; + typedef agg::font_engine_freetype_int32 fontEngineType; + typedef agg::font_cache_manager<fontEngineType> fontManagerType; + typedef agg::font_cache_manager<fontEngineType>::gray8_adaptor_type fontRasterizer; + typedef agg::font_cache_manager<fontEngineType>::gray8_scanline_type fontScanline; + typedef agg::conv_curve<agg::path_storage> convCurve; + typedef agg::conv_stroke<convCurve> convStroke; + typedef agg::conv_transform<convCurve> pathTransform; + typedef agg::conv_transform<convStroke> strokeTransform; + + enum drawPathFlag { Fill, Stroke, FillAndStroke }; + public: /* methods */ wxPLDevAGG( void ); ~wxPLDevAGG( void ); @@ -243,24 +252,41 @@ void ProcessString( PLStream* pls, EscText* args ); void PSDrawTextToDC( char* utf8_string, bool drawText ); void PSSetFont( PLUNICODE fci ); + void drawPath( drawPathFlag flag ); private: /* variables */ - wxDC* m_dc; - wxImage* m_buffer; - agg::rendering_buffer *m_rendering_buffer; -// font_engine_type m_font_engine; -// font_manager_type m_font_manager; -// agg::conv_curve<font_manager_type::path_adaptor_type> m_curves; -// agg::conv_contour<agg::conv_curve<font_manager_type::path_adaptor_type> > m_contour; + wxDC* mDC; + wxImage* mBuffer; + agg::rendering_buffer mRenderingBuffer; + fontEngineType mFontEngine; + fontManagerType mFontManager; + agg::conv_curve<fontManagerType::path_adaptor_type> mCurves; + agg::conv_contour<agg::conv_curve<fontManagerType::path_adaptor_type> > mContour; - double m_strokewidth; - wxUint8 m_StrokeOpacity; - unsigned char m_colredstroke; - unsigned char m_colgreenstroke; - unsigned char m_colbluestroke; - unsigned char m_colredfill; - unsigned char m_colgreenfill; - unsigned char m_colbluefill; + pixFormat mPixFormat; + rendererBase mRendererBase; + rendererSolid mRendererSolid; + + agg::scanline_u8 mScanLine; + agg::rasterizer_scanline_aa<> mRasterizer; + agg::path_storage mPath; + agg::trans_affine mTransform; + + convCurve mConvCurve; + convStroke mConvStroke; + pathTransform mPathTransform; + strokeTransform mStrokeTransform; + + double mStrokeWidth; + wxUint8 mStrokeOpacity; + unsigned char mColorRedStroke; + unsigned char mColorGreenStroke; + unsigned char mColorBlueStroke; + unsigned char mColorRedFill; + unsigned char mColorGreenFill; + unsigned char mColorBlueFill; + + double textWidth, textHeight; }; #endif Modified: trunk/drivers/wxwidgets_agg.cpp =================================================================== --- trunk/drivers/wxwidgets_agg.cpp 2008-10-22 04:25:30 UTC (rev 8953) +++ trunk/drivers/wxwidgets_agg.cpp 2008-10-22 15:01:00 UTC (rev 8954) @@ -25,187 +25,203 @@ /* plplot headers */ #include "plplotP.h" +#include "plfci-truetype.h" /* wxwidgets headers */ #include "wx/wx.h" +#include <wx/strconv.h> /* std and driver headers */ #include "wxwidgets.h" +#include <wchar.h> + +/* Constructor initializes all variables and objects */ wxPLDevAGG::wxPLDevAGG() : - wxPLDevBase() //, -// m_font_engine(), m_font_manager( m_font_engine ), -// m_curves( m_font_manager.path_adaptor() ), m_contour( m_curves ) + wxPLDevBase(), + mRenderingBuffer(), + mPixFormat( mRenderingBuffer ), + mRendererBase( mPixFormat ), + mRendererSolid( mRendererBase ), + + mPath(), + mTransform(), + mConvCurve( mPath ), + mConvStroke( mConvCurve ), + mPathTransform( mConvCurve, mTransform ), + mStrokeTransform( mConvStroke, mTransform ), + + mFontEngine(), + mFontManager( mFontEngine ), + mCurves( mFontManager.path_adaptor() ), + mContour( mCurves ), + + mBuffer( NULL ), + mStrokeWidth( 1.0 ), + mStrokeOpacity( 255 ), + mColorRedStroke( 255 ), + mColorGreenStroke( 255 ), + mColorBlueStroke( 255 ), + mColorRedFill( 0 ), + mColorGreenFill( 0 ), + mColorBlueFill( 0 ) { - m_buffer=NULL; - m_rendering_buffer=NULL; - m_strokewidth=1.0; - m_StrokeOpacity=255; - m_colredstroke=255; - m_colgreenstroke=255; - m_colbluestroke=255; - m_colredfill=0; - m_colgreenfill=0; - m_colbluefill=0; + mCurves.approximation_scale( 2.0 ); + mContour.auto_detect_orientation( false ); + mConvStroke.line_join( agg::round_join ); + mConvStroke.line_cap( agg::round_cap ); } + +/* Deconstructor frees allocated buffer */ wxPLDevAGG::~wxPLDevAGG() { - if( ownGUI ) { - if( m_buffer ) - delete m_buffer; - if( m_rendering_buffer ) - delete m_rendering_buffer; + if( ownGUI ) + if( mBuffer ) + delete mBuffer; +} + + +void wxPLDevAGG::drawPath( drawPathFlag flag ) +{ + mRasterizer.reset(); + + switch( flag ) { + case Stroke: + if( mStrokeOpacity && mStrokeWidth>0.0 ) { + mConvStroke.width( mStrokeWidth ); + mRasterizer.add_path( mStrokeTransform ); + mRendererSolid.color( agg::rgba8(mColorRedStroke, mColorGreenStroke, mColorBlueStroke, mStrokeOpacity) ); + agg::render_scanlines( mRasterizer, mScanLine, mRendererSolid ); + } + break; + case FillAndStroke: + if( mStrokeOpacity ) { + mRasterizer.add_path( mPathTransform ); + mRendererSolid.color( agg::rgba8(mColorRedStroke, mColorGreenStroke, mColorBlueStroke, mStrokeOpacity) ); + agg::render_scanlines( mRasterizer, mScanLine, mRendererSolid ); + } + + if( mStrokeOpacity && mStrokeWidth>0.0 ) { + mConvStroke.width( mStrokeWidth ); + mRasterizer.add_path( mStrokeTransform ); + mRendererSolid.color( agg::rgba8(mColorRedStroke, mColorGreenStroke, mColorBlueStroke, mStrokeOpacity) ); + agg::render_scanlines( mRasterizer, mScanLine, mRendererSolid ); + } + break; } } + void wxPLDevAGG::DrawLine( short x1a, short y1a, short x2a, short y2a ) { x1a=(short)(x1a/scalex); y1a=(short)(height-y1a/scaley); x2a=(short)(x2a/scalex); y2a=(short)(height-y2a/scaley); - agg::rasterizer_scanline_aa<> ras; - agg::scanline_u8 sl; - pixfmt pixf( *m_rendering_buffer ); - ren_base renb( pixf ); - renderer ren( renb ); + mPath.remove_all(); + mPath.move_to( x1a, y1a ); + mPath.line_to( x2a, y2a ); - agg::path_storage path; - path.move_to( x1a, y1a ); - path.line_to( x2a, y2a ); - - agg::conv_stroke<agg::path_storage> stroke(path); - stroke.line_join( agg::round_join ); - stroke.line_cap( agg::round_cap ); - stroke.width( m_strokewidth ); - ras.add_path( stroke ); - - ren.color( agg::rgba8(m_colredstroke, m_colgreenstroke, m_colbluestroke, m_StrokeOpacity) ); - - agg::render_scanlines( ras, sl, ren ); + drawPath( Stroke ); } + void wxPLDevAGG::DrawPolyline( short *xa, short *ya, PLINT npts ) { short x1a, y1a, x2a, y2a; - agg::rasterizer_scanline_aa<> ras; - agg::scanline_u8 sl; - pixfmt pixf( *m_rendering_buffer ); - ren_base renb( pixf ); - renderer ren( renb ); - - agg::path_storage path; x2a=(short)(xa[0]/scalex); y2a=(short)(height-ya[0]/scaley); - path.move_to( x2a, y2a ); + mPath.remove_all(); + mPath.move_to( x2a, y2a ); for ( PLINT i=1; i<npts; i++ ) { x1a=x2a; y1a=y2a; x2a=(short)(xa[i]/scalex); y2a=(short)(height-ya[i]/scaley); - path.line_to( x2a, y2a ); + mPath.line_to( x2a, y2a ); if( !resizing && ownGUI ) AddtoClipRegion( (int)x1a, (int)y1a, (int)x2a, (int)y2a ); } - agg::conv_stroke<agg::path_storage> stroke( path ); - stroke.line_join( agg::round_join ); - stroke.line_cap( agg::round_cap ); - stroke.width( m_strokewidth ); - ras.add_path( stroke ); - - ren.color( agg::rgba8(m_colredstroke, m_colgreenstroke, m_colbluestroke, m_StrokeOpacity) ); - - agg::render_scanlines( ras, sl, ren ); + drawPath( Stroke ); } + void wxPLDevAGG::ClearBackground( PLINT bgr, PLINT bgg, PLINT bgb, PLINT x1, PLINT y1, PLINT x2, PLINT y2 ) { - pixfmt pixf( *m_rendering_buffer ); - ren_base renb( pixf ); - renb.clear( agg::rgba8(bgr, bgg, bgb) ); + mRendererBase.clear( agg::rgba8(bgr, bgg, bgb) ); } + void wxPLDevAGG::FillPolygon( PLStream *pls ) { short x1a, y1a, x2a, y2a; - agg::rasterizer_scanline_aa<> ras; - agg::scanline_u8 sl; - pixfmt pixf( *m_rendering_buffer ); - ren_base renb( pixf ); - renderer ren( renb ); - agg::path_storage path; + mPath.remove_all(); x2a=(short)(pls->dev_x[0]/scalex); y2a=(short)(height-pls->dev_y[0]/scaley); - path.move_to( x2a, y2a ); + mPath.move_to( x2a, y2a ); for ( PLINT i=1; i<pls->dev_npts; i++ ) { x1a=x2a; y1a=y2a; x2a=(short)(pls->dev_x[i]/scalex); y2a=(short)(height-pls->dev_y[i]/scaley); - path.line_to( x2a, y2a ); + mPath.line_to( x2a, y2a ); if( !resizing && ownGUI ) AddtoClipRegion( (int)x1a, (int)y1a, (int)x2a, (int)y2a ); } - path.line_to( pls->dev_x[0]/scalex, height-pls->dev_y[0]/scaley ); - path.close_polygon(); + mPath.line_to( pls->dev_x[0]/scalex, height-pls->dev_y[0]/scaley ); + mPath.close_polygon(); - ren.color( agg::rgba8(m_colredstroke, m_colgreenstroke, m_colbluestroke, m_StrokeOpacity) ); - ras.add_path( path ); - agg::render_scanlines( ras, sl, ren ); - - agg::conv_stroke<agg::path_storage> stroke( path ); - stroke.line_join( agg::round_join ); - stroke.line_cap( agg::round_cap ); - stroke.width( m_strokewidth ); - ras.add_path( stroke ); - ren.color( agg::rgba8(m_colredstroke, m_colgreenstroke, m_colbluestroke, m_StrokeOpacity) ); - agg::render_scanlines( ras, sl, ren ); + drawPath( FillAndStroke ); } + void wxPLDevAGG::BlitRectangle( wxPaintDC* dc, int vX, int vY, int vW, int vH ) { - if( m_buffer ) { + if( mBuffer ) { wxMemoryDC MemoryDC; - wxBitmap bitmap( m_buffer->GetSubImage(wxRect(vX, vY, vW, vH)), -1 ); + wxBitmap bitmap( mBuffer->GetSubImage(wxRect(vX, vY, vW, vH)), -1 ); MemoryDC.SelectObject( bitmap ); dc->Blit( vX, vY, vW, vH, &MemoryDC, 0, 0 ); MemoryDC.SelectObject( wxNullBitmap ); } } + void wxPLDevAGG::CreateCanvas() { - if( m_rendering_buffer ) - delete m_rendering_buffer; - m_rendering_buffer = new agg::rendering_buffer; - if( ownGUI ) { /* get a new wxImage (image buffer) */ - if( m_buffer ) - delete m_buffer; - m_buffer = new wxImage( bm_width, bm_height ); - m_rendering_buffer->attach( m_buffer->GetData(), bm_width, bm_height, bm_width*3 ); + if( mBuffer ) + delete mBuffer; + mBuffer = new wxImage( bm_width, bm_height ); + mRenderingBuffer.attach( mBuffer->GetData(), bm_width, bm_height, bm_width*3 ); } else - m_rendering_buffer->attach( m_buffer->GetData(), width, height, width*3 ); + mRenderingBuffer.attach( mBuffer->GetData(), width, height, width*3 ); + + mRendererBase.reset_clipping( true ); + } + void wxPLDevAGG::SetWidth( PLStream *pls ) { - m_strokewidth = pls->width>0 ? pls->width : 1; // TODO: why and when ist width 0??? + mStrokeWidth = pls->width>0 ? pls->width : 1; // TODO: why and when ist width 0??? } + void wxPLDevAGG::SetColor0( PLStream *pls ) { - m_colredstroke = pls->cmap0[pls->icol0].r; - m_colgreenstroke = pls->cmap0[pls->icol0].g; - m_colbluestroke = pls->cmap0[pls->icol0].b; - m_StrokeOpacity = (wxUint8)(pls->cmap0[pls->icol0].a*255); + mColorRedStroke = pls->cmap0[pls->icol0].r; + mColorGreenStroke = pls->cmap0[pls->icol0].g; + mColorBlueStroke = pls->cmap0[pls->icol0].b; + mStrokeOpacity = (wxUint8)(pls->cmap0[pls->icol0].a*255); } + void wxPLDevAGG::SetColor1( PLStream *pls ) { - m_colredstroke = pls->curcolor.r; - m_colgreenstroke = pls->curcolor.g; - m_colbluestroke = pls->curcolor.b; - m_StrokeOpacity = (wxUint8)(pls->curcolor.a*255); + mColorRedStroke = pls->curcolor.r; + mColorGreenStroke = pls->curcolor.g; + mColorBlueStroke = pls->curcolor.b; + mStrokeOpacity = (wxUint8)(pls->curcolor.a*255); } @@ -217,14 +233,13 @@ \*--------------------------------------------------------------------------*/ void wxPLDevAGG::SetExternalBuffer( void* dc ) { - m_dc=(wxDC*)dc; /* Add the dc to the device */ - if( m_buffer ) - delete m_buffer; - m_buffer = new wxImage( width, height ); - if( m_rendering_buffer ) - delete m_rendering_buffer; - m_rendering_buffer = new agg::rendering_buffer; - m_rendering_buffer->attach( m_buffer->GetData(), width, height, width*3 ); + mDC=(wxDC*)dc; /* Add the dc to the device */ + if( mBuffer ) + delete mBuffer; + mBuffer = new wxImage( width, height ); + mRenderingBuffer.attach( mBuffer->GetData(), width, height, width*3 ); + + mRendererBase.reset_clipping( true ); ready = true; ownGUI = false; @@ -235,17 +250,17 @@ void wxPLDevAGG::PutPixel( short x, short y, PLINT color ) { - m_buffer->SetRGB( x, y, GetRValue(color), GetGValue(color), GetBValue(color) ); + mBuffer->SetRGB( x, y, GetRValue(color), GetGValue(color), GetBValue(color) ); } void wxPLDevAGG::PutPixel( short x, short y ) { - m_buffer->SetRGB( x, y, m_colredstroke, m_colgreenstroke, m_colbluestroke ); + mBuffer->SetRGB( x, y, mColorRedStroke, mColorGreenStroke, mColorBlueStroke ); } PLINT wxPLDevAGG::GetPixel( short x, short y ) { - return RGB( m_buffer->GetRed( x, y ), m_buffer->GetGreen( x, y ), m_buffer->GetBlue( x, y ) ); + return RGB( mBuffer->GetRed( x, y ), mBuffer->GetGreen( x, y ), mBuffer->GetBlue( x, y ) ); } #endif // HAVE_FREETYPE @@ -253,17 +268,53 @@ void wxPLDevAGG::PSDrawTextToDC( char* utf8_string, bool drawText ) { + // Log_Verbose( "%s", __FUNCTION__ ); + printf( "utf8_string=%s\n", utf8_string ); + + double start_x = 0.0; + double start_y = 0.0; + + //wchar_t str[512]; + //size_t len=wxConvUTF8.ToWChar( str, 512, utf8_string ); + size_t len = strlen( utf8_string ); + char* str=utf8_string; + printf("len=%d\n", len ); + + const agg::glyph_cache* glyph; + for( size_t i=0; i<len && str[i]; i++ ) { + glyph = mFontManager.glyph( str[i] ); + if( glyph ) { + if( i ) + mFontManager.add_kerning( &start_x, &start_y ); + printf( "start_x=%f, start_y=%f\n", start_x, start_y ); + mFontManager.init_embedded_adaptors( glyph, start_x, start_y ); + + if( drawText ) { + mRendererSolid.color( agg::rgba8(mColorRedStroke, mColorGreenStroke, mColorBlueStroke, mStrokeOpacity) ); + agg::render_scanlines( mFontManager.gray8_adaptor(), mFontManager.gray8_scanline(), mRendererSolid ); + } + + textHeight = textHeight>(glyph->bounds.y2-glyph->bounds.y1+yOffset/scaley) ? + textHeight : (glyph->bounds.y2-glyph->bounds.y1+yOffset/scaley); + start_x += glyph->advance_x/64; + } + } + + textWidth += start_x; memset( utf8_string, '\0', max_string_length ); } void wxPLDevAGG::PSSetFont( PLUNICODE fci ) { - unsigned char fontFamily, fontStyle, fontWeight; + /* convert the fci to Base14/Type1 font information */ + char* fontname = plP_FCI2FontName( fci, TrueTypeLookup, N_TrueTypeLookup ); + printf("fontname=%s\n", fontname ); - plP_fci2hex( fci, &fontFamily, PL_FCI_FAMILY ); - plP_fci2hex( fci, &fontStyle, PL_FCI_STYLE ); - plP_fci2hex( fci, &fontWeight, PL_FCI_WEIGHT ); + mFontEngine.load_font( "c:\\windows\\fonts\\arial.ttf", 0, agg::glyph_ren_agg_gray8 ); + mFontEngine.height( fontSize*fontScale ); + mFontEngine.width( fontSize*fontScale ); + mFontEngine.flip_y( true ); } @@ -271,7 +322,7 @@ { /* Check that we got unicode, warning message and return if not */ if( args->unicode_array_len == 0 ) { - printf( "Non unicode string passed to a cairo driver, ignoring\n" ); + printf( "Non unicode string passed to a wxWidgets driver, ignoring\n" ); return; } @@ -285,19 +336,26 @@ fontSize = pls->chrht * DEVICE_PIXELS_PER_MM * 1.2; /* calculate rotation of text */ - plRotationShear( args->xform, &rotation, &shear, &stride); + plRotationShear( args->xform, &rotation, &shear, &stride ); rotation -= pls->diorot * M_PI / 2.0; cos_rot = cos( rotation ); sin_rot = sin( rotation ); cos_shear = cos(shear); sin_shear = sin(shear); - posX = args->x; - posY = args->y; PSDrawText( args->unicode_array, args->unicode_array_len, false ); - posX = args->x-(args->just*textWidth)*scalex*cos_rot-(0.5*textHeight)*scalex*sin_rot; - posY = args->y-(args->just*textWidth)*scaley*sin_rot+(0.5*textHeight)*scaley*cos_rot; + agg::trans_affine mtx; + mtx *= agg::trans_affine_translation( args->x/scalex, height-args->y/scaley ); + //mtx *= agg::trans_affine_rotation( rotation ); + //mtx *= agg::trans_affine_skewing( cos_shear, sin_shear ); + printf("textWidth=%f, textHeight=%f\n", textWidth, textHeight ); + + mtx *= agg::trans_affine_translation( -args->just*textWidth, -0.5*textHeight ); + mFontEngine.transform(mtx); + + agg::conv_transform<fontManagerType::path_adaptor_type> tr( mFontManager.path_adaptor(), mtx ); + PSDrawText( args->unicode_array, args->unicode_array_len, true ); AddtoClipRegion( 0, 0, width, height ); This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |