V_BEGIN_NAMESPACE
+enum class Operation {
+ Add,
+ Xor
+};
+
struct VRleHelper {
ushort alloc;
ushort size;
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)
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).
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);
}
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)
{
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;
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);
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;
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);
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;
}