Reduce Cyclomatic Complexity of some methods in text-typesetter, transtion-data ... 52/245852/6
authorAdeel Kazmi <adeel.kazmi@samsung.com>
Fri, 16 Oct 2020 11:06:40 +0000 (12:06 +0100)
committerAdeel Kazmi <adeel.kazmi@samsung.com>
Wed, 21 Oct 2020 13:38:09 +0000 (14:38 +0100)
Change-Id: I7c9a5b8c2ffc59837b0e8bcf85f78fe96df1bf9c

dali-toolkit/internal/controls/text-controls/text-label-impl.cpp
dali-toolkit/internal/controls/text-controls/text-label-impl.h
dali-toolkit/internal/text/rendering/text-typesetter.cpp
dali-toolkit/internal/visuals/transition-data-impl.cpp

index 1cdb0f8..d1c1b1a 100755 (executable)
@@ -62,33 +62,29 @@ namespace Internal
 
 namespace
 {
 
 namespace
 {
-  const unsigned int DEFAULT_RENDERING_BACKEND = Dali::Toolkit::DevelText::DEFAULT_RENDERING_BACKEND;
-
-  /**
-   * @brief How the text visual should be aligned vertically inside the control.
-   *
-   * 0.0f aligns the text to the top, 0.5f aligns the text to the center, 1.0f aligns the text to the bottom.
-   * The alignment depends on the alignment value of the text label (Use Text::VerticalAlignment enumerations).
-   */
-  const float VERTICAL_ALIGNMENT_TABLE[ Text::VerticalAlignment::BOTTOM + 1 ] =
-  {
-    0.0f,  // VerticalAlignment::TOP
-    0.5f,  // VerticalAlignment::CENTER
-    1.0f   // VerticalAlignment::BOTTOM
-  };
-
-  const std::string TEXT_FIT_ENABLE_KEY( "enable" );
-  const std::string TEXT_FIT_MIN_SIZE_KEY( "minSize" );
-  const std::string TEXT_FIT_MAX_SIZE_KEY( "maxSize" );
-  const std::string TEXT_FIT_STEP_SIZE_KEY( "stepSize" );
-  const std::string TEXT_FIT_FONT_SIZE_TYPE_KEY( "fontSizeType" );
-}
+const unsigned int DEFAULT_RENDERING_BACKEND = Dali::Toolkit::DevelText::DEFAULT_RENDERING_BACKEND;
 
 
-namespace
+/**
+ * @brief How the text visual should be aligned vertically inside the control.
+ *
+ * 0.0f aligns the text to the top, 0.5f aligns the text to the center, 1.0f aligns the text to the bottom.
+ * The alignment depends on the alignment value of the text label (Use Text::VerticalAlignment enumerations).
+ */
+const float VERTICAL_ALIGNMENT_TABLE[ Text::VerticalAlignment::BOTTOM + 1 ] =
 {
 {
+  0.0f,  // VerticalAlignment::TOP
+  0.5f,  // VerticalAlignment::CENTER
+  1.0f   // VerticalAlignment::BOTTOM
+};
+
+const std::string TEXT_FIT_ENABLE_KEY( "enable" );
+const std::string TEXT_FIT_MIN_SIZE_KEY( "minSize" );
+const std::string TEXT_FIT_MAX_SIZE_KEY( "maxSize" );
+const std::string TEXT_FIT_STEP_SIZE_KEY( "stepSize" );
+const std::string TEXT_FIT_FONT_SIZE_TYPE_KEY( "fontSizeType" );
 
 #if defined ( DEBUG_ENABLED )
 
 #if defined ( DEBUG_ENABLED )
-  Debug::Filter* gLogFilter = Debug::Filter::New(Debug::NoLogging, true, "LOG_TEXT_CONTROLS");
+Debug::Filter* gLogFilter = Debug::Filter::New(Debug::NoLogging, true, "LOG_TEXT_CONTROLS");
 #endif
 
 const Scripting::StringEnum AUTO_SCROLL_STOP_MODE_TABLE[] =
 #endif
 
 const Scripting::StringEnum AUTO_SCROLL_STOP_MODE_TABLE[] =
@@ -145,6 +141,73 @@ DALI_ANIMATABLE_PROPERTY_COMPONENT_REGISTRATION( Toolkit,    TextLabel, "textCol
 DALI_ANIMATABLE_PROPERTY_COMPONENT_REGISTRATION( Toolkit,    TextLabel, "textColorAlpha", TEXT_COLOR_ALPHA, TEXT_COLOR, 3  )
 DALI_TYPE_REGISTRATION_END()
 
 DALI_ANIMATABLE_PROPERTY_COMPONENT_REGISTRATION( Toolkit,    TextLabel, "textColorAlpha", TEXT_COLOR_ALPHA, TEXT_COLOR, 3  )
 DALI_TYPE_REGISTRATION_END()
 
+/// Parses the property map for the TEXT_FIT property
+void ParseTextFitProperty(Text::ControllerPtr& controller, const Property::Map* propertiesMap)
+{
+  if ( propertiesMap && !propertiesMap->Empty() )
+  {
+    bool enabled = false;
+    float minSize = 0.f;
+    float maxSize = 0.f;
+    float stepSize = 0.f;
+    bool isMinSizeSet = false, isMaxSizeSet = false, isStepSizeSet = false;
+    Controller::FontSizeType type = Controller::FontSizeType::POINT_SIZE;
+
+    const unsigned int numberOfItems = propertiesMap->Count();
+
+    // Parses and applies
+    for( unsigned int index = 0u; index < numberOfItems; ++index )
+    {
+      const KeyValuePair& valueGet = propertiesMap->GetKeyValue( index );
+
+      if( ( Controller::TextFitInfo::Property::TEXT_FIT_ENABLE == valueGet.first.indexKey ) || ( TEXT_FIT_ENABLE_KEY == valueGet.first.stringKey ) )
+      {
+        /// Enable key.
+        enabled = valueGet.second.Get< bool >();
+      }
+      else if( ( Controller::TextFitInfo::Property::TEXT_FIT_MIN_SIZE == valueGet.first.indexKey ) || ( TEXT_FIT_MIN_SIZE_KEY == valueGet.first.stringKey ) )
+      {
+        /// min size.
+        minSize = valueGet.second.Get< float >();
+        isMinSizeSet = true;
+      }
+      else if( ( Controller::TextFitInfo::Property::TEXT_FIT_MAX_SIZE == valueGet.first.indexKey ) || ( TEXT_FIT_MAX_SIZE_KEY == valueGet.first.stringKey ) )
+      {
+        /// max size.
+        maxSize = valueGet.second.Get< float >();
+        isMaxSizeSet = true;
+      }
+      else if( ( Controller::TextFitInfo::Property::TEXT_FIT_STEP_SIZE == valueGet.first.indexKey ) || ( TEXT_FIT_STEP_SIZE_KEY == valueGet.first.stringKey ) )
+      {
+        /// step size.
+        stepSize = valueGet.second.Get< float >();
+        isStepSizeSet = true;
+      }
+      else if( ( Controller::TextFitInfo::Property::TEXT_FIT_FONT_SIZE_TYPE == valueGet.first.indexKey ) || ( TEXT_FIT_FONT_SIZE_TYPE_KEY == valueGet.first.stringKey ) )
+      {
+        if( "pixelSize" == valueGet.second.Get< std::string >() )
+        {
+          type = Controller::FontSizeType::PIXEL_SIZE;
+        }
+      }
+    }
+
+    controller->SetTextFitEnabled( enabled );
+    if( isMinSizeSet )
+    {
+      controller->SetTextFitMinSize( minSize, type );
+    }
+    if( isMaxSizeSet )
+    {
+      controller->SetTextFitMaxSize( maxSize, type );
+    }
+    if( isStepSizeSet )
+    {
+      controller->SetTextFitStepSize( stepSize, type );
+    }
+  }
+}
+
 } // namespace
 
 Toolkit::TextLabel TextLabel::New()
 } // namespace
 
 Toolkit::TextLabel TextLabel::New()
@@ -275,101 +338,61 @@ void TextLabel::SetProperty( BaseObject* object, Property::Index index, const Pr
       }
       case Toolkit::TextLabel::Property::AUTO_SCROLL_STOP_MODE:
       {
       }
       case Toolkit::TextLabel::Property::AUTO_SCROLL_STOP_MODE:
       {
-        if( !impl.mTextScroller )
-        {
-          impl.mTextScroller = Text::TextScroller::New( impl );
-        }
-        Toolkit::TextLabel::AutoScrollStopMode::Type stopMode = impl.mTextScroller->GetStopMode();
+        Text::TextScrollerPtr textScroller = impl.GetTextScroller();
+        Toolkit::TextLabel::AutoScrollStopMode::Type stopMode = textScroller->GetStopMode();
         if( Scripting::GetEnumerationProperty< Toolkit::TextLabel::AutoScrollStopMode::Type >( value,
         if( Scripting::GetEnumerationProperty< Toolkit::TextLabel::AutoScrollStopMode::Type >( value,
-                                                                                                    AUTO_SCROLL_STOP_MODE_TABLE,
-                                                                                                    AUTO_SCROLL_STOP_MODE_TABLE_COUNT,
-                                                                                                    stopMode ) )
+                                                                                               AUTO_SCROLL_STOP_MODE_TABLE,
+                                                                                               AUTO_SCROLL_STOP_MODE_TABLE_COUNT,
+                                                                                               stopMode ) )
         {
         {
-            impl.mTextScroller->SetStopMode( stopMode );
+          textScroller->SetStopMode( stopMode );
         }
         break;
       }
       case Toolkit::TextLabel::Property::AUTO_SCROLL_SPEED:
       {
         }
         break;
       }
       case Toolkit::TextLabel::Property::AUTO_SCROLL_SPEED:
       {
-        if( !impl.mTextScroller )
-        {
-          impl.mTextScroller = Text::TextScroller::New( impl );
-        }
-        impl.mTextScroller->SetSpeed( value.Get<int>() );
+        impl.GetTextScroller()->SetSpeed( value.Get<int>() );
         break;
       }
       case Toolkit::TextLabel::Property::AUTO_SCROLL_LOOP_COUNT:
       {
         break;
       }
       case Toolkit::TextLabel::Property::AUTO_SCROLL_LOOP_COUNT:
       {
-        if( !impl.mTextScroller )
-        {
-          impl.mTextScroller = Text::TextScroller::New( impl );
-        }
-        impl.mTextScroller->SetLoopCount( value.Get<int>() );
+        impl.GetTextScroller()->SetLoopCount( value.Get<int>() );
         break;
       }
       case Toolkit::TextLabel::Property::AUTO_SCROLL_LOOP_DELAY:
       {
         break;
       }
       case Toolkit::TextLabel::Property::AUTO_SCROLL_LOOP_DELAY:
       {
-         if( !impl.mTextScroller )
-        {
-          impl.mTextScroller = Text::TextScroller::New( impl );
-        }
-        impl.mTextScroller->SetLoopDelay( value.Get<float>() );
+        impl.GetTextScroller()->SetLoopDelay( value.Get<float>() );
         break;
       }
       case Toolkit::TextLabel::Property::AUTO_SCROLL_GAP:
       {
         break;
       }
       case Toolkit::TextLabel::Property::AUTO_SCROLL_GAP:
       {
-        if( !impl.mTextScroller )
-        {
-          impl.mTextScroller = Text::TextScroller::New( impl );
-        }
-        impl.mTextScroller->SetGap( value.Get<float>() );
+        impl.GetTextScroller()->SetGap( value.Get<float>() );
         break;
       }
       case Toolkit::TextLabel::Property::LINE_SPACING:
       {
         const float lineSpacing = value.Get<float>();
         break;
       }
       case Toolkit::TextLabel::Property::LINE_SPACING:
       {
         const float lineSpacing = value.Get<float>();
-
-        // Don't trigger anything if the line spacing didn't change
-        if( impl.mController->SetDefaultLineSpacing( lineSpacing ) )
-        {
-          impl.mTextUpdateNeeded = true;
-        }
+        impl.mTextUpdateNeeded = impl.mController->SetDefaultLineSpacing( lineSpacing ) || impl.mTextUpdateNeeded;
         break;
       }
       case Toolkit::TextLabel::Property::UNDERLINE:
       {
         break;
       }
       case Toolkit::TextLabel::Property::UNDERLINE:
       {
-        const bool update = SetUnderlineProperties( impl.mController, value, Text::EffectStyle::DEFAULT );
-        if( update )
-        {
-          impl.mTextUpdateNeeded = true;
-        }
+        impl.mTextUpdateNeeded = SetUnderlineProperties( impl.mController, value, Text::EffectStyle::DEFAULT ) || impl.mTextUpdateNeeded;
         break;
       }
       case Toolkit::TextLabel::Property::SHADOW:
       {
         break;
       }
       case Toolkit::TextLabel::Property::SHADOW:
       {
-        const bool update = SetShadowProperties( impl.mController, value, Text::EffectStyle::DEFAULT );
-        if( update )
-        {
-          impl.mTextUpdateNeeded = true;
-        }
+        impl.mTextUpdateNeeded = SetShadowProperties( impl.mController, value, Text::EffectStyle::DEFAULT ) || impl.mTextUpdateNeeded;
         break;
       }
       case Toolkit::TextLabel::Property::EMBOSS:
       {
         break;
       }
       case Toolkit::TextLabel::Property::EMBOSS:
       {
-        const bool update = SetEmbossProperties( impl.mController, value, Text::EffectStyle::DEFAULT );
-        if( update )
-        {
-          impl.mTextUpdateNeeded = true;
-        }
+        impl.mTextUpdateNeeded = SetEmbossProperties( impl.mController, value, Text::EffectStyle::DEFAULT ) || impl.mTextUpdateNeeded;
         break;
       }
       case Toolkit::TextLabel::Property::OUTLINE:
       {
         break;
       }
       case Toolkit::TextLabel::Property::OUTLINE:
       {
-        const bool update = SetOutlineProperties( impl.mController, value, Text::EffectStyle::DEFAULT );
-        if( update )
-        {
-          impl.mTextUpdateNeeded = true;
-        }
+        impl.mTextUpdateNeeded = SetOutlineProperties( impl.mController, value, Text::EffectStyle::DEFAULT ) || impl.mTextUpdateNeeded;
         break;
       }
       case Toolkit::TextLabel::Property::PIXEL_SIZE:
         break;
       }
       case Toolkit::TextLabel::Property::PIXEL_SIZE:
