From 13acf6420faa3eb816492f6e508a31d6b65fbcc1 Mon Sep 17 00:00:00 2001 From: Robert Osfield Date: Sun, 11 May 2008 14:23:19 +0000 Subject: [PATCH] From Miguel Escriva, Here you will find a SVG Image Reader. It renders a SVG file as an osg::Image using cairo and rsvg. --- CMakeLists.txt | 3 + src/osgPlugins/CMakeLists.txt | 4 +- src/osgPlugins/svg/CMakeLists.txt | 11 +++ src/osgPlugins/svg/ReaderWriterSVG.cpp | 121 +++++++++++++++++++++++++ 4 files changed, 138 insertions(+), 1 deletion(-) create mode 100644 src/osgPlugins/svg/CMakeLists.txt create mode 100644 src/osgPlugins/svg/ReaderWriterSVG.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 3cbae38ce..0f103de38 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -221,6 +221,9 @@ ELSE(WIN32) PKG_CHECK_MODULES(GTKGL gtkglext-x11-1.0) ENDIF(WIN32) +PKG_CHECK_MODULES(RSVG librsvg-2.0) +PKG_CHECK_MODULES(CAIRO cairo) + SET(wxWidgets_USE_LIBS base core gl net) FIND_PACKAGE(wxWidgets) diff --git a/src/osgPlugins/CMakeLists.txt b/src/osgPlugins/CMakeLists.txt index c21ebfc43..20c090c2b 100644 --- a/src/osgPlugins/CMakeLists.txt +++ b/src/osgPlugins/CMakeLists.txt @@ -161,7 +161,9 @@ IF(ZLIB_FOUND) ADD_SUBDIRECTORY(zip) ENDIF(ZLIB_FOUND) - +IF(RSVG_FOUND) + ADD_SUBDIRECTORY(svg) +ENDIF(RSVG_FOUND) ##########to get all the variables of Cmake diff --git a/src/osgPlugins/svg/CMakeLists.txt b/src/osgPlugins/svg/CMakeLists.txt new file mode 100644 index 000000000..59f3858a6 --- /dev/null +++ b/src/osgPlugins/svg/CMakeLists.txt @@ -0,0 +1,11 @@ +#this file is automatically generated + + +INCLUDE_DIRECTORIES( ${RSVG_INCLUDE_DIRS} ${CAIRO_INCLUDE_DIRS}) +LINK_DIRECTORIES(${RSVG_LIBRARY_DIRS} ${CAIRO_LIBRARY_DIRS}) +LINK_LIBRARIES(${RSVG_LIBRARIES} ${CAIRO_LIBRARIES}) + + +SET(TARGET_SRC ReaderWriterSVG.cpp ) +#### end var setup ### +SETUP_PLUGIN(svg) diff --git a/src/osgPlugins/svg/ReaderWriterSVG.cpp b/src/osgPlugins/svg/ReaderWriterSVG.cpp new file mode 100644 index 000000000..5540ac954 --- /dev/null +++ b/src/osgPlugins/svg/ReaderWriterSVG.cpp @@ -0,0 +1,121 @@ +/* -*-c++-*- Copyright (C) 2008 Miguel Escriva Gregori + * + * This library is open source and may be redistributed and/or modified under + * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or + * (at your option) any later version. The full license is in LICENSE file + * included with this distribution, and on the openscenegraph.org website. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * OpenSceneGraph Public License for more details. +*/ + +#include +#include +#include +#include + +#include +#include +#include +#include + +extern "C" { + #include + #include +} + +class ReaderWriterSVG : public osgDB::ReaderWriter +{ + public: + ReaderWriterSVG() + { + rsvg_init(); + } + + virtual const char* className() const { return "SVG Image Reader"; } + virtual bool acceptsExtension(const std::string& extension) const + { + return osgDB::equalCaseInsensitive(extension,"svg"); + } + + virtual ReadResult readObject(const std::string& file, const osgDB::ReaderWriter::Options* options) const + { + return readImage(file, options); + } + + virtual ReadResult readImage(const std::string& file, const osgDB::ReaderWriter::Options* options) const + { + std::string ext = osgDB::getLowerCaseFileExtension(file); + if (!acceptsExtension(ext)) return ReadResult::FILE_NOT_HANDLED; + + std::string fileName = osgDB::findDataFile( file, options ); + if (fileName.empty()) return ReadResult::FILE_NOT_FOUND; + + RsvgDimensionData dimensionData; + RsvgHandle* handle = rsvg_handle_new_from_file (file.c_str(), NULL); + rsvg_handle_get_dimensions( handle, &dimensionData); + + osg::Image *image; + if (options) + { + unsigned int w=0, h=0; + std::string op = options->getOptionString(); + size_t i = op.find("x"); + + std::stringstream ss1(op.substr(0, i)); + std::stringstream ss2(op.substr(i+1, op.size())); + ss1 >> w; + ss1 >> h; + if (w==0 || h==0){ + image = createImage(handle, dimensionData.width, dimensionData.height); + } + else{ + image = createImage(handle, w, h); + } + } + else{ + image = createImage(handle, dimensionData.width, dimensionData.height); + } + rsvg_handle_free(handle); + image->setFileName(file); + return image; + } + + osg::Image* createImage(RsvgHandle *handle, unsigned int width, unsigned int height) const + { + RsvgDimensionData dimensionData; + rsvg_handle_get_dimensions( handle, &dimensionData); + // If image resollution < 128, cairo produces some artifacts. + // I don't know why, but we check the size... + if (width < 128) width = 128; + if (height < 128) height = 128; + width = osg::Image::computeNearestPowerOfTwo(width); + height = osg::Image::computeNearestPowerOfTwo(height); + osg::Image *image = new osg::Image(); + image->allocateImage(width, height, 1, GL_RGBA, GL_UNSIGNED_BYTE); + image->setPixelFormat(GL_BGRA); + + cairo_surface_t *cairo_surface = cairo_image_surface_create_for_data(image->data(), + CAIRO_FORMAT_ARGB32, width, height, image->getRowSizeInBytes()); + cairo_t *cr = cairo_create(cairo_surface); + cairo_scale(cr,((float)width)/dimensionData.width, ((float)height)/dimensionData.height); + rsvg_handle_render_cairo(handle, cr); + + cairo_destroy(cr); + free(cairo_surface); + + image->flipVertical(); + return image; + } + protected: + virtual ~ReaderWriterSVG() + { + rsvg_term(); + } +}; + +// now register with Registry to instantiate the above +// reader/writer. +REGISTER_OSGPLUGIN(SVG, ReaderWriterSVG)