From 6f356aeb97c39dfd2ace909ab9313fdcd4dcbdc0 Mon Sep 17 00:00:00 2001 From: Robert Osfield Date: Sun, 7 Dec 2008 17:02:30 +0000 Subject: [PATCH] Intoduce new osgWidget::PdfReader and osgWidget::VncClient front ends to osgWidget, with new pdf plugin and updated vnc plugin that now support these front ends. Updated osgpdf and osgvnc examples to new these new interfaces. --- examples/CMakeLists.txt | 4 +- examples/osgpdf/CMakeLists.txt | 6 +- examples/osgpdf/osgpdf.cpp | 305 +--------------------- examples/osgvnc/osgvnc.cpp | 88 ++----- examples/osgwidgetscrolled/CMakeLists.txt | 5 +- include/osg/Image | 8 +- include/osgViewer/ViewerEventHandlers | 6 +- include/osgWidget/PdfReader | 116 ++++++++ include/osgWidget/VncClient | 63 +++++ src/osgPlugins/CMakeLists.txt | 3 + src/osgPlugins/gecko/UBrowser.cpp | 18 +- src/osgPlugins/gecko/UBrowser.h | 8 +- src/osgPlugins/pdf/CMakeLists.txt | 10 + src/osgPlugins/pdf/ReaderWriterPDF.cpp | 292 +++++++++++++++++++++ src/osgPlugins/vnc/CMakeLists.txt | 2 +- src/osgPlugins/vnc/ReaderWriterVNC.cpp | 119 +++------ src/osgViewer/ViewerEventHandlers.cpp | 7 +- src/osgWidget/CMakeLists.txt | 4 + src/osgWidget/PdfReader.cpp | 100 +++++++ src/osgWidget/VncClient.cpp | 64 +++++ 20 files changed, 752 insertions(+), 476 deletions(-) create mode 100644 include/osgWidget/PdfReader create mode 100644 include/osgWidget/VncClient create mode 100644 src/osgPlugins/pdf/CMakeLists.txt create mode 100644 src/osgPlugins/pdf/ReaderWriterPDF.cpp create mode 100644 src/osgWidget/PdfReader.cpp create mode 100644 src/osgWidget/VncClient.cpp diff --git a/examples/CMakeLists.txt b/examples/CMakeLists.txt index 95fb62da7..220f20290 100644 --- a/examples/CMakeLists.txt +++ b/examples/CMakeLists.txt @@ -133,9 +133,7 @@ IF(DYNAMIC_OPENSCENEGRAPH) ADD_SUBDIRECTORY(osgwidgettable) ADD_SUBDIRECTORY(osgwidgetwindow) - IF (POPPLER_FOUND AND CAIRO_FOUND) - ADD_SUBDIRECTORY(osgpdf) - ENDIF(POPPLER_FOUND AND CAIRO_FOUND) + ADD_SUBDIRECTORY(osgpdf) IF (BUILD_OSG_WRAPPERS) ADD_SUBDIRECTORY(osgintrospection) diff --git a/examples/osgpdf/CMakeLists.txt b/examples/osgpdf/CMakeLists.txt index 69379374a..0b2606cde 100644 --- a/examples/osgpdf/CMakeLists.txt +++ b/examples/osgpdf/CMakeLists.txt @@ -1,10 +1,6 @@ SET(TARGET_SRC osgpdf.cpp) -INCLUDE_DIRECTORIES( ${CAIRO_INCLUDE_DIRS} ${POPPLER_INCLUDE_DIRS} ) -LINK_DIRECTORIES(${CAIRO_LIBRARY_DIRS} ${POPPLER_LIB_DIRS}) - -#SET(TARGET_EXTERNAL_LIBRARIES ${CAIRO_LIBRARIES} poppler poppler-glib) -SET(TARGET_EXTERNAL_LIBRARIES ${CAIRO_LIBRARIES} ${POPPLER_LIBRARIES}) +SET(TARGET_ADDED_LIBRARIES osgWidget ) #### end var setup ### SETUP_EXAMPLE(osgpdf) diff --git a/examples/osgpdf/osgpdf.cpp b/examples/osgpdf/osgpdf.cpp index 240138819..6b33b2f67 100644 --- a/examples/osgpdf/osgpdf.cpp +++ b/examples/osgpdf/osgpdf.cpp @@ -10,314 +10,37 @@ #include #include -#include -#include - -class CarioImage : public osg::Image -{ - public: - - CarioImage(): - _surface(0), - _context(0) {} - - - void create(unsigned int width, unsigned int height) - { - if (data() && width==s() && height==t()) return; - - osg::notify(osg::NOTICE)<<"Create cario surface/context "<=getNumOfPages()) return false; - - PopplerPage* page = poppler_document_get_page(_doc, pageNum); - - if(!page) return false; - - _pageNum = pageNum; - - double w = 0.0f; - double h = 0.0f; - - poppler_page_get_size(page, &w, &h); - - create((unsigned int)(w*2.0),(unsigned int)(h*2.0)); - - double r = 1.0; - double g = 1.0; - double b = 1.0; - double a = 1.0; - - cairo_save(_context); - - cairo_set_source_rgba(_context, r, g, b, a); - cairo_rectangle(_context, 0.0, 0.0, double(s()), double(t())); - cairo_fill(_context); - - cairo_scale(_context, double(s())/w, double(t())/h); - - poppler_page_render(page, getContext()); - - - cairo_restore(_context); - - dirty(); - - } - - -}; - - -osg::Node* createInteractiveQuad(const osg::Vec3& origin, osg::Vec3& widthAxis, osg::Vec3& heightAxis, - osg::Image* image) -{ - bool flip = image->getOrigin()==osg::Image::TOP_LEFT; - - osg::Geometry* pictureQuad = osg::createTexturedQuadGeometry(origin, widthAxis, heightAxis, - 0.0f, flip ? 1.0f : 0.0f , 1.0f, flip ? 0.0f : 1.0f); - - osg::Texture2D* texture = new osg::Texture2D(image); - texture->setResizeNonPowerOfTwoHint(false); - texture->setFilter(osg::Texture::MIN_FILTER,osg::Texture::LINEAR); - texture->setWrap(osg::Texture::WRAP_S, osg::Texture::CLAMP_TO_EDGE); - texture->setWrap(osg::Texture::WRAP_T, osg::Texture::CLAMP_TO_EDGE); - - pictureQuad->getOrCreateStateSet()->setTextureAttributeAndModes(0, - texture, - osg::StateAttribute::ON); - - pictureQuad->setEventCallback(new osgViewer::InteractiveImageHandler(image)); - - osg::Geode* geode = new osg::Geode; - geode->addDrawable(pictureQuad); - - return geode; -} - -class PageHandler : public osgGA::GUIEventHandler -{ - public: - - PageHandler() {} - - bool handle(const osgGA::GUIEventAdapter& ea,osgGA::GUIActionAdapter& aa) - { - if (ea.getHandled()) return false; - - switch(ea.getEventType()) - { - case(osgGA::GUIEventAdapter::KEYDOWN): - { - if (ea.getKey()=='n') - { - osg::notify(osg::NOTICE)<<"Next page"< int main(int argc,char** argv) { - osg::ArgumentParser arguments(&argc, argv); osgViewer::Viewer viewer(arguments); - - typedef std::list< osg::ref_ptr > Images; - Images images; + + osgWidget::GeometryHints hints(osg::Vec3(1.0f,0.0f,0.0f), + osg::Vec3(1.0f,0.0f,0.0f), + osg::Vec3(0.0f,0.0f,1.0f), + osgWidget::GeometryHints::RESIZE_HEIGHT_TO_MAINTAINCE_ASPECT_RATIO); + + osg::ref_ptr group = new osg::Group; for(int i=1; i pdfImage= new PdfImage; - if (pdfImage->open(arguments[i])) + osg::ref_ptr pdfReader = new osgWidget::PdfReader; + if (pdfReader->open(arguments[i], hints)) { - images.push_back(pdfImage.get()); + group->addChild(pdfReader.get()); + + hints.position.x() += 1.1f; } } } - bool xyPlane = false; - - osg::Group* group = new osg::Group; - - osg::Vec3 origin = osg::Vec3(0.0f,0.0f,0.0f); - for(Images::iterator itr = images.begin(); - itr != images.end(); - ++itr) - { - osg::Image* image = itr->get(); - float width = 1.0; - float height = float(image->t())/float(image->s()); - osg::Vec3 widthAxis = osg::Vec3(width,0.0f,0.0f); - osg::Vec3 heightAxis = xyPlane ? osg::Vec3(0.0f,height,0.0f) : osg::Vec3(0.0f,0.0f,height); - group->addChild(createInteractiveQuad(origin, widthAxis, heightAxis, image)); - - origin += widthAxis*1.1f; - } - - viewer.setSceneData(group); + viewer.setSceneData(group.get()); viewer.addEventHandler(new osgViewer::StatsHandler); - - //viewer.addEventHandler(new PageHandler); return viewer.run(); } diff --git a/examples/osgvnc/osgvnc.cpp b/examples/osgvnc/osgvnc.cpp index 15a3c7bcb..4f963aadb 100644 --- a/examples/osgvnc/osgvnc.cpp +++ b/examples/osgvnc/osgvnc.cpp @@ -12,38 +12,6 @@ #include - -osg::Node* createInteractiveQuad(const osg::Vec3& origin, osg::Vec3& widthAxis, osg::Vec3& heightAxis, - osg::Image* image) -{ - bool flip = image->getOrigin()==osg::Image::TOP_LEFT; - - osg::Geometry* pictureQuad = osg::createTexturedQuadGeometry(origin, widthAxis, heightAxis, - 0.0f, flip ? 1.0f : 0.0f , 1.0f, flip ? 0.0f : 1.0f); - - osg::Texture2D* texture = new osg::Texture2D(image); - texture->setResizeNonPowerOfTwoHint(false); - texture->setFilter(osg::Texture::MIN_FILTER,osg::Texture::LINEAR); - texture->setWrap(osg::Texture::WRAP_S, osg::Texture::CLAMP_TO_EDGE); - texture->setWrap(osg::Texture::WRAP_T, osg::Texture::CLAMP_TO_EDGE); - - pictureQuad->getOrCreateStateSet()->setTextureAttributeAndModes(0, - texture, - osg::StateAttribute::ON); - - - - osg::ref_ptr callback = new osgViewer::InteractiveImageHandler(image); - - pictureQuad->setEventCallback(callback.get()); - pictureQuad->setCullCallback(callback.get()); - - osg::Geode* geode = new osg::Geode; - geode->addDrawable(pictureQuad); - - return geode; -} - class EscapeHandler : public osgGA::GUIEventHandler { public: @@ -76,48 +44,34 @@ class EscapeHandler : public osgGA::GUIEventHandler int main(int argc,char** argv) { - osg::ArgumentParser arguments(&argc, argv); - osgViewer::Viewer viewer; - - typedef std::list< osg::ref_ptr > Images; - Images images; + osgViewer::Viewer viewer(arguments); - std::string hostname; - while (arguments.read("--host",hostname)) + osgWidget::GeometryHints hints(osg::Vec3(1.0f,0.0f,0.0f), + osg::Vec3(1.0f,0.0f,0.0f), + osg::Vec3(0.0f,0.0f,1.0f), + osgWidget::GeometryHints::RESIZE_HEIGHT_TO_MAINTAINCE_ASPECT_RATIO); + + osg::ref_ptr group = new osg::Group; + + for(int i=1; i image = osgDB::readImageFile(hostname+std::string(".vnc")); - if (image.valid()) images.push_back(image.get()); - } - - if (images.empty()) - { - return 1; + if (!arguments.isOption(i)) + { + osg::ref_ptr vncClient = new osgWidget::VncClient; + if (vncClient->connect(arguments[i], hints)) + { + group->addChild(vncClient.get()); + + hints.position.x() += 1.1f; + } + } } - bool xyPlane = false; - - osg::Group* group = new osg::Group; - - osg::Vec3 origin = osg::Vec3(0.0f,0.0f,0.0f); - for(Images::iterator itr = images.begin(); - itr != images.end(); - ++itr) - { - osg::Image* image = itr->get(); - float width = 1.0; - float height = float(image->t())/float(image->s()); - osg::Vec3 widthAxis = osg::Vec3(width,0.0f,0.0f); - osg::Vec3 heightAxis = xyPlane ? osg::Vec3(0.0f,height,0.0f) : osg::Vec3(0.0f,0.0f,height); - group->addChild(createInteractiveQuad(origin, widthAxis, heightAxis, image)); - - origin += widthAxis*1.1f; - } - - viewer.setSceneData(group); + viewer.setSceneData(group.get()); viewer.addEventHandler(new osgViewer::StatsHandler); - + // add a custom escape handler, but disable the standard viewer one to enable the vnc images to handle // the escape without it getting caught by the viewer. viewer.addEventHandler(new EscapeHandler); diff --git a/examples/osgwidgetscrolled/CMakeLists.txt b/examples/osgwidgetscrolled/CMakeLists.txt index bbafc94e1..0d5e65022 100644 --- a/examples/osgwidgetscrolled/CMakeLists.txt +++ b/examples/osgwidgetscrolled/CMakeLists.txt @@ -1,7 +1,6 @@ -#this file is automatically generated - - SET(TARGET_SRC osgwidgetscrolled.cpp ) + SET(TARGET_ADDED_LIBRARIES osgWidget ) + #### end var setup ### SETUP_EXAMPLE(osgwidgetscrolled) diff --git a/include/osg/Image b/include/osg/Image index 6a143e062..e665372b6 100644 --- a/include/osg/Image +++ b/include/osg/Image @@ -324,11 +324,11 @@ class OSG_EXPORT Image : public Object virtual void update(NodeVisitor* nv) {} - /** method for sending pointer events to images that are acting as front ends to interactive surfaces such as a vnc or browser window.*/ - virtual void sendPointerEvent(int x, int y, int buttonMask) {} + /** method for sending pointer events to images that are acting as front ends to interactive surfaces such as a vnc or browser window. Return true if handled. */ + virtual bool sendPointerEvent(int x, int y, int buttonMask) { return false; } - /** method for sending key events to images that are acting as front ends to interactive surfaces such as a vnc or browser window.*/ - virtual void sendKeyEvent(int key, bool keyDown) {} + /** method for sending key events to images that are acting as front ends to interactive surfaces such as a vnc or browser window. Return true if handled.*/ + virtual bool sendKeyEvent(int key, bool keyDown) { return false; } /** method for passing frame information to the custom Image classes, to be called only when objects associated with imagery are not culled.*/ virtual void setFrameLastRendered(const osg::FrameStamp* frameStamp) {} diff --git a/include/osgViewer/ViewerEventHandlers b/include/osgViewer/ViewerEventHandlers index 3e42dc4a1..d6fd43896 100644 --- a/include/osgViewer/ViewerEventHandlers +++ b/include/osgViewer/ViewerEventHandlers @@ -373,7 +373,7 @@ public: _image(image) {} META_Object(osgViewer, InteractiveImageHandler); - + virtual bool handle(const osgGA::GUIEventAdapter& ea,osgGA::GUIActionAdapter& aa, osg::Object*, osg::NodeVisitor* nv); virtual bool cull(osg::NodeVisitor* nv, osg::Drawable* drawable, osg::RenderInfo* renderInfo) const; @@ -389,6 +389,10 @@ protected: bool mousePosition(osgViewer::View* view, osg::NodeVisitor* nv, const osgGA::GUIEventAdapter& ea, int& x, int &y) const; osg::observer_ptr _image; + bool _handleKeyboardEvents; + bool _handledOnKeyboardEvents; + bool _handleMouseEvents; + bool _handledOnMouseEvents; }; diff --git a/include/osgWidget/PdfReader b/include/osgWidget/PdfReader new file mode 100644 index 000000000..2a2dfcc42 --- /dev/null +++ b/include/osgWidget/PdfReader @@ -0,0 +1,116 @@ +/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2008 Robert Osfield + * + * 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. +*/ + +#ifndef OSGWIDGET_PDFREADER +#define OSGWIDGET_PDFREADER + +#include +#include + +#include + +namespace osgWidget { + + +/** Hints structure that can be passed to PdfReader and VncClient classes to help guide them on what geometry to build.*/ +struct GeometryHints +{ + enum AspectRatioPolicy + { + RESIZE_HEIGHT_TO_MAINTAINCE_ASPECT_RATIO, + RESIZE_WIDTH_TO_MAINTAINCE_ASPECT_RATIO, + IGNORE_DOCUMENT_ASPECT_RATIO, + }; + + GeometryHints(): + position(0.0f,0.0f,0.0f), + widthVec(1.0f,0.0f,0.0f), + heightVec(0.0f,1.0f,0.0f), + aspectRatioPolicy(RESIZE_HEIGHT_TO_MAINTAINCE_ASPECT_RATIO) {} + + GeometryHints(const osg::Vec3& pos, + const osg::Vec3& wVec, + const osg::Vec3& hVec, + AspectRatioPolicy asp=RESIZE_HEIGHT_TO_MAINTAINCE_ASPECT_RATIO): + position(pos), + widthVec(wVec), + heightVec(hVec), + aspectRatioPolicy(asp) {} + + osg::Vec3 position; + osg::Vec3 widthVec; + osg::Vec3 heightVec; + AspectRatioPolicy aspectRatioPolicy; + +}; + +/** Pure virtual base class for interfacing with implementation of PDF reader.*/ +class PdfImage : public osg::Image +{ + public: + + PdfImage():_pageNum(0) {} + + int getPageNum() const { return _pageNum; } + + virtual int getNumOfPages() = 0; + + virtual bool page(int pageNum) = 0; + + bool previous() + { + return page(_pageNum-1); + } + + bool next() + { + return page(_pageNum+1); + } + + + protected: + + virtual ~PdfImage() {} + + int _pageNum; + +}; + + +/** Convinience class that provides a interactive quad that can be placed directly in the scene.*/ +class OSGWIDGET_EXPORT PdfReader : public osg::Geode +{ + public: + + PdfReader() {} + + PdfReader(const std::string& filename, GeometryHints hints = GeometryHints()); + + bool assign(PdfImage* pdfImage, GeometryHints hints = GeometryHints()); + + bool open(const std::string& filename, GeometryHints hints = GeometryHints()); + + bool page(int pageNum); + + bool previous(); + + bool next(); + + protected: + + osg::ref_ptr _pdfImage; +}; + +} + +#endif diff --git a/include/osgWidget/VncClient b/include/osgWidget/VncClient new file mode 100644 index 000000000..cedb8af24 --- /dev/null +++ b/include/osgWidget/VncClient @@ -0,0 +1,63 @@ +/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2008 Robert Osfield + * + * 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. +*/ + +#ifndef OSGWIDGET_VNCCLIENT +#define OSGWIDGET_VNCCLIENT + +#include + +#include + +namespace osgWidget { + +/** Pure virtual base class for VncImage that is sublcassed by vnc plugin to provide the actual implementation.*/ +class VncImage : public osg::Image +{ + public: + + VncImage() {} + + virtual bool connect(const std::string& hostname) = 0; + + virtual void close() = 0; + + protected: + + virtual ~VncImage() {} + +}; + + +/** Convinience Vnc Client class that provides a interactive quad that can be placed directly in the scene.*/ +class OSGWIDGET_EXPORT VncClient : public osg::Geode +{ + public: + + VncClient() {} + + VncClient(const std::string& hostname, GeometryHints hints = GeometryHints()); + + bool assign(VncImage* vncImage, GeometryHints hints = GeometryHints()); + + bool connect(const std::string& hostname, GeometryHints hints = GeometryHints()); + + void close(); + + protected: + + osg::ref_ptr _vncImage; +}; + +} + +#endif diff --git a/src/osgPlugins/CMakeLists.txt b/src/osgPlugins/CMakeLists.txt index 86dd99fc2..8f0f5156f 100644 --- a/src/osgPlugins/CMakeLists.txt +++ b/src/osgPlugins/CMakeLists.txt @@ -196,6 +196,9 @@ IF(RSVG_FOUND AND CAIRO_FOUND) ADD_SUBDIRECTORY(svg) ENDIF(RSVG_FOUND AND CAIRO_FOUND) +IF (POPPLER_FOUND AND CAIRO_FOUND) + ADD_SUBDIRECTORY(pdf) +ENDIF(POPPLER_FOUND AND CAIRO_FOUND) IF (LIBVNCSERVER_FOUND) ADD_SUBDIRECTORY(vnc) diff --git a/src/osgPlugins/gecko/UBrowser.cpp b/src/osgPlugins/gecko/UBrowser.cpp index fdebf2f6c..a5b3e2311 100644 --- a/src/osgPlugins/gecko/UBrowser.cpp +++ b/src/osgPlugins/gecko/UBrowser.cpp @@ -478,7 +478,7 @@ struct PointerEventOperation : public osg::Operation int _buttonDelta; }; -void UBrowserManager::sendPointerEvent(UBrowserImage* image, int x, int y, int buttonMask) +bool UBrowserManager::sendPointerEvent(UBrowserImage* image, int x, int y, int buttonMask) { int deltaButton = (buttonMask&1) - (_previousButtonMask&1); _previousButtonMask = buttonMask; @@ -486,6 +486,8 @@ void UBrowserManager::sendPointerEvent(UBrowserImage* image, int x, int y, int b _thread->add(new PointerEventOperation(image, x, y, deltaButton)); active(image); + + return true; } @@ -509,15 +511,17 @@ struct KeyEventOperation : public osg::Operation bool _isUnicode; }; -void UBrowserManager::sendKeyEvent(UBrowserImage* image, int key, bool keyDown) +bool UBrowserManager::sendKeyEvent(UBrowserImage* image, int key, bool keyDown) { - if (!keyDown) return; + if (!keyDown) return false; KeyMap::const_iterator itr = _keyMap.find(key); if (_keyMap.find(key)==_keyMap.end()) _thread->add(new KeyEventOperation(image, key, true)); else _thread->add(new KeyEventOperation(image, itr->second, false)); active(image); + + return true; } @@ -582,14 +586,14 @@ UBrowserImage::~UBrowserImage() _manager->unregisterUBrowserImage(this); } -void UBrowserImage::sendPointerEvent(int x, int y, int buttonMask) +bool UBrowserImage::sendPointerEvent(int x, int y, int buttonMask) { - _manager->sendPointerEvent(this, x, y, buttonMask); + return _manager->sendPointerEvent(this, x, y, buttonMask); } -void UBrowserImage::sendKeyEvent(int key, bool keyDown) +bool UBrowserImage::sendKeyEvent(int key, bool keyDown) { - _manager->sendKeyEvent(this, key, keyDown); + return _manager->sendKeyEvent(this, key, keyDown); } void UBrowserImage::setFrameLastRendered(const osg::FrameStamp*) diff --git a/src/osgPlugins/gecko/UBrowser.h b/src/osgPlugins/gecko/UBrowser.h index 126ba6a46..97db55152 100644 --- a/src/osgPlugins/gecko/UBrowser.h +++ b/src/osgPlugins/gecko/UBrowser.h @@ -60,9 +60,9 @@ class UBrowserManager : public osgWidget::BrowserManager if (itr != _ubrowserImageList.end()) _ubrowserImageList.erase(itr); } - void sendKeyEvent(UBrowserImage* image, int key, bool keyDown); + bool sendKeyEvent(UBrowserImage* image, int key, bool keyDown); - void sendPointerEvent(UBrowserImage* image, int x, int y, int buttonMask); + bool sendPointerEvent(UBrowserImage* image, int x, int y, int buttonMask); void navigateTo(UBrowserImage* image, const std::string& page); @@ -108,9 +108,9 @@ class UBrowserImage : public osgWidget::BrowserImage, public LLEmbeddedBrowserWi const std::string& getHomeURL() const { return _homeURL; } - virtual void sendPointerEvent(int x, int y, int buttonMask); + virtual bool sendPointerEvent(int x, int y, int buttonMask); - virtual void sendKeyEvent(int key, bool keyDown); + virtual bool sendKeyEvent(int key, bool keyDown); virtual void setFrameLastRendered(const osg::FrameStamp* frameStamp); diff --git a/src/osgPlugins/pdf/CMakeLists.txt b/src/osgPlugins/pdf/CMakeLists.txt new file mode 100644 index 000000000..e09ccd540 --- /dev/null +++ b/src/osgPlugins/pdf/CMakeLists.txt @@ -0,0 +1,10 @@ +SET(TARGET_SRC ReaderWriterPDF.cpp ) + +INCLUDE_DIRECTORIES( ${CAIRO_INCLUDE_DIRS} ${POPPLER_INCLUDE_DIRS} ) +LINK_DIRECTORIES(${CAIRO_LIBRARY_DIRS} ${POPPLER_LIB_DIRS}) +SET(TARGET_EXTERNAL_LIBRARIES ${CAIRO_LIBRARIES} ${POPPLER_LIBRARIES} ) + +SET(TARGET_ADDED_LIBRARIES osgWidget ) + +#### end var setup ### +SETUP_PLUGIN(pdf) diff --git a/src/osgPlugins/pdf/ReaderWriterPDF.cpp b/src/osgPlugins/pdf/ReaderWriterPDF.cpp new file mode 100644 index 000000000..9b18b165a --- /dev/null +++ b/src/osgPlugins/pdf/ReaderWriterPDF.cpp @@ -0,0 +1,292 @@ +/* -*-c++-*- OpenSceneGraph - Copyright (C) 1999-2008 Robert Osfield + * + * This software is open source and may be redistributed and/or modified under + * the terms of the GNU General Public License (GPL) version 2.0. + * The full license is in LICENSE.txt file included with this distribution,. + * + * This software 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 + * include LICENSE.txt for more details. +*/ + +#include +#include +#include +#include + +#include + +#include +#include + +class CairoImage : public osg::Referenced +{ + public: + + CairoImage(osg::Image* image): + _image(image), + _surface(0), + _context(0) {} + + + void create(unsigned int width, unsigned int height) + { + if (_image->data() && width==_image->s() && height==_image->t()) return; + + osg::notify(osg::NOTICE)<<"Create cario surface/context "<allocateImage(width, height, 1, GL_RGBA, GL_UNSIGNED_BYTE); + _image->setPixelFormat(GL_BGRA); + _image->setDataVariance(osg::Object::DYNAMIC); + _image->setOrigin(osg::Image::TOP_LEFT); + + + // create a cairo surface for this image data + _surface = cairo_image_surface_create_for_data( + _image->data(), + CAIRO_FORMAT_ARGB32, + width, height, + _image->getRowSizeInBytes()); + + // create a context for the surface + _context = cairo_create(_surface); + } + + void destroy() + { + if (_surface) cairo_surface_destroy(_surface); + if (_context) cairo_destroy(_context); + } + + cairo_surface_t* getSurface() { return _surface; } + const cairo_surface_t* getSurface() const { return _surface; } + + cairo_t* getContext() { return _context; } + const cairo_t* getContext() const { return _context; } + + protected: + + virtual ~CairoImage() + { + destroy(); + } + + osg::observer_ptr _image; + cairo_surface_t* _surface; + cairo_t* _context; +}; + +class PopplerPdfImage : public osgWidget::PdfImage +{ + public: + + PopplerPdfImage(): + _doc(0) + { + _cairoImage = new CairoImage(this); + } + + virtual ~PopplerPdfImage() + { + _cairoImage = 0; + + if (_doc) + { + g_object_unref(_doc); + } + } + + PopplerDocument* _doc; + + int getNumOfPages() { return _doc ? poppler_document_get_n_pages(_doc) : 0; } + + bool open(const std::string& filename) + { + osg::notify(osg::NOTICE)<<"open("<=getNumOfPages()) return false; + + PopplerPage* page = poppler_document_get_page(_doc, pageNum); + + if(!page) return false; + + _pageNum = pageNum; + + double w = 0.0f; + double h = 0.0f; + + poppler_page_get_size(page, &w, &h); + + _cairoImage->create((unsigned int)(w*2.0),(unsigned int)(h*2.0)); + + double r = 1.0; + double g = 1.0; + double b = 1.0; + double a = 1.0; + + cairo_save(_cairoImage->getContext()); + + cairo_set_source_rgba(_cairoImage->getContext(), r, g, b, a); + cairo_rectangle(_cairoImage->getContext(), 0.0, 0.0, double(s()), double(t())); + cairo_fill(_cairoImage->getContext()); + + cairo_scale(_cairoImage->getContext(), double(s())/w, double(t())/h); + + poppler_page_render(page, _cairoImage->getContext()); + + + cairo_restore(_cairoImage->getContext()); + + dirty(); + + } + + + protected: + + osg::ref_ptr _cairoImage; + +}; + + +class ReaderWriterPDF : public osgDB::ReaderWriter +{ + public: + + ReaderWriterPDF() + { + supportsExtension("pdf","PDF plugin"); + } + + virtual const char* className() const { return "PDF plugin"; } + + virtual osgDB::ReaderWriter::ReadResult readObject(const std::string& file, const osgDB::ReaderWriter::Options* options) const + { + return readImage(file,options); + } + + virtual osgDB::ReaderWriter::ReadResult readImage(const std::string& fileName, const osgDB::ReaderWriter::Options* options) const + { + if (!osgDB::equalCaseInsensitive(osgDB::getFileExtension(fileName),"pdf")) + { + return osgDB::ReaderWriter::ReadResult::FILE_NOT_HANDLED; + } + + std::string file = osgDB::findDataFile(fileName); + if (file.empty()) + { + return osgDB::ReaderWriter::ReadResult::FILE_NOT_FOUND; + } + + osg::ref_ptr image = new PopplerPdfImage; + image->setDataVariance(osg::Object::DYNAMIC); + + image->setOrigin(osg::Image::TOP_LEFT); + + if (!image->open(file)) + { + return "Could not open "+file; + } + + return image.get(); + } + + virtual osgDB::ReaderWriter::ReadResult readNode(const std::string& fileName, const osgDB::ReaderWriter::Options* options) const + { + osgDB::ReaderWriter::ReadResult result = readImage(fileName, options); + if (!result.validImage()) return result; + + + osg::ref_ptr pdfReader = new osgWidget::PdfReader(); + if (pdfReader->assign(dynamic_cast(result.getImage()))) + { + return pdfReader.release(); + } + else + { + return osgDB::ReaderWriter::ReadResult::FILE_NOT_HANDLED; + } + } +}; + +// now register with Registry to instantiate the above +// reader/writer. +osgDB::RegisterReaderWriterProxy g_readerWriter_PDF_Proxy; + diff --git a/src/osgPlugins/vnc/CMakeLists.txt b/src/osgPlugins/vnc/CMakeLists.txt index 7dd0d9429..b1b3d9faf 100644 --- a/src/osgPlugins/vnc/CMakeLists.txt +++ b/src/osgPlugins/vnc/CMakeLists.txt @@ -4,7 +4,7 @@ INCLUDE_DIRECTORIES(${LIBVNCCLIENT_INCLUDE_DIR}) SET(TARGET_EXTERNAL_LIBRARIES ${LIBVNCCLIENT_LIBRARY} ${ZLIB_LIBRARY} ${JPEG_LIBRARY} ) -SET(TARGET_ADDED_LIBRARIES osgViewer ) +SET(TARGET_ADDED_LIBRARIES osgWidget ) #### end var setup ### SETUP_PLUGIN(vnc) diff --git a/src/osgPlugins/vnc/ReaderWriterVNC.cpp b/src/osgPlugins/vnc/ReaderWriterVNC.cpp index 9027ed8bf..5e3e56292 100644 --- a/src/osgPlugins/vnc/ReaderWriterVNC.cpp +++ b/src/osgPlugins/vnc/ReaderWriterVNC.cpp @@ -16,32 +16,30 @@ #include #include -#include +#include extern "C" { #include } -class VncImage : public osg::Image +class LibVncImage : public osgWidget::VncImage { public: - VncImage(); + LibVncImage(); - bool connect(int* argc, char** argv); - - bool connect(const std::string& hostname, const osgDB::ReaderWriter::Options* options); + bool connect(const std::string& hostname); void close(); - virtual void sendPointerEvent(int x, int y, int buttonMask); + virtual bool sendPointerEvent(int x, int y, int buttonMask); double getTimeOfLastUpdate() const { return _timeOfLastUpdate; } double getTimeOfLastRender() const { return _timeOfLastRender; } double time() const { return osg::Timer::instance()->time_s(); } - virtual void sendKeyEvent(int key, bool keyDown); + virtual bool sendKeyEvent(int key, bool keyDown); virtual void setFrameLastRendered(const osg::FrameStamp* frameStamp); @@ -59,13 +57,13 @@ class VncImage : public osg::Image protected: - virtual ~VncImage(); + virtual ~LibVncImage(); class RfbThread : public osg::Referenced, public OpenThreads::Thread { public: - RfbThread(rfbClient* client, VncImage* image): + RfbThread(rfbClient* client, LibVncImage* image): _client(client), _image(image), _done(false) {} @@ -119,9 +117,9 @@ class VncImage : public osg::Image } while (!_done && !testCancel()); } - rfbClient* _client; - osg::observer_ptr _image; - bool _done; + rfbClient* _client; + osg::observer_ptr _image; + bool _done; }; @@ -133,7 +131,7 @@ class VncImage : public osg::Image }; -VncImage::VncImage(): +LibVncImage::LibVncImage(): _client(0) { // setPixelBufferObject(new osg::PixelBufferObject(this); @@ -142,40 +140,11 @@ VncImage::VncImage(): } -VncImage::~VncImage() +LibVncImage::~LibVncImage() { close(); } -bool VncImage::connect(int* argc, char** argv) -{ - if (_client) close(); - - - _client = rfbGetClient(8,3,4); - _client->canHandleNewFBSize = TRUE; - _client->MallocFrameBuffer = resizeImage; - _client->GotFrameBufferUpdate = updateImage; - _client->HandleKeyboardLedState = 0; - _client->HandleTextChat = 0; - - rfbClientSetClientData(_client, 0, this); - - if (rfbInitClient(_client,argc,argv)) - { - _rfbThread = new RfbThread(_client, this); - _rfbThread->startThread(); - - return true; - } - else - { - close(); - - return false; - } -} - static rfbBool rfbInitConnection(rfbClient* client) { /* Unless we accepted an incoming connection, make a TCP connection to the @@ -229,7 +198,7 @@ static rfbBool rfbInitConnection(rfbClient* client) } -bool VncImage::connect(const std::string& hostname, const osgDB::ReaderWriter::Options* options) +bool LibVncImage::connect(const std::string& hostname) { if (hostname.empty()) return false; @@ -268,7 +237,7 @@ bool VncImage::connect(const std::string& hostname, const osgDB::ReaderWriter::O } -void VncImage::close() +void LibVncImage::close() { if (_rfbThread.valid()) { @@ -287,7 +256,7 @@ void VncImage::close() } -rfbBool VncImage::resizeImage(rfbClient* client) +rfbBool LibVncImage::resizeImage(rfbClient* client) { osg::Image* image = (osg::Image*)(rfbClientGetClientData(client, 0)); @@ -304,30 +273,32 @@ rfbBool VncImage::resizeImage(rfbClient* client) return TRUE; } -void VncImage::updateImage(rfbClient* client,int x,int y,int w,int h) +void LibVncImage::updateImage(rfbClient* client,int x,int y,int w,int h) { osg::Image* image = (osg::Image*)(rfbClientGetClientData(client, 0)); image->dirty(); } -void VncImage::sendPointerEvent(int x, int y, int buttonMask) +bool LibVncImage::sendPointerEvent(int x, int y, int buttonMask) { if (_client) { SendPointerEvent(_client ,x, y, buttonMask); + return true; } } -void VncImage::sendKeyEvent(int key, bool keyDown) +bool LibVncImage::sendKeyEvent(int key, bool keyDown) { if (_client) { SendKeyEvent(_client, key, keyDown ? TRUE : FALSE); + return true; } } -void VncImage::setFrameLastRendered(const osg::FrameStamp*) +void LibVncImage::setFrameLastRendered(const osg::FrameStamp*) { _timeOfLastRender = time(); @@ -335,7 +306,7 @@ void VncImage::setFrameLastRendered(const osg::FrameStamp*) _active = true; } -void VncImage::updated() +void LibVncImage::updated() { _timeOfLastUpdate = time(); } @@ -367,12 +338,12 @@ class ReaderWriterVNC : public osgDB::ReaderWriter osg::notify(osg::NOTICE)<<"Hostname = "< image = new VncImage; + osg::ref_ptr image = new LibVncImage; image->setDataVariance(osg::Object::DYNAMIC); image->setOrigin(osg::Image::TOP_LEFT); - if (!image->connect(hostname, options)) + if (!image->connect(hostname)) { return "Could not connect to "+hostname; } @@ -385,38 +356,16 @@ class ReaderWriterVNC : public osgDB::ReaderWriter osgDB::ReaderWriter::ReadResult result = readImage(fileName, options); if (!result.validImage()) return result; - osg::Image* image = result.getImage(); - - bool xyPlane = false; - bool flip = image->getOrigin()==osg::Image::TOP_LEFT; - osg::Vec3 origin = osg::Vec3(0.0f,0.0f,0.0f); - float width = 1.0; - float height = float(image->t())/float(image->s()); - osg::Vec3 widthAxis = osg::Vec3(width,0.0f,0.0f); - osg::Vec3 heightAxis = xyPlane ? osg::Vec3(0.0f,height,0.0f) : osg::Vec3(0.0f,0.0f,height); - osg::Geometry* pictureQuad = osg::createTexturedQuadGeometry(origin, widthAxis, heightAxis, - 0.0f, flip ? 1.0f : 0.0f , 1.0f, flip ? 0.0f : 1.0f); - - osg::Texture2D* texture = new osg::Texture2D(image); - texture->setResizeNonPowerOfTwoHint(false); - texture->setFilter(osg::Texture::MIN_FILTER,osg::Texture::LINEAR); - texture->setWrap(osg::Texture::WRAP_S, osg::Texture::CLAMP_TO_EDGE); - texture->setWrap(osg::Texture::WRAP_T, osg::Texture::CLAMP_TO_EDGE); - - pictureQuad->getOrCreateStateSet()->setTextureAttributeAndModes(0, - texture, - osg::StateAttribute::ON); - - osg::ref_ptr callback = new osgViewer::InteractiveImageHandler(image); - - pictureQuad->setEventCallback(callback.get()); - pictureQuad->setCullCallback(callback.get()); - - osg::Geode* geode = new osg::Geode; - geode->addDrawable(pictureQuad); - - return geode; + osg::ref_ptr vncClient = new osgWidget::VncClient(); + if (vncClient->assign(dynamic_cast(result.getImage()))) + { + return vncClient.release(); + } + else + { + return osgDB::ReaderWriter::ReadResult::FILE_NOT_HANDLED; + } } }; diff --git a/src/osgViewer/ViewerEventHandlers.cpp b/src/osgViewer/ViewerEventHandlers.cpp index 305d7a290..8a02f2ea5 100644 --- a/src/osgViewer/ViewerEventHandlers.cpp +++ b/src/osgViewer/ViewerEventHandlers.cpp @@ -705,8 +705,7 @@ bool InteractiveImageHandler::handle(const osgGA::GUIEventAdapter& ea,osgGA::GUI int x,y; if (mousePosition(view, nv, ea, x, y)) { - _image->sendPointerEvent(x, y, ea.getButtonMask()); - return true; + return _image->sendPointerEvent(x, y, ea.getButtonMask()); } break; } @@ -719,9 +718,7 @@ bool InteractiveImageHandler::handle(const osgGA::GUIEventAdapter& ea,osgGA::GUI if (sendKeyEvent) { - _image->sendKeyEvent(ea.getKey(), ea.getEventType()==osgGA::GUIEventAdapter::KEYDOWN); - - return true; + return _image->sendKeyEvent(ea.getKey(), ea.getEventType()==osgGA::GUIEventAdapter::KEYDOWN); } } diff --git a/src/osgWidget/CMakeLists.txt b/src/osgWidget/CMakeLists.txt index 34b6da365..335741ae9 100644 --- a/src/osgWidget/CMakeLists.txt +++ b/src/osgWidget/CMakeLists.txt @@ -10,6 +10,8 @@ SET(LIB_PUBLIC_HEADERS ${HEADER_PATH}/Export ${HEADER_PATH}/Box ${HEADER_PATH}/Browser + ${HEADER_PATH}/PdfReader + ${HEADER_PATH}/VncClient ${HEADER_PATH}/Canvas ${HEADER_PATH}/EventInterface ${HEADER_PATH}/Frame @@ -37,6 +39,8 @@ ADD_LIBRARY(${LIB_NAME} ${LIB_PUBLIC_HEADERS} Box.cpp Browser.cpp + PdfReader.cpp + VncClient.cpp Canvas.cpp CMakeLists.txt Frame.cpp diff --git a/src/osgWidget/PdfReader.cpp b/src/osgWidget/PdfReader.cpp new file mode 100644 index 000000000..22d01a966 --- /dev/null +++ b/src/osgWidget/PdfReader.cpp @@ -0,0 +1,100 @@ +/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2008 Robert Osfield + * + * 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 + +using namespace osgWidget; + +PdfReader::PdfReader(const std::string& filename, GeometryHints hints) +{ + open(filename, hints); +} + +bool PdfReader::assign(PdfImage* pdfImage, GeometryHints hints) +{ + if (!pdfImage) return false; + + _pdfImage = pdfImage; + + bool flip = _pdfImage->getOrigin()==osg::Image::TOP_LEFT; + + float aspectRatio = (_pdfImage->t()>0 && _pdfImage->s()>0) ? float(_pdfImage->t()) / float(_pdfImage->s()) : 1.0; + + osg::Vec3 widthVec(hints.widthVec); + osg::Vec3 heightVec(hints.heightVec); + + switch(hints.aspectRatioPolicy) + { + case(GeometryHints::RESIZE_HEIGHT_TO_MAINTAINCE_ASPECT_RATIO): + heightVec *= aspectRatio; + break; + case(GeometryHints::RESIZE_WIDTH_TO_MAINTAINCE_ASPECT_RATIO): + widthVec /= aspectRatio; + break; + default: + // no need to adjust aspect ratio + break; + } + + osg::Geometry* pictureQuad = osg::createTexturedQuadGeometry(hints.position, widthVec, heightVec, + 0.0f, flip ? 1.0f : 0.0f , 1.0f, flip ? 0.0f : 1.0f); + + osg::Texture2D* texture = new osg::Texture2D(_pdfImage.get()); + texture->setResizeNonPowerOfTwoHint(false); + texture->setFilter(osg::Texture::MIN_FILTER,osg::Texture::LINEAR); + texture->setWrap(osg::Texture::WRAP_S, osg::Texture::CLAMP_TO_EDGE); + texture->setWrap(osg::Texture::WRAP_T, osg::Texture::CLAMP_TO_EDGE); + + pictureQuad->getOrCreateStateSet()->setTextureAttributeAndModes(0, + texture, + osg::StateAttribute::ON); + + pictureQuad->setEventCallback(new osgViewer::InteractiveImageHandler(_pdfImage.get())); + + addDrawable(pictureQuad); + + return true; +} + +bool PdfReader::open(const std::string& filename, GeometryHints hints) +{ + osg::ref_ptr image = osgDB::readImageFile(filename); + return assign(dynamic_cast(image.get()), hints); +} + +bool PdfReader::page(int pageNum) +{ + if (!_pdfImage) return false; + + return _pdfImage->page(pageNum); +} + +bool PdfReader::previous() +{ + if (!_pdfImage) return false; + + return _pdfImage->previous(); +} + +bool PdfReader::next() +{ + if (!_pdfImage) return false; + + return _pdfImage->next(); +} diff --git a/src/osgWidget/VncClient.cpp b/src/osgWidget/VncClient.cpp new file mode 100644 index 000000000..3cff10ae4 --- /dev/null +++ b/src/osgWidget/VncClient.cpp @@ -0,0 +1,64 @@ +/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2008 Robert Osfield + * + * 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 + +using namespace osgWidget; + +VncClient::VncClient(const std::string& hostname, GeometryHints hints) +{ + connect(hostname, hints); +} + +bool VncClient::assign(VncImage* vncImage, GeometryHints hints) +{ + if (!vncImage) return false; + + _vncImage = vncImage; + + bool flip = _vncImage->getOrigin()==osg::Image::TOP_LEFT; + + osg::Geometry* pictureQuad = osg::createTexturedQuadGeometry(hints.position, hints.widthVec, hints.heightVec, + 0.0f, flip ? 1.0f : 0.0f , 1.0f, flip ? 0.0f : 1.0f); + + osg::Texture2D* texture = new osg::Texture2D(_vncImage.get()); + texture->setResizeNonPowerOfTwoHint(false); + texture->setFilter(osg::Texture::MIN_FILTER,osg::Texture::LINEAR); + texture->setWrap(osg::Texture::WRAP_S, osg::Texture::CLAMP_TO_EDGE); + texture->setWrap(osg::Texture::WRAP_T, osg::Texture::CLAMP_TO_EDGE); + + pictureQuad->getOrCreateStateSet()->setTextureAttributeAndModes(0, + texture, + osg::StateAttribute::ON); + + pictureQuad->setEventCallback(new osgViewer::InteractiveImageHandler(_vncImage.get())); + + addDrawable(pictureQuad); + + return true; +} + +bool VncClient::connect(const std::string& hostname, GeometryHints hints) +{ + osg::ref_ptr image = osgDB::readImageFile(hostname+".vnc"); + return assign(dynamic_cast(image.get())); +} + +void VncClient::close() +{ + if (!_vncImage) return; + + _vncImage->close(); +}