2 * Copyright (c) 2020 Samsung Electronics Co., Ltd.
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
19 * @file simple-text-renderer-example.cpp
20 * @brief Basic usage of Text Renderer utility.
24 #include <dali-toolkit/dali-toolkit.h>
25 #include <dali-toolkit/devel-api/text/text-utils-devel.h>
26 #include <dali/devel-api/adaptor-framework/image-loading.h>
27 #include <dali/devel-api/adaptor-framework/pixel-buffer.h>
31 using namespace Dali::Toolkit;
35 const std::string IMAGE1 = DEMO_IMAGE_DIR "application-icon-1.png";
36 const std::string IMAGE2 = DEMO_IMAGE_DIR "application-icon-6.png";
38 #define MAKE_SHADER(A) #A
40 const std::string VERSION_3_ES = "#version 300 es\n";
42 const char* VERTEX_SHADER = MAKE_SHADER(
43 precision mediump float;
51 uniform mat4 uMvpMatrix;
54 vec4 vertexPosition = vec4(aPosition, 0.0, 1.0);
55 vertexPosition.xyz *= uSize;
56 gl_Position = uMvpMatrix * vertexPosition;
61 const char* FRAGMENT_SHADER = MAKE_SHADER(
62 precision mediump float;
68 uniform sampler2D sAlbedo;
72 vec4 color = texture(sAlbedo, vUV);
73 FragColor = vec4(color.rgb, uColor.a * color.a);
76 Renderer CreateRenderer()
78 // Create the geometry.
81 Dali::Vector2 position;
82 Dali::Vector2 texCoord;
85 static const Vertex vertices[] = {{Dali::Vector2(-0.5f, -0.5f), Dali::Vector2(0.0f, 0.0f)},
86 {Dali::Vector2(0.5f, -0.5f), Dali::Vector2(1.0f, 0.0f)},
87 {Dali::Vector2(-0.5f, 0.5f), Dali::Vector2(0.0f, 1.0f)},
88 {Dali::Vector2(0.5f, 0.5f), Dali::Vector2(1.0f, 1.0f)}};
90 Property::Map property;
91 property.Add("aPosition", Property::VECTOR2).Add("aTexCoord", Property::VECTOR2);
93 VertexBuffer vertexBuffer = VertexBuffer::New(property);
95 vertexBuffer.SetData(vertices, sizeof(vertices) / sizeof(Vertex));
97 Geometry geometry = Geometry::New();
98 geometry.AddVertexBuffer(vertexBuffer);
100 geometry.SetType(Geometry::TRIANGLE_STRIP);
103 Shader shader = Shader::New(VERSION_3_ES + VERTEX_SHADER, VERSION_3_ES + FRAGMENT_SHADER);
105 // Create the renderer
107 Renderer renderer = Renderer::New(geometry, shader);
112 TextureSet CreateTextureSet(const Dali::Toolkit::DevelText::RendererParameters& textParameters, const std::vector<std::string>& embeddedItems)
114 Dali::Vector<Dali::Toolkit::DevelText::EmbeddedItemInfo> embeddedItemLayout;
116 Devel::PixelBuffer pixelBuffer = Toolkit::DevelText::Render(textParameters, embeddedItemLayout);
118 const int dstWidth = static_cast<int>(pixelBuffer.GetWidth());
119 const int dstHeight = static_cast<int>(pixelBuffer.GetHeight());
121 unsigned int index = 0u;
122 for(const auto& itemLayout : embeddedItemLayout)
124 int width = static_cast<int>(itemLayout.size.width);
125 int height = static_cast<int>(itemLayout.size.height);
126 int x = static_cast<int>(itemLayout.position.x);
127 int y = static_cast<int>(itemLayout.position.y);
129 Dali::Devel::PixelBuffer itemPixelBuffer = Dali::LoadImageFromFile(embeddedItems[index++]);
130 itemPixelBuffer.Resize(width, height);
131 itemPixelBuffer.Rotate(itemLayout.angle);
133 width = static_cast<int>(itemPixelBuffer.GetWidth());
134 height = static_cast<int>(itemPixelBuffer.GetHeight());
136 Dali::Pixel::Format itemPixelFormat = itemPixelBuffer.GetPixelFormat();
138 // Check if the item is out of the buffer.
140 if((x + width < 0) ||
143 (y - height > dstHeight))
145 // The embedded item is completely out of the buffer.
149 // Crop if it exceeds the boundaries of the destination buffer.
154 int newWidth = width;
155 int newHeight = height;
170 if(cropX + newWidth > dstWidth)
173 newWidth -= ((cropX + newWidth) - dstWidth);
179 newHeight += layoutY;
180 cropY = std::abs(layoutY);
184 if(cropY + newHeight > dstHeight)
187 newHeight -= ((cropY + newHeight) - dstHeight);
190 uint16_t uiCropX = static_cast<uint16_t>(cropX);
191 uint16_t uiCropY = static_cast<uint16_t>(cropY);
192 uint16_t uiNewWidth = static_cast<uint16_t>(newWidth);
193 uint16_t uiNewHeight = static_cast<uint16_t>(newHeight);
197 itemPixelBuffer.Crop(uiCropX, uiCropY, uiNewWidth, uiNewHeight);
200 // Blend the item pixel buffer with the text's color according its blending mode.
201 if(Dali::TextAbstraction::ColorBlendingMode::MULTIPLY == itemLayout.colorBlendingMode)
203 Dali::Devel::PixelBuffer buffer = Dali::Devel::PixelBuffer::New(uiNewWidth,
207 unsigned char* bufferPtr = buffer.GetBuffer();
208 const unsigned char* itemBufferPtr = itemPixelBuffer.GetBuffer();
209 const unsigned int bytesPerPixel = Dali::Pixel::GetBytesPerPixel(itemPixelFormat);
210 const unsigned int size = uiNewWidth * uiNewHeight * bytesPerPixel;
212 for(unsigned int i = 0u; i < size; i += bytesPerPixel)
214 *(bufferPtr + 0u) = static_cast<unsigned char>(static_cast<float>(*(itemBufferPtr + 0u)) * textParameters.textColor.r);
215 *(bufferPtr + 1u) = static_cast<unsigned char>(static_cast<float>(*(itemBufferPtr + 1u)) * textParameters.textColor.g);
216 *(bufferPtr + 2u) = static_cast<unsigned char>(static_cast<float>(*(itemBufferPtr + 2u)) * textParameters.textColor.b);
217 *(bufferPtr + 3u) = static_cast<unsigned char>(static_cast<float>(*(itemBufferPtr + 3u)) * textParameters.textColor.a);
219 itemBufferPtr += bytesPerPixel;
220 bufferPtr += bytesPerPixel;
223 itemPixelBuffer = buffer;
226 Dali::Toolkit::DevelText::UpdateBuffer(itemPixelBuffer, pixelBuffer, layoutX, layoutY, true);
229 PixelData pixelData = Devel::PixelBuffer::Convert(pixelBuffer);
231 Texture texture = Texture::New(TextureType::TEXTURE_2D,
232 pixelData.GetPixelFormat(),
233 pixelData.GetWidth(),
234 pixelData.GetHeight());
235 texture.Upload(pixelData);
237 TextureSet textureSet = TextureSet::New();
238 textureSet.SetTexture(0u, texture);
246 * @brief The main class of the demo.
248 class SimpleTextRendererExample : public ConnectionTracker
251 SimpleTextRendererExample(Application& application)
252 : mApplication(application)
254 // Connect to the Application's Init signal
255 mApplication.InitSignal().Connect(this, &SimpleTextRendererExample::Create);
258 ~SimpleTextRendererExample()
260 // Nothing to do here.
264 * One-time setup in response to Application InitSignal.
266 void Create(Application& application)
268 Window window = application.GetWindow();
269 window.SetBackgroundColor(Color::WHITE);
270 window.SetBackgroundColor(Vector4(0.04f, 0.345f, 0.392f, 1.0f));
272 window.KeyEventSignal().Connect(this, &SimpleTextRendererExample::OnKeyEvent);
274 const std::string image1 = "<item 'width'=26 'height'=26 'url'='" + IMAGE1 + "'/>";
275 const std::string image2 = "<item 'width'=26 'height'=26/>";
277 Dali::Toolkit::DevelText::RendererParameters textParameters;
278 textParameters.text = "Hello " + image1 + " world " + image2 + " this " + image1 + " is " + image2 + " a " + image1 + " demo " + image2 + " of " + image1 + " circular " + image2 + " text " + image1 + " width " + image2 + " icons.";
279 textParameters.horizontalAlignment = "center";
280 textParameters.verticalAlignment = "center";
281 textParameters.circularAlignment = "center";
282 textParameters.fontFamily = "SamsungUI";
283 textParameters.fontWeight = "";
284 textParameters.fontWidth = "";
285 textParameters.fontSlant = "";
286 textParameters.layout = "circular";
287 textParameters.textColor = Color::BLACK;
288 textParameters.fontSize = 25.f;
289 textParameters.textWidth = 360u;
290 textParameters.textHeight = 360u;
291 textParameters.radius = 180u;
292 textParameters.beginAngle = 15.f;
293 textParameters.incrementAngle = 360.f;
294 textParameters.ellipsisEnabled = true;
295 textParameters.markupEnabled = true;
297 std::vector<std::string> embeddedItems = {IMAGE2, IMAGE2, IMAGE2, IMAGE2, IMAGE2};
299 TextureSet textureSet = CreateTextureSet(textParameters, embeddedItems);
301 Renderer renderer = CreateRenderer();
302 renderer.SetTextures(textureSet);
304 Actor actor = Actor::New();
305 actor.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::CENTER);
306 actor.SetProperty(Actor::Property::PARENT_ORIGIN, ParentOrigin::CENTER);
307 actor.SetProperty(Actor::Property::POSITION, Vector2(0.f, 0.f));
308 actor.SetProperty(Actor::Property::SIZE, Vector2(360.f, 360.f));
309 actor.SetProperty(Actor::Property::COLOR, Color::WHITE);
311 actor.AddRenderer(renderer);
317 * Main key event handler
319 void OnKeyEvent(const KeyEvent& event)
321 if(event.GetState() == KeyEvent::DOWN)
323 if(IsKey(event, DALI_KEY_ESCAPE) || IsKey(event, DALI_KEY_BACK))
331 Application& mApplication;
334 /** Entry point for Linux & Tizen applications */
335 int DALI_EXPORT_API main(int argc, char** argv)
337 Application application = Application::New(&argc, &argv);
339 SimpleTextRendererExample test(application);
341 application.MainLoop();