Merge remote-tracking branch 'origin/tizen' into devel/new_mesh
[platform/core/uifw/dali-demo.git] / examples / new-window / new-window-example.cpp
1 /*
2  * Copyright (c) 2014 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 #include <dali-toolkit/dali-toolkit.h>
18 #include <dali-toolkit/devel-api/controls/bubble-effect/bubble-emitter.h>
19
20 #include "shared/view.h"
21 #include <cstdio>
22 #include <iostream>
23
24 using namespace Dali;
25 using namespace Dali::Toolkit;
26
27 class NewWindowController;
28
29 namespace
30 {
31 const char * const BACKGROUND_IMAGE( DALI_IMAGE_DIR "background-2.jpg" );
32 const char * const TOOLBAR_IMAGE( DALI_IMAGE_DIR "top-bar.png" );
33 const char * const LOSE_CONTEXT_IMAGE( DALI_IMAGE_DIR "icon-cluster-wobble.png" );
34 const char * const BASE_IMAGE( DALI_IMAGE_DIR "gallery-large-14.jpg" );
35 const char * const EFFECT_IMAGE( DALI_IMAGE_DIR "gallery-large-18.jpg" );
36 const char * const LOGO_IMAGE(DALI_IMAGE_DIR "dali-logo.png");
37
38 const float EXPLOSION_DURATION(1.2f);
39 const unsigned int EMIT_INTERVAL_IN_MS(40);
40 const float TRACK_DURATION_IN_MS(970);
41
42 Application gApplication;
43 NewWindowController* gNewWindowController(NULL);
44
45 #define MAKE_SHADER(A)#A
46
47 const char* VERTEX_COLOR_MESH = MAKE_SHADER(
48 attribute mediump vec3  aPosition;\n
49 attribute lowp    vec3  aColor;\n
50 uniform   mediump mat4  uMvpMatrix;\n
51 uniform   mediump vec3  uSize;\n
52 varying   lowp    vec3  vColor;\n
53 \n
54 void main()\n
55 {\n
56   gl_Position = uMvpMatrix * vec4( aPosition*uSize, 1.0 );\n
57   vColor = aColor;\n
58 }\n
59 );
60
61 const char* FRAGMENT_COLOR_MESH = MAKE_SHADER(
62 uniform lowp vec4  uColor;\n
63 varying lowp vec3  vColor;\n
64 \n
65 void main()\n
66 {\n
67   gl_FragColor = vec4(vColor,1.0)*uColor;
68 }\n
69 );
70
71 const char* VERTEX_TEXTURE_MESH = MAKE_SHADER(
72 attribute mediump vec3  aPosition;\n
73 attribute highp   vec2  aTexCoord;\n
74 uniform   mediump mat4  uMvpMatrix;\n
75 uniform   mediump vec3  uSize;\n
76 varying   mediump vec2  vTexCoord;\n
77 \n
78 void main()\n
79 {\n
80   gl_Position = uMvpMatrix * vec4( aPosition*uSize, 1.0 );\n
81   vTexCoord = aTexCoord;\n
82 }\n
83 );
84
85 const char* FRAGMENT_TEXTURE_MESH = MAKE_SHADER(
86 varying mediump vec2  vTexCoord;\n
87 uniform lowp    vec4  uColor;\n
88 uniform sampler2D     sTexture;\n
89 \n
90 void main()\n
91 {\n
92   gl_FragColor = texture2D( sTexture, vTexCoord ) * uColor;
93 }\n
94 );
95
96 const char* FRAGMENT_BLEND_SHADER = MAKE_SHADER(
97 uniform mediump float alpha;\n
98 \n
99 void main()\n
100 {\n
101   mediump vec4 fragColor = texture2D(sTexture, vTexCoord);\n
102   mediump vec4 fxColor   = texture2D(sEffect, vTexCoord);\n
103   gl_FragColor = mix(fragColor,fxColor, alpha);\n
104 }\n
105 );
106
107 }; // anonymous namespace
108
109
110 class NewWindowController : public ConnectionTracker
111 {
112 public:
113   NewWindowController( Application& app );
114   void Create( Application& app );
115   void Destroy( Application& app );
116
117   void AddBubbles(const Vector2& stageSize);
118   void AddMeshActor();
119   void AddBlendingImageActor();
120   void AddTextLabel();
121
122   ImageActor CreateBlurredMirrorImage(const char* imageName);
123   FrameBufferImage CreateFrameBufferForImage(const char* imageName, Image image, ShaderEffect shaderEffect);
124   void SetUpBubbleEmission( const Vector2& emitPosition, const Vector2& direction );
125   Geometry CreateMeshGeometry();
126   ShaderEffect CreateColorModifierer( const Vector3& rgbDelta );
127
128   static void NewWindow(void);
129
130   bool OnTrackTimerTick();
131   void OnKeyEvent(const KeyEvent& event);
132   bool OnLoseContextButtonClicked( Toolkit::Button button );
133   void OnContextLost();
134   void OnContextRegained();
135
136 private:
137   Application                mApplication;
138   TextLabel                  mTextActor;
139
140   Toolkit::Control           mView;                              ///< The View instance.
141   Toolkit::ToolBar           mToolBar;                           ///< The View's Toolbar.
142   TextLabel                  mTitleActor;                        ///< The Toolbar's Title.
143   Layer                      mContentLayer;                      ///< Content layer (scrolling cluster content)
144   Toolkit::PushButton        mLoseContextButton;
145
146   Toolkit::BubbleEmitter     mEmitter;
147   Timer                      mEmitTrackTimer;
148   bool                       mNeedNewAnimation;
149   unsigned int               mAnimateComponentCount;
150   Animation                  mEmitAnimation;
151 };
152
153
154 NewWindowController::NewWindowController( Application& application )
155 : mApplication(application),
156   mNeedNewAnimation(true)
157 {
158   mApplication.InitSignal().Connect(this, &NewWindowController::Create);
159   mApplication.TerminateSignal().Connect(this, &NewWindowController::Destroy);
160 }
161
162 void NewWindowController::Create( Application& app )
163 {
164   Stage stage = Stage::GetCurrent();
165   stage.SetBackgroundColor(Color::YELLOW);
166
167   stage.KeyEventSignal().Connect(this, &NewWindowController::OnKeyEvent);
168
169   // The Init signal is received once (only) during the Application lifetime
170
171   // Hide the indicator bar
172   mApplication.GetWindow().ShowIndicator( Dali::Window::INVISIBLE );
173
174   mContentLayer = DemoHelper::CreateView( app,
175                                           mView,
176                                           mToolBar,
177                                           "",
178                                           TOOLBAR_IMAGE,
179                                           "Context recovery" );
180
181   Size stageSize = stage.GetSize();
182   Image backgroundImage = ResourceImage::New( BACKGROUND_IMAGE, Dali::ImageDimensions( stageSize.x, stageSize.y ), Dali::FittingMode::SCALE_TO_FILL, Dali::SamplingMode::BOX_THEN_LINEAR );
183   ImageActor backgroundActor = ImageActor::New( backgroundImage );
184   backgroundActor.SetParentOrigin( ParentOrigin::CENTER );
185   backgroundActor.SetZ(-2.f);
186   mContentLayer.Add(backgroundActor);
187
188   // Point the default render task at the view
189   RenderTaskList taskList = stage.GetRenderTaskList();
190   RenderTask defaultTask = taskList.GetTask( 0u );
191   if ( defaultTask )
192   {
193     defaultTask.SetSourceActor( mView );
194   }
195
196   mLoseContextButton = Toolkit::PushButton::New();
197   mLoseContextButton.SetBackgroundImage( ResourceImage::New( LOSE_CONTEXT_IMAGE ) );
198   mLoseContextButton.ClickedSignal().Connect( this, &NewWindowController::OnLoseContextButtonClicked );
199   mToolBar.AddControl( mLoseContextButton, DemoHelper::DEFAULT_VIEW_STYLE.mToolBarButtonPercentage, Toolkit::Alignment::HorizontalRight, DemoHelper::DEFAULT_MODE_SWITCH_PADDING );
200
201   Actor logoLayoutActor = Actor::New();
202   logoLayoutActor.SetParentOrigin(ParentOrigin::CENTER);
203   logoLayoutActor.SetPosition(0.0f, -200.0f, 0.0f);
204   logoLayoutActor.SetScale(0.5f);
205   mContentLayer.Add(logoLayoutActor);
206
207   Image image = ResourceImage::New(LOGO_IMAGE);
208   ImageActor imageActor = ImageActor::New(image);
209   imageActor.SetName("dali-logo");
210   imageActor.SetParentOrigin(ParentOrigin::CENTER);
211   imageActor.SetAnchorPoint(AnchorPoint::BOTTOM_CENTER);
212   logoLayoutActor.Add(imageActor);
213
214   ImageActor mirrorImageActor = CreateBlurredMirrorImage(LOGO_IMAGE);
215   mirrorImageActor.SetParentOrigin(ParentOrigin::CENTER);
216   mirrorImageActor.SetAnchorPoint(AnchorPoint::TOP_CENTER);
217   logoLayoutActor.Add(mirrorImageActor);
218
219   AddBubbles(stage.GetSize());
220   AddMeshActor();
221   AddBlendingImageActor();
222   AddTextLabel();
223
224   stage.ContextLostSignal().Connect(this, &NewWindowController::OnContextLost);
225   stage.ContextRegainedSignal().Connect(this, &NewWindowController::OnContextRegained);
226 }
227
228 void NewWindowController::Destroy( Application& app )
229 {
230   UnparentAndReset(mTextActor);
231 }
232
233 void NewWindowController::AddBubbles(const Vector2& stageSize)
234 {
235   mEmitter = Toolkit::BubbleEmitter::New( stageSize,
236                                           ResourceImage::New( DALI_IMAGE_DIR "bubble-ball.png" ),
237                                           200, Vector2( 5.0f, 5.0f ) );
238
239   Image background = ResourceImage::New(BACKGROUND_IMAGE);
240   mEmitter.SetBackground( background, Vector3(0.5f, 0.f,0.5f) );
241   mEmitter.SetBubbleDensity( 9.f );
242   Actor bubbleRoot = mEmitter.GetRootActor();
243   mContentLayer.Add( bubbleRoot );
244   bubbleRoot.SetParentOrigin(ParentOrigin::CENTER);
245   bubbleRoot.SetZ(0.1f);
246
247   mEmitTrackTimer = Timer::New( EMIT_INTERVAL_IN_MS );
248   mEmitTrackTimer.TickSignal().Connect(this, &NewWindowController::OnTrackTimerTick);
249   mEmitTrackTimer.Start();
250 }
251
252 void NewWindowController::AddMeshActor()
253 {
254   Geometry meshGeometry = CreateMeshGeometry();
255
256   // Create a coloured mesh
257   Shader shaderColorMesh = Shader::New( VERTEX_COLOR_MESH, FRAGMENT_COLOR_MESH );
258   Material colorMeshmaterial = Material::New( shaderColorMesh );
259   Renderer colorMeshRenderer = Renderer::New( meshGeometry, colorMeshmaterial );
260
261   Actor colorMeshActor = Actor::New();
262   colorMeshActor.AddRenderer( colorMeshRenderer );
263   colorMeshActor.SetSize( 175.f,175.f );
264   colorMeshActor.SetParentOrigin( ParentOrigin::CENTER );
265   colorMeshActor.SetAnchorPoint(AnchorPoint::TOP_CENTER);
266   colorMeshActor.SetPosition(Vector3(0.0f, 50.0f, 0.0f));
267   colorMeshActor.SetOrientation( Degree(75.f), Vector3::XAXIS );
268   colorMeshActor.SetName("ColorMeshActor");
269   mContentLayer.Add( colorMeshActor );
270
271  // Create a textured mesh
272   Image effectImage = ResourceImage::New(EFFECT_IMAGE);
273   Sampler sampler = Sampler::New(effectImage, "sTexture");
274
275   Shader shaderTextureMesh = Shader::New( VERTEX_TEXTURE_MESH, FRAGMENT_TEXTURE_MESH );
276   Material textureMeshMaterial = Material::New( shaderTextureMesh );
277   textureMeshMaterial.AddSampler( sampler );
278   Renderer textureMeshRenderer = Renderer::New( meshGeometry, textureMeshMaterial );
279
280   Actor textureMeshActor = Actor::New();
281   textureMeshActor.AddRenderer( textureMeshRenderer );
282   textureMeshActor.SetSize( 175.f,175.f );
283   textureMeshActor.SetParentOrigin( ParentOrigin::CENTER );
284   textureMeshActor.SetAnchorPoint(AnchorPoint::TOP_CENTER);
285   textureMeshActor.SetPosition(Vector3(0.0f, 200.0f, 0.0f));
286   textureMeshActor.SetOrientation( Degree(75.f), Vector3::XAXIS );
287   textureMeshActor.SetName("TextureMeshActor");
288   mContentLayer.Add( textureMeshActor );
289 }
290
291 void NewWindowController::AddBlendingImageActor()
292 {
293   ShaderEffect colorModifier = CreateColorModifierer(Vector3( 0.5f, 0.5f, 0.5f ));
294   Image effectImage = ResourceImage::New(EFFECT_IMAGE);
295   FrameBufferImage fb2 = CreateFrameBufferForImage( EFFECT_IMAGE, effectImage, colorModifier );
296
297   ImageActor tmpActor = ImageActor::New(fb2);
298   mContentLayer.Add(tmpActor);
299   tmpActor.SetParentOrigin(ParentOrigin::CENTER_RIGHT);
300   tmpActor.SetAnchorPoint(AnchorPoint::TOP_RIGHT);
301   tmpActor.SetPosition(Vector3(0.0f, 150.0f, 0.0f));
302   tmpActor.SetScale(0.25f);
303
304   // create blending shader effect
305   ShaderEffect blendShader = ShaderEffect::New( "", FRAGMENT_BLEND_SHADER );
306   blendShader.SetEffectImage( fb2 );
307   blendShader.SetUniform("alpha", 0.5f);
308
309   Image baseImage = ResourceImage::New(BASE_IMAGE);
310   ImageActor blendActor = ImageActor::New( baseImage );
311   blendActor.SetParentOrigin(ParentOrigin::CENTER_RIGHT);
312   blendActor.SetAnchorPoint(AnchorPoint::BOTTOM_RIGHT);
313   blendActor.SetPosition(Vector3(0.0f, 100.0f, 0.0f));
314   blendActor.SetSize(140, 140);
315   blendActor.SetShaderEffect( blendShader );
316   mContentLayer.Add(blendActor);
317 }
318
319 void NewWindowController::AddTextLabel()
320 {
321   mTextActor = TextLabel::New("Some text");
322   mTextActor.SetParentOrigin(ParentOrigin::CENTER);
323   mTextActor.SetColor(Color::RED);
324   mTextActor.SetName("PushMe text");
325   mContentLayer.Add( mTextActor );
326 }
327
328 ImageActor NewWindowController::CreateBlurredMirrorImage(const char* imageName)
329 {
330   Image image = ResourceImage::New(imageName);
331
332   Uint16Pair intFboSize = ResourceImage::GetImageSize(imageName);
333   Vector2 FBOSize = Vector2( intFboSize.GetWidth(), intFboSize.GetHeight() );
334   FrameBufferImage fbo = FrameBufferImage::New( FBOSize.width, FBOSize.height, Pixel::RGBA8888);
335
336   GaussianBlurView gbv = GaussianBlurView::New(5, 2.0f, Pixel::RGBA8888, 0.5f, 0.5f, true);
337   gbv.SetBackgroundColor(Color::TRANSPARENT);
338   gbv.SetUserImageAndOutputRenderTarget( image, fbo );
339   gbv.SetSize(FBOSize);
340   Stage::GetCurrent().Add(gbv);
341   gbv.ActivateOnce();
342
343   ImageActor blurredActor = ImageActor::New(fbo);
344   blurredActor.SetSize(FBOSize);
345   blurredActor.SetScale(1.0f, -1.0f, 1.0f);
346   return blurredActor;
347 }
348
349 FrameBufferImage NewWindowController::CreateFrameBufferForImage(const char* imageName, Image image, ShaderEffect shaderEffect)
350 {
351   Stage stage = Stage::GetCurrent();
352   Uint16Pair intFboSize = ResourceImage::GetImageSize(imageName);
353   Vector2 FBOSize = Vector2(intFboSize.GetWidth(), intFboSize.GetHeight());
354
355   FrameBufferImage framebuffer = FrameBufferImage::New(FBOSize.x, FBOSize.y );
356
357   RenderTask renderTask = stage.GetRenderTaskList().CreateTask();
358
359   ImageActor imageActor = ImageActor::New(image);
360   imageActor.SetName("Source image actor");
361   if(shaderEffect)
362   {
363     imageActor.SetShaderEffect(shaderEffect);
364   }
365   imageActor.SetParentOrigin(ParentOrigin::CENTER);
366   imageActor.SetAnchorPoint(AnchorPoint::CENTER);
367   imageActor.SetScale(1.0f, -1.0f, 1.0f);
368   stage.Add(imageActor); // Not in default image view
369
370   CameraActor cameraActor = CameraActor::New(FBOSize);
371   cameraActor.SetParentOrigin(ParentOrigin::CENTER);
372   cameraActor.SetFieldOfView(Math::PI*0.25f);
373   cameraActor.SetNearClippingPlane(1.0f);
374   cameraActor.SetAspectRatio(FBOSize.width / FBOSize.height);
375   cameraActor.SetType(Dali::Camera::FREE_LOOK); // camera orientation based solely on actor
376   cameraActor.SetPosition(0.0f, 0.0f, ((FBOSize.height * 0.5f) / tanf(Math::PI * 0.125f)));
377   stage.Add(cameraActor);
378
379   renderTask.SetSourceActor(imageActor);
380   renderTask.SetInputEnabled(false);
381   renderTask.SetTargetFrameBuffer(framebuffer);
382   renderTask.SetCameraActor( cameraActor );
383   renderTask.SetClearColor( Color::TRANSPARENT );
384   renderTask.SetClearEnabled( true );
385   renderTask.SetRefreshRate(RenderTask::REFRESH_ONCE);
386
387   return framebuffer;
388 }
389
390 void NewWindowController::SetUpBubbleEmission( const Vector2& emitPosition, const Vector2& direction)
391 {
392   if( mNeedNewAnimation )
393   {
394     float duration = Random::Range(1.f, 1.5f);
395     mEmitAnimation = Animation::New( duration );
396     mNeedNewAnimation = false;
397     mAnimateComponentCount = 0;
398   }
399
400   mEmitter.EmitBubble( mEmitAnimation, emitPosition, direction, Vector2(10,10) );
401
402   mAnimateComponentCount++;
403
404   if( mAnimateComponentCount % 6 ==0 )
405   {
406     mEmitAnimation.Play();
407     mNeedNewAnimation = true;
408   }
409 }
410
411 Geometry NewWindowController::CreateMeshGeometry()
412 {
413   // Create vertices and specify their color
414   struct Vertex
415   {
416     Vector3 position;
417     Vector2 textureCoordinates;
418     Vector3 color;
419   };
420
421   Vertex vertexData[5] = {
422     { Vector3(  0.0f,  0.0f, 0.5f ), Vector2(0.5f, 0.5f), Vector3(1.0f, 1.0f, 1.0f) },
423     { Vector3( -0.5f, -0.5f, 0.0f ), Vector2(0.0f, 0.0f), Vector3(1.0f, 0.0f, 0.0f) },
424     { Vector3(  0.5f, -0.5f, 0.0f ), Vector2(1.0f, 0.0f), Vector3(1.0f, 1.0f, 0.0f) },
425     { Vector3( -0.5f,  0.5f, 0.0f ), Vector2(0.0f, 1.0f), Vector3(0.0f, 1.0f, 0.0f) },
426     { Vector3(  0.5f,  0.5f, 0.0f ), Vector2(1.0f, 1.0f), Vector3(0.0f, 0.0f, 1.0f) }  };
427
428   Property::Map vertexFormat;
429   vertexFormat["aPosition"] = Property::VECTOR3;
430   vertexFormat["aTexCoord"] = Property::VECTOR2;
431   vertexFormat["aColor"] = Property::VECTOR3;
432   PropertyBuffer vertices = PropertyBuffer::New( vertexFormat, 5 );
433   vertices.SetData( vertexData );
434
435   // Specify all the faces
436   unsigned int indexData[12] = { 0,1,3,0,2,4,0,3,4,0,2,1 };
437   Property::Map indexFormat;
438   indexFormat["indices"] = Property::UNSIGNED_INTEGER;
439   PropertyBuffer indices = PropertyBuffer::New( indexFormat, 12 );
440   indices.SetData( indexData );
441
442   // Create the geometry object
443   Geometry geometry = Geometry::New();
444   geometry.AddVertexBuffer( vertices );
445   geometry.SetIndexBuffer( indices );
446
447   return geometry;
448 }
449
450 ShaderEffect NewWindowController::CreateColorModifierer( const Vector3& rgbDelta )
451 {
452  std::string fragmentShader = MAKE_SHADER(
453    precision highp float;\n
454    uniform vec3 uRGBDelta;\n
455    uniform float uIgnoreAlpha;\n
456    float rand(vec2 co) \n
457    {\n
458      return fract(sin(dot(co.xy ,vec2(12.9898,78.233))) * 43758.5453); \n}
459    \n
460    void main() {\n
461      vec4 color = texture2D(sTexture, vTexCoord); \n
462      // modify the hsv Value
463      color.rgb += uRGBDelta * rand(vTexCoord); \n
464      // if the new vale exceeds one, then decrease it
465      color.rgb -= max(color.rgb*2.0 - vec3(2.0), 0.0);\n
466      // if the new vale drops below zero, then increase it
467      color.rgb -= min(color.rgb*2.0, 0.0);\n
468      gl_FragColor = color; \n
469    }\n
470  );
471
472  ShaderEffect shaderEffect = ShaderEffect::New("", fragmentShader);
473  shaderEffect.SetUniform( "uRGBDelta", rgbDelta );
474
475  return shaderEffect;
476 }
477
478 void NewWindowController::NewWindow(void)
479 {
480   PositionSize posSize(0, 0, 720, 1280);
481   gApplication.ReplaceWindow(posSize, "NewWindow"); // Generates a new window
482 }
483
484 bool NewWindowController::OnLoseContextButtonClicked( Toolkit::Button button )
485 {
486   // Add as an idle callback to avoid ProcessEvents being recursively called.
487   mApplication.AddIdle( MakeCallback( NewWindowController::NewWindow ) );
488   return true;
489 }
490
491 bool NewWindowController::OnTrackTimerTick()
492 {
493   static int time=0;
494   const float radius(250.0f);
495
496   time += EMIT_INTERVAL_IN_MS;
497   float modTime = time / TRACK_DURATION_IN_MS;
498   float angle = 2.0f*Math::PI*modTime;
499
500   Vector2 position(radius*cosf(angle), radius*-sinf(angle));
501   Vector2 aimPos(radius*2*sinf(angle), radius*2*-cosf(angle));
502   Vector2 direction = aimPos-position;
503   Vector2 stageSize = Stage::GetCurrent().GetSize();
504
505   SetUpBubbleEmission( stageSize*0.5f+position, direction );
506   SetUpBubbleEmission( stageSize*0.5f+position*0.75f, direction );
507   SetUpBubbleEmission( stageSize*0.5f+position*0.7f, direction );
508
509   return true;
510 }
511
512 void NewWindowController::OnKeyEvent(const KeyEvent& event)
513 {
514   if(event.state == KeyEvent::Down)
515   {
516     if( IsKey( event, Dali::DALI_KEY_ESCAPE) || IsKey( event, Dali::DALI_KEY_BACK) )
517     {
518       mApplication.Quit();
519     }
520   }
521 }
522
523 void NewWindowController::OnContextLost()
524 {
525   printf("Stage reporting context loss\n");
526 }
527
528 void NewWindowController::OnContextRegained()
529 {
530   printf("Stage reporting context regain\n");
531 }
532
533 void RunTest(Application& app)
534 {
535   gNewWindowController = new NewWindowController(app);
536   app.MainLoop(Configuration::APPLICATION_DOES_NOT_HANDLE_CONTEXT_LOSS);
537 }
538
539 // Entry point for Linux & Tizen applications
540 //
541 int main(int argc, char **argv)
542 {
543   gApplication = Application::New(&argc, &argv, DALI_DEMO_THEME_PATH);
544   RunTest(gApplication);
545
546   return 0;
547 }