root/OpenSceneGraph/trunk/src/osgPlugins/pdf/ReaderWriterPDF.cpp @ 13041

Revision 13041, 7.9 kB (checked in by robert, 2 years ago)

Ran script to remove trailing spaces and tabs

  • Property svn:eol-style set to native
Line 
1/* -*-c++-*- OpenSceneGraph - Copyright (C) 1999-2008 Robert Osfield
2 *
3 * This software is open source and may be redistributed and/or modified under
4 * the terms of the GNU General Public License (GPL) version 2.0.
5 * The full license is in LICENSE.txt file included with this distribution,.
6 *
7 * This software is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
10 * include LICENSE.txt for more details.
11*/
12
13#include <osgDB/ReaderWriter>
14#include <osgDB/FileNameUtils>
15#include <osgDB/Registry>
16#include <osgDB/FileUtils>
17
18#include <osgWidget/PdfReader>
19#include <osg/ImageUtils>
20
21#include <cairo.h>
22#include <poppler.h>
23
24class CairoImage : public osg::Referenced
25{
26    public:
27
28        CairoImage(osg::Image* image):
29            _image(image),
30            _surface(0),
31            _context(0) {}
32
33
34        void create(int width, int height)
35        {
36            if (_image->data() && width==_image->s() && height==_image->t())
37            {
38                return;
39            }
40
41            OSG_NOTICE<<"Create cario surface/context "<<width<<", "<<height<<std::endl;
42
43            // allocate the image data
44            _image->allocateImage(width, height, 1, GL_RGBA, GL_UNSIGNED_BYTE);
45            _image->setPixelFormat(GL_BGRA);
46            _image->setDataVariance(osg::Object::DYNAMIC);
47            _image->setOrigin(osg::Image::TOP_LEFT);
48
49
50            // create a cairo surface for this image data
51            _surface = cairo_image_surface_create_for_data(
52                    _image->data(),
53                    CAIRO_FORMAT_ARGB32,
54                    width, height,
55                    _image->getRowSizeInBytes());
56
57            // create a context for the surface
58            _context = cairo_create(_surface);
59        }
60
61        void destroy()
62        {
63            if (_surface) cairo_surface_destroy(_surface);
64            if (_context) cairo_destroy(_context);
65        }
66
67        cairo_surface_t* getSurface() { return _surface; }
68        const cairo_surface_t* getSurface() const { return _surface; }
69
70        cairo_t* getContext() { return _context; }
71        const cairo_t* getContext() const { return _context; }
72
73    protected:
74
75        virtual ~CairoImage()
76        {
77            destroy();
78        }
79
80        osg::observer_ptr<osg::Image> _image;
81        cairo_surface_t*              _surface;
82        cairo_t*                      _context;
83};
84
85class PopplerPdfImage : public osgWidget::PdfImage
86{
87    public:
88
89        PopplerPdfImage():
90            _doc(0)
91        {
92            _cairoImage = new CairoImage(this);
93        }
94
95        virtual ~PopplerPdfImage()
96        {
97            _cairoImage = 0;
98
99            if (_doc)
100            {
101                g_object_unref(_doc);
102            }
103        }
104
105        PopplerDocument* _doc;
106
107        int getNumOfPages() { return _doc ? poppler_document_get_n_pages(_doc) : 0; }
108
109        bool open(const std::string& filename)
110        {
111            OSG_NOTICE<<"open("<<filename<<")"<<std::endl;
112
113            std::string foundFile = osgDB::findDataFile(filename);
114            if (foundFile.empty())
115            {
116                OSG_NOTICE<<"could not find filename="<<filename<<std::endl;
117                return false;
118            }
119
120            OSG_NOTICE<<"foundFile = "<<foundFile<<std::endl;
121            foundFile = osgDB::getRealPath(foundFile);
122            OSG_NOTICE<<"foundFile = "<<foundFile<<std::endl;
123
124            static bool gTypeInit = false;
125
126            if(!gTypeInit)
127            {
128                g_type_init();
129
130                gTypeInit = true;
131            }
132
133#if defined(WIN32) && !defined(__CYGWIN__)
134            std::string uri = std::string("file:///") + foundFile;
135#else
136            std::string uri = std::string("file:") + foundFile;
137#endif
138
139            PopplerDocument* doc = poppler_document_new_from_file(uri.c_str(), NULL, NULL);
140            if (!doc)
141            {
142                OSG_NOTICE<<" could not open("<<filename<<"), uri="<<uri<<std::endl;
143
144                return false;
145            }
146
147            if (_doc)
148            {
149                g_object_unref(_doc);
150            }
151
152            _doc = doc;
153            _pageNum = 0;
154
155            setFileName(filename);
156
157            OSG_NOTICE<<"getNumOfPages()=="<<getNumOfPages()<<std::endl;
158
159            if (getNumOfPages()==0)
160            {
161                return false;
162            }
163
164            page(0);
165
166            return true;
167        }
168
169        virtual bool sendKeyEvent(int key, bool keyDown)
170        {
171            if (keyDown && key!=0)
172            {
173                if (key==_nextPageKeyEvent)
174                {
175                    next();
176                    return true;
177                }
178                else if (key==_previousPageKeyEvent)
179                {
180                    previous();
181                    return true;
182                }
183            }
184            return false;
185        }
186
187
188        virtual bool page(int pageNum)
189        {
190            if (!_doc) return false;
191
192            if (pageNum<0 || pageNum>=getNumOfPages()) return false;
193
194            PopplerPage* page = poppler_document_get_page(_doc, pageNum);
195
196            if(!page) return false;
197
198            _pageNum = pageNum;
199
200            double w = 0.0f;
201            double h = 0.0f;
202
203            poppler_page_get_size(page, &w, &h);
204
205            _cairoImage->create((unsigned int)(w*2.0),(unsigned int)(h*2.0));
206
207            osg::clearImageToColor(this, _backgroundColor);
208
209            cairo_save(_cairoImage->getContext());
210
211                cairo_rectangle(_cairoImage->getContext(), 0.0, 0.0, double(s()), double(t()));
212                cairo_scale(_cairoImage->getContext(), double(s())/w, double(t())/h);
213                poppler_page_render(page, _cairoImage->getContext());
214
215            cairo_restore(_cairoImage->getContext());
216
217            dirty();
218
219            return true;
220    }
221
222
223    protected:
224
225        osg::ref_ptr<CairoImage> _cairoImage;
226
227};
228
229
230class ReaderWriterPDF : public osgDB::ReaderWriter
231{
232    public:
233
234        ReaderWriterPDF()
235        {
236            supportsExtension("pdf","PDF plugin");
237        }
238
239        virtual const char* className() const { return "PDF plugin"; }
240
241        virtual osgDB::ReaderWriter::ReadResult readObject(const std::string& file, const osgDB::ReaderWriter::Options* options) const
242        {
243            return readImage(file,options);
244        }
245
246        virtual osgDB::ReaderWriter::ReadResult readImage(const std::string& fileName, const osgDB::ReaderWriter::Options* options) const
247        {
248            if (!osgDB::equalCaseInsensitive(osgDB::getFileExtension(fileName),"pdf"))
249            {
250                return osgDB::ReaderWriter::ReadResult::FILE_NOT_HANDLED;
251            }
252
253            std::string file = osgDB::findDataFile(fileName);
254            if (file.empty())
255            {
256                return osgDB::ReaderWriter::ReadResult::FILE_NOT_FOUND;
257            }
258
259            osg::ref_ptr<PopplerPdfImage> image = new PopplerPdfImage;
260            image->setDataVariance(osg::Object::DYNAMIC);
261
262            image->setOrigin(osg::Image::TOP_LEFT);
263
264            if (!image->open(file))
265            {
266                return "Could not open "+file;
267            }
268
269            return image.get();
270        }
271
272        virtual osgDB::ReaderWriter::ReadResult readNode(const std::string& fileName, const osgDB::ReaderWriter::Options* options) const
273        {
274            osgDB::ReaderWriter::ReadResult result = readImage(fileName, options);
275            if (!result.validImage()) return result;
276
277
278            osg::ref_ptr<osgWidget::PdfReader> pdfReader = new osgWidget::PdfReader();
279            if (pdfReader->assign(dynamic_cast<osgWidget::PdfImage*>(result.getImage())))
280            {
281                return pdfReader.release();
282            }
283            else
284            {
285                return osgDB::ReaderWriter::ReadResult::FILE_NOT_HANDLED;
286            }
287        }
288};
289
290// now register with Registry to instantiate the above
291// reader/writer.
292REGISTER_OSGPLUGIN(pdf, ReaderWriterPDF)
Note: See TracBrowser for help on using the browser.