source: mainline/uspace/lib/gfx/src/coord.c@ 1388f7f0

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since 1388f7f0 was 1388f7f0, checked in by Jiri Svoboda <jiri@…>, 5 years ago

Support absolute movement events from input device

  • Property mode set to 100644
File size: 6.8 KB
Line 
1/*
2 * Copyright (c) 2019 Jiri Svoboda
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *
9 * - Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * - Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * - The name of the author may not be used to endorse or promote products
15 * derived from this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29/** @addtogroup libgfx
30 * @{
31 */
32/**
33 * @file Coordinates
34 */
35
36#include <gfx/coord.h>
37#include <macros.h>
38#include <stdbool.h>
39
40/** Add two vectors.
41 *
42 * @param a First vector
43 * @param b Second vector
44 * @param d Destination
45 */
46void gfx_coord2_add(gfx_coord2_t *a, gfx_coord2_t *b, gfx_coord2_t *d)
47{
48 d->x = a->x + b->x;
49 d->y = a->y + b->y;
50}
51
52/** Subtract two vectors.
53 *
54 * @param a First vector
55 * @param b Second vector
56 * @param d Destination
57 */
58void gfx_coord2_subtract(gfx_coord2_t *a, gfx_coord2_t *b, gfx_coord2_t *d)
59{
60 d->x = a->x - b->x;
61 d->y = a->y - b->y;
62}
63
64/** Clip point coordinates to be within a rectangle.
65 *
66 * @param a Pixel coordinates
67 * @param clip Clipping rectangle
68 * @param d Place to store clipped coordinates
69 */
70void gfx_coord2_clip(gfx_coord2_t *a, gfx_rect_t *clip, gfx_coord2_t *d)
71{
72 gfx_rect_t sclip;
73 gfx_coord2_t t;
74
75 gfx_rect_points_sort(clip, &sclip);
76
77 t.x = min(a->x, clip->p1.x - 1);
78 t.y = min(a->y, clip->p1.y - 1);
79
80 d->x = max(clip->p0.x, t.x);
81 d->y = max(clip->p0.y, t.y);
82}
83
84/** Transform coordinates via rectangle to rectangle projection.
85 *
86 * Transform pixel coordinate via a projection that maps one rectangle
87 * onto another rectangle. The source rectangle must have both dimensions
88 * greater than one.
89 *
90 * @param a Pixel coordinates
91 * @param srect Source rectangle
92 * @param drect Destination rectangle
93 * @param d Place to store resulting coordinates.
94 */
95void gfx_coord2_project(gfx_coord2_t *a, gfx_rect_t *srect, gfx_rect_t *drect,
96 gfx_coord2_t *d)
97{
98 gfx_rect_t sr;
99 gfx_rect_t dr;
100
101 gfx_rect_points_sort(srect, &sr);
102 gfx_rect_points_sort(drect, &dr);
103
104 d->x = dr.p0.x + (a->x - sr.p0.x) * (dr.p1.x - dr.p0.x - 1) /
105 (sr.p1.x - sr.p0.x - 1);
106 d->y = dr.p0.y + (a->y - sr.p0.y) * (dr.p1.y - dr.p0.y - 1) /
107 (sr.p1.y - sr.p0.y - 1);
108}
109
110/** Sort points of a span.
111 *
112 * Sort the begin and end points so that the begin point has the lower
113 * coordinate (i.e. if needed, the span is transposed, if not, it is simply
114 * copied).
115 *
116 * @param s0 Source span start point
117 * @param s1 Source span end point
118 * @param d0 Destination span start point
119 * @param d1 Destination span end point
120 */
121void gfx_span_points_sort(gfx_coord_t s0, gfx_coord_t s1, gfx_coord_t *d0,
122 gfx_coord_t *d1)
123{
124 if (s0 <= s1) {
125 *d0 = s0;
126 *d1 = s1;
127 } else {
128 *d0 = s1 + 1;
129 *d1 = s0 + 1;
130 }
131}
132
133/** Move (translate) rectangle.
134 *
135 * @param trans Translation offset
136 * @param src Source rectangle
137 * @param dest Destination rectangle
138 */
139void gfx_rect_translate(gfx_coord2_t *trans, gfx_rect_t *src, gfx_rect_t *dest)
140{
141 gfx_coord2_add(&src->p0, trans, &dest->p0);
142 gfx_coord2_add(&src->p1, trans, &dest->p1);
143}
144
145/** Reverse move (translate) rectangle.
146 *
147 * @param trans Translation offset
148 * @param src Source rectangle
149 * @param dest Destination rectangle
150 */
151void gfx_rect_rtranslate(gfx_coord2_t *trans, gfx_rect_t *src, gfx_rect_t *dest)
152{
153 gfx_coord2_subtract(&src->p0, trans, &dest->p0);
154 gfx_coord2_subtract(&src->p1, trans, &dest->p1);
155}
156
157/** Compute envelope of two rectangles.
158 *
159 * Envelope is the minimal rectangle covering all pixels of both rectangles.
160 *
161 * @param a First rectangle
162 * @param b Second rectangle
163 * @param dest Place to store enveloping rectangle
164 */
165void gfx_rect_envelope(gfx_rect_t *a, gfx_rect_t *b, gfx_rect_t *dest)
166{
167 gfx_rect_t sa, sb;
168
169 if (gfx_rect_is_empty(a)) {
170 *dest = *b;
171 return;
172 }
173
174 if (gfx_rect_is_empty(b)) {
175 *dest = *a;
176 return;
177 }
178
179 /* a and b are both non-empty */
180
181 gfx_rect_points_sort(a, &sa);
182 gfx_rect_points_sort(b, &sb);
183
184 dest->p0.x = min(sa.p0.x, sb.p0.x);
185 dest->p0.y = min(sa.p0.y, sb.p0.y);
186 dest->p1.x = max(sa.p1.x, sb.p1.x);
187 dest->p1.y = max(sa.p1.y, sb.p1.y);
188}
189
190/** Compute intersection of two rectangles.
191 *
192 * If the two rectangles do not intersect, the result will be an empty
193 * rectangle (check with gfx_rect_is_empty()). The resulting rectangle
194 * is always sorted.
195 *
196 * @param rect Source rectangle
197 * @param clip Clipping rectangle
198 * @param dest Place to store clipped rectangle
199 */
200void gfx_rect_clip(gfx_rect_t *rect, gfx_rect_t *clip, gfx_rect_t *dest)
201{
202 gfx_rect_t srect, sclip;
203
204 gfx_rect_points_sort(rect, &srect);
205 gfx_rect_points_sort(clip, &sclip);
206
207 dest->p0.x = min(max(srect.p0.x, sclip.p0.x), sclip.p1.x);
208 dest->p0.y = min(max(srect.p0.y, sclip.p0.y), sclip.p1.y);
209 dest->p1.x = max(sclip.p0.x, min(srect.p1.x, sclip.p1.x));
210 dest->p1.y = max(sclip.p0.y, min(srect.p1.y, sclip.p1.y));
211}
212
213/** Sort points of a rectangle.
214 *
215 * Shuffle around coordinates of a rectangle so that p0.x < p1.x and
216 * p0.y < p0.y.
217 *
218 * @param src Source rectangle
219 * @param dest Destination (sorted) rectangle
220 */
221void gfx_rect_points_sort(gfx_rect_t *src, gfx_rect_t *dest)
222{
223 gfx_span_points_sort(src->p0.x, src->p1.x, &dest->p0.x, &dest->p1.x);
224 gfx_span_points_sort(src->p0.y, src->p1.y, &dest->p0.y, &dest->p1.y);
225}
226
227/** Determine if rectangle contains no pixels
228 *
229 * @param rect Rectangle
230 * @return @c true iff rectangle contains no pixels
231 */
232bool gfx_rect_is_empty(gfx_rect_t *rect)
233{
234 return rect->p0.x == rect->p1.x || rect->p0.y == rect->p1.y;
235}
236
237/** Return true if pixel at coordinate @a coord lies within rectangle @a rect. */
238bool gfx_pix_inside_rect(gfx_coord2_t *coord, gfx_rect_t *rect)
239{
240 gfx_rect_t sr;
241
242 gfx_rect_points_sort(rect, &sr);
243
244 if (coord->x < sr.p0.x || coord->y < sr.p0.y)
245 return false;
246
247 if (coord->x >= sr.p1.x || coord->y >= sr.p1.y)
248 return false;
249
250 return true;
251}
252
253/** @}
254 */
Note: See TracBrowser for help on using the repository browser.