Merge branch 'devel/master' into tizen 61/137161/1
authorJinho, Lee <jeano.lee@samsung.com>
Tue, 4 Jul 2017 12:52:03 +0000 (21:52 +0900)
committerJinho, Lee <jeano.lee@samsung.com>
Tue, 4 Jul 2017 12:52:12 +0000 (21:52 +0900)
Change-Id: Ie31341e5982d1a9af4507e9659ba08fe5cf20369

127 files changed:
README.md
adaptors/base/combined-update-render/combined-update-render-controller.cpp
adaptors/base/combined-update-render/combined-update-render-controller.h
adaptors/base/environment-options.cpp
adaptors/base/environment-options.h
adaptors/base/environment-variables.h
adaptors/base/separate-update-render/render-thread.cpp
adaptors/base/single-threaded/single-thread-controller.cpp
adaptors/base/single-threaded/single-thread-controller.h
adaptors/common/adaptor-impl.cpp
adaptors/common/adaptor-impl.h
adaptors/common/adaptor.cpp
adaptors/common/application-impl.cpp
adaptors/common/application-impl.h
adaptors/common/bitmap-loader-impl.cpp [deleted file]
adaptors/common/bitmap-loader-impl.h [deleted file]
adaptors/common/file.list
adaptors/common/gl/egl-implementation.h
adaptors/common/pixel-buffer-impl.cpp [new file with mode: 0644]
adaptors/common/pixel-buffer-impl.h [new file with mode: 0644]
adaptors/common/video-player-impl.cpp
adaptors/common/video-player-impl.h
adaptors/common/window-impl.h
adaptors/devel-api/adaptor-framework/application-devel.cpp [moved from adaptors/emscripten/wrappers/property-buffer-wrapper.cpp with 50% similarity]
adaptors/devel-api/adaptor-framework/application-devel.h [new file with mode: 0644]
adaptors/devel-api/adaptor-framework/bitmap-loader.cpp [deleted file]
adaptors/devel-api/adaptor-framework/bitmap-loader.h [deleted file]
adaptors/devel-api/adaptor-framework/image-loading.cpp
adaptors/devel-api/adaptor-framework/image-loading.h
adaptors/devel-api/adaptor-framework/pixel-buffer.cpp [new file with mode: 0644]
adaptors/devel-api/adaptor-framework/pixel-buffer.h [new file with mode: 0644]
adaptors/devel-api/adaptor-framework/video-player-plugin.h
adaptors/devel-api/adaptor-framework/video-player.cpp
adaptors/devel-api/adaptor-framework/video-player.h
adaptors/devel-api/adaptor-framework/window-devel.cpp
adaptors/devel-api/adaptor-framework/window-devel.h
adaptors/devel-api/file.list
adaptors/ecore/wayland/key-grab-ecore-wl.cpp [changed mode: 0644->0755]
adaptors/ecore/wayland/window-impl-ecore-wl.cpp
adaptors/ecore/wayland/window-render-surface-ecore-wl.cpp
adaptors/ecore/wayland/window-render-surface.h
adaptors/emscripten/egl-implementation-emscripten.cpp [deleted file]
adaptors/emscripten/main.cpp [deleted file]
adaptors/emscripten/sdl-application.cpp [deleted file]
adaptors/emscripten/sdl-application.h [deleted file]
adaptors/emscripten/sdl-gesture-manager.h [deleted file]
adaptors/emscripten/sdl-gl-sync-abstraction.cpp [deleted file]
adaptors/emscripten/sdl-gl-sync-abstraction.h [deleted file]
adaptors/emscripten/sdl-render-controller.h [deleted file]
adaptors/emscripten/wrappers/actor-wrapper.cpp [deleted file]
adaptors/emscripten/wrappers/actor-wrapper.h [deleted file]
adaptors/emscripten/wrappers/animation-wrapper.cpp [deleted file]
adaptors/emscripten/wrappers/animation-wrapper.h [deleted file]
adaptors/emscripten/wrappers/dali-wrapper.cpp [deleted file]
adaptors/emscripten/wrappers/dali-wrapper.js [deleted file]
adaptors/emscripten/wrappers/emscripten-utils.cpp [deleted file]
adaptors/emscripten/wrappers/emscripten-utils.h [deleted file]
adaptors/emscripten/wrappers/geometry-wrapper.cpp [deleted file]
adaptors/emscripten/wrappers/geometry-wrapper.h [deleted file]
adaptors/emscripten/wrappers/handle-wrapper.cpp [deleted file]
adaptors/emscripten/wrappers/handle-wrapper.h [deleted file]
adaptors/emscripten/wrappers/image-wrapper.cpp [deleted file]
adaptors/emscripten/wrappers/image-wrapper.h [deleted file]
adaptors/emscripten/wrappers/property-buffer-wrapper.h [deleted file]
adaptors/emscripten/wrappers/property-value-wrapper.cpp [deleted file]
adaptors/emscripten/wrappers/property-value-wrapper.h [deleted file]
adaptors/emscripten/wrappers/render-task-wrapper.cpp [deleted file]
adaptors/emscripten/wrappers/render-task-wrapper.h [deleted file]
adaptors/emscripten/wrappers/signal-holder.h [deleted file]
adaptors/emscripten/wrappers/tests/README.TXT [deleted file]
adaptors/emscripten/wrappers/tests/all.html [deleted file]
adaptors/emscripten/wrappers/tests/animation.js [deleted file]
adaptors/emscripten/wrappers/tests/dali-page.html [deleted file]
adaptors/emscripten/wrappers/tests/dali-tests.css [deleted file]
adaptors/emscripten/wrappers/tests/dali-tests.html [deleted file]
adaptors/emscripten/wrappers/tests/geometry.js [deleted file]
adaptors/emscripten/wrappers/tests/math.js [deleted file]
adaptors/emscripten/wrappers/tests/properties.js [deleted file]
adaptors/emscripten/wrappers/tests/qunit/qunit-1.21.0.css [deleted file]
adaptors/emscripten/wrappers/tests/qunit/qunit-1.21.0.js [deleted file]
adaptors/emscripten/wrappers/tests/shaders.js [deleted file]
adaptors/emscripten/wrappers/tests/signals.js [deleted file]
adaptors/emscripten/wrappers/tests/utilities.js [deleted file]
adaptors/emscripten/wrappers/tests/views.js [deleted file]
adaptors/emscripten/wrappers/type-info-wrapper.cpp [deleted file]
adaptors/emscripten/wrappers/type-info-wrapper.h [deleted file]
adaptors/integration-api/adaptor.h
adaptors/public-api/adaptor-framework/application.cpp
adaptors/public-api/dali-adaptor-version.cpp
adaptors/tizen/key-grab.h [changed mode: 0644->0755]
adaptors/wayland/window-impl-wl.cpp
adaptors/wearable/watch-application-impl.cpp
adaptors/x11/window-impl-x.cpp
automated-tests/execute.sh
automated-tests/src/dali-adaptor-internal/CMakeLists.txt
automated-tests/src/dali-adaptor-internal/utc-Dali-Internal-PixelBuffer.cpp [new file with mode: 0644]
automated-tests/src/dali-adaptor/CMakeLists.txt
automated-tests/src/dali-adaptor/utc-Dali-BitmapLoader.cpp [deleted file]
automated-tests/src/dali-adaptor/utc-Dali-ImageLoading.cpp
automated-tests/src/dali-adaptor/utc-Dali-PixelBuffer.cpp [new file with mode: 0644]
build/emscripten/.gitignore [deleted file]
build/emscripten/CMakeLists.txt [deleted file]
build/emscripten/build.sh [deleted file]
build/tizen/adaptor/Makefile.am
build/tizen/plugins/Makefile.am
build/tizen/plugins/configure.ac
packaging/dali-adaptor.spec
platform-abstractions/emscripten/emscripten-callbacks.cpp [deleted file]
platform-abstractions/emscripten/emscripten-callbacks.h [deleted file]
platform-abstractions/emscripten/emscripten-platform-abstraction.cpp [deleted file]
platform-abstractions/emscripten/emscripten-platform-abstraction.h [deleted file]
platform-abstractions/emscripten/file.list [deleted file]
platform-abstractions/portable/alpha-mask.cpp [new file with mode: 0644]
platform-abstractions/portable/alpha-mask.h [new file with mode: 0644]
platform-abstractions/portable/image-operations.cpp
platform-abstractions/portable/pixel-manipulation.cpp [new file with mode: 0644]
platform-abstractions/portable/pixel-manipulation.h [new file with mode: 0644]
platform-abstractions/tizen/file.list
plugins/dali-feedback.cpp
plugins/dali-feedback.h
plugins/video-player/tizen-video-player.cpp
plugins/video-player/tizen-video-player.h
text/dali/devel-api/text-abstraction/script.cpp
text/dali/devel-api/text-abstraction/script.h
text/dali/internal/text-abstraction/shaping-impl.cpp
third-party/image-resampler/resampler.cpp
third-party/image-resampler/resampler.h

index d415a76..691f4ab 100644 (file)
--- a/README.md
+++ b/README.md
          * [Building and executing test cases](#building-and-executing-test-cases)
       * [2. GBS Builds](#2-gbs-builds)
          * [DEBUG Builds](#debug-builds)
-      * [3. Building for Emscripten](#3-building-for-emscripten)
-         * [Setup dali-env &amp; build dali-core](#setup-dali-env--build-dali-core)
-         * [Build the minimal dali-adaptor](#build-the-minimal-dali-adaptor)
-         * [Using the Javascript Build](#using-the-javascript-build)
 
 # Build Instructions
 
@@ -62,33 +58,3 @@ See the README.md in dali-adaptor/automated-tests.
 
          $ gbs build -A [TARGET_ARCH] --define "%enable_debug 1"
 
-## 3. Building for Emscripten
-
-Currently the build for emscripten uses a minimal adaptor which does not support dali-toolkit.
-
-### Setup dali-env & build dali-core
-
- The build requires the Emscripten SDK, this is installed automatically by running dali_env with the correct parameters.
- dali_env is part of the dali-core repository.
- Please see the README within dali-core to setup dali_env and build dali-core.
-
-### Build the minimal dali-adaptor
-
-  Use the build.sh script build adaptor.
-  This uses emscriptens emcc to compile byte code to javascript (full OpenGL ES support with stb-image loading library and cpp bindings).
-  Note: Please view the build.sh script for debug build options.
-
-         $ # cd ./build/emscripten
-         $ # ./build.sh
-
-### Using the Javascript Build
-
- The build will create 1 main Javascript artifact, and its html counterpart; dali-emscripten.js
-
- This is required by any dali JS app, and must be located in the same directory as the app JS in order for the browser to find it.
-
- After the build, the necessary artifacts (which include dali-wrapper.js) will be placed in the dali-env directory under opt/share/emscripten:
-
- dali-env/opt/share/emscripten
-
- If dali-demo is built, any JS examples will also be placed in this directory, so they are ready to run.
index 5f9e700..715053f 100644 (file)
@@ -376,8 +376,10 @@ void CombinedUpdateRenderController::UpdateRenderThread()
 
   bool useElapsedTime = true;
   bool updateRequired = true;
+  uint64_t timeToSleepUntil = 0;
+  int extraFramesDropped = 0;
 
-  while( UpdateRenderReady( useElapsedTime, updateRequired ) )
+  while( UpdateRenderReady( useElapsedTime, updateRequired, timeToSleepUntil ) )
   {
     LOG_UPDATE_RENDER_TRACE;
 
@@ -422,8 +424,8 @@ void CombinedUpdateRenderController::UpdateRenderThread()
     if( useElapsedTime )
     {
       // If using the elapsed time, then calculate frameDelta as a multiple of mDefaultFrameDelta
-      // Round up if remainder is more than half the default frame time
-      noOfFramesSinceLastUpdate = ( timeSinceLastFrame + mDefaultHalfFrameNanoseconds) / mDefaultFrameDurationNanoseconds;
+      noOfFramesSinceLastUpdate += extraFramesDropped;
+
       frameDelta = mDefaultFrameDelta * noOfFramesSinceLastUpdate;
     }
     LOG_UPDATE_RENDER( "timeSinceLastFrame(%llu) noOfFramesSinceLastUpdate(%u) frameDelta(%.6f)", timeSinceLastFrame, noOfFramesSinceLastUpdate, frameDelta );
@@ -459,7 +461,10 @@ void CombinedUpdateRenderController::UpdateRenderThread()
     mCore.Render( renderStatus );
     AddPerformanceMarker( PerformanceInterface::RENDER_END );
 
-    mRenderHelper.PostRender();
+    if( renderStatus.NeedsPostRender() )
+    {
+      mRenderHelper.PostRender();
+    }
 
     // Trigger event thread to request Update/Render thread to sleep if update not required
     if( ( Integration::KeepUpdating::NOT_REQUESTED == keepUpdatingStatus ) &&
@@ -478,8 +483,40 @@ void CombinedUpdateRenderController::UpdateRenderThread()
     // FRAME TIME
     //////////////////////////////
 
+    extraFramesDropped = 0;
+
+    if (timeToSleepUntil == 0)
+    {
+      // If this is the first frame after the thread is initialized or resumed, we
+      // use the actual time the current frame starts from to calculate the time to
+      // sleep until the next frame.
+      timeToSleepUntil = currentFrameStartTime + mDefaultFrameDurationNanoseconds;
+    }
+    else
+    {
+      // Otherwise, always use the sleep-until time calculated in the last frame to
+      // calculate the time to sleep until the next frame. In this way, if there is
+      // any time gap between the current frame and the next frame, or if update or
+      // rendering in the current frame takes too much time so that the specified
+      // sleep-until time has already passed, it will try to keep the frames syncing
+      // by shortening the duration of the next frame.
+      timeToSleepUntil += mDefaultFrameDurationNanoseconds;
+
+      // Check the current time at the end of the frame
+      uint64_t currentFrameEndTime = 0;
+      TimeService::GetNanoseconds( currentFrameEndTime );
+      while ( currentFrameEndTime > timeToSleepUntil + mDefaultFrameDurationNanoseconds )
+      {
+         // We are more than one frame behind already, so just drop the next frames
+         // until the sleep-until time is later than the current time so that we can
+         // catch up.
+         timeToSleepUntil += mDefaultFrameDurationNanoseconds;
+         extraFramesDropped++;
+      }
+    }
+
     // Sleep until at least the the default frame duration has elapsed. This will return immediately if the specified end-time has already passed.
-    TimeService::SleepUntil( currentFrameStartTime + mDefaultFrameDurationNanoseconds );
+    TimeService::SleepUntil( timeToSleepUntil );
   }
 
   // Inform core of context destruction & shutdown EGL
@@ -492,7 +529,7 @@ void CombinedUpdateRenderController::UpdateRenderThread()
   mEnvironmentOptions.UnInstallLogFunction();
 }
 
-bool CombinedUpdateRenderController::UpdateRenderReady( bool& useElapsedTime, bool updateRequired )
+bool CombinedUpdateRenderController::UpdateRenderReady( bool& useElapsedTime, bool updateRequired, uint64_t& timeToSleepUntil )
 {
   useElapsedTime = true;
 
@@ -507,6 +544,11 @@ bool CombinedUpdateRenderController::UpdateRenderReady( bool& useElapsedTime, bo
     LOG_UPDATE_RENDER( "      mDestroyUpdateRenderThread:  %d", mDestroyUpdateRenderThread );
     LOG_UPDATE_RENDER( "      mNewSurface:                 %d", mNewSurface );
 
+    // Reset the time when the thread is waiting, so the sleep-until time for
+    // the first frame after resuming should be based on the actual start time
+    // of the first frame.
+    timeToSleepUntil = 0;
+
     mUpdateRenderThreadWaitCondition.Wait( updateLock );
 
     if( ! mUseElapsedTimeAfterWait )
index 9179c6b..6f409cf 100644 (file)
@@ -192,12 +192,13 @@ private:
   /**
    * Called by the Update/Render Thread which ensures a wait if required.
    *
-   * @param[out] useElapsedTime  If true when returned, then the actual elapsed time will be used for animation.
-   *                             If false when returned, then there should NOT be any animation progression in the next Update.
-   * @param[in]  updateRequired  Whether another update is required.
+   * @param[out] useElapsedTime    If true when returned, then the actual elapsed time will be used for animation.
+   *                               If false when returned, then there should NOT be any animation progression in the next Update.
+   * @param[in]  updateRequired    Whether another update is required.
+   * @param[out] timeToSleepUntil  The time remaining in nanoseconds to keep the thread sleeping before resuming.
    * @return false, if the thread should stop.
    */
-  bool UpdateRenderReady( bool& useElapsedTime, bool updateRequired );
+  bool UpdateRenderReady( bool& useElapsedTime, bool updateRequired, uint64_t& timeToSleepUntil );
 
   /**
    * Checks to see if the surface needs to be replaced.
index 0dbf614..806c428 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2017 Samsung Electronics Co., Ltd.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -108,6 +108,7 @@ EnvironmentOptions::EnvironmentOptions()
   mRenderRefreshRate( 1 ),
   mGlesCallAccumulate( false ),
   mMultiSamplingLevel( 0 ),
+  mMaxTextureSize( 0 ),
   mLogFunction( NULL )
 {
   ParseEnvironmentOptions();
@@ -259,6 +260,11 @@ unsigned int EnvironmentOptions::GetMultiSamplingLevel() const
   return mMultiSamplingLevel;
 }
 
+unsigned int EnvironmentOptions::GetMaxTextureSize() const
+{
+  return mMaxTextureSize;
+}
+
 bool EnvironmentOptions::PerformanceServerRequired() const
 {
   return ( ( GetPerformanceStatsLoggingOptions() > 0) ||
@@ -411,6 +417,15 @@ void EnvironmentOptions::ParseEnvironmentOptions()
       mMultiSamplingLevel = multiSamplingLevel;
     }
   }
+
+  int maxTextureSize( 0 );
+  if( GetIntegerEnvironmentVariable( DALI_ENV_MAX_TEXTURE_SIZE, maxTextureSize ) )
+  {
+    if( maxTextureSize > 0 )
+    {
+      mMaxTextureSize = maxTextureSize;
+    }
+  }
 }
 
 } // Adaptor
index dacaa11..2ab19a9 100644 (file)
@@ -2,7 +2,7 @@
 #define __DALI_INTERNAL_ADAPTOR_ENVIRONMENT_OPTIONS_H__
 
 /*
- * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2017 Samsung Electronics Co., Ltd.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -208,6 +208,11 @@ public:
    */
   unsigned int GetMultiSamplingLevel() const;
 
+  /**
+   * @return The maximum texture size
+   */
+  unsigned int GetMaxTextureSize() const;
+
 private: // Internal
 
   /**
@@ -244,6 +249,7 @@ private: // Data
   unsigned int mRenderRefreshRate;                ///< render refresh rate
   bool mGlesCallAccumulate;                       ///< Whether or not to accumulate gles call statistics
   unsigned int mMultiSamplingLevel;               ///< The number of samples required in multisample buffers
+  unsigned int mMaxTextureSize;                   ///< The maximum texture size that GL can handle
 
   Dali::Integration::Log::LogFunction mLogFunction;
 
index fa010f9..53fe21b 100644 (file)
@@ -2,7 +2,7 @@
 #define __DALI_INTERNAL_ADAPTOR_ENVIRONMENT_VARIABLES_H__
 
 /*
- * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2017 Samsung Electronics Co., Ltd.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -95,6 +95,8 @@ namespace Adaptor
 
 #define DALI_ENV_MULTI_SAMPLING_LEVEL "DALI_MULTI_SAMPLING_LEVEL"
 
+#define DALI_ENV_MAX_TEXTURE_SIZE "DALI_MAX_TEXTURE_SIZE"
+
 } // namespace Adaptor
 
 } // namespace Internal
index e31a98b..5d57c9e 100644 (file)
@@ -139,8 +139,11 @@ bool RenderThread::Run()
         mThreadSynchronization.RenderFinished();
 
         // Perform any post-render operations
-        DALI_LOG_INFO( gRenderLogFilter, Debug::Verbose, "RenderThread::Run. 4 - PostRender()\n");
-        mRenderHelper.PostRender();
+        if( renderStatus.NeedsPostRender() )
+        {
+          DALI_LOG_INFO( gRenderLogFilter, Debug::Verbose, "RenderThread::Run. 4 - PostRender()\n");
+          mRenderHelper.PostRender();
+        }
       }
     }
 
index b5905b6..e24429a 100644 (file)
@@ -176,10 +176,7 @@ void SingleThreadController::RequestUpdateOnce()
     Integration::UpdateStatus status;
     mCore.Update( 0.0f, mLastUpdateRenderTime, mLastUpdateRenderTime + mRefreshRate * MILLISECONDS_PER_FRAME, status );
 
-    Integration::RenderStatus renderStatus;
-    mRenderHelper.PreRender();
-    mCore.Render( renderStatus );
-    mRenderHelper.PostRender();
+    Render();
   }
 }
 
@@ -258,17 +255,10 @@ void SingleThreadController::UpdateRender( bool incrementTime )
   if( mState != State::STOPPED )
   {
     mRenderHelper.ConsumeEvents();
-    mRenderHelper.PreRender();
-
-    Integration::RenderStatus renderStatus;
-    AddPerformanceMarker( PerformanceInterface::RENDER_START );
-    mCore.Render( renderStatus );
-    AddPerformanceMarker( PerformanceInterface::RENDER_END );
 
-    mRenderHelper.PostRender();
+    const bool needsUpdate = Render();
 
-    if( ! keepUpdatingStatus &&
-        ! renderStatus.NeedsUpdate() )
+    if( !keepUpdatingStatus && !needsUpdate )
     {
       ChangeState( State::SLEEPING );
     }
@@ -337,6 +327,23 @@ void SingleThreadController::StopRendering()
   mRenderHelper.ShutdownEgl();
 }
 
+bool SingleThreadController::Render()
+{
+  mRenderHelper.PreRender();
+
+  Integration::RenderStatus renderStatus;
+  AddPerformanceMarker( PerformanceInterface::RENDER_START );
+  mCore.Render( renderStatus );
+  AddPerformanceMarker( PerformanceInterface::RENDER_END );
+
+  if( renderStatus.NeedsPostRender() )
+  {
+    mRenderHelper.PostRender();
+  }
+
+  return renderStatus.NeedsUpdate();
+}
+
 } // namespace Adaptor
 
 } // namespace Internal
index e5bf676..01dbdb1 100644 (file)
@@ -166,6 +166,12 @@ private:
    */
   void StopRendering();
 
+  /**
+   * Runs render (along with pre & post steps as required).
+   * @return True if an update is required.
+   */
+  bool Render();
+
 private:
 
   Dali::Timer                       mTimer;                           ///< Ensures an update & render is run every frame.
index a3dc3ee..70f65ad 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2016 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2017 Samsung Electronics Co., Ltd.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -29,7 +29,7 @@
 
 // INTERNAL INCLUDES
 #include <base/thread-controller.h>
-#  include <base/performance-logging/performance-interface-factory.h>
+#include <base/performance-logging/performance-interface-factory.h>
 #include <base/lifecycle-observer.h>
 
 #include <dali/devel-api/text-abstraction/font-client.h>
@@ -53,6 +53,7 @@
 #include <window-impl.h>
 
 #include <tizen-logging.h>
+#include <image-loading.h>
 
 using Dali::TextAbstraction::FontClient;
 
@@ -183,6 +184,12 @@ void Adaptor::Initialize( Dali::Configuration::ContextLoss configuration )
   {
     Integration::SetPanGestureSmoothingAmount(mEnvironmentOptions->GetPanGestureSmoothingAmount());
   }
+
+  // Set max texture size
+  if( mEnvironmentOptions->GetMaxTextureSize() > 0 )
+  {
+    Dali::SetMaxTextureSize( mEnvironmentOptions->GetMaxTextureSize() );
+  }
 }
 
 Adaptor::~Adaptor()
@@ -385,39 +392,6 @@ void Adaptor::FeedKeyEvent( KeyEvent& keyEvent )
   mEventHandler->FeedKeyEvent( keyEvent );
 }
 
-bool Adaptor::MoveResize( const PositionSize& positionSize )
-{
-  PositionSize old = mSurface->GetPositionSize();
-
-  // just resize the surface. The driver should automatically resize the egl Surface (untested)
-  // EGL Spec says : EGL window surfaces need to be resized when their corresponding native window
-  // is resized. Implementations typically use hooks into the OS and native window
-  // system to perform this resizing on demand, transparently to the client.
-  mSurface->MoveResize( positionSize );
-
-  if(old.width != positionSize.width || old.height != positionSize.height)
-  {
-    SurfaceSizeChanged(positionSize);
-  }
-
-  return true;
-}
-
-void Adaptor::SurfaceResized( const PositionSize& positionSize )
-{
-  PositionSize old = mSurface->GetPositionSize();
-
-  // Called by an application, when it has resized a window outside of Dali.
-  // The EGL driver automatically detects X Window resize calls, and resizes
-  // the EGL surface for us.
-  mSurface->MoveResize( positionSize );
-
-  if(old.width != positionSize.width || old.height != positionSize.height)
-  {
-    SurfaceSizeChanged(positionSize);
-  }
-}
-
 void Adaptor::ReplaceSurface( Any nativeWindow, RenderSurface& surface )
 {
   mNativeWindow = nativeWindow;
@@ -722,10 +696,10 @@ void Adaptor::OnDamaged( const DamageArea& area )
   RequestUpdate();
 }
 
-void Adaptor::SurfaceSizeChanged( const PositionSize& positionSize )
+void Adaptor::SurfaceSizeChanged( Dali::Adaptor::SurfaceSize surfaceSize )
 {
   // let the core know the surface size has changed
-  mCore->SurfaceResized(positionSize.width, positionSize.height);
+  mCore->SurfaceResized( surfaceSize.GetWidth(), surfaceSize.GetHeight() );
 
   mResizedSignal.Emit( mAdaptor );
 }
index 4cbbdc2..425bfcf 100644 (file)
@@ -2,7 +2,7 @@
 #define __DALI_INTERNAL_ADAPTOR_IMPL_H__
 
 /*
- * Copyright (c) 2016 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2017 Samsung Electronics Co., Ltd.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -184,16 +184,6 @@ public: // AdaptorInternalServices implementation
   virtual void FeedKeyEvent( KeyEvent& keyEvent );
 
   /**
-   * @copydoc AdaptorInterface::MoveResize()
-   */
-  virtual bool MoveResize( const PositionSize& positionSize );
-
-  /**
-   * @copydoc AdaptorInterface::SurfaceResized()
-   */
-  virtual void SurfaceResized( const PositionSize& positionSize );
-
-  /**
    * @copydoc AdaptorInterface::ReplaceSurface()
    */
   virtual void ReplaceSurface( Any nativeWindow, RenderSurface& surface );
@@ -348,7 +338,7 @@ public:
   /**
    * Informs core the surface size has changed
    */
-  void SurfaceSizeChanged( const PositionSize& positionSize );
+  void SurfaceSizeChanged( Dali::Adaptor::SurfaceSize surfaceSize );
 
 public:  //AdaptorInternalServices
 
index 3e96cf1..a6810c7 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2016 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2017 Samsung Electronics Co., Ltd.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -184,9 +184,9 @@ void Adaptor::SetStereoBase(  float stereoBase )
   mImpl->SetStereoBase( stereoBase );
 }
 
-void Adaptor::SurfaceSizeChanged( const PositionSize& positionSize )
+void Adaptor::SurfaceSizeChanged( SurfaceSize surfaceSize )
 {
-  mImpl->SurfaceSizeChanged( positionSize );
+  mImpl->SurfaceSizeChanged( surfaceSize );
 }
 
 Adaptor::Adaptor()
index c949758..cd05c95 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2016 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2017 Samsung Electronics Co., Ltd.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -53,14 +53,15 @@ ApplicationPtr Application::New(
   char **argv[],
   const std::string& stylesheet,
   Dali::Application::WINDOW_MODE windowMode,
+  const PositionSize& positionSize,
   Framework::Type applicationType)
 {
-  ApplicationPtr application ( new Application (argc, argv, stylesheet, windowMode, applicationType ) );
+  ApplicationPtr application ( new Application (argc, argv, stylesheet, windowMode, positionSize, applicationType ) );
   return application;
 }
 
 Application::Application( int* argc, char** argv[], const std::string& stylesheet,
-  Dali::Application::WINDOW_MODE windowMode, Framework::Type applicationType )
+  Dali::Application::WINDOW_MODE windowMode, const PositionSize& positionSize, Framework::Type applicationType )
 : mInitSignal(),
   mTerminateSignal(),
   mPauseSignal(),
@@ -83,6 +84,7 @@ Application::Application( int* argc, char** argv[], const std::string& styleshee
   mName(),
   mStylesheet( stylesheet ),
   mEnvironmentOptions(),
+  mWindowPositionSize( positionSize ),
   mSlotDelegate( this )
 {
   // Get mName from environment options
@@ -110,21 +112,24 @@ Application::~Application()
 
 void Application::CreateWindow()
 {
-  PositionSize windowPosition(0, 0, 0, 0);  // this will use full screen
-
-  if( mCommandLineOptions->stageWidth > 0 && mCommandLineOptions->stageHeight > 0 )
-  {
-    // Command line options override environment options and full screen
-    windowPosition = PositionSize( 0, 0, mCommandLineOptions->stageWidth, mCommandLineOptions->stageHeight );
-  }
-  else if( mEnvironmentOptions.GetWindowWidth() && mEnvironmentOptions.GetWindowHeight() )
+  if( mWindowPositionSize.width == 0 && mWindowPositionSize.height == 0 )
   {
-    // Environment options override full screen functionality if command line arguments not provided
-    windowPosition = PositionSize( 0, 0, mEnvironmentOptions.GetWindowWidth(), mEnvironmentOptions.GetWindowHeight() );
+    if( mCommandLineOptions->stageWidth > 0 && mCommandLineOptions->stageHeight > 0 )
+    {
+      // Command line options override environment options and full screen
+      mWindowPositionSize.width = mCommandLineOptions->stageWidth;
+      mWindowPositionSize.height = mCommandLineOptions->stageHeight;
+    }
+    else if( mEnvironmentOptions.GetWindowWidth() && mEnvironmentOptions.GetWindowHeight() )
+    {
+      // Environment options override full screen functionality if command line arguments not provided
+      mWindowPositionSize.width = mEnvironmentOptions.GetWindowWidth();
+      mWindowPositionSize.height = mEnvironmentOptions.GetWindowHeight();
+    }
   }
 
   const std::string& windowClassName = mEnvironmentOptions.GetWindowClassName();
-  mWindow = Dali::Window::New( windowPosition, mName, windowClassName, mWindowMode == Dali::Application::TRANSPARENT );
+  mWindow = Dali::Window::New( mWindowPositionSize, mName, windowClassName, mWindowMode == Dali::Application::TRANSPARENT );
 
   // Quit the application when the window is closed
   GetImplementation( mWindow ).DeleteRequestSignal().Connect( mSlotDelegate, &Application::Quit );
@@ -370,18 +375,19 @@ float Application::GetStereoBase() const
 }
 
 
-void Application::ReplaceWindow(PositionSize windowPosition, const std::string& name)
+void Application::ReplaceWindow( const PositionSize& positionSize, const std::string& name )
 {
-  Dali::Window newWindow = Dali::Window::New( windowPosition, name, mWindowMode == Dali::Application::TRANSPARENT );
+  Dali::Window newWindow = Dali::Window::New( positionSize, name, mWindowMode == Dali::Application::TRANSPARENT );
   Window& windowImpl = GetImplementation(newWindow);
   windowImpl.SetAdaptor(*mAdaptor);
   newWindow.ShowIndicator(Dali::Window::INVISIBLE);
   Dali::RenderSurface* renderSurface = windowImpl.GetSurface();
 
   Any nativeWindow = newWindow.GetNativeHandle();
-  Internal::Adaptor::Adaptor::GetImplementation( *mAdaptor ).SurfaceSizeChanged( windowPosition );
+  Internal::Adaptor::Adaptor::GetImplementation( *mAdaptor ).SurfaceSizeChanged( Dali::Adaptor::SurfaceSize( positionSize.width, positionSize.height ) );
   Internal::Adaptor::Adaptor::GetImplementation( *mAdaptor ).ReplaceSurface(nativeWindow, *renderSurface);
   mWindow = newWindow;
+  mWindowPositionSize = positionSize;
 }
 
 std::string Application::GetResourcePath()
index 4af4577..509cb54 100644 (file)
@@ -2,7 +2,7 @@
 #define __DALI_INTERNAL_APPLICATION_H__
 
 /*
- * Copyright (c) 2016 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2017 Samsung Electronics Co., Ltd.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -60,14 +60,15 @@ public:
 
   /**
    * Create a new application
-   * @param[in]  argc        A pointer to the number of arguments
-   * @param[in]  argv        A pointer to the argument list
-   * @param[in]  stylesheet  The path to user defined theme file
-   * @param[in]  windowMode  A member of Dali::Application::WINDOW_MODE
+   * @param[in]  argc         A pointer to the number of arguments
+   * @param[in]  argv         A pointer to the argument list
+   * @param[in]  stylesheet   The path to user defined theme file
+   * @param[in]  windowMode   A member of Dali::Application::WINDOW_MODE
+   * @param[in]  positionSize A position and a size of the window
    * @param[in]  applicationType  A member of Dali::Framework::Type
    */
   static ApplicationPtr New( int* argc, char **argv[], const std::string& stylesheet,
-    WINDOW_MODE windowMode, Framework::Type applicationType );
+    WINDOW_MODE windowMode, const PositionSize& positionSize, Framework::Type applicationType );
 
 public:
 
@@ -104,7 +105,7 @@ public:
   /**
    * @copydoc Dali::Application::ReplaceWindow();
    */
-  void ReplaceWindow(PositionSize windowPosition, const std::string& name);
+  void ReplaceWindow( const PositionSize& positionSize, const std::string& name);
 
   /**
    * @copydoc Dali::Application::GetResourcePath();
@@ -287,13 +288,15 @@ protected:
 
   /**
    * Private Constructor
-   * @param[in]  argc        A pointer to the number of arguments
-   * @param[in]  argv        A pointer to the argument list
-   * @param[in]  stylesheet  The path to user defined theme file
-   * @param[in]  windowMode  A member of Dali::Application::WINDOW_MODE
+   * @param[in]  argc         A pointer to the number of arguments
+   * @param[in]  argv         A pointer to the argument list
+   * @param[in]  stylesheet   The path to user defined theme file
+   * @param[in]  windowMode   A member of Dali::Application::WINDOW_MODE
+   * @param[in]  positionSize A position and a size of the window
+   * @param[in]  applicationType  A member of Dali::Framework::Type
    */
   Application( int* argc, char **argv[], const std::string& stylesheet,
-      WINDOW_MODE windowMode, Framework::Type applicationType );
+      WINDOW_MODE windowMode, const PositionSize& positionSize, Framework::Type applicationType );
 
   /**
    * Destructor
@@ -346,6 +349,7 @@ private:
   std::string                           mName;
   std::string                           mStylesheet;
   EnvironmentOptions                    mEnvironmentOptions;
+  PositionSize                          mWindowPositionSize;
   bool                                  mUseRemoteSurface;
 
   SlotDelegate< Application >           mSlotDelegate;
diff --git a/adaptors/common/bitmap-loader-impl.cpp b/adaptors/common/bitmap-loader-impl.cpp
deleted file mode 100644 (file)
index 9cef7ee..0000000
+++ /dev/null
@@ -1,78 +0,0 @@
-/*
- * Copyright (c) 2014 Samsung Electronics Co., Ltd.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-// EXTERNAL INCLUDES
-#include <string>
-
-// INTERNAL INCLUDES
-#include "image-loading.h"
-#include "bitmap-loader-impl.h"
-
-namespace Dali
-{
-namespace Internal
-{
-
-IntrusivePtr<BitmapLoader> BitmapLoader::New(const std::string& url,
-                                             ImageDimensions size,
-                                             FittingMode::Type fittingMode,
-                                             SamplingMode::Type samplingMode,
-                                             bool orientationCorrection)
-{
-  IntrusivePtr<BitmapLoader> internal = new BitmapLoader( url, size, fittingMode, samplingMode, orientationCorrection );
-  return internal;
-}
-
-BitmapLoader::BitmapLoader(const std::string& url,
-                           ImageDimensions size,
-                           FittingMode::Type fittingMode,
-                           SamplingMode::Type samplingMode,
-                           bool orientationCorrection )
-: mPixelData(),
-  mUrl(url),
-  mSize( size ),
-  mFittingMode( fittingMode ),
-  mSamplingMode( samplingMode ),
-  mOrientationCorrection( orientationCorrection )
-{
-}
-
-BitmapLoader::~BitmapLoader()
-{
-}
-
-void BitmapLoader::Load()
-{
-  mPixelData = Dali::LoadImageFromFile( mUrl, mSize, mFittingMode, mSamplingMode, mOrientationCorrection );
-}
-
-bool BitmapLoader::IsLoaded()
-{
-  return mPixelData ? true : false ;
-}
-
-const std::string& BitmapLoader::GetUrl() const
-{
-  return mUrl;
-}
-
-Dali::PixelData BitmapLoader::GetPixelData() const
-{
-  return mPixelData;
-}
-
-} // namespace Internal
-} // namespace Dali
diff --git a/adaptors/common/bitmap-loader-impl.h b/adaptors/common/bitmap-loader-impl.h
deleted file mode 100644 (file)
index f328889..0000000
+++ /dev/null
@@ -1,120 +0,0 @@
-#ifndef __DALI_BITMAP_LOADER_IMPL_H__
-#define __DALI_BITMAP_LOADER_IMPL_H__
-
-/*
- * Copyright (c) 2014 Samsung Electronics Co., Ltd.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-// EXTERNAL INCLUDES
-#include <string>
-#include <dali/public-api/images/pixel.h>
-#include <dali/public-api/object/base-object.h>
-#include <dali/public-api/common/intrusive-ptr.h>
-#include <dali/integration-api/bitmap.h>
-#include <dali/integration-api/resource-types.h>
-
-// INTERNAL INCLUDES
-#include <bitmap-loader.h>
-
-namespace Dali
-{
-namespace Internal
-{
-
-class BitmapLoader : public BaseObject
-{
-public:
-
-  /**
-   * @copydoc Dali::BitmapLoader::New
-   */
-  static IntrusivePtr<BitmapLoader> New( const std::string& url,
-                                         ImageDimensions size,
-                                         FittingMode::Type fittingMode,
-                                         SamplingMode::Type samplingMode,
-                                         bool orientationCorrection);
-
-  /**
-   * Create the bitmap loader object.
-   */
-   BitmapLoader(const std::string& url,
-               ImageDimensions size,
-               FittingMode::Type fittingMode,
-               SamplingMode::Type samplingMode,
-               bool orientationCorrection);
-
-protected:
-  /**
-   * Destructor
-   */
-  ~BitmapLoader();
-
-public:
-
-  /**
-   * @copydoc Dali::BitmapLoader::Load
-   */
-  void Load();
-
-  /**
-   * @copydoc Dali::BitmapLoader::IsLoaded
-   */
-  bool IsLoaded();
-
-  /**
-   * @copydoc Dali::BitmapLoader::GetUrl()
-   */
-  const std::string& GetUrl() const;
-
-  /**
-   * @copydoc Dali::BitmapLoader::GetPixelData
-   */
-  Dali::PixelData GetPixelData() const;
-
-private:
-
-  Dali::PixelData mPixelData;
-  const std::string mUrl;
-  ImageDimensions mSize;
-  FittingMode::Type mFittingMode;
-  SamplingMode::Type mSamplingMode;
-  bool mOrientationCorrection;
-
-};
-
-} // Internal
-
-
-inline Internal::BitmapLoader& GetImplementation(Dali::BitmapLoader& handle)
-{
-  DALI_ASSERT_ALWAYS( handle && "handle is empty" );
-
-  BaseObject& object = handle.GetBaseObject();
-
-  return static_cast<Internal::BitmapLoader&>(object);
-}
-
-inline const Internal::BitmapLoader& GetImplementation(const Dali::BitmapLoader& handle)
-{
-  DALI_ASSERT_ALWAYS( handle && "handle is empty" );
-
-  const BaseObject& object = handle.GetBaseObject();
-
-  return static_cast<const Internal::BitmapLoader&>(object);
-}
-
-} // Dali
-
-#endif // __DALI_BITMAP_LOADER_IMPL_H__
index af0bebe..af15d62 100644 (file)
@@ -7,7 +7,6 @@ adaptor_common_internal_src_files = \
   $(adaptor_common_dir)/adaptor.cpp \
   $(adaptor_common_dir)/adaptor-impl.cpp \
   $(adaptor_common_dir)/application-impl.cpp \
-  $(adaptor_common_dir)/bitmap-loader-impl.cpp \
   $(adaptor_common_dir)/clipboard-event-notifier-impl.cpp \
   $(adaptor_common_dir)/command-line-options.cpp \
   $(adaptor_common_dir)/drag-and-drop-detector-impl.cpp \
@@ -22,6 +21,7 @@ adaptor_common_internal_src_files = \
   $(adaptor_common_dir)/orientation-impl.cpp  \
   $(adaptor_common_dir)/performance-logger-impl.cpp \
   $(adaptor_common_dir)/physical-keyboard-impl.cpp \
+  $(adaptor_common_dir)/pixel-buffer-impl.cpp \
   $(adaptor_common_dir)/shared-file.cpp \
   $(adaptor_common_dir)/singleton-service-impl.cpp \
   $(adaptor_common_dir)/sound-player-impl.cpp \
index 9cad11e..003af2b 100644 (file)
@@ -2,7 +2,7 @@
 #define __DALI_INTERNAL_EGL_IMPLEMENTATION_H__
 
 /*
- * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2017 Samsung Electronics Co., Ltd.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -179,9 +179,9 @@ private:
   Vector<EGLint>       mContextAttribs;
 
   EGLNativeDisplayType mEglNativeDisplay;
-#ifndef EMSCRIPTEN
+
   EGLNativeWindowType  mEglNativeWindow;
-#endif
+
   EGLNativePixmapType  mCurrentEglNativePixmap;
 
   EGLDisplay           mEglDisplay;
diff --git a/adaptors/common/pixel-buffer-impl.cpp b/adaptors/common/pixel-buffer-impl.cpp
new file mode 100644 (file)
index 0000000..a2b1610
--- /dev/null
@@ -0,0 +1,173 @@
+/*
+ * Copyright (c) 2017 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// CLASS HEADER
+#include "pixel-buffer-impl.h"
+
+// EXTERNAL INCLUDES
+#include <stdlib.h>
+#include <cstring>
+
+// INTERNAL INCLUDES
+#include "pixel-manipulation.h"
+#include "alpha-mask.h"
+
+namespace Dali
+{
+
+namespace Internal
+{
+
+namespace Adaptor
+{
+
+PixelBuffer::PixelBuffer( unsigned char* buffer,
+                          unsigned int bufferSize,
+                          unsigned int width,
+                          unsigned int height,
+                          Dali::Pixel::Format pixelFormat )
+: mBuffer( buffer ),
+  mBufferSize( bufferSize ),
+  mWidth( width ),
+  mHeight( height ),
+  mPixelFormat( pixelFormat )
+{
+}
+
+PixelBuffer::~PixelBuffer()
+{
+  ReleaseBuffer();
+}
+
+PixelBufferPtr PixelBuffer::New( unsigned int width,
+                                 unsigned int height,
+                                 Dali::Pixel::Format pixelFormat )
+{
+  unsigned int bufferSize = width * height * Dali::Pixel::GetBytesPerPixel( pixelFormat );
+  unsigned char* buffer = NULL;
+  if( bufferSize > 0 )
+  {
+    buffer = static_cast<unsigned char*>( malloc ( bufferSize ) );
+  }
+  return new PixelBuffer( buffer, bufferSize, width, height, pixelFormat );
+}
+
+PixelBufferPtr PixelBuffer::New( unsigned char* buffer,
+                                 unsigned int bufferSize,
+                                 unsigned int width,
+                                 unsigned int height,
+                                 Dali::Pixel::Format pixelFormat )
+{
+  return new PixelBuffer( buffer, bufferSize, width, height, pixelFormat );
+}
+
+Dali::PixelData PixelBuffer::Convert( PixelBuffer& pixelBuffer )
+{
+  Dali::PixelData pixelData = Dali::PixelData::New( pixelBuffer.mBuffer,
+                                                    pixelBuffer.mBufferSize,
+                                                    pixelBuffer.mWidth,
+                                                    pixelBuffer.mHeight,
+                                                    pixelBuffer.mPixelFormat,
+                                                    Dali::PixelData::FREE );
+  pixelBuffer.mBuffer = NULL;
+  pixelBuffer.mWidth = 0;
+  pixelBuffer.mHeight = 0;
+  pixelBuffer.mBufferSize = 0;
+
+  return pixelData;
+}
+
+unsigned int PixelBuffer::GetWidth() const
+{
+  return mWidth;
+}
+
+unsigned int PixelBuffer::GetHeight() const
+{
+  return mHeight;
+}
+
+Dali::Pixel::Format PixelBuffer::GetPixelFormat() const
+{
+  return mPixelFormat;
+}
+
+unsigned char* PixelBuffer::GetBuffer() const
+{
+  return mBuffer;
+}
+
+unsigned int PixelBuffer::GetBufferSize() const
+{
+  return mBufferSize;
+}
+
+Dali::PixelData PixelBuffer::CreatePixelData() const
+{
+  unsigned char* destBuffer = NULL;
+
+  if( mBufferSize > 0 )
+  {
+    destBuffer = static_cast<unsigned char*>( malloc( mBufferSize ) );
+    memcpy( destBuffer, mBuffer, mBufferSize );
+  }
+
+  Dali::PixelData pixelData = Dali::PixelData::New( destBuffer, mBufferSize,
+                                                    mWidth, mHeight,
+                                                    mPixelFormat,
+                                                    Dali::PixelData::FREE );
+  return pixelData;
+}
+
+void PixelBuffer::ApplyMask( const PixelBuffer& mask )
+{
+  int byteOffset=0;
+  int bitMask=0;
+
+  Dali::Pixel::GetAlphaOffsetAndMask(mPixelFormat, byteOffset, bitMask);
+
+  if( Dali::Pixel::HasAlpha( mPixelFormat ) && bitMask == 255 )
+  {
+    ApplyMaskToAlphaChannel( *this, mask );
+  }
+  else
+  {
+    PixelBufferPtr newPixelBuffer = CreateNewMaskedBuffer( *this, mask );
+    ReleaseBuffer();
+
+    // Take ownership of new buffer
+    mBuffer = newPixelBuffer->mBuffer;
+    newPixelBuffer->mBuffer = NULL;
+    mPixelFormat = newPixelBuffer->mPixelFormat;
+    mBufferSize = newPixelBuffer->mBufferSize;
+
+    // On leaving scope, newPixelBuffer will get destroyed.
+  }
+}
+
+void PixelBuffer::ReleaseBuffer()
+{
+  if( mBuffer )
+  {
+    free( mBuffer );
+  }
+}
+
+
+}// namespace Adaptor
+}// namespace Internal
+}// namespace Dali
diff --git a/adaptors/common/pixel-buffer-impl.h b/adaptors/common/pixel-buffer-impl.h
new file mode 100644 (file)
index 0000000..4853001
--- /dev/null
@@ -0,0 +1,201 @@
+#ifndef DALI_INTERNAL_ADAPTOR_PIXEL_BUFFER_H
+#define DALI_INTERNAL_ADAPTOR_PIXEL_BUFFER_H
+
+/*
+ * Copyright (c) 2017 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// INTERNAL INCLUDES
+#include <pixel-buffer.h>
+#include <dali/public-api/images/pixel-data.h>
+#include <dali/public-api/object/base-object.h>
+
+namespace Dali
+{
+
+namespace Internal
+{
+
+namespace Adaptor
+{
+
+class PixelBuffer;
+typedef IntrusivePtr<PixelBuffer> PixelBufferPtr;
+
+class PixelBuffer : public BaseObject
+{
+public:
+
+  /**
+   * @brief Create a PixelBuffer object with a pre-allocated buffer.
+   * The PixelBuffer object owns this buffer, which may be retrieved
+   * and modified using GetBuffer().
+   *
+   * @param [in] width            Buffer width in pixels
+   * @param [in] height           Buffer height in pixels
+   * @param [in] pixelFormat      The pixel format
+   */
+  static PixelBufferPtr New( unsigned int width,
+                             unsigned int height,
+                             Pixel::Format pixelFormat );
+
+  /**
+   * @brief Create a PixelBuffer object. For internal use only.
+   *
+   * @param [in] buffer           The raw pixel data.
+   * @param [in] bufferSize       The size of the buffer in bytes
+   * @param [in] width            Buffer width in pixels
+   * @param [in] height           Buffer height in pixels
+   * @param [in] pixelFormat      The pixel format
+   * @param [in] releaseFunction  The function used to release the memory.
+   */
+  static PixelBufferPtr New( unsigned char* buffer,
+                             unsigned int bufferSize,
+                             unsigned int width,
+                             unsigned int height,
+                             Pixel::Format pixelFormat );
+
+  /**
+   * Convert a pixelBuffer object into a PixelData object.
+   * The new object takes ownership of the buffer data, and the
+   * mBuffer pointer is reset to NULL.
+   * @param[in] pixelBuffer The buffer to convert
+   * @return the pixelData
+   */
+  static Dali::PixelData Convert( PixelBuffer& pixelBuffer );
+
+  /**
+   * @brief Constructor.
+   *
+   * @param [in] buffer           The raw pixel data.
+   * @param [in] bufferSize       The size of the buffer in bytes
+   * @param [in] width            Buffer width in pixels
+   * @param [in] height           Buffer height in pixels
+   * @param [in] pixelFormat      The pixel format
+   */
+  PixelBuffer( unsigned char* buffer,
+               unsigned int bufferSize,
+               unsigned int width,
+               unsigned int height,
+               Pixel::Format pixelFormat );
+
+protected:
+
+  /**
+   * @brief Destructor.
+   *
+   * Release the pixel buffer if exists.
+   */
+  ~PixelBuffer();
+
+public:
+
+  /**
+   * Get the width of the buffer in pixels.
+   * @return The width of the buffer in pixels
+   */
+  unsigned int GetWidth() const;
+
+  /**
+   * Get the height of the buffer in pixels
+   * @return The height of the buffer in pixels
+   */
+  unsigned int GetHeight() const;
+
+  /**
+   * Get the pixel format
+   * @return The pixel format
+   */
+  Pixel::Format GetPixelFormat() const;
+
+  /**
+   * Get the pixel buffer if it's present.
+   * @return The buffer if exists, or NULL if there is no pixel buffer.
+   */
+  unsigned char* GetBuffer() const;
+
+  /**
+   * Get the size of the buffer in bytes
+   * @return The size of the buffer
+   */
+  unsigned int GetBufferSize() const;
+
+  /**
+   * Copy the buffer into a new PixelData
+   */
+  Dali::PixelData CreatePixelData() const;
+
+  /**
+   * Apply the mask to the current buffer. This method may update the
+   * internal object - e.g. the new buffer may have a different pixel
+   * format - as an alpha channel may be added.
+   * @param[in] mask The mask to apply to this pixel buffer
+   */
+  void ApplyMask( const PixelBuffer& mask );
+
+private:
+  /*
+   * Undefined copy constructor.
+   */
+  PixelBuffer(const PixelBuffer& other);
+
+  /*
+   * Undefined assignment operator.
+   */
+  PixelBuffer& operator= (const PixelBuffer& other);
+
+  /**
+   * Release the buffer
+   */
+  void ReleaseBuffer();
+
+private:
+
+  unsigned char* mBuffer;           ///< The raw pixel data
+  unsigned int   mBufferSize;       ///< Buffer sized in bytes
+  unsigned int   mWidth;            ///< Buffer width in pixels
+  unsigned int   mHeight;           ///< Buffer height in pixels
+  Pixel::Format  mPixelFormat;      ///< Pixel format
+};
+
+} // namespace Adaptor
+
+} // namespace Internal
+
+/**
+ * Helper methods for public API
+ */
+inline Internal::Adaptor::PixelBuffer& GetImplementation( Devel::PixelBuffer& handle )
+{
+  DALI_ASSERT_ALWAYS( handle && "handle is empty" );
+
+  BaseObject& object = handle.GetBaseObject();
+
+  return static_cast<Internal::Adaptor::PixelBuffer&>( object );
+}
+
+inline const Internal::Adaptor::PixelBuffer& GetImplementation( const Devel::PixelBuffer& handle )
+{
+  DALI_ASSERT_ALWAYS( handle && "handle is empty" );
+
+  const BaseObject& object = handle.GetBaseObject();
+
+  return static_cast<const Internal::Adaptor::PixelBuffer&>( object );
+}
+
+} // namespace Dali
+
+#endif // __DALI_INTERNAL_ADAPTOR_PIXEL_BUFFER_H__
index b87f091..2585b17 100644 (file)
@@ -232,6 +232,14 @@ int VideoPlayer::GetPlayPosition()
   return 0;
 }
 
+void VideoPlayer::SetDisplayArea( DisplayArea area )
+{
+  if( mPlugin != NULL )
+  {
+    mPlugin->SetDisplayArea( area );
+  }
+}
+
 void VideoPlayer::SetDisplayRotation( Dali::VideoPlayerPlugin::DisplayRotation rotation )
 {
   if( mPlugin != NULL )
@@ -260,6 +268,22 @@ Dali::VideoPlayerPlugin::VideoPlayerSignalType& VideoPlayer::FinishedSignal()
   return mFinishedSignal;
 }
 
+void VideoPlayer::Forward( int millisecond )
+{
+  if( mPlugin != NULL )
+  {
+    mPlugin->Forward( millisecond );
+  }
+}
+
+void VideoPlayer::Backward( int millisecond )
+{
+  if( mPlugin != NULL )
+  {
+    mPlugin->Backward( millisecond );
+  }
+}
+
 } // namespace Adaptor;
 } // namespace Internal;
 } // namespace Dali;
index 4424217..e37b5f6 100644 (file)
@@ -125,6 +125,11 @@ public:
   int GetPlayPosition();
 
   /**
+   * @copydoc Dali::VideoPlayer::SetDisplayArea()
+   */
+  void SetDisplayArea( DisplayArea area );
+
+  /**
    * @copydoc Dali::VideoPlayer::SetSetDisplayRotation()
    */
   void SetDisplayRotation( Dali::VideoPlayerPlugin::DisplayRotation rotation );
@@ -144,6 +149,16 @@ public:
    */
   void Initialize();
 
+  /**
+   * @brief Dali::VideoPlayer::Forward()
+   */
+  void Forward( int millisecond );
+
+  /**
+   * @brief Dali::VideoPlayer::Backward()
+   */
+  void Backward( int millisecond );
+
 private:
 
   /**
index d4774f1..9ef6140 100644 (file)
@@ -65,13 +65,13 @@ public:
 
   /**
    * Create a new Window. This should only be called once by the Application class
-   * @param[in] windowPosition The position and size of the window
+   * @param[in] positionSize The position and size of the window
    * @param[in] name The window title
    * @param[in] className The window class name
    * @param[in] isTransparent Whether window is transparent
    * @return A newly allocated Window
    */
-  static Window* New(const PositionSize& posSize, const std::string& name, const std::string& className, bool isTransparent = false);
+  static Window* New(const PositionSize& positionSize, const std::string& name, const std::string& className, bool isTransparent = false);
 
   /**
    * Pass the adaptor back to the overlay. This allows the window to access Core's overlay.
@@ -276,6 +276,26 @@ public:
   int GetBrightness();
 
   /**
+   * @copydoc Dali::DevelWindow::SetSize()
+   */
+  void SetSize( Dali::DevelWindow::WindowSize size );
+
+  /**
+   * @copydoc Dali::DevelWindow::GetSize()
+   */
+  Dali::DevelWindow::WindowSize GetSize();
+
+  /**
+   * @copydoc Dali::DevelWindow::SetPosition()
+   */
+  void SetPosition( Dali::DevelWindow::WindowPosition position );
+
+  /**
+   * @copydoc Dali::DevelWindow::GetPosition()
+   */
+  Dali::DevelWindow::WindowPosition GetPosition();
+
+  /**
    * Called from Orientation after the Change signal has been sent
    */
   void RotationDone( int orientation, int width, int height );
@@ -295,7 +315,7 @@ private:
   /**
    * Second stage initialization
    */
-  void Initialize(const PositionSize& posSize, const std::string& name, const std::string& className);
+  void Initialize(const PositionSize& positionSize, const std::string& name, const std::string& className);
 
   /**
    * Shows / hides the indicator bar.
@@ -400,6 +420,7 @@ private:
   bool                             mIsFocusAcceptable:1;
   bool                             mVisible:1;
   bool                             mOpaqueState:1;
+  bool                             mResizeEnabled:1;
   IndicatorInterface*              mIndicator;
   Dali::Window::WindowOrientation  mIndicatorOrientation;
   Dali::Window::WindowOrientation  mNextIndicatorOrientation;
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2016 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2017 Samsung Electronics Co., Ltd.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
  *
  */
 
-
-// CLASS HEADER
-#include "property-buffer-wrapper.h"
-
 // INTERNAL INCLUDES
-#include "property-value-wrapper.h"
+#include <adaptors/devel-api/adaptor-framework/application-devel.h>
+#include <adaptors/common/application-impl.h>
 
 namespace Dali
 {
-namespace Internal
-{
-namespace Emscripten
+
+namespace DevelApplication
 {
 
-void SetPropertyBufferDataRaw(Dali::PropertyBuffer& self, const std::string& data, std::size_t size )
+Application New( int* argc, char **argv[], const std::string& stylesheet, Application::WINDOW_MODE windowMode, PositionSize positionSize )
 {
-  self.SetData( reinterpret_cast<void*>( const_cast<char*>(data.c_str()) ), size );
+  Internal::Adaptor::ApplicationPtr internal = Internal::Adaptor::Application::New( argc, argv, stylesheet, windowMode, positionSize, Internal::Adaptor::Framework::NORMAL );
+  return Application( internal.Get() );
 }
 
+} // namespace DevelApplication
 
-}; // namespace Emscripten
-}; // namespace Internal
-}; // namespace Dali
+} // namespace Dali
diff --git a/adaptors/devel-api/adaptor-framework/application-devel.h b/adaptors/devel-api/adaptor-framework/application-devel.h
new file mode 100644 (file)
index 0000000..6360011
--- /dev/null
@@ -0,0 +1,53 @@
+#ifndef DALI_APPLICATION_DEVEL_H
+#define DALI_APPLICATION_DEVEL_H
+
+/*
+ * Copyright (c) 2017 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// INTERNAL INCLUDES
+#ifdef DALI_ADAPTOR_COMPILATION  // full path doesn't exist until adaptor is installed so we have to use relative
+#include <application.h>
+#else
+#include <dali/public-api/adaptor-framework/application.h>
+#endif
+
+namespace Dali
+{
+
+namespace DevelApplication
+{
+
+/**
+ * @brief This is the constructor for applications.
+ *
+ * @PRIVLEVEL_PUBLIC
+ * @PRIVILEGE_DISPLAY
+ * @param[in,out]  argc         A pointer to the number of arguments
+ * @param[in,out]  argv         A pointer to the argument list
+ * @param[in]      stylesheet   The path to user defined theme file
+ * @param[in]      windowMode   A member of WINDOW_MODE
+ * @param[in]      positionSize A position and a size of the window
+ * @return A handle to the Application
+ * @note If the stylesheet is not specified, then the library's default stylesheet will not be overridden.
+ */
+DALI_IMPORT_API Application New( int* argc, char **argv[], const std::string& stylesheet, Application::WINDOW_MODE windowMode, PositionSize positionSize );
+
+} // namespace DevelApplication
+
+} // namespace Dali
+
+#endif // DALI_APPLICATION_DEVEL_H
diff --git a/adaptors/devel-api/adaptor-framework/bitmap-loader.cpp b/adaptors/devel-api/adaptor-framework/bitmap-loader.cpp
deleted file mode 100644 (file)
index 4aa2bd6..0000000
+++ /dev/null
@@ -1,83 +0,0 @@
-/*
- * Copyright (c) 2015 Samsung Electronics Co., Ltd.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-// CLASS HEADER
-#include "bitmap-loader.h"
-
-// EXTERNAL INCLUDES
-#include <string>
-
-// INTERNAL INCLUDES
-#include <bitmap-loader-impl.h>
-
-namespace Dali
-{
-
-BitmapLoader BitmapLoader::New( const std::string& url,
-                                ImageDimensions size,
-                                FittingMode::Type fittingMode,
-                                SamplingMode::Type samplingMode,
-                                bool orientationCorrection)
-{
-  IntrusivePtr<Internal::BitmapLoader> internal = Internal::BitmapLoader::New(url, size, fittingMode, samplingMode, orientationCorrection);
-  return BitmapLoader( internal.Get() );
-}
-
-BitmapLoader::BitmapLoader()
-{
-}
-
-BitmapLoader::BitmapLoader(Internal::BitmapLoader* internal)
-: BaseHandle( internal )
-{
-}
-
-BitmapLoader::~BitmapLoader()
-{
-}
-
-BitmapLoader::BitmapLoader( const BitmapLoader& handle )
-: BaseHandle( handle )
-{
-}
-
-BitmapLoader& BitmapLoader::operator=(const BitmapLoader& rhs)
-{
-  BaseHandle::operator=(rhs);
-  return *this;
-}
-
-void BitmapLoader::Load()
-{
-  GetImplementation(*this).Load();
-}
-
-bool BitmapLoader::IsLoaded()
-{
-  return GetImplementation(*this).IsLoaded();
-}
-
-std::string BitmapLoader::GetUrl() const
-{
-  return GetImplementation(*this).GetUrl();
-}
-
-PixelData BitmapLoader::GetPixelData() const
-{
-  return GetImplementation(*this).GetPixelData();
-}
-
-} // namespace Dali
diff --git a/adaptors/devel-api/adaptor-framework/bitmap-loader.h b/adaptors/devel-api/adaptor-framework/bitmap-loader.h
deleted file mode 100644 (file)
index 7849db4..0000000
+++ /dev/null
@@ -1,127 +0,0 @@
-#ifndef DALI_BITMAP_LOADER_H
-#define DALI_BITMAP_LOADER_H
-
-/*
- * Copyright (c) 2015 Samsung Electronics Co., Ltd.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-// EXTERNAL INCLUDES
-#include <string>
-#include <dali/public-api/common/dali-common.h>
-#include <dali/public-api/images/image-operations.h>
-#include <dali/public-api/images/pixel.h>
-#include <dali/public-api/images/pixel-data.h>
-#include <dali/public-api/object/base-handle.h>
-
-namespace Dali
-{
-namespace Internal
-{
-class BitmapLoader;
-}
-
-/**
- * @brief The BitmapLoader class is used to load bitmap from the URL synchronously.
- *
- * As the loading is synchronous, it will block the loop whilst executing.
- * Therefore, it should be used sparingly in the main event thread, and better to be called in the worker thread.
- * The Load() API is thread safe, it can be called from any thread without changing the state of DALI.
- */
-class DALI_IMPORT_API BitmapLoader : public BaseHandle
-{
-public:
-
-  /**
-   * @brief Create an initialized bitmap loader.
-   *
-   * By calling Load(), the synchronous loading is started immediately.
-   *
-   * @param [in] url The URL of the image file to load.
-   * @param [in] size The width and height to fit the loaded image to.
-   * @param [in] fittingMode The method used to fit the shape of the image before loading to the shape defined by the size parameter.
-   * @param [in] samplingMode The filtering method used when sampling pixels from the input image while fitting it to desired size.
-   * @param [in] orientationCorrection Reorient the image to respect any orientation metadata in its header.
-   */
-  static BitmapLoader New( const std::string& url,
-                           ImageDimensions size = ImageDimensions( 0, 0 ),
-                           FittingMode::Type fittingMode = FittingMode::DEFAULT,
-                           SamplingMode::Type samplingMode = SamplingMode::BOX_THEN_LINEAR,
-                           bool orientationCorrection = true);
-
-  /**
-   * @brief Create an empty handle.
-   *
-   * Use BitmapLoader::New() to create an initialized object.
-   */
-  BitmapLoader();
-
-  /**
-   * Destructor
-   */
-  ~BitmapLoader();
-
-  /**
-   * @brief This copy constructor is required for (smart) pointer semantics.
-   *
-   * @param [in] handle A reference to the copied handle
-   */
-  BitmapLoader(const BitmapLoader& handle);
-
-  /**
-   * @brief This assignment operator is required for (smart) pointer semantics.
-   *
-   * @param [in] rhs  A reference to the copied handle
-   * @return A reference to this
-   */
-  BitmapLoader& operator=(const BitmapLoader& rhs);
-
-public:
-
-  /**
-   * @brief Start the synchronous loading.
-   */
-  void Load();
-
-  /**
-   * @brief Query whether the image is loaded.
-   *
-   * @return true if the image is loaded, false otherwise.
-   */
-  bool IsLoaded();
-
-  /**
-   * @brief Returns the URL of the image.
-   *
-   * @return The URL of the image file.
-   */
-  std::string GetUrl() const;
-
-  /**
-   * @brief Get the pixel data.
-   *
-   * The returned pixel data is still valid after the BitmapLoader been destroyed.
-   *
-   * @return The pixel data.
-   */
-  PixelData GetPixelData() const;
-
-public: // Not intended for application developers
-
-  explicit DALI_INTERNAL BitmapLoader(Internal::BitmapLoader*);
-};
-
-} // Dali
-
-#endif // DALI_BITMAP_LOADER_H
index 701ccc7..e2f896b 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2016 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2017 Samsung Electronics Co., Ltd.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
 #include "image-loaders/image-loader.h"
 #include <resource-loader/network/file-download.h>
 #include <platform-abstractions/portable/file-closer.h>
+#include "pixel-buffer-impl.h"
 
 namespace Dali
 {
 
 namespace
 {
+
 // limit maximum image down load size to 50 MB
 const size_t MAXIMUM_DOWNLOAD_IMAGE_SIZE  = 50 * 1024 * 1024 ;
+
+static unsigned int gMaxTextureSize = 4096;
+
 }
 
-PixelData LoadImageFromFile( const std::string& url, ImageDimensions size, FittingMode::Type fittingMode, SamplingMode::Type samplingMode, bool orientationCorrection )
+Devel::PixelBuffer LoadImageFromFile( const std::string& url, ImageDimensions size, FittingMode::Type fittingMode, SamplingMode::Type samplingMode, bool orientationCorrection )
 {
   Integration::BitmapResourceType resourceType( size, fittingMode, samplingMode, orientationCorrection );
-  IntrusivePtr<Dali::RefObject> resource = TizenPlatform::ImageLoader::LoadImageSynchronously( resourceType, url );
 
-  if( resource )
+  Internal::Platform::FileCloser fc( url.c_str(), "rb");
+  FILE * const fp = fc.GetFile();
+  if( fp != NULL )
   {
-    Integration::Bitmap* bitmap = static_cast<Integration::Bitmap*>( resource.Get() );
-
-    // Use bitmap->GetBufferOwnership() to transfer the buffer ownership to pixelData.
-    // The destroy of bitmap will not release the buffer, instead, the pixelData is responsible for releasing when its reference count falls to zero.
-    return Dali::PixelData::New( bitmap->GetBufferOwnership(),
-                                 bitmap->GetBufferSize(),
-                                 bitmap->GetImageWidth(),
-                                 bitmap->GetImageHeight(),
-                                 bitmap->GetPixelFormat(),
-                                 Dali::PixelData::FREE );
+    Integration::BitmapPtr bitmap;
+    bool success = TizenPlatform::ImageLoader::ConvertStreamToBitmap( resourceType, url, fp, bitmap );
+    if( success && bitmap )
+    {
+      // Use bitmap->GetBufferOwnership() to transfer the buffer ownership
+      // to pixelData.  The destroy of bitmap will not release the buffer,
+      // instead, the pixelBuffer is responsible for releasing when its
+      // reference count falls to zero.
+      Internal::Adaptor::PixelBufferPtr pixelBufferImpl =
+        Internal::Adaptor::PixelBuffer::New( bitmap->GetBufferOwnership(),
+                                             bitmap->GetBufferSize(),
+                                             bitmap->GetImageWidth(),
+                                             bitmap->GetImageHeight(),
+                                             bitmap->GetPixelFormat() );
+
+      Dali::Devel::PixelBuffer pixelBuffer( pixelBufferImpl.Get() );
+      return pixelBuffer;
+    }
   }
-  return Dali::PixelData();
+  return Dali::Devel::PixelBuffer();
 }
 
 ImageDimensions GetClosestImageSize( const std::string& filename,
@@ -58,11 +72,16 @@ ImageDimensions GetClosestImageSize( const std::string& filename,
                                      SamplingMode::Type samplingMode,
                                      bool orientationCorrection )
 {
-  return TizenPlatform::ImageLoader::GetClosestImageSize( filename, size, fittingMode, samplingMode, orientationCorrection );
+  ImageDimensions dimension = TizenPlatform::ImageLoader::GetClosestImageSize( filename, size, fittingMode, samplingMode, orientationCorrection );
+
+  dimension.SetWidth( std::min( dimension.GetWidth(), static_cast< uint16_t >( GetMaxTextureSize() ) ) );
+  dimension.SetHeight( std::min( dimension.GetHeight(), static_cast< uint16_t >( GetMaxTextureSize() ) ) );
+
+  return dimension;
 }
 
 
-PixelData DownloadImageSynchronously( const std::string& url, ImageDimensions size, FittingMode::Type fittingMode, SamplingMode::Type samplingMode, bool orientationCorrection )
+Devel::PixelBuffer DownloadImageSynchronously( const std::string& url, ImageDimensions size, FittingMode::Type fittingMode, SamplingMode::Type samplingMode, bool orientationCorrection )
 {
   Integration::BitmapResourceType resourceType( size, fittingMode, samplingMode, orientationCorrection );
 
@@ -96,12 +115,15 @@ PixelData DownloadImageSynchronously( const std::string& url, ImageDimensions si
 
         if ( result && bitmap )
         {
-          return Dali::PixelData::New( bitmap->GetBufferOwnership(),
-                                       bitmap->GetBufferSize(),
-                                       bitmap->GetImageWidth(),
-                                       bitmap->GetImageHeight(),
-                                       bitmap->GetPixelFormat(),
-                                       Dali::PixelData::FREE );
+          Internal::Adaptor::PixelBufferPtr pixelBufferImpl =
+            Internal::Adaptor::PixelBuffer::New( bitmap->GetBufferOwnership(),
+                                                 bitmap->GetBufferSize(),
+                                                 bitmap->GetImageWidth(),
+                                                 bitmap->GetImageHeight(),
+                                                 bitmap->GetPixelFormat() );
+
+          Dali::Devel::PixelBuffer pixelBuffer( pixelBufferImpl.Get() );
+          return pixelBuffer;
         }
         else
         {
@@ -109,10 +131,18 @@ PixelData DownloadImageSynchronously( const std::string& url, ImageDimensions si
         }
       }
     }
-
   }
-  return Dali::PixelData();
+  return Dali::Devel::PixelBuffer();
+}
+
+void SetMaxTextureSize( unsigned int size )
+{
+  gMaxTextureSize = size;
 }
 
+unsigned int GetMaxTextureSize()
+{
+  return gMaxTextureSize;
+}
 
 } // namespace Dali
index 124b27b..a9476e3 100644 (file)
 #include <string>
 #include <dali/public-api/common/dali-common.h>
 #include <dali/public-api/images/image-operations.h>
-#include <dali/public-api/images/pixel-data.h>
+
+#ifdef DALI_ADAPTOR_COMPILATION  // full path doesn't exist until adaptor is installed so we have to use relative
+// @todo Make dali-adaptor code folder structure mirror the folder structure installed to dali-env
+#include <pixel-buffer.h>
+#else
+#include <dali/devel-api/adaptor-framework/pixel-buffer.h>
+#endif
 
 namespace Dali
 {
@@ -36,9 +42,9 @@ namespace Dali
  * @param [in] fittingMode The method used to fit the shape of the image before loading to the shape defined by the size parameter.
  * @param [in] samplingMode The filtering method used when sampling pixels from the input image while fitting it to desired size.
  * @param [in] orientationCorrection Reorient the image to respect any orientation metadata in its header.
- * @return handle to the loaded PixelData object or an empty handle in case loading failed.
+ * @return handle to the loaded PixelBuffer object or an empty handle in case loading failed.
  */
-DALI_IMPORT_API PixelData LoadImageFromFile(
+DALI_IMPORT_API Devel::PixelBuffer LoadImageFromFile(
   const std::string& url,
   ImageDimensions size = ImageDimensions( 0, 0 ),
   FittingMode::Type fittingMode = FittingMode::DEFAULT,
@@ -77,15 +83,28 @@ DALI_IMPORT_API ImageDimensions GetClosestImageSize(
  * @param [in] samplingMode The filtering method used when sampling pixels from the input image while fitting it to desired size.
  * @param [in] orientationCorrection Reorient the image to respect any orientation metadata in its header.
  *
- * @return handle to the loaded PixelData object or an empty handle in case downloading or decoding failed.
+ * @return handle to the loaded PixelBuffer object or an empty handle in case downloading or decoding failed.
  */
-DALI_IMPORT_API PixelData DownloadImageSynchronously(
+DALI_IMPORT_API Devel::PixelBuffer DownloadImageSynchronously(
   const std::string& url,
   ImageDimensions size = ImageDimensions( 0, 0 ),
   FittingMode::Type fittingMode = FittingMode::DEFAULT,
   SamplingMode::Type samplingMode = SamplingMode::BOX_THEN_LINEAR,
   bool orientationCorrection = true );
 
+/**
+ * @brief Set the maximum texture size. Then size can be kwown by GL_MAX_TEXTURE_SIZE.
+ *
+ * @param [in] size The maximum texture size to set
+ */
+void SetMaxTextureSize( unsigned int size );
+
+/**
+ * @brief get the maximum texture size.
+ *
+ * @return The maximum texture size
+ */
+unsigned int GetMaxTextureSize();
 
 } // Dali
 
diff --git a/adaptors/devel-api/adaptor-framework/pixel-buffer.cpp b/adaptors/devel-api/adaptor-framework/pixel-buffer.cpp
new file mode 100644 (file)
index 0000000..52d8b8f
--- /dev/null
@@ -0,0 +1,106 @@
+/*
+ * Copyright (c) 2017 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// CLASS HEADER
+#include "pixel-buffer.h"
+
+// EXTERNAL INLCUDES
+#include <stdlib.h>
+
+// INTERNAL INCLUDES
+#include <pixel-buffer-impl.h>
+
+namespace Dali
+{
+namespace Devel
+{
+
+PixelBuffer PixelBuffer::New( unsigned int width,
+                              unsigned int height,
+                              Dali::Pixel::Format pixelFormat )
+{
+  Internal::Adaptor::PixelBufferPtr internal =
+    Internal::Adaptor::PixelBuffer::New( width, height, pixelFormat );
+  return Devel::PixelBuffer( internal.Get() );
+}
+
+Dali::PixelData PixelBuffer::Convert( PixelBuffer& pixelBuffer )
+{
+  Dali::PixelData pixelData =
+    Internal::Adaptor::PixelBuffer::Convert( GetImplementation(pixelBuffer) );
+  pixelBuffer.Reset();
+  return pixelData;
+}
+
+Dali::PixelData PixelBuffer::CreatePixelData() const
+{
+  return GetImplementation(*this).CreatePixelData();
+}
+
+
+PixelBuffer::PixelBuffer()
+{
+}
+
+PixelBuffer::~PixelBuffer()
+{
+}
+
+PixelBuffer::PixelBuffer( Internal::Adaptor::PixelBuffer* internal )
+: BaseHandle( internal )
+{
+}
+
+PixelBuffer::PixelBuffer(const PixelBuffer& handle)
+: BaseHandle( handle )
+{
+}
+
+PixelBuffer& PixelBuffer::operator=(const PixelBuffer& rhs)
+{
+  BaseHandle::operator=(rhs);
+  return *this;
+}
+
+unsigned int PixelBuffer::GetWidth() const
+{
+  return GetImplementation(*this).GetWidth();
+}
+
+unsigned int PixelBuffer::GetHeight() const
+{
+  return GetImplementation(*this).GetHeight();
+}
+
+Pixel::Format PixelBuffer::GetPixelFormat() const
+{
+  return GetImplementation(*this).GetPixelFormat();
+}
+
+unsigned char* PixelBuffer::GetBuffer()
+{
+  return GetImplementation(*this).GetBuffer();
+}
+
+void PixelBuffer::ApplyMask( PixelBuffer mask )
+{
+  GetImplementation(*this).ApplyMask( GetImplementation( mask ) );
+}
+
+} // namespace Devel
+
+} // namespace Dali
diff --git a/adaptors/devel-api/adaptor-framework/pixel-buffer.h b/adaptors/devel-api/adaptor-framework/pixel-buffer.h
new file mode 100644 (file)
index 0000000..deb7823
--- /dev/null
@@ -0,0 +1,179 @@
+#ifndef DALI_PIXEL_BUFFER_H
+#define DALI_PIXEL_BUFFER_H
+
+/*
+ * Copyright (c) 2017 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#include <dali/public-api/images/pixel.h>
+#include <dali/public-api/images/pixel-data.h>
+#include <dali/public-api/object/base-handle.h>
+
+namespace Dali
+{
+
+namespace Internal
+{
+namespace Adaptor
+{
+class PixelBuffer;
+}
+}
+
+// Use namespace to separate from PixelBuffer typedef in buffer-image.h
+namespace Devel
+{
+
+/**
+ * @brief The PixelBuffer object holds a pixel buffer.
+ *
+ * The PixelBuffer keeps ownership of it's initial buffer however, the
+ * user is free to modify the pixel data, either directly, or via
+ * image operations.
+ *
+ * In order to upload the pixel data to texture memory, there are two
+ * possibilities - either convert it back to a PixelData object, which
+ * releases the PixelBuffer object, leaving the user with an empty handle
+ * (ideal for one-time indirect image manipulation), or create a new
+ * PixelData object from this object, leaving the buffer intact (ideal
+ * for continuous manipulation)
+ *
+ * @SINCE_1_2.46
+ */
+class DALI_IMPORT_API PixelBuffer : public BaseHandle
+{
+public:
+
+  /**
+   * Create a PixelBuffer with it's own data buffer.
+   */
+  static PixelBuffer New( unsigned int width,
+                          unsigned int height,
+                          Dali::Pixel::Format pixelFormat );
+
+  /**
+   * @brief Creates an empty handle.
+   * Use PixelBuffer::New() to create an initialized object.
+   *
+   * @SINCE_1_2.46
+   */
+  PixelBuffer();
+
+  /**
+   * @brief Destructor.
+   *
+   * @SINCE_1_2.46
+   */
+  ~PixelBuffer();
+
+  /**
+   * @brief This copy constructor is required for (smart) pointer semantics.
+   *
+   * @SINCE_1_2.46
+   * @param[in] handle A reference to the copied handle
+   */
+  PixelBuffer(const PixelBuffer& handle);
+
+  /**
+   * @brief This assignment operator is required for (smart) pointer semantics.
+   *
+   * @SINCE_1_2.46
+   * @param[in] rhs A reference to the copied handle
+   * @return A reference to this object
+   */
+  PixelBuffer& operator=(const PixelBuffer& rhs);
+
+  /**
+   * Convert to a pixel data and release the pixelBuffer's object.
+   * This handle is left empty.
+   *
+   * @warning Any other handles that keep a reference to this object
+   * will be left with no buffer, trying to access it will return NULL.
+   *
+   * @SINCE_1_2.46
+   * @param[in,out] pixelBuffer
+   * @return a new PixelData which takes ownership of the PixelBuffer's buffer.
+   */
+  static PixelData Convert( PixelBuffer& pixelBuffer );
+
+  /**
+   * Copy the data from this object into a new PixelData object, which could be
+   * used for uploading to a texture.
+   * @return a new PixelData object containing a copy of this pixel buffer's data.
+   */
+  Dali::PixelData CreatePixelData() const;
+
+  /**
+   * @brief Gets the pixel buffer. This is a pointer to the internal
+   * pixel buffer.
+   *
+   * @warning If there is no pixel buffer (e.g. this object has been
+   * converted to a PixelData), this method will return NULL.
+   *
+   * @SINCE_1_2.46
+   * @return The pixel buffer, or NULL.
+   */
+  unsigned char* GetBuffer();
+
+  /**
+   * @brief Gets the width of the buffer in pixels.
+   *
+   * @SINCE_1_2.46
+   * @return The width of the buffer in pixels
+   */
+  unsigned int GetWidth() const;
+
+  /**
+   * @brief Gets the height of the buffer in pixels.
+   *
+   * @SINCE_1_2.46
+   * @return The height of the buffer in pixels
+   */
+  unsigned int GetHeight() const;
+
+  /**
+   * @brief Gets the pixel format.
+   *
+   * @SINCE_1_2.46
+   * @return The pixel format
+   */
+  Pixel::Format GetPixelFormat() const;
+
+  /**
+   * Apply the mask to this pixel data, and return a new pixel data
+   * containing the masked image. If this PixelBuffer doesn't have an alpha channel,
+   * then the resultant PixelBuffer will be converted to a format that
+   * supports at least the width of the color channels and the alpha channel
+   * from the mask.
+   * @param[in] mask The mask to apply.
+   */
+  void ApplyMask( PixelBuffer mask );
+
+public:
+
+  /**
+   * @brief The constructor.
+   * @note  Not intended for application developers.
+   * @SINCE_1_2.46
+   * @param[in] pointer A pointer to a newly allocated PixelBuffer
+   */
+  explicit DALI_INTERNAL PixelBuffer( Internal::Adaptor::PixelBuffer* pointer );
+};
+
+} // namespace Devel
+} // namespace Dali
+
+#endif // DALI_PIXEL_BUFFER_H
index 0791db1..4bbcc04 100644 (file)
 
 // EXTERNAL INCLUDES
 #include <dali/public-api/signals/dali-signal.h>
+#include <dali/public-api/math/rect.h>
 
 namespace Dali
 {
 
 class Any;
+typedef Dali::Rect< int > DisplayArea;
 
 /**
  * @brief VideoPlayerPlugin is an abstract interface, used by dali-adaptor to access video player plugin.
@@ -165,6 +167,13 @@ public:
   virtual int GetPlayPosition() = 0;
 
   /**
+   * @brief Sets the area of video display.
+   * @SINCE_1_2.46
+   * param[in] area The left-top position and size of the video display area
+   */
+  virtual void SetDisplayArea( DisplayArea area ) = 0;
+
+  /**
    * @brief Sets video display rotation
    * @SINCE_1_1.38
    * @param[in] rotation The rotation of display
@@ -186,6 +195,22 @@ public:
    */
   virtual VideoPlayerSignalType& FinishedSignal() = 0;
 
+  /**
+   * @brief Seeks forward by the specified number of milliseconds.
+   *
+   * @SINCE_1_2.46
+   * @param[in] millisecond The position for forward playback
+   */
+  virtual void Forward( int millisecond ) = 0;
+
+  /**
+   * @brief Seeks backward by the specified number of milliseconds.
+   *
+   * @SINCE_1_2.46
+   * @param[in] millisecond The position for backward playback
+   */
+  virtual void Backward( int millisecond ) = 0;
+
 };
 
 } // namespace Dali;
index 8cb5395..fb4b2a2 100644 (file)
@@ -141,6 +141,11 @@ int VideoPlayer::GetPlayPosition()
   return GetImplementation( *this ).GetPlayPosition();
 }
 
+void VideoPlayer::SetDisplayArea( DisplayArea area )
+{
+  GetImplementation( *this ).SetDisplayArea( area );
+}
+
 void VideoPlayer::SetDisplayRotation( Dali::VideoPlayerPlugin::DisplayRotation rotation )
 {
   GetImplementation( *this ).SetDisplayRotation( rotation );
@@ -156,5 +161,15 @@ Dali::VideoPlayerPlugin::VideoPlayerSignalType& VideoPlayer::FinishedSignal()
   return GetImplementation( *this ).FinishedSignal();
 }
 
+void VideoPlayer::Forward( int millisecond )
+{
+  GetImplementation( *this ).Forward( millisecond );
+}
+
+void VideoPlayer::Backward( int millisecond )
+{
+  GetImplementation( *this ).Backward( millisecond );
+}
+
 } // namespace Dali;
 
index 9d37043..8c69719 100644 (file)
@@ -197,6 +197,13 @@ public:
   int GetPlayPosition();
 
   /**
+   * @brief Sets the area of video display.
+   * @SINCE_1_2.46
+   * param[in] area The left-top position and size of the video display area
+   */
+  void SetDisplayArea( DisplayArea area );
+
+  /**
    * @brief Sets video display rotation
    * @SINCE_1_1.38
    * @param[in] rotation The rotation of display
@@ -218,6 +225,22 @@ public:
    */
   Dali::VideoPlayerPlugin::VideoPlayerSignalType& FinishedSignal();
 
+  /**
+   * @brief Seeks forward by the specified number of milliseconds.
+   *
+   * @SINCE_1_2.46
+   * @param[in] millisecond The position for forward playback
+   */
+  void Forward( int millisecond );
+
+  /**
+   * @brief Seeks backward by the specified number of milliseconds.
+   *
+   * @SINCE_1_2.46
+   * @param[in] millisecond The position for backward playback
+   */
+  void Backward( int millisecond );
+
 private: // Not intended for application developers
 
   /**
index 447cdd1..0ad934e 100644 (file)
@@ -150,6 +150,26 @@ ResizedSignalType& ResizedSignal( Window window )
   return GetImplementation( window ).ResizedSignal();
 }
 
+void SetSize( Window window, WindowSize size )
+{
+  GetImplementation( window ).SetSize( size );
+}
+
+WindowSize GetSize( Window window )
+{
+  return GetImplementation( window ).GetSize();
+}
+
+void SetPosition( Window window, WindowPosition position )
+{
+  GetImplementation( window ).SetPosition( position );
+}
+
+WindowPosition GetPosition( Window window )
+{
+  return GetImplementation( window ).GetPosition();
+}
+
 } // namespace DevelWindow
 
 } // namespace Dali
index be087f0..0357be8 100644 (file)
@@ -21,6 +21,7 @@
 // EXTERNAL INCLUDES
 #include <string>
 #include <dali/public-api/math/rect.h>
+#include <dali/public-api/math/uint-16-pair.h>
 
 // INTERNAL INCLUDES
 #ifdef DALI_ADAPTOR_COMPILATION  // full path doesn't exist until adaptor is installed so we have to use relative
@@ -77,8 +78,11 @@ enum Type
   DIALOG            ///< Used for simple dialog windows.
 };
 
-typedef Signal< void (bool) > FocusSignalType;      ///< Window focus signal type
-typedef Signal< void (int, int) > ResizedSignalType; ///< Window resized signal type
+typedef Uint16Pair WindowSize;          ///< Window size type
+typedef Uint16Pair WindowPosition;      ///< Window position type
+
+typedef Signal< void ( bool ) > FocusSignalType;         ///< Window focus signal type
+typedef Signal< void ( WindowSize ) > ResizedSignalType; ///< Window resized signal type
 
 /**
  * @brief The user should connect to this signal to get a timing when window gains focus or loses focus.
@@ -308,6 +312,38 @@ DALI_IMPORT_API int GetBrightness( Window window );
  */
 DALI_IMPORT_API ResizedSignalType& ResizedSignal( Window window );
 
+/**
+ * @brief Sets a size of the window.
+ *
+ * @param[in] window The window to set a size
+ * @param[in] size The new window size
+ */
+DALI_IMPORT_API void SetSize( Window window, WindowSize size );
+
+/**
+ * @brief Gets a size of the window.
+ *
+ * @param[in] window The window to get a size
+ * @return The size of the window
+ */
+DALI_IMPORT_API WindowSize GetSize( Window window );
+
+/**
+ * @brief Sets a position of the window.
+ *
+ * @param[in] window The window to set a position
+ * @param[in] position The new window position
+ */
+DALI_IMPORT_API void SetPosition( Window window, WindowPosition position );
+
+/**
+ * @brief Gets a position of the window.
+ *
+ * @param[in] window The window to get a position
+ * @return The position of the window
+ */
+DALI_IMPORT_API WindowPosition GetPosition( Window window );
+
 } // namespace DevelWindow
 
 } // namespace Dali
index 894b0a5..0ce6e62 100644 (file)
@@ -1,7 +1,7 @@
 devel_api_src_files = \
   $(adaptor_devel_api_dir)/adaptor-framework/accessibility-adaptor.cpp \
+  $(adaptor_devel_api_dir)/adaptor-framework/application-devel.cpp \
   $(adaptor_devel_api_dir)/adaptor-framework/application-extensions.cpp \
-  $(adaptor_devel_api_dir)/adaptor-framework/bitmap-loader.cpp \
   $(adaptor_devel_api_dir)/adaptor-framework/bitmap-saver.cpp \
   $(adaptor_devel_api_dir)/adaptor-framework/clipboard.cpp \
   $(adaptor_devel_api_dir)/adaptor-framework/clipboard-event-notifier.cpp \
@@ -19,6 +19,7 @@ devel_api_src_files = \
   $(adaptor_devel_api_dir)/adaptor-framework/orientation.cpp \
   $(adaptor_devel_api_dir)/adaptor-framework/performance-logger.cpp \
   $(adaptor_devel_api_dir)/adaptor-framework/physical-keyboard.cpp \
+  $(adaptor_devel_api_dir)/adaptor-framework/pixel-buffer.cpp \
   $(adaptor_devel_api_dir)/adaptor-framework/singleton-service.cpp \
   $(adaptor_devel_api_dir)/adaptor-framework/sound-player.cpp \
   $(adaptor_devel_api_dir)/adaptor-framework/style-monitor.cpp \
@@ -33,8 +34,8 @@ devel_api_adaptor_framework_header_files = \
   $(adaptor_devel_api_dir)/adaptor-framework/accessibility-adaptor.h \
   $(adaptor_devel_api_dir)/adaptor-framework/accessibility-action-handler.h \
   $(adaptor_devel_api_dir)/adaptor-framework/accessibility-gesture-handler.h \
+  $(adaptor_devel_api_dir)/adaptor-framework/application-devel.h \
   $(adaptor_devel_api_dir)/adaptor-framework/application-extensions.h \
-  $(adaptor_devel_api_dir)/adaptor-framework/bitmap-loader.h \
   $(adaptor_devel_api_dir)/adaptor-framework/bitmap-saver.h \
   $(adaptor_devel_api_dir)/adaptor-framework/clipboard-event-notifier.h \
   $(adaptor_devel_api_dir)/adaptor-framework/clipboard.h \
@@ -54,6 +55,7 @@ devel_api_adaptor_framework_header_files = \
   $(adaptor_devel_api_dir)/adaptor-framework/lifecycle-controller.h \
   $(adaptor_devel_api_dir)/adaptor-framework/orientation.h \
   $(adaptor_devel_api_dir)/adaptor-framework/performance-logger.h \
+  $(adaptor_devel_api_dir)/adaptor-framework/pixel-buffer.h \
   $(adaptor_devel_api_dir)/adaptor-framework/render-surface.h \
   $(adaptor_devel_api_dir)/adaptor-framework/singleton-service.h \
   $(adaptor_devel_api_dir)/adaptor-framework/sound-player.h \
@@ -65,4 +67,3 @@ devel_api_adaptor_framework_header_files = \
   $(adaptor_devel_api_dir)/adaptor-framework/virtual-keyboard.h \
   $(adaptor_devel_api_dir)/adaptor-framework/physical-keyboard.h \
   $(adaptor_devel_api_dir)/adaptor-framework/window-devel.h
-
old mode 100644 (file)
new mode 100755 (executable)
index afe3859..551000c
@@ -27,6 +27,8 @@
 #include <key-impl.h>
 
 #include <iostream>
+#include <string.h>
+
 using namespace std;
 
 namespace Dali
@@ -40,11 +42,13 @@ bool GrabKeyTopmost( Window window, Dali::KEY daliKey )
   return GrabKey( window, daliKey, TOPMOST);
 }
 
+
 bool UngrabKeyTopmost( Window window, Dali::KEY daliKey )
 {
   return UngrabKey( window, daliKey );
 }
 
+
 bool GrabKey( Window window, Dali::KEY daliKey, KeyGrabMode grabMode )
 {
   Ecore_Wl_Window_Keygrab_Mode wlGrabMode;
@@ -58,11 +62,11 @@ bool GrabKey( Window window, Dali::KEY daliKey, KeyGrabMode grabMode )
   }
   else if( grabMode == OVERRIDE_EXCLUSIVE )
   {
-    wlGrabMode = ECORE_WL_WINDOW_KEYGRAB_EXCLUSIVE;
+    wlGrabMode = ECORE_WL_WINDOW_KEYGRAB_OVERRIDE_EXCLUSIVE;
   }
   else if( grabMode == EXCLUSIVE )
   {
-    wlGrabMode = ECORE_WL_WINDOW_KEYGRAB_OVERRIDE_EXCLUSIVE;
+    wlGrabMode = ECORE_WL_WINDOW_KEYGRAB_EXCLUSIVE;
   }
   else
   {
@@ -74,6 +78,7 @@ bool GrabKey( Window window, Dali::KEY daliKey, KeyGrabMode grabMode )
                                       0, 0, 0, wlGrabMode );
 }
 
+
 bool UngrabKey( Window window, Dali::KEY daliKey )
 {
   return ecore_wl_window_keygrab_unset( AnyCast<Ecore_Wl_Window*>( window.GetNativeHandle() ),
@@ -81,8 +86,152 @@ bool UngrabKey( Window window, Dali::KEY daliKey )
                                       0, 0 );
 }
 
+
+bool GrabKeyList( Window window, const Dali::Vector<Dali::KEY>& daliKeyVector, const Dali::Vector<KeyGrabMode>& grabModeVector, Dali::Vector<bool>& returnVector)
+{
+  const Dali::Vector<bool>::SizeType returnCount = returnVector.Count();
+  const Dali::Vector<Dali::KEY>::SizeType keyCount = daliKeyVector.Count();
+  const Dali::Vector<KeyGrabMode>::SizeType keyGrabModeCount = grabModeVector.Count();
+
+  if( keyCount != keyGrabModeCount || keyCount != returnCount || keyCount == 0 )
+  {
+    return false;
+  }
+
+  eina_init();
+
+  Eina_List* keyList = NULL;
+  {
+    for( Dali::Vector<float>::SizeType index = 0; index < keyCount; ++index )
+    {
+      Ecore_Wl_Window_Keygrab_Info info;
+      info.key = const_cast<char*>(Dali::Internal::Adaptor::KeyLookup::GetKeyName( daliKeyVector[index] ));
+
+      switch( grabModeVector[index] )
+      {
+        case TOPMOST:
+        {
+          info.mode = ECORE_WL_WINDOW_KEYGRAB_TOPMOST;
+          break;
+        }
+        case SHARED:
+        {
+          info.mode = ECORE_WL_WINDOW_KEYGRAB_SHARED;
+          break;
+        }
+        case OVERRIDE_EXCLUSIVE:
+        {
+          info.mode = ECORE_WL_WINDOW_KEYGRAB_OVERRIDE_EXCLUSIVE;
+          break;
+        }
+        case EXCLUSIVE:
+        {
+          info.mode = ECORE_WL_WINDOW_KEYGRAB_EXCLUSIVE;
+          break;
+        }
+        default:
+        {
+          info.mode = ECORE_WL_WINDOW_KEYGRAB_UNKNOWN;
+          break;
+        }
+      }
+
+      keyList = eina_list_append( keyList, &info );
+    }
+  }
+
+  Eina_List* grabList = ecore_wl_window_keygrab_list_set( AnyCast<Ecore_Wl_Window*>( window.GetNativeHandle() ), keyList );
+
+  returnVector.Resize( keyCount, true );
+
+  Eina_List* l = NULL;
+  Eina_List* m = NULL;
+  void *listData = NULL;
+  void *data = NULL;
+  if( grabList != NULL )
+  {
+    EINA_LIST_FOREACH( grabList, m, data )
+    {
+      Dali::Vector<float>::SizeType index = 0;
+      EINA_LIST_FOREACH( keyList, l, listData )
+      {
+        if((static_cast<Ecore_Wl_Window_Keygrab_Info*>(listData))->key == NULL)
+        {
+          DALI_LOG_ERROR("input key list has null data!");
+          break;
+        }
+
+        if( strcmp( static_cast<char*>(data), static_cast<Ecore_Wl_Window_Keygrab_Info*>(listData)->key ) == 0 )
+        {
+          returnVector[index] = false;
+        }
+        ++index;
+      }
+    }
+  }
+
+  eina_list_free( keyList );
+  eina_list_free( grabList );
+  eina_shutdown();
+
+  return true;
+}
+
+bool UngrabKeyList( Window window, const Dali::Vector<Dali::KEY>& daliKeyVector, Dali::Vector<bool>& returnVector)
+{
+  const Dali::Vector<bool>::SizeType returnCount = returnVector.Count();
+  const Dali::Vector<Dali::KEY>::SizeType keyCount = daliKeyVector.Count();
+
+  if( keyCount != returnCount ||keyCount == 0 )
+  {
+    return false;
+  }
+
+  eina_init();
+
+  Eina_List* keyList = NULL;
+  {
+    for( Dali::Vector<float>::SizeType index = 0; index < keyCount; ++index )
+    {
+      Ecore_Wl_Window_Keygrab_Info info;
+      info.key = const_cast<char*>(Dali::Internal::Adaptor::KeyLookup::GetKeyName( daliKeyVector[index] ));
+      keyList = eina_list_append( keyList, &info );
+    }
+  }
+
+  Eina_List* ungrabList = ecore_wl_window_keygrab_list_unset( AnyCast<Ecore_Wl_Window*>( window.GetNativeHandle() ), keyList );
+
+  returnVector.Resize( keyCount, true );
+
+  Eina_List* l = NULL;
+  Eina_List* m = NULL;
+  void *listData = NULL;
+  void *data = NULL;
+
+  if( ungrabList != NULL )
+  {
+    EINA_LIST_FOREACH( ungrabList, m, data )
+    {
+      Dali::Vector<float>::SizeType index = 0;
+      EINA_LIST_FOREACH( keyList, l, listData )
+      {
+        if( strcmp( static_cast<char*>(data), static_cast<Ecore_Wl_Window_Keygrab_Info*>(listData)->key ) == 0 )
+        {
+          returnVector[index] = false;
+        }
+        ++index;
+      }
+    }
+  }
+
+  eina_list_free( keyList );
+  eina_list_free( ungrabList );
+  eina_shutdown();
+
+  return true;
+}
+
 } // namespace KeyGrab
 
 } // namespace Dali
 
-
index 692749b..f090ad1 100644 (file)
@@ -382,11 +382,11 @@ struct Window::EventHandler
   bool mBrightnessChangeDone;
 };
 
-Window* Window::New(const PositionSize& posSize, const std::string& name, const std::string& className, bool isTransparent)
+Window* Window::New( const PositionSize& positionSize, const std::string& name, const std::string& className, bool isTransparent )
 {
   Window* window = new Window();
   window->mIsTransparent = isTransparent;
-  window->Initialize(posSize, name, className);
+  window->Initialize( positionSize, name, className );
   return window;
 }
 
@@ -511,6 +511,7 @@ Window::Window()
   mIsFocusAcceptable( true ),
   mVisible( true ),
   mOpaqueState( false ),
+  mResizeEnabled( false ),
   mIndicator( NULL ),
   mIndicatorOrientation( Dali::Window::PORTRAIT ),
   mNextIndicatorOrientation( Dali::Window::PORTRAIT ),
@@ -552,17 +553,13 @@ Window::~Window()
   mAuxiliaryHints.clear();
 }
 
-void Window::Initialize(const PositionSize& windowPosition, const std::string& name, const std::string& className)
+void Window::Initialize(const PositionSize& positionSize, const std::string& name, const std::string& className)
 {
   // create an Wayland window by default
   Any surface;
-  ECore::WindowRenderSurface* windowSurface = new ECore::WindowRenderSurface( windowPosition, surface, name, mIsTransparent );
+  ECore::WindowRenderSurface* windowSurface = new ECore::WindowRenderSurface( positionSize, surface, name, mIsTransparent );
 
   mSurface = windowSurface;
-  SetClass( name, className );
-  windowSurface->Map();
-
-  mOrientation = Orientation::New(this);
 
   // create event handler for Wayland window
   mEventHandler = new EventHandler( this );
@@ -581,6 +578,17 @@ void Window::Initialize(const PositionSize& windowPosition, const std::string& n
       DALI_LOG_INFO( gWindowLogFilter, Debug::Verbose, "Window::Initialize: %s\n", hint );
     }
   }
+
+  if( !positionSize.IsEmpty() )
+  {
+    AddAuxiliaryHint( "wm.policy.win.user.geometry", "1" );
+    mResizeEnabled = true;
+  }
+
+  SetClass( name, className );
+  windowSurface->Map();
+
+  mOrientation = Orientation::New(this);
 }
 
 void Window::DoShowIndicator( Dali::Window::WindowOrientation lastOrientation )
@@ -899,12 +907,10 @@ bool Window::IsVisible() const
 
 void Window::RotationDone( int orientation, int width, int height )
 {
-  PositionSize positionSize( 0, 0, width, height );
-
-  mAdaptor->SurfaceSizeChanged( positionSize );
+  mAdaptor->SurfaceSizeChanged( Dali::Adaptor::SurfaceSize( width, height ) );
 
   // Emit signal
-  mResizedSignal.Emit( positionSize.width, positionSize.height );
+  mResizedSignal.Emit( Dali::DevelWindow::WindowSize( width, height ) );
 
   Dali::Window::WindowOrientation windowOrientation;
   switch( orientation )
@@ -937,7 +943,7 @@ void Window::RotationDone( int orientation, int width, int height )
   }
 
   ECore::WindowRenderSurface* wlSurface( dynamic_cast< ECore::WindowRenderSurface * >( mSurface ) );
-  wlSurface->RequestRotation( windowOrientation, positionSize.width, positionSize.height );
+  wlSurface->RequestRotation( windowOrientation, width, height );
 }
 
 unsigned int Window::GetSupportedAuxiliaryHintCount()
@@ -1452,6 +1458,63 @@ int Window::GetBrightness()
   return mEventHandler->mBrightness;
 }
 
+void Window::SetSize( Dali::DevelWindow::WindowSize size )
+{
+  if( !mResizeEnabled )
+  {
+    AddAuxiliaryHint( "wm.policy.win.user.geometry", "1" );
+    mResizeEnabled = true;
+  }
+
+  PositionSize positionSize = mSurface->GetPositionSize();
+
+  if( positionSize.width != size.GetWidth() || positionSize.height != size.GetHeight() )
+  {
+    positionSize.width = size.GetWidth();
+    positionSize.height = size.GetHeight();
+
+    mSurface->MoveResize( positionSize );
+
+    mAdaptor->SurfaceSizeChanged( Dali::Adaptor::SurfaceSize( positionSize.width, positionSize.height ) );
+
+    // Emit signal
+    mResizedSignal.Emit( Dali::DevelWindow::WindowSize( positionSize.width, positionSize.height ) );
+  }
+}
+
+Dali::DevelWindow::WindowSize Window::GetSize()
+{
+  PositionSize positionSize = mSurface->GetPositionSize();
+
+  return Dali::DevelWindow::WindowSize( positionSize.width, positionSize.height );
+}
+
+void Window::SetPosition( Dali::DevelWindow::WindowPosition position )
+{
+  if( !mResizeEnabled )
+  {
+    AddAuxiliaryHint( "wm.policy.win.user.geometry", "1" );
+    mResizeEnabled = true;
+  }
+
+  PositionSize positionSize = mSurface->GetPositionSize();
+
+  if( positionSize.x != position.GetX() || positionSize.y != position.GetY() )
+  {
+    positionSize.x = position.GetX();
+    positionSize.y = position.GetY();
+
+    mSurface->MoveResize( positionSize );
+  }
+}
+
+Dali::DevelWindow::WindowPosition Window::GetPosition()
+{
+  PositionSize positionSize = mSurface->GetPositionSize();
+
+  return Dali::DevelWindow::WindowPosition( positionSize.x, positionSize.y );
+}
+
 } // Adaptor
 
 } // Internal
index 17c5515..6fc7677 100644 (file)
@@ -19,6 +19,7 @@
 #include <window-render-surface.h>
 
 // EXTERNAL INCLUDES
+#include <dlfcn.h>
 #include <dali/integration-api/gl-abstraction.h>
 #include <dali/integration-api/debug.h>
 #include <dali/integration-api/gl-defines.h>
@@ -44,6 +45,7 @@ namespace
 {
 
 const int MINIMUM_DIMENSION_CHANGE( 1 ); ///< Minimum change for window to be considered to have moved
+const char* WAYLAND_EGL_SO( "libwayland-egl.so" );
 
 } // unnamed namespace
 
@@ -52,7 +54,11 @@ WindowRenderSurface::WindowRenderSurface( Dali::PositionSize positionSize,
                                           const std::string& name,
                                           bool isTransparent)
 : EcoreWlRenderSurface( positionSize, surface, name, isTransparent ),
+  mEglWinGetCapabilitiesPtr( NULL ),
+  mEglWinSetRotationPtr( NULL ),
+  mLibHandle( NULL ),
   mWlWindow( NULL ),
+  mWlSurface( NULL ),
   mEglWindow( NULL ),
   mThreadSynchronization( NULL ),
   mRotationTrigger( NULL ),
@@ -80,6 +86,11 @@ WindowRenderSurface::~WindowRenderSurface()
   {
     delete mRotationTrigger;
   }
+
+  if( mLibHandle != NULL )
+  {
+    dlclose( mLibHandle );
+  }
 }
 
 Ecore_Wl_Window* WindowRenderSurface::GetDrawable()
@@ -159,7 +170,10 @@ void WindowRenderSurface::RequestRotation( Dali::Window::WindowOrientation orien
 
   ecore_wl_window_rotation_set( mWlWindow, angle );
 
-  wl_egl_window_set_rotation( mEglWindow, rotation );
+  if( mEglWinSetRotationPtr )
+  {
+    mEglWinSetRotationPtr( mEglWindow, rotation );
+  }
 }
 
 void WindowRenderSurface::InitializeEgl( EglInterface& eglIf )
@@ -187,18 +201,46 @@ void WindowRenderSurface::CreateEglSurface( EglInterface& eglIf )
     ecore_wl_window_alpha_set( mWlWindow, false );
   }
 
-  // create the EGL surface
-  ecore_wl_window_surface_create(mWlWindow);
-  mEglWindow = wl_egl_window_create(ecore_wl_window_surface_get(mWlWindow), mPosition.width, mPosition.height);
+  // create the EGL window
+  mEglWindow = wl_egl_window_create( mWlSurface, mPosition.width, mPosition.height );
   EGLNativeWindowType windowType( mEglWindow );
   eglImpl.CreateSurfaceWindow( windowType, mColorDepth );
 
   // Check capability
-  wl_egl_window_capability capability = static_cast< wl_egl_window_capability >( wl_egl_window_get_capabilities( mEglWindow ) );
-  if( capability == WL_EGL_WINDOW_CAPABILITY_ROTATION_SUPPORTED )
+  if( !mLibHandle )
+  {
+    mLibHandle = dlopen( WAYLAND_EGL_SO, RTLD_LAZY );
+
+    char* error = dlerror();
+    if( mLibHandle == NULL || error != NULL )
+    {
+      DALI_LOG_INFO( gRenderSurfaceLogFilter, Debug::Verbose, "WindowRenderSurface::CreateEglSurface: dlopen error: %s\n", error );
+      return;
+    }
+
+    mEglWinGetCapabilitiesPtr = reinterpret_cast< EglWinGetCapabilitiesFunction >( dlsym( mLibHandle, "wl_egl_window_get_capabilities" ) );
+    if( !mEglWinGetCapabilitiesPtr )
+    {
+      DALI_LOG_INFO( gRenderSurfaceLogFilter, Debug::Verbose, "WindowRenderSurface::CreateEglSurface: Can't load wl_egl_window_get_capabilities\n" );
+      return;
+    }
+
+    mEglWinSetRotationPtr = reinterpret_cast< EglWinSetRotationFunction >( dlsym( mLibHandle, "wl_egl_window_set_rotation" ) );
+    if( !mEglWinSetRotationPtr )
+    {
+      DALI_LOG_INFO( gRenderSurfaceLogFilter, Debug::Verbose, "WindowRenderSurface::CreateEglSurface: Can't load wl_egl_window_set_rotation\n" );
+      return;
+    }
+  }
+
+  if( mEglWinGetCapabilitiesPtr )
   {
-    DALI_LOG_INFO( gRenderSurfaceLogFilter, Debug::Verbose, "WindowRenderSurface::CreateEglSurface: capability = %d\n", capability );
-    mRotationSupported = true;
+    wl_egl_window_capability capability = static_cast< wl_egl_window_capability >( mEglWinGetCapabilitiesPtr( mEglWindow ) );
+    if( capability == WL_EGL_WINDOW_CAPABILITY_ROTATION_SUPPORTED )
+    {
+      DALI_LOG_INFO( gRenderSurfaceLogFilter, Debug::Verbose, "WindowRenderSurface::CreateEglSurface: capability = %d\n", capability );
+      mRotationSupported = true;
+    }
   }
 }
 
@@ -236,7 +278,7 @@ bool WindowRenderSurface::ReplaceEGLSurface( EglInterface& egl )
     ecore_wl_window_alpha_set( mWlWindow, false );
   }
 
-  mEglWindow = wl_egl_window_create(ecore_wl_window_surface_get(mWlWindow), mPosition.width, mPosition.height);
+  mEglWindow = wl_egl_window_create( mWlSurface, mPosition.width, mPosition.height );
 
   Internal::Adaptor::EglImplementation& eglImpl = static_cast<Internal::Adaptor::EglImplementation&>( egl );
   EGLNativeWindowType windowType( mEglWindow );
@@ -264,15 +306,18 @@ void WindowRenderSurface::MoveResize( Dali::PositionSize positionSize )
 
   if(needToMove)
   {
-    ecore_wl_window_move(mWlWindow, positionSize.x, positionSize.y);
-    mPosition = positionSize;
+    ecore_wl_window_position_set( mWlWindow, positionSize.x, positionSize.y );
   }
   if (needToResize)
   {
-    ecore_wl_window_resize(mWlWindow, positionSize.width, positionSize.height, 0);
-    mPosition = positionSize;
+    ecore_wl_window_update_size( mWlWindow, positionSize.width, positionSize.height );
   }
 
+  mPosition = positionSize;
+
+  wl_egl_window_resize( mEglWindow, mPosition.width, mPosition.height, mPosition.x, mPosition.y );
+
+  DALI_LOG_INFO( gRenderSurfaceLogFilter, Debug::Verbose, "WindowRenderSurface::MoveResize: %d, %d, %d, %d\n", mPosition.x, mPosition.y, mPosition.width, mPosition.height );
 }
 
 void WindowRenderSurface::Map()
@@ -350,6 +395,8 @@ void WindowRenderSurface::CreateWlRenderable()
   {
     DALI_ASSERT_ALWAYS(0 && "Failed to create Wayland window");
   }
+
+  mWlSurface = ecore_wl_window_surface_create( mWlWindow );
 }
 
 void WindowRenderSurface::UseExistingRenderable( unsigned int surfaceId )
index 40a0d2a..b5a9e81 100644 (file)
@@ -170,7 +170,15 @@ private:
 
 private: // Data
 
-  Ecore_Wl_Window*                mWlWindow; ///< Wayland-Window
+  typedef int (*EglWinGetCapabilitiesFunction)( wl_egl_window* eglWindow );
+  typedef int (*EglWinSetRotationFunction)( wl_egl_window* eglWindow, int rotation );
+
+  EglWinGetCapabilitiesFunction  mEglWinGetCapabilitiesPtr;
+  EglWinSetRotationFunction      mEglWinSetRotationPtr;
+
+  void*                           mLibHandle; ///< Handle for the loaded library
+  Ecore_Wl_Window*                mWlWindow;  ///< Wayland-Window
+  wl_surface*                     mWlSurface;
   wl_egl_window*                  mEglWindow;
   ThreadSynchronizationInterface* mThreadSynchronization;
   TriggerEventInterface*          mRotationTrigger;
diff --git a/adaptors/emscripten/egl-implementation-emscripten.cpp b/adaptors/emscripten/egl-implementation-emscripten.cpp
deleted file mode 100644 (file)
index eec071a..0000000
+++ /dev/null
@@ -1,561 +0,0 @@
-/*
-Copyright (c) 2000-2013 Samsung Electronics Co., Ltd All Rights Reserved
-
-This file is part of Dali Adaptor
-
-PROPRIETARY/CONFIDENTIAL
-
-This software is the confidential and proprietary information of
-SAMSUNG ELECTRONICS ("Confidential Information"). You shall not
-disclose such Confidential Information and shall use it only in
-accordance with the terms of the license agreement you entered
-into with SAMSUNG ELECTRONICS.
-
-SAMSUNG make no representations or warranties about the suitability
-of the software, either express or implied, including but not limited
-to the implied warranties of merchantability, fitness for a particular
-purpose, or non-infringement. SAMSUNG shall not be liable for any
-damages suffered by licensee as a result of using, modifying or
-distributing this software or its derivatives.
-*/
-
-
-// CLASS HEADER
-#include <gl/egl-implementation.h>
-
-// EXTERNAL INCLUDES
-#include <iostream>
-#include <dali/integration-api/debug.h>
-#include <dali/public-api/common/dali-common.h>
-#include <dali/public-api/common/dali-vector.h>
-
-// INTERNAL INCLUDES
-namespace
-{
-
-#if defined(DEBUG_ENABLED)
-
-void PrintConfigs(EGLDisplay d)
-{
-  EGLint numConfigs;
-
-  eglGetConfigs(d, NULL, 0, &numConfigs);
-  EGLConfig *configs = new EGLConfig[numConfigs];
-
-  eglGetConfigs(d, configs, numConfigs, &numConfigs);
-
-  printf("Configurations: N=%d\n", numConfigs);
-  printf(" - config id\n");
-  printf(" - buffer size\n");
-  printf(" - level\n");
-  printf(" - double buffer\n");
-  printf(" - stereo\n");
-  printf(" - r, g, b\n");
-  printf(" - depth\n");
-  printf(" - stencil\n");
-
-  printf("     bf lv d st colorbuffer dp st   supported \n");
-  printf("  id sz  l b ro  r  g  b  a th cl   surfaces  \n");
-  printf("----------------------------------------------\n");
-  for (EGLint i = 0; i < numConfigs; i++) {
-    EGLint id, size, level;
-    EGLint red, green, blue, alpha;
-    EGLint depth, stencil;
-    EGLint surfaces;
-    EGLint doubleBuf = 1, stereo = 0;
-    char surfString[100] = "";
-
-    eglGetConfigAttrib(d, configs[i], EGL_CONFIG_ID, &id);
-    eglGetConfigAttrib(d, configs[i], EGL_BUFFER_SIZE, &size);
-    eglGetConfigAttrib(d, configs[i], EGL_LEVEL, &level);
-
-    eglGetConfigAttrib(d, configs[i], EGL_RED_SIZE, &red);
-    eglGetConfigAttrib(d, configs[i], EGL_GREEN_SIZE, &green);
-    eglGetConfigAttrib(d, configs[i], EGL_BLUE_SIZE, &blue);
-    eglGetConfigAttrib(d, configs[i], EGL_ALPHA_SIZE, &alpha);
-    eglGetConfigAttrib(d, configs[i], EGL_DEPTH_SIZE, &depth);
-    eglGetConfigAttrib(d, configs[i], EGL_STENCIL_SIZE, &stencil);
-    eglGetConfigAttrib(d, configs[i], EGL_SURFACE_TYPE, &surfaces);
-
-    if (surfaces & EGL_WINDOW_BIT)
-      strcat(surfString, "win,");
-    if (surfaces & EGL_PBUFFER_BIT)
-      strcat(surfString, "pb,");
-    if (surfaces & EGL_PIXMAP_BIT)
-      strcat(surfString, "pix,");
-    if (strlen(surfString) > 0)
-      surfString[strlen(surfString) - 1] = 0;
-
-    printf("0x%02x %2d %2d %c  %c %2d %2d %2d %2d %2d %2d   %-12s\n",
-           id, size, level,
-           doubleBuf ? 'y' : '.',
-           stereo ? 'y' : '.',
-           red, green, blue, alpha,
-           depth, stencil, surfString);
-  }
-
-  delete [] configs;
-}
-
-#endif
-
-} // namespace anon
-
-namespace Dali
-{
-namespace Internal
-{
-namespace Adaptor
-{
-
-#define TEST_EGL_ERROR(lastCommand) \
-{ \
-  EGLint err = eglGetError(); \
-  if (err != EGL_SUCCESS) \
-  { \
-    printf("EGL error after %s code=%x\n", lastCommand, err); \
-    DALI_LOG_ERROR("EGL error after %s code=%x\n", lastCommand,err); \
-    DALI_ASSERT_ALWAYS(0 && "EGL error");                            \
-  } \
-}
-
-EglImplementation::EglImplementation()
-  : mEglNativeDisplay(0),
-    mCurrentEglNativePixmap(0),
-    mEglDisplay(0),
-    mEglConfig(0),
-    mEglContext(0),
-    mCurrentEglSurface(0),
-    mGlesInitialized(false),
-    mIsOwnSurface(true),
-    mContextCurrent(false),
-    mIsWindow(true),
-    mColorDepth(COLOR_DEPTH_24)
-{
-}
-
-EglImplementation::~EglImplementation()
-{
-  TerminateGles();
-}
-
-bool EglImplementation::InitializeGles( EGLNativeDisplayType display, bool isOwnSurface )
-{
-  if ( !mGlesInitialized )
-  {
-    mEglNativeDisplay = display;
-
-    //@todo see if we can just EGL_DEFAULT_DISPLAY instead
-    mEglDisplay = eglGetDisplay(mEglNativeDisplay);
-
-    EGLint majorVersion = 0;
-    EGLint minorVersion = 0;
-    if ( !eglInitialize( mEglDisplay, &majorVersion, &minorVersion ) )
-    {
-      return false;
-    }
-    eglBindAPI(EGL_OPENGL_ES_API);
-
-#if defined(DEBUG_ENABLED)
-    PrintConfigs(mEglDisplay);
-#endif
-
-    mContextAttribs.Clear();
-
-#if DALI_GLES_VERSION >= 30
-
-    mContextAttribs.Reserve(5);
-    mContextAttribs.PushBack( EGL_CONTEXT_MAJOR_VERSION_KHR );
-    mContextAttribs.PushBack( 3 );
-    mContextAttribs.PushBack( EGL_CONTEXT_MINOR_VERSION_KHR );
-    mContextAttribs.PushBack( 0 );
-
-#else // DALI_GLES_VERSION >= 30
-
-    mContextAttribs.Reserve(3);
-    mContextAttribs.PushBack( EGL_CONTEXT_CLIENT_VERSION );
-    mContextAttribs.PushBack( 2 );
-
-#endif // DALI_GLES_VERSION >= 30
-
-    mContextAttribs.PushBack( EGL_NONE );
-
-    mGlesInitialized = true;
-    mIsOwnSurface = isOwnSurface;
-  }
-
-  return mGlesInitialized;
-}
-
-bool EglImplementation::CreateContext()
-{
-  // make sure a context isn't created twice
-  DALI_ASSERT_ALWAYS( (mEglContext == 0) && "EGL context recreated" );
-  DALI_ASSERT_ALWAYS( mGlesInitialized );
-
-  mEglContext = eglCreateContext(mEglDisplay, mEglConfig, NULL, &(mContextAttribs[0]));
-
-  // if emscripten ignore this (egl spec says non gles2 implementation must return EGL_BAD_MATCH if it doesnt support gles2)
-  // so just ignore error for now....
-  // TEST_EGL_ERROR("eglCreateContext render thread");
-  // DALI_ASSERT_ALWAYS( EGL_NO_CONTEXT != mEglContext && "EGL context not created" );
-
-  return true;
-}
-
-void EglImplementation::DestroyContext()
-{
-  DALI_ASSERT_ALWAYS( mEglContext && "no EGL context" );
-
-  eglDestroyContext( mEglDisplay, mEglContext );
-  mEglContext = 0;
-}
-
-void EglImplementation::DestroySurface()
-{
-  if(mIsOwnSurface && mCurrentEglSurface)
-  {
-    eglDestroySurface( mEglDisplay, mCurrentEglSurface );
-    mCurrentEglSurface = 0;
-  }
-}
-
-void EglImplementation::MakeContextCurrent()
-{
-  mContextCurrent = true;
-
-  if(mIsOwnSurface)
-  {
-    eglMakeCurrent( mEglDisplay, mCurrentEglSurface, mCurrentEglSurface, mEglContext );
-  }
-
-  EGLint error = eglGetError();
-
-  if ( error != EGL_SUCCESS )
-  {
-    switch (error)
-    {
-      case EGL_BAD_DISPLAY:
-      {
-        DALI_LOG_ERROR("EGL_BAD_DISPLAY : Display is not an EGL display connection\n");
-        break;
-      }
-      case EGL_NOT_INITIALIZED:
-      {
-        DALI_LOG_ERROR("EGL_NOT_INITIALIZED : Display has not been initialized\n");
-        break;
-      }
-      case EGL_BAD_SURFACE:
-      {
-        DALI_LOG_ERROR("EGL_BAD_SURFACE : Draw or read is not an EGL surface\n");
-        break;
-      }
-      case EGL_BAD_CONTEXT:
-      {
-        DALI_LOG_ERROR("EGL_BAD_CONTEXT : Context is not an EGL rendering context\n");
-        break;
-      }
-      case EGL_BAD_MATCH:
-      {
-        DALI_LOG_ERROR("EGL_BAD_MATCH : Draw or read are not compatible with context, or if context is set to EGL_NO_CONTEXT and draw or read are not set to EGL_NO_SURFACE, or if draw or read are set to EGL_NO_SURFACE and context is not set to EGL_NO_CONTEXT\n");
-        break;
-      }
-      case EGL_BAD_ACCESS:
-      {
-        DALI_LOG_ERROR("EGL_BAD_ACCESS : Context is current to some other thread\n");
-        break;
-      }
-      case EGL_BAD_NATIVE_PIXMAP:
-      {
-        DALI_LOG_ERROR("EGL_BAD_NATIVE_PIXMAP : A native pixmap underlying either draw or read is no longer valid.\n");
-        break;
-      }
-      case EGL_BAD_NATIVE_WINDOW:
-      {
-        DALI_LOG_ERROR("EGL_BAD_NATIVE_WINDOW : A native window underlying either draw or read is no longer valid.\n");
-        break;
-      }
-      case EGL_BAD_CURRENT_SURFACE:
-      {
-        DALI_LOG_ERROR("EGL_BAD_CURRENT_SURFACE : The previous context has unflushed commands and the previous surface is no longer valid.\n");
-        break;
-      }
-      case EGL_BAD_ALLOC:
-      {
-        DALI_LOG_ERROR("EGL_BAD_ALLOC : Allocation of ancillary buffers for draw or read were delayed until eglMakeCurrent is called, and there are not enough resources to allocate them\n");
-        break;
-      }
-      case EGL_CONTEXT_LOST:
-      {
-        DALI_LOG_ERROR("EGL_CONTEXT_LOST : If a power management event has occurred. The application must destroy all contexts and reinitialise OpenGL ES state and objects to continue rendering\n");
-        break;
-      }
-      default:
-      {
-        DALI_LOG_ERROR("Unknown error\n");
-        break;
-      }
-    }
-    DALI_ASSERT_ALWAYS(false && "MakeContextCurrent failed!");
-  }
-
-  DALI_LOG_WARNING("- EGL Information\nVendor: %s\nVersion: %s\nClient APIs: %s\nExtensions: %s\n",
-                   eglQueryString(mEglDisplay, EGL_VENDOR),
-                   eglQueryString(mEglDisplay, EGL_VERSION),
-                   eglQueryString(mEglDisplay, EGL_CLIENT_APIS),
-                   eglQueryString(mEglDisplay, EGL_EXTENSIONS));
-
-}
-
-void EglImplementation::MakeContextNull()
-{
-  mContextCurrent = false;
-  // clear the current context
-  eglMakeCurrent( mEglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT );
-}
-
-void EglImplementation::TerminateGles()
-{
-  if ( mGlesInitialized )
-  {
-    // in latest Mali DDK (r2p3 ~ r3p0 in April, 2012),
-    // MakeContextNull should be called before eglDestroy surface
-    // to prevent crash in _mali_surface_destroy_callback
-    MakeContextNull();
-
-    if(mIsOwnSurface && mCurrentEglSurface)
-    {
-      eglDestroySurface(mEglDisplay, mCurrentEglSurface);
-    }
-    eglDestroyContext(mEglDisplay, mEglContext);
-
-    eglTerminate(mEglDisplay);
-
-    mEglDisplay = NULL;
-    mEglConfig  = NULL;
-    mEglContext = NULL;
-    mCurrentEglSurface = NULL;
-
-    mGlesInitialized = false;
-  }
-}
-
-bool EglImplementation::IsGlesInitialized() const
-{
-  return mGlesInitialized;
-}
-
-void EglImplementation::SwapBuffers()
-{
-  eglSwapBuffers( mEglDisplay, mCurrentEglSurface );
-}
-
-void EglImplementation::CopyBuffers()
-{
-  eglCopyBuffers( mEglDisplay, mCurrentEglSurface, mCurrentEglNativePixmap );
-}
-
-void EglImplementation::WaitGL()
-{
-  eglWaitGL();
-}
-
-void EglImplementation::ChooseConfig( bool isWindowType, ColorDepth depth )
-{
-  if(mEglConfig && isWindowType == mIsWindow && mColorDepth == depth)
-  {
-    return;
-  }
-
-  mIsWindow = isWindowType;
-
-  EGLint numConfigs;
-  Vector<EGLint> configAttribs;
-  configAttribs.Reserve(31);
-
-  if(isWindowType)
-  {
-    configAttribs.PushBack( EGL_SURFACE_TYPE );
-    configAttribs.PushBack( EGL_WINDOW_BIT );
-  }
-  else
-  {
-    DALI_ASSERT_ALWAYS(!"uninplemented");
-    configAttribs.PushBack( EGL_SURFACE_TYPE );
-    configAttribs.PushBack( EGL_PIXMAP_BIT );
-  }
-
-  configAttribs.PushBack( EGL_RENDERABLE_TYPE );
-
-#if DALI_GLES_VERSION >= 30
-  DALI_ASSERT_ALWAYS(!"uninplemented");
-
-#ifdef _ARCH_ARM_
-  configAttribs.PushBack( EGL_OPENGL_ES3_BIT_KHR );
-#else
-  // There is a bug in the desktop emulator
-  // Requesting for ES3 causes eglCreateContext even though it allows to ask
-  // for a configuration that supports GLES 3.0
-  configAttribs.PushBack( EGL_OPENGL_ES2_BIT );
-#endif // _ARCH_ARM_
-
-#else // DALI_GLES_VERSION >= 30
-
-  configAttribs.PushBack( EGL_OPENGL_ES2_BIT );
-
-#endif //DALI_GLES_VERSION >= 30
-
-  configAttribs.PushBack( EGL_RED_SIZE );
-  configAttribs.PushBack( 8 );
-  configAttribs.PushBack( EGL_GREEN_SIZE );
-  configAttribs.PushBack( 8 );
-  configAttribs.PushBack( EGL_BLUE_SIZE );
-  configAttribs.PushBack( 8 );
-
-  //
-  // Setting the alpha crashed .... need SDL_SetVideo(...) with alpha somehow??
-  //
-
-  configAttribs.PushBack( EGL_ALPHA_SIZE );
-  configAttribs.PushBack( 8 );
-  configAttribs.PushBack( EGL_DEPTH_SIZE );
-  configAttribs.PushBack( 24 );
-
-  configAttribs.PushBack( EGL_NONE );
-
-  if ( eglChooseConfig( mEglDisplay, &(configAttribs[0]), &mEglConfig, 1, &numConfigs ) != EGL_TRUE )
-  {
-    EGLint error = eglGetError();
-    switch (error)
-    {
-      case EGL_BAD_DISPLAY:
-      {
-        DALI_LOG_ERROR("Display is not an EGL display connection\n");
-        break;
-      }
-      case EGL_BAD_ATTRIBUTE:
-      {
-        DALI_LOG_ERROR("The parameter confirAttribs contains an invalid frame buffer configuration attribute or an attribute value that is unrecognized or out of range\n");
-        break;
-      }
-      case EGL_NOT_INITIALIZED:
-      {
-        DALI_LOG_ERROR("Display has not been initialized\n");
-        break;
-      }
-      case EGL_BAD_PARAMETER:
-      {
-        DALI_LOG_ERROR("The parameter numConfig is NULL\n");
-        break;
-      }
-      default:
-      {
-        DALI_LOG_ERROR("Unknown error\n");
-      }
-    }
-    DALI_ASSERT_ALWAYS(false && "eglChooseConfig failed!");
-  }
-
-  if ( numConfigs != 1 )
-  {
-    DALI_LOG_ERROR("No configurations found.\n");
-    TEST_EGL_ERROR("eglChooseConfig");
-  }
-}
-
-
-void EglImplementation::CreateSurfaceWindow( EGLNativeWindowType window, ColorDepth depth )
-{
-  DALI_ASSERT_ALWAYS( ( mCurrentEglSurface == 0 ) && "EGL surface already exists" );
-
-  mColorDepth = depth;
-  mIsWindow = true;
-
-  // egl choose config
-  static_cast<void>(window);
-  EGLNativeWindowType dummyWindow = NULL;
-
-  mCurrentEglSurface = eglCreateWindowSurface( mEglDisplay, mEglConfig, dummyWindow, NULL );
-
-
-  TEST_EGL_ERROR("eglCreateWindowSurface");
-
-  DALI_ASSERT_ALWAYS( mCurrentEglSurface && "Create window surface failed" );
-}
-
-
-EGLSurface EglImplementation::CreateSurfacePixmap( EGLNativePixmapType pixmap, ColorDepth depth )
-{
-  DALI_ASSERT_ALWAYS( mCurrentEglSurface == 0 && "Cannot create more than one instance of surface pixmap" );
-
-  mCurrentEglNativePixmap = pixmap;
-  mColorDepth = depth;
-  mIsWindow = false;
-
-  // egl choose config
-  ChooseConfig(mIsWindow, mColorDepth);
-
-  mCurrentEglSurface = eglCreatePixmapSurface( mEglDisplay, mEglConfig, mCurrentEglNativePixmap, NULL );
-  TEST_EGL_ERROR("eglCreatePixmapSurface");
-
-  DALI_ASSERT_ALWAYS( mCurrentEglSurface && "Create pixmap surface failed" );
-
-  return mCurrentEglSurface;
-}
-
-bool EglImplementation::ReplaceSurfaceWindow( EGLNativeWindowType window )
-{
-  DALI_ASSERT_ALWAYS(!"Unimplemented");
-
-  bool contextLost = false;
-
-  //  the surface is bound to the context, so set the context to null
-  MakeContextNull();
-
-  // destroy the surface
-  DestroySurface();
-
-  // create the EGL surface
-  CreateSurfaceWindow( window, mColorDepth );
-
-  // set the context to be current with the new surface
-  MakeContextCurrent();
-
-  return contextLost;
-}
-
-bool EglImplementation::ReplaceSurfacePixmap( EGLNativePixmapType pixmap, EGLSurface& eglSurface  )
-{
-  bool contextLost = false;
-
-  //  the surface is bound to the context, so set the context to null
-  MakeContextNull();
-
-  // destroy the surface
-  DestroySurface();
-
-  // create the EGL surface
-  eglSurface = CreateSurfacePixmap( pixmap, mColorDepth );
-
-  // set the context to be current with the new surface
-  MakeContextCurrent();
-
-  return contextLost;
-}
-
-EGLDisplay EglImplementation::GetDisplay() const
-{
-  return mEglDisplay;
-}
-
-EGLDisplay EglImplementation::GetContext() const
-{
-  return mEglContext;
-}
-
-} // namespace Adaptor
-
-} // namespace Internal
-
-} // namespace Dali
-
diff --git a/adaptors/emscripten/main.cpp b/adaptors/emscripten/main.cpp
deleted file mode 100644 (file)
index 56e2e48..0000000
+++ /dev/null
@@ -1,110 +0,0 @@
-
-#include "sdl-application.h"
-#include <cassert>
-
-#include <dali/public-api/dali-core.h>
-
-#include <SDL/SDL.h>
-
-// main loop function called by emscripten/browser
-extern void emscripten_set_main_loop(void (*func)(), int fps, int simulate_infinite_loop);
-
-namespace Dali
-{
-namespace Internal
-{
-namespace Emscripten
-{
-extern void RenderFinished();
-};
-};
-};
-
-Dali::SdlApplication *app = NULL;
-
-void EmscriptenMouseEvent(double x, double y, int downUpMotion)
-{
-  DALI_ASSERT_ALWAYS(app);
-
-  if(app)
-  {
-    app->SendTouchEvent(x,y, downUpMotion);
-  }
-}
-
-void ProcessEvents()
-{
-  SDL_PumpEvents();
-
-  //
-  // This wasnt working prior to emscripten v1.25
-  //
-  // But it only gives event inside the gl window.
-  // When dragging (for rotation etc) we want the drag/rotate to continue outside the window
-  //
-  // So we'll disable this handling for now
-  //
-  SDL_Event event;
-  while (SDL_PollEvent(&event))
-  {
-  } // Poll(event)
-
-} // ProcessEvents()
-
-
-void EmscriptenUpdateOnce()
-{
-  DALI_ASSERT_ALWAYS(app);
-  app->DoUpdate();
-};
-
-void EmscriptenRenderOnce()
-{
-  DALI_ASSERT_ALWAYS(app);
-
-  static int w = 0;
-  static int h = 0;
-
-  // 'Module' here should be 'dali' with emcc switch -s EXPORT_NAME="dali"
-  // but on upgrading to emscripten 1.34.2 it's broken.
-  int _x = EM_ASM_INT_V({ return Module.canvas.width;  });
-  int _y = EM_ASM_INT_V({ return Module.canvas.height; });
-
-  bool resize = false;
-  if( _x != w )
-  {
-    w = _x;
-    resize = true;
-  }
-  if( _y != h )
-  {
-    h = _y;
-    resize = true;
-  }
-  if( resize )
-  {
-    app->SetSurfaceWidth(w, h);
-  }
-
-  ProcessEvents();
-
-  EmscriptenUpdateOnce();
-
-  app->DoRender();
-
-  Dali::Internal::Emscripten::RenderFinished();
-}
-
-int main(int argc, char *argv[])
-{
-  using namespace Dali;
-
-  // need to reference everything as emscripten/llvm will cut it all out so put a Actor here
-  Dali::Actor actor;
-
-  app = new SdlApplication( 0, 0, SdlApplication::DEFAULT_HORIZONTAL_DPI,  SdlApplication::DEFAULT_VERTICAL_DPI );
-
-  emscripten_set_main_loop(EmscriptenRenderOnce, 0, 1);
-
-  return 1;
-}
diff --git a/adaptors/emscripten/sdl-application.cpp b/adaptors/emscripten/sdl-application.cpp
deleted file mode 100644 (file)
index 8cca15d..0000000
+++ /dev/null
@@ -1,247 +0,0 @@
-// EXTERNAL INCLUDES
-#include "sdl-application.h"
-
-#include <SDL.h>
-#include <SDL_image.h>
-#include <X11/Xlib.h>
-#include <EGL/egl.h>
-#include <SDL_syswm.h>
-#include <stdio.h>
-#include <sys/select.h>
-#include <sys/ioctl.h>
-#include <termios.h>
-#include <stropts.h>
-#include <unistd.h>
-
-#include <dali/public-api/dali-core.h>
-#include <dali/integration-api/events/touch-event-integ.h>
-
-// INTERNAL INCLUDES
-#include "integration-api/egl-interface.h"
-#include "base/separate-update-render/frame-time.h"
-#include <gl/egl-implementation.h>
-
-#include "platform-abstractions/emscripten/emscripten-callbacks.h"
-
-// emscripten are using SDL version 1.3 that isnt available for download
-// but version 2.0 is close to version 1.3 but version 1.2 support removed.
-// This is one way it isnt.
-#if SDL_MAJOR_VERSION == 2
-# define VIDEO_FLAGS SDL_WINDOW_OPENGL
-#else
-# define VIDEO_FLAGS SDL_OPENGL
-#endif
-
-namespace
-{
-
-void LogFunction(Dali::Integration::Log::DebugPriority priority, std::string& message)
-{
-  printf("%s", message.c_str());
-  EM_ASM( console.log( message.c_str() ) );
-}
-
-}
-
-namespace Dali
-{
-
-typedef ::Pixmap XPixmap;
-typedef ::Window XWindow;
-typedef ::Display XDisplay;
-typedef ::Screen XScreen;
-
-const unsigned int SdlApplication::DEFAULT_SURFACE_WIDTH = 600;
-const unsigned int SdlApplication::DEFAULT_SURFACE_HEIGHT= 480;
-
-
-SdlApplication::SdlApplication( size_t surfaceWidth,
-                                size_t surfaceHeight,
-                                float  horizontalDpi,
-                                float  verticalDpi )
-  : mCore( NULL ),
-    mSurfaceWidth( surfaceWidth ),
-    mSurfaceHeight( surfaceHeight ),
-    mFrame( 0u ),
-    mSeconds(0),
-    mMicroSeconds(0)
-{
-
-  EGLNativeDisplayType  display        = (EGLNativeDisplayType)XOpenDisplay(NULL);
-  bool                  isOwnSurface   = true;
-  mEglImplementation.InitializeGles( display, isOwnSurface );
-
-  SdlCreateWindow(surfaceWidth, surfaceHeight, "Dali");
-
-  bool                  isWindowType      = true;
-  Dali::ColorDepth      depth             = Dali::COLOR_DEPTH_32;
-  mEglImplementation.ChooseConfig( isWindowType, depth );
-
-  EGLNativeWindowType window = NULL;
-
-  mEglImplementation.CreateSurfaceWindow( window, depth );
-
-  mEglImplementation.CreateContext();
-
-  mEglImplementation.MakeContextCurrent();
-
-  //
-  // SDL/EGL setup, now create core
-  //
-  mCore = Dali::Integration::Core::New(
-    mRenderController,
-    mPlatformAbstraction,
-    mGlAbstraction,
-    mGlSyncAbstraction,
-    mGestureManager,
-    ResourcePolicy::DataRetention::DALI_RETAINS_ALL_DATA);
-
-  mCore->ContextCreated();
-  mCore->SurfaceResized( mSurfaceWidth, mSurfaceHeight );
-  mCore->SetDpi( horizontalDpi, verticalDpi );
-
-  Dali::Integration::Log::InstallLogFunction( LogFunction );
-
-  mCore->SceneCreated();
-}
-
-SdlApplication::~SdlApplication()
-{
-  Dali::Integration::Log::UninstallLogFunction();
-  delete mCore;
-  SDL_Quit();
-}
-
-void SdlApplication::SdlCreateWindow(size_t surfaceWidth,
-                                     size_t surfaceHeight,
-                                     const std::string &title)
-{
-  if( SDL_Init( SDL_INIT_VIDEO ) < 0 )
-  {
-    DALI_LOG_WARNING("SDL_Init Err: %s\n", SDL_GetError() );
-    DALI_ASSERT_ALWAYS(!"Couldn't initialize SDL");
-  }
-
-  // load support for the JPG and PNG image formats
-  int flags    = IMG_INIT_JPG | IMG_INIT_PNG;
-  int initted  = IMG_Init(flags);
-  if( (initted & flags) != flags)
-  {
-    DALI_LOG_WARNING("IMG_Init Err:%s\n", IMG_GetError());
-    DALI_ASSERT_ALWAYS("!IMG_Init: Failed to init required jpg and png support!\n");
-  }
-
-  float gamma      = 0.0;
-  int bpp          = 0; // 0 means current display bpp
-
-  Uint32 video_flags = VIDEO_FLAGS;
-
-  SDL_Surface *surface = SDL_SetVideoMode( static_cast<int>(surfaceWidth),
-                                           static_cast<int>(surfaceHeight),
-                                           bpp,
-                                           video_flags );
-
-  if ( surface == NULL )
-  {
-    DALI_LOG_WARNING("Couldn't set GL mode: %s\n", SDL_GetError());
-    DALI_ASSERT_ALWAYS("Couldn't set GL mode");
-    SDL_Quit();
-    exit(1);
-  }
-
-  /* Set the window manager title bar */
-  SDL_WM_SetCaption( title.c_str(), "daliweb" );
-
-  /* Set the gamma for the window */
-  if ( gamma != 0.0 )
-  {
-    SDL_SetGamma(gamma, gamma, gamma);
-  }
-
-}
-
-void SdlApplication::DoUpdate( void )
-{
-  // pump events
-  mCore->ProcessEvents();
-
-  // Update Time values
-  static Internal::Adaptor::FrameTime frameTime;
-  static bool init = false;
-  if( !init )
-  {
-    frameTime.SetMinimumFrameTimeInterval( 16667 );
-    init = true;
-  }
-
-  static unsigned int frameNo = 0;
-  frameNo++;
-  frameTime.SetSyncTime(frameNo);
-
-  float lastFrameDelta( 0.0f );
-  unsigned int lastSyncTime( 0 );
-  unsigned int nextSyncTime( 0 );
-  frameTime.PredictNextSyncTime( lastFrameDelta, lastSyncTime, nextSyncTime );
-
-  Integration::UpdateStatus status;
-
-  mCore->Update( lastFrameDelta, lastSyncTime, nextSyncTime, status );
-
-  Dali::Internal::Emscripten::stats.lastFrameDeltaSeconds = lastFrameDelta;
-  Dali::Internal::Emscripten::stats.lastSyncTimeMilliseconds = lastSyncTime;
-  Dali::Internal::Emscripten::stats.nextSyncTimeMilliseconds = nextSyncTime;
-
-  Dali::Internal::Emscripten::stats.keepUpdating = status.keepUpdating;
-  Dali::Internal::Emscripten::stats.needsNotification = status.needsNotification;
-  Dali::Internal::Emscripten::stats.secondsFromLastFrame = status.secondsFromLastFrame;
-
-}
-
-
-void SdlApplication::DoRender()
-{
-  // render
-  mCore->Render( mRenderStatus );
-
-  mFrame++;
-
-  Dali::Internal::Emscripten::stats.frameCount = mFrame;
-
-  mEglImplementation.SwapBuffers();
-
-}
-
-void SdlApplication::SendTouchEvent(double x, double y, int mouseState)
-{
-  PointState::Type state = PointState::UP;
-  if( 0 == mouseState )
-  {
-    state = PointState::DOWN;
-  }
-  else if( 1 == mouseState )
-  {
-    state = PointState::UP;
-  }
-  else if( 2 == mouseState )
-  {
-    state = PointState::MOTION;
-  }
-
-  Dali::Integration::TouchEvent e;
-  Dali::Integration::Point point;
-  point.SetState( state );
-  point.SetScreenPosition( Vector2( static_cast<float>(x), static_cast<float>(y) ) );
-  e.AddPoint( point );
-
-  mCore->QueueEvent(e);
-}
-
-void SdlApplication::SetSurfaceWidth( unsigned int width, unsigned height )
-{
-  mSurfaceWidth = width;
-  mSurfaceHeight = height;
-
-  mCore->SurfaceResized( mSurfaceWidth, mSurfaceHeight );
-}
-
-}
diff --git a/adaptors/emscripten/sdl-application.h b/adaptors/emscripten/sdl-application.h
deleted file mode 100644 (file)
index d95c4db..0000000
+++ /dev/null
@@ -1,143 +0,0 @@
-#ifndef __DALI_SDL_APPLICATION_H__
-#define __DALI_SDL_APPLICATION_H__
-
-/*
-Copyright (c) 2016 Samsung Electronics Co., Ltd All Rights Reserved
-
-This file is part of Dali
-
-PROPRIETARY/CONFIDENTIAL
-
-This software is the confidential and proprietary information of
-SAMSUNG ELECTRONICS ("Confidential Information"). You shall not
-disclose such Confidential Information and shall use it only in
-accordance with the terms of the license agreement you entered
-into with SAMSUNG ELECTRONICS.
-
-SAMSUNG make no representations or warranties about the suitability
-of the software, either express or implied, including but not limited
-to the implied warranties of merchantability, fitness for a particular
-purpose, or non-infringement. SAMSUNG shall not be liable for any
-damages suffered by licensee as a result of using, modifying or
-distributing this software or its derivatives.
-*/
-
-// INTERNAL INCLUDES
-#include "platform-abstractions/emscripten/emscripten-platform-abstraction.h"
-#include "sdl-gesture-manager.h"
-#include "adaptors/common/gl/gl-implementation.h"
-#include "sdl-gl-sync-abstraction.h"
-#include "sdl-render-controller.h"
-#include <dali/public-api/common/dali-common.h>
-#include <dali/public-api/signals/connection-tracker.h>
-#include <dali/integration-api/core.h>
-#include <gl/egl-implementation.h>
-
-namespace Dali
-{
-
-/**
- *
- * An SdlApplication object for Emscripten main()
- *
- * This provides libSDL calls for creating the application surface and running
- * the update and rendering.
- * The libSDL calls are stubbed by Emscripten into browser canvas construction
- * calls. The update and rendering are exposed as we are in a single threaded
- * environment and the browser needs to control the main loop.
- * Emscripten provides emscripten_set_main_loop() for the 'loop' function which
- * should render one frame and return
- *
- */
-class DALI_IMPORT_API SdlApplication : public ConnectionTracker
-{
-public:
-
-  // Default values derived from H2 device.
-  static const unsigned int DEFAULT_SURFACE_WIDTH;
-  static const unsigned int DEFAULT_SURFACE_HEIGHT;
-
-#ifdef _CPP11
-  static constexpr float DEFAULT_HORIZONTAL_DPI = 220.0f;
-  static constexpr float DEFAULT_VERTICAL_DPI   = 217.0f;
-#else
-  static const float DEFAULT_HORIZONTAL_DPI = 220.0f;
-  static const float DEFAULT_VERTICAL_DPI   = 217.0f;
-#endif
-
-  static const unsigned int DEFAULT_RENDER_INTERVAL = 1;
-
-  /**
-   * Constructor
-   *
-   * @param[in] surfaceWidth  Initial width of the browser canvas
-   * @param[in] surfaceHeight Initial height of the browser canvas
-   * @param[in] horizontalDpi Horizontal Dpi
-   * @param[in] verticalDpi Vertical Dpi
-   */
-  SdlApplication( size_t surfaceWidth  = DEFAULT_SURFACE_WIDTH,
-                  size_t surfaceHeight = DEFAULT_SURFACE_HEIGHT,
-                  float  horizontalDpi = DEFAULT_HORIZONTAL_DPI,
-                  float  verticalDpi   = DEFAULT_VERTICAL_DPI );
-
-  /**
-   * Destructor
-   */
-  virtual ~SdlApplication();
-
-  /**
-   * Run the update once.
-   * The browser is a single threaded environment and this is called on a browser callback.
-   */
-  void DoUpdate();
-
-  /**
-   * Render once. The browser is a single threaded environment.
-   * The browser is a single threaded environment and this is called on a browser callback.
-   */
-  void DoRender();
-
-  /**
-   * Send Touch event into Dali event loop.
-   * The allows the browser to supply touch events.
-   */
-  void SendTouchEvent(double x, double y, int downUpMotion);
-
-  /**
-   * Set surface width.
-   * The allows the browser to tell Dali that the rendering canvas has changed size.
-   *
-   * @param[in] width  The surface/canvas width
-   * @param[in] height The surface/canvas height
-   */
-  void SetSurfaceWidth( unsigned int width, unsigned height );
-
-protected:
-  EmscriptenPlatformAbstraction        mPlatformAbstraction;
-  SdlGlSyncAbstraction                 mGlSyncAbstraction;
-  SdlRenderController                  mRenderController;
-  Internal::Adaptor::GlImplementation  mGlAbstraction;
-  SdlGestureManager                    mGestureManager;
-
-  Integration::UpdateStatus            mStatus;
-  Integration::RenderStatus            mRenderStatus;
-
-  Integration::Core*                   mCore;
-  Internal::Adaptor::EglImplementation mEglImplementation;
-
-  unsigned int mSurfaceWidth;
-  unsigned int mSurfaceHeight;
-  unsigned int mFrame;
-
-  unsigned int mSeconds;
-  unsigned int mMicroSeconds;
-
-  void SdlCreateWindow(size_t surfaceWidth,
-                       size_t surfaceHeight,
-                       const std::string &title);
-
-};
-
-} // Dali
-
-#endif // header
diff --git a/adaptors/emscripten/sdl-gesture-manager.h b/adaptors/emscripten/sdl-gesture-manager.h
deleted file mode 100644 (file)
index ddea4b7..0000000
+++ /dev/null
@@ -1,146 +0,0 @@
-#ifndef __DALI_SDL_GESTURE_MANAGER_H__
-#define __DALI_SDL_GESTURE_MANAGER_H__
-
-/*
-Copyright (c) 2000-2012 Samsung Electronics Co., Ltd All Rights Reserved
-
-This file is part of Dali
-
-PROPRIETARY/CONFIDENTIAL
-
-This software is the confidential and proprietary information of
-SAMSUNG ELECTRONICS ("Confidential Information"). You shall not
-disclose such Confidential Information and shall use it only in
-accordance with the terms of the license agreement you entered
-into with SAMSUNG ELECTRONICS.
-
-SAMSUNG make no representations or warranties about the suitability
-of the software, either express or implied, including but not limited
-to the implied warranties of merchantability, fitness for a particular
-purpose, or non-infringement. SAMSUNG shall not be liable for any
-damages suffered by licensee as a result of using, modifying or
-distributing this software or its derivatives.
-*/
-
-// INTERNAL INCLUDES
-#include <dali/integration-api/gesture-manager.h>
-#include <dali/public-api/common/dali-common.h>
-
-namespace Dali
-{
-
-/**
- * Concrete implementation of the gesture manager class.
- *
- * A stubb class to give to core in the Emscripten/browser environment
- */
-class DALI_IMPORT_API SdlGestureManager : public Dali::Integration::GestureManager
-{
-
-public:
-
-  /**
-   * Constructor
-   */
-  SdlGestureManager()
-  {
-    Initialize();
-  }
-
-  /**
-   * Destructor
-   */
-  virtual ~SdlGestureManager()
-  {
-  }
-
-  /**
-   * @copydoc Dali::Integration::GestureManager::Register(Gesture::Type)
-   */
-  virtual void Register(const Integration::GestureRequest& request)
-  {
-    mFunctionsCalled.Register = true;
-  }
-
-  /**
-   * @copydoc Dali::Integration::GestureManager::Unregister(Gesture::Type)
-   */
-  virtual void Unregister(const Integration::GestureRequest& request)
-  {
-    mFunctionsCalled.Unregister = true;
-  }
-
-  /**
-   * @copydoc Dali::Integration::GestureManager::Update(Gesture::Type)
-   */
-  virtual void Update(const Integration::GestureRequest& request)
-  {
-    mFunctionsCalled.Update = true;
-  }
-
-public: // TEST FUNCTIONS
-
-  // Enumeration of Gesture Manager methods
-  enum SdlFuncEnum
-  {
-    RegisterType,
-    UnregisterType,
-    UpdateType,
-  };
-
-  /** Call this every test */
-  void Initialize()
-  {
-    mFunctionsCalled.Reset();
-  }
-
-  bool WasCalled(SdlFuncEnum func)
-  {
-    switch(func)
-    {
-      case RegisterType:             return mFunctionsCalled.Register;
-      case UnregisterType:           return mFunctionsCalled.Unregister;
-      case UpdateType:               return mFunctionsCalled.Update;
-    }
-    return false;
-  }
-
-  void ResetCallStatistics(SdlFuncEnum func)
-  {
-    switch(func)
-    {
-      case RegisterType:             mFunctionsCalled.Register = false; break;
-      case UnregisterType:           mFunctionsCalled.Unregister = false; break;
-      case UpdateType:               mFunctionsCalled.Update = false; break;
-    }
-  }
-
-private:
-
-  struct SdlFunctions
-  {
-    SdlFunctions()
-    : Register(false),
-      Unregister(false),
-      Update(false)
-    {
-    }
-
-    void Reset()
-    {
-      Register = false;
-      Unregister = false;
-      Update = false;
-    }
-
-    bool Register;
-    bool Unregister;
-    bool Update;
-  };
-
-  SdlFunctions mFunctionsCalled;
-};
-
-} // Dali
-
-#endif // __DALI_SDL_GESTURE_MANAGER_H__
diff --git a/adaptors/emscripten/sdl-gl-sync-abstraction.cpp b/adaptors/emscripten/sdl-gl-sync-abstraction.cpp
deleted file mode 100644 (file)
index fe52e6c..0000000
+++ /dev/null
@@ -1,32 +0,0 @@
-#include "sdl-gl-sync-abstraction.h"
-
-using namespace Dali;
-
-
-class SdlSyncObject : public Integration::GlSyncAbstraction::SyncObject
-{
-public:
-  virtual bool IsSynced() { return true; }
-};
-
-
-SdlGlSyncAbstraction::~SdlGlSyncAbstraction()
-{
-}
-
-bool SdlGlSyncAbstraction::SyncObject::IsSynced()
-{
-  return true;
-}
-
-Integration::GlSyncAbstraction::SyncObject* SdlGlSyncAbstraction::CreateSyncObject()
-{
-  return new SdlSyncObject();
-}
-
-
-void SdlGlSyncAbstraction::DestroySyncObject(Integration::GlSyncAbstraction::SyncObject* syncObject)
-{
-  delete static_cast<SdlSyncObject*>( syncObject );
-}
-
diff --git a/adaptors/emscripten/sdl-gl-sync-abstraction.h b/adaptors/emscripten/sdl-gl-sync-abstraction.h
deleted file mode 100644 (file)
index 21b536b..0000000
+++ /dev/null
@@ -1,48 +0,0 @@
-#ifndef __DALI_INTEGRATION_SDL_GL_SYNC_ABSTRACTION_H__
-#define __DALI_INTEGRATION_SDL_GL_SYNC_ABSTRACTION_H__
-
-//
-// Copyright (c) 2014 Samsung Electronics Co., Ltd.
-//
-// Licensed under the Flora License, Version 1.0 (the License);
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//     http://floralicense.org/license/
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an AS IS BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-//
-
-#include <dali/integration-api/gl-sync-abstraction.h>
-
-namespace Dali
-{
-
-/**
- *
- * This is a stubb GLSyncAbstraction class to pass to core for the Emscripten/browser environment
- */
-class DALI_IMPORT_API SdlGlSyncAbstraction : public Dali::Integration::GlSyncAbstraction
-{
-public:
-
-  virtual ~SdlGlSyncAbstraction();
-
-  /**
-   * @copydoc Dali::Integration::GlSyncAbstraction::CreateSyncObject()
-   */
-  virtual Integration::GlSyncAbstraction::SyncObject* CreateSyncObject();
-
-  /**
-   * @copydoc Dali::Integration::GlSyncAbstraction::DestroySyncObject(Integration::GlSyncAbstraction::SyncObject* syncObject)
-   */
-  virtual void DestroySyncObject(Integration::GlSyncAbstraction::SyncObject* syncObject);
-};
-
-} // namespace Dali
-
-#endif // __DALI_INTEGRATION_SDL_GL_SYNC_ABSTRACTION_H__
diff --git a/adaptors/emscripten/sdl-render-controller.h b/adaptors/emscripten/sdl-render-controller.h
deleted file mode 100644 (file)
index d113c69..0000000
+++ /dev/null
@@ -1,83 +0,0 @@
-#ifndef __SDL_RENDER_CONTROLLER_H__
-#define __SDL_RENDER_CONTROLLER_H__
-
-/*
-Copyright (c) 2000-2012 Samsung Electronics Co., Ltd All Rights Reserved
-
-This file is part of Dali
-
-PROPRIETARY/CONFIDENTIAL
-
-This software is the confidential and proprietary information of
-SAMSUNG ELECTRONICS ("Confidential Information"). You shall not
-disclose such Confidential Information and shall use it only in
-accordance with the terms of the license agreement you entered
-into with SAMSUNG ELECTRONICS.
-
-SAMSUNG make no representations or warranties about the suitability
-of the software, either express or implied, including but not limited
-to the implied warranties of merchantability, fitness for a particular
-purpose, or non-infringement. SAMSUNG shall not be liable for any
-damages suffered by licensee as a result of using, modifying or
-distributing this software or its derivatives.
-*/
-
-// INTERNAL INCLUDES
-#include <dali/integration-api/render-controller.h>
-
-namespace Dali
-{
-
-/**
- * This class is a stubb RenderController to pass to core in the Emscripten/browser environment.
- *
- */
-class DALI_IMPORT_API SdlRenderController : public Dali::Integration::RenderController
-{
-public:
-  SdlRenderController()
-  {
-    Initialize();
-  }
-
-  ~SdlRenderController()
-  {
-  }
-
-  /**
-   * @copydoc Dali::Integration::RenderController::RequestUpdate()
-   */
-  virtual void RequestUpdate()
-  {
-    mRequestUpdateCalled = true;
-  }
-
-  /**
-   * @copydoc Dali::Integration::RenderController::RequestProcessEventsOnIdle()
-   */
-  virtual void RequestProcessEventsOnIdle()
-  {
-  }
-
-  /**
-   * @copydoc Dali::Integration::RenderController::RequestNotificationEventOnIdle()
-   */
-  virtual void RequestNotificationEventOnIdle()
-  {
-    mRequestNotificationEventOnIdleCalled = true;
-  }
-
-  void Initialize()
-  {
-    mRequestUpdateCalled = false;
-    mRequestNotificationEventOnIdleCalled = false;
-  }
-
-private:
-  bool mRequestUpdateCalled;
-  bool mRequestNotificationEventOnIdleCalled;
-};
-
-} // Dali
-
-#endif
diff --git a/adaptors/emscripten/wrappers/actor-wrapper.cpp b/adaptors/emscripten/wrappers/actor-wrapper.cpp
deleted file mode 100644 (file)
index 2b3911f..0000000
+++ /dev/null
@@ -1,308 +0,0 @@
-/*
- * Copyright (c) 2015 Samsung Electronics Co., Ltd.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- */
-
-#include "actor-wrapper.h"
-
-// EXTERNAL INCLUDES
-#include <dali/devel-api/scripting/scripting.h>
-
-// INTERNAL INCLUDES
-#include "emscripten-utils.h"
-#include "signal-holder.h"
-
-namespace
-{
-  enum ConditionType
-  {
-    False,                ///< Result Always False
-    LessThan,             ///< Magnitude of type is less than float value (arg0).
-    GreaterThan,          ///< Magnitude of type is greater than float value (arg0).
-    Inside,               ///< Magnitude of type is within float values (arg0 & arg1).
-    Outside,              ///< Magnitude of type is outside float values (arg0 & arg1).
-    Step,                 ///< Value of type has crossed a step amount
-    VariableStep          ///< Similar to step, except user can define a list of steps from reference value
-  };
-
-  Dali::Scripting::StringEnum ConditionTypeTable[] =
-  { { "False",           ConditionType::False},
-    { "LessThan",        ConditionType::LessThan},
-    { "GreaterThan",     ConditionType::GreaterThan},
-    { "Inside",          ConditionType::Inside},
-    { "Outside",         ConditionType::Outside},
-    { "Step",            ConditionType::Step},
-    { "VariableStep",    ConditionType::VariableStep}
-  };
-
-const unsigned int ConditionTypeTableSize = sizeof( ConditionTypeTable ) / sizeof( ConditionTypeTable[0] );
-
-};
-
-namespace Dali
-{
-namespace Internal
-{
-namespace Emscripten
-{
-
-emscripten::val JavascriptValue( const Dali::Property::Value& v );
-
-/**
- * Struct to hold notification callback
- */
-struct EmscriptenNotifiy
-{
-  EmscriptenNotifiy(const emscripten::val& callback )
-    : mCallback(callback) {};
-  emscripten::val mCallback;
-
-  void operator()(void)
-  {
-    emscripten::val ret = mCallback();
-  }
-};
-
-/**
- * Emscripten touched signal callback.
- *
- * Provides more contextual state information to the browser with the OnTouched signal.
- *
- */
-struct EmscriptenTouchedSignal : public BaseSignalSlot
-{
-  EmscriptenTouchedSignal(const emscripten::val& callback, unsigned int id)
-    : mCallback(callback), mId(id)  {};
-  emscripten::val mCallback;
-  unsigned int mId;
-
-  bool OnTouched(Dali::Actor actor, const Dali::TouchData& touch)
-  {
-    Dali::Property::Map map;
-    Dali::Property::Array points;
-
-    const int pointCount = static_cast<int>( touch.GetPointCount() );
-
-    map["pointCount"] = pointCount;
-    map["time"] = static_cast<int>( touch.GetTime() );
-
-    for( int i = 0; i < pointCount; ++i )
-    {
-      Dali::Property::Map pointMap;
-      Dali::Actor hitActor = touch.GetHitActor( i );
-
-      pointMap["deviceId"] = touch.GetDeviceId( i );
-      pointMap["hitActorId"] = static_cast<int>( hitActor ? hitActor.GetId() : -1 );
-      pointMap["local"] = touch.GetLocalPosition( i );
-      pointMap["screen"]= touch.GetScreenPosition( i );
-
-      switch( touch.GetState( i ) )
-      {
-        case PointState::DOWN:        { pointMap["state"] = "DOWN";         break; }
-        case PointState::UP:          { pointMap["state"] = "UP";           break; }
-        case PointState::MOTION:      { pointMap["state"] = "MOTION";       break; }
-        case PointState::LEAVE:       { pointMap["state"] = "LEAVE";        break; }
-        case PointState::STATIONARY:  { pointMap["state"] = "STATIONARY";   break; }
-        case PointState::INTERRUPTED: { pointMap["state"] = "INTERRUPTED";  break; }
-      };
-
-      points.PushBack(pointMap);
-    }
-
-    map["points"] = points;
-
-    Dali::Property::Value value(map);
-    emscripten::val ret = mCallback( actor, JavascriptValue(value) );
-    return true;
-  }
-
-  bool OnHovered(Dali::Actor actor, const Dali::HoverEvent& event)
-  {
-    Dali::Property::Map map;
-    Dali::Property::Array points;
-
-    map["pointCount"] = static_cast<int>(event.GetPointCount());
-    map["time"] = static_cast<int>(event.time);
-
-    for(TouchPointContainer::const_iterator iter = event.points.begin();
-        iter != event.points.end(); ++iter) {
-      const Dali::TouchPoint& pt = *iter;
-      Dali::Property::Map pointMap;
-      pointMap["deviceId"] = pt.deviceId;
-      pointMap["hitActorId"] = static_cast<int>(pt.hitActor.GetId());
-      pointMap["local"] = pt.local;
-      pointMap["screen"]= pt.screen;
-
-      switch(pt.state)
-      {
-        case TouchPoint::Down:        { pointMap["state"] = "Down"; break; }
-        case TouchPoint::Up:          { pointMap["state"] = "Up"; break; }
-        case TouchPoint::Motion:      { pointMap["state"] = "Motion"; break; }
-        case TouchPoint::Leave:       { pointMap["state"] = "Leave"; break; }
-        case TouchPoint::Stationary:  { pointMap["state"] = "Stationary"; break; }
-        case TouchPoint::Interrupted: { pointMap["state"] = "Interrupted"; break; }
-        case TouchPoint::Last:        { pointMap["state"] = "Last"; break; }
-      };
-
-      points.PushBack(pointMap);
-    }
-
-    map["points"] = points;
-
-    Dali::Property::Value value(map);
-    emscripten::val ret = mCallback( actor, JavascriptValue(value) );
-    return true;
-  }
-
-};
-
-/**
- * Struct to wrap a generic Emscripten callback.
- *
- */
-struct EmscriptenSignal
-{
-  EmscriptenSignal(const emscripten::val& callback, unsigned int id)
-    : mCallback(callback), mId(id) {};
-  emscripten::val mCallback;
-  unsigned int mId;
-  bool operator()()
-  {
-    Dali::Actor a = Dali::Stage::GetCurrent().GetRootLayer().FindChildById(mId);
-    if(a)
-    {
-      emscripten::val ret = mCallback( a );
-    }
-    else
-    {
-      emscripten::val ret = mCallback();
-    }
-    return true;
-  }
-};
-
-bool ConnectSignal( Dali::Actor actor,
-                    SignalHolder& signalHolder,
-                    const std::string& signalName,
-                    const emscripten::val& javascriptFunction )
-{
-  bool ret = false;
-  if(0 == signalName.compare("touched"))
-  {
-    EmscriptenTouchedSignal* slot = new EmscriptenTouchedSignal(javascriptFunction, actor.GetId());
-    actor.TouchSignal().Connect(slot, &EmscriptenTouchedSignal::OnTouched);
-    signalHolder.add(slot);
-    ret = true;
-  }
-  else if(0 == signalName.compare("hovered"))
-  {
-    EmscriptenTouchedSignal* slot = new EmscriptenTouchedSignal(javascriptFunction, actor.GetId());
-    actor.HoveredSignal().Connect(slot, &EmscriptenTouchedSignal::OnHovered);
-    signalHolder.add(slot);
-    ret = true;
-  }
-  else
-  {
-    actor.ConnectSignal( &signalHolder, signalName, EmscriptenSignal(javascriptFunction, actor.GetId()));
-    ret = true;
-  }
-
-  return ret;
-}
-
-unsigned int AddressOf(Dali::Actor self)
-{
-  return (unsigned int)&self.GetBaseObject();
-}
-
-std::vector<float> ScreenToLocal(Dali::Actor self, float screenX, float screenY)
-{
-  std::vector<float> ret;
-  float localX = 0.f;
-  float localY = 0.f;
-  bool ok = self.ScreenToLocal(localX, localY, screenX, screenY);
-  if( ok )
-  {
-    ret.push_back(localX);
-    ret.push_back(localY);
-    ret.push_back(1.0);
-  }
-  else
-  {
-    ret.push_back(0.0);
-    ret.push_back(0.0);
-    ret.push_back(0.0);
-  }
-  return ret;
-}
-
-void SetPropertyNotification( Dali::Actor self,
-                              SignalHolder& signalHolder,
-                              Dali::Property::Index index, const std::string& propertyConditionType, float arg0, float arg1,
-                              const emscripten::val& javascriptFunction)
-{
-  unsigned int i = FindEnumIndex( propertyConditionType.c_str(), ConditionTypeTable, ConditionTypeTableSize );
-
-  if( i < ConditionTypeTableSize )
-  {
-    ConditionType type = static_cast<ConditionType>(ConditionTypeTable[i].value);
-    Dali::PropertyNotification notification;
-    switch(type)
-    {
-      case ConditionType::False:
-      {
-        notification = self.AddPropertyNotification( index, Dali::LessThanCondition(arg0) );
-      }
-      case ConditionType::LessThan:
-      {
-        notification = self.AddPropertyNotification( index, Dali::LessThanCondition(arg0) );
-      }
-      case ConditionType::GreaterThan:
-      {
-        notification = self.AddPropertyNotification( index, Dali::GreaterThanCondition(arg0) );
-      }
-      case ConditionType::Inside:
-      {
-        notification = self.AddPropertyNotification( index, Dali::InsideCondition(arg0, arg1) );
-      }
-      case ConditionType::Outside:
-      {
-        notification = self.AddPropertyNotification( index, Dali::OutsideCondition(arg0, arg1) );
-      }
-      case ConditionType::Step:
-      {
-        notification = self.AddPropertyNotification( index, Dali::StepCondition(arg0, arg1) );
-      }
-      case ConditionType::VariableStep:
-      {
-        notification = self.AddPropertyNotification( index, Dali::StepCondition(arg0, arg1) );
-      }
-    };
-
-    if(notification)
-    {
-      notification.NotifySignal().Connect( &signalHolder, FunctorDelegate::New(EmscriptenNotifiy(javascriptFunction)) );
-    }
-    else
-    {
-      EM_ASM( throw "Cannot set notification" );
-    }
-  }
-}
-
-
-}; // namespace Emscripten
-}; // namespace Internal
-}; // namespace Dali
diff --git a/adaptors/emscripten/wrappers/actor-wrapper.h b/adaptors/emscripten/wrappers/actor-wrapper.h
deleted file mode 100644 (file)
index 6a35cda..0000000
+++ /dev/null
@@ -1,99 +0,0 @@
-#ifndef __DALI_ACTOR_WRAPPER_H__
-#define __DALI_ACTOR_WRAPPER_H__
-
-/*
- * Copyright (c) 2015 Samsung Electronics Co., Ltd.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- */
-
-// EXTERNAL INCLUDES
-#include <dali/public-api/dali-core.h>
-#include "emscripten/emscripten.h"
-#include "emscripten/val.h"
-
-// INTERNAL INCLUDES
-#include "signal-holder.h"
-
-namespace Dali
-{
-namespace Internal
-{
-namespace Emscripten
-{
-
-/**
- * Exposes a representation of the actor base object pointer for javascript debugging
- *
- * @param[in] self The dali actor
- *
- * @return the address as an int
- */
-unsigned int AddressOf(Dali::Actor self);
-
-/**
- * Provides screen to local values conveniently for javascript
- *
- * @param[in] self The dali actor
- * @param[in] screenX The screen X coordinate
- * @param[in] screenY The screen Y coordinate
- *
- * @return the local coordinates
- */
-std::vector<float> ScreenToLocal(Dali::Actor self, float screenX, float screenY);
-
-/**
- * Connect a javascript function to a dali signal.
- *
- * Handles touched and hovered specially to provide more context than Dali provides.
- *
- * @param[in] actor The dali actor
- * @param[in] signalHolder The Dali signal holder
- * @param[in] signalName The name of the signal
- * @param[in] javascriptFunction The function to call back when the signal is triggered
- *
- * @return the local coordinates
- *
- */
-bool ConnectSignal( Dali::Actor actor,
-                    SignalHolder& signalHolder,
-                    const std::string& signalName,
-                    const emscripten::val& javascriptFunction );
-
-/**
- * Sets a javascript function to an actor property notification
- *
- * @param[in] self The dali actor
- * @param[in] signalHolder The Dali signal holder
- * @param[in] index The property Index
- * @param[in] propertyConditionType The condition type name
- * @param[in] arg0 The property notification arg0
- * @param[in] arg1 The property notification arg1
- * @param[in] propertyConditionType The condition type name
- * @param[in] javascriptFunction The function to call back when the signal is triggered
- *
- * @return the local coordinates
-
- */
-void SetPropertyNotification( Dali::Actor self,
-                              SignalHolder& signalHolder,
-                              Dali::Property::Index index, const std::string& propertyConditionType, float arg0, float arg1,
-                              const emscripten::val& javascriptFunction);
-
-
-}; // namespace Emscripten
-}; // namespace Internal
-}; // namespace Dali
-
-#endif // header
diff --git a/adaptors/emscripten/wrappers/animation-wrapper.cpp b/adaptors/emscripten/wrappers/animation-wrapper.cpp
deleted file mode 100644 (file)
index eafd0c4..0000000
+++ /dev/null
@@ -1,211 +0,0 @@
-/*
- * Copyright (c) 2015 Samsung Electronics Co., Ltd.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- */
-
-// #include "animation-wrapper.h"
-
-// EXTERNAL INCLUDES
-#include "emscripten/emscripten.h"
-#include <dali/devel-api/scripting/scripting.h>
-
-// INTERNAL INCLUDES
-#include "property-value-wrapper.h"
-
-namespace Dali
-{
-namespace Internal
-{
-namespace Emscripten
-{
-
-void KeyFramesAddWithAlpha(Dali::KeyFrames& keyFrames, float progress, Property::Value& value,
-                           const std::string& alphaFunction)
-{
-  Dali::AlphaFunction func(AlphaFunction::LINEAR);
-
-  if( alphaFunction == "LINEAR" )
-  {
-    func = Dali::AlphaFunction(AlphaFunction::LINEAR);
-  }
-  else if( alphaFunction == "REVERSE" )
-  {
-    func = Dali::AlphaFunction(AlphaFunction::REVERSE);
-  }
-  else if( alphaFunction == "EASE_IN_SQUARE" )
-  {
-    func = Dali::AlphaFunction(AlphaFunction::EASE_IN_SQUARE);
-  }
-  else if( alphaFunction == "EASE_OUT_SQUARE" )
-  {
-    func = Dali::AlphaFunction(AlphaFunction::EASE_OUT_SQUARE);
-  }
-  else if( alphaFunction == "EASE_IN" )
-  {
-    func = Dali::AlphaFunction(AlphaFunction::EASE_IN);
-  }
-  else if( alphaFunction == "EASE_OUT" )
-  {
-    func = Dali::AlphaFunction(AlphaFunction::EASE_OUT);
-  }
-  else if( alphaFunction == "EASE_IN_OUT" )
-  {
-    func = Dali::AlphaFunction(AlphaFunction::EASE_IN_OUT);
-  }
-  else if( alphaFunction == "EASE_IN_SINE" )
-  {
-    func = Dali::AlphaFunction(AlphaFunction::EASE_IN_SINE);
-  }
-  else if( alphaFunction == "EASE_OUT_SINE" )
-  {
-    func = Dali::AlphaFunction(AlphaFunction::EASE_OUT_SINE);
-  }
-  else if( alphaFunction == "EASE_IN_OUT_SINE" )
-  {
-    func = Dali::AlphaFunction(AlphaFunction::EASE_IN_OUT_SINE);
-  }
-  else if( alphaFunction == "BOUNCE" )
-  {
-    func = Dali::AlphaFunction(AlphaFunction::BOUNCE);
-  }
-  else if( alphaFunction == "SIN" )
-  {
-    func = Dali::AlphaFunction(AlphaFunction::SIN);
-  }
-  else if( alphaFunction == "EASE_OUT_BACK" )
-  {
-    func = Dali::AlphaFunction(AlphaFunction::EASE_OUT_BACK);
-  }
-  else
-  {
-    EM_ASM( console.log( "KeyFramesAddWithAlpha: Unknown alpha function" ) );
-  }
-
-  keyFrames.Add(progress, value, func);
-}
-
-void AnimateTo(Dali::Animation& self,
-               Dali::Handle& handle,
-               const std::string& property,
-               const Dali::Property::Value& destinationValue,
-               const Dali::AlphaFunction::BuiltinFunction& alphaFunction,
-               const float delay,
-               const float duration)
-{
-  DALI_ASSERT_ALWAYS(self);
-
-  Dali::Property::Index propertyIndex = handle.GetPropertyIndex(property);
-
-  Dali::Property::Type propertyType = handle.GetPropertyType(propertyIndex);
-
-  if( propertyType != destinationValue.GetType() )
-  {
-    EM_ASM( throw "animateTo property types are not the same" );
-  }
-  else if( propertyIndex != Dali::Property::INVALID_INDEX )
-  {
-    Dali::Property target( handle, propertyIndex );
-    self.AnimateTo( target, destinationValue, alphaFunction, Dali::TimePeriod(delay, duration) );
-  }
-  else
-  {
-    EM_ASM( throw "unknown property" );
-  }
-}
-
-void AnimateBy(Dali::Animation& self,
-               Dali::Handle& handle,
-               const std::string& property,
-               const Dali::Property::Value& destinationValue,
-               const Dali::AlphaFunction::BuiltinFunction& alphaFunction,
-               const float delay,
-               const float duration)
-{
-  DALI_ASSERT_ALWAYS(self);
-
-  Dali::Property::Index propertyIndex = handle.GetPropertyIndex(property);
-
-  Dali::Property::Type propertyType = handle.GetPropertyType(propertyIndex);
-
-  if( propertyType != destinationValue.GetType() )
-  {
-    EM_ASM( throw "animateTo property types are not the same" );
-  }
-  else if( propertyIndex != Dali::Property::INVALID_INDEX )
-  {
-    Dali::Property target( handle, propertyIndex );
-    self.AnimateBy( target, destinationValue, alphaFunction, Dali::TimePeriod(delay,duration));
-  }
-  else
-  {
-    EM_ASM( throw "unknown property" );
-  }
-}
-
-void AnimateBetween(Dali::Animation& self,
-                    Dali::Handle& handle,
-                    const std::string& property,
-                    Dali::KeyFrames& keyFrames,
-                    const Dali::AlphaFunction::BuiltinFunction& alphaFunction,
-                    const float delay,
-                    const float duration,
-                    const Dali::Animation::Interpolation& interpolation)
-{
-  DALI_ASSERT_ALWAYS(self);
-
-  Dali::Property::Index propertyIndex = handle.GetPropertyIndex(property);
-
-  if( propertyIndex != Dali::Property::INVALID_INDEX )
-  {
-    Dali::Property target( handle, propertyIndex );
-    self.AnimateBetween(target, keyFrames, alphaFunction, Dali::TimePeriod(delay, duration), interpolation);
-  }
-  else
-  {
-    EM_ASM( throw "unknown property" );
-  }
-}
-
-void AnimatePath(Dali::Animation& self,
-                 Dali::Handle& target,
-                 const Dali::Path& path,
-                 const Dali::Vector3& forward,
-                 const Dali::AlphaFunction::BuiltinFunction& alphaFunction,
-                 const float delay,
-                 const float duration)
-{
-  DALI_ASSERT_ALWAYS(self);
-
-  if(!path)
-  {
-    printf("Unable to add animation, bad path object\n");
-  }
-  else
-  {
-    Dali::Actor actor = Dali::Actor::DownCast(target);
-    if( !actor )
-    {
-      printf("Unable to add path animation, bad actor\n");
-    }
-    else
-    {
-      self.Animate( actor, path, forward, alphaFunction, Dali::TimePeriod( delay, duration ) );
-    }
-  }
-}
-
-}; // namespace Emscripten
-}; // namespace Internal
-}; // namespace Dali
diff --git a/adaptors/emscripten/wrappers/animation-wrapper.h b/adaptors/emscripten/wrappers/animation-wrapper.h
deleted file mode 100644 (file)
index 6791811..0000000
+++ /dev/null
@@ -1,137 +0,0 @@
-#ifndef __DALI_ANIMATION_WRAPPER_H__
-#define __DALI_ANIMATION_WRAPPER_H__
-
-/*
- * Copyright (c) 2015 Samsung Electronics Co., Ltd.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- */
-
-// EXTERNAL INCLUDES
-#include <dali/public-api/dali-core.h>
-#include "emscripten/emscripten.h"
-#include "emscripten/bind.h"
-
-// INTERNAL INCLUDES
-#include "handle-wrapper.h"
-
-namespace Dali
-{
-namespace Internal
-{
-namespace Emscripten
-{
-
-/**
- * Keyframe animation helper functions for Emscripten.
- *
- * Allows a string alphaFunction
- *
- * @param[in] keyFrames The dali keyframes
- * @param[in] progress The keyframe progress
- * @param[in] value The property value
- * @param[in] alphaFunction The alpha function by name
- *
- */
-void KeyFramesAddWithAlpha(Dali::KeyFrames& keyFrames, float progress, Property::Value& value,
-                           const std::string& alphaFunction);
-
-
-/**
- * Animation helper functions for Emscripten.
- *
- * Allows string property names without function overloading which is unavailable with Javascript
- *
- * @param[in] self The animation
- * @param[in] handle The handle to animate
- * @param[in] property The property name to animate
- * @param[in] alphaFunction The alpha function
- * @param[in] delay The animation delay
- * @param[in] duration The animation duration
- *
- */
-void AnimateTo(Dali::Animation& self,
-               Dali::Handle& handle,
-               const std::string& property,
-               const Dali::Property::Value& destinationValue,
-               const Dali::AlphaFunction::BuiltinFunction& alphaFunction,
-               const float delay,
-               const float duration);
-
-/**
- * AnimateBy helper
- *
- * Allows string property names without function overloading which is unavailable with Javascript
- *
- * @param[in] self The animation
- * @param[in] handle The handle to animate
- * @param[in] property The property name to animate
- * @param[in] alphaFunction The alpha function
- * @param[in] delay The animation delay
- * @param[in] duration The animation duration
- */
-void AnimateBy(Dali::Animation& self,
-               Dali::Handle& handle,
-               const std::string& property,
-               const Dali::Property::Value& destinationValue,
-               const Dali::AlphaFunction::BuiltinFunction& alphaFunction,
-               const float delay,
-               const float duration);
-
-/**
- * AnimateBetween helper
- *
- * Allows string property names without function overloading which is unavailable with Javascript
- *
- * @param[in] self The animation
- * @param[in] handle The handle to animate
- * @param[in] property The property name to animate
- * @param[in] alphaFunction The alpha function
- * @param[in] delay The animation delay
- * @param[in] duration The animation duration
- */
-void AnimateBetween(Dali::Animation& self,
-                    Dali::Handle& handle,
-                    const std::string& property,
-                    Dali::KeyFrames& keyFrames,
-                    const Dali::AlphaFunction::BuiltinFunction& alphaFunction,
-                    const float delay,
-                    const float duration,
-                    const Dali::Animation::Interpolation& interpolation);
-
-/**
- * AnimatePath helper (see AnimateTo docs above)
- *
- * Allows string property names without function overloading which is unavailable with Javascript
- *
- * @param[in] self The animation
- * @param[in] target The handle to animate
- * @param[in] path The dali Path
- * @param[in] forward The path animation forward vector
- * @param[in] delay The animation delay
- * @param[in] duration The animation duration
- */
-void AnimatePath(Dali::Animation& self,
-                 Dali::Handle& target,
-                 const Dali::Path& path,
-                 const Dali::Vector3& forward,
-                 const Dali::AlphaFunction::BuiltinFunction& alphaFunction,
-                 const float delay,
-                 const float duration);
-
-}; // namespace Emscripten
-}; // namespace Internal
-}; // namespace Dali
-
-#endif // header
diff --git a/adaptors/emscripten/wrappers/dali-wrapper.cpp b/adaptors/emscripten/wrappers/dali-wrapper.cpp
deleted file mode 100644 (file)
index e4cf675..0000000
+++ /dev/null
@@ -1,1189 +0,0 @@
-/*
- * Copyright (c) 2016 Samsung Electronics Co., Ltd.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- */
-
-
-// EXTERNAL INCLUDES
-#include <sstream>
-#include <dali/public-api/rendering/geometry.h>
-#include <dali/public-api/rendering/sampler.h>
-#include <dali/public-api/rendering/shader.h>
-#include <dali/public-api/rendering/texture-set.h>
-#include <dali/public-api/rendering/renderer.h>
-#include <dali/devel-api/scripting/scripting.h>
-#include <dali/devel-api/events/hit-test-algorithm.h>
-#include <dali/devel-api/images/texture-set-image.h>
-#include "emscripten/emscripten.h"
-#include "emscripten/bind.h"
-#include "emscripten/val.h"
-
-// INTERNAL INCLUDES
-#include "platform-abstractions/emscripten/emscripten-callbacks.h"
-#include "platform-abstractions/emscripten/emscripten-platform-abstraction.h"
-#include "sdl-application.h"
-#include "actor-wrapper.h"
-#include "animation-wrapper.h"
-#include "emscripten-utils.h"
-#include "geometry-wrapper.h"
-#include "handle-wrapper.h"
-#include "image-wrapper.h"
-#include "property-buffer-wrapper.h"
-#include "property-value-wrapper.h"
-#include "render-task-wrapper.h"
-#include "signal-holder.h"
-#include "type-info-wrapper.h"
-
-////////////////////////////////////////////////////////////////////////////////
-//
-// The browser javascript wrapper consists of this cpp file and a counterpart
-// javascript file.
-//
-// They work in tandem to help make the interface natural and convenient
-// for a Javascript programmer.
-//
-// Unfortunately there is no finalize/destruction in javascript so any cpp
-// objects created must be explicitly deleted. Sometimes this wrapper can
-// hide the details and simple types can be immediately marshalled to and
-// from javascript values. More often objects created must have
-// object.delete() called at the correct time.
-//
-////////////////////////////////////////////////////////////////////////////////
-
-extern void EmscriptenMouseEvent(double x, double y, int mouseIsDown);
-extern void EmscriptenUpdateOnce();
-extern void EmscriptenRenderOnce();
-
-namespace Dali
-{
-namespace Internal
-{
-namespace Emscripten
-{
-
-// Javascript callbacks. These are set in the Javascript wrapper source and called
-// from the c++ wrapper source
-extern emscripten::val JSGetGlyphImage;
-extern emscripten::val JSGetImage;
-extern emscripten::val JSGetImageMetaData;
-extern emscripten::val JSRenderFinished;
-
-using namespace emscripten;
-
-/**
- * Dali Vector access for Emscripten wrapping of Dali::Vector
- */
-template<typename DaliVectorType>
-struct DaliVectorAccess
-{
-  static emscripten::val Get( const DaliVectorType& v, typename DaliVectorType::SizeType index )
-  {
-    if (index < v.Size())
-    {
-      return emscripten::val(v[index]);
-    }
-    else
-    {
-      return emscripten::val::undefined();
-    }
-  }
-
-  static bool Set( DaliVectorType& v, typename DaliVectorType::SizeType index, const typename DaliVectorType::ItemType& value)
-  {
-    v[index] = value;
-    return true;
-  }
-
-  static size_t Size( DaliVectorType& v)
-  {
-    return v.Size();
-  }
-};
-
-/**
- * Registering a Dali Vector with Emscripten to wrap for JavaScript
- */
-template<typename T>
-class_<Dali::Vector<T>> register_dali_vector(const char* name)
-{
-  typedef Dali::Vector<T> DaliVecType;
-
-  void (DaliVecType::*PushBack)(const T&) = &DaliVecType::PushBack;
-  void (DaliVecType::*Resize)(const size_t, const T&) = &DaliVecType::Resize;
-  return class_<DaliVecType>(name)
-    .template constructor<>()
-    .function("push_back", PushBack)
-    .function("resize", Resize)
-    .function("size", &DaliVectorAccess<DaliVecType>::Size)
-    .function("get", &DaliVectorAccess<DaliVecType>::Get)
-    .function("set", &DaliVectorAccess<DaliVecType>::Set)
-;
-};
-
-
-namespace
-{
-
-std::string VersionString()
-{
-  std::stringstream versionString;
-  versionString <<  "DALi Core:      " << Dali::CORE_MAJOR_VERSION << "." << Dali::CORE_MINOR_VERSION << "." << Dali::CORE_MICRO_VERSION << " (" << Dali::CORE_BUILD_DATE << ")" << std::endl;
-  return versionString.str();
-}
-
-/**
- * Creates an Actor previously registered with the TypeRegistry by name
- * Actors are currently differentiated in the dali-wrapper.js and have accessor functions
- * to support 'property.name=' access in the Javascript side object
- */
-Dali::Actor CreateActor(const std::string& name)
-{
-  Dali::Actor ret;
-
-  Dali::TypeRegistry registry = Dali::TypeRegistry::Get();
-
-  Dali::TypeInfo typeInfo = registry.GetTypeInfo( name );
-
-  if(!typeInfo)
-  {
-    EM_ASM( throw "Invalid type name" );
-  }
-  else
-  {
-    Dali::BaseHandle handle = typeInfo.CreateInstance();
-
-    if(!handle)
-    {
-      EM_ASM( throw "Invalid handle. Cannot downcast (not an actor)" );
-    }
-
-    if( Dali::Actor actor = Dali::Actor::DownCast(handle) )
-    {
-      ret = actor;
-    }
-  }
-
-  return ret;
-}
-
-/**
- * Creates any Handle from the TypeRegistry by name
- */
-Dali::Handle CreateHandle(const std::string& name)
-{
-  Dali::Handle ret;
-
-  Dali::TypeRegistry registry = Dali::TypeRegistry::Get();
-
-  Dali::TypeInfo typeInfo = registry.GetTypeInfo( name );
-
-  if(!typeInfo)
-  {
-    EM_ASM( throw "Invalid type name" );
-  }
-  else
-  {
-    Dali::BaseHandle base = typeInfo.CreateInstance();
-    if(!base)
-    {
-      EM_ASM( throw "Cannot create instance (not a handle)" );
-    }
-    Dali::Handle handle = Dali::Handle::DownCast(base);
-
-    if(!handle)
-    {
-      EM_ASM( throw "Invalid handle. Cannot downcast" );
-    }
-
-    ret = handle;
-  }
-
-  return ret;
-}
-
-/**
- * The functor to be used in the hit-test algorithm to check whether the actor is hittable.
- */
-bool IsActorHittableFunction(Dali::Actor actor, Dali::HitTestAlgorithm::TraverseType type)
-{
-  const std::string& name = actor.GetName();
-  // by convention if not visible, or with a * starting the name or if the root layer
-  return actor.IsVisible() && (name.size() ? name[0] != '*' : true);
-};
-
-/*
- * Hit Test wrapper
- *
- */
-Dali::Actor HitTest(float x, float y)
-{
-  Dali::HitTestAlgorithm::Results results;
-  Dali::HitTestAlgorithm::HitTest( Dali::Stage::GetCurrent(), Dali::Vector2(x,y), results, IsActorHittableFunction );
-  return results.actor;
-}
-
-/**
- * Creates a solid colour actor
- */
-Dali::Actor CreateSolidColorActor( const Dali::Vector4& color, bool border, const Dali::Vector4& borderColor, const unsigned int borderSize )
-{
-  static const unsigned int MAX_BORDER_SIZE( 9 );
-
-  Dali::Actor image;
-  if( borderSize > MAX_BORDER_SIZE )
-  {
-    return image;
-  }
-
-  const unsigned int bitmapWidth = borderSize * 2 + 2;
-
-  // Using a (2 + border) x (2 + border) image gives a better blend with the GL implementation
-  // than a (1 + border) x (1 + border) image
-  const unsigned int bitmapSize = bitmapWidth * bitmapWidth;
-  const unsigned int topLeft = bitmapWidth * borderSize + borderSize;
-  const unsigned int topRight = topLeft + 1;
-  const unsigned int bottomLeft = bitmapWidth * (borderSize + 1) + borderSize;
-  const unsigned int bottomRight = bottomLeft + 1;
-
-  Dali::BufferImage imageData;
-  if(color.a != 1.0 || borderColor.a != 1.0)
-  {
-    imageData = Dali::BufferImage::New( bitmapWidth, bitmapWidth, Dali::Pixel::RGBA8888 );
-
-    // Create the image
-    Dali::PixelBuffer* pixbuf = imageData.GetBuffer();
-    Dali::Vector4 outerColor = color;
-    if ( border )
-    {
-      outerColor = borderColor;
-    }
-
-    for( size_t i = 0; i < bitmapSize; ++i )
-    {
-      if( i == topLeft ||
-          i == topRight ||
-          i == bottomLeft ||
-          i == bottomRight )
-      {
-        pixbuf[i*4+0] = 0xFF * color.r;
-        pixbuf[i*4+1] = 0xFF * color.g;
-        pixbuf[i*4+2] = 0xFF * color.b;
-        pixbuf[i*4+3] = 0xFF * color.a;
-      }
-      else
-      {
-        pixbuf[i*4+0] = 0xFF * outerColor.r;
-        pixbuf[i*4+1] = 0xFF * outerColor.g;
-        pixbuf[i*4+2] = 0xFF * outerColor.b;
-        pixbuf[i*4+3] = 0xFF * outerColor.a;
-      }
-    }
-  }
-  else
-  {
-    imageData = Dali::BufferImage::New( bitmapWidth, bitmapWidth, Dali::Pixel::RGB888 );
-
-    // Create the image
-    Dali::PixelBuffer* pixbuf = imageData.GetBuffer();
-    Dali::Vector4 outerColor = color;
-    if ( border )
-    {
-      outerColor = borderColor;
-    }
-
-    for( size_t i = 0; i < bitmapSize; ++i )
-    {
-      if( i == topLeft ||
-          i == topRight ||
-          i == bottomLeft ||
-          i == bottomRight )
-      {
-        pixbuf[i*3+0] = 0xFF * color.r;
-        pixbuf[i*3+1] = 0xFF * color.g;
-        pixbuf[i*3+2] = 0xFF * color.b;
-      }
-      else
-      {
-        pixbuf[i*3+0] = 0xFF * outerColor.r;
-        pixbuf[i*3+1] = 0xFF * outerColor.g;
-        pixbuf[i*3+2] = 0xFF * outerColor.b;
-      }
-    }
-  }
-
-  imageData.Update();
-  image = Dali::Actor::New();
-  image.SetAnchorPoint( Dali::AnchorPoint::CENTER );
-  image.SetParentOrigin( Dali::ParentOrigin::CENTER );
-
-  std::string vertexShader(
-    "attribute mediump vec2 aPosition;\n"
-    "varying mediump vec2 vTexCoord;\n"
-    "uniform mediump mat4 uMvpMatrix;\n"
-    "uniform mediump vec3 uSize;\n"
-    "uniform mediump vec4 sTextureRect;\n"
-    "void main()\n"
-    "{\n"
-    "  gl_Position = uMvpMatrix * vec4(aPosition * uSize.xy, 0.0, 1.0);\n"
-    "  vTexCoord = aPosition + vec2(0.5);\n"
-    "}\n");
-
-  std::string fragmentShader(
-    "varying mediump vec2 vTexCoord;\n"
-    "uniform sampler2D sTexture;\n"
-    "uniform lowp vec4 uColor;\n"
-    "void main()\n"
-    "{\n"
-    "  gl_FragColor = texture2D( sTexture, vTexCoord )*uColor;\n"
-    "}\n");
-
-  Dali::Shader shader = Dali::Shader::New( vertexShader, fragmentShader );
-
-  // Create Quad geometry
-  Dali::Property::Map quadVertexFormat;
-  quadVertexFormat["aPosition"] = Dali::Property::VECTOR2;
-  Dali::PropertyBuffer vertexData = Dali::PropertyBuffer::New( quadVertexFormat );
-  const float halfQuadSize = .5f;
-  struct QuadVertex { Dali::Vector2 position; };
-  QuadVertex quadVertexData[4] = {
-      { Dali::Vector2(-halfQuadSize, -halfQuadSize) },
-      { Dali::Vector2(-halfQuadSize, halfQuadSize) },
-      { Dali::Vector2( halfQuadSize, -halfQuadSize) },
-      { Dali::Vector2( halfQuadSize, halfQuadSize) } };
-  vertexData.SetData(quadVertexData, 4);
-
-  Dali::Geometry quad = Dali::Geometry::New();
-  quad.AddVertexBuffer( vertexData );
-  quad.SetType( Dali::Geometry::TRIANGLE_STRIP );
-
-  Dali::Renderer renderer = Dali::Renderer::New( quad, shader );
-  Dali::TextureSet textureSet = Dali::TextureSet::New();
-  TextureSetImage( textureSet, 0u, imageData );
-  renderer.SetTextures( textureSet );
-
-  image.AddRenderer( renderer );
-
-  return image;
-}
-
-} // anon namespace
-
-/**
- * Sets the callback to getting a glyph (from dali-wrapper.js/browser)
- */
-void SetCallbackGetGlyphImage(const emscripten::val& callback)
-{
-  JSGetGlyphImage = callback;
-}
-
-/**
- * Sets the callback to get an image (from dali-wrapper.js/browser)
- */
-void SetCallbackGetImage(const emscripten::val& callback)
-{
-  JSGetImage = callback;
-}
-
-/**
- * Sets the callback to get image meta data (from dali-wrapper.js/browser)
- */
-void SetCallbackGetImageMetadata(const emscripten::val& callback)
-{
-  JSGetImageMetaData = callback;
-}
-
-/**
- * Sets the callback to signal render finished to dali-wrapper.js/browser
- */
-void SetCallbackRenderFinished(const emscripten::val& callback)
-{
-  JSRenderFinished = callback;
-}
-
-/**
- * Generates control points for a Path
- */
-void GenerateControlPoints(Dali::Handle& handle, float curvature)
-{
-  if( handle )
-  {
-    Dali::Path path = Dali::Path::DownCast(handle);
-    if(path)
-    {
-      path.GenerateControlPoints(curvature);
-    }
-    else
-    {
-      EM_ASM( throw "Handle is not a path object" );
-    }
-  }
-  else
-  {
-    EM_ASM( throw "Handle is empty" );
-  }
-
-}
-
-/**
- * Creating property Value Objects
- *   javascript can't select on type so we have renamed constructors
- *
- * Emscripten can convert some basic types and ones we've declared as value_array(s)
- * (These are given member access offsets/functions and are for simple structs etc)
- *
- * The composite types need converting.
- */
-Dali::Property::Value PropertyValueBoolean(bool v)
-{
-  return Dali::Property::Value(v);
-}
-
-Dali::Property::Value PropertyValueFloat(float v)
-{
-  return Dali::Property::Value(v);
-}
-
-Dali::Property::Value PropertyValueInteger(int v)
-{
-  return Dali::Property::Value(v);
-}
-
-Dali::Property::Value PropertyValueVector2( const Dali::Vector2& v )
-{
-  return Dali::Property::Value(v);
-}
-
-Dali::Property::Value PropertyValueVector3( const Dali::Vector3& v )
-{
-  return Dali::Property::Value(v);
-}
-
-Dali::Property::Value PropertyValueVector4( const Dali::Vector4& v )
-{
-  return Dali::Property::Value(v);
-}
-
-Dali::Property::Value PropertyValueIntRect( int a, int b, int c, int d )
-{
-  return Dali::Property::Value(Dali::Rect<int>( a, b, c, d));
-}
-
-Dali::Property::Value PropertyValueMatrix( const Dali::Matrix& v )
-{
-  return Dali::Property::Value(v);
-}
-
-Dali::Property::Value PropertyValueMatrix3( const Dali::Matrix3& v )
-{
-  return Dali::Property::Value(v);
-}
-
-Dali::Property::Value PropertyValueEuler( const Dali::Vector3& v )
-{
-  return Dali::Property::Value( Dali::Quaternion(
-                                  Dali::Radian(Dali::Degree(v.x)),
-                                  Dali::Radian(Dali::Degree(v.y)),
-                                  Dali::Radian(Dali::Degree(v.z)) ) );
-}
-
-Dali::Property::Value PropertyValueAxisAngle( const Dali::Vector4& v )
-{
-  return Dali::Quaternion( Dali::Radian(Dali::Degree(v[3])), Dali::Vector3(v) );
-}
-
-Dali::Property::Value PropertyValueString( const std::string& v )
-{
-  return Dali::Property::Value(v);
-}
-
-Dali::Property::Value PropertyValueContainer( const emscripten::val& v )
-{
-  Dali::Property::Value ret;
-  RecursiveSetProperty( ret, v );
-  return ret;
-}
-
-/**
- * Property value accessors from Dali Property Value
- */
-bool PropertyGetBoolean(const Dali::Property::Value& v)
-{
-  return v.Get<bool>();
-}
-
-float PropertyGetFloat(const Dali::Property::Value& v)
-{
-  return v.Get<float>();
-}
-
-int PropertyGetInteger(const Dali::Property::Value& v)
-{
-  return v.Get<int>();
-}
-
-Dali::Vector2 PropertyGetVector2(const Dali::Property::Value& v)
-{
-  return v.Get<Dali::Vector2>();
-}
-
-Dali::Vector3 PropertyGetVector3(const Dali::Property::Value& v)
-{
-  return v.Get<Dali::Vector3>();
-}
-
-Dali::Vector4 PropertyGetVector4(const Dali::Property::Value& v)
-{
-  return v.Get<Dali::Vector4>();
-}
-
-emscripten::val PropertyGetIntRect(const Dali::Property::Value& v)
-{
-  return JavascriptValue(v);
-}
-
-std::string PropertyGetString(const Dali::Property::Value& v)
-{
-  return v.Get<std::string>();
-}
-
-emscripten::val PropertyGetMap(const Dali::Property::Value& v)
-{
-  return JavascriptValue(v);
-}
-
-emscripten::val PropertyGetArray(const Dali::Property::Value& v)
-{
-  return JavascriptValue(v);
-}
-
-emscripten::val PropertyGetMatrix(const Dali::Property::Value& v)
-{
-  return JavascriptValue(v);
-}
-
-emscripten::val PropertyGetMatrix3(const Dali::Property::Value& v)
-{
-  return JavascriptValue(v);
-}
-
-emscripten::val PropertyGetEuler(const Dali::Property::Value& v)
-{
-  return JavascriptValue(v);
-}
-
-emscripten::val PropertyGetRotation(const Dali::Property::Value& v)
-{
-  return JavascriptValue(v);
-}
-
-int PropertyGetType(Dali::Property::Value& v)
-{
-  return (int)v.GetType();
-}
-
-std::string PropertyGetTypeName(Dali::Property::Value& v)
-{
-  return Dali::PropertyTypes::GetName(v.GetType());
-}
-
-template <typename T>
-float MatrixGetter(T &v, int n)
-{
-  return *(v.AsFloat() + n);
-}
-
-template <typename T>
-void MatrixSetter(T &v, float f, int n)
-{
-  *(v.AsFloat() + n) = f;
-}
-
-float MatrixGetter0(const Dali::Matrix &v)        { return MatrixGetter(v, 0); }
-float MatrixGetter1(const Dali::Matrix &v)        { return MatrixGetter(v, 1); }
-float MatrixGetter2(const Dali::Matrix &v)        { return MatrixGetter(v, 2); }
-float MatrixGetter3(const Dali::Matrix &v)        { return MatrixGetter(v, 3); }
-float MatrixGetter4(const Dali::Matrix &v)        { return MatrixGetter(v, 4); }
-float MatrixGetter5(const Dali::Matrix &v)        { return MatrixGetter(v, 5); }
-float MatrixGetter6(const Dali::Matrix &v)        { return MatrixGetter(v, 6); }
-float MatrixGetter7(const Dali::Matrix &v)        { return MatrixGetter(v, 7); }
-float MatrixGetter8(const Dali::Matrix &v)        { return MatrixGetter(v, 8); }
-float MatrixGetter9(const Dali::Matrix &v)        { return MatrixGetter(v, 9); }
-float MatrixGetter10(const Dali::Matrix &v)        { return MatrixGetter(v,10); }
-float MatrixGetter11(const Dali::Matrix &v)        { return MatrixGetter(v,11); }
-float MatrixGetter12(const Dali::Matrix &v)        { return MatrixGetter(v,12); }
-float MatrixGetter13(const Dali::Matrix &v)        { return MatrixGetter(v,13); }
-float MatrixGetter14(const Dali::Matrix &v)        { return MatrixGetter(v,14); }
-float MatrixGetter15(const Dali::Matrix &v)        { return MatrixGetter(v,15); }
-float MatrixGetter16(const Dali::Matrix &v)        { return MatrixGetter(v,16); }
-
-void MatrixSetter0(Dali::Matrix &v, float f)      { MatrixSetter(v, f, 0); }
-void MatrixSetter1(Dali::Matrix &v, float f)      { MatrixSetter(v, f, 1); }
-void MatrixSetter2(Dali::Matrix &v, float f)      { MatrixSetter(v, f, 2); }
-void MatrixSetter3(Dali::Matrix &v, float f)      { MatrixSetter(v, f, 3); }
-void MatrixSetter4(Dali::Matrix &v, float f)      { MatrixSetter(v, f, 4); }
-void MatrixSetter5(Dali::Matrix &v, float f)      { MatrixSetter(v, f, 5); }
-void MatrixSetter6(Dali::Matrix &v, float f)      { MatrixSetter(v, f, 6); }
-void MatrixSetter7(Dali::Matrix &v, float f)      { MatrixSetter(v, f, 7); }
-void MatrixSetter8(Dali::Matrix &v, float f)      { MatrixSetter(v, f, 8); }
-void MatrixSetter9(Dali::Matrix &v, float f)      { MatrixSetter(v, f, 9); }
-void MatrixSetter10(Dali::Matrix &v, float f)      { MatrixSetter(v, f,10); }
-void MatrixSetter11(Dali::Matrix &v, float f)      { MatrixSetter(v, f,11); }
-void MatrixSetter12(Dali::Matrix &v, float f)      { MatrixSetter(v, f,12); }
-void MatrixSetter13(Dali::Matrix &v, float f)      { MatrixSetter(v, f,13); }
-void MatrixSetter14(Dali::Matrix &v, float f)      { MatrixSetter(v, f,14); }
-void MatrixSetter15(Dali::Matrix &v, float f)      { MatrixSetter(v, f,15); }
-void MatrixSetter16(Dali::Matrix &v, float f)      { MatrixSetter(v, f,16); }
-
-float Matrix3Getter0(const Dali::Matrix3 &v)        { return MatrixGetter(v, 0); }
-float Matrix3Getter1(const Dali::Matrix3 &v)        { return MatrixGetter(v, 1); }
-float Matrix3Getter2(const Dali::Matrix3 &v)        { return MatrixGetter(v, 2); }
-float Matrix3Getter3(const Dali::Matrix3 &v)        { return MatrixGetter(v, 3); }
-float Matrix3Getter4(const Dali::Matrix3 &v)        { return MatrixGetter(v, 4); }
-float Matrix3Getter5(const Dali::Matrix3 &v)        { return MatrixGetter(v, 5); }
-float Matrix3Getter6(const Dali::Matrix3 &v)        { return MatrixGetter(v, 6); }
-float Matrix3Getter7(const Dali::Matrix3 &v)        { return MatrixGetter(v, 7); }
-float Matrix3Getter8(const Dali::Matrix3 &v)        { return MatrixGetter(v, 8); }
-
-void Matrix3Setter0(Dali::Matrix3 &v, float f)      { MatrixSetter(v, f, 0); }
-void Matrix3Setter1(Dali::Matrix3 &v, float f)      { MatrixSetter(v, f, 1); }
-void Matrix3Setter2(Dali::Matrix3 &v, float f)      { MatrixSetter(v, f, 2); }
-void Matrix3Setter3(Dali::Matrix3 &v, float f)      { MatrixSetter(v, f, 3); }
-void Matrix3Setter4(Dali::Matrix3 &v, float f)      { MatrixSetter(v, f, 4); }
-void Matrix3Setter5(Dali::Matrix3 &v, float f)      { MatrixSetter(v, f, 5); }
-void Matrix3Setter6(Dali::Matrix3 &v, float f)      { MatrixSetter(v, f, 6); }
-void Matrix3Setter7(Dali::Matrix3 &v, float f)      { MatrixSetter(v, f, 7); }
-void Matrix3Setter8(Dali::Matrix3 &v, float f)      { MatrixSetter(v, f, 8); }
-
-val JavascriptUpdateCallback( val::undefined() );
-bool JavascriptUpdateCallbackSet = false;
-
-void JavascriptUpdate(int dt)
-{
-  if( JavascriptUpdateCallbackSet )
-  {
-    JavascriptUpdateCallback( val(dt) );
-  }
-}
-
-void SetUpdateFunction( const emscripten::val& function )
-{
-  JavascriptUpdateCallback = function;
-  JavascriptUpdateCallbackSet = true;
-}
-
-const emscripten::val& GetUpdateFunction()
-{
-  return JavascriptUpdateCallback;
-}
-
-/**
- * Emscripten Bindings
- *
- * This uses Emscripten 'bind' (similar in design to Boost's python wrapper library).
- * It provides a simplified way to wrap C++ classes and wraps Emscriptens type
- * registration API.
- *
- * A convention below is that where there is a function or method name prepended
- * with '__' there is a corresponding Javascript helper function to help with
- * marshalling parameters and return values.
- *
- */
-EMSCRIPTEN_BINDINGS(dali_wrapper)
-{
-  // With a little help embind knows about vectors so we tell it which ones to instantiate
-  register_dali_vector<int>("DaliVectorInt");
-  register_vector<std::string>("VectorString");
-  register_vector<int>("VectorInt");
-  register_vector<float>("VectorFloat");
-  register_vector<Dali::Actor>("VectorActor");
-
-  //
-  // Creation functions.
-  //
-  emscripten::function("VersionString", &VersionString);
-  emscripten::function("__createActor", &CreateActor);
-  emscripten::function("__createHandle", &CreateHandle);
-  emscripten::function("__createSolidColorActor", &CreateSolidColorActor);
-
-  //
-  // Helper functions
-  //
-  emscripten::function("javascriptValue", &JavascriptValue);
-  emscripten::function("__hitTest", &HitTest);
-  emscripten::function("sendMouseEvent", &EmscriptenMouseEvent);
-  emscripten::function("__updateOnce", &EmscriptenUpdateOnce);
-  emscripten::function("__renderOnce", &EmscriptenRenderOnce);
-  emscripten::function("generateControlPoints", &GenerateControlPoints);
-
-  //
-  // Global callback functions
-  //
-  emscripten::function("setCallbackGetGlyphImage", &SetCallbackGetGlyphImage);
-  emscripten::function("setCallbackGetImage", &SetCallbackGetImage);
-  emscripten::function("setCallbackGetImageMetadata", &SetCallbackGetImageMetadata);
-  emscripten::function("setCallbackRenderFinished", &SetCallbackRenderFinished);
-  emscripten::function("setUpdateFunction", &SetUpdateFunction);
-  emscripten::function("getUpdateFunction", &GetUpdateFunction);
-
-  //
-  // Property value creation (Javascript can't select on type)
-  //
-  emscripten::function("PropertyValueBoolean", &PropertyValueBoolean);
-  emscripten::function("PropertyValueFloat", &PropertyValueFloat);
-  emscripten::function("PropertyValueInteger", &PropertyValueInteger);
-  emscripten::function("PropertyValueString", &PropertyValueString);
-  emscripten::function("PropertyValueVector2", &PropertyValueVector2);
-  emscripten::function("PropertyValueVector3", &PropertyValueVector3);
-  emscripten::function("PropertyValueVector4", &PropertyValueVector4);
-  emscripten::function("PropertyValueMatrix", &PropertyValueMatrix);
-  emscripten::function("PropertyValueMatrix3", &PropertyValueMatrix3);
-  emscripten::function("PropertyValueMap", &PropertyValueContainer);
-  emscripten::function("PropertyValueArray", &PropertyValueContainer);
-  emscripten::function("PropertyValueEuler", &PropertyValueEuler);
-  emscripten::function("PropertyValueAxisAngle", &PropertyValueAxisAngle);
-  emscripten::function("PropertyValueString", &PropertyValueString);
-  emscripten::function("PropertyValueIntRect", &PropertyValueIntRect);
-
-  //
-  // One unfortunate aspect of wrapping for the browser is that we get no notification
-  // of object deletion so all JS wrapper objects must be wrapper.delete() correctly.
-  //
-  // Embind has a mechanism around this for simple c style structs decared as value_arrays.
-  // These are immediately transformed to Javascript arrays and don't need explicit
-  // destruction, however the API needs a member offset.
-  //
-  value_array<Dali::Internal::Emscripten::Statistics>("Statistics")
-    .element(&Dali::Internal::Emscripten::Statistics::on)
-    .element(&Dali::Internal::Emscripten::Statistics::frameCount)
-    .element(&Dali::Internal::Emscripten::Statistics::lastFrameDeltaSeconds)
-    .element(&Dali::Internal::Emscripten::Statistics::lastSyncTimeMilliseconds)
-    .element(&Dali::Internal::Emscripten::Statistics::nextSyncTimeMilliseconds)
-    .element(&Dali::Internal::Emscripten::Statistics::keepUpdating)
-    .element(&Dali::Internal::Emscripten::Statistics::needsNotification)
-    .element(&Dali::Internal::Emscripten::Statistics::secondsFromLastFrame)
-;
-
-  value_array<Dali::Vector2>("Vector2")
-    .element(&Dali::Vector2::x)
-    .element(&Dali::Vector2::y)
-;
-
-  value_array<Dali::Vector3>("Vector3")
-    .element(&Dali::Vector3::x)
-    .element(&Dali::Vector3::y)
-    .element(&Dali::Vector3::z)
-;
-
-  value_array<Dali::Vector4>("Vector4")
-    .element(&Dali::Vector4::x)
-    .element(&Dali::Vector4::y)
-    .element(&Dali::Vector4::z)
-    .element(&Dali::Vector4::w)
-;
-
-  value_array<Dali::Matrix>("Matrix")
-    .element(&MatrixGetter0, &MatrixSetter0)
-    .element(&MatrixGetter1, &MatrixSetter1)
-    .element(&MatrixGetter2, &MatrixSetter2)
-    .element(&MatrixGetter3, &MatrixSetter3)
-    .element(&MatrixGetter4, &MatrixSetter4)
-    .element(&MatrixGetter5, &MatrixSetter5)
-    .element(&MatrixGetter6, &MatrixSetter6)
-    .element(&MatrixGetter7, &MatrixSetter7)
-    .element(&MatrixGetter8, &MatrixSetter8)
-    .element(&MatrixGetter9, &MatrixSetter9)
-    .element(&MatrixGetter10, &MatrixSetter10)
-    .element(&MatrixGetter11, &MatrixSetter11)
-    .element(&MatrixGetter12, &MatrixSetter12)
-    .element(&MatrixGetter13, &MatrixSetter13)
-    .element(&MatrixGetter14, &MatrixSetter14)
-    .element(&MatrixGetter15, &MatrixSetter15)
-;
-
-  value_array<Dali::Matrix3>("Matrix3")
-    .element(&Matrix3Getter0, &Matrix3Setter0)
-    .element(&Matrix3Getter1, &Matrix3Setter1)
-    .element(&Matrix3Getter2, &Matrix3Setter2)
-    .element(&Matrix3Getter3, &Matrix3Setter3)
-    .element(&Matrix3Getter4, &Matrix3Setter4)
-    .element(&Matrix3Getter5, &Matrix3Setter5)
-    .element(&Matrix3Getter6, &Matrix3Setter6)
-    .element(&Matrix3Getter7, &Matrix3Setter7)
-    .element(&Matrix3Getter8, &Matrix3Setter8)
-;
-
-  //
-  // enums
-  //
-  enum_<Dali::Property::Type>("PropertyType")
-    .value("NONE", Dali::Property::NONE)
-    .value("BOOLEAN", Dali::Property::BOOLEAN)
-    .value("FLOAT", Dali::Property::FLOAT)
-    .value("INTEGER", Dali::Property::INTEGER)
-    .value("VECTOR2", Dali::Property::VECTOR2)
-    .value("VECTOR3", Dali::Property::VECTOR3)
-    .value("VECTOR4", Dali::Property::VECTOR4)
-    .value("MATRIX3", Dali::Property::MATRIX3)
-    .value("MATRIX", Dali::Property::MATRIX)
-    .value("RECTANGLE", Dali::Property::RECTANGLE)
-    .value("ROTATION", Dali::Property::ROTATION)
-    .value("STRING", Dali::Property::STRING)
-    .value("ARRAY", Dali::Property::ARRAY)
-    .value("MAP", Dali::Property::MAP)
-;
-
-  enum_<Dali::Shader::Hint::Value>("ShaderHints")
-    .value("NONE",                      Dali::Shader::Hint::NONE)
-    .value("OUTPUT_IS_TRANSPARENT",     Dali::Shader::Hint::OUTPUT_IS_TRANSPARENT)
-    .value("MODIFIES_GEOMETRY",         Dali::Shader::Hint::MODIFIES_GEOMETRY)
-;
-
-  enum_<Dali::Animation::EndAction>("EndAction")
-    .value("Bake",        Dali::Animation::Bake)
-    .value("Discard",     Dali::Animation::Discard)
-    .value("BakeFinal",   Dali::Animation::BakeFinal)
-;
-
-  enum_<Dali::Animation::Interpolation>("Interpolation")
-    .value("Linear", Dali::Animation::Interpolation::Linear)
-    .value("Cubic", Dali::Animation::Interpolation::Cubic)
-;
-
-  enum_<Dali::Geometry::Type>("Type")
-    .value("POINTS",          Dali::Geometry::POINTS)
-    .value("LINES",           Dali::Geometry::LINES)
-    .value("LINE_LOOP",       Dali::Geometry::LINE_LOOP)
-    .value("LINE_STRIP",      Dali::Geometry::LINE_STRIP)
-    .value("TRIANGLES",       Dali::Geometry::TRIANGLES)
-    .value("TRIANGLE_FAN",    Dali::Geometry::TRIANGLE_FAN)
-    .value("TRIANGLE_STRIP",  Dali::Geometry::TRIANGLE_STRIP)
-;
-
-  enum_<Dali::Pixel::Format>("PixelFormat")
-    .value("A8", Dali::Pixel::Format::A8)
-    .value("L8", Dali::Pixel::Format::L8)
-    .value("LA88", Dali::Pixel::Format::LA88)
-    .value("RGB565", Dali::Pixel::Format::RGB565)
-    .value("BGR565", Dali::Pixel::Format::BGR565)
-    .value("RGBA4444", Dali::Pixel::Format::RGBA4444)
-    .value("BGRA4444", Dali::Pixel::Format::BGRA4444)
-    .value("RGBA5551", Dali::Pixel::Format::RGBA5551)
-    .value("BGRA5551", Dali::Pixel::Format::BGRA5551)
-    .value("RGB888", Dali::Pixel::Format::RGB888)
-    .value("RGB8888", Dali::Pixel::Format::RGB8888)
-    .value("BGR8888", Dali::Pixel::Format::BGR8888)
-    .value("RGBA8888", Dali::Pixel::Format::RGBA8888)
-    .value("BGRA8888", Dali::Pixel::Format::BGRA8888)
-    // GLES 3 Standard compressed formats:
-    .value("COMPRESSED_R11_EAC", Dali::Pixel::Format::COMPRESSED_R11_EAC)
-    .value("COMPRESSED_SIGNED_R11_EAC", Dali::Pixel::Format::COMPRESSED_SIGNED_R11_EAC)
-    .value("COMPRESSED_RG11_EAC", Dali::Pixel::Format::COMPRESSED_RG11_EAC)
-    .value("COMPRESSED_SIGNED_RG11_EAC", Dali::Pixel::Format::COMPRESSED_SIGNED_RG11_EAC)
-    .value("COMPRESSED_RGB8_ETC2", Dali::Pixel::Format::COMPRESSED_RGB8_ETC2)
-    .value("COMPRESSED_SRGB8_ETC2", Dali::Pixel::Format::COMPRESSED_SRGB8_ETC2)
-    .value("COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2", Dali::Pixel::Format::COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2)
-    .value("COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2", Dali::Pixel::Format::COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2)
-    .value("COMPRESSED_RGBA8_ETC2_EAC", Dali::Pixel::Format::COMPRESSED_RGBA8_ETC2_EAC)
-    .value("COMPRESSED_SRGB8_ALPHA8_ETC2_EAC", Dali::Pixel::Format::COMPRESSED_SRGB8_ALPHA8_ETC2_EAC)
-    // GLES 2 extension compressed formats:
-    .value("COMPRESSED_RGB8_ETC1", Dali::Pixel::Format::COMPRESSED_RGB8_ETC1)
-    .value("COMPRESSED_RGB_PVRTC_4BPPV1", Dali::Pixel::Format::COMPRESSED_RGB_PVRTC_4BPPV1)
-;
-
-  enum_<Dali::FaceCullingMode::Type>("FaceCullingMode")
-    .value("NONE", Dali::FaceCullingMode::NONE)
-    .value("FRONT", Dali::FaceCullingMode::FRONT)
-    .value("BACK", Dali::FaceCullingMode::BACK)
-    .value("FRONT_AND_BACK", Dali::FaceCullingMode::FRONT_AND_BACK)
-;
-
-  enum_<Dali::DepthWriteMode::Type>("DepthWriteMode")
-    .value("OFF", Dali::DepthWriteMode::OFF)
-    .value("AUTO", Dali::DepthWriteMode::AUTO)
-    .value("ON", Dali::DepthWriteMode::ON)
-;
-
-  enum_<Dali::BlendMode::Type>("BlendMode")
-    .value("OFF", Dali::BlendMode::OFF)
-    .value("AUTO", Dali::BlendMode::AUTO)
-    .value("ON", Dali::BlendMode::ON)
-;
-
-  enum_<Dali::AlphaFunction::BuiltinFunction>("AlphaFunction")
-    .value("DEFAULT", Dali::AlphaFunction::BuiltinFunction::DEFAULT)
-    .value("LINEAR", Dali::AlphaFunction::BuiltinFunction::LINEAR)
-    .value("REVERSE", Dali::AlphaFunction::BuiltinFunction::REVERSE)
-    .value("EASE_IN_SQUARE", Dali::AlphaFunction::BuiltinFunction::EASE_IN_SQUARE)
-    .value("EASE_OUT_SQUARE", Dali::AlphaFunction::BuiltinFunction::EASE_OUT_SQUARE)
-    .value("EASE_IN", Dali::AlphaFunction::BuiltinFunction::EASE_IN)
-    .value("EASE_OUT", Dali::AlphaFunction::BuiltinFunction::EASE_OUT)
-    .value("EASE_IN_OUT", Dali::AlphaFunction::BuiltinFunction::EASE_IN_OUT)
-    .value("EASE_IN_SINE", Dali::AlphaFunction::BuiltinFunction::EASE_IN_SINE)
-    .value("EASE_OUT_SINE", Dali::AlphaFunction::BuiltinFunction::EASE_OUT_SINE)
-    .value("EASE_IN_OUT_SINE", Dali::AlphaFunction::BuiltinFunction::EASE_IN_OUT_SINE)
-    .value("BOUNCE", Dali::AlphaFunction::BuiltinFunction::BOUNCE)
-    .value("SIN", Dali::AlphaFunction::BuiltinFunction::SIN)
-    .value("EASE_OUT_BACK", Dali::AlphaFunction::BuiltinFunction::EASE_OUT_BACK)
-;
-
-  //
-  // classes
-  //
-
-  // we need property map as an object rather than straight conversion to javascript 'object'
-  // because its ordered. And PropertyBuffer needs an order.
-  class_<Dali::Property::Map>("PropertyMap")
-    .constructor<>()
-    .function("count", &Dali::Property::Map::Count)
-    .function("empty", &Dali::Property::Map::Empty)
-    .function("__insert", select_overload< void(const std::string&, const Dali::Property::Value&) > (&Dali::Property::Map::Insert))
-    .function("__get", &PropertyMapGet)
-    .function("__getValue", &Dali::Property::Map::GetValue)
-    .function("getKey", &Dali::Property::Map::GetKey)
-    .function("clear", &Dali::Property::Map::Clear)
-    .function("merge", &Dali::Property::Map::Merge)
-;
-
-  class_<Dali::Property::Value>("PropertyValue")
-    .constructor<>()
-    .function("getType", &PropertyGetType)
-    .function("getTypeName", &PropertyGetTypeName)
-    .function("getBoolean", &PropertyGetBoolean)
-    .function("getFloat", &PropertyGetFloat)
-    .function("getInteger", &PropertyGetInteger)
-    .function("getVector2", &PropertyGetVector2)
-    .function("getVector3", &PropertyGetVector3)
-    .function("getVector4", &PropertyGetVector4)
-    .function("getString", &PropertyGetString)
-    .function("getMap", &PropertyGetMap)
-    .function("getArray", &PropertyGetArray)
-    .function("getMatrix", &PropertyGetMatrix)
-    .function("getMatrix3", &PropertyGetMatrix3)
-    .function("getEuler", &PropertyGetEuler)
-    .function("getRotation", &PropertyGetRotation)
-    .function("getIntRect", &PropertyGetIntRect)
-;
-
-  class_<Dali::BaseHandle>("BaseHandle")
-    .function("ok", &BaseHandleOk)
-    .function("getTypeName", &BaseHandle::GetTypeName)
-;
-
-  class_<Dali::TypeInfo, base<Dali::BaseHandle>>("TypeInfo")
-    .function("getName", &Dali::TypeInfo::GetName)
-    .function("getBaseName", &Dali::TypeInfo::GetBaseName)
-    .function("getProperties", &GetAllProperties)
-    .function("getActions", &GetActions)
-    .function("getSignals", &GetSignals)
-    .function("getPropertyIndices", &Dali::TypeInfo::GetPropertyIndices)
-;
-
-  class_<Dali::TypeRegistry>("TypeRegistry")
-    .constructor<>(&Dali::TypeRegistry::Get)
-    .function("getTypeNameCount", &Dali::TypeRegistry::GetTypeNameCount)
-    .function("getTypeName", &Dali::TypeRegistry::GetTypeName)
-    .function("getTypeInfo", select_overload< Dali::TypeInfo(const std::string&) > (&Dali::TypeRegistry::GetTypeInfo))
-;
-
-  class_<SignalHolder>("SignalHolder")
-    .constructor<>()
-;
-
-  class_<Dali::Handle, base<Dali::BaseHandle>>("Handle")
-    .function("__registerProperty", &RegisterProperty)
-    .function("__registerAnimatedProperty", &RegisterAnimatedProperty)
-    .function("setSelf", &SetSelf)
-    .function("setProperty", &SetProperty)
-    .function("getProperty", &GetProperty)
-    .function("getPropertyIndex", &GetPropertyIndex)
-    .function("getProperties", &GetProperties)
-    .function("getPropertyIndices", &Handle::GetPropertyIndices)
-    .function("getPropertyTypeFromName", &GetPropertyTypeFromName)
-    .function("getPropertyTypeName", &GetPropertyTypeName)
-    .function("registerProperty", &RegisterProperty)
-    .function("registerAnimatedProperty", &RegisterAnimatedProperty)
-    .function("getTypeInfo", &GetTypeInfo)
-    .function("isPropertyWritable", &Handle::IsPropertyWritable)
-    .function("isPropertyAnimatable", &Handle::IsPropertyAnimatable)
-    .function("isPropertyAConstraintInput", &Handle::IsPropertyAConstraintInput)
-;
-
-  class_<Dali::Path, base<Dali::Handle>>("Path")
-    .constructor<>(&Dali::Path::New)
-    .function("addPoint", &Dali::Path::AddPoint)
-    .function("addControlPoint", &Dali::Path::AddControlPoint)
-    .function("generateControlPoints", &Dali::Path::GenerateControlPoints)
-    .function("sample", &Dali::Path::Sample)
-    .function("getPoint", &Dali::Path::GetPoint)
-    .function("getControlPoint", &Dali::Path::GetControlPoint)
-    .function("getPointCount", &Dali::Path::GetPointCount)
-;
-
-  class_<Dali::KeyFrames>("KeyFrames")
-    .constructor<>(&Dali::KeyFrames::New)
-    .function("add", select_overload<void (float progress, Property::Value value)>(&Dali::KeyFrames::Add))
-    .function("addWithAlpha", &KeyFramesAddWithAlpha)
-;
-
-  class_<Dali::Animation>("Animation")
-    .constructor<float>(&Dali::Animation::New)
-    .function("__animateTo", &AnimateTo)
-    .function("__animateBy", &AnimateBy)
-    .function("__animateBetween", &AnimateBetween)
-    .function("__animatePath", &AnimatePath)
-    .function("setDuration", &Dali::Animation::SetDuration)
-    .function("getDuration", &Dali::Animation::GetDuration)
-    .function("setLooping", &Dali::Animation::SetLooping)
-    .function("isLooping", &Dali::Animation::IsLooping)
-    .function("setEndAction", &Dali::Animation::SetEndAction)
-    .function("getEndAction", &Dali::Animation::GetEndAction)
-    .function("setDisconnectAction", &Dali::Animation::SetDisconnectAction)
-    .function("getDisconnectAction", &Dali::Animation::GetDisconnectAction)
-    .function("setCurrentProgress", &Dali::Animation::SetCurrentProgress)
-    .function("getCurrentProgress", &Dali::Animation::GetCurrentProgress)
-    .function("setSpeedFactor", &Dali::Animation::SetSpeedFactor)
-    .function("getSpeedFactor", &Dali::Animation::GetSpeedFactor)
-    .function("setPlayRange", &Dali::Animation::SetPlayRange)
-    .function("getPlayRange", &Dali::Animation::GetPlayRange)
-    .function("play", &Dali::Animation::Play)
-    .function("playFrom", &Dali::Animation::PlayFrom)
-    .function("pause", &Dali::Animation::Pause)
-    .function("stop", &Dali::Animation::Stop)
-    .function("clear", &Dali::Animation::Clear)
-;
-
-  class_<Dali::PropertyBuffer>("PropertyBuffer")
-    .constructor<Dali::Property::Map&>(Dali::PropertyBuffer::New)
-    .function("setData", &SetPropertyBufferDataRaw)
-;
-
-  class_<Dali::Geometry>("Geometry")
-    .constructor<>(&Dali::Geometry::New)
-    .function("addVertexBuffer", &Dali::Geometry::AddVertexBuffer)
-    .function("getNumberOfVertexBuffers", &Dali::Geometry::GetNumberOfVertexBuffers)
-    .function("setIndexBuffer", &SetIndexBufferDataRaw)
-    .function("setType", &Dali::Geometry::SetType)
-    .function("getType", &Dali::Geometry::GetType)
-;
-
-  class_<Dali::Image>("Image")
-;
-
-  class_<Dali::BufferImage, base<Dali::Image> >("BufferImage")
-    .constructor<const std::string&, unsigned int, unsigned int, Dali::Pixel::Format>(&BufferImageNew)
-;
-
-  class_<Dali::EncodedBufferImage, base<Dali::Image> >("EncodedBufferImage")
-    .constructor<const std::string&>(&EncodedBufferImageNew)
-;
-
-  class_<Dali::Sampler>("Sampler")
-    .constructor<>(&Dali::Sampler::New)
-;
-
-  class_<Dali::Shader, base<Dali::Handle>>("Shader")
-    .constructor<>(&Dali::Shader::New)
-;
-
-  class_<Dali::TextureSet>("TextureSet")
-    .constructor<>(&Dali::TextureSet::New)
-    .function("setTexture", &Dali::TextureSet::SetTexture)
-    .function("setSampler", &Dali::TextureSet::SetSampler)
-    .function("getTexture", &Dali::TextureSet::GetTexture)
-    .function("getSampler", &Dali::TextureSet::GetSampler)
-    .function("getTextureCount", &Dali::TextureSet::GetTextureCount)
-;
-
-  class_<Dali::Renderer, base<Dali::Handle>>("Renderer")
-    .constructor<>(&Dali::Renderer::New)
-    .function("setGeometry", &Dali::Renderer::SetGeometry)
-    .function("getGeometry", &Dali::Renderer::GetGeometry)
-    .function("SetTextures", &Dali::Renderer::SetTextures)
-    .function("SetTextures", &Dali::Renderer::SetTextures)
-;
-
-  class_<Dali::Actor, base<Dali::Handle>>("Actor")
-    .constructor<>(&Dali::Actor::New)
-    .function("add", &Dali::Actor::Add)
-    .function("remove", &Dali::Actor::Remove)
-    .function("getId", &Dali::Actor::GetId)
-    .function("__getParent", &Dali::Actor::GetParent)
-    .function("__findChildById", &Dali::Actor::FindChildById)
-    .function("__findChildByName", &Dali::Actor::FindChildByName)
-    .function("__getChildAt", &Dali::Actor::GetChildAt)
-    .function("getChildCount", &Dali::Actor::GetChildCount)
-    .function("__screenToLocal",
-              select_overload<std::vector<float> (Dali::Actor, float, float)>(&ScreenToLocal))
-    .function("addressOf", &AddressOf)
-    .function("__connect", &ConnectSignal)
-    .function("__setPropertyNotification", &SetPropertyNotification)
-    .function("addRenderer", &Dali::Actor::AddRenderer)
-    .function("getRendererCount", &Dali::Actor::GetRendererCount)
-    .function("removeRenderer",
-              select_overload<void(unsigned int)>(&Dali::Actor::RemoveRenderer))
-    .function("__getRendererAt", &Dali::Actor::GetRendererAt)
-;
-
-  class_<Dali::CameraActor, base<Dali::Actor>>("CameraActor")
-    .constructor<>( select_overload<Dali::CameraActor()>(&Dali::CameraActor::New))
-;
-
-  class_<Dali::Layer, base<Dali::Actor>>("Layer")
-    .constructor<>(&Dali::Layer::New)
-    .function("raise", &Dali::Layer::Raise)
-    .function("lower", &Dali::Layer::Lower)
-;
-
-  class_<Dali::Stage>("Stage")
-    .constructor<>(&Dali::Stage::GetCurrent)
-    .function("add", &Dali::Stage::Add)
-    .function("remove", &Dali::Stage::Remove)
-    .function("__getRootLayer", &Dali::Stage::GetRootLayer)
-    .function("getLayer", &Dali::Stage::GetLayer)
-    .function("getRenderTaskList", &Dali::Stage::GetRenderTaskList)
-    .function("setBackgroundColor", &Dali::Stage::SetBackgroundColor)
-;
-
-  class_<Dali::RenderTaskList>("RenderTaskList")
-    .function("createTask", &Dali::RenderTaskList::CreateTask)
-    .function("removeTask", &Dali::RenderTaskList::RemoveTask)
-    .function("getTaskCount", &Dali::RenderTaskList::GetTaskCount)
-    .function("getTask", &Dali::RenderTaskList::GetTask)
-;
-
-  class_<Dali::RenderTask>("RenderTask")
-    .function("__getCameraActor", &Dali::RenderTask::GetCameraActor)
-    .function("setCameraActor", &Dali::RenderTask::SetCameraActor)
-    .function("setSourceActor", &Dali::RenderTask::SetSourceActor)
-    .function("setExclusive", &Dali::RenderTask::SetExclusive)
-    .function("setInputEnabled", &Dali::RenderTask::SetInputEnabled)
-    .function("setViewportPosition", &Dali::RenderTask::SetViewportPosition)
-    .function("setViewportSize", &Dali::RenderTask::SetViewportSize)
-    .function("getCurrentViewportPosition", &Dali::RenderTask::GetCurrentViewportPosition)
-    .function("getCurrentViewportSize", &Dali::RenderTask::GetCurrentViewportSize)
-    .function("setClearColor", &Dali::RenderTask::SetClearColor)
-    .function("getClearColor", &Dali::RenderTask::GetClearColor)
-    .function("setClearEnabled", &Dali::RenderTask::SetClearEnabled)
-    .function("getClearEnabled", &Dali::RenderTask::GetClearEnabled)
-    .function("screenToLocal",
-              select_overload<Dali::Vector2(Dali::RenderTask, Dali::Actor, float, float)>(&ScreenToLocal))
-    .function("worldToScreen", &WorldToScreen)
-;
-
-}
-
-}; // namespace Emscripten
-}; // namespace Internal
-}; // namespace Dali
diff --git a/adaptors/emscripten/wrappers/dali-wrapper.js b/adaptors/emscripten/wrappers/dali-wrapper.js
deleted file mode 100644 (file)
index d9179b6..0000000
+++ /dev/null
@@ -1,3489 +0,0 @@
-/*
- * Copyright (c) 2016 Samsung Electronics Co., Ltd.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- */
-
-/* eslint-env browser */
-/* eslint "brace-style": [2, "1tbs"] */
-/* eslint "no-console": 0 */
-/* eslint "no-underscore-dangle": 0 */
-
-/*******************************************************************************
- *
- * The javascript counterpart to the C++ DALi wrapper.
- *
- * Provides helper functionality to make the use of the dali module.
- *
- * Where possible it creates a natural Javascript API. One problem
- * is that wrapped C++ objects must be explicitly deleted '<obj>.delete()'.
- * This is because javascript in the browser has no available hook to watch
- * for an objects destruction.
- *
- * This file combines several 'Modules' and could be split when using a
- * a recombining web build tool.
- *
- *
- ******************************************************************************/
-
-// forward refs for lint
-var Module;
-// On upgrading to emscripten 1.34.2 and -s EXPORT_NAME="dali" on emcc command
-// line no longer seems to work so set it here.
-var dali = Module;
-var document;
-var console;
-
-//------------------------------------------------------------------------------
-//
-// Math Module
-//
-//------------------------------------------------------------------------------
-
-/**
- * Matrix Multiplication
- * @method matrixByMatrix
- * @param {Array} A Matrix4 array
- * @param {Array} B Matrix4 array
- * @return {Array} Matrix4
- */
-dali.matrixByMatrix = function(A, B) {
-  "use strict";
-
-  var ret = [1, 0, 0, 0,
-             0, 1, 0, 0,
-             0, 0, 1, 0,
-             0, 0, 0, 1
-            ];
-
-  ret[0] = A[0] * B[0] + A[1] * B[4] + A[2] * B[8] + A[3] * B[12];
-  ret[4] = A[4] * B[0] + A[5] * B[4] + A[6] * B[8] + A[7] * B[12];
-  ret[8] = A[8] * B[0] + A[9] * B[4] + A[10] * B[8] + A[11] * B[12];
-  ret[12] = A[12] * B[0] + A[13] * B[4] + A[14] * B[8] + A[15] * B[12];
-
-  ret[1] = A[0] * B[1] + A[1] * B[5] + A[2] * B[9] + A[3] * B[13];
-  ret[5] = A[4] * B[1] + A[5] * B[5] + A[6] * B[9] + A[7] * B[13];
-  ret[9] = A[8] * B[1] + A[9] * B[5] + A[10] * B[9] + A[11] * B[13];
-  ret[13] = A[12] * B[1] + A[13] * B[5] + A[14] * B[9] + A[15] * B[13];
-
-  ret[2] = A[0] * B[2] + A[1] * B[6] + A[2] * B[10] + A[3] * B[14];
-  ret[6] = A[4] * B[2] + A[5] * B[6] + A[6] * B[10] + A[7] * B[14];
-  ret[10] = A[8] * B[2] + A[9] * B[6] + A[10] * B[10] + A[11] * B[14];
-  ret[14] = A[12] * B[2] + A[13] * B[6] + A[14] * B[10] + A[15] * B[14];
-
-  ret[3] = A[0] * B[3] + A[1] * B[7] + A[2] * B[11] + A[3] * B[15];
-  ret[7] = A[4] * B[3] + A[5] * B[7] + A[6] * B[11] + A[7] * B[15];
-  ret[11] = A[8] * B[3] + A[9] * B[7] + A[10] * B[11] + A[11] * B[15];
-  ret[15] = A[12] * B[3] + A[13] * B[7] + A[14] * B[11] + A[15] * B[15];
-
-  return ret;
-};
-
-/**
- * Matrix Vector4 Multiplication
- * @method matrixByVector
- * @param {Array} A Matrix4 array
- * @param {Array} v Vector4
- * @return {Array} Vector4
- */
-dali.matrixByVector = function(A, v) {
-  "use strict";
-
-  var x = v[0];
-  var y = v[1];
-  var z = v[2];
-  var w = 1;
-
-  if (v.length === 4) {
-    w = v[3];
-  }
-
-  return [
-    A[0] * x + A[4] * y + A[8] * z + A[12] * w,
-    A[1] * x + A[5] * y + A[9] * z + A[13] * w,
-    A[2] * x + A[6] * y + A[10] * z + A[14] * w,
-    A[3] * x + A[7] * y + A[11] * z + A[15] * w
-  ];
-};
-
-/**
- * Get Matrix Determinant
- * @method matrixDeterminant
- * @param {Array} A Matrix4 array
- * @return {float} Determinant
- */
-dali.matrixDeterminant = function(A) {
-  "use strict";
-
-  var n11 = A[0],
-      n12 = A[4],
-      n13 = A[8],
-      n14 = A[12];
-  var n21 = A[1],
-      n22 = A[5],
-      n23 = A[9],
-      n24 = A[13];
-  var n31 = A[2],
-      n32 = A[6],
-      n33 = A[10],
-      n34 = A[14];
-  var n41 = A[3],
-      n42 = A[7],
-      n43 = A[11],
-      n44 = A[15];
-
-  var m0 = n23 * n34 * n42 - n24 * n33 * n42 + n24 * n32 * n43 - n22 * n34 * n43 - n23 * n32 * n44 + n22 * n33 * n44;
-  var m4 = n14 * n33 * n42 - n13 * n34 * n42 - n14 * n32 * n43 + n12 * n34 * n43 + n13 * n32 * n44 - n12 * n33 * n44;
-  var m8 = n13 * n24 * n42 - n14 * n23 * n42 + n14 * n22 * n43 - n12 * n24 * n43 - n13 * n22 * n44 + n12 * n23 * n44;
-  var m12 = n14 * n23 * n32 - n13 * n24 * n32 - n14 * n22 * n33 + n12 * n24 * n33 + n13 * n22 * n34 - n12 * n23 * n34;
-
-  return n11 * m0 + n21 * m4 + n31 * m8 + n41 * m12;
-};
-
-/**
- * Matrix Multiplication by scalar
- * @method matrixByScalar
- * @param {Array} A Matrix4 array
- * @param {float} s float
- * @return {Array} Matrix4
- */
-dali.matrixByScalar = function(A, s) {
-  "use strict";
-  return [A[0] * s, A[1] * s, A[2] * s, A[3] * s,
-          A[4] * s, A[5] * s, A[6] * s, A[7] * s,
-          A[8] * s, A[9] * s, A[10] * s, A[11] * s,
-          A[12] * s, A[13] * s, A[14] * s, A[15] * s
-         ];
-};
-
-/**
- * Matrix Inverse. Raises if there is none.
- * @method matrixInverse
- * @param {Array} A Matrix4 array
- * @return {Array} Inverse Matrix4
- */
-dali.matrixInverse = function(A) {
-  "use strict";
-  var ret = [1, 0, 0, 0,
-             0, 1, 0, 0,
-             0, 0, 1, 0,
-             0, 0, 0, 1
-            ];
-
-  ret[0] = A[5] * A[10] * A[15] - A[5] * A[11] * A[14] - A[9] * A[6] * A[15] + A[9] * A[7] * A[14] + A[13] * A[6] * A[11] - A[13] * A[7] * A[10];
-  ret[4] = -A[4] * A[10] * A[15] + A[4] * A[11] * A[14] + A[8] * A[6] * A[15] - A[8] * A[7] * A[14] - A[12] * A[6] * A[11] + A[12] * A[7] * A[10];
-  ret[8] = A[4] * A[9] * A[15] - A[4] * A[11] * A[13] - A[8] * A[5] * A[15] + A[8] * A[7] * A[13] + A[12] * A[5] * A[11] - A[12] * A[7] * A[9];
-  ret[12] = -A[4] * A[9] * A[14] + A[4] * A[10] * A[13] + A[8] * A[5] * A[14] - A[8] * A[6] * A[13] - A[12] * A[5] * A[10] + A[12] * A[6] * A[9];
-
-  ret[1] = -A[1] * A[10] * A[15] + A[1] * A[11] * A[14] + A[9] * A[2] * A[15] - A[9] * A[3] * A[14] - A[13] * A[2] * A[11] + A[13] * A[3] * A[10];
-  ret[5] = A[0] * A[10] * A[15] - A[0] * A[11] * A[14] - A[8] * A[2] * A[15] + A[8] * A[3] * A[14] + A[12] * A[2] * A[11] - A[12] * A[3] * A[10];
-  ret[9] = -A[0] * A[9] * A[15] + A[0] * A[11] * A[13] + A[8] * A[1] * A[15] - A[8] * A[3] * A[13] - A[12] * A[1] * A[11] + A[12] * A[3] * A[9];
-  ret[13] = A[0] * A[9] * A[14] - A[0] * A[10] * A[13] - A[8] * A[1] * A[14] + A[8] * A[2] * A[13] + A[12] * A[1] * A[10] - A[12] * A[2] * A[9];
-
-  ret[2] = A[1] * A[6] * A[15] - A[1] * A[7] * A[14] - A[5] * A[2] * A[15] + A[5] * A[3] * A[14] + A[13] * A[2] * A[7] - A[13] * A[3] * A[6];
-  ret[6] = -A[0] * A[6] * A[15] + A[0] * A[7] * A[14] + A[4] * A[2] * A[15] - A[4] * A[3] * A[14] - A[12] * A[2] * A[7] + A[12] * A[3] * A[6];
-  ret[10] = A[0] * A[5] * A[15] - A[0] * A[7] * A[13] - A[4] * A[1] * A[15] + A[4] * A[3] * A[13] + A[12] * A[1] * A[7] - A[12] * A[3] * A[5];
-  ret[14] = -A[0] * A[5] * A[14] + A[0] * A[6] * A[13] + A[4] * A[1] * A[14] - A[4] * A[2] * A[13] - A[12] * A[1] * A[6] + A[12] * A[2] * A[5];
-
-  ret[3] = -A[1] * A[6] * A[11] + A[1] * A[7] * A[10] + A[5] * A[2] * A[11] - A[5] * A[3] * A[10] - A[9] * A[2] * A[7] + A[9] * A[3] * A[6];
-  ret[7] = A[0] * A[6] * A[11] - A[0] * A[7] * A[10] - A[4] * A[2] * A[11] + A[4] * A[3] * A[10] + A[8] * A[2] * A[7] - A[8] * A[3] * A[6];
-  ret[11] = -A[0] * A[5] * A[11] + A[0] * A[7] * A[9] + A[4] * A[1] * A[11] - A[4] * A[3] * A[9] - A[8] * A[1] * A[7] + A[8] * A[3] * A[5];
-  ret[15] = A[0] * A[5] * A[10] - A[0] * A[6] * A[9] - A[4] * A[1] * A[10] + A[4] * A[2] * A[9] + A[8] * A[1] * A[6] - A[8] * A[2] * A[5];
-
-  var det = A[0] * ret[0] + A[1] * ret[4] + A[2] * ret[8] + A[3] * ret[12];
-
-  if (det === 0) {
-    throw "no inverse";
-  }
-
-  return dali.matrixByScalar(ret, 1 / det);
-};
-
-/**
- * Radian to degree
- * @method degree
- * @param {float} radians
- * @return {float} degrees
- */
-dali.degree = function(radians) {
-  "use strict";
-  return (radians * 180.0) / Math.PI;
-};
-
-/**
- * Degree to Radians
- * @method radian
- * @param {float} degree
- * @return {float} radian
- */
-dali.radian = function(degrees) {
-  "use strict";
-  return (degrees / 180.0) * Math.PI;
-};
-
-/**
- * Length of a vector
- * @method vectorLength
- * @param {array} Vector4
- * @return {float} The length of a vector
- */
-dali.vectorLength = function(array) {
-  "use strict";
-  var N = 3; // array.length;
-
-  var length = 0;
-  for (var i = 0; i < N; ++i) {
-    length += array[i] * array[i];
-  }
-  return Math.sqrt(length);
-};
-
-/**
- * Length of a vector squared
- * @method vectorLengthSquared
- * @param {array} Vector4
- * @return {float} The length of a vector squared
- */
-dali.vectorLengthSquared = function(array) {
-  "use strict";
-  var N = 3; // array.length;
-
-  var length = 0;
-  for (var i = 0; i < N; ++i) {
-    length += array[i] * array[i];
-  }
-  return length;
-};
-
-/**
- * Normalized vector
- * @method normalize
- * @param {array} Vector4
- * @return {float} The normalized vector
- */
-dali.normalize = function(array) {
-  "use strict";
-  var N = 3; // array.length;
-
-  var length = 0;
-  for (var i = 0; i < 3; ++i) {
-    length += array[i] * array[i];
-  }
-  length = Math.sqrt(length);
-
-  if (length !== 0) {
-    var ret = [];
-    for (i = 0; i < N; ++i) {
-      ret.push(array[i] / length);
-    }
-    for (i = N; i < array.length; ++i) {
-      ret.push(array[i]);
-    }
-    return ret;
-  } else {
-    return array;
-  }
-
-};
-
-/**
- * AxisAngle conversion to Quaternion
- * @method axisAngleToQuaternion
- * @param {array} axisAngle Vector4 [Axis.x, Axis.y, Axis.z, Angle]
- * @return {array} Quaternion
- */
-dali.axisAngleToQuaternion = function(axisAngle) {
-  "use strict";
-  var an = dali.normalize(axisAngle);
-  var angle = axisAngle[axisAngle.length - 1];
-  var halfTheta = angle * 0.5;
-  var sinThetaByTwo = Math.sin(halfTheta);
-  var cosThetaByTwo = Math.cos(halfTheta);
-  return [an[0] * sinThetaByTwo,
-          an[1] * sinThetaByTwo,
-          an[2] * sinThetaByTwo,
-          cosThetaByTwo
-         ];
-};
-
-/**
- * Vector3 dot product
- * @method vectorDot
- * @param {array} v1 Vector3
- * @param {array} v2 Vector3
- * @return {array} Quaternion
- */
-dali.vectorDot = function(v1, v2) {
-  "use strict";
-  return v1[0] * v2[0] + v1[1] * v2[1] + v1[2] * v2[2];
-};
-
-/**
- * Vector4 dot product
- * @method vectorDot
- * @param {array} v1 Vector4
- * @param {array} v2 Vector4
- * @return {float} Dot product
- */
-dali.vectorDot4 = function(v1, v2) {
-  "use strict";
-  return v1[0] * v2[0] + v1[1] * v2[1] + v1[2] * v2[2] + v1[3] * v2[3];
-};
-
-/**
- * Vector3 cross product
- * @method vectorCross
- * @param {array} v1 Vector3
- * @param {array} v2 Vector3
- * @return {array} Vector3 cross product
- */
-dali.vectorCross = function(v1, v2) {
-  "use strict";
-  var v1X = v1[0];
-  var v1Y = v1[1];
-  var v1Z = v1[2];
-
-  var v2X = v2[0];
-  var v2Y = v2[1];
-  var v2Z = v2[2];
-
-  return [v1Y * v2Z - v1Z * v2Y,
-          v1Z * v2X - v1X * v2Z,
-          v1X * v2Y - v1Y * v2X
-         ];
-};
-
-/**
- * VectorN dot product
- * @method vectorByScalar
- * @param {array} v1 VectorN
- * @param {array} v2 VectorN
- * @return {array} VectorN * s
- */
-dali.vectorByScalar = function(v1, s) {
-  "use strict";
-  var ret = [];
-  for (var i = 0, len = v1.length; i < len; i++) {
-    ret.push(v1[i] * s);
-  }
-  return ret;
-};
-
-/**
- * VectorN dot product
- * @method vectorAdd
- * @param {array} v1 VectorN
- * @param {array} v2 VectorN
- * @param {array} ..vN VectorN
- * @return {array} v1 + v2 + ... + vN
- */
-dali.vectorAdd = function() {
-  "use strict";
-  var ret = arguments[0];
-  var l = ret.length;
-  for (var i = 1, len = arguments.length; i < len; i++) {
-    var v = arguments[i];
-    for (var j = 0; j < l; j++) {
-      ret[j] += v[j];
-    }
-  }
-  return ret;
-};
-
-/**
- * Quaternion by quaternion
- * @method quatByQuat
- * @param {array} q1 Quaternion
- * @param {array} q2 Quaternion
- * @return {array} Quaternion
- */
-dali.quatByQuat = function(q1, q2) {
-  "use strict";
-  var q1X = q1[0];
-  var q1Y = q1[1];
-  var q1Z = q1[2];
-  var q1W = q1[3];
-
-  var q2X = q2[0];
-  var q2Y = q2[1];
-  var q2Z = q2[2];
-  var q2W = q2[3];
-
-  return [q1Y * q2Z - q1Z * q2Y + q1W * q2X + q1X * q2W,
-          q1Z * q2X - q1X * q2Z + q1W * q2Y + q1Y * q2W,
-          q1X * q2Y - q1Y * q2X + q1W * q2Z + q1Z * q2W,
-          q1W * q2W - dali.vectorDot(q1, q2)
-         ];
-};
-
-/**
- * Quaternion to Vector4 Axis angle
- * @method quaternionToAxisAngle
- * @param {array} q Quaternion
- * @return {array} Vector4 [Axis.x, Axis.y, Axis.z, Angle]
- */
-dali.quaternionToAxisAngle = function(q) {
-  "use strict";
-  var angle = Math.acos(q[3]);
-  var sine = Math.sin(angle);
-
-  if (sine === 0.0) {
-    throw "Cannot convert quaternion";
-  }
-
-  var sinfThetaInv = 1.0 / sine;
-
-  return [q[0] * sinfThetaInv,
-          q[1] * sinfThetaInv,
-          q[2] * sinfThetaInv,
-          angle * 2.0
-         ];
-};
-
-/**
- * Euler angles to Quaternion
- * @method eulerToQuaternion
- * @param {float} rxPitch Euler radians pitch
- * @param {float} ryYaw Euler radians yaw
- * @param {float} rzRoll Euler radians roll
- * @return {array} Quaternion
- */
-dali.eulerToQuaternion = function(rXPitch, rYYaw, rZRoll)
-{
-  var halfX = 0.5 * rXPitch;
-  var halfY = 0.5 * rYYaw;
-  var halfZ = 0.5 * rZRoll;
-
-  var cosX2 = Math.cos(halfX);
-  var cosY2 = Math.cos(halfY);
-  var cosZ2 = Math.cos(halfZ);
-
-  var sinX2 = Math.sin(halfX);
-  var sinY2 = Math.sin(halfY);
-  var sinZ2 = Math.sin(halfZ);
-
-  return [ cosZ2 * cosY2 * sinX2 - sinZ2 * sinY2 * cosX2,
-           cosZ2 * sinY2 * cosX2 + sinZ2 * cosY2 * sinX2,
-           sinZ2 * cosY2 * cosX2 - cosZ2 * sinY2 * sinX2,
-           cosZ2 * cosY2 * cosX2 + sinZ2 * sinY2 * sinX2 ];
-};
-
-/**
- * Euler angles to Vector4 Axis angle
- * @method eulerToAxisAngle
- * @param {float} eulerInDegrees
- * @return {array} Vector4 [Axis.x, Axis.y, Axis.z, Angle]
- */
-dali.eulerToAxisAngle = function(eulerInDegrees)
-{
-  var q = dali.eulerToQuaternion(dali.radian(eulerInDegrees[0]),dali.radian(eulerInDegrees[1]), dali.radian(eulerInDegrees[2]));
-  var aa = dali.quaternionToAxisAngle(q);
-  aa[3] = dali.degree(aa[3]); // @todo - radian?
-  return aa;
-};
-
-/**
- * Axis angle to Euler
- * @method axisAngleToEuler
- * @param {float} axisAngle [Axis.x, Axis.y, Axis.z, Angle]
- * @return {array} Vector4 [roll, pitch, yaw]
- */
-dali.axisAngleToEuler = function(axisAngle)
-{
-  // presume return from dali.js is degrees
-  axisAngle[3] = dali.radian(axisAngle[3]);
-  var q = dali.axisAngleToQuaternion(axisAngle);
-  return dali.quaternionToEuler(q).map(dali.degree);
-};
-
-/**
- * Euler angles to Vector4 Axis angle
- * @method quaternionToMatrix
- * @param {float} axisAngle [Axis.x, Axis.y, Axis.z, Angle]
- * @return {array} Vector4
- */
-dali.quaternionToMatrix = function(q) {
-  "use strict";
-  var x = q[0];
-  var y = q[1];
-  var z = q[2];
-  var w = q[3];
-  var xx = x * x;
-  var yy = y * y;
-  var zz = z * z;
-  var xy = x * y;
-  var xz = x * z;
-  var wx = w * x;
-  var wy = w * y;
-  var wz = w * z;
-  var yz = y * z;
-
-  var m = [1, 0, 0, 0,
-           0, 1, 0, 0,
-           0, 0, 1, 0,
-           0, 0, 0, 1];
-
-  m[0] = 1.0 - 2.0 * (yy + zz);
-  m[1] = 2.0 * (xy + wz);
-  m[2] = 2.0 * (xz - wy);
-  m[3] = 0.0;
-
-  m[4] = 2.0 * (xy - wz);
-  m[5] = 1.0 - 2.0 * (xx + zz);
-  m[6] = 2.0 * (yz + wx);
-  m[7] = 0.0;
-
-  m[8] = 2.0 * (xz + wy);
-  m[9] = 2.0 * (yz - wx);
-  m[10] = 1.0 - 2.0 * (xx + yy);
-  m[11] = 0.0;
-
-  m[12] = 0.0;
-  m[13] = 0.0;
-  m[14] = 0.0;
-  m[15] = 1.0;
-
-  return m;
-};
-
-/**
- * Quaternion to Euler
- * @method quaternionToEuler
- * @param {array} q Quaternion
- * @return {array} Vector3 [roll, pitch, yaw]
- */
-dali.quaternionToEuler = function(q) {
-  "use strict";
-  var x = q[0];
-  var y = q[1];
-  var z = q[2];
-  var w = q[3];
-
-  var sqw = w * w;
-  var sqx = x * x;
-  var sqy = y * y;
-  var sqz = z * z;
-
-  return [ Math.atan2(2.0 * (y * z + x * w), -sqx - sqy + sqz + sqw),
-           Math.asin(-2.0 * (x * z - y * w)),
-           Math.atan2(2.0 * (x * y + z * w), sqx - sqy - sqz + sqw)];
-};
-
-
-/**
- * Gets screen coordinates of world position
- * @method worldToScreen
- * @param {array} position array
- * @param {Dali.RenderTask} renderTask Dali RenderTask object
- * @return {array} Vector3 Screen position
- */
-dali.worldToScreen = function(position, renderTask) {
-  "use strict";
-  var useFirstRenderTask = false;
-
-  if (typeof renderTask === "undefined") {
-    useFirstRenderTask = true;
-  } else if (renderTask === null) { // null is an object
-    useFirstRenderTask = true;
-  }
-
-  if (useFirstRenderTask) {
-    var tasks = dali.stage.getRenderTaskList();
-    renderTask = tasks.getTask(0);
-    tasks.delete(); // wrapper
-  }
-
-  var camera = renderTask.getCameraActor();
-  var pos = renderTask.getCurrentViewportPosition();
-  var size = renderTask.getCurrentViewportSize();
-
-  var mat = dali.matrixByMatrix(camera.viewMatrix, camera.projectionMatrix);
-  var p = dali.matrixByVector(mat, position);
-  var depthRange = [0, 1];
-  var viewport = [pos[0], pos[1], size[0], size[1]];
-
-  var div;
-  // homogenous divide
-  if(0.0 === p[3]) {
-    div = 1.0;
-  } else {
-    div = 1 / p[3];
-  }
-
-  camera.delete(); // wrapper
-
-  return [
-    (1 + p[0] * div) * viewport[2] / 2 + viewport[0], (1 - p[1] * div) * viewport[3] / 2 + viewport[1], (p[2] * div) * (depthRange[1] - depthRange[0]) + depthRange[0],
-    div
-  ];
-};
-
-/**
- * Gets matrix identity
- * @method matrixIdentity
- * @return {array} Matrix4 identity
- */
-dali.matrixIdentity = function() {
-  "use strict";
-  return [1, 0, 0, 0,
-          0, 1, 0, 0,
-          0, 0, 1, 0,
-          0, 0, 0, 1
-         ];
-};
-
-/**
- * Gets matrix identity with position transformation
- * @method matrixTransform
- * @param {float} x X position
- * @param {float} y Y position
- * @param {float} z Z position
- * @return {array} Matrix4
- */
-dali.matrixTransform = function(x, y, z) {
-  "use strict";
-  return [1, 0, 0, 0,
-          0, 1, 0, 0,
-          0, 0, 1, 0,
-          x, y, z, 1
-         ];
-};
-
-/**
- * Gets matrix identity with position transformation
- * @method screenToPlaneLocal
- * @param {float} screenX Screen X position
- * @param {float} screenY Screen Y position
- * @param {Dali.RenderTask} Dali RenderTask
- * @param {array} planeOrientationMatrix
- * @param {float} planeWidth
- * @param {float} planeHeight
- * @return {array} Local coordinates
- */
-dali.screenToPlaneLocal = function(screenX, screenY, renderTask, planeOrientationMatrix, planeWidth, planeHeight) {
-  "use strict";
-
-  var camera = renderTask.getCameraActor();
-
-  var pos = renderTask.getCurrentViewportPosition();
-  var size = renderTask.getCurrentViewportSize();
-  var viewportX = pos[0];
-  var viewportY = pos[1];
-  var viewportW = size[0];
-  var viewportH = size[1];
-  var modelView = dali.matrixByMatrix(planeOrientationMatrix, camera.viewMatrix);
-
-  var inverseMvp = dali.matrixInverse(
-    dali.matrixByMatrix(modelView, camera.projectionMatrix));
-
-  var screenPos = [screenX - viewportX,
-                   viewportH - (screenY - viewportY),
-                   0.0, 1.0
-                  ];
-
-  screenPos[2] = 0.0;
-
-  var oglScreenPos = [(screenPos[0] / viewportW) * 2 - 1, (screenPos[1] / viewportH) * 2 - 1, (screenPos[2]) * 2 - 1,
-                      1
-                     ];
-
-
-  var nearPoint = dali.matrixByVector(inverseMvp, oglScreenPos);
-
-  if (nearPoint[3] === 0.0) {
-    throw "Unproject near fails";
-  }
-
-  nearPoint[3] = 1 / nearPoint[3];
-  nearPoint[0] = nearPoint[0] * nearPoint[3];
-  nearPoint[1] = nearPoint[1] * nearPoint[3];
-  nearPoint[2] = nearPoint[2] * nearPoint[3];
-
-
-  oglScreenPos[2] = 1.0 * 2 - 1;
-
-  var farPoint = dali.matrixByVector(inverseMvp, oglScreenPos);
-
-  if (farPoint[3] === 0.0) {
-    throw "Unproject far fails";
-  }
-
-  farPoint[3] = 1 / farPoint[3];
-  farPoint[0] = farPoint[0] * farPoint[3];
-  farPoint[1] = farPoint[1] * farPoint[3];
-  farPoint[2] = farPoint[2] * farPoint[3];
-
-  if (!((farPoint[2] < 0) && (nearPoint[2] > 0))) {
-    throw "ray not crossing xy plane";
-  }
-
-  var dist = nearPoint[2] / (nearPoint[2] - farPoint[2]);
-
-  var intersect = [nearPoint[0] + (farPoint[0] - nearPoint[0]) * dist,
-                   nearPoint[1] + (farPoint[1] - nearPoint[1]) * dist,
-                   0.0
-                  ];
-
-  intersect[0] = intersect[0] + planeWidth * 0.5;
-  intersect[1] = intersect[1] + planeHeight * 0.5;
-
-  return intersect;
-};
-
-/**
- * Gets matrix identity with position transformation
- * @method screenToLocal
- * @param {float} screenX Screen X position
- * @param {float} screenY Screen Y position
- * @param {Dali.Actor} actor Dali Actor
- * @param {Dali.RenderTask} renderTask Dali RenderTask
- * @return {array} Local coordinates
- */
-dali.screenToLocal = function(screenX, screenY, actor, renderTask) {
-  "use strict";
-  return dali.screenToPlaneLocal(screenX, screenY, renderTask, actor.worldMatrix, actor.size[0], actor.size[1]);
-};
-
-/**
- * Screen to local coordinates in the XY plane
- * @method screenToXY
- * @param {float} screenX Screen X position
- * @param {float} screenY Screen Y position
- * @param {Dali.Actor} actor Dali Actor
- * @param {Dali.RenderTask} renderTask Dali RenderTask
- * @return {array} Local coordinates
- */
-dali.screenToXY = function(screenX, screenY, actor, renderTask) {
-  "use strict";
-  var size = dali.stage.getSize();
-  return dali.screenToPlaneLocal(screenX, screenY,
-                                 renderTask,
-                                 dali.matrixIdentity(),
-                                 size[0],
-                                 size[1]);
-};
-
-/**
- * Screen to local coordinates in the YZ plane
- * @method screenToYZ
- * @param {float} screenX Screen X position
- * @param {float} screenY Screen Y position
- * @param {Dali.Actor} actor Dali Actor
- * @param {Dali.RenderTask} renderTask Dali RenderTask
- * @return {array} Local coordinates
- */
-dali.screenToYZ = function(screenX, screenY, actor, renderTask) {
-  "use strict";
-  var size = dali.stage.getSize();
-  var q = dali.axisAngleToQuaternion( [0, 1, 0, dali.radian(90)] );
-  return dali.screenToPlaneLocal(screenX, screenY,
-                                 renderTask,
-                                 dali.quaternionToMatrix(q),
-                                 size[0],
-                                 size[1]);
-};
-
-/**
- * Screen to local coordinates in the XZ plane
- * @method screenToXZ
- * @param {float} screenX Screen X position
- * @param {float} screenY Screen Y position
- * @param {Dali.Actor} actor Dali Actor
- * @param {Dali.RenderTask} renderTask Dali RenderTask
- * @return {array} Local coordinates
- */
-dali.screenToXZ = function(screenX, screenY, actor, renderTask) {
-  "use strict";
-  var size = dali.stage.getSize();
-  var q = dali.axisAngleToQuaternion( [1, 0, 0, dali.radian(90)] );
-  return dali.screenToPlaneLocal(screenX, screenY,
-                                 renderTask,
-                                 dali.quaternionToMatrix(q),
-                                 size[0],
-                                 size[1]);
-};
-
-/**
- * Screen coordinates for the given renderTask
- * @method screenCoordinates
- * @param {Dali.Actor} actor Dali Actor
- * @param {Dali.RenderTask} renderTask Dali RenderTask
- * @return {array} Local coordinates
- */
-dali.screenCoordinates = function(actor, renderTask) {
-  "use strict";
-  var size = actor.size;
-  var w2 = size[0] / 2;
-  var h2 = size[1] / 2;
-  var actorWorldMatrix = actor.worldMatrix;
-  var actorWorldPosition = actor.worldPosition;
-
-  return {
-    topLeft: dali.worldToScreen(dali.matrixByVector(actorWorldMatrix, [-w2, -h2, 0]), renderTask),
-    topRight: dali.worldToScreen(dali.matrixByVector(actorWorldMatrix, [+w2, -h2, 0]), renderTask),
-    bottomRight: dali.worldToScreen(dali.matrixByVector(actorWorldMatrix, [+w2, +h2, 0]), renderTask),
-    bottomLeft: dali.worldToScreen(dali.matrixByVector(actorWorldMatrix, [-w2, +h2, 0]), renderTask),
-    centre: dali.worldToScreen(actorWorldPosition, renderTask)
-  };
-};
-
-/**
- * Screen coordinates for the given renderTask
- * @method screenCoordinates
- * @param {Dali.Actor} actor Dali Actor
- * @param {Dali.RenderTask} renderTask Dali RenderTask
- * @return {array} Local coordinates
- */
-dali.screenToActor = function(actor, screenPos, renderTask) {
-  "use strict";
-  // , function will return coordinates in relation to actor`s anchorPoint (client coordinates).
-  var useFirstRenderTask = false;
-
-  if (typeof renderTask === "undefined") {
-    useFirstRenderTask = true;
-  } else if (renderTask === null) { // null is an object
-    useFirstRenderTask = true;
-  }
-
-  if (useFirstRenderTask) {
-    var tasks = dali.stage.getRenderTaskList();
-    renderTask = tasks.getTask(0);
-    tasks.delete(); // wrapper
-  }
-
-  var camera = renderTask.getCameraActor();
-  var vpp = renderTask.getCurrentViewportPosition();
-  var vps = renderTask.getCurrentViewportSize();
-
-  var mat = dali.matrixByMatrix(camera.projectionMatrix, camera.viewMatrix);
-
-  var inverseMvp = dali.matrixInverse(mat);
-
-  var x = screenPos[0];
-  var y = screenPos[1];
-  var z = screenPos[2];
-
-  var objectPos = dali.matrixByVector(inverseMvp,
-                                      // normalized +-1
-                                      [((x - vpp[0]) / vps[0]) * 2.0 - 1.0, ((y - vpp[1]) / vps[1]) * 2.0 - 1.0, (z * 2.0) - 1.0,
-                                       1.0
-                                      ]);
-
-  if (objectPos[3] === 0.0) {
-    throw "Cannot find screen Position";
-  }
-
-  objectPos[3] = 1 / objectPos[3];
-
-  return [objectPos[0] * objectPos[3],
-          objectPos[1] * objectPos[3],
-          objectPos[2] * objectPos[3],
-          objectPos[3]
-         ];
-};
-
-
-//------------------------------------------------------------------------------
-//
-// Utils Module
-//
-//------------------------------------------------------------------------------
-
-/**
- * Cache to fix the dali get/set thread issue
- *
- * Property sets are cached and cleared at the renderFinished callback
- */
-dali.internalUniqueId = function() {
-  "use strict";
-};
-
-dali.internalUniqueId.prototype._id = 0;
-dali.internalUniqueId.prototype.generateId = function() {
-  "use strict";
-  return ++dali.internalUniqueId.prototype._id;
-};
-
-dali.internalPropertyCacheEnable = true;
-dali.internalPropertyCache = {};
-
-/**
- * Merge two objects together in a simplistic key,value merge
- * @method mergeObjects
- * @param {object} o1 first object
- * @param {object} o2 second object
- * @return {object} The merged objects
- */
-dali.mergeObjects = function(o1, o2) {
-  "use strict";
-  for (var p in o2) {
-    try {
-      // Property in destination object set; update its value.
-      if ( o2[p].constructor === Object){
-        o1[p] = dali.mergeObjects(o1[p], o2[p]);
-
-      } else {
-        o1[p] = o2[p];
-      }
-    } catch(e) {
-      // Property in destination object not set; create it and set its value.
-      o1[p] = o2[p];
-    }
-  }
-  return o1;
-};
-
-//------------------------------------------------------------------------------
-//
-// Callbacks Module
-//
-// Data dali can request during update & render loop.
-//
-//------------------------------------------------------------------------------
-
-/**
- * Gets a glyph by rendering to a hidden browser canvas
- */
-/** @private */
-dali.requestedGlyphImage = function(sFontFamily, sFontStyle, fFontSize, iChar) {
-  "use strict";
-
-  var buffer = document.createElement("canvas");
-  buffer.width = fFontSize;
-  buffer.height = fFontSize;
-  var ctx = buffer.getContext("2d");
-
-  ctx.font = sFontStyle + " " + fFontSize + "px " + sFontFamily;
-  ctx.fillText(String.fromCharCode(iChar), 0, 0 + fFontSize);
-
-  var imageData = ctx.getImageData(0, 0, fFontSize, fFontSize);
-
-  // emscripten checks only for this type if array in converting to strings
-  // (getImageData() returns Uint8CheckedArray or some such)
-  //  var uint8array = new Uint8Array( imageData.data );
-
-  return imageData.data; // return uint8array; //
-};
-
-/** @private */
-dali.postRenderFunction = undefined;
-
-/*
- * End of renderering tasks
- *  - Reset the property cache
- */
-/** @private */
-dali.requestedRenderFinished = function() {
-  "use strict";
-  // reset the temporary cache
-  dali.internalPropertyCache = {};
-  if(dali.postRenderFunction) {
-    dali.postRenderFunction();
-  }
-};
-
-dali.setCallbackGetGlyphImage(dali.requestedGlyphImage);
-dali.setCallbackRenderFinished(dali.requestedRenderFinished);
-
-//------------------------------------------------------------------------------
-//
-// Property Marshalling Module
-//
-// Javascript objects are adorned with dali properties as they are created or
-// fetched from the C++ api
-//
-// Data is marshalled to avoid some of the necessary C++ memory management for
-// small property classes.
-//
-//------------------------------------------------------------------------------
-dali.__propertyTypeJsLut = { boolean: dali.PropertyType.BOOLEAN,
-                             number: dali.PropertyType.FLOAT,
-                             string: dali.PropertyType.STRING };
-
-dali.__propertyValueCtor = {};
-
-[ [dali.PropertyType.INTEGER.value, dali.PropertyValueInteger],
-  [dali.PropertyType.FLOAT.value, dali.PropertyValueFloat],
-  [dali.PropertyType.STRING.value, dali.PropertyValueString],
-  [dali.PropertyType.VECTOR2.value, dali.PropertyValueVector2],
-  [dali.PropertyType.VECTOR3.value, dali.PropertyValueVector3],
-  [dali.PropertyType.VECTOR4.value, dali.PropertyValueVector4],
-  [dali.PropertyType.MATRIX.value, dali.PropertyValueMatrix],
-  [dali.PropertyType.MATRIX3.value, dali.PropertyValueMatrix3],
-  [dali.PropertyType.ARRAY.value, dali.PropertyValueArray],
-  [dali.PropertyType.MAP.value, dali.PropertyValueMap],
-  [dali.PropertyType.RECTANGLE.value, dali.PropertyValueIntRect] ].map( function(ab) { dali.__propertyValueCtor[ ab[0] ] = ab[1]; } );
-
-dali.propertyTypeFromJsValue = function(value) {
-  return dali.__propertyTypeJsLut[ typeof(value) ];
-};
-
-dali.propertyValueCtor = function(propertyType) {
-  return dali.__propertyValueCtor[ propertyType.value ];
-};
-
-/**
- * Create a Dali PropertyValue from a javascript value.
- * @method DaliPropertyValue
- * @param {object} object to retrieve the property type when value is an object
- * @param {string} name The name of the property
- * @return {Dali.PropertyValue} A Dali PropertyValue which must be '.delete()' when finished with
- */
-dali.DaliPropertyValue = function(object, name, value) {
-  "use strict";
-
-  var setProperty = false;
-  if (typeof (value) === "boolean") {
-    setProperty = new dali.PropertyValueBoolean(value);
-  } else if (typeof (value) === "number") {
-    setProperty = new dali.PropertyValueFloat(value);
-  } else if (typeof (value) === "string") {
-    setProperty = new dali.PropertyValueString(value);
-  } else if (typeof (value) === "object") {
-    if (value.constructor === dali.PropertyValueValue) {
-      setProperty = value;
-    } else {
-      var type = false;
-      if (object) {
-        type = object.getPropertyTypeFromName(name);
-      }
-      if (type === dali.PropertyType.ROTATION) {
-        if (value.length === 3) {
-          setProperty = new dali.PropertyValueEuler(value);
-        } else {
-          setProperty = new dali.PropertyValueAxisAngle(value);
-        }
-      } else if (value.length) {
-        if (type === dali.PropertyType.ARRAY) {
-          setProperty = new dali.PropertyValueArray(value);
-        } else {
-          if (value.length === 2) {
-            setProperty = new dali.PropertyValueVector2(value);
-          } else if (value.length === 3) {
-            setProperty = new dali.PropertyValueVector3(value);
-          } else if (value.length === 4) {
-            if (type === dali.PropertyType.RECTANGLE) {
-              setProperty = new dali.PropertyValueIntRect(value[0], value[1], value[2], value[3]);
-            } else {
-              setProperty = new dali.PropertyValueVector4(value);
-            }
-          } else if (value.length === 9) {
-            setProperty = new dali.PropertyValueMatrix3(value);
-          } else if (value.length === 16) {
-            setProperty = new dali.PropertyValueMatrix(value);
-          } else {
-            throw new Error("Cannot set property");
-          }
-        }
-      } else {
-        // todo; I think a map has a length....
-        setProperty = new dali.PropertyValueMap(value);
-      }
-    }
-  } else {
-    if (object) {
-      throw object.toString() + " " + name.toString() + " " + value.toString();
-    } else {
-      throw name.toString() + " " + value.toString();
-    }
-  }
-
-  return setProperty;
-};
-
-/**
- * Get the value type held in a PropertyValue and call '.delete()' to drop the C++ backing object
- * @method marshallProperty
- * @param {Dali.PropertyValue} p A Dali PropertyValue. This will be '.delete()'ed.
- * @return {any} The value held
- */
-/** @private */
-dali.marshallProperty = function(p) {
-  "use strict";
-
-  var ret;
-  var type = p.getType();
-
-  if (type === 0) {
-    // raise?
-    throw new Error("Property has no type?");
-  } else if (type === dali.PropertyType.BOOLEAN.value) {
-    ret = p.getBoolean();
-  } else if (type === dali.PropertyType.FLOAT.value) {
-    ret = p.getFloat();
-  } else if (type === dali.PropertyType.INTEGER.value) {
-    ret = p.getInteger();
-  } else if (type === dali.PropertyType.VECTOR2.value) {
-    ret = p.getVector2();
-  } else if (type === dali.PropertyType.VECTOR3.value) {
-    ret = p.getVector3();
-  } else if (type === dali.PropertyType.VECTOR4.value) {
-    ret = p.getVector4();
-  } else if (type === dali.PropertyType.MATRIX3.value) {
-    ret = p.getMatrix3();
-  } else if (type === dali.PropertyType.MATRIX.value) {
-    ret = p.getMatrix();
-  } else if( type === dali.PropertyType.RECTANGLE ) {
-    ret = p.getIntRect();
-  } else if (type === dali.PropertyType.ROTATION.value) {
-    ret = p.getRotation();
-  } else if (type === dali.PropertyType.STRING.value) {
-    ret = p.getString();
-  } else if (type === dali.PropertyType.ARRAY.value) {
-    ret = p.getArray();
-  } else if (type === dali.PropertyType.MAP.value) {
-    ret = p.getMap();
-  }
-  p.delete();
-  return ret;
-};
-
-/**
- * Set a value on an object by creating and deleting a Dali PropertyValue object
- * @method marshallSetProperty
- * @param {object} object The object who's property to set from
- * @param {string} name The property name
- * @param {any} value The Javascript value
- */
-/** @private */
-dali.marshallSetProperty = function(object, name, value) {
-  "use strict";
-  var setProperty = new dali.DaliPropertyValue(object, name, value);
-
-  if (setProperty) {
-
-    object.setProperty(name, setProperty);
-
-    //console.log("marshallSetProperty set property" + setProperty );
-    setProperty.delete();
-
-    if(dali.internalPropertyCacheEnable) {
-      // set in cache to fix dali get/set problem
-      if("getId" in object ) // only with actors
-      {
-        var uniqueId = object.getId(); // _uniqueId;
-        if (uniqueId !== undefined) {
-          var objectDict = dali.internalPropertyCache[uniqueId];
-          if (objectDict === undefined) {
-            dali.internalPropertyCache[uniqueId] = {};
-          }
-          dali.internalPropertyCache[uniqueId][name] = value;
-        }
-      }
-    }
-  }
-};
-
-/**
- * Get a Javascript value from an object by creating and deleting a PropertyValue
- * @method marshallGetProperty
- * @param {object} object The object who's property to get from
- * @param {string} name The property name
- * @return {any} The value of the property
- */
-/** @private */
-dali.marshallGetProperty = function(object, name) {
-  "use strict";
-
-  if(dali.internalPropertyCacheEnable) {
-    // is the value live in the cache? if so use that value instead
-    if("getId" in object) { // only with actors
-      var uniqueId = object.getId(); // _uniqueId;
-      if (uniqueId !== undefined) {
-        var objectDict = dali.internalPropertyCache[uniqueId];
-        if (objectDict !== undefined) {
-          var value = dali.internalPropertyCache[uniqueId][name];
-          if (value !== undefined) {
-            return value;
-          }
-        }
-      }
-    }
-  }
-
-  var ret;
-  var p;
-  p = object.getProperty(name);
-  if (!p) {
-    throw new Error("Property doesnt exist?");
-  }
-  var type = p.getType();
-
-  if (type === 0) {
-    // raise?
-    throw new Error("Property has no type?");
-  } else if (type === dali.PropertyType.BOOLEAN.value) {
-    ret = p.getBoolean();
-  } else if (type === dali.PropertyType.FLOAT.value) {
-    ret = p.getFloat();
-  } else if (type === dali.PropertyType.INTEGER.value) {
-    ret = p.getInteger();
-  } else if (type === dali.PropertyType.VECTOR2.value) {
-    ret = p.getVector2();
-  } else if (type === dali.PropertyType.VECTOR3.value) {
-    ret = p.getVector3();
-  } else if (type === dali.PropertyType.VECTOR4.value) {
-    // VECTOR4
-    ret = p.getVector4();
-  } else if (type === dali.PropertyType.MATRIX3.value) {
-    // MATRIX3
-    ret = p.getMatrix3();
-  } else if (type === dali.PropertyType.MATRIX.value) {
-    // MATRIX
-    ret = p.getMatrix();
-  } else if( type === dali.PropertyType.RECTANGLE ) {
-    ret = p.getIntRect();
-  } else if (type === dali.PropertyType.ROTATION.value) {
-    ret = p.getRotation();
-  } else if (type === dali.PropertyType.STRING.value) {
-    ret = p.getString();
-  } else if (type === dali.PropertyType.ARRAY.value) {
-    ret = p.getArray();
-  } else if (type === dali.PropertyType.MAP.value) {
-    ret = p.getMap();
-  }
-  p.delete();
-  return ret;
-};
-
-
-/**
- * Set property accessors on the given handle for each property found on the handle
- * @method internalSetupProperties
- * @param {Dali.BaseHandle} handle A Dali property holding object
- * @return {Dali.BaseHandle} The same handle which has property accessors.
- */
-/** @private */
-dali.internalSetupProperties = function(handle) {
-  "use strict";
-  if(handle.ok()) {
-    var props = handle.getProperties();
-
-    for (var i = 0; i < props.size(); i++) {
-      // anon function because of closure with defineProperty
-      // (if just variable in loop then the variable 'address' is captured, not the value
-      //  so it becomes last value set)
-      (function(name, object) {
-        // @todo Dali error?? name lengths should never be zero
-        if (name.length) {
-          Object.defineProperty(handle, name, {
-            enumerable: true,
-            configurable: false,
-            get: function() {
-              return dali.marshallGetProperty(handle, name);
-            },
-            set: function(newValue) {
-              dali.marshallSetProperty(handle, name, newValue);
-            }
-          });
-        }
-      })(props.get(i), handle);
-    }
-
-    // handle._uniqueId = dali.internalUniqueId.prototype.generateId();
-  }
-
-  return handle;
-};
-
-//------------------------------------------------------------------------------
-//
-// Handle API Module
-//
-// API Wrappers for some Dali.Handle methods to marshall properties
-//
-//------------------------------------------------------------------------------
-
-/**
- * Register a new property and add JS style property accessors
- * @method registerProperty
- * @param {string} name The property name
- * @param {any} value Any Javascript value
- * @return {int} The registered properties ID
- */
-dali.Handle.prototype.registerProperty = function(name, value) {
-  "use strict";
-  var ret = -1;
-
-  var propertyValue = new dali.DaliPropertyValue(null, name, value);
-  ret = this.__registerProperty(name, propertyValue);
-  propertyValue.delete(); // wrapper
-  Object.defineProperty(this, name, {
-    enumerable: true,
-    configurable: false,
-    get: function() {
-      return dali.marshallGetProperty(this, name);
-    },
-    set: function(newValue) {
-      dali.marshallSetProperty(this, name, newValue);
-    }
-  });
-
-  return ret;
-};
-
-/**
- * Register a new animated property
- * @method registerAnimatedProperty
- * @param {string} name The property name
- * @param {any} value Any Javascript value
- * @return {int} The registered properties ID
- */
-dali.Handle.prototype.registerAnimatedProperty = function(name, value) {
-  "use strict";
-  var ret = -1;
-
-  var propertyValue = new dali.DaliPropertyValue(null, name, value);
-  ret = this.__registerAnimatedProperty(name, propertyValue);
-  propertyValue.delete(); // wrapper
-  Object.defineProperty(this, name, {
-    enumerable: true,
-    configurable: false,
-    get: function() {
-      return dali.marshallGetProperty(this, name);
-    },
-    set: function(newValue) {
-      dali.marshallSetProperty(this, name, newValue);
-    }
-  });
-  return ret;
-};
-
-//------------------------------------------------------------------------------
-//
-// Stage Module
-//
-//------------------------------------------------------------------------------
-dali.Stage.prototype.getRootLayer = function() {
-  "use strict";
-  var root = this.__getRootLayer();
-  dali.internalSetupProperties(root);
-  return root;
-};
-
-//------------------------------------------------------------------------------
-//
-// PropertyMap Module
-//
-// API Wrappers for some Dali.PropertyMap methods to marshall properties
-//
-//------------------------------------------------------------------------------
-
-/**
- * Insert a value into the PropertyMap
- * @method insert
- * @param {string} key The key
- * @param {any} value Any Javascript value
- * @param {PropertyType} propertyType The Dali property type
- */
-dali.PropertyMap.prototype.insert = function(key, value, propertyType) {
-  "use strict";
-
-  var type = propertyType;
-
-  if( propertyType === undefined ) { // can be optional
-    propertyType = dali.propertyTypeFromJsValue(value);
-  }
-
-  var constructor = dali.propertyValueCtor(propertyType);
-
-  var setProperty = constructor( value );
-
-  if(setProperty) {
-    this.__insert(key, setProperty);
-    setProperty.delete();
-  }
-};
-
-/**
- * Get a value from the PropertyMap
- * @method get
- * @param {string} key The key
- * @return The Javascript value
- */
-dali.PropertyMap.prototype.get = function(key) {
-  "use strict";
-  var p = this.__get(key);
-
-  var ret = dali.marshallProperty(p);
-
-  // p.delete(); // @todo should we delete here?
-
-  return ret;
-};
-
-//------------------------------------------------------------------------------
-//
-// PropertyBuffer Module
-//
-// API Wrappers for some Dali.PropertyBuffer methods to marshall properties
-//
-//------------------------------------------------------------------------------
-var _propertyTypeInfoList = [
-  [ dali.PropertyType.FLOAT.value, { size: 4, length: 1, dataView: Float32Array }],
-  [ dali.PropertyType.INTEGER.value, { size: 4, length: 1, dataView: Int32Array }],
-  [ dali.PropertyType.VECTOR2.value, { size: 2 * 4, length: 2, dataView: Float32Array }],
-  [ dali.PropertyType.VECTOR3.value, { size: 3 * 4, length: 3, dataView: Float32Array }],
-  [ dali.PropertyType.VECTOR4.value, { size: 4 * 4, length: 4, dataView: Float32Array }],
-  [ dali.PropertyType.MATRIX3.value, { size: 9 * 4, length: 9, dataView: Float32Array }],
-  [ dali.PropertyType.MATRIX.value, { size: 16 * 4, length: 16, dataView: Float32Array }]
-];
-
-var _propertyTypeInfo = {};
-function _createPropertyBuffer() {
-  "use strict";
-  for(var i = 0; i < _propertyTypeInfoList.length; i++) {
-    _propertyTypeInfo[ _propertyTypeInfoList[i][0] ] = _propertyTypeInfoList[i][1];
-  }
-}
-
-_createPropertyBuffer();
-
-/**
- * Create a Dali.PropertyBuffer from an info dictionary
- * @method createPropertyBuffer
- * @param {object} info
- * @param {any} value Any Javascript value
- * @param {PropertyType} propertyType The Dali property type
- * @example
- * var verts = createPropertyBuffer( {format: [ ["apos", dali.PropertyType.VECTOR2],
- *                                              ["acol", dali.PropertyType.VECTOR4] ],
- *                                    data: { "apos": [ [-halfQuadSize, -halfQuadSize],
- *                                                      [+halfQuadSize, -halfQuadSize],
- *                                                      [-halfQuadSize, +halfQuadSize],
- *                                                      [+halfQuadSize, +halfQuadSize]
- *                                                    ],
- *                                            "acol": [ [0, 0, 0, 1],
- *                                                      [1, 0, 1, 1],
- *                                                      [0, 1, 0, 1],
- *                                                      [1, 1, 1, 1]
- *                                                    ]
- *                                          }
- *                                   }
- */
-dali.createPropertyBuffer = function(info) {
-  "use strict";
-  var format = new dali.PropertyMap();
-  var dataLength;
-  var recordSize = 0;
-  var i;
-  for(i = 0; i < info.format.length; i++) {
-    format.insert(info.format[i][0], info.format[i][1].value, dali.PropertyType.INTEGER);
-    if(dataLength === undefined) {
-      dataLength = info.data[info.format[i][0]].length;
-    }
-    assert(info.data[info.format[i][0]]);
-    assert(dataLength === info.data[info.format[i][0]].length);
-    recordSize += _propertyTypeInfo[info.format[i][1].value].size;
-  }
-
-  var buffer = new ArrayBuffer(dataLength * recordSize);
-
-  var recordOffset = 0;
-  var offset = 0;
-  for(i = 0; i < dataLength; i++) {
-    for(var j = 0; j < info.format.length; j++) {
-      var name = info.format[j][0];
-      var type = info.format[j][1].value;
-      var length = _propertyTypeInfo[type].length;
-      var DataView = _propertyTypeInfo[type].dataView;
-      var view = new DataView(buffer, recordOffset + offset, length);
-      offset += _propertyTypeInfo[type].size;
-      if(length === 1) {
-        view[0] = info.data[name][i];
-      } else {
-        for(var k = 0; k < length; k++) {
-          view[k] = info.data[name][i][k];
-        }
-      }
-    }
-    offset = 0;
-    recordOffset += recordSize;
-  }
-
-  var propertyBuffer = new dali.PropertyBuffer(format);
-
-  propertyBuffer.setData(buffer, dataLength);
-
-  format.delete(); //
-
-  return propertyBuffer;
-};
-
-//------------------------------------------------------------------------------
-//
-// Actor Module
-//
-// API Wrappers for some Dali.PropertyBuffer methods to marshall properties
-//
-//------------------------------------------------------------------------------
-
-/**
- * Gets a parent with JS style property accessors
- * @method getParent
- * @return The parent
- */
-dali.Actor.prototype.getParent = function() {
-  "use strict";
-  var bareActor = this.__getParent();
-  if(!bareActor.ok()) {
-    bareActor.delete(); // wrapper
-    bareActor = null;
-  } else {
-    // add properties to the bare Actor
-    dali.internalSetupProperties(bareActor);
-  }
-  return bareActor;
-};
-
-/**
- * Finds child by ID and adorns with JS style property accessors
- * @method findChildById
- * @param {int} index The ID of the child
- * @return The found child or null
- */
-dali.Actor.prototype.findChildById = function(index) {
-  "use strict";
-  var bareActor = this.__findChildById(index);
-  if(!bareActor.ok()) {
-    bareActor.delete(); // wrapper
-    bareActor = null;
-  } else {
-    dali.internalSetupProperties(bareActor);
-  }
-  return bareActor;
-};
-
-/**
- * Finds child by name and adorns with JS style property accessors
- * @method findChildByName
- * @param {string} name The ID of the child
- * @return The found child or null
- */
-dali.Actor.prototype.findChildByName = function(name) {
-  "use strict";
-  var bareActor = this.__findChildByName(name);
-  if(!bareActor.ok()) {
-    bareActor.delete(); // wrapper
-    bareActor = null;
-  } else {
-    dali.internalSetupProperties(bareActor);
-  }
-  return bareActor;
-};
-
-/**
- * Gets child at child index and adorns with JS style property accessors
- * @method getChildAt
- * @param {int} index The ID of the child
- * @return The found child or null
- */
-dali.Actor.prototype.getChildAt = function(index) {
-  "use strict";
-  var bareActor = this.__getChildAt(index);
-  if(!bareActor.ok()) {
-    bareActor.delete(); // wrapper
-    bareActor = null;
-  } else {
-    dali.internalSetupProperties(bareActor);
-  }
-  return bareActor;
-};
-
-/*
- * add children of actor to collection in depth first manner
- */
-/** @private */
-dali.internalDepthFirstCollection = function(actor, collection) {
-  "use strict";
-  for (var i = 0; i < actor.getChildCount(); i++) {
-    var a = actor.getChildAt(i); // adds properties in dotted
-    collection.push(a);
-    dali.internalDepthFirstCollection(a, collection);
-  }
-};
-
-/**
- * Finds all children of the actor and adorns with JS style property accessors
- * @method findAllChildren
- * @return A list of children
- */
-dali.Actor.prototype.findAllChildren = function() {
-  "use strict";
-  var col = [];
-  dali.internalDepthFirstCollection(this, col);
-  return col;
-};
-
-/**
- * Gets a childFinds all children of the actor and adorns with JS style property accessors
- * @method getChildren
- * @return A list of children
- */
-dali.Actor.prototype.getChildren = function() {
-  "use strict";
-  var col = [];
-  for (var i = 0, len = this.getChildCount(); i < len; i++) {
-    var c = this.getChildAt(i);
-    col.push(c);
-  }
-  return col;
-};
-
-/**
- * 'directChildren' kept for GUIBuilder support
- * @deprecated
- */
-dali.Actor.prototype.directChildren = dali.Actor.prototype.getChildren;
-
-/**
- * Connects a callback to a signal by name
- * @method connect
- * @param {string} signalName The signal to connect to
- * @param {function} callback The callback to call
- * @param {Dali.SignalHolder} The signal holder object that can signal connection deletion
- * @return true if connection was possible
- */
-dali.Actor.prototype.connect = function(signalName, callback, signalHolder) {
-  "use strict";
-  // wrap in closure so we can setup properties in . notation
-  // and add actor methods to c++ raw Actor
-  if(signalHolder === undefined) {
-    // default js signal holder if none provided
-    signalHolder = dali.jsSignalHolder;
-  }
-
-  return this.__connect( signalHolder,
-                         signalName,
-                         (function(cb) {
-                           return function() {
-                             var args = [dali.internalSetupProperties(arguments[0])];
-                             for(var i = 1; i < arguments.length; i++) {
-                               args.push( arguments[i] );
-                             }
-                             cb.apply(null, args);
-                           };
-                         })(callback)
-                       );
-};
-
-/**
- * Connects a callback to a property notification
- * @method setPropertyNotification
- * @param {string} property The property name
- * @param {string} condition The condition [False,LessTHan,GreaterThan,Inside,Outside,Step,VariableStep]
- * @param {any} arg0 The first property notification argument
- * @param {any} arg1 The second property notification argument
- * @param {function} callback The callback function
- * @param {Dali.SignalHolder} The signal holder object that can signal connection deletion
- * @return true if connection was possible
- */
-dali.Actor.prototype.setPropertyNotification = function(property, condition, arg0, arg1, callback, signalHolder) {
-  "use strict";
-
-  if(signalHolder === undefined) {
-    // default js signal holder if none provided
-    signalHolder = dali.jsSignalHolder;
-  }
-
-  var index = this.getPropertyIndex(property);
-
-  this.__setPropertyNotification(signalHolder, index, condition, arg0, arg1, callback);
-};
-
-/**
- * Gets the renderer by index
- * @method getRendererAt
- * @param {int} index The index of the renderer
- * @return The Render or null
- */
-dali.Actor.prototype.getRendererAt = function(index) {
-  "use strict";
-  var renderer = this.__getRendererAt(index);
-  if(!renderer.ok()) {
-    renderer.delete(); // wrapper
-    renderer = null;
-  } else {
-    dali.internalSetupProperties(renderer);
-  }
-  return renderer;
-};
-
-/** private */
-dali.__ActorConstructor = dali.Actor;
-
-/**
- * Construtor that adorns with JS style property accessors
- * @return The wrapped Dali.Actor object
- */
-dali.Actor = function() {
-  "use strict";
-  var a = new dali.__ActorConstructor();
-  dali.internalSetupProperties(a);
-  return a;
-};
-
-//------------------------------------------------------------------------------
-//
-// New Mesh Module
-//
-//------------------------------------------------------------------------------
-dali.__ShaderConstructor = dali.Shader;
-dali.Shader = function(vertex, fragment, hints) {
-  "use strict";
-  var a = new dali.__ShaderConstructor(vertex, fragment, hints);
-  dali.internalSetupProperties(a);
-  return a;
-};
-
-dali.__MaterialConstructor = dali.Material;
-dali.Material = function(shader) {
-  "use strict";
-  var a = new dali.__MaterialConstructor(shader);
-  dali.internalSetupProperties(a);
-  return a;
-};
-
-dali.__RendererConstructor = dali.Renderer;
-dali.Renderer = function(geometry, material) {
-  "use strict";
-  var a = new dali.__RendererConstructor(geometry, material);
-  dali.internalSetupProperties(a);
-  return a;
-};
-
-//------------------------------------------------------------------------------
-//
-// Animation Module
-//
-//------------------------------------------------------------------------------
-dali.__PathConstructor = dali.Path;
-dali.Path = function() {
-  "use strict";
-  var a = new dali.__PathConstructor();
-  dali.internalSetupProperties(a);
-  return a;
-};
-
-/**
- * animateTo a value
- * @method animateTo
- * @param {object} The object
- * @param {string} propertyName The objects property name
- * @param {any} value The value
- * @param {string} alphaFunction The alpha function
- * @param {float} delay The delay
- * @param {float} duration The duration
- */
-dali.Animation.prototype.animateTo = function(object, propertyName, value, alphaFunction, delay, duration) {
-  "use strict";
-  var propertyValue = new dali.DaliPropertyValue(object, propertyName, value);
-  if (propertyValue) {
-    this.__animateTo(object, propertyName, propertyValue, alphaFunction, delay, duration);
-    propertyValue.delete();
-  } else {
-    throw new Error("Unknown property?");
-  }
-};
-
-/**
- * animateBy a value
- * @method animateBy
- * @param {object} The object
- * @param {string} propertyName The objects property name
- * @param {any} value The value
- * @param {string} alphaFunction The alpha function
- * @param {float} delay The delay
- * @param {float} duration The duration
- */
-dali.Animation.prototype.animateBy = function(object, propertyName, value, alphaFunction, delay, duration) {
-  "use strict";
-  var propertyValue = new dali.DaliPropertyValue(object, propertyName, value);
-  if (propertyValue) {
-    this.__animateBy(object, propertyName, propertyValue, alphaFunction, delay, duration);
-    propertyValue.delete();
-  } else {
-    throw new Error("Unknown property?");
-  }
-};
-
-/**
- * Animate a Path
- * @method animatePath
- * @param {object} The object
- * @param {Dali.Path} pathObject The path object
- * @param {array} forward The path forward vector
- * @param {string} alphaFunction The alpha function
- * @param {float} delay The delay
- * @param {float} duration The duration
- */
-dali.Animation.prototype.animatePath = function(object, pathObject, forward, alphaFunction, delay, duration) {
-  "use strict";
-  this.__animatePath(object, pathObject, forward, alphaFunction, delay, duration);
-};
-
-/**
- * animateBetween a value
- * @method animateBetween
- * @param {object} The object
- * @param {string} propertyName The objects property name
- * @param {dali.KeyFrames} keyFrames The keyframes
- * @param {string} alphaFunction The alpha function
- * @param {float} delay The delay
- * @param {float} duration The duration
- */
-dali.Animation.prototype.animateBetween = function(object, propertyName, keyFrames, alphaFunction, delay, duration, interpolation) {
-  "use strict";
-  var propertyValue;
-
-  var daliKeyFrames = new dali.KeyFrames();
-
-  for(var i = 0; i < keyFrames.length; i++) {
-    if(keyFrames[i].length > 2) { // has alpha
-      propertyValue = dali.DaliPropertyValue(null, null, keyFrames[i][1]);
-      if(!propertyValue) {
-        throw new Error("Unknown property?");
-      }
-      daliKeyFrames.add(keyFrames[i][0], propertyValue, keyFrames[i][2]);
-      propertyValue.delete();
-    } else {
-      propertyValue = dali.DaliPropertyValue(null, null, keyFrames[i][1]);
-      if(!propertyValue) {
-        throw new Error("Unknown property?");
-      }
-      daliKeyFrames.add(keyFrames[i][0], propertyValue);
-      propertyValue.delete();
-    }
-  }
-
-  this.__animateBetween(object, propertyName, daliKeyFrames, alphaFunction, delay, duration, interpolation);
-
-  daliKeyFrames.delete();
-
-};
-
-//------------------------------------------------------------------------------
-//
-// RenderTask Module
-//
-//------------------------------------------------------------------------------
-dali.RenderTask.prototype.getCameraActor = function() {
-  "use strict";
-  var a = this.__getCameraActor();
-  if (a.ok()) {
-    dali.internalSetupProperties(a);
-  }
-  return a;
-};
-
-Object.defineProperty(dali.RenderTask.prototype, "x", {
-  enumerable: true,
-  configurable: false,
-  get: function() {
-    return this.getCurrentViewportPosition()[0];
-  },
-  set: function(v) {
-    var pos = this.getCurrentViewportPosition();
-    this.setViewportPosition(v, pos[1]);
-  }
-});
-
-Object.defineProperty(dali.RenderTask.prototype, "y", {
-  enumerable: true,
-  configurable: false,
-  get: function() {
-    return this.getCurrentViewportPosition()[1];
-  },
-  set: function(v) {
-    var pos = this.getCurrentViewportPosition();
-    this.setViewportPosition(pos[0], v);
-  }
-});
-
-Object.defineProperty(dali.RenderTask.prototype, "width", {
-  enumerable: true,
-  configurable: false,
-  get: function() {
-    return this.getCurrentViewportSize()[0];
-  },
-  set: function(v) {
-    var pos = this.getCurrentViewportSize();
-    this.setViewportSize(v, pos[1]);
-  }
-});
-
-Object.defineProperty(dali.RenderTask.prototype, "height", {
-  enumerable: true,
-  configurable: false,
-  get: function() {
-    return this.getCurrentViewportSize()[1];
-  },
-  set: function(v) {
-    var pos = this.getCurrentViewportSize();
-    this.setViewportSize(pos[0], v);
-  }
-});
-
-//------------------------------------------------------------------------------
-//
-// Solid Actor Module
-//
-//------------------------------------------------------------------------------
-
-/**
- * Create a solid color actor
- * @method createSolidColorActor
- * @param {array} color The color
- * @param {bool} border Whether to add a border
- * @param {array} color The border color
- * @param {float} borderSize The size of a border
- * @return {Dali.Actor} The Dali actor
- */
-dali.createSolidColorActor = function(color, border, borderColor, borderSize) {
-  "use strict";
-  var a = dali.__createSolidColorActor(color, border, borderColor, borderSize);
-  dali.internalSetupProperties(a);
-  return a;
-};
-
-//------------------------------------------------------------------------------
-//
-// Mesh import support Module
-//
-//------------------------------------------------------------------------------
-function ObjectLoader(fileObject) {
-  "use strict";
-  // cached
-  this.self = this;
-  this.meshByUUID = {};
-  this.geomByUUID = {};
-  this.matByUUID = {};
-
-  this.fileObject = fileObject;
-}
-
-function __longToArray(v) {
-  "use strict";
-  return [((v >> 24) & 0xFF) / 255.0, ((v >> 16) & 0xFF) / 255.0, ((v >> 8) & 0xFF) / 255.0, (v & 0xFF) / 255.0];
-}
-
-function __isBitSet(value, bit) {
-  "use strict";
-  return (value & (1 << bit));
-}
-
-ObjectLoader.prototype.__getMaterial = function(uuid) {
-  "use strict";
-  if (!(uuid in this.matByUUID)) {
-    for (var i = 0, len = this.fileObject.materials.length; i < len; i++) {
-      var f_mat = this.fileObject["materials"][i];
-      skewer.log(i + ":" + f_mat["uuid"] + " " + (f_mat["uuid"] === uuid));
-      if (f_mat["uuid"] === uuid) {
-        assert(f_mat["type"] === "MeshPhongMaterial");
-        var mat = new dali.MaterialWrapper(uuid);
-        mat.setDiffuseColor(__longToArray(f_mat["color"]));
-        mat.setAmbientColor(__longToArray(f_mat["ambient"]));
-        mat.setSpecularColor(__longToArray(f_mat["specular"]));
-        mat.setEmissiveColor(__longToArray(f_mat["emmissive"]));
-        mat.setShininess(f_mat["shininess"]);
-        this.matByUUID[uuid] = mat;
-        break;
-      }
-    }
-  }
-  return this.matByUUID[uuid];
-};
-
-ObjectLoader.prototype.__getMeshData = function(uuid, uuid_material) {
-  "use strict";
-  if (!(uuid in this.meshByUUID)) {
-    for (var i = 0, len = this.fileObject["geometries"].length; i < len; i++) {
-      var f_geom = this.fileObject["geometries"][i];
-      if (f_geom["uuid"] === uuid) {
-        var f_indices, // file data
-            f_posns,
-            f_norms,
-            f_uvs,
-            f_faces;
-
-        if (!("metadata" in f_geom)) {
-          f_geom["metadata"] = {
-            "type": ""
-          }; // Warning: modified input!?
-        }
-
-        if ("formatVersion" in f_geom["metadata"]) // then version 3.1
-        {
-          f_indices = f_geom["indices"];
-          f_posns = f_geom["vertices"];
-          f_norms = f_geom["normals"];
-          f_uvs = f_geom["uvs"];
-          f_faces = f_geom["faces"];
-        } else if (f_geom["type"] === "Geometry") // V4 clara io output? not standard???
-        {
-          f_indices = f_geom["data"]["indices"];
-          f_posns = f_geom["data"]["vertices"];
-          f_norms = f_geom["data"]["normals"];
-          f_uvs = f_geom["data"]["uvs"];
-          f_faces = f_geom["data"]["faces"];
-        } else if (f_geom["metadata"]["type"] === "Geometry") // V4
-        {
-          f_indices = f_geom["indices"];
-          f_posns = f_geom["vertices"];
-          f_norms = f_geom["normals"];
-          f_uvs = f_geom["uvs"];
-          f_faces = f_geom["faces"];
-        } else if (f_geom["metadata"]["type"] === "BufferGeometry") // V4
-        {
-          f_posns = f_geom["data"]["attributes"]["position"]["array"];
-          f_norms = f_geom["data"]["attributes"]["norms"]["array"];
-          f_uvs = f_geom["data"]["attributes"]["uv"]["array"];
-        }
-
-        var nUvLayers = 0;
-
-        // disregard empty arrays
-        for (var i = 0; i < this.fileObject.uvs.length; i++) {
-          if (this.fileObject.uvs[i].length)
-            nUvLayers++;
-        }
-
-        var verts = new dali.VectorVertex();
-        var vert = []; //new dali.Vertex();
-        for (var i = 0, len = f_posns.length / 3; i < len; i++) {
-          vert.push(f_posns[(i * 3) + 0]);
-          vert.push(f_posns[(i * 3) + 1]);
-          vert.push(f_posns[(i * 3) + 2]);
-
-          vert.push(0); // norm
-          vert.push(0);
-          vert.push(0);
-
-          vert.push(0); // uvs
-          vert.push(0);
-
-          verts.push_back(vert);
-        }
-
-        var mesh = new dali.MeshDataWrapper();
-        var faces = new dali.VectorFaceIndex();
-        var faceSets = {};
-        //faceSets.length = this.fileObject.materials;
-        for (var i = 0, len = this.fileObject.materials.length; i < len; ++i) {
-          // get materials and force them to be loaded up
-          var mat = this.__getMaterial(this.fileObject.materials[i]["uuid"]);
-        }
-
-        var idx = 0;
-        var idx_len = f_faces.length;
-        var materialUUID = undefined;
-        while (idx < idx_len) {
-          var f_type = f_faces[idx++];
-          var isQuad = __isBitSet(f_type, 0);
-          var hasMaterial = __isBitSet(f_type, 1);
-          var hasFaceUv = __isBitSet(f_type, 2);
-          var hasFaceVertexUv = __isBitSet(f_type, 3);
-          var hasFaceNormal = __isBitSet(f_type, 4);
-          var hasFaceVertexNormal = __isBitSet(f_type, 5);
-          var hasFaceColor = __isBitSet(f_type, 6);
-          var hasFaceVertexColor = __isBitSet(f_type, 7);
-
-          var nVertices = 3;
-          var faceVertexIndices;
-          if (isQuad) {
-            faces.push_back(f_faces[idx]);
-            faces.push_back(f_faces[idx + 1]);
-            faces.push_back(f_faces[idx + 2]);
-
-            faces.push_back(f_faces[idx]);
-            faces.push_back(f_faces[idx + 2]);
-            faces.push_back(f_faces[idx + 3]);
-
-            faceVertexIndices = [f_faces[idx],
-                                 f_faces[idx + 1],
-                                 f_faces[idx + 2]
-                                ];
-
-            idx += 4;
-            nVertices = 4;
-          } else {
-            faces.push_back(f_faces[idx]);
-            faces.push_back(f_faces[idx + 1]);
-            faces.push_back(f_faces[idx + 2]);
-
-            faceVertexIndices = [f_faces[idx],
-                                 f_faces[idx + 1],
-                                 f_faces[idx + 2]
-                                ];
-
-            idx += 3;
-          }
-
-          if (hasMaterial) {
-            if (materialUUID === undefined) {
-              materialUUID = this.fileObject.materials[f_faces[idx]]["uuid"];
-            } else {
-              // different material per face is bonkers - I'm not going to support it.
-              if (this.fileObject.materials[f_faces[idx]]["uuid"] !== materialUUID) {
-                throw "Faces with different materials is not supported";
-              }
-            }
-            idx++;
-          }
-
-
-          if (hasFaceUv) {
-            for (var i = 0; i < nUvLayers; i++) {
-              var uvLayer = self.fileObject.uvs[i];
-              var uvIndex = f_faces[idx++];
-              var u = uvLayer[uvIndex * 2];
-              var v = uvLayer[uvIndex * 2 + 1];
-              // discarded - tbd ?
-            }
-          }
-
-          if (hasFaceVertexUv) {
-            for (var i = 0; i < nUvLayers; i++) {
-              var uvLayer = f_geom.uvs[i];
-              var uvs = [];
-              for (var j = 0; j < nVertices; j++) {
-                var uvIndex = f_faces[idx++];
-                var u = uvLayer[uvIndex * 2];
-                var v = uvLayer[uvIndex * 2 + 1];
-                // discarded- tbd ?
-              }
-            }
-          }
-
-          if (hasFaceNormal) {
-            var normalIndex = f_faces[idx++] * 3;
-
-            var x = f_geom.normals[normalIndex++];
-            var y = f_geom.normals[normalIndex++];
-            var z = f_geom.normals[normalIndex];
-
-            for (var i = 0; i < faceVertexIndices.length; i++) {
-              var v = vert.get(faceVertexIndices[i]);
-
-              v[4] += x;
-              v[5] += y;
-              v[6] += z;
-            }
-          }
-
-          if (hasFaceVertexNormal) {
-            for (var i = 0; i < nVertices; i++) {
-              var normalIndex = faces[idx] * 3;
-              var x = f_geom.normals[normalIndex++];
-              var y = f_geom.normals[normalIndex++];
-              var z = f_geom.normals[normalIndex];
-
-              var v = vert.get(faces[idx]);
-
-              v[4] += x;
-              v[5] += y;
-              v[6] += z;
-
-              idx += 1;
-              // face.vertexNormals.push( normal );
-            }
-          }
-
-          if (hasFaceColor) {
-            var color = f_faces[idx++];
-          }
-
-          if (hasFaceVertexColor) {
-            for (var i = 0; i < nVertices; i++) {
-              var colorIndex = faces[idx++];
-              var color = f_geom.colors[colorIndex]; // ??? f_geom.colors?
-              // face.vertexColors.push( color );
-            }
-          }
-
-          var faces = null;
-          if (f_faces) {
-            for (var i = 1, len = f_faces.length; i < len; i++) {
-              faces.push_back(f_faces[i]);
-            }
-          }
-
-          if (f_indices) {
-            faces = new dali.VectorFaceIndex();
-            for (var i = 1, len = f_indices.length; i < len; i++) {
-              faces.push_back(f_indices[i]);
-            }
-          }
-
-          if (!faces) {
-            faces = [];
-            for (var i = 0, len = f_posns.length; i < len; i++) {
-              faces.push(i);
-            }
-          }
-
-          console.log(verts.size() + ":" + faces.size() + ":" + uuid_material);
-
-          var material = this.__getMaterial(uuid_material);
-          mesh.setLineData(verts, faces, material);
-        }
-
-        this.meshByUUID[uuid] = mesh;
-        verts.delete();
-        faces.delete();
-        break;
-      } // if uuid found
-    } // for geom in geometries
-  } // if uid ! in meshByUUID
-
-  return this.meshByUUID[uuid];
-};
-
-ObjectLoader.prototype.delete = function() {
-  "use strict";
-  for (var a in this.meshByUUID) {
-    a.delete();
-  }
-  this.meshByUUID = {};
-  for (var b in this.matByUUID) {
-    b.delete();
-  }
-  this.matByUUID = {};
-};
-
-ObjectLoader.prototype.createMeshActors = function() {
-  "use strict";
-  var ret = [];
-  if ("object" in this.fileObject) {
-    for (var i = 0, len = this.fileObject["object"]["children"].length; i < len; i++) {
-      var child = this.fileObject["children"];
-      if (child["type"] === "Mesh") {
-        var meshData = this.__getMeshData(child["geometry"],
-                                          child["material"]);
-        ret.push(dali.__createMeshActor(meshData));
-        meshData.delete();
-      }
-    }
-  }
-
-  var parent;
-
-  if (ret) {
-    parent = new dali.Actor();
-    for (var a in ret) {
-      parent.add(a);
-      a.delete();
-    }
-  }
-
-  return parent;
-};
-
-dali.createMeshActor = function(threeDjs_formatV4) {
-  "use strict";
-  var loader = new ObjectLoader(threeDjs_formatV4);
-  return loader.createMeshActor();
-};
-
-
-
-//------------------------------------------------------------------------------
-//
-// Hit test
-//
-//------------------------------------------------------------------------------
-dali.hitTest = function(x, y) {
-  "use strict";
-  var a = dali.__hitTest(x, y);
-  if (a.ok()) {
-    dali.internalSetupProperties(a);
-    return a;
-  } else {
-    return null;
-  }
-};
-
-
-//------------------------------------------------------------------------------
-//
-// Shader support
-//
-//------------------------------------------------------------------------------
-
-/**
- * ShaderInfo class to get shader metadata.
- */
-dali.ShaderInfo = function() {
-  "use strict";
-};
-
-// supported uniforms
-dali.ShaderInfo.prototype._supportedUniformTypes = ["bool",
-                                                    "int",
-                                                    "float",
-                                                    "vec2", "vec3", "vec4",
-                                                    "bvec2", "bvec3", "bvec4",
-                                                    "ivec2", "ivec3", "ivec4",
-                                                    "mat2", "mat3", "mat4",
-                                                    "sampler2D",
-                                                    "samplerCube"
-                                                   ];
-
-// need to add a value to uniform registration call
-dali.ShaderInfo.prototype._supportedUniformValues = [0,
-                                                     0,
-                                                     0.0,
-                                                     [0.0, 0.0], [0.0, 0.0, 0.0], [0.0, 0.0, 0.0, 0.0],
-                                                     [0, 0], [0, 0, 0], [0, 0, 0, 0],
-                                                     [0, 0], [0, 0, 0], [0, 0, 0, 0],
-                                                     [1.0, 0.0,
-                                                      0.0, 1.0
-                                                     ],
-                                                     [1.0, 0.0, 0.0,
-                                                      0.0, 1.0, 0.0,
-                                                      0.0, 0.0, 1.0
-                                                     ],
-                                                     [1.0, 0.0, 0.0, 0.0,
-                                                      0.0, 1.0, 0.0, 0.0,
-                                                      0.0, 0.0, 1.0, 0.0,
-                                                      0.0, 0.0, 0.0, 1.0
-                                                     ]
-                                                    ];
-
-
-/**
- * Get shader metadata from compilation.
- *
- * Compiles the shader. On error set 'hasError' and error strings. On Success
- * query gl for the attributes and uniforms in the shaders.
- *
- * @param {object} gl ie from canvas.getContext("webgl")
- * @param {string} vertex shader
- * @param {string} fragment shader
- * @return {Object} shader metadata (see 'var info' below)
- */
-dali.ShaderInfo.prototype.fromCompilation = function(gl, vertex, fragment) {
-  "use strict";
-  var i;
-  var info = {
-    vertex: vertex,     // vertex source code
-    fragment: fragment, // fragment source code
-    attributes: {},     // {aName1: {name:"aName1", ... }
-    uniforms: {},       // {uName1: {name:"uName1", type:"vec2", ...}
-    uniformUISpec: {},  // {uName1: {ui:"slider", min:0, max:1, ...}
-    attributeCount: 0,  // Number of attributes
-    uniformCount: 0,    // Number of uniforms
-    hasError: false,    // compiles without error
-    vertexError: "",    // Vertex compilation error
-    fragmentError: "",  // Fragment compilation error
-    linkError: ""       // Linker error
-  };
-
-  var vertexShader = gl.createShader(gl.VERTEX_SHADER);
-  gl.shaderSource(vertexShader, vertex);
-  gl.compileShader(vertexShader);
-
-  // Check the compile status, return an error if failed
-  if (!gl.getShaderParameter(vertexShader, gl.COMPILE_STATUS)) {
-    info.hasError = true;
-    info.vertexError = gl.getShaderInfoLog(vertexShader);
-  }
-
-  var fragmentShader = gl.createShader(gl.FRAGMENT_SHADER);
-  gl.shaderSource(fragmentShader, fragment);
-  gl.compileShader(fragmentShader);
-
-  // Check the compile status, return an error if failed
-  if (!gl.getShaderParameter(fragmentShader, gl.COMPILE_STATUS)) {
-    info.hasError = true;
-    info.fragmentError = gl.getShaderInfoLog(fragmentShader);
-  }
-
-  if(info.hasError) {
-    gl.deleteShader(vertexShader);
-    gl.deleteShader(fragmentShader);
-    return info; // ==> out
-  } else {
-    var program = gl.createProgram();
-    gl.attachShader(program, vertexShader);
-    gl.attachShader(program, fragmentShader);
-
-    gl.linkProgram(program);
-
-    if(!gl.getProgramParameter(program, gl.LINK_STATUS)) {
-      info.hasError = true;
-      info.linkError = gl.getProgramInfoLog(program);
-      gl.deleteProgram(program);
-      gl.deleteShader(vertexShader);
-      gl.deleteShader(fragmentShader);
-      return info; // ==> out
-    }
-  }
-
-  var activeUniforms = gl.getProgramParameter(program, gl.ACTIVE_UNIFORMS);
-  var activeAttributes = gl.getProgramParameter(program, gl.ACTIVE_ATTRIBUTES);
-
-  // Taken from the WebGl spec:
-  // http://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14
-  var enums = {
-    0x8B50: "FLOAT_VEC2",
-    0x8B51: "FLOAT_VEC3",
-    0x8B52: "FLOAT_VEC4",
-    0x8B53: "INT_VEC2",
-    0x8B54: "INT_VEC3",
-    0x8B55: "INT_VEC4",
-    0x8B56: "BOOL",
-    0x8B57: "BOOL_VEC2",
-    0x8B58: "BOOL_VEC3",
-    0x8B59: "BOOL_VEC4",
-    0x8B5A: "FLOAT_MAT2",
-    0x8B5B: "FLOAT_MAT3",
-    0x8B5C: "FLOAT_MAT4",
-    0x8B5E: "SAMPLER_2D",
-    0x8B60: "SAMPLER_CUBE",
-    0x1400: "BYTE",
-    0x1401: "UNSIGNED_BYTE",
-    0x1402: "SHORT",
-    0x1403: "UNSIGNED_SHORT",
-    0x1404: "INT",
-    0x1405: "UNSIGNED_INT",
-    0x1406: "FLOAT"
-  };
-
-  // Loop through active uniforms
-  for (i = 0; i < activeUniforms; i++) {
-    var uniform = gl.getActiveUniform(program, i);
-    info.uniforms[uniform.name] = {name: uniform.name,
-                                   type: uniform.type,
-                                   typeName: enums[uniform.type],
-                                   size: uniform.size};
-    info.uniformCount += uniform.size;
-  }
-
-  // Loop through active attributes
-  for (i = 0; i < activeAttributes; i++) {
-    var attribute = gl.getActiveAttrib(program, i);
-    info.attributes[attribute.name] = {name: attribute.name,
-                                       type: attribute.type,
-                                       typeName: enums[attribute.type],
-                                       size: attribute.size};
-    info.attributeCount += attribute.size;
-  }
-
-  // uniformUISpec
-  this._addUniformMetaData(vertex, info);
-  this._addUniformMetaData(fragment, info);
-
-  return info;
-};
-
-/*
- * add unform metadata from shader source comments
- *  ie return as an object the comment following a uniform
- *     uniform float uAlpha; // {"min":0, "max":1}
- */
-/** private */
-dali.ShaderInfo.prototype._addUniformMetaData = function(src, metadata) {
-  "use strict";
-  // Loop through active uniforms
-  for(var name in metadata.uniforms) {
-    var reguniform = new RegExp(name + "[^;]*;(.*)");
-
-    var tmp = reguniform.exec(src);
-    if(tmp && tmp[1]) {
-      var meta;
-      var uComments = tmp[1].trim();
-      if(uComments.startsWith("//")) { // meta data in comments
-        try {
-          meta = eval("(" + uComments.substr(2) + ")"); // brackets to be expression not opening statement
-          if(typeof meta !== typeof ({})) {
-            throw ("Uniform UI Spec in comments must be an object");
-          }
-        } catch (e) {
-          meta = {};
-        }
-      } else {
-        meta = {};
-      }
-      metadata.uniformUISpec[name] = meta;
-    }
-  }
-};
-
-/**
- * Get shader metadata from regex search.
- *
- * Attempts a regex search to get the shader meta data.
- * Use fromCompilation() instead of this function wherever compilation is
- * possible as this approach will never work for all shaders.
- * Does no compilation or error checking but retains fields for
- * compatibility with .fromCompilation(...)
- * May return an error if the regex fails.
- *
- * @param {string} vertex shader
- * @param {string} fragment shader
- * @return  {Object} shader metadata (see 'var info' below)
- */
-dali.ShaderInfo.prototype.fromRegEx = function(vertex, fragment) {
-  "use strict";
-  var info = {          // similar to this.fromCompilation()
-    vertex: vertex,     // source code
-    fragment: fragment,
-    attributes: {},     // {aName1: {name:"aName1", ... }
-    uniforms: {},       // {uName1: {name:"uName1", type:"vec2", ...}
-    attributeCount: 0,
-    uniformCount: 0,
-    uniformUISpec: {},  // {uName1: {ui:"slider", min:0, max:1, ...}
-    hasError: false,    // compiles without error
-    vertexError: "",
-    fragmentError: "",
-    linkError: ""
-  };
-
-  var metaVertex;
-  try {
-    metaVertex = this._getRegExMetaData(vertex);
-  } catch(e) {
-    info.hasError = true;
-    info.vertexError = e.message;
-    return info;
-  }
-
-  var metaFragment;
-  try {
-    metaFragment = this._getRegExMetaData(fragment);
-  } catch(e) {
-    info.hasError = true;
-    info.fragmentError = e.message;
-    return info;
-  }
-
-  var name;
-
-  // merge
-  info.uniforms = metaVertex.uniformMetaData;
-  info.uniformUISpec = metaVertex.uniformUISpec;
-
-  for(name in metaFragment.uniformMetaData) {
-    if( name in info.uniforms ) {
-      info.uniforms[name] = dali.mergeObjects(info.uniforms[name], metaVertex.uniformMetaData);
-    } else {
-      info.uniforms[name] = metaFragment.uniformMetaData[name];
-    }
-    if( name in info.uniformUISpec ) {
-      info.uniformUISpec[name] = dali.mergeObjects(info.uniformUISpec[name], metaVertex.uniformUISpec);
-    } else {
-      info.uniformUISpec[name] = metaFragment.uniformUISpec[name];
-    }
-  }
-
-  info.attributes = metaVertex.attributeMetaData;
-  for(name in metaFragment.attributeMetaData) {
-    if( name in metaVertex.attributeMetaData ) {
-      info.attributes[name] = dali.mergeObjects(info.attributes[name], metaVertex.attributeMetaData);
-    } else {
-      info.attributes[name] = metaFragment.attributeMetaData[name];
-    }
-  }
-
-  return info;
-};
-
-/*
- * Returns a string with all comments removed
- */
-/** private */
-dali.ShaderInfo.prototype._removeComments = function(str) {
-  "use strict";
-  var uid = "_" + new Date(),
-      primatives = [],
-      primIndex = 0;
-
-  return (
-    str
-    /* Remove strings */
-      .replace(/(['"])(\\\1|.)+?\1/g, function(match){
-        primatives[primIndex] = match;
-        return (uid + "") + primIndex++;
-      })
-
-    /* Remove Regexes */
-      .replace(/([^\/])(\/(?!\*|\/)(\\\/|.)+?\/[gim]{0,3})/g, function(match, $1, $2){
-        primatives[primIndex] = $2;
-        return $1 + (uid + "") + primIndex++;
-      })
-
-    /*
-     - Remove single-line comments that contain would-be multi-line delimiters
-     E.g. // Comment /* <--
-     - Remove multi-line comments that contain would be single-line delimiters
-     E.g. /* // <--
-     */
-      .replace(/\/\/.*?\/?\*.+?(?=\n|\r|$)|\/\*[\s\S]*?\/\/[\s\S]*?\*\//g, "")
-
-    /*
-     Remove single and multi-line comments,
-     no consideration of inner-contents
-     */
-      .replace(/\/\/.+?(?=\n|\r|$)|\/\*[\s\S]+?\*\//g, "")
-
-    /*
-     Remove multi-line comments that have a replace ending (string/regex)
-     Greedy, so no inner strings/regexes will stop it.
-     */
-      .replace(RegExp("\\/\\*[\\s\\S]+" + uid + "\\d+", "g"), "")
-
-    /* Bring back strings & regexes */
-      .replace(RegExp(uid + "(\\d+)", "g"), function(match, n){
-        return primatives[n];
-      })
-  );
-};
-
-/*
- * Returns true if value is in the array
- */
-/** private */
-dali.ShaderInfo.prototype._contains = function(array, value) {
-  "use strict";
-  for(var i = 0; i < array.length; i++) {
-    if(array[i] === value) {
-      return true;
-    }
-  }
-  // else
-  return false;
-};
-
-/*
- * Get the src meta data for unforms and attributes armed only with a regexp
- */
-/** private */
-dali.ShaderInfo.prototype._getRegExMetaData = function(src) {
-  "use strict";
-  var ret = {"uniforms": [],         // ["uName1", ["uName2"]
-             "uniformMetaData": {},  // {uName1: {type:"vec3,...}
-             "uniformUISpec": {},    // {ui:"slider", min:..., max:...}
-             "attributes": [],       // ["aName2"]
-             "attributeMetaData": {} // ["aName2"]
-            };
-
-  // Undoubtedly this approach will be wrong. Hopefully on not too many corner cases...
-  // A better way is to compile the source see (fromCompilation())
-  // but that requres a gl context.
-  var tmp;
-
-  var definesOut = /#define[ \t]+([A-Za-z_0-9]*)[ \t]+(.*)/g;
-
-  var reg = /[ \t]?uniform[ ]*((?:lowp|mediump|highp)?[ \t]*(bool|int|uint|float|[biu]?vec[234]|mat[234]x?[234]?|[^ ]*)[ \t]*([A-Za-z0-9]*))[ \t]*(;|\[.*\][ \t]*;)(.*)/gi;
-
-  var regAttrib = /[ \t]?attribute[ ]*((?:lowp|mediump|highp)?[ \t]*(bool|int|uint|float|[biu]?vec[234]|mat[234]x?[234]?|[^ ]*)[ \t]*([A-Za-z0-9]*))[ \t]*(;|\[.*\][ \t]*;)(.*)/gi;
-
-  // 1. no commented out uniforms
-  var noCommentSource = this._removeComments(src);
-
-  var validUniforms = [];
-  while ((tmp = reg.exec(noCommentSource))) {
-    validUniforms.push( tmp[3] );
-  }
-
-  while ((tmp = regAttrib.exec(noCommentSource))) {
-    ret.attributes.push( tmp[3] );
-    ret.attributeMetaData[ tmp[3] ] = {name: tmp[3], type: tmp[2] };
-  }
-
-  // 2. replace defines
-  var defines = [];
-  while ((tmp = definesOut.exec(noCommentSource))) {
-    defines.push([tmp[1], tmp[2]]);
-  }
-  var defineDict = {};
-  var defineList = [];
-  while(defines.length) {
-    var p = defines.pop();
-    var n = p[0];
-    var v = p[1];
-    try {
-      defineDict[n] = eval(v);
-      defineList.push([n, defineDict[n]]);
-    } catch(e) {
-      var d = /([A-Za-z]+[A-Za-z0-9]*)/g;
-      while ((tmp = d.exec(v))) {
-        if(tmp[0] in defineDict) {
-          v = v.replace(tmp[0], defineDict[tmp[0]]);
-        } else {
-          defines.push(p); // stick it back to try again. ...and endless loop if we can't(!)
-        }
-      }
-    }
-  }
-
-  for(var i = 0; i < defineList.length; i++) {
-    var re = new RegExp(defineList[i][0], "g");
-    src = src.replace(re, defineList[i][1]);
-  }
-
-  // 3. get uniforms
-  while ((tmp = reg.exec(src))) {
-    if(!this._contains(validUniforms, tmp[3])) {
-      continue;
-    }
-    var uType = tmp[2];
-    var uName = tmp[3];
-    var uArray = tmp[4].slice(0, -1);
-    var uComments = tmp[5].trim();
-    var meta;
-    var uiSpecMeta = null;
-    if(uComments.startsWith("//")) { // meta data in comments
-      uiSpecMeta = eval("(" + uComments.substr(2) + ")"); // brackets to be expression not opening statement
-      if(typeof uiSpecMeta !== typeof ({})) {
-        throw ("Uniform UI Spec in comments must be an object");
-      }
-    }
-
-    if(uiSpecMeta) {
-      uiSpecMeta.name = tmp[3];
-      ret.uniformUISpec[uName] = uiSpecMeta;
-    }
-
-    meta = {};
-    meta.type = tmp[2];
-    meta.name = tmp[3];
-    meta.count = 0;
-
-    var name;
-    if(uArray.search("[[]") >= 0) { // an array
-      meta.count = Number(uArray.slice(1, -1));
-    }
-
-    if(this._contains( this._supportedUniformTypes, uType) ) {
-      if(meta.count !== 0) { // array
-        for(var j = 0; j < meta.count; j++) {
-          ret.uniforms.push( meta.name );
-          ret.uniformMetaData[ meta.name ] = {type: meta.type,
-                                              name: meta.name + "[" + j + "]",
-                                              index: j,
-                                              count: meta.count};
-        }
-      } else {
-        ret.uniforms.push( meta.name );
-        ret.uniformMetaData[ meta.name ] = {type: meta.type,
-                                            name: meta.name,
-                                            index: 0,
-                                            count: 0};
-      }
-    } else {
-      // not a base type so need to get the compound type
-      var structFind = new RegExp( "(struct[ \t\n]*" + uType + "[^{]*{)([^}]*)", "g");
-      var structLines = structFind.exec(src)[2].split(";");
-      var structUniforms = [];
-      var tmpStruct;
-      var k;
-      for(var lineNo = 0; lineNo < structLines.length; lineNo++) {
-        var line = structLines[lineNo].replace(/\n/g, "") + ";";
-        if(line !== ";") {
-          var structReg = /[ \t\n]*((?:lowp|mediump|highp)?[ \t\n]*(bool|int|uint|float|[biu]?vec[234]|mat[234]x?[234]?|[^ ]*)[ \t\n]*([A-Za-z0-9]*))[ \t\n]*(;|\[.*\][ \t\n]*;)/gi;
-          while ((tmpStruct = structReg.exec(line))) {
-            structUniforms.push( { type: tmpStruct[2],
-                                   name: tmpStruct[3],
-                                   count: meta.count } );
-          }
-        }
-      }
-      if(meta.count === 0) {
-        for(k = 0; k < structUniforms.length; k++) {
-          name = uName + "." + structUniforms[k].name;
-          ret.uniforms.push( name );
-          ret.uniformMetaData[ name ] = {type: structUniforms[k].type,
-                                         name: name,
-                                         count: meta.count,
-                                         index: 0,
-                                         structType: meta.type,
-                                         structName: meta.name};
-        }
-      } else { // array
-        for(var l = 0; l < meta.count; l++) {
-          for(k = 0; k < structUniforms.length; k++) {
-            name = uName + "[" + l + "]" + "." + structUniforms[k].name;
-            ret.uniforms.push( name );
-            ret.uniformMetaData[ name ] = {type: structUniforms[k].type,
-                                           name: name,
-                                           count: meta.count,
-                                           index: l,
-                                           structType: meta.type,
-                                           structName: meta.name};
-          }
-        }
-      }
-    }
-  }
-
-  return ret;
-};
-
-//------------------------------------------------------------------------------
-//
-// Debug Module
-//
-//------------------------------------------------------------------------------
-dali.Debug = function() {
-  "use strict";
-};
-
-dali.Debug.prototype.printTypeProperties = function(typeName) {
-  "use strict";
-  var t = new dali.TypeRegistry();
-  var info = t.getTypeInfo(typeName);
-  var props = info.getProperties();
-  for (var i = 0; i < props.size(); i++) {
-    console.log(i + ":" + props.get(i));
-  }
-  info.delete(); // wrapper
-  t.delete(); // wrapper
-};
-
-dali.Debug.prototype.printProperties = function(o) {
-  "use strict";
-  var props = o.getProperties();
-
-  var len = props.size();
-  for(var i = 0; i < len; i++) {
-    var name = props.get(i);
-    var type = o.getPropertyTypeName(name);
-    if(type !== "NONE") {
-      console.log(i + ":" + name + " " + type);
-    } else {
-      type = o.getPropertyTypeName(name);
-      console.log(i + ":" + name + " " + type + " (Not mangled)");
-    }
-  }
-  props.delete(); // wrapper
-};
-
-dali.Debug.prototype.printTypes = function() {
-  "use strict";
-
-  var t = new dali.TypeRegistry();
-  for (var i = 0; i < t.getTypeNameCount(); i++) {
-    console.log(t.getTypeName(i));
-  }
-  t.delete(); // wrapper
-};
-
-
-dali._debugPrintParents = function(actor, list) {
-  "use strict";
-  var p = null;
-
-  if (!actor.ok()) {
-    return;
-  }
-
-  try {
-    p = actor.getParent();
-    if (!p.ok()){
-      p = null;
-    }
-  } catch (e) {
-    // console.log("Cannot get parent", e);
-  }
-
-  if (p) {
-    list.push(p);
-    dali._debugPrintParents(p, list);
-  }
-};
-
-dali.Debug.prototype.printTree = function(actor) {
-  "use strict";
-  var l = [];
-  dali._debugPrintParents(actor, l);
-  var a;
-  var ti;
-  console.log("---");
-  for (var i = l.length - 1; i >= 0; i--) {
-    a = l[i];
-    ti = a.getTypeInfo();
-    console.log("|", Array(l.length - i).join("-"), ti.getName(), "P", a.position, "R", a.orientation, a.name);
-    ti.delete();
-  }
-  ti = actor.getTypeInfo();
-  console.log("*", Array(l.length + 1).join("*"), ti.getName(), "P", actor.position, "R", actor.orientation, actor.name);
-  ti.delete();
-
-  var children = actor.getChildren();
-  for (var j = 0; j < children.length; j++) {
-    a = children[j];
-    ti = a.getTypeInfo();
-    console.log("|", Array(l.length + 1 + 1 + j).join("-"), ti.getName(), "P", a.position, "R", a.orientation, a.name);
-    ti.delete();
-  }
-};
-
-dali.Debug.prototype.printRenderTask = function(rendertask) {
-  "use strict";
-  console.log("[X,Y]", rendertask.getCurrentViewportPosition());
-  console.log("[W,H]", rendertask.getCurrentViewportSize());
-
-  var c = rendertask.getCameraActor();
-  if (!c.ok()) {
-    console.log("No Camera");
-  } else {
-    console.log("Camera Pos:", c.position);
-    console.log("Camera Rot:", c.orientation);
-    console.log("Camera Inherit:", c.inheritRotation);
-    console.log("Camera ParentOrigin:", c.parentOrigin);
-    console.log("Camera AnchorPoint:", c.anchorPoint);
-    var p = null;
-    try {
-      p = c.getParent();
-      if(!p.ok()) {
-        p = null;
-      }
-    } catch (e) {
-      console.log("Cannot get parent", e);
-    }
-
-    if (!p) {
-      console.log("Camera has no parent?");
-    } else {
-      var ti = p.getTypeInfo();
-      console.log("Parent Name", ti.getName());
-      ti.delete();
-      p.delete();
-    }
-  }
-};
-
-dali.Debug.prototype.printRenderTasks = function() {
-  "use strict";
-  var stage = dali.stage;
-  var taskList = stage.getRenderTaskList();
-  for (var i = 0; i < taskList.getTaskCount(); i++) {
-    var t = taskList.getTask(i);
-    console.log("RenderTask:", i);
-    this.printRenderTask(t);
-    t.delete(); // wrapper
-  }
-  taskList.delete(); // wrapper
-};
-
-dali.Debug.prototype.findFirstActor = function(actor, predicateFunction) {
-  "use strict";
-  for (var i = 0, len = actor.getChildCount(); i < len; i++) {
-    var a = actor.getChildAt(i);
-    var found = predicateFunction(a);
-    if (found) {
-      return a;
-    }
-    var child = this.findFirstActor(a, predicateFunction);
-    if (child) {
-      return child;
-    }
-    a.delete();
-  }
-  return null;
-};
-
-dali.Debug.prototype.depthVisit = function(actor, operation, dontDelete) {
-  "use strict";
-  for (var i = 0, len = actor.getChildCount(); i < len; i++) {
-    var a = actor.getChildAt(i);
-    var done = operation(a);
-    if (!done) {
-      return false;
-    }
-    if (!this.depthVisit(a, operation, dontDelete)) {
-      return false;
-    }
-    var doit = true;
-    if (dontDelete !== undefined) {
-      if (dontDelete) {
-        doit = false;
-      }
-    }
-    if (doit) {
-      a.delete();
-    }
-  }
-  return true;
-};
-
-dali.operationPrintProperty = function(property, all) {
-  "use strict";
-  return (function(actor) {
-    if (property in actor) {
-      dali.log(actor.getId() + "property:" + actor[property]);
-    } else {
-      dali.log(actor.getId() + "property:n/a");
-    }
-    return all;
-  });
-};
-
-dali.predicatePropertyEquals = function(property, value) {
-  "use strict";
-  return (function(actor) {
-    if (property in actor) {
-      if (actor[property] === value) {
-        return true;
-      }
-    }
-    return false;
-  });
-};
-
-dali.typeInheritsFrom = function(type, basename) {
-  var inherits = false;
-
-  var registry = new dali.TypeRegistry();
-
-  var base = registry.getTypeInfo( type.getBaseName() );
-
-  if(base.ok())
-  {
-    inherits = (base.getName() === basename);
-
-    while(!inherits)
-    {
-      base = registry.getTypeInfo( base.getBaseName() );
-      if(base.ok())
-      {
-        inherits = (base.getName() === basename);
-      }
-      else
-      {
-        break;
-      }
-    }
-  }
-
-  return inherits;
-};
-
-
-
-//------------------------------------------------------------------------------
-//
-// View Module
-//
-// Helper functions for creating front/top/left views with RenderTasks
-//
-//------------------------------------------------------------------------------
-
-/**
- * Sets the clear colour in a RenderTask
- * @method setClearColor
- * @param {int} renderTaskIndex
- * @param {array} color The rgba colour array
- */
-dali.setClearColor = function(renderTaskIndex, color) {
-  "use strict";
-  var stage = dali.stage;
-  var taskList = stage.getRenderTaskList();
-  if (renderTaskIndex >= taskList.getTaskCount()) {
-    console.log("RenderTaskIndex out of bounds:", renderTaskIndex);
-    taskList.delete(); // wrapper
-    return;
-  }
-  var rendertask = taskList.getTask(renderTaskIndex);
-  rendertask.setClearEnabled(true);
-  rendertask.setClearColor(color);
-};
-
-/**
- * Gets the clear colour of a RenderTask
- * @method setClearColor
- * @param {int} renderTaskIndex
- * @return {array} The rgba colour array
- */
-dali.getClearColor = function(renderTaskIndex) {
-  "use strict";
-  var stage = dali.stage;
-  var taskList = stage.getRenderTaskList();
-  if (renderTaskIndex >= taskList.getTaskCount()) {
-    console.log("RenderTaskIndex out of bounds:", renderTaskIndex);
-    taskList.delete(); // wrapper
-    return null;
-  }
-  var rendertask = taskList.getTask(renderTaskIndex);
-  return rendertask.getClearColor();
-};
-
-/**
- * Set a front view camera with viewport x,y,w,h
- * @method setFrontView
- * @param {int} renderTaskIndex
- * @param {int} x Viewport X
- * @param {int} y Viewport Y
- * @param {int} w Viewport W
- * @param {int} h Viewport H
- */
-dali.setFrontView = function(renderTaskIndex, x, y, w, h) {
-  "use strict";
-  var stage = dali.stage;
-  var taskList = stage.getRenderTaskList();
-  if (renderTaskIndex >= taskList.getTaskCount()) {
-    console.log("RenderTaskIndex out of bounds:", renderTaskIndex);
-    taskList.delete(); // wrapper
-    return;
-  }
-  var rendertask = taskList.getTask(renderTaskIndex);
-
-  var c = rendertask.getCameraActor();
-  assert(c.ok(), "Rendertask has no valid camera actor");
-
-  rendertask.setViewportPosition([x, y]);
-  rendertask.setViewportSize([w, h]);
-  c.position = [0, 0, 800];
-  c.orientation = [0, 1, 0, 180];
-  c.aspectRatio = w / h;
-
-  c.delete(); // wrapper
-  rendertask.delete(); // wrapper
-  taskList.delete(); // wrapper
-};
-
-/**
- * Set a top view camera with viewport x,y,w,h
- * @method setTopView
- * @param {int} renderTaskIndex
- * @param {int} x Viewport X
- * @param {int} y Viewport Y
- * @param {int} w Viewport W
- * @param {int} h Viewport H
- */
-dali.setTopView = function(renderTaskIndex, x, y, w, h) {
-  "use strict";
-  var stage = dali.stage;
-  var taskList = stage.getRenderTaskList();
-  if (renderTaskIndex >= taskList.getTaskCount()) {
-    console.log("RenderTaskIndex out of bounds:", renderTaskIndex);
-    taskList.delete(); // wrapper
-    return;
-  }
-  var rendertask = taskList.getTask(renderTaskIndex);
-
-  var c = rendertask.getCameraActor();
-  assert(c.ok(), "Rendertask has no valid camera actor");
-
-  rendertask.setViewportPosition([x, y]);
-  rendertask.setViewportSize([w, h]);
-
-  var q1 = dali.axisAngleToQuaternion([0, 1, 0, dali.radian(180)]); // yaw around to look at scene down -ve z
-  var q2 = dali.axisAngleToQuaternion([1, 0, 0, dali.radian(-90)]); // pitch to look at scene
-  var q = dali.quaternionToAxisAngle(dali.quatByQuat(q1, q2));
-
-  c.position = [0, -800, 0]; // @todo; get 800 from dali not hard coded here
-  c.orientation = [q[0], q[1], q[2], dali.degree(q[3])]; // @todo; should really all be in radians
-  c.aspectRatio = w / h;
-
-  c.delete(); // wrapper
-  rendertask.delete(); // wrapper
-  taskList.delete(); // wrapper
-};
-
-/**
- * Set a right view camera with viewport x,y,w,h
- * @method setRightView
- * @param {int} renderTaskIndex
- * @param {int} x Viewport X
- * @param {int} y Viewport Y
- * @param {int} w Viewport W
- * @param {int} h Viewport H
- */
-dali.setRightView = function(renderTaskIndex, x, y, w, h) {
-  "use strict";
-  var stage = dali.stage;
-  var taskList = stage.getRenderTaskList();
-  if (renderTaskIndex >= taskList.getTaskCount()) {
-    console.log("RenderTaskIndex out of bounds:", renderTaskIndex);
-    taskList.delete(); // wrapper
-    return;
-  }
-  var rendertask = taskList.getTask(renderTaskIndex);
-
-  var c = rendertask.getCameraActor();
-  assert(c.ok(), "Rendertask has no valid camera actor");
-
-  rendertask.setViewportPosition([x, y]);
-  rendertask.setViewportSize([w, h]);
-
-  var q1 = dali.axisAngleToQuaternion([0, 1, 0, dali.radian(180)]); // yaw around to look at scene down -ve z
-  var q2 = dali.axisAngleToQuaternion([0, 1, 0, dali.radian(90)]); // yaw again to look from right
-  var q = dali.quaternionToAxisAngle(dali.quatByQuat(q1, q2));
-
-  c.position = [800, 0, 0];
-  c.orientation = [q[0], q[1], q[2], dali.degree(q[3])]; // @todo; should really all be in radians
-  c.aspectRatio = w / h;
-
-  c.delete(); // wrapper
-  rendertask.delete(); // wrapper
-  taskList.delete(); // wrapper
-};
-
-/**
- * Remove all but one render task. Presumes RenderTasks are being use only for viewing windows.
- * @method onePane
- */
-dali.onePane = function() {
-  "use strict";
-  var stage = dali.stage;
-  var taskList = stage.getRenderTaskList();
-  var tasks = [];
-  var i, len;
-
-  for (i = 1, len = taskList.getTaskCount(); i < len; i++) {
-    tasks.push(taskList.getTask(i));
-  }
-
-  for (i = 0, len = tasks.length; i < len; i++) {
-    var task = tasks[i];
-    // delete the camera actors we created in twoPane and threePane
-    var c = task.getCameraActor();
-    if (c.ok()) {
-      var p = c.getParent();
-      if (p.ok()) {
-        p.remove(c);
-      }
-      p.delete(); // wrapper
-    }
-    c.delete(); // wrapper
-
-    taskList.removeTask(task);
-    task.delete(); // wrapper
-  }
-
-  taskList.delete();
-};
-
-/**
- * Creates render tasks and cameras for a two pane view.
- * Use setFrontView/Top/Right with 0-2 index to setup the actual views.
- * (in a separate function to allow window gutters)
- * @method twoPane
- */
-dali.twoPane = function() {
-  "use strict";
-  dali.onePane();
-
-  var stage = dali.stage;
-  var taskList = stage.getRenderTaskList();
-
-  var defaultTask = taskList.getTask(0);
-  var defaultCamera = defaultTask.getCameraActor();
-  var defaultCameraParent = defaultCamera.getParent();
-
-  var t;
-  t = taskList.createTask();
-
-  var c = new dali.CameraActor(); // add camera for different viewpoint
-  c.position = [0, 0, 800];
-  c.orientation = [0, 1, 0, 180];
-  c.parentOrigin = [0.5, 0.5, 0.5];
-  c.anchorPoint = [0.5, 0.5, 0.5];
-  t.setCameraActor(c);
-  defaultCameraParent.add(c);
-  c.delete(); // wrapper
-
-  t.delete(); // wrapper
-
-  defaultCameraParent.delete(); // wrapper
-  defaultCamera.delete(); // wrapper
-  defaultTask.delete(); // wrapper
-
-  taskList.delete(); // wrapper
-};
-
-/**
- * Creates render tasks and cameras for a three pane view.
- * Use setFrontView/Top/Right with 0-2 index to setup the actual views.
- * (in a separate function to allow window gutters)
- * @method threePane
- */
-dali.threePane = function() {
-  "use strict";
-  dali.onePane();
-
-  var stage = dali.stage;
-  var taskList = stage.getRenderTaskList();
-
-  var defaultTask = taskList.getTask(0);
-  var defaultCamera = defaultTask.getCameraActor();
-  var defaultCameraParent = defaultCamera.getParent();
-
-  var t;
-  t = taskList.createTask();
-
-  var c = new dali.CameraActor(); // add camera for different viewpoint
-  c.position = [0, 0, 800];
-  c.orientation = [0, 1, 0, 180];
-  c.parentOrigin = [0.5, 0.5, 0.5];
-  c.anchorPoint = [0.5, 0.5, 0.5];
-  t.setCameraActor(c);
-  defaultCameraParent.add(c);
-  c.delete(); // wrapper
-
-  t.delete(); // wrapper
-
-  t = taskList.createTask();
-
-  c = new dali.CameraActor(); // add camera for different viewpoint
-  c.position = [0, 0, 800];
-  c.orientation = [0, 1, 0, 180];
-  c.parentOrigin = [0.5, 0.5, 0.5];
-  c.anchorPoint = [0.5, 0.5, 0.5];
-  t.setCameraActor(c);
-  defaultCameraParent.add(c);
-  c.delete(); // wrapper
-
-  t.delete(); // wrapper
-
-  defaultCameraParent.delete(); // wrapper
-  defaultCamera.delete(); // wrapper
-  defaultTask.delete(); // wrapper
-
-  taskList.delete(); // wrapper
-};
-
-//------------------------------------------------------------------------------
-//
-// Dali Initialization Module
-//
-//------------------------------------------------------------------------------
-
-/**
- * Create a Dali object by type name
- * @method create
- * @param {string} name The type name to create
- * @return A Dali handle to the Dali object
- */
-dali.create = function(name) {
-  "use strict";
-
-  var handle = dali.__createActor(name);
-
-  if (!handle.ok()) {
-    handle.delete(); // handle
-    handle = dali.__createHandle(name);
-  }
-
-  dali.internalSetupProperties(handle);
-
-  return handle;
-};
-
-dali.updateFrame = function() {
-  dali.__updateOnce();
-  dali.__renderOnce();
-};
-
-/**
- * Creates constructors for objects found in the TypeRegistry. Some objects are
- * individually wrapped. Sets some global objects eg. debug/stage.
- */
-/** private */
-dali.init = function() {
-  "use strict";
-
-  console.log( dali.VersionString() );
-
-  dali.jsSignalHolder = new dali.SignalHolder(); // for js callbacks
-
-  dali.debug = new dali.Debug();
-
-  dali.stage = new dali.Stage();
-
-  dali.getStage = function() { // duplication of dali.stage to stop regressions
-    return dali.stage;
-  };
-
-  //
-  // Add constructor functions to dali from the type registry
-  //
-  // Uses separate create functions to add methods for the different base classes.
-  // Other generic access is by properties. Currently
-  //
-  //              +------------+
-  //              | BaseHandle |
-  //              +------+-----+
-  //                     |
-  //      |--------------+------------|
-  //      |              |            |
-  // +----+------+  +----+---+   +----+--+
-  // | Animation |  | Handle |   | Image |
-  // +-----------+  +--------+   +-------+
-  //
-
-  var t = new dali.TypeRegistry();
-
-  // use the emscripten wrapping for these and not the typeregisitry creation function
-  var useWrapping = { RenderTask: 1, RenderTaskList: 1, CameraActor: 1,
-                      TypeInfo: 1,
-                      Path: 1, Animation: 1,
-                      Handle: 1, Actor: 1,
-                      PropertyMap: 1, PropertyBuffer: 1,
-                      Image: 1, BufferImage: 1, EncodedBufferImage: 1,
-                      Geometry: 1, Material: 1, Shader: 1, Sampler: 1, Renderer: 1
-                    };
-
-  for (var i = 0; i < t.getTypeNameCount(); i++) {
-    // anon function because of closure with defineProperty
-    // (if just variable in loop then the variable 'address' is captured, not the value
-    //  so it becomes last value set)
-    (function(name) {
-      var createFunc;
-      var info = t.getTypeInfo(name);
-
-      if(dali.typeInheritsFrom(info, "Actor")) {
-        createFunc = dali.__createActor;
-      } else if(dali.typeInheritsFrom(info, "Handle")) {
-        createFunc = dali.__createHandle;
-      }
-
-      // @todo Dali error?? name lengths should never be zero
-      if (name.length && !(name in useWrapping) ) {
-        Object.defineProperty(dali, name, {
-          enumerable: true,
-          configurable: false,
-          get: function() {
-            return function() {
-              // console.log(name);
-              return dali.create(name);
-            };
-          }
-        });
-      }
-    })(t.getTypeName(i));
-  }
-
-  dali.updateFrame();
-
-}(); // call init
-
-
-//------------------------------------------------------------------------------
-//
-// Post run
-//
-// Call postDaliWrapperRun() to indicate dali-wrapper.js has loaded
-// and other sequential tasks can run (js files can load async)
-//
-//------------------------------------------------------------------------------
-if(Module)
-{
-  if (Module.postDaliWrapperRun) {
-    Module.postDaliWrapperRun();
-  }
-}
diff --git a/adaptors/emscripten/wrappers/emscripten-utils.cpp b/adaptors/emscripten/wrappers/emscripten-utils.cpp
deleted file mode 100644 (file)
index 7ba051c..0000000
+++ /dev/null
@@ -1,70 +0,0 @@
-/*
- * Copyright (c) 2015 Samsung Electronics Co., Ltd.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- */
-
-#include "emscripten-utils.h"
-
-// EXTERNAL INCLUDES
-
-
-// INTERNAL INCLUDES
-
-namespace Dali
-{
-namespace Internal
-{
-namespace Emscripten
-{
-
-Dali::Image CreateImageRGBA(unsigned int width, unsigned int height, const std::string& data)
-{
-  Dali::BufferImage b = Dali::BufferImage::New( width, height, Dali::Pixel::RGBA8888 );
-
-  const Dali::PixelBuffer* from = reinterpret_cast<const Dali::PixelBuffer*>( data.c_str() );
-  Dali::PixelBuffer* to = b.GetBuffer();
-
-  unsigned int len = std::max( width * height * 4, data.size() );
-  for(int i = 0; i < len; i++)
-  {
-    *to++ = *from++;
-  }
-  return b;
-}
-
-Dali::Image CreateImageRGB(unsigned int width, unsigned int height, const std::string& data)
-{
-  Dali::BufferImage b = Dali::BufferImage::New( width, height, Dali::Pixel::RGB888 );
-
-  const Dali::PixelBuffer* from = reinterpret_cast<const Dali::PixelBuffer*>( data.c_str() );
-  Dali::PixelBuffer* to = b.GetBuffer();
-
-  unsigned int len = std::max( width * height * 3, data.size() );
-  for(int i = 0; i < len; i++)
-  {
-    *to++ = *from++;
-  }
-  return b;
-}
-
-Dali::Image GetImage(const std::string& data)
-{
-  const uint8_t* const ptr = reinterpret_cast<const uint8_t * const>(data.c_str());
-  return Dali::EncodedBufferImage::New(ptr, data.size());
-}
-
-}; // namespace Emscripten
-}; // namespace Internal
-}; // namespace Dali
diff --git a/adaptors/emscripten/wrappers/emscripten-utils.h b/adaptors/emscripten/wrappers/emscripten-utils.h
deleted file mode 100644 (file)
index ac8f604..0000000
+++ /dev/null
@@ -1,71 +0,0 @@
-#ifndef __DALI_EMSCRIPTEN_UTILS_H__
-#define __DALI_EMSCRIPTEN_UTILS_H__
-
-/*
- * Copyright (c) 2015 Samsung Electronics Co., Ltd.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- */
-
-// EXTERNAL INCLUDES
-#include <string>
-#include <dali/public-api/dali-core.h>
-#include "emscripten/val.h"
-
-// INTERNAL INCLUDES
-
-namespace Dali
-{
-namespace Internal
-{
-namespace Emscripten
-{
-
-/**
- * Creates a Dali RGBA Image from raw bytes
- *
- * @param[in] width The image width
- * @param[in] height The image height
- * @param[in] data The byte data
- * @returns The Dali Image
- *
- */
-Dali::Image CreateImageRGBA(unsigned int width, unsigned int height, const std::string& data);
-
-/**
- * Creates a Dali RGB Image from raw bytes
- *
- * @param[in] width The image width
- * @param[in] height The image height
- * @param[in] data The byte data
- * @returns The Dali Image
- *
- */
-Dali::Image CreateImageRGB(unsigned int width, unsigned int height, const std::string& data);
-
-/**
- * Creates a dali Image from encoded bytes (ie jpg/png etc)
- *
- * @param[in] data The byte data
- *
- * @returns The Dali Image
- *
- */
-Dali::Image GetImage(const std::string& data);
-
-}; // namespace Emscripten
-}; // namespace Internal
-}; // namespace Dali
-
-#endif // header
diff --git a/adaptors/emscripten/wrappers/geometry-wrapper.cpp b/adaptors/emscripten/wrappers/geometry-wrapper.cpp
deleted file mode 100644 (file)
index c75768a..0000000
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- * Copyright (c) 2016 Samsung Electronics Co., Ltd.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- */
-
-#include "geometry-wrapper.h"
-
-namespace Dali
-{
-namespace Internal
-{
-namespace Emscripten
-{
-
-void SetIndexBufferDataRaw(Dali::Geometry& self, const std::string& data, std::size_t size )
-{
-  self.SetIndexBuffer( reinterpret_cast<unsigned short*>( const_cast<char*>(data.c_str()) ), size );
-}
-
-}; // namespace Emscripten
-}; // namespace Internal
-}; // namespace Dali
diff --git a/adaptors/emscripten/wrappers/geometry-wrapper.h b/adaptors/emscripten/wrappers/geometry-wrapper.h
deleted file mode 100644 (file)
index f9fc075..0000000
+++ /dev/null
@@ -1,49 +0,0 @@
-#ifndef __DALI_GEOMETRY_WRAPPER_H__
-#define __DALI_GEOMETRY_WRAPPER_H__
-
-/*
- * Copyright (c) 2016 Samsung Electronics Co., Ltd.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- */
-
-// EXTERNAL INCLUDES
-#include <dali/public-api/dali-core.h>
-#include "emscripten/emscripten.h"
-#include "emscripten/val.h"
-#include "emscripten/bind.h"
-
-// INTERNAL INCLUDES
-
-namespace Dali
-{
-namespace Internal
-{
-namespace Emscripten
-{
-
-/**
- * Sets the index buffer
- *
- * @param[in] self The Geometry
- * @param[in] data The raw byte data
- *
- */
-void SetIndexBufferDataRaw(Dali::Geometry& self, const std::string& data, std::size_t size );
-
-}; // namespace Emscripten
-}; // namespace Internal
-}; // namespace Dali
-
-#endif // header
diff --git a/adaptors/emscripten/wrappers/handle-wrapper.cpp b/adaptors/emscripten/wrappers/handle-wrapper.cpp
deleted file mode 100644 (file)
index 4272114..0000000
+++ /dev/null
@@ -1,201 +0,0 @@
-/*
- * Copyright (c) 2015 Samsung Electronics Co., Ltd.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- */
-
-#include "handle-wrapper.h"
-
-// EXTERNAL INCLUDES
-#include <sstream>
-#include <dali/devel-api/scripting/scripting.h>
-
-// INTERNAL INCLUDES
-#include "type-info-wrapper.h"
-#include "property-value-wrapper.h"
-
-namespace Dali
-{
-namespace Internal
-{
-namespace Emscripten
-{
-
-bool BaseHandleOk(Dali::BaseHandle& self)
-{
-  return self;
-}
-
-void SetSelf(Dali::Handle& self, Dali::Handle& other)
-{
-  self = other;
-}
-
-void SetProperty(Dali::Handle& self, const std::string& name, const Dali::Property::Value& value)
-{
-  DALI_ASSERT_ALWAYS(self);
-  if( self )
-  {
-    Dali::Property::Index index = self.GetPropertyIndex(name);
-
-    if( Dali::Property::INVALID_INDEX != index )
-    {
-      self.SetProperty(index, value);
-    }
-    else
-    {
-      printf("ERR Invalid property name:%s", name.c_str());
-      EM_ASM( throw "Invalid property name (HandleWrapper::SetProperty)" );
-    }
-  }
-  else
-  {
-    EM_ASM( throw "ActorWrapper has no actor" );
-  }
-
-}
-
-Dali::Property::Value GetProperty(Dali::Handle& self, const std::string& name)
-{
-  DALI_ASSERT_ALWAYS(self);
-  Dali::Property::Value ret;
-  if( self )
-  {
-    Dali::Property::Index index = self.GetPropertyIndex(name);
-
-    if( Dali::Property::INVALID_INDEX != index )
-    {
-      ret = self.GetProperty(index);
-    }
-    else
-    {
-      printf("ERR Invalid property name:%s", name.c_str());
-      EM_ASM( throw new Error("Invalid property name (HandleWrapper::GetProperty)") );
-    }
-  }
-  else
-  {
-    EM_ASM( throw new Error("ActorWrapper has no actor") );
-  }
-
-  return ret;
-}
-
-int GetPropertyIndex(Dali::Handle& self, const std::string& name)
-{
-  if( self )
-  {
-    Dali::Property::Index index = self.GetPropertyIndex(name);
-
-    return (int)index; // self.GetPropertyIndex(name);
-  }
-
-  return -1;
-}
-
-std::vector<std::string> GetProperties(Dali::Handle& self)
-{
-  Dali::Property::IndexContainer indices;
-  self.GetPropertyIndices( indices );
-  std::vector<std::string> names;
-  for(Dali::Property::IndexContainer::Iterator iter(indices.Begin()); iter != indices.End(); ++iter)
-  {
-    std::string name = self.GetPropertyName( *iter );
-
-    names.push_back(name);
-  }
-  return names;
-}
-
-std::string GetPropertyTypeName(Dali::Handle& self, const std::string& name)
-{
-  if(self)
-  {
-    Dali::Property::Index index = self.GetPropertyIndex(name);
-    if(Dali::Property::INVALID_INDEX != index)
-    {
-      return Dali::PropertyTypes::GetName(self.GetPropertyType(index));
-    }
-  }
-
-  // if we got here
-  return Dali::PropertyTypes::GetName(Dali::Property::NONE);
-}
-
-Dali::Property::Type GetPropertyTypeFromName(Dali::Handle& self, const std::string& name)
-{
-  Dali::Property::Type type = Dali::Property::NONE;
-
-  if(self)
-  {
-    Dali::Property::Index index = self.GetPropertyIndex(name);
-    if(Dali::Property::INVALID_INDEX != index)
-    {
-      type = self.GetPropertyType(index);
-    }
-  }
-
-  return type;
-}
-
-Dali::Property::Index RegisterProperty(Dali::Handle& self, const std::string& name, const Dali::Property::Value& propertyValue)
-{
-  Dali::Property::Index ret = Dali::Property::INVALID_INDEX;
-
-  Dali::Property::Type type = propertyValue.GetType();
-  if(Dali::Property::ARRAY == type || Dali::Property::MAP == type)
-  {
-    // these types would need support in the javascript side of the wrapper
-    EM_ASM( throw "Property type not supported" );
-  }
-
-  if(self)
-  {
-    ret = self.RegisterProperty(name, propertyValue, Dali::Property::AccessMode::READ_WRITE);
-  }
-  return ret;
-}
-
-Dali::TypeInfo GetTypeInfo(Dali::Handle& self)
-{
-  Dali::TypeInfo ret;
-  if( self )
-  {
-    self.GetTypeInfo(ret);
-  }
-  return ret;
-}
-
-Dali::Property::Index RegisterAnimatedProperty(Dali::Handle& self, const std::string& name, const Dali::Property::Value& propertyValue)
-{
-  Dali::Property::Index ret = Dali::Property::INVALID_INDEX;
-
-  Dali::Property::Type type = propertyValue.GetType();
-  if(Dali::Property::ARRAY == type || Dali::Property::MAP == type)
-  {
-    // these types would need support in the javascript side of the wrapper
-    EM_ASM( throw "Property type not supported" );
-  }
-
-  if(self)
-  {
-    ret = self.RegisterProperty(name, propertyValue,  Dali::Property::AccessMode::ANIMATABLE);
-  }
-  return ret;
-}
-
-
-}; // namespace Emscripten
-}; // namespace Internal
-}; // namespace Dali
diff --git a/adaptors/emscripten/wrappers/handle-wrapper.h b/adaptors/emscripten/wrappers/handle-wrapper.h
deleted file mode 100644 (file)
index 8e39be1..0000000
+++ /dev/null
@@ -1,148 +0,0 @@
-#ifndef __DALI_HANDLE_WRAPPER_H__
-#define __DALI_HANDLE_WRAPPER_H__
-
-/*
- * Copyright (c) 2015 Samsung Electronics Co., Ltd.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- */
-
-// EXTERNAL INCLUDES
-#include <dali/public-api/dali-core.h>
-
-#include "emscripten/emscripten.h"
-#include "emscripten/bind.h"
-
-// INTERNAL INCLUDES
-#include "type-info-wrapper.h"
-
-
-namespace Dali
-{
-namespace Internal
-{
-namespace Emscripten
-{
-
-/**
- * Checks if a handle is pointing somewhere
- *
- * @param[in] self The basehandle
- * @returns true if the handle is not empty
- *
- */
-bool BaseHandleOk(Dali::BaseHandle& self);
-
-/**
- * Sets a handle to point to another object
- *
- * @param[in] self The handle to change
- * @param[in] self The handle to point to
- *
- */
-void SetSelf(Dali::Handle& self, Dali::Handle& other);
-
-/**
- * Sets a property by name
- *
- * @param[in] self The handle
- * @param[in] javascriptName The property by name
- * @param[in] value The property value
- *
- */
-void SetProperty(Dali::Handle& self, const std::string& javascriptName, const Dali::Property::Value& value);
-
-/**
- * Gets a property by name
- *
- * @param[in] self The handle
- * @param[in] javascriptName The property by name
- * @returns The property value
- *
- */
-Dali::Property::Value GetProperty(Dali::Handle& self, const std::string& javascriptName);
-
-/**
- * Gets a property index
- *
- * @param[in] self The handle
- * @param[in] javascriptName The property by name
- * @returns The property index
- *
- */
-int GetPropertyIndex(Dali::Handle& self, const std::string& javascriptName);
-
-/**
- * Gets a list of property names
- *
- * @param[in] self The handle
- * @returns The list of property names
- *
- */
-std::vector<std::string> GetProperties(Dali::Handle& self);
-
-/**
- * Gets a property type by name
- *
- * @param[in] self The handle
- * @param[in] name The property type name
- * @returns The property type
- *
- */
-Dali::Property::Type GetPropertyTypeFromName(Dali::Handle& self, const std::string& name);
-
-/**
- * Gets a property type name
- *
- * @param[in] self The handle
- * @param[in] name The property by name
- * @returns The property type name
- *
- */
-std::string GetPropertyTypeName(Dali::Handle& self, const std::string& name);
-
-/**
- * Registers a property by name
- *
- * @param[in] self The handle
- * @param[in] name The property by name
- * @returns The property index of the newly registered property
- *
- */
-Dali::Property::Index RegisterProperty(Dali::Handle& self, const std::string& name, const Dali::Property::Value& propertyValue);
-
-/**
- * Registers an animated property
- *
- * @param[in] self The handle
- * @param[in] name The property by name
- * @returns The property index of the newly registered property
- *
- */
-Dali::Property::Index RegisterAnimatedProperty(Dali::Handle& self, const std::string& name, const Dali::Property::Value& propertyValue);
-
-/**
- * Gets Dali type info
- *
- * @param[in] self The handle
- * @returns The type info
- *
- */
-Dali::TypeInfo GetTypeInfo(Dali::Handle& self);
-
-}; // namespace Emscripten
-}; // namespace Internal
-}; // namespace Dali
-
-#endif // header
diff --git a/adaptors/emscripten/wrappers/image-wrapper.cpp b/adaptors/emscripten/wrappers/image-wrapper.cpp
deleted file mode 100644 (file)
index 7d6ffc1..0000000
+++ /dev/null
@@ -1,54 +0,0 @@
-/*
- * Copyright (c) 2015 Samsung Electronics Co., Ltd.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- */
-
-#include "image-wrapper.h"
-
-// EXTERNAL INCLUDES
-
-// INTERNAL INCLUDES
-
-namespace Dali
-{
-namespace Internal
-{
-namespace Emscripten
-{
-
-Dali::BufferImage BufferImageNew(const std::string& data, unsigned int width, unsigned int height, Dali::Pixel::Format pixelFormat)
-{
-  Dali::BufferImage b = Dali::BufferImage::New( width, height, pixelFormat );
-
-  const Dali::PixelBuffer* from = reinterpret_cast<const Dali::PixelBuffer*>( data.c_str() );
-  Dali::PixelBuffer* to = b.GetBuffer();
-
-  unsigned int len = std::min( width * height * GetBytesPerPixel(pixelFormat), data.size() );
-  for(int i = 0; i < len; i++)
-  {
-    *to++ = *from++;
-  }
-  return b;
-}
-
-Dali::EncodedBufferImage EncodedBufferImageNew(const std::string& data)
-{
-  const uint8_t* const ptr = reinterpret_cast<const uint8_t * const>(data.c_str());
-  return Dali::EncodedBufferImage::New(ptr, data.size());
-}
-
-}; // namespace Emscripten
-}; // namespace Internal
-}; // namespace Dali
diff --git a/adaptors/emscripten/wrappers/image-wrapper.h b/adaptors/emscripten/wrappers/image-wrapper.h
deleted file mode 100644 (file)
index c0dd144..0000000
+++ /dev/null
@@ -1,61 +0,0 @@
-#ifndef __DALI_IMAGE_WRAPPER_H__
-#define __DALI_IMAGE_WRAPPER_H__
-
-/*
- * Copyright (c) 2015 Samsung Electronics Co., Ltd.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- */
-
-// EXTERNAL INCLUDES
-#include <dali/public-api/dali-core.h>
-#include "emscripten/emscripten.h"
-#include "emscripten/bind.h"
-
-// INTERNAL INCLUDES
-
-namespace Dali
-{
-namespace Internal
-{
-namespace Emscripten
-{
-
-/**
- * Creates a new buffer image from raw data
- *
- * @param[in] data The image byte data
- * @param[in] width The width of the image
- * @param[in] height The height of the image
- * @param[in] pixelFormat The pixel format
- *
- * @returns A Dali BufferImage
- */
-Dali::BufferImage BufferImageNew(const std::string& data, unsigned int width, unsigned int height, Dali::Pixel::Format pixelFormat);
-
-/**
- * Gets an encoded buffer from encoded data
- *
- * @param[in] data The image data
- *
- * @returns A Dali EncodedBufferImage
- *
- */
-Dali::EncodedBufferImage EncodedBufferImageNew(const std::string& data);
-
-}; // namespace Emscripten
-}; // namespace Internal
-}; // namespace Dali
-
-#endif // header
diff --git a/adaptors/emscripten/wrappers/property-buffer-wrapper.h b/adaptors/emscripten/wrappers/property-buffer-wrapper.h
deleted file mode 100644 (file)
index 364b8e0..0000000
+++ /dev/null
@@ -1,50 +0,0 @@
-#ifndef DALI_PROPERTYBUFFER_WRAPPER_H
-#define DALI_PROPERTYBUFFER_WRAPPER_H
-
-/*
- * Copyright (c) 2016 Samsung Electronics Co., Ltd.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- */
-
-// EXTERNAL INCLUDES
-#include <dali/public-api/dali-core.h>
-#include <dali/public-api/rendering/property-buffer.h>
-#include "emscripten/emscripten.h"
-#include "emscripten/val.h"
-#include "emscripten/bind.h"
-
-// INTERNAL INCLUDES
-
-namespace Dali
-{
-namespace Internal
-{
-namespace Emscripten
-{
-
-/**
- * Sets a property buffer from raw data
- *
- * @param[in] self The PropertyBuffer
- * @param[in] data The raw byte data
- *
- */
-void SetPropertyBufferDataRaw(Dali::PropertyBuffer& self, const std::string& data, std::size_t size );
-
-}; // namespace Emscripten
-}; // namespace Internal
-}; // namespace Dali
-
-#endif // DALI_PROPERTYBUFFER_WRAPPER_H
diff --git a/adaptors/emscripten/wrappers/property-value-wrapper.cpp b/adaptors/emscripten/wrappers/property-value-wrapper.cpp
deleted file mode 100644 (file)
index 0b54761..0000000
+++ /dev/null
@@ -1,315 +0,0 @@
-/*
- * Copyright (c) 2015 Samsung Electronics Co., Ltd.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- */
-
-#include "property-value-wrapper.h"
-
-// EXTERNAL INCLUDES
-#include <sstream>
-#include <cassert>
-
-// INTERNAL INCLUDES
-
-namespace Dali
-{
-namespace Internal
-{
-namespace Emscripten
-{
-
-void RecursiveSetProperty(Dali::Property::Value& propertyValue, const emscripten::val& fromVal)
-{
-  static const std::string number("number"); // we could maybe just check the first three chars? (avoiding null ...if that's returned)
-  const std::string fromType( fromVal.typeof().as<std::string>() );
-
-  if( fromType == "object" )
-  {
-    // hasOwnProperty is the only way I can find to tell if the object is an array
-    // (keys in HasKey returns the JS keys "0","1","2","3",...)
-    if( fromVal.hasOwnProperty("length") )
-    {
-      int length = fromVal["length"].as<int>();
-      // we can't tell if what the user of the property value wants with a JS Array
-      // by default 'standard' length arrays are always interpreted as Vector2/3/4 etc
-      // If the user specifically wants an array they must recast.
-      bool isArray = false; // nested ie [ [1,2,3], [4,5,6] ]
-      if( 4 == length )
-      {
-        if( number == fromVal["0"].typeof().as<std::string>() &&
-            number == fromVal["1"].typeof().as<std::string>() &&
-            number == fromVal["2"].typeof().as<std::string>() &&
-            number == fromVal["3"].typeof().as<std::string>() )
-        {
-          propertyValue = Dali::Vector4( fromVal["0"].as<float>(),
-                                         fromVal["1"].as<float>(),
-                                         fromVal["2"].as<float>(),
-                                         fromVal["3"].as<float>() );
-        }
-        else
-        {
-          isArray = true;
-        }
-      }
-      else if( 3 == length )
-      {
-        if( number == fromVal["0"].typeof().as<std::string>() &&
-            number == fromVal["1"].typeof().as<std::string>() &&
-            number == fromVal["2"].typeof().as<std::string>() )
-        {
-          propertyValue = Dali::Vector3( fromVal["0"].as<float>(),
-                                         fromVal["1"].as<float>(),
-                                         fromVal["2"].as<float>() );
-        }
-        else
-        {
-          isArray = true;
-        }
-      }
-      else if( 2 == length )
-      {
-        if( number == fromVal["0"].typeof().as<std::string>() &&
-            number == fromVal["1"].typeof().as<std::string>() )
-        {
-          propertyValue = Dali::Vector2( fromVal["0"].as<float>(),
-                                         fromVal["1"].as<float>() );
-        }
-        else
-        {
-          isArray = true;
-        }
-      }
-      else
-      {
-        isArray = true;
-      }
-
-      if( isArray )
-      {
-        propertyValue = Dali::Property::Value(Dali::Property::ARRAY);
-        Dali::Property::Array* array = propertyValue.GetArray();
-        for( int j = 0; j < length; ++j )
-        {
-          Dali::Property::Value add;
-          array->PushBack( add );
-
-          std::stringstream ss;
-          ss << j;
-
-          emscripten::val val = fromVal[ ss.str() ];
-          RecursiveSetProperty( array->GetElementAt(j), val );
-        }
-      }
-    }
-    else
-    {
-      propertyValue = Dali::Property::Value(Dali::Property::MAP);
-      Dali::Property::Map* map = propertyValue.GetMap();
-      emscripten::val keys = emscripten::val::global("Object").call<emscripten::val>("keys", fromVal);
-      int keyLength = keys["length"].as<int>();
-      for( int j = 0; j < keyLength; ++j )
-      {
-        Dali::Property::Value add;
-        std::string key = keys[j].as<std::string>();
-        (*map)[key] = add;
-        emscripten::val keyVal = fromVal[ key ];
-        RecursiveSetProperty( *(map->Find( key )), keyVal );
-      }
-    }
-  }
-  else if( fromType == "number" )
-  {
-    propertyValue = Dali::Property::Value( fromVal.as<float>() );
-  }
-  else if( fromType == "string" )
-  {
-    propertyValue = Dali::Property::Value( fromVal.as<std::string>() );
-  }
-  else
-  {
-    assert(0);
-  }
-
-}
-
-emscripten::val JavascriptValue( const Dali::Property::Value& v )
-{
-  switch( v.GetType() )
-  {
-    case Dali::Property::BOOLEAN:
-    {
-      return emscripten::val(v.Get<bool>());
-      break;
-    }
-    case Dali::Property::FLOAT:
-    {
-      return emscripten::val(v.Get<float>());
-      break;
-    }
-    case Dali::Property::INTEGER:
-    {
-      return emscripten::val(v.Get<int>());
-      break;
-    }
-    case Dali::Property::VECTOR2:
-    {
-      Dali::Vector2 in = v.Get<Dali::Vector2>();
-      emscripten::val out = emscripten::val::array();
-      out.set("0", emscripten::val(in.x) );
-      out.set("1", emscripten::val(in.y) );
-      return out;
-      break;
-    }
-    case Dali::Property::VECTOR3:
-    {
-      Dali::Vector3 in = v.Get<Dali::Vector3>();
-      emscripten::val out = emscripten::val::array();
-      out.set("0", emscripten::val(in.x) );
-      out.set("1", emscripten::val(in.y) );
-      out.set("2", emscripten::val(in.z) );
-      return out;
-      break;
-    }
-    case Dali::Property::VECTOR4:
-    {
-      Dali::Vector4 in = v.Get<Dali::Vector4>();
-      emscripten::val out = emscripten::val::array();
-      out.set("0", emscripten::val(in.x) );
-      out.set("1", emscripten::val(in.y) );
-      out.set("2", emscripten::val(in.z) );
-      out.set("3", emscripten::val(in.w) );
-      return out;
-      break;
-    }
-    case Dali::Property::MATRIX3:
-    {
-      emscripten::val val = emscripten::val::array();
-      Dali::Matrix3 mat3 = v.Get<Dali::Matrix3>();
-
-      for( int i = 0; i < 9; ++i )
-      {
-        std::stringstream key;
-        key << i;
-        val.set( key.str(), emscripten::val(mat3.AsFloat()[i]) );
-      }
-      return val;
-      break;
-    }
-    case Dali::Property::MATRIX:
-    {
-      emscripten::val val = emscripten::val::array();
-      Dali::Matrix mat = v.Get<Dali::Matrix>();
-
-      for( int i = 0; i < 16; ++i )
-      {
-        std::stringstream key;
-        key << i;
-        val.set( key.str(), emscripten::val(mat.AsFloat()[i]) );
-      }
-      return val;
-      break;
-    }
-    case Dali::Property::RECTANGLE:
-    {
-      Dali::Rect<int> in = v.Get<Dali::Rect<int> >();
-      emscripten::val out = emscripten::val::array();
-      out.set("0", emscripten::val(in.x) );
-      out.set("1", emscripten::val(in.y) );
-      out.set("2", emscripten::val(in.width) );
-      out.set("3", emscripten::val(in.height) );
-      return out;
-      break;
-    }
-    case Dali::Property::ROTATION:
-    {
-      Dali::Quaternion in = v.Get<Dali::Quaternion>();
-      emscripten::val out = emscripten::val::array();
-      Dali::Vector3 axis;
-      Dali::Radian angle;
-      in.ToAxisAngle(axis, angle);
-
-      out.set("0", emscripten::val( axis.x ) );
-      out.set("1", emscripten::val( axis.y ) );
-      out.set("2", emscripten::val( axis.z ) );
-      out.set("3", emscripten::val( Dali::Degree(angle).degree ) );
-
-      return out;
-      break;
-    }
-    case Dali::Property::STRING:
-    {
-      return emscripten::val( v.Get<std::string>() );
-      break;
-    }
-    case Dali::Property::ARRAY:
-    {
-      emscripten::val val = emscripten::val::array();
-      Dali::Property::Array *array = v.GetArray();
-      DALI_ASSERT_ALWAYS(array);
-
-      for( int i = 0; i < array->Count(); ++i )
-      {
-        Dali::Property::Value& property = array->GetElementAt( i );
-        std::stringstream key;
-        key << i;
-        val.set( key.str(), JavascriptValue( property ) );
-      }
-
-      return val;
-      break;
-    }
-    case Dali::Property::MAP:
-    {
-      emscripten::val val = emscripten::val::object();
-      Dali::Property::Map *map = v.GetMap();
-      DALI_ASSERT_ALWAYS(map);
-
-      for( int i = 0; i < map->Count(); ++i )
-      {
-        std::string key;
-        StringValuePair pair = map->GetPair(i);
-        val.set( pair.first, JavascriptValue( pair.second ) );
-      }
-
-      return val;
-      break;
-    }
-    case Dali::Property::NONE:
-    {
-      break;
-    }
-  } // switch type
-
-  return emscripten::val::undefined();
-
-}
-
-Dali::Property::Value PropertyMapGet( Dali::Property::Map& self, const std::string& key)
-{
-  Dali::Property::Value ret;
-
-  Dali::Property::Value* v = self.Find(key);
-
-  if(v)
-  {
-    ret = *v;
-  }
-
-  return ret;
-}
-
-}; // namespace Emscripten
-}; // namespace Internal
-}; // namespace Dali
diff --git a/adaptors/emscripten/wrappers/property-value-wrapper.h b/adaptors/emscripten/wrappers/property-value-wrapper.h
deleted file mode 100644 (file)
index 86c73c8..0000000
+++ /dev/null
@@ -1,69 +0,0 @@
-#ifndef __DALI_PROPERTY_VALUE_WRAPPER_H__
-#define __DALI_PROPERTY_VALUE_WRAPPER_H__
-
-/*
- * Copyright (c) 2015 Samsung Electronics Co., Ltd.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- */
-
-// EXTERNAL INCLUDES
-#include <string>
-#include <dali/public-api/dali-core.h>
-#include "emscripten/val.h"
-
-// INTERNAL INCLUDES
-
-namespace Dali
-{
-namespace Internal
-{
-namespace Emscripten
-{
-
-/**
- * Sets a property value From an Emscripten value. Recursively for Maps and Arrays
- *
- * @param[in] propertyValue The property value to set
- * @param[in] fromVal The emscripten value to set from
- *
- */
-void RecursiveSetProperty(Dali::Property::Value& propertyValue, const emscripten::val& fromVal);
-
-/**
- * Set an Emscripten value from a Dali property Value
- *
- * @param[in] value The Dali Property value
- *
- * @returns The Emscripten value
- *
- */
-emscripten::val JavascriptValue( const Dali::Property::Value& value );
-
-/**
- * Gets a Dali value from a Dali Property Map
- *
- * @param[in] self The property map
- * @param[in] key The key of the value to fetch
- *
- * @returns The property value
- *
- */
-Dali::Property::Value PropertyMapGet( Dali::Property::Map& self, const std::string& key );
-
-}; // namespace Emscripten
-}; // namespace Internal
-}; // namespace Dali
-
-#endif // header
diff --git a/adaptors/emscripten/wrappers/render-task-wrapper.cpp b/adaptors/emscripten/wrappers/render-task-wrapper.cpp
deleted file mode 100644 (file)
index 255162d..0000000
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
- * Copyright (c) 2015 Samsung Electronics Co., Ltd.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- */
-
-#include "render-task-wrapper.h"
-
-// EXTERNAL INCLUDES
-
-// INTERNAL INCLUDES
-
-namespace Dali
-{
-namespace Internal
-{
-namespace Emscripten
-{
-
-Dali::Vector2 ScreenToLocal(Dali::RenderTask self, Dali::Actor actor, float screenX, float screenY)
-{
-  float localX = 0;
-  float localY = 0;
-  self.ViewportToLocal(actor, screenX, screenY, localX, localY);
-  return Dali::Vector2(localX,localY);
-}
-
-Dali::Vector2 WorldToScreen(Dali::RenderTask self, const Dali::Vector3 &position)
-{
-  float screenX = 0;
-  float screenY = 0;
-  self.WorldToViewport(position, screenX, screenY);
-  return Dali::Vector2(screenX, screenY);
-}
-
-
-}; // namespace Emscripten
-}; // namespace Internal
-}; // namespace Dali
diff --git a/adaptors/emscripten/wrappers/render-task-wrapper.h b/adaptors/emscripten/wrappers/render-task-wrapper.h
deleted file mode 100644 (file)
index fc799c9..0000000
+++ /dev/null
@@ -1,64 +0,0 @@
-#ifndef __DALI_RENDER_TASK_WRAPPER_H__
-#define __DALI_RENDER_TASK_WRAPPER_H__
-
-/*
- * Copyright (c) 2015 Samsung Electronics Co., Ltd.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- */
-
-// EXTERNAL INCLUDES
-#include <dali/public-api/dali-core.h>
-#include "emscripten/emscripten.h"
-#include "emscripten/bind.h"
-
-// INTERNAL INCLUDES
-#include "actor-wrapper.h"
-
-namespace Dali
-{
-namespace Internal
-{
-namespace Emscripten
-{
-
-/**
- * Gets the local coordinates from the screen coordinates
- *
- * @param[in] self The render task
- * @param[in] actor The Dali actor
- * @param[in] screenX The screen X position
- * @param[in] screenY The screen Y position
- *
- * @returns The Local coordinates
- *
- */
-Dali::Vector2 ScreenToLocal(Dali::RenderTask self, Dali::Actor actor, float screenX, float screenY);
-
-/**
- * Gets the screen coordinates from a position
- *
- * @param[in] self The RenderTask
- * @param[in] position The position
- *
- * @returns The screen coordinates of the actor
- *
- */
-Dali::Vector2 WorldToScreen(Dali::RenderTask self, const Dali::Vector3 &position);
-
-}; // namespace Emscripten
-}; // namespace Internal
-}; // namespace Dali
-
-#endif // header
diff --git a/adaptors/emscripten/wrappers/signal-holder.h b/adaptors/emscripten/wrappers/signal-holder.h
deleted file mode 100644 (file)
index 0e96bc7..0000000
+++ /dev/null
@@ -1,49 +0,0 @@
-#ifndef DALI_SIGNAL_HOLDER_H
-#define DALI_SIGNAL_HOLDER_H
-
-namespace Dali
-{
-namespace Internal
-{
-namespace Emscripten
-{
-
-struct BaseSignalSlot : public Dali::ConnectionTracker
-{
-};
-
-/**
- * A wrapper class to let JS hold Signals
- */
-class SignalHolder : public Dali::ConnectionTracker
-{
-public:
-  typedef Dali::Vector<BaseSignalSlot*> Slots;
-  Slots mSlots;
-  SignalHolder() {}
-
-  ~SignalHolder()
-  {
-    for(Slots::Iterator iter = mSlots.Begin(); iter != mSlots.End(); ++iter)
-    {
-      delete *iter;
-    }
-  }
-
-  /*
-   * Adds a base signal to the list of slots
-   */
-  void add(BaseSignalSlot* s) { mSlots.PushBack(s); }
-
-private:
-  SignalHolder(const SignalHolder& nocopy);
-  SignalHolder& operator=(const SignalHolder& noassign);
-};
-
-
-}; // Emscripten
-}; // Internal
-}; // Dali
-
-
-#endif // header
diff --git a/adaptors/emscripten/wrappers/tests/README.TXT b/adaptors/emscripten/wrappers/tests/README.TXT
deleted file mode 100644 (file)
index a0b8c54..0000000
+++ /dev/null
@@ -1,25 +0,0 @@
-Dali Browser Regression Tests
------------------------------
-
-These tests work with a web server but not from the filesystem (a "file:///" URI).
-
-To run the tests locally run a local web server.
-
-One quick way to do this if you have nodeJS and npm installed is
-
-npm install http-server -g
-
-then in the directory with dali_tests.html run
-
-http-server
-
-or
-
-http-server -p:8888
-
-if you already have a local server running on 8080.
-
-Note: Alternatively you can use python with
-
-python -m SimpleHTTPServer 8080
-
diff --git a/adaptors/emscripten/wrappers/tests/all.html b/adaptors/emscripten/wrappers/tests/all.html
deleted file mode 100644 (file)
index 1347271..0000000
+++ /dev/null
@@ -1,30 +0,0 @@
-<html>
-
-        <head>
-                 <meta charset="utf-8">
-                 <meta name="viewport" content="width=device-width">
-                 <title>DALi Browser Wrapper Regression Tests</title>
-                 <link rel="stylesheet" href="qunit-1.21.0.css">
-                 <link rel="stylesheet" href="dali-tests.css" type="text/css" media="screen"/>
-
-        </head>
-
-        <body style="background-color: #fff;width:700px">
-                 <script src="qunit-1.21.0.js"></script>
-                 <script type="text/javascript" src="./utilities.js"></script>
-                 <script type="text/javascript" src="./properties.js"></script>
-                 <script type="text/javascript" src="./geometry.js"></script>
-                 <script type="text/javascript" src="./signals.js"></script>
-                 <script type="text/javascript" src="./math.js"></script>
-                 <script type="text/javascript" src="./animation.js"></script>
-                 <script type="text/javascript" src="./shaders.js"></script>
-                 <script type="text/javascript" src="./views.js"></script>
-
-                 <div id="qunit"></div>
-                 <iframe id="daliframe" scrolling="no" width="600px" border="1px solid" ></iframe>
-
-                 <img alt="Brand" width="50" id="testImage" style="visibility: hidden" src="data:image/png;base64,/9j/4QCGRXhpZgAASUkqAAgAAAABAJiCAgBiAAAAGgAAAAAAAABDb3B5cmlnaHQgKGMpIDIwMTQgU2Ftc3VuZyBFbGVjdHJvbmljcywgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMDogaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wAAAA/+EC12h0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC8APD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiPz4KPHg6eG1wbWV0YSB4bWxuczp4PSJhZG9iZTpuczptZXRhLyIgeDp4bXB0az0iWE1QIENvcmUgNC40LjAtRXhpdjIiPgogPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4KICA8cmRmOkRlc2NyaXB0aW9uIHJkZjphYm91dD0iIgogICAgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIgogICAgeG1sbnM6dGlmZj0iaHR0cDovL25zLmFkb2JlLmNvbS90aWZmLzEuMC8iCiAgICB4bWxuczpkYz0iaHR0cDovL3B1cmwub3JnL2RjL2VsZW1lbnRzLzEuMS8iCiAgIHhtcDpDcmVhdG9yVG9vbD0iS2lwaS1wbHVnaW5zLTIuNS4wIgogICB0aWZmOlNvZnR3YXJlPSJLaXBpLXBsdWdpbnMtMi41LjAiPgogICA8ZGM6cmlnaHRzPgogICAgPHJkZjpBbHQ+CiAgICAgPHJkZjpsaSB4bWw6bGFuZz0ieC1kZWZhdWx0Ij5Db3B5cmlnaHQgKGMpIDIwMTQgU2Ftc3VuZyBFbGVjdHJvbmljcywgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMDogaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wPC9yZGY6bGk+CiAgICA8L3JkZjpBbHQ+CiAgIDwvZGM6cmlnaHRzPgogIDwvcmRmOkRlc2NyaXB0aW9uPgogPC9yZGY6UkRGPgo8L3g6eG1wbWV0YT4K/+0ArlBob3Rv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">
-                 
-        </body>
-
-</html>
diff --git a/adaptors/emscripten/wrappers/tests/animation.js b/adaptors/emscripten/wrappers/tests/animation.js
deleted file mode 100644 (file)
index 115f1d8..0000000
+++ /dev/null
@@ -1,128 +0,0 @@
-
-QUnit.module("Animation", {
-    setup : function() {
-        QUnit.stop();
-        var that = this;
-        this.cb = function(e) {
-          QUnit.ok(true, "Scene loaded");
-          var iframe = document.getElementById('daliframe');
-          that.doc =  iframe.contentDocument || iframe.contentWindow.document;
-          that.doc.Module.postDaliWrapperRun = function() {
-            dali = that.doc.Module;
-            QUnit.start();
-          };
-        };
-        loadDocument("dali-page.html"+window.location.search, this.cb);
-    },
-    teardown : function() {
-        var v = document.getElementById("daliframe");
-        v.removeEventListener("load", this.cb, true);
-    }
-});
-
-QUnit.test( "spline path", function( assert ) {
-
-  var done1 = assert.async();
-
-  threeSquares();
-  var col = {};
-  collectByName(col);
-  var actor = col.red;
-
-  var a = new dali.Animation(0);
-  var path = new dali.Path();
-
-  path.points = [
-    [-150, -50, 0],
-    [0.0, 70.0, 0.0],
-    [190.0, -150.0, 0.0]
-  ];
-
-  assert.ok(compareArrays(path.points, [
-    [-150, -50, 0],
-    [0.0, 70.0, 0.0],
-    [190.0, -150.0, 0.0]
-  ]));
-
-  dali.generateControlPoints(path, 0.35);
-
-  assert.ok(compareArrays(path.controlPoints, [
-    [-97.5, -8, 0],
-    [-66.94940948486328, 76.16658020019531, 0],
-    [101.31224060058594, 60.66832733154297, 0],
-    [123.5, -73, 0]
-  ]));
-
-  a.setDuration(0.1);
-  a.animatePath(actor, path, [1, 0, 0], dali.AlphaFunction.LINEAR, 0, 0.1);
-  a.play();
-
-
-  function checkPos() {
-    assert.ok(actor.position = path.points[2]);
-    clear();
-    actor.delete();
-    path.delete();
-    a.delete();
-    done1();
-  }
-
-  window.setTimeout(checkPos, 200);
-
-});
-
-QUnit.test( "linear", function( assert ) {
-
-  var done1 = assert.async();
-  var done2 = assert.async();
-  var done3 = assert.async();
-
-  threeSquares();
-  var col = {};
-  collectByName(col);
-  var actor = col.red;
-
-  var a = new dali.Animation(0);
-  a.setDuration(0.1);
-  a.animateTo(actor, "position", [20, 0, 0], dali.AlphaFunction.LINEAR, 0, 0.1);
-  a.play();
-
-  function checkAnimateBetween() {
-    assert.ok(actor.position = [0, 0, -30]);
-    clear();
-    a.delete();
-    actor.delete();
-    done3();
-  }
-
-  function checkAnimateBy() {
-    assert.ok(actor.position = [120, 100, 0]);
-    a.clear();
-    a.animateBetween(actor,
-                     "position", [ [ 0,  [10,20,30] ],
-                                   [ 1.0,[0, 0, -30] ] ],
-                     "linear",
-                     0,
-                     0.1,
-                     "linear");
-    a.play();
-    window.setTimeout(checkAnimateBetween, 200);
-    done2();
-  }
-
-  function checkAnimateTo() {
-    assert.ok(actor.position = [20, 0, 0]);
-    actor.position = [100, 100, 0];
-
-    a.clear(); // var a = new dali.Animation(0);
-    a.setDuration(0.1);
-    a.animateBy(actor, "position", [20, 0, 0], dali.AlphaFunction.LINEAR, 0, 0.1);
-    a.play();
-    window.setTimeout(checkAnimateBy, 200);
-    done1();
-  }
-
-  window.setTimeout(checkAnimateTo, 200);
-
-});
-
diff --git a/adaptors/emscripten/wrappers/tests/dali-page.html b/adaptors/emscripten/wrappers/tests/dali-page.html
deleted file mode 100644 (file)
index ee6226f..0000000
+++ /dev/null
@@ -1,110 +0,0 @@
-<html><head>
-        <title>Dali Browser Wrapper Regression Tests</title>
-
-        <meta charset="utf-8">
-        <meta name="viewport" content="width=device-width">
-
-</head>
-<body style="background-color: #fff;width=600px">
-
-        <div class="emscripten" id="status">
-                 Downloading...
-        </div>
-
-        <canvas class="emscripten" id="canvas" oncontextmenu="event.preventDefault()" width="600" height="800" style="background-color: black;"></canvas>
-
-        <script type="text/javascript">  //  emscripten
-
-         var statusElement = document.getElementById('status');
-
-         var Module = {
-                       doNotCaptureKeyboard:true,
-                       preRun: [],
-                       postRun: [],
-                       print: (function() {
-                                return function(text) {
-                                         text = Array.prototype.slice.call(arguments).join(' ');
-                                         console.log("STDOUT:", text);
-                                };
-                       })(),
-                       printErr: function(text) {
-                                text = Array.prototype.slice.call(arguments).join(' ');
-                                console.error("STDERR:", text);
-                       },
-                       canvas: document.getElementById('canvas'),
-                       setStatus: function(text) {
-                                if (!Module.setStatus.last) Module.setStatus.last = { time: Date.now(), text: '' };
-                                if (text === Module.setStatus.text) return;
-                                statusElement.innerHTML = text;
-                       },
-                       totalDependencies: 0,
-                       monitorRunDependencies: function(left) {
-                                this.totalDependencies = Math.max(this.totalDependencies, left);
-                                Module.setStatus(left ? 'Preparing... (' + (this.totalDependencies-left) + '/' + this.totalDependencies + ')' : 'All downloads complete.');
-                       },
-
-                       postRun: function () {
-                                // postRun; so that dali-emscripten.js is loaded first
-                                // (postMainLoop to run all the time)
-                                var s = document.createElement("script");
-                                s.src = "dali-wrapper.js";
-                                document.body.appendChild(s);
-                                Module.setStatus("Loading: dali-wrapper.js");
-                       },
-
-                       loadScriptFile: function(name) {
-                                var chainLoadScript = document.createElement("script");
-                                chainLoadScript.src = name;
-                                document.body.appendChild(chainLoadScript);
-                                Module.setStatus("Loading: " + name);
-                       },
-                       
-                       postDaliWrapperRun: function () {
-                                //
-                                // chain load main.js
-                                //
-
-                                // ** todo run the tests?? ... in geometry.js callback
-                                //
-                                document.dali = dali;
-                       },
-
-                       // This function is here as putting it in utilities.js caused the BufferImage() ctor to fail.
-                  // The ctor uses 'instanceof' to check for string/uint8array and converts if needed to copy binary
-                       // data into Dali. Apparently 'instanceof' in Javascript can lie if the data is coming from a 
-                       // different frame. I think(!) this is why 'uint8array instanceof Uint8array' succeded outside the ctor
-                       // call, but once inside the ctor 'arguments[0] instanceof Uint8array' failed and the ctor didn't
-                       // pick the correct conversion function. ....don't we love Javascript.
-         // tldr; If the function is here then we can use it.
-                       unitTestEmbeddedImage: function () {
-                                "use strict";
-                                // name is presumed to be in the html as base64 data
-                                // (from the iframe document)
-                                         // var iframe = document.getElementById('daliframe');
-                                var doc = document; // iframe.contentDocument || iframe.contentWindow.document;
-                                var c = doc.createElement("canvas");
-                                var img = doc.getElementById("testImage");
-                                c.width = img.naturalWidth;
-                                c.height = img.naturalHeight;
-                                var context = c.getContext("2d");
-                                context.drawImage(img, 0, 0 );
-                                var imageData = context.getImageData(0, 0, img.naturalWidth, img.naturalHeight); // <-ImageData
-                                var uint8clampedarray = new Uint8ClampedArray(imageData.data);
-                                var uint8array = new Uint8Array(uint8clampedarray);
-                                var image = new dali.BufferImage(uint8array, imageData.width, imageData.height, dali.PixelFormat.RGBA8888);
-                                return image;
-                       }
-
-         }; // Module
-
-         document.Module = Module;
-         
-        </script>
-
-        <script async type="text/javascript" src="dali-emscripten.js"></script>
-
-        <img alt="Brand" width="50" id="testImage" style="visibility: hidden" src="data:image/png;base64,/9j/4QCGRXhpZgAASUkqAAgAAAABAJiCAgBiAAAAGgAAAAAAAABDb3B5cmlnaHQgKGMpIDIwMTQgU2Ftc3VuZyBFbGVjdHJvbmljcywgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMDogaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wAAAA/+EC12h0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC8APD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiPz4KPHg6eG1wbWV0YSB4bWxuczp4PSJhZG9iZTpuczptZXRhLyIgeDp4bXB0az0iWE1QIENvcmUgNC40LjAtRXhpdjIiPgogPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4KICA8cmRmOkRlc2NyaXB0aW9uIHJkZjphYm91dD0iIgogICAgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIgogICAgeG1sbnM6dGlmZj0iaHR0cDovL25zLmFkb2JlLmNvbS90aWZmLzEuMC8iCiAgICB4bWxuczpkYz0iaHR0cDovL3B1cmwub3JnL2RjL2VsZW1lbnRzLzEuMS8iCiAgIHhtcDpDcmVhdG9yVG9vbD0iS2lwaS1wbHVnaW5zLTIuNS4wIgogICB0aWZmOlNvZnR3YXJlPSJLaXBpLXBsdWdpbnMtMi41LjAiPgogICA8ZGM6cmlnaHRzPgogICAgPHJkZjpBbHQ+CiAgICAgPHJkZjpsaSB4bWw6bGFuZz0ieC1kZWZhdWx0Ij5Db3B5cmlnaHQgKGMpIDIwMTQgU2Ftc3VuZyBFbGVjdHJvbmljcywgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMDogaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wPC9yZGY6bGk+CiAgICA8L3JkZjpBbHQ+CiAgIDwvZGM6cmlnaHRzPgogIDwvcmRmOkRlc2NyaXB0aW9uPgogPC9yZGY6UkRGPgo8L3g6eG1wbWV0YT4K/+0ArlBob3Rv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">
-        
-</body>
-</html>
-
diff --git a/adaptors/emscripten/wrappers/tests/dali-tests.css b/adaptors/emscripten/wrappers/tests/dali-tests.css
deleted file mode 100644 (file)
index 07a5d7b..0000000
+++ /dev/null
@@ -1,19 +0,0 @@
-div#overall {
-    padding-right: 550px;
-}
-
-iframe#daliframe {
-    position: fixed;
-    top: 2px;
-    right: 2px;
-    border: 1px solid;
-    width: 604px;
-    height: 800px;
-}
-
-#daliframe.qunit-pass {
-    border-color: #C6E746;
-}
-#daliframe.qunit-fail {
-    border-color: #EE5757;
-}
\ No newline at end of file
diff --git a/adaptors/emscripten/wrappers/tests/dali-tests.html b/adaptors/emscripten/wrappers/tests/dali-tests.html
deleted file mode 100644 (file)
index 2d244b3..0000000
+++ /dev/null
@@ -1,29 +0,0 @@
-<html>
-        <head>
-                 <meta charset="UTF-8"/>
-                 <title>DALi Browser API Regression Tests</title>
-                 <link rel="stylesheet" href="qunit-1.21.0.css" type="text/css" media="screen"/>
-
-        </head>
-        <body>
-                 <h1 id="qunit-header">DALi Browser Test Suite</h1>
-
-                 <div id="qunit-testrunner-toolbar"></div>
-
-                 <h2 id="qunit-userAgent">All</h2>
-                 <ol id="qunit-testresult">
-                               <li><a href="all.html">All</a></li>
-                 </ol>
-                 <h2 id="qunit-userAgent">Browser API</h2>
-                 <ol id="qunit-testresult">
-                               <li><a href="all.html?filter=Properties">Properties</a></li>
-                               <li><a href="all.html?filter=Geometry">Geometry</a></li>
-                               <li><a href="all.html?filter=Signals">Signals</a></li>
-                               <li><a href="all.html?filter=Math">Math</a></li>
-                               <li><a href="all.html?filter=Animation">Animation</a></li>
-                               <li><a href="all.html?filter=Shaders">Shaders</a></li>
-                               <li><a href="all.html?filter=Views">Views</a></li>
-                 </ol>
-                 
-        </body>
-</html>
diff --git a/adaptors/emscripten/wrappers/tests/geometry.js b/adaptors/emscripten/wrappers/tests/geometry.js
deleted file mode 100644 (file)
index 9b6cc55..0000000
+++ /dev/null
@@ -1,187 +0,0 @@
-
-QUnit.module("Geometry", {
-    setup : function() {
-        QUnit.stop();
-        var that = this;
-        this.cb = function(e) {
-          QUnit.ok(true, "Scene loaded");
-          var iframe = document.getElementById('daliframe');
-          that.doc =  iframe.contentDocument || iframe.contentWindow.document;
-          that.doc.Module.postDaliWrapperRun = function() {
-            dali = that.doc.Module;
-            QUnit.start();
-          };
-        };
-        loadDocument("dali-page.html"+window.location.search, this.cb);
-    },
-    teardown : function() {
-        var v = document.getElementById("daliframe");
-        v.removeEventListener("load", this.cb, true);
-    }
-});
-
-
-QUnit.test( "colour quad", function( assert ) {
-  var halfQuadSize = 0.5;
-
-  // using helper function to create property buffer
-  var verts = dali.createPropertyBuffer( {format: [ ["aPosition", dali.PropertyType.VECTOR3],
-                                                    ["aCol", dali.PropertyType.VECTOR4] ],
-                                          data: { "aPosition": [ [-halfQuadSize, -halfQuadSize, 0.0],
-                                                                 [+halfQuadSize, -halfQuadSize, 0.0],
-                                                                 [-halfQuadSize, +halfQuadSize, 0.0],
-                                                                 [+halfQuadSize, +halfQuadSize, 0.0]
-                                                               ],
-                                                  "aCol": [ [0, 0, 0, 1],
-                                                            [1, 0, 1, 1],
-                                                            [0, 1, 0, 1],
-                                                            [1, 1, 1, 1]
-                                                          ]
-                                                }
-                                         });
-
-  var indices = dali.createPropertyBuffer( { format: [ ["indices", dali.PropertyType.INTEGER]],
-                                             data: { "indices": [0, 3, 1, 0, 2, 3] } } ) ;
-
-  var geometry = new dali.Geometry();
-
-  assert.ok(verts);
-  assert.ok(indices);
-  assert.ok(geometry);
-
-  geometry.addVertexBuffer(verts);
-  geometry.setIndexBuffer(indices);
-
-  var vertex = "" +
-        "attribute mediump vec3 aPosition;" +
-        "attribute mediump vec4 aCol;" +
-        "uniform mediump mat4 uMvpMatrix;" +
-        "uniform mediump vec3 uSize;" +
-        "uniform lowp vec4 uColor;" +
-        "varying lowp vec4 vColor;" +
-        "" +
-        "void main()" +
-        "{" +
-        "  vColor = aCol * uColor;" +
-        "  mediump vec4 vertexPosition = vec4(aPosition,1.0);" +
-        "  vertexPosition.xyz *= uSize;" +
-        "  gl_Position = uMvpMatrix * vertexPosition;" +
-        "}";
-
-  var fragment = "" +
-        "varying lowp vec4 vColor;" +
-        "uniform lowp vec4 uColor;" +
-        "" +
-        "void main()" +
-        "{" +
-        "  gl_FragColor = vColor * uColor;" +
-        "}";
-
-  var shader = new dali.Shader(vertex, fragment, dali.ShaderHints.HINT_NONE);
-  assert.ok(shader);
-
-  var material = new dali.Material(shader);
-  assert.ok(material);
-
-  var renderer = new dali.Renderer(geometry, material);
-  assert.ok(renderer);
-
-  var actor = new dali.Actor();
-  assert.ok(actor);
-
-  actor.addRenderer(renderer);
-
-  dali.stage.add(actor);
-
-  actor.parentOrigin = [0.5, 0.5, 0.0];
-  actor.size = [100,100,1];
-
-});
-
-
-QUnit.test( "textured quad", function( assert ) {
-
-  var halfQuadSize = 0.5;
-
-  // using helper function to create property buffer
-  var verts = dali.createPropertyBuffer( {format: [ ["aPosition", dali.PropertyType.VECTOR3],
-                                                    ["aTexCoord", dali.PropertyType.VECTOR2] ],
-                                          data: { "aPosition": [ [-halfQuadSize, -halfQuadSize, 0.0],
-                                                                 [+halfQuadSize, -halfQuadSize, 0.0],
-                                                                 [-halfQuadSize, +halfQuadSize, 0.0],
-                                                                 [+halfQuadSize, +halfQuadSize, 0.0]
-                                                               ],
-                                                  "aTexCoord": [ [0, 0],
-                                                                 [1, 0],
-                                                                 [0, 1],
-                                                                 [1, 1]
-                                                               ]
-                                                }
-                                         });
-
-  var indices = dali.createPropertyBuffer( { format: [ ["indices", dali.PropertyType.INTEGER]],
-                                             data: { "indices": [0, 3, 1, 0, 2, 3] } } ) ;
-
-  var geometry = new dali.Geometry();
-
-  assert.ok(verts);
-  assert.ok(indices);
-  assert.ok(geometry);
-
-  geometry.addVertexBuffer(verts);
-  geometry.setIndexBuffer(indices);
-
-  var vertex = "" +
-        "// atributes\n" +
-        "attribute mediump vec3 aPosition;" +
-        "attribute mediump vec2 aTexCoord;\n" +
-        "// inbuilt\n" +
-        "uniform mediump mat4 uMvpMatrix;" +
-        "uniform mediump vec3 uSize;" +
-        "uniform lowp vec4 uColor;" +
-        "// varying\n" +
-        "varying mediump vec2 vTexCoord;\n" +
-        "" +
-        "void main()" +
-        "{" +
-        "  mediump vec4 vertexPosition = vec4(aPosition, 1.0);" +
-        "  vertexPosition.xyz *= uSize;" +
-        "  gl_Position = uMvpMatrix * vertexPosition;" +
-        "  vTexCoord = aTexCoord;\n" +
-        "}";
-
-  var fragment = "" +
-        "uniform lowp vec4 uColor;" +
-        "uniform sampler2D sTexture;\n" +
-        "varying mediump vec2 vTexCoord;\n" +
-        "\n" +
-        "void main()" +
-        "{" +
-        "  gl_FragColor = texture2D(sTexture, vTexCoord) * uColor;\n" +
-        "}";
-
-
-  var shader = new dali.Shader(vertex, fragment, dali.ShaderHints.HINT_NONE);
-  assert.ok(shader);
-
-  var material = new dali.Material(shader);
-  assert.ok(material);
-
-  var image = dali.unitTestEmbeddedImage() ;
-  assert.ok(image);
-  var sampler = new dali.Sampler();
-  material.addTexture(image, "sTexture", sampler);
-
-  var renderer = new dali.Renderer(geometry, material);
-  assert.ok(renderer);
-
-  var actor = new dali.Actor();
-
-  actor.addRenderer(renderer);
-
-  dali.stage.add(actor);
-
-  actor.parentOrigin = [0.5, 0.5, 0.0];
-  actor.size = [100,100,1];
-
-});
diff --git a/adaptors/emscripten/wrappers/tests/math.js b/adaptors/emscripten/wrappers/tests/math.js
deleted file mode 100644 (file)
index addfba3..0000000
+++ /dev/null
@@ -1,60 +0,0 @@
-function assertArray(assert, a, b, epsilon) {
-  assert.ok(a.length === b.length);
-  for (var i = 0, len = a.length; i < len; ++i) {
-    assert.ok(a[i] > b[i] - epsilon && a[i] < b[i] + epsilon);
-  }
-}
-
-QUnit.module("Math", {
-    setup : function() {
-        QUnit.stop();
-        var that = this;
-        this.cb = function(e) {
-          QUnit.ok(true, "Scene loaded");
-          var iframe = document.getElementById('daliframe');
-          that.doc =  iframe.contentDocument || iframe.contentWindow.document;
-          that.doc.Module.postDaliWrapperRun = function() {
-            dali = that.doc.Module;
-            QUnit.start();
-          };
-        };
-        loadDocument("dali-page.html"+window.location.search, this.cb);
-    },
-    teardown : function() {
-        var v = document.getElementById("daliframe");
-        v.removeEventListener("load", this.cb, true);
-    }
-});
-
-QUnit.test( "vector", function( assert ) {
-  assert.ok(dali.vectorLength([1, 2, 3, 4]) === Math.sqrt(1 * 1 + 2 * 2 + 3 * 3));
-  assert.ok(dali.vectorLengthSquared(dali.normalize([0, 0, 0, 1])) === 0);
-
-  var f = 2;
-  assert.ok(1 === dali.vectorLengthSquared(dali.normalize([Math.cos(f) * 10.0,
-                                                        Math.cos(f + 1.0) * 10.0,
-                                                        Math.cos(f + 2.0) * 10.0,
-                                                        1.0
-                                                       ])));
-  assertArray(assert, dali.vectorCross([0, 1, 0], [0, 0, 1]), [1, 0, 0], 0.001);
-
-  assertArray(assert, dali.vectorAdd([1, 2, 3], [2, 3, 4], [1, 1, 1]), [4, 6, 8], 0.001);
-
-});
-
-
-QUnit.test( "quaternion", function( assert ) {
-
-  assertArray(assert, dali.axisAngleToQuaternion([1.0, 2.0, 3.0, Math.PI / 3.0, Math.PI / 2.0]), [0.189, 0.378, 0.567, 0.707], 0.001);
-
-  assertArray(assert, dali.quaternionToAxisAngle([1.1, 3.4, 2.7, 0.932]), [3.03, 9.38, 7.45, 0.74],
-              0.01);
-
-  var mq = dali.vectorAdd(dali.vectorCross([0.045, 0.443, 0.432], [0.612, 0.344, -0.144]),
-                          dali.vectorByScalar([0.612, 0.344, -0.144], 0.784),
-                          dali.vectorByScalar([0.045, 0.443, 0.432], 0.697));
-
-  assertArray(assert, dali.quatByQuat([0.045, 0.443, 0.432, 0.784], [0.612, 0.344, -0.144, 0.697]), [mq[0], mq[1], mq[2], (0.784 * 0.697) - dali.vectorDot([0.045, 0.443, 0.432], [0.612, 0.344, -0.144])],
-              0.001);
-
-});
diff --git a/adaptors/emscripten/wrappers/tests/properties.js b/adaptors/emscripten/wrappers/tests/properties.js
deleted file mode 100644 (file)
index 194889f..0000000
+++ /dev/null
@@ -1,132 +0,0 @@
-
-QUnit.module("Properties", {
-    setup : function() {
-        QUnit.stop();
-        var that = this;
-        this.cb = function(e) {
-          QUnit.ok(true, "Scene loaded");
-          var iframe = document.getElementById('daliframe');
-          that.doc =  iframe.contentDocument || iframe.contentWindow.document;
-          that.doc.Module.postDaliWrapperRun = function() {
-            dali = that.doc.Module;
-            QUnit.start();
-          };
-        };
-        loadDocument("dali-page.html"+window.location.search, this.cb);
-    },
-    teardown : function() {
-        var v = document.getElementById("daliframe");
-        v.removeEventListener("load", this.cb, true);
-    }
-});
-
-QUnit.test( "dotted property access", function( assert ) {
-
-  var actor = new dali.Actor();
-
-  assert.ok( "" === actor.name );
-  assert.ok( compareArrays(actor.position, [0, 0, 0]) );
-  assert.ok( compareArrays(actor.parentOrigin, [0, 0, 0.5]) );
-
-});
-
-QUnit.test( "hierarchy", function( assert ) {
-
-  var actor = new dali.Actor();
-  actor.parentOrigin = [0.5, 0.5, 0.5];
-  actor.anchorPoint = [0.5, 0.5, 0.5];
-  actor.text = "actor";
-  actor.name = actor.text;
-  actor.size = [100, 100, 1];
-  actor.position = [0, 0, 10];
-  dali.stage.add(actor);
-
-  var hello = new dali.Actor();
-  hello.text = "hello";
-  hello.name = hello.text;
-  actor.add(hello);
-
-  var hellochild = new dali.Actor();
-  hellochild.text = "hello-child";
-  hellochild.name = hellochild.text;
-  hello.add(hellochild);
-
-  var hellochild2 = new dali.Actor();
-  hellochild2.text = "hello-child2";
-  hellochild2.name = hellochild2.text;
-  hello.add(hellochild2);
-
-  var hellochildchild = new dali.Actor();
-  hellochildchild.text = "hello-child-child1";
-  hellochildchild.name = "hello-child-child1";
-  hellochildchild.name = hellochildchild.text;
-  hellochild.add(hellochildchild);
-
-
-  var depthfirst = actor.findAllChildren();
-
-  assert.ok(actor.getChildCount() === 1);
-
-  var directChildren = actor.directChildren();
-
-  assert.ok(directChildren.length === 1);
-  assert.ok(directChildren[0].getId() === hello.getId());
-
-  actor.position = [100, 100, 0];
-
-  var root = dali.stage.getRootLayer(); //rootRotationActor;
-
-  actor.remove(hello);
-  assert.ok(actor.getChildCount() === 0);
-
-  actor.add(hello);
-  assert.ok(actor.getChildCount() === 1);
-
-  var rootLayerCount = root.getChildCount();
-  dali.stage.remove(actor); // check these don't assert
-  assert.ok(root.getChildCount() === rootLayerCount - 1);
-
-  dali.stage.add(actor);
-  assert.ok(root.getChildCount() === rootLayerCount);
-
-  assert.ok(root.findChildByName("none") === null);
-
-});
-
-QUnit.test( "register property", function( assert ) {
-  var s = dali.stage;
-  var root = s.getRootLayer(); //rootRotationActor;
-
-  var another = new dali.Actor();
-  another.parentOrigin = [0.5, 0.5, 0.5];
-  another.anchorPoint = [0.5, 0.5, 0.5];
-  another.text = "peppa";
-  another.name = another.text;
-  another.size = [100, 100, 1];
-  another.position = [-50, 100, 0];
-  root.add(another);
-
-  var c = root.getChildAt(root.getChildCount() - 1);
-  //var n = c.getChildCount();
-  var p = c.getParent();
-  assert.ok(p.getId() == root.getId());
-
-  var matrix = c.worldMatrix;
-
-  assert.ok(matrix.length === 16);
-
-});
-
-QUnit.test( "get/set", function( assert ) {
-  var s = dali.stage;
-  threeSquares();
-  var col = {};
-  collectByName(col);
-  var actor = col.red;
-  var p = actor.position;
-  actor.position = [1, 1, 1];
-  assert.ok(compareArrays(actor.position, [1, 1, 1]));
-  actor.position = [3, 3, 3];
-  assert.ok(compareArrays(actor.position, [3, 3, 3]));
-  actor.position = p;
-});
diff --git a/adaptors/emscripten/wrappers/tests/qunit/qunit-1.21.0.css b/adaptors/emscripten/wrappers/tests/qunit/qunit-1.21.0.css
deleted file mode 100644 (file)
index b23d647..0000000
+++ /dev/null
@@ -1,305 +0,0 @@
-/*!
- * QUnit 1.21.0
- * https://qunitjs.com/
- *
- * Copyright jQuery Foundation and other contributors
- * Released under the MIT license
- * https://jquery.org/license
- *
- * Date: 2016-02-01T13:07Z
- */
-
-/** Font Family and Sizes */
-
-#qunit-tests, #qunit-header, #qunit-banner, #qunit-testrunner-toolbar, #qunit-filteredTest, #qunit-userAgent, #qunit-testresult {
-       font-family: "Helvetica Neue Light", "HelveticaNeue-Light", "Helvetica Neue", Calibri, Helvetica, Arial, sans-serif;
-}
-
-#qunit-testrunner-toolbar, #qunit-filteredTest, #qunit-userAgent, #qunit-testresult, #qunit-tests li { font-size: small; }
-#qunit-tests { font-size: smaller; }
-
-
-/** Resets */
-
-#qunit-tests, #qunit-header, #qunit-banner, #qunit-filteredTest, #qunit-userAgent, #qunit-testresult, #qunit-modulefilter {
-       margin: 0;
-       padding: 0;
-}
-
-
-/** Header */
-
-#qunit-header {
-       padding: 0.5em 0 0.5em 1em;
-
-       color: #8699A4;
-       background-color: #0D3349;
-
-       font-size: 1.5em;
-       line-height: 1em;
-       font-weight: 400;
-
-       border-radius: 5px 5px 0 0;
-}
-
-#qunit-header a {
-       text-decoration: none;
-       color: #C2CCD1;
-}
-
-#qunit-header a:hover,
-#qunit-header a:focus {
-       color: #FFF;
-}
-
-#qunit-testrunner-toolbar label {
-       display: inline-block;
-       padding: 0 0.5em 0 0.1em;
-}
-
-#qunit-banner {
-       height: 5px;
-}
-
-#qunit-testrunner-toolbar {
-       padding: 0.5em 1em 0.5em 1em;
-       color: #5E740B;
-       background-color: #EEE;
-       overflow: hidden;
-}
-
-#qunit-filteredTest {
-       padding: 0.5em 1em 0.5em 1em;
-       background-color: #F4FF77;
-       color: #366097;
-}
-
-#qunit-userAgent {
-       padding: 0.5em 1em 0.5em 1em;
-       background-color: #2B81AF;
-       color: #FFF;
-       text-shadow: rgba(0, 0, 0, 0.5) 2px 2px 1px;
-}
-
-#qunit-modulefilter-container {
-       float: right;
-       padding: 0.2em;
-}
-
-.qunit-url-config {
-       display: inline-block;
-       padding: 0.1em;
-}
-
-.qunit-filter {
-       display: block;
-       float: right;
-       margin-left: 1em;
-}
-
-/** Tests: Pass/Fail */
-
-#qunit-tests {
-       list-style-position: inside;
-}
-
-#qunit-tests li {
-       padding: 0.4em 1em 0.4em 1em;
-       border-bottom: 1px solid #FFF;
-       list-style-position: inside;
-}
-
-#qunit-tests > li {
-       display: none;
-}
-
-#qunit-tests li.running,
-#qunit-tests li.pass,
-#qunit-tests li.fail,
-#qunit-tests li.skipped {
-       display: list-item;
-}
-
-#qunit-tests.hidepass {
-       position: relative;
-}
-
-#qunit-tests.hidepass li.running,
-#qunit-tests.hidepass li.pass {
-       visibility: hidden;
-       position: absolute;
-       width:   0;
-       height:  0;
-       padding: 0;
-       border:  0;
-       margin:  0;
-}
-
-#qunit-tests li strong {
-       cursor: pointer;
-}
-
-#qunit-tests li.skipped strong {
-       cursor: default;
-}
-
-#qunit-tests li a {
-       padding: 0.5em;
-       color: #C2CCD1;
-       text-decoration: none;
-}
-
-#qunit-tests li p a {
-       padding: 0.25em;
-       color: #6B6464;
-}
-#qunit-tests li a:hover,
-#qunit-tests li a:focus {
-       color: #000;
-}
-
-#qunit-tests li .runtime {
-       float: right;
-       font-size: smaller;
-}
-
-.qunit-assert-list {
-       margin-top: 0.5em;
-       padding: 0.5em;
-
-       background-color: #FFF;
-
-       border-radius: 5px;
-}
-
-.qunit-source {
-       margin: 0.6em 0 0.3em;
-}
-
-.qunit-collapsed {
-       display: none;
-}
-
-#qunit-tests table {
-       border-collapse: collapse;
-       margin-top: 0.2em;
-}
-
-#qunit-tests th {
-       text-align: right;
-       vertical-align: top;
-       padding: 0 0.5em 0 0;
-}
-
-#qunit-tests td {
-       vertical-align: top;
-}
-
-#qunit-tests pre {
-       margin: 0;
-       white-space: pre-wrap;
-       word-wrap: break-word;
-}
-
-#qunit-tests del {
-       background-color: #E0F2BE;
-       color: #374E0C;
-       text-decoration: none;
-}
-
-#qunit-tests ins {
-       background-color: #FFCACA;
-       color: #500;
-       text-decoration: none;
-}
-
-/*** Test Counts */
-
-#qunit-tests b.counts                       { color: #000; }
-#qunit-tests b.passed                       { color: #5E740B; }
-#qunit-tests b.failed                       { color: #710909; }
-
-#qunit-tests li li {
-       padding: 5px;
-       background-color: #FFF;
-       border-bottom: none;
-       list-style-position: inside;
-}
-
-/*** Passing Styles */
-
-#qunit-tests li li.pass {
-       color: #3C510C;
-       background-color: #FFF;
-       border-left: 10px solid #C6E746;
-}
-
-#qunit-tests .pass                          { color: #528CE0; background-color: #D2E0E6; }
-#qunit-tests .pass .test-name               { color: #366097; }
-
-#qunit-tests .pass .test-actual,
-#qunit-tests .pass .test-expected           { color: #999; }
-
-#qunit-banner.qunit-pass                    { background-color: #C6E746; }
-
-/*** Failing Styles */
-
-#qunit-tests li li.fail {
-       color: #710909;
-       background-color: #FFF;
-       border-left: 10px solid #EE5757;
-       white-space: pre;
-}
-
-#qunit-tests > li:last-child {
-       border-radius: 0 0 5px 5px;
-}
-
-#qunit-tests .fail                          { color: #000; background-color: #EE5757; }
-#qunit-tests .fail .test-name,
-#qunit-tests .fail .module-name             { color: #000; }
-
-#qunit-tests .fail .test-actual             { color: #EE5757; }
-#qunit-tests .fail .test-expected           { color: #008000; }
-
-#qunit-banner.qunit-fail                    { background-color: #EE5757; }
-
-/*** Skipped tests */
-
-#qunit-tests .skipped {
-       background-color: #EBECE9;
-}
-
-#qunit-tests .qunit-skipped-label {
-       background-color: #F4FF77;
-       display: inline-block;
-       font-style: normal;
-       color: #366097;
-       line-height: 1.8em;
-       padding: 0 0.5em;
-       margin: -0.4em 0.4em -0.4em 0;
-}
-
-/** Result */
-
-#qunit-testresult {
-       padding: 0.5em 1em 0.5em 1em;
-
-       color: #2B81AF;
-       background-color: #D2E0E6;
-
-       border-bottom: 1px solid #FFF;
-}
-#qunit-testresult .module-name {
-       font-weight: 700;
-}
-
-/** Fixture */
-
-#qunit-fixture {
-       position: absolute;
-       top: -10000px;
-       left: -10000px;
-       width: 1000px;
-       height: 1000px;
-}
diff --git a/adaptors/emscripten/wrappers/tests/qunit/qunit-1.21.0.js b/adaptors/emscripten/wrappers/tests/qunit/qunit-1.21.0.js
deleted file mode 100644 (file)
index 2d740f1..0000000
+++ /dev/null
@@ -1,4125 +0,0 @@
-/*!
- * QUnit 1.21.0
- * https://qunitjs.com/
- *
- * Copyright jQuery Foundation and other contributors
- * Released under the MIT license
- * https://jquery.org/license
- *
- * Date: 2016-02-01T13:07Z
- */
-
-(function( global ) {
-
-var QUnit = {};
-
-var Date = global.Date;
-var now = Date.now || function() {
-       return new Date().getTime();
-};
-
-var setTimeout = global.setTimeout;
-var clearTimeout = global.clearTimeout;
-
-// Store a local window from the global to allow direct references.
-var window = global.window;
-
-var defined = {
-       document: window && window.document !== undefined,
-       setTimeout: setTimeout !== undefined,
-       sessionStorage: (function() {
-               var x = "qunit-test-string";
-               try {
-                       sessionStorage.setItem( x, x );
-                       sessionStorage.removeItem( x );
-                       return true;
-               } catch ( e ) {
-                       return false;
-               }
-       }() )
-};
-
-var fileName = ( sourceFromStacktrace( 0 ) || "" ).replace( /(:\d+)+\)?/, "" ).replace( /.+\//, "" );
-var globalStartCalled = false;
-var runStarted = false;
-
-var toString = Object.prototype.toString,
-       hasOwn = Object.prototype.hasOwnProperty;
-
-// returns a new Array with the elements that are in a but not in b
-function diff( a, b ) {
-       var i, j,
-               result = a.slice();
-
-       for ( i = 0; i < result.length; i++ ) {
-               for ( j = 0; j < b.length; j++ ) {
-                       if ( result[ i ] === b[ j ] ) {
-                               result.splice( i, 1 );
-                               i--;
-                               break;
-                       }
-               }
-       }
-       return result;
-}
-
-// from jquery.js
-function inArray( elem, array ) {
-       if ( array.indexOf ) {
-               return array.indexOf( elem );
-       }
-
-       for ( var i = 0, length = array.length; i < length; i++ ) {
-               if ( array[ i ] === elem ) {
-                       return i;
-               }
-       }
-
-       return -1;
-}
-
-/**
- * Makes a clone of an object using only Array or Object as base,
- * and copies over the own enumerable properties.
- *
- * @param {Object} obj
- * @return {Object} New object with only the own properties (recursively).
- */
-function objectValues ( obj ) {
-       var key, val,
-               vals = QUnit.is( "array", obj ) ? [] : {};
-       for ( key in obj ) {
-               if ( hasOwn.call( obj, key ) ) {
-                       val = obj[ key ];
-                       vals[ key ] = val === Object( val ) ? objectValues( val ) : val;
-               }
-       }
-       return vals;
-}
-
-function extend( a, b, undefOnly ) {
-       for ( var prop in b ) {
-               if ( hasOwn.call( b, prop ) ) {
-
-                       // Avoid "Member not found" error in IE8 caused by messing with window.constructor
-                       // This block runs on every environment, so `global` is being used instead of `window`
-                       // to avoid errors on node.
-                       if ( prop !== "constructor" || a !== global ) {
-                               if ( b[ prop ] === undefined ) {
-                                       delete a[ prop ];
-                               } else if ( !( undefOnly && typeof a[ prop ] !== "undefined" ) ) {
-                                       a[ prop ] = b[ prop ];
-                               }
-                       }
-               }
-       }
-
-       return a;
-}
-
-function objectType( obj ) {
-       if ( typeof obj === "undefined" ) {
-               return "undefined";
-       }
-
-       // Consider: typeof null === object
-       if ( obj === null ) {
-               return "null";
-       }
-
-       var match = toString.call( obj ).match( /^\[object\s(.*)\]$/ ),
-               type = match && match[ 1 ];
-
-       switch ( type ) {
-               case "Number":
-                       if ( isNaN( obj ) ) {
-                               return "nan";
-                       }
-                       return "number";
-               case "String":
-               case "Boolean":
-               case "Array":
-               case "Set":
-               case "Map":
-               case "Date":
-               case "RegExp":
-               case "Function":
-               case "Symbol":
-                       return type.toLowerCase();
-       }
-       if ( typeof obj === "object" ) {
-               return "object";
-       }
-}
-
-// Safe object type checking
-function is( type, obj ) {
-       return QUnit.objectType( obj ) === type;
-}
-
-var getUrlParams = function() {
-       var i, current;
-       var urlParams = {};
-       var location = window.location;
-       var params = location.search.slice( 1 ).split( "&" );
-       var length = params.length;
-
-       if ( params[ 0 ] ) {
-               for ( i = 0; i < length; i++ ) {
-                       current = params[ i ].split( "=" );
-                       current[ 0 ] = decodeURIComponent( current[ 0 ] );
-
-                       // allow just a key to turn on a flag, e.g., test.html?noglobals
-                       current[ 1 ] = current[ 1 ] ? decodeURIComponent( current[ 1 ] ) : true;
-                       if ( urlParams[ current[ 0 ] ] ) {
-                               urlParams[ current[ 0 ] ] = [].concat( urlParams[ current[ 0 ] ], current[ 1 ] );
-                       } else {
-                               urlParams[ current[ 0 ] ] = current[ 1 ];
-                       }
-               }
-       }
-
-       return urlParams;
-};
-
-// Doesn't support IE6 to IE9, it will return undefined on these browsers
-// See also https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Error/Stack
-function extractStacktrace( e, offset ) {
-       offset = offset === undefined ? 4 : offset;
-
-       var stack, include, i;
-
-       if ( e.stack ) {
-               stack = e.stack.split( "\n" );
-               if ( /^error$/i.test( stack[ 0 ] ) ) {
-                       stack.shift();
-               }
-               if ( fileName ) {
-                       include = [];
-                       for ( i = offset; i < stack.length; i++ ) {
-                               if ( stack[ i ].indexOf( fileName ) !== -1 ) {
-                                       break;
-                               }
-                               include.push( stack[ i ] );
-                       }
-                       if ( include.length ) {
-                               return include.join( "\n" );
-                       }
-               }
-               return stack[ offset ];
-
-       // Support: Safari <=6 only
-       } else if ( e.sourceURL ) {
-
-               // exclude useless self-reference for generated Error objects
-               if ( /qunit.js$/.test( e.sourceURL ) ) {
-                       return;
-               }
-
-               // for actual exceptions, this is useful
-               return e.sourceURL + ":" + e.line;
-       }
-}
-
-function sourceFromStacktrace( offset ) {
-       var error = new Error();
-
-       // Support: Safari <=7 only, IE <=10 - 11 only
-       // Not all browsers generate the `stack` property for `new Error()`, see also #636
-       if ( !error.stack ) {
-               try {
-                       throw error;
-               } catch ( err ) {
-                       error = err;
-               }
-       }
-
-       return extractStacktrace( error, offset );
-}
-
-/**
- * Config object: Maintain internal state
- * Later exposed as QUnit.config
- * `config` initialized at top of scope
- */
-var config = {
-       // The queue of tests to run
-       queue: [],
-
-       // block until document ready
-       blocking: true,
-
-       // by default, run previously failed tests first
-       // very useful in combination with "Hide passed tests" checked
-       reorder: true,
-
-       // by default, modify document.title when suite is done
-       altertitle: true,
-
-       // HTML Reporter: collapse every test except the first failing test
-       // If false, all failing tests will be expanded
-       collapse: true,
-
-       // by default, scroll to top of the page when suite is done
-       scrolltop: true,
-
-       // depth up-to which object will be dumped
-       maxDepth: 5,
-
-       // when enabled, all tests must call expect()
-       requireExpects: false,
-
-       // add checkboxes that are persisted in the query-string
-       // when enabled, the id is set to `true` as a `QUnit.config` property
-       urlConfig: [
-               {
-                       id: "hidepassed",
-                       label: "Hide passed tests",
-                       tooltip: "Only show tests and assertions that fail. Stored as query-strings."
-               },
-               {
-                       id: "noglobals",
-                       label: "Check for Globals",
-                       tooltip: "Enabling this will test if any test introduces new properties on the " +
-                               "global object (`window` in Browsers). Stored as query-strings."
-               },
-               {
-                       id: "notrycatch",
-                       label: "No try-catch",
-                       tooltip: "Enabling this will run tests outside of a try-catch block. Makes debugging " +
-                               "exceptions in IE reasonable. Stored as query-strings."
-               }
-       ],
-
-       // Set of all modules.
-       modules: [],
-
-       // Stack of nested modules
-       moduleStack: [],
-
-       // The first unnamed module
-       currentModule: {
-               name: "",
-               tests: []
-       },
-
-       callbacks: {}
-};
-
-var urlParams = defined.document ? getUrlParams() : {};
-
-// Push a loose unnamed module to the modules collection
-config.modules.push( config.currentModule );
-
-if ( urlParams.filter === true ) {
-       delete urlParams.filter;
-}
-
-// String search anywhere in moduleName+testName
-config.filter = urlParams.filter;
-
-config.testId = [];
-if ( urlParams.testId ) {
-       // Ensure that urlParams.testId is an array
-       urlParams.testId = decodeURIComponent( urlParams.testId ).split( "," );
-       for (var i = 0; i < urlParams.testId.length; i++ ) {
-               config.testId.push( urlParams.testId[ i ] );
-       }
-}
-
-var loggingCallbacks = {};
-
-// Register logging callbacks
-function registerLoggingCallbacks( obj ) {
-       var i, l, key,
-               callbackNames = [ "begin", "done", "log", "testStart", "testDone",
-                       "moduleStart", "moduleDone" ];
-
-       function registerLoggingCallback( key ) {
-               var loggingCallback = function( callback ) {
-                       if ( objectType( callback ) !== "function" ) {
-                               throw new Error(
-                                       "QUnit logging methods require a callback function as their first parameters."
-                               );
-                       }
-
-                       config.callbacks[ key ].push( callback );
-               };
-
-               // DEPRECATED: This will be removed on QUnit 2.0.0+
-               // Stores the registered functions allowing restoring
-               // at verifyLoggingCallbacks() if modified
-               loggingCallbacks[ key ] = loggingCallback;
-
-               return loggingCallback;
-       }
-
-       for ( i = 0, l = callbackNames.length; i < l; i++ ) {
-               key = callbackNames[ i ];
-
-               // Initialize key collection of logging callback
-               if ( objectType( config.callbacks[ key ] ) === "undefined" ) {
-                       config.callbacks[ key ] = [];
-               }
-
-               obj[ key ] = registerLoggingCallback( key );
-       }
-}
-
-function runLoggingCallbacks( key, args ) {
-       var i, l, callbacks;
-
-       callbacks = config.callbacks[ key ];
-       for ( i = 0, l = callbacks.length; i < l; i++ ) {
-               callbacks[ i ]( args );
-       }
-}
-
-// DEPRECATED: This will be removed on 2.0.0+
-// This function verifies if the loggingCallbacks were modified by the user
-// If so, it will restore it, assign the given callback and print a console warning
-function verifyLoggingCallbacks() {
-       var loggingCallback, userCallback;
-
-       for ( loggingCallback in loggingCallbacks ) {
-               if ( QUnit[ loggingCallback ] !== loggingCallbacks[ loggingCallback ] ) {
-
-                       userCallback = QUnit[ loggingCallback ];
-
-                       // Restore the callback function
-                       QUnit[ loggingCallback ] = loggingCallbacks[ loggingCallback ];
-
-                       // Assign the deprecated given callback
-                       QUnit[ loggingCallback ]( userCallback );
-
-                       if ( global.console && global.console.warn ) {
-                               global.console.warn(
-                                       "QUnit." + loggingCallback + " was replaced with a new value.\n" +
-                                       "Please, check out the documentation on how to apply logging callbacks.\n" +
-                                       "Reference: https://api.qunitjs.com/category/callbacks/"
-                               );
-                       }
-               }
-       }
-}
-
-( function() {
-       if ( !defined.document ) {
-               return;
-       }
-
-       // `onErrorFnPrev` initialized at top of scope
-       // Preserve other handlers
-       var onErrorFnPrev = window.onerror;
-
-       // Cover uncaught exceptions
-       // Returning true will suppress the default browser handler,
-       // returning false will let it run.
-       window.onerror = function( error, filePath, linerNr ) {
-               var ret = false;
-               if ( onErrorFnPrev ) {
-                       ret = onErrorFnPrev( error, filePath, linerNr );
-               }
-
-               // Treat return value as window.onerror itself does,
-               // Only do our handling if not suppressed.
-               if ( ret !== true ) {
-                       if ( QUnit.config.current ) {
-                               if ( QUnit.config.current.ignoreGlobalErrors ) {
-                                       return true;
-                               }
-                               QUnit.pushFailure( error, filePath + ":" + linerNr );
-                       } else {
-                               QUnit.test( "global failure", extend(function() {
-                                       QUnit.pushFailure( error, filePath + ":" + linerNr );
-                               }, { validTest: true } ) );
-                       }
-                       return false;
-               }
-
-               return ret;
-       };
-} )();
-
-QUnit.urlParams = urlParams;
-
-// Figure out if we're running the tests from a server or not
-QUnit.isLocal = !( defined.document && window.location.protocol !== "file:" );
-
-// Expose the current QUnit version
-QUnit.version = "1.21.0";
-
-extend( QUnit, {
-
-       // call on start of module test to prepend name to all tests
-       module: function( name, testEnvironment, executeNow ) {
-               var module, moduleFns;
-               var currentModule = config.currentModule;
-
-               if ( arguments.length === 2 ) {
-                       if ( testEnvironment instanceof Function ) {
-                               executeNow = testEnvironment;
-                               testEnvironment = undefined;
-                       }
-               }
-
-               // DEPRECATED: handles setup/teardown functions,
-               // beforeEach and afterEach should be used instead
-               if ( testEnvironment && testEnvironment.setup ) {
-                       testEnvironment.beforeEach = testEnvironment.setup;
-                       delete testEnvironment.setup;
-               }
-               if ( testEnvironment && testEnvironment.teardown ) {
-                       testEnvironment.afterEach = testEnvironment.teardown;
-                       delete testEnvironment.teardown;
-               }
-
-               module = createModule();
-
-               moduleFns = {
-                       beforeEach: setHook( module, "beforeEach" ),
-                       afterEach: setHook( module, "afterEach" )
-               };
-
-               if ( executeNow instanceof Function ) {
-                       config.moduleStack.push( module );
-                       setCurrentModule( module );
-                       executeNow.call( module.testEnvironment, moduleFns );
-                       config.moduleStack.pop();
-                       module = module.parentModule || currentModule;
-               }
-
-               setCurrentModule( module );
-
-               function createModule() {
-                       var parentModule = config.moduleStack.length ?
-                               config.moduleStack.slice( -1 )[ 0 ] : null;
-                       var moduleName = parentModule !== null ?
-                               [ parentModule.name, name ].join( " > " ) : name;
-                       var module = {
-                               name: moduleName,
-                               parentModule: parentModule,
-                               tests: []
-                       };
-
-                       var env = {};
-                       if ( parentModule ) {
-                               extend( env, parentModule.testEnvironment );
-                               delete env.beforeEach;
-                               delete env.afterEach;
-                       }
-                       extend( env, testEnvironment );
-                       module.testEnvironment = env;
-
-                       config.modules.push( module );
-                       return module;
-               }
-
-               function setCurrentModule( module ) {
-                       config.currentModule = module;
-               }
-
-       },
-
-       // DEPRECATED: QUnit.asyncTest() will be removed in QUnit 2.0.
-       asyncTest: asyncTest,
-
-       test: test,
-
-       skip: skip,
-
-       only: only,
-
-       // DEPRECATED: The functionality of QUnit.start() will be altered in QUnit 2.0.
-       // In QUnit 2.0, invoking it will ONLY affect the `QUnit.config.autostart` blocking behavior.
-       start: function( count ) {
-               var globalStartAlreadyCalled = globalStartCalled;
-
-               if ( !config.current ) {
-                       globalStartCalled = true;
-
-                       if ( runStarted ) {
-                               throw new Error( "Called start() outside of a test context while already started" );
-                       } else if ( globalStartAlreadyCalled || count > 1 ) {
-                               throw new Error( "Called start() outside of a test context too many times" );
-                       } else if ( config.autostart ) {
-                               throw new Error( "Called start() outside of a test context when " +
-                                       "QUnit.config.autostart was true" );
-                       } else if ( !config.pageLoaded ) {
-
-                               // The page isn't completely loaded yet, so bail out and let `QUnit.load` handle it
-                               config.autostart = true;
-                               return;
-                       }
-               } else {
-
-                       // If a test is running, adjust its semaphore
-                       config.current.semaphore -= count || 1;
-
-                       // If semaphore is non-numeric, throw error
-                       if ( isNaN( config.current.semaphore ) ) {
-                               config.current.semaphore = 0;
-
-                               QUnit.pushFailure(
-                                       "Called start() with a non-numeric decrement.",
-                                       sourceFromStacktrace( 2 )
-                               );
-                               return;
-                       }
-
-                       // Don't start until equal number of stop-calls
-                       if ( config.current.semaphore > 0 ) {
-                               return;
-                       }
-
-                       // throw an Error if start is called more often than stop
-                       if ( config.current.semaphore < 0 ) {
-                               config.current.semaphore = 0;
-
-                               QUnit.pushFailure(
-                                       "Called start() while already started (test's semaphore was 0 already)",
-                                       sourceFromStacktrace( 2 )
-                               );
-                               return;
-                       }
-               }
-
-               resumeProcessing();
-       },
-
-       // DEPRECATED: QUnit.stop() will be removed in QUnit 2.0.
-       stop: function( count ) {
-
-               // If there isn't a test running, don't allow QUnit.stop() to be called
-               if ( !config.current ) {
-                       throw new Error( "Called stop() outside of a test context" );
-               }
-
-               // If a test is running, adjust its semaphore
-               config.current.semaphore += count || 1;
-
-               pauseProcessing();
-       },
-
-       config: config,
-
-       is: is,
-
-       objectType: objectType,
-
-       extend: extend,
-
-       load: function() {
-               config.pageLoaded = true;
-
-               // Initialize the configuration options
-               extend( config, {
-                       stats: { all: 0, bad: 0 },
-                       moduleStats: { all: 0, bad: 0 },
-                       started: 0,
-                       updateRate: 1000,
-                       autostart: true,
-                       filter: ""
-               }, true );
-
-               config.blocking = false;
-
-               if ( config.autostart ) {
-                       resumeProcessing();
-               }
-       },
-
-       stack: function( offset ) {
-               offset = ( offset || 0 ) + 2;
-               return sourceFromStacktrace( offset );
-       }
-});
-
-registerLoggingCallbacks( QUnit );
-
-function begin() {
-       var i, l,
-               modulesLog = [];
-
-       // If the test run hasn't officially begun yet
-       if ( !config.started ) {
-
-               // Record the time of the test run's beginning
-               config.started = now();
-
-               verifyLoggingCallbacks();
-
-               // Delete the loose unnamed module if unused.
-               if ( config.modules[ 0 ].name === "" && config.modules[ 0 ].tests.length === 0 ) {
-                       config.modules.shift();
-               }
-
-               // Avoid unnecessary information by not logging modules' test environments
-               for ( i = 0, l = config.modules.length; i < l; i++ ) {
-                       modulesLog.push({
-                               name: config.modules[ i ].name,
-                               tests: config.modules[ i ].tests
-                       });
-               }
-
-               // The test run is officially beginning now
-               runLoggingCallbacks( "begin", {
-                       totalTests: Test.count,
-                       modules: modulesLog
-               });
-       }
-
-       config.blocking = false;
-       process( true );
-}
-
-function process( last ) {
-       function next() {
-               process( last );
-       }
-       var start = now();
-       config.depth = ( config.depth || 0 ) + 1;
-
-       while ( config.queue.length && !config.blocking ) {
-               if ( !defined.setTimeout || config.updateRate <= 0 ||
-                               ( ( now() - start ) < config.updateRate ) ) {
-                       if ( config.current ) {
-
-                               // Reset async tracking for each phase of the Test lifecycle
-                               config.current.usedAsync = false;
-                       }
-                       config.queue.shift()();
-               } else {
-                       setTimeout( next, 13 );
-                       break;
-               }
-       }
-       config.depth--;
-       if ( last && !config.blocking && !config.queue.length && config.depth === 0 ) {
-               done();
-       }
-}
-
-function pauseProcessing() {
-       config.blocking = true;
-
-       if ( config.testTimeout && defined.setTimeout ) {
-               clearTimeout( config.timeout );
-               config.timeout = setTimeout(function() {
-                       if ( config.current ) {
-                               config.current.semaphore = 0;
-                               QUnit.pushFailure( "Test timed out", sourceFromStacktrace( 2 ) );
-                       } else {
-                               throw new Error( "Test timed out" );
-                       }
-                       resumeProcessing();
-               }, config.testTimeout );
-       }
-}
-
-function resumeProcessing() {
-       runStarted = true;
-
-       // A slight delay to allow this iteration of the event loop to finish (more assertions, etc.)
-       if ( defined.setTimeout ) {
-               setTimeout(function() {
-                       if ( config.current && config.current.semaphore > 0 ) {
-                               return;
-                       }
-                       if ( config.timeout ) {
-                               clearTimeout( config.timeout );
-                       }
-
-                       begin();
-               }, 13 );
-       } else {
-               begin();
-       }
-}
-
-function done() {
-       var runtime, passed;
-
-       config.autorun = true;
-
-       // Log the last module results
-       if ( config.previousModule ) {
-               runLoggingCallbacks( "moduleDone", {
-                       name: config.previousModule.name,
-                       tests: config.previousModule.tests,
-                       failed: config.moduleStats.bad,
-                       passed: config.moduleStats.all - config.moduleStats.bad,
-                       total: config.moduleStats.all,
-                       runtime: now() - config.moduleStats.started
-               });
-       }
-       delete config.previousModule;
-
-       runtime = now() - config.started;
-       passed = config.stats.all - config.stats.bad;
-
-       runLoggingCallbacks( "done", {
-               failed: config.stats.bad,
-               passed: passed,
-               total: config.stats.all,
-               runtime: runtime
-       });
-}
-
-function setHook( module, hookName ) {
-       if ( module.testEnvironment === undefined ) {
-               module.testEnvironment = {};
-       }
-
-       return function( callback ) {
-               module.testEnvironment[ hookName ] = callback;
-       };
-}
-
-var focused = false;
-var priorityCount = 0;
-
-function Test( settings ) {
-       var i, l;
-
-       ++Test.count;
-
-       extend( this, settings );
-       this.assertions = [];
-       this.semaphore = 0;
-       this.usedAsync = false;
-       this.module = config.currentModule;
-       this.stack = sourceFromStacktrace( 3 );
-
-       // Register unique strings
-       for ( i = 0, l = this.module.tests; i < l.length; i++ ) {
-               if ( this.module.tests[ i ].name === this.testName ) {
-                       this.testName += " ";
-               }
-       }
-
-       this.testId = generateHash( this.module.name, this.testName );
-
-       this.module.tests.push({
-               name: this.testName,
-               testId: this.testId
-       });
-
-       if ( settings.skip ) {
-
-               // Skipped tests will fully ignore any sent callback
-               this.callback = function() {};
-               this.async = false;
-               this.expected = 0;
-       } else {
-               this.assert = new Assert( this );
-       }
-}
-
-Test.count = 0;
-
-Test.prototype = {
-       before: function() {
-               if (
-
-                       // Emit moduleStart when we're switching from one module to another
-                       this.module !== config.previousModule ||
-
-                               // They could be equal (both undefined) but if the previousModule property doesn't
-                               // yet exist it means this is the first test in a suite that isn't wrapped in a
-                               // module, in which case we'll just emit a moduleStart event for 'undefined'.
-                               // Without this, reporters can get testStart before moduleStart  which is a problem.
-                               !hasOwn.call( config, "previousModule" )
-               ) {
-                       if ( hasOwn.call( config, "previousModule" ) ) {
-                               runLoggingCallbacks( "moduleDone", {
-                                       name: config.previousModule.name,
-                                       tests: config.previousModule.tests,
-                                       failed: config.moduleStats.bad,
-                                       passed: config.moduleStats.all - config.moduleStats.bad,
-                                       total: config.moduleStats.all,
-                                       runtime: now() - config.moduleStats.started
-                               });
-                       }
-                       config.previousModule = this.module;
-                       config.moduleStats = { all: 0, bad: 0, started: now() };
-                       runLoggingCallbacks( "moduleStart", {
-                               name: this.module.name,
-                               tests: this.module.tests
-                       });
-               }
-
-               config.current = this;
-
-               if ( this.module.testEnvironment ) {
-                       delete this.module.testEnvironment.beforeEach;
-                       delete this.module.testEnvironment.afterEach;
-               }
-               this.testEnvironment = extend( {}, this.module.testEnvironment );
-
-               this.started = now();
-               runLoggingCallbacks( "testStart", {
-                       name: this.testName,
-                       module: this.module.name,
-                       testId: this.testId
-               });
-
-               if ( !config.pollution ) {
-                       saveGlobal();
-               }
-       },
-
-       run: function() {
-               var promise;
-
-               config.current = this;
-
-               if ( this.async ) {
-                       QUnit.stop();
-               }
-
-               this.callbackStarted = now();
-
-               if ( config.notrycatch ) {
-                       runTest( this );
-                       return;
-               }
-
-               try {
-                       runTest( this );
-               } catch ( e ) {
-                       this.pushFailure( "Died on test #" + ( this.assertions.length + 1 ) + " " +
-                               this.stack + ": " + ( e.message || e ), extractStacktrace( e, 0 ) );
-
-                       // else next test will carry the responsibility
-                       saveGlobal();
-
-                       // Restart the tests if they're blocking
-                       if ( config.blocking ) {
-                               QUnit.start();
-                       }
-               }
-
-               function runTest( test ) {
-                       promise = test.callback.call( test.testEnvironment, test.assert );
-                       test.resolvePromise( promise );
-               }
-       },
-
-       after: function() {
-               checkPollution();
-       },
-
-       queueHook: function( hook, hookName ) {
-               var promise,
-                       test = this;
-               return function runHook() {
-                       config.current = test;
-                       if ( config.notrycatch ) {
-                               callHook();
-                               return;
-                       }
-                       try {
-                               callHook();
-                       } catch ( error ) {
-                               test.pushFailure( hookName + " failed on " + test.testName + ": " +
-                               ( error.message || error ), extractStacktrace( error, 0 ) );
-                       }
-
-                       function callHook() {
-                               promise = hook.call( test.testEnvironment, test.assert );
-                               test.resolvePromise( promise, hookName );
-                       }
-               };
-       },
-
-       // Currently only used for module level hooks, can be used to add global level ones
-       hooks: function( handler ) {
-               var hooks = [];
-
-               function processHooks( test, module ) {
-                       if ( module.parentModule ) {
-                               processHooks( test, module.parentModule );
-                       }
-                       if ( module.testEnvironment &&
-                               QUnit.objectType( module.testEnvironment[ handler ] ) === "function" ) {
-                               hooks.push( test.queueHook( module.testEnvironment[ handler ], handler ) );
-                       }
-               }
-
-               // Hooks are ignored on skipped tests
-               if ( !this.skip ) {
-                       processHooks( this, this.module );
-               }
-               return hooks;
-       },
-
-       finish: function() {
-               config.current = this;
-               if ( config.requireExpects && this.expected === null ) {
-                       this.pushFailure( "Expected number of assertions to be defined, but expect() was " +
-                               "not called.", this.stack );
-               } else if ( this.expected !== null && this.expected !== this.assertions.length ) {
-                       this.pushFailure( "Expected " + this.expected + " assertions, but " +
-                               this.assertions.length + " were run", this.stack );
-               } else if ( this.expected === null && !this.assertions.length ) {
-                       this.pushFailure( "Expected at least one assertion, but none were run - call " +
-                               "expect(0) to accept zero assertions.", this.stack );
-               }
-
-               var i,
-                       bad = 0;
-
-               this.runtime = now() - this.started;
-               config.stats.all += this.assertions.length;
-               config.moduleStats.all += this.assertions.length;
-
-               for ( i = 0; i < this.assertions.length; i++ ) {
-                       if ( !this.assertions[ i ].result ) {
-                               bad++;
-                               config.stats.bad++;
-                               config.moduleStats.bad++;
-                       }
-               }
-
-               runLoggingCallbacks( "testDone", {
-                       name: this.testName,
-                       module: this.module.name,
-                       skipped: !!this.skip,
-                       failed: bad,
-                       passed: this.assertions.length - bad,
-                       total: this.assertions.length,
-                       runtime: this.runtime,
-
-                       // HTML Reporter use
-                       assertions: this.assertions,
-                       testId: this.testId,
-
-                       // Source of Test
-                       source: this.stack,
-
-                       // DEPRECATED: this property will be removed in 2.0.0, use runtime instead
-                       duration: this.runtime
-               });
-
-               // QUnit.reset() is deprecated and will be replaced for a new
-               // fixture reset function on QUnit 2.0/2.1.
-               // It's still called here for backwards compatibility handling
-               QUnit.reset();
-
-               config.current = undefined;
-       },
-
-       queue: function() {
-               var priority,
-                       test = this;
-
-               if ( !this.valid() ) {
-                       return;
-               }
-
-               function run() {
-
-                       // each of these can by async
-                       synchronize([
-                               function() {
-                                       test.before();
-                               },
-
-                               test.hooks( "beforeEach" ),
-                               function() {
-                                       test.run();
-                               },
-
-                               test.hooks( "afterEach" ).reverse(),
-
-                               function() {
-                                       test.after();
-                               },
-                               function() {
-                                       test.finish();
-                               }
-                       ]);
-               }
-
-               // Prioritize previously failed tests, detected from sessionStorage
-               priority = QUnit.config.reorder && defined.sessionStorage &&
-                               +sessionStorage.getItem( "qunit-test-" + this.module.name + "-" + this.testName );
-
-               return synchronize( run, priority );
-       },
-
-       push: function( result, actual, expected, message, negative ) {
-               var source,
-                       details = {
-                               module: this.module.name,
-                               name: this.testName,
-                               result: result,
-                               message: message,
-                               actual: actual,
-                               expected: expected,
-                               testId: this.testId,
-                               negative: negative || false,
-                               runtime: now() - this.started
-                       };
-
-               if ( !result ) {
-                       source = sourceFromStacktrace();
-
-                       if ( source ) {
-                               details.source = source;
-                       }
-               }
-
-               runLoggingCallbacks( "log", details );
-
-               this.assertions.push({
-                       result: !!result,
-                       message: message
-               });
-       },
-
-       pushFailure: function( message, source, actual ) {
-               if ( !( this instanceof Test ) ) {
-                       throw new Error( "pushFailure() assertion outside test context, was " +
-                               sourceFromStacktrace( 2 ) );
-               }
-
-               var details = {
-                               module: this.module.name,
-                               name: this.testName,
-                               result: false,
-                               message: message || "error",
-                               actual: actual || null,
-                               testId: this.testId,
-                               runtime: now() - this.started
-                       };
-
-               if ( source ) {
-                       details.source = source;
-               }
-
-               runLoggingCallbacks( "log", details );
-
-               this.assertions.push({
-                       result: false,
-                       message: message
-               });
-       },
-
-       resolvePromise: function( promise, phase ) {
-               var then, message,
-                       test = this;
-               if ( promise != null ) {
-                       then = promise.then;
-                       if ( QUnit.objectType( then ) === "function" ) {
-                               QUnit.stop();
-                               then.call(
-                                       promise,
-                                       function() { QUnit.start(); },
-                                       function( error ) {
-                                               message = "Promise rejected " +
-                                                       ( !phase ? "during" : phase.replace( /Each$/, "" ) ) +
-                                                       " " + test.testName + ": " + ( error.message || error );
-                                               test.pushFailure( message, extractStacktrace( error, 0 ) );
-
-                                               // else next test will carry the responsibility
-                                               saveGlobal();
-
-                                               // Unblock
-                                               QUnit.start();
-                                       }
-                               );
-                       }
-               }
-       },
-
-       valid: function() {
-               var filter = config.filter,
-                       regexFilter = /^(!?)\/([\w\W]*)\/(i?$)/.exec( filter ),
-                       module = QUnit.urlParams.module && QUnit.urlParams.module.toLowerCase(),
-                       fullName = ( this.module.name + ": " + this.testName );
-
-               function testInModuleChain( testModule ) {
-                       var testModuleName = testModule.name ? testModule.name.toLowerCase() : null;
-                       if ( testModuleName === module ) {
-                               return true;
-                       } else if ( testModule.parentModule ) {
-                               return testInModuleChain( testModule.parentModule );
-                       } else {
-                               return false;
-                       }
-               }
-
-               // Internally-generated tests are always valid
-               if ( this.callback && this.callback.validTest ) {
-                       return true;
-               }
-
-               if ( config.testId.length > 0 && inArray( this.testId, config.testId ) < 0 ) {
-                       return false;
-               }
-
-               if ( module && !testInModuleChain( this.module ) ) {
-                       return false;
-               }
-
-               if ( !filter ) {
-                       return true;
-               }
-
-               return regexFilter ?
-                       this.regexFilter( !!regexFilter[1], regexFilter[2], regexFilter[3], fullName ) :
-                       this.stringFilter( filter, fullName );
-       },
-
-       regexFilter: function( exclude, pattern, flags, fullName ) {
-               var regex = new RegExp( pattern, flags );
-               var match = regex.test( fullName );
-
-               return match !== exclude;
-       },
-
-       stringFilter: function( filter, fullName ) {
-               filter = filter.toLowerCase();
-               fullName = fullName.toLowerCase();
-
-               var include = filter.charAt( 0 ) !== "!";
-               if ( !include ) {
-                       filter = filter.slice( 1 );
-               }
-
-               // If the filter matches, we need to honour include
-               if ( fullName.indexOf( filter ) !== -1 ) {
-                       return include;
-               }
-
-               // Otherwise, do the opposite
-               return !include;
-       }
-};
-
-// Resets the test setup. Useful for tests that modify the DOM.
-/*
-DEPRECATED: Use multiple tests instead of resetting inside a test.
-Use testStart or testDone for custom cleanup.
-This method will throw an error in 2.0, and will be removed in 2.1
-*/
-QUnit.reset = function() {
-
-       // Return on non-browser environments
-       // This is necessary to not break on node tests
-       if ( !defined.document ) {
-               return;
-       }
-
-       var fixture = defined.document && document.getElementById &&
-                       document.getElementById( "qunit-fixture" );
-
-       if ( fixture ) {
-               fixture.innerHTML = config.fixture;
-       }
-};
-
-QUnit.pushFailure = function() {
-       if ( !QUnit.config.current ) {
-               throw new Error( "pushFailure() assertion outside test context, in " +
-                       sourceFromStacktrace( 2 ) );
-       }
-
-       // Gets current test obj
-       var currentTest = QUnit.config.current;
-
-       return currentTest.pushFailure.apply( currentTest, arguments );
-};
-
-// Based on Java's String.hashCode, a simple but not
-// rigorously collision resistant hashing function
-function generateHash( module, testName ) {
-       var hex,
-               i = 0,
-               hash = 0,
-               str = module + "\x1C" + testName,
-               len = str.length;
-
-       for ( ; i < len; i++ ) {
-               hash  = ( ( hash << 5 ) - hash ) + str.charCodeAt( i );
-               hash |= 0;
-       }
-
-       // Convert the possibly negative integer hash code into an 8 character hex string, which isn't
-       // strictly necessary but increases user understanding that the id is a SHA-like hash
-       hex = ( 0x100000000 + hash ).toString( 16 );
-       if ( hex.length < 8 ) {
-               hex = "0000000" + hex;
-       }
-
-       return hex.slice( -8 );
-}
-
-function synchronize( callback, priority ) {
-       var last = !priority;
-
-       if ( QUnit.objectType( callback ) === "array" ) {
-               while ( callback.length ) {
-                       synchronize( callback.shift() );
-               }
-               return;
-       }
-
-       if ( priority ) {
-               config.queue.splice( priorityCount++, 0, callback );
-       } else {
-               config.queue.push( callback );
-       }
-
-       if ( config.autorun && !config.blocking ) {
-               process( last );
-       }
-}
-
-function saveGlobal() {
-       config.pollution = [];
-
-       if ( config.noglobals ) {
-               for ( var key in global ) {
-                       if ( hasOwn.call( global, key ) ) {
-
-                               // in Opera sometimes DOM element ids show up here, ignore them
-                               if ( /^qunit-test-output/.test( key ) ) {
-                                       continue;
-                               }
-                               config.pollution.push( key );
-                       }
-               }
-       }
-}
-
-function checkPollution() {
-       var newGlobals,
-               deletedGlobals,
-               old = config.pollution;
-
-       saveGlobal();
-
-       newGlobals = diff( config.pollution, old );
-       if ( newGlobals.length > 0 ) {
-               QUnit.pushFailure( "Introduced global variable(s): " + newGlobals.join( ", " ) );
-       }
-
-       deletedGlobals = diff( old, config.pollution );
-       if ( deletedGlobals.length > 0 ) {
-               QUnit.pushFailure( "Deleted global variable(s): " + deletedGlobals.join( ", " ) );
-       }
-}
-
-// Will be exposed as QUnit.asyncTest
-function asyncTest( testName, expected, callback ) {
-       if ( arguments.length === 2 ) {
-               callback = expected;
-               expected = null;
-       }
-
-       QUnit.test( testName, expected, callback, true );
-}
-
-// Will be exposed as QUnit.test
-function test( testName, expected, callback, async ) {
-       if ( focused )  { return; }
-
-       var newTest;
-
-       if ( arguments.length === 2 ) {
-               callback = expected;
-               expected = null;
-       }
-
-       newTest = new Test({
-               testName: testName,
-               expected: expected,
-               async: async,
-               callback: callback
-       });
-
-       newTest.queue();
-}
-
-// Will be exposed as QUnit.skip
-function skip( testName ) {
-       if ( focused )  { return; }
-
-       var test = new Test({
-               testName: testName,
-               skip: true
-       });
-
-       test.queue();
-}
-
-// Will be exposed as QUnit.only
-function only( testName, expected, callback, async ) {
-       var newTest;
-
-       if ( focused )  { return; }
-
-       QUnit.config.queue.length = 0;
-       focused = true;
-
-       if ( arguments.length === 2 ) {
-               callback = expected;
-               expected = null;
-       }
-
-       newTest = new Test({
-               testName: testName,
-               expected: expected,
-               async: async,
-               callback: callback
-       });
-
-       newTest.queue();
-}
-
-function Assert( testContext ) {
-       this.test = testContext;
-}
-
-// Assert helpers
-QUnit.assert = Assert.prototype = {
-
-       // Specify the number of expected assertions to guarantee that failed test
-       // (no assertions are run at all) don't slip through.
-       expect: function( asserts ) {
-               if ( arguments.length === 1 ) {
-                       this.test.expected = asserts;
-               } else {
-                       return this.test.expected;
-               }
-       },
-
-       // Increment this Test's semaphore counter, then return a function that
-       // decrements that counter a maximum of once.
-       async: function( count ) {
-               var test = this.test,
-                       popped = false,
-                       acceptCallCount = count;
-
-               if ( typeof acceptCallCount === "undefined" ) {
-                       acceptCallCount = 1;
-               }
-
-               test.semaphore += 1;
-               test.usedAsync = true;
-               pauseProcessing();
-
-               return function done() {
-
-                       if ( popped ) {
-                               test.pushFailure( "Too many calls to the `assert.async` callback",
-                                       sourceFromStacktrace( 2 ) );
-                               return;
-                       }
-                       acceptCallCount -= 1;
-                       if ( acceptCallCount > 0 ) {
-                               return;
-                       }
-
-                       test.semaphore -= 1;
-                       popped = true;
-                       resumeProcessing();
-               };
-       },
-
-       // Exports test.push() to the user API
-       push: function( /* result, actual, expected, message, negative */ ) {
-               var assert = this,
-                       currentTest = ( assert instanceof Assert && assert.test ) || QUnit.config.current;
-
-               // Backwards compatibility fix.
-               // Allows the direct use of global exported assertions and QUnit.assert.*
-               // Although, it's use is not recommended as it can leak assertions
-               // to other tests from async tests, because we only get a reference to the current test,
-               // not exactly the test where assertion were intended to be called.
-               if ( !currentTest ) {
-                       throw new Error( "assertion outside test context, in " + sourceFromStacktrace( 2 ) );
-               }
-
-               if ( currentTest.usedAsync === true && currentTest.semaphore === 0 ) {
-                       currentTest.pushFailure( "Assertion after the final `assert.async` was resolved",
-                               sourceFromStacktrace( 2 ) );
-
-                       // Allow this assertion to continue running anyway...
-               }
-
-               if ( !( assert instanceof Assert ) ) {
-                       assert = currentTest.assert;
-               }
-               return assert.test.push.apply( assert.test, arguments );
-       },
-
-       ok: function( result, message ) {
-               message = message || ( result ? "okay" : "failed, expected argument to be truthy, was: " +
-                       QUnit.dump.parse( result ) );
-               this.push( !!result, result, true, message );
-       },
-
-       notOk: function( result, message ) {
-               message = message || ( !result ? "okay" : "failed, expected argument to be falsy, was: " +
-                       QUnit.dump.parse( result ) );
-               this.push( !result, result, false, message );
-       },
-
-       equal: function( actual, expected, message ) {
-               /*jshint eqeqeq:false */
-               this.push( expected == actual, actual, expected, message );
-       },
-
-       notEqual: function( actual, expected, message ) {
-               /*jshint eqeqeq:false */
-               this.push( expected != actual, actual, expected, message, true );
-       },
-
-       propEqual: function( actual, expected, message ) {
-               actual = objectValues( actual );
-               expected = objectValues( expected );
-               this.push( QUnit.equiv( actual, expected ), actual, expected, message );
-       },
-
-       notPropEqual: function( actual, expected, message ) {
-               actual = objectValues( actual );
-               expected = objectValues( expected );
-               this.push( !QUnit.equiv( actual, expected ), actual, expected, message, true );
-       },
-
-       deepEqual: function( actual, expected, message ) {
-               this.push( QUnit.equiv( actual, expected ), actual, expected, message );
-       },
-
-       notDeepEqual: function( actual, expected, message ) {
-               this.push( !QUnit.equiv( actual, expected ), actual, expected, message, true );
-       },
-
-       strictEqual: function( actual, expected, message ) {
-               this.push( expected === actual, actual, expected, message );
-       },
-
-       notStrictEqual: function( actual, expected, message ) {
-               this.push( expected !== actual, actual, expected, message, true );
-       },
-
-       "throws": function( block, expected, message ) {
-               var actual, expectedType,
-                       expectedOutput = expected,
-                       ok = false,
-                       currentTest = ( this instanceof Assert && this.test ) || QUnit.config.current;
-
-               // 'expected' is optional unless doing string comparison
-               if ( message == null && typeof expected === "string" ) {
-                       message = expected;
-                       expected = null;
-               }
-
-               currentTest.ignoreGlobalErrors = true;
-               try {
-                       block.call( currentTest.testEnvironment );
-               } catch (e) {
-                       actual = e;
-               }
-               currentTest.ignoreGlobalErrors = false;
-
-               if ( actual ) {
-                       expectedType = QUnit.objectType( expected );
-
-                       // we don't want to validate thrown error
-                       if ( !expected ) {
-                               ok = true;
-                               expectedOutput = null;
-
-                       // expected is a regexp
-                       } else if ( expectedType === "regexp" ) {
-                               ok = expected.test( errorString( actual ) );
-
-                       // expected is a string
-                       } else if ( expectedType === "string" ) {
-                               ok = expected === errorString( actual );
-
-                       // expected is a constructor, maybe an Error constructor
-                       } else if ( expectedType === "function" && actual instanceof expected ) {
-                               ok = true;
-
-                       // expected is an Error object
-                       } else if ( expectedType === "object" ) {
-                               ok = actual instanceof expected.constructor &&
-                                       actual.name === expected.name &&
-                                       actual.message === expected.message;
-
-                       // expected is a validation function which returns true if validation passed
-                       } else if ( expectedType === "function" && expected.call( {}, actual ) === true ) {
-                               expectedOutput = null;
-                               ok = true;
-                       }
-               }
-
-               currentTest.assert.push( ok, actual, expectedOutput, message );
-       }
-};
-
-// Provide an alternative to assert.throws(), for environments that consider throws a reserved word
-// Known to us are: Closure Compiler, Narwhal
-(function() {
-       /*jshint sub:true */
-       Assert.prototype.raises = Assert.prototype[ "throws" ];
-}());
-
-function errorString( error ) {
-       var name, message,
-               resultErrorString = error.toString();
-       if ( resultErrorString.substring( 0, 7 ) === "[object" ) {
-               name = error.name ? error.name.toString() : "Error";
-               message = error.message ? error.message.toString() : "";
-               if ( name && message ) {
-                       return name + ": " + message;
-               } else if ( name ) {
-                       return name;
-               } else if ( message ) {
-                       return message;
-               } else {
-                       return "Error";
-               }
-       } else {
-               return resultErrorString;
-       }
-}
-
-// Test for equality any JavaScript type.
-// Author: Philippe Rathé <prathe@gmail.com>
-QUnit.equiv = (function() {
-
-       // Stack to decide between skip/abort functions
-       var callers = [];
-
-       // Stack to avoiding loops from circular referencing
-       var parents = [];
-       var parentsB = [];
-
-       var getProto = Object.getPrototypeOf || function( obj ) {
-
-               /*jshint proto: true */
-               return obj.__proto__;
-       };
-
-       function useStrictEquality( b, a ) {
-
-               // To catch short annotation VS 'new' annotation of a declaration. e.g.:
-               // `var i = 1;`
-               // `var j = new Number(1);`
-               if ( typeof a === "object" ) {
-                       a = a.valueOf();
-               }
-               if ( typeof b === "object" ) {
-                       b = b.valueOf();
-               }
-
-               return a === b;
-       }
-
-       function compareConstructors( a, b ) {
-               var protoA = getProto( a );
-               var protoB = getProto( b );
-
-               // Comparing constructors is more strict than using `instanceof`
-               if ( a.constructor === b.constructor ) {
-                       return true;
-               }
-
-               // Ref #851
-               // If the obj prototype descends from a null constructor, treat it
-               // as a null prototype.
-               if ( protoA && protoA.constructor === null ) {
-                       protoA = null;
-               }
-               if ( protoB && protoB.constructor === null ) {
-                       protoB = null;
-               }
-
-               // Allow objects with no prototype to be equivalent to
-               // objects with Object as their constructor.
-               if ( ( protoA === null && protoB === Object.prototype ) ||
-                               ( protoB === null && protoA === Object.prototype ) ) {
-                       return true;
-               }
-
-               return false;
-       }
-
-       function getRegExpFlags( regexp ) {
-               return "flags" in regexp ? regexp.flags : regexp.toString().match( /[gimuy]*$/ )[ 0 ];
-       }
-
-       var callbacks = {
-               "string": useStrictEquality,
-               "boolean": useStrictEquality,
-               "number": useStrictEquality,
-               "null": useStrictEquality,
-               "undefined": useStrictEquality,
-               "symbol": useStrictEquality,
-               "date": useStrictEquality,
-
-               "nan": function() {
-                       return true;
-               },
-
-               "regexp": function( b, a ) {
-                       return a.source === b.source &&
-
-                               // Include flags in the comparison
-                               getRegExpFlags( a ) === getRegExpFlags( b );
-               },
-
-               // - skip when the property is a method of an instance (OOP)
-               // - abort otherwise,
-               // initial === would have catch identical references anyway
-               "function": function() {
-                       var caller = callers[ callers.length - 1 ];
-                       return caller !== Object && typeof caller !== "undefined";
-               },
-
-               "array": function( b, a ) {
-                       var i, j, len, loop, aCircular, bCircular;
-
-                       len = a.length;
-                       if ( len !== b.length ) {
-                               // safe and faster
-                               return false;
-                       }
-
-                       // Track reference to avoid circular references
-                       parents.push( a );
-                       parentsB.push( b );
-                       for ( i = 0; i < len; i++ ) {
-                               loop = false;
-                               for ( j = 0; j < parents.length; j++ ) {
-                                       aCircular = parents[ j ] === a[ i ];
-                                       bCircular = parentsB[ j ] === b[ i ];
-                                       if ( aCircular || bCircular ) {
-                                               if ( a[ i ] === b[ i ] || aCircular && bCircular ) {
-                                                       loop = true;
-                                               } else {
-                                                       parents.pop();
-                                                       parentsB.pop();
-                                                       return false;
-                                               }
-                                       }
-                               }
-                               if ( !loop && !innerEquiv( a[ i ], b[ i ] ) ) {
-                                       parents.pop();
-                                       parentsB.pop();
-                                       return false;
-                               }
-                       }
-                       parents.pop();
-                       parentsB.pop();
-                       return true;
-               },
-
-               "set": function( b, a ) {
-                       var aArray, bArray;
-
-                       aArray = [];
-                       a.forEach( function( v ) {
-                               aArray.push( v );
-                       });
-                       bArray = [];
-                       b.forEach( function( v ) {
-                               bArray.push( v );
-                       });
-
-                       return innerEquiv( bArray, aArray );
-               },
-
-               "map": function( b, a ) {
-                       var aArray, bArray;
-
-                       aArray = [];
-                       a.forEach( function( v, k ) {
-                               aArray.push( [ k, v ] );
-                       });
-                       bArray = [];
-                       b.forEach( function( v, k ) {
-                               bArray.push( [ k, v ] );
-                       });
-
-                       return innerEquiv( bArray, aArray );
-               },
-
-               "object": function( b, a ) {
-                       var i, j, loop, aCircular, bCircular;
-
-                       // Default to true
-                       var eq = true;
-                       var aProperties = [];
-                       var bProperties = [];
-
-                       if ( compareConstructors( a, b ) === false ) {
-                               return false;
-                       }
-
-                       // Stack constructor before traversing properties
-                       callers.push( a.constructor );
-
-                       // Track reference to avoid circular references
-                       parents.push( a );
-                       parentsB.push( b );
-
-                       // Be strict: don't ensure hasOwnProperty and go deep
-                       for ( i in a ) {
-                               loop = false;
-                               for ( j = 0; j < parents.length; j++ ) {
-                                       aCircular = parents[ j ] === a[ i ];
-                                       bCircular = parentsB[ j ] === b[ i ];
-                                       if ( aCircular || bCircular ) {
-                                               if ( a[ i ] === b[ i ] || aCircular && bCircular ) {
-                                                       loop = true;
-                                               } else {
-                                                       eq = false;
-                                                       break;
-                                               }
-                                       }
-                               }
-                               aProperties.push( i );
-                               if ( !loop && !innerEquiv( a[ i ], b[ i ] ) ) {
-                                       eq = false;
-                                       break;
-                               }
-                       }
-
-                       parents.pop();
-                       parentsB.pop();
-
-                       // Unstack, we are done
-                       callers.pop();
-
-                       for ( i in b ) {
-
-                               // Collect b's properties
-                               bProperties.push( i );
-                       }
-
-                       // Ensures identical properties name
-                       return eq && innerEquiv( aProperties.sort(), bProperties.sort() );
-               }
-       };
-
-       function typeEquiv( a, b ) {
-               var type = QUnit.objectType( a );
-               return QUnit.objectType( b ) === type && callbacks[ type ]( b, a );
-       }
-
-       // The real equiv function
-       function innerEquiv( a, b ) {
-
-               // We're done when there's nothing more to compare
-               if ( arguments.length < 2 ) {
-                       return true;
-               }
-
-               // Require type-specific equality
-               return ( a === b || typeEquiv( a, b ) ) &&
-
-                       // ...across all consecutive argument pairs
-                       ( arguments.length === 2 || innerEquiv.apply( this, [].slice.call( arguments, 1 ) ) );
-       }
-
-       return innerEquiv;
-}());
-
-// Based on jsDump by Ariel Flesler
-// http://flesler.blogspot.com/2008/05/jsdump-pretty-dump-of-any-javascript.html
-QUnit.dump = (function() {
-       function quote( str ) {
-               return "\"" + str.toString().replace( /\\/g, "\\\\" ).replace( /"/g, "\\\"" ) + "\"";
-       }
-       function literal( o ) {
-               return o + "";
-       }
-       function join( pre, arr, post ) {
-               var s = dump.separator(),
-                       base = dump.indent(),
-                       inner = dump.indent( 1 );
-               if ( arr.join ) {
-                       arr = arr.join( "," + s + inner );
-               }
-               if ( !arr ) {
-                       return pre + post;
-               }
-               return [ pre, inner + arr, base + post ].join( s );
-       }
-       function array( arr, stack ) {
-               var i = arr.length,
-                       ret = new Array( i );
-
-               if ( dump.maxDepth && dump.depth > dump.maxDepth ) {
-                       return "[object Array]";
-               }
-
-               this.up();
-               while ( i-- ) {
-                       ret[ i ] = this.parse( arr[ i ], undefined, stack );
-               }
-               this.down();
-               return join( "[", ret, "]" );
-       }
-
-       var reName = /^function (\w+)/,
-               dump = {
-
-                       // objType is used mostly internally, you can fix a (custom) type in advance
-                       parse: function( obj, objType, stack ) {
-                               stack = stack || [];
-                               var res, parser, parserType,
-                                       inStack = inArray( obj, stack );
-
-                               if ( inStack !== -1 ) {
-                                       return "recursion(" + ( inStack - stack.length ) + ")";
-                               }
-
-                               objType = objType || this.typeOf( obj  );
-                               parser = this.parsers[ objType ];
-                               parserType = typeof parser;
-
-                               if ( parserType === "function" ) {
-                                       stack.push( obj );
-                                       res = parser.call( this, obj, stack );
-                                       stack.pop();
-                                       return res;
-                               }
-                               return ( parserType === "string" ) ? parser : this.parsers.error;
-                       },
-                       typeOf: function( obj ) {
-                               var type;
-                               if ( obj === null ) {
-                                       type = "null";
-                               } else if ( typeof obj === "undefined" ) {
-                                       type = "undefined";
-                               } else if ( QUnit.is( "regexp", obj ) ) {
-                                       type = "regexp";
-                               } else if ( QUnit.is( "date", obj ) ) {
-                                       type = "date";
-                               } else if ( QUnit.is( "function", obj ) ) {
-                                       type = "function";
-                               } else if ( obj.setInterval !== undefined &&
-                                               obj.document !== undefined &&
-                                               obj.nodeType === undefined ) {
-                                       type = "window";
-                               } else if ( obj.nodeType === 9 ) {
-                                       type = "document";
-                               } else if ( obj.nodeType ) {
-                                       type = "node";
-                               } else if (
-
-                                       // native arrays
-                                       toString.call( obj ) === "[object Array]" ||
-
-                                       // NodeList objects
-                                       ( typeof obj.length === "number" && obj.item !== undefined &&
-                                       ( obj.length ? obj.item( 0 ) === obj[ 0 ] : ( obj.item( 0 ) === null &&
-                                       obj[ 0 ] === undefined ) ) )
-                               ) {
-                                       type = "array";
-                               } else if ( obj.constructor === Error.prototype.constructor ) {
-                                       type = "error";
-                               } else {
-                                       type = typeof obj;
-                               }
-                               return type;
-                       },
-                       separator: function() {
-                               return this.multiline ? this.HTML ? "<br />" : "\n" : this.HTML ? "&#160;" : " ";
-                       },
-                       // extra can be a number, shortcut for increasing-calling-decreasing
-                       indent: function( extra ) {
-                               if ( !this.multiline ) {
-                                       return "";
-                               }
-                               var chr = this.indentChar;
-                               if ( this.HTML ) {
-                                       chr = chr.replace( /\t/g, "   " ).replace( / /g, "&#160;" );
-                               }
-                               return new Array( this.depth + ( extra || 0 ) ).join( chr );
-                       },
-                       up: function( a ) {
-                               this.depth += a || 1;
-                       },
-                       down: function( a ) {
-                               this.depth -= a || 1;
-                       },
-                       setParser: function( name, parser ) {
-                               this.parsers[ name ] = parser;
-                       },
-                       // The next 3 are exposed so you can use them
-                       quote: quote,
-                       literal: literal,
-                       join: join,
-                       //
-                       depth: 1,
-                       maxDepth: QUnit.config.maxDepth,
-
-                       // This is the list of parsers, to modify them, use dump.setParser
-                       parsers: {
-                               window: "[Window]",
-                               document: "[Document]",
-                               error: function( error ) {
-                                       return "Error(\"" + error.message + "\")";
-                               },
-                               unknown: "[Unknown]",
-                               "null": "null",
-                               "undefined": "undefined",
-                               "function": function( fn ) {
-                                       var ret = "function",
-
-                                               // functions never have name in IE
-                                               name = "name" in fn ? fn.name : ( reName.exec( fn ) || [] )[ 1 ];
-
-                                       if ( name ) {
-                                               ret += " " + name;
-                                       }
-                                       ret += "( ";
-
-                                       ret = [ ret, dump.parse( fn, "functionArgs" ), "){" ].join( "" );
-                                       return join( ret, dump.parse( fn, "functionCode" ), "}" );
-                               },
-                               array: array,
-                               nodelist: array,
-                               "arguments": array,
-                               object: function( map, stack ) {
-                                       var keys, key, val, i, nonEnumerableProperties,
-                                               ret = [];
-
-                                       if ( dump.maxDepth && dump.depth > dump.maxDepth ) {
-                                               return "[object Object]";
-                                       }
-
-                                       dump.up();
-                                       keys = [];
-                                       for ( key in map ) {
-                                               keys.push( key );
-                                       }
-
-                                       // Some properties are not always enumerable on Error objects.
-                                       nonEnumerableProperties = [ "message", "name" ];
-                                       for ( i in nonEnumerableProperties ) {
-                                               key = nonEnumerableProperties[ i ];
-                                               if ( key in map && inArray( key, keys ) < 0 ) {
-                                                       keys.push( key );
-                                               }
-                                       }
-                                       keys.sort();
-                                       for ( i = 0; i < keys.length; i++ ) {
-                                               key = keys[ i ];
-                                               val = map[ key ];
-                                               ret.push( dump.parse( key, "key" ) + ": " +
-                                                       dump.parse( val, undefined, stack ) );
-                                       }
-                                       dump.down();
-                                       return join( "{", ret, "}" );
-                               },
-                               node: function( node ) {
-                                       var len, i, val,
-                                               open = dump.HTML ? "&lt;" : "<",
-                                               close = dump.HTML ? "&gt;" : ">",
-                                               tag = node.nodeName.toLowerCase(),
-                                               ret = open + tag,
-                                               attrs = node.attributes;
-
-                                       if ( attrs ) {
-                                               for ( i = 0, len = attrs.length; i < len; i++ ) {
-                                                       val = attrs[ i ].nodeValue;
-
-                                                       // IE6 includes all attributes in .attributes, even ones not explicitly
-                                                       // set. Those have values like undefined, null, 0, false, "" or
-                                                       // "inherit".
-                                                       if ( val && val !== "inherit" ) {
-                                                               ret += " " + attrs[ i ].nodeName + "=" +
-                                                                       dump.parse( val, "attribute" );
-                                                       }
-                                               }
-                                       }
-                                       ret += close;
-
-                                       // Show content of TextNode or CDATASection
-                                       if ( node.nodeType === 3 || node.nodeType === 4 ) {
-                                               ret += node.nodeValue;
-                                       }
-
-                                       return ret + open + "/" + tag + close;
-                               },
-
-                               // function calls it internally, it's the arguments part of the function
-                               functionArgs: function( fn ) {
-                                       var args,
-                                               l = fn.length;
-
-                                       if ( !l ) {
-                                               return "";
-                                       }
-
-                                       args = new Array( l );
-                                       while ( l-- ) {
-
-                                               // 97 is 'a'
-                                               args[ l ] = String.fromCharCode( 97 + l );
-                                       }
-                                       return " " + args.join( ", " ) + " ";
-                               },
-                               // object calls it internally, the key part of an item in a map
-                               key: quote,
-                               // function calls it internally, it's the content of the function
-                               functionCode: "[code]",
-                               // node calls it internally, it's a html attribute value
-                               attribute: quote,
-                               string: quote,
-                               date: quote,
-                               regexp: literal,
-                               number: literal,
-                               "boolean": literal
-                       },
-                       // if true, entities are escaped ( <, >, \t, space and \n )
-                       HTML: false,
-                       // indentation unit
-                       indentChar: "  ",
-                       // if true, items in a collection, are separated by a \n, else just a space.
-                       multiline: true
-               };
-
-       return dump;
-}());
-
-// back compat
-QUnit.jsDump = QUnit.dump;
-
-// For browser, export only select globals
-if ( defined.document ) {
-
-       // Deprecated
-       // Extend assert methods to QUnit and Global scope through Backwards compatibility
-       (function() {
-               var i,
-                       assertions = Assert.prototype;
-
-               function applyCurrent( current ) {
-                       return function() {
-                               var assert = new Assert( QUnit.config.current );
-                               current.apply( assert, arguments );
-                       };
-               }
-
-               for ( i in assertions ) {
-                       QUnit[ i ] = applyCurrent( assertions[ i ] );
-               }
-       })();
-
-       (function() {
-               var i, l,
-                       keys = [
-                               "test",
-                               "module",
-                               "expect",
-                               "asyncTest",
-                               "start",
-                               "stop",
-                               "ok",
-                               "notOk",
-                               "equal",
-                               "notEqual",
-                               "propEqual",
-                               "notPropEqual",
-                               "deepEqual",
-                               "notDeepEqual",
-                               "strictEqual",
-                               "notStrictEqual",
-                               "throws",
-                               "raises"
-                       ];
-
-               for ( i = 0, l = keys.length; i < l; i++ ) {
-                       window[ keys[ i ] ] = QUnit[ keys[ i ] ];
-               }
-       })();
-
-       window.QUnit = QUnit;
-}
-
-// For nodejs
-if ( typeof module !== "undefined" && module && module.exports ) {
-       module.exports = QUnit;
-
-       // For consistency with CommonJS environments' exports
-       module.exports.QUnit = QUnit;
-}
-
-// For CommonJS with exports, but without module.exports, like Rhino
-if ( typeof exports !== "undefined" && exports ) {
-       exports.QUnit = QUnit;
-}
-
-if ( typeof define === "function" && define.amd ) {
-       define( function() {
-               return QUnit;
-       } );
-       QUnit.config.autostart = false;
-}
-
-/*
- * This file is a modified version of google-diff-match-patch's JavaScript implementation
- * (https://code.google.com/p/google-diff-match-patch/source/browse/trunk/javascript/diff_match_patch_uncompressed.js),
- * modifications are licensed as more fully set forth in LICENSE.txt.
- *
- * The original source of google-diff-match-patch is attributable and licensed as follows:
- *
- * Copyright 2006 Google Inc.
- * https://code.google.com/p/google-diff-match-patch/
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * https://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- * More Info:
- *  https://code.google.com/p/google-diff-match-patch/
- *
- * Usage: QUnit.diff(expected, actual)
- *
- */
-QUnit.diff = ( function() {
-       function DiffMatchPatch() {
-       }
-
-       //  DIFF FUNCTIONS
-
-       /**
-        * The data structure representing a diff is an array of tuples:
-        * [[DIFF_DELETE, 'Hello'], [DIFF_INSERT, 'Goodbye'], [DIFF_EQUAL, ' world.']]
-        * which means: delete 'Hello', add 'Goodbye' and keep ' world.'
-        */
-       var DIFF_DELETE = -1,
-               DIFF_INSERT = 1,
-               DIFF_EQUAL = 0;
-
-       /**
-        * Find the differences between two texts.  Simplifies the problem by stripping
-        * any common prefix or suffix off the texts before diffing.
-        * @param {string} text1 Old string to be diffed.
-        * @param {string} text2 New string to be diffed.
-        * @param {boolean=} optChecklines Optional speedup flag. If present and false,
-        *     then don't run a line-level diff first to identify the changed areas.
-        *     Defaults to true, which does a faster, slightly less optimal diff.
-        * @return {!Array.<!DiffMatchPatch.Diff>} Array of diff tuples.
-        */
-       DiffMatchPatch.prototype.DiffMain = function( text1, text2, optChecklines ) {
-               var deadline, checklines, commonlength,
-                       commonprefix, commonsuffix, diffs;
-
-               // The diff must be complete in up to 1 second.
-               deadline = ( new Date() ).getTime() + 1000;
-
-               // Check for null inputs.
-               if ( text1 === null || text2 === null ) {
-                       throw new Error( "Null input. (DiffMain)" );
-               }
-
-               // Check for equality (speedup).
-               if ( text1 === text2 ) {
-                       if ( text1 ) {
-                               return [
-                                       [ DIFF_EQUAL, text1 ]
-                               ];
-                       }
-                       return [];
-               }
-
-               if ( typeof optChecklines === "undefined" ) {
-                       optChecklines = true;
-               }
-
-               checklines = optChecklines;
-
-               // Trim off common prefix (speedup).
-               commonlength = this.diffCommonPrefix( text1, text2 );
-               commonprefix = text1.substring( 0, commonlength );
-               text1 = text1.substring( commonlength );
-               text2 = text2.substring( commonlength );
-
-               // Trim off common suffix (speedup).
-               commonlength = this.diffCommonSuffix( text1, text2 );
-               commonsuffix = text1.substring( text1.length - commonlength );
-               text1 = text1.substring( 0, text1.length - commonlength );
-               text2 = text2.substring( 0, text2.length - commonlength );
-
-               // Compute the diff on the middle block.
-               diffs = this.diffCompute( text1, text2, checklines, deadline );
-
-               // Restore the prefix and suffix.
-               if ( commonprefix ) {
-                       diffs.unshift( [ DIFF_EQUAL, commonprefix ] );
-               }
-               if ( commonsuffix ) {
-                       diffs.push( [ DIFF_EQUAL, commonsuffix ] );
-               }
-               this.diffCleanupMerge( diffs );
-               return diffs;
-       };
-
-       /**
-        * Reduce the number of edits by eliminating operationally trivial equalities.
-        * @param {!Array.<!DiffMatchPatch.Diff>} diffs Array of diff tuples.
-        */
-       DiffMatchPatch.prototype.diffCleanupEfficiency = function( diffs ) {
-               var changes, equalities, equalitiesLength, lastequality,
-                       pointer, preIns, preDel, postIns, postDel;
-               changes = false;
-               equalities = []; // Stack of indices where equalities are found.
-               equalitiesLength = 0; // Keeping our own length var is faster in JS.
-               /** @type {?string} */
-               lastequality = null;
-               // Always equal to diffs[equalities[equalitiesLength - 1]][1]
-               pointer = 0; // Index of current position.
-               // Is there an insertion operation before the last equality.
-               preIns = false;
-               // Is there a deletion operation before the last equality.
-               preDel = false;
-               // Is there an insertion operation after the last equality.
-               postIns = false;
-               // Is there a deletion operation after the last equality.
-               postDel = false;
-               while ( pointer < diffs.length ) {
-
-                       // Equality found.
-                       if ( diffs[ pointer ][ 0 ] === DIFF_EQUAL ) {
-                               if ( diffs[ pointer ][ 1 ].length < 4 && ( postIns || postDel ) ) {
-
-                                       // Candidate found.
-                                       equalities[ equalitiesLength++ ] = pointer;
-                                       preIns = postIns;
-                                       preDel = postDel;
-                                       lastequality = diffs[ pointer ][ 1 ];
-                               } else {
-
-                                       // Not a candidate, and can never become one.
-                                       equalitiesLength = 0;
-                                       lastequality = null;
-                               }
-                               postIns = postDel = false;
-
-                       // An insertion or deletion.
-                       } else {
-
-                               if ( diffs[ pointer ][ 0 ] === DIFF_DELETE ) {
-                                       postDel = true;
-                               } else {
-                                       postIns = true;
-                               }
-
-                               /*
-                                * Five types to be split:
-                                * <ins>A</ins><del>B</del>XY<ins>C</ins><del>D</del>
-                                * <ins>A</ins>X<ins>C</ins><del>D</del>
-                                * <ins>A</ins><del>B</del>X<ins>C</ins>
-                                * <ins>A</del>X<ins>C</ins><del>D</del>
-                                * <ins>A</ins><del>B</del>X<del>C</del>
-                                */
-                               if ( lastequality && ( ( preIns && preDel && postIns && postDel ) ||
-                                               ( ( lastequality.length < 2 ) &&
-                                               ( preIns + preDel + postIns + postDel ) === 3 ) ) ) {
-
-                                       // Duplicate record.
-                                       diffs.splice(
-                                               equalities[ equalitiesLength - 1 ],
-                                               0,
-                                               [ DIFF_DELETE, lastequality ]
-                                       );
-
-                                       // Change second copy to insert.
-                                       diffs[ equalities[ equalitiesLength - 1 ] + 1 ][ 0 ] = DIFF_INSERT;
-                                       equalitiesLength--; // Throw away the equality we just deleted;
-                                       lastequality = null;
-                                       if ( preIns && preDel ) {
-                                               // No changes made which could affect previous entry, keep going.
-                                               postIns = postDel = true;
-                                               equalitiesLength = 0;
-                                       } else {
-                                               equalitiesLength--; // Throw away the previous equality.
-                                               pointer = equalitiesLength > 0 ? equalities[ equalitiesLength - 1 ] : -1;
-                                               postIns = postDel = false;
-                                       }
-                                       changes = true;
-                               }
-                       }
-                       pointer++;
-               }
-
-               if ( changes ) {
-                       this.diffCleanupMerge( diffs );
-               }
-       };
-
-       /**
-        * Convert a diff array into a pretty HTML report.
-        * @param {!Array.<!DiffMatchPatch.Diff>} diffs Array of diff tuples.
-        * @param {integer} string to be beautified.
-        * @return {string} HTML representation.
-        */
-       DiffMatchPatch.prototype.diffPrettyHtml = function( diffs ) {
-               var op, data, x,
-                       html = [];
-               for ( x = 0; x < diffs.length; x++ ) {
-                       op = diffs[ x ][ 0 ]; // Operation (insert, delete, equal)
-                       data = diffs[ x ][ 1 ]; // Text of change.
-                       switch ( op ) {
-                       case DIFF_INSERT:
-                               html[ x ] = "<ins>" + data + "</ins>";
-                               break;
-                       case DIFF_DELETE:
-                               html[ x ] = "<del>" + data + "</del>";
-                               break;
-                       case DIFF_EQUAL:
-                               html[ x ] = "<span>" + data + "</span>";
-                               break;
-                       }
-               }
-               return html.join( "" );
-       };
-
-       /**
-        * Determine the common prefix of two strings.
-        * @param {string} text1 First string.
-        * @param {string} text2 Second string.
-        * @return {number} The number of characters common to the start of each
-        *     string.
-        */
-       DiffMatchPatch.prototype.diffCommonPrefix = function( text1, text2 ) {
-               var pointermid, pointermax, pointermin, pointerstart;
-               // Quick check for common null cases.
-               if ( !text1 || !text2 || text1.charAt( 0 ) !== text2.charAt( 0 ) ) {
-                       return 0;
-               }
-               // Binary search.
-               // Performance analysis: https://neil.fraser.name/news/2007/10/09/
-               pointermin = 0;
-               pointermax = Math.min( text1.length, text2.length );
-               pointermid = pointermax;
-               pointerstart = 0;
-               while ( pointermin < pointermid ) {
-                       if ( text1.substring( pointerstart, pointermid ) ===
-                                       text2.substring( pointerstart, pointermid ) ) {
-                               pointermin = pointermid;
-                               pointerstart = pointermin;
-                       } else {
-                               pointermax = pointermid;
-                       }
-                       pointermid = Math.floor( ( pointermax - pointermin ) / 2 + pointermin );
-               }
-               return pointermid;
-       };
-
-       /**
-        * Determine the common suffix of two strings.
-        * @param {string} text1 First string.
-        * @param {string} text2 Second string.
-        * @return {number} The number of characters common to the end of each string.
-        */
-       DiffMatchPatch.prototype.diffCommonSuffix = function( text1, text2 ) {
-               var pointermid, pointermax, pointermin, pointerend;
-               // Quick check for common null cases.
-               if ( !text1 ||
-                               !text2 ||
-                               text1.charAt( text1.length - 1 ) !== text2.charAt( text2.length - 1 ) ) {
-                       return 0;
-               }
-               // Binary search.
-               // Performance analysis: https://neil.fraser.name/news/2007/10/09/
-               pointermin = 0;
-               pointermax = Math.min( text1.length, text2.length );
-               pointermid = pointermax;
-               pointerend = 0;
-               while ( pointermin < pointermid ) {
-                       if ( text1.substring( text1.length - pointermid, text1.length - pointerend ) ===
-                                       text2.substring( text2.length - pointermid, text2.length - pointerend ) ) {
-                               pointermin = pointermid;
-                               pointerend = pointermin;
-                       } else {
-                               pointermax = pointermid;
-                       }
-                       pointermid = Math.floor( ( pointermax - pointermin ) / 2 + pointermin );
-               }
-               return pointermid;
-       };
-
-       /**
-        * Find the differences between two texts.  Assumes that the texts do not
-        * have any common prefix or suffix.
-        * @param {string} text1 Old string to be diffed.
-        * @param {string} text2 New string to be diffed.
-        * @param {boolean} checklines Speedup flag.  If false, then don't run a
-        *     line-level diff first to identify the changed areas.
-        *     If true, then run a faster, slightly less optimal diff.
-        * @param {number} deadline Time when the diff should be complete by.
-        * @return {!Array.<!DiffMatchPatch.Diff>} Array of diff tuples.
-        * @private
-        */
-       DiffMatchPatch.prototype.diffCompute = function( text1, text2, checklines, deadline ) {
-               var diffs, longtext, shorttext, i, hm,
-                       text1A, text2A, text1B, text2B,
-                       midCommon, diffsA, diffsB;
-
-               if ( !text1 ) {
-                       // Just add some text (speedup).
-                       return [
-                               [ DIFF_INSERT, text2 ]
-                       ];
-               }
-
-               if ( !text2 ) {
-                       // Just delete some text (speedup).
-                       return [
-                               [ DIFF_DELETE, text1 ]
-                       ];
-               }
-
-               longtext = text1.length > text2.length ? text1 : text2;
-               shorttext = text1.length > text2.length ? text2 : text1;
-               i = longtext.indexOf( shorttext );
-               if ( i !== -1 ) {
-                       // Shorter text is inside the longer text (speedup).
-                       diffs = [
-                               [ DIFF_INSERT, longtext.substring( 0, i ) ],
-                               [ DIFF_EQUAL, shorttext ],
-                               [ DIFF_INSERT, longtext.substring( i + shorttext.length ) ]
-                       ];
-                       // Swap insertions for deletions if diff is reversed.
-                       if ( text1.length > text2.length ) {
-                               diffs[ 0 ][ 0 ] = diffs[ 2 ][ 0 ] = DIFF_DELETE;
-                       }
-                       return diffs;
-               }
-
-               if ( shorttext.length === 1 ) {
-                       // Single character string.
-                       // After the previous speedup, the character can't be an equality.
-                       return [
-                               [ DIFF_DELETE, text1 ],
-                               [ DIFF_INSERT, text2 ]
-                       ];
-               }
-
-               // Check to see if the problem can be split in two.
-               hm = this.diffHalfMatch( text1, text2 );
-               if ( hm ) {
-                       // A half-match was found, sort out the return data.
-                       text1A = hm[ 0 ];
-                       text1B = hm[ 1 ];
-                       text2A = hm[ 2 ];
-                       text2B = hm[ 3 ];
-                       midCommon = hm[ 4 ];
-                       // Send both pairs off for separate processing.
-                       diffsA = this.DiffMain( text1A, text2A, checklines, deadline );
-                       diffsB = this.DiffMain( text1B, text2B, checklines, deadline );
-                       // Merge the results.
-                       return diffsA.concat( [
-                               [ DIFF_EQUAL, midCommon ]
-                       ], diffsB );
-               }
-
-               if ( checklines && text1.length > 100 && text2.length > 100 ) {
-                       return this.diffLineMode( text1, text2, deadline );
-               }
-
-               return this.diffBisect( text1, text2, deadline );
-       };
-
-       /**
-        * Do the two texts share a substring which is at least half the length of the
-        * longer text?
-        * This speedup can produce non-minimal diffs.
-        * @param {string} text1 First string.
-        * @param {string} text2 Second string.
-        * @return {Array.<string>} Five element Array, containing the prefix of
-        *     text1, the suffix of text1, the prefix of text2, the suffix of
-        *     text2 and the common middle.  Or null if there was no match.
-        * @private
-        */
-       DiffMatchPatch.prototype.diffHalfMatch = function( text1, text2 ) {
-               var longtext, shorttext, dmp,
-                       text1A, text2B, text2A, text1B, midCommon,
-                       hm1, hm2, hm;
-
-               longtext = text1.length > text2.length ? text1 : text2;
-               shorttext = text1.length > text2.length ? text2 : text1;
-               if ( longtext.length < 4 || shorttext.length * 2 < longtext.length ) {
-                       return null; // Pointless.
-               }
-               dmp = this; // 'this' becomes 'window' in a closure.
-
-               /**
-                * Does a substring of shorttext exist within longtext such that the substring
-                * is at least half the length of longtext?
-                * Closure, but does not reference any external variables.
-                * @param {string} longtext Longer string.
-                * @param {string} shorttext Shorter string.
-                * @param {number} i Start index of quarter length substring within longtext.
-                * @return {Array.<string>} Five element Array, containing the prefix of
-                *     longtext, the suffix of longtext, the prefix of shorttext, the suffix
-                *     of shorttext and the common middle.  Or null if there was no match.
-                * @private
-                */
-               function diffHalfMatchI( longtext, shorttext, i ) {
-                       var seed, j, bestCommon, prefixLength, suffixLength,
-                               bestLongtextA, bestLongtextB, bestShorttextA, bestShorttextB;
-                       // Start with a 1/4 length substring at position i as a seed.
-                       seed = longtext.substring( i, i + Math.floor( longtext.length / 4 ) );
-                       j = -1;
-                       bestCommon = "";
-                       while ( ( j = shorttext.indexOf( seed, j + 1 ) ) !== -1 ) {
-                               prefixLength = dmp.diffCommonPrefix( longtext.substring( i ),
-                                       shorttext.substring( j ) );
-                               suffixLength = dmp.diffCommonSuffix( longtext.substring( 0, i ),
-                                       shorttext.substring( 0, j ) );
-                               if ( bestCommon.length < suffixLength + prefixLength ) {
-                                       bestCommon = shorttext.substring( j - suffixLength, j ) +
-                                               shorttext.substring( j, j + prefixLength );
-                                       bestLongtextA = longtext.substring( 0, i - suffixLength );
-                                       bestLongtextB = longtext.substring( i + prefixLength );
-                                       bestShorttextA = shorttext.substring( 0, j - suffixLength );
-                                       bestShorttextB = shorttext.substring( j + prefixLength );
-                               }
-                       }
-                       if ( bestCommon.length * 2 >= longtext.length ) {
-                               return [ bestLongtextA, bestLongtextB,
-                                       bestShorttextA, bestShorttextB, bestCommon
-                               ];
-                       } else {
-                               return null;
-                       }
-               }
-
-               // First check if the second quarter is the seed for a half-match.
-               hm1 = diffHalfMatchI( longtext, shorttext,
-                       Math.ceil( longtext.length / 4 ) );
-               // Check again based on the third quarter.
-               hm2 = diffHalfMatchI( longtext, shorttext,
-                       Math.ceil( longtext.length / 2 ) );
-               if ( !hm1 && !hm2 ) {
-                       return null;
-               } else if ( !hm2 ) {
-                       hm = hm1;
-               } else if ( !hm1 ) {
-                       hm = hm2;
-               } else {
-                       // Both matched.  Select the longest.
-                       hm = hm1[ 4 ].length > hm2[ 4 ].length ? hm1 : hm2;
-               }
-
-               // A half-match was found, sort out the return data.
-               text1A, text1B, text2A, text2B;
-               if ( text1.length > text2.length ) {
-                       text1A = hm[ 0 ];
-                       text1B = hm[ 1 ];
-                       text2A = hm[ 2 ];
-                       text2B = hm[ 3 ];
-               } else {
-                       text2A = hm[ 0 ];
-                       text2B = hm[ 1 ];
-                       text1A = hm[ 2 ];
-                       text1B = hm[ 3 ];
-               }
-               midCommon = hm[ 4 ];
-               return [ text1A, text1B, text2A, text2B, midCommon ];
-       };
-
-       /**
-        * Do a quick line-level diff on both strings, then rediff the parts for
-        * greater accuracy.
-        * This speedup can produce non-minimal diffs.
-        * @param {string} text1 Old string to be diffed.
-        * @param {string} text2 New string to be diffed.
-        * @param {number} deadline Time when the diff should be complete by.
-        * @return {!Array.<!DiffMatchPatch.Diff>} Array of diff tuples.
-        * @private
-        */
-       DiffMatchPatch.prototype.diffLineMode = function( text1, text2, deadline ) {
-               var a, diffs, linearray, pointer, countInsert,
-                       countDelete, textInsert, textDelete, j;
-               // Scan the text on a line-by-line basis first.
-               a = this.diffLinesToChars( text1, text2 );
-               text1 = a.chars1;
-               text2 = a.chars2;
-               linearray = a.lineArray;
-
-               diffs = this.DiffMain( text1, text2, false, deadline );
-
-               // Convert the diff back to original text.
-               this.diffCharsToLines( diffs, linearray );
-               // Eliminate freak matches (e.g. blank lines)
-               this.diffCleanupSemantic( diffs );
-
-               // Rediff any replacement blocks, this time character-by-character.
-               // Add a dummy entry at the end.
-               diffs.push( [ DIFF_EQUAL, "" ] );
-               pointer = 0;
-               countDelete = 0;
-               countInsert = 0;
-               textDelete = "";
-               textInsert = "";
-               while ( pointer < diffs.length ) {
-                       switch ( diffs[ pointer ][ 0 ] ) {
-                       case DIFF_INSERT:
-                               countInsert++;
-                               textInsert += diffs[ pointer ][ 1 ];
-                               break;
-                       case DIFF_DELETE:
-                               countDelete++;
-                               textDelete += diffs[ pointer ][ 1 ];
-                               break;
-                       case DIFF_EQUAL:
-                               // Upon reaching an equality, check for prior redundancies.
-                               if ( countDelete >= 1 && countInsert >= 1 ) {
-                                       // Delete the offending records and add the merged ones.
-                                       diffs.splice( pointer - countDelete - countInsert,
-                                               countDelete + countInsert );
-                                       pointer = pointer - countDelete - countInsert;
-                                       a = this.DiffMain( textDelete, textInsert, false, deadline );
-                                       for ( j = a.length - 1; j >= 0; j-- ) {
-                                               diffs.splice( pointer, 0, a[ j ] );
-                                       }
-                                       pointer = pointer + a.length;
-                               }
-                               countInsert = 0;
-                               countDelete = 0;
-                               textDelete = "";
-                               textInsert = "";
-                               break;
-                       }
-                       pointer++;
-               }
-               diffs.pop(); // Remove the dummy entry at the end.
-
-               return diffs;
-       };
-
-       /**
-        * Find the 'middle snake' of a diff, split the problem in two
-        * and return the recursively constructed diff.
-        * See Myers 1986 paper: An O(ND) Difference Algorithm and Its Variations.
-        * @param {string} text1 Old string to be diffed.
-        * @param {string} text2 New string to be diffed.
-        * @param {number} deadline Time at which to bail if not yet complete.
-        * @return {!Array.<!DiffMatchPatch.Diff>} Array of diff tuples.
-        * @private
-        */
-       DiffMatchPatch.prototype.diffBisect = function( text1, text2, deadline ) {
-               var text1Length, text2Length, maxD, vOffset, vLength,
-                       v1, v2, x, delta, front, k1start, k1end, k2start,
-                       k2end, k2Offset, k1Offset, x1, x2, y1, y2, d, k1, k2;
-               // Cache the text lengths to prevent multiple calls.
-               text1Length = text1.length;
-               text2Length = text2.length;
-               maxD = Math.ceil( ( text1Length + text2Length ) / 2 );
-               vOffset = maxD;
-               vLength = 2 * maxD;
-               v1 = new Array( vLength );
-               v2 = new Array( vLength );
-               // Setting all elements to -1 is faster in Chrome & Firefox than mixing
-               // integers and undefined.
-               for ( x = 0; x < vLength; x++ ) {
-                       v1[ x ] = -1;
-                       v2[ x ] = -1;
-               }
-               v1[ vOffset + 1 ] = 0;
-               v2[ vOffset + 1 ] = 0;
-               delta = text1Length - text2Length;
-               // If the total number of characters is odd, then the front path will collide
-               // with the reverse path.
-               front = ( delta % 2 !== 0 );
-               // Offsets for start and end of k loop.
-               // Prevents mapping of space beyond the grid.
-               k1start = 0;
-               k1end = 0;
-               k2start = 0;
-               k2end = 0;
-               for ( d = 0; d < maxD; d++ ) {
-                       // Bail out if deadline is reached.
-                       if ( ( new Date() ).getTime() > deadline ) {
-                               break;
-                       }
-
-                       // Walk the front path one step.
-                       for ( k1 = -d + k1start; k1 <= d - k1end; k1 += 2 ) {
-                               k1Offset = vOffset + k1;
-                               if ( k1 === -d || ( k1 !== d && v1[ k1Offset - 1 ] < v1[ k1Offset + 1 ] ) ) {
-                                       x1 = v1[ k1Offset + 1 ];
-                               } else {
-                                       x1 = v1[ k1Offset - 1 ] + 1;
-                               }
-                               y1 = x1 - k1;
-                               while ( x1 < text1Length && y1 < text2Length &&
-                                       text1.charAt( x1 ) === text2.charAt( y1 ) ) {
-                                       x1++;
-                                       y1++;
-                               }
-                               v1[ k1Offset ] = x1;
-                               if ( x1 > text1Length ) {
-                                       // Ran off the right of the graph.
-                                       k1end += 2;
-                               } else if ( y1 > text2Length ) {
-                                       // Ran off the bottom of the graph.
-                                       k1start += 2;
-                               } else if ( front ) {
-                                       k2Offset = vOffset + delta - k1;
-                                       if ( k2Offset >= 0 && k2Offset < vLength && v2[ k2Offset ] !== -1 ) {
-                                               // Mirror x2 onto top-left coordinate system.
-                                               x2 = text1Length - v2[ k2Offset ];
-                                               if ( x1 >= x2 ) {
-                                                       // Overlap detected.
-                                                       return this.diffBisectSplit( text1, text2, x1, y1, deadline );
-                                               }
-                                       }
-                               }
-                       }
-
-                       // Walk the reverse path one step.
-                       for ( k2 = -d + k2start; k2 <= d - k2end; k2 += 2 ) {
-                               k2Offset = vOffset + k2;
-                               if ( k2 === -d || ( k2 !== d && v2[ k2Offset - 1 ] < v2[ k2Offset + 1 ] ) ) {
-                                       x2 = v2[ k2Offset + 1 ];
-                               } else {
-                                       x2 = v2[ k2Offset - 1 ] + 1;
-                               }
-                               y2 = x2 - k2;
-                               while ( x2 < text1Length && y2 < text2Length &&
-                                       text1.charAt( text1Length - x2 - 1 ) ===
-                                       text2.charAt( text2Length - y2 - 1 ) ) {
-                                       x2++;
-                                       y2++;
-                               }
-                               v2[ k2Offset ] = x2;
-                               if ( x2 > text1Length ) {
-                                       // Ran off the left of the graph.
-                                       k2end += 2;
-                               } else if ( y2 > text2Length ) {
-                                       // Ran off the top of the graph.
-                                       k2start += 2;
-                               } else if ( !front ) {
-                                       k1Offset = vOffset + delta - k2;
-                                       if ( k1Offset >= 0 && k1Offset < vLength && v1[ k1Offset ] !== -1 ) {
-                                               x1 = v1[ k1Offset ];
-                                               y1 = vOffset + x1 - k1Offset;
-                                               // Mirror x2 onto top-left coordinate system.
-                                               x2 = text1Length - x2;
-                                               if ( x1 >= x2 ) {
-                                                       // Overlap detected.
-                                                       return this.diffBisectSplit( text1, text2, x1, y1, deadline );
-                                               }
-                                       }
-                               }
-                       }
-               }
-               // Diff took too long and hit the deadline or
-               // number of diffs equals number of characters, no commonality at all.
-               return [
-                       [ DIFF_DELETE, text1 ],
-                       [ DIFF_INSERT, text2 ]
-               ];
-       };
-
-       /**
-        * Given the location of the 'middle snake', split the diff in two parts
-        * and recurse.
-        * @param {string} text1 Old string to be diffed.
-        * @param {string} text2 New string to be diffed.
-        * @param {number} x Index of split point in text1.
-        * @param {number} y Index of split point in text2.
-        * @param {number} deadline Time at which to bail if not yet complete.
-        * @return {!Array.<!DiffMatchPatch.Diff>} Array of diff tuples.
-        * @private
-        */
-       DiffMatchPatch.prototype.diffBisectSplit = function( text1, text2, x, y, deadline ) {
-               var text1a, text1b, text2a, text2b, diffs, diffsb;
-               text1a = text1.substring( 0, x );
-               text2a = text2.substring( 0, y );
-               text1b = text1.substring( x );
-               text2b = text2.substring( y );
-
-               // Compute both diffs serially.
-               diffs = this.DiffMain( text1a, text2a, false, deadline );
-               diffsb = this.DiffMain( text1b, text2b, false, deadline );
-
-               return diffs.concat( diffsb );
-       };
-
-       /**
-        * Reduce the number of edits by eliminating semantically trivial equalities.
-        * @param {!Array.<!DiffMatchPatch.Diff>} diffs Array of diff tuples.
-        */
-       DiffMatchPatch.prototype.diffCleanupSemantic = function( diffs ) {
-               var changes, equalities, equalitiesLength, lastequality,
-                       pointer, lengthInsertions2, lengthDeletions2, lengthInsertions1,
-                       lengthDeletions1, deletion, insertion, overlapLength1, overlapLength2;
-               changes = false;
-               equalities = []; // Stack of indices where equalities are found.
-               equalitiesLength = 0; // Keeping our own length var is faster in JS.
-               /** @type {?string} */
-               lastequality = null;
-               // Always equal to diffs[equalities[equalitiesLength - 1]][1]
-               pointer = 0; // Index of current position.
-               // Number of characters that changed prior to the equality.
-               lengthInsertions1 = 0;
-               lengthDeletions1 = 0;
-               // Number of characters that changed after the equality.
-               lengthInsertions2 = 0;
-               lengthDeletions2 = 0;
-               while ( pointer < diffs.length ) {
-                       if ( diffs[ pointer ][ 0 ] === DIFF_EQUAL ) { // Equality found.
-                               equalities[ equalitiesLength++ ] = pointer;
-                               lengthInsertions1 = lengthInsertions2;
-                               lengthDeletions1 = lengthDeletions2;
-                               lengthInsertions2 = 0;
-                               lengthDeletions2 = 0;
-                               lastequality = diffs[ pointer ][ 1 ];
-                       } else { // An insertion or deletion.
-                               if ( diffs[ pointer ][ 0 ] === DIFF_INSERT ) {
-                                       lengthInsertions2 += diffs[ pointer ][ 1 ].length;
-                               } else {
-                                       lengthDeletions2 += diffs[ pointer ][ 1 ].length;
-                               }
-                               // Eliminate an equality that is smaller or equal to the edits on both
-                               // sides of it.
-                               if ( lastequality && ( lastequality.length <=
-                                               Math.max( lengthInsertions1, lengthDeletions1 ) ) &&
-                                               ( lastequality.length <= Math.max( lengthInsertions2,
-                                                       lengthDeletions2 ) ) ) {
-
-                                       // Duplicate record.
-                                       diffs.splice(
-                                               equalities[ equalitiesLength - 1 ],
-                                               0,
-                                               [ DIFF_DELETE, lastequality ]
-                                       );
-
-                                       // Change second copy to insert.
-                                       diffs[ equalities[ equalitiesLength - 1 ] + 1 ][ 0 ] = DIFF_INSERT;
-
-                                       // Throw away the equality we just deleted.
-                                       equalitiesLength--;
-
-                                       // Throw away the previous equality (it needs to be reevaluated).
-                                       equalitiesLength--;
-                                       pointer = equalitiesLength > 0 ? equalities[ equalitiesLength - 1 ] : -1;
-
-                                       // Reset the counters.
-                                       lengthInsertions1 = 0;
-                                       lengthDeletions1 = 0;
-                                       lengthInsertions2 = 0;
-                                       lengthDeletions2 = 0;
-                                       lastequality = null;
-                                       changes = true;
-                               }
-                       }
-                       pointer++;
-               }
-
-               // Normalize the diff.
-               if ( changes ) {
-                       this.diffCleanupMerge( diffs );
-               }
-
-               // Find any overlaps between deletions and insertions.
-               // e.g: <del>abcxxx</del><ins>xxxdef</ins>
-               //   -> <del>abc</del>xxx<ins>def</ins>
-               // e.g: <del>xxxabc</del><ins>defxxx</ins>
-               //   -> <ins>def</ins>xxx<del>abc</del>
-               // Only extract an overlap if it is as big as the edit ahead or behind it.
-               pointer = 1;
-               while ( pointer < diffs.length ) {
-                       if ( diffs[ pointer - 1 ][ 0 ] === DIFF_DELETE &&
-                                       diffs[ pointer ][ 0 ] === DIFF_INSERT ) {
-                               deletion = diffs[ pointer - 1 ][ 1 ];
-                               insertion = diffs[ pointer ][ 1 ];
-                               overlapLength1 = this.diffCommonOverlap( deletion, insertion );
-                               overlapLength2 = this.diffCommonOverlap( insertion, deletion );
-                               if ( overlapLength1 >= overlapLength2 ) {
-                                       if ( overlapLength1 >= deletion.length / 2 ||
-                                                       overlapLength1 >= insertion.length / 2 ) {
-                                               // Overlap found.  Insert an equality and trim the surrounding edits.
-                                               diffs.splice(
-                                                       pointer,
-                                                       0,
-                                                       [ DIFF_EQUAL, insertion.substring( 0, overlapLength1 ) ]
-                                               );
-                                               diffs[ pointer - 1 ][ 1 ] =
-                                                       deletion.substring( 0, deletion.length - overlapLength1 );
-                                               diffs[ pointer + 1 ][ 1 ] = insertion.substring( overlapLength1 );
-                                               pointer++;
-                                       }
-                               } else {
-                                       if ( overlapLength2 >= deletion.length / 2 ||
-                                                       overlapLength2 >= insertion.length / 2 ) {
-
-                                               // Reverse overlap found.
-                                               // Insert an equality and swap and trim the surrounding edits.
-                                               diffs.splice(
-                                                       pointer,
-                                                       0,
-                                                       [ DIFF_EQUAL, deletion.substring( 0, overlapLength2 ) ]
-                                               );
-
-                                               diffs[ pointer - 1 ][ 0 ] = DIFF_INSERT;
-                                               diffs[ pointer - 1 ][ 1 ] =
-                                                       insertion.substring( 0, insertion.length - overlapLength2 );
-                                               diffs[ pointer + 1 ][ 0 ] = DIFF_DELETE;
-                                               diffs[ pointer + 1 ][ 1 ] =
-                                                       deletion.substring( overlapLength2 );
-                                               pointer++;
-                                       }
-                               }
-                               pointer++;
-                       }
-                       pointer++;
-               }
-       };
-
-       /**
-        * Determine if the suffix of one string is the prefix of another.
-        * @param {string} text1 First string.
-        * @param {string} text2 Second string.
-        * @return {number} The number of characters common to the end of the first
-        *     string and the start of the second string.
-        * @private
-        */
-       DiffMatchPatch.prototype.diffCommonOverlap = function( text1, text2 ) {
-               var text1Length, text2Length, textLength,
-                       best, length, pattern, found;
-               // Cache the text lengths to prevent multiple calls.
-               text1Length = text1.length;
-               text2Length = text2.length;
-               // Eliminate the null case.
-               if ( text1Length === 0 || text2Length === 0 ) {
-                       return 0;
-               }
-               // Truncate the longer string.
-               if ( text1Length > text2Length ) {
-                       text1 = text1.substring( text1Length - text2Length );
-               } else if ( text1Length < text2Length ) {
-                       text2 = text2.substring( 0, text1Length );
-               }
-               textLength = Math.min( text1Length, text2Length );
-               // Quick check for the worst case.
-               if ( text1 === text2 ) {
-                       return textLength;
-               }
-
-               // Start by looking for a single character match
-               // and increase length until no match is found.
-               // Performance analysis: https://neil.fraser.name/news/2010/11/04/
-               best = 0;
-               length = 1;
-               while ( true ) {
-                       pattern = text1.substring( textLength - length );
-                       found = text2.indexOf( pattern );
-                       if ( found === -1 ) {
-                               return best;
-                       }
-                       length += found;
-                       if ( found === 0 || text1.substring( textLength - length ) ===
-                                       text2.substring( 0, length ) ) {
-                               best = length;
-                               length++;
-                       }
-               }
-       };
-
-       /**
-        * Split two texts into an array of strings.  Reduce the texts to a string of
-        * hashes where each Unicode character represents one line.
-        * @param {string} text1 First string.
-        * @param {string} text2 Second string.
-        * @return {{chars1: string, chars2: string, lineArray: !Array.<string>}}
-        *     An object containing the encoded text1, the encoded text2 and
-        *     the array of unique strings.
-        *     The zeroth element of the array of unique strings is intentionally blank.
-        * @private
-        */
-       DiffMatchPatch.prototype.diffLinesToChars = function( text1, text2 ) {
-               var lineArray, lineHash, chars1, chars2;
-               lineArray = []; // e.g. lineArray[4] === 'Hello\n'
-               lineHash = {}; // e.g. lineHash['Hello\n'] === 4
-
-               // '\x00' is a valid character, but various debuggers don't like it.
-               // So we'll insert a junk entry to avoid generating a null character.
-               lineArray[ 0 ] = "";
-
-               /**
-                * Split a text into an array of strings.  Reduce the texts to a string of
-                * hashes where each Unicode character represents one line.
-                * Modifies linearray and linehash through being a closure.
-                * @param {string} text String to encode.
-                * @return {string} Encoded string.
-                * @private
-                */
-               function diffLinesToCharsMunge( text ) {
-                       var chars, lineStart, lineEnd, lineArrayLength, line;
-                       chars = "";
-                       // Walk the text, pulling out a substring for each line.
-                       // text.split('\n') would would temporarily double our memory footprint.
-                       // Modifying text would create many large strings to garbage collect.
-                       lineStart = 0;
-                       lineEnd = -1;
-                       // Keeping our own length variable is faster than looking it up.
-                       lineArrayLength = lineArray.length;
-                       while ( lineEnd < text.length - 1 ) {
-                               lineEnd = text.indexOf( "\n", lineStart );
-                               if ( lineEnd === -1 ) {
-                                       lineEnd = text.length - 1;
-                               }
-                               line = text.substring( lineStart, lineEnd + 1 );
-                               lineStart = lineEnd + 1;
-
-                               if ( lineHash.hasOwnProperty ? lineHash.hasOwnProperty( line ) :
-                                                       ( lineHash[ line ] !== undefined ) ) {
-                                       chars += String.fromCharCode( lineHash[ line ] );
-                               } else {
-                                       chars += String.fromCharCode( lineArrayLength );
-                                       lineHash[ line ] = lineArrayLength;
-                                       lineArray[ lineArrayLength++ ] = line;
-                               }
-                       }
-                       return chars;
-               }
-
-               chars1 = diffLinesToCharsMunge( text1 );
-               chars2 = diffLinesToCharsMunge( text2 );
-               return {
-                       chars1: chars1,
-                       chars2: chars2,
-                       lineArray: lineArray
-               };
-       };
-
-       /**
-        * Rehydrate the text in a diff from a string of line hashes to real lines of
-        * text.
-        * @param {!Array.<!DiffMatchPatch.Diff>} diffs Array of diff tuples.
-        * @param {!Array.<string>} lineArray Array of unique strings.
-        * @private
-        */
-       DiffMatchPatch.prototype.diffCharsToLines = function( diffs, lineArray ) {
-               var x, chars, text, y;
-               for ( x = 0; x < diffs.length; x++ ) {
-                       chars = diffs[ x ][ 1 ];
-                       text = [];
-                       for ( y = 0; y < chars.length; y++ ) {
-                               text[ y ] = lineArray[ chars.charCodeAt( y ) ];
-                       }
-                       diffs[ x ][ 1 ] = text.join( "" );
-               }
-       };
-
-       /**
-        * Reorder and merge like edit sections.  Merge equalities.
-        * Any edit section can move as long as it doesn't cross an equality.
-        * @param {!Array.<!DiffMatchPatch.Diff>} diffs Array of diff tuples.
-        */
-       DiffMatchPatch.prototype.diffCleanupMerge = function( diffs ) {
-               var pointer, countDelete, countInsert, textInsert, textDelete,
-                       commonlength, changes, diffPointer, position;
-               diffs.push( [ DIFF_EQUAL, "" ] ); // Add a dummy entry at the end.
-               pointer = 0;
-               countDelete = 0;
-               countInsert = 0;
-               textDelete = "";
-               textInsert = "";
-               commonlength;
-               while ( pointer < diffs.length ) {
-                       switch ( diffs[ pointer ][ 0 ] ) {
-                       case DIFF_INSERT:
-                               countInsert++;
-                               textInsert += diffs[ pointer ][ 1 ];
-                               pointer++;
-                               break;
-                       case DIFF_DELETE:
-                               countDelete++;
-                               textDelete += diffs[ pointer ][ 1 ];
-                               pointer++;
-                               break;
-                       case DIFF_EQUAL:
-                               // Upon reaching an equality, check for prior redundancies.
-                               if ( countDelete + countInsert > 1 ) {
-                                       if ( countDelete !== 0 && countInsert !== 0 ) {
-                                               // Factor out any common prefixes.
-                                               commonlength = this.diffCommonPrefix( textInsert, textDelete );
-                                               if ( commonlength !== 0 ) {
-                                                       if ( ( pointer - countDelete - countInsert ) > 0 &&
-                                                                       diffs[ pointer - countDelete - countInsert - 1 ][ 0 ] ===
-                                                                       DIFF_EQUAL ) {
-                                                               diffs[ pointer - countDelete - countInsert - 1 ][ 1 ] +=
-                                                                       textInsert.substring( 0, commonlength );
-                                                       } else {
-                                                               diffs.splice( 0, 0, [ DIFF_EQUAL,
-                                                                       textInsert.substring( 0, commonlength )
-                                                               ] );
-                                                               pointer++;
-                                                       }
-                                                       textInsert = textInsert.substring( commonlength );
-                                                       textDelete = textDelete.substring( commonlength );
-                                               }
-                                               // Factor out any common suffixies.
-                                               commonlength = this.diffCommonSuffix( textInsert, textDelete );
-                                               if ( commonlength !== 0 ) {
-                                                       diffs[ pointer ][ 1 ] = textInsert.substring( textInsert.length -
-                                                                       commonlength ) + diffs[ pointer ][ 1 ];
-                                                       textInsert = textInsert.substring( 0, textInsert.length -
-                                                               commonlength );
-                                                       textDelete = textDelete.substring( 0, textDelete.length -
-                                                               commonlength );
-                                               }
-                                       }
-                                       // Delete the offending records and add the merged ones.
-                                       if ( countDelete === 0 ) {
-                                               diffs.splice( pointer - countInsert,
-                                                       countDelete + countInsert, [ DIFF_INSERT, textInsert ] );
-                                       } else if ( countInsert === 0 ) {
-                                               diffs.splice( pointer - countDelete,
-                                                       countDelete + countInsert, [ DIFF_DELETE, textDelete ] );
-                                       } else {
-                                               diffs.splice(
-                                                       pointer - countDelete - countInsert,
-                                                       countDelete + countInsert,
-                                                       [ DIFF_DELETE, textDelete ], [ DIFF_INSERT, textInsert ]
-                                               );
-                                       }
-                                       pointer = pointer - countDelete - countInsert +
-                                               ( countDelete ? 1 : 0 ) + ( countInsert ? 1 : 0 ) + 1;
-                               } else if ( pointer !== 0 && diffs[ pointer - 1 ][ 0 ] === DIFF_EQUAL ) {
-
-                                       // Merge this equality with the previous one.
-                                       diffs[ pointer - 1 ][ 1 ] += diffs[ pointer ][ 1 ];
-                                       diffs.splice( pointer, 1 );
-                               } else {
-                                       pointer++;
-                               }
-                               countInsert = 0;
-                               countDelete = 0;
-                               textDelete = "";
-                               textInsert = "";
-                               break;
-                       }
-               }
-               if ( diffs[ diffs.length - 1 ][ 1 ] === "" ) {
-                       diffs.pop(); // Remove the dummy entry at the end.
-               }
-
-               // Second pass: look for single edits surrounded on both sides by equalities
-               // which can be shifted sideways to eliminate an equality.
-               // e.g: A<ins>BA</ins>C -> <ins>AB</ins>AC
-               changes = false;
-               pointer = 1;
-
-               // Intentionally ignore the first and last element (don't need checking).
-               while ( pointer < diffs.length - 1 ) {
-                       if ( diffs[ pointer - 1 ][ 0 ] === DIFF_EQUAL &&
-                                       diffs[ pointer + 1 ][ 0 ] === DIFF_EQUAL ) {
-
-                               diffPointer = diffs[ pointer ][ 1 ];
-                               position = diffPointer.substring(
-                                       diffPointer.length - diffs[ pointer - 1 ][ 1 ].length
-                               );
-
-                               // This is a single edit surrounded by equalities.
-                               if ( position === diffs[ pointer - 1 ][ 1 ] ) {
-
-                                       // Shift the edit over the previous equality.
-                                       diffs[ pointer ][ 1 ] = diffs[ pointer - 1 ][ 1 ] +
-                                               diffs[ pointer ][ 1 ].substring( 0, diffs[ pointer ][ 1 ].length -
-                                                       diffs[ pointer - 1 ][ 1 ].length );
-                                       diffs[ pointer + 1 ][ 1 ] =
-                                               diffs[ pointer - 1 ][ 1 ] + diffs[ pointer + 1 ][ 1 ];
-                                       diffs.splice( pointer - 1, 1 );
-                                       changes = true;
-                               } else if ( diffPointer.substring( 0, diffs[ pointer + 1 ][ 1 ].length ) ===
-                                               diffs[ pointer + 1 ][ 1 ] ) {
-
-                                       // Shift the edit over the next equality.
-                                       diffs[ pointer - 1 ][ 1 ] += diffs[ pointer + 1 ][ 1 ];
-                                       diffs[ pointer ][ 1 ] =
-                                               diffs[ pointer ][ 1 ].substring( diffs[ pointer + 1 ][ 1 ].length ) +
-                                               diffs[ pointer + 1 ][ 1 ];
-                                       diffs.splice( pointer + 1, 1 );
-                                       changes = true;
-                               }
-                       }
-                       pointer++;
-               }
-               // If shifts were made, the diff needs reordering and another shift sweep.
-               if ( changes ) {
-                       this.diffCleanupMerge( diffs );
-               }
-       };
-
-       return function( o, n ) {
-               var diff, output, text;
-               diff = new DiffMatchPatch();
-               output = diff.DiffMain( o, n );
-               diff.diffCleanupEfficiency( output );
-               text = diff.diffPrettyHtml( output );
-
-               return text;
-       };
-}() );
-
-// Get a reference to the global object, like window in browsers
-}( (function() {
-       return this;
-})() ));
-
-(function() {
-
-// Don't load the HTML Reporter on non-Browser environments
-if ( typeof window === "undefined" || !window.document ) {
-       return;
-}
-
-// Deprecated QUnit.init - Ref #530
-// Re-initialize the configuration options
-QUnit.init = function() {
-       var tests, banner, result, qunit,
-               config = QUnit.config;
-
-       config.stats = { all: 0, bad: 0 };
-       config.moduleStats = { all: 0, bad: 0 };
-       config.started = 0;
-       config.updateRate = 1000;
-       config.blocking = false;
-       config.autostart = true;
-       config.autorun = false;
-       config.filter = "";
-       config.queue = [];
-
-       // Return on non-browser environments
-       // This is necessary to not break on node tests
-       if ( typeof window === "undefined" ) {
-               return;
-       }
-
-       qunit = id( "qunit" );
-       if ( qunit ) {
-               qunit.innerHTML =
-                       "<h1 id='qunit-header'>" + escapeText( document.title ) + "</h1>" +
-                       "<h2 id='qunit-banner'></h2>" +
-                       "<div id='qunit-testrunner-toolbar'></div>" +
-                       "<h2 id='qunit-userAgent'></h2>" +
-                       "<ol id='qunit-tests'></ol>";
-       }
-
-       tests = id( "qunit-tests" );
-       banner = id( "qunit-banner" );
-       result = id( "qunit-testresult" );
-
-       if ( tests ) {
-               tests.innerHTML = "";
-       }
-
-       if ( banner ) {
-               banner.className = "";
-       }
-
-       if ( result ) {
-               result.parentNode.removeChild( result );
-       }
-
-       if ( tests ) {
-               result = document.createElement( "p" );
-               result.id = "qunit-testresult";
-               result.className = "result";
-               tests.parentNode.insertBefore( result, tests );
-               result.innerHTML = "Running...<br />&#160;";
-       }
-};
-
-var config = QUnit.config,
-       collapseNext = false,
-       hasOwn = Object.prototype.hasOwnProperty,
-       defined = {
-               document: window.document !== undefined,
-               sessionStorage: (function() {
-                       var x = "qunit-test-string";
-                       try {
-                               sessionStorage.setItem( x, x );
-                               sessionStorage.removeItem( x );
-                               return true;
-                       } catch ( e ) {
-                               return false;
-                       }
-               }())
-       },
-       modulesList = [];
-
-/**
-* Escape text for attribute or text content.
-*/
-function escapeText( s ) {
-       if ( !s ) {
-               return "";
-       }
-       s = s + "";
-
-       // Both single quotes and double quotes (for attributes)
-       return s.replace( /['"<>&]/g, function( s ) {
-               switch ( s ) {
-               case "'":
-                       return "&#039;";
-               case "\"":
-                       return "&quot;";
-               case "<":
-                       return "&lt;";
-               case ">":
-                       return "&gt;";
-               case "&":
-                       return "&amp;";
-               }
-       });
-}
-
-/**
- * @param {HTMLElement} elem
- * @param {string} type
- * @param {Function} fn
- */
-function addEvent( elem, type, fn ) {
-       if ( elem.addEventListener ) {
-
-               // Standards-based browsers
-               elem.addEventListener( type, fn, false );
-       } else if ( elem.attachEvent ) {
-
-               // support: IE <9
-               elem.attachEvent( "on" + type, function() {
-                       var event = window.event;
-                       if ( !event.target ) {
-                               event.target = event.srcElement || document;
-                       }
-
-                       fn.call( elem, event );
-               });
-       }
-}
-
-/**
- * @param {Array|NodeList} elems
- * @param {string} type
- * @param {Function} fn
- */
-function addEvents( elems, type, fn ) {
-       var i = elems.length;
-       while ( i-- ) {
-               addEvent( elems[ i ], type, fn );
-       }
-}
-
-function hasClass( elem, name ) {
-       return ( " " + elem.className + " " ).indexOf( " " + name + " " ) >= 0;
-}
-
-function addClass( elem, name ) {
-       if ( !hasClass( elem, name ) ) {
-               elem.className += ( elem.className ? " " : "" ) + name;
-       }
-}
-
-function toggleClass( elem, name ) {
-       if ( hasClass( elem, name ) ) {
-               removeClass( elem, name );
-       } else {
-               addClass( elem, name );
-       }
-}
-
-function removeClass( elem, name ) {
-       var set = " " + elem.className + " ";
-
-       // Class name may appear multiple times
-       while ( set.indexOf( " " + name + " " ) >= 0 ) {
-               set = set.replace( " " + name + " ", " " );
-       }
-
-       // trim for prettiness
-       elem.className = typeof set.trim === "function" ? set.trim() : set.replace( /^\s+|\s+$/g, "" );
-}
-
-function id( name ) {
-       return defined.document && document.getElementById && document.getElementById( name );
-}
-
-function getUrlConfigHtml() {
-       var i, j, val,
-               escaped, escapedTooltip,
-               selection = false,
-               len = config.urlConfig.length,
-               urlConfigHtml = "";
-
-       for ( i = 0; i < len; i++ ) {
-               val = config.urlConfig[ i ];
-               if ( typeof val === "string" ) {
-                       val = {
-                               id: val,
-                               label: val
-                       };
-               }
-
-               escaped = escapeText( val.id );
-               escapedTooltip = escapeText( val.tooltip );
-
-               if ( config[ val.id ] === undefined ) {
-                       config[ val.id ] = QUnit.urlParams[ val.id ];
-               }
-
-               if ( !val.value || typeof val.value === "string" ) {
-                       urlConfigHtml += "<input id='qunit-urlconfig-" + escaped +
-                               "' name='" + escaped + "' type='checkbox'" +
-                               ( val.value ? " value='" + escapeText( val.value ) + "'" : "" ) +
-                               ( config[ val.id ] ? " checked='checked'" : "" ) +
-                               " title='" + escapedTooltip + "' /><label for='qunit-urlconfig-" + escaped +
-                               "' title='" + escapedTooltip + "'>" + val.label + "</label>";
-               } else {
-                       urlConfigHtml += "<label for='qunit-urlconfig-" + escaped +
-                               "' title='" + escapedTooltip + "'>" + val.label +
-                               ": </label><select id='qunit-urlconfig-" + escaped +
-                               "' name='" + escaped + "' title='" + escapedTooltip + "'><option></option>";
-
-                       if ( QUnit.is( "array", val.value ) ) {
-                               for ( j = 0; j < val.value.length; j++ ) {
-                                       escaped = escapeText( val.value[ j ] );
-                                       urlConfigHtml += "<option value='" + escaped + "'" +
-                                               ( config[ val.id ] === val.value[ j ] ?
-                                                       ( selection = true ) && " selected='selected'" : "" ) +
-                                               ">" + escaped + "</option>";
-                               }
-                       } else {
-                               for ( j in val.value ) {
-                                       if ( hasOwn.call( val.value, j ) ) {
-                                               urlConfigHtml += "<option value='" + escapeText( j ) + "'" +
-                                                       ( config[ val.id ] === j ?
-                                                               ( selection = true ) && " selected='selected'" : "" ) +
-                                                       ">" + escapeText( val.value[ j ] ) + "</option>";
-                                       }
-                               }
-                       }
-                       if ( config[ val.id ] && !selection ) {
-                               escaped = escapeText( config[ val.id ] );
-                               urlConfigHtml += "<option value='" + escaped +
-                                       "' selected='selected' disabled='disabled'>" + escaped + "</option>";
-                       }
-                       urlConfigHtml += "</select>";
-               }
-       }
-
-       return urlConfigHtml;
-}
-
-// Handle "click" events on toolbar checkboxes and "change" for select menus.
-// Updates the URL with the new state of `config.urlConfig` values.
-function toolbarChanged() {
-       var updatedUrl, value,
-               field = this,
-               params = {};
-
-       // Detect if field is a select menu or a checkbox
-       if ( "selectedIndex" in field ) {
-               value = field.options[ field.selectedIndex ].value || undefined;
-       } else {
-               value = field.checked ? ( field.defaultValue || true ) : undefined;
-       }
-
-       params[ field.name ] = value;
-       updatedUrl = setUrl( params );
-
-       if ( "hidepassed" === field.name && "replaceState" in window.history ) {
-               config[ field.name ] = value || false;
-               if ( value ) {
-                       addClass( id( "qunit-tests" ), "hidepass" );
-               } else {
-                       removeClass( id( "qunit-tests" ), "hidepass" );
-               }
-
-               // It is not necessary to refresh the whole page
-               window.history.replaceState( null, "", updatedUrl );
-       } else {
-               window.location = updatedUrl;
-       }
-}
-
-function setUrl( params ) {
-       var key,
-               querystring = "?";
-
-       params = QUnit.extend( QUnit.extend( {}, QUnit.urlParams ), params );
-
-       for ( key in params ) {
-               if ( hasOwn.call( params, key ) ) {
-                       if ( params[ key ] === undefined ) {
-                               continue;
-                       }
-                       querystring += encodeURIComponent( key );
-                       if ( params[ key ] !== true ) {
-                               querystring += "=" + encodeURIComponent( params[ key ] );
-                       }
-                       querystring += "&";
-               }
-       }
-       return location.protocol + "//" + location.host +
-               location.pathname + querystring.slice( 0, -1 );
-}
-
-function applyUrlParams() {
-       var selectedModule,
-               modulesList = id( "qunit-modulefilter" ),
-               filter = id( "qunit-filter-input" ).value;
-
-       selectedModule = modulesList ?
-               decodeURIComponent( modulesList.options[ modulesList.selectedIndex ].value ) :
-               undefined;
-
-       window.location = setUrl({
-               module: ( selectedModule === "" ) ? undefined : selectedModule,
-               filter: ( filter === "" ) ? undefined : filter,
-
-               // Remove testId filter
-               testId: undefined
-       });
-}
-
-function toolbarUrlConfigContainer() {
-       var urlConfigContainer = document.createElement( "span" );
-
-       urlConfigContainer.innerHTML = getUrlConfigHtml();
-       addClass( urlConfigContainer, "qunit-url-config" );
-
-       // For oldIE support:
-       // * Add handlers to the individual elements instead of the container
-       // * Use "click" instead of "change" for checkboxes
-       addEvents( urlConfigContainer.getElementsByTagName( "input" ), "click", toolbarChanged );
-       addEvents( urlConfigContainer.getElementsByTagName( "select" ), "change", toolbarChanged );
-
-       return urlConfigContainer;
-}
-
-function toolbarLooseFilter() {
-       var filter = document.createElement( "form" ),
-               label = document.createElement( "label" ),
-               input = document.createElement( "input" ),
-               button = document.createElement( "button" );
-
-       addClass( filter, "qunit-filter" );
-
-       label.innerHTML = "Filter: ";
-
-       input.type = "text";
-       input.value = config.filter || "";
-       input.name = "filter";
-       input.id = "qunit-filter-input";
-
-       button.innerHTML = "Go";
-
-       label.appendChild( input );
-
-       filter.appendChild( label );
-       filter.appendChild( button );
-       addEvent( filter, "submit", function( ev ) {
-               applyUrlParams();
-
-               if ( ev && ev.preventDefault ) {
-                       ev.preventDefault();
-               }
-
-               return false;
-       });
-
-       return filter;
-}
-
-function toolbarModuleFilterHtml() {
-       var i,
-               moduleFilterHtml = "";
-
-       if ( !modulesList.length ) {
-               return false;
-       }
-
-       modulesList.sort(function( a, b ) {
-               return a.localeCompare( b );
-       });
-
-       moduleFilterHtml += "<label for='qunit-modulefilter'>Module: </label>" +
-               "<select id='qunit-modulefilter' name='modulefilter'><option value='' " +
-               ( QUnit.urlParams.module === undefined ? "selected='selected'" : "" ) +
-               ">< All Modules ></option>";
-
-       for ( i = 0; i < modulesList.length; i++ ) {
-               moduleFilterHtml += "<option value='" +
-                       escapeText( encodeURIComponent( modulesList[ i ] ) ) + "' " +
-                       ( QUnit.urlParams.module === modulesList[ i ] ? "selected='selected'" : "" ) +
-                       ">" + escapeText( modulesList[ i ] ) + "</option>";
-       }
-       moduleFilterHtml += "</select>";
-
-       return moduleFilterHtml;
-}
-
-function toolbarModuleFilter() {
-       var toolbar = id( "qunit-testrunner-toolbar" ),
-               moduleFilter = document.createElement( "span" ),
-               moduleFilterHtml = toolbarModuleFilterHtml();
-
-       if ( !toolbar || !moduleFilterHtml ) {
-               return false;
-       }
-
-       moduleFilter.setAttribute( "id", "qunit-modulefilter-container" );
-       moduleFilter.innerHTML = moduleFilterHtml;
-
-       addEvent( moduleFilter.lastChild, "change", applyUrlParams );
-
-       toolbar.appendChild( moduleFilter );
-}
-
-function appendToolbar() {
-       var toolbar = id( "qunit-testrunner-toolbar" );
-
-       if ( toolbar ) {
-               toolbar.appendChild( toolbarUrlConfigContainer() );
-               toolbar.appendChild( toolbarLooseFilter() );
-       }
-}
-
-function appendHeader() {
-       var header = id( "qunit-header" );
-
-       if ( header ) {
-               header.innerHTML = "<a href='" +
-                       setUrl({ filter: undefined, module: undefined, testId: undefined }) +
-                       "'>" + header.innerHTML + "</a> ";
-       }
-}
-
-function appendBanner() {
-       var banner = id( "qunit-banner" );
-
-       if ( banner ) {
-               banner.className = "";
-       }
-}
-
-function appendTestResults() {
-       var tests = id( "qunit-tests" ),
-               result = id( "qunit-testresult" );
-
-       if ( result ) {
-               result.parentNode.removeChild( result );
-       }
-
-       if ( tests ) {
-               tests.innerHTML = "";
-               result = document.createElement( "p" );
-               result.id = "qunit-testresult";
-               result.className = "result";
-               tests.parentNode.insertBefore( result, tests );
-               result.innerHTML = "Running...<br />&#160;";
-       }
-}
-
-function storeFixture() {
-       var fixture = id( "qunit-fixture" );
-       if ( fixture ) {
-               config.fixture = fixture.innerHTML;
-       }
-}
-
-function appendFilteredTest() {
-       var testId = QUnit.config.testId;
-       if ( !testId || testId.length <= 0 ) {
-               return "";
-       }
-       return "<div id='qunit-filteredTest'>Rerunning selected tests: " + testId.join(", ") +
-               " <a id='qunit-clearFilter' href='" +
-               setUrl({ filter: undefined, module: undefined, testId: undefined }) +
-               "'>" + "Run all tests" + "</a></div>";
-}
-
-function appendUserAgent() {
-       var userAgent = id( "qunit-userAgent" );
-
-       if ( userAgent ) {
-               userAgent.innerHTML = "";
-               userAgent.appendChild(
-                       document.createTextNode(
-                               "QUnit " + QUnit.version + "; " + navigator.userAgent
-                       )
-               );
-       }
-}
-
-function appendTestsList( modules ) {
-       var i, l, x, z, test, moduleObj;
-
-       for ( i = 0, l = modules.length; i < l; i++ ) {
-               moduleObj = modules[ i ];
-
-               if ( moduleObj.name ) {
-                       modulesList.push( moduleObj.name );
-               }
-
-               for ( x = 0, z = moduleObj.tests.length; x < z; x++ ) {
-                       test = moduleObj.tests[ x ];
-
-                       appendTest( test.name, test.testId, moduleObj.name );
-               }
-       }
-}
-
-function appendTest( name, testId, moduleName ) {
-       var title, rerunTrigger, testBlock, assertList,
-               tests = id( "qunit-tests" );
-
-       if ( !tests ) {
-               return;
-       }
-
-       title = document.createElement( "strong" );
-       title.innerHTML = getNameHtml( name, moduleName );
-
-       rerunTrigger = document.createElement( "a" );
-       rerunTrigger.innerHTML = "Rerun";
-       rerunTrigger.href = setUrl({ testId: testId });
-
-       testBlock = document.createElement( "li" );
-       testBlock.appendChild( title );
-       testBlock.appendChild( rerunTrigger );
-       testBlock.id = "qunit-test-output-" + testId;
-
-       assertList = document.createElement( "ol" );
-       assertList.className = "qunit-assert-list";
-
-       testBlock.appendChild( assertList );
-
-       tests.appendChild( testBlock );
-}
-
-// HTML Reporter initialization and load
-QUnit.begin(function( details ) {
-       var qunit = id( "qunit" );
-
-       // Fixture is the only one necessary to run without the #qunit element
-       storeFixture();
-
-       if ( qunit ) {
-               qunit.innerHTML =
-                       "<h1 id='qunit-header'>" + escapeText( document.title ) + "</h1>" +
-                       "<h2 id='qunit-banner'></h2>" +
-                       "<div id='qunit-testrunner-toolbar'></div>" +
-                       appendFilteredTest() +
-                       "<h2 id='qunit-userAgent'></h2>" +
-                       "<ol id='qunit-tests'></ol>";
-       }
-
-       appendHeader();
-       appendBanner();
-       appendTestResults();
-       appendUserAgent();
-       appendToolbar();
-       appendTestsList( details.modules );
-       toolbarModuleFilter();
-
-       if ( qunit && config.hidepassed ) {
-               addClass( qunit.lastChild, "hidepass" );
-       }
-});
-
-QUnit.done(function( details ) {
-       var i, key,
-               banner = id( "qunit-banner" ),
-               tests = id( "qunit-tests" ),
-               html = [
-                       "Tests completed in ",
-                       details.runtime,
-                       " milliseconds.<br />",
-                       "<span class='passed'>",
-                       details.passed,
-                       "</span> assertions of <span class='total'>",
-                       details.total,
-                       "</span> passed, <span class='failed'>",
-                       details.failed,
-                       "</span> failed."
-               ].join( "" );
-
-       if ( banner ) {
-               banner.className = details.failed ? "qunit-fail" : "qunit-pass";
-       }
-
-       if ( tests ) {
-               id( "qunit-testresult" ).innerHTML = html;
-       }
-
-       if ( config.altertitle && defined.document && document.title ) {
-
-               // show âœ– for good, âœ” for bad suite result in title
-               // use escape sequences in case file gets loaded with non-utf-8-charset
-               document.title = [
-                       ( details.failed ? "\u2716" : "\u2714" ),
-                       document.title.replace( /^[\u2714\u2716] /i, "" )
-               ].join( " " );
-       }
-
-       // clear own sessionStorage items if all tests passed
-       if ( config.reorder && defined.sessionStorage && details.failed === 0 ) {
-               for ( i = 0; i < sessionStorage.length; i++ ) {
-                       key = sessionStorage.key( i++ );
-                       if ( key.indexOf( "qunit-test-" ) === 0 ) {
-                               sessionStorage.removeItem( key );
-                       }
-               }
-       }
-
-       // scroll back to top to show results
-       if ( config.scrolltop && window.scrollTo ) {
-               window.scrollTo( 0, 0 );
-       }
-});
-
-function getNameHtml( name, module ) {
-       var nameHtml = "";
-
-       if ( module ) {
-               nameHtml = "<span class='module-name'>" + escapeText( module ) + "</span>: ";
-       }
-
-       nameHtml += "<span class='test-name'>" + escapeText( name ) + "</span>";
-
-       return nameHtml;
-}
-
-QUnit.testStart(function( details ) {
-       var running, testBlock, bad;
-
-       testBlock = id( "qunit-test-output-" + details.testId );
-       if ( testBlock ) {
-               testBlock.className = "running";
-       } else {
-
-               // Report later registered tests
-               appendTest( details.name, details.testId, details.module );
-       }
-
-       running = id( "qunit-testresult" );
-       if ( running ) {
-               bad = QUnit.config.reorder && defined.sessionStorage &&
-                       +sessionStorage.getItem( "qunit-test-" + details.module + "-" + details.name );
-
-               running.innerHTML = ( bad ?
-                       "Rerunning previously failed test: <br />" :
-                       "Running: <br />" ) +
-                       getNameHtml( details.name, details.module );
-       }
-
-});
-
-function stripHtml( string ) {
-       // strip tags, html entity and whitespaces
-       return string.replace(/<\/?[^>]+(>|$)/g, "").replace(/\&quot;/g, "").replace(/\s+/g, "");
-}
-
-QUnit.log(function( details ) {
-       var assertList, assertLi,
-               message, expected, actual, diff,
-               showDiff = false,
-               testItem = id( "qunit-test-output-" + details.testId );
-
-       if ( !testItem ) {
-               return;
-       }
-
-       message = escapeText( details.message ) || ( details.result ? "okay" : "failed" );
-       message = "<span class='test-message'>" + message + "</span>";
-       message += "<span class='runtime'>@ " + details.runtime + " ms</span>";
-
-       // pushFailure doesn't provide details.expected
-       // when it calls, it's implicit to also not show expected and diff stuff
-       // Also, we need to check details.expected existence, as it can exist and be undefined
-       if ( !details.result && hasOwn.call( details, "expected" ) ) {
-               if ( details.negative ) {
-                       expected = escapeText( "NOT " + QUnit.dump.parse( details.expected ) );
-               } else {
-                       expected = escapeText( QUnit.dump.parse( details.expected ) );
-               }
-
-               actual = escapeText( QUnit.dump.parse( details.actual ) );
-               message += "<table><tr class='test-expected'><th>Expected: </th><td><pre>" +
-                       expected +
-                       "</pre></td></tr>";
-
-               if ( actual !== expected ) {
-
-                       message += "<tr class='test-actual'><th>Result: </th><td><pre>" +
-                               actual + "</pre></td></tr>";
-
-                       // Don't show diff if actual or expected are booleans
-                       if ( !( /^(true|false)$/.test( actual ) ) &&
-                                       !( /^(true|false)$/.test( expected ) ) ) {
-                               diff = QUnit.diff( expected, actual );
-                               showDiff = stripHtml( diff ).length !==
-                                       stripHtml( expected ).length +
-                                       stripHtml( actual ).length;
-                       }
-
-                       // Don't show diff if expected and actual are totally different
-                       if ( showDiff ) {
-                               message += "<tr class='test-diff'><th>Diff: </th><td><pre>" +
-                                       diff + "</pre></td></tr>";
-                       }
-               } else if ( expected.indexOf( "[object Array]" ) !== -1 ||
-                               expected.indexOf( "[object Object]" ) !== -1 ) {
-                       message += "<tr class='test-message'><th>Message: </th><td>" +
-                               "Diff suppressed as the depth of object is more than current max depth (" +
-                               QUnit.config.maxDepth + ").<p>Hint: Use <code>QUnit.dump.maxDepth</code> to " +
-                               " run with a higher max depth or <a href='" + setUrl({ maxDepth: -1 }) + "'>" +
-                               "Rerun</a> without max depth.</p></td></tr>";
-               }
-
-               if ( details.source ) {
-                       message += "<tr class='test-source'><th>Source: </th><td><pre>" +
-                               escapeText( details.source ) + "</pre></td></tr>";
-               }
-
-               message += "</table>";
-
-       // this occurs when pushFailure is set and we have an extracted stack trace
-       } else if ( !details.result && details.source ) {
-               message += "<table>" +
-                       "<tr class='test-source'><th>Source: </th><td><pre>" +
-                       escapeText( details.source ) + "</pre></td></tr>" +
-                       "</table>";
-       }
-
-       assertList = testItem.getElementsByTagName( "ol" )[ 0 ];
-
-       assertLi = document.createElement( "li" );
-       assertLi.className = details.result ? "pass" : "fail";
-       assertLi.innerHTML = message;
-       assertList.appendChild( assertLi );
-});
-
-QUnit.testDone(function( details ) {
-       var testTitle, time, testItem, assertList,
-               good, bad, testCounts, skipped, sourceName,
-               tests = id( "qunit-tests" );
-
-       if ( !tests ) {
-               return;
-       }
-
-       testItem = id( "qunit-test-output-" + details.testId );
-
-       assertList = testItem.getElementsByTagName( "ol" )[ 0 ];
-
-       good = details.passed;
-       bad = details.failed;
-
-       // store result when possible
-       if ( config.reorder && defined.sessionStorage ) {
-               if ( bad ) {
-                       sessionStorage.setItem( "qunit-test-" + details.module + "-" + details.name, bad );
-               } else {
-                       sessionStorage.removeItem( "qunit-test-" + details.module + "-" + details.name );
-               }
-       }
-
-       if ( bad === 0 ) {
-
-               // Collapse the passing tests
-               addClass( assertList, "qunit-collapsed" );
-       } else if ( bad && config.collapse && !collapseNext ) {
-
-               // Skip collapsing the first failing test
-               collapseNext = true;
-       } else {
-
-               // Collapse remaining tests
-               addClass( assertList, "qunit-collapsed" );
-       }
-
-       // testItem.firstChild is the test name
-       testTitle = testItem.firstChild;
-
-       testCounts = bad ?
-               "<b class='failed'>" + bad + "</b>, " + "<b class='passed'>" + good + "</b>, " :
-               "";
-
-       testTitle.innerHTML += " <b class='counts'>(" + testCounts +
-               details.assertions.length + ")</b>";
-
-       if ( details.skipped ) {
-               testItem.className = "skipped";
-               skipped = document.createElement( "em" );
-               skipped.className = "qunit-skipped-label";
-               skipped.innerHTML = "skipped";
-               testItem.insertBefore( skipped, testTitle );
-       } else {
-               addEvent( testTitle, "click", function() {
-                       toggleClass( assertList, "qunit-collapsed" );
-               });
-
-               testItem.className = bad ? "fail" : "pass";
-
-               time = document.createElement( "span" );
-               time.className = "runtime";
-               time.innerHTML = details.runtime + " ms";
-               testItem.insertBefore( time, assertList );
-       }
-
-       // Show the source of the test when showing assertions
-       if ( details.source ) {
-               sourceName = document.createElement( "p" );
-               sourceName.innerHTML = "<strong>Source: </strong>" + details.source;
-               addClass( sourceName, "qunit-source" );
-               if ( bad === 0 ) {
-                       addClass( sourceName, "qunit-collapsed" );
-               }
-               addEvent( testTitle, "click", function() {
-                       toggleClass( sourceName, "qunit-collapsed" );
-               });
-               testItem.appendChild( sourceName );
-       }
-});
-
-if ( defined.document ) {
-
-       // Avoid readyState issue with phantomjs
-       // Ref: #818
-       var notPhantom = ( function( p ) {
-               return !( p && p.version && p.version.major > 0 );
-       } )( window.phantom );
-
-       if ( notPhantom && document.readyState === "complete" ) {
-               QUnit.load();
-       } else {
-               addEvent( window, "load", QUnit.load );
-       }
-} else {
-       config.pageLoaded = true;
-       config.autorun = true;
-}
-
-})();
diff --git a/adaptors/emscripten/wrappers/tests/shaders.js b/adaptors/emscripten/wrappers/tests/shaders.js
deleted file mode 100644 (file)
index 94af16a..0000000
+++ /dev/null
@@ -1,105 +0,0 @@
-
-QUnit.module("Shaders", {
-    setup : function() {
-        QUnit.stop();
-        var that = this;
-        this.cb = function(e) {
-          QUnit.ok(true, "Scene loaded");
-          var iframe = document.getElementById('daliframe');
-          that.doc =  iframe.contentDocument || iframe.contentWindow.document;
-          that.doc.Module.postDaliWrapperRun = function() {
-            dali = that.doc.Module;
-            QUnit.start();
-          };
-        };
-        loadDocument("dali-page.html"+window.location.search, this.cb);
-    },
-    teardown : function() {
-        var v = document.getElementById("daliframe");
-        v.removeEventListener("load", this.cb, true);
-    }
-});
-
-QUnit.test( "shader meta data", function( assert ) {
-  var info = new dali.ShaderInfo();
-
-  var vertex;
-  var fragment;
-
-  vertex = "\n" +
-    "attribute mediump vec3 aPosition;\n" +
-    "attribute mediump vec2 aTexCoord;\n" +
-    "varying mediump vec2 vTexCoord;\n" +
-    "uniform mediump vec3 uSize;\n" +
-    "// uniform mediump vec3 unusedUniform;\n" +
-    "uniform mediump mat4 uModelView;\n" +
-    "uniform mediump mat4 uProjection;\n" +
-    "\n" +
-    "void main(void)\n" +
-    "{\n" +
-    "  gl_Position = uProjection * uModelView * vec4(aPosition, 1.0);\n" +
-    "  gl_Position.xyz *= uSize;\n" +
-    "  vTexCoord = aTexCoord;\n" +
-    "}\n";
-
-  fragment = "precision mediump float;\n" +
-    "\n" +
-    "uniform sampler2D sTexture;\n" +
-    "uniform mediump vec4 uMyColor; // {min:[0,0,0,0], max:[1,1,1,1]}\n" +
-    "uniform mediump vec4 uColor;\n" +
-    "varying mediump vec2 vTexCoord;\n" +
-    "\n" +
-    "void main()\n" +
-    "{\n" +
-    "  gl_FragColor = texture2D( sTexture, vTexCoord ) * uColor * uMyColor;\n" +
-    "}\n";
-
-  var canvas = document.createElement("canvas");
-  var meta = info.fromCompilation(canvas.getContext("webgl"), vertex, fragment);
-
-  var uniforms = { uSize: 1,
-                   uModelView: 1,
-                   uProjection: 1,
-                   uMyColor: 1,
-                   uColor: 1
-                 };
-
-  assert.ok(meta.hasError === false);
-  var name;
-  var metaUniformName;
-  var found;
-
-  for(name in uniforms) {
-    found = false;
-    for(metaUniformName in meta.uniforms) {
-      if(metaUniformName === name) {
-        found = true;
-        break;
-      }
-    }
-    assert.ok(found, "missing:" + name);
-  }
-
-  assert.ok(compareArrays(meta.uniformUISpec.uMyColor.min, [0, 0, 0, 0]));
-  assert.ok(compareArrays(meta.uniformUISpec.uMyColor.max, [1, 1, 1, 1]));
-
-
-  meta = info.fromRegEx(vertex, fragment);
-
-  assert.ok(meta.hasError === false);
-
-  for(name in uniforms) {
-    found = false;
-    for(metaUniformName in meta.uniforms) {
-      if(metaUniformName === name) {
-        found = true;
-        break;
-      }
-    }
-    assert.ok(found, "missing:" + name);
-  }
-
-  assert.ok(compareArrays(meta.uniformUISpec.uMyColor.min, [0, 0, 0, 0]));
-  assert.ok(compareArrays(meta.uniformUISpec.uMyColor.max, [1, 1, 1, 1]));
-
-});
diff --git a/adaptors/emscripten/wrappers/tests/signals.js b/adaptors/emscripten/wrappers/tests/signals.js
deleted file mode 100644 (file)
index de03121..0000000
+++ /dev/null
@@ -1,46 +0,0 @@
-
-QUnit.module("Signals", {
-    setup : function() {
-        QUnit.stop();
-        var that = this;
-        this.cb = function(e) {
-          QUnit.ok(true, "Scene loaded");
-          var iframe = document.getElementById('daliframe');
-          that.doc =  iframe.contentDocument || iframe.contentWindow.document;
-          that.doc.Module.postDaliWrapperRun = function() {
-            dali = that.doc.Module;
-            QUnit.start();
-          };
-        };
-        loadDocument("dali-page.html"+window.location.search, this.cb);
-    },
-    teardown : function() {
-        var v = document.getElementById("daliframe");
-        v.removeEventListener("load", this.cb, true);
-    }
-});
-
-QUnit.test( "hello test", function( assert ) {
-  var done = false;
-
-  function onStage() {
-    done = true;
-  }
-
-  var actor = new dali.Actor();
-  actor.parentOrigin = [0.5, 0.5, 0.5];
-  actor.anchorPoint = [0.5, 0.5, 0.5];
-  actor.text = "actor";
-  actor.name = actor.text;
-  actor.size = [100, 100, 1];
-  actor.position = [0, 0, 10];
-
-  actor.connect("onStage", onStage);
-
-  dali.stage.add(actor);
-
-  dali.updateFrame();
-
-  assert.ok(done === true);
-
-});
diff --git a/adaptors/emscripten/wrappers/tests/utilities.js b/adaptors/emscripten/wrappers/tests/utilities.js
deleted file mode 100644 (file)
index 8bbc251..0000000
+++ /dev/null
@@ -1,102 +0,0 @@
-var EPSILON = 0.005;
-
-function compareArrays(a, b) {
-  "use strict";
-  if (Array.isArray(a) && Array.isArray(b)) {
-    if (a.length === b.length) {
-      for (var i = 0, len = a.length; i < len; i++) {
-        if (Array.isArray(a[i])) {
-          if (Array.isArray(b[i])) {
-            if (!compareArrays(a[i], b[i])) {
-              return false;
-            }
-          } else {
-            return false;
-          }
-        } else {
-          if (typeof (a[i]) === "number") {
-            if (typeof (b[i]) !== "number") {
-              return false;
-            } else {
-              if (Math.abs(a[i]) > Math.abs(b[i]) + EPSILON ||
-                  Math.abs(a[i]) < Math.abs(b[i]) - EPSILON) {
-                return false;
-              }
-            }
-          } else {
-            if (a[i] !== b[i]) {
-              return false;
-            }
-          }
-        }
-      }
-      return true;
-    }
-  }
-  return false;
-}
-
-function collectByName(collection) {
-  var root = dali.stage.getRootLayer();
-  if (collection === undefined) {
-    collection = {};
-  }
-  var op = function(actor) {
-    if (actor.name) {
-      collection[actor.name] = actor;
-    }
-    return true;
-  };
-
-  dali.debug.depthVisit(root, op, true);
-
-  return collection;
-}
-
-function square(color, size) {
-  var a = dali.createSolidColorActor(color, 0, [0, 0, 0, 1], 0);
-  a.size = size;
-  return a;
-}
-
-function threeSquares() {
-  var root = dali.stage.getRootLayer();
-
-  var a = square([1, 0, 0, 1], [200, 200, 0]);
-  a.name = "red";
-  a.position = [-100, 0, -20];
-  root.add(a);
-  a.delete();
-
-  a = square([0, 1, 0, 1], [200, 200, 0]);
-  a.name = "green";
-  a.position = [0, -100, -10];
-  root.add(a);
-  a.delete();
-
-  a = square([0, 0, 1, 1], [200, 200, 0]);
-  a.name = "blue";
-  a.position = [0, -100, 0];
-  root.add(a);
-  a.delete();
-
-  //  root.delete();
-}
-
-function clear() {
-  var root = dali.stage.getRootLayer();
-  var children = root.getChildren();
-
-  for (var i = 0, len = children.length; i < len; i++) {
-    root.remove(children[i]);
-    children[i].delete(); // delete the wrapper
-  }
-  //  root.delete(); // wrapper
-}
-
-var loadDocument = function(url, f) {
-    var v = document.getElementById("daliframe");
-    QUnit.ok(v, "Found frame.");
-    v.addEventListener("load", f, true);
-    v.src = url;
-};
diff --git a/adaptors/emscripten/wrappers/tests/views.js b/adaptors/emscripten/wrappers/tests/views.js
deleted file mode 100644 (file)
index c4cfbb7..0000000
+++ /dev/null
@@ -1,151 +0,0 @@
-
-QUnit.module("Views", {
-    setup : function() {
-        QUnit.stop();
-        var that = this;
-        this.cb = function(e) {
-          QUnit.ok(true, "Scene loaded");
-          var iframe = document.getElementById('daliframe');
-          that.doc =  iframe.contentDocument || iframe.contentWindow.document;
-          that.doc.Module.postDaliWrapperRun = function() {
-            dali = that.doc.Module;
-            QUnit.start();
-          };
-        };
-        loadDocument("dali-page.html"+window.location.search, this.cb);
-    },
-    teardown : function() {
-        var v = document.getElementById("daliframe");
-        v.removeEventListener("load", this.cb, true);
-    }
-});
-
-function addOnScreenQuad(assert)
-{
-  var halfQuadSize = 0.5;
-
-  // using helper function to create property buffer
-  var verts = dali.createPropertyBuffer( {format: [ ["aPosition", dali.PropertyType.VECTOR3],
-                                                    ["aCol", dali.PropertyType.VECTOR4] ],
-                                          data: { "aPosition": [ [-halfQuadSize, -halfQuadSize, 0.0],
-                                                                 [+halfQuadSize, -halfQuadSize, 0.0],
-                                                                 [-halfQuadSize, +halfQuadSize, 0.0],
-                                                                 [+halfQuadSize, +halfQuadSize, 0.0]
-                                                               ],
-                                                  "aCol": [ [0, 0, 0, 1],
-                                                            [1, 0, 1, 1],
-                                                            [0, 1, 0, 1],
-                                                            [1, 1, 1, 1]
-                                                          ]
-                                                }
-                                         });
-
-  var indices = dali.createPropertyBuffer( { format: [ ["indices", dali.PropertyType.INTEGER]],
-                                             data: { "indices": [0, 3, 1, 0, 2, 3] } } ) ;
-
-  var geometry = new dali.Geometry();
-
-  assert.ok(verts);
-  assert.ok(indices);
-  assert.ok(geometry);
-
-  geometry.addVertexBuffer(verts);
-  geometry.setIndexBuffer(indices);
-
-  var vertex = "" +
-        "attribute mediump vec3 aPosition;" +
-        "attribute mediump vec4 aCol;" +
-        "uniform mediump mat4 uMvpMatrix;" +
-        "uniform mediump vec3 uSize;" +
-        "uniform lowp vec4 uColor;" +
-        "varying lowp vec4 vColor;" +
-        "" +
-        "void main()" +
-        "{" +
-        "  vColor = aCol * uColor;" +
-        "  mediump vec4 vertexPosition = vec4(aPosition,1.0);" +
-        "  vertexPosition.xyz *= uSize;" +
-        "  gl_Position = uMvpMatrix * vertexPosition;" +
-        "}";
-
-  var fragment = "" +
-        "varying lowp vec4 vColor;" +
-        "uniform lowp vec4 uColor;" +
-        "" +
-        "void main()" +
-        "{" +
-        "  gl_FragColor = vColor * uColor;" +
-        "}";
-
-  var shader = new dali.Shader(vertex, fragment, dali.ShaderHints.HINT_NONE);
-  assert.ok(shader);
-
-  var material = new dali.Material(shader);
-  assert.ok(material);
-
-  var renderer = new dali.Renderer(geometry, material);
-  assert.ok(renderer);
-
-  var actor = new dali.Actor();
-  assert.ok(actor);
-
-  actor.addRenderer(renderer);
-
-  dali.stage.add(actor);
-
-  actor.parentOrigin = [0.5, 0.5, 0.0];
-  actor.size = [100,100,1];
-}
-
-
-QUnit.test( "Exercise view helpers", function( assert ) {
-
-  // just setting the back colour doesnt trigger a redraw in Dali so we
-  // add a quad just to see the test running
-  addOnScreenQuad(assert);
-
-  var done1 = assert.async();
-  var done2 = assert.async();
-  var done3 = assert.async();
-
-  var w = dali.canvas.width;
-  var h = dali.canvas.height;
-  var col = dali.getClearColor(0);
-  console.log(col);
-
-  function one() {
-    dali.onePane();
-    dali.setFrontView(0, 0, 0, w, h);
-    dali.setClearColor(0, col);
-    done3();
-  }
-
-  function three() {
-    dali.threePane();
-    dali.setClearColor(0, [0.4, 0, 0, 1]);
-    dali.setClearColor(1, [0, 0.4, 0, 1]);
-    dali.setClearColor(2, [0, 0, 0.4, 1]);
-    dali.setFrontView(0, 0, 0, w / 2 - 5, h);
-    dali.setTopView(1, w / 2, 0, w / 2, h / 2 - 5);
-    dali.setRightView(2, w / 2, h / 2 + 5, w / 2, h / 2 - 5);
-
-    window.setTimeout(one, 100);
-    done2();
-  }
-
-  function two() {
-    dali.twoPane();
-    dali.setFrontView(0, 0, 0, w / 2 - 10, h);
-    dali.setTopView(1, 210, 0, w / 2 - 10, h);
-    dali.setClearColor(0, [0.4, 0, 0, 1]);
-    dali.setClearColor(1, [0, 0.4, 0, 1]);
-
-    window.setTimeout(three, 100);
-    done1();
-  }
-
-  //one();
-
-  window.setTimeout(two, 100);
-
-});
diff --git a/adaptors/emscripten/wrappers/type-info-wrapper.cpp b/adaptors/emscripten/wrappers/type-info-wrapper.cpp
deleted file mode 100644 (file)
index 2380347..0000000
+++ /dev/null
@@ -1,117 +0,0 @@
-/*
- * Copyright (c) 2015 Samsung Electronics Co., Ltd.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- */
-
-#include "type-info-wrapper.h"
-
-// EXTERNAL INCLUDES
-
-// INTERNAL INCLUDES
-#include "property-value-wrapper.h"
-
-namespace Dali
-{
-namespace Internal
-{
-namespace Emscripten
-{
-
-std::vector<std::string> GetAllProperties(Dali::TypeInfo self)
-{
-  std::vector<std::string> names;
-
-  // get the other properties
-  if(Dali::Handle handle = Dali::Handle::DownCast( self.CreateInstance() ) )
-  {
-    typedef Dali::Property::IndexContainer IndexContainer;
-
-    Dali::Property::IndexContainer indices;
-    handle.GetPropertyIndices( indices );
-
-    for(IndexContainer::Iterator iter(indices.Begin()); iter != indices.End(); ++iter)
-    {
-      std::string name = handle.GetPropertyName( *iter );
-
-      names.push_back(name);
-    }
-  }
-  else
-  {
-    // all we can do is get the event side properties
-    // get the event side properties
-    Property::IndexContainer indices;
-    self.GetPropertyIndices( indices );
-    for(Property::IndexContainer::Iterator iter(indices.Begin()); iter != indices.End(); ++iter)
-    {
-      std::string name = self.GetPropertyName( *iter );
-      names.push_back(name);
-    }
-  }
-
-  return names;
-}
-
-std::vector<int> GetPropertyIndices(Dali::TypeInfo& self)
-{
-  Dali::Property::IndexContainer indices;
-  self.GetPropertyIndices( indices );
-
-  std::vector<int> ret( indices.Begin(), indices.End() );
-  return ret;
-}
-
-std::vector<std::string> GetActions(Dali::TypeInfo& self)
-{
-  std::vector<std::string> names;
-  std::size_t size = self.GetActionCount();
-  for(std::size_t i = 0; i < size; i++)
-  {
-    names.push_back(self.GetActionName(i));
-  }
-  return names;
-}
-
-std::vector<std::string> GetSignals(Dali::TypeInfo& self)
-{
-  std::vector<std::string> names;
-  std::size_t size = self.GetSignalCount();
-  for(std::size_t i = 0; i < size; i++)
-  {
-    names.push_back(self.GetSignalName(i));
-  }
-  return names;
-}
-
-std::vector<std::string> GetBases(Dali::TypeInfo& self)
-{
-  std::vector<std::string> names;
-
-  Dali::TypeRegistry registry = Dali::TypeRegistry::Get();
-
-  Dali::TypeInfo base = registry.GetTypeInfo( self.GetBaseName() );
-
-  while(base)
-  {
-    base = registry.GetTypeInfo( base.GetBaseName() );
-    names.push_back(base.GetName());
-  }
-
-  return names;
-}
-
-}; // namespace Emscripten
-}; // namespace Internal
-}; // namespace Dali
diff --git a/adaptors/emscripten/wrappers/type-info-wrapper.h b/adaptors/emscripten/wrappers/type-info-wrapper.h
deleted file mode 100644 (file)
index 8c6fdda..0000000
+++ /dev/null
@@ -1,103 +0,0 @@
-#ifndef __DALI_TYPE_INFO_WRAPPER_H__
-#define __DALI_TYPE_INFO_WRAPPER_H__
-
-/*
- * Copyright (c) 2015 Samsung Electronics Co., Ltd.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- */
-
-// EXTERNAL INCLUDES
-#include <dali/public-api/dali-core.h>
-
-#include "emscripten/emscripten.h"
-#include "emscripten/bind.h"
-#include <vector>
-#include <string>
-
-// INTERNAL INCLUDES
-
-namespace Dali
-{
-namespace Internal
-{
-namespace Emscripten
-{
-
-/**
- * Gets all properties from TypeInfo
- *
- * @param[in] self The TypeInfo
- *
- * @returns A list of property names
- *
- */
-std::vector<std::string> GetAllProperties(Dali::TypeInfo self);
-
-/**
- * Gets all property indices from TypeInfo
- *
- * @param[in] self The TypeInfo
- *
- * @returns A list of property indices
- *
- */
-std::vector<int> GetPropertyIndices(Dali::TypeInfo& self);
-
-/**
- * Gets all actions from TypeInfo
- *
- * @param[in] self The TypeInfo
- *
- * @returns A list of property action names
- *
- */
-std::vector<std::string> GetActions(Dali::TypeInfo& self);
-
-/**
- * Gets all signals from TypeInfo
- *
- * @param[in] self The TypeInfo
- *
- * @returns A list of signal names
- *
- */
-std::vector<std::string> GetSignals(Dali::TypeInfo& self);
-
-/**
- * Gets all bases classes from TypeInfo
- *
- * @param[in] self The TypeInfo
- *
- * @returns A list of base class names
- *
- */
-std::vector<std::string> GetBases(Dali::TypeInfo& self);
-
-/**
- * Check if a TypeInfo has a base name
- *
- * @param[in] self The TypeInfo
- * @param[in] baseName The base class name
- *
- * @returns true if baseName is a base class of self
- *
- */
-bool InheritsFrom(Dali::TypeInfo& self, const std::string& baseName);
-
-}; // namespace Emscripten
-}; // namespace Internal
-}; // namespace Dali
-
-#endif // header
index 93fbd7b..1d023ad 100644 (file)
@@ -2,7 +2,7 @@
 #define __DALI_INTEGRATION_ADAPTOR_H__
 
 /*
- * Copyright (c) 2016 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2017 Samsung Electronics Co., Ltd.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
 #include <dali/public-api/math/rect.h>
 #include <dali/public-api/events/touch-event.h>
 #include <dali/public-api/common/view-mode.h>
+#include <dali/public-api/math/uint-16-pair.h>
 
 // INTERNAL INCLUDES
 
-
 #ifdef DALI_ADAPTOR_COMPILATION  // full path doesn't exist until adaptor is installed so we have to use relative
 // @todo Make dali-adaptor code folder structure mirror the folder structure installed to dali-env
 #include <window.h>
@@ -115,6 +115,8 @@ public:
 
   typedef Signal< void (Adaptor&) > AdaptorSignalType; ///< Generic Type for adaptor signals
 
+  typedef Uint16Pair SurfaceSize;          ///< Surface size type
+
 public:
   /**
    * @brief Create a new adaptor using the window.
@@ -340,7 +342,7 @@ public:
   /**
    * @brief Informs core the surface size has changed
    */
-  void SurfaceSizeChanged( const PositionSize& positionSize );
+  void SurfaceSizeChanged( SurfaceSize surfaceSize );
 
 public:  // Signals
 
index 1d4fb36..3530906 100644 (file)
@@ -34,21 +34,21 @@ Application Application::New()
 
 Application Application::New( int* argc, char **argv[] )
 {
-  Internal::Adaptor::ApplicationPtr internal = Internal::Adaptor::Application::New( argc, argv, "", OPAQUE,
+  Internal::Adaptor::ApplicationPtr internal = Internal::Adaptor::Application::New( argc, argv, "", OPAQUE, PositionSize(),
     Internal::Adaptor::Framework::NORMAL);
   return Application(internal.Get());
 }
 
 Application Application::New( int* argc, char **argv[], const std::string& stylesheet )
 {
-  Internal::Adaptor::ApplicationPtr internal = Internal::Adaptor::Application::New( argc, argv, stylesheet, OPAQUE,
+  Internal::Adaptor::ApplicationPtr internal = Internal::Adaptor::Application::New( argc, argv, stylesheet, OPAQUE, PositionSize(),
     Internal::Adaptor::Framework::NORMAL);
   return Application(internal.Get());
 }
 
 Application Application::New( int* argc, char **argv[], const std::string& stylesheet, WINDOW_MODE windowMode )
 {
-  Internal::Adaptor::ApplicationPtr internal = Internal::Adaptor::Application::New( argc, argv, stylesheet, windowMode,
+  Internal::Adaptor::ApplicationPtr internal = Internal::Adaptor::Application::New( argc, argv, stylesheet, windowMode, PositionSize(),
     Internal::Adaptor::Framework::NORMAL);
   return Application(internal.Get());
 }
index cf80028..193696a 100644 (file)
@@ -28,7 +28,7 @@ namespace Dali
 
 const unsigned int ADAPTOR_MAJOR_VERSION = 1;
 const unsigned int ADAPTOR_MINOR_VERSION = 2;
-const unsigned int ADAPTOR_MICRO_VERSION = 44;
+const unsigned int ADAPTOR_MICRO_VERSION = 46;
 const char * const ADAPTOR_BUILD_DATE    = __DATE__ " " __TIME__;
 
 #ifdef DEBUG_ENABLED
old mode 100644 (file)
new mode 100755 (executable)
index 43090f5..725c282
@@ -20,6 +20,7 @@
 
 // INTERNAL INCLUDES
 #include <dali/public-api/common/dali-common.h>
+#include <dali/public-api/common/dali-vector.h>
 #include "key.h"
 
 namespace Dali
@@ -109,6 +110,45 @@ DALI_IMPORT_API bool GrabKey( Window window, Dali::KEY daliKey, KeyGrabMode grab
  */
 DALI_IMPORT_API bool UngrabKey( Window window, Dali::KEY daliKey );
 
+
+/**
+ * @PLATFORM
+ * @brief Grabs the list of keys specified by @Dali::Vector of keys for @a window in @Vector of grabModes.
+ *
+ * @details This function can be used for following example scenarios:
+ * - TV - A user might want to change the volume or channel of the background TV contents while focusing on the foregrund app.
+ * - Mobile - When a user presses Home key, the homescreen appears regardless of current foreground app.
+ * - Mobile - Using volume up/down as zoom up/down in camera apps.
+ *
+ * @SINCE_1_2.0
+ * @PRIVLEVEL_PLATFORM
+ * @PRIVILEGE_KEYGRAB
+ * @param[in] window The window to set
+ * @param[in] daliKeyVector The Dali::Vector of key codes to grab (defined in key.h)
+ * @param[in] grabModeVector The Dali::Vector of grab modes for the keys
+ * @param[in] returnVector The Dali::Vector of return boolean values for the results of multiple grab succeeds/fails
+ * @return bool false when error occurs
+ */
+DALI_IMPORT_API bool GrabKeyList( Window window, const Dali::Vector<Dali::KEY>& daliKeyVector, const Dali::Vector<KeyGrabMode>& grabModeVector, Dali::Vector<bool>& returnVector);
+
+
+/**
+ * @PLATFORM
+ * @brief Ungrabs the list of keys specified by @Dali::Vector of keys for @a window.
+ *
+ * @SINCE_1_2.0
+ * @PRIVLEVEL_PLATFORM
+ * @PRIVILEGE_KEYGRAB
+ * @param[in] window The window to set
+ * @param[in] daliKeyVector The Dali::Vector of key codes to ungrab (defined in key.h)
+ * @param[in] returnVector The Dali::Vector of return boolean values for the results of multiple ungrab succeeds/fails
+ * @return bool false when error occurs
+ * @note If this function is called between key down and up events of a grabbed key,
+ * an application doesn't receive the key up event.
+ */
+DALI_IMPORT_API bool UngrabKeyList( Window window, const Dali::Vector<Dali::KEY>& daliKeyVector, Dali::Vector<bool>& returnVector);
+
+
 } // namespace KeyGrab
 
 /**
index 79e2555..51d5899 100644 (file)
@@ -48,11 +48,11 @@ struct Window::EventHandler
   // place holder
 };
 
-Window* Window::New(const PositionSize& posSize, const std::string& name, const std::string& className, bool isTransparent)
+Window* Window::New( const PositionSize& positionSize, const std::string& name, const std::string& className, bool isTransparent )
 {
   Window* window = new Window();
   window->mIsTransparent = isTransparent;
-  window->Initialize(posSize, name, className);
+  window->Initialize( positionSize, name, className );
   return window;
 }
 
@@ -112,6 +112,7 @@ Window::Window()
   mIsFocusAcceptable( true ),
   mVisible( true ),
   mOpaqueState( false ),
+  mResizeEnabled( true ),
   mIndicator( NULL ),
   mIndicatorOrientation( Dali::Window::PORTRAIT ),
   mNextIndicatorOrientation( Dali::Window::PORTRAIT ),
@@ -144,16 +145,15 @@ Window::~Window()
   delete mSurface;
 }
 
-void Window::Initialize(const PositionSize& windowPosition, const std::string& name, const std::string& className)
+void Window::Initialize(const PositionSize& positionSize, const std::string& name, const std::string& className)
 {
   // create an Wayland window by default
   Any surface;
-  Wayland::RenderSurface* windowSurface = new Wayland::RenderSurface( windowPosition, surface, name, mIsTransparent );
+  Wayland::RenderSurface* windowSurface = new Wayland::RenderSurface( positionSize, surface, name, mIsTransparent );
 
   mSurface = windowSurface;
 
   mOrientation = Orientation::New(this);
-
 }
 
 void Window::DoShowIndicator( Dali::Window::WindowOrientation lastOrientation )
@@ -407,6 +407,51 @@ int Window::GetBrightness()
   return 0;
 }
 
+void Window::SetSize( Dali::DevelWindow::WindowSize size )
+{
+  PositionSize positionSize = mSurface->GetPositionSize();
+
+  if( positionSize.width != size.GetWidth() || positionSize.height != size.GetHeight() )
+  {
+    positionSize.width = size.GetWidth();
+    positionSize.height = size.GetHeight();
+
+    mSurface->MoveResize( positionSize );
+
+    mAdaptor->SurfaceSizeChanged( Dali::Adaptor::SurfaceSize( positionSize.width, positionSize.height ) );
+
+    // Emit signal
+    mResizedSignal.Emit( Dali::DevelWindow::WindowSize( positionSize.width, positionSize.height ) );
+  }
+}
+
+Dali::DevelWindow::WindowSize Window::GetSize()
+{
+  PositionSize positionSize = mSurface->GetPositionSize();
+
+  return Dali::DevelWindow::WindowSize( positionSize.width, positionSize.height );
+}
+
+void Window::SetPosition( Dali::DevelWindow::WindowPosition position )
+{
+  PositionSize positionSize = mSurface->GetPositionSize();
+
+  if( positionSize.x != position.GetX() || positionSize.y != position.GetY() )
+  {
+    positionSize.x = position.GetX();
+    positionSize.y = position.GetY();
+
+    mSurface->MoveResize( positionSize );
+  }
+}
+
+Dali::DevelWindow::WindowPosition Window::GetPosition()
+{
+  PositionSize positionSize = mSurface->GetPositionSize();
+
+  return Dali::DevelWindow::WindowPosition( positionSize.x, positionSize.y );
+}
+
 } // Adaptor
 } // Internal
 } // Dali
index da3eae8..2f47a33 100644 (file)
@@ -38,7 +38,7 @@ WatchApplicationPtr WatchApplication::New(
 }
 
 WatchApplication::WatchApplication( int* argc, char** argv[], const std::string& stylesheet, Dali::Application::WINDOW_MODE windowMode )
-: Application(argc, argv, stylesheet, windowMode, Framework::WATCH)
+: Application(argc, argv, stylesheet, windowMode, PositionSize(), Framework::WATCH)
 {
 }
 
index c748c56..b6a0b8a 100644 (file)
@@ -225,11 +225,11 @@ struct Window::EventHandler
 };
 
 
-Window* Window::New(const PositionSize& posSize, const std::string& name, const std::string& className, bool isTransparent)
+Window* Window::New( const PositionSize& positionSize, const std::string& name, const std::string& className, bool isTransparent )
 {
   Window* window = new Window();
   window->mIsTransparent = isTransparent;
-  window->Initialize(posSize, name, className);
+  window->Initialize( positionSize, name, className );
   return window;
 }
 
@@ -349,6 +349,7 @@ Window::Window()
   mIsFocusAcceptable( true ),
   mVisible( true ),
   mOpaqueState( false ),
+  mResizeEnabled( true ),
   mIndicator( NULL ),
   mIndicatorOrientation( Dali::Window::PORTRAIT ),
   mNextIndicatorOrientation( Dali::Window::PORTRAIT ),
@@ -402,11 +403,11 @@ Window::~Window()
   delete mSurface;
 }
 
-void Window::Initialize(const PositionSize& windowPosition, const std::string& name, const std::string& className)
+void Window::Initialize(const PositionSize& positionSize, const std::string& name, const std::string& className)
 {
   // create an X11 window by default
   Any surface;
-  ECore::WindowRenderSurface* windowSurface = new ECore::WindowRenderSurface( windowPosition, surface, name, className, mIsTransparent );
+  ECore::WindowRenderSurface* windowSurface = new ECore::WindowRenderSurface( positionSize, surface, name, className, mIsTransparent );
   windowSurface->Map();
 
   mSurface = windowSurface;
@@ -911,6 +912,51 @@ int Window::GetBrightness()
   return 0;
 }
 
+void Window::SetSize( Dali::DevelWindow::WindowSize size )
+{
+  PositionSize positionSize = mSurface->GetPositionSize();
+
+  if( positionSize.width != size.GetWidth() || positionSize.height != size.GetHeight() )
+  {
+    positionSize.width = size.GetWidth();
+    positionSize.height = size.GetHeight();
+
+    mSurface->MoveResize( positionSize );
+
+    mAdaptor->SurfaceSizeChanged( Dali::Adaptor::SurfaceSize( positionSize.width, positionSize.height ) );
+
+    // Emit signal
+    mResizedSignal.Emit( Dali::DevelWindow::WindowSize( positionSize.width, positionSize.height ) );
+  }
+}
+
+Dali::DevelWindow::WindowSize Window::GetSize()
+{
+  PositionSize positionSize = mSurface->GetPositionSize();
+
+  return Dali::DevelWindow::WindowSize( positionSize.width, positionSize.height );
+}
+
+void Window::SetPosition( Dali::DevelWindow::WindowPosition position )
+{
+  PositionSize positionSize = mSurface->GetPositionSize();
+
+  if( positionSize.x != position.GetX() || positionSize.y != position.GetY() )
+  {
+    positionSize.x = position.GetX();
+    positionSize.y = position.GetY();
+
+    mSurface->MoveResize( positionSize );
+  }
+}
+
+Dali::DevelWindow::WindowPosition Window::GetPosition()
+{
+  PositionSize positionSize = mSurface->GetPositionSize();
+
+  return Dali::DevelWindow::WindowPosition( positionSize.x, positionSize.y );
+}
+
 } // Adaptor
 
 } // Internal
index bc108fa..bc51cfb 100755 (executable)
@@ -75,7 +75,7 @@ rm -f tct*core-tests.xml
 
 # Clean up old coverage data
 if [ -d ../build/tizen ] ; then
-    rm -f ../build/tizen/dali-toolkit/.libs/*.gcda
+    rm -f ../build/tizen/dali/.libs/*.gcda
 fi
 
 find build \( -name "*.gcda" \) -exec rm '{}' \;
@@ -138,9 +138,9 @@ else
             ret=$?
             if [ $ret -ne 6 ] ; then
                 if [ $opt_debug -ne 0 ] ; then
-                    if [ $ret -eq 0 ] ; then
-                        gdb --args build/src/$mod/tct-$mod-core $1
-                    fi
+                    echo DEBUGGING:
+                    gdb --args build/src/$mod/tct-$mod-core $1
+
                 else
                     echo $output
                     if [ $ret -eq 0 ] ; then echo -e "\nPassed" ; fi
index af08fd1..c41bc4d 100644 (file)
@@ -12,6 +12,7 @@ SET(TC_SOURCES
     utc-Dali-GifLoader.cpp
     utc-Dali-IcoLoader.cpp
     utc-Dali-ImageOperations.cpp
+    utc-Dali-Internal-PixelBuffer.cpp
     utc-Dali-Lifecycle-Controller.cpp
     utc-Dali-TiltSensor.cpp
 )
diff --git a/automated-tests/src/dali-adaptor-internal/utc-Dali-Internal-PixelBuffer.cpp b/automated-tests/src/dali-adaptor-internal/utc-Dali-Internal-PixelBuffer.cpp
new file mode 100644 (file)
index 0000000..710e52c
--- /dev/null
@@ -0,0 +1,186 @@
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#include <iostream>
+
+#include <stdlib.h>
+#include <dali/public-api/dali-core.h>
+
+#include <dali-test-suite-utils.h>
+
+// Internal headers are allowed here
+
+#include <platform-abstractions/portable/pixel-manipulation.h>
+
+using namespace Dali;
+using namespace Dali::Internal::Adaptor;
+void utc_dali_internal_pixel_data_startup()
+{
+  test_return_value = TET_UNDEF;
+}
+
+void utc_dali_internal_pixel_data_cleanup()
+{
+  test_return_value = TET_PASS;
+}
+
+const char* ChannelToString( Dali::Internal::Adaptor::Channel channel )
+{
+  switch(channel)
+  {
+    case LUMINANCE: return "Luminance";
+    case RED: return "Red";
+    case GREEN: return "Green";
+    case BLUE: return "Blue";
+    case ALPHA: return "Alpha";
+    default:
+      return "Unknown";
+  }
+}
+
+const char* FormatToString( Dali::Pixel::Format format )
+{
+  switch(format)
+  {
+    case Dali::Pixel::A8: return "A8";
+    case Dali::Pixel::L8: return "L8";
+    case Dali::Pixel::LA88: return "LA88";
+    case Dali::Pixel::RGB565: return "RGB565";
+    case Dali::Pixel::BGR565: return "BGR565";
+    case Dali::Pixel::RGBA4444: return "RGBA4444";
+    case Dali::Pixel::BGRA4444: return "BGRA4444";
+    case Dali::Pixel::RGBA5551: return "RGBA5551";
+    case Dali::Pixel::BGRA5551: return "BGRA5551";
+
+    case Dali::Pixel::RGB888: return "RGB888";
+    case Dali::Pixel::RGBA8888: return "RGBA8888";
+    case Dali::Pixel::BGRA8888: return "BGRA8888";
+
+    default:
+      return "Unknown";
+  }
+}
+
+
+int UtcDaliPixelManipulation01(void)
+{
+  tet_infoline("Testing Dali::Internal::AdaptorManipulation HasChannel");
+
+  DALI_TEST_EQUALS( Dali::Internal::Adaptor::HasChannel( Dali::Pixel::A8, Dali::Internal::Adaptor::ALPHA ), true, TEST_LOCATION );
+  DALI_TEST_EQUALS( Dali::Internal::Adaptor::HasChannel( Dali::Pixel::A8, Dali::Internal::Adaptor::LUMINANCE ), false, TEST_LOCATION );
+
+  DALI_TEST_EQUALS( Dali::Internal::Adaptor::HasChannel( Dali::Pixel::L8, Dali::Internal::Adaptor::LUMINANCE ), true, TEST_LOCATION );
+  DALI_TEST_EQUALS( Dali::Internal::Adaptor::HasChannel( Dali::Pixel::L8, Dali::Internal::Adaptor::ALPHA ), false, TEST_LOCATION );
+
+  DALI_TEST_EQUALS( Dali::Internal::Adaptor::HasChannel( Dali::Pixel::LA88, Dali::Internal::Adaptor::LUMINANCE ), true, TEST_LOCATION );
+  DALI_TEST_EQUALS( Dali::Internal::Adaptor::HasChannel( Dali::Pixel::LA88, Dali::Internal::Adaptor::ALPHA ), true, TEST_LOCATION );
+  DALI_TEST_EQUALS( Dali::Internal::Adaptor::HasChannel( Dali::Pixel::LA88, Dali::Internal::Adaptor::RED ), false, TEST_LOCATION );
+
+  DALI_TEST_EQUALS( Dali::Internal::Adaptor::HasChannel( Dali::Pixel::RGB565, Dali::Internal::Adaptor::RED ), true, TEST_LOCATION );
+  DALI_TEST_EQUALS( Dali::Internal::Adaptor::HasChannel( Dali::Pixel::RGB565, Dali::Internal::Adaptor::GREEN ), true, TEST_LOCATION );
+  DALI_TEST_EQUALS( Dali::Internal::Adaptor::HasChannel( Dali::Pixel::RGB565, Dali::Internal::Adaptor::BLUE ), true, TEST_LOCATION );
+  DALI_TEST_EQUALS( Dali::Internal::Adaptor::HasChannel( Dali::Pixel::RGB565, Dali::Internal::Adaptor::LUMINANCE ), false, TEST_LOCATION );
+
+  DALI_TEST_EQUALS( Dali::Internal::Adaptor::HasChannel( Dali::Pixel::RGBA8888, Dali::Internal::Adaptor::RED ), true, TEST_LOCATION );
+  DALI_TEST_EQUALS( Dali::Internal::Adaptor::HasChannel( Dali::Pixel::RGBA8888, Dali::Internal::Adaptor::GREEN ), true, TEST_LOCATION );
+  DALI_TEST_EQUALS( Dali::Internal::Adaptor::HasChannel( Dali::Pixel::RGBA8888, Dali::Internal::Adaptor::BLUE ), true, TEST_LOCATION );
+  DALI_TEST_EQUALS( Dali::Internal::Adaptor::HasChannel( Dali::Pixel::RGBA8888, Dali::Internal::Adaptor::ALPHA ), true, TEST_LOCATION );
+  DALI_TEST_EQUALS( Dali::Internal::Adaptor::HasChannel( Dali::Pixel::RGBA8888, Dali::Internal::Adaptor::LUMINANCE ), false, TEST_LOCATION );
+
+  DALI_TEST_EQUALS( Dali::Internal::Adaptor::HasChannel( Dali::Pixel::COMPRESSED_RGBA_ASTC_10x6_KHR, Dali::Internal::Adaptor::BLUE ), false, TEST_LOCATION );
+
+  END_TEST;
+}
+
+
+
+int UtcDaliPixelManipulation02(void)
+{
+  tet_infoline("Testing Dali::Internal::AdaptorManipulation Read/WriteChannel");
+
+  unsigned char pixel[4] = {0,0,0,0};
+
+  for( int formatIdx=1; formatIdx<Dali::Pixel::COMPRESSED_R11_EAC; ++formatIdx)
+  {
+    pixel[0] = 0xFF;
+    pixel[1] = 0xFF;
+    pixel[2] = 0xFF;
+    pixel[3] = 0xFF;
+
+    for( int channelIdx=0; channelIdx < Dali::Internal::Adaptor::MAX_NUMBER_OF_CHANNELS; ++channelIdx )
+    {
+      Dali::Pixel::Format format = static_cast<Dali::Pixel::Format>(formatIdx);
+      Dali::Internal::Adaptor::Channel channel = static_cast<Dali::Internal::Adaptor::Channel>(channelIdx);
+      if( Dali::Internal::Adaptor::HasChannel( format, channel ) )
+      {
+        Dali::Internal::Adaptor::WriteChannel( &pixel[0], format, channel, 0x15);
+        unsigned int value = Dali::Internal::Adaptor::ReadChannel( &pixel[0], format, channel );
+
+        tet_printf( "Testing writing and reading to %s channel in %s format:\n",
+                      ChannelToString(channel), FormatToString(format) );
+
+        if( channel == Dali::Internal::Adaptor::ALPHA && (format == Dali::Pixel::RGBA5551 || format == Dali::Pixel::BGRA5551 ) )
+        {
+          DALI_TEST_EQUALS( value, 0x1, TEST_LOCATION );
+        }
+        else if( format == Dali::Pixel::RGBA4444 || format == Dali::Pixel::BGRA4444 )
+        {
+          DALI_TEST_EQUALS( value, 0x05, TEST_LOCATION );
+        }
+        else
+        {
+          DALI_TEST_EQUALS( value, 0x15, TEST_LOCATION );
+        }
+      }
+    }
+  }
+
+  END_TEST;
+}
+
+
+int UtcDaliPixelManipulation03N(void)
+{
+  tet_infoline("Testing Dali::Internal::AdaptorManipulation Read/WriteChannel");
+
+  unsigned char pixel[4] = {0,0,0,0};
+
+  for( int formatIdx=1; formatIdx<Dali::Pixel::COMPRESSED_R11_EAC; ++formatIdx)
+  {
+    pixel[0] = 0xFF;
+    pixel[1] = 0xFF;
+    pixel[2] = 0xFF;
+    pixel[3] = 0xFF;
+
+    for( int channelIdx=0; channelIdx < Dali::Internal::Adaptor::MAX_NUMBER_OF_CHANNELS; ++channelIdx )
+    {
+      Dali::Pixel::Format format = static_cast<Dali::Pixel::Format>(formatIdx);
+      Dali::Internal::Adaptor::Channel channel = static_cast<Dali::Internal::Adaptor::Channel>(channelIdx);
+      if( ! Dali::Internal::Adaptor::HasChannel( format, channel ) )
+      {
+        unsigned int value = Dali::Internal::Adaptor::ReadChannel( &pixel[0], format, channel );
+
+        tet_printf( "Testing reading from %s channel in %s format:\n",
+                      ChannelToString(channel), FormatToString(format) );
+
+        DALI_TEST_EQUALS( value, 0x00, TEST_LOCATION );
+      }
+    }
+  }
+
+  END_TEST;
+}
index 04311e0..4ae66c4 100644 (file)
@@ -6,12 +6,12 @@ SET(RPM_NAME "core-${PKG_NAME}-tests")
 SET(CAPI_LIB "dali-adaptor")
 SET(TC_SOURCES
     utc-Dali-Application.cpp
-    utc-Dali-BitmapLoader.cpp
     utc-Dali-FileLoader.cpp
     utc-Dali-GifLoading.cpp
     utc-Dali-ImageLoading.cpp
     utc-Dali-Key.cpp
     utc-Dali-NativeImageSource.cpp
+    utc-Dali-PixelBuffer.cpp
     utc-Dali-SingletonService.cpp
     utc-Dali-Timer.cpp
     utc-Dali-TtsPlayer.cpp
diff --git a/automated-tests/src/dali-adaptor/utc-Dali-BitmapLoader.cpp b/automated-tests/src/dali-adaptor/utc-Dali-BitmapLoader.cpp
deleted file mode 100644 (file)
index 1490ea4..0000000
+++ /dev/null
@@ -1,140 +0,0 @@
-/*
- * Copyright (c) 2015 Samsung Electronics Co., Ltd.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- */
-
-#include <stdlib.h>
-#include <dali/dali.h>
-#include <dali-test-suite-utils.h>
-#include <dali/devel-api/adaptor-framework/bitmap-loader.h>
-
-using namespace Dali;
-
-namespace
-{
-// resolution: 34*34, pixel format: RGBA8888
-static const char* gImage_34_RGBA = TEST_RESOURCE_DIR "/icon-edit.png";
-// resolution: 128*128, pixel format: RGB888
-static const char* gImage_128_RGB = TEST_RESOURCE_DIR "/gallery-small-1.jpg";
-
-// this is image is not exist, for negative test
-static const char* gImageNonExist = "non-exist.jpg";
-}
-
-void utc_dali_bitmap_loader_startup(void)
-{
-  test_return_value = TET_UNDEF;
-}
-
-void utc_dali_bitmap_loader_cleanup(void)
-{
-  test_return_value = TET_PASS;
-}
-
-int UtcDaliBitmapLoaderNew(void)
-{
-  TestApplication application;
-
-  // invoke default handle constructor
-  BitmapLoader loader;
-
-  DALI_TEST_CHECK( !loader );
-
-  // initialise handle
-  loader = BitmapLoader::New( gImage_34_RGBA );
-
-  DALI_TEST_CHECK( loader );
-  END_TEST;
-}
-
-int UtcDaliBitmapLoaderCopyConstructor(void)
-{
-  TestApplication application;
-
-  BitmapLoader loader = BitmapLoader::New( gImage_34_RGBA);
-  BitmapLoader loaderCopy(loader);
-
-  DALI_TEST_EQUALS( (bool)loaderCopy, true, TEST_LOCATION );
-  END_TEST;
-}
-
-int UtcDaliBitmapLoaderAssignmentOperator(void)
-{
-  TestApplication application;
-
-  BitmapLoader loader = BitmapLoader::New( gImage_34_RGBA );
-
-  BitmapLoader loader2;
-  DALI_TEST_EQUALS( (bool)loader2, false, TEST_LOCATION );
-
-  loader2 = loader;
-  DALI_TEST_EQUALS( (bool)loader2, true, TEST_LOCATION );
-
-  END_TEST;
-}
-
-int UtcDaliBitmapLoaderGetUrl(void)
-{
-  TestApplication application;
-
-  BitmapLoader loader = BitmapLoader::New( gImage_34_RGBA );
-  DALI_TEST_CHECK( loader.GetUrl() == gImage_34_RGBA );
-
-  END_TEST;
-}
-
-
-int UtcDaliBitmapLoaderLoadP(void)
-{
-  TestApplication application;
-
-  BitmapLoader loader1 = BitmapLoader::New( gImage_34_RGBA );
-  DALI_TEST_CHECK( ! loader1.IsLoaded() );
-  loader1.Load();
-  DALI_TEST_CHECK( loader1.IsLoaded() );
-  PixelData pixelData1 = loader1.GetPixelData();
-  DALI_TEST_CHECK( pixelData1 );
-  DALI_TEST_CHECK( pixelData1.GetWidth() == 34u );
-  DALI_TEST_CHECK( pixelData1.GetHeight() == 34u );
-  DALI_TEST_CHECK( pixelData1.GetPixelFormat() == Pixel::RGBA8888 );
-
-  BitmapLoader loader2 = BitmapLoader::New( gImage_128_RGB );
-  DALI_TEST_CHECK( ! loader2.IsLoaded() );
-  loader2.Load();
-  DALI_TEST_CHECK( loader2.IsLoaded() );
-  PixelData pixelData2 = loader2.GetPixelData();
-  DALI_TEST_CHECK( pixelData2 );
-  DALI_TEST_CHECK( pixelData2.GetWidth() == 128u );
-  DALI_TEST_CHECK( pixelData2.GetHeight() == 128u );
-  DALI_TEST_CHECK( pixelData2.GetPixelFormat() == Pixel::RGB888 );
-
-  END_TEST;
-}
-
-int UtcDaliBitmapLoaderLoadN(void)
-{
-  TestApplication application;
-
-  BitmapLoader loader = BitmapLoader::New( gImageNonExist );
-  DALI_TEST_CHECK( ! loader.IsLoaded() );
-  loader.Load();
-
-  // cannot load image that is not exist
-  DALI_TEST_CHECK( ! loader.IsLoaded() );
-  PixelData pixelData = loader.GetPixelData();
-  DALI_TEST_CHECK( !pixelData);
-
-  END_TEST;
-}
index a4682bc..b05ffed 100644 (file)
@@ -45,25 +45,25 @@ void utc_dali_load_image_cleanup(void)
 
 int UtcDaliLoadImageP(void)
 {
-  PixelData pixelData = Dali::LoadImageFromFile( gImage_34_RGBA );
-  DALI_TEST_CHECK( pixelData );
-  DALI_TEST_EQUALS( pixelData.GetWidth(), 34u, TEST_LOCATION );
-  DALI_TEST_EQUALS( pixelData.GetHeight(), 34u, TEST_LOCATION );
-  DALI_TEST_EQUALS( pixelData.GetPixelFormat(), Pixel::RGBA8888, TEST_LOCATION  );
-
-  PixelData pixelData2 = Dali::LoadImageFromFile( gImage_128_RGB );
-  DALI_TEST_CHECK( pixelData2 );
-  DALI_TEST_EQUALS( pixelData2.GetWidth(), 128u, TEST_LOCATION  );
-  DALI_TEST_EQUALS( pixelData2.GetHeight(), 128u, TEST_LOCATION  );
-  DALI_TEST_EQUALS( pixelData2.GetPixelFormat(), Pixel::RGB888, TEST_LOCATION  );
+  Devel::PixelBuffer pixelBuffer = Dali::LoadImageFromFile( gImage_34_RGBA );
+  DALI_TEST_CHECK( pixelBuffer );
+  DALI_TEST_EQUALS( pixelBuffer.GetWidth(), 34u, TEST_LOCATION );
+  DALI_TEST_EQUALS( pixelBuffer.GetHeight(), 34u, TEST_LOCATION );
+  DALI_TEST_EQUALS( pixelBuffer.GetPixelFormat(), Pixel::RGBA8888, TEST_LOCATION  );
+
+  Devel::PixelBuffer pixelBuffer2 = Dali::LoadImageFromFile( gImage_128_RGB );
+  DALI_TEST_CHECK( pixelBuffer2 );
+  DALI_TEST_EQUALS( pixelBuffer2.GetWidth(), 128u, TEST_LOCATION  );
+  DALI_TEST_EQUALS( pixelBuffer2.GetHeight(), 128u, TEST_LOCATION  );
+  DALI_TEST_EQUALS( pixelBuffer2.GetPixelFormat(), Pixel::RGB888, TEST_LOCATION  );
 
   END_TEST;
 }
 
 int UtcDaliLoadImageN(void)
 {
-  PixelData pixelData = Dali::LoadImageFromFile( gImageNonExist );
-  DALI_TEST_CHECK( !pixelData );
+  Devel::PixelBuffer pixelBuffer = Dali::LoadImageFromFile( gImageNonExist );
+  DALI_TEST_CHECK( !pixelBuffer );
 
   END_TEST;
 }
@@ -77,25 +77,25 @@ int UtcDaliDownloadImageP(void)
   std::string url2("file://");
   url2.append( gImage_128_RGB );
 
-  PixelData pixelData = Dali::DownloadImageSynchronously( url );
-  DALI_TEST_CHECK( pixelData );
-  DALI_TEST_EQUALS( pixelData.GetWidth(), 34u, TEST_LOCATION );
-  DALI_TEST_EQUALS( pixelData.GetHeight(), 34u, TEST_LOCATION );
-  DALI_TEST_EQUALS( pixelData.GetPixelFormat(), Pixel::RGBA8888, TEST_LOCATION  );
+  Devel::PixelBuffer pixelBuffer = Dali::DownloadImageSynchronously( url );
+  DALI_TEST_CHECK( pixelBuffer );
+  DALI_TEST_EQUALS( pixelBuffer.GetWidth(), 34u, TEST_LOCATION );
+  DALI_TEST_EQUALS( pixelBuffer.GetHeight(), 34u, TEST_LOCATION );
+  DALI_TEST_EQUALS( pixelBuffer.GetPixelFormat(), Pixel::RGBA8888, TEST_LOCATION  );
 
-  PixelData pixelData2 = Dali::DownloadImageSynchronously( url2 );
-  DALI_TEST_CHECK( pixelData2 );
-  DALI_TEST_EQUALS( pixelData2.GetWidth(), 128u, TEST_LOCATION  );
-  DALI_TEST_EQUALS( pixelData2.GetHeight(), 128u, TEST_LOCATION  );
-  DALI_TEST_EQUALS( pixelData2.GetPixelFormat(), Pixel::RGB888, TEST_LOCATION  );
+  Devel::PixelBuffer pixelBuffer2 = Dali::DownloadImageSynchronously( url2 );
+  DALI_TEST_CHECK( pixelBuffer2 );
+  DALI_TEST_EQUALS( pixelBuffer2.GetWidth(), 128u, TEST_LOCATION  );
+  DALI_TEST_EQUALS( pixelBuffer2.GetHeight(), 128u, TEST_LOCATION  );
+  DALI_TEST_EQUALS( pixelBuffer2.GetPixelFormat(), Pixel::RGB888, TEST_LOCATION  );
 
   END_TEST;
 }
 
 int UtcDaliDownloadImageN(void)
 {
-  PixelData pixelData = Dali::DownloadImageSynchronously( gImageNonExist );
-  DALI_TEST_CHECK( !pixelData );
+  Devel::PixelBuffer pixelBuffer = Dali::DownloadImageSynchronously( gImageNonExist );
+  DALI_TEST_CHECK( !pixelBuffer );
 
   END_TEST;
 }
diff --git a/automated-tests/src/dali-adaptor/utc-Dali-PixelBuffer.cpp b/automated-tests/src/dali-adaptor/utc-Dali-PixelBuffer.cpp
new file mode 100644 (file)
index 0000000..4a83d8f
--- /dev/null
@@ -0,0 +1,405 @@
+/*
+ * Copyright (c) 2017 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <dali/dali.h>
+#include <dali-test-suite-utils.h>
+#include <dali/devel-api/adaptor-framework/pixel-buffer.h>
+#include "mesh-builder.h"
+using namespace Dali;
+
+void utc_dali_pixelbuffer_startup(void)
+{
+  test_return_value = TET_UNDEF;
+}
+
+void utc_dali_pixelbuffer_cleanup(void)
+{
+  test_return_value = TET_PASS;
+}
+
+int UtcDaliPixelBufferCreatePixelData(void)
+{
+  TestApplication application;
+
+  unsigned int width = 20u;
+  unsigned int height = 20u;
+  Devel::PixelBuffer imageData = Devel::PixelBuffer::New( width, height, Pixel::RGB888 );
+
+  PixelData pixelData = imageData.CreatePixelData();
+
+  DALI_TEST_EQUALS( true, (bool)pixelData, TEST_LOCATION );
+
+  END_TEST;
+}
+
+
+void Mask1stQuadrant( Devel::PixelBuffer maskData )
+{
+  int width = maskData.GetWidth();
+  int height = maskData.GetHeight();
+  Pixel::Format pixelFormat = maskData.GetPixelFormat();
+  int bpp = Pixel::GetBytesPerPixel(pixelFormat);
+
+  unsigned char* maskBuffer = maskData.GetBuffer();
+  memset( maskBuffer, 0, width*height*bpp );
+  int offset=0;
+  for( int x=0; x<width; ++x)
+  {
+    for( int y=0; y<height; ++y)
+    {
+      if(x>=width/2 || y>=height/2)
+      {
+        for(int b=0;b<bpp;++b)
+        {
+          maskBuffer[offset+b] = 0xff;
+        }
+      }
+      offset+=bpp;
+    }
+  }
+}
+
+void FillCheckerboard( Devel::PixelBuffer imageData )
+{
+  int width = imageData.GetWidth();
+  int height = imageData.GetHeight();
+  Pixel::Format pixelFormat = imageData.GetPixelFormat();
+  int bpp = Pixel::GetBytesPerPixel(pixelFormat);
+
+  unsigned char* imageBuffer = imageData.GetBuffer();
+  memset( imageBuffer, 0, width*height*bpp );
+  int offset=0;
+  for( int x=0; x<width; ++x)
+  {
+    for( int y=0; y<height; ++y)
+    {
+      // on even lines, odd pixels, or on odd lines, even pixels
+      if( (x%2 && y%2==0) || (x%2==0 && y%2) )
+      {
+        switch(pixelFormat)
+        {
+          case Pixel::RGBA5551:
+            imageBuffer[offset] = 0xFF;
+            imageBuffer[offset+1] = 0xFF;
+            break;
+          case Pixel::RGBA4444:
+            imageBuffer[offset] = 0xFF;
+            imageBuffer[offset+1] = 0xFF;
+            break;
+          case Pixel::RGB565:
+            imageBuffer[offset] = 0xFF;
+            imageBuffer[offset+1] = 0xFF;
+            break;
+          case Pixel::RGB888:
+            imageBuffer[offset] = 0xFF;
+            imageBuffer[offset+1] = 0xFF;
+            imageBuffer[offset+2] = 0xFF;
+            break;
+          case Pixel::RGBA8888:
+            imageBuffer[offset] = 0xFF;
+            imageBuffer[offset+1] = 0xFF;
+            imageBuffer[offset+2] = 0xFF;
+            imageBuffer[offset+3] = 0xFF;
+            break;
+          default:
+            break;
+        }
+      }
+      offset+=bpp;
+    }
+  }
+}
+
+int UtcDaliPixelBufferNew01P(void)
+{
+  TestApplication application;
+  Devel::PixelBuffer pixbuf = Devel::PixelBuffer::New( 10, 10, Pixel::RGBA8888 );
+  DALI_TEST_CHECK( pixbuf );
+  DALI_TEST_CHECK( pixbuf.GetBuffer() != NULL );
+  END_TEST;
+}
+
+int UtcDaliPixelBufferNew01N(void)
+{
+  TestApplication application;
+  Devel::PixelBuffer pixbuf = Devel::PixelBuffer::New( 0, 0, Pixel::RGBA8888 );
+  DALI_TEST_CHECK( pixbuf );
+  DALI_TEST_CHECK( pixbuf.GetBuffer() == NULL );
+  END_TEST;
+}
+
+int UtcDaliPixelBufferConvert(void)
+{
+  TestApplication application;
+  TestGlAbstraction& gl=application.GetGlAbstraction();
+  TraceCallStack& textureTrace=gl.GetTextureTrace();
+  textureTrace.Enable(true);
+
+  Devel::PixelBuffer pixbuf = Devel::PixelBuffer::New( 10, 10, Pixel::RGB565 );
+  FillCheckerboard(pixbuf);
+
+  {
+    Devel::PixelBuffer pixbufPrime = pixbuf; // store a second handle to the data
+
+    Dali::PixelData pixelData = Devel::PixelBuffer::Convert( pixbuf );
+    DALI_TEST_CHECK( !pixbuf );
+
+    // check the buffer in the second handle is empty
+    DALI_TEST_CHECK( pixbufPrime.GetBuffer() == NULL );
+
+    DALI_TEST_CHECK( pixelData );
+    DALI_TEST_EQUALS( pixelData.GetWidth(), 10, TEST_LOCATION );
+    DALI_TEST_EQUALS( pixelData.GetHeight(), 10, TEST_LOCATION );
+    DALI_TEST_EQUALS( pixelData.GetPixelFormat(), Pixel::RGB565, TEST_LOCATION );
+
+    // Try drawing it
+    Texture t = Texture::New(TextureType::TEXTURE_2D, Pixel::RGB565, 10, 10);
+    t.Upload( pixelData );
+    TextureSet ts = TextureSet::New();
+    ts.SetTexture(0, t);
+    Geometry g = CreateQuadGeometry();
+    Shader s = Shader::New("v", "f");
+    Renderer r = Renderer::New( g, s );
+    r.SetTextures(ts);
+    Actor a = Actor::New();
+    a.AddRenderer(r);
+    a.SetSize(10, 10);
+    a.SetParentOrigin(ParentOrigin::CENTER);
+    Stage::GetCurrent().Add(a);
+
+    application.SendNotification();
+    application.Render();
+    DALI_TEST_EQUALS( textureTrace.FindMethod("BindTexture"), true, TEST_LOCATION );
+
+    // Let secondary scope destroy pixbufPrime
+  }
+
+  END_TEST;
+}
+
+int UtcDaliPixelBufferGetWidth(void)
+{
+  TestApplication application;
+  Devel::PixelBuffer pixbuf = Devel::PixelBuffer::New( 10, 10, Pixel::RGB565 );
+  FillCheckerboard(pixbuf);
+
+  DALI_TEST_EQUALS( pixbuf.GetWidth(), 10, TEST_LOCATION ) ;
+
+  END_TEST;
+}
+
+int UtcDaliPixelBufferGetHeight(void)
+{
+  TestApplication application;
+  Devel::PixelBuffer pixbuf = Devel::PixelBuffer::New( 10, 10, Pixel::RGB565 );
+  FillCheckerboard(pixbuf);
+
+  DALI_TEST_EQUALS( pixbuf.GetHeight(), 10, TEST_LOCATION ) ;
+
+  END_TEST;
+}
+
+int UtcDaliPixelBufferGetPixelFormat(void)
+{
+  TestApplication application;
+  Devel::PixelBuffer pixbuf = Devel::PixelBuffer::New( 10, 10, Pixel::RGB565 );
+  FillCheckerboard(pixbuf);
+
+  DALI_TEST_EQUALS( pixbuf.GetPixelFormat(), Pixel::RGB565, TEST_LOCATION ) ;
+
+  END_TEST;
+}
+
+
+
+int UtcDaliPixelBufferMask01(void)
+{
+  TestApplication application;
+
+  unsigned int width = 10u;
+  unsigned int height = 10u;
+  Pixel::Format pixelFormat = Pixel::L8;
+  Devel::PixelBuffer maskData = Devel::PixelBuffer::New( width, height, pixelFormat );
+
+  Mask1stQuadrant(maskData);
+
+  width = 20u;
+  height = 20u;
+  pixelFormat = Pixel::RGBA5551;
+
+  Devel::PixelBuffer imageData = Devel::PixelBuffer::New( width, height, pixelFormat );
+  FillCheckerboard(imageData);
+
+  imageData.ApplyMask( maskData );
+
+  // Test that the pixel format has been promoted to RGBA8888
+  DALI_TEST_EQUALS( imageData.GetPixelFormat(), Pixel::RGBA8888, TEST_LOCATION );
+
+  // Test that a pixel in the first quadrant has no alpha value
+  unsigned char* buffer = imageData.GetBuffer();
+  DALI_TEST_EQUALS( buffer[3], 0x00u, TEST_LOCATION );
+  DALI_TEST_EQUALS( buffer[7], 0x00u, TEST_LOCATION );
+
+  // Test that an even pixel in the second quadrant has a full alpha value
+  DALI_TEST_EQUALS( buffer[43], 0x00u, TEST_LOCATION );
+
+  // Test that an odd pixel in the second quadrant has full alpha value
+  DALI_TEST_EQUALS( buffer[47], 0xffu, TEST_LOCATION );
+
+  END_TEST;
+}
+
+
+int UtcDaliPixelBufferMask02(void)
+{
+  TestApplication application;
+
+  unsigned int width = 10u;
+  unsigned int height = 10u;
+  Pixel::Format pixelFormat = Pixel::L8;
+  Devel::PixelBuffer maskData = Devel::PixelBuffer::New( width, height, pixelFormat );
+
+  Mask1stQuadrant(maskData);
+
+  width = 20u;
+  height = 20u;
+  pixelFormat = Pixel::RGBA4444;
+
+  Devel::PixelBuffer imageData = Devel::PixelBuffer::New( width, height, pixelFormat );
+  FillCheckerboard(imageData);
+
+  imageData.ApplyMask( maskData );
+
+  // Test that the pixel format has been promoted to RGBA8888
+  DALI_TEST_EQUALS( imageData.GetPixelFormat(), Pixel::RGBA8888, TEST_LOCATION );
+
+  // Test that a pixel in the first quadrant has no alpha value
+  unsigned char* buffer = imageData.GetBuffer();
+  DALI_TEST_EQUALS( buffer[3], 0x00u, TEST_LOCATION );
+  DALI_TEST_EQUALS( buffer[7], 0x00u, TEST_LOCATION );
+
+  // Test that an even pixel in the second quadrant has no alpha value
+  DALI_TEST_EQUALS( buffer[43], 0x00u, TEST_LOCATION );
+
+  // Test that an odd pixel in the second quadrant has full alpha value
+  DALI_TEST_EQUALS( buffer[47], 0xffu, TEST_LOCATION );
+
+  END_TEST;
+}
+
+int UtcDaliPixelBufferMask03(void)
+{
+  TestApplication application;
+  tet_infoline("Test application of alpha mask to smaller RGB565 image");
+
+  unsigned int width = 20u;
+  unsigned int height = 20u;
+  Devel::PixelBuffer maskData = Devel::PixelBuffer::New( width, height, Pixel::L8 );
+  Mask1stQuadrant(maskData);
+
+  width = 10u;
+  height = 10u;
+  Pixel::Format format = Pixel::RGB565;
+  Devel::PixelBuffer imageData = Devel::PixelBuffer::New( width, height, format );
+  FillCheckerboard(imageData);
+
+  imageData.ApplyMask( maskData );
+
+  // Test that the pixel format has been promoted to RGBA8888
+  DALI_TEST_EQUALS( imageData.GetPixelFormat(), Pixel::RGBA8888, TEST_LOCATION );
+
+  // Test that a pixel in the first quadrant has no alpha value
+  unsigned char* buffer = imageData.GetBuffer();
+  DALI_TEST_EQUALS( buffer[3], 0x00u, TEST_LOCATION );
+  DALI_TEST_EQUALS( buffer[7], 0x00u, TEST_LOCATION );
+
+  // Test that an odd pixel in the second quadrant has full alpha value
+  DALI_TEST_EQUALS( buffer[23], 0xffu, TEST_LOCATION );
+
+  // Test that an even pixel in the second quadrant has full alpha value
+  DALI_TEST_EQUALS( buffer[27], 0xffu, TEST_LOCATION );
+
+  END_TEST;
+}
+
+
+int UtcDaliPixelBufferMask04(void)
+{
+  TestApplication application;
+  tet_infoline("Test application of alpha mask to larger RGBA8888 image");
+
+  unsigned int width = 10u;
+  unsigned int height = 10u;
+  Devel::PixelBuffer maskData = Devel::PixelBuffer::New( width, height, Pixel::L8 );
+  Mask1stQuadrant(maskData);
+
+  width = 20u;
+  height = 20u;
+  Devel::PixelBuffer imageData = Devel::PixelBuffer::New( width, height, Pixel::RGBA8888 );
+  FillCheckerboard(imageData);
+
+  imageData.ApplyMask( maskData );
+
+  // Test that the pixel format has been promoted to RGBA8888
+  DALI_TEST_EQUALS( imageData.GetPixelFormat(), Pixel::RGBA8888, TEST_LOCATION );
+
+  // Test that a pixel in the first quadrant has no alpha value
+  unsigned char* buffer = imageData.GetBuffer();
+  DALI_TEST_EQUALS( buffer[3], 0x00u, TEST_LOCATION );
+  DALI_TEST_EQUALS( buffer[7], 0x00u, TEST_LOCATION );
+
+  // Test that an even pixel in the second quadrant has no alpha value
+  DALI_TEST_EQUALS( buffer[43], 0x00u, TEST_LOCATION );
+
+  // Test that an odd pixel in the second quadrant has full alpha value
+  DALI_TEST_EQUALS( buffer[47], 0xffu, TEST_LOCATION );
+
+  END_TEST;
+}
+
+int UtcDaliPixelBufferMask05(void)
+{
+  TestApplication application;
+  tet_infoline("Test application of alpha mask to smaller RGBA8888 image");
+
+  unsigned int width = 20u;
+  unsigned int height = 20u;
+  Devel::PixelBuffer maskData = Devel::PixelBuffer::New( width, height, Pixel::L8 );
+  Mask1stQuadrant(maskData);
+
+  width = 10u;
+  height = 10u;
+  Devel::PixelBuffer imageData = Devel::PixelBuffer::New( width, height, Pixel::RGBA8888 );
+  FillCheckerboard(imageData);
+
+  imageData.ApplyMask( maskData );
+
+  // Test that the pixel format has been promoted to RGBA8888
+  DALI_TEST_EQUALS( imageData.GetPixelFormat(), Pixel::RGBA8888, TEST_LOCATION );
+
+  // Test that a pixel in the first quadrant has no alpha value
+  unsigned char* buffer = imageData.GetBuffer();
+  DALI_TEST_EQUALS( buffer[3], 0x00u, TEST_LOCATION );
+  DALI_TEST_EQUALS( buffer[7], 0x00u, TEST_LOCATION );
+
+  // Test that an odd pixel in the second quadrant has full alpha value
+  DALI_TEST_EQUALS( buffer[23], 0xffu, TEST_LOCATION );
+
+  // Test that an even pixel in the second quadrant has no alpha value
+  DALI_TEST_EQUALS( buffer[27], 0x00u, TEST_LOCATION );
+
+  END_TEST;
+}
diff --git a/build/emscripten/.gitignore b/build/emscripten/.gitignore
deleted file mode 100644 (file)
index 796b96d..0000000
+++ /dev/null
@@ -1 +0,0 @@
-/build
diff --git a/build/emscripten/CMakeLists.txt b/build/emscripten/CMakeLists.txt
deleted file mode 100644 (file)
index 91de672..0000000
+++ /dev/null
@@ -1,149 +0,0 @@
-cmake_minimum_required(VERSION 2.6)
-
-if( ${EMSCRIPTEN} )
-  message("EMSCRIPTEN BUILD")
-  set(CMAKE_C_COMPILER "emcc")
-  set(CMAKE_CXX_COMPILER "em++")
-else( ${EMSCRIPTEN} )
-  message( FATAL_ERROR "Native Build not supported via cmake." )
-endif( ${EMSCRIPTEN} )
-
-if(NOT DEFINED ENV{DESKTOP_PREFIX})
-  message( FATAL_ERROR "DESKTOP_PREFIX is required to build adaptor against dali-core. Please make sure you have sourced your setenv script (created by dali_env)." )
-endif()
-
-project(dali-emscripten CXX)
-
-set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_SOURCE_DIR}/cmake/modules/")
-
-set(SRCS
-  ${CMAKE_SOURCE_DIR}/../../adaptors/emscripten/wrappers/actor-wrapper.cpp
-  ${CMAKE_SOURCE_DIR}/../../adaptors/emscripten/wrappers/animation-wrapper.cpp
-  ${CMAKE_SOURCE_DIR}/../../adaptors/emscripten/wrappers/dali-wrapper.cpp
-  ${CMAKE_SOURCE_DIR}/../../adaptors/emscripten/wrappers/emscripten-utils.cpp
-  ${CMAKE_SOURCE_DIR}/../../adaptors/emscripten/wrappers/handle-wrapper.cpp
-  ${CMAKE_SOURCE_DIR}/../../adaptors/emscripten/wrappers/image-wrapper.cpp
-  ${CMAKE_SOURCE_DIR}/../../adaptors/emscripten/wrappers/property-buffer-wrapper.cpp
-  ${CMAKE_SOURCE_DIR}/../../adaptors/emscripten/wrappers/property-value-wrapper.cpp
-  ${CMAKE_SOURCE_DIR}/../../adaptors/emscripten/wrappers/render-task-wrapper.cpp
-  ${CMAKE_SOURCE_DIR}/../../adaptors/emscripten/wrappers/type-info-wrapper.cpp
-  ${CMAKE_SOURCE_DIR}/../../adaptors/base/separate-update-render/frame-time.cpp
-  ${CMAKE_SOURCE_DIR}/../../adaptors/base/time-service.cpp
-  ${CMAKE_SOURCE_DIR}/../../adaptors/common/gl/egl-image-extensions.cpp
-  ${CMAKE_SOURCE_DIR}/../../adaptors/common/gl/gl-extensions.cpp
-  ${CMAKE_SOURCE_DIR}/../../adaptors/emscripten/egl-implementation-emscripten.cpp
-  ${CMAKE_SOURCE_DIR}/../../adaptors/emscripten/main.cpp
-  ${CMAKE_SOURCE_DIR}/../../adaptors/emscripten/sdl-application.cpp
-  ${CMAKE_SOURCE_DIR}/../../adaptors/emscripten/sdl-gl-sync-abstraction.cpp
-  ${CMAKE_SOURCE_DIR}/../../platform-abstractions/emscripten/emscripten-callbacks.cpp
-  ${CMAKE_SOURCE_DIR}/../../platform-abstractions/emscripten/emscripten-platform-abstraction.cpp
-)
-
-include_directories(${CMAKE_SOURCE_DIR}/../../)
-include_directories(${CMAKE_SOURCE_DIR}/../../adaptors/)
-include_directories(${CMAKE_SOURCE_DIR}/../../adaptors/common)
-include_directories(${CMAKE_SOURCE_DIR}/../../adaptors/tizen)
-include_directories(${CMAKE_SOURCE_DIR}/../../adaptors/emscripten)
-include_directories(${CMAKE_SOURCE_DIR}/../../platform-abstractions/slp)
-
-configure_file(${CMAKE_SOURCE_DIR}/../../adaptors/emscripten/wrappers/tests/all.html all.html COPYONLY)
-configure_file(${CMAKE_SOURCE_DIR}/../../adaptors/emscripten/wrappers/tests/dali-page.html dali-page.html COPYONLY)
-configure_file(${CMAKE_SOURCE_DIR}/../../adaptors/emscripten/wrappers/tests/dali-tests.css dali-tests.css COPYONLY)
-configure_file(${CMAKE_SOURCE_DIR}/../../adaptors/emscripten/wrappers/tests/dali-tests.html dali-tests.html COPYONLY)
-configure_file(${CMAKE_SOURCE_DIR}/../../adaptors/emscripten/wrappers/tests/geometry.js geometry.js COPYONLY)
-configure_file(${CMAKE_SOURCE_DIR}/../../adaptors/emscripten/wrappers/tests/properties.js properties.js COPYONLY)
-configure_file(${CMAKE_SOURCE_DIR}/../../adaptors/emscripten/wrappers/tests/signals.js signals.js COPYONLY)
-configure_file(${CMAKE_SOURCE_DIR}/../../adaptors/emscripten/wrappers/tests/math.js math.js COPYONLY)
-configure_file(${CMAKE_SOURCE_DIR}/../../adaptors/emscripten/wrappers/tests/animation.js animation.js COPYONLY)
-configure_file(${CMAKE_SOURCE_DIR}/../../adaptors/emscripten/wrappers/tests/utilities.js utilities.js COPYONLY)
-configure_file(${CMAKE_SOURCE_DIR}/../../adaptors/emscripten/wrappers/tests/shaders.js shaders.js COPYONLY)
-configure_file(${CMAKE_SOURCE_DIR}/../../adaptors/emscripten/wrappers/tests/views.js views.js COPYONLY)
-
-configure_file(${CMAKE_SOURCE_DIR}/../../adaptors/emscripten/wrappers/tests/qunit/qunit-1.21.0.css qunit-1.21.0.css COPYONLY)
-configure_file(${CMAKE_SOURCE_DIR}/../../adaptors/emscripten/wrappers/tests/qunit/qunit-1.21.0.js qunit-1.21.0.js COPYONLY)
-
-configure_file(${CMAKE_SOURCE_DIR}/../../adaptors/emscripten/wrappers/dali-wrapper.js dali-wrapper.js COPYONLY)
-
-set(VENDOR "samsung")
-set(PACKAGE ${PROJECT_NAME})
-set(DESKTOP_PREFIX $ENV{DESKTOP_PREFIX})
-set(CPP_DEFINES -DDALI_GLES_VERSION=2)
-
-set(EMSCRIPTEN_ENV_DIR ${DESKTOP_PREFIX}/share/emscripten)
-
-set(DEBUG_FLAGS "-Wall -g -O2")
-set(RELEASE_FLAGS "-Wall -g -O2")
-
-if( ${EMSCRIPTEN} )
- set(DEBUG_FLAGS "${DEBUG_FLAGS} -std=c++11 -DBOOST_ERROR_CODE_HEADER_ONLY")
- set(RELEASE_FLAGS "${RELEASE_FLAGS} -std=c++11 -DBOOST_ERROR_CODE_HEADER_ONLY")
-endif( ${EMSCRIPTEN} )
-
-
-include(FindPkgConfig)
-
-pkg_check_modules(pkgs REQUIRED
-  dali-core
-  # sdl from emscripten
-  )
-
-if( ${EMSCRIPTEN} )
-
-pkg_check_modules(pkgs REQUIRED
-  dali-core
-  # sdl from emscripten
-  )
-
-else( ${EMSCRIPTEN} )
-
-find_library(SDL VERSION "1.2" REQUIRED HINTS $DESKTOP_PREFIX/lib)
-find_library(SDL REQUIRED)
-find_library(SDL_image REQUIRED)
-
-find_library(jpeg REQUIRED)
-find_library(ft2build REQUIRED)
-find_library(turbojpeg REQUIRED)
-
-pkg_check_modules(pkgs REQUIRED
-  dali-core
-  # sdl from emscripten
-  sdl
-  egl
-  )
-
-include_directories(/usr/local/include/SDL/)
-set(LIBS ${LIBS} -lSDL -lSDL_image -lEGL -lGLESv2)
-
-endif( ${EMSCRIPTEN} )
-
-# non pkg config
-include_directories(${DESKTOP_PREFIX}/include/)
-
-add_definitions( ${CPP_DEFINES} ) # see configure_file() for *.in to *.h style
-
-set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} ${DEBUG_FLAGS}")
-set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} ${RELEASE_FLAGS}")
-
-add_executable(${PROJECT_NAME} ${SRCS})
-
-target_link_libraries(${PROJECT_NAME} ${pkgs_LDFLAGS} ${LIBS}) # "-lm"
-
-# Copy dali-wrapper.js to dali-env
-configure_file(${CMAKE_SOURCE_DIR}/../../adaptors/emscripten/wrappers/dali-wrapper.js ${EMSCRIPTEN_ENV_DIR}/dali-wrapper.js COPYONLY)
-
-# tests
-configure_file(${CMAKE_SOURCE_DIR}/../../adaptors/emscripten/wrappers/tests/all.html ${EMSCRIPTEN_ENV_DIR}/all.html COPYONLY)
-configure_file(${CMAKE_SOURCE_DIR}/../../adaptors/emscripten/wrappers/tests/dali-page.html ${EMSCRIPTEN_ENV_DIR}/dali-page.html COPYONLY)
-configure_file(${CMAKE_SOURCE_DIR}/../../adaptors/emscripten/wrappers/tests/dali-tests.css ${EMSCRIPTEN_ENV_DIR}/dali-tests.css COPYONLY)
-configure_file(${CMAKE_SOURCE_DIR}/../../adaptors/emscripten/wrappers/tests/dali-tests.html ${EMSCRIPTEN_ENV_DIR}/dali-tests.html COPYONLY)
-configure_file(${CMAKE_SOURCE_DIR}/../../adaptors/emscripten/wrappers/tests/geometry.js ${EMSCRIPTEN_ENV_DIR}/geometry.js COPYONLY)
-configure_file(${CMAKE_SOURCE_DIR}/../../adaptors/emscripten/wrappers/tests/properties.js ${EMSCRIPTEN_ENV_DIR}/properties.js COPYONLY)
-configure_file(${CMAKE_SOURCE_DIR}/../../adaptors/emscripten/wrappers/tests/signals.js ${EMSCRIPTEN_ENV_DIR}/signals.js COPYONLY)
-configure_file(${CMAKE_SOURCE_DIR}/../../adaptors/emscripten/wrappers/tests/math.js ${EMSCRIPTEN_ENV_DIR}/math.js COPYONLY)
-configure_file(${CMAKE_SOURCE_DIR}/../../adaptors/emscripten/wrappers/tests/animation.js ${EMSCRIPTEN_ENV_DIR}/animation.js COPYONLY)
-configure_file(${CMAKE_SOURCE_DIR}/../../adaptors/emscripten/wrappers/tests/utilities.js ${EMSCRIPTEN_ENV_DIR}/utilities.js COPYONLY)
-configure_file(${CMAKE_SOURCE_DIR}/../../adaptors/emscripten/wrappers/tests/shaders.js ${EMSCRIPTEN_ENV_DIR}/shaders.js COPYONLY)
-configure_file(${CMAKE_SOURCE_DIR}/../../adaptors/emscripten/wrappers/tests/views.js ${EMSCRIPTEN_ENV_DIR}/views.js COPYONLY)
-
-configure_file(${CMAKE_SOURCE_DIR}/../../adaptors/emscripten/wrappers/tests/qunit/qunit-1.21.0.css ${EMSCRIPTEN_ENV_DIR}/qunit-1.21.0.css COPYONLY)
-configure_file(${CMAKE_SOURCE_DIR}/../../adaptors/emscripten/wrappers/tests/qunit/qunit-1.21.0.js ${EMSCRIPTEN_ENV_DIR}/qunit-1.21.0.js COPYONLY)
diff --git a/build/emscripten/build.sh b/build/emscripten/build.sh
deleted file mode 100755 (executable)
index 15472ac..0000000
+++ /dev/null
@@ -1,49 +0,0 @@
-#!/bin/bash
-
-# This script builds dali-adaptor using Emscripten.
-
-# DESKTOP_PREFIX is required to build Emscripten DALi.
-if [ -z ${DESKTOP_PREFIX} ]; then
-  echo "DESKTOP_PREFIX is required to build adaptor against dali-core. Please make sure you have sourced your setenv script (created by dali_env)."
-  exit 1
-fi
-
-
-mkdir -p build
-cd build
-rm CMakeCache.txt
-
-/usr/bin/cmake .. -DCMAKE_BUILD_TYPE=Debug -DEMSCRIPTEN=1
-
-make -j8
-# On error, exit and return error.
-if [ $? -ne 0 ] ; then
- exit 1
-fi
-
-
-
-mv dali-emscripten dali-emscripten.bc
-
-# Non-optimised build.
-emcc dali-emscripten.bc -o dali-emscripten.html --memory-init-file 0 -s FULL_ES2=1 -s STB_IMAGE=1 -s ALLOW_MEMORY_GROWTH=1 -s ASSERTIONS=1 -s DEMANGLE_SUPPORT=1 -s DISABLE_EXCEPTION_CATCHING=0 -s EXPORT_NAME=\"dali\" -g4 --bind ; make -j8
-# On error, exit and return error.
-if [ $? -ne 0 ] ; then
- exit 1
-fi
-
-
-# Debug build.
-#emcc dali-emscripten.bc -o dali-emscripten.html --memory-init-file 0 -s FULL_ES2=1 -s STB_IMAGE=1 -s ALLOW_MEMORY_GROWTH=1 -s ASSERTIONS=2 -s DEMANGLE_SUPPORT=1 -s DISABLE_EXCEPTION_CATCHING=0 -s EXPORT_NAME=\"dali\" --js-opts 0 -g4 --bind
-
-# Optimised build.
-#emcc dali-emscripten.bc -o dali-emscripten.html -s FULL_ES2=1 -s STB_IMAGE=1 -s ALLOW_MEMORY_GROWTH=1 -s ASSERTIONS=0 -s DISABLE_EXCEPTION_CATCHING=2  -s EXPORT_NAME=\"dali\" -O2 --bind
-
-# Copy the required built artifacts to dali-env.
-mv ./dali-emscripten.js ${DESKTOP_PREFIX}/share/emscripten/
-mv ./dali-emscripten.html ${DESKTOP_PREFIX}/share/emscripten/
-
-# If static memory initialisation code was created in a separate file, copy this too.
-if [ -a ./dali-emcripten.html.mem ]; then
-  mv ./dali-emscripten.html.mem ${DESKTOP_PREFIX}/share/emscripten/
-fi
index 927c5f0..d04baf7 100644 (file)
@@ -493,7 +493,7 @@ endif
 if WEARABLE_PROFILE
 libdali_adaptor_la_CXXFLAGS += \
                       $(HAPTIC_CFLAGS) \
-                      $(EFL_ASSIST_CFLAGS)
+                      $(EFL_ASSIST_CFLAGS) \
                       $(APPCORE_WATCH_CFLAGS)
 
 libdali_adaptor_la_LIBADD += \
index 2fb8f35..5944acd 100644 (file)
@@ -56,6 +56,7 @@ libdali_feedback_plugin_la_CXXFLAGS = -DDALI_COMPILATION \
                       -I../../../adaptors/public-api \
                       -I../../../adaptors/integration-api \
                       -I../../../adaptors/public-api/adaptor-framework \
+                      -I../../../adaptors/devel-api/adaptor-framework \
                       -Werror -Wall
 
 libdali_feedback_plugin_la_LIBADD = \
@@ -65,30 +66,6 @@ libdali_feedback_plugin_la_LIBADD = \
 libdali_feedback_plugin_la_LDFLAGS = \
                       -rdynamic
 
-if MOBILE_PROFILE
-libdali_feedback_plugin_la_CXXFLAGS += \
-                      $(DEVICED_CFLAGS)
-
-libdali_feedback_plugin_la_LIBADD += \
-                      $(DEVICED_LIBS)
-endif
-
-if TV_PROFILE
-libdali_feedback_plugin_la_CXXFLAGS += \
-                      $(HAPTIC_CFLAGS)
-
-libdali_feedback_plugin_la_LIBADD += \
-                      $(HAPTIC_LIBS)
-endif
-
-if COMMON_PROFILE
-libdali_feedback_plugin_la_CXXFLAGS += \
-                      $(HAPTIC_CFLAGS)
-
-libdali_feedback_plugin_la_LIBADD += \
-                      $(HAPTIC_LIBS)
-endif
-
 libdali_feedback_plugin_la_LIBADD += \
                       $(FEEDBACK_LIBS)
 
index b8088b2..3bd8eb9 100644 (file)
@@ -35,18 +35,12 @@ fi # enable_videoplayer
 fi # enable_wayland
 
 if test "x$enable_feedback" = "xyes"; then
-
-if test "x$enable_profile" = "xCOMMON" || test "x$enable_profile" = "xTV"; then
-PKG_CHECK_MODULES(HAPTIC, haptic)
-fi
-
-if test "x$enable_profile" = "xMOBILE"; then
-PKG_CHECK_MODULES(DEVICED, deviced)
-fi
+if test "x$enable_profile" != "xUBUNTU"; then
 
 PKG_CHECK_MODULES(FEEDBACK, feedback)
 PKG_CHECK_MODULES(MMFSOUND, mm-sound)
 
+fi # check UNBUNTU
 fi # enable_feedback
 
 AC_CONFIG_FILES(Makefile)
index 848f5bf..6fb6c70 100644 (file)
@@ -9,12 +9,17 @@
 # performing a gbs build ( use gbs build -v to see it download location) E.g.
 # http://download.tizen.org/snapshots/tizen/tv/tizen-tv/repos/arm-wayland/packages/repodata/xxxx-build.conf.gz
 
+# Do not provide .so automatically for the extensions.
+# This if statement is for backward compatibility with GBM/Obsolete build systems
+%if "%{?profile}" != "wearable" && "%{?profile}" != "mobile" && "%{?profile}" != "tv" && "%{?profile}" != "ivi" && "%{?profile}" != "common"
+%global __provides_exclude_from ^.*\\.(wearable|mobile|tv|ivi|common)$
+%endif
 
 %bcond_with wayland
 
 Name:       dali-adaptor
 Summary:    The DALi Tizen Adaptor
-Version:    1.2.44
+Version:    1.2.46
 Release:    1
 Group:      System/Libraries
 License:    Apache-2.0 and BSD-3-Clause and MIT
@@ -39,56 +44,15 @@ BuildRequires:  pkgconfig(libtzplatform-config)
 %define profile %{tizen_profile_name}
 %endif
 
-%if "%{profile}" == "mobile"
-%define dali_profile MOBILE
-%define dali_feedback_plugin 0
-%define dali_videoplayer_plugin 1
-%define shaderbincache_flag DISABLE
-BuildRequires:  pkgconfig(gles20)
-%define gles_requirement_setup 1
-%endif
-
-%if "%{profile}" == "tv"
-%define dali_profile TV
-%define dali_feedback_plugin 0
-%define dali_videoplayer_plugin 1
-%define shaderbincache_flag DISABLE
-BuildRequires:  pkgconfig(glesv2)
-%define gles_requirement_setup 1
-%endif
-
-%if "%{profile}" == "wearable"
-%define dali_profile WEARABLE
-%define dali_feedback_plugin 0
-%define dali_videoplayer_plugin 1
-%define shaderbincache_flag DISABLE
-BuildRequires:  pkgconfig(gles20)
+# This is for backward-compatibility. This does not deteriorate 4.0 Configurability
+# if wearable || "undefined"
+%if "%{?profile}" != "mobile" && "%{?profile}" != "tv" && "%{?profile}" != "ivi" && "%{?profile}" != "common"
 BuildRequires:  pkgconfig(capi-appfw-watch-application)
 BuildRequires:  pkgconfig(appcore-watch)
-%define gles_requirement_setup 1
 %endif
 
-%if "%{profile}" == "ivi"
-%define dali_profile IVI
-%define dali_feedback_plugin 0
-%define dali_videoplayer_plugin 1
-%define shaderbincache_flag DISABLE
-BuildRequires:  pkgconfig(glesv2)
-%define gles_requirement_setup 1
-%endif
-
-%if "%{profile}" == "common"
-%define dali_profile COMMON
-%define dali_feedback_plugin 0
-%define dali_videoplayer_plugin 1
-%define tizen_2_2_compatibility 0
-%define shaderbincache_flag DISABLE
+BuildRequires:  pkgconfig(gles20)
 BuildRequires:  pkgconfig(glesv2)
-%define gles_requirement_setup 1
-%endif
-
-# If we have not set a BuildRequires for the gles version, default it here.
-%{!?gles_requirement_setup: BuildRequires:  pkgconfig(glesv2)}
 
 BuildRequires:  pkgconfig
 BuildRequires:  gawk
@@ -109,10 +73,8 @@ BuildRequires:  libcurl-devel
 BuildRequires:  pkgconfig(harfbuzz)
 BuildRequires:  fribidi-devel
 
-%if 0%{?tizen_2_2_compatibility} != 1
 BuildRequires:  pkgconfig(capi-system-info)
 BuildRequires:  pkgconfig(capi-system-sensor)
-%endif
 
 # Tizen currently does not have libuv as a separate libuv package
 # So we have to look into the uv headers bundled inside node-js
@@ -125,10 +87,7 @@ BuildRequires:  nodejs-devel
 BuildRequires:  pkgconfig(wayland-egl)
 BuildRequires:  pkgconfig(wayland-client)
 BuildRequires:  wayland-devel
-# Currently Tizen Common we use does not have wayland extensions like xdg-shell
-%if "%{profile}" != "common"
 BuildRequires:  wayland-extension-client-devel
-%endif
 
 # dali-adaptor-uv uses libuv mainloop and has its own wayland client (it needs wayland-client headers).
 BuildRequires:  libxkbcommon-devel
@@ -158,16 +117,100 @@ BuildRequires:  pkgconfig(elementary)
 BuildRequires:  pkgconfig(capi-appfw-application)
 BuildRequires:  pkgconfig(capi-system-system-settings)
 
-%if 0%{?over_tizen_2_2}
-BuildRequires:  pkgconfig(capi-system-info)
+# for feedback plugin
+BuildRequires:  pkgconfig(mm-sound)
+%if 0%{?tizen_version_major} >= 3
+BuildRequires:  pkgconfig(feedback)
 %endif
 
+# for videoplayer Plugin
+BuildRequires:  pkgconfig(capi-media-player)
+
 
+# for multiprofile
+Requires:   %{name}-compat = %{version}-%{release}
+Recommends: %{name}-profile_common = %{version}-%{release}
 
 %description
 The DALi Tizen Adaptor provides a Tizen specific implementation of the dali-core
 platform abstraction and application shell
 
+###########################################
+# Dali adapter for profiles
+###########################################
+
+# This is for backward-compatibility. This does not deteriorate 4.0 Configurability
+# if mobile || "undefined"
+%if "%{?profile}" != "wearable" && "%{?profile}" != "tv" && "%{?profile}" != "ivi" && "%{?profile}" != "common"
+%package profile_mobile
+Summary:        The DALi Tizen Adaptor for mobile
+Provides:       %{name}-compat = %{version}-%{release}
+Conflicts:      %{name}-profile_tv
+Conflicts:      %{name}-profile_wearable
+Conflicts:      %{name}-profile_ivi
+Conflicts:      %{name}-profile_common
+%description profile_mobile
+The DALi Tizen Adaptor for mobile.
+%endif
+
+# This is for backward-compatibility. This does not deteriorate 4.0 Configurability
+# if tv ||"undefined"
+%if "%{?profile}" != "wearable" && "%{?profile}" != "common" && "%{?profile}" != "ivi" && "%{?profile}" != "mobile"
+%package profile_tv
+Summary:        The DALi Tizen Adaptor for tv
+Provides:       %{name}-compat = %{version}-%{release}
+Conflicts:      %{name}-profile_mobile
+Conflicts:      %{name}-profile_wearable
+Conflicts:      %{name}-profile_ivi
+Conflicts:      %{name}-profile_common
+%description profile_tv
+The DALi Tizen Adaptor for tv.
+%endif
+
+# This is for backward-compatibility. This does not deteriorate 4.0 Configurability
+# if wearable || "undefined"
+%if "%{?profile}" != "mobile" && "%{?profile}" != "tv" && "%{?profile}" != "ivi" && "%{?profile}" != "common"
+%package profile_wearable
+Summary:        The DALi Tizen Adaptor for wearable
+Provides:       %{name}-compat = %{version}-%{release}
+Conflicts:      %{name}-profile_mobile
+Conflicts:      %{name}-profile_tv
+Conflicts:      %{name}-profile_ivi
+Conflicts:      %{name}-profile_common
+%description profile_wearable
+The DALi Tizen Adaptor for wearable.
+%endif
+
+# This is for backward-compatibility. This does not deteriorate 4.0 Configurability
+# if ivi ||"undefined"
+%if "%{?profile}" != "wearable" && "%{?profile}" != "tv" && "%{?profile}" != "common" && "%{?profile}" != "mobile"
+%package profile_ivi
+Summary:        The DALi Tizen Adaptor for ivi
+Provides:       %{name}-compat = %{version}-%{release}
+Conflicts:      %{name}-profile_mobile
+Conflicts:      %{name}-profile_wearable
+Conflicts:      %{name}-profile_tv
+Conflicts:      %{name}-profile_common
+%description profile_ivi
+The DALi Tizen Adaptor for ivi.
+%endif
+
+# This is for backward-compatibility. This does not deteriorate 4.0 Configurability
+# if common ||"undefined"
+%if "%{?profile}" != "wearable" && "%{?profile}" != "tv" && "%{?profile}" != "ivi" && "%{?profile}" != "mobile"
+# Currently Tizen Common we use does not have wayland extensions like xdg-shell
+%package profile_common
+%define tizen_2_2_compatibility 0
+Summary:        The DALi Tizen Adaptor for common
+Provides:       %{name}-compat = %{version}-%{release}
+Conflicts:      %{name}-profile_mobile
+Conflicts:      %{name}-profile_wearable
+Conflicts:      %{name}-profile_tv
+Conflicts:      %{name}-profile_ivi
+%description profile_common
+The DALi Tizen Adaptor for common.
+%endif
+
 ##############################
 # devel
 ##############################
@@ -197,13 +240,7 @@ Integration development package for the Adaptor - headers for integrating with a
 %package dali-feedback-plugin
 Summary:    Plugin to play haptic and audio feedback for Dali
 Group:      System/Libraries
-%if 0%{?dali_feedback_plugin}
-#Requires:       libdeviced
-BuildRequires:  pkgconfig(mm-sound)
-#BuildRequires:  pkgconfig(haptic)
-BuildRequires:  libfeedback-devel
-%endif
-
+Requires:   %{name} = %{version}-%{release}
 %description dali-feedback-plugin
 Feedback plugin to play haptic and audio feedback for Dali
 
@@ -215,10 +252,6 @@ Feedback plugin to play haptic and audio feedback for Dali
 %package dali-video-player-plugin
 Summary:    Plugin to play a video file for Dali
 Group:      System/Libraries
-%if 0%{?dali_videoplayer_plugin}
-BuildRequires:  pkgconfig(capi-media-player)
-%endif
-
 %description dali-video-player-plugin
 VideoPlayer plugin to play a video file for Dali
 %endif
@@ -248,7 +281,7 @@ VideoPlayer plugin to play a video file for Dali
 %endif
 
 %define user_shader_cache_dir    %{dali_data_ro_dir}/core/shaderbin/
-%define dali_plugin_sound_files  %{dali_data_ro_dir}/plugins/sounds/
+%define dali_plugin_sound_files  /plugins/sounds/
 %define dev_include_path %{_includedir}
 
 ##############################
@@ -295,14 +328,56 @@ TIZEN_PLATFORM_CONFIG_SUPPORTED="%{tizen_platform_config_supported}" ; export TI
 #--enable-appfw=yes \ # affects both dali-adaptor & dali-adaptor-uv
 #--with-libuv=/usr/include/node/ \ # only affects dali-adaptor-uv
 
+
 # Set up the build via configure.
-%configure --prefix=$PREFIX --with-jpeg-turbo --enable-gles=%{target_gles_version} --enable-shaderbincache=%{shaderbincache_flag} --enable-profile=%{dali_profile} \
-%if 0%{?dali_feedback_plugin}
+#######################################################################
+# This is for backward-compatibility. This does not deteriorate 4.0 Configurability
+# if mobile || "undefined"
+%if "%{?profile}" != "wearable" && "%{?profile}" != "tv" && "%{?profile}" != "ivi" && "%{?profile}" != "common"
+%configure --prefix=$PREFIX --with-jpeg-turbo --enable-gles=%{target_gles_version} \
+           --enable-shaderbincache=DISABLE --enable-profile=MOBILE \
+%if 0%{?tizen_version_major} >= 3
            --enable-feedback \
 %endif
-%if 0%{?dali_videoplayer_plugin}
            --enable-videoplayer \
+%if 0%{?tizen_2_2_compatibility}
+           --with-tizen-2-2-compatibility \
+%endif
+%if %{with wayland}
+           --enable-efl=no \
+%else
+           --enable-efl=yes \
 %endif
+%if 0%{?enable_debug}
+           --enable-debug \
+%endif
+           --enable-appfw=yes \
+           --with-libuv=/usr/include/node/ \
+           $configure_flags --libdir=%{_libdir}
+
+# Build.
+make %{?jobs:-j%jobs}
+
+pushd %{_builddir}/%{name}-%{version}/build/tizen
+%make_install DALI_DATA_RW_DIR="%{dali_data_rw_dir}" DALI_DATA_RO_DIR="%{dali_data_ro_dir}"
+popd
+
+pushd %{buildroot}%{_libdir}
+for FILE in libdali-adap*.so*; do mv "$FILE" "%{_builddir}/%{name}-%{version}/build/tizen/$FILE.mobile"; done
+popd
+
+%endif
+
+#######################################################################
+# This is for backward-compatibility. This does not deteriorate 4.0 Configurability
+# if tv ||"undefined"
+%if "%{?profile}" != "wearable" && "%{?profile}" != "common" && "%{?profile}" != "ivi" && "%{?profile}" != "mobile"
+%configure --prefix=$PREFIX --with-jpeg-turbo --enable-gles=%{target_gles_version} \
+           --enable-shaderbincache=DISABLE --enable-profile=TV \
+%if 0%{?tizen_version_major} >= 3
+           --enable-feedback \
+%endif
+           --enable-videoplayer \
 %if 0%{?tizen_2_2_compatibility}
            --with-tizen-2-2-compatibility \
 %endif
@@ -321,15 +396,146 @@ TIZEN_PLATFORM_CONFIG_SUPPORTED="%{tizen_platform_config_supported}" ; export TI
 # Build.
 make %{?jobs:-j%jobs}
 
+pushd %{_builddir}/%{name}-%{version}/build/tizen
+%make_install DALI_DATA_RW_DIR="%{dali_data_rw_dir}" DALI_DATA_RO_DIR="%{dali_data_ro_dir}"
+popd
+
+pushd %{buildroot}%{_libdir}
+for FILE in libdali-adap*.so*; do mv "$FILE" "%{_builddir}/%{name}-%{version}/build/tizen/$FILE.tv"; done
+popd
+
+%endif
+
+#######################################################################
+# This is for backward-compatibility. This does not deteriorate 4.0 Configurability
+# if wearable || "undefined"
+%if "%{?profile}" != "mobile" && "%{?profile}" != "tv" && "%{?profile}" != "ivi" && "%{?profile}" != "common"
+%configure --prefix=$PREFIX --with-jpeg-turbo --enable-gles=%{target_gles_version} \
+           --enable-shaderbincache=DISABLE --enable-profile=WEARABLE \
+%if 0%{?tizen_version_major} >= 3
+           --enable-feedback \
+%endif
+           --enable-videoplayer \
+%if 0%{?tizen_2_2_compatibility}
+           --with-tizen-2-2-compatibility \
+%endif
+%if %{with wayland}
+           --enable-efl=no \
+%else
+           --enable-efl=yes \
+%endif
+%if 0%{?enable_debug}
+           --enable-debug \
+%endif
+           --enable-appfw=yes \
+           --with-libuv=/usr/include/node/ \
+           $configure_flags --libdir=%{_libdir}
+
+# Build.
+make %{?jobs:-j%jobs}
+
+pushd %{_builddir}/%{name}-%{version}/build/tizen
+%make_install DALI_DATA_RW_DIR="%{dali_data_rw_dir}" DALI_DATA_RO_DIR="%{dali_data_ro_dir}"
+popd
+
+pushd %{buildroot}%{_libdir}
+for FILE in libdali-adap*.so*; do mv "$FILE" "%{_builddir}/%{name}-%{version}/build/tizen/$FILE.wearable"; done
+popd
+
+%endif
+
+#######################################################################
+# This is for backward-compatibility. This does not deteriorate 4.0 Configurability
+# if ivi ||"undefined"
+%if "%{?profile}" != "wearable" && "%{?profile}" != "tv" && "%{?profile}" != "common" && "%{?profile}" != "mobile"
+%configure --prefix=$PREFIX --with-jpeg-turbo --enable-gles=%{target_gles_version} \
+           --enable-shaderbincache=DISABLE --enable-profile=IVI \
+%if 0%{?tizen_version_major} >= 3
+           --enable-feedback \
+%endif
+           --enable-videoplayer \
+%if 0%{?tizen_2_2_compatibility}
+           --with-tizen-2-2-compatibility \
+%endif
+%if %{with wayland}
+           --enable-efl=no \
+%else
+           --enable-efl=yes \
+%endif
+%if 0%{?enable_debug}
+           --enable-debug \
+%endif
+           --enable-appfw=yes \
+           --with-libuv=/usr/include/node/ \
+           $configure_flags --libdir=%{_libdir}
+
+# Build.
+make %{?jobs:-j%jobs}
+
+pushd %{_builddir}/%{name}-%{version}/build/tizen
+%make_install DALI_DATA_RW_DIR="%{dali_data_rw_dir}" DALI_DATA_RO_DIR="%{dali_data_ro_dir}"
+popd
+
+pushd %{buildroot}%{_libdir}
+for FILE in libdali-adap*.so*; do mv "$FILE" "%{_builddir}/%{name}-%{version}/build/tizen/$FILE.ivi"; done
+popd
+
+%endif
+
+#######################################################################
+# common ( build dali_videoplayer_plugin for common uses )
+# This is for backward-compatibility. This does not deteriorate 4.0 Configurability
+# if common ||"undefined"
+%if "%{?profile}" != "wearable" && "%{?profile}" != "tv" && "%{?profile}" != "ivi" && "%{?profile}" != "mobile"
+%configure --prefix=$PREFIX --with-jpeg-turbo --enable-gles=%{target_gles_version} \
+           --enable-shaderbincache=DISABLE --enable-profile=COMMON \
+%if 0%{?tizen_version_major} >= 3
+           --enable-feedback \
+%endif
+           --enable-videoplayer \
+%if 0%{?tizen_2_2_compatibility}
+           --with-tizen-2-2-compatibility \
+%endif
+%if %{with wayland}
+           --enable-efl=no \
+%else
+           --enable-efl=yes \
+%endif
+%if 0%{?enable_debug}
+           --enable-debug \
+%endif
+           --enable-appfw=yes \
+           --with-libuv=/usr/include/node/ \
+           $configure_flags --libdir=%{_libdir}
+
+# Build.
+make %{?jobs:-j%jobs}
+%endif
+
+
 ##############################
 # Installation
 ##############################
 %install
 rm -rf %{buildroot}
-cd build/tizen
+
+pushd %{_builddir}/%{name}-%{version}/build/tizen
 %make_install DALI_DATA_RW_DIR="%{dali_data_rw_dir}" DALI_DATA_RO_DIR="%{dali_data_ro_dir}"
 
 
+# This is for backward-compatibility. This does not deteriorate 4.0 Configurability
+# !unified && (wearable || tv || ivi || mobile)
+%if "%{?profile}" == "wearable" || "%{?profile}" == "tv" || "%{?profile}" == "ivi" || "%{?profile}" == "mobile"
+rm -rf %{buildroot}%{_libdir}/libdali-adap*.so*
+%endif
+
+# This is for backward-compatibility. This does not deteriorate 4.0 Configurability
+# wearable || tv || ivi || mobile || unified
+%if "%{?profile}" != "common"
+for FILE in libdali-*.so*; do mv "$FILE" "%{buildroot}%{_libdir}/$FILE"; done
+%endif
+popd
+
 ##############################
 # Upgrade order:
 # 1 - Pre Install new package
@@ -350,47 +556,101 @@ exit 0
 /sbin/ldconfig
 exit 0
 
-%if 0%{?dali_feedback_plugin}
-%post dali-feedback-plugin
+##############################
+#  Pre Uninstall old package
+##############################
+%preun
+exit 0
+
+##############################
+#  Post Uninstall old package
+##############################
+%postun
 /sbin/ldconfig
 exit 0
-%endif
 
 %if %{with wayland}
-%if 0%{?dali_videoplayer_plugin}
 %post dali-video-player-plugin
 /sbin/ldconfig
 exit 0
 %endif
+
+%if %{with wayland}
+%postun dali-video-player-plugin
+/sbin/ldconfig
+exit 0
 %endif
 
+
 ##############################
-#   Pre Uninstall old package
-##############################
-%preun
+
+# This is for backward-compatibility. This does not deteriorate 4.0 Configurability
+# if mobile || "undefined"
+%if "%{?profile}" != "wearable" && "%{?profile}" != "tv" && "%{?profile}" != "ivi" && "%{?profile}" != "common"
+%post profile_mobile
+pushd %{_libdir}
+for FILE in libdali-adap*.so*.mobile; do ln -sf "$FILE" "${FILE%.mobile}"; done
+popd
+/sbin/ldconfig
 exit 0
 
+%postun profile_mobile
+/sbin/ldconfig
+exit 0
+%endif
+
 ##############################
-#   Post Uninstall old package
-##############################
-%postun
+
+# This is for backward-compatibility. This does not deteriorate 4.0 Configurability
+# if tv ||"undefined"
+%if "%{?profile}" != "wearable" && "%{?profile}" != "common" && "%{?profile}" != "ivi" && "%{?profile}" != "mobile"
+%post profile_tv
+pushd %{_libdir}
+for FILE in libdali-adap*.so*.tv; do ln -sf "$FILE" "${FILE%.tv}"; done
+popd
 /sbin/ldconfig
 exit 0
 
-%if 0%{?dali_feedback_plugin}
-%postun dali-feedback-plugin
+%postun profile_tv
 /sbin/ldconfig
 exit 0
 %endif
 
-%if %{with wayland}
-%if 0%{?dali_videoplayer_plugin}
-%postun dali-video-player-plugin
+##############################
+
+# This is for backward-compatibility. This does not deteriorate 4.0 Configurability
+# if wearable || "undefined"
+%if "%{?profile}" != "mobile" && "%{?profile}" != "tv" && "%{?profile}" != "ivi" && "%{?profile}" != "common"
+%post profile_wearable
+pushd %{_libdir}
+for FILE in libdali-adap*.so*.wearable; do ln -sf "$FILE" "${FILE%.wearable}"; done
+popd
+/sbin/ldconfig
+exit 0
+
+%postun profile_wearable
 /sbin/ldconfig
 exit 0
 %endif
+
+##############################
+
+# This is for backward-compatibility. This does not deteriorate 4.0 Configurability
+# if ivi ||"undefined"
+%if "%{?profile}" != "wearable" && "%{?profile}" != "tv" && "%{?profile}" != "common" && "%{?profile}" != "mobile"
+%post profile_ivi
+pushd %{_libdir}
+for FILE in libdali-adap*.so*.ivi; do ln -sf "$FILE" "${FILE%.ivi}"; done
+popd
+/sbin/ldconfig
+exit 0
+
+%postun profile_ivi
+/sbin/ldconfig
+exit 0
 %endif
 
+
 ##############################
 # Files in Binary Packages
 ##############################
@@ -398,39 +658,92 @@ exit 0
 %files
 %manifest dali-adaptor.manifest
 %defattr(-,root,root,-)
-%{_libdir}/libdali-adap*.so*
 %defattr(-,app,app,-)
 %dir %{user_shader_cache_dir}
 %{_bindir}/*
 %license LICENSE
 
-%files devel
+# This is for backward-compatibility. This does not deteriorate 4.0 Configurability
+# if common ||"undefined"
+%if "%{?profile}" != "wearable" && "%{?profile}" != "tv" && "%{?profile}" != "ivi" && "%{?profile}" != "mobile"
 %defattr(-,root,root,-)
-%{dev_include_path}/dali/dali.h
-%{dev_include_path}/dali/public-api/*
-%{dev_include_path}/dali/devel-api/*
-%{dev_include_path}/dali/doc/*
-%{_libdir}/pkgconfig/dali-adaptor.pc
-%{_libdir}/pkgconfig/dali-adaptor-uv.pc
+%{_libdir}/libdali-adap*.so*
+%exclude %{_libdir}/libdali-adap*.so*.mobile
+%exclude %{_libdir}/libdali-adap*.so*.wearable
+%exclude %{_libdir}/libdali-adap*.so*.tv
+%exclude %{_libdir}/libdali-adap*.so*.ivi
+%endif
 
-%files integration-devel
+%if %{with wayland}
+%files dali-video-player-plugin
+%manifest dali-adaptor.manifest
 %defattr(-,root,root,-)
-%{dev_include_path}/dali/integration-api/adaptors/*
-%{_libdir}/pkgconfig/dali-adaptor-integration.pc
+%{_libdir}/libdali-video-player-plugin.so*
+%license LICENSE
+%endif
 
-%if 0%{?dali_feedback_plugin}
+%if 0%{?tizen_version_major} >= 3
 %files dali-feedback-plugin
+%manifest dali-adaptor.manifest
 %defattr(-,root,root,-)
 %{_libdir}/libdali-feedback-plugin.so*
 %{dali_plugin_sound_files}/*
 %endif
 
-%if %{with wayland}
-%if 0%{?dali_videoplayer_plugin}
-%files dali-video-player-plugin
+# This is for backward-compatibility. This does not deteriorate 4.0 Configurability
+# if common ||"undefined"
+%if "%{?profile}" != "wearable" && "%{?profile}" != "tv" && "%{?profile}" != "ivi" && "%{?profile}" != "mobile"
+%files profile_common
+# default .so files are housed in the main pkg.
+%endif
+
+# This is for backward-compatibility. This does not deteriorate 4.0 Configurability
+# if mobile || "undefined"
+%if "%{?profile}" != "wearable" && "%{?profile}" != "tv" && "%{?profile}" != "ivi" && "%{?profile}" != "common"
+%files profile_mobile
 %manifest dali-adaptor.manifest
 %defattr(-,root,root,-)
-%{_libdir}/libdali-video-player-plugin.so*
-%license LICENSE
+%{_libdir}/libdali-adap*.so*.mobile
+%endif
+
+# This is for backward-compatibility. This does not deteriorate 4.0 Configurability
+# if tv ||"undefined"
+%if "%{?profile}" != "wearable" && "%{?profile}" != "common" && "%{?profile}" != "ivi" && "%{?profile}" != "mobile"
+%files profile_tv
+%manifest dali-adaptor.manifest
+%defattr(-,root,root,-)
+%{_libdir}/libdali-adap*.so*.tv
 %endif
+
+# This is for backward-compatibility. This does not deteriorate 4.0 Configurability
+# if wearable || "undefined"
+%if "%{?profile}" != "mobile" && "%{?profile}" != "tv" && "%{?profile}" != "ivi" && "%{?profile}" != "common"
+%files profile_wearable
+%manifest dali-adaptor.manifest
+%defattr(-,root,root,-)
+%{_libdir}/libdali-adap*.so*.wearable
+%endif
+
+# This is for backward-compatibility. This does not deteriorate 4.0 Configurability
+# if ivi ||"undefined"
+%if "%{?profile}" != "wearable" && "%{?profile}" != "tv" && "%{?profile}" != "common" && "%{?profile}" != "mobile"
+%files profile_ivi
+%manifest dali-adaptor.manifest
+%defattr(-,root,root,-)
+%{_libdir}/libdali-adap*.so*.ivi
 %endif
+
+
+%files devel
+%defattr(-,root,root,-)
+%{dev_include_path}/dali/dali.h
+%{dev_include_path}/dali/public-api/*
+%{dev_include_path}/dali/devel-api/*
+%{dev_include_path}/dali/doc/*
+%{_libdir}/pkgconfig/dali-adaptor.pc
+%{_libdir}/pkgconfig/dali-adaptor-uv.pc
+
+%files integration-devel
+%defattr(-,root,root,-)
+%{dev_include_path}/dali/integration-api/adaptors/*
+%{_libdir}/pkgconfig/dali-adaptor-integration.pc
diff --git a/platform-abstractions/emscripten/emscripten-callbacks.cpp b/platform-abstractions/emscripten/emscripten-callbacks.cpp
deleted file mode 100644 (file)
index a7abb08..0000000
+++ /dev/null
@@ -1,200 +0,0 @@
-/*
- * Copyright (c) 2015 Samsung Electronics Co., Ltd.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- */
-
-#include "emscripten-callbacks.h"
-
-// EXTERNAL INCLUDES
-#include <vector>
-#include <dali/public-api/dali-core.h>
-#include "emscripten/emscripten.h"
-#include "emscripten/bind.h"
-#include "emscripten/val.h"
-
-// INTERNAL INCLUDES
-
-namespace Dali
-{
-namespace Internal
-{
-namespace Emscripten
-{
-
-Statistics stats;
-
-// Javascript callbacks
-
-// Allows the adaptor to get a glyph image from the browser
-emscripten::val JSGetGlyphImage(emscripten::val::null());
-
-// Allows the adaptor to request an image from the browser
-emscripten::val JSGetImage(emscripten::val::null());
-
-// Allows the adaptor to get image meta data
-emscripten::val JSGetImageMetaData(emscripten::val::null());
-
-// Signals to the browser the end of rendering
-emscripten::val JSRenderFinished(emscripten::val::null());
-
-
-Integration::BitmapPtr GetGlyphImage( const std::string& fontFamily, const std::string& fontStyle, float fontSize, uint32_t character )
-{
-  Integration::BitmapPtr ret;
-
-  // causes exception in browser if callback isnt set to a function;
-  emscripten::val val = JSGetGlyphImage(fontFamily,
-                                        fontStyle,
-                                        fontSize,
-                                        character);
-
-  std::vector<unsigned char> data = emscripten::vecFromJSArray<unsigned char>(val);
-
-  int step = fontSize * 4;
-
-  if( data.size() )
-  {
-    Integration::Bitmap* bitmap = Integration::Bitmap::New(Integration::Bitmap::BITMAP_2D_PACKED_PIXELS,
-                                                           ResourcePolicy::OWNED_DISCARD); // dali manages buffer
-
-    if(bitmap)
-    {
-      Integration::Bitmap::PackedPixelsProfile* profile = bitmap->GetPackedPixelsProfile();
-
-      if(profile)
-      {
-        std::vector<unsigned char> *buffer = new std::vector<unsigned char>;
-
-        buffer->reserve( fontSize * fontSize );
-
-        // take only alpha
-        for(int y = 0; y < fontSize; ++y)
-        {
-          for(int x = 0; x < step; x+=4)
-          {
-            buffer->push_back(data[ x + (y*step) +3]);
-          }
-        }
-
-        if( buffer )
-        {
-          profile->AssignBuffer(Pixel::A8,
-                                &(*buffer)[0],
-                                (*buffer).size(),
-                                fontSize,
-                                fontSize);
-        }
-
-        ret = Integration::BitmapPtr( bitmap );
-      }
-      else
-      {
-        printf("bitmap has no packedpixelsprofile\n");
-      }
-    }
-    else
-    {
-      printf("bitmap not created\n");
-    }
-  }
-  else
-  {
-    printf("Image data from javascript is empty\n");
-  }
-
-  return ret;
-}
-
-
-Integration::BitmapPtr GetImage( const Dali::ImageDimensions& size,
-                                 const Dali::FittingMode::Type& scalingMode,
-                                 const Dali::SamplingMode::Type& samplingMode,
-                                 const bool orientationCorrection,
-                                 const std::string& filename )
-{
-  Integration::BitmapPtr ret;
-
-  // causes exception in browser if callback isnt set to a function;
-  emscripten::val val = JSGetImage(filename);
-
-  emscripten::val array = val["array"];
-  int w     = val["x"].as<int>();
-  int h     = val["y"].as<int>();
-
-  std::vector<unsigned char> data = emscripten::vecFromJSArray<unsigned char>(array);
-
-  Integration::Bitmap* bitmap = Integration::Bitmap::New(Integration::Bitmap::BITMAP_2D_PACKED_PIXELS,
-                                                         Dali::ResourcePolicy::OWNED_DISCARD); // dali manages buffer
-
-  if(bitmap)
-  {
-    Integration::Bitmap::PackedPixelsProfile* profile = bitmap->GetPackedPixelsProfile();
-
-    if(profile)
-    {
-      std::vector<unsigned char> *buffer = new std::vector<unsigned char>(data.begin(), data.end());
-
-      if( buffer )
-      {
-        profile->AssignBuffer(Pixel::RGBA8888,
-                              &(*buffer)[0],
-                              (*buffer).size(),
-                              w,
-                              h);
-      }
-
-      ret = Integration::BitmapPtr( bitmap );
-    }
-    else
-    {
-      printf("bitmap has no packedpixelsprofile\n");
-    }
-  }
-  else
-  {
-    printf("bitmap not created\n");
-  }
-
-  return ret;
-}
-
-Dali::ImageDimensions LoadImageMetadata(const std::string filename,
-                                        Dali::ImageDimensions& size,
-                                        Dali::FittingMode::Type fittingMode,
-                                        Dali::SamplingMode::Type samplingMode,
-                                        bool orientationCorrection )
-{
-  emscripten::val val = JSGetImageMetaData(filename);
-
-  // @todo
-  // size.x = val["w"]
-  // size.y = val["h"]
-  //
-  return Dali::ImageDimensions();
-}
-
-void RenderFinished()
-{
-  if (JSRenderFinished.typeof().as<std::string>() == "function")
-  {
-    emscripten::val val = JSRenderFinished();
-  }
-}
-
-
-}; // namespace Emscripten
-}; // namespace Internal
-}; // namespace Dali
-
diff --git a/platform-abstractions/emscripten/emscripten-callbacks.h b/platform-abstractions/emscripten/emscripten-callbacks.h
deleted file mode 100644 (file)
index 43a0457..0000000
+++ /dev/null
@@ -1,117 +0,0 @@
-#ifndef __DALI_EMSCRIPTEN_CALLBACKS_H__
-#define __DALI_EMSCRIPTEN_CALLBACKS_H__
-
-/*
- * Copyright (c) 2015 Samsung Electronics Co., Ltd.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- */
-
-// EXTERNAL INCLUDES
-#include <dali/integration-api/platform-abstraction.h>
-#include <dali/public-api/common/dali-common.h>
-
-// INTERNAL INCLUDES
-
-namespace Dali
-{
-namespace Internal
-{
-namespace Emscripten
-{
-
-/**
- * Glyph helper
- *
- * Allows Dali adaptor to request a glyph image from the browser
- *
- * @param[in] fontFamily The font family name
- * @param[in] fontStyle The font style name
- * @param[in] fontSize The font size
- * @param[in] character The character
- *
- */
-Dali::Integration::BitmapPtr GetGlyphImage( const std::string& fontFamily, const std::string& fontStyle, float fontSize, uint32_t character );
-
-/**
- * Image meta data helper
- *
- * Allows Dali adaptor to request image metadata from image known to the browser
- *
- * @param[in] filename The image name (possibly not directly a filename due to the browser sandboxing)
- * @param[in] size The image dimensions
- * @param[in] fittingMode The dali fitting mode
- * @param[in] samplingMode The dali sampling mode
- * @param[in] orientationCorrection The orientation correction
- *
- */
-Dali::ImageDimensions LoadImageMetadata(const std::string filename,
-                                        Dali::ImageDimensions& size,
-                                        Dali::FittingMode::Type fittingMode,
-                                        Dali::SamplingMode::Type samplingMode,
-                                        bool orientationCorrection );
-
-/**
- * Image helper
- *
- * Allows Dali adaptor to request an image from the browser
- *
- * @param[in] size The image dimensionsn
- * @param[in] fittingMode The dali fitting mode
- * @param[in] samplingMode The dali sampling mode
- * @param[in] orientationCorrection The orientation correction
- * @param[in] filename The image name (possibly not directly a filename due to the browser sandboxing)
- *
- */
-Dali::Integration::BitmapPtr GetImage(const Dali::ImageDimensions& size,
-                                      const Dali::FittingMode::Type& fittingMode,
-                                      const Dali::SamplingMode::Type& samplingMode,
-                                      const bool orientationCorrection,
-                                      const std::string& filename );
-
-/**
- * Debug statistics for the browser
- *
- */
-struct Statistics
-{
-  bool on;
-  float frameCount;
-
-  float lastFrameDeltaSeconds;
-  unsigned int lastSyncTimeMilliseconds;
-  unsigned int nextSyncTimeMilliseconds;
-
-  unsigned int keepUpdating; ///< A bitmask of KeepUpdating values
-  bool needsNotification;
-  float secondsFromLastFrame;
-
-Statistics() :on(true),
-    frameCount(0.0),
-    lastFrameDeltaSeconds(0.0),
-    lastSyncTimeMilliseconds(0.0),
-    nextSyncTimeMilliseconds(0.0),
-    keepUpdating(0),
-    needsNotification(false),
-    secondsFromLastFrame(0.0)
-  {};
-};
-
-extern Statistics stats;
-
-}; // namespace Emscripten
-}; // namespace Internal
-}; // namespace Dali
-
-#endif // header
diff --git a/platform-abstractions/emscripten/emscripten-platform-abstraction.cpp b/platform-abstractions/emscripten/emscripten-platform-abstraction.cpp
deleted file mode 100644 (file)
index d744308..0000000
+++ /dev/null
@@ -1,260 +0,0 @@
-/*
- * Copyright (c) 2016 Samsung Electronics Co., Ltd.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- */
-
-#include "emscripten-platform-abstraction.h"
-
-// EXTERNAL INCLUDES
-#include <set>
-#include <stdint.h>
-#include <cstring>
-#include <SDL_surface.h>
-#include <SDL_image.h>
-#include "emscripten/emscripten.h"
-#include "emscripten-callbacks.h"
-
-#define EM_LOG(x); // EM_ASM( console.log( x ) );
-
-
-// INTERNAL INCLUDES
-#include <dali/integration-api/platform-abstraction.h>
-#include <dali/devel-api/common/ref-counted-dali-vector.h>
-
-namespace
-{
-
-Dali::Integration::BitmapPtr LoadResourceEncodedImage( Dali::RefCountedVector<uint8_t>* encodedBlob )
-{
-  Dali::Integration::BitmapPtr bitmapPtr = NULL;
-
-  if( encodedBlob != 0 )
-  {
-    const size_t blobSize     = encodedBlob->GetVector().Size();
-    uint8_t * const blobBytes = &(encodedBlob->GetVector()[0]);
-    DALI_ASSERT_DEBUG( blobSize > 0U );
-    DALI_ASSERT_DEBUG( blobBytes != 0U );
-
-    if( blobBytes != 0 && blobSize > 0U )
-    {
-
-      SDL_RWops *memory = SDL_RWFromMem(blobBytes, blobSize);
-
-      if(!memory)
-      {
-        printf("  Error Null pointer from SDL RW memory?\n");
-      }
-
-      SDL_Surface *surface = IMG_Load_RW(memory, 0);
-
-      if(surface)
-      {
-        bitmapPtr = Dali::Integration::Bitmap::New( Dali::Integration::Bitmap::BITMAP_2D_PACKED_PIXELS,
-                                                    Dali::ResourcePolicy::OWNED_DISCARD ); // DISCARD; Dali manages
-
-        Dali::Integration::Bitmap::PackedPixelsProfile* packedProfile = bitmapPtr->GetPackedPixelsProfile();
-        DALI_ASSERT_ALWAYS(packedProfile);
-
-        unsigned char bytesPerPixel = surface->format->BytesPerPixel;
-
-        Dali::Integration::PixelBuffer* pixels = NULL;
-
-        unsigned char targetBytesPerPixel = 3; // bytesPerPixel;
-
-        // SDL in emscripten returns us a 4byteperpixel image regardless of rgb/png etc
-        // Theres no apparent way to differentiate an image with an alpha channel
-        // In Dali if an image has an alpha channel it gets sorted. This introduces odd artifacts on rotation
-        // as the sorting algorithm presumes front on view.
-        // So here well just support pngs with an alpha channel.
-        // We're poking around in the format as emscripten currently lacks a file memory api where we could use
-        // Dali's machinery to read the format.
-        unsigned char *pBytes = blobBytes;
-
-        if( 0x89 == *(pBytes+0) && 0x50 == *(pBytes+1) ) // magic bytes for png_all_filters
-        {
-          pBytes+=8; // 8 bytes for header
-          pBytes+=4; // 4 bytes for chunk length
-          pBytes+=4; // 4 bytes for chunk type
-          // ihdr data (must be first chunk)
-          pBytes+=4; // 4 for width,height
-          pBytes+=4;
-          pBytes+=1; // 1 for bit depth
-          unsigned char ihdr_colorType= *pBytes;    // 1 for bit colorType
-          if( (4 == ihdr_colorType ||               // 4 is 8,16 bit depth with alpha LA
-               6 == ihdr_colorType) )               // 6 is 8,16 bit depth with alpha RGBA
-          {
-            targetBytesPerPixel = 4;
-          }
-        }
-
-        if(3 == targetBytesPerPixel)
-        {
-          pixels = packedProfile->ReserveBuffer(Dali::Pixel::RGB888,
-                                                surface->w, surface->h,
-                                                surface->w, surface->h);
-        }
-        else if(4 == targetBytesPerPixel)
-        {
-          pixels = packedProfile->ReserveBuffer(Dali::Pixel::RGBA8888,
-                                                surface->w, surface->h,
-                                                surface->w, surface->h);
-        }
-        else
-        {
-          DALI_ASSERT_ALWAYS(0 && "bad bytes per pixel");
-        }
-
-        unsigned char* fromPtr = static_cast<unsigned char*>(surface->pixels);
-
-        int stride = surface->pitch;
-        int index = 0;
-        for(int h = 0; h < surface->h; ++h)
-        {
-          for(int w = 0; w < (surface->w*bytesPerPixel); w+=bytesPerPixel)
-          {
-            for(int j = 0; j < targetBytesPerPixel; ++j)
-            {
-              pixels[ index++ ] = *( (fromPtr + (h * stride) ) + w + j );
-            }
-          }
-        }
-      } // if surface
-      else
-      {
-        printf("  Error empty surface when decoding image? (SDL RW Memory ptr=%llx) %s. %d\n", (long long)(memory), SDL_GetError(), blobSize);
-      }
-
-    } // if blobSize
-    else
-    {
-      printf(" Error No bytes in image?\n");
-    }
-
-  } // if encodedBlob
-  else
-  {
-    printf("  Error Null pointer given for decoding image?\n");
-  }
-
-  if(bitmapPtr)
-  {
-    int x = 0;
-    EM_ASM( console.log( "LoadResourceEncodedImage: Image:-" ) );
-    x = EM_ASM_INT({
-        console.log( $0 ) }, bitmapPtr->GetImageWidth() );
-    x = EM_ASM_INT({
-        console.log( $0 ) }, bitmapPtr->GetImageHeight() );
-    x = EM_ASM_INT({
-        console.log( $0 ) }, bitmapPtr->GetBufferSize() );
-
-  }
-  else
-  {
-    EM_ASM( console.log( "LoadResourceEncodedImage: no bitmap data?" ) );
-  }
-
-  return bitmapPtr;
-}
-
-} // anon namespace
-
-namespace Dali
-{
-
-EmscriptenPlatformAbstraction::EmscriptenPlatformAbstraction()
-  :
-    mSize(10,10)
-{
-}
-
-
-EmscriptenPlatformAbstraction::~EmscriptenPlatformAbstraction()
-{
-}
-
-void EmscriptenPlatformAbstraction::GetTimeMicroseconds(unsigned int &seconds, unsigned int &microSeconds)
-{
-  double current = EM_ASM_DOUBLE_V({ return new Date().getTime(); }); // getTime() in ms
-
-  seconds         = static_cast<unsigned int>(current/1000.0);
-  microSeconds    = (static_cast<unsigned int>(current) - seconds*1000.0) * 1000;
-}
-
-ImageDimensions EmscriptenPlatformAbstraction::GetClosestImageSize( const std::string& filename,
-                                                             ImageDimensions size,
-                                                             FittingMode::Type fittingMode,
-                                                             SamplingMode::Type samplingMode,
-                                                             bool orientationCorrection )
-{
-  return Dali::Internal::Emscripten::LoadImageMetadata(filename, size, fittingMode, samplingMode, orientationCorrection);
-}
-
-ImageDimensions EmscriptenPlatformAbstraction::GetClosestImageSize( Integration::ResourcePointer resourceBuffer,
-                                                             ImageDimensions size,
-                                                             FittingMode::Type fittingMode,
-                                                             SamplingMode::Type samplingMode,
-                                                             bool orientationCorrection )
-{
-  // @todo
-  return Dali::ImageDimensions(); // Dali::Internal::Emscripten::LoadImageMetadata(filename, size, fittingMode, samplingMode, orientationCorrection);
-}
-
-Integration::ResourcePointer EmscriptenPlatformAbstraction::LoadResourceSynchronously( const Integration::ResourceType& resourceType, const std::string& resourcePath )
-{
-  Integration::ResourcePointer ret;
-
-  switch(resourceType.id)
-  {
-    case Integration::ResourceBitmap:
-    {
-      const Integration::BitmapResourceType& bitmapResource( static_cast<const Integration::BitmapResourceType&>(resourceType) );
-
-      Integration::BitmapPtr bitmapPtr = Dali::Internal::Emscripten::GetImage( bitmapResource.size,
-                                                                               bitmapResource.scalingMode,
-                                                                               bitmapResource.samplingMode,
-                                                                               bitmapResource.orientationCorrection,
-                                                                               resourcePath );
-
-      ret = bitmapPtr;
-    }
-    break;
-  } // switch(resourceType->id)
-
-  return ret;
-}
-
-Integration::BitmapPtr EmscriptenPlatformAbstraction::DecodeBuffer( const Integration::ResourceType& resourceType, uint8_t * buffer, size_t bufferSize )
-{
-  return Integration::BitmapPtr();
-}
-
-
-bool EmscriptenPlatformAbstraction::LoadShaderBinaryFile( const std::string& filename, Dali::Vector< unsigned char >& buffer ) const
-{
-  EM_LOG("EmscriptenPlatformAbstraction::LoadShaderBinaryFile");
-  return false;
-}
-
-void EmscriptenPlatformAbstraction::UpdateDefaultsFromDevice()
-{
-  DALI_ASSERT_ALWAYS("!Unimplemented");
-  mGetDefaultFontFamilyResult+=1.0f;
-}
-
-void EmscriptenPlatformAbstraction::IncrementGetTimeResult(size_t milliseconds)
-{
-}
-
-} // Dali
diff --git a/platform-abstractions/emscripten/emscripten-platform-abstraction.h b/platform-abstractions/emscripten/emscripten-platform-abstraction.h
deleted file mode 100644 (file)
index 97e9a51..0000000
+++ /dev/null
@@ -1,137 +0,0 @@
-#ifndef __DALI_EMSCRIPTEN_PLATFORM_ABSTRACTION_H__
-#define __DALI_EMSCRIPTEN_PLATFORM_ABSTRACTION_H__
-
-/*
- * Copyright (c) 2016 Samsung Electronics Co., Ltd.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- */
-
-// EXTERNAL INCLUDES
-#include <set>
-#include <stdint.h>
-#include <cstring>
-#include <queue>
-
-// INTERNAL INCLUDES
-#include <dali/integration-api/platform-abstraction.h>
-#include <dali/integration-api/bitmap.h>
-
-namespace Dali
-{
-
-namespace Integration
-{
-
-typedef IntrusivePtr<Dali::RefObject> ResourcePointer;
-} // namespace Integration
-
-/**
- * An Dali Platform abstraction using libSDL for Emscripten.
- *
- * Emscripten already wraps the SDL API so we can use this API to create windows/canvas in the browser
- *
- */
-class DALI_IMPORT_API EmscriptenPlatformAbstraction : public Dali::Integration::PlatformAbstraction
-{
-
-public:
-
-  struct LoadFileResult
-  {
-    LoadFileResult()
-    : loadResult(false)
-    {
-
-    }
-
-    bool loadResult;
-    std::vector< unsigned char> buffer;
-  };
-
-
-  /**
-   * Constructor
-   */
-  EmscriptenPlatformAbstraction();
-
-
-  /**
-   * Destructor
-   */
-  virtual ~EmscriptenPlatformAbstraction();
-
-  /**
-   * @copydoc PlatformAbstraction::GetTimeMicroseconds()
-   */
-  virtual void GetTimeMicroseconds(unsigned int &seconds, unsigned int &microSeconds);
-
-  void IncrementGetTimeResult(size_t milliseconds);
-
-  /**
-   * @copydoc PlatformAbstraction::GetClosestImageSize()
-   */
-  virtual ImageDimensions GetClosestImageSize( const std::string& filename,
-                                               ImageDimensions size,
-                                               FittingMode::Type fittingMode,
-                                               SamplingMode::Type samplingMode,
-                                               bool orientationCorrection );
-  /**
-   * @copydoc PlatformAbstraction::GetClosestImageSize()
-   */
-  virtual ImageDimensions GetClosestImageSize( Integration::ResourcePointer resourceBuffer,
-                                               ImageDimensions size,
-                                               FittingMode::Type fittingMode,
-                                               SamplingMode::Type samplingMode,
-                                               bool orientationCorrection );
-
-  /**
-   * @copydoc PlatformAbstraction::LoadResourceSynchronously()
-   */
-  virtual Integration::ResourcePointer LoadResourceSynchronously( const Integration::ResourceType& resourceType, const std::string& resourcePath );
-
-  /**
-   * @copydoc PlatformAbstraction::DecodeBuffer()
-   */
-  virtual Integration::BitmapPtr DecodeBuffer( const Integration::ResourceType& resourceType, uint8_t * buffer, size_t bufferSize );
-
-  /**
-   * @copydoc PlatformAbstraction::LoadShaderBinaryFile()
-   */
-  virtual bool LoadShaderBinaryFile( const std::string& filename, Dali::Vector< unsigned char >& buffer ) const;
-
-  /**
-   * @copydoc PlatformAbstraction::SaveShaderBinaryFile()
-   */
-  virtual bool SaveShaderBinaryFile( const std::string& filename, const unsigned char * buffer, unsigned int numBytes ) const;
-
-  /**
-   * @copydoc PlatformAbstraction::UpdateDefaultsFromDevice()
-   */
-  virtual void UpdateDefaultsFromDevice();
-
-private:
-  std::string                   mGetDefaultFontFamilyResult;
-  Vector2                       mSize;
-
-  LoadFileResult                mLoadFileResult;
-
-  typedef std::pair< Integration::ResourceId, Integration::BitmapPtr > ResourceIdBitmapPair;
-  std::queue<ResourceIdBitmapPair> mResourceQueue;
-
-};
-
-} // Dali
-
-#endif /* __DALI_TET_PLATFORM_ABSTRACTION_H__ */
diff --git a/platform-abstractions/emscripten/file.list b/platform-abstractions/emscripten/file.list
deleted file mode 100755 (executable)
index c64c830..0000000
+++ /dev/null
@@ -1,13 +0,0 @@
-# Add local source files here:
-
-slp_platform_abstraction_src_files = \
-  $(slp_platform_abstraction_src_dir)/emscripten-callbacks.cpp \
-  $(slp_platform_abstraction_src_dir)/emscripten-platform-abstraction.cpp
-
-slp_assimp_src_files =
-
-slp_assimp_stub_src_files =
-
-# Add public headers here:
-
-# platform_abstraction_header_files =
diff --git a/platform-abstractions/portable/alpha-mask.cpp b/platform-abstractions/portable/alpha-mask.cpp
new file mode 100644 (file)
index 0000000..e930fc6
--- /dev/null
@@ -0,0 +1,245 @@
+/*
+ * Copyright (c) 2017 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "pixel-manipulation.h"
+#include "alpha-mask.h"
+#include "pixel-buffer-impl.h"
+
+namespace Dali
+{
+namespace Internal
+{
+namespace Adaptor
+{
+
+
+void ApplyMaskToAlphaChannel( PixelBuffer& buffer, const PixelBuffer& mask )
+{
+  const float rowFactor = float(mask.GetHeight()) / (1.0f * buffer.GetHeight());
+  const float colFactor = float(mask.GetWidth()) / (1.0f * buffer.GetWidth()) ;
+
+  int numSamples = 1;
+  if( mask.GetHeight() > buffer.GetHeight() || mask.GetWidth() > buffer.GetWidth() )
+  {
+    numSamples = 4;
+  }
+
+  int srcAlphaByteOffset=0;
+  int srcAlphaMask=0;
+  Dali::Pixel::Format srcPixelFormat = mask.GetPixelFormat();
+
+  Channel alphaChannel = ALPHA;
+  if( Pixel::HasAlpha(srcPixelFormat) )
+  {
+    Dali::Pixel::GetAlphaOffsetAndMask( srcPixelFormat, srcAlphaByteOffset, srcAlphaMask );
+  }
+  else if( srcPixelFormat == Pixel::L8 )
+  {
+    srcAlphaMask=0xFF;
+    alphaChannel = LUMINANCE;
+  }
+
+  int destAlphaByteOffset=0;
+  int destAlphaMask=0;
+  Dali::Pixel::GetAlphaOffsetAndMask( buffer.GetPixelFormat(), destAlphaByteOffset, destAlphaMask );
+
+  unsigned int srcBytesPerPixel = Dali::Pixel::GetBytesPerPixel( srcPixelFormat );
+  int srcStride = mask.GetWidth() * srcBytesPerPixel;
+  unsigned char* srcBuffer = mask.GetBuffer();
+  unsigned char* destBuffer = buffer.GetBuffer();
+
+  unsigned int destBytesPerPixel = Dali::Pixel::GetBytesPerPixel( buffer.GetPixelFormat() );
+
+  int srcOffset=0;
+  int destOffset=0;
+
+  float srcAlphaValue = 1.0f;
+
+  for( unsigned int row = 0; row < buffer.GetHeight(); ++row )
+  {
+    for( unsigned int col = 0; col < buffer.GetWidth(); ++col )
+    {
+      if( numSamples == 1 )
+      {
+        srcOffset = floorf(row * rowFactor) * srcStride + floorf(col * colFactor) * srcBytesPerPixel;
+        unsigned char alpha = srcBuffer[srcOffset + srcAlphaByteOffset] & srcAlphaMask;
+        srcAlphaValue = float(alpha)/255.0f;
+      }
+      else
+      {
+        srcAlphaValue = ReadWeightedSample( srcBuffer, srcPixelFormat, srcStride, col*colFactor, row*rowFactor, mask.GetWidth(), mask.GetHeight(), alphaChannel );
+      }
+
+      unsigned char destAlpha = destBuffer[destOffset + destAlphaByteOffset] & destAlphaMask;
+      float destAlphaValue = Clamp(float(destAlpha) * srcAlphaValue, 0.0f, 255.0f);
+      destAlpha = destAlphaValue;
+      destBuffer[destOffset + destAlphaByteOffset] &= ~destAlphaMask;
+      destBuffer[destOffset + destAlphaByteOffset] |= ( destAlpha & destAlphaMask );
+
+      destOffset += destBytesPerPixel;
+    }
+  }
+}
+
+PixelBufferPtr CreateNewMaskedBuffer( const PixelBuffer& buffer, const PixelBuffer& mask )
+{
+  const float rowFactor = float(mask.GetHeight()) / (1.0f * buffer.GetHeight());
+  const float colFactor = float(mask.GetWidth()) / (1.0f * buffer.GetWidth()) ;
+
+  int numSamples = 1;
+  if( mask.GetHeight() > buffer.GetHeight() || mask.GetWidth() > buffer.GetWidth() )
+  {
+    numSamples = 4;
+  }
+
+  // Set up source alpha offsets
+  int srcAlphaByteOffset=0;
+  int srcAlphaMask=0;
+  Dali::Pixel::Format srcPixelFormat = mask.GetPixelFormat();
+  Channel alphaChannel = ALPHA;
+  if( Pixel::HasAlpha(srcPixelFormat) )
+  {
+    Dali::Pixel::GetAlphaOffsetAndMask( srcPixelFormat, srcAlphaByteOffset, srcAlphaMask );
+  }
+  else if( srcPixelFormat == Pixel::L8 )
+  {
+    srcAlphaMask=0xFF;
+    alphaChannel = LUMINANCE;
+  }
+
+  unsigned int srcBytesPerPixel = Dali::Pixel::GetBytesPerPixel( srcPixelFormat );
+  int srcStride = mask.GetWidth() * srcBytesPerPixel;
+  unsigned char* srcBuffer = mask.GetBuffer();
+
+  // Set up source color offsets
+  Dali::Pixel::Format srcColorPixelFormat = buffer.GetPixelFormat();
+  unsigned int srcColorBytesPerPixel = Dali::Pixel::GetBytesPerPixel( srcColorPixelFormat );
+
+  // Setup destination offsets
+  Dali::Pixel::Format destPixelFormat = Dali::Pixel::RGBA8888;
+  unsigned int destBytesPerPixel = Dali::Pixel::GetBytesPerPixel( destPixelFormat );
+  int destAlphaByteOffset=0;
+  int destAlphaMask=0;
+  Dali::Pixel::GetAlphaOffsetAndMask( destPixelFormat, destAlphaByteOffset, destAlphaMask );
+
+  PixelBufferPtr newPixelBuffer = PixelBuffer::New( buffer.GetWidth(), buffer.GetHeight(),
+                                                    destPixelFormat );
+  unsigned char* destBuffer = newPixelBuffer->GetBuffer();
+
+  unsigned char* oldBuffer = buffer.GetBuffer();
+
+  int srcAlphaOffset=0;
+  int srcColorOffset=0;
+  int destOffset=0;
+  bool hasAlpha = Dali::Pixel::HasAlpha(buffer.GetPixelFormat());
+
+  float srcAlphaValue = 1.0f;
+  unsigned char destAlpha = 0;
+
+  for( unsigned int row = 0; row < buffer.GetHeight(); ++row )
+  {
+    for( unsigned int col = 0; col < buffer.GetWidth(); ++col )
+    {
+      if( numSamples == 1 )
+      {
+        srcAlphaOffset = floorf(row * rowFactor) * srcStride + floorf(col * colFactor) * srcBytesPerPixel;
+        unsigned char alpha = srcBuffer[srcAlphaOffset + srcAlphaByteOffset] & srcAlphaMask;
+        srcAlphaValue = float(alpha)/255.0f;
+      }
+      else
+      {
+        srcAlphaValue = ReadWeightedSample( srcBuffer, srcPixelFormat, srcStride, col*colFactor, row*rowFactor, mask.GetWidth(), mask.GetHeight(), alphaChannel );
+      }
+
+      ConvertColorChannelsToRGBA8888(oldBuffer, srcColorOffset, srcColorPixelFormat, destBuffer, destOffset );
+
+      if( hasAlpha )
+      {
+        destAlpha = ConvertAlphaChannelToA8( oldBuffer, srcColorOffset, srcColorPixelFormat );
+        float destAlphaValue = Clamp(float(destAlpha) * srcAlphaValue, 0.0f, 255.0f);
+        destAlpha = destAlphaValue;
+      }
+      else
+      {
+        destAlpha = floorf(Clamp(srcAlphaValue * 255.0f, 0.0f, 255.0f));
+      }
+
+      destBuffer[destOffset + destAlphaByteOffset] &= ~destAlphaMask;
+      destBuffer[destOffset + destAlphaByteOffset] |= ( destAlpha & destAlphaMask );
+
+      srcColorOffset += srcColorBytesPerPixel;
+      destOffset += destBytesPerPixel;
+    }
+  }
+
+  return newPixelBuffer;
+}
+
+
+float ReadWeightedSample( unsigned char* buffer, Pixel::Format pixelFormat, int stride, float x, float y, int width, int height, Channel alphaChannel )
+{
+  int srcRow = floorf( y );
+  int srcCol = floorf( x );
+
+  int bytesPerPixel = Dali::Pixel::GetBytesPerPixel( pixelFormat );
+  int srcOffset = srcRow * stride + srcCol * bytesPerPixel;
+  float samples[4];
+
+  samples[0] = ReadChannel( buffer + srcOffset, pixelFormat, alphaChannel );
+
+  if( srcCol < width-1 )
+  {
+    samples[1] = ReadChannel( buffer + srcOffset+bytesPerPixel, pixelFormat, alphaChannel );
+  }
+  else
+  {
+    samples[1] = samples[0];
+  }
+
+  if( srcRow < height-1 )
+  {
+    samples[2] = ReadChannel( buffer + stride + srcOffset, pixelFormat, alphaChannel );
+  }
+  else
+  {
+    samples[2] = samples[0];
+  }
+
+  if( srcRow < height-1 && srcCol < width-1 )
+  {
+    samples[3] = ReadChannel( buffer + stride + srcOffset + bytesPerPixel, pixelFormat, alphaChannel );
+  }
+  else
+  {
+    samples[3] = samples[2];
+  }
+
+  // Bilinear interpolation:
+  float weight[4];
+  weight[0] = float(srcRow+1.0f) - y;
+  weight[1] = y - float(srcRow);
+  weight[2] = float(srcCol+1.0f) - x;
+  weight[3] = x - float(srcCol);
+
+  return ( weight[2] * (samples[0] * weight[0] + samples[1] * weight[1]) +
+           weight[3] * (samples[2] * weight[0] + samples[3] * weight[1]) ) / 255.0f;
+}
+
+} //namespace Adaptor
+
+}// namespace Internal
+
+}// namespace Dali
diff --git a/platform-abstractions/portable/alpha-mask.h b/platform-abstractions/portable/alpha-mask.h
new file mode 100644 (file)
index 0000000..192b9f5
--- /dev/null
@@ -0,0 +1,66 @@
+#ifndef DALI_INTERNAL_ADAPTOR_ALPHA_MASK_H
+#define DALI_INTERNAL_ADAPTOR_ALPHA_MASK_H
+
+/*
+ * Copyright (c) 2017 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#include "pixel-buffer-impl.h"
+
+namespace Dali
+{
+namespace Internal
+{
+namespace Adaptor
+{
+
+
+/**
+ * Apply the mask to a buffer's alpha channel
+ * @param[in] buffer The buffer to apply the mask to
+ * @param[in] mask The mask to apply
+ */
+void ApplyMaskToAlphaChannel( PixelBuffer& buffer, const PixelBuffer& mask );
+
+/**
+ * Create a new PixelBuffer with an alpha channel large enough to handle the alpha from
+ * the mask, converting the color values to the new size, and either multiplying the mask's
+ * alpha into the existing alpha value, or writing the mask's alpha value directly into
+ * the new buffer's alpha channel.
+ *
+ * @param[in] buffer The buffer to apply the mask to
+ * @param[in] mask The mask to apply
+ * @return A new pixel buffer containing the masked image
+ */
+PixelBufferPtr CreateNewMaskedBuffer( const PixelBuffer& buffer, const PixelBuffer& mask );
+
+/**
+ * Read a weighted sample from the given channel for a given coordinate
+ * @param[in] buffer The buffer to read from
+ * @param[in] pixelFormat The pixel format of the buffer
+ * @param[in] stride The stride across the buffer
+ * @param[in] x The x coordinate to sample from
+ * @param[in] y The y coordinate to sample from
+ * @param[in] width The width of the buffer in pixels
+ * @param[in] height  The height of the buffer in pixels
+ * @param[in] channel The channel to read from
+ * @return An averaged value from the 4 pixels around the given coordinate
+ */
+float ReadWeightedSample( unsigned char* buffer, Pixel::Format pixelFormat, int stride, float x, float y, int width, int height, Channel channel );
+
+} //namespace Adaptor
+} //namespace Internal
+} //namespace Dali
+
+#endif // DALI_INTERNAL_ADAPTOR_ALPHA_MASK_H
index c301fcc..81936fa 100644 (file)
@@ -26,6 +26,7 @@
 #include <dali/public-api/common/dali-vector.h>
 #include <dali/public-api/math/vector2.h>
 #include <resampler.h>
+#include <image-loading.h>
 
 // INTERNAL INCLUDES
 
@@ -49,7 +50,7 @@ const unsigned int MAXIMUM_TARGET_BITMAP_SIZE( ( 1u << 16 ) - 1 );
 // Constants used by the ImageResampler.
 const float DEFAULT_SOURCE_GAMMA = 1.75f;   ///< Default source gamma value used in the Resampler() function. Partial gamma correction looks better on mips. Set to 1.0 to disable gamma correction.
 const float FILTER_SCALE = 1.f;             ///< Default filter scale value used in the Resampler() function. Filter scale - values < 1.0 cause aliasing, but create sharper looking mips.
-const char* const FILTER_TYPE = "lanczos4"; ///< Default filter used in the Resampler() function. Possible Lanczos filters are: lanczos3, lanczos4, lanczos6, lanczos12
+const Resampler::Filter FILTER_TYPE = Resampler::LANCZOS4; ///< Default filter used in the Resampler() function. Possible Lanczos filters are: lanczos3, lanczos4, lanczos6, lanczos12
 
 using Integration::Bitmap;
 using Integration::BitmapPtr;
@@ -449,24 +450,29 @@ BitmapPtr MakeBitmap( const uint8_t * const pixels, Pixel::Format pixelFormat, u
  */
 ImageDimensions CalculateDesiredDimensions( unsigned int bitmapWidth, unsigned int bitmapHeight, unsigned int requestedWidth, unsigned int requestedHeight )
 {
+  unsigned int maxSize = Dali::GetMaxTextureSize();
+
   // If no dimensions have been requested, default to the source ones:
   if( requestedWidth == 0 && requestedHeight == 0 )
   {
-    return ImageDimensions( bitmapWidth, bitmapHeight );
+    return ImageDimensions( std::min( bitmapWidth, maxSize ), std::min( bitmapHeight, maxSize ) );
   }
 
   // If both dimensions have values requested, use them both:
   if( requestedWidth != 0 && requestedHeight != 0 )
   {
-    return ImageDimensions( requestedWidth, requestedHeight );
+    return ImageDimensions( std::min( requestedWidth, maxSize ), std::min( requestedHeight, maxSize ) );
   }
 
   // Only one of the dimensions has been requested. Calculate the other from
   // the requested one and the source image aspect ratio:
   if( requestedWidth != 0 )
   {
+    requestedWidth = std::min( requestedWidth, maxSize );
     return ImageDimensions( requestedWidth, bitmapHeight / float(bitmapWidth) * requestedWidth + 0.5f );
   }
+
+  requestedHeight = std::min( requestedHeight, maxSize );
   return ImageDimensions( bitmapWidth / float(bitmapHeight) * requestedHeight + 0.5f, requestedHeight );
 }
 
diff --git a/platform-abstractions/portable/pixel-manipulation.cpp b/platform-abstractions/portable/pixel-manipulation.cpp
new file mode 100644 (file)
index 0000000..ef2defc
--- /dev/null
@@ -0,0 +1,714 @@
+/*
+ * Copyright (c) 2017 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// CLASS HEADER
+#include "pixel-manipulation.h"
+
+// INTERNAL HEADERS
+#include <dali/public-api/images/pixel.h>
+#include <dali/integration-api/debug.h>
+
+namespace Dali
+{
+namespace Internal
+{
+namespace Adaptor
+{
+
+struct Location
+{
+  unsigned int bitShift;
+  unsigned int bitMask;
+  bool available;
+};
+
+struct Locations
+{
+  Location luminance;
+  Location alpha;
+  Location red;
+  Location green;
+  Location blue;
+};
+
+
+bool HasChannel( Dali::Pixel::Format pixelFormat, Channel channel )
+{
+  switch (pixelFormat)
+  {
+    case Dali::Pixel::A8:
+    {
+      return (channel == ALPHA);
+    }
+    case Dali::Pixel::L8:
+    {
+      return (channel == LUMINANCE);
+    }
+    case Dali::Pixel::LA88:
+    {
+      return ( channel == LUMINANCE || channel == ALPHA );
+    }
+    case Dali::Pixel::RGB565:
+    case Dali::Pixel::BGR565:
+    case Dali::Pixel::RGB888:
+    case Dali::Pixel::RGB8888:
+    case Dali::Pixel::BGR8888:
+    {
+      return ( channel == RED || channel == GREEN || channel == BLUE );
+    }
+
+    case Dali::Pixel::RGBA8888:
+    case Dali::Pixel::BGRA8888:
+    case Dali::Pixel::RGBA4444:
+    case Dali::Pixel::BGRA4444:
+    case Dali::Pixel::RGBA5551:
+    case Dali::Pixel::BGRA5551:
+    {
+      return ( channel == RED || channel == GREEN || channel == BLUE || channel == ALPHA );
+    }
+
+    case Dali::Pixel::INVALID:
+    case Dali::Pixel::COMPRESSED_R11_EAC:
+    case Dali::Pixel::COMPRESSED_SIGNED_R11_EAC:
+    case Dali::Pixel::COMPRESSED_RG11_EAC:
+    case Dali::Pixel::COMPRESSED_SIGNED_RG11_EAC:
+    case Dali::Pixel::COMPRESSED_RGB8_ETC2:
+    case Dali::Pixel::COMPRESSED_SRGB8_ETC2:
+    case Dali::Pixel::COMPRESSED_RGB8_ETC1:
+    case Dali::Pixel::COMPRESSED_RGB_PVRTC_4BPPV1:
+    case Dali::Pixel::COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2:
+    case Dali::Pixel::COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2:
+    case Dali::Pixel::COMPRESSED_RGBA8_ETC2_EAC:
+    case Dali::Pixel::COMPRESSED_SRGB8_ALPHA8_ETC2_EAC:
+    case Dali::Pixel::COMPRESSED_RGBA_ASTC_4x4_KHR:
+    case Dali::Pixel::COMPRESSED_RGBA_ASTC_5x4_KHR:
+    case Dali::Pixel::COMPRESSED_RGBA_ASTC_5x5_KHR:
+    case Dali::Pixel::COMPRESSED_RGBA_ASTC_6x5_KHR:
+    case Dali::Pixel::COMPRESSED_RGBA_ASTC_6x6_KHR:
+    case Dali::Pixel::COMPRESSED_RGBA_ASTC_8x5_KHR:
+    case Dali::Pixel::COMPRESSED_RGBA_ASTC_8x6_KHR:
+    case Dali::Pixel::COMPRESSED_RGBA_ASTC_8x8_KHR:
+    case Dali::Pixel::COMPRESSED_RGBA_ASTC_10x5_KHR:
+    case Dali::Pixel::COMPRESSED_RGBA_ASTC_10x6_KHR:
+    case Dali::Pixel::COMPRESSED_RGBA_ASTC_10x8_KHR:
+    case Dali::Pixel::COMPRESSED_RGBA_ASTC_10x10_KHR:
+    case Dali::Pixel::COMPRESSED_RGBA_ASTC_12x10_KHR:
+    case Dali::Pixel::COMPRESSED_RGBA_ASTC_12x12_KHR:
+    case Dali::Pixel::COMPRESSED_SRGB8_ALPHA8_ASTC_4x4_KHR:
+    case Dali::Pixel::COMPRESSED_SRGB8_ALPHA8_ASTC_5x4_KHR:
+    case Dali::Pixel::COMPRESSED_SRGB8_ALPHA8_ASTC_5x5_KHR:
+    case Dali::Pixel::COMPRESSED_SRGB8_ALPHA8_ASTC_6x5_KHR:
+    case Dali::Pixel::COMPRESSED_SRGB8_ALPHA8_ASTC_6x6_KHR:
+    case Dali::Pixel::COMPRESSED_SRGB8_ALPHA8_ASTC_8x5_KHR:
+    case Dali::Pixel::COMPRESSED_SRGB8_ALPHA8_ASTC_8x6_KHR:
+    case Dali::Pixel::COMPRESSED_SRGB8_ALPHA8_ASTC_8x8_KHR:
+    case Dali::Pixel::COMPRESSED_SRGB8_ALPHA8_ASTC_10x5_KHR:
+    case Dali::Pixel::COMPRESSED_SRGB8_ALPHA8_ASTC_10x6_KHR:
+    case Dali::Pixel::COMPRESSED_SRGB8_ALPHA8_ASTC_10x8_KHR:
+    case Dali::Pixel::COMPRESSED_SRGB8_ALPHA8_ASTC_10x10_KHR:
+    case Dali::Pixel::COMPRESSED_SRGB8_ALPHA8_ASTC_12x10_KHR:
+    case Dali::Pixel::COMPRESSED_SRGB8_ALPHA8_ASTC_12x12_KHR:
+    {
+      DALI_LOG_ERROR("Pixel formats for compressed images are not compatible with simple channels.\n");
+      break;
+    }
+  }
+
+  return false;
+}
+
+unsigned int ReadChannel( unsigned char* pixelData,
+                          Dali::Pixel::Format pixelFormat,
+                          Channel channel )
+{
+  switch (pixelFormat)
+  {
+    case Dali::Pixel::A8:
+    {
+      if( channel == ALPHA )
+      {
+        return static_cast<unsigned int>(*pixelData);
+      }
+      else return 0u;
+    }
+    case Dali::Pixel::L8:
+    {
+      if( channel == LUMINANCE )
+      {
+        return static_cast<unsigned int>(*pixelData);
+      }
+      else return 0u;
+    }
+    case Dali::Pixel::LA88:
+    {
+      if( channel == LUMINANCE )
+      {
+        return static_cast<unsigned int>(*pixelData);
+      }
+      else if( channel == ALPHA )
+      {
+        return static_cast<unsigned int>(*(pixelData+1));
+      }
+      else return 0u;
+    }
+    case Dali::Pixel::RGB565:
+    {
+      if( channel == RED )
+      {
+        return (static_cast<unsigned int>(*pixelData) & 0xF8) >> 3;
+      }
+      else if( channel == GREEN )
+      {
+        return ((static_cast<unsigned int>(*pixelData) & 0x07) << 3) |
+          ((static_cast<unsigned int>(*(pixelData+1)) & 0xE0) >> 5);
+      }
+      else if( channel == BLUE )
+      {
+        return static_cast<unsigned int>(*(pixelData+1)) & 0x1F;
+      }
+      else return 0u;
+    }
+
+    case Dali::Pixel::BGR565:
+    {
+      if( channel == BLUE )
+      {
+        return (static_cast<unsigned int>(*pixelData) & 0xF8) >> 3;
+      }
+      else if( channel == GREEN )
+      {
+        return ((static_cast<unsigned int>(*pixelData) & 0x07) << 3) |
+          ((static_cast<unsigned int>(*(pixelData+1)) & 0xE0) >> 5);
+      }
+      else if( channel == RED )
+      {
+        return (static_cast<unsigned int>(*(pixelData+1) & 0x1F) );
+      }
+      else return 0u;
+    }
+
+    case Dali::Pixel::RGB888:
+    case Dali::Pixel::RGB8888:
+    {
+      if( channel == RED )
+      {
+        return static_cast<unsigned int>(*pixelData);
+      }
+      else if( channel == GREEN )
+      {
+        return static_cast<unsigned int>(*(pixelData+1));
+      }
+      else if( channel == BLUE )
+      {
+        return static_cast<unsigned int>(*(pixelData+2));
+      }
+      else return 0u;
+    }
+
+    case Dali::Pixel::BGR8888:
+    {
+      if( channel == BLUE )
+      {
+        return static_cast<unsigned int>(*pixelData);
+      }
+      else if( channel == GREEN )
+      {
+        return static_cast<unsigned int>(*(pixelData+1));
+      }
+      else if( channel == RED )
+      {
+        return static_cast<unsigned int>(*(pixelData+2));
+      }
+      else return 0u;
+    }
+
+    case Dali::Pixel::RGBA8888:
+    {
+      if( channel == RED )
+      {
+        return static_cast<unsigned int>(*pixelData);
+      }
+      else if( channel == GREEN )
+      {
+        return static_cast<unsigned int>(*(pixelData+1));
+      }
+      else if( channel == BLUE )
+      {
+        return static_cast<unsigned int>(*(pixelData+2));
+      }
+      else if( channel == ALPHA )
+      {
+        return static_cast<unsigned int>(*(pixelData+3));
+      }
+      else return 0u;
+    }
+
+    case Dali::Pixel::BGRA8888:
+    {
+      if( channel == BLUE )
+      {
+        return static_cast<unsigned int>(*pixelData);
+      }
+      else if( channel == GREEN )
+      {
+        return static_cast<unsigned int>(*(pixelData+1));
+      }
+      else if( channel == RED )
+      {
+        return static_cast<unsigned int>(*(pixelData+2));
+      }
+      else if( channel == ALPHA )
+      {
+        return static_cast<unsigned int>(*(pixelData+3));
+      }
+      else return 0u;
+    }
+
+    case Dali::Pixel::RGBA4444:
+    {
+      if( channel == RED )
+      {
+        return (static_cast<unsigned int>(*pixelData) & 0xF0) >> 4;
+      }
+      else if( channel == GREEN )
+      {
+        return (static_cast<unsigned int>(*pixelData) & 0x0F);
+      }
+      else if( channel == BLUE )
+      {
+        return (static_cast<unsigned int>(*(pixelData+1)) & 0xF0) >> 4;
+      }
+      else if( channel == ALPHA )
+      {
+        return (static_cast<unsigned int>(*(pixelData+1)) & 0x0F);
+      }
+      else return 0u;
+    }
+
+    case Dali::Pixel::BGRA4444:
+    {
+      if( channel == BLUE )
+      {
+        return (static_cast<unsigned int>(*pixelData) & 0xF0) >> 4;
+      }
+      else if( channel == GREEN )
+      {
+        return (static_cast<unsigned int>(*pixelData) & 0x0F);
+      }
+      else if( channel == RED )
+      {
+        return (static_cast<unsigned int>(*(pixelData+1)) & 0xF0) >> 4;
+      }
+      else if( channel == ALPHA )
+      {
+        return (static_cast<unsigned int>(*(pixelData+1)) & 0x0F);
+      }
+      else return 0u;
+    }
+
+    case Dali::Pixel::RGBA5551:
+    {
+      if( channel == RED )
+      {
+        return (static_cast<unsigned int>(*pixelData) & 0xF8) >> 3;
+      }
+      else if( channel == GREEN )
+      {
+        return ((static_cast<unsigned int>(*pixelData) & 0x07) << 2) |
+          ((static_cast<unsigned int>(*(pixelData+1)) & 0xC0) >> 6);
+      }
+      else if( channel == BLUE )
+      {
+        return (static_cast<unsigned int>(*(pixelData+1)) & 0x3E) >> 1;
+      }
+      else if( channel == ALPHA )
+      {
+        return static_cast<unsigned int>(*(pixelData+1)) & 0x01;
+      }
+
+      else return 0u;
+    }
+
+    case Dali::Pixel::BGRA5551:
+    {
+      if( channel == BLUE )
+      {
+        return (static_cast<unsigned int>(*pixelData) & 0xF8) >> 3;
+      }
+      else if( channel == GREEN )
+      {
+        return ((static_cast<unsigned int>(*pixelData) & 0x07) << 2) |
+          ((static_cast<unsigned int>(*(pixelData+1)) & 0xC0) >> 6);
+      }
+      else if( channel == RED )
+      {
+        return ( static_cast<unsigned int>(*(pixelData+1)) & 0x3E) >> 1;
+      }
+      else if( channel == ALPHA )
+      {
+        return static_cast<unsigned int>(*(pixelData+1)) & 0x01;
+      }
+
+      else return 0u;
+    }
+
+    default:
+    {
+      return 0u;
+    }
+  }
+}
+
+void WriteChannel( unsigned char* pixelData,
+                   Dali::Pixel::Format pixelFormat,
+                   Channel channel,
+                   unsigned int channelValue )
+{
+  switch (pixelFormat)
+  {
+    case Dali::Pixel::A8:
+    {
+      if( channel == ALPHA )
+      {
+        *pixelData = static_cast<unsigned char>( channelValue & 0xFF );
+      }
+      break;
+    }
+    case Dali::Pixel::L8:
+    {
+      if( channel == LUMINANCE )
+      {
+        *pixelData = static_cast<unsigned char>( channelValue & 0xFF );
+      }
+      break;
+    }
+    case Dali::Pixel::LA88:
+    {
+      if( channel == LUMINANCE )
+      {
+        *pixelData = static_cast<unsigned char>( channelValue & 0xFF );
+      }
+      else if( channel == ALPHA )
+      {
+        *(pixelData+1) = static_cast<unsigned char>( channelValue & 0xFF );
+      }
+      break;
+    }
+    case Dali::Pixel::RGB565:
+    {
+      if( channel == RED )
+      {
+        *pixelData &= ~0xF8;
+        *pixelData |= static_cast<unsigned char>( (channelValue << 3) & 0xF8 );
+      }
+      else if( channel == GREEN )
+      {
+        *pixelData &= ~0x07;
+        *pixelData |= static_cast<unsigned char>( (channelValue >> 3) & 0x07 );
+
+        *(pixelData+1) &= ~0xE0;
+        *(pixelData+1) |= static_cast<unsigned char>( (channelValue << 5) & 0xE0 );
+      }
+      else if( channel == BLUE )
+      {
+        *(pixelData+1) &= ~0x1F;
+        *(pixelData+1) |= static_cast<unsigned char>( channelValue & 0x1F );
+      }
+      break;
+    }
+
+    case Dali::Pixel::BGR565:
+    {
+      if( channel == BLUE )
+      {
+        *pixelData &= ~0xF8;
+        *pixelData |= static_cast<unsigned char>( (channelValue << 3) & 0xF8 );
+      }
+      else if( channel == GREEN )
+      {
+        *pixelData &= ~0x07;
+        *pixelData |= static_cast<unsigned char>( (channelValue >> 3) & 0x07 );
+
+        *(pixelData+1) &= ~0xE0;
+        *(pixelData+1) |= static_cast<unsigned char>( (channelValue << 5) & 0xE0 );
+      }
+      else if( channel == RED )
+      {
+        *(pixelData+1) &= ~0x1F;
+        *(pixelData+1) |= static_cast<unsigned char>( channelValue & 0x1F );
+      }
+      break;
+    }
+
+    case Dali::Pixel::RGB888:
+    case Dali::Pixel::RGB8888:
+    {
+      if( channel == RED )
+      {
+        *pixelData = static_cast<unsigned char>( channelValue & 0xFF );
+      }
+      else if( channel == GREEN )
+      {
+        *(pixelData+1) = static_cast<unsigned char>( channelValue & 0xFF );
+      }
+      else if( channel == BLUE )
+      {
+        *(pixelData+2) = static_cast<unsigned char>( channelValue & 0xFF );
+      }
+      break;
+    }
+
+    case Dali::Pixel::BGR8888:
+    {
+      if( channel == BLUE )
+      {
+        *pixelData = static_cast<unsigned char>( channelValue & 0xFF );
+      }
+      else if( channel == GREEN )
+      {
+        *(pixelData+1) = static_cast<unsigned char>( channelValue & 0xFF );
+      }
+      else if( channel == RED )
+      {
+        *(pixelData+2) = static_cast<unsigned char>( channelValue & 0xFF );
+      }
+      break;
+    }
+
+    case Dali::Pixel::RGBA8888:
+    {
+      if( channel == RED )
+      {
+        *pixelData = static_cast<unsigned char>( channelValue & 0xFF );
+      }
+      else if( channel == GREEN )
+      {
+        *(pixelData+1) = static_cast<unsigned char>( channelValue & 0xFF );
+      }
+      else if( channel == BLUE )
+      {
+        *(pixelData+2) = static_cast<unsigned char>( channelValue & 0xFF );
+      }
+      else if( channel == ALPHA )
+      {
+        *(pixelData+3) = static_cast<unsigned char>( channelValue & 0xFF );
+      }
+      break;
+    }
+
+    case Dali::Pixel::BGRA8888:
+    {
+      if( channel == BLUE )
+      {
+        *pixelData = static_cast<unsigned char>( channelValue & 0xFF );
+      }
+      else if( channel == GREEN )
+      {
+        *(pixelData+1) = static_cast<unsigned char>( channelValue & 0xFF );
+      }
+      else if( channel == RED )
+      {
+        *(pixelData+2) = static_cast<unsigned char>( channelValue & 0xFF );
+      }
+      else if( channel == ALPHA )
+      {
+        *(pixelData+3) = static_cast<unsigned char>( channelValue & 0xFF );
+      }
+      break;
+    }
+
+    case Dali::Pixel::RGBA4444:
+    {
+      if( channel == RED )
+      {
+        *pixelData &= ~0xF0;
+        *pixelData |= static_cast<unsigned char>( (channelValue << 4) & 0xF0 );
+      }
+      else if( channel == GREEN )
+      {
+        *pixelData &= ~0x0F;
+        *pixelData |= static_cast<unsigned char>( channelValue & 0x0F );
+      }
+      else if( channel == BLUE )
+      {
+        *(pixelData+1) &= ~0xF0;
+        *(pixelData+1) |= static_cast<unsigned char>( (channelValue << 4) & 0xF0 );
+      }
+      else if( channel == ALPHA )
+      {
+        *(pixelData+1) &= ~0x0F;
+        *(pixelData+1) |= static_cast<unsigned char>( channelValue & 0x0F );
+      }
+      break;
+    }
+
+    case Dali::Pixel::BGRA4444:
+    {
+      if( channel == BLUE )
+      {
+        *pixelData &= ~0xF0;
+        *pixelData |= static_cast<unsigned char>( (channelValue << 4) & 0xF0 );
+      }
+      else if( channel == GREEN )
+      {
+        *pixelData &= ~0x0F;
+        *pixelData |= static_cast<unsigned char>( channelValue & 0x0F );
+      }
+      else if( channel == RED )
+      {
+        *(pixelData+1) &= ~0xF0;
+        *(pixelData+1) |= static_cast<unsigned char>( (channelValue << 4) & 0xF0 );
+      }
+      else if( channel == ALPHA )
+      {
+        *(pixelData+1) &= ~0x0F;
+        *(pixelData+1) |= static_cast<unsigned char>( channelValue & 0x0F );
+      }
+      break;
+    }
+
+    case Dali::Pixel::RGBA5551:
+    {
+      // rrrrrggg ggbbbbba
+      //    F8  7 C0  3E 1
+      if( channel == RED )
+      {
+        *pixelData &= ~0xF8;
+        *pixelData |= static_cast<unsigned char>( (channelValue << 3) & 0xF8 );
+      }
+      else if( channel == GREEN )
+      {
+        *pixelData &= ~0x07;
+        *pixelData |= static_cast<unsigned char>( (channelValue >> 2) & 0x07 );
+
+        *(pixelData+1) &= ~0xC0;
+        *(pixelData+1) |= static_cast<unsigned char>( (channelValue << 6) & 0xC0 );
+      }
+      else if( channel == BLUE )
+      {
+        *(pixelData+1) &= ~0x3E;
+        *(pixelData+1) |= static_cast<unsigned char>( (channelValue << 1) & 0x3E );
+      }
+      else if( channel == ALPHA )
+      {
+        *(pixelData+1) &= ~0x01;
+        *(pixelData+1) |= static_cast<unsigned char>( channelValue & 0x01 );
+      }
+      break;
+    }
+
+    case Dali::Pixel::BGRA5551:
+    {
+      if( channel == BLUE )
+      {
+        *pixelData &= ~0xF8;
+        *pixelData |= static_cast<unsigned char>( (channelValue << 3) & 0xF8 );
+      }
+      else if( channel == GREEN )
+      {
+        *pixelData &= ~0x07;
+        *pixelData |= static_cast<unsigned char>( (channelValue >> 2) & 0x07 );
+
+        *(pixelData+1) &= ~0xC0;
+        *(pixelData+1) |= static_cast<unsigned char>( (channelValue << 6) & 0xC0 );
+      }
+      else if( channel == RED )
+      {
+        *(pixelData+1) &= ~0x3E;
+        *(pixelData+1) |= static_cast<unsigned char>( (channelValue << 1 ) & 0x3E );
+      }
+      else if( channel == ALPHA )
+      {
+        *(pixelData+1) &= ~0x01;
+        *(pixelData+1) |= static_cast<unsigned char>( channelValue & 0x01 );
+      }
+      break;
+    }
+
+    default:
+      break;
+  }
+}
+
+void ConvertColorChannelsToRGBA8888(
+  unsigned char* srcPixel,  int srcOffset,  Dali::Pixel::Format srcFormat,
+  unsigned char* destPixel, int destOffset )
+{
+  int red   = ReadChannel(srcPixel+srcOffset, srcFormat, RED );
+  int green = ReadChannel(srcPixel+srcOffset, srcFormat, GREEN );
+  int blue  = ReadChannel(srcPixel+srcOffset, srcFormat, BLUE );
+  switch( srcFormat )
+  {
+    case Dali::Pixel::RGB565:
+    case Dali::Pixel::BGR565:
+    {
+      red = (red<<3) | (red & 0x07);
+      green = (green << 2) | (green & 0x03);
+      blue = (blue<<3) | (blue & 0x07);
+      break;
+    }
+    case Dali::Pixel::RGBA4444:
+    case Dali::Pixel::BGRA4444:
+    {
+      red = (red<<4) | (red&0x0F);
+      green = (green<<4) | (green&0x0F);
+      blue = (blue<<4) | (blue&0x0F);
+      break;
+    }
+    case Dali::Pixel::RGBA5551:
+    case Dali::Pixel::BGRA5551:
+    {
+      red = (red<<3) | (red&0x07);
+      green = (green<<3) | (green&0x07);
+      blue = (blue<<3) | (blue&0x07);
+      break;
+    }
+    default:
+      break;
+  }
+  WriteChannel(destPixel+destOffset, Dali::Pixel::RGBA8888, RED, red);
+  WriteChannel(destPixel+destOffset, Dali::Pixel::RGBA8888, GREEN, green);
+  WriteChannel(destPixel+destOffset, Dali::Pixel::RGBA8888, BLUE, blue);
+}
+
+
+int ConvertAlphaChannelToA8( unsigned char* srcPixel, int srcOffset, Dali::Pixel::Format srcFormat )
+{
+  int alpha = ReadChannel(srcPixel+srcOffset, srcFormat, ALPHA );
+  int destAlpha = alpha;
+  switch( srcFormat )
+  {
+    case Pixel::RGBA5551:
+    case Pixel::BGRA5551:
+    {
+      destAlpha = (alpha==0)?0:255;
+      break;
+    }
+    case Pixel::RGBA4444:
+    case Pixel::BGRA4444:
+    {
+      destAlpha = (alpha<<4) | (alpha&0x0F);
+      break;
+    }
+    default:
+      break;
+  }
+  return destAlpha;
+}
+
+} // Adaptor
+} // Internal
+} // Dali
diff --git a/platform-abstractions/portable/pixel-manipulation.h b/platform-abstractions/portable/pixel-manipulation.h
new file mode 100644 (file)
index 0000000..611b5a6
--- /dev/null
@@ -0,0 +1,101 @@
+#ifndef DALI_INTERNAL_ADAPTOR_PIXEL_MANIPULATION_H
+#define DALI_INTERNAL_ADAPTOR_PIXEL_MANIPULATION_H
+
+/*
+ * Copyright (c) 2017 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <dali/public-api/images/pixel.h>
+
+namespace Dali
+{
+
+namespace Internal
+{
+
+namespace Adaptor
+{
+
+enum Channel
+{
+  LUMINANCE,
+  RED,
+  GREEN,
+  BLUE,
+  ALPHA,
+  MAX_NUMBER_OF_CHANNELS
+};
+
+/**
+ * Return true if the channel exists in the pixel format
+ * @param[in] pixelFormat The pixelFormat
+ * @param[in] channel The channel to test for
+ * @return true if the channel exists
+ */
+bool HasChannel( Dali::Pixel::Format pixelFormat, Channel channel );
+
+
+/**
+ * Read a colour channel from the pixel with the given pixel format.
+ * Returns zero if the format does not support the channel
+ * @param[in] pixelData Location of the pixel
+ * @param[in] pixelFormat The format of the pixel
+ * @param[in] channel The channel to read
+ * @return the channel value
+ */
+unsigned int ReadChannel( unsigned char* pixelData,
+                          Dali::Pixel::Format pixelFormat,
+                          Channel channel );
+
+/**
+ * Write a colour channel to the pixel with the given pixel format.
+ * @param[in] pixelData Location of the pixel
+ * @param[in] pixelFormat The format of the pixel
+ * @param[in] channel The channel to write
+ * @param[in] channelValue the value to write to the channel
+ */
+void WriteChannel( unsigned char* pixelData,
+                   Dali::Pixel::Format pixelFormat,
+                   Channel channel,
+                   unsigned int channelValue );
+
+/**
+ * Convert the colors in the source pixel from their natural format to RGBA8888.
+ * @param[in] srcBuffer The source buffer to read from
+ * @param[in] srcOffset The offset of the pixel to convert
+ * @param[in] srcFormat The pixel format of the source pixel
+ * @param[in] destBuffer The destination buffer to write to
+ * @param[in] destOffset The offset of the pixel to write
+ */
+void ConvertColorChannelsToRGBA8888(
+  unsigned char* srcBuffer,  int srcOffset,  Dali::Pixel::Format srcFormat,
+  unsigned char* destBuffer, int destOffset );
+
+/**
+ * Convert the alpha in the source pixel to A8.
+ * @param[in] srcBuffer The source buffer to read from
+ * @param[in] srcOffset The offset of the pixel to convert
+ * @param[in] srcFormat The pixel format of the source pixel
+ * @return the alpha value in the range 0-255
+ */
+int ConvertAlphaChannelToA8( unsigned char* srcPixel, int srcOffset, Dali::Pixel::Format srcFormat );
+
+
+} // Adaptor
+} // Internal
+} // Dali
+
+
+#endif // DALI_INTERNAL_ADAPTOR_PIXEL_MANIPULATION_H
index be5f212..bb4e908 100755 (executable)
@@ -16,7 +16,10 @@ tizen_platform_abstraction_src_files = \
   $(tizen_platform_abstraction_src_dir)/image-loaders/loader-png.cpp \
   $(tizen_platform_abstraction_src_dir)/image-loaders/loader-wbmp.cpp \
   $(tizen_platform_abstraction_src_dir)/image-loaders/image-loader.cpp \
-  $(portable_platform_abstraction_src_dir)/image-operations.cpp
+  \
+  $(portable_platform_abstraction_src_dir)/image-operations.cpp \
+  $(portable_platform_abstraction_src_dir)/pixel-manipulation.cpp \
+  $(portable_platform_abstraction_src_dir)/alpha-mask.cpp
 
 # Add public headers here:
 
index 14ae644..99fb1be 100644 (file)
@@ -47,86 +47,25 @@ namespace Plugin
 {
 
 DaliFeedback::DaliFeedback()
-: mHapticInitialized( false )
 {
   feedback_initialize();
-
-  if( 0 == haptic_open( HAPTIC_DEVICE_0, &mDeviceHandle ) )
-  {
-    mHapticInitialized = true;
-  }
-  else
-  {
-    DEBUG_PRINTF( "Haptic feedback controller failed to initialize\n" );
-  }
 }
 
 DaliFeedback::~DaliFeedback()
 {
-  if( mHapticInitialized )
-  {
-    int errorCode = haptic_close( mDeviceHandle );
-    if( errorCode < 0 )
-    {
-      DEBUG_PRINTF( "device_haptic_close() failed with error code: %d\n", errorCode );
-    }
-  }
-
   feedback_deinitialize();
 }
 
 void DaliFeedback::PlayHaptic( const std::string& filePath )
 {
-  if( mHapticInitialized )
-  {
-    if ( filePath.size() == 0 )
-    {
-      DEBUG_PRINTF( "File Path can't be NULL!\n" );
-      return;
-    }
-
-    int errorCode = haptic_vibrate_file_with_detail( mDeviceHandle, filePath.c_str(), HAPTIC_ITERATION_ONCE, HAPTIC_FEEDBACK_AUTO, HAPTIC_PRIORITY_MIN, NULL );
-    if( errorCode != 0 )
-    {
-      DEBUG_PRINTF( "PlayHaptic() failed with error code: %d\n", errorCode );
-    }
-  }
-  else
-  {
-    DEBUG_PRINTF( "HapticPlayer is not Initialized\n" );
-  }
 }
 
 void DaliFeedback::PlayHapticMonotone( unsigned int duration )
 {
-  if( mHapticInitialized )
-  {
-    int errorCode = haptic_vibrate_monotone_with_detail( mDeviceHandle, duration, HAPTIC_FEEDBACK_AUTO, HAPTIC_PRIORITY_MIN, NULL );
-    if( errorCode != 0 )
-    {
-      DEBUG_PRINTF( "PlayHapticMonotone() failed with error code: %d\n", errorCode );
-    }
-  }
-  else
-  {
-    DEBUG_PRINTF( "HapticPlayer is not Initialized\n" );
-  }
 }
 
 void DaliFeedback::StopHaptic()
 {
-  if( mHapticInitialized )
-  {
-    int errorCode = haptic_stop_all_effects( mDeviceHandle );
-    if( errorCode != 0 )
-    {
-      DEBUG_PRINTF( "StopHaptic() failed with error code: %d\n", errorCode );
-    }
-  }
-  else
-  {
-    DEBUG_PRINTF( "HapticPlayer is not Initialized\n" );
-  }
 }
 
 int DaliFeedback::PlaySound( const std::string& fileName )
index c9967ec..0c598e2 100644 (file)
  *
  */
 
-// EXTERNAL INCLUDES
-#if defined(DALI_PROFILE_MOBILE)
-#include <dd-haptic.h>
-#else
-#include <haptic.h>
-#endif
-
 // INTERNAL INCLUDES
 #include <feedback-plugin.h>
 
@@ -83,12 +76,6 @@ public: // FeedbackPlugin overrides
    * @copydoc Dali::FeedbackPlugin::PlayFeedbackPattern()
    */
   void PlayFeedbackPattern( int type, int pattern );
-
-private:
-
-  haptic_device_h mDeviceHandle;
-
-  bool mHapticInitialized;
 };
 
 }  // namespace Plugin
index d33e234..c54a558 100644 (file)
@@ -208,8 +208,8 @@ TizenVideoPlayer::TizenVideoPlayer()
   mPlayerState( PLAYER_STATE_NONE ),
   mTbmSurface( NULL ),
   mPacket( NULL ),
-  mBackgroundColor( Dali::Stage::DEFAULT_BACKGROUND_COLOR ),
-  mTargetType( NativeImage )
+  mTargetType( NativeImage ),
+  mAlphaBitChanged( false )
 {
 }
 
@@ -279,13 +279,10 @@ void TizenVideoPlayer::SetRenderingTarget( Any target )
   }
 
   mNativeImageSourcePtr = NULL;
+  mEcoreWlWindow = NULL;
 
   if( target.GetType() == typeid( Dali::NativeImageSourcePtr ) )
   {
-    if( mTargetType == TizenVideoPlayer::WindowSurface )
-    {
-      Stage::GetCurrent().SetBackgroundColor( mBackgroundColor );
-    }
     mTargetType = TizenVideoPlayer::NativeImage;
 
     Dali::NativeImageSourcePtr nativeImageSourcePtr = AnyCast< Dali::NativeImageSourcePtr >( target );
@@ -295,8 +292,6 @@ void TizenVideoPlayer::SetRenderingTarget( Any target )
   else if( target.GetType() == typeid( Ecore_Wl_Window* ) )
   {
     mTargetType = TizenVideoPlayer::WindowSurface;
-    mBackgroundColor = Stage::GetCurrent().GetBackgroundColor();
-    Stage::GetCurrent().SetBackgroundColor( Color::TRANSPARENT );
 
     Ecore_Wl_Window* nativeWindow = Dali::AnyCast< Ecore_Wl_Window* >( target );
     InitializeUnderlayMode( nativeWindow );
@@ -512,6 +507,12 @@ void TizenVideoPlayer::InitializeTextureStreamMode( Dali::NativeImageSourcePtr n
 
   mNativeImageSourcePtr = nativeImageSourcePtr;
 
+  if( mAlphaBitChanged )
+  {
+    ecore_wl_window_alpha_set( mEcoreWlWindow, false );
+    mAlphaBitChanged = false;
+  }
+
   if( mPlayerState == PLAYER_STATE_NONE )
   {
     error = player_create( &mPlayer );
@@ -555,6 +556,7 @@ void TizenVideoPlayer::InitializeUnderlayMode( Ecore_Wl_Window* ecoreWlWindow )
   }
 
   GetPlayerState( &mPlayerState );
+  mEcoreWlWindow = ecoreWlWindow;
 
   if( mPlayerState == PLAYER_STATE_IDLE )
   {
@@ -564,12 +566,20 @@ void TizenVideoPlayer::InitializeUnderlayMode( Ecore_Wl_Window* ecoreWlWindow )
     error = player_set_sound_type( mPlayer, SOUND_TYPE_MEDIA );
     LogPlayerError( error );
 
-    error = player_set_display_mode( mPlayer, PLAYER_DISPLAY_MODE_FULL_SCREEN );
+    error = player_set_display_mode( mPlayer, PLAYER_DISPLAY_MODE_DST_ROI );
     LogPlayerError( error );
 
+    error = player_set_display_roi_area( mPlayer, 0, 0, 1, 1 );
+
     int width, height;
+    mAlphaBitChanged = ( ecore_wl_window_alpha_get( mEcoreWlWindow ) )? false: true;
     ecore_wl_screen_size_get( &width, &height );
-    error = player_set_ecore_wl_display( mPlayer, PLAYER_DISPLAY_TYPE_OVERLAY, ecoreWlWindow, 0, 0, width, height );
+
+    if( mAlphaBitChanged )
+    {
+      ecore_wl_window_alpha_set( mEcoreWlWindow, true );
+    }
+    error = player_set_ecore_wl_display( mPlayer, PLAYER_DISPLAY_TYPE_OVERLAY, mEcoreWlWindow, 0, 0, width, height );
     LogPlayerError( error );
 
     error = player_set_display_visible( mPlayer, true );
@@ -646,5 +656,76 @@ void TizenVideoPlayer::PushPacket( media_packet_h packet )
   mPacketVector.PushBack( packet );
 }
 
+void TizenVideoPlayer::SetDisplayArea( DisplayArea area )
+{
+  GetPlayerState( &mPlayerState );
+
+  if( mNativeImageSourcePtr != NULL )
+  {
+    DALI_LOG_ERROR( "SetDisplayArea is only for window surface target.\n" );
+    return;
+  }
+
+  if( mPlayerState == PLAYER_STATE_IDLE ||
+      mPlayerState == PLAYER_STATE_READY ||
+      mPlayerState == PLAYER_STATE_PLAYING ||
+      mPlayerState == PLAYER_STATE_PAUSED
+
+  )
+  {
+    int error = player_set_display_roi_area( mPlayer, area.x, area.y, area.width, area.height );
+    LogPlayerError( error );
+  }
+}
+
+void TizenVideoPlayer::Forward( int millisecond )
+{
+  int error;
+
+  GetPlayerState( &mPlayerState );
+
+  if( mPlayerState == PLAYER_STATE_READY ||
+      mPlayerState == PLAYER_STATE_PLAYING ||
+      mPlayerState == PLAYER_STATE_PAUSED
+  )
+  {
+    int currentPosition = 0;
+    int nextPosition = 0;
+
+    error = player_get_play_position( mPlayer, &currentPosition );
+    LogPlayerError( error );
+
+    nextPosition = currentPosition + millisecond;
+
+    error = player_set_play_position( mPlayer, nextPosition, true, NULL, NULL );
+    LogPlayerError( error );
+  }
+}
+
+void TizenVideoPlayer::Backward( int millisecond )
+{
+  int error;
+
+  GetPlayerState( &mPlayerState );
+
+  if( mPlayerState == PLAYER_STATE_READY ||
+      mPlayerState == PLAYER_STATE_PLAYING ||
+      mPlayerState == PLAYER_STATE_PAUSED
+  )
+  {
+    int currentPosition = 0;
+    int nextPosition = 0;
+
+    error = player_get_play_position( mPlayer, &currentPosition );
+    LogPlayerError( error );
+
+    nextPosition = currentPosition - millisecond;
+    nextPosition = ( nextPosition < 0 )? 0 : nextPosition;
+
+    error = player_set_play_position( mPlayer, nextPosition, true, NULL, NULL );
+    LogPlayerError( error );
+  }
+}
+
 } // namespace Plugin
 } // namespace Dali;
index ac82edd..9f870cc 100644 (file)
@@ -140,6 +140,11 @@ public:
   virtual int GetPlayPosition();
 
   /**
+   * @copydoc Dali::VideoPlayerPlugin::SetDisplayArea()
+   */
+  virtual void SetDisplayArea( DisplayArea area );
+
+  /**
    * @copydoc Dali::VideoPlayerPlugin::SetDisplayRotation()
    */
   virtual void SetDisplayRotation( Dali::VideoPlayerPlugin::DisplayRotation rotation );
@@ -159,6 +164,16 @@ public:
    */
   void PushPacket( media_packet_h packet );
 
+  /**
+   * @brief Dali::VideoPlayer::Forward()
+   */
+  void Forward( int millisecond );
+
+  /**
+   * @brief Dali::VideoPlayer::Backward()
+   */
+  void Backward( int millisecond );
+
 private:
 
   /**
@@ -201,6 +216,10 @@ private:
   Dali::Mutex mPacketMutex;
   Dali::Vector< media_packet_h > mPacketVector; ///< Container for media packet handle from Tizen player callback
 
+  Ecore_Wl_Window* mEcoreWlWindow;
+
+  bool mAlphaBitChanged; ///< True if underlay rendering initialization changes window alpha
+
 public:
 
   Dali::VideoPlayerPlugin::VideoPlayerSignalType mFinishedSignal;
index bb73ca9..2314f2d 100644 (file)
@@ -244,6 +244,10 @@ Script GetCharacterScript( Character character )
   // Ol Chiki Script
   // 0x1c50 - 0x1c7f Ol Chiki
 
+  // Meitei Script
+  // 0xabc0 - 0xabff Meetei Mayek
+  // 0xaae0 - 0xaaff Meetei Mayek Extensions
+
   // The Emoji which map to standardized Unicode characters
   // 1. Emoticons ( 1F601 - 1F64F )
   // 2. Dingbats ( 2702 - 27B0 )
@@ -739,6 +743,14 @@ Script GetCharacterScript( Character character )
         {
           return LATIN;
         }
+        if( ( 0xaae0 <= character ) && ( character <= 0xaaff ) )
+        {
+          return MEITEI;
+        }
+        if( ( 0xabc0 <= character ) && ( character <= 0xabff ) )
+        {
+          return MEITEI;
+        }
         if( ( 0xac00 <= character ) && ( character <= 0xd7af ) )
         {
           return HANGUL;
index 9331381..93d1021 100644 (file)
@@ -94,6 +94,7 @@ enum Script
   GEEZ,          ///< The Ge'ez script. Used by the Amharic, Tigrinya and other languages in Ethiopia and Eritrea.
   OL_CHIKI,      ///< The Ol Chiki script. Used by the Santali.
   BAYBAYIN,      ///< The Baybayin script. Used by the Tagalog, Bikol languages, Ilocano, Pangasinan, Visayan and other languages in Philippines.
+  MEITEI,        ///< The Meitei script used for the Meitei language in Manipur, India.
 
   EMOJI,         ///< The Emoji which map to standardized Unicode characters.
 
@@ -166,6 +167,7 @@ const char* const ScriptName[] =
   "GEEZ",          ///< The Ge'ez script also known as Ethiopic. Used by the Amharic, Tigrinya and other languages in Ethiopia and Eritrea.
   "OL_CHIKI",      ///< The Ol Chiki script. Used by the Santali.
   "BAYBAYIN",      ///< The Baybayin script. Used by the Tagalog, Bikol languages, Ilocano, Pangasinan, Visayan and other languages in Philippines.
+  "MEITEI",        ///< The Meitei script used for the Meitei language in Manipur, India.
 
   "EMOJI",         ///< The Emoji which map to standardized Unicode characters.
 
index 270c406..3eb3488 100644 (file)
@@ -100,6 +100,7 @@ const hb_script_t SCRIPT_TO_HARFBUZZ[] =
   HB_SCRIPT_ETHIOPIC,
   HB_SCRIPT_OL_CHIKI,
   HB_SCRIPT_TAGALOG,
+  HB_SCRIPT_MEETEI_MAYEK,
 
   HB_SCRIPT_UNKNOWN, // EMOJI
   HB_SCRIPT_UNKNOWN, // SYMBOLS1
index 045549c..c602466 100644 (file)
@@ -362,27 +362,27 @@ static Resample_Real kaiser_filter(Resample_Real t)
 // filters[] is a list of all the available filter functions.
 static struct
 {
-   char name[32];
+   Resampler::Filter name;
    Resample_Real (*func)(Resample_Real t);
    Resample_Real support;
 } g_filters[] =
 {
-   { "box",              box_filter,              BOX_FILTER_SUPPORT },
-   { "tent",             tent_filter,             TENT_FILTER_SUPPORT },
-   { "bell",             bell_filter,             BELL_SUPPORT },
-   { "b-spline",         B_spline_filter,         B_SPLINE_SUPPORT },
-   { "mitchell",         mitchell_filter,         MITCHELL_SUPPORT },
-   { "lanczos3",         lanczos3_filter,         LANCZOS3_SUPPORT },
-   { "blackman",         blackman_filter,         BLACKMAN_SUPPORT },
-   { "lanczos4",         lanczos4_filter,         LANCZOS4_SUPPORT },
-   { "lanczos6",         lanczos6_filter,         LANCZOS6_SUPPORT },
-   { "lanczos12",        lanczos12_filter,        LANCZOS12_SUPPORT },
-   { "kaiser",           kaiser_filter,           KAISER_SUPPORT },
-   { "gaussian",         gaussian_filter,         GAUSSIAN_SUPPORT },
-   { "catmullrom",       catmull_rom_filter,      CATMULL_ROM_SUPPORT },
-   { "quadratic_interp", quadratic_interp_filter, QUADRATIC_SUPPORT },
-   { "quadratic_approx", quadratic_approx_filter, QUADRATIC_SUPPORT },
-   { "quadratic_mix",    quadratic_mix_filter,    QUADRATIC_SUPPORT },
+   { Resampler::BOX,              box_filter,              BOX_FILTER_SUPPORT },
+   { Resampler::TENT,             tent_filter,             TENT_FILTER_SUPPORT },
+   { Resampler::BELL,             bell_filter,             BELL_SUPPORT },
+   { Resampler::B_SPLINE,         B_spline_filter,         B_SPLINE_SUPPORT },
+   { Resampler::MITCHELL,         mitchell_filter,         MITCHELL_SUPPORT },
+   { Resampler::LANCZOS3,         lanczos3_filter,         LANCZOS3_SUPPORT },
+   { Resampler::BLACKMAN,         blackman_filter,         BLACKMAN_SUPPORT },
+   { Resampler::LANCZOS4,         lanczos4_filter,         LANCZOS4_SUPPORT },
+   { Resampler::LANCZOS6,         lanczos6_filter,         LANCZOS6_SUPPORT },
+   { Resampler::LANCZOS12,        lanczos12_filter,        LANCZOS12_SUPPORT },
+   { Resampler::KAISER,           kaiser_filter,           KAISER_SUPPORT },
+   { Resampler::GAUSSIAN,         gaussian_filter,         GAUSSIAN_SUPPORT },
+   { Resampler::CATMULLROM,       catmull_rom_filter,      CATMULL_ROM_SUPPORT },
+   { Resampler::QUADRATIC_INTERPOLATION, quadratic_interp_filter, QUADRATIC_SUPPORT },
+   { Resampler::QUADRATIC_APPROXIMATION, quadratic_approx_filter, QUADRATIC_SUPPORT },
+   { Resampler::QUADRATIC_MIX,    quadratic_mix_filter,    QUADRATIC_SUPPORT },
 };
 
 static const int NUM_FILTERS = sizeof(g_filters) / sizeof(g_filters[0]);
@@ -1012,7 +1012,7 @@ Resampler::Resampler(int src_x, int src_y,
                      int dst_x, int dst_y,
                      Boundary_Op boundary_op,
                      Resample_Real sample_low, Resample_Real sample_high,
-                     const char* Pfilter_name,
+                     Resampler::Filter filter,
                      Contrib_List* Pclist_x,
                      Contrib_List* Pclist_y,
                      Resample_Real filter_x_scale,
@@ -1062,17 +1062,13 @@ Resampler::Resampler(int src_x, int src_y,
    }
 
    // Find the specified filter.
-
-   if (Pfilter_name == NULL)
-      Pfilter_name = RESAMPLER_DEFAULT_FILTER;
-
    for (i = 0; i < NUM_FILTERS; i++)
-      if (strcmp(Pfilter_name, g_filters[i].name) == 0)
+      if ( filter ==  g_filters[i].name )
          break;
 
    if (i == NUM_FILTERS)
    {
-      m_status = STATUS_BAD_FILTER_NAME;
+      m_status = STATUS_BAD_FILTER_TYPE;
       return;
    }
 
@@ -1205,17 +1201,4 @@ void Resampler::get_clists(Contrib_List** ptr_clist_x, Contrib_List** ptr_clist_
       *ptr_clist_y = m_Pclist_y;
 }
 
-int Resampler::get_filter_num()
-{
-   return NUM_FILTERS;
-}
-
-char* Resampler::get_filter_name(int filter_num)
-{
-   if ((filter_num < 0) || (filter_num >= NUM_FILTERS))
-      return NULL;
-   else
-      return g_filters[filter_num].name;
-}
-
 #pragma GCC diagnostic pop
index c28daaf..4cc78a5 100644 (file)
@@ -1,10 +1,10 @@
 // resampler.h, Separable filtering image rescaler v2.21, Rich Geldreich - richgel99@gmail.com
 // See unlicense.org text at the bottom of this file.
+// Modified to specify filters as enum rather than char *
 #ifndef __RESAMPLER_H__
 #define __RESAMPLER_H__
 
 #define RESAMPLER_DEBUG_OPS 0
-#define RESAMPLER_DEFAULT_FILTER "lanczos4"
 
 #define RESAMPLER_MAX_DIMENSION 16384
 
@@ -16,6 +16,29 @@ class Resampler
 public:
    typedef Resample_Real Sample;
 
+   /**
+    * Supported filter types
+    */
+   enum Filter
+   {
+     BOX,
+     TENT,
+     BELL,
+     B_SPLINE,
+     MITCHELL,
+     LANCZOS3,
+     BLACKMAN,
+     LANCZOS4,
+     LANCZOS6,
+     LANCZOS12,
+     KAISER,
+     GAUSSIAN,
+     CATMULLROM,
+     QUADRATIC_INTERPOLATION,
+     QUADRATIC_APPROXIMATION,
+     QUADRATIC_MIX,
+   };
+
    struct Contrib
    {
       Resample_Real weight;
@@ -39,7 +62,7 @@ public:
    {
       STATUS_OKAY = 0,
       STATUS_OUT_OF_MEMORY = 1,
-      STATUS_BAD_FILTER_NAME = 2,
+      STATUS_BAD_FILTER_TYPE = 2,
       STATUS_SCAN_BUFFER_FULL = 3
    };
 
@@ -54,7 +77,7 @@ public:
       int dst_x, int dst_y,
       Boundary_Op boundary_op = BOUNDARY_CLAMP,
       Resample_Real sample_low = 0.0f, Resample_Real sample_high = 0.0f,
-      const char* Pfilter_name = RESAMPLER_DEFAULT_FILTER,
+      Resampler::Filter = Resampler::LANCZOS3,
       Contrib_List* Pclist_x = NULL,
       Contrib_List* Pclist_y = NULL,
       Resample_Real filter_x_scale = 1.0f,
@@ -80,10 +103,6 @@ public:
    Contrib_List* get_clist_x() const { return m_Pclist_x; }
    Contrib_List* get_clist_y() const { return m_Pclist_y; }
 
-   // Filter accessors.
-   static int get_filter_num();
-   static char* get_filter_name(int filter_num);
-
 private:
    Resampler();
    Resampler(const Resampler& o);