Combine textvisual shader by TextShaderFactory 06/276106/15
authorEunki, Hong <eunkiki.hong@samsung.com>
Thu, 9 Jun 2022 13:20:36 +0000 (22:20 +0900)
committerEunki Hong <eunkiki.hong@samsung.com>
Mon, 11 Jul 2022 04:19:00 +0000 (04:19 +0000)
Let TextVisual can control the shader & textures as factory.
Now we don't need to create new shader file
when we add more feature for text visual.

Change-Id: I4615de30f39715f45678c87dd2755a8be99f861e
Signed-off-by: Eunki, Hong <eunkiki.hong@samsung.com>
18 files changed:
dali-toolkit/internal/file.list
dali-toolkit/internal/graphics/shaders/text-visual-multi-color-text-shader.frag [deleted file]
dali-toolkit/internal/graphics/shaders/text-visual-multi-color-text-with-style-shader.frag [deleted file]
dali-toolkit/internal/graphics/shaders/text-visual-shader.frag [new file with mode: 0644]
dali-toolkit/internal/graphics/shaders/text-visual-shader.vert
dali-toolkit/internal/graphics/shaders/text-visual-single-color-text-shader.frag [deleted file]
dali-toolkit/internal/graphics/shaders/text-visual-single-color-text-with-emoji-shader.frag [deleted file]
dali-toolkit/internal/graphics/shaders/text-visual-single-color-text-with-style-and-emoji-shader.frag [deleted file]
dali-toolkit/internal/graphics/shaders/text-visual-single-color-text-with-style-shader.frag [deleted file]
dali-toolkit/internal/text/markup-processor.cpp
dali-toolkit/internal/text/rendering/atlas/text-atlas-renderer.cpp
dali-toolkit/internal/visuals/text-visual-shader-factory.cpp [new file with mode: 0644]
dali-toolkit/internal/visuals/text-visual-shader-factory.h [new file with mode: 0644]
dali-toolkit/internal/visuals/text/text-visual.cpp
dali-toolkit/internal/visuals/text/text-visual.h
dali-toolkit/internal/visuals/visual-factory-cache.h
dali-toolkit/internal/visuals/visual-factory-impl.cpp
dali-toolkit/internal/visuals/visual-factory-impl.h

