- reimplemented using organic masks, rendered with gouraud shaded triangles
authorWim Taymans <wim.taymans@gmail.com>
Sun, 13 Oct 2002 18:46:10 +0000 (18:46 +0000)
committerWim Taymans <wim.taymans@gmail.com>
Sun, 13 Oct 2002 18:46:10 +0000 (18:46 +0000)
Original commit message from CVS:
- reimplemented using organic masks, rendered with gouraud shaded triangles
- implemented more masks
- implemented adjustable border

common
gst/smpte/barboxwipes.c
gst/smpte/gstmask.c
gst/smpte/gstmask.h
gst/smpte/gstsmpte.c
gst/smpte/gstsmpte.h
gst/smpte/paint.c
gst/smpte/paint.h

diff --git a/common b/common
index fa2e4df..2f0e1ec 160000 (submodule)
--- a/common
+++ b/common
@@ -1 +1 @@
-Subproject commit fa2e4df50fd965b1dbd3b35b87d914ff87362815
+Subproject commit 2f0e1ecbfe7d27cf1b2215204958c95516db173d
index 031c282..8c858f9 100644 (file)
 #include "paint.h"
 #include "gstmask.h"
 
-static void
-gst_bar_wipe_lr_update (GstMask *mask,
-                       GstClockTime position,
-                       GstClockTime duration)
+enum
 {
-  gint width = mask->width;
-  gint height = mask->height;
-  gint split = (position * width) / duration;
+  BOX_VERTICAL                 = 1,
+  BOX_HORIZONTAL       = 2,
+  TRIGANLE_LINEAR      = 3,
+};
 
-  gst_smpte_paint_rect (mask->data, width, split, 0, width - split, height, 0);
-  gst_smpte_paint_rect (mask->data, width, 0,     0, split,         height, 255);
-}
+static gint boxes_1b[][7] = 
+{
+#define WIPE_B1_1      0
+  { BOX_VERTICAL,   0, 0, 0,  1, 1, 1 },
+#define WIPE_B1_2      1
+  { BOX_HORIZONTAL, 0, 0, 0,  1, 1, 1 }
+};
 
-static void
-gst_bar_wipe_tb_update (GstMask *mask,
-                       GstClockTime position,
-                       GstClockTime duration)
+static gint boxes_2b[][7*2] = 
 {
-  gint width = mask->width;
-  gint height = mask->height;
-  gint split = (position * height) / duration;
+#define WIPE_B2_21     0
+  { BOX_VERTICAL,   0, 0, 1,  1, 2, 0,
+    BOX_VERTICAL,   1, 0, 0,  2, 2, 1 },
+#define WIPE_B2_22     1
+  { BOX_HORIZONTAL, 0, 0, 1,  2, 1, 0,
+    BOX_HORIZONTAL, 0, 1, 0,  2, 2, 1 },
+};
 
