Add TextFitArray
authorBowon Ryu <bowon.ryu@samsung.com>
Tue, 10 Oct 2023 02:20:47 +0000 (11:20 +0900)
committerEunki Hong <h.pichulia@gmail.com>
Tue, 31 Oct 2023 14:07:28 +0000 (23:07 +0900)
Add a new function to satisfy the UX that
operates TextFit by considering the PointSize and MinLineSize of the text.

For example, TextFit should be able to find the one that
fits among [PointSize 24 + MinLineSize 40] or [PointSize 28 + MinLineSize 44].

But the previous TextFit only considers PointSize.

TextFitArray can solve this problem,
and this implemented it to respond to additional requirements without modifying the API.

https://review.tizen.org/gerrit/#/c/platform/core/uifw/dali-toolkit/+/299557/
https://review.tizen.org/gerrit/#/c/platform/core/uifw/dali-csharp-binder/+/299690/

Signed-off-by: Bowon Ryu <bowon.ryu@samsung.com>
src/Tizen.NUI/src/internal/Interop/Interop.TextLabel.cs
src/Tizen.NUI/src/public/BaseComponents/TextConstants.cs
src/Tizen.NUI/src/public/BaseComponents/TextLabel.cs
src/Tizen.NUI/src/public/BaseComponents/TextMapHelper.cs
src/Tizen.NUI/src/public/BaseComponents/TextUtils.cs
test/Tizen.NUI.Samples/Tizen.NUI.Samples/Samples/TextFitChangedSample.cs

