Merge "Support paragraph tag <p> in markup" into devel/master
authorBowon Ryu <bowon.ryu@samsung.com>
Thu, 24 Feb 2022 10:34:59 +0000 (10:34 +0000)
committerGerrit Code Review <gerrit@review>
Thu, 24 Feb 2022 10:34:59 +0000 (10:34 +0000)
1  2 
automated-tests/src/dali-toolkit-internal/utc-Dali-TextLabel-internal.cpp
automated-tests/src/dali-toolkit/utc-Dali-TextEditor.cpp
automated-tests/src/dali-toolkit/utc-Dali-TextField.cpp
dali-toolkit/internal/file.list
dali-toolkit/internal/text/markup-processor.cpp

@@@ -15,6 -15,7 +15,6 @@@
   *
   */
  
 -#include <bits/stdint-uintn.h>
  #include <stdlib.h>
  #include <iostream>
  
@@@ -523,4 -524,40 +523,40 @@@ int UtcDaliTextLabelMarkupStrikethrough
    DALI_TEST_EQUALS(numberOfStrikethroughRuns, expectedNumberOfStrikethroughGlyphs, TEST_LOCATION);
  
    END_TEST;
+ }
+ int UtcDaliTextLabelMarkupParagraphTag(void)
+ {
+   ToolkitTestApplication application;
+   tet_infoline(" UtcDaliTextLabelMarkupParagraphTag ");
+   TextLabel textLabel = TextLabel::New();
+   application.GetScene().Add(textLabel);
+   textLabel.SetProperty(TextLabel::Property::TEXT, "text one <p>Paragraph two</p> text three <p>Paragraph four</p> text five");
+   textLabel.SetProperty(TextLabel ::Property::ENABLE_MARKUP, true);
+   textLabel.SetProperty(TextLabel::Property::MULTI_LINE, true);
+   application.SendNotification();
+   application.Render();
+   uint32_t expectedNumberOfBoundedParagraphRuns = 2u;
+   Toolkit::Internal::TextLabel& textLabelImpl                = GetImpl(textLabel);
+   const Text::Length            numberOfBoundedParagraphRuns = textLabelImpl.GetTextController()->GetTextModel()->GetNumberOfBoundedParagraphRuns();
+   DALI_TEST_EQUALS(numberOfBoundedParagraphRuns, expectedNumberOfBoundedParagraphRuns, TEST_LOCATION);
+   const Vector<BoundedParagraphRun>& boundedParagraphRuns = textLabelImpl.GetTextController()->GetTextModel()->GetBoundedParagraphRuns();
+   //<p>Paragraph two</p>
+   DALI_TEST_EQUALS(boundedParagraphRuns[0u].characterRun.characterIndex, 10u, TEST_LOCATION);
+   DALI_TEST_EQUALS(boundedParagraphRuns[0u].characterRun.numberOfCharacters, 14u, TEST_LOCATION);
+   //<p>Paragraph four</p>
+   DALI_TEST_EQUALS(boundedParagraphRuns[1u].characterRun.characterIndex, 37u, TEST_LOCATION);
+   DALI_TEST_EQUALS(boundedParagraphRuns[1u].characterRun.numberOfCharacters, 15u, TEST_LOCATION);
+   END_TEST;
  }
@@@ -1920,7 -1920,7 +1920,7 @@@ int utcDaliTextEditorEvent02(void
    application.SendNotification();
    application.Render();
  
 -  Actor layer = editor.GetChildAt(1u);
 +  Actor layer = editor.GetChildAt(2u);
    DALI_TEST_EQUALS(layer.GetChildCount(), 1u, TEST_LOCATION); // The cursor.
    DALI_TEST_EQUALS(stencil.GetChildCount(), 0u, TEST_LOCATION);
  
  
    // Checks the cursor and the renderer have been created.
    DALI_TEST_EQUALS(layer.GetChildCount(), 1u, TEST_LOCATION);   // The cursor.
 -  DALI_TEST_EQUALS(stencil.GetChildCount(), 1u, TEST_LOCATION); // The renderer
 +  DALI_TEST_EQUALS(stencil.GetChildCount(), 2u, TEST_LOCATION); // The renderer, clipped cursor
  
    Control cursor = Control::DownCast(layer.GetChildAt(0u));
    DALI_TEST_CHECK(cursor);
  
    DALI_TEST_EQUALS(position2, position6, TEST_LOCATION); // Should be in the same position2.
  
 -  // Should not be a renderer.
 -  DALI_TEST_EQUALS(stencil.GetChildCount(), 0u, TEST_LOCATION);
 +  // Should not be a renderer, there is only a clipped cursor.
 +  DALI_TEST_EQUALS(stencil.GetChildCount(), 1u, TEST_LOCATION);
  
    END_TEST;
  }
