[dia] New std-prop 'pixbuf': preparation of embedding image data



commit ca269a01119195b204db4974fe6eb4add5001f62
Author: Hans Breuer <hans breuer org>
Date:   Sat Aug 14 19:42:00 2010 +0200

    New std-prop 'pixbuf': preparation of embedding image data
    
    A bitmap editor is not yet built in but may come later;)
    Also it is not yet used anywhere, but that's coming with
    the next commit.

 lib/Makefile.am     |    2 +
 lib/dia_xml.c       |    2 +
 lib/dia_xml.h       |    6 +-
 lib/libdia.def      |    4 +
 lib/makefile.msc    |    1 +
 lib/prop_pixbuf.c   |  268 +++++++++++++++++++++++++++++++++++++++++++++++++++
 lib/prop_pixbuf.h   |   41 ++++++++
 lib/properties.c    |    1 +
 lib/properties.h    |    1 +
 lib/propinternals.h |    1 +
 10 files changed, 326 insertions(+), 1 deletions(-)
---
diff --git a/lib/Makefile.am b/lib/Makefile.am
index 0cf7bf2..424735d 100644
--- a/lib/Makefile.am
+++ b/lib/Makefile.am
@@ -14,6 +14,8 @@ stdprop_files = \
 	prop_basic.h \
 	prop_dict.c \
 	prop_dict.h \
+	prop_pixbuf.c \
+	prop_pixbuf.h \
 	prop_inttypes.c \
 	prop_inttypes.h \
 	prop_geomtypes.c \
diff --git a/lib/dia_xml.c b/lib/dia_xml.c
index 096e9e3..9cef604 100644
--- a/lib/dia_xml.c
+++ b/lib/dia_xml.c
@@ -424,6 +424,8 @@ data_type(DataNode data)
     return DATATYPE_BEZPOINT;
   } else if (strcmp(name, "dict")==0) {
     return DATATYPE_DICT;
+  } else if (strcmp(name, "pixbuf")==0) {
+    return DATATYPE_PIXBUF;
   }
 
   message_error("Unknown type of DataNode");