@@ -419,11 +442,7 @@ void TextLabel::SetProperty( BaseObject* object, Property::Index index, const Pr
       }
       case Toolkit::DevelTextLabel::Property::BACKGROUND:
       {
       }
       case Toolkit::DevelTextLabel::Property::BACKGROUND:
       {
-        const bool update = SetBackgroundProperties( impl.mController, value, Text::EffectStyle::DEFAULT );
-        if( update )
-        {
-          impl.mTextUpdateNeeded = true;
-        }
+        impl.mTextUpdateNeeded = SetBackgroundProperties( impl.mController, value, Text::EffectStyle::DEFAULT ) || impl.mTextUpdateNeeded;
         break;
       }
       case Toolkit::DevelTextLabel::Property::IGNORE_SPACES_AFTER_TEXT:
         break;
       }
       case Toolkit::DevelTextLabel::Property::IGNORE_SPACES_AFTER_TEXT:
@@ -438,80 +457,13 @@ void TextLabel::SetProperty( BaseObject* object, Property::Index index, const Pr
       }
       case Toolkit::DevelTextLabel::Property::TEXT_FIT:
       {
       }
       case Toolkit::DevelTextLabel::Property::TEXT_FIT:
       {
-        const Property::Map& propertiesMap = value.Get<Property::Map>();
-
-        bool enabled = false;
-        float minSize = 0.f;
-        float maxSize = 0.f;
-        float stepSize = 0.f;
-        bool isMinSizeSet = false, isMaxSizeSet = false, isStepSizeSet = false;
-        Controller::FontSizeType type = Controller::FontSizeType::POINT_SIZE;
-
-        if ( !propertiesMap.Empty() )
-        {
-          const unsigned int numberOfItems = propertiesMap.Count();
-
-          // Parses and applies
-          for( unsigned int index = 0u; index < numberOfItems; ++index )
-          {
-            const KeyValuePair& valueGet = propertiesMap.GetKeyValue( index );
-
-            if( ( Controller::TextFitInfo::Property::TEXT_FIT_ENABLE == valueGet.first.indexKey ) || ( TEXT_FIT_ENABLE_KEY == valueGet.first.stringKey ) )
-            {
-              /// Enable key.
-              enabled = valueGet.second.Get< bool >();
-            }
-            else if( ( Controller::TextFitInfo::Property::TEXT_FIT_MIN_SIZE == valueGet.first.indexKey ) || ( TEXT_FIT_MIN_SIZE_KEY == valueGet.first.stringKey ) )
-            {
-              /// min size.
-              minSize = valueGet.second.Get< float >();
-              isMinSizeSet = true;
-            }
-            else if( ( Controller::TextFitInfo::Property::TEXT_FIT_MAX_SIZE == valueGet.first.indexKey ) || ( TEXT_FIT_MAX_SIZE_KEY == valueGet.first.stringKey ) )
-            {
-              /// max size.
-              maxSize = valueGet.second.Get< float >();
-              isMaxSizeSet = true;
-            }
-            else if( ( Controller::TextFitInfo::Property::TEXT_FIT_STEP_SIZE == valueGet.first.indexKey ) || ( TEXT_FIT_STEP_SIZE_KEY == valueGet.first.stringKey ) )
-            {
-              /// step size.
-              stepSize = valueGet.second.Get< float >();
-              isStepSizeSet = true;
-            }
-            else if( ( Controller::TextFitInfo::Property::TEXT_FIT_FONT_SIZE_TYPE == valueGet.first.indexKey ) || ( TEXT_FIT_FONT_SIZE_TYPE_KEY == valueGet.first.stringKey ) )
-            {
-              if( "pixelSize" == valueGet.second.Get< std::string >() )
-              {
-                type = Controller::FontSizeType::PIXEL_SIZE;
-              }
-            }
-          }
-
-          impl.mController->SetTextFitEnabled( enabled );
-          if( isMinSizeSet )
-          {
-            impl.mController->SetTextFitMinSize( minSize, type );
-          }
-          if( isMaxSizeSet )
-          {
-            impl.mController->SetTextFitMaxSize( maxSize, type );
-          }
-          if( isStepSizeSet )
-          {
-            impl.mController->SetTextFitStepSize( stepSize, type );
-          }
-        }
+        ParseTextFitProperty(impl.mController, value.GetMap());
         break;
       }
       case Toolkit::DevelTextLabel::Property::MIN_LINE_SIZE:
       {
         const float lineSize = value.Get<float>();
         break;
       }
       case Toolkit::DevelTextLabel::Property::MIN_LINE_SIZE:
       {
         const float lineSize = value.Get<float>();
-
-        if( impl.mController->SetDefaultLineSize( lineSize ) )
-        {
-          impl.mTextUpdateNeeded = true;
-        }
+        impl.mTextUpdateNeeded = impl.mController->SetDefaultLineSize( lineSize ) || impl.mTextUpdateNeeded;
         break;
       }
     }
         break;
       }
     }
