Revert "Updates following rename of PropertyBuffer"
[platform/core/uifw/dali-demo.git] / examples / simple-text-renderer / simple-text-renderer-example.cpp
1 /*
2  * Copyright (c) 2020 Samsung Electronics Co., Ltd.
3  *
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
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
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.
15  *
16  */
17
18 /**
19  * @file simple-text-renderer-example.cpp
20  * @brief Basic usage of Text Renderer utility.
21  */
22
23 // EXTERNAL INCLUDES
24 #include <dali/devel-api/adaptor-framework/pixel-buffer.h>
25 #include <dali-toolkit/dali-toolkit.h>
26 #include <dali-toolkit/devel-api/text/text-utils-devel.h>
27 #include <dali/devel-api/adaptor-framework/image-loading.h>
28
29 using namespace std;
30 using namespace Dali;
31 using namespace Dali::Toolkit;
32
33 namespace
34 {
35
36 const std::string IMAGE1 = DEMO_IMAGE_DIR "application-icon-1.png";
37 const std::string IMAGE2 = DEMO_IMAGE_DIR "application-icon-6.png";
38
39 #define MAKE_SHADER(A)#A
40
41 const std::string VERSION_3_ES = "#version 300 es\n";
42
43 const char* VERTEX_SHADER = MAKE_SHADER(
44   precision mediump float;
45
46   in vec2 aPosition;
47   in vec2 aTexCoord;
48
49   out vec2 vUV;
50
51   uniform vec3 uSize;
52   uniform mat4 uMvpMatrix;
53
54   void main()
55   {
56     vec4 vertexPosition = vec4(aPosition, 0.0, 1.0);
57     vertexPosition.xyz *= uSize;
58     gl_Position = uMvpMatrix * vertexPosition;
59
60     vUV = aTexCoord;
61   }
62 );
63
64 const char* FRAGMENT_SHADER = MAKE_SHADER(
65   precision mediump float;
66
67   in vec2 vUV;
68
69   out vec4 FragColor;
70
71   uniform sampler2D sAlbedo;
72   uniform vec4 uColor;
73
74   void main()
75   {
76     vec4 color = texture( sAlbedo, vUV );
77     FragColor = vec4( color.rgb, uColor.a * color.a );
78   }
79 );
80
81 Renderer CreateRenderer()
82 {
83   // Create the geometry.
84   struct Vertex
85   {
86     Dali::Vector2 position;
87     Dali::Vector2 texCoord;
88   };
89
90   static const Vertex vertices[] = {{ Dali::Vector2( -0.5f, -0.5f ), Dali::Vector2( 0.0f, 0.0f ) },
91                                     { Dali::Vector2(  0.5f, -0.5f ), Dali::Vector2( 1.0f, 0.0f ) },
92                                     { Dali::Vector2( -0.5f,  0.5f ), Dali::Vector2( 0.0f, 1.0f ) },
93                                     { Dali::Vector2(  0.5f,  0.5f ), Dali::Vector2( 1.0f, 1.0f ) }};
94
95   Property::Map property;
96   property.Add("aPosition", Property::VECTOR2).Add("aTexCoord", Property::VECTOR2);
97
98   PropertyBuffer vertexBuffer = PropertyBuffer::New(property);
99
100   vertexBuffer.SetData(vertices, sizeof(vertices) / sizeof(Vertex));
101
102   Geometry geometry = Geometry::New();
103   geometry.AddVertexBuffer(vertexBuffer);
104
105   geometry.SetType(Geometry::TRIANGLE_STRIP);
106
107   // Create the shader
108   Shader shader = Shader::New( VERSION_3_ES + VERTEX_SHADER, VERSION_3_ES + FRAGMENT_SHADER );
109
110   // Create the renderer
111
112   Renderer renderer = Renderer::New( geometry, shader );
113
114   return renderer;
115 }
116
117 TextureSet CreateTextureSet( const Dali::Toolkit::DevelText::RendererParameters& textParameters, const std::vector<std::string>& embeddedItems )
118 {
119
120   Dali::Vector<Dali::Toolkit::DevelText::EmbeddedItemInfo> embeddedItemLayout;
121
122   Devel::PixelBuffer pixelBuffer = Toolkit::DevelText::Render( textParameters, embeddedItemLayout );
123
124
125   const int dstWidth = static_cast<int>( pixelBuffer.GetWidth() );
126   const int dstHeight = static_cast<int>( pixelBuffer.GetHeight() );
127
128   unsigned int index = 0u;
129   for( const auto& itemLayout : embeddedItemLayout )
130   {
131     int width = static_cast<int>( itemLayout.size.width );
132     int height = static_cast<int>( itemLayout.size.height );
133     int x = static_cast<int>( itemLayout.position.x );
134     int y = static_cast<int>( itemLayout.position.y );
135
136     Dali::Devel::PixelBuffer itemPixelBuffer = Dali::LoadImageFromFile( embeddedItems[index++] );
137     itemPixelBuffer.Resize( width, height );
138     itemPixelBuffer.Rotate( itemLayout.angle );
139
140     width = static_cast<int>( itemPixelBuffer.GetWidth() );
141     height = static_cast<int>( itemPixelBuffer.GetHeight() );
142
143     Dali::Pixel::Format itemPixelFormat = itemPixelBuffer.GetPixelFormat();
144
145     // Check if the item is out of the buffer.
146
147     if( ( x + width < 0 ) ||
148         ( x > dstWidth ) ||
149         ( y < 0 ) ||
150         ( y - height > dstHeight ) )
151     {
152       // The embedded item is completely out of the buffer.
153       continue;
154     }
155
156     // Crop if it exceeds the boundaries of the destination buffer.
157     int layoutX = 0;
158     int layoutY = 0;
159     int cropX = 0;
160     int cropY = 0;
161     int newWidth = width;
162     int newHeight = height;
163
164     bool crop = false;
165
166     if( 0 > x )
167     {
168       newWidth += x;
169       cropX = std::abs( x );
170       crop = true;
171     }
172     else
173     {
174       layoutX = x;
175     }
176
177     if( cropX + newWidth > dstWidth )
178     {
179       crop = true;
180       newWidth -= ( ( cropX + newWidth ) - dstWidth );
181     }
182
183     layoutY = y;
184     if( 0.f > layoutY )
185     {
186       newHeight += layoutY;
187       cropY = std::abs(layoutY);
188       crop = true;
189     }
190
191     if( cropY + newHeight > dstHeight )
192     {
193       crop = true;
194       newHeight -= ( ( cropY + newHeight ) - dstHeight );
195     }
196
197     uint16_t uiCropX = static_cast<uint16_t>(cropX);
198     uint16_t uiCropY = static_cast<uint16_t>(cropY);
199     uint16_t uiNewWidth = static_cast<uint16_t>(newWidth);
200     uint16_t uiNewHeight = static_cast<uint16_t>(newHeight);
201
202     if( crop )
203     {
204       itemPixelBuffer.Crop( uiCropX, uiCropY, uiNewWidth, uiNewHeight );
205     }
206
207     // Blend the item pixel buffer with the text's color according its blending mode.
208     if( Dali::TextAbstraction::ColorBlendingMode::MULTIPLY == itemLayout.colorBlendingMode )
209     {
210       Dali::Devel::PixelBuffer buffer = Dali::Devel::PixelBuffer::New( uiNewWidth,
211                                                                        uiNewHeight,
212                                                                        itemPixelFormat );
213
214       unsigned char* bufferPtr = buffer.GetBuffer();
215       const unsigned char* itemBufferPtr = itemPixelBuffer.GetBuffer();
216       const unsigned int bytesPerPixel = Dali::Pixel::GetBytesPerPixel(itemPixelFormat);
217       const unsigned int size = uiNewWidth * uiNewHeight * bytesPerPixel;
218
219       for (unsigned int i = 0u; i < size; i += bytesPerPixel)
220       {
221         *(bufferPtr + 0u) = static_cast<unsigned char>( static_cast<float>( *(itemBufferPtr + 0u) ) * textParameters.textColor.r );
222         *(bufferPtr + 1u) = static_cast<unsigned char>( static_cast<float>( *(itemBufferPtr + 1u) ) * textParameters.textColor.g );
223         *(bufferPtr + 2u) = static_cast<unsigned char>( static_cast<float>( *(itemBufferPtr + 2u) ) * textParameters.textColor.b );
224         *(bufferPtr + 3u) = static_cast<unsigned char>( static_cast<float>( *(itemBufferPtr + 3u) ) * textParameters.textColor.a );
225
226         itemBufferPtr += bytesPerPixel;
227         bufferPtr += bytesPerPixel;
228       }
229
230       itemPixelBuffer = buffer;
231     }
232
233     Dali::Toolkit::DevelText::UpdateBuffer(itemPixelBuffer, pixelBuffer, layoutX, layoutY, true);
234   }
235
236   PixelData pixelData = Devel::PixelBuffer::Convert( pixelBuffer );
237
238   Texture texture = Texture::New( TextureType::TEXTURE_2D,
239                                   pixelData.GetPixelFormat(),
240                                   pixelData.GetWidth(),
241                                   pixelData.GetHeight() );
242   texture.Upload(pixelData);
243
244   TextureSet textureSet = TextureSet::New();
245   textureSet.SetTexture( 0u, texture );
246
247   return textureSet;
248 }
249
250 } // namespace
251
252
253 /**
254  * @brief The main class of the demo.
255  */
256 class SimpleTextRendererExample : public ConnectionTracker
257 {
258 public:
259
260   SimpleTextRendererExample( Application& application )
261   : mApplication( application )
262   {
263     // Connect to the Application's Init signal
264     mApplication.InitSignal().Connect( this, &SimpleTextRendererExample::Create );
265   }
266
267   ~SimpleTextRendererExample()
268   {
269     // Nothing to do here.
270   }
271
272   /**
273    * One-time setup in response to Application InitSignal.
274    */
275   void Create( Application& application )
276   {
277     Window window = application.GetWindow();
278     window.SetBackgroundColor( Color::WHITE );
279     window.SetBackgroundColor( Vector4( 0.04f, 0.345f, 0.392f, 1.0f ) );
280
281     window.KeyEventSignal().Connect(this, &SimpleTextRendererExample::OnKeyEvent);
282
283     const std::string image1 = "<item 'width'=26 'height'=26 'url'='" + IMAGE1 + "'/>";
284     const std::string image2 = "<item 'width'=26 'height'=26/>";
285
286     Dali::Toolkit::DevelText::RendererParameters textParameters;
287     textParameters.text = "Hello " + image1 + " world " + image2 + " this " + image1 + " is " + image2 + " a " + image1 + " demo " + image2 + " of " + image1 + " circular " + image2 + " text " + image1 + " width " + image2 + " icons.";
288     textParameters.horizontalAlignment = "center";
289     textParameters.verticalAlignment = "center";
290     textParameters.circularAlignment = "center";
291     textParameters.fontFamily = "SamsungUI";
292     textParameters.fontWeight = "";
293     textParameters.fontWidth = "";
294     textParameters.fontSlant = "";
295     textParameters.layout = "circular";
296     textParameters.textColor = Color::BLACK;
297     textParameters.fontSize = 25.f;
298     textParameters.textWidth = 360u;
299     textParameters.textHeight = 360u;
300     textParameters.radius = 180u;
301     textParameters.beginAngle = 15.f;
302     textParameters.incrementAngle = 360.f;
303     textParameters.ellipsisEnabled = true;
304     textParameters.markupEnabled = true;
305
306     std::vector<std::string> embeddedItems = { IMAGE2, IMAGE2, IMAGE2, IMAGE2, IMAGE2 };
307
308     TextureSet textureSet = CreateTextureSet( textParameters, embeddedItems );
309
310     Renderer renderer = CreateRenderer();
311     renderer.SetTextures( textureSet );
312
313     Actor actor = Actor::New();
314     actor.SetProperty( Actor::Property::ANCHOR_POINT, AnchorPoint::CENTER );
315     actor.SetProperty( Actor::Property::PARENT_ORIGIN, ParentOrigin::CENTER );
316     actor.SetProperty( Actor::Property::POSITION, Vector2( 0.f, 0.f));
317     actor.SetProperty( Actor::Property::SIZE, Vector2( 360.f, 360.f ) );
318     actor.SetProperty( Actor::Property::COLOR, Color::WHITE );
319
320     actor.AddRenderer( renderer );
321
322     window.Add( actor );
323   }
324
325   /**
326    * Main key event handler
327    */
328   void OnKeyEvent(const KeyEvent& event)
329   {
330     if(event.state == KeyEvent::Down)
331     {
332       if( IsKey( event, DALI_KEY_ESCAPE) || IsKey( event, DALI_KEY_BACK ) )
333       {
334         mApplication.Quit();
335       }
336     }
337   }
338
339 private:
340
341   Application& mApplication;
342 };
343
344 /** Entry point for Linux & Tizen applications */
345 int DALI_EXPORT_API main( int argc, char **argv )
346 {
347   Application application = Application::New( &argc, &argv );
348
349   SimpleTextRendererExample test( application );
350
351   application.MainLoop();
352
353   return 0;
354 }