NetSurf
gdk.c
Go to the documentation of this file.
1/*
2 * Copyright 2011 Vincent Sanders <vince@netsurf-browser.org>
3 *
4 * This file is part of NetSurf, http://www.netsurf-browser.org/
5 *
6 * NetSurf is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; version 2 of the License.
9 *
10 * NetSurf is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
17 */
18
19#include <string.h>
20
21#include "utils/log.h"
22
23#include "gtk/gdk.h"
24
25static void
26convert_alpha(guchar *dest_data,
27 int dest_stride,
28 guchar *src_data,
29 int src_stride,
30 int width,
31 int height)
32{
33 int x, y;
34
35 for (y = 0; y < height; y++) {
36 /* this cast is safe, the buffer is appropriately aligned */
37 guint32 *src = (void *) src_data;
38
39 for (x = 0; x < width; x++) {
40 guint alpha = src[x] >> 24;
41
42 if (alpha == 0) {
43 dest_data[x * 4 + 0] = 0;
44 dest_data[x * 4 + 1] = 0;
45 dest_data[x * 4 + 2] = 0;
46 } else {
47 dest_data[x * 4 + 0] = (((src[x] & 0xff0000) >> 16) * 255 + alpha / 2) / alpha;
48 dest_data[x * 4 + 1] = (((src[x] & 0x00ff00) >> 8) * 255 + alpha / 2) / alpha;
49 dest_data[x * 4 + 2] = (((src[x] & 0x0000ff) >> 0) * 255 + alpha / 2) / alpha;
50 }
51 dest_data[x * 4 + 3] = alpha;
52 }
53
54 src_data += src_stride;
55 dest_data += dest_stride;
56 }
57}
58
59
60GdkPixbuf *
61nsgdk_pixbuf_get_from_surface(cairo_surface_t *surface, int scwidth, int scheight)
62{
63 int width, height; /* source width and height */
64 cairo_surface_t *scsurface; /* scaled surface */
65 cairo_t *cr; /* cairo context for scaled surface */
66 GdkPixbuf *pixbuf; /* The result pixel buffer */
67
68 /* create pixmap */
69 pixbuf = gdk_pixbuf_new(GDK_COLORSPACE_RGB, true, 8, scwidth, scheight);
70 if (pixbuf == NULL) {
71 return NULL;
72 }
73
74 memset(gdk_pixbuf_get_pixels(pixbuf),
75 0xff,
76 gdk_pixbuf_get_rowstride(pixbuf) * (size_t)scheight);
77
78 /* scale cairo surface into new surface the target size */
79 cairo_surface_flush(surface); /* ensure source surface is ready */
80
81 /* get source surface dimensions */
82 width = cairo_image_surface_get_width(surface);
83 height = cairo_image_surface_get_height(surface);
84
85 /* scaled surface always has an alpha chanel for ease */
86 scsurface = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, scwidth, scheight);
87 if (cairo_surface_status(scsurface) != CAIRO_STATUS_SUCCESS) {
88 cairo_surface_destroy(scsurface);
89 g_object_unref(pixbuf);
90 NSLOG(netsurf, INFO, "Surface creation failed");
91 return NULL;
92 }
93
94 cr = cairo_create(scsurface);
95
96 /* Scale *before* setting the source surface */
97 cairo_scale(cr, (double)scwidth / width, (double)scheight / height);
98 cairo_set_source_surface(cr, surface, 0, 0);
99
100 /* To avoid getting the edge pixels blended with 0
101 * alpha, which would occur with the default
102 * EXTEND_NONE. Use EXTEND_PAD for 1.2 or newer
103 */
104 cairo_pattern_set_extend(cairo_get_source(cr), CAIRO_EXTEND_REFLECT);
105
106 /* Replace the destination with the source instead of overlaying */
107 cairo_set_operator(cr, CAIRO_OPERATOR_SOURCE);
108
109 /* Do the actual drawing */
110 cairo_paint(cr);
111
112 cairo_destroy(cr);
113
114 /* copy data from surface into pixmap */
115 convert_alpha(gdk_pixbuf_get_pixels(pixbuf),
116 gdk_pixbuf_get_rowstride(pixbuf),
117 cairo_image_surface_get_data(scsurface),
118 cairo_image_surface_get_stride(scsurface),
119 scwidth, scheight);
120
121 cairo_surface_destroy(scsurface);
122
123 return pixbuf;
124}
125
GdkPixbuf * nsgdk_pixbuf_get_from_surface(cairo_surface_t *surface, int scwidth, int scheight)
obtain a pixbuf of the specified size from a cairo surface.
Definition: gdk.c:61
static void convert_alpha(guchar *dest_data, int dest_stride, guchar *src_data, int src_stride, int width, int height)
Definition: gdk.c:26
GDK support functions for missing interfaces.
#define NSLOG(catname, level, logmsg, args...)
Definition: log.h:116
int width
Definition: gui.c:166
int height
Definition: gui.c:167
Interface to utility string handling.