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