lottie/vector: added Xor operation to Rle object 88/187188/3
authorsub.mohanty@samsung.com <smohantty@gmail.com>
Mon, 20 Aug 2018 15:31:57 +0000 (00:31 +0900)
committerHermet Park <chuneon.park@samsung.com>
Tue, 21 Aug 2018 03:49:40 +0000 (03:49 +0000)
Change-Id: I48cb3680a22ce3fb7f07048385dd5cc518ff9c7e

src/vector/vrle.cpp
src/vector/vrle.h

index 67a5e60..1ab7393 100644 (file)
 
 V_BEGIN_NAMESPACE
 
+enum class Operation {
+    Add,
+    Xor
+};
+
 struct VRleHelper {
     ushort      alloc;
     ushort      size;
@@ -18,7 +23,7 @@ struct VRleHelper {
 static void rleIntersectWithRle(VRleHelper *, int, int, VRleHelper *,
                                 VRleHelper *);
 static void rleIntersectWithRect(const VRect &, VRleHelper *, VRleHelper *);
-static void rleAddWithRle(VRleHelper *, VRleHelper *, VRleHelper *);
+static void rleOpGeneric(VRleHelper *, VRleHelper *, VRleHelper *, Operation op);
 static void rleSubstractWithRle(VRleHelper *, VRleHelper *, VRleHelper *);
 
 static inline uchar divBy255(int x)
@@ -207,7 +212,7 @@ void VRle::VRleData::opSubstract(const VRle::VRleData &a,
     mBboxDirty = true;
 }
 
-void VRle::VRleData::opAdd(const VRle::VRleData &a, const VRle::VRleData &b)
+void VRle::VRleData::opGeneric(const VRle::VRleData &a, const VRle::VRleData &b, OpCode code)
 {
     // This routine assumes, obj1(span_y) < obj2(span_y).
 
@@ -256,9 +261,20 @@ void VRle::VRleData::opAdd(const VRle::VRleData &a, const VRle::VRleData &b)
         bObj.size = b.mSpans.size() - sizeB;
         bObj.spans = bPtr;
 
+        Operation op = Operation::Add;
+        switch (code) {
+        case OpCode::Add:
+            op = Operation::Add;
+            break;
+        case OpCode::Xor:
+            op = Operation::Xor;
+            break;
+        default:
+            break;
+        }
         // run till all the spans are processed
         while (aObj.size && bObj.size) {
-            rleAddWithRle(&aObj, &bObj, &tresult);
+            rleOpGeneric(&aObj, &bObj, &tresult, op);
             if (tresult.size) {
                 copyArrayToVector(tresult.spans, tresult.size, mSpans);
             }
@@ -443,6 +459,23 @@ static void rleIntersectWithRect(const VRect &clip, VRleHelper *tmp_obj,
     result->size = result->alloc - available;
 }
 
+void blitXor(VRle::Span *spans, int count, uchar *buffer,
+                        int offsetX)
+{
+    uchar *ptr;
+    while (count--) {
+        int x = spans->x + offsetX;
+        int l = spans->len;
+        ptr = buffer + x;
+        while (l--) {
+            int da = *ptr;
+            *ptr = divBy255((255 - spans->coverage) * (da) + spans->coverage * (255 - da));
+            ptr++;
+        }
+        spans++;
+    }
+}
+
 void blitDestinationOut(VRle::Span *spans, int count, uchar *buffer,
                         int offsetX)
 {
@@ -522,7 +555,7 @@ int bufferToRle(uchar *buffer, int size, int offsetX, int y, VRle::Span *out)
     return count;
 }
 
-static void rleAddWithRle(VRleHelper *a, VRleHelper *b, VRleHelper *result)
+static void rleOpGeneric(VRleHelper *a, VRleHelper *b, VRleHelper *result, Operation op)
 {
     std::array<VRle::Span, 256> temp;
     VRle::Span *                out = result->spans;
@@ -554,7 +587,10 @@ static void rleAddWithRle(VRleHelper *a, VRleHelper *b, VRleHelper *result)
 
             std::array<uchar, 1024> array = {{0}};
             blit(aStart, (aPtr - aStart), array.data(), -offset);
-            blitSrcOver(bStart, (bPtr - bStart), array.data(), -offset);
+            if (op == Operation::Add)
+                blitSrcOver(bStart, (bPtr - bStart), array.data(), -offset);
+            else if (op == Operation::Xor)
+                blitXor(bStart, (bPtr - bStart), array.data(), -offset);
             VRle::Span *tResult = temp.data();
             int size = bufferToRle(array.data(), std::max(aLength, bLength),
                                    offset, y, tResult);
index 9a45824..e5ecc36 100644 (file)
@@ -34,11 +34,16 @@ public:
     VRle operator&(const VRle &o) const;
     VRle operator-(const VRle &o) const;
     VRle operator+(const VRle &o) const;
+    VRle operator^(const VRle &o) const;
 
     static VRle toRle(const VRect &rect);
 
 private:
     struct VRleData {
+        enum class OpCode {
+            Add,
+            Xor
+        };
         bool  isEmpty() const { return mSpans.empty(); }
         void  addSpan(const VRle::Span *span, int count);
         void  updateBbox() const;
@@ -48,7 +53,7 @@ private:
         void  operator*=(int alpha);
         void  invert();
         void  opIntersect(const VRect &, VRle::VRleSpanCb, void *) const;
-        void  opAdd(const VRle::VRleData &, const VRle::VRleData &);
+        void  opGeneric(const VRle::VRleData &, const VRle::VRleData &, OpCode code);
         void  opSubstract(const VRle::VRleData &, const VRle::VRleData &);
         void  opIntersect(const VRle::VRleData &, const VRle::VRleData &);
         void  addRect(const VRect &rect);
@@ -102,7 +107,18 @@ inline VRle VRle::operator+(const VRle &o) const
     if (o.isEmpty()) return *this;
 
     VRle result;
-    result.d.write().opAdd(d.read(), o.d.read());
+    result.d.write().opGeneric(d.read(), o.d.read(), VRleData::OpCode::Add);
+
+    return result;
+}
+
+inline VRle VRle::operator^(const VRle &o) const
+{
+    if (isEmpty()) return o;
+    if (o.isEmpty()) return *this;
+
+    VRle result;
+    result.d.write().opGeneric(d.read(), o.d.read(), VRleData::OpCode::Xor);
 
     return result;
 }