TestObserver()
: mCompleteType( CompleteType::NOT_COMPLETED ),
mLoaded(false),
- mObserverCalled(false)
+ mObserverCalled(false),
+ mTextureSet()
{
}
mCompleteType = CompleteType::UPLOAD_COMPLETE;
mLoaded = loadSuccess;
mObserverCalled = true;
+ mTextureSet = textureSet;
}
virtual void LoadComplete( bool loadSuccess, Devel::PixelBuffer pixelBuffer, const VisualUrl& url, bool preMultiplied ) override
CompleteType mCompleteType;
bool mLoaded;
bool mObserverCalled;
+ TextureSet mTextureSet;
};
END_TEST;
}
+
+int UtcTextureManagerSynchronousLoadingFail(void)
+{
+ ToolkitTestApplication application;
+ tet_infoline( "UtcTextureManagerSynchronousLoadingFail" );
+
+ TextureManager textureManager; // Create new texture manager
+
+ std::string maskname("");
+ TextureManager::MaskingDataPointer maskInfo = nullptr;
+ maskInfo.reset(new TextureManager::MaskingData());
+ maskInfo->mAlphaMaskUrl = maskname;
+ maskInfo->mAlphaMaskId = TextureManager::INVALID_TEXTURE_ID;
+ maskInfo->mCropToMask = true;
+ maskInfo->mContentScaleFactor = 1.0f;
+
+ std::string filename("dummy");
+ auto textureId( TextureManager::INVALID_TEXTURE_ID );
+ Vector4 atlasRect( 0.f, 0.f, 0.f, 0.f );
+ Dali::ImageDimensions atlasRectSize( 0,0 );
+ bool atlasingStatus(false);
+ bool loadingStatus(false);
+ auto preMultiply = TextureManager::MultiplyOnLoad::LOAD_WITHOUT_MULTIPLY;
+ ImageAtlasManagerPtr atlasManager = nullptr;
+ Toolkit::AtlasUploadObserver* atlasUploadObserver = nullptr;
+
+ // load image synchronously.
+ TestObserver observer;
+ TextureSet textureSet = textureManager.LoadTexture(
+ filename,
+ ImageDimensions(),
+ FittingMode::SCALE_TO_FILL,
+ SamplingMode::BOX_THEN_LINEAR,
+ maskInfo,
+ true, // synchronous loading.
+ textureId,
+ atlasRect,
+ atlasRectSize,
+ atlasingStatus,
+ loadingStatus,
+ WrapMode::DEFAULT,
+ WrapMode::DEFAULT,
+ &observer,
+ atlasUploadObserver,
+ atlasManager,
+ true,
+ TextureManager::ReloadPolicy::CACHED,
+ preMultiply
+ );
+
+ DALI_TEST_EQUALS(loadingStatus, false, TEST_LOCATION);
+ DALI_TEST_CHECK(!textureSet); // texture loading fail.
+ DALI_TEST_CHECK(textureId == TextureManager::INVALID_TEXTURE_ID); // invalid texture id is returned.
+
+ END_TEST;
+}
+
+int UtcTextureManagerCachingSynchronousLoading(void)
+{
+ ToolkitTestApplication application;
+ tet_infoline( "UtcTextureManagerCachingSynchronousLoading" );
+
+ TextureManager textureManager; // Create new texture manager
+
+ std::string filename( TEST_IMAGE_FILE_NAME );
+
+ std::string maskname("");
+ TextureManager::MaskingDataPointer maskInfo = nullptr;
+ maskInfo.reset(new TextureManager::MaskingData());
+ maskInfo->mAlphaMaskUrl = maskname;
+ maskInfo->mAlphaMaskId = TextureManager::INVALID_TEXTURE_ID;
+ maskInfo->mCropToMask = true;
+ maskInfo->mContentScaleFactor = 1.0f;
+
+ Vector4 atlasRect( 0.f, 0.f, 0.f, 0.f );
+ Dali::ImageDimensions atlasRectSize( 0,0 );
+ bool atlasingStatus(false);
+ bool loadingStatus(false);
+ auto preMultiply = TextureManager::MultiplyOnLoad::LOAD_WITHOUT_MULTIPLY;
+ ImageAtlasManagerPtr atlasManager = nullptr;
+ Toolkit::AtlasUploadObserver* atlasUploadObserver = nullptr;
+
+ // load image synchronously.
+ TestObserver observer;
+ auto textureId( TextureManager::INVALID_TEXTURE_ID );
+ TextureSet textureSet = textureManager.LoadTexture(
+ filename,
+ ImageDimensions(),
+ FittingMode::SCALE_TO_FILL,
+ SamplingMode::BOX_THEN_LINEAR,
+ maskInfo,
+ true, // synchronous loading.
+ textureId,
+ atlasRect,
+ atlasRectSize,
+ atlasingStatus,
+ loadingStatus,
+ WrapMode::DEFAULT,
+ WrapMode::DEFAULT,
+ &observer,
+ atlasUploadObserver,
+ atlasManager,
+ true,
+ TextureManager::ReloadPolicy::CACHED,
+ preMultiply
+ );
+
+ DALI_TEST_EQUALS(loadingStatus, false, TEST_LOCATION);
+ DALI_TEST_CHECK(textureSet); // texture is loaded.
+
+ // observer isn't called in synchronous loading.
+ DALI_TEST_EQUALS(observer.mLoaded, false, TEST_LOCATION);
+ DALI_TEST_EQUALS(observer.mObserverCalled, false, TEST_LOCATION);
+
+
+ // load same image asynchronously.
+ TestObserver asyncObserver;
+ auto asyncTextureId( TextureManager::INVALID_TEXTURE_ID );
+ loadingStatus = false;
+ TextureSet asyncTextureSet = textureManager.LoadTexture(
+ filename,
+ ImageDimensions(),
+ FittingMode::SCALE_TO_FILL,
+ SamplingMode::BOX_THEN_LINEAR,
+ maskInfo,
+ false, // asynchronous loading.
+ asyncTextureId,
+ atlasRect,
+ atlasRectSize,
+ atlasingStatus,
+ loadingStatus,
+ WrapMode::DEFAULT,
+ WrapMode::DEFAULT,
+ &asyncObserver,
+ atlasUploadObserver,
+ atlasManager,
+ true,
+ TextureManager::ReloadPolicy::CACHED,
+ preMultiply
+ );
+
+ DALI_TEST_EQUALS(asyncTextureId, textureId, TEST_LOCATION); // texture is loaded.
+ DALI_TEST_EQUALS(loadingStatus, false, TEST_LOCATION);
+ DALI_TEST_CHECK(asyncTextureSet); // Cached texture.
+
+ // observer is directly called because textureSet is retrieved by cache.
+ DALI_TEST_EQUALS(asyncObserver.mLoaded, true, TEST_LOCATION);
+ DALI_TEST_EQUALS(asyncObserver.mObserverCalled, true, TEST_LOCATION);
+
+ END_TEST;
+}
+
+int UtcTextureManagerAsyncSyncAsync(void)
+{
+ ToolkitTestApplication application;
+ tet_infoline( "UtcTextureManagerAsyncSyncAsync" );
+
+ TextureManager textureManager; // Create new texture manager
+
+ std::string filename( TEST_IMAGE_FILE_NAME );
+
+ std::string maskname("");
+ TextureManager::MaskingDataPointer maskInfo = nullptr;
+ maskInfo.reset(new TextureManager::MaskingData());
+ maskInfo->mAlphaMaskUrl = maskname;
+ maskInfo->mAlphaMaskId = TextureManager::INVALID_TEXTURE_ID;
+ maskInfo->mCropToMask = true;
+ maskInfo->mContentScaleFactor = 1.0f;
+
+ Vector4 atlasRect( 0.f, 0.f, 0.f, 0.f );
+ Dali::ImageDimensions atlasRectSize( 0,0 );
+ bool atlasingStatus(false);
+ auto preMultiply = TextureManager::MultiplyOnLoad::LOAD_WITHOUT_MULTIPLY;
+ ImageAtlasManagerPtr atlasManager = nullptr;
+ Toolkit::AtlasUploadObserver* atlasUploadObserver = nullptr;
+
+ // load image asynchronously.
+ TestObserver asyncObserver1;
+ auto asyncTextureId1( TextureManager::INVALID_TEXTURE_ID );
+ bool asyncLoadingStatus1 = false;
+ TextureSet asyncTextureSet1 = textureManager.LoadTexture(
+ filename,
+ ImageDimensions(),
+ FittingMode::SCALE_TO_FILL,
+ SamplingMode::BOX_THEN_LINEAR,
+ maskInfo,
+ false, // asynchronous loading.
+ asyncTextureId1,
+ atlasRect,
+ atlasRectSize,
+ atlasingStatus,
+ asyncLoadingStatus1,
+ WrapMode::DEFAULT,
+ WrapMode::DEFAULT,
+ &asyncObserver1,
+ atlasUploadObserver,
+ atlasManager,
+ true,
+ TextureManager::ReloadPolicy::CACHED,
+ preMultiply
+ );
+
+ DALI_TEST_EQUALS(asyncLoadingStatus1, true, TEST_LOCATION); // texture is loading now.
+ DALI_TEST_CHECK(!asyncTextureSet1); // texture is not loaded yet.
+
+ // observer is still not called.
+ DALI_TEST_EQUALS(asyncObserver1.mLoaded, false, TEST_LOCATION);
+ DALI_TEST_EQUALS(asyncObserver1.mObserverCalled, false, TEST_LOCATION);
+
+
+ // load same image synchronously just after asynchronous loading.
+ TestObserver syncObserver;
+ auto textureId( TextureManager::INVALID_TEXTURE_ID );
+ bool syncLoadingStatus = false;
+ TextureSet syncTextureSet = textureManager.LoadTexture(
+ filename,
+ ImageDimensions(),
+ FittingMode::SCALE_TO_FILL,
+ SamplingMode::BOX_THEN_LINEAR,
+ maskInfo,
+ true, // synchronous loading.
+ textureId,
+ atlasRect,
+ atlasRectSize,
+ atlasingStatus,
+ syncLoadingStatus,
+ WrapMode::DEFAULT,
+ WrapMode::DEFAULT,
+ &syncObserver,
+ atlasUploadObserver,
+ atlasManager,
+ true,
+ TextureManager::ReloadPolicy::CACHED,
+ preMultiply
+ );
+
+ DALI_TEST_EQUALS(asyncTextureId1, textureId, TEST_LOCATION); // texture is loaded.
+ DALI_TEST_EQUALS(syncLoadingStatus, false, TEST_LOCATION); // texture is loaded.
+ DALI_TEST_CHECK(syncTextureSet); // texture is loaded.
+
+ // syncObserver isn't called in synchronous loading.
+ DALI_TEST_EQUALS(syncObserver.mLoaded, false, TEST_LOCATION);
+ DALI_TEST_EQUALS(syncObserver.mObserverCalled, false, TEST_LOCATION);
+
+ // asyncObserver1 is still not called too.
+ DALI_TEST_EQUALS(asyncObserver1.mLoaded, false, TEST_LOCATION);
+ DALI_TEST_EQUALS(asyncObserver1.mObserverCalled, false, TEST_LOCATION);
+
+
+
+ // load image asynchronously.
+ TestObserver asyncObserver2;
+ auto asyncTextureId2( TextureManager::INVALID_TEXTURE_ID );
+ bool asyncLoadingStatus2 = false;
+ TextureSet asyncTextureSet2 = textureManager.LoadTexture(
+ filename,
+ ImageDimensions(),
+ FittingMode::SCALE_TO_FILL,
+ SamplingMode::BOX_THEN_LINEAR,
+ maskInfo,
+ false, // asynchronous loading.
+ asyncTextureId2,
+ atlasRect,
+ atlasRectSize,
+ atlasingStatus,
+ asyncLoadingStatus2,
+ WrapMode::DEFAULT,
+ WrapMode::DEFAULT,
+ &asyncObserver2,
+ atlasUploadObserver,
+ atlasManager,
+ true,
+ TextureManager::ReloadPolicy::CACHED,
+ preMultiply
+ );
+
+ DALI_TEST_EQUALS(asyncLoadingStatus2, false, TEST_LOCATION); // texture is loaded by previous sync request
+ DALI_TEST_CHECK(asyncTextureSet2); // texture is loaded
+ DALI_TEST_CHECK(asyncTextureSet2 == syncTextureSet); // check loaded two texture is same.
+
+ // observer is called synchronously because the texture is cached.
+ DALI_TEST_EQUALS(asyncObserver2.mLoaded, true, TEST_LOCATION);
+ DALI_TEST_EQUALS(asyncObserver2.mObserverCalled, true, TEST_LOCATION);
+
+ asyncObserver2.mLoaded = false;
+ asyncObserver2.mObserverCalled = false;
+
+ application.SendNotification();
+ application.Render();
+
+ // Requested asynchronous loading at first is finished now and async observer is called now.
+ DALI_TEST_EQUALS( Test::WaitForEventThreadTrigger( 1 ), true, TEST_LOCATION );
+ DALI_TEST_EQUALS(asyncObserver1.mLoaded, true, TEST_LOCATION);
+ DALI_TEST_EQUALS(asyncObserver1.mObserverCalled, true, TEST_LOCATION);
+ DALI_TEST_CHECK(asyncObserver1.mTextureSet == asyncTextureSet2); // check loaded two texture is same.
+
+ // asyncObserver2 was already called so it isn't called here.
+ DALI_TEST_EQUALS(asyncObserver2.mLoaded, false, TEST_LOCATION);
+ DALI_TEST_EQUALS(asyncObserver2.mObserverCalled, false, TEST_LOCATION);
+
+ END_TEST;
+}
dali-toolkit-test-utils/test-render-controller.cpp
dali-toolkit-test-utils/test-trace-call-stack.cpp
dali-toolkit-test-utils/test-native-image.cpp
+ test-text-geometry-utils.cpp
)
PKG_CHECK_MODULES(${CAPI_LIB} REQUIRED
--- /dev/null
+/*
+ * 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 "test-text-geometry-utils.h"
+
+namespace TestTextGeometryUtils
+{
+
+void CheckGeometryResult(Vector<Vector2> positionsList, Vector<Vector2> sizeList, Vector<Vector2> expectedPositions, Vector<Vector2> expectedSizes)
+{
+ unsigned int expectedCount = expectedSizes.Size();
+
+ for(unsigned int i = 0; i < expectedCount; i++)
+ {
+ DALI_TEST_EQUALS((int)positionsList[i].x, (int)expectedPositions[i].x, TEST_LOCATION);
+ DALI_TEST_EQUALS((int)positionsList[i].y, (int)expectedPositions[i].y, TEST_LOCATION);
+
+ DALI_TEST_EQUALS((int)sizeList[i].x, (int)expectedSizes[i].x, TEST_LOCATION);
+ DALI_TEST_EQUALS((int)sizeList[i].y, (int)expectedSizes[i].y, TEST_LOCATION);
+ }
+}
+
+}
\ No newline at end of file
--- /dev/null
+#ifndef TOOLKIT_TEXT_GEOMETRY_UTILS_H
+#define TOOLKIT_TEXT_GEOMETRY_UTILS_H
+
+/*
+ * Copyright (c) 2021 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-toolkit-test-suite-utils.h>
+#include <dali-toolkit/dali-toolkit.h>
+
+
+
+namespace TestTextGeometryUtils
+{
+void CheckGeometryResult(Vector<Vector2> positionsList, Vector<Vector2> sizeList, Vector<Vector2> expectedPositions, Vector<Vector2> expectedSizes);
+}
+
+#endif // TOOLKIT_TEXT_GEOMETRY_UTILS_H
#include <dali-toolkit/devel-api/controls/text-controls/text-editor-devel.h>
#include <dali-toolkit/devel-api/text/rendering-backend.h>
#include <dali-toolkit/devel-api/text/text-enumerations-devel.h>
+#include "test-text-geometry-utils.h"
using namespace Dali;
using namespace Toolkit;
END_TEST;
}
+int utcDaliTextEditorGeometryEllipsisStart(void)
+{
+ ToolkitTestApplication application;
+ tet_infoline(" utcDaliTextEditorGeometryEllipsisStart");
+
+ TextEditor editor = TextEditor::New();
+ DALI_TEST_CHECK( editor );
+
+ application.GetScene().Add( editor );
+
+ editor.SetProperty( TextEditor::Property::POINT_SIZE, 7.f );
+ editor.SetProperty( Actor::Property::SIZE, Vector2( 100.f, 50.f ) );
+ editor.SetProperty( Actor::Property::PARENT_ORIGIN, ParentOrigin::TOP_LEFT );
+ editor.SetProperty( Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_LEFT );
+ editor.SetProperty( TextEditor::Property::ENABLE_MARKUP, true );
+ editor.SetProperty( DevelTextEditor::Property::ENABLE_SCROLL_BAR, false );
+ editor.SetProperty( DevelTextEditor::Property::ELLIPSIS, true );
+ editor.SetProperty( DevelTextEditor::Property::ELLIPSIS_POSITION, DevelText::EllipsisPosition::START );
+ editor.SetProperty( TextEditor::Property::TEXT, "line1 \nline2\nline 3\nline4" );
+
+ // Avoid a crash when core load gl resources.
+ application.GetGlAbstraction().SetCheckFramebufferStatusResult( GL_FRAMEBUFFER_COMPLETE );
+
+ // Render and notify
+ application.SendNotification();
+ application.Render();
+
+ unsigned int expectedCount = 2;
+ unsigned int startIndex = 0;
+ unsigned int endIndex = 24;
+
+ Vector<Vector2> positionsList = DevelTextEditor::GetTextPosition(editor, startIndex, endIndex);
+ Vector<Vector2> sizeList = DevelTextEditor::GetTextSize(editor, startIndex, endIndex);
+
+ DALI_TEST_EQUALS(positionsList.Size(), expectedCount, TEST_LOCATION);
+ DALI_TEST_EQUALS(sizeList.Size(), expectedCount, TEST_LOCATION);
+
+ Vector<Vector2> expectedSizes;
+ Vector<Vector2> expectedPositions;
+
+ expectedPositions.PushBack(Vector2(37, 0));
+ expectedSizes.PushBack(Vector2(20, 25));
+
+ expectedPositions.PushBack(Vector2(-1, 25));
+ expectedSizes.PushBack(Vector2(52, 25));
+
+ TestTextGeometryUtils::CheckGeometryResult(positionsList, sizeList, expectedPositions, expectedSizes);
+
+ END_TEST;
+}
+
+int utcDaliTextEditorGeometryEllipsisMiddle(void)
+{
+ ToolkitTestApplication application;
+ tet_infoline(" utcDaliTextEditorGeometryEllipsisMiddle");
+
+ TextEditor editor = TextEditor::New();
+ DALI_TEST_CHECK( editor );
+
+ application.GetScene().Add( editor );
+
+ editor.SetProperty( TextEditor::Property::POINT_SIZE, 7.f );
+ editor.SetProperty( Actor::Property::SIZE, Vector2( 100.f, 50.f ) );
+ editor.SetProperty( Actor::Property::PARENT_ORIGIN, ParentOrigin::TOP_LEFT );
+ editor.SetProperty( Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_LEFT );
+ editor.SetProperty( TextEditor::Property::ENABLE_MARKUP, true );
+ editor.SetProperty( DevelTextEditor::Property::ENABLE_SCROLL_BAR, false );
+ editor.SetProperty( DevelTextEditor::Property::ELLIPSIS, true );
+ editor.SetProperty( DevelTextEditor::Property::ELLIPSIS_POSITION, DevelText::EllipsisPosition::MIDDLE );
+ editor.SetProperty( TextEditor::Property::TEXT, "line1 \nline2\nline 3\nline4" );
+
+ // Avoid a crash when core load gl resources.
+ application.GetGlAbstraction().SetCheckFramebufferStatusResult( GL_FRAMEBUFFER_COMPLETE );
+
+ // Render and notify
+ application.SendNotification();
+ application.Render();
+
+ unsigned int expectedCount = 2;
+ unsigned int startIndex = 0;
+ unsigned int endIndex = 24;
+
+ Vector<Vector2> positionsList = DevelTextEditor::GetTextPosition(editor, startIndex, endIndex);
+ Vector<Vector2> sizeList = DevelTextEditor::GetTextSize(editor, startIndex, endIndex);
+
+ DALI_TEST_EQUALS(positionsList.Size(), expectedCount, TEST_LOCATION);
+ DALI_TEST_EQUALS(sizeList.Size(), expectedCount, TEST_LOCATION);
+
+ Vector<Vector2> expectedSizes;
+ Vector<Vector2> expectedPositions;
+
+ expectedPositions.PushBack(Vector2(-1, 0));
+ expectedSizes.PushBack(Vector2(25, 25));
+
+ expectedPositions.PushBack(Vector2(-1, 25));
+ expectedSizes.PushBack(Vector2(52, 25));
+
+ TestTextGeometryUtils::CheckGeometryResult(positionsList, sizeList, expectedPositions, expectedSizes);
+
+ END_TEST;
+}
+
+int utcDaliTextEditorGeometryEllipsisEnd(void)
+{
+ ToolkitTestApplication application;
+ tet_infoline(" utcDaliTextEditorGeometryEllipsisEnd");
+
+ TextEditor editor = TextEditor::New();
+ DALI_TEST_CHECK( editor );
+
+ application.GetScene().Add( editor );
+
+ editor.SetProperty( TextEditor::Property::POINT_SIZE, 7.f );
+ editor.SetProperty( Actor::Property::SIZE, Vector2( 100.f, 50.f ) );
+ editor.SetProperty( Actor::Property::PARENT_ORIGIN, ParentOrigin::TOP_LEFT );
+ editor.SetProperty( Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_LEFT );
+ editor.SetProperty( TextEditor::Property::ENABLE_MARKUP, true );
+ editor.SetProperty( DevelTextEditor::Property::ENABLE_SCROLL_BAR, false );
+ editor.SetProperty( DevelTextEditor::Property::ELLIPSIS, true );
+ editor.SetProperty( DevelTextEditor::Property::ELLIPSIS_POSITION, DevelText::EllipsisPosition::END );
+ editor.SetProperty( TextEditor::Property::TEXT, "line1 \nline2\nline 3\nline4" );
+
+ // Avoid a crash when core load gl resources.
+ application.GetGlAbstraction().SetCheckFramebufferStatusResult( GL_FRAMEBUFFER_COMPLETE );
+
+ // Render and notify
+ application.SendNotification();
+ application.Render();
+
+ unsigned int expectedCount = 2;
+ unsigned int startIndex = 0;
+ unsigned int endIndex = 24;
+
+ Vector<Vector2> positionsList = DevelTextEditor::GetTextPosition(editor, startIndex, endIndex);
+ Vector<Vector2> sizeList = DevelTextEditor::GetTextSize(editor, startIndex, endIndex);
+
+ DALI_TEST_EQUALS(positionsList.Size(), expectedCount, TEST_LOCATION);
+ DALI_TEST_EQUALS(sizeList.Size(), expectedCount, TEST_LOCATION);
+
+ Vector<Vector2> expectedSizes;
+ Vector<Vector2> expectedPositions;
+
+ expectedPositions.PushBack(Vector2(-1, 0));
+ expectedSizes.PushBack(Vector2(59, 25));
+
+ expectedPositions.PushBack(Vector2(-1, 25));
+ expectedSizes.PushBack(Vector2(25, 25));
+
+ TestTextGeometryUtils::CheckGeometryResult(positionsList, sizeList, expectedPositions, expectedSizes);
+
+ END_TEST;
+}
+
+int utcDaliTextEditorGeometryRTL(void)
+{
+ ToolkitTestApplication application;
+ tet_infoline(" utcDaliTextEditorGeometryRTL");
+
+ TextEditor editor = TextEditor::New();
+ DALI_TEST_CHECK( editor );
+
+ application.GetScene().Add( editor );
+
+ editor.SetProperty( TextEditor::Property::POINT_SIZE, 7.f );
+ editor.SetProperty( Actor::Property::SIZE, Vector2( 100.f, 50.f ) );
+ editor.SetProperty( Actor::Property::PARENT_ORIGIN, ParentOrigin::TOP_LEFT );
+ editor.SetProperty( Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_LEFT );
+ editor.SetProperty( TextEditor::Property::ENABLE_MARKUP, true );
+ editor.SetProperty( TextEditor::Property::TEXT, "line1 \nline2\nline 3\nالاخيرالسطر" );
+
+ // Avoid a crash when core load gl resources.
+ application.GetGlAbstraction().SetCheckFramebufferStatusResult( GL_FRAMEBUFFER_COMPLETE );
+
+ // Render and notify
+ application.SendNotification();
+ application.Render();
+
+ unsigned int expectedCount = 4;
+ unsigned int startIndex = 3;
+ unsigned int endIndex = 24;
+
+ Vector<Vector2> positionsList = DevelTextEditor::GetTextPosition(editor, startIndex, endIndex);
+ Vector<Vector2> sizeList = DevelTextEditor::GetTextSize(editor, startIndex, endIndex);
+
+ DALI_TEST_EQUALS(positionsList.Size(), expectedCount, TEST_LOCATION);
+ DALI_TEST_EQUALS(sizeList.Size(), expectedCount, TEST_LOCATION);
+
+ Vector<Vector2> expectedSizes;
+ Vector<Vector2> expectedPositions;
+
+ expectedPositions.PushBack(Vector2(24, 0));
+ expectedSizes.PushBack(Vector2(33, 25));
+
+ expectedPositions.PushBack(Vector2(-1, 25));
+ expectedSizes.PushBack(Vector2(52, 25));
+
+ expectedPositions.PushBack(Vector2(-1, 50));
+ expectedSizes.PushBack(Vector2(59, 25));
+
+ expectedPositions.PushBack(Vector2(61, 75));
+ expectedSizes.PushBack(Vector2(37, 25));
+
+ TestTextGeometryUtils::CheckGeometryResult(positionsList, sizeList, expectedPositions, expectedSizes);
+
+ END_TEST;
+}
+
+int utcDaliTextEditorGeometryGlyphMiddle(void)
+{
+ ToolkitTestApplication application;
+ tet_infoline(" utcDaliTextEditorGeometryGlyphMiddle");
+
+ TextEditor editor = TextEditor::New();
+ DALI_TEST_CHECK( editor );
+
+ application.GetScene().Add( editor );
+
+ editor.SetProperty( TextEditor::Property::POINT_SIZE, 7.f );
+ editor.SetProperty( Actor::Property::SIZE, Vector2( 150.f, 200.f ) );
+ editor.SetProperty( Actor::Property::PARENT_ORIGIN, ParentOrigin::TOP_LEFT );
+ editor.SetProperty( Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_LEFT );
+ editor.SetProperty( TextEditor::Property::ENABLE_MARKUP, true );
+ editor.SetProperty( TextEditor::Property::TEXT, "لا تØتوي على لا" );
+
+ // Avoid a crash when core load gl resources.
+ application.GetGlAbstraction().SetCheckFramebufferStatusResult( GL_FRAMEBUFFER_COMPLETE );
+
+ // Render and notify
+ application.SendNotification();
+ application.Render();
+
+ unsigned int expectedCount = 1;
+ unsigned int startIndex = 1;
+ unsigned int endIndex = 13;
+
+ Vector<Vector2> positionsList = DevelTextEditor::GetTextPosition(editor, startIndex, endIndex);
+ Vector<Vector2> sizeList = DevelTextEditor::GetTextSize(editor, startIndex, endIndex);
+
+ DALI_TEST_EQUALS(positionsList.Size(), expectedCount, TEST_LOCATION);
+ DALI_TEST_EQUALS(sizeList.Size(), expectedCount, TEST_LOCATION);
+
+ Vector<Vector2> expectedSizes;
+ Vector<Vector2> expectedPositions;
+
+ expectedPositions.PushBack(Vector2(6, 0));
+ expectedSizes.PushBack(Vector2(124, 25));
+
+ TestTextGeometryUtils::CheckGeometryResult(positionsList, sizeList, expectedPositions, expectedSizes);
+
+ END_TEST;
+}
+
int utcDaliTextEditorSelectionClearedSignal(void)
{
ToolkitTestApplication application;
#include <dali-toolkit/devel-api/text/rendering-backend.h>
#include "toolkit-clipboard.h"
#include <dali-toolkit/devel-api/text/text-enumerations-devel.h>
+#include "test-text-geometry-utils.h"
using namespace Dali;
using namespace Toolkit;
END_TEST;
}
+int utcDaliTextFieldGeometryEllipsisStart(void)
+{
+ ToolkitTestApplication application;
+ tet_infoline(" utcDaliTextFieldGeometryEllipsisStart");
+
+ TextField field = TextField::New();
+ DALI_TEST_CHECK( field );
+
+ application.GetScene().Add( field );
+
+ field.SetProperty( TextField::Property::POINT_SIZE, 7.f );
+ field.SetProperty( Actor::Property::SIZE, Vector2( 250.f, 50.f ) );
+ field.SetProperty( Actor::Property::PARENT_ORIGIN, ParentOrigin::TOP_LEFT );
+ field.SetProperty( Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_LEFT );
+ field.SetProperty( TextField::Property::ENABLE_MARKUP, true );
+ field.SetProperty( DevelTextField::Property::ELLIPSIS, true );
+ field.SetProperty( DevelTextField::Property::ELLIPSIS_POSITION, DevelText::EllipsisPosition::START );
+ field.SetProperty( TextField::Property::TEXT, "Hello World" );
+
+ // Avoid a crash when core load gl resources.
+ application.GetGlAbstraction().SetCheckFramebufferStatusResult( GL_FRAMEBUFFER_COMPLETE );
+
+ // Render and notify
+ application.SendNotification();
+ application.Render();
+
+ unsigned int expectedCount = 1;
+ unsigned int startIndex = 0;
+ unsigned int endIndex = 10;
+
+ Vector<Vector2> positionsList = DevelTextField::GetTextPosition(field, startIndex, endIndex);
+ Vector<Vector2> sizeList = DevelTextField::GetTextSize(field, startIndex, endIndex);
+
+ DALI_TEST_EQUALS(positionsList.Size(), expectedCount, TEST_LOCATION);
+ DALI_TEST_EQUALS(sizeList.Size(), expectedCount, TEST_LOCATION);
+
+ Vector<Vector2> expectedSizes;
+ Vector<Vector2> expectedPositions;
+
+ expectedPositions.PushBack(Vector2(14, 0));
+ expectedSizes.PushBack(Vector2(106, 25));
+
+ TestTextGeometryUtils::CheckGeometryResult(positionsList, sizeList, expectedPositions, expectedSizes);
+
+ END_TEST;
+}
+
+int utcDaliTextFieldGeometryEllipsisEnd(void)
+{
+ ToolkitTestApplication application;
+ tet_infoline(" utcDaliTextFieldGeometryEllipsisEnd");
+
+ TextField field = TextField::New();
+ DALI_TEST_CHECK( field );
+
+ application.GetScene().Add( field );
+
+ field.SetProperty( TextField::Property::POINT_SIZE, 7.f );
+ field.SetProperty( Actor::Property::SIZE, Vector2( 250.f, 50.f ) );
+ field.SetProperty( Actor::Property::PARENT_ORIGIN, ParentOrigin::TOP_LEFT );
+ field.SetProperty( Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_LEFT );
+ field.SetProperty( TextField::Property::ENABLE_MARKUP, true );
+ field.SetProperty( DevelTextField::Property::ELLIPSIS, true );
+ field.SetProperty( DevelTextField::Property::ELLIPSIS_POSITION, DevelText::EllipsisPosition::END );
+ field.SetProperty( TextField::Property::TEXT, "Hello World" );
+
+ // Avoid a crash when core load gl resources.
+ application.GetGlAbstraction().SetCheckFramebufferStatusResult( GL_FRAMEBUFFER_COMPLETE );
+
+ // Render and notify
+ application.SendNotification();
+ application.Render();
+
+ unsigned int expectedCount = 1;
+ unsigned int startIndex = 0;
+ unsigned int endIndex = 10;
+
+ Vector<Vector2> positionsList = DevelTextField::GetTextPosition(field, startIndex, endIndex);
+ Vector<Vector2> sizeList = DevelTextField::GetTextSize(field, startIndex, endIndex);
+
+ DALI_TEST_EQUALS(positionsList.Size(), expectedCount, TEST_LOCATION);
+ DALI_TEST_EQUALS(sizeList.Size(), expectedCount, TEST_LOCATION);
+
+ Vector<Vector2> expectedSizes;
+ Vector<Vector2> expectedPositions;
+
+ expectedPositions.PushBack(Vector2(-2, 0));
+ expectedSizes.PushBack(Vector2(122, 25));
+
+ TestTextGeometryUtils::CheckGeometryResult(positionsList, sizeList, expectedPositions, expectedSizes);
+
+ END_TEST;
+}
+
+int utcDaliTextFieldGeometryRTL(void)
+{
+ ToolkitTestApplication application;
+ tet_infoline(" utcDaliTextFieldGeometryRTL");
+
+ TextField field = TextField::New();
+ DALI_TEST_CHECK( field );
+
+ application.GetScene().Add( field );
+
+ field.SetProperty( TextField::Property::POINT_SIZE, 7.f );
+ field.SetProperty( Actor::Property::SIZE, Vector2( 300.f, 50.f ) );
+ field.SetProperty( Actor::Property::PARENT_ORIGIN, ParentOrigin::TOP_LEFT );
+ field.SetProperty( Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_LEFT );
+ field.SetProperty( TextField::Property::ENABLE_MARKUP, true );
+ field.SetProperty( TextField::Property::TEXT, "السطر الاخير" );
+
+ // Avoid a crash when core load gl resources.
+ application.GetGlAbstraction().SetCheckFramebufferStatusResult( GL_FRAMEBUFFER_COMPLETE );
+
+ // Render and notify
+ application.SendNotification();
+ application.Render();
+
+ unsigned int expectedCount = 1;
+ unsigned int startIndex = 1;
+ unsigned int endIndex = 7;
+
+ Vector<Vector2> positionsList = DevelTextField::GetTextPosition(field, startIndex, endIndex);
+ Vector<Vector2> sizeList = DevelTextField::GetTextSize(field, startIndex, endIndex);
+
+ DALI_TEST_EQUALS(positionsList.Size(), expectedCount, TEST_LOCATION);
+ DALI_TEST_EQUALS(sizeList.Size(), expectedCount, TEST_LOCATION);
+
+ Vector<Vector2> expectedSizes;
+ Vector<Vector2> expectedPositions;
+
+ expectedPositions.PushBack(Vector2(38, 0));
+ expectedSizes.PushBack(Vector2(73, 25));
+
+ TestTextGeometryUtils::CheckGeometryResult(positionsList, sizeList, expectedPositions, expectedSizes);
+
+ END_TEST;
+}
+
+int utcDaliTextFieldGeometryGlyphMiddle(void)
+{
+ ToolkitTestApplication application;
+ tet_infoline(" utcDaliTextFieldGeometryGlyphMiddle");
+
+ TextField field = TextField::New();
+ DALI_TEST_CHECK( field );
+
+ application.GetScene().Add( field );
+
+ field.SetProperty( TextField::Property::POINT_SIZE, 7.f );
+ field.SetProperty( Actor::Property::SIZE, Vector2( 150.f, 200.f ) );
+ field.SetProperty( Actor::Property::PARENT_ORIGIN, ParentOrigin::TOP_LEFT );
+ field.SetProperty( Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_LEFT );
+ field.SetProperty( TextField::Property::ENABLE_MARKUP, true );
+ field.SetProperty( TextField::Property::TEXT, "لا تØتوي على لا" );
+
+ // Avoid a crash when core load gl resources.
+ application.GetGlAbstraction().SetCheckFramebufferStatusResult( GL_FRAMEBUFFER_COMPLETE );
+
+ // Render and notify
+ application.SendNotification();
+ application.Render();
+
+ unsigned int expectedCount = 1;
+ unsigned int startIndex = 1;
+ unsigned int endIndex = 13;
+
+ Vector<Vector2> positionsList = DevelTextField::GetTextPosition(field, startIndex, endIndex);
+ Vector<Vector2> sizeList = DevelTextField::GetTextSize(field, startIndex, endIndex);
+
+ DALI_TEST_EQUALS(positionsList.Size(), expectedCount, TEST_LOCATION);
+ DALI_TEST_EQUALS(sizeList.Size(), expectedCount, TEST_LOCATION);
+
+ Vector<Vector2> expectedSizes;
+ Vector<Vector2> expectedPositions;
+
+ expectedPositions.PushBack(Vector2(6, 0));
+ expectedSizes.PushBack(Vector2(124, 25));
+
+ TestTextGeometryUtils::CheckGeometryResult(positionsList, sizeList, expectedPositions, expectedSizes);
+
+ END_TEST;
+}
+
int utcDaliTextFieldSelectionClearedSignal(void)
{
ToolkitTestApplication application;
#include <dali-toolkit/devel-api/text/bitmap-font.h>
#include <dali-toolkit/devel-api/text/rendering-backend.h>
#include <dali-toolkit/devel-api/text/text-utils-devel.h>
+#include "test-text-geometry-utils.h"
using namespace Dali;
using namespace Toolkit;
END_TEST;
}
+int utcDaliTextLabelGeometryRTL(void)
+{
+ ToolkitTestApplication application;
+ tet_infoline(" utcDaliTextLabelGeometryRTL");
+
+ TextLabel label = TextLabel::New();
+ DALI_TEST_CHECK( label );
+
+ application.GetScene().Add( label );
+
+ label.SetProperty( TextLabel::Property::POINT_SIZE, 7.f );
+ label.SetProperty( Actor::Property::SIZE, Vector2( 150.f, 100.f ) );
+ label.SetProperty( Actor::Property::PARENT_ORIGIN, ParentOrigin::TOP_LEFT );
+ label.SetProperty( Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_LEFT );
+ label.SetProperty( TextLabel::Property::ENABLE_MARKUP, true );
+ label.SetProperty( TextLabel::Property::MULTI_LINE, true);
+ label.SetProperty( TextLabel::Property::TEXT, "line1 \nline2\nline 3\nالاخيرالسطر" );
+
+ // Avoid a crash when core load gl resources.
+ application.GetGlAbstraction().SetCheckFramebufferStatusResult( GL_FRAMEBUFFER_COMPLETE );
+
+ // Render and notify
+ application.SendNotification();
+ application.Render();
+
+ unsigned int expectedCount = 4;
+ unsigned int startIndex = 3;
+ unsigned int endIndex = 24;
+
+ Vector<Vector2> positionsList = DevelTextLabel::GetTextPosition(label, startIndex, endIndex);
+ Vector<Vector2> sizeList = DevelTextLabel::GetTextSize(label, startIndex, endIndex);
+
+ DALI_TEST_EQUALS(positionsList.Size(), expectedCount, TEST_LOCATION);
+ DALI_TEST_EQUALS(sizeList.Size(), expectedCount, TEST_LOCATION);
+
+ Vector<Vector2> expectedSizes;
+ Vector<Vector2> expectedPositions;
+
+ expectedPositions.PushBack(Vector2(24, 0));
+ expectedSizes.PushBack(Vector2(33, 25));
+
+ expectedPositions.PushBack(Vector2(-1, 25));
+ expectedSizes.PushBack(Vector2(52, 25));
+
+ expectedPositions.PushBack(Vector2(-1, 50));
+ expectedSizes.PushBack(Vector2(59, 25));
+
+ expectedPositions.PushBack(Vector2(73, 75));
+ expectedSizes.PushBack(Vector2(37, 25));
+
+ TestTextGeometryUtils::CheckGeometryResult(positionsList, sizeList, expectedPositions, expectedSizes);
+
+ END_TEST;
+}
+
+int utcDaliTextLabelGeometryGlyphMiddle(void)
+{
+ ToolkitTestApplication application;
+ tet_infoline(" utcDaliTextLabelGeometryGlyphMiddle");
+
+ TextLabel label = TextLabel::New();
+ DALI_TEST_CHECK( label );
+
+ application.GetScene().Add( label );
+
+ label.SetProperty( TextLabel::Property::POINT_SIZE, 7.f );
+ label.SetProperty( Actor::Property::SIZE, Vector2( 200.f, 200.f ) );
+ label.SetProperty( Actor::Property::PARENT_ORIGIN, ParentOrigin::TOP_LEFT );
+ label.SetProperty( Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_LEFT );
+ label.SetProperty( TextLabel::Property::ENABLE_MARKUP, true );
+ label.SetProperty( TextLabel::Property::TEXT, "لا تØتوي على لا" );
+
+ // Avoid a crash when core load gl resources.
+ application.GetGlAbstraction().SetCheckFramebufferStatusResult( GL_FRAMEBUFFER_COMPLETE );
+
+ // Render and notify
+ application.SendNotification();
+ application.Render();
+
+ unsigned int expectedCount = 1;
+ unsigned int startIndex = 1;
+ unsigned int endIndex = 13;
+
+ Vector<Vector2> positionsList = DevelTextLabel::GetTextPosition(label, startIndex, endIndex);
+ Vector<Vector2> sizeList = DevelTextLabel::GetTextSize(label, startIndex, endIndex);
+
+ DALI_TEST_EQUALS(positionsList.Size(), expectedCount, TEST_LOCATION);
+ DALI_TEST_EQUALS(sizeList.Size(), expectedCount, TEST_LOCATION);
+
+ Vector<Vector2> expectedSizes;
+ Vector<Vector2> expectedPositions;
+
+ expectedPositions.PushBack(Vector2(12, 0));
+ expectedSizes.PushBack(Vector2(118, 25));
+
+ TestTextGeometryUtils::CheckGeometryResult(positionsList, sizeList, expectedPositions, expectedSizes);
+
+ END_TEST;
+}
+
int UtcDaliToolkitTextlabelEllipsisPositionProperty(void)
{
ToolkitTestApplication application;
#include <dali-toolkit/devel-api/visual-factory/transition-data.h>
#include <dali-toolkit/devel-api/visuals/color-visual-properties-devel.h>
#include <dali-toolkit/devel-api/visuals/visual-properties-devel.h>
+#include <dali-toolkit/devel-api/visuals/visual-actions-devel.h>
#include <dali-toolkit/devel-api/visuals/image-visual-properties-devel.h>
#include <dali-toolkit/devel-api/visuals/text-visual-properties-devel.h>
#include <dali-toolkit/devel-api/visuals/animated-gradient-visual-properties-devel.h>
#endif
END_TEST;
+}
+
+int UtcDaliVisualUpdateProperty(void)
+{
+ ToolkitTestApplication application;
+ tet_infoline( "UtcDaliVisualUpdateProperty: Test update property by DoAction. Standard case" );
+
+ VisualFactory factory = VisualFactory::Get();
+ Property::Map propertyMap;
+ propertyMap[Visual::Property::TYPE] = Visual::Type::IMAGE;
+ propertyMap[ImageVisual::Property::URL] = TEST_IMAGE_FILE_NAME;
+ propertyMap[Visual::Property::MIX_COLOR] = Color::BLUE;
+ propertyMap[DevelVisual::Property::VISUAL_FITTING_MODE] = DevelVisual::FIT_WIDTH;
+
+ Visual::Base imageVisual = factory.CreateVisual(propertyMap);
+
+ DummyControl dummyControl = DummyControl::New(true);
+ Impl::DummyControl& dummyImpl = static_cast<Impl::DummyControl&>(dummyControl.GetImplementation());
+ dummyImpl.RegisterVisual(DummyControl::Property::TEST_VISUAL, imageVisual);
+ dummyControl[Actor::Property::SIZE] = Vector2(200.f, 200.f);
+ application.GetScene().Add(dummyControl);
+
+ application.SendNotification();
+ application.Render();
+
+ // Wait for image loading
+ DALI_TEST_EQUALS(Test::WaitForEventThreadTrigger(1), true, TEST_LOCATION);
+
+ application.SendNotification();
+ application.Render();
+
+ Property::Map originalMap;
+ imageVisual.CreatePropertyMap( originalMap );
+
+ float targetOpacity = 0.5f;
+ Vector3 targetMixColor = Vector3(1.0f, 0.4f, 0.2f);
+ bool targetPreMultipliedAlpha = originalMap[Visual::Property::PREMULTIPLIED_ALPHA].Get<bool>() ^ true;
+ DevelVisual::FittingMode targetVisualFittingMode = DevelVisual::CENTER;
+
+ Property::Map targetPropertyMap;
+ targetPropertyMap[Visual::Property::OPACITY] = targetOpacity;
+ targetPropertyMap[ImageVisual::Property::URL] = "foobar";
+ targetPropertyMap[Visual::Property::MIX_COLOR] = targetMixColor;
+ targetPropertyMap[Visual::Property::PREMULTIPLIED_ALPHA] = targetPreMultipliedAlpha;
+ targetPropertyMap[DevelVisual::Property::VISUAL_FITTING_MODE] = targetVisualFittingMode;
+
+ // Update Properties
+ DevelControl::DoAction(dummyControl, DummyControl::Property::TEST_VISUAL, DevelVisual::Action::UPDATE_PROPERTY, targetPropertyMap);
+
+ Property::Map resultMap;
+ imageVisual.CreatePropertyMap( resultMap );
+
+ // Test property values: they should be updated
+ Property::Value* colorValue = resultMap.Find(Visual::Property::MIX_COLOR, Property::VECTOR4);
+ DALI_TEST_CHECK(colorValue);
+ DALI_TEST_EQUALS(colorValue->Get<Vector4>(), Vector4(targetMixColor.r, targetMixColor.g, targetMixColor.b, targetOpacity), TEST_LOCATION);
+
+ Property::Value* urlValue = resultMap.Find(ImageVisual::Property::URL, Property::STRING);
+ DALI_TEST_CHECK(urlValue);
+ // NOTE : ImageVisual URL must NOT changed.
+ DALI_TEST_EQUALS(urlValue->Get< std::string >(), TEST_IMAGE_FILE_NAME, TEST_LOCATION);
+
+ Property::Value* preMultipliedValue = resultMap.Find(Visual::Property::PREMULTIPLIED_ALPHA, Property::BOOLEAN);
+ DALI_TEST_CHECK(preMultipliedValue);
+ DALI_TEST_EQUALS(preMultipliedValue->Get< bool >(), targetPreMultipliedAlpha, TEST_LOCATION);
+
+ Property::Value* visualFittingModeValue = resultMap.Find(DevelVisual::Property::VISUAL_FITTING_MODE, Property::STRING);
+ DALI_TEST_CHECK(visualFittingModeValue);
+ DALI_TEST_EQUALS(visualFittingModeValue->Get< std::string >(), "CENTER", TEST_LOCATION);
+
+ END_TEST;
+}
+
+int UtcDaliVisualUpdatePropertyChangeShader01(void)
+{
+ ToolkitTestApplication application;
+ tet_infoline( "UtcDaliVisualUpdatePropertyChangeShader01: Test update property by DoAction. Change the shader case" );
+
+ TraceCallStack& callStack = application.GetGraphicsController().mCallStack;
+
+ VisualFactory factory = VisualFactory::Get();
+ Property::Map propertyMap;
+ // Case ImageVisual
+ propertyMap[Visual::Property::TYPE] = Visual::Type::IMAGE;
+ propertyMap[ImageVisual::Property::URL] = TEST_IMAGE_FILE_NAME;
+
+ Visual::Base imageVisual = factory.CreateVisual(propertyMap);
+
+ DummyControl dummyControl = DummyControl::New(true);
+ Impl::DummyControl& dummyImpl = static_cast<Impl::DummyControl&>(dummyControl.GetImplementation());
+ dummyImpl.RegisterVisual(DummyControl::Property::TEST_VISUAL, imageVisual);
+ dummyControl[Actor::Property::SIZE] = Vector2(200.f, 200.f);
+ application.GetScene().Add(dummyControl);
+
+ application.SendNotification();
+ application.Render();
+
+ // Wait for image loading
+ DALI_TEST_EQUALS(Test::WaitForEventThreadTrigger(1), true, TEST_LOCATION);
+
+ application.SendNotification();
+ application.Render();
+
+ // Get shader
+ {
+ Renderer renderer = dummyControl.GetRendererAt( 0 );
+ Shader shader = renderer.GetShader();
+ Property::Value value = shader.GetProperty( Shader::Property::PROGRAM );
+ Property::Map* map = value.GetMap();
+ DALI_TEST_CHECK( map );
+
+ Property::Value* fragment = map->Find( "fragment" ); // fragment key name from shader-impl.cpp
+ DALI_TEST_CHECK( fragment );
+ std::string fragmentShader;
+ DALI_TEST_CHECK( fragment->Get(fragmentShader) );
+ DALI_TEST_CHECK( fragmentShader.find("#define IS_REQUIRED_BORDERLINE 1") == std::string::npos );
+ DALI_TEST_CHECK( fragmentShader.find("#define IS_REQUIRED_ROUNDED_CORNER 1") == std::string::npos );
+
+ Property::Value* vertex = map->Find( "vertex" ); // vertex key name from shader-impl.cpp
+ std::string vertexShader;
+ DALI_TEST_CHECK( vertex->Get(vertexShader) );
+ DALI_TEST_CHECK( vertexShader.find("#define IS_REQUIRED_BORDERLINE 1") == std::string::npos );
+ DALI_TEST_CHECK( vertexShader.find("#define IS_REQUIRED_ROUNDED_CORNER 1") == std::string::npos );
+ }
+ callStack.Reset();
+ callStack.Enable(true);
+
+ Vector4 targetCornerRadius = Vector4(1.0f, 12.0f, 2.0f, 21.0f);
+
+ Property::Map targetPropertyMap;
+ targetPropertyMap[DevelVisual::Property::CORNER_RADIUS] = targetCornerRadius;
+ targetPropertyMap[DevelVisual::Property::CORNER_RADIUS_POLICY] = Toolkit::Visual::Transform::Policy::RELATIVE;
+
+ // Update Properties with CornerRadius
+ DevelControl::DoAction(dummyControl, DummyControl::Property::TEST_VISUAL, DevelVisual::Action::UPDATE_PROPERTY, targetPropertyMap);
+
+ Property::Map resultMap;
+ imageVisual.CreatePropertyMap( resultMap );
+
+ // Test property values: they should be updated
+ Property::Value* cornerRadiusValue = resultMap.Find(DevelVisual::Property::CORNER_RADIUS, Property::VECTOR4);
+ DALI_TEST_CHECK(cornerRadiusValue);
+ DALI_TEST_EQUALS(cornerRadiusValue->Get<Vector4>(), targetCornerRadius, TEST_LOCATION);
+
+ Property::Value* cornerRadiusPolicyValue = resultMap.Find(DevelVisual::Property::CORNER_RADIUS_POLICY, Property::INTEGER);
+ DALI_TEST_CHECK(cornerRadiusPolicyValue);
+ DALI_TEST_EQUALS(cornerRadiusPolicyValue->Get<int>(), static_cast<int>(Toolkit::Visual::Transform::Policy::RELATIVE), TEST_LOCATION);
+
+ // Get shader
+ {
+ Renderer renderer = dummyControl.GetRendererAt( 0 );
+ Shader shader = renderer.GetShader();
+ Property::Value value = shader.GetProperty( Shader::Property::PROGRAM );
+ Property::Map* map = value.GetMap();
+ DALI_TEST_CHECK( map );
+
+ Property::Value* fragment = map->Find( "fragment" ); // fragment key name from shader-impl.cpp
+ DALI_TEST_CHECK( fragment );
+ std::string fragmentShader;
+ DALI_TEST_CHECK( fragment->Get(fragmentShader) );
+ DALI_TEST_CHECK( fragmentShader.find("#define IS_REQUIRED_BORDERLINE 1") == std::string::npos );
+ DALI_TEST_CHECK( fragmentShader.find("#define IS_REQUIRED_ROUNDED_CORNER 1") != std::string::npos );
+
+ Property::Value* vertex = map->Find( "vertex" ); // vertex key name from shader-impl.cpp
+ std::string vertexShader;
+ DALI_TEST_CHECK( vertex->Get(vertexShader) );
+ DALI_TEST_CHECK( vertexShader.find("#define IS_REQUIRED_BORDERLINE 1") == std::string::npos );
+ DALI_TEST_CHECK( vertexShader.find("#define IS_REQUIRED_ROUNDED_CORNER 1") != std::string::npos );
+ }
+
+ // Send shader compile signal
+ application.SendNotification();
+ application.Render();
+
+ callStack.Enable(false);
+ // Shader changed
+ DALI_TEST_CHECK( callStack.FindMethod("CreateShader") );
+ callStack.Reset();
+ callStack.Enable(true);
+
+ float targetBorderlineWidth = 10.0f;
+ Vector4 targetBorderlineColor = Vector4(1.0f, 0.2f, 0.1f, 0.5f);
+ float targetBorderlineOffset = -0.3f;
+
+ Property::Map targetPropertyMap2;
+ targetPropertyMap2[DevelVisual::Property::CORNER_RADIUS] = Vector4::ZERO;
+ targetPropertyMap2[DevelVisual::Property::CORNER_RADIUS_POLICY] = Toolkit::Visual::Transform::Policy::ABSOLUTE;
+ targetPropertyMap2[DevelVisual::Property::BORDERLINE_WIDTH] = targetBorderlineWidth;
+ targetPropertyMap2[DevelVisual::Property::BORDERLINE_COLOR] = targetBorderlineColor;
+ targetPropertyMap2[DevelVisual::Property::BORDERLINE_OFFSET] = targetBorderlineOffset;
+
+ // Update Properties with Borderline
+ DevelControl::DoAction(dummyControl, DummyControl::Property::TEST_VISUAL, DevelVisual::Action::UPDATE_PROPERTY, targetPropertyMap2);
+
+ Property::Map resultMap2;
+ imageVisual.CreatePropertyMap( resultMap2 );
+
+ // Test property values: they should be updated
+ cornerRadiusValue = resultMap2.Find(DevelVisual::Property::CORNER_RADIUS, Property::VECTOR4);
+ DALI_TEST_CHECK(cornerRadiusValue);
+ DALI_TEST_EQUALS(cornerRadiusValue->Get<Vector4>(), Vector4::ZERO, TEST_LOCATION);
+
+ cornerRadiusPolicyValue = resultMap2.Find(DevelVisual::Property::CORNER_RADIUS_POLICY, Property::INTEGER);
+ DALI_TEST_CHECK(cornerRadiusPolicyValue);
+ DALI_TEST_EQUALS(cornerRadiusPolicyValue->Get<int>(), static_cast<int>(Toolkit::Visual::Transform::Policy::ABSOLUTE), TEST_LOCATION);
+
+ Property::Value* borderlineWidthValue = resultMap2.Find(DevelVisual::Property::BORDERLINE_WIDTH, Property::FLOAT);
+ DALI_TEST_CHECK(borderlineWidthValue);
+ DALI_TEST_EQUALS(borderlineWidthValue->Get<float>(), targetBorderlineWidth, TEST_LOCATION);
+
+ Property::Value* borderlineColorValue = resultMap2.Find(DevelVisual::Property::BORDERLINE_COLOR, Property::VECTOR4);
+ DALI_TEST_CHECK(borderlineColorValue);
+ DALI_TEST_EQUALS(borderlineColorValue->Get<Vector4>(), targetBorderlineColor, TEST_LOCATION);
+
+ Property::Value* borderlineOffsetValue = resultMap2.Find(DevelVisual::Property::BORDERLINE_OFFSET, Property::FLOAT);
+ DALI_TEST_CHECK(borderlineOffsetValue);
+ DALI_TEST_EQUALS(borderlineOffsetValue->Get<float>(), targetBorderlineOffset, TEST_LOCATION);
+
+ // Get shader
+ {
+ Renderer renderer = dummyControl.GetRendererAt( 0 );
+ Shader shader = renderer.GetShader();
+ Property::Value value = shader.GetProperty( Shader::Property::PROGRAM );
+ Property::Map* map = value.GetMap();
+ DALI_TEST_CHECK( map );
+
+ Property::Value* fragment = map->Find( "fragment" ); // fragment key name from shader-impl.cpp
+ DALI_TEST_CHECK( fragment );
+ std::string fragmentShader;
+ DALI_TEST_CHECK( fragment->Get(fragmentShader) );
+ DALI_TEST_CHECK( fragmentShader.find("#define IS_REQUIRED_BORDERLINE 1") != std::string::npos );
+ // Note : mAlwaysUsingCornerRadius is true.
+ DALI_TEST_CHECK( fragmentShader.find("#define IS_REQUIRED_ROUNDED_CORNER 1") != std::string::npos );
+
+ Property::Value* vertex = map->Find( "vertex" ); // vertex key name from shader-impl.cpp
+ std::string vertexShader;
+ DALI_TEST_CHECK( vertex->Get(vertexShader) );
+ DALI_TEST_CHECK( vertexShader.find("#define IS_REQUIRED_BORDERLINE 1") != std::string::npos );
+ // Note : mAlwaysUsingCornerRadius is true.
+ DALI_TEST_CHECK( vertexShader.find("#define IS_REQUIRED_ROUNDED_CORNER 1") != std::string::npos );
+ }
+
+ // Send shader compile signal
+ application.SendNotification();
+ application.Render();
+
+ callStack.Enable(false);
+ // Shader changed
+ DALI_TEST_CHECK( callStack.FindMethod("CreateShader") );
+ callStack.Reset();
+ callStack.Enable(true);
+
+ Property::Map targetPropertyMap3;
+ targetPropertyMap3[DevelVisual::Property::CORNER_RADIUS] = Vector4::ZERO;
+ targetPropertyMap3[DevelVisual::Property::CORNER_RADIUS_POLICY] = Toolkit::Visual::Transform::Policy::ABSOLUTE;
+ targetPropertyMap3[DevelVisual::Property::BORDERLINE_WIDTH] = 0.0f;
+ targetPropertyMap3[DevelVisual::Property::BORDERLINE_COLOR] = Vector4::ZERO;
+ targetPropertyMap3[DevelVisual::Property::BORDERLINE_OFFSET] = 0.0f;
+
+ // Update Properties into zero
+ DevelControl::DoAction(dummyControl, DummyControl::Property::TEST_VISUAL, DevelVisual::Action::UPDATE_PROPERTY, targetPropertyMap3);
+
+ Property::Map resultMap3;
+ imageVisual.CreatePropertyMap( resultMap3 );
+
+ // Test property values: they should be updated
+ cornerRadiusValue = resultMap3.Find(DevelVisual::Property::CORNER_RADIUS, Property::VECTOR4);
+ DALI_TEST_CHECK(cornerRadiusValue);
+ DALI_TEST_EQUALS(cornerRadiusValue->Get<Vector4>(), Vector4::ZERO, TEST_LOCATION);
+
+ cornerRadiusPolicyValue = resultMap3.Find(DevelVisual::Property::CORNER_RADIUS_POLICY, Property::INTEGER);
+ DALI_TEST_CHECK(cornerRadiusPolicyValue);
+ DALI_TEST_EQUALS(cornerRadiusPolicyValue->Get<int>(), static_cast<int>(Toolkit::Visual::Transform::Policy::ABSOLUTE), TEST_LOCATION);
+
+ borderlineWidthValue = resultMap3.Find(DevelVisual::Property::BORDERLINE_WIDTH, Property::FLOAT);
+ DALI_TEST_CHECK(borderlineWidthValue);
+ DALI_TEST_EQUALS(borderlineWidthValue->Get<float>(), 0.0f, TEST_LOCATION);
+
+ borderlineColorValue = resultMap3.Find(DevelVisual::Property::BORDERLINE_COLOR, Property::VECTOR4);
+ DALI_TEST_CHECK(borderlineColorValue);
+ DALI_TEST_EQUALS(borderlineColorValue->Get<Vector4>(), Vector4::ZERO, TEST_LOCATION);
+
+ borderlineOffsetValue = resultMap3.Find(DevelVisual::Property::BORDERLINE_OFFSET, Property::FLOAT);
+ DALI_TEST_CHECK(borderlineOffsetValue);
+ DALI_TEST_EQUALS(borderlineOffsetValue->Get<float>(), 0.0f, TEST_LOCATION);
+
+ // Get shader
+ {
+ Renderer renderer = dummyControl.GetRendererAt( 0 );
+ Shader shader = renderer.GetShader();
+ Property::Value value = shader.GetProperty( Shader::Property::PROGRAM );
+ Property::Map* map = value.GetMap();
+ DALI_TEST_CHECK( map );
+
+ Property::Value* fragment = map->Find( "fragment" ); // fragment key name from shader-impl.cpp
+ DALI_TEST_CHECK( fragment );
+ std::string fragmentShader;
+ DALI_TEST_CHECK( fragment->Get(fragmentShader) );
+ // Note : mAlwaysUsingBorderline and mAlwaysUsingCornerRadius is true.
+ DALI_TEST_CHECK( fragmentShader.find("#define IS_REQUIRED_BORDERLINE 1") != std::string::npos );
+ DALI_TEST_CHECK( fragmentShader.find("#define IS_REQUIRED_ROUNDED_CORNER 1") != std::string::npos );
+
+ Property::Value* vertex = map->Find( "vertex" ); // vertex key name from shader-impl.cpp
+ std::string vertexShader;
+ DALI_TEST_CHECK( vertex->Get(vertexShader) );
+ // Note : mAlwaysUsingBorderline and mAlwaysUsingCornerRadius is true.
+ DALI_TEST_CHECK( vertexShader.find("#define IS_REQUIRED_BORDERLINE 1") != std::string::npos );
+ DALI_TEST_CHECK( vertexShader.find("#define IS_REQUIRED_ROUNDED_CORNER 1") != std::string::npos );
+ }
+
+ // Send shader compile signal
+ application.SendNotification();
+ application.Render();
+
+ callStack.Enable(false);
+ // Shader not changed
+ DALI_TEST_CHECK( !callStack.FindMethod("CreateShader") );
+
+ END_TEST;
+}
+
+int UtcDaliVisualUpdatePropertyChangeShader02(void)
+{
+ ToolkitTestApplication application;
+ tet_infoline( "UtcDaliVisualUpdatePropertyChangeShader02: Test update property by DoAction. Fake update" );
+
+ TraceCallStack& callStack = application.GetGraphicsController().mCallStack;
+
+ VisualFactory factory = VisualFactory::Get();
+ Property::Map propertyMap;
+ // Case ImageVisual
+ propertyMap[Visual::Property::TYPE] = Visual::Type::IMAGE;
+ propertyMap[ImageVisual::Property::URL] = TEST_IMAGE_FILE_NAME;
+
+ Visual::Base imageVisual = factory.CreateVisual(propertyMap);
+
+ DummyControl dummyControl = DummyControl::New(true);
+ Impl::DummyControl& dummyImpl = static_cast<Impl::DummyControl&>(dummyControl.GetImplementation());
+ dummyImpl.RegisterVisual(DummyControl::Property::TEST_VISUAL, imageVisual);
+ dummyControl[Actor::Property::SIZE] = Vector2(200.f, 200.f);
+ application.GetScene().Add(dummyControl);
+
+ application.SendNotification();
+ application.Render();
+
+ // Wait for image loading
+ DALI_TEST_EQUALS(Test::WaitForEventThreadTrigger(1), true, TEST_LOCATION);
+
+ application.SendNotification();
+ application.Render();
+
+ // Get shader
+ {
+ Renderer renderer = dummyControl.GetRendererAt( 0 );
+ Shader shader = renderer.GetShader();
+ Property::Value value = shader.GetProperty( Shader::Property::PROGRAM );
+ Property::Map* map = value.GetMap();
+ DALI_TEST_CHECK( map );
+
+ Property::Value* fragment = map->Find( "fragment" ); // fragment key name from shader-impl.cpp
+ DALI_TEST_CHECK( fragment );
+ std::string fragmentShader;
+ DALI_TEST_CHECK( fragment->Get(fragmentShader) );
+ DALI_TEST_CHECK( fragmentShader.find("#define IS_REQUIRED_BORDERLINE 1") == std::string::npos );
+ DALI_TEST_CHECK( fragmentShader.find("#define IS_REQUIRED_ROUNDED_CORNER 1") == std::string::npos );
+
+ Property::Value* vertex = map->Find( "vertex" ); // vertex key name from shader-impl.cpp
+ std::string vertexShader;
+ DALI_TEST_CHECK( vertex->Get(vertexShader) );
+ DALI_TEST_CHECK( vertexShader.find("#define IS_REQUIRED_BORDERLINE 1") == std::string::npos );
+ DALI_TEST_CHECK( vertexShader.find("#define IS_REQUIRED_ROUNDED_CORNER 1") == std::string::npos );
+ }
+
+ Vector4 targetCornerRadius = Vector4(0.0f, 0.0f, 0.0f, 0.0f);
+
+ Property::Map targetPropertyMap;
+ targetPropertyMap[DevelVisual::Property::CORNER_RADIUS] = targetCornerRadius;
+
+ callStack.Reset();
+ callStack.Enable(true);
+
+ // Update Properties with CornerRadius
+ DevelControl::DoAction(dummyControl, DummyControl::Property::TEST_VISUAL, DevelVisual::Action::UPDATE_PROPERTY, targetPropertyMap);
+
+ Property::Map resultMap;
+ imageVisual.CreatePropertyMap( resultMap );
+
+ // Test property values: they should be updated
+ Property::Value* cornerRadiusValue = resultMap.Find(DevelVisual::Property::CORNER_RADIUS, Property::VECTOR4);
+ DALI_TEST_CHECK(cornerRadiusValue);
+ DALI_TEST_EQUALS(cornerRadiusValue->Get<Vector4>(), targetCornerRadius, TEST_LOCATION);
+
+ // Get shader
+ {
+ Renderer renderer = dummyControl.GetRendererAt( 0 );
+ Shader shader = renderer.GetShader();
+ Property::Value value = shader.GetProperty( Shader::Property::PROGRAM );
+ Property::Map* map = value.GetMap();
+ DALI_TEST_CHECK( map );
+
+ Property::Value* fragment = map->Find( "fragment" ); // fragment key name from shader-impl.cpp
+ DALI_TEST_CHECK( fragment );
+ std::string fragmentShader;
+ DALI_TEST_CHECK( fragment->Get(fragmentShader) );
+ DALI_TEST_CHECK( fragmentShader.find("#define IS_REQUIRED_BORDERLINE 1") == std::string::npos );
+ // Note : corner radius is zero. so we don't change shader!
+ DALI_TEST_CHECK( fragmentShader.find("#define IS_REQUIRED_ROUNDED_CORNER 1") == std::string::npos );
+
+ Property::Value* vertex = map->Find( "vertex" ); // vertex key name from shader-impl.cpp
+ std::string vertexShader;
+ DALI_TEST_CHECK( vertex->Get(vertexShader) );
+ DALI_TEST_CHECK( vertexShader.find("#define IS_REQUIRED_BORDERLINE 1") == std::string::npos );
+ // Note : corner radius is zero. so we don't change shader!
+ DALI_TEST_CHECK( vertexShader.find("#define IS_REQUIRED_ROUNDED_CORNER 1") == std::string::npos );
+ }
+
+ // Send shader compile signal
+ application.SendNotification();
+ application.Render();
+
+ callStack.Enable(false);
+
+ // Shader doesn't changed
+ DALI_TEST_CHECK( !(callStack.FindMethod("CreateShader")) );
+ callStack.Reset();
+ callStack.Enable(true);
+
+ float targetBorderlineWidth = 0.0f;
+ Vector4 targetBorderlineColor = Vector4(1.0f, 1.0f, 0.0f, 0.0f);
+ float targetBorderlineOffset = -1.0f;
+
+ Property::Map targetPropertyMap2;
+ targetPropertyMap2[DevelVisual::Property::BORDERLINE_WIDTH] = targetBorderlineWidth;
+ targetPropertyMap2[DevelVisual::Property::BORDERLINE_COLOR] = targetBorderlineColor;
+ targetPropertyMap2[DevelVisual::Property::BORDERLINE_OFFSET] = targetBorderlineOffset;
+
+ // Update Properties with Borderline
+ DevelControl::DoAction(dummyControl, DummyControl::Property::TEST_VISUAL, DevelVisual::Action::UPDATE_PROPERTY, targetPropertyMap2);
+
+ Property::Map resultMap2;
+ imageVisual.CreatePropertyMap( resultMap2 );
+
+ // Test property values: they should be updated
+ Property::Value* borderlineWidthValue = resultMap2.Find(DevelVisual::Property::BORDERLINE_WIDTH, Property::FLOAT);
+ DALI_TEST_CHECK(borderlineWidthValue);
+ DALI_TEST_EQUALS(borderlineWidthValue->Get<float>(), targetBorderlineWidth, TEST_LOCATION);
+
+ Property::Value* borderlineColorValue = resultMap2.Find(DevelVisual::Property::BORDERLINE_COLOR, Property::VECTOR4);
+ DALI_TEST_CHECK(borderlineColorValue);
+ DALI_TEST_EQUALS(borderlineColorValue->Get<Vector4>(), targetBorderlineColor, TEST_LOCATION);
+
+ Property::Value* borderlineOffsetValue = resultMap2.Find(DevelVisual::Property::BORDERLINE_OFFSET, Property::FLOAT);
+ DALI_TEST_CHECK(borderlineOffsetValue);
+ DALI_TEST_EQUALS(borderlineOffsetValue->Get<float>(), targetBorderlineOffset, TEST_LOCATION);
+
+ // Get shader
+ {
+ Renderer renderer = dummyControl.GetRendererAt( 0 );
+ Shader shader = renderer.GetShader();
+ Property::Value value = shader.GetProperty( Shader::Property::PROGRAM );
+ Property::Map* map = value.GetMap();
+ DALI_TEST_CHECK( map );
+
+ Property::Value* fragment = map->Find( "fragment" ); // fragment key name from shader-impl.cpp
+ DALI_TEST_CHECK( fragment );
+ std::string fragmentShader;
+ DALI_TEST_CHECK( fragment->Get(fragmentShader) );
+ // Note : borderline width is zero. so we don't change shader!
+ DALI_TEST_CHECK( fragmentShader.find("#define IS_REQUIRED_BORDERLINE 1") == std::string::npos );
+ DALI_TEST_CHECK( fragmentShader.find("#define IS_REQUIRED_ROUNDED_CORNER 1") == std::string::npos );
+
+ Property::Value* vertex = map->Find( "vertex" ); // vertex key name from shader-impl.cpp
+ std::string vertexShader;
+ DALI_TEST_CHECK( vertex->Get(vertexShader) );
+ // Note : borderline width is zero. so we don't change shader!
+ DALI_TEST_CHECK( vertexShader.find("#define IS_REQUIRED_BORDERLINE 1") == std::string::npos );
+ DALI_TEST_CHECK( vertexShader.find("#define IS_REQUIRED_ROUNDED_CORNER 1") == std::string::npos );
+ }
+
+ // Send shader compile signal
+ application.SendNotification();
+ application.Render();
+
+ callStack.Enable(false);
+
+ // Shader doesn't changed
+ DALI_TEST_CHECK( !(callStack.FindMethod("CreateShader")) );
+
+ END_TEST;
+}
+
+int UtcDaliVisualUpdatePropertyChangeShader03(void)
+{
+ ToolkitTestApplication application;
+ tet_infoline( "UtcDaliVisualUpdatePropertyChangeShader03: Test update property by DoAction. Blur Radius" );
+
+ TraceCallStack& callStack = application.GetGraphicsController().mCallStack;
+
+ VisualFactory factory = VisualFactory::Get();
+ Property::Map propertyMap;
+ // Case ImageVisual
+ propertyMap[Visual::Property::TYPE] = Visual::Type::COLOR;
+ propertyMap[ColorVisual::Property::MIX_COLOR] = Color::BLUE;
+
+ Visual::Base imageVisual = factory.CreateVisual(propertyMap);
+
+ DummyControl dummyControl = DummyControl::New(true);
+ Impl::DummyControl& dummyImpl = static_cast<Impl::DummyControl&>(dummyControl.GetImplementation());
+ dummyImpl.RegisterVisual(DummyControl::Property::TEST_VISUAL, imageVisual);
+ dummyControl[Actor::Property::SIZE] = Vector2(200.f, 200.f);
+ application.GetScene().Add(dummyControl);
+
+ application.SendNotification();
+ application.Render();
+
+ application.SendNotification();
+ application.Render();
+
+ // Get shader
+ {
+ Renderer renderer = dummyControl.GetRendererAt( 0 );
+ Shader shader = renderer.GetShader();
+ Property::Value value = shader.GetProperty( Shader::Property::PROGRAM );
+ Property::Map* map = value.GetMap();
+ DALI_TEST_CHECK( map );
+
+ Property::Value* fragment = map->Find( "fragment" ); // fragment key name from shader-impl.cpp
+ DALI_TEST_CHECK( fragment );
+ std::string fragmentShader;
+ DALI_TEST_CHECK( fragment->Get(fragmentShader) );
+ DALI_TEST_CHECK( fragmentShader.find("#define IS_REQUIRED_BLUR 1") == std::string::npos );
+ DALI_TEST_CHECK( fragmentShader.find("#define IS_REQUIRED_BORDERLINE 1") == std::string::npos );
+ DALI_TEST_CHECK( fragmentShader.find("#define IS_REQUIRED_ROUNDED_CORNER 1") == std::string::npos );
+
+ Property::Value* vertex = map->Find( "vertex" ); // vertex key name from shader-impl.cpp
+ std::string vertexShader;
+ DALI_TEST_CHECK( vertex->Get(vertexShader) );
+ DALI_TEST_CHECK( vertexShader.find("#define IS_REQUIRED_BLUR 1") == std::string::npos );
+ DALI_TEST_CHECK( vertexShader.find("#define IS_REQUIRED_BORDERLINE 1") == std::string::npos );
+ DALI_TEST_CHECK( vertexShader.find("#define IS_REQUIRED_ROUNDED_CORNER 1") == std::string::npos );
+ }
+
+ float targetBlurRadius = 15.0f;
+ Vector4 targetCornerRadius = Vector4(1.0f, 0.1f, 1.1f, 0.0f);
+
+ Property::Map targetPropertyMap;
+ targetPropertyMap[DevelColorVisual::Property::BLUR_RADIUS] = targetBlurRadius;
+ targetPropertyMap[DevelVisual::Property::CORNER_RADIUS] = targetCornerRadius;
+ targetPropertyMap[DevelVisual::Property::BORDERLINE_WIDTH] = 10.0f; // Don't care. just dummy
+
+ callStack.Reset();
+ callStack.Enable(true);
+
+ // Update Properties with CornerRadius
+ DevelControl::DoAction(dummyControl, DummyControl::Property::TEST_VISUAL, DevelVisual::Action::UPDATE_PROPERTY, targetPropertyMap);
+
+ Property::Map resultMap;
+ imageVisual.CreatePropertyMap( resultMap );
+
+ // Test property values: they should be updated
+ Property::Value* blurRadiusValue = resultMap.Find(DevelColorVisual::Property::BLUR_RADIUS, Property::FLOAT);
+ DALI_TEST_CHECK(blurRadiusValue);
+ DALI_TEST_EQUALS(blurRadiusValue->Get<float>(), targetBlurRadius, TEST_LOCATION);
+
+ Property::Value* cornerRadiusValue = resultMap.Find(DevelVisual::Property::CORNER_RADIUS, Property::VECTOR4);
+ DALI_TEST_CHECK(cornerRadiusValue);
+ DALI_TEST_EQUALS(cornerRadiusValue->Get<Vector4>(), targetCornerRadius, TEST_LOCATION);
+
+ // Get shader
+ {
+ Renderer renderer = dummyControl.GetRendererAt( 0 );
+ Shader shader = renderer.GetShader();
+ Property::Value value = shader.GetProperty( Shader::Property::PROGRAM );
+ Property::Map* map = value.GetMap();
+ DALI_TEST_CHECK( map );
+
+ Property::Value* fragment = map->Find( "fragment" ); // fragment key name from shader-impl.cpp
+ DALI_TEST_CHECK( fragment );
+ std::string fragmentShader;
+ DALI_TEST_CHECK( fragment->Get(fragmentShader) );
+ DALI_TEST_CHECK( fragmentShader.find("#define IS_REQUIRED_BLUR 1") != std::string::npos );
+ // Note : We ignore borderline when blur radius occured
+ DALI_TEST_CHECK( fragmentShader.find("#define IS_REQUIRED_BORDERLINE 1") == std::string::npos );
+ DALI_TEST_CHECK( fragmentShader.find("#define IS_REQUIRED_ROUNDED_CORNER 1") != std::string::npos );
+
+ Property::Value* vertex = map->Find( "vertex" ); // vertex key name from shader-impl.cpp
+ std::string vertexShader;
+ DALI_TEST_CHECK( vertex->Get(vertexShader) );
+ DALI_TEST_CHECK( vertexShader.find("#define IS_REQUIRED_BLUR 1") != std::string::npos );
+ // Note : We ignore borderline when blur radius occured
+ DALI_TEST_CHECK( vertexShader.find("#define IS_REQUIRED_BORDERLINE 1") == std::string::npos );
+ DALI_TEST_CHECK( vertexShader.find("#define IS_REQUIRED_ROUNDED_CORNER 1") != std::string::npos );
+ }
+
+ // Send shader compile signal
+ application.SendNotification();
+ application.Render();
+
+ callStack.Enable(false);
+
+ // Shader changed
+ DALI_TEST_CHECK( (callStack.FindMethod("CreateShader")) );
+ callStack.Reset();
+ callStack.Enable(true);
+
+ Property::Map targetPropertyMap2;
+ targetPropertyMap2[DevelColorVisual::Property::BLUR_RADIUS] = 0.0f;
+ targetPropertyMap2[DevelVisual::Property::CORNER_RADIUS] = Vector4::ZERO;
+ targetPropertyMap2[DevelVisual::Property::BORDERLINE_WIDTH] = 15.0f; // Don't care. just dummy
+
+ // Update Properties with CornerRadius
+ DevelControl::DoAction(dummyControl, DummyControl::Property::TEST_VISUAL, DevelVisual::Action::UPDATE_PROPERTY, targetPropertyMap2);
+
+ Property::Map resultMap2;
+ imageVisual.CreatePropertyMap( resultMap2 );
+
+ // Test property values: they should be updated
+ blurRadiusValue = resultMap2.Find(DevelColorVisual::Property::BLUR_RADIUS, Property::FLOAT);
+ DALI_TEST_CHECK(blurRadiusValue);
+ DALI_TEST_EQUALS(blurRadiusValue->Get<float>(), 0.0f, TEST_LOCATION);
+
+ cornerRadiusValue = resultMap2.Find(DevelVisual::Property::CORNER_RADIUS, Property::VECTOR4);
+ DALI_TEST_CHECK(cornerRadiusValue);
+ DALI_TEST_EQUALS(cornerRadiusValue->Get<Vector4>(), Vector4::ZERO, TEST_LOCATION);
+
+ // Get shader
+ {
+ Renderer renderer = dummyControl.GetRendererAt( 0 );
+ Shader shader = renderer.GetShader();
+ Property::Value value = shader.GetProperty( Shader::Property::PROGRAM );
+ Property::Map* map = value.GetMap();
+ DALI_TEST_CHECK( map );
+
+ Property::Value* fragment = map->Find( "fragment" ); // fragment key name from shader-impl.cpp
+ DALI_TEST_CHECK( fragment );
+ std::string fragmentShader;
+ DALI_TEST_CHECK( fragment->Get(fragmentShader) );
+ // Note : mAlwaysUsingBlurRadius and mAlwaysUsingCornerRadius is true.
+ DALI_TEST_CHECK( fragmentShader.find("#define IS_REQUIRED_BLUR 1") != std::string::npos );
+ // Note : We ignore borderline when blur radius occured
+ DALI_TEST_CHECK( fragmentShader.find("#define IS_REQUIRED_BORDERLINE 1") == std::string::npos );
+ DALI_TEST_CHECK( fragmentShader.find("#define IS_REQUIRED_ROUNDED_CORNER 1") != std::string::npos );
+
+ Property::Value* vertex = map->Find( "vertex" ); // vertex key name from shader-impl.cpp
+ std::string vertexShader;
+ DALI_TEST_CHECK( vertex->Get(vertexShader) );
+ // Note : mAlwaysUsingBlurRadius and mAlwaysUsingCornerRadius is true.
+ DALI_TEST_CHECK( vertexShader.find("#define IS_REQUIRED_BLUR 1") != std::string::npos );
+ // Note : We ignore borderline when blur radius occured
+ DALI_TEST_CHECK( vertexShader.find("#define IS_REQUIRED_BORDERLINE 1") == std::string::npos );
+ DALI_TEST_CHECK( vertexShader.find("#define IS_REQUIRED_ROUNDED_CORNER 1") != std::string::npos );
+ }
+
+ // Send shader compile signal
+ application.SendNotification();
+ application.Render();
+
+ callStack.Enable(false);
+
+ // Shader not changed
+ DALI_TEST_CHECK( !(callStack.FindMethod("CreateShader")) );
+
+ END_TEST;
}
\ No newline at end of file
GetImpl(textEditor).ScrollBy(scroll);
}
+Vector<Vector2> GetTextSize(TextEditor textEditor, const uint32_t startIndex, const uint32_t endIndex)
+{
+ return GetImpl(textEditor).GetTextSize(startIndex, endIndex);
+}
+
+Vector<Vector2> GetTextPosition(TextEditor textEditor, const uint32_t startIndex, const uint32_t endIndex)
+{
+ return GetImpl(textEditor).GetTextPosition(startIndex, endIndex);
+}
+
string CopyText(TextEditor textEditor)
{
return GetImpl(textEditor).CopyText();
DALI_TOOLKIT_API void ScrollBy(TextEditor textEditor, Vector2 scroll);
/**
+ * @brief Get the rendered size of a specific text range.
+ * if the requested text is at multilines, multiple sizes will be returned for each text located in a separate line.
+ * if a line contains characters with different directions, multiple sizes will be returned for each block of contiguous characters with the same direction.
+ *
+ * @param[in] textEditor The instance of TextEditor.
+ * @param[in] startIndex start index of the text requested to calculate size for.
+ * @param[in] endIndex end index(included) of the text requested to calculate size for.
+ * @return list of sizes of the reuested text.
+ */
+DALI_TOOLKIT_API Vector<Vector2> GetTextSize(TextEditor textEditor, const uint32_t startIndex, const uint32_t endIndex);
+
+/**
+ * @brief Get the top/left rendered position of a specific text range.
+ * if the requested text is at multilines, multiple positions will be returned for each text located in a separate line.
+ * if a line contains characters with different directions, multiple positions will be returned for each block of contiguous characters with the same direction.
+ *
+ * @param[in] textEditor The instance of TextEditor.
+ * @param[in] startIndex start index of the text requested to get position to.
+ * @param[in] endIndex end index(included) of the text requested to get position to.
+ * @return list of positions of the requested text.
+ */
+DALI_TOOLKIT_API Vector<Vector2> GetTextPosition(TextEditor textEditor, const uint32_t startIndex, const uint32_t endIndex);
+
+/**
* @brief Copy and return the selected text of TextEditor.
*
* @param[in] textEditor The instance of TextEditor.
GetImpl(textField).SelectText(start, end);
}
+Vector<Vector2> GetTextSize(TextField textField, const uint32_t startIndex, const uint32_t endIndex)
+{
+ return GetImpl(textField).GetTextSize(startIndex, endIndex);
+}
+
+Vector<Vector2> GetTextPosition(TextField textField, const uint32_t startIndex, const uint32_t endIndex)
+{
+ return GetImpl(textField).GetTextPosition(startIndex, endIndex);
+}
+
string CopyText(TextField textField)
{
return GetImpl(textField).CopyText();
DALI_TOOLKIT_API SelectionClearedSignalType& SelectionClearedSignal(TextField textField);
/**
+ * @brief Get the rendered size of a specific text range.
+ * if the requested text is at multilines, multiple sizes will be returned for each text located in a separate line.
+ * if a line contains characters with different directions, multiple sizes will be returned for each block of contiguous characters with the same direction.
+ *
+ * @param[in] textField The instance of TextField.
+ * @param[in] startIndex start index of the text requested to calculate size for.
+ * @param[in] endIndex end index(included) of the text requested to calculate size for.
+ * @return list of sizes of the reuested text.
+ */
+DALI_TOOLKIT_API Vector<Vector2> GetTextSize(TextField textField, const uint32_t startIndex, const uint32_t endIndex);
+
+/**
+ * @brief Get the top/left rendered position of a specific text range.
+ * if the requested text is at multilines, multiple positions will be returned for each text located in a separate line.
+ * if a line contains characters with different directions, multiple positions will be returned for each block of contiguous characters with the same direction.
+ *
+ * @param[in] textField The instance of TextField.
+ * @param[in] startIndex start index of the text requested to get position to.
+ * @param[in] endIndex end index(included) of the text requested to get position to.
+ * @return list of positions of the requested text.
+ */
+DALI_TOOLKIT_API Vector<Vector2> GetTextPosition(TextField textField, const uint32_t startIndex, const uint32_t endIndex);
+
+/**
* @brief Select the whole text of TextField.
*
* @param[in] textField The instance of TextField.
return GetImpl(textLabel).TextFitChangedSignal();
}
+Vector<Vector2> GetTextSize(TextLabel textLabel, const uint32_t startIndex, const uint32_t endIndex)
+{
+ return GetImpl(textLabel).GetTextSize(startIndex, endIndex);
+}
+
+Vector<Vector2> GetTextPosition(TextLabel textLabel, const uint32_t startIndex, const uint32_t endIndex)
+{
+ return GetImpl(textLabel).GetTextPosition(startIndex, endIndex);
+}
+
} // namespace DevelTextLabel
} // namespace Toolkit
} // namespace Property
/**
+ * @brief Get the rendered size of a specific text range.
+ * if the requested text is at multilines, multiple sizes will be returned for each text located in a separate line.
+ * if a line contains characters with different directions, multiple sizes will be returned for each block of contiguous characters with the same direction.
+ *
+ * @param[in] textLabel The instance of TextLabel.
+ * @param[in] startIndex start index of the text requested to calculate size for.
+ * @param[in] endIndex end index(included) of the text requested to calculate size for.
+ * @return list of sizes of the reuested text.
+ */
+DALI_TOOLKIT_API Vector<Vector2> GetTextSize(TextLabel textLabel, const uint32_t startIndex, const uint32_t endIndex);
+
+/**
+ * @brief Get the top/left rendered position of a specific text range.
+ * if the requested text is at multilines, multiple positions will be returned for each text located in a separate line.
+ * if a line contains characters with different directions, multiple positions will be returned for each block of contiguous characters with the same direction.
+ *
+ * @param[in] textLabel The instance of TextLabel.
+ * @param[in] startIndex start index of the text requested to get position to.
+ * @param[in] endIndex end index(included) of the text requested to get position to.
+ * @return list of positions of the requested text.
+ */
+DALI_TOOLKIT_API Vector<Vector2> GetTextPosition(TextLabel textLabel, const uint32_t startIndex, const uint32_t endIndex);
+
+/**
* @brief Anchor clicked signal type.
*
* @note Signal
const unsigned int ALIGNMENT_STRING_TABLE_COUNT = sizeof(ALIGNMENT_STRING_TABLE) / sizeof(ALIGNMENT_STRING_TABLE[0]);
-const Property::Index VISUAL_INDEX_FOR_STATE[][Button::STATE_COUNT] =
+const Property::Index VISUAL_INDEX_FOR_STATE[Button::STATE_COUNT][Button::VISUAL_STATE_COUNT] =
{
{Toolkit::Button::Property::UNSELECTED_BACKGROUND_VISUAL, Toolkit::Button::Property::UNSELECTED_VISUAL},
{Toolkit::Button::Property::SELECTED_BACKGROUND_VISUAL, Toolkit::Button::Property::SELECTED_VISUAL},
return 0;
}
+Vector<Vector2> TextEditor::GetTextSize(const uint32_t startIndex, const uint32_t endIndex) const
+{
+ return mController->GetTextSize(startIndex, endIndex);
+}
+
+Vector<Vector2> TextEditor::GetTextPosition(const uint32_t startIndex, const uint32_t endIndex) const
+{
+ return mController->GetTextPosition(startIndex, endIndex);
+}
+
string TextEditor::GetSelectedText() const
{
string selectedText = "";
float GetVerticalScrollPosition();
/**
+ * @brief Get the rendered size of a specific text range.
+ * if the requested text is at multilines, multiple sizes will be returned for each text located in a separate line.
+ * if a line contains characters with different directions, multiple sizes will be returned for each block of contiguous characters with the same direction.
+ *
+ * @param[in] startIndex start index of the text requested to calculate size for.
+ * @param[in] endIndex end index(included) of the text requested to calculate size for.
+ * @return list of sizes of the reuested text.
+ */
+ Vector<Vector2> GetTextSize(const uint32_t startIndex, const uint32_t endIndex) const;
+
+ /**
+ * @brief Get the top/left rendered position of a specific text range.
+ * if the requested text is at multilines, multiple positions will be returned for each text located in a separate line.
+ * if a line contains characters with different directions, multiple positions will be returned for each block of contiguous characters with the same direction.
+ *
+ * @param[in] startIndex start index of the text requested to get position to.
+ * @param[in] endIndex end index(included) of the text requested to get position to.
+ * @return list of positions of the requested text.
+ */
+ Vector<Vector2> GetTextPosition(const uint32_t startIndex, const uint32_t endIndex) const;
+
+ /**
* @copydoc Text::SelectableControlInterface::GetSelectedText()
*/
string GetSelectedText() const override;
bool IsHiddenInput(Toolkit::TextField textField)
{
Property::Map hiddenInputSettings = textField.GetProperty<Property::Map>(Toolkit::TextField::Property::HIDDEN_INPUT_SETTINGS);
- auto mode = hiddenInputSettings.Find(Toolkit::HiddenInput::Property::MODE);
- if (mode && (mode->Get<int>() != Toolkit::HiddenInput::Mode::HIDE_NONE))
+ auto mode = hiddenInputSettings.Find(Toolkit::HiddenInput::Property::MODE);
+ if(mode && (mode->Get<int>() != Toolkit::HiddenInput::Mode::HIDE_NONE))
{
return true;
}
char GetSubstituteCharacter(Toolkit::TextField textField)
{
Property::Map hiddenInputSettings = textField.GetProperty<Property::Map>(Toolkit::TextField::Property::HIDDEN_INPUT_SETTINGS);
- auto substChar = hiddenInputSettings.Find(Toolkit::HiddenInput::Property::SUBSTITUTE_CHARACTER);
- if (substChar)
+ auto substChar = hiddenInputSettings.Find(Toolkit::HiddenInput::Property::SUBSTITUTE_CHARACTER);
+ if(substChar)
{
return static_cast<char>(substChar->Get<int>());
}
}
}
+Vector<Vector2> TextField::GetTextSize(const uint32_t startIndex, const uint32_t endIndex) const
+{
+ return mController->GetTextSize(startIndex, endIndex);
+}
+
+Vector<Vector2> TextField::GetTextPosition(const uint32_t startIndex, const uint32_t endIndex) const
+{
+ return mController->GetTextPosition(startIndex, endIndex);
+}
+
std::string TextField::AccessibleImpl::GetName()
{
auto self = Toolkit::TextField::DownCast(Self());
- if (IsHiddenInput(self))
+ if(IsHiddenInput(self))
{
return {};
}
Dali::Accessibility::Range TextField::AccessibleImpl::GetTextAtOffset(
size_t offset, Dali::Accessibility::TextBoundary boundary)
{
- auto self = Toolkit::TextField::DownCast(Self());
- auto range = Dali::Accessibility::Range{};
+ auto self = Toolkit::TextField::DownCast(Self());
+ auto range = Dali::Accessibility::Range{};
if(IsHiddenInput(self))
{
return {};
}
- auto self = Toolkit::TextField::DownCast(Self());
+ auto self = Toolkit::TextField::DownCast(Self());
auto controller = Dali::Toolkit::GetImpl(self).GetTextController();
- auto indices = controller->GetSelectionIndexes();
+ auto indices = controller->GetSelectionIndexes();
auto startOffset = static_cast<size_t>(indices.first);
- auto endOffset = static_cast<size_t>(indices.second);
+ auto endOffset = static_cast<size_t>(indices.second);
- if (IsHiddenInput(self))
+ if(IsHiddenInput(self))
{
return {startOffset, endOffset, std::string(endOffset - startOffset, GetSubstituteCharacter(self))};
}
*/
void AnchorClicked(const std::string& href) override;
+ /**
+ * @brief Get the rendered size of a specific text range.
+ * if the requested text is at multilines, multiple sizes will be returned for each text located in a separate line.
+ * if a line contains characters with different directions, multiple sizes will be returned for each block of contiguous characters with the same direction.
+ *
+ * @param[in] startIndex start index of the text requested to calculate size for.
+ * @param[in] endIndex end index(included) of the text requested to calculate size for.
+ * @return list of sizes of the reuested text.
+ */
+ Vector<Vector2> GetTextSize(const uint32_t startIndex, const uint32_t endIndex) const;
+
+ /**
+ * @brief Get the top/left rendered position of a specific text range.
+ * if the requested text is at multilines, multiple positions will be returned for each text located in a separate line.
+ * if a line contains characters with different directions, multiple positions will be returned for each block of contiguous characters with the same direction.
+ *
+ * @param[in] startIndex start index of the text requested to get position to.
+ * @param[in] endIndex end index(included) of the text requested to get position to.
+ * @return list of positions of the requested text.
+ */
+ Vector<Vector2> GetTextPosition(const uint32_t startIndex, const uint32_t endIndex) const;
+
private: // Implementation
/**
* @copydoc Dali::Toolkit::Text::Controller::(InputMethodContext& inputMethodContext, const InputMethodContext::EventData& inputMethodContextEvent)
// INTERNAL INCLUDES
#include <dali-toolkit/devel-api/controls/control-depth-index-ranges.h>
#include <dali-toolkit/devel-api/text/rendering-backend.h>
+#include <dali-toolkit/internal/controls/text-controls/common-text-utils.h>
#include <dali-toolkit/internal/styling/style-manager-impl.h>
#include <dali-toolkit/internal/text/property-string-parser.h>
#include <dali-toolkit/internal/text/rendering/text-backend.h>
#include <dali-toolkit/internal/text/text-effects-style.h>
#include <dali-toolkit/internal/text/text-font-style.h>
#include <dali-toolkit/internal/text/text-view.h>
-#include <dali-toolkit/internal/controls/text-controls/common-text-utils.h>
#include <dali-toolkit/public-api/text/text-enumerations.h>
#include <dali-toolkit/devel-api/controls/control-devel.h>
}
case Toolkit::DevelTextLabel::Property::TEXT_FIT:
{
- const bool enabled = impl.mController->IsTextFitEnabled();
- const float minSize = impl.mController->GetTextFitMinSize();
- const float maxSize = impl.mController->GetTextFitMaxSize();
- const float stepSize = impl.mController->GetTextFitStepSize();
+ const bool enabled = impl.mController->IsTextFitEnabled();
+ const float minSize = impl.mController->GetTextFitMinSize();
+ const float maxSize = impl.mController->GetTextFitMaxSize();
+ const float stepSize = impl.mController->GetTextFitStepSize();
const float pointSize = impl.mController->GetTextFitPointSize();
Property::Map map;
{
}
+Vector<Vector2> TextLabel::GetTextSize(const uint32_t startIndex, const uint32_t endIndex) const
+{
+ return mController->GetTextSize(startIndex, endIndex);
+}
+
+Vector<Vector2> TextLabel::GetTextPosition(const uint32_t startIndex, const uint32_t endIndex) const
+{
+ return mController->GetTextPosition(startIndex, endIndex);
+}
+
std::string TextLabel::AccessibleImpl::GetNameRaw()
{
auto self = Toolkit::TextLabel::DownCast(Self());
*/
Text::ControllerPtr GetTextController();
+ /**
+ * @brief Get the rendered size of a specific text range.
+ * if the requested text is at multilines, multiple sizes will be returned for each text located in a separate line.
+ * if a line contains characters with different directions, multiple sizes will be returned for each block of contiguous characters with the same direction.
+ *
+ * @param[in] startIndex start index of the text requested to calculate size for.
+ * @param[in] endIndex end index(included) of the text requested to calculate size for.
+ * @return list of sizes of the reuested text.
+ */
+ Vector<Vector2> GetTextSize(const uint32_t startIndex, const uint32_t endIndex) const;
+
+ /**
+ * @brief Get the top/left rendered position of a specific text range.
+ * if the requested text is at multilines, multiple positions will be returned for each text located in a separate line.
+ * if a line contains characters with different directions, multiple positions will be returned for each block of contiguous characters with the same direction.
+ *
+ * @param[in] startIndex start index of the text requested to get position to.
+ * @param[in] endIndex end index(included) of the text requested to get position to.
+ * @return list of positions of the requested text.
+ */
+ Vector<Vector2> GetTextPosition(const uint32_t startIndex, const uint32_t endIndex) const;
+
private: // From Control
/**
* @copydoc Control::OnInitialize()
std::vector<Toolkit::TextAnchor> mAnchorActors;
// Signals
- Toolkit::DevelTextLabel::AnchorClickedSignalType mAnchorClickedSignal;
+ Toolkit::DevelTextLabel::AnchorClickedSignalType mAnchorClickedSignal;
Toolkit::DevelTextLabel::TextFitChangedSignalType mTextFitChangedSignal;
int mRenderingBackend;
${toolkit_src_dir}/text/xhtml-entities.cpp
${toolkit_src_dir}/drag-drop-detector/drag-and-drop-detector-impl.cpp
${toolkit_src_dir}/text/emoji-helper.cpp
+ ${toolkit_src_dir}/text/text-geometry.cpp
)
SET( SOURCES ${SOURCES}
#include <dali-toolkit/internal/text/text-controller-relayouter.h>
#include <dali-toolkit/internal/text/text-controller-text-updater.h>
#include <dali-toolkit/internal/text/text-editable-control-interface.h>
+#include <dali-toolkit/internal/text/text-geometry.h>
namespace
{
mImpl->RequestRelayout();
}
+Vector<Vector2> Controller::GetTextSize(CharacterIndex startIndex, CharacterIndex endIndex)
+{
+ Vector<Vector2> sizesList;
+ Vector<Vector2> positionsList;
+
+ GetTextGeometry(mImpl->mModel, startIndex, endIndex, sizesList, positionsList);
+ return sizesList;
+}
+
+Vector<Vector2> Controller::GetTextPosition(CharacterIndex startIndex, CharacterIndex endIndex)
+{
+ Vector<Vector2> sizesList;
+ Vector<Vector2> positionsList;
+
+ GetTextGeometry(mImpl->mModel, startIndex, endIndex, sizesList, positionsList);
+ return positionsList;
+}
+
bool Controller::IsInputStyleChangedSignalsQueueEmpty()
{
return mImpl->IsInputStyleChangedSignalsQueueEmpty();
#include <dali/public-api/events/gesture.h>
// INTERNAL INCLUDES
+#include <dali-toolkit/devel-api/controls/text-controls/text-anchor-devel.h>
#include <dali-toolkit/devel-api/controls/text-controls/text-label-devel.h>
#include <dali-toolkit/devel-api/controls/text-controls/text-selection-popup-callback-interface.h>
-#include <dali-toolkit/devel-api/controls/text-controls/text-anchor-devel.h>
#include <dali-toolkit/devel-api/text/text-enumerations-devel.h>
#include <dali-toolkit/internal/text/decorator/text-decorator.h>
#include <dali-toolkit/internal/text/hidden-text.h>
Dali::LayoutDirection::Type GetLayoutDirection(Dali::Actor& actor) const;
/**
+ * @brief Get the rendered size of a specific text range.
+ * if the requested text is at multilines, multiple sizes will be returned for each text located in a separate line.
+ * if a line contains characters with different directions, multiple sizes will be returned for each block of contiguous characters with the same direction.
+ *
+ * @param[in] startIndex start index of the text requested to calculate size for.
+ * @param[in] endIndex end index(included) of the text requested to calculate size for.
+ * @return list of sizes of the reuested text.
+ */
+ Vector<Vector2> GetTextSize(CharacterIndex startIndex, CharacterIndex endIndex);
+
+ /**
+ * @brief Get the top/left rendered position of a specific text range.
+ * if the requested text is at multilines, multiple positions will be returned for each text located in a separate line.
+ * if a line contains characters with different directions, multiple positions will be returned for each block of contiguous characters with the same direction.
+ *
+ * @param[in] startIndex start index of the text requested to get position to.
+ * @param[in] endIndex end index(included) of the text requested to get position to.
+ * @return list of positions of the requested text.
+ */
+ Vector<Vector2> GetTextPosition(CharacterIndex startIndex, CharacterIndex endIndex);
+
+ /**
* @brief Sets the layout direction changed.
*/
void ChangedLayoutDirection();
--- /dev/null
+/*
+ * Copyright (c) 2021 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 <dali-toolkit/internal/text/text-geometry.h>
+
+// EXTERNAL INCLUDES
+#include <dali/integration-api/debug.h>
+
+// INTERNAL INCLUDES
+#include <dali-toolkit/internal/text/cursor-helper-functions.h>
+
+using namespace Dali;
+
+namespace Dali
+{
+namespace Toolkit
+{
+namespace Text
+{
+bool GetNextLine(GlyphIndex index, LineIndex& lineIndex, LineRun*& lineRun, GlyphIndex& lastGlyphOfLine, Length numberOfLines)
+{
+ if(index == lastGlyphOfLine)
+ {
+ ++lineIndex;
+ if(lineIndex < numberOfLines)
+ {
+ ++lineRun;
+ return true;
+ }
+ }
+
+ return false;
+}
+
+void UpdateLineInfo(const LineRun* lineRun, float& currentLineOffset, float& currentLineHeight, GlyphIndex& lastGlyphOfLine)
+{
+ lastGlyphOfLine = lineRun->glyphRun.glyphIndex + lineRun->glyphRun.numberOfGlyphs - 1u;
+ currentLineOffset = currentLineOffset + currentLineHeight;
+ currentLineHeight = GetLineHeight(*lineRun);
+}
+
+void GetTextGeometry(ModelPtr textModel, CharacterIndex startIndex, CharacterIndex endIndex, Vector<Vector2>& sizesList, Vector<Vector2>& positionsList)
+{
+ VisualModelPtr& visualModel = textModel->mVisualModel;
+ LogicalModelPtr& logicalModel = textModel->mLogicalModel;
+
+ const GlyphIndex* const charactersToGlyphBuffer = visualModel->mCharactersToGlyph.Begin();
+ const Length* const glyphsPerCharacterBuffer = visualModel->mGlyphsPerCharacter.Begin();
+ const GlyphInfo* const glyphsBuffer = visualModel->mGlyphs.Begin();
+ const Vector2* const positionsBuffer = visualModel->mGlyphPositions.Begin();
+ const Length* const charactersPerGlyphBuffer = visualModel->mCharactersPerGlyph.Begin();
+ const CharacterIndex* const glyphToCharacterBuffer = visualModel->mGlyphsToCharacters.Begin();
+ const CharacterDirection* const modelCharacterDirectionsBuffer = (0u != logicalModel->mCharacterDirections.Count()) ? logicalModel->mCharacterDirections.Begin() : NULL;
+
+ if(startIndex >= logicalModel->mText.Count() && endIndex >= logicalModel->mText.Count())
+ return;
+
+ if(startIndex >= logicalModel->mText.Count())
+ startIndex = logicalModel->mText.Count() - 1;
+
+ if(endIndex >= logicalModel->mText.Count())
+ endIndex = logicalModel->mText.Count() - 1;
+
+ if(startIndex > endIndex)
+ {
+ std::swap(startIndex, endIndex);
+ }
+
+ LineRun* lineRun = visualModel->mLines.Begin();
+ GlyphIndex glyphStart = *(charactersToGlyphBuffer + startIndex);
+
+ //if glyph not in the first line (in some ellipsis cases)
+ if(glyphStart < lineRun->glyphRun.glyphIndex)
+ {
+ glyphStart = lineRun->glyphRun.glyphIndex;
+ startIndex = *(glyphToCharacterBuffer + glyphStart);
+
+ if(startIndex > endIndex)
+ {
+ std::swap(startIndex, endIndex);
+ }
+ }
+
+ const Length numberOfGlyphs = *(glyphsPerCharacterBuffer + endIndex);
+ GlyphIndex glyphEnd = *(charactersToGlyphBuffer + endIndex) + ((numberOfGlyphs > 0) ? numberOfGlyphs - 1u : 0u);
+ LineIndex lineIndex = visualModel->GetLineOfCharacter(startIndex);
+ Length numberOfLines = visualModel->GetTotalNumberOfLines();
+
+ LineIndex firstLineIndex = lineIndex;
+ Size textInLineSize;
+ Vector2 textInLinePosition;
+
+ lineRun += firstLineIndex;
+
+ //get the first line and its vertical offset
+ float currentLineOffset = CalculateLineOffset(visualModel->mLines, firstLineIndex);
+ float currentLineHeight = GetLineHeight(*lineRun);
+ GlyphIndex lastGlyphOfLine = lineRun->glyphRun.glyphIndex + lineRun->glyphRun.numberOfGlyphs - 1;
+
+ // Check if the first/last glyph is a ligature that needs be splitted like English fi or Arabic ï»».
+ const Length numberOfCharactersStart = *(charactersPerGlyphBuffer + glyphStart);
+ const Length numberOfCharactersEnd = *(charactersPerGlyphBuffer + glyphEnd);
+
+ bool splitStartGlyph = (numberOfCharactersStart > 1u) && HasLigatureMustBreak(logicalModel->GetScript(startIndex));
+ bool splitEndGlyph = (glyphStart != glyphEnd) && (numberOfCharactersEnd > 1u) && HasLigatureMustBreak(logicalModel->GetScript(endIndex));
+
+ Vector2 currentSize;
+ Vector2 currentPosition;
+ Vector2 blockSize;
+ Vector2 blockPos;
+ CharacterDirection isCurrentRightToLeft;
+
+ CharacterDirection isPrevoiusRightToLeft = (nullptr != modelCharacterDirectionsBuffer ? *(modelCharacterDirectionsBuffer + startIndex) : false);
+ const bool isEllipsisEnabled = textModel->mElideEnabled;
+ const GlyphIndex startIndexOfGlyphs = textModel->GetStartIndexOfElidedGlyphs();
+ const GlyphIndex endIndexOfGlyphs = textModel->GetEndIndexOfElidedGlyphs();
+ const GlyphIndex firstMiddleIndexOfElidedGlyphs = textModel->GetFirstMiddleIndexOfElidedGlyphs();
+ const GlyphIndex secondMiddleIndexOfElidedGlyphs = textModel->GetSecondMiddleIndexOfElidedGlyphs();
+ const DevelText::EllipsisPosition::Type ellipsisPosition = textModel->GetEllipsisPosition();
+
+ for(GlyphIndex index = glyphStart; index <= glyphEnd; ++index)
+ {
+ if(isEllipsisEnabled)
+ {
+ if(ellipsisPosition == DevelText::EllipsisPosition::MIDDLE)
+ {
+ if(index >= firstMiddleIndexOfElidedGlyphs &&
+ index < secondMiddleIndexOfElidedGlyphs)
+ {
+ if((index - 1 == firstMiddleIndexOfElidedGlyphs) && (firstMiddleIndexOfElidedGlyphs != 0))
+ {
+ sizesList.PushBack(blockSize);
+ positionsList.PushBack(blockPos);
+ }
+
+ if(GetNextLine(index, lineIndex, lineRun, lastGlyphOfLine, numberOfLines))
+ {
+ UpdateLineInfo(lineRun, currentLineOffset, currentLineHeight, lastGlyphOfLine);
+ }
+ // Ignore any glyph that was removed
+ continue;
+ }
+ }
+ else
+ {
+ if((ellipsisPosition == DevelText::EllipsisPosition::END) && (index >= endIndexOfGlyphs))
+ {
+ //skip remaining elided glyphs
+ break;
+ }
+ else if((ellipsisPosition == DevelText::EllipsisPosition::START) && (index <= startIndexOfGlyphs))
+ {
+ if(GetNextLine(index, lineIndex, lineRun, lastGlyphOfLine, numberOfLines))
+ {
+ UpdateLineInfo(lineRun, currentLineOffset, currentLineHeight, lastGlyphOfLine);
+ }
+
+ continue;
+ }
+ }
+ }
+
+ const GlyphInfo& glyph = *(glyphsBuffer + index);
+ const Vector2& position = *(positionsBuffer + index);
+
+ // If NULL, means all of the characters is left to right.
+ isCurrentRightToLeft = (nullptr != modelCharacterDirectionsBuffer ? *(modelCharacterDirectionsBuffer + *(glyphToCharacterBuffer + index)) : false);
+
+ if(splitStartGlyph && (index == glyphStart))
+ {
+ // If the first glyph is a ligature that needs to be splitted, we may need only to add part of the glyph.
+ const float glyphAdvance = glyph.advance / static_cast<float>(numberOfCharactersStart);
+ const CharacterIndex interGlyphIndex = startIndex - *(glyphToCharacterBuffer + glyphStart);
+ const Length numberOfCharacters = (glyphStart == glyphEnd) ? (endIndex - startIndex) + 1 : (numberOfCharactersStart - interGlyphIndex);
+
+ currentPosition.x = lineRun->alignmentOffset + position.x - glyph.xBearing + textModel->mScrollPosition.x + glyphAdvance * static_cast<float>(isCurrentRightToLeft ? (numberOfCharactersStart - interGlyphIndex - numberOfCharacters) : interGlyphIndex);
+ currentPosition.y = currentLineOffset + textModel->mScrollPosition.y;
+ currentSize.x = static_cast<float>(numberOfCharacters) * glyphAdvance;
+ currentSize.y = currentLineHeight;
+ splitStartGlyph = false;
+ }
+ else if(splitEndGlyph && (index == glyphEnd))
+ {
+ const float glyphAdvance = glyph.advance / static_cast<float>(numberOfCharactersEnd);
+ const CharacterIndex interGlyphIndex = endIndex - *(glyphToCharacterBuffer + glyphEnd);
+ const Length numberOfCharacters = numberOfCharactersEnd - interGlyphIndex - 1;
+
+ currentPosition.x = lineRun->alignmentOffset + position.x - glyph.xBearing + textModel->mScrollPosition.x + (isCurrentRightToLeft ? (glyphAdvance * static_cast<float>(numberOfCharacters)) : 0.f);
+ currentPosition.y = currentLineOffset + textModel->mScrollPosition.y;
+ currentSize.x = static_cast<float>(interGlyphIndex + 1) * glyphAdvance;
+ currentSize.y = currentLineHeight;
+ splitEndGlyph = false;
+ }
+ else
+ {
+ currentPosition.x = lineRun->alignmentOffset + position.x - glyph.xBearing + textModel->mScrollPosition.x;
+ currentPosition.y = currentLineOffset + textModel->mScrollPosition.y;
+ currentSize.x = glyph.advance;
+ currentSize.y = currentLineHeight;
+
+ // if there is next line to retrieve.
+ if(GetNextLine(index, lineIndex, lineRun, lastGlyphOfLine, numberOfLines))
+ {
+ UpdateLineInfo(lineRun, currentLineOffset, currentLineHeight, lastGlyphOfLine);
+ }
+ }
+
+ if((index == glyphStart) || (isEllipsisEnabled && (((ellipsisPosition == DevelText::EllipsisPosition::MIDDLE) && (index == secondMiddleIndexOfElidedGlyphs)) || ((ellipsisPosition == DevelText::EllipsisPosition::START) && (index - 1 == startIndexOfGlyphs)))))
+ {
+ blockPos = currentPosition;
+ blockSize = currentSize;
+ }
+ else if((isPrevoiusRightToLeft != isCurrentRightToLeft) || (blockPos.y != currentPosition.y)) //new direction or new line
+ {
+ sizesList.PushBack(blockSize);
+ positionsList.PushBack(blockPos);
+
+ blockPos = currentPosition;
+ blockSize = currentSize;
+ }
+ else
+ {
+ if(isCurrentRightToLeft)
+ {
+ blockPos.x -= currentSize.x;
+ }
+
+ blockSize.x += currentSize.x;
+ }
+
+ isPrevoiusRightToLeft = isCurrentRightToLeft;
+ }
+
+ //add last block
+ sizesList.PushBack(blockSize);
+ positionsList.PushBack(blockPos);
+}
+
+} // namespace Text
+
+} // namespace Toolkit
+
+} // namespace Dali
--- /dev/null
+#ifndef DALI_TOOLKIT_TEXT_GEOMETRY_H
+#define DALI_TOOLKIT_TEXT_GEOMETRY_H
+
+/*
+ * Copyright (c) 2021 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 <dali-toolkit/internal/text/text-model.h>
+
+namespace Dali
+{
+namespace Toolkit
+{
+namespace Text
+{
+/**
+ * @brief Get the rendered size & position of a specific text range.
+ * if the requested text is at multilines, multiple sizes/positions will be returned for each text located in a separate line.
+ * if a line contains characters with different directions, multiple sizes will be returned for each block of contiguous characters with the same direction.
+ *
+ * @param[in] textModel text model containing text info.
+ * @param[in] startIndex start index of the text requested to get position/size for.
+ * @param[in] endIndex end index(included) of the text requested to get position/size for.
+ * @param[in] sizesList list of sizes for the reuested text.
+ * @param[in] positionsList list of positions for the requested text
+ */
+void GetTextGeometry(ModelPtr textModel, CharacterIndex startIndex, CharacterIndex endIndex, Vector<Vector2>& sizesList, Vector<Vector2>& positionsList);
+
+} // namespace Text
+
+} // namespace Toolkit
+
+} // namespace Dali
+
+#endif // DALI_TOOLKIT_TEXT_GEOMETRY_H
memcpy(glyphPositions, mGlyphPositions.Begin() + glyphIndex, numberOfGlyphs * sizeof(Vector2));
}
+Length VisualModel::GetTotalNumberOfLines() const
+{
+ return mLines.Size();
+}
+
void VisualModel::GetNumberOfLines(GlyphIndex glyphIndex,
Length numberOfGlyphs,
LineIndex& firstLine,
// Line interface.
/**
+ * @brief Retrieves the total number of lines.
+ *
+ * @return The number of lines.
+ */
+ Length GetTotalNumberOfLines() const;
+
+ /**
* @brief Retrieves the number of lines and the index to the first line where the given range of glyphs is laid out.
*
* @param[in] glyphIndex Index to the first glyph.
/**
* @copydoc Visual::Base::OnDoAction
*/
- void OnDoAction(const Dali::Property::Index actionName, const Dali::Property::Value& attributes) override;
+ void OnDoAction(const Dali::Property::Index actionId, const Dali::Property::Value& attributes) override;
protected:
/**
#include <dali/integration-api/debug.h>
//INTERNAL INCLUDES
+#include <dali-toolkit/devel-api/visuals/visual-actions-devel.h>
#include <dali-toolkit/devel-api/visuals/color-visual-properties-devel.h>
#include <dali-toolkit/internal/graphics/builtin-shader-extern-gen.h>
#include <dali-toolkit/internal/visuals/visual-base-data-impl.h>
{
DALI_LOG_ERROR("ColorVisual:DoSetProperties:: BLUR_RADIUS property has incorrect type: %d\n", blurRadiusValue->GetType());
}
+
+ if(mBlurRadiusIndex != Property::INVALID_INDEX)
+ {
+ mImpl->mRenderer.SetProperty(mBlurRadiusIndex, mBlurRadius);
+ }
+ else if(DALI_UNLIKELY(mImpl->mRenderer && (!EqualsZero(mBlurRadius) || mAlwaysUsingBlurRadius)))
+ {
+ // Unusual case. SetProperty called after OnInitialize().
+ // Assume that DoAction call UPDATE_PROPERTY.
+ // We must regist properies into renderer, and update shader.
+
+ // BlurRadius added by this action. Regist property to renderer.
+ mBlurRadiusIndex = mImpl->mRenderer.RegisterProperty(DevelColorVisual::Property::BLUR_RADIUS, BLUR_RADIUS_NAME, mBlurRadius);
+ mImpl->mRenderer.SetProperty(Renderer::Property::BLEND_MODE, BlendMode::ON);
+
+ // Change the shader must not be occured many times. we always have to use blur feature.
+ mAlwaysUsingBlurRadius = true;
+
+ // Change shader
+ UpdateShader();
+ }
}
}
{
}
+bool ImageAtlasManager::CheckAtlasAvailable(const VisualUrl& url, const ImageDimensions& size) const
+{
+ ImageDimensions dimensions = size;
+ ImageDimensions zero;
+ if(size == zero)
+ {
+ dimensions = Dali::GetClosestImageSize(url.GetUrl());
+ }
+
+ // big image, atlasing is not applied
+ if(static_cast<uint32_t>(dimensions.GetWidth()) * static_cast<uint32_t>(dimensions.GetHeight()) > MAX_ITEM_AREA || dimensions.GetWidth() > DEFAULT_ATLAS_SIZE || dimensions.GetHeight() > DEFAULT_ATLAS_SIZE)
+ {
+ return false;
+ }
+ return true;
+}
+
TextureSet ImageAtlasManager::Add(Vector4& textureRect,
const VisualUrl& url,
ImageDimensions& size,
ImageAtlasManager();
/**
+ * @brief Check whether the image of url could be Atlas or not.
+ *
+ * @param [in] url The URL of the resource image file to use.
+ * @param [in] size The width and height to fit the loaded image to.
+ * @return True if the image could be Atlas.
+ */
+ bool CheckAtlasAvailable(const VisualUrl& url, const ImageDimensions& size) const;
+
+ /**
* @brief Add an image to the atlas.
*
* @note To make the atlasing efficient, an valid size should be provided.
}
auto textureSet = mImpl->mRenderer.GetTextures();
- if(textureSet)
+ if(textureSet && textureSet.GetTextureCount())
{
auto texture = textureSet.GetTexture(0);
if(texture)
}
}
-void ImageVisual::OnDoAction(const Dali::Property::Index actionName, const Dali::Property::Value& attributes)
+void ImageVisual::OnDoAction(const Dali::Property::Index actionId, const Dali::Property::Value& attributes)
{
// Check if action is valid for this visual type and perform action if possible
- switch(actionName)
+ switch(actionId)
{
case DevelImageVisual::Action::RELOAD:
{
/**
* @copydoc Visual::Base::OnDoAction
*/
- void OnDoAction(const Dali::Property::Index actionName, const Dali::Property::Value& attributes) override;
+ void OnDoAction(const Dali::Property::Index actionId, const Dali::Property::Value& attributes) override;
protected:
/**
}
TextureManager::TextureManager()
-: mAsyncLocalLoaders(GetNumberOfLocalLoaderThreads(), [&]() { return AsyncLoadingHelper(*this); }),
- mAsyncRemoteLoaders(GetNumberOfRemoteLoaderThreads(), [&]() { return AsyncLoadingHelper(*this); }),
+: mAsyncLocalLoaders(GetNumberOfLocalLoaderThreads(), [&]()
+ { return AsyncLoadingHelper(*this); }),
+ mAsyncRemoteLoaders(GetNumberOfRemoteLoaderThreads(), [&]()
+ { return AsyncLoadingHelper(*this); }),
mExternalTextures(),
mLifecycleObservers(),
mLoadQueue(),
else
{
auto preMultiply = TextureManager::MultiplyOnLoad::LOAD_WITHOUT_MULTIPLY;
- textureId = RequestLoadInternal(animatedImageLoading.GetUrl(), INVALID_TEXTURE_ID, 1.0f, ImageDimensions(), FittingMode::SCALE_TO_FILL, SamplingMode::BOX_THEN_LINEAR, TextureManager::NO_ATLAS, false, StorageType::UPLOAD_TO_TEXTURE, textureObserver, true, TextureManager::ReloadPolicy::CACHED, preMultiply, animatedImageLoading, frameIndex);
+ textureId = RequestLoadInternal(animatedImageLoading.GetUrl(), INVALID_TEXTURE_ID, 1.0f, ImageDimensions(), FittingMode::SCALE_TO_FILL, SamplingMode::BOX_THEN_LINEAR, TextureManager::NO_ATLAS, false, StorageType::UPLOAD_TO_TEXTURE, textureObserver, true, TextureManager::ReloadPolicy::CACHED, preMultiply, animatedImageLoading, frameIndex, false);
TextureManager::LoadState loadState = GetTextureStateInternal(textureId);
if(loadState == TextureManager::LoadState::UPLOADED)
{
}
else
{
- RequestLoadInternal(url, INVALID_TEXTURE_ID, 1.0f, desiredSize, fittingMode, samplingMode, TextureManager::NO_ATLAS, false, StorageType::RETURN_PIXEL_BUFFER, textureObserver, orientationCorrection, TextureManager::ReloadPolicy::FORCED, preMultiplyOnLoad, Dali::AnimatedImageLoading(), 0u);
+ RequestLoadInternal(url, INVALID_TEXTURE_ID, 1.0f, desiredSize, fittingMode, samplingMode, TextureManager::NO_ATLAS, false, StorageType::RETURN_PIXEL_BUFFER, textureObserver, orientationCorrection, TextureManager::ReloadPolicy::FORCED, preMultiplyOnLoad, Dali::AnimatedImageLoading(), 0u, false);
}
return pixelBuffer;
}
}
}
- else if(synchronousLoading)
+ else
{
- PixelData data;
- if(url.IsValid())
+ // For Atlas
+ if(synchronousLoading && atlasingStatus && imageAtlasManager->CheckAtlasAvailable(url, desiredSize))
{
- Devel::PixelBuffer pixelBuffer;
- if(url.IsBufferResource())
- {
- const EncodedImageBuffer& encodedImageBuffer = GetEncodedImageBuffer(url.GetUrl());
- if(encodedImageBuffer)
- {
- pixelBuffer = LoadImageFromBuffer(encodedImageBuffer.GetRawBuffer(), desiredSize, fittingMode, samplingMode, orientationCorrection);
- }
- }
- else
- {
- pixelBuffer = LoadImageFromFile(url.GetUrl(), desiredSize, fittingMode, samplingMode, orientationCorrection);
- }
+ Devel::PixelBuffer pixelBuffer = LoadImageSynchronously(url, desiredSize, fittingMode, samplingMode, orientationCorrection);
+
if(maskInfo && maskInfo->mAlphaMaskUrl.IsValid())
{
- Devel::PixelBuffer maskPixelBuffer = LoadImageFromFile(maskInfo->mAlphaMaskUrl.GetUrl(), ImageDimensions(), FittingMode::SCALE_TO_FILL, SamplingMode::NO_FILTER, true);
+ Devel::PixelBuffer maskPixelBuffer = LoadImageSynchronously(maskInfo->mAlphaMaskUrl.GetUrl(), ImageDimensions(), FittingMode::SCALE_TO_FILL, SamplingMode::NO_FILTER, true);
if(maskPixelBuffer)
{
pixelBuffer.ApplyMask(maskPixelBuffer, maskInfo->mContentScaleFactor, maskInfo->mCropToMask);
}
}
+
+ PixelData data;
if(pixelBuffer)
{
PreMultiply(pixelBuffer, preMultiplyOnLoad);
data = Devel::PixelBuffer::Convert(pixelBuffer); // takes ownership of buffer
+
+ if(data)
+ {
+ textureSet = imageAtlasManager->Add(textureRect, data);
+ if(textureSet)
+ {
+ textureRectSize.SetWidth(data.GetWidth());
+ textureRectSize.SetHeight(data.GetHeight());
+ }
+ }
+ else
+ {
+ DALI_LOG_ERROR("TextureManager::LoadTexture: Synchronous Texture loading with atlasing is failed.\n");
+ }
}
- }
- if(!data)
- {
- DALI_LOG_ERROR("TextureManager::LoadTexture: Synchronous loading is failed\n");
- }
- else
- {
- if(atlasingStatus) // attempt atlasing
- {
- textureSet = imageAtlasManager->Add(textureRect, data);
- }
- if(!textureSet) // big image, no atlasing or atlasing failed
- {
- atlasingStatus = false;
- Texture texture = Texture::New(Dali::TextureType::TEXTURE_2D, data.GetPixelFormat(), data.GetWidth(), data.GetHeight());
- texture.Upload(data);
- textureSet = TextureSet::New();
- textureSet.SetTexture(0u, texture);
- }
- else
+ if(!textureSet)
{
- textureRectSize.SetWidth(data.GetWidth());
- textureRectSize.SetHeight(data.GetHeight());
+ atlasingStatus = false;
}
}
- }
- else
- {
- loadingStatus = true;
- if(atlasingStatus)
- {
- textureSet = imageAtlasManager->Add(textureRect, url.GetUrl(), desiredSize, fittingMode, true, atlasObserver);
- }
- if(!textureSet) // big image, no atlasing or atlasing failed
+
+ if(!textureSet)
{
- atlasingStatus = false;
- if(!maskInfo || !maskInfo->mAlphaMaskUrl.IsValid())
+ loadingStatus = true;
+ if(atlasingStatus)
{
- textureId = RequestLoad(url, desiredSize, fittingMode, samplingMode, TextureManager::NO_ATLAS, textureObserver, orientationCorrection, reloadPolicy, preMultiplyOnLoad);
+ textureSet = imageAtlasManager->Add(textureRect, url.GetUrl(), desiredSize, fittingMode, true, atlasObserver);
}
- else
+ if(!textureSet) // big image, no atlasing or atlasing failed
{
- maskInfo->mAlphaMaskId = RequestMaskLoad(maskInfo->mAlphaMaskUrl);
- textureId = RequestLoad(url,
- maskInfo->mAlphaMaskId,
- maskInfo->mContentScaleFactor,
- desiredSize,
- fittingMode,
- samplingMode,
- TextureManager::NO_ATLAS,
- maskInfo->mCropToMask,
- textureObserver,
- orientationCorrection,
- reloadPolicy,
- preMultiplyOnLoad);
- }
+ atlasingStatus = false;
+ if(!maskInfo || !maskInfo->mAlphaMaskUrl.IsValid())
+ {
+ textureId = RequestLoad(url, desiredSize, fittingMode, samplingMode, TextureManager::NO_ATLAS, textureObserver, orientationCorrection, reloadPolicy, preMultiplyOnLoad, synchronousLoading);
+ }
+ else
+ {
+ maskInfo->mAlphaMaskId = RequestMaskLoad(maskInfo->mAlphaMaskUrl, synchronousLoading);
+ textureId = RequestLoad(url,
+ maskInfo->mAlphaMaskId,
+ maskInfo->mContentScaleFactor,
+ desiredSize,
+ fittingMode,
+ samplingMode,
+ TextureManager::NO_ATLAS,
+ maskInfo->mCropToMask,
+ textureObserver,
+ orientationCorrection,
+ reloadPolicy,
+ preMultiplyOnLoad,
+ synchronousLoading);
+ }
+
+ TextureManager::LoadState loadState = GetTextureStateInternal(textureId);
+ if(loadState == TextureManager::LoadState::UPLOADED)
+ {
+ // UploadComplete has already been called - keep the same texture set
+ textureSet = GetTextureSet(textureId);
+ }
- TextureManager::LoadState loadState = GetTextureStateInternal(textureId);
- if(loadState == TextureManager::LoadState::UPLOADED)
+ // If we are loading the texture, or waiting for the ready signal handler to complete, inform
+ // caller that they need to wait.
+ loadingStatus = (loadState == TextureManager::LoadState::LOADING ||
+ loadState == TextureManager::LoadState::WAITING_FOR_MASK ||
+ loadState == TextureManager::LoadState::MASK_APPLYING ||
+ loadState == TextureManager::LoadState::MASK_APPLIED ||
+ loadState == TextureManager::LoadState::NOT_STARTED ||
+ mQueueLoadFlag);
+ }
+ else
{
- // UploadComplete has already been called - keep the same texture set
- textureSet = GetTextureSet(textureId);
+ textureRectSize = desiredSize;
}
-
- // If we are loading the texture, or waiting for the ready signal handler to complete, inform
- // caller that they need to wait.
- loadingStatus = (loadState == TextureManager::LoadState::LOADING ||
- loadState == TextureManager::LoadState::WAITING_FOR_MASK ||
- loadState == TextureManager::LoadState::MASK_APPLYING ||
- loadState == TextureManager::LoadState::MASK_APPLIED ||
- loadState == TextureManager::LoadState::NOT_STARTED ||
- mQueueLoadFlag);
- }
- else
- {
- textureRectSize = desiredSize;
}
}
textureSet.SetSampler(0u, sampler);
}
+ if(synchronousLoading)
+ {
+ loadingStatus = false;
+ }
+
return textureSet;
}
TextureUploadObserver* observer,
bool orientationCorrection,
TextureManager::ReloadPolicy reloadPolicy,
- TextureManager::MultiplyOnLoad& preMultiplyOnLoad)
+ TextureManager::MultiplyOnLoad& preMultiplyOnLoad,
+ bool synchronousLoading)
{
- return RequestLoadInternal(url, INVALID_TEXTURE_ID, 1.0f, desiredSize, fittingMode, samplingMode, useAtlas, false, StorageType::UPLOAD_TO_TEXTURE, observer, orientationCorrection, reloadPolicy, preMultiplyOnLoad, Dali::AnimatedImageLoading(), 0u);
+ return RequestLoadInternal(url, INVALID_TEXTURE_ID, 1.0f, desiredSize, fittingMode, samplingMode, useAtlas, false, StorageType::UPLOAD_TO_TEXTURE, observer, orientationCorrection, reloadPolicy, preMultiplyOnLoad, Dali::AnimatedImageLoading(), 0u, synchronousLoading);
}
TextureManager::TextureId TextureManager::RequestLoad(
TextureUploadObserver* observer,
bool orientationCorrection,
TextureManager::ReloadPolicy reloadPolicy,
- TextureManager::MultiplyOnLoad& preMultiplyOnLoad)
+ TextureManager::MultiplyOnLoad& preMultiplyOnLoad,
+ bool synchronousLoading)
{
- return RequestLoadInternal(url, maskTextureId, contentScale, desiredSize, fittingMode, samplingMode, useAtlas, cropToMask, StorageType::UPLOAD_TO_TEXTURE, observer, orientationCorrection, reloadPolicy, preMultiplyOnLoad, Dali::AnimatedImageLoading(), 0u);
+ return RequestLoadInternal(url, maskTextureId, contentScale, desiredSize, fittingMode, samplingMode, useAtlas, cropToMask, StorageType::UPLOAD_TO_TEXTURE, observer, orientationCorrection, reloadPolicy, preMultiplyOnLoad, Dali::AnimatedImageLoading(), 0u, synchronousLoading);
}
-TextureManager::TextureId TextureManager::RequestMaskLoad(const VisualUrl& maskUrl)
+TextureManager::TextureId TextureManager::RequestMaskLoad(const VisualUrl& maskUrl, bool synchronousLoading)
{
// Use the normal load procedure to get the alpha mask.
auto preMultiply = TextureManager::MultiplyOnLoad::LOAD_WITHOUT_MULTIPLY;
- return RequestLoadInternal(maskUrl, INVALID_TEXTURE_ID, 1.0f, ImageDimensions(), FittingMode::SCALE_TO_FILL, SamplingMode::NO_FILTER, NO_ATLAS, false, StorageType::KEEP_PIXEL_BUFFER, NULL, true, TextureManager::ReloadPolicy::CACHED, preMultiply, Dali::AnimatedImageLoading(), 0u);
+ return RequestLoadInternal(maskUrl, INVALID_TEXTURE_ID, 1.0f, ImageDimensions(), FittingMode::SCALE_TO_FILL, SamplingMode::NO_FILTER, NO_ATLAS, false, StorageType::KEEP_PIXEL_BUFFER, NULL, true, TextureManager::ReloadPolicy::CACHED, preMultiply, Dali::AnimatedImageLoading(), 0u, synchronousLoading);
}
TextureManager::TextureId TextureManager::RequestLoadInternal(
TextureManager::ReloadPolicy reloadPolicy,
TextureManager::MultiplyOnLoad& preMultiplyOnLoad,
Dali::AnimatedImageLoading animatedImageLoading,
- uint32_t frameIndex)
+ uint32_t frameIndex,
+ bool synchronousLoading)
{
// First check if the requested Texture is cached.
bool isAnimatedImage = (animatedImageLoading) ? true : false;
DALI_LOG_INFO(gTextureManagerLogFilter, Debug::General, "TextureManager::RequestLoad( url=%s observer=%p ) Using cached texture id@%d, textureId=%d\n", url.GetUrl().c_str(), observer, cacheIndex, textureId);
}
- // Check if the requested Texture exist in Encoded Buffer
- // This mean, that buffer is not cached, and need to be decoded.
- if(textureId == INVALID_TEXTURE_ID && VisualUrl::BUFFER == url.GetProtocolType())
+ if(textureId == INVALID_TEXTURE_ID) // There was no caching, or caching not required
{
- std::string location = url.GetLocation();
- if(location.size() > 0u)
+ if(VisualUrl::BUFFER == url.GetProtocolType())
{
- TextureId targetId = std::stoi(location);
- const EncodedImageBuffer& encodedImageBuffer = GetEncodedImageBuffer(targetId);
- if(encodedImageBuffer)
+ std::string location = url.GetLocation();
+ if(location.size() > 0u)
{
- textureId = targetId;
-
- // Increase EncodedImageBuffer reference during it contains mTextureInfoContainer.
- UseExternalResource(url.GetUrl());
-
- // Insert this buffer at mTextureInfoContainer.
- // This buffer will decode at ImageLoaderThread.
- bool preMultiply = (preMultiplyOnLoad == TextureManager::MultiplyOnLoad::MULTIPLY_ON_LOAD);
- mTextureInfoContainer.push_back(TextureInfo(textureId, maskTextureId, url, desiredSize, contentScale, fittingMode, samplingMode, false, cropToMask, useAtlas, textureHash, orientationCorrection, preMultiply, animatedImageLoading, frameIndex));
- cacheIndex = mTextureInfoContainer.size() - 1u;
+ TextureId targetId = std::stoi(location);
+ const EncodedImageBuffer& encodedImageBuffer = GetEncodedImageBuffer(targetId);
+ if(encodedImageBuffer)
+ {
+ textureId = targetId;
- DALI_LOG_INFO(gTextureManagerLogFilter, Debug::General, "TextureManager::RequestLoad( url=%s observer=%p ) New buffered texture, cacheIndex:%d, textureId=%d\n", url.GetUrl().c_str(), observer, cacheIndex, textureId);
+ // Increase EncodedImageBuffer reference during it contains mTextureInfoContainer.
+ UseExternalResource(url.GetUrl());
+ }
}
}
- }
- if(textureId == INVALID_TEXTURE_ID) // There was no caching, or caching not required
- {
- // We need a new Texture.
- textureId = GenerateUniqueTextureId();
+ if(textureId == INVALID_TEXTURE_ID)
+ {
+ textureId = GenerateUniqueTextureId();
+ }
+
bool preMultiply = (preMultiplyOnLoad == TextureManager::MultiplyOnLoad::MULTIPLY_ON_LOAD);
mTextureInfoContainer.push_back(TextureInfo(textureId, maskTextureId, url, desiredSize, contentScale, fittingMode, samplingMode, false, cropToMask, useAtlas, textureHash, orientationCorrection, preMultiply, animatedImageLoading, frameIndex));
cacheIndex = mTextureInfoContainer.size() - 1u;
textureInfo.loadState = TextureManager::LoadState::NOT_STARTED;
}
- // Check if we should add the observer.
- // Only do this if we have not loaded yet and it will not have loaded by the end of this method.
- switch(textureInfo.loadState)
+ if(!synchronousLoading)
{
- case TextureManager::LoadState::LOAD_FAILED: // Failed notifies observer which then stops observing.
- case TextureManager::LoadState::NOT_STARTED:
- {
- LoadOrQueueTexture(textureInfo, observer); // If called inside NotifyObservers, queues until afterwards
- break;
- }
- case TextureManager::LoadState::LOADING:
- case TextureManager::LoadState::WAITING_FOR_MASK:
- case TextureManager::LoadState::MASK_APPLYING:
- case TextureManager::LoadState::MASK_APPLIED:
+ // Check if we should add the observer.
+ // Only do this if we have not loaded yet and it will not have loaded by the end of this method.
+ switch(textureInfo.loadState)
{
- ObserveTexture(textureInfo, observer);
- break;
- }
- case TextureManager::LoadState::UPLOADED:
- {
- if(observer)
+ case TextureManager::LoadState::LOAD_FAILED: // Failed notifies observer which then stops observing.
+ case TextureManager::LoadState::NOT_STARTED:
+ {
+ LoadOrQueueTexture(textureInfo, observer); // If called inside NotifyObservers, queues until afterwards
+ break;
+ }
+ case TextureManager::LoadState::LOADING:
+ case TextureManager::LoadState::WAITING_FOR_MASK:
+ case TextureManager::LoadState::MASK_APPLYING:
+ case TextureManager::LoadState::MASK_APPLIED:
{
- LoadOrQueueTexture(textureInfo, observer);
+ ObserveTexture(textureInfo, observer);
+ break;
+ }
+ case TextureManager::LoadState::UPLOADED:
+ {
+ if(observer)
+ {
+ LoadOrQueueTexture(textureInfo, observer);
+ }
+ break;
+ }
+ case TextureManager::LoadState::CANCELLED:
+ {
+ // A cancelled texture hasn't finished loading yet. Treat as a loading texture
+ // (it's ref count has already been incremented, above)
+ textureInfo.loadState = TextureManager::LoadState::LOADING;
+ ObserveTexture(textureInfo, observer);
+ break;
+ }
+ case TextureManager::LoadState::LOAD_FINISHED:
+ {
+ // Loading has already completed.
+ if(observer && textureInfo.storageType == StorageType::RETURN_PIXEL_BUFFER)
+ {
+ LoadOrQueueTexture(textureInfo, observer);
+ }
+ break;
}
- break;
}
- case TextureManager::LoadState::CANCELLED:
+ }
+ else
+ {
+ // If the image is already finished to load, use cached texture.
+ // We don't need to consider Observer becaouse this is synchronous loading.
+ if(textureInfo.loadState == TextureManager::LoadState::UPLOADED ||
+ textureInfo.loadState == TextureManager::LoadState::LOAD_FINISHED)
{
- // A cancelled texture hasn't finished loading yet. Treat as a loading texture
- // (it's ref count has already been incremented, above)
- textureInfo.loadState = TextureManager::LoadState::LOADING;
- ObserveTexture(textureInfo, observer);
- break;
+ return textureId;
}
- case TextureManager::LoadState::LOAD_FINISHED:
+ else
{
- // Loading has already completed.
- if(observer && textureInfo.storageType == StorageType::RETURN_PIXEL_BUFFER)
+ Devel::PixelBuffer pixelBuffer = LoadImageSynchronously(url, desiredSize, fittingMode, samplingMode, orientationCorrection);;
+
+ if(!pixelBuffer)
{
- LoadOrQueueTexture(textureInfo, observer);
+ // If pixelBuffer loading is failed in synchronously, call Remove() method.
+ Remove(textureId, nullptr);
+ return INVALID_TEXTURE_ID;
+ }
+
+ if(storageType == StorageType::KEEP_PIXEL_BUFFER) // For the mask image loading.
+ {
+ textureInfo.pixelBuffer = pixelBuffer; // Store the pixel data
+ textureInfo.loadState = LoadState::LOAD_FINISHED;
+ }
+ else // For the image loading.
+ {
+ if(maskTextureId != INVALID_TEXTURE_ID)
+ {
+ int maskCacheIndex = GetCacheIndexFromId(maskTextureId);
+ if(maskCacheIndex != INVALID_CACHE_INDEX)
+ {
+ Devel::PixelBuffer maskPixelBuffer = mTextureInfoContainer[maskCacheIndex].pixelBuffer;
+ if(maskPixelBuffer)
+ {
+ pixelBuffer.ApplyMask(maskPixelBuffer, contentScale, cropToMask);
+ }
+ }
+ else
+ {
+ DALI_LOG_ERROR("Mask image is not stored in cache.\n");
+ }
+ }
+ PreMultiply(pixelBuffer, preMultiplyOnLoad);
+
+ // Upload texture
+ UploadTexture(pixelBuffer, textureInfo);
}
- break;
}
}
return loadState;
}
+Devel::PixelBuffer TextureManager::LoadImageSynchronously(const VisualUrl& url,
+ const ImageDimensions desiredSize,
+ FittingMode::Type fittingMode,
+ Dali::SamplingMode::Type samplingMode,
+ bool orientationCorrection)
+{
+ Devel::PixelBuffer pixelBuffer;
+ if(url.IsBufferResource())
+ {
+ const EncodedImageBuffer& encodedImageBuffer = GetEncodedImageBuffer(url.GetUrl());
+ if(encodedImageBuffer)
+ {
+ pixelBuffer = LoadImageFromBuffer(encodedImageBuffer.GetRawBuffer(), desiredSize, fittingMode, samplingMode, orientationCorrection);
+ }
+ }
+ else
+ {
+ pixelBuffer = LoadImageFromFile(url.GetUrl(), desiredSize, fittingMode, samplingMode, orientationCorrection);
+ }
+ return pixelBuffer;
+}
+
TextureSet TextureManager::GetTextureSet(TextureId textureId)
{
TextureSet textureSet; // empty handle
{
// If same buffer added, increase reference count and return.
elem.referenceCount++;
- return VisualUrl::CreateBufferUrl(std::to_string(elem.textureId));;
+ return VisualUrl::CreateBufferUrl(std::to_string(elem.textureId));
}
}
TextureManager::EncodedBufferTextureInfo info(GenerateUniqueTextureId(), encodedImageBuffer);
std::string location = VisualUrl::GetLocation(url);
if(location.size() > 0u)
{
- TextureId id = std::stoi(location);
+ TextureId id = std::stoi(location);
const auto end = mEncodedBufferTextures.end();
for(auto iter = mEncodedBufferTextures.begin(); iter != end; ++iter)
{
// If there is a mask texture ID associated with this texture, then apply the mask
// if it's already loaded. If it hasn't, and the mask is still loading,
// wait for the mask to finish loading.
- if(textureInfo.maskTextureId != INVALID_TEXTURE_ID)
+ // note, If the texture is already uploaded synchronously during loading,
+ // we don't need to apply mask.
+ if(textureInfo.loadState != LoadState::UPLOADED &&
+ textureInfo.maskTextureId != INVALID_TEXTURE_ID)
{
if(textureInfo.loadState == LoadState::MASK_APPLYING)
{
void TextureManager::UploadTexture(Devel::PixelBuffer& pixelBuffer, TextureInfo& textureInfo)
{
- if(textureInfo.useAtlas != USE_ATLAS)
+ if(textureInfo.loadState != LoadState::UPLOADED && textureInfo.useAtlas != USE_ATLAS)
{
DALI_LOG_INFO(gTextureManagerLogFilter, Debug::General, " TextureManager::UploadTexture() New Texture for textureId:%d\n", textureInfo.textureId);
*/
enum class StorageType : uint8_t
{
- KEEP_PIXEL_BUFFER,
- RETURN_PIXEL_BUFFER,
- UPLOAD_TO_TEXTURE
+ KEEP_PIXEL_BUFFER, ///< Keep loaded pixel buffer inside of texture manager without making texture. This could be used for inside pixel process like mask image.
+ RETURN_PIXEL_BUFFER, ///< Return loaded pixel buffer without making texture.
+ /// Because a pixel buffer cannot be used multiple texture, this pixel buffer only cached during loading, and is removed after loading is finished.
+ UPLOAD_TO_TEXTURE ///< Loaded image will be uploaded to texture and the texture will be returned.
};
/**
*
* @return The texture set containing the frame of animated image, or empty if still loading.
*/
-
TextureSet LoadAnimatedImageTexture(Dali::AnimatedImageLoading animatedImageLoading,
uint32_t frameIndex,
Dali::SamplingMode::Type samplingMode,
*
* @return The pixel buffer containing the image, or empty if still loading.
*/
-
Devel::PixelBuffer LoadPixelBuffer(const VisualUrl& url,
Dali::ImageDimensions desiredSize,
Dali::FittingMode::Type fittingMode,
*
* @return The texture set containing the image, or empty if still loading.
*/
-
TextureSet LoadTexture(const VisualUrl& url,
Dali::ImageDimensions desiredSize,
Dali::FittingMode::Type fittingMode,
* @param[in] orientationCorrection Whether to rotate image to match embedded orientation data
* @param[in] reloadPolicy Forces a reload of the texture even if already cached
* @param[in,out] preMultiplyOnLoad True if the image color should be multiplied by it's alpha. Set to false if the image has no alpha channel
+ * @param[in] synchronousLoading true if the frame should be loaded synchronously
* @return A TextureId to use as a handle to reference this Texture
*/
TextureId RequestLoad(const VisualUrl& url,
TextureUploadObserver* observer,
bool orientationCorrection,
TextureManager::ReloadPolicy reloadPolicy,
- MultiplyOnLoad& preMultiplyOnLoad);
+ MultiplyOnLoad& preMultiplyOnLoad,
+ bool synchronousLoading = false);
/**
* @brief Requests an image load of the given URL, when the texture has
* @param[in] reloadPolicy Forces a reload of the texture even if already cached
* @param[in] preMultiplyOnLoad True if the image color should be multiplied by it's alpha. Set to false if the
* image has no alpha channel
+ * @param[in] synchronousLoading true if the frame should be loaded synchronously
* @return A TextureId to use as a handle to reference this Texture
*/
TextureId RequestLoad(const VisualUrl& url,
TextureUploadObserver* observer,
bool orientationCorrection,
TextureManager::ReloadPolicy reloadPolicy,
- MultiplyOnLoad& preMultiplyOnLoad);
+ MultiplyOnLoad& preMultiplyOnLoad,
+ bool synchronousLoading = false);
/**
* Requests a masking image to be loaded. This mask is not uploaded to GL,
* instead, it is stored in CPU memory, and can be used for CPU blending.
*/
- TextureId RequestMaskLoad(const VisualUrl& maskUrl);
+ TextureId RequestMaskLoad(const VisualUrl& maskUrl,
+ bool synchronousLoading = false);
/**
* @brief Remove a Texture from the TextureManager.
* there is no alpha
* @param[in] animatedImageLoading The AnimatedImageLoading to load animated image
* @param[in] frameIndex The frame index of a frame to be loaded frame
+ * @param[in] synchronousLoading true if the frame should be loaded synchronously
* @return A TextureId to use as a handle to reference this Texture
*/
TextureId RequestLoadInternal(
TextureManager::ReloadPolicy reloadPolicy,
MultiplyOnLoad& preMultiplyOnLoad,
Dali::AnimatedImageLoading animatedImageLoading,
- uint32_t frameIndex);
+ uint32_t frameIndex,
+ bool synchronousLoading);
/**
* @brief Get the current state of a texture
*/
LoadState GetTextureStateInternal(TextureId textureId);
+ /**
+ * @brief Load a new image synchronously.
+ * @param[in] url The URL of the image to load
+ * @param[in] desiredSize The size the image is likely to appear at.
+ * This can be set to 0,0 for automatic
+ * @param[in] fittingMode The FittingMode to use
+ * @param[in] samplingMode The SamplingMode to use
+ * @param[in] orientationCorrection Whether to use image metadata to rotate or flip the image,
+ * e.g., from portrait to landscape
+ * @return PixelBuffer of loaded image.
+ */
+ Devel::PixelBuffer LoadImageSynchronously(const VisualUrl& url,
+ const ImageDimensions desiredSize,
+ FittingMode::Type fittingMode,
+ Dali::SamplingMode::Type samplingMode,
+ bool orientationCorrection);
+
typedef size_t TextureHash; ///< The type used to store the hash used for Texture caching.
// Structs:
void Visual::Base::SetProperties(const Property::Map& propertyMap)
{
+ bool needUpdateShader = false;
for(size_t i = 0; i < propertyMap.Count(); ++i)
{
const KeyValuePair& pair = propertyMap.GetKeyValue(i);
{
mImpl->mRenderer.SetProperty(mImpl->mBorderlineWidthIndex, mImpl->mBorderlineWidth);
}
+ else if(DALI_UNLIKELY(mImpl->mRenderer && IsBorderlineRequired()))
+ {
+ // Unusual case. SetProperty called after OnInitialize().
+ // Assume that DoAction call UPDATE_PROPERTY.
+ // We must regist properies into renderer, and update shader.
+
+ // Borderline added by this action. Regist property to renderer.
+ mImpl->mBorderlineWidthIndex = mImpl->mRenderer.RegisterProperty(DevelVisual::Property::BORDERLINE_WIDTH, BORDERLINE_WIDTH, mImpl->mBorderlineWidth);
+ mImpl->mBorderlineColorIndex = mImpl->mRenderer.RegisterProperty(DevelVisual::Property::BORDERLINE_COLOR, BORDERLINE_COLOR, mImpl->mBorderlineColor);
+ mImpl->mBorderlineOffsetIndex = mImpl->mRenderer.RegisterProperty(DevelVisual::Property::BORDERLINE_OFFSET, BORDERLINE_OFFSET, mImpl->mBorderlineOffset);
+
+ // Make Blend mode ON_WITHOUT_CULL for transparent mix color.
+ mImpl->mRenderer.SetProperty(Renderer::Property::BLEND_MODE, BlendMode::ON_WITHOUT_CULL);
+
+ // Change the shader must not be occured many times. we always have to use borderline feature.
+ mImpl->mAlwaysUsingBorderline = true;
+
+ // Change shader
+ needUpdateShader = true;
+ }
break;
}
case Toolkit::DevelVisual::Property::BORDERLINE_COLOR:
{
mImpl->mRenderer.SetProperty(mImpl->mCornerRadiusIndex, mImpl->mCornerRadius);
}
+ else if(DALI_UNLIKELY(mImpl->mRenderer && IsRoundedCornerRequired()))
+ {
+ // Unusual case. SetProperty called after OnInitialize().
+ // Assume that DoAction call UPDATE_PROPERTY.
+ // We must regist properies into renderer, and update shader.
+
+ // CornerRadius added by this action. Regist property to renderer.
+ mImpl->mCornerRadiusIndex = mImpl->mRenderer.RegisterProperty(DevelVisual::Property::CORNER_RADIUS, CORNER_RADIUS, mImpl->mCornerRadius);
+ mImpl->mRenderer.RegisterProperty(CORNER_RADIUS_POLICY, mImpl->mCornerRadiusPolicy);
+
+ // Change the shader must not be occured many times. we always have to use corner radius feature.
+ mImpl->mAlwaysUsingCornerRadius = true;
+
+ if(!IsBorderlineRequired())
+ {
+ // If IsBorderlineRequired is true, BLEND_MODE is already BlendMode::ON_WITHOUT_CULL. So we don't overwrite it.
+ mImpl->mRenderer.SetProperty(Renderer::Property::BLEND_MODE, BlendMode::ON);
+ }
+
+ // Change shader
+ needUpdateShader = true;
+ }
break;
}
case Toolkit::DevelVisual::Property::CORNER_RADIUS_POLICY:
case Toolkit::Visual::Transform::Policy::ABSOLUTE:
{
mImpl->mCornerRadiusPolicy = policy;
+ if(DALI_UNLIKELY(mImpl->mRenderer && mImpl->mCornerRadiusIndex != Property::INVALID_INDEX))
+ {
+ // Unusual case. SetProperty called after OnInitialize().
+ // Assume that DoAction call UPDATE_PROPERTY.
+ // We must update properies result into renderer
+ // Note : mImpl->mCornerRadiusIndex is not INVALID_INDEX.
+ // So CornerRadiusPolicy property is already registed.
+ mImpl->mRenderer.SetProperty(mImpl->mRenderer.GetPropertyIndex(CORNER_RADIUS_POLICY), mImpl->mCornerRadiusPolicy);
+ }
break;
}
default:
}
DoSetProperties(propertyMap);
+
+ if(DALI_UNLIKELY(needUpdateShader))
+ {
+ UpdateShader();
+ }
}
void Visual::Base::SetTransformAndSize(const Property::Map& transform, Size controlSize)
void SetTransformAndSize(const Property::Map& transform, Size controlSize);
/**
- * @brief Performs an action on the visual with the given action name and attributes.
+ * @brief Performs an action on the visual with the given action id and attributes.
*
- * @param[in] actionName The name of the action to perform this API only takes an Index
+ * @param[in] actionId The id of the action to perform this API only takes an Index
* @param[in] attributes The list of attributes for the action. ( optional for this data structure to have content )
*/
- void DoAction(const Dali::Property::Index actionName, const Dali::Property::Value attributes);
+ void DoAction(const Dali::Property::Index actionId, const Dali::Property::Value attributes);
/**
* @copydoc Toolkit::Visual::Base::GetHeightForWidth
{
const unsigned int TOOLKIT_MAJOR_VERSION = 2;
const unsigned int TOOLKIT_MINOR_VERSION = 1;
-const unsigned int TOOLKIT_MICRO_VERSION = 1;
+const unsigned int TOOLKIT_MICRO_VERSION = 2;
const char* const TOOLKIT_BUILD_DATE = __DATE__ " " __TIME__;
#ifdef DEBUG_ENABLED
Name: dali2-toolkit
Summary: Dali 3D engine Toolkit
-Version: 2.1.1
+Version: 2.1.2
Release: 1
Group: System/Libraries
License: Apache-2.0 and BSD-3-Clause and MIT