-  gst_smpte_paint_rect (mask->data, width, 0, 0,     width, split,          255);
-  gst_smpte_paint_rect (mask->data, width, 0, split, width, height - split, 0);
-}
+static gint triangles_2t[][2*9] = 
+{
+  /* 3 -> 6 */
+#define WIPE_T2_3      0
+  { 0, 0, 0,  0, 1, 1,  1, 1, 1,   
+    1, 0, 1,  0, 0, 0,  1, 1, 1 },
+#define WIPE_T2_4      WIPE_T2_3+1
+  { 0, 0, 1,  1, 0, 0,  0, 1, 1, 
+    1, 0, 0,  0, 1, 1,  1, 1, 1 },
+#define WIPE_T2_5      WIPE_T2_4+1
+  { 0, 0, 1,  0, 1, 1,  1, 1, 0,
+    1, 0, 1,  0, 0, 1,  1, 1, 0 },
+#define WIPE_T2_6      WIPE_T2_5+1
+  { 0, 0, 1,  1, 0, 1,  0, 1, 0,
+    1, 0, 1,  0, 1, 0,  1, 1, 1 },
+#define WIPE_T2_41     WIPE_T2_6+1
+  { 0, 0, 0,  1, 0, 1,  0, 1, 1,
+    1, 0, 1,  0, 1, 1,  1, 1, 2 },
+#define WIPE_T2_42     WIPE_T2_41+1
+  { 0, 0, 1,  1, 0, 0,  1, 1, 1,
+    0, 0, 1,  0, 1, 2,  1, 1, 1 },
+#define WIPE_T2_45     WIPE_T2_42+1
+  { 0, 0, 1,  1, 0, 0,  0, 1, 0,
+    1, 0, 0,  0, 1, 0,  1, 1, 1 },
+#define WIPE_T2_46     WIPE_T2_45+1
+  { 0, 0, 0,  1, 0, 1,  1, 1, 0,
+    0, 0, 0,  0, 1, 1,  1, 1, 0 },
+};
+
+static gint triangles_3t[][3*9] = 
+{
+  /* 23 -> 26 */
+#define WIPE_T3_23     0
+  { 0, 0, 1,  1, 0, 0,  0, 2, 1,   
+    1, 0, 0,  0, 2, 1,  2, 2, 1,
+    1, 0, 0,  2, 0, 1,  2, 2, 1 },
+#define WIPE_T3_24     1
+  { 0, 0, 1,  2, 0, 1,  2, 1, 0,
+    0, 0, 1,  2, 1, 0,  0, 2, 1,
+    2, 1, 0,  0, 2, 1,  2, 2, 1 },
+#define WIPE_T3_25     2
+  { 0, 0, 1,  0, 2, 1,  1, 2, 0,
+    0, 0, 1,  2, 0, 1,  1, 2, 0,
+    2, 0, 1,  1, 2, 0,  2, 2, 1 },
+#define WIPE_T3_26     3
+  { 0, 0, 1,  2, 0, 1,  0, 1, 0,
+    2, 0, 1,  0, 1, 0,  2, 2, 1,
+    0, 1, 0,  0, 2, 1,  2, 2, 1 }
+};
+
+static gint triangles_4t[][4*9] = 
+{
+#define WIPE_T4_61     0
+  { 0, 0, 1,  1, 0, 0,  1, 2, 1,   
+    0, 0, 1,  0, 2, 2,  1, 2, 1,
+    1, 0, 0,  2, 0, 1,  1, 2, 1,
+    2, 0, 1,  1, 2, 1,  2, 2, 2 },
+#define WIPE_T4_62     1
+  { 0, 0, 2,  2, 0, 1,  0, 1, 1,   
+    2, 0, 1,  0, 1, 1,  2, 1, 0,
+    0, 1, 1,  2, 1, 0,  2, 2, 1,
+    0, 1, 1,  0, 2, 2,  2, 2, 1 },
+#define WIPE_T4_63     2
+  { 0, 0, 2,  1, 0, 1,  0, 2, 1,   
+    1, 0, 1,  0, 2, 1,  1, 2, 0,
+    1, 0, 1,  1, 2, 0,  2, 2, 1,
+    1, 0, 1,  2, 0, 2,  2, 2, 1 },
+#define WIPE_T4_64     3
+  { 0, 0, 1,  2, 0, 2,  2, 1, 1,   
+    0, 0, 1,  0, 1, 0,  2, 1, 1,
+    0, 1, 0,  2, 1, 1,  0, 2, 1,
+    2, 1, 1,  0, 2, 1,  2, 2, 2 },
+#define WIPE_T4_65     4
+  { 0, 0, 0,  1, 0, 1,  1, 2, 0,   
+    0, 0, 0,  0, 2, 1,  1, 2, 0,
+    1, 0, 1,  2, 0, 0,  1, 2, 0,
+    2, 0, 0,  1, 2, 0,  2, 2, 1 },
+#define WIPE_T4_66     5
+  { 0, 0, 1,  2, 0, 0,  0, 1, 0,   
+    2, 0, 0,  0, 1, 0,  2, 1, 1,
+    0, 1, 0,  2, 1, 1,  2, 2, 0,
+    0, 1, 0,  0, 2, 1,  2, 2, 0 },
+#define WIPE_T4_67     6
+  { 0, 0, 1,  1, 0, 0,  0, 2, 0,   
+    1, 0, 0,  0, 2, 0,  1, 2, 1,
+    1, 0, 0,  1, 2, 1,  2, 2, 0,
+    1, 0, 0,  2, 0, 1,  2, 2, 0 },
+#define WIPE_T4_68     7
+  { 0, 0, 0,  2, 0, 1,  2, 1, 0,   
+    0, 0, 0,  0, 1, 1,  2, 1, 0,
+    0, 1, 1,  2, 1, 0,  0, 2, 0,
+    2, 1, 0,  0, 2, 0,  2, 2, 1 },
+#define WIPE_T4_101    8
+  { 0, 0, 1,  2, 0, 1,  1, 1, 0,   
+    0, 0, 1,  1, 1, 0,  0, 2, 1,
+    1, 1, 0,  0, 2, 1,  2, 2, 1,
+    2, 0, 1,  1, 1, 0,  2, 2, 1 }
+};
+
+static gint triangles_8t[][8*9] = 
+{
+  /* 7 */
+#define WIPE_T8_7      0
+  { 0, 0, 0,  1, 0, 1,  1, 1, 1,   
+    1, 0, 1,  2, 0, 0,  1, 1, 1,
+    2, 0, 0,  1, 1, 1,  2, 1, 1,
+    1, 1, 1,  2, 1, 1,  2, 2, 0,
+    1, 1, 1,  1, 2, 1,  2, 2, 0,
+    1, 1, 1,  0, 2, 0,  1, 2, 1,
+    0, 1, 1,  1, 1, 1,  0, 2, 0,
+    0, 0, 0,  0, 1, 1,  1, 1, 1 },
+#define WIPE_T8_43     1
+  { 0, 0, 1,  1, 0, 0,  1, 1, 1,   
+    1, 0, 0,  2, 0, 1,  1, 1, 1,
+    2, 0, 1,  1, 1, 1,  2, 1, 2,
+    1, 1, 1,  2, 1, 2,  2, 2, 1,
+    1, 1, 1,  1, 2, 0,  2, 2, 1,
+    1, 1, 1,  0, 2, 1,  1, 2, 0,
+    0, 1, 2,  1, 1, 1,  0, 2, 1,
+    0, 0, 1,  0, 1, 2,  1, 1, 1 },
+#define WIPE_T8_44     2
+  { 0, 0, 1,  1, 0, 2,  1, 1, 1,   
+    1, 0, 2,  2, 0, 1,  1, 1, 1,
+    2, 0, 1,  1, 1, 1,  2, 1, 0,
+    1, 1, 1,  2, 1, 0,  2, 2, 1,
+    1, 1, 1,  1, 2, 2,  2, 2, 1,
+    1, 1, 1,  0, 2, 1,  1, 2, 2,
+    0, 1, 0,  1, 1, 1,  0, 2, 1,
+    0, 0, 1,  0, 1, 0,  1, 1, 1 },
+#define WIPE_T8_47     3
+  { 0, 0, 0,  1, 0, 1,  1, 1, 0,   
+    1, 0, 1,  2, 0, 0,  1, 1, 0,
+    2, 0, 0,  1, 1, 0,  2, 1, 1,
+    1, 1, 0,  2, 1, 1,  2, 2, 0,
+    1, 1, 0,  1, 2, 1,  2, 2, 0,
+    1, 1, 0,  0, 2, 0,  1, 2, 1,
+    0, 1, 1,  1, 1, 0,  0, 2, 0,
+    0, 0, 0,  0, 1, 1,  1, 1, 0 },
+#define WIPE_T8_48     4
+  { 0, 0, 1,  1, 0, 0,  0, 1, 0,   
+    1, 0, 0,  0, 1, 0,  1, 1, 1,
+    1, 0, 0,  2, 0, 1,  2, 1, 0,
+    1, 0, 0,  1, 1, 1,  2, 1, 0,
+    0, 1, 0,  1, 1, 1,  1, 2, 0,
+    0, 1, 0,  0, 2, 1,  1, 2, 0,
+    1, 1, 1,  2, 1, 0,  1, 2, 0,
+    2, 1, 0,  1, 2, 0,  2, 2, 1 },
+};
+
+static gint triangles_16t[][16*9] = 
+{
+  /* 8 */
+#define WIPE_T16_8     0
+  { 0, 0, 1,  2, 0, 1,  1, 1, 0,   
+    2, 0, 1,  1, 1, 0,  2, 2, 1,
+    1, 1, 0,  0, 2, 1,  2, 2, 1,
+    0, 0, 1,  1, 1, 0,  0, 2, 1,
+    2, 0, 1,  4, 0, 1,  3, 1, 0,   
+    4, 0, 1,  3, 1, 0,  4, 2, 1,
+    3, 1, 0,  2, 2, 1,  4, 2, 1,
+    2, 0, 1,  3, 1, 0,  2, 2, 1,
+    0, 2, 1,  2, 2, 1,  1, 3, 0,   
+    2, 2, 1,  1, 3, 0,  2, 4, 1,
+    1, 3, 0,  0, 4, 1,  2, 4, 1,
+    0, 2, 1,  1, 3, 0,  0, 4, 1,
+    2, 2, 1,  4, 2, 1,  3, 3, 0,   
+    4, 2, 1,  3, 3, 0,  4, 4, 1,
+    3, 3, 0,  2, 4, 1,  4, 4, 1,
+    2, 2, 1,  3, 3, 0,  2, 4, 1 }
+};
+
+typedef struct _GstWipeConfig GstWipeConfig;
+
+struct _GstWipeConfig {
+  gint         *objects;
+  gint   nobjects;
+  gint   xscale;
+  gint   yscale;
+  gint   cscale;
+};
+
+static GstWipeConfig wipe_config[] = 
+{
+#define WIPE_CONFIG_1  0
+  { boxes_1b[WIPE_B1_1],       1,  0, 0, 0 }, /* 1 */
+#define WIPE_CONFIG_2  WIPE_CONFIG_1+1
+  { boxes_1b[WIPE_B1_2],       1,  0, 0, 0 }, /* 2 */
+#define WIPE_CONFIG_3  WIPE_CONFIG_2+1
+  { triangles_2t[WIPE_T2_3],   2,  0, 0, 0 }, /* 3 */
+#define WIPE_CONFIG_4  WIPE_CONFIG_3+1
+  { triangles_2t[WIPE_T2_4],   2,  0, 0, 0 }, /* 4 */
+#define WIPE_CONFIG_5  WIPE_CONFIG_4+1
+  { triangles_2t[WIPE_T2_5],   2,  0, 0, 0 }, /* 5 */
+#define WIPE_CONFIG_6  WIPE_CONFIG_5+1
+  { triangles_2t[WIPE_T2_6],   2,  0, 0, 0 }, /* 6 */
+#define WIPE_CONFIG_7  WIPE_CONFIG_6+1
+  { triangles_8t[WIPE_T8_7],   8,  1, 1, 0 }, /* 7 */
+#define WIPE_CONFIG_8  WIPE_CONFIG_7+1
+  { triangles_16t[WIPE_T16_8], 16, 2, 2, 0 }, /* 8 */
+
+#define WIPE_CONFIG_21 WIPE_CONFIG_8+1
+  { boxes_2b[WIPE_B2_21],      2, 1, 1, 0 }, /* 21 */
+#define WIPE_CONFIG_22 WIPE_CONFIG_21+1
+  { boxes_2b[WIPE_B2_22],      2, 1, 1, 0 }, /* 22 */
+
+#define WIPE_CONFIG_23 WIPE_CONFIG_22+1
+  { triangles_3t[WIPE_T3_23],   3,  1, 1, 0 }, /* 23 */
+#define WIPE_CONFIG_24 WIPE_CONFIG_23+1
+  { triangles_3t[WIPE_T3_24],   3,  1, 1, 0 }, /* 24 */
+#define WIPE_CONFIG_25 WIPE_CONFIG_24+1
+  { triangles_3t[WIPE_T3_23],   3,  1, 1, 0 }, /* 25 */
+#define WIPE_CONFIG_26 WIPE_CONFIG_25+1
+  { triangles_3t[WIPE_T3_26],   3,  1, 1, 0 }, /* 26 */
+#define WIPE_CONFIG_41 WIPE_CONFIG_26+1
+  { triangles_2t[WIPE_T2_41],   2,  0, 0, 1 }, /* 41 */
+#define WIPE_CONFIG_42 WIPE_CONFIG_41+1
+  { triangles_2t[WIPE_T2_42],   2,  0, 0, 1 }, /* 42 */
+#define WIPE_CONFIG_43 WIPE_CONFIG_42+1
+  { triangles_8t[WIPE_T8_43],   8,  1, 1, 1 }, /* 43 */
+#define WIPE_CONFIG_44 WIPE_CONFIG_43+1
+  { triangles_8t[WIPE_T8_44],   8,  1, 1, 1 }, /* 44 */
+#define WIPE_CONFIG_45 WIPE_CONFIG_44+1
+  { triangles_2t[WIPE_T2_45],   2,  0, 0, 0 }, /* 45 */
+#define WIPE_CONFIG_46 WIPE_CONFIG_45+1
+  { triangles_2t[WIPE_T2_46],   2,  0, 0, 0 }, /* 46 */
+#define WIPE_CONFIG_47 WIPE_CONFIG_46+1
+  { triangles_8t[WIPE_T8_47],   8,  1, 1, 0 }, /* 47 */
+#define WIPE_CONFIG_48 WIPE_CONFIG_47+1
+  { triangles_8t[WIPE_T8_48],   8,  1, 1, 0 }, /* 48 */
+#define WIPE_CONFIG_61 WIPE_CONFIG_48+1
+  { triangles_4t[WIPE_T4_61],   4,  1, 1, 1 }, /* 61 */
+#define WIPE_CONFIG_62 WIPE_CONFIG_61+1
+  { triangles_4t[WIPE_T4_62],   4,  1, 1, 1 }, /* 62 */
+#define WIPE_CONFIG_63 WIPE_CONFIG_62+1
+  { triangles_4t[WIPE_T4_63],   4,  1, 1, 1 }, /* 63 */
+#define WIPE_CONFIG_64 WIPE_CONFIG_63+1
+  { triangles_4t[WIPE_T4_64],   4,  1, 1, 1 }, /* 64 */
+#define WIPE_CONFIG_65 WIPE_CONFIG_64+1
+  { triangles_4t[WIPE_T4_65],   4,  1, 1, 0 }, /* 65 */
+#define WIPE_CONFIG_66 WIPE_CONFIG_65+1
+  { triangles_4t[WIPE_T4_66],   4,  1, 1, 0 }, /* 66 */
+#define WIPE_CONFIG_67 WIPE_CONFIG_66+1
+  { triangles_4t[WIPE_T4_67],   4,  1, 1, 0 }, /* 67 */
+#define WIPE_CONFIG_68 WIPE_CONFIG_67+1
+  { triangles_4t[WIPE_T4_68],   4,  1, 1, 0 }, /* 68 */
+#define WIPE_CONFIG_101        WIPE_CONFIG_68+1
+  { triangles_4t[WIPE_T4_101],  4,  1, 1, 0 }, /* 101 */
+};
 
 static void