index d80bffe..6edbd75 100644 (file)
@@ -44,6 +44,7 @@ SET( toolkit_src_files
    ${toolkit_src_dir}/visuals/primitive/primitive-visual.cpp
    ${toolkit_src_dir}/visuals/svg/svg-rasterize-thread.cpp
    ${toolkit_src_dir}/visuals/svg/svg-visual.cpp
+   ${toolkit_src_dir}/visuals/text-visual-shader-factory.cpp
    ${toolkit_src_dir}/visuals/text/text-visual.cpp
    ${toolkit_src_dir}/visuals/transition-data-impl.cpp
    ${toolkit_src_dir}/visuals/image-visual-shader-factory.cpp
diff --git a/dali-toolkit/internal/graphics/shaders/text-visual-multi-color-text-shader.frag b/dali-toolkit/internal/graphics/shaders/text-visual-multi-color-text-shader.frag
deleted file mode 100644 (file)
index e9e1069..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-varying mediump vec2 vTexCoord;
-uniform sampler2D sTexture;
-uniform lowp vec4 uColor;
-uniform lowp vec3 mixColor;
-
-void main()
-{
-  mediump vec4 textTexture = texture2D( sTexture, vTexCoord );
-
-  gl_FragColor = textTexture * uColor * vec4( mixColor, 1.0 );
-}
diff --git a/dali-toolkit/internal/graphics/shaders/text-visual-multi-color-text-with-style-shader.frag b/dali-toolkit/internal/graphics/shaders/text-visual-multi-color-text-with-style-shader.frag
deleted file mode 100644 (file)
index ca42ca6..0000000
+++ /dev/null
@@ -1,16 +0,0 @@
-varying mediump vec2 vTexCoord;
-uniform sampler2D sTexture;
-uniform sampler2D sStyle;
-uniform sampler2D sOverlayStyle;
-uniform lowp vec4 uColor;
-uniform lowp vec3 mixColor;
-
-void main()
-{
-  mediump vec4 textTexture = texture2D( sTexture, vTexCoord );
-  mediump vec4 styleTexture = texture2D( sStyle, vTexCoord );
-  mediump vec4 overlayStyleTexture = texture2D( sOverlayStyle, vTexCoord );
-
-  // Draw the text as overlay above the style
-  gl_FragColor = ( overlayStyleTexture + textTexture * (1.0 - overlayStyleTexture.a) + styleTexture * ( 1.0 - textTexture.a ) * (1.0 - overlayStyleTexture.a) ) * uColor * vec4( mixColor, 1.0 );
-}
diff --git a/dali-toolkit/internal/graphics/shaders/text-visual-shader.frag b/dali-toolkit/internal/graphics/shaders/text-visual-shader.frag
new file mode 100644 (file)
index 0000000..0fc642e
--- /dev/null
@@ -0,0 +1,63 @@
+INPUT mediump vec2 vTexCoord;
+uniform sampler2D sTexture;
+#ifdef IS_REQUIRED_STYLE
+uniform sampler2D sStyle;
+#endif
+#ifdef IS_REQUIRED_OVERLAY
+uniform sampler2D sOverlayStyle;
+#endif
+#ifdef IS_REQUIRED_MULTI_COLOR
+#elif defined(IS_REQUIRED_EMOJI)
+// Single color with emoji.
+uniform sampler2D sMask;
+uniform lowp float uHasMultipleTextColors;
+#endif
+uniform lowp vec4 uTextColorAnimatable;
+uniform lowp vec4 uColor;
+uniform lowp vec3 mixColor;
+
+void main()
+{
+#ifdef IS_REQUIRED_STYLE
+  mediump vec4 styleTexture = TEXTURE( sStyle, vTexCoord );
+#endif
+
+#ifdef IS_REQUIRED_OVERLAY
+  mediump vec4 overlayStyleTexture = TEXTURE( sOverlayStyle, vTexCoord );
+#endif
+
+#if defined(IS_REQUIRED_MULTI_COLOR) || defined(IS_REQUIRED_EMOJI)
+  // Multiple color or use emoji.
+  mediump vec4 textColor = TEXTURE(sTexture, vTexCoord);
+
+#ifdef IS_REQUIRED_MULTI_COLOR
+#elif defined(IS_REQUIRED_EMOJI)
+  // Single color with emoji.
+  mediump float maskTexture = TEXTURE(sMask, vTexCoord).r;
+
+  // Set the color of non-transparent pixel in text to what it is animated to.
+  // Markup text with multiple text colors are not animated (but can be supported later on if required).
+  // Emoji color are not animated.
+  mediump float vstep = step( 0.0001, textColor.a );
+  textColor.rgb = mix(textColor.rgb, uTextColorAnimatable.rgb, vstep * maskTexture * (1.0 - uHasMultipleTextColors));
+#endif
+#else
+  // Single color without emoji.
+  mediump float textTexture = TEXTURE(sTexture, vTexCoord).r;
+  mediump vec4 textColor = uTextColorAnimatable * textTexture;
+#endif
+
+  // Draw the text as overlay above the style
+  OUT_COLOR = uColor * vec4(mixColor, 1.0) * (
+#ifdef IS_REQUIRED_OVERLAY
+                   (
+#endif
+                     textColor
+#ifdef IS_REQUIRED_STYLE
+                     + styleTexture * (1.0 - textColor.a)
+#endif
+#ifdef IS_REQUIRED_OVERLAY
+                   ) * (1.0 - overlayStyleTexture.a) + overlayStyleTexture
+#endif
+                 );
+}
index 4cc1212..6e90fe9 100644 (file)
@@ -1,9 +1,9 @@
-attribute mediump vec2 aPosition;
+INPUT mediump vec2 aPosition;
 uniform highp mat4 uMvpMatrix;
 uniform highp vec3 uSize;
 uniform mediump vec4 pixelArea;
 
-varying mediump vec2 vTexCoord;
+OUTPUT mediump vec2 vTexCoord;
 
 //Visual size and offset
 uniform mediump vec2 offset;
diff --git a/dali-toolkit/internal/graphics/shaders/text-visual-single-color-text-shader.frag b/dali-toolkit/internal/graphics/shaders/text-visual-single-color-text-shader.frag
deleted file mode 100644 (file)
index ab44460..0000000
+++ /dev/null
@@ -1,13 +0,0 @@
-varying mediump vec2 vTexCoord;
-uniform sampler2D sTexture;
-uniform lowp vec4 uTextColorAnimatable;
-uniform lowp vec4 uColor;
-uniform lowp vec3 mixColor;
-
-void main()
-{
-  mediump float textTexture = texture2D( sTexture, vTexCoord ).r;
-
-  // Set the color of the text to what it is animated to.
-  gl_FragColor = uTextColorAnimatable * textTexture * uColor * vec4( mixColor, 1.0 );
-}
diff --git a/dali-toolkit/internal/graphics/shaders/text-visual-single-color-text-with-emoji-shader.frag b/dali-toolkit/internal/graphics/shaders/text-visual-single-color-text-with-emoji-shader.frag
deleted file mode 100644 (file)
index 544f0be..0000000
+++ /dev/null
@@ -1,21 +0,0 @@
-varying mediump vec2 vTexCoord;
-uniform sampler2D sTexture;
-uniform sampler2D sMask;
-uniform lowp vec4 uTextColorAnimatable;
-uniform lowp vec4 uColor;
-uniform lowp vec3 mixColor;
-
-void main()
-{
-  mediump vec4 textTexture = texture2D( sTexture, vTexCoord );
-  mediump float maskTexture = texture2D( sMask, vTexCoord ).r;
-
-  // Set the color of non-transparent pixel in text to what it is animated to.
-  // Markup text with multiple text colors are not animated (but can be supported later on if required).
-  // Emoji color are not animated.
-  mediump float vstep = step( 0.0001, textTexture.a );
-  textTexture.rgb = mix( textTexture.rgb, uTextColorAnimatable.rgb, vstep * maskTexture );
-
-  // Draw the text as overlay above the style
-  gl_FragColor = textTexture * uColor * vec4( mixColor, 1.0 );
-}
diff --git a/dali-toolkit/internal/graphics/shaders/text-visual-single-color-text-with-style-and-emoji-shader.frag b/dali-toolkit/internal/graphics/shaders/text-visual-single-color-text-with-style-and-emoji-shader.frag
deleted file mode 100644 (file)
index 0d82aa7..0000000
+++ /dev/null
@@ -1,26 +0,0 @@
-varying mediump vec2 vTexCoord;
-uniform sampler2D sTexture;
-uniform sampler2D sStyle;
-uniform sampler2D sOverlayStyle;
-uniform sampler2D sMask;
-uniform lowp float uHasMultipleTextColors;
-uniform lowp vec4 uTextColorAnimatable;
-uniform lowp vec4 uColor;
-uniform lowp vec3 mixColor;
-
-void main()
-{
-  mediump vec4 textTexture = texture2D( sTexture, vTexCoord );
-  mediump vec4 styleTexture = texture2D( sStyle, vTexCoord );
-  mediump vec4 overlayStyleTexture = texture2D( sOverlayStyle, vTexCoord );
-  mediump float maskTexture = texture2D( sMask, vTexCoord ).r;
-
-  // Set the color of non-transparent pixel in text to what it is animated to.
-  // Markup text with multiple text colors are not animated (but can be supported later on if required).
-  // Emoji color are not animated.
-  mediump float vstep = step( 0.0001, textTexture.a );
-  textTexture.rgb = mix( textTexture.rgb, uTextColorAnimatable.rgb, vstep * maskTexture * ( 1.0 - uHasMultipleTextColors ) );
-
-  // Draw the text as overlay above the style
-  gl_FragColor = ( overlayStyleTexture + textTexture * (1.0 - overlayStyleTexture.a) + styleTexture * ( 1.0 - textTexture.a ) * (1.0 - overlayStyleTexture.a) ) * uColor * vec4( mixColor, 1.0 );
-}
diff --git a/dali-toolkit/internal/graphics/shaders/text-visual-single-color-text-with-style-shader.frag b/dali-toolkit/internal/graphics/shaders/text-visual-single-color-text-with-style-shader.frag
deleted file mode 100644 (file)
index cf93f15..0000000
+++ /dev/null
@@ -1,17 +0,0 @@
-varying mediump vec2 vTexCoord;
-uniform sampler2D sTexture;
-uniform sampler2D sStyle;
-uniform sampler2D sOverlayStyle;
-uniform lowp vec4 uTextColorAnimatable;
-uniform lowp vec4 uColor;
-uniform lowp vec3 mixColor;
-
-void main()
-{
-  mediump float textTexture = texture2D( sTexture, vTexCoord ).r;
-  mediump vec4 styleTexture = texture2D( sStyle, vTexCoord );
-  mediump vec4 overlayStyleTexture = texture2D( sOverlayStyle, vTexCoord );
-
-  // Draw the text as overlay above the style
-  gl_FragColor = ( overlayStyleTexture + uTextColorAnimatable * textTexture * (1.0 - overlayStyleTexture.a) + styleTexture * ( 1.0 - uTextColorAnimatable.a * textTexture ) * (1.0 - overlayStyleTexture.a) ) * uColor * vec4( mixColor, 1.0 );
-}
\ No newline at end of file
index 1047411..344cde1 100644 (file)
@@ -941,10 +941,13 @@ void ResizeModelVectors(MarkupProcessData& markupProcessData,
   markupProcessData.characterSpacingCharacterRuns.Resize(characterSpacingCharacterRunIndex);
 
 #ifdef DEBUG_ENABLED
-  for(uint32_t i = 0; gLogFilter->IsEnabledFor(Debug::Verbose) && i < colorRunIndex; ++i)
+  if(gLogFilter->IsEnabledFor(Debug::Verbose))
   {
-    ColorRun& run = markupProcessData.colorRuns[i];
-    DALI_LOG_INFO(gLogFilter, Debug::Verbose, "run[%d] index: %d, length: %d, color %f,%f,%f,%f\n", i, run.characterRun.characterIndex, run.characterRun.numberOfCharacters, run.color.r, run.color.g, run.color.b, run.color.a);
+    for(uint32_t i = 0; i < colorRunIndex; ++i)
+    {
+      ColorRun& run = markupProcessData.colorRuns[i];
+      DALI_LOG_INFO(gLogFilter, Debug::Verbose, "run[%d] index: %d, length: %d, color %f,%f,%f,%f\n", i, run.characterRun.characterIndex, run.characterRun.numberOfCharacters, run.color.r, run.color.g, run.color.b, run.color.a);
+    }
   }
 #endif
 }
index 1a1063c..1d8731d 100644 (file)
@@ -802,11 +802,14 @@ struct AtlasRenderer::Impl
     Toolkit::AtlasGlyphManager::Metrics metrics = mGlyphManager.GetMetrics();
     DALI_LOG_INFO(gLogFilter, Debug::General, "TextAtlasRenderer::GlyphManager::GlyphCount: %i, AtlasCount: %i, TextureMemoryUse: %iK\n", metrics.mGlyphCount, metrics.mAtlasMetrics.mAtlasCount, metrics.mAtlasMetrics.mTextureMemoryUsed / 1024);
 
-    DALI_LOG_INFO(gLogFilter, Debug::Verbose, "%s\n", metrics.mVerboseGlyphCounts.c_str());
-
-    for(uint32_t i = 0; gLogFilter->IsEnabledFor(Debug::Verbose) && i < metrics.mAtlasMetrics.mAtlasCount; ++i)
+    if(gLogFilter->IsEnabledFor(Debug::Verbose))
     {
-      DALI_LOG_INFO(gLogFilter, Debug::Verbose, "   Atlas [%i] %sPixels: %s Size: %ix%i, BlockSize: %ix%i, BlocksUsed: %i/%i\n", i + 1, i > 8 ? "" : " ", metrics.mAtlasMetrics.mAtlasMetrics[i].mPixelFormat == Pixel::L8 ? "L8  " : "BGRA", metrics.mAtlasMetrics.mAtlasMetrics[i].mSize.mWidth, metrics.mAtlasMetrics.mAtlasMetrics[i].mSize.mHeight, metrics.mAtlasMetrics.mAtlasMetrics[i].mSize.mBlockWidth, metrics.mAtlasMetrics.mAtlasMetrics[i].mSize.mBlockHeight, metrics.mAtlasMetrics.mAtlasMetrics[i].mBlocksUsed, metrics.mAtlasMetrics.mAtlasMetrics[i].mTotalBlocks);
+      DALI_LOG_INFO(gLogFilter, Debug::Verbose, "%s\n", metrics.mVerboseGlyphCounts.c_str());
+
+      for(uint32_t i = 0; i < metrics.mAtlasMetrics.mAtlasCount; ++i)
+      {
+        DALI_LOG_INFO(gLogFilter, Debug::Verbose, "   Atlas [%i] %sPixels: %s Size: %ix%i, BlockSize: %ix%i, BlocksUsed: %i/%i\n", i + 1, i > 8 ? "" : " ", metrics.mAtlasMetrics.mAtlasMetrics[i].mPixelFormat == Pixel::L8 ? "L8  " : "BGRA", metrics.mAtlasMetrics.mAtlasMetrics[i].mSize.mWidth, metrics.mAtlasMetrics.mAtlasMetrics[i].mSize.mHeight, metrics.mAtlasMetrics.mAtlasMetrics[i].mSize.mBlockWidth, metrics.mAtlasMetrics.mAtlasMetrics[i].mSize.mBlockHeight, metrics.mAtlasMetrics.mAtlasMetrics[i].mBlocksUsed, metrics.mAtlasMetrics.mAtlasMetrics[i].mTotalBlocks);
+      }
     }
 #endif
   }
