paint.c 9.54 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
/* GStreamer
 * Copyright (C) <1999> Erik Walthinsen <omega@cse.ogi.edu>
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Library General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Library General Public License for more details.
 *
 * You should have received a copy of the GNU Library General Public
 * License along with this library; if not, write to the
 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
 * Boston, MA 02111-1307, USA.
 */

20 21 22 23
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif

24
#include <math.h>
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
25
#include <stdlib.h>
26 27
#include "paint.h"

28 29 30 31
#ifndef M_PI
#define M_PI  3.14159265358979323846
#endif

32
void
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
33 34
gst_smpte_paint_vbox (guint32 * dest, gint stride,
    gint x0, gint y0, gint c0, gint x1, gint y1, gint c1)
35 36 37 38 39 40
{
  gint i, j;
  gint width, height;

  width = x1 - x0;
  height = y1 - y0;
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
41

42 43 44 45
  g_assert (width > 0);
  g_assert (height > 0);

  dest = dest + y0 * stride + x0;
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
46

47 48 49 50 51 52 53 54 55
  for (i = 0; i < height; i++) {
    for (j = 0; j < width; j++) {
      dest[j] = (c1 * j + c0 * (width - j)) / width;
    }
    dest += stride;
  }
}

void
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
56 57
gst_smpte_paint_hbox (guint32 * dest, gint stride,
    gint x0, gint y0, gint c0, gint x1, gint y1, gint c1)
58 59 60 61 62 63
{
  gint i, j;
  gint width, height;

  width = x1 - x0;
  height = y1 - y0;
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
64

65 66 67 68 69 70
  g_assert (width > 0);
  g_assert (height > 0);

  dest = dest + y0 * stride + x0;

  for (i = 0; i < height; i++) {
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
71 72
    guint32 value = (c1 * i + c0 * (height - i)) / height;

73
    for (j = 0; j < width; j++) {
74
      dest[j] = value;
75
    }
76
    dest += stride;
77 78 79
  }
}

Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118
#define STEP_3D_LINE(dxabs,dyabs,dzabs,sdx,sdy,sdz,xr,yr,zr,px,py,pz)           \
G_STMT_START {                                          \
  if (dxabs >= dyabs && dxabs >= dzabs) {               \
    yr += dyabs;                                        \
    zr += dzabs;                                        \
    if (yr >= dxabs) {                                  \
      py += sdy;                                        \
      yr -= dxabs;                                      \
    }                                                   \
    if (zr >= dzabs) {                                  \
      pz += sdz;                                        \
      zr -= dxabs;                                      \
    }                                                   \
    px += sdx;                                          \
  } else if (dyabs >= dxabs && dyabs >= dzabs) {        \
    xr += dxabs;                                        \
    zr += dzabs;                                        \
    if (xr >= dyabs) {                                  \
      px += sdx;                                        \
      xr -= dyabs;                                      \
    }                                                   \
    if (zr >= dzabs) {                                  \
      pz += sdz;                                        \
      zr -= dyabs;                                      \
    }                                                   \
    py += sdy;                                          \
  } else {                                              \
    yr += dyabs;                                        \
    xr += dxabs;                                        \
    if (yr >= dyabs) {                                  \
      py += sdy;                                        \
      yr -= dzabs;                                      \
    }                                                   \
    if (xr >= dyabs) {                                  \
      px += sdx;                                        \
      xr -= dzabs;                                      \
    }                                                   \
    pz += sdz;                                          \
  }                                                     \
119 120
} G_STMT_END

Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
121 122 123 124 125 126
#define SWAP_INT(a,b)           \
G_STMT_START {                  \
  gint tmp;                     \
  tmp = (a);                    \
  (a) = (b);                    \
  (b) = (tmp);                  \
127 128 129 130 131
} G_STMT_END

#define SIGN(a) ((a) < 0 ? -1 : 1)

#define PREPARE_3D_LINE(x0,y0,z0,x1,y1,z1,dxabs,dyabs,dzabs,sdx,sdy,sdz,xr,yr,zr,px,py,pz)\
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148
G_STMT_START {                  \
  gint dx, dy, dz;              \
  dx = x1 - x0;                 \
  dy = y1 - y0;                 \
  dz = z1 - z0;                 \
  dxabs = abs (dx);             \
  dyabs = abs (dy);             \
  dzabs = abs (dz);             \
  sdx = SIGN (dx);              \
  sdy = SIGN (dy);              \
  sdz = SIGN (dz);              \
  xr = dxabs >> 1;              \
  yr = dyabs >> 1;              \
  zr = dzabs >> 1;              \
  px = x0;                      \
  py = y0;                      \
  pz = z0;                      \
149 150 151
} G_STMT_END