-gst_box_wipe_update (GstMask *mask,
-                    GstClockTime position,
-                    GstClockTime duration)
+gst_wipe_boxes_draw (GstMask *mask)
 {
-  static gint box_wipe_impacts[8][4] = 
-  {
-    /* 3 -> 6 */
-    { 0, 0, 0, 0 },
-    { 2, 2, 0, 0 },
-    { 2, 2, 2, 2 },
-    { 0, 0, 2, 2 },
-    /* 23 -> 26 */
-    { 1, 1, 0, 0 },
-    { 2, 2, 1, 1 },
-    { 1, 1, 2, 2 },
-    { 0, 0, 1, 1 },
-  };
-  gint *impacts = box_wipe_impacts[(mask->type & 0x0F) - 3];
-  gint width = mask->width;
-  gint height = mask->height;
-  gint splitx = (position * width) / duration;
-  gint splity = (position * height) / duration;
-
-  gst_smpte_paint_rect (mask->data, width, 0, 0, width,  height, 0);
-  gst_smpte_paint_rect (mask->data, width, 
-                       (impacts[0] * width)/2  - (impacts[1] * splitx)/2,
-                       (impacts[2] * height)/2 - (impacts[3] * splity)/2,
-                       splitx, splity, 255);
+  GstWipeConfig *config = mask->user_data;
+  gint *impacts = config->objects;
+  gint width = (mask->width >> config->xscale) - 1;
+  gint height = (mask->height >> config->yscale) - 1;
+  gint depth = (1 << mask->bpp) >> config->cscale;
+
+  gint i;
+
+  for (i = 0; i < config->nobjects; i++) {
+    switch (impacts[0]) {
+      case BOX_VERTICAL:
+        gst_smpte_paint_vbox (mask->data, mask->width, 
+                             impacts[1] * width, impacts[2] * height, impacts[3] * depth,
+                             impacts[4] * width, impacts[5] * height, impacts[6] * depth);
+       impacts += 7;
+        break;
+      case BOX_HORIZONTAL:
+        gst_smpte_paint_hbox (mask->data, mask->width, 
+                             impacts[1] * width, impacts[2] * height, impacts[3] * depth,
+                             impacts[4] * width, impacts[5] * height, impacts[6] * depth);
+       impacts += 7;
+      default:
+        break;
+    }
+  }
 }
 
 static void
