~ubuntu-branches/ubuntu/saucy/goffice/saucy-proposed

« back to all changes in this revision

Viewing changes to .pc/pixbuf-fixes.patch/goffice/utils/go-pixbuf.c

  • Committer: Package Import Robot
  • Author(s): Dmitry Smirnov
  • Date: 2013-08-30 14:03:56 UTC
  • mfrom: (1.2.35)
  • Revision ID: package-import@ubuntu.com-20130830140356-a1e30nbdku8kg4q0
Tags: 0.10.6-1
* New upstream release [August 2013].
* Dropped backported "pixbuf-fixes.patch".

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/*
2
 
 * go-pixbuf.c
3
 
 *
4
 
 * Copyright (C) 2011 Jean Brefort (jean.brefort@normalesup.org)
5
 
 *
6
 
 * This program is free software; you can redistribute it and/or
7
 
 * modify it under the terms of the GNU General Public License as
8
 
 * published by the Free Software Foundation; either version 2 of the
9
 
 * License, or (at your option) version 3.
10
 
 *
11
 
 * This program is distributed in the hope that it will be useful,
12
 
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
 
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
 
 * GNU General Public License for more details.
15
 
 *
16
 
 * You should have received a copy of the GNU General Public License
17
 
 * along with this program; if not, write to the Free Software
18
 
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301
19
 
 * USA
20
 
 */
21
 
 
22
 
#include <goffice/goffice-config.h>
23
 
#include "go-pixbuf.h"
24
 
 
25
 
#include <goffice/goffice-priv.h>
26
 
#include <gsf/gsf-utils.h>
27
 
#include <gsf/gsf-impl-utils.h>
28
 
#include <glib/gi18n-lib.h>
29
 
 
30
 
/* GOPixbuf implementation */
31
 
 
32
 
struct _GOPixbuf {
33
 
        GOImage parent;
34
 
        unsigned rowstride;
35
 
        GdkPixbuf *pixbuf;
36
 
        cairo_surface_t *surface;
37
 
};
38
 
 
39
 
typedef GOImageClass GOPixbufClass;
40
 
 
41
 
static GObjectClass *parent_klass;
42
 
 
43
 
enum {
44
 
        PIXBUF_PROP_0,
45
 
        PIXBUF_PROP_PIXBUF
46
 
};
47
 
 
48
 
static void
49
 
pixbuf_to_cairo (GOPixbuf *pixbuf)
50
 
{
51
 
        unsigned char *src, *dst;
52
 
        GOImage *image = GO_IMAGE (pixbuf);
53
 
 
54
 
        g_return_if_fail (GO_IS_PIXBUF (pixbuf) && image->data && pixbuf->pixbuf);
55
 
 
56
 
        src = gdk_pixbuf_get_pixels (pixbuf->pixbuf);
57
 
        dst = image->data;
58
 
 
59
 
        g_return_if_fail (gdk_pixbuf_get_rowstride (pixbuf->pixbuf) == (int) pixbuf->rowstride);
60
 
 
61
 
        go_cairo_convert_data_from_pixbuf (dst, src, image->width, image->height, pixbuf->rowstride);
62
 
}
63
 
 
64
 
static void
65
 
cairo_to_pixbuf (GOPixbuf *pixbuf)
66
 
{
67
 
        unsigned char *src, *dst;
68
 
        GOImage *image = GO_IMAGE (pixbuf);
69
 
 
70
 
        g_return_if_fail (GO_IS_PIXBUF (pixbuf) && image->data && pixbuf->pixbuf);
71
 
 
72
 
        dst = gdk_pixbuf_get_pixels (pixbuf->pixbuf);
73
 
        src = image->data;
74
 
 
75
 
        g_return_if_fail (gdk_pixbuf_get_rowstride (pixbuf->pixbuf) == (int) pixbuf->rowstride);
76
 
 
77
 
        go_cairo_convert_data_to_pixbuf (dst, src, image->width, image->height, pixbuf->rowstride);
78
 
}
79
 
 
80
 
static void
81
 
go_pixbuf_save (GOImage *image, GsfXMLOut *output)
82
 
