1 #include <limits.h>
2 #include <math.h>
3 #include <stdbool.h>
4 #include <stdlib.h>
5 #include <wayland-server-protocol.h>
6 #include <wlr/types/wlr_box.h>
7 #include <wlr/util/log.h>
8 
wlr_box_closest_point(const struct wlr_box * box,double x,double y,double * dest_x,double * dest_y)9 void wlr_box_closest_point(const struct wlr_box *box, double x, double y,
10 		double *dest_x, double *dest_y) {
11 	// if box is empty, then it contains no points, so no closest point either
12 	if (box->width <= 0 || box->height <= 0) {
13 		*dest_x = NAN;
14 		*dest_y = NAN;
15 		return;
16 	}
17 
18 	// find the closest x point
19 	if (x < box->x) {
20 		*dest_x = box->x;
21 	} else if (x >= box->x + box->width) {
22 		*dest_x = box->x + box->width - 1;
23 	} else {
24 		*dest_x = x;
25 	}
26 
27 	// find closest y point
28 	if (y < box->y) {
29 		*dest_y = box->y;
30 	} else if (y >= box->y + box->height) {
31 		*dest_y = box->y + box->height - 1;
32 	} else {
33 		*dest_y = y;
34 	}
35 }
36 
wlr_box_empty(const struct wlr_box * box)37 bool wlr_box_empty(const struct wlr_box *box) {
38 	return box == NULL || box->width <= 0 || box->height <= 0;
39 }
40 
wlr_box_intersection(struct wlr_box * dest,const struct wlr_box * box_a,const struct wlr_box * box_b)41 bool wlr_box_intersection(struct wlr_box *dest, const struct wlr_box *box_a,
42 		const struct wlr_box *box_b) {
43 	bool a_empty = wlr_box_empty(box_a);
44 	bool b_empty = wlr_box_empty(box_b);
45 
46 	if (a_empty || b_empty) {
47 		dest->x = 0;
48 		dest->y = 0;
49 		dest->width = -100;
50 		dest->height = -100;
51 		return false;
52 	}
53 
54 	int x1 = fmax(box_a->x, box_b->x);
55 	int y1 = fmax(box_a->y, box_b->y);
56 	int x2 = fmin(box_a->x + box_a->width, box_b->x + box_b->width);
57 	int y2 = fmin(box_a->y + box_a->height, box_b->y + box_b->height);
58 
59 	dest->x = x1;
60 	dest->y = y1;
61 	dest->width = x2 - x1;
62 	dest->height = y2 - y1;
63 
64 	return !wlr_box_empty(dest);
65 }
66 
wlr_box_contains_point(const struct wlr_box * box,double x,double y)67 bool wlr_box_contains_point(const struct wlr_box *box, double x, double y) {
68 	if (wlr_box_empty(box)) {
69 		return false;
70 	} else {
71 		return x >= box->x && x < box->x + box->width &&
72 			y >= box->y && y < box->y + box->height;
73 	}
74 }
75 
wlr_box_transform(struct wlr_box * dest,const struct wlr_box * box,enum wl_output_transform transform,int width,int height)76 void wlr_box_transform(struct wlr_box *dest, const struct wlr_box *box,
77 		enum wl_output_transform transform, int width, int height) {
78 	struct wlr_box src = *box;
79 
80 	if (transform % 2 == 0) {
81 		dest->width = src.width;
82 		dest->height = src.height;
83 	} else {
84 		dest->width = src.height;
85 		dest->height = src.width;
86 	}
87 
88 	switch (transform) {
89 	case WL_OUTPUT_TRANSFORM_NORMAL:
90 		dest->x = src.x;
91 		dest->y = src.y;
92 		break;
93 	case WL_OUTPUT_TRANSFORM_90:
94 		dest->x = height - src.y - src.height;
95 		dest->y = src.x;
96 		break;
97 	case WL_OUTPUT_TRANSFORM_180:
98 		dest->x = width - src.x - src.width;
99 		dest->y = height - src.y - src.height;
100 		break;
101 	case WL_OUTPUT_TRANSFORM_270:
102 		dest->x = src.y;
103 		dest->y = width - src.x - src.width;
104 		break;
105 	case WL_OUTPUT_TRANSFORM_FLIPPED:
106 		dest->x = width - src.x - src.width;
107 		dest->y = src.y;
108 		break;
109 	case WL_OUTPUT_TRANSFORM_FLIPPED_90:
110 		dest->x = src.y;
111 		dest->y = src.x;
112 		break;
113 	case WL_OUTPUT_TRANSFORM_FLIPPED_180:
114 		dest->x = src.x;
115 		dest->y = height - src.y - src.height;
116 		break;
117 	case WL_OUTPUT_TRANSFORM_FLIPPED_270:
118 		dest->x = height - src.y - src.height;
119 		dest->y = width - src.x - src.width;
120 		break;
121 	}
122 }
123 
wlr_box_rotated_bounds(struct wlr_box * dest,const struct wlr_box * box,float rotation)124 void wlr_box_rotated_bounds(struct wlr_box *dest, const struct wlr_box *box,
125 		float rotation) {
126 	if (rotation == 0) {
127 		*dest = *box;
128 		return;
129 	}
130 
131 	double ox = box->x + (double)box->width/2;
132 	double oy = box->y + (double)box->height/2;
133 
134 	double c = fabs(cos(rotation));
135 	double s = fabs(sin(rotation));
136 
137 	double x1 = ox + (box->x - ox) * c + (box->y - oy) * s;
138 	double x2 = ox +
139 		(box->x + box->width - ox) * c +
140 		(box->y + box->height - oy) * s;
141 
142 	double y1 = oy + (box->x - ox) * s + (box->y - oy) * c;
143 	double y2 = oy +
144 		(box->x + box->width - ox) * s +
145 		(box->y + box->height - oy) * c;
146 
147 	dest->x = floor(fmin(x1, x2));
148 	dest->width = ceil(fmax(x1, x2) - fmin(x1, x2));
149 	dest->y = floor(fmin(y1, y2));
150 	dest->height = ceil(fmax(y1, y2) - fmin(y1, y2));
151 }
152 
wlr_box_from_pixman_box32(struct wlr_box * dest,const pixman_box32_t box)153 void wlr_box_from_pixman_box32(struct wlr_box *dest, const pixman_box32_t box) {
154 	*dest = (struct wlr_box){
155 		.x = box.x1,
156 		.y = box.y1,
157 		.width = box.x2 - box.x1,
158 		.height = box.y2 - box.y1,
159 	};
160 }
161