-gst_fourc_box_wipe_update (GstMask *mask,
-                          GstClockTime position,
-                          GstClockTime duration)
+gst_wipe_triangles_draw (GstMask *mask)
 {
-  static gint box_wipe_impacts[8][4] = 
-  {
-    { 0, 0, 0, 0 },
-    { 1, 1, 1, 1 },
-    { 4, 2, 0, 0 },
-    { 3, 1, 1, 1 },
-    { 4, 2, 4, 2 },
-    { 1, 1, 3, 1 },
-    { 0, 0, 4, 2 },
-    { 3, 1, 3, 1 },
-  };
-  gint *impacts;
-  gint width = mask->width;
-  gint height = mask->height;
-  gint splitx = (position * width/2) / duration;
-  gint splity = (position * height/2) / duration;
-  gint i;
+  GstWipeConfig *config = mask->user_data;
+  gint *impacts = config->objects;
+  gint width = (mask->width >> config->xscale) - 1;
+  gint height = (mask->height >> config->yscale) - 1;
+  gint depth = (1 << mask->bpp) >> config->cscale;
 
-  gst_smpte_paint_rect (mask->data, width, 0, 0, width,  height, 0);
+  gint i;
 
-  for (i = 7; i > 0; i -= 2) {
-    impacts = box_wipe_impacts[mask->type - i];
-    gst_smpte_paint_rect (mask->data, width, 
-                         (impacts[0] * width)/4  - (impacts[1] * splitx)/2,
-                         (impacts[2] * height)/4 - (impacts[3] * splity)/2,
-                         splitx, splity, 255);
+  for (i = 0; i < config->nobjects; i++) {
+    gst_smpte_paint_triangle_linear (mask->data, mask->width,
+                          impacts[0] * width, impacts[1] * height, impacts[2] * depth,
+                          impacts[3] * width, impacts[4] * height, impacts[5] * depth,
+                          impacts[6] * width, impacts[7] * height, impacts[8] * depth);
+    impacts += 9;
   }
 }
 
 static GstMaskDefinition definitions[] = { 
- { 1,  "bar_wipe_lr", "A bar moves from left to right", 
-                       _gst_mask_default_new, _gst_mask_default_destroy, gst_bar_wipe_lr_update },
- { 2,  "bar_wipe_tb", "A bar moves from top to bottom", 
-                       _gst_mask_default_new, _gst_mask_default_destroy, gst_bar_wipe_tb_update },
- { 3,  "box_wipe_tl", "A box expands from the upper-left corner to the lower-right corner", 
-                       _gst_mask_default_new, _gst_mask_default_destroy, gst_box_wipe_update },
- { 4,  "box_wipe_tr", "A box expands from the upper-right corner to the lower-left corner", 
-                       _gst_mask_default_new, _gst_mask_default_destroy, gst_box_wipe_update },
- { 5,  "box_wipe_br", "A box expands from the lower-right corner to the upper-left corner", 
-                       _gst_mask_default_new, _gst_mask_default_destroy, gst_box_wipe_update },
- { 6,  "box_wipe_bl", "A box expands from the lower-left corner to the upper-right corner", 
-                       _gst_mask_default_new, _gst_mask_default_destroy, gst_box_wipe_update },
- { 23, "box_wipe_tc", "A box expands from the top edge's midpoint to the bottom corners", 
-                       _gst_mask_default_new, _gst_mask_default_destroy, gst_box_wipe_update },
- { 24, "box_wipe_rc", "A box expands from the right edge's midpoint to the left corners", 
-                       _gst_mask_default_new, _gst_mask_default_destroy, gst_box_wipe_update },
- { 25, "box_wipe_bc", "A box expands from the bottom edge's midpoint to the top corners", 
-                       _gst_mask_default_new, _gst_mask_default_destroy, gst_box_wipe_update },
- { 26, "box_wipe_lc", "A box expands from the left edge's midpoint to the right corners", 
-                       _gst_mask_default_new, _gst_mask_default_destroy, gst_box_wipe_update },
- { 7 , "four_box_wipe_ci", "A box shape expands from each of the four corners toward the center", 
-                       _gst_mask_default_new, _gst_mask_default_destroy, gst_fourc_box_wipe_update },
- { 8 , "four_box_wipe_co", "A box shape expands from the center of each quadrant toward the corners of each quadrant", 
-                       _gst_mask_default_new, _gst_mask_default_destroy, gst_fourc_box_wipe_update },
+ { 1,  "bar_wipe_lr", 
+       "A bar moves from left to right", 
+       gst_wipe_boxes_draw, _gst_mask_default_destroy, 
+       &wipe_config[WIPE_CONFIG_1] },
+ { 2,  "bar_wipe_tb", 
+       "A bar moves from top to bottom", 
+       gst_wipe_boxes_draw, _gst_mask_default_destroy, 
+       &wipe_config[WIPE_CONFIG_2] },
+ { 3,  "box_wipe_tl", 
+       "A box expands from the upper-left corner to the lower-right corner", 
+       gst_wipe_triangles_draw, _gst_mask_default_destroy, 
+       &wipe_config[WIPE_CONFIG_3] },
+ { 4,  "box_wipe_tr", 
+       "A box expands from the upper-right corner to the lower-left corner", 
+       gst_wipe_triangles_draw, _gst_mask_default_destroy, 
+       &wipe_config[WIPE_CONFIG_4] },
+ { 5,  "box_wipe_br", 
+       "A box expands from the lower-right corner to the upper-left corner", 
+       gst_wipe_triangles_draw, _gst_mask_default_destroy, 
+       &wipe_config[WIPE_CONFIG_5] },
+ { 6,  "box_wipe_bl", 
+       "A box expands from the lower-left corner to the upper-right corner", 
+       gst_wipe_triangles_draw, _gst_mask_default_destroy,
+       &wipe_config[WIPE_CONFIG_6] },
+ { 7 , "four_box_wipe_ci", 
+       "A box shape expands from each of the four corners toward the center", 
+       gst_wipe_triangles_draw, _gst_mask_default_destroy,
+       &wipe_config[WIPE_CONFIG_7] },
+ { 8 , "four_box_wipe_co", 
+       "A box shape expands from the center of each quadrant toward the corners of each quadrant", 
+       gst_wipe_triangles_draw, _gst_mask_default_destroy,
+       &wipe_config[WIPE_CONFIG_8] },
+ { 21, "barndoor_v",
+       "A central, vertical line splits and expands toward the left and right edges", 
+       gst_wipe_boxes_draw, _gst_mask_default_destroy, 
+       &wipe_config[WIPE_CONFIG_21] },
+ { 22, "barndoor_h",
+       "A central, horizontal line splits and expands toward the top and bottom edges", 
+       gst_wipe_boxes_draw, _gst_mask_default_destroy, 
+       &wipe_config[WIPE_CONFIG_22] },
+ { 23, "box_wipe_tc",
+       "A box expands from the top edge's midpoint to the bottom corners", 
+       gst_wipe_triangles_draw, _gst_mask_default_destroy,
+       &wipe_config[WIPE_CONFIG_23] },
+ { 24, "box_wipe_rc",
+       "A box expands from the right edge's midpoint to the left corners", 
+       gst_wipe_triangles_draw, _gst_mask_default_destroy,
+       &wipe_config[WIPE_CONFIG_24] },
+ { 25, "box_wipe_bc",
+       "A box expands from the bottom edge's midpoint to the top corners", 
+       gst_wipe_triangles_draw, _gst_mask_default_destroy,
+       &wipe_config[WIPE_CONFIG_25] },
+ { 26, "box_wipe_lc",
+       "A box expands from the left edge's midpoint to the right corners", 
+       gst_wipe_triangles_draw, _gst_mask_default_destroy,
+       &wipe_config[WIPE_CONFIG_26] },
+ { 41, "diagonal_tl",
+       "A diagonal line moves from the upper-left corner to the lower-right corner", 
+       gst_wipe_triangles_draw, _gst_mask_default_destroy,
+       &wipe_config[WIPE_CONFIG_41] },
+ { 42, "diagonal_tr",
+       "A diagonal line moves from the upper right corner to the lower-left corner", 
+       gst_wipe_triangles_draw, _gst_mask_default_destroy,
+       &wipe_config[WIPE_CONFIG_42] },
+ { 43, "bowtie_v",
+       "Two wedge shapes slide in from the top and bottom edges toward the center", 
+       gst_wipe_triangles_draw, _gst_mask_default_destroy,
+       &wipe_config[WIPE_CONFIG_43] },
+ { 44, "bowtie_h",
+       "Two wedge shapes slide in from the left and right edges toward the center", 
+       gst_wipe_triangles_draw, _gst_mask_default_destroy,
+       &wipe_config[WIPE_CONFIG_44] },
+ { 45, "barndoor_dbl",
+       "A diagonal line from the lower-left to upper-right corners splits and expands toward the opposite corners", 
+       gst_wipe_triangles_draw, _gst_mask_default_destroy,
+       &wipe_config[WIPE_CONFIG_45] },
+ { 46, "barndoor_dtl",
+       "A diagonal line from upper-left to lower-right corners splits and expands toward the opposite corners", 
+       gst_wipe_triangles_draw, _gst_mask_default_destroy,
+       &wipe_config[WIPE_CONFIG_46] },
+ { 47, "misc_diagonal_dbd",
+       "Four wedge shapes split from the center and retract toward the four edges", 
+       gst_wipe_triangles_draw, _gst_mask_default_destroy,
+       &wipe_config[WIPE_CONFIG_47] },
+ { 48, "misc_diagonal_dd",
+       "A diamond connecting the four edge midpoints simultaneously contracts toward the center and expands toward the edges", 
+       gst_wipe_triangles_draw, _gst_mask_default_destroy,
+       &wipe_config[WIPE_CONFIG_48] },
+ { 61, "vee_d",
+       "A wedge shape moves from top to bottom", 
+       gst_wipe_triangles_draw, _gst_mask_default_destroy,
+       &wipe_config[WIPE_CONFIG_61] },
+ { 62, "vee_l",
+       "A wedge shape moves from right to left", 
+       gst_wipe_triangles_draw, _gst_mask_default_destroy,
+       &wipe_config[WIPE_CONFIG_62] },
+ { 63, "vee_u",
+       "A wedge shape moves from bottom to top", 
+       gst_wipe_triangles_draw, _gst_mask_default_destroy,
+       &wipe_config[WIPE_CONFIG_63] },
+ { 64, "vee_r",
+       "A wedge shape moves from left to right", 
+       gst_wipe_triangles_draw, _gst_mask_default_destroy,
+       &wipe_config[WIPE_CONFIG_64] },
+ { 65, "barnvee_d",
+       "A 'V' shape extending from the bottom edge's midpoint to the opposite corners contracts toward the center and expands toward the edges", 
+       gst_wipe_triangles_draw, _gst_mask_default_destroy,
+       &wipe_config[WIPE_CONFIG_65] },
+ { 66, "barnvee_l",
+       "A 'V' shape extending from the left edge's midpoint to the opposite corners contracts toward the center and expands toward the edges", 
+       gst_wipe_triangles_draw, _gst_mask_default_destroy,
+       &wipe_config[WIPE_CONFIG_66] },
+ { 67, "barnvee_u",
+       "A 'V' shape extending from the top edge's midpoint to the opposite corners contracts toward the center and expands toward the edges", 
+       gst_wipe_triangles_draw, _gst_mask_default_destroy,
+       &wipe_config[WIPE_CONFIG_67] },
+ { 68, "barnvee_r",
+       "A 'V' shape extending from the right edge's midpoint to the opposite corners contracts toward the center and expands toward the edges", 
+       gst_wipe_triangles_draw, _gst_mask_default_destroy,
+       &wipe_config[WIPE_CONFIG_68] },
+ { 101, "iris_rect",
+       "A rectangle expands from the center.", 
+       gst_wipe_triangles_draw, _gst_mask_default_destroy,
+       &wipe_config[WIPE_CONFIG_101] },
  { 0, NULL, NULL, NULL }
 };
 
index a26d719..1480452 100644 (file)
@@ -19,6 +19,7 @@
 
 
 #include "gstmask.h"
+#include "paint.h"
 
 extern void _gst_barboxwipes_register (void);
 
@@ -73,31 +74,23 @@ gst_mask_factory_new (gint type, gint bpp, gint width, gint height)
 
   definition = gst_mask_find_definition (type);
   if (definition) {
-    mask = definition->new_func (definition, bpp, width, height);
+    mask = g_new0 (GstMask, 1);
+
+    mask->type = definition->type;
+    mask->bpp = bpp;
+    mask->width = width;
+    mask->height = height;
+    mask->destroy_func = definition->destroy_func;
+    mask->user_data = definition->user_data;
+    mask->data = g_malloc (width * height * sizeof (guint32));
+
+    if (definition->draw_func)
+      definition->draw_func (mask);
   }
 
   return mask;
 }
 
