[poppler] [Patch] Add 3DPDF interface to glib frontend

IHARA Hiroka ihara_h at live.jp
Wed Sep 14 15:36:14 UTC 2016


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: ihara_h at live.jp

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 <carlosgc at gnome.org>
+ *
+ * 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 <carlosgc at gnome.org>
+ *
+ * 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 <pino at kde.org>
+ *
+ * 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 <pino at kde.org>
+ *
+ * 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



More information about the poppler mailing list