canvas/paint: ++exception handling 50/320150/1
authorjoogab.yun <joogab.yun@samsung.com>
Wed, 6 Nov 2024 05:58:02 +0000 (14:58 +0900)
committerjoogab.yun <joogab.yun@samsung.com>
Fri, 8 Nov 2024 08:16:29 +0000 (17:16 +0900)
enhanced reference count verification
to prevent unintentional deletion of used composition targets.

Change-Id: I71c3339eea1d57cad7b6631a5756acde6d15aefa

src/lib/tvgCommon.h
src/lib/tvgPaint.h
src/lib/tvgShapeImpl.h

index 9d36c675b8536b58c73001d471df94cdd8a8d3fb..fbc82c2c1a35dc7b960e910c1d4e9a642608a797 100644 (file)
@@ -83,4 +83,7 @@ enum class FileType { Tvg = 0, Svg, Raw, Png, Jpg, Unknown };
 
 uint16_t THORVG_VERSION_NUMBER();
 
+#define P(A) ((A)->pImpl)              //Access to pimpl.
+#define PP(A) (((Paint*)(A))->pImpl)   //Access to pimpl.
+
 #endif //_TVG_COMMON_H_
index 9ec0232949df8beeb6b8960c4a97ea9704be3dd1..801c46bd5f22c3aa98fe72f8328a80e7a91b88c7 100644 (file)
@@ -67,17 +67,30 @@ namespace tvg
         uint32_t ctxFlag = ContextFlag::Invalid;
         uint32_t id;
         uint8_t opacity = 255;
+        uint8_t refCnt = 0;
 
         ~Impl()
         {
             if (compData) {
-                delete(compData->target);
+                if (P(compData->target)->unref() == 0) delete(compData->target);
                 free(compData);
             }
             if (smethod) delete(smethod);
             if (rTransform) delete(rTransform);
         }
 
+        uint8_t ref()
+        {
+            if (refCnt == 255) TVGERR("RENDERER", "Corrupted reference count!");
+            return (++refCnt);
+        }
+
+        uint8_t unref()
+        {
+            if (refCnt == 0) TVGERR("RENDERER", "Corrupted reference count!");
+            return (--refCnt);
+        }
+
         void method(StrategyMethod* method)
         {
             smethod = method;
@@ -126,7 +139,10 @@ namespace tvg
             if ((!target && method != CompositeMethod::None) || (target && method == CompositeMethod::None)) return false;
 
             if (compData) {
-                delete(compData->target);
+                P(compData->target)->unref();
+                if ((compData->target != target) && P(compData->target)->refCnt == 0) {
+                    delete(compData->target);
+                }
                 //Reset scenario
                 if (!target && method == CompositeMethod::None) {
                     free(compData);
@@ -137,6 +153,7 @@ namespace tvg
                 if (!target && method == CompositeMethod::None) return true;
                 compData = static_cast<Composite*>(calloc(1, sizeof(Composite)));
             }
+            P(target)->ref();
             compData->target = target;
             compData->source = source;
             compData->method = method;
index 74988c31dc4e0000b8e4d699352ac0c77875848a..00276f5db2d2cbc25227708bf3b183f49a6ab521 100644 (file)
@@ -115,7 +115,7 @@ struct Shape::Impl
         rs.path.cmdCnt = 0;
         rs.path.ptsCnt = 0;
 
-        flag = RenderUpdateFlag::Path;
+        flag |= RenderUpdateFlag::Path;
     }
 
     void append(const PathCommand* cmds, uint32_t cmdCnt, const Point* pts, uint32_t ptsCnt)