Ignore vertical line alignment when the line spacing is negative 03/274903/5
authorssabah <s.sabah@samsung.com>
Wed, 11 May 2022 14:21:06 +0000 (17:21 +0300)
committerssabah <s.sabah@samsung.com>
Mon, 30 May 2022 10:50:40 +0000 (13:50 +0300)
This is to resolved cut-off in first-line when line-spacing is negative
 and vertical line alignment is bottom or middle.

Testing code:
https://github.com/wonrst/NUI-Test/blob/main/text-vertical-line-align/verticalline.cs

This patch should be preceded by the patch below:
https://review.tizen.org/gerrit/c/platform/core/uifw/dali-toolkit/+/274097

Change-Id: I80e6d838ad08f7f34d79f6018bb44ae467c7a89a

automated-tests/src/dali-toolkit-internal/CMakeLists.txt
automated-tests/src/dali-toolkit-internal/utc-Dali-LineHelperFunctions.cpp [new file with mode: 0644]
dali-toolkit/internal/file.list
dali-toolkit/internal/text/line-helper-functions.cpp [new file with mode: 0644]
dali-toolkit/internal/text/line-helper-functions.h [new file with mode: 0644]
dali-toolkit/internal/text/rendering/text-typesetter.cpp

index 035f6c3..ebed7c6 100755 (executable)
@@ -16,6 +16,7 @@ SET(TC_SOURCES
  utc-Dali-Dictionary.cpp
  utc-Dali-FeedbackStyle.cpp
  utc-Dali-ItemView-internal.cpp
+ utc-Dali-LineHelperFunctions.cpp
  utc-Dali-LogicalModel.cpp
  utc-Dali-PropertyHelper.cpp
  utc-Dali-Text-Characters.cpp
diff --git a/automated-tests/src/dali-toolkit-internal/utc-Dali-LineHelperFunctions.cpp b/automated-tests/src/dali-toolkit-internal/utc-Dali-LineHelperFunctions.cpp
new file mode 100644 (file)
index 0000000..2930c6d
--- /dev/null
@@ -0,0 +1,228 @@
+/*
+ * Copyright (c) 2020 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#include <stdlib.h>
+#include <unistd.h>
+#include <iostream>
+
+#include <dali-toolkit-test-suite-utils.h>
+#include <dali-toolkit/dali-toolkit.h>
+#include <dali-toolkit/internal/text/line-helper-functions.h>
+#include <dali-toolkit/internal/text/rendering/text-typesetter.h>
+#include <dali-toolkit/internal/text/rendering/view-model.h>
+#include <dali-toolkit/internal/text/text-controller.h>
+#include <toolkit-text-utils.h>
+
+using namespace Dali;
+using namespace Toolkit;
+using namespace Text;
+
+int UtcDaliGetPreOffsetVerticalLineAlignmentWithNegativeLineSpacing(void)
+{
+  tet_infoline(" UtcDaliGetPreOffsetVerticalLineAlignmentWithNegativeLineSpacing ");
+  ToolkitTestApplication application;
+
+  uint32_t expectedNumberOfLines = 2u;
+
+  // Creates a text controller.
+  ControllerPtr controller = Controller::New();
+
+  // Configures the text controller similarly to the text-label.
+  ConfigureTextLabel(controller);
+
+  // Sets the text.
+  controller->SetMarkupProcessorEnabled(true);
+  controller->SetTextElideEnabled(false);
+  controller->SetText("<p rel-line-height=0.5>Line one Line two</p>");
+
+  // Creates the text's model and relais-out the text.
+  const Size relayoutSize(120.f, 100.f);
+  controller->Relayout(relayoutSize);
+
+  // Tests the rendering controller has been created.
+  TypesetterPtr typesetter = Typesetter::New(controller->GetTextModel());
+  DALI_TEST_CHECK(typesetter);
+
+  // Tests the view model has been created.
+  ViewModel* model = typesetter->GetViewModel();
+  DALI_TEST_CHECK(model);
+
+  application.SendNotification();
+  application.Render();
+
+  DALI_TEST_EQUALS(model->GetNumberOfLines(), expectedNumberOfLines, TEST_LOCATION);
+  DALI_TEST_CHECK(model->GetLines());
+
+  const LineRun& lineOne = *(model->GetLines() + 0u);
+  const LineRun& lineTwo = *(model->GetLines() + 1u);
+
+  DALI_TEST_EQUALS(GetPreOffsetVerticalLineAlignment(lineOne, Dali::Toolkit::DevelText::VerticalLineAlignment::TOP), 0.0f, TEST_LOCATION);
+  DALI_TEST_EQUALS(GetPreOffsetVerticalLineAlignment(lineOne, Dali::Toolkit::DevelText::VerticalLineAlignment::MIDDLE), 0.0f, TEST_LOCATION);
+  DALI_TEST_EQUALS(GetPreOffsetVerticalLineAlignment(lineOne, Dali::Toolkit::DevelText::VerticalLineAlignment::BOTTOM), 0.0f, TEST_LOCATION);
+
+  DALI_TEST_EQUALS(GetPreOffsetVerticalLineAlignment(lineTwo, Dali::Toolkit::DevelText::VerticalLineAlignment::TOP), 0.0f, TEST_LOCATION);
+  DALI_TEST_EQUALS(GetPreOffsetVerticalLineAlignment(lineTwo, Dali::Toolkit::DevelText::VerticalLineAlignment::MIDDLE), 0.0f, TEST_LOCATION);
+  DALI_TEST_EQUALS(GetPreOffsetVerticalLineAlignment(lineTwo, Dali::Toolkit::DevelText::VerticalLineAlignment::BOTTOM), 0.0f, TEST_LOCATION);
+  END_TEST;
+}
+
+int UtcDaliGetPreOffsetVerticalLineAlignmentWithPositiveLineSpacing(void)
+{
+  tet_infoline(" UtcDaliGetPreOffsetVerticalLineAlignmentWithPositiveLineSpacing ");
+  ToolkitTestApplication application;
+
+  uint32_t expectedNumberOfLines = 2u;
+
+  // Creates a text controller.
+  ControllerPtr controller = Controller::New();
+
+  // Configures the text controller similarly to the text-label.
+  ConfigureTextLabel(controller);
+
+  // Sets the text.
+  controller->SetMarkupProcessorEnabled(true);
+  controller->SetTextElideEnabled(false);
+  controller->SetText("<p rel-line-height=2.0>Line one Line two</p>");
+
+  // Creates the text's model and relais-out the text.
+  const Size relayoutSize(120.f, 100.f);
+  controller->Relayout(relayoutSize);
+
+  // Tests the rendering controller has been created.
+  TypesetterPtr typesetter = Typesetter::New(controller->GetTextModel());
+  DALI_TEST_CHECK(typesetter);
+
+  // Tests the view model has been created.
+  ViewModel* model = typesetter->GetViewModel();
+  DALI_TEST_CHECK(model);
+
+  application.SendNotification();
+  application.Render();
+
+  DALI_TEST_EQUALS(model->GetNumberOfLines(), expectedNumberOfLines, TEST_LOCATION);
+  DALI_TEST_CHECK(model->GetLines());
+
+  const LineRun& lineOne = *(model->GetLines() + 0u);
+  const LineRun& lineTwo = *(model->GetLines() + 1u);
+
+  DALI_TEST_EQUALS(GetPreOffsetVerticalLineAlignment(lineOne, Dali::Toolkit::DevelText::VerticalLineAlignment::TOP), 0.0f, TEST_LOCATION);
+  DALI_TEST_EQUALS(GetPreOffsetVerticalLineAlignment(lineOne, Dali::Toolkit::DevelText::VerticalLineAlignment::MIDDLE), 9.5f, TEST_LOCATION);
+  DALI_TEST_EQUALS(GetPreOffsetVerticalLineAlignment(lineOne, Dali::Toolkit::DevelText::VerticalLineAlignment::BOTTOM), 19.0f, TEST_LOCATION);
+
+  DALI_TEST_EQUALS(GetPreOffsetVerticalLineAlignment(lineTwo, Dali::Toolkit::DevelText::VerticalLineAlignment::TOP), 0.0f, TEST_LOCATION);
+  DALI_TEST_EQUALS(GetPreOffsetVerticalLineAlignment(lineTwo, Dali::Toolkit::DevelText::VerticalLineAlignment::MIDDLE), 0.0f, TEST_LOCATION);
+  DALI_TEST_EQUALS(GetPreOffsetVerticalLineAlignment(lineTwo, Dali::Toolkit::DevelText::VerticalLineAlignment::BOTTOM), 0.0f, TEST_LOCATION);
+  END_TEST;
+}
+
+int UtcDaliGetPostOffsetVerticalLineAlignmentWithNegativeLineSpacing(void)
+{
+  tet_infoline(" UtcDaliGetPostOffsetVerticalLineAlignmentWithNegativeLineSpacing ");
+  ToolkitTestApplication application;
+
+  uint32_t expectedNumberOfLines = 2u;
+
+  // Creates a text controller.
+  ControllerPtr controller = Controller::New();
+
+  // Configures the text controller similarly to the text-label.
+  ConfigureTextLabel(controller);
+
+  // Sets the text.
+  controller->SetMarkupProcessorEnabled(true);
+  controller->SetTextElideEnabled(false);
+  controller->SetText("<p rel-line-height=0.5>Line one Line two</p>");
+
+  // Creates the text's model and relais-out the text.
+  const Size relayoutSize(120.f, 100.f);
+  controller->Relayout(relayoutSize);
+
+  // Tests the rendering controller has been created.
+  TypesetterPtr typesetter = Typesetter::New(controller->GetTextModel());
+  DALI_TEST_CHECK(typesetter);
+
+  // Tests the view model has been created.
+  ViewModel* model = typesetter->GetViewModel();
+  DALI_TEST_CHECK(model);
+
+  application.SendNotification();
+  application.Render();
+
+  DALI_TEST_EQUALS(model->GetNumberOfLines(), expectedNumberOfLines, TEST_LOCATION);
+  DALI_TEST_CHECK(model->GetLines());
+
+  const LineRun& lineOne = *(model->GetLines() + 0u);
+  const LineRun& lineTwo = *(model->GetLines() + 1u);
+
+  DALI_TEST_EQUALS(GetPostOffsetVerticalLineAlignment(lineOne, Dali::Toolkit::DevelText::VerticalLineAlignment::TOP), -9.5f, TEST_LOCATION);
+  DALI_TEST_EQUALS(GetPostOffsetVerticalLineAlignment(lineOne, Dali::Toolkit::DevelText::VerticalLineAlignment::MIDDLE), -9.5f, TEST_LOCATION);
+  DALI_TEST_EQUALS(GetPostOffsetVerticalLineAlignment(lineOne, Dali::Toolkit::DevelText::VerticalLineAlignment::BOTTOM), -9.5f, TEST_LOCATION);
+
+  DALI_TEST_EQUALS(GetPostOffsetVerticalLineAlignment(lineTwo, Dali::Toolkit::DevelText::VerticalLineAlignment::TOP), 0.0f, TEST_LOCATION);
+  DALI_TEST_EQUALS(GetPostOffsetVerticalLineAlignment(lineTwo, Dali::Toolkit::DevelText::VerticalLineAlignment::MIDDLE), 0.0f, TEST_LOCATION);
+  DALI_TEST_EQUALS(GetPostOffsetVerticalLineAlignment(lineTwo, Dali::Toolkit::DevelText::VerticalLineAlignment::BOTTOM), 0.0f, TEST_LOCATION);
+  END_TEST;
+}
+
+int UtcDaliGetPostOffsetVerticalLineAlignmentWithPositiveLineSpacing(void)
+{
+  tet_infoline(" UtcDaliGetPostOffsetVerticalLineAlignmentWithPositiveLineSpacing ");
+  ToolkitTestApplication application;
+
+  uint32_t expectedNumberOfLines = 2u;
+
+  // Creates a text controller.
+  ControllerPtr controller = Controller::New();
+
+  // Configures the text controller similarly to the text-label.
+  ConfigureTextLabel(controller);
+
+  // Sets the text.
+  controller->SetMarkupProcessorEnabled(true);
+  controller->SetTextElideEnabled(false);
+  controller->SetText("<p rel-line-height=2.0>Line one Line two</p>");
+
+  // Creates the text's model and relais-out the text.
+  const Size relayoutSize(120.f, 100.f);
+  controller->Relayout(relayoutSize);
+
+  // Tests the rendering controller has been created.
+  TypesetterPtr typesetter = Typesetter::New(controller->GetTextModel());
+  DALI_TEST_CHECK(typesetter);
+
+  // Tests the view model has been created.
+  ViewModel* model = typesetter->GetViewModel();
+  DALI_TEST_CHECK(model);
+
+  application.SendNotification();
+  application.Render();
+
+  DALI_TEST_EQUALS(model->GetNumberOfLines(), expectedNumberOfLines, TEST_LOCATION);
+  DALI_TEST_CHECK(model->GetLines());
+
+  const LineRun& lineOne = *(model->GetLines() + 0u);
+  const LineRun& lineTwo = *(model->GetLines() + 1u);
+
+  DALI_TEST_EQUALS(GetPostOffsetVerticalLineAlignment(lineOne, Dali::Toolkit::DevelText::VerticalLineAlignment::TOP), 19.0f, TEST_LOCATION);
+  DALI_TEST_EQUALS(GetPostOffsetVerticalLineAlignment(lineOne, Dali::Toolkit::DevelText::VerticalLineAlignment::MIDDLE), 9.5f, TEST_LOCATION);
+  DALI_TEST_EQUALS(GetPostOffsetVerticalLineAlignment(lineOne, Dali::Toolkit::DevelText::VerticalLineAlignment::BOTTOM), 0.0f, TEST_LOCATION);
+
+  DALI_TEST_EQUALS(GetPostOffsetVerticalLineAlignment(lineTwo, Dali::Toolkit::DevelText::VerticalLineAlignment::TOP), 0.0f, TEST_LOCATION);
+  DALI_TEST_EQUALS(GetPostOffsetVerticalLineAlignment(lineTwo, Dali::Toolkit::DevelText::VerticalLineAlignment::MIDDLE), 0.0f, TEST_LOCATION);
+  DALI_TEST_EQUALS(GetPostOffsetVerticalLineAlignment(lineTwo, Dali::Toolkit::DevelText::VerticalLineAlignment::BOTTOM), 0.0f, TEST_LOCATION);
+  END_TEST;
+}
index 15640b7..5d6926f 100644 (file)
@@ -163,6 +163,7 @@ SET( toolkit_src_files
    ${toolkit_src_dir}/text/multi-language-support.cpp
    ${toolkit_src_dir}/text/hidden-text.cpp
    ${toolkit_src_dir}/text/input-filter.cpp
+   ${toolkit_src_dir}/text/line-helper-functions.cpp
    ${toolkit_src_dir}/text/property-string-parser.cpp
    ${toolkit_src_dir}/text/segmentation.cpp
    ${toolkit_src_dir}/text/shaper.cpp
diff --git a/dali-toolkit/internal/text/line-helper-functions.cpp b/dali-toolkit/internal/text/line-helper-functions.cpp
new file mode 100644 (file)
index 0000000..d2ffcd1
--- /dev/null
@@ -0,0 +1,88 @@
+/*
+ * Copyright (c) 2021 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// FILE HEADER
+#include <dali-toolkit/internal/text/line-helper-functions.h>
+
+namespace Dali
+{
+namespace Toolkit
+{
+namespace Text
+{
+float GetPreOffsetVerticalLineAlignment(const LineRun& line, const DevelText::VerticalLineAlignment::Type& verLineAlign)
+{
+  // Calculate vertical line alignment
+  float offset = 0.0f;
+
+  switch(verLineAlign)
+  {
+    case DevelText::VerticalLineAlignment::TOP:
+    {
+      break;
+    }
+    case DevelText::VerticalLineAlignment::MIDDLE:
+    {
+      offset = line.lineSpacing * 0.5f;
+      break;
+    }
+    case DevelText::VerticalLineAlignment::BOTTOM:
+    {
+      offset = line.lineSpacing;
+      break;
+    }
+  }
+
+  // Apply TOP case when the lineSpacing is less than zero.
+  offset = line.lineSpacing < 0.0f ? 0.0f : offset;
+
+  return offset;
+}
+
+float GetPostOffsetVerticalLineAlignment(const LineRun& line, const DevelText::VerticalLineAlignment::Type& verLineAlign)
+{
+  // Calculate vertical line alignment
+  float offset = 0.0f;
+
+  switch(verLineAlign)
+  {
+    case DevelText::VerticalLineAlignment::TOP:
+    {
+      offset = line.lineSpacing;
+      break;
+    }
+    case DevelText::VerticalLineAlignment::MIDDLE:
+    {
+      offset = line.lineSpacing * 0.5f;
+      break;
+    }
+    case DevelText::VerticalLineAlignment::BOTTOM:
+    {
+      break;
+    }
+  }
+
+  // Apply TOP case when the lineSpacing is less than zero.
+  offset = line.lineSpacing < 0.0f ? line.lineSpacing : offset;
+
+  return offset;
+}
+} // namespace Text
+
+} // namespace Toolkit
+
+} // namespace Dali
diff --git a/dali-toolkit/internal/text/line-helper-functions.h b/dali-toolkit/internal/text/line-helper-functions.h
new file mode 100644 (file)
index 0000000..ad94086
--- /dev/null
@@ -0,0 +1,59 @@
+#ifndef DALI_TOOLKIT_TEXT_LINE_HELPER_FUNCTIONS_H
+#define DALI_TOOLKIT_TEXT_LINE_HELPER_FUNCTIONS_H
+
+/*
+ * Copyright (c) 2021 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// INTERNAL INCLUDES
+
+#include <dali-toolkit/devel-api/text/text-enumerations-devel.h>
+#include <dali-toolkit/internal/text/line-run.h>
+
+namespace Dali
+{
+namespace Toolkit
+{
+namespace Text
+{
+/**
+  * @brief Retrieves the vertical offset to shift text inside line to up by negative value and to down by positive value.
+  * The shifting depends on the vertical line alignment @p verLineAlign and lineSpacing when the lineSpacing is poistive.
+  * When the lineSpacing is negative then ignore @p verLineAlign
+  * @param[in] line the line.
+  * @param[in] line the line.
+  *
+  * @return The vertical offset before text.
+  */
+float GetPreOffsetVerticalLineAlignment(const LineRun& line, const Dali::Toolkit::DevelText::VerticalLineAlignment::Type& verLineAlign);
+
+/**
+  * @brief Retrieves the vertical offset to shift the next line to up by negative value and to down by positive value.
+  * The shifting depends on the vertical line alignment @p verLineAlign and lineSpacing when the lineSpacing is poistive.
+  * When the lineSpacing is negative then ignore @p verLineAlign
+  * @param[in] line the line.
+  * @param[in] line the line.
+  *
+  * @return The vertical offset after text.
+  */
+float GetPostOffsetVerticalLineAlignment(const LineRun& line, const Dali::Toolkit::DevelText::VerticalLineAlignment::Type& verLineAlign);
+} // namespace Text
+
+} // namespace Toolkit
+
+} // namespace Dali
+
+#endif // DALI_TOOLKIT_TEXT_LINE_HELPER_FUNCTIONS_H
index 1cd9d56..b1502a9 100644 (file)
@@ -26,6 +26,7 @@
 // INTERNAL INCLUDES
 #include <dali-toolkit/devel-api/controls/text-controls/text-label-devel.h>
 #include <dali-toolkit/internal/text/glyph-metrics-helper.h>