-GstMask*
-_gst_mask_default_new (GstMaskDefinition *definition,
-                      gint bpp, gint width, gint height)
-{
-  GstMask *mask;
-
-  mask = g_new0 (GstMask, 1);
-
-  mask->type = definition->type;
-  mask->bpp = bpp;
-  mask->width = width;
-  mask->height = height;
-  mask->update_func = definition->update_func;
-  mask->destroy_func = definition->destroy_func;
-  mask->data = g_malloc (width * height * (bpp+7)>>3);
-  
-  return mask;
-}
-
 void
 _gst_mask_default_destroy (GstMask *mask)
 {
@@ -119,6 +112,4 @@ gst_mask_update (GstMask *mask,
 {
   g_return_if_fail (mask != NULL);
 
-  if (mask->update_func)
-    mask->update_func (mask, position, duration);
 }
index f53fb99..6131c62 100644 (file)
 typedef struct _GstMask GstMask;
 typedef struct _GstMaskDefinition GstMaskDefinition;
 
-typedef GstMask*       (*GstMaskNewFunc)               (GstMaskDefinition *definition,
-                                                        gint bpp, gint width, gint height);
+typedef void           (*GstMaskDrawFunc)              (GstMask *mask);
 typedef void           (*GstMaskDestroyFunc)           (GstMask *mask);
-typedef void           (*GstMaskUpdateFunc)            (GstMask *mask, 
-                                                        GstClockTime position, 
-                                                        GstClockTime duration);
+
 struct _GstMaskDefinition {
   gint                          type;
   gchar                *short_name;
   gchar                *long_name;
-  GstMaskNewFunc        new_func;
+  GstMaskDrawFunc       draw_func;
   GstMaskDestroyFunc    destroy_func;
-  GstMaskUpdateFunc     update_func;
+  gpointer              user_data;
 };
 
 struct _GstMask {
   gint                          type;
-  guint8               *data;
+  guint32              *data;
+  gpointer              user_data;
 
   gint                  width;
   gint                  height;
   gint                  bpp;
 
-  GstMaskUpdateFunc     update_func;
   GstMaskDestroyFunc    destroy_func;
 };
 
 void                   _gst_mask_init                  (void);
 void                   _gst_mask_register              (GstMaskDefinition *definition);
 
-GstMask*               _gst_mask_default_new           (GstMaskDefinition *definition,
-                                                        gint bpp, gint width, gint height);
 void                   _gst_mask_default_destroy       (GstMask *mask);
 
 const GList*           gst_mask_get_definitions        (void);
 GstMask*               gst_mask_factory_new            (gint type, gint bpp, gint width, gint height);
 void                   gst_mask_destroy                (GstMask *mask);
 
-void                   gst_mask_update                 (GstMask *mask,
-                                                        GstClockTime position, 
-                                                        GstClockTime duration);
-
-
 #endif /* __GST_MASK_H__ */
index 536be8d..47de304 100644 (file)
@@ -79,6 +79,9 @@ enum {
 enum {
   ARG_0,
   ARG_TYPE,
+  ARG_BORDER,
+  ARG_DEPTH,
+  ARG_FPS,
 };
 
 #define GST_TYPE_SMPTE_TRANSITION_TYPE (gst_smpte_transition_type_get_type())
@@ -106,7 +109,8 @@ gst_smpte_transition_type_get_type (void)
       i++;
     }
 
-    smpte_transition_type = g_enum_register_static ("GstSMPTETransitionType", smpte_transitions);
+    smpte_transition_type = 
+           g_enum_register_static ("GstSMPTETransitionType", smpte_transitions);
   }
   return smpte_transition_type;
 }   
