20 #include <wx/wfstream.h>
25 #if defined(__WXMSW__)
31 #include "wx/msw/dcclient.h"
32 #include "wx/msw/dcmemory.h"
33 #include "wx/msw/dcscreen.h"
37 #include "wx/gtk/dc.h"
38 #elif defined __WXGTK20__
39 #include "wx/gtk/dcclient.h"
40 #elif defined(__WXGTK__)
41 #include "wx/gtk1/dcclient.h"
42 #include "wx/gtk1/dcmemory.h"
43 #include "wx/gtk1/dcscreen.h"
47 #include "wx/osx/dcclient.h"
48 #include "wx/osx/dcmemory.h"
49 #include "wx/osx/dcscreen.h"
53 #include "wx/os2/dcclient.h"
54 #include "wx/os2/dcmemory.h"
55 #include "wx/os2/dcscreen.h"
59 #include "wx/cocoa/dcclient.h"
60 #include "wx/cocoa/dcmemory.h"
61 #include "wx/cocoa/dcscreen.h"
65 #include "wx/motif/dcclient.h"
66 #include "wx/motif/dcmemory.h"
67 #include "wx/motif/dcscreen.h"
71 #include "wx/x11/dcclient.h"
72 #include "wx/x11/dcmemory.h"
73 #include "wx/x11/dcscreen.h"
77 #include "wx/dfb/dcclient.h"
78 #include "wx/dfb/dcmemory.h"
79 #include "wx/dfb/dcscreen.h"
82 #if defined(__WXMSW__)
83 #include <wx/msw/private.h>
84 #elif defined(__WXGTK__)
100 #if wxART2D_USE_AGGDRAWER
105 #if wxART2D_USE_FREETYPE
106 #include <ft2build.h>
110 #include <freetype/freetype.h>
111 #include <freetype/ftoutln.h>
114 #include FT_FREETYPE_H
115 #include FT_OUTLINE_H
129 m_externalDc =
false;
130 m_renderDC = m_deviceDC = 0;
162 wxASSERT_MSG(
m_beginDraw_endDraw >= 0, wxT(
"a2dDcDrawer, unbalanced BeginDraw EndDraw" ) );
168 wxASSERT_MSG(
m_renderDC != NULL, wxT(
"a2dMemDcDrawer, wxClientDc not set yet" ) );
172 wxASSERT_MSG(
m_renderDC == NULL, wxT(
"a2dMemDcDrawer, unbalanced BeginDraw EndDraw" ) );
196 wxASSERT_MSG(
m_beginDraw_endDraw >= 0, wxT(
"a2dDcDrawer, unbalanced BeginDraw EndDraw" ) );
200 wxASSERT_MSG(
m_renderDC != NULL, wxT(
"a2dDcDrawer, unbalanced BeginDraw EndDraw" ) );
203 wxASSERT_MSG(
true ==
m_externalDc, wxT(
"a2dDcDrawer, wxClientDc not set yet" ) );
226 wxFAIL_MSG( wxT(
"a2dDcDrawer has no buffer" ) );
228 wxASSERT_MSG(
m_renderDC, wxT(
"no renderDc set" ) );
231 wxBitmap ret( rect.width, rect.height, 32 );
233 wxBitmap ret( rect.width, rect.height,
m_renderDC->GetDepth() );
235 wxASSERT_MSG( ret.Ok(), wxT(
"GetSubImage error" ) );
241 dcb.SelectObject( ret );
242 dcb.Blit( 0, 0, rect.width, rect.height,
m_renderDC, rect.x, rect.y, wxCOPY,
false );
243 dcb.SelectObject( wxNullBitmap );
264 wxASSERT_MSG(
m_renderDC, wxT(
"no renderDc set" ) );
265 unsigned int n = points->size();
285 m_clip = wxRegion( n, intpoints, fillStyle );
287 wxCoord originX, originY;
288 m_renderDC->GetDeviceOrigin( &originX, &originY );
289 m_clip.Offset( originX, originY );
291 #if wxCHECK_VERSION(2,9,0)
292 m_renderDC->SetDeviceClippingRegion( m_clip );
304 wxASSERT_MSG(
m_renderDC, wxT(
"no renderDc set" ) );
306 wxRegion* push =
new wxRegion( m_clip );
315 wxASSERT_MSG(
m_renderDC, wxT(
"no renderDc set" ) );
321 bool smallPoly =
false;
322 unsigned int segments =
ToDeviceLines( points, devbox, smallPoly );
331 wxRegion add = wxRegion( segments, int_cpts, wxWINDING_RULE );
332 wxCoord originX, originY;
333 m_renderDC->GetDeviceOrigin( &originX, &originY );
334 add.Offset( originX, originY );
341 totaladd.Union( add );
343 if ( !m_clip.Empty() )
346 switch ( clipoperation )
349 result = m_clip.Intersect( totaladd );
353 result = m_clip.Union( totaladd );
357 result = m_clip.Xor( totaladd );
361 result = m_clip.Subtract( totaladd );
373 #if wxCHECK_VERSION(2,9,0)
374 m_renderDC->SetDeviceClippingRegion( m_clip );
384 #if wxCHECK_VERSION(2,9,0)
385 m_renderDC->SetDeviceClippingRegion( m_clip );
398 wxASSERT_MSG(
m_renderDC, wxT(
"no renderDc set" ) );
407 #if wxCHECK_VERSION(2,9,0)
408 m_renderDC->SetDeviceClippingRegion( m_clip );
413 wxCoord originX, originY;
414 m_renderDC->GetDeviceOrigin( &originX, &originY );
422 wxASSERT_MSG(
m_renderDC, wxT(
"no renderDc set" ) );
423 m_clip = wxRegion( minx, miny, width, height );
424 wxCoord originX, originY;
425 m_renderDC->GetDeviceOrigin( &originX, &originY );
426 m_clip.Offset( originX, originY );
428 #if wxCHECK_VERSION(2,9,0)
429 m_renderDC->SetDeviceClippingRegion( m_clip );
440 wxASSERT_MSG(
m_renderDC, wxT(
"no renderDc set" ) );
447 m_clip = wxRegion( iminx, imaxy, imaxx - iminx, iminy - imaxy );
448 m_clipboxdev = wxRect( iminx, imaxy, imaxx - iminx, iminy - imaxy );
452 m_clip = wxRegion( iminx, iminy, imaxx - iminx, imaxy - iminy );
453 m_clipboxdev = wxRect( iminx, iminy, imaxx - iminx, imaxy - iminy );
459 wxCoord originX, originY;
460 m_renderDC->GetDeviceOrigin( &originX, &originY );
461 m_clip.Offset( originX, originY );
462 #if wxCHECK_VERSION(2,9,0)
463 m_renderDC->SetDeviceClippingRegion( m_clip );
538 default: style = wxSOLID;
555 dcpen.SetWidth( widthDev );
578 #if defined(__WXMSW__)
583 style = wxBRUSHSTYLE_STIPPLE;
584 dcpen.SetStyle( style );
592 noMask.SetMask( NULL );
593 style = wxBRUSHSTYLE_STIPPLE;
594 dcpen.SetStyle( style );
595 dcpen.SetStipple( noMask );
599 style = wxBRUSHSTYLE_STIPPLE_MASK_OPAQUE;
600 dcpen.SetStyle( style );
604 default: style = wxBRUSHSTYLE_SOLID;
605 dcpen.SetStyle( style );
644 style = wxBRUSHSTYLE_TRANSPARENT;
646 dcbrush.SetStyle( style );
650 dcbrush.SetStyle( style );
653 style = wxBRUSHSTYLE_BDIAGONAL_HATCH;
655 dcbrush.SetStyle( style );
658 style = wxBRUSHSTYLE_CROSSDIAG_HATCH;
660 dcbrush.SetStyle( style );
663 style = wxBRUSHSTYLE_FDIAGONAL_HATCH;
665 dcbrush.SetStyle( style );
668 style = wxBRUSHSTYLE_CROSS_HATCH;
670 dcbrush.SetStyle( style );
673 style = wxBRUSHSTYLE_HORIZONTAL_HATCH;
675 dcbrush.SetStyle( style );
678 style = wxBRUSHSTYLE_VERTICAL_HATCH;
680 dcbrush.SetStyle( style );
682 default: style = wxBRUSHSTYLE_SOLID;
684 dcbrush.SetStyle( style );
697 style = wxBRUSHSTYLE_TRANSPARENT;
699 dcbrush.SetStyle( style );
702 style = wxBRUSHSTYLE_BDIAGONAL_HATCH;
704 dcbrush.SetStyle( style );
707 style = wxBRUSHSTYLE_CROSSDIAG_HATCH;
709 dcbrush.SetStyle( style );
712 style = wxBRUSHSTYLE_FDIAGONAL_HATCH;
714 dcbrush.SetStyle( style );
717 style = wxBRUSHSTYLE_CROSS_HATCH;
719 dcbrush.SetStyle( style );
722 style = wxBRUSHSTYLE_HORIZONTAL_HATCH;
724 dcbrush.SetStyle( style );
727 style = wxBRUSHSTYLE_VERTICAL_HATCH;
729 dcbrush.SetStyle( style );
732 style = wxBRUSHSTYLE_SOLID;
734 dcbrush.SetStyle( style );
747 style = wxBRUSHSTYLE_STIPPLE;
750 dcbrush.SetStyle( style );
757 noMask.SetMask( NULL );
758 style = wxBRUSHSTYLE_STIPPLE;
760 dcbrush.SetStipple( noMask );
764 style = wxBRUSHSTYLE_STIPPLE_MASK_OPAQUE;
768 dcbrush.SetStyle( style );
770 default: style = wxBRUSHSTYLE_SOLID;
772 dcbrush.SetStyle( style );
781 void a2dDcDrawer::DoSetDrawStyle(
a2dDrawStyle drawstyle )
790 SetLogicalFunction( wxINVERT );
796 SetLogicalFunction( wxCOPY );
802 SetLogicalFunction( wxCOPY );
808 SetLogicalFunction( wxINVERT );
814 SetLogicalFunction( wxCOPY );
826 SetLogicalFunction( wxCOPY );
831 SetLogicalFunction( wxINVERT );
845 wxASSERT_MSG(
m_renderDC, wxT(
"no renderDc set" ) );
847 wxPoint centr( (
int ) width / 2, (
int ) height / 2 );
852 wxImage image = imagein;
854 if ( fabs( angle ) > 0.5 )
856 image.SetMask(
true );
858 image = imagein.Rotate( angle / 180.0 *
wxPI, centr,
true, NULL );
860 image = imagein.Rotate( -angle / 180.0 *
wxPI, centr,
true, NULL );
863 int devicew, deviceh;
869 int devicex = ( int ) ( hx - devicew / 2.0 );
870 int devicey = ( int ) ( hy - deviceh / 2.0 );
873 bool imgHasMask = image.HasMask();
875 if ( devicew == 0 || deviceh == 0 )
878 double sx = image.GetWidth() / ( double ) devicew;
879 double sy = image.GetHeight() / ( double ) deviceh;
883 clipped.Intersect( wxRect( devicex, devicey, devicew, deviceh ) );
884 int deviceClipX = clipped.GetX();
885 int deviceClipY = clipped.GetY();
886 int deviceClipW = clipped.GetWidth();
887 int deviceClipH = clipped.GetHeight();
889 clipped.SetX( (
int ) ( ( clipped.GetX() - devicex ) * sx ) );
890 clipped.SetY( (
int ) ( ( clipped.GetY() - devicey ) * sy ) );
891 clipped.SetWidth( (
int ) ( clipped.GetWidth() * sx ) );
892 clipped.SetHeight( (
int ) ( clipped.GetHeight() * sy ) );
895 if ( clipped.GetWidth() < 1 || clipped.GetHeight() < 1 )
897 m_renderDC->DrawRectangle( devicex, devicey, devicew, deviceh );
901 if ( deviceClipW != devicew || deviceClipH != deviceh )
902 image = image.GetSubImage( clipped );
906 image.Rescale( deviceClipW, deviceClipH );
909 wxBitmap Bitmap( image );
914 MemoryDc.SelectObject( Bitmap );
916 m_renderDC->Blit( deviceClipX, deviceClipY, deviceClipW, deviceClipH, &MemoryDc, 0, 0, wxCOPY, imgHasMask );
920 m_renderDC->DrawRectangle( devicex, devicey, devicew, deviceh );
942 void a2dDcDrawer::SetLogicalFunction( wxRasterOperationMode
function )
1133 wxASSERT_MSG(
m_renderDC, wxT(
"no renderDc set" ) );
1135 wxPoint centr( (
int ) width / 2, (
int ) height / 2 );
1138 int devicew, deviceh;
1144 int devicex = ( int ) ( hx - devicew / 2.0 );
1145 int devicey = ( int ) ( hy - deviceh / 2.0 );
1151 m_clip.GetBox( clipx, clipy, clipwidth, clipheight );
1155 if ( devicew == 0 || deviceh == 0 )
1184 unsigned int segments = 0;
1188 for ( i = 0; i < path->size(); i++ )
1191 switch ( seg->GetType() )
1208 double radius, center_x, center_y, beginrad, midrad, endrad, phit;
1210 if ( cseg->
CalcR( path->operator[]( i ? i - 1 : 0 ), radius, center_x, center_y, beginrad, midrad, endrad, phit ) )
1213 unsigned int circlesegments;
1216 segments += circlesegments + 1;
1234 bool nostrokeparts =
false;
1237 for ( i = 0; i < path->size(); i++ )
1240 switch ( seg->GetType() )
1268 nostrokeparts =
true;
1272 nostrokeparts =
true;
1277 double xwl = path->operator[]( i ? i - 1 : 0 )->m_x1;
1278 double ywl = path->operator[]( i ? i - 1 : 0 )->m_y1;
1285 xw = xwl * pow( 1 - t, 3 ) + cseg->
m_x2 * pow( 1 - t, 2 ) * t * 3 + cseg->
m_x3 * ( 1 - t ) * t * t * 3 + cseg->
m_x1 * pow( t, 3 );
1286 yw = ywl * pow( 1 - t, 3 ) + cseg->
m_y2 * pow( 1 - t, 2 ) * t * 3 + cseg->
m_y3 * ( 1 - t ) * t * t * 3 + cseg->
m_y1 * pow( t, 3 );
1297 nostrokeparts =
true;
1302 double xwl = path->operator[]( i ? i - 1 : 0 )->m_x1;
1303 double ywl = path->operator[]( i ? i - 1 : 0 )->m_y1;
1310 xw = xwl * pow( 1 - t, 2 ) + cseg->
m_x2 * ( 1 - t ) * t * 2 + cseg->
m_x1 * pow( t, 2 );
1311 yw = ywl * pow( 1 - t, 2 ) + cseg->
m_y2 * ( 1 - t ) * t * 2 + cseg->
m_y1 * pow( t, 2 );
1322 nostrokeparts =
true;
1327 double radius, center_x, center_y, beginrad, midrad, endrad, phit;
1329 if ( cseg->
CalcR( path->operator[]( i ? i - 1 : 0 ), radius, center_x, center_y, beginrad, midrad, endrad, phit ) )
1332 unsigned int segments;
1336 double theta = beginrad;
1340 for ( step = 0; step < segments + 1; step++ )
1346 theta = theta + dphi;
1377 nostrokeparts =
true;
1387 else if ( i == path->size() - 1 )
1393 if ( nostrokeparts )
1397 nostrokeparts =
false;
1399 double lastmovex = 0;
1400 double lastmovey = 0;
1402 for ( i = 0; i < path->size(); i++ )
1405 switch ( seg->GetType() )
1445 nostrokeparts =
true;
1453 double xwl = path->operator[]( i ? i - 1 : 0 )->m_x1;
1454 double ywl = path->operator[]( i ? i - 1 : 0 )->m_y1;
1461 xw = xwl * pow( 1 - t, 3 ) + cseg->
m_x2 * pow( 1 - t, 2 ) * t * 3 + cseg->
m_x3 * ( 1 - t ) * t * t * 3 + cseg->
m_x1 * pow( t, 3 );
1462 yw = ywl * pow( 1 - t, 3 ) + cseg->
m_y2 * pow( 1 - t, 2 ) * t * 3 + cseg->
m_y3 * ( 1 - t ) * t * t * 3 + cseg->
m_y1 * pow( t, 3 );
1476 double xwl = path->operator[]( i ? i - 1 : 0 )->m_x1;
1477 double ywl = path->operator[]( i ? i - 1 : 0 )->m_y1;
1484 xw = xwl * pow( 1 - t, 2 ) + cseg->
m_x2 * ( 1 - t ) * t * 2 + cseg->
m_x1 * pow( t, 2 );
1485 yw = ywl * pow( 1 - t, 2 ) + cseg->
m_y2 * ( 1 - t ) * t * 2 + cseg->
m_y1 * pow( t, 2 );
1499 double radius, center_x, center_y, beginrad, midrad, endrad, phit;
1501 if ( cseg->
CalcR( path->operator[]( i ? i - 1 : 0 ), radius, center_x, center_y, beginrad, midrad, endrad, phit ) )
1504 unsigned int segments;
1508 double theta = beginrad;
1512 for ( step = 0; step < segments + 1; step++ )
1518 theta = theta + dphi;
1536 if ( move || nostrokeparts )
1540 nostrokeparts =
false;
1552 nostrokeparts =
false;
1556 else if ( i == path->size() )
1571 bool smallPoly =
false;
1574 std::vector<int> pcount;
1575 pcount.resize( polylist.size() );
1578 for( a2dListOfa2dVertexList::iterator iterp = polylist.begin(); iterp != polylist.end(); iterp++ )
1580 int segments =
ToDeviceLines( ( *iterp ).Get(), devbox, smallPoly );
1581 pcount[ j++ ] = segments;
1584 for (
int i = 0; i < segments; i++ )
1589 totalsize += segments;
1611 wxASSERT_MSG(
m_renderDC, wxT(
"no renderDc set" ) );
1644 if ( m00 == m11 && m10 == m01 )
1649 #if defined(__WXMSW__)
1655 else if ( ( 100.0 * m10 < m00 ) && ( 100.0 * m01 < m11 ) )
1661 double x, y, rx, ry;
1667 else if ( ( 100.0 * m00 < m10 ) && ( 100.0 * m11 < m01 ) )
1670 double x, y, rx, ry;
1679 DrawEllipse( xc, yc, 2.0 * radius, 2.0 * radius );
1702 wxASSERT_MSG(
m_renderDC, wxT(
"no renderDc set" ) );
1722 wxASSERT_MSG(
m_renderDC, wxT(
"no renderDc set" ) );
1752 wxASSERT_MSG(
m_renderDC, wxT(
"no renderDc set" ) );
1776 wxASSERT_MSG(
m_renderDC, wxT(
"no renderDc set" ) );
1792 m_renderDC->DrawLine( int_cpts[0].x, int_cpts[0].y, int_cpts[n - 1].x, int_cpts[n - 1].y );
1798 #if defined(__WXMSW__)
1799 #if wxCHECK_VERSION(2,9,0)
1801 WXHDC hdc = dcimpl->GetHDC();
1805 SetPolyFillMode( (
struct HDC__* ) hdc, fillStyle == wxODDEVEN_RULE ? ALTERNATE : WINDING );
1808 ( void )Polygon( (
struct HDC__* ) hdc, ( POINT* )int_cpts, n );
1811 m_renderDC->DrawPolygon( n, int_cpts, 0, 0, fillStyle );
1823 m_renderDC->DrawLine( int_cpts[0].x, int_cpts[0].y, int_cpts[n - 1].x, int_cpts[n - 1].y );
1828 #if defined(__WXMSW__)
1831 m_renderDC->SetLogicalFunction( wxAND_INVERT );
1834 COLORREF colFgOld, colBgOld;
1836 #if wxCHECK_VERSION(2,9,0)
1838 WXHDC hdc = dcimpl->GetHDC();
1843 colBgOld = ::GetBkColor( (
struct HDC__* ) hdc );
1844 colFgOld = ::GetTextColor( (
struct HDC__* ) hdc );
1848 ::SetBkColor( (
struct HDC__* ) hdc,
m_renderDC->GetTextForeground().GetPixel() );
1851 ::SetTextColor( (
struct HDC__* ) hdc,
m_renderDC->GetTextBackground().GetPixel() );
1853 int prev = SetPolyFillMode( (
struct HDC__* ) hdc, WINDING );
1854 ( void )Polygon( (
struct HDC__* ) hdc, ( POINT* )int_cpts, n );
1866 ::SetBkColor( (
struct HDC__* ) hdc,
m_renderDC->GetTextForeground().GetPixel() );
1869 ::SetTextColor( (
struct HDC__* ) hdc,
m_renderDC->GetTextBackground().GetPixel() );
1870 ( void )Polygon( (
struct HDC__* ) hdc, ( POINT* )int_cpts, n );
1871 SetPolyFillMode( (
struct HDC__* ) hdc, prev );
1874 ::SetBkMode( (
struct HDC__* ) hdc, TRANSPARENT );
1875 ::SetTextColor( (
struct HDC__* ) hdc, colFgOld );
1876 ::SetBkColor( (
struct HDC__* ) hdc, colBgOld );
1886 m_renderDC->DrawLine( int_cpts[0].x, int_cpts[0].y, int_cpts[n - 1].x, int_cpts[n - 1].y );
1901 m_renderDC->SetLogicalFunction( wxAND_INVERT );
1903 m_renderDC->DrawPolygon( n, int_cpts, 0, 0, fillStyle );
1913 m_renderDC->DrawPolygon( n, int_cpts, 0, 0, fillStyle );
1925 m_renderDC->DrawPolygon( n, int_cpts, 0, 0, fillStyle );
1931 m_renderDC->DrawLine( int_cpts[0].x, int_cpts[0].y, int_cpts[n - 1].x, int_cpts[n - 1].y );
1942 m_renderDC->DrawPolygon( n, int_cpts, 0, 0, fillStyle );
1949 wxBrush cur_dcbrush =
m_renderDC->GetBrush();
1951 m_renderDC->DrawPolygon( n, int_cpts, 0, 0, fillStyle );
1953 m_renderDC->DrawPolygon( n, int_cpts, 0, 0, fillStyle );
1957 #if defined(__WXMSW__)
1963 m_renderDC->DrawPolygon( n, int_cpts, 0, 0, fillStyle );
1966 m_renderDC->DrawPolygon( n, int_cpts, 0, 0, fillStyle );
1975 wxRealPoint* copy =
new wxRealPoint[n + 1];
1990 wxASSERT_MSG(
m_renderDC, wxT(
"no renderDc set" ) );
1997 m_renderDC->DrawCircle( int_cpts[0].x, int_cpts[0].y, 2 );
2002 #if defined(__WXMSW__)
2005 if ( n > 1 &&
m_renderDC->GetPen().GetWidth() == 1 )
2006 m_renderDC->DrawPoint( int_cpts[n - 1].x, int_cpts[n - 1].y );
2016 wxASSERT_MSG(
m_renderDC, wxT(
"no renderDc set" ) );
2026 wxASSERT_MSG(
m_renderDC, wxT(
"no renderDc set" ) );
2029 if ( use_stroke_color )
2048 wxASSERT_MSG(
m_renderDC, wxT(
"no renderDc set" ) );
2051 if ( use_stroke_color )
2067 #if defined(__WXMSW__)
2068 #if wxCHECK_VERSION(2,9,0)
2070 WXHDC hdc = dcimpl->GetHDC();
2074 ::SetPixelV( (
struct HDC__* )hdc, x1, y1, RGB( r, g, b ) );
2077 #if wxCHECK_VERSION(2,9,1)
2086 wxColour col( r, g, b );
2087 col.CalcPixel( ( ( wxWindowDC* )
m_renderDC )->m_cmap );
2088 gdk_gc_set_foreground( ( ( wxWindowDC* )
m_renderDC )->m_penGC, col.GetColor() );
2089 gdk_draw_point( ( ( wxWindowDC* )
m_renderDC )->m_window, ( ( wxWindowDC* )
m_renderDC )->m_penGC, x1, y1 );
2102 wxASSERT_MSG(
m_renderDC, wxT(
"no renderDc set" ) );
2124 wxASSERT_MSG(
m_renderDC, wxT(
"no renderDc set" ) );
2129 unsigned int fontsize;
2136 m_renderDC->SetBackgroundMode( wxTRANSPARENT );
2157 m_renderDC->DrawRotatedText( text, (
int ) dx, (
int ) dy, -angle );
2161 #if wxART2D_USE_FREETYPE
2162 extern FT_Library g_freetypeLibrary;
2168 int xmin, ymax, ymin;
2177 static void a2dSpanFuncGray(
int y,
int count, FT_Span* spans,
a2dSpanData* user )
2179 unsigned int alpha, invalpha, len;
2181 unsigned int r, g, b, rpm, gpm, bpm;
2182 r = user->colour.Red();
2183 g = user->colour.Green();
2184 b = user->colour.Blue();
2186 unsigned char* buf, *buf2;
2187 buf = user->buf + ( user->ymax - y ) * user->stride - user->xmin * 3;
2190 buf2 = buf + spans->x * 3;
2192 alpha = spans->coverage;
2217 invalpha = 255 - alpha;
2223 buf2[0] = ( buf2[0] * invalpha + rpm ) / 255;
2224 buf2[1] = ( buf2[1] * invalpha + gpm ) / 255;
2225 buf2[2] = ( buf2[2] * invalpha + bpm ) / 255;
2227 buf2[0] = ( buf2[0] * invalpha + bpm ) / 255;
2228 buf2[1] = ( buf2[1] * invalpha + gpm ) / 255;
2229 buf2[2] = ( buf2[2] * invalpha + rpm ) / 255;
2243 static void a2dSpanFuncGrayStrImage(
int y,
int count, FT_Span* spans,
a2dSpanData* user )
2245 unsigned int alpha, invalpha, len;
2247 unsigned int r, g, b, rpm, gpm, bpm;
2248 r = user->colour.Red();
2249 g = user->colour.Green();
2250 b = user->colour.Blue();
2252 unsigned char* buf, *buf2;
2253 buf = user->buf + ( user->height - user->descent - y ) * user->stride + user->xmin * 3;
2257 buf2 = buf + spans->x * 3;
2259 alpha = spans->coverage;
2284 invalpha = 255 - alpha;
2290 buf2[0] = ( buf2[0] * invalpha + rpm ) / 255;
2291 buf2[1] = ( buf2[1] * invalpha + gpm ) / 255;
2292 buf2[2] = ( buf2[2] * invalpha + bpm ) / 255;
2294 buf2[0] = ( buf2[0] * invalpha + bpm ) / 255;
2295 buf2[1] = ( buf2[1] * invalpha + gpm ) / 255;
2296 buf2[2] = ( buf2[2] * invalpha + rpm ) / 255;
2321 #if wxART2D_USE_FREETYPE
2348 wxBrush dcbrush( color );
2349 wxBrush cur_dcbrush =
m_renderDC->GetBrush();
2351 wxPen dcpen = *wxTRANSPARENT_PEN;
2364 #else // wxART2D_USE_FREETYPE
2366 #endif // wxART2D_USE_FREETYPE
2375 wxASSERT_MSG(
m_renderDC, wxT(
"no renderDc set" ) );
2382 m_renderDC->DrawRectangle( x - 1, y - 1, w + 2, h + 2 );
2405 #if defined(__WXMSW__)
2406 m_hdc1 = ::GetDC( NULL );
2407 m_hdc2 = ::CreateCompatibleDC( m_hdc1 );
2413 m_buffer = wxBitmap( width, height );
2414 #if defined(__WXMSW__)
2415 m_hdc1 = ::GetDC( NULL );
2416 m_hdc2 = ::CreateCompatibleDC( m_hdc1 );
2422 #if defined(__WXMSW__)
2423 ::DeleteDC( m_hdc1 );
2424 ::ReleaseDC( NULL, m_hdc2 );
2425 #endif // defined( __WXMSW__ )
2432 #if defined(__WXMSW__)
2433 m_hdc1 = ::GetDC( NULL );
2434 m_hdc2 = ::CreateCompatibleDC( m_hdc1 );
2440 wxASSERT_MSG(
m_beginDraw_endDraw >= 0, wxT(
"a2dMemDcDrawer, unbalanced BeginDraw EndDraw" ) );
2446 wxASSERT_MSG(
m_renderDC != NULL, wxT(
"a2dMemDcDrawer, wxClientDc not set yet" ) );
2450 wxASSERT_MSG(
m_renderDC == NULL, wxT(
"a2dMemDcDrawer, unbalanced BeginDraw EndDraw" ) );
2479 wxASSERT_MSG(
m_renderDC != NULL, wxT(
"a2dMemDcDrawer, unbalanced BeginDraw EndDraw" ) );
2480 wxASSERT_MSG(
m_beginDraw_endDraw >= 0, wxT(
"a2dMemDcDrawer, unbalanced BeginDraw EndDraw" ) );
2484 wxASSERT_MSG(
m_renderDC != NULL, wxT(
"a2dDcDrawer, unbalanced BeginDraw EndDraw" ) );
2487 wxASSERT_MSG(
m_renderDC != NULL, wxT(
"a2dDcDrawer, wxClientDc not set yet" ) );
2491 m_memdc->SelectObject( wxNullBitmap );
2504 wxBitmap helpbuf = wxBitmap( w, h );
2509 m_mdc2.SelectObject( helpbuf );
2510 m_mdc2.Blit( 0, 0, w, h, &m_mdc1, 0, 0 );
2511 m_mdc1.SelectObject( wxNullBitmap );
2512 m_mdc2.SelectObject( wxNullBitmap );
2532 wxBitmap ret( rect.width, rect.height,
m_buffer.GetDepth() );
2533 wxASSERT_MSG( ret.Ok(), wxT(
"GetSubImage error" ) );
2538 m_mdc1.SelectObject( ret );
2539 m_mdc1.Blit( 0, 0, rect.width, rect.height,
m_renderDC, rect.x, rect.y, wxCOPY,
false );
2540 m_mdc1.SelectObject( wxNullBitmap );
2544 m_mdc2.SelectObject( const_cast<wxBitmap&>(
m_buffer ) );
2547 m_mdc1.SelectObject( ret );
2548 m_mdc1.Blit( 0, 0, rect.width, rect.height, &m_mdc2, rect.x, rect.y, wxCOPY,
false );
2549 m_mdc1.SelectObject( wxNullBitmap );
2551 m_mdc2.SelectObject( wxNullBitmap );
2557 void a2dMemDcDrawer::CopyIntoBuffer(
const wxBitmap& bitm )
2567 rect.width += rect.x;
2570 if ( rect.width <= 0 )
return;
2574 rect.height += rect.y;
2577 if ( rect.height <= 0 )
return;
2579 if ( rect.x + rect.width >
m_width )
2581 rect.width =
m_width - rect.x;
2583 if ( rect.width <= 0 )
return;
2585 if ( rect.y + rect.height >
m_height )
2589 if ( rect.height <= 0 )
return;
2595 dc->Blit( rect.x - bufferpos.x, rect.y - bufferpos.y, rect.width, rect.height, &m_mdc1, rect.x, rect.y, wxCOPY,
false );
2597 m_mdc1.SelectObject( wxNullBitmap );
2601 dc->Blit( rect.x - bufferpos.x, rect.y - bufferpos.y, rect.width, rect.height,
m_renderDC, rect.x, rect.y, wxCOPY,
false );
2619 if ( dxy > 0 && dxy < bh )
2621 wxRect rect( 0, 0, bw, bh - dxy );
2622 wxBitmap sub_bitmap(
m_buffer.GetSubBitmap( rect ) );
2624 m_mdc1.DrawBitmap( sub_bitmap, 0, dxy,
true );
2625 m_mdc1.SelectObject( wxNullBitmap );
2627 else if ( dxy < 0 && dxy > -bh )
2629 wxRect rect( 0, -dxy, bw, bh + dxy );
2630 wxBitmap sub_bitmap(
m_buffer.GetSubBitmap( rect ) );
2632 m_mdc1.DrawBitmap( sub_bitmap, 0, 0,
true );
2633 m_mdc1.SelectObject( wxNullBitmap );
2636 wxFAIL_MSG( wxT(
"you can only shift within height of buffer" ) );
2641 if ( dxy > 0 && dxy < bw )
2643 wxRect rect( 0, 0, bw - dxy, bh );
2644 wxBitmap sub_bitmap(
m_buffer.GetSubBitmap( rect ) );
2646 m_mdc1.DrawBitmap( sub_bitmap, dxy, 0,
true );
2647 m_mdc1.SelectObject( wxNullBitmap );
2649 else if ( dxy < 0 && dxy > -bw )
2651 wxRect rect( -dxy, 0, bw + dxy, bh );
2652 wxBitmap sub_bitmap(
m_buffer.GetSubBitmap( rect ) );
2654 m_mdc1.DrawBitmap( sub_bitmap, 0, 0,
true );
2655 m_mdc1.SelectObject( wxNullBitmap );
2658 wxFAIL_MSG( wxT(
"you can only shift within width of buffer" ) );
2664 #if wxART2D_USE_AGGDRAWER
2668 if ( width == 0 || height == 0 )
2676 if ( fabs( angle ) > 0.5 || Opacity != 255 )
2681 m_memdc->SelectObject( wxNullBitmap );
2694 aggDrawer.
DrawImage( image, x , y, width, height, Opacity );
2720 #if wxART2D_USE_AGGDRAWER
2724 if ( width == 0 || height == 0 )
2737 m_memdc->SelectObject( wxNullBitmap );
2750 aggDrawer.
DrawImage( image, x , y, width, height );
2774 #define BBOX_GLYPH_EXTEND 1
2778 void DrawCharFreetypeHorizontal( wxColour col,
const a2dGlyph* a2dglyph,
unsigned char* buf,
int bufwidth,
int bufheight, wxChar c,
int dx,
int deviceDescent, FT_BBox bbox )
2784 #if wxART2D_USE_FREETYPE
2786 FT_Glyph image = a2dglyph->m_glyph;
2789 if ( bbox.xMax - bbox.xMin <= 0 || bbox.yMax - bbox.yMin <= 0 )
2795 if ( image->format == FT_GLYPH_FORMAT_OUTLINE )
2798 spandata.colour = col;
2800 spandata.height = bufheight;
2801 spandata.descent = deviceDescent;
2802 spandata.ymin = bbox.yMin;
2803 spandata.ymax = bbox.yMax;
2804 spandata.stride = bufwidth * 3;
2805 #if defined(__WXMSW__)
2807 spandata.stride = ( spandata.stride +
sizeof( DWORD ) - 1 ) /
sizeof( DWORD ) *
sizeof( DWORD );
2808 #endif // defined( __WXMSW__ )
2810 wxASSERT( spandata.buf != NULL );
2812 FT_Raster_Params params;
2813 params.target = NULL;
2814 params.flags = FT_RASTER_FLAG_AA | FT_RASTER_FLAG_DIRECT | FT_RASTER_FLAG_CLIP;
2815 params.gray_spans = ( FT_SpanFunc ) & a2dSpanFuncGrayStrImage;
2816 params.black_spans = NULL;
2817 params.bit_test = ( FT_Raster_BitTest_Func ) NULL;
2818 params.bit_set = ( FT_Raster_BitSet_Func ) NULL;
2819 params.user = &spandata;
2820 params.clip_box = bbox;
2822 FT_Outline& outline = ( ( FT_OutlineGlyph ) image )->outline;
2823 if ( FT_Outline_Render( g_freetypeLibrary, &outline, ¶ms ) == 0 )
2827 else if ( image->format == FT_GLYPH_FORMAT_BITMAP )
2829 wxFAIL_MSG( _(
"Non vector bitmap fonts are not supported" ) );
2832 wxFAIL_MSG( _(
"Non vector fonts are not supported" ) );
2834 #else // wxART2D_USE_FREETYPE
2835 DrawCharUnknown( c );
2836 #endif // wxART2D_USE_FREETYPE
2852 bool textwasvisible =
false;
2859 yBboxMinY =
Round( hdy );
2867 const a2dGlyph* a2dglyphprev = NULL;
2887 const wxStringCharType *cp(text.wx_str());
2889 const wxChar* cp(text.c_str());
2890 #endif // wxUSE_UNICODE
2892 size_t n = text.Length();
2893 for (
size_t i = 0; i < n; i++ )
2903 FT_Face face = a2dglyph->m_face;
2905 FT_Get_Kerning( a2dglyph->m_face, a2dglyphprev->m_index, a2dglyph->m_index, FT_KERNING_DEFAULT, &kern );
2906 dxrel += ( int ) ( kern.x / 64.0 );
2908 if ( a2dglyphprev->m_rsb - a2dglyph->m_lsb >= 32 )
2910 else if ( a2dglyphprev->m_rsb - a2dglyph->m_lsb < -32 )
2913 a2dglyphprev = a2dglyph;
2914 FT_Glyph glyphimage = a2dglyph->m_glyph;
2917 FT_Glyph_Get_CBox( glyphimage, FT_GLYPH_BBOX_PIXELS, &bbox );
2919 int advance = ( int ) ( glyphimage->advance.x / 64.0 );
2923 int devicew = dxrel + cheat;
2925 wxRect stringBbox( dx, yBboxMinY - deviceh, devicew, deviceh + cheat);
2926 if ( stringBbox.GetWidth() == 0 || stringBbox.GetHeight() == 0 )
2933 #if defined(__WXMSW__)
2935 bi.bmiHeader.biSize =
sizeof( bi.bmiHeader );
2936 bi.bmiHeader.biWidth = devicew;
2937 bi.bmiHeader.biHeight = -deviceh;
2938 bi.bmiHeader.biPlanes = 1;
2939 bi.bmiHeader.biBitCount = 24;
2940 bi.bmiHeader.biCompression = BI_RGB;
2941 bi.bmiHeader.biSizeImage = 0;
2942 bi.bmiHeader.biClrUsed = 0;
2943 bi.bmiHeader.biClrImportant = 0;
2945 HBITMAP hbitmap = ( HBITMAP ) sub_bitmap.GetHBITMAP();
2946 buf = (
unsigned char* ) malloc( ( 3 * devicew +
sizeof( DWORD ) - 1 ) /
sizeof( DWORD ) *
sizeof( DWORD ) * (deviceh + 1) );
2947 ::GetDIBits( m_hdc2, hbitmap, 0, deviceh, buf, &bi, DIB_RGB_COLORS );
2948 #else // defined( __WXMSW__ )
2949 wxImage strImage( sub_bitmap.ConvertToImage() );
2950 buf = strImage.GetData();
2952 #endif // defined( __WXMSW__ )
2959 #endif // wxUSE_UNICODE
2960 for (
size_t i = 0; i < n; i++ )
2970 FT_Face face = a2dglyph->m_face;
2972 FT_Get_Kerning( a2dglyph->m_face, a2dglyphprev->m_index, a2dglyph->m_index, FT_KERNING_DEFAULT, &kern );
2973 dxrel += ( int ) ( kern.x / 64.0 );
2975 if ( a2dglyphprev->m_rsb - a2dglyph->m_lsb >= 32 )
2977 else if ( a2dglyphprev->m_rsb - a2dglyph->m_lsb < -32 )
2981 a2dglyphprev = a2dglyph;
2983 FT_Glyph glyphimage = a2dglyph->m_glyph;
2986 FT_Glyph_Get_CBox( glyphimage, FT_GLYPH_BBOX_PIXELS, &bbox );
2987 int px = dx + dxrel + bbox.xMin;
2988 int py = dy - bbox.yMax;
2989 int wbox = bbox.xMax - bbox.xMin;
2990 int hbox = bbox.yMax - bbox.yMin;
2992 int advance = ( int ) ( glyphimage->advance.x / 64.0 );
2996 wxRect bboxglyph( px, py, wbox, hbox );
3003 wxRect bboxd( px, yBboxMinY - deviceh, advance, deviceh );
3010 DrawCharFreetypeHorizontal( stroke, a2dglyph, buf, devicew, deviceh, c, dxrel, deviceDescent, bbox );
3012 textwasvisible =
true;
3014 else if ( textwasvisible )
3026 #if defined( __WXMSW__ )
3027 ::SetDIBits( m_hdc2, hbitmap, 0, deviceh, buf, &bi, DIB_RGB_COLORS );
3029 #else // defined( __WXMSW__ )
3030 wxBitmap sub_bitmap( strImage );
3031 #endif // defined( __WXMSW__ )
3062 bool textwasvisible =
false;
3065 size_t n = text.Length();
3066 for (
size_t i = 0; i < n; i++ )
3068 const wxChar oldc = c;
3077 FT_Face face = a2dglyph->m_face;
3079 FT_Get_Kerning( a2dglyph->m_face, a2dglyphprev->m_index, a2dglyph->m_index, FT_KERNING_DEFAULT, &kern );
3080 dxrel += ( int ) ( kern.x / 64.0 );
3082 if ( a2dglyphprev->m_rsb - a2dglyph->m_lsb >= 32 )
3084 else if ( a2dglyphprev->m_rsb - a2dglyph->m_lsb < -32 )
3088 a2dglyphprev = a2dglyph;
3091 FT_Glyph glyphimage = a2dglyph->m_glyph;
3094 FT_Glyph_Get_CBox( glyphimage, FT_GLYPH_BBOX_PIXELS, &bbox );
3095 int px = dx + dxrel + bbox.xMin;
3096 int py = dy - bbox.yMax;
3097 int wbox = bbox.xMax - bbox.xMin;
3098 int hbox = bbox.yMax - bbox.yMin;
3100 int advance = ( int ) ( glyphimage->advance.x / 64.0 );
3102 wxRect bboxglyph( px, py, wbox, hbox );
3103 bboxglyph.Inflate( 1 );
3109 wxRect bboxd( px, yBboxMinY - deviceh, advance, deviceh );
3117 FT_Matrix trans_matrix;
3129 trans_matrix.xx = ( FT_Fixed )( 0x10000L );
3130 trans_matrix.xy = ( FT_Fixed )( 0 );
3131 trans_matrix.yx = ( FT_Fixed )( 0 );
3132 trans_matrix.yy = ( FT_Fixed )( 0x10000L );
3138 textwasvisible =
true;
3140 else if ( textwasvisible )
3168 #if wxART2D_USE_FREETYPE
3173 int dx =
Round( wdx );
3174 int dy =
Round( wdy );
3178 FT_Matrix trans_matrix;
3188 trans_matrix.xx = ( FT_Fixed ) ( glyphToDevice.
GetValue( 0, 0 ) * 0x10000 );
3189 trans_matrix.xy = ( FT_Fixed ) ( glyphToDevice.
GetValue( 1, 0 ) * 0x10000 );
3190 trans_matrix.yx = ( FT_Fixed ) ( -glyphToDevice.
GetValue( 0, 1 ) * 0x10000 );
3191 trans_matrix.yy = ( FT_Fixed ) ( -glyphToDevice.
GetValue( 1, 1 ) * 0x10000 );
3192 vec.x = ( int ) ( ( wdx - dx ) * 64.0 );
3193 vec.y = ( int ) ( ( wdy - dy ) * -64.0 );
3197 trans_matrix.xx = ( FT_Fixed )( 0x10000L );
3198 trans_matrix.xy = ( FT_Fixed )( 0 );
3199 trans_matrix.yx = ( FT_Fixed )( 0 );
3200 trans_matrix.yy = ( FT_Fixed )( 0x10000L );
3207 #else // wxART2D_USE_FREETYPE
3209 #endif // wxART2D_USE_FREETYPE
3220 #if wxART2D_USE_FREETYPE
3228 if ( FT_Glyph_Copy( a2dglyph->m_glyph, &image ) != 0 )
3234 if ( FT_Glyph_Transform( image, &trans_matrix, &vec ) != 0 )
3236 wxFAIL_MSG( _(
"glyph transform wrong" ) );
3237 FT_Done_Glyph( image );
3243 FT_Glyph_Get_CBox( image, FT_GLYPH_BBOX_PIXELS, &bbox );
3275 if ( bbox.xMax - bbox.xMin <= 0 || bbox.yMax - bbox.yMin <= 0 )
3277 FT_Done_Glyph( image );
3288 int px = dx + bbox.xMin;
3289 int py = dy - bbox.yMax;
3290 int w = bbox.xMax - bbox.xMin + 1;
3291 int h = bbox.yMax - bbox.yMin + 1;
3310 wxRect absarea2( px, py, w, h );
3312 #if defined(__WXMSW__)
3314 bi.bmiHeader.biSize =
sizeof( bi.bmiHeader );
3315 bi.bmiHeader.biWidth = w;
3316 bi.bmiHeader.biHeight = -h;
3317 bi.bmiHeader.biPlanes = 1;
3318 bi.bmiHeader.biBitCount = 24;
3319 bi.bmiHeader.biCompression = BI_RGB;
3320 bi.bmiHeader.biSizeImage = 0;
3321 bi.bmiHeader.biClrUsed = 0;
3322 bi.bmiHeader.biClrImportant = 0;
3324 HBITMAP hbitmap = ( HBITMAP ) sub_bitmap.GetHBITMAP();
3325 unsigned char* buf = (
unsigned char* ) malloc( ( 3 * w +
sizeof( DWORD ) - 1 ) /
sizeof( DWORD ) *
sizeof( DWORD ) * h );
3326 ::GetDIBits( m_hdc2, hbitmap, 0, h, buf, &bi, DIB_RGB_COLORS );
3327 #else // defined( __WXMSW__ )
3328 wxImage wximage( sub_bitmap.ConvertToImage() );
3329 #endif // defined( __WXMSW__ )
3332 if ( image->format == FT_GLYPH_FORMAT_OUTLINE )
3335 spandata.colour = col;
3336 spandata.xmin = bbox.xMin;
3337 spandata.ymax = bbox.yMax;
3338 spandata.stride = w * 3;
3339 #if defined(__WXMSW__)
3341 spandata.stride = ( spandata.stride +
sizeof( DWORD ) - 1 ) /
sizeof( DWORD ) *
sizeof( DWORD );
3343 #else // defined( __WXMSW__ )
3344 spandata.buf = wximage.GetData();
3345 #endif // defined( __WXMSW__ )
3346 wxASSERT( spandata.buf != NULL );
3348 FT_Raster_Params params;
3349 params.target = NULL;
3350 params.flags = FT_RASTER_FLAG_AA | FT_RASTER_FLAG_DIRECT | FT_RASTER_FLAG_CLIP;
3351 params.gray_spans = ( FT_SpanFunc ) & a2dSpanFuncGray;
3352 params.black_spans = NULL;
3353 params.bit_test = ( FT_Raster_BitTest_Func ) NULL;
3354 params.bit_set = ( FT_Raster_BitSet_Func ) NULL;
3355 params.user = &spandata;
3356 params.clip_box = bbox;
3358 FT_Outline& outline = ( ( FT_OutlineGlyph ) image )->outline;
3359 if ( FT_Outline_Render( g_freetypeLibrary, &outline, ¶ms ) == 0 )
3361 #if defined( __WXMSW__ )
3362 ::SetDIBits( m_hdc2, hbitmap, 0, h, buf, &bi, DIB_RGB_COLORS );
3363 #else // defined( __WXMSW__ )
3364 wxBitmap sub_bitmap( wximage );
3365 #endif // defined( __WXMSW__ )
3371 wxFAIL_MSG( _(
"Non vector fonts are not supported" ) );
3373 #if defined(__WXMSW__)
3375 #endif // defined( __WXMSW__ )
3377 FT_Done_Glyph( image );
3378 #else // wxART2D_USE_FREETYPE
3380 #endif // wxART2D_USE_FREETYPE
3384 #if wxART2D_USE_GRAPHICS_CONTEXT
3386 IMPLEMENT_DYNAMIC_CLASS( a2dGcDrawer, a2dGcBaseDrawer )
3392 void a2dGcDrawer::InitContext()
3394 m_externalDc =
false;
3396 m_buffer = wxBitmap( m_width, m_height );
3397 m_memdc.SelectObject( m_buffer );
3398 m_render =
new a2dRenderer();
3399 m_context = ( a2dDcContext* ) ( ( a2dRenderer* )m_render )->CreateContext( &m_memdc, &m_buffer );
3402 a2dGcDrawer::a2dGcDrawer(
const wxSize& size ): a2dGcBaseDrawer( size.GetWidth(), size.GetHeight() )
3407 a2dGcDrawer::a2dGcDrawer(
int width,
int height ): a2dGcBaseDrawer( width, height )
3412 a2dGcDrawer::a2dGcDrawer(
const a2dGcDrawer& other )
3413 : a2dGcBaseDrawer( other )
3418 a2dGcDrawer::a2dGcDrawer(
const a2dDrawer2D& other )
3419 : a2dGcBaseDrawer( other )
3424 a2dGcDrawer::~a2dGcDrawer()
3428 m_memdc.SelectObject( wxNullBitmap );
3431 wxBitmap a2dGcDrawer::GetBuffer()
const
3436 void a2dGcDrawer::BeginDraw()
3438 wxASSERT_MSG( m_beginDraw_endDraw >= 0, wxT(
"a2dMemDcDrawer, unbalanced BeginDraw EndDraw" ) );
3440 if ( m_beginDraw_endDraw == 0 )
3442 m_memdc.SelectObject( m_buffer );
3444 SetDrawerFill( m_currentfill );
3445 SetDrawerStroke( m_currentstroke );
3447 DestroyClippingRegion();
3449 SetDrawStyle( m_drawstyle );
3451 m_memdc.SetMapMode( wxMM_TEXT );
3454 m_beginDraw_endDraw++;
3457 void a2dGcDrawer::EndDraw()
3459 m_beginDraw_endDraw--;
3461 wxASSERT_MSG( m_beginDraw_endDraw >= 0, wxT(
"a2dMemDcDrawer, unbalanced BeginDraw EndDraw" ) );
3463 if ( m_beginDraw_endDraw == 0 )
3465 m_memdc.SelectObject( wxNullBitmap );
3469 void a2dGcDrawer::SetBufferSize(
int w,
int h )
3473 wxBitmap helpbuf = wxBitmap( w, h );
3478 mdch.SelectObject( helpbuf );
3479 mdch.Blit( 0, 0, w, h, &m_memdc, 0, 0 );
3480 mdch.SelectObject( wxNullBitmap );
3482 m_memdc.SelectObject( wxNullBitmap );
3484 m_memdc.SelectObject( m_buffer );
3486 m_context = ( a2dDcContext* ) ( ( a2dRenderer* )m_render )->CreateContext( &m_memdc, &m_buffer );
3489 wxBitmap a2dGcDrawer::GetSubBitmap( wxRect rect )
const
3491 wxBitmap ret( rect.width, rect.height, m_buffer.GetDepth() );
3492 wxASSERT_MSG( ret.Ok(), wxT(
"GetSubImage error" ) );
3496 dcb.SelectObject( ret );
3497 dcb.Blit( 0, 0, rect.width, rect.height, const_cast<wxMemoryDC*>( &m_memdc ), rect.x, rect.y, wxCOPY,
false );
3498 dcb.SelectObject( wxNullBitmap );
3503 void a2dGcDrawer::BlitBuffer( wxDC* dc, wxRect rect,
const wxPoint& bufferpos )
3508 rect.width += rect.x;
3511 if ( rect.width <= 0 )
return;
3515 rect.height += rect.y;
3518 if ( rect.height <= 0 )
return;
3520 if ( rect.x + rect.width > m_width )
3522 rect.width = m_width - rect.x;
3524 if ( rect.width <= 0 )
return;
3526 if ( rect.y + rect.height > m_height )
3528 rect.height = m_height - rect.y;
3530 if ( rect.height <= 0 )
return;
3532 dc->Blit( rect.x - bufferpos.x, rect.y - bufferpos.y, rect.width, rect.height, &m_memdc, rect.x, rect.y, wxCOPY,
false );
3535 void a2dGcDrawer::ShiftBuffer(
int dxy,
bool yshift )
3537 int bw = GetBuffer().GetWidth();
3538 int bh = GetBuffer().GetHeight();
3541 if ( dxy > 0 && dxy < bh )
3543 wxRect rect( 0, 0, bw, bh - dxy );
3544 wxBitmap sub_bitmap( m_buffer.GetSubBitmap( rect ) );
3546 m_mdc1.SelectObject( m_buffer );
3547 m_mdc1.DrawBitmap( sub_bitmap, 0, dxy,
true );
3548 m_mdc1.SelectObject( wxNullBitmap );
3550 else if ( dxy < 0 && dxy > -bh )
3552 wxRect rect( 0, -dxy, bw, bh + dxy );
3553 wxBitmap sub_bitmap( m_buffer.GetSubBitmap( rect ) );
3555 m_mdc1.SelectObject( m_buffer );
3556 m_mdc1.DrawBitmap( sub_bitmap, 0, 0,
true );
3557 m_mdc1.SelectObject( wxNullBitmap );
3560 wxFAIL_MSG( wxT(
"you can only shift within height of buffer" ) );
3565 if ( dxy > 0 && dxy < bw )
3567 wxRect rect( 0, 0, bw - dxy, bh );
3568 wxBitmap sub_bitmap( m_buffer.GetSubBitmap( rect ) );
3570 m_mdc1.SelectObject( m_buffer );
3571 m_mdc1.DrawBitmap( sub_bitmap, dxy, 0,
true );
3572 m_mdc1.SelectObject( wxNullBitmap );
3574 else if ( dxy < 0 && dxy > -bw )
3576 wxRect rect( -dxy, 0, bw + dxy, bh );
3577 wxBitmap sub_bitmap( m_buffer.GetSubBitmap( rect ) );
3579 m_mdc1.SelectObject( m_buffer );
3580 m_mdc1.DrawBitmap( sub_bitmap, 0, 0,
true );
3581 m_mdc1.SelectObject( wxNullBitmap );
3584 wxFAIL_MSG( wxT(
"you can only shift within width of buffer" ) );
3588 void a2dGcDrawer::SetYaxis(
bool up )
3595 void a2dGcDrawer::DoSetActiveFont(
const a2dFont& font )
3597 a2dContext* context = ( a2dContext* ) m_context;
3598 a2dRenderer* render = ( a2dRenderer* ) m_render;
3599 wxGraphicsFont f = render->CreateFont( font );
3600 context->SetFont( f );
3603 void a2dGcDrawer::DoSetActiveStroke()
3607 a2dRenderer* render = ( a2dRenderer* ) m_render;
3608 a2dContext* context = ( a2dContext* ) m_context;
3609 wxGraphicsPen p = render->CreateStroke( m_activestroke );
3610 m_context->SetPen( p );
3613 void a2dGcDrawer::DoSetActiveFill()
3617 a2dRenderer* render = ( a2dRenderer* ) m_render;
3618 a2dContext* context = ( a2dContext* ) m_context;
3619 wxGraphicsBrush b = render->CreateFill( m_activefill );
3620 m_context->SetBrush( b );
3623 void a2dGcDrawer::DrawImage(
const wxImage& imagein,
double x,
double y,
double width,
double height, wxUint8 Opacity )
3625 if ( m_disableDrawing )
3630 a2dRenderer* render = ( a2dRenderer* ) m_render;
3631 a2dContext* context = ( a2dContext* ) m_context;
3632 wxGraphicsBitmap bitmap = render->CreateBitmap( imagein );
3633 #if wxCHECK_VERSION(2,9,0)
3634 context->DrawBitmap( bitmap, x, y, width, height );
3636 context->DrawGraphicsBitmap( bitmap, x, y, width, height );
3640 void a2dGcDrawer::DrawImage(
const a2dImageRGBA& image,
double x,
double y,
double width,
double height, wxUint8 Opacity )
3642 if ( m_disableDrawing )
3645 wxImage wximage = image.GetImage();
3646 a2dGcDrawer::DrawImage( wximage, x, y, width, height, Opacity );
3649 void a2dGcDrawer::DrawPoint(
double xc,
double yc )
3651 if ( m_disableDrawing )
3655 GetUserToDeviceTransform().TransformPoint( xc, yc, xt, yt );
3686 void a2dGcDrawer::DrawCharFreetype( wxChar c )
3688 wxGraphicsMatrix m = m_context->CreateMatrix();
3690 m_usertodevice( 0, 0), m_usertodevice( 0, 1),
3691 m_usertodevice( 1, 0), m_usertodevice( 1, 1),
3692 m_usertodevice( 2, 0), m_usertodevice( 2, 1) );
3693 m_context->SetTransform( m );
3694 static_cast<a2dDcContext*>(m_context)->DrawCharFreetype( c );
3700 #endif // wxART2D_USE_GRAPHICS_CONTEXT
virtual ~a2dMemDcDrawer()
destructor
virtual void SetYaxis(bool up)
set if the Yaxis goes up or down
int WorldToDeviceXRel(double x) const
convert x relative from world to device coordinates
a2dAffineMatrix m_usertodevice
pointer to current user-to-device transform matrix ( so includes mapping matrix ) ...
a2dStroke m_activestroke
used while rendering
wxPoint2DDouble a2dPoint2D
this to define if coordinate numbers are integer or doubles
a2dDrawStyle m_drawstyle
drawstyle (like invert mode)
void DoSetActiveStroke()
per drawer implementation
double GetSize() const
Get the font size.
void DrawPoint(double xc, double yc)
draw single point
wxUint8 m_StrokeOpacityCol1
active stroke alpha
#define wxDynamicCast(obj, className)
Define wxDynamicCast so that it will give a compiler error for unrelated types.
Base class for all types of strokes, understood by a2dDrawer2D classes.
virtual void SetTransform(const a2dAffineMatrix &userToWorld)
set user-to-world transform matrix.
a2dStroke m_fixStrokeRestore
used to restore an overruled fix style
a2dFill m_activefill
used while rendering
unsigned int ConvertSplinedPolyline2(unsigned int n)
converts internal device points array to spline. Returns new number of points.
void SetDrawStyle(a2dDrawStyle drawstyle)
set drawstyle to use for drawing,
void DrawLine(double x1, double y1, double x2, double y2)
Draw line in world coordinates.
int WorldToDeviceY(double y) const
convert y from world to device coordinates
const a2dStroke * a2dBLACK_STROKE
global a2dStroke stock object for BLACK stroking
Stroke and fill base classes.
virtual void DeviceDrawAnnotation(const wxString &text, wxCoord x, wxCoord y, const wxFont &font)
text drawn in device coordinates
virtual void PopTransform(void)
Recall the previously saved user-to-world transform off the matrix stack.
wxColour GetColour2() const
return colour 2
const int SPLINE_STEP
number of steps when converting a spline to lines.
a2dStroke m_currentstroke
used while rendering
a2dDrawStyle m_fixDrawstyle
used to restore an overruled fix style
virtual void DeviceDrawLines(unsigned int n, bool spline)
draw an internal polyline in device coordinates
void SetClippingRegion(a2dVertexList *points, bool spline=false, wxPolygonFillMode fillStyle=wxODDEVEN_RULE)
set clipping region from polygon to which everything drawn will be clipped.
void ResetStyle()
set a pre-defined style reseting cashed values.
void SetBufferSize(int w, int h)
change the size of the buffer
wxBitmap GetSubBitmap(wxRect sub_rect) const
return a bitmap representing a rectangular part of the buffer
const a2dFill * a2dBLACK_FILL
global a2dFill stock object for BLACK filling
wxFont & GetFont(void)
wxFont in case of a2dFONT_WXDC
bool IsStrokeOnly()
wxART2D_USE_GRAPHICS_CONTEXT
void SetBufferSize(int w, int h)
set buffer size to w pixel wide and h pixels heigh
void DrawEllipse(double xc, double yc, double width, double height)
Draw Ellipse in world coordinates.
void SetRenderDC(wxDC *dc)
set the DC that is used for rendering
a2dMemDcDrawer(int width=0, int height=0)
constructor ( just some default )
std::vector< wxRealPoint > m_cpointsDouble
cached array for containing transformed device coordinates (double)
double DeviceToWorldYRel(double y) const
convert y relative from device to world coordinates
double m_y3
control point 2
virtual void BeginDraw()
start to draw on this context (used to initialize a specific drawer)
double GetDescent() const
Get descent.
void SetDrawerStroke(const a2dStroke &stroke)
Used to set the current stroke.
bool IsIdentity(void) const
Is the matrix the identity matrix?
Defines a font to be set to a2dDrawer2D or stored in a2dCanvsObject etc.
double m_x3
control point 2
virtual void DrawPolygon(a2dVertexArray *points, bool spline=false, wxPolygonFillMode fillStyle=wxODDEVEN_RULE)
Draw polygon in world coordinates using pointarray.
This class implements drawing functions for wxDC based drawing.
bool GetPixelStroke() const
if the width is pixels or not.
double GetValue(int col, int row) const
get the value in the matrix at col,row
bool GetYaxis() const
get y axis orientation
void DrawCircle(double xc, double yc, double radius)
Draw Circle in world coordinates.
a2dFont m_currentfont
current font set
This class implements drawing functions for wxDC based drawing.
a2dBoundingBox m_clipboxworld
current clipping area in world coordinates
virtual void DrawCharFreetype(wxChar c)
Draw a freetype character.
a2dAffineMatrix m_usertoworld
pointer to current user-to-world transform matrix
void DrawCharFreetype(wxColour col, wxChar c, int x, int y, FT_Matrix trans_matrix, FT_Vector vec)
draw one character into screen buffer, at the position (x,y).
void DrawCharFreetypeCb(wxChar c)
Wrapper for DrawCharFreetype.
wxColour GetColour() const
return colour 1
unsigned char m_colour1blueStroke
active stroke colours
wxBitmap GetBuffer() const
return buffer as a bitmap
double m_y2
control point 1
virtual void BeginDraw()
start to draw on this context (used to initialize a specific drawer)
bool GetVpath(wxChar c, a2dVpath &glyph, const a2dAffineMatrix &affine=a2dIDENTITY_MATRIX)
Get the glyph of a single character as a vpath.
void DeviceDrawLine(double x1, double y1, double x2, double y2)
draw in pixels
std::vector< wxPoint > m_cpointsInt
cached array for containing transformed device coordinates (integer)
vertex list of line and arc segments.
void TransformPoint(double x, double y, double &tx, double &ty) const
Transform a point.
virtual void DrawCenterRoundedRectangle(double xc, double yc, double width, double height, double radius, bool pixelsize=false)
Draw CenterRoundedRectangle in world coordinates.
virtual void ExtendClippingRegion(a2dVertexList *points, bool spline=false, wxPolygonFillMode fillStyle=wxODDEVEN_RULE, a2dBooleanClip clipoperation=a2dCLIP_AND)
extend clipping region with a polygon to which everything drawn will be clipped.
double GetRotation() const
return rotation
virtual void EndDraw()
end drawing on this context (used to reset a specific drawer)
double TransformDistance(double distance) const
Transform a distance.
void DrawTextGeneric(const wxString &text, double x, double y, void(a2dDrawer2D::*drawchar)(wxChar))
virtual void ExtendAndPushClippingRegion(a2dVertexList *points, bool spline=false, wxPolygonFillMode fillStyle=wxODDEVEN_RULE, a2dBooleanClip clipoperation=a2dCLIP_AND)
push on stack the current clipping region and extend clipping region
virtual void SetActiveFill(const a2dFill &fill)
sync with actual API graphical context
a2dDrawStyle
Define the manner in which a2dCanvasView draws to the device.
void SetClippingRegionDev(wxCoord minx, wxCoord miny, wxCoord width, wxCoord height)
set clipping region using x y values in device coordinates
void SetDrawerFill(const a2dFill &fill)
Used to set the current fill.
int WorldToDeviceYRel(double y) const
convert y relative from world to device coordinates
void DestroyClippingRegion()
set clipping region off
virtual void PushTransform()
Save the current user-to-world transform on the affine stack.
a2dClipRegionList m_clipregionlist
pushed clipping regions
void PopClippingRegion()
pop a previously pushed clipping region
virtual ~a2dDcDrawer()
destructor
virtual void DrawRoundedRectangle(double x, double y, double width, double height, double radius, bool pixelsize=false)
Draw RoundedRectangle in world coordinates.
a2dAffineMatrix m_worldtodevice
world to device coordinate mapping
double GetLineHeight() const
Get the line height.
double m_displayaberration
accuracy of arc segment calculation etc. in device coordinates
virtual void ResetStyle()
set a pre-defined style reseting cashed values.
void DeviceDrawVerticalLine(int x1, int y1, int y2, bool use_stroke_color)
Draw a pixel-width, unstroked vertical line in device (pixel) coordinates.
#define forEachIn(listtype, list)
easy iteration for a2dlist
the antigrain based drawing context derived from a2dDrawer2D
wxDC * m_renderDC
The DC to use to draw to the device or buffer ( depends on type of a2dCanvasView ) ...
unsigned char m_colour1greenStroke
active stroke colours
wxBitmap GetBuffer() const
get buffer as bitmap pointer
void DeviceDrawBitmap(const wxBitmap &bmp, double x, double y, bool useMask=false)
in pixels
#define wxStaticCast(obj, className)
The wxWindows 2.4.2 wxStaticCast is buggy. It evaluates its argument twice.
Drawing context abstraction.
wxBitmap GetSubBitmap(wxRect sub_rect) const
get part of the buffer given a rect
bool CalcR(a2dVpathSegmentPtr prev, double &radius, double ¢er_x, double ¢er_y, double &beginrad, double &midrad, double &endrad, double &phit)
Calculation of center for the Arc.
void DoSetActiveFill()
per drawer implementation
Contains graphical drawing context specific classes. a2dDcDrawer and derived classes are used for dra...
int WorldToDeviceX(double x) const
convert x from world to device coordinates
virtual void DrawLine(double x1, double y1, double x2, double y2)
Draw line in world coordinates.
virtual void ShiftBuffer(int dxy, bool yshift)
quick scroll over small distance
the antigrain based drawing context derived from a2dDrawer2D
void SetClippingRegionDev(wxCoord minx, wxCoord miny, wxCoord width, wxCoord height)
set clipping region using x y values in device coordinates
double m_x2
control point 1
A 2x3 affine matrix class for 2D transformations.
a2dStroke GetDrawerStroke() const
get the current stroke
wxMemoryDC * m_memdc
Created at BeginDraw, and destoyed at EndDraw, used to actually draw.
virtual void SetActiveStroke(const a2dStroke &stroke)
sync with actual API graphical context
void DeviceDrawPixel(int x1, int y1, unsigned char r, unsigned char g, unsigned char b, unsigned char a)
draw a single, unstroked pixel in device coordinates with the given color
a2dBoundingBox ToWorld(const wxRect &rect)
convert the rect in device coordinates to a bounding box in world coordinates and return that boundin...
void SetMappingMatrix(const a2dAffineMatrix &mapping)
int m_height
device size height
bool m_disableDrawing
all drawing is disabled when this is true
void DrawPolyPolygon(a2dListOfa2dVertexList polylist, wxPolygonFillMode fillStyle=wxODDEVEN_RULE)
draw a list of polygons ( contour clockwise becomes hole )
bool GetFilling() const
if true, filling is on else filling is transparent.
a2dDcDrawer(int width=0, int height=0)
Drawer having a buffer of w pixel wide and h pixels heigh.
void DrawImage(const wxImage &image, double x, double y, double width, double height, wxUint8 Opacity=255)
Draw wxImage in world coordinates.
Contains graphical drawing context specific classes. a2dDrawer2D and derived classes are used for dra...
wxPoint * _convertToIntPointCache(int n, wxRealPoint *pts)
Convert double points to integer coords in the point cache and return pointer.
holes one glyph from a freetype font.
a2dBooleanClip
Used for defining how a ClippingRegion defined as a polygon is combined with.
wxClientDC * m_deviceDC
wxDc to draw or blit to the device
wxRect m_clipboxdev
current clipping area in device coordinates
virtual void DrawCharFreetype(wxChar c)
Draw a freetype character.
virtual void BeginDraw()
start to draw on this context (used to initialize a specific drawer)
used in freetype rendering
void FillPolygon(int n, wxRealPoint points[])
Used for filling with Gradient fill style.
void Aberration(double aber, double angle, double radius, double &dphi, unsigned int &segments)
calculate number of segments in an arc such that a certain accuracy is maintained ...
virtual void DrawPolygon(const a2dVertexList *list, bool spline=false, wxPolygonFillMode fillStyle=wxODDEVEN_RULE)
Draw polygon in world coordinates using pointlist.
virtual void DrawCharDc(wxChar c)
Draw a dc character.
int m_beginDraw_endDraw
counter for BeginDraw EndDraw calls
int m_width
device size width
virtual void DrawCharUnknown(wxChar c)
Draw a cross instead of a character.
double m_y1
y endpoint of line
void DeviceDrawHorizontalLine(int x1, int y1, int x2, bool use_stroke_color)
Draw a pixel-width, unstroked horizontal line in device (pixel) coordinates.
unsigned char m_colour1redStroke
active stroke colours
void BlitBuffer()
blit whole buffer to device
wxColour GetColour() const
return colour
bool Scale(double scale)
Scale by scale (isotropic scaling i.e. the same in x and y):
const a2dStroke * a2dTRANSPARENT_STROKE
global a2dStroke stock object for TRANSPARENT stroking
virtual void DeviceDrawPolygon(unsigned int n, bool spline, wxPolygonFillMode fillStyle)
draw an internal polygon in device coordinates
wxWindow * m_display
view its window.
bool m_forceNormalizedFont
up or down
int ToDeviceLines(a2dVertexArray *points, a2dBoundingBox &devbbox, bool &smallPoly, bool replaceByRectangle=false)
convert vertex array containing line and arc segments in user coordinates to device coordinate lines...
The a2dBoundingBox class stores one a2dBoundingBox of a a2dCanvasObject.
bool m_externalDc
when dc is set from the outside, this is true.
void DrawVpath(const a2dVpath *path)
Draw vector path in world coordinates.
const a2dAffineMatrix & GetTransform() const
get the user-to-world transform matrix.
wxBitmap m_buffer
the buffer that is used for rendering
void DrawRoundedRectangle(double x, double y, double width, double height, double radius, bool pixelsize=false)
Draw RoundedRectangle in world coordinates.
double m_x1
x endpoint of line
virtual void DrawEllipse(double x, double y, double width, double height)
Draw Ellipse in world coordinates.
void DrawImage(const wxImage &image, double x, double y, double width, double height, wxUint8 Opacity=255)
Draw a wxImage in world coordinates.
void ConvertToPolygon(a2dListOfa2dVertexList &addTo, bool arc=true)
#define Round(x)
round to integer such that e.g 2.5 < x < 3.5 becomes 3
virtual void DrawTextDc(const wxString &text, double x, double y)
Draw text in user coordinates, based on a dc font .
void DrawImage(const wxImage &image, double x, double y, double width, double height, wxUint8 Opacity=255)
Draw a wxImage in world coordinates.
virtual void DeviceDrawPolygon(unsigned int n, bool spline, wxPolygonFillMode fillStyle)
draw an internal polygon in device coordinates
virtual void DrawTextFreetype(const wxString &text, double x, double y)
Draw text in world coordinates, based on a freetype font .
virtual void EndDraw()
end drawing on this context (used to reset a specific drawer)
a2dFill m_currentfill
used while rendering
const a2dAffineMatrix & GetMappingMatrix()
get the world-to-device (aka mapping) matrix
A pointer class, that automatically calls SmrtPtrOwn/SmrtPtrRelease.
wxUint8 m_OpacityFactor
opacity will be the one set, derived by this
double DeviceToWorldXRel(double x) const
convert x relative from device to world coordinates
const a2dAffineMatrix & GetUserToDeviceTransform() const
get matrix which transforms directly from user coordinates to device
const double wxPI
defines PI
virtual void EndDraw()
end drawing on this context (used to reset a specific drawer)
unsigned int ConvertSplinedPolygon2(unsigned int n)
converts internal device points array to spline. Returns new number of points.
const a2dFill * a2dTRANSPARENT_FILL
global a2dFill stock object for TRANSPARENT filling
a2dFill m_fixFillRestore
used to restore an overruled fix style