summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorsubhransu mohanty <sub.mohanty@samsung.com>2018-07-09 19:16:39 +0900
committersubhransu mohanty <sub.mohanty@samsung.com>2018-07-09 19:16:39 +0900
commit0bcd85feed10e8d73becbebb8541aed5e2ce246f (patch)
tree6b105e09320de66b50dcb1b4b009bc3055cb9e25
parent4904ff62ef9afa35fe8320cd1d2f7bd388b3c292 (diff)
lottie: added masking feature and opened lottieplayer object.
-rw-r--r--include/lottiemodel.h40
-rw-r--r--include/lottieplayer.h5
-rw-r--r--include/meson.build3
-rw-r--r--include/sgrect.h4
-rw-r--r--include/sgrle.h6
-rw-r--r--src/lottie/lottieitem.cpp80
-rw-r--r--src/lottie/lottieitem.h34
-rw-r--r--src/lottie/lottieparser.cpp61
-rw-r--r--src/util/sgrle.cpp214
9 files changed, 311 insertions, 136 deletions
diff --git a/include/lottiemodel.h b/include/lottiemodel.h
index 32a00d5..f72e9f9 100644
--- a/include/lottiemodel.h
+++ b/include/lottiemodel.h
@@ -10,6 +10,7 @@
10#include"sgmatrix.h" 10#include"sgmatrix.h"
11#include"sgbezier.h" 11#include"sgbezier.h"
12#include"vbrush.h" 12#include"vbrush.h"
13#include"sgpath.h"
13 14
14 15
15class LOTCompositionData; 16class LOTCompositionData;
@@ -28,6 +29,7 @@ class LOTGFillData;
28class LOTGStrokeData; 29class LOTGStrokeData;
29class LottieShapeData; 30class LottieShapeData;
30class LOTPolystarData; 31class LOTPolystarData;
32class LOTMaskData;
31 33
32class LOTDataVisitor 34class LOTDataVisitor
33{ 35{
@@ -100,6 +102,22 @@ inline const LottieColor operator*(float m, const LottieColor &c)
100class LottieShapeData 102class LottieShapeData
101{ 103{
102public: 104public:
105 SGPath toPath() const{
106 if (mPoints.empty()) return SGPath();
107
108 SGPath path;
109 int size = mPoints.size();
110 const SGPointF *points = mPoints.data();
111 path.moveTo(points[0]);
112 for (int i = 1 ; i < size; i+=3) {
113 path.cubicTo(points[i], points[i+1], points[i+2]);
114 }
115 if (mClosed)
116 path.close();
117
118 return path;
119 }
120public:
103 std::vector<SGPointF> mPoints; 121 std::vector<SGPointF> mPoints;
104 bool mClosed = false; /* "c" */ 122 bool mClosed = false; /* "c" */
105}; 123};
@@ -373,7 +391,7 @@ public:
373 mMatteType(MatteType::None), 391 mMatteType(MatteType::None),
374 mParentId(-1), 392 mParentId(-1),
375 mId(-1), 393 mId(-1),
376 mHasPathOperator(false){} 394 mHasPathOperator(false), mHasMask(false){}
377 inline bool hasPathOperator() const noexcept {return mHasPathOperator;} 395 inline bool hasPathOperator() const noexcept {return mHasPathOperator;}
378 inline int id() const noexcept{ return mId;} 396 inline int id() const noexcept{ return mId;}
379 inline int parentId() const noexcept{ return mParentId;} 397 inline int parentId() const noexcept{ return mParentId;}
@@ -403,6 +421,8 @@ public:
403 }; 421 };
404 SolidLayer mSolidLayer; 422 SolidLayer mSolidLayer;
405 bool mHasPathOperator; 423 bool mHasPathOperator;
424 bool mHasMask;
425 std::vector<std::shared_ptr<LOTMaskData>> mMasks;
406}; 426};
407 427
408class LOTTransformData : public LOTData 428class LOTTransformData : public LOTData
@@ -605,6 +625,24 @@ public:
605 LOTAnimatable<LottieShapeData> mShape; 625 LOTAnimatable<LottieShapeData> mShape;
606}; 626};
607 627
628class LOTMaskData
629{
630public:
631 enum class Mode {
632 None,
633 Add,
634 Substarct,
635 Intersect
636 };
637 LOTMaskData():mInv(false){}
638 inline float opacity(int frameNo) const {return mOpacity.value(frameNo)/100.0;}
639public:
640 LOTAnimatable<LottieShapeData> mShape;
641 LOTAnimatable<float> mOpacity;
642 bool mInv;
643 LOTMaskData::Mode mMode;
644};
645
608class LOTRectData : public LOTPath 646class LOTRectData : public LOTPath
609{ 647{
610public: 648public:
diff --git a/include/lottieplayer.h b/include/lottieplayer.h
index 3a84cf8..408dde3 100644
--- a/include/lottieplayer.h
+++ b/include/lottieplayer.h
@@ -19,7 +19,7 @@ struct LOTBuffer
19 bool clear; 19 bool clear;
20}; 20};
21 21
22class LOTPlayer 22class SG_EXPORT LOTPlayer
23{ 23{
24public: 24public:
25 ~LOTPlayer(); 25 ~LOTPlayer();
@@ -54,7 +54,7 @@ public:
54#define ChangeFlagPaint 0x0010 54#define ChangeFlagPaint 0x0010
55#define ChangeFlagAll (ChangeFlagPath & ChangeFlagPaint) 55#define ChangeFlagAll (ChangeFlagPath & ChangeFlagPaint)
56 56
57class LOTNode 57class SG_EXPORT LOTNode
58{ 58{
59public: 59public:
60 struct PathData { 60 struct PathData {
@@ -128,6 +128,7 @@ public:
128 SGPath mFinalPath; 128 SGPath mFinalPath;
129 SGRle mRleInfo; 129 SGRle mRleInfo;
130 VBrush mBrush; 130 VBrush mBrush;
131 SGRle mMaskRle;
131}; 132};
132 133
133#endif // LOTPLAYER_H 134#endif // LOTPLAYER_H
diff --git a/include/meson.build b/include/meson.build
index 568d597..e415fb8 100644
--- a/include/meson.build
+++ b/include/meson.build
@@ -4,5 +4,6 @@ install_headers([
4 'sgglobal.h', 4 'sgglobal.h',
5 'sgregion.h', 5 'sgregion.h',
6 'sgnode.h', 6 'sgnode.h',
7 'sgmatrix.h'], 7 'sgmatrix.h',
8 'lottieplayer.h'],
8 subdir: 'ssg') 9 subdir: 'ssg')
diff --git a/include/sgrect.h b/include/sgrect.h
index c3696e2..5172d2c 100644
--- a/include/sgrect.h
+++ b/include/sgrect.h
@@ -42,8 +42,8 @@ private:
42 42
43inline bool SGRect::intersects(const SGRect &r) 43inline bool SGRect::intersects(const SGRect &r)
44{ 44{
45 return (right() >= r.left() && left() <= r.right() && 45 return (right() > r.left() && left() < r.right() &&
46 bottom() >= r.top() && top() <= r.bottom()); 46 bottom() > r.top() && top() < r.bottom());
47} 47}
48 48
49inline SGDebug& operator<<(SGDebug& os, const SGRect& o) 49inline SGDebug& operator<<(SGDebug& os, const SGRect& o)
diff --git a/include/sgrle.h b/include/sgrle.h
index 46db345..c4a5bc3 100644
--- a/include/sgrle.h
+++ b/include/sgrle.h
@@ -39,8 +39,8 @@ public:
39 SGRle operator-(const SGRle &o) const; 39 SGRle operator-(const SGRle &o) const;
40 SGRle operator&(const SGRle &o) const; 40 SGRle operator&(const SGRle &o) const;
41 static SGRle toRle(const SGRectF &rect); 41 static SGRle toRle(const SGRectF &rect);
42 friend SGRle operator*(const SGRle &, float alpha); 42 friend SGRle operator*(const SGRle &, int alpha);
43 inline friend SGRle operator*(float alpha, const SGRle &); 43 inline friend SGRle operator*(int alpha, const SGRle &);
44 friend SGDebug& operator<<(SGDebug& os, const SGRle& object); 44 friend SGDebug& operator<<(SGDebug& os, const SGRle& object);
45private: 45private:
46 SGRle copy() const; 46 SGRle copy() const;
@@ -54,7 +54,7 @@ inline void SGRle::translate(int x, int y)
54 translate(SGPoint(x,y)); 54 translate(SGPoint(x,y));
55} 55}
56 56
57inline SGRle operator*(float alpha, const SGRle &rle) 57inline SGRle operator*(int alpha, const SGRle &rle)
58{ 58{
59 return (rle * alpha); 59 return (rle * alpha);
60} 60}
diff --git a/src/lottie/lottieitem.cpp b/src/lottie/lottieitem.cpp
index dc81477..0e887a5 100644
--- a/src/lottie/lottieitem.cpp
+++ b/src/lottie/lottieitem.cpp
@@ -144,8 +144,12 @@ bool LOTCompItem::render(const LOTBuffer &buffer)
144 } 144 }
145 VBrush brush(i->mColor.r, i->mColor.g, i->mColor.b, i->mColor.a); 145 VBrush brush(i->mColor.r, i->mColor.g, i->mColor.b, i->mColor.a);
146 painter.setBrush(brush); 146 painter.setBrush(brush);
147 painter.drawRle(SGPoint(), i->mRleInfo); 147 if (!i->mMaskRle.isEmpty()) {
148 148 SGRle rle = i->mRleInfo + i->mMaskRle;
149 painter.drawRle(SGPoint(), rle);
150 } else {
151 painter.drawRle(SGPoint(), i->mRleInfo);
152 }
149 } else if(i->mType == LOTNode::Type::TypeStroke) { 153 } else if(i->mType == LOTNode::Type::TypeStroke) {
150 if (i->mFlag & ChangeFlagPath) { 154 if (i->mFlag & ChangeFlagPath) {
151 SGPath final = i->mFinalPath; 155 SGPath final = i->mFinalPath;
@@ -176,13 +180,67 @@ bool LOTCompItem::render(const LOTBuffer &buffer)
176 return true; 180 return true;
177} 181}
178 182
183void LOTMaskItem::update(int frameNo, const SGMatrix &parentMatrix,
184 float parentAlpha, const DirtyFlag &flag)
185{
186 if (mData->mShape.isStatic()) {
187 if (mLocalPath.isEmpty()) {
188 mLocalPath = mData->mShape.value(frameNo).toPath();
189 }
190 } else {
191 mLocalPath = mData->mShape.value(frameNo).toPath();
192 }
193 float opacity = mData->opacity(frameNo);
194 opacity = opacity * parentAlpha;
195
196 SGPath path = mLocalPath;
197 path.transform(parentMatrix);
198
199 FTOutline *outline = FTRaster::toFTOutline(path);
200 mRle = FTRaster::instance().generateFillInfo(outline);
201 FTRaster::deleteFTOutline(outline);
202
203 mRle = mRle * (opacity * 255);
204
205 if (mData->mInv) {
206 mRle = ~mRle;
207 }
208}
209
210SGRle LOTLayerItem::maskRle()
211{
212 SGRle rle;
213 for (auto &i : mMasks) {
214 switch (i->maskMode()) {
215 case LOTMaskData::Mode::Add: {
216 rle = rle + i->mRle;
217 break;
218 }
219 case LOTMaskData::Mode::Substarct: {
220 rle = rle - i->mRle;
221 break;
222 }
223 case LOTMaskData::Mode::Intersect: {
224 rle = rle & i->mRle;
225 break;
226 }
227 default:
228 break;
229 }
230 }
231 return rle;
232}
179 233
180LOTLayerItem::LOTLayerItem(LOTLayerData *layerData):mLayerData(layerData), 234LOTLayerItem::LOTLayerItem(LOTLayerData *layerData):mLayerData(layerData),
181 mParentLayer(nullptr), 235 mParentLayer(nullptr),
182 mFrameNo(-1), 236 mFrameNo(-1),
183 mDirtyFlag(DirtyFlagBit::All) 237 mDirtyFlag(DirtyFlagBit::All)
184{ 238{
185 239 if (mLayerData->mHasMask) {
240 for (auto i : mLayerData->mMasks) {
241 mMasks.push_back(std::unique_ptr<LOTMaskItem>(new LOTMaskItem(i.get())));
242 }
243 }
186} 244}
187 245
188void LOTLayerItem::updateStaticProperty() 246void LOTLayerItem::updateStaticProperty()
@@ -203,6 +261,12 @@ void LOTLayerItem::update(int frameNo, const SGMatrix &parentMatrix, float paren
203 SGMatrix m = matrix(frameNo) * parentMatrix; 261 SGMatrix m = matrix(frameNo) * parentMatrix;
204 float alpha = parentAlpha * opacity(frameNo); 262 float alpha = parentAlpha * opacity(frameNo);
205 263
264 //6. update the mask
265 if (hasMask()) {
266 for (auto &i : mMasks)
267 i->update(frameNo, m, alpha, mDirtyFlag);
268 }
269
206 // 3. update the dirty flag based on the change 270 // 3. update the dirty flag based on the change
207 if (flag() & DirtyFlagBit::All) { 271 if (flag() & DirtyFlagBit::All) {
208 mCombinedMatrix = m; 272 mCombinedMatrix = m;
@@ -253,6 +317,8 @@ bool LOTLayerItem::visible() const
253 return false; 317 return false;
254} 318}
255 319
320
321
256LOTCompLayerItem::LOTCompLayerItem(LOTLayerData *layerModel):LOTLayerItem(layerModel) 322LOTCompLayerItem::LOTCompLayerItem(LOTLayerData *layerModel):LOTLayerItem(layerModel)
257{ 323{
258 for(auto i : mLayerData->mChildren) { 324 for(auto i : mLayerData->mChildren) {
@@ -321,7 +387,9 @@ void LOTSolidLayerItem::updateContent()
321 mRenderNode->mType = LOTNode::Type::TypeFill; 387 mRenderNode->mType = LOTNode::Type::TypeFill;
322 mRenderNode->mFlag |= ChangeFlagAll; 388 mRenderNode->mFlag |= ChangeFlagAll;
323 } 389 }
324 390 if (hasMask()) {
391 mRenderNode->mMaskRle = maskRle();
392 }
325 if (flag() & DirtyFlagBit::Matrix) { 393 if (flag() & DirtyFlagBit::Matrix) {
326 SGPath path; 394 SGPath path;
327 path.addRect(SGRectF(0, 0, mLayerData->solidWidth(), mLayerData->solidHeight())); 395 path.addRect(SGRectF(0, 0, mLayerData->solidWidth(), mLayerData->solidHeight()));
@@ -337,7 +405,9 @@ void LOTSolidLayerItem::updateContent()
337 mRenderNode->mPath.elmPtr = elmPtr; 405 mRenderNode->mPath.elmPtr = elmPtr;
338 mRenderNode->mPath.elmCount = elmSize; 406 mRenderNode->mPath.elmCount = elmSize;
339 mRenderNode->mFlag |= ChangeFlagPath; 407 mRenderNode->mFlag |= ChangeFlagPath;
340 } else if (flag() & DirtyFlagBit::Alpha) { 408 mRenderNode->mFinalPath = path;
409 }
410 if (flag() & DirtyFlagBit::Alpha) {
341 LottieColor color = mLayerData->solidColor(); 411 LottieColor color = mLayerData->solidColor();
342 SGColor c = color.toColor(combinedAlpha()); 412 SGColor c = color.toColor(combinedAlpha());
343 mRenderNode->mColor.r = c.r; 413 mRenderNode->mColor.r = c.r;
diff --git a/src/lottie/lottieitem.h b/src/lottie/lottieitem.h
index ea25a18..72aa109 100644
--- a/src/lottie/lottieitem.h
+++ b/src/lottie/lottieitem.h
@@ -20,6 +20,7 @@ enum class DirtyFlagBit
20}; 20};
21 21
22class LOTLayerItem; 22class LOTLayerItem;
23class LOTMaskItem;
23 24
24class LOTCompItem 25class LOTCompItem
25{ 26{
@@ -67,15 +68,18 @@ protected:
67 float opacity(int frameNo) const; 68 float opacity(int frameNo) const;
68 bool visible() const; 69 bool visible() const;
69 inline DirtyFlag flag() const {return mDirtyFlag;} 70 inline DirtyFlag flag() const {return mDirtyFlag;}
71 SGRle maskRle();
72 bool hasMask() const {return !mMasks.empty();}
70protected: 73protected:
71 LOTLayerData *mLayerData; 74 std::vector<std::unique_ptr<LOTMaskItem>> mMasks;
72 LOTLayerItem *mParentLayer; 75 LOTLayerData *mLayerData;
73 SGMatrix mCombinedMatrix; 76 LOTLayerItem *mParentLayer;
74 float mCombinedAlpha; 77 SGMatrix mCombinedMatrix;
75 int mFrameNo; 78 float mCombinedAlpha;
76 DirtyFlag mDirtyFlag; 79 int mFrameNo;
77 bool mVisible; 80 DirtyFlag mDirtyFlag;
78 bool mStatic; 81 bool mVisible;
82 bool mStatic;
79}; 83};
80 84
81class LOTCompLayerItem: public LOTLayerItem 85class LOTCompLayerItem: public LOTLayerItem
@@ -125,6 +129,20 @@ protected:
125 void updateContent() final; 129 void updateContent() final;
126}; 130};
127 131
132class LOTMaskItem
133{
134public:
135 LOTMaskItem(LOTMaskData *data): mData(data), mCombinedAlpha(0){}
136 void update(int frameNo, const SGMatrix &parentMatrix, float parentAlpha, const DirtyFlag &flag);
137 LOTMaskData::Mode maskMode() const { return mData->mMode;}
138public:
139 LOTMaskData *mData;
140 float mCombinedAlpha;
141 SGMatrix mCombinedMatrix;
142 SGPath mLocalPath;
143 SGRle mRle;
144};
145
128class LOTNode; 146class LOTNode;
129class LOTPathDataItem; 147class LOTPathDataItem;
130class LOTPaintDataItem; 148class LOTPaintDataItem;
diff --git a/src/lottie/lottieparser.cpp b/src/lottie/lottieparser.cpp
index 1582b3e..d81fcdd 100644
--- a/src/lottie/lottieparser.cpp
+++ b/src/lottie/lottieparser.cpp
@@ -130,8 +130,10 @@ public:
130 std::shared_ptr<LOTAsset> parseAsset(); 130 std::shared_ptr<LOTAsset> parseAsset();
131 void parseLayers(LOTCompositionData *comp); 131 void parseLayers(LOTCompositionData *comp);
132 std::shared_ptr<LOTData> parseLayer(); 132 std::shared_ptr<LOTData> parseLayer();
133 void parseMaskProperty(LOTLayerData *layer);
133 void parseShapesAttr(LOTLayerData *layer); 134 void parseShapesAttr(LOTLayerData *layer);
134 void parseObject(LOTGroupData *parent); 135 void parseObject(LOTGroupData *parent);
136 std::shared_ptr<LOTMaskData> parseMaskObject();
135 std::shared_ptr<LOTData> parseObjectTypeAttr(); 137 std::shared_ptr<LOTData> parseObjectTypeAttr();
136 std::shared_ptr<LOTData> parseGroupObject(); 138 std::shared_ptr<LOTData> parseGroupObject();
137 std::shared_ptr<LOTData> parseRectObject(); 139 std::shared_ptr<LOTData> parseRectObject();
@@ -147,6 +149,7 @@ public:
147 std::shared_ptr<LOTData> parseTrimObject(); 149 std::shared_ptr<LOTData> parseTrimObject();
148 std::shared_ptr<LOTData> parseReapeaterObject(); 150 std::shared_ptr<LOTData> parseReapeaterObject();
149 151
152
150 void parseGradientProperty(LOTGradient *gradient, const char *key); 153 void parseGradientProperty(LOTGradient *gradient, const char *key);
151 154
152 SGPointF parseInperpolatorPoint(); 155 SGPointF parseInperpolatorPoint();
@@ -697,6 +700,12 @@ LottieParserImpl::parseLayer()
697 layer->mSolidLayer.mColor = toColor(GetString()); 700 layer->mSolidLayer.mColor = toColor(GetString());
698 } else if (0 == strcmp(key, "tt")) { 701 } else if (0 == strcmp(key, "tt")) {
699 layer->mMatteType = getMatteType(); 702 layer->mMatteType = getMatteType();
703 } else if (0 == strcmp(key, "tt")) {
704 layer->mMatteType = getMatteType();
705 } else if (0 == strcmp(key, "hasMask")) {
706 layer->mHasMask = GetBool();
707 } else if (0 == strcmp(key, "masksProperties")) {
708 parseMaskProperty(layer);
700 }else { 709 }else {
701 #ifdef DEBUG_PARSER 710 #ifdef DEBUG_PARSER
702 sgWarning<<"Layer Attribute Skipped : "<<key; 711 sgWarning<<"Layer Attribute Skipped : "<<key;
@@ -717,6 +726,58 @@ LottieParserImpl::parseLayer()
717 return sharedLayer; 726 return sharedLayer;
718} 727}
719 728
729void LottieParserImpl::parseMaskProperty(LOTLayerData *layer)
730{
731 RAPIDJSON_ASSERT(PeekType() == kArrayType);
732 EnterArray();
733 while (NextArrayValue()) {
734 layer->mMasks.push_back(parseMaskObject());
735 }
736}
737
738std::shared_ptr<LOTMaskData>
739LottieParserImpl::parseMaskObject()
740{
741 std::shared_ptr<LOTMaskData> sharedMask = std::make_shared<LOTMaskData>();
742 LOTMaskData *obj = sharedMask.get();
743
744 RAPIDJSON_ASSERT(PeekType() == kObjectType);
745 EnterObject();
746 while (const char* key = NextObjectKey()) {
747 if (0 == strcmp(key, "inv")) {
748 obj->mInv = GetBool();
749 } else if (0 == strcmp(key, "mode")) {
750 const char *str = GetString();
751 switch (str[0]) {
752 case 'n':
753 obj->mMode = LOTMaskData::Mode::None;
754 break;
755 case 'a':
756 obj->mMode = LOTMaskData::Mode::Add;
757 break;
758 case 's':
759 obj->mMode = LOTMaskData::Mode::Substarct;
760 break;
761 case 'i':
762 obj->mMode = LOTMaskData::Mode::Intersect;
763 break;
764 default:
765 obj->mMode = LOTMaskData::Mode::None;
766 break;
767 }
768 } else if (0 == strcmp(key, "pt")) {
769 parseShapeProperty(obj->mShape);
770 } else if (0 == strcmp(key, "o")) {
771 parseProperty(obj->mOpacity);
772 } else {
773 Skip(key);
774 }
775 }
776 return sharedMask;
777}
778
779
780
720void LottieParserImpl::parseShapesAttr(LOTLayerData *layer) 781void LottieParserImpl::parseShapesAttr(LOTLayerData *layer)
721{ 782{
722 RAPIDJSON_ASSERT(PeekType() == kArrayType); 783 RAPIDJSON_ASSERT(PeekType() == kArrayType);
diff --git a/src/util/sgrle.cpp b/src/util/sgrle.cpp
index 6c66d0e..4cadaf3 100644
--- a/src/util/sgrle.cpp
+++ b/src/util/sgrle.cpp
@@ -18,7 +18,7 @@ struct SGRleHelper
18#define SGMIN(a,b) ((a) < (b) ? (a) : (b)) 18#define SGMIN(a,b) ((a) < (b) ? (a) : (b))
19#define SGMAX(a,b) ((a) > (b) ? (a) : (b)) 19#define SGMAX(a,b) ((a) > (b) ? (a) : (b))
20 20
21static inline int 21static inline uchar
22divBy255(int x) { return (x + (x>>8) + 0x80) >> 8; } 22divBy255(int x) { return (x + (x>>8) + 0x80) >> 8; }
23 23
24/* 24/*
@@ -180,141 +180,124 @@ rleIntersectWithRect(const SGRect &clip,
180 result->size = result->alloc - available; 180 result->size = result->alloc - available;
181} 181}
182 182
183void drawSpanlineMul(SGRle::Span *spans, int count, uchar *buffer, int offsetX)
184{
185 uchar *ptr;
186 while (count--) {
187 int x = spans->x + offsetX;
188 int l = spans->len;
189 ptr = buffer + x;
190 while (l--) {
191 uchar cov = *ptr;
192 *ptr++ = divBy255(spans->coverage * cov);
193 }
194 spans++;
195 }
196}
197
198void drawSpanline(SGRle::Span *spans, int count, uchar *buffer, int offsetX)
199{
200 uchar *ptr;
201 while (count--) {
202 int x = spans->x + offsetX;
203 int l = spans->len;
204 ptr = buffer + x;
205 while (l--) {
206 *ptr++ = spans->coverage;
207 }
208 spans++;
209 }
210}
211
212int bufferToRle(uchar *buffer, int size, int offsetX, int y, SGRle::Span *out)
213{
214 int count = 0;
215 uchar value = buffer[0];
216 int curIndex = 0;
217 for (int i = 0; i < size ; i++) {
218 uchar curValue = buffer[0];
219 if (value != curValue) {
220 out->y = y;
221 out->x = offsetX + curIndex;
222 out->len = i - curIndex;
223 out->coverage = value;
224 out++;
225 curIndex = i;
226 value = curValue;
227 count++;
228 }
229 buffer++;
230 }
231 out->y = y;
232 out->x = offsetX + curIndex;
233 out->len = size - curIndex;
234 out->coverage = value;
235 count++;
236 return count;
237}
238
183static void 239static void
184rleAddWithRle(SGRleHelper *tmp_clip, 240rleAddWithRle1(SGRleHelper *tmp_clip,
185 SGRleHelper *tmp_obj, 241 SGRleHelper *tmp_obj,
186 SGRleHelper *result) 242 SGRleHelper *result)
187{ 243{
244 std::array<SGRle::Span,256> rleHolder;
188 SGRle::Span *out = result->spans; 245 SGRle::Span *out = result->spans;
189 int available = result->alloc; 246 int available = result->alloc;
190 SGRle::Span *spans = tmp_obj->spans; 247 SGRle::Span *spans = tmp_obj->spans;
191 SGRle::Span *end = tmp_obj->spans + tmp_obj->size; 248 SGRle::Span *end = tmp_obj->spans + tmp_obj->size;
192 SGRle::Span *clipSpans = tmp_clip->spans; 249 SGRle::Span *clipSpans = tmp_clip->spans;
193 SGRle::Span *clipEnd = tmp_clip->spans + tmp_clip->size; 250 SGRle::Span *clipEnd = tmp_clip->spans + tmp_clip->size;
194 int sx1, sx2, cx1, cx2, x, len;
195
196 251
197 while (available && spans < end ) 252 while (available && spans < end && clipSpans < clipEnd) {
198 { 253 if (spans->y < clipSpans->y) {
199 if (clipSpans >= clipEnd)
200 {
201 *out++ = *spans++; 254 *out++ = *spans++;
202 available--; 255 available--;
203 break; 256 } else if (clipSpans->y < spans->y) {
204 }
205 if (clipSpans->y < spans->y)
206 {
207 *out++ = *clipSpans++;
208 available--;
209 continue;
210 }
211 if (spans->y < clipSpans->y)
212 {
213 *out++ = *spans++;
214 available--;
215 continue;
216 }
217 sx1 = spans->x;
218 sx2 = sx1 + spans->len;
219 cx1 = (clipSpans->x);
220 cx2 = cx1 + clipSpans->len;
221
222 if (cx1 < sx1 && cx2 < sx1) {
223 *out++ = *clipSpans++; 257 *out++ = *clipSpans++;
224 available--; 258 available--;
225 continue; 259 } else { // same y
226 } else if (sx1 < cx1 && sx2 < cx1) { 260 int y = spans->y;
227 *out++ = *spans++; 261 SGRle::Span *spanPtr = spans;
228 available--; 262 SGRle::Span *clipPtr = clipSpans;
229 continue; 263
230 } else if (spans->coverage == clipSpans->coverage) { //merge 264 while (spanPtr < end && spanPtr->y == y) spanPtr++;
231 out->x = SGMIN(cx1, sx1); 265 while (clipPtr < clipEnd && clipPtr->y == y) clipPtr++;
232 out->len = SGMAX(cx2, sx2) - out->x; 266
233 out->coverage = spans->coverage; 267 int spanLength = (spanPtr-1)->x + (spanPtr-1)->len - spans->x;
234 out->y = spans->y; 268 int clipLength = (clipPtr-1)->x + (clipPtr-1)->len - clipSpans->x;
235 out++; spans++ ; clipSpans++; available--; 269 int offsetX = SGMIN(spans->x, clipSpans->x);
236 } else if (cx1 <= sx1) { 270 std::array<uchar,1024> array = {0};
237 if (available < 3) 271 drawSpanline(spans, (spanPtr - spans), array.data(), -offsetX);
238 break; 272 drawSpanlineMul(clipSpans, (clipPtr - clipSpans), array.data(), -offsetX);
239 // segment 1 273 SGRle::Span *rleHolderPtr = rleHolder.data();
240 int l = sx1 - cx1; 274 int size = bufferToRle(array.data(), SGMAX(spanLength, clipLength),
241 if (l) { 275 offsetX, y, rleHolderPtr);
242 *out = *clipSpans; 276 if (available >= size) {
243 out->len = sx1 - cx1; 277 while(size--) {
244 out++; available--; 278 *out++ = *rleHolderPtr++;
245 } 279 available--;
246 // segment 2
247 l = SGMIN(cx2, sx2) - sx1;
248 if (l) {
249 *out = *spans;
250 out->len = l;
251 out->coverage = divBy255(spans->coverage * clipSpans->coverage);
252 out++; available--;
253 }
254 // segment 3
255 if (cx2 <= sx2) {
256 l = sx2 - cx2;
257 if (l) {
258 *out = *spans;
259 out->len = l;
260 out->x = cx2; //+1 ?
261 } 280 }
262 } else { 281 } else {
263 *out = *clipSpans;
264 out->len = cx2 - sx2;
265 out->x = sx2;//+1 ?
266 }
267 clipSpans++; spans++;
268 } else if (sx1 < cx1) {
269 if (available < 3)
270 break; 282 break;
271 // segment 1
272 int l = cx1 - sx1;
273 *out = *spans;
274 out->len = l;
275 out++; available--;
276
277 // segment 2
278 l = SGMIN(cx2, sx2) - cx1;
279 if (l) {
280 *out = *clipSpans;
281 out->len = l;
282 out->coverage = divBy255(spans->coverage * clipSpans->coverage);
283 out++; available--;
284 }
285 // segment 3
286 if (cx2 <= sx2) {
287 l = sx2 - cx2;
288 if (l) {
289 *out = *spans;
290 out->len = l;
291 out->x = cx2;//+1 ?
292 out++; available--;
293 }
294 } else {
295 *out = *clipSpans;
296 out->len = cx2 - sx2;
297 out->x = sx2;//+1 ?
298 out++; available--;
299 } 283 }
300 clipSpans++; spans++; 284 spans = spanPtr;
285 clipSpans = clipPtr;
301 } 286 }
302 } 287 }
288 // update the span list that yet to be processed
289 tmp_obj->spans = spans;
290 tmp_obj->size = end - spans;
303 291
304 // update the span list that yet to be processed 292 // update the clip list that yet to be processed
305 tmp_obj->spans = spans; 293 tmp_clip->spans = clipSpans;
306 tmp_obj->size = end - spans; 294 tmp_clip->size = clipEnd - clipSpans;
307 295
308 // update the clip list that yet to be processed 296 // update the result
309 tmp_clip->spans = clipSpans; 297 result->size = result->alloc - available;
310 tmp_clip->size = clipEnd - clipSpans;
311
312 // update the result
313 result->size = result->alloc - available;
314} 298}
315 299
316 300
317
318class SGRleImpl 301class SGRleImpl
319{ 302{
320public: 303public:
@@ -485,9 +468,9 @@ void SGRleImpl::opAdd(const SGRleImpl &other, SGRleImpl &result)
485 tmp_other.spans = const_cast<SGRle::Span *>(other.m_spans.data()); 468 tmp_other.spans = const_cast<SGRle::Span *>(other.m_spans.data());
486 469
487 // run till all the spans are processed 470 // run till all the spans are processed
488 while (tmp_obj.size) 471 while (tmp_obj.size && tmp_other.size)
489 { 472 {
490 rleAddWithRle(&tmp_other, &tmp_obj, &tresult); 473 rleAddWithRle1(&tmp_other, &tmp_obj, &tresult);
491 if (tresult.size) { 474 if (tresult.size) {
492 copyArrayToVector(tresult.spans, tresult.size, result.m_spans); 475 copyArrayToVector(tresult.spans, tresult.size, result.m_spans);
493 } 476 }
@@ -497,6 +480,9 @@ void SGRleImpl::opAdd(const SGRleImpl &other, SGRleImpl &result)
497 if (tmp_other.size) { 480 if (tmp_other.size) {
498 copyArrayToVector(tmp_other.spans, tmp_other.size, result.m_spans); 481 copyArrayToVector(tmp_other.spans, tmp_other.size, result.m_spans);
499 } 482 }
483 if (tmp_obj.size) {
484 copyArrayToVector(tmp_obj.spans, tmp_obj.size, result.m_spans);
485 }
500 } 486 }
501 487
502 // update result bounding box 488 // update result bounding box
@@ -769,7 +755,7 @@ SGRle &SGRle::intersect(const SGRect &r)
769 return *this = result; 755 return *this = result;
770} 756}
771 757
772SGRle operator*(const SGRle &obj, float alpha) 758SGRle operator*(const SGRle &obj, int alpha)
773{ 759{
774 if (obj.isEmpty()) return obj; 760 if (obj.isEmpty()) return obj;
775 761