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.
This commit is contained in:
Robert Osfield
2008-12-07 17:02:30 +00:00
parent 0114ac4734
commit 6f356aeb97
20 changed files with 752 additions and 476 deletions

View File

@@ -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 <osgDB/ReaderWriter>
#include <osgDB/FileNameUtils>
#include <osgDB/Registry>
#include <osgDB/FileUtils>
#include <osgWidget/PdfReader>
#include <cairo.h>
#include <poppler.h>
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 "<<width<<", "<<height<<std::endl;
// allocate the image data
_image->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<osg::Image> _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("<<filename<<")"<<std::endl;
std::string foundFile = osgDB::findDataFile(filename);
if (foundFile.empty())
{
osg::notify(osg::NOTICE)<<"could not find filename="<<filename<<std::endl;
return false;
}
osg::notify(osg::NOTICE)<<"foundFile = "<<foundFile<<std::endl;
foundFile = osgDB::getRealPath(foundFile);
osg::notify(osg::NOTICE)<<"foundFile = "<<foundFile<<std::endl;
static bool gTypeInit = false;
if(!gTypeInit)
{
g_type_init();
gTypeInit = true;
}
std::string uri = std::string("file:") + foundFile;
PopplerDocument* doc = poppler_document_new_from_file(uri.c_str(), NULL, NULL);
if (!doc)
{
osg::notify(osg::NOTICE)<<" could not open("<<filename<<"), uri="<<uri<<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 bool sendKeyEvent(int key, bool keyDown)
{
if (keyDown)
{
if (key=='n')
{
next();
return true;
}
else if (key=='p')
{
previous();
return true;
}
}
return false;
}
virtual 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);
_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> _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<PopplerPdfImage> 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<osgWidget::PdfReader> pdfReader = new osgWidget::PdfReader();
if (pdfReader->assign(dynamic_cast<osgWidget::PdfImage*>(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<ReaderWriterPDF> g_readerWriter_PDF_Proxy;