From 71f4c72692a6c21b9f41273f93ecc97f0d595812 Mon Sep 17 00:00:00 2001
From: Andrey Utkin <andrey.krieger.utkin@gmail.com>
Date: Fri, 20 Jun 2014 20:28:55 +0300
Subject: [PATCH] Issue #3302 fix WIP

---
 libavfilter/drawutils.c | 30 ++++++++++++++++++++----------
 1 file changed, 20 insertions(+), 10 deletions(-)

diff --git a/libavfilter/drawutils.c b/libavfilter/drawutils.c
index 4437c2c..8b6a738 100644
--- a/libavfilter/drawutils.c
+++ b/libavfilter/drawutils.c
@@ -182,7 +182,7 @@ int ff_draw_init(FFDrawContext *draw, enum AVPixelFormat format, unsigned flags)
     memcpy(draw->pixelstep, pixelstep, sizeof(draw->pixelstep));
     draw->hsub[1] = draw->hsub[2] = draw->hsub_max = desc->log2_chroma_w;
     draw->vsub[1] = draw->vsub[2] = draw->vsub_max = desc->log2_chroma_h;
-    for (i = 0; i < ((desc->nb_components - 1) | 1); i++)
+    for (i = 0; i < desc->nb_components; i++)
         draw->comp_mask[desc->comp[i].plane] |=
             1 << (desc->comp[i].offset_plus1 - 1);
     return 0;
@@ -397,8 +397,13 @@ void ff_blend_rectangle(FFDrawContext *draw, FFDrawColor *color,
 
 static void blend_pixel(uint8_t *dst, unsigned src, unsigned alpha,
                         uint8_t *mask, int mask_linesize, int l2depth,
-                        unsigned w, unsigned h, unsigned shift, unsigned xm0)
+                        unsigned w, unsigned h, unsigned shift, unsigned xm0, int strategy)
 {
+    if (strategy == 1) {
+        /* Reverting expression: alpha = (0x10307 * color->rgba[3] + 0x3) >> 8 */
+        *dst = ((alpha << 8) - 0x3) / 0x10307;
+        return;
+    }
     unsigned xm, x, y, t = 0;
     unsigned xmshf = 3 - l2depth;
     unsigned xmmod = 7 >> l2depth;
@@ -422,31 +427,31 @@ static void blend_line_hv(uint8_t *dst, int dst_delta,
                           unsigned src, unsigned alpha,
                           uint8_t *mask, int mask_linesize, int l2depth, int w,
                           unsigned hsub, unsigned vsub,
-                          int xm, int left, int right, int hband)
+                          int xm, int left, int right, int hband, int strategy)
 {
     int x;
 
     if (left) {
         blend_pixel(dst, src, alpha, mask, mask_linesize, l2depth,
-                    left, hband, hsub + vsub, xm);
+                    left, hband, hsub + vsub, xm, strategy);
         dst += dst_delta;
         xm += left;
     }
     for (x = 0; x < w; x++) {
         blend_pixel(dst, src, alpha, mask, mask_linesize, l2depth,
-                    1 << hsub, hband, hsub + vsub, xm);
+                    1 << hsub, hband, hsub + vsub, xm, strategy);
         dst += dst_delta;
         xm += 1 << hsub;
     }
     if (right)
         blend_pixel(dst, src, alpha, mask, mask_linesize, l2depth,
-                    right, hband, hsub + vsub, xm);
+                    right, hband, hsub + vsub, xm, strategy);
 }
 
 void ff_blend_mask(FFDrawContext *draw, FFDrawColor *color,
                    uint8_t *dst[], int dst_linesize[], int dst_w, int dst_h,
                    uint8_t *mask,  int mask_linesize, int mask_w, int mask_h,
-                   int l2depth, unsigned endianness, int x0, int y0)
+                   int l2depth, unsigned endianness, int x0, int y0 /* TODO , int strategy */)
 {
     unsigned alpha, nb_planes, nb_comp, plane, comp;
     int xm0, ym0, w_sub, h_sub, x_sub, y_sub, left, right, top, bottom, y;
@@ -475,12 +480,17 @@ void ff_blend_mask(FFDrawContext *draw, FFDrawColor *color,
                 continue;
             p = p0 + comp;
             m = mask;
+            /* Treat alpha component specially. TODO Support more cases */
+            int strategy = 0 /* use existing algorithm */;
+            if (draw->format == AV_PIX_FMT_RGBA && comp == 3)
+                strategy = 1 /* just set *dst to alpha */;
+
             if (top) {
                 blend_line_hv(p, draw->pixelstep[plane],
                               color->comp[plane].u8[comp], alpha,
                               m, mask_linesize, l2depth, w_sub,
                               draw->hsub[plane], draw->vsub[plane],
-                              xm0, left, right, top);
+                              xm0, left, right, top, strategy);
                 p += dst_linesize[plane];
                 m += top * mask_linesize;
             }
@@ -489,7 +499,7 @@ void ff_blend_mask(FFDrawContext *draw, FFDrawColor *color,
                               color->comp[plane].u8[comp], alpha,
                               m, mask_linesize, l2depth, w_sub,
                               draw->hsub[plane], draw->vsub[plane],
-                              xm0, left, right, 1 << draw->vsub[plane]);
+                              xm0, left, right, 1 << draw->vsub[plane], strategy);
                 p += dst_linesize[plane];
                 m += mask_linesize << draw->vsub[plane];
             }
@@ -498,7 +508,7 @@ void ff_blend_mask(FFDrawContext *draw, FFDrawColor *color,
                               color->comp[plane].u8[comp], alpha,
                               m, mask_linesize, l2depth, w_sub,
                               draw->hsub[plane], draw->vsub[plane],
-                              xm0, left, right, bottom);
+                              xm0, left, right, bottom, strategy);
         }
     }
 }
-- 
1.8.3.2