@@@ -2830,7 -2830,7 +2830,7 @@@ int utcDaliTextEditorHandles(void
    Actor activeLayer = editor.GetChildAt(1u);
  
    // Get the handle's actor.
 -  Actor handle = activeLayer.GetChildAt(1u);
 +  Actor handle = activeLayer.GetChildAt(0u);
    handle.SetProperty(Actor::Property::SIZE, Vector2(100.f, 100.f));
  
    // Render and notify
@@@ -5748,3 -5748,42 +5748,42 @@@ int UtcDaliTextEditorCharacterSpacing(v
  
    END_TEST;
  }
+ int UtcDaliToolkitTexteditorParagraphTag(void)
+ {
+   ToolkitTestApplication application;
+   tet_infoline(" UtcDaliToolkitTexteditorParagraphTag");
+   TextEditor editorNewlineSeparator = TextEditor::New();
+   TextEditor editorParagraphTag     = TextEditor::New();
+   DALI_TEST_CHECK(editorNewlineSeparator);
+   DALI_TEST_CHECK(editorParagraphTag);
+   application.GetScene().Add(editorNewlineSeparator);
+   application.GetScene().Add(editorParagraphTag);
+   //Same utterance uses new-line to split paragraphs should give similar results for paragraph tag.
+   editorNewlineSeparator.SetProperty(TextEditor::Property::ENABLE_MARKUP, true);
+   editorNewlineSeparator.SetProperty(Actor::Property::SIZE, Vector2(100.f, 50.f));
+   editorNewlineSeparator.SetProperty(Actor::Property::PARENT_ORIGIN, ParentOrigin::TOP_LEFT);
+   editorNewlineSeparator.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_LEFT);
+   editorNewlineSeparator.SetProperty(TextEditor::Property::TEXT, "test paragraph tag \ntest paragraph tag \ntest paragraph tag ");
+   editorParagraphTag.SetProperty(TextEditor::Property::ENABLE_MARKUP, true);
+   editorParagraphTag.SetProperty(Actor::Property::SIZE, Vector2(100.f, 50.f));
+   editorParagraphTag.SetProperty(Actor::Property::PARENT_ORIGIN, ParentOrigin::TOP_LEFT);
+   editorParagraphTag.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_LEFT);
+   editorParagraphTag.SetProperty(TextEditor::Property::TEXT, "test paragraph tag <p>test paragraph tag </p>test paragraph tag ");
+   application.SendNotification();
+   application.Render();
+   Vector3 textNaturalSizeNewlineSeparator = editorNewlineSeparator.GetNaturalSize();
+   Vector3 textNaturalSizeParagraphTag     = editorParagraphTag.GetNaturalSize();
+   DALI_TEST_EQUALS(textNaturalSizeNewlineSeparator, textNaturalSizeParagraphTag, TEST_LOCATION);
+   application.SendNotification();
+   application.Render();
+   END_TEST;
+ }
@@@ -2372,7 -2372,7 +2372,7 @@@ int utcDaliTextFieldEvent02(void
    application.SendNotification();
    application.Render();
  
 -  Actor layer = field.GetChildAt(1u);
 +  Actor layer = field.GetChildAt(2u);
    DALI_TEST_EQUALS(layer.GetChildCount(), 1u, TEST_LOCATION); // The cursor.
    DALI_TEST_EQUALS(stencil.GetChildCount(), 0u, TEST_LOCATION);
  
  
    // Checks the cursor and the renderer have been created.
    DALI_TEST_EQUALS(layer.GetChildCount(), 1u, TEST_LOCATION);   // The cursor.
 -  DALI_TEST_EQUALS(stencil.GetChildCount(), 1u, TEST_LOCATION); // The renderer
 +  DALI_TEST_EQUALS(stencil.GetChildCount(), 2u, TEST_LOCATION); // The renderer, clipped cursor
  
    Control cursor = Control::DownCast(layer.GetChildAt(0u));
    DALI_TEST_CHECK(cursor);
  
    DALI_TEST_EQUALS(position4, position7, TEST_LOCATION); // Should be in the same position2.
  
 -  // Should not be a renderer.
 -  DALI_TEST_EQUALS(stencil.GetChildCount(), 0u, TEST_LOCATION);
 +  // Should not be a renderer, there is only a clipped cursor.
 +  DALI_TEST_EQUALS(stencil.GetChildCount(), 1u, TEST_LOCATION);
  
    // Chanege exceed policy (EXCEED_POLICY_ORIGINAL doesn't use stencil )
    field.SetProperty(TextField::Property::TEXT, "This is a long text for the size of the text-field.");
@@@ -5280,4 -5280,43 +5280,43 @@@ int UtcDaliToolkitTextFieldUnderlineTyp
    application.Render();
  
    END_TEST;
+ }
+ int UtcDaliToolkitTextfieldParagraphTag(void)
+ {
+   ToolkitTestApplication application;
+   tet_infoline(" UtcDaliToolkitTextfieldParagraphTag");
+   TextField fieldNewlineSeparator = TextField::New();
+   TextField fieldParagraphTag     = TextField::New();
+   DALI_TEST_CHECK(fieldNewlineSeparator);
+   DALI_TEST_CHECK(fieldParagraphTag);
+   application.GetScene().Add(fieldNewlineSeparator);
+   application.GetScene().Add(fieldParagraphTag);
+   //Same utterance uses new-line to split paragraphs should give similar results for paragraph tag.
+   fieldNewlineSeparator.SetProperty(TextField::Property::ENABLE_MARKUP, true);
+   fieldNewlineSeparator.SetProperty(Actor::Property::SIZE, Vector2(100.f, 50.f));
+   fieldNewlineSeparator.SetProperty(Actor::Property::PARENT_ORIGIN, ParentOrigin::TOP_LEFT);
+   fieldNewlineSeparator.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_LEFT);
+   fieldNewlineSeparator.SetProperty(TextField::Property::TEXT, "test paragraph tag \ntest paragraph tag \ntest paragraph tag ");
+   fieldParagraphTag.SetProperty(TextField::Property::ENABLE_MARKUP, true);
+   fieldParagraphTag.SetProperty(Actor::Property::SIZE, Vector2(100.f, 50.f));
+   fieldParagraphTag.SetProperty(Actor::Property::PARENT_ORIGIN, ParentOrigin::TOP_LEFT);
+   fieldParagraphTag.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_LEFT);
+   fieldParagraphTag.SetProperty(TextField::Property::TEXT, "test paragraph tag <p>test paragraph tag </p>test paragraph tag ");
+   application.SendNotification();
+   application.Render();
+   Vector3 textNaturalSizeNewlineSeparator = fieldNewlineSeparator.GetNaturalSize();
+   Vector3 textNaturalSizeParagraphTag     = fieldParagraphTag.GetNaturalSize();
+   DALI_TEST_EQUALS(textNaturalSizeNewlineSeparator, textNaturalSizeParagraphTag, TEST_LOCATION);
+   application.SendNotification();
+   application.Render();
+   END_TEST;
  }