diff --git a/lib/dia_xml.h b/lib/dia_xml.h
index f6082e0..faff1cb 100644
--- a/lib/dia_xml.h
+++ b/lib/dia_xml.h
@@ -58,7 +58,8 @@ typedef enum{
   DATATYPE_STRING,
   DATATYPE_FONT,
   DATATYPE_BEZPOINT,
-  DATATYPE_DICT
+  DATATYPE_DICT,
+  DATATYPE_PIXBUF
 } DataType;
 
 AttributeNode object_find_attribute(ObjectNode obj_node,
@@ -101,5 +102,8 @@ DataNode data_add_composite(AttributeNode attr,
 GHashTable *data_dict (DataNode data);
 void data_add_dict (AttributeNode attr, GHashTable *data);
 
+GdkPixbuf *data_pixbuf (DataNode data);
+void data_add_pixbuf (AttributeNode attr, GdkPixbuf *pixbuf);
+
 #endif /* DIA_XML_H */
 
diff --git a/lib/libdia.def b/lib/libdia.def
index f344af1..454d546 100644
--- a/lib/libdia.def
+++ b/lib/libdia.def
@@ -130,11 +130,13 @@ EXPORTS
  data_add_color
  data_add_composite
  data_add_enum
+ data_add_dict
  data_add_filename
  data_add_font
  data_add_int
  data_add_layer
  data_add_layer_at
+ data_add_pixbuf
  data_add_point
  data_add_bezpoint
  data_add_real
@@ -143,6 +145,7 @@ EXPORTS
  data_boolean
  data_color
  data_delete_layer
+ data_dict
  data_emit
  data_enum
  data_filename
@@ -159,6 +162,7 @@ EXPORTS
  data_layer_get_nth
  data_lower_layer
  data_next
+ data_pixbuf
  data_point
  data_bezpoint
  data_raise_layer
diff --git a/lib/makefile.msc b/lib/makefile.msc
index 6a863f7..1103d8b 100644
--- a/lib/makefile.msc
+++ b/lib/makefile.msc
@@ -95,6 +95,7 @@ OBJECTS = \
 	prop_dict.obj \
 	prop_geomtypes.obj \
 	prop_inttypes.obj \
+	prop_pixbuf.obj \
 	prop_sdarray.obj \
 	prop_text.obj \
 	prop_widgets.obj \
diff --git a/lib/prop_pixbuf.c b/lib/prop_pixbuf.c
new file mode 100644
index 0000000..9d174b6
--- /dev/null
+++ b/lib/prop_pixbuf.c
@@ -0,0 +1,268 @@
+/* Dia -- a diagram creation/manipulation program -*- c -*-
+ * Copyright (C) 1998 Alexander Larsson
+ *
+ * Property system for dia objects/shapes.
+ * Copyright (C) 2000 James Henstridge
+ * Copyright (C) 2001 Cyrille Chepelov
+ *
+ * Copyright (C) 2010 Hans Breuer
+ * Property types for pixbuf.
+ *
+ * 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 of the License, 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+#include <config.h>
+
+#include <gtk/gtk.h>
+#define WIDGET GtkWidget
+#include "widgets.h"
+#include "properties.h"
+#include "propinternals.h"
+#include "message.h"
+
+static PixbufProperty *
+pixbufprop_new(const PropDescription *pdesc, PropDescToPropPredicate reason)
+{
+  PixbufProperty *prop = g_new0(PixbufProperty,1);
+
+  initialize_property(&prop->common, pdesc, reason);
+  /* empty by default */
+  prop->pixbuf = NULL;
+
+  return prop;
+}
+
+static void
+pixbufprop_free(PixbufProperty *prop) 
+{
+  if (prop->pixbuf)
+    g_object_unref(prop->pixbuf);
+  g_free(prop);
+} 
+
+static PixbufProperty *
+pixbufprop_copy(PixbufProperty *src) 
+{
+  PixbufProperty *prop = 
+    (PixbufProperty *)src->common.ops->new_prop(src->common.descr,
+                                              src->common.reason);
+  if (src->pixbuf) /* TODO: rething on edit - gdk_pixbuf_copy() ? */
+    prop->pixbuf = g_object_ref (src->pixbuf);
+
+  return prop;
+}
+
+GdkPixbuf *
+data_pixbuf (DataNode data)
+{
+  GdkPixbuf *pixbuf = NULL;
+  GdkPixbufLoader *loader;
+  GError *error = NULL;
+  AttributeNode attr = composite_find_attribute(data, "data");
+
+  loader = gdk_pixbuf_loader_new ();
+  if (loader) {
+    xmlNode *node = attribute_first_data (attr);
+    gint state = 0;
+    guint save = 0;
+#  define BUF_SIZE 4096
+    guchar buf[BUF_SIZE];
+    guchar *in = NULL; /* direct access, not involving another xmlStrDup/xmlFree */
+    gssize len = 0;
+
+    if (node->children && xmlStrcmp (node->children->name, "text") == 0) {
+      in = node->children->content;
+      len = strlen (in);
+    }
+
+    do {
+      gsize step = g_base64_decode_step (in,
+					 len > BUF_SIZE ? BUF_SIZE : len,
+					 buf, &state, &save);
+
+      if (!gdk_pixbuf_loader_write (loader, buf, step, &error))
+	break;
+
+      in += BUF_SIZE;
+      len -= BUF_SIZE;
+    } while (len > 0);
+    if (gdk_pixbuf_loader_close (loader, error ? NULL : &error)) {
+      pixbuf = g_object_ref (gdk_pixbuf_loader_get_pixbuf (loader));
+    } else {
+      message_warning ("%s", error->message);
+      g_error_free (error);
+    }
+
+    g_object_unref (loader);
+  }
+#  undef BUF_SIZE
+  return pixbuf;
+}
+
+static void 
+pixbufprop_load(PixbufProperty *prop, AttributeNode attr, DataNode data)
+{
+  prop->pixbuf = data_pixbuf (data);
+}
+
+typedef struct _EncodeData {
+  GByteArray *array;
+  
+  gsize size;
+
+  gint state;
+  gint save;
+} EncodeData;
+static gboolean
+_pixbuf_encode (const gchar *buf,
+		gsize count,
+		GError **error,
+		gpointer data)
+{
+  EncodeData *ed = data;
+  gsize size;
+  guint old_len;
+  gsize growth = (count / 3 + 1) * 4 + 4 + ((count / 3 + 1) * 4 + 4) / 72 + 1;
+  guchar *out;
+
+  old_len = ed->array->len;
+  g_byte_array_set_size (ed->array, ed->size + growth);
+  out = &ed->array->data[ed->size];
+  ed->size += g_base64_encode_step (buf, count, TRUE, out, &ed->state, &ed->save);
+
+  return TRUE;
+}
+void
+data_add_pixbuf (AttributeNode attr, GdkPixbuf *pixbuf)
+{
+  ObjectNode composite = data_add_composite(attr, "pixbuf");
+  AttributeNode comp_attr = composite_add_attribute (composite, "data");
+  GError *error = NULL;
+  EncodeData ed = { 0, };
+
+  ed.array = g_byte_array_new ();
+
+  if (!gdk_pixbuf_save_to_callback (pixbuf, _pixbuf_encode, &ed, "png", &error, NULL)) {
+    message_error (_("Saving inline pixbuf failed:\n%s"), error->message);
+    g_error_free (error);
+    return;
+  }
+  /* FIXME: is there enough space for the rest? */
+  ed.size += g_base64_encode_close (TRUE, &ed.array->data[ed.size], &ed.state, &ed.save);
+  /* is the array 0-terminated? */
+  if (ed.array->data[ed.size] != 0) {
+    g_byte_array_append (ed.array, "\0", 1);
+    ed.array->data[ed.size] = '\0';
+  }
+  (void)xmlNewChild (comp_attr, NULL, "data", ed.array->data);
+
+  g_byte_array_free (ed.array, TRUE);
+}
+
+static void 
+pixbufprop_save(PixbufProperty *prop, AttributeNode attr) 
+{
+  if (prop->pixbuf) {
+    data_add_pixbuf (attr, prop->pixbuf);
+  }
+}
+
+static void 
+pixbufprop_get_from_offset(PixbufProperty *prop,
+                         void *base, guint offset, guint offset2) 
+{
+  /* before we start editing a simple refernce should be enough */
+  GdkPixbuf *pixbuf = struct_member(base,offset,GdkPixbuf *);
+
+  if (pixbuf)
+    prop->pixbuf = g_object_ref (pixbuf);
+  else
+    prop->pixbuf = NULL;
+}
+
+static void 
+pixbufprop_set_from_offset(PixbufProperty *prop,
+                           void *base, guint offset, guint offset2)
+{
+  GdkPixbuf *dest = struct_member(base,offset,GdkPixbuf *);
+  if (dest)
+    g_object_unref (dest);
+  if (prop->pixbuf)
+    struct_member(base,offset, GdkPixbuf *) = g_object_ref (prop->pixbuf);
+  else
+    struct_member(base,offset, GdkPixbuf *) = NULL;
+}
+
+/* GUI stuff - not yet 
+   - allow to crop
+   - maybe scale
+ */
+static void
+_pixbuf_toggled(GtkWidget *wid)
+{
+  if (GTK_TOGGLE_BUTTON(wid)->active)
+    gtk_label_set_text(GTK_LABEL(GTK_BIN(wid)->child), _("Yes"));
+  else
+    gtk_label_set_text(GTK_LABEL(GTK_BIN(wid)->child), _("No"));
+}
+
+static GtkWidget *
+pixbufprop_get_widget (PixbufProperty *prop, PropDialog *dialog) 
+{ 
+  GtkWidget *ret = gtk_toggle_button_new_with_label(_("No"));
+  g_signal_connect(G_OBJECT(ret), "toggled",
+                   G_CALLBACK (_pixbuf_toggled), NULL);
+  prophandler_connect(&prop->common, G_OBJECT(ret), "toggled");
+  return ret;
+}
+
+static void 
+pixbufprop_reset_widget(PixbufProperty *prop, GtkWidget *widget)
+{
+  gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(widget),prop->pixbuf != NULL);
+}
+
+static void 
+pixbufprop_set_from_widget(PixbufProperty *prop, GtkWidget *widget) 
+{
+  if (GTK_TOGGLE_BUTTON(widget)->active) {
+    if (!prop->pixbuf)
+      message_warning (_("Cant create image data from scratch!"));
+  } else {
+    if (prop->pixbuf)
+      g_object_unref (prop->pixbuf);
+    prop->pixbuf = NULL;
+  }
+}
+
+static const PropertyOps pixbufprop_ops = {
+  (PropertyType_New) pixbufprop_new,
+  (PropertyType_Free) pixbufprop_free,
+  (PropertyType_Copy) pixbufprop_copy,
+  (PropertyType_Load) pixbufprop_load,
+  (PropertyType_Save) pixbufprop_save,
+  (PropertyType_GetWidget) pixbufprop_get_widget,
+  (PropertyType_ResetWidget) pixbufprop_reset_widget,
+  (PropertyType_SetFromWidget) pixbufprop_set_from_widget,
+
+  (PropertyType_CanMerge) noopprop_can_merge,
+  (PropertyType_GetFromOffset) pixbufprop_get_from_offset,
+  (PropertyType_SetFromOffset) pixbufprop_set_from_offset
+};
+
+void 
+prop_pixbuftypes_register(void)
+{
+  prop_type_register(PROP_TYPE_PIXBUF, &pixbufprop_ops);
+}
diff --git a/lib/prop_pixbuf.h b/lib/prop_pixbuf.h
new file mode 100644
index 0000000..e82daaf
--- /dev/null
+++ b/lib/prop_pixbuf.h
@@ -0,0 +1,41 @@
+/* Dia -- a diagram creation/manipulation program -*- c -*-
+ * Copyright (C) 1998 Alexander Larsson
+ *
+ * Property system for dia objects/shapes.
+ * Copyright (C) 2000 James Henstridge
+ * Copyright (C) 2001 Cyrille Chepelov
+ * Major restructuration done in August 2001 by C. Chepelov
+ *
+ * Copyright (C) 2010 Hans Breuer
+ * Property types for pixbuf.
+ *
+ * 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 of the License, 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+#ifndef PROP_PIXBUF_H
+#define PROP_PIXBUF_H
+
+#include <gdk-pixbuf/gdk-pixbuf.h>
+
+#include "properties.h"
+#include "dia_xml.h"
+
+typedef struct {
+  Property common;
+  GdkPixbuf *pixbuf; /* just the reference */
+} PixbufProperty;
+
+void prop_pixbuftypes_register(void);
+
+#endif /* PROP_PIXBUF_H */
diff --git a/lib/properties.c b/lib/properties.c
index 8f8c5b2..ce568ba 100644
--- a/lib/properties.c
+++ b/lib/properties.c
@@ -51,6 +51,7 @@ stdprops_init(void)
   prop_widgets_register();
   prop_sdarray_register();
   prop_dicttypes_register();
+  prop_pixbuftypes_register();
 }
 
 /* --------------------------------------- */
diff --git a/lib/properties.h b/lib/properties.h
index 7e2071d..fcf89c6 100644
--- a/lib/properties.h
+++ b/lib/properties.h
@@ -198,6 +198,7 @@ typedef const gchar *PropertyType;
 #define PROP_TYPE_SARRAY "sarray" /* ArrayProperty */
 #define PROP_TYPE_DARRAY "darray" /* ArrayProperty */
 #define PROP_TYPE_DICT "dict" /* DictProperty */
+#define PROP_TYPE_PIXBUF "pixbuf" /* PixbufProperty */
 
 /* **************************************************************** */
 
diff --git a/lib/propinternals.h b/lib/propinternals.h
index c20fccf..728e7e1 100644
--- a/lib/propinternals.h
+++ b/lib/propinternals.h
@@ -86,6 +86,7 @@ void do_get_props_from_offsets(void *base, GPtrArray *props,
 #include "prop_widgets.h"
 #include "prop_sdarray.h"
 #include "prop_dict.h"
+#include "prop_pixbuf.h"
 
 #endif /* PROPINTERNALS_H */
 



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]