53baad6822c13e76bc30a960250806e345366516
[platform/core/uifw/dali-demo.git] / examples / text-memory-profiling / text-memory-profiling-example.cpp
1 /*
2  * Copyright (c) 2019 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 text-memory-profiling-example.cpp
20  * @brief Memory consumption profiling for TextLabel
21  */
22
23 // EXTERNAL INCLUDES
24 #include <dali/dali.h>
25 #include <dali-toolkit/dali-toolkit.h>
26 #include <dali-toolkit/devel-api/controls/navigation-view/navigation-view.h>
27
28 // INTERNAL INCLUDES
29 #include "shared/view.h"
30
31 using namespace Dali;
32 using namespace Dali::Toolkit;
33
34 namespace
35 {
36
37 enum TextType
38 {
39   SINGLE_COLOR_TEXT,
40   SINGLE_COLOR_TEXT_WITH_STYLE,
41   SINGLE_COLOR_TEXT_WITH_EMOJI,
42   SINGLE_COLOR_TEXT_WITH_STYLE_EMOJI,
43   MULTI_COLOR_TEXT,
44   MULTI_COLOR_TEXT_WITH_STYLE,
45   MULTI_COLOR_TEXT_WITH_EMOJI,
46   MULTI_COLOR_TEXT_WITH_STYLE_EMOJI,
47   SMALL_TEXT_IN_LARGE_TEXT_LABEL,
48   NUMBER_OF_TYPES
49 };
50
51 std::string TEXT_TYPE_STRING[ NUMBER_OF_TYPES ] =
52 {
53   "Single color text",
54   "Single color text with style",
55   "Single color text with emoji",
56   "Single color text with style and emoji",
57   "Multi color text",
58   "Multi color text with style",
59   "Multi color text with emoji",
60   "Multi color text with style and emoji",
61   "Small text in large Text Label"
62 };
63
64 const int NUMBER_OF_LABELS = 500;
65
66 const char* BACKGROUND_IMAGE( "" );
67 const char* TOOLBAR_IMAGE( DEMO_IMAGE_DIR "top-bar.png" );
68 const char* BACK_IMAGE( DEMO_IMAGE_DIR "icon-change.png" );
69 const char* BACK_IMAGE_SELECTED( DEMO_IMAGE_DIR "icon-change-selected.png" );
70 const char* INDICATOR_IMAGE( DEMO_IMAGE_DIR "loading.png" );
71
72 } // anonymous namespace
73
74 /**
75  * @brief The main class of the demo.
76  */
77 class TextMemoryProfilingExample : public ConnectionTracker, public Toolkit::ItemFactory
78 {
79 public:
80
81   TextMemoryProfilingExample( Application& application )
82   : mApplication( application ),
83     mCurrentTextStyle( SINGLE_COLOR_TEXT )
84   {
85     // Connect to the Application's Init signal
86     mApplication.InitSignal().Connect( this, &TextMemoryProfilingExample::Create );
87   }
88
89   ~TextMemoryProfilingExample()
90   {
91     // Nothing to do here.
92   }
93
94   /**
95    * @brief Create a text label in the given type
96    */
97   TextLabel SetupTextLabel( int type )
98   {
99     TextLabel label = TextLabel::New();
100     label.SetProperty( Actor::Property::ANCHOR_POINT, ParentOrigin::TOP_LEFT );
101     label.SetProperty( Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_LEFT );
102     label.SetProperty( TextLabel::Property::TEXT_COLOR, Color::BLACK );
103     label.SetProperty( TextLabel::Property::POINT_SIZE, 12.0f );
104     Property::Map shadowMap;
105     shadowMap.Insert( "color", Color::YELLOW );
106     label.SetProperty( TextLabel::Property::SHADOW, shadowMap );
107     label.SetProperty( TextLabel::Property::ENABLE_MARKUP, true );
108
109     Vector2 stageSize = Stage::GetCurrent().GetSize();
110     label.SetPosition( Vector3( Random::Range( 0.0f, stageSize.x ), Random::Range( 0.0f, stageSize.y ), 0.0f) );
111
112     switch ( type )
113     {
114       case SINGLE_COLOR_TEXT:
115       {
116         label.SetProperty( TextLabel::Property::TEXT, "A Quick Brown Fox Jumps Over The Lazy Dog" );
117
118         shadowMap.Insert( "offset", Vector2( 0.0f, 0.0f ) );
119         label.SetProperty( TextLabel::Property::SHADOW, shadowMap );
120         break;
121       }
122       case SINGLE_COLOR_TEXT_WITH_STYLE:
123       {
124         label.SetProperty( TextLabel::Property::TEXT, "A Quick Brown Fox Jumps Over The Lazy Dog" );
125
126         shadowMap.Insert( "offset", Vector2( 2.0f, 2.0f ) );
127         label.SetProperty( TextLabel::Property::SHADOW, shadowMap );
128         break;
129       }
130       case SINGLE_COLOR_TEXT_WITH_EMOJI:
131       {
132         label.SetProperty( TextLabel::Property::TEXT, "\xF0\x9F\x98\x81 A Quick Brown Fox Jumps Over The Lazy Dog" );
133
134         shadowMap.Insert( "offset", Vector2( 0.0f, 0.0f ) );
135         label.SetProperty( TextLabel::Property::SHADOW, shadowMap );
136         break;
137       }
138       case SINGLE_COLOR_TEXT_WITH_STYLE_EMOJI:
139       {
140         label.SetProperty( TextLabel::Property::TEXT, "\xF0\x9F\x98\x81 A Quick Brown Fox Jumps Over The Lazy Dog" );
141
142         shadowMap.Insert( "offset", Vector2( 2.0f, 2.0f ) );
143         label.SetProperty( TextLabel::Property::SHADOW, shadowMap );
144         break;
145       }
146       case MULTI_COLOR_TEXT:
147       {
148         label.SetProperty( TextLabel::Property::TEXT, "A <color value='cyan'>Quick Brown Fox</color> Jumps Over The <color value='yellow'>Lazy Dog</color>" );
149
150         shadowMap.Insert( "offset", Vector2( 0.0f, 0.0f ) );
151         label.SetProperty( TextLabel::Property::SHADOW, shadowMap );
152         break;
153       }
154       case MULTI_COLOR_TEXT_WITH_STYLE:
155       {
156         label.SetProperty( TextLabel::Property::TEXT, "A <color value='cyan'>Quick Brown Fox</color> Jumps Over The <color value='yellow'>Lazy Dog</color>" );
157
158         shadowMap.Insert( "offset", Vector2( 2.0f, 2.0f ) );
159         label.SetProperty( TextLabel::Property::SHADOW, shadowMap );
160         break;
161       }
162       case MULTI_COLOR_TEXT_WITH_EMOJI:
163       {
164         label.SetProperty( TextLabel::Property::TEXT, " \xF0\x9F\x98\x81 A <color value='cyan'>Quick Brown Fox</color> Jumps Over The <color value='yellow'>Lazy Dog</color>" );
165
166         shadowMap.Insert( "offset", Vector2( 0.0f, 0.0f ) );
167         label.SetProperty( TextLabel::Property::SHADOW, shadowMap );
168         break;
169       }
170       case MULTI_COLOR_TEXT_WITH_STYLE_EMOJI:
171       {
172         label.SetProperty( TextLabel::Property::TEXT, " \xF0\x9F\x98\x81 A <color value='cyan'>Quick Brown Fox</color> Jumps Over The <color value='yellow'>Lazy Dog</color>" );
173
174         shadowMap.Insert( "offset", Vector2( 2.0f, 2.0f ) );
175         label.SetProperty( TextLabel::Property::SHADOW, shadowMap );
176         break;
177       }
178       case SMALL_TEXT_IN_LARGE_TEXT_LABEL:
179       {
180         label.SetProperty( TextLabel::Property::TEXT, "A Quick Brown Fox Jumps Over The Lazy Dog" );
181
182         shadowMap.Insert( "offset", Vector2( 0.0f, 0.0f ) );
183         label.SetProperty( TextLabel::Property::SHADOW, shadowMap );
184         label.SetSize(stageSize.x, stageSize.y * 0.25f); // Set the text label in larger size
185         break;
186       }
187       default:
188         break;
189     }
190
191     return label;
192   }
193
194   /**
195    * @brief Create the main menu
196    */
197   void CreateMainMenu()
198   {
199     Stage stage = Stage::GetCurrent();
200     Vector2 stageSize = stage.GetSize();
201
202     mTapDetector = TapGestureDetector::New();
203     mTapDetector.DetectedSignal().Connect( this, &TextMemoryProfilingExample::OnTap );
204
205     // Create an item view for the main menu
206     mItemView = ItemView::New( *this );
207
208     mItemView.SetProperty( Actor::Property::PARENT_ORIGIN, ParentOrigin::CENTER );
209     mItemView.SetProperty( Actor::Property::ANCHOR_POINT, AnchorPoint::CENTER );
210
211     mLayout = DefaultItemLayout::New( DefaultItemLayout::LIST );
212     mLayout->SetItemSize( Vector3( stageSize.width, 60.0f, 0.0f ) );
213
214     mItemView.AddLayout( *mLayout );
215
216     // Activate the layout
217     mItemView.ActivateLayout( 0, Vector3( stageSize ), 0.0f );
218   }
219
220   /**
221    * @brief Return the number of items in the main menu
222    */
223   virtual unsigned int GetNumberOfItems()
224   {
225     return NUMBER_OF_TYPES;
226   }
227
228   /**
229    * @brief Create new item for the main menu
230    */
231   virtual Actor NewItem( unsigned int itemId )
232   {
233     TextLabel label = TextLabel::New( TEXT_TYPE_STRING[itemId] );
234     label.SetStyleName( "BuilderLabel" );
235     label.SetResizePolicy( ResizePolicy::FILL_TO_PARENT, Dimension::WIDTH );
236
237     // Hook up tap detector
238     mTapDetector.Attach( label );
239
240     return label;
241   }
242
243   /**
244    * @brief Create text labels for memory profiling
245    */
246   void CreateTextLabels( int type )
247   {
248     Stage stage = Stage::GetCurrent();
249
250     // Render tasks may have been setup last load so remove them
251     RenderTaskList taskList = stage.GetRenderTaskList();
252     if( taskList.GetTaskCount() > 1 )
253     {
254       typedef std::vector<RenderTask> Collection;
255       typedef Collection::iterator ColIter;
256       Collection tasks;
257
258       for( unsigned int i = 1; i < taskList.GetTaskCount(); ++i )
259       {
260         tasks.push_back( taskList.GetTask(i) );
261       }
262
263       for( ColIter iter = tasks.begin(); iter != tasks.end(); ++iter )
264       {
265         taskList.RemoveTask(*iter);
266       }
267
268       RenderTask defaultTask = taskList.GetTask( 0 );
269       defaultTask.SetSourceActor( stage.GetRootLayer() );
270       defaultTask.SetTargetFrameBuffer( FrameBufferImage() );
271     }
272
273     // Delete any existing text labels
274     unsigned int numChildren = mLayer.GetChildCount();
275
276     for( unsigned int i = 0; i < numChildren; ++i )
277     {
278       mLayer.Remove( mLayer.GetChildAt( 0 ) );
279     }
280
281     mLayer.SetProperty( Actor::Property::PARENT_ORIGIN, ParentOrigin::BOTTOM_CENTER );
282     mLayer.SetProperty( Actor::Property::ANCHOR_POINT, AnchorPoint::BOTTOM_CENTER );
283     mLayer.SetResizePolicy( ResizePolicy::FILL_TO_PARENT, Dimension::WIDTH );
284     mLayer.SetResizePolicy( ResizePolicy::SIZE_FIXED_OFFSET_FROM_PARENT, Dimension::HEIGHT );
285     mLayer.SetSizeModeFactor( Vector3( 0.0f, -DemoHelper::DEFAULT_VIEW_STYLE.mToolBarHeight, 0.0f ) );
286
287     mNavigationView.Push( mLayer );
288
289     // Create new text labels
290     for ( int i = 0; i < NUMBER_OF_LABELS; i++ )
291     {
292       TextLabel label = SetupTextLabel( type );
293       mLayer.Add( label );
294     }
295
296     mTitle.SetProperty( TextLabel::Property::TEXT, "Run memps on target" );
297   }
298
299   /**
300    * @brief One-time setup in response to Application InitSignal.
301    */
302   void Create( Application& application )
303   {
304     Stage stage = Stage::GetCurrent();
305
306     stage.KeyEventSignal().Connect(this, &TextMemoryProfilingExample::OnKeyEvent);
307
308     Layer contents = DemoHelper::CreateView( mApplication,
309                                              mView,
310                                              mToolBar,
311                                              BACKGROUND_IMAGE,
312                                              TOOLBAR_IMAGE,
313                                              "" );
314
315     mTitle = DemoHelper::CreateToolBarLabel( "" );
316     mTitle.SetProperty( TextLabel::Property::TEXT, "Select the type of text" );
317
318     // Add title to the tool bar.
319     mToolBar.AddControl( mTitle, DemoHelper::DEFAULT_VIEW_STYLE.mToolBarTitlePercentage, Alignment::HorizontalCenter );
320
321     // Create a layer to contain dynamically created text labels
322     mLayer = Layer::New();
323
324     mIndicator = Toolkit::ImageView::New(INDICATOR_IMAGE);
325     mIndicator.SetProperty( Actor::Property::PARENT_ORIGIN, ParentOrigin::CENTER );
326     mIndicator.SetProperty( Actor::Property::ANCHOR_POINT, AnchorPoint::CENTER );
327     mIndicator.SetProperty( Actor::Property::VISIBLE, false );
328
329     // Create a back button in the left of toolbar
330     PushButton backButton = PushButton::New();
331     backButton.SetProperty( Button::Property::UNSELECTED_BACKGROUND_VISUAL, BACK_IMAGE );
332     backButton.SetProperty( Button::Property::SELECTED_BACKGROUND_VISUAL, BACK_IMAGE_SELECTED );
333     backButton.ClickedSignal().Connect( this, &TextMemoryProfilingExample::OnBackButtonPressed );
334     backButton.SetProperty( Actor::Property::LEAVE_REQUIRED, true );
335     mToolBar.AddControl( backButton, DemoHelper::DEFAULT_VIEW_STYLE.mToolBarButtonPercentage, Alignment::HorizontalLeft, DemoHelper::DEFAULT_MODE_SWITCH_PADDING );
336
337     // Create a navigation view to navigate different types of text labels
338     mNavigationView = NavigationView::New();
339     mNavigationView.SetResizePolicy( ResizePolicy::FILL_TO_PARENT, Dimension::ALL_DIMENSIONS );
340     mNavigationView.SetProperty( Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_LEFT );
341     mNavigationView.SetBackgroundColor( Color::WHITE );
342     stage.Add( mNavigationView );
343
344     CreateMainMenu();
345     mNavigationView.Push( mItemView );
346
347     mItemView.Add(mIndicator);
348
349     PropertyNotification notification = mIndicator.AddPropertyNotification( Actor::Property::VISIBLE, GreaterThanCondition(0.01f) );
350     notification.NotifySignal().Connect( this, &TextMemoryProfilingExample::OnIndicatorVisible );
351   }
352
353   /**
354    * @brief Main key event handler
355    */
356   void OnKeyEvent( const KeyEvent& event )
357   {
358     if( event.state == KeyEvent::Down )
359     {
360       if( IsKey( event, DALI_KEY_ESCAPE) || IsKey( event, DALI_KEY_BACK ) )
361       {
362         ReturnToPreviousScreen();
363       }
364     }
365   }
366
367   /**
368    * @brief Tap gesture handler
369    */
370   void OnTap( Actor actor, const TapGesture& tap )
371   {
372     mCurrentTextStyle = mItemView.GetItemId( actor );
373
374     // Show the loading indicator
375     mIndicator.SetProperty( Actor::Property::VISIBLE, true );
376
377     if ( mAnimation )
378     {
379       mAnimation.Clear();
380       mAnimation.Reset();
381     }
382
383     mAnimation = Animation::New( 0.8f );
384     mAnimation.AnimateBy( Property( mIndicator, Actor::Property::ORIENTATION ), Quaternion( Radian( Degree(180.0f) ), Vector3::ZAXIS ) );
385     mAnimation.SetLooping( true );
386     mAnimation.Play();
387   }
388
389   /**
390    * @brief Property notification handler
391    */
392   void OnIndicatorVisible( PropertyNotification& source )
393   {
394     CreateTextLabels( mCurrentTextStyle );
395
396     // Hide the loading indicator
397     mAnimation.Stop();
398     mIndicator.SetProperty( Actor::Property::VISIBLE, false );
399   }
400
401   /**
402    * @brief Button signal handler
403    */
404   bool OnBackButtonPressed( Toolkit::Button button )
405   {
406     ReturnToPreviousScreen();
407     return true;
408   }
409
410   /**
411    * @brief Returns to the previous screen
412    */
413   void ReturnToPreviousScreen()
414   {
415     if ( mItemView.OnStage() )
416     {
417       // Quit the application if it is in the main menu
418       mApplication.Quit();
419     }
420     else
421     {
422       // Return to the main menu
423       mNavigationView.Pop();
424
425       mTitle.SetProperty( TextLabel::Property::TEXT, "Select type of text to test" );
426     }
427   }
428
429 private:
430
431   Application& mApplication;
432
433   ItemLayoutPtr mLayout;
434   ItemView mItemView;
435   NavigationView mNavigationView;
436
437   Control mView;
438   ToolBar mToolBar;
439   TextLabel mTitle;
440   ImageView mIndicator;
441   Animation mAnimation;
442
443   Layer mLayer;
444
445   TapGestureDetector mTapDetector;
446
447   unsigned int mCurrentTextStyle;
448 };
449
450 int DALI_EXPORT_API main( int argc, char **argv )
451 {
452   Application application = Application::New( &argc, &argv, DEMO_THEME_PATH );
453   TextMemoryProfilingExample test( application );
454   application.MainLoop();
455   return 0;
456 }