index 23ebfe0..205cc46 100755 (executable)
@@ -1,5 +1,5 @@
 /*
- * Copyright(c) 2021 Samsung Electronics Co., Ltd.
+ * Copyright(c) 2023 Samsung Electronics Co., Ltd.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -165,6 +165,12 @@ namespace Tizen.NUI
             [global::System.Runtime.InteropServices.DllImport(NDalicPINVOKE.Lib, EntryPoint = "CSharp_Dali_TextLabel_GetTextPosition")]
             public static extern global::System.IntPtr GetTextPosition(global::System.Runtime.InteropServices.HandleRef textLabelRef, uint start, uint end);
 
+            [global::System.Runtime.InteropServices.DllImport(NDalicPINVOKE.Lib, EntryPoint = "CSharp_Dali_TextLabel_SetTextFitArray")]
+            public static extern void SetTextFitArray(global::System.Runtime.InteropServices.HandleRef textLabel, bool enable, uint arraySize, float[] pointSizeArray, float[] minLineSizeArray);
+
+            [global::System.Runtime.InteropServices.DllImport(NDalicPINVOKE.Lib, EntryPoint = "CSharp_Dali_TextLabel_GetTextFitArray")]
+            public static extern global::System.IntPtr GetTextFitArray(global::System.Runtime.InteropServices.HandleRef textLabel);
+
             [global::System.Runtime.InteropServices.DllImport(NDalicPINVOKE.Lib, EntryPoint = "CSharp_Dali_TextLabel_AnchorClickedSignal")]
             public static extern global::System.IntPtr AnchorClickedSignal(global::System.Runtime.InteropServices.HandleRef jarg1);
 
index b141b0a..85b0b0d 100644 (file)
@@ -1,4 +1,4 @@
-// Copyright (c) 2021 Samsung Electronics Co., Ltd.
+// Copyright (c) 2023 Samsung Electronics Co., Ltd.
 //
 // Licensed under the Apache License, Version 2.0 (the "License");
 // you may not use this file except in compliance with the License.
@@ -13,6 +13,7 @@
 // limitations under the License.
 
 using System;
+using System.Collections.Generic;
 using System.ComponentModel;
 using System.Diagnostics.CodeAnalysis;
 
@@ -547,6 +548,77 @@ namespace Tizen.NUI.Text
     }
 
     /// <summary>
+    /// A struct to pass data of TextFitArray's OptionList.
+    /// </summary>
+    /// <remarks>
+    /// The TextFitArrayOption struct is used as an item to TextFitArray's OptionList. <br />
+    /// See <see cref="Tizen.NUI.Text.TextFitArray"/>.
+    /// </remarks>
+    [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1815: Override equals and operator equals on value types")]
+    [EditorBrowsable(EditorBrowsableState.Never)]
+    public struct TextFitArrayOption
+    {
+        /// <summary>
+        /// Constructor.
+        /// </summary>
+        /// <param name="pointSize">The PointSize for TextFitArrayOption</param>
+        [EditorBrowsable(EditorBrowsableState.Never)]
+        public TextFitArrayOption(float pointSize)
+        {
+            PointSize = pointSize;
+            MinLineSize = null;
+        }
+
+        /// <summary>
+        /// Constructor.
+        /// </summary>
+        /// <param name="pointSize">The PointSize for TextFitArrayOption</param>
+        /// <param name="minLineSize">The MinLineSize for TextFitArrayOption</param>
+        [EditorBrowsable(EditorBrowsableState.Never)]
+        public TextFitArrayOption(float pointSize, float? minLineSize)
+        {
+            PointSize = pointSize;
+            MinLineSize = minLineSize;
+        }
+
+        /// <summary>
+        /// Point size for text fit array.
+        /// </summary>
+        [EditorBrowsable(EditorBrowsableState.Never)]
+        public float PointSize { get; set; }
+
+        /// <summary>
+        /// Min line size for text fit array.
+        /// </summary>
+        [EditorBrowsable(EditorBrowsableState.Never)]
+        public float? MinLineSize { get; set; }
+    }
+
+    /// <summary>
+    /// A struct to pass data of SetTextFitArray and GetTextFitArray methods.
+    /// </summary>
+    /// <remarks>
+    /// The TextFitArray struct is used as an argument to SetTextFitArray and GetTextFitArray methods. <br />
+    /// See <see cref="Tizen.NUI.BaseComponents.TextLabel.SetTextFitArray"/> and <see cref="Tizen.NUI.BaseComponents.TextLabel.GetTextFitArray"/>.
+    /// </remarks>
+    [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1815: Override equals and operator equals on value types")]
+    [EditorBrowsable(EditorBrowsableState.Never)]
+    public struct TextFitArray
+    {
+        /// <summary>
+        /// True to enable the text fit array or false to disable (the default value is false).
+        /// </summary>
+        [EditorBrowsable(EditorBrowsableState.Never)]
+        public bool Enable { get; set; }
+
+        /// <summary>
+        /// A List of TextFitArrayOptions.
+        /// </summary>
+        [EditorBrowsable(EditorBrowsableState.Never)]
+        public List<TextFitArrayOption> OptionList { get; set; }
+    }
+
+    /// <summary>
     /// A struct to pass data of Placeholder PropertyMap. <br />
     /// </summary>
     /// <remarks>
index 91e3659..e935960 100755 (executable)
@@ -1,5 +1,5 @@
 /*
- * Copyright(c) 2021 Samsung Electronics Co., Ltd.
+ * Copyright(c) 2023 Samsung Electronics Co., Ltd.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -1405,6 +1405,105 @@ namespace Tizen.NUI.BaseComponents
         }
 
         /// <summary>
+        /// Set TextFitArray to TextLabel. <br />
+        /// TextFitArray finds and applies the largest PointSize that fits among OptionList.
+        /// </summary>
+        /// <param name="textFitArray">The TextFitArray</param>
+        /// <remarks>
+        /// TextFitArray tries binary search by default. <br />
+        /// The precondition for TextFitArray to perform binary search is sorting in ascending order of MinLineSize. <br />
+        /// Because if MinLineSize is not sorted in ascending order, <br />
+        /// binary search cannot guarantee that it will always find the best value. <br />
+        /// In this case, the search sequentially starts from the largest PointSize. <br />
+        /// If TextFitArrayOption's MinLineSize is set to null or 0, <br />
+        /// TextFitArray is calculated without applying MinLineSize. <br />
+        /// If TextFitArray is enabled, TextLabel's MinLineSize property is ignored. <br />
+        /// See <see cref="Tizen.NUI.Text.TextFitArray"/> and <see cref="Tizen.NUI.Text.TextFitArrayOption"/>.
+        /// </remarks>
+        /// <example>
+        /// The following example demonstrates how to use the SetTextFitArray method. <br />
+        /// <code>
+        /// var textFitArray = new Tizen.NUI.Text.TextFitArray();
+        /// textFitArray.Enable = true;
+        /// textFitArray.OptionList = new List<Tizen.NUI.Text.TextFitArrayOption>()
+        /// {
+        ///     new Tizen.NUI.Text.TextFitArrayOption(12, 18),
+        ///     new Tizen.NUI.Text.TextFitArrayOption(24, 40),
+        ///     new Tizen.NUI.Text.TextFitArrayOption(28, 48),
+        ///     new Tizen.NUI.Text.TextFitArrayOption(32, 56),
+        ///     new Tizen.NUI.Text.TextFitArrayOption(50, 72),
+        /// };
+        /// label.SetTextFitArray(textFitArray);
+        /// </code>
+        /// <br />
+        /// The table below shows cases where binary search is possible and where it is not possible. <br />
+        /// <code>
+        /// [Binary search possible]
+        /// |            | List index  |  0 |  1 |  2 |  3 |
+        /// | OptionList | PointSize   | 24 | 28 | 32 | 48 |
+        /// |            | MinLineSize | 40 | 48 | 48 | 62 | << MinLineSize sorted in ascending order
+        ///                                    ^    ^
+        ///                                    same values ​are not a problem
+        ///
+        /// [Binary search not possible]
+        /// |            | List index  |  0 |  1 |  2 |  3 |
+        /// | OptionList | PointSize   | 24 | 28 | 32 | 48 |
+        /// |            | MinLineSize | 40 | 48 | 38 | 62 | << MinLineSize is not sorted in ascending order
+        ///                                         ^
+        /// </code>
+        /// </example>
+        [EditorBrowsable(EditorBrowsableState.Never)]
+        public void SetTextFitArray(TextFitArray textFitArray)
+        {
+            bool enable = textFitArray.Enable;
+            int optionListSize = textFitArray.OptionList?.Count ?? 0;
+
+            float[] pointSizeArray = new float[optionListSize];
+            float[] minLineSizeArray = new float[optionListSize];
+
+            for (int i = 0 ; i < optionListSize ; i ++)
+            {
+                TextFitArrayOption option = textFitArray.OptionList[i];
+                pointSizeArray[i] = option.PointSize;
+                minLineSizeArray[i] = option.MinLineSize ?? 0;
+            }
+
+            Interop.TextLabel.SetTextFitArray(SwigCPtr, enable, (uint)optionListSize, pointSizeArray, minLineSizeArray);
+            if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
+        }
+
+        /// <summary>
+        /// Get TextFitArray from TextLabel.
+        /// </summary>
+        /// <returns>The TextFitArray</returns>
+        /// <remarks>
+        /// See <see cref="Tizen.NUI.Text.TextFitArray"/> and <see cref="Tizen.NUI.Text.TextFitArrayOption"/>.
+        /// </remarks>
+        /// <example>
+        /// The following example demonstrates how to use the GetTextFitArray method. <br />
+        /// <code>
+        /// Tizen.NUI.Text.TextFitArray textFitArray = label.GetTextFitArray();
+        /// bool enable = textFitArray.Enable;
+        /// var optionList = textFitArray.OptionList;
+        /// foreach(Tizen.NUI.Text.TextFitArrayOption option in optionList)
+        /// {
+        ///     float pointSize = option.PointSize;
+        ///     float minLinesize = option.MinLineSize;
+        /// }
+        /// </code>
+        /// </example>
+        [EditorBrowsable(EditorBrowsableState.Never)]
+        public TextFitArray GetTextFitArray()
+        {
+            using PropertyMap textFitArrayMap = new PropertyMap(Interop.TextLabel.GetTextFitArray(SwigCPtr), true);
+            if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
+
+            TextFitArray textFitArray;
+            textFitArray = TextUtils.GetMapToTextFitArray(textFitArrayMap);
+            return textFitArray;
+        }
+
+        /// <summary>
         /// The MinLineSize property.<br />
         /// The height of the line in points. <br />
         /// If the font size is larger than the line size, it works with the font size. <br />
index d90ce64..cf04549 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright(c) 2021 Samsung Electronics Co., Ltd.
+ * Copyright(c) 2023 Samsung Electronics Co., Ltd.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -737,6 +737,16 @@ namespace Tizen.NUI.BaseComponents
             return value;
         }
 
+        internal static PropertyArray GetArrayFromMap(PropertyMap map, string key)
+        {
+            PropertyArray value = new PropertyArray();
+            using (var propertyValue = map.Find(0, key))
+            {
+                if (null != propertyValue) propertyValue.Get(value);
+            }
+            return value;
+        }
+
         internal static int? GetNullableIntFromMap(PropertyMap map, int key)
         {
             using (var propertyValue = map.Find(key))
index 93edc25..b1255b0 100755 (executable)
@@ -1,5 +1,5 @@
 /*
- * Copyright(c) 2020 Samsung Electronics Co., Ltd.
+ * Copyright(c) 2023 Samsung Electronics Co., Ltd.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -1122,6 +1122,40 @@ namespace Tizen.NUI.BaseComponents
             return fontList;
         }
 
+        /// <summary>
+        /// This method converts a TextFitArray property map to a TextFitArray and returns it.
+        /// <param name="textFitArrayMap">The TextFitArray PropertyMap.</param>
+        /// <returns> A TextFitArray struct. </returns>
+        /// </summary>
+        [EditorBrowsable(EditorBrowsableState.Never)]
+        public static TextFitArray GetMapToTextFitArray(PropertyMap textFitArrayMap)
+        {
+            var textFitArray = new TextFitArray();
+            if (textFitArrayMap != null)
+            {
+                textFitArray.Enable = TextMapHelper.GetBoolFromMap(textFitArrayMap, "enable", false);
+                textFitArray.OptionList = new List<TextFitArrayOption>();
+
+                var pointSizeArray = TextMapHelper.GetArrayFromMap(textFitArrayMap, "pointSizeArray");
+                var minLineSizeArray = TextMapHelper.GetArrayFromMap(textFitArrayMap, "minLineSizeArray");
+
+                if (pointSizeArray != null && minLineSizeArray != null && pointSizeArray.Count() == minLineSizeArray.Count())
+                {
+                    for (uint i = 0 ; i < pointSizeArray.Count() ; i ++)
+                    {
+                        using (var pointSizeValue = pointSizeArray[i])
+                        using (var minLineSizeValue = minLineSizeArray[i])
+                        {
+                            minLineSizeValue.Get(out float minLineSize);
+                            pointSizeValue.Get(out float pointSize);
+                            textFitArray.OptionList.Add(new TextFitArrayOption(pointSize, minLineSize));
+                        }
+                    }
+                }
+            }
+            return textFitArray;
+        }
+
 #if PROFILE_TV
         private const float FontSizeScaleSmall = 0.8f;
         private const float FontSizeScaleNormal = 1.0f;
index dc6d731..a2116af 100755 (executable)
@@ -1,3 +1,4 @@
+using System.Collections.Generic;
 using Tizen.NUI;
 using Tizen.NUI.BaseComponents;
 using Tizen.NUI.Components;
@@ -8,10 +9,13 @@ namespace Tizen.NUI.Samples
     public class TextFitChangedSample : IExample
     {
         private TextLabel label;
+        private TextLabel labelFitArray;
 
         public void Activate()
         {
             Window window = NUIApplication.GetDefaultWindow();
+
+            // TextFit
             var fit = new TextFit();
             fit.Enable = true;
             fit.MinSize = 5.0f;
@@ -34,6 +38,39 @@ namespace Tizen.NUI.Samples
                 TextFit textfit = label.GetTextFit();
                 Tizen.Log.Error("NUI", $"FontSize : {textfit.FontSize}\n");
             };
+
+            // TextFitArray
+            labelFitArray = new TextLabel()
+            {
+                Text = "ABCDE",
+                Size = new Size(300, 100),
+                PointSize = 10,
+                Position = new Position(100, 250),
+                BackgroundColor = Color.Yellow,
+            };
+            window.Add(labelFitArray);
+
+            var textFitArray = new Tizen.NUI.Text.TextFitArray();
+            textFitArray.Enable = true;
+            textFitArray.OptionList = new List<Tizen.NUI.Text.TextFitArrayOption>()
+            {
+                new Tizen.NUI.Text.TextFitArrayOption(5, 10),
+                new Tizen.NUI.Text.TextFitArrayOption(10, 15),
+                new Tizen.NUI.Text.TextFitArrayOption(15, 15),
+                new Tizen.NUI.Text.TextFitArrayOption(20, 25),
+                new Tizen.NUI.Text.TextFitArrayOption(50, 70),
+                new Tizen.NUI.Text.TextFitArrayOption(60, 70),
+                new Tizen.NUI.Text.TextFitArrayOption(70, 70),
+            };
+            labelFitArray.SetTextFitArray(textFitArray);
+
+            var getFitArray = labelFitArray.GetTextFitArray();
+
+            Tizen.Log.Error("NUI", $"GetTextFitArray:enable:[{getFitArray.Enable}] \n");
+            for (int i = 0 ; i < getFitArray.OptionList.Count ; i ++)
+            {
+                Tizen.Log.Error("NUI", $"GetTextFitArray:option:[{getFitArray.OptionList[i].PointSize}, {getFitArray.OptionList[i].MinLineSize}] \n");
+            }
         }
 
         public void Deactivate()