1 | /* |
2 | * Copyright © 2018 Benjamin Otte |
3 | * |
4 | * This library is free software; you can redistribute it and/or |
5 | * modify it under the terms of the GNU Lesser General Public |
6 | * License as published by the Free Software Foundation; either |
7 | * version 2.1 of the License, or (at your option) any later version. |
8 | * |
9 | * This library is distributed in the hope that it will be useful, |
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
12 | * Lesser General Public License for more details. |
13 | * |
14 | * You should have received a copy of the GNU Lesser General Public |
15 | * License along with this library. If not, see <http://www.gnu.org/licenses/>. |
16 | * |
17 | * Authors: Benjamin Otte <otte@gnome.org> |
18 | */ |
19 | |
20 | #include "config.h" |
21 | |
22 | #include "gtkscalerprivate.h" |
23 | |
24 | #include "gtksnapshot.h" |
25 | |
26 | struct _GtkScaler |
27 | { |
28 | GObject parent_instance; |
29 | |
30 | GdkPaintable *paintable; |
31 | double scale_factor; |
32 | }; |
33 | |
34 | struct _GtkScalerClass |
35 | { |
36 | GObjectClass parent_class; |
37 | }; |
38 | |
39 | static void |
40 | gtk_scaler_paintable_snapshot (GdkPaintable *paintable, |
41 | GdkSnapshot *snapshot, |
42 | double width, |
43 | double height) |
44 | { |
45 | GtkScaler *self = GTK_SCALER (ptr: paintable); |
46 | |
47 | gtk_snapshot_save (snapshot); |
48 | |
49 | gtk_snapshot_scale (snapshot, factor_x: 1.0 / self->scale_factor, factor_y: 1.0 / self->scale_factor); |
50 | |
51 | gdk_paintable_snapshot (paintable: self->paintable, |
52 | snapshot, |
53 | width: width * self->scale_factor, |
54 | height: height * self->scale_factor); |
55 | |
56 | gtk_snapshot_restore (snapshot); |
57 | } |
58 | |
59 | static GdkPaintable * |
60 | gtk_scaler_paintable_get_current_image (GdkPaintable *paintable) |
61 | { |
62 | GtkScaler *self = GTK_SCALER (ptr: paintable); |
63 | GdkPaintable *current_paintable, *current_self; |
64 | |
65 | current_paintable = gdk_paintable_get_current_image (paintable: self->paintable); |
66 | current_self = gtk_scaler_new (paintable: current_paintable, scale_factor: self->scale_factor); |
67 | g_object_unref (object: current_paintable); |
68 | |
69 | return current_self; |
70 | } |
71 | |
72 | static GdkPaintableFlags |
73 | gtk_scaler_paintable_get_flags (GdkPaintable *paintable) |
74 | { |
75 | GtkScaler *self = GTK_SCALER (ptr: paintable); |
76 | |
77 | return gdk_paintable_get_flags (paintable: self->paintable); |
78 | } |
79 | |
80 | static int |
81 | gtk_scaler_paintable_get_intrinsic_width (GdkPaintable *paintable) |
82 | { |
83 | GtkScaler *self = GTK_SCALER (ptr: paintable); |
84 | |
85 | return gdk_paintable_get_intrinsic_width (paintable: self->paintable) / self->scale_factor; |
86 | } |
87 | |
88 | static int |
89 | gtk_scaler_paintable_get_intrinsic_height (GdkPaintable *paintable) |
90 | { |
91 | GtkScaler *self = GTK_SCALER (ptr: paintable); |
92 | |
93 | return gdk_paintable_get_intrinsic_height (paintable: self->paintable) / self->scale_factor; |
94 | } |
95 | |
96 | static double gtk_scaler_paintable_get_intrinsic_aspect_ratio (GdkPaintable *paintable) |
97 | { |
98 | GtkScaler *self = GTK_SCALER (ptr: paintable); |
99 | |
100 | return gdk_paintable_get_intrinsic_aspect_ratio (paintable: self->paintable); |
101 | }; |
102 | |
103 | static void |
104 | gtk_scaler_paintable_init (GdkPaintableInterface *iface) |
105 | { |
106 | iface->snapshot = gtk_scaler_paintable_snapshot; |
107 | iface->get_current_image = gtk_scaler_paintable_get_current_image; |
108 | iface->get_flags = gtk_scaler_paintable_get_flags; |
109 | iface->get_intrinsic_width = gtk_scaler_paintable_get_intrinsic_width; |
110 | iface->get_intrinsic_height = gtk_scaler_paintable_get_intrinsic_height; |
111 | iface->get_intrinsic_aspect_ratio = gtk_scaler_paintable_get_intrinsic_aspect_ratio; |
112 | } |
113 | |
114 | G_DEFINE_TYPE_EXTENDED (GtkScaler, gtk_scaler, G_TYPE_OBJECT, 0, |
115 | G_IMPLEMENT_INTERFACE (GDK_TYPE_PAINTABLE, |
116 | gtk_scaler_paintable_init)) |
117 | |
118 | static void |
119 | gtk_scaler_dispose (GObject *object) |
120 | { |
121 | GtkScaler *self = GTK_SCALER (ptr: object); |
122 | |
123 | if (self->paintable) |
124 | { |
125 | const guint flags = gdk_paintable_get_flags (paintable: self->paintable); |
126 | |
127 | if ((flags & GDK_PAINTABLE_STATIC_CONTENTS) == 0) |
128 | g_signal_handlers_disconnect_by_func (self->paintable, gdk_paintable_invalidate_contents, self); |
129 | |
130 | if ((flags & GDK_PAINTABLE_STATIC_SIZE) == 0) |
131 | g_signal_handlers_disconnect_by_func (self->paintable, gdk_paintable_invalidate_size, self); |
132 | |
133 | g_clear_object (&self->paintable); |
134 | } |
135 | |
136 | G_OBJECT_CLASS (gtk_scaler_parent_class)->dispose (object); |
137 | } |
138 | |
139 | static void |
140 | gtk_scaler_class_init (GtkScalerClass *klass) |
141 | { |
142 | GObjectClass *gobject_class = G_OBJECT_CLASS (klass); |
143 | |
144 | gobject_class->dispose = gtk_scaler_dispose; |
145 | } |
146 | |
147 | static void |
148 | gtk_scaler_init (GtkScaler *self) |
149 | { |
150 | self->scale_factor = 1.0; |
151 | } |
152 | |
153 | GdkPaintable * |
154 | gtk_scaler_new (GdkPaintable *paintable, |
155 | double scale_factor) |
156 | { |
157 | GtkScaler *self; |
158 | guint flags; |
159 | |
160 | g_return_val_if_fail (GDK_IS_PAINTABLE (paintable), NULL); |
161 | g_return_val_if_fail (scale_factor > 0.0, NULL); |
162 | |
163 | self = g_object_new (GTK_TYPE_SCALER, NULL); |
164 | |
165 | self->paintable = g_object_ref (paintable); |
166 | flags = gdk_paintable_get_flags (paintable); |
167 | |
168 | if ((flags & GDK_PAINTABLE_STATIC_CONTENTS) == 0) |
169 | g_signal_connect_swapped (paintable, "invalidate-contents" , G_CALLBACK (gdk_paintable_invalidate_contents), self); |
170 | |
171 | if ((flags & GDK_PAINTABLE_STATIC_SIZE) == 0) |
172 | g_signal_connect_swapped (paintable, "invalidate-size" , G_CALLBACK (gdk_paintable_invalidate_size), self); |
173 | |
174 | self->scale_factor = scale_factor; |
175 | |
176 | return GDK_PAINTABLE (ptr: self); |
177 | } |
178 | |