GCC Code Coverage Report


Directory: ./
File: panels/wacom/cc-drawing-area.c
Date: 2024-05-03 09:46:52
Exec Total Coverage
Lines: 0 74 0.0%
Functions: 0 12 0.0%
Branches: 0 21 0.0%

Line Branch Exec Source
1 /*
2 * Copyright © 2016 Red Hat, Inc.
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
8 *
9 * This program 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
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, see <http://www.gnu.org/licenses/>.
16 *
17 * Author: Carlos Garnacho <carlosg@gnome.org>
18 */
19
20 #include "config.h"
21 #include <cairo/cairo.h>
22 #include "cc-drawing-area.h"
23
24 typedef struct _CcDrawingArea CcDrawingArea;
25
26 struct _CcDrawingArea {
27 GtkDrawingArea parent;
28 GtkGesture *stylus_gesture;
29 cairo_surface_t *surface;
30 cairo_t *cr;
31 };
32
33 G_DEFINE_TYPE (CcDrawingArea, cc_drawing_area, GTK_TYPE_DRAWING_AREA)
34
35 static void
36 ensure_drawing_surface (CcDrawingArea *area,
37 gint width,
38 gint height)
39 {
40 if (!area->surface ||
41 cairo_image_surface_get_width (area->surface) != width ||
42 cairo_image_surface_get_height (area->surface) != height) {
43 cairo_surface_t *surface;
44
45 surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32,
46 width, height);
47 if (area->surface) {
48 cairo_t *cr;
49
50 cr = cairo_create (surface);
51 cairo_set_source_surface (cr, area->surface, 0, 0);
52 cairo_paint (cr);
53
54 cairo_surface_destroy (area->surface);
55 cairo_destroy (area->cr);
56 cairo_destroy (cr);
57 }
58
59 area->surface = surface;
60 area->cr = cairo_create (surface);
61 }
62 }
63
64 static void
65 cc_drawing_area_map (GtkWidget *widget)
66 {
67 GtkAllocation allocation;
68
69 GTK_WIDGET_CLASS (cc_drawing_area_parent_class)->map (widget);
70
71 gtk_widget_get_allocation (widget, &allocation);
72 ensure_drawing_surface (CC_DRAWING_AREA (widget),
73 allocation.width, allocation.height);
74 }
75
76 static void
77 cc_drawing_area_unmap (GtkWidget *widget)
78 {
79 CcDrawingArea *area = CC_DRAWING_AREA (widget);
80
81 if (area->cr) {
82 cairo_destroy (area->cr);
83 area->cr = NULL;
84 }
85
86 if (area->surface) {
87 cairo_surface_destroy (area->surface);
88 area->surface = NULL;
89 }
90
91 GTK_WIDGET_CLASS (cc_drawing_area_parent_class)->unmap (widget);
92 }
93
94 static void
95 draw_cb (GtkDrawingArea *drawing_area,
96 cairo_t *cr,
97 gint width,
98 gint height,
99 gpointer user_data)
100 {
101 CcDrawingArea *area = CC_DRAWING_AREA (drawing_area);
102
103 ensure_drawing_surface (area, width, height);
104
105 cairo_set_source_rgb (cr, 1, 1, 1);
106 cairo_paint (cr);
107
108 cairo_set_source_surface (cr, area->surface, 0, 0);
109 cairo_paint (cr);
110
111 cairo_set_source_rgb (cr, 0.6, 0.6, 0.6);
112 cairo_rectangle (cr, 0, 0, width, height);
113 cairo_stroke (cr);
114 }
115
116 static void
117 stylus_down_cb (CcDrawingArea *area,
118 double x,
119 double y)
120 {
121 cairo_new_path (area->cr);
122 }
123
124 static void
125 stylus_motion_cb (CcDrawingArea *area,
126 double x,
127 double y,
128 GtkGestureStylus *gesture)
129 {
130 GdkDeviceTool *tool;
131 gdouble pressure;
132
133 tool = gtk_gesture_stylus_get_device_tool (gesture);
134 gtk_gesture_stylus_get_axis (gesture,
135 GDK_AXIS_PRESSURE,
136 &pressure);
137
138 if (gdk_device_tool_get_tool_type (tool) == GDK_DEVICE_TOOL_TYPE_ERASER) {
139 cairo_set_line_width (area->cr, 10 * pressure);
140 cairo_set_operator (area->cr, CAIRO_OPERATOR_DEST_OUT);
141 } else {
142 cairo_set_line_width (area->cr, 4 * pressure);
143 cairo_set_operator (area->cr, CAIRO_OPERATOR_SATURATE);
144 }
145
146 cairo_set_source_rgba (area->cr, 0, 0, 0, pressure);
147 cairo_line_to (area->cr, x, y);
148 cairo_stroke (area->cr);
149
150 cairo_move_to (area->cr, x, y);
151
152 gtk_widget_queue_draw (GTK_WIDGET (area));
153 }
154
155 static void
156 cc_drawing_area_class_init (CcDrawingAreaClass *klass)
157 {
158 GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
159
160 widget_class->map = cc_drawing_area_map;
161 widget_class->unmap = cc_drawing_area_unmap;
162 }
163
164 static void
165 cc_drawing_area_init (CcDrawingArea *area)
166 {
167 gtk_drawing_area_set_draw_func (GTK_DRAWING_AREA (area), draw_cb, NULL, NULL);
168 area->stylus_gesture = gtk_gesture_stylus_new ();
169 g_signal_connect_swapped (area->stylus_gesture, "down",
170 G_CALLBACK (stylus_down_cb), area);
171 g_signal_connect_swapped (area->stylus_gesture, "motion",
172 G_CALLBACK (stylus_motion_cb), area);
173 gtk_widget_add_controller (GTK_WIDGET (area),
174 GTK_EVENT_CONTROLLER (area->stylus_gesture));
175 }
176
177 GtkWidget *
178 cc_drawing_area_new (void)
179 {
180 return g_object_new (CC_TYPE_DRAWING_AREA, NULL);
181 }
182