1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
|
/**
* @file
* Cairo integration helpers.
*//*
* Authors:
* Krzysztof Kosiński <tweenk.pl@gmail.com>
*
* Copyright (C) 2010 Authors
* Released under GNU GPL, read the file 'COPYING' for more information
*/
#ifndef SEEN_INKSCAPE_DISPLAY_CAIRO_UTILS_H
#define SEEN_INKSCAPE_DISPLAY_CAIRO_UTILS_H
#include <glib.h>
#include <cairomm/cairomm.h>
#include <2geom/forward.h>
struct SPColor;
struct _GdkPixbuf;
typedef struct _GdkPixbuf GdkPixbuf;
namespace Inkscape {
/**
* RAII idiom for Cairo groups.
* Groups are temporary surfaces used when rendering e.g. masks and opacity.
* Use this class to ensure that each group push is matched with a pop.
*/
class CairoGroup {
public:
CairoGroup(cairo_t *_ct);
~CairoGroup();
void push();
void push_with_content(cairo_content_t content);
cairo_pattern_t *pop();
Cairo::RefPtr<Cairo::Pattern> popmm();
void pop_to_source();
private:
cairo_t *ct;
bool pushed;
};
/** RAII idiom for Cairo state saving. */
class CairoSave {
public:
CairoSave(cairo_t *_ct, bool save=false)
: ct(_ct)
, saved(save)
{
if (save) {
cairo_save(ct);
}
}
void save() {
if (!saved) {
cairo_save(ct);
saved = true;
}
}
~CairoSave() {
if (saved)
cairo_restore(ct);
}
private:
cairo_t *ct;
bool saved;
};
/** Cairo context with Inkscape-specific operations. */
class CairoContext : public Cairo::Context {
public:
CairoContext(cairo_t *obj, bool ref = false);
void transform(Geom::Affine const &m);
void set_source_rgba32(guint32 color);
void append_path(Geom::PathVector const &pv);
static Cairo::RefPtr<CairoContext> create(Cairo::RefPtr<Cairo::Surface> const &target);
};
} // namespace Inkscape
void ink_cairo_set_source_color(cairo_t *ct, SPColor const &color, double opacity);
void ink_cairo_set_source_rgba32(cairo_t *ct, guint32 rgba);
void ink_cairo_transform(cairo_t *ct, Geom::Affine const &m);
void ink_cairo_pattern_set_matrix(cairo_pattern_t *cp, Geom::Affine const &m);
void ink_cairo_set_source_argb32_pixbuf(cairo_t *ct, GdkPixbuf *pb, double x, double y);
void ink_matrix_to_2geom(Geom::Affine &, cairo_matrix_t const &);
void ink_matrix_to_cairo(cairo_matrix_t &, Geom::Affine const &);
cairo_surface_t *ink_cairo_surface_copy(cairo_surface_t *s);
cairo_surface_t *ink_cairo_surface_create_identical(cairo_surface_t *s);
cairo_surface_t *ink_cairo_surface_create_same_size(cairo_surface_t *s, cairo_content_t c);
cairo_surface_t *ink_cairo_extract_alpha(cairo_surface_t *s);
cairo_surface_t *ink_cairo_surface_create_output(cairo_surface_t *image, cairo_surface_t *bg);
void ink_cairo_surface_blit(cairo_surface_t *src, cairo_surface_t *dest);
int ink_cairo_surface_get_width(cairo_surface_t *surface);
int ink_cairo_surface_get_height(cairo_surface_t *surface);
guint32 ink_cairo_surface_average_color(cairo_surface_t *surface);
void ink_cairo_surface_average_color(cairo_surface_t *surface, double &r, double &g, double &b, double &a);
void ink_cairo_surface_average_color_premul(cairo_surface_t *surface, double &r, double &g, double &b, double &a);
cairo_pattern_t *ink_cairo_pattern_create_checkerboard();
void convert_pixels_pixbuf_to_argb32(guchar *data, int w, int h, int rs);
void convert_pixels_argb32_to_pixbuf(guchar *data, int w, int h, int rs);
void convert_pixbuf_normal_to_argb32(GdkPixbuf *);
void convert_pixbuf_argb32_to_normal(GdkPixbuf *);
cairo_surface_t *ink_cairo_surface_create_for_argb32_pixbuf(GdkPixbuf *pb);
void ink_cairo_pixbuf_cleanup(guchar *pixels, void *surface);
G_GNUC_CONST guint32 argb32_from_pixbuf(guint32 in);
G_GNUC_CONST guint32 pixbuf_from_argb32(guint32 in);
/** Convert a pixel in 0xRRGGBBAA format to Cairo ARGB32 format. */
G_GNUC_CONST guint32 argb32_from_rgba(guint32 in);
G_GNUC_CONST inline guint32
premul_alpha(guint32 color, guint32 alpha)
{
guint32 temp = alpha * color + 128;
return (temp + (temp >> 8)) >> 8;
}
G_GNUC_CONST inline guint32
unpremul_alpha(guint32 color, guint32 alpha)
{
// NOTE: you must check for alpha != 0 yourself.
return (255 * color + alpha/2) / alpha;
}
// TODO: move those to 2Geom
void feed_pathvector_to_cairo (cairo_t *ct, Geom::PathVector const &pathv, Geom::Affine trans, Geom::OptRect area, bool optimize_stroke, double stroke_width);
void feed_pathvector_to_cairo (cairo_t *ct, Geom::PathVector const &pathv);
#define EXTRACT_ARGB32(px,a,r,g,b) \
guint32 a, r, g, b; \
a = ((px) & 0xff000000) >> 24; \
r = ((px) & 0x00ff0000) >> 16; \
g = ((px) & 0x0000ff00) >> 8; \
b = ((px) & 0x000000ff);
#define ASSEMBLE_ARGB32(px,a,r,g,b) \
guint32 px = (a << 24) | (r << 16) | (g << 8) | b;
namespace Inkscape {
namespace Display
{
inline void ExtractARGB32(guint32 px, guint32 &a, guint32 &r, guint32 &g, guint &b)
{
a = ((px) & 0xff000000) >> 24;
r = ((px) & 0x00ff0000) >> 16;
g = ((px) & 0x0000ff00) >> 8;
b = ((px) & 0x000000ff);
}
inline void ExtractRGB32(guint32 px, guint32 &r, guint32 &g, guint &b)
{
r = ((px) & 0x00ff0000) >> 16;
g = ((px) & 0x0000ff00) >> 8;
b = ((px) & 0x000000ff);
}
inline guint AssembleARGB32(guint32 a, guint32 r, guint32 g, guint32 b)
{
return (a << 24) | (r << 16) | (g << 8) | b;
}
} // namespace Display
} // namespace Inkscape
#endif // SEEN_INKSCAPE_DISPLAY_CAIRO_UTILS_H
/*
Local Variables:
mode:c++
c-file-style:"stroustrup"
c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
indent-tabs-mode:nil
fill-column:99
End:
*/
// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 :
|