1 /* GStreamer
2 * Copyright (C) <1999> Erik Walthinsen <omega@cse.ogi.edu>
3 *
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Library General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 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 * Library General Public License for more details.
13 *
14 * You should have received a copy of the GNU Library General Public
15 * License along with this library; if not, write to the
16 * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
17 * Boston, MA 02110-1301, USA.
18 */
19
20 #ifdef HAVE_CONFIG_H
21 #include "config.h"
22 #endif
23
24 #include <math.h>
25 #include <stdlib.h>
26 #include "paint.h"
27
28 #ifndef M_PI
29 #define M_PI 3.14159265358979323846
30 #endif
31
32 void
gst_smpte_paint_vbox(guint32 * dest,gint stride,gint x0,gint y0,gint c0,gint x1,gint y1,gint c1)33 gst_smpte_paint_vbox (guint32 * dest, gint stride,
34 gint x0, gint y0, gint c0, gint x1, gint y1, gint c1)
35 {
36 gint i, j;
37 gint width, height;
38
39 width = x1 - x0;
40 height = y1 - y0;
41
42 g_assert (width > 0);
43 g_assert (height > 0);
44
45 dest = dest + y0 * stride + x0;
46
47 for (i = 0; i < height; i++) {
48 for (j = 0; j < width; j++) {
49 dest[j] = (c1 * j + c0 * (width - j)) / width;
50 }
51 dest += stride;
52 }
53 }
54
55 void
gst_smpte_paint_hbox(guint32 * dest,gint stride,gint x0,gint y0,gint c0,gint x1,gint y1,gint c1)56 gst_smpte_paint_hbox (guint32 * dest, gint stride,
57 gint x0, gint y0, gint c0, gint x1, gint y1, gint c1)
58 {
59 gint i, j;
60 gint width, height;
61
62 width = x1 - x0;
63 height = y1 - y0;
64
65 g_assert (width > 0);
66 g_assert (height > 0);
67
68 dest = dest + y0 * stride + x0;
69
70 for (i = 0; i < height; i++) {
71 guint32 value = (c1 * i + c0 * (height - i)) / height;
72
73 for (j = 0; j < width; j++) {
74 dest[j] = value;
75 }
76 dest += stride;
77 }
78 }
79
80 #define STEP_3D_LINE(dxabs,dyabs,dzabs,sdx,sdy,sdz,xr,yr,zr,px,py,pz) \
81 G_STMT_START { \
82 if (dxabs >= dyabs && dxabs >= dzabs) { \
83 yr += dyabs; \
84 zr += dzabs; \
85 if (yr >= dxabs) { \
86 py += sdy; \
87 yr -= dxabs; \
88 } \
89 if (zr >= dzabs) { \
90 pz += sdz; \
91 zr -= dxabs; \
92 } \
93 px += sdx; \
94 } else if (dyabs >= dxabs && dyabs >= dzabs) { \
95 xr += dxabs; \
96 zr += dzabs; \
97 if (xr >= dyabs) { \
98 px += sdx; \
99 xr -= dyabs; \
100 } \
101 if (zr >= dzabs) { \
102 pz += sdz; \
103 zr -= dyabs; \
104 } \
105 py += sdy; \
106 } else { \
107 yr += dyabs; \
108 xr += dxabs; \
109 if (yr >= dyabs) { \
110 py += sdy; \
111 yr -= dzabs; \
112 } \
113 if (xr >= dyabs) { \
114 px += sdx; \
115 xr -= dzabs; \
116 } \
117 pz += sdz; \
118 } \
119 } G_STMT_END
120
121 #define SWAP_INT(a,b) \
122 G_STMT_START { \
123 gint tmp; \
124 tmp = (a); \
125 (a) = (b); \
126 (b) = (tmp); \
127 } G_STMT_END
128
129 #define SIGN(a) ((a) < 0 ? -1 : 1)
130
131 #define PREPARE_3D_LINE(x0,y0,z0,x1,y1,z1,dxabs,dyabs,dzabs,sdx,sdy,sdz,xr,yr,zr,px,py,pz)\
132 G_STMT_START { \
133 gint dx, dy, dz; \
134 dx = x1 - x0; \
135 dy = y1 - y0; \
136 dz = z1 - z0; \
137 dxabs = abs (dx); \
138 dyabs = abs (dy); \
139 dzabs = abs (dz); \
140 sdx = SIGN (dx); \
141 sdy = SIGN (dy); \
142 sdz = SIGN (dz); \
143 xr = dxabs >> 1; \
144 yr = dyabs >> 1; \
145 zr = dzabs >> 1; \
146 px = x0; \
147 py = y0; \
148 pz = z0; \
149 } G_STMT_END
150
151 void
gst_smpte_paint_triangle_linear(guint32 * dest,gint stride,gint x0,gint y0,gint c0,gint x1,gint y1,gint c1,gint x2,gint y2,gint c2)152 gst_smpte_paint_triangle_linear (guint32 * dest, gint stride,
153 gint x0, gint y0, gint c0,
154 gint x1, gint y1, gint c1, gint x2, gint y2, gint c2)
155 {
156 gint sdxl, sdyl, sdcl, dxlabs, dylabs, dclabs, xrl, yrl, crl, pxl, pyl, pcl;
157 gint sdxr, sdyr, sdcr, dxrabs, dyrabs, dcrabs, xrr, yrr, crr, pxr, pyr, pcr;
158 gint i, j, k, seg_start, seg_end;
159
160 if (y0 > y1) {
161 SWAP_INT (x0, x1);
162 SWAP_INT (y0, y1);
163 SWAP_INT (c0, c1);
164 }
165 if (y0 > y2) {
166 SWAP_INT (x0, x2);
167 SWAP_INT (y0, y2);
168 SWAP_INT (c0, c2);
169 }
170 if (y1 > y2) {
171 SWAP_INT (x1, x2);
172 SWAP_INT (y1, y2);
173 SWAP_INT (c1, c2);
174 }
175
176 PREPARE_3D_LINE (x0, y0, c0, x2, y2, c2,
177 dxlabs, dylabs, dclabs, sdxl, sdyl, sdcl, xrl, yrl, crl, pxl, pyl, pcl);
178
179 PREPARE_3D_LINE (x0, y0, c0, x1, y1, c1,
180 dxrabs, dyrabs, dcrabs, sdxr, sdyr, sdcr, xrr, yrr, crr, pxr, pyr, pcr);
181
182 dest = dest + stride * y0;
183 seg_start = y0;
184 seg_end = y1;
185
186 /* do two passes */
187 for (k = 0; k < 2; k++) {
188 for (i = seg_start; i < seg_end; i++) {
189 gint s = pxl, e = pxr, sc = pcl, ec = pcr;
190 gint sign = SIGN (e - s);
191
192 e += sign;
193 for (j = s; j != e; j += sign) {
194 dest[j] = (ec * (j - s) + sc * (e - j)) / (e - s);
195 }
196
197 while (pyr == i) {
198 STEP_3D_LINE (dxrabs, dyrabs, dcrabs, sdxr, sdyr, sdcr,
199 xrr, yrr, crr, pxr, pyr, pcr);
200 }
201 while (pyl == i) {
202 STEP_3D_LINE (dxlabs, dylabs, dclabs, sdxl, sdyl, sdcl,
203 xrl, yrl, crl, pxl, pyl, pcl);
204 }
205 dest += stride;
206 }
207
208 PREPARE_3D_LINE (x1, y1, c1, x2, y2, c2,
209 dxrabs, dyrabs, dcrabs, sdxr, sdyr, sdcr, xrr, yrr, crr, pxr, pyr, pcr);
210
211 seg_start = y1;
212 seg_end = y2;
213 }
214 }
215
216 static void
draw_bresenham_line(guint32 * dest,gint stride,gint x0,gint y0,gint x1,gint y1,guint32 col)217 draw_bresenham_line (guint32 * dest, gint stride,
218 gint x0, gint y0, gint x1, gint y1, guint32 col)
219 {
220 gint dx, dy;
221 gint x_incr, y_incr;
222 gint i, dpr, dpru, P, indep;
223
224 dx = abs (x1 - x0);
225 dy = abs (y1 - y0);
226
227 dest = dest + y0 * stride + x0;
228
229 x_incr = SIGN (x1 - x0);
230 y_incr = SIGN (y1 - y0) * stride;
231
232 if (dx >= dy) {
233 dpr = dy << 1;
234 i = dx;
235 indep = x_incr;
236 } else {
237 dpr = dx << 1;
238 i = dy;
239 indep = y_incr;
240 }
241
242 dpru = dpr - (i << 1);
243 P = dpr - i;
244
245 for (; i >= 0; i--) {
246 *dest = col;
247
248 if (P > 0) {
249 dest += x_incr;
250 dest += y_incr;
251 P += dpru;
252 } else {
253 dest += indep;
254 P += dpr;
255 }
256 }
257 }
258
259 void
gst_smpte_paint_triangle_clock(guint32 * dest,gint stride,gint x0,gint y0,gint c0,gint x1,gint y1,gint c1,gint x2,gint y2,gint c2)260 gst_smpte_paint_triangle_clock (guint32 * dest, gint stride,
261 gint x0, gint y0, gint c0,
262 gint x1, gint y1, gint c1, gint x2, gint y2, gint c2)
263 {
264 gint i;
265 gint sign;
266 gfloat angle, angle_e;
267 gfloat len1;
268
269 angle_e = acos (((x1 - x0) * (x2 - x0) + (y1 - y0) * (y2 - y0)) /
270 (sqrt ((x1 - x0) * (x1 - x0) + (y1 - y0) * (y1 - y0)) *
271 sqrt ((x2 - x0) * (x2 - x0) + (y2 - y0) * (y2 - y0))));
272
273 len1 = sqrt ((x1 - x0) * (x1 - x0) + (y1 - y0) * (y1 - y0));
274
275 if (x1 == x2) {
276 sign = SIGN (y2 - y1);
277
278 for (i = y1; i != (y2 + sign); i += sign) {
279 if (y1 == i)
280 angle = 0;
281 else
282 angle = acos (((x1 - x0) * (x2 - x0) + (y1 - y0) * (i - y0)) /
283 (len1 * sqrt ((x1 - x0) * (x1 - x0) + (i - y0) * (i -
284 y0)))) / angle_e;
285
286 draw_bresenham_line (dest, stride,
287 x0, y0, x1, i, (c2 * angle + c1 * (1.0 - angle)));
288 }
289 } else if (y1 == y2) {
290 sign = SIGN (x2 - x1);
291
292 for (i = x1; i != (x2 + sign); i += sign) {
293 if (x1 == i)
294 angle = 0;
295 else
296 angle = acos (((x1 - x0) * (i - x0) + (y1 - y0) * (y2 - y0)) /
297 (len1 * sqrt ((i - x0) * (i - x0) + (y2 - y0) * (y2 -
298 y0)))) / angle_e;
299
300 draw_bresenham_line (dest, stride,
301 x0, y0, i, y1, (c2 * angle + c1 * (1.0 - angle)));
302 }
303 } else {
304 g_warning ("paint triangle clock: not supported");
305 return;
306 }
307 }
308
309 void
gst_smpte_paint_box_clock(guint32 * dest,gint stride,gint x0,gint y0,gint c0,gint x1,gint y1,gint c1,gint x2,gint y2,gint c2)310 gst_smpte_paint_box_clock (guint32 * dest, gint stride,
311 gint x0, gint y0, gint c0,
312 gint x1, gint y1, gint c1, gint x2, gint y2, gint c2)
313 {
314 gfloat angle_m, col_m;
315 gint xv, yv;
316
317 if (x1 == x0) {
318 xv = x2;
319 yv = y1;
320 } else if (y1 == y0) {
321 xv = x1;
322 yv = y2;
323 } else {
324 g_warning ("paint box clock: not supported");
325 return;
326 }
327
328 angle_m = 2 * acos (((x1 - x0) * (xv - x0) + (y1 - y0) * (yv - y0)) /
329 (sqrt ((x1 - x0) * (x1 - x0) + (y1 - y0) * (y1 - y0)) *
330 sqrt ((xv - x0) * (xv - x0) + (yv - y0) * (yv - y0)))) / M_PI;
331
332 col_m = c2 * angle_m + c1 * (1.0 - angle_m);
333
334 gst_smpte_paint_triangle_clock (dest, stride,
335 x0, y0, c0, x1, y1, c1, xv, yv, col_m);
336 gst_smpte_paint_triangle_clock (dest, stride,
337 x0, y0, c0, xv, yv, col_m, x2, y2, c2);
338 }
339