Published the AsyncImageLoader and SyncImageLoader to the public API 78/96978/15
authorTom Robinson <tom.robinson@samsung.com>
Thu, 10 Nov 2016 15:33:03 +0000 (15:33 +0000)
committerTom Robinson <tom.robinson@samsung.com>
Fri, 11 Nov 2016 16:16:03 +0000 (08:16 -0800)
The AsyncImageLoader API allows asynchronous image loading via an internal thread.
Multiple images can be loaded with one AsyncImageLoader.
The load of each image returns an ID.
This ID is returned, along with the pixel data in a signal once the load for each individual image has completed.

The SyncImageLoader allows synchronous image loading.
It consists of a set of Load functions mirroring the prototypes of the Load functions within the AsyncImageLoader.
The loads are performed within the same thread (the thread is blocked whilst loading).

Change-Id: If1d59bf5981de5f52371bd5838371b41031d1fd4

16 files changed:
automated-tests/src/dali-toolkit/CMakeLists.txt
automated-tests/src/dali-toolkit/utc-Dali-AsyncImageLoader.cpp
automated-tests/src/dali-toolkit/utc-Dali-SyncImageLoader.cpp [new file with mode: 0644]
build/tizen/dali-toolkit/Makefile.am
build/tizen/docs/dali.doxy.in
dali-toolkit/dali-toolkit.h
dali-toolkit/devel-api/file.list
dali-toolkit/internal/image-loader/async-image-loader-impl.cpp
dali-toolkit/internal/image-loader/async-image-loader-impl.h
dali-toolkit/internal/image-loader/image-atlas-impl.h
dali-toolkit/internal/image-loader/image-load-thread.cpp
dali-toolkit/public-api/file.list
dali-toolkit/public-api/image-loader/async-image-loader.cpp [moved from dali-toolkit/devel-api/image-loader/async-image-loader.cpp with 70% similarity]
dali-toolkit/public-api/image-loader/async-image-loader.h [moved from dali-toolkit/devel-api/image-loader/async-image-loader.h with 52% similarity]
dali-toolkit/public-api/image-loader/sync-image-loader.cpp [new file with mode: 0644]
dali-toolkit/public-api/image-loader/sync-image-loader.h [new file with mode: 0644]

index 1c6f3c9..f30e3d1 100644 (file)
@@ -57,6 +57,7 @@ SET(TC_SOURCES
    utc-Dali-ImageAtlas.cpp
    utc-Dali-VideoView.cpp
    utc-Dali-AsyncImageLoader.cpp
+   utc-Dali-SyncImageLoader.cpp
 )
 
 # Append list of test harness files (Won't get parsed for test cases)
index 3ee9a77..74dcc73 100644 (file)
@@ -19,7 +19,7 @@
 #include <dali/dali.h>
 #include <dali-toolkit-test-suite-utils.h>
 #include <toolkit-event-thread-callback.h>
-#include <dali-toolkit/devel-api/image-loader/async-image-loader.h>
+#include <dali-toolkit/dali-toolkit.h>
 
 using namespace Dali;
 using namespace Dali::Toolkit;
@@ -139,6 +139,28 @@ int UtcDaliAsyncImageLoaderAssignmentOperator(void)
   END_TEST;
 }
 
+int UtcDaliAsyncImageLoaderDownCastP(void)
+{
+  AsyncImageLoader asyncImageLoader = AsyncImageLoader::New();
+  BaseHandle object(asyncImageLoader);
+
+  AsyncImageLoader asyncImageLoader2 = AsyncImageLoader::DownCast( object );
+
+  DALI_TEST_CHECK( asyncImageLoader2 );
+
+  END_TEST;
+}
+
+int UtcDaliAsyncImageLoaderDownCastN(void)
+{
+  BaseHandle unInitializedObject;
+  AsyncImageLoader asyncImageLoader = AsyncImageLoader::DownCast( unInitializedObject );
+
+  DALI_TEST_CHECK( !asyncImageLoader );
+
+  END_TEST;
+}
+
 int UtcDaliAsyncImageLoaderLoadAndLoadedSignal(void)
 {
   ToolkitTestApplication application;
@@ -169,6 +191,7 @@ int UtcDaliAsyncImageLoaderLoadAndLoadedSignal(void)
   END_TEST;
 }
 
