[NUI] CanvasView: Add ClipPath and Mask feature for Drawable (#3346)
authorJunsuChoi <jsuya.choi@samsung.com>
Fri, 30 Jul 2021 00:26:11 +0000 (09:26 +0900)
committerdongsug-song <35130733+dongsug-song@users.noreply.github.com>
Tue, 3 Aug 2021 01:50:50 +0000 (10:50 +0900)
* [NUI] CanvasView: Add ClipPath and Mask feature for Drawable

Shape and DrawableGroup, which inherit drawable class,
can clipping and masking using ClipPath and Mask methods.

* [NUI] CanvasView: Change return type of Mask and ClipPath methods

Throws an exception when masking and clipping fail.

src/Tizen.NUI/src/internal/Interop/Interop.Drawable.cs
src/Tizen.NUI/src/public/BaseComponents/VectorGraphics/Drawable.cs
test/Tizen.NUI.Samples/Tizen.NUI.Samples/Samples/CanvasViewSamsple.cs

index fb724f4..b37143d 100755 (executable)
@@ -45,6 +45,14 @@ namespace Tizen.NUI
 
             [global::System.Runtime.InteropServices.DllImport(NDalicPINVOKE.Lib, EntryPoint = "CSharp_Dali_Drawable_GetBoundingBox")]
             public static extern global::System.IntPtr GetBoundingBox(global::System.Runtime.InteropServices.HandleRef jarg1);
+
+            [global::System.Runtime.InteropServices.DllImport(NDalicPINVOKE.Lib, EntryPoint = "CSharp_Dali_Drawable_SetClipPath")]
+            [return: global::System.Runtime.InteropServices.MarshalAs(global::System.Runtime.InteropServices.UnmanagedType.U1)]
+            public static extern bool SetClipPath(global::System.Runtime.InteropServices.HandleRef jarg1, global::System.Runtime.InteropServices.HandleRef jarg2);
+
+            [global::System.Runtime.InteropServices.DllImport(NDalicPINVOKE.Lib, EntryPoint = "CSharp_Dali_Drawable_SetMask")]
+            [return: global::System.Runtime.InteropServices.MarshalAs(global::System.Runtime.InteropServices.UnmanagedType.U1)]
+            public static extern bool SetMask(global::System.Runtime.InteropServices.HandleRef jarg1, global::System.Runtime.InteropServices.HandleRef jarg2, int jarg3);
         }
     }
 }
index f59a510..6d5c29b 100755 (executable)
@@ -36,6 +36,22 @@ namespace Tizen.NUI.BaseComponents.VectorGraphics
         }
 
         /// <summary>
+        /// Enumeration indicating the type used in the masking of two objects - the mask drawable and the own drawable.
+        /// </summary>
+        [EditorBrowsable(EditorBrowsableState.Never)]
+        public enum MaskType
+        {
+            /// <summary>
+            /// The pixels of the own drawable and the mask drawable are alpha blended. As a result, only the part of the own drawable, which intersects with the mask drawable is visible.
+            /// </summary>
+            Alpha = 0,
+            /// <summary>
+            /// The pixels of the own drawable and the complement to the mask drawable's pixels are alpha blended. As a result, only the part of the own which is not covered by the mask is visible.
+            /// </summary>
+            AlphaInverse
+        }
+
+        /// <summary>
         /// The transparency level [0 ~ 1.0], 0 means totally transparent, while 1 means opaque.
         /// </summary>
         /// <since_tizen> 9 </since_tizen>
@@ -85,6 +101,49 @@ namespace Tizen.NUI.BaseComponents.VectorGraphics
         }
 
         /// <summary>
