1
|
|
-Author: Victor Kareh <vkareh@redhat.com>
|
2
|
|
-Description: Render window buttons as cairo surfaces
|
3
|
|
-
|
4
|
|
-diff --git a/src/ui/theme.c b/src/ui/theme.c
|
5
|
|
-index 11cf3608..e15cf2ec 100644
|
6
|
|
---- a/src/ui/theme.c
|
7
|
|
-+++ b/src/ui/theme.c
|
8
|
|
-@@ -96,6 +96,114 @@ static void hls_to_rgb (gdouble *h,
|
9
|
|
- */
|
10
|
|
- static MetaTheme *meta_current_theme = NULL;
|
11
|
|
-
|
12
|
|
-+static cairo_surface_t *
|
13
|
|
-+scale_surface (cairo_surface_t *surface,
|
14
|
|
-+ gdouble old_width,
|
15
|
|
-+ gdouble old_height,
|
16
|
|
-+ gdouble new_width,
|
17
|
|
-+ gdouble new_height,
|
18
|
|
-+ gboolean vertical_stripes,
|
19
|
|
-+ gboolean horizontal_stripes)
|
20
|
|
-+{
|
21
|
|
-+ gdouble scale_x;
|
22
|
|
-+ gdouble scale_y;
|
23
|
|
-+ cairo_content_t content;
|
24
|
|
-+ gint width;
|
25
|
|
-+ gint height;
|
26
|
|
-+ cairo_surface_t *scaled;
|
27
|
|
-+ cairo_t *cr;
|
28
|
|
-+
|
29
|
|
-+ scale_x = new_width / old_width;
|
30
|
|
-+ scale_y = new_height / old_height;
|
31
|
|
-+
|
32
|
|
-+ if (horizontal_stripes && !vertical_stripes)
|
33
|
|
-+ {
|
34
|
|
-+ new_width = old_width;
|
35
|
|
-+ scale_x = 1.0;
|
36
|
|
-+ }
|
37
|
|
-+ else if (vertical_stripes && !horizontal_stripes)
|
38
|
|
-+ {
|
39
|
|
-+ new_height = old_height;
|
40
|
|
-+ scale_y = 1.0;
|
41
|
|
-+ }
|
42
|
|
-+
|
43
|
|
-+ content = CAIRO_CONTENT_COLOR_ALPHA;
|
44
|
|
-+ width = ceil (new_width);
|
45
|
|
-+ height = ceil (new_height);
|
46
|
|
-+
|
47
|
|
-+ scaled = cairo_surface_create_similar (surface, content, width, height);
|
48
|
|
-+ cr = cairo_create (scaled);
|
49
|
|
-+
|
50
|
|
-+ cairo_scale (cr, scale_x, scale_y);
|
51
|
|
-+ cairo_set_source_surface (cr, surface, 0, 0);
|
52
|
|
-+
|
53
|
|
-+ cairo_pattern_set_extend (cairo_get_source (cr), CAIRO_EXTEND_PAD);
|
54
|
|
-+
|
55
|
|
-+ cairo_paint (cr);
|
56
|
|
-+ cairo_destroy (cr);
|
57
|
|
-+
|
58
|
|
-+ return scaled;
|
59
|
|
-+}
|
60
|
|
-+
|
61
|
|
-+static cairo_surface_t *
|
62
|
|
-+get_surface_from_pixbuf (GdkPixbuf *pixbuf,
|
63
|
|
-+ MetaImageFillType fill_type,
|
64
|
|
-+ gdouble width,
|
65
|
|
-+ gdouble height,
|
66
|
|
-+ gboolean vertical_stripes,
|
67
|
|
-+ gboolean horizontal_stripes)
|
68
|
|
-+{
|
69
|
|
-+ gdouble pixbuf_width;
|
70
|
|
-+ gdouble pixbuf_height;
|
71
|
|
-+ cairo_surface_t *surface;
|
72
|
|
-+ cairo_content_t content;
|
73
|
|
-+ cairo_surface_t *copy;
|
74
|
|
-+ cairo_t *cr;
|
75
|
|
-+
|
76
|
|
-+ pixbuf_width = gdk_pixbuf_get_width (pixbuf);
|
77
|
|
-+ pixbuf_height = gdk_pixbuf_get_height (pixbuf);
|
78
|
|
-+ surface = gdk_cairo_surface_create_from_pixbuf (pixbuf, 1, NULL);
|
79
|
|
-+
|
80
|
|
-+ if (pixbuf_width == width && pixbuf_height == height)
|
81
|
|
-+ {
|
82
|
|
-+ return surface;
|
83
|
|
-+ }
|
84
|
|
-+
|
85
|
|
-+ if (fill_type != META_IMAGE_FILL_TILE)
|
86
|
|
-+ {
|
87
|
|
-+ cairo_surface_t *scaled;
|
88
|
|
-+
|
89
|
|
-+ scaled = scale_surface (surface, pixbuf_width, pixbuf_height,
|
90
|
|
-+ width, height, vertical_stripes,
|
91
|
|
-+ horizontal_stripes);
|
92
|
|
-+
|
93
|
|
-+ cairo_surface_destroy (surface);
|
94
|
|
-+ surface = scaled;
|
95
|
|
-+ }
|
96
|
|
-+
|
97
|
|
-+ content = CAIRO_CONTENT_COLOR_ALPHA;
|
98
|
|
-+ width = ceil (width);
|
99
|
|
-+ height = ceil (height);
|
100
|
|
-+
|
101
|
|
-+ copy = cairo_surface_create_similar (surface, content, width, height);
|
102
|
|
-+ cr = cairo_create (copy);
|
103
|
|
-+
|
104
|
|
-+ cairo_set_source_surface (cr, surface, 0, 0);
|
105
|
|
-+
|
106
|
|
-+ if (fill_type == META_IMAGE_FILL_TILE ||
|
107
|
|
-+ vertical_stripes || horizontal_stripes)
|
108
|
|
-+ {
|
109
|
|
-+ cairo_pattern_set_extend (cairo_get_source (cr), CAIRO_EXTEND_REPEAT);
|
110
|
|
-+ }
|
111
|
|
-+
|
112
|
|
-+ cairo_paint (cr);
|
113
|
|
-+ cairo_destroy (cr);
|
114
|
|
-+
|
115
|
|
-+ cairo_surface_destroy (surface);
|
116
|
|
-+
|
117
|
|
-+ return copy;
|
118
|
|
-+}
|
119
|
|
-+
|
120
|
|
- static GdkPixbuf *
|
121
|
|
- colorize_pixbuf (GdkPixbuf *orig,
|
122
|
|
- GdkRGBA *new_color)
|
123
|
|
-@@ -1149,6 +1257,38 @@ meta_alpha_gradient_spec_free (MetaAlphaGradientSpec *spec)
|
124
|
|
- g_free (spec);
|
125
|
|
- }
|
126
|
|
-
|
127
|
|
-+cairo_pattern_t *
|
128
|
|
-+meta_alpha_gradient_spec_get_mask (const MetaAlphaGradientSpec *spec)
|
129
|
|
-+{
|
130
|
|
-+ gint n_alphas;
|
131
|
|
-+ cairo_pattern_t *pattern;
|
132
|
|
-+ gint i;
|
133
|
|
-+
|
134
|
|
-+ /* Hardcoded in theme-parser.c */
|
135
|
|
-+ g_assert (spec->type == META_GRADIENT_HORIZONTAL);
|
136
|
|
-+
|
137
|
|
-+ n_alphas = spec->n_alphas;
|
138
|
|
-+ if (n_alphas == 0)
|
139
|
|
-+ return NULL;
|
140
|
|
-+
|
141
|
|
-+ if (n_alphas == 1)
|
142
|
|
-+ return cairo_pattern_create_rgba (0, 0, 0, spec->alphas[0] / 255.0);
|
143
|
|
-+
|
144
|
|
-+ pattern = cairo_pattern_create_linear (0, 0, 1, 0);
|
145
|
|
-+
|
146
|
|
-+ for (i = 0; i < n_alphas; i++)
|
147
|
|
-+ cairo_pattern_add_color_stop_rgba (pattern, i / (gfloat) (n_alphas - 1),
|
148
|
|
-+ 0, 0, 0, spec->alphas[i] / 255.0);
|
149
|
|
-+
|
150
|
|
-+ if (cairo_pattern_status (pattern) != CAIRO_STATUS_SUCCESS)
|
151
|
|
-+ {
|
152
|
|
-+ cairo_pattern_destroy (pattern);
|
153
|
|
-+ return NULL;
|
154
|
|
-+ }
|
155
|
|
-+
|
156
|
|
-+ return pattern;
|
157
|
|
-+}
|
158
|
|
-+
|
159
|
|
- MetaColorSpec*
|
160
|
|
- meta_color_spec_new (MetaColorSpecType type)
|
161
|
|
- {
|
162
|
|
-@@ -3625,6 +3765,94 @@ draw_op_as_pixbuf (const MetaDrawOp *op,
|
163
|
|
- return pixbuf;
|
164
|
|
- }
|
165
|
|
-
|
166
|
|
-+static cairo_surface_t *
|
167
|
|
-+draw_op_as_surface (const MetaDrawOp *op,
|
168
|
|
-+ GtkStyleContext *style,
|
169
|
|
-+ const MetaDrawInfo *info,
|
170
|
|
-+ gdouble width,
|
171
|
|
-+ gdouble height)
|
172
|
|
-+{
|
173
|
|
-+ cairo_surface_t *surface;
|
174
|
|
-+
|
175
|
|
-+ surface = NULL;
|
176
|
|
-+
|
177
|
|
-+ switch (op->type)
|
178
|
|
-+ {
|
179
|
|
-+ case META_DRAW_IMAGE:
|
180
|
|
-+ {
|
181
|
|
-+ if (op->data.image.colorize_spec)
|
182
|
|
-+ {
|
183
|
|
-+ GdkRGBA color;
|
184
|
|
-+
|
185
|
|
-+ meta_color_spec_render (op->data.image.colorize_spec,
|
186
|
|
-+ style, &color);
|
187
|
|
-+
|
188
|
|
-+ if (op->data.image.colorize_cache_pixbuf == NULL ||
|
189
|
|
-+ op->data.image.colorize_cache_pixel != GDK_COLOR_RGB (color))
|
190
|
|
-+ {
|
191
|
|
-+ if (op->data.image.colorize_cache_pixbuf)
|
192
|
|
-+ g_object_unref (G_OBJECT (op->data.image.colorize_cache_pixbuf));
|
193
|
|
-+
|
194
|
|
-+ /* const cast here */
|
195
|
|
-+ ((MetaDrawOp*)op)->data.image.colorize_cache_pixbuf =
|
196
|
|
-+ colorize_pixbuf (op->data.image.pixbuf,
|
197
|
|
-+ &color);
|
198
|
|
-+ ((MetaDrawOp*)op)->data.image.colorize_cache_pixel =
|
199
|
|
-+ GDK_COLOR_RGB (color);
|
200
|
|
-+ }
|
201
|
|
-+
|
202
|
|
-+ if (op->data.image.colorize_cache_pixbuf)
|
203
|
|
-+ {
|
204
|
|
-+ surface = get_surface_from_pixbuf (op->data.image.colorize_cache_pixbuf,
|
205
|
|
-+ op->data.image.fill_type,
|
206
|
|
-+ width, height,
|
207
|
|
-+ op->data.image.vertical_stripes,
|
208
|
|
-+ op->data.image.horizontal_stripes);
|
209
|
|
-+ }
|
210
|
|
-+ }
|
211
|
|
-+ else
|
212
|
|
-+ {
|
213
|
|
-+ surface = get_surface_from_pixbuf (op->data.image.pixbuf,
|
214
|
|
-+ op->data.image.fill_type,
|
215
|
|
-+ width, height,
|
216
|
|
-+ op->data.image.vertical_stripes,
|
217
|
|
-+ op->data.image.horizontal_stripes);
|
218
|
|
-+ }
|
219
|
|
-+ break;
|
220
|
|
-+ }
|
221
|
|
-+
|
222
|
|
-+ case META_DRAW_ICON:
|
223
|
|
-+ if (info->mini_icon &&
|
224
|
|
-+ width <= gdk_pixbuf_get_width (info->mini_icon) &&
|
225
|
|
-+ height <= gdk_pixbuf_get_height (info->mini_icon))
|
226
|
|
-+ surface = get_surface_from_pixbuf (info->mini_icon, op->data.icon.fill_type,
|
227
|
|
-+ width, height, FALSE, FALSE);
|
228
|
|
-+ else if (info->icon)
|
229
|
|
-+ surface = get_surface_from_pixbuf (info->icon, op->data.icon.fill_type,
|
230
|
|
-+ width, height, FALSE, FALSE);
|
231
|
|
-+ break;
|
232
|
|
-+
|
233
|
|
-+ case META_DRAW_TINT:
|
234
|
|
-+ case META_DRAW_LINE:
|
235
|
|
-+ case META_DRAW_RECTANGLE:
|
236
|
|
-+ case META_DRAW_ARC:
|
237
|
|
-+ case META_DRAW_CLIP:
|
238
|
|
-+ case META_DRAW_GRADIENT:
|
239
|
|
-+ case META_DRAW_GTK_ARROW:
|
240
|
|
-+ case META_DRAW_GTK_BOX:
|
241
|
|
-+ case META_DRAW_GTK_VLINE:
|
242
|
|
-+ case META_DRAW_TITLE:
|
243
|
|
-+ case META_DRAW_OP_LIST:
|
244
|
|
-+ case META_DRAW_TILE:
|
245
|
|
-+ break;
|
246
|
|
-+
|
247
|
|
-+ default:
|
248
|
|
-+ break;
|
249
|
|
-+ }
|
250
|
|
-+
|
251
|
|
-+ return surface;
|
252
|
|
-+}
|
253
|
|
-+
|
254
|
|
- static void
|
255
|
|
- fill_env (MetaPositionExprEnv *env,
|
256
|
|
- const MetaDrawInfo *info,
|
257
|
|
-@@ -3897,8 +4125,12 @@ meta_draw_op_draw_with_env (const MetaDrawOp *op,
|
258
|
|
-
|
259
|
|
- case META_DRAW_IMAGE:
|
260
|
|
- {
|
261
|
|
-- int rx, ry, rwidth, rheight;
|
262
|
|
-- GdkPixbuf *pixbuf;
|
263
|
|
-+ gint scale;
|
264
|
|
-+ gdouble rx, ry, rwidth, rheight;
|
265
|
|
-+ cairo_surface_t *surface;
|
266
|
|
-+
|
267
|
|
-+ scale = gdk_window_get_scale_factor (gdk_get_default_root_window ());
|
268
|
|
-+ cairo_scale (cr, 1.0 / scale, 1.0 / scale);
|
269
|
|
-
|
270
|
|
- if (op->data.image.pixbuf)
|
271
|
|
- {
|
272
|
|
-@@ -3906,21 +4138,36 @@ meta_draw_op_draw_with_env (const MetaDrawOp *op,
|
273
|
|
- env->object_height = gdk_pixbuf_get_height (op->data.image.pixbuf);
|
274
|
|
- }
|
275
|
|
-
|
276
|
|
-- rwidth = parse_size_unchecked (op->data.image.width, env);
|
277
|
|
-- rheight = parse_size_unchecked (op->data.image.height, env);
|
278
|
|
-+ rwidth = parse_size_unchecked (op->data.image.width, env) * scale;
|
279
|
|
-+ rheight = parse_size_unchecked (op->data.image.height, env) * scale;
|
280
|
|
-
|
281
|
|
-- pixbuf = draw_op_as_pixbuf (op, style_gtk, info,
|
282
|
|
-- rwidth, rheight);
|
283
|
|
-+ surface = draw_op_as_surface (op, style_gtk, info, rwidth, rheight);
|
284
|
|
-
|
285
|
|
-- if (pixbuf)
|
286
|
|
-+ if (surface)
|
287
|
|
- {
|
288
|
|
-- rx = parse_x_position_unchecked (op->data.image.x, env);
|
289
|
|
-- ry = parse_y_position_unchecked (op->data.image.y, env);
|
290
|
|
-+ rx = parse_x_position_unchecked (op->data.image.x, env) * scale;
|
291
|
|
-+ ry = parse_y_position_unchecked (op->data.image.y, env) * scale;
|
292
|
|
-
|
293
|
|
-- gdk_cairo_set_source_pixbuf (cr, pixbuf, rx, ry);
|
294
|
|
-- cairo_paint (cr);
|
295
|
|
-+ cairo_set_source_surface (cr, surface, rx, ry);
|
296
|
|
-
|
297
|
|
-- g_object_unref (G_OBJECT (pixbuf));
|
298
|
|
-+ if (op->data.image.alpha_spec)
|
299
|
|
-+ {
|
300
|
|
-+ cairo_pattern_t *pattern;
|
301
|
|
-+
|
302
|
|
-+ cairo_translate (cr, rx, ry);
|
303
|
|
-+ cairo_scale (cr, rwidth, rheight);
|
304
|
|
-+
|
305
|
|
-+ pattern = meta_alpha_gradient_spec_get_mask (op->data.image.alpha_spec);
|
306
|
|
-+ cairo_mask (cr, pattern);
|
307
|
|
-+
|
308
|
|
-+ cairo_pattern_destroy (pattern);
|
309
|
|
-+ }
|
310
|
|
-+ else
|
311
|
|
-+ {
|
312
|
|
-+ cairo_paint (cr);
|
313
|
|
-+ }
|
314
|
|
-+
|
315
|
|
-+ cairo_surface_destroy (surface);
|
316
|
|
- }
|
317
|
|
- }
|
318
|
|
- break;
|
319
|
|
-@@ -3989,24 +4236,43 @@ meta_draw_op_draw_with_env (const MetaDrawOp *op,
|
320
|
|
-
|
321
|
|
- case META_DRAW_ICON:
|
322
|
|
- {
|
323
|
|
-- int rx, ry, rwidth, rheight;
|
324
|
|
-- GdkPixbuf *pixbuf;
|
325
|
|
-+ gint scale;
|
326
|
|
-+ gdouble rx, ry, rwidth, rheight;
|
327
|
|
-+ cairo_surface_t *surface;
|
328
|
|
-+
|
329
|
|
-+ scale = gdk_window_get_scale_factor (gdk_get_default_root_window ());
|
330
|
|
-+ cairo_scale (cr, 1.0 / scale, 1.0 / scale);
|
331
|
|
-
|
332
|
|
-- rwidth = parse_size_unchecked (op->data.icon.width, env);
|
333
|
|
-- rheight = parse_size_unchecked (op->data.icon.height, env);
|
334
|
|
-+ rwidth = parse_size_unchecked (op->data.icon.width, env) * scale;
|
335
|
|
-+ rheight = parse_size_unchecked (op->data.icon.height, env) * scale;
|
336
|
|
-
|
337
|
|
-- pixbuf = draw_op_as_pixbuf (op, style_gtk, info,
|
338
|
|
-- rwidth, rheight);
|
339
|
|
-+ surface = draw_op_as_surface (op, style_gtk, info, rwidth, rheight);
|
340
|
|
-
|
341
|
|
-- if (pixbuf)
|
342
|
|
-+ if (surface)
|
343
|
|
- {
|
344
|
|
-- rx = parse_x_position_unchecked (op->data.icon.x, env);
|
345
|
|
-- ry = parse_y_position_unchecked (op->data.icon.y, env);
|
346
|
|
-+ rx = parse_x_position_unchecked (op->data.icon.x, env) * scale;
|
347
|
|
-+ ry = parse_y_position_unchecked (op->data.icon.y, env) * scale;
|
348
|
|
-
|
349
|
|
-- gdk_cairo_set_source_pixbuf (cr, pixbuf, rx, ry);
|
350
|
|
-- cairo_paint (cr);
|
351
|
|
-+ cairo_set_source_surface (cr, surface, rx, ry);
|
352
|
|
-
|
353
|
|
-- g_object_unref (G_OBJECT (pixbuf));
|
354
|
|
-+ if (op->data.icon.alpha_spec)
|
355
|
|
-+ {
|
356
|
|
-+ cairo_pattern_t *pattern;
|
357
|
|
-+
|
358
|
|
-+ cairo_translate (cr, rx, ry);
|
359
|
|
-+ cairo_scale (cr, rwidth, rheight);
|
360
|
|
-+
|
361
|
|
-+ pattern = meta_alpha_gradient_spec_get_mask (op->data.icon.alpha_spec);
|
362
|
|
-+ cairo_mask (cr, pattern);
|
363
|
|
-+
|
364
|
|
-+ cairo_pattern_destroy (pattern);
|
365
|
|
-+ }
|
366
|
|
-+ else
|
367
|
|
-+ {
|
368
|
|
-+ cairo_paint (cr);
|
369
|
|
-+ }
|
370
|
|
-+
|
371
|
|
-+ cairo_surface_destroy (surface);
|
372
|
|
- }
|
373
|
|
- }
|
374
|
|
- break;
|
375
|
|
-diff --git a/src/ui/theme.h b/src/ui/theme.h
|
376
|
|
-index 34b98935..9dfb8d89 100644
|
377
|
|
---- a/src/ui/theme.h
|
378
|
|
-+++ b/src/ui/theme.h
|
379
|
|
-@@ -964,6 +964,7 @@ gboolean meta_gradient_spec_validate (MetaGradientSpec *spec,
|
380
|
|
- MetaAlphaGradientSpec* meta_alpha_gradient_spec_new (MetaGradientType type,
|
381
|
|
- int n_alphas);
|
382
|
|
- void meta_alpha_gradient_spec_free (MetaAlphaGradientSpec *spec);
|
383
|
|
-+cairo_pattern_t * meta_alpha_gradient_spec_get_mask (const MetaAlphaGradientSpec *spec);
|
384
|
|
-
|
385
|
|
-
|
386
|
|
- MetaFrameStyle* meta_frame_style_new (MetaFrameStyle *parent);
|