{
83
 
        GOPixbuf *pixbuf;
84
 
        g_return_if_fail (GO_IS_PIXBUF (image));
85
 
        pixbuf = GO_PIXBUF (image);
86
 
        gsf_xml_out_add_int (output, "rowstride", pixbuf->rowstride);
87
 
        if (!image->data) {
88
 
                image->data = g_new0 (guint8, image->height * pixbuf->rowstride);
89
 
                g_return_if_fail (image->data !=NULL);
90
 
                pixbuf_to_cairo (pixbuf);
91
 
        }
92
 
        gsf_xml_out_add_base64
93
 
                (output, NULL,
94
 
                 image->data, image->height * pixbuf->rowstride);
95
 
}
96
 
 
97
 
static void
98
 
go_pixbuf_load_attr (GOImage *image, xmlChar const *attr_name, xmlChar const *attr_value)
99
 
{
100
 
        GOPixbuf *pixbuf = GO_PIXBUF (image);
101
 
        g_return_if_fail (pixbuf);
102
 
        if (!strcmp (attr_name, "rowstride"))
103
 
                pixbuf->rowstride = strtol (attr_value, NULL, 10);
104
 
}
105
 
 
106
 
static void
107
 
go_pixbuf_load_data (GOImage *image, GsfXMLIn *xin)
108
 
{
109
 
        size_t length, expected;
110
 
        length = gsf_base64_decode_simple (xin->content->str, strlen(xin->content->str));
111
 
        expected = image->height * go_pixbuf_get_rowstride (GO_PIXBUF (image));
112
 
        if (expected != length)
113
 
                g_critical ("Invalid image size, expected %lu bytes, got %lu", expected, length);
114
 
        image->data = g_malloc (expected);
115
 
        g_return_if_fail (image->data !=NULL);
116
 
        memcpy (image->data, xin->content->str, (length < expected)? length: expected);
117
 
        if (length < expected) /* fill with 0 */
118
 
                memset (image->data + length, 0, expected - length);
119
 
}
120
 
 
121
 
static void
122
 
go_pixbuf_draw (GOImage *image, cairo_t *cr)
123
 
{
124
 
        GOPixbuf *pixbuf = GO_PIXBUF (image);
125
 
        g_return_if_fail (pixbuf);
126
 
        if (pixbuf->surface == NULL) {
127
 
                if (image->data == NULL) {
128
 
                        /* image built from a pixbuf */
129
 
                        image->data = g_new0 (guint8, image->height * pixbuf->rowstride);
130
 
                        g_return_if_fail (image->data !=NULL);
131
 
                        pixbuf_to_cairo (pixbuf);
132
 
                }
133
 
                pixbuf->surface = cairo_image_surface_create_for_data (image->data,
134
 
                                                                       CAIRO_FORMAT_ARGB32,
135
 
                                                                       image->width,
136
 
                                                                       image->height,
137
 
                                                                       pixbuf->rowstride);
138
 
        }
139
 
        cairo_save (cr);
140
 
        cairo_set_source_surface (cr, pixbuf->surface, 0., 0.);
141
 
        cairo_rectangle (cr, 0., 0., image->width, image->height);
142
 
        cairo_fill (cr);
143
 
        cairo_restore (cr);
144
 
}
145
 
 
146
 
static GdkPixbuf *
147
 
go_pixbuf_get_pixbuf (GOImage *image)
148
 
{
149
 
        GOPixbuf *pixbuf = GO_PIXBUF (image);
150
 
        g_return_val_if_fail (pixbuf, NULL);
151
 
        if (!pixbuf->pixbuf) {
152
 
                if (image->width == 0 || image->height == 0 || image->data == NULL)
153
 
                        return NULL;
154
 
                pixbuf->pixbuf = gdk_pixbuf_new (GDK_COLORSPACE_RGB, TRUE, 8,
155
 
                                                                image->width, image->height);
156
 
                cairo_to_pixbuf (pixbuf);
157
 
        }
158
 
        return g_object_ref (pixbuf->pixbuf);
159
 
}
160
 
 
161
 
static GdkPixbuf *
162
 
