diff --git a/build/cmake/samples/CMakeLists.txt b/build/cmake/samples/CMakeLists.txt index b796023b2f..a28eee226f 100644 --- a/build/cmake/samples/CMakeLists.txt +++ b/build/cmake/samples/CMakeLists.txt @@ -70,7 +70,7 @@ endif() wx_add_sample(image image.cpp canvas.cpp canvas.h cursor_png.c RES image.rc DATA horse.png horse.jpg horse.bmp horse.gif horse.pcx horse.pnm horse_ag.pnm horse_rg.pnm horse.tif horse.tga horse.xpm horse.cur - horse.ico horse3.ani smile.xbm toucan.png cmyk.jpg cursor.png + horse.ico horse3.ani horse.svg smile.xbm toucan.png cmyk.jpg cursor.png NAME imagesample DEPENDS wxUSE_IMAGE) foreach(lang ar bg cs de fr it ka pl ru sv ja ja_JP.EUC-JP) list(APPEND INTERNAT_DATA_FILES ${lang}/internat.po ${lang}/internat.mo) diff --git a/build/cmake/tests/gui/CMakeLists.txt b/build/cmake/tests/gui/CMakeLists.txt index 7ff31daf37..a412248df5 100644 --- a/build/cmake/tests/gui/CMakeLists.txt +++ b/build/cmake/tests/gui/CMakeLists.txt @@ -141,6 +141,7 @@ set(TEST_GUI_DATA horse.pcx horse.png horse.pnm + horse.svg horse.tga horse.tif horse.xpm diff --git a/include/wx/bmpbndl.h b/include/wx/bmpbndl.h index 646c006b72..5f2b414c7b 100644 --- a/include/wx/bmpbndl.h +++ b/include/wx/bmpbndl.h @@ -82,6 +82,9 @@ public: // This overload currently makes a copy of the data. static wxBitmapBundle FromSVG(const char* data, const wxSize& sizeDef); + + // Load SVG image from the given file (must be a local file, not an URL). + static wxBitmapBundle FromSVGFile(const wxString& path, const wxSize& sizeDef); #endif // wxHAS_SVG // Create from the resources: all existing versions of the bitmap of the diff --git a/interface/wx/bmpbndl.h b/interface/wx/bmpbndl.h index 400b2471c5..a5f9e061c2 100644 --- a/interface/wx/bmpbndl.h +++ b/interface/wx/bmpbndl.h @@ -247,6 +247,20 @@ public: /// @overload static wxBitmapBundle FromSVG(const char* data, const wxSize& sizeDef); + /** + Create a bundle from the SVG image loaded from the given file. + + This function loads the SVG data from the given @a path and calls + FromSVG() with it. As it is just a wrapper for FromSVG(), please see + that function documentation for more information about SVG support. + + @param path Path to the SVG file. Notice that it should a local file, + not an URL. + @param sizeDef The default size to return from GetDefaultSize() for + this bundle. + */ + static wxBitmapBundle FromSVGFile(const wxString& path, const wxSize& sizeDef); + /** Check if bitmap bundle is non-empty. diff --git a/samples/image/Makefile.in b/samples/image/Makefile.in index 8a4593f697..50defa89ce 100644 --- a/samples/image/Makefile.in +++ b/samples/image/Makefile.in @@ -186,7 +186,7 @@ image$(EXEEXT): $(IMAGE_OBJECTS) $(__image___win32rc) data: @mkdir -p . - @for f in horse.png horse.jpg horse.bmp horse.gif horse.pcx horse.pnm horse_ag.pnm horse_rg.pnm horse.tif horse.tga horse.xpm horse.cur horse.ico horse3.ani smile.xbm toucan.png cmyk.jpg cursor.png; do \ + @for f in horse.png horse.jpg horse.bmp horse.gif horse.pcx horse.pnm horse_ag.pnm horse_rg.pnm horse.tif horse.tga horse.xpm horse.cur horse.ico horse3.ani horse.svg smile.xbm toucan.png cmyk.jpg cursor.png; do \ if test ! -f ./$$f -a ! -d ./$$f ; \ then x=yep ; \ else x=`find $(srcdir)/$$f -newer ./$$f -print` ; \ diff --git a/samples/image/horse.svg b/samples/image/horse.svg new file mode 100644 index 0000000000..2483101380 --- /dev/null +++ b/samples/image/horse.svg @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/samples/image/image.bkl b/samples/image/image.bkl index 4cfbd8ad36..84fe4f82b9 100644 --- a/samples/image/image.bkl +++ b/samples/image/image.bkl @@ -21,7 +21,7 @@ horse.png horse.jpg horse.bmp horse.gif horse.pcx horse.pnm horse_ag.pnm horse_rg.pnm - horse.tif horse.tga horse.xpm horse.cur horse.ico horse3.ani + horse.tif horse.tga horse.xpm horse.cur horse.ico horse3.ani horse.svg smile.xbm toucan.png cmyk.jpg cursor.png diff --git a/samples/image/image.cpp b/samples/image/image.cpp index ec3b894310..64dfb8aa0c 100644 --- a/samples/image/image.cpp +++ b/samples/image/image.cpp @@ -78,6 +78,9 @@ public: void OnAbout( wxCommandEvent &event ); void OnNewFrame( wxCommandEvent &event ); void OnNewFrameHiDPI(wxCommandEvent&); +#ifdef wxHAS_SVG + void OnNewSVGFrame(wxCommandEvent&); +#endif // wxHAS_SVG void OnImageInfo( wxCommandEvent &event ); void OnThumbnail( wxCommandEvent &event ); void OnFilters(wxCommandEvent& event); @@ -967,6 +970,7 @@ enum ID_ABOUT = wxID_ABOUT, ID_NEW = 100, ID_NEW_HIDPI, + ID_NEW_SVG, ID_INFO, ID_SHOWRAW, ID_GRAPHICS, @@ -982,6 +986,9 @@ wxBEGIN_EVENT_TABLE(MyFrame, wxFrame) EVT_MENU (ID_QUIT, MyFrame::OnQuit) EVT_MENU (ID_NEW, MyFrame::OnNewFrame) EVT_MENU (ID_NEW_HIDPI, MyFrame::OnNewFrameHiDPI) +#ifdef wxHAS_SVG + EVT_MENU (ID_NEW_SVG, MyFrame::OnNewSVGFrame) +#endif // wxHAS_SVG EVT_MENU (ID_INFO, MyFrame::OnImageInfo) EVT_MENU (ID_SHOWTHUMBNAIL, MyFrame::OnThumbnail) EVT_MENU (ID_FILTERS, MyFrame::OnFilters) @@ -1011,6 +1018,9 @@ MyFrame::MyFrame() wxMenu *menuImage = new wxMenu; menuImage->Append( ID_NEW, "&Show any image...\tCtrl-O"); menuImage->Append(ID_NEW_HIDPI, "Show any image as &HiDPI...\tCtrl-H"); +#ifdef wxHAS_SVG + menuImage->Append( ID_NEW_SVG, "Show &SVG image...\tCtrl-S"); +#endif // wxHAS_SVG menuImage->Append( ID_INFO, "Show image &information...\tCtrl-I"); #ifdef wxHAVE_RAW_BITMAP menuImage->AppendSeparator(); @@ -1131,6 +1141,76 @@ void MyFrame::OnNewFrameHiDPI(wxCommandEvent&) new MyImageFrame(this, filename, image, GetContentScaleFactor()); } +#ifdef wxHAS_SVG + +class MySVGFrame : public wxFrame +{ +public: + explicit MySVGFrame(wxFrame* parent, + const wxString& filename, + const wxBitmapBundle& bundle) + : wxFrame(parent, wxID_ANY, wxString::Format("SVG image %s", filename), + wxDefaultPosition, wxDefaultSize, + wxDEFAULT_FRAME_STYLE | wxFULL_REPAINT_ON_RESIZE), + m_bundle(bundle) + { + Bind(wxEVT_PAINT, &MySVGFrame::OnPaint, this); + + SetClientSize(bundle.GetDefaultSize()); + + Show(); + } + +private: + void OnPaint(wxPaintEvent&) + { + wxPaintDC dc(this); + + // Check if the bitmap needs to be re-rendered at the new size. Note + // that the bitmap size is in physical pixels, which can be different + // from the logical pixels in which the window size is expressed. + const wxSize sizeWin = GetClientSize(); + const wxSize sizeBmp = sizeWin*GetContentScaleFactor(); + if ( !m_bitmap.IsOk() || m_bitmap.GetSize() != sizeBmp ) + { + m_bitmap = m_bundle.GetBitmap(sizeBmp); + } + + // Use wxGraphicsContext if available for alpha support. +#if wxUSE_GRAPHICS_CONTEXT + wxScopedPtr const + gc(wxGraphicsRenderer::GetDefaultRenderer()->CreateContext(dc)); + + gc->DrawBitmap(m_bitmap, 0, 0, sizeWin.x, sizeWin.y); +#else + dc.DrawBitmap(m_bitmap, wxPoint(0, 0), true); +#endif + } + + const wxBitmapBundle m_bundle; + wxBitmap m_bitmap; + + wxDECLARE_NO_COPY_CLASS(MySVGFrame); +}; + +void MyFrame::OnNewSVGFrame(wxCommandEvent&) +{ + const wxString + filename = wxLoadFileSelector("SVG document", ".svg", "image", this); + if ( filename.empty() ) + return; + + // The default size here is completely arbitrary, as we don't know anything + // about the SVG being loaded. + wxBitmapBundle bb = wxBitmapBundle::FromSVGFile(filename, wxSize(200, 200)); + if ( !bb.IsOk() ) + return; + + new MySVGFrame(this, filename, bb); +} + +#endif // wxHAS_SVG + void MyFrame::OnUpdateNewFrameHiDPI(wxUpdateUIEvent& event) { event.Enable(GetContentScaleFactor() > 1); diff --git a/samples/image/makefile.gcc b/samples/image/makefile.gcc index 072b0e5a18..eff4b36106 100644 --- a/samples/image/makefile.gcc +++ b/samples/image/makefile.gcc @@ -223,7 +223,7 @@ $(OBJS)\image.exe: $(IMAGE_OBJECTS) $(OBJS)\image_image_rc.o data: if not exist $(OBJS) mkdir $(OBJS) - for %%f in (horse.png horse.jpg horse.bmp horse.gif horse.pcx horse.pnm horse_ag.pnm horse_rg.pnm horse.tif horse.tga horse.xpm horse.cur horse.ico horse3.ani smile.xbm toucan.png cmyk.jpg cursor.png) do if not exist $(OBJS)\%%f copy .\%%f $(OBJS) + for %%f in (horse.png horse.jpg horse.bmp horse.gif horse.pcx horse.pnm horse_ag.pnm horse_rg.pnm horse.tif horse.tga horse.xpm horse.cur horse.ico horse3.ani horse.svg smile.xbm toucan.png cmyk.jpg cursor.png) do if not exist $(OBJS)\%%f copy .\%%f $(OBJS) $(OBJS)\image_image.o: ./image.cpp $(CXX) -c -o $@ $(IMAGE_CXXFLAGS) $(CPPDEPS) $< diff --git a/samples/image/makefile.vc b/samples/image/makefile.vc index ebea4d430a..ed81f0e56f 100644 --- a/samples/image/makefile.vc +++ b/samples/image/makefile.vc @@ -568,7 +568,7 @@ $(OBJS)\image.exe: $(IMAGE_OBJECTS) $(OBJS)\image_image.res data: if not exist $(OBJS) mkdir $(OBJS) - for %f in (horse.png horse.jpg horse.bmp horse.gif horse.pcx horse.pnm horse_ag.pnm horse_rg.pnm horse.tif horse.tga horse.xpm horse.cur horse.ico horse3.ani smile.xbm toucan.png cmyk.jpg cursor.png) do if not exist $(OBJS)\%f copy .\%f $(OBJS) + for %f in (horse.png horse.jpg horse.bmp horse.gif horse.pcx horse.pnm horse_ag.pnm horse_rg.pnm horse.tif horse.tga horse.xpm horse.cur horse.ico horse3.ani horse.svg smile.xbm toucan.png cmyk.jpg cursor.png) do if not exist $(OBJS)\%f copy .\%f $(OBJS) $(OBJS)\image_image.obj: .\image.cpp $(CXX) /c /nologo /TP /Fo$@ $(IMAGE_CXXFLAGS) .\image.cpp diff --git a/src/generic/bmpsvg.cpp b/src/generic/bmpsvg.cpp index 1c34e5215b..8517508896 100644 --- a/src/generic/bmpsvg.cpp +++ b/src/generic/bmpsvg.cpp @@ -42,6 +42,13 @@ #include "wx/utils.h" // Only for wxMin() #endif // WX_PRECOMP +#ifdef wxUSE_FFILE + #include "wx/ffile.h" +#elif wxUSE_FILE + #include "wx/file.h" +#else + #define wxNO_SVG_FILE +#endif #include "wx/rawbmp.h" #include "wx/private/bmpbndl.h" @@ -203,4 +210,34 @@ wxBitmapBundle wxBitmapBundle::FromSVG(const char* data, const wxSize& sizeDef) return FromSVG(copy.data(), sizeDef); } +/* static */ +wxBitmapBundle wxBitmapBundle::FromSVGFile(const wxString& path, const wxSize& sizeDef) +{ + // There is nsvgParseFromFile(), but it doesn't work with Unicode filenames + // under MSW and does exactly the same thing that we do here in any case, + // so it seems better to use our code. +#ifndef wxNO_SVG_FILE +#if wxUSE_FFILE + wxFFile file(path, "rb"); +#elif wxUSE_FILE + wxFile file(path); +#endif + if ( file.IsOpened() ) + { + const wxFileOffset lenAsOfs = file.Length(); + if ( lenAsOfs != wxInvalidOffset ) + { + const size_t len = static_cast(lenAsOfs); + + wxCharBuffer buf(len); + char* const ptr = buf.data(); + if ( file.Read(ptr, len) == len ) + return wxBitmapBundle::FromSVG(ptr, sizeDef); + } + } +#endif // !wxNO_SVG_FILE + + return wxBitmapBundle(); +} + #endif // wxHAS_SVG diff --git a/tests/Makefile.in b/tests/Makefile.in index 747e4c5f18..21e8258c99 100644 --- a/tests/Makefile.in +++ b/tests/Makefile.in @@ -448,7 +448,7 @@ COND_wxUSE_REGEX_builtin___LIB_REGEX_p = \ ### Targets: ### -all: test$(EXEEXT) $(__test_drawing___depname) $(__test_drawingplugin___depname) $(__test_gui___depname) $(__test_gui_bundle___depname) $(__test_allheaders___depname) $(__test_allheaders_bundle___depname) data data-images fr ja +all: test$(EXEEXT) $(__test_drawing___depname) $(__test_drawingplugin___depname) $(__test_gui___depname) $(__test_gui_bundle___depname) $(__test_allheaders___depname) $(__test_allheaders_bundle___depname) data data-image-sample data-images fr ja install: @@ -552,6 +552,18 @@ test$(EXEEXT): $(TEST_OBJECTS) @COND_USE_PCH_1@ $(BK_MAKE_PCH) ./.pch/testprec_test_allheaders/testprec.h.gch testprec.h $(CXX) $(TEST_ALLHEADERS_CXXFLAGS) data: + @mkdir -p . + @for f in testdata.fc horse.svg; do \ + if test ! -f ./$$f -a ! -d ./$$f ; \ + then x=yep ; \ + else x=`find $(srcdir)/$$f -newer ./$$f -print` ; \ + fi; \ + case "$$x" in ?*) \ + cp -pRf $(srcdir)/$$f . ;; \ + esac; \ + done + +data-image-sample: @mkdir -p . @for f in horse.ani horse.bmp horse.cur horse.gif horse.ico horse.jpg horse.pcx horse.png horse.pnm horse.tga horse.tif horse.xpm; do \ if test ! -f ./$$f -a ! -d ./$$f ; \ @@ -1248,4 +1260,4 @@ failtest_allheaders: @IF_GNU_MAKE@-include ./.deps/*.d .PHONY: all install uninstall clean distclean test_gui_bundle \ - test_allheaders_bundle data data-images fr ja + test_allheaders_bundle data data-image-sample data-images fr ja diff --git a/tests/graphics/bmpbundle.cpp b/tests/graphics/bmpbundle.cpp index 0f0abfe913..cebbc0c110 100644 --- a/tests/graphics/bmpbundle.cpp +++ b/tests/graphics/bmpbundle.cpp @@ -136,4 +136,11 @@ TEST_CASE("BitmapBundle::FromSVG", "[bmpbundle][svg]") CHECK( b.GetBitmap(wxSize(16, 16)).GetSize() == wxSize(16, 16) ); } +TEST_CASE("BitmapBundle::FromSVGFile", "[bmpbundle][svg][file]") +{ + wxBitmapBundle b = wxBitmapBundle::FromSVGFile("horse.svg", wxSize(20, 20)); + REQUIRE( b.IsOk() ); + CHECK( b.GetDefaultSize() == wxSize(20, 20) ); +} + #endif // wxHAS_SVG diff --git a/tests/horse.svg b/tests/horse.svg new file mode 100644 index 0000000000..2483101380 --- /dev/null +++ b/tests/horse.svg @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/tests/makefile.gcc b/tests/makefile.gcc index e2ba26d653..0cdc08d7aa 100644 --- a/tests/makefile.gcc +++ b/tests/makefile.gcc @@ -501,7 +501,7 @@ $(OBJS): ### Targets: ### -all: $(OBJS)\test.exe $(__test_drawing___depname) $(__test_drawingplugin___depname) $(__test_gui___depname) $(__test_allheaders___depname) data data-images fr ja +all: $(OBJS)\test.exe $(__test_drawing___depname) $(__test_drawingplugin___depname) $(__test_gui___depname) $(__test_allheaders___depname) data data-image-sample data-images fr ja clean: -if exist $(OBJS)\*.o del $(OBJS)\*.o @@ -550,6 +550,10 @@ $(OBJS)\test_allheaders.exe: $(TEST_ALLHEADERS_OBJECTS) $(OBJS)\test_allheaders_ endif data: + if not exist $(OBJS) mkdir $(OBJS) + for %%f in (testdata.fc horse.svg) do if not exist $(OBJS)\%%f copy .\%%f $(OBJS) + +data-image-sample: if not exist $(OBJS) mkdir $(OBJS) for %%f in (horse.ani horse.bmp horse.cur horse.gif horse.ico horse.jpg horse.pcx horse.png horse.pnm horse.tga horse.tif horse.xpm) do if not exist $(OBJS)\%%f copy .\%%f $(OBJS) @@ -1183,7 +1187,7 @@ $(OBJS)\test_allheaders_allheaders.o: ./allheaders.cpp $(OBJS)\test_allheaders_testableframe.o: ./testableframe.cpp $(CXX) -c -o $@ $(TEST_ALLHEADERS_CXXFLAGS) $(CPPDEPS) $< -.PHONY: all clean data data-images fr ja +.PHONY: all clean data data-image-sample data-images fr ja SHELL := $(COMSPEC) diff --git a/tests/makefile.vc b/tests/makefile.vc index eeab8e73dd..4aa2cbf510 100644 --- a/tests/makefile.vc +++ b/tests/makefile.vc @@ -928,7 +928,7 @@ $(OBJS): ### Targets: ### -all: $(OBJS)\test.exe $(__test_drawing___depname) $(__test_drawingplugin___depname) $(__test_gui___depname) $(__test_allheaders___depname) data data-images fr ja +all: $(OBJS)\test.exe $(__test_drawing___depname) $(__test_drawingplugin___depname) $(__test_gui___depname) $(__test_allheaders___depname) data data-image-sample data-images fr ja clean: -if exist $(OBJS)\*.obj del $(OBJS)\*.obj @@ -984,6 +984,10 @@ $(OBJS)\test_allheaders.exe: $(OBJS)\test_allheaders_dummy.obj $(TEST_ALLHEADER !endif data: + if not exist $(OBJS) mkdir $(OBJS) + for %f in (testdata.fc horse.svg) do if not exist $(OBJS)\%f copy .\%f $(OBJS) + +data-image-sample: if not exist $(OBJS) mkdir $(OBJS) for %f in (horse.ani horse.bmp horse.cur horse.gif horse.ico horse.jpg horse.pcx horse.png horse.pnm horse.tga horse.tif horse.xpm) do if not exist $(OBJS)\%f copy .\%f $(OBJS) diff --git a/tests/test.bkl b/tests/test.bkl index 89ef76cb0d..e45d45a5df 100644 --- a/tests/test.bkl +++ b/tests/test.bkl @@ -338,8 +338,10 @@ - testdata.fc + testdata.fc horse.svg + + horse.ani horse.bmp horse.cur horse.gif horse.ico horse.jpg horse.pcx horse.png horse.pnm horse.tga horse.tif horse.xpm