+        /// The intersection with clip drawable is determined and only the resulting pixels from own drawable are rendered.
+        /// </summary>
+        /// <param name="clip">The clip drawable object.</param>
+        /// <exception cref="Exception"> Drawable clpping failed. </exception>
+        /// <exception cref="ArgumentNullException"> Thrown when drawable is null. </exception>
+        [EditorBrowsable(EditorBrowsableState.Never)]
+        public void ClipPath(Drawable clip)
+        {
+            if (clip == null)
+            {
+                throw new ArgumentNullException(nameof(clip));
+            }
+            bool ret = Interop.Drawable.SetClipPath(View.getCPtr(this), BaseHandle.getCPtr(clip));
+            if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
+            if (!ret)
+            {
+                throw new Exception("Drawable clipping failed or clip drawable is already added other drawable or canvas.");
+            }
+        }
+
+        /// <summary>
+        /// The pixels of mask drawable and own drawable are blended according to MaskType.
+        /// </summary>
+        /// <param name="mask">The mask drawable object.</param>
+        /// <param name="type">The masking type.</param>
+        /// <exception cref="Exception"> Drawable masking failed. </exception>
+        /// <exception cref="ArgumentNullException"> Thrown when drawable is null. </exception>
+        [EditorBrowsable(EditorBrowsableState.Never)]
+        public void Mask(Drawable mask, MaskType type)
+        {
+            if (mask == null)
+            {
+                throw new ArgumentNullException(nameof(mask));
+            }
+            bool ret = Interop.Drawable.SetMask(View.getCPtr(this), BaseHandle.getCPtr(mask), (int)type);
+            if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
+            if (!ret)
+            {
+                throw new Exception("Drawable masking failed or mask drawable is already added other drawable or canvas.");
+            }
+        }
+
+        /// <summary>
         /// Set the angle of rotation transformation.
         /// </summary>
         /// <param name="degree">The degree value of angle.</param>
index b16dff7..c494838 100644 (file)
@@ -54,6 +54,13 @@ namespace Tizen.NUI.Samples
             roundedRectShape.Rotate(45.0f);
             roundedRectShape.AddRect(-50.0f, -50.0f, 100.0f, 100.0f, 0.0f, 0.0f);
 
+            Shape circleMask = new Shape()
+            {
+                FillColor = new Color(1.0f, 1.0f, 1.0f, 1.0f),
+            };
+            circleMask.AddRect(-50.0f, -50.0f, 100.0f, 100.0f, 0.0f, 0.0f);
+            circleMask.Translate(350.0f, 100.0f);
+
             circleShape = new Shape()
             {
                 Opacity = 0.5f,
@@ -65,6 +72,8 @@ namespace Tizen.NUI.Samples
             circleShape.AddCircle(0.0f, 0.0f, 150.0f, 100.0f);
             circleShape.Transform(new float[] { 0.6f, 0.0f, 350.0f, 0.0f, 0.6f, 100.0f, 0.0f, 0.0f, 1.0f });
 
+            circleShape.Mask(circleMask, Drawable.MaskType.Alpha);
+
             arcShape = new Shape()
             {
                 StrokeColor = new Color(0.0f, 0.5f, 0.0f, 0.5f),
@@ -94,6 +103,13 @@ namespace Tizen.NUI.Samples
 
             canvasView.AddDrawable(shape);
 
+            Shape starClipper = new Shape()
+            {
+                FillColor = new Color(1.0f, 1.0f, 1.0f, 1.0f),
+            };
+            starClipper.AddCircle(0.0f, 0.0f, 160.0f, 160.0f);
+            starClipper.Translate(250.0f, 550.0f);
+
             starShape = new Shape()
             {
                 Opacity = 0.5f,
@@ -116,8 +132,9 @@ namespace Tizen.NUI.Samples
             starShape.AddLineTo(-54.0f, -56.0f);
             starShape.Close();
 
-            canvasView.AddDrawable(starShape);
+            starShape.ClipPath(starClipper);
 
+            canvasView.AddDrawable(starShape);
 
             group1 = new DrawableGroup();
             group1.AddDrawable(roundedRectShape);