go_pixbuf_get_scaled_pixbuf (GOImage *image, int width, int height)
163
 
{
164
 
        GOPixbuf *pixbuf = GO_PIXBUF (image);
165
 
        g_return_val_if_fail (pixbuf, NULL);
166
 
        if (!pixbuf->pixbuf) {
167
 
                if (image->width == 0 || image->height == 0 || image->data == NULL)
168
 
                        return NULL;
169
 
                pixbuf->pixbuf = gdk_pixbuf_new (GDK_COLORSPACE_RGB, TRUE, 8,
170
 
                                                                image->width, image->height);
171
 
                cairo_to_pixbuf (pixbuf);
172
 
        }
173
 
        return gdk_pixbuf_scale_simple (pixbuf->pixbuf, width, height, GDK_INTERP_HYPER);
174
 
}
175
 
 
176
 
static gboolean
177
 
go_pixbuf_differ (GOImage *first, GOImage *second)
178
 
{
179
 
        void *pixels1, *pixels2;
180
 
        int size;
181
 
        GOPixbuf *pfirst = GO_PIXBUF (first), *psecond = GO_PIXBUF (second);
182
 
        if (!pfirst->pixbuf)
183
 
                go_pixbuf_get_pixbuf (first);
184
 
        if (!psecond->pixbuf)
185
 
                go_pixbuf_get_pixbuf (second);
186
 
        if (!pfirst->pixbuf || !psecond->pixbuf)
187
 
                return TRUE; /* this should not happen */
188
 
        if (gdk_pixbuf_get_n_channels (pfirst->pixbuf) != gdk_pixbuf_get_n_channels (psecond->pixbuf))
189
 
                return TRUE;
190
 
        if (gdk_pixbuf_get_colorspace (pfirst->pixbuf) != gdk_pixbuf_get_colorspace (psecond->pixbuf))
191
 
                return TRUE;
192
 
        if (gdk_pixbuf_get_bits_per_sample (pfirst->pixbuf) != gdk_pixbuf_get_bits_per_sample (psecond->pixbuf))
193
 
                return TRUE;
194
 
        if (gdk_pixbuf_get_has_alpha (pfirst->pixbuf) != gdk_pixbuf_get_has_alpha (psecond->pixbuf))
195
 
                return TRUE;
196
 
        if (gdk_pixbuf_get_width (pfirst->pixbuf) != gdk_pixbuf_get_width (psecond->pixbuf))
197
 
                return TRUE;
198
 
        if (gdk_pixbuf_get_height (pfirst->pixbuf) != gdk_pixbuf_get_height (psecond->pixbuf))
199
 
                return TRUE;
200
 
        if (gdk_pixbuf_get_rowstride (pfirst->pixbuf) != gdk_pixbuf_get_rowstride (psecond->pixbuf))
201
 
                return TRUE;
202
 
        pixels1 = gdk_pixbuf_get_pixels (pfirst->pixbuf);
203
 
        pixels2 = gdk_pixbuf_get_pixels (psecond->pixbuf);
204
 
        size = gdk_pixbuf_get_rowstride (pfirst->pixbuf) * gdk_pixbuf_get_height (pfirst->pixbuf);
205
 
        return memcmp (pixels1, pixels2, size);
206
 
}
207
 
 
208
 
static void
209
 
go_pixbuf_set_property (GObject *obj, guint param_id,
210
 
                       GValue const *value, GParamSpec *pspec)
211
 
