]> git.donarmstrong.com Git - xournal.git/blob - src/xo-image.c
Image patch
[xournal.git] / src / xo-image.c
1 /*
2  *  This program is free software; you can redistribute it and/or
3  *  modify it under the terms of the GNU General Public
4  *  License as published by the Free Software Foundation; either
5  *  version 2 of the License, or (at your option) any later version.
6  *
7  *  This software is distributed in the hope that it will be useful,
8  *  but WITHOUT ANY WARRANTY; without even the implied warranty of  
9  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
10  *  General Public License for more details.
11  *
12  *  You should have received a copy of the GNU General Public License
13  *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
14  */
15
16 #ifdef HAVE_CONFIG_H
17 #  include <config.h>
18 #endif
19
20 #include <math.h>
21 #include <string.h>
22 #include <gtk/gtk.h>
23 #include <gio/gio.h>
24
25 #include "xournal.h"
26 #include "xo-support.h"
27 #include "xo-image.h"
28
29 // create pixbuf from buffer, or return NULL on failure
30 GdkPixbuf *pixbuf_from_buffer(const gchar *buf, gsize buflen)
31 {
32   GInputStream *istream;
33   GdkPixbuf *pixbuf;
34   GError *error;
35
36   error = NULL;
37
38   istream = g_memory_input_stream_new_from_data (buf, buflen, NULL);
39   pixbuf = gdk_pixbuf_new_from_stream(istream, NULL, &error); 
40   g_input_stream_close(istream, NULL, &error);
41   return pixbuf;
42 }
43
44 void create_image_from_pixbuf(GdkPixbuf *pixbuf, double *pt)
45 {
46   double scale;
47   struct Item *item;
48
49   item = g_new(struct Item, 1);
50   item->type = ITEM_IMAGE;
51   item->canvas_item = NULL;
52   item->bbox.left = pt[0];
53   item->bbox.top = pt[1];
54   item->image = pixbuf;
55   item->image_png = NULL;
56   item->image_png_len = 0;
57
58   // Scale at native size, unless that won't fit, in which case we shrink it down.
59   scale = 1 / ui.zoom;
60   if ((scale * gdk_pixbuf_get_width(item->image)) > ui.cur_page->width - item->bbox.left)
61     scale = (ui.cur_page->width - item->bbox.left) / gdk_pixbuf_get_width(item->image);
62   if ((scale * gdk_pixbuf_get_height(item->image)) > ui.cur_page->height - item->bbox.top)
63     scale = (ui.cur_page->height - item->bbox.top) / gdk_pixbuf_get_height(item->image);
64
65   item->bbox.right = item->bbox.left + scale * gdk_pixbuf_get_width(item->image);
66   item->bbox.bottom = item->bbox.top + scale * gdk_pixbuf_get_height(item->image);
67   ui.cur_layer->items = g_list_append(ui.cur_layer->items, item);
68   ui.cur_layer->nitems++;
69   
70   make_canvas_item_one(ui.cur_layer->group, item);
71
72   // add undo information
73   prepare_new_undo();
74   undo->type = ITEM_IMAGE;
75   undo->item = item;
76   undo->layer = ui.cur_layer;
77   ui.cur_item = NULL;
78   ui.cur_item_type = ITEM_NONE;
79
80   // select image
81   reset_selection();
82   ui.selection = g_new0(struct Selection, 1);
83   ui.selection->type = ITEM_SELECTRECT;
84   ui.selection->layer = ui.cur_layer;
85   ui.selection->bbox = item->bbox;
86   ui.selection->items = g_list_append(ui.selection->items, item);
87   ui.selection->canvas_item = gnome_canvas_item_new(ui.cur_layer->group,
88       gnome_canvas_rect_get_type(), "width-pixels", 1,
89       "outline-color-rgba", 0x000000ff,
90       "fill-color-rgba", 0x80808040,
91       "x1", ui.selection->bbox.left, "x2", ui.selection->bbox.right, 
92       "y1", ui.selection->bbox.top, "y2", ui.selection->bbox.bottom, NULL);
93   make_dashed(ui.selection->canvas_item);
94   update_copy_paste_enabled();
95 }
96
97 void insert_image(GdkEvent *event)
98 {
99   GtkTextBuffer *buffer;
100   GnomeCanvasItem *canvas_item;
101   GdkColor color;
102   GtkWidget *dialog;
103   GtkFileFilter *filt_all;
104   GtkFileFilter *filt_gdkimage;
105   char *filename;
106   GdkPixbuf *pixbuf;
107   double scale=1;
108   double pt[2];
109   
110   dialog = gtk_file_chooser_dialog_new(_("Insert Image"), GTK_WINDOW (winMain),
111      GTK_FILE_CHOOSER_ACTION_OPEN, GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
112      GTK_STOCK_OPEN, GTK_RESPONSE_OK, NULL);
113 #ifdef FILE_DIALOG_SIZE_BUGFIX
114   gtk_window_set_default_size(GTK_WINDOW(dialog), 500, 400);
115 #endif
116      
117   filt_all = gtk_file_filter_new();
118   gtk_file_filter_set_name(filt_all, _("All files"));
119   gtk_file_filter_add_pattern(filt_all, "*");
120   filt_gdkimage = gtk_file_filter_new();
121   gtk_file_filter_set_name(filt_gdkimage, _("Image files"));
122   gtk_file_filter_add_pixbuf_formats(filt_gdkimage);
123   gtk_file_chooser_add_filter(GTK_FILE_CHOOSER (dialog), filt_gdkimage);
124   gtk_file_chooser_add_filter(GTK_FILE_CHOOSER (dialog), filt_all);
125
126   if (ui.default_image != NULL) gtk_file_chooser_set_filename(GTK_FILE_CHOOSER (dialog), ui.default_image);
127
128   if (gtk_dialog_run(GTK_DIALOG(dialog)) != GTK_RESPONSE_OK) {
129     gtk_widget_destroy(dialog);
130     return;
131   }
132   filename = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER (dialog));
133   gtk_widget_destroy(dialog);
134
135   if (filename == NULL) return; /* nothing selected */
136
137   if (ui.default_image != NULL) g_free(ui.default_image);
138   ui.default_image = g_strdup(filename);
139   
140   set_cursor_busy(TRUE);
141   pixbuf=gdk_pixbuf_new_from_file(filename, NULL);
142   set_cursor_busy(FALSE);
143   
144   if(pixbuf==NULL) { /* open failed */
145     dialog = gtk_message_dialog_new(GTK_WINDOW (winMain), GTK_DIALOG_MODAL,
146       GTK_MESSAGE_ERROR, GTK_BUTTONS_OK, _("Error opening image '%s'"), filename);
147     gtk_dialog_run(GTK_DIALOG(dialog));
148     gtk_widget_destroy(dialog);
149     g_free(filename);
150     ui.cur_item = NULL;
151     ui.cur_item_type = ITEM_NONE;
152     return;
153   }
154
155   ui.cur_item_type = ITEM_IMAGE;
156
157   get_pointer_coords(event, pt);
158   set_current_page(pt);  
159
160   create_image_from_pixbuf(pixbuf, pt);
161 }
162
163 void rescale_images(void)
164 {
165   // nothing needed in this implementation
166 }
167