@@ -166,7 +170,15 @@ gst_smpte_class_init (GstSMPTEClass *klass)
   g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_TYPE,
     g_param_spec_enum ("type", "Type", "The type of transition to use",
                        GST_TYPE_SMPTE_TRANSITION_TYPE, 1, G_PARAM_READWRITE));
-
+  g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_FPS,
+    g_param_spec_int ("fps", "FPS", "Frames per second if no input files are given",
+                      1, 255, 1, G_PARAM_READWRITE));
+  g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_BORDER,
+    g_param_spec_int ("border", "Border", "The border width of the transition",
+                      0, G_MAXINT, 0, G_PARAM_READWRITE));
+  g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_DEPTH,
+    g_param_spec_int ("depth", "Depth", "Depth of the mask in bits",
+                      1, 24, 16, G_PARAM_READWRITE));
 }
 
 /*                        wht  yel  cya  grn  mag  red  blu  blk   -I    Q */
@@ -177,13 +189,35 @@ static int v_colors[] = { 128, 155,   0,  21, 235, 255, 107, 128, 128, 255 };
 static void
 fill_i420 (guint8 *data, gint width, gint height, gint color)
 {
+  gint size = width * height, size4 = size >> 2;
   guint8 *yp = data;
-  guint8 *up = data + width * height;
-  guint8 *vp = data + width * height + (width * height) / 4;
+  guint8 *up = data + size;
+  guint8 *vp = data + size + size4;
   
-  gst_smpte_paint_rect (yp, width,   0, 0, width,   height,   y_colors[color]);
-  gst_smpte_paint_rect (up, width/2, 0, 0, width/2, height/2, u_colors[color]);
-  gst_smpte_paint_rect (vp, width/2, 0, 0, width/2, height/2, v_colors[color]);
+  memset (yp, y_colors[color], size);
+  memset (up, u_colors[color], size4);
+  memset (vp, v_colors[color], size4);
+}
+
+static gboolean
+gst_smpte_update_mask (GstSMPTE *smpte, gint type, gint depth, gint width, gint height)
+{
+  GstMask *newmask;
+
+  newmask = gst_mask_factory_new (type, depth, width, height);
+  if (newmask) {
+    if (smpte->mask) {
+      gst_mask_destroy (smpte->mask);
+    }
+    smpte->mask = newmask;
+    smpte->type = type;
+    smpte->depth = depth;
+    smpte->width = width;
+    smpte->height = height;
+
+    return TRUE;
+  }
+  return FALSE;
 }
 
 static gboolean