index bdbdbbc..a863c9c 100644 (file)
@@ -2,7 +2,7 @@
 #define DALI_TOOLKIT_INTERNAL_TEXT_LABEL_H
 
 /*
 #define DALI_TOOLKIT_INTERNAL_TEXT_LABEL_H
 
 /*
- * Copyright (c) 2017 Samsung Electronics Co., Ltd.
+ * 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.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -142,6 +142,19 @@ private:
    */
   void SetUpAutoScrolling();
 
    */
   void SetUpAutoScrolling();
 
+  /**
+   * Creates a text-scroller if one has not been created.
+   * @return The text scroller.
+   */
+  Text::TextScrollerPtr GetTextScroller()
+  {
+    if( !mTextScroller )
+    {
+      mTextScroller = Text::TextScroller::New( *this );
+    }
+    return mTextScroller;
+  }
+
 private: // Data
 
   Text::ControllerPtr mController;
 private: // Data
 
   Text::ControllerPtr mController;
index 0256a43..05b4a67 100755 (executable)
@@ -1,5 +1,5 @@
 /*
 /*
- * Copyright (c) 2019 Samsung Electronics Co., Ltd.
+ * 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.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -278,6 +278,149 @@ bool IsGlyphUnderlined( GlyphIndex index,
   return false;
 }
 
   return false;
 }
 
+/// Helper method to fetch the underline metrics for the specified font glyph
+void FetchFontUnderlineMetrics(
+    TextAbstraction::FontClient& fontClient,
+    const GlyphInfo* const glyphInfo,
+    float& currentUnderlinePosition,
+    const float underlineHeight,
+    float& currentUnderlineThickness,
+    float& maxUnderlineThickness,
+    FontId& lastUnderlinedFontId)
+{
+  FontMetrics fontMetrics;
+  fontClient.GetFontMetrics( glyphInfo->fontId, fontMetrics );
+  currentUnderlinePosition = ceil( fabsf( fontMetrics.underlinePosition ) );
+  const float descender = ceil( fabsf( fontMetrics.descender ) );
+
+  if( fabsf( underlineHeight ) < Math::MACHINE_EPSILON_1000 )
+  {
+    currentUnderlineThickness = fontMetrics.underlineThickness;
+
+    // Ensure underline will be at least a pixel high
+    if ( currentUnderlineThickness < 1.0f )
+    {
+      currentUnderlineThickness = 1.0f;
+    }
+    else
+    {
+      currentUnderlineThickness = ceil( currentUnderlineThickness );
+    }
+  }
+
+  // The underline thickness should be the max underline thickness of all glyphs of the line.
+  if ( currentUnderlineThickness > maxUnderlineThickness )
+  {
+    maxUnderlineThickness = currentUnderlineThickness;
+  }
+
+  // Clamp the underline position at the font descender and check for ( as EFL describes it ) a broken font
+  if( currentUnderlinePosition > descender )
+  {
+    currentUnderlinePosition = descender;
+  }
+
+  if( fabsf( currentUnderlinePosition ) < Math::MACHINE_EPSILON_1000 )
+  {
+    // Move offset down by one ( EFL behavior )
+    currentUnderlinePosition = 1.0f;
+  }
+
+  lastUnderlinedFontId = glyphInfo->fontId;
+}
+
+/// Draws the specified color to the pixel buffer
+void WriteColorToPixelBuffer(
+    GlyphData& glyphData,
+    uint32_t* bitmapBuffer,
+    const Vector4& color,
+    const unsigned int x,
+    const unsigned int y)
+{
+  // Always RGBA image for text with styles
+  uint32_t pixel = *( bitmapBuffer + y * glyphData.width + x );
+  uint8_t* pixelBuffer = reinterpret_cast<uint8_t*>( &pixel );
+
+  // Write the color to the pixel buffer
+  uint8_t colorAlpha = static_cast< uint8_t >( color.a * 255.f );
+  *( pixelBuffer + 3u ) = colorAlpha;
+  *( pixelBuffer + 2u ) = static_cast< uint8_t >( color.b * colorAlpha );
+  *( pixelBuffer + 1u ) = static_cast< uint8_t >( color.g * colorAlpha );
+  *( pixelBuffer      ) = static_cast< uint8_t >( color.r * colorAlpha );
+
+  *( bitmapBuffer + y * glyphData.width + x ) = pixel;
+}
+
+/// Draws the specified underline color to the buffer
+void DrawUnderline(
+    const Vector4& underlineColor,
+    const unsigned int bufferWidth,
+    const unsigned int bufferHeight,
+    GlyphData& glyphData,
+    const float baseline,
+    const float currentUnderlinePosition,
+    const float maxUnderlineThickness,
+    const float lineExtentLeft,
+    const float lineExtentRight)
+{
+  int underlineYOffset = glyphData.verticalOffset + baseline + currentUnderlinePosition;
+  uint32_t* bitmapBuffer = reinterpret_cast< uint32_t* >( glyphData.bitmapBuffer.GetBuffer() );
+
+  for( unsigned int y = underlineYOffset; y < underlineYOffset + maxUnderlineThickness; y++ )
+  {
+    if( y > bufferHeight - 1 )
+    {
+      // Do not write out of bounds.
+      break;
+    }
+
+    for( unsigned int x = glyphData.horizontalOffset + lineExtentLeft; x <= glyphData.horizontalOffset + lineExtentRight; x++ )
+    {
+      if( x > bufferWidth - 1 )
+      {
+        // Do not write out of bounds.
+        break;
+      }
+
+      WriteColorToPixelBuffer(glyphData, bitmapBuffer, underlineColor, x, y);
+    }
+  }
+}
+
+/// Draws the background color to the buffer
+void DrawBackgroundColor(
+    Vector4 backgroundColor,
+    const unsigned int bufferWidth,
+    const unsigned int bufferHeight,
+    GlyphData& glyphData,
+    const float baseline,
+    const LineRun& line,
+    const float lineExtentLeft,
+    const float lineExtentRight)
+{
+  uint32_t* bitmapBuffer = reinterpret_cast< uint32_t* >( glyphData.bitmapBuffer.GetBuffer() );
+
+  for( int y = glyphData.verticalOffset + baseline - line.ascender; y < glyphData.verticalOffset + baseline - line.descender; y++ )
+  {
+    if( ( y < 0 ) || ( y > static_cast<int>(bufferHeight - 1) ) )
+    {
+      // Do not write out of bounds.
+      continue;
+    }
+
+    for( int x = glyphData.horizontalOffset + lineExtentLeft; x <= glyphData.horizontalOffset + lineExtentRight; x++ )
+    {
+      if( ( x < 0 ) || ( x > static_cast<int>(bufferWidth - 1) ) )
+      {
+        // Do not write out of bounds.
+        continue;
+      }
+
+      WriteColorToPixelBuffer(glyphData, bitmapBuffer, backgroundColor, x, y);
+    }
+  }
+}
+
 } // namespace
 
 TypesetterPtr Typesetter::New( const ModelInterface* const model )
 } // namespace
 
 TypesetterPtr Typesetter::New( const ModelInterface* const model )
@@ -593,45 +736,7 @@ Devel::PixelBuffer Typesetter::CreateImageBuffer( const unsigned int bufferWidth
       if( underlineGlyph && ( glyphInfo->fontId != lastUnderlinedFontId ) )
       {
         // We need to fetch fresh font underline metrics
       if( underlineGlyph && ( glyphInfo->fontId != lastUnderlinedFontId ) )
       {
         // We need to fetch fresh font underline metrics
-        FontMetrics fontMetrics;
-        fontClient.GetFontMetrics( glyphInfo->fontId, fontMetrics );
-        currentUnderlinePosition = ceil( fabsf( fontMetrics.underlinePosition ) );
-        const float descender = ceil( fabsf( fontMetrics.descender ) );
-
-        if( fabsf( underlineHeight ) < Math::MACHINE_EPSILON_1000 )
-        {
-          currentUnderlineThickness = fontMetrics.underlineThickness;
-
-          // Ensure underline will be at least a pixel high
-          if ( currentUnderlineThickness < 1.0f )
-          {
-            currentUnderlineThickness = 1.0f;
-          }
-          else
-          {
-            currentUnderlineThickness = ceil( currentUnderlineThickness );
-          }
-        }
-
-        // The underline thickness should be the max underline thickness of all glyphs of the line.
-        if ( currentUnderlineThickness > maxUnderlineThickness )
-        {
-          maxUnderlineThickness = currentUnderlineThickness;
-        }
-
-        // Clamp the underline position at the font descender and check for ( as EFL describes it ) a broken font
-        if( currentUnderlinePosition > descender )
-        {
-          currentUnderlinePosition = descender;
-        }
-
-        if( fabsf( currentUnderlinePosition ) < Math::MACHINE_EPSILON_1000 )
-        {
-          // Move offset down by one ( EFL behavior )
-          currentUnderlinePosition = 1.0f;
-        }
-
-        lastUnderlinedFontId = glyphInfo->fontId;
+        FetchFontUnderlineMetrics(fontClient, glyphInfo, currentUnderlinePosition, underlineHeight, currentUnderlineThickness, maxUnderlineThickness, lastUnderlinedFontId);
       } // underline
 
       // Retrieves the glyph's position.
       } // underline
 
       // Retrieves the glyph's position.
@@ -728,77 +833,13 @@ Devel::PixelBuffer Typesetter::CreateImageBuffer( const unsigned int bufferWidth
     // Draw the underline from the leftmost glyph to the rightmost glyph
     if ( thereAreUnderlinedGlyphs && style == Typesetter::STYLE_UNDERLINE )
     {
     // Draw the underline from the leftmost glyph to the rightmost glyph
     if ( thereAreUnderlinedGlyphs && style == Typesetter::STYLE_UNDERLINE )
     {
-      int underlineYOffset = glyphData.verticalOffset + baseline + currentUnderlinePosition;
-
-      for( unsigned int y = underlineYOffset; y < underlineYOffset + maxUnderlineThickness; y++ )
-      {
-        if( y > bufferHeight - 1 )
-        {
-          // Do not write out of bounds.
-          break;
-        }
-
-        for( unsigned int x = glyphData.horizontalOffset + lineExtentLeft; x <= glyphData.horizontalOffset + lineExtentRight; x++ )
-        {
-          if( x > bufferWidth - 1 )
-          {
-            // Do not write out of bounds.
-            break;
-          }
-
-          // Always RGBA image for text with styles
-          uint32_t* bitmapBuffer = reinterpret_cast< uint32_t* >( glyphData.bitmapBuffer.GetBuffer() );
-          uint32_t underlinePixel = *( bitmapBuffer + y * glyphData.width + x );
-          uint8_t* underlinePixelBuffer = reinterpret_cast<uint8_t*>( &underlinePixel );
-
-          // Write the underline color to the pixel buffer
-          uint8_t colorAlpha = static_cast< uint8_t >( underlineColor.a * 255.f );
-          *( underlinePixelBuffer + 3u ) = colorAlpha;
-          *( underlinePixelBuffer + 2u ) = static_cast< uint8_t >( underlineColor.b * colorAlpha );
-          *( underlinePixelBuffer + 1u ) = static_cast< uint8_t >( underlineColor.g * colorAlpha );
-          *( underlinePixelBuffer      ) = static_cast< uint8_t >( underlineColor.r * colorAlpha );
-
-          *( bitmapBuffer + y * glyphData.width + x ) = underlinePixel;
-        }
-      }
+      DrawUnderline(underlineColor, bufferWidth, bufferHeight, glyphData, baseline, currentUnderlinePosition, maxUnderlineThickness, lineExtentLeft, lineExtentRight);
     }
 
     // Draw the background color from the leftmost glyph to the rightmost glyph
     if ( style == Typesetter::STYLE_BACKGROUND )
     {
     }
 
     // Draw the background color from the leftmost glyph to the rightmost glyph
     if ( style == Typesetter::STYLE_BACKGROUND )
     {
-      Vector4 backgroundColor = mModel->GetBackgroundColor();
-
-      for( int y = glyphData.verticalOffset + baseline - line.ascender; y < glyphData.verticalOffset + baseline - line.descender; y++ )
-      {
-        if( ( y < 0 ) || ( y > static_cast<int>(bufferHeight - 1) ) )
-        {
-          // Do not write out of bounds.
-          continue;
-        }
-
-        for( int x = glyphData.horizontalOffset + lineExtentLeft; x <= glyphData.horizontalOffset + lineExtentRight; x++ )
-        {
-          if( ( x < 0 ) || ( x > static_cast<int>(bufferWidth - 1) ) )
-          {
-            // Do not write out of bounds.
-            continue;
-          }
-
-          // Always RGBA image for text with styles
-          uint32_t* bitmapBuffer = reinterpret_cast< uint32_t* >( glyphData.bitmapBuffer.GetBuffer() );
-          uint32_t backgroundPixel = *( bitmapBuffer + y * glyphData.width + x );
-          uint8_t* backgroundPixelBuffer = reinterpret_cast<uint8_t*>( &backgroundPixel );
-
-          // Write the background color to the pixel buffer
-          uint8_t colorAlpha = static_cast< uint8_t >( backgroundColor.a * 255.f );
-          *( backgroundPixelBuffer + 3u ) = colorAlpha;
-          *( backgroundPixelBuffer + 2u ) = static_cast< uint8_t >( backgroundColor.b * colorAlpha );
-          *( backgroundPixelBuffer + 1u ) = static_cast< uint8_t >( backgroundColor.g * colorAlpha );
-          *( backgroundPixelBuffer      ) = static_cast< uint8_t >( backgroundColor.r * colorAlpha );
-
-          *( bitmapBuffer + y * glyphData.width + x ) = backgroundPixel;
-        }
-      }
+      DrawBackgroundColor(mModel->GetBackgroundColor(), bufferWidth, bufferHeight, glyphData, baseline, line, lineExtentLeft, lineExtentRight);
     }
 
     // Increases the vertical offset with the line's descender.
     }
 
     // Increases the vertical offset with the line's descender.
index 78dab18..bda70a4 100644 (file)
@@ -1,5 +1,5 @@
 /*
 /*
- * Copyright (c) 2016 Samsung Electronics Co., Ltd.
+ * 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.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -65,6 +65,114 @@ namespace Toolkit
 namespace Internal
 {
 
 namespace Internal
 {
 
+namespace
+{
+
+/// Parses a Property::Array and sets up the animator appropriately
+void ParseArray(TransitionData::Animator* animator, const Property::Array* array)
+{
+  bool valid = true;
+  Vector4 controlPoints;
+  if( array && array->Count() >= 4 )
+  {
+    for( size_t vecIdx = 0; vecIdx < 4; ++vecIdx )
+    {
+      const Property::Value& v = array->GetElementAt(vecIdx);
+      if( v.GetType() == Property::FLOAT )
+      {
+        controlPoints[vecIdx] = v.Get<float>();
+      }
+      else
+      {
+        valid = false;
+        break;
+      }
+    }
+  }
+  else
+  {
+    valid = false;
+  }
+
+  if( valid )
+  {
+    Vector2 controlPoint1( controlPoints.x, controlPoints.y );
+    Vector2 controlPoint2( controlPoints.z, controlPoints.w );
+    animator->alphaFunction = AlphaFunction( controlPoint1, controlPoint2 );
+  }
+  else
+  {
+    animator->animate = false;
+  }
+}
+
+/// Parses a string value and sets up the animator appropriately
+void ParseString(TransitionData::Animator* animator, std::string alphaFunctionValue)
+{
+  if( alphaFunctionValue == "LINEAR" )
+  {
+    animator->alphaFunction = AlphaFunction(AlphaFunction::LINEAR);
+  }
+  else if( ! alphaFunctionValue.compare(0, 5, "EASE_" ) )
+  {
+    if( alphaFunctionValue == "EASE_IN" )
+    {
+      animator->alphaFunction = AlphaFunction(AlphaFunction::EASE_IN);
+    }
+    else if( alphaFunctionValue == "EASE_OUT" )
+    {
+      animator->alphaFunction = AlphaFunction(AlphaFunction::EASE_OUT);
+    }
+    else if( ! alphaFunctionValue.compare( 5, 3, "IN_" ) )
+    {
+      if( ! alphaFunctionValue.compare(8, -1, "SQUARE" ))
+      {
+        animator->alphaFunction = AlphaFunction(AlphaFunction::EASE_IN_SQUARE);
+      }
+      else if( ! alphaFunctionValue.compare(8, -1, "OUT" ))
+      {
+        animator->alphaFunction = AlphaFunction(AlphaFunction::EASE_IN_OUT);
+      }
+      else if( ! alphaFunctionValue.compare(8, -1, "OUT_SINE" ))
+      {
+        animator->alphaFunction = AlphaFunction(AlphaFunction::EASE_IN_OUT_SINE);
+      }
+      else if( ! alphaFunctionValue.compare(8, -1, "SINE" ))
+      {
+        animator->alphaFunction = AlphaFunction(AlphaFunction::EASE_IN_SINE);
+      }
+    }
+    else if( ! alphaFunctionValue.compare( 5, 4, "OUT_" ) )
+    {
+      if( ! alphaFunctionValue.compare(9, -1, "SQUARE" ) )
+      {
+        animator->alphaFunction = AlphaFunction(AlphaFunction::EASE_OUT_SQUARE);
+      }
+      else if( ! alphaFunctionValue.compare(9, -1, "SINE" ) )
+      {
+        animator->alphaFunction = AlphaFunction(AlphaFunction::EASE_OUT_SINE);
+      }
+      else if( ! alphaFunctionValue.compare(9, -1, "BACK" ) )
+      {
+        animator->alphaFunction = AlphaFunction(AlphaFunction::EASE_OUT_BACK);
+      }
+    }
+  }
+  else if( alphaFunctionValue == "REVERSE" )
+  {
+    animator->alphaFunction = AlphaFunction(AlphaFunction::REVERSE);
+  }
+  else if( alphaFunctionValue == "BOUNCE" )
+  {
+    animator->alphaFunction = AlphaFunction(AlphaFunction::BOUNCE);
+  }
+  else if( alphaFunctionValue == "SIN" )
+  {
+    animator->alphaFunction = AlphaFunction(AlphaFunction::SIN);
+  }
+}
+} // unnamed namespace
+
 TransitionData::TransitionData()
 {
 }
 TransitionData::TransitionData()
 {
 }
@@ -171,40 +279,7 @@ TransitionData::Animator* TransitionData::ConvertMap( const Property::Map& map)
         {
           if( value.GetType() == Property::ARRAY )
           {
         {
           if( value.GetType() == Property::ARRAY )
           {
-            bool valid = true;
-            Vector4 controlPoints;
-            const Property::Array* array = value.GetArray();
-            if( array && array->Count() >= 4 )
-            {
-              for( size_t vecIdx = 0; vecIdx < 4; ++vecIdx )
-              {
-                const Property::Value& v = array->GetElementAt(vecIdx);
-                if( v.GetType() == Property::FLOAT )
-                {
-                  controlPoints[vecIdx] = v.Get<float>();
-                }
-                else
-                {
-                  valid = false;
-                  break;
-                }
-              }
-            }
-            else
-            {
-              valid = false;
-            }
-
-            if( valid )
-            {
-              Vector2 controlPoint1( controlPoints.x, controlPoints.y );
-              Vector2 controlPoint2( controlPoints.z, controlPoints.w );
-              animator->alphaFunction = AlphaFunction( controlPoint1, controlPoint2 );
-            }
-            else
-            {
-              animator->animate = false;
-            }
+            ParseArray(animator, value.GetArray());
           }
           else if( value.GetType() == Property::VECTOR4 )
           {
           }
           else if( value.GetType() == Property::VECTOR4 )
           {
@@ -215,69 +290,7 @@ TransitionData::Animator* TransitionData::ConvertMap( const Property::Map& map)
           }
           else if( value.GetType() == Property::STRING )
           {
           }
           else if( value.GetType() == Property::STRING )
           {
-            std::string alphaFunctionValue = value.Get< std::string >();
-
-            if( alphaFunctionValue == "LINEAR" )
-            {
-              animator->alphaFunction = AlphaFunction(AlphaFunction::LINEAR);
-            }
-            else if( ! alphaFunctionValue.compare(0, 5, "EASE_" ) )
-            {
-              if( alphaFunctionValue == "EASE_IN" )
-              {
-                animator->alphaFunction = AlphaFunction(AlphaFunction::EASE_IN);
-              }
-              else if( alphaFunctionValue == "EASE_OUT" )
-              {
-                animator->alphaFunction = AlphaFunction(AlphaFunction::EASE_OUT);
-              }
-              else if( ! alphaFunctionValue.compare( 5, 3, "IN_" ) )
-              {
-                if( ! alphaFunctionValue.compare(8, -1, "SQUARE" ))
-                {
-                  animator->alphaFunction = AlphaFunction(AlphaFunction::EASE_IN_SQUARE);
-                }
-                else if( ! alphaFunctionValue.compare(8, -1, "OUT" ))
-                {
-                  animator->alphaFunction = AlphaFunction(AlphaFunction::EASE_IN_OUT);
-                }
-                else if( ! alphaFunctionValue.compare(8, -1, "OUT_SINE" ))
-                {
-                  animator->alphaFunction = AlphaFunction(AlphaFunction::EASE_IN_OUT_SINE);
-                }
-                else if( ! alphaFunctionValue.compare(8, -1, "SINE" ))
-                {
-                  animator->alphaFunction = AlphaFunction(AlphaFunction::EASE_IN_SINE);
-                }
-              }
-              else if( ! alphaFunctionValue.compare( 5, 4, "OUT_" ) )
-              {
-                if( ! alphaFunctionValue.compare(9, -1, "SQUARE" ) )
-                {
-                  animator->alphaFunction = AlphaFunction(AlphaFunction::EASE_OUT_SQUARE);
-                }
-                else if( ! alphaFunctionValue.compare(9, -1, "SINE" ) )
-                {
-                  animator->alphaFunction = AlphaFunction(AlphaFunction::EASE_OUT_SINE);
-                }
-                else if( ! alphaFunctionValue.compare(9, -1, "BACK" ) )
-                {
-                  animator->alphaFunction = AlphaFunction(AlphaFunction::EASE_OUT_BACK);
-                }
-              }
-            }
-            else if( alphaFunctionValue == "REVERSE" )
-            {
-              animator->alphaFunction = AlphaFunction(AlphaFunction::REVERSE);
-            }
-            else if( alphaFunctionValue == "BOUNCE" )
-            {
-              animator->alphaFunction = AlphaFunction(AlphaFunction::BOUNCE);
-            }
-            else if( alphaFunctionValue == "SIN" )
-            {
-              animator->alphaFunction = AlphaFunction(AlphaFunction::SIN);
-            }
+            ParseString(animator, value.Get< std::string >());
           }
           else
           {
           }
           else
           {