Introduced new osgpdf example that use Cario + Poppler libraries to provide a means of rendering a pdf document to an osg::Image.

This commit is contained in:
Robert Osfield 2008-11-12 14:21:05 +00:00
parent 453e595636
commit 771dc7d645
3 changed files with 325 additions and 0 deletions

View File

@ -108,6 +108,12 @@ IF(DYNAMIC_OPENSCENEGRAPH)
ADD_SUBDIRECTORY(osgvolume) ADD_SUBDIRECTORY(osgvolume)
ADD_SUBDIRECTORY(osgwindows) ADD_SUBDIRECTORY(osgwindows)
IF (POPPLER_FOUND AND CAIRO_FOUND)
ADD_SUBDIRECTORY(osgpdf)
ENDIF(POPPLER_FOUND AND CAIRO_FOUND)
IF (BUILD_OSG_WRAPPERS) IF (BUILD_OSG_WRAPPERS)
ADD_SUBDIRECTORY(osgintrospection) ADD_SUBDIRECTORY(osgintrospection)
ENDIF(BUILD_OSG_WRAPPERS) ENDIF(BUILD_OSG_WRAPPERS)

View File

@ -0,0 +1,13 @@
PKG_CHECK_MODULES(POPPLER poppler-glib)
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})
#### end var setup ###
SETUP_EXAMPLE(osgpdf)

306
examples/osgpdf/osgpdf.cpp Normal file
View File

@ -0,0 +1,306 @@
#include <osg/Image>
#include <osg/Geometry>
#include <osg/Texture2D>
#include <osg/io_utils>
#include <osgViewer/Viewer>
#include <osgViewer/ViewerEventHandlers>
#include <osgDB/ReadFile>
#include <cairo.h>
#include <poppler.h>
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 "<<width<<", "<<height<<std::endl;
// allocate the image data
allocateImage(width, height, 1, GL_RGBA, GL_UNSIGNED_BYTE);
setPixelFormat(GL_BGRA);
setDataVariance(osg::Object::DYNAMIC);
setOrigin(osg::Image::TOP_LEFT);
// create a cairo surface for this image data
_surface = cairo_image_surface_create_for_data(
data(),
CAIRO_FORMAT_ARGB32,
width, height,
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 ~CarioImage()
{
destroy();
}
cairo_surface_t* _surface;
cairo_t* _context;
};
class PdfImage : public CarioImage
{
public:
PdfImage():
_doc(0),
_pageNum(0)
{
}
virtual ~PdfImage()
{
if (_doc)
{
g_object_unref(_doc);
}
}
PopplerDocument* _doc;
int _pageNum;
int getNumOfPages() { return _doc ? poppler_document_get_n_pages(_doc) : 0; }
bool open(const std::string& filename)
{
osg::notify(osg::NOTICE)<<"open("<<filename<<")"<<std::endl;
static bool gTypeInit = false;
if(!gTypeInit)
{
g_type_init();
gTypeInit = true;
}
PopplerDocument* doc = poppler_document_new_from_file(filename.c_str(), NULL, NULL);
if (!doc)
{
osg::notify(osg::NOTICE)<<" could not open("<<filename<<")"<<std::endl;
return false;
}
if (_doc)
{
g_object_unref(_doc);
}
_doc = doc;
_pageNum = 0;
setFileName(filename);
osg::notify(osg::NOTICE)<<"getNumOfPages()=="<<getNumOfPages()<<std::endl;
if (getNumOfPages()==0)
{
return false;
}
page(0);
return true;
}
virtual void sendKeyEvent(int key, bool keyDown)
{
if (keyDown)
{
if (key=='n') next();
else if (key=='p') previous();
}
}
bool previous()
{
return page(_pageNum-1);
}
bool next()
{
return page(_pageNum+1);
}
bool page(int pageNum)
{
if (!_doc) return false;
if (pageNum<0 || pageNum>=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),(unsigned int)(h));
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, w, h);
cairo_fill(_context);
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"<<std::endl;
return true;
}
else
if (ea.getKey()=='p')
{
osg::notify(osg::NOTICE)<<"Previous page"<<std::endl;
return true;
}
}
default:
return false;
}
return false;
}
};
int main(int argc,char** argv)
{
osg::ArgumentParser arguments(&argc, argv);
osgViewer::Viewer viewer(arguments);
typedef std::list< osg::ref_ptr<osg::Image> > Images;
Images images;
for(int i=1; i<arguments.argc(); ++i)
{
if (!arguments.isOption(i))
{
osg::ref_ptr<PdfImage> pdfImage= new PdfImage;
if (pdfImage->open(arguments[i]))
{
images.push_back(pdfImage.get());
}
}
}
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.addEventHandler(new osgViewer::StatsHandler);
//viewer.addEventHandler(new PageHandler);
return viewer.run();
}