diff --git a/dali-toolkit/internal/visuals/text-visual-shader-factory.cpp b/dali-toolkit/internal/visuals/text-visual-shader-factory.cpp
new file mode 100644 (file)
index 0000000..5a2eba8
--- /dev/null
@@ -0,0 +1,167 @@
+/*
+ * Copyright (c) 2022 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.
+ */
+
+// CLASS HEADER
+#include <dali-toolkit/internal/visuals/text-visual-shader-factory.h>
+
+// INTERNAL INCLUDES
+#include <dali-toolkit/internal/graphics/builtin-shader-extern-gen.h>
+#include <dali-toolkit/internal/visuals/visual-string-constants.h>
+#include <dali/integration-api/debug.h>
+
+namespace Dali
+{
+namespace Toolkit
+{
+namespace Internal
+{
+namespace
+{
+// global string variable to caching complate vertex shader
+static std::string gVertexShader;
+
+// global string variable to caching complate fragment shader (no atlas)
+static std::string gFragmentShaderNoAtlas;
+
+// enum of required list when we select shader
+enum class TextVisualRequireFlag : uint32_t
+{
+  DEFAULT     = 0,
+  STYLES      = 1 << 0,
+  OVERLAY     = 1 << 1,
+  EMOJI       = 1 << 2,
+  MULTI_COLOR = 1 << 3,
+};
+
+const VisualFactoryCache::ShaderType SHADER_TYPE_TABLE[] =
+  {
+    VisualFactoryCache::TEXT_SHADER_SINGLE_COLOR_TEXT,
+    VisualFactoryCache::TEXT_SHADER_SINGLE_COLOR_TEXT_WITH_STYLE,
+    VisualFactoryCache::TEXT_SHADER_SINGLE_COLOR_TEXT_WITH_OVERLAY,
+    VisualFactoryCache::TEXT_SHADER_SINGLE_COLOR_TEXT_WITH_STYLE_AND_OVERLAY,
+    VisualFactoryCache::TEXT_SHADER_SINGLE_COLOR_TEXT_WITH_EMOJI,
+    VisualFactoryCache::TEXT_SHADER_SINGLE_COLOR_TEXT_WITH_STYLE_AND_EMOJI,
+    VisualFactoryCache::TEXT_SHADER_SINGLE_COLOR_TEXT_WITH_OVERLAY_AND_EMOJI,
+    VisualFactoryCache::TEXT_SHADER_SINGLE_COLOR_TEXT_WITH_STYLE_AND_OVERLAY_AND_EMOJI,
+    VisualFactoryCache::TEXT_SHADER_MULTI_COLOR_TEXT,
+    VisualFactoryCache::TEXT_SHADER_MULTI_COLOR_TEXT_WITH_STYLE,
+    VisualFactoryCache::TEXT_SHADER_MULTI_COLOR_TEXT_WITH_OVERLAY,
+    VisualFactoryCache::TEXT_SHADER_MULTI_COLOR_TEXT_WITH_STYLE_AND_OVERLAY,
+};
+
+} // unnamed namespace
+
+namespace TextVisualShaderFeature
+{
+FeatureBuilder& FeatureBuilder::EnableMultiColor(bool enableMultiColor)
+{
+  mTextMultiColor = enableMultiColor ? TextMultiColor::MULTI_COLOR_TEXT : TextMultiColor::SINGLE_COLOR_TEXT;
+  return *this;
+}
+FeatureBuilder& FeatureBuilder::EnableEmoji(bool enableEmoji)
+{
+  mTextEmoji = enableEmoji ? TextEmoji::HAS_EMOJI : TextEmoji::NO_EMOJI;
+  return *this;
+}
+FeatureBuilder& FeatureBuilder::EnableStyle(bool enableStyle)
+{
+  mTextStyle = enableStyle ? TextStyle::HAS_STYLES : TextStyle::NO_STYLES;
+  return *this;
+}
+FeatureBuilder& FeatureBuilder::EnableOverlay(bool enableOverlay)
+{
+  mTextOverlay = enableOverlay ? TextOverlay::HAS_OVERLAY : TextOverlay::NO_OVERLAY;
+  return *this;
+}
+} // namespace TextVisualShaderFeature
+
+TextVisualShaderFactory::TextVisualShaderFactory()
+{
+}
+
+TextVisualShaderFactory::~TextVisualShaderFactory()
+{
+}
+
+Shader TextVisualShaderFactory::GetShader(VisualFactoryCache& factoryCache, const TextVisualShaderFeature::FeatureBuilder& featureBuilder)
+{
+  Shader                         shader;
+  uint32_t                       shaderTypeFlag = static_cast<uint32_t>(TextVisualRequireFlag::DEFAULT);
+  VisualFactoryCache::ShaderType shaderType     = VisualFactoryCache::TEXT_SHADER_SINGLE_COLOR_TEXT;
+
+  const auto& multiColor = featureBuilder.mTextMultiColor;
+  const auto& emoji      = featureBuilder.mTextEmoji;
+  const auto& style      = featureBuilder.mTextStyle;
+  const auto& overlay    = featureBuilder.mTextOverlay;
+
+  if(style == TextVisualShaderFeature::TextStyle::HAS_STYLES)
+  {
+    shaderTypeFlag |= static_cast<uint32_t>(TextVisualRequireFlag::STYLES);
+  }
+  if(overlay == TextVisualShaderFeature::TextOverlay::HAS_OVERLAY)
+  {
+    shaderTypeFlag |= static_cast<uint32_t>(TextVisualRequireFlag::OVERLAY);
+  }
+  // multi color can also render emoji. If multi color text, dont consider emoji
+  if(multiColor != TextVisualShaderFeature::TextMultiColor::MULTI_COLOR_TEXT && emoji == TextVisualShaderFeature::TextEmoji::HAS_EMOJI)
+  {
+    shaderTypeFlag |= static_cast<uint32_t>(TextVisualRequireFlag::EMOJI);
+  }
+  if(multiColor == TextVisualShaderFeature::TextMultiColor::MULTI_COLOR_TEXT)
+  {
+    shaderTypeFlag |= static_cast<uint32_t>(TextVisualRequireFlag::MULTI_COLOR);
+  }
+
+  shaderType = SHADER_TYPE_TABLE[shaderTypeFlag];
+  shader     = factoryCache.GetShader(shaderType);
+
+  if(!shader)
+  {
+    std::string vertexShaderPrefixList;
+    std::string fragmentShaderPrefixList;
+
+    if(style == TextVisualShaderFeature::TextStyle::HAS_STYLES)
+    {
+      fragmentShaderPrefixList += "#define IS_REQUIRED_STYLE\n";
+    }
+    if(overlay == TextVisualShaderFeature::TextOverlay::HAS_OVERLAY)
+    {
+      fragmentShaderPrefixList += "#define IS_REQUIRED_OVERLAY\n";
+    }
+    // multi color can also render emoji. If multi color text, dont consider emoji
+    if(multiColor != TextVisualShaderFeature::TextMultiColor::MULTI_COLOR_TEXT && emoji == TextVisualShaderFeature::TextEmoji::HAS_EMOJI)
+    {
+      fragmentShaderPrefixList += "#define IS_REQUIRED_EMOJI\n";
+    }
+    if(multiColor == TextVisualShaderFeature::TextMultiColor::MULTI_COLOR_TEXT)
+    {
+      fragmentShaderPrefixList += "#define IS_REQUIRED_MULTI_COLOR\n";
+    }
+
+    std::string vertexShader   = std::string(Dali::Shader::GetVertexShaderPrefix() + vertexShaderPrefixList + SHADER_TEXT_VISUAL_SHADER_VERT.data());
+    std::string fragmentShader = std::string(Dali::Shader::GetFragmentShaderPrefix() + fragmentShaderPrefixList + SHADER_TEXT_VISUAL_SHADER_FRAG.data());
+
+    shader = Shader::New(vertexShader, fragmentShader);
+    factoryCache.SaveShader(shaderType, shader);
+  }
+  return shader;
+}
+
+} // namespace Internal
+
+} // namespace Toolkit
+
+} // namespace Dali
diff --git a/dali-toolkit/internal/visuals/text-visual-shader-factory.h b/dali-toolkit/internal/visuals/text-visual-shader-factory.h
new file mode 100644 (file)
index 0000000..4a9969b
--- /dev/null
@@ -0,0 +1,172 @@
+#ifndef DALI_TOOLKIT_TEXT_VISUAL_SHADER_FACTORY_H
+#define DALI_TOOLKIT_TEXT_VISUAL_SHADER_FACTORY_H
+
+/*
+ * Copyright (c) 2022 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.
+ */
+
+// EXTERNAL INCLUDES
+
+// INTERNAL INCLUDES
+#include <dali-toolkit/internal/visuals/visual-factory-cache.h>
+#include <string_view>
+
+namespace Dali
+{
+namespace Toolkit
+{
+namespace Internal
+{
+/**
+ * TextVisualShaderFeature contains feature lists what text visual shader need to know.
+ */
+namespace TextVisualShaderFeature
+{
+namespace TextMultiColor
+{
+/**
+ * @brief Whether text contains single color or not.
+ */
+enum Type
+{
+  SINGLE_COLOR_TEXT = 0, ///< The text contains single color only.
+  MULTI_COLOR_TEXT       ///< The text contains multiple colors.
+};
+} // namespace TextMultiColor
+
+namespace TextEmoji
+{
+/**
+ * @brief Whether text contains emoji or not.
+ */
+enum Type
+{
+  NO_EMOJI = 0, ///< The text contains no emoji.
+  HAS_EMOJI     ///< The text contains emoji.
+};
+} // namespace TextEmoji
+
+namespace TextStyle
+{
+/**
+ * @brief Whether text contains styles (like shadow or background color) or not.
+ */
+enum Type
+{
+  NO_STYLES = 0, ///< The text contains contains no styles.
+  HAS_STYLES     ///< The text contains contains styles.
+};
+} // namespace TextStyle
+
+namespace TextOverlay
+{
+/**
+ * @brief Whether text contains overlay styles (like markdown) or not.
+ */
+enum Type
+{
+  NO_OVERLAY = 0, ///< The text contains contains no overlay.
+  HAS_OVERLAY     ///< The text contains contains overlay.
+};
+} // namespace TextOverlay
+
+/**
+ * @brief Collection of current text visual feature.
+ */
+struct FeatureBuilder
+{
+  FeatureBuilder()
+  : mTextMultiColor(TextMultiColor::SINGLE_COLOR_TEXT),
+    mTextEmoji(TextEmoji::NO_EMOJI),
+    mTextStyle(TextStyle::NO_STYLES),
+    mTextOverlay(TextOverlay::NO_OVERLAY)
+  {
+  }
+
+  FeatureBuilder& EnableMultiColor(bool enableMultiColor);
+  FeatureBuilder& EnableEmoji(bool enableEmoji);
+  FeatureBuilder& EnableStyle(bool enableStyle);
+  FeatureBuilder& EnableOverlay(bool enableOverlay);
+
+  bool IsEnabledMultiColor() const
+  {
+    return mTextMultiColor == TextMultiColor::MULTI_COLOR_TEXT;
+  }
+  bool IsEnabledEmoji() const
+  {
+    return mTextEmoji == TextEmoji::HAS_EMOJI;
+  }
+  bool IsEnabledStyle() const
+  {
+    return mTextStyle == TextStyle::HAS_STYLES;
+  }
+  bool IsEnabledOverlay() const
+  {
+    return mTextOverlay == TextOverlay::HAS_OVERLAY;
+  }
+
+  TextMultiColor::Type mTextMultiColor : 2; ///< Whether text has multiple color, or not. default as TextMultiColor::SINGLE_COLOR_TEXT
+  TextEmoji::Type      mTextEmoji : 2;      ///< Whether text has emoji, or not. default as TextEmoji::NO_EMOJI
+  TextStyle::Type      mTextStyle : 2;      ///< Whether text has style, or not. default as TextStyle::NO_STYLES
+  TextOverlay::Type    mTextOverlay : 2;    ///< Whether text has overlay style, or not. default as TextOverlay::NO_OVERLAY
+};
+
+} // namespace TextVisualShaderFeature
+
+/**
+ * TextVisualShaderFactory is an object that provides and shares shaders for text visuals
+ */
+class TextVisualShaderFactory
+{
+public:
+  /**
+   * @brief Constructor
+   */
+  TextVisualShaderFactory();
+
+  /**
+   * @brief Destructor
+   */
+  ~TextVisualShaderFactory();
+
+  /**
+   * @brief Get the standard text rendering shader.
+   * @param[in] factoryCache A pointer pointing to the VisualFactoryCache object
+   * @param[in] featureBuilder Collection of current text shader's features
+   * @return The standard text rendering shader with features.
+   */
+  Shader GetShader(VisualFactoryCache& factoryCache, const TextVisualShaderFeature::FeatureBuilder& featureBuilder);
+
+protected:
+  /**
+   * Undefined copy constructor.
+   */
+  TextVisualShaderFactory(const TextVisualShaderFactory&);
+
+  /**
+   * Undefined assignment operator.
+   */
+  TextVisualShaderFactory& operator=(const TextVisualShaderFactory& rhs);
+
+private:
+};
+
+} // namespace Internal
+
+} // namespace Toolkit
+
+} // namespace Dali
+
+#endif // DALI_TOOLKIT_TEXT_VISUAL_SHADER_FACTORY_H
index 777e48f..2106745 100644 (file)
@@ -148,9 +148,9 @@ void OpacityConstraint(float& current, const PropertyInputContainer& inputs)
 
 } // unnamed namespace
 
