const char* const PROPERTY_NAME_REMOVE_FRONT_INSET = "removeFrontInset";
const char* const PROPERTY_NAME_REMOVE_BACK_INSET = "removeBackInset";
+const char* const PROPERTY_NAME_REMOVE_CUTOUT = "cutout";
const std::string DEFAULT_FONT_DIR("/resources/fonts");
const unsigned int EMOJI_FONT_SIZE = 3840u; // 60 * 64
DALI_TEST_CHECK(label.GetPropertyIndex(PROPERTY_NAME_ANCHOR_CLICKED_COLOR) == DevelTextLabel::Property::ANCHOR_CLICKED_COLOR);
DALI_TEST_CHECK(label.GetPropertyIndex(PROPERTY_NAME_REMOVE_FRONT_INSET) == DevelTextLabel::Property::REMOVE_FRONT_INSET);
DALI_TEST_CHECK(label.GetPropertyIndex(PROPERTY_NAME_REMOVE_BACK_INSET) == DevelTextLabel::Property::REMOVE_BACK_INSET);
+ DALI_TEST_CHECK(label.GetPropertyIndex(PROPERTY_NAME_REMOVE_CUTOUT) == DevelTextLabel::Property::CUTOUT);
END_TEST;
}
application.SendNotification();
application.Render();
+ // Check cutout Property
+ DALI_TEST_CHECK(!label.GetProperty<bool>(DevelTextLabel::Property::CUTOUT));
+ label.SetProperty(DevelTextLabel::Property::CUTOUT, true);
+ DALI_TEST_CHECK(label.GetProperty<bool>(DevelTextLabel::Property::CUTOUT));
+
+ application.SendNotification();
+ application.Render();
+
END_TEST;
}
DALI_TEST_EQUALS(drawTrace.FindMethod("DrawArrays"), false, TEST_LOCATION); // Rendering should be skipped
+ label.SetProperty(DevelTextLabel::Property::CUTOUT, true);
+
+ drawTrace.Reset();
+
+ application.SendNotification();
+ application.Render();
+
+ DALI_TEST_EQUALS(drawTrace.FindMethod("DrawArrays"), true, TEST_LOCATION); // When cutout is enabled, should not be skipped
+
+ label.SetProperty(DevelTextLabel::Property::CUTOUT, false);
label.SetProperty(TextLabel::Property::TEXT_COLOR, Color::RED);
drawTrace.Reset();
* @details Name "removeBackInset", type Property::BOOLEAN.
*/
REMOVE_BACK_INSET,
+
+ /**
+ * @brief Whether to make the elements transparent, such as background or outline behind the text.
+ * @details Name "cutout", type Property::BOOLEAN.
+ */
+ CUTOUT,
};
} // namespace Property
#include <dali-toolkit/public-api/align-enumerations.h>
#include <dali-toolkit/public-api/visuals/text-visual-properties.h>
#include <dali-toolkit/public-api/visuals/visual-properties.h>
+#include <dali-toolkit/public-api/visuals/color-visual-properties.h>
// DEVEL INCLUDES
#include <dali-toolkit/devel-api/controls/text-controls/text-label-devel.h>
DALI_DEVEL_PROPERTY_REGISTRATION(Toolkit, TextLabel, "anchorClickedColor", VECTOR4, ANCHOR_CLICKED_COLOR )
DALI_DEVEL_PROPERTY_REGISTRATION(Toolkit, TextLabel, "removeFrontInset", BOOLEAN, REMOVE_FRONT_INSET )
DALI_DEVEL_PROPERTY_REGISTRATION(Toolkit, TextLabel, "removeBackInset", BOOLEAN, REMOVE_BACK_INSET )
+DALI_DEVEL_PROPERTY_REGISTRATION(Toolkit, TextLabel, "cutout", BOOLEAN, CUTOUT )
DALI_ANIMATABLE_PROPERTY_REGISTRATION_WITH_DEFAULT(Toolkit, TextLabel, "textColor", Color::BLACK, TEXT_COLOR )
DALI_ANIMATABLE_PROPERTY_COMPONENT_REGISTRATION(Toolkit, TextLabel, "textColorRed", TEXT_COLOR_RED, TEXT_COLOR, 0)
impl.mController->SetRemoveBackInset(remove);
break;
}
+ case Toolkit::DevelTextLabel::Property::CUTOUT:
+ {
+ const bool cutout = value.Get<bool>();
+
+ impl.mController->SetTextCutout(cutout);
+
+ // Property doesn't affect the layout, only Visual must be updated
+ TextVisual::EnableRendererUpdate(impl.mVisual);
+
+ // No need to trigger full re-layout. Instead call UpdateRenderer() directly
+ TextVisual::UpdateRenderer(impl.mVisual);
+ break;
+ }
}
// Request relayout when text update is needed. It's necessary to call it
value = impl.mController->IsRemoveBackInset();
break;
}
+ case Toolkit::DevelTextLabel::Property::CUTOUT:
+ {
+ value = impl.mController->IsTextCutout();
+ break;
+ }
}
}
CommonTextUtils::SynchronizeTextAnchorsInParent(Self(), mController, mAnchorActors);
break;
}
+ case Toolkit::Control::Property::BACKGROUND:
+ {
+ const Vector4 backgroundColor = propertyValue.Get<Vector4>();
+
+ if(mController->IsTextCutout())
+ {
+ DevelControl::EnableVisual(*this, Toolkit::Control::Property::BACKGROUND, false);
+ mController->SetBackgroundWithCutoutEnabled(true);
+ mController->SetBackgroundColorWithCutout(backgroundColor);
+ }
+
+ break;
+ }
+ case Toolkit::DevelTextLabel::Property::CUTOUT:
+ {
+ const bool cutoutEnabled = propertyValue.Get<bool>();
+
+ if(cutoutEnabled)
+ {
+ Vector4 backgroundColor = Vector4::ZERO;
+
+ const Property::Map backgroundMap = Self().GetProperty(Toolkit::Control::Property::BACKGROUND).Get<Property::Map>();
+ Property::Value* backgroundValue = backgroundMap.Find(ColorVisual::Property::MIX_COLOR);
+ if(backgroundValue)
+ {
+ backgroundColor = backgroundValue->Get<Vector4>();
+ }
+
+ DevelControl::EnableVisual(*this, Toolkit::Control::Property::BACKGROUND, false);
+ mController->SetBackgroundWithCutoutEnabled(true);
+ mController->SetBackgroundColorWithCutout(backgroundColor);
+ }
+ else
+ {
+ DevelControl::EnableVisual(*this, Toolkit::Control::Property::BACKGROUND, true);
+
+ Property::Map backgroundMapSet;
+ mController->SetBackgroundWithCutoutEnabled(false);
+ }
+
+ TextVisual::SetRequireRender(mVisual, cutoutEnabled);
+ }
default:
{
Control::OnPropertySet(index, propertyValue); // up call to control for non-handled properties
mTextFitArrayEnabled(false),
mIsLayoutDirectionChanged(false),
mIsUserInteractionEnabled(true),
- mProcessorRegistered(false)
+ mProcessorRegistered(false),
+ mTextCutout(false)
{
mModel = Model::New();
bool mIsLayoutDirectionChanged : 1; ///< Whether the layout has changed.
bool mIsUserInteractionEnabled : 1; ///< Whether the user interaction is enabled.
bool mProcessorRegistered : 1; ///< Whether the text controller registered into processor or not.
+ bool mTextCutout : 1; ///< Whether the text cutout enabled.
private:
friend ControllerImplEventHandler;
mImpl->mModel->mRemoveBackInset = remove;
}
+bool Controller::IsTextCutout() const
+{
+ return mImpl->mTextCutout;
+}
+
+void Controller::SetTextCutout(bool cutout)
+{
+ if(cutout != mImpl->mTextCutout)
+ {
+ mImpl->mModel->mVisualModel->SetCutoutEnabled(cutout);
+ mImpl->mTextCutout = cutout;
+ mImpl->RequestRelayout();
+ }
+}
+
void Controller::ChangedLayoutDirection()
{
mImpl->mIsLayoutDirectionChanged = true;
mImpl->mModel->mVisualTransformOffset = offset;
}
+void Controller::SetBackgroundWithCutoutEnabled(bool cutout)
+{
+ mImpl->mModel->mVisualModel->SetBackgroundWithCutoutEnabled(cutout);
+ RequestRelayout();
+}
+
+bool Controller::IsBackgroundWithCutoutEnabled() const
+{
+ return mImpl->mModel->mVisualModel->IsBackgroundWithCutoutEnabled();
+}
+
+void Controller::SetBackgroundColorWithCutout(const Vector4& color)
+{
+ mImpl->mModel->mVisualModel->SetBackgroundColorWithCutout(color);
+ mImpl->RequestRelayout();
+}
+
+const Vector4 Controller::GetBackgroundColorWithCutout() const
+{
+ return mImpl->mModel->mVisualModel->GetBackgroundColorWithCutout();
+}
+
Controller::UpdateTextType Controller::Relayout(const Size& size, Dali::LayoutDirection::Type layoutDirection)
{
return Relayouter::Relayout(*this, size, layoutDirection);
*/
void SetVisualTransformOffset(Vector2 offset);
+ /**
+ * @brief Sets whether background color with cutout is enabled.
+ *
+ * @param[in] enable True if enabled.
+ */
+ void SetBackgroundWithCutoutEnabled(bool enable);
+
+ /**
+ * @brief Whether background color with cutout is enabled.
+ *
+ * @return True if enabled.
+ */
+ bool IsBackgroundWithCutoutEnabled() const;
+
+ /**
+ * @brief Sets whether background color with cutout.
+ *
+ * @param[in] color The color to set.
+ */
+ void SetBackgroundColorWithCutout(const Vector4& color);
+
+ /**
+ * @brief Retrieves background color with cutout.
+ *
+ * @return The color.
+ */
+ const Vector4 GetBackgroundColorWithCutout() const;
+
public: // Queries & retrieves.
/**
* @brief Return the layout engine.
void SetRemoveBackInset(bool remove);
/**
+ * @brief Retrieves cutout value to model
+ * @return The value of cutout for the text
+ */
+ bool IsTextCutout() const;
+
+ /**
+ * @brief Sets cutout value to model
+ * @param[in] cutout The value of cutout for the text
+ */
+ void SetTextCutout(bool cutout);
+
+ /**
* @brief Sets SetMatchLayoutDirection value to model
* @param[in] match The value of matchLayoutDirection for the text
*/
// EXTERNAL INCLUDES
#include <dali/devel-api/text-abstraction/font-client.h>
+#include <dali/integration-api/debug.h>
#include <dali/integration-api/trace.h>
#include <dali/public-api/common/constants.h>
#include <dali/public-api/math/math-utils.h>
const Vector2* const positionBuffer = model->GetLayout();
const Vector4* const backgroundColorsBuffer = model->GetBackgroundColors();
const ColorIndex* const backgroundColorIndicesBuffer = model->GetBackgroundColorIndices();
+ const bool removeFrontInset = model->IsRemoveFrontInset();
+ const bool removeBackInset = model->IsRemoveBackInset();
const DevelText::VerticalLineAlignment::Type verLineAlign = model->GetVerticalLineAlignment();
}
// Calculate the positions of leftmost and rightmost glyphs in the current line
- if((position->x < left) || (backgroundColorIndex != prevBackgroundColorIndex))
+ if(removeFrontInset)
{
- left = position->x - glyphInfo->xBearing;
+ if((position->x < left) || (backgroundColorIndex != prevBackgroundColorIndex))
+ {
+ left = position->x;
+ }
+ }
+ else
+ {
+ const float originPositionLeft = position->x - glyphInfo->xBearing;
+ if((originPositionLeft < left) || (backgroundColorIndex != prevBackgroundColorIndex))
+ {
+ left = originPositionLeft;
+ }
}
- if(position->x + glyphInfo->width > right)
+ if(removeBackInset)
{
- right = position->x - glyphInfo->xBearing + glyphInfo->advance;
+ if(position->x + glyphInfo->width > right)
+ {
+ right = position->x - position->x + glyphInfo->width;
+ }
+ }
+ else
+ {
+ const float originPositionRight = position->x - glyphInfo->xBearing + glyphInfo->advance;
+ if(originPositionRight > right)
+ {
+ right = originPositionRight;
+ }
}
prevBackgroundColorIndex = backgroundColorIndex;
PixelData Typesetter::Render(const Vector2& size, Toolkit::DevelText::TextDirection::Type textDirection, RenderBehaviour behaviour, bool ignoreHorizontalAlignment, Pixel::Format pixelFormat)
{
+ Devel::PixelBuffer result = RenderWithPixelBuffer(size, textDirection, behaviour, ignoreHorizontalAlignment, pixelFormat);
+ PixelData pixelData = Devel::PixelBuffer::Convert(result);
+
+ return pixelData;
+}
+
+PixelData Typesetter::RenderWithCutout(const Vector2& size, Toolkit::DevelText::TextDirection::Type textDirection, Devel::PixelBuffer mask, RenderBehaviour behaviour, bool ignoreHorizontalAlignment, Pixel::Format pixelFormat, float originAlpha)
+{
+ Devel::PixelBuffer result = RenderWithPixelBuffer(size, textDirection, behaviour, ignoreHorizontalAlignment, pixelFormat);
+ SetMaskForImageBuffer(mask, result, size.width, size.height, originAlpha);
+
+ PixelData pixelData = Devel::PixelBuffer::Convert(result);
+
+ return pixelData;
+}
+
+Devel::PixelBuffer Typesetter::RenderWithPixelBuffer(const Vector2& size, Toolkit::DevelText::TextDirection::Type textDirection, RenderBehaviour behaviour, bool ignoreHorizontalAlignment, Pixel::Format pixelFormat)
+{
DALI_TRACE_SCOPE(gTraceFilter, "DALI_TEXT_RENDERING_TYPESETTER");
// @todo. This initial implementation for a TextLabel has only one visible page.
// Retrieves the layout size.
const Size& layoutSize = mModel->GetLayoutSize();
-
const int32_t outlineWidth = static_cast<int32_t>(mModel->GetOutlineWidth());
// Set the offset for the horizontal alignment according to the text direction and outline width.
int32_t penX = 0;
-
switch(mModel->GetHorizontalAlignment())
{
case HorizontalAlignment::BEGIN:
// Set the offset for the vertical alignment.
int32_t penY = 0u;
-
switch(mModel->GetVerticalAlignment())
{
case VerticalAlignment::TOP:
CombineImageBuffer(imageBuffer, backgroundImageBuffer, bufferWidth, bufferHeight, true);
}
+ // Generate the background_with_mask if enabled
+ const bool backgroundWithCutoutEnabled = mModel->IsBackgroundWithCutoutEnabled();
+ if((backgroundWithCutoutEnabled) && RENDER_OVERLAY_STYLE != behaviour)
+ {
+ Devel::PixelBuffer backgroundImageBuffer;
+
+ backgroundImageBuffer = CreateFullBackgroundBuffer(bufferWidth, bufferHeight, mModel->GetBackgroundColorWithCutout());
+
+ // Combine the two buffers
+ CombineImageBuffer(imageBuffer, backgroundImageBuffer, bufferWidth, bufferHeight, true);
+ }
+
if(RENDER_OVERLAY_STYLE == behaviour)
{
if(mModel->IsUnderlineEnabled())
}
}
- // Create the final PixelData for the combined image buffer
- PixelData pixelData = Devel::PixelBuffer::Convert(imageBuffer);
+ return imageBuffer;
+}
- return pixelData;
+Devel::PixelBuffer Typesetter::CreateFullBackgroundBuffer(const uint32_t bufferWidth, const uint32_t bufferHeight, const Vector4& backgroundColor)
+{
+ const uint32_t bufferSizeInt = bufferWidth * bufferHeight;
+ uint8_t backgroundColorAlpha = static_cast<uint8_t>(backgroundColor.a * 255.f);
+
+ Devel::PixelBuffer buffer = Devel::PixelBuffer::New(bufferWidth, bufferHeight, Pixel::RGBA8888);
+
+ uint32_t* bitmapBuffer = reinterpret_cast<uint32_t*>(buffer.GetBuffer());
+
+ uint32_t packedBackgroundColor = 0u;
+ uint8_t* packedBackgroundColorBuffer = reinterpret_cast<uint8_t*>(&packedBackgroundColor);
+
+ // Write the color to the pixel buffer
+ *(packedBackgroundColorBuffer + 3u) = backgroundColorAlpha;
+ *(packedBackgroundColorBuffer + 2u) = static_cast<uint8_t>(backgroundColor.b * backgroundColorAlpha);
+ *(packedBackgroundColorBuffer + 1u) = static_cast<uint8_t>(backgroundColor.g * backgroundColorAlpha);
+ *(packedBackgroundColorBuffer) = static_cast<uint8_t>(backgroundColor.r * backgroundColorAlpha);
+
+ std::fill(bitmapBuffer, bitmapBuffer + bufferSizeInt, packedBackgroundColor);
+
+ return buffer;
}
Devel::PixelBuffer Typesetter::CreateImageBuffer(const uint32_t bufferWidth, const uint32_t bufferHeight, const Typesetter::Style style, const bool ignoreHorizontalAlignment, const Pixel::Format pixelFormat, const int32_t horizontalOffset, const int32_t verticalOffset, const GlyphIndex fromGlyphIndex, const GlyphIndex toGlyphIndex)
const GlyphInfo* __restrict__ hyphens = mModel->GetHyphens();
const Length* __restrict__ hyphenIndices = mModel->GetHyphenIndices();
const Length hyphensCount = mModel->GetHyphensCount();
+ const bool removeFrontInset = mModel->IsRemoveFrontInset();
+ const bool removeBackInset = mModel->IsRemoveBackInset();
+ const bool cutoutEnabled = mModel->IsCutoutEnabled();
// Elided text info. Indices according to elided text and Ellipsis position.
const auto startIndexOfGlyphs = mModel->GetStartIndexOfElidedGlyphs();
}
// Calculate the positions of leftmost and rightmost glyphs in the current line
- if(position.x < lineExtentLeft)
+ if(removeFrontInset)
+ {
+ if(position.x < lineExtentLeft)
+ {
+ lineExtentLeft = position.x;
+ }
+ }
+ else
{
- lineExtentLeft = position.x;
+ const float originPositionLeft = position.x - glyphInfo->xBearing;
+ if(originPositionLeft < lineExtentLeft)
+ {
+ lineExtentLeft = originPositionLeft;
+ }
}
- if(position.x + glyphInfo->width > lineExtentRight)
+ if(removeBackInset)
{
- lineExtentRight = position.x + glyphInfo->width;
+ if(position.x + glyphInfo->width > lineExtentRight)
+ {
+ lineExtentRight = position.x + glyphInfo->width;
+ }
+ }
+ else
+ {
+ const float originPositionRight = position.x - glyphInfo->xBearing + glyphInfo->advance;
+ if(originPositionRight > lineExtentRight)
+ {
+ lineExtentRight = originPositionRight;
+ }
}
// Retrieves the glyph's color.
color = (useDefaultColor || (0u == colorIndex)) ? defaultColor : *(colorsBuffer + (colorIndex - 1u));
}
+ if(style == Typesetter::STYLE_NONE && cutoutEnabled)
+ {
+ // Temporarily adjust the transparency to 1.f
+ color.a = 1.f;
+ }
+
// Premultiply alpha
color.r *= color.a;
color.g *= color.a;
return topPixelBuffer;
}
+void Typesetter::SetMaskForImageBuffer(Devel::PixelBuffer& __restrict__ topPixelBuffer, Devel::PixelBuffer& __restrict__ bottomPixelBuffer, const uint32_t bufferWidth, const uint32_t bufferHeight, float originAlpha)
+{
+ // Assume that we always combine two RGBA images
+ // Jump with 4bytes for optimize runtime.
+ uint32_t* topBuffer = reinterpret_cast<uint32_t*>(topPixelBuffer.GetBuffer());
+ uint32_t* bottomBuffer = reinterpret_cast<uint32_t*>(bottomPixelBuffer.GetBuffer());
+
+ if(topBuffer == NULL || bottomBuffer == NULL)
+ {
+ // Nothing to do if one of both buffers are empty.
+ return;
+ }
+
+ const uint32_t bufferSizeInt = bufferWidth * bufferHeight;
+
+ for(uint32_t pixelIndex = 0; pixelIndex < bufferSizeInt; ++pixelIndex)
+ {
+ uint32_t topBufferColor = *(topBuffer);
+ uint32_t bottomBufferColor = *(bottomBuffer);
+ uint8_t* __restrict__ topBufferColorBuffer = reinterpret_cast<uint8_t*>(&topBufferColor);
+ uint8_t* __restrict__ bottomBufferColorBuffer = reinterpret_cast<uint8_t*>(&bottomBufferColor);
+
+ uint8_t topAlpha = topBufferColorBuffer[3];
+ uint8_t bottomAlpha = 255 - topAlpha;
+
+ float tempTop[4], tempBottom[4];
+
+ // Return the transparency of the text to original.
+ tempTop[0] = static_cast<float>(topBufferColorBuffer[0]) * originAlpha;
+ tempTop[1] = static_cast<float>(topBufferColorBuffer[1]) * originAlpha;
+ tempTop[2] = static_cast<float>(topBufferColorBuffer[2]) * originAlpha;
+ tempTop[3] = static_cast<float>(topBufferColorBuffer[3]) * originAlpha;
+
+ // Manual blending.
+ tempBottom[0] = static_cast<float>(bottomBufferColorBuffer[0]) * static_cast<float>(bottomAlpha) / 255.f;
+ tempBottom[1] = static_cast<float>(bottomBufferColorBuffer[1]) * static_cast<float>(bottomAlpha) / 255.f;
+ tempBottom[2] = static_cast<float>(bottomBufferColorBuffer[2]) * static_cast<float>(bottomAlpha) / 255.f;
+ tempBottom[3] = static_cast<float>(bottomBufferColorBuffer[3]) * static_cast<float>(bottomAlpha) / 255.f;
+
+ bottomBufferColorBuffer[0] = static_cast<uint8_t>(std::min(255u, static_cast<uint32_t>(tempBottom[0] + tempTop[0])));
+ bottomBufferColorBuffer[1] = static_cast<uint8_t>(std::min(255u, static_cast<uint32_t>(tempBottom[1] + tempTop[1])));
+ bottomBufferColorBuffer[2] = static_cast<uint8_t>(std::min(255u, static_cast<uint32_t>(tempBottom[2] + tempTop[2])));
+ bottomBufferColorBuffer[3] = static_cast<uint8_t>(std::min(255u, static_cast<uint32_t>(tempBottom[3] + tempTop[3])));
+
+ *(bottomBuffer) = bottomBufferColor;
+
+ // Increase each buffer's pointer.
+ ++topBuffer;
+ ++bottomBuffer;
+ }
+}
+
Typesetter::Typesetter(const ModelInterface* const model)
: mModel(new ViewModel(model))
{
*/
PixelData Render(const Vector2& size, Toolkit::DevelText::TextDirection::Type textDirection, RenderBehaviour behaviour = RENDER_TEXT_AND_STYLES, bool ignoreHorizontalAlignment = false, Pixel::Format pixelFormat = Pixel::RGBA8888);
+ /**
+ * @brief After the Render, use the pixel information of the given cutoutBuffer to make the part where the pixel is drawn transparent.
+ *
+ * @param[in] size The renderer size.
+ * @param[in] textDirection The direction of the text.
+ * @param[in] cutoutBuffer The buffer to use pixel information to cutout.
+ * @param[in] behaviour The behaviour of how to render the text (i.e. whether to render the text only or the styles only or both).
+ * @param[in] ignoreHorizontalAlignment Whether to ignore the horizontal alignment (i.e. always render as if HORIZONTAL_ALIGN_BEGIN).
+ * @param[in] pixelFormat The format of the pixel in the image that the text is rendered as (i.e. either Pixel::BGRA8888 or Pixel::L8).
+ * @param[in] originAlpha The original alpha of text.
+ *
+ * @return A pixel data with the text rendered.
+ */
+ PixelData RenderWithCutout(const Vector2& size, Toolkit::DevelText::TextDirection::Type textDirection, Devel::PixelBuffer cutoutBuffer, RenderBehaviour behaviour = RENDER_TEXT_AND_STYLES, bool ignoreHorizontalAlignment = false, Pixel::Format pixelFormat = Pixel::RGBA8888, float originAlpha = 1.f);
+
+ /**
+ * @brief Renders the text, return as Devel::PixelBuffer.
+ *
+ * This function is used to obtain the PixelBuffer required for cutout.
+ *
+ * @param[in] size The renderer size.
+ * @param[in] textDirection The direction of the text.
+ * @param[in] cutoutBuffer The buffer to use pixel information to cutout.
+ * @param[in] behaviour The behaviour of how to render the text (i.e. whether to render the text only or the styles only or both).
+ * @param[in] ignoreHorizontalAlignment Whether to ignore the horizontal alignment (i.e. always render as if HORIZONTAL_ALIGN_BEGIN).
+ * @param[in] pixelFormat The format of the pixel in the image that the text is rendered as (i.e. either Pixel::BGRA8888 or Pixel::L8).
+ *
+ * @return A pixel data with the text rendered.
+ */
+ Devel::PixelBuffer RenderWithPixelBuffer(const Vector2& size, Toolkit::DevelText::TextDirection::Type textDirection, RenderBehaviour behaviour = RENDER_TEXT_AND_STYLES, bool ignoreHorizontalAlignment = false, Pixel::Format pixelFormat = Pixel::RGBA8888);
+
+ /**
+ * @brief Create & draw the image buffer of single background color.
+ *
+ * @param[in] bufferWidth The width of the image buffer.
+ * @param[in] bufferHeight The height of the image buffer.
+ * @param[in] backgroundColor The backgroundColor of image buffer.
+ *
+ * @return An image buffer with the text.
+ */
+ Devel::PixelBuffer CreateFullBackgroundBuffer(const uint32_t bufferWidth, const uint32_t bufferHeight, const Vector4& backgroundColor);
+
+ /**
+ * @brief Set Mask for two pixel buffer.
+ *
+ * The alpha value of bottomPixelBuffer is decreased as the alpha value of topPixelBuffer is higher.
+ *
+ * @param[in, out] topPixelBuffer The top layer buffer.
+ * @param[in, out] bottomPixelBuffer The bottom layer buffer.
+ * @param[in] bufferWidth The width of the image buffer.
+ * @param[in] bufferHeight The height of the image buffer.
+ * @param[in] originAlpha The original alpha value of the text.
+ */
+ void SetMaskForImageBuffer(Devel::PixelBuffer& __restrict__ topPixelBuffer, Devel::PixelBuffer& __restrict__ bottomPixelBuffer, const uint32_t bufferWidth, const uint32_t bufferHeight, float originAlpha);
+
private:
/**
* @brief Private constructor.
return mModel->GetFontDescriptionRuns();
}
+bool ViewModel::IsRemoveFrontInset() const
+{
+ return mModel->IsRemoveFrontInset();
+}
+
+bool ViewModel::IsRemoveBackInset() const
+{
+ return mModel->IsRemoveBackInset();
+}
+
+bool ViewModel::IsCutoutEnabled() const
+{
+ return mModel->IsCutoutEnabled();
+}
+
+const bool ViewModel::IsBackgroundWithCutoutEnabled() const
+{
+ return mModel->IsBackgroundWithCutoutEnabled();
+}
+
+const Vector4& ViewModel::GetBackgroundColorWithCutout() const
+{
+ return mModel->GetBackgroundColorWithCutout();
+}
+
} // namespace Text
} // namespace Toolkit
*/
const Vector<FontDescriptionRun>& GetFontDescriptionRuns() const override;
+ /**
+ * @copydoc ModelInterface::IsRemoveFrontInset()
+ */
+ bool IsRemoveFrontInset() const override;
+
+ /**
+ * @copydoc ModelInterface::IsRemoveBackInset()
+ */
+ bool IsRemoveBackInset() const override;
+
+ /**
+ * @copydoc ModelInterface::IsCutoutEnabled()
+ */
+ bool IsCutoutEnabled() const override;
+
+ /**
+ * @copydoc ModelInterface::IsBackgroundWithCutoutEnabled()
+ */
+ const bool IsBackgroundWithCutoutEnabled() const override;
+
+ /**
+ * @copydoc ModelInterface::GetBackgroundColorWithCutout()
+ */
+ const Vector4& GetBackgroundColorWithCutout() const override;
+
private:
const ModelInterface* const mModel; ///< Pointer to the text's model.
Vector<GlyphInfo> mElidedGlyphs; ///< Stores the glyphs of the elided text.
* @return The reference for font description runs.
*/
virtual const Vector<FontDescriptionRun>& GetFontDescriptionRuns() const = 0;
+
+ /**
+ * @brief Retrieves the remove front inset is enabled or not.
+ *
+ * @return boolean if it is enabled.
+ */
+ virtual bool IsRemoveFrontInset() const = 0;
+
+ /**
+ * @brief Retrieves the remove back inset is enabled or not.
+ *
+ * @return boolean if it is enabled.
+ */
+ virtual bool IsRemoveBackInset() const = 0;
+
+ /**
+ * @brief Retrieves the cutout is enabled or not.
+ *
+ * @return boolean if it is enabled.
+ */
+ virtual bool IsCutoutEnabled() const = 0;
+
+ /**
+ * @brief Retrieves the background with cutout is enabled or not.
+ *
+ * @return boolean if it is enabled.
+ */
+ virtual const bool IsBackgroundWithCutoutEnabled() const = 0;
+
+ /**
+ * @brief Retrieves the color of the background with cutout.
+ *
+ * @return The color of the background with cutout.
+ */
+ virtual const Vector4& GetBackgroundColorWithCutout() const = 0;
};
} // namespace Text
return mLogicalModel->mFontDescriptionRuns;
}
+bool Model::IsRemoveFrontInset() const
+{
+ return mRemoveFrontInset;
+}
+
+bool Model::IsRemoveBackInset() const
+{
+ return mRemoveBackInset;
+}
+
+bool Model::IsCutoutEnabled() const
+{
+ return mVisualModel->IsCutoutEnabled();
+}
+
+const bool Model::IsBackgroundWithCutoutEnabled() const
+{
+ return mVisualModel->IsBackgroundWithCutoutEnabled();
+}
+
+const Vector4& Model::GetBackgroundColorWithCutout() const
+{
+ return mVisualModel->GetBackgroundColorWithCutout();
+}
+
Model::Model()
: mLogicalModel(),
mVisualModel(),
*/
const Vector<FontDescriptionRun>& GetFontDescriptionRuns() const override;
+ /**
+ * @copydoc ModelInterface::IsRemoveFrontInset()
+ */
+ bool IsRemoveFrontInset() const override;
+
+ /**
+ * @copydoc ModelInterface::IsRemoveBackInset()
+ */
+ bool IsRemoveBackInset() const override;
+
+ /**
+ * @copydoc ModelInterface::IsCutoutEnabled()
+ */
+ bool IsCutoutEnabled() const override;
+
+ /**
+ * @copydoc ModelInterface::IsBackgroundWithCutoutEnabled()
+ */
+ const bool IsBackgroundWithCutoutEnabled() const override;
+
+ /**
+ * @copydoc ModelInterface::GetBackgroundColorWithCutout()
+ */
+ const Vector4& GetBackgroundColorWithCutout() const override;
+
private: // Private contructors & copy operator.
/**
* @brief Private constructor.
* @return GetGlyphsToCharacters.
*/
virtual const Vector<CharacterIndex>& GetGlyphsToCharacters() const = 0;
+
+ /**
+ * @brief Returns whether cutout is enabled or not.
+ *
+ * @return The cutout state.
+ */
+ virtual bool IsCutoutEnabled() const = 0;
};
} // namespace Text
return mImpl->mVisualModel->GetGlyphsToCharacters();
}
+bool View::IsCutoutEnabled() const
+{
+ if(mImpl->mVisualModel)
+ {
+ return mImpl->mVisualModel->IsCutoutEnabled();
+ }
+ return false;
+}
+
} // namespace Dali::Toolkit::Text
*/
const Vector<CharacterIndex>& GetGlyphsToCharacters() const override;
+ /**
+ * @copydoc Dali::Toolkit::Text::ViewInterface::IsCutoutEnabled()
+ */
+ bool IsCutoutEnabled() const override;
+
private:
// Undefined
View(const View& handle);
return mGlyphsToCharacters;
}
+void VisualModel::SetCutoutEnabled(bool enable)
+{
+ mCutoutEnabled = enable;
+}
+
+bool VisualModel::IsCutoutEnabled() const
+{
+ return mCutoutEnabled;
+}
+
+void VisualModel::SetBackgroundWithCutoutEnabled(bool enable)
+{
+ mBackgroundWithCutoutEnabled = enable;
+}
+
+bool VisualModel::IsBackgroundWithCutoutEnabled() const
+{
+ return mBackgroundWithCutoutEnabled;
+}
+
+void VisualModel::SetBackgroundColorWithCutout(const Vector4& color)
+{
+ mBackgroundColorWithCutout = color;
+}
+
+const Vector4& VisualModel::GetBackgroundColorWithCutout() const
+{
+ return mBackgroundColorWithCutout;
+}
+
VisualModel::~VisualModel()
{
}
mBackgroundEnabled(false),
mMarkupProcessorEnabled(false),
mStrikethroughEnabled(false),
- mCharacterSpacing(0.0f)
-
+ mCharacterSpacing(0.0f),
+ mCutoutEnabled(false),
+ mBackgroundWithCutoutEnabled(false)
{
}
*/
const Vector<CharacterSpacingGlyphRun>& GetCharacterSpacingGlyphRuns() const;
+ /**
+ * @brief Sets the cutout flag.
+ *
+ * @param[in] enable true if cutouted.
+ */
+ void SetCutoutEnabled(bool enable);
+
+ /**
+ * @brief Returns whether the text is cutouted or not.
+ *
+ * @return cutout state.
+ */
+ bool IsCutoutEnabled() const;
+
+ /**
+ * @brief Sets the background with cutout flag.
+ *
+ * @param[in] enable true if background enabled.
+ */
+ void SetBackgroundWithCutoutEnabled(bool enable);
+
+ /**
+ * @brief Returns whether the text is cutouted or not.
+ *
+ * @return True if enabled.
+ */
+ bool IsBackgroundWithCutoutEnabled() const;
+
+ /**
+ * @brief Sets the Color of background with cutout.
+ *
+ * @param[in] color The color to set.
+ */
+ void SetBackgroundColorWithCutout(const Vector4& color);
+
+ /**
+ * @brief Retrieves the Color of background with cutout.
+ *
+ * @return The color.
+ */
+ const Vector4& GetBackgroundColorWithCutout() const;
+
protected:
/**
* @brief A reference counted object may only be deleted by calling Unreference().
VisualModel& operator=(const VisualModel& handle);
public:
- Vector<GlyphInfo> mGlyphs; ///< For each glyph, the font's id, glyph's index within the font and glyph's metrics.
- Vector<CharacterIndex> mGlyphsToCharacters; ///< For each glyph, the index of the first character.
- Vector<GlyphIndex> mCharactersToGlyph; ///< For each character, the index of the first glyph.
- Vector<Length> mCharactersPerGlyph; ///< For each glyph, the number of characters that form the glyph.
- Vector<Length> mGlyphsPerCharacter; ///< For each character, the number of glyphs that are shaped.
- Vector<Vector2> mGlyphPositions; ///< For each glyph, the position.
- Vector<LineRun> mLines; ///< The laid out lines.
- Vector<UnderlinedGlyphRun> mUnderlineRuns; ///< Runs of glyphs that are underlined.
- Vector<Vector4> mColors; ///< Colors of the glyphs.
- Vector<ColorIndex> mColorIndices; ///< Indices to the vector of colors for each glyphs.
- Vector<Vector4> mBackgroundColors; ///< Background colors of the glyphs.
- Vector<ColorIndex> mBackgroundColorIndices; ///< Indices to the vector of background colors for each glyphs.
- Vector4 mTextColor; ///< The text color
- Vector4 mShadowColor; ///< Color of drop shadow
- Vector4 mUnderlineColor; ///< Color of underline
- Vector4 mOutlineColor; ///< Color of outline
- Vector4 mBackgroundColor; ///< Color of text background
- Vector4 mStrikethroughColor; ///< Color of text background
- Size mControlSize; ///< The size of the UI control.
- Vector2 mShadowOffset; ///< Offset for drop shadow, 0 indicates no shadow
- Vector2 mOutlineOffset; ///< Offset for outline
- float mUnderlineHeight; ///< Fixed height for underline to override font metrics.
- float mStrikethroughHeight; ///< Fixed height for strikethrough to override font metrics.
- Text::Underline::Type mUnderlineType; ///< The type of the underline.
- float mDashedUnderlineWidth; ///< The width of the dashes of the dashed underline.
- float mDashedUnderlineGap; ///< The gap between the dashes of the dashed underline.
- float mShadowBlurRadius; ///< Blur radius of shadow, 0 indicates no blur.
+ Vector<GlyphInfo> mGlyphs; ///< For each glyph, the font's id, glyph's index within the font and glyph's metrics.
+ Vector<CharacterIndex> mGlyphsToCharacters; ///< For each glyph, the index of the first character.
+ Vector<GlyphIndex> mCharactersToGlyph; ///< For each character, the index of the first glyph.
+ Vector<Length> mCharactersPerGlyph; ///< For each glyph, the number of characters that form the glyph.
+ Vector<Length> mGlyphsPerCharacter; ///< For each character, the number of glyphs that are shaped.
+ Vector<Vector2> mGlyphPositions; ///< For each glyph, the position.
+ Vector<LineRun> mLines; ///< The laid out lines.
+ Vector<UnderlinedGlyphRun> mUnderlineRuns; ///< Runs of glyphs that are underlined.
+ Vector<Vector4> mColors; ///< Colors of the glyphs.
+ Vector<ColorIndex> mColorIndices; ///< Indices to the vector of colors for each glyphs.
+ Vector<Vector4> mBackgroundColors; ///< Background colors of the glyphs.
+ Vector<ColorIndex> mBackgroundColorIndices; ///< Indices to the vector of background colors for each glyphs.
+ Vector4 mTextColor; ///< The text color
+ Vector4 mShadowColor; ///< Color of drop shadow
+ Vector4 mUnderlineColor; ///< Color of underline
+ Vector4 mOutlineColor; ///< Color of outline
+ Vector4 mBackgroundColor; ///< Color of text background
+ Vector4 mStrikethroughColor; ///< Color of text background
+ Size mControlSize; ///< The size of the UI control.
+ Vector2 mShadowOffset; ///< Offset for drop shadow, 0 indicates no shadow
+ Vector2 mOutlineOffset; ///< Offset for outline
+ float mUnderlineHeight; ///< Fixed height for underline to override font metrics.
+ float mStrikethroughHeight; ///< Fixed height for strikethrough to override font metrics.
+ Text::Underline::Type mUnderlineType; ///< The type of the underline.
+ float mDashedUnderlineWidth; ///< The width of the dashes of the dashed underline.
+ float mDashedUnderlineGap; ///< The gap between the dashes of the dashed underline.
+ float mShadowBlurRadius; ///< Blur radius of shadow, 0 indicates no blur.
float mOutlineBlurRadius; ///< Blur radius of outline, 0 indicates no blur.
- uint16_t mOutlineWidth; ///< Width of outline.
- Vector<StrikethroughGlyphRun> mStrikethroughRuns; ///< Runs of glyphs that have strikethrough.
- Vector<CharacterSpacingGlyphRun> mCharacterSpacingRuns; ///< Runs of glyphs that have character-spacing.
+ uint16_t mOutlineWidth; ///< Width of outline.
+ Vector<StrikethroughGlyphRun> mStrikethroughRuns; ///< Runs of glyphs that have strikethrough.
+ Vector<CharacterSpacingGlyphRun> mCharacterSpacingRuns; ///< Runs of glyphs that have character-spacing.
+ Vector4 mBackgroundColorWithCutout; ///< Background color with cutout.
private:
Size mNaturalSize; ///< Size of the text with no line wrapping.
bool mTextElideEnabled : 1; ///< Whether the text's elide is enabled.
public:
- bool mUnderlineEnabled : 1; ///< Underline enabled flag
- bool mUnderlineColorSet : 1; ///< Has the underline color been explicitly set?
- bool mBackgroundEnabled : 1; ///< Background enabled flag
- bool mMarkupProcessorEnabled : 1; ///< Markup-processor enabled flag
- HyphenInfo mHyphen; ///< Contains hyphen glyph info & the character index to draw hyphen after.
- bool mStrikethroughEnabled : 1; ///< Strikethrough enabled flag
- float mCharacterSpacing; ///< Contains the value of the character spacing.
+ bool mUnderlineEnabled : 1; ///< Underline enabled flag
+ bool mUnderlineColorSet : 1; ///< Has the underline color been explicitly set?
+ bool mBackgroundEnabled : 1; ///< Background enabled flag
+ bool mMarkupProcessorEnabled : 1; ///< Markup-processor enabled flag
+ HyphenInfo mHyphen; ///< Contains hyphen glyph info & the character index to draw hyphen after.
+ bool mStrikethroughEnabled : 1; ///< Strikethrough enabled flag
+ float mCharacterSpacing; ///< Contains the value of the character spacing.
+ bool mCutoutEnabled : 1; ///< Cutout enabled flag
+ bool mBackgroundWithCutoutEnabled : 1; ///< Background with cutout enabled flag.
};
} // namespace Text
{
DALI_INIT_TRACE_FILTER(gTraceFilter, DALI_TRACE_TEXT_PERFORMANCE_MARKER, false);
-const int CUSTOM_PROPERTY_COUNT(2); // uTextColorAnimatable, uHasMultipleTextColors
+const int CUSTOM_PROPERTY_COUNT(3); // uTextColorAnimatable, uHasMultipleTextColors, requireRender
/**
* Return Property index for the given string key
void OpacityConstraint(float& current, const PropertyInputContainer& inputs)
{
// Make zero if the alpha value of text color is zero to skip rendering text
- if(EqualsZero(inputs[0]->GetVector4().a))
+ if(EqualsZero(inputs[0]->GetVector4().a) && !inputs[1]->GetBoolean())
{
current = 0.0f;
}
mHasMultipleTextColorsIndex(Property::INVALID_INDEX),
mAnimatableTextColorPropertyIndex(Property::INVALID_INDEX),
mTextColorAnimatableIndex(Property::INVALID_INDEX),
- mRendererUpdateNeeded(false)
+ mTextRequireRenderPropertyIndex(Property::INVALID_INDEX),
+ mRendererUpdateNeeded(false),
+ mTextRequireRender(false)
{
// Enable the pre-multiplied alpha to improve the text quality
mImpl->mFlags |= Impl::IS_PREMULTIPLIED_ALPHA;
mImpl->mRenderer = VisualRenderer::New(geometry, shader);
mImpl->mRenderer.ReserveCustomProperties(CUSTOM_PROPERTY_COUNT);
+ mTextRequireRenderPropertyIndex = mImpl->mRenderer.RegisterUniqueProperty("requireRender", mTextRequireRender);
mHasMultipleTextColorsIndex = mImpl->mRenderer.RegisterUniqueProperty("uHasMultipleTextColors", static_cast<float>(false));
}
// VisualRenderer::Property::OPACITY uses same animatable property internally.
mOpacityConstraint = Constraint::New<float>(mImpl->mRenderer, Dali::DevelRenderer::Property::OPACITY, OpacityConstraint);
mOpacityConstraint.AddSource(Source(actor, mAnimatableTextColorPropertyIndex));
+ mOpacityConstraint.AddSource(Source(mImpl->mRenderer, mTextRequireRenderPropertyIndex));
}
mOpacityConstraint.Apply();
}
const bool isWidthRelative = fabsf(mImpl->mTransform.mOffsetSizeMode.z) < Math::MACHINE_EPSILON_1000;
const bool isHeightRelative = fabsf(mImpl->mTransform.mOffsetSizeMode.w) < Math::MACHINE_EPSILON_1000;
+ const float controlWidth = mImpl->mControlSize.width;
+ const float controlHeight = mImpl->mControlSize.height;
+
// Round the size and offset to avoid pixel alignement issues.
- relayoutSize.width = floorf(0.5f + (isWidthRelative ? mImpl->mControlSize.width * mImpl->mTransform.mSize.x : mImpl->mTransform.mSize.width));
- relayoutSize.height = floorf(0.5f + (isHeightRelative ? mImpl->mControlSize.height * mImpl->mTransform.mSize.y : mImpl->mTransform.mSize.height));
+ relayoutSize.width = floorf(0.5f + (isWidthRelative ? controlWidth * mImpl->mTransform.mSize.x : mImpl->mTransform.mSize.width));
+ relayoutSize.height = floorf(0.5f + (isHeightRelative ? controlHeight * mImpl->mTransform.mSize.y : mImpl->mTransform.mSize.height));
auto textLengthUtf32 = mController->GetNumberOfCharacters();
shadowEnabled = true;
}
- const bool outlineEnabled = (mController->GetTextModel()->GetOutlineWidth() > Math::MACHINE_EPSILON_1);
- const bool backgroundEnabled = mController->GetTextModel()->IsBackgroundEnabled();
- const bool markupOrSpannedText = mController->IsMarkupProcessorEnabled() || mController->GetTextModel()->IsSpannedTextPlaced();
- const bool markupUnderlineEnabled = markupOrSpannedText && mController->GetTextModel()->IsMarkupUnderlineSet();
- const bool markupStrikethroughEnabled = markupOrSpannedText && mController->GetTextModel()->IsMarkupStrikethroughSet();
- const bool underlineEnabled = mController->GetTextModel()->IsUnderlineEnabled() || markupUnderlineEnabled;
- const bool strikethroughEnabled = mController->GetTextModel()->IsStrikethroughEnabled() || markupStrikethroughEnabled;
- const bool backgroundMarkupSet = mController->GetTextModel()->IsMarkupBackgroundColorSet();
- const bool styleEnabled = (shadowEnabled || outlineEnabled || backgroundEnabled || markupOrSpannedText || backgroundMarkupSet);
- const bool isOverlayStyle = underlineEnabled || strikethroughEnabled;
+ const bool outlineEnabled = (mController->GetTextModel()->GetOutlineWidth() > Math::MACHINE_EPSILON_1);
+ const bool backgroundEnabled = mController->GetTextModel()->IsBackgroundEnabled();
+ const bool markupOrSpannedText = mController->IsMarkupProcessorEnabled() || mController->GetTextModel()->IsSpannedTextPlaced();
+ const bool markupUnderlineEnabled = markupOrSpannedText && mController->GetTextModel()->IsMarkupUnderlineSet();
+ const bool markupStrikethroughEnabled = markupOrSpannedText && mController->GetTextModel()->IsMarkupStrikethroughSet();
+ const bool underlineEnabled = mController->GetTextModel()->IsUnderlineEnabled() || markupUnderlineEnabled;
+ const bool strikethroughEnabled = mController->GetTextModel()->IsStrikethroughEnabled() || markupStrikethroughEnabled;
+ const bool backgroundMarkupSet = mController->GetTextModel()->IsMarkupBackgroundColorSet();
+ const bool cutoutEnabled = mController->IsTextCutout();
+ const bool backgroundWithCutoutEnabled = mController->GetTextModel()->IsBackgroundWithCutoutEnabled();
+ const bool styleEnabled = (shadowEnabled || outlineEnabled || backgroundEnabled || markupOrSpannedText || backgroundMarkupSet || cutoutEnabled || backgroundWithCutoutEnabled);
+ const bool isOverlayStyle = underlineEnabled || strikethroughEnabled;
+
+ // if background with cutout is enabled, This text visual must render the entire control size.
+ if(backgroundWithCutoutEnabled)
+ {
+ relayoutSize = Vector2(controlWidth, controlHeight);
+ mImpl->mTransform.mSize.width = controlWidth;
+ mImpl->mTransform.mSize.height = controlHeight;
+ mImpl->mTransform.mOffset.x = 0;
+ mImpl->mTransform.mOffset.y = 0;
+ }
AddRenderer(control, relayoutSize, hasMultipleTextColors, containsColorGlyph, styleEnabled, isOverlayStyle);
// VisualRenderer::Property::OPACITY uses same animatable property internally.
Constraint opacityConstraint = Constraint::New<float>(renderer, Dali::DevelRenderer::Property::OPACITY, OpacityConstraint);
opacityConstraint.AddSource(Source(actor, mAnimatableTextColorPropertyIndex));
+ opacityConstraint.AddSource(Source(mImpl->mRenderer, mTextRequireRenderPropertyIndex));
opacityConstraint.Apply();
}
}
TextureSet TextVisual::GetTextTexture(const Vector2& size)
{
+ const bool cutoutEnabled = mController->IsTextCutout();
+
// Filter mode needs to be set to linear to produce better quality while scaling.
Sampler sampler = Sampler::New();
sampler.SetFilterMode(FilterMode::LINEAR, FilterMode::LINEAR);
TextureSet textureSet = TextureSet::New();
// Create RGBA texture if the text contains emojis or multiple text colors, otherwise L8 texture
- Pixel::Format textPixelFormat = (mTextShaderFeatureCache.IsEnabledEmoji() || mTextShaderFeatureCache.IsEnabledMultiColor()) ? Pixel::RGBA8888 : Pixel::L8;
+ Pixel::Format textPixelFormat = (mTextShaderFeatureCache.IsEnabledEmoji() || mTextShaderFeatureCache.IsEnabledMultiColor() || cutoutEnabled) ? Pixel::RGBA8888 : Pixel::L8;
// Check the text direction
Toolkit::DevelText::TextDirection::Type textDirection = mController->GetTextDirection();
-
+ uint32_t textureSetIndex = 0u;
// Create a texture for the text without any styles
- PixelData data = mTypesetter->Render(size, textDirection, Text::Typesetter::RENDER_NO_STYLES, false, textPixelFormat);
- uint32_t textureSetIndex = 0u;
- AddTexture(textureSet, data, sampler, textureSetIndex);
- ++textureSetIndex;
+ Devel::PixelBuffer cutoutData;
+ float cutoutAlpha = mController->GetTextModel()->GetDefaultColor().a;
+ if(cutoutEnabled)
+ {
+ cutoutData = mTypesetter->RenderWithPixelBuffer(size, textDirection, Text::Typesetter::RENDER_NO_STYLES, false, textPixelFormat);
+
+ // Make transparent buffer.
+ // If the cutout is enabled, a separate texture is not used for the text.
+ Devel::PixelBuffer buffer = mTypesetter->CreateFullBackgroundBuffer(1, 1, Vector4(0.f, 0.f ,0.f ,0.f));
+ PixelData data = Devel::PixelBuffer::Convert(buffer);
+ AddTexture(textureSet, data, sampler, textureSetIndex);
+ ++textureSetIndex;
+ }
+ else
+ {
+ PixelData data = mTypesetter->Render(size, textDirection, Text::Typesetter::RENDER_NO_STYLES, false, textPixelFormat);
+ AddTexture(textureSet, data, sampler, textureSetIndex);
+ ++textureSetIndex;
+ }
+
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);
+ PixelData styleData;
+
+ if(cutoutEnabled && cutoutData)
+ {
+ styleData = mTypesetter->RenderWithCutout(size, textDirection, cutoutData, Text::Typesetter::RENDER_NO_TEXT, false, Pixel::RGBA8888, cutoutAlpha);
+ }
+ else
+ {
+ styleData = mTypesetter->Render(size, textDirection, Text::Typesetter::RENDER_NO_TEXT, false, Pixel::RGBA8888);
+ }
+
AddTexture(textureSet, styleData, sampler, textureSetIndex);
++textureSetIndex;
}
return shader;
}
+void TextVisual::SetRequireRender(bool requireRender)
+{
+ mTextRequireRender = requireRender;
+ mImpl->mRenderer.SetProperty(mTextRequireRenderPropertyIndex, mTextRequireRender);
+}
+
} // namespace Internal
} // namespace Toolkit
};
/**
+ * @brief Set the text to be always rendered
+ * @param[in] visual The text visual.
+ * @param[in] requireRender Whether to text always rendered.
+ */
+ static void SetRequireRender(Toolkit::Visual::Base visual, bool requireRender)
+ {
+ GetVisualObject(visual).SetRequireRender(requireRender);
+ };
+
+ /**
* @brief Instantly updates the renderer
* @param[in] visual The text visual.
*/
Shader GetTextShader(VisualFactoryCache& factoryCache, const TextVisualShaderFeature::FeatureBuilder& featureBuilder);
/**
+ * @brief Set the text to be always rendered
+ * @param[in] requireRender Whether to text always rendered.
+ */
+ void SetRequireRender(bool requireRender);
+
+ /**
* @brief Retrieve the TextVisual object.
* @param[in] visual A handle to the TextVisual
* @return The TextVisual object
Property::Index mHasMultipleTextColorsIndex; ///< The index of uHasMultipleTextColors proeprty.
Property::Index mAnimatableTextColorPropertyIndex; ///< The index of animatable text color property registered by the control.
Property::Index mTextColorAnimatableIndex; ///< The index of uTextColorAnimatable property.
+ Property::Index mTextRequireRenderPropertyIndex; ///< The index of requireRender property.
bool mRendererUpdateNeeded : 1; ///< The flag to indicate whether the renderer needs to be updated.
+ bool mTextRequireRender : 1; ///< The flag to indicate whether the text needs to be rendered.
RendererContainer mRendererList;
};