+// Note: This is not an ideal test, but we cannot guarantee we can call Cancel() before the image has finished loading.
 int UtcDaliAsyncImageLoaderCancel(void)
 {
   ToolkitTestApplication application;
@@ -182,31 +205,28 @@ int UtcDaliAsyncImageLoaderCancel(void)
   uint32_t id02 = loader.Load( gImage_50_RGBA, ImageDimensions( 25, 25 ) );
   uint32_t id03 = loader.Load( gImage_128_RGB, ImageDimensions( 100, 100 ), FittingMode::SCALE_TO_FILL, SamplingMode::BOX_THEN_LINEAR, true );
 
-  // cancel the loading of the second image
-  DALI_TEST_CHECK( loader.Cancel( id02 ) );
-
   EventThreadCallback* eventTrigger = EventThreadCallback::Get();
   CallbackBase* callback = eventTrigger->GetCallback();
 
-  eventTrigger->WaitingForTrigger( 2 );// waiting until first and third images are loaded
+  eventTrigger->WaitingForTrigger( 3 ); // waiting until images are loaded
 
   CallbackBase::Execute( *callback );
 
-  DALI_TEST_CHECK( ! loader.Cancel( id03 ) ); // can not cancel a task that is already implemeted
-
   application.SendNotification();
   application.Render();
 
-  DALI_TEST_CHECK( loadedSignalVerifier.LoadedImageCount() == 2 );
+  DALI_TEST_CHECK( loadedSignalVerifier.LoadedImageCount() == 3 );
+
+  DALI_TEST_CHECK( !loader.Cancel( id03 ) ); // Cannot cancel a task that is already implemeted
 
-  DALI_TEST_CHECK( loadedSignalVerifier.Verify( id01, 34, 34 ) );  // first image is successfully loaded
-  DALI_TEST_CHECK( !loadedSignalVerifier.Verify( id02, 25, 25 ) ); // second image is not loaded
-  DALI_TEST_CHECK( loadedSignalVerifier.Verify( id03, 100, 100 ) ); // third image is successfully loaded
+  DALI_TEST_CHECK( loadedSignalVerifier.Verify( id01, 34, 34 ) );   // first image is loaded
+  DALI_TEST_CHECK( loadedSignalVerifier.Verify( id02, 25, 25 ) );   // second image is loaded
+  DALI_TEST_CHECK( loadedSignalVerifier.Verify( id03, 100, 100 ) ); // third image is loaded
 
   END_TEST;
 }
 
-int UtcDaliAsncImageLoaderCancelAll01(void)
+int UtcDaliAsyncImageLoaderCancelAll(void)
 {
   ToolkitTestApplication application;
 
@@ -229,38 +249,3 @@ int UtcDaliAsncImageLoaderCancelAll01(void)
   END_TEST;
 }
 
