[xournal] #827922 - image insertion patch
Jaromír Cápík
jcapik at fedoraproject.org
Mon Jul 9 17:22:59 UTC 2012
commit 9b61d4357ee6ad84d17ea21189af1eb1e1a9786a
Author: Jaromir Capik <jcapik at redhat.com>
Date: Mon Jul 9 19:22:47 2012 +0200
#827922 - image insertion patch
xournal-0.4.5-sjg-image-rev7.patch | 3110 ++++++++++++++++++++++++++++++++++++
xournal.spec | 8 +-
2 files changed, 3117 insertions(+), 1 deletions(-)
---
diff --git a/xournal-0.4.5-sjg-image-rev7.patch b/xournal-0.4.5-sjg-image-rev7.patch
new file mode 100644
index 0000000..a3be178
--- /dev/null
+++ b/xournal-0.4.5-sjg-image-rev7.patch
@@ -0,0 +1,3110 @@
+# This is a patch for xournal-0.4.5 to update it to xournal
+#
+# To apply this patch:
+# STEP 1: Chdir to the source directory.
+# STEP 2: Run the 'applypatch' program with this patch file as input.
+#
+# If you do not have 'applypatch', it is part of the 'makepatch' package
+# that you can fetch from the Comprehensive Perl Archive Network:
+# http://www.perl.com/CPAN/authors/Johan_Vromans/makepatch-x.y.tar.gz
+# In the above URL, 'x' should be 2 or higher.
+#
+# To apply this patch without the use of 'applypatch':
+# STEP 1: Chdir to the source directory.
+# If you have a decent Bourne-type shell:
+# STEP 2: Run the shell with this file as input.
+# If you don't have such a shell, you may need to manually create
+# the files as shown below.
+# STEP 3: Run the 'patch' program with this file as input.
+#
+# These are the commands needed to create/delete files/directories:
+#
+touch './README.image'
+chmod 0644 './README.image'
+touch './src/xo-clipboard.c'
+chmod 0644 './src/xo-clipboard.c'
+touch './src/xo-clipboard.h'
+chmod 0644 './src/xo-clipboard.h'
+touch './src/xo-image.c'
+chmod 0644 './src/xo-image.c'
+touch './src/xo-image.h'
+chmod 0644 './src/xo-image.h'
+#
+# This command terminates the shell and need not be executed manually.
+exit
+#
+#### End of Preamble ####
+
+#### Patch data follows ####
+diff -c /dev/null 'xournal/README.image'
+Index: ./README.image
+*** ./README.image Thu Jan 1 12:00:00 1970
+--- ./README.image Thu Apr 15 17:16:44 2010
+***************
+*** 0 ****
+--- 1,19 ----
++ This paste image patch is based on Victor Saase's insert image patch,
++ with grateful thanks to Victor for making a good start.
++
++ This patch is to be applied to a vanilla xournal-0.4.5.
++
++ This patch therefore contains Victor's changes, and also:
++
++ + images are now stored in the journal file, inline in the XML, as
++ base64 encoded PNGs.
++ + images can be pasted in from the clipboard
++ + copy and paste of images works within the application
++ + export of image with PDF now works
++
++ I also fixed this bug:
++
++ + free pixbufs using g_object_unref not g_free.
++
++
++ Simon Guest 14/4/10
+diff -c 'xournal-0.4.5/src/Makefile.am' 'xournal/src/Makefile.am'
+Index: ./src/Makefile.am
+*** ./src/Makefile.am Tue Sep 22 03:24:32 2009
+--- ./src/Makefile.am Thu Apr 15 17:22:24 2010
+***************
+*** 12,17 ****
+--- 12,19 ----
+ xournal_SOURCES = \
+ main.c xournal.h \
+ xo-misc.c xo-misc.h \
++ xo-clipboard.c xo-clipboard.h \
++ xo-image.c xo-image.h \
+ xo-file.c xo-file.h \
+ xo-paint.c xo-paint.h \
+ xo-print.c xo-print.h \
+diff -c 'xournal-0.4.5/src/Makefile.in' 'xournal/src/Makefile.in'
+Index: ./src/Makefile.in
+*** ./src/Makefile.in Fri Oct 2 19:42:14 2009
+--- ./src/Makefile.in Thu Apr 15 17:27:17 2010
+***************
+*** 1,4 ****
+! # Makefile.in generated by automake 1.11 from Makefile.am.
+ # @configure_input@
+
+ # Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
+--- 1,4 ----
+! # Makefile.in generated by automake 1.11.1 from Makefile.am.
+ # @configure_input@
+
+ # Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
+***************
+*** 46,54 ****
+ am__installdirs = "$(DESTDIR)$(bindir)"
+ PROGRAMS = $(bin_PROGRAMS)
+ am_xournal_OBJECTS = main.$(OBJEXT) xo-misc.$(OBJEXT) \
+! xo-file.$(OBJEXT) xo-paint.$(OBJEXT) xo-print.$(OBJEXT) \
+! xo-support.$(OBJEXT) xo-interface.$(OBJEXT) \
+! xo-callbacks.$(OBJEXT) xo-shapes.$(OBJEXT)
+ xournal_OBJECTS = $(am_xournal_OBJECTS)
+ am__DEPENDENCIES_1 =
+ xournal_DEPENDENCIES = ttsubset/libttsubset.a $(am__DEPENDENCIES_1)
+--- 46,55 ----
+ am__installdirs = "$(DESTDIR)$(bindir)"
+ PROGRAMS = $(bin_PROGRAMS)
+ am_xournal_OBJECTS = main.$(OBJEXT) xo-misc.$(OBJEXT) \
+! xo-clipboard.$(OBJEXT) xo-image.$(OBJEXT) xo-file.$(OBJEXT) \
+! xo-paint.$(OBJEXT) xo-print.$(OBJEXT) xo-support.$(OBJEXT) \
+! xo-interface.$(OBJEXT) xo-callbacks.$(OBJEXT) \
+! xo-shapes.$(OBJEXT)
+ xournal_OBJECTS = $(am_xournal_OBJECTS)
+ am__DEPENDENCIES_1 =
+ xournal_DEPENDENCIES = ttsubset/libttsubset.a $(am__DEPENDENCIES_1)
+***************
+*** 154,159 ****
+--- 155,161 ----
+ PACKAGE_NAME = @PACKAGE_NAME@
+ PACKAGE_STRING = @PACKAGE_STRING@
+ PACKAGE_TARNAME = @PACKAGE_TARNAME@
++ PACKAGE_URL = @PACKAGE_URL@
+ PACKAGE_VERSION = @PACKAGE_VERSION@
+ PATH_SEPARATOR = @PATH_SEPARATOR@
+ PKG_CONFIG = @PKG_CONFIG@
+***************
+*** 219,224 ****
+--- 221,228 ----
+ xournal_SOURCES = \
+ main.c xournal.h \
+ xo-misc.c xo-misc.h \
++ xo-clipboard.c xo-clipboard.h \
++ xo-image.c xo-image.h \
+ xo-file.c xo-file.h \
+ xo-paint.c xo-paint.h \
+ xo-print.c xo-print.h \
+***************
+*** 311,317 ****
+--- 315,323 ----
+
+ @AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/main.Po at am__quote@
+ @AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/xo-callbacks.Po at am__quote@
++ @AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/xo-clipboard.Po at am__quote@
+ @AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/xo-file.Po at am__quote@
++ @AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/xo-image.Po at am__quote@
+ @AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/xo-interface.Po at am__quote@
+ @AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/xo-misc.Po at am__quote@
+ @AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/xo-paint.Po at am__quote@
+***************
+*** 340,346 ****
+ # (which will cause the Makefiles to be regenerated when you run `make');
+ # (2) otherwise, pass the desired values on the `make' command line.
+ $(RECURSIVE_TARGETS):
+! @failcom='exit 1'; \
+ for f in x $$MAKEFLAGS; do \
+ case $$f in \
+ *=* | --[!k]*);; \
+--- 346,352 ----
+ # (which will cause the Makefiles to be regenerated when you run `make');
+ # (2) otherwise, pass the desired values on the `make' command line.
+ $(RECURSIVE_TARGETS):
+! @fail= failcom='exit 1'; \
+ for f in x $$MAKEFLAGS; do \
+ case $$f in \
+ *=* | --[!k]*);; \
+***************
+*** 365,371 ****
+ fi; test -z "$$fail"
+
+ $(RECURSIVE_CLEAN_TARGETS):
+! @failcom='exit 1'; \
+ for f in x $$MAKEFLAGS; do \
+ case $$f in \
+ *=* | --[!k]*);; \
+--- 371,377 ----
+ fi; test -z "$$fail"
+
+ $(RECURSIVE_CLEAN_TARGETS):
+! @fail= failcom='exit 1'; \
+ for f in x $$MAKEFLAGS; do \
+ case $$f in \
+ *=* | --[!k]*);; \
+diff -c 'xournal-0.4.5/src/TODO' 'xournal/src/TODO'
+Index: ./src/TODO
+*** ./src/TODO Sat Oct 3 12:20:35 2009
+--- ./src/TODO Fri May 14 17:59:39 2010
+***************
+*** 138,145 ****
+ - copy/paste of an entire page (beware if PDF bg is not compatible!)
+ - rewrite printing using GtkPrint + Cairo as GnomePrint replacement
+ (keep GnomePrint option for compatibility with GTK+ <2.10)
+- - insert images (screen capture or from file or from clipboard),
+- not as full-page backgrounds (new ITEM type)
+
+ - convert to/from Jarnal format; to/from MS Journal format???
+ - export as SVG, as bitmap (use Cairo for this)
+--- 138,143 ----
+diff -c 'xournal-0.4.5/src/main.c' 'xournal/src/main.c'
+Index: ./src/main.c
+*** ./src/main.c Mon Sep 28 11:08:34 2009
+--- ./src/main.c Sun Jun 27 16:22:44 2010
+***************
+*** 287,292 ****
+--- 287,295 ----
+ g_free(tmpfn);
+ set_cursor_busy(FALSE);
+ if (!success) {
++ #ifdef IMAGE_DEBUG
++ printf("error opening file '%s'\n",argv[1]);
++ #endif
+ w = gtk_message_dialog_new(GTK_WINDOW (winMain), GTK_DIALOG_DESTROY_WITH_PARENT,
+ GTK_MESSAGE_ERROR, GTK_BUTTONS_OK, _("Error opening file '%s'"), argv[1]);
+ gtk_dialog_run(GTK_DIALOG(w));
+diff -c 'xournal-0.4.5/src/xo-callbacks.c' 'xournal/src/xo-callbacks.c'
+Index: ./src/xo-callbacks.c
+*** ./src/xo-callbacks.c Tue Sep 29 12:42:49 2009
+--- ./src/xo-callbacks.c Thu Jun 24 20:32:09 2010
+***************
+*** 452,458 ****
+ if (undo == NULL) return; // nothing to undo!
+ reset_selection(); // safer
+ reset_recognizer(); // safer
+! if (undo->type == ITEM_STROKE || undo->type == ITEM_TEXT) {
+ // we're keeping the stroke info, but deleting the canvas item
+ gtk_object_destroy(GTK_OBJECT(undo->item->canvas_item));
+ undo->item->canvas_item = NULL;
+--- 452,458 ----
+ if (undo == NULL) return; // nothing to undo!
+ reset_selection(); // safer
+ reset_recognizer(); // safer
+! if (undo->type == ITEM_STROKE || undo->type == ITEM_TEXT || undo->type == ITEM_IMAGE) {
+ // we're keeping the stroke info, but deleting the canvas item
+ gtk_object_destroy(GTK_OBJECT(undo->item->canvas_item));
+ undo->item->canvas_item = NULL;
+***************
+*** 666,672 ****
+ if (redo == NULL) return; // nothing to redo!
+ reset_selection(); // safer
+ reset_recognizer(); // safer
+! if (redo->type == ITEM_STROKE || redo->type == ITEM_TEXT) {
+ // re-create the canvas_item
+ make_canvas_item_one(redo->layer->group, redo->item);
+ // reinsert the item on its layer
+--- 666,672 ----
+ if (redo == NULL) return; // nothing to redo!
+ reset_selection(); // safer
+ reset_recognizer(); // safer
+! if (redo->type == ITEM_STROKE || redo->type == ITEM_TEXT || redo->type == ITEM_IMAGE) {
+ // re-create the canvas_item
+ make_canvas_item_one(redo->layer->group, redo->item);
+ // reinsert the item on its layer
+***************
+*** 824,829 ****
+--- 824,835 ----
+ if (it->type == ITEM_TEXT && it->canvas_item != NULL)
+ gnome_canvas_item_set(it->canvas_item,
+ "fill-color-rgba", it->brush.color_rgba, NULL);
++ if (it->type == ITEM_IMAGE && it->canvas_item != NULL) {
++ // remark: a variable-width item might have lost its variable-width
++ group = (GnomeCanvasGroup *) it->canvas_item->parent;
++ gtk_object_destroy(GTK_OBJECT(it->canvas_item));
++ make_canvas_item_one(group, it);
++ }
+ }
+ }
+ else if (redo->type == ITEM_TEXT_EDIT) {
+***************
+*** 946,951 ****
+--- 952,958 ----
+ gnome_canvas_set_pixels_per_unit(canvas, ui.zoom);
+ rescale_text_items();
+ rescale_bg_pixmaps();
++ rescale_images();
+ }
+
+
+***************
+*** 958,963 ****
+--- 965,971 ----
+ gnome_canvas_set_pixels_per_unit(canvas, ui.zoom);
+ rescale_text_items();
+ rescale_bg_pixmaps();
++ rescale_images();
+ }
+
+
+***************
+*** 969,974 ****
+--- 977,983 ----
+ gnome_canvas_set_pixels_per_unit(canvas, ui.zoom);
+ rescale_text_items();
+ rescale_bg_pixmaps();
++ rescale_images();
+ }
+
+
+***************
+*** 980,985 ****
+--- 989,995 ----
+ gnome_canvas_set_pixels_per_unit(canvas, ui.zoom);
+ rescale_text_items();
+ rescale_bg_pixmaps();
++ rescale_images();
+ }
+
+
+***************
+*** 1539,1544 ****
+--- 1549,1555 ----
+ gnome_canvas_set_pixels_per_unit(canvas, ui.zoom);
+ rescale_text_items();
+ rescale_bg_pixmaps();
++ rescale_images();
+ }
+ do_switch_page(ui.pageno, TRUE, TRUE);
+ }
+***************
+*** 1585,1590 ****
+--- 1596,1602 ----
+ gnome_canvas_set_pixels_per_unit(canvas, ui.zoom);
+ rescale_text_items();
+ rescale_bg_pixmaps();
++ rescale_images();
+ }
+ do_switch_page(ui.pageno, TRUE, TRUE);
+ }
+***************
+*** 1747,1752 ****
+--- 1759,1790 ----
+ update_cursor();
+ }
+
++ void
++ on_toolsImage_activate (GtkMenuItem *menuitem,
++ gpointer user_data)
++ {
++ if (GTK_OBJECT_TYPE(menuitem) == GTK_TYPE_RADIO_MENU_ITEM) {
++ if (!gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM (menuitem)))
++ return;
++ } else {
++ if (!gtk_toggle_tool_button_get_active(GTK_TOGGLE_TOOL_BUTTON (menuitem)))
++ return;
++ }
++
++ if (ui.cur_mapping != 0 && !ui.button_switch_mapping) return; // not user-generated
++ if (ui.toolno[ui.cur_mapping] == TOOL_IMAGE) return;
++
++ ui.cur_mapping = 0; // don't use switch_mapping() (refreshes buttons too soon)
++ reset_selection();
++ ui.toolno[ui.cur_mapping] = TOOL_IMAGE;
++ ui.cur_brush = &(ui.brushes[ui.cur_mapping][TOOL_PEN]);
++ update_mapping_linkings(-1);
++ update_tool_buttons();
++ update_tool_menu();
++ update_color_menu();
++ update_cursor();
++ }
++
+
+ void
+ on_toolsSelectRegion_activate (GtkMenuItem *menuitem,
+***************
+*** 2321,2328 ****
+ gpointer user_data)
+ {
+ double pt[2];
+- gboolean page_change;
+- struct Page *tmppage;
+ GtkWidget *dialog;
+ int mapping;
+ gboolean is_core;
+--- 2359,2364 ----
+***************
+*** 2407,2430 ****
+ else mapping = event->button-1;
+
+ // check whether we're in a page
+- page_change = FALSE;
+- tmppage = ui.cur_page;
+ get_pointer_coords((GdkEvent *)event, pt);
+! while (ui.view_continuous && (pt[1] < - VIEW_CONTINUOUS_SKIP)) {
+! if (ui.pageno == 0) break;
+! page_change = TRUE;
+! ui.pageno--;
+! tmppage = g_list_nth_data(journal.pages, ui.pageno);
+! pt[1] += tmppage->height + VIEW_CONTINUOUS_SKIP;
+! }
+! while (ui.view_continuous && (pt[1] > tmppage->height + VIEW_CONTINUOUS_SKIP)) {
+! if (ui.pageno == journal.npages-1) break;
+! pt[1] -= tmppage->height + VIEW_CONTINUOUS_SKIP;
+! page_change = TRUE;
+! ui.pageno++;
+! tmppage = g_list_nth_data(journal.pages, ui.pageno);
+! }
+! if (page_change) do_switch_page(ui.pageno, FALSE, FALSE);
+
+ // can't paint on the background...
+
+--- 2443,2450 ----
+ else mapping = event->button-1;
+
+ // check whether we're in a page
+ get_pointer_coords((GdkEvent *)event, pt);
+! set_current_page(pt);
+
+ // can't paint on the background...
+
+***************
+*** 2487,2492 ****
+--- 2507,2515 ----
+ else if (ui.toolno[mapping] == TOOL_TEXT) {
+ start_text((GdkEvent *)event, NULL);
+ }
++ else if (ui.toolno[mapping] == TOOL_IMAGE) {
++ insert_image((GdkEvent *)event, NULL);
++ }
+ return FALSE;
+ }
+
+***************
+*** 2665,2671 ****
+ or if there's a selection (then we might want to change the mouse
+ cursor to indicate the possibility of resizing) */
+ if (ui.cur_item_type == ITEM_NONE && ui.selection==NULL) return FALSE;
+! if (ui.cur_item_type == ITEM_TEXT) return FALSE;
+
+ is_core = (event->device == gdk_device_get_core_pointer());
+ if (!ui.use_xinput && !is_core) return FALSE;
+--- 2688,2694 ----
+ or if there's a selection (then we might want to change the mouse
+ cursor to indicate the possibility of resizing) */
+ if (ui.cur_item_type == ITEM_NONE && ui.selection==NULL) return FALSE;
+! if (ui.cur_item_type == ITEM_TEXT || ui.cur_item_type == ITEM_IMAGE) return FALSE;
+
+ is_core = (event->device == gdk_device_get_core_pointer());
+ if (!ui.use_xinput && !is_core) return FALSE;
+***************
+*** 3340,3345 ****
+--- 3363,3369 ----
+ gnome_canvas_set_pixels_per_unit(canvas, ui.zoom);
+ rescale_text_items();
+ rescale_bg_pixmaps();
++ rescale_images();
+ }
+ } while (response == GTK_RESPONSE_APPLY);
+
+diff -c 'xournal-0.4.5/src/xo-callbacks.h' 'xournal/src/xo-callbacks.h'
+Index: ./src/xo-callbacks.h
+*** ./src/xo-callbacks.h Tue Sep 29 12:43:34 2009
+--- ./src/xo-callbacks.h Mon Mar 22 11:39:25 2010
+***************
+*** 211,216 ****
+--- 211,220 ----
+ void
+ on_toolsText_activate (GtkMenuItem *menuitem,
+ gpointer user_data);
++
++ void
++ on_toolsImage_activate (GtkMenuItem *menuitem,
++ gpointer user_data);
+
+ void
+ on_toolsSelectRegion_activate (GtkMenuItem *menuitem,
+diff -c /dev/null 'xournal/src/xo-clipboard.c'
+Index: ./src/xo-clipboard.c
+*** ./src/xo-clipboard.c Thu Jan 1 12:00:00 1970
+--- ./src/xo-clipboard.c Thu Jul 29 19:56:43 2010
+***************
+*** 0 ****
+--- 1,304 ----
++ #ifdef HAVE_CONFIG_H
++ # include <config.h>
++ #endif
++
++ #include <string.h>
++ #include <gtk/gtk.h>
++
++ #include "xournal.h"
++ #include "xo-callbacks.h"
++ #include "xo-interface.h"
++ #include "xo-support.h"
++ #include "xo-misc.h"
++ #include "xo-paint.h"
++ #include "xo-image.h"
++
++
++ void callback_clipboard_get(GtkClipboard *clipboard,
++ GtkSelectionData *selection_data,
++ guint info, gpointer user_data)
++ {
++ int length;
++
++ g_memmove(&length, user_data, sizeof(int));
++ gtk_selection_data_set(selection_data,
++ gdk_atom_intern("_XOURNAL", FALSE), 8, user_data, length);
++ }
++
++ void callback_clipboard_clear(GtkClipboard *clipboard, gpointer user_data)
++ {
++ g_free(user_data);
++ }
++
++ void callback_clipboard_targets_received(GtkClipboard *clipboard,
++ GdkAtom *atoms,
++ gint n_atoms,
++ gpointer data)
++ {
++ gint i;
++ printf("clipboard targets:\n");
++ for (i = 0; i < n_atoms; i++) {
++ printf("%s\n", gdk_atom_name(atoms[i]));
++ }
++ }
++
++ void selection_to_clip(void)
++ {
++ int bufsz, nitems, val;
++ char *buf, *p;
++ GList *list;
++ struct Item *item;
++ GtkTargetEntry target;
++
++ if (ui.selection == NULL) return;
++ bufsz = 2*sizeof(int) // bufsz, nitems
++ + sizeof(struct BBox); // bbox
++ nitems = 0;
++ for (list = ui.selection->items; list != NULL; list = list->next) {
++ item = (struct Item *)list->data;
++ nitems++;
++ if (item->type == ITEM_STROKE) {
++ bufsz+= sizeof(int) // type
++ + sizeof(struct Brush) // brush
++ + sizeof(int) // num_points
++ + 2*item->path->num_points*sizeof(double); // the points
++ if (item->brush.variable_width)
++ bufsz += (item->path->num_points-1)*sizeof(double); // the widths
++ }
++ else if (item->type == ITEM_TEXT) {
++ bufsz+= sizeof(int) // type
++ + sizeof(struct Brush) // brush
++ + 2*sizeof(double) // bbox upper-left
++ + sizeof(int) // text len
++ + strlen(item->text)+1 // text
++ + sizeof(int) // font_name len
++ + strlen(item->font_name)+1 // font_name
++ + sizeof(double); // font_size
++ }
++ else if (item->type == ITEM_IMAGE) {
++ if (item->image_png == NULL) {
++ if (!pixbuf_to_buffer(item->image, &item->image_png, &item->image_png_len, "png")) {
++ item->image_png_len = 0; // failed for some reason, so forget it
++ }
++ }
++ bufsz+= sizeof(int) // type
++ + sizeof(struct BBox)
++ + sizeof(gsize) // png_buflen
++ + item->image_png_len;
++ }
++ else bufsz+= sizeof(int); // type
++ }
++ p = buf = g_malloc(bufsz);
++ g_memmove(p, &bufsz, sizeof(int)); p+= sizeof(int);
++ g_memmove(p, &nitems, sizeof(int)); p+= sizeof(int);
++ g_memmove(p, &ui.selection->bbox, sizeof(struct BBox)); p+= sizeof(struct BBox);
++ for (list = ui.selection->items; list != NULL; list = list->next) {
++ item = (struct Item *)list->data;
++ g_memmove(p, &item->type, sizeof(int)); p+= sizeof(int);
++ if (item->type == ITEM_STROKE) {
++ g_memmove(p, &item->brush, sizeof(struct Brush)); p+= sizeof(struct Brush);
++ g_memmove(p, &item->path->num_points, sizeof(int)); p+= sizeof(int);
++ g_memmove(p, item->path->coords, 2*item->path->num_points*sizeof(double));
++ p+= 2*item->path->num_points*sizeof(double);
++ if (item->brush.variable_width) {
++ g_memmove(p, item->widths, (item->path->num_points-1)*sizeof(double));
++ p+= (item->path->num_points-1)*sizeof(double);
++ }
++ }
++ if (item->type == ITEM_TEXT) {
++ g_memmove(p, &item->brush, sizeof(struct Brush)); p+= sizeof(struct Brush);
++ g_memmove(p, &item->bbox.left, sizeof(double)); p+= sizeof(double);
++ g_memmove(p, &item->bbox.top, sizeof(double)); p+= sizeof(double);
++ val = strlen(item->text);
++ g_memmove(p, &val, sizeof(int)); p+= sizeof(int);
++ g_memmove(p, item->text, val+1); p+= val+1;
++ val = strlen(item->font_name);
++ g_memmove(p, &val, sizeof(int)); p+= sizeof(int);
++ g_memmove(p, item->font_name, val+1); p+= val+1;
++ g_memmove(p, &item->font_size, sizeof(double)); p+= sizeof(double);
++ }
++ if (item->type == ITEM_IMAGE) {
++ g_memmove(p, &item->bbox, sizeof(struct BBox)); p+= sizeof(struct BBox);
++ g_memmove(p, &item->image_png_len, sizeof(gsize)); p+= sizeof(gsize);
++ if (item->image_png_len > 0) {
++ g_memmove(p, item->image_png, item->image_png_len); p+= item->image_png_len;
++ }
++ }
++ }
++
++ target.target = "_XOURNAL";
++ target.flags = 0;
++ target.info = 0;
++
++ gtk_clipboard_set_with_data(gtk_clipboard_get(GDK_SELECTION_CLIPBOARD),
++ &target, 1,
++ callback_clipboard_get, callback_clipboard_clear, buf);
++ }
++
++ // local paste within the application
++ void clipboard_paste_from_xournal(GtkSelectionData *sel_data)
++ {
++ unsigned char *p;
++ int nitems, npts, i, len;
++ struct Item *item;
++ double hoffset, voffset, cx, cy;
++ double *pf;
++ int sx, sy, wx, wy;
++
++ reset_selection();
++
++ ui.selection = g_new(struct Selection, 1);
++ p = sel_data->data + sizeof(int);
++ g_memmove(&nitems, p, sizeof(int)); p+= sizeof(int);
++ ui.selection->type = ITEM_SELECTRECT;
++ ui.selection->layer = ui.cur_layer;
++ g_memmove(&ui.selection->bbox, p, sizeof(struct BBox)); p+= sizeof(struct BBox);
++ ui.selection->items = NULL;
++
++ // find by how much we translate the pasted selection
++ gnome_canvas_get_scroll_offsets(canvas, &sx, &sy);
++ gdk_window_get_geometry(GTK_WIDGET(canvas)->window, NULL, NULL, &wx, &wy, NULL);
++ gnome_canvas_window_to_world(canvas, sx + wx/2, sy + wy/2, &cx, &cy);
++ cx -= ui.cur_page->hoffset;
++ cy -= ui.cur_page->voffset;
++ if (cx + (ui.selection->bbox.right-ui.selection->bbox.left)/2 > ui.cur_page->width)
++ cx = ui.cur_page->width - (ui.selection->bbox.right-ui.selection->bbox.left)/2;
++ if (cx - (ui.selection->bbox.right-ui.selection->bbox.left)/2 < 0)
++ cx = (ui.selection->bbox.right-ui.selection->bbox.left)/2;
++ if (cy + (ui.selection->bbox.bottom-ui.selection->bbox.top)/2 > ui.cur_page->height)
++ cy = ui.cur_page->height - (ui.selection->bbox.bottom-ui.selection->bbox.top)/2;
++ if (cy - (ui.selection->bbox.bottom-ui.selection->bbox.top)/2 < 0)
++ cy = (ui.selection->bbox.bottom-ui.selection->bbox.top)/2;
++ hoffset = cx - (ui.selection->bbox.right+ui.selection->bbox.left)/2;
++ voffset = cy - (ui.selection->bbox.top+ui.selection->bbox.bottom)/2;
++ ui.selection->bbox.left += hoffset;
++ ui.selection->bbox.right += hoffset;
++ ui.selection->bbox.top += voffset;
++ ui.selection->bbox.bottom += voffset;
++
++ ui.selection->canvas_item = gnome_canvas_item_new(ui.cur_layer->group,
++ gnome_canvas_rect_get_type(), "width-pixels", 1,
++ "outline-color-rgba", 0x000000ff,
++ "fill-color-rgba", 0x80808040,
++ "x1", ui.selection->bbox.left, "x2", ui.selection->bbox.right,
++ "y1", ui.selection->bbox.top, "y2", ui.selection->bbox.bottom, NULL);
++ make_dashed(ui.selection->canvas_item);
++
++ while (nitems-- > 0) {
++ item = g_new(struct Item, 1);
++ ui.selection->items = g_list_append(ui.selection->items, item);
++ ui.cur_layer->items = g_list_append(ui.cur_layer->items, item);
++ ui.cur_layer->nitems++;
++ g_memmove(&item->type, p, sizeof(int)); p+= sizeof(int);
++ if (item->type == ITEM_STROKE) {
++ g_memmove(&item->brush, p, sizeof(struct Brush)); p+= sizeof(struct Brush);
++ g_memmove(&npts, p, sizeof(int)); p+= sizeof(int);
++ item->path = gnome_canvas_points_new(npts);
++ pf = (double *)p;
++ for (i=0; i<npts; i++) {
++ item->path->coords[2*i] = pf[2*i] + hoffset;
++ item->path->coords[2*i+1] = pf[2*i+1] + voffset;
++ }
++ p+= 2*item->path->num_points*sizeof(double);
++ if (item->brush.variable_width) {
++ item->widths = g_memdup(p, (item->path->num_points-1)*sizeof(double));
++ p+= (item->path->num_points-1)*sizeof(double);
++ }
++ else item->widths = NULL;
++ update_item_bbox(item);
++ make_canvas_item_one(ui.cur_layer->group, item);
++ }
++ if (item->type == ITEM_TEXT) {
++ g_memmove(&item->brush, p, sizeof(struct Brush)); p+= sizeof(struct Brush);
++ g_memmove(&item->bbox.left, p, sizeof(double)); p+= sizeof(double);
++ g_memmove(&item->bbox.top, p, sizeof(double)); p+= sizeof(double);
++ item->bbox.left += hoffset;
++ item->bbox.top += voffset;
++ g_memmove(&len, p, sizeof(int)); p+= sizeof(int);
++ item->text = g_malloc(len+1);
++ g_memmove(item->text, p, len+1); p+= len+1;
++ g_memmove(&len, p, sizeof(int)); p+= sizeof(int);
++ item->font_name = g_malloc(len+1);
++ g_memmove(item->font_name, p, len+1); p+= len+1;
++ g_memmove(&item->font_size, p, sizeof(double)); p+= sizeof(double);
++ make_canvas_item_one(ui.cur_layer->group, item);
++ }
++ if (item->type == ITEM_IMAGE) {
++ item->canvas_item = NULL;
++ item->image_scaled = NULL;
++ item->image_png = NULL;
++ item->image_png_len = 0;
++ g_memmove(&item->bbox, p, sizeof(struct BBox)); p+= sizeof(struct BBox);
++ item->bbox.left += hoffset;
++ item->bbox.right += hoffset;
++ item->bbox.top += voffset;
++ item->bbox.bottom += voffset;
++ g_memmove(&item->image_png_len, p, sizeof(gsize)); p+= sizeof(gsize);
++ if (item->image_png_len > 0) {
++ item->image_png = g_memdup(p, item->image_png_len);
++ item->image = pixbuf_from_buffer(item->image_png, item->image_png_len);
++ p+= item->image_png_len;
++ } else {
++ item->image = NULL;
++ }
++ make_canvas_item_one(ui.cur_layer->group, item);
++ }
++ }
++
++ prepare_new_undo();
++ undo->type = ITEM_PASTE;
++ undo->layer = ui.cur_layer;
++ undo->itemlist = g_list_copy(ui.selection->items);
++
++ gtk_selection_data_free(sel_data);
++ update_copy_paste_enabled();
++ update_color_menu();
++ update_thickness_buttons();
++ update_color_buttons();
++ update_font_button();
++ update_cursor(); // FIXME: can't know if pointer is within selection!
++ }
++
++ // paste an external image
++ void clipboard_paste_image(GdkPixbuf *pixbuf)
++ {
++ double pt[2];
++
++ reset_selection();
++
++ get_current_pointer_coords(pt);
++ set_current_page(pt);
++
++ create_image_from_pixbuf(pixbuf, NULL, pt);
++ }
++
++ // work out what format the clipboard data is in, and paste accordingly
++ void clipboard_paste(void)
++ {
++ GtkSelectionData *sel_data;
++ GdkPixbuf *pixbuf;
++ GtkClipboard *clipboard;
++ unsigned char *p;
++ int nitems, npts, i, len;
++ struct Item *item;
++ double hoffset, voffset, cx, cy;
++ double *pf;
++ int sx, sy, wx, wy;
++
++ if (ui.cur_layer == NULL) return;
++
++ ui.cur_item_type = ITEM_PASTE;
++ clipboard = gtk_clipboard_get(GDK_SELECTION_CLIPBOARD);
++ sel_data = gtk_clipboard_wait_for_contents(
++ clipboard,
++ gdk_atom_intern("_XOURNAL", FALSE));
++ ui.cur_item_type = ITEM_NONE;
++ if (sel_data != NULL) {
++ clipboard_paste_from_xournal(sel_data);
++ } else {
++ pixbuf = gtk_clipboard_wait_for_image(clipboard);
++ if (pixbuf != NULL) {
++ clipboard_paste_image(pixbuf);
++ }
++ }
++ }
+diff -c /dev/null 'xournal/src/xo-clipboard.h'
+Index: ./src/xo-clipboard.h
+*** ./src/xo-clipboard.h Thu Jan 1 12:00:00 1970
+--- ./src/xo-clipboard.h Thu Mar 25 15:09:53 2010
+***************
+*** 0 ****
+--- 1,2 ----
++ void selection_to_clip(void);
++ void clipboard_paste(void);
+diff -c 'xournal-0.4.5/src/xo-file.c' 'xournal/src/xo-file.c'
+Index: ./src/xo-file.c
+*** ./src/xo-file.c Tue Sep 29 12:36:05 2009
+--- ./src/xo-file.c Thu Jul 29 16:59:47 2010
+***************
+*** 25,30 ****
+--- 25,31 ----
+ #include "xo-misc.h"
+ #include "xo-file.h"
+ #include "xo-paint.h"
++ #include "xo-image.h"
+
+ const char *tool_names[NUM_TOOLS] = {"pen", "eraser", "highlighter", "text", "", "selectrect", "vertspace", "hand"};
+ const char *color_names[COLOR_MAX] = {"black", "blue", "red", "green",
+***************
+*** 68,73 ****
+--- 69,122 ----
+ }
+ }
+
++
++ // Write image to file: returns true on success, false on error.
++ // The image is written as a base64 encoded PNG.
++ gboolean write_image(gzFile f, Item *item)
++ {
++ gchar *base64_str;
++ GError **error;
++
++ error = NULL;
++
++ if (item->image_png == NULL) {
++ if (!pixbuf_to_buffer(item->image, &item->image_png, &item->image_png_len, "png")) {
++ item->image_png_len = 0; // failed for some reason, so forget it
++ return FALSE;
++ }
++ }
++
++ base64_str = g_base64_encode(item->image_png, item->image_png_len);
++
++ gzputs(f, base64_str);
++
++ g_free(base64_str);
++
++ return TRUE;
++ }
++
++ // create pixbuf from base64 encoded PNG, or return NULL on failure
++ GdkPixbuf *read_pixbuf(const gchar *base64_str, gsize base64_strlen)
++ {
++ gchar *base64_str2;
++ gchar *png_buf;
++ gsize png_buflen;
++ GdkPixbuf *pixbuf;
++
++ // We have to copy the string in order to null terminate it, sigh.
++ base64_str2 = g_memdup(base64_str, base64_strlen + 1);
++ base64_str2[ base64_strlen ] = '\0';
++
++ png_buf = g_base64_decode(base64_str2, &png_buflen);
++
++ pixbuf = pixbuf_from_buffer(png_buf, png_buflen);
++
++ g_free(png_buf);
++ g_free(base64_str2);
++
++ return pixbuf;
++ }
++
+ // saves the journal to a file: returns true on success, false on error
+
+ gboolean save_journal(const char *filename)
+***************
+*** 199,204 ****
+--- 248,261 ----
+ gzprintf(f, "\">%s</text>\n", tmpstr);
+ g_free(tmpstr);
+ }
++ if (item->type == ITEM_IMAGE) {
++ gzprintf(f, "<image left=\"%.2f\" top=\"%.2f\" right=\"%.2f\" bottom=\"%.2f\">", item->bbox.left, item->bbox.top, item->bbox.right, item->bbox.bottom);
++
++ if (!write_image(f, item)) {
++ success = FALSE;
++ }
++ gzprintf(f, "</image>\n");
++ }
+ }
+ gzprintf(f, "</layer>\n");
+ }
+***************
+*** 575,580 ****
+--- 632,688 ----
+ }
+ if (has_attr!=31) *error = xoj_invalid();
+ }
++ else if (!strcmp(element_name, "image")) { // start of a image item
++ if (tmpLayer == NULL || tmpItem != NULL) {
++ *error = xoj_invalid();
++ return;
++ }
++ tmpItem = (struct Item *)g_malloc0(sizeof(struct Item));
++ tmpItem->type = ITEM_IMAGE;
++ tmpItem->canvas_item = NULL;
++ tmpItem->image=NULL;
++ tmpItem->image_scaled=NULL;
++ tmpItem->image_png = NULL;
++ tmpItem->image_png_len = 0;
++ tmpLayer->items = g_list_append(tmpLayer->items, tmpItem);
++ tmpLayer->nitems++;
++ // scan for x, y
++ has_attr = 0;
++ while (*attribute_names!=NULL) {
++ if (!strcmp(*attribute_names, "left")) {
++ if (has_attr & 1) *error = xoj_invalid();
++ cleanup_numeric((gchar *)*attribute_values);
++ tmpItem->bbox.left = g_ascii_strtod(*attribute_values, &ptr);
++ if (ptr == *attribute_values) *error = xoj_invalid();
++ has_attr |= 1;
++ }
++ else if (!strcmp(*attribute_names, "top")) {
++ if (has_attr & 2) *error = xoj_invalid();
++ cleanup_numeric((gchar *)*attribute_values);
++ tmpItem->bbox.top = g_ascii_strtod(*attribute_values, &ptr);
++ if (ptr == *attribute_values) *error = xoj_invalid();
++ has_attr |= 2;
++ }
++ else if (!strcmp(*attribute_names, "right")) {
++ if (has_attr & 4) *error = xoj_invalid();
++ cleanup_numeric((gchar *)*attribute_values);
++ tmpItem->bbox.right = g_ascii_strtod(*attribute_values, &ptr);
++ if (ptr == *attribute_values) *error = xoj_invalid();
++ has_attr |= 4;
++ }
++ else if (!strcmp(*attribute_names, "bottom")) {
++ if (has_attr & 8) *error = xoj_invalid();
++ cleanup_numeric((gchar *)*attribute_values);
++ tmpItem->bbox.bottom = g_ascii_strtod(*attribute_values, &ptr);
++ if (ptr == *attribute_values) *error = xoj_invalid();
++ has_attr |= 8;
++ }
++ else *error = xoj_invalid();
++ attribute_names++;
++ attribute_values++;
++ }
++ if (has_attr!=15) *error = xoj_invalid();
++ }
+ }
+
+ void xoj_parser_end_element(GMarkupParseContext *context,
+***************
+*** 610,615 ****
+--- 718,730 ----
+ }
+ tmpItem = NULL;
+ }
++ if (!strcmp(element_name, "image")) {
++ if (tmpItem == NULL) {
++ *error = xoj_invalid();
++ return;
++ }
++ tmpItem = NULL;
++ }
+ }
+
+ void xoj_parser_text(GMarkupParseContext *context,
+***************
+*** 647,652 ****
+--- 762,770 ----
+ g_memmove(tmpItem->text, text, text_len);
+ tmpItem->text[text_len]=0;
+ }
++ if (!strcmp(element_name, "image")) {
++ tmpItem->image = read_pixbuf(text, text_len);
++ }
+ }
+
+ gboolean user_wants_second_chance(char **filename)
+***************
+*** 716,722 ****
+ g_free(tmpfn);
+
+ f = gzopen(filename, "r");
+! if (f==NULL) return FALSE;
+ if (filename[0]=='/') {
+ if (ui.default_path != NULL) g_free(ui.default_path);
+ ui.default_path = g_path_get_dirname(filename);
+--- 834,845 ----
+ g_free(tmpfn);
+
+ f = gzopen(filename, "r");
+! if (f==NULL) {
+! #ifdef IMAGE_DEBUG
+! printf("gzopen failed\n");
+! #endif
+! return FALSE;
+! }
+ if (filename[0]=='/') {
+ if (ui.default_path != NULL) g_free(ui.default_path);
+ ui.default_path = g_path_get_dirname(filename);
+***************
+*** 737,752 ****
+
+ while (valid && !gzeof(f)) {
+ len = gzread(f, buffer, 1000);
+! if (len<0) valid = FALSE;
+ if (maybe_pdf && len>=4 && !strncmp(buffer, "%PDF", 4))
+ { valid = FALSE; break; } // most likely pdf
+ else maybe_pdf = FALSE;
+ if (len<=0) break;
+ valid = g_markup_parse_context_parse(context, buffer, len, &error);
+ }
+ gzclose(f);
+! if (valid) valid = g_markup_parse_context_end_parse(context, &error);
+! if (tmpJournal.npages == 0) valid = FALSE;
+ g_markup_parse_context_free(context);
+
+ if (!valid) {
+--- 860,893 ----
+
+ while (valid && !gzeof(f)) {
+ len = gzread(f, buffer, 1000);
+! if (len<0){
+! valid = FALSE;
+! }
+ if (maybe_pdf && len>=4 && !strncmp(buffer, "%PDF", 4))
+ { valid = FALSE; break; } // most likely pdf
+ else maybe_pdf = FALSE;
+ if (len<=0) break;
+ valid = g_markup_parse_context_parse(context, buffer, len, &error);
++
++ #ifdef IMAGE_DEBUG
++ if(!valid) printf("parsing failed\n");
++ #endif
+ }
+ gzclose(f);
+!
+! if (valid) {
+! valid = g_markup_parse_context_end_parse(context, &error);
+!
+! #ifdef IMAGE_DEBUG
+! if(!valid) printf("end parsing failed\n");
+! #endif
+! }
+! if (tmpJournal.npages == 0){
+! #ifdef IMAGE_DEBUG
+! printf("found no pages\n");
+! #endif
+! valid = FALSE;
+! }
+ g_markup_parse_context_free(context);
+
+ if (!valid) {
+***************
+*** 823,828 ****
+--- 964,970 ----
+ update_page_stuff();
+ rescale_bg_pixmaps(); // this requests the PDF pages if need be
+ gtk_adjustment_set_value(gtk_layout_get_vadjustment(GTK_LAYOUT(canvas)), 0);
++
+ return TRUE;
+ }
+
+***************
+*** 1338,1343 ****
+--- 1480,1486 ----
+ ui.print_ruling = TRUE;
+ ui.default_unit = UNIT_CM;
+ ui.default_path = NULL;
++ ui.default_image = NULL;
+ ui.default_font_name = g_strdup(DEFAULT_FONT);
+ ui.default_font_size = DEFAULT_FONT_SIZE;
+ ui.pressure_sensitivity = FALSE;
+diff -c /dev/null 'xournal/src/xo-image.c'
+Index: ./src/xo-image.c
+*** ./src/xo-image.c Thu Jan 1 12:00:00 1970
+--- ./src/xo-image.c Thu Jul 29 16:54:52 2010
+***************
+*** 0 ****
+--- 1,238 ----
++ #ifdef HAVE_CONFIG_H
++ # include <config.h>
++ #endif
++
++ #include <math.h>
++ #include <string.h>
++ #include <gtk/gtk.h>
++ #include <gio/gio.h>
++
++ #include "xournal.h"
++ #include "xo-support.h"
++ #include "xo-image.h"
++
++
++ // Write pixmap to buffer: returns true on success, false on error.
++ gboolean pixbuf_to_buffer(GdkPixbuf *pixbuf, gchar **buf, gsize *buflen, const char *type)
++ {
++ GError *error;
++
++ error = NULL;
++
++ if (!gdk_pixbuf_save_to_buffer(pixbuf,
++ buf,
++ buflen,
++ type,
++ &error,
++ NULL)) {
++ return FALSE;
++ }
++
++ return TRUE;
++ }
++
++ // create pixbuf from buffer, or return NULL on failure
++ GdkPixbuf *pixbuf_from_buffer(const gchar *buf, gsize buflen)
++ {
++ GInputStream *istream;
++ GdkPixbuf *pixbuf;
++ GError *error;
++
++ error = NULL;
++
++ istream = g_memory_input_stream_new_from_data (buf, buflen, NULL);
++
++ pixbuf = gdk_pixbuf_new_from_stream(istream, NULL, &error);
++
++ g_input_stream_close(istream, NULL, &error);
++
++ return pixbuf;
++ }
++
++ void create_image_from_pixbuf(GdkPixbuf *pixbuf, struct Item *item, double *pt)
++ {
++ GtkTextBuffer *buffer;
++ GnomeCanvasItem *canvas_item;
++ GdkColor color;
++ GtkWidget *dialog;
++ GtkFileFilter *filt_all;
++ GtkFileFilter *filt_gdkimage;
++ double scale;
++
++ if (item==NULL) {
++ item = g_new(struct Item, 1);
++ item->type = ITEM_IMAGE;
++ item->canvas_item = NULL;
++ item->bbox.left = pt[0];
++ item->bbox.top = pt[1];
++ item->image = pixbuf;
++ item->image_scaled = NULL;
++ item->image_png = NULL;
++ item->image_png_len = 0;
++
++ // Scale at native size, unless that won't fit,
++ // in which case we shrink it down.
++ scale = 1 / ui.zoom;
++ if( (scale * gdk_pixbuf_get_width(item->image)) > ui.cur_page->width - item->bbox.left ) {
++ //set scale so that it does not extend too far to the right
++ scale = (ui.cur_page->width - item->bbox.left) / gdk_pixbuf_get_width(item->image);
++ }
++ if( (scale * gdk_pixbuf_get_height(item->image)) > ui.cur_page->height - item->bbox.top ) {
++ //set scale so that it does not extend too far to the bottom
++ scale = (ui.cur_page->height - item->bbox.top) / gdk_pixbuf_get_height(item->image);
++ }
++
++ item->bbox.right = item->bbox.left + scale * gdk_pixbuf_get_width(item->image);
++ item->bbox.bottom = item->bbox.top + scale * gdk_pixbuf_get_height(item->image);
++ g_memmove(&(item->brush), ui.cur_brush, sizeof(struct Brush));
++ ui.cur_layer->items = g_list_append(ui.cur_layer->items, item);
++ ui.cur_layer->nitems++;
++ }
++
++ item->type = ITEM_IMAGE;
++ ui.cur_item = item;
++
++ if (item->canvas_item!=NULL) {
++ lower_canvas_item_to(ui.cur_layer->group, canvas_item, item->canvas_item);
++ gtk_object_destroy(GTK_OBJECT(item->canvas_item));
++ }
++
++ make_canvas_item_one(ui.cur_layer->group, item);
++
++ // select image
++ reset_selection();
++ ui.selection = g_new0(struct Selection, 1);
++ ui.selection->type = ITEM_SELECTRECT;
++ ui.selection->layer = ui.cur_layer;
++ ui.selection->bbox = item->bbox;
++ ui.selection->items = g_list_append(ui.selection->items, item);
++ ui.selection->canvas_item = gnome_canvas_item_new(ui.cur_layer->group,
++ gnome_canvas_rect_get_type(), "width-pixels", 1,
++ "outline-color-rgba", 0x000000ff,
++ "fill-color-rgba", 0x80808040,
++ "x1", ui.selection->bbox.left, "x2", ui.selection->bbox.right,
++ "y1", ui.selection->bbox.top, "y2", ui.selection->bbox.bottom, NULL);
++ make_dashed(ui.selection->canvas_item);
++
++ // add undo information
++ prepare_new_undo();
++ undo->type = ITEM_IMAGE;
++ undo->item = ui.cur_item;
++ undo->layer = ui.cur_layer;
++
++ ui.cur_item = NULL;
++ ui.cur_item_type = ITEM_NONE;
++ }
++
++ void insert_image(GdkEvent *event, struct Item *item)
++ {
++ GtkTextBuffer *buffer;
++ GnomeCanvasItem *canvas_item;
++ GdkColor color;
++ GtkWidget *dialog;
++ GtkFileFilter *filt_all;
++ GtkFileFilter *filt_gdkimage;
++ char *filename;
++ GdkPixbuf *pixbuf;
++ double scale=1;
++ double pt[2];
++
++ dialog = gtk_file_chooser_dialog_new(_("Insert Image"), GTK_WINDOW (winMain),
++ GTK_FILE_CHOOSER_ACTION_OPEN, GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
++ GTK_STOCK_OPEN, GTK_RESPONSE_OK, NULL);
++ #ifdef FILE_DIALOG_SIZE_BUGFIX
++ gtk_window_set_default_size(GTK_WINDOW(dialog), 500, 400);
++ #endif
++
++ filt_all = gtk_file_filter_new();
++ gtk_file_filter_set_name(filt_all, _("All files"));
++ gtk_file_filter_add_pattern(filt_all, "*");
++ filt_gdkimage = gtk_file_filter_new();
++ gtk_file_filter_set_name(filt_gdkimage, _("supported image files"));
++ gtk_file_filter_add_pixbuf_formats(filt_gdkimage);
++ gtk_file_chooser_add_filter(GTK_FILE_CHOOSER (dialog), filt_gdkimage);
++ gtk_file_chooser_add_filter(GTK_FILE_CHOOSER (dialog), filt_all);
++
++ if (ui.default_image != NULL) gtk_file_chooser_set_filename(GTK_FILE_CHOOSER (dialog), ui.default_image);
++
++ if (gtk_dialog_run(GTK_DIALOG(dialog)) != GTK_RESPONSE_OK) {
++ gtk_widget_destroy(dialog);
++ return;
++ }
++ filename = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER (dialog));
++ gtk_widget_destroy(dialog);
++
++ if (filename == NULL) {
++ /* nothing selected */
++ return;
++ }
++
++ if (ui.default_image != NULL) g_free(ui.default_image);
++ ui.default_image = g_strdup(filename);
++
++ pixbuf=gdk_pixbuf_new_from_file(filename, NULL);
++ if(pixbuf==NULL){
++ /* open failed */
++ dialog = gtk_message_dialog_new(GTK_WINDOW (winMain), GTK_DIALOG_DESTROY_WITH_PARENT,
++ GTK_MESSAGE_ERROR, GTK_BUTTONS_OK, _("Error opening image '%s'"), filename);
++ gtk_dialog_run(GTK_DIALOG(dialog));
++ gtk_widget_destroy(dialog);
++ g_free(filename);
++ ui.cur_item = NULL;
++ ui.cur_item_type = ITEM_NONE;
++ return;
++ }
++
++ ui.cur_item_type = ITEM_IMAGE;
++
++ get_pointer_coords(event, pt);
++ set_current_page(pt);
++
++ create_image_from_pixbuf(pixbuf, item, pt);
++ }
++
++ void update_scaled_image(struct Item *item)
++ {
++ gboolean use_native = is_native_image_usable( item );
++ if ( is_native_image_usable( item ) != (item->image_scaled == NULL) ) {
++ // we are currently using a scaled image, and should switch to native,
++ // or vice versa
++
++ adjust_or_make_canvas_item_image(ui.cur_layer->group, item);
++ }
++ }
++
++ void rescale_images(void)
++ {
++ GList *pagelist, *layerlist, *itemlist;
++ struct Item *item;
++
++ for (pagelist = journal.pages; pagelist!=NULL; pagelist = pagelist->next)
++ for (layerlist = ((struct Page *)pagelist->data)->layers; layerlist!=NULL; layerlist = layerlist->next)
++ for (itemlist = ((struct Layer *)layerlist->data)->items; itemlist!=NULL; itemlist = itemlist->next) {
++ item = (struct Item *)itemlist->data;
++ if ( item->type == ITEM_IMAGE ) {
++ update_scaled_image( item );
++ }
++ }
++ }
++
++ gboolean is_native_image_usable(struct Item *item)
++ {
++ double native_width;
++ double native_height;
++ double required_width;
++ double required_height;
++ gboolean usable;
++
++ // use the original image at native resolution if it's close enough to what we need
++ native_width = gdk_pixbuf_get_width(item->image) / ui.zoom;
++ native_height = gdk_pixbuf_get_height(item->image) / ui.zoom;
++ required_width = item->bbox.right - item->bbox.left;
++ required_height = item->bbox.bottom - item->bbox.top;
++
++ usable = ( fabs( native_width - required_width ) < 1 &&
++ fabs( native_height - required_height ) < 1 );
++
++ return usable;
++ }
+diff -c /dev/null 'xournal/src/xo-image.h'
+Index: ./src/xo-image.h
+*** ./src/xo-image.h Thu Jan 1 12:00:00 1970
+--- ./src/xo-image.h Thu Jun 24 20:42:02 2010
+***************
+*** 0 ****
+--- 1,7 ----
++ extern gboolean pixbuf_to_buffer(GdkPixbuf *pixbuf, gchar **buf, gsize *buflen, const char *type);
++ extern GdkPixbuf *pixbuf_from_buffer(const gchar *buf, gsize buflen);
++
++ void create_image_from_pixbuf(GdkPixbuf *pixbuf, struct Item *item, double *pt);
++ void insert_image(GdkEvent *event, struct Item *item);
++ void rescale_images(void);
++ gboolean is_native_image_usable(struct Item *item);
+diff -c 'xournal-0.4.5/src/xo-interface.c' 'xournal/src/xo-interface.c'
+Index: ./src/xo-interface.c
+*** ./src/xo-interface.c Fri Oct 2 19:03:32 2009
+--- ./src/xo-interface.c Mon Mar 22 11:39:25 2010
+***************
+*** 36,42 ****
+ GtkWidget *menuFile_menu;
+ GtkWidget *fileNew;
+ GtkWidget *fileNewBackground;
+- GtkWidget *image623;
+ GtkWidget *fileOpen;
+ GtkWidget *fileSave;
+ GtkWidget *fileSaveAs;
+--- 36,41 ----
+***************
+*** 53,59 ****
+ GtkWidget *mru7;
+ GtkWidget *separator22;
+ GtkWidget *filePrintOptions;
+- GtkWidget *image624;
+ GtkWidget *filePrint;
+ GtkWidget *filePrintPDF;
+ GtkWidget *separator2;
+--- 52,57 ----
+***************
+*** 81,102 ****
+ GtkWidget *viewZoomOut;
+ GtkWidget *viewNormalSize;
+ GtkWidget *viewPageWidth;
+- GtkWidget *image625;
+ GtkWidget *viewSetZoom;
+ GtkWidget *separator5;
+ GtkWidget *viewFirstPage;
+- GtkWidget *image626;
+ GtkWidget *viewPreviousPage;
+- GtkWidget *image627;
+ GtkWidget *viewNextPage;
+- GtkWidget *image628;
+ GtkWidget *viewLastPage;
+- GtkWidget *image629;
+ GtkWidget *separator6;
+ GtkWidget *viewShowLayer;
+- GtkWidget *image630;
+ GtkWidget *viewHideLayer;
+- GtkWidget *image631;
+ GtkWidget *menuJournal;
+ GtkWidget *menuJournal_menu;
+ GtkWidget *journalNewPageBefore;
+--- 79,93 ----
+***************
+*** 131,137 ****
+ GtkWidget *journalApplyAllPages;
+ GtkWidget *separator23;
+ GtkWidget *journalLoadBackground;
+- GtkWidget *image632;
+ GtkWidget *journalScreenshot;
+ GtkWidget *separator19;
+ GtkWidget *journalDefaultBackground;
+--- 122,127 ----
+***************
+*** 153,159 ****
+ GtkWidget *toolsHand;
+ GtkWidget *separator16;
+ GtkWidget *toolsColor;
+- GtkWidget *image633;
+ GtkWidget *toolsColor_menu;
+ GSList *colorBlack_group = NULL;
+ GtkWidget *colorBlack;
+--- 143,148 ----
+***************
+*** 196,202 ****
+ GtkWidget *highlighterMedium;
+ GtkWidget *highlighterThick;
+ GtkWidget *toolsTextFont;
+- GtkWidget *image634;
+ GtkWidget *separator10;
+ GtkWidget *toolsDefaultPen;
+ GtkWidget *toolsDefaultEraser;
+--- 185,190 ----
+***************
+*** 289,294 ****
+--- 277,283 ----
+ GtkWidget *buttonEraser;
+ GtkWidget *buttonHighlighter;
+ GtkWidget *buttonText;
++ GtkWidget *buttonImage;
+ GtkWidget *buttonReco;
+ GtkWidget *buttonRuler;
+ GtkWidget *toolitem15;
+***************
+*** 368,381 ****
+ gtk_widget_show (fileNew);
+ gtk_container_add (GTK_CONTAINER (menuFile_menu), fileNew);
+
+! fileNewBackground = gtk_image_menu_item_new_with_mnemonic (_("Annotate PD_F"));
+ gtk_widget_show (fileNewBackground);
+ gtk_container_add (GTK_CONTAINER (menuFile_menu), fileNewBackground);
+
+- image623 = gtk_image_new_from_stock ("gtk-open", GTK_ICON_SIZE_MENU);
+- gtk_widget_show (image623);
+- gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (fileNewBackground), image623);
+-
+ fileOpen = gtk_image_menu_item_new_from_stock ("gtk-open", accel_group);
+ gtk_widget_show (fileOpen);
+ gtk_container_add (GTK_CONTAINER (menuFile_menu), fileOpen);
+--- 357,366 ----
+ gtk_widget_show (fileNew);
+ gtk_container_add (GTK_CONTAINER (menuFile_menu), fileNew);
+
+! fileNewBackground = gtk_image_menu_item_new_with_mnemonic ("Annotate PD_F");
+ gtk_widget_show (fileNewBackground);
+ gtk_container_add (GTK_CONTAINER (menuFile_menu), fileNewBackground);
+
+ fileOpen = gtk_image_menu_item_new_from_stock ("gtk-open", accel_group);
+ gtk_widget_show (fileOpen);
+ gtk_container_add (GTK_CONTAINER (menuFile_menu), fileOpen);
+***************
+*** 437,450 ****
+ gtk_container_add (GTK_CONTAINER (menuFile_menu), separator22);
+ gtk_widget_set_sensitive (separator22, FALSE);
+
+! filePrintOptions = gtk_image_menu_item_new_with_mnemonic (_("Print Options"));
+ gtk_widget_show (filePrintOptions);
+ gtk_container_add (GTK_CONTAINER (menuFile_menu), filePrintOptions);
+
+- image624 = gtk_image_new_from_stock ("gtk-preferences", GTK_ICON_SIZE_MENU);
+- gtk_widget_show (image624);
+- gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (filePrintOptions), image624);
+-
+ filePrint = gtk_image_menu_item_new_from_stock ("gtk-print", accel_group);
+ gtk_widget_show (filePrint);
+ gtk_container_add (GTK_CONTAINER (menuFile_menu), filePrint);
+--- 422,431 ----
+ gtk_container_add (GTK_CONTAINER (menuFile_menu), separator22);
+ gtk_widget_set_sensitive (separator22, FALSE);
+
+! filePrintOptions = gtk_image_menu_item_new_with_mnemonic ("Print Options");
+ gtk_widget_show (filePrintOptions);
+ gtk_container_add (GTK_CONTAINER (menuFile_menu), filePrintOptions);
+
+ filePrint = gtk_image_menu_item_new_from_stock ("gtk-print", accel_group);
+ gtk_widget_show (filePrint);
+ gtk_container_add (GTK_CONTAINER (menuFile_menu), filePrint);
+***************
+*** 577,593 ****
+ GDK_0, (GdkModifierType) GDK_CONTROL_MASK,
+ GTK_ACCEL_VISIBLE);
+
+! viewPageWidth = gtk_image_menu_item_new_with_mnemonic (_("Page _Width"));
+ gtk_widget_show (viewPageWidth);
+ gtk_container_add (GTK_CONTAINER (menuViewZoom_menu), viewPageWidth);
+ gtk_widget_add_accelerator (viewPageWidth, "activate", accel_group,
+ GDK_equal, (GdkModifierType) GDK_CONTROL_MASK,
+ GTK_ACCEL_VISIBLE);
+
+- image625 = gtk_image_new_from_stock ("gtk-zoom-fit", GTK_ICON_SIZE_MENU);
+- gtk_widget_show (image625);
+- gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (viewPageWidth), image625);
+-
+ viewSetZoom = gtk_menu_item_new_with_mnemonic (_("_Set Zoom"));
+ gtk_widget_show (viewSetZoom);
+ gtk_container_add (GTK_CONTAINER (menuViewZoom_menu), viewSetZoom);
+--- 558,570 ----
+ GDK_0, (GdkModifierType) GDK_CONTROL_MASK,
+ GTK_ACCEL_VISIBLE);
+
+! viewPageWidth = gtk_image_menu_item_new_with_mnemonic ("Page _Width");
+ gtk_widget_show (viewPageWidth);
+ gtk_container_add (GTK_CONTAINER (menuViewZoom_menu), viewPageWidth);
+ gtk_widget_add_accelerator (viewPageWidth, "activate", accel_group,
+ GDK_equal, (GdkModifierType) GDK_CONTROL_MASK,
+ GTK_ACCEL_VISIBLE);
+
+ viewSetZoom = gtk_menu_item_new_with_mnemonic (_("_Set Zoom"));
+ gtk_widget_show (viewSetZoom);
+ gtk_container_add (GTK_CONTAINER (menuViewZoom_menu), viewSetZoom);
+***************
+*** 597,667 ****
+ gtk_container_add (GTK_CONTAINER (menuView_menu), separator5);
+ gtk_widget_set_sensitive (separator5, FALSE);
+
+! viewFirstPage = gtk_image_menu_item_new_with_mnemonic (_("_First Page"));
+ gtk_widget_show (viewFirstPage);
+ gtk_container_add (GTK_CONTAINER (menuView_menu), viewFirstPage);
+ gtk_widget_add_accelerator (viewFirstPage, "activate", accel_group,
+ GDK_Home, (GdkModifierType) GDK_CONTROL_MASK,
+ GTK_ACCEL_VISIBLE);
+
+! image626 = gtk_image_new_from_stock ("gtk-goto-first", GTK_ICON_SIZE_MENU);
+! gtk_widget_show (image626);
+! gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (viewFirstPage), image626);
+!
+! viewPreviousPage = gtk_image_menu_item_new_with_mnemonic (_("_Previous Page"));
+ gtk_widget_show (viewPreviousPage);
+ gtk_container_add (GTK_CONTAINER (menuView_menu), viewPreviousPage);
+ gtk_widget_add_accelerator (viewPreviousPage, "activate", accel_group,
+ GDK_Left, (GdkModifierType) GDK_CONTROL_MASK,
+ GTK_ACCEL_VISIBLE);
+
+! image627 = gtk_image_new_from_stock ("gtk-go-back", GTK_ICON_SIZE_MENU);
+! gtk_widget_show (image627);
+! gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (viewPreviousPage), image627);
+!
+! viewNextPage = gtk_image_menu_item_new_with_mnemonic (_("_Next Page"));
+ gtk_widget_show (viewNextPage);
+ gtk_container_add (GTK_CONTAINER (menuView_menu), viewNextPage);
+ gtk_widget_add_accelerator (viewNextPage, "activate", accel_group,
+ GDK_Right, (GdkModifierType) GDK_CONTROL_MASK,
+ GTK_ACCEL_VISIBLE);
+
+! image628 = gtk_image_new_from_stock ("gtk-go-forward", GTK_ICON_SIZE_MENU);
+! gtk_widget_show (image628);
+! gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (viewNextPage), image628);
+!
+! viewLastPage = gtk_image_menu_item_new_with_mnemonic (_("_Last Page"));
+ gtk_widget_show (viewLastPage);
+ gtk_container_add (GTK_CONTAINER (menuView_menu), viewLastPage);
+ gtk_widget_add_accelerator (viewLastPage, "activate", accel_group,
+ GDK_End, (GdkModifierType) GDK_CONTROL_MASK,
+ GTK_ACCEL_VISIBLE);
+
+- image629 = gtk_image_new_from_stock ("gtk-goto-last", GTK_ICON_SIZE_MENU);
+- gtk_widget_show (image629);
+- gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (viewLastPage), image629);
+-
+ separator6 = gtk_separator_menu_item_new ();
+ gtk_widget_show (separator6);
+ gtk_container_add (GTK_CONTAINER (menuView_menu), separator6);
+ gtk_widget_set_sensitive (separator6, FALSE);
+
+! viewShowLayer = gtk_image_menu_item_new_with_mnemonic (_("_Show Layer"));
+ gtk_widget_show (viewShowLayer);
+ gtk_container_add (GTK_CONTAINER (menuView_menu), viewShowLayer);
+
+! image630 = gtk_image_new_from_stock ("gtk-add", GTK_ICON_SIZE_MENU);
+! gtk_widget_show (image630);
+! gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (viewShowLayer), image630);
+!
+! viewHideLayer = gtk_image_menu_item_new_with_mnemonic (_("_Hide Layer"));
+ gtk_widget_show (viewHideLayer);
+ gtk_container_add (GTK_CONTAINER (menuView_menu), viewHideLayer);
+
+- image631 = gtk_image_new_from_stock ("gtk-remove", GTK_ICON_SIZE_MENU);
+- gtk_widget_show (image631);
+- gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (viewHideLayer), image631);
+-
+ menuJournal = gtk_menu_item_new_with_mnemonic (_("_Journal"));
+ gtk_widget_show (menuJournal);
+ gtk_container_add (GTK_CONTAINER (menubar), menuJournal);
+--- 574,620 ----
+ gtk_container_add (GTK_CONTAINER (menuView_menu), separator5);
+ gtk_widget_set_sensitive (separator5, FALSE);
+
+! viewFirstPage = gtk_image_menu_item_new_with_mnemonic ("_First Page");
+ gtk_widget_show (viewFirstPage);
+ gtk_container_add (GTK_CONTAINER (menuView_menu), viewFirstPage);
+ gtk_widget_add_accelerator (viewFirstPage, "activate", accel_group,
+ GDK_Home, (GdkModifierType) GDK_CONTROL_MASK,
+ GTK_ACCEL_VISIBLE);
+
+! viewPreviousPage = gtk_image_menu_item_new_with_mnemonic ("_Previous Page");
+ gtk_widget_show (viewPreviousPage);
+ gtk_container_add (GTK_CONTAINER (menuView_menu), viewPreviousPage);
+ gtk_widget_add_accelerator (viewPreviousPage, "activate", accel_group,
+ GDK_Left, (GdkModifierType) GDK_CONTROL_MASK,
+ GTK_ACCEL_VISIBLE);
+
+! viewNextPage = gtk_image_menu_item_new_with_mnemonic ("_Next Page");
+ gtk_widget_show (viewNextPage);
+ gtk_container_add (GTK_CONTAINER (menuView_menu), viewNextPage);
+ gtk_widget_add_accelerator (viewNextPage, "activate", accel_group,
+ GDK_Right, (GdkModifierType) GDK_CONTROL_MASK,
+ GTK_ACCEL_VISIBLE);
+
+! viewLastPage = gtk_image_menu_item_new_with_mnemonic ("_Last Page");
+ gtk_widget_show (viewLastPage);
+ gtk_container_add (GTK_CONTAINER (menuView_menu), viewLastPage);
+ gtk_widget_add_accelerator (viewLastPage, "activate", accel_group,
+ GDK_End, (GdkModifierType) GDK_CONTROL_MASK,
+ GTK_ACCEL_VISIBLE);
+
+ separator6 = gtk_separator_menu_item_new ();
+ gtk_widget_show (separator6);
+ gtk_container_add (GTK_CONTAINER (menuView_menu), separator6);
+ gtk_widget_set_sensitive (separator6, FALSE);
+
+! viewShowLayer = gtk_image_menu_item_new_with_mnemonic ("_Show Layer");
+ gtk_widget_show (viewShowLayer);
+ gtk_container_add (GTK_CONTAINER (menuView_menu), viewShowLayer);
+
+! viewHideLayer = gtk_image_menu_item_new_with_mnemonic ("_Hide Layer");
+ gtk_widget_show (viewHideLayer);
+ gtk_container_add (GTK_CONTAINER (menuView_menu), viewHideLayer);
+
+ menuJournal = gtk_menu_item_new_with_mnemonic (_("_Journal"));
+ gtk_widget_show (menuJournal);
+ gtk_container_add (GTK_CONTAINER (menubar), menuJournal);
+***************
+*** 808,821 ****
+ gtk_container_add (GTK_CONTAINER (menuJournal_menu), separator23);
+ gtk_widget_set_sensitive (separator23, FALSE);
+
+! journalLoadBackground = gtk_image_menu_item_new_with_mnemonic (_("_Load Background"));
+ gtk_widget_show (journalLoadBackground);
+ gtk_container_add (GTK_CONTAINER (menuJournal_menu), journalLoadBackground);
+
+- image632 = gtk_image_new_from_stock ("gtk-open", GTK_ICON_SIZE_MENU);
+- gtk_widget_show (image632);
+- gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (journalLoadBackground), image632);
+-
+ journalScreenshot = gtk_menu_item_new_with_mnemonic (_("Background Screens_hot"));
+ gtk_widget_show (journalScreenshot);
+ gtk_container_add (GTK_CONTAINER (menuJournal_menu), journalScreenshot);
+--- 761,770 ----
+ gtk_container_add (GTK_CONTAINER (menuJournal_menu), separator23);
+ gtk_widget_set_sensitive (separator23, FALSE);
+
+! journalLoadBackground = gtk_image_menu_item_new_with_mnemonic ("_Load Background");
+ gtk_widget_show (journalLoadBackground);
+ gtk_container_add (GTK_CONTAINER (menuJournal_menu), journalLoadBackground);
+
+ journalScreenshot = gtk_menu_item_new_with_mnemonic (_("Background Screens_hot"));
+ gtk_widget_show (journalScreenshot);
+ gtk_container_add (GTK_CONTAINER (menuJournal_menu), journalScreenshot);
+***************
+*** 940,953 ****
+ gtk_container_add (GTK_CONTAINER (menuTools_menu), separator16);
+ gtk_widget_set_sensitive (separator16, FALSE);
+
+! toolsColor = gtk_image_menu_item_new_with_mnemonic (_("_Color"));
+ gtk_widget_show (toolsColor);
+ gtk_container_add (GTK_CONTAINER (menuTools_menu), toolsColor);
+
+- image633 = gtk_image_new_from_stock ("gtk-select-color", GTK_ICON_SIZE_MENU);
+- gtk_widget_show (image633);
+- gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (toolsColor), image633);
+-
+ toolsColor_menu = gtk_menu_new ();
+ gtk_menu_item_set_submenu (GTK_MENU_ITEM (toolsColor), toolsColor_menu);
+
+--- 889,898 ----
+ gtk_container_add (GTK_CONTAINER (menuTools_menu), separator16);
+ gtk_widget_set_sensitive (separator16, FALSE);
+
+! toolsColor = gtk_image_menu_item_new_with_mnemonic ("_Color");
+ gtk_widget_show (toolsColor);
+ gtk_container_add (GTK_CONTAINER (menuTools_menu), toolsColor);
+
+ toolsColor_menu = gtk_menu_new ();
+ gtk_menu_item_set_submenu (GTK_MENU_ITEM (toolsColor), toolsColor_menu);
+
+***************
+*** 1141,1157 ****
+ gtk_container_add (GTK_CONTAINER (toolsHighlighterOptions_menu), highlighterThick);
+ gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (highlighterThick), TRUE);
+
+! toolsTextFont = gtk_image_menu_item_new_with_mnemonic (_("Text _Font..."));
+ gtk_widget_show (toolsTextFont);
+ gtk_container_add (GTK_CONTAINER (menuTools_menu), toolsTextFont);
+ gtk_widget_add_accelerator (toolsTextFont, "activate", accel_group,
+ GDK_F, (GdkModifierType) GDK_CONTROL_MASK | GDK_SHIFT_MASK,
+ GTK_ACCEL_VISIBLE);
+
+- image634 = gtk_image_new_from_stock ("gtk-select-font", GTK_ICON_SIZE_MENU);
+- gtk_widget_show (image634);
+- gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (toolsTextFont), image634);
+-
+ separator10 = gtk_separator_menu_item_new ();
+ gtk_widget_show (separator10);
+ gtk_container_add (GTK_CONTAINER (menuTools_menu), separator10);
+--- 1086,1098 ----
+ gtk_container_add (GTK_CONTAINER (toolsHighlighterOptions_menu), highlighterThick);
+ gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (highlighterThick), TRUE);
+
+! toolsTextFont = gtk_image_menu_item_new_with_mnemonic ("Text _Font...");
+ gtk_widget_show (toolsTextFont);
+ gtk_container_add (GTK_CONTAINER (menuTools_menu), toolsTextFont);
+ gtk_widget_add_accelerator (toolsTextFont, "activate", accel_group,
+ GDK_F, (GdkModifierType) GDK_CONTROL_MASK | GDK_SHIFT_MASK,
+ GTK_ACCEL_VISIBLE);
+
+ separator10 = gtk_separator_menu_item_new ();
+ gtk_widget_show (separator10);
+ gtk_container_add (GTK_CONTAINER (menuTools_menu), separator10);
+***************
+*** 1588,1593 ****
+--- 1529,1545 ----
+ gtk_radio_tool_button_set_group (GTK_RADIO_TOOL_BUTTON (buttonText), buttonPen_group);
+ buttonPen_group = gtk_radio_tool_button_get_group (GTK_RADIO_TOOL_BUTTON (buttonText));
+
++ buttonImage = (GtkWidget*) gtk_radio_tool_button_new (NULL);
++ gtk_tool_button_set_label (GTK_TOOL_BUTTON (buttonImage), _("Image"));
++ tmp_image = gtk_image_new_from_stock ("gtk-orientation-portrait", tmp_toolbar_icon_size);
++ gtk_widget_show (tmp_image);
++ gtk_tool_button_set_icon_widget (GTK_TOOL_BUTTON (buttonImage), tmp_image);
++ gtk_widget_show (buttonImage);
++ gtk_container_add (GTK_CONTAINER (toolbarPen), buttonImage);
++ gtk_tool_item_set_tooltip (GTK_TOOL_ITEM (buttonImage), tooltips, _("Image"), NULL);
++ gtk_radio_tool_button_set_group (GTK_RADIO_TOOL_BUTTON (buttonImage), buttonPen_group);
++ buttonPen_group = gtk_radio_tool_button_get_group (GTK_RADIO_TOOL_BUTTON (buttonImage));
++
+ buttonReco = (GtkWidget*) gtk_toggle_tool_button_new ();
+ gtk_tool_button_set_label (GTK_TOOL_BUTTON (buttonReco), _("Shape Recognizer"));
+ tmp_image = create_pixmap (winMain, "shapes.png");
+***************
+*** 1669,1675 ****
+ gtk_widget_show (tmp_image);
+ buttonToolDefault = (GtkWidget*) gtk_tool_button_new (tmp_image, _("Default"));
+ gtk_widget_show (buttonToolDefault);
+- gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (buttonToolDefault), FALSE);
+ gtk_container_add (GTK_CONTAINER (toolbarPen), buttonToolDefault);
+ gtk_tool_item_set_tooltip (GTK_TOOL_ITEM (buttonToolDefault), tooltips, _("Default"), NULL);
+
+--- 1621,1626 ----
+***************
+*** 1694,1700 ****
+ gtk_widget_show (tmp_image);
+ gtk_tool_button_set_icon_widget (GTK_TOOL_BUTTON (buttonFine), tmp_image);
+ gtk_widget_show (buttonFine);
+- gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (buttonFine), FALSE);
+ gtk_container_add (GTK_CONTAINER (toolbarPen), buttonFine);
+ gtk_widget_set_size_request (buttonFine, 24, -1);
+ gtk_tool_item_set_tooltip (GTK_TOOL_ITEM (buttonFine), tooltips, _("Fine"), NULL);
+--- 1645,1650 ----
+***************
+*** 1707,1713 ****
+ gtk_widget_show (tmp_image);
+ gtk_tool_button_set_icon_widget (GTK_TOOL_BUTTON (buttonMedium), tmp_image);
+ gtk_widget_show (buttonMedium);
+- gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (buttonMedium), FALSE);
+ gtk_container_add (GTK_CONTAINER (toolbarPen), buttonMedium);
+ gtk_widget_set_size_request (buttonMedium, 24, -1);
+ gtk_tool_item_set_tooltip (GTK_TOOL_ITEM (buttonMedium), tooltips, _("Medium"), NULL);
+--- 1657,1662 ----
+***************
+*** 1720,1726 ****
+ gtk_widget_show (tmp_image);
+ gtk_tool_button_set_icon_widget (GTK_TOOL_BUTTON (buttonThick), tmp_image);
+ gtk_widget_show (buttonThick);
+- gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (buttonThick), FALSE);
+ gtk_container_add (GTK_CONTAINER (toolbarPen), buttonThick);
+ gtk_widget_set_size_request (buttonThick, 24, -1);
+ gtk_tool_item_set_tooltip (GTK_TOOL_ITEM (buttonThick), tooltips, _("Thick"), NULL);
+--- 1669,1674 ----
+***************
+*** 1747,1753 ****
+ gtk_widget_show (tmp_image);
+ gtk_tool_button_set_icon_widget (GTK_TOOL_BUTTON (buttonBlack), tmp_image);
+ gtk_widget_show (buttonBlack);
+- gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (buttonBlack), FALSE);
+ gtk_container_add (GTK_CONTAINER (toolbarPen), buttonBlack);
+ gtk_tool_item_set_tooltip (GTK_TOOL_ITEM (buttonBlack), tooltips, _("Black"), NULL);
+ gtk_radio_tool_button_set_group (GTK_RADIO_TOOL_BUTTON (buttonBlack), buttonBlack_group);
+--- 1695,1700 ----
+***************
+*** 1759,1765 ****
+ gtk_widget_show (tmp_image);
+ gtk_tool_button_set_icon_widget (GTK_TOOL_BUTTON (buttonBlue), tmp_image);
+ gtk_widget_show (buttonBlue);
+- gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (buttonBlue), FALSE);
+ gtk_container_add (GTK_CONTAINER (toolbarPen), buttonBlue);
+ gtk_tool_item_set_tooltip (GTK_TOOL_ITEM (buttonBlue), tooltips, _("Blue"), NULL);
+ gtk_radio_tool_button_set_group (GTK_RADIO_TOOL_BUTTON (buttonBlue), buttonBlack_group);
+--- 1706,1711 ----
+***************
+*** 1771,1777 ****
+ gtk_widget_show (tmp_image);
+ gtk_tool_button_set_icon_widget (GTK_TOOL_BUTTON (buttonRed), tmp_image);
+ gtk_widget_show (buttonRed);
+- gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (buttonRed), FALSE);
+ gtk_container_add (GTK_CONTAINER (toolbarPen), buttonRed);
+ gtk_tool_item_set_tooltip (GTK_TOOL_ITEM (buttonRed), tooltips, _("Red"), NULL);
+ gtk_radio_tool_button_set_group (GTK_RADIO_TOOL_BUTTON (buttonRed), buttonBlack_group);
+--- 1717,1722 ----
+***************
+*** 1783,1789 ****
+ gtk_widget_show (tmp_image);
+ gtk_tool_button_set_icon_widget (GTK_TOOL_BUTTON (buttonGreen), tmp_image);
+ gtk_widget_show (buttonGreen);
+- gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (buttonGreen), FALSE);
+ gtk_container_add (GTK_CONTAINER (toolbarPen), buttonGreen);
+ gtk_tool_item_set_tooltip (GTK_TOOL_ITEM (buttonGreen), tooltips, _("Green"), NULL);
+ gtk_radio_tool_button_set_group (GTK_RADIO_TOOL_BUTTON (buttonGreen), buttonBlack_group);
+--- 1728,1733 ----
+***************
+*** 1795,1801 ****
+ gtk_widget_show (tmp_image);
+ gtk_tool_button_set_icon_widget (GTK_TOOL_BUTTON (buttonGray), tmp_image);
+ gtk_widget_show (buttonGray);
+- gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (buttonGray), FALSE);
+ gtk_container_add (GTK_CONTAINER (toolbarPen), buttonGray);
+ gtk_tool_item_set_tooltip (GTK_TOOL_ITEM (buttonGray), tooltips, _("Gray"), NULL);
+ gtk_radio_tool_button_set_group (GTK_RADIO_TOOL_BUTTON (buttonGray), buttonBlack_group);
+--- 1739,1744 ----
+***************
+*** 1807,1813 ****
+ gtk_widget_show (tmp_image);
+ gtk_tool_button_set_icon_widget (GTK_TOOL_BUTTON (buttonLightBlue), tmp_image);
+ gtk_widget_show (buttonLightBlue);
+- gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (buttonLightBlue), FALSE);
+ gtk_container_add (GTK_CONTAINER (toolbarPen), buttonLightBlue);
+ gtk_tool_item_set_tooltip (GTK_TOOL_ITEM (buttonLightBlue), tooltips, _("Light Blue"), NULL);
+ gtk_radio_tool_button_set_group (GTK_RADIO_TOOL_BUTTON (buttonLightBlue), buttonBlack_group);
+--- 1750,1755 ----
+***************
+*** 1819,1825 ****
+ gtk_widget_show (tmp_image);
+ gtk_tool_button_set_icon_widget (GTK_TOOL_BUTTON (buttonLightGreen), tmp_image);
+ gtk_widget_show (buttonLightGreen);
+- gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (buttonLightGreen), FALSE);
+ gtk_container_add (GTK_CONTAINER (toolbarPen), buttonLightGreen);
+ gtk_tool_item_set_tooltip (GTK_TOOL_ITEM (buttonLightGreen), tooltips, _("Light Green"), NULL);
+ gtk_radio_tool_button_set_group (GTK_RADIO_TOOL_BUTTON (buttonLightGreen), buttonBlack_group);
+--- 1761,1766 ----
+***************
+*** 1831,1837 ****
+ gtk_widget_show (tmp_image);
+ gtk_tool_button_set_icon_widget (GTK_TOOL_BUTTON (buttonMagenta), tmp_image);
+ gtk_widget_show (buttonMagenta);
+- gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (buttonMagenta), FALSE);
+ gtk_container_add (GTK_CONTAINER (toolbarPen), buttonMagenta);
+ gtk_tool_item_set_tooltip (GTK_TOOL_ITEM (buttonMagenta), tooltips, _("Magenta"), NULL);
+ gtk_radio_tool_button_set_group (GTK_RADIO_TOOL_BUTTON (buttonMagenta), buttonBlack_group);
+--- 1772,1777 ----
+***************
+*** 1843,1849 ****
+ gtk_widget_show (tmp_image);
+ gtk_tool_button_set_icon_widget (GTK_TOOL_BUTTON (buttonOrange), tmp_image);
+ gtk_widget_show (buttonOrange);
+- gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (buttonOrange), FALSE);
+ gtk_container_add (GTK_CONTAINER (toolbarPen), buttonOrange);
+ gtk_tool_item_set_tooltip (GTK_TOOL_ITEM (buttonOrange), tooltips, _("Orange"), NULL);
+ gtk_radio_tool_button_set_group (GTK_RADIO_TOOL_BUTTON (buttonOrange), buttonBlack_group);
+--- 1783,1788 ----
+***************
+*** 1855,1861 ****
+ gtk_widget_show (tmp_image);
+ gtk_tool_button_set_icon_widget (GTK_TOOL_BUTTON (buttonYellow), tmp_image);
+ gtk_widget_show (buttonYellow);
+- gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (buttonYellow), FALSE);
+ gtk_container_add (GTK_CONTAINER (toolbarPen), buttonYellow);
+ gtk_tool_item_set_tooltip (GTK_TOOL_ITEM (buttonYellow), tooltips, _("Yellow"), NULL);
+ gtk_radio_tool_button_set_group (GTK_RADIO_TOOL_BUTTON (buttonYellow), buttonBlack_group);
+--- 1794,1799 ----
+***************
+*** 1867,1873 ****
+ gtk_widget_show (tmp_image);
+ gtk_tool_button_set_icon_widget (GTK_TOOL_BUTTON (buttonWhite), tmp_image);
+ gtk_widget_show (buttonWhite);
+- gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (buttonWhite), FALSE);
+ gtk_container_add (GTK_CONTAINER (toolbarPen), buttonWhite);
+ gtk_tool_item_set_tooltip (GTK_TOOL_ITEM (buttonWhite), tooltips, _("White"), NULL);
+ gtk_radio_tool_button_set_group (GTK_RADIO_TOOL_BUTTON (buttonWhite), buttonBlack_group);
+--- 1805,1810 ----
+***************
+*** 2426,2431 ****
+--- 2363,2371 ----
+ g_signal_connect ((gpointer) buttonText, "toggled",
+ G_CALLBACK (on_toolsText_activate),
+ NULL);
++ g_signal_connect ((gpointer) buttonImage, "toggled",
++ G_CALLBACK (on_toolsImage_activate),
++ NULL);
+ g_signal_connect ((gpointer) buttonReco, "toggled",
+ G_CALLBACK (on_toolsReco_activate),
+ NULL);
+***************
+*** 2513,2519 ****
+ GLADE_HOOKUP_OBJECT (winMain, menuFile_menu, "menuFile_menu");
+ GLADE_HOOKUP_OBJECT (winMain, fileNew, "fileNew");
+ GLADE_HOOKUP_OBJECT (winMain, fileNewBackground, "fileNewBackground");
+- GLADE_HOOKUP_OBJECT (winMain, image623, "image623");
+ GLADE_HOOKUP_OBJECT (winMain, fileOpen, "fileOpen");
+ GLADE_HOOKUP_OBJECT (winMain, fileSave, "fileSave");
+ GLADE_HOOKUP_OBJECT (winMain, fileSaveAs, "fileSaveAs");
+--- 2453,2458 ----
+***************
+*** 2530,2536 ****
+ GLADE_HOOKUP_OBJECT (winMain, mru7, "mru7");
+ GLADE_HOOKUP_OBJECT (winMain, separator22, "separator22");
+ GLADE_HOOKUP_OBJECT (winMain, filePrintOptions, "filePrintOptions");
+- GLADE_HOOKUP_OBJECT (winMain, image624, "image624");
+ GLADE_HOOKUP_OBJECT (winMain, filePrint, "filePrint");
+ GLADE_HOOKUP_OBJECT (winMain, filePrintPDF, "filePrintPDF");
+ GLADE_HOOKUP_OBJECT (winMain, separator2, "separator2");
+--- 2469,2474 ----
+***************
+*** 2557,2578 ****
+ GLADE_HOOKUP_OBJECT (winMain, viewZoomOut, "viewZoomOut");
+ GLADE_HOOKUP_OBJECT (winMain, viewNormalSize, "viewNormalSize");
+ GLADE_HOOKUP_OBJECT (winMain, viewPageWidth, "viewPageWidth");
+- GLADE_HOOKUP_OBJECT (winMain, image625, "image625");
+ GLADE_HOOKUP_OBJECT (winMain, viewSetZoom, "viewSetZoom");
+ GLADE_HOOKUP_OBJECT (winMain, separator5, "separator5");
+ GLADE_HOOKUP_OBJECT (winMain, viewFirstPage, "viewFirstPage");
+- GLADE_HOOKUP_OBJECT (winMain, image626, "image626");
+ GLADE_HOOKUP_OBJECT (winMain, viewPreviousPage, "viewPreviousPage");
+- GLADE_HOOKUP_OBJECT (winMain, image627, "image627");
+ GLADE_HOOKUP_OBJECT (winMain, viewNextPage, "viewNextPage");
+- GLADE_HOOKUP_OBJECT (winMain, image628, "image628");
+ GLADE_HOOKUP_OBJECT (winMain, viewLastPage, "viewLastPage");
+- GLADE_HOOKUP_OBJECT (winMain, image629, "image629");
+ GLADE_HOOKUP_OBJECT (winMain, separator6, "separator6");
+ GLADE_HOOKUP_OBJECT (winMain, viewShowLayer, "viewShowLayer");
+- GLADE_HOOKUP_OBJECT (winMain, image630, "image630");
+ GLADE_HOOKUP_OBJECT (winMain, viewHideLayer, "viewHideLayer");
+- GLADE_HOOKUP_OBJECT (winMain, image631, "image631");
+ GLADE_HOOKUP_OBJECT (winMain, menuJournal, "menuJournal");
+ GLADE_HOOKUP_OBJECT (winMain, menuJournal_menu, "menuJournal_menu");
+ GLADE_HOOKUP_OBJECT (winMain, journalNewPageBefore, "journalNewPageBefore");
+--- 2495,2509 ----
+***************
+*** 2605,2611 ****
+ GLADE_HOOKUP_OBJECT (winMain, journalApplyAllPages, "journalApplyAllPages");
+ GLADE_HOOKUP_OBJECT (winMain, separator23, "separator23");
+ GLADE_HOOKUP_OBJECT (winMain, journalLoadBackground, "journalLoadBackground");
+- GLADE_HOOKUP_OBJECT (winMain, image632, "image632");
+ GLADE_HOOKUP_OBJECT (winMain, journalScreenshot, "journalScreenshot");
+ GLADE_HOOKUP_OBJECT (winMain, separator19, "separator19");
+ GLADE_HOOKUP_OBJECT (winMain, journalDefaultBackground, "journalDefaultBackground");
+--- 2536,2541 ----
+***************
+*** 2626,2632 ****
+ GLADE_HOOKUP_OBJECT (winMain, toolsHand, "toolsHand");
+ GLADE_HOOKUP_OBJECT (winMain, separator16, "separator16");
+ GLADE_HOOKUP_OBJECT (winMain, toolsColor, "toolsColor");
+- GLADE_HOOKUP_OBJECT (winMain, image633, "image633");
+ GLADE_HOOKUP_OBJECT (winMain, toolsColor_menu, "toolsColor_menu");
+ GLADE_HOOKUP_OBJECT (winMain, colorBlack, "colorBlack");
+ GLADE_HOOKUP_OBJECT (winMain, colorBlue, "colorBlue");
+--- 2556,2561 ----
+***************
+*** 2664,2670 ****
+ GLADE_HOOKUP_OBJECT (winMain, highlighterMedium, "highlighterMedium");
+ GLADE_HOOKUP_OBJECT (winMain, highlighterThick, "highlighterThick");
+ GLADE_HOOKUP_OBJECT (winMain, toolsTextFont, "toolsTextFont");
+- GLADE_HOOKUP_OBJECT (winMain, image634, "image634");
+ GLADE_HOOKUP_OBJECT (winMain, separator10, "separator10");
+ GLADE_HOOKUP_OBJECT (winMain, toolsDefaultPen, "toolsDefaultPen");
+ GLADE_HOOKUP_OBJECT (winMain, toolsDefaultEraser, "toolsDefaultEraser");
+--- 2593,2598 ----
+***************
+*** 2750,2755 ****
+--- 2678,2684 ----
+ GLADE_HOOKUP_OBJECT (winMain, buttonEraser, "buttonEraser");
+ GLADE_HOOKUP_OBJECT (winMain, buttonHighlighter, "buttonHighlighter");
+ GLADE_HOOKUP_OBJECT (winMain, buttonText, "buttonText");
++ GLADE_HOOKUP_OBJECT (winMain, buttonImage, "buttonImage");
+ GLADE_HOOKUP_OBJECT (winMain, buttonReco, "buttonReco");
+ GLADE_HOOKUP_OBJECT (winMain, buttonRuler, "buttonRuler");
+ GLADE_HOOKUP_OBJECT (winMain, toolitem15, "toolitem15");
+***************
+*** 2860,2865 ****
+--- 2789,2795 ----
+ entryWidth = gtk_entry_new ();
+ gtk_widget_show (entryWidth);
+ gtk_box_pack_start (GTK_BOX (hbox3), entryWidth, TRUE, TRUE, 0);
++ gtk_entry_set_invisible_char (GTK_ENTRY (entryWidth), 9679);
+ gtk_entry_set_width_chars (GTK_ENTRY (entryWidth), 5);
+
+ labelHeight = gtk_label_new (_("Height:"));
+***************
+*** 2869,2874 ****
+--- 2799,2805 ----
+ entryHeight = gtk_entry_new ();
+ gtk_widget_show (entryHeight);
+ gtk_box_pack_start (GTK_BOX (hbox3), entryHeight, TRUE, TRUE, 0);
++ gtk_entry_set_invisible_char (GTK_ENTRY (entryHeight), 9679);
+ gtk_entry_set_width_chars (GTK_ENTRY (entryHeight), 5);
+
+ comboUnit = gtk_combo_box_new_text ();
+***************
+*** 2951,2962 ****
+ labelTitle = gtk_label_new (_("Xournal"));
+ gtk_widget_show (labelTitle);
+ gtk_box_pack_start (GTK_BOX (dialog_vbox2), labelTitle, FALSE, FALSE, 3);
+- gtk_label_set_justify (GTK_LABEL (labelTitle), GTK_JUSTIFY_CENTER);
+
+ labelInfo = gtk_label_new (_("Written by Denis Auroux\nand other contributors\n http://xournal.sourceforge.net/ "));
+ gtk_widget_show (labelInfo);
+ gtk_box_pack_start (GTK_BOX (dialog_vbox2), labelInfo, FALSE, FALSE, 0);
+- gtk_label_set_justify (GTK_LABEL (labelInfo), GTK_JUSTIFY_CENTER);
+ gtk_misc_set_padding (GTK_MISC (labelInfo), 20, 10);
+
+ dialog_action_area2 = GTK_DIALOG (aboutDialog)->action_area;
+--- 2882,2891 ----
+diff -c 'xournal-0.4.5/src/xo-misc.c' 'xournal/src/xo-misc.c'
+Index: ./src/xo-misc.c
+*** ./src/xo-misc.c Fri Oct 2 20:20:30 2009
+--- ./src/xo-misc.c Thu Jul 29 16:11:24 2010
+***************
+*** 17,22 ****
+--- 17,23 ----
+ #include "xo-file.h"
+ #include "xo-paint.h"
+ #include "xo-shapes.h"
++ #include "xo-image.h"
+
+ // some global constants
+
+***************
+*** 90,95 ****
+--- 91,121 ----
+ return pg;
+ }
+
++ // change the current page if necessary for pointer at pt
++ void set_current_page(gdouble *pt)
++ {
++ gboolean page_change;
++ struct Page *tmppage;
++
++ page_change = FALSE;
++ tmppage = ui.cur_page;
++ while (ui.view_continuous && (pt[1] < - VIEW_CONTINUOUS_SKIP)) {
++ if (ui.pageno == 0) break;
++ page_change = TRUE;
++ ui.pageno--;
++ tmppage = g_list_nth_data(journal.pages, ui.pageno);
++ pt[1] += tmppage->height + VIEW_CONTINUOUS_SKIP;
++ }
++ while (ui.view_continuous && (pt[1] > tmppage->height + VIEW_CONTINUOUS_SKIP)) {
++ if (ui.pageno == journal.npages-1) break;
++ pt[1] -= tmppage->height + VIEW_CONTINUOUS_SKIP;
++ page_change = TRUE;
++ ui.pageno++;
++ tmppage = g_list_nth_data(journal.pages, ui.pageno);
++ }
++ if (page_change) do_switch_page(ui.pageno, FALSE, FALSE);
++ }
++
+ void realloc_cur_path(int n)
+ {
+ if (n <= ui.cur_path_storage_alloc) return;
+***************
+*** 142,147 ****
+--- 168,179 ----
+ g_free(redo->item->font_name);
+ g_free(redo->item);
+ }
++ else if (redo->type == ITEM_IMAGE) {
++ g_object_unref(redo->item->image);
++ if (redo->item->image_scaled != NULL) g_object_unref(redo->item->image_scaled);
++ g_free(redo->item->image_png);
++ g_free(redo->item);
++ }
+ else if (redo->type == ITEM_ERASURE || redo->type == ITEM_RECOGNIZER) {
+ for (list = redo->erasurelist; list!=NULL; list=list->next) {
+ erasure = (struct UndoErasureData *)list->data;
+***************
+*** 218,223 ****
+--- 250,260 ----
+ }
+ if (erasure->item->type == ITEM_TEXT)
+ { g_free(erasure->item->text); g_free(erasure->item->font_name); }
++ if (erasure->item->type == ITEM_IMAGE) {
++ g_object_unref(erasure->item->image);
++ if (erasure->item->image_scaled != NULL) g_object_unref(erasure->item->image_scaled);
++ g_free(erasure->item->image_png);
++ }
+ g_free(erasure->item);
+ g_list_free(erasure->replacement_items);
+ g_free(erasure);
+***************
+*** 302,307 ****
+--- 339,349 ----
+ if (item->type == ITEM_TEXT) {
+ g_free(item->font_name); g_free(item->text);
+ }
++ if (item->type == ITEM_IMAGE) {
++ g_object_unref(item->image);
++ if (item->image_scaled != NULL) g_object_unref(item->image_scaled);
++ g_free(item->image_png);
++ }
+ // don't need to delete the canvas_item, as it's part of the group destroyed below
+ g_free(item);
+ l->items = g_list_delete_link(l->items, l->items);
+***************
+*** 350,355 ****
+--- 392,409 ----
+ ret[1] -= ui.cur_page->voffset;
+ }
+
++ // get the current pointer position in canvas world coordinates
++ void get_current_pointer_coords(gdouble *ret)
++ {
++ gint wx, wy, sx, sy;
++
++ gtk_widget_get_pointer((GtkWidget *)canvas, &wx, &wy);
++ gnome_canvas_get_scroll_offsets(canvas, &sx, &sy);
++ gnome_canvas_window_to_world(canvas, (double)(wx + sx), (double)(wy + sy), ret, ret+1);
++ ret[0] -= ui.cur_page->hoffset;
++ ret[1] -= ui.cur_page->voffset;
++ }
++
+ void fix_xinput_coords(GdkEvent *event)
+ {
+ double *axes, *px, *py, axis_width;
+***************
+*** 440,446 ****
+ {
+ int i;
+ gdouble *p, h, w;
+!
+ if (item->type == ITEM_STROKE) {
+ item->bbox.left = item->bbox.right = item->path->coords[0];
+ item->bbox.top = item->bbox.bottom = item->path->coords[1];
+--- 494,501 ----
+ {
+ int i;
+ gdouble *p, h, w;
+! gboolean width_in_pixels, height_in_pixels;
+!
+ if (item->type == ITEM_STROKE) {
+ item->bbox.left = item->bbox.right = item->path->coords[0];
+ item->bbox.top = item->bbox.bottom = item->path->coords[1];
+***************
+*** 458,463 ****
+--- 513,534 ----
+ item->bbox.right = item->bbox.left + w;
+ item->bbox.bottom = item->bbox.top + h;
+ }
++ if (item->type == ITEM_IMAGE && item->canvas_item!=NULL) {
++ // be careful in case canvas item size in pixels
++ h=0.; w=0.;
++ g_object_get(item->canvas_item, "width", &w, "height", &h,
++ "width-in-pixels", &width_in_pixels,
++ "height-in-pixels", &height_in_pixels,
++ NULL);
++ if (width_in_pixels) {
++ w /= ui.zoom;
++ }
++ if (height_in_pixels) {
++ h /= ui.zoom;
++ }
++ item->bbox.right = item->bbox.left + w;
++ item->bbox.bottom = item->bbox.top + h;
++ }
+ }
+
+ void make_page_clipbox(struct Page *pg)
+***************
+*** 474,483 ****
+--- 545,640 ----
+ gnome_canvas_path_def_unref(pg_clip);
+ }
+
++ void adjust_or_make_canvas_item_image(GnomeCanvasGroup *group, struct Item *item)
++ {
++ double required_width;
++ double required_height;
++
++ // discard previous scaled image, if any
++ if ( item->image_scaled != NULL ) {
++ g_object_unref(item->image_scaled);
++ item->image_scaled = NULL;
++ }
++
++ if ( is_native_image_usable( item ) ) {
++ // use native resolution, for sharper image
++ if (item->canvas_item == NULL) {
++ // first time, create new canvas item
++ item->canvas_item = gnome_canvas_item_new(group,
++ GNOME_TYPE_CANVAS_PIXBUF,
++ "anchor", GTK_ANCHOR_NW,
++ "height-in-pixels", TRUE,
++ "width-in-pixels", TRUE,
++ "x-in-pixels", FALSE,
++ "y-in-pixels", FALSE,
++ "pixbuf", item->image,
++ "x", item->bbox.left,
++ "y", item->bbox.top,
++ "height", (double)gdk_pixbuf_get_height(item->image),
++ "width", (double)gdk_pixbuf_get_width(item->image),
++ NULL);
++ } else {
++ // update the existing one, which may have been for a scaled image
++ gnome_canvas_item_set(item->canvas_item,
++ "height-in-pixels", TRUE,
++ "width-in-pixels", TRUE,
++ "pixbuf", item->image,
++ "height", (double)gdk_pixbuf_get_height(item->image),
++ "width", (double)gdk_pixbuf_get_width(item->image),
++ NULL);
++ }
++ } else {
++ // settle for scaled (and blurry) image
++ required_width = item->bbox.right - item->bbox.left;
++ required_height = item->bbox.bottom - item->bbox.top;
++
++ item->image_scaled = gdk_pixbuf_scale_simple(item->image,
++ required_width,
++ required_height,
++ GDK_INTERP_HYPER);
++ if (item->canvas_item == NULL) {
++ // first time, create new canvas item
++ item->canvas_item = gnome_canvas_item_new(group,
++ GNOME_TYPE_CANVAS_PIXBUF,
++ "anchor", GTK_ANCHOR_NW,
++ "height-in-pixels", FALSE,
++ "width-in-pixels", FALSE,
++ "x-in-pixels", FALSE,
++ "y-in-pixels", FALSE,
++ "pixbuf", item->image_scaled,
++ "x", item->bbox.left,
++ "y", item->bbox.top,
++ "height", required_height,
++ "width", required_width,
++ NULL);
++ } else {
++ // update the existing one, which may have been for a scaled image
++ gnome_canvas_item_set(item->canvas_item,
++ "height-in-pixels", FALSE,
++ "width-in-pixels", FALSE,
++ "pixbuf", item->image_scaled,
++ "height", required_height,
++ "width", required_width,
++ NULL);
++ }
++ }
++
++ // reposition the canvas item absolutely, and reset the affine transformation
++ gnome_canvas_item_affine_absolute(item->canvas_item, NULL);
++ gnome_canvas_item_set(item->canvas_item,
++ "x", item->bbox.left,
++ "y", item->bbox.top,
++ NULL);
++ }
++
+ void make_canvas_item_one(GnomeCanvasGroup *group, struct Item *item)
+ {
+ PangoFontDescription *font_desc;
+ GnomeCanvasPoints points;
++ GtkFileFilter *filt_all;
++ GtkFileFilter *filt_gdkimage;
++ GtkWidget *dialog;
++ char *tmp_filename;
+ int j;
+
+ if (item->type == ITEM_STROKE) {
+***************
+*** 513,518 ****
+--- 670,678 ----
+ "text", item->text, NULL);
+ update_item_bbox(item);
+ }
++ if (item->type == ITEM_IMAGE) {
++ adjust_or_make_canvas_item_image(group, item);
++ }
+ }
+
+ void make_canvas_items(void)
+***************
+*** 861,866 ****
+--- 1021,1031 ----
+ gtk_toggle_tool_button_set_active(
+ GTK_TOGGLE_TOOL_BUTTON(GET_COMPONENT("buttonText")), TRUE);
+ break;
++
++ case TOOL_IMAGE:
++ gtk_toggle_tool_button_set_active(
++ GTK_TOGGLE_TOOL_BUTTON(GET_COMPONENT("buttonImage")), TRUE);
++ break;
+ case TOOL_SELECTREGION:
+ gtk_toggle_tool_button_set_active(
+ GTK_TOGGLE_TOOL_BUTTON(GET_COMPONENT("buttonSelectRegion")), TRUE);
+***************
+*** 1377,1383 ****
+ gtk_widget_set_sensitive(GET_COMPONENT("viewHideLayer"), ui.layerno>=0);
+
+ gtk_widget_set_sensitive(GET_COMPONENT("editPaste"), ui.cur_layer!=NULL);
+! gtk_widget_set_sensitive(GET_COMPONENT("buttonPaste"), ui.cur_layer!=NULL);
+ }
+
+ void update_toolbar_and_menu(void)
+--- 1542,1549 ----
+ gtk_widget_set_sensitive(GET_COMPONENT("viewHideLayer"), ui.layerno>=0);
+
+ gtk_widget_set_sensitive(GET_COMPONENT("editPaste"), ui.cur_layer!=NULL);
+!
+! gtk_widget_set_sensitive(GET_COMPONENT("buttonPaste"), ui.cur_layer!=NULL);
+ }
+
+ void update_toolbar_and_menu(void)
+***************
+*** 1716,1722 ****
+ if (item->type == ITEM_STROKE)
+ for (pt=item->path->coords, i=0; i<item->path->num_points; i++, pt+=2)
+ { pt[0] += dx; pt[1] += dy; }
+! if (item->type == ITEM_STROKE || item->type == ITEM_TEXT || item->type == ITEM_TEMP_TEXT) {
+ item->bbox.left += dx;
+ item->bbox.right += dx;
+ item->bbox.top += dy;
+--- 1882,1888 ----
+ if (item->type == ITEM_STROKE)
+ for (pt=item->path->coords, i=0; i<item->path->num_points; i++, pt+=2)
+ { pt[0] += dx; pt[1] += dy; }
+! if (item->type == ITEM_STROKE || item->type == ITEM_TEXT || item->type == ITEM_TEMP_TEXT || item->type==ITEM_IMAGE) {
+ item->bbox.left += dx;
+ item->bbox.right += dx;
+ item->bbox.top += dy;
+***************
+*** 1799,1809 ****
+ item->bbox.left = item->bbox.left*scaling_x + offset_x;
+ item->bbox.top = item->bbox.top*scaling_y + offset_y;
+ }
+ // redraw the item
+ if (item->canvas_item!=NULL) {
+ group = (GnomeCanvasGroup *) item->canvas_item->parent;
+! gtk_object_destroy(GTK_OBJECT(item->canvas_item));
+! make_canvas_item_one(group, item);
+ }
+ }
+ }
+--- 1965,1995 ----
+ item->bbox.left = item->bbox.left*scaling_x + offset_x;
+ item->bbox.top = item->bbox.top*scaling_y + offset_y;
+ }
++ if (item->type == ITEM_IMAGE) {
++ item->bbox.left = item->bbox.left*scaling_x + offset_x;
++ item->bbox.right = item->bbox.right*scaling_x + offset_x;
++ item->bbox.top = item->bbox.top*scaling_y + offset_y;
++ item->bbox.bottom = item->bbox.bottom*scaling_y + offset_y;
++ if (item->bbox.left > item->bbox.right) {
++ temp = item->bbox.left;
++ item->bbox.left = item->bbox.right;
++ item->bbox.right = temp;
++ }
++ if (item->bbox.top > item->bbox.bottom) {
++ temp = item->bbox.top;
++ item->bbox.top = item->bbox.bottom;
++ item->bbox.bottom = temp;
++ }
++ }
+ // redraw the item
+ if (item->canvas_item!=NULL) {
+ group = (GnomeCanvasGroup *) item->canvas_item->parent;
+! if (item->type == ITEM_IMAGE) {
+! adjust_or_make_canvas_item_image(group, item);
+! } else {
+! gtk_object_destroy(GTK_OBJECT(item->canvas_item));
+! make_canvas_item_one(group, item);
+! }
+ }
+ }
+ }
+diff -c 'xournal-0.4.5/src/xo-misc.h' 'xournal/src/xo-misc.h'
+Index: ./src/xo-misc.h
+*** ./src/xo-misc.h Mon Sep 28 16:45:56 2009
+--- ./src/xo-misc.h Sun Jun 27 16:18:01 2010
+***************
+*** 2,7 ****
+--- 2,8 ----
+
+ struct Page *new_page(struct Page *template);
+ struct Page *new_page_with_bg(struct Background *bg, double width, double height);
++ void set_current_page(gdouble *pt);
+ void realloc_cur_path(int n);
+ void realloc_cur_widths(int n);
+ void clear_redo_stack(void);
+***************
+*** 20,30 ****
+--- 21,33 ----
+ // helper functions
+
+ void get_pointer_coords(GdkEvent *event, double *ret);
++ void get_current_pointer_coords(double *ret);
+ double get_pressure_multiplier(GdkEvent *event);
+ void fix_xinput_coords(GdkEvent *event);
+ void update_item_bbox(struct Item *item);
+ void make_page_clipbox(struct Page *pg);
+ void make_canvas_items(void);
++ void adjust_or_make_canvas_item_image(GnomeCanvasGroup *group, struct Item *item);
+ void make_canvas_item_one(GnomeCanvasGroup *group, struct Item *item);
+ void update_canvas_bg(struct Page *pg);
+ gboolean is_visible(struct Page *pg);
+diff -c 'xournal-0.4.5/src/xo-paint.c' 'xournal/src/xo-paint.c'
+Index: ./src/xo-paint.c
+*** ./src/xo-paint.c Mon Sep 28 09:54:18 2009
+--- ./src/xo-paint.c Thu Jul 29 16:01:42 2010
+***************
+*** 879,1089 ****
+ the forward direction */
+ }
+
+- void callback_clipboard_get(GtkClipboard *clipboard,
+- GtkSelectionData *selection_data,
+- guint info, gpointer user_data)
+- {
+- int length;
+-
+- g_memmove(&length, user_data, sizeof(int));
+- gtk_selection_data_set(selection_data,
+- gdk_atom_intern("_XOURNAL", FALSE), 8, user_data, length);
+- }
+-
+- void callback_clipboard_clear(GtkClipboard *clipboard, gpointer user_data)
+- {
+- g_free(user_data);
+- }
+-
+- void selection_to_clip(void)
+- {
+- int bufsz, nitems, val;
+- char *buf, *p;
+- GList *list;
+- struct Item *item;
+- GtkTargetEntry target;
+-
+- if (ui.selection == NULL) return;
+- bufsz = 2*sizeof(int) // bufsz, nitems
+- + sizeof(struct BBox); // bbox
+- nitems = 0;
+- for (list = ui.selection->items; list != NULL; list = list->next) {
+- item = (struct Item *)list->data;
+- nitems++;
+- if (item->type == ITEM_STROKE) {
+- bufsz+= sizeof(int) // type
+- + sizeof(struct Brush) // brush
+- + sizeof(int) // num_points
+- + 2*item->path->num_points*sizeof(double); // the points
+- if (item->brush.variable_width)
+- bufsz += (item->path->num_points-1)*sizeof(double); // the widths
+- }
+- else if (item->type == ITEM_TEXT) {
+- bufsz+= sizeof(int) // type
+- + sizeof(struct Brush) // brush
+- + 2*sizeof(double) // bbox upper-left
+- + sizeof(int) // text len
+- + strlen(item->text)+1 // text
+- + sizeof(int) // font_name len
+- + strlen(item->font_name)+1 // font_name
+- + sizeof(double); // font_size
+- }
+- else bufsz+= sizeof(int); // type
+- }
+- p = buf = g_malloc(bufsz);
+- g_memmove(p, &bufsz, sizeof(int)); p+= sizeof(int);
+- g_memmove(p, &nitems, sizeof(int)); p+= sizeof(int);
+- g_memmove(p, &ui.selection->bbox, sizeof(struct BBox)); p+= sizeof(struct BBox);
+- for (list = ui.selection->items; list != NULL; list = list->next) {
+- item = (struct Item *)list->data;
+- g_memmove(p, &item->type, sizeof(int)); p+= sizeof(int);
+- if (item->type == ITEM_STROKE) {
+- g_memmove(p, &item->brush, sizeof(struct Brush)); p+= sizeof(struct Brush);
+- g_memmove(p, &item->path->num_points, sizeof(int)); p+= sizeof(int);
+- g_memmove(p, item->path->coords, 2*item->path->num_points*sizeof(double));
+- p+= 2*item->path->num_points*sizeof(double);
+- if (item->brush.variable_width) {
+- g_memmove(p, item->widths, (item->path->num_points-1)*sizeof(double));
+- p+= (item->path->num_points-1)*sizeof(double);
+- }
+- }
+- if (item->type == ITEM_TEXT) {
+- g_memmove(p, &item->brush, sizeof(struct Brush)); p+= sizeof(struct Brush);
+- g_memmove(p, &item->bbox.left, sizeof(double)); p+= sizeof(double);
+- g_memmove(p, &item->bbox.top, sizeof(double)); p+= sizeof(double);
+- val = strlen(item->text);
+- g_memmove(p, &val, sizeof(int)); p+= sizeof(int);
+- g_memmove(p, item->text, val+1); p+= val+1;
+- val = strlen(item->font_name);
+- g_memmove(p, &val, sizeof(int)); p+= sizeof(int);
+- g_memmove(p, item->font_name, val+1); p+= val+1;
+- g_memmove(p, &item->font_size, sizeof(double)); p+= sizeof(double);
+- }
+- }
+-
+- target.target = "_XOURNAL";
+- target.flags = 0;
+- target.info = 0;
+-
+- gtk_clipboard_set_with_data(gtk_clipboard_get(GDK_SELECTION_CLIPBOARD),
+- &target, 1,
+- callback_clipboard_get, callback_clipboard_clear, buf);
+- }
+-
+-
+- void clipboard_paste(void)
+- {
+- GtkSelectionData *sel_data;
+- unsigned char *p;
+- int nitems, npts, i, len;
+- struct Item *item;
+- double hoffset, voffset, cx, cy;
+- double *pf;
+- int sx, sy, wx, wy;
+-
+- if (ui.cur_layer == NULL) return;
+-
+- ui.cur_item_type = ITEM_PASTE;
+- sel_data = gtk_clipboard_wait_for_contents(
+- gtk_clipboard_get(GDK_SELECTION_CLIPBOARD),
+- gdk_atom_intern("_XOURNAL", FALSE));
+- ui.cur_item_type = ITEM_NONE;
+- if (sel_data == NULL) return; // paste failed
+-
+- reset_selection();
+-
+- ui.selection = g_new(struct Selection, 1);
+- p = sel_data->data + sizeof(int);
+- g_memmove(&nitems, p, sizeof(int)); p+= sizeof(int);
+- ui.selection->type = ITEM_SELECTRECT;
+- ui.selection->layer = ui.cur_layer;
+- g_memmove(&ui.selection->bbox, p, sizeof(struct BBox)); p+= sizeof(struct BBox);
+- ui.selection->items = NULL;
+-
+- // find by how much we translate the pasted selection
+- gnome_canvas_get_scroll_offsets(canvas, &sx, &sy);
+- gdk_window_get_geometry(GTK_WIDGET(canvas)->window, NULL, NULL, &wx, &wy, NULL);
+- gnome_canvas_window_to_world(canvas, sx + wx/2, sy + wy/2, &cx, &cy);
+- cx -= ui.cur_page->hoffset;
+- cy -= ui.cur_page->voffset;
+- if (cx + (ui.selection->bbox.right-ui.selection->bbox.left)/2 > ui.cur_page->width)
+- cx = ui.cur_page->width - (ui.selection->bbox.right-ui.selection->bbox.left)/2;
+- if (cx - (ui.selection->bbox.right-ui.selection->bbox.left)/2 < 0)
+- cx = (ui.selection->bbox.right-ui.selection->bbox.left)/2;
+- if (cy + (ui.selection->bbox.bottom-ui.selection->bbox.top)/2 > ui.cur_page->height)
+- cy = ui.cur_page->height - (ui.selection->bbox.bottom-ui.selection->bbox.top)/2;
+- if (cy - (ui.selection->bbox.bottom-ui.selection->bbox.top)/2 < 0)
+- cy = (ui.selection->bbox.bottom-ui.selection->bbox.top)/2;
+- hoffset = cx - (ui.selection->bbox.right+ui.selection->bbox.left)/2;
+- voffset = cy - (ui.selection->bbox.top+ui.selection->bbox.bottom)/2;
+- ui.selection->bbox.left += hoffset;
+- ui.selection->bbox.right += hoffset;
+- ui.selection->bbox.top += voffset;
+- ui.selection->bbox.bottom += voffset;
+-
+- ui.selection->canvas_item = gnome_canvas_item_new(ui.cur_layer->group,
+- gnome_canvas_rect_get_type(), "width-pixels", 1,
+- "outline-color-rgba", 0x000000ff,
+- "fill-color-rgba", 0x80808040,
+- "x1", ui.selection->bbox.left, "x2", ui.selection->bbox.right,
+- "y1", ui.selection->bbox.top, "y2", ui.selection->bbox.bottom, NULL);
+- make_dashed(ui.selection->canvas_item);
+-
+- while (nitems-- > 0) {
+- item = g_new(struct Item, 1);
+- ui.selection->items = g_list_append(ui.selection->items, item);
+- ui.cur_layer->items = g_list_append(ui.cur_layer->items, item);
+- ui.cur_layer->nitems++;
+- g_memmove(&item->type, p, sizeof(int)); p+= sizeof(int);
+- if (item->type == ITEM_STROKE) {
+- g_memmove(&item->brush, p, sizeof(struct Brush)); p+= sizeof(struct Brush);
+- g_memmove(&npts, p, sizeof(int)); p+= sizeof(int);
+- item->path = gnome_canvas_points_new(npts);
+- pf = (double *)p;
+- for (i=0; i<npts; i++) {
+- item->path->coords[2*i] = pf[2*i] + hoffset;
+- item->path->coords[2*i+1] = pf[2*i+1] + voffset;
+- }
+- p+= 2*item->path->num_points*sizeof(double);
+- if (item->brush.variable_width) {
+- item->widths = g_memdup(p, (item->path->num_points-1)*sizeof(double));
+- p+= (item->path->num_points-1)*sizeof(double);
+- }
+- else item->widths = NULL;
+- update_item_bbox(item);
+- make_canvas_item_one(ui.cur_layer->group, item);
+- }
+- if (item->type == ITEM_TEXT) {
+- g_memmove(&item->brush, p, sizeof(struct Brush)); p+= sizeof(struct Brush);
+- g_memmove(&item->bbox.left, p, sizeof(double)); p+= sizeof(double);
+- g_memmove(&item->bbox.top, p, sizeof(double)); p+= sizeof(double);
+- item->bbox.left += hoffset;
+- item->bbox.top += voffset;
+- g_memmove(&len, p, sizeof(int)); p+= sizeof(int);
+- item->text = g_malloc(len+1);
+- g_memmove(item->text, p, len+1); p+= len+1;
+- g_memmove(&len, p, sizeof(int)); p+= sizeof(int);
+- item->font_name = g_malloc(len+1);
+- g_memmove(item->font_name, p, len+1); p+= len+1;
+- g_memmove(&item->font_size, p, sizeof(double)); p+= sizeof(double);
+- make_canvas_item_one(ui.cur_layer->group, item);
+- }
+- }
+-
+- prepare_new_undo();
+- undo->type = ITEM_PASTE;
+- undo->layer = ui.cur_layer;
+- undo->itemlist = g_list_copy(ui.selection->items);
+-
+- gtk_selection_data_free(sel_data);
+- update_copy_paste_enabled();
+- update_color_menu();
+- update_thickness_buttons();
+- update_color_buttons();
+- update_font_button();
+- update_cursor(); // FIXME: can't know if pointer is within selection!
+- }
+-
+ // modify the color or thickness of pen strokes in a selection
+
+ void recolor_selection(int color_no, guint color_rgba)
+--- 879,884 ----
+diff -c 'xournal-0.4.5/src/xo-paint.h' 'xournal/src/xo-paint.h'
+Index: ./src/xo-paint.h
+*** ./src/xo-paint.h Thu Sep 17 16:49:04 2009
+--- ./src/xo-paint.h Thu Apr 15 16:25:13 2010
+***************
+*** 22,29 ****
+ void finalize_resizesel(void);
+
+ void selection_delete(void);
+- void selection_to_clip(void);
+- void clipboard_paste(void);
+
+ void recolor_selection(int color_no, guint color_rgba);
+ void rethicken_selection(int val);
+--- 22,27 ----
+diff -c 'xournal-0.4.5/src/xo-print.c' 'xournal/src/xo-print.c'
+Index: ./src/xo-print.c
+*** ./src/xo-print.c Tue Sep 29 10:36:54 2009
+--- ./src/xo-print.c Thu Jul 29 16:31:20 2010
+***************
+*** 772,777 ****
+--- 772,851 ----
+ return xref->last;
+ }
+
++ gboolean pdf_draw_image(PdfImage *image, struct XrefTable *xref, GString *pdfbuf)
++ {
++ char *buf, *p1, *p2;
++ int height, width, stride, x, y, chan;
++ GString *zpix;
++
++ if (gdk_pixbuf_get_bits_per_sample(image->pixbuf) != 8 ||
++ gdk_pixbuf_get_colorspace(image->pixbuf) != GDK_COLORSPACE_RGB) {
++ return FALSE;
++ }
++
++ width = gdk_pixbuf_get_width(image->pixbuf);
++ height = gdk_pixbuf_get_height(image->pixbuf);
++ stride = gdk_pixbuf_get_rowstride(image->pixbuf);
++ chan = gdk_pixbuf_get_n_channels(image->pixbuf);
++ if (!((chan==3 && !image->has_alpha) || (chan==4 && image->has_alpha))) {
++ return FALSE;
++ }
++
++ p2 = buf = (char *)g_malloc(3*width*height);
++ for (y=0; y<height; y++) {
++ p1 = (char *)gdk_pixbuf_get_pixels(image->pixbuf)+stride*y;
++ for (x=0; x<width; x++) {
++ *(p2++)=*(p1++); *(p2++)=*(p1++); *(p2++)=*(p1++);
++ if (chan==4) p1++;
++ }
++ }
++ zpix = do_deflate(buf, 3*width*height);
++ g_free(buf);
++
++ xref->data[image->n_obj] = pdfbuf->len;
++ g_string_append_printf(pdfbuf,
++ "%d 0 obj\n<< /Length %d /Filter /FlateDecode /Type /Xobject "
++ "/Subtype /Image /Width %d /Height %d /ColorSpace /DeviceRGB "
++ "/BitsPerComponent 8 ",
++ image->n_obj, zpix->len, width, height);
++ if (image->has_alpha) {
++ g_string_append_printf(pdfbuf,
++ "/SMask %d 0 R ",
++ image->n_obj_smask);
++ }
++ g_string_append_printf(pdfbuf, " >> stream\n");
++
++ g_string_append_len(pdfbuf, zpix->str, zpix->len);
++ g_string_free(zpix, TRUE);
++ g_string_append(pdfbuf, "endstream\nendobj\n");
++
++ if (image->has_alpha) {
++ p2 = buf = (char *)g_malloc(width*height);
++ for (y=0; y<height; y++) {
++ p1 = (char *)gdk_pixbuf_get_pixels(image->pixbuf)+stride*y;
++ for (x=0; x<width; x++) {
++ p1+=3; /* skip the RGB */
++ *(p2++)=*(p1++); /* just copy the alpha */
++ }
++ }
++ zpix = do_deflate(buf, width*height);
++ g_free(buf);
++
++ xref->data[image->n_obj_smask] = pdfbuf->len;
++ g_string_append_printf(pdfbuf,
++ "%d 0 obj\n<< /Length %d /Filter /FlateDecode /Type /Xobject "
++ "/Subtype /Image /Width %d /Height %d /ColorSpace /DeviceGray "
++ "/BitsPerComponent 8 >> stream\n",
++ image->n_obj_smask, zpix->len, width, height);
++
++ g_string_append_len(pdfbuf, zpix->str, zpix->len);
++ g_string_free(zpix, TRUE);
++ g_string_append(pdfbuf, "endstream\nendobj\n");
++ }
++
++ return TRUE;
++ }
++
+ // manipulate Pdf fonts
+
+ struct PdfFont *new_pdffont(struct XrefTable *xref, GList **fonts,
+***************
+*** 1006,1015 ****
+ g_string_append(pdfbuf, ">> endobj\n");
+ }
+
+ // draw a page's graphics
+
+ void pdf_draw_page(struct Page *pg, GString *str, gboolean *use_hiliter,
+! struct XrefTable *xref, GList **pdffonts)
+ {
+ GList *layerlist, *itemlist, *tmplist;
+ struct Layer *l;
+--- 1080,1110 ----
+ g_string_append(pdfbuf, ">> endobj\n");
+ }
+
++ // Pdf images
++
++ struct PdfImage *new_pdfimage(struct XrefTable *xref, GList **images, GdkPixbuf *pixbuf)
++ {
++ GList *list;
++ struct PdfImage *image;
++
++ image = g_malloc(sizeof(struct PdfImage));
++ *images = g_list_append(*images, image);
++ image->n_obj = xref->last+1;
++ make_xref(xref, xref->last+1, 0); // will give it a value later
++ image->has_alpha = gdk_pixbuf_get_has_alpha(pixbuf);
++ if (image->has_alpha) {
++ image->n_obj_smask = xref->last+1;
++ make_xref(xref, xref->last+1, 0); // will give it a value later
++ }
++ image->pixbuf = pixbuf;
++
++ return image;
++ }
++
+ // draw a page's graphics
+
+ void pdf_draw_page(struct Page *pg, GString *str, gboolean *use_hiliter,
+! struct XrefTable *xref, GList **pdffonts, GList **pdfimages)
+ {
+ GList *layerlist, *itemlist, *tmplist;
+ struct Layer *l;
+***************
+*** 1034,1039 ****
+--- 1129,1135 ----
+ int font_id;
+ FT_Face ftface;
+ struct PdfFont *cur_font;
++ struct PdfImage *cur_image;
+ gboolean in_string;
+
+ old_rgba = old_text_rgba = 0x12345678; // not any values we use, so we'll reset them
+***************
+*** 1161,1166 ****
+--- 1257,1272 ----
+ pango_layout_iter_free(iter);
+ g_object_unref(layout);
+ }
++ else if (item->type == ITEM_IMAGE) {
++ cur_image = new_pdfimage(xref, pdfimages, item->image);
++ g_string_append_printf(str, "\nq 1 0 0 1 %.2f %.2f cm %.2f 0 0 %.2f 0 %.2f cm /Im%d Do Q ",
++ item->bbox.left, // translation
++ item->bbox.top,
++ item->bbox.right - item->bbox.left, // scaling
++ item->bbox.top - item->bbox.bottom,
++ item->bbox.bottom - item->bbox.top,
++ cur_image->n_obj);
++ }
+ }
+ }
+ }
+***************
+*** 1187,1194 ****
+ gboolean use_hiliter;
+ struct PdfInfo pdfinfo;
+ struct PdfObj *obj;
+! GList *pdffonts, *list;
+ struct PdfFont *font;
+ char *tmpbuf;
+
+ f = fopen(filename, "w");
+--- 1293,1301 ----
+ gboolean use_hiliter;
+ struct PdfInfo pdfinfo;
+ struct PdfObj *obj;
+! GList *pdffonts, *pdfimages, *list;
+ struct PdfFont *font;
++ struct PdfImage *image;
+ char *tmpbuf;
+
+ f = fopen(filename, "w");
+***************
+*** 1198,1203 ****
+--- 1305,1311 ----
+ xref.data = NULL;
+ uses_pdf = FALSE;
+ pdffonts = NULL;
++ pdfimages = NULL;
+ for (pglist = journal.pages; pglist!=NULL; pglist = pglist->next) {
+ pg = (struct Page *)pglist->data;
+ if (pg->bg->type == BG_PDF) uses_pdf = TRUE;
+***************
+*** 1267,1273 ****
+ n_obj_bgpix = pdf_draw_bitmap_background(pg, pgstrm, &xref, pdfbuf);
+ // draw the page contents
+ use_hiliter = FALSE;
+! pdf_draw_page(pg, pgstrm, &use_hiliter, &xref, &pdffonts);
+ g_string_append_printf(pgstrm, "Q\n");
+
+ // deflate pgstrm and write it
+--- 1375,1381 ----
+ n_obj_bgpix = pdf_draw_bitmap_background(pg, pgstrm, &xref, pdfbuf);
+ // draw the page contents
+ use_hiliter = FALSE;
+! pdf_draw_page(pg, pgstrm, &use_hiliter, &xref, &pdffonts, &pdfimages);
+ g_string_append_printf(pgstrm, "Q\n");
+
+ // deflate pgstrm and write it
+***************
+*** 1323,1329 ****
+ }
+ add_dict_subentry(pdfbuf, &xref,
+ obj, "/ProcSet", PDFTYPE_ARRAY, NULL, mk_pdfname("/PDF"));
+! if (n_obj_bgpix>0)
+ add_dict_subentry(pdfbuf, &xref,
+ obj, "/ProcSet", PDFTYPE_ARRAY, NULL, mk_pdfname("/ImageC"));
+ if (use_hiliter)
+--- 1431,1437 ----
+ }
+ add_dict_subentry(pdfbuf, &xref,
+ obj, "/ProcSet", PDFTYPE_ARRAY, NULL, mk_pdfname("/PDF"));
+! if (n_obj_bgpix>0 || pdfimages!=NULL)
+ add_dict_subentry(pdfbuf, &xref,
+ obj, "/ProcSet", PDFTYPE_ARRAY, NULL, mk_pdfname("/ImageC"));
+ if (use_hiliter)
+***************
+*** 1343,1353 ****
+ g_free(tmpbuf);
+ }
+ }
+ show_pdfobj(obj, pdfbuf);
+ free_pdfobj(obj);
+ g_string_append(pdfbuf, " >> endobj\n");
+ }
+!
+ // after the pages, we insert fonts
+ for (list = pdffonts; list!=NULL; list = list->next) {
+ font = (struct PdfFont *)list->data;
+--- 1451,1468 ----
+ g_free(tmpbuf);
+ }
+ }
++ for (list=pdfimages; list!=NULL; list = list->next) {
++ image = (struct PdfImage *)list->data;
++ tmpbuf = g_strdup_printf("/Im%d", image->n_obj);
++ add_dict_subentry(pdfbuf, &xref,
++ obj, "/XObject", PDFTYPE_DICT, tmpbuf, mk_pdfref(image->n_obj));
++ g_free(tmpbuf);
++ }
+ show_pdfobj(obj, pdfbuf);
+ free_pdfobj(obj);
+ g_string_append(pdfbuf, " >> endobj\n");
+ }
+!
+ // after the pages, we insert fonts
+ for (list = pdffonts; list!=NULL; list = list->next) {
+ font = (struct PdfFont *)list->data;
+***************
+*** 1357,1362 ****
+--- 1472,1489 ----
+ g_free(font);
+ }
+ g_list_free(pdffonts);
++
++ // after the fonts, we insert images
++ if (pdfimages!=NULL) {
++ for (list = pdfimages; list!=NULL; list = list->next) {
++ image = (struct PdfImage *)list->data;
++ if (!pdf_draw_image(image, &xref, pdfbuf)) {
++ return FALSE;
++ }
++ g_free(image);
++ }
++ g_list_free(pdfimages);
++ }
+
+ // PDF trailer
+ startxref = pdfbuf->len;
+***************
+*** 1476,1481 ****
+--- 1603,1609 ----
+ void print_job_render_page(GtkPrintOperation *print, GtkPrintContext *context, gint pageno, gpointer user_data)
+ {
+ cairo_t *cr;
++ cairo_t *tempcr;
+ gdouble width, height, scale;
+ struct Page *pg;
+ guint old_rgba;
+***************
+*** 1487,1492 ****
+--- 1615,1621 ----
+ double *pt;
+ PangoFontDescription *font_desc;
+ PangoLayout *layout;
++ cairo_surface_t *surf;
+
+ pg = (struct Page *)g_list_nth_data(journal.pages, pageno);
+ cr = gtk_print_context_get_cairo_context(context);
+***************
+*** 1509,1515 ****
+ l = (struct Layer *)layerlist->data;
+ for (itemlist = l->items; itemlist!=NULL; itemlist = itemlist->next) {
+ item = (struct Item *)itemlist->data;
+! if (item->type == ITEM_STROKE || item->type == ITEM_TEXT) {
+ if (item->brush.color_rgba != old_rgba)
+ cairo_set_source_rgba(cr, RGBA_RGB(item->brush.color_rgba),
+ RGBA_ALPHA(item->brush.color_rgba));
+--- 1638,1644 ----
+ l = (struct Layer *)layerlist->data;
+ for (itemlist = l->items; itemlist!=NULL; itemlist = itemlist->next) {
+ item = (struct Item *)itemlist->data;
+! if (item->type == ITEM_STROKE || item->type == ITEM_TEXT || item->type==ITEM_IMAGE) {
+ if (item->brush.color_rgba != old_rgba)
+ cairo_set_source_rgba(cr, RGBA_RGB(item->brush.color_rgba),
+ RGBA_ALPHA(item->brush.color_rgba));
+***************
+*** 1548,1553 ****
+--- 1677,1694 ----
+ pango_cairo_show_layout(cr, layout);
+ g_object_unref(layout);
+ }
++ if (item->type == ITEM_IMAGE) {
++ double required_width = item->bbox.right - item->bbox.left;
++ double required_height = item->bbox.bottom - item->bbox.top;
++ double scalex = required_width / gdk_pixbuf_get_width(item->image);
++ double scaley = required_height / gdk_pixbuf_get_height(item->image);
++ cairo_scale(cr,scalex,scaley);
++ gdk_cairo_set_source_pixbuf(cr,item->image,item->bbox.left/scalex,item->bbox.top/scaley);
++ cairo_scale(cr,1/scalex,1/scaley);
++ cairo_paint (cr);
++ old_rgba = predef_colors_rgba[COLOR_BLACK]; //this is an ugly fix, I (victor) don't understand cairo enough
++ cairo_set_source_rgb(cr, 0, 0, 0);
++ }
+ }
+ }
+ }
+diff -c 'xournal-0.4.5/src/xo-print.h' 'xournal/src/xo-print.h'
+Index: ./src/xo-print.h
+*** ./src/xo-print.h Tue Sep 15 09:26:26 2009
+--- ./src/xo-print.h Fri May 28 20:43:50 2010
+***************
+*** 45,50 ****
+--- 45,57 ----
+ int flags;
+ } PdfFont;
+
++ typedef struct PdfImage {
++ int n_obj;
++ gboolean has_alpha;
++ int n_obj_smask; /* only if has_alpha */
++ GdkPixbuf *pixbuf;
++ } PdfImage;
++
+ #define PDFTYPE_CST 0 // intval: true=1, false=0, null=-1
+ #define PDFTYPE_INT 1 // intval
+ #define PDFTYPE_REAL 2 // realval
+diff -c 'xournal-0.4.5/src/xournal.h' 'xournal/src/xournal.h'
+Index: ./src/xournal.h
+*** ./src/xournal.h Sat Oct 3 12:42:28 2009
+--- ./src/xournal.h Thu Jul 29 17:02:19 2010
+***************
+*** 17,22 ****
+--- 17,24 ----
+ "tiny file dialog" syndrome, without hurting those with well-behaved
+ versions of GTK+. Comment out if you'd prefer not to include this fix. */
+
++ //#define IMAGE_DEBUG //this is for debugging of the "insert image" patch
++
+ // PREF FILES INFO
+
+ #define CONFIG_DIR ".xournal"
+***************
+*** 120,125 ****
+--- 122,128 ----
+ #define TOOL_SELECTRECT 5
+ #define TOOL_VERTSPACE 6
+ #define TOOL_HAND 7
++ #define TOOL_IMAGE 8
+ #define NUM_STROKE_TOOLS 3
+ #define NUM_TOOLS 8
+ #define NUM_BUTTONS 3
+***************
+*** 150,155 ****
+--- 153,163 ----
+ gchar *font_name;
+ gdouble font_size;
+ GtkWidget *widget; // the widget while text is being edited (ITEM_TEMP_TEXT)
++ // the following fields for ITEM_IMAGE:
++ GdkPixbuf* image; // original image for print and resizing quality
++ GdkPixbuf* image_scaled; // scaled pixbuf for display
++ gchar *image_png; // PNG of original image, for save and clipboard
++ gsize image_png_len;
+ } Item;
+
+ // item type values for Item.type, UndoItem.type, ui.cur_item_type ...
+***************
+*** 178,183 ****
+--- 186,192 ----
+ #define ITEM_TEXT_ATTRIB 21
+ #define ITEM_RESIZESEL 22
+ #define ITEM_RECOGNIZER 23
++ #define ITEM_IMAGE 24
+
+ typedef struct Layer {
+ GList *items; // the items on the layer, from bottom to top
+***************
+*** 251,256 ****
+--- 260,266 ----
+ gboolean hand_scrollto_pending;
+ char *filename;
+ gchar *default_path; // default path for new notes
++ gchar *default_image; // path for previous image
+ gboolean view_continuous, fullscreen, maximize_at_start;
+ gboolean in_update_page_stuff; // semaphore to avoid scrollbar retroaction
+ struct Selection *selection;
+***************
+*** 300,307 ****
+
+ typedef struct UndoItem {
+ int type;
+! struct Item *item; // for ITEM_STROKE, ITEM_TEXT, ITEM_TEXT_EDIT, ITEM_TEXT_ATTRIB
+! struct Layer *layer; // for ITEM_STROKE, ITEM_ERASURE, ITEM_PASTE, ITEM_NEW_LAYER, ITEM_DELETE_LAYER, ITEM_MOVESEL, ITEM_TEXT, ITEM_TEXT_EDIT, ITEM_RECOGNIZER
+ struct Layer *layer2; // for ITEM_DELETE_LAYER with val=-1, ITEM_MOVESEL
+ struct Page *page; // for ITEM_NEW_BG_ONE/RESIZE, ITEM_NEW_PAGE, ITEM_NEW_LAYER, ITEM_DELETE_LAYER, ITEM_DELETE_PAGE
+ GList *erasurelist; // for ITEM_ERASURE, ITEM_RECOGNIZER
+--- 310,317 ----
+
+ typedef struct UndoItem {
+ int type;
+! struct Item *item; // for ITEM_STROKE, ITEM_TEXT, ITEM_TEXT_EDIT, ITEM_TEXT_ATTRIB, ITEM_IMAGE
+! struct Layer *layer; // for ITEM_STROKE, ITEM_ERASURE, ITEM_PASTE, ITEM_NEW_LAYER, ITEM_DELETE_LAYER, ITEM_MOVESEL, ITEM_TEXT, ITEM_TEXT_EDIT, ITEM_RECOGNIZER, ITEM_IMAGE
+ struct Layer *layer2; // for ITEM_DELETE_LAYER with val=-1, ITEM_MOVESEL
+ struct Page *page; // for ITEM_NEW_BG_ONE/RESIZE, ITEM_NEW_PAGE, ITEM_NEW_LAYER, ITEM_DELETE_LAYER, ITEM_DELETE_PAGE
+ GList *erasurelist; // for ITEM_ERASURE, ITEM_RECOGNIZER
+#### End of Patch data ####
+
+#### ApplyPatch data follows ####
+# Data version : 1.0
+# Date generated : Thu Jul 29 20:05:54 2010
+# Generated by : makepatch 2.03
+# Recurse directories : Yes
+# Excluded files : (\A|/).*\~\Z
+# (\A|/).*\.a\Z
+# (\A|/).*\.bak\Z
+# (\A|/).*\.BAK\Z
+# (\A|/).*\.elc\Z
+# (\A|/).*\.exe\Z
+# (\A|/).*\.gz\Z
+# (\A|/).*\.ln\Z
+# (\A|/).*\.o\Z
+# (\A|/).*\.obj\Z
+# (\A|/).*\.olb\Z
+# (\A|/).*\.old\Z
+# (\A|/).*\.orig\Z
+# (\A|/).*\.rej\Z
+# (\A|/).*\.so\Z
+# (\A|/).*\.Z\Z
+# (\A|/)\.del\-.*\Z
+# (\A|/)\.make\.state\Z
+# (\A|/)\.nse_depinfo\Z
+# (\A|/)core\Z
+# (\A|/)tags\Z
+# (\A|/)TAGS\Z
+# c './README.image' 0 1271308604 0100644
+# p './src/Makefile.am' 560 1271308944 0100644
+# p './src/Makefile.in' 21256 1271309237 0100644
+# p './src/TODO' 12113 1273816779 0100644
+# p './src/main.c' 11751 1277612564 0100644
+# p './src/xo-callbacks.c' 115621 1277368329 0100644
+# p './src/xo-callbacks.h' 22740 1269211165 0100644
+# c './src/xo-clipboard.c' 0 1280390203 0100644
+# c './src/xo-clipboard.h' 0 1269482993 0100644
+# p './src/xo-file.c' 72283 1280379587 0100644
+# c './src/xo-image.c' 0 1280379292 0100644
+# c './src/xo-image.h' 0 1277368922 0100644
+# p './src/xo-interface.c' 154893 1269211165 0100644
+# p './src/xo-misc.c' 75933 1280376684 0100644
+# p './src/xo-misc.h' 4155 1277612281 0100644
+# p './src/xo-paint.c' 51578 1280376102 0100644
+# p './src/xo-paint.h' 1292 1271305513 0100644
+# p './src/xo-print.c' 51697 1280377880 0100644
+# p './src/xo-print.h' 1872 1275036230 0100644
+# p './src/xournal.h' 12910 1280379739 0100644
+#### End of ApplyPatch data ####
+
+#### End of Patch kit [created: Thu Jul 29 20:05:54 2010] ####
+#### Patch checksum: 3071 115300 31326 ####
+#### Checksum: 3109 116607 9177 ####
diff --git a/xournal.spec b/xournal.spec
index 5ac6b4e..635f9b8 100644
--- a/xournal.spec
+++ b/xournal.spec
@@ -1,6 +1,6 @@
Name: xournal
Version: 0.4.5
-Release: 18%{?dist}
+Release: 19%{?dist}
Summary: Notetaking, sketching, PDF annotation and general journal
Group: Applications/Editors
@@ -10,6 +10,8 @@ Source0: http://downloads.sourceforge.net/xournal/%{name}-%{version}.tar.gz
Patch0: xournal-configure.in.patch
Patch1: xournal-0.4.5-xoprint-len.patch
Patch2: xournal-poppler-api.patch
+Patch3: xournal-0.4.5-sjg-image-rev7.patch
+
BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n)
BuildRequires: gtk2-devel >= 2.10.0
@@ -41,6 +43,7 @@ resolution) and overall functionality.
%patch0 -p1
%patch1 -p1
%patch2 -p0
+%patch3 -p0
%build
NOCONFIGURE=1 ./autogen.sh
@@ -112,6 +115,9 @@ update-desktop-database %{_datadir}/applications > /dev/null 2>&1 || :
%changelog
+* Mon Jul 09 2012 Jaromir Capik <jcapik at redhat.com> - 0.4.5-19
+- #827922 - image insertion patch
+
* Wed May 16 2012 Marek Kasik <mkasik at redhat.com> - 0.4.5-18
- Rebuild (poppler-0.20.0)
More information about the scm-commits
mailing list