+#include <dali-toolkit/internal/text/line-helper-functions.h>
 #include <dali-toolkit/internal/text/rendering/styles/character-spacing-helper-functions.h>
 #include <dali-toolkit/internal/text/rendering/styles/strikethrough-helper-functions.h>
 #include <dali-toolkit/internal/text/rendering/styles/underline-helper-functions.h>
@@ -475,58 +476,6 @@ void DrawBackgroundColor(
   }
 }
 
-float GetPreOffsetVerticalLineAlignment(LineRun line, DevelText::VerticalLineAlignment::Type verLineAlign)
-{
-  // Calculate vertical line alignment
-  float offset = 0.0f;
-
-  switch(verLineAlign)
-  {
-    case DevelText::VerticalLineAlignment::TOP:
-    {
-      break;
-    }
-    case DevelText::VerticalLineAlignment::MIDDLE:
-    {
-      offset = line.lineSpacing * 0.5f;
-      break;
-    }
-    case DevelText::VerticalLineAlignment::BOTTOM:
-    {
-      offset = line.lineSpacing;
-      break;
-    }
-  }
-
-  return offset;
-}
-
-float GetPostOffsetVerticalLineAlignment(LineRun line, DevelText::VerticalLineAlignment::Type verLineAlign)
-{
-  // Calculate vertical line alignment
-  float offset = 0.0f;
-
-  switch(verLineAlign)
-  {
-    case DevelText::VerticalLineAlignment::TOP:
-    {
-      offset = line.lineSpacing;
-      break;
-    }
-    case DevelText::VerticalLineAlignment::MIDDLE:
-    {
-      offset = line.lineSpacing * 0.5f;
-      break;
-    }
-    case DevelText::VerticalLineAlignment::BOTTOM:
-    {
-      break;
-    }
-  }
-
-  return offset;
-}
-
 Devel::PixelBuffer DrawGlyphsBackground(const ViewModel* model, Devel::PixelBuffer& buffer, const uint32_t& bufferWidth, const uint32_t& bufferHeight, bool ignoreHorizontalAlignment, int32_t horizontalOffset, int32_t verticalOffset)
 {
   // Retrieve lines, glyphs, positions and colors from the view model.