X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/11fdee427ee7c2aae0fda8655b30791f084a45ab..82a234fbff7fbc174c9459980995b73f37087992:/samples/drawing/drawing.cpp diff --git a/samples/drawing/drawing.cpp b/samples/drawing/drawing.cpp index 38ae2301d5..021de6387b 100644 --- a/samples/drawing/drawing.cpp +++ b/samples/drawing/drawing.cpp @@ -1,5 +1,5 @@ ///////////////////////////////////////////////////////////////////////////// -// Name: drawing.cpp +// Name: samples/drawing/drawing.cpp // Purpose: shows and tests wxDC features // Author: Robert Roebling // Modified by: @@ -17,11 +17,6 @@ // headers // ---------------------------------------------------------------------------- -#if defined(__GNUG__) && !defined(__APPLE__) - #pragma implementation - #pragma interface -#endif - // For compilers that support precompilation, includes "wx/wx.h". #include "wx/wxprec.h" @@ -39,6 +34,19 @@ #include "wx/image.h" #include "wx/artprov.h" +#define wxTEST_GRAPHICS 1 + +#if wxTEST_GRAPHICS +#include "wx/graphics.h" +#if wxUSE_GRAPHICS_CONTEXT == 0 +#undef wxTEST_GRAPHICS +#define wxTEST_GRAPHICS 0 +#endif +#else +#undef wxUSE_GRAPHICS_CONTEXT +#define wxUSE_GRAPHICS_CONTEXT 0 +#endif + // ---------------------------------------------------------------------------- // ressources // ---------------------------------------------------------------------------- @@ -62,9 +70,16 @@ enum ScreenToShow Show_Brushes, Show_Polygons, Show_Mask, + Show_Mask_Stretch, Show_Ops, Show_Regions, - Show_Circles + Show_Circles, + Show_Splines, +#if wxUSE_GRAPHICS_CONTEXT + Show_Alpha, +#endif + Show_Gradient, + Show_Max }; // ---------------------------------------------------------------------------- @@ -116,6 +131,9 @@ public: void OnQuit(wxCommandEvent& event); void OnAbout(wxCommandEvent& event); void OnClip(wxCommandEvent& event); +#if wxUSE_GRAPHICS_CONTEXT + void OnGraphicContext(wxCommandEvent& event); +#endif void OnShow(wxCommandEvent &event); void OnOption(wxCommandEvent &event); @@ -156,17 +174,31 @@ public: // set or remove the clipping region void Clip(bool clip) { m_clip = clip; Refresh(); } +#if wxUSE_GRAPHICS_CONTEXT + void UseGraphicContext(bool use) { m_useContext = use; Refresh(); } +#endif protected: + enum DrawMode + { + Draw_Normal, + Draw_Stretch + }; + void DrawTestLines( int x, int y, int width, wxDC &dc ); void DrawTestPoly(wxDC& dc); void DrawTestBrushes(wxDC& dc); void DrawText(wxDC& dc); - void DrawImages(wxDC& dc); + void DrawImages(wxDC& dc, DrawMode mode); void DrawWithLogicalOps(wxDC& dc); +#if wxUSE_GRAPHICS_CONTEXT + void DrawAlpha(wxDC& dc); +#endif void DrawRegions(wxDC& dc); void DrawCircles(wxDC& dc); + void DrawSplines(wxDC& dc); void DrawDefault(wxDC& dc); + void DrawGradients(wxDC& dc); void DrawRegionsHelper(wxDC& dc, wxCoord x, bool firstTime); @@ -177,6 +209,9 @@ private: wxBitmap m_smile_bmp; wxIcon m_std_icon; bool m_clip; +#if wxUSE_GRAPHICS_CONTEXT + bool m_useContext ; +#endif DECLARE_EVENT_TABLE() }; @@ -189,22 +224,31 @@ private: enum { // menu items - File_Quit = 1, - File_About, + File_Quit = wxID_EXIT, + File_About = wxID_ABOUT, - MenuShow_First, + MenuShow_First = wxID_HIGHEST, File_ShowDefault = MenuShow_First, File_ShowText, File_ShowLines, File_ShowBrushes, File_ShowPolygons, File_ShowMask, + File_ShowMaskStretch, File_ShowOps, File_ShowRegions, File_ShowCircles, - MenuShow_Last = File_ShowCircles, + File_ShowSplines, +#if wxUSE_GRAPHICS_CONTEXT + File_ShowAlpha, +#endif + File_ShowGradients, + MenuShow_Last = File_ShowGradients, File_Clip, +#if wxUSE_GRAPHICS_CONTEXT + File_GraphicContext, +#endif MenuOption_First, @@ -274,6 +318,7 @@ bool MyApp::LoadImages() wxPathList pathList; pathList.Add(_T(".")); pathList.Add(_T("..")); + pathList.Add(_T("../..")); wxString path = pathList.FindValidPath(_T("pat4.bmp")); if ( !path ) @@ -317,6 +362,9 @@ bool MyApp::LoadImages() // `Main program' equivalent: the program execution "starts" here bool MyApp::OnInit() { + if ( !wxApp::OnInit() ) + return false; + // Create the main application window MyFrame *frame = new MyFrame(_T("Drawing sample"), wxPoint(50, 50), wxSize(550, 340)); @@ -382,6 +430,9 @@ MyCanvas::MyCanvas(MyFrame *parent) m_smile_bmp = wxBitmap(smile_xpm); m_std_icon = wxArtProvider::GetIcon(wxART_INFORMATION); m_clip = false; +#if wxUSE_GRAPHICS_CONTEXT + m_useContext = false; +#endif } void MyCanvas::DrawTestBrushes(wxDC& dc) @@ -513,7 +564,7 @@ void MyCanvas::DrawDefault(wxDC& dc) // mark the origin dc.DrawCircle(0, 0, 10); -#if !wxMAC_USE_CORE_GRAPHICS +#if !defined(wxMAC_USE_CORE_GRAPHICS) || !wxMAC_USE_CORE_GRAPHICS // GetPixel and FloodFill not supported by Mac OS X CoreGraphics // (FloodFill uses Blit from a non-wxMemoryDC) //flood fill using brush, starting at 1,1 and replacing whatever colour we find there @@ -669,7 +720,7 @@ void MyCanvas::DrawDefault(wxDC& dc) // Added by JACS to demonstrate bizarre behaviour. // With a size of 70, we get a missing red RHS, - // and the hight is too small, so we get yellow + // and the height is too small, so we get yellow // showing. With a size of 40, it draws as expected: // it just shows a white rectangle with red outline. int totalWidth = 70; @@ -739,9 +790,9 @@ void MyCanvas::DrawText(wxDC& dc) dc.DrawText( _T("This is Swiss 18pt text."), 110, 40 ); - long length; - long height; - long descent; + wxCoord length; + wxCoord height; + wxCoord descent; dc.GetTextExtent( _T("This is Swiss 18pt text."), &length, &height, &descent ); text.Printf( wxT("Dimensions are length %ld, height %ld, descent %ld"), length, height, descent ); dc.DrawText( text, 110, 80 ); @@ -793,7 +844,7 @@ static const struct { wxT("wxXOR"), wxXOR }, }; -void MyCanvas::DrawImages(wxDC& dc) +void MyCanvas::DrawImages(wxDC& dc, DrawMode mode) { dc.DrawText(_T("original image"), 0, 0); dc.DrawBitmap(*gs_bmpNoMask, 0, 20, 0); @@ -815,7 +866,15 @@ void MyCanvas::DrawImages(wxDC& dc) dc.DrawText(rasterOperations[n].name, x, y - 20); memDC.SelectObject(*gs_bmpWithColMask); - dc.Blit(x, y, cx, cy, &memDC, 0, 0, rasterOperations[n].rop, true); + if ( mode == Draw_Stretch ) + { + dc.StretchBlit(x, y, cx, cy, &memDC, 0, 0, cx/2, cy/2, + rasterOperations[n].rop, true); + } + else + { + dc.Blit(x, y, cx, cy, &memDC, 0, 0, rasterOperations[n].rop, true); + } } } @@ -855,12 +914,92 @@ void MyCanvas::DrawWithLogicalOps(wxDC& dc) } } +#if wxUSE_GRAPHICS_CONTEXT +#ifdef __WXGTK20__ +void MyCanvas::DrawAlpha(wxDC& no_dc) +#else +void MyCanvas::DrawAlpha(wxDC& dc) +#endif +{ +#ifdef __WXGTK__ + wxGCDC dc( this ); + PrepareDC( dc ); +#endif + + wxDouble margin = 20 ; + wxDouble width = 180 ; + wxDouble radius = 30 ; + + dc.SetPen( wxPen( wxColour( 128, 0, 0, 255 ),12, wxSOLID)); + dc.SetBrush( wxBrush( wxColour( 255, 0, 0, 255),wxSOLID)); + + wxRect r(margin,margin+width*0.66,width,width) ; + + dc.DrawRoundedRectangle( r.x, r.y, r.width, r.width, radius ) ; + + dc.SetPen( wxPen( wxColour( 0, 0, 128, 255 ),12, wxSOLID)); + dc.SetBrush( wxBrush( wxColour( 0, 0, 255, 255),wxSOLID)); + + r.Offset( width * 0.8 , - width * 0.66 ) ; + + dc.DrawRoundedRectangle( r.x, r.y, r.width, r.width, radius ) ; + + dc.SetPen( wxPen( wxColour( 128, 128, 0, 255 ),12, wxSOLID)); + dc.SetBrush( wxBrush( wxColour( 192, 192, 0, 255),wxSOLID)); + + r.Offset( width * 0.8 , width *0.5 ) ; + + dc.DrawRoundedRectangle( r.x, r.y, r.width, r.width, radius ) ; + + dc.SetPen( *wxTRANSPARENT_PEN ) ; + dc.SetBrush( wxBrush( wxColour(255,255,128,128) ) ); + dc.DrawRoundedRectangle( 0 , margin + width / 2 , width * 3 , 100 , radius) ; + + dc.SetTextForeground( wxColour(255,255,0,128) ); + dc.SetFont( wxFont( 40, wxFONTFAMILY_SWISS, wxFONTSTYLE_ITALIC, wxFONTWEIGHT_NORMAL ) ); + dc.DrawText( wxT("Hello!"), 120, 80 ); +} + +#endif + void MyCanvas::DrawCircles(wxDC& dc) { int x = 100, y = 100, r = 20; + dc.SetPen( *wxRED_PEN ); + dc.SetBrush( *wxGREEN_BRUSH ); + + dc.DrawText(_T("Some circles"), 0, y); + dc.DrawCircle(x, y, r); + dc.DrawCircle(x + 2*r, y, r); + dc.DrawCircle(x + 4*r, y, r); + + y += 2*r; + dc.DrawText(_T("And ellipses"), 0, y); + dc.DrawEllipse(x - r, y, 2*r, r); + dc.DrawEllipse(x + r, y, 2*r, r); + dc.DrawEllipse(x + 3*r, y, 2*r, r); + + y += 2*r; + dc.DrawText(_T("And arcs"), 0, y); + dc.DrawArc(x - r, y, x + r, y, x, y); + dc.DrawArc(x + 4*r, y, x + 2*r, y, x + 3*r, y); + dc.DrawArc(x + 5*r, y, x + 5*r, y, x + 6*r, y); + + y += 2*r; + dc.DrawEllipticArc(x - r, y, 2*r, r, 0, 90); + dc.DrawEllipticArc(x + r, y, 2*r, r, 90, 180); + dc.DrawEllipticArc(x + 3*r, y, 2*r, r, 180, 270); + dc.DrawEllipticArc(x + 5*r, y, 2*r, r, 270, 360); + + // same as above, just transparent brush + + dc.SetPen( *wxRED_PEN ); + dc.SetBrush( *wxTRANSPARENT_BRUSH ); + + y += 2*r; dc.DrawText(_T("Some circles"), 0, y); dc.DrawCircle(x, y, r); dc.DrawCircle(x + 2*r, y, r); @@ -883,6 +1022,174 @@ void MyCanvas::DrawCircles(wxDC& dc) dc.DrawEllipticArc(x + r, y, 2*r, r, 90, 180); dc.DrawEllipticArc(x + 3*r, y, 2*r, r, 180, 270); dc.DrawEllipticArc(x + 5*r, y, 2*r, r, 270, 360); + +} + +void MyCanvas::DrawSplines(wxDC& dc) +{ +#if wxUSE_SPLINES + dc.DrawText(_T("Some splines"), 10, 5); + + // values are hardcoded rather than randomly generated + // so the output can be compared between native + // implementations on platforms with different random + // generators + + const int R = 300; + const wxPoint center( R + 20, R + 20 ); + const int angles[7] = { 0, 10, 33, 77, 13, 145, 90 }; + const int radii[5] = { 100 , 59, 85, 33, 90 }; + const int n = 200; + wxPoint pts[n]; + + // background spline calculation + unsigned int radius_pos = 0; + unsigned int angle_pos = 0; + int angle = 0; + for ( int i = 0; i < n; i++ ) + { + angle += angles[ angle_pos ]; + int r = R * radii[ radius_pos ] / 100; + pts[ i ].x = center.x + (wxCoord)( r * cos( M_PI * angle / 180.0) ); + pts[ i ].y = center.y + (wxCoord)( r * sin( M_PI * angle / 180.0) ); + + angle_pos++; + if ( angle_pos >= WXSIZEOF(angles) ) angle_pos = 0; + + radius_pos++; + if ( radius_pos >= WXSIZEOF(radii) ) radius_pos = 0; + } + + // background spline drawing + dc.SetPen(*wxRED_PEN); + dc.DrawSpline(WXSIZEOF(pts), pts); + + // less detailed spline calculation + wxPoint letters[4][5]; + // w + letters[0][0] = wxPoint( 0,1); // O O + letters[0][1] = wxPoint( 1,3); // * * + letters[0][2] = wxPoint( 2,2); // * O * + letters[0][3] = wxPoint( 3,3); // * * * * + letters[0][4] = wxPoint( 4,1); // O O + // x1 + letters[1][0] = wxPoint( 5,1); // O*O + letters[1][1] = wxPoint( 6,1); // * + letters[1][2] = wxPoint( 7,2); // O + letters[1][3] = wxPoint( 8,3); // * + letters[1][4] = wxPoint( 9,3); // O*O + // x2 + letters[2][0] = wxPoint( 5,3); // O*O + letters[2][1] = wxPoint( 6,3); // * + letters[2][2] = wxPoint( 7,2); // O + letters[2][3] = wxPoint( 8,1); // * + letters[2][4] = wxPoint( 9,1); // O*O + // W + letters[3][0] = wxPoint(10,0); // O O + letters[3][1] = wxPoint(11,3); // * * + letters[3][2] = wxPoint(12,1); // * O * + letters[3][3] = wxPoint(13,3); // * * * * + letters[3][4] = wxPoint(14,0); // O O + + const int dx = 2 * R / letters[3][4].x; + const int h[4] = { -R/2, 0, R/4, R/2 }; + + for ( int m = 0; m < 4; m++ ) + { + for ( int n = 0; n < 5; n++ ) + { + letters[m][n].x = center.x - R + letters[m][n].x * dx; + letters[m][n].y = center.y + h[ letters[m][n].y ]; + } + + dc.SetPen( wxPen( wxT("blue"), 1, wxDOT) ); + dc.DrawLines(5, letters[m]); + dc.SetPen( wxPen( wxT("black"), 4, wxSOLID) ); + dc.DrawSpline(5, letters[m]); + } + +#else + dc.DrawText(_T("Splines not supported."), 10, 5); +#endif +} + +void MyCanvas::DrawGradients(wxDC& dc) +{ + static const int TEXT_HEIGHT = 15; + + // LHS: linear + wxRect r(10, 10, 50, 50); + dc.DrawText(_T("wxRIGHT"), r.x, r.y); + r.Offset(0, TEXT_HEIGHT); + dc.GradientFillLinear(r, *wxWHITE, *wxBLUE, wxRIGHT); + + r.Offset(0, r.height + 10); + dc.DrawText(_T("wxLEFT"), r.x, r.y); + r.Offset(0, TEXT_HEIGHT); + dc.GradientFillLinear(r, *wxWHITE, *wxBLUE, wxLEFT); + + r.Offset(0, r.height + 10); + dc.DrawText(_T("wxDOWN"), r.x, r.y); + r.Offset(0, TEXT_HEIGHT); + dc.GradientFillLinear(r, *wxWHITE, *wxBLUE, wxDOWN); + + r.Offset(0, r.height + 10); + dc.DrawText(_T("wxUP"), r.x, r.y); + r.Offset(0, TEXT_HEIGHT); + dc.GradientFillLinear(r, *wxWHITE, *wxBLUE, wxUP); + + + // RHS: concentric + r = wxRect(200, 10, 50, 50); + dc.DrawText(_T("Blue inside"), r.x, r.y); + r.Offset(0, TEXT_HEIGHT); + dc.GradientFillConcentric(r, *wxBLUE, *wxWHITE); + + r.Offset(0, r.height + 10); + dc.DrawText(_T("White inside"), r.x, r.y); + r.Offset(0, TEXT_HEIGHT); + dc.GradientFillConcentric(r, *wxWHITE, *wxBLUE); + + r.Offset(0, r.height + 10); + dc.DrawText(_T("Blue in top left corner"), r.x, r.y); + r.Offset(0, TEXT_HEIGHT); + dc.GradientFillConcentric(r, *wxBLUE, *wxWHITE, wxPoint(0, 0)); + + r.Offset(0, r.height + 10); + dc.DrawText(_T("Blue in bottom right corner"), r.x, r.y); + r.Offset(0, TEXT_HEIGHT); + dc.GradientFillConcentric(r, *wxBLUE, *wxWHITE, wxPoint(r.width, r.height)); + + // check that the area filled by the gradient is exactly the interior of + // the rectangle + r.x = 350; + r.y = 30; + dc.DrawText("The interior should be filled but", r.x, r.y); + r.y += 15; + dc.DrawText(" the red border should remain visible:", r.x, r.y); + r.y += 15; + + r.width = + r.height = 50; + wxRect r2 = r; + r2.x += 60; + wxRect r3 = r; + r3.y += 60; + wxRect r4 = r2; + r4.y += 60; + dc.SetPen(wxPen(wxColour(255, 0, 0))); + dc.DrawRectangle(r); + r.Deflate(1); + dc.GradientFillLinear(r, wxColour(0,255,0), wxColour(0,0,0), wxNORTH); + dc.DrawRectangle(r2); + r2.Deflate(1); + dc.GradientFillLinear(r2, wxColour(0,0,0), wxColour(0,255,0), wxSOUTH); + dc.DrawRectangle(r3); + r3.Deflate(1); + dc.GradientFillLinear(r3, wxColour(0,255,0), wxColour(0,0,0), wxEAST); + dc.DrawRectangle(r4); + r4.Deflate(1); + dc.GradientFillLinear(r4, wxColour(0,0,0), wxColour(0,255,0), wxWEST); } void MyCanvas::DrawRegions(wxDC& dc) @@ -942,7 +1249,15 @@ void MyCanvas::DrawRegionsHelper(wxDC& dc, wxCoord x, bool firstTime) void MyCanvas::OnPaint(wxPaintEvent &WXUNUSED(event)) { - wxPaintDC dc(this); + wxPaintDC pdc(this); + +#if wxUSE_GRAPHICS_CONTEXT + wxGCDC gdc( pdc ) ; + wxDC &dc = m_useContext ? (wxDC&) gdc : (wxDC&) pdc ; +#else + wxDC &dc = pdc ; +#endif + PrepareDC(dc); m_owner->PrepareDC(dc); @@ -985,6 +1300,10 @@ void MyCanvas::OnPaint(wxPaintEvent &WXUNUSED(event)) DrawCircles(dc); break; + case Show_Splines: + DrawSplines(dc); + break; + case Show_Regions: DrawRegions(dc); break; @@ -1009,12 +1328,29 @@ void MyCanvas::OnPaint(wxPaintEvent &WXUNUSED(event)) break; case Show_Mask: - DrawImages(dc); + DrawImages(dc, Draw_Normal); + break; + + case Show_Mask_Stretch: + DrawImages(dc, Draw_Stretch); break; case Show_Ops: DrawWithLogicalOps(dc); break; + +#if wxUSE_GRAPHICS_CONTEXT + case Show_Alpha: + DrawAlpha(dc); + break; +#endif + + case Show_Gradient: + DrawGradients(dc); + break; + + default: + break; } } @@ -1047,6 +1383,9 @@ BEGIN_EVENT_TABLE(MyFrame, wxFrame) EVT_MENU (File_Quit, MyFrame::OnQuit) EVT_MENU (File_About, MyFrame::OnAbout) EVT_MENU (File_Clip, MyFrame::OnClip) +#if wxUSE_GRAPHICS_CONTEXT + EVT_MENU (File_GraphicContext, MyFrame::OnGraphicContext) +#endif EVT_MENU_RANGE(MenuShow_First, MenuShow_Last, MyFrame::OnShow) @@ -1068,11 +1407,20 @@ MyFrame::MyFrame(const wxString& title, const wxPoint& pos, const wxSize& size) menuFile->Append(File_ShowBrushes, _T("&Brushes screen\tF4")); menuFile->Append(File_ShowPolygons, _T("&Polygons screen\tF5")); menuFile->Append(File_ShowMask, _T("&Mask screen\tF6")); + menuFile->Append(File_ShowMaskStretch, _T("1/&2 scaled mask\tShift-F6")); menuFile->Append(File_ShowOps, _T("&ROP screen\tF7")); menuFile->Append(File_ShowRegions, _T("Re&gions screen\tF8")); menuFile->Append(File_ShowCircles, _T("&Circles screen\tF9")); +#if wxUSE_GRAPHICS_CONTEXT + menuFile->Append(File_ShowAlpha, _T("&Alpha screen\tF10")); +#endif + menuFile->Append(File_ShowSplines, _T("&Splines screen\tF11")); + menuFile->Append(File_ShowGradients, _T("&Gradients screen\tF12")); menuFile->AppendSeparator(); menuFile->AppendCheckItem(File_Clip, _T("&Clip\tCtrl-C"), _T("Clip/unclip drawing")); +#if wxUSE_GRAPHICS_CONTEXT + menuFile->AppendCheckItem(File_GraphicContext, _T("&Use GraphicContext\tCtrl-Y"), _T("Use GraphicContext")); +#endif menuFile->AppendSeparator(); menuFile->Append(File_About, _T("&About...\tCtrl-A"), _T("Show about dialog")); menuFile->AppendSeparator(); @@ -1173,6 +1521,13 @@ void MyFrame::OnClip(wxCommandEvent& event) m_canvas->Clip(event.IsChecked()); } +#if wxUSE_GRAPHICS_CONTEXT +void MyFrame::OnGraphicContext(wxCommandEvent& event) +{ + m_canvas->UseGraphicContext(event.IsChecked()); +} +#endif + void MyFrame::OnShow(wxCommandEvent& event) { m_canvas->ToShow((ScreenToShow)(event.GetId() - MenuShow_First)); @@ -1301,4 +1656,3 @@ wxColour MyFrame::SelectColour() return col; } #endif // wxUSE_COLOURDLG -