# 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 <config.h>
+ #endif
+
+ #include <string.h>
+ #include <gtk/gtk.h>
+
+ #include "xournal.h"
+ #include "xo-callbacks.h"
+ #include "xo-interface.h"
+ #include "xo-support.h"
+ #include "xo-misc.h"
+ #include "xo-paint.h"
+ #include "xo-image.h"
+
+
+ void callback_clipboard_get(GtkClipboard *clipboard,
+ GtkSelectionData *selection_data,
+ guint info, gpointer user_data)
+ {
+ int length;
+
+ g_memmove(&length, user_data, sizeof(int));
+ gtk_selection_data_set(selection_data,
+ gdk_atom_intern("_XOURNAL", FALSE), 8, user_data, length);
+ }
+
+ void callback_clipboard_clear(GtkClipboard *clipboard, gpointer user_data)
+ {
+ g_free(user_data);
+ }
+
+ void callback_clipboard_targets_received(GtkClipboard *clipboard,
+ GdkAtom *atoms,
+ gint n_atoms,
+ gpointer data)
+ {
+ gint i;
+ printf("clipboard targets:\n");
+ for (i = 0; i < n_atoms; i++) {
+ printf("%s\n", gdk_atom_name(atoms[i]));
+ }
+ }
+
+ void selection_to_clip(void)
+ {
+ int bufsz, nitems, val;
+ char *buf, *p;
+ GList *list;
+ struct Item *item;
+ GtkTargetEntry target;
+
+ if (ui.selection == NULL) return;
+ bufsz = 2*sizeof(int) // bufsz, nitems
+ + sizeof(struct BBox); // bbox
+ nitems = 0;
+ for (list = ui.selection->items; list != NULL; list = list->next) {
+ item = (struct Item *)list->data;
+ nitems++;
+ if (item->type == ITEM_STROKE) {
+ bufsz+= sizeof(int) // type
+ + sizeof(struct Brush) // brush
+ + sizeof(int) // num_points
+ + 2*item->path->num_points*sizeof(double); // the points
+ if (item->brush.variable_width)
+ bufsz += (item->path->num_points-1)*sizeof(double); // the widths
+ }
+ else if (item->type == ITEM_TEXT) {
+ bufsz+= sizeof(int) // type
+ + sizeof(struct Brush) // brush
+ + 2*sizeof(double) // bbox upper-left
+ + sizeof(int) // text len
+ + strlen(item->text)+1 // text
+ + sizeof(int) // font_name len
+ + strlen(item->font_name)+1 // font_name
+ + sizeof(double); // font_size
+ }
+ else if (item->type == ITEM_IMAGE) {
+ if (item->image_png == NULL) {
+ if (!pixbuf_to_buffer(item->image, &item->image_png, &item->image_png_len, "png")) {
+ item->image_png_len = 0; // failed for some reason, so forget it
+ }
+ }
+ bufsz+= sizeof(int) // type
+ + sizeof(struct BBox)
+ + sizeof(gsize) // png_buflen
+ + item->image_png_len;
+ }
+ else bufsz+= sizeof(int); // type
+ }
+ p = buf = g_malloc(bufsz);
+ g_memmove(p, &bufsz, sizeof(int)); p+= sizeof(int);
+ g_memmove(p, &nitems, sizeof(int)); p+= sizeof(int);
+ g_memmove(p, &ui.selection->bbox, sizeof(struct BBox)); p+= sizeof(struct BBox);
+ for (list = ui.selection->items; list != NULL; list = list->next) {
+ item = (struct Item *)list->data;
+ g_memmove(p, &item->type, sizeof(int)); p+= sizeof(int);
+ if (item->type == ITEM_STROKE) {
+ g_memmove(p, &item->brush, sizeof(struct Brush)); p+= sizeof(struct Brush);
+ g_memmove(p, &item->path->num_points, sizeof(int)); p+= sizeof(int);
+ g_memmove(p, item->path->coords, 2*item->path->num_points*sizeof(double));
+ p+= 2*item->path->num_points*sizeof(double);
+ if (item->brush.variable_width) {
+ g_memmove(p, item->widths, (item->path->num_points-1)*sizeof(double));
+ p+= (item->path->num_points-1)*sizeof(double);
+ }
+ }
+ if (item->type == ITEM_TEXT) {
+ g_memmove(p, &item->brush, sizeof(struct Brush)); p+= sizeof(struct Brush);
+ g_memmove(p, &item->bbox.left, sizeof(double)); p+= sizeof(double);
+ g_memmove(p, &item->bbox.top, sizeof(double)); p+= sizeof(double);
+ val = strlen(item->text);
+ g_memmove(p, &val, sizeof(int)); p+= sizeof(int);
+ g_memmove(p, item->text, val+1); p+= val+1;
+ val = strlen(item->font_name);
+ g_memmove(p, &val, sizeof(int)); p+= sizeof(int);
+ g_memmove(p, item->font_name, val+1); p+= val+1;
+ g_memmove(p, &item->font_size, sizeof(double)); p+= sizeof(double);
+ }
+ if (item->type == ITEM_IMAGE) {
+ g_memmove(p, &item->bbox, sizeof(struct BBox)); p+= sizeof(struct BBox);
+ g_memmove(p, &item->image_png_len, sizeof(gsize)); p+= sizeof(gsize);
+ if (item->image_png_len > 0) {
+ g_memmove(p, item->image_png, item->image_png_len); p+= item->image_png_len;
+ }
+ }
+ }
+
+ target.target = "_XOURNAL";
+ target.flags = 0;
+ target.info = 0;
+
+ gtk_clipboard_set_with_data(gtk_clipboard_get(GDK_SELECTION_CLIPBOARD),
+ &target, 1,
+ callback_clipboard_get, callback_clipboard_clear, buf);
+ }
+
+ // local paste within the application
+ void clipboard_paste_from_xournal(GtkSelectionData *sel_data)
+ {
+ unsigned char *p;
+ int nitems, npts, i, len;
+ struct Item *item;
+ double hoffset, voffset, cx, cy;
+ double *pf;
+ int sx, sy, wx, wy;
+
+ reset_selection();
+
+ ui.selection = g_new(struct Selection, 1);
+ p = sel_data->data + sizeof(int);
+ g_memmove(&nitems, p, sizeof(int)); p+= sizeof(int);
+ ui.selection->type = ITEM_SELECTRECT;
+ ui.selection->layer = ui.cur_layer;
+ g_memmove(&ui.selection->bbox, p, sizeof(struct BBox)); p+= sizeof(struct BBox);
+ ui.selection->items = NULL;
+
+ // find by how much we translate the pasted selection
+ gnome_canvas_get_scroll_offsets(canvas, &sx, &sy);
+ gdk_window_get_geometry(GTK_WIDGET(canvas)->window, NULL, NULL, &wx, &wy, NULL);
+ gnome_canvas_window_to_world(canvas, sx + wx/2, sy + wy/2, &cx, &cy);
+ cx -= ui.cur_page->hoffset;
+ cy -= ui.cur_page->voffset;
+ if (cx + (ui.selection->bbox.right-ui.selection->bbox.left)/2 > ui.cur_page->width)
+ cx = ui.cur_page->width - (ui.selection->bbox.right-ui.selection->bbox.left)/2;
+ if (cx - (ui.selection->bbox.right-ui.selection->bbox.left)/2 < 0)
+ cx = (ui.selection->bbox.right-ui.selection->bbox.left)/2;
+ if (cy + (ui.selection->bbox.bottom-ui.selection->bbox.top)/2 > ui.cur_page->height)
+ cy = ui.cur_page->height - (ui.selection->bbox.bottom-ui.selection->bbox.top)/2;
+ if (cy - (ui.selection->bbox.bottom-ui.selection->bbox.top)/2 < 0)
+ cy = (ui.selection->bbox.bottom-ui.selection->bbox.top)/2;
+ hoffset = cx - (ui.selection->bbox.right+ui.selection->bbox.left)/2;
+ voffset = cy - (ui.selection->bbox.top+ui.selection->bbox.bottom)/2;
+ ui.selection->bbox.left += hoffset;
+ ui.selection->bbox.right += hoffset;
+ ui.selection->bbox.top += voffset;
+ ui.selection->bbox.bottom += voffset;
+
+ ui.selection->canvas_item = gnome_canvas_item_new(ui.cur_layer->group,
+ gnome_canvas_rect_get_type(), "width-pixels", 1,
+ "outline-color-rgba", 0x000000ff,
+ "fill-color-rgba", 0x80808040,
+ "x1", ui.selection->bbox.left, "x2", ui.selection->bbox.right,
+ "y1", ui.selection->bbox.top, "y2", ui.selection->bbox.bottom, NULL);
+ make_dashed(ui.selection->canvas_item);
+
+ while (nitems-- > 0) {
+ item = g_new(struct Item, 1);
+ ui.selection->items = g_list_append(ui.selection->items, item);
+ ui.cur_layer->items = g_list_append(ui.cur_layer->items, item);
+ ui.cur_layer->nitems++;
+ g_memmove(&item->type, p, sizeof(int)); p+= sizeof(int);
+ if (item->type == ITEM_STROKE) {
+ g_memmove(&item->brush, p, sizeof(struct Brush)); p+= sizeof(struct Brush);
+ g_memmove(&npts, p, sizeof(int)); p+= sizeof(int);
+ item->path = gnome_canvas_points_new(npts);
+ pf = (double *)p;
+ for (i=0; i<npts; i++) {
+ item->path->coords[2*i] = pf[2*i] + hoffset;
+ item->path->coords[2*i+1] = pf[2*i+1] + voffset;
+ }
+ p+= 2*item->path->num_points*sizeof(double);
+ if (item->brush.variable_width) {
+ item->widths = g_memdup(p, (item->path->num_points-1)*sizeof(double));
+ p+= (item->path->num_points-1)*sizeof(double);
+ }
+ else item->widths = NULL;
+ update_item_bbox(item);
+ make_canvas_item_one(ui.cur_layer->group, item);
+ }
+ if (item->type == ITEM_TEXT) {
+ g_memmove(&item->brush, p, sizeof(struct Brush)); p+= sizeof(struct Brush);
+ g_memmove(&item->bbox.left, p, sizeof(double)); p+= sizeof(double);
+ g_memmove(&item->bbox.top, p, sizeof(double)); p+= sizeof(double);
+ item->bbox.left += hoffset;
+ item->bbox.top += voffset;
+ g_memmove(&len, p, sizeof(int)); p+= sizeof(int);
+ item->text = g_malloc(len+1);
+ g_memmove(item->text, p, len+1); p+= len+1;
+ g_memmove(&len, p, sizeof(int)); p+= sizeof(int);
+ item->font_name = g_malloc(len+1);
+ g_memmove(item->font_name, p, len+1); p+= len+1;
+ g_memmove(&item->font_size, p, sizeof(double)); p+= sizeof(double);
+ make_canvas_item_one(ui.cur_layer->group, item);
+ }
+ if (item->type == ITEM_IMAGE) {
+ item->canvas_item = NULL;
+ item->image_scaled = NULL;
+ item->image_png = NULL;
+ item->image_png_len = 0;
+ g_memmove(&item->bbox, p, sizeof(struct BBox)); p+= sizeof(struct BBox);
+ item->bbox.left += hoffset;
+ item->bbox.right += hoffset;
+ item->bbox.top += voffset;
+ item->bbox.bottom += voffset;
+ g_memmove(&item->image_png_len, p, sizeof(gsize)); p+= sizeof(gsize);
+ if (item->image_png_len > 0) {
+ item->image_png = g_memdup(p, item->image_png_len);
+ item->image = pixbuf_from_buffer(item->image_png, item->image_png_len);
+ p+= item->image_png_len;
+ } else {
+ item->image = NULL;
+ }
+ make_canvas_item_one(ui.cur_layer->group, item);
+ }
+ }
+
+ prepare_new_undo();
+ undo->type = ITEM_PASTE;
+ undo->layer = ui.cur_layer;
+ undo->itemlist = g_list_copy(ui.selection->items);
+
+ gtk_selection_data_free(sel_data);
+ update_copy_paste_enabled();
+ update_color_menu();
+ update_thickness_buttons();
+ update_color_buttons();
+ update_font_button();
+ update_cursor(); // FIXME: can't know if pointer is within selection!
+ }
+
+ // paste an external image
+ void clipboard_paste_image(GdkPixbuf *pixbuf)
+ {
+ double pt[2];
+
+ reset_selection();
+
+ get_current_pointer_coords(pt);
+ set_current_page(pt);
+
+ create_image_from_pixbuf(pixbuf, NULL, pt);
+ }
+
+ // work out what format the clipboard data is in, and paste accordingly
+ void clipboard_paste(void)
+ {
+ GtkSelectionData *sel_data;
+ GdkPixbuf *pixbuf;
+ GtkClipboard *clipboard;
+ unsigned char *p;
+ int nitems, npts, i, len;
+ struct Item *item;
+ double hoffset, voffset, cx, cy;
+ double *pf;
+ int sx, sy, wx, wy;
+
+ if (ui.cur_layer == NULL) return;
+
+ ui.cur_item_type = ITEM_PASTE;
+ clipboard = gtk_clipboard_get(GDK_SELECTION_CLIPBOARD);
+ sel_data = gtk_clipboard_wait_for_contents(
+ clipboard,
+ gdk_atom_intern("_XOURNAL", FALSE));
+ ui.cur_item_type = ITEM_NONE;
+ if (sel_data != NULL) {
+ clipboard_paste_from_xournal(sel_data);
+ } else {
+ pixbuf = gtk_clipboard_wait_for_image(clipboard);
+ if (pixbuf != NULL) {
+ clipboard_paste_image(pixbuf);
+ }
+ }
+ }
diff -c /dev/null 'xournal/src/xo-clipboard.h'
Index: ./src/xo-clipboard.h
*** ./src/xo-clipboard.h Thu Jan 1 12:00:00 1970
--- ./src/xo-clipboard.h Thu Mar 25 15:09:53 2010
***************
*** 0 ****
--- 1,2 ----
+ void selection_to_clip(void);
+ void clipboard_paste(void);
diff -c 'xournal-0.4.5/src/xo-file.c' 'xournal/src/xo-file.c'
Index: ./src/xo-file.c
*** ./src/xo-file.c Tue Sep 29 12:36:05 2009
--- ./src/xo-file.c Thu Jul 29 16:59:47 2010
***************
*** 25,30 ****
--- 25,31 ----
#include "xo-misc.h"
#include "xo-file.h"
#include "xo-paint.h"
+ #include "xo-image.h"
const char *tool_names[NUM_TOOLS] = {"pen", "eraser", "highlighter", "text", "", "selectrect", "vertspace", "hand"};
const char *color_names[COLOR_MAX] = {"black", "blue", "red", "green",
***************
*** 68,73 ****
--- 69,122 ----
}
}
+
+ // Write image to file: returns true on success, false on error.
+ // The image is written as a base64 encoded PNG.
+ gboolean write_image(gzFile f, Item *item)
+ {
+ gchar *base64_str;
+ GError **error;
+
+ error = NULL;
+
+ if (item->image_png == NULL) {
+ if (!pixbuf_to_buffer(item->image, &item->image_png, &item->image_png_len, "png")) {
+ item->image_png_len = 0; // failed for some reason, so forget it
+ return FALSE;
+ }
+ }
+
+ base64_str = g_base64_encode(item->image_png, item->image_png_len);
+
+ gzputs(f, base64_str);
+
+ g_free(base64_str);
+
+ return TRUE;
+ }
+
+ // create pixbuf from base64 encoded PNG, or return NULL on failure
+ GdkPixbuf *read_pixbuf(const gchar *base64_str, gsize base64_strlen)
+ {
+ gchar *base64_str2;
+ gchar *png_buf;
+ gsize png_buflen;
+ GdkPixbuf *pixbuf;
+
+ // We have to copy the string in order to null terminate it, sigh.
+ base64_str2 = g_memdup(base64_str, base64_strlen + 1);
+ base64_str2[ base64_strlen ] = '\0';
+
+ png_buf = g_base64_decode(base64_str2, &png_buflen);
+
+ pixbuf = pixbuf_from_buffer(png_buf, png_buflen);
+
+ g_free(png_buf);
+ g_free(base64_str2);
+
+ return pixbuf;
+ }
+
// saves the journal to a file: returns true on success, false on error
gboolean save_journal(const char *filename)
***************
*** 199,204 ****
--- 248,261 ----
gzprintf(f, "\">%s</text>\n", tmpstr);
g_free(tmpstr);
}
+ if (item->type == ITEM_IMAGE) {
+ gzprintf(f, "<image left=\"%.2f\" top=\"%.2f\" right=\"%.2f\" bottom=\"%.2f\">", item->bbox.left, item->bbox.top, item->bbox.right, item->bbox.bottom);
+
+ if (!write_image(f, item)) {
+ success = FALSE;
+ }
+ gzprintf(f, "</image>\n");
+ }
}
gzprintf(f, "</layer>\n");
}
***************
*** 575,580 ****
--- 632,688 ----
}
if (has_attr!=31) *error = xoj_invalid();
}
+ else if (!strcmp(element_name, "image")) { // start of a image item
+ if (tmpLayer == NULL || tmpItem != NULL) {
+ *error = xoj_invalid();
+ return;
+ }
+ tmpItem = (struct Item *)g_malloc0(sizeof(struct Item));
+ tmpItem->type = ITEM_IMAGE;
+ tmpItem->canvas_item = NULL;
+ tmpItem->image=NULL;
+ tmpItem->image_scaled=NULL;
+ tmpItem->image_png = NULL;
+ tmpItem->image_png_len = 0;
+ tmpLayer->items = g_list_append(tmpLayer->items, tmpItem);
+ tmpLayer->nitems++;
+ // scan for x, y
+ has_attr = 0;
+ while (*attribute_names!=NULL) {
+ if (!strcmp(*attribute_names, "left")) {
+ if (has_attr & 1) *error = xoj_invalid();
+ cleanup_numeric((gchar *)*attribute_values);
+ tmpItem->bbox.left = g_ascii_strtod(*attribute_values, &ptr);
+ if (ptr == *attribute_values) *error = xoj_invalid();
+ has_attr |= 1;
+ }
+ else if (!strcmp(*attribute_names, "top")) {
+ if (has_attr & 2) *error = xoj_invalid();
+ cleanup_numeric((gchar *)*attribute_values);
+ tmpItem->bbox.top = g_ascii_strtod(*attribute_values, &ptr);
+ if (ptr == *attribute_values) *error = xoj_invalid();
+ has_attr |= 2;
+ }
+ else if (!strcmp(*attribute_names, "right")) {
+ if (has_attr & 4) *error = xoj_invalid();
+ cleanup_numeric((gchar *)*attribute_values);
+ tmpItem->bbox.right = g_ascii_strtod(*attribute_values, &ptr);
+ if (ptr == *attribute_values) *error = xoj_invalid();
+ has_attr |= 4;
+ }
+ else if (!strcmp(*attribute_names, "bottom")) {
+ if (has_attr & 8) *error = xoj_invalid();
+ cleanup_numeric((gchar *)*attribute_values);
+ tmpItem->bbox.bottom = g_ascii_strtod(*attribute_values, &ptr);
+ if (ptr == *attribute_values) *error = xoj_invalid();
+ has_attr |= 8;
+ }
+ else *error = xoj_invalid();
+ attribute_names++;
+ attribute_values++;
+ }
+ if (has_attr!=15) *error = xoj_invalid();
+ }
}
void xoj_parser_end_element(GMarkupParseContext *context,
***************
*** 610,615 ****
--- 718,730 ----
}
tmpItem = NULL;
}
+ if (!strcmp(element_name, "image")) {
+ if (tmpItem == NULL) {
+ *error = xoj_invalid();
+ return;
+ }
+ tmpItem = NULL;
+ }
}
void xoj_parser_text(GMarkupParseContext *context,
***************
*** 647,652 ****
--- 762,770 ----
g_memmove(tmpItem->text, text, text_len);
tmpItem->text[text_len]=0;
}
+ if (!strcmp(element_name, "image")) {
+ tmpItem->image = read_pixbuf(text, text_len);
+ }
}
gboolean user_wants_second_chance(char **filename)
***************
*** 716,722 ****
g_free(tmpfn);
f = gzopen(filename, "r");
! if (f==NULL) return FALSE;
if (filename[0]=='/') {
if (ui.default_path != NULL) g_free(ui.default_path);
ui.default_path = g_path_get_dirname(filename);
--- 834,845 ----
g_free(tmpfn);
f = gzopen(filename, "r");
! if (f==NULL) {
! #ifdef IMAGE_DEBUG
! printf("gzopen failed\n");
! #endif
! return FALSE;
! }
if (filename[0]=='/') {
if (ui.default_path != NULL) g_free(ui.default_path);
ui.default_path = g_path_get_dirname(filename);
***************
*** 737,752 ****
while (valid && !gzeof(f)) {
len = gzread(f, buffer, 1000);
! if (len<0) valid = FALSE;
if (maybe_pdf && len>=4 && !strncmp(buffer, "%PDF", 4))
{ valid = FALSE; break; } // most likely pdf
else maybe_pdf = FALSE;
if (len<=0) break;
valid = g_markup_parse_context_parse(context, buffer, len, &error);
}
gzclose(f);
! if (valid) valid = g_markup_parse_context_end_parse(context, &error);
! if (tmpJournal.npages == 0) valid = FALSE;
g_markup_parse_context_free(context);
if (!valid) {
--- 860,893 ----
while (valid && !gzeof(f)) {
len = gzread(f, buffer, 1000);
! if (len<0){
! valid = FALSE;
! }
if (maybe_pdf && len>=4 && !strncmp(buffer, "%PDF", 4))
{ valid = FALSE; break; } // most likely pdf
else maybe_pdf = FALSE;
if (len<=0) break;
valid = g_markup_parse_context_parse(context, buffer, len, &error);
+
+ #ifdef IMAGE_DEBUG
+ if(!valid) printf("parsing failed\n");
+ #endif
}
gzclose(f);
!
! if (valid) {
! valid = g_markup_parse_context_end_parse(context, &error);
!
! #ifdef IMAGE_DEBUG
! if(!valid) printf("end parsing failed\n");
! #endif
! }
! if (tmpJournal.npages == 0){
! #ifdef IMAGE_DEBUG
! printf("found no pages\n");
! #endif
! valid = FALSE;
! }
g_markup_parse_context_free(context);
if (!valid) {
***************
*** 823,828 ****
--- 964,970 ----
update_page_stuff();
rescale_bg_pixmaps(); // this requests the PDF pages if need be
gtk_adjustment_set_value(gtk_layout_get_vadjustment(GTK_LAYOUT(canvas)), 0);
+
return TRUE;
}
***************
*** 1338,1343 ****
--- 1480,1486 ----
ui.print_ruling = TRUE;
ui.default_unit = UNIT_CM;
ui.default_path = NULL;
+ ui.default_image = NULL;
ui.default_font_name = g_strdup(DEFAULT_FONT);
ui.default_font_size = DEFAULT_FONT_SIZE;
ui.pressure_sensitivity = FALSE;
diff -c /dev/null 'xournal/src/xo-image.c'
Index: ./src/xo-image.c
*** ./src/xo-image.c Thu Jan 1 12:00:00 1970
--- ./src/xo-image.c Thu Jul 29 16:54:52 2010
***************
*** 0 ****
--- 1,238 ----
+ #ifdef HAVE_CONFIG_H
+ # include <config.h>
+ #endif
+
+ #include <math.h>
+ #include <string.h>
+ #include <gtk/gtk.h>
+ #include <gio/gio.h>
+
+ #include "xournal.h"
+ #include "xo-support.h"
+ #include "xo-image.h"
+
+
+ // Write pixmap to buffer: returns true on success, false on error.
+ gboolean pixbuf_to_buffer(GdkPixbuf *pixbuf, gchar **buf, gsize *buflen, const char *type)
+ {
+ GError *error;
+
+ error = NULL;
+
+ if (!gdk_pixbuf_save_to_buffer(pixbuf,
+ buf,
+ buflen,
+ type,
+ &error,
+ NULL)) {
+ return FALSE;
+ }
+
+ return TRUE;
+ }
+
+ // create pixbuf from buffer, or return NULL on failure
+ GdkPixbuf *pixbuf_from_buffer(const gchar *buf, gsize buflen)
+ {
+ GInputStream *istream;
+ GdkPixbuf *pixbuf;
+ GError *error;
+
+ error = NULL;
+
+ istream = g_memory_input_stream_new_from_data (buf, buflen, NULL);
+
+ pixbuf = gdk_pixbuf_new_from_stream(istream, NULL, &error);
+
+ g_input_stream_close(istream, NULL, &error);
+
+ return pixbuf;
+ }
+
+ void create_image_from_pixbuf(GdkPixbuf *pixbuf, struct Item *item, double *pt)
+ {
+ GtkTextBuffer *buffer;
+ GnomeCanvasItem *canvas_item;
+ GdkColor color;
+ GtkWidget *dialog;
+ GtkFileFilter *filt_all;
+ GtkFileFilter *filt_gdkimage;
+ double scale;
+
+ if (item==NULL) {
+ item = g_new(struct Item, 1);
+ item->type = ITEM_IMAGE;
+ item->canvas_item = NULL;
+ item->bbox.left = pt[0];
+ item->bbox.top = pt[1];
+ item->image = pixbuf;
+ item->image_scaled = NULL;
+ item->image_png = NULL;
+ item->image_png_len = 0;
+
+ // Scale at native size, unless that won't fit,
+ // in which case we shrink it down.
+ scale = 1 / ui.zoom;
+ if( (scale * gdk_pixbuf_get_width(item->image)) > ui.cur_page->width - item->bbox.left ) {
+ //set scale so that it does not extend too far to the right
+ scale = (ui.cur_page->width - item->bbox.left) / gdk_pixbuf_get_width(item->image);
+ }
+ if( (scale * gdk_pixbuf_get_height(item->image)) > ui.cur_page->height - item->bbox.top ) {
+ //set scale so that it does not extend too far to the bottom
+ scale = (ui.cur_page->height - item->bbox.top) / gdk_pixbuf_get_height(item->image);
+ }
+
+ item->bbox.right = item->bbox.left + scale * gdk_pixbuf_get_width(item->image);
+ item->bbox.bottom = item->bbox.top + scale * gdk_pixbuf_get_height(item->image);
+ g_memmove(&(item->brush), ui.cur_brush, sizeof(struct Brush));
+ ui.cur_layer->items = g_list_append(ui.cur_layer->items, item);
+ ui.cur_layer->nitems++;
+ }
+
+ item->type = ITEM_IMAGE;
+ ui.cur_item = item;
+
+ if (item->canvas_item!=NULL) {
+ lower_canvas_item_to(ui.cur_layer->group, canvas_item, item->canvas_item);
+ gtk_object_destroy(GTK_OBJECT(item->canvas_item));
+ }
+
+ make_canvas_item_one(ui.cur_layer->group, item);
+
+ // select image
+ reset_selection();
+ ui.selection = g_new0(struct Selection, 1);
+ ui.selection->type = ITEM_SELECTRECT;
+ ui.selection->layer = ui.cur_layer;
+ ui.selection->bbox = item->bbox;
+ ui.selection->items = g_list_append(ui.selection->items, item);
+ ui.selection->canvas_item = gnome_canvas_item_new(ui.cur_layer->group,
+ gnome_canvas_rect_get_type(), "width-pixels", 1,
+ "outline-color-rgba", 0x000000ff,
+ "fill-color-rgba", 0x80808040,
+ "x1", ui.selection->bbox.left, "x2", ui.selection->bbox.right,
+ "y1", ui.selection->bbox.top, "y2", ui.selection->bbox.bottom, NULL);
+ make_dashed(ui.selection->canvas_item);
+
+ // add undo information
+ prepare_new_undo();
+ undo->type = ITEM_IMAGE;
+ undo->item = ui.cur_item;
+ undo->layer = ui.cur_layer;
+
+ ui.cur_item = NULL;
+ ui.cur_item_type = ITEM_NONE;
+ }
+
+ void insert_image(GdkEvent *event, struct Item *item)
+ {
+ GtkTextBuffer *buffer;
+ GnomeCanvasItem *canvas_item;
+ GdkColor color;
+ GtkWidget *dialog;
+ GtkFileFilter *filt_all;
+ GtkFileFilter *filt_gdkimage;
+ char *filename;
+ GdkPixbuf *pixbuf;
+ double scale=1;
+ double pt[2];
+
+ dialog = gtk_file_chooser_dialog_new(_("Insert Image"), GTK_WINDOW (winMain),
+ GTK_FILE_CHOOSER_ACTION_OPEN, GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
+ GTK_STOCK_OPEN, GTK_RESPONSE_OK, NULL);
+ #ifdef FILE_DIALOG_SIZE_BUGFIX
+ gtk_window_set_default_size(GTK_WINDOW(dialog), 500, 400);
+ #endif
+
+ filt_all = gtk_file_filter_new();
+ gtk_file_filter_set_name(filt_all, _("All files"));
+ gtk_file_filter_add_pattern(filt_all, "*");
+ filt_gdkimage = gtk_file_filter_new();
+ gtk_file_filter_set_name(filt_gdkimage, _("supported image files"));
+ gtk_file_filter_add_pixbuf_formats(filt_gdkimage);
+ gtk_file_chooser_add_filter(GTK_FILE_CHOOSER (dialog), filt_gdkimage);
+ gtk_file_chooser_add_filter(GTK_FILE_CHOOSER (dialog), filt_all);
+
+ if (ui.default_image != NULL) gtk_file_chooser_set_filename(GTK_FILE_CHOOSER (dialog), ui.default_image);
+
+ if (gtk_dialog_run(GTK_DIALOG(dialog)) != GTK_RESPONSE_OK) {
+ gtk_widget_destroy(dialog);
+ return;
+ }
+ filename = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER (dialog));
+ gtk_widget_destroy(dialog);
+
+ if (filename == NULL) {
+ /* nothing selected */
+ return;
+ }
+
+ if (ui.default_image != NULL) g_free(ui.default_image);
+ ui.default_image = g_strdup(filename);
+
+ pixbuf=gdk_pixbuf_new_from_file(filename, NULL);
+ if(pixbuf==NULL){
+ /* open failed */
+ dialog = gtk_message_dialog_new(GTK_WINDOW (winMain), GTK_DIALOG_DESTROY_WITH_PARENT,
+ GTK_MESSAGE_ERROR, GTK_BUTTONS_OK, _("Error opening image '%s'"), filename);
+ gtk_dialog_run(GTK_DIALOG(dialog));
+ gtk_widget_destroy(dialog);
+ g_free(filename);
+ ui.cur_item = NULL;
+ ui.cur_item_type = ITEM_NONE;
+ return;
+ }
+
+ ui.cur_item_type = ITEM_IMAGE;
+
+ get_pointer_coords(event, pt);
+ set_current_page(pt);
+
+ create_image_from_pixbuf(pixbuf, item, pt);
+ }
+
+ void update_scaled_image(struct Item *item)
+ {
+ gboolean use_native = is_native_image_usable( item );
+ if ( is_native_image_usable( item ) != (item->image_scaled == NULL) ) {
+ // we are currently using a scaled image, and should switch to native,
+ // or vice versa
+
+ adjust_or_make_canvas_item_image(ui.cur_layer->group, item);
+ }
+ }
+
+ void rescale_images(void)
+ {
+ GList *pagelist, *layerlist, *itemlist;
+ struct Item *item;
+
+ for (pagelist = journal.pages; pagelist!=NULL; pagelist = pagelist->next)
+ for (layerlist = ((struct Page *)pagelist->data)->layers; layerlist!=NULL; layerlist = layerlist->next)
+ for (itemlist = ((struct Layer *)layerlist->data)->items; itemlist!=NULL; itemlist = itemlist->next) {
+ item = (struct Item *)itemlist->data;
+ if ( item->type == ITEM_IMAGE ) {
+ update_scaled_image( item );
+ }
+ }
+ }
+
+ gboolean is_native_image_usable(struct Item *item)
+ {
+ double native_width;
+ double native_height;
+ double required_width;
+ double required_height;
+ gboolean usable;
+
+ // use the original image at native resolution if it's close enough to what we need
+ native_width = gdk_pixbuf_get_width(item->image) / ui.zoom;
+ native_height = gdk_pixbuf_get_height(item->image) / ui.zoom;
+ required_width = item->bbox.right - item->bbox.left;
+ required_height = item->bbox.bottom - item->bbox.top;
+
+ usable = ( fabs( native_width - required_width ) < 1 &&
+ fabs( native_height - required_height ) < 1 );
+
+ return usable;
+ }
diff -c /dev/null 'xournal/src/xo-image.h'
Index: ./src/xo-image.h
*** ./src/xo-image.h Thu Jan 1 12:00:00 1970
--- ./src/xo-image.h Thu Jun 24 20:42:02 2010
***************
*** 0 ****
--- 1,7 ----
+ extern gboolean pixbuf_to_buffer(GdkPixbuf *pixbuf, gchar **buf, gsize *buflen, const char *type);
+ extern GdkPixbuf *pixbuf_from_buffer(const gchar *buf, gsize buflen);
+
+ void create_image_from_pixbuf(GdkPixbuf *pixbuf, struct Item *item, double *pt);
+ void insert_image(GdkEvent *event, struct Item *item);
+ void rescale_images(void);
+ gboolean is_native_image_usable(struct Item *item);
diff -c 'xournal-0.4.5/src/xo-interface.c' 'xournal/src/xo-interface.c'
Index: ./src/xo-interface.c
*** ./src/xo-interface.c Fri Oct 2 19:03:32 2009
--- ./src/xo-interface.c Mon Mar 22 11:39:25 2010
***************
*** 36,42 ****
GtkWidget *menuFile_menu;
GtkWidget *fileNew;
GtkWidget *fileNewBackground;
- GtkWidget *image623;
GtkWidget *fileOpen;
GtkWidget *fileSave;
GtkWidget *fileSaveAs;
--- 36,41 ----
***************
*** 53,59 ****
GtkWidget *mru7;
GtkWidget *separator22;
GtkWidget *filePrintOptions;
- GtkWidget *image624;
GtkWidget *filePrint;
GtkWidget *filePrintPDF;
GtkWidget *separator2;
--- 52,57 ----
***************
*** 81,102 ****
GtkWidget *viewZoomOut;
GtkWidget *viewNormalSize;
GtkWidget *viewPageWidth;
- GtkWidget *image625;
GtkWidget *viewSetZoom;
GtkWidget *separator5;
GtkWidget *viewFirstPage;
- GtkWidget *image626;
GtkWidget *viewPreviousPage;
- GtkWidget *image627;
GtkWidget *viewNextPage;
- GtkWidget *image628;
GtkWidget *viewLastPage;
- GtkWidget *image629;
GtkWidget *separator6;
GtkWidget *viewShowLayer;
- GtkWidget *image630;
GtkWidget *viewHideLayer;
- GtkWidget *image631;
GtkWidget *menuJournal;
GtkWidget *menuJournal_menu;
GtkWidget *journalNewPageBefore;
--- 79,93 ----
***************
*** 131,137 ****
GtkWidget *journalApplyAllPages;
GtkWidget *separator23;
GtkWidget *journalLoadBackground;
- GtkWidget *image632;
GtkWidget *journalScreenshot;
GtkWidget *separator19;
GtkWidget *journalDefaultBackground;
--- 122,127 ----
***************
*** 153,159 ****
GtkWidget *toolsHand;
GtkWidget *separator16;
GtkWidget *toolsColor;
- GtkWidget *image633;
GtkWidget *toolsColor_menu;
GSList *colorBlack_group = NULL;
GtkWidget *colorBlack;
--- 143,148 ----
***************
*** 196,202 ****
GtkWidget *highlighterMedium;
GtkWidget *highlighterThick;
GtkWidget *toolsTextFont;
- GtkWidget *image634;
GtkWidget *separator10;
GtkWidget *toolsDefaultPen;
GtkWidget *toolsDefaultEraser;
--- 185,190 ----
***************
*** 289,294 ****
--- 277,283 ----
GtkWidget *buttonEraser;
GtkWidget *buttonHighlighter;
GtkWidget *buttonText;
+ GtkWidget *buttonImage;
GtkWidget *buttonReco;
GtkWidget *buttonRuler;
GtkWidget *toolitem15;
***************
*** 368,381 ****
gtk_widget_show (fileNew);
gtk_container_add (GTK_CONTAINER (menuFile_menu), fileNew);
! fileNewBackground = gtk_image_menu_item_new_with_mnemonic (_("Annotate PD_F"));
gtk_widget_show (fileNewBackground);
gtk_container_add (GTK_CONTAINER (menuFile_menu), fileNewBackground);
- image623 = gtk_image_new_from_stock ("gtk-open", GTK_ICON_SIZE_MENU);
- gtk_widget_show (image623);
- gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (fileNewBackground), image623);
-
fileOpen = gtk_image_menu_item_new_from_stock ("gtk-open", accel_group);
gtk_widget_show (fileOpen);
gtk_container_add (GTK_CONTAINER (menuFile_menu), fileOpen);
--- 357,366 ----
gtk_widget_show (fileNew);
gtk_container_add (GTK_CONTAINER (menuFile_menu), fileNew);
! fileNewBackground = gtk_image_menu_item_new_with_mnemonic ("Annotate PD_F");
gtk_widget_show (fileNewBackground);
gtk_container_add (GTK_CONTAINER (menuFile_menu), fileNewBackground);
fileOpen = gtk_image_menu_item_new_from_stock ("gtk-open", accel_group);
gtk_widget_show (fileOpen);
gtk_container_add (GTK_CONTAINER (menuFile_menu), fileOpen);
***************
*** 437,450 ****
gtk_container_add (GTK_CONTAINER (menuFile_menu), separator22);
gtk_widget_set_sensitive (separator22, FALSE);
! filePrintOptions = gtk_image_menu_item_new_with_mnemonic (_("Print Options"));
gtk_widget_show (filePrintOptions);
gtk_container_add (GTK_CONTAINER (menuFile_menu), filePrintOptions);
- image624 = gtk_image_new_from_stock ("gtk-preferences", GTK_ICON_SIZE_MENU);
- gtk_widget_show (image624);
- gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (filePrintOptions), image624);
-
filePrint = gtk_image_menu_item_new_from_stock ("gtk-print", accel_group);
gtk_widget_show (filePrint);
gtk_container_add (GTK_CONTAINER (menuFile_menu), filePrint);
--- 422,431 ----
gtk_container_add (GTK_CONTAINER (menuFile_menu), separator22);
gtk_widget_set_sensitive (separator22, FALSE);
! filePrintOptions = gtk_image_menu_item_new_with_mnemonic ("Print Options");
gtk_widget_show (filePrintOptions);
gtk_container_add (GTK_CONTAINER (menuFile_menu), filePrintOptions);
filePrint = gtk_image_menu_item_new_from_stock ("gtk-print", accel_group);
gtk_widget_show (filePrint);
gtk_container_add (GTK_CONTAINER (menuFile_menu), filePrint);
***************
*** 577,593 ****
GDK_0, (GdkModifierType) GDK_CONTROL_MASK,
GTK_ACCEL_VISIBLE);
! viewPageWidth = gtk_image_menu_item_new_with_mnemonic (_("Page _Width"));
gtk_widget_show (viewPageWidth);
gtk_container_add (GTK_CONTAINER (menuViewZoom_menu), viewPageWidth);
gtk_widget_add_accelerator (viewPageWidth, "activate", accel_group,
GDK_equal, (GdkModifierType) GDK_CONTROL_MASK,
GTK_ACCEL_VISIBLE);
- image625 = gtk_image_new_from_stock ("gtk-zoom-fit", GTK_ICON_SIZE_MENU);
- gtk_widget_show (image625);
- gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (viewPageWidth), image625);
-
viewSetZoom = gtk_menu_item_new_with_mnemonic (_("_Set Zoom"));
gtk_widget_show (viewSetZoom);
gtk_container_add (GTK_CONTAINER (menuViewZoom_menu), viewSetZoom);
--- 558,570 ----
GDK_0, (GdkModifierType) GDK_CONTROL_MASK,
GTK_ACCEL_VISIBLE);
! viewPageWidth = gtk_image_menu_item_new_with_mnemonic ("Page _Width");
gtk_widget_show (viewPageWidth);
gtk_container_add (GTK_CONTAINER (menuViewZoom_menu), viewPageWidth);
gtk_widget_add_accelerator (viewPageWidth, "activate", accel_group,
GDK_equal, (GdkModifierType) GDK_CONTROL_MASK,
GTK_ACCEL_VISIBLE);
viewSetZoom = gtk_menu_item_new_with_mnemonic (_("_Set Zoom"));
gtk_widget_show (viewSetZoom);
gtk_container_add (GTK_CONTAINER (menuViewZoom_menu), viewSetZoom);
***************
*** 597,667 ****
gtk_container_add (GTK_CONTAINER (menuView_menu), separator5);
gtk_widget_set_sensitive (separator5, FALSE);
! viewFirstPage = gtk_image_menu_item_new_with_mnemonic (_("_First Page"));
gtk_widget_show (viewFirstPage);
gtk_container_add (GTK_CONTAINER (menuView_menu), viewFirstPage);
gtk_widget_add_accelerator (viewFirstPage, "activate", accel_group,
GDK_Home, (GdkModifierType) GDK_CONTROL_MASK,
GTK_ACCEL_VISIBLE);
! image626 = gtk_image_new_from_stock ("gtk-goto-first", GTK_ICON_SIZE_MENU);
! gtk_widget_show (image626);
! gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (viewFirstPage), image626);
!
! viewPreviousPage = gtk_image_menu_item_new_with_mnemonic (_("_Previous Page"));
gtk_widget_show (viewPreviousPage);
gtk_container_add (GTK_CONTAINER (menuView_menu), viewPreviousPage);
gtk_widget_add_accelerator (viewPreviousPage, "activate", accel_group,
GDK_Left, (GdkModifierType) GDK_CONTROL_MASK,
GTK_ACCEL_VISIBLE);
! image627 = gtk_image_new_from_stock ("gtk-go-back", GTK_ICON_SIZE_MENU);
! gtk_widget_show (image627);
! gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (viewPreviousPage), image627);
!
! viewNextPage = gtk_image_menu_item_new_with_mnemonic (_("_Next Page"));
gtk_widget_show (viewNextPage);
gtk_container_add (GTK_CONTAINER (menuView_menu), viewNextPage);
gtk_widget_add_accelerator (viewNextPage, "activate", accel_group,
GDK_Right, (GdkModifierType) GDK_CONTROL_MASK,
GTK_ACCEL_VISIBLE);
! image628 = gtk_image_new_from_stock ("gtk-go-forward", GTK_ICON_SIZE_MENU);
! gtk_widget_show (image628);
! gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (viewNextPage), image628);
!
! viewLastPage = gtk_image_menu_item_new_with_mnemonic (_("_Last Page"));
gtk_widget_show (viewLastPage);
gtk_container_add (GTK_CONTAINER (menuView_menu), viewLastPage);
gtk_widget_add_accelerator (viewLastPage, "activate", accel_group,
GDK_End, (GdkModifierType) GDK_CONTROL_MASK,
GTK_ACCEL_VISIBLE);
- image629 = gtk_image_new_from_stock ("gtk-goto-last", GTK_ICON_SIZE_MENU);
- gtk_widget_show (image629);
- gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (viewLastPage), image629);
-
separator6 = gtk_separator_menu_item_new ();
gtk_widget_show (separator6);
gtk_container_add (GTK_CONTAINER (menuView_menu), separator6);
gtk_widget_set_sensitive (separator6, FALSE);
! viewShowLayer = gtk_image_menu_item_new_with_mnemonic (_("_Show Layer"));
gtk_widget_show (viewShowLayer);
gtk_container_add (GTK_CONTAINER (menuView_menu), viewShowLayer);
! image630 = gtk_image_new_from_stock ("gtk-add", GTK_ICON_SIZE_MENU);
! gtk_widget_show (image630);
! gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (viewShowLayer), image630);
!
! viewHideLayer = gtk_image_menu_item_new_with_mnemonic (_("_Hide Layer"));
gtk_widget_show (viewHideLayer);
gtk_container_add (GTK_CONTAINER (menuView_menu), viewHideLayer);
- image631 = gtk_image_new_from_stock ("gtk-remove", GTK_ICON_SIZE_MENU);
- gtk_widget_show (image631);
- gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (viewHideLayer), image631);
-
menuJournal = gtk_menu_item_new_with_mnemonic (_("_Journal"));
gtk_widget_show (menuJournal);
gtk_container_add (GTK_CONTAINER (menubar), menuJournal);
--- 574,620 ----
gtk_container_add (GTK_CONTAINER (menuView_menu), separator5);
gtk_widget_set_sensitive (separator5, FALSE);
! viewFirstPage = gtk_image_menu_item_new_with_mnemonic ("_First Page");
gtk_widget_show (viewFirstPage);
gtk_container_add (GTK_CONTAINER (menuView_menu), viewFirstPage);
gtk_widget_add_accelerator (viewFirstPage, "activate", accel_group,
GDK_Home, (GdkModifierType) GDK_CONTROL_MASK,
GTK_ACCEL_VISIBLE);
! viewPreviousPage = gtk_image_menu_item_new_with_mnemonic ("_Previous Page");
gtk_widget_show (viewPreviousPage);
gtk_container_add (GTK_CONTAINER (menuView_menu), viewPreviousPage);
gtk_widget_add_accelerator (viewPreviousPage, "activate", accel_group,
GDK_Left, (GdkModifierType) GDK_CONTROL_MASK,
GTK_ACCEL_VISIBLE);
! viewNextPage = gtk_image_menu_item_new_with_mnemonic ("_Next Page");
gtk_widget_show (viewNextPage);
gtk_container_add (GTK_CONTAINER (menuView_menu), viewNextPage);
gtk_widget_add_accelerator (viewNextPage, "activate", accel_group,
GDK_Right, (GdkModifierType) GDK_CONTROL_MASK,
GTK_ACCEL_VISIBLE);
! viewLastPage = gtk_image_menu_item_new_with_mnemonic ("_Last Page");
gtk_widget_show (viewLastPage);
gtk_container_add (GTK_CONTAINER (menuView_menu), viewLastPage);
gtk_widget_add_accelerator (viewLastPage, "activate", accel_group,
GDK_End, (GdkModifierType) GDK_CONTROL_MASK,
GTK_ACCEL_VISIBLE);
separator6 = gtk_separator_menu_item_new ();
gtk_widget_show (separator6);
gtk_container_add (GTK_CONTAINER (menuView_menu), separator6);
gtk_widget_set_sensitive (separator6, FALSE);
! viewShowLayer = gtk_image_menu_item_new_with_mnemonic ("_Show Layer");
gtk_widget_show (viewShowLayer);
gtk_container_add (GTK_CONTAINER (menuView_menu), viewShowLayer);
! viewHideLayer = gtk_image_menu_item_new_with_mnemonic ("_Hide Layer");
gtk_widget_show (viewHideLayer);
gtk_container_add (GTK_CONTAINER (menuView_menu), viewHideLayer);
menuJournal = gtk_menu_item_new_with_mnemonic (_("_Journal"));
gtk_widget_show (menuJournal);
gtk_container_add (GTK_CONTAINER (menubar), menuJournal);
***************
*** 808,821 ****
gtk_container_add (GTK_CONTAINER (menuJournal_menu), separator23);
gtk_widget_set_sensitive (separator23, FALSE);
! journalLoadBackground = gtk_image_menu_item_new_with_mnemonic (_("_Load Background"));
gtk_widget_show (journalLoadBackground);
gtk_container_add (GTK_CONTAINER (menuJournal_menu), journalLoadBackground);
- image632 = gtk_image_new_from_stock ("gtk-open", GTK_ICON_SIZE_MENU);
- gtk_widget_show (image632);
- gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (journalLoadBackground), image632);
-
journalScreenshot = gtk_menu_item_new_with_mnemonic (_("Background Screens_hot"));
gtk_widget_show (journalScreenshot);
gtk_container_add (GTK_CONTAINER (menuJournal_menu), journalScreenshot);
--- 761,770 ----
gtk_container_add (GTK_CONTAINER (menuJournal_menu), separator23);
gtk_widget_set_sensitive (separator23, FALSE);
! journalLoadBackground = gtk_image_menu_item_new_with_mnemonic ("_Load Background");
gtk_widget_show (journalLoadBackground);
gtk_container_add (GTK_CONTAINER (menuJournal_menu), journalLoadBackground);
journalScreenshot = gtk_menu_item_new_with_mnemonic (_("Background Screens_hot"));
gtk_widget_show (journalScreenshot);
gtk_container_add (GTK_CONTAINER (menuJournal_menu), journalScreenshot);
***************
*** 940,953 ****
gtk_container_add (GTK_CONTAINER (menuTools_menu), separator16);
gtk_widget_set_sensitive (separator16, FALSE);
! toolsColor = gtk_image_menu_item_new_with_mnemonic (_("_Color"));
gtk_widget_show (toolsColor);
gtk_container_add (GTK_CONTAINER (menuTools_menu), toolsColor);
- image633 = gtk_image_new_from_stock ("gtk-select-color", GTK_ICON_SIZE_MENU);
- gtk_widget_show (image633);
- gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (toolsColor), image633);
-
toolsColor_menu = gtk_menu_new ();
gtk_menu_item_set_submenu (GTK_MENU_ITEM (toolsColor), toolsColor_menu);
--- 889,898 ----
gtk_container_add (GTK_CONTAINER (menuTools_menu), separator16);
gtk_widget_set_sensitive (separator16, FALSE);
! toolsColor = gtk_image_menu_item_new_with_mnemonic ("_Color");
gtk_widget_show (toolsColor);
gtk_container_add (GTK_CONTAINER (menuTools_menu), toolsColor);
toolsColor_menu = gtk_menu_new ();
gtk_menu_item_set_submenu (GTK_MENU_ITEM (toolsColor), toolsColor_menu);
***************
*** 1141,1157 ****
gtk_container_add (GTK_CONTAINER (toolsHighlighterOptions_menu), highlighterThick);
gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (highlighterThick), TRUE);
! toolsTextFont = gtk_image_menu_item_new_with_mnemonic (_("Text _Font..."));
gtk_widget_show (toolsTextFont);
gtk_container_add (GTK_CONTAINER (menuTools_menu), toolsTextFont);
gtk_widget_add_accelerator (toolsTextFont, "activate", accel_group,
GDK_F, (GdkModifierType) GDK_CONTROL_MASK | GDK_SHIFT_MASK,
GTK_ACCEL_VISIBLE);
- image634 = gtk_image_new_from_stock ("gtk-select-font", GTK_ICON_SIZE_MENU);
- gtk_widget_show (image634);
- gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (toolsTextFont), image634);
-
separator10 = gtk_separator_menu_item_new ();
gtk_widget_show (separator10);
gtk_container_add (GTK_CONTAINER (menuTools_menu), separator10);
--- 1086,1098 ----
gtk_container_add (GTK_CONTAINER (toolsHighlighterOptions_menu), highlighterThick);
gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (highlighterThick), TRUE);
! toolsTextFont = gtk_image_menu_item_new_with_mnemonic ("Text _Font...");
gtk_widget_show (toolsTextFont);
gtk_container_add (GTK_CONTAINER (menuTools_menu), toolsTextFont);
gtk_widget_add_accelerator (toolsTextFont, "activate", accel_group,
GDK_F, (GdkModifierType) GDK_CONTROL_MASK | GDK_SHIFT_MASK,
GTK_ACCEL_VISIBLE);
separator10 = gtk_separator_menu_item_new ();
gtk_widget_show (separator10);
gtk_container_add (GTK_CONTAINER (menuTools_menu), separator10);
***************
*** 1588,1593 ****
--- 1529,1545 ----
gtk_radio_tool_button_set_group (GTK_RADIO_TOOL_BUTTON (buttonText), buttonPen_group);
buttonPen_group = gtk_radio_tool_button_get_group (GTK_RADIO_TOOL_BUTTON (buttonText));
+ buttonImage = (GtkWidget*) gtk_radio_tool_button_new (NULL);
+ gtk_tool_button_set_label (GTK_TOOL_BUTTON (buttonImage), _("Image"));
+ tmp_image = gtk_image_new_from_stock ("gtk-orientation-portrait", tmp_toolbar_icon_size);
+ gtk_widget_show (tmp_image);
+ gtk_tool_button_set_icon_widget (GTK_TOOL_BUTTON (buttonImage), tmp_image);
+ gtk_widget_show (buttonImage);
+ gtk_container_add (GTK_CONTAINER (toolbarPen), buttonImage);
+ gtk_tool_item_set_tooltip (GTK_TOOL_ITEM (buttonImage), tooltips, _("Image"), NULL);
+ gtk_radio_tool_button_set_group (GTK_RADIO_TOOL_BUTTON (buttonImage), buttonPen_group);
+ buttonPen_group = gtk_radio_tool_button_get_group (GTK_RADIO_TOOL_BUTTON (buttonImage));
+
buttonReco = (GtkWidget*) gtk_toggle_tool_button_new ();
gtk_tool_button_set_label (GTK_TOOL_BUTTON (buttonReco), _("Shape Recognizer"));
tmp_image = create_pixmap (winMain, "shapes.png");
***************
*** 1669,1675 ****
gtk_widget_show (tmp_image);
buttonToolDefault = (GtkWidget*) gtk_tool_button_new (tmp_image, _("Default"));
gtk_widget_show (buttonToolDefault);
- gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (buttonToolDefault), FALSE);
gtk_container_add (GTK_CONTAINER (toolbarPen), buttonToolDefault);
gtk_tool_item_set_tooltip (GTK_TOOL_ITEM (buttonToolDefault), tooltips, _("Default"), NULL);
--- 1621,1626 ----
***************
*** 1694,1700 ****
gtk_widget_show (tmp_image);
gtk_tool_button_set_icon_widget (GTK_TOOL_BUTTON (buttonFine), tmp_image);
gtk_widget_show (buttonFine);
- gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (buttonFine), FALSE);
gtk_container_add (GTK_CONTAINER (toolbarPen), buttonFine);
gtk_widget_set_size_request (buttonFine, 24, -1);
gtk_tool_item_set_tooltip (GTK_TOOL_ITEM (buttonFine), tooltips, _("Fine"), NULL);
--- 1645,1650 ----
***************
*** 1707,1713 ****
gtk_widget_show (tmp_image);
gtk_tool_button_set_icon_widget (GTK_TOOL_BUTTON (buttonMedium), tmp_image);
gtk_widget_show (buttonMedium);
- gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (buttonMedium), FALSE);
gtk_container_add (GTK_CONTAINER (toolbarPen), buttonMedium);
gtk_widget_set_size_request (buttonMedium, 24, -1);
gtk_tool_item_set_tooltip (GTK_TOOL_ITEM (buttonMedium), tooltips, _("Medium"), NULL);
--- 1657,1662 ----
***************
*** 1720,1726 ****
gtk_widget_show (tmp_image);
gtk_tool_button_set_icon_widget (GTK_TOOL_BUTTON (buttonThick), tmp_image);
gtk_widget_show (buttonThick);
- gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (buttonThick), FALSE);
gtk_container_add (GTK_CONTAINER (toolbarPen), buttonThick);
gtk_widget_set_size_request (buttonThick, 24, -1);
gtk_tool_item_set_tooltip (GTK_TOOL_ITEM (buttonThick), tooltips, _("Thick"), NULL);
--- 1669,1674 ----
***************
*** 1747,1753 ****
gtk_widget_show (tmp_image);
gtk_tool_button_set_icon_widget (GTK_TOOL_BUTTON (buttonBlack), tmp_image);
gtk_widget_show (buttonBlack);
- gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (buttonBlack), FALSE);
gtk_container_add (GTK_CONTAINER (toolbarPen), buttonBlack);
gtk_tool_item_set_tooltip (GTK_TOOL_ITEM (buttonBlack), tooltips, _("Black"), NULL);
gtk_radio_tool_button_set_group (GTK_RADIO_TOOL_BUTTON (buttonBlack), buttonBlack_group);
--- 1695,1700 ----
***************
*** 1759,1765 ****
gtk_widget_show (tmp_image);
gtk_tool_button_set_icon_widget (GTK_TOOL_BUTTON (buttonBlue), tmp_image);
gtk_widget_show (buttonBlue);
- gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (buttonBlue), FALSE);
gtk_container_add (GTK_CONTAINER (toolbarPen), buttonBlue);
gtk_tool_item_set_tooltip (GTK_TOOL_ITEM (buttonBlue), tooltips, _("Blue"), NULL);
gtk_radio_tool_button_set_group (GTK_RADIO_TOOL_BUTTON (buttonBlue), buttonBlack_group);
--- 1706,1711 ----
***************
*** 1771,1777 ****
gtk_widget_show (tmp_image);
gtk_tool_button_set_icon_widget (GTK_TOOL_BUTTON (buttonRed), tmp_image);
gtk_widget_show (buttonRed);
- gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (buttonRed), FALSE);
gtk_container_add (GTK_CONTAINER (toolbarPen), buttonRed);
gtk_tool_item_set_tooltip (GTK_TOOL_ITEM (buttonRed), tooltips, _("Red"), NULL);
gtk_radio_tool_button_set_group (GTK_RADIO_TOOL_BUTTON (buttonRed), buttonBlack_group);
--- 1717,1722 ----
***************
*** 1783,1789 ****
gtk_widget_show (tmp_image);
gtk_tool_button_set_icon_widget (GTK_TOOL_BUTTON (buttonGreen), tmp_image);
gtk_widget_show (buttonGreen);
- gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (buttonGreen), FALSE);
gtk_container_add (GTK_CONTAINER (toolbarPen), buttonGreen);
gtk_tool_item_set_tooltip (GTK_TOOL_ITEM (buttonGreen), tooltips, _("Green"), NULL);
gtk_radio_tool_button_set_group (GTK_RADIO_TOOL_BUTTON (buttonGreen), buttonBlack_group);
--- 1728,1733 ----
***************
*** 1795,1801 ****
gtk_widget_show (tmp_image);
gtk_tool_button_set_icon_widget (GTK_TOOL_BUTTON (buttonGray), tmp_image);
gtk_widget_show (buttonGray);
- gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (buttonGray), FALSE);
gtk_container_add (GTK_CONTAINER (toolbarPen), buttonGray);
gtk_tool_item_set_tooltip (GTK_TOOL_ITEM (buttonGray), tooltips, _("Gray"), NULL);
gtk_radio_tool_button_set_group (GTK_RADIO_TOOL_BUTTON (buttonGray), buttonBlack_group);
--- 1739,1744 ----
***************
*** 1807,1813 ****
gtk_widget_show (tmp_image);
gtk_tool_button_set_icon_widget (GTK_TOOL_BUTTON (buttonLightBlue), tmp_image);
gtk_widget_show (buttonLightBlue);
- gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (buttonLightBlue), FALSE);
gtk_container_add (GTK_CONTAINER (toolbarPen), buttonLightBlue);
gtk_tool_item_set_tooltip (GTK_TOOL_ITEM (buttonLightBlue), tooltips, _("Light Blue"), NULL);
gtk_radio_tool_button_set_group (GTK_RADIO_TOOL_BUTTON (buttonLightBlue), buttonBlack_group);
--- 1750,1755 ----
***************
*** 1819,1825 ****
gtk_widget_show (tmp_image);
gtk_tool_button_set_icon_widget (GTK_TOOL_BUTTON (buttonLightGreen), tmp_image);
gtk_widget_show (buttonLightGreen);
- gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (buttonLightGreen), FALSE);
gtk_container_add (GTK_CONTAINER (toolbarPen), buttonLightGreen);
gtk_tool_item_set_tooltip (GTK_TOOL_ITEM (buttonLightGreen), tooltips, _("Light Green"), NULL);
gtk_radio_tool_button_set_group (GTK_RADIO_TOOL_BUTTON (buttonLightGreen), buttonBlack_group);
--- 1761,1766 ----
***************
*** 1831,1837 ****
gtk_widget_show (tmp_image);
gtk_tool_button_set_icon_widget (GTK_TOOL_BUTTON (buttonMagenta), tmp_image);
gtk_widget_show (buttonMagenta);
- gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (buttonMagenta), FALSE);
gtk_container_add (GTK_CONTAINER (toolbarPen), buttonMagenta);
gtk_tool_item_set_tooltip (GTK_TOOL_ITEM (buttonMagenta), tooltips, _("Magenta"), NULL);
gtk_radio_tool_button_set_group (GTK_RADIO_TOOL_BUTTON (buttonMagenta), buttonBlack_group);
--- 1772,1777 ----
***************
*** 1843,1849 ****
gtk_widget_show (tmp_image);
gtk_tool_button_set_icon_widget (GTK_TOOL_BUTTON (buttonOrange), tmp_image);
gtk_widget_show (buttonOrange);
- gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (buttonOrange), FALSE);
gtk_container_add (GTK_CONTAINER (toolbarPen), buttonOrange);
gtk_tool_item_set_tooltip (GTK_TOOL_ITEM (buttonOrange), tooltips, _("Orange"), NULL);
gtk_radio_tool_button_set_group (GTK_RADIO_TOOL_BUTTON (buttonOrange), buttonBlack_group);
--- 1783,1788 ----
***************
*** 1855,1861 ****
gtk_widget_show (tmp_image);
gtk_tool_button_set_icon_widget (GTK_TOOL_BUTTON (buttonYellow), tmp_image);
gtk_widget_show (buttonYellow);
- gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (buttonYellow), FALSE);
gtk_container_add (GTK_CONTAINER (toolbarPen), buttonYellow);
gtk_tool_item_set_tooltip (GTK_TOOL_ITEM (buttonYellow), tooltips, _("Yellow"), NULL);
gtk_radio_tool_button_set_group (GTK_RADIO_TOOL_BUTTON (buttonYellow), buttonBlack_group);
--- 1794,1799 ----
***************
*** 1867,1873 ****
gtk_widget_show (tmp_image);
gtk_tool_button_set_icon_widget (GTK_TOOL_BUTTON (buttonWhite), tmp_image);
gtk_widget_show (buttonWhite);
- gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (buttonWhite), FALSE);
gtk_container_add (GTK_CONTAINER (toolbarPen), buttonWhite);
gtk_tool_item_set_tooltip (GTK_TOOL_ITEM (buttonWhite), tooltips, _("White"), NULL);
gtk_radio_tool_button_set_group (GTK_RADIO_TOOL_BUTTON (buttonWhite), buttonBlack_group);
--- 1805,1810 ----
***************
*** 2426,2431 ****
--- 2363,2371 ----
g_signal_connect ((gpointer) buttonText, "toggled",
G_CALLBACK (on_toolsText_activate),
NULL);
+ g_signal_connect ((gpointer) buttonImage, "toggled",
+ G_CALLBACK (on_toolsImage_activate),
+ NULL);
g_signal_connect ((gpointer) buttonReco, "toggled",
G_CALLBACK (on_toolsReco_activate),
NULL);
***************
*** 2513,2519 ****
GLADE_HOOKUP_OBJECT (winMain, menuFile_menu, "menuFile_menu");
GLADE_HOOKUP_OBJECT (winMain, fileNew, "fileNew");
GLADE_HOOKUP_OBJECT (winMain, fileNewBackground, "fileNewBackground");
- GLADE_HOOKUP_OBJECT (winMain, image623, "image623");
GLADE_HOOKUP_OBJECT (winMain, fileOpen, "fileOpen");
GLADE_HOOKUP_OBJECT (winMain, fileSave, "fileSave");
GLADE_HOOKUP_OBJECT (winMain, fileSaveAs, "fileSaveAs");
--- 2453,2458 ----
***************
*** 2530,2536 ****
GLADE_HOOKUP_OBJECT (winMain, mru7, "mru7");
GLADE_HOOKUP_OBJECT (winMain, separator22, "separator22");
GLADE_HOOKUP_OBJECT (winMain, filePrintOptions, "filePrintOptions");
- GLADE_HOOKUP_OBJECT (winMain, image624, "image624");
GLADE_HOOKUP_OBJECT (winMain, filePrint, "filePrint");
GLADE_HOOKUP_OBJECT (winMain, filePrintPDF, "filePrintPDF");
GLADE_HOOKUP_OBJECT (winMain, separator2, "separator2");
--- 2469,2474 ----
***************
*** 2557,2578 ****
GLADE_HOOKUP_OBJECT (winMain, viewZoomOut, "viewZoomOut");
GLADE_HOOKUP_OBJECT (winMain, viewNormalSize, "viewNormalSize");
GLADE_HOOKUP_OBJECT (winMain, viewPageWidth, "viewPageWidth");
- GLADE_HOOKUP_OBJECT (winMain, image625, "image625");
GLADE_HOOKUP_OBJECT (winMain, viewSetZoom, "viewSetZoom");
GLADE_HOOKUP_OBJECT (winMain, separator5, "separator5");
GLADE_HOOKUP_OBJECT (winMain, viewFirstPage, "viewFirstPage");
- GLADE_HOOKUP_OBJECT (winMain, image626, "image626");
GLADE_HOOKUP_OBJECT (winMain, viewPreviousPage, "viewPreviousPage");
- GLADE_HOOKUP_OBJECT (winMain, image627, "image627");
GLADE_HOOKUP_OBJECT (winMain, viewNextPage, "viewNextPage");
- GLADE_HOOKUP_OBJECT (winMain, image628, "image628");
GLADE_HOOKUP_OBJECT (winMain, viewLastPage, "viewLastPage");
- GLADE_HOOKUP_OBJECT (winMain, image629, "image629");
GLADE_HOOKUP_OBJECT (winMain, separator6, "separator6");
GLADE_HOOKUP_OBJECT (winMain, viewShowLayer, "viewShowLayer");
- GLADE_HOOKUP_OBJECT (winMain, image630, "image630");
GLADE_HOOKUP_OBJECT (winMain, viewHideLayer, "viewHideLayer");
- GLADE_HOOKUP_OBJECT (winMain, image631, "image631");
GLADE_HOOKUP_OBJECT (winMain, menuJournal, "menuJournal");
GLADE_HOOKUP_OBJECT (winMain, menuJournal_menu, "menuJournal_menu");
GLADE_HOOKUP_OBJECT (winMain, journalNewPageBefore, "journalNewPageBefore");
--- 2495,2509 ----
***************
*** 2605,2611 ****
GLADE_HOOKUP_OBJECT (winMain, journalApplyAllPages, "journalApplyAllPages");
GLADE_HOOKUP_OBJECT (winMain, separator23, "separator23");
GLADE_HOOKUP_OBJECT (winMain, journalLoadBackground, "journalLoadBackground");
- GLADE_HOOKUP_OBJECT (winMain, image632, "image632");
GLADE_HOOKUP_OBJECT (winMain, journalScreenshot, "journalScreenshot");
GLADE_HOOKUP_OBJECT (winMain, separator19, "separator19");
GLADE_HOOKUP_OBJECT (winMain, journalDefaultBackground, "journalDefaultBackground");
--- 2536,2541 ----
***************
*** 2626,2632 ****
GLADE_HOOKUP_OBJECT (winMain, toolsHand, "toolsHand");
GLADE_HOOKUP_OBJECT (winMain, separator16, "separator16");
GLADE_HOOKUP_OBJECT (winMain, toolsColor, "toolsColor");
- GLADE_HOOKUP_OBJECT (winMain, image633, "image633");
GLADE_HOOKUP_OBJECT (winMain, toolsColor_menu, "toolsColor_menu");
GLADE_HOOKUP_OBJECT (winMain, colorBlack, "colorBlack");
GLADE_HOOKUP_OBJECT (winMain, colorBlue, "colorBlue");
--- 2556,2561 ----
***************
*** 2664,2670 ****
GLADE_HOOKUP_OBJECT (winMain, highlighterMedium, "highlighterMedium");
GLADE_HOOKUP_OBJECT (winMain, highlighterThick, "highlighterThick");
GLADE_HOOKUP_OBJECT (winMain, toolsTextFont, "toolsTextFont");
- GLADE_HOOKUP_OBJECT (winMain, image634, "image634");
GLADE_HOOKUP_OBJECT (winMain, separator10, "separator10");
GLADE_HOOKUP_OBJECT (winMain, toolsDefaultPen, "toolsDefaultPen");
GLADE_HOOKUP_OBJECT (winMain, toolsDefaultEraser, "toolsDefaultEraser");
--- 2593,2598 ----
***************
*** 2750,2755 ****
--- 2678,2684 ----
GLADE_HOOKUP_OBJECT (winMain, buttonEraser, "buttonEraser");
GLADE_HOOKUP_OBJECT (winMain, buttonHighlighter, "buttonHighlighter");
GLADE_HOOKUP_OBJECT (winMain, buttonText, "buttonText");
+ GLADE_HOOKUP_OBJECT (winMain, buttonImage, "buttonImage");
GLADE_HOOKUP_OBJECT (winMain, buttonReco, "buttonReco");
GLADE_HOOKUP_OBJECT (winMain, buttonRuler, "buttonRuler");
GLADE_HOOKUP_OBJECT (winMain, toolitem15, "toolitem15");
***************
*** 2860,2865 ****
--- 2789,2795 ----
entryWidth = gtk_entry_new ();
gtk_widget_show (entryWidth);
gtk_box_pack_start (GTK_BOX (hbox3), entryWidth, TRUE, TRUE, 0);
+ gtk_entry_set_invisible_char (GTK_ENTRY (entryWidth), 9679);
gtk_entry_set_width_chars (GTK_ENTRY (entryWidth), 5);
labelHeight = gtk_label_new (_("Height:"));
***************
*** 2869,2874 ****
--- 2799,2805 ----
entryHeight = gtk_entry_new ();
gtk_widget_show (entryHeight);
gtk_box_pack_start (GTK_BOX (hbox3), entryHeight, TRUE, TRUE, 0);
+ gtk_entry_set_invisible_char (GTK_ENTRY (entryHeight), 9679);
gtk_entry_set_width_chars (GTK_ENTRY (entryHeight), 5);
comboUnit = gtk_combo_box_new_text ();
***************
*** 2951,2962 ****
labelTitle = gtk_label_new (_("Xournal"));
gtk_widget_show (labelTitle);
gtk_box_pack_start (GTK_BOX (dialog_vbox2), labelTitle, FALSE, FALSE, 3);
- gtk_label_set_justify (GTK_LABEL (labelTitle), GTK_JUSTIFY_CENTER);
labelInfo = gtk_label_new (_("Written by Denis Auroux\nand other contributors\n http://xournal.sourceforge.net/ "));
gtk_widget_show (labelInfo);
gtk_box_pack_start (GTK_BOX (dialog_vbox2), labelInfo, FALSE, FALSE, 0);
- gtk_label_set_justify (GTK_LABEL (labelInfo), GTK_JUSTIFY_CENTER);
gtk_misc_set_padding (GTK_MISC (labelInfo), 20, 10);
dialog_action_area2 = GTK_DIALOG (aboutDialog)->action_area;
--- 2882,2891 ----
diff -c 'xournal-0.4.5/src/xo-misc.c' 'xournal/src/xo-misc.c'
Index: ./src/xo-misc.c
*** ./src/xo-misc.c Fri Oct 2 20:20:30 2009
--- ./src/xo-misc.c Thu Jul 29 16:11:24 2010
***************
*** 17,22 ****
--- 17,23 ----
#include "xo-file.h"
#include "xo-paint.h"
#include "xo-shapes.h"
+ #include "xo-image.h"
// some global constants
***************
*** 90,95 ****
--- 91,121 ----
return pg;
}
+ // change the current page if necessary for pointer at pt
+ void set_current_page(gdouble *pt)
+ {
+ gboolean page_change;
+ struct Page *tmppage;
+
+ page_change = FALSE;
+ tmppage = ui.cur_page;
+ while (ui.view_continuous && (pt[1] < - VIEW_CONTINUOUS_SKIP)) {
+ if (ui.pageno == 0) break;
+ page_change = TRUE;
+ ui.pageno--;
+ tmppage = g_list_nth_data(journal.pages, ui.pageno);
+ pt[1] += tmppage->height + VIEW_CONTINUOUS_SKIP;
+ }
+ while (ui.view_continuous && (pt[1] > tmppage->height + VIEW_CONTINUOUS_SKIP)) {
+ if (ui.pageno == journal.npages-1) break;
+ pt[1] -= tmppage->height + VIEW_CONTINUOUS_SKIP;
+ page_change = TRUE;
+ ui.pageno++;
+ tmppage = g_list_nth_data(journal.pages, ui.pageno);
+ }
+ if (page_change) do_switch_page(ui.pageno, FALSE, FALSE);
+ }
+
void realloc_cur_path(int n)
{
if (n <= ui.cur_path_storage_alloc) return;
***************
*** 142,147 ****
--- 168,179 ----
g_free(redo->item->font_name);
g_free(redo->item);
}
+ else if (redo->type == ITEM_IMAGE) {
+ g_object_unref(redo->item->image);
+ if (redo->item->image_scaled != NULL) g_object_unref(redo->item->image_scaled);
+ g_free(redo->item->image_png);
+ g_free(redo->item);
+ }
else if (redo->type == ITEM_ERASURE || redo->type == ITEM_RECOGNIZER) {
for (list = redo->erasurelist; list!=NULL; list=list->next) {
erasure = (struct UndoErasureData *)list->data;
***************
*** 218,223 ****
--- 250,260 ----
}
if (erasure->item->type == ITEM_TEXT)
{ g_free(erasure->item->text); g_free(erasure->item->font_name); }
+ if (erasure->item->type == ITEM_IMAGE) {
+ g_object_unref(erasure->item->image);
+ if (erasure->item->image_scaled != NULL) g_object_unref(erasure->item->image_scaled);
+ g_free(erasure->item->image_png);
+ }
g_free(erasure->item);
g_list_free(erasure->replacement_items);
g_free(erasure);
***************
*** 302,307 ****
--- 339,349 ----
if (item->type == ITEM_TEXT) {
g_free(item->font_name); g_free(item->text);
}
+ if (item->type == ITEM_IMAGE) {
+ g_object_unref(item->image);
+ if (item->image_scaled != NULL) g_object_unref(item->image_scaled);
+ g_free(item->image_png);
+ }
// don't need to delete the canvas_item, as it's part of the group destroyed below
g_free(item);
l->items = g_list_delete_link(l->items, l->items);
***************
*** 350,355 ****
--- 392,409 ----
ret[1] -= ui.cur_page->voffset;
}
+ // get the current pointer position in canvas world coordinates
+ void get_current_pointer_coords(gdouble *ret)
+ {
+ gint wx, wy, sx, sy;
+
+ gtk_widget_get_pointer((GtkWidget *)canvas, &wx, &wy);
+ gnome_canvas_get_scroll_offsets(canvas, &sx, &sy);
+ gnome_canvas_window_to_world(canvas, (double)(wx + sx), (double)(wy + sy), ret, ret+1);
+ ret[0] -= ui.cur_page->hoffset;
+ ret[1] -= ui.cur_page->voffset;
+ }
+
void fix_xinput_coords(GdkEvent *event)
{
double *axes, *px, *py, axis_width;
***************
*** 440,446 ****
{
int i;
gdouble *p, h, w;
!
if (item->type == ITEM_STROKE) {
item->bbox.left = item->bbox.right = item->path->coords[0];
item->bbox.top = item->bbox.bottom = item->path->coords[1];
--- 494,501 ----
{
int i;
gdouble *p, h, w;
! gboolean width_in_pixels, height_in_pixels;
!
if (item->type == ITEM_STROKE) {
item->bbox.left = item->bbox.right = item->path->coords[0];
item->bbox.top = item->bbox.bottom = item->path->coords[1];
***************
*** 458,463 ****
--- 513,534 ----
item->bbox.right = item->bbox.left + w;
item->bbox.bottom = item->bbox.top + h;
}
+ if (item->type == ITEM_IMAGE && item->canvas_item!=NULL) {
+ // be careful in case canvas item size in pixels
+ h=0.; w=0.;
+ g_object_get(item->canvas_item, "width", &w, "height", &h,
+ "width-in-pixels", &width_in_pixels,
+ "height-in-pixels", &height_in_pixels,
+ NULL);
+ if (width_in_pixels) {
+ w /= ui.zoom;
+ }
+ if (height_in_pixels) {
+ h /= ui.zoom;
+ }
+ item->bbox.right = item->bbox.left + w;
+ item->bbox.bottom = item->bbox.top + h;
+ }
}
void make_page_clipbox(struct Page *pg)
***************
*** 474,483 ****
--- 545,640 ----
gnome_canvas_path_def_unref(pg_clip);
}
+ void adjust_or_make_canvas_item_image(GnomeCanvasGroup *group, struct Item *item)
+ {
+ double required_width;
+ double required_height;
+
+ // discard previous scaled image, if any
+ if ( item->image_scaled != NULL ) {
+ g_object_unref(item->image_scaled);
+ item->image_scaled = NULL;
+ }
+
+ if ( is_native_image_usable( item ) ) {
+ // use native resolution, for sharper image
+ if (item->canvas_item == NULL) {
+ // first time, create new canvas item
+ item->canvas_item = gnome_canvas_item_new(group,
+ GNOME_TYPE_CANVAS_PIXBUF,
+ "anchor", GTK_ANCHOR_NW,
+ "height-in-pixels", TRUE,
+ "width-in-pixels", TRUE,
+ "x-in-pixels", FALSE,
+ "y-in-pixels", FALSE,
+ "pixbuf", item->image,
+ "x", item->bbox.left,
+ "y", item->bbox.top,
+ "height", (double)gdk_pixbuf_get_height(item->image),
+ "width", (double)gdk_pixbuf_get_width(item->image),
+ NULL);
+ } else {
+ // update the existing one, which may have been for a scaled image
+ gnome_canvas_item_set(item->canvas_item,
+ "height-in-pixels", TRUE,
+ "width-in-pixels", TRUE,
+ "pixbuf", item->image,
+ "height", (double)gdk_pixbuf_get_height(item->image),
+ "width", (double)gdk_pixbuf_get_width(item->image),
+ NULL);
+ }
+ } else {
+ // settle for scaled (and blurry) image
+ required_width = item->bbox.right - item->bbox.left;
+ required_height = item->bbox.bottom - item->bbox.top;
+
+ item->image_scaled = gdk_pixbuf_scale_simple(item->image,
+ required_width,
+ required_height,
+ GDK_INTERP_HYPER);
+ if (item->canvas_item == NULL) {
+ // first time, create new canvas item
+ item->canvas_item = gnome_canvas_item_new(group,
+ GNOME_TYPE_CANVAS_PIXBUF,
+ "anchor", GTK_ANCHOR_NW,
+ "height-in-pixels", FALSE,
+ "width-in-pixels", FALSE,
+ "x-in-pixels", FALSE,
+ "y-in-pixels", FALSE,
+ "pixbuf", item->image_scaled,
+ "x", item->bbox.left,
+ "y", item->bbox.top,
+ "height", required_height,
+ "width", required_width,
+ NULL);
+ } else {
+ // update the existing one, which may have been for a scaled image
+ gnome_canvas_item_set(item->canvas_item,
+ "height-in-pixels", FALSE,
+ "width-in-pixels", FALSE,
+ "pixbuf", item->image_scaled,
+ "height", required_height,
+ "width", required_width,
+ NULL);
+ }
+ }
+
+ // reposition the canvas item absolutely, and reset the affine transformation
+ gnome_canvas_item_affine_absolute(item->canvas_item, NULL);
+ gnome_canvas_item_set(item->canvas_item,
+ "x", item->bbox.left,
+ "y", item->bbox.top,
+ NULL);
+ }
+
void make_canvas_item_one(GnomeCanvasGroup *group, struct Item *item)
{
PangoFontDescription *font_desc;
GnomeCanvasPoints points;
+ GtkFileFilter *filt_all;
+ GtkFileFilter *filt_gdkimage;
+ GtkWidget *dialog;
+ char *tmp_filename;
int j;
if (item->type == ITEM_STROKE) {
***************
*** 513,518 ****
--- 670,678 ----
"text", item->text, NULL);
update_item_bbox(item);
}
+ if (item->type == ITEM_IMAGE) {
+ adjust_or_make_canvas_item_image(group, item);
+ }
}
void make_canvas_items(void)
***************
*** 861,866 ****
--- 1021,1031 ----
gtk_toggle_tool_button_set_active(
GTK_TOGGLE_TOOL_BUTTON(GET_COMPONENT("buttonText")), TRUE);
break;
+
+ case TOOL_IMAGE:
+ gtk_toggle_tool_button_set_active(
+ GTK_TOGGLE_TOOL_BUTTON(GET_COMPONENT("buttonImage")), TRUE);
+ break;
case TOOL_SELECTREGION:
gtk_toggle_tool_button_set_active(
GTK_TOGGLE_TOOL_BUTTON(GET_COMPONENT("buttonSelectRegion")), TRUE);
***************
*** 1377,1383 ****
gtk_widget_set_sensitive(GET_COMPONENT("viewHideLayer"), ui.layerno>=0);
gtk_widget_set_sensitive(GET_COMPONENT("editPaste"), ui.cur_layer!=NULL);
! gtk_widget_set_sensitive(GET_COMPONENT("buttonPaste"), ui.cur_layer!=NULL);
}
void update_toolbar_and_menu(void)
--- 1542,1549 ----
gtk_widget_set_sensitive(GET_COMPONENT("viewHideLayer"), ui.layerno>=0);
gtk_widget_set_sensitive(GET_COMPONENT("editPaste"), ui.cur_layer!=NULL);
!
! gtk_widget_set_sensitive(GET_COMPONENT("buttonPaste"), ui.cur_layer!=NULL);
}
void update_toolbar_and_menu(void)
***************
*** 1716,1722 ****
if (item->type == ITEM_STROKE)
for (pt=item->path->coords, i=0; i<item->path->num_points; i++, pt+=2)
{ pt[0] += dx; pt[1] += dy; }
! if (item->type == ITEM_STROKE || item->type == ITEM_TEXT || item->type == ITEM_TEMP_TEXT) {
item->bbox.left += dx;
item->bbox.right += dx;
item->bbox.top += dy;
--- 1882,1888 ----
if (item->type == ITEM_STROKE)
for (pt=item->path->coords, i=0; i<item->path->num_points; i++, pt+=2)
{ pt[0] += dx; pt[1] += dy; }
! if (item->type == ITEM_STROKE || item->type == ITEM_TEXT || item->type == ITEM_TEMP_TEXT || item->type==ITEM_IMAGE) {
item->bbox.left += dx;
item->bbox.right += dx;
item->bbox.top += dy;
***************
*** 1799,1809 ****
item->bbox.left = item->bbox.left*scaling_x + offset_x;
item->bbox.top = item->bbox.top*scaling_y + offset_y;
}
// redraw the item
if (item->canvas_item!=NULL) {
group = (GnomeCanvasGroup *) item->canvas_item->parent;
! gtk_object_destroy(GTK_OBJECT(item->canvas_item));
! make_canvas_item_one(group, item);
}
}
}
--- 1965,1995 ----
item->bbox.left = item->bbox.left*scaling_x + offset_x;
item->bbox.top = item->bbox.top*scaling_y + offset_y;
}
+ if (item->type == ITEM_IMAGE) {
+ item->bbox.left = item->bbox.left*scaling_x + offset_x;
+ item->bbox.right = item->bbox.right*scaling_x + offset_x;
+ item->bbox.top = item->bbox.top*scaling_y + offset_y;
+ item->bbox.bottom = item->bbox.bottom*scaling_y + offset_y;
+ if (item->bbox.left > item->bbox.right) {
+ temp = item->bbox.left;
+ item->bbox.left = item->bbox.right;
+ item->bbox.right = temp;
+ }
+ if (item->bbox.top > item->bbox.bottom) {
+ temp = item->bbox.top;
+ item->bbox.top = item->bbox.bottom;
+ item->bbox.bottom = temp;
+ }
+ }
// redraw the item
if (item->canvas_item!=NULL) {
group = (GnomeCanvasGroup *) item->canvas_item->parent;
! if (item->type == ITEM_IMAGE) {
! adjust_or_make_canvas_item_image(group, item);
! } else {
! gtk_object_destroy(GTK_OBJECT(item->canvas_item));
! make_canvas_item_one(group, item);
! }
}
}
}
diff -c 'xournal-0.4.5/src/xo-misc.h' 'xournal/src/xo-misc.h'
Index: ./src/xo-misc.h
*** ./src/xo-misc.h Mon Sep 28 16:45:56 2009
--- ./src/xo-misc.h Sun Jun 27 16:18:01 2010
***************
*** 2,7 ****
--- 2,8 ----
struct Page *new_page(struct Page *template);
struct Page *new_page_with_bg(struct Background *bg, double width, double height);
+ void set_current_page(gdouble *pt);
void realloc_cur_path(int n);
void realloc_cur_widths(int n);
void clear_redo_stack(void);
***************
*** 20,30 ****
--- 21,33 ----
// helper functions
void get_pointer_coords(GdkEvent *event, double *ret);
+ void get_current_pointer_coords(double *ret);
double get_pressure_multiplier(GdkEvent *event);
void fix_xinput_coords(GdkEvent *event);
void update_item_bbox(struct Item *item);
void make_page_clipbox(struct Page *pg);
void make_canvas_items(void);
+ void adjust_or_make_canvas_item_image(GnomeCanvasGroup *group, struct Item *item);
void make_canvas_item_one(GnomeCanvasGroup *group, struct Item *item);
void update_canvas_bg(struct Page *pg);
gboolean is_visible(struct Page *pg);
diff -c 'xournal-0.4.5/src/xo-paint.c' 'xournal/src/xo-paint.c'
Index: ./src/xo-paint.c
*** ./src/xo-paint.c Mon Sep 28 09:54:18 2009
--- ./src/xo-paint.c Thu Jul 29 16:01:42 2010
***************
*** 879,1089 ****
the forward direction */
}
- void callback_clipboard_get(GtkClipboard *clipboard,
- GtkSelectionData *selection_data,
- guint info, gpointer user_data)
- {
- int length;
-
- g_memmove(&length, user_data, sizeof(int));
- gtk_selection_data_set(selection_data,
- gdk_atom_intern("_XOURNAL", FALSE), 8, user_data, length);
- }
-
- void callback_clipboard_clear(GtkClipboard *clipboard, gpointer user_data)
- {
- g_free(user_data);
- }
-
- void selection_to_clip(void)
- {
- int bufsz, nitems, val;
- char *buf, *p;
- GList *list;
- struct Item *item;
- GtkTargetEntry target;
-
- if (ui.selection == NULL) return;
- bufsz = 2*sizeof(int) // bufsz, nitems
- + sizeof(struct BBox); // bbox
- nitems = 0;
- for (list = ui.selection->items; list != NULL; list = list->next) {
- item = (struct Item *)list->data;
- nitems++;
- if (item->type == ITEM_STROKE) {
- bufsz+= sizeof(int) // type
- + sizeof(struct Brush) // brush
- + sizeof(int) // num_points
- + 2*item->path->num_points*sizeof(double); // the points
- if (item->brush.variable_width)
- bufsz += (item->path->num_points-1)*sizeof(double); // the widths
- }
- else if (item->type == ITEM_TEXT) {
- bufsz+= sizeof(int) // type
- + sizeof(struct Brush) // brush
- + 2*sizeof(double) // bbox upper-left
- + sizeof(int) // text len
- + strlen(item->text)+1 // text
- + sizeof(int) // font_name len
- + strlen(item->font_name)+1 // font_name
- + sizeof(double); // font_size
- }
- else bufsz+= sizeof(int); // type
- }
- p = buf = g_malloc(bufsz);
- g_memmove(p, &bufsz, sizeof(int)); p+= sizeof(int);
- g_memmove(p, &nitems, sizeof(int)); p+= sizeof(int);
- g_memmove(p, &ui.selection->bbox, sizeof(struct BBox)); p+= sizeof(struct BBox);
- for (list = ui.selection->items; list != NULL; list = list->next) {
- item = (struct Item *)list->data;
- g_memmove(p, &item->type, sizeof(int)); p+= sizeof(int);
- if (item->type == ITEM_STROKE) {
- g_memmove(p, &item->brush, sizeof(struct Brush)); p+= sizeof(struct Brush);
- g_memmove(p, &item->path->num_points, sizeof(int)); p+= sizeof(int);
- g_memmove(p, item->path->coords, 2*item->path->num_points*sizeof(double));
- p+= 2*item->path->num_points*sizeof(double);
- if (item->brush.variable_width) {
- g_memmove(p, item->widths, (item->path->num_points-1)*sizeof(double));
- p+= (item->path->num_points-1)*sizeof(double);
- }
- }
- if (item->type == ITEM_TEXT) {
- g_memmove(p, &item->brush, sizeof(struct Brush)); p+= sizeof(struct Brush);
- g_memmove(p, &item->bbox.left, sizeof(double)); p+= sizeof(double);
- g_memmove(p, &item->bbox.top, sizeof(double)); p+= sizeof(double);
- val = strlen(item->text);
- g_memmove(p, &val, sizeof(int)); p+= sizeof(int);
- g_memmove(p, item->text, val+1); p+= val+1;
- val = strlen(item->font_name);
- g_memmove(p, &val, sizeof(int)); p+= sizeof(int);
- g_memmove(p, item->font_name, val+1); p+= val+1;
- g_memmove(p, &item->font_size, sizeof(double)); p+= sizeof(double);
- }
- }
-
- target.target = "_XOURNAL";
- target.flags = 0;
- target.info = 0;
-
- gtk_clipboard_set_with_data(gtk_clipboard_get(GDK_SELECTION_CLIPBOARD),
- &target, 1,
- callback_clipboard_get, callback_clipboard_clear, buf);
- }
-
-
- void clipboard_paste(void)
- {
- GtkSelectionData *sel_data;
- unsigned char *p;
- int nitems, npts, i, len;
- struct Item *item;
- double hoffset, voffset, cx, cy;
- double *pf;
- int sx, sy, wx, wy;
-
- if (ui.cur_layer == NULL) return;
-
- ui.cur_item_type = ITEM_PASTE;
- sel_data = gtk_clipboard_wait_for_contents(
- gtk_clipboard_get(GDK_SELECTION_CLIPBOARD),
- gdk_atom_intern("_XOURNAL", FALSE));
- ui.cur_item_type = ITEM_NONE;
- if (sel_data == NULL) return; // paste failed
-
- reset_selection();
-
- ui.selection = g_new(struct Selection, 1);
- p = sel_data->data + sizeof(int);
- g_memmove(&nitems, p, sizeof(int)); p+= sizeof(int);
- ui.selection->type = ITEM_SELECTRECT;
- ui.selection->layer = ui.cur_layer;
- g_memmove(&ui.selection->bbox, p, sizeof(struct BBox)); p+= sizeof(struct BBox);
- ui.selection->items = NULL;
-
- // find by how much we translate the pasted selection
- gnome_canvas_get_scroll_offsets(canvas, &sx, &sy);
- gdk_window_get_geometry(GTK_WIDGET(canvas)->window, NULL, NULL, &wx, &wy, NULL);
- gnome_canvas_window_to_world(canvas, sx + wx/2, sy + wy/2, &cx, &cy);
- cx -= ui.cur_page->hoffset;
- cy -= ui.cur_page->voffset;
- if (cx + (ui.selection->bbox.right-ui.selection->bbox.left)/2 > ui.cur_page->width)
- cx = ui.cur_page->width - (ui.selection->bbox.right-ui.selection->bbox.left)/2;
- if (cx - (ui.selection->bbox.right-ui.selection->bbox.left)/2 < 0)
- cx = (ui.selection->bbox.right-ui.selection->bbox.left)/2;
- if (cy + (ui.selection->bbox.bottom-ui.selection->bbox.top)/2 > ui.cur_page->height)
- cy = ui.cur_page->height - (ui.selection->bbox.bottom-ui.selection->bbox.top)/2;
- if (cy - (ui.selection->bbox.bottom-ui.selection->bbox.top)/2 < 0)
- cy = (ui.selection->bbox.bottom-ui.selection->bbox.top)/2;
- hoffset = cx - (ui.selection->bbox.right+ui.selection->bbox.left)/2;
- voffset = cy - (ui.selection->bbox.top+ui.selection->bbox.bottom)/2;
- ui.selection->bbox.left += hoffset;
- ui.selection->bbox.right += hoffset;
- ui.selection->bbox.top += voffset;
- ui.selection->bbox.bottom += voffset;
-
- ui.selection->canvas_item = gnome_canvas_item_new(ui.cur_layer->group,
- gnome_canvas_rect_get_type(), "width-pixels", 1,
- "outline-color-rgba", 0x000000ff,
- "fill-color-rgba", 0x80808040,
- "x1", ui.selection->bbox.left, "x2", ui.selection->bbox.right,
- "y1", ui.selection->bbox.top, "y2", ui.selection->bbox.bottom, NULL);
- make_dashed(ui.selection->canvas_item);
-
- while (nitems-- > 0) {
- item = g_new(struct Item, 1);
- ui.selection->items = g_list_append(ui.selection->items, item);
- ui.cur_layer->items = g_list_append(ui.cur_layer->items, item);
- ui.cur_layer->nitems++;
- g_memmove(&item->type, p, sizeof(int)); p+= sizeof(int);
- if (item->type == ITEM_STROKE) {
- g_memmove(&item->brush, p, sizeof(struct Brush)); p+= sizeof(struct Brush);
- g_memmove(&npts, p, sizeof(int)); p+= sizeof(int);
- item->path = gnome_canvas_points_new(npts);
- pf = (double *)p;
- for (i=0; i<npts; i++) {
- item->path->coords[2*i] = pf[2*i] + hoffset;
- item->path->coords[2*i+1] = pf[2*i+1] + voffset;
- }
- p+= 2*item->path->num_points*sizeof(double);
- if (item->brush.variable_width) {
- item->widths = g_memdup(p, (item->path->num_points-1)*sizeof(double));
- p+= (item->path->num_points-1)*sizeof(double);
- }
- else item->widths = NULL;
- update_item_bbox(item);
- make_canvas_item_one(ui.cur_layer->group, item);
- }
- if (item->type == ITEM_TEXT) {
- g_memmove(&item->brush, p, sizeof(struct Brush)); p+= sizeof(struct Brush);
- g_memmove(&item->bbox.left, p, sizeof(double)); p+= sizeof(double);
- g_memmove(&item->bbox.top, p, sizeof(double)); p+= sizeof(double);
- item->bbox.left += hoffset;
- item->bbox.top += voffset;
- g_memmove(&len, p, sizeof(int)); p+= sizeof(int);
- item->text = g_malloc(len+1);
- g_memmove(item->text, p, len+1); p+= len+1;
- g_memmove(&len, p, sizeof(int)); p+= sizeof(int);
- item->font_name = g_malloc(len+1);
- g_memmove(item->font_name, p, len+1); p+= len+1;
- g_memmove(&item->font_size, p, sizeof(double)); p+= sizeof(double);
- make_canvas_item_one(ui.cur_layer->group, item);
- }
- }
-
- prepare_new_undo();
- undo->type = ITEM_PASTE;
- undo->layer = ui.cur_layer;
- undo->itemlist = g_list_copy(ui.selection->items);
-
- gtk_selection_data_free(sel_data);
- update_copy_paste_enabled();
- update_color_menu();
- update_thickness_buttons();
- update_color_buttons();
- update_font_button();
- update_cursor(); // FIXME: can't know if pointer is within selection!
- }
-
// modify the color or thickness of pen strokes in a selection
void recolor_selection(int color_no, guint color_rgba)
--- 879,884 ----
diff -c 'xournal-0.4.5/src/xo-paint.h' 'xournal/src/xo-paint.h'
Index: ./src/xo-paint.h
*** ./src/xo-paint.h Thu Sep 17 16:49:04 2009
--- ./src/xo-paint.h Thu Apr 15 16:25:13 2010
***************
*** 22,29 ****
void finalize_resizesel(void);
void selection_delete(void);
- void selection_to_clip(void);
- void clipboard_paste(void);
void recolor_selection(int color_no, guint color_rgba);
void rethicken_selection(int val);
--- 22,27 ----
diff -c 'xournal-0.4.5/src/xo-print.c' 'xournal/src/xo-print.c'
Index: ./src/xo-print.c
*** ./src/xo-print.c Tue Sep 29 10:36:54 2009
--- ./src/xo-print.c Thu Jul 29 16:31:20 2010
***************
*** 772,777 ****
--- 772,851 ----
return xref->last;
}
+ gboolean pdf_draw_image(PdfImage *image, struct XrefTable *xref, GString *pdfbuf)
+ {
+ char *buf, *p1, *p2;
+ int height, width, stride, x, y, chan;
+ GString *zpix;
+
+ if (gdk_pixbuf_get_bits_per_sample(image->pixbuf) != 8 ||
+ gdk_pixbuf_get_colorspace(image->pixbuf) != GDK_COLORSPACE_RGB) {
+ return FALSE;
+ }
+
+ width = gdk_pixbuf_get_width(image->pixbuf);
+ height = gdk_pixbuf_get_height(image->pixbuf);
+ stride = gdk_pixbuf_get_rowstride(image->pixbuf);
+ chan = gdk_pixbuf_get_n_channels(image->pixbuf);
+ if (!((chan==3 && !image->has_alpha) || (chan==4 && image->has_alpha))) {
+ return FALSE;
+ }
+
+ p2 = buf = (char *)g_malloc(3*width*height);
+ for (y=0; y<height; y++) {
+ p1 = (char *)gdk_pixbuf_get_pixels(image->pixbuf)+stride*y;
+ for (x=0; x<width; x++) {
+ *(p2++)=*(p1++); *(p2++)=*(p1++); *(p2++)=*(p1++);
+ if (chan==4) p1++;
+ }
+ }
+ zpix = do_deflate(buf, 3*width*height);
+ g_free(buf);
+
+ xref->data[image->n_obj] = pdfbuf->len;
+ g_string_append_printf(pdfbuf,
+ "%d 0 obj\n<< /Length %d /Filter /FlateDecode /Type /Xobject "
+ "/Subtype /Image /Width %d /Height %d /ColorSpace /DeviceRGB "
+ "/BitsPerComponent 8 ",
+ image->n_obj, zpix->len, width, height);
+ if (image->has_alpha) {
+ g_string_append_printf(pdfbuf,
+ "/SMask %d 0 R ",
+ image->n_obj_smask);
+ }
+ g_string_append_printf(pdfbuf, " >> stream\n");
+
+ g_string_append_len(pdfbuf, zpix->str, zpix->len);
+ g_string_free(zpix, TRUE);
+ g_string_append(pdfbuf, "endstream\nendobj\n");
+
+ if (image->has_alpha) {
+ p2 = buf = (char *)g_malloc(width*height);
+ for (y=0; y<height; y++) {
+ p1 = (char *)gdk_pixbuf_get_pixels(image->pixbuf)+stride*y;
+ for (x=0; x<width; x++) {
+ p1+=3; /* skip the RGB */
+ *(p2++)=*(p1++); /* just copy the alpha */
+ }
+ }
+ zpix = do_deflate(buf, width*height);
+ g_free(buf);
+
+ xref->data[image->n_obj_smask] = pdfbuf->len;
+ g_string_append_printf(pdfbuf,
+ "%d 0 obj\n<< /Length %d /Filter /FlateDecode /Type /Xobject "
+ "/Subtype /Image /Width %d /Height %d /ColorSpace /DeviceGray "
+ "/BitsPerComponent 8 >> stream\n",
+ image->n_obj_smask, zpix->len, width, height);
+
+ g_string_append_len(pdfbuf, zpix->str, zpix->len);
+ g_string_free(zpix, TRUE);
+ g_string_append(pdfbuf, "endstream\nendobj\n");
+ }
+
+ return TRUE;
+ }
+
// manipulate Pdf fonts
struct PdfFont *new_pdffont(struct XrefTable *xref, GList **fonts,
***************
*** 1006,1015 ****
g_string_append(pdfbuf, ">> endobj\n");
}
// draw a page's graphics
void pdf_draw_page(struct Page *pg, GString *str, gboolean *use_hiliter,
! struct XrefTable *xref, GList **pdffonts)
{
GList *layerlist, *itemlist, *tmplist;
struct Layer *l;
--- 1080,1110 ----
g_string_append(pdfbuf, ">> endobj\n");
}
+ // Pdf images
+
+ struct PdfImage *new_pdfimage(struct XrefTable *xref, GList **images, GdkPixbuf *pixbuf)
+ {
+ GList *list;
+ struct PdfImage *image;
+
+ image = g_malloc(sizeof(struct PdfImage));
+ *images = g_list_append(*images, image);
+ image->n_obj = xref->last+1;
+ make_xref(xref, xref->last+1, 0); // will give it a value later
+ image->has_alpha = gdk_pixbuf_get_has_alpha(pixbuf);
+ if (image->has_alpha) {
+ image->n_obj_smask = xref->last+1;
+ make_xref(xref, xref->last+1, 0); // will give it a value later
+ }
+ image->pixbuf = pixbuf;
+
+ return image;
+ }
+
// draw a page's graphics
void pdf_draw_page(struct Page *pg, GString *str, gboolean *use_hiliter,
! struct XrefTable *xref, GList **pdffonts, GList **pdfimages)
{
GList *layerlist, *itemlist, *tmplist;
struct Layer *l;
***************
*** 1034,1039 ****
--- 1129,1135 ----
int font_id;
FT_Face ftface;
struct PdfFont *cur_font;
+ struct PdfImage *cur_image;
gboolean in_string;
old_rgba = old_text_rgba = 0x12345678; // not any values we use, so we'll reset them
***************
*** 1161,1166 ****
--- 1257,1272 ----
pango_layout_iter_free(iter);
g_object_unref(layout);
}
+ else if (item->type == ITEM_IMAGE) {
+ cur_image = new_pdfimage(xref, pdfimages, item->image);
+ g_string_append_printf(str, "\nq 1 0 0 1 %.2f %.2f cm %.2f 0 0 %.2f 0 %.2f cm /Im%d Do Q ",
+ item->bbox.left, // translation
+ item->bbox.top,
+ item->bbox.right - item->bbox.left, // scaling
+ item->bbox.top - item->bbox.bottom,
+ item->bbox.bottom - item->bbox.top,
+ cur_image->n_obj);
+ }
}
}
}
***************
*** 1187,1194 ****
gboolean use_hiliter;
struct PdfInfo pdfinfo;
struct PdfObj *obj;
! GList *pdffonts, *list;
struct PdfFont *font;
char *tmpbuf;
f = fopen(filename, "w");
--- 1293,1301 ----
gboolean use_hiliter;
struct PdfInfo pdfinfo;
struct PdfObj *obj;
! GList *pdffonts, *pdfimages, *list;
struct PdfFont *font;
+ struct PdfImage *image;
char *tmpbuf;
f = fopen(filename, "w");
***************
*** 1198,1203 ****
--- 1305,1311 ----
xref.data = NULL;
uses_pdf = FALSE;
pdffonts = NULL;
+ pdfimages = NULL;
for (pglist = journal.pages; pglist!=NULL; pglist = pglist->next) {
pg = (struct Page *)pglist->data;
if (pg->bg->type == BG_PDF) uses_pdf = TRUE;
***************
*** 1267,1273 ****
n_obj_bgpix = pdf_draw_bitmap_background(pg, pgstrm, &xref, pdfbuf);
// draw the page contents
use_hiliter = FALSE;
! pdf_draw_page(pg, pgstrm, &use_hiliter, &xref, &pdffonts);
g_string_append_printf(pgstrm, "Q\n");
// deflate pgstrm and write it
--- 1375,1381 ----
n_obj_bgpix = pdf_draw_bitmap_background(pg, pgstrm, &xref, pdfbuf);
// draw the page contents
use_hiliter = FALSE;
! pdf_draw_page(pg, pgstrm, &use_hiliter, &xref, &pdffonts, &pdfimages);
g_string_append_printf(pgstrm, "Q\n");
// deflate pgstrm and write it
***************
*** 1323,1329 ****
}
add_dict_subentry(pdfbuf, &xref,
obj, "/ProcSet", PDFTYPE_ARRAY, NULL, mk_pdfname("/PDF"));
! if (n_obj_bgpix>0)
add_dict_subentry(pdfbuf, &xref,
obj, "/ProcSet", PDFTYPE_ARRAY, NULL, mk_pdfname("/ImageC"));
if (use_hiliter)
--- 1431,1437 ----
}
add_dict_subentry(pdfbuf, &xref,
obj, "/ProcSet", PDFTYPE_ARRAY, NULL, mk_pdfname("/PDF"));
! if (n_obj_bgpix>0 || pdfimages!=NULL)
add_dict_subentry(pdfbuf, &xref,
obj, "/ProcSet", PDFTYPE_ARRAY, NULL, mk_pdfname("/ImageC"));
if (use_hiliter)
***************
*** 1343,1353 ****
g_free(tmpbuf);
}
}
show_pdfobj(obj, pdfbuf);
free_pdfobj(obj);
g_string_append(pdfbuf, " >> endobj\n");
}
!
// after the pages, we insert fonts
for (list = pdffonts; list!=NULL; list = list->next) {
font = (struct PdfFont *)list->data;
--- 1451,1468 ----
g_free(tmpbuf);
}
}
+ for (list=pdfimages; list!=NULL; list = list->next) {
+ image = (struct PdfImage *)list->data;
+ tmpbuf = g_strdup_printf("/Im%d", image->n_obj);
+ add_dict_subentry(pdfbuf, &xref,
+ obj, "/XObject", PDFTYPE_DICT, tmpbuf, mk_pdfref(image->n_obj));
+ g_free(tmpbuf);
+ }
show_pdfobj(obj, pdfbuf);
free_pdfobj(obj);
g_string_append(pdfbuf, " >> endobj\n");
}
!
// after the pages, we insert fonts
for (list = pdffonts; list!=NULL; list = list->next) {
font = (struct PdfFont *)list->data;
***************
*** 1357,1362 ****
--- 1472,1489 ----
g_free(font);
}
g_list_free(pdffonts);
+
+ // after the fonts, we insert images
+ if (pdfimages!=NULL) {
+ for (list = pdfimages; list!=NULL; list = list->next) {
+ image = (struct PdfImage *)list->data;
+ if (!pdf_draw_image(image, &xref, pdfbuf)) {
+ return FALSE;
+ }
+ g_free(image);
+ }
+ g_list_free(pdfimages);
+ }
// PDF trailer
startxref = pdfbuf->len;
***************
*** 1476,1481 ****
--- 1603,1609 ----
void print_job_render_page(GtkPrintOperation *print, GtkPrintContext *context, gint pageno, gpointer user_data)
{
cairo_t *cr;
+ cairo_t *tempcr;
gdouble width, height, scale;
struct Page *pg;
guint old_rgba;
***************
*** 1487,1492 ****
--- 1615,1621 ----
double *pt;
PangoFontDescription *font_desc;
PangoLayout *layout;
+ cairo_surface_t *surf;
pg = (struct Page *)g_list_nth_data(journal.pages, pageno);
cr = gtk_print_context_get_cairo_context(context);
***************
*** 1509,1515 ****
l = (struct Layer *)layerlist->data;
for (itemlist = l->items; itemlist!=NULL; itemlist = itemlist->next) {
item = (struct Item *)itemlist->data;
! if (item->type == ITEM_STROKE || item->type == ITEM_TEXT) {
if (item->brush.color_rgba != old_rgba)
cairo_set_source_rgba(cr, RGBA_RGB(item->brush.color_rgba),
RGBA_ALPHA(item->brush.color_rgba));
--- 1638,1644 ----
l = (struct Layer *)layerlist->data;
for (itemlist = l->items; itemlist!=NULL; itemlist = itemlist->next) {
item = (struct Item *)itemlist->data;
! if (item->type == ITEM_STROKE || item->type == ITEM_TEXT || item->type==ITEM_IMAGE) {
if (item->brush.color_rgba != old_rgba)
cairo_set_source_rgba(cr, RGBA_RGB(item->brush.color_rgba),
RGBA_ALPHA(item->brush.color_rgba));
***************
*** 1548,1553 ****
--- 1677,1694 ----
pango_cairo_show_layout(cr, layout);
g_object_unref(layout);
}
+ if (item->type == ITEM_IMAGE) {
+ double required_width = item->bbox.right - item->bbox.left;
+ double required_height = item->bbox.bottom - item->bbox.top;
+ double scalex = required_width / gdk_pixbuf_get_width(item->image);
+ double scaley = required_height / gdk_pixbuf_get_height(item->image);
+ cairo_scale(cr,scalex,scaley);
+ gdk_cairo_set_source_pixbuf(cr,item->image,item->bbox.left/scalex,item->bbox.top/scaley);
+ cairo_scale(cr,1/scalex,1/scaley);
+ cairo_paint (cr);
+ old_rgba = predef_colors_rgba[COLOR_BLACK]; //this is an ugly fix, I (victor) don't understand cairo enough
+ cairo_set_source_rgb(cr, 0, 0, 0);
+ }
}
}
}
diff -c 'xournal-0.4.5/src/xo-print.h' 'xournal/src/xo-print.h'
Index: ./src/xo-print.h
*** ./src/xo-print.h Tue Sep 15 09:26:26 2009
--- ./src/xo-print.h Fri May 28 20:43:50 2010
***************
*** 45,50 ****
--- 45,57 ----
int flags;
} PdfFont;
+ typedef struct PdfImage {
+ int n_obj;
+ gboolean has_alpha;
+ int n_obj_smask; /* only if has_alpha */
+ GdkPixbuf *pixbuf;
+ } PdfImage;
+
#define PDFTYPE_CST 0 // intval: true=1, false=0, null=-1
#define PDFTYPE_INT 1 // intval
#define PDFTYPE_REAL 2 // realval
diff -c 'xournal-0.4.5/src/xournal.h' 'xournal/src/xournal.h'
Index: ./src/xournal.h
*** ./src/xournal.h Sat Oct 3 12:42:28 2009
--- ./src/xournal.h Thu Jul 29 17:02:19 2010
***************
*** 17,22 ****
--- 17,24 ----
"tiny file dialog" syndrome, without hurting those with well-behaved
versions of GTK+. Comment out if you'd prefer not to include this fix. */
+ //#define IMAGE_DEBUG //this is for debugging of the "insert image" patch
+
// PREF FILES INFO
#define CONFIG_DIR ".xournal"
***************
*** 120,125 ****
--- 122,128 ----
#define TOOL_SELECTRECT 5
#define TOOL_VERTSPACE 6
#define TOOL_HAND 7
+ #define TOOL_IMAGE 8
#define NUM_STROKE_TOOLS 3
#define NUM_TOOLS 8
#define NUM_BUTTONS 3
***************
*** 150,155 ****
--- 153,163 ----
gchar *font_name;
gdouble font_size;
GtkWidget *widget; // the widget while text is being edited (ITEM_TEMP_TEXT)
+ // the following fields for ITEM_IMAGE:
+ GdkPixbuf* image; // original image for print and resizing quality
+ GdkPixbuf* image_scaled; // scaled pixbuf for display
+ gchar *image_png; // PNG of original image, for save and clipboard
+ gsize image_png_len;
} Item;
// item type values for Item.type, UndoItem.type, ui.cur_item_type ...
***************
*** 178,183 ****
--- 186,192 ----
#define ITEM_TEXT_ATTRIB 21
#define ITEM_RESIZESEL 22
#define ITEM_RECOGNIZER 23
+ #define ITEM_IMAGE 24
typedef struct Layer {
GList *items; // the items on the layer, from bottom to top
***************
*** 251,256 ****
--- 260,266 ----
gboolean hand_scrollto_pending;
char *filename;
gchar *default_path; // default path for new notes
+ gchar *default_image; // path for previous image
gboolean view_continuous, fullscreen, maximize_at_start;
gboolean in_update_page_stuff; // semaphore to avoid scrollbar retroaction
struct Selection *selection;
***************
*** 300,307 ****
typedef struct UndoItem {
int type;
! struct Item *item; // for ITEM_STROKE, ITEM_TEXT, ITEM_TEXT_EDIT, ITEM_TEXT_ATTRIB
! struct Layer *layer; // for ITEM_STROKE, ITEM_ERASURE, ITEM_PASTE, ITEM_NEW_LAYER, ITEM_DELETE_LAYER, ITEM_MOVESEL, ITEM_TEXT, ITEM_TEXT_EDIT, ITEM_RECOGNIZER
struct Layer *layer2; // for ITEM_DELETE_LAYER with val=-1, ITEM_MOVESEL
struct Page *page; // for ITEM_NEW_BG_ONE/RESIZE, ITEM_NEW_PAGE, ITEM_NEW_LAYER, ITEM_DELETE_LAYER, ITEM_DELETE_PAGE
GList *erasurelist; // for ITEM_ERASURE, ITEM_RECOGNIZER
--- 310,317 ----
typedef struct UndoItem {
int type;
! struct Item *item; // for ITEM_STROKE, ITEM_TEXT, ITEM_TEXT_EDIT, ITEM_TEXT_ATTRIB, ITEM_IMAGE
! struct Layer *layer; // for ITEM_STROKE, ITEM_ERASURE, ITEM_PASTE, ITEM_NEW_LAYER, ITEM_DELETE_LAYER, ITEM_MOVESEL, ITEM_TEXT, ITEM_TEXT_EDIT, ITEM_RECOGNIZER, ITEM_IMAGE
struct Layer *layer2; // for ITEM_DELETE_LAYER with val=-1, ITEM_MOVESEL
struct Page *page; // for ITEM_NEW_BG_ONE/RESIZE, ITEM_NEW_PAGE, ITEM_NEW_LAYER, ITEM_DELETE_LAYER, ITEM_DELETE_PAGE
GList *erasurelist; // for ITEM_ERASURE, ITEM_RECOGNIZER
#### End of Patch data ####
#### ApplyPatch data follows ####
# Data version : 1.0
# Date generated : Thu Jul 29 20:05:54 2010
# Generated by : makepatch 2.03
# Recurse directories : Yes
# Excluded files : (\A|/).*\~\Z
# (\A|/).*\.a\Z
# (\A|/).*\.bak\Z
# (\A|/).*\.BAK\Z
# (\A|/).*\.elc\Z
# (\A|/).*\.exe\Z
# (\A|/).*\.gz\Z
# (\A|/).*\.ln\Z
# (\A|/).*\.o\Z
# (\A|/).*\.obj\Z
# (\A|/).*\.olb\Z
# (\A|/).*\.old\Z
# (\A|/).*\.orig\Z
# (\A|/).*\.rej\Z
# (\A|/).*\.so\Z
# (\A|/).*\.Z\Z
# (\A|/)\.del\-.*\Z
# (\A|/)\.make\.state\Z
# (\A|/)\.nse_depinfo\Z
# (\A|/)core\Z
# (\A|/)tags\Z
# (\A|/)TAGS\Z
# c './README.image' 0 1271308604 0100644
# p './src/Makefile.am' 560 1271308944 0100644
# p './src/Makefile.in' 21256 1271309237 0100644
# p './src/TODO' 12113 1273816779 0100644
# p './src/main.c' 11751 1277612564 0100644
# p './src/xo-callbacks.c' 115621 1277368329 0100644
# p './src/xo-callbacks.h' 22740 1269211165 0100644
# c './src/xo-clipboard.c' 0 1280390203 0100644
# c './src/xo-clipboard.h' 0 1269482993 0100644
# p './src/xo-file.c' 72283 1280379587 0100644
# c './src/xo-image.c' 0 1280379292 0100644
# c './src/xo-image.h' 0 1277368922 0100644
# p './src/xo-interface.c' 154893 1269211165 0100644
# p './src/xo-misc.c' 75933 1280376684 0100644
# p './src/xo-misc.h' 4155 1277612281 0100644
# p './src/xo-paint.c' 51578 1280376102 0100644
# p './src/xo-paint.h' 1292 1271305513 0100644
# p './src/xo-print.c' 51697 1280377880 0100644
# p './src/xo-print.h' 1872 1275036230 0100644
# p './src/xournal.h' 12910 1280379739 0100644
#### End of ApplyPatch data ####
#### End of Patch kit [created: Thu Jul 29 20:05:54 2010] ####
#### Patch checksum: 3071 115300 31326 ####
#### Checksum: 3109 116607 9177 ####