-int UtcDaliAsyncImageLoaderCancelAll02(void)
-{
-  ToolkitTestApplication application;
-
-  AsyncImageLoader loader = AsyncImageLoader::New();
-  ImageLoadedSignalVerifier loadedSignalVerifier;
-
-  loader.ImageLoadedSignal().Connect( &loadedSignalVerifier, &ImageLoadedSignalVerifier::ImageLoaded );
-
-  loader.Load( gImage_34_RGBA, ImageDimensions( 34, 34 ) );
-  uint32_t id02 = loader.Load( gImage_50_RGBA, ImageDimensions( 25, 25 ) );
-
-  // try to cancel the loading of the first and second image, however the cancellation of the first image is not guaranteed
-  loader.CancelAll();
-
-  uint32_t id03 = loader.Load( gImage_128_RGB, ImageDimensions( 100, 100 ), FittingMode::SCALE_TO_FILL, SamplingMode::BOX_THEN_LINEAR, true );
-  loader.Load( gImage_128_RGB, ImageDimensions( 128, 128 ), FittingMode::SCALE_TO_FILL, SamplingMode::BOX_THEN_LINEAR, true );
-
-  EventThreadCallback* eventTrigger = EventThreadCallback::Get();
-  CallbackBase* callback = eventTrigger->GetCallback();
-
-  eventTrigger->WaitingForTrigger( 2 );// waiting until the third images is loaded
-
-  CallbackBase::Execute( *callback );
-
-  application.SendNotification();
-  application.Render();
-
-  DALI_TEST_CHECK( !loadedSignalVerifier.Verify( id02, 25, 25 ) ); // second image is not loaded
-  DALI_TEST_CHECK( loadedSignalVerifier.Verify( id03, 100, 100 ) ); // third image is successfully loaded
-
-  END_TEST;
-}
-
-
diff --git a/automated-tests/src/dali-toolkit/utc-Dali-SyncImageLoader.cpp b/automated-tests/src/dali-toolkit/utc-Dali-SyncImageLoader.cpp
new file mode 100644 (file)
index 0000000..d37c5fc
--- /dev/null
@@ -0,0 +1,74 @@
+/*
+ * 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 <stdlib.h>
+#include <unistd.h>
+#include <dali/dali.h>
+#include <dali-toolkit-test-suite-utils.h>
+#include <dali-toolkit/dali-toolkit.h>
+
+using namespace Dali;
+using namespace Dali::Toolkit;
+
+namespace
+{
+
+// Resolution: 50*50, pixel format: RGBA8888
+static const char* gImage_50_RGBA = TEST_RESOURCE_DIR "/icon-delete.png";
+
+// Resolution: 128*128, pixel format: RGB888
+static const char* gImage_128_RGB = TEST_RESOURCE_DIR "/gallery-small-1.jpg";
+
+
+void VerifyLoad( PixelData pixelData, uint32_t width, uint32_t height )
+{
+  DALI_TEST_CHECK( pixelData );
+  DALI_TEST_EQUALS<unsigned int>( pixelData.GetWidth(), width, TEST_LOCATION );
+  DALI_TEST_EQUALS<unsigned int>( pixelData.GetHeight(), height, TEST_LOCATION );
+}
+
+} // anonymous namespace
+
+
+int UtcDaliSyncImageLoaderLoad(void)
+{
+  PixelData pixelData = Toolkit::SyncImageLoader::Load( gImage_50_RGBA );
+
+  DALI_TEST_EQUALS<bool>( pixelData, true, TEST_LOCATION );
+
+  END_TEST;
+}
+
+int UtcDaliSyncImageLoaderLoadWithDimensions(void)
+{
+  PixelData pixelData = Toolkit::SyncImageLoader::Load( gImage_50_RGBA, ImageDimensions( 25, 25 ) );
+
+  VerifyLoad( pixelData, 25u, 25u );
+
+  END_TEST;
+}
+
+int UtcDaliSyncImageLoaderLoadWithAllOptions(void)
+{
+  PixelData pixelData = Toolkit::SyncImageLoader::Load( gImage_128_RGB, ImageDimensions( 100, 100 ), FittingMode::SCALE_TO_FILL, SamplingMode::BOX_THEN_LINEAR, true );
+
+  VerifyLoad( pixelData, 100u, 100u );
+
+  END_TEST;
+}
+
+
index fd09527..166feb4 100644 (file)
@@ -111,7 +111,7 @@ develapiprogressbardir =        $(develapicontrolsdir)/progress-bar
 develapishadowviewdir =         $(develapicontrolsdir)/shadow-view
 develapisuperblurviewdir =      $(develapicontrolsdir)/super-blur-view
 develapifocusmanagerdir =       $(develapidir)/focus-manager
-develapiimageloaderdir =         $(develapidir)/image-loader
+develapiimageloaderdir =        $(develapidir)/image-loader
 develapiscriptingdir =          $(develapidir)/scripting
 develapishadereffectsdir =      $(develapidir)/shader-effects
 develapitransitioneffectsdir =  $(develapidir)/transition-effects
@@ -146,6 +146,7 @@ develapitextselectionpopup_HEADERS = $(devel_api_text_controls_header_files)
 # public api source
 publicapidir =                     $(topleveldir)/public-api
 publicapicontrolsdir =             $(publicapidir)/controls
+publicapiimageloaderdir =          $(publicapidir)/image-loader
 publicapiaccessibilitymanagerdir = $(publicapidir)/accessibility-manager
 publicapialignmentdir =            $(publicapicontrolsdir)/alignment
 publicapibuttonsdir =              $(publicapicontrolsdir)/buttons
@@ -169,6 +170,7 @@ publicapivisualsdir =              $(publicapidir)/visuals
 # public api headers
 publicapi_HEADERS =                     $(public_api_header_files)
 publicapicontrols_HEADERS =             $(public_api_controls_header_files)
+publicapiimageloader_HEADERS =          $(public_api_image_loader_header_files)
 publicapiaccessibilitymanager_HEADERS = $(public_api_accessibility_manager_header_files)
 publicapialignment_HEADERS =            $(public_api_alignment_header_files)
 publicapibuttons_HEADERS =              $(public_api_buttons_header_files)
index 6cdabe4..6007065 100644 (file)
@@ -351,6 +351,7 @@ ALIASES += SINCE_1_2_2="@since 1.2.2"
 ALIASES += SINCE_1_2_4="@since 1.2.4"
 ALIASES += SINCE_1_2_5="@since 1.2.5"
 ALIASES += SINCE_1_2_10="@since 1.2.10"
+ALIASES += SINCE_1_2_14="@since 1.2.14"
 
 ALIASES += DEPRECATED_1_0="@deprecated Deprecated since 1.0"
 ALIASES += DEPRECATED_1_1="@deprecated Deprecated since 1.1"
@@ -375,6 +376,7 @@ ALIASES += REMARK_INTERNET=""
 #ALIASES += SINCE_1_2_4="\par Since:\n 3.0, DALi version 1.2.4"
 #ALIASES += SINCE_1_2_5="\par Since:\n 3.0, DALi version 1.2.5"
 #ALIASES += SINCE_1_2_10="\par Since:\n 3.0, DALi version 1.2.10"
+#ALIASES += SINCE_1_2_14="\par Since:\n 3.0, DALi version 1.2.14"
 
 ## DALi has no deprecated API in Tizen 2.4 because it's DALi's first release.
 ## Thus deprecated APIs in DALi 1.0.xx will be deprecated in Tizen 3.0.
index be46ddd..ba7e85b 100644 (file)
@@ -47,6 +47,9 @@
 #include <dali-toolkit/public-api/controls/text-controls/text-label.h>
 #include <dali-toolkit/public-api/controls/video-view/video-view.h>
 
+#include <dali-toolkit/public-api/image-loader/async-image-loader.h>
+#include <dali-toolkit/public-api/image-loader/sync-image-loader.h>
+
 #include <dali-toolkit/public-api/accessibility-manager/accessibility-manager.h>
 
 #include <dali-toolkit/public-api/focus-manager/keyboard-focus-manager.h>
index 78e96e5..8af4766 100755 (executable)
@@ -21,7 +21,6 @@ devel_api_src_files = \
   $(devel_api_src_dir)/controls/text-controls/text-selection-toolbar.cpp \
   $(devel_api_src_dir)/controls/tool-bar/tool-bar.cpp \
   $(devel_api_src_dir)/focus-manager/keyinput-focus-manager.cpp \
-  $(devel_api_src_dir)/image-loader/async-image-loader.cpp \
   $(devel_api_src_dir)/image-loader/atlas-upload-observer.cpp \
   $(devel_api_src_dir)/image-loader/image-atlas.cpp \
   $(devel_api_src_dir)/scripting/script.cpp \
@@ -88,7 +87,6 @@ devel_api_focus_manager_header_files = \
   $(devel_api_src_dir)/focus-manager/keyinput-focus-manager.h
 
 devel_api_image_loader_header_files = \
-  $(devel_api_src_dir)/image-loader/async-image-loader.h \
   $(devel_api_src_dir)/image-loader/atlas-upload-observer.h \
   $(devel_api_src_dir)/image-loader/image-atlas.h
 
index d25ea5c..06065b7 100644 (file)
@@ -34,7 +34,7 @@ namespace Internal
 AsyncImageLoader::AsyncImageLoader()
 : mLoadedSignal(),
   mLoadThread( new EventThreadCallback( MakeCallback( this, &AsyncImageLoader::ProcessLoadedImage ) ) ),
-  mLoadTaskId( 0 ),
+  mLoadTaskId( 0u ),
   mIsLoadThreadStarted( false )
 {
 }
@@ -51,7 +51,7 @@ IntrusivePtr<AsyncImageLoader> AsyncImageLoader::New()
 }
 
 uint32_t AsyncImageLoader::Load( const std::string& url,
-                                 ImageDimensions size,
+                                 ImageDimensions dimensions,
                                  FittingMode::Type fittingMode,
                                  SamplingMode::Type samplingMode,
                                  bool orientationCorrection )
@@ -62,7 +62,7 @@ uint32_t AsyncImageLoader::Load( const std::string& url,
     mIsLoadThreadStarted = true;
   }
 
-  BitmapLoader loader = BitmapLoader::New( url, size, fittingMode, samplingMode, orientationCorrection );
+  BitmapLoader loader = BitmapLoader::New( url, dimensions, fittingMode, samplingMode, orientationCorrection );
 
   mLoadThread.AddTask( new LoadingTask( ++mLoadTaskId, loader ) );
 
index cb0311c..92a1652 100644 (file)
@@ -1,5 +1,5 @@
-#ifndef DALI_TOOLKIT_ASYNC_IMAGE_LOADER_IMPL_H__
-#define DALI_TOOLKIT_ASYNC_IMAGE_LOADER_IMPL_H__
+#ifndef DALI_TOOLKIT_ASYNC_IMAGE_LOADER_IMPL_H
+#define DALI_TOOLKIT_ASYNC_IMAGE_LOADER_IMPL_H
 
 /*
  * Copyright (c) 2016 Samsung Electronics Co., Ltd.
@@ -22,7 +22,7 @@
 #include <dali/public-api/object/base-object.h>
 
 // INTERNAL INCLUDES
-#include <dali-toolkit/devel-api/image-loader/async-image-loader.h>
+#include <dali-toolkit/public-api/image-loader/async-image-loader.h>
 #include <dali-toolkit/internal/image-loader/image-load-thread.h>
 
 namespace Dali
@@ -49,10 +49,10 @@ public:
   static IntrusivePtr<AsyncImageLoader> New();
 
   /**
-   * @copydoc Toolkit::AsyncImageLoader::Load( const std::string&, ImageDimensions,FittingMode::Type, SamplingMode::Type, bool )
+   * @copydoc Toolkit::AsyncImageLoader::Load( const std::string&, ImageDimensions, FittingMode::Type, SamplingMode::Type, bool )
    */
   uint32_t Load( const std::string& url,
-                 ImageDimensions size,
+                 ImageDimensions dimensions,
                  FittingMode::Type fittingMode,
                  SamplingMode::Type samplingMode,
                  bool orientationCorrection );