{
212
 
        GOPixbuf *pixbuf = GO_PIXBUF (obj);
213
 
        GOImage *image = GO_IMAGE (obj);
214
 
 
215
 
        switch (param_id) {
216
 
        case PIXBUF_PROP_PIXBUF: {
217
 
                GdkPixbuf *pix = GDK_PIXBUF (g_value_get_object (value));
218
 
                if (!GDK_IS_PIXBUF (pix))
219
 
                        break;
220
 
                if (!gdk_pixbuf_get_has_alpha (pix))
221
 
                        pix = gdk_pixbuf_add_alpha (pix, FALSE, 0, 0, 0);
222
 
                else
223
 
                        g_object_ref (pix);
224
 
                if (pixbuf->pixbuf)
225
 
                        g_object_unref (pixbuf->pixbuf);
226
 
                pixbuf->pixbuf = pix;
227
 
                g_free (image->data); /* this should be in GOPixbuf */
228
 
                image->data = NULL; /* this should be in GOPixbuf */
229
 
                _go_image_changed (image, gdk_pixbuf_get_width (pix), gdk_pixbuf_get_height (pix));
230
 
                pixbuf->rowstride = gdk_pixbuf_get_rowstride (pix); /* this should be in GOPixbuf */
231
 
        }
232
 
                break;
233
 
 
234
 
        default: G_OBJECT_WARN_INVALID_PROPERTY_ID (obj, param_id, pspec);
235
 
                return; /* NOTE : RETURN */
236
 
        }
237
 
}
238
 
 
239
 
static void
240
 
go_pixbuf_get_property (GObject *obj, guint param_id,
241
 
                       GValue *value, GParamSpec *pspec)
242
 
{
243
 
        GOPixbuf *pixbuf = GO_PIXBUF (obj);
244
 
 
245
 
        switch (param_id) {
246
 
        case PIXBUF_PROP_PIXBUF:
247
 
                g_value_set_object (value, pixbuf->pixbuf);
248
 
                break;
249
 
 
250
 
        default: G_OBJECT_WARN_INVALID_PROPERTY_ID (obj, param_id, pspec);
251
 
                return; /* NOTE : RETURN */
252
 
        }
253
 
}
254
 
 
255
 
static void
256
 
go_pixbuf_finalize (GObject *obj)
257
 
{
258
 
        GOPixbuf *pixbuf = GO_PIXBUF (obj);
259
 
        if (pixbuf->pixbuf)
260
 
                g_object_unref (pixbuf->pixbuf);
261
 
        if (pixbuf->surface)
262
 
                cairo_surface_destroy (pixbuf->surface);
263
 
        (parent_klass->finalize) (obj);
264
 
}
265
 
 
266
 
static void
267
 
go_pixbuf_class_init (GObjectClass *klass)
268
 
{
269
 
        GOImageClass *image_klass = (GOImageClass *) klass;
270
 
 
271
 
        klass->finalize = go_pixbuf_finalize;
272
 
        klass->set_property = go_pixbuf_set_property;
273
 
        klass->get_property = go_pixbuf_get_property;
274
 
        parent_klass = g_type_class_peek_parent (klass);
275
 
 
276
 
        image_klass->save = go_pixbuf_save;
277
 
        image_klass->load_attr = go_pixbuf_load_attr;
278
 
        image_klass->load_data = go_pixbuf_load_data;
279
 
        image_klass->get_pixbuf = go_pixbuf_get_pixbuf;
280
 
        image_klass->get_scaled_pixbuf = go_pixbuf_get_scaled_pixbuf;
281
 
        image_klass->draw = go_pixbuf_draw;
282
 
        image_klass->differ = go_pixbuf_differ;
283
 
 
284
 
        g_object_class_install_property (klass, PIXBUF_PROP_PIXBUF,
285
 
                                         g_param_spec_object ("pixbuf", _("Pixbuf"),
286
 
                                                              _("GdkPixbuf object from which the GOPixbuf is built"),
287
 
                                                              GDK_TYPE_PIXBUF, G_PARAM_READWRITE));
288
 
}
289
 
 
290
 
GSF_CLASS (GOPixbuf, go_pixbuf,
291
 
           go_pixbuf_class_init, NULL,
292
 
           GO_TYPE_IMAGE)
293
 
 
294
 
 
295
 
GOImage *
296
 
go_pixbuf_new_from_pixbuf (GdkPixbuf *pixbuf)
297
 
{
298
 
        return g_object_new (GO_TYPE_PIXBUF, "pixbuf", pixbuf, NULL);
299
 
}
300
 
 
301
 
int
302
 
go_pixbuf_get_rowstride (GOPixbuf *pixbuf)
303
 
{
304
 
        g_return_val_if_fail (GO_IS_PIXBUF (pixbuf), 0);
305
 
        return pixbuf->rowstride;
306
 
}