GCC Code Coverage Report


Directory: ./
File: panels/background/cc-background-paintable.c
Date: 2024-05-04 07:58:27
Exec Total Coverage
Lines: 0 149 0.0%
Functions: 0 16 0.0%
Branches: 0 67 0.0%

Line Branch Exec Source
1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
2 *
3 * Copyright (C) 2021 Alexander Mikhaylenko <alexm@gnome.org>
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program 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
20 #include <config.h>
21
22 #include "cc-background-enum-types.h"
23 #include "cc-background-paintable.h"
24
25 struct _CcBackgroundPaintable
26 {
27 GObject parent_instance;
28
29 GnomeDesktopThumbnailFactory *thumbnail_factory;
30 CcBackgroundItem *item;
31 int width;
32 int height;
33 int scale_factor;
34 GtkTextDirection text_direction;
35
36 GdkPaintable *texture;
37 GdkPaintable *dark_texture;
38
39 CcBackgroundPaintFlags paint_flags;
40 };
41
42 enum
43 {
44 PROP_0,
45 PROP_THUMBNAIL_FACTORY,
46 PROP_ITEM,
47 PROP_WIDTH,
48 PROP_HEIGHT,
49 PROP_SCALE_FACTOR,
50 PROP_TEXT_DIRECTION,
51 PROP_PAINT_FLAGS,
52 N_PROPS
53 };
54
55 static GParamSpec *properties [N_PROPS];
56
57 static void cc_background_paintable_paintable_init (GdkPaintableInterface *iface);
58
59 G_DEFINE_TYPE_WITH_CODE (CcBackgroundPaintable, cc_background_paintable, G_TYPE_OBJECT,
60 G_IMPLEMENT_INTERFACE (GDK_TYPE_PAINTABLE,
61 cc_background_paintable_paintable_init))
62
63 static void
64 update_cache (CcBackgroundPaintable *self)
65 {
66 g_autoptr(GdkPixbuf) pixbuf = NULL;
67 g_autoptr(GdkPixbuf) dark_pixbuf = NULL;
68 gboolean has_dark;
69
70 g_clear_object (&self->texture);
71 g_clear_object (&self->dark_texture);
72
73 has_dark = cc_background_item_has_dark_version (self->item);
74
75 if ((self->paint_flags & CC_BACKGROUND_PAINT_LIGHT) || !has_dark)
76 {
77 pixbuf = cc_background_item_get_thumbnail (self->item,
78 self->thumbnail_factory,
79 self->width,
80 self->height,
81 self->scale_factor,
82 FALSE);
83 self->texture = GDK_PAINTABLE (gdk_texture_new_for_pixbuf (pixbuf));
84 }
85
86 if ((self->paint_flags & CC_BACKGROUND_PAINT_DARK) && has_dark)
87 {
88 dark_pixbuf = cc_background_item_get_thumbnail (self->item,
89 self->thumbnail_factory,
90 self->width,
91 self->height,
92 self->scale_factor,
93 TRUE);
94 self->dark_texture = GDK_PAINTABLE (gdk_texture_new_for_pixbuf (dark_pixbuf));
95 }
96
97 gdk_paintable_invalidate_size (GDK_PAINTABLE (self));
98 }
99
100 static void
101 cc_background_paintable_dispose (GObject *object)
102 {
103 CcBackgroundPaintable *self = CC_BACKGROUND_PAINTABLE (object);
104
105 g_clear_object (&self->item);
106 g_clear_object (&self->thumbnail_factory);
107 g_clear_object (&self->texture);
108 g_clear_object (&self->dark_texture);
109
110 G_OBJECT_CLASS (cc_background_paintable_parent_class)->dispose (object);
111 }
112
113 static void
114 cc_background_paintable_constructed (GObject *object)
115 {
116 CcBackgroundPaintable *self = CC_BACKGROUND_PAINTABLE (object);
117
118 G_OBJECT_CLASS (cc_background_paintable_parent_class)->constructed (object);
119
120 update_cache (self);
121 }
122
123 static void
124 cc_background_paintable_get_property (GObject *object,
125 guint prop_id,
126 GValue *value,
127 GParamSpec *pspec)
128 {
129 CcBackgroundPaintable *self = CC_BACKGROUND_PAINTABLE (object);
130
131 switch (prop_id)
132 {
133 case PROP_THUMBNAIL_FACTORY:
134 g_value_set_object (value, self->thumbnail_factory);
135 break;
136
137 case PROP_ITEM:
138 g_value_set_object (value, self->item);
139 break;
140
141 case PROP_WIDTH:
142 g_value_set_int (value, self->width);
143 break;
144
145 case PROP_HEIGHT:
146 g_value_set_int (value, self->height);
147 break;
148
149 case PROP_SCALE_FACTOR:
150 g_value_set_int (value, self->scale_factor);
151 break;
152
153 case PROP_TEXT_DIRECTION:
154 g_value_set_enum (value, self->text_direction);
155 break;
156
157 case PROP_PAINT_FLAGS:
158 g_value_set_flags (value, self->paint_flags);
159 break;
160
161 default:
162 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
163 }
164 }
165
166 static void
167 cc_background_paintable_set_property (GObject *object,
168 guint prop_id,
169 const GValue *value,
170 GParamSpec *pspec)
171 {
172 CcBackgroundPaintable *self = CC_BACKGROUND_PAINTABLE (object);
173
174 switch (prop_id)
175 {
176 case PROP_THUMBNAIL_FACTORY:
177 g_set_object (&self->thumbnail_factory, g_value_get_object (value));
178 break;
179
180 case PROP_ITEM:
181 g_set_object (&self->item, g_value_get_object (value));
182 break;
183
184 case PROP_WIDTH:
185 self->width = g_value_get_int (value);
186 break;
187
188 case PROP_HEIGHT:
189 self->height = g_value_get_int (value);
190 break;
191
192 case PROP_SCALE_FACTOR:
193 self->scale_factor = g_value_get_int (value);
194 update_cache (self);
195 break;
196
197 case PROP_TEXT_DIRECTION:
198 self->text_direction = g_value_get_enum (value);
199 gdk_paintable_invalidate_contents (GDK_PAINTABLE (self));
200 break;
201
202 case PROP_PAINT_FLAGS:
203 self->paint_flags = g_value_get_flags (value);
204 break;
205
206 default:
207 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
208 }
209 }
210
211 static void
212 cc_background_paintable_class_init (CcBackgroundPaintableClass *klass)
213 {
214 GObjectClass *object_class = G_OBJECT_CLASS (klass);
215
216 object_class->dispose = cc_background_paintable_dispose;
217 object_class->constructed = cc_background_paintable_constructed;
218 object_class->get_property = cc_background_paintable_get_property;
219 object_class->set_property = cc_background_paintable_set_property;
220
221 properties[PROP_THUMBNAIL_FACTORY] =
222 g_param_spec_object ("thumbnail-factory",
223 "Thumbnail factory",
224 "Thumbnail factory",
225 GNOME_DESKTOP_TYPE_THUMBNAIL_FACTORY,
226 G_PARAM_READWRITE |
227 G_PARAM_CONSTRUCT_ONLY |
228 G_PARAM_STATIC_STRINGS);
229
230 properties[PROP_ITEM] =
231 g_param_spec_object ("item",
232 "Item",
233 "Item",
234 CC_TYPE_BACKGROUND_ITEM,
235 G_PARAM_READWRITE |
236 G_PARAM_CONSTRUCT_ONLY |
237 G_PARAM_STATIC_STRINGS);
238
239 properties[PROP_WIDTH] =
240 g_param_spec_int ("width",
241 "Width",
242 "Width",
243 1, G_MAXINT, 144,
244 G_PARAM_READWRITE |
245 G_PARAM_CONSTRUCT_ONLY |
246 G_PARAM_STATIC_STRINGS);
247
248 properties[PROP_HEIGHT] =
249 g_param_spec_int ("height",
250 "Height",
251 "Height",
252 1, G_MAXINT, 144 * 3 / 4,
253 G_PARAM_READWRITE |
254 G_PARAM_CONSTRUCT_ONLY |
255 G_PARAM_STATIC_STRINGS);
256
257 properties[PROP_SCALE_FACTOR] =
258 g_param_spec_int ("scale-factor",
259 "Scale Factor",
260 "Scale Factor",
261 1, G_MAXINT, 1,
262 G_PARAM_READWRITE |
263 G_PARAM_STATIC_STRINGS);
264
265 properties[PROP_TEXT_DIRECTION] =
266 g_param_spec_enum ("text-direction",
267 "Text Direction",
268 "Text Direction",
269 GTK_TYPE_TEXT_DIRECTION,
270 GTK_TEXT_DIR_LTR,
271 G_PARAM_READWRITE |
272 G_PARAM_STATIC_STRINGS);
273
274 properties[PROP_PAINT_FLAGS] =
275 g_param_spec_flags ("paint-flags",
276 "Paint Flags",
277 "Paint Flags",
278 CC_TYPE_BACKGROUND_PAINT_FLAGS,
279 CC_BACKGROUND_PAINT_LIGHT,
280 G_PARAM_READWRITE |
281 G_PARAM_CONSTRUCT_ONLY |
282 G_PARAM_STATIC_STRINGS);
283
284 g_object_class_install_properties (object_class, N_PROPS, properties);
285 }
286
287 static void
288 cc_background_paintable_init (CcBackgroundPaintable *self)
289 {
290 self->scale_factor = 1;
291 self->text_direction = GTK_TEXT_DIR_LTR;
292 }
293
294 static void
295 cc_background_paintable_snapshot (GdkPaintable *paintable,
296 GdkSnapshot *snapshot,
297 double width,
298 double height)
299 {
300 CcBackgroundPaintable *self = CC_BACKGROUND_PAINTABLE (paintable);
301 gboolean is_rtl;
302
303 if (!self->dark_texture)
304 {
305 gdk_paintable_snapshot (self->texture, snapshot, width, height);
306 return;
307 }
308
309 if (!self->texture)
310 {
311 gdk_paintable_snapshot (self->dark_texture, snapshot, width, height);
312 return;
313 }
314
315 is_rtl = self->text_direction == GTK_TEXT_DIR_RTL;
316
317 gtk_snapshot_push_clip (GTK_SNAPSHOT (snapshot),
318 &GRAPHENE_RECT_INIT (is_rtl ? width / 2.0f : 0.0f,
319 0.0f,
320 width / 2.0f,
321 height));
322 gdk_paintable_snapshot (self->texture, snapshot, width, height);
323 gtk_snapshot_pop (GTK_SNAPSHOT (snapshot));
324
325 gtk_snapshot_push_clip (GTK_SNAPSHOT (snapshot),
326 &GRAPHENE_RECT_INIT (is_rtl ? 0.0f : width / 2.0f,
327 0.0f,
328 width / 2.0f,
329 height));
330 gdk_paintable_snapshot (self->dark_texture, snapshot, width, height);
331 gtk_snapshot_pop (GTK_SNAPSHOT (snapshot));
332 }
333
334 static int
335 cc_background_paintable_get_intrinsic_width (GdkPaintable *paintable)
336 {
337 CcBackgroundPaintable *self = CC_BACKGROUND_PAINTABLE (paintable);
338 GdkPaintable *valid_texture = self->texture ? self->texture : self->dark_texture;
339
340 return gdk_paintable_get_intrinsic_width (valid_texture) / self->scale_factor;
341 }
342
343 static int
344 cc_background_paintable_get_intrinsic_height (GdkPaintable *paintable)
345 {
346 CcBackgroundPaintable *self = CC_BACKGROUND_PAINTABLE (paintable);
347 GdkPaintable *valid_texture = self->texture ? self->texture : self->dark_texture;
348
349 return gdk_paintable_get_intrinsic_height (valid_texture) / self->scale_factor;
350 }
351
352 static double
353 cc_background_paintable_get_intrinsic_aspect_ratio (GdkPaintable *paintable)
354 {
355 CcBackgroundPaintable *self = CC_BACKGROUND_PAINTABLE (paintable);
356 GdkPaintable *valid_texture = self->texture ? self->texture : self->dark_texture;
357
358 return gdk_paintable_get_intrinsic_aspect_ratio (valid_texture);
359 }
360
361 static void
362 cc_background_paintable_paintable_init (GdkPaintableInterface *iface)
363 {
364 iface->snapshot = cc_background_paintable_snapshot;
365 iface->get_intrinsic_width = cc_background_paintable_get_intrinsic_width;
366 iface->get_intrinsic_height = cc_background_paintable_get_intrinsic_height;
367 iface->get_intrinsic_aspect_ratio = cc_background_paintable_get_intrinsic_aspect_ratio;
368 }
369
370 /* Workaround for a typo in libgnome-desktop, see gnome-desktop!160 */
371 #define G_TYPE_INSTANCE_CHECK_TYPE G_TYPE_CHECK_INSTANCE_TYPE
372
373 CcBackgroundPaintable *
374 cc_background_paintable_new (GnomeDesktopThumbnailFactory *thumbnail_factory,
375 CcBackgroundItem *item,
376 CcBackgroundPaintFlags paint_flags,
377 int width,
378 int height)
379 {
380 g_return_val_if_fail (GNOME_DESKTOP_IS_THUMBNAIL_FACTORY (thumbnail_factory), NULL);
381 g_return_val_if_fail (CC_IS_BACKGROUND_ITEM (item), NULL);
382
383 return g_object_new (CC_TYPE_BACKGROUND_PAINTABLE,
384 "thumbnail-factory", thumbnail_factory,
385 "item", item,
386 "paint-flags", paint_flags,
387 "width", width,
388 "height", height,
389 NULL);
390 }
391