Dear poppler maintainers, Attached below is a suggested patch (to git master) which adds a binary interface to read directly from 3DD objects carrying U3D or PRC data.
I am now trying to add 3DPDF support to Evince, and this is meant to be the first step of the improvement. Therefore changes are only applied to the glib frontend as for now, and contain minimal updates in functionality, without inspection through the Activation (3DA) Dictionary. I promise I will add the rest of the interface after everything is deemed stable in both components, Evince and poppler. This is the very first time I ever submit a patch to OSS projects, so there might be problems with what I am doing, though most of the lines are adapted from existing code. May I await your approval before commit? I am not familiar with how patches are accepted or rejected here. Thank you. -- Hiroka IHARA Department of Information and Communication Engineering, The University of Tokyo PC: [email protected] diff --git CMakeLists.txt CMakeLists.txt index d59a6fc..811da4e 100644 --- CMakeLists.txt +++ CMakeLists.txt @@ -396,6 +396,7 @@ set(poppler_SRCS poppler/XpdfPluginAPI.cc poppler/Movie.cc poppler/Rendition.cc + poppler/Artwork3D.cc ) set(poppler_LIBS ${FREETYPE_LIBRARIES}) if(ENABLE_SPLASH) @@ -582,6 +583,7 @@ if(ENABLE_XPDF_HEADERS) poppler/UTF8.h poppler/XpdfPluginAPI.h poppler/Sound.h + poppler/Artwork3D.h ${CMAKE_CURRENT_BINARY_DIR}/poppler/poppler-config.h DESTINATION include/poppler) install(FILES diff --git glib/CMakeLists.txt glib/CMakeLists.txt index a40fc8a..69e9d7a 100644 --- glib/CMakeLists.txt +++ glib/CMakeLists.txt @@ -31,6 +31,7 @@ set(poppler_glib_public_headers poppler-media.h poppler.h poppler-structure-element.h + poppler-artwork3d.h ) find_program(GLIB2_MKENUMS glib-mkenums) @@ -73,6 +74,7 @@ set(poppler_glib_SRCS poppler-cached-file-loader.cc poppler-input-stream.cc poppler-structure-element.cc + poppler-artwork3d.cc ) set(poppler_glib_generated_SRCS ${CMAKE_CURRENT_BINARY_DIR}/poppler-enums.c diff --git glib/poppler-annot.cc glib/poppler-annot.cc index 312aa31..6c61b4a 100644 --- glib/poppler-annot.cc +++ glib/poppler-annot.cc @@ -40,6 +40,7 @@ typedef struct _PopplerAnnotScreenClass PopplerAnnotScreenClass; typedef struct _PopplerAnnotLineClass PopplerAnnotLineClass; typedef struct _PopplerAnnotCircleClass PopplerAnnotCircleClass; typedef struct _PopplerAnnotSquareClass PopplerAnnotSquareClass; +typedef struct _PopplerAnnotArtwork3DClass PopplerAnnotArtwork3DClass; struct _PopplerAnnotClass { @@ -150,6 +151,18 @@ struct _PopplerAnnotSquareClass PopplerAnnotMarkupClass parent_class; }; +struct _PopplerAnnotArtwork3D +{ + PopplerAnnot parent_instance; + + PopplerArtwork3D *artwork3d; +}; + +struct _PopplerAnnotArtwork3DClass +{ + PopplerAnnotClass parent_class; +}; + G_DEFINE_TYPE (PopplerAnnot, poppler_annot, G_TYPE_OBJECT) G_DEFINE_TYPE (PopplerAnnotMarkup, poppler_annot_markup, POPPLER_TYPE_ANNOT) G_DEFINE_TYPE (PopplerAnnotTextMarkup, poppler_annot_text_markup, POPPLER_TYPE_ANNOT_MARKUP) @@ -161,6 +174,7 @@ G_DEFINE_TYPE (PopplerAnnotScreen, poppler_annot_screen, POPPLER_TYPE_ANNOT) G_DEFINE_TYPE (PopplerAnnotLine, poppler_annot_line, POPPLER_TYPE_ANNOT_MARKUP) G_DEFINE_TYPE (PopplerAnnotCircle, poppler_annot_circle, POPPLER_TYPE_ANNOT_MARKUP) G_DEFINE_TYPE (PopplerAnnotSquare, poppler_annot_square, POPPLER_TYPE_ANNOT_MARKUP) +G_DEFINE_TYPE (PopplerAnnotArtwork3D, poppler_annot_artwork3d, POPPLER_TYPE_ANNOT) static PopplerAnnot * _poppler_create_annot (GType annot_type, Annot *annot) @@ -533,6 +547,51 @@ _poppler_annot_movie_new (Annot *annot) } static void +poppler_annot_artwork3d_finalize (GObject *object) +{ + PopplerAnnotArtwork3D *annot_artwork3d = POPPLER_ANNOT_3D (object); + + if (annot_artwork3d->artwork3d) { + g_object_unref (annot_artwork3d->artwork3d); + annot_artwork3d->artwork3d = NULL; + } + + G_OBJECT_CLASS (poppler_annot_artwork3d_parent_class)->finalize (object); +} + +static void +poppler_annot_artwork3d_init (PopplerAnnotArtwork3D *poppler_annot) +{ +} + +static void +poppler_annot_artwork3d_class_init (PopplerAnnotArtwork3DClass *klass) +{ + GObjectClass *gobject_class = G_OBJECT_CLASS (klass); + + gobject_class->finalize = poppler_annot_artwork3d_finalize; +} + +PopplerAnnot * +_poppler_annot_artwork3d_new (Annot *annot) +{ + PopplerAnnot *poppler_annot; + Annot3D *annot3d; + + poppler_annot = _poppler_create_annot (POPPLER_TYPE_ANNOT_3D, annot); + annot3d = static_cast<Annot3D *>(poppler_annot->annot); + POPPLER_ANNOT_3D (poppler_annot)->artwork3d = _poppler_artwork3d_new (annot3d->getArtwork()); + + return poppler_annot; +} + +PopplerArtwork3D * +poppler_annot_artwork3d_get_artwork3d (PopplerAnnotArtwork3D *poppler_annot) +{ + return poppler_annot->artwork3d; +} + +static void poppler_annot_screen_finalize (GObject *object) { PopplerAnnotScreen *annot_screen = POPPLER_ANNOT_SCREEN (object); diff --git glib/poppler-annot.h glib/poppler-annot.h index 44ab5e3..24740d1 100644 --- glib/poppler-annot.h +++ glib/poppler-annot.h @@ -73,6 +73,10 @@ G_BEGIN_DECLS #define POPPLER_ANNOT_SQUARE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), POPPLER_TYPE_ANNOT_SQUARE, PopplerAnnotSquare)) #define POPPLER_IS_ANNOT_SQUARE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), POPPLER_TYPE_ANNOT_SQUARE)) +#define POPPLER_TYPE_ANNOT_3D (poppler_annot_artwork3d_get_type ()) +#define POPPLER_ANNOT_3D(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), POPPLER_TYPE_ANNOT_3D, PopplerAnnotArtwork3D)) +#define POPPLER_IS_ANNOT_3D(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), POPPLER_TYPE_ANNOT_3D)) + typedef enum { POPPLER_ANNOT_UNKNOWN, @@ -293,6 +297,10 @@ void poppler_annot_square_set_interior_color ( PopplerColor *poppler_color); PopplerColor *poppler_annot_square_get_interior_color (PopplerAnnotSquare *poppler_annot); +/* PopplerAnnotArtwork3D */ +GType poppler_annot_artwork3d_get_type (void) G_GNUC_CONST; +PopplerArtwork3D *poppler_annot_artwork3d_get_artwork3d (PopplerAnnotArtwork3D *poppler_annot); + G_END_DECLS #endif /* __POPPLER_ANNOT_H__ */ diff --git glib/poppler-artwork3d.cc glib/poppler-artwork3d.cc new file mode 100644 index 0000000..c69eb2a --- /dev/null +++ glib/poppler-artwork3d.cc @@ -0,0 +1,137 @@ +/* poppler-artwork3d.cc: glib interface to Artwork3D (adapted from poppler-media.cc) + * + * Copyright (C) 2010 Carlos Garcia Campos <[email protected]> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This program 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 + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include <errno.h> +#include <glib/gstdio.h> + +#include "poppler-artwork3d.h" +#include "poppler-private.h" + +typedef struct _PopplerArtwork3DClass PopplerArtwork3DClass; + +struct _PopplerArtwork3D +{ + GObject parent_instance; + + Stream *stream; +}; + +struct _PopplerArtwork3DClass +{ + GObjectClass parent_class; +}; + +G_DEFINE_TYPE (PopplerArtwork3D, poppler_artwork3d, G_TYPE_OBJECT); + +static void +poppler_artwork3d_finalize (GObject *object) +{ + PopplerArtwork3D *artwork3d = POPPLER_ARTWORK3D (object); + + if (artwork3d->stream) { + artwork3d->stream->decRef(); + artwork3d->stream = NULL; + } + + G_OBJECT_CLASS (poppler_artwork3d_parent_class)->finalize (object); +} + +static void +poppler_artwork3d_class_init (PopplerArtwork3DClass *klass) +{ + GObjectClass *gobject_class = G_OBJECT_CLASS (klass); + + gobject_class->finalize = poppler_artwork3d_finalize; +} + +static void +poppler_artwork3d_init (PopplerArtwork3D *artwork3d) +{ +} + +PopplerArtwork3D * +_poppler_artwork3d_new (Artwork3D *poppler_artwork3d) +{ + PopplerArtwork3D *artwork3d; + + g_assert (poppler_artwork3d != NULL); + + artwork3d = POPPLER_ARTWORK3D (g_object_new (POPPLER_TYPE_ARTWORK3D, NULL)); + + artwork3d->stream = poppler_artwork3d->getStream(); + + return artwork3d; +} + +gboolean +poppler_artwork3d_save (PopplerArtwork3D *artwork3d, + const char *filename, + GError **error) +{ + gboolean result = TRUE; + FILE *f; + + g_return_val_if_fail (POPPLER_IS_ARTWORK3D (artwork3d), FALSE); + g_return_val_if_fail (artwork3d->stream != NULL, FALSE); + + f = g_fopen (filename, "wb"); + + if (f == NULL) { + gchar *display_name = g_filename_display_name (filename); + g_set_error (error, + G_FILE_ERROR, + g_file_error_from_errno (errno), + "Failed to open '%s' for writing: %s", + display_name, + g_strerror (errno)); + g_free (display_name); + return FALSE; + } + + artwork3d->stream->reset (); + while(1) { + int data = artwork3d->stream->getChar (); + if (data == EOF) break; + if (fputc (data, f) == EOF) { + g_set_error (error, + G_FILE_ERROR, + g_file_error_from_errno (errno), + "Error writing to 3D artwork file: %s", + g_strerror (errno)); + result = FALSE; + break; + } + } + artwork3d->stream->close (); + + if (fclose (f) < 0) + { + gchar *display_name = g_filename_display_name (filename); + g_set_error (error, + G_FILE_ERROR, + g_file_error_from_errno (errno), + "Failed to close '%s', all data may not have been saved: %s", + display_name, + g_strerror (errno)); + g_free (display_name); + return FALSE; + } + + return result; +} diff --git glib/poppler-artwork3d.h glib/poppler-artwork3d.h new file mode 100644 index 0000000..98f2c30 --- /dev/null +++ glib/poppler-artwork3d.h @@ -0,0 +1,39 @@ +/* poppler-artwork3d.h: glib interface to Artwork3D (adapted from poppler-media.h) + * + * Copyright (C) 2010 Carlos Garcia Campos <[email protected]> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This program 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 + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef __POPPLER_ARTWORK3D_H__ +#define __POPPLER_ARTWORK3D_H__ + +#include <glib-object.h> +#include "poppler.h" + +G_BEGIN_DECLS + +#define POPPLER_TYPE_ARTWORK3D (poppler_artwork3d_get_type ()) +#define POPPLER_ARTWORK3D(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), POPPLER_TYPE_ARTWORK3D, PopplerArtwork3D)) +#define POPPLER_IS_ARTWORK3D(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), POPPLER_TYPE_ARTWORK3D)) + +GType poppler_artwork3d_get_type (void) G_GNUC_CONST; +gboolean poppler_artwork3d_save (PopplerArtwork3D *artwork3d, + const char *filename, + GError **error); + +G_END_DECLS + +#endif diff --git glib/poppler-page.cc glib/poppler-page.cc index 3d63bfd..00d06f1 100644 --- glib/poppler-page.cc +++ glib/poppler-page.cc @@ -1416,7 +1416,10 @@ poppler_page_get_annot_mapping (PopplerPage *page) case Annot::typeSquiggly: case Annot::typeStrikeOut: mapping->annot = _poppler_annot_text_markup_new (annot); - break; + break; + case Annot::type3D: + mapping->annot = _poppler_annot_artwork3d_new (annot); + break; default: mapping->annot = _poppler_annot_new (annot); break; diff --git glib/poppler-private.h glib/poppler-private.h index 9abdd7c..8eada2f 100644 --- glib/poppler-private.h +++ glib/poppler-private.h @@ -18,6 +18,7 @@ #include <CairoOutputDev.h> #include <FileSpec.h> #include <StructElement.h> +#include <Artwork3D.h> #endif struct _PopplerDocument @@ -134,6 +135,8 @@ PopplerAnnot *_poppler_annot_screen_new (PopplerDocument *doc, Annot *annot PopplerAnnot *_poppler_annot_line_new (Annot *annot); PopplerAnnot *_poppler_annot_circle_new (Annot *annot); PopplerAnnot *_poppler_annot_square_new (Annot *annot); +PopplerAnnot *_poppler_annot_artwork3d_new (Annot *annot); +PopplerArtwork3D *_poppler_artwork3d_new (Artwork3D *artwork3d); char *_poppler_goo_string_to_utf8(GooString *s); gboolean _poppler_convert_pdf_date_to_gtime (GooString *date, diff --git glib/poppler.h glib/poppler.h index 1e78050..3945ca4 100644 --- glib/poppler.h +++ glib/poppler.h @@ -204,6 +204,8 @@ typedef struct _PopplerQuadrilateral PopplerQuadrilateral; typedef struct _PopplerStructureElement PopplerStructureElement; typedef struct _PopplerStructureElementIter PopplerStructureElementIter; typedef struct _PopplerTextSpan PopplerTextSpan; +typedef struct _PopplerAnnotArtwork3D PopplerAnnotArtwork3D; +typedef struct _PopplerArtwork3D PopplerArtwork3D; /** * PopplerBackend: @@ -238,5 +240,6 @@ G_END_DECLS #include "poppler-movie.h" #include "poppler-media.h" #include "poppler-structure-element.h" +#include "poppler-artwork3d.h" #endif /* __POPPLER_GLIB_H__ */ diff --git poppler/Annot.cc poppler/Annot.cc index 51a80e5..4bc0db3 100644 --- poppler/Annot.cc +++ poppler/Annot.cc @@ -73,6 +73,7 @@ #include "FileSpec.h" #include "DateInfo.h" #include "Link.h" +#include "Artwork3D.h" #include <string.h> #include <algorithm> @@ -6612,6 +6613,17 @@ void Annot3D::initialize(PDFDoc *docA, Dict* dict) { activation = NULL; } obj1.free(); + + if (dict->lookup("3DD", &obj1)->isStream()) { + artwork = new Artwork3D(&obj1); + } else if(obj1.isDict()) { + Object obj2; + if (obj1.getDict()->lookup("3DD", &obj2)->isStream()) { + artwork = new Artwork3D(&obj2); + } + obj2.free(); + } + obj1.free(); } Annot3D::Activation::Activation(Dict *dict) { @@ -6698,6 +6710,10 @@ Annot3D::Activation::Activation(Dict *dict) { obj1.free(); } +Artwork3D *Annot3D::getArtwork() const { + return artwork; +} + //------------------------------------------------------------------------ // AnnotRichMedia //------------------------------------------------------------------------ diff --git poppler/Annot.h poppler/Annot.h index 02311cb..166db7d 100644 --- poppler/Annot.h +++ poppler/Annot.h @@ -57,6 +57,7 @@ class Movie; class LinkAction; class Sound; class FileSpec; +class Artwork3D; enum AnnotLineEndingStyle { annotLineEndingSquare, // Square @@ -1403,11 +1404,14 @@ public: // getters + Artwork3D *getArtwork() const; + private: void initialize(PDFDoc *docA, Dict *dict); Activation *activation; // 3DA + Artwork3D *artwork; // 3DD }; //------------------------------------------------------------------------ diff --git poppler/Artwork3D.cc poppler/Artwork3D.cc new file mode 100644 index 0000000..9fd3514 --- /dev/null +++ poppler/Artwork3D.cc @@ -0,0 +1,62 @@ +/* Artwork3D.cc - Intermediate buffer for 3DD binary object (adapted from Sound.cc) + * Copyright (C) 2006-2007, Pino Toscano <[email protected]> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This program 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 + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include "Object.h" +#include "Artwork3D.h" +#include "Stream.h" + +Artwork3D::Artwork3D(Object *obj) +{ + streamObj = new Object(); + streamObj->initNull(); + obj->copy(streamObj); +} + +Artwork3D::~Artwork3D() +{ + streamObj->free(); + delete streamObj; +} + +Stream *Artwork3D::getStream() +{ + return streamObj->getStream(); +} + +Artwork3D *Artwork3D::copy() +{ + Artwork3D *newartwork = new Artwork3D(streamObj); + + return newartwork; +} + +Artwork3DKind Artwork3D::getKind() +{ + Object obj1; + streamObj->getDict()->lookup("Subtype", &obj1); + if (obj1.isName("U3D")) { + obj1.free(); + return artwork3d_U3D; + } else if (obj1.isName("PRC")) { + obj1.free(); + return artwork3d_PRC; + } + obj1.free(); + return artwork3d_UnknownKind; +} + diff --git poppler/Artwork3D.h poppler/Artwork3D.h new file mode 100644 index 0000000..379fdca --- /dev/null +++ poppler/Artwork3D.h @@ -0,0 +1,39 @@ +/* Artwork3D.h - Intermediate buffer for 3DD objects (adapted from Sound.h) + * Copyright (C) 2006-2007, Pino Toscano <[email protected]> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This program 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 + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef Artwork3D_H +#define Artwork3D_H + +enum Artwork3DKind { + artwork3d_UnknownKind, + artwork3d_U3D, + artwork3d_PRC +}; + +class Artwork3D +{ + Object *streamObj; +public: + Artwork3D(Object *obj); + ~Artwork3D(); + Stream *getStream(); + Artwork3D *copy(); + Artwork3DKind getKind(); +}; + +#endif _______________________________________________ poppler mailing list [email protected] https://lists.freedesktop.org/mailman/listinfo/poppler