-TextVisualPtr TextVisual::New(VisualFactoryCache& factoryCache, const Property::Map& properties)
+TextVisualPtr TextVisual::New(VisualFactoryCache& factoryCache, TextVisualShaderFactory& shaderFactory, const Property::Map& properties)
 {
-  TextVisualPtr textVisualPtr(new TextVisual(factoryCache));
+  TextVisualPtr textVisualPtr(new TextVisual(factoryCache, shaderFactory));
   textVisualPtr->SetProperties(properties);
   textVisualPtr->Initialize();
   return textVisualPtr;
@@ -249,10 +249,12 @@ void TextVisual::EnablePreMultipliedAlpha(bool preMultiplied)
   }
 }
 
-TextVisual::TextVisual(VisualFactoryCache& factoryCache)
+TextVisual::TextVisual(VisualFactoryCache& factoryCache, TextVisualShaderFactory& shaderFactory)
 : Visual::Base(factoryCache, Visual::FittingMode::FIT_KEEP_ASPECT_RATIO, Toolkit::Visual::TEXT),
   mController(Text::Controller::New()),
   mTypesetter(Text::Typesetter::New(mController->GetTextModel())),
+  mTextVisualShaderFactory(shaderFactory),
+  mTextShaderFeatureCache(),
   mAnimatableTextColorPropertyIndex(Property::INVALID_INDEX),
   mTextColorAnimatableIndex(Property::INVALID_INDEX),
   mRendererUpdateNeeded(false)
