• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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