From 9b61d4357ee6ad84d17ea21189af1eb1e1a9786a Mon Sep 17 00:00:00 2001 From: Jaromir Capik Date: Jul 09 2012 17:22:47 +0000 Subject: #827922 - image insertion patch --- 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@./$(DEPDIR)/main.Po@am__quote@ + @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/xo-callbacks.Po@am__quote@ ++ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/xo-clipboard.Po@am__quote@ + @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/xo-file.Po@am__quote@ ++ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/xo-image.Po@am__quote@ + @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/xo-interface.Po@am__quote@ + @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/xo-misc.Po@am__quote@ + @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/xo-paint.Po@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 ++ #endif ++ ++ #include ++ #include ++ ++ #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; ipath->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\n", tmpstr); + g_free(tmpstr); + } ++ if (item->type == ITEM_IMAGE) { ++ gzprintf(f, "", item->bbox.left, item->bbox.top, item->bbox.right, item->bbox.bottom); ++ ++ if (!write_image(f, item)) { ++ success = FALSE; ++ } ++ gzprintf(f, "\n"); ++ } + } + gzprintf(f, "\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 ++ #endif ++ ++ #include ++ #include ++ #include ++ #include ++ ++ #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; ipath->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; ipath->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; ipath->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; ypixbuf)+stride*y; ++ for (x=0; xdata[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; ypixbuf)+stride*y; ++ for (x=0; xdata[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 - 0.4.5-19 +- #827922 - image insertion patch + * Wed May 16 2012 Marek Kasik - 0.4.5-18 - Rebuild (poppler-0.20.0)