@@ -268,7 +270,7 @@ TextVisual::~TextVisual()
 void TextVisual::OnInitialize()
 {
   Geometry geometry = mFactoryCache.GetGeometry(VisualFactoryCache::QUAD_GEOMETRY);
-  Shader   shader   = GetTextShader(mFactoryCache, TextType::SINGLE_COLOR_TEXT, TextType::NO_EMOJI, TextType::NO_STYLES);
+  Shader   shader   = GetTextShader(mFactoryCache, TextVisualShaderFeature::FeatureBuilder());
 
   mImpl->mRenderer = VisualRenderer::New(geometry, shader);
   mImpl->mRenderer.ReserveCustomProperties(CUSTOM_PROPERTY_COUNT);
@@ -604,7 +606,7 @@ PixelData TextVisual::ConvertToPixelData(unsigned char* buffer, int width, int h
   return pixelData;
 }
 
-void TextVisual::CreateTextureSet(TilingInfo& info, VisualRenderer& renderer, Sampler& sampler, bool hasMultipleTextColors, bool containsColorGlyph, bool styleEnabled, bool isOverlayStyle)
+void TextVisual::CreateTextureSet(TilingInfo& info, VisualRenderer& renderer, Sampler& sampler)
 {
   TextureSet   textureSet      = TextureSet::New();
   unsigned int textureSetIndex = 0u;
@@ -618,21 +620,21 @@ void TextVisual::CreateTextureSet(TilingInfo& info, VisualRenderer& renderer, Sa
     ++textureSetIndex;
   }
 
-  if(styleEnabled && info.styleBuffer && info.overlayStyleBuffer)
+  if(mTextShaderFeatureCache.IsEnabledStyle() && info.styleBuffer)
   {
     PixelData styleData = ConvertToPixelData(info.styleBuffer, info.width, info.height, info.offsetPosition, Pixel::RGBA8888);
     AddTexture(textureSet, styleData, sampler, textureSetIndex);
     ++textureSetIndex;
+  }
 
-    // TODO : We need to seperate whether use overlayStyle or not.
-    // Current text visual shader required both of them.
-
+  if(mTextShaderFeatureCache.IsEnabledOverlay() && info.overlayStyleBuffer)
+  {
     PixelData overlayStyleData = ConvertToPixelData(info.overlayStyleBuffer, info.width, info.height, info.offsetPosition, Pixel::RGBA8888);
     AddTexture(textureSet, overlayStyleData, sampler, textureSetIndex);
     ++textureSetIndex;
   }
 
-  if(containsColorGlyph && !hasMultipleTextColors && info.maskBuffer)
+  if(mTextShaderFeatureCache.IsEnabledEmoji() && !mTextShaderFeatureCache.IsEnabledMultiColor() && info.maskBuffer)
   {
     PixelData maskData = ConvertToPixelData(info.maskBuffer, info.width, info.height, info.offsetPosition, Pixel::L8);
     AddTexture(textureSet, maskData, sampler, textureSetIndex);
@@ -651,14 +653,14 @@ void TextVisual::CreateTextureSet(TilingInfo& info, VisualRenderer& renderer, Sa
   renderer.SetProperty(VisualRenderer::Property::TRANSFORM_SIZE, Vector2(info.width, info.height));
   renderer.SetProperty(VisualRenderer::Property::TRANSFORM_OFFSET, Vector2(info.offSet.x, info.offSet.y));
   renderer.SetProperty(Renderer::Property::BLEND_MODE, BlendMode::ON);
-  renderer.RegisterProperty("uHasMultipleTextColors", static_cast<float>(hasMultipleTextColors));
+  renderer.RegisterProperty("uHasMultipleTextColors", static_cast<float>(mTextShaderFeatureCache.IsEnabledMultiColor()));
 
   mRendererList.push_back(renderer);
 }
 
 void TextVisual::AddRenderer(Actor& actor, const Vector2& size, bool hasMultipleTextColors, bool containsColorGlyph, bool styleEnabled, bool isOverlayStyle)
 {
-  Shader shader = GetTextShader(mFactoryCache, hasMultipleTextColors, containsColorGlyph, styleEnabled);
+  Shader shader = GetTextShader(mFactoryCache, TextVisualShaderFeature::FeatureBuilder().EnableMultiColor(hasMultipleTextColors).EnableEmoji(containsColorGlyph).EnableStyle(styleEnabled).EnableOverlay(isOverlayStyle));
   mImpl->mRenderer.SetShader(shader);
 
   // Get the maximum size.
@@ -667,7 +669,7 @@ void TextVisual::AddRenderer(Actor& actor, const Vector2& size, bool hasMultiple
   // No tiling required. Use the default renderer.
   if(size.height < maxTextureSize)
   {
-    TextureSet textureSet = GetTextTexture(size, hasMultipleTextColors, containsColorGlyph, styleEnabled, isOverlayStyle);
+    TextureSet textureSet = GetTextTexture(size);
 
     mImpl->mRenderer.SetTextures(textureSet);
     //Register transform properties
@@ -703,23 +705,23 @@ void TextVisual::AddRenderer(Actor& actor, const Vector2& size, bool hasMultiple
     Dali::DevelPixelData::PixelDataBuffer textPixelData = Dali::DevelPixelData::ReleasePixelDataBuffer(data);
     info.textBuffer                                     = textPixelData.buffer;
 
-    if(styleEnabled)
+    if(mTextShaderFeatureCache.IsEnabledStyle())
     {
       // Create RGBA texture for all the text styles (without the text itself)
       PixelData                             styleData      = mTypesetter->Render(size, textDirection, Text::Typesetter::RENDER_NO_TEXT, false, Pixel::RGBA8888);
       Dali::DevelPixelData::PixelDataBuffer stylePixelData = Dali::DevelPixelData::ReleasePixelDataBuffer(styleData);
       info.styleBuffer                                     = stylePixelData.buffer;
+    }
 
-      // TODO : We need to seperate whether use overlayStyle or not.
-      // Current text visual shader required both of them.
-
+    if(mTextShaderFeatureCache.IsEnabledOverlay())
+    {
       // Create RGBA texture for all the overlay styles
       PixelData                             overlayStyleData      = mTypesetter->Render(size, textDirection, Text::Typesetter::RENDER_OVERLAY_STYLE, false, Pixel::RGBA8888);
       Dali::DevelPixelData::PixelDataBuffer overlayStylePixelData = Dali::DevelPixelData::ReleasePixelDataBuffer(overlayStyleData);
       info.overlayStyleBuffer                                     = overlayStylePixelData.buffer;
     }
 
-    if(containsColorGlyph && !hasMultipleTextColors)
+    if(mTextShaderFeatureCache.IsEnabledEmoji() && !mTextShaderFeatureCache.IsEnabledMultiColor())
     {
       // Create a L8 texture as a mask to avoid color glyphs (e.g. emojis) to be affected by text color animation
       PixelData                             maskData      = mTypesetter->Render(size, textDirection, Text::Typesetter::RENDER_MASK, false, Pixel::L8);
@@ -737,7 +739,7 @@ void TextVisual::AddRenderer(Actor& actor, const Vector2& size, bool hasMultiple
     }
 
     // Create a textureset in the default renderer.
-    CreateTextureSet(info, mImpl->mRenderer, sampler, hasMultipleTextColors, containsColorGlyph, styleEnabled, isOverlayStyle);
+    CreateTextureSet(info, mImpl->mRenderer, sampler);
 
     verifiedHeight -= maxTextureSize;
 
@@ -756,7 +758,7 @@ void TextVisual::AddRenderer(Actor& actor, const Vector2& size, bool hasMultiple
       // New offset for tiling.
       info.offSet.y += maxTextureSize;
       // Create a textureset int the new tiling renderer.
-      CreateTextureSet(info, tilingRenderer, sampler, hasMultipleTextColors, containsColorGlyph, styleEnabled, isOverlayStyle);
+      CreateTextureSet(info, tilingRenderer, sampler);
 
       verifiedHeight -= maxTextureSize;
     }
@@ -800,7 +802,7 @@ void TextVisual::AddRenderer(Actor& actor, const Vector2& size, bool hasMultiple
   }
 }
 
-TextureSet TextVisual::GetTextTexture(const Vector2& size, bool hasMultipleTextColors, bool containsColorGlyph, bool styleEnabled, bool isOverlayStyle)
+TextureSet TextVisual::GetTextTexture(const Vector2& size)
 {
   // Filter mode needs to be set to linear to produce better quality while scaling.
   Sampler sampler = Sampler::New();
@@ -809,7 +811,7 @@ TextureSet TextVisual::GetTextTexture(const Vector2& size, bool hasMultipleTextC
   TextureSet textureSet = TextureSet::New();
 
   // Create RGBA texture if the text contains emojis or multiple text colors, otherwise L8 texture
-  Pixel::Format textPixelFormat = (containsColorGlyph || hasMultipleTextColors) ? Pixel::RGBA8888 : Pixel::L8;
+  Pixel::Format textPixelFormat = (mTextShaderFeatureCache.IsEnabledEmoji() || mTextShaderFeatureCache.IsEnabledMultiColor()) ? Pixel::RGBA8888 : Pixel::L8;
 
   // Check the text direction
   Toolkit::DevelText::TextDirection::Type textDirection = mController->GetTextDirection();
@@ -823,23 +825,23 @@ TextureSet TextVisual::GetTextTexture(const Vector2& size, bool hasMultipleTextC
   AddTexture(textureSet, data, sampler, textureSetIndex);
   ++textureSetIndex;
 
-  if(styleEnabled)
+  if(mTextShaderFeatureCache.IsEnabledStyle())
   {
     // Create RGBA texture for all the text styles that render in the background (without the text itself)
     PixelData styleData = mTypesetter->Render(size, textDirection, Text::Typesetter::RENDER_NO_TEXT, false, Pixel::RGBA8888);
     AddTexture(textureSet, styleData, sampler, textureSetIndex);
     ++textureSetIndex;
+  }
 
-    // TODO : We need to seperate whether use overlayStyle or not.
-    // Current text visual shader required both of them.
-
+  if(mTextShaderFeatureCache.IsEnabledOverlay())
+  {
     // Create RGBA texture for overlay styles such as underline and strikethrough (without the text itself)
     PixelData overlayStyleData = mTypesetter->Render(size, textDirection, Text::Typesetter::RENDER_OVERLAY_STYLE, false, Pixel::RGBA8888);
     AddTexture(textureSet, overlayStyleData, sampler, textureSetIndex);
     ++textureSetIndex;
   }
 
-  if(containsColorGlyph && !hasMultipleTextColors)
+  if(mTextShaderFeatureCache.IsEnabledEmoji() && !mTextShaderFeatureCache.IsEnabledMultiColor())
   {
     // Create a L8 texture as a mask to avoid color glyphs (e.g. emojis) to be affected by text color animation
     PixelData maskData = mTypesetter->Render(size, textDirection, Text::Typesetter::RENDER_MASK, false, Pixel::L8);
@@ -850,73 +852,13 @@ TextureSet TextVisual::GetTextTexture(const Vector2& size, bool hasMultipleTextC
   return textureSet;
 }
 
-Shader TextVisual::GetTextShader(VisualFactoryCache& factoryCache, bool hasMultipleTextColors, bool containsColorGlyph, bool styleEnabled)
+Shader TextVisual::GetTextShader(VisualFactoryCache& factoryCache, const TextVisualShaderFeature::FeatureBuilder& featureBuilder)
 {
-  Shader shader;
-
-  if(hasMultipleTextColors && !styleEnabled)
-  {
-    // We don't animate text color if the text contains multiple colors
-    shader = factoryCache.GetShader(VisualFactoryCache::TEXT_SHADER_MULTI_COLOR_TEXT);
-    if(!shader)
-    {
-      shader = Shader::New(SHADER_TEXT_VISUAL_SHADER_VERT, SHADER_TEXT_VISUAL_MULTI_COLOR_TEXT_SHADER_FRAG);
-      shader.RegisterProperty(PIXEL_AREA_UNIFORM_NAME, FULL_TEXTURE_RECT);
-      factoryCache.SaveShader(VisualFactoryCache::TEXT_SHADER_MULTI_COLOR_TEXT, shader);
-    }
-  }
-  else if(hasMultipleTextColors && styleEnabled)
-  {
-    // We don't animate text color if the text contains multiple colors
-    shader = factoryCache.GetShader(VisualFactoryCache::TEXT_SHADER_MULTI_COLOR_TEXT_WITH_STYLE);
-    if(!shader)
-    {
-      shader = Shader::New(SHADER_TEXT_VISUAL_SHADER_VERT, SHADER_TEXT_VISUAL_MULTI_COLOR_TEXT_WITH_STYLE_SHADER_FRAG);
-      shader.RegisterProperty(PIXEL_AREA_UNIFORM_NAME, FULL_TEXTURE_RECT);
-      factoryCache.SaveShader(VisualFactoryCache::TEXT_SHADER_MULTI_COLOR_TEXT_WITH_STYLE, shader);
-    }
-  }
-  else if(!hasMultipleTextColors && !containsColorGlyph && !styleEnabled)
-  {
-    shader = factoryCache.GetShader(VisualFactoryCache::TEXT_SHADER_SINGLE_COLOR_TEXT);
-    if(!shader)
-    {
-      shader = Shader::New(SHADER_TEXT_VISUAL_SHADER_VERT, SHADER_TEXT_VISUAL_SINGLE_COLOR_TEXT_SHADER_FRAG);
-      shader.RegisterProperty(PIXEL_AREA_UNIFORM_NAME, FULL_TEXTURE_RECT);
-      factoryCache.SaveShader(VisualFactoryCache::TEXT_SHADER_SINGLE_COLOR_TEXT, shader);
-    }
-  }
-  else if(!hasMultipleTextColors && !containsColorGlyph && styleEnabled)
-  {
-    shader = factoryCache.GetShader(VisualFactoryCache::TEXT_SHADER_SINGLE_COLOR_TEXT_WITH_STYLE);
-    if(!shader)
-    {
-      shader = Shader::New(SHADER_TEXT_VISUAL_SHADER_VERT, SHADER_TEXT_VISUAL_SINGLE_COLOR_TEXT_WITH_STYLE_SHADER_FRAG);
-      shader.RegisterProperty(PIXEL_AREA_UNIFORM_NAME, FULL_TEXTURE_RECT);
-      factoryCache.SaveShader(VisualFactoryCache::TEXT_SHADER_SINGLE_COLOR_TEXT_WITH_STYLE, shader);
-    }
-  }
-  else if(!hasMultipleTextColors && containsColorGlyph && !styleEnabled)
-  {
-    shader = factoryCache.GetShader(VisualFactoryCache::TEXT_SHADER_SINGLE_COLOR_TEXT_WITH_EMOJI);
-    if(!shader)
-    {
-      shader = Shader::New(SHADER_TEXT_VISUAL_SHADER_VERT, SHADER_TEXT_VISUAL_SINGLE_COLOR_TEXT_WITH_EMOJI_SHADER_FRAG);
-      shader.RegisterProperty(PIXEL_AREA_UNIFORM_NAME, FULL_TEXTURE_RECT);
-      factoryCache.SaveShader(VisualFactoryCache::TEXT_SHADER_SINGLE_COLOR_TEXT_WITH_EMOJI, shader);
-    }
-  }
-  else // if( !hasMultipleTextColors && containsColorGlyph && styleEnabled )
-  {
-    shader = factoryCache.GetShader(VisualFactoryCache::TEXT_SHADER_SINGLE_COLOR_TEXT_WITH_STYLE_AND_EMOJI);
-    if(!shader)
-    {
-      shader = Shader::New(SHADER_TEXT_VISUAL_SHADER_VERT, SHADER_TEXT_VISUAL_SINGLE_COLOR_TEXT_WITH_STYLE_AND_EMOJI_SHADER_FRAG);
-      shader.RegisterProperty(PIXEL_AREA_UNIFORM_NAME, FULL_TEXTURE_RECT);
-      factoryCache.SaveShader(VisualFactoryCache::TEXT_SHADER_SINGLE_COLOR_TEXT_WITH_STYLE_AND_EMOJI, shader);
-    }
-  }
+  // Cache feature builder informations.
+  mTextShaderFeatureCache = featureBuilder;
 
+  Shader shader = mTextVisualShaderFactory.GetShader(factoryCache, mTextShaderFeatureCache);
+  shader.RegisterProperty(PIXEL_AREA_UNIFORM_NAME, FULL_TEXTURE_RECT);
   return shader;
 }
 
index c79c254..05d1585 100644 (file)
@@ -27,6 +27,7 @@
 // INTERNAL INCLUDES
 #include <dali-toolkit/internal/text/rendering/text-typesetter.h>
 #include <dali-toolkit/internal/text/text-controller.h>
+#include <dali-toolkit/internal/visuals/text-visual-shader-factory.h>
 #include <dali-toolkit/internal/visuals/visual-base-impl.h>
 
 namespace Dali
@@ -72,10 +73,11 @@ public:
    * @brief Create a new text visual.
    *
    * @param[in] factoryCache A pointer pointing to the VisualFactoryCache object
+   * @param[in] shaderFactory The TextVisualShaderFactory object
    * @param[in] properties A Property::Map containing settings for this visual
    * @return A smart-pointer to the newly allocated visual.
    */
-  static TextVisualPtr New(VisualFactoryCache& factoryCache, const Property::Map& properties);
+  static TextVisualPtr New(VisualFactoryCache& factoryCache, TextVisualShaderFactory& shaderFactory, const Property::Map& properties);
 
   /**
    * @brief Converts all strings keys in property map to index keys.  Property Map can then be merged correctly.
@@ -153,8 +155,9 @@ protected:
    * @brief Constructor.
    *
    * @param[in] factoryCache The VisualFactoryCache object
+   * @param[in] shaderFactory The TextVisualShaderFactory object
    */
-  TextVisual(VisualFactoryCache& factoryCache);
+  TextVisual(VisualFactoryCache& factoryCache, TextVisualShaderFactory& shaderFactory);
 
   /**
    * @brief A reference counted object may only be deleted by calling Unreference().
@@ -274,16 +277,12 @@ private:
   PixelData ConvertToPixelData(unsigned char* buffer, int width, int height, int offsetPosition, const Pixel::Format textPixelFormat);
 
   /**
-   * @brief Create the text's texture.
+   * @brief Create the text's texture. It will use cached shader feature for text visual.
    * @param[in] info This is the information you need to create a Tiling.
    * @param[in] renderer The renderer to which the TextureSet will be added.
    * @param[in] sampler The sampler.
-   * @param[in] hasMultipleTextColors Whether the text contains multiple colors.
-   * @param[in] containsColorGlyph Whether the text contains color glyph.
-   * @param[in] styleEnabled Whether the text contains any styles (e.g. shadow, underline, etc.).
-   * @param[in] isOverlayStyle Whether the style needs to overlay on the text (e.g. strikethrough, underline, etc.).
    */
-  void CreateTextureSet(TilingInfo& info, VisualRenderer& renderer, Sampler& sampler, bool hasMultipleTextColors, bool containsColorGlyph, bool styleEnabled, bool isOverlayStyle);
+  void CreateTextureSet(TilingInfo& info, VisualRenderer& renderer, Sampler& sampler);
 
   /**
    * Create renderer of the text for rendering.
@@ -297,23 +296,17 @@ private:
   void AddRenderer(Actor& actor, const Vector2& size, bool hasMultipleTextColors, bool containsColorGlyph, bool styleEnabled, bool isOverlayStyle);
 
   /**
-   * Get the texture of the text for rendering.
+   * Get the texture of the text for rendering. It will use cached shader feature for text visual.
    * @param[in] size The texture size.
-   * @param[in] hasMultipleTextColors Whether the text contains multiple colors.
-   * @param[in] containsColorGlyph Whether the text contains color glyph.
-   * @param[in] styleEnabled Whether the text contains any styles (e.g. shadow, underline, etc.).
-   * @param[in] isOverlayStyle Whether the style needs to overlay on the text (e.g. strikethrough, underline, etc.).
    */
-  TextureSet GetTextTexture(const Vector2& size, bool hasMultipleTextColors, bool containsColorGlyph, bool styleEnabled, bool isOverlayStyle);
+  TextureSet GetTextTexture(const Vector2& size);
 
   /**
    * Get the text rendering shader.
    * @param[in] factoryCache A pointer pointing to the VisualFactoryCache object
-   * @param[in] hasMultipleTextColors Whether the text contains multiple colors.
-   * @param[in] containsColorGlyph Whether the text contains color glyph.
-   * @param[in] styleEnabled Whether the text contains any styles (e.g. shadow, underline, etc.).
+   * @param[in] featureBuilder Collection of current text shader's features. It will be cached as text visual.
    */
-  Shader GetTextShader(VisualFactoryCache& factoryCache, bool hasMultipleTextColors, bool containsColorGlyph, bool styleEnabled);
+  Shader GetTextShader(VisualFactoryCache& factoryCache, const TextVisualShaderFeature::FeatureBuilder& featureBuilder);
 
   /**
    * @brief Retrieve the TextVisual object.
@@ -328,32 +321,20 @@ private:
 private:
   typedef std::vector<Renderer> RendererContainer;
 
-  /**
-   * Used as an alternative to boolean so that it is obvious whether the text contains single or multiple text colors, and emoji and styles.
-   */
-  struct TextType
-  {
-    enum Type
-    {
-      SINGLE_COLOR_TEXT = 0, ///< The text contains single color only.
-      MULTI_COLOR_TEXT  = 1, ///< The text contains multiple colors.
-      NO_EMOJI          = 0, ///< The text contains no emoji.
-      HAS_EMOJI         = 1, ///< The text contains emoji.
-      NO_STYLES         = 0, ///< The text contains contains no styles.
-      HAS_SYLES         = 1  ///< The text contains contains styles.
-    };
-  };
-
 private:
-  Text::ControllerPtr mController;                       ///< The text's controller.
-  Text::TypesetterPtr mTypesetter;                       ///< The text's typesetter.
-  WeakHandle<Actor>   mControl;                          ///< The control where the renderer is added.
-  Constraint          mColorConstraint{};                ///< Color constraint
-  Constraint          mOpacityConstraint{};              ///< Opacity constraint
-  Property::Index     mAnimatableTextColorPropertyIndex; ///< The index of animatable text color property registered by the control.
-  Property::Index     mTextColorAnimatableIndex;         ///< The index of uTextColorAnimatable property.
-  bool                mRendererUpdateNeeded : 1;         ///< The flag to indicate whether the renderer needs to be updated.
-  RendererContainer   mRendererList;
+  Text::ControllerPtr mController; ///< The text's controller.
+  Text::TypesetterPtr mTypesetter; ///< The text's typesetter.
+
+  TextVisualShaderFactory&                mTextVisualShaderFactory; ///< The shader factory for text visual.
+  TextVisualShaderFeature::FeatureBuilder mTextShaderFeatureCache;  ///< The cached shader feature for text visual.
+
+  WeakHandle<Actor> mControl;                          ///< The control where the renderer is added.
+  Constraint        mColorConstraint{};                ///< Color constraint
+  Constraint        mOpacityConstraint{};              ///< Opacity constraint
+  Property::Index   mAnimatableTextColorPropertyIndex; ///< The index of animatable text color property registered by the control.
+  Property::Index   mTextColorAnimatableIndex;         ///< The index of uTextColorAnimatable property.
+  bool              mRendererUpdateNeeded : 1;         ///< The flag to indicate whether the renderer needs to be updated.
+  RendererContainer mRendererList;
 };
 
 } // namespace Internal
index 6d9f28c..0edda01 100644 (file)
@@ -104,12 +104,18 @@ public:
     NATIVE_IMAGE_SHADER_ROUNDED_BORDERLINE_MASKING,
     NINE_PATCH_SHADER,
     NINE_PATCH_MASK_SHADER,
-    TEXT_SHADER_MULTI_COLOR_TEXT,
-    TEXT_SHADER_MULTI_COLOR_TEXT_WITH_STYLE,
     TEXT_SHADER_SINGLE_COLOR_TEXT,
     TEXT_SHADER_SINGLE_COLOR_TEXT_WITH_STYLE,
+    TEXT_SHADER_SINGLE_COLOR_TEXT_WITH_OVERLAY,
+    TEXT_SHADER_SINGLE_COLOR_TEXT_WITH_STYLE_AND_OVERLAY,
     TEXT_SHADER_SINGLE_COLOR_TEXT_WITH_EMOJI,
     TEXT_SHADER_SINGLE_COLOR_TEXT_WITH_STYLE_AND_EMOJI,
+    TEXT_SHADER_SINGLE_COLOR_TEXT_WITH_OVERLAY_AND_EMOJI,
+    TEXT_SHADER_SINGLE_COLOR_TEXT_WITH_STYLE_AND_OVERLAY_AND_EMOJI,
+    TEXT_SHADER_MULTI_COLOR_TEXT,
+    TEXT_SHADER_MULTI_COLOR_TEXT_WITH_STYLE,
+    TEXT_SHADER_MULTI_COLOR_TEXT_WITH_OVERLAY,
+    TEXT_SHADER_MULTI_COLOR_TEXT_WITH_STYLE_AND_OVERLAY,
     ANIMATED_GRADIENT_SHADER_LINEAR_BOUNDING_REFLECT,
     ANIMATED_GRADIENT_SHADER_LINEAR_BOUNDING_REPEAT,
     ANIMATED_GRADIENT_SHADER_LINEAR_BOUNDING_CLAMP,
index a4b0a0a..57290a1 100644 (file)
@@ -40,6 +40,7 @@
 #include <dali-toolkit/internal/visuals/npatch/npatch-visual.h>
 #include <dali-toolkit/internal/visuals/primitive/primitive-visual.h>
 #include <dali-toolkit/internal/visuals/svg/svg-visual.h>
+#include <dali-toolkit/internal/visuals/text-visual-shader-factory.h>
 #include <dali-toolkit/internal/visuals/text/text-visual.h>
 #include <dali-toolkit/internal/visuals/visual-factory-cache.h>
 #include <dali-toolkit/internal/visuals/visual-string-constants.h>
@@ -77,6 +78,7 @@ const char* const BROKEN_IMAGE_FILE_NAME = "broken.png"; ///< The file name of t
 VisualFactory::VisualFactory(bool debugEnabled)
 : mFactoryCache(),
   mImageVisualShaderFactory(),
+  mTextVisualShaderFactory(),
   mSlotDelegate(this),
   mDebugEnabled(debugEnabled),
   mPreMultiplyOnLoad(true)
@@ -207,7 +209,7 @@ Toolkit::Visual::Base VisualFactory::CreateVisual(const Property::Map& propertyM
 
     case Toolkit::Visual::TEXT:
     {
-      visualPtr = TextVisual::New(GetFactoryCache(), propertyMap);
+      visualPtr = TextVisual::New(GetFactoryCache(), GetTextVisualShaderFactory(), propertyMap);
       break;
     }
 
@@ -426,6 +428,15 @@ ImageVisualShaderFactory& VisualFactory::GetImageVisualShaderFactory()
   return *mImageVisualShaderFactory;
 }
 
+TextVisualShaderFactory& VisualFactory::GetTextVisualShaderFactory()
+{
+  if(!mTextVisualShaderFactory)
+  {
+    mTextVisualShaderFactory = std::unique_ptr<TextVisualShaderFactory>(new TextVisualShaderFactory());
+  }
+  return *mTextVisualShaderFactory;
+}
+
 } // namespace Internal
 
 } // namespace Toolkit
index a5ecda8..616b8d0 100644 (file)
@@ -2,7 +2,7 @@
 #define DALI_TOOLKIT_VISUAL_FACTORY_IMPL_H
 
 /*
- * Copyright (c) 2021 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2022 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.
@@ -35,6 +35,7 @@ namespace Internal
 {
 class VisualFactoryCache;
 class ImageVisualShaderFactory;
+class TextVisualShaderFactory;
 
 /**
  * @copydoc Toolkit::VisualFactory
@@ -112,6 +113,11 @@ private:
    */
   ImageVisualShaderFactory& GetImageVisualShaderFactory();
 
+  /**
+   * Get the text visual shader factory, creating it if necessary.
+   */
+  TextVisualShaderFactory& GetTextVisualShaderFactory();
+
   VisualFactory(const VisualFactory&) = delete;
 
   VisualFactory& operator=(const VisualFactory& rhs) = delete;
@@ -119,6 +125,7 @@ private:
 private:
   std::unique_ptr<VisualFactoryCache>       mFactoryCache;
   std::unique_ptr<ImageVisualShaderFactory> mImageVisualShaderFactory;
+  std::unique_ptr<TextVisualShaderFactory>  mTextVisualShaderFactory;
   SlotDelegate<VisualFactory>               mSlotDelegate;
   bool                                      mDebugEnabled : 1;
   bool                                      mPreMultiplyOnLoad : 1; ///< Local store for this flag