utc-Dali-DebugRendering.cpp
utc-Dali-ImageAtlas.cpp
utc-Dali-VideoView.cpp
+ utc-Dali-AsyncImageLoader.cpp
)
# Append list of test harness files (Won't get parsed for test cases)
--- /dev/null
+/*
+ * 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 <toolkit-event-thread-callback.h>
+#include <dali-toolkit/devel-api/image-loader/async-image-loader.h>
+
+using namespace Dali;
+using namespace Dali::Toolkit;
+
+namespace
+{
+// resolution: 34*34, pixel format: RGBA8888
+static const char* gImage_34_RGBA = TEST_RESOURCE_DIR "/icon-edit.png";
+// 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";
+
+// for testing the ImageLoadedSignal
+class ImageLoadedSignalVerifier : public ConnectionTracker
+{
+public:
+
+ ImageLoadedSignalVerifier()
+ : mCount( 0 )
+ {}
+
+ virtual ~ImageLoadedSignalVerifier()
+ {}
+
+ void ImageLoaded( uint32_t id, PixelData pixelData )
+ {
+ mIDs.push_back( id );
+ mPixelDataList.push_back( pixelData );
+ mCount++;
+ }
+
+ int LoadedImageCount()
+ {
+ return mCount;
+ }
+
+ bool Verify( uint32_t id, uint32_t width, uint32_t height )
+ {
+ int size = mIDs.size();
+ for( int i = 0; i<size; i++ )
+ {
+ if( mIDs[i] == id )
+ {
+ return mPixelDataList[i].GetWidth() == width
+ && mPixelDataList[i].GetHeight() == height;
+ }
+ }
+
+ return false;
+ }
+
+private:
+
+ int mCount;
+
+ std::vector<uint32_t> mIDs;
+ std::vector<PixelData> mPixelDataList;
+};
+
+
+} // anonymous namespace
+
+void dali_async_image_loader_startup(void)
+{
+ test_return_value = TET_UNDEF;
+}
+
+void dali_async_image_loader_cleanup(void)
+{
+ test_return_value = TET_PASS;
+}
+
+int UtcDaliImageAtlasNew01(void)
+{
+ ToolkitTestApplication application;
+
+ //invoke default handle constructor
+ AsyncImageLoader loader;
+
+ DALI_TEST_CHECK( !loader );
+
+ // initialise handle
+ loader = AsyncImageLoader::New();
+ DALI_TEST_CHECK( loader );
+
+ END_TEST;
+}
+
+int UtcDaliAsyncImageLoaderCopyConstructor(void)
+{
+ ToolkitTestApplication application;
+
+ AsyncImageLoader loader = AsyncImageLoader::New( );
+ DALI_TEST_CHECK( loader );
+
+ AsyncImageLoader loaderCopy(loader);
+ DALI_TEST_CHECK( loaderCopy );
+
+ END_TEST;
+}
+
+int UtcDaliAsyncImageLoaderAssignmentOperator(void)
+{
+ ToolkitTestApplication application;
+
+ AsyncImageLoader loader = AsyncImageLoader::New();
+ DALI_TEST_CHECK( loader );
+
+ AsyncImageLoader loader2;
+ DALI_TEST_CHECK( !loader2 );
+
+ loader2 = loader;
+ DALI_TEST_CHECK( loader2 );
+ DALI_TEST_CHECK( loader == loader2 ); // the two handles are pointing to the same object.
+
+ END_TEST;
+}
+
+int UtcDaliAsyncImageLoaderLoadAndLoadedSignal(void)
+{
+ ToolkitTestApplication application;
+
+ AsyncImageLoader loader = AsyncImageLoader::New();
+ ImageLoadedSignalVerifier loadedSignalVerifier;
+
+ loader.ImageLoadedSignal().Connect( &loadedSignalVerifier, &ImageLoadedSignalVerifier::ImageLoaded );
+
+ loader.Load( gImage_34_RGBA );
+ 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 );
+
+ EventThreadCallback* eventTrigger = EventThreadCallback::Get();
+ CallbackBase* callback = eventTrigger->GetCallback();
+
+ eventTrigger->WaitingForTrigger( 3 );// waiting until all three images are loaded
+
+ CallbackBase::Execute( *callback );
+
+ application.SendNotification();
+ application.Render();
+
+ DALI_TEST_CHECK( loadedSignalVerifier.LoadedImageCount() == 3 );
+ DALI_TEST_CHECK( loadedSignalVerifier.Verify( id02, 25, 25 ) );
+ DALI_TEST_CHECK( loadedSignalVerifier.Verify( id03, 100, 100 ) );
+
+ END_TEST;
+}
+
+int UtcDaliAsyncImageLoaderCancel(void)
+{
+ ToolkitTestApplication application;
+
+ AsyncImageLoader loader = AsyncImageLoader::New();
+ ImageLoadedSignalVerifier loadedSignalVerifier;
+
+ loader.ImageLoadedSignal().Connect( &loadedSignalVerifier, &ImageLoadedSignalVerifier::ImageLoaded );
+
+ uint32_t id01 = loader.Load( gImage_34_RGBA, ImageDimensions( 34, 34 ) );
+ 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
+
+ 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.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
+
+ END_TEST;
+}
+
+int UtcDaliAsyncImageLoaderCancelAll(void)
+{
+ ToolkitTestApplication application;
+
+ AsyncImageLoader loader = AsyncImageLoader::New();
+ ImageLoadedSignalVerifier loadedSignalVerifier;
+
+ loader.ImageLoadedSignal().Connect( &loadedSignalVerifier, &ImageLoadedSignalVerifier::ImageLoaded );
+
+ uint32_t id01 = loader.Load( gImage_34_RGBA, ImageDimensions( 34, 34 ) );
+ uint32_t id02 = loader.Load( gImage_50_RGBA, ImageDimensions( 25, 25 ) );
+
+ // cancel the loading of the first and second image
+ loader.CancelAll();
+
+ uint32_t id03 = loader.Load( gImage_128_RGB, ImageDimensions( 100, 100 ), FittingMode::SCALE_TO_FILL, SamplingMode::BOX_THEN_LINEAR, true );
+
+ EventThreadCallback* eventTrigger = EventThreadCallback::Get();
+ CallbackBase* callback = eventTrigger->GetCallback();
+
+ eventTrigger->WaitingForTrigger( 1 );// waiting until the third images is loaded
+
+ CallbackBase::Execute( *callback );
+
+ application.SendNotification();
+ application.Render();
+
+ DALI_TEST_CHECK( loadedSignalVerifier.LoadedImageCount() == 1 );
+
+ DALI_TEST_CHECK( !loadedSignalVerifier.Verify( id01, 34, 34 ) ); // first image is not 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
+
+ END_TEST;
+}
+
+
#include <dali/dali.h>
#include <dali-toolkit-test-suite-utils.h>
#include <toolkit-event-thread-callback.h>
-#include <dali/devel-api/images/atlas.h>
-#include <dali-toolkit/devel-api/image-atlas/image-atlas.h>
+#include <dali-toolkit/devel-api/image-loader/image-atlas.h>
#include <dali-toolkit/public-api/controls/image-view/image-view.h>
using namespace Dali;
ToolkitTestApplication application;
ImageAtlas atlas = ImageAtlas::New( 32, 32 );
- Image image = atlas.GetAtlas();
+ Texture image = atlas.GetAtlas();
// test the atlas created
DALI_TEST_EQUALS( (bool)image, true, TEST_LOCATION );
DALI_TEST_CHECK( image.GetHeight() == 32u );
DALI_TEST_CHECK( image.GetWidth() == 32u );
- Atlas coreAtlas = Atlas::DownCast( image );
- DALI_TEST_EQUALS( (bool)coreAtlas, true, TEST_LOCATION );
+ END_TEST;
+}
+
+int UtcDaliImageAtlasGetOccupancyRate(void)
+{
+ ToolkitTestApplication application;
+
+ ImageAtlas atlas = ImageAtlas::New( 100, 100 );
+
+ DALI_TEST_EQUALS( atlas.GetOccupancyRate(), 0.f, TEST_LOCATION );
+
+ Vector4 textureRect1;
+ atlas.Upload( textureRect1, gImage_34_RGBA, ImageDimensions(34, 34) );
+ DALI_TEST_EQUALS( atlas.GetOccupancyRate(), 34.f*34.f/10000.f, 0.001f, TEST_LOCATION );
+
+ Vector4 textureRect2;
+ atlas.Upload( textureRect2, gImage_50_RGBA, ImageDimensions(50, 50) );
+ DALI_TEST_EQUALS( atlas.GetOccupancyRate(), (34.f*34.f+50.f*50.f)/10000.f, 0.001f, TEST_LOCATION );
END_TEST;
}
unsigned int size = 200;
ImageAtlas atlas = ImageAtlas::New( size, size );
- EventThreadCallback* eventTrigger = EventThreadCallback::Get();
- CallbackBase* callback = eventTrigger->GetCallback();
-
TraceCallStack& callStack = application.GetGlAbstraction().GetTextureTrace();
callStack.Reset();
callStack.Enable(true);
Vector4 textureRect3;
atlas.Upload( textureRect3, gImage_128_RGB, ImageDimensions(128, 128) );
+ EventThreadCallback* eventTrigger = EventThreadCallback::Get();
+ CallbackBase* callback = eventTrigger->GetCallback();
+
eventTrigger->WaitingForTrigger( 3 );// waiting until all three images are loaded
CallbackBase::Execute( *callback );
loader.WaitForLoading();// waiting until the image to be loaded
DALI_TEST_CHECK( loader.IsLoaded() );
+ eventTrigger->WaitingForTrigger( 1 );
CallbackBase* callback = eventTrigger->GetCallback();
CallbackBase::Execute( *callback );
develapishadowviewdir = $(develapicontrolsdir)/shadow-view
develapisuperblurviewdir = $(develapicontrolsdir)/super-blur-view
develapifocusmanagerdir = $(develapidir)/focus-manager
-develapiimageatlasdir = $(develapidir)/image-atlas
+develapiimageloaderdir = $(develapidir)/image-loader
develapiscriptingdir = $(develapidir)/scripting
develapishadereffectsdir = $(develapidir)/shader-effects
develapitransitioneffectsdir = $(develapidir)/transition-effects
develapieffectsview_HEADERS = $(devel_api_effects_view_header_files)
develapifocusmanager_HEADERS = $(devel_api_focus_manager_header_files)
develapigaussianblurview_HEADERS = $(devel_api_gaussian_blur_view_header_files)
-develapiimageatlas_HEADERS = $(devel_api_image_atlas_header_files)
+develapiimageloader_HEADERS = $(devel_api_image_loader_header_files)
develapimagnifier_HEADERS = $(devel_api_magnifier_header_files)
develapipageturnview_HEADERS = $(devel_api_page_turn_view_header_files)
develapipopup_HEADERS = $(devel_api_popup_header_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-atlas/image-atlas.cpp \
+ $(devel_api_src_dir)/image-loader/async-image-loader.cpp \
+ $(devel_api_src_dir)/image-loader/image-atlas.cpp \
$(devel_api_src_dir)/scripting/script.cpp \
$(devel_api_src_dir)/transition-effects/cube-transition-cross-effect.cpp \
$(devel_api_src_dir)/transition-effects/cube-transition-effect.cpp \
devel_api_focus_manager_header_files = \
$(devel_api_src_dir)/focus-manager/keyinput-focus-manager.h
-devel_api_image_atlas_header_files = \
- $(devel_api_src_dir)/image-atlas/image-atlas.h
+devel_api_image_loader_header_files = \
+ $(devel_api_src_dir)/image-loader/async-image-loader.h \
+ $(devel_api_src_dir)/image-loader/image-atlas.h
devel_api_scripting_header_files = \
$(devel_api_src_dir)/scripting/script.h \
--- /dev/null
+/*
+ * 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 "async-image-loader.h"
+
+// INTERNAL INCLUDES
+#include <dali-toolkit/internal/image-loader/async-image-loader-impl.h>
+
+namespace Dali
+{
+
+namespace Toolkit
+{
+
+AsyncImageLoader::AsyncImageLoader()
+{
+}
+
+AsyncImageLoader::~AsyncImageLoader()
+{
+}
+
+AsyncImageLoader::AsyncImageLoader( Internal::AsyncImageLoader* impl )
+: BaseHandle( impl )
+{}
+
+AsyncImageLoader::AsyncImageLoader( const AsyncImageLoader& handle )
+: BaseHandle( handle )
+{
+}
+
+AsyncImageLoader& AsyncImageLoader::operator=( const AsyncImageLoader& handle )
+{
+ BaseHandle::operator=(handle);
+ return *this;
+}
+
+AsyncImageLoader AsyncImageLoader::New()
+{
+ IntrusivePtr<Internal::AsyncImageLoader> internal = Internal::AsyncImageLoader::New();
+ return AsyncImageLoader( internal.Get() );
+}
+
+uint32_t AsyncImageLoader::Load( const std::string& url )
+{
+ return GetImplementation(*this).Load( url, ImageDimensions(), FittingMode::DEFAULT, SamplingMode::BOX_THEN_LINEAR, true );
+}
+
+uint32_t AsyncImageLoader::Load( const std::string& url, ImageDimensions size )
+{
+ return GetImplementation(*this).Load( url, size, FittingMode::DEFAULT, SamplingMode::BOX_THEN_LINEAR, true );
+}
+
+uint32_t AsyncImageLoader::Load( const std::string& url,
+ ImageDimensions size,
+ FittingMode::Type fittingMode,
+ SamplingMode::Type samplingMode,
+ bool orientationCorrection )
+{
+ return GetImplementation(*this).Load( url, size, fittingMode, samplingMode, orientationCorrection );
+}
+
+bool AsyncImageLoader::Cancel( uint32_t loadingTaskId)
+{
+ return GetImplementation(*this).Cancel( loadingTaskId );
+}
+
+void AsyncImageLoader::CancelAll()
+{
+ GetImplementation(*this).CancelAll();
+}
+
+AsyncImageLoader::ImageLoadedSignalType& AsyncImageLoader::ImageLoadedSignal()
+{
+ return GetImplementation(*this).ImageLoadedSignal();
+}
+} // namespace Toolkit
+
+} // namespace Dali
--- /dev/null
+#ifndef __DALI_TOOLKIT_ASYNC_IMAGE_LOADER_H__
+#define __DALI_TOOLKIT_ASYNC_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/object/base-handle.h>
+#include <dali/public-api/images/image-operations.h>
+#include <dali/public-api/signals/dali-signal.h>
+
+namespace Dali
+{
+class PixelData;
+
+namespace Toolkit
+{
+
+namespace Internal DALI_INTERNAL
+{
+class AsyncImageLoader;
+}
+
+/**
+ *@brief The AysncImageLoader is used to load pixel data from the 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 make sure the signal is always received, the signal should get connected before invoking the load call.
+ * @code
+ * class MyClass : public ConnectionTracker
+ * {
+ * public:
+ *
+ * MyCallback( uint32_t id, PixelData pixelData)
+ * {
+ * if(id == mId1)
+ * {
+ * // use the loaded pixel data from the first image
+ * }
+ * else if( id == mId2 )
+ * {
+ * // use the loaded pixel data from the second image
+ * }
+ * }
+ *
+ * uint32_t mId1;
+ * uint32_t mId2;
+ * };
+ *
+ * MyClass myObject;
+ * AsyncImageLoader imageLoader = AsyncImageLoader::New();
+ * // 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" );
+ *
+ * @endcode
+ */
+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;
+
+public:
+
+ /**
+ * @brief Constructor which creates an empty AsyncImageLoader handle.
+ *
+ * Use AsyncImageLoader::New() to create an initialised object.
+ */
+ AsyncImageLoader();
+
+ /**
+ * @brief Destructor
+ *
+ * This is non-virtual since derived Handle types must not contain data or virtual methods.
+ */
+ ~AsyncImageLoader();
+
+ /**
+ * @brief This copy constructor is required for (smart) pointer semantics.
+ *
+ * @param [in] handle A reference to the copied handle
+ */
+ AsyncImageLoader( const AsyncImageLoader& handle );
+
+ /**
+ * @brief This assignment operator is required for (smart) pointer semantics.
+ *
+ * @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.
+ */
+ static AsyncImageLoader New();
+
+ /**
+ * @brief Start a image loading task.
+ *
+ * @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.
+ *
+ * @param[in] url The URL of the image file to load.
+ * @param[in] size The width and height to fit the loaded image to.
+ * @return The loading task id.
+ */
+ uint32_t Load( const std::string& url, ImageDimensions size );
+
+ /*
+ * @brief Start a image loading task.
+ *
+ * @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.
+ * @return The loading task id.
+ */
+ uint32_t Load( const std::string& url,
+ ImageDimensions size,
+ FittingMode::Type fittingMode,
+ SamplingMode::Type samplingMode,
+ bool orientationCorrection );
+
+ /**
+ * @brief Cancel a image loading task if it is still queuing in the work thread.
+ *
+ * @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);
+
+ /**
+ * @brief Cancel all the loading tasks in the queue
+ */
+ void CancelAll();
+
+ /**
+ * @brief Signal emit for connected callback functions to get access to the loaded pixel data.
+ *
+ * A callback of the following type may be connected:
+ * @code
+ * void YourCallbackName( uint32_t id, PixelData pixelData );
+ * @endcode
+ *
+ * @return A signal object to Connect() with.
+ */
+ ImageLoadedSignalType& ImageLoadedSignal();
+
+public: // Not intended for developer use
+
+ explicit DALI_INTERNAL AsyncImageLoader( Internal::AsyncImageLoader* impl );
+
+};
+
+} // namespace Toolkit
+
+} // namespace Dali
+
+#endif /* __DALI_TOOLKIT_ASYNC_IMAGE_LOADER_H__ */
#include "image-atlas.h"
// INTERNAL INCLUDES
-#include <dali-toolkit/internal/image-atlas/image-atlas-impl.h>
+#include <dali-toolkit/internal/image-loader/image-atlas-impl.h>
namespace Dali
{
return ImageAtlas( internal.Get() );
}
-Image ImageAtlas::GetAtlas()
+Texture ImageAtlas::GetAtlas()
{
return GetImplementation( *this ).GetAtlas();
}
+float ImageAtlas::GetOccupancyRate() const
+{
+ return GetImplementation( *this ).GetOccupancyRate();
+}
+
+
void ImageAtlas::SetBrokenImage( const std::string& brokenImageUrl )
{
GetImplementation( *this ).SetBrokenImage( brokenImageUrl );
#include <string>
#include <stdint.h>
#include <dali/public-api/object/base-handle.h>
-#include <dali/public-api/images/image.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/rendering/texture.h>
namespace Dali
{
}
/**
- * @brief An ImageAtlas is a large image containing multiple smaller images.
+ * @brief An ImageAtlas is a large texture containing multiple smaller images.
*
- * Only images with url provided are supported for uploading.
- * The image are loaded by a worker thread to avoid blocking the main event thread.
+ * Only images with url provided or pixel data are supported for uploading.
+ * The images are loaded by a worker thread to avoid blocking the main event thread.
*/
class DALI_IMPORT_API ImageAtlas : public BaseHandle
{
/**
* @brief Get the atlas image.
*
- * This atlas image is still valid after destroying the ImageAtlas object.
+ * This atlas texture is still valid after destroying the ImageAtlas object.
*
- * @return the atlas image with type of Dali::Atlas
+ * @return The atlas texture
*/
- Image GetAtlas();
+ Texture GetAtlas();
+
+ /*
+ * @brief Query what percentage of space is been occupied in the atlas.
+ *
+ * @return The occupancy rate of the atlas.
+ */
+ float GetOccupancyRate() const;
/**
* @brief Set the broken image which is used to replace the image if loading fails.
$(toolkit_src_dir)/filters/emboss-filter.cpp \
$(toolkit_src_dir)/filters/image-filter.cpp \
$(toolkit_src_dir)/filters/spread-filter.cpp \
- $(toolkit_src_dir)/image-atlas/atlas-packer.cpp \
- $(toolkit_src_dir)/image-atlas/image-atlas-impl.cpp \
- $(toolkit_src_dir)/image-atlas/image-load-thread.cpp \
+ $(toolkit_src_dir)/image-loader/async-image-loader-impl.cpp \
+ $(toolkit_src_dir)/image-loader/atlas-packer.cpp \
+ $(toolkit_src_dir)/image-loader/image-atlas-impl.cpp \
+ $(toolkit_src_dir)/image-loader/image-load-thread.cpp \
$(toolkit_src_dir)/styling/style-manager-impl.cpp \
$(toolkit_src_dir)/text/bidirectional-support.cpp \
$(toolkit_src_dir)/text/character-set-conversion.cpp \
--- /dev/null
+/*
+ * 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 "async-image-loader-impl.h"
+
+// EXTERNAL INCLUDES
+#include <dali/devel-api/adaptor-framework/bitmap-loader.h>
+#include <dali/integration-api/adaptors/adaptor.h>
+
+namespace Dali
+{
+
+namespace Toolkit
+{
+
+namespace Internal
+{
+
+AsyncImageLoader::AsyncImageLoader()
+: mLoadedSignal(),
+ mLoadThread( new EventThreadCallback( MakeCallback( this, &AsyncImageLoader::ProcessLoadedImage ) ) ),
+ mLoadTaskId( 0 ),
+ mIsLoadThreadStarted( false )
+{
+}
+
+AsyncImageLoader::~AsyncImageLoader()
+{
+ mLoadThread.CancelAll();
+}
+
+IntrusivePtr<AsyncImageLoader> AsyncImageLoader::New()
+{
+ IntrusivePtr<AsyncImageLoader> internal = new AsyncImageLoader();
+ return internal;
+}
+
+uint32_t AsyncImageLoader::Load( const std::string& url,
+ ImageDimensions size,
+ FittingMode::Type fittingMode,
+ SamplingMode::Type samplingMode,
+ bool orientationCorrection )
+{
+ if( !mIsLoadThreadStarted )
+ {
+ mLoadThread.Start();
+ mIsLoadThreadStarted = true;
+ }
+
+ BitmapLoader loader = BitmapLoader::New( url, size, fittingMode, samplingMode, orientationCorrection );
+
+ mLoadThread.AddTask( new LoadingTask( ++mLoadTaskId, loader ) );
+
+ return mLoadTaskId;
+}
+
+Toolkit::AsyncImageLoader::ImageLoadedSignalType& AsyncImageLoader::ImageLoadedSignal()
+{
+ return mLoadedSignal;
+}
+
+bool AsyncImageLoader::Cancel( uint32_t loadingTaskId )
+{
+ return mLoadThread.CancelTask( loadingTaskId );
+}
+
+void AsyncImageLoader::CancelAll()
+{
+ mLoadThread.CancelAll();
+}
+
+void AsyncImageLoader::ProcessLoadedImage()
+{
+ while( LoadingTask *next = mLoadThread.NextCompletedTask() )
+ {
+ mLoadedSignal.Emit( next->id, next->loader.GetPixelData() );
+ delete next;
+ }
+}
+
+} // namespace Internal
+
+} // namespace Toolkit
+
+} // namespace Dali
--- /dev/null
+#ifndef DALI_TOOLKIT_ASYNC_IMAGE_LOADER_IMPL_H__
+#define DALI_TOOLKIT_ASYNC_IMAGE_LOADER_IMPL_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/images/pixel-data.h>
+#include <dali/public-api/object/base-object.h>
+
+// INTERNAL INCLUDES
+#include <dali-toolkit/devel-api/image-loader/async-image-loader.h>
+#include <dali-toolkit/internal/image-loader/image-load-thread.h>
+
+namespace Dali
+{
+
+namespace Toolkit
+{
+
+namespace Internal
+{
+
+class AsyncImageLoader : public BaseObject
+{
+public:
+
+ /**
+ * Constructor
+ */
+ AsyncImageLoader();
+
+ /**
+ * @copydoc Toolkit::AsyncImageLoader::New()
+ */
+ static IntrusivePtr<AsyncImageLoader> New();
+
+ /**
+ * @copydoc Toolkit::AsyncImageLoader::Load( const std::string&, ImageDimensions,FittingMode::Type, SamplingMode::Type, bool )
+ */
+ uint32_t Load( const std::string& url,
+ ImageDimensions size,
+ FittingMode::Type fittingMode,
+ SamplingMode::Type samplingMode,
+ bool orientationCorrection );
+
+ /**
+ * @copydoc Toolkit::AsyncImageLoader::ImageLoadedSignal
+ */
+ Toolkit::AsyncImageLoader::ImageLoadedSignalType& ImageLoadedSignal();
+
+ /**
+ * @copydoc Toolkit::AsyncImageLoader::Cancel
+ */
+ bool Cancel( uint32_t loadingTaskId );
+
+ /**
+ * @copydoc Toolkit::AsyncImageLoader::CancelAll
+ */
+ void CancelAll();
+
+ /**
+ * Process the completed loading task from the worker thread.
+ */
+ void ProcessLoadedImage();
+
+protected:
+
+ /**
+ * Destructor
+ */
+ ~AsyncImageLoader();
+
+private:
+
+ Toolkit::AsyncImageLoader::ImageLoadedSignalType mLoadedSignal;
+
+ ImageLoadThread mLoadThread;
+ uint32_t mLoadTaskId;
+ bool mIsLoadThreadStarted;
+
+
+};
+
+} // namespace Internal
+
+inline const Internal::AsyncImageLoader& GetImplementation( const Toolkit::AsyncImageLoader& loader )
+{
+ DALI_ASSERT_ALWAYS( loader && "AsyncImageLoader handle is empty" );
+
+ const BaseObject& object = loader.GetBaseObject();
+
+ return static_cast<const Internal::AsyncImageLoader&>( object );
+}
+
+inline Internal::AsyncImageLoader& GetImplementation( Toolkit::AsyncImageLoader& loader )
+{
+ DALI_ASSERT_ALWAYS( loader && "AsyncImageLoader handle is empty" );
+
+ BaseObject& object = loader.GetBaseObject();
+
+ return static_cast<Internal::AsyncImageLoader&>( object );
+}
+
+} // namespace Toolkit
+
+} // namespace Dali
+
+#endif /* DALI_TOOLKIT_ASYNC_IMAGE_LOADER_IMPL_H__ */
AtlasPacker::Node* AtlasPacker::SearchNode( Node* node, SizeType packPositionX, SizeType packPositionY, SizeType blockWidth, SizeType blockHeight )
{
- if( node == NULL )
- {
- return NULL;
- }
-
- if( node->child[0] != NULL) //not a leaf
+ if( node != NULL )
{
- Node* newNode = SearchNode(node->child[0], packPositionX, packPositionY, blockWidth, blockHeight);
- if( newNode == NULL )// try search from the second child.
+ if( node->child[0] != NULL) //not a leaf
{
- newNode = SearchNode(node->child[1], packPositionX, packPositionY, blockWidth, blockHeight);
+ Node* newNode = SearchNode(node->child[0], packPositionX, packPositionY, blockWidth, blockHeight);
+ if( newNode == NULL )// try search from the second child.
+ {
+ newNode = SearchNode(node->child[1], packPositionX, packPositionY, blockWidth, blockHeight);
+ }
+ return newNode;
+ }
+ else if( ApproximatelyEqual(node->rectArea.x, packPositionX) && ApproximatelyEqual(node->rectArea.y, packPositionY )
+ && ApproximatelyEqual(node->rectArea.width, blockWidth) && ApproximatelyEqual( node->rectArea.height, blockHeight) )
+ {
+ return node;
}
- return newNode;
- }
- else if( ApproximatelyEqual(node->rectArea.x, packPositionX) && ApproximatelyEqual(node->rectArea.y, packPositionY )
- && ApproximatelyEqual(node->rectArea.width, blockWidth) && ApproximatelyEqual( node->rectArea.height, blockHeight) )
- {
- return node;
}
return NULL;
/*
- * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ * 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.
#include <string.h>
#include <dali/public-api/signals/callback.h>
#include <dali/public-api/images/resource-image.h>
+#include <dali/devel-api/adaptor-framework/bitmap-loader.h>
#include <dali/integration-api/debug.h>
namespace Dali
{
ImageAtlas::ImageAtlas( SizeType width, SizeType height, Pixel::Format pixelFormat )
-: mPacker( width, height ),
- mLoadQueue(),
- mCompleteQueue( new EventThreadCallback( MakeCallback( this, &ImageAtlas::UploadToAtlas ) ) ),
- mLoadingThread( mLoadQueue, mCompleteQueue ),
+: mAtlas( Texture::New( Dali::TextureType::TEXTURE_2D, pixelFormat, width, height ) ),
+ mPacker( width, height ),
+ mAsyncLoader( Toolkit::AsyncImageLoader::New() ),
mBrokenImageUrl(""),
mBrokenImageSize(),
- mPixelFormat( pixelFormat ),
- mLoadingThreadStarted( false )
+ mWidth( static_cast<float>(width) ),
+ mHeight( static_cast<float>( height ) ),
+ mPixelFormat( pixelFormat )
{
- mAtlas = Atlas::New( width, height, pixelFormat );
- mWidth = static_cast<float>(width);
- mHeight = static_cast<float>( height );
+ mAsyncLoader.ImageLoadedSignal().Connect( this, &ImageAtlas::UploadToAtlas );
}
ImageAtlas::~ImageAtlas()
{
- if( mLoadingThreadStarted )
- {
- // add an empty task would stop the loading thread from contional wait.
- mLoadQueue.AddTask( NULL );
- // stop the loading thread
- mLoadingThread.Join();
- // The atlas can still be used as texture after ImageAtlas has been thrown away,
- // so make sure all the loaded bitmap been uploaded to atlas
- UploadToAtlas();
- }
+ mIdRectContainer.Clear();
}
IntrusivePtr<ImageAtlas> ImageAtlas::New( SizeType width, SizeType height, Pixel::Format pixelFormat )
{
IntrusivePtr<ImageAtlas> internal = new ImageAtlas( width, height, pixelFormat );
+
return internal;
}
-Image ImageAtlas::GetAtlas()
+Texture ImageAtlas::GetAtlas()
{
return mAtlas;
}
+float ImageAtlas::GetOccupancyRate() const
+{
+ return 1.f - static_cast<float>( mPacker.GetAvailableArea() ) / ( mWidth*mHeight );
+}
+
void ImageAtlas::SetBrokenImage( const std::string& brokenImageUrl )
{
mBrokenImageSize = ResourceImage::GetImageSize( brokenImageUrl );
}
}
- if( static_cast<unsigned int>(dimensions.GetWidth() * dimensions.GetHeight()) > mPacker.GetAvailableArea() )
- {
- return false;
- }
-
unsigned int packPositionX = 0;
unsigned int packPositionY = 0;
if( mPacker.Pack( dimensions.GetWidth(), dimensions.GetHeight(), packPositionX, packPositionY ) )
{
- if( !mLoadingThreadStarted )
- {
- mLoadingThread.Start();
- mLoadingThreadStarted = true;
- }
-
- LoadingTask* newTask = new LoadingTask(BitmapLoader::New(url, size, fittingMode, SamplingMode::BOX_THEN_LINEAR, orientationCorrection ),
- packPositionX, packPositionY, dimensions.GetWidth(), dimensions.GetHeight());
- mLoadQueue.AddTask( newTask );
+ unsigned short loadId = mAsyncLoader.Load( url, size, fittingMode, SamplingMode::BOX_THEN_LINEAR, orientationCorrection );
+ mIdRectContainer.PushBack( new IdRectPair( loadId, packPositionX, packPositionY, dimensions.GetWidth(), dimensions.GetHeight() ) );
// apply the half pixel correction
textureRect.x = ( static_cast<float>( packPositionX ) +0.5f ) / mWidth; // left
unsigned int packPositionY = 0;
if( mPacker.Pack( pixelData.GetWidth(), pixelData.GetHeight(), packPositionX, packPositionY ) )
{
- mAtlas.Upload( pixelData, packPositionX, packPositionY );
+ mAtlas.Upload( pixelData, 0u, 0u, packPositionX, packPositionY, pixelData.GetWidth(), pixelData.GetHeight() );
// apply the half pixel correction
textureRect.x = ( static_cast<float>( packPositionX ) +0.5f ) / mWidth; // left
static_cast<SizeType>((textureRect.w-textureRect.y)*mHeight+1.f) );
}
-void ImageAtlas::UploadToAtlas()
+void ImageAtlas::UploadToAtlas( unsigned int id, PixelData pixelData )
{
- while( LoadingTask* next = mCompleteQueue.NextTask() )
+ if( mIdRectContainer[0]->loadTaskId == id)
{
- if( ! next->loader.IsLoaded() )
+ if( !pixelData || ( pixelData.GetWidth() ==0 && pixelData.GetHeight() == 0 ))
{
if(!mBrokenImageUrl.empty()) // replace with the broken image
{
- UploadBrokenImage( next->packRect );
+ UploadBrokenImage( mIdRectContainer[0]->packRect );
}
-
- DALI_LOG_ERROR( "Failed to load the image: %s\n", (next->loader.GetUrl()).c_str());
}
else
{
- if( next->loader.GetPixelData().GetWidth() < next->packRect.width || next->loader.GetPixelData().GetHeight() < next->packRect.height )
+ if( pixelData.GetWidth() < mIdRectContainer[0]->packRect.width || pixelData.GetHeight() < mIdRectContainer[0]->packRect.height )
{
DALI_LOG_ERROR( "Can not upscale the image from actual loaded size [ %d, %d ] to specified size [ %d, %d ]\n",
- next->loader.GetPixelData().GetWidth(),
- next->loader.GetPixelData().GetHeight(),
- next->packRect.width,
- next->packRect.height );
+ pixelData.GetWidth(), pixelData.GetHeight(),
+ mIdRectContainer[0]->packRect.width, mIdRectContainer[0]->packRect.height );
}
- mAtlas.Upload( next->loader.GetPixelData(), next->packRect.x, next->packRect.y );
+ mAtlas.Upload( pixelData, 0u, 0u,
+ mIdRectContainer[0]->packRect.x, mIdRectContainer[0]->packRect.y,
+ mIdRectContainer[0]->packRect.width, mIdRectContainer[0]->packRect.height );
}
-
- delete next;
}
+
+ mIdRectContainer.Erase( mIdRectContainer.Begin() );
}
-void ImageAtlas::UploadBrokenImage( const Rect<SizeType>& area )
+void ImageAtlas::UploadBrokenImage( const Rect<unsigned int>& area )
{
BitmapLoader loader = BitmapLoader::New(mBrokenImageUrl, ImageDimensions( area.width, area.height ) );
loader.Load();
{
buffer[idx] = 0x00;
}
- mAtlas.Upload( background, area.x, area.y );
+ mAtlas.Upload( background, 0u, 0u, area.x, area.y, area.width, area.height );
}
- mAtlas.Upload( loader.GetPixelData(), packX, packY );
+ mAtlas.Upload( loader.GetPixelData(), 0u, 0u, packX, packY, loadedWidth, loadedHeight );
}
} // namespace Internal
// EXTERNAL INCLUDES
#include <dali/public-api/common/intrusive-ptr.h>
#include <dali/public-api/object/base-object.h>
+#include <dali/public-api/signals/connection-tracker.h>
+#include <dali/devel-api/common/owner-container.h>
#include <dali/devel-api/images/atlas.h>
// INTERNAL INCLUDES
-#include <dali-toolkit/devel-api/image-atlas/image-atlas.h>
-#include <dali-toolkit/internal/image-atlas/atlas-packer.h>
-#include <dali-toolkit/internal/image-atlas/image-load-thread.h>
+#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>
namespace Dali
{
namespace Internal
{
-class ImageAtlas : public BaseObject
+class ImageAtlas : public BaseObject, public ConnectionTracker
{
public:
/**
* @copydoc Toolkit::ImageAtlas::GetAtlas
*/
- Image GetAtlas();
+ Texture GetAtlas();
+
+ /**
+ * @copydoc Toolkit::ImageAtlas::GetOccupancyRate
+ */
+ float GetOccupancyRate() const;
/**
* @copydoc Toolkit::ImageAtlas::SetBrokenImage
private:
/**
- * Upload the bitmap to atlas when the image is loaded in the worker thread.
+ * @copydoc PixelDataRequester::ProcessPixels
*/
- void UploadToAtlas();
+ void UploadToAtlas( unsigned int id, PixelData pixelData );
/**
* Upload broken image
*
* @param[in] area The pixel area for uploading.
*/
- void UploadBrokenImage( const Rect<SizeType>& area );
+ void UploadBrokenImage( const Rect<unsigned int>& area );
// Undefined
ImageAtlas( const ImageAtlas& imageAtlas);
private:
- Atlas mAtlas;
- AtlasPacker mPacker;
-
- LoadQueue mLoadQueue;
- CompleteQueue mCompleteQueue;
- ImageLoadThread mLoadingThread;
-
- std::string mBrokenImageUrl;
- ImageDimensions mBrokenImageSize;
- float mWidth;
- float mHeight;
- Pixel::Format mPixelFormat;
- bool mLoadingThreadStarted;
+ struct IdRectPair
+ {
+ IdRectPair( unsigned short loadTaskId,
+ unsigned int packPositionX,
+ unsigned int packPositionY,
+ unsigned int width,
+ unsigned int height )
+ : loadTaskId( loadTaskId ),
+ packRect( packPositionX, packPositionY, width, height )
+ {}
+
+ unsigned short loadTaskId;
+ Rect<unsigned int> packRect;
+ };
+
+ OwnerContainer<IdRectPair*> mIdRectContainer;
+
+ Texture mAtlas;
+ AtlasPacker mPacker;
+ Toolkit::AsyncImageLoader mAsyncLoader;
+ std::string mBrokenImageUrl;
+ ImageDimensions mBrokenImageSize;
+ float mWidth;
+ float mHeight;
+ Pixel::Format mPixelFormat;
};
namespace Internal
{
-LoadingTask::LoadingTask(BitmapLoader loader, uint32_t packPositionX, uint32_t packPositionY, uint32_t width, uint32_t height )
+LoadingTask::LoadingTask(uint32_t id, BitmapLoader loader )
: loader( loader ),
- packRect( packPositionX, packPositionY, width, height )
+ id( id )
{
}
-LoadQueue::LoadQueue()
+ImageLoadThread::ImageLoadThread( EventThreadCallback* trigger )
+: mTrigger( trigger )
{
}
-LoadQueue::~LoadQueue()
+ImageLoadThread::~ImageLoadThread()
{
+ // add an empty task would stop the thread from conditional wait.
+ AddTask( NULL );
+ // stop the thread
+ Join();
+
+ delete mTrigger;
}
-LoadingTask* LoadQueue::NextTask()
+void ImageLoadThread::Run()
{
- // Lock while popping task out from the queue
- ConditionalWait::ScopedLock lock( mConditionalWait );
-
- while( mTasks.Empty() )
+ while( LoadingTask* task = NextTaskToProcess())
{
- mConditionalWait.Wait( lock );
+ task->loader.Load();
+ AddCompletedTask( task );
}
-
- Vector< LoadingTask* >::Iterator next = mTasks.Begin();
- LoadingTask* nextTask = *next;
- mTasks.Erase( next );
-
- return nextTask;
}
-void LoadQueue::AddTask( LoadingTask* task )
+void ImageLoadThread::AddTask( LoadingTask* task )
{
bool wasEmpty = false;
{
// Lock while adding task to the queue
ConditionalWait::ScopedLock lock( mConditionalWait );
- wasEmpty = mTasks.Empty();
- mTasks.PushBack( task );
+ wasEmpty = mLoadQueue.Empty();
+ mLoadQueue.PushBack( task );
}
if( wasEmpty)
}
}
-CompleteQueue::CompleteQueue(EventThreadCallback* trigger)
-: mTrigger( trigger )
-{}
-
-CompleteQueue::~CompleteQueue()
-{
- delete mTrigger;
-}
-
-LoadingTask* CompleteQueue::NextTask()
+LoadingTask* ImageLoadThread::NextCompletedTask()
{
// Lock while popping task out from the queue
Mutex::ScopedLock lock( mMutex );
- if( mTasks.Empty() )
+ if( mCompleteQueue.Empty() )
{
return NULL;
}
- Vector< LoadingTask* >::Iterator next = mTasks.Begin();
+ Vector< LoadingTask* >::Iterator next = mCompleteQueue.Begin();
LoadingTask* nextTask = *next;
- mTasks.Erase( next );
+ mCompleteQueue.Erase( next );
return nextTask;
}
-void CompleteQueue::AddTask( LoadingTask* task )
+bool ImageLoadThread::CancelTask( uint32_t loadingTaskId )
{
- // Lock while adding task to the queue
- Mutex::ScopedLock lock( mMutex );
- mTasks.PushBack( task );
+ // Lock while remove task from the queue
+ ConditionalWait::ScopedLock lock( mConditionalWait );
- // wake up the main thread
- mTrigger->Trigger();
+ for( Vector< LoadingTask* >::Iterator iter = mLoadQueue.Begin(); iter != mLoadQueue.End(); iter++ )
+ {
+ if( (*iter)->id == loadingTaskId )
+ {
+ delete (*iter);
+ mLoadQueue.Erase( iter );
+ return true;
+ }
+ }
+
+ return false;
}
-ImageLoadThread::ImageLoadThread( LoadQueue& loadQueue, CompleteQueue& completeQueue )
-: mLoadQueue( loadQueue ),
- mCompleteQueue( completeQueue )
+void ImageLoadThread::CancelAll()
{
-}
+ // Lock while remove task from the queue
+ ConditionalWait::ScopedLock lock( mConditionalWait );
-ImageLoadThread::~ImageLoadThread()
-{
+ for( Vector< LoadingTask* >::Iterator iter = mLoadQueue.Begin(); iter != mLoadQueue.End(); iter++ )
+ {
+ delete (*iter);
+ }
+ mLoadQueue.Clear();
}
-void ImageLoadThread::Run()
+LoadingTask* ImageLoadThread::NextTaskToProcess()
{
- while( LoadingTask* task = mLoadQueue.NextTask() )
+ // Lock while popping task out from the queue
+ ConditionalWait::ScopedLock lock( mConditionalWait );
+
+ while( mLoadQueue.Empty() )
{
- task->loader.Load();
- mCompleteQueue.AddTask( task );
+ mConditionalWait.Wait( lock );
}
+
+ Vector< LoadingTask* >::Iterator next = mLoadQueue.Begin();
+ LoadingTask* nextTask = *next;
+ mLoadQueue.Erase( next );
+
+ return nextTask;
}
+void ImageLoadThread::AddCompletedTask( LoadingTask* task )
+{
+ // Lock while adding task to the queue
+ Mutex::ScopedLock lock( mMutex );
+ mCompleteQueue.PushBack( task );
+
+ // wake up the main thread
+ mTrigger->Trigger();
+}
+
+
+
} // namespace Internal
} // namespace Toolkit
/**
* Constructor.
*/
- LoadingTask( BitmapLoader loader, uint32_t packPositionX, uint32_t packPositionY, uint32_t width, uint32_t height );
+ LoadingTask( uint32_t id, BitmapLoader loader );
private:
public:
- BitmapLoader loader; ///< The loader used to load the bitmap from URL
- Rect<uint32_t> packRect; ///< The x coordinate of the position to pack the image.
-
+ BitmapLoader loader; ///< The loader used to load the bitmap from URL
+ uint32_t id; ///< The id associated with this task.
};
+
/**
- * The queue of the tasks waiting to load the bitmap from the URL in the worker thread/
+ * The worker thread for image loading.
*/
-class LoadQueue //: public TaskQueue
+class ImageLoadThread : public Thread
{
public:
/**
- * Constructor
+ * Constructor.
+ *
+ * @param[in] mTrigger The trigger to wake up the main thread.
*/
- LoadQueue();
+ ImageLoadThread( EventThreadCallback* mTrigger );
/**
* Destructor.
*/
- ~LoadQueue();
-
- /**
- * Pop the next task out from the queue.
- *
- * @return The next task to be processed.
- */
- LoadingTask* NextTask();
+ virtual ~ImageLoadThread();
/**
- * Add a task in to the queue
+ * Add a task in to the loading queue
*
* @param[in] task The task added to the queue.
*/
void AddTask( LoadingTask* task );
-private:
-
- // Undefined
- LoadQueue( const LoadQueue& queue );
-
- // Undefined
- LoadQueue& operator=( const LoadQueue& queue );
-
-private:
-
- Vector< LoadingTask* > mTasks;
- ConditionalWait mConditionalWait;
-};
-
-/**
- * The queue of the tasks, with the image loaded, waiting for the main thread to upload the bitmap.
- */
-class CompleteQueue //: public TaskQueue
-{
-public:
-
/**
- * Constructor
+ * Pop the next task out from the completed queue.
*
- * @param[in] mTrigger The trigger to wake up the main thread.
- */
- CompleteQueue( EventThreadCallback* mTrigger );
-
- /**
- * Destructor.
+ * @return The next task to be processed.
*/
- ~CompleteQueue();
+ LoadingTask* NextCompletedTask();
/**
- * Pop the next task out from the queue.
- *
- * @return The next task to be processed.
+ * Remove the loading task from the waiting queue.
*/
- LoadingTask* NextTask();
+ bool CancelTask( uint32_t loadingTaskId );
/**
- * Add a task in to the queue
- *
- * @param[in] task The task added to the queue.
+ * Remove all the loading tasks in the waiting queue.
*/
- void AddTask( LoadingTask* task );
-
-private:
-
- // Undefined
- CompleteQueue( const CompleteQueue& queue );
-
- // Undefined
- CompleteQueue& operator=( const CompleteQueue& queue );
+ void CancelAll();
private:
- Vector< LoadingTask* > mTasks;
- Dali::Mutex mMutex;
- EventThreadCallback* mTrigger;
-};
-
-/**
- * The worker thread for image loading.
- */
-class ImageLoadThread : public Thread
-{
-public:
-
/**
- * Constructor.
+ * Pop the next loading task out from the queue to process.
*
- * @param[in] loadQueue The task queue with images for loading.
- * @param[in] completeQurue The task queue with images loaded.
+ * @return The next task to be processed.
*/
- ImageLoadThread( LoadQueue& loadQueue, CompleteQueue& completeQueue );
+ LoadingTask* NextTaskToProcess();
/**
- * Destructor.
+ * Add a task in to the loading queue
+ *
+ * @param[in] task The task added to the queue.
*/
- virtual ~ImageLoadThread();
+ void AddCompletedTask( LoadingTask* task );
protected:
private:
- LoadQueue& mLoadQueue; ///<The task queue with images for loading.
- CompleteQueue& mCompleteQueue; ///<The task queue with images loaded.
+ Vector< LoadingTask* > mLoadQueue; ///<The task queue with images for loading.
+ Vector< LoadingTask* > mCompleteQueue; ///<The task queue with images loaded.
+
+ ConditionalWait mConditionalWait;
+ Dali::Mutex mMutex;
+ EventThreadCallback* mTrigger;
};
} // namespace Internal
}
mAtlasList.push_back( newAtlas );
TextureSet textureSet = TextureSet::New();
- TextureSetImage( textureSet, 0u, newAtlas.GetAtlas() );
+ textureSet.SetTexture( 0u, newAtlas.GetAtlas() );
mTextureSetList.push_back( textureSet );
}
#include <dali/public-api/rendering/texture-set.h>
// INTERNAL INCLUDES
-#include <dali-toolkit/devel-api/image-atlas/image-atlas.h>
+#include <dali-toolkit/devel-api/image-loader/image-atlas.h>
namespace Dali
{