@@ -199,7 +233,7 @@ gst_smpte_sinkconnect (GstPad *pad, GstCaps *caps)
   gst_caps_get_int (caps, "width", &smpte->width);
   gst_caps_get_int (caps, "height", &smpte->height);
 
-  smpte->mask = gst_mask_factory_new (smpte->type, 8, smpte->width, smpte->height);
+  gst_smpte_update_mask (smpte, smpte->type, smpte->depth, smpte->width, smpte->height);
 
   /* forward to the next plugin */
   return gst_pad_try_set_caps(smpte->srcpad, gst_caps_copy_1(caps));
@@ -229,35 +263,43 @@ gst_smpte_init (GstSMPTE *smpte)
   smpte->duration = 64;
   smpte->position = 0;
   smpte->type = 1;
-  smpte->mask = gst_mask_factory_new (smpte->type, 8, smpte->width, smpte->height);
+  smpte->fps = 1;
+  smpte->border = 0;
+  smpte->depth = 16;
+  gst_smpte_update_mask (smpte, smpte->type, smpte->depth, smpte->width, smpte->height);
 }
 
 static void
 gst_smpte_blend_i420 (guint8 *in1, guint8 *in2, guint8 *out, GstMask *mask,
-                     gint width, gint height)
+                     gint width, gint height, gint border, gint pos)
 {
-  gint i, j;
-  guint8 *maskporig, *maskp;
+  guint32 *maskp;
+  gint value;
+  gint i;
+  gint min, max;
   guint8 *in1u, *in1v, *in2u, *in2v, *outu, *outv; 
-  guint8 value;
-  gint chromsize = (width * height) >> 2;
+  gint lumsize = width * height;
+  gint chromsize = lumsize >> 2;
+
+  if (border == 0) border++;
 
-  maskp = maskporig = mask->data;
+  min = pos - border; 
+  max = pos;
+
+  in1u = in1 + lumsize; in1v = in1 + chromsize;
+  in2u = in2 + lumsize; in2v = in2 + chromsize;
+  outu = out + lumsize; outv = out + chromsize;
   
-  for (i = width * height; i; i--) {
+  maskp = mask->data;
+
+  for (i = lumsize; i; i--) {
     value = *maskp++;
-    *out++ = ((*in2++ * value) + (*in1++ * (255 - value))) >> 8;
-  }
-  in1u = in1; in1v = in1 + chromsize;
-  in2u = in2; in2v = in2 + chromsize;
-  outu = out; outv = out + chromsize;
-
-  maskp = maskporig;
-  for (i = height/2; i; i--, maskp += width) {
-    for (j = width/2; j; j--, maskp += 2) {
-      value = *maskp;
-      *outu++ = ((*in2u++ * value) + (*in1u++ * (255 - value))) >> 8;
-      *outv++ = ((*in2v++ * value) + (*in1v++ * (255 - value))) >> 8;
+    value = ((CLAMP (value, min, max) - min) << 8) / border;
+    
+    *out++ = ((*in1++ * value) + (*in2++ * (255 - value))) >> 8;
+    if (i % 4) {
+      *outu++ = ((*in1u++ * value) + (*in2u++ * (255 - value))) >> 8;
+      *outv++ = ((*in1v++ * value) + (*in2v++ * (255 - value))) >> 8;
     }
   }
 }
@@ -272,7 +314,7 @@ gst_smpte_loop (GstElement *element)
 
   smpte = GST_SMPTE (element);
 
-  ts = smpte->position * GST_SECOND;
+  ts = smpte->position * GST_SECOND / smpte->fps;
 
   if (GST_PAD_IS_USABLE (smpte->sinkpad1)) {
     in1 = gst_pad_pull (smpte->sinkpad1);
@@ -297,23 +339,26 @@ gst_smpte_loop (GstElement *element)
 
     if (!GST_PAD_CAPS (smpte->srcpad)) {
       if (!gst_pad_try_set_caps (smpte->srcpad,
-                           GST_CAPS_NEW (
-                                   "smpte_srccaps",
-                                   "video/raw",
-                                     "format",   GST_PROPS_FOURCC (GST_MAKE_FOURCC ('I','4','2','0')),
-                                     "width",    GST_PROPS_INT (smpte->width),
-                                     "height",   GST_PROPS_INT (smpte->height)
-                                   )))
+           GST_CAPS_NEW (
+                   "smpte_srccaps",
+                   "video/raw",
+                     "format",   GST_PROPS_FOURCC (GST_MAKE_FOURCC ('I','4','2','0')),
+                     "width",    GST_PROPS_INT (smpte->width),
+                     "height",   GST_PROPS_INT (smpte->height)
+                   )))
       {
         gst_element_error (element, "cannot set caps");
         return;
       }
     }
 
-    gst_mask_update (smpte->mask, smpte->position, smpte->duration);
-
-    gst_smpte_blend_i420 (GST_BUFFER_DATA (in1), GST_BUFFER_DATA (in2), GST_BUFFER_DATA (outbuf),
-                         smpte->mask, smpte->width, smpte->height);
+    gst_smpte_blend_i420 (GST_BUFFER_DATA (in1), 
+                         GST_BUFFER_DATA (in2), 
+                         GST_BUFFER_DATA (outbuf),
+                         smpte->mask, smpte->width, smpte->height, 
+                         smpte->border,
+                         ((1 << smpte->depth) + smpte->border) * 
+                           smpte->position / smpte->duration);
   }
   else {
     outbuf = in2;
@@ -342,17 +387,24 @@ gst_smpte_set_property (GObject *object, guint prop_id,
   switch (prop_id) {
     case ARG_TYPE:
     {
-      GstMask *newmask;
       gint type = g_value_get_enum (value);
 
-      newmask = gst_mask_factory_new (type, 8, smpte->width, smpte->height);
-      if (newmask) {
-       if (smpte->mask) {
-          gst_mask_destroy (smpte->mask);
-       }
-       smpte->mask = newmask;
-       smpte->type = type;
-      }
+      gst_smpte_update_mask (smpte, type, smpte->depth, 
+                            smpte->width, smpte->height);
+      break;
+    }
+    case ARG_FPS:
+      smpte->fps = g_value_get_int (value);
+      break;
+    case ARG_BORDER:
+      smpte->border = g_value_get_int (value);
+      break;
+    case ARG_DEPTH:
+    {
+      gint depth = g_value_get_int (value);
+
+      gst_smpte_update_mask (smpte, smpte->type, depth, 
+                            smpte->width, smpte->height);
       break;
     }
     default:
@@ -375,6 +427,15 @@ gst_smpte_get_property (GObject *object, guint prop_id,
        g_value_set_enum (value, smpte->mask->type);
       }
       break;
+    case ARG_FPS:
+      g_value_set_int (value, smpte->fps);
+      break;
+    case ARG_BORDER:
+      g_value_set_int (value, smpte->border);
+      break;
+    case ARG_DEPTH:
+      g_value_set_int (value, smpte->depth);
+      break;
     default:
       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
       break;
@@ -391,9 +452,12 @@ plugin_init (GModule *module, GstPlugin *plugin)
                                    &smpte_details);
   g_return_val_if_fail(factory != NULL, FALSE);
 
-  gst_element_factory_add_pad_template (factory, GST_PAD_TEMPLATE_GET (smpte_sink1_factory));
-  gst_element_factory_add_pad_template (factory, GST_PAD_TEMPLATE_GET (smpte_sink2_factory));
-  gst_element_factory_add_pad_template (factory, GST_PAD_TEMPLATE_GET (smpte_src_factory));
+  gst_element_factory_add_pad_template (factory, 
+                 GST_PAD_TEMPLATE_GET (smpte_sink1_factory));
+  gst_element_factory_add_pad_template (factory, 
+                 GST_PAD_TEMPLATE_GET (smpte_sink2_factory));
+  gst_element_factory_add_pad_template (factory, 
+                 GST_PAD_TEMPLATE_GET (smpte_src_factory));
 
   gst_plugin_add_feature (plugin, GST_PLUGIN_FEATURE (factory));
 
index 5ba6278..5c86389 100644 (file)
@@ -53,6 +53,9 @@ struct _GstSMPTE {
                *sinkpad2;
 
   gint                  type;
+  gint                  fps;
+  gint                  border;
+  gint                  depth;
   GstMask      *mask;
 };
 
index 0fb96d7..3ccfc23 100644 (file)
 #include "paint.h"
 
 void
-gst_smpte_paint_rect (guint8 *dest, gint stride, gint x, gint y, gint w, gint h, guint8 color)
-{ 
-  guint8 *d = dest + stride * y + x;
-  gint i;
-             
-  for (i = 0; i < h; i++) {
-    memset (d, color, w);
-    d += stride; 
+gst_smpte_paint_vbox (guint32 *dest, gint stride, 
+                     gint x0, gint y0, gint c0, 
+                     gint x1, gint y1, gint c1)
+{
+  gint i, j;
+  gint width, height;
+
+  width = x1 - x0;
+  height = y1 - y0;
+  
+  g_assert (width > 0);
+  g_assert (height > 0);
+
+  dest = dest + y0 * stride + x0;
+        
+  for (i = 0; i < height; i++) {
+    for (j = 0; j < width; j++) {
+      dest[j] = (c1 * j + c0 * (width - j)) / width;
+    }
+    dest += stride;
+  }
+}
+
+void
+gst_smpte_paint_hbox (guint32 *dest, gint stride, 
+                     gint x0, gint y0, gint c0, 
+                     gint x1, gint y1, gint c1)
+{
+  gint i, j;
+  gint width, height;
+
+  width = x1 - x0;
+  height = y1 - y0;
+  
+  g_assert (width > 0);
+  g_assert (height > 0);
+
+  g_print ("vbox: %d %d %d %d %d %d\n", x0, y0, c0, x1, y1, c1);
+
+  dest = dest + y0 * stride + x0;
+
+  for (i = 0; i < height; i++) {
+    guint32 value  = (c1 * i + c0 * (height - i)) / height;
+    for (j = 0; j < width; j++) {
+      *dest++ = value;
+    }
   }
 }
 
 void
-gst_smpte_paint_rect_s (guint8 *dest, gint stride, gint x, gint y, gint w, gint h, guint8 color)
-{ 
-  guint8 *d = dest + stride * y + x;
+gst_smpte_paint_rect16 (guint16 * dest, gint depth, gint w, gint h)
+{
   gint i, j;
-  gint border = 100;
 
   for (i = 0; i < h; i++) {
-    if (w - border > 0) {
-      memset (d, color, w - border);
+    for (j = 0; j < w; j++) {
+      *dest++ = (guint16) ((double) (1 << depth) * j / w);
     }
+  }
+}
+
+#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;                                         \
+  }                                                    \
+} G_STMT_END
+
+#define SWAP(a,b)              \
+G_STMT_START {                         \
+  typeof (a) tmp;              \
+  tmp = (a);                   \
+  (a) = (b);                   \
+  (b) = (tmp);                 \
+} 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)\
+G_STMT_START {                         \
+  typeof (x0) 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;                     \
+} G_STMT_END
+
+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)
+{
+  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;
+
+  if (y0 > y1) { SWAP (x0, x1); SWAP (y0, y1); SWAP (c0, c1); }
+  if (y0 > y2) { SWAP (x0, x2); SWAP (y0, y2); SWAP (c0, c2); }
+  if (y1 > y2) { SWAP (x1, x2); SWAP (y1, y2); SWAP (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);
+
+  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;
+
+      for (j = s; j != e; j+=sign) {
+       dest[j] = (ec * (j - s) + sc * (e - j)) / (e - s);
+      }
+      while (pyr == i) {
+        STEP_3D_LINE (dxrabs, dyrabs, dcrabs, sdxr, sdyr, sdcr, 
+                     xrr, yrr, crr, pxr, pyr, pcr);
+      }
+      while (pyl == i) {
+        STEP_3D_LINE (dxlabs, dylabs, dclabs, sdxl, sdyl, sdcl, 
+                     xrl, yrl, crl, pxl, pyl, pcl);
+      }
+      dest += stride;
+    }
+
+    PREPARE_3D_LINE (x1,y1,c1,x2,y2,c2,
+                    dxrabs,dyrabs,dcrabs,
+                    sdxr, sdyr,sdcr,
+                    xrr,yrr,crr,
+                    pxr,pyr,pcr);
 
-    for (j = 0; j < border - w; j++) {
-      *(d+w+j) = (color*(border-j)/border);
-    } 
-    d += stride; 
+    seg_start = y1;
+    seg_end = y2;
   }
 }
index fc51a63..224ded7 100644 (file)
 
 #include <glib.h>
 
-void   gst_smpte_paint_rect    (guint8 *dest, gint stride, 
-                                gint x, gint y, gint w, gint h, 
-                                guint8 color);
+void   gst_smpte_paint_vbox            (guint32 *dest, gint stride, 
+                                        gint x0, gint y0, gint c0, 
+                                        gint x1, gint y1, gint c1);
+void   gst_smpte_paint_hbox            (guint32 *dest, gint stride, 
+                                        gint x0, gint y0, gint c0, 
+                                        gint x1, gint y1, gint c1);
 
-void   gst_smpte_paint_rect_s  (guint8 *dest, gint stride, 
-                                gint x, gint y, gint w, gint h, 
-                                guint8 color);
+void   gst_smpte_paint_rect16  (guint16 *dest, gint depth, gint width, gint height);
 
 
+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);
+
 
 #endif /* __GST_SMPTE_PAINT_H__ */