@@@ -13,10 -13,6 +13,10 @@@ SET( toolkit_src_file
     ${toolkit_src_dir}/builder/style.cpp
     ${toolkit_src_dir}/builder/tree-node-manipulator.cpp
     ${toolkit_src_dir}/builder/replacement.cpp
 +   ${toolkit_src_dir}/texture-manager/texture-async-loading-helper.cpp
 +   ${toolkit_src_dir}/texture-manager/texture-cache-manager.cpp
 +   ${toolkit_src_dir}/texture-manager/texture-manager-impl.cpp
 +   ${toolkit_src_dir}/texture-manager/texture-upload-observer.cpp
     ${toolkit_src_dir}/visuals/animated-image/animated-image-visual.cpp
     ${toolkit_src_dir}/visuals/animated-image/image-cache.cpp
     ${toolkit_src_dir}/visuals/animated-image/fixed-image-cache.cpp
@@@ -46,6 -42,8 +46,6 @@@
     ${toolkit_src_dir}/visuals/svg/svg-visual.cpp
     ${toolkit_src_dir}/visuals/text/text-visual.cpp
     ${toolkit_src_dir}/visuals/transition-data-impl.cpp
 -   ${toolkit_src_dir}/visuals/texture-manager-impl.cpp
 -   ${toolkit_src_dir}/visuals/texture-upload-observer.cpp
     ${toolkit_src_dir}/visuals/image-visual-shader-factory.cpp
     ${toolkit_src_dir}/visuals/visual-base-data-impl.cpp
     ${toolkit_src_dir}/visuals/visual-base-impl.cpp
     ${toolkit_src_dir}/image-loader/image-url-impl.cpp
     ${toolkit_src_dir}/styling/style-manager-impl.cpp
     ${toolkit_src_dir}/text/bidirectional-support.cpp
+    ${toolkit_src_dir}/text/bounded-paragraph-helper-functions.cpp
     ${toolkit_src_dir}/text/character-set-conversion.cpp
     ${toolkit_src_dir}/text/color-segmentation.cpp
     ${toolkit_src_dir}/text/cursor-helper-functions.cpp
@@@ -60,6 -60,7 +60,7 @@@ const std::string XHTML_ANCHOR_TAG("a")
  const std::string XHTML_BACKGROUND_TAG("background");
  const std::string XHTML_SPAN_TAG("span");
  const std::string XHTML_STRIKETHROUGH_TAG("s");
+ const std::string XHTML_PARAGRAPH_TAG("p");
  
  const char LESS_THAN      = '<';
  const char GREATER_THAN   = '>';
@@@ -74,6 -75,7 +75,7 @@@ const char CHAR_ARRAY_END = '\0'
  const char HEX_CODE       = 'x';
  
  const char WHITE_SPACE = 0x20; // ASCII value of the white space.
+ const char NEW_LINE    = 0x0A; // ASCII value of the newline.
  
  // Range 1 0x0u < XHTML_DECIMAL_ENTITY_RANGE <= 0xD7FFu
  // Range 2 0xE000u < XHTML_DECIMAL_ENTITY_RANGE <= 0xFFFDu
@@@ -211,6 -213,17 +213,17 @@@ void Initialize(StrikethroughCharacterR
  }
  
  /**
+  * @brief Initializes a  bounded-paragraph character run to its defaults.
+  *
+  * @param[in,out] boundedParagraphRun The bounded paragraphRun run to initialize.
+  */
+ void Initialize(BoundedParagraphRun& boundedParagraphRun)
+ {
+   boundedParagraphRun.characterRun.characterIndex     = 0u;
+   boundedParagraphRun.characterRun.numberOfCharacters = 0u;
+ }
+ /**
   * @brief Splits the tag string into the tag name and its attributes.
   *
   * The attributes are stored in a vector in the tag.
@@@ -637,6 -650,30 +650,30 @@@ void ProcessItemTag
  }
  
  /**
+  * @brief Processes the paragraph-tag
+  *
+  * @param[in/out] markupProcessData The markup process data
+  * @param[in] tag The current tag
+  * @param[in] isEndBuffer Whether the end of buffer
+  * @param[in/out] characterIndex The current character index
+  */
+ void ProcessParagraphTag(
+   MarkupProcessData& markupProcessData,
+   const Tag          tag,
+   bool               isEndBuffer,
+   CharacterIndex&    characterIndex)
+ {
+   if((characterIndex > 0 &&
+       markupProcessData.markupProcessedText[characterIndex - 1u] != NEW_LINE) &&
+      (!(tag.isEndTag && isEndBuffer)))
+   {
+     // Insert new-line character at the start and end of paragraph.
+     markupProcessData.markupProcessedText.append(1u, NEW_LINE);
+     ++characterIndex;
+   }
+ }
+ /**
   * @brief Processes the anchor tag
   *
   * @param[in/out] markupProcessData The markup process data
@@@ -764,13 -801,21 +801,21 @@@ void ProcessSpanForRun
   * @param[in] colorRunIndex The color run index
   * @param[in] underlinedCharacterRunIndex The underlined character run index
   * @param[in] backgroundRunIndex The background run index
+  * @param[in] boundedParagraphRunIndex The bounded paragraph run index
+  *
   */
- void ResizeModelVectors(MarkupProcessData& markupProcessData, const RunIndex fontRunIndex, const RunIndex colorRunIndex, const RunIndex underlinedCharacterRunIndex, const RunIndex backgroundRunIndex)
+ void ResizeModelVectors(MarkupProcessData& markupProcessData,
+                         const RunIndex     fontRunIndex,
+                         const RunIndex     colorRunIndex,
+                         const RunIndex     underlinedCharacterRunIndex,
+                         const RunIndex     backgroundRunIndex,
+                         const RunIndex     boundedParagraphRunIndex)
  {
    markupProcessData.fontRuns.Resize(fontRunIndex);
    markupProcessData.colorRuns.Resize(colorRunIndex);
    markupProcessData.underlinedCharacterRuns.Resize(underlinedCharacterRunIndex);
    markupProcessData.backgroundColorRuns.Resize(backgroundRunIndex);
+   markupProcessData.boundedParagraphRuns.Resize(boundedParagraphRunIndex);
  
  #ifdef DEBUG_ENABLED
    for(unsigned int i = 0; i < colorRunIndex; ++i)
@@@ -895,6 -940,7 +940,7 @@@ void ProcessMarkupString(const std::str
    RunIndex underlinedCharacterRunIndex    = 0u;
    RunIndex backgroundRunIndex             = 0u;
    RunIndex strikethroughCharacterRunIndex = 0u;
+   RunIndex boundedParagraphRunIndex       = 0u;
  
    // check tag reference
    int colorTagReference      = 0u;
    int backgroundTagReference = 0u;
    int spanTagReference       = 0u;
    int sTagReference          = 0u;
+   int pTagReference          = 0u;
  
    // Give an initial default value to the model's vectors.
    markupProcessData.colorRuns.Reserve(DEFAULT_VECTOR_SIZE);
              run.color = Color::BLUE;
              ProcessColorTag(tag, run);
            });
 -        /* TODO - underline */
 +        /* Underline */
 +        ProcessTagForRun<UnderlinedCharacterRun>(
 +          markupProcessData.underlinedCharacterRuns, styleStack, tag, characterIndex, underlinedCharacterRunIndex, uTagReference, [](const Tag& tag, UnderlinedCharacterRun& run) {
 +            run.properties.color = Color::BLUE;
 +            run.properties.colorDefined = true;
 +            ProcessUnderlineTag(tag, run);
 +          });
        } // <a href=https://www.tizen.org>tizen</a>
        else if(TokenComparison(XHTML_SHADOW_TAG, tag.buffer, tag.length))
        {
          ProcessTagForRun<StrikethroughCharacterRun>(
            markupProcessData.strikethroughCharacterRuns, styleStack, tag, characterIndex, strikethroughCharacterRunIndex, sTagReference, [](const Tag& tag, StrikethroughCharacterRun& run) { ProcessStrikethroughTag(tag, run); });
        } // <s></s>
+       else if(TokenComparison(XHTML_PARAGRAPH_TAG, tag.buffer, tag.length))
+       {
+         ProcessParagraphTag(markupProcessData, tag, (markupStringBuffer == markupStringEndBuffer), characterIndex);
+         ProcessTagForRun<BoundedParagraphRun>(
+           markupProcessData.boundedParagraphRuns, styleStack, tag, characterIndex, boundedParagraphRunIndex, pTagReference, [](const Tag& tag, BoundedParagraphRun& run) {});
+       } // <p></p>
      }   // end if( IsTag() )
      else if(markupStringBuffer < markupStringEndBuffer)
      {
    }
  
    // Resize the model's vectors.
-   ResizeModelVectors(markupProcessData, fontRunIndex, colorRunIndex, underlinedCharacterRunIndex, backgroundRunIndex);
+   ResizeModelVectors(markupProcessData, fontRunIndex, colorRunIndex, underlinedCharacterRunIndex, backgroundRunIndex, boundedParagraphRunIndex);
  }
  
  } // namespace Text