void
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
152 153 154
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)
155 156 157 158 159
{
  gint sdxl, sdyl, sdcl, dxlabs, dylabs, dclabs, xrl, yrl, crl, pxl, pyl, pcl;
  gint sdxr, sdyr, sdcr, dxrabs, dyrabs, dcrabs, xrr, yrr, crr, pxr, pyr, pcr;
  gint i, j, k, seg_start, seg_end;

Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180
  if (y0 > y1) {
    SWAP_INT (x0, x1);
    SWAP_INT (y0, y1);
    SWAP_INT (c0, c1);
  }
  if (y0 > y2) {
    SWAP_INT (x0, x2);
    SWAP_INT (y0, y2);
    SWAP_INT (c0, c2);
  }
  if (y1 > y2) {
    SWAP_INT (x1, x2);
    SWAP_INT (y1, y2);
    SWAP_INT (c1, c2);
  }

  PREPARE_3D_LINE (x0, y0, c0, x2, y2, c2,
      dxlabs, dylabs, dclabs, sdxl, sdyl, sdcl, xrl, yrl, crl, pxl, pyl, pcl);

  PREPARE_3D_LINE (x0, y0, c0, x1, y1, c1,
      dxrabs, dyrabs, dcrabs, sdxr, sdyr, sdcr, xrr, yrr, crr, pxr, pyr, pcr);
181 182 183 184 185 186 187 188 189 190 191 192

  dest = dest + stride * y0;
  seg_start = y0;
  seg_end = y1;

  /* do two passes */
  for (k = 0; k < 2; k++) {
    for (i = seg_start; i < seg_end; i++) {
      gint s = pxl, e = pxr, sc = pcl, ec = pcr;
      gint sign = SIGN (e - s);

      e += sign;
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
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 199
        STEP_3D_LINE (dxrabs, dyrabs, dcrabs, sdxr, sdyr, sdcr,
            xrr, yrr, crr, pxr, pyr, pcr);
200 201
      }
      while (pyl == i) {
202 203
        STEP_3D_LINE (dxlabs, dylabs, dclabs, sdxl, sdyl, sdcl,
            xrl, yrl, crl, pxl, pyl, pcl);
204 205 206 207
      }
      dest += stride;
    }

Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
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 212
    seg_start = y1;
    seg_end = y2;
213 214
  }
}
215

Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
216 217 218
static void
draw_bresenham_line (guint32 * dest, gint stride,
    gint x0, gint y0, gint x1, gint y1, guint32 col)
219
{
220
  gint dx, dy;
221 222 223
  gint x_incr, y_incr;
  gint i, dpr, dpru, P, indep;

224 225 226
  dx = abs (x1 - x0);
  dy = abs (y1 - y0);

227 228 229 230
  dest = dest + y0 * stride + x0;

  x_incr = SIGN (x1 - x0);
  y_incr = SIGN (y1 - y0) * stride;
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
231 232

  if (dx >= dy) {
233 234 235
    dpr = dy << 1;
    i = dx;
    indep = x_incr;
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
236
  } else {
237 238 239
    dpr = dx << 1;
    i = dy;
    indep = y_incr;
240 241
  }

242 243 244 245 246 247
  dpru = dpr - (i << 1);
  P = dpr - i;

  for (; i >= 0; i--) {
    *dest = col;

Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
248
    if (P > 0) {
249 250 251 252 253 254
      dest += x_incr;
      dest += y_incr;
      P += dpru;
    } else {
      dest += indep;
      P += dpr;
255 256 257 258 259
    }
  }
}

void
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
260 261 262
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)
263 264 265
{
  gint i;
  gint sign;
266
  gfloat angle, angle_e;
267
  gfloat len1;
268

Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
269 270
  angle_e = acos (((x1 - x0) * (x2 - x0) + (y1 - y0) * (y2 - y0)) /
      (sqrt ((x1 - x0) * (x1 - x0) + (y1 - y0) * (y1 - y0)) *
271
          sqrt ((x2 - x0) * (x2 - x0) + (y2 - y0) * (y2 - y0))));
272

Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
273
  len1 = sqrt ((x1 - x0) * (x1 - x0) + (y1 - y0) * (y1 - y0));
274

275
  if (x1 == x2) {
276 277
    sign = SIGN (y2 - y1);

278 279
    for (i = y1; i != (y2 + sign); i += sign) {
      if (y1 == i)
280
        angle = 0;
281
      else
282 283 284
        angle = acos (((x1 - x0) * (x2 - x0) + (y1 - y0) * (i - y0)) /
            (len1 * sqrt ((x1 - x0) * (x1 - x0) + (i - y0) * (i -
                        y0)))) / angle_e;
285

286
      draw_bresenham_line (dest, stride,
287
          x0, y0, x1, i, (c2 * angle + c1 * (1.0 - angle)));
288
    }
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
289
  } else if (y1 == y2) {
290 291
    sign = SIGN (x2 - x1);

292 293
    for (i = x1; i != (x2 + sign); i += sign) {
      if (x1 == i)
294
        angle = 0;
295
      else
296 297 298
        angle = acos (((x1 - x0) * (i - x0) + (y1 - y0) * (y2 - y0)) /
            (len1 * sqrt ((i - x0) * (i - x0) + (y2 - y0) * (y2 -
                        y0)))) / angle_e;
299

300
      draw_bresenham_line (dest, stride,
301
          x0, y0, i, y1, (c2 * angle + c1 * (1.0 - angle)));
302
    }
303 304 305
  } else {
    g_warning ("paint triangle clock: not supported");
    return;
306 307
  }
}
308 309

void
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
310 311 312
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)
313
{
314 315 316
  gfloat angle_m, col_m;
  gint xv, yv;

Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
317
  if (x1 == x0) {
318 319 320 321 322
    xv = x2;
    yv = y1;
  } else if (y1 == y0) {
    xv = x1;
    yv = y2;
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
323
  } else {
324 325 326
    g_warning ("paint box clock: not supported");
    return;
  }
327

Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
328 329
  angle_m = 2 * acos (((x1 - x0) * (xv - x0) + (y1 - y0) * (yv - y0)) /
      (sqrt ((x1 - x0) * (x1 - x0) + (y1 - y0) * (y1 - y0)) *
330
          sqrt ((xv - x0) * (xv - x0) + (yv - y0) * (yv - y0)))) / M_PI;
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
331 332

  col_m = c2 * angle_m + c1 * (1.0 - angle_m);
333

334
  gst_smpte_paint_triangle_clock (dest, stride,
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
335
      x0, y0, c0, x1, y1, c1, xv, yv, col_m);
336
  gst_smpte_paint_triangle_clock (dest, stride,
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
337
      x0, y0, c0, xv, yv, col_m, x2, y2, c2);
338
}