@@ -97,20 +97,20 @@ private:
 
 } // namespace Internal
 
-inline const Internal::AsyncImageLoader& GetImplementation( const Toolkit::AsyncImageLoader& loader )
+inline const Internal::AsyncImageLoader& GetImplementation( const Toolkit::AsyncImageLoader& handle )
 {
-  DALI_ASSERT_ALWAYS( loader && "AsyncImageLoader handle is empty" );
+  DALI_ASSERT_ALWAYS( handle && "AsyncImageLoader handle is empty" );
 
-  const BaseObject& object = loader.GetBaseObject();
+  const BaseObject& object = handle.GetBaseObject();
 
   return static_cast<const Internal::AsyncImageLoader&>( object );
 }
 
-inline Internal::AsyncImageLoader& GetImplementation( Toolkit::AsyncImageLoader& loader )
+inline Internal::AsyncImageLoader& GetImplementation( Toolkit::AsyncImageLoader& handle )
 {
-  DALI_ASSERT_ALWAYS( loader && "AsyncImageLoader handle is empty" );
+  DALI_ASSERT_ALWAYS( handle && "AsyncImageLoader handle is empty" );
 
-  BaseObject& object = loader.GetBaseObject();
+  BaseObject& object = handle.GetBaseObject();
 
   return static_cast<Internal::AsyncImageLoader&>( object );
 }
