Branch data Line data Source code
1 : : /*
2 : : * This file is part of libplacebo.
3 : : *
4 : : * libplacebo 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 : : * libplacebo 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 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 libplacebo. If not, see <http://www.gnu.org/licenses/>.
16 : : */
17 : :
18 : : #ifndef LIBPLACEBO_COMMON_H_
19 : : #define LIBPLACEBO_COMMON_H_
20 : :
21 : : #include <stdbool.h>
22 : :
23 : : #include <libplacebo/config.h>
24 : :
25 : : PL_API_BEGIN
26 : :
27 : : // Some common utility types. These are overloaded to support 2D, 3D and
28 : : // integer/float variants.
29 : : typedef struct pl_rect2d {
30 : : int x0, y0;
31 : : int x1, y1;
32 : : } pl_rect2d;
33 : :
34 : : typedef struct pl_rect3d {
35 : : int x0, y0, z0;
36 : : int x1, y1, z1;
37 : : } pl_rect3d;
38 : :
39 : : typedef struct pl_rect2df {
40 : : float x0, y0;
41 : : float x1, y1;
42 : : } pl_rect2df;
43 : :
44 : : typedef struct pl_rect3df {
45 : : float x0, y0, z0;
46 : : float x1, y1, z1;
47 : : } pl_rect3df;
48 : :
49 : : // These macros will work for any of the above pl_rect variants (with enough
50 : : // dimensions). Careful: double-evaluation hazard
51 : : #define pl_rect_w(r) ((r).x1 - (r).x0)
52 : : #define pl_rect_h(r) ((r).y1 - (r).y0)
53 : : #define pl_rect_d(r) ((r).z1 - (r).z0)
54 : :
55 : : #define pl_rect2d_eq(a, b) \
56 : : ((a).x0 == (b).x0 && (a).x1 == (b).x1 && \
57 : : (a).y0 == (b).y0 && (a).y1 == (b).y1)
58 : :
59 : : #define pl_rect3d_eq(a, b) \
60 : : ((a).x0 == (b).x0 && (a).x1 == (b).x1 && \
61 : : (a).y0 == (b).y0 && (a).y1 == (b).y1 && \
62 : : (a).z0 == (b).z0 && (a).z1 == (b).z1)
63 : :
64 : : // "Normalize" a rectangle: This ensures d1 >= d0 for all dimensions.
65 : : PL_API void pl_rect2d_normalize(pl_rect2d *rc);
66 : : PL_API void pl_rect3d_normalize(pl_rect3d *rc);
67 : :
68 : : PL_API void pl_rect2df_normalize(pl_rect2df *rc);
69 : : PL_API void pl_rect3df_normalize(pl_rect3df *rc);
70 : :
71 : : // Return the rounded form of a rect.
72 : : PL_API pl_rect2d pl_rect2df_round(const pl_rect2df *rc);
73 : : PL_API pl_rect3d pl_rect3df_round(const pl_rect3df *rc);
74 : :
75 : : // Represents a row-major matrix, i.e. the following matrix
76 : : // [ a11 a12 a13 ]
77 : : // [ a21 a22 a23 ]
78 : : // [ a31 a32 a33 ]
79 : : // is represented in C like this:
80 : : // { { a11, a12, a13 },
81 : : // { a21, a22, a23 },
82 : : // { a31, a32, a33 } };
83 : : typedef struct pl_matrix3x3 {
84 : : float m[3][3];
85 : : } pl_matrix3x3;
86 : :
87 : : PL_API extern const pl_matrix3x3 pl_matrix3x3_identity;
88 : :
89 : : // Applies a matrix to a float vector in-place.
90 : : PL_API void pl_matrix3x3_apply(const pl_matrix3x3 *mat, float vec[3]);
91 : :
92 : : // Applies a matrix to a pl_rect3df
93 : : PL_API void pl_matrix3x3_apply_rc(const pl_matrix3x3 *mat, pl_rect3df *rc);
94 : :
95 : : // Scales a color matrix by a linear factor.
96 : : PL_API void pl_matrix3x3_scale(pl_matrix3x3 *mat, float scale);
97 : :
98 : : // Inverts a matrix. Only use where precision is not that important.
99 : : PL_API void pl_matrix3x3_invert(pl_matrix3x3 *mat);
100 : :
101 : : // Composes/multiplies two matrices. Multiples B into A, i.e.
102 : : // A := A * B
103 : : PL_API void pl_matrix3x3_mul(pl_matrix3x3 *a, const pl_matrix3x3 *b);
104 : :
105 : : // Flipped version of `pl_matrix3x3_mul`.
106 : : // B := A * B
107 : : PL_API void pl_matrix3x3_rmul(const pl_matrix3x3 *a, pl_matrix3x3 *b);
108 : :
109 : : // Represents an affine transformation, which is basically a 3x3 matrix
110 : : // together with a column vector to add onto the output.
111 : : typedef struct pl_transform3x3 {
112 : : pl_matrix3x3 mat;
113 : : float c[3];
114 : : } pl_transform3x3;
115 : :
116 : : PL_API extern const pl_transform3x3 pl_transform3x3_identity;
117 : :
118 : : // Applies a transform to a float vector in-place.
119 : : PL_API void pl_transform3x3_apply(const pl_transform3x3 *t, float vec[3]);
120 : :
121 : : // Applies a transform to a pl_rect3df
122 : : PL_API void pl_transform3x3_apply_rc(const pl_transform3x3 *t, pl_rect3df *rc);
123 : :
124 : : // Scales the output of a transform by a linear factor. Since an affine
125 : : // transformation is non-linear, this does not commute. If you want to scale
126 : : // the *input* of a transform, use pl_matrix3x3_scale on `t.mat`.
127 : : PL_API void pl_transform3x3_scale(pl_transform3x3 *t, float scale);
128 : :
129 : : // Inverts a transform. Only use where precision is not that important.
130 : : PL_API void pl_transform3x3_invert(pl_transform3x3 *t);
131 : :
132 : : // 2D analog of the above structs. Since these are featured less prominently,
133 : : // we omit some of the other helper functions.
134 : : typedef struct pl_matrix2x2 {
135 : : float m[2][2];
136 : : } pl_matrix2x2;
137 : :
138 : : PL_API extern const pl_matrix2x2 pl_matrix2x2_identity;
139 : : PL_API pl_matrix2x2 pl_matrix2x2_rotation(float angle);
140 : :
141 : : PL_API void pl_matrix2x2_apply(const pl_matrix2x2 *mat, float vec[2]);
142 : : PL_API void pl_matrix2x2_apply_rc(const pl_matrix2x2 *mat, pl_rect2df *rc);
143 : :
144 : : PL_API void pl_matrix2x2_mul(pl_matrix2x2 *a, const pl_matrix2x2 *b);
145 : : PL_API void pl_matrix2x2_rmul(const pl_matrix2x2 *a, pl_matrix2x2 *b);
146 : :
147 : : PL_API void pl_matrix2x2_scale(pl_matrix2x2 *mat, float scale);
148 : : PL_API void pl_matrix2x2_invert(pl_matrix2x2 *mat);
149 : :
150 : : typedef struct pl_transform2x2 {
151 : : pl_matrix2x2 mat;
152 : : float c[2];
153 : : } pl_transform2x2;
154 : :
155 : : PL_API extern const pl_transform2x2 pl_transform2x2_identity;
156 : :
157 : : PL_API void pl_transform2x2_apply(const pl_transform2x2 *t, float vec[2]);
158 : : PL_API void pl_transform2x2_apply_rc(const pl_transform2x2 *t, pl_rect2df *rc);
159 : :
160 : : PL_API void pl_transform2x2_mul(pl_transform2x2 *a, const pl_transform2x2 *b);
161 : : PL_API void pl_transform2x2_rmul(const pl_transform2x2 *a, pl_transform2x2 *b);
162 : :
163 : : PL_API void pl_transform2x2_scale(pl_transform2x2 *t, float scale);
164 : : PL_API void pl_transform2x2_invert(pl_transform2x2 *t);
165 : :
166 : : // Compute new bounding box of a transformation (as applied to a given rect).
167 : : PL_API pl_rect2df pl_transform2x2_bounds(const pl_transform2x2 *t,
168 : : const pl_rect2df *rc);
169 : :
170 : : // Helper functions for dealing with aspect ratios and stretched/scaled rects.
171 : :
172 : : // Return the (absolute) aspect ratio (width/height) of a given pl_rect2df.
173 : : // This will always be a positive number, even if `rc` is flipped.
174 : : PL_API float pl_rect2df_aspect(const pl_rect2df *rc);
175 : :
176 : : // Set the aspect of a `rc` to a given aspect ratio with an extra 'panscan'
177 : : // factor choosing the balance between shrinking and growing the `rc` to meet
178 : : // this aspect ratio.
179 : : //
180 : : // Notes:
181 : : // - If `panscan` is 0.0, this function will only ever shrink the `rc`.
182 : : // - If `panscan` is 1.0, this function will only ever grow the `rc`.
183 : : // - If `panscan` is 0.5, this function is area-preserving.
184 : : PL_API void pl_rect2df_aspect_set(pl_rect2df *rc, float aspect, float panscan);
185 : :
186 : : // Set one rect's aspect to that of another
187 : : #define pl_rect2df_aspect_copy(rc, src, panscan) \
188 : : pl_rect2df_aspect_set((rc), pl_rect2df_aspect(src), (panscan))
189 : :
190 : : // 'Fit' one rect inside another. `rc` will be set to the same size and aspect
191 : : // ratio as `src`, but with the size limited to fit inside the original `rc`.
192 : : // Like `pl_rect2df_aspect_set`, `panscan` controls the pan&scan factor.
193 : : PL_API void pl_rect2df_aspect_fit(pl_rect2df *rc, const pl_rect2df *src, float panscan);
194 : :
195 : : // Scale rect in each direction while keeping it centered.
196 : : PL_API void pl_rect2df_stretch(pl_rect2df *rc, float stretch_x, float stretch_y);
197 : :
198 : : // Offset rect by an arbitrary offset factor. If the corresponding dimension
199 : : // of a rect is flipped, so too is the applied offset.
200 : : PL_API void pl_rect2df_offset(pl_rect2df *rc, float offset_x, float offset_y);
201 : :
202 : : // Scale a rect uniformly in both dimensions.
203 : : #define pl_rect2df_zoom(rc, zoom) pl_rect2df_stretch((rc), (zoom), (zoom))
204 : :
205 : : // Rotation in degrees clockwise
206 : : typedef int pl_rotation;
207 : : enum {
208 : : PL_ROTATION_0 = 0,
209 : : PL_ROTATION_90 = 1,
210 : : PL_ROTATION_180 = 2,
211 : : PL_ROTATION_270 = 3,
212 : : PL_ROTATION_360 = 4, // equivalent to PL_ROTATION_0
213 : :
214 : : // Note: Values outside the range [0,4) are legal, including negatives.
215 : : };
216 : :
217 : : // Constrains to the interval [PL_ROTATION_0, PL_ROTATION_360).
218 : : static inline pl_rotation pl_rotation_normalize(pl_rotation rot)
219 : : {
220 [ + + ]: 4610 : return (rot % PL_ROTATION_360 + PL_ROTATION_360) % PL_ROTATION_360;
221 : : }
222 : :
223 : : // Rotates the coordinate system of a `pl_rect2d(f)` in a certain direction.
224 : : // For example, calling this with PL_ROTATION_90 will correspond to rotating
225 : : // the coordinate system 90° to the right (so the x axis becomes the y axis).
226 : : //
227 : : // The resulting rect is re-normalized in the same coordinate system.
228 : : PL_API void pl_rect2df_rotate(pl_rect2df *rc, pl_rotation rot);
229 : :
230 : : // Returns the aspect ratio in a rotated frame of reference.
231 : : static inline float pl_aspect_rotate(float aspect, pl_rotation rot)
232 : : {
233 : : return (rot % PL_ROTATION_180) ? 1.0 / aspect : aspect;
234 : : }
235 : :
236 : : #define pl_rect2df_aspect_set_rot(rc, aspect, rot, panscan) \
237 : : pl_rect2df_aspect_set((rc), pl_aspect_rotate((aspect), (rot)), (panscan))
238 : :
239 : : #define pl_rect2df_aspect_copy_rot(rc, src, panscan, rot) \
240 : : pl_rect2df_aspect_set_rot((rc), pl_rect2df_aspect(src), (rot), (panscan))
241 : :
242 : : PL_API_END
243 : :
244 : : #endif // LIBPLACEBO_COMMON_H_
|