diff options
Diffstat (limited to 'common/cairo.c')
-rw-r--r-- | common/cairo.c | 99 |
1 files changed, 0 insertions, 99 deletions
diff --git a/common/cairo.c b/common/cairo.c index f2ad54c1..403dcf49 100644 --- a/common/cairo.c +++ b/common/cairo.c | |||
@@ -1,9 +1,6 @@ | |||
1 | #include <stdint.h> | 1 | #include <stdint.h> |
2 | #include <cairo/cairo.h> | 2 | #include <cairo/cairo.h> |
3 | #include "cairo.h" | 3 | #include "cairo.h" |
4 | #if HAVE_GDK_PIXBUF | ||
5 | #include <gdk-pixbuf/gdk-pixbuf.h> | ||
6 | #endif | ||
7 | 4 | ||
8 | void cairo_set_source_u32(cairo_t *cairo, uint32_t color) { | 5 | void cairo_set_source_u32(cairo_t *cairo, uint32_t color) { |
9 | cairo_set_source_rgba(cairo, | 6 | cairo_set_source_rgba(cairo, |
@@ -45,99 +42,3 @@ cairo_surface_t *cairo_image_surface_scale(cairo_surface_t *image, | |||
45 | cairo_destroy(cairo); | 42 | cairo_destroy(cairo); |
46 | return new; | 43 | return new; |
47 | } | 44 | } |
48 | |||
49 | #if HAVE_GDK_PIXBUF | ||
50 | cairo_surface_t* gdk_cairo_image_surface_create_from_pixbuf(const GdkPixbuf *gdkbuf) { | ||
51 | int chan = gdk_pixbuf_get_n_channels(gdkbuf); | ||
52 | if (chan < 3) { | ||
53 | return NULL; | ||
54 | } | ||
55 | |||
56 | const guint8* gdkpix = gdk_pixbuf_read_pixels(gdkbuf); | ||
57 | if (!gdkpix) { | ||
58 | return NULL; | ||
59 | } | ||
60 | gint w = gdk_pixbuf_get_width(gdkbuf); | ||
61 | gint h = gdk_pixbuf_get_height(gdkbuf); | ||
62 | int stride = gdk_pixbuf_get_rowstride(gdkbuf); | ||
63 | |||
64 | cairo_format_t fmt = (chan == 3) ? CAIRO_FORMAT_RGB24 : CAIRO_FORMAT_ARGB32; | ||
65 | cairo_surface_t * cs = cairo_image_surface_create (fmt, w, h); | ||
66 | cairo_surface_flush (cs); | ||
67 | if ( !cs || cairo_surface_status(cs) != CAIRO_STATUS_SUCCESS) { | ||
68 | return NULL; | ||
69 | } | ||
70 | |||
71 | int cstride = cairo_image_surface_get_stride(cs); | ||
72 | unsigned char * cpix = cairo_image_surface_get_data(cs); | ||
73 | |||
74 | if (chan == 3) { | ||
75 | int i; | ||
76 | for (i = h; i; --i) { | ||
77 | const guint8 *gp = gdkpix; | ||
78 | unsigned char *cp = cpix; | ||
79 | const guint8* end = gp + 3*w; | ||
80 | while (gp < end) { | ||
81 | #if G_BYTE_ORDER == G_LITTLE_ENDIAN | ||
82 | cp[0] = gp[2]; | ||
83 | cp[1] = gp[1]; | ||
84 | cp[2] = gp[0]; | ||
85 | #else | ||
86 | cp[1] = gp[0]; | ||
87 | cp[2] = gp[1]; | ||
88 | cp[3] = gp[2]; | ||
89 | #endif | ||
90 | gp += 3; | ||
91 | cp += 4; | ||
92 | } | ||
93 | gdkpix += stride; | ||
94 | cpix += cstride; | ||
95 | } | ||
96 | } else { | ||
97 | /* premul-color = alpha/255 * color/255 * 255 = (alpha*color)/255 | ||
98 | * (z/255) = z/256 * 256/255 = z/256 (1 + 1/255) | ||
99 | * = z/256 + (z/256)/255 = (z + z/255)/256 | ||
100 | * # recurse once | ||
101 | * = (z + (z + z/255)/256)/256 | ||
102 | * = (z + z/256 + z/256/255) / 256 | ||
103 | * # only use 16bit uint operations, loose some precision, | ||
104 | * # result is floored. | ||
105 | * -> (z + z>>8)>>8 | ||
106 | * # add 0x80/255 = 0.5 to convert floor to round | ||
107 | * => (z+0x80 + (z+0x80)>>8 ) >> 8 | ||
108 | * ------ | ||
109 | * tested as equal to lround(z/255.0) for uint z in [0..0xfe02] | ||
110 | */ | ||
111 | #define PREMUL_ALPHA(x,a,b,z) \ | ||
112 | G_STMT_START { z = a * b + 0x80; x = (z + (z >> 8)) >> 8; } \ | ||
113 | G_STMT_END | ||
114 | int i; | ||
115 | for (i = h; i; --i) { | ||
116 | const guint8 *gp = gdkpix; | ||
117 | unsigned char *cp = cpix; | ||
118 | const guint8* end = gp + 4*w; | ||
119 | guint z1, z2, z3; | ||
120 | while (gp < end) { | ||
121 | #if G_BYTE_ORDER == G_LITTLE_ENDIAN | ||
122 | PREMUL_ALPHA(cp[0], gp[2], gp[3], z1); | ||
123 | PREMUL_ALPHA(cp[1], gp[1], gp[3], z2); | ||
124 | PREMUL_ALPHA(cp[2], gp[0], gp[3], z3); | ||
125 | cp[3] = gp[3]; | ||
126 | #else | ||
127 | PREMUL_ALPHA(cp[1], gp[0], gp[3], z1); | ||
128 | PREMUL_ALPHA(cp[2], gp[1], gp[3], z2); | ||
129 | PREMUL_ALPHA(cp[3], gp[2], gp[3], z3); | ||
130 | cp[0] = gp[3]; | ||
131 | #endif | ||
132 | gp += 4; | ||
133 | cp += 4; | ||
134 | } | ||
135 | gdkpix += stride; | ||
136 | cpix += cstride; | ||
137 | } | ||
138 | #undef PREMUL_ALPHA | ||
139 | } | ||
140 | cairo_surface_mark_dirty(cs); | ||
141 | return cs; | ||
142 | } | ||
143 | #endif // HAVE_GDK_PIXBUF | ||