@@ -119,4 +119,4 @@ inline Internal::AsyncImageLoader& GetImplementation( Toolkit::AsyncImageLoader&
 
 } // namespace Dali
 
-#endif /* DALI_TOOLKIT_ASYNC_IMAGE_LOADER_IMPL_H__ */
+#endif // DALI_TOOLKIT_ASYNC_IMAGE_LOADER_IMPL_H
index a773ea7..4f735ef 100644 (file)
@@ -27,8 +27,8 @@
 
 // INTERNAL INCLUDES
 #include <dali-toolkit/devel-api/image-loader/image-atlas.h>
-#include <dali-toolkit/devel-api/image-loader/async-image-loader.h>
 #include <dali-toolkit/internal/image-loader/atlas-packer.h>
+#include <dali-toolkit/public-api/image-loader/async-image-loader.h>
 
 namespace Dali
 {
index a27db14..11e251a 100644 (file)
@@ -50,7 +50,7 @@ ImageLoadThread::~ImageLoadThread()
 
 void ImageLoadThread::Run()
 {
-  while( LoadingTask* task =  NextTaskToProcess())
+  while( LoadingTask* task = NextTaskToProcess() )
   {
     task->loader.Load();
     AddCompletedTask( task );
@@ -68,7 +68,7 @@ void ImageLoadThread::AddTask( LoadingTask* task )
     mLoadQueue.PushBack( task );
   }
 
-  if( wasEmpty)
+  if( wasEmpty )
   {
     // wake up the image loading thread
     mConditionalWait.Notify();
@@ -97,7 +97,7 @@ bool ImageLoadThread::CancelTask( uint32_t loadingTaskId )
   // Lock while remove task from the queue
   ConditionalWait::ScopedLock lock( mConditionalWait );
 
-  for( Vector< LoadingTask* >::Iterator iter = mLoadQueue.Begin(); iter != mLoadQueue.End(); iter++ )
+  for( Vector< LoadingTask* >::Iterator iter = mLoadQueue.Begin(); iter != mLoadQueue.End(); ++iter )
   {
     if( (*iter)->id == loadingTaskId )
     {
@@ -116,9 +116,9 @@ void ImageLoadThread::CancelAll()
   // Lock while remove task from the queue
   ConditionalWait::ScopedLock lock( mConditionalWait );
 
-  for( Vector< LoadingTask* >::Iterator iter = mLoadQueue.Begin(); iter != mLoadQueue.End(); iter++ )
+  for( Vector< LoadingTask* >::Iterator iter = mLoadQueue.Begin(); iter != mLoadQueue.End(); ++iter )
   {
-    delete (*iter);
+    delete ( *iter );
   }
   mLoadQueue.Clear();
 }
index 3734525..a4e4e56 100755 (executable)
@@ -26,6 +26,8 @@ public_api_src_files = \
   $(public_api_src_dir)/controls/text-controls/text-label.cpp \
   $(public_api_src_dir)/controls/text-controls/text-field.cpp \
   $(public_api_src_dir)/controls/video-view/video-view.cpp \
+  $(public_api_src_dir)/image-loader/async-image-loader.cpp \
+  $(public_api_src_dir)/image-loader/sync-image-loader.cpp \
   $(public_api_src_dir)/styling/style-manager.cpp \
   $(public_api_src_dir)/accessibility-manager/accessibility-manager.cpp \
   $(public_api_src_dir)/focus-manager/keyboard-focus-manager.cpp \
@@ -68,6 +70,10 @@ public_api_item_view_header_files = \
   $(public_api_src_dir)/controls/scrollable/item-view/item-view-declarations.h \
   $(public_api_src_dir)/controls/scrollable/item-view/item-view.h
 
+public_api_image_loader_header_files = \
+  $(public_api_src_dir)/image-loader/async-image-loader.h \
+  $(public_api_src_dir)/image-loader/sync-image-loader.h
+
 public_api_scrollable_header_files = \
   $(public_api_src_dir)/controls/scrollable/scrollable.h
 
@@ -36,7 +36,8 @@ AsyncImageLoader::~AsyncImageLoader()
 
 AsyncImageLoader::AsyncImageLoader( Internal::AsyncImageLoader* impl )
 : BaseHandle( impl )
-{}
+{
+}
 
 AsyncImageLoader::AsyncImageLoader( const AsyncImageLoader& handle )
 : BaseHandle( handle )
@@ -45,10 +46,15 @@ AsyncImageLoader::AsyncImageLoader( const AsyncImageLoader& handle )
 
 AsyncImageLoader& AsyncImageLoader::operator=( const AsyncImageLoader& handle )
 {
-  BaseHandle::operator=(handle);
+  BaseHandle::operator=( handle );
   return *this;
 }
 
+AsyncImageLoader AsyncImageLoader::DownCast( BaseHandle handle )
+{
+  return AsyncImageLoader( dynamic_cast<Dali::Toolkit::Internal::AsyncImageLoader*>( handle.GetObjectPtr() ) );
+}
+
 AsyncImageLoader AsyncImageLoader::New()
 {
   IntrusivePtr<Internal::AsyncImageLoader> internal = Internal::AsyncImageLoader::New();
@@ -57,36 +63,36 @@ AsyncImageLoader AsyncImageLoader::New()
 
 uint32_t AsyncImageLoader::Load( const std::string& url )
 {
-  return GetImplementation(*this).Load( url, ImageDimensions(), FittingMode::DEFAULT, SamplingMode::BOX_THEN_LINEAR, true );
+  return GetImplementation( *this ).Load( url, ImageDimensions(), FittingMode::DEFAULT, SamplingMode::BOX_THEN_LINEAR, true );
 }
 
-uint32_t AsyncImageLoader::Load( const std::string& url, ImageDimensions size )
+uint32_t AsyncImageLoader::Load( const std::string& url, ImageDimensions dimensions )
 {
-  return GetImplementation(*this).Load( url, size, FittingMode::DEFAULT, SamplingMode::BOX_THEN_LINEAR, true );
+  return GetImplementation( *this ).Load( url, dimensions, FittingMode::DEFAULT, SamplingMode::BOX_THEN_LINEAR, true );
 }
 
 uint32_t AsyncImageLoader::Load( const std::string& url,
-                                 ImageDimensions size,
+                                 ImageDimensions dimensions,
                                  FittingMode::Type fittingMode,
                                  SamplingMode::Type samplingMode,
                                  bool orientationCorrection )
 {
-  return GetImplementation(*this).Load( url, size, fittingMode, samplingMode, orientationCorrection );
+  return GetImplementation(*this).Load( url, dimensions, fittingMode, samplingMode, orientationCorrection );
 }
 
-bool AsyncImageLoader::Cancel( uint32_t loadingTaskId)
+bool AsyncImageLoader::Cancel( uint32_t loadingTaskId )
 {
   return GetImplementation(*this).Cancel( loadingTaskId );
 }
 
 void AsyncImageLoader::CancelAll()
 {
-  GetImplementation(*this).CancelAll();
+  GetImplementation( *this ).CancelAll();
 }
 
 AsyncImageLoader::ImageLoadedSignalType& AsyncImageLoader::ImageLoadedSignal()
 {
-  return GetImplementation(*this).ImageLoadedSignal();
+  return GetImplementation( *this ).ImageLoadedSignal();
 }
 } // namespace Toolkit
 
@@ -1,5 +1,5 @@
-#ifndef __DALI_TOOLKIT_ASYNC_IMAGE_LOADER_H__
-#define __DALI_TOOLKIT_ASYNC_IMAGE_LOADER_H__
+#ifndef DALI_TOOLKIT_ASYNC_IMAGE_LOADER_H
+#define DALI_TOOLKIT_ASYNC_IMAGE_LOADER_H
 
 /*
  * Copyright (c) 2016 Samsung Electronics Co., Ltd.
@@ -36,27 +36,38 @@ class AsyncImageLoader;
 }
 
 /**
- *@brief The AysncImageLoader is used to load pixel data from the URL asynchronously.
+ * @brief The AsyncImageLoader is used to load pixel data from a URL asynchronously.
  *
  * The images are loaded in a worker thread to avoid blocking the main event thread.
  *
- * Each load call is assigned with an ID, connect to the ImageLoadedSignal and receive the corresponding pixel data by comparing the ID.
+ * To keep track of the loading images, each load call is assigned an ID (which is returned by the Load() call).
+ * To know when the Load has completed, connect to the ImageLoadedSignal.
+ * This signal should be connected before Load is called (in case the signal is emitted immediately).
+ *
+ * Load errors can be detected by checking the PixelData object is valid from within the signal handler.
+
+ * Note: The PixelData object will automatically be destroyed when it leaves its scope.
+ *
+ * Example:
  *
- * To make sure the signal is always received, the signal should get connected before invoking the load call.
  * @code
  * class MyClass : public ConnectionTracker
  * {
- * public:
+ *   public:
  *
- *   MyCallback( uint32_t id, PixelData pixelData)
+ *   MyCallback( uint32_t loadedTaskId, PixelData pixelData )
  *   {
- *     if(id == mId1)
+ *     // First check if the image loaded correctly.
+ *     if( pixelData )
  *     {
- *       // use the loaded pixel data from the first image
- *     }
- *     else if( id == mId2 )
- *     {
- *       // use the loaded pixel data from the second image
+ *       if( loadedTaskId == mId1 )
+ *       {
+ *         // use the loaded pixel data from the first image
+ *       }
+ *       else if( loadedTaskId == mId2 )
+ *       {
+ *         // use the loaded pixel data from the second image
+ *       }
  *     }
  *   }
  *
@@ -66,11 +77,13 @@ class AsyncImageLoader;
  *
  * MyClass myObject;
  * AsyncImageLoader imageLoader = AsyncImageLoader::New();
- * // connect the signal here
+ *
+ * // Connect the signal here.
  * imageLoader.ImageLoadedSignal().Connect( &myObject, &MyClass::MyCallback );
- * // then invoke the load calls
- * testCallback.mId1 = imageLoader.Load( "first_image_url.jpg" );
- * testCallback.mId2 = imageLoader.Load( "second_image_url.jpg" );
+ *
+ * // Invoke the load calls (must do this after connecting the signal to guarantee callbacks occur).
+ * myObject.mId1 = imageLoader.Load( "first_image_url.jpg" );
+ * myObject.mId2 = imageLoader.Load( "second_image_url.jpg" );
  *
  * @endcode
  */
@@ -78,17 +91,13 @@ class DALI_IMPORT_API AsyncImageLoader : public BaseHandle
 {
 public:
 
-  /**
-   * @brief Type of signal for image loading finished.
-   *
-   * The signal is emit with the load ID and its corresponding loaded pixel data
-   */
-  typedef Signal< void( uint32_t, PixelData ) > ImageLoadedSignalType;
+  typedef Signal< void( uint32_t, PixelData ) > ImageLoadedSignalType; ///< Image loaded signal type @SINCE_1_2_14
 
 public:
 
   /**
    * @brief Constructor which creates an empty AsyncImageLoader handle.
+   * @SINCE_1_2_14
    *
    * Use AsyncImageLoader::New() to create an initialised object.
    */
@@ -96,6 +105,7 @@ public:
 
   /**
    * @brief Destructor
+   * @SINCE_1_2_14
    *
    * This is non-virtual since derived Handle types must not contain data or virtual methods.
    */
@@ -103,68 +113,99 @@ public:
 
   /**
    * @brief This copy constructor is required for (smart) pointer semantics.
+   * @SINCE_1_2_14
    *
-   * @param [in] handle A reference to the copied handle
+   * @param[in] handle A reference to the copied handle
    */
   AsyncImageLoader( const AsyncImageLoader& handle );
 
   /**
    * @brief This assignment operator is required for (smart) pointer semantics.
+   * @SINCE_1_2_14
    *
-   * @param [in] handle  A reference to the copied handle
+   * @param[in] handle  A reference to the copied handle
    * @return A reference to this
    */
   AsyncImageLoader& operator=( const AsyncImageLoader& handle );
 
- /*
-  * @brief Create a new loader to load the image asynchronously in a worker thread.
-  *
-  * @return The image loader.
-  */
+  /**
+   * @brief Create a new loader to load the image asynchronously in a worker thread.
+   * @SINCE_1_2_14
+   *
+   * @return The image loader.
+   */
   static AsyncImageLoader New();
 
   /**
-   * @brief Start a image loading task.
+   * @brief Downcast a handle to AsyncImageLoader handle.
+   *
+   * If the handle points to an AsyncImageLoader object the downcast produces
+   * a valid handle. If not, the returned handle is left uninitialized.
+   *
+   * @SINCE_1_2_14
+   * @param[in] handle A handle to an object
+   * @return A handle to a AsyncImageLoader object or an uninitialized handle
+   */
+  static AsyncImageLoader DownCast( BaseHandle handle );
+
+  /**
+   * @brief Start an image loading task.
+   * Note: When using this method, the following defaults will be used:
+   * fittingMode = FittingMode::DEFAULT
+   * samplingMode = SamplingMode::BOX_THEN_LINEAR
+   * orientationCorrection = true
+   *
+   * @SINCE_1_2_14
    *
    * @param[in] url The URL of the image file to load.
    * @return The loading task id.
    */
   uint32_t Load( const std::string& url );
-  /*
-   * @brief Start a image loading task.
+
+  /**
+   * @brief Start an image loading task.
+   * Note: When using this method, the following defaults will be used:
+   * fittingMode = FittingMode::DEFAULT
+   * samplingMode = SamplingMode::BOX_THEN_LINEAR
+   * orientationCorrection = true
+   *
+   * @SINCE_1_2_14
    *
    * @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] dimensions The width and height to fit the loaded image to.
    * @return The loading task id.
    */
-  uint32_t Load( const std::string& url, ImageDimensions size );
+  uint32_t Load( const std::string& url, ImageDimensions dimensions );
 
-  /*
-   * @brief Start a image loading task.
+  /**
+   * @brief Start an image loading task.
+   * @SINCE_1_2_14
    *
    * @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] dimensions 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.
    * @return The loading task id.
    */
   uint32_t Load( const std::string& url,
-                 ImageDimensions size,
+                 ImageDimensions dimensions,
                  FittingMode::Type fittingMode,
                  SamplingMode::Type samplingMode,
                  bool orientationCorrection );
 
   /**
-   * @brief Cancel a image loading task if it is still queuing in the work thread.
+   * @brief Cancel a image loading task if it is still queueing in the work thread.
+   * @SINCE_1_2_14
    *
    * @param[in] loadingTaskId The task id returned when invoking the load call.
    * @return If true, the loading task is removed from the queue, otherwise the loading is already implemented and unable to cancel anymore
    */
-  bool Cancel( uint32_t loadingTaskId);
+  bool Cancel( uint32_t loadingTaskId );
 
   /**
    * @brief Cancel all the loading tasks in the queue
+   * @SINCE_1_2_14
    */
   void CancelAll();
 
@@ -175,14 +216,25 @@ public:
    * @code
    *   void YourCallbackName( uint32_t id, PixelData pixelData );
    * @endcode
+   * @SINCE_1_2_14
    *
-   * @return A signal object to Connect() with.
+   * @return A reference to a signal object to Connect() with.
    */
   ImageLoadedSignalType& ImageLoadedSignal();
 
 public: // Not intended for developer use
 
+  /// @cond internal
+  /**
+   * @brief Allows the creation of a AsyncImageLoader handle from an internal pointer.
+   *
+   * @note Not intended for application developers
+   * @SINCE_1_2_14
+   *
+   * @param[in] impl A pointer to the object.
+   */
   explicit DALI_INTERNAL AsyncImageLoader( Internal::AsyncImageLoader* impl );
+  /// @endcond
 
 };
 
@@ -190,4 +242,4 @@ public: // Not intended for developer use
 
 } // namespace Dali
 
-#endif /* __DALI_TOOLKIT_ASYNC_IMAGE_LOADER_H__ */
+#endif // DALI_TOOLKIT_ASYNC_IMAGE_LOADER_H
diff --git a/dali-toolkit/public-api/image-loader/sync-image-loader.cpp b/dali-toolkit/public-api/image-loader/sync-image-loader.cpp
new file mode 100644 (file)
index 0000000..de489dc
--- /dev/null
@@ -0,0 +1,61 @@
+/*
+ * 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.
+ */
+
+// CLASS HEADER
+#include "sync-image-loader.h"
+#include <dali/devel-api/adaptor-framework/bitmap-loader.h>
+
+
+namespace Dali
+{
+
+namespace Toolkit
+{
+
+namespace SyncImageLoader
+{
+
+
+PixelData Load( const std::string& url )
+{
+  return Load( url, ImageDimensions(), FittingMode::DEFAULT, SamplingMode::BOX_THEN_LINEAR, true );
+}
+
+PixelData Load( const std::string& url, ImageDimensions dimensions )
+{
+  return Load( url, dimensions, FittingMode::DEFAULT, SamplingMode::BOX_THEN_LINEAR, true );
+}
+
+PixelData Load( const std::string& url,
+                ImageDimensions dimensions,
+                FittingMode::Type fittingMode,
+                SamplingMode::Type samplingMode,
+                bool orientationCorrection )
+{
+  BitmapLoader loader = BitmapLoader::New( url, dimensions, fittingMode, samplingMode, orientationCorrection );
+
+  // Load the image synchronously (block the thread here).
+  loader.Load();
+
+  return loader.GetPixelData();
+}
+
+
+} // namespace SyncImageLoader
+
+} // namespace Toolkit
+
+} // namespace Dali
diff --git a/dali-toolkit/public-api/image-loader/sync-image-loader.h b/dali-toolkit/public-api/image-loader/sync-image-loader.h
new file mode 100644 (file)
index 0000000..3450ba9
--- /dev/null
@@ -0,0 +1,103 @@
+#ifndef DALI_TOOLKIT_SYNC_IMAGE_LOADER_H
+#define DALI_TOOLKIT_SYNC_IMAGE_LOADER_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 <string>
+#include <dali/public-api/images/image-operations.h>
+#include <dali/public-api/images/pixel-data.h>
+
+namespace Dali
+{
+
+namespace Toolkit
+{
+
+namespace SyncImageLoader
+{
+
+/**
+ * @brief The methods in the SyncImageLoader namespace are used to load pixel data from a URL synchronously.
+ *
+ * Example:
+ *
+ * @code
+ * PixelData pixelData = Toolkit::SyncImageLoader::Load( "image_url.jpg" );
+ *
+ * // Check the image was loaded without error.
+ * if( pixelData )
+ * {
+ *   // Do work...
+ * }
+ *
+ * @endcode
+ */
+
+/**
+ * @brief Load an image synchronously.
+ * Note: When using this method, the following defaults will be used:
+ * fittingMode = FittingMode::DEFAULT
+ * samplingMode = SamplingMode::BOX_THEN_LINEAR
+ * orientationCorrection = true
+ *
+ * @SINCE_1_2_14
+ *
+ * @param[in] url The URL of the image file to load.
+ * @return A PixelData object containing the image, or an invalid object on failure.
+ */
+PixelData Load( const std::string& url );
+
+/**
+ * @brief Load an image synchronously by specifying the target dimensions.
+ * Note: When using this method, the following defaults will be used:
+ * fittingMode = FittingMode::DEFAULT
+ * samplingMode = SamplingMode::BOX_THEN_LINEAR
+ * orientationCorrection = true
+ *
+ * @SINCE_1_2_14
+ *
+ * @param[in] url The URL of the image file to load.
+ * @param[in] dimensions The width and height to fit the loaded image to.
+ * @return A PixelData object containing the image, or an invalid object on failure.
+ */
+PixelData Load( const std::string& url, ImageDimensions dimensions );
+
+/**
+ * @brief Load an image synchronously by specifying the target dimensions and options.
+ * @SINCE_1_2_14
+ *
+ * @param[in] url The URL of the image file to load.
+ * @param[in] dimensions 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.
+ * @return A PixelData object containing the image, or an invalid object on failure.
+ */
+PixelData Load( const std::string& url,
+                ImageDimensions dimensions,
+                FittingMode::Type fittingMode,
+                SamplingMode::Type samplingMode,
+                bool orientationCorrection );
+
+} // namespace SyncImageLoader
+
+} // namespace Toolkit
+
+} // namespace Dali
+
+#endif // DALI_TOOLKIT_SYNC_IMAGE_LOADER_H