Some more wipes, added radial wipes
[platform/upstream/gst-plugins-good.git] / gst / smpte / paint.c
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., 59 Temple Place - Suite 330,
17  * Boston, MA 02111-1307, USA.
18  */
19
20 #include <math.h>
21 #include "paint.h"
22
23 void
24 gst_smpte_paint_vbox (guint32 *dest, gint stride, 
25                       gint x0, gint y0, gint c0, 
26                       gint x1, gint y1, gint c1)
27 {
28   gint i, j;
29   gint width, height;
30
31   width = x1 - x0;
32   height = y1 - y0;
33   
34   g_assert (width > 0);
35   g_assert (height > 0);
36
37   dest = dest + y0 * stride + x0;
38         
39   for (i = 0; i < height; i++) {
40     for (j = 0; j < width; j++) {
41       dest[j] = (c1 * j + c0 * (width - j)) / width;
42     }
43     dest += stride;
44   }
45 }
46
47 void
48 gst_smpte_paint_hbox (guint32 *dest, gint stride, 
49                       gint x0, gint y0, gint c0, 
50                       gint x1, gint y1, gint c1)
51 {
52   gint i, j;
53   gint width, height;
54
55   width = x1 - x0;
56   height = y1 - y0;
57   
58   g_assert (width > 0);
59   g_assert (height > 0);
60
61   g_print ("vbox: %d %d %d %d %d %d\n", x0, y0, c0, x1, y1, c1);
62
63   dest = dest + y0 * stride + x0;
64
65   for (i = 0; i < height; i++) {
66     guint32 value  = (c1 * i + c0 * (height - i)) / height;
67     for (j = 0; j < width; j++) {
68       dest[j] = value;
69     }
70     dest += stride;
71   }
72 }
73
74 #define STEP_3D_LINE(dxabs,dyabs,dzabs,sdx,sdy,sdz,xr,yr,zr,px,py,pz)           \
75 G_STMT_START {                                          \
76   if (dxabs >= dyabs && dxabs >= dzabs) {               \
77     yr += dyabs;                                        \
78     zr += dzabs;                                        \
79     if (yr >= dxabs) {                                  \
80       py += sdy;                                        \
81       yr -= dxabs;                                      \
82     }                                                   \
83     if (zr >= dzabs) {                                  \
84       pz += sdz;                                        \
85       zr -= dxabs;                                      \
86     }                                                   \
87     px += sdx;                                          \
88   } else if (dyabs >= dxabs && dyabs >= dzabs) {        \
89     xr += dxabs;                                        \
90     zr += dzabs;                                        \
91     if (xr >= dyabs) {                                  \
92       px += sdx;                                        \
93       xr -= dyabs;                                      \
94     }                                                   \
95     if (zr >= dzabs) {                                  \
96       pz += sdz;                                        \
97       zr -= dyabs;                                      \
98     }                                                   \
99     py += sdy;                                          \
100   } else {                                              \
101     yr += dyabs;                                        \
102     xr += dxabs;                                        \
103     if (yr >= dyabs) {                                  \
104       py += sdy;                                        \
105       yr -= dzabs;                                      \
106     }                                                   \
107     if (xr >= dyabs) {                                  \
108       px += sdx;                                        \
109       xr -= dzabs;                                      \
110     }                                                   \
111     pz += sdz;                                          \
112   }                                                     \
113 } G_STMT_END
114
115 #define SWAP(a,b)               \
116 G_STMT_START {                  \
117   typeof (a) tmp;               \
118   tmp = (a);                    \
119   (a) = (b);                    \
120   (b) = (tmp);                  \
121 } G_STMT_END
122
123 #define SIGN(a) ((a) < 0 ? -1 : 1)
124
125 #define PREPARE_3D_LINE(x0,y0,z0,x1,y1,z1,dxabs,dyabs,dzabs,sdx,sdy,sdz,xr,yr,zr,px,py,pz)\
126 G_STMT_START {                  \
127   typeof (x0) dx, dy, dz;       \
128   dx = x1 - x0;                 \
129   dy = y1 - y0;                 \
130   dz = z1 - z0;                 \
131   dxabs = abs (dx);             \
132   dyabs = abs (dy);             \
133   dzabs = abs (dz);             \
134   sdx = SIGN (dx);              \
135   sdy = SIGN (dy);              \
136   sdz = SIGN (dz);              \
137   xr = dxabs >> 1;              \
138   yr = dyabs >> 1;              \
139   zr = dzabs >> 1;              \
140   px = x0;                      \
141   py = y0;                      \
142   pz = z0;                      \
143 } G_STMT_END
144
145 void
146 gst_smpte_paint_triangle_linear (guint32 *dest, gint stride,
147                                  gint x0, gint y0, gint c0,
148                                  gint x1, gint y1, gint c1, gint x2, gint y2, gint c2)
149 {
150   gint sdxl, sdyl, sdcl, dxlabs, dylabs, dclabs, xrl, yrl, crl, pxl, pyl, pcl;
151   gint sdxr, sdyr, sdcr, dxrabs, dyrabs, dcrabs, xrr, yrr, crr, pxr, pyr, pcr;
152   gint i, j, k, seg_start, seg_end;
153
154   if (y0 > y1) { SWAP (x0, x1); SWAP (y0, y1); SWAP (c0, c1); }
155   if (y0 > y2) { SWAP (x0, x2); SWAP (y0, y2); SWAP (c0, c2); }
156   if (y1 > y2) { SWAP (x1, x2); SWAP (y1, y2); SWAP (c1, c2); }
157   
158   PREPARE_3D_LINE (x0,y0,c0,x2,y2,c2,
159                    dxlabs,dylabs,dclabs,
160                    sdxl, sdyl,sdcl,
161                    xrl,yrl,crl,
162                    pxl,pyl,pcl);
163
164   PREPARE_3D_LINE (x0,y0,c0,x1,y1,c1,
165                    dxrabs,dyrabs,dcrabs,
166                    sdxr, sdyr,sdcr,
167                    xrr,yrr,crr,
168                    pxr,pyr,pcr);
169
170   dest = dest + stride * y0;
171   seg_start = y0;
172   seg_end = y1;
173
174   /* do two passes */
175   for (k = 0; k < 2; k++) {
176     for (i = seg_start; i < seg_end; i++) {
177       gint s = pxl, e = pxr, sc = pcl, ec = pcr;
178       gint sign = SIGN (e - s);
179
180       e += sign;
181       for (j = s; j != e; j+=sign) {
182        dest[j] = (ec * (j - s) + sc * (e - j)) / (e - s);
183       }
184
185       while (pyr == i) {
186         STEP_3D_LINE (dxrabs, dyrabs, dcrabs, sdxr, sdyr, sdcr, 
187                       xrr, yrr, crr, pxr, pyr, pcr);
188       }
189       while (pyl == i) {
190         STEP_3D_LINE (dxlabs, dylabs, dclabs, sdxl, sdyl, sdcl, 
191                       xrl, yrl, crl, pxl, pyl, pcl);
192       }
193       dest += stride;
194     }
195
196     PREPARE_3D_LINE (x1,y1,c1,x2,y2,c2,
197                      dxrabs,dyrabs,dcrabs,
198                      sdxr, sdyr,sdcr,
199                      xrr,yrr,crr,
200                      pxr,pyr,pcr);
201
202     seg_start = y1;
203     seg_end = y2;
204   }
205 }
206
207
208 void 
209 draw_line (guint32* dest, gint stride, int x, int y, int x2, int y2, int col) 
210 {
211   gboolean yLonger=FALSE;
212   int incrementVal, endVal;
213   gdouble decInc;
214   int shortLen=y2-y;
215   int longLen=x2-x;
216   gdouble j=0.0;
217   int i;
218
219   if (abs(shortLen)>abs(longLen)) {
220     int swap=shortLen;
221     shortLen=longLen;
222     longLen=swap;
223     yLonger=TRUE;
224   }
225
226   endVal=longLen;
227   if (longLen<0) {
228     incrementVal=-1;
229     longLen=-longLen;
230   } 
231   else incrementVal=1;
232    
233   if (longLen==0) decInc=(gdouble)shortLen;
234   else decInc = ((gdouble)shortLen/(gdouble)longLen);
235   
236   if (yLonger) {
237     for (i=0;i!=endVal;i+=incrementVal) {
238       *(dest+(x+(int)j) + (y+i)*stride) = col;
239       j+=decInc;
240     }
241   } else {
242     for (i=0;i!=endVal;i+=incrementVal) {
243       *(dest+(x+i) + (y+(int)j)*stride) = col;
244       j+=decInc;
245     }
246   }
247 }
248
249 void
250 gst_smpte_paint_triangle_clock (guint32 *dest, gint stride,
251                                  gint x0, gint y0, gint c0,
252                                  gint x1, gint y1, gint c1, gint x2, gint y2, gint c2)
253 {
254   gint i;
255   gint sign;
256   gfloat angle, angle_s, angle_e;
257
258   if (x1 == x2) {
259     gfloat len1 = sqrt ((x1-x0) * (x1-x0) + (y1-y0) * (y1-y0));
260
261     sign = SIGN (y2 - y1);
262
263     angle_s = 0.0;
264     angle_e = acos (((x1-x0) * (x2-x0) + (y1-y0) * (y2-y0))/
265                     (sqrt ((x1-x0) * (x1-x0) + (y1-y0) * (y1-y0)) * 
266                      sqrt ((x2-x0) * (x2-x0) + (y2-y0) * (y2-y0))));
267
268     for (i=y1; i != y2+sign; i+=sign) {
269       gfloat len2 = sqrt ((x1-x0) * (x1-x0) + (i-y0) * (i-y0));
270       
271       if (y1==i)
272         angle = 0;
273       else
274         angle = acos (((x1-x0) * (x2-x0) + (y1-y0) * (i-y0))/ (len1 * len2));
275
276       angle = angle / angle_e;
277
278       draw_line (dest, stride,
279                     x0, y0, x1, i, 
280                     (c2 * angle + c1 * (1.0-angle)));
281     }
282   }
283   else if (y1 == y2) {
284     gfloat len1 = sqrt ((x1-x0) * (x1-x0) + (y1-y0) * (y1-y0));
285
286     sign = SIGN (x2 - x1);
287
288     angle_s = 0.0;
289     angle_e = acos (((x1-x0) * (x2-x0) + (y1-y0) * (y2-y0))/
290                     (sqrt ((x1-x0) * (x1-x0) + (y1-y0) * (y1-y0)) * 
291                      sqrt ((x2-x0) * (x2-x0) + (y2-y0) * (y2-y0))));
292
293     for (i=x1; i != x2+sign; i+=sign) {
294       gfloat len2 = sqrt ((i-x0) * (i-x0) + (y2-y0) * (y2-y0));
295
296       if (x1==i)
297         angle = 0;
298       else
299         angle = acos (((x1-x0) * (i-x0) + (y1-y0) * (y2-y0)) / (len1 * len2));
300
301       angle = angle / angle_e;
302
303       draw_line (dest, stride,
304                     x0, y0, i, y1, 
305                     (c2 * angle + c1 * (1.0-angle)));
306     }
307   }
308 }